socket ioctl and mac address

socket ioctl and mac address

Post by John Jo » Wed, 14 Mar 2001 02:33:16



Hi,

  When using ioctl() with SIOCGENADDR on a socket, it is giving the error
message "No such file or directory". I was trying to find the mac address
of  the network  interfaces.  I am able to  find other informations like,
IP address, netmask, mtu and stuffs like that. Only mac address is giving
error. Is there any  workaround or any other  system call to find the mac
address of an interface.

Thanks,
John.

 
 
 

socket ioctl and mac address

Post by Richard L. Hamilt » Wed, 14 Mar 2001 14:59:03


In article <3AAD085C.9525B...@lucent.com>,
        John Joy <johnko...@lucent.com> writes:

> Hi,

>   When using ioctl() with SIOCGENADDR on a socket, it is giving the error
> message "No such file or directory". I was trying to find the mac address
> of  the network  interfaces.  I am able to  find other informations like,
> IP address, netmask, mtu and stuffs like that. Only mac address is giving
> error. Is there any  workaround or any other  system call to find the mac
> address of an interface.

> Thanks,
> John.

The SIOCGENADDR ioctl seems to be unimplemented on Solaris,
unfortunately.  But obviously one can do it, since ifconfig does it.  It
takes a bunch of DLPI primitives to get the job done.  The following post
describes a way that appears to work; you may need to modify the list of
devices to reflect the interfaces you have, and the order you want to
search them in.  Or you may want to rip the whole thing apart and
parameterize it.

[I bet Sun _could_ implement SIOCGENADDR (not to mention the IFF_PROMISC
flag, at least for reading) if they really wanted to.  But very few things
actually use these, so I guess they never got around to it (both would
probably be difficult and violate normal layering conventions).]

---------------------- Begin included message ---------------------

>From: mko...@my-deja.com

Subject: answer: finding out the MAC address using DLPI
Date: 22 Oct 1999 00:00:00 GMT
Message-ID: <7upebt$l2e$1@nnrp1.deja.com>
X-Http-Proxy: 1.0 getint.quantum.de:82 (Squid/2.2.STABLE2), 1.0 x29.deja.com:80 (Squid/1.1.22) for client 149.232.160.21, 149.232.56.8
Organization: Deja.com
X-Article-Creation-Date: Fri Oct 22 10:30:20 1999 GMT
X-MyDeja-Info: XMYDJUIDmkompf
Newsgroups: comp.dcom.lans.ethernet,comp.sys.aix,comp.sys.hp.hpux,comp.unix.solaris
X-Http-User-Agent: Mozilla/4.61 [en]C-NECCK (WinNT; I)

Hi,

often people are asking how to find out the MAC- (ethernet-, hardware-,
...) address from inside a C program.
For those who are interested, I will post a portable solution that uses
the DLPI API. I compiled this example succesfull on HP-UX 10.20, AIX
4.2, and Solaris 2.6.

Hope this is usefull at this place and will help someone.

---------------- cut -------------------------

/*
 * mac_addr_dlpi.c
 *
 * Return the MAC (ie, ethernet hardware) address by using the dlpi api.
 *
 * compile with: gcc -c -D "OS" mac_addr_dlpi.c
 * with "OS" is one of AIX, SunOS, HPUX
 */

/**********************************************************************/
/* this section defines a list of the dlpi capable devices
 * this depends on the operating system
 */

#undef DLPI_DEV

#ifdef HPUX
static char *dlpi_dev[] = {"/dev/dlpi", ""};
#define DLPI_DEV
#endif

#ifdef AIX
static char *dlpi_dev[] = {"/dev/dlpi/et", "/dev/dlpi/en",
"/dev/dlpi/tr", "/dev/dlpi/fddi", ""};
#define DLPI_DEV
/* AIX: remember to set up /etc/pse.conf or /etc/dlpi.conf */
#endif

#ifdef SunOS
static char *dlpi_dev[] = {"/dev/hme", "/dev/ie", "/dev/le", ""};
#define DLPI_DEV
#endif

#ifndef DLPI_DEV
static char *dlpi_dev[] = {"/dev/dlpi", ""};
/* unknown OS - hope that this will work ??? */
#define DLPI_DEV
#endif

/**********************************************************************/
/*
 * implementation
 */

#define INSAP 22
#define OUTSAP 24

#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <sys/stropts.h>
#include <sys/poll.h>
#include <sys/dlpi.h>

#define bcopy(source, destination, length) memcpy(destination, source, length)

#define AREA_SZ 5000 /*-=-* buffer length in bytes *-=-*/
static u_long ctl_area[AREA_SZ];
static u_long dat_area[AREA_SZ];
static struct strbuf ctl = {AREA_SZ, 0, (char *)ctl_area};
static struct strbuf dat = {AREA_SZ, 0, (char *)dat_area};
#define GOT_CTRL 1
#define GOT_DATA 2
#define GOT_BOTH 3
#define GOT_INTR 4
#define GOT_ERR 128

/*-=-* get a message from a stream; return type of message *-=-*/
static int get_msg(int fd)
{
    int flags = 0;
    int res, ret;
    ctl_area[0] = 0;
    dat_area[0] = 0;
    ret = 0;
    res = getmsg(fd, &ctl, &dat, &flags);
    if(res < 0) {
        if(errno == EINTR) {
            return(GOT_INTR);
        } else {
            return(GOT_ERR);
        }
    }
    if(ctl.len > 0) {
        ret |= GOT_CTRL;
    }
    if(dat.len > 0) {
        ret |= GOT_DATA;
    }
    return(ret);

}

