Example #1
0
/*
	Resource free.
*/	
RC_TYPE http_client_destruct(HTTP_CLIENT *p_self)
{
	RC_TYPE	rc;


	if (p_self==NULL)
	{
		return RC_OK;
	}

	rc=super_destruct(&p_self->super);

	if (!(p_self->is_constructed))
	{
		return RC_OK;
	}

	http_client_shutdown(p_self);

	memset(p_self,0,sizeof(HTTP_CLIENT));
	

	/*free*/
	return rc;
}
Example #2
0
/*
	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;
}
Example #3
0
/* 
	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;
}
Example #4
0
/*
	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;
}
Example #5
0
RC_TYPE http_client_do_init(HTTP_CLIENT *p_self,int is_init_all)
{
	RC_TYPE rc;

	do
	{
		rc = local_set_params(p_self);

		if (rc != RC_OK)
		{
			break;
		}


		rc = super_initialize(&p_self->super,is_init_all);

		if (rc != RC_OK)
		{
			break;
		}

		/*local init*/

	}
	while(0);

	if (rc != RC_OK)
	{
		http_client_shutdown(p_self);
	}
	else
	{
		p_self->initialized = TRUE;
	}

	return rc;
}
/* 
	Sets up the object.

	- ...
*/
RC_TYPE http_client_init(HTTP_CLIENT *p_self)
{
	RC_TYPE rc;
	do
	{
		/*set local params*/
		rc = local_set_params(p_self);
		if (rc != RC_OK)
		{
			break;
		}


		/*call super*/
		rc = super_init(&p_self->super);
		if (rc != RC_OK)
		{
			break;
		}

		/*local init*/

	}
	while(0);

	if (rc != RC_OK)
	{
		http_client_shutdown(p_self);		
	}
	else
	{
		p_self->initialized = TRUE;
	}
	
	return rc;
}
Example #7
0
RC_TYPE http_client_init_async(HTTP_CLIENT *p_self,CB_EXIT_COND p_exit_func,void *p_cb_data)
{
	RC_TYPE rc;
	do
	{
		/*set local params*/
		rc = local_set_params(p_self);
		if (rc != RC_OK)
		{
			break;
		}


		/*call super*/
		rc = super_init_async(&p_self->super);
		if (rc != RC_OK)
		{
			break;
		}

		/*local init*/

	}
	while(0);

	if (rc != RC_OK)
	{
		http_client_shutdown(p_self);
	}
	else
	{
		p_self->initialized = TRUE;
	}

	return rc;
}
Example #8
0
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);
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
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;
}
Example #12
0
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;
}
Example #13
0
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);
}