/* * Parse a DHCP response packet * Returns: * 0 = Unexpected packet, not parsed * 2 = DHCPOFFER (from dhcp_proto.h) * 5 = DHCPACK * 6 = DHCPNACK */ static int dhcp_parse(struct netdev *dev, struct bootp_hdr *hdr, uint8_t *exts, int extlen) { uint8_t type = 0; uint32_t serverid = INADDR_NONE; int ret = 0; if (extlen >= 4 && exts[0] == 99 && exts[1] == 130 && exts[2] == 83 && exts[3] == 99) { uint8_t *ext; for (ext = exts + 4; ext - exts < extlen;) { uint8_t len, *opt = ext++; if (*opt == 0) continue; len = *ext++; ext += len; if (*opt == 53) type = opt[2]; if (*opt == 54) memcpy(&serverid, opt + 2, 4); } } switch (type) { case DHCPOFFER: ret = bootp_parse(dev, hdr, exts, extlen) ? DHCPOFFER : 0; if (ret == DHCPOFFER && serverid != INADDR_NONE) dev->serverid = serverid; dprintf("\n dhcp offer\n"); break; case DHCPACK: ret = bootp_parse(dev, hdr, exts, extlen) ? DHCPACK : 0; dprintf("\n dhcp ack\n"); break; case DHCPNAK: ret = DHCPNAK; dprintf("\n dhcp nak\n"); break; } return ret; }
/* * Parse a DHCP response packet * Returns: * 0 = Unexpected packet, not parsed * 2 = DHCPOFFER (from dhcp_proto.h) * 5 = DHCPACK * 6 = DHCPNACK */ static int dhcp_parse(struct netdev *dev, struct bootp_hdr *hdr, uint8_t *exts, int extlen) { uint8_t type = 0; uint32_t serverid = INADDR_NONE; uint32_t leasetime = 0; int ret = 0; if (extlen >= 4 && exts[0] == 99 && exts[1] == 130 && exts[2] == 83 && exts[3] == 99) { uint8_t *ext; for (ext = exts + 4; ext - exts < extlen;) { int len; uint8_t opt = *ext++; if (opt == 0) continue; else if (opt == 255) break; if (ext - exts >= extlen) break; len = *ext++; if (ext - exts + len > extlen) break; switch (opt) { case 51: /* IP Address Lease Time */ if (len == 4) leasetime = ntohl(*(uint32_t *)ext); break; case 53: /* DHCP Message Type */ if (len == 1) type = *ext; break; case 54: /* Server Identifier */ if (len == 4) memcpy(&serverid, ext, 4); break; } ext += len; } } switch (type) { case DHCPOFFER: ret = bootp_parse(dev, hdr, exts, extlen) ? DHCPOFFER : 0; if (ret == DHCPOFFER && serverid != INADDR_NONE) dev->serverid = serverid; dprintf("\n dhcp offer\n"); break; case DHCPACK: dev->dhcpleasetime = leasetime; ret = bootp_parse(dev, hdr, exts, extlen) ? DHCPACK : 0; dprintf("\n dhcp ack\n"); break; case DHCPNAK: ret = DHCPNAK; dprintf("\n dhcp nak\n"); break; } return ret; }