Blame


1 9aec88f2 2005-12-31 devnull #include <u.h>
2 9aec88f2 2005-12-31 devnull #include <sys/ioctl.h>
3 9aec88f2 2005-12-31 devnull #include <sys/socket.h>
4 9aec88f2 2005-12-31 devnull #include <netinet/in.h>
5 9aec88f2 2005-12-31 devnull #include <arpa/inet.h>
6 9aec88f2 2005-12-31 devnull #include <asm/types.h>
7 9aec88f2 2005-12-31 devnull #include <net/if_arp.h>
8 9aec88f2 2005-12-31 devnull #include <linux/netlink.h>
9 9aec88f2 2005-12-31 devnull #include <linux/rtnetlink.h>
10 9aec88f2 2005-12-31 devnull #include <net/if.h>
11 9aec88f2 2005-12-31 devnull #include <libc.h>
12 9aec88f2 2005-12-31 devnull #include <ip.h>
13 9aec88f2 2005-12-31 devnull
14 9aec88f2 2005-12-31 devnull /*
15 9aec88f2 2005-12-31 devnull * Use netlink sockets to find interfaces.
16 9aec88f2 2005-12-31 devnull * Thanks to Erik Quanstrom.
17 9aec88f2 2005-12-31 devnull */
18 9aec88f2 2005-12-31 devnull static int
19 fa325e9b 2020-01-10 cross netlinkrequest(int fd, int type, int (*fn)(struct nlmsghdr *h, Ipifc**, int),
20 9aec88f2 2005-12-31 devnull Ipifc **ifc, int index)
21 9aec88f2 2005-12-31 devnull {
22 9aec88f2 2005-12-31 devnull char buf[1024];
23 9aec88f2 2005-12-31 devnull int n;
24 9aec88f2 2005-12-31 devnull struct sockaddr_nl nl;
25 9aec88f2 2005-12-31 devnull struct {
26 9aec88f2 2005-12-31 devnull struct nlmsghdr nlh;
27 9aec88f2 2005-12-31 devnull struct rtgenmsg g;
28 9aec88f2 2005-12-31 devnull } req;
29 9aec88f2 2005-12-31 devnull struct nlmsghdr *h;
30 9aec88f2 2005-12-31 devnull
31 9aec88f2 2005-12-31 devnull memset(&nl, 0, sizeof nl);
32 9aec88f2 2005-12-31 devnull nl.nl_family = AF_NETLINK;
33 9aec88f2 2005-12-31 devnull
34 9aec88f2 2005-12-31 devnull memset(&req, 0, sizeof req);
35 9aec88f2 2005-12-31 devnull req.nlh.nlmsg_len = sizeof req;
36 9aec88f2 2005-12-31 devnull req.nlh.nlmsg_type = type;
37 9aec88f2 2005-12-31 devnull req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
38 9aec88f2 2005-12-31 devnull req.nlh.nlmsg_pid = 0;
39 9aec88f2 2005-12-31 devnull req.nlh.nlmsg_seq = 1;
40 9aec88f2 2005-12-31 devnull req.g.rtgen_family = AF_NETLINK;
41 9aec88f2 2005-12-31 devnull
42 9aec88f2 2005-12-31 devnull if(sendto(fd, (void*)&req, sizeof req, 0, (struct sockaddr*)&nl, sizeof nl) < 0)
43 9aec88f2 2005-12-31 devnull return -1;
44 9aec88f2 2005-12-31 devnull
45 9aec88f2 2005-12-31 devnull while((n=read(fd, buf, sizeof buf)) > 0){
46 9aec88f2 2005-12-31 devnull for(h=(struct nlmsghdr*)buf; NLMSG_OK(h, n); h = NLMSG_NEXT(h, n)){
47 9aec88f2 2005-12-31 devnull if(h->nlmsg_type == NLMSG_DONE)
48 9aec88f2 2005-12-31 devnull return 0;
49 9aec88f2 2005-12-31 devnull if(h->nlmsg_type == NLMSG_ERROR){
50 9aec88f2 2005-12-31 devnull werrstr("netlink error");
51 9aec88f2 2005-12-31 devnull return -1;
52 9aec88f2 2005-12-31 devnull }
53 9aec88f2 2005-12-31 devnull if(fn(h, ifc, index) < 0)
54 9aec88f2 2005-12-31 devnull return -1;
55 9aec88f2 2005-12-31 devnull }
56 9aec88f2 2005-12-31 devnull }
57 9aec88f2 2005-12-31 devnull werrstr("netlink error");
58 9aec88f2 2005-12-31 devnull return -1;
59 9aec88f2 2005-12-31 devnull }
60 9aec88f2 2005-12-31 devnull
61 9aec88f2 2005-12-31 devnull static int
62 9aec88f2 2005-12-31 devnull devsocket(void)
63 9aec88f2 2005-12-31 devnull {
64 9aec88f2 2005-12-31 devnull /* we couldn't care less which one; just want to talk to the kernel! */
65 9aec88f2 2005-12-31 devnull static int dumb[3] = { AF_INET, AF_PACKET, AF_INET6 };
66 9aec88f2 2005-12-31 devnull int i, fd;
67 fa325e9b 2020-01-10 cross
68 9aec88f2 2005-12-31 devnull for(i=0; i<nelem(dumb); i++)
69 9aec88f2 2005-12-31 devnull if((fd = socket(dumb[i], SOCK_DGRAM, 0)) >= 0)
70 9aec88f2 2005-12-31 devnull return fd;
71 9aec88f2 2005-12-31 devnull return -1;
72 9aec88f2 2005-12-31 devnull }
73 9aec88f2 2005-12-31 devnull
74 9aec88f2 2005-12-31 devnull static int
75 9aec88f2 2005-12-31 devnull parsertattr(struct rtattr **dst, int ndst, struct nlmsghdr *h, int type, int skip)
76 9aec88f2 2005-12-31 devnull {
77 9aec88f2 2005-12-31 devnull struct rtattr *src;
78 9aec88f2 2005-12-31 devnull int len;
79 fa325e9b 2020-01-10 cross
80 9aec88f2 2005-12-31 devnull len = h->nlmsg_len - NLMSG_LENGTH(skip);
81 9aec88f2 2005-12-31 devnull if(len < 0 || h->nlmsg_type != type){
82 9aec88f2 2005-12-31 devnull werrstr("attrs too short");
83 9aec88f2 2005-12-31 devnull return -1;
84 9aec88f2 2005-12-31 devnull }
85 9aec88f2 2005-12-31 devnull src = (struct rtattr*)((char*)NLMSG_DATA(h) + NLMSG_ALIGN(skip));
86 9aec88f2 2005-12-31 devnull
87 9aec88f2 2005-12-31 devnull memset(dst, 0, ndst*sizeof dst[0]);
88 9aec88f2 2005-12-31 devnull for(; RTA_OK(src, len); src = RTA_NEXT(src, len))
89 9aec88f2 2005-12-31 devnull if(src->rta_type < ndst)
90 9aec88f2 2005-12-31 devnull dst[src->rta_type] = src;
91 9aec88f2 2005-12-31 devnull return 0;
92 9aec88f2 2005-12-31 devnull }
93 9aec88f2 2005-12-31 devnull
94 9aec88f2 2005-12-31 devnull static void
95 9aec88f2 2005-12-31 devnull rta2ip(int af, uchar *ip, struct rtattr *rta)
96 9aec88f2 2005-12-31 devnull {
97 9aec88f2 2005-12-31 devnull memset(ip, 0, IPaddrlen);
98 fa325e9b 2020-01-10 cross
99 9aec88f2 2005-12-31 devnull switch(af){
100 9aec88f2 2005-12-31 devnull case AF_INET:
101 9aec88f2 2005-12-31 devnull memmove(ip, v4prefix, IPv4off);
102 9aec88f2 2005-12-31 devnull memmove(ip+IPv4off, RTA_DATA(rta), IPv4addrlen);
103 9aec88f2 2005-12-31 devnull break;
104 9aec88f2 2005-12-31 devnull case AF_INET6:
105 9aec88f2 2005-12-31 devnull memmove(ip, RTA_DATA(rta), IPaddrlen);
106 9aec88f2 2005-12-31 devnull break;
107 9aec88f2 2005-12-31 devnull }
108 9aec88f2 2005-12-31 devnull }
109 9aec88f2 2005-12-31 devnull
110 9aec88f2 2005-12-31 devnull static int
111 9aec88f2 2005-12-31 devnull getlink(struct nlmsghdr *h, Ipifc **ipifclist, int index)
112 9aec88f2 2005-12-31 devnull {
113 9aec88f2 2005-12-31 devnull char *p;
114 9aec88f2 2005-12-31 devnull int fd;
115 9aec88f2 2005-12-31 devnull struct rtattr *attr[IFLA_MAX+1];
116 9aec88f2 2005-12-31 devnull struct ifinfomsg *ifi;
117 9aec88f2 2005-12-31 devnull Ipifc *ifc;
118 fa325e9b 2020-01-10 cross
119 9aec88f2 2005-12-31 devnull ifi = (struct ifinfomsg*)NLMSG_DATA(h);
120 9aec88f2 2005-12-31 devnull if(index >= 0 && ifi->ifi_index != index)
121 9aec88f2 2005-12-31 devnull return 0;
122 9aec88f2 2005-12-31 devnull
123 9aec88f2 2005-12-31 devnull ifc = mallocz(sizeof *ifc, 1);
124 9aec88f2 2005-12-31 devnull if(ifc == nil)
125 9aec88f2 2005-12-31 devnull return -1;
126 9aec88f2 2005-12-31 devnull ifc->index = ifi->ifi_index;
127 9aec88f2 2005-12-31 devnull
128 9aec88f2 2005-12-31 devnull while(*ipifclist)
129 9aec88f2 2005-12-31 devnull ipifclist = &(*ipifclist)->next;
130 9aec88f2 2005-12-31 devnull *ipifclist = ifc;
131 9aec88f2 2005-12-31 devnull
132 9aec88f2 2005-12-31 devnull if(parsertattr(attr, nelem(attr), h, RTM_NEWLINK, sizeof(struct ifinfomsg)) < 0)
133 9aec88f2 2005-12-31 devnull return -1;
134 9aec88f2 2005-12-31 devnull
135 9aec88f2 2005-12-31 devnull if(attr[IFLA_IFNAME])
136 9aec88f2 2005-12-31 devnull p = (char*)RTA_DATA(attr[IFLA_IFNAME]);
137 9aec88f2 2005-12-31 devnull else
138 9aec88f2 2005-12-31 devnull p = "nil";
139 9aec88f2 2005-12-31 devnull strecpy(ifc->dev, ifc->dev+sizeof ifc->dev, p);
140 9aec88f2 2005-12-31 devnull
141 9aec88f2 2005-12-31 devnull if(attr[IFLA_MTU])
142 9aec88f2 2005-12-31 devnull ifc->mtu = *(int*)RTA_DATA(attr[IFLA_MTU]);
143 d9742d7e 2006-01-05 devnull
144 d9742d7e 2006-01-05 devnull /*
145 d9742d7e 2006-01-05 devnull * Does not work on old Linux systems,
146 d9742d7e 2006-01-05 devnull * and not really necessary for my purposes.
147 d9742d7e 2006-01-05 devnull * Uncomment if you want it bad.
148 d9742d7e 2006-01-05 devnull *
149 9aec88f2 2005-12-31 devnull if(attr[IFLA_STATS]){
150 9aec88f2 2005-12-31 devnull struct rtnl_link_stats *s;
151 9aec88f2 2005-12-31 devnull
152 9aec88f2 2005-12-31 devnull s = RTA_DATA(attr[IFLA_STATS]);
153 9aec88f2 2005-12-31 devnull ifc->pktin = s->rx_packets;
154 9aec88f2 2005-12-31 devnull ifc->pktout = s->tx_packets;
155 9aec88f2 2005-12-31 devnull ifc->errin = s->rx_errors;
156 9aec88f2 2005-12-31 devnull ifc->errout = s->tx_errors;
157 9aec88f2 2005-12-31 devnull }
158 d9742d7e 2006-01-05 devnull *
159 d9742d7e 2006-01-05 devnull */
160 d9742d7e 2006-01-05 devnull
161 9aec88f2 2005-12-31 devnull if((fd = devsocket()) > 0){
162 9aec88f2 2005-12-31 devnull struct ifreq ifr;
163 9aec88f2 2005-12-31 devnull
164 9aec88f2 2005-12-31 devnull memset(&ifr, 0, sizeof ifr);
165 9aec88f2 2005-12-31 devnull strncpy(ifr.ifr_name, p, IFNAMSIZ);
166 9aec88f2 2005-12-31 devnull ifr.ifr_mtu = 0;
167 9aec88f2 2005-12-31 devnull if(ioctl(fd, SIOCGIFMTU, &ifr) >= 0)
168 9aec88f2 2005-12-31 devnull ifc->rp.linkmtu = ifr.ifr_mtu;
169 9aec88f2 2005-12-31 devnull
170 9aec88f2 2005-12-31 devnull memset(&ifr, 0, sizeof ifr);
171 9aec88f2 2005-12-31 devnull strncpy(ifr.ifr_name, p, IFNAMSIZ);
172 9aec88f2 2005-12-31 devnull if(ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0
173 9aec88f2 2005-12-31 devnull && ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER)
174 9aec88f2 2005-12-31 devnull memmove(ifc->ether, ifr.ifr_hwaddr.sa_data, 6);
175 fa325e9b 2020-01-10 cross
176 9aec88f2 2005-12-31 devnull close(fd);
177 9aec88f2 2005-12-31 devnull }
178 9aec88f2 2005-12-31 devnull return 0;
179 9aec88f2 2005-12-31 devnull }
180 9aec88f2 2005-12-31 devnull
181 9aec88f2 2005-12-31 devnull static int
182 9aec88f2 2005-12-31 devnull getaddr(struct nlmsghdr *h, Ipifc **ipifclist, int index)
183 9aec88f2 2005-12-31 devnull {
184 9aec88f2 2005-12-31 devnull int mask;
185 9aec88f2 2005-12-31 devnull Ipifc *ifc;
186 9aec88f2 2005-12-31 devnull Iplifc *lifc, **l;
187 9aec88f2 2005-12-31 devnull struct ifaddrmsg *ifa;
188 9aec88f2 2005-12-31 devnull struct rtattr *attr[IFA_MAX+1];
189 fa325e9b 2020-01-10 cross
190 9aec88f2 2005-12-31 devnull USED(index);
191 9aec88f2 2005-12-31 devnull
192 9aec88f2 2005-12-31 devnull ifa = (struct ifaddrmsg*)NLMSG_DATA(h);
193 9aec88f2 2005-12-31 devnull for(ifc=*ipifclist; ifc; ifc=ifc->next)
194 9aec88f2 2005-12-31 devnull if(ifc->index == ifa->ifa_index)
195 9aec88f2 2005-12-31 devnull break;
196 9aec88f2 2005-12-31 devnull if(ifc == nil)
197 9aec88f2 2005-12-31 devnull return 0;
198 9aec88f2 2005-12-31 devnull if(parsertattr(attr, nelem(attr), h, RTM_NEWADDR, sizeof(struct ifaddrmsg)) < 0)
199 9aec88f2 2005-12-31 devnull return -1;
200 fa325e9b 2020-01-10 cross
201 9aec88f2 2005-12-31 devnull lifc = mallocz(sizeof *lifc, 1);
202 9aec88f2 2005-12-31 devnull if(lifc == nil)
203 9aec88f2 2005-12-31 devnull return -1;
204 9aec88f2 2005-12-31 devnull for(l=&ifc->lifc; *l; l=&(*l)->next)
205 9aec88f2 2005-12-31 devnull ;
206 9aec88f2 2005-12-31 devnull *l = lifc;
207 9aec88f2 2005-12-31 devnull
208 9aec88f2 2005-12-31 devnull if(attr[IFA_ADDRESS] == nil)
209 9aec88f2 2005-12-31 devnull attr[IFA_ADDRESS] = attr[IFA_LOCAL];
210 9aec88f2 2005-12-31 devnull if(attr[IFA_ADDRESS] == nil)
211 9aec88f2 2005-12-31 devnull return 0;
212 9aec88f2 2005-12-31 devnull
213 9aec88f2 2005-12-31 devnull rta2ip(ifa->ifa_family, lifc->ip, attr[IFA_ADDRESS]);
214 fa325e9b 2020-01-10 cross
215 9aec88f2 2005-12-31 devnull mask = ifa->ifa_prefixlen/8;
216 9aec88f2 2005-12-31 devnull if(ifa->ifa_family == AF_INET)
217 9aec88f2 2005-12-31 devnull mask += IPv4off;
218 9aec88f2 2005-12-31 devnull memset(lifc->mask, 0xFF, mask);
219 9aec88f2 2005-12-31 devnull memmove(lifc->net, lifc->ip, mask);
220 fa325e9b 2020-01-10 cross
221 9aec88f2 2005-12-31 devnull if(attr[IFA_CACHEINFO]){
222 9aec88f2 2005-12-31 devnull struct ifa_cacheinfo *ci;
223 9aec88f2 2005-12-31 devnull
224 9aec88f2 2005-12-31 devnull ci = RTA_DATA(attr[IFA_CACHEINFO]);
225 9aec88f2 2005-12-31 devnull lifc->preflt = ci->ifa_prefered;
226 9aec88f2 2005-12-31 devnull lifc->validlt = ci->ifa_valid;
227 9aec88f2 2005-12-31 devnull }
228 9aec88f2 2005-12-31 devnull return 0;
229 9aec88f2 2005-12-31 devnull }
230 9aec88f2 2005-12-31 devnull
231 9aec88f2 2005-12-31 devnull Ipifc*
232 9aec88f2 2005-12-31 devnull readipifc(char *net, Ipifc *ifc, int index)
233 9aec88f2 2005-12-31 devnull {
234 9aec88f2 2005-12-31 devnull int fd;
235 9aec88f2 2005-12-31 devnull
236 9aec88f2 2005-12-31 devnull USED(net);
237 9aec88f2 2005-12-31 devnull freeipifc(ifc);
238 9aec88f2 2005-12-31 devnull ifc = nil;
239 fa325e9b 2020-01-10 cross
240 9aec88f2 2005-12-31 devnull fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
241 9aec88f2 2005-12-31 devnull if(fd < 0)
242 9aec88f2 2005-12-31 devnull return nil;
243 9aec88f2 2005-12-31 devnull ifc = nil;
244 9aec88f2 2005-12-31 devnull if(netlinkrequest(fd, RTM_GETLINK, getlink, &ifc, index) < 0
245 9aec88f2 2005-12-31 devnull || netlinkrequest(fd, RTM_GETADDR, getaddr, &ifc, index) < 0){
246 9aec88f2 2005-12-31 devnull close(fd);
247 9aec88f2 2005-12-31 devnull freeipifc(ifc);
248 9aec88f2 2005-12-31 devnull return nil;
249 9aec88f2 2005-12-31 devnull }
250 9aec88f2 2005-12-31 devnull close(fd);
251 9aec88f2 2005-12-31 devnull return ifc;
252 9aec88f2 2005-12-31 devnull }