bindresvport.c revision 157016
1124208Sdes/* This file has be substantially modified from the original OpenBSD source */ 298937Sdes 3157016Sdes/* $OpenBSD: bindresvport.c,v 1.16 2005/04/01 07:44:03 otto Exp $ */ 4124208Sdes 598937Sdes/* 6124208Sdes * Copyright 1996, Jason Downs. All rights reserved. 7124208Sdes * Copyright 1998, Theo de Raadt. All rights reserved. 8124208Sdes * Copyright 2000, Damien Miller. All rights reserved. 9124208Sdes * 10124208Sdes * Redistribution and use in source and binary forms, with or without 11124208Sdes * modification, are permitted provided that the following conditions 12124208Sdes * are met: 13124208Sdes * 1. Redistributions of source code must retain the above copyright 14124208Sdes * notice, this list of conditions and the following disclaimer. 15124208Sdes * 2. Redistributions in binary form must reproduce the above copyright 16124208Sdes * notice, this list of conditions and the following disclaimer in the 17124208Sdes * documentation and/or other materials provided with the distribution. 18124208Sdes * 19124208Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20124208Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21124208Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22124208Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23124208Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24124208Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25124208Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26124208Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27124208Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28124208Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2998937Sdes */ 3098937Sdes 31157016Sdes/* OPENBSD ORIGINAL: lib/libc/rpc/bindresvport.c */ 32157016Sdes 33106121Sdes#include "includes.h" 3498937Sdes 3598937Sdes#ifndef HAVE_BINDRESVPORT_SA 3698937Sdes 3798937Sdes#include "includes.h" 3898937Sdes 3998937Sdes#define STARTPORT 600 4098937Sdes#define ENDPORT (IPPORT_RESERVED - 1) 4198937Sdes#define NPORTS (ENDPORT - STARTPORT + 1) 4298937Sdes 4398937Sdes/* 4498937Sdes * Bind a socket to a privileged IP port 4598937Sdes */ 4698937Sdesint 47157016Sdesbindresvport_sa(int sd, struct sockaddr *sa) 4898937Sdes{ 4998937Sdes int error, af; 5098937Sdes struct sockaddr_storage myaddr; 5198937Sdes struct sockaddr_in *sin; 5298937Sdes struct sockaddr_in6 *sin6; 5398937Sdes u_int16_t *portp; 5498937Sdes u_int16_t port; 5598937Sdes socklen_t salen; 5698937Sdes int i; 5798937Sdes 5898937Sdes if (sa == NULL) { 5998937Sdes memset(&myaddr, 0, sizeof(myaddr)); 6098937Sdes sa = (struct sockaddr *)&myaddr; 6198937Sdes 6298937Sdes if (getsockname(sd, sa, &salen) == -1) 6398937Sdes return -1; /* errno is correctly set */ 6498937Sdes 6598937Sdes af = sa->sa_family; 6698937Sdes memset(&myaddr, 0, salen); 6798937Sdes } else 6898937Sdes af = sa->sa_family; 6998937Sdes 7098937Sdes if (af == AF_INET) { 7198937Sdes sin = (struct sockaddr_in *)sa; 7298937Sdes salen = sizeof(struct sockaddr_in); 7398937Sdes portp = &sin->sin_port; 7498937Sdes } else if (af == AF_INET6) { 7598937Sdes sin6 = (struct sockaddr_in6 *)sa; 7698937Sdes salen = sizeof(struct sockaddr_in6); 7798937Sdes portp = &sin6->sin6_port; 7898937Sdes } else { 7998937Sdes errno = EPFNOSUPPORT; 8098937Sdes return (-1); 8198937Sdes } 8298937Sdes sa->sa_family = af; 8398937Sdes 8498937Sdes port = ntohs(*portp); 8598937Sdes if (port == 0) 8698937Sdes port = (arc4random() % NPORTS) + STARTPORT; 8798937Sdes 8898937Sdes /* Avoid warning */ 8998937Sdes error = -1; 9098937Sdes 9198937Sdes for(i = 0; i < NPORTS; i++) { 9298937Sdes *portp = htons(port); 9398937Sdes 9498937Sdes error = bind(sd, sa, salen); 9598937Sdes 9698937Sdes /* Terminate on success */ 9798937Sdes if (error == 0) 9898937Sdes break; 9998937Sdes 10098937Sdes /* Terminate on errors, except "address already in use" */ 10198937Sdes if ((error < 0) && !((errno == EADDRINUSE) || (errno == EINVAL))) 10298937Sdes break; 10398937Sdes 10498937Sdes port++; 10598937Sdes if (port > ENDPORT) 10698937Sdes port = STARTPORT; 10798937Sdes } 10898937Sdes 10998937Sdes return (error); 11098937Sdes} 11198937Sdes 11298937Sdes#endif /* HAVE_BINDRESVPORT_SA */ 113