Send Raw arp reply packet in windows - c

I am currently learning how to use the windows raw sockets.
I created a raw arp reply frame(includes all headers (ethernet+arp headers)), and when I send it using sendto function,
It fails and return SOCKET_ERROR with error code 10047.
The parameters I used to create the socket are as follows:
socket s = socket(AF_INET,SOCK_RAW,IPPROTO_RAW);
and also I changed the socket options as follows:
int on=1;
setsockopt(s,IPPROTO_IP, 2,(char*)&on,sizeof(on));
(By the way, '2' is equal to IP_HDRINCL, for some reason, visual studio didn't recognize it..)
I try to send the packet as follows:
socketaddr sa = { 0 };
int SentBytesCount = sendto(s, (char*)&arp_raw_msg,sizeof(Arp_Frame),0,&sa,sizeof(sa));
Where Arp_Frame is a struct that includes ethernet header+arp header+18 Bytes for padding.
After this call I get that SentBytesCount is equal to SOCKET_ERROR(-1), and no packet is sent.
Thank you for your help!

Winsock error 10047 is WSAEAFNOSUPPORT:
Address family not supported by protocol family.
An address incompatible with the requested protocol was used. All sockets are created with an associated address family (that is, AF_INET for Internet Protocols) and a generic protocol type (that is, SOCK_STREAM). This error is returned if an incorrect protocol is explicitly requested in the socket call, or if an address of the wrong family is used for a socket, for example, in sendto.
You created an AF_INET (IPv4) socket, but you are not passing sendto() a valid sockaddr_in containing an IPv4 address and port, hence the error. You are passing it an empty socketaddr (what is that?) instead.
Any sockaddr_... struct you use with a socket must match what the socket's address family expects, as set by the socket() call (in your case, AF_INET, which uses sockaddr_in addresses).
sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = inet_addr("destination IP address");
sa.sin_port = htons(Destination port number);
int SentBytesCount = sendto(s, (char*)&arp_raw_msg, sizeof(Arp_Frame), 0, (struct sockaddr*)&sa, sizeof(sa));
As for IP_HDRINCL, it is defined in ws2tcpip.h.

Related

Send a single RIPv2 datagram using UDP from and to a specific port?

I have an assignment to make a Routing Information Protocol sniffer and a program in C/C++ capable of sending custom RIP entry using the information gathered from the sniffer.
I'm running both in a school provided Ubuntu Virtualbox image, which is connected via "Internal Network" option to a BSD image running a routing daemon generating RIP traffic.
I got to the part where I need to send the custom packet to the "router" but I hit a wall when trying to send it from port 520.
From the RFC 1058 describing the RIP protocol I gathered that in order for a router to acknowledge a new route, the RIP message has to come from and to the port 520.
I can send my packet to port 520 of the router just fine, but the source port is always a random port assigned by system after my binding fails with an errno message "Cannot assign requested address".
The packet itself looks just fine in WireShark, with the exception of the source port which is for example 60818.
I am doing the following in my response program:
#define ROUTERADDR "10.0.0.1"
int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in router;
router.sin_family = AF_INET;
router.sin_port = htons(520);
router.sin_addr.s_addr = inet_addr(ROUTERADDR);
bind (fd, (struct sockaddr*)&router, sizeof(router));
connect (fd, (struct sockaddr*)&router, sizeof(router));
send(fd, &payload, sizeof(payload), 0);
close(fd);
Binding to a port < 1024 requires root permission, unless you add your executable to CAP_NET_BIND_SERVICE capability as below.
setcap 'cap_net_bind_service=+ep' /path/to/executable
There is another issue in your code, where you are trying to bind to router's address. You need to bind to the specific local address or INADDR_ANY, as shown below.
struct sockaddr_in local, router;
local.sin_family = AF_INET;
local.sin_port = htons(520);
local.sin_addr.s_addr = htonl(INADDR_ANY);
bind (fd, (struct sockaddr*)&local, sizeof(local));
router.sin_family = AF_INET;
router.sin_port = htons(520);
router.sin_addr.s_addr = inet_addr(ROUTERADDR);
connect (fd, (struct sockaddr*)&router, sizeof(router));
You should check the return value of your system calls, so you know when things don't work, as in your case the bind() call likely fails.
In your case bind() would fail because you try to bind to a port on the remote address you're sending to, which you cannot do.
bind() specifies the local endpoint you want to use, thus you should specify one of the local IP addresses you want to send from.
Or you can bind the socket to any local address, using INADDR_ANY. so you might want to create another struct sockaddr_in and do it like this:
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(520);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(fd, (struct sockaddr*)&my_addr, sizeof(my_addr)) != 0) {
perror("bind() failed");
}

