find_interface.c revision 21673
190075Sobrien/*
2169689Skan * Copyright 1994, 1995 Massachusetts Institute of Technology
3132718Skan *
490075Sobrien * Permission to use, copy, modify, and distribute this software and
590075Sobrien * its documentation for any purpose and without fee is hereby
690075Sobrien * granted, provided that both the above copyright notice and this
790075Sobrien * permission notice appear in all copies, that both the above
890075Sobrien * copyright notice and this permission notice appear in all
990075Sobrien * supporting documentation, and that the name of M.I.T. not be used
1090075Sobrien * in advertising or publicity pertaining to distribution of the
1190075Sobrien * software without specific, written prior permission.  M.I.T. makes
1290075Sobrien * no representations about the suitability of this software for any
1390075Sobrien * purpose.  It is provided "as is" without express or implied
1490075Sobrien * warranty.
1590075Sobrien *
1690075Sobrien * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
1790075Sobrien * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
1890075Sobrien * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19169689Skan * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
20169689Skan * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2190075Sobrien * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2290075Sobrien * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
2390075Sobrien * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2490075Sobrien * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2590075Sobrien * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
2690075Sobrien * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27132718Skan * SUCH DAMAGE.
2890075Sobrien *
2990075Sobrien * $FreeBSD: head/share/examples/find_interface/find_interface.c 21673 1997-01-14 07:20:47Z jkh $
30132718Skan */
31117395Skan
32132718Skan/*
33161651Skan * This is a simple program which demonstrates how to query the kernel
34132718Skan * routing mechanism using only a UDP socket.  Pass it a hostname on
35117395Skan * the command line (sorry, it doesn't parse dotted decimal) and it will
36117395Skan * print out an IP address which names the interface over which UDP
37117395Skan * packets intended for that destination would be sent.
38132718Skan * A more sophisticated program might use the list obtained from SIOCGIFCONF
39132718Skan * to match the address with an interface name, but applications programmers
40132718Skan * much more often need to know the address of the interface rather than
41132718Skan * the name.
42132718Skan */
43132718Skan#include <sys/types.h>
44132718Skan#include <sys/socket.h>
45132718Skan#include <unistd.h>
46132718Skan#include <netinet/in.h>
47132718Skan#include <arpa/inet.h>
48132718Skan#include <stdlib.h>
49132718Skan#include <stdio.h>
50132718Skan#include <netdb.h>
51117395Skan#include <err.h>
52132718Skan#include <errno.h>
53132718Skan#include <string.h>
54132718Skan#include <sysexits.h>
55132718Skan
56132718Skanint
57132718Skanmain(int argc, char **argv)
58132718Skan{
59117395Skan	struct sockaddr_in local, remote;
60117395Skan	struct hostent *hp;
61117395Skan	int s, rv, namelen;
62117395Skan
6390075Sobrien	argc--, argv++;
64169689Skan
65169689Skan	if (!*argv) {
66169689Skan		errx(EX_USAGE, "must supply a hostname");
6790075Sobrien	}
6890075Sobrien
6990075Sobrien	hp = gethostbyname(*argv);
70132718Skan	if (!hp) {
7190075Sobrien		errx(EX_NOHOST, "cannot resolve hostname: %s", *argv);
72132718Skan	}
73132718Skan
74132718Skan	memcpy(&remote.sin_addr, hp->h_addr_list[0], sizeof remote.sin_addr);
75132718Skan	remote.sin_port = htons(60000);
76132718Skan	remote.sin_family = AF_INET;
77132718Skan	remote.sin_len = sizeof remote;
78132718Skan
79132718Skan	local.sin_addr.s_addr = htonl(INADDR_ANY);
80132718Skan	local.sin_port = htons(60000);
81132718Skan	local.sin_family = AF_INET;
82132718Skan	local.sin_len = sizeof local;
8390075Sobrien
8490075Sobrien	s = socket(PF_INET, SOCK_DGRAM, 0);
8590075Sobrien	if (s < 0)
8690075Sobrien		err(EX_OSERR, "socket");
8790075Sobrien
88132718Skan	do {
8990075Sobrien		rv = bind(s, (struct sockaddr *)&local, sizeof local);
90117395Skan		local.sin_port = htons(ntohs(local.sin_port) + 1);
9190075Sobrien	} while(rv < 0 && errno == EADDRINUSE);
9290075Sobrien
93117395Skan	if (rv < 0)
94117395Skan		err(EX_OSERR, "bind");
95117395Skan
9690075Sobrien	do {
9790075Sobrien		rv = connect(s, (struct sockaddr *)&remote, sizeof remote);
9890075Sobrien		remote.sin_port = htons(ntohs(remote.sin_port) + 1);
9990075Sobrien	} while(rv < 0 && errno == EADDRINUSE);
10090075Sobrien
10190075Sobrien	if (rv < 0)
10290075Sobrien		err(EX_OSERR, "connect");
103132718Skan
10490075Sobrien	namelen = sizeof local;
105117395Skan	rv = getsockname(s, (struct sockaddr *)&local, &namelen);
106117395Skan	if (rv < 0)
107117395Skan		err(EX_OSERR, "getsockname");
108117395Skan
109117395Skan	printf("Route to %s is out %s\n", *argv, inet_ntoa(local.sin_addr));
11090075Sobrien	return 0;
111117395Skan}
112117395Skan