/* Send req to IP server and get the response */ static RC_TYPE do_ip_server_transaction(DYN_DNS_CLIENT *p_self) { RC_TYPE rc = RC_OK; HTTP_CLIENT *p_http; p_http = &p_self->http_to_ip_server; rc = http_client_init(&p_self->http_to_ip_server); if (rc != RC_OK) { return rc; } do { /*prepare request for IP server*/ { HTTP_TRANSACTION *p_tr = &p_self->http_tr; p_tr->req_len = get_req_for_ip_server((DYN_DNS_CLIENT*) p_self, p_self->info.p_dns_system->p_specific_data); if (p_self->dbg.level > 2) { DBG_PRINTF((LOG_DEBUG, "The request for IP server:\n%s\n",p_self->p_req_buffer)); } p_tr->p_req = (char*) p_self->p_req_buffer; p_tr->p_rsp = (char*) p_self->p_work_buffer; p_tr->max_rsp_len = p_self->work_buffer_size - 1;/*save place for a \0 at the end*/ p_tr->rsp_len = 0; rc = http_client_transaction(&p_self->http_to_ip_server, &p_self->http_tr); p_self->p_work_buffer[p_tr->rsp_len] = 0; } } while(0); /*close*/ http_client_shutdown(&p_self->http_to_ip_server); return rc; }
/* Send req to IP server and get the response */ static RC_TYPE do_ip_server_transaction(DYN_DNS_CLIENT *p_self, int servernum) { RC_TYPE rc = RC_OK; HTTP_CLIENT *p_http; HTTP_TRANSACTION *p_tr; if (p_self == NULL) { return RC_INVALID_POINTER; } p_http = &p_self->http_to_ip_server[servernum]; rc = http_client_init(p_http, "Checking for IP# change"); if (rc != RC_OK) { return rc; } /* Prepare request for IP server */ p_tr = &p_self->http_tr; p_tr->req_len = get_req_for_ip_server(p_self, servernum); if (p_self->dbg.level > 2) { logit(LOG_DEBUG, MODULE_TAG "Querying DDNS server for my public IP#:"); logit(LOG_DEBUG, MODULE_TAG "%s", p_self->p_req_buffer); } p_tr->p_req = (char*) p_self->p_req_buffer; p_tr->p_rsp = (char*) p_self->p_work_buffer; p_tr->max_rsp_len = p_self->work_buffer_size - 1; /* Save place for terminating \0 in string. */ p_tr->rsp_len = 0; rc = http_client_transaction(p_http, &p_self->http_tr); p_tr->p_rsp[p_tr->rsp_len] = 0; if (p_tr->status != 200) rc = RC_DYNDNS_INVALID_RSP_FROM_IP_SERVER; http_client_shutdown(p_http); return rc; }
/* Send req to IP server and get the response */ static int do_ip_server_transaction(ddns_t *ctx, int servernum) { int rc = 0; http_client_t *p_http; http_trans_t *p_tr; if (!ctx) return RC_INVALID_POINTER; p_http = &ctx->http_to_ip_server[servernum]; rc = http_client_init(p_http, "Checking for IP# change"); if (rc != 0) { return rc; } /* Prepare request for IP server */ p_tr = &ctx->http_transaction; p_tr->req_len = get_req_for_ip_server(ctx, servernum); if (ctx->dbg.level > 2) { logit(LOG_DEBUG, "Querying DDNS server for my public IP#:"); logit(LOG_DEBUG, "%s", ctx->request_buf); } p_tr->p_req = (char *)ctx->request_buf; p_tr->p_rsp = (char *)ctx->work_buf; p_tr->max_rsp_len = ctx->work_buflen - 1; /* Save place for terminating \0 in string. */ p_tr->rsp_len = 0; rc = http_client_transaction(p_http, &ctx->http_transaction); p_tr->p_rsp[p_tr->rsp_len] = 0; if (p_tr->status != 200) rc = RC_DYNDNS_INVALID_RSP_FROM_IP_SERVER; http_client_shutdown(p_http); return rc; }
static int get_req_for_freedns_server(DYN_DNS_CLIENT *p_self, int infcnt, int alcnt) { RC_TYPE rc = RC_OK, rc2; HTTP_CLIENT http_to_dyndns; HTTP_TRANSACTION http_tr; char buffer[256]; unsigned char digestbuf[SHA1_DIGEST_BYTES]; char digeststr[SHA1_DIGEST_BYTES*2+1]; int i; char *buf, *tmp, *line; char host[256], updateurl[256]; char *hash = NULL; if (p_self == NULL) { /* 0 == "No characters written" */ return 0; } // I know it's ugly, http client needs redesign. do { if ((rc = http_client_construct(&http_to_dyndns)) != RC_OK) break; http_client_set_port(&http_to_dyndns, p_self->info[infcnt].dyndns_server_name.port); http_client_set_remote_name(&http_to_dyndns, p_self->info[infcnt].dyndns_server_name.name); http_client_set_bind_iface(&http_to_dyndns, p_self->bind_interface); if ((rc = http_client_init(&http_to_dyndns, "Sending update URL query")) != RC_OK) break; snprintf(buffer, sizeof(buffer), "%s|%s", p_self->info[infcnt].credentials.my_username, p_self->info[infcnt].credentials.my_password); sha1(buffer, strlen(buffer), digestbuf); for (i = 0; i < SHA1_DIGEST_BYTES; i++) sprintf(&digeststr[i*2], "%02x", digestbuf[i]); snprintf(buffer, sizeof(buffer), "/api/?action=getdyndns&sha=%s", digeststr); http_tr.req_len = sprintf(p_self->p_req_buffer, GENERIC_HTTP_REQUEST, buffer, p_self->info[infcnt].dyndns_server_name.name); http_tr.p_req = (char*) p_self->p_req_buffer; http_tr.p_rsp = (char*) p_self->p_work_buffer; http_tr.max_rsp_len = p_self->work_buffer_size - 1; /* Save place for a \0 at the end */ http_tr.rsp_len = 0; rc = http_client_transaction(&http_to_dyndns, &http_tr); http_tr.p_rsp[http_tr.rsp_len] = 0; rc2 = http_client_shutdown(&http_to_dyndns); http_client_destruct(&http_to_dyndns, 1); if (rc != RC_OK || rc2 != RC_OK) break; if ((rc = is_http_status_code_ok(http_tr.status)) != RC_OK) break; tmp = buf = strdup(http_tr.p_rsp_body); for (line = strsep(&tmp, "\n"); line; line = strsep(&tmp, "\n")) { if (*line && sscanf(line, "%255[^|\r\n]|%*[^|\r\n]|%255[^|\r\n]", host, updateurl) == 2 && !strcmp(host, p_self->info[infcnt].alias_info[alcnt].names.name)) { hash = strstr(updateurl, "?"); break; } } free(buf); if (!hash) rc = RC_DYNDNS_RSP_NOTOK; } while (0); if (rc != RC_OK) { logit(LOG_INFO, MODULE_TAG "Update URL query failed"); return 0; } return sprintf(p_self->p_req_buffer, FREEDNS_UPDATE_IP_REQUEST, p_self->info[infcnt].dyndns_server_url, hash, p_self->info[infcnt].my_ip_address.name, p_self->info[infcnt].dyndns_server_name.name); }
static RC_TYPE do_update_alias_table(DYN_DNS_CLIENT *p_self) { int i, j; RC_TYPE rc = RC_OK, rc2; HTTP_TRANSACTION http_tr; int anychange = 0; for (i = 0; i < p_self->info_count; i++) { DYNDNS_INFO_TYPE *info = &p_self->info[i]; for (j = 0; j < info->alias_count; j++) { if (info->alias_info[j].update_required != TRUE) { continue; } rc = http_client_init(&p_self->http_to_dyndns[i], "Sending IP# update to DDNS server"); if (rc != RC_OK) { break; } /* Build dyndns transaction */ http_tr.req_len = info->p_dns_system->p_dns_update_req_func( (struct _DYN_DNS_CLIENT*) p_self, i, j); http_tr.p_req = (char*) p_self->p_req_buffer; http_tr.p_rsp = (char*) p_self->p_work_buffer; http_tr.max_rsp_len = p_self->work_buffer_size - 1; /* Save place for a \0 at the end */ http_tr.rsp_len = 0; rc = http_client_transaction(&p_self->http_to_dyndns[i], &http_tr); http_tr.p_rsp[http_tr.rsp_len] = 0; if (p_self->dbg.level > 2) { p_self->p_req_buffer[http_tr.req_len] = 0; logit(LOG_DEBUG, MODULE_TAG "Sending alias table update to DDNS server:"); logit(LOG_DEBUG, MODULE_TAG "%s", p_self->p_req_buffer); } if (rc == RC_OK) { rc = info->p_dns_system->p_rsp_ok_func((struct _DYN_DNS_CLIENT*)p_self, &http_tr, i); if (rc == RC_OK) { info->alias_info[j].update_required = FALSE; logit(LOG_INFO, MODULE_TAG "Successful alias table update for %s => new IP# %s", info->alias_info[j].names.name, info->my_ip_address.name); p_self->time_since_last_update = 0; anychange++; /* Adjust forced update period on success */ } else { logit(LOG_WARNING, MODULE_TAG "%s error in DDNS server response:", rc == RC_DYNDNS_RSP_RETRY_LATER ? "Temporary" : "Fatal"); logit(LOG_WARNING, MODULE_TAG "[%d %s] %s", http_tr.status, http_tr.status_desc, http_tr.p_rsp_body != http_tr.p_rsp ? http_tr.p_rsp_body : ""); } if (p_self->dbg.level > 2) { logit(LOG_DEBUG, MODULE_TAG "DDNS server response:"); logit(LOG_DEBUG, MODULE_TAG "%s", http_tr.p_rsp); } } rc2 = http_client_shutdown(&p_self->http_to_dyndns[i]); if (rc == RC_OK) { /* Only overwrite rc with of http_client_shutdown() rc if previous call, in * e.g., http_client_transaction() or the p_rsp_ok_func() callback was OK. */ rc = rc2; } if (rc != RC_OK) { break; } os_sleep_ms(1000); } } /* Successful change or when cache file does not yet exist! */ if (anychange || access(p_self->cachefile, F_OK)) { FILE *fp; /* Update cache with new IP */ fp = fopen(p_self->cachefile, "w"); if (fp) { fprintf(fp, "%s", p_self->info[0].my_ip_address.name); fclose(fp); } if (anychange && p_self->external_command) { /* Run external command hook on update. */ os_shell_execute(p_self->external_command); } } return rc; }
static RC_TYPE do_update_alias_table(DYN_DNS_CLIENT *p_self) { int i; int shutdown = 0; RC_TYPE rc = RC_OK; FILE *fp; do { for (i = 0; i < p_self->alias_info.count; ++i) { if (p_self->alias_info.update_required[i] != TRUE) { continue; } rc = http_client_init(&p_self->http_to_dyndns); if (rc != RC_OK) { break; } /*build dyndns transaction*/ { HTTP_TRANSACTION http_tr; http_tr.req_len = p_self->info.p_dns_system->p_dns_update_req_func( (struct _DYN_DNS_CLIENT*) p_self,i, (struct DYNDNS_SYSTEM*) p_self->info.p_dns_system); http_tr.p_req = (char*) p_self->p_req_buffer; http_tr.p_rsp = (char*) p_self->p_work_buffer; http_tr.max_rsp_len = p_self->work_buffer_size - 1;/*save place for a \0 at the end*/ http_tr.rsp_len = 0; p_self->p_work_buffer[http_tr.rsp_len+1] = 0; /*send it*/ rc = http_client_transaction(&p_self->http_to_dyndns, &http_tr); if (p_self->dbg.level > 2) { p_self->p_req_buffer[http_tr.req_len] = 0; DBG_PRINTF((LOG_DEBUG,"DYNDNS my Request:\n%s\n", p_self->p_req_buffer)); } if (rc == RC_OK) { int rc = p_self->info.p_dns_system->p_rsp_ok_func((struct _DYN_DNS_CLIENT*)p_self, http_tr.p_rsp, p_self->info.p_dns_system->p_success_string); if (rc == RC_OK) { p_self->alias_info.update_required[i] = FALSE; DBG_PRINTF((LOG_WARNING,"I:" MODULE_TAG "Alias '%s' to IP '%s' updated successfully.\n", p_self->alias_info.names[i].name, p_self->info.my_ip_address.name)); p_self->times_since_last_update = 0; /*recalc forced update period*/ p_self->forced_update_period_sec = p_self->forced_update_period_sec_orig; p_self->forced_update_times = p_self->forced_update_period_sec / p_self->sleep_sec; if ((fp=fopen(p_self->ip_cache, "w"))) { fprintf(fp,"%s", p_self->info.my_ip_address.name); fclose(fp); } if ((fp=fopen(p_self->time_cache, "w"))) { fprintf(fp,"%ld", time (NULL)); fclose(fp); } if (strlen(p_self->external_command) > 0) os_shell_execute(p_self->external_command); } else { DBG_PRINTF((LOG_WARNING,"W:" MODULE_TAG "Response Code: %d\n", rc)); DBG_PRINTF((LOG_WARNING,"W:" MODULE_TAG "Error validating DYNDNS svr answer. Check usr,pass,hostname! (%s)\n", http_tr.p_rsp)); shutdown++; } if (p_self->dbg.level > 2) { http_tr.p_rsp[http_tr.rsp_len] = 0; DBG_PRINTF((LOG_WARNING,"W:" MODULE_TAG "DYNDNS Server response:\n%s\n", http_tr.p_rsp)); } } } { RC_TYPE rc2 = http_client_shutdown(&p_self->http_to_dyndns); if (rc == RC_OK) { rc = rc2; } } if (rc != RC_OK || shutdown>2) { break; } os_sleep_ms(1000); } if (rc != RC_OK) { break; } } while(0); return rc; }
static RC_TYPE do_update_alias_table(DYN_DNS_CLIENT *p_self) { int i; RC_TYPE rc = RC_OK; do { for (i = 0; i < p_self->alias_info.count; ++i) { if (p_self->alias_info.update_required[i] != TRUE) { continue; } rc = http_client_init(&p_self->http_to_dyndns); if (rc != RC_OK) { break; } /*build dyndns transaction*/ { HTTP_TRANSACTION http_tr; http_tr.req_len = p_self->info.p_dns_system->p_dns_update_req_func( (struct _DYN_DNS_CLIENT*) p_self,i, (struct DYNDNS_SYSTEM*) p_self->info.p_dns_system); http_tr.p_req = (char*) p_self->p_req_buffer; http_tr.p_rsp = (char*) p_self->p_work_buffer; http_tr.max_rsp_len = p_self->work_buffer_size - 1;/*save place for a \0 at the end*/ http_tr.rsp_len = 0; p_self->p_work_buffer[http_tr.rsp_len+1] = 0; /*send it*/ rc = http_client_transaction(&p_self->http_to_dyndns, &http_tr); if (p_self->dbg.level > 2) { p_self->p_req_buffer[http_tr.req_len] = 0; DBG_PRINTF((LOG_DEBUG,"DYNDNS my Request:\n%s\n", p_self->p_req_buffer)); } if (rc == RC_OK) { BOOL update_ok = p_self->info.p_dns_system->p_rsp_ok_func((struct _DYN_DNS_CLIENT*)p_self, http_tr.p_rsp, p_self->info.p_dns_system->p_success_string); if (update_ok) { p_self->alias_info.update_required[i] = FALSE; DBG_PRINTF((LOG_WARNING,"I:" MODULE_TAG "Alias '%s' to IP '%s' updated successful.\n", p_self->alias_info.names[i].name, p_self->info.my_ip_address.name)); p_self->times_since_last_update = 0; } else { DBG_PRINTF((LOG_WARNING,"W:" MODULE_TAG "Error validating DYNDNS svr answer. Check usr,pass,hostname!\n", http_tr.p_rsp)); } if (p_self->dbg.level > 2) { http_tr.p_rsp[http_tr.rsp_len] = 0; DBG_PRINTF((LOG_WARNING,"W:" MODULE_TAG "DYNDNS Server response:\n%s\n", http_tr.p_rsp)); } } } { RC_TYPE rc2 = http_client_shutdown(&p_self->http_to_dyndns); if (rc == RC_OK) { rc = rc2; } } if (rc != RC_OK) { break; } os_sleep_ms(1000); } if (rc != RC_OK) { break; } } while(0); return rc; }
static int do_update_alias_table(ddns_t *ctx) { int i, j; int rc = 0, rc2; http_trans_t http_tr; int anychange = 0; for (i = 0; i < ctx->info_count; i++) { ddns_info_t *info = &ctx->info[i]; for (j = 0; j < info->alias_count; j++) { if (info->alias[j].update_required != 1) { continue; } rc = http_client_init(&ctx->http_to_dyndns[i], "Sending IP# update to DDNS server"); if (rc != 0) { break; } /* Build dyndns transaction */ http_tr.req_len = info->system->update_request_func(ctx, i, j); http_tr.p_req = (char *)ctx->request_buf; http_tr.p_rsp = (char *)ctx->work_buf; http_tr.max_rsp_len = ctx->work_buflen - 1; /* Save place for a \0 at the end */ http_tr.rsp_len = 0; rc = http_client_transaction(&ctx->http_to_dyndns[i], &http_tr); http_tr.p_rsp[http_tr.rsp_len] = 0; if (ctx->dbg.level > 2) { ctx->request_buf[http_tr.req_len] = 0; logit(LOG_DEBUG, "Sending alias table update to DDNS server:"); logit(LOG_DEBUG, "%s", ctx->request_buf); } if (rc == 0) { rc = info->system->response_ok_func(ctx, &http_tr, i); if (rc == 0) { info->alias[j].update_required = 0; logit(LOG_INFO, "Successful alias table update for %s => new IP# %s", info->alias[j].names.name, info->my_ip_address.name); ctx->time_since_last_update = 0; ctx->force_addr_update = 0; anychange++; } else { logit(LOG_WARNING, "%s error in DDNS server response:", rc == RC_DYNDNS_RSP_RETRY_LATER ? "Temporary" : "Fatal"); logit(LOG_WARNING, "[%d %s] %s", http_tr.status, http_tr.status_desc, http_tr.p_rsp_body != http_tr.p_rsp ? http_tr.p_rsp_body : ""); } if (ctx->dbg.level > 2) { logit(LOG_DEBUG, "DDNS server response:"); logit(LOG_DEBUG, "%s", http_tr.p_rsp); } } rc2 = http_client_shutdown(&ctx->http_to_dyndns[i]); if (rc == 0) { /* Only overwrite rc with of http_client_shutdown() rc if previous call, in * e.g., http_client_transaction() or the response_ok_func() callback was OK. */ rc = rc2; } if (rc != 0) { break; } os_sleep_ms(1000); } } /* Successful change or when cache file does not yet exist! */ if (anychange || access(ctx->cache_file, F_OK)) { FILE *fp; /* Update cache with new IP */ fp = fopen(ctx->cache_file, "w"); if (fp) { fprintf(fp, "%s", ctx->info[0].my_ip_address.name); fclose(fp); } /* Run external command hook on update. */ if (anychange && ctx->external_command) { os_shell_execute(ctx->external_command, ctx->info[0].my_ip_address.name, ctx->info[0].alias[0].names.name, ctx->bind_interface); } } return rc; }
static int get_req_for_freedns_server(ddns_t *ctx, int infcnt, int alcnt) { int rc = 0, rc2; http_client_t client; http_trans_t trans; char buffer[256]; unsigned char digestbuf[SHA1_DIGEST_BYTES]; char digeststr[SHA1_DIGEST_BYTES * 2 + 1]; int i; char *buf, *tmp, *line; char host[256], updateurl[256]; char *hash = NULL; if (ctx == NULL) { /* 0 == "No characters written" */ return 0; } // I know it's ugly, http client needs redesign. do { if ((rc = http_client_construct(&client)) != 0) break; http_client_set_port(&client, ctx->info[infcnt].dyndns_server_name.port); http_client_set_remote_name(&client, ctx->info[infcnt].dyndns_server_name.name); http_client_set_bind_iface(&client, ctx->bind_interface); if ((rc = http_client_init(&client, "Sending update URL query")) != 0) break; snprintf(buffer, sizeof(buffer), "%s|%s", ctx->info[infcnt].creds.username, ctx->info[infcnt].creds.password); sha1((unsigned char *)buffer, strlen(buffer), digestbuf); for (i = 0; i < SHA1_DIGEST_BYTES; i++) sprintf(&digeststr[i * 2], "%02x", digestbuf[i]); snprintf(buffer, sizeof(buffer), "/api/?action=getdyndns&sha=%s", digeststr); trans.req_len = sprintf(ctx->request_buf, GENERIC_HTTP_REQUEST, buffer, ctx->info[infcnt].dyndns_server_name.name); trans.p_req = (char *)ctx->request_buf; trans.p_rsp = (char *)ctx->work_buf; trans.max_rsp_len = ctx->work_buflen - 1; /* Save place for a \0 at the end */ trans.rsp_len = 0; rc = http_client_transaction(&client, &trans); trans.p_rsp[trans.rsp_len] = 0; rc2 = http_client_shutdown(&client); http_client_destruct(&client, 1); if (rc != 0 || rc2 != 0) break; if ((rc = is_http_status_code_ok(trans.status)) != 0) break; tmp = buf = strdup(trans.p_rsp_body); for (line = strsep(&tmp, "\n"); line; line = strsep(&tmp, "\n")) { if (*line && sscanf(line, "%255[^|\r\n]|%*[^|\r\n]|%255[^|\r\n]", host, updateurl) == 2 && !strcmp(host, ctx->info[infcnt].alias[alcnt].names.name)) { hash = strstr(updateurl, "?"); break; } } free(buf); if (!hash) rc = RC_DYNDNS_RSP_NOTOK; } while (0); if (rc != 0) { logit(LOG_INFO, "Update URL query failed"); return 0; } return sprintf(ctx->request_buf, FREEDNS_UPDATE_IP_REQUEST, ctx->info[infcnt].dyndns_server_url, hash, ctx->info[infcnt].my_ip_address.name, ctx->info[infcnt].dyndns_server_name.name); }