"UDP datagrams only" socket in C

In Linux, Ubuntu 14.04:
I'm writing a code that implements socket to send pure UDP datagrams which includes UDP header+payload, without any part of IP header.
I have created the socket
sokt_fd=socket(AF_INET, SOCK_RAW, IPPROTO_UDP)
Also, I have prepared the UDP header.
I want to leave the IP encapsulation process to the kernel.
I want to send the datagram over any available IP interface. (I do not want to specify the source IP, and also leave this task to the kernel).
Do I need to specify the destination IP address before sending the datagram.
I must use "sendto()" command to send the datagram; how I must fill the "sockaddr" data structure?
#include <netinet/in.h>
struct sockaddr
{
unsigned short sa_family;// address family, AF_xxx
char sa_data[14];// 14 bytes of protocol address
};
Don't use the sockaddr structure. Use sockaddr_in instead and cast it when you have to pass a sockaddr* to a function.
struct sockaddr_in myaddr;
int s;
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(3490);
inet_aton("63.161.169.137", &myaddr.sin_addr.s_addr);
s = socket(PF_INET, SOCK_STREAM, 0);
bind(s, (struct sockaddr*)myaddr, sizeof(myaddr));
The socket API is designed for different addressing families, others are Infrared and Bluetooth. Since AF_INET is only one of the families the API functions use the general sockaddr type in the parameters.
There is a nice explanation of this in Chapter 3, "Sockets Introduction" in the well-known book Unix Network Programming, The Sockets Networking API (Volume 1) by Richard Stevens et. al. Let me quote:
Most socket functions require a pointer to a socket address structure
as an argument. Each supported protocol suite defines its own socket
address structure. The names of these structures begin with
sockaddr_ and end with a unique suffix for each protocol suite.
For the IP (Internet protocol) suite, the structure is sockaddr_in so it follows that since your example is specifying the AF_INET address family when you created the socket that you would use the more specific sockaddr_in structure instead of the more generic sockaddr. The socket API, as a matter of efficiency uses the more generic sockaddr pointer in the signature prototype.
With regard to using send() versus sendto(), I have found that sendto() is used more commonly with UDP and send() with TCP sockets. Therefore, to answer your question in #3 above, with UDP you don't have to specify the destination address up front, but instead it is supplied as an argument to sendto().
For a given udp_datagram and datagram_length, your code might look something like this:
uint32_t address = inet_addr("1.2.3.4"); // can also provide hostname here
uint16_t port = 27890;
sockaddr_in_t dest_addr;
memset(*dest_addr, 0, sizeof(dest_addr));
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(port);
dest_addr.sin_addr.s_addr = htonl(address);
sendto(socket_fd,
(const char*)upd_datagram,
datagram_length,
0,
reinterpret_cast<sockaddr_t*>(&dest_addr),
sizeof(dest_addr));
The address API really wanted to be object-oriented, but had to deal with the fact that C isn't an OO language. sockaddr can be seen as the "base class" and the parameter type that bind, connect, sendto, recvfrom, etc. use when they need an address. However, you must provide a "subclassed" address matching the socket domain that you're using. This is because Berkeley sockets can be used for a wide and extensible range of protocols. IPv4 and IPv6 are the most typical, but UNIX-based installs also support sockets as filesystem objects ("addressed" by path), and, for instance, a hypervisor driver can install support for special inter-VM or guest-to-host sockets. See man 7 socket for an overview.
If you use IPv4, you need to use sockaddr_in. If you use IPv6, you need to use sockaddr_in6. In both cases, you need to cast your pointer to a sockaddr*.
To fill in a sockaddr_in, you need to do something like this:
struct sockaddr_in inet_addr;
inet_addr.sin_family = AF_INET;
inet_addr.sin_port = htons(port);
inet_addr.sin_addr.s_addr = htonl(ip_address_as_number);
struct sockaddr* addr = (struct sockaddr*)&inet_addr;
htons and htonl stand for "host to network (short)" and "host to network (long)", respectively. You need this because there was a time at which network drivers were too dumb to abstract away the machine's endianness and we can't go back in time to fix them. (The network byte order is big endian.)

