Print this page
    
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/cmd-inet/usr.sbin/arp.c
          +++ new/usr/src/cmd/cmd-inet/usr.sbin/arp.c
   1    1  /*
   2    2   * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
   3    3   * Use is subject to license terms.
   4    4   */
   5    5  /*
   6    6   * Copyright (c) 1984 Regents of the University of California.
   7    7   * All rights reserved.
   8    8   *
   9    9   * This code is derived from software contributed to Berkeley by
  10   10   * Sun Microsystems, Inc.
  11   11   *
  12   12   * Redistribution and use in source and binary forms, with or without
  13   13   * modification, are permitted provided that the following conditions
  14   14   * are met:
  15   15   * 1. Redistributions of source code must retain the above copyright
  16   16   *    notice, this list of conditions and the following disclaimer.
  17   17   * 2. Redistributions in binary form must reproduce the above copyright
  18   18   *    notice, this list of conditions and the following disclaimer in the
  19   19   *    documentation and/or other materials provided with the distribution.
  20   20   * 3. All advertising materials mentioning features or use of this software
  21   21   *    must display the following acknowledgement:
  22   22   *      This product includes software developed by the University of
  23   23   *      California, Berkeley and its contributors.
  24   24   * 4. Neither the name of the University nor the names of its contributors
  25   25   *    may be used to endorse or promote products derived from this software
  26   26   *    without specific prior written permission.
  27   27   *
  28   28   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  29   29   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30   30   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31   31   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  32   32   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33   33   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34   34   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35   35   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36   36   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  37   37   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  38   38   * SUCH DAMAGE.
  39   39   */
  40   40  
  41   41  
  42   42  /*
  43   43   * arp - display, set, and delete arp table entries
  44   44   */
  45   45  
  46   46  #include <stdio.h>
  47   47  #include <sys/types.h>
  48   48  #include <sys/socket.h>
  49   49  #include <netinet/in.h>
  50   50  #include <sys/ioctl.h>
  51   51  #include <errno.h>
  52   52  #include <netdb.h>
  53   53  #include <net/if.h>
  54   54  #include <net/if_arp.h>
  55   55  #include <stdlib.h>
  56   56  #include <unistd.h>
  57   57  #include <string.h>
  58   58  #include <arpa/inet.h>
  59   59  #include <net/if_types.h>
  60   60  #include <net/if_dl.h>
  61   61  #include <zone.h>
  62   62  
  63   63  static int file(char *);
  64   64  static int set(int, char *[]);
  65   65  static void get(char *);
  66   66  static void delete(char *);
  67   67  static void usage(void);
  68   68  
  69   69  int
  70   70  main(int argc, char *argv[])
  71   71  {
  72   72          int c, nflags = 0, argsleft;
  73   73          int n_flag, a_flag, d_flag, f_flag, s_flag;
  74   74  
  75   75          n_flag = a_flag = d_flag = f_flag = s_flag = 0;
  76   76  
  77   77  #define CASE(x, y)                              \
  78   78                  case x:                         \
  79   79                          if (nflags > 0) {       \
  80   80                                  usage();        \
  81   81                                  exit(1);        \
  82   82                          } else                  \
  83   83                                  y##_flag = 1;   \
  84   84                                  nflags++;       \
  85   85                          break
  86   86  
  87   87          while ((c = getopt(argc, argv, "nadfs")) != EOF) {
  88   88                  switch (c) {
  89   89                  case '?':
  90   90                          usage();
  91   91                          exit(1);
  92   92                          /* NOTREACHED */
  93   93                          break;
  94   94                  case 'n':
  95   95                          n_flag = 1;
  96   96                          break;
  97   97                  CASE('a', a);
  98   98                  CASE('d', d);
  99   99                  CASE('f', f);
 100  100                  CASE('s', s);
 101  101                  }
 102  102          }
 103  103  
 104  104  #undef CASE
 105  105  
 106  106          /*
 107  107           * -n only allowed with -a
 108  108           */
 109  109          if (n_flag && !a_flag) {
 110  110                  usage();
 111  111                  exit(1);
 112  112          }
 113  113  
 114  114          argsleft = argc - optind;
 115  115  
 116  116          if (a_flag && (argsleft == 0)) {
 117  117                  /*
 118  118                   * the easiest way to get the complete arp table
  
    | 
      ↓ open down ↓ | 
    118 lines elided | 
    
      ↑ open up ↑ | 
  
 119  119                   * is to let netstat, which prints it as part of
 120  120                   * the MIB statistics, do it.
 121  121                   */
 122  122                  char netstat_path[MAXPATHLEN];
 123  123                  const char *zroot = zone_get_nroot();
 124  124                  (void) snprintf(netstat_path, sizeof (netstat_path), "%s%s", zroot != NULL ?
 125  125                      zroot : "", "/usr/bin/netstat");
 126  126                  (void) execl(netstat_path, "netstat",
 127  127                      (n_flag ? "-np" : "-p"),
 128  128                      "-f", "inet", (char *)0);
 129      -                (void) fprintf(stderr, "failed to exec netstat: %s\n",
 130      -                    strerror(errno));
      129 +                (void) fprintf(stderr, "failed to exec %s: %s\n",
      130 +                    netstat_path, strerror(errno));
 131  131                  exit(1);
 132  132  
 133  133          } else if (s_flag && (argsleft >= 2)) {
 134  134                  if (set(argsleft, &argv[optind]) != 0)
 135  135                          exit(1);
 136  136  
 137  137          } else if (d_flag && (argsleft == 1)) {
 138  138                  delete(argv[optind]);
 139  139  
 140  140          } else if (f_flag && (argsleft == 1)) {
 141  141                  if (file(argv[optind]) != 0)
 142  142                          exit(1);
 143  143  
 144  144          } else if ((nflags == 0) && (argsleft == 1)) {
 145  145                  get(argv[optind]);
 146  146  
 147  147          } else {
 148  148                  usage();
 149  149                  exit(1);
 150  150          }
 151  151          return (0);
 152  152  }
 153  153  
 154  154  /*
 155  155   * Process a file to set standard arp entries
 156  156   */
 157  157  static int
 158  158  file(char *name)
 159  159  {
 160  160          /*
 161  161           * A line of input can be:
 162  162           * <hostname> <macaddr> ["temp"] ["pub"] ["trail"] ["permanent"]
 163  163           */
 164  164  #define MAX_LINE_LEN    (MAXHOSTNAMELEN + \
 165  165          sizeof (" xx:xx:xx:xx:xx:xx temp pub trail permanent\n"))
 166  166  #define MIN_ARGS        2
 167  167  #define MAX_ARGS        5
 168  168  
 169  169          FILE *fp;
 170  170          char line[MAX_LINE_LEN];
 171  171          int retval;
 172  172  
 173  173          if ((fp = fopen(name, "r")) == NULL) {
 174  174                  (void) fprintf(stderr, "arp: cannot open %s\n", name);
 175  175                  exit(1);
 176  176          }
 177  177  
 178  178          retval = 0;
 179  179          while (fgets(line, MAX_LINE_LEN, fp) != NULL) {
 180  180                  char line_copy[MAX_LINE_LEN];
 181  181                  char *args[MAX_ARGS];
 182  182                  char *start;
 183  183                  int i;
 184  184  
 185  185                  /*
 186  186                   * Keep a copy of the un-altered line for error
 187  187                   * reporting.
 188  188                   */
 189  189                  (void) strlcpy(line_copy, line, MAX_LINE_LEN);
 190  190  
 191  191                  start = line_copy;
 192  192                  for (i = 0; i < MAX_ARGS; i++) {
 193  193                          if ((args[i] = strtok(start, " \t\n")) == NULL)
 194  194                                  break;
 195  195  
 196  196                          start = NULL;
 197  197                  }
 198  198  
 199  199                  if (i < MIN_ARGS) {
 200  200                          (void) fprintf(stderr, "arp: bad line: %s\n",
 201  201                              line);
 202  202                          retval = 1;
 203  203                          continue;
 204  204                  }
 205  205  
 206  206                  if (set(i, args) != 0)
 207  207                          retval = 1;
 208  208          }
 209  209  
 210  210  #undef  MAX_LINE_LEN
 211  211  #undef  MIN_ARGS
 212  212  #undef  MAX_ARGS
 213  213  
 214  214          (void) fclose(fp);
 215  215          return (retval);
 216  216  }
 217  217  
 218  218  /*
 219  219   * Set an individual arp entry
 220  220   */
 221  221  static int
 222  222  set(int argc, char *argv[])
 223  223  {
 224  224          struct xarpreq ar;
 225  225          struct hostent *hp;
 226  226          struct sockaddr_in *sin;
 227  227          uchar_t *ea;
 228  228          int s;
 229  229          char *host = argv[0], *eaddr = argv[1];
 230  230  
 231  231          argc -= 2;
 232  232          argv += 2;
 233  233          (void) memset(&ar, 0, sizeof (ar));
 234  234          sin = (struct sockaddr_in *)&ar.xarp_pa;
 235  235          sin->sin_family = AF_INET;
 236  236          sin->sin_addr.s_addr = inet_addr(host);
 237  237          if (sin->sin_addr.s_addr == (in_addr_t)-1) {
 238  238                  hp = gethostbyname(host);
 239  239                  if (hp == NULL) {
 240  240                          (void) fprintf(stderr, "arp: %s: unknown host\n",
 241  241                              host);
 242  242                          return (1);
 243  243                  }
 244  244                  (void) memcpy(&sin->sin_addr, hp->h_addr,
 245  245                      sizeof (sin->sin_addr));
 246  246          }
 247  247          ea = _link_aton(eaddr, &s);
 248  248          if (ea == NULL) {
 249  249                  if (s == -1) {
 250  250                          (void) fprintf(stderr,
 251  251                              "arp: invalid link layer address '%s'\n", eaddr);
 252  252                          return (1);
 253  253                  }
 254  254                  perror("arp: nomem");
 255  255                  exit(1);
 256  256          }
 257  257          ar.xarp_ha.sdl_alen = s;
 258  258          (void) memcpy(LLADDR(&ar.xarp_ha), ea, ar.xarp_ha.sdl_alen);
 259  259          free(ea);
 260  260          ar.xarp_ha.sdl_family = AF_LINK;
 261  261          ar.xarp_flags = ATF_PERM;
 262  262          while (argc-- > 0) {
 263  263                  if (strncmp(argv[0], "temp", 4) == 0) {
 264  264                          ar.xarp_flags &= ~ATF_PERM;
 265  265                  } else if (strncmp(argv[0], "pub", 3) == 0) {
 266  266                          ar.xarp_flags |= ATF_PUBL;
 267  267                  } else if (strncmp(argv[0], "trail", 5) == 0) {
 268  268                          ar.xarp_flags |= ATF_USETRAILERS;
 269  269                  } else if (strcmp(argv[0], "permanent") == 0) {
 270  270                          ar.xarp_flags |= ATF_AUTHORITY;
 271  271                  } else {
 272  272                          (void) fprintf(stderr,
 273  273                              "arp: unknown keyword '%s'\n", argv[0]);
 274  274                          return (1);
 275  275                  }
 276  276                  argv++;
 277  277          }
 278  278  
 279  279          if ((ar.xarp_flags & (ATF_PERM|ATF_AUTHORITY)) == ATF_AUTHORITY) {
 280  280                  (void) fprintf(stderr, "arp: 'temp' and 'permanent' flags are "
 281  281                      "not usable together.\n");
 282  282                  return (1);
 283  283          }
 284  284  
 285  285          s = socket(AF_INET, SOCK_DGRAM, 0);
 286  286          if (s < 0) {
 287  287                  perror("arp: socket");
 288  288                  exit(1);
 289  289          }
 290  290          if (ioctl(s, SIOCSXARP, (caddr_t)&ar) < 0) {
 291  291                  perror(host);
 292  292                  exit(1);
 293  293          }
 294  294          (void) close(s);
 295  295          return (0);
 296  296  }
 297  297  
 298  298  /*
 299  299   * Display an individual arp entry
 300  300   */
 301  301  static void
 302  302  get(char *host)
 303  303  {
 304  304          struct xarpreq ar;
 305  305          struct hostent *hp;
 306  306          struct sockaddr_in *sin;
 307  307          uchar_t *ea;
 308  308          int s;
 309  309          char *str = NULL;
 310  310  
 311  311          (void) memset(&ar, 0, sizeof (ar));
 312  312          sin = (struct sockaddr_in *)&ar.xarp_pa;
 313  313          sin->sin_family = AF_INET;
 314  314          sin->sin_addr.s_addr = inet_addr(host);
 315  315          if (sin->sin_addr.s_addr == (in_addr_t)-1) {
 316  316                  hp = gethostbyname(host);
 317  317                  if (hp == NULL) {
 318  318                          (void) fprintf(stderr, "arp: %s: unknown host\n",
 319  319                              host);
 320  320                          exit(1);
 321  321                  }
 322  322                  (void) memcpy(&sin->sin_addr, hp->h_addr,
 323  323                      sizeof (sin->sin_addr));
 324  324          }
 325  325          s = socket(AF_INET, SOCK_DGRAM, 0);
 326  326          if (s < 0) {
 327  327                  perror("arp: socket");
 328  328                  exit(1);
 329  329          }
 330  330          ar.xarp_ha.sdl_family = AF_LINK;
 331  331          if (ioctl(s, SIOCGXARP, (caddr_t)&ar) < 0) {
 332  332                  if (errno == ENXIO)
 333  333                          (void) printf("%s (%s) -- no entry\n",
 334  334                              host, inet_ntoa(sin->sin_addr));
 335  335                  else
 336  336                          perror("SIOCGXARP");
 337  337                  exit(1);
 338  338          }
 339  339          (void) close(s);
 340  340          ea = (uchar_t *)LLADDR(&ar.xarp_ha);
 341  341          if (ar.xarp_flags & ATF_COM) {
 342  342                  str = _link_ntoa(ea, str, ar.xarp_ha.sdl_alen, IFT_OTHER);
 343  343                  if (str != NULL) {
 344  344                          (void) printf("%s (%s) at %s", host,
 345  345                              inet_ntoa(sin->sin_addr), str);
 346  346                          free(str);
 347  347                  } else {
 348  348                          perror("arp: nomem");
 349  349                          exit(1);
 350  350                  }
 351  351          } else {
 352  352                  (void) printf("%s (%s) at (incomplete)", host,
 353  353                      inet_ntoa(sin->sin_addr));
 354  354          }
 355  355          if (!(ar.xarp_flags & ATF_PERM))
 356  356                  (void) printf(" temp");
 357  357          if (ar.xarp_flags & ATF_PUBL)
 358  358                  (void) printf(" pub");
 359  359          if (ar.xarp_flags & ATF_USETRAILERS)
 360  360                  (void) printf(" trail");
 361  361          if (ar.xarp_flags & ATF_AUTHORITY)
 362  362                  (void) printf(" permanent");
 363  363          (void) printf("\n");
 364  364  }
 365  365  
 366  366  /*
 367  367   * Delete an arp entry
 368  368   */
 369  369  static void
 370  370  delete(char *host)
 371  371  {
 372  372          struct xarpreq ar;
 373  373          struct hostent *hp;
 374  374          struct sockaddr_in *sin;
 375  375          int s;
 376  376  
 377  377          (void) memset(&ar, 0, sizeof (ar));
 378  378          sin = (struct sockaddr_in *)&ar.xarp_pa;
 379  379          sin->sin_family = AF_INET;
 380  380          sin->sin_addr.s_addr = inet_addr(host);
 381  381          if (sin->sin_addr.s_addr == (in_addr_t)-1) {
 382  382                  hp = gethostbyname(host);
 383  383                  if (hp == NULL) {
 384  384                          (void) fprintf(stderr, "arp: %s: unknown host\n",
 385  385                              host);
 386  386                          exit(1);
 387  387                  }
 388  388                  (void) memcpy(&sin->sin_addr, hp->h_addr,
 389  389                      sizeof (sin->sin_addr));
 390  390          }
 391  391          s = socket(AF_INET, SOCK_DGRAM, 0);
 392  392          if (s < 0) {
 393  393                  perror("arp: socket");
 394  394                  exit(1);
 395  395          }
 396  396          ar.xarp_ha.sdl_family = AF_LINK;
 397  397          if (ioctl(s, SIOCDXARP, (caddr_t)&ar) < 0) {
 398  398                  if (errno == ENXIO)
 399  399                          (void) printf("%s (%s) -- no entry\n",
 400  400                              host, inet_ntoa(sin->sin_addr));
 401  401                  else
 402  402                          perror("SIOCDXARP");
 403  403                  exit(1);
 404  404          }
 405  405          (void) close(s);
 406  406          (void) printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
 407  407  }
 408  408  
 409  409  static void
 410  410  usage(void)
 411  411  {
 412  412          (void) printf("Usage: arp hostname\n");
 413  413          (void) printf("       arp -a [-n]\n");
 414  414          (void) printf("       arp -d hostname\n");
 415  415          (void) printf("       arp -s hostname ether_addr "
 416  416              "[temp] [pub] [trail] [permanent]\n");
 417  417          (void) printf("       arp -f filename\n");
 418  418  }
  
    | 
      ↓ open down ↓ | 
    278 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX