/* Sets addr by hostname, or by ip in string form (AF_INET) */ int php_set_inet_addr(struct sockaddr_in *sin, char *string, php_socket *php_sock) /* {{{ */ { struct in_addr tmp; struct hostent *host_entry; if (inet_aton(string, &tmp)) { sin->sin_addr.s_addr = tmp.s_addr; } else { if (strlen(string) > MAXFQDNLEN || ! (host_entry = php_network_gethostbyname(string))) { /* Note: < -10000 indicates a host lookup error */ #ifdef PHP_WIN32 PHP_SOCKET_ERROR(php_sock, "Host lookup failed", WSAGetLastError()); #else PHP_SOCKET_ERROR(php_sock, "Host lookup failed", (-10000 - h_errno)); #endif return 0; } if (host_entry->h_addrtype != AF_INET) { php_error_docref(NULL, E_WARNING, "Host lookup failed: Non AF_INET domain returned on AF_INET socket"); return 0; } memcpy(&(sin->sin_addr.s_addr), host_entry->h_addr_list[0], host_entry->h_length); } return 1; }
/* {{{ php_gethostbyname */ static zend_string *php_gethostbyname(char *name) { struct hostent *hp; struct in_addr in; char *address; hp = php_network_gethostbyname(name); if (!hp || !*(hp->h_addr_list)) { return zend_string_init(name, strlen(name), 0); } memcpy(&in.s_addr, *(hp->h_addr_list), sizeof(in.s_addr)); address = inet_ntoa(in); return zend_string_init(address, strlen(address), 0); }
int fcgi_listen(const char *path, int backlog) { char *s; int tcp = 0; char host[MAXPATHLEN]; short port = 0; int listen_socket; sa_t sa; socklen_t sock_len; #ifdef SO_REUSEADDR # ifdef _WIN32 BOOL reuse = 1; # else int reuse = 1; # endif #endif if ((s = strchr(path, ':'))) { port = atoi(s+1); if (port != 0 && (s-path) < MAXPATHLEN) { strncpy(host, path, s-path); host[s-path] = '\0'; tcp = 1; } } else if (is_port_number(path)) { port = atoi(path); if (port != 0) { host[0] = '\0'; tcp = 1; } } /* Prepare socket address */ if (tcp) { memset(&sa.sa_inet, 0, sizeof(sa.sa_inet)); sa.sa_inet.sin_family = AF_INET; sa.sa_inet.sin_port = htons(port); sock_len = sizeof(sa.sa_inet); if (!*host || !strncmp(host, "*", sizeof("*")-1)) { sa.sa_inet.sin_addr.s_addr = htonl(INADDR_ANY); } else { sa.sa_inet.sin_addr.s_addr = inet_addr(host); if (sa.sa_inet.sin_addr.s_addr == INADDR_NONE) { struct hostent *hep; if(strlen(host) > MAXFQDNLEN) { hep = NULL; } else { hep = php_network_gethostbyname(host); } if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) { fcgi_log(FCGI_ERROR, "Cannot resolve host name '%s'!\n", host); return -1; } else if (hep->h_addr_list[1]) { fcgi_log(FCGI_ERROR, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host); return -1; } sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)hep->h_addr_list[0])->s_addr; } } } else { #ifdef _WIN32 SECURITY_DESCRIPTOR sd; SECURITY_ATTRIBUTES saw; PACL acl; HANDLE namedPipe; memset(&sa, 0, sizeof(saw)); saw.nLength = sizeof(saw); saw.bInheritHandle = FALSE; acl = prepare_named_pipe_acl(&sd, &saw); namedPipe = CreateNamedPipe(path, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_READMODE_BYTE, PIPE_UNLIMITED_INSTANCES, 8192, 8192, 0, &saw); if (namedPipe == INVALID_HANDLE_VALUE) { return -1; } listen_socket = _open_osfhandle((intptr_t)namedPipe, 0); if (!is_initialized) { fcgi_init(); } is_fastcgi = 1; return listen_socket; #else int path_len = strlen(path); if (path_len >= (int)sizeof(sa.sa_unix.sun_path)) { fcgi_log(FCGI_ERROR, "Listening socket's path name is too long.\n"); return -1; } memset(&sa.sa_unix, 0, sizeof(sa.sa_unix)); sa.sa_unix.sun_family = AF_UNIX; memcpy(sa.sa_unix.sun_path, path, path_len + 1); sock_len = (size_t)(((struct sockaddr_un *)0)->sun_path) + path_len; #ifdef HAVE_SOCKADDR_UN_SUN_LEN sa.sa_unix.sun_len = sock_len; #endif unlink(path); #endif } /* Create, bind socket and start listen on it */ if ((listen_socket = socket(sa.sa.sa_family, SOCK_STREAM, 0)) < 0 || #ifdef SO_REUSEADDR setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) < 0 || #endif bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 || listen(listen_socket, backlog) < 0) { close(listen_socket); fcgi_log(FCGI_ERROR, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno)); return -1; } if (!tcp) { chmod(path, 0777); } else { char *ip = getenv("FCGI_WEB_SERVER_ADDRS"); char *cur, *end; int n; if (ip) { ip = strdup(ip); cur = ip; n = 0; while (*cur) { if (*cur == ',') n++; cur++; } allowed_clients = malloc(sizeof(sa_t) * (n+2)); n = 0; cur = ip; while (cur) { end = strchr(cur, ','); if (end) { *end = 0; end++; } if (inet_pton(AF_INET, cur, &allowed_clients[n].sa_inet.sin_addr)>0) { allowed_clients[n].sa.sa_family = AF_INET; n++; #ifdef HAVE_IPV6 } else if (inet_pton(AF_INET6, cur, &allowed_clients[n].sa_inet6.sin6_addr)>0) { allowed_clients[n].sa.sa_family = AF_INET6; n++; #endif } else { fcgi_log(FCGI_ERROR, "Wrong IP address '%s' in listen.allowed_clients", cur); } cur = end; } allowed_clients[n].sa.sa_family = 0; free(ip); if (!n) { fcgi_log(FCGI_ERROR, "There are no allowed addresses"); /* don't clear allowed_clients as it will create an "open for all" security issue */ } } } if (!is_initialized) { fcgi_init(); } is_fastcgi = 1; #ifdef _WIN32 if (tcp) { listen_socket = _open_osfhandle((intptr_t)listen_socket, 0); } #else fcgi_setup_signals(); #endif return listen_socket; }