/*
---------------------------------------------------------------------------
 $Id: tsp_tun.c,v 1.3 2006/09/22 23:06:22 cnepveu Exp $
---------------------------------------------------------------------------
Copyright (c) 2001-2006 Hexago Inc. All rights reserved.

  LICENSE NOTICE: You may use and modify this source code only if you
  have executed a valid license agreement with Hexago Inc. granting
  you the right to do so, the said license agreement governing such
  use and modifications.   Copyright or other intellectual property
  notices are not to be removed from the source code.
---------------------------------------------------------------------------
*/

/* Darwin */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>

#include <sys/select.h>
#include <sys/stat.h>
#include <sys/types.h>

#define _USES_SYS_IOCTL_H_
#define _USES_SYS_TIME_H_
#define _USES_SYS_SOCKET_H_
#define _USES_NET_IF_H_
#define _USES_ARPA_INET_H_
#define _USES_NETINET_IN_H_
#define _USES_NETINET_IP6_H_
#define _USES_NETINET_ICMP6_H_

#include "platform.h"

#include <fcntl.h>

#include "tsp_tun.h"
#include "net_ka.h"
#include "log.h"
#include "hex_strings.h"
#include "lib.h" /* Display */
#include "config.h" /* tBoolean define */
#include "errors.h"

#define HEXTUN_BUFSIZE 2048

/* Initialize tun interface */
int TunInit(char *TunDevice) {
  int tunfd;
  char iftun[128];

  strcpy(iftun,"/dev/");
  strcat(iftun,TunDevice);

  tunfd = open(iftun,O_RDWR);
  if (tunfd == -1) {
    Display(LOG_LEVEL_1, ELError, "TunInit", HEX_STR_ERR_OPEN_TUN_DEV, iftun);
    return(-1);
  }
  return tunfd;
}

int TunMainLoop(int tunfd, SOCKET Socket, tBoolean keepalive, int keepalive_interval,
				char *local_address_ipv6, char *keepalive_address) {
  fd_set rfds;
  int count, maxfd;
  char bufin[HEXTUN_BUFSIZE];
  char bufout[HEXTUN_BUFSIZE];
  struct timeval timeout;
  int ret = 0;

  if (keepalive_interval != 0) {
	  timeout.tv_sec = 0;
	  timeout.tv_usec = 100000;	// 100 ms
	  NetKeepaliveInit(local_address_ipv6, keepalive_address, keepalive_interval, AF_INET6);
  }
  else {
	  keepalive = FALSE;
	  timeout.tv_sec = 7 * 24 * 60 * 60 ; /* one week */
	  timeout.tv_usec = 0;
  }

  while(1) {
    FD_ZERO(&rfds); 
    FD_SET(tunfd,&rfds);
    FD_SET(Socket,&rfds);

    maxfd = tunfd>Socket?tunfd:Socket;

    if(keepalive) 
	    if (NetKeepaliveDo() == 2)
		    return KEEPALIVE_TIMEOUT;
  
    
    ret = select(maxfd+1,&rfds,0,0,&timeout);

    if (ret > 0) {
	    if( FD_ISSET(tunfd, &rfds) ) {
		    /* data sent through udp tunnel */
		    /* ioctl(tunfd, FIONREAD, &count); */
		    if ((count = read(tunfd, bufout, HEXTUN_BUFSIZE)) < -1) {
			    Display(LOG_LEVEL_3, ELError, "TunMainLoop", HEX_STR_ERR_READING_TUN_DEV);
			    return(TUNNEL_ERROR);
		    }
		    NetKeepaliveGotWrite();
		    if (send(Socket, bufout, count, 0) != count) {
			    Display(LOG_LEVEL_3, ELError, "TunMainLoop", HEX_STR_ERR_WRITE_SOCKET);
			    return(TUNNEL_ERROR);
		    }
	    }

	    if(FD_ISSET(Socket,&rfds)) {
		    /* data received through udp tunnel */
		    count=recvfrom(Socket,bufin,HEXTUN_BUFSIZE,0,NULL,NULL);
		    NetKeepaliveGotRead();
		    if (write(tunfd, bufin, count) != count) {
			    Display(LOG_LEVEL_3, ELError, "TunMainLoop", HEX_STR_ERR_WRITE_TUN_DEV);
			    return(TUNNEL_ERROR);
		    }
	    }
    }//if (ret>0)
  }//while(1)
}

				
				




syntax highlighted by Code2HTML, v. 0.9.1