diff options
author | kstailey <kstailey@cvs.openbsd.org> | 1997-02-13 01:19:06 +0000 |
---|---|---|
committer | kstailey <kstailey@cvs.openbsd.org> | 1997-02-13 01:19:06 +0000 |
commit | bac3c998667f3b450e9f449c272a223943ece2d9 (patch) | |
tree | 32e72c1517e808e075354ce5277c8a8bed0ac1fd /sbin/ipnat/ipnat.c | |
parent | 531b83cb6b19c9503a281f5f86dfe84c33c02f02 (diff) |
Allow use of interface name in rules file. This way if you have a dynamic
IP address you don't have to edit the rules file every time you connect.
Example of usage:
coyote% cat /etc/nat.rules
map ppp0 10.0.0.0/8 -> ppp0/32 portmap tcp/udp 10000:20000
ppp0 is automagically transformed into the IP address of the ppp0 interface.
Diffstat (limited to 'sbin/ipnat/ipnat.c')
-rw-r--r-- | sbin/ipnat/ipnat.c | 68 |
1 files changed, 66 insertions, 2 deletions
diff --git a/sbin/ipnat/ipnat.c b/sbin/ipnat/ipnat.c index afc22306a2e..f1911c53c31 100644 --- a/sbin/ipnat/ipnat.c +++ b/sbin/ipnat/ipnat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ipnat.c,v 1.10 1997/02/11 22:24:20 kstailey Exp $ */ +/* $OpenBSD: ipnat.c,v 1.11 1997/02/13 01:19:05 kstailey Exp $ */ /* * (C)opyright 1993,1994,1995 by Darren Reed. * @@ -373,6 +373,67 @@ char *msk; return mask; } +/* + * get_if_addr(): given a string containing an interface name (e.g. "ppp0") + * return the IP address it represents as an unsigned long + */ +u_long if_addr(name) +char *name; +{ + struct ifconf ifc; + struct ifreq ifreq, *ifr; + char *inbuf = NULL; + int s, i, len = 8192; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + warn("socket"); + return INADDR_NONE; + } + + while (1) { + ifc.ifc_len = len; + ifc.ifc_buf = inbuf = realloc(inbuf, len); + if (inbuf == NULL) + err(1, "malloc"); + if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { + warn("SIOCGIFCONF"); + goto if_addr_lose; + } + if (ifc.ifc_len + sizeof(ifreq) < len) + break; + len *= 2; + } + ifr = ifc.ifc_req; + ifreq.ifr_name[0] = '\0'; + for (i = 0; i < ifc.ifc_len; ) { + ifr = (struct ifreq *)((caddr_t)ifc.ifc_req + i); + i += sizeof(ifr->ifr_name) + + (ifr->ifr_addr.sa_len > sizeof(struct sockaddr) + ? ifr->ifr_addr.sa_len + : sizeof(struct sockaddr)); + if (!strncmp(ifreq.ifr_name, ifr->ifr_name, + sizeof(ifr->ifr_name))) + continue; + ifreq = *ifr; + if (ioctl(s, SIOCGIFADDR, (caddr_t)ifr) < 0) { + warn("SIOCGIFADDR"); + goto if_addr_lose; + } + if (ifr->ifr_addr.sa_family != AF_INET) + continue; + if (!strcmp(name, ifr->ifr_name)) { + struct sockaddr_in *sin; + close(s); + free(inbuf); + sin = (struct sockaddr_in *)&ifr->ifr_addr; + return (sin->sin_addr.s_addr); + } + } +if_addr_lose: + close(s); + free(inbuf); + return INADDR_NONE; +} /* * returns an ip address as a long var as a result of either a DNS lookup or @@ -386,13 +447,16 @@ int *resolved; struct netent *np; *resolved = 0; - if (!strcasecmp("any",host)) + if (!strcasecmp("any", host)) return 0L; if (isdigit(*host)) return inet_addr(host); if (!(hp = gethostbyname(host))) { if (!(np = getnetbyname(host))) { + u_long addr; + if ((addr = if_addr(host)) != INADDR_NONE) + return addr; *resolved = -1; fprintf(stderr, "can't resolve hostname: %s\n", host); return 0; |