LinuxSir.cn,穿越时空的Linuxsir!

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

《UNP》卷一第三版 ARP高速缓存操作

[复制链接]
发表于 2009-5-18 21:01:04 | 显示全部楼层 |阅读模式
《UNP》卷一第三版 ARP高速缓存操作
在这一节里有一程序是为了展示读取ARP 高速缓存的SIOCGARP的ioctl的调用方法,但是例子在debian5 下不能成功运行,我把源程序贴一下:
<code>
#include                "unpifi.h"
#include                <net/if_arp.h>

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

</code>

这个程序使用了get_ifi_info()这个函数,它返回的是本机的一些接口列表。运行这个程序会出现:ioctl SIOCGAR: No such device。运行不出想要的结果,我参照别人的一个程序写的一个例子,为了给和我一样的菜鸟一些帮助,代码如下:

#include        <sys/ioctl.h>
#include        <netinet/in.h>
#include        <sys/socket.h>
#include        <net/if.h>
#include        <netinet/if_ether.h>

/* This function is need the interface name and the on the interface's ip address */

int
get_arp_entry(char *ip, char *eth_name)
{
        int                sockfd;
        struct arpreq        arpreq;
        struct sockaddr_in        *sin;
        unsigned char         *hw_addr;
        int                rc;

        sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd < 0){
                perror("socket() error\n");
                exit(1);
        }

        /* try to find an entry in arp cache for the ip address specified */

        printf("Find arp entry for IP: %s\n", ip);

        /* you must add this because some system will return "Invlid argumetn" because some argument isn't zero */
       
        memset(&arpreq, 0, sizeof(struct arpreq));

        sin = (struct sockaddr_in *) &arpreq.arp_pa;
        memset(sin, 0, sizeof(struct sockaddr_in));
        sin->sin_family = AF_INET;
        inet_pton(AF_INET, ip, &sin->sin_addr);
       
        strcpy(arpreq.arp_dev, eth_name);

        rc = ioctl(sockfd, SIOCGARP, &arpreq);

        if (rc < 0) {
                perror("Entry not available in cache...\n");
        } else {
                printf("\nentry has been successfuly retreived\n");
               
                hw_addr = (unsigned char *) arpreq.arp_ha.sa_data;

                printf("HWAddr found: %02x:%02x:%02x:%02x:%02x:%02x\n",
                        hw_addr[0], hw_addr[1], hw_addr[2], hw_addr[3], hw_addr[4], hw_addr[5]);
       
        }
        return 0;
}


int main(int argc, char ** argv)
{
        char                 *ip;
        char                 *eth_name;
        if (argc != 3){
                perror("usage:get_arp_entry <ip> <eth_name>");
                exit(1);
        }

        if (argv[1] != NULL){
                ip = malloc(sizeof(argv[1]));
                strcpy(ip, argv[1]);
        } else {
                perror("invalid argument");
                exit(1);
        }

        if (argv[2] != NULL) {
                eth_name = malloc(sizeof(argv[2]));
                strcpy(eth_name, argv[2]);
        } else {
                perror("invalid argument");
                exit(1);
        }

       
        get_arp_entry(ip, eth_name);
       
        return 0;
}

运行的时候我们不输入本机的IP 而输入在本接口 网络内的其它IP地址,例如我的网络我的IP:10.1.6.205,我的网关是:10.1.6.206, 输入的时候我输 get_arp_entry 10.1.6.206 eth0
发表于 2009-5-26 20:18:10 | 显示全部楼层
还是改用netlink接口吧,
或者直接读/proc/net/arp,
这个问题我早就遇到过了。
你可以参考下net-tools工具里的ifconfig命令的实现。
如果获取本机IP和物理地址应该不是用这个系统调用,
用SIOCGIFADDR,SIOCGIFADDR
因为本机的物理地址不存放在这里。
如果想早错arp缓存,那么你的地址应该填其他机器的地址。
可能是因为linux内核实现和其他内核不一样吧。
回复 支持 反对

使用道具 举报

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

本版积分规则

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