- 论坛徽章:
- 0
|
这段程序出自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;
}
拿去实验吧,很高兴与大家分享,这段代码不要钱!
|
|