Path: blob/main/libexec/bootpd/tools/bootptest/print-bootp.c
34874 views
/*-1* SPDX-License-Identifier: BSD-3-Clause2*3* Copyright (c) 1988-19904* The Regents of the University of California. All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that:8* 1. Source code distributions retain the above copyright9* notice and this paragraph in its entirety10* 2. Distributions including binary code include the above copyright11* notice and this paragraph in its entirety in the documentation12* or other materials provided with the distribution, and13* 3. Neither the name of the University nor the names of its contributors14* may be used to endorse or promote products derived from this software15* without specific prior written permission.16*17* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED18* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF19* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.20*21* Format and print bootp packets.22*23* This file was copied from tcpdump-2.1.1 and modified.24* There is an e-mail list for tcpdump: <[email protected]>25*/2627#include <stdio.h>2829#include <sys/param.h>30#include <sys/types.h>31#include <sys/socket.h>3233#include <sys/time.h> /* for struct timeval in net/if.h */34#include <net/if.h>35#include <netinet/in.h>3637#include <string.h>38#include <ctype.h>3940#include "bootp.h"41#include "bootptest.h"4243/* These decode the vendor data. */44static void rfc1048_print(u_char *bp, int length);45static void cmu_print(u_char *bp, int length);46static void other_print(u_char *bp, int length);47static void dump_hex(u_char *bp, int len);4849/*50* Print bootp requests51*/52void53bootp_print(struct bootp *bp, int length, u_short sport, u_short dport)54{55static char tstr[] = " [|bootp]";56static unsigned char vm_cmu[4] = VM_CMU;57static unsigned char vm_rfc1048[4] = VM_RFC1048;58u_char *ep;59int vdlen;6061#define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc6263/* Note funny sized packets */64if (length != sizeof(struct bootp))65(void) printf(" [len=%d]", length);6667/* 'ep' points to the end of available data. */68ep = (u_char *) snapend;6970switch (bp->bp_op) {7172case BOOTREQUEST:73/* Usually, a request goes from a client to a server */74if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS)75printf(" (request)");76break;7778case BOOTREPLY:79/* Usually, a reply goes from a server to a client */80if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC)81printf(" (reply)");82break;8384default:85printf(" bootp-#%d", bp->bp_op);86}8788/* The usual hardware address type is 1 (10Mb Ethernet) */89if (bp->bp_htype != 1)90printf(" htype:%d", bp->bp_htype);9192/* The usual length for 10Mb Ethernet address is 6 bytes */93if (bp->bp_hlen != 6)94printf(" hlen:%d", bp->bp_hlen);9596/* Client's Hardware address */97if (bp->bp_hlen) {98struct ether_header *eh;99char *e;100101TCHECK(bp->bp_chaddr[0], 6);102eh = (struct ether_header *) packetp;103if (bp->bp_op == BOOTREQUEST)104e = (char *) ESRC(eh);105else if (bp->bp_op == BOOTREPLY)106e = (char *) EDST(eh);107else108e = NULL;109if (e == NULL || bcmp((char *) bp->bp_chaddr, e, 6))110dump_hex(bp->bp_chaddr, bp->bp_hlen);111}112/* Only print interesting fields */113if (bp->bp_hops)114printf(" hops:%d", bp->bp_hops);115116if (bp->bp_xid)117printf(" xid:%ld", (long)ntohl(bp->bp_xid));118119if (bp->bp_secs)120printf(" secs:%d", ntohs(bp->bp_secs));121122/* Client's ip address */123TCHECK(bp->bp_ciaddr, sizeof(bp->bp_ciaddr));124if (bp->bp_ciaddr.s_addr)125printf(" C:%s", ipaddr_string(&bp->bp_ciaddr));126127/* 'your' ip address (bootp client) */128TCHECK(bp->bp_yiaddr, sizeof(bp->bp_yiaddr));129if (bp->bp_yiaddr.s_addr)130printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr));131132/* Server's ip address */133TCHECK(bp->bp_siaddr, sizeof(bp->bp_siaddr));134if (bp->bp_siaddr.s_addr)135printf(" S:%s", ipaddr_string(&bp->bp_siaddr));136137/* Gateway's ip address */138TCHECK(bp->bp_giaddr, sizeof(bp->bp_giaddr));139if (bp->bp_giaddr.s_addr)140printf(" G:%s", ipaddr_string(&bp->bp_giaddr));141142TCHECK(bp->bp_sname[0], sizeof(bp->bp_sname));143if (*bp->bp_sname) {144printf(" sname:");145if (printfn(bp->bp_sname, ep)) {146fputs(tstr + 1, stdout);147return;148}149}150TCHECK(bp->bp_file[0], sizeof(bp->bp_file));151if (*bp->bp_file) {152printf(" file:");153if (printfn(bp->bp_file, ep)) {154fputs(tstr + 1, stdout);155return;156}157}158/* Don't try to decode the vendor buffer unless we're verbose */159if (vflag <= 0)160return;161162vdlen = sizeof(bp->bp_vend);163/* Vendor data can extend to the end of the packet. */164if (vdlen < (ep - bp->bp_vend))165vdlen = (ep - bp->bp_vend);166167TCHECK(bp->bp_vend[0], vdlen);168printf(" vend");169if (!bcmp(bp->bp_vend, vm_rfc1048, sizeof(u_int32)))170rfc1048_print(bp->bp_vend, vdlen);171else if (!bcmp(bp->bp_vend, vm_cmu, sizeof(u_int32)))172cmu_print(bp->bp_vend, vdlen);173else174other_print(bp->bp_vend, vdlen);175176return;177trunc:178fputs(tstr, stdout);179#undef TCHECK180}181182/*183* Option description data follows.184* These are described in: RFC-1048, RFC-1395, RFC-1497, RFC-1533185*186* The first char of each option string encodes the data format:187* ?: unknown188* a: ASCII189* b: byte (8-bit)190* i: inet address191* l: int32192* s: short (16-bit)193*/194char *195rfc1048_opts[] = {196/* Originally from RFC-1048: */197"?PAD", /* 0: Padding - special, no data. */198"iSM", /* 1: subnet mask (RFC950)*/199"lTZ", /* 2: time offset, seconds from UTC */200"iGW", /* 3: gateways (or routers) */201"iTS", /* 4: time servers (RFC868) */202"iINS", /* 5: IEN name servers (IEN116) */203"iDNS", /* 6: domain name servers (RFC1035)(1034?) */204"iLOG", /* 7: MIT log servers */205"iCS", /* 8: cookie servers (RFC865) */206"iLPR", /* 9: lpr server (RFC1179) */207"iIPS", /* 10: impress servers (Imagen) */208"iRLP", /* 11: resource location servers (RFC887) */209"aHN", /* 12: host name (ASCII) */210"sBFS", /* 13: boot file size (in 512 byte blocks) */211212/* Added by RFC-1395: */213"aDUMP", /* 14: Merit Dump File */214"aDNAM", /* 15: Domain Name (for DNS) */215"iSWAP", /* 16: Swap Server */216"aROOT", /* 17: Root Path */217218/* Added by RFC-1497: */219"aEXTF", /* 18: Extensions Path (more options) */220221/* Added by RFC-1533: (many, many options...) */222#if 1 /* These might not be worth recognizing by name. */223224/* IP Layer Parameters, per-host (RFC-1533, sect. 4) */225"bIP-forward", /* 19: IP Forwarding flag */226"bIP-srcroute", /* 20: IP Source Routing Enable flag */227"iIP-filters", /* 21: IP Policy Filter (addr pairs) */228"sIP-maxudp", /* 22: IP Max-UDP reassembly size */229"bIP-ttlive", /* 23: IP Time to Live */230"lIP-pmtuage", /* 24: IP Path MTU aging timeout */231"sIP-pmtutab", /* 25: IP Path MTU plateau table */232233/* IP parameters, per-interface (RFC-1533, sect. 5) */234"sIP-mtu-sz", /* 26: IP MTU size */235"bIP-mtu-sl", /* 27: IP MTU all subnets local */236"bIP-bcast1", /* 28: IP Broadcast Addr ones flag */237"bIP-mask-d", /* 29: IP do mask discovery */238"bIP-mask-s", /* 30: IP do mask supplier */239"bIP-rt-dsc", /* 31: IP do router discovery */240"iIP-rt-sa", /* 32: IP router solicitation addr */241"iIP-routes", /* 33: IP static routes (dst,router) */242243/* Link Layer parameters, per-interface (RFC-1533, sect. 6) */244"bLL-trailer", /* 34: do trailer encapsulation */245"lLL-arp-tmo", /* 35: ARP cache timeout */246"bLL-ether2", /* 36: Ethernet version 2 (IEEE 802.3) */247248/* TCP parameters (RFC-1533, sect. 7) */249"bTCP-def-ttl", /* 37: default time to live */250"lTCP-KA-tmo", /* 38: keepalive time interval */251"bTCP-KA-junk", /* 39: keepalive sends extra junk */252253/* Application and Service Parameters (RFC-1533, sect. 8) */254"aNISDOM", /* 40: NIS Domain (Sun YP) */255"iNISSRV", /* 41: NIS Servers */256"iNTPSRV", /* 42: NTP (time) Servers (RFC 1129) */257"?VSINFO", /* 43: Vendor Specific Info (encapsulated) */258"iNBiosNS", /* 44: NetBIOS Name Server (RFC-1001,1..2) */259"iNBiosDD", /* 45: NetBIOS Datagram Dist. Server. */260"bNBiosNT", /* 46: NetBIOS Note Type */261"?NBiosS", /* 47: NetBIOS Scope */262"iXW-FS", /* 48: X Window System Font Servers */263"iXW-DM", /* 49: X Window System Display Managers */264265/* DHCP extensions (RFC-1533, sect. 9) */266#endif267};268#define KNOWN_OPTIONS (sizeof(rfc1048_opts) / sizeof(rfc1048_opts[0]))269270static void271rfc1048_print(u_char *bp, int length)272{273u_char tag;274u_char *ep;275int len;276u_int32 ul;277u_short us;278struct in_addr ia;279char *optstr;280281printf("-rfc1395");282283/* Step over magic cookie */284bp += sizeof(int32);285/* Setup end pointer */286ep = bp + length;287while (bp < ep) {288tag = *bp++;289/* Check for tags with no data first. */290if (tag == TAG_PAD)291continue;292if (tag == TAG_END)293return;294if (tag < KNOWN_OPTIONS) {295optstr = rfc1048_opts[tag];296printf(" %s:", optstr + 1);297} else {298printf(" T%d:", tag);299optstr = "?";300}301/* Now scan the length byte. */302len = *bp++;303if (bp + len > ep) {304/* truncated option */305printf(" |(%d>%td)", len, ep - bp);306return;307}308/* Print the option value(s). */309switch (optstr[0]) {310311case 'a': /* ASCII string */312printfn(bp, bp + len);313bp += len;314len = 0;315break;316317case 's': /* Word formats */318while (len >= 2) {319bcopy((char *) bp, (char *) &us, 2);320printf("%d", ntohs(us));321bp += 2;322len -= 2;323if (len) printf(",");324}325if (len) printf("(junk=%d)", len);326break;327328case 'l': /* Long words */329while (len >= 4) {330bcopy((char *) bp, (char *) &ul, 4);331printf("%ld", (long)ntohl(ul));332bp += 4;333len -= 4;334if (len) printf(",");335}336if (len) printf("(junk=%d)", len);337break;338339case 'i': /* INET addresses */340while (len >= 4) {341bcopy((char *) bp, (char *) &ia, 4);342printf("%s", ipaddr_string(&ia));343bp += 4;344len -= 4;345if (len) printf(",");346}347if (len) printf("(junk=%d)", len);348break;349350case 'b':351default:352break;353354} /* switch */355356/* Print as characters, if appropriate. */357if (len) {358dump_hex(bp, len);359if (isascii(*bp) && isprint(*bp)) {360printf("(");361printfn(bp, bp + len);362printf(")");363}364bp += len;365len = 0;366}367} /* while bp < ep */368}369370static void371cmu_print(u_char *bp, int length)372{373struct cmu_vend *v;374375printf("-cmu");376377v = (struct cmu_vend *) bp;378if (length < sizeof(*v)) {379printf(" |L=%d", length);380return;381}382383/* Subnet mask */384if (v->v_flags & VF_SMASK) {385printf(" SM:%s", ipaddr_string(&v->v_smask));386}387/* Default gateway */388if (v->v_dgate.s_addr)389printf(" GW:%s", ipaddr_string(&v->v_dgate));390391/* Domain name servers */392if (v->v_dns1.s_addr)393printf(" DNS1:%s", ipaddr_string(&v->v_dns1));394if (v->v_dns2.s_addr)395printf(" DNS2:%s", ipaddr_string(&v->v_dns2));396397/* IEN-116 name servers */398if (v->v_ins1.s_addr)399printf(" INS1:%s", ipaddr_string(&v->v_ins1));400if (v->v_ins2.s_addr)401printf(" INS2:%s", ipaddr_string(&v->v_ins2));402403/* Time servers */404if (v->v_ts1.s_addr)405printf(" TS1:%s", ipaddr_string(&v->v_ts1));406if (v->v_ts2.s_addr)407printf(" TS2:%s", ipaddr_string(&v->v_ts2));408409}410411412/*413* Print out arbitrary, unknown vendor data.414*/415416static void417other_print(u_char *bp, int length)418{419u_char *ep; /* end pointer */420u_char *zp; /* points one past last non-zero byte */421422/* Setup end pointer */423ep = bp + length;424425/* Find the last non-zero byte. */426for (zp = ep; zp > bp; zp--) {427if (zp[-1] != 0)428break;429}430431/* Print the all-zero case in a compact representation. */432if (zp == bp) {433printf("-all-zero");434return;435}436printf("-unknown");437438/* Are there enough trailing zeros to make "00..." worthwhile? */439if (zp + 2 > ep)440zp = ep; /* print them all normally */441442/* Now just print all the non-zero data. */443while (bp < zp) {444printf(".%02X", *bp);445bp++;446}447448if (zp < ep)449printf(".00...");450451return;452}453454static void455dump_hex(u_char *bp, int len)456{457while (len > 0) {458printf("%02X", *bp);459bp++;460len--;461if (len) printf(".");462}463}464465/*466* Local Variables:467* tab-width: 4468* c-indent-level: 4469* c-argdecl-indent: 4470* c-continued-statement-offset: 4471* c-continued-brace-offset: -4472* c-label-offset: -4473* c-brace-offset: 0474* End:475*/476477478