请看一下FreeBSD下获得ip和mac的代码

发表于:2007-05-25来源:作者:点击数: 标签:代码MacFreeBSD看一下这是
这是一段获得ip地址和mac的代码,但我有几个疑问,我的系统是写得有点乱,我在freebsd中运行,结果是错的,请各位 测试 一下在别的系统中是否可行. [code:1:b75aa64809]freebsd #includestdio.h #includesys/types.h #includesys/param.h #includesys/ioctl

这是一段获得ip地址和mac的代码,但我有几个疑问,我的系统是写得有点乱,我在freebsd中运行,结果是错的,请各位测试一下在别的系统中是否可行.
[code:1:b75aa64809]freebsd
#include <stdio.h> 
#include <sys/types.h> 
#include <sys/param.h> 

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

#define MAXINTERFACES   16 

main (argc, argv) 
register int argc; 
register char *argv[]; 

   register int fd, intrface, retn = 0; 
   struct ifreq buf[MAXINTERFACES]; 
   struct arpreq arp; 
   struct ifconf ifc; 

   if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) >= 0) { 
      ifc.ifc_len = sizeof buf; 
      ifc.ifc_buf = (caddr_t) buf; 
      if (!ioctl (fd, SIOCGIFCONF, (char *) &ifc)) { 
         intrface = ifc.ifc_len / sizeof (struct ifreq);
                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~在这个代码中,我觉得不
对,因为sizeof(struct ifreq)是等于32,是固定的长度,ioctl (fd, SIOCGIFCONF, (cha
r *) &ifc)是获得所有接口的mac和ip地址,其中包含了链路层的地址,即包含sockaddr_
dl和sockadde_in两种结构,他们是不等长的,所以实际上在ifc.ifc_buf中包含的多个if
req结构是不等长度的,所以求出来的interface不是接口的数目.
         printf("interface num is intrface=%d\n\n\n",intrface); 
         while (intrface-- > 0) 
          { 
            printf ("net device %s\n", buf[intrface].ifr_name); 
                   ~~~~~~~~~~~~~~~~~~~~~~~~在这个中也错了,
buf是一个一个ifreq结构数组,是定长的,在前面分析了实际的ifreq结构是变长的,由i
freq.ifr_addr的长度来决定,所以&buf[interface]已经不是一个ifreq的地址.
/*Jugde whether the net card status is promisc  */ 
            if (!(ioctl (fd, SIOCGIFFLAGS, (char *) &buf[intrface]))) { 
               if (buf[intrface].ifr_flags & IFF_PROMISC) { 
                  puts ("the interface is PROMISC"); 
                  retn++; 
               } 
            } else { 
               char str[256]; 

               sprintf (str, "cpm: ioctl device %s", buf[intrface].ifr_name); 

               perror (str); 
            } 

/*Jugde whether the net card status is up       */ 
            if (buf[intrface].ifr_flags & IFF_UP) { 
                puts("the interface status is UP"); 
               } 
            else { 
                puts("the interface status is DOWN"); 
            } 

/*Get IP of the net card */ 
            if (!(ioctl (fd, SIOCGIFADDR, (char *) &buf[intrface]))) 
                { 
                 puts ("IP address is:"); 
                 puts(inet_ntoa(((struct sockaddr_in*)(&buf[intrface].ifr_addr
))->sin_addr)); 
                 puts(""); 
                   //puts (buf[intrface].ifr_addr.sa_data); 
                } 
            else { 
               char str[256]; 

               sprintf (str, "cpm: ioctl device %s", buf[intrface].ifr_name); 

               perror (str); 
           } 
/* this section can't get Hardware Address,I don't know whether the reason is 
module driver 
//          ((struct sockaddr_in*)&arp.arp_pa)->sin_addr=((struct sockaddr_in*
)(&buf[intrface].ifr_addr))->sin_addr; 
            arp.arp_pa.sa_family = AF_INET; 
            arp.arp_ha.sa_family = AF_INET; 
            ((struct sockaddr_in*)&arp.arp_pa)->sin_addr.s_addr=((struct socka
ddr_in*)(&buf[intrface].ifr_addr))->sin_addr.s_addr; 
            if (!(ioctl (fd, SIOCGARP, (char *) &arp))) 
                { 
                 puts ("HW address is:"); 

                 printf("%02x:%02x:%02x:%02x:%02x:%02x\n", 
                                (unsigned char)arp.arp_ha.sa_data[0], 
                                (unsigned char)arp.arp_ha.sa_data[1], 
                                (unsigned char)arp.arp_ha.sa_data[2], 
                                (unsigned char)arp.arp_ha.sa_data[3], 
                                (unsigned char)arp.arp_ha.sa_data[4], 
                                (unsigned char)arp.arp_ha.sa_data[5]); 

                 puts(""); 
                 puts(""); 
                } 

*/ 

/*Get HW ADDRESS of the net card */ 
            if (!(ioctl (fd, SIOCGIFHWADDR, (char *) &buf[intrface]))) 
                { 
                 puts ("HW address is:"); 

                 printf("%02x:%02x:%02x:%02x:%02x:%02x\n", 
                                (unsigned char)buf[intrface].ifr_hwaddr.sa_dat
a[0], 
                                (unsigned char)buf[intrface].ifr_hwaddr.sa_dat
a[1], 
                                (unsigned char)buf[intrface].ifr_hwaddr.sa_dat
a[2], 
                                (unsigned char)buf[intrface].ifr_hwaddr.sa_dat
a[3], 
                                (unsigned char)buf[intrface].ifr_hwaddr.sa_dat
a[4], 
                                (unsigned char)buf[intrface].ifr_hwaddr.sa_dat
a[5]); 

                 puts(""); 
                 puts(""); 
                } 

            else { 
               char str[256]; 

               sprintf (str, "cpm: ioctl device %s", buf[intrface].ifr_name); 

               perror (str); 
           } 
        } 
      } else 
         perror ("cpm: ioctl"); 

   } else 
      perror ("cpm: socket"); 

    close (fd); 
    return retn; 
} [/code:1:b75aa64809][/code]

 qjlemon 回复于:2003-09-14 09:17:42
