1d95e11bfSDag-Erling Smørgrav /* This file has be substantially modified from the original OpenBSD source */ 2d95e11bfSDag-Erling Smørgrav 3d4af9e69SDag-Erling Smørgrav /* $OpenBSD: bindresvport.c,v 1.17 2005/12/21 01:40:22 millert Exp $ */ 483d2307dSDag-Erling Smørgrav 583d2307dSDag-Erling Smørgrav /* 6d95e11bfSDag-Erling Smørgrav * Copyright 1996, Jason Downs. All rights reserved. 7d95e11bfSDag-Erling Smørgrav * Copyright 1998, Theo de Raadt. All rights reserved. 8d95e11bfSDag-Erling Smørgrav * Copyright 2000, Damien Miller. All rights reserved. 983d2307dSDag-Erling Smørgrav * 10d95e11bfSDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 11d95e11bfSDag-Erling Smørgrav * modification, are permitted provided that the following conditions 12d95e11bfSDag-Erling Smørgrav * are met: 13d95e11bfSDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 14d95e11bfSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 15d95e11bfSDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 16d95e11bfSDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 17d95e11bfSDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 1883d2307dSDag-Erling Smørgrav * 19d95e11bfSDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20d95e11bfSDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21d95e11bfSDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22d95e11bfSDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23d95e11bfSDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24d95e11bfSDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25d95e11bfSDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26d95e11bfSDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27d95e11bfSDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28d95e11bfSDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2983d2307dSDag-Erling Smørgrav */ 3083d2307dSDag-Erling Smørgrav 31021d409fSDag-Erling Smørgrav /* OPENBSD ORIGINAL: lib/libc/rpc/bindresvport.c */ 32021d409fSDag-Erling Smørgrav 334b17dab0SDag-Erling Smørgrav #include "includes.h" 3483d2307dSDag-Erling Smørgrav 3583d2307dSDag-Erling Smørgrav #ifndef HAVE_BINDRESVPORT_SA 36761efaa7SDag-Erling Smørgrav #include <sys/types.h> 37761efaa7SDag-Erling Smørgrav #include <sys/socket.h> 3883d2307dSDag-Erling Smørgrav 39761efaa7SDag-Erling Smørgrav #include <netinet/in.h> 40761efaa7SDag-Erling Smørgrav #include <arpa/inet.h> 41761efaa7SDag-Erling Smørgrav 42761efaa7SDag-Erling Smørgrav #include <errno.h> 43761efaa7SDag-Erling Smørgrav #include <string.h> 4483d2307dSDag-Erling Smørgrav 4583d2307dSDag-Erling Smørgrav #define STARTPORT 600 4683d2307dSDag-Erling Smørgrav #define ENDPORT (IPPORT_RESERVED - 1) 4783d2307dSDag-Erling Smørgrav #define NPORTS (ENDPORT - STARTPORT + 1) 4883d2307dSDag-Erling Smørgrav 4983d2307dSDag-Erling Smørgrav /* 5083d2307dSDag-Erling Smørgrav * Bind a socket to a privileged IP port 5183d2307dSDag-Erling Smørgrav */ 5283d2307dSDag-Erling Smørgrav int 53021d409fSDag-Erling Smørgrav bindresvport_sa(int sd, struct sockaddr *sa) 5483d2307dSDag-Erling Smørgrav { 5583d2307dSDag-Erling Smørgrav int error, af; 5683d2307dSDag-Erling Smørgrav struct sockaddr_storage myaddr; 57d4af9e69SDag-Erling Smørgrav struct sockaddr_in *in; 58d4af9e69SDag-Erling Smørgrav struct sockaddr_in6 *in6; 5983d2307dSDag-Erling Smørgrav u_int16_t *portp; 6083d2307dSDag-Erling Smørgrav u_int16_t port; 6183d2307dSDag-Erling Smørgrav socklen_t salen; 6283d2307dSDag-Erling Smørgrav int i; 6383d2307dSDag-Erling Smørgrav 6483d2307dSDag-Erling Smørgrav if (sa == NULL) { 6583d2307dSDag-Erling Smørgrav memset(&myaddr, 0, sizeof(myaddr)); 6683d2307dSDag-Erling Smørgrav sa = (struct sockaddr *)&myaddr; 67*076ad2f8SDag-Erling Smørgrav salen = sizeof(myaddr); 6883d2307dSDag-Erling Smørgrav 6983d2307dSDag-Erling Smørgrav if (getsockname(sd, sa, &salen) == -1) 7083d2307dSDag-Erling Smørgrav return -1; /* errno is correctly set */ 7183d2307dSDag-Erling Smørgrav 7283d2307dSDag-Erling Smørgrav af = sa->sa_family; 7383d2307dSDag-Erling Smørgrav memset(&myaddr, 0, salen); 7483d2307dSDag-Erling Smørgrav } else 7583d2307dSDag-Erling Smørgrav af = sa->sa_family; 7683d2307dSDag-Erling Smørgrav 7783d2307dSDag-Erling Smørgrav if (af == AF_INET) { 78d4af9e69SDag-Erling Smørgrav in = (struct sockaddr_in *)sa; 7983d2307dSDag-Erling Smørgrav salen = sizeof(struct sockaddr_in); 80d4af9e69SDag-Erling Smørgrav portp = &in->sin_port; 8183d2307dSDag-Erling Smørgrav } else if (af == AF_INET6) { 82d4af9e69SDag-Erling Smørgrav in6 = (struct sockaddr_in6 *)sa; 8383d2307dSDag-Erling Smørgrav salen = sizeof(struct sockaddr_in6); 84d4af9e69SDag-Erling Smørgrav portp = &in6->sin6_port; 8583d2307dSDag-Erling Smørgrav } else { 8683d2307dSDag-Erling Smørgrav errno = EPFNOSUPPORT; 8783d2307dSDag-Erling Smørgrav return (-1); 8883d2307dSDag-Erling Smørgrav } 8983d2307dSDag-Erling Smørgrav sa->sa_family = af; 9083d2307dSDag-Erling Smørgrav 9183d2307dSDag-Erling Smørgrav port = ntohs(*portp); 9283d2307dSDag-Erling Smørgrav if (port == 0) 934a421b63SDag-Erling Smørgrav port = arc4random_uniform(NPORTS) + STARTPORT; 9483d2307dSDag-Erling Smørgrav 9583d2307dSDag-Erling Smørgrav /* Avoid warning */ 9683d2307dSDag-Erling Smørgrav error = -1; 9783d2307dSDag-Erling Smørgrav 9883d2307dSDag-Erling Smørgrav for(i = 0; i < NPORTS; i++) { 9983d2307dSDag-Erling Smørgrav *portp = htons(port); 10083d2307dSDag-Erling Smørgrav 10183d2307dSDag-Erling Smørgrav error = bind(sd, sa, salen); 10283d2307dSDag-Erling Smørgrav 10383d2307dSDag-Erling Smørgrav /* Terminate on success */ 10483d2307dSDag-Erling Smørgrav if (error == 0) 10583d2307dSDag-Erling Smørgrav break; 10683d2307dSDag-Erling Smørgrav 10783d2307dSDag-Erling Smørgrav /* Terminate on errors, except "address already in use" */ 10883d2307dSDag-Erling Smørgrav if ((error < 0) && !((errno == EADDRINUSE) || (errno == EINVAL))) 10983d2307dSDag-Erling Smørgrav break; 11083d2307dSDag-Erling Smørgrav 11183d2307dSDag-Erling Smørgrav port++; 11283d2307dSDag-Erling Smørgrav if (port > ENDPORT) 11383d2307dSDag-Erling Smørgrav port = STARTPORT; 11483d2307dSDag-Erling Smørgrav } 11583d2307dSDag-Erling Smørgrav 11683d2307dSDag-Erling Smørgrav return (error); 11783d2307dSDag-Erling Smørgrav } 11883d2307dSDag-Erling Smørgrav 11983d2307dSDag-Erling Smørgrav #endif /* HAVE_BINDRESVPORT_SA */ 120