== Get MAC Address == Source: http://cplus.kompf.de/artikel/macaddr.html === 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 #include #include #include #include #include #include #include #include #include #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 #include #include #include #include #ifdef Linux #include #include #include #include #include #endif #ifdef HPUX #include #endif #ifdef AIX #include #include #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.