110058Swollman/*
210058Swollman * Copyright 1994, 1995 Massachusetts Institute of Technology
310058Swollman *
410058Swollman * Permission to use, copy, modify, and distribute this software and
510058Swollman * its documentation for any purpose and without fee is hereby
610058Swollman * granted, provided that both the above copyright notice and this
710058Swollman * permission notice appear in all copies, that both the above
810058Swollman * copyright notice and this permission notice appear in all
910058Swollman * supporting documentation, and that the name of M.I.T. not be used
1010058Swollman * in advertising or publicity pertaining to distribution of the
1110058Swollman * software without specific, written prior permission.  M.I.T. makes
1210058Swollman * no representations about the suitability of this software for any
1310058Swollman * purpose.  It is provided "as is" without express or implied
1410058Swollman * warranty.
1510058Swollman *
1610058Swollman * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
1710058Swollman * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
1810058Swollman * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1910058Swollman * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
2010058Swollman * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2110058Swollman * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210058Swollman * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
2310058Swollman * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2410058Swollman * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2510058Swollman * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
2610058Swollman * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2710058Swollman * SUCH DAMAGE.
2810058Swollman *
2950476Speter * $FreeBSD: releng/10.3/share/examples/find_interface/find_interface.c 50476 1999-08-28 00:22:10Z peter $
3010058Swollman */
3110058Swollman
3210058Swollman/*
3310058Swollman * This is a simple program which demonstrates how to query the kernel
3410058Swollman * routing mechanism using only a UDP socket.  Pass it a hostname on
3510058Swollman * the command line (sorry, it doesn't parse dotted decimal) and it will
3610058Swollman * print out an IP address which names the interface over which UDP
3710058Swollman * packets intended for that destination would be sent.
3810058Swollman * A more sophisticated program might use the list obtained from SIOCGIFCONF
3910058Swollman * to match the address with an interface name, but applications programmers
4010058Swollman * much more often need to know the address of the interface rather than
4110058Swollman * the name.
4210058Swollman */
4310058Swollman#include <sys/types.h>
4410058Swollman#include <sys/socket.h>
4510058Swollman#include <unistd.h>
4610058Swollman#include <netinet/in.h>
4710058Swollman#include <arpa/inet.h>
4810058Swollman#include <stdlib.h>
4910058Swollman#include <stdio.h>
5010058Swollman#include <netdb.h>
5110058Swollman#include <err.h>
5210058Swollman#include <errno.h>
5310058Swollman#include <string.h>
5410058Swollman#include <sysexits.h>
5510058Swollman
5610058Swollmanint
5710058Swollmanmain(int argc, char **argv)
5810058Swollman{
5910058Swollman	struct sockaddr_in local, remote;
6010058Swollman	struct hostent *hp;
6110058Swollman	int s, rv, namelen;
6210058Swollman
6310058Swollman	argc--, argv++;
6410058Swollman
6510058Swollman	if (!*argv) {
6610058Swollman		errx(EX_USAGE, "must supply a hostname");
6710058Swollman	}
6810058Swollman
6910058Swollman	hp = gethostbyname(*argv);
7010058Swollman	if (!hp) {
7110058Swollman		errx(EX_NOHOST, "cannot resolve hostname: %s", *argv);
7210058Swollman	}
7310058Swollman
7410058Swollman	memcpy(&remote.sin_addr, hp->h_addr_list[0], sizeof remote.sin_addr);
7510058Swollman	remote.sin_port = htons(60000);
7610058Swollman	remote.sin_family = AF_INET;
7710058Swollman	remote.sin_len = sizeof remote;
7810058Swollman
7910058Swollman	local.sin_addr.s_addr = htonl(INADDR_ANY);
8010058Swollman	local.sin_port = htons(60000);
8110058Swollman	local.sin_family = AF_INET;
8210058Swollman	local.sin_len = sizeof local;
8310058Swollman
8410058Swollman	s = socket(PF_INET, SOCK_DGRAM, 0);
8510058Swollman	if (s < 0)
8610058Swollman		err(EX_OSERR, "socket");
8710058Swollman
8810058Swollman	do {
8910058Swollman		rv = bind(s, (struct sockaddr *)&local, sizeof local);
9014585Sache		local.sin_port = htons(ntohs(local.sin_port) + 1);
9110058Swollman	} while(rv < 0 && errno == EADDRINUSE);
9210058Swollman
9310058Swollman	if (rv < 0)
9410058Swollman		err(EX_OSERR, "bind");
9510058Swollman
9610058Swollman	do {
9710058Swollman		rv = connect(s, (struct sockaddr *)&remote, sizeof remote);
9814585Sache		remote.sin_port = htons(ntohs(remote.sin_port) + 1);
9910058Swollman	} while(rv < 0 && errno == EADDRINUSE);
10010058Swollman
10110058Swollman	if (rv < 0)
10210058Swollman		err(EX_OSERR, "connect");
10310058Swollman
10410058Swollman	namelen = sizeof local;
10510058Swollman	rv = getsockname(s, (struct sockaddr *)&local, &namelen);
10610058Swollman	if (rv < 0)
10710058Swollman		err(EX_OSERR, "getsockname");
10810058Swollman
10910058Swollman	printf("Route to %s is out %s\n", *argv, inet_ntoa(local.sin_addr));
11010058Swollman	return 0;
11110058Swollman}
112