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[] = 27a1c2090eSBill Fenner "@(#) $Header: /tcpdump/master/tcpdump/print-bootp.c,v 1.60 2001/09/17 21:57:56 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 53a1c2090eSBill Fenner static void rfc1048_print(const u_char *); 54a1c2090eSBill Fenner static void cmu_print(const u_char *); 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; 66a1c2090eSBill Fenner static const u_char vm_cmu[4] = VM_CMU; 67a1c2090eSBill Fenner static const u_char vm_rfc1048[4] = VM_RFC1048; 684edb46e9SPaul Traina 69a1c2090eSBill Fenner bp = (const 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); 135a1c2090eSBill Fenner eh = (const 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; 142a1c2090eSBill Fenner if (e == 0 || memcmp((const 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]); 169a1c2090eSBill Fenner if (memcmp((const char *)bp->bp_vend, vm_rfc1048, 1704edb46e9SPaul Traina sizeof(u_int32_t)) == 0) 171a1c2090eSBill Fenner rfc1048_print(bp->bp_vend); 172a1c2090eSBill Fenner else if (memcmp((const char *)bp->bp_vend, vm_cmu, 1734edb46e9SPaul Traina sizeof(u_int32_t)) == 0) 174a1c2090eSBill Fenner cmu_print(bp->bp_vend); 1754edb46e9SPaul Traina else { 1764edb46e9SPaul Traina u_int32_t ul; 1774edb46e9SPaul Traina 178943ee2b1SBill Fenner ul = EXTRACT_32BITS(&bp->bp_vend); 1794edb46e9SPaul Traina if (ul != 0) 1804edb46e9SPaul Traina printf("vend-#0x%x", ul); 1814edb46e9SPaul Traina } 1824edb46e9SPaul Traina 1834edb46e9SPaul Traina return; 1844edb46e9SPaul Traina trunc: 1854edb46e9SPaul Traina fputs(tstr, stdout); 1864edb46e9SPaul Traina } 1874edb46e9SPaul Traina 188a1c2090eSBill Fenner /* 189a1c2090eSBill Fenner * The first character specifies the format to print: 190a1c2090eSBill Fenner * i - ip address (32 bits) 191a1c2090eSBill Fenner * p - ip address pairs (32 bits + 32 bits) 192a1c2090eSBill Fenner * l - long (32 bits) 193a1c2090eSBill Fenner * L - unsigned long (32 bits) 194a1c2090eSBill Fenner * s - short (16 bits) 195a1c2090eSBill Fenner * b - period-seperated decimal bytes (variable length) 196a1c2090eSBill Fenner * x - colon-seperated hex bytes (variable length) 197a1c2090eSBill Fenner * a - ascii string (variable length) 198a1c2090eSBill Fenner * B - on/off (8 bits) 199a1c2090eSBill Fenner * $ - special (explicit code to handle) 200a1c2090eSBill Fenner */ 2014edb46e9SPaul Traina static struct tok tag2str[] = { 2024edb46e9SPaul Traina /* RFC1048 tags */ 2034edb46e9SPaul Traina { TAG_PAD, " PAD" }, 2044edb46e9SPaul Traina { TAG_SUBNET_MASK, "iSM" }, /* subnet mask (RFC950) */ 205943ee2b1SBill Fenner { TAG_TIME_OFFSET, "LTZ" }, /* seconds from UTC */ 2064edb46e9SPaul Traina { TAG_GATEWAY, "iDG" }, /* default gateway */ 2074edb46e9SPaul Traina { TAG_TIME_SERVER, "iTS" }, /* time servers (RFC868) */ 2084edb46e9SPaul Traina { TAG_NAME_SERVER, "iIEN" }, /* IEN name servers (IEN116) */ 2094edb46e9SPaul Traina { TAG_DOMAIN_SERVER, "iNS" }, /* domain name (RFC1035) */ 2104edb46e9SPaul Traina { TAG_LOG_SERVER, "iLOG" }, /* MIT log servers */ 2114edb46e9SPaul Traina { TAG_COOKIE_SERVER, "iCS" }, /* cookie servers (RFC865) */ 2124edb46e9SPaul Traina { TAG_LPR_SERVER, "iLPR" }, /* lpr server (RFC1179) */ 2134edb46e9SPaul Traina { TAG_IMPRESS_SERVER, "iIM" }, /* impress servers (Imagen) */ 2144edb46e9SPaul Traina { TAG_RLP_SERVER, "iRL" }, /* resource location (RFC887) */ 2154edb46e9SPaul Traina { TAG_HOSTNAME, "aHN" }, /* ascii hostname */ 2164edb46e9SPaul Traina { TAG_BOOTSIZE, "sBS" }, /* 512 byte blocks */ 2174edb46e9SPaul Traina { TAG_END, " END" }, 2184edb46e9SPaul Traina /* RFC1497 tags */ 2194edb46e9SPaul Traina { TAG_DUMPPATH, "aDP" }, 2204edb46e9SPaul Traina { TAG_DOMAINNAME, "aDN" }, 2214edb46e9SPaul Traina { TAG_SWAP_SERVER, "iSS" }, 2224edb46e9SPaul Traina { TAG_ROOTPATH, "aRP" }, 2234edb46e9SPaul Traina { TAG_EXTPATH, "aEP" }, 224a88113a8SBill Fenner /* RFC2132 tags */ 225a88113a8SBill Fenner { TAG_IP_FORWARD, "BIPF" }, 226a88113a8SBill Fenner { TAG_NL_SRCRT, "BSRT" }, 227a88113a8SBill Fenner { TAG_PFILTERS, "pPF" }, 228a88113a8SBill Fenner { TAG_REASS_SIZE, "sRSZ" }, 229a88113a8SBill Fenner { TAG_DEF_TTL, "bTTL" }, 230a88113a8SBill Fenner { TAG_MTU_TIMEOUT, "lMA" }, 231a88113a8SBill Fenner { TAG_MTU_TABLE, "sMT" }, 232a88113a8SBill Fenner { TAG_INT_MTU, "sMTU" }, 233a88113a8SBill Fenner { TAG_LOCAL_SUBNETS, "BLSN" }, 234a88113a8SBill Fenner { TAG_BROAD_ADDR, "iBR" }, 235a88113a8SBill Fenner { TAG_DO_MASK_DISC, "BMD" }, 236a88113a8SBill Fenner { TAG_SUPPLY_MASK, "BMS" }, 237a88113a8SBill Fenner { TAG_DO_RDISC, "BRD" }, 238a88113a8SBill Fenner { TAG_RTR_SOL_ADDR, "iRSA" }, 239a88113a8SBill Fenner { TAG_STATIC_ROUTE, "pSR" }, 240a88113a8SBill Fenner { TAG_USE_TRAILERS, "BUT" }, 241a88113a8SBill Fenner { TAG_ARP_TIMEOUT, "lAT" }, 242a88113a8SBill Fenner { TAG_ETH_ENCAP, "BIE" }, 243a88113a8SBill Fenner { TAG_TCP_TTL, "bTT" }, 244a88113a8SBill Fenner { TAG_TCP_KEEPALIVE, "lKI" }, 245a88113a8SBill Fenner { TAG_KEEPALIVE_GO, "BKG" }, 246a88113a8SBill Fenner { TAG_NIS_DOMAIN, "aYD" }, 247a88113a8SBill Fenner { TAG_NIS_SERVERS, "iYS" }, 248a88113a8SBill Fenner { TAG_NTP_SERVERS, "iNTP" }, 249a88113a8SBill Fenner { TAG_VENDOR_OPTS, "bVO" }, 250a88113a8SBill Fenner { TAG_NETBIOS_NS, "iWNS" }, 251a88113a8SBill Fenner { TAG_NETBIOS_DDS, "iWDD" }, 252a1c2090eSBill Fenner { TAG_NETBIOS_NODE, "$WNT" }, 253a88113a8SBill Fenner { TAG_NETBIOS_SCOPE, "aWSC" }, 254a88113a8SBill Fenner { TAG_XWIN_FS, "iXFS" }, 255a88113a8SBill Fenner { TAG_XWIN_DM, "iXDM" }, 256a88113a8SBill Fenner { TAG_NIS_P_DOMAIN, "sN+D" }, 257a88113a8SBill Fenner { TAG_NIS_P_SERVERS, "iN+S" }, 258a88113a8SBill Fenner { TAG_MOBILE_HOME, "iMH" }, 259a88113a8SBill Fenner { TAG_SMPT_SERVER, "iSMTP" }, 260a88113a8SBill Fenner { TAG_POP3_SERVER, "iPOP3" }, 261a88113a8SBill Fenner { TAG_NNTP_SERVER, "iNNTP" }, 262a88113a8SBill Fenner { TAG_WWW_SERVER, "iWWW" }, 263a88113a8SBill Fenner { TAG_FINGER_SERVER, "iFG" }, 264a88113a8SBill Fenner { TAG_IRC_SERVER, "iIRC" }, 265a88113a8SBill Fenner { TAG_STREETTALK_SRVR, "iSTS" }, 266a88113a8SBill Fenner { TAG_STREETTALK_STDA, "iSTDA" }, 267a88113a8SBill Fenner { TAG_REQUESTED_IP, "iRQ" }, 268a88113a8SBill Fenner { TAG_IP_LEASE, "lLT" }, 269a1c2090eSBill Fenner { TAG_OPT_OVERLOAD, "$OO" }, 270a88113a8SBill Fenner { TAG_TFTP_SERVER, "aTFTP" }, 271a88113a8SBill Fenner { TAG_BOOTFILENAME, "aBF" }, 272a88113a8SBill Fenner { TAG_DHCP_MESSAGE, " DHCP" }, 273a88113a8SBill Fenner { TAG_SERVER_ID, "iSID" }, 274a88113a8SBill Fenner { TAG_PARM_REQUEST, "bPR" }, 275a88113a8SBill Fenner { TAG_MESSAGE, "aMSG" }, 276a88113a8SBill Fenner { TAG_MAX_MSG_SIZE, "sMSZ" }, 277a88113a8SBill Fenner { TAG_RENEWAL_TIME, "lRN" }, 278a88113a8SBill Fenner { TAG_REBIND_TIME, "lRB" }, 279a1c2090eSBill Fenner { TAG_VENDOR_CLASS, "aVC" }, 280a1c2090eSBill Fenner { TAG_CLIENT_ID, "$CID" }, 281943ee2b1SBill Fenner /* RFC 2485 */ 282943ee2b1SBill Fenner { TAG_OPEN_GROUP_UAP, "aUAP" }, 283943ee2b1SBill Fenner /* RFC 2563 */ 284943ee2b1SBill Fenner { TAG_DISABLE_AUTOCONF, "BNOAUTO" }, 285943ee2b1SBill Fenner /* RFC 2610 */ 286943ee2b1SBill Fenner { TAG_SLP_DA, "bSLP-DA" }, /*"b" is a little wrong */ 287943ee2b1SBill Fenner { TAG_SLP_SCOPE, "bSLP-SCOPE" }, /*"b" is a little wrong */ 288943ee2b1SBill Fenner /* RFC 2937 */ 289943ee2b1SBill Fenner { TAG_NS_SEARCH, "sNSSEARCH" }, /* XXX 's' */ 290943ee2b1SBill Fenner /* RFC 3011 */ 291943ee2b1SBill Fenner { TAG_IP4_SUBNET_SELECT, "iSUBNET" }, 292943ee2b1SBill Fenner /* ftp://ftp.isi.edu/.../assignments/bootp-dhcp-extensions */ 293943ee2b1SBill Fenner { TAG_USER_CLASS, "aCLASS" }, 294943ee2b1SBill Fenner { TAG_SLP_NAMING_AUTH, "aSLP-NA" }, 295a1c2090eSBill Fenner { TAG_CLIENT_FQDN, "$FQDN" }, 296943ee2b1SBill Fenner { TAG_AGENT_CIRCUIT, "bACKT" }, 297943ee2b1SBill Fenner { TAG_AGENT_REMOTE, "bARMT" }, 298943ee2b1SBill Fenner { TAG_AGENT_MASK, "bAMSK" }, 299943ee2b1SBill Fenner { TAG_TZ_STRING, "aTZSTR" }, 300943ee2b1SBill Fenner { TAG_FQDN_OPTION, "bFQDNS" }, /* XXX 'b' */ 301943ee2b1SBill Fenner { TAG_AUTH, "bAUTH" }, /* XXX 'b' */ 302943ee2b1SBill Fenner { TAG_VINES_SERVERS, "iVINES" }, 303943ee2b1SBill Fenner { TAG_SERVER_RANK, "sRANK" }, 304943ee2b1SBill Fenner { TAG_CLIENT_ARCH, "sARCH" }, 305943ee2b1SBill Fenner { TAG_CLIENT_NDI, "bNDI" }, /* XXX 'b' */ 306943ee2b1SBill Fenner { TAG_CLIENT_GUID, "bGUID" }, /* XXX 'b' */ 307943ee2b1SBill Fenner { TAG_LDAP_URL, "aLDAP" }, 308943ee2b1SBill Fenner { TAG_6OVER4, "i6o4" }, 309943ee2b1SBill Fenner { TAG_PRINTER_NAME, "aPRTR" }, 310943ee2b1SBill Fenner { TAG_MDHCP_SERVER, "bMDHCP" }, /* XXX 'b' */ 311943ee2b1SBill Fenner { TAG_IPX_COMPAT, "bIPX" }, /* XXX 'b' */ 312943ee2b1SBill Fenner { TAG_NETINFO_PARENT, "iNI" }, 313943ee2b1SBill Fenner { TAG_NETINFO_PARENT_TAG, "aNITAG" }, 314943ee2b1SBill Fenner { TAG_URL, "aURL" }, 315943ee2b1SBill Fenner { TAG_FAILOVER, "bFAIL" }, /* XXX 'b' */ 316943ee2b1SBill Fenner { 0, NULL } 317943ee2b1SBill Fenner }; 318943ee2b1SBill Fenner /* 2-byte extended tags */ 319943ee2b1SBill Fenner static struct tok xtag2str[] = { 3204edb46e9SPaul Traina { 0, NULL } 3214edb46e9SPaul Traina }; 3224edb46e9SPaul Traina 323a1c2090eSBill Fenner /* DHCP "options overload" types */ 324a1c2090eSBill Fenner static struct tok oo2str[] = { 325a1c2090eSBill Fenner { 1, "file" }, 326a1c2090eSBill Fenner { 2, "sname" }, 327a1c2090eSBill Fenner { 3, "file+sname" }, 328a1c2090eSBill Fenner { 0, NULL } 329a1c2090eSBill Fenner }; 330a1c2090eSBill Fenner 331a1c2090eSBill Fenner /* NETBIOS over TCP/IP node type options */ 332a1c2090eSBill Fenner static struct tok nbo2str[] = { 333a1c2090eSBill Fenner { 0x1, "b-node" }, 334a1c2090eSBill Fenner { 0x2, "p-node" }, 335a1c2090eSBill Fenner { 0x4, "m-node" }, 336a1c2090eSBill Fenner { 0x8, "h-node" }, 337a1c2090eSBill Fenner { 0, NULL } 338a1c2090eSBill Fenner }; 339a1c2090eSBill Fenner 340a1c2090eSBill Fenner /* ARP Hardware types, for Client-ID option */ 341a1c2090eSBill Fenner static struct tok arp2str[] = { 342a1c2090eSBill Fenner { 0x1, "ether" }, 343a1c2090eSBill Fenner { 0x6, "ieee802" }, 344a1c2090eSBill Fenner { 0x7, "arcnet" }, 345a1c2090eSBill Fenner { 0xf, "frelay" }, 346a1c2090eSBill Fenner { 0x17, "strip" }, 347a1c2090eSBill Fenner { 0x18, "ieee1394" }, 348a1c2090eSBill Fenner { 0, NULL } 349a1c2090eSBill Fenner }; 350a1c2090eSBill Fenner 3514edb46e9SPaul Traina static void 352a1c2090eSBill Fenner rfc1048_print(register const u_char *bp) 3534edb46e9SPaul Traina { 3544edb46e9SPaul Traina register u_char tag; 3554edb46e9SPaul Traina register u_int len, size; 3564edb46e9SPaul Traina register const char *cp; 3574edb46e9SPaul Traina register char c; 3584edb46e9SPaul Traina int first; 3594edb46e9SPaul Traina u_int32_t ul; 3604edb46e9SPaul Traina u_short us; 3614edb46e9SPaul Traina 3624edb46e9SPaul Traina printf(" vend-rfc1048"); 3634edb46e9SPaul Traina 3644edb46e9SPaul Traina /* Step over magic cookie */ 3654edb46e9SPaul Traina bp += sizeof(int32_t); 3664edb46e9SPaul Traina 3674edb46e9SPaul Traina /* Loop while we there is a tag left in the buffer */ 3684edb46e9SPaul Traina while (bp + 1 < snapend) { 3694edb46e9SPaul Traina tag = *bp++; 3704edb46e9SPaul Traina if (tag == TAG_PAD) 3714edb46e9SPaul Traina continue; 3724edb46e9SPaul Traina if (tag == TAG_END) 3734edb46e9SPaul Traina return; 374943ee2b1SBill Fenner if (tag == TAG_EXTENDED_OPTION) { 375943ee2b1SBill Fenner TCHECK2(*(bp + 1), 2); 376943ee2b1SBill Fenner tag = EXTRACT_16BITS(bp + 1); 377943ee2b1SBill Fenner /* XXX we don't know yet if the IANA will 378943ee2b1SBill Fenner * preclude overlap of 1-byte and 2-byte spaces. 379943ee2b1SBill Fenner * If not, we need to offset tag after this step. 380943ee2b1SBill Fenner */ 381943ee2b1SBill Fenner cp = tok2str(xtag2str, "?xT%d", tag); 382943ee2b1SBill Fenner } else 3834edb46e9SPaul Traina cp = tok2str(tag2str, "?T%d", tag); 3844edb46e9SPaul Traina c = *cp++; 3854edb46e9SPaul Traina printf(" %s:", cp); 3864edb46e9SPaul Traina 3874edb46e9SPaul Traina /* Get the length; check for truncation */ 3884edb46e9SPaul Traina if (bp + 1 >= snapend) { 3894edb46e9SPaul Traina fputs(tstr, stdout); 3904edb46e9SPaul Traina return; 3914edb46e9SPaul Traina } 3924edb46e9SPaul Traina len = *bp++; 3934edb46e9SPaul Traina if (bp + len >= snapend) { 3944edb46e9SPaul Traina fputs(tstr, stdout); 3954edb46e9SPaul Traina return; 3964edb46e9SPaul Traina } 3974edb46e9SPaul Traina 398a88113a8SBill Fenner if (tag == TAG_DHCP_MESSAGE && len == 1) { 399a88113a8SBill Fenner c = *bp++; 400a88113a8SBill Fenner switch (c) { 401a88113a8SBill Fenner case DHCPDISCOVER: printf("DISCOVER"); break; 402a88113a8SBill Fenner case DHCPOFFER: printf("OFFER"); break; 403a88113a8SBill Fenner case DHCPREQUEST: printf("REQUEST"); break; 404a88113a8SBill Fenner case DHCPDECLINE: printf("DECLINE"); break; 405a88113a8SBill Fenner case DHCPACK: printf("ACK"); break; 406a88113a8SBill Fenner case DHCPNAK: printf("NACK"); break; 407a88113a8SBill Fenner case DHCPRELEASE: printf("RELEASE"); break; 408a88113a8SBill Fenner case DHCPINFORM: printf("INFORM"); break; 409a88113a8SBill Fenner default: printf("%u", c); break; 410a88113a8SBill Fenner } 411a88113a8SBill Fenner continue; 412a88113a8SBill Fenner } 413a88113a8SBill Fenner 414a88113a8SBill Fenner if (tag == TAG_PARM_REQUEST) { 415a88113a8SBill Fenner first = 1; 416a88113a8SBill Fenner while (len-- > 0) { 417a88113a8SBill Fenner c = *bp++; 418943ee2b1SBill Fenner cp = tok2str(tag2str, "?T%d", c); 419943ee2b1SBill Fenner if (!first) 420943ee2b1SBill Fenner putchar('+'); 421943ee2b1SBill Fenner printf("%s", cp + 1); 422943ee2b1SBill Fenner first = 0; 423943ee2b1SBill Fenner } 424943ee2b1SBill Fenner continue; 425943ee2b1SBill Fenner } 426943ee2b1SBill Fenner if (tag == TAG_EXTENDED_REQUEST) { 427943ee2b1SBill Fenner first = 1; 428943ee2b1SBill Fenner while (len > 1) { 429943ee2b1SBill Fenner len -= 2; 430943ee2b1SBill Fenner c = EXTRACT_16BITS(bp); 431943ee2b1SBill Fenner bp += 2; 432943ee2b1SBill Fenner cp = tok2str(xtag2str, "?xT%d", c); 433a88113a8SBill Fenner if (!first) 434a88113a8SBill Fenner putchar('+'); 435a88113a8SBill Fenner printf("%s", cp + 1); 436a88113a8SBill Fenner first = 0; 437a88113a8SBill Fenner } 438a88113a8SBill Fenner continue; 439a88113a8SBill Fenner } 440a88113a8SBill Fenner 4414edb46e9SPaul Traina /* Print data */ 4424edb46e9SPaul Traina size = len; 4434edb46e9SPaul Traina if (c == '?') { 4444edb46e9SPaul Traina /* Base default formats for unknown tags on data size */ 4454edb46e9SPaul Traina if (size & 1) 4464edb46e9SPaul Traina c = 'b'; 4474edb46e9SPaul Traina else if (size & 2) 4484edb46e9SPaul Traina c = 's'; 4494edb46e9SPaul Traina else 4504edb46e9SPaul Traina c = 'l'; 4514edb46e9SPaul Traina } 4524edb46e9SPaul Traina first = 1; 4534edb46e9SPaul Traina switch (c) { 4544edb46e9SPaul Traina 4554edb46e9SPaul Traina case 'a': 4564edb46e9SPaul Traina /* ascii strings */ 4574edb46e9SPaul Traina putchar('"'); 4584edb46e9SPaul Traina (void)fn_printn(bp, size, NULL); 4594edb46e9SPaul Traina putchar('"'); 4604edb46e9SPaul Traina bp += size; 4614edb46e9SPaul Traina size = 0; 4624edb46e9SPaul Traina break; 4634edb46e9SPaul Traina 4644edb46e9SPaul Traina case 'i': 4654edb46e9SPaul Traina case 'l': 466943ee2b1SBill Fenner case 'L': 4674edb46e9SPaul Traina /* ip addresses/32-bit words */ 4684edb46e9SPaul Traina while (size >= sizeof(ul)) { 4694edb46e9SPaul Traina if (!first) 4704edb46e9SPaul Traina putchar(','); 471943ee2b1SBill Fenner ul = EXTRACT_32BITS(bp); 472943ee2b1SBill Fenner if (c == 'i') { 473943ee2b1SBill Fenner ul = htonl(ul); 4744edb46e9SPaul Traina printf("%s", ipaddr_string(&ul)); 475943ee2b1SBill Fenner } else if (c == 'L') 476943ee2b1SBill Fenner printf("%d", ul); 4774edb46e9SPaul Traina else 4784edb46e9SPaul Traina printf("%u", ul); 4794edb46e9SPaul Traina bp += sizeof(ul); 4804edb46e9SPaul Traina size -= sizeof(ul); 4814edb46e9SPaul Traina first = 0; 4824edb46e9SPaul Traina } 4834edb46e9SPaul Traina break; 4844edb46e9SPaul Traina 485a88113a8SBill Fenner case 'p': 486a88113a8SBill Fenner /* IP address pairs */ 487a88113a8SBill Fenner while (size >= 2*sizeof(ul)) { 488a88113a8SBill Fenner if (!first) 489a88113a8SBill Fenner putchar(','); 490a1c2090eSBill Fenner memcpy((char *)&ul, (const char *)bp, sizeof(ul)); 491a88113a8SBill Fenner printf("(%s:", ipaddr_string(&ul)); 492a88113a8SBill Fenner bp += sizeof(ul); 493a1c2090eSBill Fenner memcpy((char *)&ul, (const char *)bp, sizeof(ul)); 494a88113a8SBill Fenner printf("%s)", ipaddr_string(&ul)); 495a88113a8SBill Fenner bp += sizeof(ul); 496a88113a8SBill Fenner size -= 2*sizeof(ul); 497a88113a8SBill Fenner first = 0; 498a88113a8SBill Fenner } 499a88113a8SBill Fenner break; 500a88113a8SBill Fenner 5014edb46e9SPaul Traina case 's': 5024edb46e9SPaul Traina /* shorts */ 5034edb46e9SPaul Traina while (size >= sizeof(us)) { 5044edb46e9SPaul Traina if (!first) 5054edb46e9SPaul Traina putchar(','); 506943ee2b1SBill Fenner us = EXTRACT_16BITS(bp); 5074edb46e9SPaul Traina printf("%d", us); 5084edb46e9SPaul Traina bp += sizeof(us); 5094edb46e9SPaul Traina size -= sizeof(us); 5104edb46e9SPaul Traina first = 0; 5114edb46e9SPaul Traina } 5124edb46e9SPaul Traina break; 5134edb46e9SPaul Traina 514a88113a8SBill Fenner case 'B': 515a88113a8SBill Fenner /* boolean */ 516a88113a8SBill Fenner while (size > 0) { 517a88113a8SBill Fenner if (!first) 518a88113a8SBill Fenner putchar(','); 519a88113a8SBill Fenner switch (*bp) { 520a88113a8SBill Fenner case 0: 521a88113a8SBill Fenner putchar('N'); 522a88113a8SBill Fenner break; 523a88113a8SBill Fenner case 1: 524a88113a8SBill Fenner putchar('Y'); 525a88113a8SBill Fenner break; 526a88113a8SBill Fenner default: 527a88113a8SBill Fenner printf("%d?", *bp); 528a88113a8SBill Fenner break; 529a88113a8SBill Fenner } 530a88113a8SBill Fenner ++bp; 531a88113a8SBill Fenner --size; 532a88113a8SBill Fenner first = 0; 533a88113a8SBill Fenner } 534a88113a8SBill Fenner break; 535a88113a8SBill Fenner 5364edb46e9SPaul Traina case 'b': 537943ee2b1SBill Fenner case 'x': 5384edb46e9SPaul Traina default: 5394edb46e9SPaul Traina /* Bytes */ 5404edb46e9SPaul Traina while (size > 0) { 5414edb46e9SPaul Traina if (!first) 542943ee2b1SBill Fenner putchar(c == 'x' ? ':' : '.'); 543a1c2090eSBill Fenner if (c == 'x') 544a1c2090eSBill Fenner printf("%02x", *bp); 545a1c2090eSBill Fenner else 546a1c2090eSBill Fenner printf("%d", *bp); 5474edb46e9SPaul Traina ++bp; 5484edb46e9SPaul Traina --size; 5494edb46e9SPaul Traina first = 0; 5504edb46e9SPaul Traina } 5514edb46e9SPaul Traina break; 552a1c2090eSBill Fenner 553a1c2090eSBill Fenner case '$': 554a1c2090eSBill Fenner /* Guys we can't handle with one of the usual cases */ 555a1c2090eSBill Fenner switch (tag) { 556a1c2090eSBill Fenner 557a1c2090eSBill Fenner case TAG_NETBIOS_NODE: 558a1c2090eSBill Fenner tag = *bp++; 559a1c2090eSBill Fenner --size; 560a1c2090eSBill Fenner fputs(tok2str(nbo2str, NULL, tag), stdout); 561a1c2090eSBill Fenner break; 562a1c2090eSBill Fenner 563a1c2090eSBill Fenner case TAG_OPT_OVERLOAD: 564a1c2090eSBill Fenner tag = *bp++; 565a1c2090eSBill Fenner --size; 566a1c2090eSBill Fenner fputs(tok2str(oo2str, NULL, tag), stdout); 567a1c2090eSBill Fenner break; 568a1c2090eSBill Fenner 569a1c2090eSBill Fenner case TAG_CLIENT_FQDN: 570a1c2090eSBill Fenner if (*bp++) 571a1c2090eSBill Fenner printf("[svrreg]"); 572a1c2090eSBill Fenner if (*bp) 573a1c2090eSBill Fenner printf("%d/%d/", *bp, *(bp+1)); 574a1c2090eSBill Fenner bp += 2; 575a1c2090eSBill Fenner putchar('"'); 576a1c2090eSBill Fenner (void)fn_printn(bp, size - 3, NULL); 577a1c2090eSBill Fenner putchar('"'); 578a1c2090eSBill Fenner bp += size - 3; 579a1c2090eSBill Fenner size = 0; 580a1c2090eSBill Fenner break; 581a1c2090eSBill Fenner 582a1c2090eSBill Fenner case TAG_CLIENT_ID: 583a1c2090eSBill Fenner { int type = *bp++; 584a1c2090eSBill Fenner size--; 585a1c2090eSBill Fenner if (type == 0) { 586a1c2090eSBill Fenner putchar('"'); 587a1c2090eSBill Fenner (void)fn_printn(bp, size, NULL); 588a1c2090eSBill Fenner putchar('"'); 589a1c2090eSBill Fenner break; 590a1c2090eSBill Fenner } else { 591a1c2090eSBill Fenner printf("[%s]", tok2str(arp2str, "type-%d", type)); 592a1c2090eSBill Fenner } 593a1c2090eSBill Fenner while (size > 0) { 594a1c2090eSBill Fenner if (!first) 595a1c2090eSBill Fenner putchar(':'); 596a1c2090eSBill Fenner printf("%02x", *bp); 597a1c2090eSBill Fenner ++bp; 598a1c2090eSBill Fenner --size; 599a1c2090eSBill Fenner first = 0; 600a1c2090eSBill Fenner } 601a1c2090eSBill Fenner break; 602a1c2090eSBill Fenner } 603a1c2090eSBill Fenner 604a1c2090eSBill Fenner default: 605a1c2090eSBill Fenner printf("[unknown special tag %d, size %d]", 606a1c2090eSBill Fenner tag, size); 607a1c2090eSBill Fenner bp += size; 608a1c2090eSBill Fenner size = 0; 609a1c2090eSBill Fenner break; 610a1c2090eSBill Fenner } 611a1c2090eSBill Fenner break; 6124edb46e9SPaul Traina } 6134edb46e9SPaul Traina /* Data left over? */ 6144edb46e9SPaul Traina if (size) 6154edb46e9SPaul Traina printf("[len %d]", len); 6164edb46e9SPaul Traina } 617943ee2b1SBill Fenner return; 618943ee2b1SBill Fenner trunc: 619943ee2b1SBill Fenner printf("|[rfc1048]"); 6204edb46e9SPaul Traina } 6214edb46e9SPaul Traina 6224edb46e9SPaul Traina static void 623a1c2090eSBill Fenner cmu_print(register const u_char *bp) 6244edb46e9SPaul Traina { 6254edb46e9SPaul Traina register const struct cmu_vend *cmu; 6264edb46e9SPaul Traina 6274edb46e9SPaul Traina #define PRINTCMUADDR(m, s) { TCHECK(cmu->m); \ 6284edb46e9SPaul Traina if (cmu->m.s_addr != 0) \ 629a1c2090eSBill Fenner printf(" %s:%s", s, ipaddr_string(&cmu->m.s_addr)); } 6304edb46e9SPaul Traina 6314edb46e9SPaul Traina printf(" vend-cmu"); 632a1c2090eSBill Fenner cmu = (const struct cmu_vend *)bp; 6334edb46e9SPaul Traina 6344edb46e9SPaul Traina /* Only print if there are unknown bits */ 6354edb46e9SPaul Traina TCHECK(cmu->v_flags); 6364edb46e9SPaul Traina if ((cmu->v_flags & ~(VF_SMASK)) != 0) 6374edb46e9SPaul Traina printf(" F:0x%x", cmu->v_flags); 6384edb46e9SPaul Traina PRINTCMUADDR(v_dgate, "DG"); 6394edb46e9SPaul Traina PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*"); 6404edb46e9SPaul Traina PRINTCMUADDR(v_dns1, "NS1"); 6414edb46e9SPaul Traina PRINTCMUADDR(v_dns2, "NS2"); 6424edb46e9SPaul Traina PRINTCMUADDR(v_ins1, "IEN1"); 6434edb46e9SPaul Traina PRINTCMUADDR(v_ins2, "IEN2"); 6444edb46e9SPaul Traina PRINTCMUADDR(v_ts1, "TS1"); 6454edb46e9SPaul Traina PRINTCMUADDR(v_ts2, "TS2"); 6464edb46e9SPaul Traina return; 6474edb46e9SPaul Traina 6484edb46e9SPaul Traina trunc: 6494edb46e9SPaul Traina fputs(tstr, stdout); 6504edb46e9SPaul Traina #undef PRINTCMUADDR 6514edb46e9SPaul Traina } 652