Linu网络接口操作之ioctl-2_ARP条目

相关定义

  1. ARP条目相关操作的定义
/* include/linux/sockios.h *//* ARP cache control calls. */            /*  0x8950 - 0x8952  * obsolete calls, don't re-use */# define SIOCDARP    0x8953      /* delete ARP table entry   */# define SIOCGARP    0x8954      /* get ARP table entry      */# define SIOCSARP    0x8955      /* set ARP table entry      */
  1. ARP条目操作的结构与相关标志
/* include/linux/if_arp.h *//* ARP ioctl request. */struct arpreq {  struct sockaddr   arp_pa;     /* protocol address     */  struct sockaddr   arp_ha;     /* hardware address     */  int               arp_flags;  /* flags            */  struct sockaddr   arp_netmask;    /* netmask (only for proxy arps) */  char              arp_dev[16];};/* ARP Flag values. */# define ATF_COM         0x02        /* completed entry (ha valid)   */# define ATF_PERM        0x04        /* permanent entry      */# define ATF_PUBL        0x08        /* publish entry        */# define ATF_USETRAILERS 0x10        /* has requested trailers   */# define ATF_NETMASK     0x20        /* want to use a netmask (only                                       for proxy entries) */# define ATF_DONTPUB     0x40        /* don't answer this addresses  */

SIOCDARP/SIOCGARP/SIOCSARP作为ioctl(2)的第2个参数,分别用于在ARP表中删除/获取/添加单个条目

struct arpreq结构地址作为ioctl(2)的第3个参数;执行操作时,arp_pa被转换为IPv4套接字地址结构(struct sockaddr_in),表示目的端的IP地址;arp_ha为通用套接字地址结构,sa_family为AF_UNSPEC,sa_data中包含网络接口的2层地址,如以太网mac地址,表示目的端的2层地址;arp_flags用于指定ARP操作的标志;arp_netmask用于代理ARP;arp_dev用于指定本地网络接口的名称

获取ARP条目时,需要初始化arp_pa,arp_dev,然后调用ioctl(SIOCGARP),成功返回后arp_pa中包含的IP地址对应的mac地址保存在arp_ha.sa_data中;若指定的网络接口不存在,或存在但与指定的目标主机IP地址不对应,则ioctl以"(ENXIO)No such device or address"错误调用失败
无法通过ioctl操作获取整个ARP表,arp(8)命令的-a选项是通过读取系统中的/proc/net/arp文件内容实现该目的

添加ARP条目时,需要同时初始化arp_pa,arp_dev,arp_ha.sa_data以及arp_flags,然后调用ioctl(SIOCSARP)

删除ARP条目时,需要初始化arp_pa,arp_dev,然后调用ioctl(SIOCDARP),成功返回后,指定目标地址对应的ARP条目被删除;若指定的网络接口不存在,或存在但与指定的目标主机IP地址不对应,则ioctl以"(ENXIO)No such device or address"错误调用失败

示例程序

系统双网卡,名称分别为eth0与eth1
初始的ARP表内容为:

# arp -nAddress                  HWtype  HWaddress           Flags Mask            Iface192.168.56.254           ether   00:50:56:f8:57:2f   C                     eth0192.168.56.2             ether   00:50:56:f4:a3:a0   C                     eth0192.168.56.1             ether   00:50:56:c0:00:08   C                     eth0

1 . 指定本地网络接口名称与目标主机IP地址作为参数,获取对应的mac地

/* get_arp_entry_ioctl.c */# include # include # include # include # include # include # include # include # include # include static void get_arp_entry(const char *, const char *);int main(int argc, char *argv[]){    if (argc != 3) {        fprintf(stderr,        "Usage: %s [local interface name] [dst ip addres]\n", argv[0]);        exit(EXIT_FAILURE);    }    char ifname[IFNAMSIZ] = {'\0'};    strncpy(ifname, argv[1], IFNAMSIZ-1);    char ipaddr[INET_ADDRSTRLEN] = {'\0'};    strncpy(ipaddr, argv[2], INET_ADDRSTRLEN);    get_arp_entry(ifname, ipaddr);    return 0;}static void get_arp_entry(const char *dev, const char *ip){    int sfd, saved_errno, ret;    unsigned char *mac;    struct arpreq arp_req;    struct sockaddr_in *sin;    sin = (struct sockaddr_in *)&(arp_req.arp_pa);    memset(&arp_req, 0, sizeof(arp_req));    sin->sin_family = AF_INET;    inet_pton(AF_INET, ip, &(sin->sin_addr));    strncpy(arp_req.arp_dev, dev, IFNAMSIZ-1);    sfd = socket(AF_INET, SOCK_DGRAM, 0);    saved_errno = errno;    ret = ioctl(sfd, SIOCGARP, &arp_req);    if (ret # include # include # include # include # include # include # include # include # include # include static void set_arp_entry(char *, char *, char *);static int parse_mac(char *, char *);int main(int argc, char *argv[]){    if (argc != 4) {        fprintf(stderr,        "Usage: %s [local interface name] [dst ip addres] [dst mac address]\n",        argv[0]);        exit(EXIT_FAILURE);    }    char ifname[IFNAMSIZ] = {'\0'};    strncpy(ifname, argv[1], IFNAMSIZ-1);    char ipaddr[INET_ADDRSTRLEN] = {'\0'};    strncpy(ipaddr, argv[2], INET_ADDRSTRLEN);    int mac_size = strlen(argv[3]);    unsigned char *macaddr = (unsigned char *)malloc(mac_size);    memcpy(macaddr, argv[3], mac_size);    set_arp_entry(ifname, ipaddr, macaddr);    printf("Adding an arp entry done.\n");    return 0;}static void set_arp_entry(char *dev, char *ip, char *mac){    int sfd, saved_errno, ret;    struct arpreq arp_req;    struct sockaddr_in *sin;    sfd = socket(AF_INET, SOCK_DGRAM, 0);    sin = (struct sockaddr_in *)&(arp_req.arp_pa);    memset(&arp_req, 0, sizeof(arp_req));    sin->sin_family = AF_INET;    inet_pton(AF_INET, ip, &(sin->sin_addr));    strncpy(arp_req.arp_dev, dev, IFNAMSIZ-1);    parse_mac(mac, arp_req.arp_ha.sa_data);    arp_req.arp_flags = ATF_PERM | ATF_COM;    saved_errno = errno;    ret = ioctl(sfd, SIOCSARP, &arp_req);    if (ret  0xff)            return -1;        *(dst+i) = byte;        i++;    }    if (i != ETH_ALEN) {        fprintf(stderr, "Invalid mac address\n");        exit(EXIT_FAILURE);    }    return 0;}

