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

  1. /*
  2.  * Copyright (c) 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) 1992 Lawrence Berkeley Laboratory\nAll rights reserved.\n";
  24. static char rcsid[] =
  25.     "@(#) $Header: myetheraddr.c,v 1.1 92/06/16 03:30:52 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.  */
  39.  
  40. #include <sys/param.h>
  41. #include <sys/socket.h>
  42. #include <sys/ioctl.h>
  43. #include <sys/cdefs.h>
  44.  
  45. #include <net/if.h>
  46. #include <net/if_dl.h>
  47. #include <net/if_types.h>
  48.  
  49. #include <netinet/in.h>
  50.  
  51. #include <arpa/inet.h>
  52.  
  53. #include <stdio.h>
  54. #include <netdb.h>
  55. #include <stdlib.h>
  56. #include <string.h>
  57.  
  58. #define NUMINTERFACES 16
  59.  
  60. struct list {
  61.     char *name;        /* interface name */
  62.     struct in_addr *inp;    /* ip address */
  63.     u_char *ea;        /* ethernet address */
  64. } list[NUMINTERFACES];
  65.  
  66. /* Cast a struct sockaddr to a structaddr_in */
  67. #define SATOSIN(sa) ((struct sockaddr_in *)(sa))
  68.  
  69. /* Cast a struct sockaddr to a structaddr_dl */
  70. #define SATOSDL(sa) ((struct sockaddr_dl *)(sa))
  71.  
  72. static char *prog;
  73.  
  74. extern char *optarg;
  75. extern int optind, opterr;
  76.  
  77. int
  78. main(argc, argv)
  79.     int argc;
  80.     char **argv;
  81. {
  82.     register char *cp;
  83.     register struct ifreq *ifrp, *ifend;
  84.     register struct list *lp, *ep;
  85.     register u_char *ea;
  86.     register u_long mask;
  87.     register int op, fd;
  88.     register struct hostent *hp;
  89.     register char *host;
  90.     register int lflag, num;
  91.     register int n;
  92.     u_long hostip;
  93.     struct ifreq ibuf[NUMINTERFACES], ifr;
  94.     struct ifconf ifc;
  95.     char *usage = "usage: %s [-l] [host]\n";
  96.  
  97.     /* Determine simple program name for error messages */
  98.     if (cp = (char *)rindex(argv[0], '/'))
  99.         prog = cp + 1;
  100.     else
  101.         prog = argv[0];
  102.  
  103.     /* Parse flags */
  104.     opterr = 0;
  105.     lflag = 0;
  106.     while ((op = getopt(argc, argv, "l")) != EOF)
  107.         switch (op) {
  108.  
  109.         case 'l':
  110.             ++lflag;
  111.             break;
  112.         default:
  113.             (void) fprintf(stderr, usage, prog);
  114.             exit(1);
  115.         }
  116.  
  117.     /* Parse optional argument */
  118.     switch (argc - optind) {
  119.  
  120.     case 0:
  121.         hostip = 0;
  122.         break;
  123.  
  124.     case 1:
  125.         host = argv[optind];
  126.         hostip = inet_addr(host);
  127.         if ((long)hostip != -1)
  128.             break;
  129.         if ((hp = gethostbyname(host)) == 0) {
  130.             fprintf(stderr, "%s: bad host \"%s\"\n", prog, host);
  131.             exit(1);
  132.         }
  133.         /*
  134.          * XXX The host might have more than one ip address. If
  135.          * so, we just blindly use the first one. Note that a
  136.          * modern named will order multiple addresses so that
  137.          * the first one is on a local interface so this isn't
  138.          * as bad as it seems.
  139.          */
  140.         bcopy(hp->h_addr, (char *)&hostip, sizeof(hostip));
  141.         break;
  142.  
  143.     default:
  144.         (void) fprintf(stderr, usage, prog);
  145.         exit(1);
  146.     }
  147.  
  148.     /* Fetch the interface configuration */
  149.     fd = socket(AF_INET, SOCK_DGRAM, 0);
  150.     if (fd < 0) {
  151.         fprintf(stderr, "%s: ", prog);
  152.         perror("socket");
  153.         exit(1);
  154.     }
  155.     ifc.ifc_len = sizeof(ibuf);
  156.     ifc.ifc_buf = (caddr_t)ibuf;
  157.     if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
  158.         ifc.ifc_len < sizeof(struct ifreq)) {
  159.         fprintf(stderr, "%s: ", prog);
  160.         perror("SIOCGIFCONF");
  161.         exit(1);
  162.     }
  163.  
  164.     /* Spin through interface configuration list, setup internal list */
  165.     ifrp = ibuf;
  166.     ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
  167.     ep = list;
  168.     while (ifrp < ifend) {
  169.         /* Look for interface */
  170.         for (lp = list; lp < ep; ++lp)
  171.             if (strncmp(lp->name,
  172.                 ifrp->ifr_name, sizeof(ifrp->ifr_name)) == 0)
  173.                 break;
  174.         if (ep <= lp) {
  175.             /* First time we've see this one */
  176.             ep = lp + 1;
  177.             lp->name = ifrp->ifr_name;
  178.         }
  179.  
  180.         /* Fill in any relevant info we learned this time */
  181.         switch (ifrp->ifr_addr.sa_family) {
  182.  
  183.         case AF_INET:
  184.             lp->inp = &SATOSIN(&ifrp->ifr_addr)->sin_addr;
  185.             break;
  186.  
  187.         case AF_LINK:
  188.             /* We're only interested in ethernet interfaces */
  189.             if (SATOSDL(&ifrp->ifr_addr)->sdl_type == IFT_ETHER)
  190.                 lp->ea =
  191.                     (u_char *)LLADDR(SATOSDL(&ifrp->ifr_addr));
  192.             break;
  193.         }
  194.  
  195.         /* Bump interface config pointer */
  196.         n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
  197.         if (n < sizeof(*ifrp))
  198.             n = sizeof(*ifrp);
  199.         ifrp = (struct ifreq *)((char *)ifrp + n);
  200.     }
  201.  
  202.     /* Spin through internal list */
  203.     for (lp = list; lp < ep; ++lp) {
  204.         /* We need both the ip and ethernet addresses */
  205.         if (lp->inp == 0 || lp->ea == 0)
  206.             continue;
  207.  
  208.         /* Optionally check if for interface on the specified subnet */
  209.         if (hostip) {
  210.             /* Get the netmask */
  211.             bcopy(lp->name, ifr.ifr_name, sizeof(ifr.ifr_name));
  212.             if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
  213.                 fprintf(stderr, "%s: SIOCGIFNETMASK: ", prog);
  214.                 perror(lp->name);
  215.                 exit(1);
  216.             }
  217.             mask = SATOSIN(&ifr.ifr_addr)->sin_addr.s_addr;
  218.             /* Skip if interface is not on correct subnet */
  219.             if ((hostip & mask) != (lp->inp->s_addr & mask))
  220.                 continue;
  221.         }
  222.  
  223.         /* Display local ethernet address */
  224.         ea = lp->ea;
  225.         printf("%x:%x:%x:%x:%x:%x",
  226.             ea[0], ea[1], ea[2], ea[3], ea[4], ea[5], ea[6]);
  227.  
  228.         /* Optionally display local ip address and interface name */
  229.         if (lflag) {
  230.             printf("\t%s\t%.*s", inet_ntoa(*lp->inp),
  231.                 sizeof(ifrp->ifr_name), lp->name);
  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.