/* $Id$ */ /* * Copyright (c) 2005 Dimitri Sokolyuk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include "request.h" #include "connect.h" #include "version.h" extern int debug; extern int verbose; #define BUFLEN 1024 static int build_request(struct dd_request *req, char *buf) { snprintf(buf, BUFLEN, "GET /nic/update?"); if (req->system != NULL) snprintf(buf + strlen(buf), BUFLEN - strlen(buf), "system=%s&", req->system); snprintf(buf + strlen(buf), BUFLEN - strlen(buf), "hostname=%s", req->hostname); if (req->myip != NULL) snprintf(buf + strlen(buf), BUFLEN - strlen(buf), "&myip=%s", req->myip); if (req->wildcard != NULL) snprintf(buf + strlen(buf), BUFLEN - strlen(buf), "&wildcard=%s", req->wildcard); if (req->mx != NULL) { snprintf(buf + strlen(buf), BUFLEN - strlen(buf), "&mx=%s", req->mx); if (req->backmx != NULL) snprintf(buf + strlen(buf), BUFLEN - strlen(buf), "&backmx=%s", req->backmx); } if (req->offline != NULL) snprintf(buf + strlen(buf), BUFLEN - strlen(buf), "&offline=%s", req->offline); snprintf(buf + strlen(buf), BUFLEN - strlen(buf), " HTTP/1.0\r\n" "Host: %s\r\n" "Authorization: Basic %s\r\n" "User-Agent: %s/%s\r\n" "Connection: close\r\n\r\n", DYNDNSHOST, req->auth, USERAGENT, VERSION); return 0; } #define RET_OK 0 #define RET_ERR 1 static struct { const char *code; const char *message; const char ret; } retcode[] = { { "badsys", "bad system parameter", RET_ERR }, { "badagent", "useragent has been blocked", RET_ERR }, { "badauth", "bad authorization", RET_ERR }, { "!donator", "option available only to credited user", RET_ERR }, { "good", "update was successful", RET_OK }, { "nochg", "no update required", RET_OK }, { "notfqdn", "fully-qualified domain name was not provided", RET_ERR }, { "nohost", "hostname does not exist in database", RET_ERR }, { "!yours", "hostname does not belong to username", RET_ERR }, { "abuse", "hostname is blocked for abuse", RET_ERR }, { "numhost", "too many or too few hosts found", RET_ERR }, { "dnserr", "DNS error encountered", RET_ERR }, { "911", "internal server failure", RET_ERR }, { NULL, NULL, 0 } }; static int parse_answer(char *buf, char *name) { char *p; int i; if (strstr(buf, "HTTP/1.") == NULL) errx(1, "strange server response"); (void) strtok(buf, "\n"); while ((p = strtok((char *) NULL, "\n")) != NULL) { for (i = 0; retcode[i].code != NULL; i++) { if (strstr(p, retcode[i].code)) { if (verbose) warnx("%s: %s", name, retcode[i].message); return retcode[i].ret; } } } return RET_ERR; } int do_request(int reqc, struct dd_request **reqv) { int i; int ret = reqc; int sockfd; char buf[BUFLEN]; for (i = 0; i < reqc; i++) { sockfd = connecttohost(DYNDNSHOST, DYNDNSPORT); build_request(reqv[i], buf); if (debug) printf("request:\n%s\n", buf); if (transfer(sockfd, buf, BUFLEN) == -1) err(1, "transfer error"); close(sockfd); if (debug) printf("response:\n%s\n", buf); if (parse_answer(buf, reqv[i]->name) == RET_OK) ret--; } return ret; }