1157016Sdes/* $OpenBSD: rresvport.c,v 1.9 2005/11/10 10:00:17 espie Exp $ */
298937Sdes/*
398937Sdes * Copyright (c) 1995, 1996, 1998 Theo de Raadt.  All rights reserved.
498937Sdes * Copyright (c) 1983, 1993, 1994
598937Sdes *	The Regents of the University of California.  All rights reserved.
698937Sdes *
798937Sdes * Redistribution and use in source and binary forms, with or without
898937Sdes * modification, are permitted provided that the following conditions
998937Sdes * are met:
1098937Sdes * 1. Redistributions of source code must retain the above copyright
1198937Sdes *    notice, this list of conditions and the following disclaimer.
1298937Sdes * 2. Redistributions in binary form must reproduce the above copyright
1398937Sdes *    notice, this list of conditions and the following disclaimer in the
1498937Sdes *    documentation and/or other materials provided with the distribution.
15124208Sdes * 3. Neither the name of the University nor the names of its contributors
1698937Sdes *    may be used to endorse or promote products derived from this software
1798937Sdes *    without specific prior written permission.
1898937Sdes *
1998937Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2098937Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2198937Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2298937Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2398937Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2498937Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2598937Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2698937Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2798937Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2898937Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2998937Sdes * SUCH DAMAGE.
3098937Sdes */
3198937Sdes
32157016Sdes/* OPENBSD ORIGINAL: lib/libc/net/rresvport.c */
33157016Sdes
34106121Sdes#include "includes.h"
3598937Sdes
3698937Sdes#ifndef HAVE_RRESVPORT_AF
3798937Sdes
38162852Sdes#include <sys/types.h>
39162852Sdes#include <sys/socket.h>
40162852Sdes
41162852Sdes#include <netinet/in.h>
42162852Sdes#include <arpa/inet.h>
43162852Sdes
44162852Sdes#include <errno.h>
45162852Sdes#include <stdlib.h>
46162852Sdes#include <string.h>
47181111Sdes#include <unistd.h>
48162852Sdes
4998937Sdes#if 0
5098937Sdesint
51157016Sdesrresvport(int *alport)
5298937Sdes{
5398937Sdes	return rresvport_af(alport, AF_INET);
5498937Sdes}
5598937Sdes#endif
5698937Sdes
57157016Sdesint
5898937Sdesrresvport_af(int *alport, sa_family_t af)
5998937Sdes{
6098937Sdes	struct sockaddr_storage ss;
6198937Sdes	struct sockaddr *sa;
6298937Sdes	u_int16_t *portp;
6398937Sdes	int s;
6498937Sdes	socklen_t salen;
6598937Sdes
6698937Sdes	memset(&ss, '\0', sizeof ss);
6798937Sdes	sa = (struct sockaddr *)&ss;
6898937Sdes
6998937Sdes	switch (af) {
7098937Sdes	case AF_INET:
7198937Sdes		salen = sizeof(struct sockaddr_in);
7298937Sdes		portp = &((struct sockaddr_in *)sa)->sin_port;
7398937Sdes		break;
7498937Sdes	case AF_INET6:
7598937Sdes		salen = sizeof(struct sockaddr_in6);
7698937Sdes		portp = &((struct sockaddr_in6 *)sa)->sin6_port;
7798937Sdes		break;
7898937Sdes	default:
7998937Sdes		errno = EPFNOSUPPORT;
8098937Sdes		return (-1);
8198937Sdes	}
8298937Sdes	sa->sa_family = af;
8398937Sdes
8498937Sdes	s = socket(af, SOCK_STREAM, 0);
8598937Sdes	if (s < 0)
8698937Sdes		return (-1);
8798937Sdes
8898937Sdes	*portp = htons(*alport);
8998937Sdes	if (*alport < IPPORT_RESERVED - 1) {
9098937Sdes		if (bind(s, sa, salen) >= 0)
9198937Sdes			return (s);
9298937Sdes		if (errno != EADDRINUSE) {
9398937Sdes			(void)close(s);
9498937Sdes			return (-1);
9598937Sdes		}
9698937Sdes	}
9798937Sdes
9898937Sdes	*portp = 0;
9998937Sdes	sa->sa_family = af;
10098937Sdes	if (bindresvport_sa(s, sa) == -1) {
10198937Sdes		(void)close(s);
10298937Sdes		return (-1);
10398937Sdes	}
10498937Sdes	*alport = ntohs(*portp);
10598937Sdes	return (s);
10698937Sdes}
10798937Sdes
10898937Sdes#endif /* HAVE_RRESVPORT_AF */
109