* RFC3319,
* RFC3633,
* RFC3646,
- * draft-ietf-dhc-dhcpv6-opt-timeconfig-03.txt,
- * draft-ietf-dhc-lifetime-00.txt,
+ * RFC3898,
+ * RFC4075,
+ * RFC4242,
+ * RFC4280,
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.34 2004-07-05 07:49:30 itojun Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.37 2008-02-06 10:26:09 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
#define DH6_INFORM_REQ 11
#define DH6_RELAY_FORW 12
#define DH6_RELAY_REPLY 13
+#define DH6_LEASEQUERY 14
+#define DH6_LQ_REPLY 15
/* DHCP6 base packet format */
struct dhcp6 {
#define DH6OPT_CLIENTID 1
#define DH6OPT_SERVERID 2
#define DH6OPT_IA_NA 3
-#define DH6OPT_IA_TMP 4
-#define DH6OPT_IADDR 5
+#define DH6OPT_IA_TA 4
+#define DH6OPT_IA_ADDR 5
#define DH6OPT_ORO 6
#define DH6OPT_PREFERENCE 7
# define DH6OPT_PREF_MAX 255
# define DH6OPT_STCODE_NOTONLINK 4
# define DH6OPT_STCODE_USEMULTICAST 5
# define DH6OPT_STCODE_NOPREFIXAVAIL 6
+# define DH6OPT_STCODE_UNKNOWNQUERYTYPE 7
+# define DH6OPT_STCODE_MALFORMEDQUERY 8
+# define DH6OPT_STCODE_NOTCONFIGURED 9
+# define DH6OPT_STCODE_NOTALLOWED 10
#define DH6OPT_RAPID_COMMIT 14
#define DH6OPT_USER_CLASS 15
#define DH6OPT_VENDOR_CLASS 16
#define DH6OPT_DNSNAME 24
#define DH6OPT_IA_PD 25
#define DH6OPT_IA_PD_PREFIX 26
-
-/*
- * The old prefix delegation option used in the service specification document
- * (200206xx version) by NTT Communications.
- */
-#define DH6OPT_PREFIX_DELEGATION 30
-#define DH6OPT_PREFIX_INFORMATION 31
-#define DH6OPT_PREFIX_REQUEST 32
-
-/*
- * The following one is an unassigned number.
- * We temporarily use values as of KAME snap 20040322.
- */
-#define DH6OPT_NTP_SERVERS 35
-#define DH6OPT_LIFETIME 36
+#define DH6OPT_NIS_SERVERS 27
+#define DH6OPT_NISP_SERVERS 28
+#define DH6OPT_NIS_NAME 29
+#define DH6OPT_NISP_NAME 30
+#define DH6OPT_NTP_SERVERS 31
+#define DH6OPT_LIFETIME 32
+#define DH6OPT_BCMCS_SERVER_D 33
+#define DH6OPT_BCMCS_SERVER_A 34
+#define DH6OPT_GEOCONF_CIVIC 36
+#define DH6OPT_REMOTE_ID 37
+#define DH6OPT_SUBSCRIBER_ID 38
+#define DH6OPT_CLIENT_FQDN 39
+#define DH6OPT_PANA_AGENT 40
+#define DH6OPT_NEW_POSIX_TIMEZONE 41
+#define DH6OPT_NEW_TZDB_TIMEZONE 42
+#define DH6OPT_ERO 43
+#define DH6OPT_LQ_QUERY 44
+#define DH6OPT_CLIENT_DATA 45
+#define DH6OPT_CLT_TIME 46
+#define DH6OPT_LQ_RELAY_DATA 47
+#define DH6OPT_LQ_CLIENT_LINK 48
struct dhcp6opt {
u_int16_t dh6opt_type;
/* type-dependent data follows */
};
-struct dhcp6_ia {
- u_int16_t dh6opt_ia_type;
- u_int16_t dh6opt_ia_len;
- u_int32_t dh6opt_ia_iaid;
- u_int32_t dh6opt_ia_t1;
- u_int32_t dh6opt_ia_t2;
-};
-
-struct dhcp6_ia_prefix {
- u_int16_t dh6opt_ia_prefix_type;
- u_int16_t dh6opt_ia_prefix_len;
- u_int32_t dh6opt_ia_prefix_pltime;
- u_int32_t dh6opt_ia_prefix_vltime;
- u_int8_t dh6opt_ia_prefix_plen;
- struct in6_addr dh6opt_ia_prefix_addr;
-} __attribute__ ((__packed__));
-
-struct dhcp6_auth {
- u_int16_t dh6opt_auth_type;
- u_int16_t dh6opt_auth_len;
- u_int8_t dh6opt_auth_proto;
- u_int8_t dh6opt_auth_alg;
- u_int8_t dh6opt_auth_rdm;
- u_int8_t dh6opt_auth_rdinfo[8];
- /* authentication information follows */
-} __attribute__ ((__packed__));
-
static const char *
dhcp6opt_name(int type)
{
static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */
if (type > 65535)
- return "INVALID option";
+ return "INVALID-option";
switch(type) {
case DH6OPT_CLIENTID:
- return "client ID";
+ return "client-ID";
case DH6OPT_SERVERID:
- return "server ID";
+ return "server-ID";
case DH6OPT_IA_NA:
return "IA_NA";
+ case DH6OPT_IA_TA:
+ return "IA_TA";
+ case DH6OPT_IA_ADDR:
+ return "IA_ADDR";
case DH6OPT_ORO:
- return "option request";
+ return "option-request";
case DH6OPT_PREFERENCE:
return "preference";
case DH6OPT_ELAPSED_TIME:
- return "elapsed time";
+ return "elapsed-time";
case DH6OPT_RELAY_MSG:
- return "relay message";
+ return "relay-message";
case DH6OPT_AUTH:
return "authentication";
case DH6OPT_UNICAST:
- return "server unicast";
+ return "server-unicast";
case DH6OPT_STATUS_CODE:
- return "status code";
+ return "status-code";
case DH6OPT_RAPID_COMMIT:
- return "rapid commit";
+ return "rapid-commit";
case DH6OPT_USER_CLASS:
- return "user class";
+ return "user-class";
case DH6OPT_VENDOR_CLASS:
- return "vendor class";
+ return "vendor-class";
case DH6OPT_VENDOR_OPTS:
- return "vendor-specific info";
+ return "vendor-specific-info";
case DH6OPT_INTERFACE_ID:
- return "interface ID";
+ return "interface-ID";
case DH6OPT_RECONF_MSG:
- return "reconfigure message";
+ return "reconfigure-message";
case DH6OPT_RECONF_ACCEPT:
- return "reconfigure accept";
+ return "reconfigure-accept";
case DH6OPT_SIP_SERVER_D:
- return "SIP servers domain";
+ return "SIP-servers-domain";
case DH6OPT_SIP_SERVER_A:
- return "SIP servers address";
+ return "SIP-servers-address";
case DH6OPT_DNS:
- return "DNS";
+ return "DNS-server";
case DH6OPT_DNSNAME:
- return "DNS name";
- case DH6OPT_PREFIX_DELEGATION:
- return "prefix delegation";
- case DH6OPT_PREFIX_INFORMATION:
- return "prefix information";
+ return "DNS-search-list";
case DH6OPT_IA_PD:
return "IA_PD";
case DH6OPT_IA_PD_PREFIX:
- return "IA_PD prefix";
+ return "IA_PD-prefix";
case DH6OPT_NTP_SERVERS:
- return "NTP Server";
+ return "NTP-server";
case DH6OPT_LIFETIME:
return "lifetime";
+ case DH6OPT_NIS_SERVERS:
+ return "NIS-server";
+ case DH6OPT_NISP_SERVERS:
+ return "NIS+-server";
+ case DH6OPT_NIS_NAME:
+ return "NIS-domain-name";
+ case DH6OPT_NISP_NAME:
+ return "NIS+-domain-name";
+ case DH6OPT_BCMCS_SERVER_D:
+ return "BCMCS-domain-name";
+ case DH6OPT_BCMCS_SERVER_A:
+ return "BCMCS-server";
+ case DH6OPT_GEOCONF_CIVIC:
+ return "Geoconf-Civic";
+ case DH6OPT_REMOTE_ID:
+ return "Remote-ID";
+ case DH6OPT_SUBSCRIBER_ID:
+ return "Subscriber-ID";
+ case DH6OPT_CLIENT_FQDN:
+ return "Client-FQDN";
+ case DH6OPT_PANA_AGENT:
+ return "PANA-agent";
+ case DH6OPT_NEW_POSIX_TIMEZONE:
+ return "POSIX-timezone";
+ case DH6OPT_NEW_TZDB_TIMEZONE:
+ return "POSIX-tz-database";
+ case DH6OPT_ERO:
+ return "Echo-request-option";
+ case DH6OPT_LQ_QUERY:
+ return "Lease-query";
+ case DH6OPT_CLIENT_DATA:
+ return "LQ-client-data";
+ case DH6OPT_CLT_TIME:
+ return "Clt-time";
+ case DH6OPT_LQ_RELAY_DATA:
+ return "LQ-relay-data";
+ case DH6OPT_LQ_CLIENT_LINK:
+ return "LQ-client-link";
default:
snprintf(genstr, sizeof(genstr), "opt_%d", type);
return(genstr);
return "use multicast";
case DH6OPT_STCODE_NOPREFIXAVAIL:
return "no prefixes";
+ case DH6OPT_STCODE_UNKNOWNQUERYTYPE:
+ return "unknown query type";
+ case DH6OPT_STCODE_MALFORMEDQUERY:
+ return "malformed query";
+ case DH6OPT_STCODE_NOTCONFIGURED:
+ return "not configured";
+ case DH6OPT_STCODE_NOTALLOWED:
+ return "not allowed";
default:
snprintf(genstr, sizeof(genstr), "code%d", code);
return(genstr);
size_t i;
u_int16_t opttype;
size_t optlen;
- u_int16_t val16;
- u_int32_t val32;
- struct in6_addr addr6;
- struct dhcp6_ia ia;
- struct dhcp6_ia_prefix ia_prefix;
- struct dhcp6_auth authopt;
- int authinfolen, authrealmlen;
+ u_int8_t auth_proto;
+ u_int authinfolen, authrealmlen;
if (cp == ep)
return;
break;
}
break;
+ case DH6OPT_IA_ADDR:
+ if (optlen < 24) {
+ /*(*/
+ printf(" ?)");
+ break;
+ }
+ tp = (u_char *)(dh6o + 1);
+ printf(" %s", ip6addr_string(&tp[0]));
+ printf(" pltime:%u vltime:%u",
+ EXTRACT_32BITS(&tp[16]),
+ EXTRACT_32BITS(&tp[20]));
+ if (optlen > 24) {
+ /* there are sub-options */
+ dhcp6opt_print(tp + 24, tp + 24 + optlen);
+ }
+ printf(")");
+ break;
case DH6OPT_ORO:
+ case DH6OPT_ERO:
if (optlen % 2) {
printf(" ?)");
break;
}
tp = (u_char *)(dh6o + 1);
for (i = 0; i < optlen; i += 2) {
- u_int16_t opt;
-
- memcpy(&opt, &tp[i], sizeof(opt));
- printf(" %s", dhcp6opt_name(ntohs(opt)));
+ printf(" %s",
+ dhcp6opt_name(EXTRACT_16BITS(&tp[i])));
}
printf(")");
break;
printf(" ?)");
break;
}
- printf(" %d)", *((u_char *)(dh6o + 1) + 1));
+ tp = (u_char *)(dh6o + 1);
+ printf(" %d)", *tp);
break;
case DH6OPT_ELAPSED_TIME:
if (optlen != 2) {
printf(" ?)");
break;
}
- memcpy(&val16, dh6o + 1, sizeof(val16));
- val16 = ntohs(val16);
- printf(" %d)", (int)val16);
+ tp = (u_char *)(dh6o + 1);
+ printf(" %d)", EXTRACT_16BITS(tp));
break;
case DH6OPT_RELAY_MSG:
printf(" (");
- dhcp6_print((const u_char *)(dh6o + 1), optlen);
+ tp = (u_char *)(dh6o + 1);
+ dhcp6_print(tp, optlen);
printf(")");
break;
case DH6OPT_AUTH:
- if (optlen < sizeof(authopt) - sizeof(*dh6o)) {
+ if (optlen < 11) {
printf(" ?)");
break;
}
- memcpy(&authopt, dh6o, sizeof(authopt));
- switch (authopt.dh6opt_auth_proto) {
+ tp = (u_char *)(dh6o + 1);
+ auth_proto = *tp;
+ switch (auth_proto) {
case DH6OPT_AUTHPROTO_DELAYED:
printf(" proto: delayed");
break;
printf(" proto: reconfigure");
break;
default:
- printf(" proto: %d",
- authopt.dh6opt_auth_proto);
+ printf(" proto: %d", auth_proto);
break;
}
- switch (authopt.dh6opt_auth_alg) {
+ tp++;
+ switch (*tp) {
case DH6OPT_AUTHALG_HMACMD5:
/* XXX: may depend on the protocol */
printf(", alg: HMAC-MD5");
break;
default:
- printf(", alg: %d", authopt.dh6opt_auth_alg);
+ printf(", alg: %d", *tp);
break;
}
- switch (authopt.dh6opt_auth_rdm) {
+ tp++;
+ switch (*tp) {
case DH6OPT_AUTHRDM_MONOCOUNTER:
printf(", RDM: mono");
break;
default:
- printf(", RDM: %d", authopt.dh6opt_auth_rdm);
+ printf(", RDM: %d", *tp);
break;
}
- tp = (u_char *)&authopt.dh6opt_auth_rdinfo;
+ tp++;
printf(", RD:");
- for (i = 0; i < 4; i++, tp += sizeof(val16))
+ for (i = 0; i < 4; i++, tp += 2)
printf(" %04x", EXTRACT_16BITS(tp));
/* protocol dependent part */
- tp = (u_char *)dh6o + sizeof(authopt);
- authinfolen =
- optlen + sizeof(*dh6o) - sizeof(authopt);
- switch (authopt.dh6opt_auth_proto) {
+ authinfolen = optlen - 11;
+ switch (auth_proto) {
case DH6OPT_AUTHPROTO_DELAYED:
if (authinfolen == 0)
break;
- authrealmlen = authinfolen - 20;
- if (authrealmlen < 0) {
+ if (authinfolen < 20) {
printf(" ??");
break;
}
+ authrealmlen = authinfolen - 20;
if (authrealmlen > 0) {
printf(", realm: ");
}
printf(")");
break;
case DH6OPT_INTERFACE_ID:
+ case DH6OPT_SUBSCRIBER_ID:
/*
* Since we cannot predict the encoding, print hex dump
* at most 10 characters.
*/
+ tp = (u_char *)(dh6o + 1);
+ printf(" ");
for (i = 0; i < optlen && i < 10; i++)
- printf("%02x", ((u_char *)(dh6o + 1))[i]);
+ printf("%02x", tp[i]);
+ printf("...)");
break;
case DH6OPT_RECONF_MSG:
tp = (u_char *)(dh6o + 1);
case DH6OPT_SIP_SERVER_A:
case DH6OPT_DNS:
case DH6OPT_NTP_SERVERS:
+ case DH6OPT_NIS_SERVERS:
+ case DH6OPT_NISP_SERVERS:
+ case DH6OPT_BCMCS_SERVER_A:
+ case DH6OPT_PANA_AGENT:
+ case DH6OPT_LQ_CLIENT_LINK:
if (optlen % 16) {
printf(" ?)");
break;
printf(" %s", ip6addr_string(&tp[i]));
printf(")");
break;
- case DH6OPT_PREFIX_DELEGATION:
- dhcp6opt_print((u_char *)(dh6o + 1),
- (u_char *)(dh6o + 1) + optlen);
- printf(")");
- break;
- case DH6OPT_PREFIX_INFORMATION:
- if (optlen % 21)
- printf(" ?)");
- memcpy(&addr6, (u_char *)(dh6o + 1) + 5,
- sizeof(addr6));
- printf(" %s/%d", ip6addr_string(&addr6),
- (int)*((u_char *)(dh6o + 1) + 4));
- memcpy(&val32, dh6o + 1, sizeof(val32));
- val32 = ntohl(val32);
- if (val32 == DHCP6_DURATITION_INFINITE)
- printf(" lease-duration: infinite)");
- else
- printf(" lease-duration: %u)", val32);
- break;
case DH6OPT_STATUS_CODE:
if (optlen < 2) {
printf(" ?)");
break;
}
- memcpy(&val16, (u_char *)(dh6o + 1), sizeof(val16));
- val16 = ntohs(val16);
- printf(" %s)", dhcp6stcode(val16));
+ tp = (u_char *)(dh6o + 1);
+ printf(" %s)", dhcp6stcode(EXTRACT_16BITS(&tp[0])));
break;
case DH6OPT_IA_NA:
case DH6OPT_IA_PD:
- if (optlen < sizeof(ia) - 4) {
+ if (optlen < 12) {
printf(" ?)");
break;
}
- memcpy(&ia, (u_char *)dh6o, sizeof(ia));
- ia.dh6opt_ia_iaid = ntohl(ia.dh6opt_ia_iaid);
- ia.dh6opt_ia_t1 = ntohl(ia.dh6opt_ia_t1);
- ia.dh6opt_ia_t2 = ntohl(ia.dh6opt_ia_t2);
- printf(" IAID:%lu T1:%lu T2:%lu",
- (unsigned long)ia.dh6opt_ia_iaid,
- (unsigned long)ia.dh6opt_ia_t1,
- (unsigned long)ia.dh6opt_ia_t2);
- if (optlen > sizeof(ia) - 4) {
+ tp = (u_char *)(dh6o + 1);
+ printf(" IAID:%u T1:%u T2:%u",
+ EXTRACT_32BITS(&tp[0]),
+ EXTRACT_32BITS(&tp[4]),
+ EXTRACT_32BITS(&tp[8]));
+ if (optlen > 12) {
/* there are sub-options */
- dhcp6opt_print((u_char *)dh6o + sizeof(ia),
- (u_char *)(dh6o + 1) + optlen);
+ dhcp6opt_print(tp + 12, tp + 12 + optlen);
+ }
+ printf(")");
+ break;
+ case DH6OPT_IA_TA:
+ if (optlen < 4) {
+ printf(" ?)");
+ break;
+ }
+ tp = (u_char *)(dh6o + 1);
+ printf(" IAID:%u", EXTRACT_32BITS(tp));
+ if (optlen > 4) {
+ /* there are sub-options */
+ dhcp6opt_print(tp + 4, tp + 4 + optlen);
}
printf(")");
break;
case DH6OPT_IA_PD_PREFIX:
- if (optlen < sizeof(ia_prefix) - 4) {
+ if (optlen < 25) {
printf(" ?)");
break;
}
- memcpy(&ia_prefix, (u_char *)dh6o, sizeof(ia_prefix));
- printf(" %s/%d",
- ip6addr_string(&ia_prefix.dh6opt_ia_prefix_addr),
- ia_prefix.dh6opt_ia_prefix_plen);
- ia_prefix.dh6opt_ia_prefix_pltime =
- ntohl(ia_prefix.dh6opt_ia_prefix_pltime);
- ia_prefix.dh6opt_ia_prefix_vltime =
- ntohl(ia_prefix.dh6opt_ia_prefix_vltime);
- printf(" pltime:%lu vltime:%lu",
- (unsigned long)ia_prefix.dh6opt_ia_prefix_pltime,
- (unsigned long)ia_prefix.dh6opt_ia_prefix_vltime);
- if (optlen > sizeof(ia_prefix) - 4) {
+ tp = (u_char *)(dh6o + 1);
+ printf(" %s/%d", ip6addr_string(&tp[9]), tp[8]);
+ printf(" pltime:%u vltime:%u",
+ EXTRACT_32BITS(&tp[0]),
+ EXTRACT_32BITS(&tp[4]));
+ if (optlen > 25) {
/* there are sub-options */
- dhcp6opt_print((u_char *)dh6o +
- sizeof(ia_prefix),
- (u_char *)(dh6o + 1) + optlen);
+ dhcp6opt_print(tp + 25, tp + 25 + optlen);
}
printf(")");
break;
case DH6OPT_LIFETIME:
+ case DH6OPT_CLT_TIME:
if (optlen != 4) {
printf(" ?)");
break;
}
- memcpy(&val32, dh6o + 1, sizeof(val32));
- val32 = ntohl(val32);
- printf(" %d)", (int)val32);
+ tp = (u_char *)(dh6o + 1);
+ printf(" %d)", EXTRACT_32BITS(tp));
+ break;
+ case DH6OPT_REMOTE_ID:
+ if (optlen < 4) {
+ printf(" ?)");
+ break;
+ }
+ tp = (u_char *)(dh6o + 1);
+ printf(" %d ", EXTRACT_32BITS(tp));
+ /*
+ * Print hex dump first 10 characters.
+ */
+ for (i = 4; i < optlen && i < 14; i++)
+ printf("%02x", tp[i]);
+ printf("...)");
+ break;
+ case DH6OPT_LQ_QUERY:
+ if (optlen < 17) {
+ printf(" ?)");
+ break;
+ }
+ tp = (u_char *)(dh6o + 1);
+ switch (*tp) {
+ case 1:
+ printf(" by-address");
+ break;
+ case 2:
+ printf(" by-clientID");
+ break;
+ default:
+ printf(" type_%d", (int)*tp);
+ break;
+ }
+ printf(" %s", ip6addr_string(&tp[1]));
+ if (optlen > 17) {
+ /* there are query-options */
+ dhcp6opt_print(tp + 17, tp + optlen);
+ }
+ printf(")");
+ break;
+ case DH6OPT_CLIENT_DATA:
+ tp = (u_char *)(dh6o + 1);
+ if (optlen > 0) {
+ /* there are encapsulated options */
+ dhcp6opt_print(tp, tp + optlen);
+ }
+ printf(")");
+ break;
+ case DH6OPT_LQ_RELAY_DATA:
+ if (optlen < 16) {
+ printf(" ?)");
+ break;
+ }
+ tp = (u_char *)(dh6o + 1);
+ printf(" %s ", ip6addr_string(&tp[0]));
+ /*
+ * Print hex dump first 10 characters.
+ */
+ for (i = 16; i < optlen && i < 26; i++)
+ printf("%02x", tp[i]);
+ printf("...)");
break;
default:
printf(")");
case DH6_RELAY_REPLY:
name= "relay-reply";
break;
+ case DH6_LEASEQUERY:
+ name= "leasequery";
+ break;
+ case DH6_LQ_REPLY:
+ name= "leasequery-reply";
+ break;
default:
name = NULL;
break;