BSD.c (2994B)
1 #include <u.h> 2 /* #include <everything_but_the_kitchen_sink.h> */ 3 #include <sys/socket.h> 4 #include <netinet/in.h> 5 #include <net/if.h> 6 #include <sys/ioctl.h> 7 #include <sys/sysctl.h> 8 #include <net/ethernet.h> 9 #include <net/if.h> 10 #include <net/if_var.h> 11 #include <net/if_dl.h> 12 #include <net/if_types.h> 13 #include <net/route.h> 14 #include <netinet/in.h> 15 #include <netinet/in_var.h> 16 #include <arpa/inet.h> 17 #include <netdb.h> 18 #include <libc.h> 19 #include <ip.h> 20 21 static void 22 sockaddr2ip(uchar *ip, struct sockaddr *sa) 23 { 24 struct sockaddr_in *sin; 25 26 sin = (struct sockaddr_in*)sa; 27 memmove(ip, v4prefix, IPaddrlen); 28 memmove(ip+IPv4off, &sin->sin_addr, 4); 29 } 30 31 Ipifc* 32 readipifc(char *net, Ipifc *ifc, int index) 33 { 34 char *p, *ep, *q, *bp; 35 int i, mib[6]; 36 size_t n; 37 Ipifc *list, **last; 38 Iplifc *lifc, **lastlifc; 39 struct if_msghdr *mh, *nmh; 40 struct ifa_msghdr *ah; 41 struct sockaddr *sa; 42 struct sockaddr_dl *sdl; 43 uchar ip[IPaddrlen]; 44 45 USED(net); 46 47 free(ifc); 48 ifc = nil; 49 list = nil; 50 last = &list; 51 52 /* 53 * Does not handle IPv6 yet. 54 */ 55 56 mib[0] = CTL_NET; 57 mib[1] = PF_ROUTE; 58 mib[2] = 0; 59 mib[3] = 0; 60 mib[4] = NET_RT_IFLIST; 61 mib[5] = 0; 62 63 n = 0; 64 if(sysctl(mib, 6, nil, &n, nil, 0) < 0) 65 return nil; 66 bp = mallocz(n, 1); 67 if(bp == nil) 68 return nil; 69 if(sysctl(mib, 6, bp, &n, nil, 0) < 0){ 70 free(bp); 71 return nil; 72 } 73 74 p = bp; 75 ep = p+n; 76 while(p < ep){ 77 mh = (struct if_msghdr*)p; 78 p += mh->ifm_msglen; 79 if(mh->ifm_type != RTM_IFINFO) 80 continue; 81 ifc = mallocz(sizeof *ifc, 1); 82 if(ifc == nil) 83 break; 84 *last = ifc; 85 last = &ifc->next; 86 sdl = (struct sockaddr_dl*)(mh+1); 87 n = sdl->sdl_nlen; 88 if(n >= sizeof ifc->dev) 89 n = sizeof ifc->dev - 1; 90 memmove(ifc->dev, sdl->sdl_data, n); 91 ifc->dev[n] = 0; 92 ifc->rp.linkmtu = mh->ifm_data.ifi_mtu; 93 lastlifc = &ifc->lifc; 94 95 if(sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == 6) 96 memmove(ifc->ether, LLADDR(sdl), 6); 97 98 while(p < ep){ 99 ah = (struct ifa_msghdr*)p; 100 nmh = (struct if_msghdr*)p; 101 if(nmh->ifm_type != RTM_NEWADDR) 102 break; 103 p += nmh->ifm_msglen; 104 lifc = nil; 105 for(i=0, q=(char*)(ah+1); i<RTAX_MAX && q<p; i++){ 106 if(!(ah->ifam_addrs & (1<<i))) 107 continue; 108 sa = (struct sockaddr*)q; 109 q += (sa->sa_len+sizeof(long)-1) & ~(sizeof(long)-1); 110 if(sa->sa_family != AF_INET) 111 continue; 112 if(lifc == nil){ 113 lifc = mallocz(sizeof *lifc, 1); 114 if(lifc == nil) 115 continue; 116 *lastlifc = lifc; 117 lastlifc = &lifc->next; 118 } 119 sockaddr2ip(ip, sa); 120 switch(i){ 121 case RTAX_IFA: 122 ipmove(lifc->ip, ip); 123 break; 124 case RTAX_NETMASK: 125 memset(ip, 0xFF, IPv4off); 126 ipmove(lifc->mask, ip); 127 break; 128 case RTAX_BRD: 129 if(mh->ifm_flags & IFF_POINTOPOINT) 130 /* ipmove(lifc->remote, ip) */ ; 131 if(mh->ifm_flags & IFF_BROADCAST) 132 /* ipmove(lifc->bcast, ip) */ ; 133 break; 134 case RTAX_GATEWAY: 135 break; 136 case RTAX_DST: 137 break; 138 } 139 } 140 if(lifc) 141 maskip(lifc->ip, lifc->mask, lifc->net); 142 } 143 } 144 free(bp); 145 return list; 146 }