Program which implements "nos" alias "ka9q" alias "IP-IP" tunnels.

PR:		1154
Reviewed by:	phk
Manpage by:	phk
Submitted by:	Nickolay N. Dudorov nnd@itfs.nsk.su
This commit is contained in:
Poul-Henning Kamp 1998-04-11 19:33:06 +00:00
parent a2481bbe8e
commit e66dbdb6c0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=35137
6 changed files with 848 additions and 0 deletions

6
sbin/noc-tun/Makefile Normal file
View File

@ -0,0 +1,6 @@
PROG=nos-tun
MAN8=nos-tun.8
.include <bsd.prog.mk>

73
sbin/noc-tun/nos-tun.8 Normal file
View File

@ -0,0 +1,73 @@
.\"
.\" ----------------------------------------------------------------------------
.\" "THE BEER-WARE LICENSE" (Revision 42):
.\" <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
.\" can do whatever you want with this stuff. If we meet some day, and you think
.\" this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
.\" ----------------------------------------------------------------------------
.\"
.\" $Id$
.\"
.Dd April 11, 1998
.Dt NOS-TUN 8
.Os FreeBSD 3.0
.Sh NAME
.Nm nos-tun
.Nd Implement ``nos'' or ``ka9q'' style IP over IP tunnel
.Sh SYNOPSIS
.Nm nos-tun
.Fl t
.Ar tunnel
.Fl s
.Ar source
.Fl d
.Ar destination
.Ar target
.Sh DESCRIPTION
.Nm
is used to establish an
.Em nos
style tunnel, (also known as
.Em ka9q
or
.Em IP-IP
tunnel) using a
.Xr tun 4
kernel interface.
.Pp
.Ar tunnel
is the name of the tunnel device
.Dq /dev/tun0
for example.
.Pp
.Ar source
and
.Ar destination
are the addresses used on the tunnel device.
If you configure the tunnel against a cisco router, use a netmask of
.Dq 255.255.255.252
on the cisco. This is because the tunnel is a point-to-point interface
in the FreeBSD end, a concept cisco doesn't really implement.
.Pp
.Ar target
is the address of the remote tunnel device, this must match the source
address set on the remote end.
.Sh EXAMPLES
This end, a FreeBSD box on address 192.168.59.34:
.Bd -literal -offset indent 4m
nos-tun -t /dev/tun0 -s 192.168.61.1 -d 192.168.61.2 192.168.56.45
.Ed
.Pp
Remote cisco on address 192.168.56.45:
.Bd -literal -offset indent 4m
interface tunnel 0
ip address 192.168.61.2 255.255.255.252
tunnel mode nos
tunnel destination 192.168.59.34
tunnel source 192.168.56.45
.Ed
.Sh BUGS
We don't allow for setting our source address for multihomed machines.
.Sh AUTHOR
Nickolay N. Dudorov <nnd@itfs.nsk.su> wrote the program,
Poul-Henning Kamp <phk@FreeBSD.org> wrote the man-page.

345
sbin/noc-tun/nos-tun.c Normal file
View File

