diff options
-rw-r--r-- | sbin/dhclient/clparse.c | 5 | ||||
-rw-r--r-- | sbin/dhclient/dhclient.c | 102 | ||||
-rw-r--r-- | sbin/dhclient/dhcp.h | 3 | ||||
-rw-r--r-- | sbin/dhclient/kroute.c | 39 | ||||
-rw-r--r-- | sbin/dhclient/tables.c | 4 |
5 files changed, 111 insertions, 42 deletions
diff --git a/sbin/dhclient/clparse.c b/sbin/dhclient/clparse.c index d261e8c05f1..f51e4148ff4 100644 --- a/sbin/dhclient/clparse.c +++ b/sbin/dhclient/clparse.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clparse.c,v 1.57 2013/05/02 16:35:27 krw Exp $ */ +/* $OpenBSD: clparse.c,v 1.58 2013/06/04 21:04:51 krw Exp $ */ /* Parser for dhclient config and lease files. */ @@ -72,6 +72,9 @@ read_client_conf(void) [config->requested_option_count++] = DHO_BROADCAST_ADDRESS; config->requested_options [config->requested_option_count++] = DHO_TIME_OFFSET; + /* RFC 3442 says CLASSLESS_STATIC_ROUTES must be before ROUTERS! */ + config->requested_options + [config->requested_option_count++] = DHO_CLASSLESS_STATIC_ROUTES; config->requested_options [config->requested_option_count++] = DHO_ROUTERS; config->requested_options diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index 7c98573da33..41ec4549d9c 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dhclient.c,v 1.248 2013/06/01 16:26:07 krw Exp $ */ +/* $OpenBSD: dhclient.c,v 1.249 2013/06/04 21:04:52 krw Exp $ */ /* * Copyright 2004 Henning Brauer <henning@openbsd.org> @@ -109,6 +109,8 @@ void socket_nonblockmode(int); void apply_ignore_list(char *); void add_default_route(int, struct in_addr, struct in_addr); +void add_static_routes(int, struct option_data *); +void add_classless_static_routes(int, struct option_data *); #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) @@ -790,12 +792,21 @@ bind_lease(void) * is done by the RTM_NEWADDR message being received. */ add_address(ifi->name, ifi->rdomain, client->new->address, mask); - if (options[DHO_ROUTERS].len) { - memset(&gateway, 0, sizeof(gateway)); - /* XXX Only use FIRST router address for now. */ - memcpy(&gateway.s_addr, options[DHO_ROUTERS].data, - options[DHO_ROUTERS].len); - add_default_route(ifi->rdomain, client->new->address, gateway); + if (options[DHO_CLASSLESS_STATIC_ROUTES].len) { + add_classless_static_routes(ifi->rdomain, + &options[DHO_CLASSLESS_STATIC_ROUTES]); + } else { + if (options[DHO_ROUTERS].len) { + memset(&gateway, 0, sizeof(gateway)); + /* XXX Only use FIRST router address for now. */ + memcpy(&gateway.s_addr, options[DHO_ROUTERS].data, + options[DHO_ROUTERS].len); + add_default_route(ifi->rdomain, client->new->address, + gateway); + } + if (options[DHO_STATIC_ROUTES].len) + add_static_routes(ifi->rdomain, + &options[DHO_STATIC_ROUTES]); } client->new->resolv_conf = resolv_conf_contents( @@ -2280,27 +2291,76 @@ priv_write_file(struct imsg_write_file *imsg) void add_default_route(int rdomain, struct in_addr addr, struct in_addr gateway) { - struct imsg_add_route imsg; - int rslt; + struct in_addr netmask; + int addrs; - memset(&imsg, 0, sizeof(imsg)); - - imsg.rdomain = rdomain; - imsg.dest = addr; - imsg.addrs = RTA_DST | RTA_NETMASK; + memset(&netmask, 0, sizeof(netmask)); + addrs = RTA_DST | RTA_NETMASK; /* * Set gateway address if and only if non-zero addr supplied. A * gateway address of 0 implies '-iface'. */ - if (bcmp(&gateway, &addr, sizeof(addr)) != 0) { - imsg.gateway = gateway; - imsg.addrs |= RTA_GATEWAY; + if (bcmp(&gateway, &addr, sizeof(addr)) != 0) + addrs |= RTA_GATEWAY; + + add_route(rdomain, addr, netmask, gateway, addrs); +} + +void +add_static_routes(int rdomain, struct option_data *static_routes) +{ + struct in_addr dest, netmask, gateway; + u_int8_t *addr; + int i; + + memset(&netmask, 0, sizeof(netmask)); /* Always 0 for class addrs. */ + + for (i = 0; (i + 7) < static_routes->len; i += 8) { + addr = &static_routes->data[i]; + memset(&dest, 0, sizeof(dest)); + memset(&gateway, 0, sizeof(gateway)); + + memcpy(&dest.s_addr, addr, 4); + if (dest.s_addr == INADDR_ANY) + continue; /* RFC 2132 says 0.0.0.0 is not allowed. */ + memcpy(&gateway.s_addr, addr+4, 4); + + /* XXX Order implies priority but we're ignoring that. */ + add_route(rdomain, dest, netmask, gateway, + RTA_DST | RTA_GATEWAY); } +} - rslt = imsg_compose(unpriv_ibuf, IMSG_ADD_ROUTE, 0, 0, -1, &imsg, - sizeof(imsg)); +void add_classless_static_routes(int rdomain, + struct option_data *classless_static_routes) +{ + struct in_addr dest, netmask, gateway; + int bits, bytes, i; - if (rslt == -1) - warning("add_route: imsg_compose: %s", strerror(errno)); + i = 0; + while (i < classless_static_routes->len) { + bits = classless_static_routes->data[i]; + bytes = (bits + 7) / 8; + i++; + + memset(&netmask, 0, sizeof(netmask)); + if (bits) + netmask.s_addr = htonl(0xffffffff << (32 - bits)); + + memset(&dest, 0, sizeof(dest)); + memcpy(&dest, &classless_static_routes->data[i], bytes); + dest.s_addr = dest.s_addr & netmask.s_addr; + i += bytes; + + memset(&gateway, 0, sizeof(gateway)); + memcpy(&gateway, &classless_static_routes->data[i], 4); + i += 4; + + if (gateway.s_addr == INADDR_ANY) + continue; /* OBSD TCP/IP doesn't support this. */ + + add_route(rdomain, dest, netmask, gateway, + RTA_DST | RTA_GATEWAY | RTA_NETMASK); + } } diff --git a/sbin/dhclient/dhcp.h b/sbin/dhclient/dhcp.h index 13d098c7237..4b5d478c871 100644 --- a/sbin/dhclient/dhcp.h +++ b/sbin/dhclient/dhcp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dhcp.h,v 1.12 2013/05/02 16:35:27 krw Exp $ */ +/* $OpenBSD: dhcp.h,v 1.13 2013/06/04 21:04:52 krw Exp $ */ /* Protocol structures. */ @@ -173,6 +173,7 @@ struct dhcp_packet { #define DHO_NDS_SERVERS 85 #define DHO_NDS_TREE_NAME 86 #define DHO_NDS_CONTEXT 87 +#define DHO_CLASSLESS_STATIC_ROUTES 121 #define DHO_TFTP_CONFIG_FILE 144 #define DHO_VOIP_CONFIGURATION_SERVER 150 #define DHO_AUTOPROXY_SCRIPT 252 diff --git a/sbin/dhclient/kroute.c b/sbin/dhclient/kroute.c index 7e0869c5c7d..71e1f92916c 100644 --- a/sbin/dhclient/kroute.c +++ b/sbin/dhclient/kroute.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kroute.c,v 1.48 2013/06/01 16:26:07 krw Exp $ */ +/* $OpenBSD: kroute.c,v 1.49 2013/06/04 21:04:53 krw Exp $ */ /* * Copyright 2012 Kenneth R Westerback <krw@openbsd.org> @@ -229,18 +229,21 @@ priv_add_route(struct imsg_add_route *imsg) iov[iovcnt].iov_base = &rtm; iov[iovcnt++].iov_len = sizeof(rtm); - /* Set destination address of all zeros. */ + /* Set destination address. */ memset(&dest, 0, sizeof(dest)); - dest.sin_len = sizeof(dest); - dest.sin_family = AF_INET; + if (imsg->addrs & RTA_DST) { + dest.sin_len = sizeof(dest); + dest.sin_family = AF_INET; + dest.sin_addr.s_addr = imsg->dest.s_addr; - rtm.rtm_addrs |= RTA_DST; - rtm.rtm_msglen += sizeof(dest); + rtm.rtm_addrs |= RTA_DST; + rtm.rtm_msglen += sizeof(dest); - iov[iovcnt].iov_base = &dest; - iov[iovcnt++].iov_len = sizeof(dest); + iov[iovcnt].iov_base = &dest; + iov[iovcnt++].iov_len = sizeof(dest); + } /* * Set gateway address if and only if non-zero addr supplied. A @@ -248,7 +251,7 @@ priv_add_route(struct imsg_add_route *imsg) */ memset(&gateway, 0, sizeof(gateway)); - if ((imsg->addrs & RTA_GATEWAY) != 0) { + if (imsg->addrs & RTA_GATEWAY) { gateway.sin_len = sizeof(gateway); gateway.sin_family = AF_INET; gateway.sin_addr.s_addr = imsg->gateway.s_addr; @@ -261,18 +264,20 @@ priv_add_route(struct imsg_add_route *imsg) iov[iovcnt++].iov_len = sizeof(gateway); } - /* Add netmask of 0. */ + /* Add netmask. */ memset(&mask, 0, sizeof(mask)); - mask.sin_len = sizeof(mask); - mask.sin_family = AF_INET; - mask.sin_addr.s_addr = imsg->netmask.s_addr; + if (imsg->addrs & RTA_NETMASK) { + mask.sin_len = sizeof(mask); + mask.sin_family = AF_INET; + mask.sin_addr.s_addr = imsg->netmask.s_addr; - rtm.rtm_addrs |= RTA_NETMASK; - rtm.rtm_msglen += sizeof(mask); + rtm.rtm_addrs |= RTA_NETMASK; + rtm.rtm_msglen += sizeof(mask); - iov[iovcnt].iov_base = &mask; - iov[iovcnt++].iov_len = sizeof(mask); + iov[iovcnt].iov_base = &mask; + iov[iovcnt++].iov_len = sizeof(mask); + } /* Add our label so we can identify the route as our creation. */ if (create_route_label(&label) == 0) { diff --git a/sbin/dhclient/tables.c b/sbin/dhclient/tables.c index 9d1cd0f07c0..84cdabbc433 100644 --- a/sbin/dhclient/tables.c +++ b/sbin/dhclient/tables.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tables.c,v 1.13 2013/05/02 16:35:27 krw Exp $ */ +/* $OpenBSD: tables.c,v 1.14 2013/06/04 21:04:53 krw Exp $ */ /* Tables of information. */ @@ -182,7 +182,7 @@ const struct option dhcp_options[256] = { /* 118 */ { "option-118", "X" }, /* 119 */ { "option-119", "X" }, /* 120 */ { "option-120", "X" }, - /* 121 */ { "option-121", "X" }, + /* 121 */ { "classless-static-routes", "X" }, /* 122 */ { "option-122", "X" }, /* 123 */ { "option-123", "X" }, /* 124 */ { "option-124", "X" }, |