/** Server TCP Socket**/ TCPServer::TCPServer(unsigned short int port, const char *ip, int backlog) throw(SocketException) { if (create() == false) throw SocketException("tcp server create error"); if (reuseaddr() == false) throw SocketException("tcp server reuseaddr error"); if (bind(port, ip) == false) throw SocketException("tcp server bind error"); if (listen(backlog) == false) throw SocketException("tcp server listen error"); }
TCPServer::TCPServer(unsigned short int port, const char *ip, int backlog) { reuseaddr(); if(create()) { bind(port,ip); if(listen(backlog)==-1) { printf("Listen error\n\a"); } } }
static int bind_with_warn(int fd, const struct sockaddr *sa, socklen_t l) { assert(fd >= 0); assert(sa); assert(l > 0); if (bind(fd, sa, l) < 0) { if (errno != EADDRINUSE) { avahi_log_warn("bind() failed: %s", strerror(errno)); return -1; } avahi_log_warn("*** WARNING: Detected another %s mDNS stack running on this host. This makes mDNS unreliable and is thus not recommended. ***", sa->sa_family == AF_INET ? "IPv4" : "IPv6"); /* Try again, this time with SO_REUSEADDR set */ if (reuseaddr(fd) < 0) return -1; if (bind(fd, sa, l) < 0) { avahi_log_warn("bind() failed: %s", strerror(errno)); return -1; } } else { /* We enable SO_REUSEADDR afterwards, to make sure that the * user may run other mDNS implementations if he really * wants. */ if (reuseaddr(fd) < 0) return -1; } return 0; }
int init_client_socket(const char *host, const char *port) { int rfd=-1; int gai_ret; struct addrinfo hints; struct addrinfo *result; struct addrinfo *rp; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; hints.ai_protocol = 0; if((gai_ret=getaddrinfo(host, port, &hints, &result))) { logp("getaddrinfo: %s\n", gai_strerror(gai_ret)); return -1; } for(rp=result; rp; rp=rp->ai_next) { rfd=socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if(rfd<0) continue; if(connect(rfd, rp->ai_addr, rp->ai_addrlen) != -1) break; close_fd(&rfd); } freeaddrinfo(result); if(!rp) { /* host==NULL and AI_PASSIVE not set -> loopback */ logp("could not connect to %s:%s\n", host?host:"loopback", port); close_fd(&rfd); return -1; } reuseaddr(rfd); #ifdef HAVE_WIN32 setmode(rfd, O_BINARY); #endif return rfd; }
int udp_listener_init(struct udp_listener *u, struct poller *p, struct in6_addr ip, u_int16_t port, udp_listener_callback_t func, struct obj *obj) { struct sockaddr_in6 sin; struct poller_item i; struct udp_listener_callback *cb; cb = obj_alloc("udp_listener_callback", sizeof(*cb), NULL); cb->func = func; cb->p = obj_get_o(obj); u->fd = socket(AF_INET6, SOCK_DGRAM, 0); if (u->fd == -1) goto fail; nonblock(u->fd); reuseaddr(u->fd); ipv6only(u->fd, 0); ZERO(sin); sin.sin6_family = AF_INET6; sin.sin6_addr = ip; sin.sin6_port = htons(port); if (bind(u->fd, (struct sockaddr *) &sin, sizeof(sin))) goto fail; ZERO(i); i.fd = u->fd; i.closed = udp_listener_closed; i.readable = udp_listener_incoming; i.obj = &cb->obj; if (poller_add_item(p, &i)) goto fail; return 0; fail: if (u->fd != -1) close(u->fd); obj_put_o(obj); obj_put(cb); return -1; }
int nfslib_bindit(struct netconfig *nconf, struct netbuf **addr, struct nd_hostserv *hs, int backlog) { int fd; struct t_bind *ntb; struct t_bind tb; struct nd_addrlist *addrlist; struct t_optmgmt req, resp; struct opthdr *opt; char reqbuf[128]; bool_t use_any = FALSE; bool_t gzone = TRUE; if ((fd = nfslib_transport_open(nconf)) == -1) { syslog(LOG_ERR, "cannot establish transport service over %s", nconf->nc_device); return (-1); } addrlist = (struct nd_addrlist *)NULL; /* nfs4_callback service does not used a fieed port number */ if (strcmp(hs->h_serv, "nfs4_callback") == 0) { tb.addr.maxlen = 0; tb.addr.len = 0; tb.addr.buf = 0; use_any = TRUE; gzone = (getzoneid() == GLOBAL_ZONEID); } else if (netdir_getbyname(nconf, hs, &addrlist) != 0) { syslog(LOG_ERR, "Cannot get address for transport %s host %s service %s", nconf->nc_netid, hs->h_host, hs->h_serv); (void) t_close(fd); return (-1); } if (strcmp(nconf->nc_proto, "tcp") == 0) { /* * If we're running over TCP, then set the * SO_REUSEADDR option so that we can bind * to our preferred address even if previously * left connections exist in FIN_WAIT states. * This is somewhat bogus, but otherwise you have * to wait 2 minutes to restart after killing it. */ if (reuseaddr(fd) == -1) { syslog(LOG_WARNING, "couldn't set SO_REUSEADDR option on transport"); } } else if (strcmp(nconf->nc_proto, "udp") == 0) { /* * In order to run MLP on UDP, we need to handle creds. */ if (recvucred(fd) == -1) { syslog(LOG_WARNING, "couldn't set SO_RECVUCRED option on transport"); } } /* * Make non global zone nfs4_callback port MLP */ if (use_any && is_system_labeled() && !gzone) { if (anonmlp(fd) == -1) { /* * failing to set this option means nfs4_callback * could fail silently later. So fail it with * with an error message now. */ syslog(LOG_ERR, "couldn't set SO_ANON_MLP option on transport"); (void) t_close(fd); return (-1); } } if (nconf->nc_semantics == NC_TPI_CLTS) tb.qlen = 0; else tb.qlen = backlog; /* LINTED pointer alignment */ ntb = (struct t_bind *)t_alloc(fd, T_BIND, T_ALL); if (ntb == (struct t_bind *)NULL) { syslog(LOG_ERR, "t_alloc failed: t_errno %d, %m", t_errno); (void) t_close(fd); netdir_free((void *)addrlist, ND_ADDRLIST); return (-1); } /* * XXX - what about the space tb->addr.buf points to? This should * be either a memcpy() to/from the buf fields, or t_alloc(fd,T_BIND,) * should't be called with T_ALL. */ if (addrlist) tb.addr = *(addrlist->n_addrs); /* structure copy */ if (t_bind(fd, &tb, ntb) == -1) { syslog(LOG_ERR, "t_bind failed: t_errno %d, %m", t_errno); (void) t_free((char *)ntb, T_BIND); netdir_free((void *)addrlist, ND_ADDRLIST); (void) t_close(fd); return (-1); } /* make sure we bound to the right address */ if (use_any == FALSE && (tb.addr.len != ntb->addr.len || memcmp(tb.addr.buf, ntb->addr.buf, tb.addr.len) != 0)) { syslog(LOG_ERR, "t_bind to wrong address"); (void) t_free((char *)ntb, T_BIND); netdir_free((void *)addrlist, ND_ADDRLIST); (void) t_close(fd); return (-1); } /* * Call nfs4svc_setport so that the kernel can be * informed what port number the daemon is listing * for incoming connection requests. */ if ((nconf->nc_semantics == NC_TPI_COTS || nconf->nc_semantics == NC_TPI_COTS_ORD) && Mysvc4 != NULL) (*Mysvc4)(fd, NULL, nconf, NFS4_SETPORT, &ntb->addr); *addr = &ntb->addr; netdir_free((void *)addrlist, ND_ADDRLIST); if (strcmp(nconf->nc_proto, "tcp") == 0) { /* * Disable the Nagle algorithm on TCP connections. * Connections accepted from this listener will * inherit the listener options. */ /* LINTED pointer alignment */ opt = (struct opthdr *)reqbuf; opt->level = IPPROTO_TCP; opt->name = TCP_NODELAY; opt->len = sizeof (int); /* LINTED pointer alignment */ *(int *)((char *)opt + sizeof (*opt)) = 1; req.flags = T_NEGOTIATE; req.opt.len = sizeof (*opt) + opt->len; req.opt.buf = (char *)opt; resp.flags = 0; resp.opt.buf = reqbuf; resp.opt.maxlen = sizeof (reqbuf); if (t_optmgmt(fd, &req, &resp) < 0 || resp.flags != T_SUCCESS) { syslog(LOG_ERR, "couldn't set NODELAY option for proto %s: t_errno = %d, %m", nconf->nc_proto, t_errno); } nfslib_set_sockbuf(fd); } return (fd); }
struct control_tcp *control_tcp_new(struct poller *p, u_int32_t ip, u_int16_t port, struct callmaster *m) { int fd; struct control_tcp *c; struct poller_item i; struct sockaddr_in sin; const char *errptr; int erroff; if (!p) return NULL; if (!m) return NULL; fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) return NULL; nonblock(fd); reuseaddr(fd); ZERO(sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = ip; sin.sin_port = htons(port); if (bind(fd, (struct sockaddr *) &sin, sizeof(sin))) goto fail; if (listen(fd, 5)) goto fail; c = obj_alloc0("control", sizeof(*c), NULL); c->parse_re = pcre_compile( /* reqtype callid streams ip fromdom fromtype todom totype agent info |reqtype callid info | reqtype */ "^(?:(request|lookup)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+info=(\\S*)|(delete)\\s+(\\S+)\\s+info=(\\S*)|(build|version|controls|quit|exit|status))$", PCRE_DOLLAR_ENDONLY | PCRE_DOTALL, &errptr, &erroff, NULL); c->parse_ree = pcre_study(c->parse_re, 0, &errptr); c->fd = fd; c->poller = p; c->callmaster = m; mutex_init(&c->lock); ZERO(i); i.fd = fd; i.closed = control_closed; i.readable = control_incoming; i.obj = &c->obj; if (poller_add_item(p, &i)) goto fail2; obj_put(c); return c; fail2: obj_put(c); fail: close(fd); return NULL; }
static int init_listen_socket(const char *address, const char *port, int *fds) { int i; int gai_ret; struct addrinfo hints; struct addrinfo *rp=NULL; struct addrinfo *info=NULL; close_fds(fds); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family=AF_UNSPEC; hints.ai_socktype=SOCK_STREAM; hints.ai_protocol=IPPROTO_TCP; hints.ai_flags=AI_NUMERICHOST; hints.ai_flags|=AI_PASSIVE; if((gai_ret=getaddrinfo(address, port, &hints, &info))) { logp("unable to getaddrinfo on port %s: %s\n", port, gai_strerror(gai_ret)); return -1; } i=0; for(rp=info; rp && i<LISTEN_SOCKETS; rp=rp->ai_next) { fds[i]=socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if(fds[i]<0) { logp("unable to create socket on port %s: %s\n", port, strerror(errno)); continue; } set_keepalive(fds[i], 1); #ifdef HAVE_IPV6 if(rp->ai_family==AF_INET6) { // Attempt to say that it should not listen on IPv6 // only. int optval=0; setsockopt(fds[i], IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)); } #endif reuseaddr(fds[i]); if(bind(fds[i], rp->ai_addr, rp->ai_addrlen)) { logp("unable to bind socket on port %s: %s\n", port, strerror(errno)); close(fds[i]); fds[i]=-1; continue; } // Say that we are happy to accept connections. if(listen(fds[i], 5)<0) { close_fd(&(fds[i])); logp("could not listen on main socket %s\n", port); return -1; } #ifdef HAVE_WIN32 { u_long ioctlArg=0; ioctlsocket(fds[i], FIONBIO, &ioctlArg); } #endif i++; } freeaddrinfo(info); if(!i) { logp("could not listen on address: %s\n", address); #ifdef HAVE_IPV6 if(strchr(address, ':')) logp("maybe check whether your OS has IPv6 enabled.\n"); #endif return -1; } return 0; }
static int process_incoming_client(struct asfd *asfd, SSL_CTX *ctx, const char *conffile, struct conf **confs) { int cfd=-1; pid_t childpid; int pipe_rfd[2]; int pipe_wfd[2]; socklen_t client_length=0; struct sockaddr_storage client_name; enum asfd_fdtype fdtype=asfd->fdtype; int forking=get_int(confs[OPT_FORK]); client_length=sizeof(client_name); if((cfd=accept(asfd->fd, (struct sockaddr *)&client_name, &client_length))==-1) { // Look out, accept will get interrupted by SIGCHLDs. if(errno==EINTR) return 0; logp("accept failed on %s (%d) in %s: %s\n", asfd->desc, asfd->fd, __func__, strerror(errno)); return -1; } reuseaddr(cfd); if(log_peer_address(&client_name)) return -1; if(!forking) return run_child(&cfd, ctx, &client_name, -1, -1, conffile, forking); if(chld_check_counts(confs, asfd)) { logp("Closing new connection.\n"); close_fd(&cfd); return 0; } if(pipe(pipe_rfd)<0 || pipe(pipe_wfd)<0) { logp("pipe failed: %s", strerror(errno)); close_fd(&cfd); return -1; } switch((childpid=fork())) { case -1: logp("fork failed: %s\n", strerror(errno)); return -1; case 0: { // Child. int p; int ret; struct sigaction sa; struct async *as=asfd->as; async_asfd_free_all(&as); // Close unnecessary file descriptors. // Go up to FD_SETSIZE and hope for the best. // FIX THIS: Now that async_asfd_free_all() is doing // everything, double check whether this is needed. for(p=3; p<(int)FD_SETSIZE; p++) { if(p!=pipe_rfd[1] && p!=pipe_wfd[0] && p!=cfd) close(p); } // Set SIGCHLD back to default, so that I // can get sensible returns from waitpid. memset(&sa, 0, sizeof(sa)); sa.sa_handler=SIG_DFL; sigaction(SIGCHLD, &sa, NULL); close(pipe_rfd[0]); // close read end close(pipe_wfd[1]); // close write end confs_free_content(confs); confs_init(confs); ret=run_child(&cfd, ctx, &client_name, pipe_rfd[1], fdtype==ASFD_FD_SERVER_LISTEN_STATUS?pipe_wfd[0]:-1, conffile, forking); close(pipe_rfd[1]); close(pipe_wfd[0]); close_fd(&cfd); exit(ret); } default: // Parent. close(pipe_rfd[1]); // close write end close(pipe_wfd[0]); // close read end close_fd(&cfd); return setup_parent_child_pipes(asfd, childpid, &pipe_rfd[0], &pipe_wfd[1]); } }
BCPLWORD callc(BCPLWORD *args, BCPLWORD *g) { int rc = 0; BCPLWORD fno = args[0]; //printf("\nCallc: fno = %d\n", fno); switch(fno) { default: return -1; case c_name2ipaddr: // name => ipaddr (host format) b2c_str(args[1], namebuf); //printf("Callc c_name2ipaddr: args[1]=%d %s\n", // args[1], namebuf); return name2ipaddr(namebuf); case c_name2port: // name => port (host format) b2c_str(args[1], namebuf); //printf("callc c_name2port: %s\n", namebuf); return name2port(namebuf); case c_newsocket: // Allocate a new socket return newsocket(); case c_reuseaddr: // Reuse address return reuseaddr((int)args[1], (int)args[2]); case c_setsndbufsz: // Set the send buffer size return setsndbufsz((int)args[1], (int)args[2]); case c_setrcvbufsz: // Set the recv buffer size return setrcvbufsz((int)args[1], (int)args[2]); case c_tcpbind: // Bind a socket to a given ipaddr/port //printf("c_tcpbind: %d %08x %d\n", args[1], args[2], args[3]); return tcpbind((int)args[1], (int)args[2], (int)args[3]); case c_tcpconnect: // Connect a socket to a given ipaddr/port //printf("tcpconnect %d %08x %d\n", args[1], args[2], args[3]); return tcpconnect((int)args[1], (int)args[2], (int)args[3]); case c_tcplisten: // Cause a socket to listen return tcplisten((int)args[1], (int)args[2]); case c_tcpaccept: // Cause a socket to accept a connection return tcpaccept((int)args[1]); case c_tcpclose: // Close a connection //printf("tcpclose %d\n", args[1]); return close((int)args[1]); case c_fd_zero: // Clear all bits in an fd_set { //fd_set *bits = (fd_set*)&W[args[2]]; FD_ZERO((fd_set*)&W[args[1]]); return 0; } case c_fd_set: // Set a bit in an fd_set //printf("c_fd_set: args[1]=%d args[2]=%d\n", args[1], args[2]); FD_SET((int)args[1], (fd_set*)&W[args[2]]); return 0; case c_fd_isset: // Test a bit in an fd_set return FD_ISSET((int)args[1], (fd_set*)&W[args[2]]); case c_select: // Call the select function { int i, rc; int s = (int) args[1]; fd_set *rd_set = (fd_set *) &W[args[2]]; fd_set *wr_set = (fd_set *) &W[args[3]]; fd_set *er_set = (fd_set *) &W[args[4]]; struct timeval *timeval = (struct timeval *) ((args[5]==0) ? NULL : &W[args[5]]); /* //for(i=0; i<10;i++) // printf("callc: rdset bit %d = %d\n", i, FD_ISSET(i, (fd_set*)&W[args[2]])); */ //printf("callc: calling select(%d,%d,%d,%d,%d)\n", // args[1],args[2],args[3],args[4],args[5]); //if(timeval) { //printf("c_select: tv_sec = %d\n", timeval->tv_sec); //printf("c_select: tv_usec = %d\n", timeval->tv_usec); //} rc = select(s, rd_set, wr_set, er_set, timeval); if(rc==-1) perror("select returned error"); //printf("\ncallc: select => rc = %d\n", rc); //for(i=0; i<10;i++) // printf("callc: rdset bit %d = %d\n", // i, FD_ISSET(i, rd_set)); return rc; } case c_recv: // Call the recv(s, buf, len, flags) { int s = (int)args[1]; char *buf = (char*)&W[args[2]]; int len = (int)args[3]; int flags = (int)args[4]; int rc = 0; //printf("cfuncs: Calling recv(%d, %d, %d, %d)\n", // args[1], args[2], args[3], args[4]); rc = recv(s, buf, len, flags); if(rc==-1)perror("recv returned error"); //printf("cfuncs: recv returned rc=%d\n", rc); return rc; } case c_send: // Call the send(s, buf, len, flags) { int s = (int)args[1]; char *buf = (char*)&W[args[2]]; int len = (int)args[3]; int flags = (int)args[4]; int rc = 0; //printf("cfuncs: Calling send(%d, %d, %d, %d)\n", // args[1], args[2], args[3], args[4]); rc = send(s, buf, len, flags); if(rc==-1)perror("send returned error"); //printf("cfuncs: send returned rc=%d\n", rc); return rc; } case c_read: // Call the read(s, buf, len) { int s = (int)args[1]; char *buf = (char*)&W[args[2]]; int len = (int)args[3]; int rc = 0; //printf("cfuncs: Calling read(%d, %d, %d)\n", args[1], args[2], args[3]); rc = read(s, buf, len); //if(rc==-1)perror("read returned error"); //printf("cfuncs: read returned rc=%d\n", rc); return rc; } case c_write: // Call the write(s, buf, len) { int s = (int) args[1]; char *buf = (char*) &W[args[2]]; int len = (int) args[3]; int rc = 0; //printf("cfuncs: Calling write(%d, %d, %d)\n", args[1], args[2], args[3]); rc = write(s, buf, len); if(rc==-1)perror("read returned error"); //printf("cfuncs: read returned rc=%d\n", rc); return rc; } } }
int init_listen_socket(const char *port, int alladdr) { int rfd; int gai_ret; #ifdef HAVE_IPV6 int no = 0; int sockopt_ret = 0; #endif struct addrinfo hints; struct addrinfo *result=NULL; struct addrinfo *rp=NULL; memset(&hints, 0, sizeof(struct addrinfo)); #ifdef HAVE_IPV6 hints.ai_family = AF_INET6; #else hints.ai_family = AF_INET; #endif /* HAVE_IPV6 */ hints.ai_socktype = SOCK_STREAM; hints.ai_flags = alladdr ? AI_PASSIVE : 0; hints.ai_protocol = IPPROTO_TCP; hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; if((gai_ret=getaddrinfo(NULL, port, &hints, &result))) { logp("unable to getaddrinfo on port %s: %s\n", port, gai_strerror(gai_ret)); return -1; } for(rp=result; rp; rp=rp->ai_next) { rfd=socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if(rfd<0) { logp("unable to create socket on port %s: %s\n", port, strerror(errno)); continue; } if(!bind(rfd, rp->ai_addr, rp->ai_addrlen)) break; logp("unable to bind socket on port %s: %s\n", port, strerror(errno)); close(rfd); rfd=-1; } if(!rp || rfd<0) { logp("unable to bind listening socket on port %s\n", port); return -1; } #ifdef HAVE_IPV6 if (rp->ai_family == AF_INET6) { sockopt_ret = setsockopt(rfd, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no)); } if(!sockopt_ret) { logp("unable to change socket option to " "listen on both IPv4 and IPv6\n"); return -1; } #endif freeaddrinfo(result); reuseaddr(rfd); // Say that we are happy to accept connections. if(listen(rfd, 5)<0) { close_fd(&rfd); logp("could not listen on main socket %d\n", port); return -1; } #ifdef HAVE_WIN32 { u_long ioctlArg=0; ioctlsocket(rfd, FIONBIO, &ioctlArg); } #endif return rfd; }
static int process_incoming_client(int rfd, struct conf *conf, SSL_CTX *ctx, const char *conffile, int is_status_server) { int cfd=-1; pid_t childpid; int pipe_rfd[2]; int pipe_wfd[2]; socklen_t client_length=0; struct sockaddr_in client_name; client_length=sizeof(client_name); if((cfd=accept(rfd, (struct sockaddr *) &client_name, &client_length))==-1) { // Look out, accept will get interrupted by SIGCHLDs. if(errno==EINTR) return 0; logp("accept failed on %d: %s\n", rfd, strerror(errno)); return -1; } reuseaddr(cfd); chld_check_for_exiting(); if(!conf->forking) { if(is_status_server) return run_status_server(&rfd, &cfd, -1, conffile); else return run_child(&rfd, &cfd, ctx, conffile, conf->forking); } if(chld_add_incoming(conf, is_status_server)) { logp("Closing new connection.\n"); close_fd(&cfd); return 0; } if(pipe(pipe_rfd)<0 || pipe(pipe_wfd)<0) { logp("pipe failed: %s", strerror(errno)); close_fd(&cfd); return -1; } /* fork off our new process to handle this request */ switch((childpid=fork())) { case -1: logp("fork failed: %s\n", strerror(errno)); return -1; case 0: { int ret; // child struct sigaction sa; // Set SIGCHLD back to default, so that I // can get sensible returns from waitpid. memset(&sa, 0, sizeof(sa)); sa.sa_handler=SIG_DFL; sigaction(SIGCHLD, &sa, NULL); close(pipe_rfd[0]); // close read end close(pipe_wfd[1]); // close write end conf_free_content(conf); set_blocking(pipe_rfd[1]); status_wfd=pipe_rfd[1]; if(is_status_server) ret=run_status_server(&rfd, &cfd, pipe_wfd[0], conffile); else ret=run_child(&rfd, &cfd, ctx, conffile, conf->forking); close(pipe_rfd[1]); close(pipe_wfd[0]); exit(ret); } default: // parent close(pipe_rfd[1]); // close write end close(pipe_wfd[0]); // close read end // keep a note of the child pid. if(is_status_server) logp("forked status server child pid %d\n", childpid); else logp("forked child pid %d\n", childpid); chld_forked(childpid, pipe_rfd[0], pipe_wfd[1], is_status_server); close_fd(&cfd); return 0; } }