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]