+
/*
* dhcp.c Functions to send/receive dhcp packets.
*
packet->id = ntohl(magic);
code = dhcp_get_option((dhcp_packet_t *) packet->data,
- packet->data_len, 53);
+ packet->data_len, PW_DHCP_MESSAGE_TYPE);
if (!code) {
fr_strerror_printf("No message-type option was found in the packet");
rad_free(&packet);
uint32_t attr;
/*
+ * Not enough room for the option header, it's a
+ * bad packet.
+ */
+ if ((p + 2) > (data + len)) {
+ fr_pair_list_free(&head);
+ return -1;
+ }
+
+ /*
+ * Not enough room for the option header + data,
+ * it's a bad packet.
+ */
+ if ((p + 2 + p[1]) > (data + len)) {
+ fr_pair_list_free(&head);
+ return -1;
+ }
+
+ /*
* The initial OID string looks like:
* <iana>.0
*
* multiple additional VPs
*/
fr_cursor_init(&cursor, vp_p);
- for (;;) {
- q = memchr(p, '\0', q - p);
+ while (p < end) {
+ q = memchr(p, '\0', end - p);
/* Malformed but recoverable */
if (!q) q = end;
fr_pair_value_bstrncpy(vp, (char const *)p, q - p);
p = q + 1;
+ if (p >= end) break;
+
/* Need another VP for the next round */
- if (p < end) {
- vp = fr_pair_afrom_da(ctx, vp->da);
- if (!vp) {
- fr_pair_list_free(vp_p);
- return -1;
- }
- fr_cursor_insert(&cursor, vp);
- continue;
+ vp = fr_pair_afrom_da(ctx, vp->da);
+ if (!vp) {
+ fr_pair_list_free(vp_p);
+ return -1;
}
- break;
+ fr_cursor_insert(&cursor, vp);
}
}
break;
* Decode the header.
*/
for (i = 0; i < 14; i++) {
- char *q;
vp = fr_pair_make(packet, NULL, dhcp_header_names[i], NULL, T_OP_EQ);
if (!vp) {
break;
case PW_TYPE_STRING:
- vp->vp_strvalue = q = talloc_array(vp, char, dhcp_header_sizes[i] + 1);
- vp->type = VT_DATA;
- memcpy(q, p, dhcp_header_sizes[i]);
- q[dhcp_header_sizes[i]] = '\0';
- vp->vp_length = strlen(vp->vp_strvalue);
- if (vp->vp_length == 0) {
- fr_pair_list_free(&vp);
+ /*
+ * According to RFC 2131, these are null terminated strings.
+ * We don't trust everyone to abide by the RFC, though.
+ */
+ if (*p != '\0') {
+ uint8_t *end;
+ int len;
+ end = memchr(p, '\0', dhcp_header_sizes[i]);
+ len = end ? end - p : dhcp_header_sizes[i];
+ fr_pair_value_bstrncpy(vp, p, len);
}
+ if (vp->vp_length == 0) fr_pair_list_free(&vp);
break;
case PW_TYPE_OCTETS:
/*
* Vendor is "MSFT 98"
*/
- vp = fr_pair_find_by_num(head, 63, DHCP_MAGIC_VENDOR, TAG_ANY);
- if (vp && (strcmp(vp->vp_strvalue, "MSFT 98") == 0)) {
+ vp = fr_pair_find_by_num(head, 60, DHCP_MAGIC_VENDOR, TAG_ANY);
+ if (vp && (vp->vp_length >= 7) && (memcmp(vp->vp_octets, "MSFT 98", 7) == 0)) {
vp = fr_pair_find_by_num(head, 262, DHCP_MAGIC_VENDOR, TAG_ANY);
/*
/*
* DHCP-Message-Type is first, for simplicity.
*/
- if ((my_a->da->attr == 53) && (my_b->da->attr != 53)) return -1;
+ if ((my_a->da->attr == PW_DHCP_MESSAGE_TYPE) && (my_b->da->attr != PW_DHCP_MESSAGE_TYPE)) return -1;
+ if ((my_a->da->attr != PW_DHCP_MESSAGE_TYPE) && (my_b->da->attr == PW_DHCP_MESSAGE_TYPE)) return +1;
/*
* Relay-Agent is last
*/
- if ((my_a->da->attr == 82) && (my_b->da->attr != 82)) return 1;
+ if ((my_a->da->attr == PW_DHCP_OPTION_82) && (my_b->da->attr != PW_DHCP_OPTION_82)) return +1;
+ if ((my_a->da->attr != PW_DHCP_OPTION_82) && (my_b->da->attr == PW_DHCP_OPTION_82)) return -1;
if (my_a->da->attr < my_b->da->attr) return -1;
if (my_a->da->attr > my_b->da->attr) return 1;
if (!vp) return -1;
if (vp->da->vendor != DHCP_MAGIC_VENDOR) goto next; /* not a DHCP option */
- if (vp->da->attr == 53) goto next; /* already done */
+ if (vp->da->attr == PW_DHCP_MESSAGE_TYPE) goto next; /* already done */
if ((vp->da->attr > 255) && (DHCP_BASE_ATTR(vp->da->attr) != PW_DHCP_OPTION_82)) goto next;
if (vp->da->flags.extended) {
packet->id = xid;
code = dhcp_get_option((dhcp_packet_t *) packet->data,
- packet->data_len, 53);
+ packet->data_len, PW_DHCP_MESSAGE_TYPE);
if (!code) {
fr_strerror_printf("No message-type option was found in the packet");
rad_free(&packet);