--- /home/thunderboltFS/mike/usr/local/src/nagios-plugins-1.4.14/plugins-root/check_dhcp.c.old 2010-03-05 11:26:26.000000000 -0600 +++ /home/thunderboltFS/mike/usr/local/src/nagios-plugins-1.4.14/plugins-root/check_dhcp.c 2010-03-10 17:36:02.313724052 -0600 @@ -291,6 +291,9 @@ /* wait for a DHCPOFFER packet */ get_dhcp_offer(dhcp_socket); + /* send DHCPREQUEST packet */ + send_dhcp_request(dhcp_socket); + /* close socket we created */ close_dhcp_socket(dhcp_socket); @@ -411,7 +414,7 @@ print_hardware_address(client_hardware_address); return OK; - } + } /* determines IP address of the client interface */ int get_ip_address(int sock,char *interface_name){ @@ -444,7 +447,7 @@ int send_dhcp_discover(int sock){ dhcp_packet discover_packet; struct sockaddr_in sockaddr_broadcast; - unsigned short opts; + unsigned short opts; /* clear the packet data structure */ @@ -490,7 +493,7 @@ discover_packet.options[2]='\x53'; discover_packet.options[3]='\x63'; - opts = 4; + 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 */ @@ -502,7 +505,7 @@ 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 */ @@ -513,8 +516,8 @@ 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_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)); @@ -522,10 +525,10 @@ 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)); + printf("DHCPDISCOVER ciaddr: %s\n",inet_ntoa(discover_packet.ciaddr)); + printf("DHCPDISCOVER yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr)); + printf("DHCPDISCOVER siaddr: %s\n",inet_ntoa(discover_packet.siaddr)); + printf("DHCPDISCOVER giaddr: %s\n",inet_ntoa(discover_packet.giaddr)); } /* send the DHCPDISCOVER packet out */ @@ -535,9 +538,110 @@ printf("\n\n"); return OK; - } + } + +/* sends a DHCPREQUEST broadcast message in an attempt to allow DHCP servers to drop any OFFER reservations and return those IPs to their free pools */ +int send_dhcp_request(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. We won't use the address so + * we don't care about high entropy here. time(2) is good enough. + */ + 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; + + /* + * 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++]=DHCPREQUEST; + + /* 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); + } + + /* Set the server identifier to our own address, so that no other DHCP server will match */ + discover_packet.options[opts++]=DHCP_OPTION_SERVER_IDENTIFIER; + discover_packet.options[opts++]='\x04'; + memcpy(&discover_packet.options[opts],&discover_packet.ciaddr,sizeof(discover_packet.ciaddr)); + + 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 DHCPREQUEST 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(_("DHCPREQUEST to %s port %d\n"),inet_ntoa(sockaddr_broadcast.sin_addr),ntohs(sockaddr_broadcast.sin_port)); + printf("DHCPREQUEST XID: %u (0x%X)\n",ntohl(discover_packet.xid),ntohl(discover_packet.xid)); + printf("DHCPREQUEST ciaddr: %s\n",inet_ntoa(discover_packet.ciaddr)); + printf("DHCPREQUEST yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr)); + printf("DHCPREQUEST siaddr: %s\n",inet_ntoa(discover_packet.siaddr)); + printf("DHCPREQUEST giaddr: %s\n",inet_ntoa(discover_packet.giaddr)); + } + /* send the DHCPREQUEST packet out */ + send_dhcp_packet(&discover_packet,sizeof(discover_packet),sock,&sockaddr_broadcast); + + if(verbose) + printf("\n\n"); + + return OK; + } /* waits for a DHCPOFFER message from one or more DHCP servers */ @@ -604,7 +708,7 @@ printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"),ntohl(offer_packet.xid),packet_xid); continue; - } + } /* check hardware address */ result=OK; @@ -626,7 +730,7 @@ printf(_("DHCPOFFER hardware address did not match our own - ignoring packet\n")); continue; - } + } if(verbose){ printf("DHCPOFFER ciaddr: %s\n",inet_ntoa(offer_packet.ciaddr)); @@ -638,7 +742,7 @@ add_dhcp_offer(source.sin_addr,&offer_packet); valid_responses++; - } + } if(verbose){ printf(_("Total responses seen on the wire: %d\n"),responses); @@ -646,7 +750,7 @@ } return OK; - } + } @@ -663,7 +767,7 @@ return ERROR; return OK; - } + } @@ -713,7 +817,7 @@ printf("errno: (%d) -> %s\n",errno,strerror(errno)); } return ERROR; - } + } else{ if(verbose){ printf(_("receive_dhcp_packet() result: %d\n"),recv_result); @@ -722,11 +826,11 @@ memcpy(address,&source_address,sizeof(source_address)); return OK; - } - } + } + } return OK; - } + } /* creates a socket for DHCP communication */ @@ -749,7 +853,7 @@ if(sock<0){ printf(_("Error: Could not create socket!\n")); exit(STATE_UNKNOWN); - } + } if(verbose) printf("DHCP socket: %d\n",sock); @@ -759,13 +863,13 @@ if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){ printf(_("Error: Could not set reuse address option on DHCP socket!\n")); exit(STATE_UNKNOWN); - } + } /* set the broadcast option - we need this to listen to DHCP broadcast messages */ if(!unicast && setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&flag,sizeof flag)<0){ printf(_("Error: Could not set broadcast option on DHCP socket!\n")); exit(STATE_UNKNOWN); - } + } /* bind socket to interface */ #if defined(__linux__) @@ -774,7 +878,7 @@ if(setsockopt(sock,SOL_SOCKET,SO_BINDTODEVICE,(char *)&interface,sizeof(interface))<0){ printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"),network_interface_name); exit(STATE_UNKNOWN); - } + } #else strncpy(interface.ifr_name,network_interface_name,IFNAMSIZ-1); @@ -785,10 +889,10 @@ if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){ printf(_("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n"),DHCP_CLIENT_PORT); exit(STATE_UNKNOWN); - } + } return sock; - } + } /* closes DHCP socket */ @@ -820,7 +924,7 @@ printf(_("Requested server address: %s\n"),inet_ntoa(new_server->server_address)); return OK; - } + } @@ -924,7 +1028,7 @@ dhcp_offer_list=new_offer; return OK; - } + } /* frees memory allocated to DHCP OFFER list */ @@ -938,7 +1042,7 @@ } return OK; - } + } /* frees memory allocated to requested server list */ @@ -949,10 +1053,10 @@ for(this_server=requested_server_list;this_server!=NULL;this_server=next_server){ next_server=this_server->next; free(this_server); - } + } return OK; - } + } /* gets state and plugin output to return */ @@ -993,11 +1097,11 @@ requested_responses++; temp_server->answered=TRUE; } - } - } - } + } + } + } - } + } /* else check and see if we got our requested address from any server */ else{ @@ -1011,8 +1115,8 @@ /* see if we got the address we requested */ if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address))) received_requested_address=TRUE; - } - } + } + } result=STATE_OK; if(valid_responses==0) @@ -1037,7 +1141,7 @@ if(dhcp_offer_list==NULL){ printf(_("No DHCPOFFERs were received.\n")); return result; - } + } printf(_("Received %d DHCPOFFER(s)"),valid_responses); @@ -1056,7 +1160,7 @@ printf(".\n"); return result; - } + } /* process command-line arguments */ @@ -1076,7 +1180,7 @@ } return validate_arguments(); - } + } @@ -1181,17 +1285,17 @@ default: break; - } - } + } + } return i; - } + } int validate_arguments(void){ return OK; - } + } #if defined(__sun__) || defined(__solaris__) || defined(__hpux__)