4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * This is used to support the hidden __sin6_src_id in the sockaddr_in6
28 * structure which is there to ensure that applications (such as UDP apps)
29 * which get an address from recvfrom and use that address in a sendto
30 * or connect will by default use the same source address in the "response"
31 * as the destination address in the "request" they received.
32 *
33 * This is built using some new functions (in IP - doing their own locking
34 * so they can be called from the transports) to map between integer IDs
35 * and in6_addr_t.
36 * The use applies to sockaddr_in6 - whether or not mapped addresses are used.
37 *
38 * This file contains the functions used by both IP and the transports
39 * to implement __sin6_src_id.
40 * The routines do their own locking since they are called from
41 * the transports (to map between a source id and an address)
42 * and from IP proper when IP addresses are added and removed.
43 *
206 smpp = srcid_lookup_addr(addr, zoneid, ipst);
207 smp = *smpp;
208 if (smp == NULL) {
209 char abuf[INET6_ADDRSTRLEN];
210
211 /* Not present - could be broadcast or multicast address */
212 ip1dbg(("ip_srcid_find_addr: unknown %s in zone %d\n",
213 inet_ntop(AF_INET6, addr, abuf, sizeof (abuf)), zoneid));
214 id = 0;
215 } else {
216 ASSERT(smp->sm_refcnt != 0);
217 id = smp->sm_srcid;
218 }
219 rw_exit(&ipst->ips_srcid_lock);
220 return (id);
221 }
222
223 /*
224 * Map from a source id to an address.
225 * If the id is unknown return the unspecified address.
226 */
227 void
228 ip_srcid_find_id(uint_t id, in6_addr_t *addr, zoneid_t zoneid,
229 netstack_t *ns)
230 {
231 srcid_map_t **smpp;
232 srcid_map_t *smp;
233 ip_stack_t *ipst = ns->netstack_ip;
234
235 rw_enter(&ipst->ips_srcid_lock, RW_READER);
236 smpp = srcid_lookup_id(id, ipst);
237 smp = *smpp;
238 if (smp == NULL || (smp->sm_zoneid != zoneid && zoneid != ALL_ZONES)) {
239 /* Not preset */
240 ip1dbg(("ip_srcid_find_id: unknown %u or in wrong zone\n", id));
241 *addr = ipv6_all_zeros;
242 } else {
243 ASSERT(smp->sm_refcnt != 0);
244 *addr = smp->sm_addr;
245 }
246 rw_exit(&ipst->ips_srcid_lock);
247 }
248
249 /* Assign the next available ID */
250 static uint_t
251 srcid_nextid(ip_stack_t *ipst)
252 {
253 uint_t id;
254 srcid_map_t **smpp;
255
256 ASSERT(rw_owner(&ipst->ips_srcid_lock) == curthread);
257
258 if (!ipst->ips_srcid_wrapped) {
259 id = ipst->ips_ip_src_id++;
260 if (ipst->ips_ip_src_id == 0)
261 ipst->ips_srcid_wrapped = B_TRUE;
262 return (id);
263 }
264 /* Once it wraps we search for an unused ID. */
265 for (id = 0; id < 0xffffffff; id++) {
266 smpp = srcid_lookup_id(id, ipst);
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
26 */
27
28 /*
29 * This is used to support the hidden __sin6_src_id in the sockaddr_in6
30 * structure which is there to ensure that applications (such as UDP apps)
31 * which get an address from recvfrom and use that address in a sendto
32 * or connect will by default use the same source address in the "response"
33 * as the destination address in the "request" they received.
34 *
35 * This is built using some new functions (in IP - doing their own locking
36 * so they can be called from the transports) to map between integer IDs
37 * and in6_addr_t.
38 * The use applies to sockaddr_in6 - whether or not mapped addresses are used.
39 *
40 * This file contains the functions used by both IP and the transports
41 * to implement __sin6_src_id.
42 * The routines do their own locking since they are called from
43 * the transports (to map between a source id and an address)
44 * and from IP proper when IP addresses are added and removed.
45 *
208 smpp = srcid_lookup_addr(addr, zoneid, ipst);
209 smp = *smpp;
210 if (smp == NULL) {
211 char abuf[INET6_ADDRSTRLEN];
212
213 /* Not present - could be broadcast or multicast address */
214 ip1dbg(("ip_srcid_find_addr: unknown %s in zone %d\n",
215 inet_ntop(AF_INET6, addr, abuf, sizeof (abuf)), zoneid));
216 id = 0;
217 } else {
218 ASSERT(smp->sm_refcnt != 0);
219 id = smp->sm_srcid;
220 }
221 rw_exit(&ipst->ips_srcid_lock);
222 return (id);
223 }
224
225 /*
226 * Map from a source id to an address.
227 * If the id is unknown return the unspecified address.
228 *
229 * For known IDs, check if the returned address is v4mapped or not, and
230 * return B_TRUE if it matches the desired v4mapped state or not. This
231 * prevents a broken app from requesting (via __sin6_src_id) a v4mapped
232 * address for a v6 destination, or vice versa.
233 *
234 * "addr" will not be set if we return B_FALSE.
235 */
236 boolean_t
237 ip_srcid_find_id(uint_t id, in6_addr_t *addr, zoneid_t zoneid,
238 boolean_t v4mapped, netstack_t *ns)
239 {
240 srcid_map_t **smpp;
241 srcid_map_t *smp;
242 ip_stack_t *ipst = ns->netstack_ip;
243 boolean_t rc;
244
245 rw_enter(&ipst->ips_srcid_lock, RW_READER);
246 smpp = srcid_lookup_id(id, ipst);
247 smp = *smpp;
248 if (smp == NULL || (smp->sm_zoneid != zoneid && zoneid != ALL_ZONES)) {
249 /* Not preset */
250 ip1dbg(("ip_srcid_find_id: unknown %u or in wrong zone\n", id));
251 *addr = ipv6_all_zeros;
252 rc = B_TRUE;
253 } else {
254 ASSERT(smp->sm_refcnt != 0);
255 /*
256 * The caller tells us if it expects a v4mapped address.
257 * Use it, along with the property of "addr" to set the rc.
258 */
259 if (IN6_IS_ADDR_V4MAPPED(&smp->sm_addr))
260 rc = v4mapped; /* We want a v4mapped address. */
261 else
262 rc = !v4mapped; /* We don't want a v4mapped address. */
263
264 if (rc)
265 *addr = smp->sm_addr;
266
267 }
268 rw_exit(&ipst->ips_srcid_lock);
269 return (rc);
270 }
271
272 /* Assign the next available ID */
273 static uint_t
274 srcid_nextid(ip_stack_t *ipst)
275 {
276 uint_t id;
277 srcid_map_t **smpp;
278
279 ASSERT(rw_owner(&ipst->ips_srcid_lock) == curthread);
280
281 if (!ipst->ips_srcid_wrapped) {
282 id = ipst->ips_ip_src_id++;
283 if (ipst->ips_ip_src_id == 0)
284 ipst->ips_srcid_wrapped = B_TRUE;
285 return (id);
286 }
287 /* Once it wraps we search for an unused ID. */
288 for (id = 0; id < 0xffffffff; id++) {
289 smpp = srcid_lookup_id(id, ipst);
|