Rename cons_options() to pack_options(), and do_packet() to
authorkrw <krw@openbsd.org>
Fri, 7 Jul 2017 14:53:06 +0000 (14:53 +0000)
committerkrw <krw@openbsd.org>
Fri, 7 Jul 2017 14:53:06 +0000 (14:53 +0000)
unpack_options(). Store the unpacked options in a static
variable. Move remaining raw packet processing from unpack_options()
to packethandler().

No more struct interface_info knowledge in options.c

sbin/dhclient/dhclient.c
sbin/dhclient/dhcpd.h
sbin/dhclient/dispatch.c
sbin/dhclient/options.c

index ccbbe58..94659f6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dhclient.c,v 1.456 2017/07/06 16:56:52 krw Exp $      */
+/*     $OpenBSD: dhclient.c,v 1.457 2017/07/07 14:53:06 krw Exp $      */
 
 /*
  * Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -1560,7 +1560,7 @@ make_discover(struct interface_info *ifi, struct client_lease *lease)
         * 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,
+       i = pack_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.");
@@ -1636,7 +1636,7 @@ make_request(struct interface_info *ifi, struct client_lease * lease)
         * 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,
+       i = pack_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.");
@@ -1709,7 +1709,7 @@ make_decline(struct interface_info *ifi, struct client_lease *lease)
         * 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,
+       i = pack_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.");
index 9ea0104..5b3e7f7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dhcpd.h,v 1.204 2017/07/06 16:56:52 krw Exp $ */
+/*     $OpenBSD: dhcpd.h,v 1.205 2017/07/07 14:53:06 krw Exp $ */
 
 /*
  * Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -170,13 +170,12 @@ extern struct in_addr deleting;
 extern struct in_addr adding;
 
 /* options.c */
-int cons_options(unsigned char *, int, struct option_data *);
+int pack_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);
 char *pretty_print_classless_routes(unsigned char *, size_t);
-void do_packet(struct interface_info *, unsigned int, struct in_addr,
-    struct ether_addr *);
+struct option_data *unpack_options(struct dhcp_packet *);
 
 /* conflex.c */
 extern int lexline, lexchar;
index a9d4fc8..b3afeff 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: dispatch.c,v 1.131 2017/07/06 16:56:52 krw Exp $      */
+/*     $OpenBSD: dispatch.c,v 1.132 2017/07/07 14:53:07 krw Exp $      */
 
 /*
  * Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -205,7 +205,12 @@ packethandler(struct interface_info *ifi)
        struct in_addr           ifrom;
        struct dhcp_packet      *packet = &ifi->recv_packet;
        struct reject_elem      *ap;
+       struct option_data      *options;
+       char                    *type, *info;
        ssize_t                  result;
+       void                    (*handler)(struct interface_info *,
+           struct option_data *, char *);
+       int                      i, rslt;
 
        if ((result = receive_packet(ifi, &from, &hfrom)) == -1) {
                ifi->errors++;
@@ -256,7 +261,69 @@ packethandler(struct interface_info *ifi)
                    return;
            }
 
-       do_packet(ifi, from.sin_port, ifrom, &hfrom);
+       options = unpack_options(&ifi->recv_packet);
+
+       /*
+        * RFC 6842 says if the server sends a client identifier
+        * that doesn't match then the packet must be dropped.
+        */
+       i = DHO_DHCP_CLIENT_IDENTIFIER;
+       if ((options[i].len != 0) &&
+           ((options[i].len != config->send_options[i].len) ||
+           memcmp(options[i].data, config->send_options[i].data,
+           options[i].len) != 0)) {
+#ifdef DEBUG
+               log_debug("Discarding packet with client-identifier "
+                   "'%s'", pretty_print_option(i, &options[i], 0));
+#endif /* DEBUG */
+               return;
+       }
+
+       type = "<unknown>";
+       handler = NULL;
+
+       i = DHO_DHCP_MESSAGE_TYPE;
+       if (options[i].data != NULL) {
+               /* Always try a DHCP packet, even if a bad option was seen. */
+               switch (options[i].data[0]) {
+               case DHCPOFFER:
+                       handler = dhcpoffer;
+                       type = "DHCPOFFER";
+                       break;
+               case DHCPNAK:
+                       handler = dhcpnak;
+                       type = "DHCPNACK";
+                       break;
+               case DHCPACK:
+                       handler = dhcpack;
+                       type = "DHCPACK";
+                       break;
+               default:
+#ifdef DEBUG
+                       log_debug("Discarding DHCP packet of unknown type "
+                           "(%d)", options[i].data[0]);
+#endif /* DEBUG */
+                       return;
+               }
+       } else if (packet->op == BOOTREPLY) {
+               handler = dhcpoffer;
+               type = "BOOTREPLY";
+       } else {
+#ifdef DEBUG
+               log_debug("Discarding packet which is neither DHCP nor BOOTP");
+#endif /* DEBUG */
+               return;
+       }
+
+       rslt = asprintf(&info, "%s from %s (%s)", type, inet_ntoa(ifrom),
+           ether_ntoa(&hfrom));
+       if (rslt == -1)
+               fatalx("no memory for info string");
+
+       if (handler)
+               (*handler)(ifi, options, info);
+
+       free(info);
 }
 
 void
