/* Authentication (Client side) */ int auth_client(int fd, struct vtun_host *host, int * reason) { char buf[VTUN_MESG_SIZE], chal[VTUN_CHAL_SIZE]; int stage, success=0 ; stage = ST_INIT; *reason = D_NOREAD; while( readn_t(fd, buf, VTUN_MESG_SIZE, vtun.timeout) > 0 ){ *reason = D_OTHER; buf[sizeof(buf)-1]='\0'; switch( stage ){ case ST_INIT: if (!strncmp(buf, "VTRUNKD", 7)) { stage = ST_HOST; print_p(fd,"HOST: %s\n",host->host); continue; } *reason = D_GREET; break; case ST_HOST: if( !strncmp(buf,"OK",2) && cs2cl(buf,chal)){ stage = ST_CHAL; encrypt_chal(chal,host->passwd); print_p(fd,"CHAL: %s\n", cl2cs(chal)); continue; } *reason = D_CHAL; break; case ST_CHAL: if( !strncmp(buf,"OK",2) && cf2bf(buf,host) ) success = 1; else *reason = D_PWD; break; } break; } return success; }
/* Authentication (Server side) */ struct vtun_host * auth_server(int fd) { char chal_req[VTUN_CHAL_SIZE], chal_res[VTUN_CHAL_SIZE]; char buf[VTUN_MESG_SIZE], *str1, *str2; struct vtun_host *h = NULL; char *host = NULL; int stage; set_title("authentication"); print_p(fd,"VTUN server ver %s\n",VTUN_VER); stage = ST_HOST; while( readn_t(fd, buf, VTUN_MESG_SIZE, vtun.timeout) > 0 ){ buf[sizeof(buf)-1]='\0'; strtok(buf,"\r\n"); if( !(str1=strtok(buf," :")) ) break; if( !(str2=strtok(NULL," :")) ) break; switch( stage ){ case ST_HOST: if( !strcmp(str1,"HOST") ){ host = strdup(str2); gen_chal(chal_req); print_p(fd,"OK CHAL: %s\n", cl2cs(chal_req)); stage = ST_CHAL; continue; } break; case ST_CHAL: if( !strcmp(str1,"CHAL") ){ if( !cs2cl(str2,chal_res) ) break; if( !(h = find_host(host)) ) break; decrypt_chal(chal_res, h->passwd); if( !memcmp(chal_req, chal_res, VTUN_CHAL_SIZE) ){ /* Auth successeful. */ /* Lock host */ if( lock_host(h) < 0 ){ /* Multiple connections are denied */ h = NULL; break; } print_p(fd,"OK FLAGS: %s\n", bf2cf(h)); } else h = NULL; } break; } break; } if( host ) free(host); if( !h ) print_p(fd,"ERR\n"); return h; }
//add by adonis for multiple interfaces int udp_session_fs1(struct vtun_host *host) { struct sockaddr_in saddr; short port; int s, opt; vtun_syslog(LOG_ERR, "in udp_session_fs1"); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); /* Set local address and port */ vtun_syslog(LOG_ERR, "in local_addr"); local_addr(&saddr, host, 1); vtun_syslog(LOG_ERR, "after local_addr"); vtun_syslog(LOG_ERR, "debug %d", host->sport[1]); vtun_syslog(LOG_ERR, "debug %d, %s", host->sport[1], host->saddr[1].ip); saddr.sin_port = host->sport[1]; saddr.sin_addr.s_addr = inet_addr(host->saddr[1].ip); vtun_syslog(LOG_ERR, "before bind"); if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket %s", strerror(errno)); return -1; } opt = sizeof(saddr); if (getsockname(s, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } vtun_syslog(LOG_ERR, "after bind"); /* Write port of the new UDP socket */ port = saddr.sin_port; if (write_n(host->rmt_fd2, (char *) &port, sizeof(short)) < 0) { vtun_syslog(LOG_ERR, "Can't write port number"); return -1; } host->sopt.lport = htons(port); vtun_syslog(LOG_ERR, "after port ex send"); /* Read port of the other's end UDP socket */ if (readn_t(host->rmt_fd2, &port, sizeof(short), host->timeout) < 0) { vtun_syslog(LOG_ERR, "Can't read port number %s", strerror(errno)); return -1; } vtun_syslog(LOG_ERR, "after port ex recv"); opt = sizeof(saddr); if (getpeername(host->rmt_fd2, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get peer name"); return -1; } saddr.sin_port = port; if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } host->sopt.rport = htons(port); host->rmt_sock2 = saddr; /* Close TCP socket and replace with UDP socket */ close(host->rmt_fd2); host->rmt_fd2 = s; //add by Kai for multiple interfaces host->fs[1].saddr = saddr; host->fs[1].fd = s; host->fs[1].fd_flag = 1; //end add vtun_syslog(LOG_INFO, "UDP 1 connection initialized"); return s; }
int udp_session(struct vtun_host *host) { struct sockaddr_in saddr; short port; int s, opt; extern int is_rmt_fd_connected; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); /* Set local address and port */ local_addr(&saddr, host, 1); if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket"); return -1; } opt = sizeof(saddr); if (getsockname(s, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } /* Write port of the new UDP socket */ port = saddr.sin_port; if (write_n(host->rmt_fd, (char *) &port, sizeof(short)) < 0) { vtun_syslog(LOG_ERR, "Can't write port number"); return -1; } host->sopt.lport = htons(port); /* Read port of the other's end UDP socket */ if (readn_t(host->rmt_fd, &port, sizeof(short), host->timeout) < 0) { vtun_syslog(LOG_ERR, "Can't read port number %s", strerror(errno)); return -1; } opt = sizeof(saddr); if (getpeername(host->rmt_fd, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get peer name"); return -1; } saddr.sin_port = port; /* if the config says to delay the UDP connection, we wait for an incoming packet and then force a connection back. We need to put this here because we need to keep that incoming triggering packet and pass it back up the chain. */ if (VTUN_USE_NAT_HACK(host)) is_rmt_fd_connected = 0; else { if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } is_rmt_fd_connected = 1; } host->sopt.rport = htons(port); /* Close TCP socket and replace with UDP socket */ close(host->rmt_fd); host->rmt_fd = s; vtun_syslog(LOG_INFO, "UDP connection initialized"); return s; }
int udp_session2(struct vtun_host *host) { struct sockaddr_in saddr; short port; int s, opt; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); /* Set local address and port */ local_addr(&saddr, host, 1); saddr.sin_port = host->sport[0]; saddr.sin_addr.s_addr = inet_addr(host->saddr[0].ip); if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket %s", strerror(errno)); return -1; } opt = sizeof(saddr); if (getsockname(s, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } /* Write port of the new UDP socket */ port = saddr.sin_port; if (write_n(host->rmt_fd, (char *) &port, sizeof(short)) < 0) { vtun_syslog(LOG_ERR, "Can't write port number"); return -1; } host->sopt.lport = htons(port); /* Read port of the other's end UDP socket */ if (readn_t(host->rmt_fd, &port, sizeof(short), host->timeout) < 0) { vtun_syslog(LOG_ERR, "Can't read port number %s", strerror(errno)); return -1; } opt = sizeof(saddr); if (getpeername(host->rmt_fd, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get peer name"); return -1; } saddr.sin_port = port; if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } host->sopt.rport = htons(port); host->rmt_sock = saddr; /* Close TCP socket and replace with UDP socket */ close(host->rmt_fd); host->rmt_fd = s; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket2"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); /* Set local address and port */ saddr.sin_port = host->sport[1]; saddr.sin_addr.s_addr = inet_addr(host->saddr[1].ip); vtun_syslog(LOG_ERR, "address %s:%d", host->saddr[0].ip, host->sport[0]); vtun_syslog(LOG_ERR, "address %s:%d", host->saddr[1].ip, host->sport[1]); vtun_syslog(LOG_ERR, "address %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket2 (%d:%s)", errno, strerror(errno)); return -1; } saddr.sin_port = host->dport[1]; saddr.sin_addr.s_addr = inet_addr(host->daddr[1].ip); if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket2 "); return -1; } host->rmt_sock2 = saddr; host->rmt_fd2 = s; //vtun.rmt_sock2 = saddr; //vtun.rmt_fd2 = s; vtun_syslog(LOG_INFO, "UDP connection initialized"); return s; }
/* * Establish UDP session with host connected to fd(socket). * Returns connected UDP socket or -1 on error. */ int udp_session(struct vtun_host *host) { struct sockaddr_in saddr; short port; int s, opt; int buflen = 10; char buf[10]; char ipstr[INET_ADDRSTRLEN]; vtun_syslog(LOG_INFO, "UDP connection initialized %d,%d", host->rmt_fd, host->rmt_fd2); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); /* Set local address and port */ local_addr(&saddr, host, 1); saddr.sin_port = htons(host->sport[0]); saddr.sin_addr.s_addr = inet_addr(host->saddr[0].ip); errno = 0; if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket %s (%s:%d)", strerror(errno), host->saddr[0].ip, host->sport[0]); return -1; } opt = sizeof(saddr); if (getsockname(s, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } host->fs[0].saddr = saddr; /* if we are not just binding port number then we are server*/ if (host->role == 1) { vtun_syslog(LOG_INFO, "udp_session for server 1"); /* Write port of the new UDP socket */ port = saddr.sin_port; if (write_n(host->rmt_fd, (char *) &port, sizeof(short)) < 0) { vtun_syslog(LOG_ERR, "Can't write port number"); return -1; } vtun_syslog(LOG_INFO, "Waiting for UDP ACK 1, wrote port %d", port); opt = sizeof(saddr); while (recvfrom(s, (char *) &port, sizeof(short), 0, (struct sockaddr *) &saddr, &opt) <= 0) ; vtun_syslog(LOG_INFO, "UDP ACK 1 from %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); host->fs[0].daddr.sin_family = saddr.sin_family; host->fs[0].daddr.sin_port = saddr.sin_port; host->fs[0].daddr.sin_addr.s_addr = saddr.sin_addr.s_addr; inet_ntop(AF_INET, &(host->fs[0].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "%s:%d", ipstr, ntohs(host->fs[0].daddr.sin_port)); if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } write_n(s, (char *) &port, sizeof(short)); vtun_syslog(LOG_INFO, "FINAL ACK SENT 1"); } else { //vtun_syslog(LOG_INFO,"udp_session for client 1"); /* Read port of the other's end UDP socket */ if (readn_t(host->rmt_fd, (char *) &port, sizeof(short), host->timeout) < 0) { vtun_syslog(LOG_ERR, "Can't read port number %s", strerror(errno)); return -1; } vtun_syslog(LOG_INFO, "Recieved port %d info from server 1", port); opt = sizeof(saddr); if (getpeername(host->rmt_fd, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get peer name"); return -1; } saddr.sin_port = port; sendto(s, (char *) &port, sizeof(short), 0, (struct sockaddr *) &saddr, opt); vtun_syslog(LOG_INFO, "Sent ACK on UDP 1"); host->fs[0].daddr = saddr; if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } read_n(s, (char *) &port, sizeof(short)); vtun_syslog(LOG_INFO, "Connected & Recived final ACK 1"); } /* Why we need this ??*/ host->sopt.rport = htons(port); host->rmt_sock = saddr; /* Close TCP socket and replace with UDP socket */ close(host->rmt_fd); host->rmt_fd = s; //add by Kai for multiple interfaces // host->fs[0].daddr = saddr; host->fs[0].fd = s; host->fs[0].fd_flag = 1; s = 0; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); /* Set local address and port */ local_addr(&saddr, host, 1); saddr.sin_port = htons(host->sport[1]); saddr.sin_addr.s_addr = inet_addr(host->saddr[1].ip); if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket"); return -1; } opt = sizeof(saddr); if (getsockname(s, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } host->fs[1].saddr = saddr; /* if we are not just binding port number then we are server*/ //if(saddr.sin_addr.s_addr == inet_addr("0.0.0.0")){ if (host->role == 1) { vtun_syslog(LOG_INFO, "udp_session for server 2"); /* Write port of the new UDP socket */ port = saddr.sin_port; if (write_n(host->rmt_fd2, (char *) &port, sizeof(short)) < 0) { vtun_syslog(LOG_ERR, "Can't write port number"); return -1; } vtun_syslog(LOG_INFO, "Waiting for UDP ACK 2 wrote port %d", port); opt = sizeof(saddr); while (recvfrom(s, (char *) &port, sizeof(short), 0, (struct sockaddr *) &saddr, &opt) <= 0) ; vtun_syslog(LOG_INFO, "UDP ACK 2 from %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); host->fs[1].daddr.sin_family = saddr.sin_family; host->fs[1].daddr.sin_port = saddr.sin_port; host->fs[1].daddr.sin_addr.s_addr = saddr.sin_addr.s_addr; inet_ntop(AF_INET, &(host->fs[1].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "%s:%d", ipstr, ntohs(host->fs[1].daddr.sin_port)); if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } write_n(s, (char *) &port, sizeof(short)); vtun_syslog(LOG_INFO, "FINAL ACK SENT 2"); } else { vtun_syslog(LOG_INFO, "udp_session for client 2"); /* Read port of the other's end UDP socket */ if (readn_t(host->rmt_fd2, (char *) &port, sizeof(short), host->timeout) < 0) { vtun_syslog(LOG_ERR, "Can't read port number %s", strerror(errno)); return -1; } opt = sizeof(saddr); if (getpeername(host->rmt_fd2, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get peer name"); return -1; } saddr.sin_port = port; vtun_syslog(LOG_INFO, "Recieved port %d info from server 2", port); sendto(s, (char *) &port, sizeof(short), 0, (struct sockaddr *) &saddr, opt); host->fs[1].daddr = saddr; if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } read_n(s, (char *) &port, sizeof(short)); vtun_syslog(LOG_INFO, "Connected & Recived final ACK 2"); } host->rmt_sock2 = saddr; /* Close TCP socket and replace with UDP socket */ close(host->rmt_fd2); host->rmt_fd2 = s; //add by Kai for multiple interfaces host->fs[1].fd = s; host->fs[1].fd_flag = 1; inet_ntop(AF_INET, &(host->fs[0].saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d ->", ipstr, ntohs(host->fs[0].saddr.sin_port)); inet_ntop(AF_INET, &(host->fs[0].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d <-", ipstr, ntohs(host->fs[0].daddr.sin_port)); inet_ntop(AF_INET, &(host->fs[1].saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d ->", ipstr, ntohs(host->fs[1].saddr.sin_port)); inet_ntop(AF_INET, &(host->fs[1].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d <-", ipstr, ntohs(host->fs[1].daddr.sin_port)); host->fs[0].saddr.sin_port = htons(4444); host->fs[0].daddr.sin_port = htons(4444); host->fs[1].saddr.sin_port = htons(4444); host->fs[1].daddr.sin_port = htons(4444); /* host->fs[0].saddr.sin_port = htons(host->dport[1]+10); host->fs[0].daddr.sin_port = htons(host->dport[1]+10); host->fs[1].saddr.sin_port = htons(host->dport[1]+10); host->fs[1].daddr.sin_port = htons(host->dport[1]+10); */ inet_ntop(AF_INET, &(host->fs[0].saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d ->", ipstr, ntohs(host->fs[0].saddr.sin_port)); inet_ntop(AF_INET, &(host->fs[0].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d <-", ipstr, ntohs(host->fs[0].daddr.sin_port)); inet_ntop(AF_INET, &(host->fs[1].saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d ->", ipstr, ntohs(host->fs[1].saddr.sin_port)); inet_ntop(AF_INET, &(host->fs[1].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, " fd is %s:%d <-", ipstr, ntohs(host->fs[1].daddr.sin_port)); vtun_syslog(LOG_INFO, "UDP connection initialized"); return s; }
int fetch_server_data(struct vtun_host *host, int i, int j) { struct sockaddr_in saddr; short port; int s, opt; int buflen = 10; char buf[10]; char ipstr[INET_ADDRSTRLEN]; opt = sizeof(saddr); vtun_syslog(LOG_ERR, "Wait for response from client on Control"); /*Wait for response from client on Control*/ while (recvfrom(host->ctrl, (char *) &port, sizeof(short), 0, (struct sockaddr *) &saddr, &opt) <= 0) ; inet_ntop(AF_INET, &(saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "recvfrom %s:%d", ipstr, ntohs(saddr.sin_port)); /*Open a UDP socket*/ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); saddr.sin_family = AF_INET; saddr.sin_port = htons(host->sport[i]); vtun_syslog(LOG_INFO, "trying to bind"); vtun_syslog(LOG_INFO, "%d %s", i, host->saddr[i].ip); saddr.sin_addr.s_addr = inet_addr(host->saddr[i].ip); vtun_syslog(LOG_ERR, "Binding with %s", host->saddr[i].ip); /*Bind a port*/ if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket"); host->fs[i].fd_flag = 0; return -1; } host->fs[i].saddr = saddr; inet_ntop(AF_INET, &(host->fs[i].saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "saddr %s:%d", ipstr, ntohs(saddr.sin_port)); opt = sizeof(saddr); if (getsockname(s, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } port = saddr.sin_port; vtun_syslog(LOG_ERR, "Send port number to Client on Control"); /*Send port number to Client on Control*/ opt = sizeof(host->fs[j].daddr); saddr = host->fs[j].daddr; saddr.sin_port = htons(host->ctrl_port); inet_ntop(AF_INET, &(saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "%s:%d", ipstr, ntohs(saddr.sin_port)); inet_ntop(AF_INET, &(host->fs[j].saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "%s:%d", ipstr, ntohs(host->fs[j].saddr.sin_port)); errno = 0; sendfromto(host->ctrl, (char *) &port, sizeof(short), 0, (struct sockaddr *) &host->fs[j].saddr, opt, (struct sockaddr *) &saddr, opt); /*Wait for PING on new Data Path*/ vtun_syslog(LOG_ERR, "Wait for PING on new Control Path %s port %d", strerror(errno), port); while (recvfrom(s, (char *) &port, sizeof(short), 0, (struct sockaddr *) &saddr, &opt) <= 0) ; host->fs[i].daddr = saddr; if (connect(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't connect socket"); return -1; } host->fs[i].fd_flag = 1; host->fs[i].fd = s; port = 0; errno = 0; vtun_syslog(LOG_ERR, "Sent PONG on new Control Path"); write_n(host->fs[i].fd, (char*) &port, sizeof(short)); vtun_syslog(LOG_ERR, "WAIT PONG on new Control Path %s", strerror(errno)); while (readn_t(host->fs[i].fd, (char*) &port, sizeof(short), host->timeout) < 0) ; vtun_syslog(LOG_ERR, "%s", strerror(errno)); /*SEND END_OF_REG*/ return 0; }
int fetch_control(struct vtun_host * host) { struct sockaddr_in saddr; short port; int s, opt; int buflen = 10; char buf[10]; char ipstr[INET_ADDRSTRLEN]; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { vtun_syslog(LOG_ERR, "Can't create socket"); return -1; } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); fcntl(s, F_SETFL, O_NONBLOCK); /* Set local address and port */ saddr.sin_family = AF_INET; saddr.sin_port = htons(host->ctrl_port); saddr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(s, (struct sockaddr *) &saddr, sizeof(saddr))) { vtun_syslog(LOG_ERR, "Can't bind to the socket"); return -1; } opt = sizeof(saddr); if (getsockname(host->rmt_fd, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } host->fs[0].saddr = saddr; if (getsockname(s, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get socket name"); return -1; } /* if we are not just binding port number then we are server*/ if (host->role == 1) { vtun_syslog(LOG_INFO, "udp_ctrl_session for server"); /* Write port of the new UDP socket */ port = saddr.sin_port; if (write_n(host->rmt_fd, (char *) &port, sizeof(short)) < 0) { vtun_syslog(LOG_ERR, "Can't write port number"); return -1; } vtun_syslog(LOG_INFO, "Waiting for UDP ACK 1, wrote port %d", port); opt = sizeof(saddr); while (recvfrom(s, (char *) &port, sizeof(short), 0, (struct sockaddr *) &saddr, &opt) <= 0) ; vtun_syslog(LOG_INFO, "UDP ACK 1 from %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); host->fs[0].daddr.sin_family = saddr.sin_family; host->fs[0].daddr.sin_port = saddr.sin_port; host->fs[0].daddr.sin_addr.s_addr = saddr.sin_addr.s_addr; inet_ntop(AF_INET, &(host->fs[0].daddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "%s:%d", ipstr, ntohs(host->fs[0].daddr.sin_port)); //sendto(s,(char *)&port,sizeof(short),0,(struct sockaddr *)&saddr,opt); errno = 0; sendfromto(s, (char *) &port, sizeof(short), 0, (struct sockaddr *) &host->fs[0].saddr, opt, (struct sockaddr *) &saddr, opt); vtun_syslog(LOG_INFO, "FINAL ACK SENT 1 %s", strerror(errno)); inet_ntop(AF_INET, &(saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "%s:%d", ipstr, ntohs(saddr.sin_port)); host->ctrl_port = ntohs(saddr.sin_port); } else { //vtun_syslog(LOG_INFO,"udp_session for client 1"); /* Read port of the other's end UDP socket */ if (readn_t(host->rmt_fd, (char *) &port, sizeof(short), host->timeout) < 0) { vtun_syslog(LOG_ERR, "Can't read port number %s", strerror(errno)); return -1; } vtun_syslog(LOG_INFO, "Recieved port %d info from server 1", port); opt = sizeof(saddr); if (getpeername(host->rmt_fd, (struct sockaddr *) &saddr, &opt)) { vtun_syslog(LOG_ERR, "Can't get peer name"); return -1; } saddr.sin_port = port; inet_ntop(AF_INET, &(saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "%s:%d", ipstr, ntohs(saddr.sin_port)); inet_ntop(AF_INET, &(host->fs[0].saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "%s:%d", ipstr, ntohs(host->fs[0].saddr.sin_port)); errno = 0; sendfromto(s, (char *) &port, sizeof(short), 0, (struct sockaddr *) &host->fs[0].saddr, opt, (struct sockaddr *) &saddr, opt); vtun_syslog(LOG_INFO, "Sent ACK on UDP 1 :%s", strerror(errno)); host->fs[0].daddr = saddr; while (recvfrom(s, (char *) &port, sizeof(short), 0, (struct sockaddr *) &saddr, &opt) <= 0) ; vtun_syslog(LOG_INFO, "Connected & Recived final ACK 1"); inet_ntop(AF_INET, &(saddr.sin_addr), ipstr, INET_ADDRSTRLEN); vtun_syslog(LOG_INFO, "%s:%d", ipstr, ntohs(saddr.sin_port)); host->ctrl_port = ntohs(saddr.sin_port); } return s; }
/* * Establish UDP session with host connected to fd(socket). * Returns connected UDP socket or -1 on error. */ int udp_session(struct vtun_host *host) { struct sockaddr_in saddr; short port; int s,opt; if( (s=socket(AF_INET,SOCK_DGRAM,0))== -1 ){ vtun_syslog(LOG_ERR,"Can't create socket"); return -1; } opt=1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); /* Set local address and port */ local_addr(&saddr, host, 1); if( bind(s,(struct sockaddr *)&saddr,sizeof(saddr)) ){ vtun_syslog(LOG_ERR,"Can't bind to the socket"); return -1; } opt = sizeof(saddr); if( getsockname(s,(struct sockaddr *)&saddr,&opt) ){ vtun_syslog(LOG_ERR,"Can't get socket name"); return -1; } /* Write port of the new UDP socket */ port = saddr.sin_port; if( write_n(host->rmt_fd,(char *)&port,sizeof(short)) < 0 ){ vtun_syslog(LOG_ERR,"Can't write port number"); return -1; } host->sopt.lport = htons(port); /* Read port of the other's end UDP socket */ if( readn_t(host->rmt_fd,&port,sizeof(short),host->timeout) < 0 ){ vtun_syslog(LOG_ERR,"Can't read port number %s", strerror(errno)); return -1; } opt = sizeof(saddr); if( getpeername(host->rmt_fd,(struct sockaddr *)&saddr,&opt) ){ vtun_syslog(LOG_ERR,"Can't get peer name"); return -1; } saddr.sin_port = port; if( connect(s,(struct sockaddr *)&saddr,sizeof(saddr)) ){ vtun_syslog(LOG_ERR,"Can't connect socket"); return -1; } host->sopt.rport = htons(port); /* Close TCP socket and replace with UDP socket */ close(host->rmt_fd); host->rmt_fd = s; vtun_syslog(LOG_INFO,"UDP connection initialized"); return s; }