免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 13405 | 回复: 7
打印 上一主题 下一主题

通过ioctl 函数的SIOCGARP 参数 获取硬件地址 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-22 19:52 |只看该作者 |倒序浏览
已知ip 通过ioctl 函数的SIOCGARP 参数 获取硬件地址 时出错  , 有人知道怎么解决吗?
出No such device or address错

CODE 大概是


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 *)&myarpreq.arp_pa;
                memcpy(sin, ifi->ifi_addr, sizeof(struct sockaddr_in));
               
                if (ioctl(sockfd, SIOCGARP, &myarpreq) < 0) {
                        err_ret("ioctl error");
                        continue;
                }
               
                ptr = &myarpreq.arp_ha.sa_data[0];
                printf("%x:%x:%x:%x:%x:%x\n", *ptr, *(ptr+1), *(ptr+2),
                                *(ptr+3), *(ptr+4), *(ptr+5));
}

get_ifi_info(AF_INET, 0)函数是过的本机的所有的ip

ioctl(sockfd, SIOCGARP, &myarpreq) 获取硬件地址 时出错  , 有人知道怎么解决吗?
出No such device or address错

论坛徽章:
0
2 [报告]
发表于 2009-08-22 20:29 |只看该作者
权限不够?还是系统不支持,看看源码吧

论坛徽章:
0
3 [报告]
发表于 2009-08-22 20:55 |只看该作者
恩  查了unp
说一些较新的系统不支持这些与ARP 相关的ioctl请求, 而是改用路由套接口执行这些ARP操作

可能是我系统不支持ioctl SIOCGARP接口吧 不知道是不是,

论坛徽章:
0
4 [报告]
发表于 2009-08-22 21:45 |只看该作者

回复 #3 tianxiaogang12 的帖子

肯定不是不支持,不然不会返回这个错误,

把myarpreq中内容打出来就知道哪错了,

论坛徽章:
0
5 [报告]
发表于 2009-08-22 22:35 |只看该作者
取mac地址吗?用过另一个不是SIOCGARP

论坛徽章:
0
6 [报告]
发表于 2014-04-26 11:14 |只看该作者
这段程序出自unix网络编程卷一,我看的是第三版第17.8节:arp高速缓存操作。
这里指的是查询我与本机互联的arp信息,即与本机互联网卡(即struct arpreq 中的arp_dev[16])的对端接口设备的信息,其中struct sockaddr arp_pa为对方ip地址,我们输入上述两项信息,从而获得对方的设备的mac地址,即struct sockaddr arp_ha;      /* hardware address */,而其他结构体成员,是用作操作路由表时用的,在本例当中用不到,请不必关心,当我们用arp命令时,我们可以看到效果:
$ arp
地址                     类型    硬件地址            标志  Mask            接口
192.168.1.1              ether   a8:15:4d:6d:8a:06   C                     eth1
192.168.1.139            ether   20:68:9d:48:ee:fe   C                     eth1
在我的手提电脑中是这样的效果,eth1为无线网卡。
以上arp命令的表现也印证了我的描述,诸如子网掩码的结构体是没有意义的,在本例当中:arp_netmask; /* netmask of protocol address */。
其中对本结构体和宏的一些解释说明由man 7 arp给出,正如许多getsockopt的宏选项由man 7 socket给出一样,大家一定要将知识掌握到这样的程度,在书本上学来的知识,一定都要迁移到linux这个系统上来,当然,我的是linux,其他系统也是同理,以后我们要参照的不是书本,而是要在系统上就能找到相关内容,我们所学习的就是驾驭这个系统的能力,而这个系统也充分为我们提供了这样良好的环境,man 7 是个很有用的东西,只会man 1 2 3,就太局限了,而man 7 是系统提供的绝大多数宏的所在,也就是说,很多东西前人都定义好了,就等着我们去用了,这就是站在巨人肩膀上的意义,我们不要为了吃一块面包就想去亲自种一个麦子,留点经历去造其他没人造过的车轮,这样生活才能大步向前,这些前人给我们留下唯一能做的就是,如果你发现BUG了,那么这是给你唯一一个再去深入研究的机会,如若不然,请向前,不要往后看,除非有这个研究的价值和工作需要。
结构体如下:
           struct arpreq {
               struct sockaddr arp_pa;      /* protocol address */
               struct sockaddr arp_ha;      /* hardware address */
               int             arp_flags;   /* flags */
               struct sockaddr arp_netmask; /* netmask of protocol address */
               char            arp_dev[16];
           };
萨家的源代码如下:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <arpa/inet.h>



int socket_func(int domain, int type, int protocol)
{
        int fd;
        if ((fd = socket(domain, type, protocol)) < 0)
        {
                fprintf(stdout, "socket failed :%s\n", strerror(errno));
                exit(EXIT_FAILURE);
        }
}
void *realloc_func(void *ptr, size_t size)
{
        void *p;
        if ((p = realloc(ptr, size)) == NULL)
        {
                fprintf(stdout, "realloc failed :%s\n", strerror(errno));
                exit(EXIT_FAILURE);
        }
        return p;
}

int ioctl_func(int fd, int request, void *argp)
{
        int ret;
        if ((ret = ioctl(fd, request, argp)) < 0)
        {
                fprintf(stdout, "ioctl failure :%s\n", strerror(errno));
                exit(EXIT_FAILURE);
        }
        return ret;
}

int main(int argc, char *argv[])
{
        /* create socket */
        int     fd;
        fd = socket_func(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

        /* successivily get interface infomation */
        struct arpreq   arpp;
        char ip[(128 / 16) * (4 + 1)];
        /* arp commond resolu query link ip :192.168.1.2 */
#if 0
        inet_pton(AF_INET, "192.168.1.2", &((struct sockaddr_in*)&arpp.arp_pa)->sin_addr);
#else
        if (argc != 3)
        {
                fprintf(stdout, "usage : ./a.out <ipaddr> <netdevice>\n");
                exit(EXIT_FAILURE);
        }
        inet_pton(AF_INET, argv[1], &((struct sockaddr_in*)&arpp.arp_pa)->sin_addr);
#endif

        bzero(arpp.arp_dev, sizeof(arpp.arp_dev));
        arpp.arp_pa.sa_family = AF_INET;
        /* ip :192.168.1.2 corresponding netdevice name */
#if 0
        bcopy("eth0", arpp.arp_dev, strlen("eth0"));
#else
        bcopy(argv[2], arpp.arp_dev, strlen(argv[2]));
#endif
        ioctl_func(fd, SIOCGARP, &arpp);
        int i;
        for (i = 0; i < 6; i++)
        {
                if (i == 0)
                        fprintf(stdout, "arp_ha:");
                fprintf(stdout, "%02x", (unsigned char)arpp.arp_ha.sa_data[i]);
                if (i == 5)
                        fprintf(stdout, "\n");
                else
                        fprintf(stdout, ":");
        }

        /* close socket*/
        close(fd);
        return 0;
}

拿去实验吧,很高兴与大家分享,这段代码不要钱!

论坛徽章:
0
7 [报告]
发表于 2014-04-26 11:17 |只看该作者
忘了说明一点,上边代码有多余没用的函数,我先前xiedeamon时留下的,大家尽可删去便是,删错了也不要紧,再复制一遍重来即可!

论坛徽章:
0
8 [报告]
发表于 2014-04-26 11:41 |只看该作者
子网掩码怎么用man 7 arp看一下吧,我刚又看了一下,没太看懂,大家研究一下吧,我的程序是能用的,只是对掩码的结构体说明不够严谨,大家尽管无视即可!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP