#include #include #include #include #include #include #include typedef unsigned int uint32; /** Call as: $0 src-ip src-dev dest-ip */ int createUdpSocket(uint32 sip, uint32 sp, const char* bind_dev) { int s = socket(AF_INET, SOCK_DGRAM, 0); int r; //retval struct sockaddr_in my_ip_addr; if (s < 0) { perror("socket"); return s; } memset(&my_ip_addr, '\0', sizeof(my_ip_addr)); my_ip_addr.sin_family = AF_INET; my_ip_addr.sin_addr.s_addr = htonl(sip); my_ip_addr.sin_port = htons(sp); r = bind(s, (struct sockaddr*)(&my_ip_addr), sizeof(my_ip_addr)); if (r < 0) { perror("bind"); return r; } if (bind_dev) { // Bind to specific device. if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, bind_dev, strlen(bind_dev) + 1)) { perror("BINDTODEVICE"); } }//if return s; } int toIpString(const char* ip, uint32* retval) { struct hostent *hp; *retval = 0; if (strcmp(ip, "0.0.0.0") == 0) { return 0; } if (ip[0] == 0) { return 0; } // It seems it can't resolve IP addresses, or tries too hard to find a name, // or something. Need to check for a.b.c.d *retval = inet_addr(ip); if (*retval != INADDR_NONE) { *retval = ntohl(*retval); return 0; } // Otherwise, try to resolve it below. hp = gethostbyname(ip); if (hp == NULL) { return -1; }//if else { *retval = ntohl(*((unsigned int*)(hp->h_addr_list[0]))); if (*retval != 0) { return 0; } else { return -1; } } return -1; } /** Call as: $0 src-ip src-dev dest-ip */ int main(int argc, char** argv) { uint32 sip; uint32 dip; int s; int i; int z = 0; char buf[16]; struct sockaddr_in dest_addr; if (argc < 3) { printf("usage: bind_test src-ip src-dev dest-ip\n"); exit(2); } toIpString(argv[1], &sip); toIpString(argv[3], &dip); s = createUdpSocket(sip, 9, argv[2]); if (s < 0) { printf("ERROR: couldn't create udp socket.\n"); exit(1); } // set up the destination address memset(&dest_addr, '\0', sizeof(dest_addr)); dest_addr.sin_family = AF_INET; dest_addr.sin_addr.s_addr = htonl(dip); dest_addr.sin_port = htons(9); for (i = 0; i<5; i++) { int r = sendto(s, "sending text, bound", strlen("sending text, bound"), 0, (struct sockaddr*)(&dest_addr), sizeof(dest_addr)); if (r < 0) { perror("sendto"); } } /* unbind and send 5 more, use old API for pre-patched kernels. */ if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &z, sizeof(z))) { perror("BINDTODEVICE"); }//if for (i = 0; i<5; i++) { int r = sendto(s, "sending text, un-bound", strlen("sending text, un-bound"), 0, (struct sockaddr*)(&dest_addr), sizeof(dest_addr)); if (r < 0) { perror("sendto"); } } /* unbind the right way */ memset(&buf, 0, sizeof(buf)); if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, buf, sizeof(buf))) { perror("UN-BINDTODEVICE-2"); }//if for (i = 0; i<5; i++) { int r = sendto(s, "sending text, un-bound-2", strlen("sending text, un-bound-2"), 0, (struct sockaddr*)(&dest_addr), sizeof(dest_addr)); if (r < 0) { perror("sendto"); } } /* Unbind in the post-patch way (length of zero) */ if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, "", 0)) { perror("UN-BINDTODEVICE-3"); }//if close(s); exit(0); }//main