home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / tcpdumpb.zip / print-atalk.c < prev    next >
C/C++ Source or Header  |  1997-02-14  |  20KB  |  575 lines

  1. /*
  2.  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 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 AppleTalk packets.
  22.  */
  23. #ifndef lint
  24. static  char rcsid[] =
  25.         "@(#)$Header: print-atalk.c,v 1.43 96/07/23 14:16:55 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/in_systm.h>
  40. #include <netinet/ip.h>
  41. #ifndef __EMX__
  42. #include <netinet/ip_var.h>
  43. #endif
  44. #include <netinet/if_ether.h>
  45. #include <netinet/udp.h>
  46. #include <netinet/udp_var.h>
  47. #include <netinet/tcp.h>
  48. #ifndef __EMX__
  49. #include <netinet/tcpip.h>
  50. #endif
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include <string.h>
  54.  
  55. #include "interface.h"
  56. #include "addrtoname.h"
  57. #include "ethertype.h"
  58. #include "extract.h"                    /* must come after interface.h */
  59. #include "appletalk.h"
  60.  
  61. static struct tok type2str[] = {
  62.         { ddpRTMP,              "rtmp" },
  63.         { ddpRTMPrequest,       "rtmpReq" },
  64.         { ddpECHO,              "echo" },
  65.         { ddpIP,                "IP" },
  66.         { ddpARP,               "ARP" },
  67.         { ddpKLAP,              "KLAP" },
  68.         { 0,                    NULL }
  69. };
  70.  
  71. struct aarp {
  72.         u_short htype, ptype;
  73.         u_char  halen, palen;
  74.         u_short op;
  75.         u_char  hsaddr[6];
  76.         u_char  psaddr[4];
  77.         u_char  hdaddr[6];
  78.         u_char  pdaddr[4];
  79. };
  80.  
  81. static char tstr[] = "[|atalk]";
  82.  
  83. static void atp_print(const struct atATP *, u_int);
  84. static void atp_bitmap_print(u_char);
  85. static void nbp_print(const struct atNBP *, u_int, u_short, u_char, u_char);
  86. static const char *print_cstring(const char *, const u_char *);
  87. static const struct atNBPtuple *nbp_tuple_print(const struct atNBPtuple *,
  88.                                                 const u_char *,
  89.                                                 u_short, u_char, u_char);
  90. static const struct atNBPtuple *nbp_name_print(const struct atNBPtuple *,
  91.                                                const u_char *);
  92. static const char *ataddr_string(u_short, u_char);
  93. static void ddp_print(const u_char *, u_int, int, u_short, u_char, u_char);
  94. static const char *ddpskt_string(int);
  95.  
  96. /*
  97.  * Print AppleTalk Datagram Delivery Protocol packets.
  98.  */
  99. void
  100. atalk_print(register const u_char *bp, u_int length)
  101. {
  102.         register const struct LAP *lp;
  103.         register const struct atDDP *dp;
  104.         register const struct atShortDDP *sdp;
  105.         u_short snet;
  106.  
  107.         lp = (struct LAP *)bp;
  108.         bp += sizeof(*lp);
  109.         length -= sizeof(*lp);
  110.         switch (lp->type) {
  111.  
  112.         case lapShortDDP:
  113.                 if (length < ddpSSize) {
  114.                         (void)printf(" [|sddp %d]", length);
  115.                         return;
  116.                 }
  117.                 sdp = (const struct atShortDDP *)bp;
  118.                 printf("%s.%s",
  119.                     ataddr_string(0, lp->src), ddpskt_string(sdp->srcSkt));
  120.                 printf(" > %s.%s:",
  121.                     ataddr_string(0, lp->dst), ddpskt_string(sdp->dstSkt));
  122.                 bp += ddpSSize;
  123.                 length -= ddpSSize;
  124.                 ddp_print(bp, length, sdp->type, 0, lp->src, sdp->srcSkt);
  125.                 break;
  126.  
  127.         case lapDDP:
  128.                 if (length < ddpSize) {
  129.                         (void)printf(" [|ddp %d]", length);
  130.                         return;
  131.                 }
  132.                 dp = (const struct atDDP *)bp;
  133.                 snet = EXTRACT_16BITS(&dp->srcNet);
  134.                 printf("%s.%s", ataddr_string(snet, dp->srcNode),
  135.                     ddpskt_string(dp->srcSkt));
  136.                 printf(" > %s.%s:",
  137.                     ataddr_string(EXTRACT_16BITS(&dp->dstNet), dp->dstNode),
  138.                     ddpskt_string(dp->dstSkt));
  139.                 bp += ddpSize;
  140.                 length -= ddpSize;
  141.                 ddp_print(bp, length, dp->type, snet, dp->srcNode, dp->srcSkt);
  142.                 break;
  143.  
  144. #ifdef notdef
  145.         case lapKLAP:
  146.                 klap_print(bp, length);
  147.                 break;
  148. #endif
  149.  
  150.         default:
  151.                 printf("%d > %d at-lap#%d %d",
  152.                     lp->src, lp->dst, lp->type, length);
  153.                 break;
  154.         }
  155. }
  156.  
  157. /* XXX should probably pass in the snap header and do checks like arp_print() */
  158. void
  159. aarp_print(register const u_char *bp, u_int length)
  160. {
  161.         register const struct aarp *ap;
  162.  
  163. #define AT(member) ataddr_string((ap->member[1]<<8)|ap->member[2],ap->member[3])
  164.  
  165.         printf("aarp ");
  166.         ap = (const struct aarp *)bp;
  167.         if (ap->htype == 1 && ap->ptype == ETHERTYPE_ATALK &&
  168.             ap->halen == 6 && ap->palen == 4 )
  169.                 switch (ap->op) {
  170.  
  171.                 case 1:                         /* request */
  172.                         (void)printf("who-has %s tell %s",
  173.                             AT(pdaddr), AT(psaddr));
  174.                         return;
  175.  
  176.                 case 2:                         /* response */
  177.                         (void)printf("reply %s is-at %s",
  178.                             AT(pdaddr), etheraddr_string(ap->hdaddr));
  179.                         return;
  180.  
  181.                 case 3:                         /* probe (oy!) */
  182.                         (void)printf("probe %s tell %s",
  183.                             AT(pdaddr), AT(psaddr));
  184.                         return;
  185.                 }
  186.         (void)printf("len %d op %d htype %d ptype %#x halen %d palen %d",
  187.             length, ap->op, ap->htype, ap->ptype, ap->halen, ap->palen );
  188. }
  189.  
  190. static void
  191. ddp_print(register const u_char *bp, register u_int length, register int t,
  192.           register u_short snet, register u_char snode, u_char skt)
  193. {
  194.  
  195.         switch (t) {
  196.  
  197.         case ddpNBP:
  198.                 nbp_print((const struct atNBP *)bp, length, snet, snode, skt);
  199.                 break;
  200.  
  201.         case ddpATP:
  202.                 atp_print((const struct atATP *)bp, length);
  203.                 break;
  204.  
  205.         default:
  206.                 (void)printf(" at-%s %d", tok2str(type2str, NULL, t), length);
  207.                 break;
  208.         }
  209. }
  210.  
  211. static void
  212. atp_print(register const struct atATP *ap, u_int length)
  213. {
  214.         char c;
  215.         u_int32_t data;
  216.  
  217.         if ((const u_char *)(ap + 1) > snapend) {
  218.                 /* Just bail if we don't have the whole chunk. */
  219.                 fputs(tstr, stdout);
  220.                 return;
  221.         }
  222.         length -= sizeof(*ap);
  223.         switch (ap->control & 0xc0) {
  224.  
  225.         case atpReqCode:
  226.                 (void)printf(" atp-req%s %d",
  227.                              ap->control & atpXO? " " : "*",
  228.                              EXTRACT_16BITS(&ap->transID));
  229.  
  230.                 atp_bitmap_print(ap->bitmap);
  231.  
  232.                 if (length != 0)
  233.                         (void)printf(" [len=%d]", length);
  234.  
  235.                 switch (ap->control & (atpEOM|atpSTS)) {
  236.                 case atpEOM:
  237.                         (void)printf(" [EOM]");
  238.                         break;
  239.                 case atpSTS:
  240.                         (void)printf(" [STS]");
  241.                         break;
  242.                 case atpEOM|atpSTS:
  243.                         (void)printf(" [EOM,STS]");
  244.                         break;
  245.                 }
  246.                 break;
  247.  
  248.         case atpRspCode:
  249.                 (void)printf(" atp-resp%s%d:%d (%d)",
  250.                              ap->control & atpEOM? "*" : " ",
  251.                              EXTRACT_16BITS(&ap->transID), ap->bitmap, length);
  252.                 switch (ap->control & (atpXO|atpSTS)) {
  253.                 case atpXO:
  254.                         (void)printf(" [XO]");
  255.                         break;
  256.                 case atpSTS:
  257.                         (void)printf(" [STS]");
  258.                         break;
  259.                 case atpXO|atpSTS:
  260.                         (void)printf(" [XO,STS]");
  261.                         break;
  262.                 }
  263.                 break;
  264.  
  265.         case atpRelCode:
  266.                 (void)printf(" atp-rel  %d", EXTRACT_16BITS(&ap->transID));
  267.  
  268.                 atp_bitmap_print(ap->bitmap);
  269.  
  270.                 /* length should be zero */
  271.                 if (length)
  272.                         (void)printf(" [len=%d]", length);
  273.  
  274.                 /* there shouldn't be any control flags */
  275.                 if (ap->control & (atpXO|atpEOM|atpSTS)) {
  276.                         c = '[';
  277.                         if (ap->control & atpXO) {
  278.                                 (void)printf("%cXO", c);
  279.                                 c = ',';
  280.                         }
  281.                         if (ap->control & atpEOM) {
  282.                                 (void)printf("%cEOM", c);
  283.                                 c = ',';
  284.                         }
  285.                         if (ap->control & atpSTS) {
  286.                                 (void)printf("%cSTS", c);
  287.                                 c = ',';
  288.                         }
  289.                         (void)printf("]");
  290.                 }
  291.                 break;
  292.  
  293.         default:
  294.                 (void)printf(" atp-0x%x  %d (%d)", ap->control,
  295.                              EXTRACT_16BITS(&ap->transID), length);
  296.                 break;
  297.         }
  298.         data = EXTRACT_32BITS(&ap->userData);
  299.         if (data != 0)
  300.                 (void)printf(" 0x%x", data);
  301. }
  302.  
  303. static void
  304. atp_bitmap_print(register u_char bm)
  305. {
  306.         register char c;
  307.         register int i;
  308.  
  309.         /*
  310.          * The '& 0xff' below is needed for compilers that want to sign
  311.          * extend a u_char, which is the case with the Ultrix compiler.
  312.          * (gcc is smart enough to eliminate it, at least on the Sparc).
  313.          */
  314.         if ((bm + 1) & (bm & 0xff)) {
  315.                 c = '<';
  316.                 for (i = 0; bm; ++i) {
  317.                         if (bm & 1) {
  318.                                 (void)printf("%c%d", c, i);
  319.                                 c = ',';
  320.                         }
  321.                         bm >>= 1;
  322.                 }
  323.                 (void)printf(">");
  324.         } else {
  325.                 for (i = 0; bm; ++i)
  326.                         bm >>= 1;
  327.                 if (i > 1)
  328.                         (void)printf("<0-%d>", i - 1);
  329.                 else
  330.                         (void)printf("<0>");
  331.         }
  332. }
  333.  
  334. static void
  335. nbp_print(register const struct atNBP *np, u_int length, register u_short snet,
  336.           register u_char snode, register u_char skt)
  337. {
  338.         register const struct atNBPtuple *tp =
  339.                         (struct atNBPtuple *)((u_char *)np + nbpHeaderSize);
  340.         int i;
  341.         const u_char *ep;
  342.  
  343.         length -= nbpHeaderSize;
  344.         if (length < 8) {
  345.                 /* must be room for at least one tuple */
  346.                 (void)printf(" truncated-nbp %d", length + nbpHeaderSize);
  347.                 return;
  348.         }
  349.         /* ep points to end of available data */
  350.         ep = snapend;
  351.         if ((const u_char *)tp > ep) {
  352.                 fputs(tstr, stdout);
  353.                 return;
  354.         }
  355.         switch (i = np->control & 0xf0) {
  356.  
  357.         case nbpBrRq:
  358.         case nbpLkUp:
  359.                 (void)printf(i == nbpLkUp? " nbp-lkup %d:":" nbp-brRq %d:",
  360.                              np->id);
  361.                 if ((const u_char *)(tp + 1) > ep) {
  362.                         fputs(tstr, stdout);
  363.                         return;
  364.                 }
  365.                 (void)nbp_name_print(tp, ep);
  366.                 /*
  367.                  * look for anomalies: the spec says there can only
  368.                  * be one tuple, the address must match the source
  369.                  * address and the enumerator should be zero.
  370.                  */
  371.                 if ((np->control & 0xf) != 1)
  372.                         (void)printf(" [ntup=%d]", np->control & 0xf);
  373.                 if (tp->enumerator)
  374.                         (void)printf(" [enum=%d]", tp->enumerator);
  375.                 if (EXTRACT_16BITS(&tp->net) != snet ||
  376.                     tp->node != snode || tp->skt != skt)
  377.                         (void)printf(" [addr=%s.%d]",
  378.                             ataddr_string(EXTRACT_16BITS(&tp->net),
  379.                             tp->node), tp->skt);
  380.                 break;
  381.  
  382.         case nbpLkUpReply:
  383.                 (void)printf(" nbp-reply %d:", np->id);
  384.  
  385.                 /* print each of the tuples in the reply */
  386.                 for (i = np->control & 0xf; --i >= 0 && tp; )
  387.                         tp = nbp_tuple_print(tp, ep, snet, snode, skt);
  388.                 break;
  389.  
  390.         default:
  391.                 (void)printf(" nbp-0x%x  %d (%d)", np->control, np->id,
  392.                                 length);
  393.                 break;
  394.         }
  395. }
  396.  
  397. /* print a counted string */
  398. static const char *
  399. print_cstring(register const char *cp, register const u_char *ep)
  400. {
  401.         register u_int length;
  402.  
  403.         if (cp >= (const char *)ep) {
  404.                 fputs(tstr, stdout);
  405.                 return (0);
  406.         }
  407.         length = *cp++;
  408.  
  409.         /* Spec says string can be at most 32 bytes long */
  410.         if (length < 0 || length > 32) {
  411.                 (void)printf("[len=%d]", length);
  412.                 return (0);
  413.         }
  414.         while (--length >= 0) {
  415.                 if (cp >= (char *)ep) {
  416.                         fputs(tstr, stdout);
  417.                         return (0);
  418.                 }
  419.                 putchar(*cp++);
  420.         }
  421.         return (cp);
  422. }
  423.  
  424. static const struct atNBPtuple *
  425. nbp_tuple_print(register const struct atNBPtuple *tp,
  426.                 register const u_char *ep,
  427.                 register u_short snet, register u_char snode,
  428.                 register u_char skt)
  429. {
  430.         register const struct atNBPtuple *tpn;
  431.  
  432.         if ((const u_char *)(tp + 1) > ep) {
  433.                 fputs(tstr, stdout);
  434.                 return 0;
  435.         }
  436.         tpn = nbp_name_print(tp, ep);
  437.  
  438.         /* if the enumerator isn't 1, print it */
  439.         if (tp->enumerator != 1)
  440.                 (void)printf("(%d)", tp->enumerator);
  441.  
  442.         /* if the socket doesn't match the src socket, print it */
  443.         if (tp->skt != skt)
  444.                 (void)printf(" %d", tp->skt);
  445.  
  446.         /* if the address doesn't match the src address, it's an anomaly */
  447.         if (EXTRACT_16BITS(&tp->net) != snet || tp->node != snode)
  448.                 (void)printf(" [addr=%s]",
  449.                     ataddr_string(EXTRACT_16BITS(&tp->net), tp->node));
  450.  
  451.         return (tpn);
  452. }
  453.  
  454. static const struct atNBPtuple *
  455. nbp_name_print(const struct atNBPtuple *tp, register const u_char *ep)
  456. {
  457.         register const char *cp = (const char *)tp + nbpTupleSize;
  458.  
  459.         putchar(' ');
  460.  
  461.         /* Object */
  462.         putchar('"');
  463.         if ((cp = print_cstring(cp, ep)) != NULL) {
  464.                 /* Type */
  465.                 putchar(':');
  466.                 if ((cp = print_cstring(cp, ep)) != NULL) {
  467.                         /* Zone */
  468.                         putchar('@');
  469.                         if ((cp = print_cstring(cp, ep)) != NULL)
  470.                                 putchar('"');
  471.                 }
  472.         }
  473.         return ((const struct atNBPtuple *)cp);
  474. }
  475.  
  476.  
  477. #define HASHNAMESIZE 4096
  478.  
  479. struct hnamemem {
  480.         int addr;
  481.         char *name;
  482.         struct hnamemem *nxt;
  483. };
  484.  
  485. static struct hnamemem hnametable[HASHNAMESIZE];
  486.  
  487. static const char *
  488. ataddr_string(u_short atnet, u_char athost)
  489. {
  490.         register struct hnamemem *tp, *tp2;
  491.         register int i = (atnet << 8) | athost;
  492.         char nambuf[256];
  493.         static int first = 1;
  494.         FILE *fp;
  495.  
  496.         /*
  497.          * if this is the first call, see if there's an AppleTalk
  498.          * number to name map file.
  499.          */
  500.         if (first && (first = 0, !nflag)
  501.             && (fp = fopen("/etc/atalk.names", "r"))) {
  502.                 char line[256];
  503.                 int i1, i2, i3;
  504.  
  505.                 while (fgets(line, sizeof(line), fp)) {
  506.                         if (line[0] == '\n' || line[0] == 0 || line[0] == '#')
  507.                                 continue;
  508.                         if (sscanf(line, "%d.%d.%d %s", &i1, &i2, &i3,
  509.                                      nambuf) == 4)
  510.                                 /* got a hostname. */
  511.                                 i3 |= ((i1 << 8) | i2) << 8;
  512.                         else if (sscanf(line, "%d.%d %s", &i1, &i2,
  513.                                         nambuf) == 3)
  514.                                 /* got a net name */
  515.                                 i3 = (((i1 << 8) | i2) << 8) | 255;
  516.                         else
  517.                                 continue;
  518.  
  519.                         for (tp = &hnametable[i3 & (HASHNAMESIZE-1)];
  520.                              tp->nxt; tp = tp->nxt)
  521.                                 ;
  522.                         tp->addr = i3;
  523.                         tp->nxt = newhnamemem();
  524.                         tp->name = savestr(nambuf);
  525.                 }
  526.                 fclose(fp);
  527.         }
  528.  
  529.         for (tp = &hnametable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
  530.                 if (tp->addr == i)
  531.                         return (tp->name);
  532.  
  533.         /* didn't have the node name -- see if we've got the net name */
  534.         i |= 255;
  535.         for (tp2 = &hnametable[i & (HASHNAMESIZE-1)]; tp2->nxt; tp2 = tp2->nxt)
  536.                 if (tp2->addr == i) {
  537.                         tp->addr = (atnet << 8) | athost;
  538.                         tp->nxt = newhnamemem();
  539.                         (void)sprintf(nambuf, "%s.%d", tp2->name, athost);
  540.                         tp->name = savestr(nambuf);
  541.                         return (tp->name);
  542.                 }
  543.  
  544.         tp->addr = (atnet << 8) | athost;
  545.         tp->nxt = newhnamemem();
  546.         if (athost != 255)
  547.                 (void)sprintf(nambuf, "%d.%d.%d",
  548.                     atnet >> 8, atnet & 0xff, athost);
  549.         else
  550.                 (void)sprintf(nambuf, "%d.%d", atnet >> 8, atnet & 0xff);
  551.         tp->name = savestr(nambuf);
  552.  
  553.         return (tp->name);
  554. }
  555.  
  556. static struct tok skt2str[] = {
  557.         { rtmpSkt,      "rtmp" },       /* routing table maintenance */
  558.         { nbpSkt,       "nis" },        /* name info socket */
  559.         { echoSkt,      "echo" },       /* AppleTalk echo protocol */
  560.         { zipSkt,       "zip" },        /* zone info protocol */
  561.         { 0,            NULL }
  562. };
  563.  
  564. static const char *
  565. ddpskt_string(register int skt)
  566. {
  567.         static char buf[8];
  568.  
  569.         if (nflag) {
  570.                 (void)sprintf(buf, "%d", skt);
  571.                 return (buf);
  572.         }
  573.         return (tok2str(skt2str, "%d", skt));
  574. }
  575.