SUMMARY: Solaris 2.2 ethernet address

From: Chris P. Ross (cross@eng.umd.edu)
Date: Fri Jul 23 1993 - 03:25:29 CDT


On Jul 12; I wrote:
> Hi. I am looking for some help. I want to be able to query the hardware
> device and get back the ethernet address. Under SunOS 4.x, I was able to
> send an ioctl() or two to /dev/nit. But, I can't figure out how to do it
> under solaris. Does anyone know how, or have a code segment, to do this?
>
> Thanks.
>
> - Chris

  Well, after a few responces, which unfortunately didn't find me an
answer, and alot of playing around with the code myself, I did figure out
how to do it.

  Big thanks go to Kevin Sheehan (kevin@uniq.com.au) who pointed me at
some things that helped me write the code. Specifically, the output of
'truss ifconfig -a'.

  Other responders:

"Andrew Luebker" <aahvdl@eye.psych.umn.edu>
peters@nms.otc.com.au (Peter Samuel)
kwak@snoopy.postech.ac.kr (Kwak Jong-Geun)
Craig Kruck <kruckc@hitachi.hitachi.com>

  Most of the responses pointed me at arp, or other commands. But, not
at C level stuff. Also, was the request to see what I ended up with, and
what I had to do it under 4.x.

  So, in response to all of that, here it is. This is a chunk of code
