LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 3771|回复: 8

Linux中用C代码如何获得网关的MAC地址?

[复制链接]
发表于 2006-10-28 16:27:02 | 显示全部楼层 |阅读模式
我想获得局域网中网关的MAC地址,
如何用函数获得网关的MAC地址,
为保证可移植性,不要读取机器的配置文件,也不用网关IP作为参数。
UNIX中有操作路由的结构,可是在LINUX中我没找到。
高手指点下!
发表于 2006-10-28 16:57:14 | 显示全部楼层
cat /proc/net/arp
cat /proc/net/route 其中的Gateway,实际是个struct in_addr的类型。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-10-29 19:15:06 | 显示全部楼层
可是我该怎么读啊,我不知道文件的结构,不可能直接用啊,你看:
ouldump@BirdSky:/proc/net> cat route
Iface   Destination     Gateway         Flags   RefCnt  Use     Metric  Mask            MTU     WindowIRTT
eth0    0077000A        00000000        0001    0       0       0       00FFFFFF        0       0    0
lo      0000007F        00000000        0001    0       0       0       000000FF        0       0    0
eth0    00000000        FE77000A        0003    0       0       0       00000000        0       0    0

我该怎么去定位 ,上面的输出中只有FE77000A对我有用,可我不可能直接读它啊,全部读取倒是没问题,可那些都没用啊,我不知道偏移,也不知道它是按什么结构存的。读了也没用
再指点下吧!
回复 支持 反对

使用道具 举报

发表于 2006-10-30 10:47:09 | 显示全部楼层
网关的记录在KERNEL-ROUTE-TABLE里具有0.0.0.0的Destination IP,及mask为0.0.0.0
这样,你便可过滤了

参考一下route程序的源码,对你应会有帮助。
回复 支持 反对

使用道具 举报

发表于 2006-10-30 10:51:15 | 显示全部楼层
发重了。。。删除
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-10-31 13:40:11 | 显示全部楼层
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/ioctl.h>
#include<net/if.h>
#include<netinet/ip.h>
#include<err.h>
#include<netdb.h>
#include<fcntl.h>
#include<linux/netlink.h>
#include<linux/rtnetlink.h>
#include<net/route.h>

int main(void)
{
       


        char *buf[BUFSIZ];

        int fd;
        int n;
        struct rtmsg rtreq;
        struct sockaddr_nl nl;
        struct nlmsghdr msghdr, *msghdrp;
       
        struct sockaddr addr;
        char *c;
        struct rtentry *entryp;
        struct msghdr msg, recev;
        struct iovec iov;
        int len;
       
        fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
        if (fd < 0) {
                perror("open error");
                exit (1);
        }
        nl.nl_family = AF_NETLINK;
        nl.nl_pad = 0;
        nl.nl_pid = getpid();
        nl.nl_groups = 0;
       
        n = bind(fd, (struct sockaddr*)&nl, sizeof(nl));
        if (n < 0) {
                perror(" bind  error");
                exit (1);
        }
        memset(&nl, 0, sizeof(rtreq));
        rtreq.rtm_family = AF_INET;
        rtreq.rtm_table = RT_SCOPE_UNIVERSE;
       
        memset(&msghdr, 0, sizeof(msghdr));
        msghdr.nlmsg_len =  NLMSG_LENGTH(sizeof(struct rtmsg));
        msghdr.nlmsg_type = RTM_GETROUTE;
        msghdr.nlmsg_flags = 0;
        msghdr.nlmsg_pid = nl.nl_pid;
       

        iov.iov_base = (void*)&msghdr;
        iov.iov_len = msghdr.nlmsg_len;
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
       
        sendmsg(fd, &msg, 0);

        msghdrp = (struct nlmsghdr *)buf;
       
        iov.iov_base = (void *)buf;
        iov.iov_len = BUFSIZ;
        recev.msg_name = (void*)&msghdrp;
        recev.msg_namelen = sizeof (struct nlmsghdr);
        recev.msg_iov = &iov;
        recev.msg_iovlen = 1;

        len = recvmsg(fd, &recev, 0);
        while ((len > 0) || (msghdrp->nlmsg_type != NLMSG_DONE)) {
                entryp = NLMSG_DATA(msghdrp);
                if (entryp->rt_flags == RTF_GATEWAY)
                        break;
                NLMSG_NEXT(msghdrp, len);
        }               
        c = inet_ntop (AF_INET, entryp->rt_gateway, &addr, INET_ADDRSTRLEN);
        if (!c) {
                perror("inet_ntop failed !");
                exit (1);
        }
        printf("%s",c);

}

