xref: /minix/minix/net/lwip/ipsock.c (revision bb9622b5)
1 /* LWIP service - ipsock.c - shared IP-level socket code */
2 
3 #include "lwip.h"
4 #include "ifaddr.h"
5 
6 #define ip6_hdr __netbsd_ip6_hdr	/* conflicting definitions */
7 #include <net/route.h>
8 #include <netinet/ip.h>
9 #include <netinet/in_pcb.h>
10 #include <netinet6/in6_pcb.h>
11 #undef ip6_hdr
12 
13 /* The following are sysctl(7) settings. */
14 int lwip_ip4_forward = 0;		/* We patch lwIP to check these.. */
15 int lwip_ip6_forward = 0;		/*  ..two settings at run time.   */
16 static int ipsock_v6only = 1;
17 
18 /* The CTL_NET PF_INET IPPROTO_IP subtree. */
19 static struct rmib_node net_inet_ip_table[] = {
20 /* 1*/	[IPCTL_FORWARDING]	= RMIB_INTPTR(RMIB_RW, &lwip_ip4_forward,
21 				    "forwarding",
22 				    "Enable forwarding of INET diagrams"),
23 /* 3*/	[IPCTL_DEFTTL]		= RMIB_INT(RMIB_RO, IP_DEFAULT_TTL, "ttl",
24 				    "Default TTL for an INET diagram"),
25 /*23*/	[IPCTL_LOOPBACKCKSUM]	= RMIB_FUNC(RMIB_RW | CTLTYPE_INT, sizeof(int),
26 				    loopif_cksum, "do_loopback_cksum",
27 				    "Perform IP checksum on loopback"),
28 };
29 
30 static struct rmib_node net_inet_ip_node =
31     RMIB_NODE(RMIB_RO, net_inet_ip_table, "ip", "IPv4 related settings");
32 
33 /* The CTL_NET PF_INET6 IPPROTO_IPV6 subtree. */
34 static struct rmib_node net_inet6_ip6_table[] = {
35 /* 1*/	[IPV6CTL_FORWARDING]	= RMIB_INTPTR(RMIB_RW, &lwip_ip6_forward,
36 				    "forwarding",
37 				    "Enable forwarding of INET6 diagrams"),
38 				/*
39 				 * The following functionality is not
40 				 * implemented in lwIP at this time.
41 				 */
42 /* 2*/	[IPV6CTL_SENDREDIRECTS]	= RMIB_INT(RMIB_RO, 0, "redirect", "Enable "
43 				    "sending of ICMPv6 redirect messages"),
44 /* 3*/	[IPV6CTL_DEFHLIM]	= RMIB_INT(RMIB_RO, IP_DEFAULT_TTL, "hlim",
45 				    "Hop limit for an INET6 datagram"),
46 /*12*/	[IPV6CTL_ACCEPT_RTADV]	= RMIB_INTPTR(RMIB_RW, &ifaddr_accept_rtadv,
47 				    "accept_rtadv",
48 				    "Accept router advertisements"),
49 /*16*/	[IPV6CTL_DAD_COUNT]	= RMIB_INT(RMIB_RO,
50 				    LWIP_IPV6_DUP_DETECT_ATTEMPTS, "dad_count",
51 				    "Number of Duplicate Address Detection "
52 				    "probes to send"),
53 /*24*/	[IPV6CTL_V6ONLY]	= RMIB_INTPTR(RMIB_RW, &ipsock_v6only,
54 				    "v6only", "Disallow PF_INET6 sockets from "
55 				    "connecting to PF_INET sockets"),
56 				/*
57 				 * The following setting is significantly
58 				 * different from NetBSD, and therefore it has
59 				 * a somewhat different description as well.
60 				 */
61 /*35*/	[IPV6CTL_AUTO_LINKLOCAL]= RMIB_INTPTR(RMIB_RW, &ifaddr_auto_linklocal,
62 				    "auto_linklocal", "Enable global support "
63 				    "for adding IPv6link-local addresses to "
64 				    "interfaces"),
65 				/*
66 				 * Temporary addresses are managed entirely by
67 				 * userland.  We only maintain the settings.
68 				 */
69 /*+0*/	[IPV6CTL_MAXID]		= RMIB_INT(RMIB_RW, 0, "use_tempaddr",
70 				    "Use temporary address"),
71 /*+1*/	[IPV6CTL_MAXID + 1]	= RMIB_INT(RMIB_RW, 86400, "temppltime",
72 				    "Preferred lifetime of a temporary "
73 				    "address"),
74 /*+2*/	[IPV6CTL_MAXID + 2]	= RMIB_INT(RMIB_RW, 604800, "tempvltime",
75 				    "Valid lifetime of a temporary address"),
76 };
77 
78 static struct rmib_node net_inet6_ip6_node =
79     RMIB_NODE(RMIB_RO, net_inet6_ip6_table, "ip6", "IPv6 related settings");
80 
81 /*
82  * Initialize the IP sockets module.
83  */
84 void
85 ipsock_init(void)
86 {
87 
88 	/*
89 	 * Register the net.inet.ip and net.inet6.ip6 subtrees.  Unlike for the
90 	 * specific protocols (TCP/UDP/RAW), here the IPv4 and IPv6 subtrees
91 	 * are and must be separate, even though many settings are shared
92 	 * between the two at the lwIP level.  Ultimately we may have to split
93 	 * the subtrees for the specific protocols, too, though..
94 	 */
95 	mibtree_register_inet(AF_INET, IPPROTO_IP, &net_inet_ip_node);
96 	mibtree_register_inet(AF_INET6, IPPROTO_IPV6, &net_inet6_ip6_node);
97 }
98 
99 /*
100  * Return the lwIP IP address type (IPADDR_TYPE_) for the given IP socket.
101  */
102 static int
103 ipsock_get_type(struct ipsock * ip)
104 {
105 
106 	if (!(ip->ip_flags & IPF_IPV6))
107 		return IPADDR_TYPE_V4;
108 	else if (ip->ip_flags & IPF_V6ONLY)
109 		return IPADDR_TYPE_V6;
110 	else
111 		return IPADDR_TYPE_ANY;
112 }
113 
114 /*
115  * Create an IP socket, for the given (PF_/AF_) domain and initial send and
116  * receive buffer sizes.  Return the lwIP IP address type that should be used
117  * to create the corresponding PCB.  Return a pointer to the libsockevent
118  * socket in 'sockp'.  This function must not allocate any resources in any
119  * form, as socket creation may still fail later, in which case no destruction
120  * function is called.
121  */
122 int
123 ipsock_socket(struct ipsock * ip, int domain, size_t sndbuf, size_t rcvbuf,
124 	struct sock ** sockp)
125 {
126 
127 	ip->ip_flags = (domain == AF_INET6) ? IPF_IPV6 : 0;
128 
129 	if (domain == AF_INET6 && ipsock_v6only)
130 		ip->ip_flags |= IPF_V6ONLY;
131 
132 	ip->ip_sndbuf = sndbuf;
133 	ip->ip_rcvbuf = rcvbuf;
134 
135 	/* Important: when adding settings here, also change ipsock_clone(). */
136 
137 	*sockp = &ip->ip_sock;
138 
139 	return ipsock_get_type(ip);
140 }
141 
142 /*
143  * Clone the given socket 'ip' into the new socket 'newip', using the socket
144  * identifier 'newid'.  In particular, tell libsockevent about the clone and
145  * copy over any settings from 'ip' to 'newip' that can be inherited on a
146  * socket.  Cloning is used for new TCP connections arriving on listening TCP
147  * sockets.  This function must not fail.
148  */
149 void
150 ipsock_clone(struct ipsock * ip, struct ipsock * newip, sockid_t newid)
151 {
152 
153 	sockevent_clone(&ip->ip_sock, &newip->ip_sock, newid);
154 
155 	/* Inherit all settings from the original socket. */
156 	newip->ip_flags = ip->ip_flags;
157 	newip->ip_sndbuf = ip->ip_sndbuf;
158 	newip->ip_rcvbuf = ip->ip_rcvbuf;
159 }
160 
161 /*
162  * Create an <any> address for the given socket, taking into account whether
163  * the socket is IPv4, IPv6, or mixed.  The generated address, stored in
164  * 'ipaddr', will have the same type as returned from the ipsock_socket() call.
165  */
166 void
167 ipsock_get_any_addr(struct ipsock * ip, ip_addr_t * ipaddr)
168 {
169 
170 	ip_addr_set_any(ipsock_is_ipv6(ip), ipaddr);
171 
172 	if (ipsock_is_ipv6(ip) && !ipsock_is_v6only(ip))
173 		IP_SET_TYPE(ipaddr, IPADDR_TYPE_ANY);
174 }
175 
176 /*
177  * Verify whether the given (properly scoped) IP address is a valid source
178  * address for the given IP socket.  The 'allow_mcast' flag indicates whether
179  * the source address is allowed to be a multicast address.  Return OK on
180  * success.  If 'ifdevp' is not NULL, it is filled with either the interface
181  * that owns the address, or NULL if the address is (while valid) not
182  * associated with a particular interface.  On failure, return a negative error
183  * code.  This function must be called, in one way or another, for every source
184  * address used for binding or sending on a IP-layer socket.
185  */
186 int
187 ipsock_check_src_addr(struct ipsock * ip, ip_addr_t * ipaddr, int allow_mcast,
188 	struct ifdev ** ifdevp)
189 {
190 	ip6_addr_t *ip6addr;
191 	struct ifdev *ifdev;
192 	uint32_t inaddr, zone;
193 	int is_mcast;
194 
195 	/*
196 	 * TODO: for now, forbid binding to multicast addresses.  Callers that
197 	 * never allow multicast addresses anyway (e.g., IPV6_PKTINFO) should
198 	 * do their own check for this; the one here may eventually be removed.
199 	 */
200 	is_mcast = ip_addr_ismulticast(ipaddr);
201 
202 	if (is_mcast && !allow_mcast)
203 		return EADDRNOTAVAIL;
204 
205 	if (IP_IS_V6(ipaddr)) {
206 		/*
207 		 * The given address must not have a KAME-style embedded zone.
208 		 * This check is already performed in addr_get_inet(), but we
209 		 * have to replicate it here because not all source addresses
210 		 * go through addr_get_inet().
211 		 */
212 		ip6addr = ip_2_ip6(ipaddr);
213 
214 		if (ip6_addr_has_scope(ip6addr, IP6_UNKNOWN) &&
215 		    (ip6addr->addr[0] & PP_HTONL(0x0000ffffUL)))
216 			return EINVAL;
217 
218 		/*
219 		 * lwIP does not support IPv4-mapped IPv6 addresses, so these
220 		 * must be converted to plain IPv4 addresses instead.  The IPv4
221 		 * 'any' address is not supported in this form.  In V6ONLY
222 		 * mode, refuse connecting or sending to IPv4-mapped addresses
223 		 * at all.
224 		 */
225 		if (ip6_addr_isipv4mappedipv6(ip6addr)) {
226 			if (ipsock_is_v6only(ip))
227 				return EINVAL;
228 
229 			inaddr = ip6addr->addr[3];
230 
231 			if (inaddr == PP_HTONL(INADDR_ANY))
232 				return EADDRNOTAVAIL;
233 
234 			ip_addr_set_ip4_u32(ipaddr, inaddr);
235 		}
236 	}
237 
238 	ifdev = NULL;
239 
240 	if (!ip_addr_isany(ipaddr)) {
241 		if (IP_IS_V6(ipaddr) &&
242 		    ip6_addr_lacks_zone(ip_2_ip6(ipaddr), IP6_UNKNOWN))
243 			return EADDRNOTAVAIL;
244 
245 		/*
246 		 * If the address is a unicast address, it must be assigned to
247 		 * an interface.  Otherwise, if it is a zoned multicast
248 		 * address, the zone denotes the interface.  For global
249 		 * multicast addresses, we cannot determine an interface.
250 		 */
251 		if (!is_mcast) {
252 			if ((ifdev = ifaddr_map_by_addr(ipaddr)) == NULL)
253 				return EADDRNOTAVAIL;
254 		} else {
255 			/* Some multicast addresses are not acceptable. */
256 			if (!addr_is_valid_multicast(ipaddr))
257 				return EINVAL;
258 
259 			if (IP_IS_V6(ipaddr) &&
260 			    ip6_addr_has_zone(ip_2_ip6(ipaddr))) {
261 				zone = ip6_addr_zone(ip_2_ip6(ipaddr));
262 
263 				if ((ifdev = ifdev_get_by_index(zone)) == NULL)
264 					return ENXIO;
265 			}
266 		}
267 	}
268 
269 	if (ifdevp != NULL)
270 		*ifdevp = ifdev;
271 
272 	return OK;
273 }
274 
275 /*
276  * Retrieve and validate a source address for use in a socket bind call on
277  * socket 'ip'.  The user-provided address is given as 'addr', with length
278  * 'addr_len'.  The socket's current local IP address and port are given as
279  * 'local_ip' and 'local_port', respectively; for raw sockets, the given local
280  * port number is always zero.  The caller's endpoint is given as 'user_endpt',
281  * used to make sure only root can bind to local port numbers.  The boolean
282  * 'allow_mcast' flag indicates whether the source address is allowed to be a
283  * multicast address.  On success, return OK with the source IP address stored
284  * in 'src_addr' and, if 'src_port' is not NULL, the port number to bind to
285  * stored in 'portp'.  Otherwise, return a negative error code.  This function
286  * performs all the tasks necessary before the socket can be bound using a lwIP
287  * call.
288  */
289 int
290 ipsock_get_src_addr(struct ipsock * ip, const struct sockaddr * addr,
291 	socklen_t addr_len, endpoint_t user_endpt, ip_addr_t * local_ip,
292 	uint16_t local_port, int allow_mcast, ip_addr_t * src_addr,
293 	uint16_t * src_port)
294 {
295 	uint16_t port;
296 	int r;
297 
298 	/*
299 	 * If the socket has been bound already, it cannot be bound again.
300 	 * We check this by checking whether the current local port is non-
301 	 * zero.  This rule does not apply to raw sockets, but raw sockets have
302 	 * no port numbers anyway, so this conveniently works out.  However,
303 	 * raw sockets may not be rebound after being connected, but that is
304 	 * checked before we even get here.
305 	 */
306 	if (local_port != 0)
307 		return EINVAL;
308 
309 	/* Parse the user-provided address. */
310 	if ((r = addr_get_inet(addr, addr_len, ipsock_get_type(ip), src_addr,
311 	    FALSE /*kame*/, &port)) != OK)
312 		return r;
313 
314 	/* Validate the user-provided address. */
315 	if ((r = ipsock_check_src_addr(ip, src_addr, allow_mcast,
316 	    NULL /*ifdevp*/)) != OK)
317 		return r;
318 
319 	/*
320 	 * If we are interested in port numbers at all (for non-raw sockets,
321 	 * meaning portp is not NULL), make sure that only the superuser can
322 	 * bind to privileged port numbers.  For raw sockets, only the
323 	 * superuser can open a socket anyway, so we need no check here.
324 	 */
325 	if (src_port != NULL) {
326 		if (port != 0 && port < IPPORT_RESERVED &&
327 		    !util_is_root(user_endpt))
328 			return EACCES;
329 
330 		*src_port = port;
331 	}
332 
333 	return OK;
334 }
335 
336 /*
337  * Retrieve and validate a destination address for use in a socket connect or
338  * sendto call.  The user-provided address is given as 'addr', with length
339  * 'addr_len'.  The socket's current local IP address is given as 'local_addr'.
340  * On success, return OK with the destination IP address stored in 'dst_addr'
341  * and, if 'dst_port' is not NULL, the port number to bind to stored in
342  * 'dst_port'.  Otherwise, return a negative error code.  This function must be
343  * called, in one way or another, for every destination address used for
344  * connecting or sending on a IP-layer socket.
345  */
346 int
347 ipsock_get_dst_addr(struct ipsock * ip, const struct sockaddr * addr,
348 	socklen_t addr_len, const ip_addr_t * local_addr, ip_addr_t * dst_addr,
349 	uint16_t * dst_port)
350 {
351 	uint16_t port;
352 	int r;
353 
354 	/* Parse the user-provided address. */
355 	if ((r = addr_get_inet(addr, addr_len, ipsock_get_type(ip), dst_addr,
356 	    FALSE /*kame*/, &port)) != OK)
357 		return r;
358 
359 	/* Destination addresses are always specific. */
360 	if (IP_GET_TYPE(dst_addr) == IPADDR_TYPE_ANY)
361 		IP_SET_TYPE(dst_addr, IPADDR_TYPE_V6);
362 
363 	/*
364 	 * lwIP does not support IPv4-mapped IPv6 addresses, so these must be
365 	 * supported to plain IPv4 addresses instead.  In V6ONLY mode, refuse
366 	 * connecting or sending to IPv4-mapped addresses at all.
367 	 */
368 	if (IP_IS_V6(dst_addr) &&
369 	    ip6_addr_isipv4mappedipv6(ip_2_ip6(dst_addr))) {
370 		if (ipsock_is_v6only(ip))
371 			return EINVAL;
372 
373 		ip_addr_set_ip4_u32(dst_addr, ip_2_ip6(dst_addr)->addr[3]);
374 	}
375 
376 	/*
377 	 * Now make sure that the local and remote addresses are of the same
378 	 * family.  The local address may be of type IPADDR_TYPE_ANY, which is
379 	 * allowed for both IPv4 and IPv6.  Even for connectionless socket
380 	 * types we must perform this check as part of connect calls (as well
381 	 * as sendto calls!) because otherwise we will create problems for
382 	 * sysctl based socket enumeration (i.e., netstat), which uses the
383 	 * local IP address type to determine the socket family.
384 	 */
385 	if (IP_GET_TYPE(local_addr) != IPADDR_TYPE_ANY &&
386 	    IP_IS_V6(local_addr) != IP_IS_V6(dst_addr))
387 		return EINVAL;
388 
389 	/*
390 	 * TODO: on NetBSD, an 'any' destination address is replaced with a
391 	 * local interface address.
392 	 */
393 	if (ip_addr_isany(dst_addr))
394 		return EHOSTUNREACH;
395 
396 	/*
397 	 * If the address is a multicast address, the multicast address itself
398 	 * must be valid.
399 	 */
400 	if (ip_addr_ismulticast(dst_addr) &&
401 	    !addr_is_valid_multicast(dst_addr))
402 		return EINVAL;
403 
404 	/*
405 	 * TODO: decide whether to add a zone to a scoped IPv6 address that
406 	 * lacks a zone.  For now, we let lwIP handle this, as lwIP itself
407 	 * will always add the zone at some point.  If anything changes there,
408 	 * this would be the place to set the zone (using a route lookup).
409 	 */
410 
411 	/*
412 	 * For now, we do not forbid or alter any other particular destination
413 	 * addresses.
414 	 */
415 
416 	if (dst_port != NULL) {
417 		/*
418 		 * Disallow connecting/sending to port zero.  There is no error
419 		 * code that applies well to this case, so we copy NetBSD's.
420 		 */
421 		if (port == 0)
422 			return EADDRNOTAVAIL;
423 
424 		*dst_port = port;
425 	}
426 
427 	return OK;
428 }
429 
430 /*
431  * Store the address 'ipaddr' associated with the socket 'ip' (for example, it
432  * may be the local or remote IP address of the socket) as a sockaddr structure
433  * in 'addr'.  A port number is provided as 'port' (in host-byte order) if
434  * relevant, and zero is passed in otherwise.  This function MUST only be
435  * called from contexts where 'addr' is a buffer provided by libsockevent or
436  * libsockdriver, meaning that it is of size SOCKADDR_MAX.  The value pointed
437  * to by 'addr_len' is not expected to be initialized in calls to this function
438  * (and will typically zero).  On return, 'addr_len' is filled with the length
439  * of the address generated in 'addr'.  This function never fails.
440  */
441 void
442 ipsock_put_addr(struct ipsock * ip, struct sockaddr * addr,
443 	socklen_t * addr_len, ip_addr_t * ipaddr, uint16_t port)
444 {
445 	ip_addr_t mappedaddr;
446 
447 	/*
448 	 * If the socket is an AF_INET6-type socket, and the given address is
449 	 * an IPv4-type address, store it as an IPv4-mapped IPv6 address.
450 	 */
451 	if (ipsock_is_ipv6(ip) && IP_IS_V4(ipaddr)) {
452 		addr_make_v4mapped_v6(&mappedaddr, ip_2_ip4(ipaddr));
453 
454 		ipaddr = &mappedaddr;
455 	}
456 
457 	/*
458 	 * We have good reasons to keep the sockdriver and sockevent APIs as
459 	 * they are, namely, defaulting 'addr_len' to zero such that the caller
460 	 * must provide a non-zero length (only) when returning a valid
461 	 * address.  The consequence here is that we have to know the size of
462 	 * the provided buffer.  For libsockevent callbacks, we are always
463 	 * guaranteed to get a buffer of at least this size.
464 	 */
465 	*addr_len = SOCKADDR_MAX;
466 
467 	addr_put_inet(addr, addr_len, ipaddr, FALSE /*kame*/, port);
468 }
469 
470 /*
471  * Set socket options on an IP socket.
472  */
473 int
474 ipsock_setsockopt(struct ipsock * ip, int level, int name,
475 	const struct sockdriver_data * data, socklen_t len,
476 	struct ipopts * ipopts)
477 {
478 	int r, val, allow;
479 	uint8_t type;
480 
481 	switch (level) {
482 	case SOL_SOCKET:
483 		switch (name) {
484 		case SO_SNDBUF:
485 			if ((r = sockdriver_copyin_opt(data, &val, sizeof(val),
486 			    len)) != OK)
487 				return r;
488 
489 			if (val <= 0 || (size_t)val < ipopts->sndmin ||
490 			    (size_t)val > ipopts->sndmax)
491 				return EINVAL;
492 
493 			ip->ip_sndbuf = val;
494 
495 			return OK;
496 
497 		case SO_RCVBUF:
498 			if ((r = sockdriver_copyin_opt(data, &val, sizeof(val),
499 			    len)) != OK)
500 				return r;
501 
502 			if (val <= 0 || (size_t)val < ipopts->rcvmin ||
503 			    (size_t)val > ipopts->rcvmax)
504 				return EINVAL;
505 
506 			ip->ip_rcvbuf = val;
507 
508 			return OK;
509 		}
510 
511 		break;
512 
513 	case IPPROTO_IP:
514 		if (ipsock_is_ipv6(ip))
515 			break;
516 
517 		switch (name) {
518 		case IP_TOS:
519 			if ((r = sockdriver_copyin_opt(data, &val, sizeof(val),
520 			    len)) != OK)
521 				return r;
522 
523 			if (val < 0 || val > UINT8_MAX)
524 				return EINVAL;
525 
526 			*ipopts->tos = (uint8_t)val;
527 
528 			return OK;
529 
530 		case IP_TTL:
531 			if ((r = sockdriver_copyin_opt(data, &val, sizeof(val),
532 			    len)) != OK)
533 				return r;
534 
535 			if (val < 0 || val > UINT8_MAX)
536 				return EINVAL;
537 
538 			*ipopts->ttl = (uint8_t)val;
539 
540 			return OK;
541 		}
542 
543 		break;
544 
545 	case IPPROTO_IPV6:
546 		if (!ipsock_is_ipv6(ip))
547 			break;
548 
549 		switch (name) {
550 		case IPV6_UNICAST_HOPS:
551 			if ((r = sockdriver_copyin_opt(data, &val, sizeof(val),
552 			    len)) != OK)
553 				return r;
554 
555 			if (val < -1 || val > UINT8_MAX)
556 				return EINVAL;
557 
558 			if (val == -1)
559 				val = IP_DEFAULT_TTL;
560 
561 			*ipopts->ttl = val;
562 
563 			return OK;
564 
565 		case IPV6_TCLASS:
566 			if ((r = sockdriver_copyin_opt(data, &val, sizeof(val),
567 			    len)) != OK)
568 				return r;
569 
570 			if (val < -1 || val > UINT8_MAX)
571 				return EINVAL;
572 
573 			if (val == -1)
574 				val = 0;
575 
576 			*ipopts->tos = val;
577 
578 			return OK;
579 
580 		case IPV6_V6ONLY:
581 			if ((r = sockdriver_copyin_opt(data, &val, sizeof(val),
582 			    len)) != OK)
583 				return r;
584 
585 			/*
586 			 * If the socket has been bound to an actual address,
587 			 * we still allow the option to be changed, but it no
588 			 * longer has any effect.
589 			 */
590 			type = IP_GET_TYPE(ipopts->local_ip);
591 			allow = (type == IPADDR_TYPE_ANY ||
592 			    (type == IPADDR_TYPE_V6 &&
593 			    ip_addr_isany(ipopts->local_ip)));
594 
595 			if (val) {
596 				ip->ip_flags |= IPF_V6ONLY;
597 
598 				type = IPADDR_TYPE_V6;
599 			} else {
600 				ip->ip_flags &= ~IPF_V6ONLY;
601 
602 				type = IPADDR_TYPE_ANY;
603 			}
604 
605 			if (allow)
606 				IP_SET_TYPE(ipopts->local_ip, type);
607 
608 			return OK;
609 		}
610 
611 		break;
612 	}
613 
614 	return ENOPROTOOPT;
615 }
616 
617 /*
618  * Retrieve socket options on an IP socket.
619  */
620 int
621 ipsock_getsockopt(struct ipsock * ip, int level, int name,
622 	const struct sockdriver_data * data, socklen_t * len,
623 	struct ipopts * ipopts)
624 {
625 	int val;
626 
627 	switch (level) {
628 	case SOL_SOCKET:
629 		switch (name) {
630 		case SO_SNDBUF:
631 			val = ip->ip_sndbuf;
632 
633 			return sockdriver_copyout_opt(data, &val, sizeof(val),
634 			    len);
635 
636 		case SO_RCVBUF:
637 			val = ip->ip_rcvbuf;
638 
639 			return sockdriver_copyout_opt(data, &val, sizeof(val),
640 			    len);
641 		}
642 
643 		break;
644 
645 	case IPPROTO_IP:
646 		if (ipsock_is_ipv6(ip))
647 			break;
648 
649 		switch (name) {
650 		case IP_TOS:
651 			val = (int)*ipopts->tos;
652 
653 			return sockdriver_copyout_opt(data, &val, sizeof(val),
654 			    len);
655 
656 		case IP_TTL:
657 			val = (int)*ipopts->ttl;
658 
659 			return sockdriver_copyout_opt(data, &val, sizeof(val),
660 			    len);
661 		}
662 
663 		break;
664 
665 	case IPPROTO_IPV6:
666 		if (!ipsock_is_ipv6(ip))
667 			break;
668 
669 		switch (name) {
670 		case IPV6_UNICAST_HOPS:
671 			val = *ipopts->ttl;
672 
673 			return sockdriver_copyout_opt(data, &val, sizeof(val),
674 			    len);
675 
676 		case IPV6_TCLASS:
677 			val = *ipopts->tos;
678 
679 			return sockdriver_copyout_opt(data, &val, sizeof(val),
680 			    len);
681 
682 		case IPV6_V6ONLY:
683 			val = !!(ip->ip_flags & IPF_V6ONLY);
684 
685 			return sockdriver_copyout_opt(data, &val, sizeof(val),
686 			    len);
687 		}
688 
689 		break;
690 	}
691 
692 	return ENOPROTOOPT;
693 }
694 
695 /*
696  * Fill the given kinfo_pcb sysctl(7) structure with IP-level information.
697  */
698 void
699 ipsock_get_info(struct kinfo_pcb * ki, const ip_addr_t * local_ip,
700 	uint16_t local_port, const ip_addr_t * remote_ip, uint16_t remote_port)
701 {
702 	ip_addr_t ipaddr;
703 	socklen_t len;
704 	uint8_t type;
705 
706 	len = sizeof(ki->ki_spad); /* use this for the full size, not ki_src */
707 
708 	addr_put_inet(&ki->ki_src, &len, local_ip, TRUE /*kame*/, local_port);
709 
710 	/*
711 	 * At this point, the local IP address type has already been used to
712 	 * determine whether this is an IPv4 or IPv6 socket.  While not ideal,
713 	 * that is the best we can do: we cannot use IPv4-mapped IPv6 addresses
714 	 * in lwIP PCBs, we cannot store the original type in those PCBs, and
715 	 * we also cannot rely on the PCB having an associated ipsock object
716 	 * anymore.  We also cannot use the ipsock only when present: it could
717 	 * make a TCP PCB "jump" from IPv6 to IPv4 in the netstat listing when
718 	 * it goes into TIME_WAIT state, for example.
719 	 *
720 	 * So, use *only* the type of the local IP address to determine whether
721 	 * this is an IPv4 or an IPv6 socket.  At the same time, do *not* rely
722 	 * on the remote IP address being IPv4 for a local IPv4 address; it may
723 	 * be of type IPADDR_TYPE_V6 for an unconnected socket bound to an
724 	 * IPv4-mapped IPv6 address.  Pretty messy, but we're limited by what
725 	 * lwIP offers here.  Since it's just netstat, it need not be perfect.
726 	 */
727 	if ((type = IP_GET_TYPE(local_ip)) == IPADDR_TYPE_V4) {
728 		if (!ip_addr_isany(local_ip) || local_port != 0)
729 			ki->ki_prstate = INP_BOUND;
730 
731 		/*
732 		 * Make sure the returned socket address types are consistent.
733 		 * The only case where the remote IP address is not IPv4 here
734 		 * is when it is not set yet, so there is no need to check
735 		 * whether it is the 'any' address: it always is.
736 		 */
737 		if (IP_GET_TYPE(remote_ip) != IPADDR_TYPE_V4) {
738 			ip_addr_set_zero_ip4(&ipaddr);
739 
740 			remote_ip = &ipaddr;
741 		}
742 	} else {
743 		if (!ip_addr_isany(local_ip) || local_port != 0)
744 			ki->ki_prstate = IN6P_BOUND;
745 		if (type != IPADDR_TYPE_ANY)
746 			ki->ki_pflags |= IN6P_IPV6_V6ONLY;
747 	}
748 
749 	len = sizeof(ki->ki_dpad); /* use this for the full size, not ki_dst */
750 
751 	addr_put_inet(&ki->ki_dst, &len, remote_ip, TRUE /*kame*/,
752 	    remote_port);
753 
754 	/* Check the type of the *local* IP address here.  See above. */
755 	if (!ip_addr_isany(remote_ip) || remote_port != 0) {
756 		if (type == IPADDR_TYPE_V4)
757 			ki->ki_prstate = INP_CONNECTED;
758 		else
759 			ki->ki_prstate = IN6P_CONNECTED;
760 	}
761 }
762