11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* This file has be substantially modified from the original OpenBSD source */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*	$OpenBSD: bindresvport.c,v 1.17 2005/12/21 01:40:22 millert Exp $	*/
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright 1996, Jason Downs.  All rights reserved.
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright 1998, Theo de Raadt.  All rights reserved.
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright 2000, Damien Miller.  All rights reserved.
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Redistribution and use in source and binary forms, with or without
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * modification, are permitted provided that the following conditions
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * are met:
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 1. Redistributions of source code must retain the above copyright
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer.
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 2. Redistributions in binary form must reproduce the above copyright
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    notice, this list of conditions and the following disclaimer in the
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *    documentation and/or other materials provided with the distribution.
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* OPENBSD ORIGINAL: lib/libc/rpc/bindresvport.c */
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef HAVE_BINDRESVPORT_SA
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/socket.h>
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <netinet/in.h>
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <arpa/inet.h>
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h>
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define STARTPORT 600
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define ENDPORT (IPPORT_RESERVED - 1)
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define NPORTS	(ENDPORT - STARTPORT + 1)
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Bind a socket to a privileged IP port
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodbindresvport_sa(int sd, struct sockaddr *sa)
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int error, af;
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct sockaddr_storage myaddr;
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct sockaddr_in *in;
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct sockaddr_in6 *in6;
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int16_t *portp;
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int16_t port;
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	socklen_t salen;
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (sa == NULL) {
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memset(&myaddr, 0, sizeof(myaddr));
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		sa = (struct sockaddr *)&myaddr;
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (getsockname(sd, sa, &salen) == -1)
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;	/* errno is correctly set */
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		af = sa->sa_family;
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memset(&myaddr, 0, salen);
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		af = sa->sa_family;
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (af == AF_INET) {
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		in = (struct sockaddr_in *)sa;
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		salen = sizeof(struct sockaddr_in);
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		portp = &in->sin_port;
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (af == AF_INET6) {
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		in6 = (struct sockaddr_in6 *)sa;
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		salen = sizeof(struct sockaddr_in6);
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		portp = &in6->sin6_port;
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		errno = EPFNOSUPPORT;
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sa->sa_family = af;
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	port = ntohs(*portp);
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (port == 0)
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		port = arc4random_uniform(NPORTS) + STARTPORT;
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Avoid warning */
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	error = -1;
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for(i = 0; i < NPORTS; i++) {
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*portp = htons(port);
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error = bind(sd, sa, salen);
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Terminate on success */
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (error == 0)
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Terminate on errors, except "address already in use" */
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if ((error < 0) && !((errno == EADDRINUSE) || (errno == EINVAL)))
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		port++;
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (port > ENDPORT)
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			port = STARTPORT;
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (error);
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* HAVE_BINDRESVPORT_SA */
119