home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / slip / cslip-2.6 / myetheraddr / myetheraddr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-17  |  6.4 KB  |  273 lines

  1. /*
  2.  * Copyright (c) 1990, 1992 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. #ifndef lint
  22. static char copyright[] =
  23.     "Copyright (c) 1990, 1992 Lawrence Berkeley Laboratory\nAll rights reserved.\n";
  24. static char rcsid[] =
  25.     "@(#) $Header: myetheraddr.c,v 1.6 92/03/17 18:43:30 leres Exp $ (LBL)";
  26. #endif
  27.  
  28. /*
  29.  * myetheraddr - display ethernet local address(es)
  30.  *
  31.  * usage:
  32.  *
  33.  *    myetheraddr [-l] [host]
  34.  *
  35.  *        -l - long output (also display ip address and interface name)
  36.  *        host - want ethernet address of interface on same subnet as host
  37.  *
  38.  * Note: This program takes advantage of the fact that the ifnet struct
  39.  * is really part of the arpcom struct.
  40.  *
  41.  */
  42.  
  43. #include <stdio.h>
  44. #include <nlist.h>
  45.  
  46. /* XXX SunOS 4.1 defines this and 3.5 doesn't... */
  47. #ifdef _nlist_h
  48. #define SUNOS4
  49. #endif
  50.  
  51. #include <sys/types.h>
  52. #include <kvm.h>
  53. #include <fcntl.h>
  54. #include <arpa/inet.h>
  55.  
  56. #include <sys/socket.h>
  57. #include <net/if.h>
  58.  
  59. #include <netinet/in.h>
  60. #ifdef SUNOS4
  61. #include <netinet/in_var.h>
  62. #endif
  63. #include <netinet/if_ether.h>
  64.  
  65. #include <netdb.h>
  66.  
  67. /* Cast a struct sockaddr to a structaddr_in */
  68. #define SATOSIN(sa) ((struct sockaddr_in *)(sa))
  69.  
  70. /* Determine if "bits" is set in "flag" */
  71. #define ALLSET(flag, bits) (((flag) & (bits)) == (bits))
  72.  
  73. static struct nlist nl[] = {
  74. #define N_IFNET 0
  75.     { "_ifnet" },
  76.     0
  77. };
  78.  
  79. void kread();
  80.  
  81. static char *prog;
  82. static kvm_t *kd;
  83.  
  84. extern char *optarg;
  85. extern int optind, opterr;
  86.  
  87. main(argc, argv)
  88.     int argc;
  89.     char **argv;
  90. {
  91.     register char *cp;
  92.     register struct ifnet *ifp;
  93.     register struct arpcom *ac;
  94.     register u_char *ep;
  95.     register int op;
  96.     struct arpcom arpcom;
  97.     struct in_addr *inp;
  98.     struct hostent *hp;
  99. #ifdef SUNOS4
  100.     register struct ifaddr *ifa;
  101.     register struct in_ifaddr *in;
  102.     union {
  103.         struct ifaddr ifa;
  104.         struct in_ifaddr in;
  105.     } ifaddr;
  106. #endif
  107.     u_long addr, hostip, mask;
  108.     char name[16];
  109.     char *host;
  110.     int lflag, num;
  111.     char *usage = "usage: %s [-l] [host]\n";
  112.  
  113.     /* Determine simple program name for error messages */
  114.     if (cp = (char *)rindex(argv[0], '/'))
  115.         prog = cp + 1;
  116.     else
  117.         prog = argv[0];
  118.  
  119.     /* Parse flags */
  120.     opterr = 0;
  121.     lflag = 0;
  122.     while ((op = getopt(argc, argv, "l")) != EOF)
  123.         switch (op) {
  124.  
  125.         case 'l':
  126.             ++lflag;
  127.             break;
  128.         default:
  129.             (void)fprintf(stderr, usage, prog);
  130.             exit(1);
  131.         }
  132.  
  133.     /* Parse optional argument */
  134.     switch (argc - optind) {
  135.  
  136.     case 0:
  137.         hostip = 0;
  138.         break;
  139.  
  140.     case 1:
  141.         host = argv[optind];
  142.         hostip = inet_addr(host);
  143.         if ((long)hostip == -1) {
  144.             hp = gethostbyname(host);
  145.             if (hp == 0) {
  146.                 fprintf(stderr, "%s: bad host \"%s\"\n",
  147.                     prog, host);
  148.                 exit(1);
  149.             }
  150.             /*
  151.              * XXX The host might have more than one ip
  152.              * address. If so, we just blindly use the
  153.              * first one. Note that a modern named will
  154.              * order multiple addresses so that the first
  155.              * one is on a local interface so this isn't as
  156.              * bad as it seems.
  157.              */
  158.             bcopy(hp->h_addr, (char *)&hostip, sizeof(hostip));
  159.         }
  160.         break;
  161.  
  162.     default:
  163.         (void)fprintf(stderr, usage, prog);
  164.         exit(1);
  165.     }
  166.  
  167.     /* Open kernel memory for reading */
  168.     kd = kvm_open(0, 0, 0, O_RDONLY, prog);
  169.     if (kd == 0) {
  170.         perror("kvm_open");
  171.         exit(1);
  172.     }
  173.  
  174.     /* Fetch namelist */
  175.     if (kvm_nlist(kd, nl) != 0) {
  176.         fprintf(stderr, "%s: bad nlist\n", prog);
  177.         exit(1);
  178.     }
  179.  
  180.     ac = &arpcom;
  181.     ifp = &arpcom.ac_if;
  182.     ep = arpcom.ac_enaddr.ether_addr_octet;
  183. #ifdef SUNOS4
  184.     ifa = &ifaddr.ifa;
  185.     in = &ifaddr.in;
  186. #endif
  187.     num = 0;
  188.     kread(nl[N_IFNET].n_value, (char *)&addr, sizeof(addr), "ifnet addr");
  189.     for ( ; addr; addr = (u_long)ifp->if_next) {
  190.         kread(addr, (char *)ac, sizeof(*ac), "ifnet");
  191.         /* Only look at configured, broadcast interfaces */
  192.         if (!ALLSET(ifp->if_flags, IFF_UP | IFF_BROADCAST))
  193.             continue;
  194. #ifdef SUNOS4
  195.         /* This probably can't happen... */
  196.         if (ifp->if_addrlist == 0)
  197.             continue;
  198. #endif
  199.         /* Get interface ip address if necessary */
  200.         if (hostip || lflag) {
  201. #ifdef SUNOS4
  202.             kread((u_long)ifp->if_addrlist, (char *)&ifaddr,
  203.                 sizeof(ifaddr), "ifaddr");
  204.             inp = &SATOSIN(&ifa->ifa_addr)->sin_addr;
  205. #else
  206.             inp = &SATOSIN(&ifp->if_addr)->sin_addr;
  207. #endif
  208.             /* Check if this interface on the right subnet */
  209.             if (hostip) {
  210. #ifdef SUNOS4
  211.                 mask = in->ia_subnetmask;
  212. #else
  213.                 mask = ifp->if_subnetmask;
  214. #endif
  215.                 /* Skip if interface is not on correct subnet */
  216.                 if ((hostip & mask) != (inp->s_addr & mask))
  217.                     continue;
  218.             }
  219.         }
  220.  
  221.         /* Display local ethernet address */
  222.         printf("%x:%x:%x:%x:%x:%x",
  223.             ep[0], ep[1], ep[2], ep[3], ep[4], ep[5], ep[6]);
  224.  
  225.         /* Optionally display local ip address and interface name */
  226.         if (lflag) {
  227.             kread((u_long)ifp->if_name,
  228.                 (char *)name, sizeof(name), "name");
  229.             name[sizeof(name) - 1] = '\0';
  230.             printf("\t%s\t%s%d",
  231.                 inet_ntoa(*inp), name, ifp->if_unit);
  232.         }
  233.         putchar('\n');
  234.         num++;
  235.     }
  236.  
  237.     /* We're only supposed to display one if a host was specified */
  238.     if (hostip && num > 1) {
  239.         fprintf(stderr,
  240.             "%s: More than one interface on same subnet as %s\n",
  241.             prog, host);
  242.         exit(1);
  243.     }
  244.  
  245.     /* If we displayed any, exit normally */
  246.     if (num)
  247.         exit(0);
  248.  
  249.     /* Complain and exit with a bad status if we didn't find any */
  250.     if (hostip)
  251.         fprintf(stderr,
  252.             "%s: Can't find interface on same subnet as %s\n",
  253.             prog, host);
  254.     else
  255.         fprintf(stderr, "%s: no network interfaces found\n", prog);
  256.     exit(1);
  257.     /*NOTREACHED*/
  258. }
  259.  
  260. void
  261. kread(addr, buf, size, errmsg)
  262.     u_long addr;
  263.     char *buf;
  264.     u_int size;
  265.     char *errmsg;
  266. {
  267.     if (kvm_read(kd, addr, buf, size) != size) {
  268.         fprintf(stderr, "%s: %s read\n", prog, errmsg);
  269.         exit(1);
  270.         /*NOTREACHED*/
  271.     }
  272. }
  273.