#ifndef __PLB_H__ #define __PLB_H__ 1 #ifndef __GNUC__ # ifdef __attribute__ # undef __attribute__ # endif # define __attribute__(a) #endif #include #ifdef STDC_HEADERS # include # include # include #else # if HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !STDC_HEADERS && HAVE_MEMORY_H # include # endif # include #else # if HAVE_STRINGS_H # include # endif #endif #include #include #include #include #ifdef HAVE_UNISTD_H # include #endif #ifdef TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include #include #ifdef HAVE_FCNTL_H # include #elif defined(HAVE_SYS_FCNTL_H) # include #endif #ifdef HAVE_IOCTL_H # include #elif defined(HAVE_SYS_IOCTL_H) # include #endif #include #ifdef HAVE_NETINET_IN_SYSTM_H # include #endif #include #include #include #include #include #include #include #include #ifndef HAVE_GETOPT_LONG # include "bsd-getopt_long.h" #else # include #endif #ifdef HAVE_ALLOCA # ifdef HAVE_ALLOCA_H # include # endif # define ALLOCA(X) alloca(X) # define ALLOCA_FREE(X) do { } while (0) #else # define ALLOCA(X) malloc(X) # define ALLOCA_FREE(X) free(X) #endif #include "mysnprintf.h" #ifndef errno extern int errno; #endif #ifdef TCP_CORK # define CORK_ON(SK) do { int optval = 1; setsockopt(SK, SOL_TCP, TCP_CORK, \ &optval, sizeof optval); } while(0) # define CORK_OFF(SK) do { int optval = 0; setsockopt(SK, SOL_TCP, TCP_CORK, \ &optval, sizeof optval); } while(0) #else # define CORK_ON(SK) do { } while(0) # define CORK_OFF(SK) do { } while(0) #endif #ifndef O_NOFOLLOW # define O_NOFOLLOW 0 #endif #ifndef O_DIRECTORY # define O_DIRECTORY 0 #endif #ifndef SOL_IP # define SOL_IP IPPROTO_IP #endif #ifndef SOL_TCP # define SOL_TCP IPPROTO_TCP #endif #ifndef INADDR_NONE # define INADDR_NONE 0 #endif #if !defined(O_NDELAY) && defined(O_NONBLOCK) # define O_NDELAY O_NONBLOCK #endif #ifndef FNDELAY # define FNDELAY O_NDELAY #endif #ifndef HAVE_STRTOULL # ifdef HAVE_STRTOQ # define strtoull(X, Y, Z) strtoq(X, Y, Z) # else # define strtoull(X, Y, Z) strtoul(X, Y, Z) # endif #endif #ifndef ULONG_LONG_MAX # define ULONG_LONG_MAX (1ULL << 63) #endif #ifdef STAT_MACROS_BROKEN # undef S_ISBLK # undef S_ISCHR # undef S_ISDIR # undef S_ISFIFO # undef S_ISLNK # undef S_ISMPB # undef S_ISMPC # undef S_ISNWK # undef S_ISREG # undef S_ISSOCK #endif /* STAT_MACROS_BROKEN. */ #ifndef S_IFMT # define S_IFMT 0170000 #endif #if !defined(S_ISBLK) && defined(S_IFBLK) # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) #endif #if !defined(S_ISCHR) && defined(S_IFCHR) # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #endif #if !defined(S_ISDIR) && defined(S_IFDIR) # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #if !defined(S_ISREG) && defined(S_IFREG) # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif #if !defined(S_ISFIFO) && defined(S_IFIFO) # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) #endif #if !defined(S_ISLNK) && defined(S_IFLNK) # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) #endif #if !defined(S_ISSOCK) && defined(S_IFSOCK) # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) #endif #if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */ # define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB) # define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC) #endif #if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */ # define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK) #endif #ifndef S_IEXEC # define S_IEXEC S_IXUSR #endif #ifndef S_IXUSR # define S_IXUSR S_IEXEC #endif #ifndef S_IXGRP # define S_IXGRP (S_IEXEC >> 3) #endif #ifndef S_IXOTH # define S_IXOTH (S_IEXEC >> 6) #endif #ifndef S_IXUGO # define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH) #endif #ifndef STDIN_FILENO # define STDIN_FILENO 0 #endif #ifndef STDOUT_FILENO # define STDOUT_FILENO 1 #endif #ifndef STDERR_FILENO # define STDERR_FILENO 2 #endif #ifndef HAVE_SETEUID # ifdef HAVE_SETREUID # define seteuid(X) setreuid(-1, (X)) # elif defined(HAVE_SETRESUID) # define seteuid(X) setresuid(-1, (X), -1) # else # define seteuid(X) (-1) # endif #endif #ifndef HAVE_SETEGID # ifdef HAVE_SETREGID # define setegid(X) setregid(-1, (X)) # elif defined(HAVE_SETRESGID) # define setegid(X) setresgid(-1, (X), -1) # else # define setegid(X) (-1) # endif #endif #ifdef ACCEPT_UNICODE_CONTROL_CHARS # define ISCTRLCODE(X) ((X) == 0x7f || ((unsigned char) (X)) < 32U) #else # define ISCTRLCODE(X) ((X) == 0x7f || !(((unsigned char) (X)) & 0x60)) #endif #define DEFAULT_BACKLOG 100 #define HEADER_MAX 8192 #define POSTBUF_CHUNKS 8192 #define REPLYBUF_CHUNKS 32768 #define DEFAULT_SERVER_TIMEOUT 30 #define DEFAULT_CLIENT_TIMEOUT 30 #define DEFAULT_CLEANUP_TIMEOUT 30 #define DEFAULT_MAX_CLIENTS 1000 #define DEFAULT_SERVER_RETRY 15U #define HTTP_HEADER_END "\r\n\r\n" #define SMTP_HEADER_END "\r\n" #define DEFAULT_LOG_LEVEL LL_WARNING #define SERVER_FULL_MSG "Server too busy, sorry\r\n" /* change this for smtp */ typedef enum State_ { STATE_OFFLINE, STATE_HEADER, STATE_SEND_HEADER, STATE_HEADER_SENT, STATE_IGNORE } State; typedef enum LogLevel_ { LL_DEBUG, LL_NOTIFY, LL_WARNING, LL_ERROR, LL_FATAL } LogLevel; typedef enum Protocol_ { PROTOCOL_HTTP, PROTOCOL_SMTP } Protocol; typedef struct Server_ { char *name; struct Server_ *next; struct sockaddr_storage ai_addr; socklen_t ai_addrlen; int ai_family; unsigned int status; int cleanup_fd; struct event cleanup_ev; } Server; typedef struct Client_ { char *header; char *postbuf; char *replybuf; struct event client_read_ev; struct event client_write_ev; struct event server_read_ev; struct event server_write_ev; size_t header_len; size_t postbuf_len; size_t replybuf_len; size_t header_written; size_t postbuf_written; size_t replybuf_written; int client_fd; int server_fd; State state; Server *server; } Client; void init_timeouts(void); int setsockopt_aggressive(const int fd); void socket_nonblock(const int fd); int daemonize(void); int update_pid_file(const char * const pid_file); int delete_pid_file(void); void server_send_header(int evfd, short event, void *client_); void client_read_header(Client * const client); void server_forward_request(int evfd, short event, void *client_); void client_forward_request(Client * const client); void server_forward_reply(int evfd, short event, void *client_); void client_forward_reply(int evfd, short event, void *client_); int connect_server(Client * const client); void server_mark_failure(Client * const client); void client_read(const int evfd, short event, void * const client_); void client_disconnect(Client * const client); int handle_timeout(const short event, Client * const client); void new_client(const int listenfd, short event, void *ev_); void periodic_cleanup(int dummy, const short event, void *ev); int plb_open_log(const char * const log_file); void plb_close_log(void); void plb_log(const LogLevel level, const char * const fmt, ...) __attribute__ ((format(printf, 2, 3))); int plb_drop_caps(const char * const user, const char * const group, const char * const emptydir); #endif