From cbd427b414d43e04ff6df58a297b98bcc024bdd9 Mon Sep 17 00:00:00 2001 From: krw Date: Thu, 6 Jul 2017 16:56:52 +0000 Subject: [PATCH] cons_options() only needs to know a buffer and a length to pack options into. Not all the gory details of interface_info. Move some of the raw packet processing out of options.c's do_packet() and into the more obvious dispatch.c's packethandler(). Mention that RFC791 is why we use 576-byte UDP packets. --- sbin/dhclient/dhclient.c | 53 ++++++++++++++++++++++++++-------------- sbin/dhclient/dhcpd.h | 4 +-- sbin/dhclient/dispatch.c | 47 +++++++++++++++++++++++++++++++---- sbin/dhclient/options.c | 40 ++---------------------------- 4 files changed, 80 insertions(+), 64 deletions(-) diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c index 49d0e4d7e61..ccbbe58425d 100644 --- a/sbin/dhclient/dhclient.c +++ b/sbin/dhclient/dhclient.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dhclient.c,v 1.455 2017/07/05 16:17:42 krw Exp $ */ +/* $OpenBSD: dhclient.c,v 1.456 2017/07/06 16:56:52 krw Exp $ */ /* * Copyright 2004 Henning Brauer @@ -1520,10 +1520,10 @@ send_decline(struct interface_info *ifi) void make_discover(struct interface_info *ifi, struct client_lease *lease) { - struct option_data options[256]; - struct dhcp_packet *packet = &ifi->sent_packet; - unsigned char discover = DHCPDISCOVER; - int i; + struct option_data options[256]; + struct dhcp_packet *packet = &ifi->sent_packet; + unsigned char discover = DHCPDISCOVER; + int i; memset(options, 0, sizeof(options)); memset(packet, 0, sizeof(*packet)); @@ -1555,8 +1555,13 @@ make_discover(struct interface_info *ifi, struct client_lease *lease) options[i].len = config->send_options[i].len; } - /* Set up the option buffer to fit in a minimal UDP packet. */ - i = cons_options(ifi, options); + /* + * Set up the option buffer to fit in a 576-byte UDP packet, which + * RFC 791 says is the largest packet that *MUST* be accepted + * by any host. + */ + i = cons_options(ifi->sent_packet.options, 576 - DHCP_FIXED_LEN, + options); if (i == -1 || packet->options[i] != DHO_END) fatalx("options do not fit in DHCPDISCOVER packet."); ifi->sent_packet_length = DHCP_FIXED_NON_UDP+i+1; @@ -1583,10 +1588,10 @@ make_discover(struct interface_info *ifi, struct client_lease *lease) void make_request(struct interface_info *ifi, struct client_lease * lease) { - struct option_data options[256]; - struct dhcp_packet *packet = &ifi->sent_packet; - unsigned char request = DHCPREQUEST; - int i; + struct option_data options[256]; + struct dhcp_packet *packet = &ifi->sent_packet; + unsigned char request = DHCPREQUEST; + int i; memset(options, 0, sizeof(options)); memset(packet, 0, sizeof(*packet)); @@ -1626,8 +1631,13 @@ make_request(struct interface_info *ifi, struct client_lease * lease) options[i].len = config->send_options[i].len; } - /* Set up the option buffer to fit in a minimal UDP packet. */ - i = cons_options(ifi, options); + /* + * Set up the option buffer to fit in a 576-byte UDP packet, which + * RFC 791 says is the largest packet that *MUST* be accepted + * by any host. + */ + i = cons_options(ifi->sent_packet.options, 576 - DHCP_FIXED_LEN, + options); if (i == -1 || packet->options[i] != DHO_END) fatalx("options do not fit in DHCPREQUEST packet."); ifi->sent_packet_length = DHCP_FIXED_NON_UDP+i+1; @@ -1664,10 +1674,10 @@ make_request(struct interface_info *ifi, struct client_lease * lease) void make_decline(struct interface_info *ifi, struct client_lease *lease) { - struct option_data options[256]; - struct dhcp_packet *packet = &ifi->sent_packet; - unsigned char decline = DHCPDECLINE; - int i; + struct option_data options[256]; + struct dhcp_packet *packet = &ifi->sent_packet; + unsigned char decline = DHCPDECLINE; + int i; memset(options, 0, sizeof(options)); memset(packet, 0, sizeof(*packet)); @@ -1694,8 +1704,13 @@ make_decline(struct interface_info *ifi, struct client_lease *lease) options[i].len = config->send_options[i].len; } - /* Set up the option buffer to fit in a minimal UDP packet. */ - i = cons_options(ifi, options); + /* + * Set up the option buffer to fit in a 576-byte UDP packet, which + * RFC 791 says is the largest packet that *MUST* be accepted + * by any host. + */ + i = cons_options(ifi->sent_packet.options, 576 - DHCP_FIXED_LEN, + options); if (i == -1 || packet->options[i] != DHO_END) fatalx("options do not fit in DHCPDECLINE packet."); ifi->sent_packet_length = DHCP_FIXED_NON_UDP+i+1; diff --git a/sbin/dhclient/dhcpd.h b/sbin/dhclient/dhcpd.h index 1003ddcd11a..9ea01048b1e 100644 --- a/sbin/dhclient/dhcpd.h +++ b/sbin/dhclient/dhcpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dhcpd.h,v 1.203 2017/07/05 16:17:42 krw Exp $ */ +/* $OpenBSD: dhcpd.h,v 1.204 2017/07/06 16:56:52 krw Exp $ */ /* * Copyright (c) 2004 Henning Brauer @@ -170,7 +170,7 @@ extern struct in_addr deleting; extern struct in_addr adding; /* options.c */ -int cons_options(struct interface_info *, struct option_data *); +int cons_options(unsigned char *, int, struct option_data *); char *pretty_print_option(unsigned int, struct option_data *, int); char *pretty_print_domain_search(unsigned char *, size_t); char *pretty_print_string(unsigned char *, size_t, int); diff --git a/sbin/dhclient/dispatch.c b/sbin/dhclient/dispatch.c index 325f6b6cc8e..a9d4fc8aba0 100644 --- a/sbin/dhclient/dispatch.c +++ b/sbin/dhclient/dispatch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dispatch.c,v 1.130 2017/07/01 23:27:56 krw Exp $ */ +/* $OpenBSD: dispatch.c,v 1.131 2017/07/06 16:56:52 krw Exp $ */ /* * Copyright 2004 Henning Brauer @@ -53,6 +53,8 @@ #include #include +#include + #include #include #include @@ -198,10 +200,12 @@ dispatch(struct interface_info *ifi, int routefd) void packethandler(struct interface_info *ifi) { - struct sockaddr_in from; - struct ether_addr hfrom; - struct in_addr ifrom; - ssize_t result; + struct sockaddr_in from; + struct ether_addr hfrom; + struct in_addr ifrom; + struct dhcp_packet *packet = &ifi->recv_packet; + struct reject_elem *ap; + ssize_t result; if ((result = receive_packet(ifi, &from, &hfrom)) == -1) { ifi->errors++; @@ -219,6 +223,39 @@ packethandler(struct interface_info *ifi) ifrom.s_addr = from.sin_addr.s_addr; + if (packet->hlen != ETHER_ADDR_LEN) { +#ifdef DEBUG + log_debug("Discarding packet with hlen != %s (%u)", + ifi->name, packet->hlen); +#endif /* DEBUG */ + return; + } else if (memcmp(&ifi->hw_address, packet->chaddr, + sizeof(ifi->hw_address))) { +#ifdef DEBUG + log_debug("Discarding packet with chaddr != %s (%s)", + ifi->name, + ether_ntoa((struct ether_addr *)packet->chaddr)); +#endif /* DEBUG */ + return; + } + + if (ifi->xid != packet->xid) { +#ifdef DEBUG + log_debug("Discarding packet with XID != %u (%u)", ifi->xid, + packet->xid); +#endif /* DEBUG */ + return; + } + + TAILQ_FOREACH(ap, &config->reject_list, next) + if (ifrom.s_addr == ap->addr.s_addr) { +#ifdef DEBUG + log_debug("Discarding packet from address on reject " + "list (%s)", inet_ntoa(ifrom)); +#endif /* DEBUG */ + return; + } + do_packet(ifi, from.sin_port, ifrom, &hfrom); } diff --git a/sbin/dhclient/options.c b/sbin/dhclient/options.c index 612632f02fc..017940af84a 100644 --- a/sbin/dhclient/options.c +++ b/sbin/dhclient/options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: options.c,v 1.92 2017/06/15 17:06:17 krw Exp $ */ +/* $OpenBSD: options.c,v 1.93 2017/07/06 16:56:52 krw Exp $ */ /* DHCP options parsing and reassembly. */ @@ -160,10 +160,8 @@ parse_option_buffer(struct option_data *options, unsigned char *buffer, * to see if it's DHO_END to decide if all the options were copied. */ int -cons_options(struct interface_info *ifi, struct option_data *options) +cons_options(unsigned char *buf, int buflen, struct option_data *options) { - unsigned char *buf = ifi->sent_packet.options; - int buflen = 576 - DHCP_FIXED_LEN; int ix, incr, length, bufix, code, lastopt = -1; memset(buf, 0, buflen); @@ -635,44 +633,10 @@ do_packet(struct interface_info *ifi, unsigned int from_port, { struct dhcp_packet *packet = &ifi->recv_packet; struct option_data options[256]; - struct reject_elem *ap; void (*handler)(struct interface_info *, struct option_data *, char *); char *type, *info; int i, rslt, options_valid = 1; - if (packet->hlen != ETHER_ADDR_LEN) { -#ifdef DEBUG - log_debug("Discarding packet with hlen != %s (%u)", - ifi->name, packet->hlen); -#endif /* DEBUG */ - return; - } else if (memcmp(&ifi->hw_address, packet->chaddr, - sizeof(ifi->hw_address))) { -#ifdef DEBUG - log_debug("Discarding packet with chaddr != %s (%s)", - ifi->name, - ether_ntoa((struct ether_addr *)packet->chaddr)); -#endif /* DEBUG */ - return; - } - - if (ifi->xid != packet->xid) { -#ifdef DEBUG - log_debug("Discarding packet with XID != %u (%u)", ifi->xid, - packet->xid); -#endif /* DEBUG */ - return; - } - - TAILQ_FOREACH(ap, &config->reject_list, next) - if (from.s_addr == ap->addr.s_addr) { -#ifdef DEBUG - log_debug("Discarding packet from address on reject " - "list (%s)", inet_ntoa(from)); -#endif /* DEBUG */ - return; - } - memset(options, 0, sizeof(options)); if (memcmp(&packet->options, DHCP_OPTIONS_COOKIE, 4) == 0) { -- 2.20.1