有人说使用AF_NETLINK,我写了这段代码,数据处理部份可能得改,因为有的成员不大明白,
可问题是我发送了请求却收不到应答,一直挂在recvmsg那里。
该怎么弄才好,
回复 支持 反对

使用道具 举报

发表于 2006-10-31 13:52:17 | 显示全部楼层
#include "../lib/unpifi.h"
#include <net/if_arp.h>
#include "../lib/error.c"
#include "../lib/wrapsock.c"
#include "../lib/sock_ntop.c"
#include "../lib/get_ifi_info.c"


int
main(int argc, char **argv)
{
        int                                     sockfd;
        struct ifi_info                 *ifi;
        unsigned char           *ptr;
        struct arpreq           arpreq;
        struct sockaddr_in      *sin;

        sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
        for (ifi = get_ifi_info(AF_INET, 0); ifi != NULL; ifi = ifi->ifi_next) {
                printf("%s: ", Sock_ntop(ifi->ifi_addr, sizeof(struct sockaddr_in)));

                sin = (struct sockaddr_in *) &arpreq.arp_pa;
                memcpy(sin, ifi->ifi_addr, sizeof(struct sockaddr_in));

                if (ioctl(sockfd, SIOCGARP, &arpreq) < 0) {
                        err_ret("ioctl SIOCGARP");
                        continue;
                }

                ptr = &arpreq.arp_ha.sa_data[0];
                printf("%x:%x:%x:%x:%x:%x\n", *ptr, *(ptr+1),
                           *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5));
        }
        exit(0);
}
引自UNIX网络编程 414页呵呵,
回复 支持 反对

使用道具 举报

发表于 2006-10-31 13:52:30 | 显示全部楼层
#include "../lib/unpifi.h"
#include <net/if_arp.h>
#include "../lib/error.c"
#include "../lib/wrapsock.c"
#include "../lib/sock_ntop.c"
#include "../lib/get_ifi_info.c"


