nd6_rtr.c 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235
  1. /* $OpenBSD: nd6_rtr.c,v 1.113 2015/07/18 15:51:17 mpi Exp $ */
  2. /* $KAME: nd6_rtr.c,v 1.97 2001/02/07 11:09:13 itojun Exp $ */
  3. /*
  4. * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the project nor the names of its contributors
  16. * may be used to endorse or promote products derived from this software
  17. * without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
  20. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. */
  31. #include <sys/param.h>
  32. #include <sys/systm.h>
  33. #include <sys/timeout.h>
  34. #include <sys/malloc.h>
  35. #include <sys/mbuf.h>
  36. #include <sys/socket.h>
  37. #include <sys/sockio.h>
  38. #include <sys/time.h>
  39. #include <sys/kernel.h>
  40. #include <sys/errno.h>
  41. #include <sys/ioctl.h>
  42. #include <sys/syslog.h>
  43. #include <sys/queue.h>
  44. #include <net/if.h>
  45. #include <net/if_dl.h>
  46. #include <net/if_var.h>
  47. #include <net/if_types.h>
  48. #include <net/route.h>
  49. #include <net/rtable.h>
  50. #include <netinet/in.h>
  51. #include <netinet6/in6_var.h>
  52. #include <netinet/ip6.h>
  53. #include <netinet6/ip6_var.h>
  54. #include <netinet6/nd6.h>
  55. #include <netinet/icmp6.h>
  56. #define SDL(s) ((struct sockaddr_dl *)s)
  57. int rtpref(struct nd_defrouter *);
  58. struct nd_defrouter *defrtrlist_update(struct nd_defrouter *);
  59. struct in6_ifaddr *in6_ifadd(struct nd_prefix *, int);
  60. struct nd_pfxrouter *pfxrtr_lookup(struct nd_prefix *, struct nd_defrouter *);
  61. void pfxrtr_add(struct nd_prefix *, struct nd_defrouter *);
  62. void pfxrtr_del(struct nd_pfxrouter *);
  63. struct nd_pfxrouter *find_pfxlist_reachable_router(struct nd_prefix *);
  64. void defrouter_delreq(struct nd_defrouter *);
  65. void purge_detached(struct ifnet *);
  66. void in6_init_address_ltimes(struct nd_prefix *, struct in6_addrlifetime *);
  67. int rt6_deleteroute(struct rtentry *, void *, unsigned int);
  68. void nd6_addr_add(void *);
  69. void nd6_rs_output_timo(void *);
  70. void nd6_rs_output_set_timo(int);
  71. void nd6_rs_output(struct ifnet *, struct in6_ifaddr *);
  72. void nd6_rs_dev_state(void *);
  73. extern int nd6_recalc_reachtm_interval;
  74. #define ND6_RS_OUTPUT_INTERVAL 60
  75. #define ND6_RS_OUTPUT_QUICK_INTERVAL 1
  76. struct timeout nd6_rs_output_timer;
  77. int nd6_rs_output_timeout = ND6_RS_OUTPUT_INTERVAL;
  78. int nd6_rs_timeout_count = 0;
  79. void
  80. nd6_rs_init(void)
  81. {
  82. timeout_set(&nd6_rs_output_timer, nd6_rs_output_timo, NULL);
  83. }
  84. /*
  85. * Receive Router Solicitation Message - just for routers.
  86. * Router solicitation/advertisement is mostly managed by userland program
  87. * (rtadvd) so here we have no function like nd6_ra_output().
  88. *
  89. * Based on RFC 2461
  90. */
  91. void
  92. nd6_rs_input(struct mbuf *m, int off, int icmp6len)
  93. {
  94. struct ifnet *ifp;
  95. struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
  96. struct nd_router_solicit *nd_rs;
  97. struct in6_addr saddr6 = ip6->ip6_src;
  98. #if 0
  99. struct in6_addr daddr6 = ip6->ip6_dst;
  100. #endif
  101. char *lladdr = NULL;
  102. int lladdrlen = 0;
  103. #if 0
  104. struct sockaddr_dl *sdl = NULL;
  105. struct llinfo_nd6 *ln = NULL;
  106. struct rtentry *rt = NULL;
  107. int is_newentry;
  108. #endif
  109. union nd_opts ndopts;
  110. char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN];
  111. ifp = if_get(m->m_pkthdr.ph_ifidx);
  112. if (ifp == NULL)
  113. goto freeit;
  114. /* If I'm not a router, ignore it. XXX - too restrictive? */
  115. if (!ip6_forwarding)
  116. goto freeit;
  117. /* Sanity checks */
  118. if (ip6->ip6_hlim != 255) {
  119. nd6log((LOG_ERR,
  120. "nd6_rs_input: invalid hlim (%d) from %s to %s on %s\n",
  121. ip6->ip6_hlim,
  122. inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)),
  123. inet_ntop(AF_INET6, &ip6->ip6_dst, dst, sizeof(dst)),
  124. ifp->if_xname));
  125. goto bad;
  126. }
  127. /*
  128. * Don't update the neighbor cache, if src = ::.
  129. * This indicates that the src has no IP address assigned yet.
  130. */
  131. if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))
  132. goto freeit;
  133. IP6_EXTHDR_GET(nd_rs, struct nd_router_solicit *, m, off, icmp6len);
  134. if (nd_rs == NULL) {
  135. icmp6stat.icp6s_tooshort++;
  136. return;
  137. }
  138. icmp6len -= sizeof(*nd_rs);
  139. nd6_option_init(nd_rs + 1, icmp6len, &ndopts);
  140. if (nd6_options(&ndopts) < 0) {
  141. nd6log((LOG_INFO,
  142. "nd6_rs_input: invalid ND option, ignored\n"));
  143. /* nd6_options have incremented stats */
  144. goto freeit;
  145. }
  146. if (ndopts.nd_opts_src_lladdr) {
  147. lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
  148. lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
  149. }
  150. if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
  151. nd6log((LOG_INFO,
  152. "nd6_rs_input: lladdrlen mismatch for %s "
  153. "(if %d, RS packet %d)\n",
  154. inet_ntop(AF_INET6, &saddr6, src, sizeof(src)),
  155. ifp->if_addrlen, lladdrlen - 2));
  156. goto bad;
  157. }
  158. nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0);
  159. freeit:
  160. m_freem(m);
  161. return;
  162. bad:
  163. icmp6stat.icp6s_badrs++;
  164. m_freem(m);
  165. }
  166. void
  167. nd6_rs_output(struct ifnet* ifp, struct in6_ifaddr *ia6)
  168. {
  169. struct mbuf *m;
  170. struct ip6_hdr *ip6;
  171. struct nd_router_solicit *rs;
  172. struct ip6_moptions im6o;
  173. caddr_t mac;
  174. int icmp6len, maxlen, s;
  175. KASSERT(ia6 != NULL);
  176. KASSERT(ifp->if_flags & IFF_RUNNING);
  177. KASSERT(ifp->if_xflags & IFXF_AUTOCONF6);
  178. KASSERT(!(ia6->ia6_flags & IN6_IFF_TENTATIVE));
  179. maxlen = sizeof(*ip6) + sizeof(*rs);
  180. maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
  181. MGETHDR(m, M_DONTWAIT, MT_DATA);
  182. if (m && max_linkhdr + maxlen >= MHLEN) {
  183. MCLGET(m, M_DONTWAIT);
  184. if ((m->m_flags & M_EXT) == 0) {
  185. m_free(m);
  186. m = NULL;
  187. }
  188. }
  189. if (m == NULL)
  190. return;
  191. m->m_pkthdr.ph_ifidx = 0;
  192. m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
  193. m->m_flags |= M_MCAST;
  194. m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT;
  195. im6o.im6o_ifidx = ifp->if_index;
  196. im6o.im6o_hlim = 255;
  197. im6o.im6o_loop = 0;
  198. icmp6len = sizeof(*rs);
  199. m->m_pkthdr.len = m->m_len = sizeof(*ip6) + icmp6len;
  200. m->m_data += max_linkhdr; /* or MH_ALIGN() equivalent? */
  201. /* fill neighbor solicitation packet */
  202. ip6 = mtod(m, struct ip6_hdr *);
  203. ip6->ip6_flow = 0;
  204. ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
  205. ip6->ip6_vfc |= IPV6_VERSION;
  206. /* ip6->ip6_plen will be set later */
  207. ip6->ip6_nxt = IPPROTO_ICMPV6;
  208. ip6->ip6_hlim = 255;
  209. ip6->ip6_dst = in6addr_linklocal_allrouters;
  210. ip6->ip6_src = ia6->ia_addr.sin6_addr;
  211. rs = (struct nd_router_solicit *)(ip6 + 1);
  212. rs->nd_rs_type = ND_ROUTER_SOLICIT;
  213. rs->nd_rs_code = 0;
  214. rs->nd_rs_cksum = 0;
  215. rs->nd_rs_reserved = 0;
  216. if ((mac = nd6_ifptomac(ifp))) {
  217. int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
  218. struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(rs + 1);
  219. /* 8 byte alignments... */
  220. optlen = (optlen + 7) & ~7;
  221. m->m_pkthdr.len += optlen;
  222. m->m_len += optlen;
  223. icmp6len += optlen;
  224. bzero((caddr_t)nd_opt, optlen);
  225. nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
  226. nd_opt->nd_opt_len = optlen >> 3;
  227. bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
  228. }
  229. ip6->ip6_plen = htons((u_short)icmp6len);
  230. s = splsoftnet();
  231. ip6_output(m, NULL, NULL, 0, &im6o, NULL, NULL);
  232. splx(s);
  233. icmp6_ifstat_inc(ifp, ifs6_out_msg);
  234. icmp6_ifstat_inc(ifp, ifs6_out_routersolicit);
  235. icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT]++;
  236. }
  237. void
  238. nd6_rs_output_set_timo(int timeout)
  239. {
  240. nd6_rs_output_timeout = timeout;
  241. timeout_add_sec(&nd6_rs_output_timer, nd6_rs_output_timeout);
  242. }
  243. void
  244. nd6_rs_output_timo(void *ignored_arg)
  245. {
  246. struct ifnet *ifp;
  247. struct in6_ifaddr *ia6;
  248. if (nd6_rs_timeout_count == 0)
  249. return;
  250. if (nd6_rs_output_timeout < ND6_RS_OUTPUT_INTERVAL)
  251. /* exponential backoff if running quick timeouts */
  252. nd6_rs_output_timeout *= 2;
  253. if (nd6_rs_output_timeout > ND6_RS_OUTPUT_INTERVAL)
  254. nd6_rs_output_timeout = ND6_RS_OUTPUT_INTERVAL;
  255. TAILQ_FOREACH(ifp, &ifnet, if_list) {
  256. if (ISSET(ifp->if_flags, IFF_RUNNING) &&
  257. ISSET(ifp->if_xflags, IFXF_AUTOCONF6)) {
  258. ia6 = in6ifa_ifpforlinklocal(ifp, IN6_IFF_TENTATIVE);
  259. if (ia6 != NULL)
  260. nd6_rs_output(ifp, ia6);
  261. }
  262. }
  263. timeout_add_sec(&nd6_rs_output_timer, nd6_rs_output_timeout);
  264. }
  265. void
  266. nd6_rs_attach(struct ifnet *ifp)
  267. {
  268. if (!ISSET(ifp->if_xflags, IFXF_AUTOCONF6)) {
  269. nd6_rs_timeout_count++;
  270. RS_LHCOOKIE(ifp) = hook_establish(ifp->if_linkstatehooks, 1,
  271. nd6_rs_dev_state, ifp);
  272. }
  273. nd6_rs_output_set_timo(ND6_RS_OUTPUT_QUICK_INTERVAL);
  274. }
  275. void
  276. nd6_rs_detach(struct ifnet *ifp)
  277. {
  278. if (ISSET(ifp->if_xflags, IFXF_AUTOCONF6)) {
  279. nd6_rs_timeout_count--;
  280. hook_disestablish(ifp->if_linkstatehooks, RS_LHCOOKIE(ifp));
  281. }
  282. if (nd6_rs_timeout_count == 0)
  283. timeout_del(&nd6_rs_output_timer);
  284. }
  285. void
  286. nd6_rs_dev_state(void *arg)
  287. {
  288. struct ifnet *ifp;
  289. ifp = (struct ifnet *) arg;
  290. if (LINK_STATE_IS_UP(ifp->if_link_state) &&
  291. ifp->if_flags & IFF_RUNNING)
  292. /* start quick timer, will exponentially back off */
  293. nd6_rs_output_set_timo(ND6_RS_OUTPUT_QUICK_INTERVAL);
  294. }
  295. /*
  296. * Receive Router Advertisement Message.
  297. *
  298. * Based on RFC 2461
  299. */
  300. void
  301. nd6_ra_input(struct mbuf *m, int off, int icmp6len)
  302. {
  303. struct ifnet *ifp;
  304. struct nd_ifinfo *ndi;
  305. struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
  306. struct nd_router_advert *nd_ra;
  307. struct in6_addr saddr6 = ip6->ip6_src;
  308. union nd_opts ndopts;
  309. struct nd_defrouter *dr;
  310. char src[INET6_ADDRSTRLEN], dst[INET6_ADDRSTRLEN];
  311. ifp = if_get(m->m_pkthdr.ph_ifidx);
  312. if (ifp == NULL)
  313. goto freeit;
  314. /* We accept RAs only if inet6 autoconf is enabled */
  315. if (!(ifp->if_xflags & IFXF_AUTOCONF6))
  316. goto freeit;
  317. ndi = ND_IFINFO(ifp);
  318. if (!(ndi->flags & ND6_IFF_ACCEPT_RTADV))
  319. goto freeit;
  320. if (nd6_rs_output_timeout != ND6_RS_OUTPUT_INTERVAL)
  321. /* we saw a RA, stop quick timer */
  322. nd6_rs_output_set_timo(ND6_RS_OUTPUT_INTERVAL);
  323. if (ip6->ip6_hlim != 255) {
  324. nd6log((LOG_ERR,
  325. "nd6_ra_input: invalid hlim (%d) from %s to %s on %s\n",
  326. ip6->ip6_hlim,
  327. inet_ntop(AF_INET6, &ip6->ip6_src, src, sizeof(src)),
  328. inet_ntop(AF_INET6, &ip6->ip6_dst, dst, sizeof(dst)),
  329. ifp->if_xname));
  330. goto bad;
  331. }
  332. if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) {
  333. nd6log((LOG_ERR,
  334. "nd6_ra_input: src %s is not link-local\n",
  335. inet_ntop(AF_INET6, &saddr6, src, sizeof(src))));
  336. goto bad;
  337. }
  338. IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len);
  339. if (nd_ra == NULL) {
  340. icmp6stat.icp6s_tooshort++;
  341. return;
  342. }
  343. icmp6len -= sizeof(*nd_ra);
  344. nd6_option_init(nd_ra + 1, icmp6len, &ndopts);
  345. if (nd6_options(&ndopts) < 0) {
  346. nd6log((LOG_INFO,
  347. "nd6_ra_input: invalid ND option, ignored\n"));
  348. /* nd6_options have incremented stats */
  349. goto freeit;
  350. }
  351. {
  352. struct nd_defrouter dr0;
  353. u_int32_t advreachable = nd_ra->nd_ra_reachable;
  354. memset(&dr0, 0, sizeof(dr0));
  355. dr0.rtaddr = saddr6;
  356. dr0.flags = nd_ra->nd_ra_flags_reserved;
  357. dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
  358. dr0.expire = time_second + dr0.rtlifetime;
  359. dr0.ifp = ifp;
  360. /* unspecified or not? (RFC 2461 6.3.4) */
  361. if (advreachable) {
  362. advreachable = ntohl(advreachable);
  363. if (advreachable <= MAX_REACHABLE_TIME &&
  364. ndi->basereachable != advreachable) {
  365. ndi->basereachable = advreachable;
  366. ndi->reachable = ND_COMPUTE_RTIME(ndi->basereachable);
  367. ndi->recalctm = nd6_recalc_reachtm_interval; /* reset */
  368. }
  369. }
  370. if (nd_ra->nd_ra_retransmit)
  371. ndi->retrans = ntohl(nd_ra->nd_ra_retransmit);
  372. if (nd_ra->nd_ra_curhoplimit)
  373. ndi->chlim = nd_ra->nd_ra_curhoplimit;
  374. dr = defrtrlist_update(&dr0);
  375. }
  376. /*
  377. * prefix
  378. */
  379. if (ndopts.nd_opts_pi) {
  380. struct nd_opt_hdr *pt;
  381. struct nd_opt_prefix_info *pi = NULL;
  382. struct nd_prefix pr;
  383. for (pt = (struct nd_opt_hdr *)ndopts.nd_opts_pi;
  384. pt <= (struct nd_opt_hdr *)ndopts.nd_opts_pi_end;
  385. pt = (struct nd_opt_hdr *)((caddr_t)pt +
  386. (pt->nd_opt_len << 3))) {
  387. if (pt->nd_opt_type != ND_OPT_PREFIX_INFORMATION)
  388. continue;
  389. pi = (struct nd_opt_prefix_info *)pt;
  390. if (pi->nd_opt_pi_len != 4) {
  391. nd6log((LOG_INFO,
  392. "nd6_ra_input: invalid option "
  393. "len %d for prefix information option, "
  394. "ignored\n", pi->nd_opt_pi_len));
  395. continue;
  396. }
  397. if (128 < pi->nd_opt_pi_prefix_len) {
  398. nd6log((LOG_INFO,
  399. "nd6_ra_input: invalid prefix "
  400. "len %d for prefix information option, "
  401. "ignored\n", pi->nd_opt_pi_prefix_len));
  402. continue;
  403. }
  404. if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix)
  405. || IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix)) {
  406. nd6log((LOG_INFO,
  407. "nd6_ra_input: invalid prefix "
  408. "%s, ignored\n",
  409. inet_ntop(AF_INET6, &pi->nd_opt_pi_prefix,
  410. src, sizeof(src))));
  411. continue;
  412. }
  413. /* aggregatable unicast address, rfc2374 */
  414. if ((pi->nd_opt_pi_prefix.s6_addr8[0] & 0xe0) == 0x20
  415. && pi->nd_opt_pi_prefix_len != 64) {
  416. nd6log((LOG_INFO,
  417. "nd6_ra_input: invalid prefixlen "
  418. "%d for rfc2374 prefix %s, ignored\n",
  419. pi->nd_opt_pi_prefix_len,
  420. inet_ntop(AF_INET6, &pi->nd_opt_pi_prefix,
  421. src, sizeof(src))));
  422. continue;
  423. }
  424. bzero(&pr, sizeof(pr));
  425. pr.ndpr_prefix.sin6_family = AF_INET6;
  426. pr.ndpr_prefix.sin6_len = sizeof(pr.ndpr_prefix);
  427. pr.ndpr_prefix.sin6_addr = pi->nd_opt_pi_prefix;
  428. pr.ndpr_ifp = ifp;
  429. pr.ndpr_raf_onlink = (pi->nd_opt_pi_flags_reserved &
  430. ND_OPT_PI_FLAG_ONLINK) ? 1 : 0;
  431. pr.ndpr_raf_auto = (pi->nd_opt_pi_flags_reserved &
  432. ND_OPT_PI_FLAG_AUTO) ? 1 : 0;
  433. pr.ndpr_plen = pi->nd_opt_pi_prefix_len;
  434. pr.ndpr_vltime = ntohl(pi->nd_opt_pi_valid_time);
  435. pr.ndpr_pltime = ntohl(pi->nd_opt_pi_preferred_time);
  436. pr.ndpr_lastupdate = time_second;
  437. if (in6_init_prefix_ltimes(&pr))
  438. continue; /* prefix lifetime init failed */
  439. (void)prelist_update(&pr, dr, m);
  440. }
  441. }
  442. /*
  443. * MTU
  444. */
  445. if (ndopts.nd_opts_mtu && ndopts.nd_opts_mtu->nd_opt_mtu_len == 1) {
  446. u_long mtu;
  447. u_long maxmtu;
  448. mtu = ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
  449. /* lower bound */
  450. if (mtu < IPV6_MMTU) {
  451. nd6log((LOG_INFO, "nd6_ra_input: bogus mtu option "
  452. "mtu=%lu sent from %s, ignoring\n",
  453. mtu,
  454. inet_ntop(AF_INET6, &ip6->ip6_src,
  455. src, sizeof(src))));
  456. goto skip;
  457. }
  458. /* upper bound */
  459. maxmtu = (ndi->maxmtu && ndi->maxmtu < ifp->if_mtu)
  460. ? ndi->maxmtu : ifp->if_mtu;
  461. if (mtu <= maxmtu) {
  462. ndi->linkmtu = mtu;
  463. } else {
  464. nd6log((LOG_INFO, "nd6_ra_input: bogus mtu "
  465. "mtu=%lu sent from %s; "
  466. "exceeds maxmtu %lu, ignoring\n",
  467. mtu,
  468. inet_ntop(AF_INET6, &ip6->ip6_src,
  469. src, sizeof(src)),
  470. maxmtu));
  471. }
  472. }
  473. skip:
  474. /*
  475. * Source link layer address
  476. */
  477. {
  478. char *lladdr = NULL;
  479. int lladdrlen = 0;
  480. if (ndopts.nd_opts_src_lladdr) {
  481. lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
  482. lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
  483. }
  484. if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
  485. nd6log((LOG_INFO,
  486. "nd6_ra_input: lladdrlen mismatch for %s "
  487. "(if %d, RA packet %d)\n",
  488. inet_ntop(AF_INET6, &saddr6, src, sizeof(src)),
  489. ifp->if_addrlen, lladdrlen - 2));
  490. goto bad;
  491. }
  492. nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_ADVERT, 0);
  493. /*
  494. * Installing a link-layer address might change the state of the
  495. * router's neighbor cache, which might also affect our on-link
  496. * detection of adveritsed prefixes.
  497. */
  498. pfxlist_onlink_check();
  499. }
  500. freeit:
  501. m_freem(m);
  502. return;
  503. bad:
  504. icmp6stat.icp6s_badra++;
  505. m_freem(m);
  506. }
  507. /*
  508. * default router list processing sub routines
  509. */
  510. void
  511. defrouter_addreq(struct nd_defrouter *new)
  512. {
  513. struct rt_addrinfo info;
  514. struct sockaddr_in6 def, mask, gate;
  515. struct rtentry *newrt = NULL;
  516. int s;
  517. int error;
  518. memset(&def, 0, sizeof(def));
  519. memset(&mask, 0, sizeof(mask));
  520. memset(&gate, 0, sizeof(gate)); /* for safety */
  521. memset(&info, 0, sizeof(info));
  522. def.sin6_len = mask.sin6_len = gate.sin6_len =
  523. sizeof(struct sockaddr_in6);
  524. def.sin6_family = mask.sin6_family = gate.sin6_family = AF_INET6;
  525. gate.sin6_addr = new->rtaddr;
  526. gate.sin6_scope_id = 0; /* XXX */
  527. info.rti_flags = RTF_GATEWAY;
  528. info.rti_info[RTAX_DST] = sin6tosa(&def);
  529. info.rti_info[RTAX_GATEWAY] = sin6tosa(&gate);
  530. info.rti_info[RTAX_NETMASK] = sin6tosa(&mask);
  531. s = splsoftnet();
  532. error = rtrequest1(RTM_ADD, &info, RTP_DEFAULT, &newrt,
  533. new->ifp->if_rdomain);
  534. if (newrt) {
  535. rt_sendmsg(newrt, RTM_ADD, new->ifp->if_rdomain);
  536. newrt->rt_refcnt--;
  537. }
  538. if (error == 0)
  539. new->installed = 1;
  540. splx(s);
  541. return;
  542. }
  543. struct nd_defrouter *
  544. defrouter_lookup(struct in6_addr *addr, struct ifnet *ifp)
  545. {
  546. struct nd_defrouter *dr;
  547. TAILQ_FOREACH(dr, &nd_defrouter, dr_entry)
  548. if (dr->ifp == ifp && IN6_ARE_ADDR_EQUAL(addr, &dr->rtaddr))
  549. return (dr);
  550. return (NULL); /* search failed */
  551. }
  552. void
  553. defrtrlist_del(struct nd_defrouter *dr)
  554. {
  555. struct nd_defrouter *deldr = NULL;
  556. struct in6_ifextra *ext = dr->ifp->if_afdata[AF_INET6];
  557. struct nd_prefix *pr;
  558. /*
  559. * Flush all the routing table entries that use the router
  560. * as a next hop.
  561. */
  562. /* XXX: better condition? */
  563. if (!ip6_forwarding)
  564. rt6_flush(&dr->rtaddr, dr->ifp);
  565. if (dr->installed) {
  566. deldr = dr;
  567. defrouter_delreq(dr);
  568. }
  569. TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
  570. /*
  571. * Also delete all the pointers to the router in each prefix lists.
  572. */
  573. LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
  574. struct nd_pfxrouter *pfxrtr;
  575. if ((pfxrtr = pfxrtr_lookup(pr, dr)) != NULL)
  576. pfxrtr_del(pfxrtr);
  577. }
  578. pfxlist_onlink_check();
  579. /*
  580. * If the router is the primary one, choose a new one.
  581. * Note that defrouter_select() will remove the current gateway
  582. * from the routing table.
  583. */
  584. if (deldr)
  585. defrouter_select();
  586. ext->ndefrouters--;
  587. if (ext->ndefrouters < 0) {
  588. log(LOG_WARNING, "defrtrlist_del: negative count on %s\n",
  589. dr->ifp->if_xname);
  590. }
  591. free(dr, M_IP6NDP, 0);
  592. }
  593. /*
  594. * Remove the default route for a given router.
  595. * This is just a subroutine function for defrouter_select(), and should
  596. * not be called from anywhere else.
  597. */
  598. void
  599. defrouter_delreq(struct nd_defrouter *dr)
  600. {
  601. struct rt_addrinfo info;
  602. struct sockaddr_in6 def, mask, gw;
  603. struct rtentry *oldrt = NULL;
  604. #ifdef DIAGNOSTIC
  605. if (!dr)
  606. panic("dr == NULL in defrouter_delreq");
  607. #endif
  608. memset(&info, 0, sizeof(info));
  609. memset(&def, 0, sizeof(def));
  610. memset(&mask, 0, sizeof(mask));
  611. memset(&gw, 0, sizeof(gw)); /* for safety */
  612. def.sin6_len = mask.sin6_len = gw.sin6_len =
  613. sizeof(struct sockaddr_in6);
  614. def.sin6_family = mask.sin6_family = gw.sin6_family = AF_INET6;
  615. gw.sin6_addr = dr->rtaddr;
  616. gw.sin6_scope_id = 0; /* XXX */
  617. info.rti_flags = RTF_GATEWAY;
  618. info.rti_info[RTAX_DST] = sin6tosa(&def);
  619. info.rti_info[RTAX_GATEWAY] = sin6tosa(&gw);
  620. info.rti_info[RTAX_NETMASK] = sin6tosa(&mask);
  621. rtrequest1(RTM_DELETE, &info, RTP_DEFAULT, &oldrt,
  622. dr->ifp->if_rdomain);
  623. if (oldrt) {
  624. rt_sendmsg(oldrt, RTM_DELETE, dr->ifp->if_rdomain);
  625. if (oldrt->rt_refcnt <= 0) {
  626. /*
  627. * XXX: borrowed from the RTM_DELETE case of
  628. * rtrequest1().
  629. */
  630. oldrt->rt_refcnt++;
  631. rtfree(oldrt);
  632. }
  633. }
  634. dr->installed = 0;
  635. }
  636. /*
  637. * remove all default routes from default router list
  638. */
  639. void
  640. defrouter_reset(void)
  641. {
  642. struct nd_defrouter *dr;
  643. TAILQ_FOREACH(dr, &nd_defrouter, dr_entry)
  644. defrouter_delreq(dr);
  645. /*
  646. * XXX should we also nuke any default routers in the kernel, by
  647. * going through them by rtalloc()?
  648. */
  649. }
  650. /*
  651. * Default Router Selection according to Section 6.3.6 of RFC 2461 and
  652. * draft-ietf-ipngwg-router-selection:
  653. * 1) Routers that are reachable or probably reachable should be preferred.
  654. * If we have more than one (probably) reachable router, prefer ones
  655. * with the highest router preference.
  656. * 2) When no routers on the list are known to be reachable or
  657. * probably reachable, routers SHOULD be selected in a round-robin
  658. * fashion, regardless of router preference values.
  659. * 3) If the Default Router List is empty, assume that all
  660. * destinations are on-link.
  661. *
  662. * We assume nd_defrouter is sorted by router preference value.
  663. * Since the code below covers both with and without router preference cases,
  664. * we do not need to classify the cases by ifdef.
  665. *
  666. * At this moment, we do not try to install more than one default router,
  667. * even when the multipath routing is available, because we're not sure about
  668. * the benefits for stub hosts comparing to the risk of making the code
  669. * complicated and the possibility of introducing bugs.
  670. */
  671. void
  672. defrouter_select(void)
  673. {
  674. struct nd_defrouter *dr, *selected_dr = NULL, *installed_dr = NULL;
  675. struct rtentry *rt = NULL;
  676. struct llinfo_nd6 *ln = NULL;
  677. int s = splsoftnet();
  678. /*
  679. * Let's handle easy case (3) first:
  680. * If default router list is empty, there's nothing to be done.
  681. */
  682. if (TAILQ_EMPTY(&nd_defrouter)) {
  683. splx(s);
  684. return;
  685. }
  686. /*
  687. * Search for a (probably) reachable router from the list.
  688. * We just pick up the first reachable one (if any), assuming that
  689. * the ordering rule of the list described in defrtrlist_update().
  690. */
  691. TAILQ_FOREACH(dr, &nd_defrouter, dr_entry) {
  692. if (!(dr->ifp->if_xflags & IFXF_AUTOCONF6))
  693. continue;
  694. if (!selected_dr &&
  695. (rt = nd6_lookup(&dr->rtaddr, 0, dr->ifp,
  696. dr->ifp->if_rdomain)) &&
  697. (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
  698. ND6_IS_LLINFO_PROBREACH(ln)) {
  699. selected_dr = dr;
  700. }
  701. if (dr->installed && !installed_dr)
  702. installed_dr = dr;
  703. else if (dr->installed && installed_dr) {
  704. /* this should not happen. warn for diagnosis. */
  705. log(LOG_ERR, "defrouter_select: more than one router"
  706. " is installed\n");
  707. }
  708. }
  709. /*
  710. * If none of the default routers was found to be reachable,
  711. * round-robin the list regardless of preference.
  712. * Otherwise, if we have an installed router, check if the selected
  713. * (reachable) router should really be preferred to the installed one.
  714. * We only prefer the new router when the old one is not reachable
  715. * or when the new one has a really higher preference value.
  716. */
  717. if (!selected_dr) {
  718. if (!installed_dr || !TAILQ_NEXT(installed_dr, dr_entry))
  719. selected_dr = TAILQ_FIRST(&nd_defrouter);
  720. else
  721. selected_dr = TAILQ_NEXT(installed_dr, dr_entry);
  722. } else if (installed_dr &&
  723. (rt = nd6_lookup(&installed_dr->rtaddr, 0, installed_dr->ifp,
  724. installed_dr->ifp->if_rdomain)) &&
  725. (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
  726. ND6_IS_LLINFO_PROBREACH(ln) &&
  727. rtpref(selected_dr) <= rtpref(installed_dr)) {
  728. selected_dr = installed_dr;
  729. }
  730. /*
  731. * If the selected router is different than the installed one,
  732. * remove the installed router and install the selected one.
  733. * Note that the selected router is never NULL here.
  734. */
  735. if (installed_dr != selected_dr) {
  736. if (installed_dr)
  737. defrouter_delreq(installed_dr);
  738. defrouter_addreq(selected_dr);
  739. }
  740. splx(s);
  741. return;
  742. }
  743. /*
  744. * for default router selection
  745. * regards router-preference field as a 2-bit signed integer
  746. */
  747. int
  748. rtpref(struct nd_defrouter *dr)
  749. {
  750. #ifdef RTPREF
  751. switch (dr->flags & ND_RA_FLAG_RTPREF_MASK) {
  752. case ND_RA_FLAG_RTPREF_HIGH:
  753. return RTPREF_HIGH;
  754. case ND_RA_FLAG_RTPREF_MEDIUM:
  755. case ND_RA_FLAG_RTPREF_RSV:
  756. return RTPREF_MEDIUM;
  757. case ND_RA_FLAG_RTPREF_LOW:
  758. return RTPREF_LOW;
  759. default:
  760. /*
  761. * This case should never happen. If it did, it would mean a
  762. * serious bug of kernel internal. We thus always bark here.
  763. * Or, can we even panic?
  764. */
  765. log(LOG_ERR, "rtpref: impossible RA flag %x", dr->flags);
  766. return RTPREF_INVALID;
  767. }
  768. /* NOTREACHED */
  769. #else
  770. return 0;
  771. #endif
  772. }
  773. struct nd_defrouter *
  774. defrtrlist_update(struct nd_defrouter *new)
  775. {
  776. struct nd_defrouter *dr, *n;
  777. struct in6_ifextra *ext = new->ifp->if_afdata[AF_INET6];
  778. int s = splsoftnet();
  779. if ((dr = defrouter_lookup(&new->rtaddr, new->ifp)) != NULL) {
  780. /* entry exists */
  781. if (new->rtlifetime == 0) {
  782. defrtrlist_del(dr);
  783. dr = NULL;
  784. } else {
  785. int oldpref = rtpref(dr);
  786. /* override */
  787. dr->flags = new->flags; /* xxx flag check */
  788. dr->rtlifetime = new->rtlifetime;
  789. dr->expire = new->expire;
  790. if (!dr->installed)
  791. defrouter_select();
  792. /*
  793. * If the preference does not change, there's no need
  794. * to sort the entries.
  795. */
  796. if (rtpref(new) == oldpref) {
  797. splx(s);
  798. return (dr);
  799. }
  800. /*
  801. * preferred router may be changed, so relocate
  802. * this router.
  803. * XXX: calling TAILQ_REMOVE directly is a bad manner.
  804. * However, since defrtrlist_del() has many side
  805. * effects, we intentionally do so here.
  806. * defrouter_select() below will handle routing
  807. * changes later.
  808. */
  809. TAILQ_REMOVE(&nd_defrouter, dr, dr_entry);
  810. n = dr;
  811. goto insert;
  812. }
  813. splx(s);
  814. return (dr);
  815. }
  816. /* entry does not exist */
  817. if (new->rtlifetime == 0) {
  818. /* flush all possible redirects */
  819. if (new->ifp->if_xflags & IFXF_AUTOCONF6)
  820. rt6_flush(&new->rtaddr, new->ifp);
  821. splx(s);
  822. return (NULL);
  823. }
  824. if (ip6_maxifdefrouters >= 0 &&
  825. ext->ndefrouters >= ip6_maxifdefrouters) {
  826. splx(s);
  827. return (NULL);
  828. }
  829. n = malloc(sizeof(*n), M_IP6NDP, M_NOWAIT | M_ZERO);
  830. if (n == NULL) {
  831. splx(s);
  832. return (NULL);
  833. }
  834. *n = *new;
  835. insert:
  836. /*
  837. * Insert the new router in the Default Router List;
  838. * The Default Router List should be in the descending order
  839. * of router-preference. Routers with the same preference are
  840. * sorted in the arriving time order.
  841. */
  842. /* insert at the end of the group */
  843. TAILQ_FOREACH(dr, &nd_defrouter, dr_entry)
  844. if (rtpref(n) > rtpref(dr))
  845. break;
  846. if (dr)
  847. TAILQ_INSERT_BEFORE(dr, n, dr_entry);
  848. else
  849. TAILQ_INSERT_TAIL(&nd_defrouter, n, dr_entry);
  850. defrouter_select();
  851. ext->ndefrouters++;
  852. splx(s);
  853. return (n);
  854. }
  855. struct nd_pfxrouter *
  856. pfxrtr_lookup(struct nd_prefix *pr, struct nd_defrouter *dr)
  857. {
  858. struct nd_pfxrouter *search;
  859. LIST_FOREACH(search, &pr->ndpr_advrtrs, pfr_entry) {
  860. if (search->router == dr)
  861. break;
  862. }
  863. return (search);
  864. }
  865. void
  866. pfxrtr_add(struct nd_prefix *pr, struct nd_defrouter *dr)
  867. {
  868. struct nd_pfxrouter *new;
  869. new = malloc(sizeof(*new), M_IP6NDP, M_NOWAIT | M_ZERO);
  870. if (new == NULL)
  871. return;
  872. new->router = dr;
  873. LIST_INSERT_HEAD(&pr->ndpr_advrtrs, new, pfr_entry);
  874. pfxlist_onlink_check();
  875. }
  876. void
  877. pfxrtr_del(struct nd_pfxrouter *pfr)
  878. {
  879. LIST_REMOVE(pfr, pfr_entry);
  880. free(pfr, M_IP6NDP, 0);
  881. }
  882. struct nd_prefix *
  883. nd6_prefix_lookup(struct nd_prefix *pr)
  884. {
  885. struct nd_prefix *search;
  886. LIST_FOREACH(search, &nd_prefix, ndpr_entry) {
  887. if (pr->ndpr_ifp == search->ndpr_ifp &&
  888. pr->ndpr_plen == search->ndpr_plen &&
  889. in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
  890. &search->ndpr_prefix.sin6_addr, pr->ndpr_plen)) {
  891. break;
  892. }
  893. }
  894. return (search);
  895. }
  896. void
  897. purge_detached(struct ifnet *ifp)
  898. {
  899. struct nd_prefix *pr, *pr_next;
  900. struct in6_ifaddr *ia6;
  901. struct ifaddr *ifa, *ifa_next;
  902. splsoftassert(IPL_SOFTNET);
  903. LIST_FOREACH_SAFE(pr, &nd_prefix, ndpr_entry, pr_next) {
  904. /*
  905. * This function is called when we need to make more room for
  906. * new prefixes rather than keeping old, possibly stale ones.
  907. * Detached prefixes would be a good candidate; if all routers
  908. * that advertised the prefix expired, the prefix is also
  909. * probably stale.
  910. */
  911. if (pr->ndpr_ifp != ifp ||
  912. IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr) ||
  913. ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
  914. !LIST_EMPTY(&pr->ndpr_advrtrs)))
  915. continue;
  916. TAILQ_FOREACH_SAFE(ifa, &ifp->if_addrlist, ifa_list, ifa_next) {
  917. if (ifa->ifa_addr->sa_family != AF_INET6)
  918. continue;
  919. ia6 = ifatoia6(ifa);
  920. if ((ia6->ia6_flags & IN6_IFF_AUTOCONF) ==
  921. IN6_IFF_AUTOCONF && ia6->ia6_ndpr == pr) {
  922. in6_purgeaddr(ifa);
  923. }
  924. }
  925. }
  926. }
  927. struct nd_prefix *
  928. nd6_prefix_add(struct ifnet *ifp, struct sockaddr_in6 *addr,
  929. struct sockaddr_in6 *mask, struct in6_addrlifetime *lt, int autoconf)
  930. {
  931. struct nd_prefix pr0, *pr;
  932. int i;
  933. /*
  934. * convert mask to prefix length (prefixmask has already
  935. * been validated in in6_update_ifa().
  936. */
  937. memset(&pr0, 0, sizeof(pr0));
  938. pr0.ndpr_ifp = ifp;
  939. pr0.ndpr_plen = in6_mask2len(&mask->sin6_addr, NULL);
  940. pr0.ndpr_prefix = *addr;
  941. pr0.ndpr_mask = mask->sin6_addr;
  942. /* apply the mask for safety. */
  943. for (i = 0; i < 4; i++) {
  944. pr0.ndpr_prefix.sin6_addr.s6_addr32[i] &=
  945. mask->sin6_addr.s6_addr32[i];
  946. }
  947. /*
  948. * XXX: since we don't have an API to set prefix (not address)
  949. * lifetimes, we just use the same lifetimes as addresses.
  950. * The (temporarily) installed lifetimes can be overridden by
  951. * later advertised RAs (when accept_rtadv is non 0), which is
  952. * an intended behavior.
  953. */
  954. pr0.ndpr_raf_onlink = 1; /* should be configurable? */
  955. pr0.ndpr_raf_auto = autoconf;
  956. pr0.ndpr_vltime = lt->ia6t_vltime;
  957. pr0.ndpr_pltime = lt->ia6t_pltime;
  958. /* add the prefix if not yet. */
  959. if ((pr = nd6_prefix_lookup(&pr0)) == NULL) {
  960. /*
  961. * nd6_prelist_add will install the corresponding
  962. * interface route.
  963. */
  964. if (nd6_prelist_add(&pr0, NULL, &pr) != 0)
  965. return (NULL);
  966. }
  967. return (pr);
  968. }
  969. int
  970. nd6_prelist_add(struct nd_prefix *pr, struct nd_defrouter *dr,
  971. struct nd_prefix **newp)
  972. {
  973. struct nd_prefix *new = NULL;
  974. int i, s;
  975. struct in6_ifextra *ext = pr->ndpr_ifp->if_afdata[AF_INET6];
  976. if (ip6_maxifprefixes >= 0) {
  977. if (ext->nprefixes >= ip6_maxifprefixes / 2) {
  978. s = splsoftnet();
  979. purge_detached(pr->ndpr_ifp);
  980. splx(s);
  981. }
  982. if (ext->nprefixes >= ip6_maxifprefixes)
  983. return(ENOMEM);
  984. }
  985. new = malloc(sizeof(*new), M_IP6NDP, M_NOWAIT | M_ZERO);
  986. if (new == NULL)
  987. return ENOMEM;
  988. *new = *pr;
  989. if (newp != NULL)
  990. *newp = new;
  991. /* initialization */
  992. LIST_INIT(&new->ndpr_advrtrs);
  993. in6_prefixlen2mask(&new->ndpr_mask, new->ndpr_plen);
  994. /* make prefix in the canonical form */
  995. for (i = 0; i < 4; i++)
  996. new->ndpr_prefix.sin6_addr.s6_addr32[i] &=
  997. new->ndpr_mask.s6_addr32[i];
  998. task_set(&new->ndpr_task, nd6_addr_add, new);
  999. s = splsoftnet();
  1000. /* link ndpr_entry to nd_prefix list */
  1001. LIST_INSERT_HEAD(&nd_prefix, new, ndpr_entry);
  1002. /* ND_OPT_PI_FLAG_ONLINK processing */
  1003. if (new->ndpr_raf_onlink) {
  1004. char addr[INET6_ADDRSTRLEN];
  1005. int e;
  1006. if ((e = nd6_prefix_onlink(new)) != 0) {
  1007. nd6log((LOG_ERR, "nd6_prelist_add: failed to make "
  1008. "the prefix %s/%d on-link on %s (errno=%d)\n",
  1009. inet_ntop(AF_INET6, &pr->ndpr_prefix.sin6_addr,
  1010. addr, sizeof(addr)),
  1011. pr->ndpr_plen, pr->ndpr_ifp->if_xname, e));
  1012. /* proceed anyway. XXX: is it correct? */
  1013. }
  1014. }
  1015. if (dr)
  1016. pfxrtr_add(new, dr);
  1017. splx(s);
  1018. ext->nprefixes++;
  1019. return 0;
  1020. }
  1021. void
  1022. prelist_remove(struct nd_prefix *pr)
  1023. {
  1024. struct nd_pfxrouter *pfr, *next;
  1025. int e, s;
  1026. struct in6_ifextra *ext = pr->ndpr_ifp->if_afdata[AF_INET6];
  1027. /* make sure to invalidate the prefix until it is really freed. */
  1028. pr->ndpr_vltime = 0;
  1029. pr->ndpr_pltime = 0;
  1030. #if 0
  1031. /*
  1032. * Though these flags are now meaningless, we'd rather keep the value
  1033. * not to confuse users when executing "ndp -p".
  1034. */
  1035. pr->ndpr_raf_onlink = 0;
  1036. pr->ndpr_raf_auto = 0;
  1037. #endif
  1038. if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0 &&
  1039. (e = nd6_prefix_offlink(pr)) != 0) {
  1040. char addr[INET6_ADDRSTRLEN];
  1041. nd6log((LOG_ERR, "prelist_remove: failed to make %s/%d offlink "
  1042. "on %s, errno=%d\n",
  1043. inet_ntop(AF_INET6, &pr->ndpr_prefix.sin6_addr,
  1044. addr, sizeof(addr)),
  1045. pr->ndpr_plen, pr->ndpr_ifp->if_xname, e));
  1046. /* what should we do? */
  1047. }
  1048. if (pr->ndpr_refcnt > 0)
  1049. return; /* notice here? */
  1050. s = splsoftnet();
  1051. /* unlink ndpr_entry from nd_prefix list */
  1052. LIST_REMOVE(pr, ndpr_entry);
  1053. /* free list of routers that adversed the prefix */
  1054. LIST_FOREACH_SAFE(pfr, &pr->ndpr_advrtrs, pfr_entry, next)
  1055. free(pfr, M_IP6NDP, 0);
  1056. ext->nprefixes--;
  1057. if (ext->nprefixes < 0) {
  1058. log(LOG_WARNING, "prelist_remove: negative count on %s\n",
  1059. pr->ndpr_ifp->if_xname);
  1060. }
  1061. free(pr, M_IP6NDP, 0);
  1062. pfxlist_onlink_check();
  1063. splx(s);
  1064. }
  1065. /*
  1066. * dr - may be NULL
  1067. */
  1068. int
  1069. prelist_update(struct nd_prefix *new, struct nd_defrouter *dr, struct mbuf *m)
  1070. {
  1071. struct in6_ifaddr *ia6_match = NULL;
  1072. struct ifaddr *ifa;
  1073. struct ifnet *ifp = new->ndpr_ifp;
  1074. struct nd_prefix *pr;
  1075. int s, error = 0;
  1076. int tempaddr_preferred = 0, autoconf = 0, statique = 0;
  1077. int auth;
  1078. struct in6_addrlifetime lt6_tmp;
  1079. char addr[INET6_ADDRSTRLEN];
  1080. s = splsoftnet();
  1081. auth = 0;
  1082. if (m) {
  1083. /*
  1084. * Authenticity for NA consists authentication for
  1085. * both IP header and IP datagrams, doesn't it ?
  1086. */
  1087. auth = (m->m_flags & M_AUTH);
  1088. }
  1089. if ((pr = nd6_prefix_lookup(new)) != NULL) {
  1090. /*
  1091. * nd6_prefix_lookup() ensures that pr and new have the same
  1092. * prefix on a same interface.
  1093. */
  1094. /*
  1095. * Update prefix information. Note that the on-link (L) bit
  1096. * and the autonomous (A) bit should NOT be changed from 1
  1097. * to 0.
  1098. */
  1099. if (new->ndpr_raf_onlink == 1)
  1100. pr->ndpr_raf_onlink = 1;
  1101. if (new->ndpr_raf_auto == 1)
  1102. pr->ndpr_raf_auto = 1;
  1103. if (new->ndpr_raf_onlink) {
  1104. pr->ndpr_vltime = new->ndpr_vltime;
  1105. pr->ndpr_pltime = new->ndpr_pltime;
  1106. pr->ndpr_preferred = new->ndpr_preferred;
  1107. pr->ndpr_expire = new->ndpr_expire;
  1108. pr->ndpr_lastupdate = new->ndpr_lastupdate;
  1109. }
  1110. if (new->ndpr_raf_onlink &&
  1111. (pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
  1112. int e;
  1113. if ((e = nd6_prefix_onlink(pr)) != 0) {
  1114. nd6log((LOG_ERR,
  1115. "prelist_update: failed to make "
  1116. "the prefix %s/%d on-link on %s "
  1117. "(errno=%d)\n",
  1118. inet_ntop(AF_INET6,
  1119. &pr->ndpr_prefix.sin6_addr,
  1120. addr, sizeof(addr)),
  1121. pr->ndpr_plen, pr->ndpr_ifp->if_xname, e));
  1122. /* proceed anyway. XXX: is it correct? */
  1123. }
  1124. }
  1125. if (dr && pfxrtr_lookup(pr, dr) == NULL)
  1126. pfxrtr_add(pr, dr);
  1127. } else {
  1128. struct nd_prefix *newpr = NULL;
  1129. if (new->ndpr_vltime == 0)
  1130. goto end;
  1131. if (new->ndpr_raf_onlink == 0 && new->ndpr_raf_auto == 0)
  1132. goto end;
  1133. error = nd6_prelist_add(new, dr, &newpr);
  1134. if (error != 0 || newpr == NULL) {
  1135. nd6log((LOG_NOTICE, "prelist_update: "
  1136. "nd6_prelist_add failed for %s/%d on %s "
  1137. "errno=%d, returnpr=%p\n",
  1138. inet_ntop(AF_INET6, &new->ndpr_prefix.sin6_addr,
  1139. addr, sizeof(addr)),
  1140. new->ndpr_plen, new->ndpr_ifp->if_xname,
  1141. error, newpr));
  1142. goto end; /* we should just give up in this case. */
  1143. }
  1144. /*
  1145. * XXX: from the ND point of view, we can ignore a prefix
  1146. * with the on-link bit being zero. However, we need a
  1147. * prefix structure for references from autoconfigured
  1148. * addresses. Thus, we explicitly make sure that the prefix
  1149. * itself expires now.
  1150. */
  1151. if (newpr->ndpr_raf_onlink == 0) {
  1152. newpr->ndpr_vltime = 0;
  1153. newpr->ndpr_pltime = 0;
  1154. in6_init_prefix_ltimes(newpr);
  1155. }
  1156. pr = newpr;
  1157. }
  1158. /*
  1159. * Address autoconfiguration based on Section 5.5.3 of RFC 2462.
  1160. * Note that pr must be non NULL at this point.
  1161. */
  1162. /* 5.5.3 (a). Ignore the prefix without the A bit set. */
  1163. if (!new->ndpr_raf_auto)
  1164. goto end;
  1165. /*
  1166. * 5.5.3 (b). the link-local prefix should have been ignored in
  1167. * nd6_ra_input.
  1168. */
  1169. /*
  1170. * 5.5.3 (c). Consistency check on lifetimes: pltime <= vltime.
  1171. * This should have been done in nd6_ra_input.
  1172. */
  1173. /*
  1174. * 5.5.3 (d). If the prefix advertised does not match the prefix of an
  1175. * address already in the list, and the Valid Lifetime is not 0,
  1176. * form an address. Note that even a manually configured address
  1177. * should reject autoconfiguration of a new address.
  1178. */
  1179. TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
  1180. struct in6_ifaddr *ia6;
  1181. int ifa_plen;
  1182. u_int32_t storedlifetime;
  1183. if (ifa->ifa_addr->sa_family != AF_INET6)
  1184. continue;
  1185. ia6 = ifatoia6(ifa);
  1186. /*
  1187. * Spec is not clear here, but I believe we should concentrate
  1188. * on unicast (i.e. not anycast) addresses.
  1189. * XXX: other ia6_flags? detached or duplicated?
  1190. */
  1191. if ((ia6->ia6_flags & IN6_IFF_ANYCAST) != 0)
  1192. continue;
  1193. ifa_plen = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL);
  1194. if (ifa_plen != new->ndpr_plen ||
  1195. !in6_are_prefix_equal(&ia6->ia_addr.sin6_addr,
  1196. &new->ndpr_prefix.sin6_addr, ifa_plen))
  1197. continue;
  1198. if (ia6_match == NULL) /* remember the first one */
  1199. ia6_match = ia6;
  1200. if ((ia6->ia6_flags & IN6_IFF_AUTOCONF) == 0) {
  1201. statique = 1;
  1202. continue;
  1203. }
  1204. /*
  1205. * An already autoconfigured address matched. Now that we
  1206. * are sure there is at least one matched address, we can
  1207. * proceed to 5.5.3. (e): update the lifetimes according to the
  1208. * "two hours" rule and the privacy extension.
  1209. */
  1210. #define TWOHOUR (120*60)
  1211. /*
  1212. * RFC2462 introduces the notion of StoredLifetime to the
  1213. * "two hours" rule as follows:
  1214. * the Lifetime associated with the previously autoconfigured
  1215. * address.
  1216. * Our interpretation of this definition is "the remaining
  1217. * lifetime to expiration at the evaluation time". One might
  1218. * be wondering if this interpretation is really conform to the
  1219. * RFC, because the text can read that "Lifetimes" are never
  1220. * decreased, and our definition of the "storedlifetime" below
  1221. * essentially reduces the "Valid Lifetime" advertised in the
  1222. * previous RA. But, this is due to the wording of the text,
  1223. * and our interpretation is the same as an author's intention.
  1224. * See the discussion in the IETF ipngwg ML in August 2001,
  1225. * with the Subject "StoredLifetime in RFC 2462".
  1226. */
  1227. lt6_tmp = ia6->ia6_lifetime;
  1228. /* RFC 4941 temporary addresses (privacy extension). */
  1229. if (ia6->ia6_flags & IN6_IFF_PRIVACY) {
  1230. /* Do we still have a non-deprecated address? */
  1231. if ((ia6->ia6_flags & IN6_IFF_DEPRECATED) == 0)
  1232. tempaddr_preferred = 1;
  1233. /* Don't extend lifetime for temporary addresses. */
  1234. if (new->ndpr_vltime >= lt6_tmp.ia6t_vltime)
  1235. continue;
  1236. if (new->ndpr_pltime >= lt6_tmp.ia6t_pltime)
  1237. continue;
  1238. } else if ((ia6->ia6_flags & IN6_IFF_DEPRECATED) == 0)
  1239. /* We have a regular SLAAC address. */
  1240. autoconf = 1;
  1241. if (lt6_tmp.ia6t_vltime == ND6_INFINITE_LIFETIME)
  1242. storedlifetime = ND6_INFINITE_LIFETIME;
  1243. else if (time_second - ia6->ia6_updatetime >
  1244. lt6_tmp.ia6t_vltime) {
  1245. /*
  1246. * The case of "invalid" address. We should usually
  1247. * not see this case.
  1248. */
  1249. storedlifetime = 0;
  1250. } else
  1251. storedlifetime = lt6_tmp.ia6t_vltime -
  1252. (time_second - ia6->ia6_updatetime);
  1253. if (TWOHOUR < new->ndpr_vltime ||
  1254. storedlifetime < new->ndpr_vltime) {
  1255. lt6_tmp.ia6t_vltime = new->ndpr_vltime;
  1256. } else if (storedlifetime <= TWOHOUR
  1257. #if 0
  1258. /*
  1259. * This condition is logically redundant, so we just
  1260. * omit it.
  1261. * See IPng 6712, 6717, and 6721.
  1262. */
  1263. && new->ndpr_vltime <= storedlifetime
  1264. #endif
  1265. ) {
  1266. if (auth) {
  1267. lt6_tmp.ia6t_vltime = new->ndpr_vltime;
  1268. }
  1269. } else {
  1270. /*
  1271. * new->ndpr_vltime <= TWOHOUR &&
  1272. * TWOHOUR < storedlifetime
  1273. */
  1274. lt6_tmp.ia6t_vltime = TWOHOUR;
  1275. }
  1276. /* The 2 hour rule is not imposed for preferred lifetime. */
  1277. lt6_tmp.ia6t_pltime = new->ndpr_pltime;
  1278. in6_init_address_ltimes(pr, &lt6_tmp);
  1279. ia6->ia6_lifetime = lt6_tmp;
  1280. ia6->ia6_updatetime = time_second;
  1281. }
  1282. if ((!autoconf || ((ifp->if_xflags & IFXF_INET6_NOPRIVACY) == 0 &&
  1283. !tempaddr_preferred)) &&
  1284. new->ndpr_vltime != 0 && new->ndpr_pltime != 0 &&
  1285. !((ifp->if_xflags & IFXF_INET6_NOPRIVACY) && statique)) {
  1286. /*
  1287. * There is no SLAAC address and/or there is no preferred RFC
  1288. * 4941 temporary address. And prefix lifetimes are non-zero.
  1289. * And there is no static address in the same prefix.
  1290. * Create new addresses in process context.
  1291. * Increment prefix refcount to ensure the prefix is not
  1292. * removed before the task is done.
  1293. */
  1294. pr->ndpr_refcnt++;
  1295. if (task_add(systq, &pr->ndpr_task) == 0)
  1296. pr->ndpr_refcnt--;
  1297. }
  1298. end:
  1299. splx(s);
  1300. return error;
  1301. }
  1302. void
  1303. nd6_addr_add(void *prptr)
  1304. {
  1305. struct nd_prefix *pr = (struct nd_prefix *)prptr;
  1306. struct in6_ifaddr *ia6;
  1307. struct ifaddr *ifa;
  1308. int ifa_plen, autoconf, privacy, s;
  1309. s = splsoftnet();
  1310. autoconf = 1;
  1311. privacy = (pr->ndpr_ifp->if_xflags & IFXF_INET6_NOPRIVACY) == 0;
  1312. /*
  1313. * Check again if a non-deprecated address has already
  1314. * been autoconfigured for this prefix.
  1315. */
  1316. TAILQ_FOREACH(ifa, &pr->ndpr_ifp->if_addrlist, ifa_list) {
  1317. if (ifa->ifa_addr->sa_family != AF_INET6)
  1318. continue;
  1319. ia6 = ifatoia6(ifa);
  1320. /*
  1321. * Spec is not clear here, but I believe we should concentrate
  1322. * on unicast (i.e. not anycast) addresses.
  1323. * XXX: other ia6_flags? detached or duplicated?
  1324. */
  1325. if ((ia6->ia6_flags & IN6_IFF_ANYCAST) != 0)
  1326. continue;
  1327. if ((ia6->ia6_flags & IN6_IFF_AUTOCONF) == 0)
  1328. continue;
  1329. if ((ia6->ia6_flags & IN6_IFF_DEPRECATED) != 0)
  1330. continue;
  1331. ifa_plen = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL);
  1332. if (ifa_plen == pr->ndpr_plen &&
  1333. in6_are_prefix_equal(&ia6->ia_addr.sin6_addr,
  1334. &pr->ndpr_prefix.sin6_addr, ifa_plen)) {
  1335. if ((ia6->ia6_flags & IN6_IFF_PRIVACY) == 0)
  1336. autoconf = 0;
  1337. else
  1338. privacy = 0;
  1339. if (!autoconf && !privacy)
  1340. break;
  1341. }
  1342. }
  1343. if (autoconf && (ia6 = in6_ifadd(pr, 0)) != NULL) {
  1344. ia6->ia6_ndpr = pr;
  1345. pr->ndpr_refcnt++;
  1346. } else
  1347. autoconf = 0;
  1348. if (privacy && (ia6 = in6_ifadd(pr, 1)) != NULL) {
  1349. ia6->ia6_ndpr = pr;
  1350. pr->ndpr_refcnt++;
  1351. } else
  1352. privacy = 0;
  1353. /*
  1354. * A newly added address might affect the status
  1355. * of other addresses, so we check and update it.
  1356. * XXX: what if address duplication happens?
  1357. */
  1358. if (autoconf || privacy)
  1359. pfxlist_onlink_check();
  1360. /* Decrement prefix refcount now that the task is done. */
  1361. if (--pr->ndpr_refcnt == 0)
  1362. prelist_remove(pr);
  1363. splx(s);
  1364. }
  1365. /*
  1366. * A supplement function used in the on-link detection below;
  1367. * detect if a given prefix has a (probably) reachable advertising router.
  1368. * XXX: lengthy function name...
  1369. */
  1370. struct nd_pfxrouter *
  1371. find_pfxlist_reachable_router(struct nd_prefix *pr)
  1372. {
  1373. struct nd_pfxrouter *pfxrtr;
  1374. struct rtentry *rt;
  1375. struct llinfo_nd6 *ln;
  1376. LIST_FOREACH(pfxrtr, &pr->ndpr_advrtrs, pfr_entry) {
  1377. if ((rt = nd6_lookup(&pfxrtr->router->rtaddr, 0,
  1378. pfxrtr->router->ifp, pfxrtr->router->ifp->if_rdomain)) &&
  1379. (ln = (struct llinfo_nd6 *)rt->rt_llinfo) &&
  1380. ND6_IS_LLINFO_PROBREACH(ln))
  1381. break; /* found */
  1382. }
  1383. return (pfxrtr);
  1384. }
  1385. /*
  1386. * Check if each prefix in the prefix list has at least one available router
  1387. * that advertised the prefix (a router is "available" if its neighbor cache
  1388. * entry is reachable or probably reachable).
  1389. * If the check fails, the prefix may be off-link, because, for example,
  1390. * we have moved from the network but the lifetime of the prefix has not
  1391. * expired yet. So we should not use the prefix if there is another prefix
  1392. * that has an available router.
  1393. * But, if there is no prefix that has an available router, we still regards
  1394. * all the prefixes as on-link. This is because we can't tell if all the
  1395. * routers are simply dead or if we really moved from the network and there
  1396. * is no router around us.
  1397. */
  1398. void
  1399. pfxlist_onlink_check(void)
  1400. {
  1401. struct nd_prefix *pr;
  1402. struct in6_ifaddr *ia6;
  1403. char addr[INET6_ADDRSTRLEN];
  1404. /*
  1405. * Check if there is a prefix that has a reachable advertising
  1406. * router.
  1407. */
  1408. LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
  1409. if (pr->ndpr_raf_onlink && find_pfxlist_reachable_router(pr))
  1410. break;
  1411. }
  1412. if (pr != NULL || !TAILQ_EMPTY(&nd_defrouter)) {
  1413. /*
  1414. * There is at least one prefix that has a reachable router,
  1415. * or at least a router which probably does not advertise
  1416. * any prefixes. The latter would be the case when we move
  1417. * to a new link where we have a router that does not provide
  1418. * prefixes and we configure an address by hand.
  1419. * Detach prefixes which have no reachable advertising
  1420. * router, and attach other prefixes.
  1421. */
  1422. LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
  1423. /* XXX: a link-local prefix should never be detached */
  1424. if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
  1425. continue;
  1426. /*
  1427. * we aren't interested in prefixes without the L bit
  1428. * set.
  1429. */
  1430. if (pr->ndpr_raf_onlink == 0)
  1431. continue;
  1432. if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
  1433. find_pfxlist_reachable_router(pr) == NULL)
  1434. pr->ndpr_stateflags |= NDPRF_DETACHED;
  1435. if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
  1436. find_pfxlist_reachable_router(pr) != 0)
  1437. pr->ndpr_stateflags &= ~NDPRF_DETACHED;
  1438. }
  1439. } else {
  1440. /* there is no prefix that has a reachable router */
  1441. LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
  1442. if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
  1443. continue;
  1444. if (pr->ndpr_raf_onlink == 0)
  1445. continue;
  1446. if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0)
  1447. pr->ndpr_stateflags &= ~NDPRF_DETACHED;
  1448. }
  1449. }
  1450. /*
  1451. * Remove each interface route associated with a (just) detached
  1452. * prefix, and reinstall the interface route for a (just) attached
  1453. * prefix. Note that all attempt of reinstallation does not
  1454. * necessarily success, when a same prefix is shared among multiple
  1455. * interfaces. Such cases will be handled in nd6_prefix_onlink,
  1456. * so we don't have to care about them.
  1457. */
  1458. LIST_FOREACH(pr, &nd_prefix, ndpr_entry) {
  1459. int e;
  1460. if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
  1461. continue;
  1462. if (pr->ndpr_raf_onlink == 0)
  1463. continue;
  1464. if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
  1465. (pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
  1466. if ((e = nd6_prefix_offlink(pr)) != 0) {
  1467. nd6log((LOG_ERR,
  1468. "pfxlist_onlink_check: failed to "
  1469. "make %s/%d offlink, errno=%d\n",
  1470. inet_ntop(AF_INET6,
  1471. &pr->ndpr_prefix.sin6_addr,
  1472. addr, sizeof(addr)),
  1473. pr->ndpr_plen, e));
  1474. }
  1475. }
  1476. if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
  1477. (pr->ndpr_stateflags & NDPRF_ONLINK) == 0 &&
  1478. pr->ndpr_raf_onlink) {
  1479. if ((e = nd6_prefix_onlink(pr)) != 0) {
  1480. nd6log((LOG_ERR,
  1481. "pfxlist_onlink_check: failed to "
  1482. "make %s/%d offlink, errno=%d\n",
  1483. inet_ntop(AF_INET6,
  1484. &pr->ndpr_prefix.sin6_addr,
  1485. addr, sizeof(addr)),
  1486. pr->ndpr_plen, e));
  1487. }
  1488. }
  1489. }
  1490. /*
  1491. * Changes on the prefix status might affect address status as well.
  1492. * Make sure that all addresses derived from an attached prefix are
  1493. * attached, and that all addresses derived from a detached prefix are
  1494. * detached. Note, however, that a manually configured address should
  1495. * always be attached.
  1496. * The precise detection logic is same as the one for prefixes.
  1497. */
  1498. TAILQ_FOREACH(ia6, &in6_ifaddr, ia_list) {
  1499. if (!(ia6->ia6_flags & IN6_IFF_AUTOCONF))
  1500. continue;
  1501. if (ia6->ia6_ndpr == NULL) {
  1502. /*
  1503. * This can happen when we first configure the address
  1504. * (i.e. the address exists, but the prefix does not).
  1505. * XXX: complicated relationships...
  1506. */
  1507. continue;
  1508. }
  1509. if (find_pfxlist_reachable_router(ia6->ia6_ndpr))
  1510. break;
  1511. }
  1512. if (ia6) {
  1513. TAILQ_FOREACH(ia6, &in6_ifaddr, ia_list) {
  1514. if ((ia6->ia6_flags & IN6_IFF_AUTOCONF) == 0)
  1515. continue;
  1516. if (ia6->ia6_ndpr == NULL) /* XXX: see above. */
  1517. continue;
  1518. if (find_pfxlist_reachable_router(ia6->ia6_ndpr))
  1519. ia6->ia6_flags &= ~IN6_IFF_DETACHED;
  1520. else
  1521. ia6->ia6_flags |= IN6_IFF_DETACHED;
  1522. }
  1523. }
  1524. else {
  1525. TAILQ_FOREACH(ia6, &in6_ifaddr, ia_list) {
  1526. if ((ia6->ia6_flags & IN6_IFF_AUTOCONF) == 0)
  1527. continue;
  1528. ia6->ia6_flags &= ~IN6_IFF_DETACHED;
  1529. }
  1530. }
  1531. }
  1532. int
  1533. nd6_prefix_onlink(struct nd_prefix *pr)
  1534. {
  1535. struct rt_addrinfo info;
  1536. struct ifaddr *ifa;
  1537. struct ifnet *ifp = pr->ndpr_ifp;
  1538. struct sockaddr_in6 mask6;
  1539. struct nd_prefix *opr;
  1540. u_long rtflags;
  1541. int error = 0;
  1542. struct rtentry *rt = NULL;
  1543. char addr[INET6_ADDRSTRLEN];
  1544. /* sanity check */
  1545. if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
  1546. nd6log((LOG_ERR,
  1547. "nd6_prefix_onlink: %s/%d is already on-link\n",
  1548. inet_ntop(AF_INET6, &pr->ndpr_prefix.sin6_addr,
  1549. addr, sizeof(addr)),
  1550. pr->ndpr_plen));
  1551. return (EEXIST);
  1552. }
  1553. /*
  1554. * Add the interface route associated with the prefix. Before
  1555. * installing the route, check if there's the same prefix on another
  1556. * interface, and the prefix has already installed the interface route.
  1557. * Although such a configuration is expected to be rare, we explicitly
  1558. * allow it.
  1559. */
  1560. LIST_FOREACH(opr, &nd_prefix, ndpr_entry) {
  1561. if (opr == pr)
  1562. continue;
  1563. if ((opr->ndpr_stateflags & NDPRF_ONLINK) == 0)
  1564. continue;
  1565. if (opr->ndpr_plen == pr->ndpr_plen &&
  1566. in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
  1567. &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen))
  1568. return (0);
  1569. }
  1570. /*
  1571. * We prefer link-local addresses as the associated interface address.
  1572. */
  1573. /* search for a link-local addr */
  1574. ifa = &in6ifa_ifpforlinklocal(ifp,
  1575. IN6_IFF_NOTREADY | IN6_IFF_ANYCAST)->ia_ifa;
  1576. if (ifa == NULL) {
  1577. TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
  1578. if (ifa->ifa_addr->sa_family == AF_INET6)
  1579. break;
  1580. }
  1581. /* should we care about ia6_flags? */
  1582. }
  1583. if (ifa == NULL) {
  1584. /*
  1585. * This can still happen, when, for example, we receive an RA
  1586. * containing a prefix with the L bit set and the A bit clear,
  1587. * after removing all IPv6 addresses on the receiving
  1588. * interface. This should, of course, be rare though.
  1589. */
  1590. nd6log((LOG_NOTICE,
  1591. "nd6_prefix_onlink: failed to find any ifaddr"
  1592. " to add route for a prefix(%s/%d) on %s\n",
  1593. inet_ntop(AF_INET6, &pr->ndpr_prefix.sin6_addr,
  1594. addr, sizeof(addr)),
  1595. pr->ndpr_plen, ifp->if_xname));
  1596. return (0);
  1597. }
  1598. /*
  1599. * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
  1600. * ifa->ifa_rtrequest = nd6_rtrequest;
  1601. */
  1602. bzero(&mask6, sizeof(mask6));
  1603. mask6.sin6_len = sizeof(mask6);
  1604. mask6.sin6_addr = pr->ndpr_mask;
  1605. if (nd6_need_cache(ifp))
  1606. rtflags = (RTF_UP | RTF_CLONING | RTF_CONNECTED);
  1607. else
  1608. rtflags = RTF_UP;
  1609. bzero(&info, sizeof(info));
  1610. info.rti_flags = rtflags;
  1611. info.rti_info[RTAX_DST] = sin6tosa(&pr->ndpr_prefix);
  1612. info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
  1613. info.rti_info[RTAX_NETMASK] = sin6tosa(&mask6);
  1614. error = rtrequest1(RTM_ADD, &info, RTP_CONNECTED, &rt, ifp->if_rdomain);
  1615. if (error == 0) {
  1616. if (rt != NULL) /* this should be non NULL, though */
  1617. rt_sendmsg(rt, RTM_ADD, ifp->if_rdomain);
  1618. pr->ndpr_stateflags |= NDPRF_ONLINK;
  1619. } else {
  1620. char gw[INET6_ADDRSTRLEN], mask[INET6_ADDRSTRLEN];
  1621. nd6log((LOG_ERR, "nd6_prefix_onlink: failed to add route for a"
  1622. " prefix (%s/%d) on %s, gw=%s, mask=%s, flags=%lx "
  1623. "errno = %d\n",
  1624. inet_ntop(AF_INET6, &pr->ndpr_prefix.sin6_addr,
  1625. addr, sizeof(addr)),
  1626. pr->ndpr_plen, ifp->if_xname,
  1627. inet_ntop(AF_INET6, &satosin6(ifa->ifa_addr)->sin6_addr,
  1628. gw, sizeof(gw)),
  1629. inet_ntop(AF_INET6, &mask6.sin6_addr, mask, sizeof(mask)),
  1630. rtflags, error));
  1631. }
  1632. if (rt != NULL)
  1633. rt->rt_refcnt--;
  1634. return (error);
  1635. }
  1636. int
  1637. nd6_prefix_offlink(struct nd_prefix *pr)
  1638. {
  1639. struct rt_addrinfo info;
  1640. int error = 0;
  1641. struct ifnet *ifp = pr->ndpr_ifp;
  1642. struct nd_prefix *opr;
  1643. struct sockaddr_in6 sa6, mask6;
  1644. struct rtentry *rt = NULL;
  1645. char addr[INET6_ADDRSTRLEN];
  1646. /* sanity check */
  1647. if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
  1648. nd6log((LOG_ERR,
  1649. "nd6_prefix_offlink: %s/%d is already off-link\n",
  1650. inet_ntop(AF_INET6, &pr->ndpr_prefix.sin6_addr,
  1651. addr, sizeof(addr)),
  1652. pr->ndpr_plen));
  1653. return (EEXIST);
  1654. }
  1655. bzero(&sa6, sizeof(sa6));
  1656. sa6.sin6_family = AF_INET6;
  1657. sa6.sin6_len = sizeof(sa6);
  1658. bcopy(&pr->ndpr_prefix.sin6_addr, &sa6.sin6_addr,
  1659. sizeof(struct in6_addr));
  1660. bzero(&mask6, sizeof(mask6));
  1661. mask6.sin6_family = AF_INET6;
  1662. mask6.sin6_len = sizeof(sa6);
  1663. bcopy(&pr->ndpr_mask, &mask6.sin6_addr, sizeof(struct in6_addr));
  1664. bzero(&info, sizeof(info));
  1665. info.rti_info[RTAX_DST] = sin6tosa(&sa6);
  1666. info.rti_info[RTAX_NETMASK] = sin6tosa(&mask6);
  1667. error = rtrequest1(RTM_DELETE, &info, RTP_CONNECTED, &rt,
  1668. ifp->if_rdomain);
  1669. if (error == 0) {
  1670. pr->ndpr_stateflags &= ~NDPRF_ONLINK;
  1671. /* report the route deletion to the routing socket. */
  1672. if (rt != NULL)
  1673. rt_sendmsg(rt, RTM_DELETE, ifp->if_rdomain);
  1674. /*
  1675. * There might be the same prefix on another interface,
  1676. * the prefix which could not be on-link just because we have
  1677. * the interface route (see comments in nd6_prefix_onlink).
  1678. * If there's one, try to make the prefix on-link on the
  1679. * interface.
  1680. */
  1681. LIST_FOREACH(opr, &nd_prefix, ndpr_entry) {
  1682. if (opr == pr)
  1683. continue;
  1684. if ((opr->ndpr_stateflags & NDPRF_ONLINK) != 0)
  1685. continue;
  1686. /*
  1687. * KAME specific: detached prefixes should not be
  1688. * on-link.
  1689. */
  1690. if ((opr->ndpr_stateflags & NDPRF_DETACHED) != 0)
  1691. continue;
  1692. if (opr->ndpr_plen == pr->ndpr_plen &&
  1693. in6_are_prefix_equal(&pr->ndpr_prefix.sin6_addr,
  1694. &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen)) {
  1695. int e;
  1696. if ((e = nd6_prefix_onlink(opr)) != 0) {
  1697. nd6log((LOG_ERR,
  1698. "nd6_prefix_offlink: failed to "
  1699. "recover a prefix %s/%d from %s "
  1700. "to %s (errno = %d)\n",
  1701. inet_ntop(AF_INET6,
  1702. &pr->ndpr_prefix.sin6_addr,
  1703. addr, sizeof(addr)),
  1704. opr->ndpr_plen, ifp->if_xname,
  1705. opr->ndpr_ifp->if_xname, e));
  1706. }
  1707. }
  1708. }
  1709. } else {
  1710. /* XXX: can we still set the NDPRF_ONLINK flag? */
  1711. nd6log((LOG_ERR,
  1712. "nd6_prefix_offlink: failed to delete route: "
  1713. "%s/%d on %s (errno = %d)\n",
  1714. inet_ntop(AF_INET6, &sa6.sin6_addr, addr, sizeof(addr)),
  1715. pr->ndpr_plen, ifp->if_xname, error));
  1716. }
  1717. if (rt != NULL) {
  1718. if (rt->rt_refcnt <= 0) {
  1719. /* XXX: we should free the entry ourselves. */
  1720. rt->rt_refcnt++;
  1721. rtfree(rt);
  1722. }
  1723. }
  1724. return (error);
  1725. }
  1726. struct in6_ifaddr *
  1727. in6_ifadd(struct nd_prefix *pr, int privacy)
  1728. {
  1729. struct ifnet *ifp = pr->ndpr_ifp;
  1730. struct ifaddr *ifa;
  1731. struct in6_aliasreq ifra;
  1732. struct in6_ifaddr *ia6;
  1733. int error, s, plen0;
  1734. struct in6_addr mask, rand_ifid;
  1735. int prefixlen = pr->ndpr_plen;
  1736. in6_prefixlen2mask(&mask, prefixlen);
  1737. /*
  1738. * find a link-local address (will be interface ID).
  1739. * Is it really mandatory? Theoretically, a global or a site-local
  1740. * address can be configured without a link-local address, if we
  1741. * have a unique interface identifier...
  1742. *
  1743. * it is not mandatory to have a link-local address, we can generate
  1744. * interface identifier on the fly. we do this because:
  1745. * (1) it should be the easiest way to find interface identifier.
  1746. * (2) RFC2462 5.4 suggesting the use of the same interface identifier
  1747. * for multiple addresses on a single interface, and possible shortcut
  1748. * of DAD. we omitted DAD for this reason in the past.
  1749. * (3) a user can prevent autoconfiguration of global address
  1750. * by removing link-local address by hand (this is partly because we
  1751. * don't have other way to control the use of IPv6 on a interface.
  1752. * this has been our design choice - cf. NRL's "ifconfig auto").
  1753. * (4) it is easier to manage when an interface has addresses
  1754. * with the same interface identifier, than to have multiple addresses
  1755. * with different interface identifiers.
  1756. */
  1757. ifa = &in6ifa_ifpforlinklocal(ifp, 0)->ia_ifa; /* 0 is OK? */
  1758. if (ifa)
  1759. ia6 = ifatoia6(ifa);
  1760. else
  1761. return NULL;
  1762. #if 0 /* don't care link local addr state, and always do DAD */
  1763. /* if link-local address is not eligible, do not autoconfigure. */
  1764. if (ifatoia6(ifa)->ia6_flags & IN6_IFF_NOTREADY) {
  1765. printf("in6_ifadd: link-local address not ready\n");
  1766. return NULL;
  1767. }
  1768. #endif
  1769. /* prefixlen + ifidlen must be equal to 128 */
  1770. plen0 = in6_mask2len(&ia6->ia_prefixmask.sin6_addr, NULL);
  1771. if (prefixlen != plen0) {
  1772. nd6log((LOG_INFO, "in6_ifadd: wrong prefixlen for %s "
  1773. "(prefix=%d ifid=%d)\n",
  1774. ifp->if_xname, prefixlen, 128 - plen0));
  1775. return NULL;
  1776. }
  1777. /* make ifaddr */
  1778. bzero(&ifra, sizeof(ifra));
  1779. /*
  1780. * in6_update_ifa() does not use ifra_name, but we accurately set it
  1781. * for safety.
  1782. */
  1783. strncpy(ifra.ifra_name, ifp->if_xname, sizeof(ifra.ifra_name));
  1784. ifra.ifra_addr.sin6_family = AF_INET6;
  1785. ifra.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
  1786. /* prefix */
  1787. bcopy(&pr->ndpr_prefix.sin6_addr, &ifra.ifra_addr.sin6_addr,
  1788. sizeof(ifra.ifra_addr.sin6_addr));
  1789. ifra.ifra_addr.sin6_addr.s6_addr32[0] &= mask.s6_addr32[0];
  1790. ifra.ifra_addr.sin6_addr.s6_addr32[1] &= mask.s6_addr32[1];
  1791. ifra.ifra_addr.sin6_addr.s6_addr32[2] &= mask.s6_addr32[2];
  1792. ifra.ifra_addr.sin6_addr.s6_addr32[3] &= mask.s6_addr32[3];
  1793. /* interface ID */
  1794. if (privacy) {
  1795. ifra.ifra_flags |= IN6_IFF_PRIVACY;
  1796. bcopy(&pr->ndpr_prefix.sin6_addr, &rand_ifid,
  1797. sizeof(rand_ifid));
  1798. in6_get_rand_ifid(ifp, &rand_ifid);
  1799. ifra.ifra_addr.sin6_addr.s6_addr32[0] |=
  1800. (rand_ifid.s6_addr32[0] & ~mask.s6_addr32[0]);
  1801. ifra.ifra_addr.sin6_addr.s6_addr32[1] |=
  1802. (rand_ifid.s6_addr32[1] & ~mask.s6_addr32[1]);
  1803. ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
  1804. (rand_ifid.s6_addr32[2] & ~mask.s6_addr32[2]);
  1805. ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
  1806. (rand_ifid.s6_addr32[3] & ~mask.s6_addr32[3]);
  1807. } else {
  1808. ifra.ifra_addr.sin6_addr.s6_addr32[0] |=
  1809. (ia6->ia_addr.sin6_addr.s6_addr32[0] & ~mask.s6_addr32[0]);
  1810. ifra.ifra_addr.sin6_addr.s6_addr32[1] |=
  1811. (ia6->ia_addr.sin6_addr.s6_addr32[1] & ~mask.s6_addr32[1]);
  1812. ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
  1813. (ia6->ia_addr.sin6_addr.s6_addr32[2] & ~mask.s6_addr32[2]);
  1814. ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
  1815. (ia6->ia_addr.sin6_addr.s6_addr32[3] & ~mask.s6_addr32[3]);
  1816. }
  1817. /* new prefix mask. */
  1818. ifra.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
  1819. ifra.ifra_prefixmask.sin6_family = AF_INET6;
  1820. bcopy(&mask, &ifra.ifra_prefixmask.sin6_addr,
  1821. sizeof(ifra.ifra_prefixmask.sin6_addr));
  1822. /*
  1823. * lifetime.
  1824. * XXX: in6_init_address_ltimes would override these values later.
  1825. * We should reconsider this logic.
  1826. */
  1827. ifra.ifra_lifetime.ia6t_vltime = pr->ndpr_vltime;
  1828. ifra.ifra_lifetime.ia6t_pltime = pr->ndpr_pltime;
  1829. if (privacy) {
  1830. if (ifra.ifra_lifetime.ia6t_vltime > ND6_PRIV_VALID_LIFETIME)
  1831. ifra.ifra_lifetime.ia6t_vltime = ND6_PRIV_VALID_LIFETIME;
  1832. if (ifra.ifra_lifetime.ia6t_pltime > ND6_PRIV_PREFERRED_LIFETIME)
  1833. ifra.ifra_lifetime.ia6t_pltime = ND6_PRIV_PREFERRED_LIFETIME
  1834. - (arc4random() % ND6_PRIV_MAX_DESYNC_FACTOR);
  1835. }
  1836. /* XXX: scope zone ID? */
  1837. ifra.ifra_flags |= IN6_IFF_AUTOCONF; /* obey autoconf */
  1838. /* allocate ifaddr structure, link into chain, etc. */
  1839. s = splsoftnet();
  1840. error = in6_update_ifa(ifp, &ifra, NULL);
  1841. splx(s);
  1842. if (error != 0) {
  1843. char addr[INET6_ADDRSTRLEN];
  1844. nd6log((LOG_ERR,
  1845. "in6_ifadd: failed to make ifaddr %s on %s (errno=%d)\n",
  1846. inet_ntop(AF_INET6, &ifra.ifra_addr.sin6_addr,
  1847. addr, sizeof(addr)),
  1848. ifp->if_xname, error));
  1849. return (NULL); /* ifaddr must not have been allocated. */
  1850. }
  1851. /* this is always non-NULL */
  1852. return (in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr));
  1853. }
  1854. int
  1855. in6_init_prefix_ltimes(struct nd_prefix *ndpr)
  1856. {
  1857. /* check if preferred lifetime > valid lifetime. RFC2462 5.5.3 (c) */
  1858. if (ndpr->ndpr_pltime > ndpr->ndpr_vltime) {
  1859. nd6log((LOG_INFO, "in6_init_prefix_ltimes: preferred lifetime"
  1860. "(%d) is greater than valid lifetime(%d)\n",
  1861. (u_int)ndpr->ndpr_pltime, (u_int)ndpr->ndpr_vltime));
  1862. return (EINVAL);
  1863. }
  1864. if (ndpr->ndpr_pltime == ND6_INFINITE_LIFETIME)
  1865. ndpr->ndpr_preferred = 0;
  1866. else
  1867. ndpr->ndpr_preferred = time_second + ndpr->ndpr_pltime;
  1868. if (ndpr->ndpr_vltime == ND6_INFINITE_LIFETIME)
  1869. ndpr->ndpr_expire = 0;
  1870. else
  1871. ndpr->ndpr_expire = time_second + ndpr->ndpr_vltime;
  1872. return 0;
  1873. }
  1874. void
  1875. in6_init_address_ltimes(struct nd_prefix *new, struct in6_addrlifetime *lt6)
  1876. {
  1877. /* Valid lifetime must not be updated unless explicitly specified. */
  1878. /* init ia6t_expire */
  1879. if (lt6->ia6t_vltime == ND6_INFINITE_LIFETIME)
  1880. lt6->ia6t_expire = 0;
  1881. else {
  1882. lt6->ia6t_expire = time_second;
  1883. lt6->ia6t_expire += lt6->ia6t_vltime;
  1884. }
  1885. /* init ia6t_preferred */
  1886. if (lt6->ia6t_pltime == ND6_INFINITE_LIFETIME)
  1887. lt6->ia6t_preferred = 0;
  1888. else {
  1889. lt6->ia6t_preferred = time_second;
  1890. lt6->ia6t_preferred += lt6->ia6t_pltime;
  1891. }
  1892. }
  1893. /*
  1894. * Delete all the routing table entries that use the specified gateway.
  1895. * XXX: this function causes search through all entries of routing table, so
  1896. * it shouldn't be called when acting as a router.
  1897. */
  1898. void
  1899. rt6_flush(struct in6_addr *gateway, struct ifnet *ifp)
  1900. {
  1901. int s;
  1902. /* We'll care only link-local addresses */
  1903. if (!IN6_IS_ADDR_LINKLOCAL(gateway))
  1904. return;
  1905. /* XXX: hack for KAME's link-local address kludge */
  1906. gateway->s6_addr16[1] = htons(ifp->if_index);
  1907. s = splsoftnet();
  1908. rtable_walk(ifp->if_rdomain, AF_INET6, rt6_deleteroute, gateway);
  1909. splx(s);
  1910. }
  1911. int
  1912. rt6_deleteroute(struct rtentry *rt, void *arg, unsigned int id)
  1913. {
  1914. struct rt_addrinfo info;
  1915. struct in6_addr *gate = (struct in6_addr *)arg;
  1916. if (rt->rt_gateway == NULL || rt->rt_gateway->sa_family != AF_INET6)
  1917. return (0);
  1918. if (!IN6_ARE_ADDR_EQUAL(gate, &satosin6(rt->rt_gateway)->sin6_addr))
  1919. return (0);
  1920. /*
  1921. * Do not delete a static route.
  1922. * XXX: this seems to be a bit ad-hoc. Should we consider the
  1923. * 'cloned' bit instead?
  1924. */
  1925. if ((rt->rt_flags & RTF_STATIC) != 0)
  1926. return (0);
  1927. /*
  1928. * We delete only host route. This means, in particular, we don't
  1929. * delete default route.
  1930. */
  1931. if ((rt->rt_flags & RTF_HOST) == 0)
  1932. return (0);
  1933. bzero(&info, sizeof(info));
  1934. info.rti_flags = rt->rt_flags;
  1935. info.rti_info[RTAX_DST] = rt_key(rt);
  1936. info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
  1937. info.rti_info[RTAX_NETMASK] = rt_mask(rt);
  1938. return (rtrequest1(RTM_DELETE, &info, RTP_ANY, NULL, id));
  1939. }