123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- /*
- * Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- #include <stdio.h>
- #include <unistd.h>
- #include <strings.h>
- #include <string.h>
- #include "perfdhcp.h"
- #include "dkdebug.h"
- static const char * enum_lookup(const char * const table[], size_t size, unsigned index);
- static const char *optionName(int v6, unsigned optnum);
- static void printOption(int v6, unsigned optnum, size_t len, const unsigned char *value);
- static void print_dhcpv4_packet(const struct dhcp_packet *pkt, size_t len);
- static void print_dhcpv6_packet(const struct dhcpv6_packet *pkt, size_t len);
- typedef enum { T_UNK, T_STRING, T_PERIOD, T_IPADDR, T_MTYPE, T_STATUS } opt_type;
- struct dhcp_option_desc {
- char *name;
- opt_type type;
- };
- static struct dhcp_option_desc option_desc[] = {
- [DHO_PAD] = { "PAD", T_UNK },
- [DHO_SUBNET_MASK] = { "SUBNET_MASK", T_UNK },
- [DHO_TIME_OFFSET] = { "TIME_OFFSET", T_PERIOD },
- [DHO_ROUTERS] = { "ROUTERS", T_IPADDR },
- [DHO_TIME_SERVERS] = { "TIME_SERVERS", T_UNK },
- [DHO_NAME_SERVERS] = { "NAME_SERVERS", T_UNK },
- [DHO_DOMAIN_NAME_SERVERS] = { "DOMAIN_NAME_SERVERS", T_IPADDR },
- [DHO_LOG_SERVERS] = { "LOG_SERVERS", T_UNK },
- [DHO_COOKIE_SERVERS] = { "COOKIE_SERVERS", T_UNK },
- [DHO_LPR_SERVERS] = { "LPR_SERVERS", T_IPADDR },
- [DHO_IMPRESS_SERVERS] = { "IMPRESS_SERVERS", T_UNK },
- [DHO_RESOURCE_LOCATION_SERVERS] = { "RESOURCE_LOCATION_SERVERS", T_UNK },
- [DHO_HOST_NAME] = { "HOST_NAME", T_UNK },
- [DHO_BOOT_SIZE] = { "BOOT_SIZE", T_UNK },
- [DHO_MERIT_DUMP] = { "MERIT_DUMP", T_UNK },
- [DHO_DOMAIN_NAME] = { "DOMAIN_NAME", T_STRING },
- [DHO_SWAP_SERVER] = { "SWAP_SERVER", T_UNK },
- [DHO_ROOT_PATH] = { "ROOT_PATH", T_UNK },
- [DHO_EXTENSIONS_PATH] = { "EXTENSIONS_PATH", T_UNK },
- [DHO_IP_FORWARDING] = { "IP_FORWARDING", T_UNK },
- [DHO_NON_LOCAL_SOURCE_ROUTING] = { "NON_LOCAL_SOURCE_ROUTING", T_UNK },
- [DHO_POLICY_FILTER] = { "POLICY_FILTER", T_UNK },
- [DHO_MAX_DGRAM_REASSEMBLY] = { "MAX_DGRAM_REASSEMBLY", T_UNK },
- [DHO_DEFAULT_IP_TTL] = { "DEFAULT_IP_TTL", T_UNK },
- [DHO_PATH_MTU_AGING_TIMEOUT] = { "PATH_MTU_AGING_TIMEOUT", T_UNK },
- [DHO_PATH_MTU_PLATEAU_TABLE] = { "PATH_MTU_PLATEAU_TABLE", T_UNK },
- [DHO_INTERFACE_MTU] = { "INTERFACE_MTU", T_UNK },
- [DHO_ALL_SUBNETS_LOCAL] = { "ALL_SUBNETS_LOCAL", T_UNK },
- [DHO_BROADCAST_ADDRESS] = { "BROADCAST_ADDRESS", T_UNK },
- [DHO_PERFORM_MASK_DISCOVERY] = { "PERFORM_MASK_DISCOVERY", T_UNK },
- [DHO_MASK_SUPPLIER] = { "MASK_SUPPLIER", T_UNK },
- [DHO_ROUTER_DISCOVERY] = { "ROUTER_DISCOVERY", T_UNK },
- [DHO_ROUTER_SOLICITATION_ADDRESS] = { "ROUTER_SOLICITATION_ADDRESS", T_UNK },
- [DHO_STATIC_ROUTES] = { "STATIC_ROUTES", T_UNK },
- [DHO_TRAILER_ENCAPSULATION] = { "TRAILER_ENCAPSULATION", T_UNK },
- [DHO_ARP_CACHE_TIMEOUT] = { "ARP_CACHE_TIMEOUT", T_UNK },
- [DHO_IEEE802_3_ENCAPSULATION] = { "IEEE802_3_ENCAPSULATION", T_UNK },
- [DHO_DEFAULT_TCP_TTL] = { "DEFAULT_TCP_TTL", T_UNK },
- [DHO_TCP_KEEPALIVE_INTERVAL] = { "TCP_KEEPALIVE_INTERVAL", T_UNK },
- [DHO_TCP_KEEPALIVE_GARBAGE] = { "TCP_KEEPALIVE_GARBAGE", T_UNK },
- [DHO_NIS_DOMAIN] = { "NIS_DOMAIN", T_UNK },
- [DHO_NIS_SERVERS] = { "NIS_SERVERS", T_UNK },
- [DHO_NTP_SERVERS] = { "NTP_SERVERS", T_IPADDR },
- [DHO_VENDOR_ENCAPSULATED_OPTIONS] = { "VENDOR_ENCAPSULATED_OPTIONS", T_UNK },
- [DHO_NETBIOS_NAME_SERVERS] = { "NETBIOS_NAME_SERVERS", T_UNK },
- [DHO_NETBIOS_DD_SERVER] = { "NETBIOS_DD_SERVER", T_UNK },
- [DHO_NETBIOS_NODE_TYPE] = { "NETBIOS_NODE_TYPE", T_UNK },
- [DHO_NETBIOS_SCOPE] = { "NETBIOS_SCOPE", T_UNK },
- [DHO_FONT_SERVERS] = { "FONT_SERVERS", T_UNK },
- [DHO_X_DISPLAY_MANAGER] = { "X_DISPLAY_MANAGER", T_UNK },
- [DHO_DHCP_REQUESTED_ADDRESS] = { "DHCP_REQUESTED_ADDRESS", T_IPADDR },
- [DHO_DHCP_LEASE_TIME] = { "DHCP_LEASE_TIME", T_PERIOD },
- [DHO_DHCP_OPTION_OVERLOAD] = { "DHCP_OPTION_OVERLOAD", T_UNK },
- [DHO_DHCP_MESSAGE_TYPE] = { "DHCP_MESSAGE_TYPE", T_MTYPE },
- [DHO_DHCP_SERVER_IDENTIFIER] = { "DHCP_SERVER_IDENTIFIER", T_UNK },
- [DHO_DHCP_PARAMETER_REQUEST_LIST] = { "DHCP_PARAMETER_REQUEST_LIST", T_UNK },
- [DHO_DHCP_MESSAGE] = { "DHCP_MESSAGE", T_UNK },
- [DHO_DHCP_MAX_MESSAGE_SIZE] = { "DHCP_MAX_MESSAGE_SIZE", T_UNK },
- [DHO_DHCP_RENEWAL_TIME] = { "DHCP_RENEWAL_TIME", T_UNK },
- [DHO_DHCP_REBINDING_TIME] = { "DHCP_REBINDING_TIME", T_UNK },
- [DHO_VENDOR_CLASS_IDENTIFIER] = { "VENDOR_CLASS_IDENTIFIER", T_UNK },
- [DHO_DHCP_CLIENT_IDENTIFIER] = { "DHCP_CLIENT_IDENTIFIER", T_UNK },
- [DHO_NWIP_DOMAIN_NAME] = { "NWIP_DOMAIN_NAME", T_UNK },
- [DHO_NWIP_SUBOPTIONS] = { "NWIP_SUBOPTIONS", T_UNK },
- [DHO_USER_CLASS] = { "USER_CLASS", T_UNK },
- [DHO_USER_CLASS] = { "USER_CLASS", T_UNK },
- [DHO_FQDN] = { "FQDN", T_UNK },
- [DHO_DHCP_AGENT_OPTIONS] = { "DHCP_AGENT_OPTIONS", T_UNK },
- [DHO_AUTHENTICATE] = { "AUTHENTICATE", T_UNK },
- [DHO_CLIENT_LAST_TRANSACTION_TIME] = { "CLIENT_LAST_TRANSACTION_TIME", T_UNK },
- [DHO_ASSOCIATED_IP] = { "ASSOCIATED_IP", T_UNK },
- [DHO_SUBNET_SELECTION] = { "SUBNET_SELECTION", T_UNK },
- [DHO_DOMAIN_SEARCH] = { "DOMAIN_SEARCH", T_UNK },
- [DHO_VIVCO_SUBOPTIONS] = { "VIVCO_SUBOPTIONS", T_UNK },
- [DHO_VIVSO_SUBOPTIONS] = { "VIVSO_SUBOPTIONS", T_UNK },
- [DHO_END] = { "END", T_UNK },
- [64] = { "NIS Domain", T_UNK },
- [65] = { "NIS Servers", T_UNK },
- [66] = { "TFTP Server", T_UNK },
- [67] = { "Bootfile name", T_UNK },
- [68] = { "Mobile IP Home Agent", T_UNK },
- [69] = { "SMTP Server", T_IPADDR },
- [70] = { "POP Server", T_IPADDR },
- [71] = { "NNTP Server", T_IPADDR },
- [72] = { "WWW Server", T_IPADDR },
- [73] = { "Finger Server", T_IPADDR },
- [74] = { "IRC Server", T_IPADDR },
- [75] = { "StreetTalk Server", T_IPADDR },
- [76] = { "StreetTalk Directory Assistance Server", T_IPADDR }
- };
- static const char * const message_types[] = {
- [DHCPDISCOVER] = "DHCPDISCOVER",
- [DHCPOFFER] = "DHCPOFFER",
- [DHCPREQUEST] = "DHCPREQUEST",
- [DHCPDECLINE] = "DHCPDECLINE",
- [DHCPACK] = "DHCPACK",
- [DHCPNAK] = "DHCPNAK",
- [DHCPRELEASE] = "DHCPRELEASE",
- [DHCPINFORM] = "DHCPINFORM",
- [DHCPLEASEQUERY] = "DHCPLEASEQUERY",
- [DHCPLEASEUNASSIGNED] = "DHCPLEASEUNASSIGNED",
- [DHCPLEASEUNKNOWN] = "DHCPLEASEUNKNOWN",
- [DHCPLEASEACTIVE] = "DHCPLEASEACTIVE"
- };
- static struct dhcp_option_desc option6_desc[] = {
- [D6O_CLIENTID] = { "D6O_CLIENTID", T_UNK },
- [D6O_SERVERID] = { "D6O_SERVERID", T_UNK },
- [D6O_IA_NA] = { "D6O_IA_NA", T_UNK },
- [D6O_IA_TA] = { "D6O_IA_TA", T_UNK },
- [D6O_IAADDR] = { "D6O_IAADDR", T_UNK },
- [D6O_ORO] = { "D6O_ORO", T_UNK },
- [D6O_PREFERENCE] = { "D6O_PREFERENCE", T_UNK },
- [D6O_ELAPSED_TIME] = { "D6O_ELAPSED_TIME", T_PERIOD },
- [D6O_RELAY_MSG] = { "D6O_RELAY_MSG", T_UNK },
- [D6O_AUTH] = { "D6O_AUTH", T_UNK },
- [D6O_UNICAST] = { "D6O_UNICAST", T_UNK },
- [D6O_STATUS_CODE] = { "D6O_STATUS_CODE", T_STATUS },
- [D6O_RAPID_COMMIT] = { "D6O_RAPID_COMMIT", T_UNK },
- [D6O_USER_CLASS] = { "D6O_USER_CLASS", T_UNK },
- [D6O_VENDOR_CLASS] = { "D6O_VENDOR_CLASS", T_UNK },
- [D6O_VENDOR_OPTS] = { "D6O_VENDOR_OPTS", T_UNK },
- [D6O_INTERFACE_ID] = { "D6O_INTERFACE_ID", T_UNK },
- [D6O_RECONF_MSG] = { "D6O_RECONF_MSG", T_UNK },
- [D6O_RECONF_ACCEPT] = { "D6O_RECONF_ACCEPT", T_UNK },
- [D6O_SIP_SERVERS_DNS] = { "D6O_SIP_SERVERS_DNS", T_UNK },
- [D6O_SIP_SERVERS_ADDR] = { "D6O_SIP_SERVERS_ADDR", T_UNK },
- [D6O_NAME_SERVERS] = { "D6O_NAME_SERVERS", T_IPADDR },
- [D6O_DOMAIN_SEARCH] = { "D6O_DOMAIN_SEARCH", T_UNK },
- [D6O_IA_PD] = { "D6O_IA_PD", T_UNK },
- [D6O_IAPREFIX] = { "D6O_IAPREFIX", T_UNK },
- [D6O_NIS_SERVERS] = { "D6O_NIS_SERVERS", T_UNK },
- [D6O_NISP_SERVERS] = { "D6O_NISP_SERVERS", T_UNK },
- [D6O_NIS_DOMAIN_NAME] = { "D6O_NIS_DOMAIN_NAME", T_UNK },
- [D6O_NISP_DOMAIN_NAME] = { "D6O_NISP_DOMAIN_NAME", T_UNK },
- [D6O_SNTP_SERVERS] = { "D6O_SNTP_SERVERS", T_UNK },
- [D6O_INFORMATION_REFRESH_TIME] = { "D6O_INFORMATION_REFRESH_TIME", T_UNK },
- [D6O_BCMCS_SERVER_D] = { "D6O_BCMCS_SERVER_D", T_UNK },
- [D6O_BCMCS_SERVER_A] = { "D6O_BCMCS_SERVER_A", T_UNK },
- [D6O_GEOCONF_CIVIC] = { "D6O_GEOCONF_CIVIC", T_UNK },
- [D6O_REMOTE_ID] = { "D6O_REMOTE_ID", T_UNK },
- [D6O_SUBSCRIBER_ID] = { "D6O_SUBSCRIBER_ID", T_UNK },
- [D6O_CLIENT_FQDN] = { "D6O_CLIENT_FQDN", T_UNK },
- [D6O_PANA_AGENT] = { "D6O_PANA_AGENT", T_UNK },
- [D6O_NEW_POSIX_TIMEZONE] = { "D6O_NEW_POSIX_TIMEZONE", T_UNK },
- [D6O_NEW_TZDB_TIMEZONE] = { "D6O_NEW_TZDB_TIMEZONE", T_UNK },
- [D6O_ERO] = { "D6O_ERO", T_UNK },
- [D6O_LQ_QUERY] = { "D6O_LQ_QUERY", T_UNK },
- [D6O_CLIENT_DATA] = { "D6O_CLIENT_DATA", T_UNK },
- [D6O_CLT_TIME] = { "D6O_CLT_TIME", T_UNK },
- [D6O_LQ_RELAY_DATA] = { "D6O_LQ_RELAY_DATA", T_UNK },
- [D6O_LQ_CLIENT_LINK] = { "D6O_LQ_CLIENT_LINK", T_UNK }
- };
- static const char * const message6_types[] = {
- [DHCPV6_SOLICIT] = "DHCPV6_SOLICIT",
- [DHCPV6_ADVERTISE] = "DHCPV6_ADVERTISE",
- [DHCPV6_REQUEST] = "DHCPV6_REQUEST",
- [DHCPV6_CONFIRM] = "DHCPV6_CONFIRM",
- [DHCPV6_RENEW] = "DHCPV6_RENEW",
- [DHCPV6_REBIND] = "DHCPV6_REBIND",
- [DHCPV6_REPLY] = "DHCPV6_REPLY",
- [DHCPV6_RELEASE] = "DHCPV6_RELEASE",
- [DHCPV6_DECLINE] = "DHCPV6_DECLINE",
- [DHCPV6_RECONFIGURE] = "DHCPV6_RECONFIGURE",
- [DHCPV6_INFORMATION_REQUEST] = "DHCPV6_INFORMATION_REQUEST",
- [DHCPV6_RELAY_FORW] = "DHCPV6_RELAY_FORW",
- [DHCPV6_RELAY_REPL] = "DHCPV6_RELAY_REPL",
- [DHCPV6_LEASEQUERY] = "DHCPV6_LEASEQUERY",
- [DHCPV6_LEASEQUERY_REPLY] = "DHCPV6_LEASEQUERY_REPLY"
- };
- static const char * const status_codes[] = {
- [STATUS_Success] = "Success",
- [STATUS_UnspecFail] = "UnspecFail",
- [STATUS_NoAddrsAvail] = "NoAddrsAvail",
- [STATUS_NoBinding] = "NoBinding",
- [STATUS_NotOnLink] = "NotOnLink",
- [STATUS_UseMulticast] = "UseMulticast",
- [STATUS_NoPrefixAvail] = "NoPrefixAvail",
- [STATUS_UnknownQueryType] = "UnknownQueryType",
- [STATUS_MalformedQuery] = "MalformedQuery",
- [STATUS_NotConfigured] = "NotConfigured",
- [STATUS_NotAllowed] = "NotAllowed",
- };
- void
- print_dhcp_packet(int v6, const void *pkt, size_t len)
- {
- if (v6)
- print_dhcpv6_packet((struct dhcpv6_packet *)pkt, len);
- else
- print_dhcpv4_packet((struct dhcp_packet *)pkt, len);
- if (dk_set(DK_PACKET)) {
- unsigned i;
- fprintf(stderr, "Raw packet contents (%zu bytes):\n", len);
- for (i = 0; i < len; i++)
- fprintf(stderr, "%02x ", ((unsigned char *)pkt)[i]);
- fputc('\n', stderr);
- }
- }
- /*
- * Note: Not reentrant
- */
- static const char *
- enum_lookup(const char * const table[], size_t size, unsigned index)
- {
- static char numbuf[10];
- if (index < (size / sizeof(char *)) && table[index] != NULL)
- return table[index];
- else {
- snprintf(numbuf, sizeof(numbuf), "%u", index);
- return numbuf;
- }
- }
- /*
- * Note: Not reentrant
- */
- static const char *
- optionName(int v6, unsigned optnum)
- {
- static char numbuf[16];
- unsigned maxOpt = ((v6 ? sizeof(option6_desc) : sizeof(option_desc)) - 1) /
- sizeof(struct dhcp_option_desc);
- struct dhcp_option_desc *descTable;
- if (optnum > maxOpt) {
- snprintf(numbuf, sizeof(numbuf), "invalid (%u)", optnum);
- return numbuf;
- }
- descTable = v6 ? option6_desc : option_desc;
- if (descTable[optnum].name == NULL) {
- snprintf(numbuf, sizeof(numbuf), "%u", optnum);
- return numbuf;
- }
- else
- return descTable[optnum].name;
- }
- /*
- *
- * Output variables: None
- */
- static void
- printOption(int v6, unsigned optnum, size_t len, const unsigned char *value)
- {
- struct dhcp_option_desc *descTable = v6 ? option6_desc : option_desc;
- char buf[ADDR_NAME_BUFSIZE];
- unsigned i;
- unsigned maxOpt = ((v6 ? sizeof(option6_desc) : sizeof(option_desc)) - 1) / sizeof(struct dhcp_option_desc);
- unsigned statusCode;
- fprintf(stderr, "Option %s (%d) length %zu value ", optionName(v6, optnum), optnum, len);
- switch (optnum > maxOpt ? T_UNK : descTable[optnum].type) {
- case T_STRING:
- fprintf(stderr, "\"%.*s\"\n", (int) len, value);
- break;
- case T_PERIOD:
- fprintf(stderr, "%d seconds\n", ntohl(*(int *)value));
- break;
- case T_MTYPE:
- fprintf(stderr, "%s\n", enum_lookup(message_types, sizeof(message_types), *value));
- break;
- case T_IPADDR:
- for (i = 0; len - i >= 4; i += 4)
- fprintf(stderr, "%s%s", addrtoa(AF_INET, (struct in_addr *)(value+i), buf), len - i > 4 ? ", " : "\n");
- break;
- case T_STATUS:
- statusCode = ntohs(*(uint16_t *)value);
- fprintf(stderr, "%s: %*.*s\n",
- enum_lookup(status_codes, sizeof(status_codes), statusCode),
- (int)len - 2, (int)len - 2, value + 2);
- break;
- default:
- for (i = 0; i < len; i++)
- fprintf(stderr, "%02x", value[i]);
- fputc('\n', stderr);
- break;
- }
- }
- static void
- print_dhcpv4_packet(const struct dhcp_packet *pkt, size_t msglen)
- {
- int i;
- const unsigned char *p;
- aaddr_buf buf1, buf2, buf3, buf4;
- fprintf(stderr,
- "opcode %u\n\
- htype %u\n\
- hlen %u\n\
- hops %u\n\
- xid 0x%0x\n\
- secs %u\n\
- flags 0x%x\n\
- ciaddr %s\n\
- yiaddr %s\n\
- siaddr %s\n\
- giaddr %s\n\
- chaddr ",
- pkt->op,
- pkt->htype,
- pkt->hlen,
- pkt->hops,
- pkt->xid,
- pkt->secs,
- pkt->flags,
- addrtoa(AF_INET, &pkt->ciaddr, buf1),
- addrtoa(AF_INET, &pkt->yiaddr, buf2),
- addrtoa(AF_INET, &pkt->siaddr, buf3),
- addrtoa(AF_INET, &pkt->giaddr, buf4));
- for (i = 0; i < pkt->hlen; i++)
- fprintf(stderr, "%02x", pkt->chaddr[i]);
- fputc('\n', stderr);
- fprintf(stderr, "magic 0x%x\n", *(unsigned int *)&pkt->options);
- p = &pkt->options[4];
- while ((unsigned) (p - (unsigned char *)pkt) < msglen && *p != DHO_END) {
- if (*p == DHO_PAD) {
- fprintf(stderr, "Option PAD\n");
- p++;
- }
- else {
- unsigned optnum = *p++;
- size_t len = *p++;
- printOption(0, optnum, len, p);
- p += len;
- }
- }
- }
- static void
- print_dhcpv6_packet(const struct dhcpv6_packet *pkt, size_t msglen)
- {
- int i;
- const unsigned char *p;
- struct v6_option *opt;
- fprintf(stderr, "msgtype\t%s\ntid\t", enum_lookup(message6_types, sizeof(message6_types), pkt->msg_type));
- for (i = 0; i <= 2; i++)
- fprintf(stderr, "%02x", pkt->transaction_id[i]);
- fputc('\n', stderr);
- p = pkt->options;
- opt = (struct v6_option *)p;
- while ((unsigned) (p - (unsigned char *)pkt) < msglen && opt->code != 0) {
- unsigned optlen = ntohs(opt->len);
- printOption(1, ntohs(opt->code), optlen, &opt->value);
- p += 4 + optlen;
- opt = (struct v6_option *)p;
- }
- }
|