/* * Receive packet with synchronous timeout */ static int recv_time (int s, void *rbuf, int len, unsigned int flags, unsigned long timeout_ms) { fd_set fdset; struct timeval tmv; int rv, err; for (;;) { FD_ZERO (&fdset); FD_SET (s, &fdset); tmv.tv_sec = timeout_ms / 1000; tmv.tv_usec = (timeout_ms % 1000) * 1000; do { rv = select (s + 1, &fdset, NULL, NULL, &tmv); } while (rv == -1 && errno == EINTR); if (rv == 0) { timer (0); /* Should not return */ return -1; } set_socket_nonblock (s, 1); rv = recv (s, rbuf, len, flags); err = errno; set_socket_nonblock (s, 0); if (rv < 0) { if (E_WOULD_BLOCK (err) || err == EINTR) { continue; /* Once again, with feeling... */ } else { errno = err; return rv; } } else { return rv; } } }
static sock_t new_listening_TCP_socket(int family, uint16_t port) { sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP); if (!sock_valid(sock)) { return ~0; } #ifndef TCP_SERVER_USE_EPOLL int ok = set_socket_nonblock(sock); #else int ok = 1; #endif if (ok && family == AF_INET6) { ok = set_socket_dualstack(sock); } ok = ok && bind_to_port(sock, family, port) && (listen(sock, TCP_MAX_BACKLOG) == 0); if (!ok) { kill_sock(sock); return ~0; } return sock; }
/* return 1 on success * return 0 on failure */ static int accept_connection(TCP_Server *TCP_server, sock_t sock) { if (!sock_valid(sock)) return 0; if (!set_socket_nonblock(sock)) { kill_sock(sock); return 0; } if (!set_socket_nosigpipe(sock)) { kill_sock(sock); return 0; } TCP_Secure_Connection *conn = &TCP_server->incomming_connection_queue[TCP_server->incomming_connection_queue_index % MAX_INCOMMING_CONNECTIONS]; if (conn->status != TCP_STATUS_NO_STATUS) kill_TCP_connection(conn); conn->status = TCP_STATUS_CONNECTED; conn->sock = sock; conn->next_packet_length = 0; ++TCP_server->incomming_connection_queue_index; return 1; }
static sock_t new_listening_TCP_socket(int family, uint16_t port) { sock_t sock = socket(family, SOCK_STREAM, IPPROTO_TCP); if (!sock_valid(sock)) { return ~0; } int ok = set_socket_nonblock(sock); if (ok && family == AF_INET6) { ok = set_socket_dualstack(sock); } if (ok) { ok = set_socket_reuseaddr(sock); } ok = ok && bind_to_port(sock, family, port) && (listen(sock, TCP_MAX_BACKLOG) == 0); if (!ok) { kill_sock(sock); return ~0; } return sock; }
/* return index on success * return -1 on failure */ static int accept_connection(TCP_Server *TCP_server, Socket sock) { if (!sock_valid(sock)) { return -1; } if (!set_socket_nonblock(sock)) { kill_sock(sock); return -1; } if (!set_socket_nosigpipe(sock)) { kill_sock(sock); return -1; } uint16_t index = TCP_server->incoming_connection_queue_index % MAX_INCOMING_CONNECTIONS; TCP_Secure_Connection *conn = &TCP_server->incoming_connection_queue[index]; if (conn->status != TCP_STATUS_NO_STATUS) { kill_TCP_secure_connection(conn); } conn->status = TCP_STATUS_CONNECTED; conn->sock = sock; conn->next_packet_length = 0; ++TCP_server->incoming_connection_queue_index; return index; }
async_sock::async_sock(): pfi::network::mprpc::socket(::socket(AF_INET, SOCK_STREAM, 0)), state_(CLOSED), progress_(0) { // FIXME: SOCK_NONBLOCK is linux only if (!set_socket_nonblock(this->get(), true)) throw JUBATUS_EXCEPTION(rpc_internal_error() << jubatus::exception::error_api_func("fcntl") << jubatus::exception::error_errno(errno)); unpacker_.reserve_buffer(4096); }
static int tcp_connect(TNetWorkMsg *_ptNetWorkMsg, const char *_pcIP, int _iPort) { if(NULL == _ptNetWorkMsg || NULL == _pcIP) { dbg(); return ERR; } int iRet = ERR; unsigned int ul; dbgprintf(0, "start tcp connect to %s:%d", _ptNetWorkMsg->m_pcIp, _ptNetWorkMsg->m_iPort); fd_set rdevents,wrevents,exevents; struct timeval tv; socklen_t sLen; struct sockaddr_in ptDestAddr; if(INVALID_SOCKET == _ptNetWorkMsg->m_iSocket) { struct linger so_linger; _ptNetWorkMsg->m_iSocket = socket(AF_INET, SOCK_STREAM, 0); if(INVALID_SOCKET == _ptNetWorkMsg->m_iSocket) { dbg(); iRet = ERR; goto EXIT; } so_linger.l_onoff = 1; so_linger.l_linger = 0; iRet = setsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(so_linger)); int cnt = SO_RCVBUF_LEN; iRet = setsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_RCVBUF, (int *)&cnt,sizeof(int)); cnt = SO_SNDBUF_LEN; iRet = setsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_SNDBUF, (int *)&cnt, sizeof(int)); } #if 0 // 绑定指定网卡或IP strut sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_addr.s_addr = xxx; sin.sin_port = xxx; bind(sock, (struct sockaddr *)&sin, sizeof(sin)); // 绑定结束 #endif //设置为非阻塞模式 ul = 1; ioctl(_ptNetWorkMsg->m_iSocket, FIONBIO, &ul); // 指定地址和端口 memset(&ptDestAddr, 0, sizeof(struct sockaddr_in)); ptDestAddr.sin_family = AF_INET; ptDestAddr.sin_port = htons(_iPort); ptDestAddr.sin_addr.s_addr = inet_addr(_pcIP); // 与服务器端建立连接 iRet = connect(_ptNetWorkMsg->m_iSocket,(struct sockaddr*)&ptDestAddr, sizeof(ptDestAddr)); dbgint(iRet); dbgint(errno); if(-1 == iRet && errno != EINPROGRESS) { dbg(); iRet = ERR; goto EXIT; } //若没有直接连接成功则需要等待 if(0 != iRet) { //把先前的套接字加到读集合里面 FD_ZERO(&rdevents); FD_SET(_ptNetWorkMsg->m_iSocket, &rdevents); wrevents = rdevents; //异常集合 exevents = rdevents; #if 1 //设置时间为5秒 tv.tv_sec = 5; tv.tv_usec = 0; #else //设置时间为10秒 tv.tv_sec = 10; tv.tv_usec = 0; #endif iRet = select(_ptNetWorkMsg->m_iSocket + 1, &rdevents, &wrevents, &exevents, &tv); dbgint(iRet); if(iRet <= 0) { dbg(); dbgint(errno); //错误处理 iRet = ERR; goto EXIT; } #if 0 else if(0 == iRet) { //超时处理 close(_pConnection->m_iSocKet); _pConnection->m_iSocKet = INVALID_SOCKET; iRet = ERR; goto leave; } #endif else { if(2 == iRet) { int iErr; int iLen = sizeof(iErr); getsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_ERROR, &iErr, (socklen_t*)&iLen); if(iErr) { //dbg(); dbgint(errno); //超时处理 iRet = ERR; goto EXIT; } } //套接字已经准备好 if(_ptNetWorkMsg->m_iSocket < 0) { dbg(); dbgint(errno); iRet = ERR; goto EXIT; } if(!FD_ISSET(_ptNetWorkMsg->m_iSocket, &rdevents) && !FD_ISSET(_ptNetWorkMsg->m_iSocket, &wrevents)) { dbg(); dbgint(errno); iRet = ERR; goto EXIT; } if (getsockopt(_ptNetWorkMsg->m_iSocket, SOL_SOCKET, SO_ERROR, &iRet, &sLen) < 0) { //perror("getsockopt "); dbg(); dbgint(errno); } #if 0 if (iRet != 0) { dbg(); } #endif if(2 == iRet) { dbg(); dbgint(errno); iRet = ERR; goto EXIT; } //到这里说明connect()正确返回 } } iRet = OK; set_socket_nonblock(_ptNetWorkMsg->m_iSocket); #if 0 iRet = epoll_add_connection(_ptConnection, 1); if(iRet!=0) { iRet = ERR; goto EXIT; } #endif EXIT: if(OK != iRet && INVALID_SOCKET != _ptNetWorkMsg->m_iSocket) { //dbg(); close(_ptNetWorkMsg->m_iSocket); _ptNetWorkMsg->m_iSocket = INVALID_SOCKET; } return iRet; }
int main(int argc,char* argv[]) { int status; char* config = CONFIG; char* optstr = "vc:?"; struct sockaddr_in cli_addr; socklen_t len_sock; struct epoll_event* ep_events; struct epoll_event event; //must have 2 paraments if(argc == 1) { print_usage(); return 0; } //get the command line paraments while( (opt = getopt(argc,argv,optstr) )!= -1) { switch (opt) { case 'c': config = optstr; break; case 'v': printf("0.1VERSION\n"); break; case '?': print_usage(); return 0; } } // print the debug file sev_debug("config file: %s \n"); // read the config file,check if success char buff[BUFLEN]; as_conf* config = (as_conf*)malloc(sizeof(as_conf)); status = read_config(config,buff,config,BUFLEN); if(status != OK) { log_err("read config file error !"); exit(-1); } int listen_fd; listen_fd = creat_sockfd(9000); status = set_socket_nonblock(listen_fd); if(status != OK) { log_err("set sock fd block err!"); exit(-1); } //create epoll ctl fd //malloc set of events int epfd = as_epoll_create(EPOLLSIZE); ep_events = (struct epoll_event*)malloc(EPOLLSIZE*sizeof(struct epoll_event)); //construct event and register event to the set event.data.fd = listen_fd; event.events = EPOLLIN | EPOLLET; as_epoll_add(epfd,listen_fd,&event); //initial the thread pool // the pool use singleton pattern, pool is defined in .h init_pool(10); //main loop while(1) { int n_eves; n_eves = as_epoll_wait(epfd,ep_events,MAXEVESZ,TIMEOUT); int i,cli_fd; for(i=0;i<n_eves;i++) { cli_fd = ep_events[i].data.fd; if(listen_fd == cli_fd) { //some new clients ask to accept //accept,make_non_block,add_event //len_sock int fd = accept(listen_fd,(struct sockaddr*)&cli_addr,&len_sock); if(fd < 0) { //log_err log_err("accept cli fd error ! \n"); break; } //set fd non block //check status if normal status = set_socket_nonblock(fd); //set event paraments event.data.fd = fd; event.events = EPOLLIN | EPOLLET; //add event-->epoll as_epoll_add(epfd,fd,&event); } else { //accepted client's data ready to do_resquest //or need to close //how to detect the fd is a close signal if( (ep_events[i].events & EPOLLERR)|| (ep_events[i].events & EPOLLHUP) || !(ep_events[i].events & EPOLLIN) ) { //log_info..need to close this client fd close(fd); continue; } //log_info need to do the resquest printf("new task client:%d \n",fd); status = pool_addtask(do_resquest,&cli_fd); printf("task from client:%d status:%d",fd,status); } } // need to fill timeout func. //printf("if timer end,the server will stop !\n"); if(!as_timer()) { log_info("long time no resquest,this server is about to out of service!"); break; } } destroy_pool(pool); return 0; }
/** * Same as eConnect() except you may the specify address family here (default is * AF_UNSPEC). * We couldn't just add the new family arg to eConnect because the original one * is pure virtual declared in EClientSocketBase. Thanks C++ design crap ... */ bool EPosixClientSocket::eConnect2( const char *host, unsigned int port, int clientId, int family ) { // already connected? if( m_fd >= 0) { assert(false); // for now we don't allow that return true; } // initialize Winsock DLL (only for Windows) if ( !SocketsInit()) { // Does this set errno? getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), "Initializing Winsock DLL failed."); return false; } // use local machine if no host passed in if ( !( host && *host)) { host = "127.0.0.1"; } // starting to connect to server struct addrinfo *aitop; int s = resolveHost( host, port, family, &aitop ); if( s != 0 ) { SocketsDestroy(); const char *err; #ifdef HAVE_GETADDRINFO err = gai_strerror(s); #else err = "Invalid address, hostname resolving not supported."; #endif getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), err ); return false; } int con_errno = 0; for( struct addrinfo *ai = aitop; ai != NULL; ai = ai->ai_next ) { // create socket m_fd = socket(ai->ai_family, ai->ai_socktype, 0); if( m_fd < 0) { con_errno = errno; continue; } /* Set socket O_NONBLOCK. If wanted we could handle errors (portability!) We could even make O_NONBLOCK optional. */ int sn = set_socket_nonblock( m_fd ); assert( sn == 0 ); // try to connect if( timeout_connect( m_fd, ai->ai_addr, ai->ai_addrlen ) < 0 ) { con_errno = errno; SocketClose(m_fd); m_fd = -1; continue; } /* successfully connected */ break; } freeaddrinfo(aitop); /* connection failed, tell the error which happened in our last try */ if( m_fd < 0 ) { const char *err = strerror(con_errno); SocketsDestroy(); getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), err ); return false; } // set client id setClientId( clientId); errno = 0; onConnectBase(); if( !isOutBufferEmpty() ) { /* For now we consider it as error if it's not possible to send an integer string within a single tcp packet. Here we don't know weather ::send() really failed or not. If so then we hopefully still have it's errno set.*/ const char *err = (errno != 0) ? strerror(errno) : "Sending client id failed."; eDisconnect(); getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), err ); return false; } if( wait_socket( m_fd, WAIT_READ ) <= 0 ) { const char *err = (errno != 0) ? strerror(errno) : strerror(ENODATA); eDisconnect(); getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), err ); return false; } while( !isConnected() ) { assert( isSocketOK() ); // need to be handled if send() would destroy it if ( !checkMessagesConnect()) { const char *err = (errno != 0) ? strerror(errno) : "The remote host closed the connection."; eDisconnect(); getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), err ); return false; } } // successfully connected return true; }
int main (int argc, char **argv) { struct tftphdr *tp; struct passwd *pw; struct options *opt; struct sockaddr_in myaddr; struct sockaddr_in bindaddr; int n; int fd = 0; int standalone = 0; /* Standalone (listen) mode */ char *address = NULL; /* Address to listen to */ pid_t pid; mode_t my_umask = 0; int spec_umask = 0; int c; int setrv; int waittime = 900; /* Default time to wait for a connect */ const char *user = "******"; /* Default user */ char *p, *ep; #ifdef WITH_REGEX char *rewrite_file = NULL; #endif /* basename() is way too much of a pain from a portability standpoint */ p = strrchr (argv[0], '/'); __progname = (p && p[1]) ? p + 1 : argv[0]; openlog (__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); while ((c = getopt (argc, argv, "cspvVla:u:U:r:t:m:")) != -1) switch (c) { case 'c': cancreate = 1; break; case 's': secure = 1; break; case 'p': unixperms = 1; break; case 'l': standalone = 1; break; case 'a': address = optarg; break; case 't': waittime = atoi (optarg); break; case 'u': user = optarg; break; case 'U': my_umask = strtoul (optarg, &ep, 8); if (*ep) { syslog (LOG_ERR, "Invalid umask: %s", optarg); exit (EX_USAGE); } spec_umask = 1; break; case 'r': for (opt = options; opt->o_opt; opt++) { if (!strcasecmp (optarg, opt->o_opt)) { opt->o_opt = ""; /* Don't support this option */ break; } } if (!opt->o_opt) { syslog (LOG_ERR, "Unknown option: %s", optarg); exit (EX_USAGE); } break; #ifdef WITH_REGEX case 'm': if (rewrite_file) { syslog (LOG_ERR, "Multiple -m options"); exit (EX_USAGE); } rewrite_file = optarg; break; #endif case 'v': verbosity++; break; case 'V': /* Print configuration to stdout and exit */ printf ("%s\n", TFTPD_CONFIG_STR); exit (0); break; default: usage (); break; } dirs = xmalloc ((argc - optind + 1) * sizeof (char *)); for (ndirs = 0; optind != argc; optind++) dirs[ndirs++] = argv[optind]; dirs[ndirs] = NULL; if (secure) { if (ndirs == 0) { syslog (LOG_ERR, "no -s directory"); exit (EX_USAGE); } if (ndirs > 1) { syslog (LOG_ERR, "too many -s directories"); exit (EX_USAGE); } if (chdir (dirs[0])) { syslog (LOG_ERR, "%s: %m", dirs[0]); exit (EX_NOINPUT); } } pw = getpwnam (user); if (!pw) { syslog (LOG_ERR, "no user %s: %m", user); exit (EX_NOUSER); } if (spec_umask || !unixperms) umask (my_umask); /* Note: on Cygwin, select() on a nonblocking socket becomes a nonblocking select. */ #ifndef __CYGWIN__ set_socket_nonblock (fd, 1); #endif #ifdef WITH_REGEX if (rewrite_file) rewrite_rules = read_remap_rules (rewrite_file); #endif /* If we're running standalone, set up the input port */ if (standalone) { fd = socket (PF_INET, SOCK_DGRAM, 0); memset (&bindaddr, 0, sizeof bindaddr); bindaddr.sin_family = AF_INET; bindaddr.sin_addr.s_addr = INADDR_ANY; bindaddr.sin_port = htons (IPPORT_TFTP); if (address) { char *portptr, *eportptr; struct hostent *hostent; struct servent *servent; unsigned long port; address = tfstrdup (address); portptr = strrchr (address, ':'); if (portptr) *portptr++ = '\0'; if (*address) { hostent = gethostbyname (address); if (!hostent || hostent->h_addrtype != AF_INET) { syslog (LOG_ERR, "cannot resolve local bind address: %s", address); exit (EX_NOINPUT); } memcpy (&bindaddr.sin_addr, hostent->h_addr, hostent->h_length); } else { /* Default to using INADDR_ANY */ } if (portptr && *portptr) { servent = getservbyname (portptr, "udp"); if (servent) { bindaddr.sin_port = servent->s_port; } else if ((port = strtoul (portptr, &eportptr, 0)) && !*eportptr) { bindaddr.sin_port = htons (port); } else if (!strcmp (portptr, "tftp")) { /* It's TFTP, we're OK */ } else { syslog (LOG_ERR, "cannot resolve local bind port: %s", portptr); exit (EX_NOINPUT); } } } if (bind (fd, (struct sockaddr *) &bindaddr, sizeof bindaddr) < 0) { syslog (LOG_ERR, "cannot bind to local socket: %m"); exit (EX_OSERR); } /* Daemonize this process */ { pid_t f = fork (); int nfd; if (f > 0) exit (0); if (f < 0) { syslog (LOG_ERR, "cannot fork: %m"); exit (EX_OSERR); } nfd = open ("/dev/null", O_RDWR); if (nfd >= 0) { #ifdef HAVE_DUP2 dup2 (nfd, 0); dup2 (nfd, 1); dup2 (nfd, 2); #else close (0); dup (nfd); close (1); dup (nfd); close (2); dup (nfd); #endif close (nfd); } else { close (0); close (1); close (2); } #ifdef HAVE_SETSID #ifndef __CYGWIN__ /* Kills the process on Cygwin? */ setsid (); #endif #endif } } else { /* 0 is our socket descriptor */ close (1); close (2); } /* This means we don't want to wait() for children */ #ifdef SA_NOCLDWAIT set_signal (SIGCHLD, SIG_IGN, SA_NOCLDSTOP | SA_NOCLDWAIT); #else set_signal (SIGCHLD, SIG_IGN, SA_NOCLDSTOP); #endif /* Take SIGHUP and use it to set a variable. This is polled synchronously to make sure we don't lose packets as a result. */ set_signal (SIGHUP, handle_sighup, 0); while (1) { fd_set readset; struct timeval tv_waittime; int rv; if (caught_sighup) { caught_sighup = 0; if (standalone) { #ifdef HAVE_REGEX if (rewrite_file) { freerules (rewrite_rules); rewrite_rules = read_remap_rules (rewrite_file); } #endif } else { /* Return to inetd for respawn */ exit (0); } } FD_ZERO (&readset); FD_SET (fd, &readset); tv_waittime.tv_sec = waittime; tv_waittime.tv_usec = 0; #ifdef __CYGWIN__ /* On Cygwin, select() on a nonblocking socket returns immediately, with a rv of 0! */ set_socket_nonblock (fd, 0); #endif /* Never time out if we're in standalone mode */ rv = select (fd + 1, &readset, NULL, NULL, standalone ? NULL : &tv_waittime); if (rv == -1 && errno == EINTR) continue; /* Signal caught, reloop */ if (rv == -1) { syslog (LOG_ERR, "select loop: %m"); exit (EX_IOERR); } else if (rv == 0) { exit (0); /* Timeout, return to inetd */ } #ifdef __CYGWIN__ set_socket_nonblock (fd, 1); #endif fromlen = sizeof (from); n = myrecvfrom (fd, buf, sizeof (buf), 0, (struct sockaddr *) &from, &fromlen, &myaddr); if (n < 0) { if (E_WOULD_BLOCK (errno) || errno == EINTR) { continue; /* Again, from the top */ } else { syslog (LOG_ERR, "recvfrom: %m"); exit (EX_IOERR); } } if (standalone && myaddr.sin_addr.s_addr == INADDR_ANY) { /* myrecvfrom() didn't capture the source address; but we might have bound to a specific address, if so we should use it */ memcpy (&myaddr.sin_addr, &bindaddr.sin_addr, sizeof bindaddr.sin_addr); } /* * Now that we have read the request packet from the UDP * socket, we fork and go back to listening to the socket. */ pid = fork (); if (pid < 0) { syslog (LOG_ERR, "fork: %m"); exit (EX_OSERR); /* Return to inetd, just in case */ } else if (pid == 0) break; /* Child exit, parent loop */ } /* Child process: handle the actual request here */ /* Ignore SIGHUP */ set_signal (SIGHUP, SIG_IGN, 0); #ifdef HAVE_TCPWRAPPERS /* Verify if this was a legal request for us. This has to be done before the chroot, while /etc is still accessible. */ request_init (&wrap_request, RQ_DAEMON, __progname, RQ_FILE, fd, RQ_CLIENT_SIN, &from, RQ_SERVER_SIN, &myaddr, 0); sock_methods (&wrap_request); if (hosts_access (&wrap_request) == 0) { if (deny_severity != -1) syslog (deny_severity, "connection refused from %s", inet_ntoa (from.sin_addr)); exit (EX_NOPERM); /* Access denied */ } else if (allow_severity != -1) { syslog (allow_severity, "connect from %s", inet_ntoa (from.sin_addr)); } #endif /* Close file descriptors we don't need */ close (fd); /* Get a socket. This has to be done before the chroot(), since some systems require access to /dev to create a socket. */ peer = socket (AF_INET, SOCK_DGRAM, 0); if (peer < 0) { syslog (LOG_ERR, "socket: %m"); exit (EX_IOERR); } /* Set up the supplementary group access list if possible */ /* /etc/group still need to be accessible at this point */ #ifdef HAVE_INITGROUPS setrv = initgroups (user, pw->pw_gid); if (setrv) { syslog (LOG_ERR, "cannot set groups for user %s", user); exit (EX_OSERR); } #else #ifdef HAVE_SETGROUPS if (setgroups (0, NULL)) { syslog (LOG_ERR, "cannot clear group list"); } #endif #endif /* Chroot and drop privileges */ if (secure) { if (chroot (".")) { syslog (LOG_ERR, "chroot: %m"); exit (EX_OSERR); } #ifdef __CYGWIN__ chdir ("/"); /* Cygwin chroot() bug workaround */ #endif } #ifdef HAVE_SETREGID setrv = setregid (pw->pw_gid, pw->pw_gid); #else setrv = setegid (pw->pw_gid) || setgid (pw->pw_gid); #endif #ifdef HAVE_SETREUID setrv = setrv || setreuid (pw->pw_uid, pw->pw_uid); #else /* Important: setuid() must come first */ setrv = setrv || setuid (pw->pw_uid) || (geteuid () != pw->pw_uid && seteuid (pw->pw_uid)); #endif if (setrv) { syslog (LOG_ERR, "cannot drop privileges: %m"); exit (EX_OSERR); } /* Other basic setup */ from.sin_family = AF_INET; /* Process the request... */ myaddr.sin_port = htons (0); /* We want a new local port */ if (bind (peer, (struct sockaddr *) &myaddr, sizeof myaddr) < 0) { syslog (LOG_ERR, "bind: %m"); exit (EX_IOERR); } if (connect (peer, (struct sockaddr *) &from, sizeof from) < 0) { syslog (LOG_ERR, "connect: %m"); exit (EX_IOERR); } tp = (struct tftphdr *) buf; tp->th_opcode = ntohs (tp->th_opcode); if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) tftp (tp, n); exit (0); }
/* Create new TCP connection to ip_port/public_key */ TCP_Client_Connection *new_TCP_connection(IP_Port ip_port, const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key, TCP_Proxy_Info *proxy_info) { if (networking_at_startup() != 0) { return NULL; } if (ip_port.ip.family != AF_INET && ip_port.ip.family != AF_INET6) { return NULL; } uint8_t family = ip_port.ip.family; TCP_Proxy_Info default_proxyinfo; if (proxy_info == NULL) { default_proxyinfo.proxy_type = TCP_PROXY_NONE; proxy_info = &default_proxyinfo; } if (proxy_info->proxy_type != TCP_PROXY_NONE) { family = proxy_info->ip_port.ip.family; } Socket sock = net_socket(family, TOX_SOCK_STREAM, TOX_PROTO_TCP); if (!sock_valid(sock)) { return NULL; } if (!set_socket_nosigpipe(sock)) { kill_sock(sock); return 0; } if (!(set_socket_nonblock(sock) && connect_sock_to(sock, ip_port, proxy_info))) { kill_sock(sock); return NULL; } TCP_Client_Connection *temp = (TCP_Client_Connection *)calloc(sizeof(TCP_Client_Connection), 1); if (temp == NULL) { kill_sock(sock); return NULL; } temp->sock = sock; memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE); encrypt_precompute(temp->public_key, self_secret_key, temp->shared_key); temp->ip_port = ip_port; temp->proxy_info = *proxy_info; switch (proxy_info->proxy_type) { case TCP_PROXY_HTTP: temp->status = TCP_CLIENT_PROXY_HTTP_CONNECTING; proxy_http_generate_connection_request(temp); break; case TCP_PROXY_SOCKS5: temp->status = TCP_CLIENT_PROXY_SOCKS5_CONNECTING; proxy_socks5_generate_handshake(temp); break; case TCP_PROXY_NONE: temp->status = TCP_CLIENT_CONNECTING; if (generate_handshake(temp) == -1) { kill_sock(sock); free(temp); return NULL; } break; } temp->kill_at = unix_time() + TCP_CONNECTION_TIMEOUT; return temp; }