Get MAC Address

Method 1

/*
 * 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/eri", "/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 != '�'; ++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

Method 2

/*
 * mac_addr_sys.c
 *
 * Return the MAC (ie, ethernet hardware) address by using system specific
 * calls.
 *
 * compile with: gcc -c -D "OS" mac_addr_sys.c
 * with "OS" is one of Linux, AIX, HPUX 
 */
 
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
 
#ifdef Linux
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/if.h>
#endif
 
#ifdef HPUX
#include <netio.h>
#endif
 
#ifdef AIX
#include <sys/ndd_var.h>
#include <sys/kinfo.h>
#endif
 
long mac_addr_sys ( u_char *addr)
{
/* implementation for Linux */
#ifdef Linux
    struct ifreq ifr;
    struct ifreq *IFR;
    struct ifconf ifc;
    char buf[1024];
    int s, i;
    int ok = 0;
 
    s = socket(AF_INET, SOCK_DGRAM, 0);
    if (s==-1) {
        return -1;
    }
 
    ifc.ifc_len = sizeof(buf);
    ifc.ifc_buf = buf;
    ioctl(s, SIOCGIFCONF, &ifc);
 
    IFR = ifc.ifc_req;
    for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; IFR++) {
 
        strcpy(ifr.ifr_name, IFR->ifr_name);
        if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) {
            if (! (ifr.ifr_flags & IFF_LOOPBACK)) {
                if (ioctl(s, SIOCGIFHWADDR, &ifr) == 0) {
                    ok = 1;
                    break;
                }
            }
        }
    }
 
    close(s);
    if (ok) {
        bcopy( ifr.ifr_hwaddr.sa_data, addr, 6);
    }
    else {
        return -1;
    }
    return 0;
#endif
 
/* implementation for HP-UX */
#ifdef HPUX
 
#define LAN_DEV0 "/dev/lan0"
 
    int             fd;
    struct fis      iocnt_block;
    int             i;
    char    net_buf[sizeof(LAN_DEV0)+1];
    char    *p;
 
    (void)sprintf(net_buf, "%s", LAN_DEV0);
    p = net_buf + strlen(net_buf) - 1;
 
    /* 
     * Get 802.3 address from card by opening the driver and interrogating it.
     */
    for (i = 0; i < 10; i++, (*p)++) {
        if ((fd = open (net_buf, O_RDONLY)) != -1) {
                        iocnt_block.reqtype = LOCAL_ADDRESS;
                        ioctl (fd, NETSTAT, &iocnt_block);
                        close (fd);
 
            if (iocnt_block.vtype == 6)
                break;
        }
    }
 
    if (fd == -1 || iocnt_block.vtype != 6) {
        return -1;
    }
 
        bcopy( &iocnt_block.value.s[0], addr, 6);
        return 0;
 
#endif /* HPUX */
 
 
/* implementation for AIX */
#ifdef AIX
 
    int size;
    struct kinfo_ndd *nddp;
 
    size = getkerninfo(KINFO_NDD, 0, 0, 0);
    if (size <= 0) {
        return -1;
    }
    nddp = (struct kinfo_ndd *)malloc(size);
 
    if (!nddp) {
        return -1;
    }
    if (getkerninfo(KINFO_NDD, nddp, &size, 0) < 0) {
        free(nddp);
        return -1;
    }
    bcopy(nddp->ndd_addr, addr, 6);
    free(nddp);
    return 0;
#endif
 
