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