int make_sockets(SOCKET fd[2]) { /* make a pair of connected ipv4 sockets */ #ifdef INET_SOCKET_PAIR struct sockaddr_in addr; socklen_t addrlen; SOCKET s; /* temporary socket awaiting for connection */ /* create two *blocking* sockets first */ s=s_socket(AF_INET, SOCK_STREAM, 0, 0, "make_sockets: s_socket#1"); if(s==INVALID_SOCKET) return 1; fd[1]=s_socket(AF_INET, SOCK_STREAM, 0, 0, "make_sockets: s_socket#2"); if(fd[1]==INVALID_SOCKET) { closesocket(s); return 1; } addrlen=sizeof addr; memset(&addr, 0, sizeof addr); addr.sin_family=AF_INET; addr.sin_addr.s_addr=htonl(INADDR_LOOPBACK); addr.sin_port=htons(0); /* dynamic port allocation */ if(bind(s, (struct sockaddr *)&addr, addrlen)) log_error(LOG_DEBUG, get_last_socket_error(), "make_sockets: bind#1"); if(bind(fd[1], (struct sockaddr *)&addr, addrlen)) log_error(LOG_DEBUG, get_last_socket_error(), "make_sockets: bind#2"); if(listen(s, 1)) { sockerror("make_sockets: listen"); closesocket(s); closesocket(fd[1]); return 1; } if(getsockname(s, (struct sockaddr *)&addr, &addrlen)) { sockerror("make_sockets: getsockname"); closesocket(s); closesocket(fd[1]); return 1; } if(connect(fd[1], (struct sockaddr *)&addr, addrlen)) { sockerror("make_sockets: connect"); closesocket(s); closesocket(fd[1]); return 1; } fd[0]=s_accept(s, (struct sockaddr *)&addr, &addrlen, 1, "make_sockets: s_accept"); if(fd[0]==INVALID_SOCKET) { closesocket(s); closesocket(fd[1]); return 1; } closesocket(s); /* don't care about the result */ set_nonblock(fd[0], 1); set_nonblock(fd[1], 1); #else if(s_socketpair(AF_UNIX, SOCK_STREAM, 0, fd, 1, "make_sockets: socketpair")) return 1; #endif return 0; }
static void make_sockets(CLI *c, int fd[2]) { /* make a pair of connected sockets */ #ifdef INET_SOCKET_PAIR SOCKADDR_UNION addr; socklen_t addrlen; int s; /* temporary socket awaiting for connection */ s=s_socket(AF_INET, SOCK_STREAM, 0, 1, "socket#1"); if(s<0) longjmp(c->err, 1); c->fd=s_socket(AF_INET, SOCK_STREAM, 0, 1, "socket#2"); if(c->fd<0) longjmp(c->err, 1); addrlen=sizeof addr; memset(&addr, 0, addrlen); addr.in.sin_family=AF_INET; addr.in.sin_addr.s_addr=htonl(INADDR_LOOPBACK); addr.in.sin_port=htons(0); /* dynamic port allocation */ if(bind(s, &addr.sa, addrlen)) log_error(LOG_DEBUG, get_last_socket_error(), "bind#1"); if(bind(c->fd, &addr.sa, addrlen)) log_error(LOG_DEBUG, get_last_socket_error(), "bind#2"); if(listen(s, 1)) { closesocket(s); sockerror("listen"); longjmp(c->err, 1); } if(getsockname(s, &addr.sa, &addrlen)) { closesocket(s); sockerror("getsockname"); longjmp(c->err, 1); } if(connect_blocking(c, &addr, addr_len(addr))) { closesocket(s); longjmp(c->err, 1); } fd[0]=s_accept(s, &addr.sa, &addrlen, 1, "accept"); if(fd[0]<0) { closesocket(s); longjmp(c->err, 1); } fd[1]=c->fd; c->fd=-1; closesocket(s); /* don't care about the result */ #else if(s_socketpair(AF_UNIX, SOCK_STREAM, 0, fd, 1, "socketpair")) longjmp(c->err, 1); #endif }
int libwrap_init() { #ifdef USE_PTHREAD int i, j, rfd, result; char servname[SERVNAME_LEN]; static int initialized=0; SERVICE_OPTIONS *opt; if(initialized) /* during startup or previous configuration file reload */ return 0; for(opt=service_options.next; opt; opt=opt->next) if(opt->option.libwrap) /* libwrap is enabled for this service */ break; if(!opt) /* disabled for all sections or inetd mode (no sections) */ return 0; num_processes=LIBWRAP_CLIENTS; ipc_socket=str_alloc(2*num_processes*sizeof(int)); busy=str_alloc(num_processes*sizeof(int)); for(i=0; i<num_processes; ++i) { /* spawn a child */ if(s_socketpair(AF_UNIX, SOCK_STREAM, 0, ipc_socket+2*i, 0, "libwrap_init")) return 1; switch(fork()) { case -1: /* error */ ioerror("fork"); return 1; case 0: /* child */ drop_privileges(0); /* libwrap processes are not chrooted */ close(0); /* stdin */ close(1); /* stdout */ if(!global_options.option.foreground) /* for logging in read_fd */ close(2); /* stderr */ for(j=0; j<=i; ++j) /* close parent-side sockets created so far */ close(ipc_socket[2*j]); while(1) { /* main libwrap child loop */ if(read_fd(ipc_socket[2*i+1], servname, SERVNAME_LEN, &rfd)<=0) _exit(0); result=check(servname, rfd); write(ipc_socket[2*i+1], (u8 *)&result, sizeof result); if(rfd>=0) close(rfd); } default: /* parent */ close(ipc_socket[2*i+1]); /* child-side socket */ } } initialized=1; #endif /* USE_PTHREAD */ return 0; }
void libwrap_init(int num) { #ifdef USE_PTHREAD int i, j, rfd, result; char servname[SERVNAME_LEN]; num_processes=num; if(!num_processes) /* no extra processes to spawn */ return; ipc_socket=str_alloc(2*num_processes*sizeof(int)); busy=str_alloc(num_processes*sizeof(int)); if(!ipc_socket || !busy) { s_log(LOG_ERR, "Memory allocation failed"); die(1); } for(i=0; i<num_processes; ++i) { /* spawn a child */ if(s_socketpair(AF_UNIX, SOCK_STREAM, 0, ipc_socket+2*i, 0, "libwrap_init")) die(1); switch(fork()) { case -1: /* error */ ioerror("fork"); die(1); case 0: /* child */ drop_privileges(); /* libwrap processes are not chrooted */ close(0); /* stdin */ close(1); /* stdout */ if(!global_options.option.foreground) /* for logging in read_fd */ close(2); /* stderr */ for(j=0; j<=i; ++j) /* close parent-side sockets created so far */ close(ipc_socket[2*j]); while(1) { /* main libwrap child loop */ if(read_fd(ipc_socket[2*i+1], servname, SERVNAME_LEN, &rfd)<=0) _exit(0); result=check(servname, rfd); write(ipc_socket[2*i+1], (u8 *)&result, sizeof result); if(rfd>=0) close(rfd); } default: /* parent */ close(ipc_socket[2*i+1]); /* child-side socket */ } } #endif /* USE_PTHREAD */ }