编译并运行

# gcc set_arp_entry_ioctl.c -g3 -DC=-5 -o set_arp_entry_ioctl# # ./set_arp_entry_ioctl eth0 192.168.56.100 aa:bb:cc:dd:ee:ffAdding an arp entry done.# # ./get_arp_entry_ioctl eth0 192.168.56.100MAC: aa:bb:cc:dd:ee:ff# # arp -nAddress                  HWtype  HWaddress           Flags Mask            Iface192.168.56.1             ether   00:50:56:c0:00:08   C                     eth0192.168.56.254           ether   00:50:56:f8:57:2f   C                     eth0192.168.56.100           ether   aa:bb:cc:dd:ee:ff   CM                    eth0192.168.56.2             ether   00:50:56:f4:a3:a0   C                     eth0

3 . 指定本地网络接口名称与目标主机IP地址作为参数,删除对应的ARP条目

/* del_arp_entry_ioctl.c */# include # include # include # include # include # include # include # include # include # include static void del_arp_entry(char *, char *);int main(int argc, char *argv[]){    if (argc != 3) {        fprintf(stderr,        "Usage: %s [local interface name] [dst ip addres]\n", argv[0]);        exit(EXIT_FAILURE);    }    char ifname[IFNAMSIZ] = {'\0'};    strncpy(ifname, argv[1], IFNAMSIZ-1);    char ipaddr[INET_ADDRSTRLEN] = {'\0'};    strncpy(ipaddr, argv[2], INET_ADDRSTRLEN);    del_arp_entry(ifname, ipaddr);    printf("Deleting an arp entry done.\n");}static void del_arp_entry(char *dev, char *ip){    int sfd, saved_errno, ret;    struct arpreq arp_req;    struct sockaddr_in *sin;    sfd = socket(AF_INET, SOCK_DGRAM, 0);    sin = (struct sockaddr_in *)&(arp_req.arp_pa);    memset(&arp_req, 0, sizeof(arp_req));    sin->sin_family = AF_INET;    strncpy(arp_req.arp_dev, dev, IFNAMSIZ-1);    inet_pton(AF_INET, ip, &(sin->sin_addr));    saved_errno = errno;    ret = ioctl(sfd, SIOCDARP, &arp_req);    if (ret < 0) {        fprintf(stderr, "Delete ARP entry failed : %s\n", strerror(errno));        exit(EXIT_FAILURE);    }    errno = saved_errno;}

编译并运行

# gcc del_arp_entry_ioctl.c -g3 -DC=-5 -o del_arp_entry_ioctl# # ./del_arp_entry_ioctl eth0 192.168.56.100Deleting an arp entry done.# # ./del_arp_entry_ioctl eth0 192.168.56.200Delete ARP entry failed : No such device or address# # ./del_arp_entry_ioctl eth1 192.168.56.100Delete ARP entry failed : No such device or address# # arp -nAddress                  HWtype  HWaddress           Flags Mask            Iface192.168.56.1             ether   00:50:56:c0:00:08   C                     eth0192.168.56.254           ether   00:50:56:f8:57:2f   C                     eth0192.168.56.100                   (incomplete)                              eth0192.168.56.2             ether   00:50:56:f4:a3:a0   C                     eth0# # cat /proc/net/arp IP address       HW type     Flags       HW address            Mask     Device192.168.56.1     0x1         0x2         00:50:56:c0:00:08     *        eth0192.168.56.254   0x1         0x2         00:50:56:f8:57:2f     *        eth0192.168.56.100   0x1         0x0         aa:bb:cc:dd:ee:ff     *        eth0192.168.56.2     0x1         0x2         00:50:56:f4:a3:a0     *        eth0# # ./get_arp_entry_ioctl eth0 192.168.56.100MAC: Not in the ARP cache.

关键字:c, linux

版权声明

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部