diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2013-06-09 16:21:51 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2013-06-09 16:21:51 +0000 |
commit | 3e2683ad937f6dcdf76303725b90a68fa9e0bbc7 (patch) | |
tree | 231779caac102d6408d183f69e5603ffbb3e3e39 /sbin | |
parent | 13b9bb63143ab0275f4bb0bb9b9b7ac460c399f7 (diff) |
Re-apply static route and classless static route support -- this time
passing the correct destination for the default route, '0.0.0.0', rather
than the new lease address.
Populating egress group works this time.
Problem found the hard way by Chris Smith.
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/dhclient/clparse.c | 5 | ||||
-rw-r--r-- | sbin/dhclient/dhclient.c | 103 | ||||
-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, 112 insertions, 42 deletions
diff --git a/sbin/dhclient/clparse.c b/sbin/dhclient/clparse.c index 1dab99a1de1..b3f198fed2a 100644 --- a/sbin/dhclient/clparse.c +++ b/sbin/dhclient/clparse.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clparse.c,v 1.59 2013/06/09 00:30:06 krw Exp $ */ +/* $OpenBSD: clparse.c,v 1.60 2013/06/09 16:21:50 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 d7f5a86c7cf..16dd15ac8c7 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dhclient.c,v 1.251 2013/06/09 15:06:34 krw Exp $ */ +/* $OpenBSD: dhclient.c,v 1.252 2013/06/09 16:21:50 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,77 @@ 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, dest; + int addrs; - memset(&imsg, 0, sizeof(imsg)); - - imsg.rdomain = rdomain; - imsg.dest = addr; - imsg.addrs = RTA_DST | RTA_NETMASK; + memset(&netmask, 0, sizeof(netmask)); + memset(&dest, 0, sizeof(dest)); + 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, dest, 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 1e24aa6fa34..53f8a0440fa 100644 --- a/sbin/dhclient/dhcp.h +++ b/sbin/dhclient/dhcp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dhcp.h,v 1.14 2013/06/09 00:30:06 krw Exp $ */ +/* $OpenBSD: dhcp.h,v 1.15 2013/06/09 16:21:50 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 1abef0d79ff..2a3321c5aab 100644 --- a/sbin/dhclient/kroute.c +++ b/sbin/dhclient/kroute.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kroute.c,v 1.51 2013/06/09 15:06:34 krw Exp $ */ +/* $OpenBSD: kroute.c,v 1.52 2013/06/09 16:21:50 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 b9112334589..5ccfe34254c 100644 --- a/sbin/dhclient/tables.c +++ b/sbin/dhclient/tables.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tables.c,v 1.15 2013/06/09 00:30:06 krw Exp $ */ +/* $OpenBSD: tables.c,v 1.16 2013/06/09 16:21:50 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" }, |