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 26cc391cceSBruce M Simpson static const char rcsid[] _U_ = 2729292c17SSam Leffler "@(#) $Header: /tcpdump/master/tcpdump/print-bootp.c,v 1.78.2.2 2005/05/06 04:19:39 guy Exp $ (LBL)"; 28a88113a8SBill Fenner #endif 29a88113a8SBill Fenner 30a88113a8SBill Fenner #ifdef HAVE_CONFIG_H 31a88113a8SBill Fenner #include "config.h" 324edb46e9SPaul Traina #endif 334edb46e9SPaul Traina 34cc391cceSBruce M Simpson #include <tcpdump-stdinc.h> 354edb46e9SPaul Traina 364edb46e9SPaul Traina #include <stdio.h> 374edb46e9SPaul Traina #include <string.h> 384edb46e9SPaul Traina 394edb46e9SPaul Traina #include "interface.h" 404edb46e9SPaul Traina #include "addrtoname.h" 41943ee2b1SBill Fenner #include "extract.h" 42943ee2b1SBill Fenner #include "ether.h" 434edb46e9SPaul Traina #include "bootp.h" 444edb46e9SPaul Traina 45a1c2090eSBill Fenner static void rfc1048_print(const u_char *); 46a1c2090eSBill Fenner static void cmu_print(const u_char *); 474edb46e9SPaul Traina 484edb46e9SPaul Traina static char tstr[] = " [|bootp]"; 494edb46e9SPaul Traina 50cc391cceSBruce M Simpson static const struct tok bootp_flag_values[] = { 51cc391cceSBruce M Simpson { 0x8000, "Broadcast" }, 52cc391cceSBruce M Simpson { 0, NULL} 53cc391cceSBruce M Simpson }; 54cc391cceSBruce M Simpson 55cc391cceSBruce M Simpson static const struct tok bootp_op_values[] = { 56cc391cceSBruce M Simpson { BOOTPREQUEST, "Request" }, 57cc391cceSBruce M Simpson { BOOTPREPLY, "Reply" }, 58cc391cceSBruce M Simpson { 0, NULL} 59cc391cceSBruce M Simpson }; 60cc391cceSBruce M Simpson 614edb46e9SPaul Traina /* 624edb46e9SPaul Traina * Print bootp requests 634edb46e9SPaul Traina */ 644edb46e9SPaul Traina void 65cc391cceSBruce M Simpson bootp_print(register const u_char *cp, u_int length) 664edb46e9SPaul Traina { 674edb46e9SPaul Traina register const struct bootp *bp; 68a1c2090eSBill Fenner static const u_char vm_cmu[4] = VM_CMU; 69a1c2090eSBill Fenner static const u_char vm_rfc1048[4] = VM_RFC1048; 704edb46e9SPaul Traina 71a1c2090eSBill Fenner bp = (const struct bootp *)cp; 724edb46e9SPaul Traina TCHECK(bp->bp_op); 734edb46e9SPaul Traina 74cc391cceSBruce M Simpson printf("BOOTP/DHCP, %s", 75cc391cceSBruce M Simpson tok2str(bootp_op_values, "unknown (0x%02x)", bp->bp_op)); 764edb46e9SPaul Traina 77cc391cceSBruce M Simpson if (bp->bp_htype == 1 && bp->bp_hlen == 6 && bp->bp_op == BOOTPREQUEST) { 78cc391cceSBruce M Simpson TCHECK2(bp->bp_chaddr[0], 6); 79cc391cceSBruce M Simpson printf(" from %s", etheraddr_string(bp->bp_chaddr)); 804edb46e9SPaul Traina } 814edb46e9SPaul Traina 82cc391cceSBruce M Simpson printf(", length: %u", length); 83cc391cceSBruce M Simpson 84cc391cceSBruce M Simpson if (!vflag) 85cc391cceSBruce M Simpson return; 86cc391cceSBruce M Simpson 874edb46e9SPaul Traina TCHECK(bp->bp_secs); 884edb46e9SPaul Traina 894edb46e9SPaul Traina /* The usual hardware address type is 1 (10Mb Ethernet) */ 904edb46e9SPaul Traina if (bp->bp_htype != 1) 91cc391cceSBruce M Simpson printf(", htype-#%d", bp->bp_htype); 924edb46e9SPaul Traina 934edb46e9SPaul Traina /* The usual length for 10Mb Ethernet address is 6 bytes */ 944edb46e9SPaul Traina if (bp->bp_htype != 1 || bp->bp_hlen != 6) 95cc391cceSBruce M Simpson printf(", hlen:%d", bp->bp_hlen); 964edb46e9SPaul Traina 974edb46e9SPaul Traina /* Only print interesting fields */ 984edb46e9SPaul Traina if (bp->bp_hops) 99cc391cceSBruce M Simpson printf(", hops:%d", bp->bp_hops); 1004edb46e9SPaul Traina if (bp->bp_xid) 101cc391cceSBruce M Simpson printf(", xid:0x%x", EXTRACT_32BITS(&bp->bp_xid)); 1024edb46e9SPaul Traina if (bp->bp_secs) 103cc391cceSBruce M Simpson printf(", secs:%d", EXTRACT_16BITS(&bp->bp_secs)); 104cc391cceSBruce M Simpson 105cc391cceSBruce M Simpson printf(", flags: [%s]", 106cc391cceSBruce M Simpson bittok2str(bootp_flag_values, "none", EXTRACT_16BITS(&bp->bp_flags))); 107cc391cceSBruce M Simpson if (vflag>1) 108cc391cceSBruce M Simpson printf( " (0x%04x)", EXTRACT_16BITS(&bp->bp_flags)); 1094edb46e9SPaul Traina 1104edb46e9SPaul Traina /* Client's ip address */ 1114edb46e9SPaul Traina TCHECK(bp->bp_ciaddr); 1124edb46e9SPaul Traina if (bp->bp_ciaddr.s_addr) 113cc391cceSBruce M Simpson printf("\n\t Client IP: %s", ipaddr_string(&bp->bp_ciaddr)); 1144edb46e9SPaul Traina 1154edb46e9SPaul Traina /* 'your' ip address (bootp client) */ 1164edb46e9SPaul Traina TCHECK(bp->bp_yiaddr); 1174edb46e9SPaul Traina if (bp->bp_yiaddr.s_addr) 118cc391cceSBruce M Simpson printf("\n\t Your IP: %s", ipaddr_string(&bp->bp_yiaddr)); 1194edb46e9SPaul Traina 1204edb46e9SPaul Traina /* Server's ip address */ 1214edb46e9SPaul Traina TCHECK(bp->bp_siaddr); 1224edb46e9SPaul Traina if (bp->bp_siaddr.s_addr) 123cc391cceSBruce M Simpson printf("\n\t Server IP: %s", ipaddr_string(&bp->bp_siaddr)); 1244edb46e9SPaul Traina 1254edb46e9SPaul Traina /* Gateway's ip address */ 1264edb46e9SPaul Traina TCHECK(bp->bp_giaddr); 1274edb46e9SPaul Traina if (bp->bp_giaddr.s_addr) 128cc391cceSBruce M Simpson printf("\n\t Gateway IP: %s", ipaddr_string(&bp->bp_giaddr)); 1294edb46e9SPaul Traina 1304edb46e9SPaul Traina /* Client's Ethernet address */ 1314edb46e9SPaul Traina if (bp->bp_htype == 1 && bp->bp_hlen == 6) { 1324edb46e9SPaul Traina TCHECK2(bp->bp_chaddr[0], 6); 133cc391cceSBruce M Simpson printf("\n\t Client Ethernet Address: %s", etheraddr_string(bp->bp_chaddr)); 1344edb46e9SPaul Traina } 1354edb46e9SPaul Traina 1364edb46e9SPaul Traina TCHECK2(bp->bp_sname[0], 1); /* check first char only */ 1374edb46e9SPaul Traina if (*bp->bp_sname) { 138cc391cceSBruce M Simpson printf("\n\t sname \""); 1394edb46e9SPaul Traina if (fn_print(bp->bp_sname, snapend)) { 1404edb46e9SPaul Traina putchar('"'); 1414edb46e9SPaul Traina fputs(tstr + 1, stdout); 1424edb46e9SPaul Traina return; 1434edb46e9SPaul Traina } 144699fc314SBill Fenner putchar('"'); 1454edb46e9SPaul Traina } 146cc391cceSBruce M Simpson TCHECK2(bp->bp_file[0], 1); /* check first char only */ 1474edb46e9SPaul Traina if (*bp->bp_file) { 148cc391cceSBruce M Simpson printf("\n\t file \""); 1494edb46e9SPaul Traina if (fn_print(bp->bp_file, snapend)) { 1504edb46e9SPaul Traina putchar('"'); 1514edb46e9SPaul Traina fputs(tstr + 1, stdout); 1524edb46e9SPaul Traina return; 1534edb46e9SPaul Traina } 154699fc314SBill Fenner putchar('"'); 1554edb46e9SPaul Traina } 1564edb46e9SPaul Traina 1574edb46e9SPaul Traina /* Decode the vendor buffer */ 1584edb46e9SPaul Traina TCHECK(bp->bp_vend[0]); 159a1c2090eSBill Fenner if (memcmp((const char *)bp->bp_vend, vm_rfc1048, 1604edb46e9SPaul Traina sizeof(u_int32_t)) == 0) 161a1c2090eSBill Fenner rfc1048_print(bp->bp_vend); 162a1c2090eSBill Fenner else if (memcmp((const char *)bp->bp_vend, vm_cmu, 1634edb46e9SPaul Traina sizeof(u_int32_t)) == 0) 164a1c2090eSBill Fenner cmu_print(bp->bp_vend); 1654edb46e9SPaul Traina else { 1664edb46e9SPaul Traina u_int32_t ul; 1674edb46e9SPaul Traina 168943ee2b1SBill Fenner ul = EXTRACT_32BITS(&bp->bp_vend); 1694edb46e9SPaul Traina if (ul != 0) 170cc391cceSBruce M Simpson printf("\n\t Vendor-#0x%x", ul); 1714edb46e9SPaul Traina } 1724edb46e9SPaul Traina 1734edb46e9SPaul Traina return; 1744edb46e9SPaul Traina trunc: 1754edb46e9SPaul Traina fputs(tstr, stdout); 1764edb46e9SPaul Traina } 1774edb46e9SPaul Traina 178a1c2090eSBill Fenner /* 179a1c2090eSBill Fenner * The first character specifies the format to print: 180a1c2090eSBill Fenner * i - ip address (32 bits) 181a1c2090eSBill Fenner * p - ip address pairs (32 bits + 32 bits) 182a1c2090eSBill Fenner * l - long (32 bits) 183a1c2090eSBill Fenner * L - unsigned long (32 bits) 184a1c2090eSBill Fenner * s - short (16 bits) 185a1c2090eSBill Fenner * b - period-seperated decimal bytes (variable length) 186a1c2090eSBill Fenner * x - colon-seperated hex bytes (variable length) 187a1c2090eSBill Fenner * a - ascii string (variable length) 188a1c2090eSBill Fenner * B - on/off (8 bits) 189a1c2090eSBill Fenner * $ - special (explicit code to handle) 190a1c2090eSBill Fenner */ 1914edb46e9SPaul Traina static struct tok tag2str[] = { 1924edb46e9SPaul Traina /* RFC1048 tags */ 1934edb46e9SPaul Traina { TAG_PAD, " PAD" }, 1944edb46e9SPaul Traina { TAG_SUBNET_MASK, "iSM" }, /* subnet mask (RFC950) */ 195943ee2b1SBill Fenner { TAG_TIME_OFFSET, "LTZ" }, /* seconds from UTC */ 1964edb46e9SPaul Traina { TAG_GATEWAY, "iDG" }, /* default gateway */ 1974edb46e9SPaul Traina { TAG_TIME_SERVER, "iTS" }, /* time servers (RFC868) */ 1984edb46e9SPaul Traina { TAG_NAME_SERVER, "iIEN" }, /* IEN name servers (IEN116) */ 1994edb46e9SPaul Traina { TAG_DOMAIN_SERVER, "iNS" }, /* domain name (RFC1035) */ 2004edb46e9SPaul Traina { TAG_LOG_SERVER, "iLOG" }, /* MIT log servers */ 2014edb46e9SPaul Traina { TAG_COOKIE_SERVER, "iCS" }, /* cookie servers (RFC865) */ 2024edb46e9SPaul Traina { TAG_LPR_SERVER, "iLPR" }, /* lpr server (RFC1179) */ 2034edb46e9SPaul Traina { TAG_IMPRESS_SERVER, "iIM" }, /* impress servers (Imagen) */ 2044edb46e9SPaul Traina { TAG_RLP_SERVER, "iRL" }, /* resource location (RFC887) */ 2054edb46e9SPaul Traina { TAG_HOSTNAME, "aHN" }, /* ascii hostname */ 2064edb46e9SPaul Traina { TAG_BOOTSIZE, "sBS" }, /* 512 byte blocks */ 2074edb46e9SPaul Traina { TAG_END, " END" }, 2084edb46e9SPaul Traina /* RFC1497 tags */ 2094edb46e9SPaul Traina { TAG_DUMPPATH, "aDP" }, 2104edb46e9SPaul Traina { TAG_DOMAINNAME, "aDN" }, 2114edb46e9SPaul Traina { TAG_SWAP_SERVER, "iSS" }, 2124edb46e9SPaul Traina { TAG_ROOTPATH, "aRP" }, 2134edb46e9SPaul Traina { TAG_EXTPATH, "aEP" }, 214a88113a8SBill Fenner /* RFC2132 tags */ 215a88113a8SBill Fenner { TAG_IP_FORWARD, "BIPF" }, 216a88113a8SBill Fenner { TAG_NL_SRCRT, "BSRT" }, 217a88113a8SBill Fenner { TAG_PFILTERS, "pPF" }, 218a88113a8SBill Fenner { TAG_REASS_SIZE, "sRSZ" }, 219a88113a8SBill Fenner { TAG_DEF_TTL, "bTTL" }, 220a88113a8SBill Fenner { TAG_MTU_TIMEOUT, "lMA" }, 221a88113a8SBill Fenner { TAG_MTU_TABLE, "sMT" }, 222a88113a8SBill Fenner { TAG_INT_MTU, "sMTU" }, 223a88113a8SBill Fenner { TAG_LOCAL_SUBNETS, "BLSN" }, 224a88113a8SBill Fenner { TAG_BROAD_ADDR, "iBR" }, 225a88113a8SBill Fenner { TAG_DO_MASK_DISC, "BMD" }, 226a88113a8SBill Fenner { TAG_SUPPLY_MASK, "BMS" }, 227a88113a8SBill Fenner { TAG_DO_RDISC, "BRD" }, 228a88113a8SBill Fenner { TAG_RTR_SOL_ADDR, "iRSA" }, 229a88113a8SBill Fenner { TAG_STATIC_ROUTE, "pSR" }, 230a88113a8SBill Fenner { TAG_USE_TRAILERS, "BUT" }, 231a88113a8SBill Fenner { TAG_ARP_TIMEOUT, "lAT" }, 232a88113a8SBill Fenner { TAG_ETH_ENCAP, "BIE" }, 233a88113a8SBill Fenner { TAG_TCP_TTL, "bTT" }, 234a88113a8SBill Fenner { TAG_TCP_KEEPALIVE, "lKI" }, 235a88113a8SBill Fenner { TAG_KEEPALIVE_GO, "BKG" }, 236a88113a8SBill Fenner { TAG_NIS_DOMAIN, "aYD" }, 237a88113a8SBill Fenner { TAG_NIS_SERVERS, "iYS" }, 238a88113a8SBill Fenner { TAG_NTP_SERVERS, "iNTP" }, 239a88113a8SBill Fenner { TAG_VENDOR_OPTS, "bVO" }, 240a88113a8SBill Fenner { TAG_NETBIOS_NS, "iWNS" }, 241a88113a8SBill Fenner { TAG_NETBIOS_DDS, "iWDD" }, 242a1c2090eSBill Fenner { TAG_NETBIOS_NODE, "$WNT" }, 243a88113a8SBill Fenner { TAG_NETBIOS_SCOPE, "aWSC" }, 244a88113a8SBill Fenner { TAG_XWIN_FS, "iXFS" }, 245a88113a8SBill Fenner { TAG_XWIN_DM, "iXDM" }, 246a88113a8SBill Fenner { TAG_NIS_P_DOMAIN, "sN+D" }, 247a88113a8SBill Fenner { TAG_NIS_P_SERVERS, "iN+S" }, 248a88113a8SBill Fenner { TAG_MOBILE_HOME, "iMH" }, 249a88113a8SBill Fenner { TAG_SMPT_SERVER, "iSMTP" }, 250a88113a8SBill Fenner { TAG_POP3_SERVER, "iPOP3" }, 251a88113a8SBill Fenner { TAG_NNTP_SERVER, "iNNTP" }, 252a88113a8SBill Fenner { TAG_WWW_SERVER, "iWWW" }, 253a88113a8SBill Fenner { TAG_FINGER_SERVER, "iFG" }, 254a88113a8SBill Fenner { TAG_IRC_SERVER, "iIRC" }, 255a88113a8SBill Fenner { TAG_STREETTALK_SRVR, "iSTS" }, 256a88113a8SBill Fenner { TAG_STREETTALK_STDA, "iSTDA" }, 257a88113a8SBill Fenner { TAG_REQUESTED_IP, "iRQ" }, 258a88113a8SBill Fenner { TAG_IP_LEASE, "lLT" }, 259a1c2090eSBill Fenner { TAG_OPT_OVERLOAD, "$OO" }, 260a88113a8SBill Fenner { TAG_TFTP_SERVER, "aTFTP" }, 261a88113a8SBill Fenner { TAG_BOOTFILENAME, "aBF" }, 262a88113a8SBill Fenner { TAG_DHCP_MESSAGE, " DHCP" }, 263a88113a8SBill Fenner { TAG_SERVER_ID, "iSID" }, 264a88113a8SBill Fenner { TAG_PARM_REQUEST, "bPR" }, 265a88113a8SBill Fenner { TAG_MESSAGE, "aMSG" }, 266a88113a8SBill Fenner { TAG_MAX_MSG_SIZE, "sMSZ" }, 267a88113a8SBill Fenner { TAG_RENEWAL_TIME, "lRN" }, 268a88113a8SBill Fenner { TAG_REBIND_TIME, "lRB" }, 269a1c2090eSBill Fenner { TAG_VENDOR_CLASS, "aVC" }, 270a1c2090eSBill Fenner { TAG_CLIENT_ID, "$CID" }, 271943ee2b1SBill Fenner /* RFC 2485 */ 272943ee2b1SBill Fenner { TAG_OPEN_GROUP_UAP, "aUAP" }, 273943ee2b1SBill Fenner /* RFC 2563 */ 274943ee2b1SBill Fenner { TAG_DISABLE_AUTOCONF, "BNOAUTO" }, 275943ee2b1SBill Fenner /* RFC 2610 */ 276943ee2b1SBill Fenner { TAG_SLP_DA, "bSLP-DA" }, /*"b" is a little wrong */ 277943ee2b1SBill Fenner { TAG_SLP_SCOPE, "bSLP-SCOPE" }, /*"b" is a little wrong */ 278943ee2b1SBill Fenner /* RFC 2937 */ 279943ee2b1SBill Fenner { TAG_NS_SEARCH, "sNSSEARCH" }, /* XXX 's' */ 280943ee2b1SBill Fenner /* RFC 3011 */ 281943ee2b1SBill Fenner { TAG_IP4_SUBNET_SELECT, "iSUBNET" }, 282cc391cceSBruce M Simpson /* http://www.iana.org/assignments/bootp-dhcp-extensions/index.htm */ 283943ee2b1SBill Fenner { TAG_USER_CLASS, "aCLASS" }, 284943ee2b1SBill Fenner { TAG_SLP_NAMING_AUTH, "aSLP-NA" }, 285a1c2090eSBill Fenner { TAG_CLIENT_FQDN, "$FQDN" }, 286943ee2b1SBill Fenner { TAG_AGENT_CIRCUIT, "bACKT" }, 287943ee2b1SBill Fenner { TAG_AGENT_REMOTE, "bARMT" }, 288943ee2b1SBill Fenner { TAG_AGENT_MASK, "bAMSK" }, 289943ee2b1SBill Fenner { TAG_TZ_STRING, "aTZSTR" }, 290943ee2b1SBill Fenner { TAG_FQDN_OPTION, "bFQDNS" }, /* XXX 'b' */ 291943ee2b1SBill Fenner { TAG_AUTH, "bAUTH" }, /* XXX 'b' */ 292943ee2b1SBill Fenner { TAG_VINES_SERVERS, "iVINES" }, 293943ee2b1SBill Fenner { TAG_SERVER_RANK, "sRANK" }, 294943ee2b1SBill Fenner { TAG_CLIENT_ARCH, "sARCH" }, 295943ee2b1SBill Fenner { TAG_CLIENT_NDI, "bNDI" }, /* XXX 'b' */ 296943ee2b1SBill Fenner { TAG_CLIENT_GUID, "bGUID" }, /* XXX 'b' */ 297943ee2b1SBill Fenner { TAG_LDAP_URL, "aLDAP" }, 298943ee2b1SBill Fenner { TAG_6OVER4, "i6o4" }, 299943ee2b1SBill Fenner { TAG_PRINTER_NAME, "aPRTR" }, 300943ee2b1SBill Fenner { TAG_MDHCP_SERVER, "bMDHCP" }, /* XXX 'b' */ 301943ee2b1SBill Fenner { TAG_IPX_COMPAT, "bIPX" }, /* XXX 'b' */ 302943ee2b1SBill Fenner { TAG_NETINFO_PARENT, "iNI" }, 303943ee2b1SBill Fenner { TAG_NETINFO_PARENT_TAG, "aNITAG" }, 304943ee2b1SBill Fenner { TAG_URL, "aURL" }, 305943ee2b1SBill Fenner { TAG_FAILOVER, "bFAIL" }, /* XXX 'b' */ 306943ee2b1SBill Fenner { 0, NULL } 307943ee2b1SBill Fenner }; 308943ee2b1SBill Fenner /* 2-byte extended tags */ 309943ee2b1SBill Fenner static struct tok xtag2str[] = { 3104edb46e9SPaul Traina { 0, NULL } 3114edb46e9SPaul Traina }; 3124edb46e9SPaul Traina 313a1c2090eSBill Fenner /* DHCP "options overload" types */ 314a1c2090eSBill Fenner static struct tok oo2str[] = { 315a1c2090eSBill Fenner { 1, "file" }, 316a1c2090eSBill Fenner { 2, "sname" }, 317a1c2090eSBill Fenner { 3, "file+sname" }, 318a1c2090eSBill Fenner { 0, NULL } 319a1c2090eSBill Fenner }; 320a1c2090eSBill Fenner 321a1c2090eSBill Fenner /* NETBIOS over TCP/IP node type options */ 322a1c2090eSBill Fenner static struct tok nbo2str[] = { 323a1c2090eSBill Fenner { 0x1, "b-node" }, 324a1c2090eSBill Fenner { 0x2, "p-node" }, 325a1c2090eSBill Fenner { 0x4, "m-node" }, 326a1c2090eSBill Fenner { 0x8, "h-node" }, 327a1c2090eSBill Fenner { 0, NULL } 328a1c2090eSBill Fenner }; 329a1c2090eSBill Fenner 330a1c2090eSBill Fenner /* ARP Hardware types, for Client-ID option */ 331a1c2090eSBill Fenner static struct tok arp2str[] = { 332a1c2090eSBill Fenner { 0x1, "ether" }, 333a1c2090eSBill Fenner { 0x6, "ieee802" }, 334a1c2090eSBill Fenner { 0x7, "arcnet" }, 335a1c2090eSBill Fenner { 0xf, "frelay" }, 336a1c2090eSBill Fenner { 0x17, "strip" }, 337a1c2090eSBill Fenner { 0x18, "ieee1394" }, 338a1c2090eSBill Fenner { 0, NULL } 339a1c2090eSBill Fenner }; 340a1c2090eSBill Fenner 3414edb46e9SPaul Traina static void 342a1c2090eSBill Fenner rfc1048_print(register const u_char *bp) 3434edb46e9SPaul Traina { 3440e0def19SBill Fenner register u_int16_t tag; 3454edb46e9SPaul Traina register u_int len, size; 3464edb46e9SPaul Traina register const char *cp; 3474edb46e9SPaul Traina register char c; 3484edb46e9SPaul Traina int first; 3494edb46e9SPaul Traina u_int32_t ul; 3500e0def19SBill Fenner u_int16_t us; 3510e0def19SBill Fenner u_int8_t uc; 3524edb46e9SPaul Traina 353cc391cceSBruce M Simpson printf("\n\t Vendor-rfc1048:"); 3544edb46e9SPaul Traina 3554edb46e9SPaul Traina /* Step over magic cookie */ 3564edb46e9SPaul Traina bp += sizeof(int32_t); 3574edb46e9SPaul Traina 3584edb46e9SPaul Traina /* Loop while we there is a tag left in the buffer */ 3594edb46e9SPaul Traina while (bp + 1 < snapend) { 3604edb46e9SPaul Traina tag = *bp++; 3614edb46e9SPaul Traina if (tag == TAG_PAD) 3624edb46e9SPaul Traina continue; 3634edb46e9SPaul Traina if (tag == TAG_END) 3644edb46e9SPaul Traina return; 365943ee2b1SBill Fenner if (tag == TAG_EXTENDED_OPTION) { 366943ee2b1SBill Fenner TCHECK2(*(bp + 1), 2); 367943ee2b1SBill Fenner tag = EXTRACT_16BITS(bp + 1); 368943ee2b1SBill Fenner /* XXX we don't know yet if the IANA will 369943ee2b1SBill Fenner * preclude overlap of 1-byte and 2-byte spaces. 370943ee2b1SBill Fenner * If not, we need to offset tag after this step. 371943ee2b1SBill Fenner */ 3720e0def19SBill Fenner cp = tok2str(xtag2str, "?xT%u", tag); 373943ee2b1SBill Fenner } else 3740e0def19SBill Fenner cp = tok2str(tag2str, "?T%u", tag); 3754edb46e9SPaul Traina c = *cp++; 376cc391cceSBruce M Simpson printf("\n\t %s:", cp); 3774edb46e9SPaul Traina 3784edb46e9SPaul Traina /* Get the length; check for truncation */ 3794edb46e9SPaul Traina if (bp + 1 >= snapend) { 3804edb46e9SPaul Traina fputs(tstr, stdout); 3814edb46e9SPaul Traina return; 3824edb46e9SPaul Traina } 3834edb46e9SPaul Traina len = *bp++; 3844edb46e9SPaul Traina if (bp + len >= snapend) { 385cc391cceSBruce M Simpson printf("[|bootp %u]", len); 3864edb46e9SPaul Traina return; 3874edb46e9SPaul Traina } 3884edb46e9SPaul Traina 389a88113a8SBill Fenner if (tag == TAG_DHCP_MESSAGE && len == 1) { 3900e0def19SBill Fenner uc = *bp++; 3910e0def19SBill Fenner switch (uc) { 392a88113a8SBill Fenner case DHCPDISCOVER: printf("DISCOVER"); break; 393a88113a8SBill Fenner case DHCPOFFER: printf("OFFER"); break; 394a88113a8SBill Fenner case DHCPREQUEST: printf("REQUEST"); break; 395a88113a8SBill Fenner case DHCPDECLINE: printf("DECLINE"); break; 396a88113a8SBill Fenner case DHCPACK: printf("ACK"); break; 397a88113a8SBill Fenner case DHCPNAK: printf("NACK"); break; 398a88113a8SBill Fenner case DHCPRELEASE: printf("RELEASE"); break; 399a88113a8SBill Fenner case DHCPINFORM: printf("INFORM"); break; 4000e0def19SBill Fenner default: printf("%u", uc); break; 401a88113a8SBill Fenner } 402a88113a8SBill Fenner continue; 403a88113a8SBill Fenner } 404a88113a8SBill Fenner 405a88113a8SBill Fenner if (tag == TAG_PARM_REQUEST) { 406a88113a8SBill Fenner first = 1; 407a88113a8SBill Fenner while (len-- > 0) { 4080e0def19SBill Fenner uc = *bp++; 4090e0def19SBill Fenner cp = tok2str(tag2str, "?T%u", uc); 410943ee2b1SBill Fenner if (!first) 411943ee2b1SBill Fenner putchar('+'); 412943ee2b1SBill Fenner printf("%s", cp + 1); 413943ee2b1SBill Fenner first = 0; 414943ee2b1SBill Fenner } 415943ee2b1SBill Fenner continue; 416943ee2b1SBill Fenner } 417943ee2b1SBill Fenner if (tag == TAG_EXTENDED_REQUEST) { 418943ee2b1SBill Fenner first = 1; 419943ee2b1SBill Fenner while (len > 1) { 420943ee2b1SBill Fenner len -= 2; 4210e0def19SBill Fenner us = EXTRACT_16BITS(bp); 422943ee2b1SBill Fenner bp += 2; 4230e0def19SBill Fenner cp = tok2str(xtag2str, "?xT%u", us); 424a88113a8SBill Fenner if (!first) 425a88113a8SBill Fenner putchar('+'); 426a88113a8SBill Fenner printf("%s", cp + 1); 427a88113a8SBill Fenner first = 0; 428a88113a8SBill Fenner } 429a88113a8SBill Fenner continue; 430a88113a8SBill Fenner } 431a88113a8SBill Fenner 4324edb46e9SPaul Traina /* Print data */ 4334edb46e9SPaul Traina size = len; 4344edb46e9SPaul Traina if (c == '?') { 4354edb46e9SPaul Traina /* Base default formats for unknown tags on data size */ 4364edb46e9SPaul Traina if (size & 1) 4374edb46e9SPaul Traina c = 'b'; 4384edb46e9SPaul Traina else if (size & 2) 4394edb46e9SPaul Traina c = 's'; 4404edb46e9SPaul Traina else 4414edb46e9SPaul Traina c = 'l'; 4424edb46e9SPaul Traina } 4434edb46e9SPaul Traina first = 1; 4444edb46e9SPaul Traina switch (c) { 4454edb46e9SPaul Traina 4464edb46e9SPaul Traina case 'a': 4474edb46e9SPaul Traina /* ascii strings */ 4484edb46e9SPaul Traina putchar('"'); 44929292c17SSam Leffler if (fn_printn(bp, size, snapend)) { 45029292c17SSam Leffler putchar('"'); 45129292c17SSam Leffler goto trunc; 45229292c17SSam Leffler } 4534edb46e9SPaul Traina putchar('"'); 4544edb46e9SPaul Traina bp += size; 4554edb46e9SPaul Traina size = 0; 4564edb46e9SPaul Traina break; 4574edb46e9SPaul Traina 4584edb46e9SPaul Traina case 'i': 4594edb46e9SPaul Traina case 'l': 460943ee2b1SBill Fenner case 'L': 4614edb46e9SPaul Traina /* ip addresses/32-bit words */ 4624edb46e9SPaul Traina while (size >= sizeof(ul)) { 4634edb46e9SPaul Traina if (!first) 4644edb46e9SPaul Traina putchar(','); 465943ee2b1SBill Fenner ul = EXTRACT_32BITS(bp); 466943ee2b1SBill Fenner if (c == 'i') { 467943ee2b1SBill Fenner ul = htonl(ul); 4684edb46e9SPaul Traina printf("%s", ipaddr_string(&ul)); 469943ee2b1SBill Fenner } else if (c == 'L') 470943ee2b1SBill Fenner printf("%d", ul); 4714edb46e9SPaul Traina else 4724edb46e9SPaul Traina printf("%u", ul); 4734edb46e9SPaul Traina bp += sizeof(ul); 4744edb46e9SPaul Traina size -= sizeof(ul); 4754edb46e9SPaul Traina first = 0; 4764edb46e9SPaul Traina } 4774edb46e9SPaul Traina break; 4784edb46e9SPaul Traina 479a88113a8SBill Fenner case 'p': 480a88113a8SBill Fenner /* IP address pairs */ 481a88113a8SBill Fenner while (size >= 2*sizeof(ul)) { 482a88113a8SBill Fenner if (!first) 483a88113a8SBill Fenner putchar(','); 484a1c2090eSBill Fenner memcpy((char *)&ul, (const char *)bp, sizeof(ul)); 485a88113a8SBill Fenner printf("(%s:", ipaddr_string(&ul)); 486a88113a8SBill Fenner bp += sizeof(ul); 487a1c2090eSBill Fenner memcpy((char *)&ul, (const char *)bp, sizeof(ul)); 488a88113a8SBill Fenner printf("%s)", ipaddr_string(&ul)); 489a88113a8SBill Fenner bp += sizeof(ul); 490a88113a8SBill Fenner size -= 2*sizeof(ul); 491a88113a8SBill Fenner first = 0; 492a88113a8SBill Fenner } 493a88113a8SBill Fenner break; 494a88113a8SBill Fenner 4954edb46e9SPaul Traina case 's': 4964edb46e9SPaul Traina /* shorts */ 4974edb46e9SPaul Traina while (size >= sizeof(us)) { 4984edb46e9SPaul Traina if (!first) 4994edb46e9SPaul Traina putchar(','); 500943ee2b1SBill Fenner us = EXTRACT_16BITS(bp); 5010e0def19SBill Fenner printf("%u", us); 5024edb46e9SPaul Traina bp += sizeof(us); 5034edb46e9SPaul Traina size -= sizeof(us); 5044edb46e9SPaul Traina first = 0; 5054edb46e9SPaul Traina } 5064edb46e9SPaul Traina break; 5074edb46e9SPaul Traina 508a88113a8SBill Fenner case 'B': 509a88113a8SBill Fenner /* boolean */ 510a88113a8SBill Fenner while (size > 0) { 511a88113a8SBill Fenner if (!first) 512a88113a8SBill Fenner putchar(','); 513a88113a8SBill Fenner switch (*bp) { 514a88113a8SBill Fenner case 0: 515a88113a8SBill Fenner putchar('N'); 516a88113a8SBill Fenner break; 517a88113a8SBill Fenner case 1: 518a88113a8SBill Fenner putchar('Y'); 519a88113a8SBill Fenner break; 520a88113a8SBill Fenner default: 5210e0def19SBill Fenner printf("%u?", *bp); 522a88113a8SBill Fenner break; 523a88113a8SBill Fenner } 524a88113a8SBill Fenner ++bp; 525a88113a8SBill Fenner --size; 526a88113a8SBill Fenner first = 0; 527a88113a8SBill Fenner } 528a88113a8SBill Fenner break; 529a88113a8SBill Fenner 5304edb46e9SPaul Traina case 'b': 531943ee2b1SBill Fenner case 'x': 5324edb46e9SPaul Traina default: 5334edb46e9SPaul Traina /* Bytes */ 5344edb46e9SPaul Traina while (size > 0) { 5354edb46e9SPaul Traina if (!first) 536943ee2b1SBill Fenner putchar(c == 'x' ? ':' : '.'); 537a1c2090eSBill Fenner if (c == 'x') 538a1c2090eSBill Fenner printf("%02x", *bp); 539a1c2090eSBill Fenner else 5400e0def19SBill Fenner printf("%u", *bp); 5414edb46e9SPaul Traina ++bp; 5424edb46e9SPaul Traina --size; 5434edb46e9SPaul Traina first = 0; 5444edb46e9SPaul Traina } 5454edb46e9SPaul Traina break; 546a1c2090eSBill Fenner 547a1c2090eSBill Fenner case '$': 548a1c2090eSBill Fenner /* Guys we can't handle with one of the usual cases */ 549a1c2090eSBill Fenner switch (tag) { 550a1c2090eSBill Fenner 551a1c2090eSBill Fenner case TAG_NETBIOS_NODE: 552a1c2090eSBill Fenner tag = *bp++; 553a1c2090eSBill Fenner --size; 554a1c2090eSBill Fenner fputs(tok2str(nbo2str, NULL, tag), stdout); 555a1c2090eSBill Fenner break; 556a1c2090eSBill Fenner 557a1c2090eSBill Fenner case TAG_OPT_OVERLOAD: 558a1c2090eSBill Fenner tag = *bp++; 559a1c2090eSBill Fenner --size; 560a1c2090eSBill Fenner fputs(tok2str(oo2str, NULL, tag), stdout); 561a1c2090eSBill Fenner break; 562a1c2090eSBill Fenner 563a1c2090eSBill Fenner case TAG_CLIENT_FQDN: 564cc391cceSBruce M Simpson /* option 81 should be at least 4 bytes long */ 56529292c17SSam Leffler if (len < 4) { 566cc391cceSBruce M Simpson printf("ERROR: options 81 len %u < 4 bytes", len); 567cc391cceSBruce M Simpson break; 56829292c17SSam Leffler } 569a1c2090eSBill Fenner if (*bp++) 570a1c2090eSBill Fenner printf("[svrreg]"); 571a1c2090eSBill Fenner if (*bp) 5720e0def19SBill Fenner printf("%u/%u/", *bp, *(bp+1)); 573a1c2090eSBill Fenner bp += 2; 574a1c2090eSBill Fenner putchar('"'); 57529292c17SSam Leffler if (fn_printn(bp, size - 3, snapend)) { 57629292c17SSam Leffler putchar('"'); 57729292c17SSam Leffler goto trunc; 57829292c17SSam Leffler } 579a1c2090eSBill Fenner putchar('"'); 580a1c2090eSBill Fenner bp += size - 3; 581a1c2090eSBill Fenner size = 0; 582a1c2090eSBill Fenner break; 583a1c2090eSBill Fenner 584a1c2090eSBill Fenner case TAG_CLIENT_ID: 585a1c2090eSBill Fenner { int type = *bp++; 586a1c2090eSBill Fenner size--; 587a1c2090eSBill Fenner if (type == 0) { 588a1c2090eSBill Fenner putchar('"'); 58929292c17SSam Leffler if (fn_printn(bp, size, snapend)) { 59029292c17SSam Leffler putchar('"'); 59129292c17SSam Leffler goto trunc; 59229292c17SSam Leffler } 593a1c2090eSBill Fenner putchar('"'); 594cc391cceSBruce M Simpson bp += size; 595cc391cceSBruce M Simpson size = 0; 596a1c2090eSBill Fenner break; 597a1c2090eSBill Fenner } else { 598a1c2090eSBill Fenner printf("[%s]", tok2str(arp2str, "type-%d", type)); 599a1c2090eSBill Fenner } 600a1c2090eSBill Fenner while (size > 0) { 601a1c2090eSBill Fenner if (!first) 602a1c2090eSBill Fenner putchar(':'); 603a1c2090eSBill Fenner printf("%02x", *bp); 604a1c2090eSBill Fenner ++bp; 605a1c2090eSBill Fenner --size; 606a1c2090eSBill Fenner first = 0; 607a1c2090eSBill Fenner } 608a1c2090eSBill Fenner break; 609a1c2090eSBill Fenner } 610a1c2090eSBill Fenner 611a1c2090eSBill Fenner default: 6120e0def19SBill Fenner printf("[unknown special tag %u, size %u]", 613a1c2090eSBill Fenner tag, size); 614a1c2090eSBill Fenner bp += size; 615a1c2090eSBill Fenner size = 0; 616a1c2090eSBill Fenner break; 617a1c2090eSBill Fenner } 618a1c2090eSBill Fenner break; 6194edb46e9SPaul Traina } 6204edb46e9SPaul Traina /* Data left over? */ 621cc391cceSBruce M Simpson if (size) { 6220e0def19SBill Fenner printf("[len %u]", len); 623cc391cceSBruce M Simpson bp += size; 624cc391cceSBruce M Simpson } 6254edb46e9SPaul Traina } 626943ee2b1SBill Fenner return; 627943ee2b1SBill Fenner trunc: 628943ee2b1SBill Fenner printf("|[rfc1048]"); 6294edb46e9SPaul Traina } 6304edb46e9SPaul Traina 6314edb46e9SPaul Traina static void 632a1c2090eSBill Fenner cmu_print(register const u_char *bp) 6334edb46e9SPaul Traina { 6344edb46e9SPaul Traina register const struct cmu_vend *cmu; 6354edb46e9SPaul Traina 6364edb46e9SPaul Traina #define PRINTCMUADDR(m, s) { TCHECK(cmu->m); \ 6374edb46e9SPaul Traina if (cmu->m.s_addr != 0) \ 638a1c2090eSBill Fenner printf(" %s:%s", s, ipaddr_string(&cmu->m.s_addr)); } 6394edb46e9SPaul Traina 6404edb46e9SPaul Traina printf(" vend-cmu"); 641a1c2090eSBill Fenner cmu = (const struct cmu_vend *)bp; 6424edb46e9SPaul Traina 6434edb46e9SPaul Traina /* Only print if there are unknown bits */ 6444edb46e9SPaul Traina TCHECK(cmu->v_flags); 6454edb46e9SPaul Traina if ((cmu->v_flags & ~(VF_SMASK)) != 0) 6464edb46e9SPaul Traina printf(" F:0x%x", cmu->v_flags); 6474edb46e9SPaul Traina PRINTCMUADDR(v_dgate, "DG"); 6484edb46e9SPaul Traina PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*"); 6494edb46e9SPaul Traina PRINTCMUADDR(v_dns1, "NS1"); 6504edb46e9SPaul Traina PRINTCMUADDR(v_dns2, "NS2"); 6514edb46e9SPaul Traina PRINTCMUADDR(v_ins1, "IEN1"); 6524edb46e9SPaul Traina PRINTCMUADDR(v_ins2, "IEN2"); 6534edb46e9SPaul Traina PRINTCMUADDR(v_ts1, "TS1"); 6544edb46e9SPaul Traina PRINTCMUADDR(v_ts2, "TS2"); 6554edb46e9SPaul Traina return; 6564edb46e9SPaul Traina 6574edb46e9SPaul Traina trunc: 6584edb46e9SPaul Traina fputs(tstr, stdout); 6594edb46e9SPaul Traina #undef PRINTCMUADDR 6604edb46e9SPaul Traina } 661