Chinaunix首页 | 论坛 | 博客
  • 博客访问: 48749
  • 博文数量: 65
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 14
  • 用 户 组: 普通用户
  • 注册时间: 2015-11-08 16:56
文章分类
文章存档

2015年(65)

我的朋友

分类: LINUX

2015-12-01 20:46:23

原文地址:socket与网卡 作者:bachelor2004

   系统中存在两个网卡,如何根据socket号知道哪个连接(tcp)在哪个网卡上? 根据getpeername好像有点行不通。或者通过SIOCGARP?netlink?
   将问题进行分解,分为主动方式和被动方式两种。主动方式即是系统调用socket创建接口得到的socket号,被动方式即是通过类似accept得到的socket号。
   主动方式创建之后,可以利用setsockopt的SO_BINDTODEVICE。
 

socket(7)中对该套接口选项的说明如下:

SO_BINDTODEVICE

      Bind this socket to a particular device like "eth0", as specified in the passed interface name. If the name is an empty string or the option length is zero, the socket  device  binding is  removed.  The passed option is a variable-length null terminated interface name string with the maximum size  of  IFNAMSIZ. If a socket is bound to an interface, only packets received from that particular interface are processed by the socket. Note that this  only  works  for  some  socket types, particularly AF_INET sockets. It is not supported  for  packet  sockets  (use  normal bind(8) there).

 

strncpy(interface.ifr_ifrn.ifrn_name, "eth0", \
  strlen("eth0"));
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, \
  (char *)&interface, sizeof(interface)) 0) {
       perror("SO_BINDTODEVICE failed");
      /* Deal with error... */
}

 

    对被动方式的socket,如何区分?一种方法是获得MAC与socket的映射关系,进一步确定是哪个网卡对应的哪些socket。

  
一段代码:

#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;
}

阅读(962) | 评论(0) | 转发(0) |
0

上一篇:Linux bootloader 编写方法

下一篇:没有了

给主人留下些什么吧!~~