Browse Source

feat: more powerful port check

master
dnomd343 2 years ago
parent
commit
9fd6d446a6
  1. 68
      src/network.c

68
src/network.c

@ -12,30 +12,68 @@ int get_random_num(int range_start, int range_end) { // create a random number i
return range_start + (rand() % (range_end - range_start + 1));
}
int check_port_available(unsigned short port) { // test a port is available or not
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr)); // struct init
server_addr.sin_family = AF_INET; // set as IP communication
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // allow any connection
server_addr.sin_port = htons(port); // set telnet port
int server_sockfd = socket(AF_INET, SOCK_STREAM, 0); // socket created
if (server_sockfd < 0) { // create failed
return 0;
int check_port_available(unsigned int port, int is_udp, int is_ipv6) { // test a port is available or not
int ipv4_tcp_sock, ipv4_udp_sock;
int ipv6_tcp_sock, ipv6_udp_sock;
struct sockaddr_in ipv4_tcp_addr, ipv4_udp_addr;
struct sockaddr_in6 ipv6_tcp_addr, ipv6_udp_addr;
ipv4_tcp_sock = socket(AF_INET, SOCK_STREAM, 0);
bzero(&ipv4_tcp_addr, sizeof(ipv4_tcp_addr));
ipv4_tcp_addr.sin_family = AF_INET;
ipv4_tcp_addr.sin_port = htons(port);
ipv4_tcp_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(ipv4_tcp_sock, (struct sockaddr*)&ipv4_tcp_addr, sizeof(ipv4_tcp_addr)) < 0) {
return 0; // false
}
close(ipv4_tcp_sock);
if (is_udp) { // udp check
ipv4_udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
bzero(&ipv4_udp_addr, sizeof(ipv4_udp_addr));
ipv4_udp_addr.sin_family = AF_INET;
ipv4_udp_addr.sin_port = htons(port);
ipv4_udp_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(ipv4_udp_sock, (struct sockaddr*)&ipv4_udp_addr, sizeof(ipv4_udp_addr)) < 0) {
return 0; // false
}
close(ipv4_udp_sock);
}
if (!is_ipv6) { // ipv6 ignore
return 1; // true
}
if (bind(server_sockfd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)) < 0) { // bind failed
return 0;
ipv6_tcp_sock = socket(AF_INET6, SOCK_STREAM, 0);
bzero(&ipv6_tcp_addr, sizeof(ipv6_tcp_addr));
ipv6_tcp_addr.sin6_family = AF_INET6;
ipv6_tcp_addr.sin6_port = htons(port);
ipv6_tcp_addr.sin6_addr = in6addr_any;
if (bind(ipv6_tcp_sock, (struct sockaddr*)&ipv6_tcp_addr, sizeof(ipv6_tcp_addr)) < 0) {
return 0; // false
}
if (close(server_sockfd) != 0) { // close failed
return 0;
close(ipv6_tcp_sock);
if (is_udp) { // udp check
ipv6_udp_sock = socket(AF_INET6, SOCK_DGRAM, 0);
bzero(&ipv6_udp_addr, sizeof(ipv6_udp_addr));
ipv6_udp_addr.sin6_family = AF_INET6;
ipv6_udp_addr.sin6_port = htons(port);
ipv6_udp_addr.sin6_addr = in6addr_any;
if (bind(ipv6_udp_sock, (struct sockaddr*)&ipv6_udp_addr, sizeof(ipv6_udp_addr)) < 0) {
return 0; // false
}
close(ipv6_udp_sock);
}
return 1; // port available
return 1; // true
}
int get_available_port(unsigned short range_start, unsigned short range_end) { // get a available port
unsigned short port;
for (;;) { // wait until a available port in range
port = get_random_num(range_start, range_end); // get a random port in range
if (check_port_available(port)) { // port available
if (check_port_available(port, 1, 1)) { // port available
return (int)port;
}
}

Loading…
Cancel
Save