Chinaunix

标题: linux socket 如何获取访问者IP和MAC地址? [打印本页]

作者: shineyear    时间: 2007-03-02 17:55
标题: linux socket 如何获取访问者IP和MAC地址?
做了一个LINUX下的SOCKET程序,基于TCP协议,当有别的计算机访问的时候,服务器端要怎么获得访问者的IP和MAC地址?
作者: anhk    时间: 2007-03-02 18:03
如果是应用层,IP很好获取,accept的时候就有了,MAC可以采用arp协议
作者: 柳五随风    时间: 2007-03-03 00:50
IP很容易,MAC不现实?首先从协议角度看你几乎不能得到client端点的MAC,其次即使要在应用里面传输MAC信息,也存在multi-host MAC的问题,当然如果你只是为了记录client MAC(s)信息那时可以在应用层做到的,不过这样作意义不大。如果是为了验证,那么此类方法不是一个好办法。
作者: 1984qht    时间: 2007-03-03 15:11
LINUX下获取IP地址和MAC地址
http://blog.chinaunix.net/u/27562/article_43597.html  
不知道能帮你不能
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <net/if_arp.h>
#ifdef SOLARIS
#include <sys/sockio.h>
#endif
#define MAXINTERFACES   16
main (argc, argv)
register int argc;
register char *argv[];
{
   register int fd, intrface, retn = 0;
   struct ifreq buf[MAXINTERFACES];
   struct arpreq arp;
   struct ifconf ifc;
if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) >= 0)
{
  ifc.ifc_len = sizeof buf;
  ifc.ifc_buf = (caddr_t) buf;
  if (!ioctl (fd, SIOCGIFCONF, (char *) &ifc))
  {
   //获取接口信息
   intrface = ifc.ifc_len / sizeof (struct ifreq);
    printf("interface num is intrface=%d\n\n\n",intrface);
   //根据借口信息循环获取设备IP和MAC地址
   while (intrface-- > 0)
   {
    //获取设备名称
    printf ("net device %s\n", buf[intrface].ifr_name);

    //判断网卡类型
    if (!(ioctl (fd, SIOCGIFFLAGS, (char *) &buf[intrface])))
    {
     if (buf[intrface].ifr_flags & IFF_PROMISC)
     {
      puts ("the interface is PROMISC" );
      retn++;
     }
    }
    else
    {
     char str[256];
     sprintf (str, "cpm: ioctl device %s", buf[intrface].ifr_name);
     perror (str);
    }
   //判断网卡状态
            if (buf[intrface].ifr_flags & IFF_UP)
   {
                puts("the interface status is UP" );
            }
            else
   {
                puts("the interface status is DOWN" );
            }
   //获取当前网卡的IP地址
            if (!(ioctl (fd, SIOCGIFADDR, (char *) &buf[intrface])))
            {
                 puts ("IP address is:" );
                 puts(inet_ntoa(((struct sockaddr_in*)(&buf[intrface].ifr_addr))->sin_addr));
                 puts("" );
                   //puts (buf[intrface].ifr_addr.sa_data);
            }
            else
   {
               char str[256];
               sprintf (str, "cpm: ioctl device %s", buf[intrface].ifr_name);
               perror (str);
           }
/* this section can't get Hardware Address,I don't know whether the reason is module driver*/
#ifdef SOLARIS
   //获取MAC地址
            arp.arp_pa.sa_family = AF_INET;
            arp.arp_ha.sa_family = AF_INET;
            ((struct sockaddr_in*)&arp.arp_pa)->sin_addr.s_addr=((struct sockaddr_in*)(&buf[intrface].ifr_addr))->sin_addr.s_addr;
            if (!(ioctl (fd, SIOCGARP, (char *) &arp)))
            {
                 puts ("HW address is:" );
    //以十六进制显示MAC地址
                 printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
                                (unsigned char)arp.arp_ha.sa_data[0],
                                (unsigned char)arp.arp_ha.sa_data[1],
                                (unsigned char)arp.arp_ha.sa_data[2],
                                (unsigned char)arp.arp_ha.sa_data[3],
                                (unsigned char)arp.arp_ha.sa_data[4],
                                (unsigned char)arp.arp_ha.sa_data[5]);
                 puts("" );
                 puts("" );
            }

#else
#if 0
   /*Get HW ADDRESS of the net card */
            if (!(ioctl (fd,  SIOCGENADDR, (char *) &buf[intrface])))
            {
                 puts ("HW address is:" );
                 printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
                                (unsigned char)buf[intrface].ifr_enaddr[0],
                                (unsigned char)buf[intrface].ifr_enaddr[1],
                                (unsigned char)buf[intrface].ifr_enaddr[2],
                                (unsigned char)buf[intrface].ifr_enaddr[3],
                                (unsigned char)buf[intrface].ifr_enaddr[4],
                                (unsigned char)buf[intrface].ifr_enaddr[5]);
                 puts("" );
                 puts(""  );
            }
#endif
            if (!(ioctl (fd, SIOCGIFHWADDR, (char *) &buf[intrface])))
            {
                 puts ("HW address is:" );
                 printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
                                (unsigned char)buf[intrface].ifr_hwaddr.sa_data[0],
                                (unsigned char)buf[intrface].ifr_hwaddr.sa_data[1],
                                (unsigned char)buf[intrface].ifr_hwaddr.sa_data[2],
                                (unsigned char)buf[intrface].ifr_hwaddr.sa_data[3],
                                (unsigned char)buf[intrface].ifr_hwaddr.sa_data[4],
                                (unsigned char)buf[intrface].ifr_hwaddr.sa_data[5]);
                 puts("" );
                 puts("" );
             }