socket connect() vs bind()

Both connect() and bind() system calls 'associate' the socket file descriptor to an address (typically an ip/port combination). Their prototypes are like:-
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
and
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
What is the exact difference between 2 calls? When should one use connect() and when bind()?
Specifically, in some sample server client codes, found that client is using connect() and server is using the bind() call. Reason was not fully clear to me.
To make understanding better , lets find out where exactly bind and connect comes into picture,
Further to positioning of two calls , as clarified by Sourav,
bind() associates the socket with its local address [that's why server side binds, so that clients can use that address to connect to server.]
connect() is used to connect to a remote [server] address, that's why is client side, connect [read as: connect to server] is used.
We cannot use them interchangeably (even when we have client/server on same machine) because of specific roles and corresponding implementation.
I will further recommend to correlate these calls TCP/IP handshake .
So, who will send SYN here, it will be connect(). While bind() is used for defining the communication end point.
The one liner : bind() to own address, connect() to remote address.
Quoting from the man page of bind()
bind() assigns the address specified by addr to the socket referred to by the file descriptor sockfd. addrlen specifies the size, in bytes, of the address structure pointed to by addr. Traditionally, this operation is called "assigning a name to a socket".
and, from the same for connect()
The connect() system call connects the socket referred to by the file descriptor sockfd to the address specified by addr.
To clarify,
bind() associates the socket with its local address [that's why
server side binds, so that clients can use that address to connect
to server.]
connect() is used to connect to a remote [server] address, that's
why is client side, connect [read as: connect to server] is used.
I think it would help your comprehension if you think of connect() and listen() as counterparts, rather than connect() and bind(). The reason for this is that you can call or omit bind() before either, although it's rarely a good idea to call it before connect(), or not to call it before listen().
If it helps to think in terms of servers and clients, it is listen() which is the hallmark of the former, and connect() the latter. bind() can be found - or not found - on either.
If we assume our server and client are on different machines, it becomes easier to understand the various functions.
bind() acts locally, which is to say it binds the end of the connection on the machine on which it is called, to the requested address and assigns the requested port to you. It does that irrespective of whether that machine will be a client or a server. connect() initiates a connection to a server, which is to say it connects to the requested address and port on the server, from a client. That server will almost certainly have called bind() prior to listen(), in order for you to be able to know on which address and port to connect to it with using connect().
If you don't call bind(), a port and address will be implicitly assigned and bound on the local machine for you when you call either connect() (client) or listen() (server). However, that's a side effect of both, not their purpose. A port assigned in this manner is ephemeral.
An important point here is that the client does not need to be bound, because clients connect to servers, and so the server will know the address and port of the client even though you are using an ephemeral port, rather than binding to something specific. On the other hand, although the server could call listen() without calling bind(), in that scenario they would need to discover their assigned ephemeral port, and communicate that to any client that it wants to connect to it.
I assume as you mention connect() you're interested in TCP, but this also carries over to UDP, where not calling bind() before the first sendto() (UDP is connection-less) also causes a port and address to be implicitly assigned and bound. One function you cannot call without binding is recvfrom(), which will return an error, because without an assigned port and bound address, there is nothing to receive from (or too much, depending on how you interpret the absence of a binding).
bind tells the running process to claim a port. i.e, it should bind itself to port 80 and listen for incomming requests. with bind, your process becomes a server. when you use connect, you tell your process to connect to a port that is ALREADY in use. your process becomes a client. the difference is important: bind wants a port that is not in use (so that it can claim it and become a server), and connect wants a port that is already in use (so it can connect to it and talk to the server)
From Wikipedia http://en.wikipedia.org/wiki/Berkeley_sockets#bind.28.29
connect():
The connect() system call connects a socket, identified by its file descriptor, to a remote host specified by that host's address in the argument list.
Certain types of sockets are connectionless, most commonly user datagram protocol sockets. For these sockets, connect takes on a special meaning: the default target for sending and receiving data gets set to the given address, allowing the use of functions such as send() and recv() on connectionless sockets.
connect() returns an integer representing the error code: 0 represents success, while -1 represents an error.
bind():
bind() assigns a socket to an address. When a socket is created using socket(), it is only given a protocol family, but not assigned an address. This association with an address must be performed with the bind() system call before the socket can accept connections to other hosts. bind() takes three arguments:
sockfd, a descriptor representing the socket to perform the bind on.
my_addr, a pointer to a sockaddr structure representing the address to bind to.
addrlen, a socklen_t field specifying the size of the sockaddr structure.
Bind() returns 0 on success and -1 if an error occurs.
Examples:
1.)Using Connect
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(){
int clientSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
socklen_t addr_size;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(7891);
/* Set the IP address to desired host to connect to */
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.17");
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Connect the socket to the server using the address struct ----*/
addr_size = sizeof serverAddr;
connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);
/*---- Read the message from the server into the buffer ----*/
recv(clientSocket, buffer, 1024, 0);
/*---- Print the received message ----*/
printf("Data received: %s",buffer);
return 0;
}
2.)Bind Example:
int main()
{
struct sockaddr_in source, destination = {}; //two sockets declared as previously
int sock = 0;
int datalen = 0;
int pkt = 0;
uint8_t *send_buffer, *recv_buffer;
struct sockaddr_storage fromAddr; // same as the previous entity struct sockaddr_storage serverStorage;
unsigned int addrlen; //in the previous example socklen_t addr_size;
struct timeval tv;
tv.tv_sec = 3; /* 3 Seconds Time-out */
tv.tv_usec = 0;
/* creating the socket */
if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
printf("Failed to create socket\n");
/*set the socket options*/
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
/*Inititalize source to zero*/
memset(&source, 0, sizeof(source)); //source is an instance of sockaddr_in. Initialization to zero
/*Inititalize destinaton to zero*/
memset(&destination, 0, sizeof(destination));
/*---- Configure settings of the source address struct, WHERE THE PACKET IS COMING FROM ----*/
/* Address family = Internet */
source.sin_family = AF_INET;
/* Set IP address to localhost */
source.sin_addr.s_addr = INADDR_ANY; //INADDR_ANY = 0.0.0.0
/* Set port number, using htons function to use proper byte order */
source.sin_port = htons(7005);
/* Set all bits of the padding field to 0 */
memset(source.sin_zero, '\0', sizeof source.sin_zero); //optional
/*bind socket to the source WHERE THE PACKET IS COMING FROM*/
if (bind(sock, (struct sockaddr *) &source, sizeof(source)) < 0)
printf("Failed to bind socket");
/* setting the destination, i.e our OWN IP ADDRESS AND PORT */
destination.sin_family = AF_INET;
destination.sin_addr.s_addr = inet_addr("127.0.0.1");
destination.sin_port = htons(7005);
//Creating a Buffer;
send_buffer=(uint8_t *) malloc(350);
recv_buffer=(uint8_t *) malloc(250);
addrlen=sizeof(fromAddr);
memset((void *) recv_buffer, 0, 250);
memset((void *) send_buffer, 0, 350);
sendto(sock, send_buffer, 20, 0,(struct sockaddr *) &destination, sizeof(destination));
pkt=recvfrom(sock, recv_buffer, 98,0,(struct sockaddr *)&destination, &addrlen);
if(pkt > 0)
printf("%u bytes received\n", pkt);
}
I hope that clarifies the difference
Please note that the socket type that you declare will depend on what you require, this is extremely important
Too Long; Don't Read: The difference is whether the source (local) or the destination address/port is being set. In short, bind() set the source and connect() set the destination. Regardless of TCP or UDP.
bind()
bind() set the socket's local (source) address. This is the address where packets are received. Packets sent by the socket carry this as the source address, so the other host will know where to send back its packets.
If receive is not needed the socket source address is useless. Protocols like TCP require receiving enabled in order to send properly, as the destination host send back a confirmation when one or more packets have arrived (i.e. acknowledgement).
connect()
TCP has a "connected" state. connect() triggers the TCP code to try to establish a connection to the other side.
UDP has no "connected" state. connect() only set a default address to where packets are sent when no address is specified. When connect() is not used, sendto() or sendmsg() must be used containing the destination address.
When connect() or a send function is called, and no address is bound, Linux automatically bind the socket to a random port. For technical details, take a look at inet_autobind() in Linux kernel source code.
Side notes
listen() is TCP only.
In AF_INET family, the socket's source or destination address (struct sockaddr_in) is composed by an IP address (see IP header), and TCP or UDP port (see TCP and UDP header).

