commit 781006e83bc50aa0a9202632ae5e087279f2ec9e Author: ston1th Date: Fri Jan 6 15:04:49 2017 +0100 initial commit diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..ba65419 --- /dev/null +++ b/build.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cc -static -Wall -Werror -o ddns ddns.c +install -o www -g www -m 0500 ddns /var/www/ddns diff --git a/ddns.c b/ddns.c new file mode 100644 index 0000000..44e0176 --- /dev/null +++ b/ddns.c @@ -0,0 +1,137 @@ +#include +#include +#include +#include +#include +#include +#include + +#define SEP '=' +#define IP_LEN 16 +#define IP_FILE "ip.txt" +#define TOKEN "" + +void free_arr(void *arr) { + uintptr_t *a = arr; + while(*a) { + free((void*)*a++); + } + free(arr); +} + +char **parse(const char *str) { + const char *s = str; + char *qs, *token; + char **arr = NULL; + int c = 1; + qs = strdup(s); + while((token = strsep(&qs, "&")) != NULL) { + c++; + if(arr == NULL) { + arr = malloc(c*sizeof(char *)); + if(arr == NULL) + break; + } else { + arr = realloc(arr, c*sizeof(char *)); + if(arr == NULL) + break; + } + arr[c-1] = NULL; + arr[c-2] = strdup(token); + } + free(qs); + return(arr); +} + +void header() { + puts("Status: 200 OK\r"); + puts("Content-Type: text/html\r"); + puts("\r"); +} + +int ctb(unsigned char a, unsigned char b) { + unsigned char c = ~(a ^ b); + c &= c >> 4; + c &= c >> 2; + c &= c >> 1; + return((int)c); +} + +int ctc(const char *a, const char *b) { + if(strlen(a) != strlen(b)) { + return(0); + } + const char *x = a, *y = b; + char v = 0; + while(*x) + v |= *x++ ^ *y++; + return(ctb(v, 0)); +} + +int set_ip(char *env, int fd) { + char *ip, *token, *tmp; + int ret = -1, len = 0; + char **arg = parse(env); + char **arr = arg; + if(arg == NULL) + return(0); + for(; *arr; arr++) { + if(strncmp(*arr, "ip", 2) == 0) { + tmp = strchr(*arr, SEP); + if(++tmp == NULL) + continue; + ip = strdup(tmp); + } else if(strncmp(*arr, "token", 5) == 0) { + tmp = strchr(*arr, SEP); + if(++tmp == NULL) + continue; + token = strdup(tmp); + } + } + tmp = NULL; + free_arr(arg); + if(ctc(token, TOKEN) == 1) { + len = strlen(ip); + if(len >= IP_LEN-1) + len = IP_LEN-1; + write(fd, ip, len); + close(fd); + } else + ret = 1; + free(token); + free(ip); + return(ret); +} + +char *err_msg[2] = {"wrong input", "wrong token"}; + +int main(void) { + char *env; + char ip[IP_LEN]; + int errn = 0, len = 0; + int rfd = open(IP_FILE, O_RDONLY|O_SHLOCK); + if(read(rfd, &ip, IP_LEN) <= 0) + ip[0] = '\0'; + close(rfd); + ip[IP_LEN] = '\0'; + int wfd = open(IP_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXLOCK); + if(pledge("stdio", NULL) == -1) + err(EXIT_FAILURE, "pledge"); + env = getenv("QUERY_STRING"); + header(); + if(env != NULL) { + if((errn = set_ip(env, wfd)) >= 0) + puts(err_msg[errn]); + else + puts("ok"); + } else { + len = strlen(ip); + write(wfd, ip, len); + close(wfd); + if(len > 1) + puts(ip); + else + puts("empty"); + } + return(EXIT_SUCCESS); +} diff --git a/httpd.conf b/httpd.conf new file mode 100644 index 0000000..117d432 --- /dev/null +++ b/httpd.conf @@ -0,0 +1,7 @@ +server "localhost" { + listen on * port 80 + location "/ddns/*" { + fastcgi + root "/" + } +} diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..a2519d2 --- /dev/null +++ b/install.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +dir=/var/www/ddns +ip=ip.txt +ip_file=${dir}/${ip} +mkdir -p ${dir} +touch ${ip_file} +chmod 0600 ${ip_file} +chown www:www ${ip_file} +rcctl enable slowcgi +rcctl start slowcgi +rcctl enable httpd +rcctl start httpd