这是从哪里搞的代码?可能太旧了,SIOCGIFHWADDR是Linux里的宏,BSD里没有这个东东。还有<arpa/inet.h>这个头文件也没包含, 这个
[code:1:ebb982e82c]
main (argc, argv) 
register int argc; 
register char *argv[]; 
[/code:1:ebb982e82c]
是什么年代的声明风格了。
找找旧贴子看,记得有文章讲过如何获得网卡硬件地址的。

 qjlemon 回复于:2003-09-14 09:24:34
http://chinaunix.net/forum/viewtopic.php?t=4973

 andytu 回复于:2003-09-14 12:49:59
这段代码是精华区找到的,我没有把后面的SIOCGIFHWADDR这一段加进去.

 andytu 回复于:2003-09-14 12:55:42
就是这个贴,怎么没有人说出他这样的错误,难道在其他系统可以运行,奇怪
[url]http://www.chinaunix.net/forum/viewtopic.php?t=85716[/url]

 gadfly 回复于:2003-09-15 16:50:38
哦,这个在linux一直都没有问题(5.2~8.0)以及solaris上都没有问题。

各个os的支持不一样,可以试试qjlemon给出地址的代码。

另外。你可以看看man ioctl_list,看看支持BSD哪种option.

 qjlemon 回复于:2003-09-15 17:13:37
我把那段代码再贴出来一下,在FreeBSD4.5上通过:
     [code:1:67105cf9fc]
//FreeBSD下获得网卡的mac地址
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h> 
#include <fcntl.h> 
#include <sys/socket.h> 
#include <sys/ioctl.h> 
#include <sys/sysctl.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <netinet/if_ether.h> 
#include <net/route.h> 
#include <net/if_dl.h> 

int 
ip2mac(u_long target_ip, unsigned char *target_mac)
{

int s, mib[6];
size_t len;
int i = 0, j = 0;
char *buf;
struct rt_msghdr *rtm;
struct sockaddr_inarp *sin;
struct sockaddr_dl *sdl;
u_long tmp_ip;

mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
mib[3] = AF_INET;
mib[4] = NET_RT_FLAGS;
mib[5] = RTF_LLINFO;

if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
return 0;
if ((buf = (char *)malloc(len)) == NULL)
return 0;

printf("len = %d\n", len);
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
free(buf);
return 0;
}
for (s = 0; s < len; s += rtm->rtm_msglen) {
rtm = (struct rt_msghdr *) (buf + s);
printf("%d\n", rtm->rtm_msglen);
sin = (struct sockaddr_inarp *) (rtm + 1);
//sdl = (struct sockaddr_dl *) ((char *)sin + 1);
sdl = (struct sockaddr_dl *) (sin + 1);

//printf("%s\n", inet_ntoa(sin->sin_addr));
tmp_ip = (u_long) (sin->sin_addr.s_addr);
if (target_ip == tmp_ip) {
memset(target_mac, 0, sizeof(target_mac));
//bcopy((char *)LLADDR(sdl), target_mac, 6);
//bcopy(target_mac, (char *)LLADDR(sdl), 6);
strcpy(target_mac, link_ntoa(sdl));
free(buf);
return 1;
}
}
free(buf);
return 0;
}


