I have some C code running on MS Windows, which I am compiling/linking with the Microsoft compiler. The code opens a socket and connects to a remote server.
I want to write some code that determines which Windows network adapter is being used by my open socket. I can list all the Network adapters in my system using Microsoft's GetAdaptersAddresses function. In my system there are 12 adapters listed. I want to write some C code to determine which of those adapters is carrying the traffic for my open socket.
Below is some working sample code, which illustrates a connected socket and enumerating the network adapters. I have Google-searched for some sample C code to determine which network adapter is associated with my socket, to no avail. Thanks for any help you can offer.
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
#include <Iphlpapi.h>
#pragma comment(lib,"WS2_32.lib")
#pragma comment(lib,"IPHLPAPI.lib")
#include <stdio.h>
#include <stdlib.h>
static void enumAdapters();
int main(int argc,char *argv[])
{
WORD ver = MAKEWORD(2,2);
WSADATA wsa;
int sockfd;
struct sockaddr_in addr;
WSAStartup(ver,&wsa);
if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
fprintf(stderr,"Failed socket\n");
exit(1);
}
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
if (inet_pton(AF_INET,"142.250.65.238",&addr.sin_addr) < 0) {
fprintf(stderr,"Failed inet_pton\n");
exit(1);
}
if (connect(sockfd,(const struct sockaddr *)&addr,sizeof(addr)) < 0) {
fprintf(stderr,"Failed connect\n");
exit(1);
}
printf("Which of these adapters is my connected socket using?\n\n");
enumAdapters();
close(sockfd);
exit(0);
}
static void enumAdapters()
{
IP_ADAPTER_ADDRESSES _dummy,*ptr,*buf=&_dummy;
ULONG bufsize=0;
GetAdaptersAddresses(AF_INET,0,NULL,buf,&bufsize);
buf = (IP_ADAPTER_ADDRESSES *)malloc(bufsize);
if (GetAdaptersAddresses(AF_INET,0,NULL,buf,&bufsize) != NO_ERROR) {
fprintf(stderr,"Failed to get adapters\n");
return;
}
for (ptr=buf; ptr!=NULL; ptr=ptr->Next) {
printf("Adapter #%d %s\n",(int)ptr->IfIndex,ptr->AdapterName);
printf(" %wS (%wS)\n",ptr->FriendlyName,ptr->Description);
}
free(buf);
return;
}
The correct solution was suggested in the comments of the question by several people, which was to use
getsockname()to obtain the IP address that the client socket is bound to, and then match that IP address against theFirstUnicastAddressfrom the adapters returned fromGetAdaptersAddresses(). Below is the C implementation that works. The code works with IPv4 only, but it could easily be extended to include IPv6.Thanks to those who commented in the question to help me solve this.