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.

iptunnel.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  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. * --
  19. * This code derives from iproute2/iprule.c, it was modified to fit in
  20. * Netsukuku.
  21. *
  22. * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  23. * Changes:
  24. * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses
  25. * Rani Assaf <rani@magic.metawire.com> 980930: do not allow key for ipip/sit
  26. * Phil Karn <karn@ka9q.ampr.org> 990408: "pmtudisc" flag
  27. */
  28. #include "includes.h"
  29. #include "inet.h"
  30. #include <linux/ip.h>
  31. #include <linux/if_tunnel.h>
  32. #include "libnetlink.h"
  33. #include "libnetlink.h"
  34. #include "ll_map.h"
  35. #include "krnl_route.h"
  36. #include "route.h"
  37. #include "iptunnel.h"
  38. #include "common.h"
  39. static int do_add(int cmd, inet_prefix * remote, inet_prefix * local,
  40. char *dev, char *tunl_prefix, int tunl_number);
  41. int do_del(inet_prefix * remote, inet_prefix * local, char *dev,
  42. char *tunl_prefix, int tunl_number);
  43. int
  44. tunnel_add(inet_prefix * remote, inet_prefix * local, char *dev,
  45. char *tunl_prefix, int tunl_number)
  46. {
  47. return do_add(SIOCADDTUNNEL, remote, local, dev, tunl_prefix,
  48. tunl_number);
  49. }
  50. int
  51. tunnel_change(inet_prefix * remote, inet_prefix * local, char *dev,
  52. char *tunl_prefix, int tunl_number)
  53. {
  54. return do_add(SIOCGETTUNNEL, remote, local, dev, tunl_prefix,
  55. tunl_number);
  56. }
  57. int
  58. tunnel_del(inet_prefix * remote, inet_prefix * local, char *dev,
  59. char *tunl_prefix, int tunl_number)
  60. {
  61. return do_del(remote, local, dev, tunl_prefix, tunl_number);
  62. }
  63. static int
  64. do_ioctl_get_ifindex(const char *dev)
  65. {
  66. struct ifreq ifr;
  67. int fd;
  68. int err;
  69. strncpy(ifr.ifr_name, dev, IFNAMSIZ);
  70. fd = socket(AF_INET, SOCK_DGRAM, 0);
  71. err = ioctl(fd, SIOCGIFINDEX, &ifr);
  72. if (err) {
  73. error(ERROR_MSG "ioctl: %s", ERROR_POS, strerror(errno));
  74. return 0;
  75. }
  76. close(fd);
  77. return ifr.ifr_ifindex;
  78. }
  79. #if 0
  80. static int
  81. do_ioctl_get_iftype(const char *dev)
  82. {
  83. struct ifreq ifr;
  84. int fd;
  85. int err;
  86. strncpy(ifr.ifr_name, dev, IFNAMSIZ);
  87. fd = socket(AF_INET, SOCK_DGRAM, 0);
  88. err = ioctl(fd, SIOCGIFHWADDR, &ifr);
  89. if (err) {
  90. error(ERROR_MSG "ioctl: %s", ERROR_POS, strerror(errno));
  91. return -1;
  92. }
  93. close(fd);
  94. return ifr.ifr_addr.sa_family;
  95. }
  96. static char *
  97. do_ioctl_get_ifname(int idx)
  98. {
  99. static struct ifreq ifr;
  100. int fd;
  101. int err;
  102. ifr.ifr_ifindex = idx;
  103. fd = socket(AF_INET, SOCK_DGRAM, 0);
  104. err = ioctl(fd, SIOCGIFNAME, &ifr);
  105. if (err) {
  106. error(ERROR_MSG "ioctl: %s", ERROR_POS, strerror(errno));
  107. return NULL;
  108. }
  109. close(fd);
  110. return ifr.ifr_name;
  111. }
  112. #endif
  113. static int
  114. do_get_ioctl(const char *basedev, struct ip_tunnel_parm *p)
  115. {
  116. struct ifreq ifr;
  117. int fd;
  118. int err;
  119. strncpy(ifr.ifr_name, basedev, IFNAMSIZ);
  120. ifr.ifr_ifru.ifru_data = (void *) p;
  121. fd = socket(AF_INET, SOCK_DGRAM, 0);
  122. err = ioctl(fd, SIOCGETTUNNEL, &ifr);
  123. /*
  124. * if (err)
  125. * error(ERROR_MSG "ioctl: %s",ERROR_POS, strerror(errno));
  126. */
  127. close(fd);
  128. return err;
  129. }
  130. static int
  131. do_add_ioctl(int cmd, const char *basedev, struct ip_tunnel_parm *p)
  132. {
  133. struct ifreq ifr;
  134. int fd;
  135. int err;
  136. if (cmd == SIOCCHGTUNNEL && p->name[0])
  137. strncpy(ifr.ifr_name, p->name, IFNAMSIZ);
  138. else
  139. strncpy(ifr.ifr_name, basedev, IFNAMSIZ);
  140. ifr.ifr_ifru.ifru_data = (void *) p;
  141. fd = socket(AF_INET, SOCK_DGRAM, 0);
  142. err = ioctl(fd, cmd, &ifr);
  143. error
  144. ("Socket File Descriptor Is: %i cmd is: %i err is: %i ifr is: %s Errno is: %d",
  145. fd, cmd, err, &ifr, errno);
  146. if (err)
  147. error(ERROR_MSG "ioctl: %s", ERROR_POS, strerror(errno));
  148. close(fd);
  149. return err;
  150. }
  151. static int
  152. do_del_ioctl(const char *basedev, struct ip_tunnel_parm *p)
  153. {
  154. struct ifreq ifr;
  155. int fd;
  156. int err;
  157. if (p->name[0])
  158. strncpy(ifr.ifr_name, p->name, IFNAMSIZ);
  159. else
  160. strncpy(ifr.ifr_name, basedev, IFNAMSIZ);
  161. ifr.ifr_ifru.ifru_data = (void *) p;
  162. fd = socket(AF_INET, SOCK_DGRAM, 0);
  163. err = ioctl(fd, SIOCDELTUNNEL, &ifr);
  164. if (err)
  165. error(ERROR_MSG "ioctl: %s", ERROR_POS, strerror(errno));
  166. close(fd);
  167. return err;
  168. }
  169. /*
  170. * fill_tunnel_parm: fills the `p' struct.
  171. * `remote' and `local' must be in host order
  172. */
  173. static int
  174. fill_tunnel_parm(int cmd, inet_prefix * remote, inet_prefix * local,
  175. char *dev, char *tunl_prefix, int tunl_number,
  176. struct ip_tunnel_parm *p)
  177. {
  178. char medium[IFNAMSIZ];
  179. memset(p, 0, sizeof(*p));
  180. memset(&medium, 0, sizeof(medium));
  181. p->iph.version = 4;
  182. p->iph.ihl = 5;
  183. #ifndef IP_DF
  184. #define IP_DF 0x4000 /* Flag: "Don't Fragment" */
  185. #endif
  186. p->iph.frag_off = htons(IP_DF);
  187. p->iph.protocol = IPPROTO_IPIP;
  188. if (remote)
  189. p->iph.daddr = htonl(remote->data[0]);
  190. if (local)
  191. p->iph.saddr = htonl(local->data[0]);
  192. if (dev)
  193. strncpy(medium, dev, IFNAMSIZ - 1);
  194. sprintf(p->name, TUNL_STRING, TUNL_N(tunl_prefix, tunl_number));
  195. if (cmd == SIOCCHGTUNNEL) {
  196. /* Change the old tunnel */
  197. struct ip_tunnel_parm old_p;
  198. memset(&old_p, 0, sizeof(old_p));
  199. if (do_get_ioctl(p->name, &old_p))
  200. return -1;
  201. *p = old_p;
  202. }
  203. if (p->iph.protocol == IPPROTO_IPIP)
  204. if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY))
  205. fatal("Keys are not allowed with ipip and sit.");
  206. if (medium[0]) {
  207. p->link = do_ioctl_get_ifindex(medium);
  208. if (p->link == 0)
  209. return -1;
  210. }
  211. if (IN_MULTICAST(ntohl(p->iph.daddr)) && !p->iph.saddr)
  212. fatal("Broadcast tunnel requires a source address.");
  213. return 0;
  214. }
  215. /*
  216. * do_get: returns 1 if the tunnel named `dev' exists.
  217. */
  218. int
  219. do_get(char *dev)
  220. {
  221. struct ip_tunnel_parm old_p;
  222. memset(&old_p, 0, sizeof(old_p));
  223. if (do_get_ioctl(dev, &old_p))
  224. return 0;
  225. return 1;
  226. }
  227. static int
  228. do_add(int cmd, inet_prefix * remote, inet_prefix * local, char *dev,
  229. char *tunl_prefix, int tunl_number)
  230. {
  231. struct ip_tunnel_parm p;
  232. if (fill_tunnel_parm(cmd, remote, local, dev, tunl_prefix,
  233. tunl_number, &p) < 0)
  234. return -1;
  235. if (p.iph.ttl && p.iph.frag_off == 0)
  236. fatal("ttl != 0 and noptmudisc are incompatible");
  237. switch (p.iph.protocol) {
  238. case IPPROTO_IPIP:
  239. return do_add_ioctl(cmd, DEFAULT_TUNL_IF, &p);
  240. default:
  241. fatal("cannot determine tunnel mode (ipip, gre or sit)\n");
  242. }
  243. return -1;
  244. }
  245. int
  246. do_del(inet_prefix * remote, inet_prefix * local, char *dev,
  247. char *tunl_prefix, int tunl_number)
  248. {
  249. struct ip_tunnel_parm p;
  250. if (fill_tunnel_parm(SIOCDELTUNNEL, remote, local, dev, tunl_prefix,
  251. tunl_number, &p) < 0)
  252. return -1;
  253. switch (p.iph.protocol) {
  254. case IPPROTO_IPIP:
  255. return do_del_ioctl(DEFAULT_TUNL_IF, &p);
  256. default:
  257. return do_del_ioctl(p.name, &p);
  258. }
  259. return -1;
  260. }
  261. /*
  262. * tun_add_tunl: it adds in the `ifs' array a new struct which refers to
  263. * the tunnel "tunlX", where X is a number equal to `tunl'.
  264. */
  265. int
  266. tun_add_tunl(interface * ifs, char *tunl_prefix, u_char tunl_number)
  267. {
  268. char tunl_name[IFNAMSIZ];
  269. sprintf(tunl_name, TUNL_STRING, TUNL_N(tunl_prefix, tunl_number));
  270. strncpy(ifs->dev_name, tunl_name, IFNAMSIZ);
  271. if (!(ifs->dev_idx = do_ioctl_get_ifindex(tunl_name)))
  272. return -1;
  273. return 0;
  274. }
  275. /*
  276. * tun_del_tunl: it removes from the `ifs' array, which must have at least
  277. * MAX_TUNNEL_IFS members, the struct which refers the tunnel "tunlX", where X
  278. * is a number equal to `tunl'.
  279. * If no such struct is found, -1 is returned.
  280. */
  281. int
  282. tun_del_tunl(interface * ifs, char *tunl_prefix, u_char tunl_number)
  283. {
  284. char tunl_name[IFNAMSIZ];
  285. int i;
  286. sprintf(tunl_name, TUNL_STRING, TUNL_N(tunl_prefix, tunl_number));
  287. for (i = 0; i < MAX_TUNNEL_IFS; i++)
  288. if (!strncmp(ifs[i].dev_name, tunl_name, IFNAMSIZ)) {
  289. memset(&ifs[i], 0, sizeof(interface));
  290. return 0;
  291. }
  292. return -1;
  293. }
  294. void
  295. init_tunnels_ifs(void)
  296. {
  297. memset(tunnel_ifs, 0, sizeof(interface) * MAX_TUNNEL_IFS);
  298. }
  299. /*
  300. * first_free_tunnel_if: returns the position of the first member of the
  301. * `tunnel_ifs' array which isn't used yet.
  302. * If the whole array is full, -1 is returned.
  303. */
  304. int
  305. first_free_tunnel_if(void)
  306. {
  307. int i;
  308. for (i = 0; i < MAX_TUNNEL_IFS; i++)
  309. if (!*tunnel_ifs[i].dev_name && !tunnel_ifs[i].dev_idx)
  310. return i;
  311. return -1;
  312. }
  313. /*
  314. * set_tunnel_ip: it brings down and up and set the `tunl_ip' IP to the
  315. * "tunl`tunl_number'" tunnel device
  316. */
  317. int
  318. set_tunnel_ip(char *tunl_prefix, int tunl_number, inet_prefix * tunl_ip)
  319. {
  320. const char *ntop;
  321. ntop = inet_to_str(*tunl_ip);
  322. set_all_ifs(&tunnel_ifs[tunl_number], 1, set_dev_down);
  323. set_all_ifs(&tunnel_ifs[tunl_number], 1, set_dev_up);
  324. if (set_all_dev_ip(*tunl_ip, &tunnel_ifs[tunl_number], 1) < 0) {
  325. error("Cannot set the %s ip to " TUNL_STRING,
  326. ntop, TUNL_N(tunl_prefix, tunl_number));
  327. return -1;
  328. }
  329. return 0;
  330. }
  331. /*
  332. * add_tunnel_if: creates a new tunnel, adds it in the `tunnel_ifs' array, and
  333. * if `tunl_ip' isn't null, sets to the tunnel the IP `tunl_ip'.
  334. */
  335. int
  336. add_tunnel_if(inet_prefix * remote, inet_prefix * local, char *dev,
  337. char *tunl_prefix, int tunl_number, inet_prefix * tunl_ip)
  338. {
  339. char tunl_name[IFNAMSIZ];
  340. /*
  341. * tunl0 zero is a special tunnel, it cannot be created nor destroyed.
  342. * It's pure energy.
  343. */
  344. if (!strcmp(tunl_prefix, DEFAULT_TUNL_PREFIX) && !tunl_number)
  345. goto skip_krnl_add_tunl;
  346. if (tunnel_add(remote, local, dev, tunl_prefix, tunl_number) < 0) {
  347. error("Cannot add the \"" TUNL_STRING "\" tunnel",
  348. TUNL_N(tunl_prefix, tunl_number));
  349. return -1;
  350. }
  351. skip_krnl_add_tunl:
  352. if (tun_add_tunl(&tunnel_ifs[tunl_number], tunl_prefix, tunl_number) <
  353. 0)
  354. return -1;
  355. if (tunl_ip) {
  356. /*
  357. * ifconfig tunnel `tunl_ip' up
  358. */
  359. if (set_tunnel_ip(tunl_prefix, tunl_number, tunl_ip) < 0)
  360. return -1;
  361. /*
  362. * ip route append tunl_ip_subnet dev tunnel proto kernel \
  363. * scope link src `tunl_ip'
  364. */
  365. sprintf(tunl_name, TUNL_STRING, TUNL_N(tunl_prefix, tunl_number));
  366. rt_append_subnet_src(tunl_ip, tunl_name);
  367. if (route_rp_filter_all_dev(my_family, &tunnel_ifs[tunl_number],
  368. 1, 0) < 0)
  369. return -1;
  370. }
  371. return 0;
  372. }
  373. /*
  374. * del_tunnel_if: the inverse of add_tunnel_if() (see above)
  375. */
  376. int
  377. del_tunnel_if(inet_prefix * remote, inet_prefix * local, char *dev,
  378. char *tunl_prefix, int tunl_number)
  379. {
  380. /* tunl0 is a highlander */
  381. if (!strcmp(tunl_prefix, DEFAULT_TUNL_PREFIX) && !tunl_number)
  382. goto skip_krnl_del_tunl;
  383. if (tunnel_del(remote, local, dev, tunl_prefix, tunl_number) < 0) {
  384. error("Cannot delete the \"" TUNL_STRING "\" tunnel",
  385. TUNL_N(tunl_prefix, tunl_number));
  386. return -1;
  387. }
  388. skip_krnl_del_tunl:
  389. tun_del_tunl(tunnel_ifs, tunl_prefix, tunl_number);
  390. return 0;
  391. }
  392. void
  393. del_all_tunnel_ifs(inet_prefix * remote, inet_prefix * local, char *dev,
  394. char *tunl_prefix)
  395. {
  396. char tunl_name[IFNAMSIZ];
  397. int i;
  398. for (i = 0; i < MAX_TUNNEL_IFS; i++) {
  399. sprintf(tunl_name, TUNL_STRING, TUNL_N(tunl_prefix, i));
  400. if (do_get(tunl_name))
  401. del_tunnel_if(remote, local, 0, tunl_prefix, i);
  402. else
  403. break;
  404. }
  405. }