linux接受局域网的ip包,Linux网络编程问题:如何获取局域网内某个IP所对应的网卡的 MAC (物理地址)?谢谢。...

如何获取局域网内某个IP所对应的网卡的 MAC (物理地址)?

我现在只会获取本机网卡的MAC地址。调用ioctl()函数。

在windows 98/NT,可以调用SendARP()来获取LAN的计算机的MAC。

那linux里,如何做呢?请帮助,谢谢!

|

PF_PACKET是用来处理原始报文协议的

这里有一个很久以前的代码,你看看能不能用

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

/* 得到本机的mac地址和ip地址 */

int GetLocalMac(const char *device,char *mac,char *ip)

{

int sockfd;

struct ifreq req;

struct sockaddr_in * sin;

if((sockfd = socket(PF_INET,SOCK_DGRAM,0))==-1)

{

fprintf(stderr,"Sock Error:%sna",strerror(errno));

return(-1);

}

memset(&req,0,sizeof(req));

strcpy(req.ifr_name,device);

if(ioctl(sockfd,SIOCGIFHWADDR,(char *)&req)==-1)

{

fprintf(stderr,"ioctl SIOCGIFHWADDR:%sna",strerror(errno));

close(sockfd);

return(-1);

}

memcpy(mac,req.ifr_hwaddr.sa_data,6);

req.ifr_addr.sa_family = PF_INET;

if(ioctl(sockfd,SIOCGIFADDR,(char *)&req)==-1)

{

fprintf(stderr,"ioctl SIOCGIFADDR:%sna",strerror(errno));

close(sockfd);

return(-1);

}

sin = (struct sockaddr_in *)&req.ifr_addr;

memcpy(ip,(char *)&sin->sin_addr,4);

return(0);

}

char *mac_ntoa(const unsigned char *mac)

{

/* Linux 下有 ether_ntoa(),不过我们重新写一个也很简单 */

static char buffer[18];

memset(buffer,0,sizeof(buffer));

sprintf(buffer,"%02X:%02X:%02X:%02X:%02X:%02X",

mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);

return(buffer);

}

/*根据 RFC 0826 修改*/

typedefstruct _Ether_pkgEther_pkg;

struct _Ether_pkg {

/* 前面是ethernet头 */

unsigned char  ether_dhost[6];/* 目地硬件地址*/

unsigned char  ether_shost[6];/* 源硬件地址*/

unsigned short int ether_type;    /* 网络类型*/

/* 下面是arp协议    */

unsigned short int ar_hrd;/* 硬件地址格式 */

unsigned short int ar_pro;/* 协议地址格式 */

unsigned char  ar_hln;/* 硬件地址长度(字节) */

unsigned char  ar_pln;/* 协议地址长度(字节) */

unsigned short int ar_op;/* 操作代码*/

unsigned char  arp_sha[6];/* 源硬件地址 */

unsigned char  arp_spa[4];/* 源协议地址*/

unsigned char  arp_tha[6];/* 目地硬件地址 */

unsigned char  arp_tpa[4];/* 目地协议地址 */

};

void parse_ether_package(const Ether_pkg *pkg)

{

printf("目地mac地址:[%s]n",mac_ntoa(pkg->ether_dhost));

printf("源  mac地址:[%s]n",mac_ntoa(pkg->ether_shost));

switch (ntohs(pkg->ether_type))

{

case  ETHERTYPE_ARP:

printf("IP->MAC解析n");

break;

case  ETHERTYPE_REVARP:

printf("MAC->IP解析n");

break;

default:

printf("解析未处理 =[%d]n",ntohs(pkg->ether_type));

break;

}

switch (ntohs(pkg->ar_hrd))

{

case ARPHRD_ETHER:

printf("以太网地址n");

break;

default:

printf("网络地址类型未解析 =[%d]n",ntohs(pkg->ar_hrd));

break;

}

switch (ntohs(pkg->ar_pro))

{

case ETHERTYPE_IP:

printf("IP地址n");

break;

default:

printf("其它地址未解析 =[%d]n",ntohs(pkg->ar_pro));

break;

}

printf("硬件地址长度=[%d]n",pkg->ar_hln);

printf("协议地址长度=[%d]n",pkg->ar_pln);

switch (ntohs(pkg->ar_op))

{

case ARPOP_REQUEST:

printf("IP->MAC地址解析请求n");

break;

case ARPOP_REPLY:

printf("IP->MAC地址解析应答n");

break;

default:

printf("其它类型的包文 =[%d]n",ntohs(pkg->ar_op));

}

printf("源  MAC地址 =[%s]n",mac_ntoa(pkg->arp_sha));

printf("源   IP地址 =[%s]n",inet_ntoa(*(struct in_addr *)pkg->arp_spa));

printf("目地MAC地址 =[%s]n",mac_ntoa(pkg->arp_tha));

printf("目地 IP地址 =[%s]n",inet_ntoa(*(struct in_addr *)pkg->arp_tpa));

}