/* Not implemented platforms */
        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_sys( 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

Get MAC Address for given IP Address

/*
 * Get the Hardware address of a given IP number.
 * Gracefully stolen from Diald.
 * Source: http://c.ittoolbox.com/groups/technical-functional/cpp-l/how-to-find-lan-card-port-address-thru-c-1118733#
 */
static int GetEtherHWaddr (unsigned int ipaddr, struct sockaddr *hwaddr)
{
  struct ifreq *ifr, *ifend;
  unsigned int ina, mask;
  struct ifreq ifreq;
  struct ifconf ifc;
  struct ifreq ifs[MAX_IFS];
  int SockFD;
 
  SockFD = socket(AF_INET, SOCK_DGRAM, 0);
 
  ifc.ifc_len = sizeof(ifs);
  ifc.ifc_req = ifs;
  if (ioctl(SockFD, SIOCGIFCONF, &ifc) < 0){
    printf("ioctl(SIOCGIFCONF): %m\n");
    return 0;
  }
 
  /*
   * Scan through looking for an interface with an Internet
   * address on the same subnet as `ipaddr'.
   */
  ifend = ifs + (ifc.ifc_len / sizeof(struct ifreq));
  for (ifr = ifc.ifc_req; ifr < ifend; ifr++){
    if (ifr->ifr_addr.sa_family == AF_INET){
      ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr;
      strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
 
      /*
       * Check that the interface is up, and not point-to-point
       * nor loopback.
       */
      if (ioctl(SockFD, SIOCGIFFLAGS, &ifreq) < 0)
         continue;
      if (((ifreq.ifr_flags ^ FLAGS_GOOD) & FLAGS_MASK) != 0)
         continue;
 
      /*
       * Get its netmask and check that it's on the right subnet.
       */
      if (ioctl(SockFD, SIOCGIFNETMASK, &ifreq) < 0)
        continue;
 
      mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr;
      if (((ipaddr ^ ina) & mask) != 0)
         continue;
      break;
    }
  }
  if (ifr >= ifend) return 0;
 
  /*
   * Finally get the hardware address.
   */
  memset (&ifreq.ifr_hwaddr, 0, sizeof (struct sockaddr));
  if (ioctl (SockFD, SIOCGIFHWADDR, &ifreq) < 0){
    printf("SIOCGIFHWADDR(%s): %m\n", ifreq.ifr_name);
    return 0;
  }
 
  memcpy (hwaddr, &ifreq.ifr_hwaddr, sizeof (struct sockaddr));
 
  printf("MacGate: Using Device %s, IP %s -> Ethernet %02x:%02x:%02x:%02x:%02x:%02x\n",
      ifreq.ifr_name, in_ntoa(ina),
      (int) ((unsigned char *
) &ifreq.ifr_hwaddr.sa_data)[0],
      (int) ((unsigned char *) &ifreq.ifr_hwaddr.sa_data)[1],
      (int) ((unsigned char *) &ifreq.ifr_hwaddr.sa_data)[2],
      (int) ((unsigned char *) &ifreq.ifr_hwaddr.sa_data)[3],
      (int) ((unsigned char *) &ifreq.ifr_hwaddr.sa_data)[4],
      (int) ((unsigned char *) &ifreq.ifr_hwaddr.sa_data)[5]);
  return 1;
} 

Get MAC Address using Delphi

unit ethernet_address;
 
interface
 
uses classes, sysutils;
 
const
    MAX_INTERFACE_NAME_LEN = $100;
    ERROR_SUCCESS = 0;
    MAXLEN_IFDESCR = $100;
    MAXLEN_PHYSADDR = 8;
 
    MIB_IF_OPER_STATUS_NON_OPERATIONAL = 0 ;
    MIB_IF_OPER_STATUS_UNREACHABLE = 1;
    MIB_IF_OPER_STATUS_DISCONNECTED = 2;
    MIB_IF_OPER_STATUS_CONNECTING = 3;
    MIB_IF_OPER_STATUS_CONNECTED = 4;
    MIB_IF_OPER_STATUS_OPERATIONAL = 5;
 
    MIB_IF_TYPE_OTHER = 1;
    MIB_IF_TYPE_ETHERNET = 6;
    MIB_IF_TYPE_TOKENRING = 9;
    MIB_IF_TYPE_FDDI = 15;
    MIB_IF_TYPE_PPP = 23;
    MIB_IF_TYPE_LOOPBACK = 24;
    MIB_IF_TYPE_SLIP = 28;
 
    MIB_IF_ADMIN_STATUS_UP = 1;
    MIB_IF_ADMIN_STATUS_DOWN = 2;
    MIB_IF_ADMIN_STATUS_TESTING = 3;
 
 
type
 
  MIB_IFROW = Record
    wszName : Array[0 .. (MAX_INTERFACE_NAME_LEN*2-1)] of char;
    dwIndex : LongInt;
    dwType : LongInt;
    dwMtu : LongInt;
    dwSpeed : LongInt;
    dwPhysAddrLen : LongInt;
    bPhysAddr : Array[0 .. (MAXLEN_PHYSADDR-1)] of Byte;
    dwAdminStatus : LongInt;
    dwOperStatus : LongInt;
    dwLastChange : LongInt;
    dwInOctets : LongInt;
    dwInUcastPkts : LongInt;
    dwInNUcastPkts : LongInt;
    dwInDiscards : LongInt;
    dwInErrors : LongInt;
    dwInUnknownProtos : LongInt;
    dwOutOctets : LongInt;
    dwOutUcastPkts : LongInt;
    dwOutNUcastPkts : LongInt;
    dwOutDiscards : LongInt;
    dwOutErrors : LongInt;
    dwOutQLen : LongInt;
    dwDescrLen : LongInt;
    bDescr : Array[0 .. (MAXLEN_IFDESCR - 1)] of Char;
  end;
 
  function Get_EthernetAddresses: TStringList;
 
  Function GetIfTable( pIfTable : Pointer;
    VAR pdwSize : LongInt;
    bOrder : LongInt ): LongInt; stdcall;
 
 
implementation
 
  Function GetIfTable; stdcall; external 'IPHLPAPI.DLL';
 
  function Get_EthernetAddresses: TStringList;
 
const
  _MAX_ROWS_ = 20;
 
type
  _IfTable = Record
    nRows : LongInt;
    ifRow : Array[1.._MAX_ROWS_] of MIB_IFROW;
  end;
 
VAR
  pIfTable : ^_IfTable;
  TableSize : LongInt;
  tmp : String;
  i,j : Integer;
  ErrCode : LongInt;
begin
  pIfTable := nil;
  //---------------------------------------------------------------
  Result:=TStringList.Create;
  if Assigned(Result) then
  try
  //-------------------------------------------------------
  // First: just get the buffer size.
  // TableSize returns the size needed.
  TableSize:=0; // Set to zero so the GetIfTabel function
  // won't try to fill the buffer yet,
  // but only return the actual size it needs.
  GetIfTable(pIfTable, TableSize, 1);
  if (TableSize < SizeOf(MIB_IFROW)+Sizeof(LongInt)) then begin
    Exit; // less than 1 table entry?!
  end; // if-end.
 
  // Second:
  // allocate memory for the buffer and retrieve the
  // entire table.
  GetMem(pIfTable, TableSize);
  ErrCode := GetIfTable(pIfTable, TableSize, 1);
  if ErrCode<>ERROR_SUCCESS then begin
    Exit; // OK, that did not work. 
    // Not enough memory i guess.
  end; // if-end.
 
  // Read the ETHERNET addresses.
  for i := 1 to pIfTable^.nRows do
    try
      if pIfTable^.ifRow[i].dwType=MIB_IF_TYPE_ETHERNET then begin
        tmp:='';
        for j:=0 to pIfTable^.ifRow[i].dwPhysAddrLen-1 do begin
          tmp := tmp + format('%.2x', [ pIfTable^.ifRow[i].bPhysAddr[j] ] );
        end; // for-end.
        //-------------------------------------
        if Length(tmp)>0 then Result.Add(tmp);
      end; // if-end.
    except
      Exit;
    end; // if-try-except-end.
  finally
    if Assigned(pIfTable) then FreeMem(pIfTable,TableSize);
  end; // if-try-finally-end.
end;
 
end.