1 /* 2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 3 * unrestricted use provided that this legend is included on all tape 4 * media and as a part of the software program in whole or part. Users 5 * may copy or modify Sun RPC without charge, but are not authorized 6 * to license or distribute it to anyone else except as part of a product or 7 * program developed by the user. 8 * 9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 12 * 13 * Sun RPC is provided with no support and without any obligation on the 14 * part of Sun Microsystems, Inc. to assist in its use, correction, 15 * modification or enhancement. 16 * 17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 19 * OR ANY PART THEREOF. 20 * 21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 22 * or profits or other special, indirect and consequential damages, even if 23 * Sun has been advised of the possibility of such damages. 24 * 25 * Sun Microsystems, Inc. 26 * 2550 Garcia Avenue 27 * Mountain View, California 94043 28 * 29 * @(#)bindresvport.c 1.8 88/02/08 SMI 30 * @(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC 31 * $NetBSD: bindresvport.c,v 1.19 2000/07/06 03:03:59 christos Exp $ 32 * $FreeBSD: src/lib/libc/rpc/bindresvport.c,v 1.16 2004/10/16 06:11:34 obrien Exp $ 33 * $DragonFly: src/lib/libc/rpc/bindresvport.c,v 1.4 2005/11/13 12:27:04 swildner Exp $ 34 */ 35 36 /* 37 * Copyright (c) 1987 by Sun Microsystems, Inc. 38 * 39 * Portions Copyright(C) 1996, Jason Downs. All rights reserved. 40 */ 41 42 #include "namespace.h" 43 #include <sys/types.h> 44 #include <sys/socket.h> 45 46 #include <netinet/in.h> 47 48 #include <errno.h> 49 #include <string.h> 50 #include <unistd.h> 51 52 #include <rpc/rpc.h> 53 54 #include <string.h> 55 #include "un-namespace.h" 56 57 /* 58 * Bind a socket to a privileged IP port 59 */ 60 int 61 bindresvport(int sd, struct sockaddr_in *sin) 62 { 63 return bindresvport_sa(sd, (struct sockaddr *)sin); 64 } 65 66 /* 67 * Bind a socket to a privileged IP port 68 */ 69 int 70 bindresvport_sa(int sd, struct sockaddr *sa) 71 { 72 int old, error, af; 73 struct sockaddr_storage myaddr; 74 struct sockaddr_in *sin; 75 #ifdef INET6 76 struct sockaddr_in6 *sin6; 77 #endif 78 int proto, portrange, portlow; 79 u_int16_t *portp; 80 socklen_t salen; 81 82 if (sa == NULL) { 83 salen = sizeof(myaddr); 84 sa = (struct sockaddr *)&myaddr; 85 86 if (_getsockname(sd, sa, &salen) == -1) 87 return -1; /* errno is correctly set */ 88 89 af = sa->sa_family; 90 memset(sa, 0, salen); 91 } else 92 af = sa->sa_family; 93 94 switch (af) { 95 case AF_INET: 96 proto = IPPROTO_IP; 97 portrange = IP_PORTRANGE; 98 portlow = IP_PORTRANGE_LOW; 99 sin = (struct sockaddr_in *)sa; 100 salen = sizeof(struct sockaddr_in); 101 portp = &sin->sin_port; 102 break; 103 #ifdef INET6 104 case AF_INET6: 105 proto = IPPROTO_IPV6; 106 portrange = IPV6_PORTRANGE; 107 portlow = IPV6_PORTRANGE_LOW; 108 sin6 = (struct sockaddr_in6 *)sa; 109 salen = sizeof(struct sockaddr_in6); 110 portp = &sin6->sin6_port; 111 break; 112 #endif 113 default: 114 errno = EPFNOSUPPORT; 115 return (-1); 116 } 117 sa->sa_family = af; 118 sa->sa_len = salen; 119 120 if (*portp == 0) { 121 socklen_t oldlen = sizeof(old); 122 123 error = _getsockopt(sd, proto, portrange, &old, &oldlen); 124 if (error < 0) 125 return (error); 126 127 error = _setsockopt(sd, proto, portrange, &portlow, 128 sizeof(portlow)); 129 if (error < 0) 130 return (error); 131 } 132 133 error = _bind(sd, sa, salen); 134 135 if (*portp == 0) { 136 int saved_errno = errno; 137 138 if (error < 0) { 139 if (_setsockopt(sd, proto, portrange, &old, 140 sizeof(old)) < 0) 141 errno = saved_errno; 142 return (error); 143 } 144 145 if (sa != (struct sockaddr *)&myaddr) { 146 /* Hmm, what did the kernel assign? */ 147 if (_getsockname(sd, sa, &salen) < 0) 148 errno = saved_errno; 149 return (error); 150 } 151 } 152 return (error); 153 } 154