You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

if.c 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. /* This file is part of Netsukuku
  2. * (c) Copyright 2005 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
  3. *
  4. * This source code is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as published
  6. * by the Free Software Foundation; either version 2 of the License,
  7. * or (at your option) any later version.
  8. *
  9. * This source code is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. * Please refer to the GNU Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Public License along with
  15. * this source code; if not, write to:
  16. * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. #include "includes.h"
  19. #include <fnmatch.h>
  20. #include "common.h"
  21. #include "inet.h"
  22. #include "if.h"
  23. #include "libnetlink.h"
  24. #include "ll_map.h"
  25. extern int errno;
  26. static struct {
  27. int ifindex;
  28. int family;
  29. int oneline;
  30. int showqueue;
  31. inet_prefix pfx;
  32. int scope, scopemask;
  33. int flags, flagmask;
  34. int up;
  35. char *label;
  36. int flushed;
  37. char *flushb;
  38. int flushp;
  39. int flushe;
  40. struct rtnl_handle *rth;
  41. } filter;
  42. /*
  43. * ifs_find_idx: returns the pointer to the interface struct of the
  44. * device which has the index equal to `dev_idx'.
  45. * `ifs' is the array which keeps the interface list and has `ifs_n' elements.
  46. */
  47. interface *
  48. ifs_find_idx(interface * ifs, int ifs_n, int dev_idx)
  49. {
  50. int i;
  51. for (i = 0; i < ifs_n; i++)
  52. if (ifs[i].dev_idx == dev_idx)
  53. return &ifs[i];
  54. return 0;
  55. }
  56. int
  57. ifs_find_devname(interface * ifs, int ifs_n, char *dev_name)
  58. {
  59. int i;
  60. if (!dev_name)
  61. return -1;
  62. for (i = 0; i < ifs_n; i++)
  63. if (ifs[i].dev_name &&
  64. !strncmp(ifs[i].dev_name, dev_name, IFNAMSIZ))
  65. return i;
  66. return -1;
  67. }
  68. /*
  69. * ifs_del: removes from the `ifs' array the device which is at the
  70. * `if_pos'th position. `*ifs_n' is then decremented.
  71. */
  72. void
  73. ifs_del(interface * ifs, int *ifs_n, int if_pos)
  74. {
  75. if (if_pos == (*ifs_n) - 1)
  76. setzero(&ifs[if_pos], sizeof(interface));
  77. else {
  78. memcpy(&ifs[if_pos], &ifs[(*ifs_n) - 1], sizeof(interface));
  79. setzero(&ifs[(*ifs_n) - 1], sizeof(interface));
  80. }
  81. (*ifs_n)--;
  82. }
  83. /*
  84. * ifs_del_byname: deletes from the `ifs' array the device whose name is equal
  85. * to `dev_name'
  86. */
  87. void
  88. ifs_del_byname(interface * ifs, int *ifs_n, char *dev_name)
  89. {
  90. int if_pos;
  91. if_pos = ifs_find_devname(ifs, *ifs_n, dev_name);
  92. if (if_pos < 0)
  93. return;
  94. ifs_del(ifs, ifs_n, if_pos);
  95. }
  96. /*
  97. * ifs_del_all_name: deleted from the `ifs' array all the device which have a
  98. * device name that begins with `dev_name'. For example,
  99. * ifs_del_all_name(ifs, ifs_n, "tun") deletes all the tunnel iifs
  100. */
  101. void
  102. ifs_del_all_name(interface * ifs, int *ifs_n, char *dev_name)
  103. {
  104. int i, dev_len;
  105. if (!dev_name || (dev_len = strlen(dev_name)) > IFNAMSIZ)
  106. return;
  107. for (i = 0; i < (*ifs_n); i++) {
  108. if (ifs[i].dev_name &&
  109. !strncmp(ifs[i].dev_name, dev_name, dev_len)) {
  110. ifs_del(ifs, ifs_n, i);
  111. if (i <= (*ifs_n) - 1)
  112. i--;
  113. }
  114. }
  115. }
  116. /*
  117. * ifs_get_pos: this is a stupid functions which returns the position of the
  118. * struct in the `ifs' array which has the dev_idx element equal to
  119. * `dev'->dev_idx. The `ifs' array has `ifs_n' members.
  120. * If it is not found -1 is returned.
  121. */
  122. int
  123. ifs_get_pos(interface * ifs, int ifs_n, interface * dev)
  124. {
  125. int i;
  126. for (i = 0; i < ifs_n; i++)
  127. if (ifs[i].dev_idx == dev->dev_idx)
  128. return i;
  129. return -1;
  130. }
  131. /*
  132. * get_dev: It returs the first dev it finds up and sets `*dev_ids' to the
  133. * device's index. On error NULL is returned.
  134. */
  135. const char *
  136. get_dev(int *dev_idx)
  137. {
  138. int idx;
  139. if ((idx = ll_first_up_if()) == -1) {
  140. error("Couldn't find \"up\" devices. Set one dev \"up\", or "
  141. "specify the device name in the options.");
  142. return 0;
  143. }
  144. if (dev_idx)
  145. *dev_idx = idx;
  146. return ll_index_to_name(idx);
  147. }
  148. /*
  149. * get_all_ifs: It fills the `ifs' array with all the network interfaces it
  150. * finds up. The `ifs' array has `ifs_n'# members.
  151. * It returns the number of filled interfaces.
  152. */
  153. int
  154. get_all_up_ifs(interface * ifs, int ifs_n)
  155. {
  156. int i, idx, n;
  157. for (i = 0, n = 0; i < ifs_n; i++) {
  158. idx = ll_nth_up_if(n + 1);
  159. if (idx <= 0)
  160. continue;
  161. ifs[n].dev_idx = idx;
  162. strncpy(ifs[n].dev_name, ll_index_to_name(idx), IFNAMSIZ);
  163. loginfo("Network interface \"%s\" detected", ifs[n].dev_name);
  164. n++;
  165. if ((idx - 1) > i)
  166. i = idx - 1;
  167. }
  168. return n;
  169. }
  170. int
  171. set_flags(char *dev, u_int flags, u_int mask)
  172. {
  173. struct ifreq ifr;
  174. int s;
  175. strcpy(ifr.ifr_name, dev);
  176. if ((s = new_socket(AF_INET)) < 0) {
  177. error("Error while setting \"%s\" flags: Cannot open socket", dev);
  178. return -1;
  179. }
  180. if (ioctl(s, SIOCGIFFLAGS, &ifr)) {
  181. error("Error while setting \"%s\" flags: %s", dev,
  182. strerror(errno));
  183. close(s);
  184. return -1;
  185. }
  186. ifr.ifr_flags &= ~mask;
  187. ifr.ifr_flags |= mask & flags;
  188. if (ioctl(s, SIOCSIFFLAGS, &ifr)) {
  189. error("Error while setting \"%s\" flags: %s", dev,
  190. strerror(errno));
  191. close(s);
  192. return -1;
  193. }
  194. close(s);
  195. return 0;
  196. }
  197. int
  198. set_dev_up(char *dev)
  199. {
  200. u_int mask = 0, flags = 0;
  201. mask |= IFF_UP;
  202. flags |= IFF_UP;
  203. return set_flags(dev, flags, mask);
  204. }
  205. int
  206. set_dev_down(char *dev)
  207. {
  208. u_int mask = 0, flags = 0;
  209. mask |= IFF_UP;
  210. flags &= ~IFF_UP;
  211. return set_flags(dev, flags, mask);
  212. }
  213. /*
  214. * set_all_ifs: for all the `ifs_n' interfaces present in the `ifs' array, it
  215. * calls the `set_func' functions, passing as argument ifs[i].dev_name.
  216. * (All the above set_* functions can be used as `set_func').
  217. * It returns the sum of all each return code, of set_func, therefore if it
  218. * returns a negative value, some `set_func' gave an error.
  219. */
  220. int
  221. set_all_ifs(interface * ifs, int ifs_n, int (*set_func) (char *dev))
  222. {
  223. int i, ret = 0;
  224. for (i = 0; i < ifs_n; i++)
  225. ret += set_func(ifs[i].dev_name);
  226. return ret;
  227. }
  228. /*
  229. * if_init_all: it initializes all the `ifs_n'# interfaces present in the
  230. * `ifs' array. If `ifs_n' is zero it gets all the current up interfaces and
  231. * stores them in `new_ifs', updating the `new_ifs_n' counter too. Then it
  232. * initializes them.
  233. * In the `new_ifs' array, which must be at least big as the `ids' array, it
  234. * stores all the initialized interfaces, updating the `new_ifs_n' counter.
  235. * On error -1 is returned.
  236. */
  237. int
  238. if_init_all(char *ifs_name[MAX_INTERFACES], int ifs_n,
  239. interface * new_ifs, int *new_ifs_n)
  240. {
  241. struct rtnl_handle rth;
  242. int ret = 0, i, n;
  243. if (rtnl_open(&rth, 0) < 0) {
  244. error("Cannot open the rtnetlink socket to talk to the kernel's "
  245. "soul");
  246. return -1;
  247. }
  248. ll_init_map(&rth);
  249. if (!ifs_n) {
  250. ret = get_all_up_ifs(new_ifs, MAX_INTERFACES);
  251. if (!ret)
  252. return -1;
  253. *new_ifs_n = ret;
  254. } else {
  255. for (i = 0, n = 0; i < ifs_n; i++) {
  256. new_ifs[n].dev_idx = ll_name_to_index(ifs_name[n]);
  257. if (!new_ifs[n].dev_idx) {
  258. error("Cannot initialize the %s interface. "
  259. "Ignoring it", ifs_name[n]);
  260. continue;
  261. }
  262. strncpy(new_ifs[n].dev_name, ifs_name[n], IFNAMSIZ);
  263. n++;
  264. }
  265. if (!n)
  266. return -1;
  267. *new_ifs_n = n;
  268. }
  269. if (set_all_ifs(new_ifs, *new_ifs_n, set_dev_up) < 0)
  270. return -1;
  271. rtnl_close(&rth);
  272. return ret;
  273. }
  274. void
  275. if_close_all(void)
  276. {
  277. #if 0
  278. /* XXX: disabled for now, it is buggy */
  279. ll_free_index();
  280. #endif
  281. }
  282. /*
  283. * set_dev_ip: Assign the given `ip' to the interface named `dev'
  284. * On success 0 is returned, -1 otherwise.
  285. */
  286. int
  287. set_dev_ip(inet_prefix ip, char *dev)
  288. {
  289. int s = -1;
  290. if (ip.family == AF_INET) {
  291. struct ifreq req;
  292. if ((s = new_socket(AF_INET)) < 0) {
  293. error("Error while setting \"%s\" ip: Cannot open socket",
  294. dev);
  295. return -1;
  296. }
  297. strncpy(req.ifr_name, dev, IFNAMSIZ);
  298. inet_to_sockaddr(&ip, 0, &req.ifr_addr, 0);
  299. if (ioctl(s, SIOCSIFADDR, &req)) {
  300. error("Error while setting \"%s\" ip: %s", dev,
  301. strerror(errno));
  302. close(s);
  303. return -1;
  304. }
  305. } else if (ip.family == AF_INET6) {
  306. struct in6_ifreq req6;
  307. struct sockaddr_in6 sin6;
  308. struct sockaddr *sa = (struct sockaddr *) &sin6;
  309. if ((s = new_socket(AF_INET6)) < 0) {
  310. error("Error while setting \"%s\" ip: Cannot open socket",
  311. dev);
  312. return -1;
  313. }
  314. req6.ifr6_ifindex = ll_name_to_index(dev);
  315. req6.ifr6_prefixlen = 0;
  316. inet_to_sockaddr(&ip, 0, sa, 0);
  317. memcpy(&req6.ifr6_addr, sin6.sin6_addr.s6_addr32, ip.len);
  318. if (ioctl(s, SIOCSIFADDR, &req6)) {
  319. error("Error while setting \"%s\" ip: %s", dev,
  320. strerror(errno));
  321. close(s);
  322. return -1;
  323. }
  324. }
  325. close(s);
  326. return 0;
  327. }
  328. /*
  329. * set_all_dev_ip: it sets the given `ip' to all the `ifs_n'# interfaces
  330. * present in the `ifs' array.
  331. * On error -1 is returned.
  332. */
  333. int
  334. set_all_dev_ip(inet_prefix ip, interface * ifs, int ifs_n)
  335. {
  336. int i, ret = 0;
  337. for (i = 0; i < ifs_n; i++)
  338. ret += set_dev_ip(ip, ifs[i].dev_name);
  339. return ret;
  340. }
  341. /*
  342. * get_dev_ip: fetches the ip currently assigned to the interface named `dev'
  343. * and stores it to `ip'.
  344. * On success 0 is returned, -1 otherwise.
  345. */
  346. int
  347. get_dev_ip(inet_prefix * ip, int family, char *dev)
  348. {
  349. int s = -1;
  350. int ret = 0;
  351. setzero(ip, sizeof(inet_prefix));
  352. if ((s = new_socket(family)) < 0) {
  353. error("Error while setting \"%s\" ip: Cannot open socket", dev);
  354. return -1;
  355. }
  356. if (family == AF_INET) {
  357. struct ifreq req;
  358. strncpy(req.ifr_name, dev, IFNAMSIZ);
  359. req.ifr_addr.sa_family = family;
  360. if (ioctl(s, SIOCGIFADDR, &req))
  361. ERROR_FINISH(ret, -1, finish);
  362. sockaddr_to_inet(&req.ifr_addr, ip, 0);
  363. } else if (family == AF_INET6) {
  364. struct in6_ifreq req6;
  365. /*
  366. * XXX: NOT TESTED
  367. */
  368. req6.ifr6_ifindex = ll_name_to_index(dev);
  369. req6.ifr6_prefixlen = 0;
  370. if (ioctl(s, SIOCGIFADDR, &req6))
  371. ERROR_FINISH(ret, -1, finish);
  372. inet_setip(ip, (u_int *) & req6.ifr6_addr, family);
  373. }
  374. finish:
  375. if (s != -1)
  376. close(s);
  377. return ret;
  378. }
  379. /*
  380. * All the code below this point is ripped from iproute2/iproute.c
  381. * written by Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>.
  382. *
  383. * Modified lightly
  384. */
  385. static int
  386. flush_update(void)
  387. {
  388. if (rtnl_send(filter.rth, filter.flushb, filter.flushp) < 0) {
  389. error("Failed to send flush request: %s", strerror(errno));
  390. return -1;
  391. }
  392. filter.flushp = 0;
  393. return 0;
  394. }
  395. int
  396. print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
  397. void *arg)
  398. {
  399. struct ifaddrmsg *ifa = NLMSG_DATA(n);
  400. int len = n->nlmsg_len;
  401. struct rtattr *rta_tb[IFA_MAX + 1];
  402. char b1[64];
  403. if (n->nlmsg_type != RTM_NEWADDR && n->nlmsg_type != RTM_DELADDR)
  404. return 0;
  405. len -= NLMSG_LENGTH(sizeof(*ifa));
  406. if (len < 0) {
  407. error("BUG: wrong nlmsg len %d\n", len);
  408. return -1;
  409. }
  410. if (filter.flushb && n->nlmsg_type != RTM_NEWADDR)
  411. return 0;
  412. parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(ifa),
  413. n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
  414. if (!rta_tb[IFA_LOCAL])
  415. rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
  416. if (!rta_tb[IFA_ADDRESS])
  417. rta_tb[IFA_ADDRESS] = rta_tb[IFA_LOCAL];
  418. if (filter.ifindex && filter.ifindex != ifa->ifa_index)
  419. return 0;
  420. if ((filter.scope ^ ifa->ifa_scope) & filter.scopemask)
  421. return 0;
  422. if ((filter.flags ^ ifa->ifa_flags) & filter.flagmask)
  423. return 0;
  424. if (filter.label) {
  425. const char *label;
  426. if (rta_tb[IFA_LABEL])
  427. label = RTA_DATA(rta_tb[IFA_LABEL]);
  428. else
  429. label = ll_idx_n2a(ifa->ifa_index, b1);
  430. if (fnmatch(filter.label, label, 0) != 0)
  431. return 0;
  432. }
  433. if (filter.pfx.family) {
  434. if (rta_tb[IFA_LOCAL]) {
  435. inet_prefix dst;
  436. setzero(&dst, sizeof(dst));
  437. dst.family = ifa->ifa_family;
  438. memcpy(&dst.data, RTA_DATA(rta_tb[IFA_LOCAL]),
  439. RTA_PAYLOAD(rta_tb[IFA_LOCAL]));
  440. if (inet_addr_match(&dst, &filter.pfx, filter.pfx.bits))
  441. return 0;
  442. }
  443. }
  444. if (filter.flushb) {
  445. struct nlmsghdr *fn;
  446. if (NLMSG_ALIGN(filter.flushp) + n->nlmsg_len > filter.flushe) {
  447. if (flush_update())
  448. return -1;
  449. }
  450. fn = (struct nlmsghdr *) (filter.flushb +
  451. NLMSG_ALIGN(filter.flushp));
  452. memcpy(fn, n, n->nlmsg_len);
  453. fn->nlmsg_type = RTM_DELADDR;
  454. fn->nlmsg_flags = NLM_F_REQUEST;
  455. fn->nlmsg_seq = ++filter.rth->seq;
  456. filter.flushp = (((char *) fn) + n->nlmsg_len) - filter.flushb;
  457. filter.flushed++;
  458. }
  459. return 0;
  460. }
  461. struct nlmsg_list {
  462. struct nlmsg_list *next;
  463. struct nlmsghdr h;
  464. };
  465. static int
  466. store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
  467. {
  468. struct nlmsg_list **linfo = (struct nlmsg_list **) arg;
  469. struct nlmsg_list *h;
  470. struct nlmsg_list **lp;
  471. h = malloc(n->nlmsg_len + sizeof(void *));
  472. if (h == NULL)
  473. return -1;
  474. memcpy(&h->h, n, n->nlmsg_len);
  475. h->next = NULL;
  476. for (lp = linfo; *lp; lp = &(*lp)->next) /* NOTHING */
  477. ;
  478. *lp = h;
  479. ll_remember_index((struct sockaddr_nl *) who, n, NULL);
  480. return 0;
  481. }
  482. int
  483. ip_addr_flush(int family, char *dev, int scope)
  484. {
  485. struct nlmsg_list *linfo = NULL;
  486. struct rtnl_handle rth;
  487. char *filter_dev = NULL;
  488. setzero(&filter, sizeof(filter));
  489. filter.showqueue = 1;
  490. filter.family = family;
  491. filter_dev = dev;
  492. if (rtnl_open(&rth, 0) < 0)
  493. return -1;
  494. if (rtnl_wilddump_request(&rth, family, RTM_GETLINK) < 0) {
  495. error("Cannot send dump request: %s", strerror(errno));
  496. return -1;
  497. }
  498. if (rtnl_dump_filter(&rth, store_nlmsg, &linfo, NULL, NULL) < 0) {
  499. error("Dump terminated");
  500. return -1;
  501. }
  502. filter.ifindex = ll_name_to_index(filter_dev);
  503. if (filter.ifindex <= 0) {
  504. error("Device \"%s\" does not exist.", filter_dev);
  505. return -1;
  506. }
  507. int round = 0;
  508. char flushb[4096 - 512];
  509. filter.flushb = flushb;
  510. filter.flushp = 0;
  511. filter.flushe = sizeof(flushb);
  512. filter.rth = &rth;
  513. filter.scopemask = -1;
  514. filter.scope = scope;
  515. for (;;) {
  516. if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
  517. error("Cannot send dump request: %s", strerror(errno));
  518. return -1;
  519. }
  520. filter.flushed = 0;
  521. if (rtnl_dump_filter(&rth, print_addrinfo, stdout, NULL, NULL) < 0) {
  522. error("Flush terminated: %s", errno);
  523. return -1;
  524. }
  525. if (filter.flushed == 0)
  526. return 0;
  527. round++;
  528. if (flush_update() < 0)
  529. return -1;
  530. }
  531. rtnl_close(&rth);
  532. }
  533. int
  534. ip_addr_flush_all_ifs(interface * ifs, int ifs_n, int family, int scope)
  535. {
  536. int i, ret = 0;
  537. for (i = 0; i < ifs_n; i++)
  538. ret += ip_addr_flush(family, ifs[i].dev_name, scope);
  539. return ret;
  540. }