main(int argc, char *argv[])
{

unsigned char   macstr[256];
if (argc == 1) {
printf("Usage:\tip2mac sourceIP\n");
return;
}
memset(macstr, 0, 256);
if (ip2mac(inet_addr(argv[1]), macstr)) {
printf("%s\n", macstr);
} else
printf("error\n");
}
[/code:1:67105cf9fc]

 andytu 回复于:2003-09-16 20:48:35
谢谢各位了,我自己已经编了一段求出接口的硬件地址和ip地址了,不过方法不同

 gadfly 回复于:2003-09-17 12:54:26
哦,如果方便,请共享一下你的思路和方法

 andytu 回复于:2003-09-17 20:09:09
这是我自己编的,可能程序结构不是很好,请多指教
[code:1:02c5384289]#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sysctl.h>

#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_types.h>

#include <netinet/in.h>
#include <netinet/in_var.h>
#include <arpa/inet.h>

#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc,char **argv)
{
struct ifreq *ifrp,ifr;
struct ifconf ifc;
char buffer[720],name[16];
int socketfd,error,flags,len,space=0;
ifc.ifc_len=sizeof(buffer);
len=ifc.ifc_len;
ifc.ifc_buf=buffer;

socketfd=socket(AF_INET,SOCK_DGRAM,0);

if((error=ioctl(socketfd,SIOCGIFCONF,&ifc))<0)
{
perror("ioctl faild");
exit(1);
}
if(ifc.ifc_len<=len)
{
ifrp=ifc.ifc_req;
do
{
struct sockaddr *sa=&ifrp->ifr_addr;
        strcpy(ifr.ifr_name,ifrp->ifr_name);
if(strcmp(ifrp->ifr_name,name)!=0){
strcpy(name,ifrp->ifr_name);
printf("%s:",ifrp->ifr_name);
if(!ioctl(socketfd,SIOCGIFFLAGS,&ifr))
{
flags=ifr.ifr_flags;
printf("flags=%x<",flags<<16);
if(ifr.ifr_flags&IFF_UP){
printf("UP,");
}
else{
printf("DOWN");
}
if(ifr.ifr_flags&IFF_BROADCAST){
printf("BOROADCAST,");
}
if(ifr.ifr_flags&IFF_POINTOPOINT){
printf("POINTOPOINT,");
}
if(ifr.ifr_flags&IFF_LOOPBACK){
printf("LOOPBACK,");
}
if(ifr.ifr_flags&IFF_RUNNING){
printf("RUNNING,");
}
if(ifr.ifr_flags&IFF_SIMPLEX){
printf("SIMPLEX,");
}
if(ifr.ifr_flags&IFF_MULTICAST){
printf("MULTICAST");
}
printf(">\n");
}
if(!ioctl(socketfd,SIOCGIFADDR,&ifr)){
printf("     inet %s",inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
}
if(!ioctl(socketfd,SIOCGIFNETMASK,&ifr)){
printf(" netmask %s",inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
}
if(!ioctl(socketfd,SIOCGIFBRDADDR,&ifr)){
printf(" broadcast %s\n",inet_ntoa(((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr));
}
if(((struct sockaddr_dl *)sa)->sdl_type==IFT_ETHER)
printf("     ether %s\n",ether_ntoa((struct ether_addr *)LLADDR((struct sockaddr_dl *)sa)));
//printf("types %x\n",((struct sockaddr_dl *)sa)->sdl_type);

}
ifrp=(struct ifreq*)(sa->sa_len+(caddr_t)&ifrp->ifr_addr);
space+=(int)sa->sa_len+sizeof(ifrp->ifr_name);
}
while(space<ifc.ifc_len);

}
exit(0);
}[/code:1:02c5384289]

 gadfly 回复于:2003-09-18 09:15:24
帮你改了一下题目,方便大家查阅

原文转自:http://www.ltesting.net

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)