Blob


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>
21 static void
22 sockaddr2ip(uchar *ip, struct sockaddr *sa)
23 {
24 struct sockaddr_in *sin;
26 sin = (struct sockaddr_in*)sa;
27 memmove(ip, v4prefix, IPaddrlen);
28 memmove(ip+IPv4off, &sin->sin_addr, 4);
29 }
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];
45 USED(net);
47 free(ifc);
48 ifc = nil;
49 list = nil;
50 last = &list;
52 /*
53 * Does not handle IPv6 yet.
54 */
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;
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 }
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;
95 if(sdl->sdl_type == IFT_ETHER && sdl->sdl_alen == 6)
96 memmove(ifc->ether, LLADDR(sdl), 6);
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;
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;
140 if(lifc)
141 maskip(lifc->ip, lifc->mask, lifc->net);
144 free(bp);
145 return list;