用sscanf函数将读取内容按格式存储在不同变量中。
route_loop(route_t *r, route_handler callback, void *arg)
{
FILE *fp;
struct route_entry entry;
char buf[BUFSIZ];
int ret = 0;
if ((fp = fopen(PROC_ROUTE_FILE, "r")) != NULL) {
char ifbuf[16];
int i, iflags, refcnt, use, metric, mss, win, irtt;
uint32_t mask;
while (fgets(buf, sizeof(buf), fp) != NULL) {
i = sscanf(buf, "%16s %X %X %X %d %d %d %X %d %d %d\n",
ifbuf, &entry.route_dst.addr_ip,
&entry.route_gw.addr_ip, &iflags, &refcnt, &use,
&metric, &mask, &mss, &win, &irtt);//获取路由表各项信息
if (i < 10 || !(iflags & RTF_UP))
continue;
entry.route_dst.addr_type = entry.route_gw.addr_type =
ADDR_TYPE_IP;
if (addr_mtob(&mask, IP_ADDR_LEN,
&entry.route_dst.addr_bits) < 0)//对mask的每一位进行是否为零的判断,IP_ADDR_LEN =4
continue;
entry.route_gw.addr_bits = IP_ADDR_BITS;
if ((ret = callback(&entry, arg)) != 0)
break;
}
fclose(fp);
}
if (ret == 0 && (fp = fopen(PROC_IPV6_ROUTE_FILE, "r")) != NULL) {
char s[33], d[8][5], n[8][5];
u_int slen, dlen;
while (fgets(buf, sizeof(buf), fp) != NULL) {
sscanf(buf, "%04s%04s%04s%04s%04s%04s%04s%04s %02x "
"%32s %02x %04s%04s%04s%04s%04s%04s%04s%04s ",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
&dlen, s, &slen,
n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]);
snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d",
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
dlen);
addr_aton(buf, &entry.route_dst);
snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d",
n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7],
IP6_ADDR_BITS);
addr_aton(buf, &entry.route_gw);
if ((ret = callback(&entry, arg)) != 0)
break;
}
fclose(fp);
}
return (ret);
}
int
addr_mtob(const void *mask, size_t size, uint16_t *bits)
{
uint16_t n;
u_char *p;
int i, j;
p = (u_char *)mask;
for (n = i = 0; i < (int)size; i++, n += 8) {//每四位进行一次判断,如果不为 1111 1111,则直接跳出循环,
if (p[i] != 0xff) //这使得下面的判断是从非零项开始
break;
}
if (i != (int)size && p[i]) {
for (j = 7; j > 0; j--, n++) {
if ((p[i] & (1 << j)) == 0)//从高位开始判断,每一位是否为1,如果为0,则跳出循环
break;
}
}*bit = n;//通过这个bit,应该就可以判断是A,B,C哪类地址了,如果是A类地址,默认子网掩码255.0.0.0,这时n = 8;