in6_src.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. /* $OpenBSD: in6_src.c,v 1.51 2015/06/08 22:19:28 krw Exp $ */
  2. /* $KAME: in6_src.c,v 1.36 2001/02/06 04:08:17 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. /*
  32. * Copyright (c) 1982, 1986, 1991, 1993
  33. * The Regents of the University of California. All rights reserved.
  34. *
  35. * Redistribution and use in source and binary forms, with or without
  36. * modification, are permitted provided that the following conditions
  37. * are met:
  38. * 1. Redistributions of source code must retain the above copyright
  39. * notice, this list of conditions and the following disclaimer.
  40. * 2. Redistributions in binary form must reproduce the above copyright
  41. * notice, this list of conditions and the following disclaimer in the
  42. * documentation and/or other materials provided with the distribution.
  43. * 3. Neither the name of the University nor the names of its contributors
  44. * may be used to endorse or promote products derived from this software
  45. * without specific prior written permission.
  46. *
  47. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  48. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  49. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  50. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  51. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  52. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  53. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  54. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  55. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  56. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  57. * SUCH DAMAGE.
  58. *
  59. * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94
  60. */
  61. #include <sys/param.h>
  62. #include <sys/systm.h>
  63. #include <sys/mbuf.h>
  64. #include <sys/protosw.h>
  65. #include <sys/socket.h>
  66. #include <sys/socketvar.h>
  67. #include <sys/ioctl.h>
  68. #include <sys/errno.h>
  69. #include <sys/time.h>
  70. #include <net/if.h>
  71. #include <net/if_var.h>
  72. #include <net/route.h>
  73. #include <netinet/in.h>
  74. #include <netinet/ip.h>
  75. #include <netinet/in_pcb.h>
  76. #include <netinet6/in6_var.h>
  77. #include <netinet/ip6.h>
  78. #include <netinet6/ip6_var.h>
  79. #include <netinet6/nd6.h>
  80. int in6_selectif(struct sockaddr_in6 *, struct ip6_pktopts *,
  81. struct ip6_moptions *, struct route_in6 *, struct ifnet **, u_int);
  82. int selectroute(struct sockaddr_in6 *, struct ip6_pktopts *,
  83. struct ip6_moptions *, struct route_in6 *, struct ifnet **,
  84. struct rtentry **, int, u_int);
  85. /*
  86. * Return an IPv6 address, which is the most appropriate for a given
  87. * destination and user specified options.
  88. * If necessary, this function lookups the routing table and returns
  89. * an entry to the caller for later use.
  90. */
  91. int
  92. in6_selectsrc(struct in6_addr **in6src, struct sockaddr_in6 *dstsock,
  93. struct ip6_pktopts *opts, struct ip6_moptions *mopts,
  94. struct route_in6 *ro, struct in6_addr *laddr, u_int rtableid)
  95. {
  96. struct ifnet *ifp = NULL;
  97. struct in6_addr *dst;
  98. struct in6_ifaddr *ia6 = NULL;
  99. struct in6_pktinfo *pi = NULL;
  100. int error;
  101. dst = &dstsock->sin6_addr;
  102. /*
  103. * If the source address is explicitly specified by the caller,
  104. * check if the requested source address is indeed a unicast address
  105. * assigned to the node, and can be used as the packet's source
  106. * address. If everything is okay, use the address as source.
  107. */
  108. if (opts && (pi = opts->ip6po_pktinfo) &&
  109. !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) {
  110. struct sockaddr_in6 sa6;
  111. /* get the outgoing interface */
  112. error = in6_selectif(dstsock, opts, mopts, ro, &ifp, rtableid);
  113. if (error)
  114. return (error);
  115. bzero(&sa6, sizeof(sa6));
  116. sa6.sin6_family = AF_INET6;
  117. sa6.sin6_len = sizeof(sa6);
  118. sa6.sin6_addr = pi->ipi6_addr;
  119. if (ifp && IN6_IS_SCOPE_EMBED(&sa6.sin6_addr))
  120. sa6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
  121. ia6 = ifatoia6(ifa_ifwithaddr(sin6tosa(&sa6), rtableid));
  122. if (ia6 == NULL ||
  123. (ia6->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY)))
  124. return (EADDRNOTAVAIL);
  125. pi->ipi6_addr = sa6.sin6_addr; /* XXX: this overrides pi */
  126. *in6src = &pi->ipi6_addr;
  127. return (0);
  128. }
  129. /*
  130. * If the source address is not specified but the socket(if any)
  131. * is already bound, use the bound address.
  132. */
  133. if (laddr && !IN6_IS_ADDR_UNSPECIFIED(laddr)) {
  134. *in6src = laddr;
  135. return (0);
  136. }
  137. /*
  138. * If the caller doesn't specify the source address but
  139. * the outgoing interface, use an address associated with
  140. * the interface.
  141. */
  142. if (pi && pi->ipi6_ifindex) {
  143. ifp = if_get(pi->ipi6_ifindex);
  144. if (ifp == NULL)
  145. return (ENXIO); /* XXX: better error? */
  146. ia6 = in6_ifawithscope(ifp, dst, rtableid);
  147. if (ia6 == NULL)
  148. return (EADDRNOTAVAIL);
  149. *in6src = &ia6->ia_addr.sin6_addr;
  150. return (0);
  151. }
  152. /*
  153. * If the destination address is a link-local unicast address or
  154. * a link/interface-local multicast address, and if the outgoing
  155. * interface is specified by the sin6_scope_id filed, use an address
  156. * associated with the interface.
  157. * XXX: We're now trying to define more specific semantics of
  158. * sin6_scope_id field, so this part will be rewritten in
  159. * the near future.
  160. */
  161. if ((IN6_IS_ADDR_LINKLOCAL(dst) || IN6_IS_ADDR_MC_LINKLOCAL(dst) ||
  162. IN6_IS_ADDR_MC_INTFACELOCAL(dst)) && dstsock->sin6_scope_id) {
  163. ifp = if_get(dstsock->sin6_scope_id);
  164. if (ifp == NULL)
  165. return (ENXIO); /* XXX: better error? */
  166. ia6 = in6_ifawithscope(ifp, dst, rtableid);
  167. if (ia6 == NULL)
  168. return (EADDRNOTAVAIL);
  169. *in6src = &ia6->ia_addr.sin6_addr;
  170. return (0);
  171. }
  172. /*
  173. * If the destination address is a multicast address and
  174. * the outgoing interface for the address is specified
  175. * by the caller, use an address associated with the interface.
  176. * Even if the outgoing interface is not specified, we also
  177. * choose a loopback interface as the outgoing interface.
  178. */
  179. if (IN6_IS_ADDR_MULTICAST(dst)) {
  180. ifp = mopts ? if_get(mopts->im6o_ifidx) : NULL;
  181. if (!ifp && dstsock->sin6_scope_id)
  182. ifp = if_get(htons(dstsock->sin6_scope_id));
  183. if (ifp) {
  184. ia6 = in6_ifawithscope(ifp, dst, rtableid);
  185. if (ia6 == NULL)
  186. return (EADDRNOTAVAIL);
  187. *in6src = &ia6->ia_addr.sin6_addr;
  188. return (0);
  189. }
  190. }
  191. /*
  192. * If the next hop address for the packet is specified
  193. * by caller, use an address associated with the route
  194. * to the next hop.
  195. */
  196. {
  197. struct sockaddr_in6 *sin6_next;
  198. struct rtentry *rt;
  199. if (opts && opts->ip6po_nexthop) {
  200. sin6_next = satosin6(opts->ip6po_nexthop);
  201. rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL,
  202. rtableid);
  203. if (rt) {
  204. ia6 = in6_ifawithscope(rt->rt_ifp, dst,
  205. rtableid);
  206. if (ia6 == NULL)
  207. ia6 = ifatoia6(rt->rt_ifa);
  208. }
  209. if (ia6 == NULL)
  210. return (EADDRNOTAVAIL);
  211. *in6src = &ia6->ia_addr.sin6_addr;
  212. return (0);
  213. }
  214. }
  215. /*
  216. * If route is known or can be allocated now,
  217. * our src addr is taken from the i/f, else punt.
  218. */
  219. if (ro) {
  220. if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
  221. !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst))) {
  222. rtfree(ro->ro_rt);
  223. ro->ro_rt = NULL;
  224. }
  225. if (ro->ro_rt == (struct rtentry *)0 ||
  226. ro->ro_rt->rt_ifp == (struct ifnet *)0) {
  227. struct sockaddr_in6 *sa6;
  228. /* No route yet, so try to acquire one */
  229. bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
  230. ro->ro_tableid = rtableid;
  231. sa6 = &ro->ro_dst;
  232. sa6->sin6_family = AF_INET6;
  233. sa6->sin6_len = sizeof(struct sockaddr_in6);
  234. sa6->sin6_addr = *dst;
  235. sa6->sin6_scope_id = dstsock->sin6_scope_id;
  236. if (IN6_IS_ADDR_MULTICAST(dst)) {
  237. ro->ro_rt = rtalloc(sin6tosa(&ro->ro_dst),
  238. RT_REPORT|RT_RESOLVE, ro->ro_tableid);
  239. } else {
  240. ro->ro_rt = rtalloc_mpath(sin6tosa(&ro->ro_dst),
  241. NULL, ro->ro_tableid);
  242. }
  243. }
  244. /*
  245. * in_pcbconnect() checks out IFF_LOOPBACK to skip using
  246. * the address. But we don't know why it does so.
  247. * It is necessary to ensure the scope even for lo0
  248. * so doesn't check out IFF_LOOPBACK.
  249. */
  250. if (ro->ro_rt) {
  251. ia6 = in6_ifawithscope(ro->ro_rt->rt_ifa->ifa_ifp, dst,
  252. rtableid);
  253. if (ia6 == NULL) /* xxx scope error ?*/
  254. ia6 = ifatoia6(ro->ro_rt->rt_ifa);
  255. }
  256. if (ia6 == NULL)
  257. return (EHOSTUNREACH); /* no route */
  258. *in6src = &ia6->ia_addr.sin6_addr;
  259. return (0);
  260. }
  261. return (EADDRNOTAVAIL);
  262. }
  263. int
  264. selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
  265. struct ip6_moptions *mopts, struct route_in6 *ro, struct ifnet **retifp,
  266. struct rtentry **retrt, int norouteok, u_int rtableid)
  267. {
  268. int error = 0;
  269. struct ifnet *ifp = NULL;
  270. struct rtentry *rt = NULL;
  271. struct sockaddr_in6 *sin6_next;
  272. struct in6_pktinfo *pi = NULL;
  273. struct in6_addr *dst;
  274. dst = &dstsock->sin6_addr;
  275. #if 0
  276. char ip[INET6_ADDRSTRLEN];
  277. if (dstsock->sin6_addr.s6_addr32[0] == 0 &&
  278. dstsock->sin6_addr.s6_addr32[1] == 0 &&
  279. !IN6_IS_ADDR_LOOPBACK(&dstsock->sin6_addr)) {
  280. printf("in6_selectroute: strange destination %s\n",
  281. inet_ntop(AF_INET6, &dstsock->sin6_addr, ip, sizeof(ip)));
  282. } else {
  283. printf("in6_selectroute: destination = %s%%%d\n",
  284. inet_ntop(AF_INET6, &dstsock->sin6_addr, ip, sizeof(ip)),
  285. dstsock->sin6_scope_id); /* for debug */
  286. }
  287. #endif
  288. /* If the caller specify the outgoing interface explicitly, use it. */
  289. if (opts && (pi = opts->ip6po_pktinfo) != NULL && pi->ipi6_ifindex) {
  290. ifp = if_get(pi->ipi6_ifindex);
  291. if (ifp != NULL &&
  292. (norouteok || retrt == NULL ||
  293. IN6_IS_ADDR_MULTICAST(dst))) {
  294. /*
  295. * we do not have to check or get the route for
  296. * multicast.
  297. */
  298. goto done;
  299. } else
  300. goto getroute;
  301. }
  302. /*
  303. * If the destination address is a multicast address and the outgoing
  304. * interface for the address is specified by the caller, use it.
  305. */
  306. if (IN6_IS_ADDR_MULTICAST(dst) &&
  307. mopts != NULL && (ifp = if_get(mopts->im6o_ifidx)) != NULL) {
  308. goto done; /* we do not need a route for multicast. */
  309. }
  310. getroute:
  311. /*
  312. * If the next hop address for the packet is specified by the caller,
  313. * use it as the gateway.
  314. */
  315. if (opts && opts->ip6po_nexthop) {
  316. struct route_in6 *ron;
  317. sin6_next = satosin6(opts->ip6po_nexthop);
  318. /* at this moment, we only support AF_INET6 next hops */
  319. if (sin6_next->sin6_family != AF_INET6) {
  320. error = EAFNOSUPPORT; /* or should we proceed? */
  321. goto done;
  322. }
  323. /*
  324. * If the next hop is an IPv6 address, then the node identified
  325. * by that address must be a neighbor of the sending host.
  326. */
  327. ron = &opts->ip6po_nextroute;
  328. if ((ron->ro_rt &&
  329. (ron->ro_rt->rt_flags & (RTF_UP | RTF_GATEWAY)) !=
  330. RTF_UP) ||
  331. !IN6_ARE_ADDR_EQUAL(&ron->ro_dst.sin6_addr,
  332. &sin6_next->sin6_addr)) {
  333. if (ron->ro_rt) {
  334. rtfree(ron->ro_rt);
  335. ron->ro_rt = NULL;
  336. }
  337. ron->ro_dst = *sin6_next;
  338. ron->ro_tableid = rtableid;
  339. }
  340. if (ron->ro_rt == NULL) {
  341. /* multi path case? */
  342. ron->ro_rt = rtalloc(sin6tosa(&ron->ro_dst),
  343. RT_REPORT|RT_RESOLVE, ron->ro_tableid);
  344. if (ron->ro_rt == NULL ||
  345. (ron->ro_rt->rt_flags & RTF_GATEWAY)) {
  346. if (ron->ro_rt) {
  347. rtfree(ron->ro_rt);
  348. ron->ro_rt = NULL;
  349. }
  350. error = EHOSTUNREACH;
  351. goto done;
  352. }
  353. }
  354. if (!nd6_is_addr_neighbor(sin6_next, ron->ro_rt->rt_ifp)) {
  355. rtfree(ron->ro_rt);
  356. ron->ro_rt = NULL;
  357. error = EHOSTUNREACH;
  358. goto done;
  359. }
  360. rt = ron->ro_rt;
  361. ifp = rt->rt_ifp;
  362. /*
  363. * When cloning is required, try to allocate a route to the
  364. * destination so that the caller can store path MTU
  365. * information.
  366. */
  367. goto done;
  368. }
  369. /*
  370. * Use a cached route if it exists and is valid, else try to allocate
  371. * a new one. Note that we should check the address family of the
  372. * cached destination, in case of sharing the cache with IPv4.
  373. */
  374. if (ro) {
  375. if (ro->ro_rt &&
  376. (!(ro->ro_rt->rt_flags & RTF_UP) ||
  377. sin6tosa(&ro->ro_dst)->sa_family != AF_INET6 ||
  378. !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst))) {
  379. rtfree(ro->ro_rt);
  380. ro->ro_rt = NULL;
  381. }
  382. if (ro->ro_rt == NULL) {
  383. struct sockaddr_in6 *sa6;
  384. /* No route yet, so try to acquire one */
  385. bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
  386. ro->ro_tableid = rtableid;
  387. sa6 = &ro->ro_dst;
  388. *sa6 = *dstsock;
  389. sa6->sin6_scope_id = 0;
  390. ro->ro_tableid = rtableid;
  391. ro->ro_rt = rtalloc_mpath(sin6tosa(&ro->ro_dst),
  392. NULL, ro->ro_tableid);
  393. }
  394. /*
  395. * do not care about the result if we have the nexthop
  396. * explicitly specified.
  397. */
  398. if (opts && opts->ip6po_nexthop)
  399. goto done;
  400. if (ro->ro_rt) {
  401. ifp = ro->ro_rt->rt_ifp;
  402. if (ifp == NULL) { /* can this really happen? */
  403. rtfree(ro->ro_rt);
  404. ro->ro_rt = NULL;
  405. }
  406. }
  407. if (ro->ro_rt == NULL)
  408. error = EHOSTUNREACH;
  409. rt = ro->ro_rt;
  410. /*
  411. * Check if the outgoing interface conflicts with
  412. * the interface specified by ipi6_ifindex (if specified).
  413. * Note that loopback interface is always okay.
  414. * (this may happen when we are sending a packet to one of
  415. * our own addresses.)
  416. */
  417. if (opts && opts->ip6po_pktinfo &&
  418. opts->ip6po_pktinfo->ipi6_ifindex) {
  419. if (!(ifp->if_flags & IFF_LOOPBACK) &&
  420. ifp->if_index !=
  421. opts->ip6po_pktinfo->ipi6_ifindex) {
  422. error = EHOSTUNREACH;
  423. goto done;
  424. }
  425. }
  426. }
  427. done:
  428. if (ifp == NULL && rt == NULL) {
  429. /*
  430. * This can happen if the caller did not pass a cached route
  431. * nor any other hints. We treat this case an error.
  432. */
  433. error = EHOSTUNREACH;
  434. }
  435. if (error == EHOSTUNREACH)
  436. ip6stat.ip6s_noroute++;
  437. if (retifp != NULL)
  438. *retifp = ifp;
  439. if (retrt != NULL)
  440. *retrt = rt; /* rt may be NULL */
  441. return (error);
  442. }
  443. int
  444. in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
  445. struct ip6_moptions *mopts, struct route_in6 *ro, struct ifnet **retifp,
  446. u_int rtableid)
  447. {
  448. struct rtentry *rt = NULL;
  449. int error;
  450. if ((error = selectroute(dstsock, opts, mopts, ro, retifp,
  451. &rt, 1, rtableid)) != 0)
  452. return (error);
  453. /*
  454. * do not use a rejected or black hole route.
  455. * XXX: this check should be done in the L2 output routine.
  456. * However, if we skipped this check here, we'd see the following
  457. * scenario:
  458. * - install a rejected route for a scoped address prefix
  459. * (like fe80::/10)
  460. * - send a packet to a destination that matches the scoped prefix,
  461. * with ambiguity about the scope zone.
  462. * - pick the outgoing interface from the route, and disambiguate the
  463. * scope zone with the interface.
  464. * - ip6_output() would try to get another route with the "new"
  465. * destination, which may be valid.
  466. * - we'd see no error on output.
  467. * Although this may not be very harmful, it should still be confusing.
  468. * We thus reject the case here.
  469. */
  470. if (rt && (rt->rt_flags & (RTF_REJECT | RTF_BLACKHOLE)))
  471. return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
  472. /*
  473. * Adjust the "outgoing" interface. If we're going to loop the packet
  474. * back to ourselves, the ifp would be the loopback interface.
  475. * However, we'd rather know the interface associated to the
  476. * destination address (which should probably be one of our own
  477. * addresses.)
  478. */
  479. if (rt && rt->rt_ifa && rt->rt_ifa->ifa_ifp)
  480. *retifp = rt->rt_ifa->ifa_ifp;
  481. return (0);
  482. }
  483. int
  484. in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
  485. struct ip6_moptions *mopts, struct route_in6 *ro, struct ifnet **retifp,
  486. struct rtentry **retrt, u_int rtableid)
  487. {
  488. return (selectroute(dstsock, opts, mopts, ro, retifp, retrt, 0,
  489. rtableid));
  490. }
  491. /*
  492. * Default hop limit selection. The precedence is as follows:
  493. * 1. Hoplimit value specified via ioctl.
  494. * 2. (If the outgoing interface is detected) the current
  495. * hop limit of the interface specified by router advertisement.
  496. * 3. The system default hoplimit.
  497. */
  498. int
  499. in6_selecthlim(struct inpcb *in6p, struct ifnet *ifp)
  500. {
  501. if (in6p && in6p->inp_hops >= 0)
  502. return (in6p->inp_hops);
  503. else if (ifp)
  504. return (ND_IFINFO(ifp)->chlim);
  505. else
  506. return (ip6_defhlim);
  507. }
  508. /*
  509. * generate kernel-internal form (scopeid embedded into s6_addr16[1]).
  510. * If the address scope of is link-local, embed the interface index in the
  511. * address. The routine determines our precedence
  512. * between advanced API scope/interface specification and basic API
  513. * specification.
  514. *
  515. * this function should be nuked in the future, when we get rid of
  516. * embedded scopeid thing.
  517. *
  518. * XXX actually, it is over-specification to return ifp against sin6_scope_id.
  519. * there can be multiple interfaces that belong to a particular scope zone
  520. * (in specification, we have 1:N mapping between a scope zone and interfaces).
  521. * we may want to change the function to return something other than ifp.
  522. */
  523. int
  524. in6_embedscope(struct in6_addr *in6, const struct sockaddr_in6 *sin6,
  525. struct inpcb *in6p, struct ifnet **ifpp)
  526. {
  527. struct ifnet *ifp = NULL;
  528. u_int32_t scopeid;
  529. *in6 = sin6->sin6_addr;
  530. scopeid = sin6->sin6_scope_id;
  531. if (ifpp)
  532. *ifpp = NULL;
  533. /*
  534. * don't try to read sin6->sin6_addr beyond here, since the caller may
  535. * ask us to overwrite existing sockaddr_in6
  536. */
  537. if (IN6_IS_SCOPE_EMBED(in6)) {
  538. struct in6_pktinfo *pi;
  539. /*
  540. * KAME assumption: link id == interface id
  541. */
  542. if (in6p && in6p->inp_outputopts6 &&
  543. (pi = in6p->inp_outputopts6->ip6po_pktinfo) &&
  544. pi->ipi6_ifindex) {
  545. ifp = if_get(pi->ipi6_ifindex);
  546. if (ifp == NULL)
  547. return ENXIO; /* XXX EINVAL? */
  548. in6->s6_addr16[1] = htons(pi->ipi6_ifindex);
  549. } else if (in6p && IN6_IS_ADDR_MULTICAST(in6) &&
  550. in6p->inp_moptions6 &&
  551. (ifp = if_get(in6p->inp_moptions6->im6o_ifidx))) {
  552. in6->s6_addr16[1] = htons(ifp->if_index);
  553. } else if (scopeid) {
  554. ifp = if_get(scopeid);
  555. if (ifp == NULL)
  556. return ENXIO; /* XXX EINVAL? */
  557. /*XXX assignment to 16bit from 32bit variable */
  558. in6->s6_addr16[1] = htons(scopeid & 0xffff);
  559. }
  560. if (ifpp)
  561. *ifpp = ifp;
  562. }
  563. return 0;
  564. }
  565. /*
  566. * generate standard sockaddr_in6 from embedded form.
  567. * touches sin6_addr and sin6_scope_id only.
  568. *
  569. * this function should be nuked in the future, when we get rid of
  570. * embedded scopeid thing.
  571. */
  572. int
  573. in6_recoverscope(struct sockaddr_in6 *sin6, const struct in6_addr *in6,
  574. struct ifnet *ifp)
  575. {
  576. u_int32_t scopeid;
  577. sin6->sin6_addr = *in6;
  578. /*
  579. * don't try to read *in6 beyond here, since the caller may
  580. * ask us to overwrite existing sockaddr_in6
  581. */
  582. sin6->sin6_scope_id = 0;
  583. if (IN6_IS_SCOPE_EMBED(in6)) {
  584. /*
  585. * KAME assumption: link id == interface id
  586. */
  587. scopeid = ntohs(sin6->sin6_addr.s6_addr16[1]);
  588. if (scopeid) {
  589. /* sanity check */
  590. if (if_get(scopeid) == NULL)
  591. return ENXIO;
  592. if (ifp && ifp->if_index != scopeid)
  593. return ENXIO;
  594. sin6->sin6_addr.s6_addr16[1] = 0;
  595. sin6->sin6_scope_id = scopeid;
  596. }
  597. }
  598. return 0;
  599. }
  600. /*
  601. * just clear the embedded scope identifer.
  602. */
  603. void
  604. in6_clearscope(struct in6_addr *addr)
  605. {
  606. if (IN6_IS_SCOPE_EMBED(addr))
  607. addr->s6_addr16[1] = 0;
  608. }