home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / tcpdumpb.zip / print-bootp.c < prev    next >
C/C++ Source or Header  |  1996-07-23  |  9KB  |  349 lines

  1. /*
  2.  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
  3.  *    The Regents of the University of California.  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.42 96/07/23 14:17:22 leres Exp $ (LBL)";
  26. #endif
  27.  
  28. #include <sys/param.h>
  29. #include <sys/time.h>
  30. #include <sys/socket.h>
  31.  
  32. #if __STDC__
  33. struct mbuf;
  34. struct rtentry;
  35. #endif
  36. #include <net/if.h>
  37.  
  38. #include <netinet/in.h>
  39. #include <netinet/if_ether.h>
  40.  
  41. #include <ctype.h>
  42. #include <stdio.h>
  43. #include <string.h>
  44.  
  45. #include "interface.h"
  46. #include "addrtoname.h"
  47. #include "bootp.h"
  48.  
  49. static void rfc1048_print(const u_char *, u_int);
  50. static void cmu_print(const u_char *, u_int);
  51.  
  52. static char tstr[] = " [|bootp]";
  53.  
  54. /*
  55.  * Print bootp requests
  56.  */
  57. void
  58. bootp_print(register const u_char *cp, u_int length,
  59.         u_short sport, u_short dport)
  60. {
  61.     register const struct bootp *bp;
  62.     static u_char vm_cmu[4] = VM_CMU;
  63.     static u_char vm_rfc1048[4] = VM_RFC1048;
  64.  
  65.     bp = (struct bootp *)cp;
  66.     TCHECK(bp->bp_op);
  67.     switch (bp->bp_op) {
  68.  
  69.     case BOOTREQUEST:
  70.         /* Usually, a request goes from a client to a server */
  71.         if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS)
  72.             printf(" (request)");
  73.         break;
  74.  
  75.     case BOOTREPLY:
  76.         /* Usually, a reply goes from a server to a client */
  77.         if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC)
  78.             printf(" (reply)");
  79.         break;
  80.  
  81.     default:
  82.         printf(" bootp-#%d", bp->bp_op);
  83.     }
  84.  
  85.     TCHECK(bp->bp_secs);
  86.  
  87.     /* The usual hardware address type is 1 (10Mb Ethernet) */
  88.     if (bp->bp_htype != 1)
  89.         printf(" htype-#%d", bp->bp_htype);
  90.  
  91.     /* The usual length for 10Mb Ethernet address is 6 bytes */
  92.     if (bp->bp_htype != 1 || bp->bp_hlen != 6)
  93.         printf(" hlen:%d", bp->bp_hlen);
  94.  
  95.     /* Only print interesting fields */
  96.     if (bp->bp_hops)
  97.         printf(" hops:%d", bp->bp_hops);
  98.     if (bp->bp_xid)
  99.         printf(" xid:0x%x", (u_int32_t)ntohl(bp->bp_xid));
  100.     if (bp->bp_secs)
  101.         printf(" secs:%d", ntohs(bp->bp_secs));
  102.  
  103.     /* Client's ip address */
  104.     TCHECK(bp->bp_ciaddr);
  105.     if (bp->bp_ciaddr.s_addr)
  106.         printf(" C:%s", ipaddr_string(&bp->bp_ciaddr));
  107.  
  108.     /* 'your' ip address (bootp client) */
  109.     TCHECK(bp->bp_yiaddr);
  110.     if (bp->bp_yiaddr.s_addr)
  111.         printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr));
  112.  
  113.     /* Server's ip address */
  114.     TCHECK(bp->bp_siaddr);
  115.     if (bp->bp_siaddr.s_addr)
  116.         printf(" S:%s", ipaddr_string(&bp->bp_siaddr));
  117.  
  118.     /* Gateway's ip address */
  119.     TCHECK(bp->bp_giaddr);
  120.     if (bp->bp_giaddr.s_addr)
  121.         printf(" G:%s", ipaddr_string(&bp->bp_giaddr));
  122.  
  123.     /* Client's Ethernet address */
  124.     if (bp->bp_htype == 1 && bp->bp_hlen == 6) {
  125.         register const struct ether_header *eh;
  126.         register const char *e;
  127.  
  128.         TCHECK2(bp->bp_chaddr[0], 6);
  129.         eh = (struct ether_header *)packetp;
  130.         if (bp->bp_op == BOOTREQUEST)
  131.             e = (const char *)ESRC(eh);
  132.         else if (bp->bp_op == BOOTREPLY)
  133.             e = (const char *)EDST(eh);
  134.         else
  135.             e = 0;
  136.         if (e == 0 || memcmp((char *)bp->bp_chaddr, e, 6) != 0)
  137.             printf(" ether %s", etheraddr_string(bp->bp_chaddr));
  138.     }
  139.  
  140.     TCHECK2(bp->bp_sname[0], 1);        /* check first char only */
  141.     if (*bp->bp_sname) {
  142.         printf(" sname \"");
  143.         if (fn_print(bp->bp_sname, snapend)) {
  144.             putchar('"');
  145.             fputs(tstr + 1, stdout);
  146.             return;
  147.         }
  148.     }
  149.     TCHECK2(bp->bp_sname[0], 1);        /* check first char only */
  150.     if (*bp->bp_file) {
  151.         printf(" file \"");
  152.         if (fn_print(bp->bp_file, snapend)) {
  153.             putchar('"');
  154.             fputs(tstr + 1, stdout);
  155.             return;
  156.         }
  157.     }
  158.  
  159.     /* Decode the vendor buffer */
  160.     TCHECK(bp->bp_vend[0]);
  161.     length -= sizeof(*bp) - sizeof(bp->bp_vend);
  162.     if (memcmp((char *)bp->bp_vend, (char *)vm_rfc1048,
  163.          sizeof(u_int32_t)) == 0)
  164.         rfc1048_print(bp->bp_vend, length);
  165.     else if (memcmp((char *)bp->bp_vend, (char *)vm_cmu,
  166.               sizeof(u_int32_t)) == 0)
  167.         cmu_print(bp->bp_vend, length);
  168.     else {
  169.         u_int32_t ul;
  170.  
  171.         memcpy((char *)&ul, (char *)bp->bp_vend, sizeof(ul));
  172.         if (ul != 0)
  173.             printf("vend-#0x%x", ul);
  174.     }
  175.  
  176.     return;
  177. trunc:
  178.     fputs(tstr, stdout);
  179. }
  180.  
  181. /* The first character specifies the format to print */
  182. static struct tok tag2str[] = {
  183. /* RFC1048 tags */
  184.     { TAG_PAD,        " PAD" },
  185.     { TAG_SUBNET_MASK,    "iSM" },    /* subnet mask (RFC950) */
  186.     { TAG_TIME_OFFSET,    "lTZ" },    /* seconds from UTC */
  187.     { TAG_GATEWAY,        "iDG" },    /* default gateway */
  188.     { TAG_TIME_SERVER,    "iTS" },    /* time servers (RFC868) */
  189.     { TAG_NAME_SERVER,    "iIEN" },    /* IEN name servers (IEN116) */
  190.     { TAG_DOMAIN_SERVER,    "iNS" },    /* domain name (RFC1035) */
  191.     { TAG_LOG_SERVER,    "iLOG" },    /* MIT log servers */
  192.     { TAG_COOKIE_SERVER,    "iCS" },    /* cookie servers (RFC865) */
  193.     { TAG_LPR_SERVER,    "iLPR" },    /* lpr server (RFC1179) */
  194.     { TAG_IMPRESS_SERVER,    "iIM" },    /* impress servers (Imagen) */
  195.     { TAG_RLP_SERVER,    "iRL" },    /* resource location (RFC887) */
  196.     { TAG_HOSTNAME,        "aHN" },    /* ascii hostname */
  197.     { TAG_BOOTSIZE,        "sBS" },    /* 512 byte blocks */
  198.     { TAG_END,        " END" },
  199. /* RFC1497 tags */
  200.     { TAG_DUMPPATH,        "aDP" },
  201.     { TAG_DOMAINNAME,    "aDN" },
  202.     { TAG_SWAP_SERVER,    "iSS" },
  203.     { TAG_ROOTPATH,        "aRP" },
  204.     { TAG_EXTPATH,        "aEP" },
  205.     { 0,            NULL }
  206. };
  207.  
  208. static void
  209. rfc1048_print(register const u_char *bp, register u_int length)
  210. {
  211.     register u_char tag;
  212.     register u_int len, size;
  213.     register const char *cp;
  214.     register char c;
  215.     int first;
  216.     u_int32_t ul;
  217.     u_short us;
  218.  
  219.     printf(" vend-rfc1048");
  220.  
  221.     /* Step over magic cookie */
  222.     bp += sizeof(int32_t);
  223.  
  224.     /* Loop while we there is a tag left in the buffer */
  225.     while (bp + 1 < snapend) {
  226.         tag = *bp++;
  227.         if (tag == TAG_PAD)
  228.             continue;
  229.         if (tag == TAG_END)
  230.             return;
  231.         cp = tok2str(tag2str, "?T%d", tag);
  232.         c = *cp++;
  233.         printf(" %s:", cp);
  234.  
  235.         /* Get the length; check for truncation */
  236.         if (bp + 1 >= snapend) {
  237.             fputs(tstr, stdout);
  238.             return;
  239.         }
  240.         len = *bp++;
  241.         if (bp + len >= snapend) {
  242.             fputs(tstr, stdout);
  243.             return;
  244.         }
  245.  
  246.         /* Print data */
  247.         size = len;
  248.         if (c == '?') {
  249.             /* Base default formats for unknown tags on data size */
  250.             if (size & 1)
  251.                 c = 'b';
  252.             else if (size & 2)
  253.                 c = 's';
  254.             else
  255.                 c = 'l';
  256.         }
  257.         first = 1;
  258.         switch (c) {
  259.  
  260.         case 'a':
  261.             /* ascii strings */
  262.             putchar('"');
  263.             (void)fn_printn(bp, size, NULL);
  264.             putchar('"');
  265.             bp += size;
  266.             size = 0;
  267.             break;
  268.  
  269.         case 'i':
  270.         case 'l':
  271.             /* ip addresses/32-bit words */
  272.             while (size >= sizeof(ul)) {
  273.                 if (!first)
  274.                     putchar(',');
  275.                 memcpy((char *)&ul, (char *)bp, sizeof(ul));
  276.                 if (c == 'i')
  277.                     printf("%s", ipaddr_string(&ul));
  278.                 else
  279.                     printf("%u", ul);
  280.                 bp += sizeof(ul);
  281.                 size -= sizeof(ul);
  282.                 first = 0;
  283.             }
  284.             break;
  285.  
  286.         case 's':
  287.             /* shorts */
  288.             while (size >= sizeof(us)) {
  289.                 if (!first)
  290.                     putchar(',');
  291.                 memcpy((char *)&us, (char *)bp, sizeof(us));
  292.                 printf("%d", us);
  293.                 bp += sizeof(us);
  294.                 size -= sizeof(us);
  295.                 first = 0;
  296.             }
  297.             break;
  298.  
  299.         case 'b':
  300.         default:
  301.             /* Bytes */
  302.             while (size > 0) {
  303.                 if (!first)
  304.                     putchar('.');
  305.                 printf("%d", *bp);
  306.                 ++bp;
  307.                 --size;
  308.                 first = 0;
  309.             }
  310.             break;
  311.         }
  312.         /* Data left over? */
  313.         if (size)
  314.             printf("[len %d]", len);
  315.     }
  316. }
  317.  
  318. static void
  319. cmu_print(register const u_char *bp, register u_int length)
  320. {
  321.     register const struct cmu_vend *cmu;
  322.     char *fmt = " %s:%s";
  323.  
  324. #define PRINTCMUADDR(m, s) { TCHECK(cmu->m); \
  325.     if (cmu->m.s_addr != 0) \
  326.     printf(fmt, s, ipaddr_string(&cmu->m.s_addr)); }
  327.  
  328.     printf(" vend-cmu");
  329.     cmu = (struct cmu_vend *)bp;
  330.  
  331.     /* Only print if there are unknown bits */
  332.     TCHECK(cmu->v_flags);
  333.     if ((cmu->v_flags & ~(VF_SMASK)) != 0)
  334.         printf(" F:0x%x", cmu->v_flags);
  335.     PRINTCMUADDR(v_dgate, "DG");
  336.     PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*");
  337.     PRINTCMUADDR(v_dns1, "NS1");
  338.     PRINTCMUADDR(v_dns2, "NS2");
  339.     PRINTCMUADDR(v_ins1, "IEN1");
  340.     PRINTCMUADDR(v_ins2, "IEN2");
  341.     PRINTCMUADDR(v_ts1, "TS1");
  342.     PRINTCMUADDR(v_ts2, "TS2");
  343.     return;
  344.  
  345. trunc:
  346.     fputs(tstr, stdout);
  347. #undef PRINTCMUADDR
  348. }
  349.