gzip support in ipset/*.sh and tpws

This commit is contained in:
bolvan
2019-05-09 19:03:50 +03:00
parent 7d59377009
commit c5dc07d049
30 changed files with 364 additions and 121 deletions

View File

@@ -1,6 +1,6 @@
CC ?= gcc
CFLAGS += -s -O3
LIBS =
LIBS = -lz
SRC_FILES = *.c
all: tpws

75
tpws/gzip.c Normal file
View File

@@ -0,0 +1,75 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gzip.h"
#define ZCHUNK 16384
#define BUFMIN 128
#define BUFCHUNK (1024*128)
int z_readfile(FILE *F,char **buf,size_t *size)
{
z_stream zs;
int r;
unsigned char in[ZCHUNK];
size_t bufsize;
void *newbuf;
memset(&zs,0,sizeof(zs));
*buf = NULL;
bufsize=*size=0;
r=inflateInit2(&zs,47);
if (r != Z_OK) return r;
do
{
zs.avail_in = fread(in, 1, sizeof(in), F);
if (ferror(F))
{
r = Z_ERRNO;
goto zerr;
}
if (!zs.avail_in) break;
zs.next_in = in;
do
{
if ((bufsize-*size)<BUFMIN)
{
bufsize += BUFCHUNK;
newbuf = *buf ? realloc(*buf,bufsize) : malloc(bufsize);
if (newbuf==*buf)
if (!newbuf)
{
r = Z_MEM_ERROR;
goto zerr;
}
*buf = newbuf;
}
zs.avail_out = bufsize - *size;
zs.next_out = (unsigned char*)(*buf + *size);
r = inflate(&zs, Z_NO_FLUSH);
if (r!=Z_OK && r!=Z_STREAM_END) goto zerr;
*size = bufsize - zs.avail_out;
} while (r==Z_OK && zs.avail_in);
} while (r==Z_OK);
if (*size<bufsize)
{
// free extra space
if (newbuf = realloc(*buf,*size)) *buf=newbuf;
}
inflateEnd(&zs);
return Z_OK;
zerr:
inflateEnd(&zs);
if (*buf)
{
free(*buf);
*buf = NULL;
}
return r;
}

6
tpws/gzip.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#include <stdio.h>
#include <zlib.h>
int z_readfile(FILE *F,char **buf,size_t *size);

82
tpws/hostlist.c Normal file
View File

@@ -0,0 +1,82 @@
#include <stdio.h>
#include "hostlist.h"
#include "gzip.h"
static bool addpool(strpool **hostlist, char **s, char *end)
{
char *p;
// advance until eol lowering all chars
for (p = *s; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
if (!StrPoolAddStrLen(hostlist, *s, p-*s))
{
StrPoolDestroy(hostlist);
*hostlist = NULL;
return false;
}
// advance to the next line
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++);
*s = p;
return true;
}
bool LoadHostList(strpool **hostlist, char *filename)
{
char *p, *e, s[256], *zbuf;
size_t zsize;
int ct = 0;
FILE *F;
if (*hostlist)
{
StrPoolDestroy(hostlist);
*hostlist = NULL;
}
if (!(F = fopen(filename, "rb")))
{
fprintf(stderr, "Could not open %s\n", filename);
return false;
}
if (z_readfile(F,&zbuf,&zsize)==Z_OK)
{
printf("libz compression detected. uncompressed size : %zu\n", zsize);
fclose(F);
p = zbuf;
e = zbuf + zsize;
while(p<e)
{
if (!addpool(hostlist,&p,e))
{
fprintf(stderr, "Not enough memory to store host list : %s\n", filename);
free(zbuf);
return false;
}
ct++;
}
free(zbuf);
}
else
{
fseek(F,0,SEEK_SET);
while (fgets(s, 256, F))
{
p = s;
if (!addpool(hostlist,&p,p+strlen(p)))
{
fprintf(stderr, "Not enough memory to store host list : %s\n", filename);
fclose(F);
return false;
}
ct++;
}
fclose(F);
}
printf("Loaded %d hosts from %s\n", ct, filename);
return true;
}

5
tpws/hostlist.h Normal file
View File

@@ -0,0 +1,5 @@
#pragma once
#include "strpool.h"
bool LoadHostList(strpool **hostlist, char *filename);

View File

@@ -11,6 +11,7 @@ static void ut_oom_recover(strpool *elem)
oom=true;
}
// for zero terminated strings
bool StrPoolAddStr(strpool **pp,const char *s)
{
strpool *elem;
@@ -31,6 +32,30 @@ bool StrPoolAddStr(strpool **pp,const char *s)
}
return true;
}
// for not zero terminated strings
bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen)
{
strpool *elem;
if (!(elem = (strpool*)malloc(sizeof(strpool))))
return false;
if (!(elem->str = malloc(slen+1)))
{
free(elem);
return false;
}
memcpy(elem->str,s,slen);
elem->str[slen]=0;
oom = false;
HASH_ADD_KEYPTR( hh, *pp, elem->str, strlen(elem->str), elem );
if (oom)
{
free(elem->str);
free(elem);
return false;
}
return true;
}
bool StrPoolCheckStr(strpool *p,const char *s)
{
strpool *elem;

View File

@@ -15,4 +15,5 @@ typedef struct strpool {
void StrPoolDestroy(strpool **p);
bool StrPoolAddStr(strpool **pp,const char *s);
bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen);
bool StrPoolCheckStr(strpool *p,const char *s);

View File

@@ -24,38 +24,7 @@
#include "tpws.h"
#include "tpws_conn.h"
#include "strpool.h"
bool LoadHostList(strpool **hostlist, char *filename)
{
char *p, s[256];
FILE *F = fopen(filename, "rt");
int ct = 0;
*hostlist = NULL;
if (!F)
{
fprintf(stderr, "Could not open %s\n", filename);
return false;
}
while (fgets(s, 256, F))
{
for (p = s + strlen(s) - 1; p >= s && (*p == '\r' || *p == '\n'); p--) *p = 0;
for (p = s; *p; p++) *p=tolower(*p);
if (!StrPoolAddStr(hostlist, s))
{
StrPoolDestroy(hostlist);
*hostlist = NULL;
fprintf(stderr, "Not enough memory to store host list : %s\n", filename);
fclose(F);
return false;
}
ct++;
}
fclose(F);
printf("Loaded %d hosts from %s\n", ct, filename);
return true;
}
#include "hostlist.h"
enum splithttpreq { split_none = 0, split_method, split_host };
@@ -72,6 +41,7 @@ struct params_s
int split_pos;
int maxconn;
char hostfile[256];
char pidfile[256];
strpool *hostlist;
};
@@ -104,7 +74,6 @@ void dohup()
{
if (params.hostlist)
{
StrPoolDestroy(&params.hostlist);
if (!LoadHostList(&params.hostlist, params.hostfile))
exit(1);
}
@@ -547,11 +516,29 @@ void exithelp()
" --methodeol\t\t; add end-of-line before method\n"
" --unixeol\t\t; replace 0D0A to 0A\n"
" --daemon\t\t; daemonize\n"
" --pidfile=<filename>\t; write pid to file\n"
" --user=<username>\t; drop root privs\n"
);
exit(1);
}
void cleanup_params()
{
if (params.hostlist)
{
StrPoolDestroy(&params.hostlist);
params.hostlist = NULL;
}
}
void exithelp_clean()
{
cleanup_params();
exithelp();
}
void exit_clean(int code)
{
cleanup_params();
exit(code);
}
void parse_params(int argc, char *argv[])
{
int option_index = 0;
@@ -580,16 +567,17 @@ void parse_params(int argc, char *argv[])
{ "hosttab",no_argument,0,0 },// optidx=15
{ "unixeol",no_argument,0,0 },// optidx=16
{ "hostlist",required_argument,0,0 },// optidx=17
{ "pidfile",required_argument,0,0 },// optidx=18
{ NULL,0,NULL,0 }
};
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
{
if (v) exithelp();
if (v) exithelp_clean();
switch (option_index)
{
case 0:
case 1:
exithelp();
exithelp_clean();
break;
case 2: /* bind-addr */
strncpy(params.bindaddr, optarg, sizeof(params.bindaddr));
@@ -600,7 +588,7 @@ void parse_params(int argc, char *argv[])
if (i <= 0 || i > 65535)
{
fprintf(stderr, "bad port number\n");
exit(1);
exit_clean(1);
}
params.port = (uint16_t)i;
break;
@@ -613,7 +601,7 @@ void parse_params(int argc, char *argv[])
if (!pwd)
{
fprintf(stderr, "non-existent username supplied\n");
exit(1);
exit_clean(1);
}
params.uid = pwd->pw_uid;
params.gid = pwd->pw_gid;
@@ -624,7 +612,7 @@ void parse_params(int argc, char *argv[])
if (params.maxconn <= 0)
{
fprintf(stderr, "bad maxconn\n");
exit(1);
exit_clean(1);
}
break;
case 7: /* hostcase */
@@ -634,7 +622,7 @@ void parse_params(int argc, char *argv[])
if (strlen(optarg) != 4)
{
fprintf(stderr, "hostspell must be exactly 4 chars long\n");
exit(1);
exit_clean(1);
}
params.hostcase = true;
memcpy(params.hostspell, optarg, 4);
@@ -653,7 +641,7 @@ void parse_params(int argc, char *argv[])
else
{
fprintf(stderr, "Invalid argument for split-http-req\n");
exit(1);
exit_clean(1);
}
break;
case 12: /* split-pos */
@@ -663,7 +651,7 @@ void parse_params(int argc, char *argv[])
else
{
fprintf(stderr, "Invalid argument for split-pos\n");
exit(1);
exit_clean(1);
}
break;
case 13: /* methodspace */
@@ -680,16 +668,20 @@ void parse_params(int argc, char *argv[])
break;
case 17: /* hostlist */
if (!LoadHostList(&params.hostlist, optarg))
exit(1);
exit_clean(1);
strncpy(params.hostfile,optarg,sizeof(params.hostfile));
params.hostfile[sizeof(params.hostfile)-1]='\0';
break;
case 18: /* pidfile */
strncpy(params.pidfile,optarg,sizeof(params.pidfile));
params.pidfile[sizeof(params.pidfile)-1]='\0';
break;
}
}
if (!params.port)
{
fprintf(stderr, "Need port number\n");
exit(1);
exit_clean(1);
}
}
@@ -740,8 +732,18 @@ bool droproot()
return true;
}
bool writepid(const char *filename)
{
FILE *F;
if (!(F=fopen(filename,"w")))
return false;
fprintf(F,"%d",getpid());
fclose(F);
return true;
}
int main(int argc, char *argv[]) {
int listen_fd = 0;
int listen_fd = -1;
int yes = 1, retval = 0;
int r;
struct sockaddr_storage salisten;
@@ -769,7 +771,7 @@ int main(int argc, char *argv[]) {
else
{
printf("bad bind addr\n");
exit(1);
goto exiterr;
}
}
else
@@ -783,29 +785,32 @@ int main(int argc, char *argv[]) {
if (params.daemon) daemonize();
if (*params.pidfile && !writepid(params.pidfile))
{
fprintf(stderr,"could not write pidfile\n");
goto exiterr;
}
if ((listen_fd = socket(salisten.ss_family, SOCK_STREAM, 0)) == -1) {
perror("socket: ");
exit(EXIT_FAILURE);
goto exiterr;
}
if ((salisten.ss_family == AF_INET6) && setsockopt(listen_fd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6_only, sizeof(ipv6_only)) == -1)
{
perror("setsockopt (IPV6_ONLY): ");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1)
{
perror("setsockopt (SO_REUSEADDR): ");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
if (setsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1)
{
perror("setsockopt (SO_KEEPALIVE): ");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
//Mark that this socket can be used for transparent proxying
@@ -813,26 +818,22 @@ int main(int argc, char *argv[]) {
if (setsockopt(listen_fd, SOL_IP, IP_TRANSPARENT, &yes, sizeof(yes)) == -1)
{
perror("setsockopt (IP_TRANSPARENT): ");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
if (!droproot())
{
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
if (bind(listen_fd, (struct sockaddr *)&salisten, salisten_len) == -1) {
perror("bind: ");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
if (listen(listen_fd, BACKLOG) == -1) {
perror("listen: ");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
//splice() causes the process to receive the SIGPIPE-signal if one part (for
@@ -840,8 +841,7 @@ int main(int argc, char *argv[]) {
//fail and return -1, so blocking SIGPIPE.
if (block_sigpipe() == -1) {
fprintf(stderr, "Could not block SIGPIPE signal\n");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
fprintf(stderr, "Will listen to port %d\n", params.port);
@@ -849,14 +849,16 @@ int main(int argc, char *argv[]) {
signal(SIGHUP, onhup);
retval = event_loop(listen_fd);
close(listen_fd);
if (params.hostlist) StrPoolDestroy(&params.hostlist);
cleanup_params();
fprintf(stderr, "Will exit\n");
if (retval < 0)
exit(EXIT_FAILURE);
else
exit(EXIT_SUCCESS);
return retval < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
exiterr:
if (listen_fd!=-1) close(listen_fd);
cleanup_params();
return EXIT_FAILURE;
}