/* * Copyright (C) 1998 and 1999 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char rcsid[] = "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.3 1999/12/22 06:27:20 itojun Exp $"; #endif #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #if __STDC__ struct mbuf; struct rtentry; #endif #include #include #include #ifdef HAVE_MEMORY_H #include #endif #include #include #include #include "interface.h" #include "addrtoname.h" #include "dhcp6.h" #include "dhcp6opt.h" #if 0 static void dhcp6opttab_init __P((void)); static struct dhcp6_opt *dhcp6opttab_byname __P((char *)); #endif static struct dhcp6_opt *dhcp6opttab_bycode __P((u_int)); static char tstr[] = " [|dhcp6]"; static struct dhcp6_opt dh6opttab[] = { /* IP Address Extension */ { 1, OL6_N, "IP Address", OT6_NONE, }, /* General Extension */ { 2, 4, "Time Offset", OT6_NUM, }, { 3, OL6_N, "IEEE 1003.1 POSIX Timezone", OT6_STR, }, { 6, OL6_16N, "Domain Name Server", OT6_V6, }, { 10, OL6_N, "Domain Name", OT6_STR, }, /* Application and Service Parameters */ { 16, OL6_N, "Directory Agent", OT6_NONE, }, { 17, OL6_N, "Service Scope" , OT6_NONE, }, { 18, OL6_16N, "Network Time Protocol Servers", OT6_V6, }, { 19, OL6_N, "NIS Domain", OT6_STR, }, { 20, OL6_16N, "NIS Servers", OT6_V6, }, { 21, OL6_N, "NIS+ Domain", OT6_STR, }, { 22, OL6_16N, "NIS+ Servers", OT6_V6, }, /* TCP Parameters */ { 32, 4, "TCP Keepalive Interval", OT6_NUM, }, /* DHCPv6 Extensions */ { 40, 4, "Maximum DHCPv6 Message Size", OT6_NUM, }, { 41, OL6_N, "DHCP Retransmission and Configuration Parameter", OT6_NONE, }, { 48, OL6_N, "Platform Specific Information", OT6_NONE, }, { 49, OL6_N, "Platform Class Identifier", OT6_STR, }, { 64, OL6_N, "Class Identifier", OT6_STR, }, { 66, 16, "Reconfigure Multicast Address", OT6_V6, }, { 67, 16, "Renumber DHCPv6 Server Address", OT6_V6, }, { 68, OL6_N, "DHCP Relay ICMP Error Message", OT6_NONE, }, { 84, OL6_N, "Client-Server Authentication", OT6_NONE, }, { 85, 4, "Client Key Selection", OT6_NUM, }, /* End Extension */ { 65536, OL6_Z, "End", OT6_NONE, }, { 0 }, }; #if 0 static struct dhcp6_opt *dh6o_pad; static struct dhcp6_opt *dh6o_end; static void dhcp6opttab_init() { dh6o_pad = dhcp6opttab_bycode(0); dh6o_end = dhcp6opttab_bycode(65536); } #endif #if 0 static struct dhcp6_opt * dhcp6opttab_byname(name) char *name; { struct dhcp6_opt *p; for (p = dh6opttab; p->code; p++) if (strcmp(name, p->name) == 0) return p; return NULL; } #endif static struct dhcp6_opt * dhcp6opttab_bycode(code) u_int code; { struct dhcp6_opt *p; for (p = dh6opttab; p->code; p++) if (p->code == code) return p; return NULL; } static void dhcp6ext_print(u_char *cp, u_char *ep) { u_int16_t code, len; struct dhcp6_opt *p; char buf[BUFSIZ]; int i; if (cp == ep) return; printf(" "); while (cp < ep) { code = ntohs(*(u_int16_t *)&cp[0]); if (code != 65535) len = ntohs(*(u_int16_t *)&cp[2]); else len = 0; p = dhcp6opttab_bycode(code); if (p == NULL) { printf("(unknown, len=%d)", len); cp += len + 4; continue; } /* sanity check on length */ switch (p->len) { case OL6_N: break; case OL6_16N: if (len % 16 != 0) goto trunc; break; case OL6_Z: if (len != 0) goto trunc; break; default: if (len != p->len) goto trunc; break; } if (cp + 4 + len > ep) { printf("[|%s]", p->name); return; } printf("(%s, ", p->name); switch (p->type) { case OT6_V6: for (i = 0; i < len; i += 16) { inet_ntop(AF_INET6, &cp[4 + i], buf, sizeof(buf)); if (i != 0) printf(","); printf("%s", buf); } break; case OT6_STR: memset(&buf, 0, sizeof(buf)); strncpy(buf, &cp[4], len); printf("%s", buf); break; case OT6_NUM: printf("%d", (u_int32_t)ntohl(*(u_int32_t *)&cp[4])); break; default: for (i = 0; i < len; i++) printf("%02x", cp[4 + i] & 0xff); } printf(")"); cp += len + 4; } return; trunc: printf("[|dhcp6ext]"); } /* * Print dhcp6 requests */ void dhcp6_print(register const u_char *cp, u_int length, u_short sport, u_short dport) { union dhcp6 *dh6; u_char *ep; u_char *extp; printf("dhcp6"); ep = (u_char *)snapend; dh6 = (union dhcp6 *)cp; TCHECK(dh6->dh6_msgtype); switch (dh6->dh6_msgtype) { case DH6_SOLICIT: if (vflag && TTEST(dh6->dh6_sol.dh6sol_relayaddr)) { printf(" solicit("); if ((dh6->dh6_sol.dh6sol_flags & DH6SOL_CLOSE) != 0) printf("C"); if (dh6->dh6_sol.dh6sol_flags != 0) printf(" "); printf("cliaddr=%s", ip6addr_string(&dh6->dh6_sol.dh6sol_cliaddr)); printf(" relayaddr=%s", ip6addr_string(&dh6->dh6_sol.dh6sol_relayaddr)); printf(")"); } else printf(" solicit"); break; case DH6_ADVERT: if (!(vflag && TTEST(dh6->dh6_adv.dh6adv_serveraddr))) { printf(" advert"); break; } printf(" advert("); if ((dh6->dh6_adv.dh6adv_flags & DH6ADV_SERVPRESENT) != 0) printf("S"); if (dh6->dh6_adv.dh6adv_flags != 0) printf(" "); printf("pref=%u", dh6->dh6_adv.dh6adv_pref); printf(" cliaddr=%s", ip6addr_string(&dh6->dh6_adv.dh6adv_cliaddr)); printf(" relayaddr=%s", ip6addr_string(&dh6->dh6_adv.dh6adv_relayaddr)); printf(" servaddr=%s", ip6addr_string(&dh6->dh6_adv.dh6adv_serveraddr)); extp = (u_char *)((&dh6->dh6_adv) + 1); dhcp6ext_print(extp, ep); printf(")"); break; case DH6_REQUEST: if (!(vflag && TTEST(dh6->dh6_req.dh6req_relayaddr))) { printf(" request"); break; } printf(" request("); if ((dh6->dh6_req.dh6req_flags & DH6REQ_CLOSE) != 0) printf("C"); if ((dh6->dh6_req.dh6req_flags & DH6REQ_SERVPRESENT) != 0) printf("S"); if ((dh6->dh6_req.dh6req_flags & DH6REQ_REBOOT) != 0) printf("R"); if (dh6->dh6_req.dh6req_flags != 0) printf(" "); printf("xid=0x%04x", dh6->dh6_req.dh6req_xid); printf(" cliaddr=%s", ip6addr_string(&dh6->dh6_req.dh6req_cliaddr)); printf(" relayaddr=%s", ip6addr_string(&dh6->dh6_req.dh6req_relayaddr)); extp = (char *)((&dh6->dh6_req) + 1); if ((dh6->dh6_req.dh6req_flags & DH6REQ_SERVPRESENT) != 0) { printf(" servaddr=%s", ip6addr_string(extp)); extp += 16; } dhcp6ext_print(extp, ep); printf(")"); break; case DH6_REPLY: if (!(vflag && TTEST(dh6->dh6_rep.dh6rep_xid))) { printf(" reply"); break; } printf(" reply("); if ((dh6->dh6_rep.dh6rep_flagandstat & DH6REP_CLIPRESENT) != 0) printf("C"); if (dh6->dh6_rep.dh6rep_flagandstat != 0) printf(" "); printf("stat=0x%02x", dh6->dh6_rep.dh6rep_flagandstat & DH6REP_STATMASK); extp = (u_char *)((&dh6->dh6_rep) + 1); if ((dh6->dh6_rep.dh6rep_flagandstat & DH6REP_CLIPRESENT) != 0) { printf(" cliaddr=%s", ip6addr_string(extp)); extp += 16; } dhcp6ext_print(extp, ep); printf(")"); break; case DH6_RELEASE: printf(" release"); break; case DH6_RECONFIG: printf(" reconfig"); break; } return; trunc: printf("%s", tstr); }