Beispiel #1
0
int main(int argc, char *argv[]) {
#ifdef DEBUG
  signal(SIGSEGV,debug_backtrace);
#endif
  printf("begin!\n");
  int tap_fd, tap_fd1, option;
  int dummy = 0;
  int flags = IFF_TUN;
  char if_name0[IFNAMSIZ] = "tap0";
  char if_name1[IFNAMSIZ] = "tap1";
  int maxfd;
  uint16_t nread, nwrite, plength;
  char buffer[BUFSIZE];
  struct sockaddr_in local, remote;
  char remote_ip[16] = "";            /* dotted quad IP string */
  unsigned short int port = PORT;
  int sock_fd, net_fd, optval = 1;
  socklen_t remotelen;
  int cliserv = -1;    /* must be specified on cmd line */
  unsigned long int tap2net = 0, net2tap = 0;

  struct in_addr addr;
  struct host twohopneis[10];
  inet_aton(twohopnei_ip_addr,&addr);
  twohopneis[0].ip_addr = addr.s_addr;
  memcpy(twohopneis[0].mac_addr,gate_mac_addr, ETHER_ADDR_LEN); 

  struct host localhost;
  inet_aton(local_ip_addr,&addr);
  localhost.ip_addr = addr.s_addr;
  memcpy(localhost.mac_addr, local_mac_addr, ETHER_ADDR_LEN);

  progname = argv[0];
  
  /* Check command line options */
  while((option = getopt(argc, argv, "i:sc:p:uahd")) > 0) {
    switch(option) {
      case 'd':
	printf("Enter dummy mode\n");
        dummy = 1;
        break;
      case 'h':
        usage();
        break;
      case 'i':
        strncpy(if_name0,optarg, IFNAMSIZ-1);
        break;
      case 's':
        cliserv = SERVER;
        break;
      case 'c':
        cliserv = CLIENT;
        strncpy(remote_ip,optarg,15);
        break;
      case 'p':
        port = atoi(optarg);
        break;
      case 'u':
        flags = IFF_TUN;
        break;
      case 'a':
        flags = IFF_TAP;
        break;
      default:
        my_err("Unknown option %c\n", option);
        usage();
    }
  }

  argv += optind;
  argc -= optind;

  if(argc > 0) {
    my_err("Too many options!\n");
    usage();
  }

  if(*if_name0 == '\0') {
    my_err("Must specify interface name!\n");
    usage();
  } else if(cliserv < 0) {
    my_err("Must specify client or server mode!\n");
    usage();
  } else if((cliserv == CLIENT)&&(*remote_ip == '\0')) {
    my_err("Must specify server address!\n");
    usage();
  }
	printf("allocate tap device!\n");
  /* initialize tun/tap interface */
  if ( (tap_fd = tun_alloc(if_name0, flags | IFF_NO_PI)) < 0 ) {
    my_err("Error connecting to tun/tap interface %s!\n", if_name0);
    exit(1);
  }
  
   if ( (tap_fd1 = tun_alloc(if_name1, flags | IFF_NO_PI)) < 0 ) {
    my_err("Error connecting to tun1/tap1 interface %s!\n", if_name1);
    exit(1);
  }
  printf("allocate tap device success!\n");

  //do_debug("Successfully connected to interface %s\n", if_name0);
  
  /* use select() to handle two descriptors at once */
  maxfd = (tap_fd > tap_fd1)?tap_fd:tap_fd1;
  while(1) {
    int ret;
    fd_set rd_set;

    FD_ZERO(&rd_set);
    FD_SET(tap_fd, &rd_set); FD_SET(tap_fd1, &rd_set);
    ret = select(maxfd + 1, &rd_set, NULL, NULL, NULL);
    if (ret < 0 && errno == EINTR){
	  do_debug("ret error");
      continue;
    }

    if (ret < 0) {
      perror("select()");
      exit(1);
    }
    if(FD_ISSET(tap_fd, &rd_set)) {
      /* data from tun/tap: just read it and write it to the network */
      
      DEBUGMSG(2,"\n--Send a packet--\n");
      nread = cread(tap_fd, buffer, BUFSIZE);

      //append the trailer
      if(!dummy){
        if(isIP((unsigned char*)buffer) && isTCP((unsigned char*)buffer)){
          ++send_counter;
          if(send_counter >= UP_LIMIT){
            const int len = 14 + sizeof(struct ip) + 4;
	    unsigned char signal[14 + sizeof(struct ip) + 4] = {0};
	    ConstructSignal(signal, &(twohopneis[0]), &localhost);	
            DEBUGMSG(1,"Epoch end and send a signal\n");
            nwrite = write(tap_fd1, signal, len);
            send_counter = 0;
	  }
          int newLen = extendPacket(TCP, (unsigned char*)buffer);
          nread = newLen;
        }
      }

      //DEBUGMSG(2,"route a packet(len: %i) to tap1\n", nread);
      nwrite = write(tap_fd1, buffer, nread);
      //DEBUGMSG(2,"Written %d bytes to the network\n", nwrite);
    }
	
    if(FD_ISSET(tap_fd1, &rd_set)) {
      /* data from tun/tap: just read it and write it to the network */

      nread = cread(tap_fd1, buffer, BUFSIZE);

 
      /* write length + packet */
      plength = htons(nread);

        if(!dummy){
	    if(isEpochEnd((unsigned char*)buffer)){
		DEBUGMSG(1,"Receive a Epoch end signal\n");
		const int len = 14 + sizeof(struct ip) + 40;
	    unsigned char echobuffer [14 + sizeof(struct ip) + 4] = {0};
		ConstructSignal(echobuffer, (unsigned char*)buffer);	
		nwrite = write(tap_fd1, echobuffer, len);
	    continue;
	  }
	  if(isIP((unsigned char*)buffer) && isTCP((unsigned char*)buffer)){
       	    int newLen = 0;
            verifyPacket(TCP, (unsigned char*)buffer, &newLen);
            nread = newLen;
	  }
	  DEBUGMSG(2,"packet len: %i\n", nread);
       }
      nwrite = write(tap_fd, buffer, nread);
      
      do_debug("TAP2NET %lu: Written %d bytes to the network\n", tap2net, nwrite);
    }

    //if(FD_ISSET(net_fd, &rd_set)) {
	if(0) {
      /* data from the network: read it, and write it to the tun/tap interface. 
       * We need to read the length first, and then the packet */

      /* Read length */      
      nread = read_n(net_fd, (char *)&plength, sizeof(plength));
      if(nread == 0) {
        /* ctrl-c at the other end */
        break;
      }

      net2tap++;

      /* read packet */
      nread = read_n(net_fd, buffer, ntohs(plength));
      do_debug("NET2TAP %lu: Read %d bytes from the network\n", net2tap, nread);

      /* now buffer[] contains a full packet or frame, write it into the tun/tap interface */ 
      nwrite = cwrite(tap_fd, buffer, nread);
      do_debug("NET2TAP %lu: Written %d bytes to the tap interface\n", net2tap, nwrite);
    }
  }
  
  return(0);
}
Beispiel #2
0
int main(int argc, char *argv[])
{
    char buf[2048], dev1[10]="tap0", dev2[10]="tap1", dev3[10]="tap2";
    int fd1, fd2, fd3, len;
    int fm;
    //int count=0;
    struct timeval time;
    //struct iphdr *myiphdr;
    //struct ether_header *myether;
    fd_set fds;

    //inizializzo i puntatori che gestiscono le catene
    primo_wlan = (struct rules*) malloc(sizeof(struct rules));
    primo_wlan->rule_type=0;
    primo_wlan->next=NULL;
    succ_wlan = primo_wlan;
    prec_wlan = primo_wlan;
    
    printf("Please connect:\n");
    printf("tap0 at br0(wlan)\n");
    printf("tap1 at br5\n");
    printf("tap2 at br6\n\n");
    
    printf("Start Now!\n");
	
    if( (fd1 = tun_alloc(dev1)) < 0 ){
       printf("1:Cannot allocate TUN device 1\n");
       exit(1);
    }

    if( (fd2 = tun_alloc(dev2)) < 0 ){
       printf("1:Cannot allocate TUN device 2\n");
       exit(1);
    }

    if( (fd3 = tun_alloc(dev3)) < 0 ){
       printf("1:Cannot allocate TUN device 3\n");
       exit(1);
    }
    
    fm = max(fd1, fd2);
    fm = max(fm, fd3);

	readconf();
	if (debug) {
		printf("dynamic: %d\n",dynamic);
		
    }
	
    while(1){
		FD_ZERO(&fds);
        FD_SET(fd1, &fds);
        FD_SET(fd2, &fds);
        FD_SET(fd3, &fds);
        
        select(fm+1, &fds, NULL, NULL, NULL);
		
		gettimeofday(&time, 0);
		
        //wlan
        if( FD_ISSET(fd1, &fds) ) {
			if (debug) printf("Packet received from wlan\n");
			
            if( (len = mytun_read(fd1, buf, sizeof(buf))) < 0 ){
                printf("2:Error in mytun_read\n");
            } 
			else {
			//qui lancia decisore.c che restituisce un intero che uso con uno switch case per fare le mytun_write
			//ci devo passare anche len per aggiornare bw nella lista
				if (debug) printf("Decisore decide :%d\n",decisore(buf,len,time));
				switch (decisore(buf,len,time)) { 
					case 5:  
						mytun_write(fd2, buf, len);
						if (debug) printf("%d.%.06d: Received %d bytes from wlan -> br5\n", (int)time.tv_sec, (int)time.tv_usec, len);
						break;
					case 6:
						mytun_write(fd3, buf, len);
						if (debug) printf("%d.%.06d: Received %d bytes from wlan -> br6\n", (int)time.tv_sec, (int)time.tv_usec, len);
						break;
					
					    /* Codice spostato al decisore !
						if (dynamic) {
							if (debug)
								printf ("Dynamic=%d", dynamic);
							//modificare, usare br5bw e br6bw per decidere dove mandare il pacchetto
							mytun_write(fd3, buf, len);
							if (debug) printf("DEFAULT %d.%.06d: Received %d bytes from wlan -> br6\n", (int)time.tv_sec, (int)time.tv_usec, len);
						}*/
				}			
/* OLD CODE
                myether = (struct ether_header *) buf;
                myiphdr = (struct iphdr *) &buf[14];   
                if ((count%10) >= 5) {            
                    mytun_write(fd2, buf, len);
                    printf("%d.%.06d: Received %d bytes from wlan -> br5\n", (int)time.tv_sec, (int)time.tv_usec, len);
                    count++;
                } else {
                    mytun_write(fd3, buf, len);
                    printf("%d.%.06d: Received %d bytes from wlan -> br6\n", (int)time.tv_sec, (int)time.tv_usec, len);
                    count++;
                }
                    
		    printf("Tipo ether: %04X\n", bswap_16(myether->ether_type));
		    if(bswap_16(myether->ether_type)==0x8000)
                	printf("Tipo IP   : %d\n", (myiphdr->protocol));                  
*/
            }
        }

		//br5
        if( FD_ISSET(fd2, &fds) ) {
			if (debug) printf("PACCHETTO FROM br5\n");
            if( (len = mytun_read(fd2, buf, sizeof(buf))) < 0 ){
                printf("2:Error in mytun_read\n");
            } else {
                mytun_write(fd1, buf, len);
            }
       
            if (debug) printf("%d.%.06d: Received %d bytes from br5 -> wlan\n", (int)time.tv_sec, (int)time.tv_usec, len);            
        }
	
		//br6
        if( FD_ISSET(fd3, &fds) ) {
			if (debug) printf("PACCHETTO FROM br6\n");
            if( (len = mytun_read(fd3, buf, sizeof(buf))) < 0 ){
                printf("2:Error in mytun_read\n");
            } else {
                mytun_write(fd1, buf, len);
            }
       
            if (debug) printf("%d.%.06d: Received %d bytes from br6 -> wlan\n", (int)time.tv_sec, (int)time.tv_usec, len);
        }
     }
}
int main(int argc, char **argv)
{
	atexit(cleanup);
	signal(SIGHUP, sigcleanup);
	signal(SIGTERM, sigcleanup);
	signal(SIGINT, sigcleanup);
	
	char* prog = argv[0];
	int c;
	while((c = getopt(argc, argv, "W::R::B::C::s::t::")) != -1) {
		switch(c) {
		case 'W':
		working_mode = WISEBED_MODE;
		break;

		case 'R':
		reservation_key = optarg;
		break;
	
		case 'B':
		border_router_node = optarg;
		break;
		
		case 'C':        
		config_path = optarg;    
		break;
		
		case 's':
		to_wisebed_max_size = atoi(optarg);
		break;

		case 't':
		if(strncmp("/dev/", optarg, 5) == 0) {
		strncpy(tundev, optarg + 5, sizeof(tundev));
		} else {
		strncpy(tundev, optarg, sizeof(tundev));
		}
		break;

		/*case 'v':
		verbose = 2;
		if (optarg) verbose = atoi(optarg);
		break;*/
	
		case '?':
		case 'h':
		default:
		fprintf(stderr,"usage: sudo %s -W -R[RESERVATION-KEY] -B[BORDER-ROUTER-URN] [TUN-IP]\n", prog);
		fprintf(stderr,"Options are:\n");
		fprintf(stderr," -W                     Enable usage with WISEBED\n");
		fprintf(stderr," -R  reservation_code   WISEBED: Reservation code\n");
		fprintf(stderr," -B  border_router_URN  WISEBED: URN of the border router node (eg:urn:wisebed:uzl1:0x2100)\n");
		fprintf(stderr," -C  config_file        WISEBED: Place of the config file (default: wisebed/live.properties)\n");
		fprintf(stderr," -s  size               WISEBED: max fragment length to WISEBED (default 499)\n");
		fprintf(stderr," -t  tundev             Name of the IPv6 interface (default tun0)\n");
		/*fprintf(stderr," -v[level]      Verbosity level\n");
		fprintf(stderr,"    -v0         No messages\n");
		fprintf(stderr,"    -v1         Encapsulated SLIP debug messages (default)\n");
		fprintf(stderr,"    -v2         Printable strings after they are received\n");
		fprintf(stderr,"    -v3         Printable strings and SLIP packet notifications\n");
		fprintf(stderr,"    -v4         All printable characters as they are received\n");
		fprintf(stderr,"    -v5         All SLIP packets in hex\n");*/
		exit(1);
		break;
		}
	}
	argc -= (optind - 1);
	argv += (optind - 1);
	
	//Parameter check
	if(working_mode == 0)
	{
		perror( "No working mode selected!" );
		exit(EXIT_FAILURE);
	}
	if(working_mode == WISEBED_MODE)
	{
		if( reservation_key == NULL )
		{
			perror( "No reservation key!" );
			exit(EXIT_FAILURE);
		}
		
		if( border_router_node == NULL )
		{
			perror( "No border router!" );
			exit(EXIT_FAILURE);
		}
	}
	else
	{
		perror( "Only the WISEBED mode is supported at the moment" );
		exit(EXIT_FAILURE);
	}
	
	if(argv[1] == NULL)
	{
		perror( "No IPv6 address!" );
		exit(EXIT_FAILURE);
	}
	
	//copy the IPv6 address
	ipaddr = argv[1];
	
	//Default values
	if( config_path == NULL )
	{
		config_path = (char*) malloc( 24 );
		strcpy(config_path, "wisebed/live.properties");
	}
	
	if( tundev == NULL )
	{
		strcpy(tundev, "tun0");
	}
	
// 	    printf("things: %s %s %s %s %i", reservation_key, border_router_node, config_path, ipaddr, to_wisebed_max_size );

	//For IO handling
	fd_set rset;
	//struct timeval timeout;
	int wisebed_listening_fd = 0;
	
	printf( "WISEBED Tunslip6 program\n" );
	
	//---------------------------- Create and open WISEBED pipe -----------------------------
	
	//****** LISTEN ********
	//Create the listening pipe WISEBED java --> pipe
	if( access(wisebed_listening_pipe, F_OK ) != 0 )
		if( mkfifo(wisebed_listening_pipe, 0666) < 0 )
		{
			perror( "L Pipe creation error (/tmp/wisebed_listening_pipe)" );
			exit(EXIT_FAILURE);
		}
		
	//Open the pipe
	wisebed_listening_fd = open( wisebed_listening_pipe, O_RDONLY | O_NONBLOCK );        
	if( wisebed_listening_fd < 1 )
	{
		perror( "L Pipe opening error" );
		exit(EXIT_FAILURE);
	}
	
	//Convert filedescriptor to FILE because of fread
	wisebed_listening_file = fdopen(wisebed_listening_fd, "r");
	if( wisebed_listening_file == NULL )
	{
		perror( "L Pipe opening error" );
		exit(EXIT_FAILURE);
	}
	
	//******* SEND **********
	//Create the sending pipe
	if( access(wisebed_sending_pipe, F_OK ) != 0 )
		if( mkfifo(wisebed_sending_pipe, 0666) < 0 )
		{
			perror( "S Pipe creation error (/tmp/wisebed_sending_pipe)" );
			exit(EXIT_FAILURE);
		}
	
	//NOTE: The file is opened only when there is something to write
	
	//Start the Wisebed send script
	ssystem( "java -Dtestbed.secretreservationkeys=%s -Dtestbed.listtype=%s -Dtestbed.nodeurns=%s -Dtestbed.max_size=%i -jar wisebed/lib/tr.scripting-client-0.8-onejar.jar -p %s -f %s &", reservation_key, list_type, border_router_node, to_wisebed_max_size, config_path, send_java_location );
	
	//Wait 3 seconds to establish the connection
	sleep(3);    
	
	//Start the Wisebed listen script
	ssystem( "java -Dtestbed.secretreservationkeys=%s -Dtestbed.listtype=%s -Dtestbed.nodeurns=%s -jar wisebed/lib/tr.scripting-client-0.8-onejar.jar -p %s -f %s &", reservation_key, list_type, border_router_node, config_path, listen_java_location );
	
	//Wait 3 seconds to establish the connection
	sleep(3);

	//---------------------------- Create and open TUN interface -----------------------------
		
	//Create and open the tunnel file
	tunnel_fd = tun_alloc( tundev );
	if(tunnel_fd == -1) 
	{
		perror(  "Tunnel opening error" );
		exit(EXIT_FAILURE);
	}
	
	printf( "Opened tunnel device ''/dev/%s''\n", tundev );
	
	//Configure the interface
	ifconf_tun( tundev, ipaddr );
	
	//---------------------------- Loop I/O handling with FD_* macros -----------------------------
	while(1)
	{
		//This is for the select command
		int maxfd = 0;
		
		//Reset the sets
		FD_ZERO(&rset);
		
		//Set the rset for the listening pipe
		FD_SET(wisebed_listening_fd, &rset);
		if(wisebed_listening_fd > maxfd) maxfd = wisebed_listening_fd;
		//Set the rset for the tunnel
		FD_SET(tunnel_fd, &rset);
		if(tunnel_fd > maxfd) maxfd = tunnel_fd;
		
		/* Initialize the timeout data structure. */
		struct timeval timeout;
		timeout.tv_sec = 120;
		timeout.tv_usec = 0;
		
		//Wait here, until one of the files are ready or the timer expires
		int ret = select(maxfd + 1, &rset, NULL, NULL, &timeout);
		
		if( ret < 0 )
		{
			perror( "I/O handling (select) failed" );
			exit(EXIT_FAILURE);
		}
		
		//Timeout
		else if( ret == 0 )
		{
			//Send a ping to the border router to keep the connection alive
			//after 2 minutes if there wasn't any activity
			if( working_mode == WISEBED_MODE )
			{
				time_t actual_time;
				time (&actual_time);
				if(  difftime(actual_time,last_listen_time) > 119 || difftime(actual_time,last_send_time) > 119 )
				{
					printf("Keepalive ping: ");
					
					char strR[INET6_ADDRSTRLEN];
					if( inet_ntop(AF_INET6, global_address_buffer, strR, INET6_ADDRSTRLEN) != NULL )
						ssystem( "ping6 -c 1 -s 0 %s > /dev/null &", strR );
					else
						printf(" address parsing failed, is there a border router?\n" );
				}
			}
		}
		else
		{
			//Test wisebed listening pipe
			if(FD_ISSET(wisebed_listening_fd, &rset)) 
			{
				//Read from the pipe, write to the tun interface
				pipe_to_tun( wisebed_listening_file, tunnel_fd );
			}
			
			//Tunnel
			if(FD_ISSET(tunnel_fd, &rset)) 
			{
				//Read from the ipv6 tunnel and call the java send
				tun_to_buffer();
			}
		}
	}
}
void tap_side()
{
    int tap0_fd, tap1_fd;
    int maxfd;
    /* initialize tun/tap interface */
    if ((tap0_fd = tun_alloc(diface, IFF_TAP | IFF_NO_PI)) < 0) {
        fprintf(stderr, "Error connecting to tun/tap interface %s!\n",
            diface);
        return;
    }
    if ((tap1_fd = tun_alloc(iface, IFF_TAP | IFF_NO_PI)) < 0) {
        fprintf(stderr, "Error connecting to tun/tap interface %s!\n",
            iface);
        return;
    }
    printf("tap0_fd = %d tap2_fd = %d\n", tap0_fd, tap1_fd);

    maxfd = (tap0_fd > tap1_fd) ? tap0_fd : tap1_fd;
    while (1) {
        int ret;
        fd_set rd_set;
        char buf[128];

        FD_ZERO(&rd_set);
        FD_SET(tap0_fd, &rd_set);
        FD_SET(tap1_fd, &rd_set);

        ret = select(maxfd + 1, &rd_set, NULL, NULL, NULL);

        if (ret < 0 && errno == EINTR) {
            continue;
        }

        if (ret < 0) {
            perror("select()");
        }

        if (FD_ISSET(tap0_fd, &rd_set)) {
            printf("*GOT tap0 fd set\n");

            /*  
               The TX that got started from parent thread 
               sendto() fn eventually calls ->dev_hard_start_xmit()
               which will not complete unless we read from tap0 fd.
               Reading from tap0 FD causes call tun_aio_read()->
               tun_put_user() which increments the tx pkt stat of tap0
             */
            memset(buf, 0, 128);
            int bytes = cread(tap0_fd, buf, 1024);
            printf("READ %d bytes (from tap0) data: \"%s\"\n",
                   bytes, buf + ETH_HLEN);

            /*      
               The recvfrom() socket call on the tap1 will not complete
               unless a ethernet frame ends up in RX of tap1. This can
               be achieved strangely by 'write' syscall on the tap1.
               The act of write will increment the rx pkt stat on tap1
               (and recvfrom will merely give it to user)
             */

            /* Lets write() slightly modifed string into tap1 fd */
            char *ptr = buf + ETH_HLEN;
            strncpy(ptr, "Bharath", 7);
            ret = write(tap1_fd, buf, bytes);
            printf
                ("written %d bytes (modified from tap0) into tap1\n",
                 ret);
            break;
        }
        if (FD_ISSET(tap1_fd, &rd_set)) {
            printf("*GOT tap0 fd set\n");
        }
    }
}
Beispiel #5
0
int tun_open()
{
	return(tun_alloc(TUNDEV));
}
Beispiel #6
0
int
main(int argc, char **argv)
{
    int c;
    int tunfd, slipfd, maxfd;
    int ret;
    fd_set rset, wset;
    FILE *inslip;
    const char *siodev = NULL;
    const char *dhcp_server = NULL;
    u_int16_t myport = BOOTPS, dhport = BOOTPS;
    int baudrate = -2;

    ip_id = getpid() * time(NULL);

    setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */

    while ((c = getopt(argc, argv, "B:D:hs:t:")) != -1) {
        switch (c) {
            case 'B':
                baudrate = atoi(optarg);
                break;

            case 'D':
                dhcp_server = optarg;
                break;

            case 's':
                if (strncmp("/dev/", optarg, 5) == 0) {
                    siodev = optarg + 5;
                }
                else {
                    siodev = optarg;
                }

                break;

            case 't':
                if (strncmp("/dev/", optarg, 5) == 0) {
                    strcpy(tundev, optarg + 5);
                }
                else {
                    strcpy(tundev, optarg);
                }

                break;

            case '?':
            case 'h':
            default:
                err(1, "usage: tunslip [-B baudrate] [-s siodev] [-t tundev] [-D dhcp-server] ipaddress netmask [dhcp-server]");
                break;
        }
    }

    argc -= (optind - 1);
    argv += (optind - 1);

    if (argc != 3 && argc != 4) {
        err(1, "usage: tunslip [-s siodev] [-t tundev] [-D dhcp-server] ipaddress netmask [dhcp-server]");
    }

    ipaddr = argv[1];
    netmask = argv[2];
    circuit_addr = inet_addr(ipaddr);
    netaddr = inet_addr(ipaddr) & inet_addr(netmask);

    switch (baudrate) {
        case -2:
            break;			/* Use default. */

        case 9600:
            b_rate = B9600;
            break;

        case 19200:
            b_rate = B19200;
            break;

        case 38400:
            b_rate = B38400;
            break;

        case 57600:
            b_rate = B57600;
            break;

        case 115200:
            b_rate = B115200;
            break;

        default:
            err(1, "unknown baudrate %d", baudrate);
            break;
    }

    /*
     * Set up DHCP relay agent socket and find the address of this relay
     * agent.
     */
    if (argc == 4) {
        dhcp_server = argv[3];
    }

    if (dhcp_server != NULL) {
        struct sockaddr_in myaddr;
        socklen_t len;
        in_addr_t a;

        if (strchr(dhcp_server, ':') != NULL) {
            dhport = atoi(strchr(dhcp_server, ':') + 1);
            myport = dhport + 1;
            *strchr(dhcp_server, ':') = '\0';
        }

        a = inet_addr(dhcp_server);

        if (a == -1) {
            err(1, "illegal dhcp-server address");
        }

#ifndef linux
        dhaddr.sin_len = sizeof(dhaddr);
#endif
        dhaddr.sin_family = AF_INET;
        dhaddr.sin_port = htons(dhport);
        dhaddr.sin_addr.s_addr = a;

        dhsock = socket(AF_INET, SOCK_DGRAM, 0);

        if (dhsock < 0) {
            err(1, "socket");
        }

        memset(&myaddr, 0x0, sizeof(myaddr));
#ifndef linux
        myaddr.sin_len = sizeof(myaddr);
#endif
        myaddr.sin_family = AF_INET;
        myaddr.sin_addr.s_addr = INADDR_ANY;
        myaddr.sin_port = htons(myport);

        if (bind(dhsock, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
            err(1, "bind dhcp-relay");
        }

        if (connect(dhsock, (struct sockaddr *)&dhaddr, sizeof(dhaddr)) < 0) {
            err(1, "connect to dhcp-server");
        }

        len = sizeof(myaddr);

        if (getsockname(dhsock, (struct sockaddr *)&myaddr, &len) < 0) {
            err(1, "getsockname dhsock");
        }

        giaddr = myaddr.sin_addr.s_addr;

        /*
         * Don't want connected socket.
         */
        close(dhsock);
        dhsock = socket(AF_INET, SOCK_DGRAM, 0);

        if (dhsock < 0) {
            err(1, "socket");
        }

        myaddr.sin_family = AF_INET;
        myaddr.sin_addr.s_addr = INADDR_ANY;
        myaddr.sin_port = htons(myport);

        if (bind(dhsock, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
            err(1, "bind dhcp-relay");
        }

        fprintf(stderr, "DHCP server at %s:%d\n", dhcp_server, dhport);
    }

    if (siodev != NULL) {
        slipfd = devopen(siodev, O_RDWR | O_NONBLOCK);

        if (slipfd == -1) {
            err(1, "can't open siodev ``/dev/%s''", siodev);
        }
    }
    else {
        static const char *siodevs[] = {
            "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */
        };
        int i;

        for (i = 0; i < 3; i++) {
            siodev = siodevs[i];
            slipfd = devopen(siodev, O_RDWR | O_NONBLOCK);

            if (slipfd != -1) {
                break;
            }
        }

        if (slipfd == -1) {
            err(1, "can't open siodev");
        }
    }

    fprintf(stderr, "slip started on ``/dev/%s''\n", siodev);
    stty_telos(slipfd);
    slip_send(slipfd, SLIP_END);
    inslip = fdopen(slipfd, "r");

    if (inslip == NULL) {
        err(1, "main: fdopen");
    }

    tunfd = tun_alloc(tundev);

    if (tunfd == -1) {
        err(1, "main: open");
    }

    fprintf(stderr, "opened device ``/dev/%s''\n", tundev);

    atexit(cleanup);
    signal(SIGHUP, sigcleanup);
    signal(SIGTERM, sigcleanup);
    signal(SIGINT, sigcleanup);
    signal(SIGALRM, sigalarm);
    ifconf(tundev, ipaddr, netmask);

    while (1) {
        maxfd = 0;
        FD_ZERO(&rset);
        FD_ZERO(&wset);

        if (got_sigalarm) {
            /* Send "?IPA". */
            slip_send(slipfd, '?');
            slip_send(slipfd, 'I');
            slip_send(slipfd, 'P');
            slip_send(slipfd, 'A');
            slip_send(slipfd, SLIP_END);
            got_sigalarm = 0;
        }

        if (!slip_empty()) {		/* Anything to flush? */
            FD_SET(slipfd, &wset);
        }

        FD_SET(slipfd, &rset);	/* Read from slip ASAP! */

        if (slipfd > maxfd) {
            maxfd = slipfd;
        }

        /* We only have one packet at a time queued for slip output. */
        if (slip_empty()) {
            FD_SET(tunfd, &rset);

            if (tunfd > maxfd) {
                maxfd = tunfd;
            }

            if (dhsock != -1) {
                FD_SET(dhsock, &rset);

                if (dhsock > maxfd) {
                    maxfd = dhsock;
                }
            }
        }

        ret = select(maxfd + 1, &rset, &wset, NULL, NULL);

        if (ret == -1 && errno != EINTR) {
            err(1, "select");
        }
        else if (ret > 0) {
            if (FD_ISSET(slipfd, &rset)) {
                serial_to_tun(inslip, tunfd);
            }

            if (FD_ISSET(slipfd, &wset)) {
                slip_flushbuf(slipfd);
                sigalarm_reset();
            }

            if (slip_empty() && FD_ISSET(tunfd, &rset)) {
                tun_to_serial(tunfd, slipfd);
                slip_flushbuf(slipfd);
                sigalarm_reset();
            }

            if (dhsock != -1 && slip_empty() && FD_ISSET(dhsock, &rset)) {
                relay_dhcp_to_client(slipfd);
                slip_flushbuf(slipfd);
            }
        }
    }
}
Beispiel #7
0
int
main(int argc, char **argv)
{
    int c;
    int tunfd, slipfd, maxfd;
    int ret;
    fd_set rset, wset;
    FILE *inslip;
    const char *siodev = NULL;
    int baudrate = -2;
    request_mac = 1;
    setvbuf(stdout, NULL, _IOLBF, 0); /* Line buffered output. */

    while ((c = getopt(argc, argv, "B:D:hs:t:")) != -1) {
        switch (c) {
            case 'B':
                baudrate = atoi(optarg);
                break;

            case 's':
                if (strncmp("/dev/", optarg, 5) == 0) {
                    siodev = optarg + 5;
                }
                else {
                    siodev = optarg;
                }

                break;

            case 't':
                if (strncmp("/dev/", optarg, 5) == 0) {
                    strcpy(tundev, optarg + 5);
                }
                else {
                    strcpy(tundev, optarg);
                }

                break;

            case '?':
            case 'h':
            default:
                errx(1, USAGE_STRING);
                break;
        }
    }

    argc -= (optind - 1);
    argv += (optind - 1);

    if (argc != 3 && argc != 4) {
        errx(1, USAGE_STRING);
    }

    ipaddr = argv[1];
    netmask = argv[2];
    circuit_addr = inet_addr(ipaddr);
    netaddr = inet_addr(ipaddr) & inet_addr(netmask);

    switch (baudrate) {
        case -2:
            break;			/* Use default. */

        case 9600:
            b_rate = B9600;
            break;

        case 19200:
            b_rate = B19200;
            break;

        case 38400:
            b_rate = B38400;
            break;

        case 57600:
            b_rate = B57600;
            break;

        case 115200:
            b_rate = B115200;
            break;

        default:
            err(1, "unknown baudrate %d", baudrate);
            break;
    }


    if (siodev != NULL) {
        slipfd = devopen(siodev, O_RDWR | O_NONBLOCK);

        if (slipfd == -1) {
            err(1, "can't open siodev ``/dev/%s''", siodev);
        }
    }
    else {
        static const char *siodevs[] = {
            "ttyUSB0", "cuaU0", "ucom0" /* linux, fbsd6, fbsd5 */
        };
        int i;

        for (i = 0; i < 3; i++) {
            siodev = siodevs[i];
            slipfd = devopen(siodev, O_RDWR | O_NONBLOCK);

            if (slipfd != -1) {
                break;
            }
        }

        if (slipfd == -1) {
            err(1, "can't open siodev");
        }
    }

    fprintf(stderr, "slip started on ``/dev/%s''\n", siodev);
    stty_telos(slipfd);
    slip_send(slipfd, SLIP_END);
    inslip = fdopen(slipfd, "r");

    if (inslip == NULL) {
        err(1, "main: fdopen");
    }

    tunfd = tun_alloc(tundev);
    printf("opening: %s", tundev);

    if (tunfd == -1) {
        err(1, "main: open");
    }

    fprintf(stderr, "opened device ``/dev/%s''\n", tundev);

    atexit(cleanup);
    signal(SIGHUP, sigcleanup);
    signal(SIGTERM, sigcleanup);
    signal(SIGINT, sigcleanup);
    signal(SIGALRM, sigalarm);
    ifconf(tundev, ipaddr, netmask);

    while (1) {
        maxfd = 0;
        FD_ZERO(&rset);
        FD_ZERO(&wset);

        /* request mac address from gateway node for autoconfiguration of
           ethernet interface tap0 */
        if (request_mac) {
            slip_send(slipfd, '?');
            slip_send(slipfd, 'M');
            slip_send(slipfd, SLIP_END);
            request_mac = 0;
        }

        if (got_sigalarm) {
            /* Send "?IPA". */
            slip_send(slipfd, '?');
            slip_send(slipfd, 'I');
            slip_send(slipfd, 'P');
            slip_send(slipfd, 'A');
            slip_send(slipfd, SLIP_END);
            got_sigalarm = 0;
        }

        if (!slip_empty()) {		/* Anything to flush? */
            FD_SET(slipfd, &wset);
        }

        FD_SET(slipfd, &rset);	/* Read from slip ASAP! */

        if (slipfd > maxfd) {
            maxfd = slipfd;
        }

        /* We only have one packet at a time queued for slip output. */
        if (slip_empty()) {
            FD_SET(tunfd, &rset);

            if (tunfd > maxfd) {
                maxfd = tunfd;
            }
        }

        ret = select(maxfd + 1, &rset, &wset, NULL, NULL);

        if (ret == -1 && errno != EINTR) {
            err(1, "select");
        }
        else if (ret > 0) {
            if (FD_ISSET(slipfd, &rset)) {
                serial_to_tun(inslip, tunfd);
            }

            if (FD_ISSET(slipfd, &wset)) {
                slip_flushbuf(slipfd);
                sigalarm_reset();
            }

            if (slip_empty() && FD_ISSET(tunfd, &rset)) {
                tun_to_serial(tunfd, slipfd);
                slip_flushbuf(slipfd);
                sigalarm_reset();
            }
        }
    }
}