@ -0,0 +1,345 @@
/*
* Copyright (c) 1996, Nickolay Dudorov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 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.
*
*/
/*
* 'nos_tun' program configure tunN interface as a point-to-point
* connection with two "pseudo"-addresses between this host and
* 'target'.
*
* It uses Ip-over-Ip incapsulation ( protocol number 94 - IPIP)
* (known as NOS-incapsulation in CISCO-routers' terminology).
*
* 'nos_tun' can works with itself and CISCO-routers.
* (It may also work with Linux 'nos_tun's, but
* I have no Linux system here to test with).
*
* BUGS (or features ?):
* - you must specify ONE of the target host's addresses
* ( nos_tun sends and accepts packets only to/from this
* address )
* - there can be only ONE tunnel between two hosts,
* more precisely - between given host and (one of)
* target hosts' address(es)
* (and why do you want more ?)
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.h>
#include <syslog.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <net/if.h>
#include <arpa/inet.h>
/* Tunnel interface configuration stuff */
static struct ifaliasreq ifra;
static struct ifreq ifrq;
/* Global descriptors */
int net; /* socket descriptor */
int tun; /* tunnel descriptor */
int Set_address(char *addr, struct sockaddr_in *sin)
{
struct hostent *hp;
bzero((char *)sin, sizeof(struct sockaddr));
sin->sin_family = AF_INET;
if((sin->sin_addr.s_addr = inet_addr(addr)) == (u_long)-1) {
hp = gethostbyname(addr);
if (!hp) {
syslog(LOG_ERR,"Unknown host %s\n", addr);
return 1;
}
sin->sin_family = hp->h_addrtype;
bcopy(hp->h_addr, (caddr_t)&sin->sin_addr, hp->h_length);
}
return 0;
}
int tun_open(char *devname, struct sockaddr *ouraddr, char *theiraddr)
{
int s;
struct sockaddr_in *sin;
/* Open tun device */
tun = open (devname, O_RDWR);
if (tun < 0) {
syslog(LOG_ERR,"Can't open %s - %m",devname);
return(1);
}
/*
* At first, name the interface.
*/
bzero((char *)&ifra, sizeof(ifra));
bzero((char *)&ifrq, sizeof(ifrq));
strncpy(ifrq.ifr_name, devname+5, IFNAMSIZ);
strncpy(ifra.ifra_name, devname+5, IFNAMSIZ);
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
syslog(LOG_ERR,"Can't open socket - %M");
goto tunc_return;
}
/*
* Delete (previous) adresses for interface
*
* !!!!
* On FreeBSD this ioctl returns error
* when tunN have no addresses, so - log and ignore it.
*
*/
if (ioctl(s, SIOCDIFADDR, &ifra) < 0) {
syslog(LOG_ERR,"SIOCDIFADDR - %m");
}
/*
* Set interface address
*/
sin = (struct sockaddr_in *)&(ifra.ifra_addr);
bcopy(ouraddr, sin, sizeof(struct sockaddr_in));
sin->sin_len = sizeof(*sin);
/*
* Set destination address
*/
sin = (struct sockaddr_in *)&(ifra.ifra_broadaddr);
if(Set_address(theiraddr,sin)) {
syslog(LOG_ERR,"Bad destination address:%s\n",theiraddr);
goto stunc_return;
}
sin->sin_len = sizeof(*sin);
if (ioctl(s, SIOCAIFADDR, &ifra) < 0) {
syslog(LOG_ERR,"Can't set interface address - %m");
goto stunc_return;
}
/*
* Now, bring up the interface.
*/
if (ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
syslog(LOG_ERR,"Can't get interface flags - %m");
goto stunc_return;
}
ifrq.ifr_flags |= IFF_UP;
if (!(ioctl(s, SIOCSIFFLAGS, &ifrq) < 0)) {
close(s);
return(0);
}
syslog(LOG_ERR,"Can't set interface UP - %m");
stunc_return:
close(s);
tunc_return:
close(tun);
return(1);
}
void Finish(int signum)
{
int s;
syslog(LOG_INFO,"Exiting");
close(net);
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
syslog(LOG_ERR,"Can't open socket - %m");
goto closing_tun;
}
/*
* Shut down interface.
*/
if (ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
syslog(LOG_ERR,"Can't get interface flags - %m");
goto closing_fds;
}
ifrq.ifr_flags &= ~(IFF_UP|IFF_RUNNING);
if (ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
syslog(LOG_ERR,"Can't set interface DOWN - %m");
goto closing_fds;
}
/*
* Delete adresses for interface
*/
bzero(&ifra.ifra_addr, sizeof(ifra.ifra_addr));
bzero(&ifra.ifra_broadaddr, sizeof(ifra.ifra_addr));
bzero(&ifra.ifra_mask, sizeof(ifra.ifra_addr));
if (ioctl(s, SIOCDIFADDR, &ifra) < 0) {
syslog(LOG_ERR,"Can't delete interface's addresses - %m");
}
closing_fds:
close(s);
closing_tun:
close(tun);
closelog();
exit(signum);
}
int main (int argc, char **argv)
{
int c, len, ipoff;
char *devname = NULL;
char *point_to = NULL;
char *to_point = NULL;
char *target;
struct sockaddr t_laddr; /* Source address of tunnel */
struct sockaddr whereto; /* Destination of tunnel */
struct sockaddr_in *to;
char buf[0x2000]; /* Packets buffer */
struct ip *ip = (struct ip *)buf;
fd_set rfds, wfds, efds; /* File descriptors for select() */
int nfds; /* Return from select() */
while ((c = getopt(argc, argv, "d:s:t:")) != EOF) {
switch (c) {
case 'd':
to_point = optarg;
break;
case 's':
point_to = optarg;
break;
case 't':
devname = optarg;
break;
}
}
argc -= optind;
argv += optind;
if (argc != 1 || (devname == NULL) ||
(point_to == NULL) || (to_point == NULL)) {
fprintf(stderr,
"Usage: nos_tun -t <tun_name> -s <source_addr> -d <dest_addr> <target_addr>\n");
exit(1);
}
target = *argv;
/* Establish logging through 'syslog' */
openlog("nos_tun", LOG_PID, LOG_DAEMON);
if(Set_address(point_to, (struct sockaddr_in *)&t_laddr)) {
closelog();
exit(2);
}
if(tun_open(devname, &t_laddr, to_point)) {
closelog();
exit(3);
}
to = (struct sockaddr_in *)&whereto;
if(Set_address(target, to))
Finish(4);
if ((net = socket(AF_INET, SOCK_RAW, 94)) < 0) {
syslog(LOG_ERR,"Can't open socket - %m");
Finish(5);
}
if (connect(net,&whereto,sizeof(struct sockaddr_in)) < 0 ) {
syslog(LOG_ERR,"Can't connect to target - %m");
close(net);
Finish(6);
}
/* Demonize it */
daemon(0,0);
/* Install signal handlers */
(void)signal(SIGHUP,Finish);
(void)signal(SIGINT,Finish);
(void)signal(SIGTERM,Finish);
for (;;) {
/* Set file descriptors for select() */
FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);
FD_SET(tun,&rfds); FD_SET(net,&rfds);
nfds = select(net+10,&rfds,&wfds,&efds,NULL);
if(nfds < 0) {
syslog(LOG_ERR,"Interrupted select");
close(net);
Finish(7);
}
if(nfds == 0) { /* Impossible ? */
syslog(LOG_ERR,"Timeout in select");
close(net);
Finish(8);
}
if(FD_ISSET(net,&rfds)) {
/* Read from socket ... */
len = read(net, buf, sizeof(buf));
/* Check if this is "our" packet */
if((ip->ip_src).s_addr == (to->sin_addr).s_addr) {
/* ... skip encapsulation headers ... */
ipoff = (ip->ip_hl << 2);
/* ... and write to tun-device */
write(tun,buf+ipoff,len-ipoff);
}
}
if(FD_ISSET(tun,&rfds)) {
/* Read from tun ... */
len = read(tun, buf, sizeof(buf));
/* ... and send to network */
if(send(net, buf, len,0) <= 0) {
syslog(LOG_ERR,"Can't send - %m");
}
}
}
}

