static int shutdown_socket(DBPROCESS *dbproc) { union { struct sockaddr sa; char data[256]; } u; SOCKLEN_T addrlen; struct stat file_stat; TDS_SYS_SOCKET sockets[2]; TDS_SYS_SOCKET socket = DBIOWDESC(dbproc); if (fstat(socket, &file_stat)) return 0; if ((file_stat.st_mode & S_IFSOCK) != S_IFSOCK) return 0; addrlen = sizeof(u); if (tds_getsockname(socket, &u.sa, &addrlen) < 0 || (u.sa.sa_family != AF_INET && u.sa.sa_family != AF_INET6)) return 0; /* replace socket with a new one */ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) return 0; /* substitute socket */ close(socket); dup2(sockets[0], socket); /* close connection */ close(sockets[0]); end_socket = sockets[1]; return 1; }
int odbc_find_last_socket(void) { int max_socket = -1, i; for (i = 3; i < 1024; ++i) { struct stat file_stat; union { struct sockaddr sa; char data[256]; } u; SOCKLEN_T addrlen; if (fstat(i, &file_stat)) continue; if ((file_stat.st_mode & S_IFSOCK) != S_IFSOCK) continue; addrlen = sizeof(u); if (tds_getsockname(i, &u.sa, &addrlen) < 0) continue; if (u.sa.sa_family != AF_INET && u.sa.sa_family != AF_INET6) continue; max_socket = i; } return max_socket; }
int tds_socketpair(int domain, int type, int protocol, int sv[2]) { struct sockaddr_in sa, sa2; SOCKLEN_T addrlen; TDS_SYS_SOCKET s; if (!sv) return -1; /* create a listener */ s = socket(AF_INET, type, 0); if (TDS_IS_SOCKET_INVALID(s)) return -1; sv[1] = INVALID_SOCKET; sv[0] = socket(AF_INET, type, 0); if (TDS_IS_SOCKET_INVALID(sv[0])) goto Cleanup; /* bind to a random port */ sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); sa.sin_port = 0; if (bind(s, (struct sockaddr*) &sa, sizeof(sa)) < 0) goto Cleanup; if (listen(s, 1) < 0) goto Cleanup; /* connect to kernel choosen port */ addrlen = sizeof(sa); if (tds_getsockname(s, (struct sockaddr*) &sa, &addrlen) < 0) goto Cleanup; if (connect(sv[0], (struct sockaddr*) &sa, sizeof(sa)) < 0) goto Cleanup; addrlen = sizeof(sa2); sv[1] = tds_accept(s, (struct sockaddr*) &sa2, &addrlen); if (TDS_IS_SOCKET_INVALID(sv[1])) goto Cleanup; /* check proper connection */ addrlen = sizeof(sa); if (tds_getsockname(sv[0], (struct sockaddr*) &sa, &addrlen) < 0) goto Cleanup; addrlen = sizeof(sa2); if (tds_getpeername(sv[1], (struct sockaddr*) &sa2, &addrlen) < 0) goto Cleanup; if (sa.sin_family != sa2.sin_family || sa.sin_port != sa2.sin_port || sa.sin_addr.s_addr != sa2.sin_addr.s_addr) goto Cleanup; CLOSESOCKET(s); return 0; Cleanup: CLOSESOCKET(s); CLOSESOCKET(sv[0]); CLOSESOCKET(sv[1]); return -1; }