1 |
/* $MidnightBSD$ */ |
2 |
/* |
3 |
* Copyright 1994, 1995 Massachusetts Institute of Technology |
4 |
* |
5 |
* Permission to use, copy, modify, and distribute this software and |
6 |
* its documentation for any purpose and without fee is hereby |
7 |
* granted, provided that both the above copyright notice and this |
8 |
* permission notice appear in all copies, that both the above |
9 |
* copyright notice and this permission notice appear in all |
10 |
* supporting documentation, and that the name of M.I.T. not be used |
11 |
* in advertising or publicity pertaining to distribution of the |
12 |
* software without specific, written prior permission. M.I.T. makes |
13 |
* no representations about the suitability of this software for any |
14 |
* purpose. It is provided "as is" without express or implied |
15 |
* warranty. |
16 |
* |
17 |
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS |
18 |
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, |
19 |
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
20 |
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT |
21 |
* SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
22 |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
23 |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
24 |
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
25 |
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
26 |
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
27 |
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
28 |
* SUCH DAMAGE. |
29 |
* |
30 |
* $FreeBSD: stable/10/share/examples/find_interface/find_interface.c 50476 1999-08-28 00:22:10Z peter $ |
31 |
*/ |
32 |
|
33 |
/* |
34 |
* This is a simple program which demonstrates how to query the kernel |
35 |
* routing mechanism using only a UDP socket. Pass it a hostname on |
36 |
* the command line (sorry, it doesn't parse dotted decimal) and it will |
37 |
* print out an IP address which names the interface over which UDP |
38 |
* packets intended for that destination would be sent. |
39 |
* A more sophisticated program might use the list obtained from SIOCGIFCONF |
40 |
* to match the address with an interface name, but applications programmers |
41 |
* much more often need to know the address of the interface rather than |
42 |
* the name. |
43 |
*/ |
44 |
#include <sys/types.h> |
45 |
#include <sys/socket.h> |
46 |
#include <unistd.h> |
47 |
#include <netinet/in.h> |
48 |
#include <arpa/inet.h> |
49 |
#include <stdlib.h> |
50 |
#include <stdio.h> |
51 |
#include <netdb.h> |
52 |
#include <err.h> |
53 |
#include <errno.h> |
54 |
#include <string.h> |
55 |
#include <sysexits.h> |
56 |
|
57 |
int |
58 |
main(int argc, char **argv) |
59 |
{ |
60 |
struct sockaddr_in local, remote; |
61 |
struct hostent *hp; |
62 |
int s, rv, namelen; |
63 |
|
64 |
argc--, argv++; |
65 |
|
66 |
if (!*argv) { |
67 |
errx(EX_USAGE, "must supply a hostname"); |
68 |
} |
69 |
|
70 |
hp = gethostbyname(*argv); |
71 |
if (!hp) { |
72 |
errx(EX_NOHOST, "cannot resolve hostname: %s", *argv); |
73 |
} |
74 |
|
75 |
memcpy(&remote.sin_addr, hp->h_addr_list[0], sizeof remote.sin_addr); |
76 |
remote.sin_port = htons(60000); |
77 |
remote.sin_family = AF_INET; |
78 |
remote.sin_len = sizeof remote; |
79 |
|
80 |
local.sin_addr.s_addr = htonl(INADDR_ANY); |
81 |
local.sin_port = htons(60000); |
82 |
local.sin_family = AF_INET; |
83 |
local.sin_len = sizeof local; |
84 |
|
85 |
s = socket(PF_INET, SOCK_DGRAM, 0); |
86 |
if (s < 0) |
87 |
err(EX_OSERR, "socket"); |
88 |
|
89 |
do { |
90 |
rv = bind(s, (struct sockaddr *)&local, sizeof local); |
91 |
local.sin_port = htons(ntohs(local.sin_port) + 1); |
92 |
} while(rv < 0 && errno == EADDRINUSE); |
93 |
|
94 |
if (rv < 0) |
95 |
err(EX_OSERR, "bind"); |
96 |
|
97 |
do { |
98 |
rv = connect(s, (struct sockaddr *)&remote, sizeof remote); |
99 |
remote.sin_port = htons(ntohs(remote.sin_port) + 1); |
100 |
} while(rv < 0 && errno == EADDRINUSE); |
101 |
|
102 |
if (rv < 0) |
103 |
err(EX_OSERR, "connect"); |
104 |
|
105 |
namelen = sizeof local; |
106 |
rv = getsockname(s, (struct sockaddr *)&local, &namelen); |
107 |
if (rv < 0) |
108 |
err(EX_OSERR, "getsockname"); |
109 |
|
110 |
printf("Route to %s is out %s\n", *argv, inet_ntoa(local.sin_addr)); |
111 |
return 0; |
112 |
} |