6
sbin/nos-tun/Makefile Normal file
View File

@ -0,0 +1,6 @@
PROG=nos-tun
MAN8=nos-tun.8
.include <bsd.prog.mk>

73
sbin/nos-tun/nos-tun.8 Normal file
View File

@ -0,0 +1,73 @@
.\"
.\" ----------------------------------------------------------------------------
.\" "THE BEER-WARE LICENSE" (Revision 42):
.\" <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
.\" can do whatever you want with this stuff. If we meet some day, and you think
.\" this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
.\" ----------------------------------------------------------------------------
.\"
.\" $Id$
.\"
.Dd April 11, 1998
.Dt NOS-TUN 8
.Os FreeBSD 3.0
.Sh NAME
.Nm nos-tun
.Nd Implement ``nos'' or ``ka9q'' style IP over IP tunnel
.Sh SYNOPSIS
.Nm nos-tun
.Fl t
.Ar tunnel
.Fl s
.Ar source
.Fl d
.Ar destination
.Ar target
.Sh DESCRIPTION
.Nm
is used to establish an
.Em nos
style tunnel, (also known as
.Em ka9q
or
.Em IP-IP
tunnel) using a
.Xr tun 4
kernel interface.
.Pp
.Ar tunnel
is the name of the tunnel device
.Dq /dev/tun0
for example.
.Pp
.Ar source
and
.Ar destination
are the addresses used on the tunnel device.
If you configure the tunnel against a cisco router, use a netmask of
.Dq 255.255.255.252
on the cisco. This is because the tunnel is a point-to-point interface
in the FreeBSD end, a concept cisco doesn't really implement.
.Pp
.Ar target
is the address of the remote tunnel device, this must match the source
address set on the remote end.
.Sh EXAMPLES
This end, a FreeBSD box on address 192.168.59.34:
.Bd -literal -offset indent 4m
nos-tun -t /dev/tun0 -s 192.168.61.1 -d 192.168.61.2 192.168.56.45
.Ed
.Pp
Remote cisco on address 192.168.56.45:
.Bd -literal -offset indent 4m
interface tunnel 0
ip address 192.168.61.2 255.255.255.252
tunnel mode nos
tunnel destination 192.168.59.34
tunnel source 192.168.56.45
.Ed
.Sh BUGS
We don't allow for setting our source address for multihomed machines.
.Sh AUTHOR
Nickolay N. Dudorov <nnd@itfs.nsk.su> wrote the program,
Poul-Henning Kamp <phk@FreeBSD.org> wrote the man-page.

