/* Return a free entry in the socket entry */ int allocsock(int sock, int options) { int i; struct threaddata *td = threaddata(); for (i = 0; i < td->MAXSOCKS; i++) { if (td->socklist[i].flags & SOCK_UNUSED) { /* yay! there is table space */ td->socklist[i].handler.sock.inbuf = NULL; td->socklist[i].handler.sock.outbuf = NULL; td->socklist[i].handler.sock.inbuflen = 0; td->socklist[i].handler.sock.outbuflen = 0; td->socklist[i].flags = options; td->socklist[i].sock = sock; return i; } } /* Try again if enlarging socketlist works */ if (increase_socks_max()) return -1; else return allocsock(sock, options); }
/* Request a normal socket for i/o */ void setsock(int sock, int options) { int i = allocsock(sock, options), parm; struct threaddata *td = threaddata(); if (i == -1) { putlog(LOG_MISC, "*", "Sockettable full."); return; } if (((sock != STDOUT) || backgrd) && !(td->socklist[i].flags & SOCK_NONSOCK)) { parm = 1; setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &parm, sizeof(int)); parm = 0; setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &parm, sizeof(int)); } if (options & SOCK_LISTEN) { /* Tris says this lets us grab the same port again next time */ parm = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &parm, sizeof(int)); } /* Yay async i/o ! */ fcntl(sock, F_SETFL, O_NONBLOCK); }
int socket_create(const char *dest_ip, int dest_port, const char *src_ip, int src_port, int flags) { char *passive[] = {"::", "0.0.0.0"}; int sock = -1, pfamily, try_ok; sockname_t dest_name, src_name; /* If no source ip address is given, try :: and 0.0.0.0 (passive). */ for (try_ok = 0; try_ok < 2; try_ok++) { /* Resolve the ip addresses. */ socket_name(&dest_name, dest_ip ? dest_ip : passive[try_ok], dest_port); socket_name(&src_name, src_ip ? src_ip : passive[try_ok], src_port); if (src_ip || src_port) flags |= SOCKET_BIND; if (flags & SOCKET_CLIENT) pfamily = dest_name.family; else if (flags & SOCKET_SERVER) pfamily = src_name.family; else { errno = EADDRNOTAVAIL; return(-1); } /* Create the socket. */ if (flags & SOCKET_UDP) sock = socket(pfamily, SOCK_DGRAM, 0); else sock = socket(pfamily, SOCK_STREAM, 0); if (sock >= 0) break; } if (sock < 0) return(-2); allocsock(sock, 0); if (flags & SOCKET_NONBLOCK) socket_set_nonblock(sock, 1); /* Do the bind if necessary. */ if (flags & (SOCKET_SERVER|SOCKET_BIND)) { int yes = 1; setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)); if (bind(sock, &src_name.u.addr, src_name.len) != 0) { killsock(sock); return(-3); } if (flags & SOCKET_SERVER) listen(sock, 50); } if (flags & SOCKET_CLIENT) { int i = -1; if ((i = findanysnum(sock)) != -1) { socklist[i].flags = (socklist[i].flags & ~SOCK_VIRTUAL) | SOCK_CONNECT | SOCK_PASS; socklist[i].host = strdup(dest_ip); socklist[i].port = dest_port; } if (connect(sock, &dest_name.u.addr, dest_name.len) != 0) { if (errno != EINPROGRESS) { killsock(sock); return(-4); } } } errno = 0; /* Yay, we're done. */ return(sock); }