#include #include #include #include #include #define MIN_TCP_PORT 1 #define TCP_TABLE "/proc/net/tcp" #define TCP_TABLE_LINE_LENGTH 151 #define LOCALHOST_HEX "0100007F" #define WILDCARD_HEX "00000000" #define LISTENING_HEX "0A" #define PORTS_BLOCKS_TO_ALLOW 4 /** * Get all the listening TCP ports */ static unsigned short *get_listening_ports(unsigned short *listening_ports, FILE *tcp_table_fptr) { char line[TCP_TABLE_LINE_LENGTH]; char delimiter[] = " "; unsigned short len = 0; char *address; char *state; char *field; size_t allowed_for_ports = PORTS_BLOCKS_TO_ALLOW; // Skip first line (header) fgets(line, sizeof(line), tcp_table_fptr); // Tokenize lines one by one while (fgets(line, sizeof(line), tcp_table_fptr) != NULL) { strtok(line, delimiter); address = strtok(NULL, delimiter); strtok(NULL, delimiter); state = strtok(NULL, delimiter); field = strtok(NULL, delimiter); while (field != NULL) { field = strtok(NULL, delimiter); } if ((!strncmp(address, LOCALHOST_HEX, 8) || !strncmp(address, WILDCARD_HEX, 8)) && !strncmp(state, LISTENING_HEX, 2)) { if (len == allowed_for_ports) { allowed_for_ports = allowed_for_ports + PORTS_BLOCKS_TO_ALLOW; listening_ports = realloc(listening_ports, allowed_for_ports * sizeof(unsigned short)); } listening_ports[len] = strtol(address + strlen(address) - 4, NULL, 16); len++; } } if (len == allowed_for_ports) { allowed_for_ports = allowed_for_ports + PORTS_BLOCKS_TO_ALLOW; listening_ports = realloc(listening_ports, allowed_for_ports * sizeof(unsigned short)); } listening_ports[len] = 0; return listening_ports; } static unsigned char is_port_available(const unsigned short port, const unsigned short *listening_ports) { unsigned short i = 0; while (listening_ports[i] != 0 && listening_ports[i] != port) { i++; } return listening_ports[i] == 0; } static inline unsigned char is_valid_tcp_port(const unsigned short tcp_port) { return tcp_port >= MIN_TCP_PORT; } int main(int argc, char *argv[]) { unsigned short current_port; if (argc >= 2) { current_port = atoi(argv[1]); } else { current_port = 0; } if (!is_valid_tcp_port(current_port)) { fprintf(stderr, "Provide a valid TCP port number as first argument.\n"); return EX_USAGE; } // Open TCP table FILE *tcp_table_fptr = fopen(TCP_TABLE, "r"); if (tcp_table_fptr == NULL) { fprintf(stderr, "Error opening the TCP table.\n"); return EX_OSFILE; } unsigned short *listening_ports = malloc(PORTS_BLOCKS_TO_ALLOW * sizeof(unsigned short)); listening_ports = get_listening_ports(listening_ports, tcp_table_fptr); // Check if the current port is available, add while (!is_port_available(current_port, listening_ports)) { current_port++; } free(listening_ports); if (is_valid_tcp_port(current_port)) { printf("%d\n", current_port); return EXIT_SUCCESS; } else { fprintf(stderr, "No more ports available. How did you fuck up that bad ???\n"); return EX_TEMPFAIL; } }