Hi,

I need to translate IP addresses to ethernet MAC addresses. I
initially tried something like the code from Steven's Unix Network
Programming book, volume 1 (see code #1). Looking up an IP address on
the same subnet gives ENXIO "no such device". No joy. 

Next I looked for other examples on the WWW. They were almost
identical to code #1. Reading arp(7) caused me to think that I needed
to fill in some of the other fields in struct arpreq. But I haven't
been able to find information on how to fill them in correctly. All
combinations I have tried resulted in EINVAL "invalid argument".

Finally I decided to look to see how the arp command does it. I
grabbed the source to net-tools-1.5.1 and scrutinized arp.c. Low and
behold, arp does not use SIOCGARP to query for MAC addresses. (It uses
ioctl calls to modify the arp cache however.) Instead it parses
/proc/net/arp. OK, I can mimic what arp.c does, but it seems a waste
to parse a text file rather than use SIOCGARP to obtain the
information directly. (Perhaps parsing is faster than servicing a
system call?)

Now for the plea for help: Is /proc/net/arp the way that everyone does
it on Linux? Is the SIOCGARP code broken? Or do I just not know how to
fill in the arpreq struct correctly? (If the latter, I would
appreciate someone modifying my code to show me what I am doing wrong.
A pointer to documentation would also be appreciated.) Finally, my
code will eventually end up as a module. What is the best way for a
module to look up a MAC address?

Mark

-- 
Mark K. Gardner
RADIANT Team
Network Engineering, CIC-5
Los Alamos National Laboratory
P.O. Box 1663, M.S. D451
Los Alamos, NM 87545
Email: [EMAIL PROTECTED]
Phone: 1-505-665-4953
-- 

=== Code #1 ===
#include <errno.h>
#include <stdio.h>
#include <sys/socket.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <linux/sockios.h>

static char *ethernet_mactoa(struct sockaddr *addr) {
  static char    buff[256];
  unsigned char *ptr = (unsigned char *) addr;

  sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X",
      (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
      (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377));
  return (buff);
}

int main(int argc, char *argv[]) {
  int                 s;
  struct arpreq       areq;
  struct sockaddr_in *sin;
  struct in_addr      ipaddr;

  if (argc < 2 || argc > 2) {
    fprintf(stderr, "-- Usage: %s ipaddress\n", argv[0]);
    exit(1);
  }
  
  /* Get an internet domain socket. */
  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
    perror("socket");
    exit(1);
  }

  /* Make the ARP request. */
  memset(&areq, 0, sizeof(areq));
  sin = (struct sockaddr_in *) &areq.arp_pa;
  sin->sin_family = AF_INET;
  if (inet_aton(argv[1], &ipaddr) == 0) {
    fprintf(stderr, "-- Error: invalid numbers-and-dots IP address %s.\n",
        argv[1]);
    exit(1);
  }

  if (ioctl(s, SIOCGARP, (caddr_t) &areq) == -1) {
    perror("-- Error: unable to make ARP request, error");
    exit(1);
  }

  printf("%s (%s) -> %s\n", argv[1], 
      inet_ntoa(&((struct sockaddr_in *) &areq.arp_pa)->sin_addr), 
      ethernet_mactoa(&areq.arp_ha));

  return 0;

}
=== End ===
-
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to [EMAIL PROTECTED]

Reply via email to