| 1 | /*	$NetBSD: bindresvport.c,v 1.25 2013/03/11 20:19:28 tron Exp $	*/ | 
| 2 |  | 
| 3 | /* | 
| 4 |  * Copyright (c) 2010, Oracle America, Inc. | 
| 5 |  * | 
| 6 |  * Redistribution and use in source and binary forms, with or without | 
| 7 |  * modification, are permitted provided that the following conditions are | 
| 8 |  * met: | 
| 9 |  * | 
| 10 |  *     * Redistributions of source code must retain the above copyright | 
| 11 |  *       notice, this list of conditions and the following disclaimer. | 
| 12 |  *     * Redistributions in binary form must reproduce the above | 
| 13 |  *       copyright notice, this list of conditions and the following | 
| 14 |  *       disclaimer in the documentation and/or other materials | 
| 15 |  *       provided with the distribution. | 
| 16 |  *     * Neither the name of the "Oracle America, Inc." nor the names of its | 
| 17 |  *       contributors may be used to endorse or promote products derived | 
| 18 |  *       from this software without specific prior written permission. | 
| 19 |  * | 
| 20 |  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
| 21 |  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
| 22 |  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 
| 23 |  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 
| 24 |  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | 
| 25 |  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
| 26 |  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | 
| 27 |  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 
| 28 |  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | 
| 29 |  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 
| 30 |  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
| 31 |  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 32 |  */ | 
| 33 |  | 
| 34 | #include <sys/cdefs.h> | 
| 35 | #if defined(LIBC_SCCS) && !defined(lint) | 
| 36 | #if 0 | 
| 37 | static char *sccsid = "@(#)bindresvport.c 1.8 88/02/08 SMI" ; | 
| 38 | static char *sccsid = "@(#)bindresvport.c	2.2 88/07/29 4.0 RPCSRC" ; | 
| 39 | #else | 
| 40 | __RCSID("$NetBSD: bindresvport.c,v 1.25 2013/03/11 20:19:28 tron Exp $" ); | 
| 41 | #endif | 
| 42 | #endif | 
| 43 |  | 
| 44 | /* | 
| 45 |  * Copyright (c) 1987 by Sun Microsystems, Inc. | 
| 46 |  */ | 
| 47 |  | 
| 48 | #include "namespace.h" | 
| 49 |  | 
| 50 | #include <sys/types.h> | 
| 51 | #include <sys/socket.h> | 
| 52 |  | 
| 53 | #include <netinet/in.h> | 
| 54 |  | 
| 55 | #include <errno.h> | 
| 56 | #include <string.h> | 
| 57 | #include <unistd.h> | 
| 58 |  | 
| 59 | #include <rpc/rpc.h> | 
| 60 | #include "svc_fdset.h" | 
| 61 |  | 
| 62 | #ifdef __weak_alias | 
| 63 | __weak_alias(bindresvport,_bindresvport) | 
| 64 | __weak_alias(bindresvport_sa,_bindresvport_sa) | 
| 65 | #endif | 
| 66 |  | 
| 67 | /* | 
| 68 |  * Bind a socket to a privileged IP port | 
| 69 |  */ | 
| 70 | int | 
| 71 | bindresvport(int sd, struct sockaddr_in *brsin) | 
| 72 | { | 
| 73 | 	return bindresvport_sa(sd, (struct sockaddr *)(void *)brsin); | 
| 74 | } | 
| 75 |  | 
| 76 | /* | 
| 77 |  * Bind a socket to a privileged IP port | 
| 78 |  */ | 
| 79 | int | 
| 80 | bindresvport_sa(int sd, struct sockaddr *sa) | 
| 81 | { | 
| 82 | 	int error, old; | 
| 83 | 	struct sockaddr_storage myaddr; | 
| 84 | 	struct sockaddr_in *brsin; | 
| 85 | #ifdef INET6 | 
| 86 | 	struct sockaddr_in6 *brsin6; | 
| 87 | #endif | 
| 88 | 	int proto, portrange, portlow; | 
| 89 | 	u_int16_t *portp; | 
| 90 | 	socklen_t salen; | 
| 91 | 	int af; | 
| 92 |  | 
| 93 | 	if (sa == NULL) { | 
| 94 | 		salen = sizeof(myaddr); | 
| 95 | 		sa = (struct sockaddr *)(void *)&myaddr; | 
| 96 |  | 
| 97 | 		if (getsockname(sd, sa, &salen) == -1) | 
| 98 | 			return -1;	/* errno is correctly set */ | 
| 99 |  | 
| 100 | 		af = sa->sa_family; | 
| 101 | 		memset(sa, 0, salen); | 
| 102 | 	} else | 
| 103 | 		af = sa->sa_family; | 
| 104 |  | 
| 105 | 	switch (af) { | 
| 106 | 	case AF_INET: | 
| 107 | 		proto = IPPROTO_IP; | 
| 108 | 		portrange = IP_PORTRANGE; | 
| 109 | 		portlow = IP_PORTRANGE_LOW; | 
| 110 | 		brsin = (struct sockaddr_in *)(void *)sa; | 
| 111 | 		salen = sizeof(struct sockaddr_in); | 
| 112 | 		portp = &brsin->sin_port; | 
| 113 | 		break; | 
| 114 | #ifdef INET6 | 
| 115 | 	case AF_INET6: | 
| 116 | 		proto = IPPROTO_IPV6; | 
| 117 | 		portrange = IPV6_PORTRANGE; | 
| 118 | 		portlow = IPV6_PORTRANGE_LOW; | 
| 119 | 		brsin6 = (struct sockaddr_in6 *)(void *)sa; | 
| 120 | 		salen = sizeof(struct sockaddr_in6); | 
| 121 | 		portp = &brsin6->sin6_port; | 
| 122 | 		break; | 
| 123 | #endif | 
| 124 | 	default: | 
| 125 | 		errno = EPFNOSUPPORT; | 
| 126 | 		return (-1); | 
| 127 | 	} | 
| 128 | 	sa->sa_family = af; | 
| 129 | 	sa->sa_len = salen; | 
| 130 |  | 
| 131 | 	if (*portp == 0) { | 
| 132 | 		socklen_t oldlen = sizeof(old); | 
| 133 |  | 
| 134 | 		error = getsockopt(sd, proto, portrange, &old, &oldlen); | 
| 135 | 		if (error < 0) | 
| 136 | 			return (error); | 
| 137 | 		error = setsockopt(sd, proto, portrange, &portlow, | 
| 138 | 		    (socklen_t)sizeof(portlow)); | 
| 139 | 		if (error < 0) | 
| 140 | 			return (error); | 
| 141 | 	} | 
| 142 |  | 
| 143 | 	error = bind(sd, sa, salen); | 
| 144 |  | 
| 145 | 	if (*portp == 0) { | 
| 146 | 		int saved_errno = errno; | 
| 147 |  | 
| 148 | 		if (error < 0) { | 
| 149 | 			if (setsockopt(sd, proto, portrange, &old, | 
| 150 | 			    (socklen_t)sizeof(old)) < 0) | 
| 151 | 				errno = saved_errno; | 
| 152 | 			return (error); | 
| 153 | 		} | 
| 154 |  | 
| 155 | 		if (sa != (struct sockaddr *)(void *)&myaddr) { | 
| 156 | 			/* What did the kernel assign? */ | 
| 157 | 			if (getsockname(sd, sa, &salen) < 0) | 
| 158 | 				errno = saved_errno; | 
| 159 | 			return (error); | 
| 160 | 		} | 
| 161 | 	} | 
| 162 | 	return (error); | 
| 163 | } | 
| 164 |  |