drop the cleanup path in system_init, since system_init failures are fatal anyway
[project/netifd.git] / system-linux.c
1 #define _GNU_SOURCE
2
3 #include <sys/socket.h>
4 #include <sys/ioctl.h>
5 #include <sys/stat.h>
6 #include <sys/syscall.h>
7
8 #include <linux/rtnetlink.h>
9 #include <linux/sockios.h>
10 #include <linux/if_vlan.h>
11 #include <linux/if_bridge.h>
12
13 #include <unistd.h>
14 #include <string.h>
15 #include <fcntl.h>
16 #include <glob.h>
17
18 #include <netlink/msg.h>
19 #include <netlink/attr.h>
20 #include <netlink/socket.h>
21 #include <libubox/uloop.h>
22
23 #include "netifd.h"
24 #include "device.h"
25 #include "system.h"
26
27 static int sock_ioctl = -1;
28 static struct nl_sock *sock_rtnl = NULL;
29 static struct nl_sock *sock_rtnl_event = NULL;
30
31 static void handler_rtnl_event(struct uloop_fd *u, unsigned int events);
32 static int cb_rtnl_event(struct nl_msg *msg, void *arg);
33 static struct uloop_fd rtnl_event = {.cb = handler_rtnl_event};
34 static struct nl_cb *nl_cb_rtnl_event;
35
36 int system_init(void)
37 {
38         sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
39         fcntl(sock_ioctl, F_SETFD, fcntl(sock_ioctl, F_GETFD) | FD_CLOEXEC);
40
41         // Prepare socket for routing / address control
42         sock_rtnl = nl_socket_alloc();
43         if (!sock_rtnl)
44                 return -1;
45
46         if (nl_connect(sock_rtnl, NETLINK_ROUTE))
47                 return -1;
48
49         // Prepare socket for link events
50         nl_cb_rtnl_event = nl_cb_alloc(NL_CB_DEFAULT);
51         if (!nl_cb_rtnl_event)
52                 return -1;
53
54         nl_cb_set(nl_cb_rtnl_event, NL_CB_VALID, NL_CB_CUSTOM,
55                   cb_rtnl_event, NULL);
56
57         sock_rtnl_event = nl_socket_alloc();
58         if (!sock_rtnl_event)
59                 return -1;
60
61         if (nl_connect(sock_rtnl_event, NETLINK_ROUTE))
62                 return -1;
63
64         // Receive network link events form kernel
65         nl_socket_add_membership(sock_rtnl_event, RTNLGRP_LINK);
66
67         rtnl_event.fd = nl_socket_get_fd(sock_rtnl_event);
68         uloop_fd_add(&rtnl_event, ULOOP_READ | ULOOP_EDGE_TRIGGER);
69
70         return 0;
71 }
72
73 // If socket is ready for reading parse netlink events
74 static void handler_rtnl_event(struct uloop_fd *u, unsigned int events)
75 {
76         nl_recvmsgs(sock_rtnl_event, nl_cb_rtnl_event);
77 }
78
79 static void system_set_sysctl(const char *path, const char *val)
80 {
81         int fd;
82
83         fd = open(path, O_WRONLY);
84         if (fd < 0)
85                 return;
86
87         write(fd, val, strlen(val));
88         close(fd);
89 }
90
91 static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
92 {
93         static char buf[256];
94
95         snprintf(buf, sizeof(buf), path, val);
96         system_set_sysctl(buf, val);
97 }
98
99 static void system_set_disable_ipv6(struct device *dev, const char *val)
100 {
101         system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
102 }
103
104 // Evaluate netlink messages
105 static int cb_rtnl_event(struct nl_msg *msg, void *arg)
106 {
107         struct nlmsghdr *nh = nlmsg_hdr(msg);
108         struct ifinfomsg *ifi = NLMSG_DATA(nh);
109         struct nlattr *nla[__IFLA_MAX];
110
111         if (nh->nlmsg_type != RTM_DELLINK && nh->nlmsg_type != RTM_NEWLINK)
112                 goto out;
113
114         nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
115         if (!nla[IFLA_IFNAME])
116                 goto out;
117
118         struct device *dev = device_get(RTA_DATA(nla[IFLA_IFNAME]), false);
119         if (!dev)
120                 goto out;
121
122         dev->ifindex = ifi->ifi_index;
123         device_set_present(dev, (nh->nlmsg_type == RTM_NEWLINK));
124
125 out:
126         return 0;
127 }
128
129 static int system_rtnl_call(struct nl_msg *msg)
130 {
131         int s = -(nl_send_auto_complete(sock_rtnl, msg)
132                         || nl_wait_for_ack(sock_rtnl));
133         nlmsg_free(msg);
134         return s;
135 }
136
137 int system_bridge_delbr(struct device *bridge)
138 {
139         return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
140 }
141
142 static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
143 {
144         struct ifreq ifr;
145         if (dev)
146                 ifr.ifr_ifindex = dev->ifindex;
147         else
148                 ifr.ifr_data = data;
149         strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
150         return ioctl(sock_ioctl, cmd, &ifr);
151 }
152
153 int system_bridge_addif(struct device *bridge, struct device *dev)
154 {
155         system_set_disable_ipv6(dev, "1");
156         return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
157 }
158
159 int system_bridge_delif(struct device *bridge, struct device *dev)
160 {
161         system_set_disable_ipv6(dev, "0");
162         return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
163 }
164
165 static bool system_is_bridge(const char *name, char *buf, int buflen)
166 {
167         struct stat st;
168
169         snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
170         if (stat(buf, &st) < 0)
171                 return false;
172
173         return true;
174 }
175
176 static char *system_get_bridge(const char *name, char *buf, int buflen)
177 {
178         char *path;
179         ssize_t len;
180         glob_t gl;
181
182         snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
183         if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
184                 return NULL;
185
186         if (gl.gl_pathc == 0)
187                 return NULL;
188
189         len = readlink(gl.gl_pathv[0], buf, buflen);
190         if (len < 0)
191                 return NULL;
192
193         buf[len] = 0;
194         path = strrchr(buf, '/');
195         if (!path)
196                 return NULL;
197
198         return path + 1;
199 }
200
201 static int system_if_resolve(struct device *dev)
202 {
203         struct ifreq ifr;
204         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
205         if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
206                 return ifr.ifr_ifindex;
207         else
208                 return 0;
209 }
210
211 static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
212 {
213         struct ifreq ifr;
214         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
215         ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
216         ifr.ifr_flags |= add;
217         ifr.ifr_flags &= ~rem;
218         return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
219 }
220
221 struct clear_data {
222         struct nl_msg *msg;
223         struct device *dev;
224         int type;
225         int size;
226         int af;
227 };
228
229
230 static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
231 {
232         struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
233
234         return ifa->ifa_index == ifindex;
235 }
236
237 static bool check_route(struct nlmsghdr *hdr, int ifindex)
238 {
239         struct nlattr *tb[__RTA_MAX];
240
241         nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
242         if (!tb[RTA_OIF])
243                 return false;
244
245         return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
246 }
247
248 static int cb_clear_event(struct nl_msg *msg, void *arg)
249 {
250         struct clear_data *clr = arg;
251         struct nlmsghdr *hdr = nlmsg_hdr(msg);
252         bool (*cb)(struct nlmsghdr *, int ifindex);
253         int type;
254
255         switch(clr->type) {
256         case RTM_GETADDR:
257                 type = RTM_DELADDR;
258                 if (hdr->nlmsg_type != RTM_NEWADDR)
259                         return NL_SKIP;
260
261                 cb = check_ifaddr;
262                 break;
263         case RTM_GETROUTE:
264                 type = RTM_DELROUTE;
265                 if (hdr->nlmsg_type != RTM_NEWROUTE)
266                         return NL_SKIP;
267
268                 cb = check_route;
269                 break;
270         default:
271                 return NL_SKIP;
272         }
273
274         if (!cb(hdr, clr->dev->ifindex))
275                 return NL_SKIP;
276
277         D(SYSTEM, "Remove %s from device %s\n",
278           type == RTM_DELADDR ? "an address" : "a route",
279           clr->dev->ifname);
280         memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
281         hdr = nlmsg_hdr(clr->msg);
282         hdr->nlmsg_type = type;
283         hdr->nlmsg_flags = NLM_F_REQUEST;
284
285         if (!nl_send_auto_complete(sock_rtnl, clr->msg))
286                 nl_wait_for_ack(sock_rtnl);
287
288         return NL_SKIP;
289 }
290
291 static int
292 cb_finish_event(struct nl_msg *msg, void *arg)
293 {
294         int *pending = arg;
295         *pending = 0;
296         return NL_STOP;
297 }
298
299 static int
300 error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
301 {
302         int *pending = arg;
303         *pending = err->error;
304         return NL_STOP;
305 }
306
307 static void
308 system_if_clear_entries(struct device *dev, int type, int af)
309 {
310         struct clear_data clr;
311         struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
312         struct rtmsg rtm = {
313                 .rtm_family = af,
314                 .rtm_flags = RTM_F_CLONED,
315         };
316         int flags = NLM_F_DUMP;
317         int pending = 1;
318
319         clr.af = af;
320         clr.dev = dev;
321         clr.type = type;
322         switch (type) {
323         case RTM_GETADDR:
324                 clr.size = sizeof(struct rtgenmsg);
325                 break;
326         case RTM_GETROUTE:
327                 clr.size = sizeof(struct rtmsg);
328                 break;
329         default:
330                 return;
331         }
332
333         if (!cb)
334                 return;
335
336         clr.msg = nlmsg_alloc_simple(type, flags);
337         if (!clr.msg)
338                 goto out;
339
340         nlmsg_append(clr.msg, &rtm, clr.size, 0);
341         nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
342         nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
343         nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
344
345         nl_send_auto_complete(sock_rtnl, clr.msg);
346         while (pending > 0)
347                 nl_recvmsgs(sock_rtnl, cb);
348
349         nlmsg_free(clr.msg);
350 out:
351         nl_cb_put(cb);
352 }
353
354 /*
355  * Clear bridge (membership) state and bring down device
356  */
357 void system_if_clear_state(struct device *dev)
358 {
359         static char buf[256];
360         char *bridge;
361
362         if (dev->external)
363                 return;
364
365         dev->ifindex = system_if_resolve(dev);
366         if (!dev->ifindex)
367                 return;
368
369         system_if_flags(dev->ifname, 0, IFF_UP);
370
371         if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
372                 D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
373                 system_bridge_delbr(dev);
374                 return;
375         }
376
377         bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
378         if (bridge) {
379                 D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
380                 system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
381         }
382
383         system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
384         system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
385         system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
386         system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
387         system_set_disable_ipv6(dev, "0");
388 }
389
390 static inline unsigned long
391 sec_to_jiffies(int val)
392 {
393         return (unsigned long) val * 100;
394 }
395
396 int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
397 {
398         unsigned long args[4] = {};
399
400         if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
401                 return -1;
402
403         args[0] = BRCTL_SET_BRIDGE_STP_STATE;
404         args[1] = !!cfg->stp;
405         system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
406
407         args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
408         args[1] = sec_to_jiffies(cfg->forward_delay);
409         system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
410
411         system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
412                 bridge->ifname, cfg->igmp_snoop ? "1" : "0");
413
414         if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
415                 args[0] = BRCTL_SET_AGEING_TIME;
416                 args[1] = sec_to_jiffies(cfg->ageing_time);
417                 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
418         }
419
420         if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
421                 args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
422                 args[1] = sec_to_jiffies(cfg->hello_time);
423                 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
424         }
425
426         if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
427                 args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
428                 args[1] = sec_to_jiffies(cfg->max_age);
429                 system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
430         }
431
432         return 0;
433 }
434
435 static int system_vlan(struct device *dev, int id)
436 {
437         struct vlan_ioctl_args ifr = {
438                 .cmd = SET_VLAN_NAME_TYPE_CMD,
439                 .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
440         };
441
442         ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
443
444         if (id < 0) {
445                 ifr.cmd = DEL_VLAN_CMD;
446                 ifr.u.VID = 0;
447         } else {
448                 ifr.cmd = ADD_VLAN_CMD;
449                 ifr.u.VID = id;
450         }
451         strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
452         return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
453 }
454
455 int system_vlan_add(struct device *dev, int id)
456 {
457         return system_vlan(dev, id);
458 }
459
460 int system_vlan_del(struct device *dev)
461 {
462         return system_vlan(dev, -1);
463 }
464
465 static void
466 system_if_apply_settings(struct device *dev)
467 {
468         struct ifreq ifr;
469
470         memset(&ifr, 0, sizeof(ifr));
471         strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
472         if (dev->flags & DEV_OPT_MTU) {
473                 ifr.ifr_mtu = dev->mtu;
474                 ioctl(sock_ioctl, SIOCSIFMTU, &ifr);
475         }
476         if (dev->flags & DEV_OPT_TXQUEUELEN) {
477                 ifr.ifr_qlen = dev->txqueuelen;
478                 ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr);
479         }
480         if (dev->flags & DEV_OPT_MACADDR) {
481                 memcpy(&ifr.ifr_hwaddr, dev->macaddr, sizeof(dev->macaddr));
482                 ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr);
483         }
484
485         dev->ifindex = system_if_resolve(dev);
486 }
487
488 int system_if_up(struct device *dev)
489 {
490         system_if_apply_settings(dev);
491         return system_if_flags(dev->ifname, IFF_UP, 0);
492 }
493
494 int system_if_down(struct device *dev)
495 {
496         return system_if_flags(dev->ifname, 0, IFF_UP);
497 }
498
499 int system_if_check(struct device *dev)
500 {
501         device_set_present(dev, (system_if_resolve(dev) >= 0));
502         return 0;
503 }
504
505 int system_if_dump_stats(struct device *dev, struct blob_buf *b)
506 {
507         const char *const counters[] = {
508                 "collisions",     "rx_frame_errors",   "tx_compressed",
509                 "multicast",      "rx_length_errors",  "tx_dropped",
510                 "rx_bytes",       "rx_missed_errors",  "tx_errors",
511                 "rx_compressed",  "rx_over_errors",    "tx_fifo_errors",
512                 "rx_crc_errors",  "rx_packets",        "tx_heartbeat_errors",
513                 "rx_dropped",     "tx_aborted_errors", "tx_packets",
514                 "rx_errors",      "tx_bytes",          "tx_window_errors",
515                 "rx_fifo_errors", "tx_carrier_errors",
516         };
517         char buf[64];
518         int stats_dir;
519         int i, fd, len;
520
521         snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
522         stats_dir = open(buf, O_DIRECTORY);
523         if (stats_dir < 0)
524                 return -1;
525
526         for (i = 0; i < ARRAY_SIZE(counters); i++) {
527                 fd = openat(stats_dir, counters[i], O_RDONLY);
528                 if (fd < 0)
529                         continue;
530
531 retry:
532                 len = read(fd, buf, sizeof(buf));
533                 if (len < 0) {
534                         if (errno == EINTR)
535                                 goto retry;
536                         continue;
537                 }
538
539                 buf[len] = 0;
540                 blobmsg_add_u32(b, counters[i], strtoul(buf, NULL, 0));
541                 close(fd);
542         }
543
544         close(stats_dir);
545         return 0;
546 }
547
548 static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
549 {
550         int alen = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
551         struct ifaddrmsg ifa = {
552                 .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
553                 .ifa_prefixlen = addr->mask,
554                 .ifa_index = dev->ifindex,
555         };
556
557         struct nl_msg *msg;
558
559         dev = addr->device;
560         if (dev) {
561                 if (!dev->ifindex)
562                         return -1;
563
564                 ifa.ifa_index = dev->ifindex;
565         }
566
567         msg = nlmsg_alloc_simple(cmd, 0);
568         if (!msg)
569                 return -1;
570
571         nlmsg_append(msg, &ifa, sizeof(ifa), 0);
572         nla_put(msg, IFA_LOCAL, alen, &addr->addr);
573         return system_rtnl_call(msg);
574 }
575
576 int system_add_address(struct device *dev, struct device_addr *addr)
577 {
578         return system_addr(dev, addr, RTM_NEWADDR);
579 }
580
581 int system_del_address(struct device *dev, struct device_addr *addr)
582 {
583         return system_addr(dev, addr, RTM_DELADDR);
584 }
585
586 static int system_rt(struct device *dev, struct device_route *route, int cmd)
587 {
588         int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
589         bool have_gw;
590         unsigned int flags = 0;
591         int ifindex = dev->ifindex;
592
593         if (alen == 4)
594                 have_gw = !!route->nexthop.in.s_addr;
595         else
596                 have_gw = route->nexthop.in6.s6_addr32[0] ||
597                         route->nexthop.in6.s6_addr32[1] ||
598                         route->nexthop.in6.s6_addr32[2] ||
599                         route->nexthop.in6.s6_addr32[3];
600
601         unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
602                         (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
603
604         struct rtmsg rtm = {
605                 .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
606                 .rtm_dst_len = route->mask,
607                 .rtm_table = RT_TABLE_MAIN,
608                 .rtm_protocol = RTPROT_BOOT,
609                 .rtm_scope = scope,
610                 .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
611         };
612         struct nl_msg *msg;
613
614         if (cmd == RTM_NEWROUTE)
615                 flags |= NLM_F_CREATE | NLM_F_REPLACE;
616
617         dev = route->device;
618         if (dev) {
619                 if (!dev->ifindex)
620                         return -1;
621
622                 ifindex = dev->ifindex;
623         }
624
625         msg = nlmsg_alloc_simple(cmd, flags);
626         if (!msg)
627                 return -1;
628
629         nlmsg_append(msg, &rtm, sizeof(rtm), 0);
630
631         if (route->mask)
632                 nla_put(msg, RTA_DST, alen, &route->addr);
633
634         if (have_gw)
635                 nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
636
637         if (route->flags & DEVADDR_DEVICE)
638                 nla_put_u32(msg, RTA_OIF, ifindex);
639
640         return system_rtnl_call(msg);
641 }
642
643 int system_add_route(struct device *dev, struct device_route *route)
644 {
645         return system_rt(dev, route, RTM_NEWROUTE);
646 }
647
648 int system_del_route(struct device *dev, struct device_route *route)
649 {
650         return system_rt(dev, route, RTM_DELROUTE);
651 }
652
653 int system_flush_routes(void)
654 {
655         const char *names[] = {
656                 "/proc/sys/net/ipv4/route/flush",
657                 "/proc/sys/net/ipv6/route/flush"
658         };
659         int fd, i;
660
661         for (i = 0; i < ARRAY_SIZE(names); i++) {
662                 fd = open(names[i], O_WRONLY);
663                 if (fd < 0)
664                         continue;
665
666                 write(fd, "-1", 2);
667                 close(fd);
668         }
669         return 0;
670 }
671
672 time_t system_get_rtime(void)
673 {
674         struct timespec ts;
675         struct timeval tv;
676
677         if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
678                 return ts.tv_sec;
679
680         if (gettimeofday(&tv, NULL) == 0)
681                 return tv.tv_sec;
682
683         return 0;
684 }