--- relay/dhcrelay.c.org 2007-02-14 17:41:23.000000000 -0500 +++ relay/dhcrelay.c 2007-11-25 14:28:24.000000000 -0500 @@ -53,6 +53,7 @@ char *tlname; const char *path_dhcrelay_pid = _PATH_DHCRELAY_PID; +const char *path_dhcrelay_hosts = NULL; int bogus_agent_drops = 0; /* Packets dropped because agent option field was specified and we're not relaying @@ -98,11 +99,19 @@ struct sockaddr_in to; } *servers; +struct hosts_list { + struct hosts_list *next; + unsigned char MACaddress[17]; /* Including : */ + struct server_list *servers; +} *hosts; + static char copyright [] = "Copyright 2004-2007 Internet Systems Consortium."; static char arr [] = "All rights reserved."; static char message [] = "Internet Systems Consortium DHCP Relay Agent"; static char url [] = "For info, please visit http://www.isc.org/sw/dhcp/"; +isc_result_t readhosts (); + int main (argc, argv, envp) int argc; char **argv, **envp; @@ -115,6 +124,7 @@ int quiet = 0; isc_result_t status; char *s; + int no_dhcrelay_hosts = 0; /* Make sure that file descriptors 0 (stdin), 1, (stdout), and 2 (stderr) are open. To do this, we assume that when we @@ -186,7 +196,12 @@ max_hop_count= hcount; else usage (); - } else if (!strcmp (argv [i], "-A")) { + } else if (!strcmp (argv [i], "-ch")) { + if (++i == argc) + usage (); + path_dhcrelay_hosts = argv [i]; + no_dhcrelay_hosts = 1; + } else if (!strcmp (argv [i], "-A")) { if (++i == argc) usage (); dhcp_max_agent_option_packet_length = atoi (argv [i]); @@ -268,6 +283,10 @@ usage (); } + /* Read the dhcrelay.hosts file... */ + if (readhosts () != ISC_R_SUCCESS) + log_fatal ("Hosts file errors encountered -- exiting"); + /* Set up the server sockaddrs. */ for (sp = servers; sp; sp = sp -> next) { sp -> to.sin_port = local_port; @@ -337,7 +356,8 @@ struct hardware *hfrom; { struct server_list *sp; - struct sockaddr_in to; + struct hosts_list *hp = NULL; + struct sockaddr_in to; struct interface_info *out; struct hardware hto, *htop; @@ -440,7 +460,29 @@ /* Otherwise, it's a BOOTREQUEST, so forward it to all the servers. */ - for (sp = servers; sp; sp = sp -> next) { + + /* Check for entry in hosts file first */ + for (hp = hosts; hp; hp = hp -> next) { + /*log_debug("Comparing BOOTREQUEST MAC %s with %s\n", print_hw_addr (packet -> htype, + packet -> hlen, packet -> chaddr), hp->MACaddress); */ + + if (strcasestr(hp->MACaddress, print_hw_addr (packet -> htype, + packet -> hlen, packet -> chaddr))) { + /* log_debug("MAC address matches\n"); */ + + for (sp = hp->servers; sp; sp = sp -> next) { + /* log_debug(" Server: %s\n", inet_ntoa (sp -> to.sin_addr)); */ + } + sp = hp->servers; + break; + } + else { + sp = servers; + } + } + + /*for (sp = servers; sp; sp = sp -> next) { */ + for (; sp; sp = sp -> next) { if (send_packet ((fallback_interface ? fallback_interface : interfaces), (struct packet *)0, @@ -464,7 +506,7 @@ "interface] [-q] [-a]\n ", "[-c count] [-A length] ", "[-m append|replace|forward|discard]\n", - " [server1 [... serverN]]"); + " [-ch hosts-file] [server1 [... serverN]]"); } int write_lease (lease) @@ -915,3 +957,109 @@ return length; } + +/* Read in dhcrelay.hosts file */ +isc_result_t readhosts () +{ + FILE *hostsfile; + char buffer[255]; + char *tokenize = NULL; + char *comment = NULL; + struct hosts_list *hp = NULL; + struct server_list *sp = NULL; + + if (!path_dhcrelay_hosts) + return 1; + + log_debug ("\nLoading hosts file %s\n",path_dhcrelay_hosts); + + hostsfile = fopen(path_dhcrelay_hosts, "r"); + if (!hostsfile) { + log_fatal ("Can't open %s: %m", path_dhcrelay_hosts); + return 1; + } + + while(fgets(buffer,255,hostsfile)) { + comment = strchr(buffer, '#'); + if (comment) { + *comment = '\0'; + } + + tokenize = strtok(buffer," \t"); + if (!tokenize) + continue; + + if (strlen(tokenize) <= 1) + continue; + + if (strlen(tokenize) != 17) { + log_debug (" Invalid MAC address detected. Skipping line: %s.\n", buffer); + continue; + } + + /* Allocate memory for MAC list structure */ + hp = ((struct hosts_list *) malloc (sizeof *hp)); + if (!hp) { + log_fatal("no memory for hosts list\n"); + } + + /* Add a structure */ + hp->next = hosts; + hosts = hp; + strncpy(hp->MACaddress, tokenize, 17); + + /* Add server(s) to structure */ + while (tokenize != NULL) { + tokenize = strtok(NULL," \t"); + + if (tokenize == NULL) + continue; + + struct hostent *he; + struct in_addr ia, *iap = (struct in_addr *)0; + if (inet_aton (tokenize, &ia)) { + iap = &ia; + } else { + he = gethostbyname (tokenize); + if (!he) { + log_error ("%s: host unknown", + tokenize); + } else { + iap = ((struct in_addr *) + he -> h_addr_list [0]); + } + } + + if (iap) { + sp = ((struct server_list *) + dmalloc (sizeof *sp, MDL)); + if (!sp) + log_fatal ("no memory for server.\n"); + sp -> next = hp->servers; + hp->servers = sp; + memcpy (&sp -> to.sin_addr, + iap, sizeof *iap); + } + } + + /* Set up the server sockaddrs. */ + for (sp = hp->servers; sp; sp = sp -> next) { + sp -> to.sin_port = local_port; + sp -> to.sin_family = AF_INET; +#ifdef HAVE_SA_LEN + sp -> to.sin_len = sizeof sp -> to; +#endif + } + } + + /* + for (hp = hosts; hp; hp = hp -> next) { + printf("MAC: %s\n",hp->MACaddress); + for (sp = hp->servers; sp; sp = sp -> next) { + printf(" Server: %s\n", inet_ntoa (sp -> to.sin_addr)); + } + }*/ + + return 0; +} +