#include /* #include */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void sockaddr2ip(uchar *ip, struct sockaddr *sa) { struct sockaddr_in *sin; sin = (struct sockaddr_in*)sa; memmove(ip, v4prefix, IPaddrlen); memmove(ip+IPv4off, &sin->sin_addr, 4); } Ipifc* readipifc(char *net, Ipifc *ifc, int index) { char *p, *ep, *q, *bp; int i, mib[6]; size_t n; Ipifc *list, **last; Iplifc *lifc, **lastlifc; struct if_msghdr *mh, *nmh; struct ifa_msghdr *ah; struct sockaddr *sa; struct sockaddr_dl *sdl; uchar ip[IPaddrlen]; USED(net); free(ifc); ifc = nil; list = nil; last = &list; /* * Does not handle IPv6 yet. */ mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = 0; mib[4] = NET_RT_IFLIST; mib[5] = 0; n = 0; if(sysctl(mib, 6, nil, &n, nil, 0) < 0) return nil; bp = mallocz(n, 1); if(bp == nil) return nil; if(sysctl(mib, 6, bp, &n, nil, 0) < 0){ free(bp); return nil; } p = bp; ep = p+n; while(p < ep){ mh = (struct if_msghdr*)p; p += mh->ifm_msglen; if(mh->ifm_type != RTM_IFINFO) continue; ifc = mallocz(sizeof *ifc, 1); if(ifc == nil) break; *last = ifc; last = &ifc->next; sdl = (struct sockaddr_dl*)(mh+1); n = sdl->sdl_nlen; if(n >= sizeof ifc->dev) n = sizeof ifc->dev - 1; memmove(ifc->dev, sdl->sdl_data, n); ifc->dev[n] = 0; ifc->rp.linkmtu = mh->ifm_data.ifi_mtu; lastlifc = &ifc->lifc; if(sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == 6) memmove(ifc->ether, LLADDR(sdl), 6); while(p < ep){ ah = (struct ifa_msghdr*)p; nmh = (struct if_msghdr*)p; if(nmh->ifm_type != RTM_NEWADDR) break; p += nmh->ifm_msglen; lifc = nil; for(i=0, q=(char*)(ah+1); iifam_addrs & (1<sa_len+sizeof(long)-1) & ~(sizeof(long)-1); if(sa->sa_family != AF_INET) continue; if(lifc == nil){ lifc = mallocz(sizeof *lifc, 1); if(lifc == nil) continue; *lastlifc = lifc; lastlifc = &lifc->next; } sockaddr2ip(ip, sa); switch(i){ case RTAX_IFA: ipmove(lifc->ip, ip); break; case RTAX_NETMASK: memset(ip, 0xFF, IPv4off); ipmove(lifc->mask, ip); break; case RTAX_BRD: if(mh->ifm_flags & IFF_POINTOPOINT) /* ipmove(lifc->remote, ip) */ ; if(mh->ifm_flags & IFF_BROADCAST) /* ipmove(lifc->bcast, ip) */ ; break; case RTAX_GATEWAY: break; case RTAX_DST: break; } } if(lifc) maskip(lifc->ip, lifc->mask, lifc->net); } } free(bp); return list; }