How do you determine Ethernet #?

Rob Warnock rpw3 at rigden.wpd.sgi.com
Sun Sep 30 17:37:32 AEST 1990


In article <Sep.28.12.11.34.1990.21193 at caip.rutgers.edu>
porter at caip.rutgers.edu (Adam Porter) writes:
+---------------
| Is there a way to determine the Ethernet number of a Personal Iris?
+---------------

I've posted this before, but here it is again. This doesn't depend on being
run on a PI, per se, but it does depend on SGI's particular version of "raw"
sockets. A similar thing can be written for most other machines which provide
some sort of raw socket access to the network link layer.

On machines with more than one network interface, it only shows the MAC address
of the "primary" interface, the one that was "ifconfig"d first at boot time.
(If you like, add code to set the variable "interface" from a command-line
option.)

Due to the use of "raw" sockets, it must be run as root or be setuid root.


-Rob

[p.s. MAC addresses of other nodes on the same network can be shown by first
"ping"ing the hosts and then typing "arp -a" to see the cached MAC addresses.]

-----
Rob Warnock, MS-9U/510		rpw3 at sgi.com		rpw3 at pei.com
Silicon Graphics, Inc.		(415)335-1673		Protocol Engines, Inc.
2011 N. Shoreline Blvd.
Mountain View, CA  94039-7311

============== attachment: macaddr.c ==========================
/*
 * macaddr.c - show Ethernet address of primary interface
 *
 * 900716 rpw3 at sgi.com
 */

#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/param.h>
#include <net/raw.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>

char	*ether_aton();

char	*interface;		/* change for other than default interface */
char	*my_etheraddr;		/* result */

main()
{
	static struct sockaddr_raw sr;	/* static, so "interface" lives on */
	static struct ifreq ifreq;	/* static, so "my_etheraddr" lives on */
	int s, n;

        s = socket(AF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
        if (s < 0) {
                perror("socket");
                exit(errno);
        }
	/*
	 * A raw bind() can be done without knowing the interface name,
	 * but we can't do the raw getsockname() without the bind(). So
	 * we do the bind() first, with a null interface name if needed.
	 */
        sr.sr_family = AF_RAW;
        sr.sr_port = 0;
        if (interface)
                (void) strncpy(sr.sr_ifname, interface, sizeof sr.sr_ifname);
        else
		bzero(sr.sr_ifname, sizeof sr.sr_ifname);
        if (bind(s, &sr, sizeof sr) < 0) {
                perror("bind");
                exit(errno);
        }
	/*
	 * Now get the "sockname", which for a raw socket is the interface
	 * name: "lo0", "ec0", "ipg0", or some such.
	 */
        if (interface == 0) {
                n = sizeof sr;
                if (getsockname(s, (struct sockaddr *)&sr, &n) < 0) {
                        perror("getsockname");
                        exit(errno);
                }
                interface = sr.sr_ifname;
		printf("primary interface = '%s'\n", interface);
        }

	/*
	 * Now get the "sockname", which for a raw socket is our link-level
	 * (Ethernet or FDDI or other MAC-level) address. Store a pointer to
	 * this in "my_etheraddr" for later inclusion in transmitted packets.
	 */
	ifreq.ifr_addr.sa_family = AF_RAW;
        (void) strncpy(ifreq.ifr_name, interface, sizeof ifreq.ifr_name);
	if (ioctl(s, SIOCGIFADDR, &ifreq) < 0) {
		/* XXX - use better error handler */
		perror("couldn't SIOCGIFADDR");
                exit(errno);
	}
	my_etheraddr = &ifreq.ifr_addr.sa_data[0];
	printf("MAC-level address of '%s' = %s\n",
		interface,
		ether_ntoa(my_etheraddr));

	exit(0);
}



More information about the Comp.sys.sgi mailing list