rt_socket.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. /*
  2. * Kernel routing table updates by routing socket.
  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 "if.h"
  24. #include "prefix.h"
  25. #include "sockunion.h"
  26. #include "log.h"
  27. #include "str.h"
  28. #include "privs.h"
  29. #include "zebra/debug.h"
  30. #include "zebra/rib.h"
  31. #include "zebra/rt.h"
  32. #include "zebra/kernel_socket.h"
  33. extern struct zebra_privs_t zserv_privs;
  34. /* kernel socket export */
  35. extern int rtm_write (int message, union sockunion *dest,
  36. union sockunion *mask, union sockunion *gate,
  37. unsigned int index, int zebra_flags, int metric);
  38. /* Adjust netmask socket length. Return value is a adjusted sin_len
  39. value. */
  40. static int
  41. sin_masklen (struct in_addr mask)
  42. {
  43. char *p, *lim;
  44. int len;
  45. struct sockaddr_in sin;
  46. if (mask.s_addr == 0)
  47. return sizeof (long);
  48. sin.sin_addr = mask;
  49. len = sizeof (struct sockaddr_in);
  50. lim = (char *) &sin.sin_addr;
  51. p = lim + sizeof (sin.sin_addr);
  52. while (*--p == 0 && p >= lim)
  53. len--;
  54. return len;
  55. }
  56. /* Interface between zebra message and rtm message. */
  57. static int
  58. kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib, int family)
  59. {
  60. struct sockaddr_in *mask = NULL;
  61. struct sockaddr_in sin_dest, sin_mask, sin_gate;
  62. struct nexthop *nexthop, *tnexthop;
  63. int recursing;
  64. int nexthop_num = 0;
  65. unsigned int ifindex = 0;
  66. int gate = 0;
  67. int error;
  68. char prefix_buf[INET_ADDRSTRLEN];
  69. if (IS_ZEBRA_DEBUG_RIB)
  70. inet_ntop (AF_INET, &p->u.prefix, prefix_buf, INET_ADDRSTRLEN);
  71. memset (&sin_dest, 0, sizeof (struct sockaddr_in));
  72. sin_dest.sin_family = AF_INET;
  73. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  74. sin_dest.sin_len = sizeof (struct sockaddr_in);
  75. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  76. sin_dest.sin_addr = p->u.prefix4;
  77. memset (&sin_mask, 0, sizeof (struct sockaddr_in));
  78. memset (&sin_gate, 0, sizeof (struct sockaddr_in));
  79. sin_gate.sin_family = AF_INET;
  80. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  81. sin_gate.sin_len = sizeof (struct sockaddr_in);
  82. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  83. /* Make gateway. */
  84. for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
  85. {
  86. if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  87. continue;
  88. gate = 0;
  89. char gate_buf[INET_ADDRSTRLEN] = "NULL";
  90. /*
  91. * XXX We need to refrain from kernel operations in some cases,
  92. * but this if statement seems overly cautious - what about
  93. * other than ADD and DELETE?
  94. */
  95. if ((cmd == RTM_ADD
  96. && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  97. || (cmd == RTM_DELETE
  98. && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
  99. ))
  100. {
  101. if (nexthop->type == NEXTHOP_TYPE_IPV4 ||
  102. nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
  103. {
  104. sin_gate.sin_addr = nexthop->gate.ipv4;
  105. gate = 1;
  106. }
  107. if (nexthop->type == NEXTHOP_TYPE_IFINDEX
  108. || nexthop->type == NEXTHOP_TYPE_IFNAME
  109. || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
  110. ifindex = nexthop->ifindex;
  111. if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
  112. {
  113. struct in_addr loopback;
  114. loopback.s_addr = htonl (INADDR_LOOPBACK);
  115. sin_gate.sin_addr = loopback;
  116. gate = 1;
  117. }
  118. if (gate && p->prefixlen == 32)
  119. mask = NULL;
  120. else
  121. {
  122. masklen2ip (p->prefixlen, &sin_mask.sin_addr);
  123. sin_mask.sin_family = AF_INET;
  124. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  125. sin_mask.sin_len = sin_masklen (sin_mask.sin_addr);
  126. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  127. mask = &sin_mask;
  128. }
  129. error = rtm_write (cmd,
  130. (union sockunion *)&sin_dest,
  131. (union sockunion *)mask,
  132. gate ? (union sockunion *)&sin_gate : NULL,
  133. ifindex,
  134. rib->flags,
  135. rib->metric);
  136. if (IS_ZEBRA_DEBUG_RIB)
  137. {
  138. if (!gate)
  139. {
  140. zlog_debug ("%s: %s/%d: attention! gate not found for rib %p",
  141. __func__, prefix_buf, p->prefixlen, rib);
  142. rib_dump (__func__, (struct prefix_ipv4 *)p, rib);
  143. }
  144. else
  145. inet_ntop (AF_INET, &sin_gate.sin_addr, gate_buf, INET_ADDRSTRLEN);
  146. }
  147. switch (error)
  148. {
  149. /* We only flag nexthops as being in FIB if rtm_write() did its work. */
  150. case ZEBRA_ERR_NOERROR:
  151. nexthop_num++;
  152. if (IS_ZEBRA_DEBUG_RIB)
  153. zlog_debug ("%s: %s/%d: successfully did NH %s",
  154. __func__, prefix_buf, p->prefixlen, gate_buf);
  155. if (cmd == RTM_ADD)
  156. SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
  157. break;
  158. /* The only valid case for this error is kernel's failure to install
  159. * a multipath route, which is common for FreeBSD. This should be
  160. * ignored silently, but logged as an error otherwise.
  161. */
  162. case ZEBRA_ERR_RTEXIST:
  163. if (cmd != RTM_ADD)
  164. zlog_err ("%s: rtm_write() returned %d for command %d",
  165. __func__, error, cmd);
  166. continue;
  167. break;
  168. /* Given that our NEXTHOP_FLAG_FIB matches real kernel FIB, it isn't
  169. * normal to get any other messages in ANY case.
  170. */
  171. case ZEBRA_ERR_RTNOEXIST:
  172. case ZEBRA_ERR_RTUNREACH:
  173. default:
  174. /* This point is reachable regardless of debugging mode. */
  175. if (!IS_ZEBRA_DEBUG_RIB)
  176. inet_ntop (AF_INET, &p->u.prefix, prefix_buf, INET_ADDRSTRLEN);
  177. zlog_err ("%s: %s/%d: rtm_write() unexpectedly returned %d for command %s",
  178. __func__, prefix_buf, p->prefixlen, error, lookup (rtm_type_str, cmd));
  179. break;
  180. }
  181. } /* if (cmd and flags make sense) */
  182. else
  183. if (IS_ZEBRA_DEBUG_RIB)
  184. zlog_debug ("%s: odd command %s for flags %d",
  185. __func__, lookup (rtm_type_str, cmd), nexthop->flags);
  186. } /* for (ALL_NEXTHOPS_RO(...))*/
  187. /* If there was no useful nexthop, then complain. */
  188. if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL)
  189. zlog_debug ("%s: No useful nexthops were found in RIB entry %p", __func__, rib);
  190. return 0; /*XXX*/
  191. }
  192. int
  193. kernel_add_ipv4 (struct prefix *p, struct rib *rib)
  194. {
  195. int route;
  196. if (zserv_privs.change(ZPRIVS_RAISE))
  197. zlog (NULL, LOG_ERR, "Can't raise privileges");
  198. route = kernel_rtm_ipv4 (RTM_ADD, p, rib, AF_INET);
  199. if (zserv_privs.change(ZPRIVS_LOWER))
  200. zlog (NULL, LOG_ERR, "Can't lower privileges");
  201. return route;
  202. }
  203. int
  204. kernel_delete_ipv4 (struct prefix *p, struct rib *rib)
  205. {
  206. int route;
  207. if (zserv_privs.change(ZPRIVS_RAISE))
  208. zlog (NULL, LOG_ERR, "Can't raise privileges");
  209. route = kernel_rtm_ipv4 (RTM_DELETE, p, rib, AF_INET);
  210. if (zserv_privs.change(ZPRIVS_LOWER))
  211. zlog (NULL, LOG_ERR, "Can't lower privileges");
  212. return route;
  213. }
  214. #ifdef HAVE_IPV6
  215. /* Calculate sin6_len value for netmask socket value. */
  216. static int
  217. sin6_masklen (struct in6_addr mask)
  218. {
  219. struct sockaddr_in6 sin6;
  220. char *p, *lim;
  221. int len;
  222. #if defined (INRIA)
  223. if (IN_ANYADDR6 (mask))
  224. return sizeof (long);
  225. #else /* ! INRIA */
  226. if (IN6_IS_ADDR_UNSPECIFIED (&mask))
  227. return sizeof (long);
  228. #endif /* ! INRIA */
  229. sin6.sin6_addr = mask;
  230. len = sizeof (struct sockaddr_in6);
  231. lim = (char *) & sin6.sin6_addr;
  232. p = lim + sizeof (sin6.sin6_addr);
  233. while (*--p == 0 && p >= lim)
  234. len--;
  235. return len;
  236. }
  237. /* Interface between zebra message and rtm message. */
  238. static int
  239. kernel_rtm_ipv6 (int message, struct prefix_ipv6 *dest,
  240. struct in6_addr *gate, int index, int flags)
  241. {
  242. struct sockaddr_in6 *mask;
  243. struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
  244. memset (&sin_dest, 0, sizeof (struct sockaddr_in6));
  245. sin_dest.sin6_family = AF_INET6;
  246. #ifdef SIN6_LEN
  247. sin_dest.sin6_len = sizeof (struct sockaddr_in6);
  248. #endif /* SIN6_LEN */
  249. memset (&sin_mask, 0, sizeof (struct sockaddr_in6));
  250. memset (&sin_gate, 0, sizeof (struct sockaddr_in6));
  251. sin_gate.sin6_family = AF_INET6;
  252. #ifdef SIN6_LEN
  253. sin_gate.sin6_len = sizeof (struct sockaddr_in6);
  254. #endif /* SIN6_LEN */
  255. sin_dest.sin6_addr = dest->prefix;
  256. if (gate)
  257. memcpy (&sin_gate.sin6_addr, gate, sizeof (struct in6_addr));
  258. /* Under kame set interface index to link local address. */
  259. #ifdef KAME
  260. #define SET_IN6_LINKLOCAL_IFINDEX(a, i) \
  261. do { \
  262. (a).s6_addr[2] = ((i) >> 8) & 0xff; \
  263. (a).s6_addr[3] = (i) & 0xff; \
  264. } while (0)
  265. if (gate && IN6_IS_ADDR_LINKLOCAL(gate))
  266. SET_IN6_LINKLOCAL_IFINDEX (sin_gate.sin6_addr, index);
  267. #endif /* KAME */
  268. if (gate && dest->prefixlen == 128)
  269. mask = NULL;
  270. else
  271. {
  272. masklen2ip6 (dest->prefixlen, &sin_mask.sin6_addr);
  273. sin_mask.sin6_family = AF_INET6;
  274. #ifdef SIN6_LEN
  275. sin_mask.sin6_len = sin6_masklen (sin_mask.sin6_addr);
  276. #endif /* SIN6_LEN */
  277. mask = &sin_mask;
  278. }
  279. return rtm_write (message,
  280. (union sockunion *) &sin_dest,
  281. (union sockunion *) mask,
  282. gate ? (union sockunion *)&sin_gate : NULL,
  283. index,
  284. flags,
  285. 0);
  286. }
  287. /* Interface between zebra message and rtm message. */
  288. static int
  289. kernel_rtm_ipv6_multipath (int cmd, struct prefix *p, struct rib *rib,
  290. int family)
  291. {
  292. struct sockaddr_in6 *mask;
  293. struct sockaddr_in6 sin_dest, sin_mask, sin_gate;
  294. struct nexthop *nexthop, *tnexthop;
  295. int recursing;
  296. int nexthop_num = 0;
  297. unsigned int ifindex = 0;
  298. int gate = 0;
  299. int error;
  300. memset (&sin_dest, 0, sizeof (struct sockaddr_in6));
  301. sin_dest.sin6_family = AF_INET6;
  302. #ifdef SIN6_LEN
  303. sin_dest.sin6_len = sizeof (struct sockaddr_in6);
  304. #endif /* SIN6_LEN */
  305. sin_dest.sin6_addr = p->u.prefix6;
  306. memset (&sin_mask, 0, sizeof (struct sockaddr_in6));
  307. memset (&sin_gate, 0, sizeof (struct sockaddr_in6));
  308. sin_gate.sin6_family = AF_INET6;
  309. #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  310. sin_gate.sin6_len = sizeof (struct sockaddr_in6);
  311. #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  312. /* Make gateway. */
  313. for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
  314. {
  315. if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
  316. continue;
  317. gate = 0;
  318. if ((cmd == RTM_ADD
  319. && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
  320. || (cmd == RTM_DELETE
  321. #if 0
  322. && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
  323. #endif
  324. ))
  325. {
  326. if (nexthop->type == NEXTHOP_TYPE_IPV6
  327. || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
  328. || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
  329. {
  330. sin_gate.sin6_addr = nexthop->gate.ipv6;
  331. gate = 1;
  332. }
  333. if (nexthop->type == NEXTHOP_TYPE_IFINDEX
  334. || nexthop->type == NEXTHOP_TYPE_IFNAME
  335. || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME
  336. || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)
  337. ifindex = nexthop->ifindex;
  338. if (cmd == RTM_ADD)
  339. SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
  340. }
  341. /* Under kame set interface index to link local address. */
  342. #ifdef KAME
  343. #define SET_IN6_LINKLOCAL_IFINDEX(a, i) \
  344. do { \
  345. (a).s6_addr[2] = ((i) >> 8) & 0xff; \
  346. (a).s6_addr[3] = (i) & 0xff; \
  347. } while (0)
  348. if (gate && IN6_IS_ADDR_LINKLOCAL(&sin_gate.sin6_addr))
  349. SET_IN6_LINKLOCAL_IFINDEX (sin_gate.sin6_addr, ifindex);
  350. #endif /* KAME */
  351. if (gate && p->prefixlen == 128)
  352. mask = NULL;
  353. else
  354. {
  355. masklen2ip6 (p->prefixlen, &sin_mask.sin6_addr);
  356. sin_mask.sin6_family = AF_INET6;
  357. #ifdef SIN6_LEN
  358. sin_mask.sin6_len = sin6_masklen (sin_mask.sin6_addr);
  359. #endif /* SIN6_LEN */
  360. mask = &sin_mask;
  361. }
  362. error = rtm_write (cmd,
  363. (union sockunion *) &sin_dest,
  364. (union sockunion *) mask,
  365. gate ? (union sockunion *)&sin_gate : NULL,
  366. ifindex,
  367. rib->flags,
  368. rib->metric);
  369. #if 0
  370. if (error)
  371. {
  372. zlog_info ("kernel_rtm_ipv6_multipath(): nexthop %d add error=%d.",
  373. nexthop_num, error);
  374. }
  375. #endif
  376. nexthop_num++;
  377. }
  378. /* If there is no useful nexthop then return. */
  379. if (nexthop_num == 0)
  380. {
  381. if (IS_ZEBRA_DEBUG_KERNEL)
  382. zlog_debug ("kernel_rtm_ipv6_multipath(): No useful nexthop.");
  383. return 0;
  384. }
  385. return 0; /*XXX*/
  386. }
  387. int
  388. kernel_add_ipv6 (struct prefix *p, struct rib *rib)
  389. {
  390. int route;
  391. if (zserv_privs.change(ZPRIVS_RAISE))
  392. zlog (NULL, LOG_ERR, "Can't raise privileges");
  393. route = kernel_rtm_ipv6_multipath (RTM_ADD, p, rib, AF_INET6);
  394. if (zserv_privs.change(ZPRIVS_LOWER))
  395. zlog (NULL, LOG_ERR, "Can't lower privileges");
  396. return route;
  397. }
  398. int
  399. kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
  400. {
  401. int route;
  402. if (zserv_privs.change(ZPRIVS_RAISE))
  403. zlog (NULL, LOG_ERR, "Can't raise privileges");
  404. route = kernel_rtm_ipv6_multipath (RTM_DELETE, p, rib, AF_INET6);
  405. if (zserv_privs.change(ZPRIVS_LOWER))
  406. zlog (NULL, LOG_ERR, "Can't lower privileges");
  407. return route;
  408. }
  409. /* Delete IPv6 route from the kernel. */
  410. int
  411. kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,
  412. unsigned int index, int flags, int table)
  413. {
  414. int route;
  415. if (zserv_privs.change(ZPRIVS_RAISE))
  416. zlog (NULL, LOG_ERR, "Can't raise privileges");
  417. route = kernel_rtm_ipv6 (RTM_DELETE, dest, gate, index, flags);
  418. if (zserv_privs.change(ZPRIVS_LOWER))
  419. zlog (NULL, LOG_ERR, "Can't lower privileges");
  420. return route;
  421. }
  422. #endif /* HAVE_IPV6 */