int arpCheck() { arpMessage ArpMsgSend,ArpMsgRecv; #ifdef OLD_LINUX_VERSION struct sockaddr addr; int j; #endif int i=0; memset(&ArpMsgSend,0,sizeof(arpMessage)); memcpy(ArpMsgSend.ethhdr.ether_dhost,MAC_BCAST_ADDR,ETH_ALEN); memcpy(ArpMsgSend.ethhdr.ether_shost,ClientHwAddr,ETH_ALEN); ArpMsgSend.ethhdr.ether_type = htons(ETHERTYPE_ARP); ArpMsgSend.htype = htons(ARPHRD_ETHER); ArpMsgSend.ptype = htons(ETHERTYPE_IP); ArpMsgSend.hlen = ETH_ALEN; ArpMsgSend.plen = 4; ArpMsgSend.operation = htons(ARPOP_REQUEST); memcpy(ArpMsgSend.sHaddr,ClientHwAddr,ETH_ALEN); memcpy(&ArpMsgSend.tInaddr,&DhcpIface.ciaddr,4); DebugSyslog(LOG_DEBUG, "broadcasting ARPOP_REQUEST for %u.%u.%u.%u\n", ArpMsgSend.tInaddr[0],ArpMsgSend.tInaddr[1], ArpMsgSend.tInaddr[2],ArpMsgSend.tInaddr[3]); do { do { if ( i++ > 4 ) return 0; /* 5 probes */ #ifdef OLD_LINUX_VERSION memset(&addr,0,sizeof(struct sockaddr)); memcpy(addr.sa_data,IfName,IfName_len); if ( sendto(dhcpSocket,&ArpMsgSend,sizeof(arpMessage),0, &addr,sizeof(struct sockaddr)) == -1 ) #else if ( send(dhcpSocket,&ArpMsgSend,sizeof(arpMessage),0) == -1 ) #endif { syslog(LOG_ERR,"arpCheck: sendto: %m\n"); return -1; } } while ( peekfd(dhcpSocket,50000) ); /* 50 msec timeout */ do { if ( recv(dhcpSocket,&ArpMsgRecv,sizeof(arpMessage),0) == -1 ) { syslog(LOG_ERR,"arpCheck: recv: %m\n"); return -1; } if ( ArpMsgRecv.ethhdr.ether_type != htons(ETHERTYPE_ARP) ) continue; if ( ArpMsgRecv.operation == htons(ARPOP_REPLY) ) { DebugSyslog(LOG_DEBUG, "ARPOP_REPLY received from %u.%u.%u.%u for %u.%u.%u.%u\n", ArpMsgRecv.sInaddr[0],ArpMsgRecv.sInaddr[1], ArpMsgRecv.sInaddr[2],ArpMsgRecv.sInaddr[3], ArpMsgRecv.tInaddr[0],ArpMsgRecv.tInaddr[1], ArpMsgRecv.tInaddr[2],ArpMsgRecv.tInaddr[3]); } else continue; if ( memcmp(ArpMsgRecv.tHaddr,ClientHwAddr,ETH_ALEN) ) { DebugSyslog(LOG_DEBUG, "target hardware address mismatch: %02X.%02X.%02X.%02X.%02X.%02X received, %02X.%02X.%02X.%02X.%02X.%02X expected\n", ArpMsgRecv.tHaddr[0],ArpMsgRecv.tHaddr[1],ArpMsgRecv.tHaddr[2], ArpMsgRecv.tHaddr[3],ArpMsgRecv.tHaddr[4],ArpMsgRecv.tHaddr[5], ClientHwAddr[0],ClientHwAddr[1], ClientHwAddr[2],ClientHwAddr[3], ClientHwAddr[4],ClientHwAddr[5]); continue; } if ( memcmp(&ArpMsgRecv.sInaddr,&DhcpIface.ciaddr,4) ) { DebugSyslog(LOG_DEBUG, "sender IP address mismatch: %u.%u.%u.%u received, %u.%u.%u.%u expected\n", ArpMsgRecv.sInaddr[0],ArpMsgRecv.sInaddr[1],ArpMsgRecv.sInaddr[2],ArpMsgRecv.sInaddr[3], ((unsigned char *)&DhcpIface.ciaddr)[0], ((unsigned char *)&DhcpIface.ciaddr)[1], ((unsigned char *)&DhcpIface.ciaddr)[2], ((unsigned char *)&DhcpIface.ciaddr)[3]); continue; } return 1; } while ( peekfd(dhcpSocket,50000) == 0 ); } while ( 1 ); return 0; }
int parseDhcpMsgRecv() /* this routine parses dhcp message received */ { #ifdef DEBUG int i,j; #endif register u_char *p = DhcpMsgRecv->options+4; unsigned char *end = DhcpMsgRecv->options+sizeof(DhcpMsgRecv->options); while ( p < end ) switch ( *p ) { case endOption: goto swend; case padOption: p++; break; default: /* Handle a bug in the redhat 6.2 bootp server * which causes it to incorrectly pad the end option */ if ( ((p - DhcpMsgRecv->options)&1) && (p[1] == endOption) ) goto swend; if ( p[1] ) { 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: #ifdef DEBUG fprintf(stderr,"parseDhcpMsgRecv: %d options received:\n",DhcpOptions.num); for (i=1;i<255;i++) if ( DhcpOptions.val[i] ) switch ( i ) { case 1: /* subnet mask */ case 3: /* routers on subnet */ case 4: /* time servers */ case 5: /* name servers */ case 6: /* dns servers */ case 28:/* broadcast addr */ case 33:/* staticRoute */ case 41:/* NIS servers */ case 42:/* NTP servers */ case 50:/* dhcpRequestdIPaddr */ case 54:/* dhcpServerIdentifier */ for (j=0;j<DhcpOptions.len[i];j+=4) fprintf(stderr,"i=%-2d len=%-2d option = %u.%u.%u.%u\n", i,DhcpOptions.len[i], ((unsigned char *)DhcpOptions.val[i])[0+j], ((unsigned char *)DhcpOptions.val[i])[1+j], ((unsigned char *)DhcpOptions.val[i])[2+j], ((unsigned char *)DhcpOptions.val[i])[3+j]); break; case 2: /* time offset */ case 51:/* dhcpAddrLeaseTime */ case 57:/* dhcpMaxMsgSize */ case 58:/* dhcpT1value */ case 59:/* dhcpT2value */ fprintf(stderr,"i=%-2d len=%-2d option = %d\n", i,DhcpOptions.len[i], ntohl(*(int *)DhcpOptions.val[i])); break; case 23:/* defaultIPTTL */ case 29:/* performMaskdiscovery */ case 31:/* performRouterdiscovery */ case 53:/* dhcpMessageType */ fprintf(stderr,"i=%-2d len=%-2d option = %u\n", i,DhcpOptions.len[i],*(unsigned char *)DhcpOptions.val[i]); break; default: fprintf(stderr,"i=%-2d len=%-2d option = \"%s\"\n", i,DhcpOptions.len[i],(char *)DhcpOptions.val[i]); } fprintf(stderr,"\ DhcpMsgRecv->yiaddr = %u.%u.%u.%u\n\ DhcpMsgRecv->siaddr = %u.%u.%u.%u\n\ DhcpMsgRecv->giaddr = %u.%u.%u.%u\n\ DhcpMsgRecv->sname = \"%s\"\n\ ServerHardwareAddr = %02X.%02X.%02X.%02X.%02X.%02X\n", ((unsigned char *)&DhcpMsgRecv->yiaddr)[0], ((unsigned char *)&DhcpMsgRecv->yiaddr)[1], ((unsigned char *)&DhcpMsgRecv->yiaddr)[2], ((unsigned char *)&DhcpMsgRecv->yiaddr)[3], ((unsigned char *)&DhcpMsgRecv->siaddr)[0], ((unsigned char *)&DhcpMsgRecv->siaddr)[1], ((unsigned char *)&DhcpMsgRecv->siaddr)[2], ((unsigned char *)&DhcpMsgRecv->siaddr)[3], ((unsigned char *)&DhcpMsgRecv->giaddr)[0], ((unsigned char *)&DhcpMsgRecv->giaddr)[1], ((unsigned char *)&DhcpMsgRecv->giaddr)[2], ((unsigned char *)&DhcpMsgRecv->giaddr)[3], DhcpMsgRecv->sname, UdpIpMsgRecv.ethhdr.ether_shost[0], UdpIpMsgRecv.ethhdr.ether_shost[1], UdpIpMsgRecv.ethhdr.ether_shost[2], UdpIpMsgRecv.ethhdr.ether_shost[3], UdpIpMsgRecv.ethhdr.ether_shost[4], UdpIpMsgRecv.ethhdr.ether_shost[5]); #endif if ( ! DhcpMsgRecv->yiaddr ) DhcpMsgRecv->yiaddr=DhcpMsgSend->ciaddr; if ( ! DhcpOptions.val[dhcpServerIdentifier] ) /* did not get dhcpServerIdentifier */ { /* make it the same as IP address of the sender */ DhcpOptions.val[dhcpServerIdentifier] = malloc(4); memcpy(DhcpOptions.val[dhcpServerIdentifier],&ipRecv->ip_src.s_addr,4); DhcpOptions.len[dhcpServerIdentifier] = 4; DhcpOptions.num++; DebugSyslog(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]); } if ( ! DhcpOptions.val[dns] ) /* did not get DNS */ { /* make it the same as dhcpServerIdentifier */ DhcpOptions.val[dns] = malloc(4); memcpy(DhcpOptions.val[dns],DhcpOptions.val[dhcpServerIdentifier],4); DhcpOptions.len[dns] = 4; DhcpOptions.num++; DebugSyslog(LOG_DEBUG, "dns option is missing in DHCP server response. Assuming %u.%u.%u.%u\n", ((unsigned char *)DhcpOptions.val[dns])[0], ((unsigned char *)DhcpOptions.val[dns])[1], ((unsigned char *)DhcpOptions.val[dns])[2], ((unsigned char *)DhcpOptions.val[dns])[3]); } if ( ! DhcpOptions.val[subnetMask] ) /* did not get subnetMask */ { DhcpOptions.val[subnetMask] = malloc(4); ((unsigned char *)DhcpOptions.val[subnetMask])[0] = 255; if ( ((unsigned char *)&DhcpMsgRecv->yiaddr)[0] < 128 ) ((unsigned char *)DhcpOptions.val[subnetMask])[1] = 0; /* class A */ else { ((unsigned char *)DhcpOptions.val[subnetMask])[1] = 255; if ( ((unsigned char *)&DhcpMsgRecv->yiaddr)[0] < 192 ) ((unsigned char *)DhcpOptions.val[subnetMask])[2] = 0;/* class B */ else ((unsigned char *)DhcpOptions.val[subnetMask])[2] = 255;/* class C */ } ((unsigned char *)DhcpOptions.val[subnetMask])[3] = 0; DhcpOptions.len[subnetMask] = 4; DhcpOptions.num++; DebugSyslog(LOG_DEBUG, "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]); } if ( ! DhcpOptions.val[broadcastAddr] ) /* did not get 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++; DebugSyslog(LOG_DEBUG, "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 0 if ( ! DhcpOptions.val[routersOnSubnet] ) { DhcpOptions.val[routersOnSubnet] = malloc(4); if ( DhcpMsgRecv->giaddr ) memcpy(DhcpOptions.val[routersOnSubnet],&DhcpMsgRecv->giaddr,4); else memcpy(DhcpOptions.val[routersOnSubnet],DhcpOptions.val[dhcpServerIdentifier],4); DhcpOptions.len[routersOnSubnet] = 4; DhcpOptions.num++; DebugSyslog(LOG_DEBUG, "routersOnSubnet option is missing in DHCP server response. Assuming %u.%u.%u.%u\n", ((unsigned char *)DhcpOptions.val[routersOnSubnet])[0], ((unsigned char *)DhcpOptions.val[routersOnSubnet])[1], ((unsigned char *)DhcpOptions.val[routersOnSubnet])[2], ((unsigned char *)DhcpOptions.val[routersOnSubnet])[3]); } #endif if ( DhcpOptions.val[dhcpIPaddrLeaseTime] ) { if ( *(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime] == 0 ) { memcpy(DhcpOptions.val[dhcpIPaddrLeaseTime],&nleaseTime,4); DebugSyslog(LOG_DEBUG, "dhcpIPaddrLeaseTime=0 in DHCP server response. Assuming %u sec\n", LeaseTime); } } else /* did not get dhcpIPaddrLeaseTime */ { DhcpOptions.val[dhcpIPaddrLeaseTime] = malloc(4); memcpy(DhcpOptions.val[dhcpIPaddrLeaseTime],&nleaseTime,4); DhcpOptions.len[dhcpIPaddrLeaseTime] = 4; DhcpOptions.num++; DebugSyslog(LOG_DEBUG,"dhcpIPaddrLeaseTime option is missing in DHCP server response. Assuming %u sec\n",LeaseTime); } if ( ! DhcpOptions.val[dhcpT1value] ) /* did not get T1 */ { int t1 = htonl((unsigned )(0.5*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]))); DhcpOptions.val[dhcpT1value] = malloc(4); memcpy(DhcpOptions.val[dhcpT1value],&t1,4); DhcpOptions.len[dhcpT1value] = 4; DhcpOptions.num++; } if ( ! DhcpOptions.val[dhcpT2value] ) /* did not get T2 */ { int t2 = htonl((unsigned )(0.875*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]))); DhcpOptions.val[dhcpT2value] = malloc(4); memcpy(DhcpOptions.val[dhcpT2value],&t2,4); DhcpOptions.len[dhcpT2value] = 4; DhcpOptions.num++; } if ( DhcpOptions.val[dhcpMessageType] ) return *(unsigned char *)DhcpOptions.val[dhcpMessageType]; return 0; }