static int is_dnsexit_server_rsp_ok(ddns_t *ctx, http_trans_t *p_tr, int infnr) { (void)ctx; (void)infnr; int rc; if ((rc = is_http_status_code_ok(p_tr->status)) != 0) return rc; int code = -1; char *tmp; if ((tmp = strstr(p_tr->p_rsp_body, "\n")) != NULL) sscanf(++tmp, "%d=", &code); switch (code) { case 0: case 1: return 0; case 4: case 11: return RC_DYNDNS_RSP_RETRY_LATER; default: return RC_DYNDNS_RSP_NOTOK; } }
static RC_TYPE is_dnsexit_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { (void)p_self; (void)infnr; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; int code = -1; char *tmp; if ((tmp = strstr(p_tr->p_rsp_body, "\n")) != NULL) sscanf(++tmp, "%d=", &code); switch (code) { case 0: case 1: return RC_OK; case 4: case 11: return RC_DYNDNS_RSP_RETRY_LATER; default: return RC_DYNDNS_RSP_NOTOK; } }
/* Freedns afraid.org.specific response validator. ok blabla and n.n.n.n fail blabla and n.n.n.n are the good answers. We search our own IP address in response and that's enough. */ static RC_TYPE is_freedns_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { char *p_rsp = p_tr->p_rsp_body; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; if (strstr(p_rsp, p_self->info[infnr].my_ip_address.name) != NULL) return RC_OK; else return RC_DYNDNS_RSP_NOTOK; }
/* Freedns afraid.org.specific response validator. ok blabla and n.n.n.n fail blabla and n.n.n.n are the good answers. We search our own IP address in response and that's enough. */ static int is_freedns_server_rsp_ok(ddns_t *ctx, http_trans_t *p_tr, int infnr) { char *p_rsp = p_tr->p_rsp_body; int rc; if ((rc = is_http_status_code_ok(p_tr->status)) != 0) return rc; if (strstr(p_rsp, ctx->info[infnr].my_ip_address.name) != NULL) return 0; else return RC_DYNDNS_RSP_NOTOK; }
/** generic http dns server ok parser parses a given string. If found is ok, Example : 'SUCCESS CODE=' */ static int is_generic_server_rsp_ok(ddns_t *ctx, http_trans_t *p_tr, int infnr) { (void)ctx; char *p_rsp = p_tr->p_rsp_body; (void)infnr; int rc; if ((rc = is_http_status_code_ok(p_tr->status)) != 0) return rc; if (strstr(p_rsp, "OK") != NULL) return 0; else return RC_DYNDNS_RSP_NOTOK; }
/* HE ipv6 tunnelbroker specific response validator. own IP address and 'already in use' are the good answers. */ static int is_he_ipv6_server_rsp_ok(ddns_t *ctx, http_trans_t *p_tr, int infnr) { char *p_rsp = p_tr->p_rsp_body; int rc; if ((rc = is_http_status_code_ok(p_tr->status)) != 0) return rc; if (strstr(p_rsp, ctx->info[infnr].my_ip_address.name) != NULL || strstr(p_rsp, "-ERROR: This tunnel is already associated with this IP address.") != NULL) return 0; else return RC_DYNDNS_RSP_NOTOK; }
/* HE ipv6 tunnelbroker specific response validator. own IP address and 'already in use' are the good answers. */ static RC_TYPE is_he_ipv6_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { char *p_rsp = p_tr->p_rsp_body; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; if (strstr(p_rsp, p_self->info[infnr].my_ip_address.name) != NULL || strstr(p_rsp, "already") != NULL) // strstr(p_rsp, "-ERROR: This tunnel is already associated with this IP address.") != NULL) return RC_OK; else return RC_DYNDNS_RSP_NOTOK; }
/** generic http dns server ok parser parses a given string. If found is ok, Example : 'SUCCESS CODE=' */ static RC_TYPE is_generic_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { (void)p_self; char *p_rsp = p_tr->p_rsp_body; (void)infnr; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; if (strstr(p_rsp, "OK") != NULL) return RC_OK; else return RC_DYNDNS_RSP_NOTOK; }
static RC_TYPE is_sitelutions_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { (void)p_self; char *p_rsp = p_tr->p_rsp_body; (void)infnr; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; if (strstr(p_rsp, "success") != NULL) return RC_OK; else if (strstr(p_rsp, "dberror") != NULL) return RC_DYNDNS_RSP_RETRY_LATER; else return RC_DYNDNS_RSP_NOTOK; }
/* DynDNS org.specific response validator. 'good' or 'nochg' are the good answers, */ static int is_dyndns_server_rsp_ok(ddns_t *ctx, http_trans_t *p_tr, int infnr) { (void)ctx; char *p_rsp = p_tr->p_rsp_body; (void)infnr; int rc; if ((rc = is_http_status_code_ok(p_tr->status)) != 0) return rc; if (strstr(p_rsp, "good") != NULL || strstr(p_rsp, "nochg") != NULL) return 0; else if (strstr(p_rsp, "dnserr") != NULL || strstr(p_rsp, "911") != NULL) return RC_DYNDNS_RSP_RETRY_LATER; else return RC_DYNDNS_RSP_NOTOK; }
/** NOERROR is the OK code here */ static int is_easydns_server_rsp_ok(ddns_t *ctx, http_trans_t *p_tr, int infnr) { (void)ctx; char *p_rsp = p_tr->p_rsp_body; (void)infnr; int rc; if ((rc = is_http_status_code_ok(p_tr->status)) != 0) return rc; if (strstr(p_rsp, "NOERROR") != NULL) return 0; else if (strstr(p_rsp, "TOOSOON") != NULL) return RC_DYNDNS_RSP_RETRY_LATER; else return RC_DYNDNS_RSP_NOTOK; }
static int is_sitelutions_server_rsp_ok(ddns_t *ctx, http_trans_t *p_tr, int infnr) { (void)ctx; char *p_rsp = p_tr->p_rsp_body; (void)infnr; int rc; if ((rc = is_http_status_code_ok(p_tr->status)) != 0) return rc; if (strstr(p_rsp, "success") != NULL) return 0; else if (strstr(p_rsp, "dberror") != NULL) return RC_DYNDNS_RSP_RETRY_LATER; else return RC_DYNDNS_RSP_NOTOK; }
/* DynDNS org.specific response validator. 'good' or 'nochg' are the good answers, */ static RC_TYPE is_dyndns_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { (void)p_self; char *p_rsp = p_tr->p_rsp_body; (void)infnr; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; if (strstr(p_rsp, "good") != NULL || strstr(p_rsp, "nochg") != NULL) return RC_OK; else if (strstr(p_rsp, "dnserr") != NULL || strstr(p_rsp, "911") != NULL) return RC_DYNDNS_RSP_RETRY_LATER; else return RC_DYNDNS_RSP_NOTOK; }
/** the OK codes are: CODE=200, 201 CODE=707, for duplicated updates */ static RC_TYPE is_zoneedit_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { (void)p_self; (void)infnr; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; int code = -1; sscanf(p_tr->p_rsp_body, "%*s CODE=\"%d\" ", &code); switch (code) { case 200: case 201: case 707: // is 707 really ok?? return RC_OK; default: return RC_DYNDNS_RSP_NOTOK; } }
/** the OK codes are: CODE=200, 201 CODE=707, for duplicated updates */ static int is_zoneedit_server_rsp_ok(ddns_t *ctx, http_trans_t *p_tr, int infnr) { (void)ctx; (void)infnr; int rc; if ((rc = is_http_status_code_ok(p_tr->status)) != 0) return rc; int code = -1; sscanf(p_tr->p_rsp_body, "%*s CODE=\"%d\" ", &code); switch (code) { case 200: case 201: case 707: // is 707 really ok?? return 0; default: return RC_DYNDNS_RSP_NOTOK; } }
/* TZO specific response validator. */ static RC_TYPE is_tzo_server_rsp_ok(DYN_DNS_CLIENT *p_self, HTTP_TRANSACTION *p_tr, int infnr) { (void)p_self; (void)infnr; RC_TYPE rc; if ((rc = is_http_status_code_ok(p_tr->status)) != RC_OK) return rc; int code = -1; sscanf(p_tr->p_rsp_body, "%d ", &code); switch (code) { case 200: case 304: return RC_OK; case 414: case 500: return RC_DYNDNS_RSP_RETRY_LATER; default: return RC_DYNDNS_RSP_NOTOK; } }
/* TZO specific response validator. */ static int is_tzo_server_rsp_ok(ddns_t *ctx, http_trans_t *p_tr, int infnr) { (void)ctx; (void)infnr; int rc; if ((rc = is_http_status_code_ok(p_tr->status)) != 0) return rc; int code = -1; sscanf(p_tr->p_rsp_body, "%d ", &code); switch (code) { case 200: case 304: return 0; case 414: case 500: return RC_DYNDNS_RSP_RETRY_LATER; default: return RC_DYNDNS_RSP_NOTOK; } }
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); }
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); }