📄 client.c
字号:
#include <sys/types.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/time.h>#include <sys/utsname.h>#include <net/if.h>#include <net/if_arp.h>#ifdef __GLIBC__#include <net/if_packet.h>#else#include <linux/if_packet.h>#endif#include <net/route.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <syslog.h>#include <errno.h>#include <setjmp.h>#include <time.h>#include "client.h"#include "setmsg.h"#include "udpipgen.h"#include "autoip.h"extern char *ProgramName;extern char *IfNameExt;extern int IfNameExt_len;extern char *HostName;extern unsigned char *ClassID;extern int ClassID_len;extern unsigned char *ClientID;extern int ClientID_len;extern int DebugFlag;extern int BeRFC1541;extern unsigned LeaseTime;extern int SetHostName;extern int SendSecondDiscover;extern unsigned short ip_id;extern void *(*currState)();extern time_t TimeOut;extern unsigned nleaseTime;extern struct in_addr inform_ipaddr;extern int DoCheckSum;extern int InitialHostName_len;extern char *InitialHostName;extern int DownIfaceOnStop;extern int autoip_flag;extern int autoip_sleep;int sendRelArp();int dhcpConfig();int dhcpSocket;int udpFooSocket;int prev_ip_addr;time_t ReqSentTime;dhcpOptions DhcpOptions;dhcpInterface DhcpIface;udpipMessage UdpIpMsgSend,UdpIpMsgRecv;jmp_buf env;unsigned char ClientHwAddr[ETH_ALEN];const struct ip *ipSend=(struct ip *)((struct udpiphdr *)UdpIpMsgSend.udpipmsg)->ip;const struct ip *ipRecv=(struct ip *)((struct udpiphdr *)UdpIpMsgRecv.udpipmsg)->ip;const dhcpMessage *DhcpMsgSend = (dhcpMessage *)&UdpIpMsgSend.udpipmsg[sizeof(udpiphdr)]; dhcpMessage *DhcpMsgRecv = (dhcpMessage *)&UdpIpMsgRecv.udpipmsg[sizeof(udpiphdr)];static short int saved_if_flags = 0;int parseDhcpMsg() { register u_char *p = DhcpMsgRecv->options+4; unsigned char *end = DhcpMsgRecv->options+sizeof(DhcpMsgRecv->options); /* Force T1 and T2 to 0: either new values will be in message, or they will need to be recalculated from lease time */ if (DhcpOptions.val[dhcpT1value] && DhcpOptions.len[dhcpT1value] > 0) memset(DhcpOptions.val[dhcpT1value],0,DhcpOptions.len[dhcpT1value]); if (DhcpOptions.val[dhcpT2value] && DhcpOptions.len[dhcpT2value] > 0) memset(DhcpOptions.val[dhcpT2value],0,DhcpOptions.len[dhcpT2value]); while (p < end) switch (*p) { case endOption: goto swend; case padOption: p++; break; default: if (p[1]) { if (p + 2 + p[1] >= end) goto swend; /* corrupt packet */ if (DhcpOptions.len[*p] == p[1]) memcpy(DhcpOptions.val[*p],p+2,p[1]); else { DhcpOptions.len[*p] = p[1]; if (DhcpOptions.val[*p]) free(DhcpOptions.val[*p]); else DhcpOptions.num++; DhcpOptions.val[*p] = malloc(p[1]+1); memset(DhcpOptions.val[*p],0,p[1]+1); memcpy(DhcpOptions.val[*p],p+2,p[1]); } } p+=p[1]+2; } swend: if (! DhcpMsgRecv->yiaddr) DhcpMsgRecv->yiaddr=DhcpMsgSend->ciaddr; /* did not get dhcpServerIdentifier, make it the same as IP address of the sender */ if (! DhcpOptions.val[dhcpServerIdentifier]) { DhcpOptions.val[dhcpServerIdentifier] = malloc(4); memcpy(DhcpOptions.val[dhcpServerIdentifier],&ipRecv->ip_src.s_addr,4); DhcpOptions.len[dhcpServerIdentifier] = 4; DhcpOptions.num++; if (DebugFlag) syslog(LOG_DEBUG, "dhcpServerIdentifier option is missing in DHCP server response. Assuming %u.%u.%u.%u\n", ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2], ((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]); } /* did not get subnetMask */ if (! DhcpOptions.val[subnetMask]) { DhcpOptions.val[subnetMask] = malloc(4); ((unsigned char *)DhcpOptions.val[subnetMask])[0] = 255; if (IN_CLASSA(ntohl(DhcpMsgRecv->yiaddr))) { ((unsigned char *)DhcpOptions.val[subnetMask])[1] = 0; /* class A */ ((unsigned char *)DhcpOptions.val[subnetMask])[2] = 0; ((unsigned char *)DhcpOptions.val[subnetMask])[3] = 0; } else { ((unsigned char *)DhcpOptions.val[subnetMask])[1] = 255; if ( IN_CLASSB(ntohl(DhcpMsgRecv->yiaddr)) ) { ((unsigned char *)DhcpOptions.val[subnetMask])[2] = 0;/* class B */ ((unsigned char *)DhcpOptions.val[subnetMask])[3] = 0; } else { ((unsigned char *)DhcpOptions.val[subnetMask])[2] = 255; if (IN_CLASSC(ntohl(DhcpMsgRecv->yiaddr))) ((unsigned char *)DhcpOptions.val[subnetMask])[3] = 0; /* class C */ else ((unsigned char *)DhcpOptions.val[subnetMask])[3] = 255; } } DhcpOptions.len[subnetMask] = 4; DhcpOptions.num++; if (DebugFlag) printf("subnetMask option is missing in DHCP server response. Assuming %u.%u.%u.%u\n", ((unsigned char *)DhcpOptions.val[subnetMask])[0], ((unsigned char *)DhcpOptions.val[subnetMask])[1], ((unsigned char *)DhcpOptions.val[subnetMask])[2], ((unsigned char *)DhcpOptions.val[subnetMask])[3]); } /* did not get broadcastAddr */ if (! DhcpOptions.val[broadcastAddr]) { int br = DhcpMsgRecv->yiaddr | ~*((int *)DhcpOptions.val[subnetMask]); DhcpOptions.val[broadcastAddr] = malloc(4); memcpy(DhcpOptions.val[broadcastAddr],&br,4); DhcpOptions.len[broadcastAddr] = 4; DhcpOptions.num++; if (DebugFlag) printf("broadcastAddr option is missing in DHCP server response. Assuming %u.%u.%u.%u\n", ((unsigned char *)DhcpOptions.val[broadcastAddr])[0], ((unsigned char *)DhcpOptions.val[broadcastAddr])[1], ((unsigned char *)DhcpOptions.val[broadcastAddr])[2], ((unsigned char *)DhcpOptions.val[broadcastAddr])[3]); } if (DhcpOptions.val[dhcpIPaddrLeaseTime] && DhcpOptions.len[dhcpIPaddrLeaseTime] == 4) { if (*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime] == 0) { memcpy(DhcpOptions.val[dhcpIPaddrLeaseTime],&nleaseTime,4); if (DebugFlag) printf("dhcpIPaddrLeaseTime=0 in DHCP server response. Assuming %u sec\n",LeaseTime); } else if (DebugFlag) printf("dhcpIPaddrLeaseTime=%u in DHCP server response.\n", ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime])); } /* did not get dhcpIPaddrLeaseTime */ else { DhcpOptions.val[dhcpIPaddrLeaseTime] = malloc(4); memcpy(DhcpOptions.val[dhcpIPaddrLeaseTime],&nleaseTime,4); DhcpOptions.len[dhcpIPaddrLeaseTime] = 4; DhcpOptions.num++; if (DebugFlag) printf("dhcpIPaddrLeaseTime option is missing in DHCP server response. Assuming %u sec\n",LeaseTime); } if (DhcpOptions.val[dhcpT1value] && DhcpOptions.len[dhcpT1value] == 4) { if (*(unsigned int *)DhcpOptions.val[dhcpT1value] == 0) { unsigned t2 = 0.5*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]); int t1 = htonl(t2); memcpy(DhcpOptions.val[dhcpT1value],&t1,4); DhcpOptions.len[dhcpT1value] = 4; if (DebugFlag) printf("dhcpT1value is missing in DHCP server response. Assuming %u sec\n",t2); } } /* did not get T1 */ else { unsigned t2 = 0.5*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]); int t1 = htonl(t2); DhcpOptions.val[dhcpT1value] = malloc(4); memcpy(DhcpOptions.val[dhcpT1value],&t1,4); DhcpOptions.len[dhcpT1value] = 4; DhcpOptions.num++; if (DebugFlag) printf("dhcpT1value is missing in DHCP server response. Assuming %u sec\n",t2); } if (DhcpOptions.val[dhcpT2value] && DhcpOptions.len[dhcpT2value] == 4) { if (*(unsigned int *)DhcpOptions.val[dhcpT2value] == 0) { unsigned t2 = 0.875*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]); int t1 = htonl(t2); memcpy(DhcpOptions.val[dhcpT2value],&t1,4); DhcpOptions.len[dhcpT2value] = 4; if (DebugFlag) printf("dhcpT2value is missing in DHCP server response. Assuming %u sec\n",t2); } } /* did not get T2 */ else { unsigned t2 = 0.875*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]); int t1 = htonl(t2); DhcpOptions.val[dhcpT2value] = malloc(4); memcpy(DhcpOptions.val[dhcpT2value],&t1,4); DhcpOptions.len[dhcpT2value] = 4; DhcpOptions.num++; if (DebugFlag) printf("dhcpT2value is missing in DHCP server response. Assuming %u sec\n",t2); } if (DhcpOptions.val[dhcpFQDNHostName]) { printf("dhcpFQDNHostName response flags = %02X rcode1 = %02X rcode2 = %02X name = \"%s\"\n", ((unsigned char *)DhcpOptions.val[dhcpFQDNHostName])[0], ((unsigned char *)DhcpOptions.val[dhcpFQDNHostName])[1], ((unsigned char *)DhcpOptions.val[dhcpFQDNHostName])[2], ((char *)DhcpOptions.val[dhcpFQDNHostName])+3); } if (DhcpOptions.val[dhcpMessageType]) return *(unsigned char *)DhcpOptions.val[dhcpMessageType]; return 0;}void classIDsetup(){ struct utsname sname; if ( uname(&sname) ) syslog(LOG_ERR,"classIDsetup: uname: %m\n"); DhcpIface.class_len=snprintf(DhcpIface.class_id,CLASS_ID_MAX_LEN, "%s %s %s",sname.sysname,sname.release,sname.machine);}void clientIDsetup(){ unsigned char *c = DhcpIface.client_id; *c++ = dhcpClientIdentifier; if (ClientID) { *c++ = ClientID_len + 1; /* 1 for the field below */ *c++ = 0; /* type: string */ memcpy(c,ClientID,ClientID_len); DhcpIface.client_len = ClientID_len + 3; return; } *c++ = ETH_ALEN + 1; /* length: 6 (MAC Addr) + 1 (# field) */ *c++ = ARPHRD_ETHER; /* type: Ethernet address */ memcpy(c,ClientHwAddr,ETH_ALEN); DhcpIface.client_len = ETH_ALEN + 3;}void releaseDhcpOptions(){ register int i; for (i=1;i<256;i++) if (DhcpOptions.val[i]) free(DhcpOptions.val[i]); memset(&DhcpOptions,0,sizeof(dhcpOptions));}/* Subtract the `struct timeval' values X and Y, storing the result in RESULT. Return 1 if the difference is negative, otherwise 0. */static int timeval_subtract(result,x,y)struct timeval *result,*x,*y;{ /* Perform the carry for the later subtraction by updating Y. */ if (x->tv_usec < y->tv_usec) { int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; y->tv_usec -= 1000000 * nsec; y->tv_sec += nsec; } if (x->tv_usec - y->tv_usec > 1000000) { int nsec = (x->tv_usec - y->tv_usec) / 1000000; y->tv_usec += 1000000 * nsec; y->tv_sec -= nsec; } /* Compute the time remaining to wait. `tv_usec' is certainly positive. */ result->tv_sec = x->tv_sec - y->tv_sec; result->tv_usec = x->tv_usec - y->tv_usec; /* Return 1 if result is negative. */ return x->tv_sec < y->tv_sec;}int dhcpSendAndRecv(xid,msg,buildUdpIpMsg)unsigned xid,msg;void (*buildUdpIpMsg)(unsigned);{ struct sockaddr addr; struct timeval begin, current, diff; int i,len,timeout=0; socklen_t addrLength; char foobuf[512]; const struct udphdr *udpRecv; int j=DHCP_INITIAL_RTO/2; do { do { j+=j; if (j > DHCP_MAX_RTO) j = DHCP_MAX_RTO; memset(&addr,0,sizeof(struct sockaddr)); memcpy(addr.sa_data,IfNameExt,IfNameExt_len); buildUdpIpMsg(xid); len = sizeof(struct packed_ether_header)+sizeof(udpiphdr)+sizeof(dhcpMessage); if (sendto(dhcpSocket, &UdpIpMsgSend, len, 0, &addr,sizeof(struct sockaddr)) == -1) { perror("sendto: %m\n"); return (-1); } gettimeofday(&begin, NULL); i=random(); } while ( waitfd(dhcpSocket,j+i%200000) ); do { struct ip ipRecv_local; char *tmp_ip; memset(&UdpIpMsgRecv,0,sizeof(udpipMessage)); addrLength=sizeof(struct sockaddr); len=recvfrom(dhcpSocket,&UdpIpMsgRecv,sizeof(udpipMessage),0,(struct sockaddr *)&addr,&addrLength); if (len == -1) { perror("recvfrom: %m\n"); return (-1); } gettimeofday(¤t, NULL); timeval_subtract(&diff, ¤t, &begin); timeout = j - diff.tv_sec*1000000 - diff.tv_usec + random()%200000; if (UdpIpMsgRecv.ethhdr.ether_type != htons(ETHERTYPE_IP)) continue; tmp_ip = UdpIpMsgRecv.udpipmsg; for (i=0;i<sizeof(struct ip)-2;i+=2) if ((UdpIpMsgRecv.udpipmsg[i] == 0x45) && (UdpIpMsgRecv.udpipmsg[i+1] == 0x00)) { tmp_ip=&(UdpIpMsgRecv.udpipmsg[i]); break; } memcpy(&ipRecv_local,((struct udpiphdr *)tmp_ip)->ip,sizeof(struct ip)); udpRecv=(struct udphdr *)((char*)(((struct udpiphdr*)tmp_ip)->ip)+sizeof(struct ip)); if (ipRecv_local.ip_p != IPPROTO_UDP) continue; len-=sizeof(struct packed_ether_header); i=(int )ntohs(ipRecv_local.ip_len); if (len < i) { if (DebugFlag) printf("corrupted IP packet of size=%d and ip_len=%d discarded\n", len, i); continue; } len=i-(ipRecv_local.ip_hl<<2); i=(int )ntohs(udpRecv->uh_ulen); if (len < i) { if (DebugFlag) printf("corrupted UDP msg of size=%d and uh_ulen=%d discarded\n", len, i); continue; } if (DoCheckSum) { len=udpipchk((udpiphdr *)tmp_ip); if (len) { if (DebugFlag) switch (len) { case -1: syslog(LOG_DEBUG, "corrupted IP packet with ip_len=%d discarded\n", (int )ntohs(ipRecv_local.ip_len)); break; case -2: syslog(LOG_DEBUG, "corrupted UDP msg with uh_ulen=%d discarded\n", (int )ntohs(udpRecv->uh_ulen)); break; } continue; } } DhcpMsgRecv=(dhcpMessage *)&tmp_ip[(ipRecv_local.ip_hl<<2)+sizeof(struct udphdr)]; if (DhcpMsgRecv->xid != xid) continue; if (DhcpMsgRecv->htype != ARPHRD_ETHER) { if (DebugFlag) printf("wrong msg htype 0x%X discarded\n",DhcpMsgRecv->htype); continue; } if (DhcpMsgRecv->op != DHCP_BOOTREPLY) continue; while (udpFooSocket > 0 && recvfrom(udpFooSocket,(void *)foobuf,sizeof(foobuf),0,NULL,NULL) != -1); if (parseDhcpMsg() == msg) return 0; if (DhcpOptions.val[dhcpMessageType]) if (*(unsigned char *)DhcpOptions.val[dhcpMessageType] == DHCP_NAK) { if (DhcpOptions.val[dhcpMsg]) syslog(LOG_ERR, "DHCP_NAK server response received: %s\n", (char *)DhcpOptions.val[dhcpMsg]); else syslog(LOG_ERR, "DHCP_NAK server response received\n"); return 1; } } while ( timeout > 0 && waitfd(dhcpSocket, timeout) == 0 ); } while ( 1 ); return 1;}void *Start(){ int flags; int o = 1; unsigned i=0; struct ifreq ifr; struct sockaddr_pkt sap; struct sockaddr_in clientAddr; memset(&ifr,0,sizeof(struct ifreq)); memcpy(ifr.ifr_name,IfNameExt,IfNameExt_len); dhcpSocket = socket(PF_PACKET,SOCK_PACKET,htons(ETH_P_ALL)); if (dhcpSocket == -1 || (flags = fcntl(dhcpSocket, F_GETFL, 0)) == -1 || fcntl(dhcpSocket, F_SETFL, flags | O_NONBLOCK) == -1) { syslog(LOG_ERR,"Start: socket: %m\n"); exit(1); } if (ioctl(dhcpSocket,SIOCGIFHWADDR,&ifr)) { syslog(LOG_ERR,"Start: ioctl SIOCGIFHWADDR: %m\n"); exit(1); } if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { syslog(LOG_ERR,"Start: interface %s is not Ethernet or 802.2 Token Ring\n",ifr.ifr_name); exit(1); } if (setsockopt(dhcpSocket,SOL_SOCKET,SO_BROADCAST,&o,sizeof(o)) == -1) { syslog(LOG_ERR,"Start: setsockopt: %m\n"); exit(1); } if (ioctl(dhcpSocket,SIOCGIFFLAGS,&ifr)) { syslog(LOG_ERR,"Start: ioctl SIOCGIFFLAGS: %m\n"); exit(1); } saved_if_flags = ifr.ifr_flags;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -