Re: programming on ethernet level

Hans-Peter Jansen (hpj.lisa@t-online.de)
Wed, 16 Dec 1998 18:18:15 +0100


Bruno Randolf wrote:
>
> hi there!
>
> can anybody here tell me how can i send and receive ethernet packets
> directly on layer 2 under linux?
[snip]
> any other suggsetions?
> help would be greatly appreciated!
>
> Br1

This was my problem some time ago, too. As suggested, I started with
pcap, but it doesn't helped too much. After fiddleing an evening with
this stuff, here is, what I found out:

open a socket:

fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
if (fd < 0) {
sprintf(ebuf, "socket: %s", strerror(errno));
goto failed;
}

/* check device type */
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0 ) {
sprintf(ebuf, "SIOCGIFHWADDR: %s", strerror(errno));
goto failed;
}

if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
sprintf(ebuf, "unsupported physical layer type 0x%x (ethernet
only)",
ifr.ifr_hwaddr.sa_family);
goto failed;
}

memcpy(ethaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);

if you need promisc mode, don't forget to restore device flags.

ifr.ifr_flags |= IFF_PROMISC;
if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0 ) {
sprintf(ebuf, "SIOCSIFFLAGS: %s", strerror(errno));
goto failed;
}
atexit(restore_ifr);

/****/

void restore_ifr(void)
{
int fd;

fd = socket(PF_INET, SOCK_PACKET, htons(0x0003));
if (fd < 0)
fprintf(stderr, "linux socket: %s", strerror(errno));
else if (ioctl(fd, SIOCSIFFLAGS, &saved_ifr) < 0)
fprintf(stderr, "linux SIOCSIFFLAGS: %s", strerror(errno));
}

So much for initialisation.

To receive/send stuff, use recvmsg/sendmsg, so no need/use of
bind, but you need to understand the concepts of the structs:
msghdr, ethhdr, iovec, and sockaddr_pkt to build/decode packages.

Take this as example code, and it may be inconsistent. But I think,
it's worth to get the concepts, without the need to look
into the kernel code (what I have done, though).

Hope this helps.

Cheers,
Hans-Peter

-
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to majordomo@vger.rutgers.edu