/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */ int send_dhcp_discover(int sock){ dhcp_packet discover_packet; struct sockaddr_in sockaddr_broadcast; unsigned short opts; /* clear the packet data structure */ bzero(&discover_packet,sizeof(discover_packet)); /* boot request flag (backward compatible with BOOTP servers) */ discover_packet.op=BOOTREQUEST; /* hardware address type */ discover_packet.htype=ETHERNET_HARDWARE_ADDRESS; /* length of our hardware address */ discover_packet.hlen=ETHERNET_HARDWARE_ADDRESS_LENGTH; /* * transaction ID is supposed to be random. * This allows for proper randomness if the system supports it, and fallback to * srand & random if not. */ int randfd = open("/dev/urandom", O_RDONLY); if (randfd > 2 && read(randfd, (char *)&packet_xid, sizeof(uint32_t)) >= 0) { /* no-op as we have successfully filled packet_xid */ } else { /* fallback bad rand */ srand(time(NULL)); packet_xid=random(); } if (randfd > 2) close(randfd); discover_packet.xid=htonl(packet_xid); /**** WHAT THE HECK IS UP WITH THIS?!? IF I DON'T MAKE THIS CALL, ONLY ONE SERVER RESPONSE IS PROCESSED!!!! ****/ /* downright bizzarre... */ ntohl(discover_packet.xid); /*discover_packet.secs=htons(65535);*/ discover_packet.secs=0xFF; /* * server needs to know if it should broadcast or unicast its response: * 0x8000L == 32768 == 1 << 15 == broadcast, 0 == unicast */ discover_packet.flags = unicast ? 0 : htons(DHCP_BROADCAST_FLAG); /* our hardware address */ memcpy(discover_packet.chaddr,client_hardware_address,ETHERNET_HARDWARE_ADDRESS_LENGTH); /* first four bytes of options field is magic cookie (as per RFC 2132) */ discover_packet.options[0]='\x63'; discover_packet.options[1]='\x82'; discover_packet.options[2]='\x53'; discover_packet.options[3]='\x63'; opts = 4; /* DHCP message type is embedded in options field */ discover_packet.options[opts++]=DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */ discover_packet.options[opts++]='\x01'; /* DHCP message option length in bytes */ discover_packet.options[opts++]=DHCPDISCOVER; /* the IP address we're requesting */ if(request_specific_address==TRUE){ discover_packet.options[opts++]=DHCP_OPTION_REQUESTED_ADDRESS; discover_packet.options[opts++]='\x04'; memcpy(&discover_packet.options[opts],&requested_address,sizeof(requested_address)); opts += sizeof(requested_address); } discover_packet.options[opts++]=DHCP_OPTION_END; /* unicast fields */ if(unicast) discover_packet.giaddr.s_addr = my_ip.s_addr; /* see RFC 1542, 4.1.1 */ discover_packet.hops = unicast ? 1 : 0; /* send the DHCPDISCOVER packet to broadcast address */ sockaddr_broadcast.sin_family=AF_INET; sockaddr_broadcast.sin_port=htons(DHCP_SERVER_PORT); sockaddr_broadcast.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST; bzero(&sockaddr_broadcast.sin_zero,sizeof(sockaddr_broadcast.sin_zero)); if(verbose){ printf(_("DHCPDISCOVER to %s port %d\n"),inet_ntoa(sockaddr_broadcast.sin_addr),ntohs(sockaddr_broadcast.sin_port)); printf("DHCPDISCOVER XID: %u (0x%X)\n",ntohl(discover_packet.xid),ntohl(discover_packet.xid)); printf("DHCDISCOVER ciaddr: %s\n",inet_ntoa(discover_packet.ciaddr)); printf("DHCDISCOVER yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr)); printf("DHCDISCOVER siaddr: %s\n",inet_ntoa(discover_packet.siaddr)); printf("DHCDISCOVER giaddr: %s\n",inet_ntoa(discover_packet.giaddr)); } /* send the DHCPDISCOVER packet out */ send_dhcp_packet(&discover_packet,sizeof(discover_packet),sock,&sockaddr_broadcast); if(verbose) printf("\n\n"); return OK; }
/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */ int send_dhcp_discover(int sock){ dhcp_packet discover_packet; struct sockaddr_in sockaddr_broadcast; /* clear the packet data structure */ bzero(&discover_packet,sizeof(discover_packet)); /* boot request flag (backward compatible with BOOTP servers) */ discover_packet.op=BOOTREQUEST; /* hardware address type */ discover_packet.htype=ETHERNET_HARDWARE_ADDRESS; /* length of our hardware address */ discover_packet.hlen=ETHERNET_HARDWARE_ADDRESS_LENGTH; discover_packet.hops=0; /* transaction id is supposed to be random */ srand(time(NULL)); packet_xid=random(); discover_packet.xid=htonl(packet_xid); /**** WHAT THE HECK IS UP WITH THIS?!? IF I DON'T MAKE THIS CALL, ONLY ONE SERVER RESPONSE IS PROCESSED!!!! ****/ /* downright bizzarre... */ ntohl(discover_packet.xid); /*discover_packet.secs=htons(65535);*/ discover_packet.secs=0xFF; /* tell server it should broadcast its response */ discover_packet.flags=htons(DHCP_BROADCAST_FLAG); /* our hardware address */ memcpy(discover_packet.chaddr,client_hardware_address,ETHERNET_HARDWARE_ADDRESS_LENGTH); /* first four bytes of options field is magic cookie (as per RFC 2132) */ discover_packet.options[0]='\x63'; discover_packet.options[1]='\x82'; discover_packet.options[2]='\x53'; discover_packet.options[3]='\x63'; /* DHCP message type is embedded in options field */ discover_packet.options[4]=DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */ discover_packet.options[5]='\x01'; /* DHCP message option length in bytes */ discover_packet.options[6]=DHCPDISCOVER; /* the IP address we're requesting */ if(request_specific_address==TRUE){ discover_packet.options[7]=DHCP_OPTION_REQUESTED_ADDRESS; discover_packet.options[8]='\x04'; memcpy(&discover_packet.options[9],&requested_address,sizeof(requested_address)); } /* send the DHCPDISCOVER packet to broadcast address */ sockaddr_broadcast.sin_family=AF_INET; sockaddr_broadcast.sin_port=htons(DHCP_SERVER_PORT); sockaddr_broadcast.sin_addr.s_addr=INADDR_BROADCAST; bzero(&sockaddr_broadcast.sin_zero,sizeof(sockaddr_broadcast.sin_zero)); #ifdef DEBUG printf("DHCPDISCOVER to %s port %d\n",inet_ntoa(sockaddr_broadcast.sin_addr),ntohs(sockaddr_broadcast.sin_port)); printf("DHCPDISCOVER XID: %lu (0x%X)\n",ntohl(discover_packet.xid),ntohl(discover_packet.xid)); printf("DHCDISCOVER ciaddr: %s\n",inet_ntoa(discover_packet.ciaddr)); printf("DHCDISCOVER yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr)); printf("DHCDISCOVER siaddr: %s\n",inet_ntoa(discover_packet.siaddr)); printf("DHCDISCOVER giaddr: %s\n",inet_ntoa(discover_packet.giaddr)); #endif /* send the DHCPDISCOVER packet out */ send_dhcp_packet(&discover_packet,sizeof(discover_packet),sock,&sockaddr_broadcast); #ifdef DEBUG printf("\n\n"); #endif return OK; }