/*-=-* verify that dl_primitive in ctl_area = prim *-=-*/
static int check_ctrl(int prim)
{
    dl_error_ack_t *err_ack = (dl_error_ack_t *)ctl_area;
    if(err_ack->dl_primitive != prim) {
        return GOT_ERR;
    }
    return 0;

}

/*-=-* put a control message on a stream *-=-*/
static int put_ctrl(int fd, int len, int pri)
{
    ctl.len = len;
    if(putmsg(fd, &ctl, 0, pri) < 0) {
        return GOT_ERR;
    }
    return  0;

}

/*-=-* put a control + data message on a stream *-=-*/
static int put_both(int fd, int clen, int dlen, int pri)
{
    ctl.len = clen;
    dat.len = dlen;
    if(putmsg(fd, &ctl, &dat, pri) < 0) {
        return GOT_ERR;
    }
    return  0;

}

/*-=-* open file descriptor and attach *-=-*/
static int dl_open(const char *dev, int ppa, int *fd)
{
    dl_attach_req_t *attach_req = (dl_attach_req_t *)ctl_area;
    if((*fd = open(dev, O_RDWR)) == -1) {
        return GOT_ERR;
    }
    attach_req->dl_primitive = DL_ATTACH_REQ;
    attach_req->dl_ppa = ppa;
    put_ctrl(*fd, sizeof(dl_attach_req_t), 0);
    get_msg(*fd);
    return check_ctrl(DL_OK_ACK);

}

/*-=-* send DL_BIND_REQ *-=-*/
static int dl_bind(int fd, int sap, u_char *addr)
{
    dl_bind_req_t *bind_req = (dl_bind_req_t *)ctl_area;
    dl_bind_ack_t *bind_ack = (dl_bind_ack_t *)ctl_area;
    bind_req->dl_primitive = DL_BIND_REQ;
    bind_req->dl_sap = sap;
    bind_req->dl_max_conind = 1;
    bind_req->dl_service_mode = DL_CLDLS;
    bind_req->dl_conn_mgmt = 0;
    bind_req->dl_xidtest_flg = 0;
    put_ctrl(fd, sizeof(dl_bind_req_t), 0);
    get_msg(fd);
    if (GOT_ERR == check_ctrl(DL_BIND_ACK)) {
        return GOT_ERR;
    }
    bcopy((u_char *)bind_ack + bind_ack->dl_addr_offset, addr,
        bind_ack->dl_addr_length);
    return 0;

}

/**********************************************************************/
/*
 * interface:
 * function mac_addr_dlpi - get the mac address of the "first" interface
 *
 * parameter: addr: an array of six bytes, has to be allocated by the
caller
 *
 * return: 0 if OK, -1 if the address could not be determined
 *
 */

long mac_addr_dlpi ( u_char  *addr)
{
    int fd;
    int ppa;
    u_char mac_addr[25];
    int i;

    char **dev;

    for (dev = dlpi_dev; **dev != '\0'; ++dev) {
        for (ppa=0; ppa<10; ++ppa) {
            if (GOT_ERR != dl_open(*dev, ppa, &fd)) {
                if (GOT_ERR != dl_bind(fd, INSAP, mac_addr)) {
                    bcopy( mac_addr, addr, 6);
                    return 0;
                }
            }
            close(fd);
        }
    }
    return -1;

}

/**********************************************************************/
/*
 * Main (only for testing)
 */
#ifdef MAIN
int main( int argc, char **argv)
{
    long stat;
    int i;
    u_char addr[6];

    stat = mac_addr_dlpi( addr);
    if (0 == stat) {
        printf( "MAC address = ");
        for (i=0; i<6; ++i) {
            printf("%2.2x", addr[i]);
        }
        printf( "\n");
    }
    else {
        fprintf( stderr, "can't get MAC address\n");
        exit( 1);
    }
    return 0;

}

#endif

---------------- cut -------------------------

ciao

--
Martin Kompf
mko...@my-deja.com

Sent via Deja.com http://www.deja.com/
Before you buy.
---------------------- End included message ---------------------

--
ftp> get |fortune
377 I/O error: smart remark generator failed

Bogonics: the primary language inside the Beltway

mailto:rlha...@mindwarp.smart.net  http://www.smart.net/~rlhamil

 
 
 

1. MAC ADDRESS/ioctl(siocgifhwaddr)

Hi (again)!
I want to figure out the mac-address of my network-devices (ippp0,eth0).
I have already found the ioctl()-call i have to use but i have the
problem, that i dont know how to decode the given data.
the ioctl call is as follows: ioctl(filedes,siocgifhwaddr,struct ifreq*)

the ifreq struct has a member ifr_ifru (a union) an this one has a
member ifru_hwaddr of type "struct sockaddr". Now i dont know how to
get the mac-address from the sockaddr.sa_data member. I thought sockaddr
was only used to store ip-addresses...

thanx for any help

Martin

2. Apache Redirect/ReWrite for redirecting old->new domains?

3. MAC address ( ioctl )

4. How can I get the fullness of a UDP socket?

5. Getting the MAC address for a socket

6. Tools

7. Which SIO call is used to obtain the mac address associated with a socket.

8. GateD is giving me unknown error message. Please HELP!!!

9. filtering users by mac address and limiting bandwidth to each mac.

10. Binding a single IP Address to two different MAC addresses

11. Is different 'Ethenet address' from 'Mac Address' ?

12. Determining IP address from MAC address

13. MAC Address From IP Address