diff options
author | Sebastian Schmelzer | 2011-12-03 13:31:09 +0100 |
---|---|---|
committer | Sebastian Schmelzer | 2011-12-03 13:31:09 +0100 |
commit | 1b48532c662470f5dd4090d47e1e2c333e967caf (patch) | |
tree | 8c23d3eca5fa088b91887d528138b9e0462382fb /src/customdhcpcd/dhcp.c | |
parent | let cmake find qxt (diff) | |
download | fbgui-1b48532c662470f5dd4090d47e1e2c333e967caf.tar.gz fbgui-1b48532c662470f5dd4090d47e1e2c333e967caf.tar.xz fbgui-1b48532c662470f5dd4090d47e1e2c333e967caf.zip |
codeformating, change to log4cxx
Diffstat (limited to 'src/customdhcpcd/dhcp.c')
-rw-r--r-- | src/customdhcpcd/dhcp.c | 1480 |
1 files changed, 770 insertions, 710 deletions
diff --git a/src/customdhcpcd/dhcp.c b/src/customdhcpcd/dhcp.c index f625e8f..7c41ad2 100644 --- a/src/customdhcpcd/dhcp.c +++ b/src/customdhcpcd/dhcp.c @@ -1,4 +1,4 @@ -/* +/* * dhcpcd - DHCP client daemon * Copyright 2006-2008 Roy Marples <roy@marples.name> * All rights reserved @@ -61,492 +61,528 @@ } while (0) #endif -typedef struct message { - int value; - const char *name; +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 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); + dhcp_message_t *d; + for (d = dhcp_messages; d->name; d++) + if (d->value == type) + return (d->name); - return (NULL); + return (NULL); } ssize_t send_message (const interface_t *iface, const dhcp_t *dhcp, - uint32_t xid, char type, const options_t *options) + 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) { + 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); - } - } + 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; + 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; + *p++ = DHCP_NISDOMAIN; + *p++ = DHCP_NISSERVER; #endif #ifdef ENABLE_NTP - *p++ = DHCP_NTPSERVER; + *p++ = DHCP_NTPSERVER; #endif - *p++ = DHCP_MTU; + *p++ = DHCP_MTU; #ifdef ENABLE_INFO - *p++ = DHCP_ROOTPATH; - *p++ = DHCP_SIPSERVER; + *p++ = DHCP_ROOTPATH; + *p++ = DHCP_SIPSERVER; #endif - } + } - *n_params = p - n_params - 1; - } - *p++ = DHCP_END; + *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; + /* 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; + message_length = p - m; - packet = xzalloc (sizeof (*packet)); - make_dhcp_packet (packet, (unsigned char *) message, message_length, - from, to); - free (message); + 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); + 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 + * 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; + 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); + 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); - } + 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) + 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); + 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); + 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 @@ -555,100 +591,107 @@ static char *decode_sipservers (const unsigned char *data, int length) * 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)); + /* 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); + 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 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)); + 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 \ { \ @@ -659,42 +702,47 @@ int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message) } 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; - } - } + 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) \ @@ -721,40 +769,42 @@ parse_start: 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; + 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 @@ -769,24 +819,24 @@ parse_start: 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; + 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; + case DHCP_ROOTPATH: + GETSTR (dhcp->rootpath); + break; #endif #ifdef ENABLE_NIS - case DHCP_NISDOMAIN: - GETSTR (dhcp->nisdomain); - break; + case DHCP_NISDOMAIN: + GETSTR (dhcp->nisdomain); + break; #endif #undef GETSTR @@ -797,137 +847,147 @@ parse_start: retval = -1; \ goto eexit; \ } - case DHCP_DNSSERVER: - GETADDR (dhcp->dnsservers); - break; + case DHCP_DNSSERVER: + GETADDR (dhcp->dnsservers); + break; #ifdef ENABLE_NTP - case DHCP_NTPSERVER: - GETADDR (dhcp->ntpservers); - break; + case DHCP_NTPSERVER: + GETADDR (dhcp->ntpservers); + break; #endif #ifdef ENABLE_NIS - case DHCP_NISSERVER: - GETADDR (dhcp->nisservers); - break; + 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; + 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; + 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; + 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; - } + default: + logger (LOG_DEBUG, + "no facility to parse DHCP code %u", + option); + break; + } - p += length; - } + 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); + /* 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); } |