14edb46e9SPaul Traina /* 2699fc314SBill Fenner * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 34edb46e9SPaul Traina * The Regents of the University of California. All rights reserved. 44edb46e9SPaul Traina * 54edb46e9SPaul Traina * Redistribution and use in source and binary forms, with or without 64edb46e9SPaul Traina * modification, are permitted provided that: (1) source code distributions 74edb46e9SPaul Traina * retain the above copyright notice and this paragraph in its entirety, (2) 84edb46e9SPaul Traina * distributions including binary code include the above copyright notice and 94edb46e9SPaul Traina * this paragraph in its entirety in the documentation or other materials 104edb46e9SPaul Traina * provided with the distribution, and (3) all advertising materials mentioning 114edb46e9SPaul Traina * features or use of this software display the following acknowledgement: 124edb46e9SPaul Traina * ``This product includes software developed by the University of California, 134edb46e9SPaul Traina * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 144edb46e9SPaul Traina * the University nor the names of its contributors may be used to endorse 154edb46e9SPaul Traina * or promote products derived from this software without specific prior 164edb46e9SPaul Traina * written permission. 174edb46e9SPaul Traina * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 184edb46e9SPaul Traina * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 194edb46e9SPaul Traina * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 204edb46e9SPaul Traina * 214edb46e9SPaul Traina * Format and print bootp packets. 22a88113a8SBill Fenner * 23a88113a8SBill Fenner * $FreeBSD$ 244edb46e9SPaul Traina */ 254edb46e9SPaul Traina #ifndef lint 262ebf6c05SBill Fenner static const char rcsid[] = 27943ee2b1SBill Fenner "@(#) $Header: /tcpdump/master/tcpdump/print-bootp.c,v 1.56 2000/12/04 00:00:08 fenner Exp $ (LBL)"; 28a88113a8SBill Fenner #endif 29a88113a8SBill Fenner 30a88113a8SBill Fenner #ifdef HAVE_CONFIG_H 31a88113a8SBill Fenner #include "config.h" 324edb46e9SPaul Traina #endif 334edb46e9SPaul Traina 344edb46e9SPaul Traina #include <sys/param.h> 354edb46e9SPaul Traina #include <sys/time.h> 364edb46e9SPaul Traina #include <sys/socket.h> 374edb46e9SPaul Traina 384edb46e9SPaul Traina struct mbuf; 394edb46e9SPaul Traina struct rtentry; 404edb46e9SPaul Traina 414edb46e9SPaul Traina #include <netinet/in.h> 424edb46e9SPaul Traina 434edb46e9SPaul Traina #include <ctype.h> 444edb46e9SPaul Traina #include <stdio.h> 454edb46e9SPaul Traina #include <string.h> 464edb46e9SPaul Traina 474edb46e9SPaul Traina #include "interface.h" 484edb46e9SPaul Traina #include "addrtoname.h" 49943ee2b1SBill Fenner #include "extract.h" 50943ee2b1SBill Fenner #include "ether.h" 514edb46e9SPaul Traina #include "bootp.h" 524edb46e9SPaul Traina 534edb46e9SPaul Traina static void rfc1048_print(const u_char *, u_int); 544edb46e9SPaul Traina static void cmu_print(const u_char *, u_int); 554edb46e9SPaul Traina 564edb46e9SPaul Traina static char tstr[] = " [|bootp]"; 574edb46e9SPaul Traina 584edb46e9SPaul Traina /* 594edb46e9SPaul Traina * Print bootp requests 604edb46e9SPaul Traina */ 614edb46e9SPaul Traina void 624edb46e9SPaul Traina bootp_print(register const u_char *cp, u_int length, 634edb46e9SPaul Traina u_short sport, u_short dport) 644edb46e9SPaul Traina { 654edb46e9SPaul Traina register const struct bootp *bp; 664edb46e9SPaul Traina static u_char vm_cmu[4] = VM_CMU; 674edb46e9SPaul Traina static u_char vm_rfc1048[4] = VM_RFC1048; 684edb46e9SPaul Traina 694edb46e9SPaul Traina bp = (struct bootp *)cp; 704edb46e9SPaul Traina TCHECK(bp->bp_op); 714edb46e9SPaul Traina switch (bp->bp_op) { 724edb46e9SPaul Traina 734edb46e9SPaul Traina case BOOTREQUEST: 744edb46e9SPaul Traina /* Usually, a request goes from a client to a server */ 754edb46e9SPaul Traina if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS) 764edb46e9SPaul Traina printf(" (request)"); 774edb46e9SPaul Traina break; 784edb46e9SPaul Traina 794edb46e9SPaul Traina case BOOTREPLY: 804edb46e9SPaul Traina /* Usually, a reply goes from a server to a client */ 814edb46e9SPaul Traina if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC) 824edb46e9SPaul Traina printf(" (reply)"); 834edb46e9SPaul Traina break; 844edb46e9SPaul Traina 854edb46e9SPaul Traina default: 864edb46e9SPaul Traina printf(" bootp-#%d", bp->bp_op); 874edb46e9SPaul Traina } 884edb46e9SPaul Traina 894edb46e9SPaul Traina TCHECK(bp->bp_secs); 904edb46e9SPaul Traina 914edb46e9SPaul Traina /* The usual hardware address type is 1 (10Mb Ethernet) */ 924edb46e9SPaul Traina if (bp->bp_htype != 1) 934edb46e9SPaul Traina printf(" htype-#%d", bp->bp_htype); 944edb46e9SPaul Traina 954edb46e9SPaul Traina /* The usual length for 10Mb Ethernet address is 6 bytes */ 964edb46e9SPaul Traina if (bp->bp_htype != 1 || bp->bp_hlen != 6) 974edb46e9SPaul Traina printf(" hlen:%d", bp->bp_hlen); 984edb46e9SPaul Traina 994edb46e9SPaul Traina /* Only print interesting fields */ 1004edb46e9SPaul Traina if (bp->bp_hops) 1014edb46e9SPaul Traina printf(" hops:%d", bp->bp_hops); 1024edb46e9SPaul Traina if (bp->bp_xid) 1034edb46e9SPaul Traina printf(" xid:0x%x", (u_int32_t)ntohl(bp->bp_xid)); 1044edb46e9SPaul Traina if (bp->bp_secs) 1054edb46e9SPaul Traina printf(" secs:%d", ntohs(bp->bp_secs)); 106a88113a8SBill Fenner if (bp->bp_flags) 107a88113a8SBill Fenner printf(" flags:0x%x", ntohs(bp->bp_flags)); 1084edb46e9SPaul Traina 1094edb46e9SPaul Traina /* Client's ip address */ 1104edb46e9SPaul Traina TCHECK(bp->bp_ciaddr); 1114edb46e9SPaul Traina if (bp->bp_ciaddr.s_addr) 1124edb46e9SPaul Traina printf(" C:%s", ipaddr_string(&bp->bp_ciaddr)); 1134edb46e9SPaul Traina 1144edb46e9SPaul Traina /* 'your' ip address (bootp client) */ 1154edb46e9SPaul Traina TCHECK(bp->bp_yiaddr); 1164edb46e9SPaul Traina if (bp->bp_yiaddr.s_addr) 1174edb46e9SPaul Traina printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr)); 1184edb46e9SPaul Traina 1194edb46e9SPaul Traina /* Server's ip address */ 1204edb46e9SPaul Traina TCHECK(bp->bp_siaddr); 1214edb46e9SPaul Traina if (bp->bp_siaddr.s_addr) 1224edb46e9SPaul Traina printf(" S:%s", ipaddr_string(&bp->bp_siaddr)); 1234edb46e9SPaul Traina 1244edb46e9SPaul Traina /* Gateway's ip address */ 1254edb46e9SPaul Traina TCHECK(bp->bp_giaddr); 1264edb46e9SPaul Traina if (bp->bp_giaddr.s_addr) 1274edb46e9SPaul Traina printf(" G:%s", ipaddr_string(&bp->bp_giaddr)); 1284edb46e9SPaul Traina 1294edb46e9SPaul Traina /* Client's Ethernet address */ 1304edb46e9SPaul Traina if (bp->bp_htype == 1 && bp->bp_hlen == 6) { 1314edb46e9SPaul Traina register const struct ether_header *eh; 1324edb46e9SPaul Traina register const char *e; 1334edb46e9SPaul Traina 1344edb46e9SPaul Traina TCHECK2(bp->bp_chaddr[0], 6); 1354edb46e9SPaul Traina eh = (struct ether_header *)packetp; 1364edb46e9SPaul Traina if (bp->bp_op == BOOTREQUEST) 1374edb46e9SPaul Traina e = (const char *)ESRC(eh); 1384edb46e9SPaul Traina else if (bp->bp_op == BOOTREPLY) 1394edb46e9SPaul Traina e = (const char *)EDST(eh); 1404edb46e9SPaul Traina else 1414edb46e9SPaul Traina e = 0; 1424edb46e9SPaul Traina if (e == 0 || memcmp((char *)bp->bp_chaddr, e, 6) != 0) 1434edb46e9SPaul Traina printf(" ether %s", etheraddr_string(bp->bp_chaddr)); 1444edb46e9SPaul Traina } 1454edb46e9SPaul Traina 1464edb46e9SPaul Traina TCHECK2(bp->bp_sname[0], 1); /* check first char only */ 1474edb46e9SPaul Traina if (*bp->bp_sname) { 1484edb46e9SPaul Traina printf(" sname \""); 1494edb46e9SPaul Traina if (fn_print(bp->bp_sname, snapend)) { 1504edb46e9SPaul Traina putchar('"'); 1514edb46e9SPaul Traina fputs(tstr + 1, stdout); 1524edb46e9SPaul Traina return; 1534edb46e9SPaul Traina } 154699fc314SBill Fenner putchar('"'); 1554edb46e9SPaul Traina } 1564edb46e9SPaul Traina TCHECK2(bp->bp_sname[0], 1); /* check first char only */ 1574edb46e9SPaul Traina if (*bp->bp_file) { 1584edb46e9SPaul Traina printf(" file \""); 1594edb46e9SPaul Traina if (fn_print(bp->bp_file, snapend)) { 1604edb46e9SPaul Traina putchar('"'); 1614edb46e9SPaul Traina fputs(tstr + 1, stdout); 1624edb46e9SPaul Traina return; 1634edb46e9SPaul Traina } 164699fc314SBill Fenner putchar('"'); 1654edb46e9SPaul Traina } 1664edb46e9SPaul Traina 1674edb46e9SPaul Traina /* Decode the vendor buffer */ 1684edb46e9SPaul Traina TCHECK(bp->bp_vend[0]); 1694edb46e9SPaul Traina length -= sizeof(*bp) - sizeof(bp->bp_vend); 1704edb46e9SPaul Traina if (memcmp((char *)bp->bp_vend, (char *)vm_rfc1048, 1714edb46e9SPaul Traina sizeof(u_int32_t)) == 0) 1724edb46e9SPaul Traina rfc1048_print(bp->bp_vend, length); 1734edb46e9SPaul Traina else if (memcmp((char *)bp->bp_vend, (char *)vm_cmu, 1744edb46e9SPaul Traina sizeof(u_int32_t)) == 0) 1754edb46e9SPaul Traina cmu_print(bp->bp_vend, length); 1764edb46e9SPaul Traina else { 1774edb46e9SPaul Traina u_int32_t ul; 1784edb46e9SPaul Traina 179943ee2b1SBill Fenner ul = EXTRACT_32BITS(&bp->bp_vend); 1804edb46e9SPaul Traina if (ul != 0) 1814edb46e9SPaul Traina printf("vend-#0x%x", ul); 1824edb46e9SPaul Traina } 1834edb46e9SPaul Traina 1844edb46e9SPaul Traina return; 1854edb46e9SPaul Traina trunc: 1864edb46e9SPaul Traina fputs(tstr, stdout); 1874edb46e9SPaul Traina } 1884edb46e9SPaul Traina 1894edb46e9SPaul Traina /* The first character specifies the format to print */ 1904edb46e9SPaul Traina static struct tok tag2str[] = { 1914edb46e9SPaul Traina /* RFC1048 tags */ 1924edb46e9SPaul Traina { TAG_PAD, " PAD" }, 1934edb46e9SPaul Traina { TAG_SUBNET_MASK, "iSM" }, /* subnet mask (RFC950) */ 194943ee2b1SBill Fenner { TAG_TIME_OFFSET, "LTZ" }, /* seconds from UTC */ 1954edb46e9SPaul Traina { TAG_GATEWAY, "iDG" }, /* default gateway */ 1964edb46e9SPaul Traina { TAG_TIME_SERVER, "iTS" }, /* time servers (RFC868) */ 1974edb46e9SPaul Traina { TAG_NAME_SERVER, "iIEN" }, /* IEN name servers (IEN116) */ 1984edb46e9SPaul Traina { TAG_DOMAIN_SERVER, "iNS" }, /* domain name (RFC1035) */ 1994edb46e9SPaul Traina { TAG_LOG_SERVER, "iLOG" }, /* MIT log servers */ 2004edb46e9SPaul Traina { TAG_COOKIE_SERVER, "iCS" }, /* cookie servers (RFC865) */ 2014edb46e9SPaul Traina { TAG_LPR_SERVER, "iLPR" }, /* lpr server (RFC1179) */ 2024edb46e9SPaul Traina { TAG_IMPRESS_SERVER, "iIM" }, /* impress servers (Imagen) */ 2034edb46e9SPaul Traina { TAG_RLP_SERVER, "iRL" }, /* resource location (RFC887) */ 2044edb46e9SPaul Traina { TAG_HOSTNAME, "aHN" }, /* ascii hostname */ 2054edb46e9SPaul Traina { TAG_BOOTSIZE, "sBS" }, /* 512 byte blocks */ 2064edb46e9SPaul Traina { TAG_END, " END" }, 2074edb46e9SPaul Traina /* RFC1497 tags */ 2084edb46e9SPaul Traina { TAG_DUMPPATH, "aDP" }, 2094edb46e9SPaul Traina { TAG_DOMAINNAME, "aDN" }, 2104edb46e9SPaul Traina { TAG_SWAP_SERVER, "iSS" }, 2114edb46e9SPaul Traina { TAG_ROOTPATH, "aRP" }, 2124edb46e9SPaul Traina { TAG_EXTPATH, "aEP" }, 213a88113a8SBill Fenner /* RFC2132 tags */ 214a88113a8SBill Fenner { TAG_IP_FORWARD, "BIPF" }, 215a88113a8SBill Fenner { TAG_NL_SRCRT, "BSRT" }, 216a88113a8SBill Fenner { TAG_PFILTERS, "pPF" }, 217a88113a8SBill Fenner { TAG_REASS_SIZE, "sRSZ" }, 218a88113a8SBill Fenner { TAG_DEF_TTL, "bTTL" }, 219a88113a8SBill Fenner { TAG_MTU_TIMEOUT, "lMA" }, 220a88113a8SBill Fenner { TAG_MTU_TABLE, "sMT" }, 221a88113a8SBill Fenner { TAG_INT_MTU, "sMTU" }, 222a88113a8SBill Fenner { TAG_LOCAL_SUBNETS, "BLSN" }, 223a88113a8SBill Fenner { TAG_BROAD_ADDR, "iBR" }, 224a88113a8SBill Fenner { TAG_DO_MASK_DISC, "BMD" }, 225a88113a8SBill Fenner { TAG_SUPPLY_MASK, "BMS" }, 226a88113a8SBill Fenner { TAG_DO_RDISC, "BRD" }, 227a88113a8SBill Fenner { TAG_RTR_SOL_ADDR, "iRSA" }, 228a88113a8SBill Fenner { TAG_STATIC_ROUTE, "pSR" }, 229a88113a8SBill Fenner { TAG_USE_TRAILERS, "BUT" }, 230a88113a8SBill Fenner { TAG_ARP_TIMEOUT, "lAT" }, 231a88113a8SBill Fenner { TAG_ETH_ENCAP, "BIE" }, 232a88113a8SBill Fenner { TAG_TCP_TTL, "bTT" }, 233a88113a8SBill Fenner { TAG_TCP_KEEPALIVE, "lKI" }, 234a88113a8SBill Fenner { TAG_KEEPALIVE_GO, "BKG" }, 235a88113a8SBill Fenner { TAG_NIS_DOMAIN, "aYD" }, 236a88113a8SBill Fenner { TAG_NIS_SERVERS, "iYS" }, 237a88113a8SBill Fenner { TAG_NTP_SERVERS, "iNTP" }, 238a88113a8SBill Fenner { TAG_VENDOR_OPTS, "bVO" }, 239a88113a8SBill Fenner { TAG_NETBIOS_NS, "iWNS" }, 240a88113a8SBill Fenner { TAG_NETBIOS_DDS, "iWDD" }, 241a88113a8SBill Fenner { TAG_NETBIOS_NODE, "bWNT" }, 242a88113a8SBill Fenner { TAG_NETBIOS_SCOPE, "aWSC" }, 243a88113a8SBill Fenner { TAG_XWIN_FS, "iXFS" }, 244a88113a8SBill Fenner { TAG_XWIN_DM, "iXDM" }, 245a88113a8SBill Fenner { TAG_NIS_P_DOMAIN, "sN+D" }, 246a88113a8SBill Fenner { TAG_NIS_P_SERVERS, "iN+S" }, 247a88113a8SBill Fenner { TAG_MOBILE_HOME, "iMH" }, 248a88113a8SBill Fenner { TAG_SMPT_SERVER, "iSMTP" }, 249a88113a8SBill Fenner { TAG_POP3_SERVER, "iPOP3" }, 250a88113a8SBill Fenner { TAG_NNTP_SERVER, "iNNTP" }, 251a88113a8SBill Fenner { TAG_WWW_SERVER, "iWWW" }, 252a88113a8SBill Fenner { TAG_FINGER_SERVER, "iFG" }, 253a88113a8SBill Fenner { TAG_IRC_SERVER, "iIRC" }, 254a88113a8SBill Fenner { TAG_STREETTALK_SRVR, "iSTS" }, 255a88113a8SBill Fenner { TAG_STREETTALK_STDA, "iSTDA" }, 256a88113a8SBill Fenner { TAG_REQUESTED_IP, "iRQ" }, 257a88113a8SBill Fenner { TAG_IP_LEASE, "lLT" }, 258a88113a8SBill Fenner { TAG_OPT_OVERLOAD, "bOO" }, 259a88113a8SBill Fenner { TAG_TFTP_SERVER, "aTFTP" }, 260a88113a8SBill Fenner { TAG_BOOTFILENAME, "aBF" }, 261a88113a8SBill Fenner { TAG_DHCP_MESSAGE, " DHCP" }, 262a88113a8SBill Fenner { TAG_SERVER_ID, "iSID" }, 263a88113a8SBill Fenner { TAG_PARM_REQUEST, "bPR" }, 264a88113a8SBill Fenner { TAG_MESSAGE, "aMSG" }, 265a88113a8SBill Fenner { TAG_MAX_MSG_SIZE, "sMSZ" }, 266a88113a8SBill Fenner { TAG_RENEWAL_TIME, "lRN" }, 267a88113a8SBill Fenner { TAG_REBIND_TIME, "lRB" }, 268a88113a8SBill Fenner { TAG_VENDOR_CLASS, "bVC" }, 269943ee2b1SBill Fenner { TAG_CLIENT_ID, "xCID" }, 270943ee2b1SBill Fenner /* RFC 2485 */ 271943ee2b1SBill Fenner { TAG_OPEN_GROUP_UAP, "aUAP" }, 272943ee2b1SBill Fenner /* RFC 2563 */ 273943ee2b1SBill Fenner { TAG_DISABLE_AUTOCONF, "BNOAUTO" }, 274943ee2b1SBill Fenner /* RFC 2610 */ 275943ee2b1SBill Fenner { TAG_SLP_DA, "bSLP-DA" }, /*"b" is a little wrong */ 276943ee2b1SBill Fenner { TAG_SLP_SCOPE, "bSLP-SCOPE" }, /*"b" is a little wrong */ 277943ee2b1SBill Fenner /* RFC 2937 */ 278943ee2b1SBill Fenner { TAG_NS_SEARCH, "sNSSEARCH" }, /* XXX 's' */ 279943ee2b1SBill Fenner /* RFC 3011 */ 280943ee2b1SBill Fenner { TAG_IP4_SUBNET_SELECT, "iSUBNET" }, 281943ee2b1SBill Fenner /* ftp://ftp.isi.edu/.../assignments/bootp-dhcp-extensions */ 282943ee2b1SBill Fenner { TAG_USER_CLASS, "aCLASS" }, 283943ee2b1SBill Fenner { TAG_SLP_NAMING_AUTH, "aSLP-NA" }, 284943ee2b1SBill Fenner { TAG_CLIENT_FQDN, "bFQDN" }, /* XXX 'b' */ 285943ee2b1SBill Fenner { TAG_AGENT_CIRCUIT, "bACKT" }, 286943ee2b1SBill Fenner { TAG_AGENT_REMOTE, "bARMT" }, 287943ee2b1SBill Fenner { TAG_AGENT_MASK, "bAMSK" }, 288943ee2b1SBill Fenner { TAG_TZ_STRING, "aTZSTR" }, 289943ee2b1SBill Fenner { TAG_FQDN_OPTION, "bFQDNS" }, /* XXX 'b' */ 290943ee2b1SBill Fenner { TAG_AUTH, "bAUTH" }, /* XXX 'b' */ 291943ee2b1SBill Fenner { TAG_VINES_SERVERS, "iVINES" }, 292943ee2b1SBill Fenner { TAG_SERVER_RANK, "sRANK" }, 293943ee2b1SBill Fenner { TAG_CLIENT_ARCH, "sARCH" }, 294943ee2b1SBill Fenner { TAG_CLIENT_NDI, "bNDI" }, /* XXX 'b' */ 295943ee2b1SBill Fenner { TAG_CLIENT_GUID, "bGUID" }, /* XXX 'b' */ 296943ee2b1SBill Fenner { TAG_LDAP_URL, "aLDAP" }, 297943ee2b1SBill Fenner { TAG_6OVER4, "i6o4" }, 298943ee2b1SBill Fenner { TAG_PRINTER_NAME, "aPRTR" }, 299943ee2b1SBill Fenner { TAG_MDHCP_SERVER, "bMDHCP" }, /* XXX 'b' */ 300943ee2b1SBill Fenner { TAG_IPX_COMPAT, "bIPX" }, /* XXX 'b' */ 301943ee2b1SBill Fenner { TAG_NETINFO_PARENT, "iNI" }, 302943ee2b1SBill Fenner { TAG_NETINFO_PARENT_TAG, "aNITAG" }, 303943ee2b1SBill Fenner { TAG_URL, "aURL" }, 304943ee2b1SBill Fenner { TAG_FAILOVER, "bFAIL" }, /* XXX 'b' */ 305943ee2b1SBill Fenner { 0, NULL } 306943ee2b1SBill Fenner }; 307943ee2b1SBill Fenner /* 2-byte extended tags */ 308943ee2b1SBill Fenner static struct tok xtag2str[] = { 3094edb46e9SPaul Traina { 0, NULL } 3104edb46e9SPaul Traina }; 3114edb46e9SPaul Traina 3124edb46e9SPaul Traina static void 3134edb46e9SPaul Traina rfc1048_print(register const u_char *bp, register u_int length) 3144edb46e9SPaul Traina { 3154edb46e9SPaul Traina register u_char tag; 3164edb46e9SPaul Traina register u_int len, size; 3174edb46e9SPaul Traina register const char *cp; 3184edb46e9SPaul Traina register char c; 3194edb46e9SPaul Traina int first; 3204edb46e9SPaul Traina u_int32_t ul; 3214edb46e9SPaul Traina u_short us; 3224edb46e9SPaul Traina 3234edb46e9SPaul Traina printf(" vend-rfc1048"); 3244edb46e9SPaul Traina 3254edb46e9SPaul Traina /* Step over magic cookie */ 3264edb46e9SPaul Traina bp += sizeof(int32_t); 3274edb46e9SPaul Traina 3284edb46e9SPaul Traina /* Loop while we there is a tag left in the buffer */ 3294edb46e9SPaul Traina while (bp + 1 < snapend) { 3304edb46e9SPaul Traina tag = *bp++; 3314edb46e9SPaul Traina if (tag == TAG_PAD) 3324edb46e9SPaul Traina continue; 3334edb46e9SPaul Traina if (tag == TAG_END) 3344edb46e9SPaul Traina return; 335943ee2b1SBill Fenner if (tag == TAG_EXTENDED_OPTION) { 336943ee2b1SBill Fenner TCHECK2(*(bp + 1), 2); 337943ee2b1SBill Fenner tag = EXTRACT_16BITS(bp + 1); 338943ee2b1SBill Fenner /* XXX we don't know yet if the IANA will 339943ee2b1SBill Fenner * preclude overlap of 1-byte and 2-byte spaces. 340943ee2b1SBill Fenner * If not, we need to offset tag after this step. 341943ee2b1SBill Fenner */ 342943ee2b1SBill Fenner cp = tok2str(xtag2str, "?xT%d", tag); 343943ee2b1SBill Fenner } else 3444edb46e9SPaul Traina cp = tok2str(tag2str, "?T%d", tag); 3454edb46e9SPaul Traina c = *cp++; 3464edb46e9SPaul Traina printf(" %s:", cp); 3474edb46e9SPaul Traina 3484edb46e9SPaul Traina /* Get the length; check for truncation */ 3494edb46e9SPaul Traina if (bp + 1 >= snapend) { 3504edb46e9SPaul Traina fputs(tstr, stdout); 3514edb46e9SPaul Traina return; 3524edb46e9SPaul Traina } 3534edb46e9SPaul Traina len = *bp++; 3544edb46e9SPaul Traina if (bp + len >= snapend) { 3554edb46e9SPaul Traina fputs(tstr, stdout); 3564edb46e9SPaul Traina return; 3574edb46e9SPaul Traina } 3584edb46e9SPaul Traina 359a88113a8SBill Fenner if (tag == TAG_DHCP_MESSAGE && len == 1) { 360a88113a8SBill Fenner c = *bp++; 361a88113a8SBill Fenner switch (c) { 362a88113a8SBill Fenner case DHCPDISCOVER: printf("DISCOVER"); break; 363a88113a8SBill Fenner case DHCPOFFER: printf("OFFER"); break; 364a88113a8SBill Fenner case DHCPREQUEST: printf("REQUEST"); break; 365a88113a8SBill Fenner case DHCPDECLINE: printf("DECLINE"); break; 366a88113a8SBill Fenner case DHCPACK: printf("ACK"); break; 367a88113a8SBill Fenner case DHCPNAK: printf("NACK"); break; 368a88113a8SBill Fenner case DHCPRELEASE: printf("RELEASE"); break; 369a88113a8SBill Fenner case DHCPINFORM: printf("INFORM"); break; 370a88113a8SBill Fenner default: printf("%u", c); break; 371a88113a8SBill Fenner } 372a88113a8SBill Fenner continue; 373a88113a8SBill Fenner } 374a88113a8SBill Fenner 375a88113a8SBill Fenner if (tag == TAG_PARM_REQUEST) { 376a88113a8SBill Fenner first = 1; 377a88113a8SBill Fenner while (len-- > 0) { 378a88113a8SBill Fenner c = *bp++; 379943ee2b1SBill Fenner cp = tok2str(tag2str, "?T%d", c); 380943ee2b1SBill Fenner if (!first) 381943ee2b1SBill Fenner putchar('+'); 382943ee2b1SBill Fenner printf("%s", cp + 1); 383943ee2b1SBill Fenner first = 0; 384943ee2b1SBill Fenner } 385943ee2b1SBill Fenner continue; 386943ee2b1SBill Fenner } 387943ee2b1SBill Fenner if (tag == TAG_EXTENDED_REQUEST) { 388943ee2b1SBill Fenner first = 1; 389943ee2b1SBill Fenner while (len > 1) { 390943ee2b1SBill Fenner len -= 2; 391943ee2b1SBill Fenner c = EXTRACT_16BITS(bp); 392943ee2b1SBill Fenner bp += 2; 393943ee2b1SBill Fenner cp = tok2str(xtag2str, "?xT%d", c); 394a88113a8SBill Fenner if (!first) 395a88113a8SBill Fenner putchar('+'); 396a88113a8SBill Fenner printf("%s", cp + 1); 397a88113a8SBill Fenner first = 0; 398a88113a8SBill Fenner } 399a88113a8SBill Fenner continue; 400a88113a8SBill Fenner } 401a88113a8SBill Fenner 4024edb46e9SPaul Traina /* Print data */ 4034edb46e9SPaul Traina size = len; 4044edb46e9SPaul Traina if (c == '?') { 4054edb46e9SPaul Traina /* Base default formats for unknown tags on data size */ 4064edb46e9SPaul Traina if (size & 1) 4074edb46e9SPaul Traina c = 'b'; 4084edb46e9SPaul Traina else if (size & 2) 4094edb46e9SPaul Traina c = 's'; 4104edb46e9SPaul Traina else 4114edb46e9SPaul Traina c = 'l'; 4124edb46e9SPaul Traina } 4134edb46e9SPaul Traina first = 1; 4144edb46e9SPaul Traina switch (c) { 4154edb46e9SPaul Traina 4164edb46e9SPaul Traina case 'a': 4174edb46e9SPaul Traina /* ascii strings */ 4184edb46e9SPaul Traina putchar('"'); 4194edb46e9SPaul Traina (void)fn_printn(bp, size, NULL); 4204edb46e9SPaul Traina putchar('"'); 4214edb46e9SPaul Traina bp += size; 4224edb46e9SPaul Traina size = 0; 4234edb46e9SPaul Traina break; 4244edb46e9SPaul Traina 4254edb46e9SPaul Traina case 'i': 4264edb46e9SPaul Traina case 'l': 427943ee2b1SBill Fenner case 'L': 4284edb46e9SPaul Traina /* ip addresses/32-bit words */ 4294edb46e9SPaul Traina while (size >= sizeof(ul)) { 4304edb46e9SPaul Traina if (!first) 4314edb46e9SPaul Traina putchar(','); 432943ee2b1SBill Fenner ul = EXTRACT_32BITS(bp); 433943ee2b1SBill Fenner if (c == 'i') { 434943ee2b1SBill Fenner ul = htonl(ul); 4354edb46e9SPaul Traina printf("%s", ipaddr_string(&ul)); 436943ee2b1SBill Fenner } else if (c == 'L') 437943ee2b1SBill Fenner printf("%d", ul); 4384edb46e9SPaul Traina else 4394edb46e9SPaul Traina printf("%u", ul); 4404edb46e9SPaul Traina bp += sizeof(ul); 4414edb46e9SPaul Traina size -= sizeof(ul); 4424edb46e9SPaul Traina first = 0; 4434edb46e9SPaul Traina } 4444edb46e9SPaul Traina break; 4454edb46e9SPaul Traina 446a88113a8SBill Fenner case 'p': 447a88113a8SBill Fenner /* IP address pairs */ 448a88113a8SBill Fenner while (size >= 2*sizeof(ul)) { 449a88113a8SBill Fenner if (!first) 450a88113a8SBill Fenner putchar(','); 451a88113a8SBill Fenner memcpy((char *)&ul, (char *)bp, sizeof(ul)); 452a88113a8SBill Fenner printf("(%s:", ipaddr_string(&ul)); 453a88113a8SBill Fenner bp += sizeof(ul); 454a88113a8SBill Fenner memcpy((char *)&ul, (char *)bp, sizeof(ul)); 455a88113a8SBill Fenner printf("%s)", ipaddr_string(&ul)); 456a88113a8SBill Fenner bp += sizeof(ul); 457a88113a8SBill Fenner size -= 2*sizeof(ul); 458a88113a8SBill Fenner first = 0; 459a88113a8SBill Fenner } 460a88113a8SBill Fenner break; 461a88113a8SBill Fenner 4624edb46e9SPaul Traina case 's': 4634edb46e9SPaul Traina /* shorts */ 4644edb46e9SPaul Traina while (size >= sizeof(us)) { 4654edb46e9SPaul Traina if (!first) 4664edb46e9SPaul Traina putchar(','); 467943ee2b1SBill Fenner us = EXTRACT_16BITS(bp); 4684edb46e9SPaul Traina printf("%d", us); 4694edb46e9SPaul Traina bp += sizeof(us); 4704edb46e9SPaul Traina size -= sizeof(us); 4714edb46e9SPaul Traina first = 0; 4724edb46e9SPaul Traina } 4734edb46e9SPaul Traina break; 4744edb46e9SPaul Traina 475a88113a8SBill Fenner case 'B': 476a88113a8SBill Fenner /* boolean */ 477a88113a8SBill Fenner while (size > 0) { 478a88113a8SBill Fenner if (!first) 479a88113a8SBill Fenner putchar(','); 480a88113a8SBill Fenner switch (*bp) { 481a88113a8SBill Fenner case 0: 482a88113a8SBill Fenner putchar('N'); 483a88113a8SBill Fenner break; 484a88113a8SBill Fenner case 1: 485a88113a8SBill Fenner putchar('Y'); 486a88113a8SBill Fenner break; 487a88113a8SBill Fenner default: 488a88113a8SBill Fenner printf("%d?", *bp); 489a88113a8SBill Fenner break; 490a88113a8SBill Fenner } 491a88113a8SBill Fenner ++bp; 492a88113a8SBill Fenner --size; 493a88113a8SBill Fenner first = 0; 494a88113a8SBill Fenner } 495a88113a8SBill Fenner break; 496a88113a8SBill Fenner 4974edb46e9SPaul Traina case 'b': 498943ee2b1SBill Fenner case 'x': 4994edb46e9SPaul Traina default: 5004edb46e9SPaul Traina /* Bytes */ 5014edb46e9SPaul Traina while (size > 0) { 5024edb46e9SPaul Traina if (!first) 503943ee2b1SBill Fenner putchar (c == 'x' ? ':' : '.'); 504943ee2b1SBill Fenner printf (c == 'x' ? "%02x" : "%d", *bp); 5054edb46e9SPaul Traina ++bp; 5064edb46e9SPaul Traina --size; 5074edb46e9SPaul Traina first = 0; 5084edb46e9SPaul Traina } 5094edb46e9SPaul Traina break; 5104edb46e9SPaul Traina } 5114edb46e9SPaul Traina /* Data left over? */ 5124edb46e9SPaul Traina if (size) 5134edb46e9SPaul Traina printf("[len %d]", len); 5144edb46e9SPaul Traina } 515943ee2b1SBill Fenner return; 516943ee2b1SBill Fenner trunc: 517943ee2b1SBill Fenner printf("|[rfc1048]"); 5184edb46e9SPaul Traina } 5194edb46e9SPaul Traina 5204edb46e9SPaul Traina static void 5214edb46e9SPaul Traina cmu_print(register const u_char *bp, register u_int length) 5224edb46e9SPaul Traina { 5234edb46e9SPaul Traina register const struct cmu_vend *cmu; 5244edb46e9SPaul Traina char *fmt = " %s:%s"; 5254edb46e9SPaul Traina 5264edb46e9SPaul Traina #define PRINTCMUADDR(m, s) { TCHECK(cmu->m); \ 5274edb46e9SPaul Traina if (cmu->m.s_addr != 0) \ 5284edb46e9SPaul Traina printf(fmt, s, ipaddr_string(&cmu->m.s_addr)); } 5294edb46e9SPaul Traina 5304edb46e9SPaul Traina printf(" vend-cmu"); 5314edb46e9SPaul Traina cmu = (struct cmu_vend *)bp; 5324edb46e9SPaul Traina 5334edb46e9SPaul Traina /* Only print if there are unknown bits */ 5344edb46e9SPaul Traina TCHECK(cmu->v_flags); 5354edb46e9SPaul Traina if ((cmu->v_flags & ~(VF_SMASK)) != 0) 5364edb46e9SPaul Traina printf(" F:0x%x", cmu->v_flags); 5374edb46e9SPaul Traina PRINTCMUADDR(v_dgate, "DG"); 5384edb46e9SPaul Traina PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*"); 5394edb46e9SPaul Traina PRINTCMUADDR(v_dns1, "NS1"); 5404edb46e9SPaul Traina PRINTCMUADDR(v_dns2, "NS2"); 5414edb46e9SPaul Traina PRINTCMUADDR(v_ins1, "IEN1"); 5424edb46e9SPaul Traina PRINTCMUADDR(v_ins2, "IEN2"); 5434edb46e9SPaul Traina PRINTCMUADDR(v_ts1, "TS1"); 5444edb46e9SPaul Traina PRINTCMUADDR(v_ts2, "TS2"); 5454edb46e9SPaul Traina return; 5464edb46e9SPaul Traina 5474edb46e9SPaul Traina trunc: 5484edb46e9SPaul Traina fputs(tstr, stdout); 5494edb46e9SPaul Traina #undef PRINTCMUADDR 5504edb46e9SPaul Traina } 551