home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume28 / bootp-2.4.0 / part03 / print-bootp.c < prev   
Encoding:
C/C++ Source or Header  |  1994-08-22  |  12.2 KB  |  494 lines

  1. /*
  2.  * Copyright (c) 1988-1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * 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: <tcpdump@ee.lbl.gov>
  25.  */
  26. #ifndef lint
  27. static char rcsid[] = "$Id: print-bootp.c $";
  28. /* 93/10/10 <gwr@mc.com> New data-driven option print routine. */
  29. #endif
  30.  
  31. #include <stdio.h>
  32.  
  33. #include <sys/param.h>
  34. #include <sys/types.h>
  35. #include <sys/socket.h>
  36. #include <net/if.h>
  37. #include <netinet/in.h>
  38. #include <string.h>
  39. #include <ctype.h>
  40.  
  41. #include "bootp.h"
  42. #include "bootptest.h"
  43.  
  44. /* These decode the vendor data. */
  45. static void rfc1048_print();
  46. static void cmu_print();
  47. static void other_print();
  48. static void dump_hex();
  49.  
  50. /*
  51.  * Print bootp requests
  52.  */
  53. void
  54. bootp_print(bp, length, sport, dport)
  55.     struct bootp *bp;
  56.     int length;
  57.     u_short sport, dport;
  58. {
  59.     static char tstr[] = " [|bootp]";
  60.     static unsigned char vm_cmu[4] = VM_CMU;
  61.     static unsigned char vm_rfc1048[4] = VM_RFC1048;
  62.     u_char *ep;
  63.     int vdlen;
  64.  
  65. #define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc
  66.  
  67.     /* Note funny sized packets */
  68.     if (length != sizeof(struct bootp))
  69.         (void) printf(" [len=%d]", length);
  70.  
  71.     /* 'ep' points to the end of avaible data. */
  72.     ep = (u_char *) snapend;
  73.  
  74.     switch (bp->bp_op) {
  75.  
  76.     case BOOTREQUEST:
  77.         /* Usually, a request goes from a client to a server */
  78.         if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS)
  79.             printf(" (request)");
  80.         break;
  81.  
  82.     case BOOTREPLY:
  83.         /* Usually, a reply goes from a server to a client */
  84.         if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC)
  85.             printf(" (reply)");
  86.         break;
  87.  
  88.     default:
  89.         printf(" bootp-#%d", bp->bp_op);
  90.     }
  91.  
  92.     /* The usual hardware address type is 1 (10Mb Ethernet) */
  93.     if (bp->bp_htype != 1)
  94.         printf(" htype:%d", bp->bp_htype);
  95.  
  96.     /* The usual length for 10Mb Ethernet address is 6 bytes */
  97.     if (bp->bp_hlen != 6)
  98.         printf(" hlen:%d", bp->bp_hlen);
  99.  
  100.     /* Client's Hardware address */
  101.     if (bp->bp_hlen) {
  102.         register struct ether_header *eh;
  103.         register char *e;
  104.  
  105.         TCHECK(bp->bp_chaddr[0], 6);
  106.         eh = (struct ether_header *) packetp;
  107.         if (bp->bp_op == BOOTREQUEST)
  108.             e = (char *) ESRC(eh);
  109.         else if (bp->bp_op == BOOTREPLY)
  110.             e = (char *) EDST(eh);
  111.         else
  112.             e = 0;
  113.         if (e == 0 || bcmp((char *) bp->bp_chaddr, e, 6))
  114.             dump_hex(bp->bp_chaddr, bp->bp_hlen);
  115.     }
  116.     /* Only print interesting fields */
  117.     if (bp->bp_hops)
  118.         printf(" hops:%d", bp->bp_hops);
  119.  
  120.     if (bp->bp_xid)
  121.         printf(" xid:%d", ntohl(bp->bp_xid));
  122.  
  123.     if (bp->bp_secs)
  124.         printf(" secs:%d", ntohs(bp->bp_secs));
  125.  
  126.     /* Client's ip address */
  127.     TCHECK(bp->bp_ciaddr, sizeof(bp->bp_ciaddr));
  128.     if (bp->bp_ciaddr.s_addr)
  129.         printf(" C:%s", ipaddr_string(&bp->bp_ciaddr));
  130.  
  131.     /* 'your' ip address (bootp client) */
  132.     TCHECK(bp->bp_yiaddr, sizeof(bp->bp_yiaddr));
  133.     if (bp->bp_yiaddr.s_addr)
  134.         printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr));
  135.  
  136.     /* Server's ip address */
  137.     TCHECK(bp->bp_siaddr, sizeof(bp->bp_siaddr));
  138.     if (bp->bp_siaddr.s_addr)
  139.         printf(" S:%s", ipaddr_string(&bp->bp_siaddr));
  140.  
  141.     /* Gateway's ip address */
  142.     TCHECK(bp->bp_giaddr, sizeof(bp->bp_giaddr));
  143.     if (bp->bp_giaddr.s_addr)
  144.         printf(" G:%s", ipaddr_string(&bp->bp_giaddr));
  145.  
  146.     TCHECK(bp->bp_sname[0], sizeof(bp->bp_sname));
  147.     if (*bp->bp_sname) {
  148.         printf(" sname:");
  149.         if (printfn(bp->bp_sname, ep)) {
  150.             fputs(tstr + 1, stdout);
  151.             return;
  152.         }
  153.     }
  154.     TCHECK(bp->bp_file[0], sizeof(bp->bp_file));
  155.     if (*bp->bp_file) {
  156.         printf(" file:");
  157.         if (printfn(bp->bp_file, ep)) {
  158.             fputs(tstr + 1, stdout);
  159.             return;
  160.         }
  161.     }
  162.     /* Don't try to decode the vendor buffer unless we're verbose */
  163.     if (vflag <= 0)
  164.         return;
  165.  
  166.     vdlen = sizeof(bp->bp_vend);
  167.     /* Vendor data can extend to the end of the packet. */
  168.     if (vdlen < (ep - bp->bp_vend))
  169.         vdlen = (ep - bp->bp_vend);
  170.  
  171.     TCHECK(bp->bp_vend[0], vdlen);
  172.     printf(" vend");
  173.     if (!bcmp(bp->bp_vend, vm_rfc1048, sizeof(u_int32)))
  174.         rfc1048_print(bp->bp_vend, vdlen);
  175.     else if (!bcmp(bp->bp_vend, vm_cmu, sizeof(u_int32)))
  176.         cmu_print(bp->bp_vend, vdlen);
  177.     else
  178.         other_print(bp->bp_vend, vdlen);
  179.  
  180.     return;
  181.  trunc:
  182.     fputs(tstr, stdout);
  183. #undef TCHECK
  184. }
  185.  
  186. /*
  187.  * Option description data follows.
  188.  * These are decribed in: RFC-1048, RFC-1395, RFC-1497, RFC-1533
  189.  *
  190.  * The first char of each option string encodes the data format:
  191.  * ?: unknown
  192.  * a: ASCII
  193.  * b: byte (8-bit)
  194.  * i: inet address
  195.  * l: int32
  196.  * s: short (16-bit)
  197.  */
  198. char *
  199. rfc1048_opts[] = {
  200.     /* Originally from RFC-1048: */
  201.     "?PAD",                /*  0: Padding - special, no data. */
  202.     "iSM",                /*  1: subnet mask (RFC950)*/
  203.     "lTZ",                /*  2: time offset, seconds from UTC */
  204.     "iGW",                /*  3: gateways (or routers) */
  205.     "iTS",                /*  4: time servers (RFC868) */
  206.     "iINS",                /*  5: IEN name servers (IEN116) */
  207.     "iDNS",                /*  6: domain name servers (RFC1035)(1034?) */
  208.     "iLOG",                /*  7: MIT log servers */
  209.     "iCS",                /*  8: cookie servers (RFC865) */
  210.     "iLPR",                /*  9: lpr server (RFC1179) */
  211.     "iIPS",                /* 10: impress servers (Imagen) */
  212.     "iRLP",                /* 11: resource location servers (RFC887) */
  213.     "aHN",                /* 12: host name (ASCII) */
  214.     "sBFS",                /* 13: boot file size (in 512 byte blocks) */
  215.  
  216.     /* Added by RFC-1395: */
  217.     "aDUMP",            /* 14: Merit Dump File */
  218.     "aDNAM",            /* 15: Domain Name (for DNS) */
  219.     "iSWAP",            /* 16: Swap Server */
  220.     "aROOT",            /* 17: Root Path */
  221.  
  222.     /* Added by RFC-1497: */
  223.     "aEXTF",            /* 18: Extensions Path (more options) */
  224.  
  225.     /* Added by RFC-1533: (many, many options...) */
  226. #if 1    /* These might not be worth recognizing by name. */
  227.  
  228.     /* IP Layer Parameters, per-host (RFC-1533, sect. 4) */
  229.     "bIP-forward",        /* 19: IP Forwarding flag */
  230.     "bIP-srcroute",        /* 20: IP Source Routing Enable flag */
  231.     "iIP-filters",        /* 21: IP Policy Filter (addr pairs) */
  232.     "sIP-maxudp",        /* 22: IP Max-UDP reassembly size */
  233.     "bIP-ttlive",        /* 23: IP Time to Live */
  234.     "lIP-pmtuage",        /* 24: IP Path MTU aging timeout */
  235.     "sIP-pmtutab",        /* 25: IP Path MTU plateau table */
  236.  
  237.     /* IP parameters, per-interface (RFC-1533, sect. 5) */
  238.     "sIP-mtu-sz",        /* 26: IP MTU size */
  239.     "bIP-mtu-sl",        /* 27: IP MTU all subnets local */
  240.     "bIP-bcast1",        /* 28: IP Broadcast Addr ones flag */
  241.     "bIP-mask-d",        /* 29: IP do mask discovery */
  242.     "bIP-mask-s",        /* 30: IP do mask supplier */
  243.     "bIP-rt-dsc",        /* 31: IP do router discovery */
  244.     "iIP-rt-sa",        /* 32: IP router solicitation addr */
  245.     "iIP-routes",        /* 33: IP static routes (dst,router) */
  246.  
  247.     /* Link Layer parameters, per-interface (RFC-1533, sect. 6) */
  248.     "bLL-trailer",        /* 34: do tralier encapsulation */
  249.     "lLL-arp-tmo",        /* 35: ARP cache timeout */
  250.     "bLL-ether2",        /* 36: Ethernet version 2 (IEEE 802.3) */
  251.  
  252.     /* TCP parameters (RFC-1533, sect. 7) */
  253.     "bTCP-def-ttl",        /* 37: default time to live */
  254.     "lTCP-KA-tmo",        /* 38: keepalive time interval */
  255.     "bTCP-KA-junk",        /* 39: keepalive sends extra junk */
  256.  
  257.     /* Application and Service Parameters (RFC-1533, sect. 8) */
  258.     "aNISDOM",            /* 40: NIS Domain (Sun YP) */
  259.     "iNISSRV",            /* 41: NIS Servers */
  260.     "iNTPSRV",            /* 42: NTP (time) Servers (RFC 1129) */
  261.     "?VSINFO",            /* 43: Vendor Specific Info (encapsulated) */
  262.     "iNBiosNS",            /* 44: NetBIOS Name Server (RFC-1001,1..2) */
  263.     "iNBiosDD",            /* 45: NetBIOS Datagram Dist. Server. */
  264.     "bNBiosNT",            /* 46: NetBIOS Note Type */
  265.     "?NBiosS",            /* 47: NetBIOS Scope */
  266.     "iXW-FS",            /* 48: X Window System Font Servers */
  267.     "iXW-DM",            /* 49: X Window System Display Managers */
  268.  
  269.     /* DHCP extensions (RFC-1533, sect. 9) */
  270. #endif
  271. };
  272. #define    KNOWN_OPTIONS (sizeof(rfc1048_opts) / sizeof(rfc1048_opts[0]))
  273.  
  274. static void print_string();
  275.  
  276. static void
  277. rfc1048_print(bp, length)
  278.     register u_char *bp;
  279.     int length;
  280. {
  281.     u_char tag;
  282.     u_char *ep;
  283.     register int len, j;
  284.     u_int32 ul;
  285.     u_short us;
  286.     struct in_addr ia;
  287.     char *optstr;
  288.  
  289.     printf("-rfc1395");
  290.  
  291.     /* Step over magic cookie */
  292.     bp += sizeof(int32);
  293.     /* Setup end pointer */
  294.     ep = bp + length;
  295.     while (bp < ep) {
  296.         tag = *bp++;
  297.         /* Check for tags with no data first. */
  298.         if (tag == TAG_PAD)
  299.             continue;
  300.         if (tag == TAG_END)
  301.             return;
  302.         if (tag < KNOWN_OPTIONS) {
  303.             optstr = rfc1048_opts[tag];
  304.             printf(" %s:", optstr + 1);
  305.         } else {
  306.             printf(" T%d:", tag);
  307.             optstr = "?";
  308.         }
  309.         /* Now scan the length byte. */
  310.         len = *bp++;
  311.         if (bp + len > ep) {
  312.             /* truncated option */
  313.             printf(" |(%d>%d)", len, ep - bp);
  314.             return;
  315.         }
  316.         /* Print the option value(s). */
  317.         switch (optstr[0]) {
  318.  
  319.         case 'a':                /* ASCII string */
  320.             printfn(bp, bp + len);
  321.             bp += len;
  322.             len = 0;
  323.             break;
  324.  
  325.         case 's':                /* Word formats */
  326.             while (len >= 2) {
  327.                 bcopy((char *) bp, (char *) &us, 2);
  328.                 printf("%d", ntohs(us));
  329.                 bp += 2;
  330.                 len -= 2;
  331.                 if (len) printf(",");
  332.             }
  333.             if (len) printf("(junk=%d)", len);
  334.             break;
  335.  
  336.         case 'l':                /* Long words */
  337.             while (len >= 4) {
  338.                 bcopy((char *) bp, (char *) &ul, 4);
  339.                 printf("%d", ntohl(ul));
  340.                 bp += 4;
  341.                 len -= 4;
  342.                 if (len) printf(",");
  343.             }
  344.             if (len) printf("(junk=%d)", len);
  345.             break;
  346.  
  347.         case 'i':                /* INET addresses */
  348.             while (len >= 4) {
  349.                 bcopy((char *) bp, (char *) &ia, 4);
  350.                 printf("%s", ipaddr_string(&ia));
  351.                 bp += 4;
  352.                 len -= 4;
  353.                 if (len) printf(",");
  354.             }
  355.             if (len) printf("(junk=%d)", len);
  356.             break;
  357.  
  358.         case 'b':
  359.         default:
  360.             break;
  361.  
  362.         }                        /* switch */
  363.  
  364.         /* Print as characters, if appropriate. */
  365.         if (len) {
  366.             dump_hex(bp, len);
  367.             if (isascii(*bp) && isprint(*bp)) {
  368.                 printf("(");
  369.                 printfn(bp, bp + len);
  370.                 printf(")");
  371.             }
  372.             bp += len;
  373.             len = 0;
  374.         }
  375.     } /* while bp < ep */
  376. }
  377.  
  378. static void
  379. cmu_print(bp, length)
  380.     register u_char *bp;
  381.     int length;
  382. {
  383.     struct cmu_vend *v;
  384.     u_char *ep;
  385.  
  386.     printf("-cmu");
  387.  
  388.     v = (struct cmu_vend *) bp;
  389.     if (length < sizeof(*v)) {
  390.         printf(" |L=%d", length);
  391.         return;
  392.     }
  393.     /* Setup end pointer */
  394.     ep = bp + length;
  395.  
  396.     /* Subnet mask */
  397.     if (v->v_flags & VF_SMASK) {
  398.         printf(" SM:%s", ipaddr_string(&v->v_smask));
  399.     }
  400.     /* Default gateway */
  401.     if (v->v_dgate.s_addr)
  402.         printf(" GW:%s", ipaddr_string(&v->v_dgate));
  403.  
  404.     /* Domain name servers */
  405.     if (v->v_dns1.s_addr)
  406.         printf(" DNS1:%s", ipaddr_string(&v->v_dns1));
  407.     if (v->v_dns2.s_addr)
  408.         printf(" DNS2:%s", ipaddr_string(&v->v_dns2));
  409.  
  410.     /* IEN-116 name servers */
  411.     if (v->v_ins1.s_addr)
  412.         printf(" INS1:%s", ipaddr_string(&v->v_ins1));
  413.     if (v->v_ins2.s_addr)
  414.         printf(" INS2:%s", ipaddr_string(&v->v_ins2));
  415.  
  416.     /* Time servers */
  417.     if (v->v_ts1.s_addr)
  418.         printf(" TS1:%s", ipaddr_string(&v->v_ts1));
  419.     if (v->v_ts2.s_addr)
  420.         printf(" TS2:%s", ipaddr_string(&v->v_ts2));
  421.  
  422. }
  423.  
  424.  
  425. /*
  426.  * Print out arbitrary, unknown vendor data.
  427.  */
  428.  
  429. static void
  430. other_print(bp, length)
  431.     register u_char *bp;
  432.     int length;
  433. {
  434.     u_char *ep;                    /* end pointer */
  435.     u_char *zp;                    /* points one past last non-zero byte */
  436.     register int i, j;
  437.  
  438.     /* Setup end pointer */
  439.     ep = bp + length;
  440.  
  441.     /* Find the last non-zero byte. */
  442.     for (zp = ep; zp > bp; zp--) {
  443.         if (zp[-1] != 0)
  444.             break;
  445.     }
  446.  
  447.     /* Print the all-zero case in a compact representation. */
  448.     if (zp == bp) {
  449.         printf("-all-zero");
  450.         return;
  451.     }
  452.     printf("-unknown");
  453.  
  454.     /* Are there enough trailing zeros to make "00..." worthwhile? */
  455.     if (zp + 2 > ep)
  456.         zp = ep;                /* print them all normally */
  457.  
  458.     /* Now just print all the non-zero data. */
  459.     while (bp < zp) {
  460.         printf(".%02X", *bp);
  461.         bp++;
  462.     }
  463.  
  464.     if (zp < ep)
  465.         printf(".00...");
  466.  
  467.     return;
  468. }
  469.  
  470. static void
  471. dump_hex(bp, len)
  472.     u_char *bp;
  473.     int len;
  474. {
  475.     while (len > 0) {
  476.         printf("%02X", *bp);
  477.         bp++;
  478.         len--;
  479.         if (len) printf(".");
  480.     }
  481. }
  482.  
  483. /*
  484.  * Local Variables:
  485.  * tab-width: 4
  486.  * c-indent-level: 4
  487.  * c-argdecl-indent: 4
  488.  * c-continued-statement-offset: 4
  489.  * c-continued-brace-offset: -4
  490.  * c-label-offset: -4
  491.  * c-brace-offset: 0
  492.  * End:
  493.  */
  494.