diff options
Diffstat (limited to 'workspace/networkDiscovery/dhcpcd/dhcp.c')
| -rw-r--r-- | workspace/networkDiscovery/dhcpcd/dhcp.c | 933 |
1 files changed, 0 insertions, 933 deletions
diff --git a/workspace/networkDiscovery/dhcpcd/dhcp.c b/workspace/networkDiscovery/dhcpcd/dhcp.c deleted file mode 100644 index f625e8f..0000000 --- a/workspace/networkDiscovery/dhcpcd/dhcp.c +++ /dev/null @@ -1,933 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples <roy@marples.name> - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/time.h> - -#include <netinet/in.h> -#include <net/if_arp.h> - -#include <arpa/inet.h> - -#include <errno.h> -#include <limits.h> -#include <math.h> -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -#include "config.h" - -#include "common.h" -#include "dhcpcd.h" -#include "dhcp.h" -#include "interface.h" -#include "logger.h" -#include "socket.h" - -#ifndef STAILQ_CONCAT -#define STAILQ_CONCAT(head1, head2) do { \ - if (!STAILQ_EMPTY((head2))) { \ - *(head1)->stqh_last = (head2)->stqh_first; \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_INIT((head2)); \ - } \ -} while (0) -#endif - -typedef struct message { - int value; - const char *name; -} dhcp_message_t; - -static dhcp_message_t dhcp_messages[] = { - { DHCP_DISCOVER, "DHCP_DISCOVER" }, - { DHCP_OFFER, "DHCP_OFFER" }, - { DHCP_REQUEST, "DHCP_REQUEST" }, - { DHCP_DECLINE, "DHCP_DECLINE" }, - { DHCP_ACK, "DHCP_ACK" }, - { DHCP_NAK, "DHCP_NAK" }, - { DHCP_RELEASE, "DHCP_RELEASE" }, - { DHCP_INFORM, "DHCP_INFORM" }, - { -1, NULL } -}; - -static const char *dhcp_message (int type) -{ - dhcp_message_t *d; - for (d = dhcp_messages; d->name; d++) - if (d->value == type) - return (d->name); - - return (NULL); -} - -ssize_t send_message (const interface_t *iface, const dhcp_t *dhcp, - uint32_t xid, char type, const options_t *options) -{ - struct udp_dhcp_packet *packet; - dhcpmessage_t *message; - unsigned char *m; - unsigned char *p; - unsigned char *n_params = NULL; - size_t l; - struct in_addr from; - struct in_addr to; - time_t up = uptime() - iface->start_uptime; - uint32_t ul; - uint16_t sz; - size_t message_length; - ssize_t retval; - - if (!iface || !options || !dhcp) - return -1; - - memset (&from, 0, sizeof (from)); - memset (&to, 0, sizeof (to)); - - if (type == DHCP_RELEASE) - to.s_addr = dhcp->serveraddress.s_addr; - - message = xzalloc (sizeof (*message)); - m = (unsigned char *) message; - p = (unsigned char *) &message->options; - - if ((type == DHCP_INFORM || - type == DHCP_RELEASE || - type == DHCP_REQUEST) && - ! IN_LINKLOCAL (ntohl (iface->previous_address.s_addr))) - { - message->ciaddr = iface->previous_address.s_addr; - from.s_addr = iface->previous_address.s_addr; - - /* Just incase we haven't actually configured the address yet */ - if (type == DHCP_INFORM && iface->previous_address.s_addr == 0) - message->ciaddr = dhcp->address.s_addr; - - /* Zero the address if we're currently on a different subnet */ - if (type == DHCP_REQUEST && - iface->previous_netmask.s_addr != dhcp->netmask.s_addr) - message->ciaddr = from.s_addr = 0; - - if (from.s_addr != 0) - to.s_addr = dhcp->serveraddress.s_addr; - } - - message->op = DHCP_BOOTREQUEST; - message->hwtype = iface->family; - switch (iface->family) { - case ARPHRD_ETHER: - case ARPHRD_IEEE802: - message->hwlen = ETHER_ADDR_LEN; - memcpy (&message->chaddr, &iface->hwaddr, - ETHER_ADDR_LEN); - break; - case ARPHRD_IEEE1394: - case ARPHRD_INFINIBAND: - message->hwlen = 0; - if (message->ciaddr == 0) - message->flags = htons (BROADCAST_FLAG); - break; - default: - logger (LOG_ERR, "dhcp: unknown hardware type %d", - iface->family); - } - - if (up < 0 || up > (time_t) UINT16_MAX) - message->secs = htons ((uint16_t) UINT16_MAX); - else - message->secs = htons (up); - message->xid = xid; - message->cookie = htonl (MAGIC_COOKIE); - - *p++ = DHCP_MESSAGETYPE; - *p++ = 1; - *p++ = type; - - if (type == DHCP_REQUEST) { - *p++ = DHCP_MAXMESSAGESIZE; - *p++ = 2; - sz = get_mtu (iface->name); - if (sz < MTU_MIN) { - if (set_mtu (iface->name, MTU_MIN) == 0) - sz = MTU_MIN; - } - sz = htons (sz); - memcpy (p, &sz, 2); - p += 2; - } - - *p++ = DHCP_CLIENTID; - *p++ = iface->clientid_len; - memcpy (p, iface->clientid, iface->clientid_len); - p+= iface->clientid_len; - - if (type != DHCP_DECLINE && type != DHCP_RELEASE) { - if (options->userclass_len > 0) { - *p++ = DHCP_USERCLASS; - *p++ = options->userclass_len; - memcpy (p, &options->userclass, options->userclass_len); - p += options->userclass_len; - } - - if (*options->classid > 0) { - *p++ = DHCP_CLASSID; - *p++ = l = strlen (options->classid); - memcpy (p, options->classid, l); - p += l; - } - } - - if (type == DHCP_DISCOVER || type == DHCP_REQUEST) { -#define PUTADDR(_type, _val) { \ - *p++ = _type; \ - *p++ = 4; \ - memcpy (p, &_val.s_addr, 4); \ - p += 4; \ -} - if (IN_LINKLOCAL (ntohl (dhcp->address.s_addr))) - logger (LOG_ERR, - "cannot request a link local address"); - else { - if (dhcp->address.s_addr && - dhcp->address.s_addr != - iface->previous_address.s_addr) - { - PUTADDR (DHCP_ADDRESS, dhcp->address); - if (dhcp->serveraddress.s_addr) - PUTADDR (DHCP_SERVERIDENTIFIER, - dhcp->serveraddress); - } - } -#undef PUTADDR - - if (options->leasetime != 0) { - *p++ = DHCP_LEASETIME; - *p++ = 4; - ul = htonl (options->leasetime); - memcpy (p, &ul, 4); - p += 4; - } - } - - if (type == DHCP_DISCOVER || - type == DHCP_INFORM || - type == DHCP_REQUEST) - { - if (options->hostname[0]) { - if (options->fqdn == FQDN_DISABLE) { - *p++ = DHCP_HOSTNAME; - *p++ = l = strlen (options->hostname); - memcpy (p, options->hostname, l); - p += l; - } else { - /* Draft IETF DHC-FQDN option (81) */ - *p++ = DHCP_FQDN; - *p++ = (l = strlen (options->hostname)) + 3; - /* Flags: 0000NEOS - * S: 1 => Client requests Server to update - * a RR in DNS as well as PTR - * O: 1 => Server indicates to client that - * DNS has been updated - * E: 1 => Name data is DNS format - * N: 1 => Client requests Server to not - * update DNS - */ - *p++ = options->fqdn & 0x9; - *p++ = 0; /* from server for PTR RR */ - *p++ = 0; /* from server for A RR if S=1 */ - memcpy (p, options->hostname, l); - p += l; - } - } - - *p++ = DHCP_PARAMETERREQUESTLIST; - n_params = p; - *p++ = 0; - /* Only request DNSSERVER in discover to keep the packets small. - * RFC2131 Section 3.5 states that the REQUEST must include the - * list from the DISCOVER message, so I think this is ok. */ - - if (type == DHCP_DISCOVER && ! options->test) - *p++ = DHCP_DNSSERVER; - else { - if (type != DHCP_INFORM) { - *p++ = DHCP_RENEWALTIME; - *p++ = DHCP_REBINDTIME; - } - *p++ = DHCP_NETMASK; - *p++ = DHCP_BROADCAST; - - /* -S means request CSR and MSCSR - * -SS means only request MSCSR incase DHCP message - * is too big */ - if (options->domscsr < 2) - *p++ = DHCP_CSR; - if (options->domscsr > 0) - *p++ = DHCP_MSCSR; - /* RFC 3442 states classless static routes should be - * before routers and static routes as classless static - * routes override them both */ - *p++ = DHCP_STATICROUTE; - *p++ = DHCP_ROUTERS; - *p++ = DHCP_HOSTNAME; - *p++ = DHCP_DNSSEARCH; - *p++ = DHCP_DNSDOMAIN; - *p++ = DHCP_DNSSERVER; -#ifdef ENABLE_NIS - *p++ = DHCP_NISDOMAIN; - *p++ = DHCP_NISSERVER; -#endif -#ifdef ENABLE_NTP - *p++ = DHCP_NTPSERVER; -#endif - *p++ = DHCP_MTU; -#ifdef ENABLE_INFO - *p++ = DHCP_ROOTPATH; - *p++ = DHCP_SIPSERVER; -#endif - } - - *n_params = p - n_params - 1; - } - *p++ = DHCP_END; - -#ifdef BOOTP_MESSAGE_LENTH_MIN - /* Some crappy DHCP servers think they have to obey the BOOTP minimum - * message length. - * They are wrong, but we should still cater for them. */ - while (p - m < BOOTP_MESSAGE_LENTH_MIN) - *p++ = DHCP_PAD; -#endif - - message_length = p - m; - - packet = xzalloc (sizeof (*packet)); - make_dhcp_packet (packet, (unsigned char *) message, message_length, - from, to); - free (message); - - logger (LOG_DEBUG, "sending %s with xid 0x%x", - dhcp_message (type), xid); - retval = send_packet (iface, ETHERTYPE_IP, (unsigned char *) packet, - message_length + - sizeof (packet->ip) + sizeof (packet->udp)); - free (packet); - return (retval); -} - -/* Decode an RFC3397 DNS search order option into a space - * seperated string. Returns length of string (including - * terminating zero) or zero on error. out may be NULL - * to just determine output length. */ -static unsigned int decode_search (const unsigned char *p, int len, char *out) -{ - const unsigned char *r, *q = p; - unsigned int count = 0, l, hops; - - while (q - p < len) { - r = NULL; - hops = 0; - while ((l = *q++)) { - unsigned int label_type = l & 0xc0; - if (label_type == 0x80 || label_type == 0x40) - return 0; - else if (label_type == 0xc0) { /* pointer */ - l = (l & 0x3f) << 8; - l |= *q++; - - /* save source of first jump. */ - if (!r) - r = q; - - hops++; - if (hops > 255) - return 0; - - q = p + l; - if (q - p >= len) - return 0; - } else { - /* straightforward name segment, add with '.' */ - count += l + 1; - if (out) { - memcpy (out, q, l); - out += l; - *out++ = '.'; - } - q += l; - } - } - - /* change last dot to space */ - if (out) - *(out - 1) = ' '; - - if (r) - q = r; - } - - /* change last space to zero terminator */ - if (out) - *(out - 1) = 0; - - return count; -} - -/* Add our classless static routes to the routes variable - * and return the last route set */ -static struct route_head *decode_CSR (const unsigned char *p, int len) -{ - const unsigned char *q = p; - unsigned int cidr; - unsigned int ocets; - struct route_head *routes = NULL; - route_t *route; - - /* Minimum is 5 -first is CIDR and a router length of 4 */ - if (len < 5) - return NULL; - - while (q - p < len) { - if (! routes) { - routes = xmalloc (sizeof (*routes)); - STAILQ_INIT (routes); - } - - route = xzalloc (sizeof (*route)); - - cidr = *q++; - if (cidr > 32) { - logger (LOG_ERR, - "invalid CIDR of %d in classless static route", - cidr); - free_route (routes); - return (NULL); - } - ocets = (cidr + 7) / 8; - - if (ocets > 0) { - memcpy (&route->destination.s_addr, q, (size_t) ocets); - q += ocets; - } - - /* Now enter the netmask */ - if (ocets > 0) { - memset (&route->netmask.s_addr, 255, (size_t) ocets - 1); - memset ((unsigned char *) &route->netmask.s_addr + - (ocets - 1), - (256 - (1 << (32 - cidr) % 8)), 1); - } - - /* Finally, snag the router */ - memcpy (&route->gateway.s_addr, q, 4); - q += 4; - - STAILQ_INSERT_TAIL (routes, route, entries); - } - - return (routes); -} - -void free_dhcp (dhcp_t *dhcp) -{ - if (! dhcp) - return; - - free_route (dhcp->routes); - free (dhcp->hostname); - free_address (dhcp->dnsservers); - free (dhcp->dnsdomain); - free (dhcp->dnssearch); - free_address (dhcp->ntpservers); - free (dhcp->nisdomain); - free_address (dhcp->nisservers); - free (dhcp->rootpath); - free (dhcp->sipservers); - if (dhcp->fqdn) { - free (dhcp->fqdn->name); - free (dhcp->fqdn); - } -} - - -static bool dhcp_add_address (struct address_head **addresses, - const unsigned char *data, - int length) -{ - int i; - address_t *address; - - for (i = 0; i < length; i += 4) { - /* Sanity check */ - if (i + 4 > length) { - logger (LOG_ERR, "invalid address length"); - return (false); - } - - if (*addresses == NULL) { - *addresses = xmalloc (sizeof (**addresses)); - STAILQ_INIT (*addresses); - } - address = xzalloc (sizeof (*address)); - memcpy (&address->address.s_addr, data + i, 4); - STAILQ_INSERT_TAIL (*addresses, address, entries); - } - - return (true); -} - -#ifdef ENABLE_INFO -static char *decode_sipservers (const unsigned char *data, int length) -{ - char *sip = NULL; - char *p; - const char encoding = *data++; - struct in_addr addr; - size_t len; - - length--; - - switch (encoding) { - case 0: - if ((len = decode_search (data, length, NULL)) > 0) { - sip = xmalloc (len); - decode_search (data, length, sip); - } - break; - - case 1: - if (length == 0 || length % 4 != 0) { - logger (LOG_ERR, - "invalid length %d for option 120", - length + 1); - break; - } - len = ((length / 4) * (4 * 4)) + 1; - sip = p = xmalloc (len); - while (length != 0) { - memcpy (&addr.s_addr, data, 4); - data += 4; - p += snprintf (p, len - (p - sip), - "%s ", inet_ntoa (addr)); - length -= 4; - } - *--p = '\0'; - break; - - default: - logger (LOG_ERR, "unknown sip encoding %d", encoding); - break; - } - - return (sip); -} -#endif - -/* This calculates the netmask that we should use for static routes. - * This IS different from the calculation used to calculate the netmask - * for an interface address. */ -static uint32_t route_netmask (uint32_t ip_in) -{ - /* used to be unsigned long - check if error */ - uint32_t p = ntohl (ip_in); - uint32_t t; - - if (IN_CLASSA (p)) - t = ~IN_CLASSA_NET; - else { - if (IN_CLASSB (p)) - t = ~IN_CLASSB_NET; - else { - if (IN_CLASSC (p)) - t = ~IN_CLASSC_NET; - else - t = 0; - } - } - - while (t & p) - t >>= 1; - - return (htonl (~t)); -} - -static struct route_head *decode_routes (const unsigned char *data, int length) -{ - int i; - struct route_head *head = NULL; - route_t *route; - - for (i = 0; i < length; i += 8) { - if (! head) { - head = xmalloc (sizeof (*head)); - STAILQ_INIT (head); - } - route = xzalloc (sizeof (*route)); - memcpy (&route->destination.s_addr, data + i, 4); - memcpy (&route->gateway.s_addr, data + i + 4, 4); - route->netmask.s_addr = - route_netmask (route->destination.s_addr); - STAILQ_INSERT_TAIL (head, route, entries); - } - - return (head); -} - -static struct route_head *decode_routers (const unsigned char *data, int length) -{ - int i; - struct route_head *head = NULL; - route_t *route = NULL; - - for (i = 0; i < length; i += 4) { - if (! head) { - head = xmalloc (sizeof (*head)); - STAILQ_INIT (head); - } - route = xzalloc (sizeof (*route)); - memcpy (&route->gateway.s_addr, data + i, 4); - STAILQ_INSERT_TAIL (head, route, entries); - } - - return (head); -} - -int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message) -{ - const unsigned char *p = message->options; - const unsigned char *end = p; /* Add size later for gcc-3 issue */ - unsigned char option; - unsigned char length; - unsigned int len = 0; - int retval = -1; - struct timeval tv; - struct route_head *routers = NULL; - struct route_head *routes = NULL; - struct route_head *csr = NULL; - struct route_head *mscsr = NULL; - bool in_overload = false; - bool parse_sname = false; - bool parse_file = false; - - end += sizeof (message->options); - - if (gettimeofday (&tv, NULL) == -1) { - logger (LOG_ERR, "gettimeofday: %s", strerror (errno)); - return (-1); - } - - dhcp->address.s_addr = message->yiaddr; - dhcp->leasedfrom = tv.tv_sec; - dhcp->frominfo = false; - dhcp->address.s_addr = message->yiaddr; - strlcpy (dhcp->servername, (char *) message->servername, - sizeof (dhcp->servername)); - -#define LEN_ERR \ - { \ - logger (LOG_ERR, "invalid length %d for option %d", \ - length, option); \ - p += length; \ - continue; \ - } - -parse_start: - while (p < end) { - option = *p++; - if (! option) - continue; - - if (option == DHCP_END) - goto eexit; - - length = *p++; - - if (option != DHCP_PAD && length == 0) { - logger (LOG_ERR, "option %d has zero length", option); - retval = -1; - goto eexit; - } - - if (p + length >= end) { - logger (LOG_ERR, "dhcp option exceeds message length"); - retval = -1; - goto eexit; - } - - switch (option) { - case DHCP_MESSAGETYPE: - retval = (int) *p; - p += length; - continue; - - default: - if (length == 0) { - logger (LOG_DEBUG, - "option %d has zero length, skipping", - option); - continue; - } - } - -#define LENGTH(_length) \ - if (length != _length) \ - LEN_ERR; -#define MIN_LENGTH(_length) \ - if (length < _length) \ - LEN_ERR; -#define MULT_LENGTH(_mult) \ - if (length % _mult != 0) \ - LEN_ERR; -#define GET_UINT8(_val) \ - LENGTH (sizeof (uint8_t)); \ - memcpy (&_val, p, sizeof (uint8_t)); -#define GET_UINT16(_val) \ - LENGTH (sizeof (uint16_t)); \ - memcpy (&_val, p, sizeof (uint16_t)); -#define GET_UINT32(_val) \ - LENGTH (sizeof (uint32_t)); \ - memcpy (&_val, p, sizeof (uint32_t)); -#define GET_UINT16_H(_val) \ - GET_UINT16 (_val); \ - _val = ntohs (_val); -#define GET_UINT32_H(_val) \ - GET_UINT32 (_val); \ - _val = ntohl (_val); - - switch (option) { - case DHCP_ADDRESS: - GET_UINT32 (dhcp->address.s_addr); - break; - case DHCP_NETMASK: - GET_UINT32 (dhcp->netmask.s_addr); - break; - case DHCP_BROADCAST: - GET_UINT32 (dhcp->broadcast.s_addr); - break; - case DHCP_SERVERIDENTIFIER: - GET_UINT32 (dhcp->serveraddress.s_addr); - break; - case DHCP_LEASETIME: - GET_UINT32_H (dhcp->leasetime); - break; - case DHCP_RENEWALTIME: - GET_UINT32_H (dhcp->renewaltime); - break; - case DHCP_REBINDTIME: - GET_UINT32_H (dhcp->rebindtime); - break; - case DHCP_MTU: - GET_UINT16_H (dhcp->mtu); - /* Minimum legal mtu is 68 accoridng to - * RFC 2132. In practise it's 576 which is the - * minimum maximum message size. */ - if (dhcp->mtu < MTU_MIN) { - logger (LOG_DEBUG, - "MTU %d is too low, minimum is %d; ignoring", - dhcp->mtu, MTU_MIN); - dhcp->mtu = 0; - } - break; - -#undef GET_UINT32_H -#undef GET_UINT32 -#undef GET_UINT16_H -#undef GET_UINT16 -#undef GET_UINT8 - -#define GETSTR(_var) { \ - MIN_LENGTH (sizeof (char)); \ - if (_var) free (_var); \ - _var = xmalloc ((size_t) length + 1); \ - memcpy (_var, p, (size_t) length); \ - memset (_var + length, 0, 1); \ -} - case DHCP_HOSTNAME: - GETSTR (dhcp->hostname); - break; - case DHCP_DNSDOMAIN: - GETSTR (dhcp->dnsdomain); - break; - case DHCP_MESSAGE: - GETSTR (dhcp->message); - break; -#ifdef ENABLE_INFO - case DHCP_ROOTPATH: - GETSTR (dhcp->rootpath); - break; -#endif -#ifdef ENABLE_NIS - case DHCP_NISDOMAIN: - GETSTR (dhcp->nisdomain); - break; -#endif -#undef GETSTR - -#define GETADDR(_var) \ - MULT_LENGTH (4); \ - if (! dhcp_add_address (&_var, p, length)) \ - { \ - retval = -1; \ - goto eexit; \ - } - case DHCP_DNSSERVER: - GETADDR (dhcp->dnsservers); - break; -#ifdef ENABLE_NTP - case DHCP_NTPSERVER: - GETADDR (dhcp->ntpservers); - break; -#endif -#ifdef ENABLE_NIS - case DHCP_NISSERVER: - GETADDR (dhcp->nisservers); - break; -#endif -#undef GETADDR - - case DHCP_DNSSEARCH: - MIN_LENGTH (1); - free (dhcp->dnssearch); - len = decode_search (p, length, NULL); - if (len > 0) { - dhcp->dnssearch = xmalloc (len); - decode_search (p, length, - dhcp->dnssearch); - } - break; - - case DHCP_CSR: - MIN_LENGTH (5); - free_route (csr); - csr = decode_CSR (p, length); - break; - - case DHCP_MSCSR: - MIN_LENGTH (5); - free_route (mscsr); - mscsr = decode_CSR (p, length); - break; - -#ifdef ENABLE_INFO - case DHCP_SIPSERVER: - free (dhcp->sipservers); - dhcp->sipservers = decode_sipservers (p,length); - break; -#endif - - case DHCP_STATICROUTE: - MULT_LENGTH (8); - free_route (routes); - routes = decode_routes (p, length); - break; - - case DHCP_ROUTERS: - MULT_LENGTH (4); - free_route (routers); - routers = decode_routers (p, length); - break; - - case DHCP_OPTIONSOVERLOADED: - LENGTH (1); - /* The overloaded option in an overloaded option - * should be ignored, overwise we may get an - * infinite loop */ - if (! in_overload) { - if (*p & 1) - parse_file = true; - if (*p & 2) - parse_sname = true; - } - break; - - case DHCP_FQDN: - /* We ignore replies about FQDN */ - break; - -#undef LENGTH -#undef MIN_LENGTH -#undef MULT_LENGTH - - default: - logger (LOG_DEBUG, - "no facility to parse DHCP code %u", - option); - break; - } - - p += length; - } - -eexit: - /* We may have options overloaded, so go back and grab them */ - if (parse_file) { - parse_file = false; - p = message->bootfile; - end = p + sizeof (message->bootfile); - in_overload = true; - goto parse_start; - } else if (parse_sname) { - parse_sname = false; - p = message->servername; - end = p + sizeof (message->servername); - memset (dhcp->servername, 0, sizeof (dhcp->servername)); - in_overload = true; - goto parse_start; - } - - /* Fill in any missing fields */ - if (! dhcp->netmask.s_addr) - dhcp->netmask.s_addr = get_netmask (dhcp->address.s_addr); - if (! dhcp->broadcast.s_addr) - dhcp->broadcast.s_addr = dhcp->address.s_addr | - ~dhcp->netmask.s_addr; - - /* If we have classess static routes then we discard - * static routes and routers according to RFC 3442 */ - if (csr) { - dhcp->routes = csr; - free_route (mscsr); - free_route (routers); - free_route (routes); - } else if (mscsr) { - dhcp->routes = mscsr; - free_route (routers); - free_route (routes); - } else { - /* Ensure that we apply static routes before routers */ - if (! routes) - routes = routers; - else if (routers) - STAILQ_CONCAT (routes, routers); - dhcp->routes = routes; - } - - return (retval); -} |