index 017940a..aa07efc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: options.c,v 1.93 2017/07/06 16:56:52 krw Exp $        */
+/*     $OpenBSD: options.c,v 1.94 2017/07/07 14:53:07 krw Exp $        */
 
 /* DHCP options parsing and reassembly. */
 
@@ -155,12 +155,12 @@ parse_option_buffer(struct option_data *options, unsigned char *buffer,
 }
 
 /*
- * Copy as many options as fit in buflen bytes of buf. Return the
+ * Pack as many options as fit in buflen bytes of buf. Return the
  * offset of the start of the last option copied. A caller can check
  * to see if it's DHO_END to decide if all the options were copied.
  */
 int
-cons_options(unsigned char *buf, int buflen, struct option_data *options)
+pack_options(unsigned char *buf, int buflen, struct option_data *options)
 {
        int ix, incr, length, bufix, code, lastopt = -1;
 
@@ -627,100 +627,36 @@ toobig:
        return (optbuf);
 }
 
-void
-do_packet(struct interface_info *ifi, unsigned int from_port,
-    struct in_addr from, struct ether_addr *hfrom)
+struct option_data *
+unpack_options(struct dhcp_packet *packet)
 {
-       struct dhcp_packet *packet = &ifi->recv_packet;
-       struct option_data options[256];
-       void (*handler)(struct interface_info *, struct option_data *, char *);
-       char *type, *info;
-       int i, rslt, options_valid = 1;
+       static struct option_data options[256];
+       int i;
 
-       memset(options, 0, sizeof(options));
+       for (i = 0; i < 256; i++) {
+               free(options[i].data);
+               options[i].data = NULL;
+               options[i].len = 0;
+       }
 
        if (memcmp(&packet->options, DHCP_OPTIONS_COOKIE, 4) == 0) {
                /* Parse the BOOTP/DHCP options field. */
-               options_valid = parse_option_buffer(options,
-                   &packet->options[4], sizeof(packet->options) - 4);
+               parse_option_buffer(options, &packet->options[4],
+                   sizeof(packet->options) - 4);
 
-               /* Only DHCP packets have overload areas for options. */
-               if (options_valid &&
-                   options[DHO_DHCP_MESSAGE_TYPE].data &&
+               /* DHCP packets can also use overload areas for options. */
+               if (options[DHO_DHCP_MESSAGE_TYPE].data &&
                    options[DHO_DHCP_OPTION_OVERLOAD].data) {
                        if (options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)
-                               options_valid = parse_option_buffer(options,
+                               parse_option_buffer(options,
                                    (unsigned char *)packet->file,
                                    sizeof(packet->file));
-                       if (options_valid &&
-                           options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)
-                               options_valid = parse_option_buffer(options,
+                       if (options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)
+                               parse_option_buffer(options,
                                    (unsigned char *)packet->sname,
                                    sizeof(packet->sname));
                }
-
-               /*
-                * RFC 6842 says if the server sends a client identifier
-                * that doesn't match then the packet must be dropped.
-                */
-               i = DHO_DHCP_CLIENT_IDENTIFIER;
-               if ((options[i].len != 0) &&
-                   ((options[i].len != config->send_options[i].len) ||
-                   memcmp(options[i].data, config->send_options[i].data,
-                   options[i].len) != 0)) {
-#ifdef DEBUG
-                       log_debug("Discarding packet with client-identifier "
-                           "'%s'", pretty_print_option(i, &options[i], 0));
-#endif /* DEBUG */
-                       goto done;
-               }
-       }
-
-       type = "<unknown>";
-       handler = NULL;
-
-       if (options[DHO_DHCP_MESSAGE_TYPE].data) {
-               /* Always try a DHCP packet, even if a bad option was seen. */
-               switch (options[DHO_DHCP_MESSAGE_TYPE].data[0]) {
-               case DHCPOFFER:
-                       handler = dhcpoffer;
-                       type = "DHCPOFFER";
-                       break;
-               case DHCPNAK:
-                       handler = dhcpnak;
-                       type = "DHCPNACK";
-                       break;
-               case DHCPACK:
-                       handler = dhcpack;
-                       type = "DHCPACK";
-                       break;
-               default:
-#ifdef DEBUG
-                       log_debug("Discarding DHCP packet of unknown type "
-                           "(%d)", options[DHO_DHCP_MESSAGE_TYPE].data[0]);
-#endif /* DEBUG */
-                       break;
-               }
-       } else if (options_valid && packet->op == BOOTREPLY) {
-               handler = dhcpoffer;
-               type = "BOOTREPLY";
-       } else {
-#ifdef DEBUG
-               log_debug("Discarding packet which is neither DHCP nor BOOTP");
-#endif /* DEBUG */
        }
 
-       rslt = asprintf(&info, "%s from %s (%s)", type, inet_ntoa(from),
-           ether_ntoa(hfrom));
-       if (rslt == -1)
-               fatalx("no memory for info string");
-
-       if (handler)
-               (*handler)(ifi, options, info);
-
-       free(info);
-
-done:
-       for (i = 0; i < 256; i++)
-               free(options[i].data);
+       return options;
 }