home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1988-1990 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that: (1) source code distributions
- * retain the above copyright notice and this paragraph in its entirety, (2)
- * distributions including binary code include the above copyright notice and
- * this paragraph in its entirety in the documentation or other materials
- * provided with the distribution, and (3) all advertising materials mentioning
- * features or use of this software display the following acknowledgement:
- * ``This product includes software developed by the University of California,
- * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
- * the University nor the names of its contributors may be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Format and print bootp packets.
- */
- #ifndef lint
- static char rcsid[] =
- "@(#) $Header: print-bootp.c,v 1.17 91/11/14 22:21:34 leres Exp $ (LBL)";
- #endif
-
- #include <stdio.h>
-
- #include <sys/param.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <net/if.h>
- #include <netinet/in.h>
- #include <netinet/if_ether.h>
- #include <strings.h>
- #include <ctype.h>
-
- #include "interface.h"
- #include "addrtoname.h"
- #include "bootp.h"
-
- /* These decode the vendor data. */
- static void rfc1048_print();
- static void cmu_print();
- static void other_print();
-
- /*
- * Print bootp requests
- */
- void
- bootp_print(bp, length, sport, dport)
- register struct bootp *bp;
- int length;
- u_short sport, dport;
- {
- static char tstr[] = " [|bootp]";
- static unsigned char vm_cmu[4] = VM_CMU;
- static unsigned char vm_rfc1048[4] = VM_RFC1048;
- u_char *ep;
- int vdlen;
-
- #define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc
-
- /* Note funny sized packets */
- if (length != sizeof(struct bootp))
- (void)printf(" [len=%d]", length);
-
- /* 'ep' points to the end of avaible data. */
- ep = (u_char *)snapend;
-
- switch (bp->bp_op) {
-
- case BOOTREQUEST:
- /* Usually, a request goes from a client to a server */
- if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS)
- printf(" (request)");
- break;
-
- case BOOTREPLY:
- /* Usually, a reply goes from a server to a client */
- if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC)
- printf(" (reply)");
- break;
-
- default:
- printf(" bootp-#%d", bp->bp_op);
- }
-
- NTOHL(bp->bp_xid);
- NTOHS(bp->bp_secs);
-
- /* The usual hardware address type is 1 (10Mb Ethernet) */
- if (bp->bp_htype != 1)
- printf(" htype-#%d", bp->bp_htype);
-
- /* The usual length for 10Mb Ethernet address is 6 bytes */
- if (bp->bp_htype != 1 || bp->bp_hlen != 6)
- printf(" hlen:%d", bp->bp_hlen);
-
- /* Only print interesting fields */
- if (bp->bp_hops)
- printf(" hops:%d", bp->bp_hops);
- if (bp->bp_xid)
- printf(" xid:0x%x", bp->bp_xid);
- if (bp->bp_secs)
- printf(" secs:%d", bp->bp_secs);
-
- /* Client's ip address */
- TCHECK(bp->bp_ciaddr, sizeof(bp->bp_ciaddr));
- if (bp->bp_ciaddr.s_addr)
- printf(" C:%s", ipaddr_string(&bp->bp_ciaddr));
-
- /* 'your' ip address (bootp client) */
- TCHECK(bp->bp_yiaddr, sizeof(bp->bp_yiaddr));
- if (bp->bp_yiaddr.s_addr)
- printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr));
-
- /* Server's ip address */
- TCHECK(bp->bp_siaddr, sizeof(bp->bp_siaddr));
- if (bp->bp_siaddr.s_addr)
- printf(" S:%s", ipaddr_string(&bp->bp_siaddr));
-
- /* Gateway's ip address */
- TCHECK(bp->bp_giaddr, sizeof(bp->bp_giaddr));
- if (bp->bp_giaddr.s_addr)
- printf(" G:%s", ipaddr_string(&bp->bp_giaddr));
-
- /* Client's Ethernet address */
- if (bp->bp_htype == 1 && bp->bp_hlen == 6) {
- register struct ether_header *eh;
- register char *e;
-
- TCHECK(bp->bp_chaddr[0], 6);
- eh = (struct ether_header *)packetp;
- if (bp->bp_op == BOOTREQUEST)
- e = (char *)ESRC(eh);
- else if (bp->bp_op == BOOTREPLY)
- e = (char *)EDST(eh);
- else
- e = 0;
- if (e == 0 || bcmp((char *)bp->bp_chaddr, e, 6) != 0)
- printf(" ether %s", etheraddr_string(bp->bp_chaddr));
- }
-
- TCHECK(bp->bp_sname[0], sizeof(bp->bp_sname));
- if (*bp->bp_sname) {
- printf(" sname ");
- if (printfn(bp->bp_sname, ep)) {
- fputs(tstr + 1, stdout);
- return;
- }
- }
- TCHECK(bp->bp_file[0], sizeof(bp->bp_file));
- if (*bp->bp_file) {
- printf(" file ");
- if (printfn(bp->bp_file, ep)) {
- fputs(tstr + 1, stdout);
- return;
- }
- }
-
- /* Don't try to decode the vendor buffer unless we're verbose */
- if (vflag <= 0)
- return;
-
- vdlen = sizeof(bp->bp_vend);
- /* Vendor data can extend to the end of the packet. */
- if (vdlen < (ep - bp->bp_vend))
- vdlen = (ep - bp->bp_vend);
-
- TCHECK(bp->bp_vend[0], vdlen);
- printf(" vend");
- if (!bcmp(bp->bp_vend, vm_rfc1048, sizeof(u_long)))
- rfc1048_print(bp->bp_vend, vdlen);
- else if (!bcmp(bp->bp_vend, vm_cmu, sizeof(u_long)))
- cmu_print(bp->bp_vend, vdlen);
- else
- other_print(bp->bp_vend, vdlen);
-
- return;
- trunc:
- fputs(tstr, stdout);
- #undef TCHECK
- }
-
- struct rfc1048dscr {
- int fmt; /* option data format (see below). */
- char *name;
- };
- /* Flags used in the format descriptor field: */
- #define ODF_LIST 0x100 /* multiples of size allowed */
- #define ODF_CHAR 0x200 /* interpret as ASCII */
- #define ODF_INET 0x400 /* interpret as INET address */
- /* Values for the option data format: */
- #define ODF_OTHER 1|ODF_LIST /* unknown data format */
- #define ODF_BYTE 1 /* exactly 1 byte */
- #define ODF_STRING 1|ODF_CHAR|ODF_LIST
- #define ODF_SHORT 2 /* short (2 bytes) */
- #define ODF_SLIST 2|ODF_LIST /* list of shorts */
- #define ODF_LONG 4 /* long (4 bytes) */
- #define ODF_INADDR 4|ODF_INET /* inet address (just one) */
- #define ODF_INALST 4|ODF_INET|ODF_LIST /* list of addresses */
-
- /*
- * These come from RFC-1048 and the IETF draft:
- * DHCP Options and BOOTP Vendor Extensions
- */
- struct rfc1048dscr
- rfc1048_opts[] = {
- /* These come from RFC-1048: */
- ODF_OTHER, "PAD", /* 0: Padding - special, no data. */
- ODF_INADDR, "SM", /* 1: subnet mask (RFC950)*/
- ODF_LONG, "TZ", /* 2: time offset, seconds from UTC */
- ODF_INALST, "GW", /* 3: gateways (or routers) */
- ODF_INALST, "TS", /* 4: time servers (RFC868) */
- ODF_INALST, "INS", /* 5: IEN name servers (IEN116) */
- ODF_INALST, "DNS", /* 6: domain name servers (RFC1035) */
- ODF_INALST, "LOG", /* 7: MIT log servers */
- ODF_INALST, "CS", /* 8: cookie servers (RFC865) */
- ODF_INALST, "LPR", /* 9: lpr server (RFC1179) */
- ODF_INALST, "IPS", /* 10: impress servers (Imagen) */
- ODF_INALST, "RLP", /* 11: resource location servers (RFC887) */
- ODF_STRING, "HN", /* 12: host name (ASCII) */
- ODF_SHORT, "BFS", /* 13: boot file size (in 512 byte blocks) */
- /*
- * These come from the IETF draft:
- * DHCP Options and BOOTP Vendor Extensions
- */
- ODF_STRING, "YPD", /* 14: NIS domain name (Sun YP) */
- ODF_INALST, "YPS", /* 15: NIS servers (Sun YP) */
- ODF_INALST, "NTP", /* 16: Network Time Protocol servers */
-
- #if 0 /* The rest are not worth recognizing by name. */
-
- /* IP parameters, per-host */
- ODF_BYTE, "IP-forward", /* 17: IP Forwarding flag */
- ODF_BYTE, "IP-srcroute", /* 18: IP Source Routing Enable flag */
- ODF_INALST, "IP-filters", /* 19: IP Policy Filter (addr pairs) */
- ODF_SHORT, "IP-maxudp", /* 20: IP Max-UDP reassembly size */
- ODF_BYTE, "IP-ttlive", /* 21: IP Time to Live */
- ODF_LONG, "IP-pmtuage", /* 22: IP Path MTU aging timeout */
- ODF_SLIST, "IP-pmtutab", /* 23: IP Path MTU size table */
-
- /* IP parameters, per-interface */
- ODF_SHORT, "IP-mtu-sz", /* 24: IP MTU size */
- ODF_BYTE, "IP-mtu-sl", /* 25: IP MTU all subnets local */
- ODF_BYTE, "IP-brc1", /* 26: IP Broadcast Addr ones flag */
- ODF_BYTE, "IP-mask-d", /* 27: IP do mask discovery */
- ODF_BYTE, "IP-mask-s", /* 28: IP do mask supplier */
- ODF_BYTE, "IP-rt-disc", /* 29: IP do router discovery */
- ODF_INADDR, "IP-rt-sa", /* 30: IP router solicitation addr */
- ODF_INALST, "IP-routes", /* 31: IP static routes (dst,router) */
-
- /* Link Layer parameters, per-interface */
- ODF_BYTE, "LL-trailer", /* 32: do tralier encapsulation */
- ODF_LONG, "LL-arp-tmo", /* 33: ARP cache timeout */
- ODF_BYTE, "LL-ether2", /* 34: Ethernet version 2 (IEEE 802.3) */
-
- /* TCP parameters */
- ODF_BYTE, "TCP-def-ttl", /* 35: default time to live */
- ODF_LONG, "TCP-KA-tmo", /* 36: keepalive time interval */
- ODF_BYTE, "TCP-KA-junk", /* 37: keepalive sends extra junk */
-
- /* Dynamic Host Configuration Protocol (DHCP) extensions */
- /* todo... */
- #endif
- };
- #define KNOWN_OPTIONS (sizeof(rfc1048_opts) / sizeof(rfc1048_opts[0]))
-
- static void
- rfc1048_print(bp, length)
- register u_char *bp;
- int length;
- {
- u_char tag;
- u_char *ep;
- register int len, j;
- u_long ul;
- u_short us;
- int fmt;
-
- printf("-rfc1048");
-
- /* Step over magic cookie */
- bp += sizeof(long);
- /* Setup end pointer */
- ep = bp + length;
- while (bp < ep) {
- tag = *bp++;
- /* Check for tags with no data first. */
- if (tag == TAG_PAD)
- continue;
- if (tag == TAG_END)
- return;
- if (tag < KNOWN_OPTIONS) {
- printf(" %s", rfc1048_opts[tag].name);
- fmt = rfc1048_opts[tag].fmt;
- } else {
- printf(" opt%d", tag);
- fmt = ODF_OTHER;
- }
- /* Now scan the length byte. */
- len = *bp++;
- if (bp + len > ep) {
- /* truncated option */
- printf(" |(%d>%d)", len, ep-bp);
- return;
- }
- while (len > 0) {
- switch (rfc1048_opts[tag].fmt & 3) {
- case 1:
- case 3:
- /* Byte formats */
- if (len > 1) printf("(L=%d)", len);
- if (fmt & ODF_CHAR) {
- printfn(bp, bp + len);
- bp += len;
- len = 0;
- break;
- }
- printf(":%d", *bp++); len--;
- if (fmt & ODF_LIST) {
- while (len--) printf(".%d", *bp++);
- }
- break;
-
- case 2:
- /* Word formats */
- while (len >= 2) {
- bcopy((char*)bp, (char*)&us, 2);
- printf(":%d", ntohs(us));
- bp += 2;
- len -= 2;
- /* break if not list? */
- }
- break;
-
- case 0:
- /* Longword formats */
- while (len >= 4) {
- bcopy((char*)bp, (char*)&ul, 4);
- if (fmt & ODF_INET)
- printf(":%s", ipaddr_string(&ul));
- else
- printf(":%d", ntohs(us));
- bp += 4;
- len -= 4;
- /* break if not list? */
- }
- break;
-
- } /* switch (fmt & 3) */
-
- if (len) {
- printf("(junk)");
- bp += len;
- len = 0;
- }
-
- } /* while len > 0 */
- } /* while bp < ep */
- }
-
- static void
- cmu_print(bp, length)
- register u_char *bp;
- int length;
- {
- struct cmu_vend *v;
- u_char *ep;
-
- printf("-cmu");
-
- v = (struct cmu_vend *) bp;
- if (length < sizeof(*v)) {
- printf(" |L=%d", length);
- return;
- }
-
- /* Setup end pointer */
- ep = bp + length;
-
- /* Subnet mask */
- if (v->v_flags & VF_SMASK) {
- printf(" SM:%s", ipaddr_string(&v->v_smask.s_addr));
- }
-
- /* Default gateway */
- if (v->v_dgate.s_addr)
- printf(" GW:%s", ipaddr_string(&v->v_dgate.s_addr));
-
- /* Domain name servers */
- if (v->v_dns1.s_addr)
- printf(" DNS1:%s", ipaddr_string(&v->v_dns1.s_addr));
- if (v->v_dns2.s_addr)
- printf(" DNS2:%s", ipaddr_string(&v->v_dns2.s_addr));
-
- /* IEN-116 name servers */
- if (v->v_ins1.s_addr)
- printf(" INS1:%s", ipaddr_string(&v->v_ins1.s_addr));
- if (v->v_ins2.s_addr)
- printf(" INS2:%s", ipaddr_string(&v->v_ins2.s_addr));
-
- /* Time servers */
- if (v->v_ts1.s_addr)
- printf(" TS1:%s", ipaddr_string(&v->v_ts1.s_addr));
- if (v->v_ts2.s_addr)
- printf(" TS2:%s", ipaddr_string(&v->v_ts2.s_addr));
-
- }
-
-
- /*
- * Print out arbitrary, unknown vendor data.
- */
-
- static void
- other_print(bp, length)
- register u_char *bp;
- int length;
- {
- u_char *ep; /* end pointer */
- u_char *zp; /* points one past last non-zero byte */
- register int i, j;
-
- /* Setup end pointer */
- ep = bp + length;
-
- /* Find the last non-zero byte. */
- for (zp = ep; zp > bp; zp--) {
- if (zp[-1] != 0) break;
- }
-
- /* Print the all-zero case in a compact representation. */
- if (zp == bp) {
- printf("-all-zero");
- return;
- }
-
- printf("-unknown");
-
- /* Are there enough trailing zeros to make "00..." worthwhile? */
- if (zp + 2 > ep)
- zp = ep; /* print them all normally */
-
- /* Now just print all the non-zero data. */
- while (bp < zp) {
- printf(".%02X", *bp);
- bp++;
- }
-
- if (zp < ep)
- printf(".00...");
-
- return;
- }
-
-