diff options
Diffstat (limited to 'usr.bin/talk/get_iface.c')
-rw-r--r-- | usr.bin/talk/get_iface.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/usr.bin/talk/get_iface.c b/usr.bin/talk/get_iface.c new file mode 100644 index 0000000..96d3d6e --- /dev/null +++ b/usr.bin/talk/get_iface.c @@ -0,0 +1,100 @@ +/* + * Copyright 1994, 1995 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> + +__FBSDID("$FreeBSD$"); + +/* + * From: + * Id: find_interface.c,v 1.1 1995/08/14 16:08:39 wollman Exp + */ + +#include <errno.h> +#include <string.h> +#include <unistd.h> + +#include "talk.h" + +/* + * Try to find the interface address that is used to route an IP + * packet to a remote peer. + */ + +int +get_iface(struct in_addr *dst, struct in_addr *iface) +{ + static struct sockaddr_in local; + struct sockaddr_in remote; + socklen_t namelen; + int s, rv; + + memcpy(&remote.sin_addr, dst, sizeof remote.sin_addr); + remote.sin_port = htons(60000); + remote.sin_family = AF_INET; + remote.sin_len = sizeof remote; + + local.sin_addr.s_addr = htonl(INADDR_ANY); + local.sin_port = htons(60000); + local.sin_family = AF_INET; + local.sin_len = sizeof local; + + s = socket(PF_INET, SOCK_DGRAM, 0); + if (s < 0) + return -1; + + do { + rv = bind(s, (struct sockaddr *)&local, sizeof local); + local.sin_port = htons(ntohs(local.sin_port) + 1); + } while(rv < 0 && errno == EADDRINUSE); + + if (rv < 0) { + close(s); + return -1; + } + + do { + rv = connect(s, (struct sockaddr *)&remote, sizeof remote); + remote.sin_port = htons(ntohs(remote.sin_port) + 1); + } while(rv < 0 && errno == EADDRINUSE); + + if (rv < 0) { + close(s); + return -1; + } + + namelen = sizeof local; + rv = getsockname(s, (struct sockaddr *)&local, &namelen); + close(s); + if (rv < 0) + return -1; + + memcpy(iface, &local.sin_addr, sizeof local.sin_addr); + return 0; +} |