Reputation: 1750
In the below function, after I use sendto() I want to know the source IP and port used for sending the message. Is it possible to find out?
void sendMsg(char* payload, size_t payloadLength, const char* ip6Addr, short port)
{
int sock;
size_t size;
socklen_t clilen;
struct sockaddr_in6 server_addr, client_addr;
sock = socket(PF_INET6, SOCK_DGRAM, 0);
if (sock < 0) {
perror("creating socket");
exit(1);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_family = AF_INET6;
inet_pton(AF_INET6, ip6Addr, &server_addr.sin6_addr);
server_addr.sin6_port = htons(port);
size = sendto(sock, payload, payloadLength, 0 , (const struct sockaddr *) &server_addr,sizeof(server_addr));
if(size < 0)
printf("Error in sending message\n");
else
printf("[%d] bytes written to network\n",size);
}
Upvotes: 3
Views: 769
Reputation: 52579
From the Linux manpage for udp(7)
In order to receive packets, the socket can be bound to a local address first by using
bind(2)
. Otherwise, the socket layer will automatically assign a free local port out of the range defined by/proc/sys/net/ipv4/ip_local_port_range
and bind the socket toINADDR_ANY
.
Unbound UDP IPv6 sockets are treated the same. So you can get the local port used by the socket after sending the first packet by using getsockname()
as already demonstrated, but you can't get a specific local address because there isn't one - a packet sent to any of the machine's addresses on that port will be received (Modulo firewall rules etc. of course).
There is hope, however.
The shell command ip route get ADDRESS
will show you the network interface and IP address used to send packets to ADDRESS
. See rtnetlink(7)
for how to access the routing tables programatically.
Upvotes: 1
Reputation: 104589
Here's how you get the port. Bind to the INADDR_ANY address (IN6ADDR_ANY_INIT). Then use getsockname.
sockaddr_in6 addr = {0};
sockaddr_in6 addrLocal = {0};
socklen_t addrSize = sizeof(addrLocal);
unsigned short port = 0;
addr.sin6_family = AF_INET6;
sock = socket(AF_INET6, SOCK_DGRAM,0);
bind(sock, (sockaddr*)&addr, sizeof(addr)); // bind to the INADDR_ANY address for IPV6
getsockname(sock, (sockaddr*)&addrLocal, &addrSize);
port = addrLocal.sin6_port;
I'm not sure about the IP address. The IP address embedded inside the addrLocal
will still be all zeros. Not sure how you get the IP address used for a particular packet send. Worst case, you enumerate the routing table to infer which interface and address are most likely to be used for particular target IP.
Upvotes: 1