124 lines
3.3 KiB
C
124 lines
3.3 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <sys/file.h>
|
|
#include <err.h>
|
|
|
|
#define MAX_QUERY_LEN 255
|
|
#define IP_LEN 16
|
|
#define IP_FILE "ip.txt"
|
|
#define TOKEN "<empty>"
|
|
|
|
char *form_value(const char *args, const char *field) {
|
|
char *s;
|
|
char *token;
|
|
char *value;
|
|
char *ret = NULL;
|
|
size_t len;
|
|
len = strlen(field);
|
|
s = strdup(args);
|
|
while((token = strsep(&s, "&")) != NULL) {
|
|
if(strlen(token) < len)
|
|
continue;
|
|
if(strncmp(field, token, len) == 0) {
|
|
value = strchr(token, '=');
|
|
ret = strdup(value);
|
|
break;
|
|
}
|
|
}
|
|
free(s);
|
|
return(ret);
|
|
}
|
|
|
|
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(!a || !b)
|
|
return(0);
|
|
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 wfd) {
|
|
char *ip = NULL, *token = NULL;
|
|
int ret = 1;
|
|
size_t len;
|
|
ip = form_value(env, "ip");
|
|
if(!ip)
|
|
return(ret);
|
|
token = form_value(env, "token");
|
|
if(!token)
|
|
free(ip);
|
|
return(ret);
|
|
if(ctc(token, TOKEN) == 1) {
|
|
len = strlen(ip);
|
|
if(len >= IP_LEN-1)
|
|
len = IP_LEN-1;
|
|
write(wfd, ip, len);
|
|
close(wfd);
|
|
ret = 0;
|
|
} else
|
|
ret = 2;
|
|
free(ip);
|
|
free(token);
|
|
return(ret);
|
|
}
|
|
|
|
char *err_msg[2] = {"invalid arguments", "wrong token"};
|
|
|
|
int main(void) {
|
|
char *env = NULL;
|
|
char ip[IP_LEN];
|
|
int errn = 0, len = 0;
|
|
int rfd, wfd;
|
|
if((rfd = open(IP_FILE, O_RDONLY|O_SHLOCK)) == -1)
|
|
err(EXIT_FAILURE, "read open failed");
|
|
if(read(rfd, &ip, IP_LEN) <= 0)
|
|
ip[0] = '\0';
|
|
close(rfd);
|
|
ip[IP_LEN] = '\0';
|
|
if((wfd = open(IP_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXLOCK)) == -1)
|
|
err(EXIT_FAILURE, "rw open failed");
|
|
if(pledge("stdio", NULL) == -1)
|
|
err(EXIT_FAILURE, "pledge");
|
|
env = getenv("QUERY_STRING");
|
|
header();
|
|
if(env != NULL) {
|
|
if(strlen(env) > MAX_QUERY_LEN) {
|
|
puts("query longer than 255 bytes");
|
|
return(EXIT_SUCCESS);
|
|
}
|
|
if((errn = set_ip(env, wfd)) > 0)
|
|
puts(err_msg[errn-1]);
|
|
else
|
|
puts("ok");
|
|
} else {
|
|
len = strlen(ip);
|
|
write(wfd, ip, len);
|
|
close(wfd);
|
|
if(len > 1)
|
|
puts(ip);
|
|
else
|
|
puts("empty");
|
|
}
|
|
return(EXIT_SUCCESS);
|
|
}
|