int main(int argc,char **argv)

{

Ether_pkgpkg,*parse;

charbuffer[255];

unsigned charmac[7];

unsigned charip[5];

struct  hostent *host =NULL;

intsockfd,len;

struct  sockaddr sa;

unsigned charbroad_mac[7]={0xff,0xff,0xff,0xff,0xff,0xff,0x00};

memset(mac,0,sizeof(mac));

memset(ip,0,sizeof(ip));

if(GetLocalMac("eth0",mac,ip)==-1)

return(-1);

printf("本地 Mac=[%s] Ip=[%s]n",

mac_ntoa(mac),inet_ntoa(*(struct in_addr *)ip));

if(argc==1)return(-1);

memset((char *)&pkg,'',sizeof(pkg));

/*  填充ethernet包文 */

memcpy((char *)pkg.ether_shost,(char *)mac,6);

memcpy((char *)pkg.ether_dhost,(char *)broad_mac,6);

pkg.ether_type = htons(ETHERTYPE_ARP);

/*  下面填充arp包文 */

pkg.ar_hrd = htons(ARPHRD_ETHER);

pkg.ar_pro = htons(ETHERTYPE_IP);

pkg.ar_hln = 6;

pkg.ar_pln = 4;

pkg.ar_op  = htons(ARPOP_REQUEST);

memcpy((char *)pkg.arp_sha,(char *)mac,6);

memcpy((char *)pkg.arp_spa,(char *)ip,4);

memcpy((char *)pkg.arp_tha,(char *)broad_mac,6);

printf("Resolve [%s],Please Waiting...",argv[1]);

fflush(stdout);

memset(ip,0,sizeof(ip));

if(inet_aton(argv[1],(struct in_addr *)ip)==0)

{

if((host = gethostbyname(argv[1]))==NULL)

{

fprintf(stderr,"Fail! %sna",hstrerror(h_errno));

return(-1);

}

memcpy((char *)ip,host->h_addr,4);

}

printf(" Done!n");

memcpy((char *)pkg.arp_tpa,(char *)ip,4);

/* 实际应该使用PF_PACKET */

if((sockfd = socket(PF_INET,SOCK_PACKET,htons(ETH_P_ALL)))==-1)

{

fprintf(stderr,"Socket Error:%sna",strerror(errno));

return(0);

}

memset(&sa,'',sizeof(sa));

strcpy(sa.sa_data,"eth0");

len = sendto(sockfd,&pkg,sizeof(pkg),0,&sa,sizeof(sa));

if(len != sizeof(pkg))

{

fprintf(stderr,"Sendto Error:%sna",strerror(errno));

return(0);

}

parse = (Ether_pkg *)buffer;

while(1)

{

memset(buffer,0,sizeof(buffer));

recvfrom(sockfd,buffer,sizeof(buffer),0,NULL,&len);

if( (ntohs(parse->ether_type) ==ETHERTYPE_ARP) &&

(ntohs(parse->ar_op) == ARPOP_REPLY))

{

parse_ether_package(parse);

break;

}

}

return(0);

}

|

1.你可以首先ping这个机器,然后执行arp就可以看到这台机器的mac地址

2。自己按照arp协议发送和接收一个包(可以参考TCP-IP详解卷1:协议一书的第四章)

欢迎访问我的个人网址 www.linuxc.net

|

上面代码太繁琐了.其实在LINUX下得到局域网内IP对应的MAC地址很简单.

只要把socket 设置为原始 socket,把网卡设为混杂模式. 然后再向局域网发送广播包(IP为255.255.255.255) 就行了.(详细实现请看ARP协议)

(注: 这种方法不适合WINDOW下,因为WINDOW下的SOCKET不支持MAC层通讯!)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值