ripng_interface.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248
  1. /*
  2. * Interface related function for RIPng.
  3. * Copyright (C) 1998 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 "linklist.h"
  24. #include "if.h"
  25. #include "prefix.h"
  26. #include "memory.h"
  27. #include "network.h"
  28. #include "filter.h"
  29. #include "log.h"
  30. #include "stream.h"
  31. #include "zclient.h"
  32. #include "command.h"
  33. #include "table.h"
  34. #include "thread.h"
  35. #include "privs.h"
  36. #include "ripngd/ripngd.h"
  37. #include "ripngd/ripng_debug.h"
  38. /* If RFC2133 definition is used. */
  39. #ifndef IPV6_JOIN_GROUP
  40. #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
  41. #endif
  42. #ifndef IPV6_LEAVE_GROUP
  43. #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
  44. #endif
  45. extern struct zebra_privs_t ripngd_privs;
  46. /* Static utility function. */
  47. static void ripng_enable_apply (struct interface *);
  48. static void ripng_passive_interface_apply (struct interface *);
  49. static int ripng_enable_if_lookup (const char *);
  50. static int ripng_enable_network_lookup2 (struct connected *);
  51. static void ripng_enable_apply_all (void);
  52. /* Join to the all rip routers multicast group. */
  53. static int
  54. ripng_multicast_join (struct interface *ifp)
  55. {
  56. int ret;
  57. struct ipv6_mreq mreq;
  58. int save_errno;
  59. if (if_is_up (ifp) && if_is_multicast (ifp)) {
  60. memset (&mreq, 0, sizeof (mreq));
  61. inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
  62. mreq.ipv6mr_interface = ifp->ifindex;
  63. /*
  64. * NetBSD 1.6.2 requires root to join groups on gif(4).
  65. * While this is bogus, privs are available and easy to use
  66. * for this call as a workaround.
  67. */
  68. if (ripngd_privs.change (ZPRIVS_RAISE))
  69. zlog_err ("ripng_multicast_join: could not raise privs");
  70. ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  71. (char *) &mreq, sizeof (mreq));
  72. save_errno = errno;
  73. if (ripngd_privs.change (ZPRIVS_LOWER))
  74. zlog_err ("ripng_multicast_join: could not lower privs");
  75. if (ret < 0 && save_errno == EADDRINUSE)
  76. {
  77. /*
  78. * Group is already joined. This occurs due to sloppy group
  79. * management, in particular declining to leave the group on
  80. * an interface that has just gone down.
  81. */
  82. zlog_warn ("ripng join on %s EADDRINUSE (ignoring)\n", ifp->name);
  83. return 0; /* not an error */
  84. }
  85. if (ret < 0)
  86. zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s",
  87. safe_strerror (save_errno));
  88. if (IS_RIPNG_DEBUG_EVENT)
  89. zlog_debug ("RIPng %s join to all-rip-routers multicast group", ifp->name);
  90. if (ret < 0)
  91. return -1;
  92. }
  93. return 0;
  94. }
  95. /* Leave from the all rip routers multicast group. */
  96. static int
  97. ripng_multicast_leave (struct interface *ifp)
  98. {
  99. int ret;
  100. struct ipv6_mreq mreq;
  101. if (if_is_up (ifp) && if_is_multicast (ifp)) {
  102. memset (&mreq, 0, sizeof (mreq));
  103. inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
  104. mreq.ipv6mr_interface = ifp->ifindex;
  105. ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
  106. (char *) &mreq, sizeof (mreq));
  107. if (ret < 0)
  108. zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s\n", safe_strerror (errno));
  109. if (IS_RIPNG_DEBUG_EVENT)
  110. zlog_debug ("RIPng %s leave from all-rip-routers multicast group",
  111. ifp->name);
  112. if (ret < 0)
  113. return -1;
  114. }
  115. return 0;
  116. }
  117. /* How many link local IPv6 address could be used on the interface ? */
  118. static int
  119. ripng_if_ipv6_lladdress_check (struct interface *ifp)
  120. {
  121. struct listnode *nn;
  122. struct connected *connected;
  123. int count = 0;
  124. for (ALL_LIST_ELEMENTS_RO (ifp->connected, nn, connected))
  125. {
  126. struct prefix *p;
  127. p = connected->address;
  128. if ((p->family == AF_INET6) &&
  129. IN6_IS_ADDR_LINKLOCAL (&p->u.prefix6))
  130. count++;
  131. }
  132. return count;
  133. }
  134. /* Check max mtu size. */
  135. static unsigned int
  136. ripng_check_max_mtu (void)
  137. {
  138. struct listnode *node;
  139. struct interface *ifp;
  140. unsigned int mtu;
  141. mtu = 0;
  142. for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  143. if (mtu < ifp->mtu6)
  144. mtu = ifp->mtu6;
  145. return mtu;
  146. }
  147. static int
  148. ripng_if_down (struct interface *ifp)
  149. {
  150. struct route_node *rp;
  151. struct ripng_info *rinfo;
  152. struct ripng_interface *ri;
  153. if (ripng)
  154. {
  155. for (rp = route_top (ripng->table); rp; rp = route_next (rp))
  156. if ((rinfo = rp->info) != NULL)
  157. {
  158. /* Routes got through this interface. */
  159. if (rinfo->ifindex == ifp->ifindex
  160. && rinfo->type == ZEBRA_ROUTE_RIPNG
  161. && rinfo->sub_type == RIPNG_ROUTE_RTE)
  162. {
  163. ripng_zebra_ipv6_delete ((struct prefix_ipv6 *) &rp->p,
  164. &rinfo->nexthop,
  165. rinfo->ifindex);
  166. ripng_redistribute_delete (rinfo->type, rinfo->sub_type,
  167. (struct prefix_ipv6 *)&rp->p,
  168. rinfo->ifindex);
  169. }
  170. else
  171. {
  172. /* All redistributed routes got through this interface,
  173. * but the static and system ones are kept. */
  174. if ((rinfo->ifindex == ifp->ifindex) &&
  175. (rinfo->type != ZEBRA_ROUTE_STATIC) &&
  176. (rinfo->type != ZEBRA_ROUTE_SYSTEM))
  177. ripng_redistribute_delete (rinfo->type, rinfo->sub_type,
  178. (struct prefix_ipv6 *) &rp->p,
  179. rinfo->ifindex);
  180. }
  181. }
  182. }
  183. ri = ifp->info;
  184. if (ri->running)
  185. {
  186. if (IS_RIPNG_DEBUG_EVENT)
  187. zlog_debug ("turn off %s", ifp->name);
  188. /* Leave from multicast group. */
  189. ripng_multicast_leave (ifp);
  190. ri->running = 0;
  191. }
  192. return 0;
  193. }
  194. /* Inteface link up message processing. */
  195. int
  196. ripng_interface_up (int command, struct zclient *zclient, zebra_size_t length)
  197. {
  198. struct stream *s;
  199. struct interface *ifp;
  200. /* zebra_interface_state_read() updates interface structure in iflist. */
  201. s = zclient->ibuf;
  202. ifp = zebra_interface_state_read (s);
  203. if (ifp == NULL)
  204. return 0;
  205. if (IS_RIPNG_DEBUG_ZEBRA)
  206. zlog_debug ("interface up %s index %d flags %llx metric %d mtu %d",
  207. ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
  208. ifp->metric, ifp->mtu6);
  209. /* Check if this interface is RIPng enabled or not. */
  210. ripng_enable_apply (ifp);
  211. /* Check for a passive interface. */
  212. ripng_passive_interface_apply (ifp);
  213. /* Apply distribute list to the all interface. */
  214. ripng_distribute_update_interface (ifp);
  215. return 0;
  216. }
  217. /* Inteface link down message processing. */
  218. int
  219. ripng_interface_down (int command, struct zclient *zclient,
  220. zebra_size_t length)
  221. {
  222. struct stream *s;
  223. struct interface *ifp;
  224. /* zebra_interface_state_read() updates interface structure in iflist. */
  225. s = zclient->ibuf;
  226. ifp = zebra_interface_state_read (s);
  227. if (ifp == NULL)
  228. return 0;
  229. ripng_if_down (ifp);
  230. if (IS_RIPNG_DEBUG_ZEBRA)
  231. zlog_debug ("interface down %s index %d flags %lld metric %d mtu %d",
  232. ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
  233. return 0;
  234. }
  235. /* Inteface addition message from zebra. */
  236. int
  237. ripng_interface_add (int command, struct zclient *zclient, zebra_size_t length)
  238. {
  239. struct interface *ifp;
  240. ifp = zebra_interface_add_read (zclient->ibuf);
  241. if (IS_RIPNG_DEBUG_ZEBRA)
  242. zlog_debug ("RIPng interface add %s index %d flags %lld metric %d mtu %d",
  243. ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
  244. /* Check is this interface is RIP enabled or not.*/
  245. ripng_enable_apply (ifp);
  246. /* Apply distribute list to the interface. */
  247. ripng_distribute_update_interface (ifp);
  248. /* Check interface routemap. */
  249. ripng_if_rmap_update_interface (ifp);
  250. return 0;
  251. }
  252. int
  253. ripng_interface_delete (int command, struct zclient *zclient,
  254. zebra_size_t length)
  255. {
  256. struct interface *ifp;
  257. struct stream *s;
  258. s = zclient->ibuf;
  259. /* zebra_interface_state_read() updates interface structure in iflist */
  260. ifp = zebra_interface_state_read(s);
  261. if (ifp == NULL)
  262. return 0;
  263. if (if_is_up (ifp)) {
  264. ripng_if_down(ifp);
  265. }
  266. zlog_info("interface delete %s index %d flags %lld metric %d mtu %d",
  267. ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu6);
  268. /* To support pseudo interface do not free interface structure. */
  269. /* if_delete(ifp); */
  270. ifp->ifindex = IFINDEX_INTERNAL;
  271. return 0;
  272. }
  273. void
  274. ripng_interface_clean (void)
  275. {
  276. struct listnode *node, *nnode;
  277. struct interface *ifp;
  278. struct ripng_interface *ri;
  279. for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
  280. {
  281. ri = ifp->info;
  282. ri->enable_network = 0;
  283. ri->enable_interface = 0;
  284. ri->running = 0;
  285. if (ri->t_wakeup)
  286. {
  287. thread_cancel (ri->t_wakeup);
  288. ri->t_wakeup = NULL;
  289. }
  290. }
  291. }
  292. void
  293. ripng_interface_reset (void)
  294. {
  295. struct listnode *node;
  296. struct interface *ifp;
  297. struct ripng_interface *ri;
  298. for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  299. {
  300. ri = ifp->info;
  301. ri->enable_network = 0;
  302. ri->enable_interface = 0;
  303. ri->running = 0;
  304. ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
  305. ri->split_horizon_default = RIPNG_NO_SPLIT_HORIZON;
  306. ri->list[RIPNG_FILTER_IN] = NULL;
  307. ri->list[RIPNG_FILTER_OUT] = NULL;
  308. ri->prefix[RIPNG_FILTER_IN] = NULL;
  309. ri->prefix[RIPNG_FILTER_OUT] = NULL;
  310. if (ri->t_wakeup)
  311. {
  312. thread_cancel (ri->t_wakeup);
  313. ri->t_wakeup = NULL;
  314. }
  315. ri->passive = 0;
  316. }
  317. }
  318. static void
  319. ripng_apply_address_add (struct connected *ifc) {
  320. struct prefix_ipv6 address;
  321. struct prefix *p;
  322. if (!ripng)
  323. return;
  324. if (! if_is_up(ifc->ifp))
  325. return;
  326. p = ifc->address;
  327. memset (&address, 0, sizeof (address));
  328. address.family = p->family;
  329. address.prefix = p->u.prefix6;
  330. address.prefixlen = p->prefixlen;
  331. apply_mask_ipv6(&address);
  332. /* Check if this interface is RIP enabled or not
  333. or Check if this address's prefix is RIP enabled */
  334. if ((ripng_enable_if_lookup(ifc->ifp->name) >= 0) ||
  335. (ripng_enable_network_lookup2(ifc) >= 0))
  336. ripng_redistribute_add(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
  337. &address, ifc->ifp->ifindex, NULL);
  338. }
  339. int
  340. ripng_interface_address_add (int command, struct zclient *zclient,
  341. zebra_size_t length)
  342. {
  343. struct connected *c;
  344. struct prefix *p;
  345. c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
  346. zclient->ibuf);
  347. if (c == NULL)
  348. return 0;
  349. p = c->address;
  350. if (p->family == AF_INET6)
  351. {
  352. struct ripng_interface *ri = c->ifp->info;
  353. if (IS_RIPNG_DEBUG_ZEBRA)
  354. zlog_debug ("RIPng connected address %s/%d add",
  355. inet6_ntoa(p->u.prefix6),
  356. p->prefixlen);
  357. /* Check is this prefix needs to be redistributed. */
  358. ripng_apply_address_add(c);
  359. /* Let's try once again whether the interface could be activated */
  360. if (!ri->running) {
  361. /* Check if this interface is RIP enabled or not.*/
  362. ripng_enable_apply (c->ifp);
  363. /* Apply distribute list to the interface. */
  364. ripng_distribute_update_interface (c->ifp);
  365. /* Check interface routemap. */
  366. ripng_if_rmap_update_interface (c->ifp);
  367. }
  368. }
  369. return 0;
  370. }
  371. static void
  372. ripng_apply_address_del (struct connected *ifc) {
  373. struct prefix_ipv6 address;
  374. struct prefix *p;
  375. if (!ripng)
  376. return;
  377. if (! if_is_up(ifc->ifp))
  378. return;
  379. p = ifc->address;
  380. memset (&address, 0, sizeof (address));
  381. address.family = p->family;
  382. address.prefix = p->u.prefix6;
  383. address.prefixlen = p->prefixlen;
  384. apply_mask_ipv6(&address);
  385. ripng_redistribute_delete(ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
  386. &address, ifc->ifp->ifindex);
  387. }
  388. int
  389. ripng_interface_address_delete (int command, struct zclient *zclient,
  390. zebra_size_t length)
  391. {
  392. struct connected *ifc;
  393. struct prefix *p;
  394. char buf[INET6_ADDRSTRLEN];
  395. ifc = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
  396. zclient->ibuf);
  397. if (ifc)
  398. {
  399. p = ifc->address;
  400. if (p->family == AF_INET6)
  401. {
  402. if (IS_RIPNG_DEBUG_ZEBRA)
  403. zlog_debug ("RIPng connected address %s/%d delete",
  404. inet_ntop (AF_INET6, &p->u.prefix6, buf,
  405. INET6_ADDRSTRLEN),
  406. p->prefixlen);
  407. /* Check wether this prefix needs to be removed. */
  408. ripng_apply_address_del(ifc);
  409. }
  410. connected_free (ifc);
  411. }
  412. return 0;
  413. }
  414. /* RIPng enable interface vector. */
  415. vector ripng_enable_if;
  416. /* RIPng enable network table. */
  417. struct route_table *ripng_enable_network;
  418. /* Lookup RIPng enable network. */
  419. /* Check wether the interface has at least a connected prefix that
  420. * is within the ripng_enable_network table. */
  421. static int
  422. ripng_enable_network_lookup_if (struct interface *ifp)
  423. {
  424. struct listnode *node;
  425. struct connected *connected;
  426. struct prefix_ipv6 address;
  427. for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected))
  428. {
  429. struct prefix *p;
  430. struct route_node *node;
  431. p = connected->address;
  432. if (p->family == AF_INET6)
  433. {
  434. address.family = AF_INET6;
  435. address.prefix = p->u.prefix6;
  436. address.prefixlen = IPV6_MAX_BITLEN;
  437. node = route_node_match (ripng_enable_network,
  438. (struct prefix *)&address);
  439. if (node)
  440. {
  441. route_unlock_node (node);
  442. return 1;
  443. }
  444. }
  445. }
  446. return -1;
  447. }
  448. /* Check wether connected is within the ripng_enable_network table. */
  449. static int
  450. ripng_enable_network_lookup2 (struct connected *connected)
  451. {
  452. struct prefix_ipv6 address;
  453. struct prefix *p;
  454. p = connected->address;
  455. if (p->family == AF_INET6) {
  456. struct route_node *node;
  457. address.family = p->family;
  458. address.prefix = p->u.prefix6;
  459. address.prefixlen = IPV6_MAX_BITLEN;
  460. /* LPM on p->family, p->u.prefix6/IPV6_MAX_BITLEN within ripng_enable_network */
  461. node = route_node_match (ripng_enable_network,
  462. (struct prefix *)&address);
  463. if (node) {
  464. route_unlock_node (node);
  465. return 1;
  466. }
  467. }
  468. return -1;
  469. }
  470. /* Add RIPng enable network. */
  471. static int
  472. ripng_enable_network_add (struct prefix *p)
  473. {
  474. struct route_node *node;
  475. node = route_node_get (ripng_enable_network, p);
  476. if (node->info)
  477. {
  478. route_unlock_node (node);
  479. return -1;
  480. }
  481. else
  482. node->info = (char *) "enabled";
  483. /* XXX: One should find a better solution than a generic one */
  484. ripng_enable_apply_all();
  485. return 1;
  486. }
  487. /* Delete RIPng enable network. */
  488. static int
  489. ripng_enable_network_delete (struct prefix *p)
  490. {
  491. struct route_node *node;
  492. node = route_node_lookup (ripng_enable_network, p);
  493. if (node)
  494. {
  495. node->info = NULL;
  496. /* Unlock info lock. */
  497. route_unlock_node (node);
  498. /* Unlock lookup lock. */
  499. route_unlock_node (node);
  500. return 1;
  501. }
  502. return -1;
  503. }
  504. /* Lookup function. */
  505. static int
  506. ripng_enable_if_lookup (const char *ifname)
  507. {
  508. unsigned int i;
  509. char *str;
  510. for (i = 0; i < vector_active (ripng_enable_if); i++)
  511. if ((str = vector_slot (ripng_enable_if, i)) != NULL)
  512. if (strcmp (str, ifname) == 0)
  513. return i;
  514. return -1;
  515. }
  516. /* Add interface to ripng_enable_if. */
  517. static int
  518. ripng_enable_if_add (const char *ifname)
  519. {
  520. int ret;
  521. ret = ripng_enable_if_lookup (ifname);
  522. if (ret >= 0)
  523. return -1;
  524. vector_set (ripng_enable_if, strdup (ifname));
  525. ripng_enable_apply_all();
  526. return 1;
  527. }
  528. /* Delete interface from ripng_enable_if. */
  529. static int
  530. ripng_enable_if_delete (const char *ifname)
  531. {
  532. int index;
  533. char *str;
  534. index = ripng_enable_if_lookup (ifname);
  535. if (index < 0)
  536. return -1;
  537. str = vector_slot (ripng_enable_if, index);
  538. free (str);
  539. vector_unset (ripng_enable_if, index);
  540. ripng_enable_apply_all();
  541. return 1;
  542. }
  543. /* Wake up interface. */
  544. static int
  545. ripng_interface_wakeup (struct thread *t)
  546. {
  547. struct interface *ifp;
  548. struct ripng_interface *ri;
  549. /* Get interface. */
  550. ifp = THREAD_ARG (t);
  551. ri = ifp->info;
  552. ri->t_wakeup = NULL;
  553. /* Join to multicast group. */
  554. if (ripng_multicast_join (ifp) < 0) {
  555. zlog_err ("multicast join failed, interface %s not running", ifp->name);
  556. return 0;
  557. }
  558. /* Set running flag. */
  559. ri->running = 1;
  560. /* Send RIP request to the interface. */
  561. ripng_request (ifp);
  562. return 0;
  563. }
  564. static void
  565. ripng_connect_set (struct interface *ifp, int set)
  566. {
  567. struct listnode *node, *nnode;
  568. struct connected *connected;
  569. struct prefix_ipv6 address;
  570. for (ALL_LIST_ELEMENTS (ifp->connected, node, nnode, connected))
  571. {
  572. struct prefix *p;
  573. p = connected->address;
  574. if (p->family != AF_INET6)
  575. continue;
  576. address.family = AF_INET6;
  577. address.prefix = p->u.prefix6;
  578. address.prefixlen = p->prefixlen;
  579. apply_mask_ipv6 (&address);
  580. if (set) {
  581. /* Check once more wether this prefix is within a "network IF_OR_PREF" one */
  582. if ((ripng_enable_if_lookup(connected->ifp->name) >= 0) ||
  583. (ripng_enable_network_lookup2(connected) >= 0))
  584. ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
  585. &address, connected->ifp->ifindex, NULL);
  586. } else {
  587. ripng_redistribute_delete (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_INTERFACE,
  588. &address, connected->ifp->ifindex);
  589. if (ripng_redistribute_check (ZEBRA_ROUTE_CONNECT))
  590. ripng_redistribute_add (ZEBRA_ROUTE_CONNECT, RIPNG_ROUTE_REDISTRIBUTE,
  591. &address, connected->ifp->ifindex, NULL);
  592. }
  593. }
  594. }
  595. /* Check RIPng is enabed on this interface. */
  596. void
  597. ripng_enable_apply (struct interface *ifp)
  598. {
  599. int ret;
  600. struct ripng_interface *ri = NULL;
  601. /* Check interface. */
  602. if (! if_is_up (ifp))
  603. return;
  604. ri = ifp->info;
  605. /* Is this interface a candidate for RIPng ? */
  606. ret = ripng_enable_network_lookup_if (ifp);
  607. /* If the interface is matched. */
  608. if (ret > 0)
  609. ri->enable_network = 1;
  610. else
  611. ri->enable_network = 0;
  612. /* Check interface name configuration. */
  613. ret = ripng_enable_if_lookup (ifp->name);
  614. if (ret >= 0)
  615. ri->enable_interface = 1;
  616. else
  617. ri->enable_interface = 0;
  618. /* any candidate interface MUST have a link-local IPv6 address */
  619. if ((! ripng_if_ipv6_lladdress_check (ifp)) &&
  620. (ri->enable_network || ri->enable_interface)) {
  621. ri->enable_network = 0;
  622. ri->enable_interface = 0;
  623. zlog_warn("Interface %s does not have any link-local address",
  624. ifp->name);
  625. }
  626. /* Update running status of the interface. */
  627. if (ri->enable_network || ri->enable_interface)
  628. {
  629. {
  630. if (IS_RIPNG_DEBUG_EVENT)
  631. zlog_debug ("RIPng turn on %s", ifp->name);
  632. /* Add interface wake up thread. */
  633. if (! ri->t_wakeup)
  634. ri->t_wakeup = thread_add_timer (master, ripng_interface_wakeup,
  635. ifp, 1);
  636. ripng_connect_set (ifp, 1);
  637. }
  638. }
  639. else
  640. {
  641. if (ri->running)
  642. {
  643. /* Might as well clean up the route table as well
  644. * ripng_if_down sets to 0 ri->running, and displays "turn off %s"
  645. **/
  646. ripng_if_down(ifp);
  647. ripng_connect_set (ifp, 0);
  648. }
  649. }
  650. }
  651. /* Set distribute list to all interfaces. */
  652. static void
  653. ripng_enable_apply_all (void)
  654. {
  655. struct interface *ifp;
  656. struct listnode *node;
  657. for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  658. ripng_enable_apply (ifp);
  659. }
  660. /* Clear all network and neighbor configuration */
  661. void
  662. ripng_clean_network ()
  663. {
  664. unsigned int i;
  665. char *str;
  666. struct route_node *rn;
  667. /* ripng_enable_network */
  668. for (rn = route_top (ripng_enable_network); rn; rn = route_next (rn))
  669. if (rn->info) {
  670. rn->info = NULL;
  671. route_unlock_node(rn);
  672. }
  673. /* ripng_enable_if */
  674. for (i = 0; i < vector_active (ripng_enable_if); i++)
  675. if ((str = vector_slot (ripng_enable_if, i)) != NULL) {
  676. free (str);
  677. vector_slot (ripng_enable_if, i) = NULL;
  678. }
  679. }
  680. /* Vector to store passive-interface name. */
  681. vector Vripng_passive_interface;
  682. /* Utility function for looking up passive interface settings. */
  683. static int
  684. ripng_passive_interface_lookup (const char *ifname)
  685. {
  686. unsigned int i;
  687. char *str;
  688. for (i = 0; i < vector_active (Vripng_passive_interface); i++)
  689. if ((str = vector_slot (Vripng_passive_interface, i)) != NULL)
  690. if (strcmp (str, ifname) == 0)
  691. return i;
  692. return -1;
  693. }
  694. void
  695. ripng_passive_interface_apply (struct interface *ifp)
  696. {
  697. int ret;
  698. struct ripng_interface *ri;
  699. ri = ifp->info;
  700. ret = ripng_passive_interface_lookup (ifp->name);
  701. if (ret < 0)
  702. ri->passive = 0;
  703. else
  704. ri->passive = 1;
  705. }
  706. static void
  707. ripng_passive_interface_apply_all (void)
  708. {
  709. struct interface *ifp;
  710. struct listnode *node;
  711. for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  712. ripng_passive_interface_apply (ifp);
  713. }
  714. /* Passive interface. */
  715. static int
  716. ripng_passive_interface_set (struct vty *vty, const char *ifname)
  717. {
  718. if (ripng_passive_interface_lookup (ifname) >= 0)
  719. return CMD_WARNING;
  720. vector_set (Vripng_passive_interface, strdup (ifname));
  721. ripng_passive_interface_apply_all ();
  722. return CMD_SUCCESS;
  723. }
  724. static int
  725. ripng_passive_interface_unset (struct vty *vty, const char *ifname)
  726. {
  727. int i;
  728. char *str;
  729. i = ripng_passive_interface_lookup (ifname);
  730. if (i < 0)
  731. return CMD_WARNING;
  732. str = vector_slot (Vripng_passive_interface, i);
  733. free (str);
  734. vector_unset (Vripng_passive_interface, i);
  735. ripng_passive_interface_apply_all ();
  736. return CMD_SUCCESS;
  737. }
  738. /* Free all configured RIP passive-interface settings. */
  739. void
  740. ripng_passive_interface_clean (void)
  741. {
  742. unsigned int i;
  743. char *str;
  744. for (i = 0; i < vector_active (Vripng_passive_interface); i++)
  745. if ((str = vector_slot (Vripng_passive_interface, i)) != NULL)
  746. {
  747. free (str);
  748. vector_slot (Vripng_passive_interface, i) = NULL;
  749. }
  750. ripng_passive_interface_apply_all ();
  751. }
  752. /* Write RIPng enable network and interface to the vty. */
  753. int
  754. ripng_network_write (struct vty *vty, int config_mode)
  755. {
  756. unsigned int i;
  757. const char *ifname;
  758. struct route_node *node;
  759. char buf[BUFSIZ];
  760. /* Write enable network. */
  761. for (node = route_top (ripng_enable_network); node; node = route_next (node))
  762. if (node->info)
  763. {
  764. struct prefix *p = &node->p;
  765. vty_out (vty, "%s%s/%d%s",
  766. config_mode ? " network " : " ",
  767. inet_ntop (p->family, &p->u.prefix, buf, BUFSIZ),
  768. p->prefixlen,
  769. VTY_NEWLINE);
  770. }
  771. /* Write enable interface. */
  772. for (i = 0; i < vector_active (ripng_enable_if); i++)
  773. if ((ifname = vector_slot (ripng_enable_if, i)) != NULL)
  774. vty_out (vty, "%s%s%s",
  775. config_mode ? " network " : " ",
  776. ifname,
  777. VTY_NEWLINE);
  778. /* Write passive interface. */
  779. if (config_mode)
  780. for (i = 0; i < vector_active (Vripng_passive_interface); i++)
  781. if ((ifname = vector_slot (Vripng_passive_interface, i)) != NULL)
  782. vty_out (vty, " passive-interface %s%s", ifname, VTY_NEWLINE);
  783. return 0;
  784. }
  785. /* RIPng enable on specified interface or matched network. */
  786. DEFUN (ripng_network,
  787. ripng_network_cmd,
  788. "network IF_OR_ADDR",
  789. "RIPng enable on specified interface or network.\n"
  790. "Interface or address")
  791. {
  792. int ret;
  793. struct prefix p;
  794. ret = str2prefix (argv[0], &p);
  795. /* Given string is IPv6 network or interface name. */
  796. if (ret)
  797. ret = ripng_enable_network_add (&p);
  798. else
  799. ret = ripng_enable_if_add (argv[0]);
  800. if (ret < 0)
  801. {
  802. vty_out (vty, "There is same network configuration %s%s", argv[0],
  803. VTY_NEWLINE);
  804. return CMD_WARNING;
  805. }
  806. return CMD_SUCCESS;
  807. }
  808. /* RIPng enable on specified interface or matched network. */
  809. DEFUN (no_ripng_network,
  810. no_ripng_network_cmd,
  811. "no network IF_OR_ADDR",
  812. NO_STR
  813. "RIPng enable on specified interface or network.\n"
  814. "Interface or address")
  815. {
  816. int ret;
  817. struct prefix p;
  818. ret = str2prefix (argv[0], &p);
  819. /* Given string is interface name. */
  820. if (ret)
  821. ret = ripng_enable_network_delete (&p);
  822. else
  823. ret = ripng_enable_if_delete (argv[0]);
  824. if (ret < 0)
  825. {
  826. vty_out (vty, "can't find network %s%s", argv[0],
  827. VTY_NEWLINE);
  828. return CMD_WARNING;
  829. }
  830. return CMD_SUCCESS;
  831. }
  832. DEFUN (ipv6_ripng_split_horizon,
  833. ipv6_ripng_split_horizon_cmd,
  834. "ipv6 ripng split-horizon",
  835. IPV6_STR
  836. "Routing Information Protocol\n"
  837. "Perform split horizon\n")
  838. {
  839. struct interface *ifp;
  840. struct ripng_interface *ri;
  841. ifp = vty->index;
  842. ri = ifp->info;
  843. ri->split_horizon = RIPNG_SPLIT_HORIZON;
  844. return CMD_SUCCESS;
  845. }
  846. DEFUN (ipv6_ripng_split_horizon_poisoned_reverse,
  847. ipv6_ripng_split_horizon_poisoned_reverse_cmd,
  848. "ipv6 ripng split-horizon poisoned-reverse",
  849. IPV6_STR
  850. "Routing Information Protocol\n"
  851. "Perform split horizon\n"
  852. "With poisoned-reverse\n")
  853. {
  854. struct interface *ifp;
  855. struct ripng_interface *ri;
  856. ifp = vty->index;
  857. ri = ifp->info;
  858. ri->split_horizon = RIPNG_SPLIT_HORIZON_POISONED_REVERSE;
  859. return CMD_SUCCESS;
  860. }
  861. DEFUN (no_ipv6_ripng_split_horizon,
  862. no_ipv6_ripng_split_horizon_cmd,
  863. "no ipv6 ripng split-horizon",
  864. NO_STR
  865. IPV6_STR
  866. "Routing Information Protocol\n"
  867. "Perform split horizon\n")
  868. {
  869. struct interface *ifp;
  870. struct ripng_interface *ri;
  871. ifp = vty->index;
  872. ri = ifp->info;
  873. ri->split_horizon = RIPNG_NO_SPLIT_HORIZON;
  874. return CMD_SUCCESS;
  875. }
  876. ALIAS (no_ipv6_ripng_split_horizon,
  877. no_ipv6_ripng_split_horizon_poisoned_reverse_cmd,
  878. "no ipv6 ripng split-horizon poisoned-reverse",
  879. NO_STR
  880. IPV6_STR
  881. "Routing Information Protocol\n"
  882. "Perform split horizon\n"
  883. "With poisoned-reverse\n")
  884. DEFUN (ripng_passive_interface,
  885. ripng_passive_interface_cmd,
  886. "passive-interface IFNAME",
  887. "Suppress routing updates on an interface\n"
  888. "Interface name\n")
  889. {
  890. return ripng_passive_interface_set (vty, argv[0]);
  891. }
  892. DEFUN (no_ripng_passive_interface,
  893. no_ripng_passive_interface_cmd,
  894. "no passive-interface IFNAME",
  895. NO_STR
  896. "Suppress routing updates on an interface\n"
  897. "Interface name\n")
  898. {
  899. return ripng_passive_interface_unset (vty, argv[0]);
  900. }
  901. static struct ripng_interface *
  902. ri_new (void)
  903. {
  904. struct ripng_interface *ri;
  905. ri = XCALLOC (MTYPE_IF, sizeof (struct ripng_interface));
  906. /* Set default split-horizon behavior. If the interface is Frame
  907. Relay or SMDS is enabled, the default value for split-horizon is
  908. off. But currently Zebra does detect Frame Relay or SMDS
  909. interface. So all interface is set to split horizon. */
  910. ri->split_horizon_default = RIPNG_SPLIT_HORIZON;
  911. ri->split_horizon = ri->split_horizon_default;
  912. return ri;
  913. }
  914. static int
  915. ripng_if_new_hook (struct interface *ifp)
  916. {
  917. ifp->info = ri_new ();
  918. return 0;
  919. }
  920. /* Called when interface structure deleted. */
  921. static int
  922. ripng_if_delete_hook (struct interface *ifp)
  923. {
  924. XFREE (MTYPE_IF, ifp->info);
  925. ifp->info = NULL;
  926. return 0;
  927. }
  928. /* Configuration write function for ripngd. */
  929. static int
  930. interface_config_write (struct vty *vty)
  931. {
  932. struct listnode *node;
  933. struct interface *ifp;
  934. struct ripng_interface *ri;
  935. int write = 0;
  936. for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
  937. {
  938. ri = ifp->info;
  939. /* Do not display the interface if there is no
  940. * configuration about it.
  941. **/
  942. if ((!ifp->desc) &&
  943. (ri->split_horizon == ri->split_horizon_default))
  944. continue;
  945. vty_out (vty, "interface %s%s", ifp->name,
  946. VTY_NEWLINE);
  947. if (ifp->desc)
  948. vty_out (vty, " description %s%s", ifp->desc,
  949. VTY_NEWLINE);
  950. /* Split horizon. */
  951. if (ri->split_horizon != ri->split_horizon_default)
  952. {
  953. switch (ri->split_horizon) {
  954. case RIPNG_SPLIT_HORIZON:
  955. vty_out (vty, " ipv6 ripng split-horizon%s", VTY_NEWLINE);
  956. break;
  957. case RIPNG_SPLIT_HORIZON_POISONED_REVERSE:
  958. vty_out (vty, " ipv6 ripng split-horizon poisoned-reverse%s",
  959. VTY_NEWLINE);
  960. break;
  961. case RIPNG_NO_SPLIT_HORIZON:
  962. default:
  963. vty_out (vty, " no ipv6 ripng split-horizon%s", VTY_NEWLINE);
  964. break;
  965. }
  966. }
  967. vty_out (vty, "!%s", VTY_NEWLINE);
  968. write++;
  969. }
  970. return write;
  971. }
  972. /* ripngd's interface node. */
  973. static struct cmd_node interface_node =
  974. {
  975. INTERFACE_NODE,
  976. "%s(config-if)# ",
  977. 1 /* VTYSH */
  978. };
  979. /* Initialization of interface. */
  980. void
  981. ripng_if_init ()
  982. {
  983. /* Interface initialize. */
  984. iflist = list_new ();
  985. if_add_hook (IF_NEW_HOOK, ripng_if_new_hook);
  986. if_add_hook (IF_DELETE_HOOK, ripng_if_delete_hook);
  987. /* RIPng enable network init. */
  988. ripng_enable_network = route_table_init ();
  989. /* RIPng enable interface init. */
  990. ripng_enable_if = vector_init (1);
  991. /* RIPng passive interface. */
  992. Vripng_passive_interface = vector_init (1);
  993. /* Install interface node. */
  994. install_node (&interface_node, interface_config_write);
  995. /* Install commands. */
  996. install_element (CONFIG_NODE, &interface_cmd);
  997. install_element (CONFIG_NODE, &no_interface_cmd);
  998. install_default (INTERFACE_NODE);
  999. install_element (INTERFACE_NODE, &interface_desc_cmd);
  1000. install_element (INTERFACE_NODE, &no_interface_desc_cmd);
  1001. install_element (RIPNG_NODE, &ripng_network_cmd);
  1002. install_element (RIPNG_NODE, &no_ripng_network_cmd);
  1003. install_element (RIPNG_NODE, &ripng_passive_interface_cmd);
  1004. install_element (RIPNG_NODE, &no_ripng_passive_interface_cmd);
  1005. install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
  1006. install_element (INTERFACE_NODE, &ipv6_ripng_split_horizon_poisoned_reverse_cmd);
  1007. install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_cmd);
  1008. install_element (INTERFACE_NODE, &no_ipv6_ripng_split_horizon_poisoned_reverse_cmd);
  1009. }