在
linux中,如何使用0.0.0.0作为源地址传输UDP数据包.
这是我到目前为止所尝试的.
#include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <net/if.h> #include <string.h> #include <unistd.h> #include <assert.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> int main(int argc,const char *argv[]) { struct sockaddr_in dst,src; struct ifreq ifr; int sock,tmp; char payload[128]; memset(payload,128); memset(&dst,sizeof(dst)); dst.sin_family = AF_INET; dst.sin_addr.s_addr = inet_addr("255.255.255.255"); dst.sin_port = htons(67); memset(&src,sizeof(src)); src.sin_family = AF_INET; src.sin_addr.s_addr = inet_addr("0.0.0.0"); src.sin_port = htons(68); sock = socket(AF_INET,SOCK_DGRAM,0); if (sock < 0) perror("Failed to create socket"); tmp = 1; if (setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&tmp,sizeof(tmp)) < 0) perror("SO_BROADCAST Failed"); if (setsockopt(sock,SO_REUSEADDR,sizeof(tmp)) < 0) perror("SO_REUSEADDR Failed"); if (setsockopt(sock,IPPROTO_IP,IP_FREEBIND,sizeof(tmp)) < 0) perror("IP_FREEBIND Failed"); memset(&ifr,sizeof(ifr)); strncpy(ifr.ifr_name,"eth1",sizeof(ifr.ifr_name)); if (setsockopt(sock,SO_BINDTODEVICE,(void *)&ifr,sizeof(ifr)) < 0) perror("SO_BINDTODEVICE Failed"); if (bind(sock,(const struct sockaddr*)&src,sizeof(struct sockaddr_in)) < 0) perror("bind Failed"); if (connect(sock,(const struct sockaddr*)&dst,sizeof(struct sockaddr_in)) < 0) perror("bind Failed"); if (write(sock,payload,128) < 0 ) perror("Write Failed"); close(sock); return 0; }
问题是如果没有接口有IPv4地址,则源地址仅设置为0.0.0.0.如果只有一个接口具有IPv4地址,则该地址用作源地址.
我查看了一些现有DHCP客户端的源代码,发现他们正在使用RAW套接字并手动构建IP和UDP头.这是可能的,但我想避免手动这样做.
解决方法
你应该使用RAW SOCKET并自己构建数据包.
举个例子,你可以这样:https://github.com/fycth/DHCP-server-scanner/blob/master/src/dhcpd-detector.c
这是我的教育项目.它很小,你可以看看这个任务究竟是如何解决的.