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