1

I'm working on a module which has a client-server architecture. And I have to authenticate the connecting peer machine on the basis of the MAC address.

At the time of installation I store an encrypted list of valid MAC addresses.

Please note that I have no control on this peer machine and some third-party application will be running on this and I can not install any application on this peer machine.

At run time when a socket connection happens I need to know the MAC address for the IP address used in the connection, so that I can validate it against the previously stored MAC address.

Are there any C/C++ APIs available which can help me to get the MAC address from the IP address. This machine is usually to be connected in a LAN, but it can be on different subnets.

My module is multiplatform and runs on Windows, Solaris and Linux and similarly the peer machine can be running on any OS.

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
nurxb01
  • 93
  • 1
  • 2
  • 9
  • 4
    If you had spent two minutes searching for "mac address", you would have found http://stackoverflow.com/questions/1092463/getting-the-mac-address-of-the-remote-host and several others telling you the answer is that this is fundamentally impossible when the two machines are not on the same LAN. – John Saunders Jul 09 '09 at 15:35
  • My mistake, I have missed that question. Most of the time the peers are on the same subnet , but there is a possibility of different subnet. I'll go through the question mentioned. – nurxb01 Jul 09 '09 at 15:47
  • Actually, I suggest you try http://stackoverflow.com/search?q=mac%20address&tab=newest. – John Saunders Jul 09 '09 at 15:48

4 Answers4

8

Unfortunately, the simple answer is really "don't do that".

If your peer machines are on a different subnet (and therefore traffic between you and the peer is passing through a router), then there's no way to do what you want -- the MAC address of the packets you receive will be the MAC address of the router which forwarded them to you, as that's the link-layer device you're communicating with. Only the router nearest to the peer machine will know what the MAC address of the peer is -- and this information isn't passed on.

If the peer machines are on the same subnet, then the incoming packets will contain the MAC address of the peer in the Ethernet header... but this gets stripped off before the packet is delivered to your application. Your options are pretty much limited to either packet-capturing on the network interface you're listening on to get the entire packet, or using whatever tools your system provides to check the local ARP table. Both of these options are very platform-dependent!

Also, neither option is likely to continue working without modification if the interfaces you're dealing with aren't Ethernet interfaces (perhaps they're PPP links, or WiFi, or a funky virtualized interface of some sort, ...), nor will they work with IPv6.

If after all that, you're still determined, look into libpcap/WinPCap for packet capturing, which is the most portable option which comes to mind. To check the local ARP tables, Linux, OS X, Solaris and Windows all provide an arp command-line utility, but the syntax is likely to vary. If an API is available, I wouldn't expect any commonality between the platforms -- there's no standard for this sort of thing, because you really shouldn't be doing it!

Stephen Veiss
  • 1,364
  • 9
  • 10
2

This is impossible to do. There is no guarantee that your connecting peer even has a MAC address. It is entirely possible that the peer connects to the network via dial-up (PPP) or some other non-Ethernet interface.

sigjuice
  • 28,661
  • 12
  • 68
  • 93
1

Do not authenticate by MAC address. It is easy to spoof them. Use an HTTP authentication library like Chilkat.

mcandre
  • 22,868
  • 20
  • 88
  • 147
  • The peer applications are , simple tcp/ip based socket application on which i don't have any control. I can not install any of my application on this peer m/c. – nurxb01 Jul 09 '09 at 15:51
1

As mcandre mentioned, it's incredibly easy to spoof MAC addresses, but to still answer your question, I think you can do this on all OS's through BSD-style sockets if you're on the same LAN:

Here's some example code from this forum post

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <arpa/inet.h>

int main(int argc, char *argv[]) {
    struct ifreq ifr;
    int sock, j, k;
    char *p, addr[32], mask[32], mac[32];

    if (argc<2) {
        fprintf(stderr,"missing argument, example: eth0\n");
        return 1;
    }

    sock=socket(PF_INET, SOCK_STREAM, 0);
    if (-1==sock) {
        perror("socket() ");
        return 1;
    }

    strncpy(ifr.ifr_name,argv[1],sizeof(ifr.ifr_name)-1);
    ifr.ifr_name[sizeof(ifr.ifr_name)-1]='\0';

    if (-1==ioctl(sock, SIOCGIFADDR, &ifr)) {
        perror("ioctl(SIOCGIFADDR) ");
        return 1;
    }
    p=inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_addr))->sin_addr);
    strncpy(addr,p,sizeof(addr)-1);
    addr[sizeof(addr)-1]='\0';

    if (-1==ioctl(sock, SIOCGIFNETMASK, &ifr)) {
        perror("ioctl(SIOCGIFNETMASK) ");
            return 1;
        }
        p=inet_ntoa(((struct sockaddr_in *)(&ifr.ifr_netmask))->sin_addr);
        strncpy(mask,p,sizeof(mask)-1);
        mask[sizeof(mask)-1]='\0';

        if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr)) {
        perror("ioctl(SIOCGIFHWADDR) ");
        return 1;
    }
    for (j=0, k=0; j<6; j++) {
        k+=snprintf(mac+k, sizeof(mac)-k-1, j ? ":%02X" : "%02X",
            (int)(unsigned int)(unsigned char)ifr.ifr_hwaddr.sa_data[j]);
    }
    mac[sizeof(mac)-1]='\0';

    printf("\n");
    printf("name:    %s\n",ifr.ifr_name);
    printf("address: %s\n",addr);
    printf("netmask: %s\n",mask);
    printf("macaddr: %s\n",mac);
    printf("\n");

    close(sock);
    return 0;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Marc
  • 2,593
  • 2
  • 18
  • 21
  • SIOCGIFADDR gets the local interface's address, the OP was after the remote peer interface's address. – caf Jul 10 '09 at 00:25
  • oops - didn't get too look too closely at what I was copying because I was at work. Edited to remove that section since it's extraneous anyways. Thanks – Marc Jul 13 '09 at 12:34