summaryrefslogtreecommitdiffstats
path: root/src/customdhcpcd/dhcp.c
diff options
context:
space:
mode:
authorSebastian Schmelzer2011-12-03 13:31:09 +0100
committerSebastian Schmelzer2011-12-03 13:31:09 +0100
commit1b48532c662470f5dd4090d47e1e2c333e967caf (patch)
tree8c23d3eca5fa088b91887d528138b9e0462382fb /src/customdhcpcd/dhcp.c
parentlet cmake find qxt (diff)
downloadfbgui-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.c1480
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);
}