rtadv.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
  1. /* Router advertisement
  2. * Copyright (C) 1999 Kunihiro Ishiguro
  3. *
  4. * This file is part of GNU Zebra.
  5. *
  6. * GNU Zebra is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the
  8. * Free Software Foundation; either version 2, or (at your option) any
  9. * later version.
  10. *
  11. * GNU Zebra is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GNU Zebra; see the file COPYING. If not, write to the Free
  18. * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  19. * 02111-1307, USA.
  20. */
  21. #include <zebra.h>
  22. #include "memory.h"
  23. #include "sockopt.h"
  24. #include "thread.h"
  25. #include "if.h"
  26. #include "log.h"
  27. #include "prefix.h"
  28. #include "linklist.h"
  29. #include "command.h"
  30. #include "privs.h"
  31. #include "zebra/interface.h"
  32. #include "zebra/rtadv.h"
  33. #include "zebra/debug.h"
  34. #include "zebra/rib.h"
  35. #include "zebra/zserv.h"
  36. extern struct zebra_privs_t zserv_privs;
  37. #if defined (HAVE_IPV6) && defined (RTADV)
  38. #ifdef OPEN_BSD
  39. #include <netinet/icmp6.h>
  40. #endif
  41. /* If RFC2133 definition is used. */
  42. #ifndef IPV6_JOIN_GROUP
  43. #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
  44. #endif
  45. #ifndef IPV6_LEAVE_GROUP
  46. #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
  47. #endif
  48. #define ALLNODE "ff02::1"
  49. #define ALLROUTER "ff02::2"
  50. extern struct zebra_t zebrad;
  51. enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER, RTADV_READ};
  52. void rtadv_event (enum rtadv_event, int);
  53. int if_join_all_router (int, struct interface *);
  54. int if_leave_all_router (int, struct interface *);
  55. /* Structure which hold status of router advertisement. */
  56. struct rtadv
  57. {
  58. int sock;
  59. int adv_if_count;
  60. struct thread *ra_read;
  61. struct thread *ra_timer;
  62. };
  63. struct rtadv *rtadv = NULL;
  64. struct rtadv *
  65. rtadv_new ()
  66. {
  67. struct rtadv *new;
  68. new = XMALLOC (MTYPE_TMP, sizeof (struct rtadv));
  69. memset (new, 0, sizeof (struct rtadv));
  70. return new;
  71. }
  72. void
  73. rtadv_free (struct rtadv *rtadv)
  74. {
  75. XFREE (MTYPE_TMP, rtadv);
  76. }
  77. int
  78. rtadv_recv_packet (int sock, u_char *buf, int buflen,
  79. struct sockaddr_in6 *from, unsigned int *ifindex,
  80. int *hoplimit)
  81. {
  82. int ret;
  83. struct msghdr msg;
  84. struct iovec iov;
  85. struct cmsghdr *cmsgptr;
  86. struct in6_addr dst;
  87. char adata[1024];
  88. /* Fill in message and iovec. */
  89. msg.msg_name = (void *) from;
  90. msg.msg_namelen = sizeof (struct sockaddr_in6);
  91. msg.msg_iov = &iov;
  92. msg.msg_iovlen = 1;
  93. msg.msg_control = (void *) adata;
  94. msg.msg_controllen = sizeof adata;
  95. iov.iov_base = buf;
  96. iov.iov_len = buflen;
  97. /* If recvmsg fail return minus value. */
  98. ret = recvmsg (sock, &msg, 0);
  99. if (ret < 0)
  100. return ret;
  101. for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
  102. cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
  103. {
  104. /* I want interface index which this packet comes from. */
  105. if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
  106. cmsgptr->cmsg_type == IPV6_PKTINFO)
  107. {
  108. struct in6_pktinfo *ptr;
  109. ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
  110. *ifindex = ptr->ipi6_ifindex;
  111. memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
  112. }
  113. /* Incoming packet's hop limit. */
  114. if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
  115. cmsgptr->cmsg_type == IPV6_HOPLIMIT)
  116. *hoplimit = *((int *) CMSG_DATA (cmsgptr));
  117. }
  118. return ret;
  119. }
  120. #define RTADV_MSG_SIZE 4096
  121. /* Send router advertisement packet. */
  122. void
  123. rtadv_send_packet (int sock, struct interface *ifp)
  124. {
  125. struct msghdr msg;
  126. struct iovec iov;
  127. struct cmsghdr *cmsgptr;
  128. struct in6_pktinfo *pkt;
  129. struct sockaddr_in6 addr;
  130. #ifdef HAVE_SOCKADDR_DL
  131. struct sockaddr_dl *sdl;
  132. #endif /* HAVE_SOCKADDR_DL */
  133. static void *adata = NULL;
  134. unsigned char buf[RTADV_MSG_SIZE];
  135. struct nd_router_advert *rtadv;
  136. int ret;
  137. int len = 0;
  138. struct zebra_if *zif;
  139. u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
  140. struct listnode *node;
  141. /*
  142. * Allocate control message bufffer. This is dynamic because
  143. * CMSG_SPACE is not guaranteed not to call a function. Note that
  144. * the size will be different on different architectures due to
  145. * differing alignment rules.
  146. */
  147. if (adata == NULL)
  148. {
  149. /* XXX Free on shutdown. */
  150. adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
  151. if (adata == NULL)
  152. zlog_err("rtadv_send_packet: can't malloc control data\n");
  153. }
  154. /* Logging of packet. */
  155. if (IS_ZEBRA_DEBUG_PACKET)
  156. zlog_debug ("Router advertisement send to %s", ifp->name);
  157. /* Fill in sockaddr_in6. */
  158. memset (&addr, 0, sizeof (struct sockaddr_in6));
  159. addr.sin6_family = AF_INET6;
  160. #ifdef SIN6_LEN
  161. addr.sin6_len = sizeof (struct sockaddr_in6);
  162. #endif /* SIN6_LEN */
  163. addr.sin6_port = htons (IPPROTO_ICMPV6);
  164. memcpy (&addr.sin6_addr, all_nodes_addr, sizeof (struct in6_addr));
  165. /* Fetch interface information. */
  166. zif = ifp->info;
  167. /* Make router advertisement message. */
  168. rtadv = (struct nd_router_advert *) buf;
  169. rtadv->nd_ra_type = ND_ROUTER_ADVERT;
  170. rtadv->nd_ra_code = 0;
  171. rtadv->nd_ra_cksum = 0;
  172. rtadv->nd_ra_curhoplimit = 64;
  173. rtadv->nd_ra_flags_reserved = 0;
  174. if (zif->rtadv.AdvManagedFlag)
  175. rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
  176. if (zif->rtadv.AdvOtherConfigFlag)
  177. rtadv->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
  178. rtadv->nd_ra_router_lifetime = htons (zif->rtadv.AdvDefaultLifetime);
  179. rtadv->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
  180. rtadv->nd_ra_retransmit = htonl (0);
  181. len = sizeof (struct nd_router_advert);
  182. /* Fill in prefix. */
  183. for (node = listhead (zif->rtadv.AdvPrefixList); node; node = nextnode (node))
  184. {
  185. struct nd_opt_prefix_info *pinfo;
  186. struct rtadv_prefix *rprefix;
  187. rprefix = getdata (node);
  188. pinfo = (struct nd_opt_prefix_info *) (buf + len);
  189. pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
  190. pinfo->nd_opt_pi_len = 4;
  191. pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
  192. pinfo->nd_opt_pi_flags_reserved = 0;
  193. if (rprefix->AdvOnLinkFlag)
  194. pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
  195. if (rprefix->AdvAutonomousFlag)
  196. pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
  197. pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
  198. pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
  199. pinfo->nd_opt_pi_reserved2 = 0;
  200. memcpy (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.u.prefix6,
  201. sizeof (struct in6_addr));
  202. #ifdef DEBUG
  203. {
  204. u_char buf[INET6_ADDRSTRLEN];
  205. zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
  206. buf, INET6_ADDRSTRLEN));
  207. }
  208. #endif /* DEBUG */
  209. len += sizeof (struct nd_opt_prefix_info);
  210. }
  211. /* Hardware address. */
  212. #ifdef HAVE_SOCKADDR_DL
  213. sdl = &ifp->sdl;
  214. if (sdl != NULL && sdl->sdl_alen != 0)
  215. {
  216. buf[len++] = ND_OPT_SOURCE_LINKADDR;
  217. buf[len++] = (sdl->sdl_alen + 2) >> 3;
  218. memcpy (buf + len, LLADDR (sdl), sdl->sdl_alen);
  219. len += sdl->sdl_alen;
  220. }
  221. #else
  222. if (ifp->hw_addr_len != 0)
  223. {
  224. buf[len++] = ND_OPT_SOURCE_LINKADDR;
  225. buf[len++] = (ifp->hw_addr_len + 2) >> 3;
  226. memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
  227. len += ifp->hw_addr_len;
  228. }
  229. #endif /* HAVE_SOCKADDR_DL */
  230. msg.msg_name = (void *) &addr;
  231. msg.msg_namelen = sizeof (struct sockaddr_in6);
  232. msg.msg_iov = &iov;
  233. msg.msg_iovlen = 1;
  234. msg.msg_control = (void *) adata;
  235. msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
  236. msg.msg_flags = 0;
  237. iov.iov_base = buf;
  238. iov.iov_len = len;
  239. cmsgptr = ZCMSG_FIRSTHDR(&msg);
  240. cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
  241. cmsgptr->cmsg_level = IPPROTO_IPV6;
  242. cmsgptr->cmsg_type = IPV6_PKTINFO;
  243. pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
  244. memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
  245. pkt->ipi6_ifindex = ifp->ifindex;
  246. ret = sendmsg (sock, &msg, 0);
  247. if (ret < 0)
  248. {
  249. zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
  250. errno, safe_strerror(errno));
  251. }
  252. }
  253. int
  254. rtadv_timer (struct thread *thread)
  255. {
  256. struct listnode *node;
  257. struct interface *ifp;
  258. struct zebra_if *zif;
  259. rtadv->ra_timer = NULL;
  260. rtadv_event (RTADV_TIMER, 1);
  261. for (node = listhead (iflist); node; nextnode (node))
  262. {
  263. ifp = getdata (node);
  264. if (if_is_loopback (ifp))
  265. continue;
  266. zif = ifp->info;
  267. if (zif->rtadv.AdvSendAdvertisements)
  268. if (--zif->rtadv.AdvIntervalTimer <= 0)
  269. {
  270. zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
  271. rtadv_send_packet (rtadv->sock, ifp);
  272. }
  273. }
  274. return 0;
  275. }
  276. void
  277. rtadv_process_solicit (struct interface *ifp)
  278. {
  279. zlog_info ("Router solicitation received on %s", ifp->name);
  280. rtadv_send_packet (rtadv->sock, ifp);
  281. }
  282. void
  283. rtadv_process_advert ()
  284. {
  285. zlog_info ("Router advertisement received");
  286. }
  287. void
  288. rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit)
  289. {
  290. struct icmp6_hdr *icmph;
  291. struct interface *ifp;
  292. struct zebra_if *zif;
  293. /* Interface search. */
  294. ifp = if_lookup_by_index (ifindex);
  295. if (ifp == NULL)
  296. {
  297. zlog_warn ("Unknown interface index: %d", ifindex);
  298. return;
  299. }
  300. if (if_is_loopback (ifp))
  301. return;
  302. /* Check interface configuration. */
  303. zif = ifp->info;
  304. if (! zif->rtadv.AdvSendAdvertisements)
  305. return;
  306. /* ICMP message length check. */
  307. if (len < sizeof (struct icmp6_hdr))
  308. {
  309. zlog_warn ("Invalid ICMPV6 packet length: %d", len);
  310. return;
  311. }
  312. icmph = (struct icmp6_hdr *) buf;
  313. /* ICMP message type check. */
  314. if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
  315. icmph->icmp6_type != ND_ROUTER_ADVERT)
  316. {
  317. zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
  318. return;
  319. }
  320. /* Hoplimit check. */
  321. if (hoplimit >= 0 && hoplimit != 255)
  322. {
  323. zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
  324. hoplimit);
  325. return;
  326. }
  327. /* Check ICMP message type. */
  328. if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
  329. rtadv_process_solicit (ifp);
  330. else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
  331. rtadv_process_advert ();
  332. return;
  333. }
  334. int
  335. rtadv_read (struct thread *thread)
  336. {
  337. int sock;
  338. int len;
  339. u_char buf[RTADV_MSG_SIZE];
  340. struct sockaddr_in6 from;
  341. unsigned int ifindex;
  342. int hoplimit = -1;
  343. sock = THREAD_FD (thread);
  344. rtadv->ra_read = NULL;
  345. /* Register myself. */
  346. rtadv_event (RTADV_READ, sock);
  347. len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
  348. if (len < 0)
  349. {
  350. zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
  351. return len;
  352. }
  353. rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit);
  354. return 0;
  355. }
  356. int
  357. rtadv_make_socket (void)
  358. {
  359. int sock;
  360. int ret;
  361. struct icmp6_filter filter;
  362. if ( zserv_privs.change (ZPRIVS_RAISE) )
  363. zlog_err ("rtadv_make_socket: could not raise privs, %s",
  364. safe_strerror (errno) );
  365. sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
  366. if ( zserv_privs.change (ZPRIVS_LOWER) )
  367. zlog_err ("rtadv_make_socket: could not lower privs, %s",
  368. safe_strerror (errno) );
  369. /* When we can't make ICMPV6 socket simply back. Router
  370. advertisement feature will not be supported. */
  371. if (sock < 0)
  372. return -1;
  373. ret = setsockopt_ipv6_pktinfo (sock, 1);
  374. if (ret < 0)
  375. return ret;
  376. ret = setsockopt_ipv6_multicast_loop (sock, 0);
  377. if (ret < 0)
  378. return ret;
  379. ret = setsockopt_ipv6_unicast_hops (sock, 255);
  380. if (ret < 0)
  381. return ret;
  382. ret = setsockopt_ipv6_multicast_hops (sock, 255);
  383. if (ret < 0)
  384. return ret;
  385. ret = setsockopt_ipv6_hoplimit (sock, 1);
  386. if (ret < 0)
  387. return ret;
  388. ICMP6_FILTER_SETBLOCKALL(&filter);
  389. ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
  390. ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
  391. ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
  392. sizeof (struct icmp6_filter));
  393. if (ret < 0)
  394. {
  395. zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
  396. return ret;
  397. }
  398. return sock;
  399. }
  400. struct rtadv_prefix *
  401. rtadv_prefix_new ()
  402. {
  403. struct rtadv_prefix *new;
  404. new = XMALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
  405. memset (new, 0, sizeof (struct rtadv_prefix));
  406. return new;
  407. }
  408. void
  409. rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
  410. {
  411. XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
  412. }
  413. struct rtadv_prefix *
  414. rtadv_prefix_lookup (struct list *rplist, struct prefix *p)
  415. {
  416. struct listnode *node;
  417. struct rtadv_prefix *rprefix;
  418. for (node = listhead (rplist); node; node = nextnode (node))
  419. {
  420. rprefix = getdata (node);
  421. if (prefix_same (&rprefix->prefix, p))
  422. return rprefix;
  423. }
  424. return NULL;
  425. }
  426. struct rtadv_prefix *
  427. rtadv_prefix_get (struct list *rplist, struct prefix *p)
  428. {
  429. struct rtadv_prefix *rprefix;
  430. rprefix = rtadv_prefix_lookup (rplist, p);
  431. if (rprefix)
  432. return rprefix;
  433. rprefix = rtadv_prefix_new ();
  434. memcpy (&rprefix->prefix, p, sizeof (struct prefix));
  435. listnode_add (rplist, rprefix);
  436. return rprefix;
  437. }
  438. void
  439. rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
  440. {
  441. struct rtadv_prefix *rprefix;
  442. rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
  443. /* Set parameters. */
  444. rprefix->AdvValidLifetime = rp->AdvValidLifetime;
  445. rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
  446. rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
  447. rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
  448. }
  449. int
  450. rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
  451. {
  452. struct rtadv_prefix *rprefix;
  453. rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
  454. if (rprefix != NULL)
  455. {
  456. listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
  457. rtadv_prefix_free (rprefix);
  458. return 1;
  459. }
  460. else
  461. return 0;
  462. }
  463. DEFUN (ipv6_nd_suppress_ra,
  464. ipv6_nd_suppress_ra_cmd,
  465. "ipv6 nd suppress-ra",
  466. "Interface IPv6 config commands\n"
  467. "Neighbor discovery\n"
  468. "Suppress Router Advertisement\n")
  469. {
  470. struct interface *ifp;
  471. struct zebra_if *zif;
  472. ifp = vty->index;
  473. zif = ifp->info;
  474. if (if_is_loopback (ifp))
  475. {
  476. vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
  477. return CMD_WARNING;
  478. }
  479. if (zif->rtadv.AdvSendAdvertisements)
  480. {
  481. zif->rtadv.AdvSendAdvertisements = 0;
  482. zif->rtadv.AdvIntervalTimer = 0;
  483. rtadv->adv_if_count--;
  484. if_leave_all_router (rtadv->sock, ifp);
  485. if (rtadv->adv_if_count == 0)
  486. rtadv_event (RTADV_STOP, 0);
  487. }
  488. return CMD_SUCCESS;
  489. }
  490. DEFUN (no_ipv6_nd_suppress_ra,
  491. no_ipv6_nd_suppress_ra_cmd,
  492. "no ipv6 nd suppress-ra",
  493. NO_STR
  494. "Interface IPv6 config commands\n"
  495. "Neighbor discovery\n"
  496. "Suppress Router Advertisement\n")
  497. {
  498. struct interface *ifp;
  499. struct zebra_if *zif;
  500. ifp = vty->index;
  501. zif = ifp->info;
  502. if (if_is_loopback (ifp))
  503. {
  504. vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
  505. return CMD_WARNING;
  506. }
  507. if (! zif->rtadv.AdvSendAdvertisements)
  508. {
  509. zif->rtadv.AdvSendAdvertisements = 1;
  510. zif->rtadv.AdvIntervalTimer = 0;
  511. rtadv->adv_if_count++;
  512. if_join_all_router (rtadv->sock, ifp);
  513. if (rtadv->adv_if_count == 1)
  514. rtadv_event (RTADV_START, rtadv->sock);
  515. }
  516. return CMD_SUCCESS;
  517. }
  518. DEFUN (ipv6_nd_ra_interval,
  519. ipv6_nd_ra_interval_cmd,
  520. "ipv6 nd ra-interval SECONDS",
  521. "Interface IPv6 config commands\n"
  522. "Neighbor discovery\n"
  523. "Router Advertisement interval\n"
  524. "Router Advertisement interval in seconds\n")
  525. {
  526. int interval;
  527. struct interface *ifp;
  528. struct zebra_if *zif;
  529. ifp = (struct interface *) vty->index;
  530. zif = ifp->info;
  531. interval = atoi (argv[0]);
  532. if (interval < 0)
  533. {
  534. vty_out (vty, "Invalid Router Advertisement Interval%s", VTY_NEWLINE);
  535. return CMD_WARNING;
  536. }
  537. zif->rtadv.MaxRtrAdvInterval = interval;
  538. zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
  539. zif->rtadv.AdvIntervalTimer = 0;
  540. return CMD_SUCCESS;
  541. }
  542. DEFUN (no_ipv6_nd_ra_interval,
  543. no_ipv6_nd_ra_interval_cmd,
  544. "no ipv6 nd ra-interval",
  545. NO_STR
  546. "Interface IPv6 config commands\n"
  547. "Neighbor discovery\n"
  548. "Router Advertisement interval\n")
  549. {
  550. struct interface *ifp;
  551. struct zebra_if *zif;
  552. ifp = (struct interface *) vty->index;
  553. zif = ifp->info;
  554. zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
  555. zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
  556. zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
  557. return CMD_SUCCESS;
  558. }
  559. DEFUN (ipv6_nd_ra_lifetime,
  560. ipv6_nd_ra_lifetime_cmd,
  561. "ipv6 nd ra-lifetime SECONDS",
  562. "Interface IPv6 config commands\n"
  563. "Neighbor discovery\n"
  564. "Router lifetime\n"
  565. "Router lifetime in seconds\n")
  566. {
  567. int lifetime;
  568. struct interface *ifp;
  569. struct zebra_if *zif;
  570. ifp = (struct interface *) vty->index;
  571. zif = ifp->info;
  572. lifetime = atoi (argv[0]);
  573. if (lifetime < 0 || lifetime > 0xffff)
  574. {
  575. vty_out (vty, "Invalid Router Lifetime%s", VTY_NEWLINE);
  576. return CMD_WARNING;
  577. }
  578. zif->rtadv.AdvDefaultLifetime = lifetime;
  579. return CMD_SUCCESS;
  580. }
  581. DEFUN (no_ipv6_nd_ra_lifetime,
  582. no_ipv6_nd_ra_lifetime_cmd,
  583. "no ipv6 nd ra-lifetime",
  584. NO_STR
  585. "Interface IPv6 config commands\n"
  586. "Neighbor discovery\n"
  587. "Router lifetime\n")
  588. {
  589. struct interface *ifp;
  590. struct zebra_if *zif;
  591. ifp = (struct interface *) vty->index;
  592. zif = ifp->info;
  593. zif->rtadv.AdvDefaultLifetime = RTADV_ADV_DEFAULT_LIFETIME;
  594. return CMD_SUCCESS;
  595. }
  596. DEFUN (ipv6_nd_reachable_time,
  597. ipv6_nd_reachable_time_cmd,
  598. "ipv6 nd reachable-time MILLISECONDS",
  599. "Interface IPv6 config commands\n"
  600. "Neighbor discovery\n"
  601. "Reachable time\n"
  602. "Reachable time in milliseconds\n")
  603. {
  604. u_int32_t rtime;
  605. struct interface *ifp;
  606. struct zebra_if *zif;
  607. ifp = (struct interface *) vty->index;
  608. zif = ifp->info;
  609. rtime = (u_int32_t) atol (argv[0]);
  610. if (rtime > RTADV_MAX_REACHABLE_TIME)
  611. {
  612. vty_out (vty, "Invalid Reachable time%s", VTY_NEWLINE);
  613. return CMD_WARNING;
  614. }
  615. zif->rtadv.AdvReachableTime = rtime;
  616. return CMD_SUCCESS;
  617. }
  618. DEFUN (no_ipv6_nd_reachable_time,
  619. no_ipv6_nd_reachable_time_cmd,
  620. "no ipv6 nd reachable-time",
  621. NO_STR
  622. "Interface IPv6 config commands\n"
  623. "Neighbor discovery\n"
  624. "Reachable time\n")
  625. {
  626. struct interface *ifp;
  627. struct zebra_if *zif;
  628. ifp = (struct interface *) vty->index;
  629. zif = ifp->info;
  630. zif->rtadv.AdvReachableTime = 0;
  631. return CMD_SUCCESS;
  632. }
  633. DEFUN (ipv6_nd_managed_config_flag,
  634. ipv6_nd_managed_config_flag_cmd,
  635. "ipv6 nd managed-config-flag",
  636. "Interface IPv6 config commands\n"
  637. "Neighbor discovery\n"
  638. "Managed address configuration flag\n")
  639. {
  640. struct interface *ifp;
  641. struct zebra_if *zif;
  642. ifp = (struct interface *) vty->index;
  643. zif = ifp->info;
  644. zif->rtadv.AdvManagedFlag = 1;
  645. return CMD_SUCCESS;
  646. }
  647. DEFUN (no_ipv6_nd_managed_config_flag,
  648. no_ipv6_nd_managed_config_flag_cmd,
  649. "no ipv6 nd managed-config-flag",
  650. NO_STR
  651. "Interface IPv6 config commands\n"
  652. "Neighbor discovery\n"
  653. "Managed address configuration flag\n")
  654. {
  655. struct interface *ifp;
  656. struct zebra_if *zif;
  657. ifp = (struct interface *) vty->index;
  658. zif = ifp->info;
  659. zif->rtadv.AdvManagedFlag = 0;
  660. return CMD_SUCCESS;
  661. }
  662. DEFUN (ipv6_nd_other_config_flag,
  663. ipv6_nd_other_config_flag_cmd,
  664. "ipv6 nd other-config-flag",
  665. "Interface IPv6 config commands\n"
  666. "Neighbor discovery\n"
  667. "Other statefull configuration flag\n")
  668. {
  669. struct interface *ifp;
  670. struct zebra_if *zif;
  671. ifp = (struct interface *) vty->index;
  672. zif = ifp->info;
  673. zif->rtadv.AdvOtherConfigFlag = 1;
  674. return CMD_SUCCESS;
  675. }
  676. DEFUN (no_ipv6_nd_other_config_flag,
  677. no_ipv6_nd_other_config_flag_cmd,
  678. "no ipv6 nd other-config-flag",
  679. NO_STR
  680. "Interface IPv6 config commands\n"
  681. "Neighbor discovery\n"
  682. "Other statefull configuration flag\n")
  683. {
  684. struct interface *ifp;
  685. struct zebra_if *zif;
  686. ifp = (struct interface *) vty->index;
  687. zif = ifp->info;
  688. zif->rtadv.AdvOtherConfigFlag = 0;
  689. return CMD_SUCCESS;
  690. }
  691. DEFUN (ipv6_nd_prefix,
  692. ipv6_nd_prefix_cmd,
  693. "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
  694. "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
  695. "Interface IPv6 config commands\n"
  696. "Neighbor discovery\n"
  697. "Prefix information\n"
  698. "IPv6 prefix\n"
  699. "Valid lifetime in seconds\n"
  700. "Infinite valid lifetime\n"
  701. "Preferred lifetime in seconds\n"
  702. "Infinite preferred lifetime\n"
  703. "Do not use prefix for onlink determination\n"
  704. "Do not use prefix for autoconfiguration\n")
  705. {
  706. int i;
  707. int ret;
  708. int cursor = 1;
  709. struct interface *ifp;
  710. struct zebra_if *zebra_if;
  711. struct rtadv_prefix rp;
  712. ifp = (struct interface *) vty->index;
  713. zebra_if = ifp->info;
  714. ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
  715. if (!ret)
  716. {
  717. vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
  718. return CMD_WARNING;
  719. }
  720. rp.AdvOnLinkFlag = 1;
  721. rp.AdvAutonomousFlag = 1;
  722. rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
  723. rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
  724. if (argc > 1)
  725. {
  726. if ((isdigit(argv[1][0])) || strncmp (argv[1], "i", 1) == 0)
  727. {
  728. if ( strncmp (argv[1], "i", 1) == 0)
  729. rp.AdvValidLifetime = UINT32_MAX;
  730. else
  731. rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
  732. (char **)NULL, 10);
  733. if ( strncmp (argv[2], "i", 1) == 0)
  734. rp.AdvPreferredLifetime = UINT32_MAX;
  735. else
  736. rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
  737. (char **)NULL, 10);
  738. if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
  739. {
  740. vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
  741. return CMD_WARNING;
  742. }
  743. cursor = cursor + 2;
  744. }
  745. if (argc > cursor)
  746. {
  747. for (i = cursor; i < argc; i++)
  748. {
  749. if (strncmp (argv[i], "of", 2) == 0)
  750. rp.AdvOnLinkFlag = 0;
  751. if (strncmp (argv[i], "no", 2) == 0)
  752. rp.AdvAutonomousFlag = 0;
  753. }
  754. }
  755. }
  756. rtadv_prefix_set (zebra_if, &rp);
  757. return CMD_SUCCESS;
  758. }
  759. ALIAS (ipv6_nd_prefix,
  760. ipv6_nd_prefix_val_rev_cmd,
  761. "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
  762. "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
  763. "Interface IPv6 config commands\n"
  764. "Neighbor discovery\n"
  765. "Prefix information\n"
  766. "IPv6 prefix\n"
  767. "Valid lifetime in seconds\n"
  768. "Infinite valid lifetime\n"
  769. "Preferred lifetime in seconds\n"
  770. "Infinite preferred lifetime\n"
  771. "Do not use prefix for autoconfiguration\n"
  772. "Do not use prefix for onlink determination\n")
  773. ALIAS (ipv6_nd_prefix,
  774. ipv6_nd_prefix_val_noauto_cmd,
  775. "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
  776. "(<0-4294967295>|infinite) (no-autoconfig|)",
  777. "Interface IPv6 config commands\n"
  778. "Neighbor discovery\n"
  779. "Prefix information\n"
  780. "IPv6 prefix\n"
  781. "Valid lifetime in seconds\n"
  782. "Infinite valid lifetime\n"
  783. "Preferred lifetime in seconds\n"
  784. "Infinite preferred lifetime\n"
  785. "Do not use prefix for autoconfigurationn")
  786. ALIAS (ipv6_nd_prefix,
  787. ipv6_nd_prefix_val_offlink_cmd,
  788. "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
  789. "(<0-4294967295>|infinite) (off-link|)",
  790. "Interface IPv6 config commands\n"
  791. "Neighbor discovery\n"
  792. "Prefix information\n"
  793. "IPv6 prefix\n"
  794. "Valid lifetime in seconds\n"
  795. "Infinite valid lifetime\n"
  796. "Preferred lifetime in seconds\n"
  797. "Infinite preferred lifetime\n"
  798. "Do not use prefix for onlink determination\n")
  799. ALIAS (ipv6_nd_prefix,
  800. ipv6_nd_prefix_val_cmd,
  801. "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
  802. "(<0-4294967295>|infinite)",
  803. "Interface IPv6 config commands\n"
  804. "Neighbor discovery\n"
  805. "Prefix information\n"
  806. "IPv6 prefix\n"
  807. "Valid lifetime in seconds\n"
  808. "Infinite valid lifetime\n"
  809. "Preferred lifetime in seconds\n"
  810. "Infinite preferred lifetime\n")
  811. ALIAS (ipv6_nd_prefix,
  812. ipv6_nd_prefix_noval_cmd,
  813. "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
  814. "Interface IPv6 config commands\n"
  815. "Neighbor discovery\n"
  816. "Prefix information\n"
  817. "IPv6 prefix\n"
  818. "Do not use prefix for autoconfiguration\n"
  819. "Do not use prefix for onlink determination\n")
  820. ALIAS (ipv6_nd_prefix,
  821. ipv6_nd_prefix_noval_rev_cmd,
  822. "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
  823. "Interface IPv6 config commands\n"
  824. "Neighbor discovery\n"
  825. "Prefix information\n"
  826. "IPv6 prefix\n"
  827. "Do not use prefix for onlink determination\n"
  828. "Do not use prefix for autoconfiguration\n")
  829. ALIAS (ipv6_nd_prefix,
  830. ipv6_nd_prefix_noval_noauto_cmd,
  831. "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
  832. "Interface IPv6 config commands\n"
  833. "Neighbor discovery\n"
  834. "Prefix information\n"
  835. "IPv6 prefix\n"
  836. "Do not use prefix for autoconfiguration\n")
  837. ALIAS (ipv6_nd_prefix,
  838. ipv6_nd_prefix_noval_offlink_cmd,
  839. "ipv6 nd prefix X:X::X:X/M (off-link|)",
  840. "Interface IPv6 config commands\n"
  841. "Neighbor discovery\n"
  842. "Prefix information\n"
  843. "IPv6 prefix\n"
  844. "Do not use prefix for onlink determination\n")
  845. ALIAS (ipv6_nd_prefix,
  846. ipv6_nd_prefix_prefix_cmd,
  847. "ipv6 nd prefix X:X::X:X/M",
  848. "Interface IPv6 config commands\n"
  849. "Neighbor discovery\n"
  850. "Prefix information\n"
  851. "IPv6 prefix\n")
  852. DEFUN (no_ipv6_nd_prefix,
  853. no_ipv6_nd_prefix_cmd,
  854. "no ipv6 nd prefix IPV6PREFIX",
  855. NO_STR
  856. "Interface IPv6 config commands\n"
  857. "Neighbor discovery\n"
  858. "Prefix information\n"
  859. "IPv6 prefix\n")
  860. {
  861. int ret;
  862. struct interface *ifp;
  863. struct zebra_if *zebra_if;
  864. struct rtadv_prefix rp;
  865. ifp = (struct interface *) vty->index;
  866. zebra_if = ifp->info;
  867. ret = str2prefix_ipv6 (argv[0], (struct prefix_ipv6 *) &rp.prefix);
  868. if (!ret)
  869. {
  870. vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
  871. return CMD_WARNING;
  872. }
  873. ret = rtadv_prefix_reset (zebra_if, &rp);
  874. if (!ret)
  875. {
  876. vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
  877. return CMD_WARNING;
  878. }
  879. return CMD_SUCCESS;
  880. }
  881. /* Write configuration about router advertisement. */
  882. void
  883. rtadv_config_write (struct vty *vty, struct interface *ifp)
  884. {
  885. struct zebra_if *zif;
  886. struct listnode *node;
  887. struct rtadv_prefix *rprefix;
  888. u_char buf[INET6_ADDRSTRLEN];
  889. if (! rtadv)
  890. return;
  891. zif = ifp->info;
  892. if (! if_is_loopback (ifp))
  893. {
  894. if (zif->rtadv.AdvSendAdvertisements)
  895. vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE);
  896. else
  897. vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE);
  898. }
  899. if (zif->rtadv.MaxRtrAdvInterval != RTADV_MAX_RTR_ADV_INTERVAL)
  900. vty_out (vty, " ipv6 nd ra-interval %d%s", zif->rtadv.MaxRtrAdvInterval,
  901. VTY_NEWLINE);
  902. if (zif->rtadv.AdvDefaultLifetime != RTADV_ADV_DEFAULT_LIFETIME)
  903. vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
  904. VTY_NEWLINE);
  905. if (zif->rtadv.AdvReachableTime)
  906. vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
  907. VTY_NEWLINE);
  908. if (zif->rtadv.AdvManagedFlag)
  909. vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
  910. if (zif->rtadv.AdvOtherConfigFlag)
  911. vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
  912. for (node = listhead(zif->rtadv.AdvPrefixList); node; node = nextnode (node))
  913. {
  914. rprefix = getdata (node);
  915. vty_out (vty, " ipv6 nd prefix %s/%d",
  916. inet_ntop (AF_INET6, &rprefix->prefix.u.prefix6,
  917. (char *) buf, INET6_ADDRSTRLEN),
  918. rprefix->prefix.prefixlen);
  919. if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
  920. (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
  921. {
  922. if (rprefix->AdvValidLifetime == UINT32_MAX)
  923. vty_out (vty, " infinite");
  924. else
  925. vty_out (vty, " %u", rprefix->AdvValidLifetime);
  926. if (rprefix->AdvPreferredLifetime == UINT32_MAX)
  927. vty_out (vty, " infinite");
  928. else
  929. vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
  930. }
  931. if (!rprefix->AdvOnLinkFlag)
  932. vty_out (vty, " off-link");
  933. if (!rprefix->AdvAutonomousFlag)
  934. vty_out (vty, " no-autoconfig");
  935. vty_out (vty, "%s", VTY_NEWLINE);
  936. }
  937. }
  938. void
  939. rtadv_event (enum rtadv_event event, int val)
  940. {
  941. switch (event)
  942. {
  943. case RTADV_START:
  944. if (! rtadv->ra_read)
  945. rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
  946. if (! rtadv->ra_timer)
  947. rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
  948. NULL, 0);
  949. break;
  950. case RTADV_STOP:
  951. if (rtadv->ra_timer)
  952. {
  953. thread_cancel (rtadv->ra_timer);
  954. rtadv->ra_timer = NULL;
  955. }
  956. if (rtadv->ra_read)
  957. {
  958. thread_cancel (rtadv->ra_read);
  959. rtadv->ra_read = NULL;
  960. }
  961. break;
  962. case RTADV_TIMER:
  963. if (! rtadv->ra_timer)
  964. rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
  965. val);
  966. break;
  967. case RTADV_READ:
  968. if (! rtadv->ra_read)
  969. rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
  970. break;
  971. default:
  972. break;
  973. }
  974. return;
  975. }
  976. void
  977. rtadv_init ()
  978. {
  979. int sock;
  980. sock = rtadv_make_socket ();
  981. if (sock < 0)
  982. return;
  983. rtadv = rtadv_new ();
  984. rtadv->sock = sock;
  985. install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
  986. install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
  987. install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
  988. install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
  989. install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
  990. install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
  991. install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
  992. install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
  993. install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
  994. install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
  995. install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
  996. install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
  997. install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
  998. install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
  999. install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
  1000. install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
  1001. install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
  1002. install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
  1003. install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
  1004. install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
  1005. install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
  1006. install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
  1007. install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
  1008. }
  1009. int
  1010. if_join_all_router (int sock, struct interface *ifp)
  1011. {
  1012. int ret;
  1013. struct ipv6_mreq mreq;
  1014. memset (&mreq, 0, sizeof (struct ipv6_mreq));
  1015. inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
  1016. mreq.ipv6mr_interface = ifp->ifindex;
  1017. ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  1018. (char *) &mreq, sizeof mreq);
  1019. if (ret < 0)
  1020. zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
  1021. zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
  1022. return 0;
  1023. }
  1024. int
  1025. if_leave_all_router (int sock, struct interface *ifp)
  1026. {
  1027. int ret;
  1028. struct ipv6_mreq mreq;
  1029. memset (&mreq, 0, sizeof (struct ipv6_mreq));
  1030. inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
  1031. mreq.ipv6mr_interface = ifp->ifindex;
  1032. ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
  1033. (char *) &mreq, sizeof mreq);
  1034. if (ret < 0)
  1035. zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
  1036. zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
  1037. return 0;
  1038. }
  1039. #else
  1040. void
  1041. rtadv_init ()
  1042. {
  1043. /* Empty.*/;
  1044. }
  1045. #endif /* RTADV && HAVE_IPV6 */