home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / trace / tcpdump-2.2.1 / addrtoname.c next >
Encoding:
C/C++ Source or Header  |  1992-05-25  |  10.2 KB  |  479 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.  *  Internet, ethernet, port, and protocol string to address
  22.  *  and address to string conversion routines
  23.  */
  24. #ifndef lint
  25. static char rcsid[] =
  26.     "@(#) $Header: addrtoname.c,v 1.14 92/05/25 14:29:07 mccanne Exp $ (LBL)";
  27. #endif
  28.  
  29. #include <stdio.h>
  30. #include <strings.h>
  31. #include <ctype.h>
  32. #include <sys/types.h>
  33. #include <sys/socket.h>
  34. #include <net/if.h>
  35. #include <netdb.h>
  36. #include <netinet/in.h>
  37. #include <netinet/if_ether.h>
  38. #include <arpa/inet.h>
  39. #include <signal.h>
  40.  
  41. #include "interface.h"
  42. #include "addrtoname.h"
  43. #include "nametoaddr.h"
  44. #include "etherent.h"
  45.  
  46. /*
  47.  * hash tables for whatever-to-name translations
  48.  */
  49.  
  50. #define HASHNAMESIZE 4096
  51.  
  52. struct hnamemem {
  53.     u_long addr;
  54.     char *name;
  55.     struct hnamemem *nxt;
  56. };
  57.  
  58. struct hnamemem hnametable[HASHNAMESIZE];
  59. struct hnamemem tporttable[HASHNAMESIZE];
  60. struct hnamemem uporttable[HASHNAMESIZE];
  61. struct hnamemem eprototable[HASHNAMESIZE];
  62.  
  63. struct enamemem {
  64.     u_short e_addr0;
  65.     u_short e_addr1;
  66.     u_short e_addr2;
  67.     char *e_name;
  68.     struct enamemem *e_nxt;
  69. };
  70.  
  71. struct enamemem enametable[HASHNAMESIZE];
  72.  
  73.  
  74. /*
  75.  * A faster replacement for inet_ntoa().
  76.  */
  77. char *
  78. intoa(addr)
  79.     u_long addr;
  80. {
  81.     register char *cp;
  82.     register u_int byte;
  83.     register int n;
  84.     static char buf[sizeof(".xxx.xxx.xxx.xxx")];
  85.  
  86.     NTOHL(addr);
  87.     cp = &buf[sizeof buf];
  88.     *--cp = '\0';
  89.  
  90.     n = 4;
  91.     do {
  92.         byte = addr & 0xff;
  93.         *--cp = byte % 10 + '0';
  94.         byte /= 10;
  95.         if (byte > 0) {
  96.             *--cp = byte % 10 + '0';
  97.             byte /= 10;
  98.             if (byte > 0)
  99.                 *--cp = byte + '0';
  100.         }
  101.         *--cp = '.';
  102.         addr >>= 8;
  103.     } while (--n > 0);
  104.  
  105.     return cp + 1;
  106. }
  107.  
  108. static u_long f_netmask;
  109. static u_long f_localnet;
  110. static u_long netmask;
  111.  
  112. /*
  113.  * "getname" is written in this atrocious way to make sure we don't
  114.  * wait forever while trying to get hostnames from yp.
  115.  */
  116. #include <setjmp.h>
  117.  
  118. jmp_buf getname_env;
  119.  
  120. static void
  121. nohostname()
  122. {
  123.     longjmp(getname_env, 1);
  124. }
  125.  
  126. /*
  127.  * Return a name for the IP address pointed to by ap.  This address
  128.  * is assumed to be in network byte order.
  129.  */
  130. char *
  131. getname(ap)
  132.     u_char *ap;
  133. {
  134.     register struct hnamemem *p;
  135.     register struct hostent *hp;
  136.     register char *cp;
  137.     u_long addr;
  138.  
  139. #ifndef TCPDUMP_ALIGN
  140.     addr = *(u_long *)ap;
  141. #else
  142.     /*
  143.      * Deal with alignment.
  144.      */
  145.     switch ((int)ap & 3) {
  146.  
  147.     case 0:
  148.         addr = *(u_long *)ap;
  149.         break;
  150.  
  151.     case 2:
  152. #if BYTE_ORDER == LITTLE_ENDIAN
  153.         addr = ((u_long)*(u_short *)(ap + 2) << 16) | 
  154.             (u_long)*(u_short *)ap;
  155. #else
  156.         addr = ((u_long)*(u_short *)ap << 16) | 
  157.             (u_long)*(u_short *)(ap + 2);
  158. #endif
  159.         break;
  160.  
  161.     default:
  162. #if BYTE_ORDER == LITTLE_ENDIAN
  163.         addr = ((u_long)ap[0] << 24) |
  164.             ((u_long)ap[1] << 16) |
  165.             ((u_long)ap[2] << 8) |
  166.             (u_long)ap[3];
  167. #else
  168.         addr = ((u_long)ap[3] << 24) |
  169.             ((u_long)ap[2] << 16) |
  170.             ((u_long)ap[1] << 8) |
  171.             (u_long)ap[0];
  172. #endif
  173.         break;
  174.     }
  175. #endif
  176.     p = &hnametable[addr & (HASHNAMESIZE-1)]; 
  177.     for (; p->nxt; p = p->nxt) {
  178.         if (p->addr == addr)
  179.             return (p->name);
  180.     }
  181.     p->addr = addr;
  182.     p->nxt = (struct hnamemem *)calloc(1, sizeof (*p));
  183.  
  184.     /*
  185.      * Only print names when:
  186.      *     (1) -n was not given.
  187.      *    (2) Address is foreign and -f was given.  If -f was not 
  188.      *        present, f_netmask and f_local are 0 and the second
  189.      *        test will succeed.
  190.      *    (3) The host portion is not 0 (i.e., a network address).
  191.      *    (4) The host portion is not broadcast.
  192.      */
  193.     if (!nflag && (addr & f_netmask) == f_localnet
  194.         && (addr &~ netmask) != 0 && (addr | netmask) != 0xffffffff) {
  195.         if (!setjmp(getname_env)) {
  196.             (void)signal(SIGALRM, nohostname);
  197.             (void)alarm(20);
  198.             hp = gethostbyaddr((char *)&addr, 4, AF_INET);
  199.             (void)alarm(0);
  200.             if (hp) {
  201.                 char *index();
  202.                 char *dotp;    
  203.                 u_int len = strlen(hp->h_name) + 1;
  204.                 p->name = (char *)malloc(len);
  205.                 (void)strcpy(p->name, hp->h_name);
  206.                 if (Nflag) {
  207.                     /* Remove domain qualifications */
  208.                     dotp = index(p->name, '.');
  209.                     if (dotp)
  210.                         *dotp = 0;
  211.                 }
  212.                 return (p->name);
  213.             }
  214.         }
  215.     }
  216.     cp = intoa(addr);
  217.     p->name = (char *)malloc((unsigned)(strlen(cp) + 1));
  218.     (void)strcpy(p->name, cp);
  219.     return (p->name);
  220. }
  221.  
  222. static char hex[] = "0123456789abcdef";
  223.  
  224.  
  225. /* Find the hash node that corresponds the ether address 'ep'. */
  226.  
  227. static inline struct enamemem *
  228. lookup_emem(ep)
  229.     u_char *ep;
  230. {
  231.     register u_int i, j, k;
  232.     struct enamemem *tp;
  233.  
  234.     k = (ep[0] << 8) | ep[1];
  235.     j = (ep[2] << 8) | ep[3];
  236.     i = (ep[4] << 8) | ep[5];
  237.  
  238.     tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)];
  239.     while (tp->e_nxt)
  240.         if (tp->e_addr0 == i &&
  241.             tp->e_addr1 == j &&
  242.             tp->e_addr2 == k)
  243.             return tp;
  244.         else
  245.             tp = tp->e_nxt;
  246.     tp->e_addr0 = i;
  247.     tp->e_addr1 = j;
  248.     tp->e_addr2 = k;
  249.     tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
  250.  
  251.     return tp;
  252. }
  253.  
  254. char *
  255. etheraddr_string(ep)
  256.     register u_char *ep;
  257. {
  258.     register u_int i, j;
  259.     register char *cp;
  260.     register struct enamemem *tp;
  261.  
  262.     tp = lookup_emem(ep);
  263.     if (tp->e_name)
  264.         return tp->e_name;
  265.  
  266. #ifdef ETHER_SERVICE
  267.     if (!nflag) {
  268.         cp = ETHER_ntohost(ep);
  269.         if (cp) {
  270.             tp->e_name = cp;
  271.             return cp;
  272.         }
  273.     }
  274. #endif        
  275.     tp->e_name = cp = (char *)malloc(sizeof("00:00:00:00:00:00"));
  276.  
  277.     if (j = *ep >> 4)
  278.         *cp++ = hex[j];
  279.     *cp++ = hex[*ep++ & 0xf];
  280.     for (i = 5; (int)--i >= 0;) {
  281.         *cp++ = ':';
  282.         if (j = *ep >> 4)
  283.             *cp++ = hex[j];
  284.         *cp++ = hex[*ep++ & 0xf];
  285.     }
  286.     *cp = '\0';
  287.     return (tp->e_name);
  288. }
  289.  
  290. char *
  291. etherproto_string(port)
  292.     u_short port;
  293. {
  294.     register char *cp;
  295.     register struct hnamemem *tp;
  296.     register u_long i = port;
  297.  
  298.     for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
  299.         if (tp->addr == i)
  300.             return (tp->name);
  301.  
  302.     tp->name = cp = (char *)malloc(sizeof("0000"));
  303.     tp->addr = i;
  304.     tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp));
  305.  
  306.     NTOHS(port);
  307.     *cp++ = hex[port >> 12 & 0xf];
  308.     *cp++ = hex[port >> 8 & 0xf];
  309.     *cp++ = hex[port >> 4 & 0xf];
  310.     *cp++ = hex[port & 0xf];
  311.     *cp++ = '\0';
  312.     return (tp->name);
  313. }
  314.  
  315. char *
  316. tcpport_string(port)
  317.     u_short port;
  318. {
  319.     register struct hnamemem *tp;
  320.     register int i = port;
  321.  
  322.     for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
  323.         if (tp->addr == i)
  324.             return (tp->name);
  325.  
  326.     tp->name = (char *)malloc(sizeof("00000"));
  327.     tp->addr = i;
  328.     tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp));
  329.  
  330.     (void)sprintf(tp->name, "%d", i);
  331.     return (tp->name);
  332. }
  333.  
  334. char *
  335. udpport_string(port)
  336.     register u_short port;
  337. {
  338.     register struct hnamemem *tp;
  339.     register int i = port;
  340.  
  341.     for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
  342.         if (tp->addr == i)
  343.             return (tp->name);
  344.  
  345.     tp->name = (char *)malloc(sizeof("00000"));
  346.     tp->addr = i;
  347.     tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp));
  348.  
  349.     (void)sprintf(tp->name, "%d", i);
  350.  
  351.     return (tp->name);
  352. }
  353.  
  354. static void
  355. init_servarray()
  356. {
  357.     struct servent *sv;
  358.     register struct hnamemem *table;
  359.     register int i;
  360.  
  361.     while (sv = getservent()) {
  362.         NTOHS(sv->s_port);
  363.         i = sv->s_port & (HASHNAMESIZE-1);
  364.         if (strcmp(sv->s_proto, "tcp") == 0)
  365.             table = &tporttable[i];
  366.         else if (strcmp(sv->s_proto, "udp") == 0)
  367.             table = &uporttable[i];
  368.         else
  369.             continue;
  370.  
  371.         while (table->name)
  372.             table = table->nxt;
  373.         if (nflag) {
  374.             char buf[32];
  375.  
  376.             (void)sprintf(buf, "%d", sv->s_port);
  377.             table->name = (char *)malloc((unsigned)strlen(buf)+1);
  378.             (void)strcpy(table->name, buf);
  379.         } else {
  380.             table->name =
  381.                 (char *)malloc((unsigned)strlen(sv->s_name)+1);
  382.             (void)strcpy(table->name, sv->s_name);
  383.         }
  384.         table->addr = sv->s_port;
  385.         table->nxt = (struct hnamemem *)calloc(1, sizeof(*table));
  386.     }
  387.     endservent();
  388. }
  389.  
  390. #include "etherproto.h"
  391.  
  392. /* Static data base of ether protocol types. */
  393. struct eproto eproto_db[] = { 
  394.     { "pup", ETHERTYPE_PUP },
  395.     { "xns", ETHERTYPE_NS },
  396.     { "ip", ETHERTYPE_IP },
  397.     { "arp", ETHERTYPE_ARP },
  398.     { "rarp", ETHERTYPE_REVARP },
  399.     { "sprite", ETHERTYPE_SPRITE },
  400.     { "mopdl", ETHERTYPE_MOPDL },
  401.     { "moprc", ETHERTYPE_MOPRC },
  402.     { "decnet", ETHERTYPE_DN },
  403.     { "lat", ETHERTYPE_LAT },
  404.     { "lanbridge", ETHERTYPE_LANBRIDGE },
  405.     { "vexp", ETHERTYPE_VEXP },
  406.     { "vprod", ETHERTYPE_VPROD },
  407.     { "atalk", ETHERTYPE_ATALK },
  408.     { "atalkarp", ETHERTYPE_AARP },
  409.     { "loopback", ETHERTYPE_LOOPBACK },
  410.     { (char *)0, 0 }
  411. };
  412.  
  413. static void
  414. init_eprotoarray()
  415. {
  416.     register int i;
  417.     register struct hnamemem *table;
  418.  
  419.     for (i = 0; eproto_db[i].s; i++) {
  420.         int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1);
  421.         table = &eprototable[j];
  422.         while (table->name)
  423.             table = table->nxt;
  424.         table->name = eproto_db[i].s;
  425.         table->addr = ntohs(eproto_db[i].p);
  426.         table->nxt = (struct hnamemem *)calloc(1, sizeof(*table));
  427.     }
  428. }
  429.  
  430. static void
  431. init_etherarray()
  432. {
  433. #ifndef ETHER_SERVICE
  434.     FILE *fp;
  435.     struct etherent *ep;
  436.     struct enamemem *tp;
  437.  
  438.     fp = fopen(ETHERS_FILE, "r");
  439.     if (fp == 0)
  440.         /* No data base; will have to settle for 
  441.            numeric addresses. */
  442.         return;
  443.  
  444.     while (ep = next_etherent(fp)) {
  445.         tp = lookup_emem(ep->addr);
  446.         tp->e_name = (char *)malloc((unsigned)strlen(ep->name)+1);
  447.         strcpy(tp->e_name, ep->name);
  448.     }
  449. #endif
  450. }
  451.  
  452. /*
  453.  * Initialize the address to name translation machinery.  We map all
  454.  * non-local IP addresses to numeric addresses if fflag is true (i.e.,
  455.  * to prevent blocking on the nameserver).  localnet is the IP address
  456.  * of the local network.  mask is its subnet mask.
  457.  */
  458. void
  459. init_addrtoname(fflag, localnet, mask)
  460.     int fflag;
  461.     u_long localnet;
  462.     u_long mask;
  463. {
  464.     netmask = mask;
  465.     if (fflag) {
  466.         f_localnet = localnet;
  467.         f_netmask = mask;
  468.     }
  469.     if (nflag)
  470.         /*
  471.          * Simplest way to suppress names.
  472.          */
  473.         return;
  474.  
  475.     init_etherarray();
  476.     init_servarray();
  477.     init_eprotoarray();
  478. }
  479.