that will return the current physical address from the ethernet device
under SunOS 4.x, SunOS 5.x, HP/UX, Ultrix, and DEC OSF/1. (Yes, hellish
#ifdef's)

  Enjoy...

---8<--- ether_addr.c ---8<---
/*
 * ether_addr.c -- Find the current ethernet address from the hardware.
 * Copyright (c) 1993 University of Maryland
 * All Rights Reserved.
 *
 * Permission to use, copy, modify, distribute, and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation, and that the name of University of Maryland
 * not be used in advertising or publicity pertaining to distribution
 * of the software without specific, written prior permission.
 * University of Maryland makes no representations about the suitability
 * of this software for any purpose. It is provided "as is" without
 * express or implied warranty.
 *
 * UNIVERSITY OF MARYLAND DISCLAIMS ALL WARRANTIES WITH REGARD TO
 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS, IN NO EVENT SHALL UNIVERSITY OF MARYLAND BE LIABLE FOR
 * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 * OF THIS SOFTWARE.
 *
 * Author: Chris P. Ross <cross@eng.umd.edu>, Project GLUE,
 * University of Maryland
 */

#include <sys/types.h>
#ifdef hpux
# include <sys/fcntl.h>
# include <netio.h>
#else
# include <sys/socket.h>
# include <sys/ioctl.h>
# include <net/if.h>
# ifdef sun
# include <fcntl.h>
# ifndef solaris
# include <sys/time.h>
# include <net/nit_if.h>
# else
# define BUF_SIZE 30
# include <stdio.h> /* Actually using fprintf(stderr,..) */
# include <stropts.h>
# include <sys/ethernet.h>
# include <sys/dlpi.h>
# endif
# endif
#endif

short
get_ether_addr(addr, print_errors)
char addr[];
int print_errors;
{
        int i;
#ifdef hpux
        int fd;
        struct fis arg;

        if ((fd = open("/dev/lan0", O_RDONLY)) < 0) {
                if (print_errors)
                        perror("open(/dev/lan0)");
                return 0; /* Failure */
        }

        arg.reqtype = LOCAL_ADDRESS;

        if (ioctl(fd, NETSTAT, &arg) < 0) {
                if (print_errors)
                        perror("ioctl(LOCAL_ADDRESS)");
                return 0; /* Failure */
        }

        for (i = 0 ; i < 6 ; i++)
                addr[i] = arg.value.s[i];

#else /* ! hpux */
# if defined(ultrix) || defined(__osf__)
        int fd;
        struct ifdevea arg;

        if ((fd = socket(AF_DLI, SOCK_DGRAM, 0)) < 0) {
                if (print_errors)
                        perror("socket");
                return 0; /* Failure */
        }

        (void)bcopy("ln0", arg.ifr_name, 4);

        if (fd >= 0 && ioctl(fd, SIOCRPHYSADDR, &arg) < 0) {
                if (print_errors)
                        perror("ioctl(SIOCRPHYSADDR)");
                return 0; /* Failure */
        }
        
        for (i = 0 ; i < 6 ; i++)
                addr[i] = arg.current_pa[i];
# else /* ! ultrix */
# ifdef sun
        int fd;
# ifdef solaris
        int res, flag=0;
        unsigned char buf[BUF_SIZE];
        struct strbuf ctrl;
        dl_error_ack_t *err_ack;

        if ((fd = open("/dev/le", O_RDWR, 0)) < 0) {
                if (print_errors)
                        perror("open(/dev/le)");
                return 0; /* Failure */
        }
        ((ulong *)buf)[0] = DL_ATTACH_REQ; /* dl_primitive */
        ((ulong *)buf)[1] = 0; /* dl_ppa */
        ctrl.len = DL_ATTACH_REQ_SIZE;
        ctrl.buf = (void *)buf;
        if (putmsg(fd, &ctrl, NULL, 0) < 0) {
                if (print_errors)
                        perror("putmsg(DL_ATTACH_REQ)");
                return 0;
        }
        ctrl.maxlen = BUF_SIZE;
        ctrl.buf = (void *)buf;
        if (getmsg(fd, &ctrl, NULL, &flag) < 0) {
                if (print_errors)
                        perror("getmsg()");
                return 0;
        }
        if (((ulong *)buf)[0] != DL_OK_ACK) {
                if (print_errors)
                        if (((ulong *)buf)[0] == DL_ERROR_ACK) {
                                err_ack = (dl_error_ack_t *)buf;
                                fprintf(stderr, "Error: primitive 0x%02x (DLPI err code 0x%02x ; UNIX errno %ld)\n", err_ack->dl_error_primitive, err_ack->dl_errno, err_ack->dl_unix_errno);
                        } else
                                fprintf(stderr, "Unknown response primitive 0x%02x\n",
                                                ((ulong *)buf)[0]);
                return 0;
        }
        ((ulong *)buf)[0] = DL_PHYS_ADDR_REQ; /* dl_primitive */
        ((ulong *)buf)[1] = DL_CURR_PHYS_ADDR; /* dl_addr_type */
        ctrl.len = DL_PHYS_ADDR_REQ_SIZE;
        ctrl.buf = (void *)buf;
        if (putmsg(fd, &ctrl, NULL, 0) < 0) {
                if (print_errors)
                        perror("putmsg(DL_PHYS_ADDR_REQ)");
                return 0;
        }
        ctrl.maxlen = BUF_SIZE;
        ctrl.buf = (void *)buf;
        if (getmsg(fd, &ctrl, NULL, &flag) < 0) {
                if (print_errors)
                        perror("getmsg()");
                return 0;
        }
        if (((ulong *)buf)[0] != DL_PHYS_ADDR_ACK) {
                if (print_errors)
                        if (((ulong *)buf)[0] == DL_ERROR_ACK) {
                                err_ack = (dl_error_ack_t *)buf;
                                fprintf(stderr, "Error: primitive 0x%02x (DLPI err code 0x%02x ; UNIX errno %ld)\n", err_ack->dl_error_primitive, err_ack->dl_errno, err_ack->dl_unix_errno);
                        } else
                                fprintf(stderr, "Unknown response primitive 0x%02x\n",
                                                ((ulong *)buf)[0]);
                return 0;
        }
        for (i = 0 ; i < 6 ; i++)
                /* ((ulong *)buf)[2] == dl_phys_addr_ack_t->dl_addr_offset */
                addr[i] = buf[((ulong *)buf)[2] + i];
        
# else /* SunOS 4.x */
        struct ifreq ifr;

        if ((fd = open("/dev/nit", O_RDONLY, 0)) < 0) {
                if (print_errors)
                        perror("open(/dev/nit)");
                return 0; /* Failure */
        }

        (void)memcpy(ifr.ifr_name, "le0", 4);

        if (ioctl(fd, NIOCBIND, (char *)&ifr) < 0) {
                if (print_errors)
                        perror("Couldn't bind to interface");
                return 0; /* Failure */
        }

        (void)memcpy(ifr.ifr_name, "le0", 4);

        if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
                if (print_errors)
                        perror("ioctl(SIOCGIFADDR)");
                return 0; /* Failure */
        }

        for (i = 0 ; i < 6 ; i++)
                addr[i] = ifr.ifr_addr.sa_data[i];
# endif /* solaris */
# else /* ! sun */
        return 0; /* Unsupported machine */
# endif /* sun */
# endif /* ultrix */
#endif /* hpux */

        return 1; /* Success */
}



This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:08:02 CDT