home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume27 / bootptest-1.1 / part01 / print-bootp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-11  |  12.1 KB  |  459 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. #ifndef lint
  24. static char rcsid[] =
  25.     "@(#) $Header: print-bootp.c,v 1.17 91/11/14 22:21:34 leres Exp $ (LBL)";
  26. #endif
  27.  
  28. #include <stdio.h>
  29.  
  30. #include <sys/param.h>
  31. #include <sys/types.h>
  32. #include <sys/socket.h>
  33. #include <net/if.h>
  34. #include <netinet/in.h>
  35. #include <netinet/if_ether.h>
  36. #include <strings.h>
  37. #include <ctype.h>
  38.  
  39. #include "interface.h"
  40. #include "addrtoname.h"
  41. #include "bootp.h"
  42.  
  43. /* These decode the vendor data. */
  44. static void rfc1048_print();
  45. static void cmu_print();
  46. static void other_print();
  47.  
  48. /*
  49.  * Print bootp requests
  50.  */
  51. void
  52. bootp_print(bp, length, sport, dport)
  53.     register struct bootp *bp;
  54.     int length;
  55.     u_short sport, dport;
  56. {
  57.     static char tstr[] = " [|bootp]";
  58.     static unsigned char vm_cmu[4] = VM_CMU;
  59.     static unsigned char vm_rfc1048[4] = VM_RFC1048;
  60.     u_char *ep;
  61.     int vdlen;
  62.  
  63. #define TCHECK(var, l) if ((u_char *)&(var) > ep - l) goto trunc
  64.  
  65.     /* Note funny sized packets */
  66.     if (length != sizeof(struct bootp))
  67.         (void)printf(" [len=%d]", length);
  68.  
  69.     /* 'ep' points to the end of avaible data. */
  70.     ep = (u_char *)snapend;
  71.  
  72.     switch (bp->bp_op) {
  73.  
  74.     case BOOTREQUEST:
  75.         /* Usually, a request goes from a client to a server */
  76.         if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS)
  77.             printf(" (request)");
  78.         break;
  79.  
  80.     case BOOTREPLY:
  81.         /* Usually, a reply goes from a server to a client */
  82.         if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC)
  83.             printf(" (reply)");
  84.         break;
  85.  
  86.     default:
  87.         printf(" bootp-#%d", bp->bp_op);
  88.     }
  89.  
  90.     NTOHL(bp->bp_xid);
  91.     NTOHS(bp->bp_secs);
  92.  
  93.     /* The usual hardware address type is 1 (10Mb Ethernet) */
  94.     if (bp->bp_htype != 1)
  95.         printf(" htype-#%d", bp->bp_htype);
  96.  
  97.     /* The usual length for 10Mb Ethernet address is 6 bytes */
  98.     if (bp->bp_htype != 1 || bp->bp_hlen != 6)
  99.         printf(" hlen:%d", bp->bp_hlen);
  100.  
  101.     /* Only print interesting fields */
  102.     if (bp->bp_hops)
  103.         printf(" hops:%d", bp->bp_hops);
  104.     if (bp->bp_xid)
  105.         printf(" xid:0x%x", bp->bp_xid);
  106.     if (bp->bp_secs)
  107.         printf(" secs:%d", bp->bp_secs);
  108.  
  109.     /* Client's ip address */
  110.     TCHECK(bp->bp_ciaddr, sizeof(bp->bp_ciaddr));
  111.     if (bp->bp_ciaddr.s_addr)
  112.         printf(" C:%s", ipaddr_string(&bp->bp_ciaddr));
  113.  
  114.     /* 'your' ip address (bootp client) */
  115.     TCHECK(bp->bp_yiaddr, sizeof(bp->bp_yiaddr));
  116.     if (bp->bp_yiaddr.s_addr)
  117.         printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr));
  118.  
  119.     /* Server's ip address */
  120.     TCHECK(bp->bp_siaddr, sizeof(bp->bp_siaddr));
  121.     if (bp->bp_siaddr.s_addr)
  122.         printf(" S:%s", ipaddr_string(&bp->bp_siaddr));
  123.  
  124.     /* Gateway's ip address */
  125.     TCHECK(bp->bp_giaddr, sizeof(bp->bp_giaddr));
  126.     if (bp->bp_giaddr.s_addr)
  127.         printf(" G:%s", ipaddr_string(&bp->bp_giaddr));
  128.  
  129.     /* Client's Ethernet address */
  130.     if (bp->bp_htype == 1 && bp->bp_hlen == 6) {
  131.         register struct ether_header *eh;
  132.         register char *e;
  133.  
  134.         TCHECK(bp->bp_chaddr[0], 6);
  135.         eh = (struct ether_header *)packetp;
  136.         if (bp->bp_op == BOOTREQUEST)
  137.             e = (char *)ESRC(eh);
  138.         else if (bp->bp_op == BOOTREPLY)
  139.             e = (char *)EDST(eh);
  140.         else
  141.             e = 0;
  142.         if (e == 0 || bcmp((char *)bp->bp_chaddr, e, 6) != 0)
  143.             printf(" ether %s", etheraddr_string(bp->bp_chaddr));
  144.     }
  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.  
  163.     /* Don't try to decode the vendor buffer unless we're verbose */
  164.     if (vflag <= 0)
  165.         return;
  166.  
  167.     vdlen = sizeof(bp->bp_vend);
  168.     /* Vendor data can extend to the end of the packet. */
  169.     if (vdlen < (ep - bp->bp_vend))
  170.         vdlen = (ep - bp->bp_vend);
  171.  
  172.     TCHECK(bp->bp_vend[0], vdlen);
  173.     printf(" vend");
  174.     if (!bcmp(bp->bp_vend, vm_rfc1048, sizeof(u_long)))
  175.         rfc1048_print(bp->bp_vend, vdlen);
  176.     else if (!bcmp(bp->bp_vend, vm_cmu, sizeof(u_long)))
  177.         cmu_print(bp->bp_vend, vdlen);
  178.     else
  179.         other_print(bp->bp_vend, vdlen);
  180.  
  181.     return;
  182. trunc:
  183.     fputs(tstr, stdout);
  184. #undef TCHECK
  185. }
  186.  
  187. struct rfc1048dscr {
  188.     int fmt;    /* option data format (see below). */
  189.     char *name;
  190. };
  191. /* Flags used in the format descriptor field: */
  192. #define ODF_LIST    0x100    /* multiples of size allowed */
  193. #define ODF_CHAR    0x200    /* interpret as ASCII */
  194. #define ODF_INET    0x400    /* interpret as INET address */
  195. /* Values for the option data format:  */
  196. #define ODF_OTHER    1|ODF_LIST    /* unknown data format */
  197. #define ODF_BYTE    1            /* exactly 1 byte */
  198. #define ODF_STRING    1|ODF_CHAR|ODF_LIST
  199. #define ODF_SHORT    2            /* short (2 bytes) */
  200. #define ODF_SLIST    2|ODF_LIST    /* list of shorts */
  201. #define ODF_LONG    4            /* long (4 bytes) */
  202. #define ODF_INADDR    4|ODF_INET    /* inet address (just one) */
  203. #define ODF_INALST    4|ODF_INET|ODF_LIST /* list of addresses */
  204.  
  205. /*
  206.  * These come from RFC-1048 and the IETF draft:
  207.  *    DHCP Options and BOOTP Vendor Extensions
  208.  */
  209. struct rfc1048dscr
  210. rfc1048_opts[] = {
  211.     /* These come from RFC-1048: */
  212.     ODF_OTHER,    "PAD",    /*  0: Padding - special, no data. */
  213.     ODF_INADDR,    "SM",    /*  1: subnet mask (RFC950)*/
  214.     ODF_LONG,    "TZ",    /*  2: time offset, seconds from UTC */
  215.     ODF_INALST,    "GW",    /*  3: gateways (or routers) */
  216.     ODF_INALST,    "TS",    /*  4: time servers (RFC868) */
  217.     ODF_INALST,    "INS",    /*  5: IEN name servers (IEN116) */
  218.     ODF_INALST,    "DNS",    /*  6: domain name servers (RFC1035) */
  219.     ODF_INALST,    "LOG",    /*  7: MIT log servers */
  220.     ODF_INALST,    "CS",    /*  8: cookie servers (RFC865) */
  221.     ODF_INALST,    "LPR",    /*  9: lpr server (RFC1179) */
  222.     ODF_INALST,    "IPS",    /* 10: impress servers (Imagen) */
  223.     ODF_INALST,    "RLP",    /* 11: resource location servers (RFC887) */
  224.     ODF_STRING,    "HN",    /* 12: host name (ASCII) */
  225.     ODF_SHORT,    "BFS",    /* 13: boot file size (in 512 byte blocks) */
  226.     /*
  227.      * These come from the IETF draft:
  228.      * DHCP Options and BOOTP Vendor Extensions
  229.      */
  230.     ODF_STRING,    "YPD",  /* 14: NIS domain name (Sun YP) */
  231.     ODF_INALST,    "YPS",  /* 15: NIS servers (Sun YP) */
  232.     ODF_INALST,    "NTP",    /* 16: Network Time Protocol servers */
  233.  
  234. #if 0    /* The rest are not worth recognizing by name. */
  235.  
  236.     /* IP parameters, per-host */
  237.     ODF_BYTE,    "IP-forward",    /* 17: IP Forwarding flag */
  238.     ODF_BYTE,    "IP-srcroute",    /* 18: IP Source Routing Enable flag */
  239.     ODF_INALST,    "IP-filters",    /* 19: IP Policy Filter (addr pairs) */
  240.     ODF_SHORT,    "IP-maxudp",    /* 20: IP Max-UDP reassembly size */
  241.     ODF_BYTE,    "IP-ttlive",    /* 21: IP Time to Live */
  242.     ODF_LONG,    "IP-pmtuage",    /* 22: IP Path MTU aging timeout */
  243.     ODF_SLIST,    "IP-pmtutab",    /* 23: IP Path MTU size table */
  244.  
  245.     /* IP parameters, per-interface */
  246.     ODF_SHORT,    "IP-mtu-sz",    /* 24: IP MTU size */
  247.     ODF_BYTE,    "IP-mtu-sl",    /* 25: IP MTU all subnets local */
  248.     ODF_BYTE,    "IP-brc1",    /* 26: IP Broadcast Addr ones flag */
  249.     ODF_BYTE,    "IP-mask-d",    /* 27: IP do mask discovery */
  250.     ODF_BYTE,    "IP-mask-s",    /* 28: IP do mask supplier */
  251.     ODF_BYTE,    "IP-rt-disc",    /* 29: IP do router discovery */
  252.     ODF_INADDR,    "IP-rt-sa",    /* 30: IP router solicitation addr */
  253.     ODF_INALST,    "IP-routes",    /* 31: IP static routes (dst,router) */
  254.  
  255.     /* Link Layer parameters, per-interface */
  256.     ODF_BYTE,    "LL-trailer",    /* 32: do tralier encapsulation */
  257.     ODF_LONG,    "LL-arp-tmo",    /* 33: ARP cache timeout */
  258.     ODF_BYTE,    "LL-ether2",    /* 34: Ethernet version 2 (IEEE 802.3) */
  259.  
  260.     /* TCP parameters */
  261.     ODF_BYTE,    "TCP-def-ttl",    /* 35: default time to live */
  262.     ODF_LONG,    "TCP-KA-tmo",    /* 36: keepalive time interval */
  263.     ODF_BYTE,    "TCP-KA-junk",    /* 37: keepalive sends extra junk */
  264.  
  265.     /* Dynamic Host Configuration Protocol (DHCP) extensions */
  266.     /* todo... */
  267. #endif
  268. };
  269. #define    KNOWN_OPTIONS (sizeof(rfc1048_opts) / sizeof(rfc1048_opts[0]))
  270.  
  271. static void
  272. rfc1048_print(bp, length)
  273.     register u_char *bp;
  274.     int length;
  275. {
  276.     u_char tag;
  277.     u_char *ep;
  278.     register int len, j;
  279.     u_long ul;
  280.     u_short us;
  281.     int fmt;
  282.  
  283.     printf("-rfc1048");
  284.  
  285.     /* Step over magic cookie */
  286.     bp += sizeof(long);
  287.     /* Setup end pointer */
  288.     ep = bp + length;
  289.     while (bp < ep) {
  290.         tag = *bp++;
  291.         /* Check for tags with no data first. */
  292.         if (tag == TAG_PAD)
  293.             continue;
  294.         if (tag == TAG_END)
  295.             return;
  296.         if (tag < KNOWN_OPTIONS) {
  297.             printf(" %s", rfc1048_opts[tag].name);
  298.             fmt = rfc1048_opts[tag].fmt;
  299.         } else {
  300.             printf(" opt%d", tag);
  301.             fmt = ODF_OTHER;
  302.         }
  303.         /* Now scan the length byte. */
  304.         len = *bp++;
  305.         if (bp + len > ep) {
  306.             /* truncated option */
  307.             printf(" |(%d>%d)", len, ep-bp);
  308.             return;
  309.         }
  310.         while (len > 0) {
  311.             switch (rfc1048_opts[tag].fmt & 3) {
  312.             case 1:
  313.             case 3:
  314.                 /* Byte formats */
  315.                 if (len > 1) printf("(L=%d)", len);
  316.                 if (fmt & ODF_CHAR) {
  317.                     printfn(bp, bp + len);
  318.                     bp += len;
  319.                     len = 0;
  320.                     break;
  321.                 }
  322.                 printf(":%d", *bp++); len--;
  323.                 if (fmt & ODF_LIST) {
  324.                     while (len--) printf(".%d", *bp++);
  325.                 }
  326.                 break;
  327.  
  328.             case 2:
  329.                 /* Word formats */
  330.                 while (len >= 2) {
  331.                     bcopy((char*)bp, (char*)&us, 2);
  332.                     printf(":%d", ntohs(us));
  333.                     bp += 2;
  334.                     len -= 2;
  335.                     /* break if not list? */
  336.                 }
  337.                 break;
  338.  
  339.             case 0:
  340.                 /* Longword formats */
  341.                 while (len >= 4) {
  342.                     bcopy((char*)bp, (char*)&ul, 4);
  343.                     if (fmt & ODF_INET)
  344.                         printf(":%s", ipaddr_string(&ul));
  345.                     else
  346.                         printf(":%d", ntohs(us));
  347.                     bp += 4;
  348.                     len -= 4;
  349.                     /* break if not list? */
  350.                 }
  351.                 break;
  352.  
  353.             } /* switch (fmt & 3) */
  354.  
  355.             if (len) {
  356.                 printf("(junk)");
  357.                 bp += len;
  358.                 len = 0;
  359.             }
  360.  
  361.         } /* while len > 0 */
  362.     } /* while bp < ep */
  363. }
  364.  
  365. static void
  366. cmu_print(bp, length)
  367.     register u_char *bp;
  368.     int length;
  369. {
  370.     struct cmu_vend *v;
  371.     u_char *ep;
  372.  
  373.     printf("-cmu");
  374.  
  375.     v = (struct cmu_vend *) bp;
  376.     if (length < sizeof(*v)) {
  377.         printf(" |L=%d", length);
  378.         return;
  379.     }
  380.  
  381.     /* Setup end pointer */
  382.     ep = bp + length;
  383.  
  384.     /* Subnet mask */
  385.     if (v->v_flags & VF_SMASK) {
  386.         printf(" SM:%s", ipaddr_string(&v->v_smask.s_addr));
  387.     }
  388.  
  389.     /* Default gateway */
  390.     if (v->v_dgate.s_addr)
  391.         printf(" GW:%s", ipaddr_string(&v->v_dgate.s_addr));
  392.  
  393.     /* Domain name servers */
  394.     if (v->v_dns1.s_addr)
  395.         printf(" DNS1:%s", ipaddr_string(&v->v_dns1.s_addr));
  396.     if (v->v_dns2.s_addr)
  397.         printf(" DNS2:%s", ipaddr_string(&v->v_dns2.s_addr));
  398.  
  399.     /* IEN-116 name servers */
  400.     if (v->v_ins1.s_addr)
  401.         printf(" INS1:%s", ipaddr_string(&v->v_ins1.s_addr));
  402.     if (v->v_ins2.s_addr)
  403.         printf(" INS2:%s", ipaddr_string(&v->v_ins2.s_addr));
  404.  
  405.     /* Time servers */
  406.     if (v->v_ts1.s_addr)
  407.         printf(" TS1:%s", ipaddr_string(&v->v_ts1.s_addr));
  408.     if (v->v_ts2.s_addr)
  409.         printf(" TS2:%s", ipaddr_string(&v->v_ts2.s_addr));
  410.  
  411. }
  412.  
  413.  
  414. /*
  415.  * Print out arbitrary, unknown vendor data.
  416.  */
  417.  
  418. static void
  419. other_print(bp, length)
  420.     register u_char *bp;
  421.     int length;
  422. {
  423.     u_char *ep;        /* end pointer */
  424.     u_char *zp;     /* points one past last non-zero byte */
  425.     register int i, j;
  426.  
  427.     /* Setup end pointer */
  428.     ep = bp + length;
  429.  
  430.     /* Find the last non-zero byte. */
  431.     for (zp = ep; zp > bp; zp--) {
  432.         if (zp[-1] != 0) break;
  433.     }
  434.  
  435.     /* Print the all-zero case in a compact representation. */
  436.     if (zp == bp) {
  437.         printf("-all-zero");
  438.         return;
  439.     }
  440.  
  441.     printf("-unknown");
  442.  
  443.     /* Are there enough trailing zeros to make "00..." worthwhile? */
  444.     if (zp + 2 > ep)
  445.         zp = ep; /* print them all normally */
  446.  
  447.     /* Now just print all the non-zero data. */
  448.     while (bp < zp) {
  449.         printf(".%02X", *bp);
  450.         bp++;
  451.     }
  452.  
  453.     if (zp < ep)
  454.         printf(".00...");
  455.  
  456.     return;
  457. }
  458.         
  459.