rt_ioctl.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /*
  2. * kernel routing table update by ioctl().
  3. * Copyright (C) 1997, 98 Kunihiro Ishiguro
  4. *
  5. * This file is part of GNU Zebra.
  6. *
  7. * GNU Zebra is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation; either version 2, or (at your option) any
  10. * later version.
  11. *
  12. * GNU Zebra is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with GNU Zebra; see the file COPYING. If not, write to the Free
  19. * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  20. * 02111-1307, USA.
  21. */
  22. #include <zebra.h>
  23. #include "prefix.h"
  24. #include "log.h"
  25. #include "if.h"
  26. #include "zebra/zserv.h"
  27. #include "zebra/rib.h"
  28. #include "zebra/debug.h"
  29. #include "zebra/rt.h"
  30. /* Initialize of kernel interface. There is no kernel communication
  31. support under ioctl(). So this is dummy stub function. */
  32. void
  33. kernel_init (void)
  34. {
  35. return;
  36. }
  37. /* Dummy function of routing socket. */
  38. static void
  39. kernel_read (int sock)
  40. {
  41. return;
  42. }
  43. #if 0
  44. /* Initialization prototype of struct sockaddr_in. */
  45. static struct sockaddr_in sin_proto =
  46. {
  47. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  48. sizeof (struct sockaddr_in),
  49. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  50. AF_INET, 0, {0}, {0}
  51. };
  52. #endif /* 0 */
  53. /* Solaris has ortentry. */
  54. #ifdef HAVE_OLD_RTENTRY
  55. #define rtentry ortentry
  56. #endif /* HAVE_OLD_RTENTRY */
  57. /* Interface to ioctl route message. */
  58. int
  59. kernel_add_route (struct prefix_ipv4 *dest, struct in_addr *gate,
  60. int index, int flags)
  61. {
  62. int ret;
  63. int sock;
  64. struct rtentry rtentry;
  65. struct sockaddr_in sin_dest, sin_mask, sin_gate;
  66. memset (&rtentry, 0, sizeof (struct rtentry));
  67. /* Make destination. */
  68. memset (&sin_dest, 0, sizeof (struct sockaddr_in));
  69. sin_dest.sin_family = AF_INET;
  70. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  71. sin_dest.sin_len = sizeof (struct sockaddr_in);
  72. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  73. sin_dest.sin_addr = dest->prefix;
  74. /* Make gateway. */
  75. if (gate)
  76. {
  77. memset (&sin_gate, 0, sizeof (struct sockaddr_in));
  78. sin_gate.sin_family = AF_INET;
  79. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  80. sin_gate.sin_len = sizeof (struct sockaddr_in);
  81. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  82. sin_gate.sin_addr = *gate;
  83. }
  84. memset (&sin_mask, 0, sizeof (struct sockaddr_in));
  85. sin_mask.sin_family = AF_INET;
  86. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  87. sin_gate.sin_len = sizeof (struct sockaddr_in);
  88. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  89. masklen2ip (dest->prefixlen, &sin_mask.sin_addr);
  90. /* Set destination address, mask and gateway.*/
  91. memcpy (&rtentry.rt_dst, &sin_dest, sizeof (struct sockaddr_in));
  92. if (gate)
  93. memcpy (&rtentry.rt_gateway, &sin_gate, sizeof (struct sockaddr_in));
  94. #ifndef SUNOS_5
  95. memcpy (&rtentry.rt_genmask, &sin_mask, sizeof (struct sockaddr_in));
  96. #endif /* SUNOS_5 */
  97. /* Routing entry flag set. */
  98. if (dest->prefixlen == 32)
  99. rtentry.rt_flags |= RTF_HOST;
  100. if (gate && gate->s_addr != INADDR_ANY)
  101. rtentry.rt_flags |= RTF_GATEWAY;
  102. rtentry.rt_flags |= RTF_UP;
  103. /* Additional flags */
  104. rtentry.rt_flags |= flags;
  105. /* For tagging route. */
  106. /* rtentry.rt_flags |= RTF_DYNAMIC; */
  107. /* Open socket for ioctl. */
  108. sock = socket (AF_INET, SOCK_DGRAM, 0);
  109. if (sock < 0)
  110. {
  111. zlog_warn ("can't make socket\n");
  112. return -1;
  113. }
  114. /* Send message by ioctl(). */
  115. ret = ioctl (sock, SIOCADDRT, &rtentry);
  116. if (ret < 0)
  117. {
  118. switch (errno)
  119. {
  120. case EEXIST:
  121. close (sock);
  122. return ZEBRA_ERR_RTEXIST;
  123. break;
  124. case ENETUNREACH:
  125. close (sock);
  126. return ZEBRA_ERR_RTUNREACH;
  127. break;
  128. case EPERM:
  129. close (sock);
  130. return ZEBRA_ERR_EPERM;
  131. break;
  132. }
  133. close (sock);
  134. zlog_warn ("write : %s (%d)", safe_strerror (errno), errno);
  135. return 1;
  136. }
  137. close (sock);
  138. return ret;
  139. }
  140. /* Interface to ioctl route message. */
  141. static int
  142. kernel_ioctl_ipv4 (u_long cmd, struct prefix *p, struct rib *rib, int family)
  143. {
  144. int ret;
  145. int sock;
  146. struct rtentry rtentry;
  147. struct sockaddr_in sin_dest, sin_mask, sin_gate;
  148. struct nexthop *nexthop, *tnexthop;
  149. int recursing;
  150. int nexthop_num = 0;
  151. struct interface *ifp;
  152. memset (&rtentry, 0, sizeof (struct rtentry));
  153. /* Make destination. */
  154. memset (&sin_dest, 0, sizeof (struct sockaddr_in));
  155. sin_dest.sin_family = AF_INET;
  156. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  157. sin_dest.sin_len = sizeof (struct sockaddr_in);
  158. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  159. sin_dest.sin_addr = p->u.prefix4;
  160. if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))
  161. {
  162. SET_FLAG (rtentry.rt_flags, RTF_REJECT);
  163. if (cmd == SIOCADDRT)
  164. for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
  165. {
  166. /* We shouldn't encounter recursive nexthops on discard routes,
  167. * but it is probably better to handle that case correctly anyway.
  168. */
  169. if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  170. continue;
  171. SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
  172. }
  173. goto skip;
  174. }
  175. memset (&sin_gate, 0, sizeof (struct sockaddr_in));
  176. /* Make gateway. */
  177. for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
  178. {
  179. if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  180. continue;
  181. if ((cmd == SIOCADDRT
  182. && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  183. || (cmd == SIOCDELRT
  184. && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
  185. {
  186. if (nexthop->type == NEXTHOP_TYPE_IPV4 ||
  187. nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
  188. {
  189. sin_gate.sin_family = AF_INET;
  190. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  191. sin_gate.sin_len = sizeof (struct sockaddr_in);
  192. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  193. sin_gate.sin_addr = nexthop->gate.ipv4;
  194. rtentry.rt_flags |= RTF_GATEWAY;
  195. }
  196. if (nexthop->type == NEXTHOP_TYPE_IFINDEX
  197. || nexthop->type == NEXTHOP_TYPE_IFNAME)
  198. {
  199. ifp = if_lookup_by_index (nexthop->ifindex);
  200. if (ifp)
  201. rtentry.rt_dev = ifp->name;
  202. else
  203. return -1;
  204. }
  205. if (cmd == SIOCADDRT)
  206. SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
  207. nexthop_num++;
  208. break;
  209. }
  210. }
  211. /* If there is no useful nexthop then return. */
  212. if (nexthop_num == 0)
  213. {
  214. if (IS_ZEBRA_DEBUG_KERNEL)
  215. zlog_debug ("netlink_route_multipath(): No useful nexthop.");
  216. return 0;
  217. }
  218. skip:
  219. memset (&sin_mask, 0, sizeof (struct sockaddr_in));
  220. sin_mask.sin_family = AF_INET;
  221. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  222. sin_mask.sin_len = sizeof (struct sockaddr_in);
  223. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  224. masklen2ip (p->prefixlen, &sin_mask.sin_addr);
  225. /* Set destination address, mask and gateway.*/
  226. memcpy (&rtentry.rt_dst, &sin_dest, sizeof (struct sockaddr_in));
  227. if (rtentry.rt_flags & RTF_GATEWAY)
  228. memcpy (&rtentry.rt_gateway, &sin_gate, sizeof (struct sockaddr_in));
  229. #ifndef SUNOS_5
  230. memcpy (&rtentry.rt_genmask, &sin_mask, sizeof (struct sockaddr_in));
  231. #endif /* SUNOS_5 */
  232. /* Metric. It seems metric minus one value is installed... */
  233. rtentry.rt_metric = rib->metric;
  234. /* Routing entry flag set. */
  235. if (p->prefixlen == 32)
  236. rtentry.rt_flags |= RTF_HOST;
  237. rtentry.rt_flags |= RTF_UP;
  238. /* Additional flags */
  239. /* rtentry.rt_flags |= flags; */
  240. /* For tagging route. */
  241. /* rtentry.rt_flags |= RTF_DYNAMIC; */
  242. /* Open socket for ioctl. */
  243. sock = socket (AF_INET, SOCK_DGRAM, 0);
  244. if (sock < 0)
  245. {
  246. zlog_warn ("can't make socket\n");
  247. return -1;
  248. }
  249. /* Send message by ioctl(). */
  250. ret = ioctl (sock, cmd, &rtentry);
  251. if (ret < 0)
  252. {
  253. switch (errno)
  254. {
  255. case EEXIST:
  256. close (sock);
  257. return ZEBRA_ERR_RTEXIST;
  258. break;
  259. case ENETUNREACH:
  260. close (sock);
  261. return ZEBRA_ERR_RTUNREACH;
  262. break;
  263. case EPERM:
  264. close (sock);
  265. return ZEBRA_ERR_EPERM;
  266. break;
  267. }
  268. close (sock);
  269. zlog_warn ("write : %s (%d)", safe_strerror (errno), errno);
  270. return ret;
  271. }
  272. close (sock);
  273. return ret;
  274. }
  275. int
  276. kernel_add_ipv4 (struct prefix *p, struct rib *rib)
  277. {
  278. return kernel_ioctl_ipv4 (SIOCADDRT, p, rib, AF_INET);
  279. }
  280. int
  281. kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
  282. {
  283. return kernel_ioctl_ipv4 (SIOCDELRT, p, rib, AF_INET);
  284. }
  285. #ifdef HAVE_IPV6
  286. /* Below is hack for GNU libc definition and Linux 2.1.X header. */
  287. #undef RTF_DEFAULT
  288. #undef RTF_ADDRCONF
  289. #include <asm/types.h>
  290. #if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
  291. /* struct in6_rtmsg will be declared in net/route.h. */
  292. #else
  293. #include <linux/ipv6_route.h>
  294. #endif
  295. static int
  296. kernel_ioctl_ipv6 (u_long type, struct prefix_ipv6 *dest, struct in6_addr *gate,
  297. int index, int flags)
  298. {
  299. int ret;
  300. int sock;
  301. struct in6_rtmsg rtm;
  302. memset (&rtm, 0, sizeof (struct in6_rtmsg));
  303. rtm.rtmsg_flags |= RTF_UP;
  304. rtm.rtmsg_metric = 1;
  305. memcpy (&rtm.rtmsg_dst, &dest->prefix, sizeof (struct in6_addr));
  306. rtm.rtmsg_dst_len = dest->prefixlen;
  307. /* We need link local index. But this should be done caller...
  308. if (IN6_IS_ADDR_LINKLOCAL(&rtm.rtmsg_gateway))
  309. {
  310. index = if_index_address (&rtm.rtmsg_gateway);
  311. rtm.rtmsg_ifindex = index;
  312. }
  313. else
  314. rtm.rtmsg_ifindex = 0;
  315. */
  316. rtm.rtmsg_flags |= RTF_GATEWAY;
  317. /* For tagging route. */
  318. /* rtm.rtmsg_flags |= RTF_DYNAMIC; */
  319. memcpy (&rtm.rtmsg_gateway, gate, sizeof (struct in6_addr));
  320. if (index)
  321. rtm.rtmsg_ifindex = index;
  322. else
  323. rtm.rtmsg_ifindex = 0;
  324. rtm.rtmsg_metric = 1;
  325. sock = socket (AF_INET6, SOCK_DGRAM, 0);
  326. if (sock < 0)
  327. {
  328. zlog_warn ("can't make socket\n");
  329. return -1;
  330. }
  331. /* Send message via ioctl. */
  332. ret = ioctl (sock, type, &rtm);
  333. if (ret < 0)
  334. {
  335. zlog_warn ("can't %s ipv6 route: %s\n", type == SIOCADDRT ? "add" : "delete",
  336. safe_strerror(errno));
  337. ret = errno;
  338. close (sock);
  339. return ret;
  340. }
  341. close (sock);
  342. return ret;
  343. }
  344. static int
  345. kernel_ioctl_ipv6_multipath (u_long cmd, struct prefix *p, struct rib *rib,
  346. int family)
  347. {
  348. int ret;
  349. int sock;
  350. struct in6_rtmsg rtm;
  351. struct nexthop *nexthop, *tnexthop;
  352. int recursing;
  353. int nexthop_num = 0;
  354. memset (&rtm, 0, sizeof (struct in6_rtmsg));
  355. rtm.rtmsg_flags |= RTF_UP;
  356. rtm.rtmsg_metric = rib->metric;
  357. memcpy (&rtm.rtmsg_dst, &p->u.prefix, sizeof (struct in6_addr));
  358. rtm.rtmsg_dst_len = p->prefixlen;
  359. /* We need link local index. But this should be done caller...
  360. if (IN6_IS_ADDR_LINKLOCAL(&rtm.rtmsg_gateway))
  361. {
  362. index = if_index_address (&rtm.rtmsg_gateway);
  363. rtm.rtmsg_ifindex = index;
  364. }
  365. else
  366. rtm.rtmsg_ifindex = 0;
  367. */
  368. rtm.rtmsg_flags |= RTF_GATEWAY;
  369. /* For tagging route. */
  370. /* rtm.rtmsg_flags |= RTF_DYNAMIC; */
  371. /* Make gateway. */
  372. for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
  373. {
  374. if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  375. continue;
  376. if ((cmd == SIOCADDRT
  377. && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  378. || (cmd == SIOCDELRT
  379. && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
  380. {
  381. if (nexthop->type == NEXTHOP_TYPE_IPV6
  382. || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
  383. || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
  384. {
  385. memcpy (&rtm.rtmsg_gateway, &nexthop->gate.ipv6,
  386. sizeof (struct in6_addr));
  387. }
  388. if (nexthop->type == NEXTHOP_TYPE_IFINDEX
  389. || nexthop->type == NEXTHOP_TYPE_IFNAME
  390. || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
  391. || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
  392. rtm.rtmsg_ifindex = nexthop->ifindex;
  393. else
  394. rtm.rtmsg_ifindex = 0;
  395. if (cmd == SIOCADDRT)
  396. SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
  397. nexthop_num++;
  398. break;
  399. }
  400. }
  401. /* If there is no useful nexthop then return. */
  402. if (nexthop_num == 0)
  403. {
  404. if (IS_ZEBRA_DEBUG_KERNEL)
  405. zlog_debug ("netlink_route_multipath(): No useful nexthop.");
  406. return 0;
  407. }
  408. sock = socket (AF_INET6, SOCK_DGRAM, 0);
  409. if (sock < 0)
  410. {
  411. zlog_warn ("can't make socket\n");
  412. return -1;
  413. }
  414. /* Send message via ioctl. */
  415. ret = ioctl (sock, cmd, &rtm);
  416. if (ret < 0)
  417. {
  418. zlog_warn ("can't %s ipv6 route: %s\n",
  419. cmd == SIOCADDRT ? "add" : "delete",
  420. safe_strerror(errno));
  421. ret = errno;
  422. close (sock);
  423. return ret;
  424. }
  425. close (sock);
  426. return ret;
  427. }
  428. int
  429. kernel_add_ipv6 (struct prefix *p, struct rib *rib)
  430. {
  431. return kernel_ioctl_ipv6_multipath (SIOCADDRT, p, rib, AF_INET6);
  432. }
  433. int
  434. kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
  435. {
  436. return kernel_ioctl_ipv6_multipath (SIOCDELRT, p, rib, AF_INET6);
  437. }
  438. /* Delete IPv6 route from the kernel. */
  439. int
  440. kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
  441. unsigned int index, int flags, int table)
  442. {
  443. return kernel_ioctl_ipv6 (SIOCDELRT, dest, gate, index, flags);
  444. }
  445. #endif /* HAVE_IPV6 */