#endif
            else
   {
               char str[256];
               sprintf (str, "cpm: ioctl device %s", buf[intrface].ifr_name);
               perror (str);
           }
        } //while
      } else
         perror ("cpm: ioctl" );
   } else
      perror ("cpm: socket" );
    close (fd);
    return retn;
}
编译:gcc 文件名即可

[ 本帖最后由 1984qht 于 2007-3-3 15:14 编辑 ]
作者: shineyear    时间: 2007-03-04 18:56
谢谢大家的帮助,这些信息对我很有帮助,谢谢
作者: Neil    时间: 2007-03-04 22:54
如果在一个网段,用arp可以获取到MAC,如果不在一个网段,如果客户端是windows主机,可以尝试通过NetBIOS包获取MAC地址,如果是非windows系统。。。没想到什么合适的办法,也许可以通过SNMP查询对端网关设备,不过1是有可能对端网关设备没有开放SNMP查询,2是即使开放了SNMP查询,MAC地址与IP地址对应的表也未必在标准MIB里面提供。。。伤脑筋啊
作者: tqyou85    时间: 2008-10-07 11:42
这个是个简单的
获取给定网卡的MAC地址
测试已通过

#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <linux/if_ether.h>

int main()
{
    struct ifreq ifr;
    int sock;
    unsigned char *ptr;
    int status;
    strcpy (ifr.ifr_name , "eth1");
    sock = socket (PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (sock == -1)
    {
        perror ("socket error ");
        return -1;
    }
    status = ioctl (sock, SIOCGIFHWADDR, &ifr);
    if (status < 0)
    {
        perror ("ioctl error ");
        close (sock);
        return -2;
    }
    ptr = ifr.ifr_hwaddr.sa_data;
    printf("%02x.%02x.%02x.%02x.%02x.%02x\n",
            ptr[0], ptr[1],ptr[2],ptr[3],ptr[4],ptr[5]);
}
作者: cugb_cat    时间: 2008-10-07 12:02
不在同一个局域网,获取不到mac吧?
作者: 贺兰云天    时间: 2008-10-07 14:36
我晕,都回复些什么咚咚????
楼主要的是访问者的IP和MAC,怎么发的代码都是获取本机IP和MAC的,难道是为了赚分?
还不如:

  1. system("arp | awk 'NR>1{print $1" "$3" "$5}' > result.txt");
复制代码

然后分析文件好呢
或者raw_socket抓包分析

[ 本帖最后由 贺兰云天 于 2008-10-7 14:49 编辑 ]
作者: flw    时间: 2008-10-07 14:46
这个帖子很“百度知道”!
作者: 贺兰云天    时间: 2008-10-07 14:49
原帖由 flw 于 2008-10-7 14:46 发表
这个帖子很“百度知道”!


我就是看见皇帝光屁股那个小孩

[ 本帖最后由 贺兰云天 于 2008-10-7 14:50 编辑 ]
作者: angus006    时间: 2008-10-07 15:52
原帖由 贺兰云天 于 2008-10-7 14:36 发表
我晕,都回复些什么咚咚????
楼主要的是访问者的IP和MAC,怎么发的代码都是获取本机IP和MAC的,难道是为了赚分?
还不如:

system("arp | awk 'NR>1{print $1" "$3" "$5}' > result.tx ...


你这个也只能得到LAN的信息吧。
作者: chary8088    时间: 2008-10-07 16:15
IP很容易得到的,不管TCP,还是UDP,MAC地址是在IP层获取,SOCK_RAW类型的
作者: flw    时间: 2008-10-07 17:28
原帖由 chary8088 于 2008-10-7 16:15 发表
IP很容易得到的,不管TCP,还是UDP,MAC地址是在IP层获取,SOCK_RAW类型的

你只能拿到上一跳的 MAC 地址,而上一跳的 MAC 地址未必就是源 MAC 地址,除了在同一个 LAN 之内。
作者: system888net    时间: 2008-10-07 22:16
ls 所言极是.

对于一个节点的mac而言,只对所在LAN有效,而一旦跨网段,那就是IP地址的事情了.

lz实在想要获取远程ip的mac,那么只有在客户端或客户端所在的网关里安装自己的检测mac回传软件了.
作者: 贺兰云天    时间: 2008-10-08 10:41
如果要刻意告诉IP和MAC的话,何必抓包劳神,何必考虑问题种种,在应用层数据中加个结构体,发送前写入自身的MAC和IP,这样不管多少跳,不管发送到哪里,接收者都能解析到你的IP和MAC




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2