Interface* discoverInterfaces(Config *config, bool shouldBind) { struct ifi_info *ifi, *ifihead; struct sockaddr *sa; bool insert = false; int server_fd = 0; // Create memory for the list. Interface *list = NULL; // Use crazy code to loop through the interfaces for (ifihead = ifi = Get_ifi_info_plus(AF_INET, 1); ifi != NULL; ifi = ifi->ifi_next) { // Create node Interface *node = malloc(sizeof(Interface)); insert = false; // Null out pointers node->next = NULL; node->prev = NULL; // Copy the name of the interface strcpy(node->name, ifi->ifi_name); // Copy the IPAddress if((sa = ifi->ifi_addr) != NULL) { strcpy(node->ip_address, Sock_ntop_host(sa, sizeof(*sa))); } // Copy the network mask if((sa = ifi->ifi_ntmaddr) != NULL) { strcpy(node->network_mask, Sock_ntop_host(sa, sizeof(*sa))); } // Print out info info("<%s> [%s%s%s%s%s\b] IP: %s Mask: %s\n", node->name, ifi->ifi_flags & IFF_UP ? "UP " : "", ifi->ifi_flags & IFF_BROADCAST ? "BCAST " : "", ifi->ifi_flags & IFF_MULTICAST ? "MCAST " : "", ifi->ifi_flags & IFF_LOOPBACK ? "LOOP " : "", ifi->ifi_flags & IFF_POINTOPOINT ? "P2P " : "", node->ip_address, node->network_mask); if(shouldBind) { /* Config was successfully parsed; attempt to bind sockets */ server_fd = createServer(node->ip_address, config->port); if(server_fd != SERVER_SOCKET_BIND_FAIL) { node->sockfd = server_fd; insert = true; } else { /* Unable to bind socket to port */ fprintf(stderr, "Failed to bind socket: %s:%u\n", node->ip_address, config->port); } } else { insert = true; } // If all was successful insert into the list if(insert) { if(list == NULL) { list = node; } else { // Just push it down the list // IE: It goes in reverse discovery order node->next = list; list->prev = node; list = node; } } } free_ifi_info_plus(ifihead); return list; }
int main(int argc, char** argv) { struct datagram conn_gram; struct ifi_info *ifihead, *ifi; struct sockaddr_in servaddr; struct sockaddr_in cliaddr; fd_set rset, allset; socklen_t len; ssize_t n; int nready; int on = 1; int maxfdp1 = 0; int i; int send_flag; pid_t pid; ifihead = get_ifi_head(); printf("Server IP Addresses:\n"); print_ifi_info(ifihead); readfile(); printf("Listening port %d\n", port); count = 0; for (ifi=ifihead;ifi!=NULL;ifi=ifi->ifi_next) { if (!(ifi->ifi_flags & IFF_UP)) continue; addrs[count] = ifi; sockfds[count] = Socket(AF_INET, SOCK_DGRAM, 0); if (sockfds[count] > maxfdp1) maxfdp1 = sockfds[count]; Setsockopt(sockfds[count], SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); memcpy(&servaddr, ifi->ifi_addr, sizeof(servaddr)); servaddr.sin_port = htons(port); Bind(sockfds[count], (SA *) &servaddr, sizeof(servaddr)); count++; if (count >= MAX_IFI_COUNT) break; } FD_ZERO(&allset); FD_ZERO(&rset); for (i=0;i<count;i++) { FD_SET(sockfds[i], &allset); } maxfdp1 = maxfdp1+1; signal(SIGCHLD, sigchld); for(;;) { rset = allset; if ((nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) { if (errno == EINTR) continue; else err_sys("select error"); } for (i=0;i<count;i++) { if (FD_ISSET(sockfds[i], &rset)) { len = sizeof(cliaddr); n = recv_from(sockfds[i], &conn_gram, &cliaddr, &len); send_flag = get_flag(&conn_gram); if (!n || (send_flag & RETRY)) { // client timeout, don't fork new child continue; } printf("Client [%s:%d] connected\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port)); pid = fork(); if (!pid) { child(i, &cliaddr, &conn_gram); // exit return 0; } } } } free_ifi_info_plus(ifihead); return 0; }