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