345
sbin/nos-tun/nos-tun.c Normal file
View File

@ -0,0 +1,345 @@
/*
* Copyright (c) 1996, Nickolay Dudorov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 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.
*
*/
/*
* 'nos_tun' program configure tunN interface as a point-to-point
* connection with two "pseudo"-addresses between this host and
* 'target'.
*
* It uses Ip-over-Ip incapsulation ( protocol number 94 - IPIP)
* (known as NOS-incapsulation in CISCO-routers' terminology).
*
* 'nos_tun' can works with itself and CISCO-routers.
* (It may also work with Linux 'nos_tun's, but
* I have no Linux system here to test with).
*
* BUGS (or features ?):
* - you must specify ONE of the target host's addresses
* ( nos_tun sends and accepts packets only to/from this
* address )
* - there can be only ONE tunnel between two hosts,
* more precisely - between given host and (one of)
* target hosts' address(es)
* (and why do you want more ?)
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.h>
#include <syslog.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <net/if.h>
#include <arpa/inet.h>
/* Tunnel interface configuration stuff */
static struct ifaliasreq ifra;
static struct ifreq ifrq;
/* Global descriptors */
int net; /* socket descriptor */
int tun; /* tunnel descriptor */
int Set_address(char *addr, struct sockaddr_in *sin)
{
struct hostent *hp;
bzero((char *)sin, sizeof(struct sockaddr));
sin->sin_family = AF_INET;
if((sin->sin_addr.s_addr = inet_addr(addr)) == (u_long)-1) {
hp = gethostbyname(addr);
if (!hp) {
syslog(LOG_ERR,"Unknown host %s\n", addr);
return 1;
}
sin->sin_family = hp->h_addrtype;
bcopy(hp->h_addr, (caddr_t)&sin->sin_addr, hp->h_length);
}
return 0;
}
int tun_open(char *devname, struct sockaddr *ouraddr, char *theiraddr)
{
int s;
struct sockaddr_in *sin;
/* Open tun device */
tun = open (devname, O_RDWR);
if (tun < 0) {
syslog(LOG_ERR,"Can't open %s - %m",devname);
return(1);
}
/*
* At first, name the interface.
*/
bzero((char *)&ifra, sizeof(ifra));
bzero((char *)&ifrq, sizeof(ifrq));
strncpy(ifrq.ifr_name, devname+5, IFNAMSIZ);
strncpy(ifra.ifra_name, devname+5, IFNAMSIZ);
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
syslog(LOG_ERR,"Can't open socket - %M");
goto tunc_return;
}
/*
* Delete (previous) adresses for interface
*
* !!!!
* On FreeBSD this ioctl returns error
* when tunN have no addresses, so - log and ignore it.
*
*/
if (ioctl(s, SIOCDIFADDR, &ifra) < 0) {
syslog(LOG_ERR,"SIOCDIFADDR - %m");
}
/*
* Set interface address
*/
sin = (struct sockaddr_in *)&(ifra.ifra_addr);
bcopy(ouraddr, sin, sizeof(struct sockaddr_in));
sin->sin_len = sizeof(*sin);
/*
* Set destination address
*/
sin = (struct sockaddr_in *)&(ifra.ifra_broadaddr);
if(Set_address(theiraddr,sin)) {
syslog(LOG_ERR,"Bad destination address:%s\n",theiraddr);
goto stunc_return;
}
sin->sin_len = sizeof(*sin);
if (ioctl(s, SIOCAIFADDR, &ifra) < 0) {
syslog(LOG_ERR,"Can't set interface address - %m");
goto stunc_return;
}
/*
* Now, bring up the interface.
*/
if (ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
syslog(LOG_ERR,"Can't get interface flags - %m");
goto stunc_return;
}
ifrq.ifr_flags |= IFF_UP;
if (!(ioctl(s, SIOCSIFFLAGS, &ifrq) < 0)) {
close(s);
return(0);
}
syslog(LOG_ERR,"Can't set interface UP - %m");
stunc_return:
close(s);
tunc_return:
close(tun);
return(1);
}
void Finish(int signum)
{
int s;
syslog(LOG_INFO,"Exiting");
close(net);
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
syslog(LOG_ERR,"Can't open socket - %m");
goto closing_tun;
}
/*
* Shut down interface.
*/
if (ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
syslog(LOG_ERR,"Can't get interface flags - %m");
goto closing_fds;
}
ifrq.ifr_flags &= ~(IFF_UP|IFF_RUNNING);
if (ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
syslog(LOG_ERR,"Can't set interface DOWN - %m");
goto closing_fds;
}
/*
* Delete adresses for interface
*/
bzero(&ifra.ifra_addr, sizeof(ifra.ifra_addr));
bzero(&ifra.ifra_broadaddr, sizeof(ifra.ifra_addr));
bzero(&ifra.ifra_mask, sizeof(ifra.ifra_addr));
if (ioctl(s, SIOCDIFADDR, &ifra) < 0) {
syslog(LOG_ERR,"Can't delete interface's addresses - %m");
}
closing_fds:
close(s);
closing_tun:
close(tun);
closelog();
exit(signum);
}
int main (int argc, char **argv)
{
int c, len, ipoff;
char *devname = NULL;
char *point_to = NULL;
char *to_point = NULL;
char *target;
struct sockaddr t_laddr; /* Source address of tunnel */
struct sockaddr whereto; /* Destination of tunnel */
struct sockaddr_in *to;
char buf[0x2000]; /* Packets buffer */
struct ip *ip = (struct ip *)buf;
fd_set rfds, wfds, efds; /* File descriptors for select() */
int nfds; /* Return from select() */
while ((c = getopt(argc, argv, "d:s:t:")) != EOF) {
switch (c) {
case 'd':
to_point = optarg;
break;
case 's':
point_to = optarg;
break;
case 't':
devname = optarg;
break;
}
}
argc -= optind;
argv += optind;
if (argc != 1 || (devname == NULL) ||
(point_to == NULL) || (to_point == NULL)) {
fprintf(stderr,
"Usage: nos_tun -t <tun_name> -s <source_addr> -d <dest_addr> <target_addr>\n");
exit(1);
}
target = *argv;
/* Establish logging through 'syslog' */
openlog("nos_tun", LOG_PID, LOG_DAEMON);
if(Set_address(point_to, (struct sockaddr_in *)&t_laddr)) {
closelog();
exit(2);
}
if(tun_open(devname, &t_laddr, to_point)) {
closelog();
exit(3);
}
to = (struct sockaddr_in *)&whereto;
if(Set_address(target, to))
Finish(4);
if ((net = socket(AF_INET, SOCK_RAW, 94)) < 0) {
syslog(LOG_ERR,"Can't open socket - %m");
Finish(5);
}
if (connect(net,&whereto,sizeof(struct sockaddr_in)) < 0 ) {
syslog(LOG_ERR,"Can't connect to target - %m");
close(net);
Finish(6);
}
/* Demonize it */
daemon(0,0);
/* Install signal handlers */
(void)signal(SIGHUP,Finish);
(void)signal(SIGINT,Finish);
(void)signal(SIGTERM,Finish);
for (;;) {
/* Set file descriptors for select() */
FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);
FD_SET(tun,&rfds); FD_SET(net,&rfds);
nfds = select(net+10,&rfds,&wfds,&efds,NULL);
if(nfds < 0) {
syslog(LOG_ERR,"Interrupted select");
close(net);
Finish(7);
}
if(nfds == 0) { /* Impossible ? */
syslog(LOG_ERR,"Timeout in select");
close(net);
Finish(8);
}
if(FD_ISSET(net,&rfds)) {
/* Read from socket ... */
len = read(net, buf, sizeof(buf));
/* Check if this is "our" packet */
if((ip->ip_src).s_addr == (to->sin_addr).s_addr) {
/* ... skip encapsulation headers ... */
ipoff = (ip->ip_hl << 2);
/* ... and write to tun-device */
write(tun,buf+ipoff,len-ipoff);
}
}
if(FD_ISSET(tun,&rfds)) {
/* Read from tun ... */
len = read(tun, buf, sizeof(buf));
/* ... and send to network */
if(send(net, buf, len,0) <= 0) {
syslog(LOG_ERR,"Can't send - %m");
}
}
}
}