diff --git a/src/server/kiwix-serve.cpp b/src/server/kiwix-serve.cpp index 4254b8c..76c02dc 100644 --- a/src/server/kiwix-serve.cpp +++ b/src/server/kiwix-serve.cpp @@ -72,6 +72,10 @@ extern "C" { #include #include #include +#include +#include +#include +#include #endif using namespace std; @@ -458,6 +462,7 @@ int main(int argc, char **argv) { string libraryPath; string indexPath; string rootPath; + string interface; int serverPort = 80; int daemonFlag = false; int libraryFlag = false; @@ -476,11 +481,12 @@ int main(int argc, char **argv) { {"index", required_argument, 0, 'i'}, {"attachToProcess", required_argument, 0, 'a'}, {"port", required_argument, 0, 'p'}, + {"interface", required_argument, 0, 'f'}, {0, 0, 0, 0} }; int option_index = 0; - int c = getopt_long(argc, argv, "ndvli:a:p:", long_options, &option_index); + int c = getopt_long(argc, argv, "ndvli:a:p:f:", long_options, &option_index); if (c != -1) { @@ -507,6 +513,9 @@ int main(int argc, char **argv) { PPIDString = string(optarg); PPID = atoi(optarg); break; + case 'f': + interface = string(optarg); + break; } } else { if (optind < argc) { @@ -521,8 +530,8 @@ int main(int argc, char **argv) { /* Print usage)) if necessary */ if (zimPath.empty() && libraryPath.empty()) { - cerr << "Usage: kiwix-serve [--index=INDEX_PATH] [--port=PORT] [--verbose] [--nosearchbar] [--daemon] [--attachToProcess=PID] ZIM_PATH" << endl; - cerr << " kiwix-serve --library [--port=PORT] [--verbose] [--daemon] [--nosearchbar] [--attachToProcess=PID] LIBRARY_PATH" << endl; + cerr << "Usage: kiwix-serve [--index=INDEX_PATH] [--port=PORT] [--verbose] [--nosearchbar] [--daemon] [--attachToProcess=PID] [--interface=IF_NAME] ZIM_PATH" << endl; + cerr << " kiwix-serve --library [--port=PORT] [--verbose] [--daemon] [--nosearchbar] [--attachToProcess=PID] [--interface=IF_NAME] LIBRARY_PATH" << endl; exit(1); } @@ -683,13 +692,64 @@ int main(int argc, char **argv) { /* Start the HTTP daemon */ void *page = NULL; - daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, - serverPort, - NULL, - NULL, - &accessHandlerCallback, - page, - MHD_OPTION_END); + if (interface.length() > 0) { + #ifndef _WIN32 + /* TBD IPv6 support */ + struct sockaddr_in sockAddr; + + struct ifaddrs *ifaddr, *ifa; + int family, n; + char host[NI_MAXHOST]; + + memset(&sockAddr,0, sizeof(sockAddr)); + + if (getifaddrs(&ifaddr) == -1) { + cerr << "Getifaddrs() failed while searching for '" << interface << "'" << endl; + exit(1); + } + for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { + if (ifa->ifa_addr == NULL) + continue; + + family = ifa->ifa_addr->sa_family; + + if (family == AF_INET) { + if (strcasecmp(ifa->ifa_name, interface.c_str()) == 0) { + sockAddr.sin_family = family; + sockAddr.sin_port = htons(serverPort); + sockAddr.sin_addr.s_addr = ((struct sockaddr_in*) ifa->ifa_addr)->sin_addr.s_addr; + break; + } + } + } + freeifaddrs(ifaddr); + if (sockAddr.sin_family == 0) { + cerr << "I couldn't find interface '" << interface << "'" << endl; + exit(1); + } + + daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, + serverPort, + NULL, + NULL, + &accessHandlerCallback, + page, + MHD_OPTION_SOCK_ADDR, + &sockAddr, + MHD_OPTION_END); + #else + cerr << "Setting interface - not yet implemented in Windows" << endl; + exit(1); + #endif + } else { + daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, + serverPort, + NULL, + NULL, + &accessHandlerCallback, + page, + MHD_OPTION_END); + } if (daemon == NULL) { cerr << "Unable to instanciate the HTTP daemon. The port " << serverPort << " is maybe already occupied or need more permissions to be open. Please try as root or with a port number higher or equal to 1024." << endl;