-/* $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>
* 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.");
* 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.");
* 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.");
-/* $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>
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;
-/* $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>
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++;
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
-/* $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. */
}
/*
- * 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;
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;
}