raw ethernet sockets filling sockaddr_ll

I am buliding a server/client software using PF_PACKET and SOCK_RAW and a custom protocol when calling socket()
When in the client software I create the socket the same way and just do a rcvfrom that socket and I get the data
My question is do I have to fill out the sockaddr_ll struct the same way I do for the server since when I reply from the client the source MAC address I got is a wierd one something like
11:11:00:00:00:00 and of course this is not my client's MAC
Does anyone know what this happens?
Open the socket
if ( (sckfd=socket(PF_PACKET, SOCK_RAW, htons(proto)))<0)
{
myError("socket");
}
this is how I receive the data
n = recvfrom(sckfd, buffer, 2048, 0, NULL, NULL);
printf("%d bytes read\n",n);
So this is how I basically receive the data in the client without filling the struct sockaddr_ll
For the server Program I do have to fill the struct
struct sockaddr_ll saddrll;
memset((void*)&saddrll, 0, sizeof(saddrll));
saddrll.sll_family = PF_PACKET;
saddrll.sll_ifindex = ifindex;
saddrll.sll_halen = ETH_ALEN;
memcpy((void*)(saddrll.sll_addr), (void*)dest, ETH_ALEN);
My question is I receive as shown and send as shown and when I reply to the server call the same function used in the server for Sending then what do I get 11:11:00:00:00:00 when receiving client replies
You should probably use
socket(AF_PACKET, SOCK_DGRAM, htons(proto)))
instead of a SOCK_RAW socket. With a SOCK_RAW, you are sending/receiving the entire ethernet frame, including source and destination MAC address. with SOCK_DGRAM, the kernel will fill in the ethernet header.
You probably want to send the reply to the same address as the request comes from, recvfrom() can fill in the source address;
struct sockaddr_ll src_addr;
socklen_t addr_len = sizeof src_addr;
n = recvfrom(sckfd, buffer, 2048, 0,
(struct sockaddr*)&src_addr, &addr_len);
Now you've learned the source address, so send the packet back to it:
...
sendto(sckfd, data, data_len, src_addr, addr_len);
And if you rather need to use SOCK_RAW, your will receive the ethernet header too, so just copy out the MAC addresses from the received data and swap them around when you are constructing the reply frame.
For an a SOCK_RAW socket, you craft the entire ethernet frame, you don't need to fill in the ethernet address, so the following is not needed;
memcpy((void*)(saddrll.sll_addr), (void*)dest, ETH_ALEN);

