Linux网络操作之访问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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值