int
main(int argc, char **argv)
{
        int                                     sockfd;
        struct ifi_info                 *ifi;
        unsigned char           *ptr;
        struct arpreq           arpreq;
        struct sockaddr_in      *sin;

        sockfd = Socket(AF_INET, SOCK_DGRAM, 0);
        for (ifi = get_ifi_info(AF_INET, 0); ifi != NULL; ifi = ifi->ifi_next) {
                printf("%s: ", Sock_ntop(ifi->ifi_addr, sizeof(struct sockaddr_in)));

                sin = (struct sockaddr_in *) &arpreq.arp_pa;
                memcpy(sin, ifi->ifi_addr, sizeof(struct sockaddr_in));

                if (ioctl(sockfd, SIOCGARP, &arpreq) < 0) {
                        err_ret("ioctl SIOCGARP");
                        continue;
                }

                ptr = &arpreq.arp_ha.sa_data[0];
                printf("%x:%x:%x:%x:%x:%x\n", *ptr, *(ptr+1),
                           *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5));
        }
        exit(0);
}
引自UNIX网络编程 414页呵呵,
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-10-31 15:29:28 | 显示全部楼层
  1. #include <features.h> /* 需要里面的 glibc 版本号 */
  2. #if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
  3. #include <netpacket/packet.h>
  4. #include <net/ethernet.h> /* 链路层(L2)协议 */
  5. #else
  6. #include <asm/types.h>
  7. #include <linux/if_packet.h>
  8. #include <linux/if_ether.h> /* 链路层协议 */
  9. #endif
  10. #include<stdio.h>
  11. #include<unistd.h>
  12. #include<stdlib.h>
  13. #include<string.h>
  14. #include<sys/socket.h>
  15. #include<netinet/in.h>
  16. #include<sys/types.h>
  17. #include<sys/ioctl.h>
  18. #include<net/if.h>
  19. #include<netinet/ip.h>
  20. #include<err.h>
  21. #include<netdb.h>
  22. #include<fcntl.h>
  23. #include<linux/netlink.h>
  24. #include<linux/rtnetlink.h>
  25. #include<net/route.h>
  26. int print_route(struct rtentry *rt);
  27. int main(void)
  28. {
  29.        
  30. /**        char buf[BUFSIZ];
  31.         int fd;
  32.         int n;
  33.         fd = open ("/proc/net/route", O_RDONLY);
  34.         if (fd < 0) {
  35.                 perror("open error");
  36.                 exit (1);
  37.         }
  38.         n = read(fd, buf , BUFSIZ-1);
  39.                
  40.         if (n < 0) {
  41.                 perror("read error");
  42.                 exit (1);
  43.         }
  44.         printf("%s",buf);
  45. **/
  46.         char *buf[BUFSIZ];
  47.         int fd;
  48.         int n;
  49.         struct rtmsg rtreq;
  50.         struct sockaddr_nl nl;
  51.         struct nlmsghdr msghdr, *msghdrp;
  52.        
  53.         struct sockaddr addr;
  54.         char *c;
  55.         struct rtentry *entryp;
  56.         struct msghdr msg, recev;
  57.         struct iovec iov;
  58.         int len;
  59.        
  60.         fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  61.         if (fd < 0) {
  62.                 perror("open error");
  63.                 exit (1);
  64.         }
  65.         nl.nl_family = AF_NETLINK;
  66.         nl.nl_pad = 0;
  67.         nl.nl_pid = getpid();
  68.         nl.nl_groups = 0;
  69.        
  70.         n = bind(fd, (struct sockaddr*)&nl, sizeof(nl));
  71.         if (n < 0) {
  72.                 perror(" bind  error");
  73.                 exit (1);
  74.         }
  75.         memset(&nl, 0, sizeof(struct rtmsg));
  76.         rtreq.rtm_family = AF_NETLINK;
  77.         rtreq.rtm_table = RT_SCOPE_UNIVERSE;
  78.        
  79.         memset(&msghdr, 0, sizeof(msghdr));
  80.         msghdr.nlmsg_len =  NLMSG_LENGTH(sizeof(struct rtmsg));
  81.         msghdr.nlmsg_type = RTM_GETROUTE;
  82.         msghdr.nlmsg_flags = NLM_F_MATCH|NLM_F_REQUEST;
  83.         msghdr.nlmsg_pid = nl.nl_pid;
  84.        
  85.         iov.iov_base = (void*)&msghdr;
  86.         iov.iov_len = msghdr.nlmsg_len;
  87.         msg.msg_iov = &iov;
  88.         msg.msg_iovlen = 1;
  89.        
  90.         len = sendmsg(fd, &msg, 0);
  91.         if (len < 0)
  92.         {
  93.                 perror("send error!");
  94.                 exit (-1);
  95.         }
  96.         else
  97.                 printf("%d bytes send!\n",len);
  98.         msghdrp = (struct nlmsghdr *)buf;
  99.        
  100.         iov.iov_base = (void *)buf;
  101.         iov.iov_len = BUFSIZ;
  102.         recev.msg_name = (void*)&msghdrp;
  103.         recev.msg_namelen = sizeof (struct nlmsghdr);
  104.         recev.msg_iov = &iov;
  105.         recev.msg_iovlen = 1;
  106.         len = recvmsg(fd, &recev, 0);
  107. //        len = recv(fd, buf, sizeof(buf)-sizeof(struct nlmsghdr),0);       
  108.         if (len < 0)
  109.                 perror("received failed!");
  110.         printf("%d bytes received!\n", len);
  111.        
  112.         for (msghdrp = (struct nlmsghdr*)buf; \
  113.                 (msghdrp->nlmsg_type != NLMSG_DONE)&& NLMSG_OK(msghdrp, len); \
  114.                          msghdrp = NLMSG_NEXT(msghdrp, len)) {
  115.                 entryp = NLMSG_DATA(msghdrp);
  116.         print_route(entryp);
  117.                
  118.         }
  119. }               
  120. int print_route(struct rtentry *rt)
  121. {
  122.         struct sockaddr addr;
  123.         char *c;
  124.         c = inet_ntop (AF_INET, &(rt->rt_dst), &addr, INET_ADDRSTRLEN);
  125.                 if (!c) {
  126.                 perror("inet_ntop failed !");
  127.                 exit (1);
  128.         }
  129.         printf("rt_dst :%s\n",c);
  130.         c = inet_ntop (AF_INET, &(rt->rt_gateway), &addr, INET_ADDRSTRLEN);
  131.                 if (!c) {
  132.                 perror("inet_ntop failed !");
  133.                 exit (1);
  134.         }
  135.         printf("rt_gateway   :%s\n",c);
  136.         c = inet_ntop (AF_INET, &(rt->rt_genmask), &addr, INET_ADDRSTRLEN);
  137.                 if (!c) {
  138.                 perror("inet_ntop failed !");
  139.                 exit (1);
  140.         }
  141.         printf("rt_genmask  :%s\n",c);
  142. }
复制代码
我上面的代码有问题,这个是我刚修改的,读是出来了,可数据和命令输出不一样。

楼上的没看清我以前的恢复,那个IOCTL在我机器上不行,总返回无效参数。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表