recvfrom not receiving depending on ai_family used

I'm trying to get my head around socket programming and have encountered some unexpected (for me) behaviour.
When I try to send data to "localhost" and set addrinfo.ai_family to AF_INET the message I send isn't coming through from my client process to my host process (recvfrom() doesn't return). If I set it to AF_INET6 all is fine. Same for AF_UNSPEC in which case it picks the IPv6 addrinfo (first in the list). Both host and client use the same ai_family of course.
I've also tried this with code copy pasted from beej's guide to network programming which had the same result. I'm using DGRAM sockets.
I tried connecting from a different pc I got the opposite results, IPv4 worked fine, IPv6 did not. I gather this may be due to me using a '6to4 gateway'. I really have no idea what this means.
The problem is related to my own machine as the code does work over IPv4 on another machine I tested it on.
I can't say if it's a sending or receiving problem.
What could prevent me from sending or receiving data to/from localhost using AF_INET sockets?
I'm on a windows7 64bit machine compiling with MingW.
If it makes any difference I'm running the same program for host and client processes with different arguments. I ran the release and debug programs together (so it's not the same program twice) but got the same results.
Thanks in advance and apologies if this is considered a stupid question.
code:
typedef struct addrinfo addrinfo_t;
typedef struct sockaddr_storage sockaddr_storage_t;
typedef struct sockaddr_in sockaddr_in_t;
typedef struct sockaddr_in6 sockaddr_in6_t;
void connect_to_server(const char* server_name, const char* message)
{
int status;
init_networking();
addrinfo_t hints;
addrinfo_t* res;
memset(&hints, 0, sizeof(addrinfo_t));
hints.ai_family = AF_INET; //or AF_INET6
hints.ai_socktype = SOCK_DGRAM;
if ((status = getaddrinfo(server_name, "4950", &hints, &res)) != 0)
{
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
SOCKET s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s == -1)
{
fprintf(stderr, "could not create a socket, errno: %u\n", errno);
exit(1);
}
int bytes_sent = sendto(s, message, strlen(message), 0, res->ai_addr, res->ai_addrlen);
close(s);
printf("Sent %i bytes to port %i\n", bytes_sent, ((sockaddr_in_t*)res->ai_addr)->sin_port);
freeaddrinfo(res);
}
void setup_server()
{
int status;
init_networking();
addrinfo_t hints;
addrinfo_t* res;
memset(&hints, 0, sizeof(addrinfo_t));
hints.ai_family = AF_INET; //or AF_INET6
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE;
if ((status = getaddrinfo(NULL, "4950", &hints, &res)) != 0)
{
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
exit(1);
}
SOCKET s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s == -1)
{
fprintf(stderr, "could not create a socket, errno: %u\n", errno);
exit(1);
}
//Bind the socket to own address (mostly the port number contained in the address)
if (bind(s, res->ai_addr, res->ai_addrlen) < 0)
{
fprintf(stderr, "failed to bind, errno: %u\n", errno);
exit(1);
}
freeaddrinfo(res);
const size_t read_buffer_size = 1024;
void* read_buffer = malloc(read_buffer_size);
sockaddr_storage_t peer_address;
int peer_address_length = sizeof(sockaddr_storage_t);
sockaddr_storage_t own_sock_addr;
int own_sock_addr_len = sizeof(sockaddr_storage_t);
getsockname(s, (struct sockaddr*)&own_sock_addr, &own_sock_addr_len);
printf("Listening on port %i\n", ((sockaddr_in_t*)&own_sock_addr)->sin_port);
int bytes_received = recvfrom(s,
read_buffer,
read_buffer_size-1,
0,
(struct sockaddr*)&peer_address,
&peer_address_length );
printf("Received %i byte message:\n%s\n", bytes_received, (char*)read_buffer);
}
AF_INET is for IPv4, and AF_INET6 is for IPv6. When sending an IPv4 datagram, the receiver must be receiving data on the destination IP/port using either an IPv4 socket or an IPv6 dual stack socket (an IPv6 socket that accepts both IPv4 and IPv6 traffic). When sending an IPv6 datagram, the receiver must be receiving data using an IPv6 socket. Otherwise, the datagram will be ignored, So it sounds like the one machine is using an IPv6 socket that ignores your IPv4 datagram, and the other machine is using an IPv4 socket that ignores your IPv6 datagram.
When you are calling getaddrinfo(), you are specifying AF_UNSPEC as the address family in both client and server. AF_UNSPEC tells getaddrinfo() that you want both IPv4 and IPv6 addresses, so it returns a linked list that potentially contains multiple entries for all of the available IPv4 and IPv6 addresses. On the server side, you are creating a single listening socket for only the first entry in the list, which may be IPv4 or IPv6. On the client side, you are creating a single sending socket for only the first entry in the list, which may be IPv4 or IPv6. So the actual address families used in both operations are going to be random and may mismatch each other at times.
On the server side, you need to either:
use AF_INET or AF_INET6 directly, instead of AF_UNSPEC, and then code the client accordingly to match.
loop through the entire addrinfo list creating a separate listening socket for every entry. That way, clients can send data to any IP/Port family the server is listening on.
use AF_INET6 only when creating the listening socket(s), but then enable dual stack functionality on them (Vista+ only) so they can receive both IPv4 and IPv6 datagrams. You will then have to pay attention to the address family reported by the sockaddr that recvfrom() returns in order to know whether any given datagram is using IPv4 or IPv6.
On the client side, you need to use AF_INET or AF_INET6 directly, instead of AF_UNSPEC, depending on what the server is actually listening on. It does not make sense to use AF_UNSPEC for a UDP client socket (it does make sense for a TCP client socket), unless the UDP protocol you are implementing replies to each datagram with an ack. Without that, the client has no way to know whether the server is accepting IPv4 or IPv6 datagrams (unless the user tells the app). With acks, the client could loop through the returned addrinfo list, sending a datagram to an entry in the list, wait a few seconds for an ack, and if not received then move on to the next entry in the list, repeating as needed until an ack actually arrives or the list is exhausted.

Resources