nmap 路由解析
一、获取系统中所有的网络接口的方法
方法1.读取/proc/net/dev
intf_loop(intf_t *intf, intf_handler callback, void *arg)//按行读取/proc/net/dev,来获取接口名 { FILE *fp; struct intf_entry *entry; char *p, buf[BUFSIZ], ebuf[BUFSIZ]; int ret; if ((fp = fopen(PROC_DEV_FILE, "r")) == NULL)//#define PROC_DEV_FILE "/proc/net/dev" return (-1); ... while (fgets(buf, sizeof(buf), fp) != NULL) { //按行读取/proc/net/dev if ((p = strchr(buf, ':')) == NULL) //遇到:,则保存指针 continue; *p = '\0'; //在原先‘:‘ 的位置,存入'\0',截断字符串 for (p = buf; *p == ' '; p++) //去掉多余的空格 ; } if (_intf_get_noalias(intf, entry) < 0) { ret = -1; break; } .... return (ret); }
写一段小程序,理解这里的字符串截取
char buf[] = "123:456"; char *p; p = strchr(buf,':'); *p = '\0'; printf("buf is %s\n",buf);
输出结果buf is 123
方法2、利用ioctl
int intf_loop(intf_t *intf, intf_handler callback, void *arg) { struct intf_entry *entry; struct ifreq *ifr, *lifr, *pifr; char *p, ebuf[BUFSIZ]; int ret; entry = (struct intf_entry *)ebuf; intf->ifc.ifc_buf = (caddr_t)intf->ifcbuf; intf->ifc.ifc_len = sizeof(intf->ifcbuf); if (ioctl(intf->fd, SIOCGIFCONF, &intf->ifc) < 0) return (-1); pifr = NULL; lifr = (struct ifreq *)&intf->ifc.ifc_buf[intf->ifc.ifc_len];//指向ifc.ifc_buf数组的最后位置 for (ifr = intf->ifc.ifc_req; ifr < lifr; ifr = NEXTIFR(ifr)) {//指针的增加,
strcmp(ifr->ifr_name, pifr->ifr_name);
这里,使用指针直接增加。看到过两种:
上面是一种,是
ifr->ifr_addr +max(ifr->ifr_addr.sa_len, sizeof(struct sockaddr))
是直接用ip地址位置 + ip地址长度。
其中max因为有ipv4 ipv6两种,其中,ipv4的sa_len和sizeof(struct sockaddr)是一样大的,而ipv6的 sa_len > sizeof(struct sockaddr)
第二种,是ifr +ifr_name长度+ ip 地址长度
for( ifr = ifc.ifc_req; ifr < buf +ifc.ifc_len; ) { ifr +=sizeof(ifr->ifr_name)+max(ifr->ifr_addr.sa_len, sizeof(struct sockaddr)); }
这两种方法,试过总出问题,并且提示sockaddr没有sa_len成员
第三种是直接计数,这中方法是要点是 1.struct ifreq *buf; 2.buf[i].ifr_name
struct ifreq *buf; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return -1; buf = malloc(10*sizeof(struct ifreq)); memset(buf, 0 ,10*sizeof(struct ifreq)); ifc.ifc_len = 10 *sizeof(struct ifreq); ifc.ifc_req = buf; ioctl(fd,SIOCGIFCONF, &ifc); lifr = (struct ifreq*)&ifc.ifc_buf[ifc.ifc_len]; count = ifc.ifc_len/(sizeof(struct ifreq)); for(i=0; i< count;i++) { printf("intf %s\n",buf[i].ifr_name); } close(fd);
_intf_get_noalias(intf_t *intf, struct intf_entry *entry) { struct ifreq ifr; /* Get interface index. */ entry->intf_index = if_nametoindex(entry->intf_name);//通过接口名获得接口索引 if (entry->intf_index == 0) return (-1); strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name)); /* Get interface flags. */ if (ioctl(intf->fd, SIOCGIFFLAGS, &ifr) < 0) return (-1); entry->intf_flags = intf_iff_to_flags(ifr.ifr_flags); _intf_set_type(entry); /* Get interface MTU. */ #ifdef SIOCGIFMTU if (ioctl(intf->fd, SIOCGIFMTU, &ifr) < 0) #endif return (-1); entry->intf_mtu = ifr.ifr_mtu; entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type = entry->intf_link_addr.addr_type = ADDR_TYPE_NONE; /* Get primary interface address. */ if (ioctl(intf->fd, SIOCGIFADDR, &ifr) == 0) { addr_ston(&ifr.ifr_addr, &entry->intf_addr); if (ioctl(intf->fd, SIOCGIFNETMASK, &ifr) < 0) return (-1); addr_stob(&ifr.ifr_addr, &entry->intf_addr.addr_bits); } /* Get other addresses. */ if (entry->intf_type == INTF_TYPE_TUN) { if (ioctl(intf->fd, SIOCGIFDSTADDR, &ifr) == 0) { if (addr_ston(&ifr.ifr_addr, &entry->intf_dst_addr) < 0) return (-1); } } else if (entry->intf_type == INTF_TYPE_ETH) { #if defined(SIOCGIFHWADDR) if (ioctl(intf->fd, SIOCGIFHWADDR, &ifr) < 0) return (-1); if (addr_ston(&ifr.ifr_addr, &entry->intf_link_addr) < 0) return (-1); #elif defined(SIOCRPHYSADDR) /* Tru64 */ struct ifdevea *ifd = (struct ifdevea *)
size_t strlcpy(dst, src, siz) char *dst; const char *src; size_t siz; { register char *d = dst; register const char *s = src; register size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { //判断n是否为0,或1,同时这样的--n也为字符串末尾的'\0'空出位置 do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++) ; } return(s - src - 1); /* count does not include NUL */ }