14edb46e9SPaul Traina /* 24edb46e9SPaul Traina * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996 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. 224edb46e9SPaul Traina */ 234edb46e9SPaul Traina #ifndef lint 244edb46e9SPaul Traina static char rcsid[] = 254edb46e9SPaul Traina "@(#) $Header: print-bootp.c,v 1.42 96/07/23 14:17:22 leres Exp $ (LBL)"; 264edb46e9SPaul Traina #endif 274edb46e9SPaul Traina 284edb46e9SPaul Traina #include <sys/param.h> 294edb46e9SPaul Traina #include <sys/time.h> 304edb46e9SPaul Traina #include <sys/socket.h> 314edb46e9SPaul Traina 324edb46e9SPaul Traina #if __STDC__ 334edb46e9SPaul Traina struct mbuf; 344edb46e9SPaul Traina struct rtentry; 354edb46e9SPaul Traina #endif 364edb46e9SPaul Traina #include <net/if.h> 374edb46e9SPaul Traina 384edb46e9SPaul Traina #include <netinet/in.h> 394edb46e9SPaul Traina #include <netinet/if_ether.h> 404edb46e9SPaul Traina 414edb46e9SPaul Traina #include <ctype.h> 424edb46e9SPaul Traina #include <stdio.h> 434edb46e9SPaul Traina #include <string.h> 444edb46e9SPaul Traina 454edb46e9SPaul Traina #include "interface.h" 464edb46e9SPaul Traina #include "addrtoname.h" 474edb46e9SPaul Traina #include "bootp.h" 484edb46e9SPaul Traina 494edb46e9SPaul Traina static void rfc1048_print(const u_char *, u_int); 504edb46e9SPaul Traina static void cmu_print(const u_char *, u_int); 514edb46e9SPaul Traina 524edb46e9SPaul Traina static char tstr[] = " [|bootp]"; 534edb46e9SPaul Traina 544edb46e9SPaul Traina /* 554edb46e9SPaul Traina * Print bootp requests 564edb46e9SPaul Traina */ 574edb46e9SPaul Traina void 584edb46e9SPaul Traina bootp_print(register const u_char *cp, u_int length, 594edb46e9SPaul Traina u_short sport, u_short dport) 604edb46e9SPaul Traina { 614edb46e9SPaul Traina register const struct bootp *bp; 624edb46e9SPaul Traina static u_char vm_cmu[4] = VM_CMU; 634edb46e9SPaul Traina static u_char vm_rfc1048[4] = VM_RFC1048; 644edb46e9SPaul Traina 654edb46e9SPaul Traina bp = (struct bootp *)cp; 664edb46e9SPaul Traina TCHECK(bp->bp_op); 674edb46e9SPaul Traina switch (bp->bp_op) { 684edb46e9SPaul Traina 694edb46e9SPaul Traina case BOOTREQUEST: 704edb46e9SPaul Traina /* Usually, a request goes from a client to a server */ 714edb46e9SPaul Traina if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS) 724edb46e9SPaul Traina printf(" (request)"); 734edb46e9SPaul Traina break; 744edb46e9SPaul Traina 754edb46e9SPaul Traina case BOOTREPLY: 764edb46e9SPaul Traina /* Usually, a reply goes from a server to a client */ 774edb46e9SPaul Traina if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC) 784edb46e9SPaul Traina printf(" (reply)"); 794edb46e9SPaul Traina break; 804edb46e9SPaul Traina 814edb46e9SPaul Traina default: 824edb46e9SPaul Traina printf(" bootp-#%d", bp->bp_op); 834edb46e9SPaul Traina } 844edb46e9SPaul Traina 854edb46e9SPaul Traina TCHECK(bp->bp_secs); 864edb46e9SPaul Traina 874edb46e9SPaul Traina /* The usual hardware address type is 1 (10Mb Ethernet) */ 884edb46e9SPaul Traina if (bp->bp_htype != 1) 894edb46e9SPaul Traina printf(" htype-#%d", bp->bp_htype); 904edb46e9SPaul Traina 914edb46e9SPaul Traina /* The usual length for 10Mb Ethernet address is 6 bytes */ 924edb46e9SPaul Traina if (bp->bp_htype != 1 || bp->bp_hlen != 6) 934edb46e9SPaul Traina printf(" hlen:%d", bp->bp_hlen); 944edb46e9SPaul Traina 954edb46e9SPaul Traina /* Only print interesting fields */ 964edb46e9SPaul Traina if (bp->bp_hops) 974edb46e9SPaul Traina printf(" hops:%d", bp->bp_hops); 984edb46e9SPaul Traina if (bp->bp_xid) 994edb46e9SPaul Traina printf(" xid:0x%x", (u_int32_t)ntohl(bp->bp_xid)); 1004edb46e9SPaul Traina if (bp->bp_secs) 1014edb46e9SPaul Traina printf(" secs:%d", ntohs(bp->bp_secs)); 1024edb46e9SPaul Traina 1034edb46e9SPaul Traina /* Client's ip address */ 1044edb46e9SPaul Traina TCHECK(bp->bp_ciaddr); 1054edb46e9SPaul Traina if (bp->bp_ciaddr.s_addr) 1064edb46e9SPaul Traina printf(" C:%s", ipaddr_string(&bp->bp_ciaddr)); 1074edb46e9SPaul Traina 1084edb46e9SPaul Traina /* 'your' ip address (bootp client) */ 1094edb46e9SPaul Traina TCHECK(bp->bp_yiaddr); 1104edb46e9SPaul Traina if (bp->bp_yiaddr.s_addr) 1114edb46e9SPaul Traina printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr)); 1124edb46e9SPaul Traina 1134edb46e9SPaul Traina /* Server's ip address */ 1144edb46e9SPaul Traina TCHECK(bp->bp_siaddr); 1154edb46e9SPaul Traina if (bp->bp_siaddr.s_addr) 1164edb46e9SPaul Traina printf(" S:%s", ipaddr_string(&bp->bp_siaddr)); 1174edb46e9SPaul Traina 1184edb46e9SPaul Traina /* Gateway's ip address */ 1194edb46e9SPaul Traina TCHECK(bp->bp_giaddr); 1204edb46e9SPaul Traina if (bp->bp_giaddr.s_addr) 1214edb46e9SPaul Traina printf(" G:%s", ipaddr_string(&bp->bp_giaddr)); 1224edb46e9SPaul Traina 1234edb46e9SPaul Traina /* Client's Ethernet address */ 1244edb46e9SPaul Traina if (bp->bp_htype == 1 && bp->bp_hlen == 6) { 1254edb46e9SPaul Traina register const struct ether_header *eh; 1264edb46e9SPaul Traina register const char *e; 1274edb46e9SPaul Traina 1284edb46e9SPaul Traina TCHECK2(bp->bp_chaddr[0], 6); 1294edb46e9SPaul Traina eh = (struct ether_header *)packetp; 1304edb46e9SPaul Traina if (bp->bp_op == BOOTREQUEST) 1314edb46e9SPaul Traina e = (const char *)ESRC(eh); 1324edb46e9SPaul Traina else if (bp->bp_op == BOOTREPLY) 1334edb46e9SPaul Traina e = (const char *)EDST(eh); 1344edb46e9SPaul Traina else 1354edb46e9SPaul Traina e = 0; 1364edb46e9SPaul Traina if (e == 0 || memcmp((char *)bp->bp_chaddr, e, 6) != 0) 1374edb46e9SPaul Traina printf(" ether %s", etheraddr_string(bp->bp_chaddr)); 1384edb46e9SPaul Traina } 1394edb46e9SPaul Traina 1404edb46e9SPaul Traina TCHECK2(bp->bp_sname[0], 1); /* check first char only */ 1414edb46e9SPaul Traina if (*bp->bp_sname) { 1424edb46e9SPaul Traina printf(" sname \""); 1434edb46e9SPaul Traina if (fn_print(bp->bp_sname, snapend)) { 1444edb46e9SPaul Traina putchar('"'); 1454edb46e9SPaul Traina fputs(tstr + 1, stdout); 1464edb46e9SPaul Traina return; 1474edb46e9SPaul Traina } 1484edb46e9SPaul Traina } 1494edb46e9SPaul Traina TCHECK2(bp->bp_sname[0], 1); /* check first char only */ 1504edb46e9SPaul Traina if (*bp->bp_file) { 1514edb46e9SPaul Traina printf(" file \""); 1524edb46e9SPaul Traina if (fn_print(bp->bp_file, snapend)) { 1534edb46e9SPaul Traina putchar('"'); 1544edb46e9SPaul Traina fputs(tstr + 1, stdout); 1554edb46e9SPaul Traina return; 1564edb46e9SPaul Traina } 1574edb46e9SPaul Traina } 1584edb46e9SPaul Traina 1594edb46e9SPaul Traina /* Decode the vendor buffer */ 1604edb46e9SPaul Traina TCHECK(bp->bp_vend[0]); 1614edb46e9SPaul Traina length -= sizeof(*bp) - sizeof(bp->bp_vend); 1624edb46e9SPaul Traina if (memcmp((char *)bp->bp_vend, (char *)vm_rfc1048, 1634edb46e9SPaul Traina sizeof(u_int32_t)) == 0) 1644edb46e9SPaul Traina rfc1048_print(bp->bp_vend, length); 1654edb46e9SPaul Traina else if (memcmp((char *)bp->bp_vend, (char *)vm_cmu, 1664edb46e9SPaul Traina sizeof(u_int32_t)) == 0) 1674edb46e9SPaul Traina cmu_print(bp->bp_vend, length); 1684edb46e9SPaul Traina else { 1694edb46e9SPaul Traina u_int32_t ul; 1704edb46e9SPaul Traina 1714edb46e9SPaul Traina memcpy((char *)&ul, (char *)bp->bp_vend, sizeof(ul)); 1724edb46e9SPaul Traina if (ul != 0) 1734edb46e9SPaul Traina printf("vend-#0x%x", ul); 1744edb46e9SPaul Traina } 1754edb46e9SPaul Traina 1764edb46e9SPaul Traina return; 1774edb46e9SPaul Traina trunc: 1784edb46e9SPaul Traina fputs(tstr, stdout); 1794edb46e9SPaul Traina } 1804edb46e9SPaul Traina 1814edb46e9SPaul Traina /* The first character specifies the format to print */ 1824edb46e9SPaul Traina static struct tok tag2str[] = { 1834edb46e9SPaul Traina /* RFC1048 tags */ 1844edb46e9SPaul Traina { TAG_PAD, " PAD" }, 1854edb46e9SPaul Traina { TAG_SUBNET_MASK, "iSM" }, /* subnet mask (RFC950) */ 1864edb46e9SPaul Traina { TAG_TIME_OFFSET, "lTZ" }, /* seconds from UTC */ 1874edb46e9SPaul Traina { TAG_GATEWAY, "iDG" }, /* default gateway */ 1884edb46e9SPaul Traina { TAG_TIME_SERVER, "iTS" }, /* time servers (RFC868) */ 1894edb46e9SPaul Traina { TAG_NAME_SERVER, "iIEN" }, /* IEN name servers (IEN116) */ 1904edb46e9SPaul Traina { TAG_DOMAIN_SERVER, "iNS" }, /* domain name (RFC1035) */ 1914edb46e9SPaul Traina { TAG_LOG_SERVER, "iLOG" }, /* MIT log servers */ 1924edb46e9SPaul Traina { TAG_COOKIE_SERVER, "iCS" }, /* cookie servers (RFC865) */ 1934edb46e9SPaul Traina { TAG_LPR_SERVER, "iLPR" }, /* lpr server (RFC1179) */ 1944edb46e9SPaul Traina { TAG_IMPRESS_SERVER, "iIM" }, /* impress servers (Imagen) */ 1954edb46e9SPaul Traina { TAG_RLP_SERVER, "iRL" }, /* resource location (RFC887) */ 1964edb46e9SPaul Traina { TAG_HOSTNAME, "aHN" }, /* ascii hostname */ 1974edb46e9SPaul Traina { TAG_BOOTSIZE, "sBS" }, /* 512 byte blocks */ 1984edb46e9SPaul Traina { TAG_END, " END" }, 1994edb46e9SPaul Traina /* RFC1497 tags */ 2004edb46e9SPaul Traina { TAG_DUMPPATH, "aDP" }, 2014edb46e9SPaul Traina { TAG_DOMAINNAME, "aDN" }, 2024edb46e9SPaul Traina { TAG_SWAP_SERVER, "iSS" }, 2034edb46e9SPaul Traina { TAG_ROOTPATH, "aRP" }, 2044edb46e9SPaul Traina { TAG_EXTPATH, "aEP" }, 2054edb46e9SPaul Traina { 0, NULL } 2064edb46e9SPaul Traina }; 2074edb46e9SPaul Traina 2084edb46e9SPaul Traina static void 2094edb46e9SPaul Traina rfc1048_print(register const u_char *bp, register u_int length) 2104edb46e9SPaul Traina { 2114edb46e9SPaul Traina register u_char tag; 2124edb46e9SPaul Traina register u_int len, size; 2134edb46e9SPaul Traina register const char *cp; 2144edb46e9SPaul Traina register char c; 2154edb46e9SPaul Traina int first; 2164edb46e9SPaul Traina u_int32_t ul; 2174edb46e9SPaul Traina u_short us; 2184edb46e9SPaul Traina 2194edb46e9SPaul Traina printf(" vend-rfc1048"); 2204edb46e9SPaul Traina 2214edb46e9SPaul Traina /* Step over magic cookie */ 2224edb46e9SPaul Traina bp += sizeof(int32_t); 2234edb46e9SPaul Traina 2244edb46e9SPaul Traina /* Loop while we there is a tag left in the buffer */ 2254edb46e9SPaul Traina while (bp + 1 < snapend) { 2264edb46e9SPaul Traina tag = *bp++; 2274edb46e9SPaul Traina if (tag == TAG_PAD) 2284edb46e9SPaul Traina continue; 2294edb46e9SPaul Traina if (tag == TAG_END) 2304edb46e9SPaul Traina return; 2314edb46e9SPaul Traina cp = tok2str(tag2str, "?T%d", tag); 2324edb46e9SPaul Traina c = *cp++; 2334edb46e9SPaul Traina printf(" %s:", cp); 2344edb46e9SPaul Traina 2354edb46e9SPaul Traina /* Get the length; check for truncation */ 2364edb46e9SPaul Traina if (bp + 1 >= snapend) { 2374edb46e9SPaul Traina fputs(tstr, stdout); 2384edb46e9SPaul Traina return; 2394edb46e9SPaul Traina } 2404edb46e9SPaul Traina len = *bp++; 2414edb46e9SPaul Traina if (bp + len >= snapend) { 2424edb46e9SPaul Traina fputs(tstr, stdout); 2434edb46e9SPaul Traina return; 2444edb46e9SPaul Traina } 2454edb46e9SPaul Traina 2464edb46e9SPaul Traina /* Print data */ 2474edb46e9SPaul Traina size = len; 2484edb46e9SPaul Traina if (c == '?') { 2494edb46e9SPaul Traina /* Base default formats for unknown tags on data size */ 2504edb46e9SPaul Traina if (size & 1) 2514edb46e9SPaul Traina c = 'b'; 2524edb46e9SPaul Traina else if (size & 2) 2534edb46e9SPaul Traina c = 's'; 2544edb46e9SPaul Traina else 2554edb46e9SPaul Traina c = 'l'; 2564edb46e9SPaul Traina } 2574edb46e9SPaul Traina first = 1; 2584edb46e9SPaul Traina switch (c) { 2594edb46e9SPaul Traina 2604edb46e9SPaul Traina case 'a': 2614edb46e9SPaul Traina /* ascii strings */ 2624edb46e9SPaul Traina putchar('"'); 2634edb46e9SPaul Traina (void)fn_printn(bp, size, NULL); 2644edb46e9SPaul Traina putchar('"'); 2654edb46e9SPaul Traina bp += size; 2664edb46e9SPaul Traina size = 0; 2674edb46e9SPaul Traina break; 2684edb46e9SPaul Traina 2694edb46e9SPaul Traina case 'i': 2704edb46e9SPaul Traina case 'l': 2714edb46e9SPaul Traina /* ip addresses/32-bit words */ 2724edb46e9SPaul Traina while (size >= sizeof(ul)) { 2734edb46e9SPaul Traina if (!first) 2744edb46e9SPaul Traina putchar(','); 2754edb46e9SPaul Traina memcpy((char *)&ul, (char *)bp, sizeof(ul)); 2764edb46e9SPaul Traina if (c == 'i') 2774edb46e9SPaul Traina printf("%s", ipaddr_string(&ul)); 2784edb46e9SPaul Traina else 2794edb46e9SPaul Traina printf("%u", ul); 2804edb46e9SPaul Traina bp += sizeof(ul); 2814edb46e9SPaul Traina size -= sizeof(ul); 2824edb46e9SPaul Traina first = 0; 2834edb46e9SPaul Traina } 2844edb46e9SPaul Traina break; 2854edb46e9SPaul Traina 2864edb46e9SPaul Traina case 's': 2874edb46e9SPaul Traina /* shorts */ 2884edb46e9SPaul Traina while (size >= sizeof(us)) { 2894edb46e9SPaul Traina if (!first) 2904edb46e9SPaul Traina putchar(','); 2914edb46e9SPaul Traina memcpy((char *)&us, (char *)bp, sizeof(us)); 2924edb46e9SPaul Traina printf("%d", us); 2934edb46e9SPaul Traina bp += sizeof(us); 2944edb46e9SPaul Traina size -= sizeof(us); 2954edb46e9SPaul Traina first = 0; 2964edb46e9SPaul Traina } 2974edb46e9SPaul Traina break; 2984edb46e9SPaul Traina 2994edb46e9SPaul Traina case 'b': 3004edb46e9SPaul Traina default: 3014edb46e9SPaul Traina /* Bytes */ 3024edb46e9SPaul Traina while (size > 0) { 3034edb46e9SPaul Traina if (!first) 3044edb46e9SPaul Traina putchar('.'); 3054edb46e9SPaul Traina printf("%d", *bp); 3064edb46e9SPaul Traina ++bp; 3074edb46e9SPaul Traina --size; 3084edb46e9SPaul Traina first = 0; 3094edb46e9SPaul Traina } 3104edb46e9SPaul Traina break; 3114edb46e9SPaul Traina } 3124edb46e9SPaul Traina /* Data left over? */ 3134edb46e9SPaul Traina if (size) 3144edb46e9SPaul Traina printf("[len %d]", len); 3154edb46e9SPaul Traina } 3164edb46e9SPaul Traina } 3174edb46e9SPaul Traina 3184edb46e9SPaul Traina static void 3194edb46e9SPaul Traina cmu_print(register const u_char *bp, register u_int length) 3204edb46e9SPaul Traina { 3214edb46e9SPaul Traina register const struct cmu_vend *cmu; 3224edb46e9SPaul Traina char *fmt = " %s:%s"; 3234edb46e9SPaul Traina 3244edb46e9SPaul Traina #define PRINTCMUADDR(m, s) { TCHECK(cmu->m); \ 3254edb46e9SPaul Traina if (cmu->m.s_addr != 0) \ 3264edb46e9SPaul Traina printf(fmt, s, ipaddr_string(&cmu->m.s_addr)); } 3274edb46e9SPaul Traina 3284edb46e9SPaul Traina printf(" vend-cmu"); 3294edb46e9SPaul Traina cmu = (struct cmu_vend *)bp; 3304edb46e9SPaul Traina 3314edb46e9SPaul Traina /* Only print if there are unknown bits */ 3324edb46e9SPaul Traina TCHECK(cmu->v_flags); 3334edb46e9SPaul Traina if ((cmu->v_flags & ~(VF_SMASK)) != 0) 3344edb46e9SPaul Traina printf(" F:0x%x", cmu->v_flags); 3354edb46e9SPaul Traina PRINTCMUADDR(v_dgate, "DG"); 3364edb46e9SPaul Traina PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*"); 3374edb46e9SPaul Traina PRINTCMUADDR(v_dns1, "NS1"); 3384edb46e9SPaul Traina PRINTCMUADDR(v_dns2, "NS2"); 3394edb46e9SPaul Traina PRINTCMUADDR(v_ins1, "IEN1"); 3404edb46e9SPaul Traina PRINTCMUADDR(v_ins2, "IEN2"); 3414edb46e9SPaul Traina PRINTCMUADDR(v_ts1, "TS1"); 3424edb46e9SPaul Traina PRINTCMUADDR(v_ts2, "TS2"); 3434edb46e9SPaul Traina return; 3444edb46e9SPaul Traina 3454edb46e9SPaul Traina trunc: 3464edb46e9SPaul Traina fputs(tstr, stdout); 3474edb46e9SPaul Traina #undef PRINTCMUADDR 3484edb46e9SPaul Traina } 349