X-Git-Url: http://git.dolda2000.com/gitweb/?a=blobdiff_plain;f=src%2Fplaintcp.c;fp=src%2Fplaintcp.c;h=72a3959ea17d82edcc4ea2f6988e4b001730d15f;hb=8774c31b4795b6cd61aeddefe8bbd1d2551d84ca;hp=0000000000000000000000000000000000000000;hpb=9dc25d3d8337f3e9ecc31530f3be10b9ecf07422;p=ashd.git diff --git a/src/plaintcp.c b/src/plaintcp.c new file mode 100644 index 0000000..72a3959 --- /dev/null +++ b/src/plaintcp.c @@ -0,0 +1,179 @@ +/* + ashd - A Sane HTTP Daemon + Copyright (C) 2008 Fredrik Tolf + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include + +#include "htparser.h" + +struct tcpconn { + struct sockaddr_storage name; +}; + +static int listensock4(int port) +{ + struct sockaddr_in name; + int fd; + int valbuf; + + memset(&name, 0, sizeof(name)); + name.sin_family = AF_INET; + name.sin_port = htons(port); + if((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) + return(-1); + valbuf = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &valbuf, sizeof(valbuf)); + if(bind(fd, (struct sockaddr *)&name, sizeof(name))) { + close(fd); + return(-1); + } + if(listen(fd, 16) < 0) { + close(fd); + return(-1); + } + return(fd); +} + +static int listensock6(int port) +{ + struct sockaddr_in6 name; + int fd; + int valbuf; + + memset(&name, 0, sizeof(name)); + name.sin6_family = AF_INET6; + name.sin6_port = htons(port); + if((fd = socket(PF_INET6, SOCK_STREAM, 0)) < 0) + return(-1); + valbuf = 1; + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &valbuf, sizeof(valbuf)); + if(bind(fd, (struct sockaddr *)&name, sizeof(name))) { + close(fd); + return(-1); + } + if(listen(fd, 16) < 0) { + close(fd); + return(-1); + } + return(fd); +} + +static int initreq(struct conn *conn, struct hthead *req) +{ + struct tcpconn *tcp = conn->pdata; + char nmbuf[256]; + + if(tcp->name.ss_family == AF_INET) { + headappheader(req, "X-Ash-Address", inet_ntop(AF_INET, &((struct sockaddr_in *)&tcp->name)->sin_addr, nmbuf, sizeof(nmbuf))); + headappheader(req, "X-Ash-Port", sprintf3("%i", ntohs(((struct sockaddr_in *)&tcp->name)->sin_port))); + } else if(tcp->name.ss_family == AF_INET6) { + headappheader(req, "X-Ash-Address", inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&tcp->name)->sin6_addr, nmbuf, sizeof(nmbuf))); + headappheader(req, "X-Ash-Port", sprintf3("%i", ntohs(((struct sockaddr_in6 *)&tcp->name)->sin6_port))); + } + return(0); +} + +void servetcp(struct muth *muth, va_list args) +{ + vavar(int, fd); + vavar(struct sockaddr_storage, name); + FILE *in; + struct conn *conn; + struct tcpconn *tcp; + + in = mtstdopen(fd, 1, 60, "r+"); + omalloc(conn); + conn->pdata = omalloc(tcp); + conn->initreq = initreq; + tcp->name = name; + + serve(in, conn); + + free(tcp); + free(conn); +} + +static void listenloop(struct muth *muth, va_list args) +{ + vavar(int, ss); + int ns; + struct sockaddr_storage name; + socklen_t namelen; + + while(1) { + namelen = sizeof(name); + block(ss, EV_READ, 0); + ns = accept(ss, (struct sockaddr *)&name, &namelen); + if(ns < 0) { + flog(LOG_ERR, "accept: %s", strerror(errno)); + goto out; + } + mustart(servetcp, ns, name); + } + +out: + close(ss); +} + +void handleplain(int argc, char **argp, char **argv) +{ + int port, fd; + int i; + + port = 80; + for(i = 0; i < argc; i++) { + if(!strcmp(argp[i], "help")) { + printf("plain handler parameters:\n"); + printf("\tport=TCP-PORT (default is 80)\n"); + exit(0); + } else if(!strcmp(argp[i], "port")) { + port = atoi(argv[i]); + } else { + flog(LOG_ERR, "unknown parameter `%s' to plain handler", argp[i]); + exit(1); + } + } + if((fd = listensock6(port)) < 0) { + flog(LOG_ERR, "could not listen on IPv6 (port %i): %s", port, strerror(errno)); + exit(1); + } + mustart(listenloop, fd); + if((fd = listensock4(port)) < 0) { + if(errno != EADDRINUSE) { + flog(LOG_ERR, "could not listen on IPv4 (port %i): %s", port, strerror(errno)); + exit(1); + } + } else { + mustart(listenloop, fd); + } +}