bindresvport.c revision 106121
138032Speter/* This file has be modified from the original OpenBSD source */
2223067Sgshapiro
364565Sgshapiro/*
438032Speter * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
538032Speter * unrestricted use provided that this legend is included on all tape
638032Speter * media and as a part of the software program in whole or part.  Users
738032Speter * may copy or modify Sun RPC without charge, but are not authorized
838032Speter * to license or distribute it to anyone else except as part of a product or
938032Speter * program developed by the user.
1038032Speter *
1138032Speter * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
1238032Speter * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
1338032Speter * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1490795Sgshapiro *
1538032Speter * Sun RPC is provided with no support and without any obligation on the
16223067Sgshapiro * part of Sun Microsystems, Inc. to assist in its use, correction,
1790795Sgshapiro * modification or enhancement.
1890795Sgshapiro *
1964565Sgshapiro * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
2064565Sgshapiro * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
2164565Sgshapiro * OR ANY PART THEREOF.
2264565Sgshapiro *
2364565Sgshapiro * In no event will Sun Microsystems, Inc. be liable for any lost revenue
2464565Sgshapiro * or profits or other special, indirect and consequential damages, even if
2564565Sgshapiro * Sun has been advised of the possibility of such damages.
2664565Sgshapiro *
2764565Sgshapiro * Sun Microsystems, Inc.
2838032Speter * 2550 Garcia Avenue
2990795Sgshapiro * Mountain View, California  94043
3090795Sgshapiro */
3190795Sgshapiro
3290795Sgshapiro#include "includes.h"
3390795Sgshapiro
3490795Sgshapiro#ifndef HAVE_BINDRESVPORT_SA
3590795Sgshapiro
3690795Sgshapiro#if defined(LIBC_SCCS) && !defined(lint)
3790795Sgshapirostatic char *rcsid = "$OpenBSD: bindresvport.c,v 1.13 2000/01/26 03:43:21 deraadt Exp $";
3890795Sgshapiro#endif /* LIBC_SCCS and not lint */
3990795Sgshapiro
4090795Sgshapiro/*
4190795Sgshapiro * Copyright (c) 1987 by Sun Microsystems, Inc.
4290795Sgshapiro *
4390795Sgshapiro * Portions Copyright(C) 1996, Jason Downs.  All rights reserved.
4490795Sgshapiro */
4590795Sgshapiro
4690795Sgshapiro#include "includes.h"
4790795Sgshapiro
4890795Sgshapiro#define STARTPORT 600
4990795Sgshapiro#define ENDPORT (IPPORT_RESERVED - 1)
5090795Sgshapiro#define NPORTS	(ENDPORT - STARTPORT + 1)
5190795Sgshapiro
5290795Sgshapiro/*
5390795Sgshapiro * Bind a socket to a privileged IP port
5490795Sgshapiro */
5590795Sgshapiroint
5690795Sgshapirobindresvport_sa(sd, sa)
5790795Sgshapiro	int sd;
5890795Sgshapiro	struct sockaddr *sa;
5990795Sgshapiro{
6090795Sgshapiro	int error, af;
6190795Sgshapiro	struct sockaddr_storage myaddr;
6290795Sgshapiro	struct sockaddr_in *sin;
6390795Sgshapiro	struct sockaddr_in6 *sin6;
6490795Sgshapiro	u_int16_t *portp;
6590795Sgshapiro	u_int16_t port;
6690795Sgshapiro	socklen_t salen;
6790795Sgshapiro	int i;
6890795Sgshapiro
6990795Sgshapiro	if (sa == NULL) {
7090795Sgshapiro		memset(&myaddr, 0, sizeof(myaddr));
7190795Sgshapiro		sa = (struct sockaddr *)&myaddr;
7290795Sgshapiro
7390795Sgshapiro		if (getsockname(sd, sa, &salen) == -1)
7490795Sgshapiro			return -1;	/* errno is correctly set */
7590795Sgshapiro
7690795Sgshapiro		af = sa->sa_family;
7790795Sgshapiro		memset(&myaddr, 0, salen);
7890795Sgshapiro	} else
7990795Sgshapiro		af = sa->sa_family;
8090795Sgshapiro
8190795Sgshapiro	if (af == AF_INET) {
8238032Speter		sin = (struct sockaddr_in *)sa;
8338032Speter		salen = sizeof(struct sockaddr_in);
8490795Sgshapiro		portp = &sin->sin_port;
8538032Speter	} else if (af == AF_INET6) {
8638032Speter		sin6 = (struct sockaddr_in6 *)sa;
8738032Speter		salen = sizeof(struct sockaddr_in6);
8838032Speter		portp = &sin6->sin6_port;
8938032Speter	} else {
9038032Speter		errno = EPFNOSUPPORT;
9190795Sgshapiro		return (-1);
9290795Sgshapiro	}
9390795Sgshapiro	sa->sa_family = af;
9490795Sgshapiro
9590795Sgshapiro	port = ntohs(*portp);
9638032Speter	if (port == 0)
9790795Sgshapiro		port = (arc4random() % NPORTS) + STARTPORT;
9890795Sgshapiro
9990795Sgshapiro	/* Avoid warning */
10038032Speter	error = -1;
10138032Speter
10238032Speter	for(i = 0; i < NPORTS; i++) {
10338032Speter		*portp = htons(port);
10490795Sgshapiro
10538032Speter		error = bind(sd, sa, salen);
10638032Speter
10738032Speter		/* Terminate on success */
10838032Speter		if (error == 0)
10938032Speter			break;
11038032Speter
11164565Sgshapiro		/* Terminate on errors, except "address already in use" */
112168520Sgshapiro		if ((error < 0) && !((errno == EADDRINUSE) || (errno == EINVAL)))
11338032Speter			break;
11438032Speter
11538032Speter		port++;
11664565Sgshapiro		if (port > ENDPORT)
11738032Speter			port = STARTPORT;
11838032Speter	}
11938032Speter
12038032Speter	return (error);
12138032Speter}
12264565Sgshapiro
12338032Speter#endif /* HAVE_BINDRESVPORT_SA */
12438032Speter