#include "monitor.h" pid_t pyfcgi_spawn_monitor() { pid_t res; res = fork(); if(res == -1) { pyfcgi_log(LOG_ALERT, "Unable to fork into monitoring server process : %s", strerror(errno)); sleep(1); } if(!res) { pyfcgi_logger_set_ident("StatServ"); pyfcgi_monitor_init(); pyfcgi_monitor_loop(); pyfcgi_log(LOG_ALERT, "Monitor loop should never return but just did it..."); exit(PYFCGI_FATAL); } return res; } void pyfcgi_monitor_init() { } void pyfcgi_monitor_loop() { } int pyfcgi_monitor_check_sock(const char* sockurl) { const char *port; short tcp; const char *urlorig; urlorig = sockurl; if(!(tcp = strncasecmp("tcp://", sockurl, 6)) || !strncasecmp("udp://", sockurl, 6)) { sockurl += 6; //first addr chr } else if(!strncasecmp("unix://", sockurl, 7)) { sockurl += 7; if(!strlen(sockurl)) { dprintf(2, "UNIX socket missing file path : '%s'\n", urlorig); return -1; } if(strlen(sockurl) > UNIX_SOCKPATH_MAX) { dprintf(2, "UNIX socket support only path with length <= %d but given path is %ld bytes long : '%s'", UNIX_SOCKPATH_MAX, strlen(sockurl), urlorig); return -1; } return 0; } else { dprintf(2, "Invalid protocol in '%s'\n", sockurl); return -1; } do { sockurl++; } while(*sockurl && *sockurl != ':'); if(!sockurl) { dprintf(2, "%s protocol choosen but not port given : '%s'\n", tcp?"TCP":"UDP", sockurl); return -1; } if(!*sockurl) { dprintf(2, "Port missing in socket URL '%s'\n", urlorig); return -1; } sockurl++; port = sockurl; while(*sockurl && *sockurl >= '0' && *sockurl <= '9') { sockurl++; } if(*sockurl) { dprintf(2, "Invalid port '%s' in socket URL '%s'\n", port, urlorig); return -1; } return 0; } int pyfcgi_monitor_parse_sock(const char *sockurl, int sockargs[3], pyfcgi_monitor_addr_t *listen_addr) { const char *addr_ptr; short tcp; int *domain, *type, *protocol; struct sockaddr_un *addr_un; domain = &sockargs[0]; type = &sockargs[1]; protocol = &sockargs[2]; addr_un = &(listen_addr->un); if(!strncasecmp("unix://", sockurl, 7)) { addr_ptr = sockurl + 7; *domain = AF_UNIX; *type = SOCK_STREAM; *protocol = 0; addr_un->sun_family = AF_UNIX; strncpy(addr_un->sun_path, addr_ptr, UNIX_SOCKPATH_MAX); return 0; } if((tcp = strncasecmp("tcp://", sockurl, 6)) && strncasecmp("udp://", sockurl, 6)) { //Unchecked URL??!! pyfcgi_log(LOG_ERR, "Invalid protocol in URL : '%s'", sockurl); return -1; } addr_ptr = sockurl + 6; *type = tcp ? SOCK_DGRAM : SOCK_STREAM; *protocol = 0; if(pyfcgi_monitor_parse_inet_addr(addr_ptr, *type, listen_addr, domain)) { return -1; } return 0; } int pyfcgi_monitor_parse_inet_addr(const char* addr_str, int socktype, pyfcgi_monitor_addr_t *listen_addr, int* domain) { char *addr, *port, *ptr, *ipstr; char v6str[64]; struct addrinfo *infos, hints, *info; short v4, v6, i; int ret; // initialize temporary address & port pointers addr = strdup(addr_str); if(!addr) { pyfcgi_log(LOG_ALERT, "strdup() failed to copy socket addr : %s", strerror(errno)); return -1; } ptr = addr; do { ptr++; }while(*ptr && *ptr != ':'); if(!ptr) { pyfcgi_log(LOG_ERR, "No port found in INET url : %s", addr_str); goto free_err; } *ptr = '\0'; port = ptr+1; memset(&hints, 0, sizeof(struct addrinfo)); v4 = PyFCGI_conf.ipv4; v6 = PyFCGI_conf.ipv6; hints.ai_family = (v4?AF_INET:(v6?AF_INET6:PF_UNSPEC)); hints.ai_socktype = socktype; hints.ai_flags = AI_CANONNAME; if((ret = getaddrinfo(addr, port, &hints, &infos))) { pyfcgi_log(LOG_ALERT, "getaddrinfo fails on '%s' : %s", gai_strerror(ret)); goto free_err; } for(info = infos; info != NULL; info = info->ai_next) { if(info->ai_family == AF_INET) { memcpy(&listen_addr->in, info->ai_addr, info->ai_addrlen); ipstr = inet_ntoa(listen_addr->in.sin_addr); } else if(info->ai_family == AF_INET6) { memcpy(&listen_addr->in6, info->ai_addr, info->ai_addrlen); ptr = v6str; for(i=0; i<16; i++) { ptr += snprintf(ptr, 4, "%s%02X", ((i==0)?"":":"), listen_addr->in6.sin6_addr.s6_addr[i]); } ipstr = v6str; } else { continue; } *domain = info->ai_family; pyfcgi_log(LOG_DEBUG, "Listen addr resolved to %s(%s)", info->ai_canonname, ipstr); freeaddrinfo(infos); free(addr); return 0; } pyfcgi_log(LOG_ERR, "Unable to resolve to a valid AF_INET[6] address"); freeaddrinfo(infos); free_err: free(addr); return -1; }