|
|
这是一段获得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
| 帮你改了一下题目,方便大家查阅
| |
|