2

There seems to be no portable way to set the source IP for sending UDP datagrams from sockets bound to INADDR_ANY, but at least on Linux and FreeBSD it can be done using sendmsg() and the IP_PKTINFO (Linux) or IP_SENDSRCADDR (FreeBSD) option. (See this question.)

Is there an equivalent option to set the UDP source IP on Windows ?

Gene Vincent
  • 5,237
  • 9
  • 50
  • 86
  • [WSASendMsg](http://msdn.microsoft.com/en-us/library/windows/desktop/ms741692(v=vs.85).aspx) is the equivalent on Windows. – Steve-o Mar 27 '13 at 14:51
  • Would WSASendMsg understand the same IP_PKTINFO to set the source IP as Linux ? – Gene Vincent Mar 27 '13 at 15:44
  • 1
    @dtb Do you want to know how to do it in `C` or `C#`, it is different depending on the language. – Scott Chamberlain Jun 25 '13 at 21:01
  • @ScottChamberlain: Yes, the code will be different for C and C#. But the question is pretty language agnostic. It's mainly about Windows. If you can do it in C, you can do it in C#. – dtb Jun 25 '13 at 21:07
  • @GeneVincent: Sorry I hijacked your question. [This Cable guy article](http://technet.microsoft.com/en-gb/magazine/2007.09.cableguy.aspx) seems to suggest that it is possible to set the source IP address, but it is not clear if this can be done only by binding the socket. The [WSASendMsg function](http://msdn.microsoft.com/en-us/library/windows/desktop/ms741692.aspx) claims that it can set the source IP address: On a "socket of type SOCK_DGRAM or SOCK_RAW, an application can specific the local IP source address to use for sending with the WSASendMsg function." I can't get it to work though. – dtb Jun 29 '13 at 10:14
  • 1
    I've got the WSASendMsg function running now. `WSACMSGHDR.cmsg_len` is of type `SIZE_T`, not `UINT` as the documentation says. Now I need a second IP address for testing... – dtb Jun 29 '13 at 12:54

2 Answers2

2

From MSDN:

WSASendMsg function

[...]

On an IPv4 socket of type SOCK_DGRAM or SOCK_RAW, an application can specific the local IP source address to use for sending with the WSASendMsg function. One of the control data objects passed in the WSAMSG structure to the WSASendMsg function may contain an in_pktinfo structure used to specify the local IPv4 source address to use for sending.

The same applies to an IPv6 socket with the in6_pktinfo structure.

For dual-mode sockets, it is important that an IPv4 source address is not specified as an IPv4-mapped IPv6 address in the in6_pktinfo, but as an IPv4 address in the in_pktinfo structure.


Example:

union {
    char in[WSA_CMSG_SPACE(sizeof(struct in_pktinfo))];
    char in6[WSA_CMSG_SPACE(sizeof(struct in6_pktinfo))];
} cdata;

WSAMSG msg;
memset(&msg, 0, sizeof(msg));
msg.name = &remote_sysaddr.addr.generic;
msg.namelen = remote_sysaddr.len;
msg.lpBuffers = &buf;
msg.dwBufferCount = 1;
msg.Control.buf = (char *)&cdata;
msg.Control.len = sizeof(cdata);

int sum = 0;

WSACMSGHDR *cmsg = WSA_CMSG_FIRSTHDR(&msg);

...
    memset(cmsg, 0, WSA_CMSG_SPACE(sizeof(struct in_pktinfo)));
    cmsg->cmsg_level = IPPROTO_IP;
    cmsg->cmsg_type = IP_PKTINFO;
    cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(struct in_pktinfo));
    struct in_pktinfo *pktinfo = (struct in_pktinfo *)WSA_CMSG_DATA(cmsg);
    pktinfo->ipi_addr.s_addr = local_addr->ipv4;
    sum += WSA_CMSG_SPACE(sizeof(struct in_pktinfo));
...

msg.Control.len = sum;

if (bs->WSASendMsg(bs->socket, &msg, 0, &bytes, NULL, NULL) != 0) {
    ...
Community
  • 1
  • 1
dtb
  • 213,145
  • 36
  • 401
  • 431
-2

I think this is it.

UdpClient Constructor (IPEndPoint)

This constructor creates a new UdpClient and binds it to the IPEndPoint specified by the localEP parameter. Before you call this constructor, you must create an IPEndPoint using the IP address and port number from which you intend to send and receive data. You do not need to specify a local IP address and port number for sending and receiving data. If you do not, the underlying service provider will assign the most appropriate local IP address and port number.

Ross Presser
  • 6,027
  • 1
  • 34
  • 66
  • 2
    -1. This does not answer the question how to set the source address when the socket is bound to IPAddress.Any – dtb Jun 29 '13 at 08:21