system-linux.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437
  1. /*
  2. * netifd - network interface daemon
  3. * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org>
  4. * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
  5. * Copyright (C) 2013 Steven Barth <steven@midlink.org>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2
  9. * as published by the Free Software Foundation
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #define _GNU_SOURCE
  17. #include <sys/socket.h>
  18. #include <sys/ioctl.h>
  19. #include <sys/stat.h>
  20. #include <sys/syscall.h>
  21. #include <net/if.h>
  22. #include <net/if_arp.h>
  23. #include <arpa/inet.h>
  24. #include <netinet/in.h>
  25. #include <linux/rtnetlink.h>
  26. #include <linux/sockios.h>
  27. #include <linux/ip.h>
  28. #include <linux/if_vlan.h>
  29. #include <linux/if_bridge.h>
  30. #include <linux/if_tunnel.h>
  31. #include <linux/ip6_tunnel.h>
  32. #include <linux/ethtool.h>
  33. #include <linux/fib_rules.h>
  34. #ifndef RTN_FAILED_POLICY
  35. #define RTN_FAILED_POLICY 12
  36. #endif
  37. #include <unistd.h>
  38. #include <string.h>
  39. #include <fcntl.h>
  40. #include <glob.h>
  41. #include <time.h>
  42. #include <netlink/msg.h>
  43. #include <netlink/attr.h>
  44. #include <netlink/socket.h>
  45. #include <libubox/uloop.h>
  46. #include "netifd.h"
  47. #include "device.h"
  48. #include "system.h"
  49. struct event_socket {
  50. struct uloop_fd uloop;
  51. struct nl_sock *sock;
  52. struct nl_cb *cb;
  53. };
  54. static int sock_ioctl = -1;
  55. static struct nl_sock *sock_rtnl = NULL;
  56. static int cb_rtnl_event(struct nl_msg *msg, void *arg);
  57. static void handle_hotplug_event(struct uloop_fd *u, unsigned int events);
  58. static char dev_buf[256];
  59. static void
  60. handler_nl_event(struct uloop_fd *u, unsigned int events)
  61. {
  62. struct event_socket *ev = container_of(u, struct event_socket, uloop);
  63. nl_recvmsgs(ev->sock, ev->cb);
  64. }
  65. static struct nl_sock *
  66. create_socket(int protocol, int groups)
  67. {
  68. struct nl_sock *sock;
  69. sock = nl_socket_alloc();
  70. if (!sock)
  71. return NULL;
  72. if (groups)
  73. nl_join_groups(sock, groups);
  74. if (nl_connect(sock, protocol))
  75. return NULL;
  76. return sock;
  77. }
  78. static bool
  79. create_raw_event_socket(struct event_socket *ev, int protocol, int groups,
  80. uloop_fd_handler cb)
  81. {
  82. ev->sock = create_socket(protocol, groups);
  83. if (!ev->sock)
  84. return false;
  85. ev->uloop.fd = nl_socket_get_fd(ev->sock);
  86. ev->uloop.cb = cb;
  87. uloop_fd_add(&ev->uloop, ULOOP_READ | ULOOP_EDGE_TRIGGER);
  88. return true;
  89. }
  90. static bool
  91. create_event_socket(struct event_socket *ev, int protocol,
  92. int (*cb)(struct nl_msg *msg, void *arg))
  93. {
  94. // Prepare socket for link events
  95. ev->cb = nl_cb_alloc(NL_CB_DEFAULT);
  96. if (!ev->cb)
  97. return false;
  98. nl_cb_set(ev->cb, NL_CB_VALID, NL_CB_CUSTOM, cb, NULL);
  99. return create_raw_event_socket(ev, protocol, 0, handler_nl_event);
  100. }
  101. int system_init(void)
  102. {
  103. static struct event_socket rtnl_event;
  104. static struct event_socket hotplug_event;
  105. sock_ioctl = socket(AF_LOCAL, SOCK_DGRAM, 0);
  106. fcntl(sock_ioctl, F_SETFD, fcntl(sock_ioctl, F_GETFD) | FD_CLOEXEC);
  107. // Prepare socket for routing / address control
  108. sock_rtnl = create_socket(NETLINK_ROUTE, 0);
  109. if (!sock_rtnl)
  110. return -1;
  111. if (!create_event_socket(&rtnl_event, NETLINK_ROUTE, cb_rtnl_event))
  112. return -1;
  113. if (!create_raw_event_socket(&hotplug_event, NETLINK_KOBJECT_UEVENT, 1,
  114. handle_hotplug_event))
  115. return -1;
  116. // Receive network link events form kernel
  117. nl_socket_add_membership(rtnl_event.sock, RTNLGRP_LINK);
  118. return 0;
  119. }
  120. static void system_set_sysctl(const char *path, const char *val)
  121. {
  122. int fd;
  123. fd = open(path, O_WRONLY);
  124. if (fd < 0)
  125. return;
  126. write(fd, val, strlen(val));
  127. close(fd);
  128. }
  129. static void system_set_dev_sysctl(const char *path, const char *device, const char *val)
  130. {
  131. snprintf(dev_buf, sizeof(dev_buf), path, device);
  132. system_set_sysctl(dev_buf, val);
  133. }
  134. static void system_set_disable_ipv6(struct device *dev, const char *val)
  135. {
  136. system_set_dev_sysctl("/proc/sys/net/ipv6/conf/%s/disable_ipv6", dev->ifname, val);
  137. }
  138. // Evaluate netlink messages
  139. static int cb_rtnl_event(struct nl_msg *msg, void *arg)
  140. {
  141. struct nlmsghdr *nh = nlmsg_hdr(msg);
  142. struct ifinfomsg *ifi = NLMSG_DATA(nh);
  143. struct nlattr *nla[__IFLA_MAX];
  144. if (nh->nlmsg_type != RTM_DELLINK && nh->nlmsg_type != RTM_NEWLINK)
  145. goto out;
  146. nlmsg_parse(nh, sizeof(*ifi), nla, __IFLA_MAX - 1, NULL);
  147. if (!nla[IFLA_IFNAME])
  148. goto out;
  149. struct device *dev = device_get(RTA_DATA(nla[IFLA_IFNAME]), false);
  150. if (!dev)
  151. goto out;
  152. dev->ifindex = ifi->ifi_index;
  153. /* TODO: parse link status */
  154. out:
  155. return 0;
  156. }
  157. static void
  158. handle_hotplug_msg(char *data, int size)
  159. {
  160. const char *subsystem = NULL, *interface = NULL;
  161. char *cur, *end, *sep;
  162. struct device *dev;
  163. int skip;
  164. bool add;
  165. if (!strncmp(data, "add@", 4))
  166. add = true;
  167. else if (!strncmp(data, "remove@", 7))
  168. add = false;
  169. else
  170. return;
  171. skip = strlen(data) + 1;
  172. end = data + size;
  173. for (cur = data + skip; cur < end; cur += skip) {
  174. skip = strlen(cur) + 1;
  175. sep = strchr(cur, '=');
  176. if (!sep)
  177. continue;
  178. *sep = 0;
  179. if (!strcmp(cur, "INTERFACE"))
  180. interface = sep + 1;
  181. else if (!strcmp(cur, "SUBSYSTEM")) {
  182. subsystem = sep + 1;
  183. if (strcmp(subsystem, "net") != 0)
  184. return;
  185. }
  186. if (subsystem && interface)
  187. goto found;
  188. }
  189. return;
  190. found:
  191. dev = device_get(interface, false);
  192. if (!dev)
  193. return;
  194. if (dev->type != &simple_device_type)
  195. return;
  196. if (add && system_if_force_external(dev->ifname))
  197. return;
  198. device_set_present(dev, add);
  199. }
  200. static void
  201. handle_hotplug_event(struct uloop_fd *u, unsigned int events)
  202. {
  203. struct event_socket *ev = container_of(u, struct event_socket, uloop);
  204. struct sockaddr_nl nla;
  205. unsigned char *buf = NULL;
  206. int size;
  207. while ((size = nl_recv(ev->sock, &nla, &buf, NULL)) > 0) {
  208. if (nla.nl_pid == 0)
  209. handle_hotplug_msg((char *) buf, size);
  210. free(buf);
  211. }
  212. }
  213. static int system_rtnl_call(struct nl_msg *msg)
  214. {
  215. int ret;
  216. ret = nl_send_auto_complete(sock_rtnl, msg);
  217. nlmsg_free(msg);
  218. if (ret < 0)
  219. return ret;
  220. return nl_wait_for_ack(sock_rtnl);
  221. }
  222. int system_bridge_delbr(struct device *bridge)
  223. {
  224. return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname);
  225. }
  226. static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data)
  227. {
  228. struct ifreq ifr;
  229. memset(&ifr, 0, sizeof(ifr));
  230. if (dev)
  231. ifr.ifr_ifindex = dev->ifindex;
  232. else
  233. ifr.ifr_data = data;
  234. strncpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
  235. return ioctl(sock_ioctl, cmd, &ifr);
  236. }
  237. static bool system_is_bridge(const char *name, char *buf, int buflen)
  238. {
  239. struct stat st;
  240. snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bridge", name);
  241. if (stat(buf, &st) < 0)
  242. return false;
  243. return true;
  244. }
  245. static char *system_get_bridge(const char *name, char *buf, int buflen)
  246. {
  247. char *path;
  248. ssize_t len;
  249. glob_t gl;
  250. snprintf(buf, buflen, "/sys/devices/virtual/net/*/brif/%s/bridge", name);
  251. if (glob(buf, GLOB_NOSORT, NULL, &gl) < 0)
  252. return NULL;
  253. if (gl.gl_pathc == 0)
  254. return NULL;
  255. len = readlink(gl.gl_pathv[0], buf, buflen);
  256. if (len < 0)
  257. return NULL;
  258. buf[len] = 0;
  259. path = strrchr(buf, '/');
  260. if (!path)
  261. return NULL;
  262. return path + 1;
  263. }
  264. int system_bridge_addif(struct device *bridge, struct device *dev)
  265. {
  266. char *oldbr;
  267. system_set_disable_ipv6(dev, "1");
  268. oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf));
  269. if (oldbr && !strcmp(oldbr, bridge->ifname))
  270. return 0;
  271. return system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL);
  272. }
  273. int system_bridge_delif(struct device *bridge, struct device *dev)
  274. {
  275. system_set_disable_ipv6(dev, "0");
  276. return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL);
  277. }
  278. static int system_if_resolve(struct device *dev)
  279. {
  280. struct ifreq ifr;
  281. strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
  282. if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr))
  283. return ifr.ifr_ifindex;
  284. else
  285. return 0;
  286. }
  287. static int system_if_flags(const char *ifname, unsigned add, unsigned rem)
  288. {
  289. struct ifreq ifr;
  290. memset(&ifr, 0, sizeof(ifr));
  291. strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
  292. ioctl(sock_ioctl, SIOCGIFFLAGS, &ifr);
  293. ifr.ifr_flags |= add;
  294. ifr.ifr_flags &= ~rem;
  295. return ioctl(sock_ioctl, SIOCSIFFLAGS, &ifr);
  296. }
  297. struct clear_data {
  298. struct nl_msg *msg;
  299. struct device *dev;
  300. int type;
  301. int size;
  302. int af;
  303. };
  304. static bool check_ifaddr(struct nlmsghdr *hdr, int ifindex)
  305. {
  306. struct ifaddrmsg *ifa = NLMSG_DATA(hdr);
  307. return ifa->ifa_index == ifindex;
  308. }
  309. static bool check_route(struct nlmsghdr *hdr, int ifindex)
  310. {
  311. struct rtmsg *r = NLMSG_DATA(hdr);
  312. struct nlattr *tb[__RTA_MAX];
  313. if (r->rtm_protocol == RTPROT_KERNEL &&
  314. r->rtm_family == AF_INET6)
  315. return false;
  316. nlmsg_parse(hdr, sizeof(struct rtmsg), tb, __RTA_MAX - 1, NULL);
  317. if (!tb[RTA_OIF])
  318. return false;
  319. return *(int *)RTA_DATA(tb[RTA_OIF]) == ifindex;
  320. }
  321. static bool check_rule(struct nlmsghdr *hdr, int ifindex)
  322. {
  323. return true;
  324. }
  325. static int cb_clear_event(struct nl_msg *msg, void *arg)
  326. {
  327. struct clear_data *clr = arg;
  328. struct nlmsghdr *hdr = nlmsg_hdr(msg);
  329. bool (*cb)(struct nlmsghdr *, int ifindex);
  330. int type;
  331. switch(clr->type) {
  332. case RTM_GETADDR:
  333. type = RTM_DELADDR;
  334. if (hdr->nlmsg_type != RTM_NEWADDR)
  335. return NL_SKIP;
  336. cb = check_ifaddr;
  337. break;
  338. case RTM_GETROUTE:
  339. type = RTM_DELROUTE;
  340. if (hdr->nlmsg_type != RTM_NEWROUTE)
  341. return NL_SKIP;
  342. cb = check_route;
  343. break;
  344. case RTM_GETRULE:
  345. type = RTM_DELRULE;
  346. if (hdr->nlmsg_type != RTM_NEWRULE)
  347. return NL_SKIP;
  348. cb = check_rule;
  349. break;
  350. default:
  351. return NL_SKIP;
  352. }
  353. if (!cb(hdr, clr->dev ? clr->dev->ifindex : 0))
  354. return NL_SKIP;
  355. if (type == RTM_DELRULE)
  356. D(SYSTEM, "Remove a rule\n");
  357. else
  358. D(SYSTEM, "Remove %s from device %s\n",
  359. type == RTM_DELADDR ? "an address" : "a route",
  360. clr->dev->ifname);
  361. memcpy(nlmsg_hdr(clr->msg), hdr, hdr->nlmsg_len);
  362. hdr = nlmsg_hdr(clr->msg);
  363. hdr->nlmsg_type = type;
  364. hdr->nlmsg_flags = NLM_F_REQUEST;
  365. if (!nl_send_auto_complete(sock_rtnl, clr->msg))
  366. nl_wait_for_ack(sock_rtnl);
  367. return NL_SKIP;
  368. }
  369. static int
  370. cb_finish_event(struct nl_msg *msg, void *arg)
  371. {
  372. int *pending = arg;
  373. *pending = 0;
  374. return NL_STOP;
  375. }
  376. static int
  377. error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
  378. {
  379. int *pending = arg;
  380. *pending = err->error;
  381. return NL_STOP;
  382. }
  383. static void
  384. system_if_clear_entries(struct device *dev, int type, int af)
  385. {
  386. struct clear_data clr;
  387. struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
  388. struct rtmsg rtm = {
  389. .rtm_family = af,
  390. .rtm_flags = RTM_F_CLONED,
  391. };
  392. int flags = NLM_F_DUMP;
  393. int pending = 1;
  394. clr.af = af;
  395. clr.dev = dev;
  396. clr.type = type;
  397. switch (type) {
  398. case RTM_GETADDR:
  399. case RTM_GETRULE:
  400. clr.size = sizeof(struct rtgenmsg);
  401. break;
  402. case RTM_GETROUTE:
  403. clr.size = sizeof(struct rtmsg);
  404. break;
  405. default:
  406. return;
  407. }
  408. if (!cb)
  409. return;
  410. clr.msg = nlmsg_alloc_simple(type, flags);
  411. if (!clr.msg)
  412. goto out;
  413. nlmsg_append(clr.msg, &rtm, clr.size, 0);
  414. nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, cb_clear_event, &clr);
  415. nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, cb_finish_event, &pending);
  416. nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &pending);
  417. nl_send_auto_complete(sock_rtnl, clr.msg);
  418. while (pending > 0)
  419. nl_recvmsgs(sock_rtnl, cb);
  420. nlmsg_free(clr.msg);
  421. out:
  422. nl_cb_put(cb);
  423. }
  424. /*
  425. * Clear bridge (membership) state and bring down device
  426. */
  427. void system_if_clear_state(struct device *dev)
  428. {
  429. static char buf[256];
  430. char *bridge;
  431. if (dev->external)
  432. return;
  433. dev->ifindex = system_if_resolve(dev);
  434. if (!dev->ifindex)
  435. return;
  436. system_if_flags(dev->ifname, 0, IFF_UP);
  437. if (system_is_bridge(dev->ifname, buf, sizeof(buf))) {
  438. D(SYSTEM, "Delete existing bridge named '%s'\n", dev->ifname);
  439. system_bridge_delbr(dev);
  440. return;
  441. }
  442. bridge = system_get_bridge(dev->ifname, buf, sizeof(buf));
  443. if (bridge) {
  444. D(SYSTEM, "Remove device '%s' from bridge '%s'\n", dev->ifname, bridge);
  445. system_bridge_if(bridge, dev, SIOCBRDELIF, NULL);
  446. }
  447. system_if_clear_entries(dev, RTM_GETROUTE, AF_INET);
  448. system_if_clear_entries(dev, RTM_GETADDR, AF_INET);
  449. system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6);
  450. system_if_clear_entries(dev, RTM_GETADDR, AF_INET6);
  451. system_set_disable_ipv6(dev, "0");
  452. }
  453. static inline unsigned long
  454. sec_to_jiffies(int val)
  455. {
  456. return (unsigned long) val * 100;
  457. }
  458. int system_bridge_addbr(struct device *bridge, struct bridge_config *cfg)
  459. {
  460. unsigned long args[4] = {};
  461. if (ioctl(sock_ioctl, SIOCBRADDBR, bridge->ifname) < 0)
  462. return -1;
  463. args[0] = BRCTL_SET_BRIDGE_STP_STATE;
  464. args[1] = !!cfg->stp;
  465. system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
  466. args[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
  467. args[1] = sec_to_jiffies(cfg->forward_delay);
  468. system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
  469. system_set_dev_sysctl("/sys/devices/virtual/net/%s/bridge/multicast_snooping",
  470. bridge->ifname, cfg->igmp_snoop ? "1" : "0");
  471. args[0] = BRCTL_SET_BRIDGE_PRIORITY;
  472. args[1] = cfg->priority;
  473. system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
  474. if (cfg->flags & BRIDGE_OPT_AGEING_TIME) {
  475. args[0] = BRCTL_SET_AGEING_TIME;
  476. args[1] = sec_to_jiffies(cfg->ageing_time);
  477. system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
  478. }
  479. if (cfg->flags & BRIDGE_OPT_HELLO_TIME) {
  480. args[0] = BRCTL_SET_BRIDGE_HELLO_TIME;
  481. args[1] = sec_to_jiffies(cfg->hello_time);
  482. system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
  483. }
  484. if (cfg->flags & BRIDGE_OPT_MAX_AGE) {
  485. args[0] = BRCTL_SET_BRIDGE_MAX_AGE;
  486. args[1] = sec_to_jiffies(cfg->max_age);
  487. system_bridge_if(bridge->ifname, NULL, SIOCDEVPRIVATE, &args);
  488. }
  489. return 0;
  490. }
  491. static int system_vlan(struct device *dev, int id)
  492. {
  493. struct vlan_ioctl_args ifr = {
  494. .cmd = SET_VLAN_NAME_TYPE_CMD,
  495. .u.name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD,
  496. };
  497. ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
  498. if (id < 0) {
  499. ifr.cmd = DEL_VLAN_CMD;
  500. ifr.u.VID = 0;
  501. } else {
  502. ifr.cmd = ADD_VLAN_CMD;
  503. ifr.u.VID = id;
  504. }
  505. strncpy(ifr.device1, dev->ifname, sizeof(ifr.device1));
  506. return ioctl(sock_ioctl, SIOCSIFVLAN, &ifr);
  507. }
  508. int system_vlan_add(struct device *dev, int id)
  509. {
  510. return system_vlan(dev, id);
  511. }
  512. int system_vlan_del(struct device *dev)
  513. {
  514. return system_vlan(dev, -1);
  515. }
  516. static void
  517. system_if_get_settings(struct device *dev, struct device_settings *s)
  518. {
  519. struct ifreq ifr;
  520. memset(&ifr, 0, sizeof(ifr));
  521. strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
  522. if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) {
  523. s->mtu = ifr.ifr_mtu;
  524. s->flags |= DEV_OPT_MTU;
  525. }
  526. if (ioctl(sock_ioctl, SIOCGIFTXQLEN, &ifr) == 0) {
  527. s->txqueuelen = ifr.ifr_qlen;
  528. s->flags |= DEV_OPT_TXQUEUELEN;
  529. }
  530. if (ioctl(sock_ioctl, SIOCGIFHWADDR, &ifr) == 0) {
  531. memcpy(s->macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(s->macaddr));
  532. s->flags |= DEV_OPT_MACADDR;
  533. }
  534. }
  535. void
  536. system_if_apply_settings(struct device *dev, struct device_settings *s)
  537. {
  538. struct ifreq ifr;
  539. memset(&ifr, 0, sizeof(ifr));
  540. strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name));
  541. if (s->flags & DEV_OPT_MTU) {
  542. ifr.ifr_mtu = s->mtu;
  543. if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0)
  544. s->flags &= ~DEV_OPT_MTU;
  545. }
  546. if (s->flags & DEV_OPT_TXQUEUELEN) {
  547. ifr.ifr_qlen = s->txqueuelen;
  548. if (ioctl(sock_ioctl, SIOCSIFTXQLEN, &ifr) < 0)
  549. s->flags &= ~DEV_OPT_TXQUEUELEN;
  550. }
  551. if ((s->flags & DEV_OPT_MACADDR) && !dev->external) {
  552. ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
  553. memcpy(&ifr.ifr_hwaddr.sa_data, s->macaddr, sizeof(s->macaddr));
  554. if (ioctl(sock_ioctl, SIOCSIFHWADDR, &ifr) < 0)
  555. s->flags &= ~DEV_OPT_MACADDR;
  556. }
  557. }
  558. int system_if_up(struct device *dev)
  559. {
  560. system_if_get_settings(dev, &dev->orig_settings);
  561. system_if_apply_settings(dev, &dev->settings);
  562. dev->ifindex = system_if_resolve(dev);
  563. return system_if_flags(dev->ifname, IFF_UP, 0);
  564. }
  565. int system_if_down(struct device *dev)
  566. {
  567. int ret = system_if_flags(dev->ifname, 0, IFF_UP);
  568. dev->orig_settings.flags &= dev->settings.flags;
  569. system_if_apply_settings(dev, &dev->orig_settings);
  570. return ret;
  571. }
  572. int system_if_check(struct device *dev)
  573. {
  574. device_set_present(dev, (system_if_resolve(dev) > 0));
  575. return 0;
  576. }
  577. struct device *
  578. system_if_get_parent(struct device *dev)
  579. {
  580. char buf[64], *devname;
  581. int ifindex, iflink, len;
  582. FILE *f;
  583. snprintf(buf, sizeof(buf), "/sys/class/net/%s/iflink", dev->ifname);
  584. f = fopen(buf, "r");
  585. if (!f)
  586. return NULL;
  587. len = fread(buf, 1, sizeof(buf) - 1, f);
  588. fclose(f);
  589. if (len <= 0)
  590. return NULL;
  591. buf[len] = 0;
  592. iflink = strtoul(buf, NULL, 0);
  593. ifindex = system_if_resolve(dev);
  594. if (!iflink || iflink == ifindex)
  595. return NULL;
  596. devname = if_indextoname(iflink, buf);
  597. if (!devname)
  598. return NULL;
  599. return device_get(devname, true);
  600. }
  601. static bool
  602. read_string_file(int dir_fd, const char *file, char *buf, int len)
  603. {
  604. bool ret = false;
  605. char *c;
  606. int fd;
  607. fd = openat(dir_fd, file, O_RDONLY);
  608. if (fd < 0)
  609. return false;
  610. retry:
  611. len = read(fd, buf, len - 1);
  612. if (len < 0) {
  613. if (errno == EINTR)
  614. goto retry;
  615. } else if (len > 0) {
  616. buf[len] = 0;
  617. c = strchr(buf, '\n');
  618. if (c)
  619. *c = 0;
  620. ret = true;
  621. }
  622. close(fd);
  623. return ret;
  624. }
  625. static bool
  626. read_uint64_file(int dir_fd, const char *file, uint64_t *val)
  627. {
  628. char buf[64];
  629. bool ret = false;
  630. ret = read_string_file(dir_fd, file, buf, sizeof(buf));
  631. if (ret)
  632. *val = strtoull(buf, NULL, 0);
  633. return ret;
  634. }
  635. /* Assume advertised flags == supported flags */
  636. static const struct {
  637. uint32_t mask;
  638. const char *name;
  639. } ethtool_link_modes[] = {
  640. { ADVERTISED_10baseT_Half, "10H" },
  641. { ADVERTISED_10baseT_Full, "10F" },
  642. { ADVERTISED_100baseT_Half, "100H" },
  643. { ADVERTISED_100baseT_Full, "100F" },
  644. { ADVERTISED_1000baseT_Half, "1000H" },
  645. { ADVERTISED_1000baseT_Full, "1000F" },
  646. };
  647. static void system_add_link_modes(struct blob_buf *b, __u32 mask)
  648. {
  649. int i;
  650. for (i = 0; i < ARRAY_SIZE(ethtool_link_modes); i++) {
  651. if (mask & ethtool_link_modes[i].mask)
  652. blobmsg_add_string(b, NULL, ethtool_link_modes[i].name);
  653. }
  654. }
  655. bool
  656. system_if_force_external(const char *ifname)
  657. {
  658. char buf[64];
  659. struct stat s;
  660. snprintf(buf, sizeof(buf), "/sys/class/net/%s/phy80211", ifname);
  661. return stat(buf, &s) == 0;
  662. }
  663. int
  664. system_if_dump_info(struct device *dev, struct blob_buf *b)
  665. {
  666. struct ethtool_cmd ecmd;
  667. struct ifreq ifr;
  668. char buf[64], *s;
  669. void *c;
  670. int dir_fd;
  671. uint64_t val = 0;
  672. snprintf(buf, sizeof(buf), "/sys/class/net/%s", dev->ifname);
  673. dir_fd = open(buf, O_DIRECTORY);
  674. if (read_uint64_file(dir_fd, "carrier", &val))
  675. blobmsg_add_u8(b, "link", !!val);
  676. memset(&ecmd, 0, sizeof(ecmd));
  677. memset(&ifr, 0, sizeof(ifr));
  678. strcpy(ifr.ifr_name, dev->ifname);
  679. ifr.ifr_data = (caddr_t) &ecmd;
  680. ecmd.cmd = ETHTOOL_GSET;
  681. if (ioctl(sock_ioctl, SIOCETHTOOL, &ifr) == 0) {
  682. c = blobmsg_open_array(b, "link-advertising");
  683. system_add_link_modes(b, ecmd.advertising);
  684. blobmsg_close_array(b, c);
  685. c = blobmsg_open_array(b, "link-supported");
  686. system_add_link_modes(b, ecmd.supported);
  687. blobmsg_close_array(b, c);
  688. s = blobmsg_alloc_string_buffer(b, "speed", 8);
  689. snprintf(s, 8, "%d%c", ethtool_cmd_speed(&ecmd),
  690. ecmd.duplex == DUPLEX_HALF ? 'H' : 'F');
  691. blobmsg_add_string_buffer(b);
  692. }
  693. close(dir_fd);
  694. return 0;
  695. }
  696. int
  697. system_if_dump_stats(struct device *dev, struct blob_buf *b)
  698. {
  699. const char *const counters[] = {
  700. "collisions", "rx_frame_errors", "tx_compressed",
  701. "multicast", "rx_length_errors", "tx_dropped",
  702. "rx_bytes", "rx_missed_errors", "tx_errors",
  703. "rx_compressed", "rx_over_errors", "tx_fifo_errors",
  704. "rx_crc_errors", "rx_packets", "tx_heartbeat_errors",
  705. "rx_dropped", "tx_aborted_errors", "tx_packets",
  706. "rx_errors", "tx_bytes", "tx_window_errors",
  707. "rx_fifo_errors", "tx_carrier_errors",
  708. };
  709. char buf[64];
  710. int stats_dir;
  711. int i;
  712. uint64_t val = 0;
  713. snprintf(buf, sizeof(buf), "/sys/class/net/%s/statistics", dev->ifname);
  714. stats_dir = open(buf, O_DIRECTORY);
  715. if (stats_dir < 0)
  716. return -1;
  717. for (i = 0; i < ARRAY_SIZE(counters); i++)
  718. if (read_uint64_file(stats_dir, counters[i], &val))
  719. blobmsg_add_u64(b, counters[i], val);
  720. close(stats_dir);
  721. return 0;
  722. }
  723. static int system_addr(struct device *dev, struct device_addr *addr, int cmd)
  724. {
  725. bool v4 = ((addr->flags & DEVADDR_FAMILY) == DEVADDR_INET4);
  726. int alen = v4 ? 4 : 16;
  727. unsigned int flags = 0;
  728. struct ifaddrmsg ifa = {
  729. .ifa_family = (alen == 4) ? AF_INET : AF_INET6,
  730. .ifa_prefixlen = addr->mask,
  731. .ifa_index = dev->ifindex,
  732. };
  733. struct nl_msg *msg;
  734. if (cmd == RTM_NEWADDR)
  735. flags |= NLM_F_CREATE | NLM_F_REPLACE;
  736. msg = nlmsg_alloc_simple(cmd, flags);
  737. if (!msg)
  738. return -1;
  739. nlmsg_append(msg, &ifa, sizeof(ifa), 0);
  740. nla_put(msg, IFA_LOCAL, alen, &addr->addr);
  741. if (v4) {
  742. if (addr->broadcast)
  743. nla_put_u32(msg, IFA_BROADCAST, addr->broadcast);
  744. if (addr->point_to_point)
  745. nla_put_u32(msg, IFA_ADDRESS, addr->point_to_point);
  746. } else {
  747. time_t now = system_get_rtime();
  748. struct ifa_cacheinfo cinfo = {0xffffffffU, 0xffffffffU, 0, 0};
  749. if (addr->preferred_until) {
  750. int64_t preferred = addr->preferred_until - now;
  751. if (preferred < 0)
  752. preferred = 0;
  753. else if (preferred > UINT32_MAX)
  754. preferred = UINT32_MAX;
  755. cinfo.ifa_prefered = preferred;
  756. }
  757. if (addr->valid_until) {
  758. int64_t valid = addr->valid_until - now;
  759. if (valid <= 0)
  760. return -1;
  761. else if (valid > UINT32_MAX)
  762. valid = UINT32_MAX;
  763. cinfo.ifa_valid = valid;
  764. }
  765. nla_put(msg, IFA_CACHEINFO, sizeof(cinfo), &cinfo);
  766. }
  767. return system_rtnl_call(msg);
  768. }
  769. int system_add_address(struct device *dev, struct device_addr *addr)
  770. {
  771. return system_addr(dev, addr, RTM_NEWADDR);
  772. }
  773. int system_del_address(struct device *dev, struct device_addr *addr)
  774. {
  775. return system_addr(dev, addr, RTM_DELADDR);
  776. }
  777. static int system_rt(struct device *dev, struct device_route *route, int cmd)
  778. {
  779. int alen = ((route->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ? 4 : 16;
  780. bool have_gw;
  781. unsigned int flags = 0;
  782. if (alen == 4)
  783. have_gw = !!route->nexthop.in.s_addr;
  784. else
  785. have_gw = route->nexthop.in6.s6_addr32[0] ||
  786. route->nexthop.in6.s6_addr32[1] ||
  787. route->nexthop.in6.s6_addr32[2] ||
  788. route->nexthop.in6.s6_addr32[3];
  789. unsigned char scope = (cmd == RTM_DELROUTE) ? RT_SCOPE_NOWHERE :
  790. (have_gw) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
  791. unsigned int table = (route->flags & (DEVROUTE_TABLE | DEVROUTE_SRCTABLE))
  792. ? route->table : RT_TABLE_MAIN;
  793. struct rtmsg rtm = {
  794. .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
  795. .rtm_dst_len = route->mask,
  796. .rtm_table = (table < 256) ? table : RT_TABLE_UNSPEC,
  797. .rtm_protocol = (route->flags & DEVADDR_KERNEL) ? RTPROT_KERNEL : RTPROT_STATIC,
  798. .rtm_scope = scope,
  799. .rtm_type = (cmd == RTM_DELROUTE) ? 0: RTN_UNICAST,
  800. };
  801. struct nl_msg *msg;
  802. if (cmd == RTM_NEWROUTE) {
  803. flags |= NLM_F_CREATE | NLM_F_REPLACE;
  804. if (!dev) { // Add null-route
  805. rtm.rtm_scope = RT_SCOPE_UNIVERSE;
  806. rtm.rtm_type = RTN_UNREACHABLE;
  807. }
  808. }
  809. msg = nlmsg_alloc_simple(cmd, flags);
  810. if (!msg)
  811. return -1;
  812. nlmsg_append(msg, &rtm, sizeof(rtm), 0);
  813. if (route->mask)
  814. nla_put(msg, RTA_DST, alen, &route->addr);
  815. if (route->metric > 0)
  816. nla_put_u32(msg, RTA_PRIORITY, route->metric);
  817. if (have_gw)
  818. nla_put(msg, RTA_GATEWAY, alen, &route->nexthop);
  819. if (dev)
  820. nla_put_u32(msg, RTA_OIF, dev->ifindex);
  821. if (table >= 256)
  822. nla_put_u32(msg, RTA_TABLE, table);
  823. return system_rtnl_call(msg);
  824. }
  825. int system_add_route(struct device *dev, struct device_route *route)
  826. {
  827. return system_rt(dev, route, RTM_NEWROUTE);
  828. }
  829. int system_del_route(struct device *dev, struct device_route *route)
  830. {
  831. return system_rt(dev, route, RTM_DELROUTE);
  832. }
  833. int system_flush_routes(void)
  834. {
  835. const char *names[] = {
  836. "/proc/sys/net/ipv4/route/flush",
  837. "/proc/sys/net/ipv6/route/flush"
  838. };
  839. int fd, i;
  840. for (i = 0; i < ARRAY_SIZE(names); i++) {
  841. fd = open(names[i], O_WRONLY);
  842. if (fd < 0)
  843. continue;
  844. write(fd, "-1", 2);
  845. close(fd);
  846. }
  847. return 0;
  848. }
  849. bool system_resolve_rt_table(const char *name, unsigned int *id)
  850. {
  851. FILE *f;
  852. char *e, buf[128];
  853. unsigned int n, table = RT_TABLE_UNSPEC;
  854. /* first try to parse table as number */
  855. if ((n = strtoul(name, &e, 0)) > 0 && !*e)
  856. table = n;
  857. /* handle well known aliases */
  858. else if (!strcmp(name, "default"))
  859. table = RT_TABLE_DEFAULT;
  860. else if (!strcmp(name, "main"))
  861. table = RT_TABLE_MAIN;
  862. else if (!strcmp(name, "local"))
  863. table = RT_TABLE_LOCAL;
  864. /* try to look up name in /etc/iproute2/rt_tables */
  865. else if ((f = fopen("/etc/iproute2/rt_tables", "r")) != NULL)
  866. {
  867. while (fgets(buf, sizeof(buf) - 1, f) != NULL)
  868. {
  869. if ((e = strtok(buf, " \t\n")) == NULL || *e == '#')
  870. continue;
  871. n = strtoul(e, NULL, 10);
  872. e = strtok(NULL, " \t\n");
  873. if (e && !strcmp(e, name))
  874. {
  875. table = n;
  876. break;
  877. }
  878. }
  879. fclose(f);
  880. }
  881. if (table == RT_TABLE_UNSPEC)
  882. return false;
  883. /* do not consider main table special */
  884. if (table == RT_TABLE_MAIN)
  885. table = RT_TABLE_UNSPEC;
  886. *id = table;
  887. return true;
  888. }
  889. static int system_iprule(struct iprule *rule, int cmd)
  890. {
  891. int alen = ((rule->flags & IPRULE_FAMILY) == IPRULE_INET4) ? 4 : 16;
  892. struct nl_msg *msg;
  893. struct rtmsg rtm = {
  894. .rtm_family = (alen == 4) ? AF_INET : AF_INET6,
  895. .rtm_protocol = RTPROT_STATIC,
  896. .rtm_scope = RT_SCOPE_UNIVERSE,
  897. .rtm_table = RT_TABLE_UNSPEC,
  898. .rtm_type = RTN_UNSPEC,
  899. .rtm_flags = 0,
  900. };
  901. if (cmd == RTM_NEWRULE) {
  902. rtm.rtm_type = RTN_UNICAST;
  903. rtm.rtm_flags |= NLM_F_REPLACE | NLM_F_EXCL;
  904. }
  905. if (rule->invert)
  906. rtm.rtm_flags |= FIB_RULE_INVERT;
  907. if (rule->flags & IPRULE_SRC)
  908. rtm.rtm_src_len = rule->src_mask;
  909. if (rule->flags & IPRULE_DEST)
  910. rtm.rtm_dst_len = rule->dest_mask;
  911. if (rule->flags & IPRULE_TOS)
  912. rtm.rtm_tos = rule->tos;
  913. if (rule->flags & IPRULE_LOOKUP) {
  914. if (rule->lookup < 256)
  915. rtm.rtm_table = rule->lookup;
  916. }
  917. if (rule->flags & IPRULE_ACTION)
  918. rtm.rtm_type = rule->action;
  919. else if (rule->flags & IPRULE_GOTO)
  920. rtm.rtm_type = FR_ACT_GOTO;
  921. else if (!(rule->flags & (IPRULE_LOOKUP | IPRULE_ACTION | IPRULE_GOTO)))
  922. rtm.rtm_type = FR_ACT_NOP;
  923. msg = nlmsg_alloc_simple(cmd, NLM_F_REQUEST);
  924. if (!msg)
  925. return -1;
  926. nlmsg_append(msg, &rtm, sizeof(rtm), 0);
  927. if (rule->flags & IPRULE_IN)
  928. nla_put(msg, FRA_IFNAME, strlen(rule->in_dev) + 1, rule->in_dev);
  929. if (rule->flags & IPRULE_OUT)
  930. nla_put(msg, FRA_OIFNAME, strlen(rule->out_dev) + 1, rule->out_dev);
  931. if (rule->flags & IPRULE_SRC)
  932. nla_put(msg, FRA_SRC, alen, &rule->src_addr);
  933. if (rule->flags & IPRULE_DEST)
  934. nla_put(msg, FRA_DST, alen, &rule->dest_addr);
  935. if (rule->flags & IPRULE_PRIORITY)
  936. nla_put_u32(msg, FRA_PRIORITY, rule->priority);
  937. else if (cmd == RTM_NEWRULE)
  938. nla_put_u32(msg, FRA_PRIORITY, rule->order);
  939. if (rule->flags & IPRULE_FWMARK)
  940. nla_put_u32(msg, FRA_FWMARK, rule->fwmark);
  941. if (rule->flags & IPRULE_FWMASK)
  942. nla_put_u32(msg, FRA_FWMASK, rule->fwmask);
  943. if (rule->flags & IPRULE_LOOKUP) {
  944. if (rule->lookup >= 256)
  945. nla_put_u32(msg, FRA_TABLE, rule->lookup);
  946. }
  947. if (rule->flags & IPRULE_GOTO)
  948. nla_put_u32(msg, FRA_GOTO, rule->gotoid);
  949. return system_rtnl_call(msg);
  950. }
  951. int system_add_iprule(struct iprule *rule)
  952. {
  953. return system_iprule(rule, RTM_NEWRULE);
  954. }
  955. int system_del_iprule(struct iprule *rule)
  956. {
  957. return system_iprule(rule, RTM_DELRULE);
  958. }
  959. int system_flush_iprules(void)
  960. {
  961. int rv = 0;
  962. struct iprule rule;
  963. system_if_clear_entries(NULL, RTM_GETRULE, AF_INET);
  964. system_if_clear_entries(NULL, RTM_GETRULE, AF_INET6);
  965. memset(&rule, 0, sizeof(rule));
  966. rule.flags = IPRULE_INET4 | IPRULE_PRIORITY | IPRULE_LOOKUP;
  967. rule.priority = 0;
  968. rule.lookup = RT_TABLE_LOCAL;
  969. rv |= system_iprule(&rule, RTM_NEWRULE);
  970. rule.priority = 32766;
  971. rule.lookup = RT_TABLE_MAIN;
  972. rv |= system_iprule(&rule, RTM_NEWRULE);
  973. rule.priority = 32767;
  974. rule.lookup = RT_TABLE_DEFAULT;
  975. rv |= system_iprule(&rule, RTM_NEWRULE);
  976. rule.flags = IPRULE_INET6 | IPRULE_PRIORITY | IPRULE_LOOKUP;
  977. rule.priority = 0;
  978. rule.lookup = RT_TABLE_LOCAL;
  979. rv |= system_iprule(&rule, RTM_NEWRULE);
  980. rule.priority = 32766;
  981. rule.lookup = RT_TABLE_MAIN;
  982. rv |= system_iprule(&rule, RTM_NEWRULE);
  983. return rv;
  984. }
  985. bool system_resolve_iprule_action(const char *action, unsigned int *id)
  986. {
  987. char *e;
  988. unsigned int n;
  989. if (!strcmp(action, "local"))
  990. n = RTN_LOCAL;
  991. else if (!strcmp(action, "nat"))
  992. n = RTN_NAT;
  993. else if (!strcmp(action, "broadcast"))
  994. n = RTN_BROADCAST;
  995. else if (!strcmp(action, "anycast"))
  996. n = RTN_ANYCAST;
  997. else if (!strcmp(action, "multicast"))
  998. n = RTN_MULTICAST;
  999. else if (!strcmp(action, "prohibit"))
  1000. n = RTN_PROHIBIT;
  1001. else if (!strcmp(action, "unreachable"))
  1002. n = RTN_UNREACHABLE;
  1003. else if (!strcmp(action, "blackhole"))
  1004. n = RTN_BLACKHOLE;
  1005. else if (!strcmp(action, "xresolve"))
  1006. n = RTN_XRESOLVE;
  1007. else if (!strcmp(action, "unicast"))
  1008. n = RTN_UNICAST;
  1009. else if (!strcmp(action, "throw"))
  1010. n = RTN_THROW;
  1011. else if (!strcmp(action, "failed_policy"))
  1012. n = RTN_FAILED_POLICY;
  1013. else {
  1014. n = strtoul(action, &e, 0);
  1015. if (!e || *e || e == action || n > 255)
  1016. return false;
  1017. }
  1018. *id = n;
  1019. return true;
  1020. }
  1021. time_t system_get_rtime(void)
  1022. {
  1023. struct timespec ts;
  1024. struct timeval tv;
  1025. if (syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts) == 0)
  1026. return ts.tv_sec;
  1027. if (gettimeofday(&tv, NULL) == 0)
  1028. return tv.tv_sec;
  1029. return 0;
  1030. }
  1031. #ifndef IP_DF
  1032. #define IP_DF 0x4000
  1033. #endif
  1034. static int tunnel_ioctl(const char *name, int cmd, void *p)
  1035. {
  1036. struct ifreq ifr;
  1037. memset(&ifr, 0, sizeof(ifr));
  1038. strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
  1039. ifr.ifr_ifru.ifru_data = p;
  1040. return ioctl(sock_ioctl, cmd, &ifr);
  1041. }
  1042. int system_del_ip_tunnel(const char *name)
  1043. {
  1044. return tunnel_ioctl(name, SIOCDELTUNNEL, NULL);
  1045. }
  1046. int system_update_ipv6_mtu(struct device *dev, int mtu)
  1047. {
  1048. int ret = -1;
  1049. char buf[64];
  1050. snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu",
  1051. dev->ifname);
  1052. int fd = open(buf, O_RDWR);
  1053. ssize_t len = read(fd, buf, sizeof(buf) - 1);
  1054. if (len < 0)
  1055. goto out;
  1056. buf[len] = 0;
  1057. ret = atoi(buf);
  1058. if (!mtu || ret <= mtu)
  1059. goto out;
  1060. lseek(fd, 0, SEEK_SET);
  1061. if (write(fd, buf, snprintf(buf, sizeof(buf), "%i", mtu)) <= 0)
  1062. ret = -1;
  1063. out:
  1064. close(fd);
  1065. return ret;
  1066. }
  1067. int system_add_ip_tunnel(const char *name, struct blob_attr *attr)
  1068. {
  1069. struct blob_attr *tb[__TUNNEL_ATTR_MAX];
  1070. struct blob_attr *cur;
  1071. const char *str;
  1072. system_del_ip_tunnel(name);
  1073. blobmsg_parse(tunnel_attr_list.params, __TUNNEL_ATTR_MAX, tb,
  1074. blob_data(attr), blob_len(attr));
  1075. if (!(cur = tb[TUNNEL_ATTR_TYPE]))
  1076. return -EINVAL;
  1077. str = blobmsg_data(cur);
  1078. unsigned int ttl = 0;
  1079. if ((cur = tb[TUNNEL_ATTR_TTL]) && (ttl = blobmsg_get_u32(cur)) > 255)
  1080. return -EINVAL;
  1081. unsigned int link = 0;
  1082. if ((cur = tb[TUNNEL_ATTR_LINK])) {
  1083. struct interface *iface = vlist_find(&interfaces, blobmsg_data(cur), iface, node);
  1084. if (!iface)
  1085. return -EINVAL;
  1086. if (iface->l3_dev.dev)
  1087. link = iface->l3_dev.dev->ifindex;
  1088. }
  1089. if (!strcmp(str, "sit")) {
  1090. struct ip_tunnel_parm p = {
  1091. .link = link,
  1092. .iph = {
  1093. .version = 4,
  1094. .ihl = 5,
  1095. .frag_off = htons(IP_DF),
  1096. .protocol = IPPROTO_IPV6,
  1097. .ttl = ttl
  1098. }
  1099. };
  1100. if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
  1101. inet_pton(AF_INET, blobmsg_data(cur), &p.iph.saddr) < 1)
  1102. return -EINVAL;
  1103. if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
  1104. inet_pton(AF_INET, blobmsg_data(cur), &p.iph.daddr) < 1)
  1105. return -EINVAL;
  1106. strncpy(p.name, name, sizeof(p.name));
  1107. if (tunnel_ioctl("sit0", SIOCADDTUNNEL, &p) < 0)
  1108. return -1;
  1109. #ifdef SIOCADD6RD
  1110. if ((cur = tb[TUNNEL_ATTR_6RD_PREFIX])) {
  1111. unsigned int mask;
  1112. struct ip_tunnel_6rd p6;
  1113. memset(&p6, 0, sizeof(p6));
  1114. if (!parse_ip_and_netmask(AF_INET6, blobmsg_data(cur),
  1115. &p6.prefix, &mask) || mask > 128)
  1116. return -EINVAL;
  1117. p6.prefixlen = mask;
  1118. if ((cur = tb[TUNNEL_ATTR_6RD_RELAY_PREFIX])) {
  1119. if (!parse_ip_and_netmask(AF_INET, blobmsg_data(cur),
  1120. &p6.relay_prefix, &mask) || mask > 32)
  1121. return -EINVAL;
  1122. p6.relay_prefixlen = mask;
  1123. }
  1124. if (tunnel_ioctl(name, SIOCADD6RD, &p6) < 0) {
  1125. system_del_ip_tunnel(name);
  1126. return -1;
  1127. }
  1128. }
  1129. #endif
  1130. } else if (!strcmp(str, "ipip6")) {
  1131. struct ip6_tnl_parm p = {
  1132. .link = link,
  1133. .proto = IPPROTO_IPIP,
  1134. .hop_limit = (ttl) ? ttl : 64,
  1135. .encap_limit = 4,
  1136. };
  1137. if ((cur = tb[TUNNEL_ATTR_LOCAL]) &&
  1138. inet_pton(AF_INET6, blobmsg_data(cur), &p.laddr) < 1)
  1139. return -EINVAL;
  1140. if ((cur = tb[TUNNEL_ATTR_REMOTE]) &&
  1141. inet_pton(AF_INET6, blobmsg_data(cur), &p.raddr) < 1)
  1142. return -EINVAL;
  1143. strncpy(p.name, name, sizeof(p.name));
  1144. if (tunnel_ioctl("ip6tnl0", SIOCADDTUNNEL, &p) < 0)
  1145. return -1;
  1146. } else
  1147. return -EINVAL;
  1148. return 0;
  1149. }