rtadv.c 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634
  1. /* Router advertisement
  2. * Copyright (C) 2005 6WIND <jean-mickael.guerin@6wind.com>
  3. * Copyright (C) 1999 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 "memory.h"
  24. #include "sockopt.h"
  25. #include "thread.h"
  26. #include "if.h"
  27. #include "log.h"
  28. #include "prefix.h"
  29. #include "command.h"
  30. #include "privs.h"
  31. #include "vrf.h"
  32. #include "zebra/interface.h"
  33. #include "zebra/rtadv.h"
  34. #include "zebra/debug.h"
  35. #include "zebra/rib.h"
  36. #include "zebra/zserv.h"
  37. extern struct zebra_privs_t zserv_privs;
  38. #if defined (HAVE_IPV6) && defined (HAVE_RTADV)
  39. #ifdef OPEN_BSD
  40. #include <netinet/icmp6.h>
  41. #endif
  42. /* If RFC2133 definition is used. */
  43. #ifndef IPV6_JOIN_GROUP
  44. #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP
  45. #endif
  46. #ifndef IPV6_LEAVE_GROUP
  47. #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
  48. #endif
  49. #define ALLNODE "ff02::1"
  50. #define ALLROUTER "ff02::2"
  51. extern struct zebra_t zebrad;
  52. enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER,
  53. RTADV_TIMER_MSEC, RTADV_READ};
  54. static void rtadv_event (struct zebra_vrf *, enum rtadv_event, int);
  55. static int if_join_all_router (int, struct interface *);
  56. static int if_leave_all_router (int, struct interface *);
  57. /* Order is intentional. Matches RFC4191. This array is also used for
  58. command matching, so only modify with care. */
  59. static const struct message rtadv_pref_strs[] =
  60. {
  61. { RTADV_PREF_MEDIUM, "medium" },
  62. { RTADV_PREF_HIGH, "high" },
  63. { RTADV_PREF_RESERVED, "INVALID" },
  64. { RTADV_PREF_LOW, "low" },
  65. };
  66. static const size_t rtadv_pref_strs_max = sizeof (rtadv_pref_strs) / sizeof (struct message);
  67. static int
  68. rtadv_recv_packet (int sock, u_char *buf, int buflen,
  69. struct sockaddr_in6 *from, ifindex_t *ifindex,
  70. int *hoplimit)
  71. {
  72. int ret;
  73. struct msghdr msg;
  74. struct iovec iov;
  75. struct cmsghdr *cmsgptr;
  76. struct in6_addr dst;
  77. char adata[1024];
  78. /* Fill in message and iovec. */
  79. msg.msg_name = (void *) from;
  80. msg.msg_namelen = sizeof (struct sockaddr_in6);
  81. msg.msg_iov = &iov;
  82. msg.msg_iovlen = 1;
  83. msg.msg_control = (void *) adata;
  84. msg.msg_controllen = sizeof adata;
  85. iov.iov_base = buf;
  86. iov.iov_len = buflen;
  87. /* If recvmsg fail return minus value. */
  88. ret = recvmsg (sock, &msg, 0);
  89. if (ret < 0)
  90. return ret;
  91. for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
  92. cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
  93. {
  94. /* I want interface index which this packet comes from. */
  95. if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
  96. cmsgptr->cmsg_type == IPV6_PKTINFO)
  97. {
  98. struct in6_pktinfo *ptr;
  99. ptr = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
  100. *ifindex = ptr->ipi6_ifindex;
  101. memcpy(&dst, &ptr->ipi6_addr, sizeof(ptr->ipi6_addr));
  102. }
  103. /* Incoming packet's hop limit. */
  104. if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
  105. cmsgptr->cmsg_type == IPV6_HOPLIMIT)
  106. {
  107. int *hoptr = (int *) CMSG_DATA (cmsgptr);
  108. *hoplimit = *hoptr;
  109. }
  110. }
  111. return ret;
  112. }
  113. #define RTADV_MSG_SIZE 4096
  114. static unsigned
  115. rtadv_append_rdnss_tlvs (unsigned char *buf, const struct list *list, const unsigned MaxRAI)
  116. {
  117. struct listnode *node;
  118. struct rtadv_rdnss_entry *rdnss_entry;
  119. unsigned len = 0;
  120. for (ALL_LIST_ELEMENTS_RO (list, node, rdnss_entry))
  121. {
  122. struct nd_opt_rdnss *tlv = (struct nd_opt_rdnss *) (buf + len);
  123. tlv->nd_opt_rdnss_type = ND_OPT_RDNSS;
  124. tlv->nd_opt_rdnss_len = 3; /* 8 bytes header, 16 bytes address */
  125. tlv->nd_opt_rdnss_reserved = 0;
  126. /* RFC6106 sets, that RDNSS Lifetime must be either 0 or "infinity" or
  127. * any value in the [MaxRAI..2*MaxRAI] range, but it doesn't set any
  128. * default value for Lifetime. rtadvd defaults to 2 times the current
  129. * MaxRAI, which seems to be the most reasonable choice. */
  130. tlv->nd_opt_rdnss_lifetime = htonl
  131. (
  132. ! rdnss_entry->track_maxrai ? rdnss_entry->lifetime :
  133. MAX (1, MaxRAI / 500) /* 2*MaxRAI in seconds */
  134. );
  135. len += sizeof (struct nd_opt_rdnss);
  136. IPV6_ADDR_COPY ((struct in6_addr *)(buf + len), &rdnss_entry->address);
  137. len += sizeof (struct in6_addr);
  138. }
  139. return len;
  140. }
  141. static unsigned
  142. rtadv_append_dnssl_tlvs (unsigned char *buf, const struct list *list, const unsigned MaxRAI)
  143. {
  144. struct listnode *node;
  145. struct rtadv_dnssl_entry *dnssl_entry;
  146. unsigned len = 0;
  147. for (ALL_LIST_ELEMENTS_RO (list, node, dnssl_entry))
  148. {
  149. /* This implementation generates one TLV per subdomain, changing this
  150. requires handling padding outside of the cycle and making sure
  151. the size of each TLV doesn't exceed the maximum value. */
  152. struct nd_opt_dnssl *tlv = (struct nd_opt_dnssl *) (buf + len);
  153. size_t padding_bytes = 8 - (dnssl_entry->length_rfc1035 % 8);
  154. tlv->nd_opt_dnssl_type = ND_OPT_DNSSL;
  155. tlv->nd_opt_dnssl_len = (8 + dnssl_entry->length_rfc1035 + padding_bytes) / 8;
  156. tlv->nd_opt_dnssl_reserved = 0;
  157. /* see RDNSS Lifetime comment */
  158. tlv->nd_opt_dnssl_lifetime = htonl
  159. (
  160. ! dnssl_entry->track_maxrai ? dnssl_entry->lifetime :
  161. MAX (1, MaxRAI / 500) /* 2*MaxRAI in seconds */
  162. );
  163. len += sizeof (struct nd_opt_dnssl);
  164. memcpy (buf + len, dnssl_entry->subdomain_rfc1035, dnssl_entry->length_rfc1035);
  165. len += dnssl_entry->length_rfc1035;
  166. if (! padding_bytes)
  167. continue;
  168. memset (buf + len, 0, padding_bytes);
  169. len += padding_bytes;
  170. }
  171. return len;
  172. }
  173. /* Send router advertisement packet. */
  174. static void
  175. rtadv_send_packet (int sock, struct interface *ifp)
  176. {
  177. struct msghdr msg;
  178. struct iovec iov;
  179. struct cmsghdr *cmsgptr;
  180. struct in6_pktinfo *pkt;
  181. struct sockaddr_in6 addr;
  182. #ifdef HAVE_STRUCT_SOCKADDR_DL
  183. struct sockaddr_dl *sdl;
  184. #endif /* HAVE_STRUCT_SOCKADDR_DL */
  185. static void *adata = NULL;
  186. unsigned char buf[RTADV_MSG_SIZE];
  187. struct nd_router_advert *ndra;
  188. int ret;
  189. int len = 0;
  190. struct zebra_if *zif;
  191. struct rtadv_prefix *rprefix;
  192. u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
  193. struct listnode *node;
  194. u_int16_t pkt_RouterLifetime;
  195. struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
  196. /*
  197. * Allocate control message bufffer. This is dynamic because
  198. * CMSG_SPACE is not guaranteed not to call a function. Note that
  199. * the size will be different on different architectures due to
  200. * differing alignment rules.
  201. */
  202. if (adata == NULL)
  203. {
  204. /* XXX Free on shutdown. */
  205. adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
  206. if (adata == NULL)
  207. zlog_err("rtadv_send_packet: can't malloc control data\n");
  208. }
  209. /* Logging of packet. */
  210. if (IS_ZEBRA_DEBUG_PACKET)
  211. zlog_debug ("Router advertisement send to %s", ifp->name);
  212. /* Fill in sockaddr_in6. */
  213. memset (&addr, 0, sizeof (struct sockaddr_in6));
  214. addr.sin6_family = AF_INET6;
  215. #ifdef SIN6_LEN
  216. addr.sin6_len = sizeof (struct sockaddr_in6);
  217. #endif /* SIN6_LEN */
  218. addr.sin6_port = htons (IPPROTO_ICMPV6);
  219. IPV6_ADDR_COPY (&addr.sin6_addr, all_nodes_addr);
  220. /* Fetch interface information. */
  221. zif = ifp->info;
  222. /* Make router advertisement message. */
  223. ndra = (struct nd_router_advert *) buf;
  224. ndra->nd_ra_type = ND_ROUTER_ADVERT;
  225. ndra->nd_ra_code = 0;
  226. ndra->nd_ra_cksum = 0;
  227. ndra->nd_ra_curhoplimit = 64;
  228. /* RFC4191: Default Router Preference is 0 if Router Lifetime is 0. */
  229. ndra->nd_ra_flags_reserved =
  230. zif->rtadv.AdvDefaultLifetime == 0 ? 0 : zif->rtadv.DefaultPreference;
  231. ndra->nd_ra_flags_reserved <<= 3;
  232. if (zif->rtadv.AdvManagedFlag)
  233. ndra->nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
  234. if (zif->rtadv.AdvOtherConfigFlag)
  235. ndra->nd_ra_flags_reserved |= ND_RA_FLAG_OTHER;
  236. if (zif->rtadv.AdvHomeAgentFlag)
  237. ndra->nd_ra_flags_reserved |= ND_RA_FLAG_HOME_AGENT;
  238. /* Note that according to Neighbor Discovery (RFC 4861 [18]),
  239. * AdvDefaultLifetime is by default based on the value of
  240. * MaxRtrAdvInterval. AdvDefaultLifetime is used in the Router Lifetime
  241. * field of Router Advertisements. Given that this field is expressed
  242. * in seconds, a small MaxRtrAdvInterval value can result in a zero
  243. * value for this field. To prevent this, routers SHOULD keep
  244. * AdvDefaultLifetime in at least one second, even if the use of
  245. * MaxRtrAdvInterval would result in a smaller value. -- RFC6275, 7.5 */
  246. pkt_RouterLifetime = zif->rtadv.AdvDefaultLifetime != -1 ?
  247. zif->rtadv.AdvDefaultLifetime :
  248. MAX (1, 0.003 * zif->rtadv.MaxRtrAdvInterval);
  249. ndra->nd_ra_router_lifetime = htons (pkt_RouterLifetime);
  250. ndra->nd_ra_reachable = htonl (zif->rtadv.AdvReachableTime);
  251. ndra->nd_ra_retransmit = htonl (0);
  252. len = sizeof (struct nd_router_advert);
  253. /* If both the Home Agent Preference and Home Agent Lifetime are set to
  254. * their default values specified above, this option SHOULD NOT be
  255. * included in the Router Advertisement messages sent by this home
  256. * agent. -- RFC6275, 7.4 */
  257. if
  258. (
  259. zif->rtadv.AdvHomeAgentFlag &&
  260. (zif->rtadv.HomeAgentPreference || zif->rtadv.HomeAgentLifetime != -1)
  261. )
  262. {
  263. struct nd_opt_homeagent_info *ndopt_hai =
  264. (struct nd_opt_homeagent_info *)(buf + len);
  265. ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
  266. ndopt_hai->nd_opt_hai_len = 1;
  267. ndopt_hai->nd_opt_hai_reserved = 0;
  268. ndopt_hai->nd_opt_hai_preference = htons(zif->rtadv.HomeAgentPreference);
  269. /* 16-bit unsigned integer. The lifetime associated with the home
  270. * agent in units of seconds. The default value is the same as the
  271. * Router Lifetime, as specified in the main body of the Router
  272. * Advertisement. The maximum value corresponds to 18.2 hours. A
  273. * value of 0 MUST NOT be used. -- RFC6275, 7.5 */
  274. ndopt_hai->nd_opt_hai_lifetime = htons
  275. (
  276. zif->rtadv.HomeAgentLifetime != -1 ?
  277. zif->rtadv.HomeAgentLifetime :
  278. MAX (1, pkt_RouterLifetime) /* 0 is OK for RL, but not for HAL*/
  279. );
  280. len += sizeof(struct nd_opt_homeagent_info);
  281. }
  282. /* Fill in all RDNS server entries. */
  283. len += rtadv_append_rdnss_tlvs (buf + len, zvrf->rtadv.AdvRDNSSList,
  284. zif->rtadv.MaxRtrAdvInterval);
  285. len += rtadv_append_rdnss_tlvs (buf + len, zif->rtadv.AdvRDNSSList,
  286. zif->rtadv.MaxRtrAdvInterval);
  287. /* DNSSL TLV(s) */
  288. len += rtadv_append_dnssl_tlvs (buf + len, zvrf->rtadv.AdvDNSSLList,
  289. zif->rtadv.MaxRtrAdvInterval);
  290. len += rtadv_append_dnssl_tlvs (buf + len, zif->rtadv.AdvDNSSLList,
  291. zif->rtadv.MaxRtrAdvInterval);
  292. /* Fill in prefix. */
  293. for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
  294. {
  295. struct nd_opt_prefix_info *pinfo;
  296. pinfo = (struct nd_opt_prefix_info *) (buf + len);
  297. pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
  298. pinfo->nd_opt_pi_len = 4;
  299. pinfo->nd_opt_pi_prefix_len = rprefix->prefix.prefixlen;
  300. pinfo->nd_opt_pi_flags_reserved = 0;
  301. if (rprefix->AdvOnLinkFlag)
  302. pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
  303. if (rprefix->AdvAutonomousFlag)
  304. pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
  305. if (rprefix->AdvRouterAddressFlag)
  306. pinfo->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;
  307. pinfo->nd_opt_pi_valid_time = htonl (rprefix->AdvValidLifetime);
  308. pinfo->nd_opt_pi_preferred_time = htonl (rprefix->AdvPreferredLifetime);
  309. pinfo->nd_opt_pi_reserved2 = 0;
  310. IPV6_ADDR_COPY (&pinfo->nd_opt_pi_prefix, &rprefix->prefix.prefix);
  311. #ifdef DEBUG
  312. {
  313. u_char buf[INET6_ADDRSTRLEN];
  314. zlog_debug ("DEBUG %s", inet_ntop (AF_INET6, &pinfo->nd_opt_pi_prefix,
  315. buf, INET6_ADDRSTRLEN));
  316. }
  317. #endif /* DEBUG */
  318. len += sizeof (struct nd_opt_prefix_info);
  319. }
  320. /* Hardware address. */
  321. if (ifp->hw_addr_len != 0)
  322. {
  323. buf[len++] = ND_OPT_SOURCE_LINKADDR;
  324. /* Option length should be rounded up to next octet if
  325. the link address does not end on an octet boundary. */
  326. buf[len++] = (ifp->hw_addr_len + 9) >> 3;
  327. memcpy (buf + len, ifp->hw_addr, ifp->hw_addr_len);
  328. len += ifp->hw_addr_len;
  329. /* Pad option to end on an octet boundary. */
  330. memset (buf + len, 0, -(ifp->hw_addr_len + 2) & 0x7);
  331. len += -(ifp->hw_addr_len + 2) & 0x7;
  332. }
  333. /* MTU */
  334. if (zif->rtadv.AdvLinkMTU)
  335. {
  336. struct nd_opt_mtu * opt = (struct nd_opt_mtu *) (buf + len);
  337. opt->nd_opt_mtu_type = ND_OPT_MTU;
  338. opt->nd_opt_mtu_len = 1;
  339. opt->nd_opt_mtu_reserved = 0;
  340. opt->nd_opt_mtu_mtu = htonl (zif->rtadv.AdvLinkMTU);
  341. len += sizeof (struct nd_opt_mtu);
  342. }
  343. msg.msg_name = (void *) &addr;
  344. msg.msg_namelen = sizeof (struct sockaddr_in6);
  345. msg.msg_iov = &iov;
  346. msg.msg_iovlen = 1;
  347. msg.msg_control = (void *) adata;
  348. msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
  349. msg.msg_flags = 0;
  350. iov.iov_base = buf;
  351. iov.iov_len = len;
  352. cmsgptr = ZCMSG_FIRSTHDR(&msg);
  353. cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
  354. cmsgptr->cmsg_level = IPPROTO_IPV6;
  355. cmsgptr->cmsg_type = IPV6_PKTINFO;
  356. pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
  357. memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
  358. pkt->ipi6_ifindex = ifp->ifindex;
  359. ret = sendmsg (sock, &msg, 0);
  360. if (ret < 0)
  361. {
  362. zlog_err ("rtadv_send_packet: sendmsg %d (%s)\n",
  363. errno, safe_strerror(errno));
  364. }
  365. }
  366. static int
  367. rtadv_timer (struct thread *thread)
  368. {
  369. struct zebra_vrf *zvrf = THREAD_ARG (thread);
  370. struct listnode *node, *nnode;
  371. struct interface *ifp;
  372. struct zebra_if *zif;
  373. int period;
  374. zvrf->rtadv.ra_timer = NULL;
  375. if (zvrf->rtadv.adv_msec_if_count == 0)
  376. {
  377. period = 1000; /* 1 s */
  378. rtadv_event (zvrf, RTADV_TIMER, 1 /* 1 s */);
  379. }
  380. else
  381. {
  382. period = 10; /* 10 ms */
  383. rtadv_event (zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */);
  384. }
  385. for (ALL_LIST_ELEMENTS (vrf_iflist (zvrf->vrf_id), node, nnode, ifp))
  386. {
  387. if (if_is_loopback (ifp) || ! if_is_operative (ifp))
  388. continue;
  389. zif = ifp->info;
  390. if (zif->rtadv.AdvSendAdvertisements)
  391. {
  392. zif->rtadv.AdvIntervalTimer -= period;
  393. if (zif->rtadv.AdvIntervalTimer <= 0)
  394. {
  395. /* FIXME: using MaxRtrAdvInterval each time isn't what section
  396. 6.2.4 of RFC4861 tells to do. */
  397. zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
  398. rtadv_send_packet (zvrf->rtadv.sock, ifp);
  399. }
  400. }
  401. }
  402. return 0;
  403. }
  404. static void
  405. rtadv_process_solicit (struct interface *ifp)
  406. {
  407. struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
  408. zlog_info ("Router solicitation received on %s vrf %u", ifp->name, zvrf->vrf_id);
  409. rtadv_send_packet (zvrf->rtadv.sock, ifp);
  410. }
  411. static void
  412. rtadv_process_advert (void)
  413. {
  414. zlog_info ("Router advertisement received");
  415. }
  416. static void
  417. rtadv_process_packet (u_char *buf, unsigned int len, ifindex_t ifindex,
  418. int hoplimit, vrf_id_t vrf_id)
  419. {
  420. struct icmp6_hdr *icmph;
  421. struct interface *ifp;
  422. struct zebra_if *zif;
  423. /* Interface search. */
  424. ifp = if_lookup_by_index_vrf (ifindex, vrf_id);
  425. if (ifp == NULL)
  426. {
  427. zlog_warn ("Unknown interface index: %d, vrf %u", ifindex, vrf_id);
  428. return;
  429. }
  430. if (if_is_loopback (ifp))
  431. return;
  432. /* Check interface configuration. */
  433. zif = ifp->info;
  434. if (! zif->rtadv.AdvSendAdvertisements)
  435. return;
  436. /* ICMP message length check. */
  437. if (len < sizeof (struct icmp6_hdr))
  438. {
  439. zlog_warn ("Invalid ICMPV6 packet length: %d", len);
  440. return;
  441. }
  442. icmph = (struct icmp6_hdr *) buf;
  443. /* ICMP message type check. */
  444. if (icmph->icmp6_type != ND_ROUTER_SOLICIT &&
  445. icmph->icmp6_type != ND_ROUTER_ADVERT)
  446. {
  447. zlog_warn ("Unwanted ICMPV6 message type: %d", icmph->icmp6_type);
  448. return;
  449. }
  450. /* Hoplimit check. */
  451. if (hoplimit >= 0 && hoplimit != 255)
  452. {
  453. zlog_warn ("Invalid hoplimit %d for router advertisement ICMP packet",
  454. hoplimit);
  455. return;
  456. }
  457. /* Check ICMP message type. */
  458. if (icmph->icmp6_type == ND_ROUTER_SOLICIT)
  459. rtadv_process_solicit (ifp);
  460. else if (icmph->icmp6_type == ND_ROUTER_ADVERT)
  461. rtadv_process_advert ();
  462. return;
  463. }
  464. static int
  465. rtadv_read (struct thread *thread)
  466. {
  467. int sock;
  468. int len;
  469. u_char buf[RTADV_MSG_SIZE];
  470. struct sockaddr_in6 from;
  471. ifindex_t ifindex = 0;
  472. int hoplimit = -1;
  473. struct zebra_vrf *zvrf = THREAD_ARG (thread);
  474. sock = THREAD_FD (thread);
  475. zvrf->rtadv.ra_read = NULL;
  476. /* Register myself. */
  477. rtadv_event (zvrf, RTADV_READ, sock);
  478. len = rtadv_recv_packet (sock, buf, sizeof (buf), &from, &ifindex, &hoplimit);
  479. if (len < 0)
  480. {
  481. zlog_warn ("router solicitation recv failed: %s.", safe_strerror (errno));
  482. return len;
  483. }
  484. rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit, zvrf->vrf_id);
  485. return 0;
  486. }
  487. static int
  488. rtadv_make_socket (vrf_id_t vrf_id)
  489. {
  490. int sock;
  491. int ret;
  492. struct icmp6_filter filter;
  493. if ( zserv_privs.change (ZPRIVS_RAISE) )
  494. zlog_err ("rtadv_make_socket: could not raise privs, %s",
  495. safe_strerror (errno) );
  496. sock = vrf_socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, vrf_id);
  497. if ( zserv_privs.change (ZPRIVS_LOWER) )
  498. zlog_err ("rtadv_make_socket: could not lower privs, %s",
  499. safe_strerror (errno) );
  500. /* When we can't make ICMPV6 socket simply back. Router
  501. advertisement feature will not be supported. */
  502. if (sock < 0)
  503. {
  504. close (sock);
  505. return -1;
  506. }
  507. ret = setsockopt_ipv6_pktinfo (sock, 1);
  508. if (ret < 0)
  509. {
  510. close (sock);
  511. return ret;
  512. }
  513. ret = setsockopt_ipv6_multicast_loop (sock, 0);
  514. if (ret < 0)
  515. {
  516. close (sock);
  517. return ret;
  518. }
  519. ret = setsockopt_ipv6_unicast_hops (sock, 255);
  520. if (ret < 0)
  521. {
  522. close (sock);
  523. return ret;
  524. }
  525. ret = setsockopt_ipv6_multicast_hops (sock, 255);
  526. if (ret < 0)
  527. {
  528. close (sock);
  529. return ret;
  530. }
  531. ret = setsockopt_ipv6_hoplimit (sock, 1);
  532. if (ret < 0)
  533. {
  534. close (sock);
  535. return ret;
  536. }
  537. ICMP6_FILTER_SETBLOCKALL(&filter);
  538. ICMP6_FILTER_SETPASS (ND_ROUTER_SOLICIT, &filter);
  539. ICMP6_FILTER_SETPASS (ND_ROUTER_ADVERT, &filter);
  540. ret = setsockopt (sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filter,
  541. sizeof (struct icmp6_filter));
  542. if (ret < 0)
  543. {
  544. zlog_info ("ICMP6_FILTER set fail: %s", safe_strerror (errno));
  545. return ret;
  546. }
  547. return sock;
  548. }
  549. static struct rtadv_prefix *
  550. rtadv_prefix_new (void)
  551. {
  552. return XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_prefix));
  553. }
  554. static void
  555. rtadv_prefix_free (struct rtadv_prefix *rtadv_prefix)
  556. {
  557. XFREE (MTYPE_RTADV_PREFIX, rtadv_prefix);
  558. }
  559. static struct rtadv_prefix *
  560. rtadv_prefix_lookup (struct list *rplist, struct prefix_ipv6 *p)
  561. {
  562. struct listnode *node;
  563. struct rtadv_prefix *rprefix;
  564. for (ALL_LIST_ELEMENTS_RO (rplist, node, rprefix))
  565. if (prefix_same ((struct prefix *) &rprefix->prefix, (struct prefix *) p))
  566. return rprefix;
  567. return NULL;
  568. }
  569. static struct rtadv_prefix *
  570. rtadv_prefix_get (struct list *rplist, struct prefix_ipv6 *p)
  571. {
  572. struct rtadv_prefix *rprefix;
  573. rprefix = rtadv_prefix_lookup (rplist, p);
  574. if (rprefix)
  575. return rprefix;
  576. rprefix = rtadv_prefix_new ();
  577. memcpy (&rprefix->prefix, p, sizeof (struct prefix_ipv6));
  578. listnode_add (rplist, rprefix);
  579. return rprefix;
  580. }
  581. static void
  582. rtadv_prefix_set (struct zebra_if *zif, struct rtadv_prefix *rp)
  583. {
  584. struct rtadv_prefix *rprefix;
  585. rprefix = rtadv_prefix_get (zif->rtadv.AdvPrefixList, &rp->prefix);
  586. /* Set parameters. */
  587. rprefix->AdvValidLifetime = rp->AdvValidLifetime;
  588. rprefix->AdvPreferredLifetime = rp->AdvPreferredLifetime;
  589. rprefix->AdvOnLinkFlag = rp->AdvOnLinkFlag;
  590. rprefix->AdvAutonomousFlag = rp->AdvAutonomousFlag;
  591. rprefix->AdvRouterAddressFlag = rp->AdvRouterAddressFlag;
  592. }
  593. static int
  594. rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp)
  595. {
  596. struct rtadv_prefix *rprefix;
  597. rprefix = rtadv_prefix_lookup (zif->rtadv.AdvPrefixList, &rp->prefix);
  598. if (rprefix != NULL)
  599. {
  600. listnode_delete (zif->rtadv.AdvPrefixList, (void *) rprefix);
  601. rtadv_prefix_free (rprefix);
  602. return 1;
  603. }
  604. else
  605. return 0;
  606. }
  607. /* RFC6106 5.1, 5.2: Lifetime SHOULD be bounded as follows:
  608. MaxRtrAdvInterval <= Lifetime <= 2*MaxRtrAdvInterval */
  609. static u_char
  610. rtadv_dns_lifetime_fits (unsigned long lifetime_msec, int MaxRAI_msec)
  611. {
  612. if
  613. (
  614. lifetime_msec == RTADV_DNS_OBSOLETE_LIFETIME * 1000 ||
  615. lifetime_msec == RTADV_DNS_INFINITY_LIFETIME * 1000
  616. )
  617. return 1;
  618. return
  619. (
  620. lifetime_msec >= MAX (1000, MaxRAI_msec) &&
  621. lifetime_msec <= MAX (1000, MaxRAI_msec * 2)
  622. );
  623. }
  624. DEFUN (ipv6_nd_suppress_ra,
  625. ipv6_nd_suppress_ra_cmd,
  626. "ipv6 nd suppress-ra",
  627. IF_IPV6_STR
  628. ND_STR
  629. "Suppress Router Advertisement\n")
  630. {
  631. struct interface *ifp;
  632. struct zebra_if *zif;
  633. struct zebra_vrf *zvrf;
  634. ifp = vty->index;
  635. zif = ifp->info;
  636. zvrf = vrf_info_lookup (ifp->vrf_id);
  637. if (if_is_loopback (ifp))
  638. {
  639. vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
  640. return CMD_WARNING;
  641. }
  642. if (zif->rtadv.AdvSendAdvertisements)
  643. {
  644. zif->rtadv.AdvSendAdvertisements = 0;
  645. zif->rtadv.AdvIntervalTimer = 0;
  646. zvrf->rtadv.adv_if_count--;
  647. if_leave_all_router (zvrf->rtadv.sock, ifp);
  648. if (zvrf->rtadv.adv_if_count == 0)
  649. rtadv_event (zvrf, RTADV_STOP, 0);
  650. }
  651. return CMD_SUCCESS;
  652. }
  653. DEFUN (no_ipv6_nd_suppress_ra,
  654. no_ipv6_nd_suppress_ra_cmd,
  655. "no ipv6 nd suppress-ra",
  656. NO_STR
  657. IF_IPV6_STR
  658. ND_STR
  659. "Suppress Router Advertisement\n")
  660. {
  661. struct interface *ifp;
  662. struct zebra_if *zif;
  663. struct zebra_vrf *zvrf;
  664. ifp = vty->index;
  665. zif = ifp->info;
  666. zvrf = vrf_info_lookup (ifp->vrf_id);
  667. if (if_is_loopback (ifp))
  668. {
  669. vty_out (vty, "Invalid interface%s", VTY_NEWLINE);
  670. return CMD_WARNING;
  671. }
  672. if (! zif->rtadv.AdvSendAdvertisements)
  673. {
  674. zif->rtadv.AdvSendAdvertisements = 1;
  675. zif->rtadv.AdvIntervalTimer = 0;
  676. zvrf->rtadv.adv_if_count++;
  677. if_join_all_router (zvrf->rtadv.sock, ifp);
  678. if (zvrf->rtadv.adv_if_count == 1)
  679. rtadv_event (zvrf, RTADV_START, zvrf->rtadv.sock);
  680. }
  681. return CMD_SUCCESS;
  682. }
  683. DEFUN (ipv6_nd_ra_interval_msec,
  684. ipv6_nd_ra_interval_msec_cmd,
  685. "ipv6 nd ra-interval msec <70-1800000>",
  686. IF_IPV6_STR
  687. ND_STR
  688. "Router Advertisement interval\n"
  689. "Router Advertisement interval in milliseconds\n")
  690. {
  691. unsigned interval;
  692. struct interface *ifp = (struct interface *) vty->index;
  693. struct zebra_if *zif = ifp->info;
  694. struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
  695. struct listnode *node;
  696. struct rtadv_rdnss_entry *rdnss_entry;
  697. struct rtadv_dnssl_entry *dnssl_entry;
  698. VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 70, 1800000);
  699. if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000))
  700. {
  701. vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
  702. return CMD_WARNING;
  703. }
  704. for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvRDNSSList, node, rdnss_entry))
  705. if
  706. (
  707. ! rdnss_entry->track_maxrai &&
  708. ! rtadv_dns_lifetime_fits (rdnss_entry->lifetime * 1000, interval)
  709. )
  710. {
  711. char buf[INET6_ADDRSTRLEN];
  712. inet_ntop (AF_INET6, rdnss_entry->address.s6_addr, buf, INET6_ADDRSTRLEN);
  713. vty_out (vty, "This ra-interval would conflict with lifetime %u of RDNSS %s !%s",
  714. rdnss_entry->lifetime, buf, VTY_NEWLINE);
  715. return CMD_WARNING;
  716. }
  717. for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvDNSSLList, node, dnssl_entry))
  718. if
  719. (
  720. ! dnssl_entry->track_maxrai &&
  721. ! rtadv_dns_lifetime_fits (dnssl_entry->lifetime * 1000, interval)
  722. )
  723. {
  724. vty_out (vty, "This ra-interval would conflict with lifetime %u of DNSSL %s !%s",
  725. dnssl_entry->lifetime, dnssl_entry->subdomain_str, VTY_NEWLINE);
  726. return CMD_WARNING;
  727. }
  728. if (zif->rtadv.MaxRtrAdvInterval % 1000)
  729. zvrf->rtadv.adv_msec_if_count--;
  730. if (interval % 1000)
  731. zvrf->rtadv.adv_msec_if_count++;
  732. zif->rtadv.MaxRtrAdvInterval = interval;
  733. zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
  734. zif->rtadv.AdvIntervalTimer = 0;
  735. return CMD_SUCCESS;
  736. }
  737. DEFUN (ipv6_nd_ra_interval,
  738. ipv6_nd_ra_interval_cmd,
  739. "ipv6 nd ra-interval <1-1800>",
  740. IF_IPV6_STR
  741. ND_STR
  742. "Router Advertisement interval\n"
  743. "Router Advertisement interval in seconds\n")
  744. {
  745. unsigned interval;
  746. struct interface *ifp = (struct interface *) vty->index;
  747. struct zebra_if *zif = ifp->info;
  748. struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
  749. struct listnode *node;
  750. struct rtadv_rdnss_entry *rdnss_entry;
  751. struct rtadv_dnssl_entry *dnssl_entry;
  752. VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 1, 1800);
  753. if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime))
  754. {
  755. vty_out (vty, "This ra-interval would conflict with configured ra-lifetime!%s", VTY_NEWLINE);
  756. return CMD_WARNING;
  757. }
  758. for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvRDNSSList, node, rdnss_entry))
  759. if
  760. (
  761. ! rdnss_entry->track_maxrai &&
  762. ! rtadv_dns_lifetime_fits (rdnss_entry->lifetime * 1000, interval * 1000)
  763. )
  764. {
  765. char buf[INET6_ADDRSTRLEN];
  766. inet_ntop (AF_INET6, rdnss_entry->address.s6_addr, buf, INET6_ADDRSTRLEN);
  767. vty_out (vty, "This ra-interval would conflict with lifetime %u of RDNSS %s !%s",
  768. rdnss_entry->lifetime, buf, VTY_NEWLINE);
  769. return CMD_WARNING;
  770. }
  771. for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvDNSSLList, node, dnssl_entry))
  772. if
  773. (
  774. ! dnssl_entry->track_maxrai &&
  775. ! rtadv_dns_lifetime_fits (dnssl_entry->lifetime * 1000, interval * 1000)
  776. )
  777. {
  778. vty_out (vty, "This ra-interval would conflict with lifetime %u of DNSSL %s !%s",
  779. dnssl_entry->lifetime, dnssl_entry->subdomain_str, VTY_NEWLINE);
  780. return CMD_WARNING;
  781. }
  782. if (zif->rtadv.MaxRtrAdvInterval % 1000)
  783. zvrf->rtadv.adv_msec_if_count--;
  784. /* convert to milliseconds */
  785. interval = interval * 1000;
  786. zif->rtadv.MaxRtrAdvInterval = interval;
  787. zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
  788. zif->rtadv.AdvIntervalTimer = 0;
  789. return CMD_SUCCESS;
  790. }
  791. DEFUN (no_ipv6_nd_ra_interval,
  792. no_ipv6_nd_ra_interval_cmd,
  793. "no ipv6 nd ra-interval",
  794. NO_STR
  795. IF_IPV6_STR
  796. ND_STR
  797. "Router Advertisement interval\n")
  798. {
  799. struct interface *ifp;
  800. struct zebra_if *zif;
  801. struct zebra_vrf *zvrf;
  802. ifp = (struct interface *) vty->index;
  803. zif = ifp->info;
  804. zvrf = vrf_info_lookup (ifp->vrf_id);
  805. if (zif->rtadv.MaxRtrAdvInterval % 1000)
  806. zvrf->rtadv.adv_msec_if_count--;
  807. zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
  808. zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
  809. zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
  810. return CMD_SUCCESS;
  811. }
  812. ALIAS (no_ipv6_nd_ra_interval,
  813. no_ipv6_nd_ra_interval_val_cmd,
  814. "no ipv6 nd ra-interval <1-1800>",
  815. NO_STR
  816. IF_IPV6_STR
  817. ND_STR
  818. "Router Advertisement interval\n")
  819. ALIAS (no_ipv6_nd_ra_interval,
  820. no_ipv6_nd_ra_interval_msec_val_cmd,
  821. "no ipv6 nd ra-interval msec <1-1800000>",
  822. NO_STR
  823. IF_IPV6_STR
  824. ND_STR
  825. "Router Advertisement interval\n"
  826. "Router Advertisement interval in milliseconds\n")
  827. DEFUN (ipv6_nd_ra_lifetime,
  828. ipv6_nd_ra_lifetime_cmd,
  829. "ipv6 nd ra-lifetime <0-9000>",
  830. IF_IPV6_STR
  831. ND_STR
  832. "Router lifetime\n"
  833. "Router lifetime in seconds (0 stands for a non-default gw)\n")
  834. {
  835. int lifetime;
  836. struct interface *ifp;
  837. struct zebra_if *zif;
  838. ifp = (struct interface *) vty->index;
  839. zif = ifp->info;
  840. VTY_GET_INTEGER_RANGE ("router lifetime", lifetime, argv[0], 0, 9000);
  841. /* The value to be placed in the Router Lifetime field
  842. * of Router Advertisements sent from the interface,
  843. * in seconds. MUST be either zero or between
  844. * MaxRtrAdvInterval and 9000 seconds. -- RFC4861, 6.2.1 */
  845. if ((lifetime != 0 && lifetime * 1000 < zif->rtadv.MaxRtrAdvInterval))
  846. {
  847. vty_out (vty, "This ra-lifetime would conflict with configured ra-interval%s", VTY_NEWLINE);
  848. return CMD_WARNING;
  849. }
  850. zif->rtadv.AdvDefaultLifetime = lifetime;
  851. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  852. return CMD_SUCCESS;
  853. }
  854. DEFUN (no_ipv6_nd_ra_lifetime,
  855. no_ipv6_nd_ra_lifetime_cmd,
  856. "no ipv6 nd ra-lifetime",
  857. NO_STR
  858. IF_IPV6_STR
  859. ND_STR
  860. "Router lifetime\n")
  861. {
  862. struct interface *ifp;
  863. struct zebra_if *zif;
  864. ifp = (struct interface *) vty->index;
  865. zif = ifp->info;
  866. zif->rtadv.AdvDefaultLifetime = -1;
  867. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  868. return CMD_SUCCESS;
  869. }
  870. ALIAS (no_ipv6_nd_ra_lifetime,
  871. no_ipv6_nd_ra_lifetime_val_cmd,
  872. "no ipv6 nd ra-lifetime <0-9000>",
  873. NO_STR
  874. IF_IPV6_STR
  875. ND_STR
  876. "Router lifetime\n"
  877. "Router lifetime in seconds (0 stands for a non-default gw)\n")
  878. DEFUN (ipv6_nd_reachable_time,
  879. ipv6_nd_reachable_time_cmd,
  880. "ipv6 nd reachable-time <1-3600000>",
  881. IF_IPV6_STR
  882. ND_STR
  883. "Reachable time\n"
  884. "Reachable time in milliseconds\n")
  885. {
  886. struct interface *ifp = (struct interface *) vty->index;
  887. struct zebra_if *zif = ifp->info;
  888. VTY_GET_INTEGER_RANGE ("reachable time", zif->rtadv.AdvReachableTime, argv[0], 1, RTADV_MAX_REACHABLE_TIME);
  889. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  890. return CMD_SUCCESS;
  891. }
  892. DEFUN (no_ipv6_nd_reachable_time,
  893. no_ipv6_nd_reachable_time_cmd,
  894. "no ipv6 nd reachable-time",
  895. NO_STR
  896. IF_IPV6_STR
  897. ND_STR
  898. "Reachable time\n")
  899. {
  900. struct interface *ifp;
  901. struct zebra_if *zif;
  902. ifp = (struct interface *) vty->index;
  903. zif = ifp->info;
  904. zif->rtadv.AdvReachableTime = 0;
  905. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  906. return CMD_SUCCESS;
  907. }
  908. ALIAS (no_ipv6_nd_reachable_time,
  909. no_ipv6_nd_reachable_time_val_cmd,
  910. "no ipv6 nd reachable-time <1-3600000>",
  911. NO_STR
  912. IF_IPV6_STR
  913. ND_STR
  914. "Reachable time\n"
  915. "Reachable time in milliseconds\n")
  916. DEFUN (ipv6_nd_homeagent_preference,
  917. ipv6_nd_homeagent_preference_cmd,
  918. "ipv6 nd home-agent-preference <0-65535>",
  919. IF_IPV6_STR
  920. ND_STR
  921. "Home Agent preference\n"
  922. "preference value (default is 0, least preferred)\n")
  923. {
  924. struct interface *ifp = (struct interface *) vty->index;
  925. struct zebra_if *zif = ifp->info;
  926. VTY_GET_INTEGER_RANGE ("home agent preference", zif->rtadv.HomeAgentPreference, argv[0], 0, 65535);
  927. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  928. return CMD_SUCCESS;
  929. }
  930. DEFUN (no_ipv6_nd_homeagent_preference,
  931. no_ipv6_nd_homeagent_preference_cmd,
  932. "no ipv6 nd home-agent-preference",
  933. NO_STR
  934. IF_IPV6_STR
  935. ND_STR
  936. "Home Agent preference\n")
  937. {
  938. struct interface *ifp;
  939. struct zebra_if *zif;
  940. ifp = (struct interface *) vty->index;
  941. zif = ifp->info;
  942. zif->rtadv.HomeAgentPreference = 0;
  943. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  944. return CMD_SUCCESS;
  945. }
  946. ALIAS (no_ipv6_nd_homeagent_preference,
  947. no_ipv6_nd_homeagent_preference_val_cmd,
  948. "no ipv6 nd home-agent-preference <0-65535>",
  949. NO_STR
  950. IF_IPV6_STR
  951. ND_STR
  952. "Home Agent preference\n"
  953. "preference value (default is 0, least preferred)\n")
  954. DEFUN (ipv6_nd_homeagent_lifetime,
  955. ipv6_nd_homeagent_lifetime_cmd,
  956. "ipv6 nd home-agent-lifetime <0-65520>",
  957. IF_IPV6_STR
  958. ND_STR
  959. "Home Agent lifetime\n"
  960. "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
  961. {
  962. struct interface *ifp = (struct interface *) vty->index;
  963. struct zebra_if *zif = ifp->info;
  964. VTY_GET_INTEGER_RANGE ("home agent lifetime", zif->rtadv.HomeAgentLifetime, argv[0], 0, RTADV_MAX_HALIFETIME);
  965. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  966. return CMD_SUCCESS;
  967. }
  968. DEFUN (no_ipv6_nd_homeagent_lifetime,
  969. no_ipv6_nd_homeagent_lifetime_cmd,
  970. "no ipv6 nd home-agent-lifetime",
  971. NO_STR
  972. IF_IPV6_STR
  973. ND_STR
  974. "Home Agent lifetime\n")
  975. {
  976. struct interface *ifp;
  977. struct zebra_if *zif;
  978. ifp = (struct interface *) vty->index;
  979. zif = ifp->info;
  980. zif->rtadv.HomeAgentLifetime = -1;
  981. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  982. return CMD_SUCCESS;
  983. }
  984. ALIAS (no_ipv6_nd_homeagent_lifetime,
  985. no_ipv6_nd_homeagent_lifetime_val_cmd,
  986. "no ipv6 nd home-agent-lifetime <0-65520>",
  987. NO_STR
  988. IF_IPV6_STR
  989. ND_STR
  990. "Home Agent lifetime\n"
  991. "Home Agent lifetime in seconds (0 to track ra-lifetime)\n")
  992. DEFUN (ipv6_nd_managed_config_flag,
  993. ipv6_nd_managed_config_flag_cmd,
  994. "ipv6 nd managed-config-flag",
  995. IF_IPV6_STR
  996. ND_STR
  997. "Managed address configuration flag\n")
  998. {
  999. struct interface *ifp;
  1000. struct zebra_if *zif;
  1001. ifp = (struct interface *) vty->index;
  1002. zif = ifp->info;
  1003. zif->rtadv.AdvManagedFlag = 1;
  1004. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1005. return CMD_SUCCESS;
  1006. }
  1007. DEFUN (no_ipv6_nd_managed_config_flag,
  1008. no_ipv6_nd_managed_config_flag_cmd,
  1009. "no ipv6 nd managed-config-flag",
  1010. NO_STR
  1011. IF_IPV6_STR
  1012. ND_STR
  1013. "Managed address configuration flag\n")
  1014. {
  1015. struct interface *ifp;
  1016. struct zebra_if *zif;
  1017. ifp = (struct interface *) vty->index;
  1018. zif = ifp->info;
  1019. zif->rtadv.AdvManagedFlag = 0;
  1020. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1021. return CMD_SUCCESS;
  1022. }
  1023. DEFUN (ipv6_nd_homeagent_config_flag,
  1024. ipv6_nd_homeagent_config_flag_cmd,
  1025. "ipv6 nd home-agent-config-flag",
  1026. IF_IPV6_STR
  1027. ND_STR
  1028. "Home Agent configuration flag\n")
  1029. {
  1030. struct interface *ifp;
  1031. struct zebra_if *zif;
  1032. ifp = (struct interface *) vty->index;
  1033. zif = ifp->info;
  1034. zif->rtadv.AdvHomeAgentFlag = 1;
  1035. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1036. return CMD_SUCCESS;
  1037. }
  1038. DEFUN (no_ipv6_nd_homeagent_config_flag,
  1039. no_ipv6_nd_homeagent_config_flag_cmd,
  1040. "no ipv6 nd home-agent-config-flag",
  1041. NO_STR
  1042. IF_IPV6_STR
  1043. ND_STR
  1044. "Home Agent configuration flag\n")
  1045. {
  1046. struct interface *ifp;
  1047. struct zebra_if *zif;
  1048. ifp = (struct interface *) vty->index;
  1049. zif = ifp->info;
  1050. zif->rtadv.AdvHomeAgentFlag = 0;
  1051. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1052. return CMD_SUCCESS;
  1053. }
  1054. DEFUN (ipv6_nd_adv_interval_config_option,
  1055. ipv6_nd_adv_interval_config_option_cmd,
  1056. "ipv6 nd adv-interval-option",
  1057. IF_IPV6_STR
  1058. ND_STR
  1059. "Advertisement Interval Option\n")
  1060. {
  1061. struct interface *ifp;
  1062. struct zebra_if *zif;
  1063. ifp = (struct interface *) vty->index;
  1064. zif = ifp->info;
  1065. zif->rtadv.AdvIntervalOption = 1;
  1066. return CMD_SUCCESS;
  1067. }
  1068. DEFUN (no_ipv6_nd_adv_interval_config_option,
  1069. no_ipv6_nd_adv_interval_config_option_cmd,
  1070. "no ipv6 nd adv-interval-option",
  1071. NO_STR
  1072. IF_IPV6_STR
  1073. ND_STR
  1074. "Advertisement Interval Option\n")
  1075. {
  1076. struct interface *ifp;
  1077. struct zebra_if *zif;
  1078. ifp = (struct interface *) vty->index;
  1079. zif = ifp->info;
  1080. zif->rtadv.AdvIntervalOption = 0;
  1081. return CMD_SUCCESS;
  1082. }
  1083. DEFUN (ipv6_nd_other_config_flag,
  1084. ipv6_nd_other_config_flag_cmd,
  1085. "ipv6 nd other-config-flag",
  1086. IF_IPV6_STR
  1087. ND_STR
  1088. "Other statefull configuration flag\n")
  1089. {
  1090. struct interface *ifp;
  1091. struct zebra_if *zif;
  1092. ifp = (struct interface *) vty->index;
  1093. zif = ifp->info;
  1094. zif->rtadv.AdvOtherConfigFlag = 1;
  1095. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1096. return CMD_SUCCESS;
  1097. }
  1098. DEFUN (no_ipv6_nd_other_config_flag,
  1099. no_ipv6_nd_other_config_flag_cmd,
  1100. "no ipv6 nd other-config-flag",
  1101. NO_STR
  1102. IF_IPV6_STR
  1103. ND_STR
  1104. "Other statefull configuration flag\n")
  1105. {
  1106. struct interface *ifp;
  1107. struct zebra_if *zif;
  1108. ifp = (struct interface *) vty->index;
  1109. zif = ifp->info;
  1110. zif->rtadv.AdvOtherConfigFlag = 0;
  1111. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1112. return CMD_SUCCESS;
  1113. }
  1114. DEFUN (ipv6_nd_prefix,
  1115. ipv6_nd_prefix_cmd,
  1116. "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
  1117. "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|) (router-address|)",
  1118. IF_IPV6_STR
  1119. ND_STR
  1120. PFX_STR
  1121. IPV6_PFX_STR
  1122. IPV6_PFX_VALID1_STR
  1123. IPV6_PFX_VALID2_STR
  1124. IPV6_PFX_PREF1_STR
  1125. IPV6_PFX_PREF2_STR
  1126. IPV6_PFX_OFFLINK_STR
  1127. IPV6_PFX_NOAUTO_STR
  1128. IPV6_PFX_RADDR_STR)
  1129. {
  1130. int i;
  1131. int ret;
  1132. int cursor = 1;
  1133. struct interface *ifp;
  1134. struct zebra_if *zebra_if;
  1135. struct rtadv_prefix rp;
  1136. ifp = (struct interface *) vty->index;
  1137. zebra_if = ifp->info;
  1138. ret = str2prefix_ipv6 (argv[0], &rp.prefix);
  1139. if (!ret)
  1140. {
  1141. vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
  1142. return CMD_WARNING;
  1143. }
  1144. apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
  1145. rp.AdvOnLinkFlag = 1;
  1146. rp.AdvAutonomousFlag = 1;
  1147. rp.AdvRouterAddressFlag = 0;
  1148. rp.AdvValidLifetime = RTADV_VALID_LIFETIME;
  1149. rp.AdvPreferredLifetime = RTADV_PREFERRED_LIFETIME;
  1150. if (argc > 1)
  1151. {
  1152. if ((isdigit((unsigned char)argv[1][0]))
  1153. || strncmp (argv[1], "i", 1) == 0)
  1154. {
  1155. if ( strncmp (argv[1], "i", 1) == 0)
  1156. rp.AdvValidLifetime = UINT32_MAX;
  1157. else
  1158. rp.AdvValidLifetime = (u_int32_t) strtoll (argv[1],
  1159. (char **)NULL, 10);
  1160. if ( strncmp (argv[2], "i", 1) == 0)
  1161. rp.AdvPreferredLifetime = UINT32_MAX;
  1162. else
  1163. rp.AdvPreferredLifetime = (u_int32_t) strtoll (argv[2],
  1164. (char **)NULL, 10);
  1165. if (rp.AdvPreferredLifetime > rp.AdvValidLifetime)
  1166. {
  1167. vty_out (vty, "Invalid preferred lifetime%s", VTY_NEWLINE);
  1168. return CMD_WARNING;
  1169. }
  1170. cursor = cursor + 2;
  1171. }
  1172. if (argc > cursor)
  1173. {
  1174. for (i = cursor; i < argc; i++)
  1175. {
  1176. if (strncmp (argv[i], "of", 2) == 0)
  1177. rp.AdvOnLinkFlag = 0;
  1178. if (strncmp (argv[i], "no", 2) == 0)
  1179. rp.AdvAutonomousFlag = 0;
  1180. if (strncmp (argv[i], "ro", 2) == 0)
  1181. rp.AdvRouterAddressFlag = 1;
  1182. }
  1183. }
  1184. }
  1185. rtadv_prefix_set (zebra_if, &rp);
  1186. zebra_if->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1187. return CMD_SUCCESS;
  1188. }
  1189. ALIAS (ipv6_nd_prefix,
  1190. ipv6_nd_prefix_val_nortaddr_cmd,
  1191. "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
  1192. "(<0-4294967295>|infinite) (off-link|) (no-autoconfig|)",
  1193. IF_IPV6_STR
  1194. ND_STR
  1195. PFX_STR
  1196. IPV6_PFX_STR
  1197. IPV6_PFX_VALID1_STR
  1198. IPV6_PFX_VALID2_STR
  1199. IPV6_PFX_PREF1_STR
  1200. IPV6_PFX_PREF2_STR
  1201. IPV6_PFX_OFFLINK_STR
  1202. IPV6_PFX_NOAUTO_STR)
  1203. ALIAS (ipv6_nd_prefix,
  1204. ipv6_nd_prefix_val_rev_cmd,
  1205. "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
  1206. "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|)",
  1207. IF_IPV6_STR
  1208. ND_STR
  1209. PFX_STR
  1210. IPV6_PFX_STR
  1211. IPV6_PFX_VALID1_STR
  1212. IPV6_PFX_VALID2_STR
  1213. IPV6_PFX_PREF1_STR
  1214. IPV6_PFX_PREF2_STR
  1215. IPV6_PFX_NOAUTO_STR
  1216. IPV6_PFX_OFFLINK_STR)
  1217. ALIAS (ipv6_nd_prefix,
  1218. ipv6_nd_prefix_val_rev_rtaddr_cmd,
  1219. "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
  1220. "(<0-4294967295>|infinite) (no-autoconfig|) (off-link|) (router-address|)",
  1221. IF_IPV6_STR
  1222. ND_STR
  1223. PFX_STR
  1224. IPV6_PFX_STR
  1225. IPV6_PFX_VALID1_STR
  1226. IPV6_PFX_VALID2_STR
  1227. IPV6_PFX_PREF1_STR
  1228. IPV6_PFX_PREF2_STR
  1229. IPV6_PFX_NOAUTO_STR
  1230. IPV6_PFX_OFFLINK_STR
  1231. IPV6_PFX_RADDR_STR)
  1232. ALIAS (ipv6_nd_prefix,
  1233. ipv6_nd_prefix_val_noauto_cmd,
  1234. "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
  1235. "(<0-4294967295>|infinite) (no-autoconfig|)",
  1236. IF_IPV6_STR
  1237. ND_STR
  1238. PFX_STR
  1239. IPV6_PFX_STR
  1240. IPV6_PFX_VALID1_STR
  1241. IPV6_PFX_VALID2_STR
  1242. IPV6_PFX_PREF1_STR
  1243. IPV6_PFX_PREF2_STR
  1244. "Do not use prefix for autoconfiguration")
  1245. ALIAS (ipv6_nd_prefix,
  1246. ipv6_nd_prefix_val_offlink_cmd,
  1247. "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
  1248. "(<0-4294967295>|infinite) (off-link|)",
  1249. IF_IPV6_STR
  1250. ND_STR
  1251. PFX_STR
  1252. IPV6_PFX_STR
  1253. IPV6_PFX_VALID1_STR
  1254. IPV6_PFX_VALID2_STR
  1255. IPV6_PFX_PREF1_STR
  1256. IPV6_PFX_PREF2_STR
  1257. IPV6_PFX_OFFLINK_STR)
  1258. ALIAS (ipv6_nd_prefix,
  1259. ipv6_nd_prefix_val_rtaddr_cmd,
  1260. "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
  1261. "(<0-4294967295>|infinite) (router-address|)",
  1262. IF_IPV6_STR
  1263. ND_STR
  1264. PFX_STR
  1265. IPV6_PFX_STR
  1266. IPV6_PFX_VALID1_STR
  1267. IPV6_PFX_VALID2_STR
  1268. IPV6_PFX_PREF1_STR
  1269. IPV6_PFX_PREF2_STR
  1270. IPV6_PFX_RADDR_STR)
  1271. ALIAS (ipv6_nd_prefix,
  1272. ipv6_nd_prefix_val_cmd,
  1273. "ipv6 nd prefix X:X::X:X/M (<0-4294967295>|infinite) "
  1274. "(<0-4294967295>|infinite)",
  1275. IF_IPV6_STR
  1276. ND_STR
  1277. PFX_STR
  1278. IPV6_PFX_STR
  1279. IPV6_PFX_VALID1_STR
  1280. IPV6_PFX_VALID2_STR
  1281. IPV6_PFX_PREF1_STR
  1282. IPV6_PFX_PREF2_STR)
  1283. ALIAS (ipv6_nd_prefix,
  1284. ipv6_nd_prefix_noval_cmd,
  1285. "ipv6 nd prefix X:X::X:X/M (no-autoconfig|) (off-link|)",
  1286. IF_IPV6_STR
  1287. ND_STR
  1288. PFX_STR
  1289. IPV6_PFX_STR
  1290. IPV6_PFX_NOAUTO_STR
  1291. IPV6_PFX_OFFLINK_STR)
  1292. ALIAS (ipv6_nd_prefix,
  1293. ipv6_nd_prefix_noval_rev_cmd,
  1294. "ipv6 nd prefix X:X::X:X/M (off-link|) (no-autoconfig|)",
  1295. IF_IPV6_STR
  1296. ND_STR
  1297. PFX_STR
  1298. IPV6_PFX_STR
  1299. IPV6_PFX_OFFLINK_STR
  1300. IPV6_PFX_NOAUTO_STR)
  1301. ALIAS (ipv6_nd_prefix,
  1302. ipv6_nd_prefix_noval_noauto_cmd,
  1303. "ipv6 nd prefix X:X::X:X/M (no-autoconfig|)",
  1304. IF_IPV6_STR
  1305. ND_STR
  1306. PFX_STR
  1307. IPV6_PFX_STR
  1308. IPV6_PFX_NOAUTO_STR)
  1309. ALIAS (ipv6_nd_prefix,
  1310. ipv6_nd_prefix_noval_offlink_cmd,
  1311. "ipv6 nd prefix X:X::X:X/M (off-link|)",
  1312. IF_IPV6_STR
  1313. ND_STR
  1314. PFX_STR
  1315. IPV6_PFX_STR
  1316. IPV6_PFX_OFFLINK_STR)
  1317. ALIAS (ipv6_nd_prefix,
  1318. ipv6_nd_prefix_noval_rtaddr_cmd,
  1319. "ipv6 nd prefix X:X::X:X/M (router-address|)",
  1320. IF_IPV6_STR
  1321. ND_STR
  1322. PFX_STR
  1323. IPV6_PFX_STR
  1324. IPV6_PFX_RADDR_STR)
  1325. ALIAS (ipv6_nd_prefix,
  1326. ipv6_nd_prefix_prefix_cmd,
  1327. "ipv6 nd prefix X:X::X:X/M",
  1328. IF_IPV6_STR
  1329. ND_STR
  1330. PFX_STR
  1331. IPV6_PFX_STR)
  1332. DEFUN (no_ipv6_nd_prefix,
  1333. no_ipv6_nd_prefix_cmd,
  1334. "no ipv6 nd prefix IPV6PREFIX",
  1335. NO_STR
  1336. IF_IPV6_STR
  1337. ND_STR
  1338. PFX_STR
  1339. IPV6_PFX_STR)
  1340. {
  1341. int ret;
  1342. struct interface *ifp;
  1343. struct zebra_if *zebra_if;
  1344. struct rtadv_prefix rp;
  1345. ifp = (struct interface *) vty->index;
  1346. zebra_if = ifp->info;
  1347. ret = str2prefix_ipv6 (argv[0], &rp.prefix);
  1348. if (!ret)
  1349. {
  1350. vty_out (vty, "Malformed IPv6 prefix%s", VTY_NEWLINE);
  1351. return CMD_WARNING;
  1352. }
  1353. apply_mask_ipv6 (&rp.prefix); /* RFC4861 4.6.2 */
  1354. ret = rtadv_prefix_reset (zebra_if, &rp);
  1355. if (!ret)
  1356. {
  1357. vty_out (vty, "Non-exist IPv6 prefix%s", VTY_NEWLINE);
  1358. return CMD_WARNING;
  1359. }
  1360. zebra_if->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1361. return CMD_SUCCESS;
  1362. }
  1363. DEFUN (ipv6_nd_router_preference,
  1364. ipv6_nd_router_preference_cmd,
  1365. "ipv6 nd router-preference (high|medium|low)",
  1366. IF_IPV6_STR
  1367. ND_STR
  1368. "Default router preference\n"
  1369. "High default router preference\n"
  1370. "Low default router preference\n"
  1371. "Medium default router preference (default)\n")
  1372. {
  1373. struct interface *ifp;
  1374. struct zebra_if *zif;
  1375. unsigned int i = 0;
  1376. ifp = (struct interface *) vty->index;
  1377. zif = ifp->info;
  1378. while (i < rtadv_pref_strs_max)
  1379. {
  1380. if (argv[0][0] == rtadv_pref_strs[i].str[0])
  1381. {
  1382. zif->rtadv.DefaultPreference = i;
  1383. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1384. return CMD_SUCCESS;
  1385. }
  1386. i++;
  1387. }
  1388. return CMD_ERR_NO_MATCH;
  1389. }
  1390. DEFUN (no_ipv6_nd_router_preference,
  1391. no_ipv6_nd_router_preference_cmd,
  1392. "no ipv6 nd router-preference",
  1393. NO_STR
  1394. IF_IPV6_STR
  1395. ND_STR
  1396. "Default router preference\n")
  1397. {
  1398. struct interface *ifp;
  1399. struct zebra_if *zif;
  1400. ifp = (struct interface *) vty->index;
  1401. zif = ifp->info;
  1402. zif->rtadv.DefaultPreference = RTADV_PREF_MEDIUM; /* Default per RFC4191. */
  1403. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1404. return CMD_SUCCESS;
  1405. }
  1406. ALIAS (no_ipv6_nd_router_preference,
  1407. no_ipv6_nd_router_preference_val_cmd,
  1408. "no ipv6 nd router-preference (high|medium|low)",
  1409. NO_STR
  1410. IF_IPV6_STR
  1411. ND_STR
  1412. "Default router preference\n"
  1413. "High default router preference\n"
  1414. "Low default router preference\n"
  1415. "Medium default router preference (default)\n")
  1416. DEFUN (ipv6_nd_mtu,
  1417. ipv6_nd_mtu_cmd,
  1418. "ipv6 nd mtu <1-65535>",
  1419. IF_IPV6_STR
  1420. ND_STR
  1421. "Advertised MTU\n"
  1422. "MTU in bytes\n")
  1423. {
  1424. struct interface *ifp = (struct interface *) vty->index;
  1425. struct zebra_if *zif = ifp->info;
  1426. VTY_GET_INTEGER_RANGE ("MTU", zif->rtadv.AdvLinkMTU, argv[0], 1, 65535);
  1427. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1428. return CMD_SUCCESS;
  1429. }
  1430. DEFUN (no_ipv6_nd_mtu,
  1431. no_ipv6_nd_mtu_cmd,
  1432. "no ipv6 nd mtu",
  1433. NO_STR
  1434. IF_IPV6_STR
  1435. ND_STR
  1436. "Advertised MTU\n")
  1437. {
  1438. struct interface *ifp = (struct interface *) vty->index;
  1439. struct zebra_if *zif = ifp->info;
  1440. zif->rtadv.AdvLinkMTU = 0;
  1441. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1442. return CMD_SUCCESS;
  1443. }
  1444. ALIAS (no_ipv6_nd_mtu,
  1445. no_ipv6_nd_mtu_val_cmd,
  1446. "no ipv6 nd mtu <1-65535>",
  1447. NO_STR
  1448. IF_IPV6_STR
  1449. ND_STR
  1450. "Advertised MTU\n"
  1451. "MTU in bytes\n")
  1452. static struct rtadv_rdnss_entry *
  1453. rtadv_rdnss_lookup (struct list *list, struct in6_addr *v6addr)
  1454. {
  1455. struct listnode *node;
  1456. struct rtadv_rdnss_entry *entry;
  1457. for (ALL_LIST_ELEMENTS_RO (list, node, entry))
  1458. if (IPV6_ADDR_SAME (entry->address.s6_addr, v6addr->s6_addr))
  1459. return entry;
  1460. return NULL;
  1461. }
  1462. /* Note how special values 0 and 4294967295 are not considered valid in CLI,
  1463. * although they are used in the internal structures (two respective keywords
  1464. * must be used instead in CLI). This is intended for a better perception of
  1465. * the running-config text. */
  1466. static int
  1467. rtadv_validate_rdnss_args
  1468. (
  1469. struct vty *vty,
  1470. struct rtadv_rdnss_entry *rdnss,
  1471. const unsigned MaxRtrAdvInterval,
  1472. const int argc,
  1473. const char *argv[]
  1474. )
  1475. {
  1476. if (1 != inet_pton (AF_INET6, argv[0], &rdnss->address))
  1477. return CMD_WARNING;
  1478. if (argc < 2) /* no explicit lifetime*/
  1479. rdnss->track_maxrai = 1;
  1480. else
  1481. {
  1482. rdnss->track_maxrai = 0;
  1483. if (! strncmp (argv[1], "i", 1)) /* infinite */
  1484. rdnss->lifetime = RTADV_DNS_INFINITY_LIFETIME;
  1485. else if (! strncmp (argv[1], "o", 1)) /* obsolete */
  1486. rdnss->lifetime = RTADV_DNS_OBSOLETE_LIFETIME;
  1487. else
  1488. {
  1489. VTY_GET_INTEGER_RANGE ("lifetime", rdnss->lifetime, argv[1], 1, 4294967294);
  1490. if (! rtadv_dns_lifetime_fits (rdnss->lifetime * 1000, MaxRtrAdvInterval))
  1491. {
  1492. vty_out (vty, "This lifetime conflicts with ra-interval (%u ms)%s",
  1493. MaxRtrAdvInterval, VTY_NEWLINE);
  1494. return CMD_WARNING;
  1495. }
  1496. }
  1497. }
  1498. return CMD_SUCCESS;
  1499. }
  1500. DEFUN (ipv6_nd_rdnss_addr,
  1501. ipv6_nd_rdnss_addr_cmd,
  1502. "ipv6 nd rdnss X:X::X:X",
  1503. IF_IPV6_STR
  1504. ND_STR
  1505. "Recursive DNS Server\n"
  1506. "IPv6 address of the server\n")
  1507. {
  1508. struct interface *ifp = (struct interface *) vty->index;
  1509. struct zebra_if *zif = ifp->info;
  1510. struct rtadv_rdnss_entry input, *stored;
  1511. if (CMD_SUCCESS != rtadv_validate_rdnss_args (vty, &input, zif->rtadv.MaxRtrAdvInterval, argc, argv))
  1512. return CMD_WARNING;
  1513. /* OK to commit the update */
  1514. if (! (stored = rtadv_rdnss_lookup (zif->rtadv.AdvRDNSSList, &input.address)))
  1515. {
  1516. stored = XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_rdnss_entry));
  1517. listnode_add (zif->rtadv.AdvRDNSSList, stored);
  1518. }
  1519. memcpy (stored, &input, sizeof (struct rtadv_rdnss_entry));
  1520. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1521. return CMD_SUCCESS;
  1522. }
  1523. ALIAS (ipv6_nd_rdnss_addr,
  1524. ipv6_nd_rdnss_addr_lft_cmd,
  1525. "ipv6 nd rdnss X:X::X:X (<1-4294967294>|infinite|obsolete)",
  1526. IF_IPV6_STR
  1527. ND_STR
  1528. "Recursive DNS Server\n"
  1529. "IPv6 address of the server\n"
  1530. "Lifetime in seconds (track ra-interval, if not set)")
  1531. DEFUN (no_ipv6_nd_rdnss_addr,
  1532. no_ipv6_nd_rdnss_addr_cmd,
  1533. "no ipv6 nd rdnss X:X::X:X",
  1534. NO_STR
  1535. IF_IPV6_STR
  1536. ND_STR
  1537. "Recursive DNS Server\n"
  1538. "IPv6 address of the server\n")
  1539. {
  1540. struct interface *ifp = (struct interface *) vty->index;
  1541. struct zebra_if *zif = ifp->info;
  1542. struct rtadv_rdnss_entry *entry;
  1543. struct in6_addr v6addr;
  1544. if (1 != inet_pton (AF_INET6, argv[0], &v6addr))
  1545. return CMD_WARNING;
  1546. if (! (entry = rtadv_rdnss_lookup (zif->rtadv.AdvRDNSSList, &v6addr)))
  1547. return CMD_ERR_NO_MATCH;
  1548. listnode_delete (zif->rtadv.AdvRDNSSList, entry);
  1549. XFREE (MTYPE_RTADV_PREFIX, entry);
  1550. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1551. return CMD_SUCCESS;
  1552. }
  1553. ALIAS (no_ipv6_nd_rdnss_addr,
  1554. no_ipv6_nd_rdnss_addr_lft_cmd,
  1555. "no ipv6 nd rdnss X:X::X:X (<1-4294967294>|infinite|obsolete)",
  1556. NO_STR
  1557. IF_IPV6_STR
  1558. ND_STR
  1559. "Recursive DNS Server\n"
  1560. "IPv6 address of the server\n"
  1561. "Lifetime in seconds (track ra-interval, if not set)")
  1562. /* start of RFC1035 BNF implementation */
  1563. /* <digit> ::= any one of the ten digits 0 through 9 */
  1564. static inline char
  1565. is_rfc1035_digit (const char c)
  1566. {
  1567. return '0' <= c && c <= '9';
  1568. }
  1569. /* <letter> ::= any one of the 52 alphabetic characters A through Z in
  1570. upper case and a through z in lower case */
  1571. static inline char
  1572. is_rfc1035_letter (const char c)
  1573. {
  1574. return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
  1575. }
  1576. /* <let-dig> ::= <letter> | <digit> */
  1577. static inline char
  1578. is_rfc1035_let_dig (const char c)
  1579. {
  1580. return is_rfc1035_letter (c) || is_rfc1035_digit (c);
  1581. }
  1582. /* <let-dig-hyp> ::= <let-dig> | "-" */
  1583. static inline char
  1584. is_rfc1035_let_dig_hyp (const char c)
  1585. {
  1586. return is_rfc1035_let_dig (c) || c == '-';
  1587. }
  1588. /* <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str> */
  1589. static inline char
  1590. is_rfc1035_ldh_str (const char * str, const size_t len)
  1591. {
  1592. size_t i;
  1593. for (i = 0; i < len; i++)
  1594. if (! is_rfc1035_let_dig_hyp (str[i]))
  1595. return 0;
  1596. return 1;
  1597. }
  1598. /* <label> ::= <letter> [ [ <ldh-str> ] <let-dig> ] */
  1599. static char
  1600. is_rfc1035_label (const char * str, const size_t len)
  1601. {
  1602. if (len < 1 || len > 63) /* 00111111 */
  1603. return 0;
  1604. if (! is_rfc1035_letter (str[0]))
  1605. return 0;
  1606. if (len > 1 && ! is_rfc1035_let_dig (str[len - 1]))
  1607. return 0;
  1608. if (len > 2 && ! is_rfc1035_ldh_str (str + 1, len - 2))
  1609. return 0;
  1610. return 1;
  1611. }
  1612. /* Transform the provided "clear-text" DNS domain name into a RFC1035
  1613. representation and return number of bytes the resulting encoding takes,
  1614. or -1 in case of error.
  1615. <subdomain> ::= <label> | <subdomain> "." <label> */
  1616. static int
  1617. parse_rfc1035_subdomain
  1618. (
  1619. const char * inbuf, /* NULL-terminated sequence of period-separated words */
  1620. u_int8_t * outbuf /* NULL-terminated sequence of RFC1035-styled "labels" */
  1621. )
  1622. {
  1623. unsigned char do_next = 1, chars_done = 0;
  1624. size_t chars_total = strlen (inbuf);
  1625. if (chars_total < 1 || chars_total > SUBDOMAIN_MAX_STRLEN)
  1626. return -1;
  1627. do
  1628. {
  1629. size_t word_len;
  1630. char * period = strchr (inbuf + chars_done, '.');
  1631. /* Find the end of the current word and decide if it is the last one. */
  1632. if (period)
  1633. word_len = period - inbuf - chars_done;
  1634. else
  1635. {
  1636. do_next = 0;
  1637. word_len = chars_total - chars_done;
  1638. }
  1639. if (! is_rfc1035_label (inbuf + chars_done, word_len))
  1640. return -1;
  1641. /* count trailing '.'/0 input byte for leading "label length" output byte */
  1642. outbuf[chars_done] = word_len;
  1643. memcpy (outbuf + chars_done + 1, inbuf + chars_done, word_len);
  1644. chars_done += word_len + 1;
  1645. }
  1646. while (do_next);
  1647. outbuf[chars_done++] = 0; /* the extra byte */
  1648. return chars_done;
  1649. }
  1650. /* end of RFC1035 BNF implementation */
  1651. static struct rtadv_dnssl_entry *
  1652. rtadv_dnssl_lookup (struct list *list, const char * subdomain)
  1653. {
  1654. struct listnode *node;
  1655. struct rtadv_dnssl_entry *entry;
  1656. for (ALL_LIST_ELEMENTS_RO (list, node, entry))
  1657. if (! strcasecmp (entry->subdomain_str, subdomain))
  1658. return entry;
  1659. return NULL;
  1660. }
  1661. static int
  1662. rtadv_validate_dnssl_args
  1663. (
  1664. struct vty *vty,
  1665. struct rtadv_dnssl_entry *dnssl,
  1666. const unsigned MaxRtrAdvInterval,
  1667. const int argc,
  1668. const char *argv[]
  1669. )
  1670. {
  1671. int parsed_bytes;
  1672. parsed_bytes = parse_rfc1035_subdomain (argv[0], dnssl->subdomain_rfc1035);
  1673. if (parsed_bytes <= 0)
  1674. {
  1675. vty_out (vty, "Invalid DNS domain name '%s'%s", argv[0], VTY_NEWLINE);
  1676. return CMD_WARNING;
  1677. }
  1678. dnssl->length_rfc1035 = parsed_bytes;
  1679. strcpy (dnssl->subdomain_str, argv[0]);
  1680. if (argc < 2) /* no explicit lifetime*/
  1681. dnssl->track_maxrai = 1;
  1682. else
  1683. {
  1684. dnssl->track_maxrai = 0;
  1685. if (! strncmp (argv[1], "i", 1)) /* infinite */
  1686. dnssl->lifetime = RTADV_DNS_INFINITY_LIFETIME;
  1687. else if (! strncmp (argv[1], "o", 1)) /* obsolete */
  1688. dnssl->lifetime = RTADV_DNS_OBSOLETE_LIFETIME;
  1689. else
  1690. {
  1691. VTY_GET_INTEGER_RANGE ("lifetime", dnssl->lifetime, argv[1], 1, 4294967294);
  1692. if (! rtadv_dns_lifetime_fits (dnssl->lifetime * 1000, MaxRtrAdvInterval))
  1693. {
  1694. vty_out (vty, "This lifetime conflicts with ra-interval (%u ms)%s",
  1695. MaxRtrAdvInterval, VTY_NEWLINE);
  1696. return CMD_WARNING;
  1697. }
  1698. }
  1699. }
  1700. return CMD_SUCCESS;
  1701. }
  1702. DEFUN (ipv6_nd_dnssl_domain,
  1703. ipv6_nd_dnssl_domain_cmd,
  1704. "ipv6 nd dnssl DNS.DOMA.IN",
  1705. IF_IPV6_STR
  1706. ND_STR
  1707. "DNS search list\n"
  1708. "DNS domain\n")
  1709. {
  1710. struct interface *ifp = (struct interface *) vty->index;
  1711. struct zebra_if *zif = ifp->info;
  1712. struct rtadv_dnssl_entry input, *stored;
  1713. if (CMD_SUCCESS != rtadv_validate_dnssl_args (vty, &input, zif->rtadv.MaxRtrAdvInterval, argc, argv))
  1714. return CMD_WARNING;
  1715. /* OK to commit the update */
  1716. if (! (stored = rtadv_dnssl_lookup (zif->rtadv.AdvDNSSLList, input.subdomain_str)))
  1717. {
  1718. stored = XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_dnssl_entry));
  1719. listnode_add (zif->rtadv.AdvDNSSLList, stored);
  1720. }
  1721. memcpy (stored, &input, sizeof (struct rtadv_dnssl_entry));
  1722. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1723. return CMD_SUCCESS;
  1724. }
  1725. ALIAS (ipv6_nd_dnssl_domain,
  1726. ipv6_nd_dnssl_domain_lft_cmd,
  1727. "ipv6 nd dnssl DNS.DOMA.IN (<1-4294967294>|infinite|obsolete)",
  1728. IF_IPV6_STR
  1729. ND_STR
  1730. "DNS search list\n"
  1731. "DNS domain\n"
  1732. "Lifetime in seconds (track ra-interval, if not set)")
  1733. DEFUN (no_ipv6_nd_dnssl_domain,
  1734. no_ipv6_nd_dnssl_domain_cmd,
  1735. "no ipv6 nd dnssl DNS.DOMA.IN",
  1736. NO_STR
  1737. IF_IPV6_STR
  1738. ND_STR
  1739. "DNS search list\n"
  1740. "DNS domain\n")
  1741. {
  1742. struct interface *ifp = (struct interface *) vty->index;
  1743. struct zebra_if *zif = ifp->info;
  1744. struct rtadv_dnssl_entry *entry;
  1745. if (! (entry = rtadv_dnssl_lookup (zif->rtadv.AdvDNSSLList, argv[0])))
  1746. return CMD_ERR_NO_MATCH;
  1747. listnode_delete (zif->rtadv.AdvDNSSLList, entry);
  1748. XFREE (MTYPE_RTADV_PREFIX, entry);
  1749. zif->rtadv.AdvIntervalTimer = 0; /* resend immediately */
  1750. return CMD_SUCCESS;
  1751. }
  1752. ALIAS (no_ipv6_nd_dnssl_domain,
  1753. no_ipv6_nd_dnssl_domain_lft_cmd,
  1754. "no ipv6 nd dnssl DNS.DOMA.IN (<1-4294967294>|infinite|obsolete)",
  1755. NO_STR
  1756. IF_IPV6_STR
  1757. ND_STR
  1758. "DNS search list\n"
  1759. "DNS domain\n"
  1760. "Lifetime in seconds (track ra-interval, if not set)")
  1761. static int
  1762. rtadv_print_rdnss_list (struct vty *vty, const struct list *list, const char *prefix)
  1763. {
  1764. struct listnode *node;
  1765. struct rtadv_rdnss_entry *rdnss_entry;
  1766. char buf[INET6_ADDRSTRLEN];
  1767. int write = 0;
  1768. for (ALL_LIST_ELEMENTS_RO (list, node, rdnss_entry))
  1769. {
  1770. write++;
  1771. inet_ntop (AF_INET6, rdnss_entry->address.s6_addr, buf, INET6_ADDRSTRLEN);
  1772. vty_out (vty, "%s %s", prefix, buf);
  1773. if (rdnss_entry->track_maxrai)
  1774. {
  1775. vty_out (vty, "%s", VTY_NEWLINE);
  1776. continue;
  1777. }
  1778. switch (rdnss_entry->lifetime)
  1779. {
  1780. case RTADV_DNS_OBSOLETE_LIFETIME:
  1781. vty_out (vty, " obsolete%s", VTY_NEWLINE);
  1782. break;
  1783. case RTADV_DNS_INFINITY_LIFETIME:
  1784. vty_out (vty, " infinite%s", VTY_NEWLINE);
  1785. break;
  1786. default:
  1787. vty_out (vty, " %u%s", rdnss_entry->lifetime, VTY_NEWLINE);
  1788. break;
  1789. }
  1790. }
  1791. return write;
  1792. }
  1793. static int
  1794. rtadv_print_dnssl_list (struct vty *vty, const struct list *list, const char *prefix)
  1795. {
  1796. struct listnode *node;
  1797. struct rtadv_dnssl_entry *dnssl_entry;
  1798. int write = 0;
  1799. for (ALL_LIST_ELEMENTS_RO (list, node, dnssl_entry))
  1800. {
  1801. write++;
  1802. vty_out (vty, "%s %s", prefix, dnssl_entry->subdomain_str);
  1803. if (dnssl_entry->track_maxrai)
  1804. {
  1805. vty_out (vty, "%s", VTY_NEWLINE);
  1806. continue;
  1807. }
  1808. switch (dnssl_entry->lifetime)
  1809. {
  1810. case RTADV_DNS_OBSOLETE_LIFETIME:
  1811. vty_out (vty, " obsolete%s", VTY_NEWLINE);
  1812. break;
  1813. case RTADV_DNS_INFINITY_LIFETIME:
  1814. vty_out (vty, " infinite%s", VTY_NEWLINE);
  1815. break;
  1816. default:
  1817. vty_out (vty, " %u%s", dnssl_entry->lifetime, VTY_NEWLINE);
  1818. break;
  1819. }
  1820. }
  1821. return write;
  1822. }
  1823. /* Write configuration about router advertisement. */
  1824. void
  1825. rtadv_config_write (struct vty *vty, struct interface *ifp)
  1826. {
  1827. struct zebra_if *zif;
  1828. struct listnode *node;
  1829. struct rtadv_prefix *rprefix;
  1830. char buf[PREFIX_STRLEN];
  1831. int interval;
  1832. struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
  1833. zif = ifp->info;
  1834. if (! if_is_loopback (ifp))
  1835. {
  1836. if (zif->rtadv.AdvSendAdvertisements != zvrf->rtadv.AdvSendAdvertisements)
  1837. vty_out (vty, " %sipv6 nd suppress-ra%s",
  1838. zif->rtadv.AdvSendAdvertisements ? "no " : "", VTY_NEWLINE);
  1839. }
  1840. interval = zif->rtadv.MaxRtrAdvInterval;
  1841. if (interval % 1000)
  1842. vty_out (vty, " ipv6 nd ra-interval msec %d%s", interval,
  1843. VTY_NEWLINE);
  1844. else
  1845. if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
  1846. vty_out (vty, " ipv6 nd ra-interval %d%s", interval / 1000,
  1847. VTY_NEWLINE);
  1848. if (zif->rtadv.AdvIntervalOption)
  1849. vty_out (vty, " ipv6 nd adv-interval-option%s", VTY_NEWLINE);
  1850. if (zif->rtadv.AdvDefaultLifetime != -1)
  1851. vty_out (vty, " ipv6 nd ra-lifetime %d%s", zif->rtadv.AdvDefaultLifetime,
  1852. VTY_NEWLINE);
  1853. if (zif->rtadv.HomeAgentPreference)
  1854. vty_out (vty, " ipv6 nd home-agent-preference %u%s",
  1855. zif->rtadv.HomeAgentPreference, VTY_NEWLINE);
  1856. if (zif->rtadv.HomeAgentLifetime != -1)
  1857. vty_out (vty, " ipv6 nd home-agent-lifetime %u%s",
  1858. zif->rtadv.HomeAgentLifetime, VTY_NEWLINE);
  1859. if (zif->rtadv.AdvHomeAgentFlag)
  1860. vty_out (vty, " ipv6 nd home-agent-config-flag%s", VTY_NEWLINE);
  1861. if (zif->rtadv.AdvReachableTime)
  1862. vty_out (vty, " ipv6 nd reachable-time %d%s", zif->rtadv.AdvReachableTime,
  1863. VTY_NEWLINE);
  1864. if (zif->rtadv.AdvManagedFlag)
  1865. vty_out (vty, " ipv6 nd managed-config-flag%s", VTY_NEWLINE);
  1866. if (zif->rtadv.AdvOtherConfigFlag)
  1867. vty_out (vty, " ipv6 nd other-config-flag%s", VTY_NEWLINE);
  1868. if (zif->rtadv.DefaultPreference != RTADV_PREF_MEDIUM)
  1869. vty_out (vty, " ipv6 nd router-preference %s%s",
  1870. rtadv_pref_strs[zif->rtadv.DefaultPreference].str,
  1871. VTY_NEWLINE);
  1872. if (zif->rtadv.AdvLinkMTU)
  1873. vty_out (vty, " ipv6 nd mtu %d%s", zif->rtadv.AdvLinkMTU, VTY_NEWLINE);
  1874. for (ALL_LIST_ELEMENTS_RO (zif->rtadv.AdvPrefixList, node, rprefix))
  1875. {
  1876. vty_out (vty, " ipv6 nd prefix %s",
  1877. prefix2str (&rprefix->prefix, buf, sizeof(buf)));
  1878. if ((rprefix->AdvValidLifetime != RTADV_VALID_LIFETIME) ||
  1879. (rprefix->AdvPreferredLifetime != RTADV_PREFERRED_LIFETIME))
  1880. {
  1881. if (rprefix->AdvValidLifetime == UINT32_MAX)
  1882. vty_out (vty, " infinite");
  1883. else
  1884. vty_out (vty, " %u", rprefix->AdvValidLifetime);
  1885. if (rprefix->AdvPreferredLifetime == UINT32_MAX)
  1886. vty_out (vty, " infinite");
  1887. else
  1888. vty_out (vty, " %u", rprefix->AdvPreferredLifetime);
  1889. }
  1890. if (!rprefix->AdvOnLinkFlag)
  1891. vty_out (vty, " off-link");
  1892. if (!rprefix->AdvAutonomousFlag)
  1893. vty_out (vty, " no-autoconfig");
  1894. if (rprefix->AdvRouterAddressFlag)
  1895. vty_out (vty, " router-address");
  1896. vty_out (vty, "%s", VTY_NEWLINE);
  1897. }
  1898. rtadv_print_rdnss_list (vty, zif->rtadv.AdvRDNSSList, " ipv6 nd rdnss");
  1899. rtadv_print_dnssl_list (vty, zif->rtadv.AdvDNSSLList, " ipv6 nd dnssl");
  1900. }
  1901. static struct cmd_node ipv6_nd_node = { IPV6_ND_NODE, "", 1 };
  1902. DEFUN (top_ipv6_nd_suppress_ra,
  1903. top_ipv6_nd_suppress_ra_cmd,
  1904. "ipv6 nd suppress-ra",
  1905. IPV6_STR
  1906. ND_STR
  1907. "Suppress Router Advertisement by default\n")
  1908. {
  1909. struct zebra_vrf *zvrf;
  1910. struct interface *ifp;
  1911. ifp = vty->index;
  1912. zvrf = vrf_info_lookup (ifp->vrf_id);
  1913. zvrf->rtadv.AdvSendAdvertisements = 0;
  1914. return CMD_SUCCESS;
  1915. }
  1916. DEFUN (top_no_ipv6_nd_suppress_ra,
  1917. top_no_ipv6_nd_suppress_ra_cmd,
  1918. "no ipv6 nd suppress-ra",
  1919. NO_STR
  1920. IPV6_STR
  1921. ND_STR
  1922. "Suppress Router Advertisement by default\n")
  1923. {
  1924. struct zebra_vrf *zvrf;
  1925. struct interface *ifp;
  1926. ifp = vty->index;
  1927. zvrf = vrf_info_lookup (ifp->vrf_id);
  1928. zvrf->rtadv.AdvSendAdvertisements = 1;
  1929. return CMD_SUCCESS;
  1930. }
  1931. /* The following commands don't allow for explicit lifetime because of
  1932. * MaxRtrAdvInterval being specific to each interface. */
  1933. DEFUN (top_ipv6_nd_rdnss_addr,
  1934. top_ipv6_nd_rdnss_addr_cmd,
  1935. "ipv6 nd rdnss X:X::X:X",
  1936. IP6_STR
  1937. ND_STR
  1938. "Recursive DNS Server\n"
  1939. "IPv6 address of the server\n")
  1940. {
  1941. struct rtadv_rdnss_entry input, *stored;
  1942. struct zebra_vrf *zvrf;
  1943. struct interface *ifp;
  1944. ifp = vty->index;
  1945. zvrf = vrf_info_lookup (ifp->vrf_id);
  1946. struct rtadv *rtadv = &zvrf->rtadv;
  1947. if (CMD_SUCCESS != rtadv_validate_rdnss_args (vty, &input, 0, argc, argv))
  1948. return CMD_WARNING;
  1949. /* OK to commit the update */
  1950. if (! (stored = rtadv_rdnss_lookup (rtadv->AdvRDNSSList, &input.address)))
  1951. {
  1952. stored = XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_rdnss_entry));
  1953. listnode_add (rtadv->AdvRDNSSList, stored);
  1954. }
  1955. memcpy (stored, &input, sizeof (struct rtadv_rdnss_entry));
  1956. return CMD_SUCCESS;
  1957. }
  1958. DEFUN (top_no_ipv6_nd_rdnss_addr,
  1959. top_no_ipv6_nd_rdnss_addr_cmd,
  1960. "no ipv6 nd rdnss X:X::X:X",
  1961. NO_STR
  1962. IPV6_STR
  1963. ND_STR
  1964. "Recursive DNS Server\n"
  1965. "IPv6 address of the server\n")
  1966. {
  1967. struct zebra_vrf *zvrf;
  1968. struct interface *ifp;
  1969. ifp = vty->index;
  1970. zvrf = vrf_info_lookup (ifp->vrf_id);
  1971. struct rtadv_rdnss_entry *entry;
  1972. struct in6_addr v6addr;
  1973. if (1 != inet_pton (AF_INET6, argv[0], &v6addr))
  1974. return CMD_WARNING;
  1975. if (! (entry = rtadv_rdnss_lookup (zvrf->rtadv.AdvRDNSSList, &v6addr)))
  1976. {
  1977. vty_out (vty, "There is no such RDNSS address configured!%s", VTY_NEWLINE);
  1978. return CMD_WARNING;
  1979. }
  1980. listnode_delete (zvrf->rtadv.AdvRDNSSList, entry);
  1981. XFREE (MTYPE_RTADV_PREFIX, entry);
  1982. return CMD_SUCCESS;
  1983. }
  1984. DEFUN (top_ipv6_nd_dnssl_domain,
  1985. top_ipv6_nd_dnssl_domain_cmd,
  1986. "ipv6 nd dnssl DNS.DOMA.IN",
  1987. IPV6_STR
  1988. ND_STR
  1989. "DNS search list\n"
  1990. "DNS domain\n")
  1991. {
  1992. struct zebra_vrf *zvrf;
  1993. struct interface *ifp;
  1994. ifp = vty->index;
  1995. zvrf = vrf_info_lookup (ifp->vrf_id);
  1996. struct rtadv *rtadv = &zvrf->rtadv;
  1997. struct rtadv_dnssl_entry input, *stored;
  1998. if (CMD_SUCCESS != rtadv_validate_dnssl_args (vty, &input, 0, argc, argv))
  1999. return CMD_WARNING;
  2000. /* OK to commit the update */
  2001. if (! (stored = rtadv_dnssl_lookup (rtadv->AdvDNSSLList, input.subdomain_str)))
  2002. {
  2003. stored = XCALLOC (MTYPE_RTADV_PREFIX, sizeof (struct rtadv_dnssl_entry));
  2004. listnode_add (rtadv->AdvDNSSLList, stored);
  2005. }
  2006. memcpy (stored, &input, sizeof (struct rtadv_dnssl_entry));
  2007. return CMD_SUCCESS;
  2008. }
  2009. DEFUN (top_no_ipv6_nd_dnssl_domain,
  2010. top_no_ipv6_nd_dnssl_domain_cmd,
  2011. "no ipv6 nd dnssl DNS.DOMA.IN",
  2012. NO_STR
  2013. IPV6_STR
  2014. ND_STR
  2015. "DNS search list\n"
  2016. "DNS domain\n")
  2017. {
  2018. struct zebra_vrf *zvrf;
  2019. struct interface *ifp;
  2020. ifp = vty->index;
  2021. zvrf = vrf_info_lookup (ifp->vrf_id);
  2022. struct rtadv *rtadv = &zvrf->rtadv;
  2023. struct rtadv_dnssl_entry *entry;
  2024. if (! (entry = rtadv_dnssl_lookup (rtadv->AdvDNSSLList, argv[0])))
  2025. {
  2026. vty_out (vty, "There is no such DNSSL domain configured!%s", VTY_NEWLINE);
  2027. return CMD_WARNING;
  2028. }
  2029. listnode_delete (rtadv->AdvDNSSLList, entry);
  2030. XFREE (MTYPE_RTADV_PREFIX, entry);
  2031. return CMD_SUCCESS;
  2032. }
  2033. static int
  2034. top_rtadv_config_write (struct vty *vty)
  2035. {
  2036. int write = 0;
  2037. struct zebra_vrf *zvrf = vrf_info_lookup (VRF_DEFAULT);
  2038. struct rtadv *rtadv = &zvrf->rtadv;
  2039. if (rtadv->AdvSendAdvertisements)
  2040. {
  2041. vty_out (vty, "no ipv6 nd suppress-ra%s", VTY_NEWLINE);
  2042. write++;
  2043. }
  2044. write += rtadv_print_rdnss_list (vty, rtadv->AdvRDNSSList, "ipv6 nd rdnss");
  2045. write += rtadv_print_dnssl_list (vty, rtadv->AdvDNSSLList, "ipv6 nd dnssl");
  2046. return write;
  2047. }
  2048. static void
  2049. rtadv_event (struct zebra_vrf *zvrf, enum rtadv_event event, int val)
  2050. {
  2051. struct rtadv *rtadv = &zvrf->rtadv;
  2052. switch (event)
  2053. {
  2054. case RTADV_START:
  2055. if (! rtadv->ra_read)
  2056. rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zvrf, val);
  2057. if (! rtadv->ra_timer)
  2058. rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
  2059. zvrf, 0);
  2060. break;
  2061. case RTADV_STOP:
  2062. if (rtadv->ra_timer)
  2063. {
  2064. thread_cancel (rtadv->ra_timer);
  2065. rtadv->ra_timer = NULL;
  2066. }
  2067. if (rtadv->ra_read)
  2068. {
  2069. thread_cancel (rtadv->ra_read);
  2070. rtadv->ra_read = NULL;
  2071. }
  2072. break;
  2073. case RTADV_TIMER:
  2074. if (! rtadv->ra_timer)
  2075. rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, zvrf,
  2076. val);
  2077. break;
  2078. case RTADV_TIMER_MSEC:
  2079. if (! rtadv->ra_timer)
  2080. rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
  2081. zvrf, val);
  2082. break;
  2083. case RTADV_READ:
  2084. if (! rtadv->ra_read)
  2085. rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zvrf, val);
  2086. break;
  2087. default:
  2088. break;
  2089. }
  2090. return;
  2091. }
  2092. void
  2093. rtadv_init (struct zebra_vrf *zvrf)
  2094. {
  2095. zvrf->rtadv.AdvRDNSSList = list_new();
  2096. zvrf->rtadv.AdvDNSSLList = list_new();
  2097. zvrf->rtadv.sock = rtadv_make_socket (zvrf->vrf_id);
  2098. }
  2099. void
  2100. rtadv_terminate (struct zebra_vrf *zvrf)
  2101. {
  2102. rtadv_event (zvrf, RTADV_STOP, 0);
  2103. if (zvrf->rtadv.sock >= 0)
  2104. {
  2105. close (zvrf->rtadv.sock);
  2106. zvrf->rtadv.sock = -1;
  2107. }
  2108. zvrf->rtadv.adv_if_count = 0;
  2109. zvrf->rtadv.adv_msec_if_count = 0;
  2110. }
  2111. void
  2112. rtadv_cmd_init (void)
  2113. {
  2114. install_node (&ipv6_nd_node, top_rtadv_config_write);
  2115. install_element (CONFIG_NODE, &top_ipv6_nd_suppress_ra_cmd);
  2116. install_element (CONFIG_NODE, &top_no_ipv6_nd_suppress_ra_cmd);
  2117. install_element (CONFIG_NODE, &top_ipv6_nd_rdnss_addr_cmd);
  2118. install_element (CONFIG_NODE, &top_no_ipv6_nd_rdnss_addr_cmd);
  2119. install_element (CONFIG_NODE, &top_ipv6_nd_dnssl_domain_cmd);
  2120. install_element (CONFIG_NODE, &top_no_ipv6_nd_dnssl_domain_cmd);
  2121. install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
  2122. install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
  2123. install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
  2124. install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_msec_cmd);
  2125. install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_cmd);
  2126. install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_val_cmd);
  2127. install_element (INTERFACE_NODE, &no_ipv6_nd_ra_interval_msec_val_cmd);
  2128. install_element (INTERFACE_NODE, &ipv6_nd_ra_lifetime_cmd);
  2129. install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_cmd);
  2130. install_element (INTERFACE_NODE, &no_ipv6_nd_ra_lifetime_val_cmd);
  2131. install_element (INTERFACE_NODE, &ipv6_nd_reachable_time_cmd);
  2132. install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_cmd);
  2133. install_element (INTERFACE_NODE, &no_ipv6_nd_reachable_time_val_cmd);
  2134. install_element (INTERFACE_NODE, &ipv6_nd_managed_config_flag_cmd);
  2135. install_element (INTERFACE_NODE, &no_ipv6_nd_managed_config_flag_cmd);
  2136. install_element (INTERFACE_NODE, &ipv6_nd_other_config_flag_cmd);
  2137. install_element (INTERFACE_NODE, &no_ipv6_nd_other_config_flag_cmd);
  2138. install_element (INTERFACE_NODE, &ipv6_nd_homeagent_config_flag_cmd);
  2139. install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_config_flag_cmd);
  2140. install_element (INTERFACE_NODE, &ipv6_nd_homeagent_preference_cmd);
  2141. install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_cmd);
  2142. install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_preference_val_cmd);
  2143. install_element (INTERFACE_NODE, &ipv6_nd_homeagent_lifetime_cmd);
  2144. install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_cmd);
  2145. install_element (INTERFACE_NODE, &no_ipv6_nd_homeagent_lifetime_val_cmd);
  2146. install_element (INTERFACE_NODE, &ipv6_nd_adv_interval_config_option_cmd);
  2147. install_element (INTERFACE_NODE, &no_ipv6_nd_adv_interval_config_option_cmd);
  2148. install_element (INTERFACE_NODE, &ipv6_nd_prefix_cmd);
  2149. install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_rtaddr_cmd);
  2150. install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_nortaddr_cmd);
  2151. install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rev_cmd);
  2152. install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_noauto_cmd);
  2153. install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_offlink_cmd);
  2154. install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_rtaddr_cmd);
  2155. install_element (INTERFACE_NODE, &ipv6_nd_prefix_val_cmd);
  2156. install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_cmd);
  2157. install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rev_cmd);
  2158. install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_noauto_cmd);
  2159. install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_offlink_cmd);
  2160. install_element (INTERFACE_NODE, &ipv6_nd_prefix_noval_rtaddr_cmd);
  2161. install_element (INTERFACE_NODE, &ipv6_nd_prefix_prefix_cmd);
  2162. install_element (INTERFACE_NODE, &no_ipv6_nd_prefix_cmd);
  2163. install_element (INTERFACE_NODE, &ipv6_nd_router_preference_cmd);
  2164. install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_cmd);
  2165. install_element (INTERFACE_NODE, &no_ipv6_nd_router_preference_val_cmd);
  2166. install_element (INTERFACE_NODE, &ipv6_nd_mtu_cmd);
  2167. install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_cmd);
  2168. install_element (INTERFACE_NODE, &no_ipv6_nd_mtu_val_cmd);
  2169. install_element (INTERFACE_NODE, &ipv6_nd_rdnss_addr_cmd);
  2170. install_element (INTERFACE_NODE, &ipv6_nd_rdnss_addr_lft_cmd);
  2171. install_element (INTERFACE_NODE, &no_ipv6_nd_rdnss_addr_cmd);
  2172. install_element (INTERFACE_NODE, &no_ipv6_nd_rdnss_addr_lft_cmd);
  2173. install_element (INTERFACE_NODE, &ipv6_nd_dnssl_domain_cmd);
  2174. install_element (INTERFACE_NODE, &ipv6_nd_dnssl_domain_lft_cmd);
  2175. install_element (INTERFACE_NODE, &no_ipv6_nd_dnssl_domain_cmd);
  2176. install_element (INTERFACE_NODE, &no_ipv6_nd_dnssl_domain_lft_cmd);
  2177. }
  2178. static int
  2179. if_join_all_router (int sock, struct interface *ifp)
  2180. {
  2181. int ret;
  2182. struct ipv6_mreq mreq;
  2183. memset (&mreq, 0, sizeof (struct ipv6_mreq));
  2184. inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
  2185. mreq.ipv6mr_interface = ifp->ifindex;
  2186. ret = setsockopt (sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  2187. (char *) &mreq, sizeof mreq);
  2188. if (ret < 0)
  2189. zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s", safe_strerror (errno));
  2190. zlog_info ("rtadv: %s join to all-routers multicast group", ifp->name);
  2191. return 0;
  2192. }
  2193. static int
  2194. if_leave_all_router (int sock, struct interface *ifp)
  2195. {
  2196. int ret;
  2197. struct ipv6_mreq mreq;
  2198. memset (&mreq, 0, sizeof (struct ipv6_mreq));
  2199. inet_pton (AF_INET6, ALLROUTER, &mreq.ipv6mr_multiaddr);
  2200. mreq.ipv6mr_interface = ifp->ifindex;
  2201. ret = setsockopt (sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
  2202. (char *) &mreq, sizeof mreq);
  2203. if (ret < 0)
  2204. zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s", safe_strerror (errno));
  2205. zlog_info ("rtadv: %s leave from all-routers multicast group", ifp->name);
  2206. return 0;
  2207. }
  2208. /* Dump interface ND information to vty. */
  2209. void
  2210. rtadv_if_dump_vty (struct vty *vty, const struct rtadvconf *conf)
  2211. {
  2212. if (! conf->AdvSendAdvertisements)
  2213. return;
  2214. vty_out (vty, " ND advertised reachable time is %d milliseconds%s",
  2215. conf->AdvReachableTime, VTY_NEWLINE);
  2216. vty_out (vty, " ND advertised retransmit interval is %d milliseconds%s",
  2217. conf->AdvRetransTimer, VTY_NEWLINE);
  2218. if (conf->MaxRtrAdvInterval % 1000)
  2219. vty_out (vty, " ND router advertisements are sent every %d milliseconds%s",
  2220. conf->MaxRtrAdvInterval, VTY_NEWLINE);
  2221. else
  2222. vty_out (vty, " ND router advertisements are sent every %d seconds%s",
  2223. conf->MaxRtrAdvInterval / 1000, VTY_NEWLINE);
  2224. if (conf->AdvDefaultLifetime != -1)
  2225. vty_out (vty, " ND router advertisements live for %d seconds%s",
  2226. conf->AdvDefaultLifetime, VTY_NEWLINE);
  2227. else
  2228. vty_out (vty, " ND router advertisements lifetime tracks ra-interval%s", VTY_NEWLINE);
  2229. vty_out (vty, " ND router advertisement default router preference is %s%s",
  2230. LOOKUP (rtadv_pref_strs, conf->DefaultPreference), VTY_NEWLINE);
  2231. if (conf->AdvManagedFlag)
  2232. vty_out (vty, " Hosts use DHCP to obtain routable addresses.%s", VTY_NEWLINE);
  2233. else
  2234. vty_out (vty, " Hosts use stateless autoconfig for addresses.%s", VTY_NEWLINE);
  2235. if (conf->AdvHomeAgentFlag)
  2236. {
  2237. vty_out (vty, " ND router advertisements with Home Agent flag bit set.%s", VTY_NEWLINE);
  2238. if (conf->HomeAgentLifetime != -1)
  2239. vty_out (vty, " Home Agent lifetime is %u seconds%s", conf->HomeAgentLifetime, VTY_NEWLINE);
  2240. else
  2241. vty_out (vty, " Home Agent lifetime tracks ra-lifetime%s", VTY_NEWLINE);
  2242. vty_out (vty, " Home Agent preference is %u%s", conf->HomeAgentPreference, VTY_NEWLINE);
  2243. }
  2244. if (listcount (conf->AdvRDNSSList))
  2245. vty_out (vty, " ND router advertisements with RDNSS information.%s", VTY_NEWLINE);
  2246. if (listcount (conf->AdvDNSSLList))
  2247. vty_out (vty, " ND router advertisements with DNSSL information%s", VTY_NEWLINE);
  2248. if (conf->AdvIntervalOption)
  2249. vty_out (vty, " ND router advertisements with Adv. Interval option.%s", VTY_NEWLINE);
  2250. }
  2251. /* Set default router advertise values. */
  2252. void
  2253. rtadv_if_new_hook (struct rtadvconf *conf)
  2254. {
  2255. struct zebra_vrf *zvrf = vrf_info_lookup (VRF_DEFAULT);
  2256. struct rtadv *rtadv = &zvrf->rtadv;
  2257. /* Derive once from global parameter, then manage independently. */
  2258. conf->AdvSendAdvertisements = rtadv->AdvSendAdvertisements;
  2259. conf->MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
  2260. conf->MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
  2261. conf->AdvIntervalTimer = 0;
  2262. conf->AdvManagedFlag = 0;
  2263. conf->AdvOtherConfigFlag = 0;
  2264. conf->AdvHomeAgentFlag = 0;
  2265. conf->AdvLinkMTU = 0;
  2266. conf->AdvReachableTime = 0;
  2267. conf->AdvRetransTimer = 0;
  2268. conf->AdvCurHopLimit = 0;
  2269. conf->AdvDefaultLifetime = -1; /* derive from MaxRtrAdvInterval */
  2270. conf->HomeAgentPreference = 0;
  2271. conf->HomeAgentLifetime = -1; /* derive from AdvDefaultLifetime */
  2272. conf->AdvIntervalOption = 0;
  2273. conf->DefaultPreference = RTADV_PREF_MEDIUM;
  2274. conf->AdvPrefixList = list_new ();
  2275. conf->AdvRDNSSList = list_new ();
  2276. conf->AdvDNSSLList = list_new ();
  2277. }
  2278. #else
  2279. void
  2280. rtadv_init (struct zebra_vrf *zvrf)
  2281. {
  2282. /* Empty.*/;
  2283. }
  2284. void
  2285. rtadv_terminate (struct zebra_vrf *zvrf)
  2286. {
  2287. /* Empty.*/;
  2288. }
  2289. void
  2290. rtadv_cmd_init (void)
  2291. {
  2292. /* Empty.*/;
  2293. }
  2294. #endif /* HAVE_RTADV && HAVE_IPV6 */