bindresvport.c revision 106121
198937Sdes/* This file has be modified from the original OpenBSD source */ 298937Sdes 398937Sdes/* 498937Sdes * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 598937Sdes * unrestricted use provided that this legend is included on all tape 698937Sdes * media and as a part of the software program in whole or part. Users 798937Sdes * may copy or modify Sun RPC without charge, but are not authorized 898937Sdes * to license or distribute it to anyone else except as part of a product or 998937Sdes * program developed by the user. 1098937Sdes * 1198937Sdes * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 1298937Sdes * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 1398937Sdes * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 1498937Sdes * 1598937Sdes * Sun RPC is provided with no support and without any obligation on the 1698937Sdes * part of Sun Microsystems, Inc. to assist in its use, correction, 1798937Sdes * modification or enhancement. 1898937Sdes * 1998937Sdes * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 2098937Sdes * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 2198937Sdes * OR ANY PART THEREOF. 2298937Sdes * 2398937Sdes * In no event will Sun Microsystems, Inc. be liable for any lost revenue 2498937Sdes * or profits or other special, indirect and consequential damages, even if 2598937Sdes * Sun has been advised of the possibility of such damages. 2698937Sdes * 2798937Sdes * Sun Microsystems, Inc. 2898937Sdes * 2550 Garcia Avenue 2998937Sdes * Mountain View, California 94043 3098937Sdes */ 3198937Sdes 32106121Sdes#include "includes.h" 3398937Sdes 3498937Sdes#ifndef HAVE_BINDRESVPORT_SA 3598937Sdes 3698937Sdes#if defined(LIBC_SCCS) && !defined(lint) 3798937Sdesstatic char *rcsid = "$OpenBSD: bindresvport.c,v 1.13 2000/01/26 03:43:21 deraadt Exp $"; 3898937Sdes#endif /* LIBC_SCCS and not lint */ 3998937Sdes 4098937Sdes/* 4198937Sdes * Copyright (c) 1987 by Sun Microsystems, Inc. 4298937Sdes * 4398937Sdes * Portions Copyright(C) 1996, Jason Downs. All rights reserved. 4498937Sdes */ 4598937Sdes 4698937Sdes#include "includes.h" 4798937Sdes 4898937Sdes#define STARTPORT 600 4998937Sdes#define ENDPORT (IPPORT_RESERVED - 1) 5098937Sdes#define NPORTS (ENDPORT - STARTPORT + 1) 5198937Sdes 5298937Sdes/* 5398937Sdes * Bind a socket to a privileged IP port 5498937Sdes */ 5598937Sdesint 5698937Sdesbindresvport_sa(sd, sa) 5798937Sdes int sd; 5898937Sdes struct sockaddr *sa; 5998937Sdes{ 6098937Sdes int error, af; 6198937Sdes struct sockaddr_storage myaddr; 6298937Sdes struct sockaddr_in *sin; 6398937Sdes struct sockaddr_in6 *sin6; 6498937Sdes u_int16_t *portp; 6598937Sdes u_int16_t port; 6698937Sdes socklen_t salen; 6798937Sdes int i; 6898937Sdes 6998937Sdes if (sa == NULL) { 7098937Sdes memset(&myaddr, 0, sizeof(myaddr)); 7198937Sdes sa = (struct sockaddr *)&myaddr; 7298937Sdes 7398937Sdes if (getsockname(sd, sa, &salen) == -1) 7498937Sdes return -1; /* errno is correctly set */ 7598937Sdes 7698937Sdes af = sa->sa_family; 7798937Sdes memset(&myaddr, 0, salen); 7898937Sdes } else 7998937Sdes af = sa->sa_family; 8098937Sdes 8198937Sdes if (af == AF_INET) { 8298937Sdes sin = (struct sockaddr_in *)sa; 8398937Sdes salen = sizeof(struct sockaddr_in); 8498937Sdes portp = &sin->sin_port; 8598937Sdes } else if (af == AF_INET6) { 8698937Sdes sin6 = (struct sockaddr_in6 *)sa; 8798937Sdes salen = sizeof(struct sockaddr_in6); 8898937Sdes portp = &sin6->sin6_port; 8998937Sdes } else { 9098937Sdes errno = EPFNOSUPPORT; 9198937Sdes return (-1); 9298937Sdes } 9398937Sdes sa->sa_family = af; 9498937Sdes 9598937Sdes port = ntohs(*portp); 9698937Sdes if (port == 0) 9798937Sdes port = (arc4random() % NPORTS) + STARTPORT; 9898937Sdes 9998937Sdes /* Avoid warning */ 10098937Sdes error = -1; 10198937Sdes 10298937Sdes for(i = 0; i < NPORTS; i++) { 10398937Sdes *portp = htons(port); 10498937Sdes 10598937Sdes error = bind(sd, sa, salen); 10698937Sdes 10798937Sdes /* Terminate on success */ 10898937Sdes if (error == 0) 10998937Sdes break; 11098937Sdes 11198937Sdes /* Terminate on errors, except "address already in use" */ 11298937Sdes if ((error < 0) && !((errno == EADDRINUSE) || (errno == EINVAL))) 11398937Sdes break; 11498937Sdes 11598937Sdes port++; 11698937Sdes if (port > ENDPORT) 11798937Sdes port = STARTPORT; 11898937Sdes } 11998937Sdes 12098937Sdes return (error); 12198937Sdes} 12298937Sdes 12398937Sdes#endif /* HAVE_BINDRESVPORT_SA */ 124