void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) { void *plugin_handle = NULL; char *plugin_abs_path = NULL; char *plugin_filename = NULL; int need_free = 0; char *plugin_name = plugin; char *plugin_symbol_name_start = plugin; struct uwsgi_plugin *up; char linkpath_buf[1024], linkpath[1024]; int linkpath_size; char *colon = strchr(plugin_name, ':'); if (colon) { colon[0] = 0; modifier = atoi(plugin_name); plugin_name = colon + 1; colon[0] = ':'; } if (!uwsgi_endswith(plugin_name, "_plugin.so")) { plugin_name = uwsgi_concat2(plugin_name, "_plugin.so"); need_free = 1; } plugin_symbol_name_start = plugin_name; // step 1: check for absolute plugin (stop if it fails) if (strchr(plugin_name, '/')) { #ifdef UWSGI_ELF uwsgi_plugin_parse_section(plugin_name); #endif plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL); if (!plugin_handle) { if (!has_option) uwsgi_log("%s\n", dlerror()); goto end; } plugin_symbol_name_start = uwsgi_get_last_char(plugin_name, '/'); plugin_symbol_name_start++; plugin_abs_path = plugin_name; goto success; } // step dir, check for user-supplied plugins directory struct uwsgi_string_list *pdir = uwsgi.plugins_dir; while (pdir) { plugin_filename = uwsgi_concat3(pdir->value, "/", plugin_name); #ifdef UWSGI_ELF uwsgi_plugin_parse_section(plugin_filename); #endif plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL); if (plugin_handle) { plugin_abs_path = plugin_filename; //free(plugin_filename); goto success; } free(plugin_filename); plugin_filename = NULL; pdir = pdir->next; } // last step: search in compile-time plugin_dir if (!plugin_handle) { plugin_filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin_name); #ifdef UWSGI_ELF uwsgi_plugin_parse_section(plugin_filename); #endif plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL); plugin_abs_path = plugin_filename; //free(plugin_filename); } success: if (!plugin_handle) { if (!has_option) uwsgi_log("!!! UNABLE to load uWSGI plugin: %s !!!\n", dlerror()); } else { char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start) - 3, "", 0); up = dlsym(plugin_handle, plugin_entry_symbol); if (!up) { // is it a link ? memset(linkpath_buf, 0, 1024); memset(linkpath, 0, 1024); if ((linkpath_size = readlink(plugin_abs_path, linkpath_buf, 1023)) > 0) { do { linkpath_buf[linkpath_size] = '\0'; strncpy(linkpath, linkpath_buf, linkpath_size + 1); } while ((linkpath_size = readlink(linkpath, linkpath_buf, 1023)) > 0); #ifdef UWSGI_DEBUG uwsgi_log("%s\n", linkpath); #endif free(plugin_entry_symbol); up = dlsym(plugin_handle, plugin_entry_symbol); char *slash = uwsgi_get_last_char(linkpath, '/'); if (!slash) { slash = linkpath; } else { slash++; } plugin_entry_symbol = uwsgi_concat2n(slash, strlen(slash) - 3, "", 0); up = dlsym(plugin_handle, plugin_entry_symbol); } } if (up) { if (!up->name) { uwsgi_log("the loaded plugin (%s) has no .name attribute\n", plugin_name); if (dlclose(plugin_handle)) { uwsgi_error("dlclose()"); } if (need_free) free(plugin_name); if (plugin_filename) free(plugin_filename); free(plugin_entry_symbol); return NULL; } if (plugin_already_loaded(up->name)) { if (dlclose(plugin_handle)) { uwsgi_error("dlclose()"); } if (need_free) free(plugin_name); if (plugin_filename) free(plugin_filename); free(plugin_entry_symbol); return NULL; } if (has_option) { struct uwsgi_option *op = up->options; int found = 0; while (op && op->name) { if (!strcmp(has_option, op->name)) { found = 1; break; } op++; } if (!found) { if (dlclose(plugin_handle)) { uwsgi_error("dlclose()"); } if (need_free) free(plugin_name); if (plugin_filename) free(plugin_filename); free(plugin_entry_symbol); return NULL; } } if (modifier != -1) { fill_plugin_table(modifier, up); up->modifier1 = modifier; } else { fill_plugin_table(up->modifier1, up); } if (need_free) free(plugin_name); if (plugin_filename) free(plugin_filename); free(plugin_entry_symbol); if (up->on_load) up->on_load(); return plugin_handle; } if (!has_option) uwsgi_log("%s\n", dlerror()); } end: if (need_free) free(plugin_name); if (plugin_filename) free(plugin_filename); return NULL; }
void uwsgi_opt_https2(char *opt, char *value, void *cr) { struct uwsgi_corerouter *ucr = (struct uwsgi_corerouter *) cr; char *s2_addr = NULL; char *s2_cert = NULL; char *s2_key = NULL; char *s2_ciphers = NULL; char *s2_clientca = NULL; char *s2_spdy = NULL; if (uwsgi_kvlist_parse(value, strlen(value), ',', '=', "addr", &s2_addr, "cert", &s2_cert, "crt", &s2_cert, "key", &s2_key, "ciphers", &s2_ciphers, "clientca", &s2_clientca, "client_ca", &s2_clientca, "spdy", &s2_spdy, NULL)) { uwsgi_log("error parsing --https2 option\n"); exit(1); } if (!s2_addr || !s2_cert || !s2_key) { uwsgi_log("--https2 option needs addr, cert and key items\n"); exit(1); } struct uwsgi_gateway_socket *ugs = uwsgi_new_gateway_socket(s2_addr, ucr->name); // ok we have the socket, initialize ssl if required if (!uwsgi.ssl_initialized) { uwsgi_ssl_init(); } // initialize ssl context char *name = uhttp.https_session_context; if (!name) { name = uwsgi_concat3(ucr->short_name, "-", ugs->name); } #ifdef UWSGI_SPDY if (s2_spdy) { uhttp.spdy_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); uhttp.spdy3_settings = uwsgi_buffer_new(uwsgi.page_size); if (uwsgi_buffer_append(uhttp.spdy3_settings, "\x80\x03\x00\x04\x01", 5)) goto spdyerror; if (uwsgi_buffer_u24be(uhttp.spdy3_settings, (8 * 2) + 4)) goto spdyerror; if (uwsgi_buffer_u32be(uhttp.spdy3_settings, 2)) goto spdyerror; // SETTINGS_ROUND_TRIP_TIME if (uwsgi_buffer_append(uhttp.spdy3_settings, "\x01\x00\x00\x03", 4)) goto spdyerror; if (uwsgi_buffer_u32be(uhttp.spdy3_settings, 30 * 1000)) goto spdyerror; // SETTINGS_INITIAL_WINDOW_SIZE if (uwsgi_buffer_append(uhttp.spdy3_settings, "\x01\x00\x00\x07", 4)) goto spdyerror; if (uwsgi_buffer_u32be(uhttp.spdy3_settings, 8192)) goto spdyerror; uhttp.spdy3_settings_size = uhttp.spdy3_settings->pos; } #endif ugs->ctx = uwsgi_ssl_new_server_context(name, s2_cert, s2_key, s2_ciphers, s2_clientca); if (!ugs->ctx) { exit(1); } #ifdef UWSGI_SPDY if (s2_spdy) { SSL_CTX_set_info_callback(ugs->ctx, uwsgi_spdy_info_cb); SSL_CTX_set_next_protos_advertised_cb(ugs->ctx, uwsgi_spdy_npn, NULL); } #endif // set the ssl mode ugs->mode = UWSGI_HTTP_SSL; ucr->has_sockets++; return; #ifdef UWSGI_SPDY spdyerror: uwsgi_log("unable to initialize SPDY settings buffers\n"); exit(1); #endif }
static char *uwsgi_xslt_apply(char *xmlfile, char *xsltfile, char *params, int *rlen) { char **vparams = NULL; char *tmp_params = NULL; uint16_t count = 0; if (params) { // first count the number of items size_t i; size_t params_len = strlen(params); for(i=0;i<params_len;i++) { if (params[i] == '=') { count++; } } vparams = uwsgi_calloc( sizeof(char *) * ((count * 2) + 1)); tmp_params = uwsgi_str(params); char *p = strtok(tmp_params, "&"); int pos = 0; while(p) { char *equal = strchr(p, '='); if (equal) { *equal = 0; vparams[pos] = p; pos++; vparams[pos] = uwsgi_concat3("\"", equal+1, "\""); pos++; } p = strtok(NULL, "&"); } } // we reset them every time to avoid collision with other xml engines xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; xmlDocPtr doc = xmlParseFile(xmlfile); if (!doc) { if (vparams) { int i; for(i=1;i<(count*2);i+=2) free(vparams[i]); free(tmp_params); free(vparams); } return NULL; } xsltStylesheetPtr ss = xsltParseStylesheetFile((const xmlChar *) xsltfile); if (!ss) { xmlFreeDoc(doc); if (vparams) { int i; for(i=1;i<(count*2);i+=2) free(vparams[i]); free(tmp_params); free(vparams); } return NULL; } xmlDocPtr res = xsltApplyStylesheet(ss, doc, (const char **) vparams); if (!res) { xsltFreeStylesheet(ss); xmlFreeDoc(doc); if (vparams) { int i; for(i=1;i<(count*2);i+=2) free(vparams[i]); free(tmp_params); free(vparams); } return NULL; } xmlChar *output; int ret = xsltSaveResultToString(&output, rlen, res, ss); xsltFreeStylesheet(ss); xmlFreeDoc(res); xmlFreeDoc(doc); if (vparams) { int i; for(i=1;i<(count*2);i+=2) free(vparams[i]); free(tmp_params); free(vparams); } if (ret < 0) return NULL; return (char *) output; }
void uwsgi_check_logrotate(void) { char message[1024]; int need_rotation = 0; int need_reopen = 0; if (uwsgi.log_master) { uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR); } else { uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR); } if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) { need_rotation = 1; } if (uwsgi_check_touches(uwsgi.touch_logrotate)) { need_rotation = 1; } if (uwsgi_check_touches(uwsgi.touch_logreopen)) { need_reopen = 1; } if (need_rotation) { char *rot_name = uwsgi.log_backupname; int need_free = 0; if (rot_name == NULL) { char *ts_str = uwsgi_num2str((int) uwsgi_now()); rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str); free(ts_str); need_free = 1; } int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name); if (ret > 0) { if (write(uwsgi.original_log_fd, message, ret) != ret) { // very probably this will never be printed uwsgi_error("write()"); } } if (rename(uwsgi.logfile, rot_name) == 0) { // reopen logfile dup'it and eventually gracefully reload workers; int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP); if (fd < 0) { uwsgi_error_open(uwsgi.logfile); grace_them_all(0); } if (dup2(fd, uwsgi.original_log_fd) < 0) { uwsgi_error("dup2()"); grace_them_all(0); } close(fd); } else { uwsgi_error("unable to rotate log: rename()"); } if (need_free) free(rot_name); } else if (need_reopen) { int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize); if (ret > 0) { if (write(uwsgi.original_log_fd, message, ret) != ret) { // very probably this will never be printed uwsgi_error("write()"); } } // reopen logfile; close(uwsgi.original_log_fd); uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP); if (uwsgi.original_log_fd < 0) { uwsgi_error_open(uwsgi.logfile); grace_them_all(0); } ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile); if (ret > 0) { if (write(uwsgi.original_log_fd, message, ret) != ret) { // very probably this will never be printed uwsgi_error("write()"); } } uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR); } }
static int uwsgi_routing_func_xmldir(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){ char **subject; uint16_t *subject_len; char *dirname; struct uwsgi_buffer *ub; char *name = NULL; char *path = NULL; int i; int n; struct dirent **tasklist; xmlDoc *rdoc; xmlNode *rtree; xmlNodePtr entrynode; char *path_info = NULL; struct stat sb; size_t sizebuf_len; char *sizebuf; char timebuf[20]; int xlen = 0; subject = (char **) (((char *)(wsgi_req))+ur->subject); subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len); ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len); if (!ub) { uwsgi_500(wsgi_req); return UWSGI_ROUTE_BREAK; } dirname = ub->buf; path_info = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "", 1); n = scandir(dirname, &tasklist, 0, alphasort); if (n < 0) { uwsgi_404(wsgi_req); goto out; } rdoc = xmlNewDoc(BAD_CAST "1.0"); rtree = xmlNewNode(NULL, BAD_CAST "index"); xmlNewProp(rtree, BAD_CAST "path", BAD_CAST path_info); xmlDocSetRootElement(rdoc, rtree); for(i = 0; i < n; i++) { if ((strcmp(tasklist[i]->d_name, ".") == 0) || (strcmp(tasklist[i]->d_name, "..") == 0)) { goto next_entry; } path = uwsgi_concat3(dirname, "/", tasklist[i]->d_name); if (lstat(path, &sb) == -1) { goto next_entry; } name = to_utf8(conf.codeset, tasklist[i]->d_name); if (name == NULL) { goto next_entry; } if (S_ISDIR(sb.st_mode)) { entrynode = xmlNewTextChild(rtree, NULL, BAD_CAST "directory", BAD_CAST name); } else if (S_ISREG(sb.st_mode)) { entrynode = xmlNewTextChild(rtree, NULL, BAD_CAST "file", BAD_CAST name); } else { /* skip everything but directories and regular files */ goto next_entry; } sizebuf_len = snprintf(NULL, 0, "%jd", (intmax_t) sb.st_size); sizebuf = uwsgi_malloc(sizebuf_len + 1); snprintf(sizebuf, sizebuf_len + 1, "%jd", (intmax_t) sb.st_size); xmlNewProp(entrynode, BAD_CAST "size", BAD_CAST sizebuf); free(sizebuf); strftime(timebuf, sizeof (timebuf), "%Y-%m-%dT%H:%M:%S", localtime(&sb.st_mtime)); xmlNewProp(entrynode, BAD_CAST "mtime", BAD_CAST timebuf); next_entry: free(path); path = NULL; free(tasklist[i]); free(name); name = NULL; } free(tasklist); xmlChar *xmlbuf; xmlDocDumpFormatMemory(rdoc, &xmlbuf, &xlen, 1); uwsgi_response_prepare_headers(wsgi_req,"200 OK", 6); uwsgi_response_write_body_do(wsgi_req, (char *) xmlbuf, xlen); xmlFreeDoc(rdoc); xmlFree(xmlbuf); out: uwsgi_buffer_destroy(ub); free(path_info); return UWSGI_ROUTE_BREAK; }
void emperor_loop() { // monitor a directory struct uwsgi_instance ui_base; struct uwsgi_instance *ui_current; pid_t diedpid; int waitpid_status; int has_children = 0; int i_am_alone = 0; int i; void *events; int nevents; int interesting_fd; char notification_message[64]; struct rlimit rl; uwsgi.disable_nuclear_blast = 1; uwsgi.emperor_stats_fd = -1; if (uwsgi.emperor_pidfile) { uwsgi_write_pidfile(uwsgi.emperor_pidfile); } signal(SIGPIPE, SIG_IGN); uwsgi_unix_signal(SIGINT, royal_death); uwsgi_unix_signal(SIGTERM, royal_death); uwsgi_unix_signal(SIGQUIT, royal_death); uwsgi_unix_signal(SIGUSR1, emperor_stats); uwsgi_unix_signal(SIGHUP, emperor_massive_reload); memset(&ui_base, 0, sizeof(struct uwsgi_instance)); if (getrlimit(RLIMIT_NOFILE, &rl)) { uwsgi_error("getrlimit()"); exit(1); } uwsgi.max_fd = rl.rlim_cur; emperor_throttle_level = uwsgi.emperor_throttle; // the queue must be initialized before adding scanners uwsgi.emperor_queue = event_queue_init(); emperor_build_scanners(); events = event_queue_alloc(64); if (uwsgi.has_emperor) { uwsgi_log("*** starting uWSGI sub-Emperor ***\n"); } else { uwsgi_log("*** starting uWSGI Emperor ***\n"); } if (uwsgi.emperor_stats) { char *tcp_port = strchr(uwsgi.emperor_stats, ':'); if (tcp_port) { // disable deferred accept for this socket int current_defer_accept = uwsgi.no_defer_accept; uwsgi.no_defer_accept = 1; uwsgi.emperor_stats_fd = bind_to_tcp(uwsgi.emperor_stats, uwsgi.listen_queue, tcp_port); uwsgi.no_defer_accept = current_defer_accept; } else { uwsgi.emperor_stats_fd = bind_to_unix(uwsgi.emperor_stats, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket); } event_queue_add_fd_read(uwsgi.emperor_queue, uwsgi.emperor_stats_fd); uwsgi_log("*** Emperor stats server enabled on %s fd: %d ***\n", uwsgi.emperor_stats, uwsgi.emperor_stats_fd); } ui = &ui_base; int freq = 0; for (;;) { if (!i_am_alone) { diedpid = waitpid(uwsgi.emperor_pid, &waitpid_status, WNOHANG); if (diedpid < 0 || diedpid > 0) { i_am_alone = 1; } } nevents = event_queue_wait_multi(uwsgi.emperor_queue, freq, events, 64); freq = uwsgi.emperor_freq; for (i = 0; i < nevents; i++) { interesting_fd = event_queue_interesting_fd(events, i); if (uwsgi.emperor_stats && uwsgi.emperor_stats_fd > -1 && interesting_fd == uwsgi.emperor_stats_fd) { emperor_send_stats(uwsgi.emperor_stats_fd); continue; } // check if a monitor is mapped to that file descriptor if (uwsgi_emperor_scanner_event(interesting_fd)) { continue; } ui_current = emperor_get_by_fd(interesting_fd); if (ui_current) { char byte; ssize_t rlen = read(interesting_fd, &byte, 1); if (rlen <= 0) { // SAFE emperor_del(ui_current); } else { if (byte == 17) { ui_current->loyal = 1; ui_current->last_loyal = uwsgi_now(); uwsgi_log("[emperor] vassal %s is now loyal\n", ui_current->name); // remove it from the blacklist uwsgi_emperor_blacklist_remove(ui_current->name); // TODO post-start hook } // heartbeat can be used for spotting blocked instances else if (byte == 26) { ui_current->last_heartbeat = uwsgi_now(); } else if (byte == 22) { emperor_stop(ui_current); } else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) { uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name); char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg"); // here we discard socket name as broodlord/zerg cannot be on demand emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid, NULL); free(zerg_name); } } } else { ui_current = emperor_get_by_socket_fd(interesting_fd); if (ui_current) { event_queue_del_fd(uwsgi.emperor_queue, ui_current->on_demand_fd, event_queue_read()); if (uwsgi_emperor_vassal_start(ui_current)) { emperor_del(ui_current); } } else { uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd); close(interesting_fd); } } } uwsgi_emperor_run_scanners(); // check for heartbeat (if required) ui_current = ui->ui_next; while (ui_current) { if (ui_current->last_heartbeat > 0) { if ((ui_current->last_heartbeat + uwsgi.emperor_heartbeat) < uwsgi_now()) { uwsgi_log("[emperor] vassal %s sent no heartbeat in last %d seconds, respawning it...\n", ui_current->name, uwsgi.emperor_heartbeat); // set last_heartbeat to 0 avoiding races ui_current->last_heartbeat = 0; emperor_respawn(ui_current, uwsgi_now()); } } ui_current = ui_current->ui_next; } // check for removed instances ui_current = ui; has_children = 0; while (ui_current->ui_next) { ui_current = ui_current->ui_next; if (ui_current->pid > -1) { has_children++; } } if (uwsgi.notify) { if (snprintf(notification_message, 64, "The Emperor is governing %d vassals", has_children) >= 34) { uwsgi_notify(notification_message); } } if (has_children) { diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG); } else { // vacuum waitpid(WAIT_ANY, &waitpid_status, WNOHANG); diedpid = 0; } if (diedpid < 0) { // it looks like it happens when OOM is triggered to Linux cgroup, but it could be a uWSGI bug :P // by the way, fallback to a clean situation... if (errno == ECHILD) { uwsgi_log("--- MUTINY DETECTED !!! IMPALING VASSALS... ---\n"); ui_current = ui->ui_next; while (ui_current) { struct uwsgi_instance *rebel_vassal = ui_current; ui_current = ui_current->ui_next; emperor_del(rebel_vassal); } } else { uwsgi_error("waitpid()"); } } ui_current = ui; while (ui_current->ui_next) { ui_current = ui_current->ui_next; if (ui_current->status == 1) { if (ui_current->config) free(ui_current->config); // SAFE emperor_del(ui_current); break; } else if (ui_current->pid == diedpid) { if (ui_current->status == 0) { // respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) { // SAFE emperor_del(ui_current); } else { // UNSAFE emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid, ui_current->socket_name); emperor_del(ui_current); } break; } else if (ui_current->status == 1) { // remove 'marked for dead' instance if (ui_current->config) free(ui_current->config); // SAFE emperor_del(ui_current); break; } } } } }
static int action_failoverip(struct uwsgi_legion *ul, char *arg) { int ret = -1; char *url = NULL; char *auth = NULL; struct hetzner_failoverip_config hfc; memset(&hfc, 0, sizeof(struct hetzner_failoverip_config)); if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=', "username", &hfc.username, "password", &hfc.password, "user", &hfc.username, "pass", &hfc.password, "url", &hfc.url, "timeout", &hfc.timeout, "ip", &hfc.ip, "active_ip", &hfc.active_ip, "active_server_ip", &hfc.active_ip, "ssl_no_verify", &hfc.ssl_no_verify, NULL)) { uwsgi_log("unable to parse hetzner-failopeverip options\n"); return -1; } if (!hfc.username || !hfc.password || !hfc.ip || !hfc.active_ip) { uwsgi_log("hetzner-failopeverip action requires username, password, ip and active_ip keys\n"); goto clear; } if (hfc.url) { url = uwsgi_str(hfc.url); } else { url = uwsgi_concat2(HETNZER_FAILOVERIP_URL, hfc.ip); } struct curl_httppost *formpost = NULL; struct curl_httppost *lastptr=NULL; curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "active_server_ip", CURLFORM_COPYCONTENTS, hfc.active_ip, CURLFORM_END); CURL *curl = curl_easy_init(); if (!curl) { curl_formfree(formpost); goto clear; } int timeout = 60; if (hfc.timeout) timeout = atoi(hfc.timeout); curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); auth = uwsgi_concat3(hfc.username, ":", hfc.password); curl_easy_setopt(curl, CURLOPT_USERPWD, auth); if (hfc.ssl_no_verify) { curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); } curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, hetzner_curl_writefunc); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { uwsgi_log("[hetzner-failoverip] curl error: %s\n", curl_easy_strerror(res)); curl_formfree(formpost); curl_easy_cleanup(curl); goto clear; } long http_code = 0; #ifdef CURLINFO_RESPONSE_CODE curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); #else curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &http_code); #endif // allows Ok and Conflict uwsgi_log("[hetzner-failoverip] HTTP status code: %ld\n", http_code); if (http_code == 200 || http_code == 409) { ret = 0; } curl_formfree(formpost); curl_easy_cleanup(curl); clear: if (url) free(url); if (auth) free(auth); if (hfc.username) free(hfc.username); if (hfc.password) free(hfc.password); if (hfc.url) free(hfc.url); if (hfc.timeout) free(hfc.timeout); if (hfc.ip) free(hfc.ip); if (hfc.active_ip) free(hfc.active_ip); if (hfc.ssl_no_verify) free(hfc.ssl_no_verify); return ret; }
void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) { socklen_t socket_type_len; union uwsgi_sockaddr_ptr gsa, isa; union uwsgi_sockaddr usa; int abstract = 0; socket_type_len = sizeof(struct sockaddr_un); gsa.sa = &usa.sa; if (!getsockname(fd, gsa.sa, &socket_type_len)) { if (socket_type_len <= 2) { // unbound socket return; } if (gsa.sa->sa_family == AF_UNIX) { if (usa.sa_un.sun_path[0] == 0) abstract = 1; // is it a zerg ? if (uwsgi_sock->name == NULL) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_UNIX; uwsgi_sock->bound = 1; uwsgi_sock->name = uwsgi_concat2(usa.sa_un.sun_path + abstract, ""); if (uwsgi.zerg) { uwsgi_log("uwsgi zerg socket %d attached to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), usa.sa_un.sun_path + abstract, uwsgi_sock->fd); } else { uwsgi_log("uwsgi socket %d attached to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), usa.sa_un.sun_path + abstract, uwsgi_sock->fd); } return; } if (!uwsgi_startswith(uwsgi_sock->name, "fd://", 5)) { if (atoi(uwsgi_sock->name + 5) == fd) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_UNIX; uwsgi_sock->bound = 1; uwsgi_sock->name = uwsgi_str(usa.sa_un.sun_path + abstract); uwsgi_log("uwsgi socket %d inherited UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd); } } else if (!strcmp(usa.sa_un.sun_path + abstract, uwsgi_sock->name + abstract)) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_UNIX; uwsgi_sock->bound = 1; uwsgi_log("uwsgi socket %d inherited UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd); } } else if (gsa.sa->sa_family == AF_INET) { char *computed_addr; char computed_port[6]; isa.sa_in = (struct sockaddr_in *) &usa; char ipv4a[INET_ADDRSTRLEN + 1]; memset(ipv4a, 0, INET_ADDRSTRLEN + 1); memset(computed_port, 0, 6); if (snprintf(computed_port, 6, "%d", ntohs(isa.sa_in->sin_port)) > 0) { if (inet_ntop(AF_INET, (const void *) &isa.sa_in->sin_addr.s_addr, ipv4a, INET_ADDRSTRLEN)) { if (!strcmp("0.0.0.0", ipv4a)) { computed_addr = uwsgi_concat2(":", computed_port); } else { computed_addr = uwsgi_concat3(ipv4a, ":", computed_port); } // is it a zerg ? if (uwsgi_sock->name == NULL) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_INET; uwsgi_sock->bound = 1; uwsgi_sock->name = uwsgi_concat2(computed_addr, ""); if (uwsgi.zerg) { uwsgi_log("uwsgi zerg socket %d attached to INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd); } else { uwsgi_log("uwsgi socket %d attached to INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd); } free(computed_addr); return; } char *asterisk = strchr(uwsgi_sock->name, '*'); int match = 1; if (asterisk) { asterisk[0] = 0; match = strncmp(computed_addr, uwsgi_sock->name, strlen(uwsgi_sock->name)); asterisk[0] = '*'; } else { if (!uwsgi_startswith(uwsgi_sock->name, "fd://", 5)) { if (atoi(uwsgi_sock->name + 5) == fd) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_INET; uwsgi_sock->bound = 1; uwsgi_sock->name = uwsgi_str(computed_addr); uwsgi_log("uwsgi socket %d inherited INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd); match = 1; } } else { match = strcmp(computed_addr, uwsgi_sock->name); } } if (!match) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_INET; uwsgi_sock->bound = 1; uwsgi_log("uwsgi socket %d inherited INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd); } free(computed_addr); } } } #ifdef UWSGI_IPV6 else if (gsa.sa->sa_family == AF_INET6) { char *computed_addr; char computed_port[6]; isa.sa_in6 = (struct sockaddr_in6 *) &usa; char ipv6a[INET6_ADDRSTRLEN + 1]; memset(ipv6a, 0, INET_ADDRSTRLEN + 1); memset(computed_port, 0, 6); int match = 0; if (snprintf(computed_port, 6, "%d", ntohs(isa.sa_in6->sin6_port)) > 0) { if (inet_ntop(AF_INET6, (const void *) &isa.sa_in6->sin6_addr.s6_addr, ipv6a, INET6_ADDRSTRLEN)) { uwsgi_log("ipv6a = %s\n", ipv6a); if (!strcmp("::", ipv6a)) { computed_addr = uwsgi_concat2("[::]:", computed_port); } else { computed_addr = uwsgi_concat4("[", ipv6a, "]:", computed_port); } // is it a zerg ? if (uwsgi_sock->name == NULL) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_INET6; uwsgi_sock->bound = 1; uwsgi_sock->name = uwsgi_concat2(computed_addr, ""); if (uwsgi.zerg) { uwsgi_log("uwsgi zerg socket %d attached to INET6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd); } else { uwsgi_log("uwsgi socket %d attached to INET6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd); } free(computed_addr); return; } if (!uwsgi_startswith(uwsgi_sock->name, "fd://", 5)) { if (atoi(uwsgi_sock->name + 5) == fd) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_INET6; uwsgi_sock->bound = 1; uwsgi_sock->name = uwsgi_str(computed_addr); uwsgi_log("uwsgi socket %d inherited INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd); match = 1; } } else { match = strcmp(computed_addr, uwsgi_sock->name); } if (!match) { uwsgi_sock->fd = fd; uwsgi_sock->family = AF_INET; uwsgi_sock->bound = 1; uwsgi_log("uwsgi socket %d inherited INET6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd); } free(computed_addr); } } } #endif } }
char *generate_socket_name(char *socket_name) { char *asterisk = strchr(socket_name, '*'); char *tcp_port; int i; char *ptr = socket_name; // ltrim spaces for (i = 0; i < (int) strlen(socket_name); i++) { if (isspace((int) socket_name[i])) { ptr++; } else { break; } } socket_name = ptr; if (socket_name[0] == 0) { uwsgi_log("invalid/empty uwsgi socket name\n"); exit(1); } tcp_port = strchr(socket_name, ':'); if (!tcp_port) return socket_name; if (asterisk) { #ifndef UWSGI_HAS_IFADDRS uwsgi_log("your system does not support ifaddrs subsystem\n"); #else char *new_socket; #ifdef UWSGI_DEBUG uwsgi_log("generate_socket_name(%s)\n", socket_name); #endif // get all the AF_INET addresses available struct ifaddrs *ifap = NULL, *ifa, *ifaf; if (getifaddrs(&ifap)) { uwsgi_error("getifaddrs()"); uwsgi_nuclear_blast(); } // here socket_name will be truncated asterisk[0] = 0; #ifdef UWSGI_DEBUG uwsgi_log("asterisk found\n"); #endif char new_addr[16]; struct sockaddr_in *sin; ifa = ifap; while (ifa) { memset(new_addr, 0, 16); sin = (struct sockaddr_in *) ifa->ifa_addr; if (inet_ntop(AF_INET, (void *) &sin->sin_addr.s_addr, new_addr, 16)) { if (!strncmp(socket_name, new_addr, strlen(socket_name))) { asterisk[0] = '*'; new_socket = uwsgi_concat3(new_addr, ":", tcp_port + 1); uwsgi_log("[uwsgi-autoip] found %s for %s on interface %s\n", new_socket, socket_name, ifa->ifa_name); freeifaddrs(ifap); return new_socket; } } ifaf = ifa; ifa = ifaf->ifa_next; } uwsgi_log("unable to find avalid socket address\n"); #endif uwsgi_nuclear_blast(); } return socket_name; }