diff options
| author | Laurent Bercot <ska-skaware@skarnet.org> | 2026-06-25 09:01:50 +0000 |
|---|---|---|
| committer | Laurent Bercot <ska-skaware@skarnet.org> | 2026-06-25 09:01:50 +0000 |
| commit | 7c5d186df1f7f00567660354905435cedffc3e20 (patch) | |
| tree | 2911cf6d75a5be2a62fd493f2ad1a05ffc7c6bb3 | |
| parent | 51ff1577ce59449b36a86f21a90101bc2750943f (diff) | |
| download | tipidee-7c5d186df1f7f00567660354905435cedffc3e20.tar.gz | |
| -rw-r--r-- | doc/tipidee.conf.html | 24 | ||||
| -rw-r--r-- | package/deps.mak | 11 | ||||
| -rw-r--r-- | src/config/lexparse.c | 239 | ||||
| -rw-r--r-- | src/include/tipidee/conf.h | 10 | ||||
| -rw-r--r-- | src/include/tipidee/redirection.h | 38 | ||||
| -rw-r--r-- | src/include/tipidee/tipidee.h | 1 | ||||
| -rw-r--r-- | src/libtipidee/tipidee_conf_get_redirection.c | 42 | ||||
| -rw-r--r-- | src/tipideed/deps-exe/tipideed | 1 | ||||
| -rw-r--r-- | src/tipideed/fastcgi.c | 66 | ||||
| -rw-r--r-- | src/tipideed/redirection.c | 4 | ||||
| -rw-r--r-- | src/tipideed/rproxy.c | 11 | ||||
| -rw-r--r-- | src/tipideed/tipideed-internal.h | 5 | ||||
| -rw-r--r-- | src/tipideed/tipideed.c | 14 |
13 files changed, 312 insertions, 154 deletions
diff --git a/doc/tipidee.conf.html b/doc/tipidee.conf.html index ead500f..da3126a 100644 --- a/doc/tipidee.conf.html +++ b/doc/tipidee.conf.html @@ -919,6 +919,28 @@ or IPv6. </li> <em>resource</em> does not need to exist in the filesystem. The same caveats apply. </li> </ul> +<div id="fastcgi"> +<h4> <tt>fastcgi</tt> </h4> +</div> + +<p> + <code> fastcgi <em>resource</em> unix <em>socketpath</em> </code> <br> + <code> fastcgi <em>resource</em> tcp <em>ip</em> <em>port</em> </code> +</p> + +<ul> + <li> The <em>fastcgi</em> directive tells tipidee that when a client hits a +given URL, the server should let a FastCGI application answer the request. +For this exchange, tipideed will connect to the FastCGI server listening +either to a Unix domain socket on <em>socketpath</em> or to an INET domain +socket listening on IP address <em>ip</em> and port <em>port</em>. </li> + <li> It is similar to the <code>rproxy</code> directive, but whereas +<code>rproxy</code> makes tipideed act as an HTTP client, <code>fastcgi</code> +makes it act as a FastCGI client. </li> + <li> <em>resource</em> is the URI to redirect, relative to the current domain. + <li> Just like with the <code>redirect</code> and <code>rproxy</code> directives, +<em>resource</em> does not need to exist in the filesystem. The same caveats apply. </li> +</ul> <div id="noredirect"> <h4> <tt>noredirect</tt> </h4> @@ -934,7 +956,7 @@ useful to carve exceptions to a generic redirection policy: if you have a <code> directive for directory A and a <code>noredirect</code> directive for resource B, and A is a prefix of B, then B will not be redirected, but everything else under A will. </li> <li> You can also use <code>noredirect</code> to prevent <em>resource</em> from being -proxied by a more generic <code>rproxy</code> directive. +proxied by a more generic <code>rproxy</code> or <code>fastcgi</code> directive. </ul> <div id="custom-response"> diff --git a/package/deps.mak b/package/deps.mak index b5ad7e0..1d880dd 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -2,16 +2,16 @@ # This file has been generated by tools/gen-deps.sh # -src/include/tipidee/conf.h: src/include/tipidee/resattr.h src/include/tipidee/uri.h +src/include/tipidee/conf.h: src/include/tipidee/redirection.h src/include/tipidee/resattr.h src/include/tipidee/uri.h src/include/tipidee/log.h: src/include/tipidee/headers.h src/include/tipidee/resattr.h src/include/tipidee/rql.h src/include/tipidee/response.h: src/include/tipidee/headers.h src/include/tipidee/rql.h src/include/tipidee/rql.h: src/include/tipidee/method.h src/include/tipidee/uri.h -src/include/tipidee/tipidee.h: src/include/tipidee/conf.h src/include/tipidee/config.h src/include/tipidee/headers.h src/include/tipidee/log.h src/include/tipidee/method.h src/include/tipidee/resattr.h src/include/tipidee/response.h src/include/tipidee/rql.h src/include/tipidee/uri.h src/include/tipidee/util.h +src/include/tipidee/tipidee.h: src/include/tipidee/conf.h src/include/tipidee/config.h src/include/tipidee/headers.h src/include/tipidee/log.h src/include/tipidee/method.h src/include/tipidee/redirection.h src/include/tipidee/resattr.h src/include/tipidee/response.h src/include/tipidee/rql.h src/include/tipidee/uri.h src/include/tipidee/util.h src/tipideed/tipideed-internal.h: src/include/tipidee/tipidee.h src/config/conftree.o src/config/conftree.lo: src/config/conftree.c src/config/tipidee-config-internal.h src/config/defaults.o src/config/defaults.lo: src/config/defaults.c src/config/tipidee-config-internal.h src/include/tipidee/log.h src/config/headers.o src/config/headers.lo: src/config/headers.c src/config/tipidee-config-internal.h src/include/tipidee/config.h -src/config/lexparse.o src/config/lexparse.lo: src/config/lexparse.c src/config/tipidee-config-internal.h src/include/tipidee/config.h src/include/tipidee/log.h +src/config/lexparse.o src/config/lexparse.lo: src/config/lexparse.c src/config/tipidee-config-internal.h src/include/tipidee/config.h src/include/tipidee/log.h src/include/tipidee/redirection.h src/include/tipidee/resattr.h src/config/node.o src/config/node.lo: src/config/node.c src/config/tipidee-config-internal.h src/config/repo.o src/config/repo.lo: src/config/repo.c src/config/tipidee-config-internal.h src/config/tipidee-config-preprocess.o src/config/tipidee-config-preprocess.lo: src/config/tipidee-config-preprocess.c @@ -21,7 +21,7 @@ src/libtipidee/tipidee_conf_get.o src/libtipidee/tipidee_conf_get.lo: src/libtip src/libtipidee/tipidee_conf_get_argv.o src/libtipidee/tipidee_conf_get_argv.lo: src/libtipidee/tipidee_conf_get_argv.c src/include/tipidee/conf.h src/libtipidee/tipidee_conf_get_content_type.o src/libtipidee/tipidee_conf_get_content_type.lo: src/libtipidee/tipidee_conf_get_content_type.c src/include/tipidee/conf.h src/libtipidee/tipidee_conf_get_errorfile.o src/libtipidee/tipidee_conf_get_errorfile.lo: src/libtipidee/tipidee_conf_get_errorfile.c src/include/tipidee/conf.h -src/libtipidee/tipidee_conf_get_redirection.o src/libtipidee/tipidee_conf_get_redirection.lo: src/libtipidee/tipidee_conf_get_redirection.c src/include/tipidee/conf.h +src/libtipidee/tipidee_conf_get_redirection.o src/libtipidee/tipidee_conf_get_redirection.lo: src/libtipidee/tipidee_conf_get_redirection.c src/include/tipidee/conf.h src/include/tipidee/redirection.h src/libtipidee/tipidee_conf_get_resattr.o src/libtipidee/tipidee_conf_get_resattr.lo: src/libtipidee/tipidee_conf_get_resattr.c src/include/tipidee/conf.h src/include/tipidee/resattr.h src/libtipidee/tipidee_conf_get_resattr1.o src/libtipidee/tipidee_conf_get_resattr1.lo: src/libtipidee/tipidee_conf_get_resattr1.c src/include/tipidee/conf.h src/include/tipidee/resattr.h src/libtipidee/tipidee_conf_get_responseheaders.o src/libtipidee/tipidee_conf_get_responseheaders.lo: src/libtipidee/tipidee_conf_get_responseheaders.c src/include/tipidee/conf.h @@ -82,6 +82,7 @@ src/misc/ls.cgi.o src/misc/ls.cgi.lo: src/misc/ls.cgi.c src/include/tipidee/resp src/misc/tipidee-logaggregate.o src/misc/tipidee-logaggregate.lo: src/misc/tipidee-logaggregate.c src/tipideed/cgi.o src/tipideed/cgi.lo: src/tipideed/cgi.c src/include/tipidee/tipidee.h src/tipideed/tipideed-internal.h src/tipideed/errors.o src/tipideed/errors.lo: src/tipideed/errors.c src/include/tipidee/log.h src/include/tipidee/response.h src/include/tipidee/util.h src/tipideed/tipideed-internal.h +src/tipideed/fastcgi.o src/tipideed/fastcgi.lo: src/tipideed/fastcgi.c src/include/tipidee/tipidee.h src/tipideed/tipideed-internal.h src/tipideed/harden.o src/tipideed/harden.lo: src/tipideed/harden.c src/tipideed/tipideed-internal.h src/tipideed/options.o src/tipideed/options.lo: src/tipideed/options.c src/include/tipidee/log.h src/include/tipidee/response.h src/tipideed/tipideed-internal.h src/tipideed/redirection.o src/tipideed/redirection.lo: src/tipideed/redirection.c src/include/tipidee/log.h src/include/tipidee/response.h src/include/tipidee/util.h src/tipideed/tipideed-internal.h @@ -114,5 +115,5 @@ ls.cgi: src/misc/ls.cgi.o libtipidee.a.xyzzy -lskarnet tipidee-logaggregate: EXTRA_LIBS := tipidee-logaggregate: src/misc/tipidee-logaggregate.o -lskarnet tipideed: EXTRA_LIBS := ${SOCKET_LIB} ${SYSCLOCK_LIB} ${SPAWN_LIB} -tipideed: src/tipideed/tipideed.o src/tipideed/cgi.o src/tipideed/errors.o src/tipideed/harden.o src/tipideed/options.o src/tipideed/regular.o src/tipideed/redirection.o src/tipideed/rproxy.o src/tipideed/send_file.o src/tipideed/stream.o src/tipideed/trace.o src/tipideed/util.o libtipidee.a.xyzzy -lskarnet +tipideed: src/tipideed/tipideed.o src/tipideed/cgi.o src/tipideed/errors.o src/tipideed/harden.o src/tipideed/fastcgi.o src/tipideed/options.o src/tipideed/regular.o src/tipideed/redirection.o src/tipideed/rproxy.o src/tipideed/send_file.o src/tipideed/stream.o src/tipideed/trace.o src/tipideed/util.o libtipidee.a.xyzzy -lskarnet INTERNAL_LIBS := diff --git a/src/config/lexparse.c b/src/config/lexparse.c index b9136ad..dd74e65 100644 --- a/src/config/lexparse.c +++ b/src/config/lexparse.c @@ -5,6 +5,7 @@ #include <stdlib.h> #include <errno.h> +#include <skalibs/uint16.h> #include <skalibs/uint32.h> #include <skalibs/fmtscan.h> #include <skalibs/buffer.h> @@ -14,10 +15,12 @@ #include <skalibs/skamisc.h> #include <tipidee/log.h> +#include <tipidee/redirection.h> +#include <tipidee/resattr.h> #include <tipidee/config.h> #include "tipidee-config-internal.h" -#define dietoobig() strerr_diefu1sys(100, "read configuration") +#define dietoobig() strerr_diefusys(100, "read configuration") typedef struct mdt_s mdt, *mdt_ref ; struct mdt_s @@ -47,6 +50,7 @@ enum directivevalue_e T_REDIRECT, T_NOREDIRECT, T_RPROXY, + T_FASTCGI, T_CGI, T_NONCGI, T_NPH, @@ -69,6 +73,13 @@ enum customheaderoptionvalue_e CHO_NEVER } ; +static unsigned int log2u (uint32_t x) +{ + unsigned int n = 0 ; + while (x >>= 1) n++ ; + return n ; +} + static void conftree_checkunique (char const *key, mdt const *md) { node const *node = conftree_search(key) ; @@ -76,7 +87,7 @@ static void conftree_checkunique (char const *key, mdt const *md) { char fmt[UINT32_FMT] ; fmt[uint32_fmt(fmt, node->line)] = 0 ; - strerr_diefn(1, 12, "duplicate ", "key ", key, " in file ", g.storage.s + md->filepos, " line ", md->linefmt, ", previously defined", " in file ", g.storage.s + node->filepos, " line ", fmt) ; + strerr_dief(1, "duplicate ", "key ", key, " in file ", g.storage.s + md->filepos, " line ", md->linefmt, ", previously defined", " in file ", g.storage.s + node->filepos, " line ", fmt) ; } } @@ -87,7 +98,7 @@ static void headers_checkunique (char const *key, mdt const *md) { char fmt[UINT32_FMT] ; fmt[uint32_fmt(fmt, node->line)] = 0 ; - strerr_diefn(1, 12, "duplicate ", "header ", key, " in file ", g.storage.s + md->filepos, " line ", md->linefmt, ", previously defined", " in file ", g.storage.s + node->filepos, " line ", fmt) ; + strerr_dief(1, "duplicate ", "header ", key, " in file ", g.storage.s + md->filepos, " line ", md->linefmt, ", previously defined", " in file ", g.storage.s + node->filepos, " line ", fmt) ; } } @@ -116,11 +127,11 @@ static inline void parse_global (char const *s, size_t const *word, size_t n, md uint32_t u ; char pack[4] ; if (n != 2) - strerr_dief8x(1, "too ", n < 2 ? "few" : "many", " arguments to directive ", "global", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "too ", n < 2 ? "few" : "many", " arguments to directive ", "global", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; x = BSEARCH(char const *, s + word[0], globalkeys) ; if (!x) strerr_dief6x(1, "unrecognized global setting ", s + word[0], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (!uint320_scan(s + word[1], &u)) - strerr_dief6x(1, "invalid (non-numeric) value for global setting ", s + word[0], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "invalid (non-numeric) value for global setting ", s + word[0], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; uint32_pack_big(pack, u) ; { size_t len = strlen(*x) ; @@ -135,7 +146,7 @@ static inline void parse_indexfile (char const *s, size_t const *word, size_t n, { node node ; if (!n) - strerr_dief8x(1, "too ", "few", " arguments to directive ", "index_file", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "too ", "few", " arguments to directive ", "index_file", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; conftree_checkunique("G:index-file", md) ; confnode_start(&node, "G:index-file", md->filepos, md->line) ; for (size_t i = 0 ; i < n ; i++) @@ -164,14 +175,14 @@ static inline void parse_log (char const *s, size_t const *word, size_t n, mdt c uint32_t v = 0 ; char pack[4] ; if (!n) - strerr_dief8x(1, "too ", "few", " arguments to directive ", "log", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "too ", "few", " arguments to directive ", "log", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; for (size_t i = 0 ; i < n ; i++) { struct namevalue_s const *l = BSEARCH(struct namevalue_s, s + word[i], logkeys) ; if (!l) strerr_dief6x(1, "unrecognized log setting ", s + word[i], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (l->value) v |= l->value ; else if (n == 1) v = 0 ; - else strerr_dief5x(1, "log nothing cannot be mixed with other log values", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + else strerr_dief(1, "log nothing cannot be mixed with other log values", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; } uint32_pack_big(pack, v) ; @@ -182,17 +193,17 @@ static inline void parse_contenttype (char const *s, size_t const *word, size_t { char const *ct ; if (n < 2) - strerr_dief8x(1, "too ", "few", " arguments to directive ", "content-type", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "too ", "few", " arguments to directive ", "content-type", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; ct = s + *word++ ; if (!strchr(ct, '/')) - strerr_dief6x(1, "Content-Type must include a slash", " - check directive content-type", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "Content-Type must include a slash", " - check directive content-type", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; n-- ; for (size_t i = 0 ; i < n ; i++) { if (s[word[i]] == '\"' && s[word[i]+1] == '\"' && !s[word[i]+2]) add_unique("T:", ct, strlen(ct) + 1, md) ; else if (s[word[i]] != '.') - strerr_dief6x(1, "file extensions must be \"\" or start with a dot", " - check directive content-type", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "file extensions must be \"\" or start with a dot", " - check directive content-type", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; else { size_t len = strlen(s + word[i]) ; @@ -217,11 +228,11 @@ static inline void parse_customheader (char const *s, size_t const *word, size_t } ; struct namevalue_s const *p ; if (n < 2) - strerr_dief8x(1, "too ", "few", " arguments to directive ", "custom-header", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "too ", "few", " arguments to directive ", "custom-header", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; p = BSEARCH(struct namevalue_s, s + *word, choptions) ; - if (!p) strerr_dief9x(1, "invalid subcommand ", s + *word, " for", " directive ", "custom-header", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + if (!p) strerr_dief(1, "invalid subcommand ", s + *word, " for", " directive ", "custom-header", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if ((p->value == CHO_ADD || p->value == CHO_ALWAYS) == (n == 2)) - strerr_dief10x(1, "too ", n == 2 ? "few" : "many", " arguments to directive ", "custom-header", " ", p->name, " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "too ", n == 2 ? "few" : "many", " arguments to directive ", "custom-header", " ", p->name, " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; word++ ; n-- ; { size_t len = strlen(s + *word) ; @@ -229,7 +240,7 @@ static inline void parse_customheader (char const *s, size_t const *word, size_t memcpy(key, s + *word++, len + 1) ; n-- ; header_canonicalize(key) ; if (!header_allowed(key)) - strerr_dief7x(1, "header ", key, " cannot be customized", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "header ", key, " cannot be customized", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; headers_checkunique(key, md) ; switch (p->value) { @@ -253,11 +264,11 @@ static inline void parse_customheader (char const *s, size_t const *word, size_t static inline void parse_noredirect (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md) { if (n != 1) - strerr_dief8x(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", "noredirect", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", "noredirect", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (!domain) - strerr_dief6x(1, "noredirection", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "noredirection", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (s[*word] != '/') - strerr_dief6x(1, "noredirected resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "noredirected resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; { size_t urlen = strlen(s + *word) ; char key[3 + domainlen + urlen] ; @@ -266,8 +277,38 @@ static inline void parse_noredirect (char const *s, size_t const *word, size_t n memcpy(key + 2, domain, domainlen) ; memcpy(key + 2 + domainlen, s + *word, urlen) ; key[2 + domainlen + urlen] = 0 ; - add_unique(key, "\200", 2, md) ; + add_unique(key, "", 1, md) ; + } +} + +static void make_redirect_node (char const *sub, uint8_t type, uint8_t flags, char const *addr, uint16_t port, char const *domain, size_t domainlen, mdt const *md) +{ + node node ; + size_t sublen = strlen(sub) ; + char key[3 + domainlen + sublen] ; + if (sub[sublen - 1] == '/') { key[0] = 'r' ; sublen-- ; } else key[0] = 'R' ; + key[1] = ':' ; + memcpy(key + 2, domain, domainlen) ; + memcpy(key + 2 + domainlen, sub, sublen) ; + key[2 + domainlen + sublen] = 0 ; + conftree_checkunique(key, md) ; + confnode_start(&node, key, md->filepos, md->line) ; + confnode_add(&node, (char *)&type, 1) ; + confnode_add(&node, (char *)&flags, 1) ; + if (type >= 2 && flags & 1) + { + char pack[2] ; + uint16_pack_big(pack, port) ; + confnode_add(&node, pack, 2) ; + confnode_add(&node, addr, flags & 2 ? 16 : 4) ; + } + else + { + size_t addrlen = strlen(addr) ; + confnode_add(&node, addr, addrlen - (addr[addrlen - 1] == '/')) ; + confnode_add(&node, "", 1) ; } + conftree_add(&node) ; } static inline void parse_redirect (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md) @@ -276,104 +317,65 @@ static inline void parse_redirect (char const *s, size_t const *word, size_t n, uint32_t code ; uint32_t i = 0 ; if (n != 3) - strerr_dief8x(1, "too ", n > 3 ? "many" : "few", " arguments to directive ", "redirect", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "too ", n > 3 ? "many" : "few", " arguments to directive ", "redirect", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (!domain) - strerr_dief6x(1, "redirection", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "redirection", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (s[word[0]] != '/') - strerr_dief6x(1, "redirected resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "redirected resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (!uint320_scan(s + word[1], &code)) - strerr_dief6x(1, "invalid redirection code ", s + word[1], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "invalid redirection code ", s + word[1], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; for (; i < 4 ; i++) if (code == codes[i]) break ; if (i >= 4) - strerr_dief6x(1, "redirection code ", "must be 301, 302, 307 or 308", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "redirection code ", "must be 301, 302, 307 or 308", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (strncmp(s + word[2], "http://", 7) && strncmp(s + word[2], "https://", 8)) - strerr_dief5x(1, "redirection target must be a full http:// or https:// target", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; - { - node node ; - size_t urlen = strlen(s + word[0]) ; - char key[3 + domainlen + urlen] ; - if (s[word[0] + urlen - 1] == '/') { key[0] = 'r' ; urlen-- ; } else key[0] = 'R' ; - key[1] = ':' ; - memcpy(key + 2, domain, domainlen) ; - memcpy(key + 2 + domainlen, s + word[0], urlen) ; - key[2 + domainlen + urlen] = 0 ; - conftree_checkunique(key, md) ; - confnode_start(&node, key, md->filepos, md->line) ; - key[0] = '@' | i ; - confnode_add(&node, &key[0], 1) ; - urlen = strlen(s + word[2]) ; - confnode_add(&node, s + word[2], urlen - (s[word[2] + urlen - 1] == '/')) ; - confnode_add(&node, "", 1) ; - conftree_add(&node) ; - } + strerr_dief(1, "redirection target must be a full http:// or https:// target", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + make_redirect_node(s + word[0], TIPIDEE_REDIR_REDIRECT, i, s + word[2], 0, domain, domainlen, md) ; } -static inline void parse_rproxy (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md) +static inline void parse_rproxy_fastcgi (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md, int isfcgi) { - uint8_t type ; + char ip[16] ; + uint16_t port = 0 ; + uint8_t flags ; if (n < 3 || n > 4) - strerr_dief8x(1, "too ", n > 4 ? "many" : "few", " arguments to directive ", "rproxy", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "too ", n > 4 ? "many" : "few", " arguments to directive ", isfcgi ? "fastcgi" : "rproxy", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (!domain) - strerr_dief6x(1, "rproxy redirection", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "redirection", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (s[word[0]] != '/') - strerr_dief6x(1, "redirected resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; - if (!strcmp(s + word[1], "unix")) - type = 48 ; - else if (!strcmp(s + word[1], "tcp")) - type = 32 ; + strerr_dief(1, "redirected resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + if (!strcmp(s + word[1], "unix")) flags = 0 ; + else if (!strcmp(s + word[1], "tcp")) flags = 1 ; else - strerr_dief7x(1, "rproxy", " directive", " needs to specify unix or tcp", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, isfcgi ? "fastcgi" : "rproxy", " directive", " needs to specify unix or tcp", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + if (flags & 1) { - node node ; - size_t urlen = strlen(s + word[0]) ; - char key[3 + domainlen + urlen] ; - if (s[word[0] + urlen - 1] == '/') { key[0] = 'r' ; urlen-- ; } else key[0] = 'R' ; - key[1] = ':' ; - memcpy(key + 2, domain, domainlen) ; - memcpy(key + 2 + domainlen, s + word[0], urlen) ; - key[2 + domainlen + urlen] = 0 ; - conftree_checkunique(key, md) ; - confnode_start(&node, key, md->filepos, md->line) ; - - if (type == 48) - { - if (n != 3) - strerr_dief8x(1, "too ", "many" , " arguments to directive ", "rproxy", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; - key[0] = '@' | type ; - confnode_add(&node, &key[0], 1) ; - confnode_add(&node, s + word[2], strlen(s + word[2]) + 1) ; - } - else - { - char ip[16] ; - uint16_t port ; - if (n != 4) - strerr_dief8x(1, "too ", "few" , " arguments to directive ", "rproxy", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; - if (ip6_scan(s + word[2], ip)) type |= 8 ; - else if (!ip4_scan(s + word[2], ip)) - strerr_dief8x(1, "invalid ip address ", "in directive ", "rproxy", " tcp", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; - if (!uint160_scan(s + word[3], &port)) - strerr_dief8x(1, "invalid port ", "in directive ", "rproxy", " tcp", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; - key[0] = '@' | type ; - uint16_pack_big(key+1, port) ; - confnode_add(&node, key, 3) ; - confnode_add(&node, ip, type & 8 ? 16 : 4) ; - } - confnode_add(&node, "", 1) ; - conftree_add(&node) ; + if (n != 4) + strerr_dief(1, "too ", "few" , " arguments to directive ", isfcgi ? "fastcgi" : "rproxy", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + if (ip6_scan(s + word[2], ip)) flags |= 2 ; + else if (!ip4_scan(s + word[2], ip)) + strerr_dief(1, "invalid ip address ", "in directive ", isfcgi ? "fastcgi" : "rproxy", " tcp", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + if (!uint160_scan(s + word[3], &port)) + strerr_dief(1, "invalid port ", "in directive ", isfcgi ? "fastcgi" : "rproxy", " tcp", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + } + else + { + if (n != 3) + strerr_dief(1, "too ", "many" , " arguments to directive ", isfcgi ? "fastcgi" : "rproxy", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; } + make_redirect_node(s + word[0], 2 + isfcgi, flags, flags & 1 ? ip : s + word[2], port, domain, domainlen, md) ; } -static void parse_bitattr (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md, uint8_t bit, int h) +static void parse_bitattr (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md, uint32_t flag, int h) { static char const *const attr[5][2] = { { "noncgi", "cgi" }, { "nonnph", "nph" }, { "noauth", "basic-auth" }, { "noautochunk", "autochunk" }, { "norealtime", "realtime" } } ; + unsigned int bit = log2u(flag) ; if (n != 1) - strerr_dief8x(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", attr[bit][h], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", attr[bit][h], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (!domain) - strerr_dief7x(1, "resource attribute ", "definition", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "resource attribute ", "definition", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; if (s[*word] != '/') - strerr_dief6x(1, "resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; + strerr_dief(1, "resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ; { node const *oldnode ; size_t arglen = strlen(s + *word) ; @@ -389,22 +391,22 @@ static void parse_bitattr (char const *s, size_t const *word, size_t n, char con uint32_t flags, mask ; uint32_unpack_big(g.storage.s + oldnode->data, &flags) ; uint32_unpack_big(g.storage.s + oldnode->data + 4, &mask) ; - if (mask & 1 << bit) + if (mask & flag) { char fmt[UINT32_FMT] ; fmt[uint32_fmt(fmt, oldnode->line)] = 0 ; - strerr_diefn(1, 13, "resource attribute ", attr[bit][h], " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ; + strerr_dief(1, "resource attribute ", attr[bit][h], " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ; } - mask |= 1 << bit ; - if (h) flags |= 1 << bit ; else flags &= ~(1 << bit) ; + mask |= flag ; + if (h) flags |= flag ; else flags &= ~flag ; uint32_pack_big(g.storage.s + oldnode->data, flags) ; uint32_pack_big(g.storage.s + oldnode->data + 4, mask) ; } else { node node ; - uint32_t flags = h ? 1 << bit : 0 ; - uint32_t mask = 1 << bit ; + uint32_t flags = h ? flag : 0 ; + uint32_t mask = flag ; char val[9] = "\0\0\0\0\0\0\0\0" ; uint32_pack_big(val, flags) ; uint32_pack_big(val + 4, mask) ; @@ -435,11 +437,20 @@ static inline void parse_filetype (char const *s, size_t const *word, size_t n, oldnode = conftree_search(key) ; if (oldnode) { + uint32_t oldflags ; + uint32_unpack_big(g.storage.s + oldnode->data, &oldflags) ; + if (oldflags & (TIPIDEE_RA_FLAG_CGI | TIPIDEE_RA_FLAG_NPH)) + { + char fmt[UINT32_FMT] ; + fmt[uint32_fmt(fmt, oldnode->line)] = 0 ; + strerr_dief(1, "incompatible", "file-type", " definition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; conflicting attribute", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ; + } + if (g.storage.s[oldnode->data + 8]) { char fmt[UINT32_FMT] ; fmt[uint32_fmt(fmt, oldnode->line)] = 0 ; - strerr_diefn(1, 12, "file-type", " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ; + strerr_dief(1, "file-type", " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ; } else { @@ -499,6 +510,7 @@ static inline void process_line (char const *s, size_t const *word, size_t n, st { .name = "custom-header", .value = T_CUSTOMHEADER }, { .name = "custom-response", .value = T_CUSTOMRESPONSE }, { .name = "domain", .value = T_DOMAIN }, + { .name = "fastcgi", .value = T_FASTCGI }, { .name = "file-type", .value = T_FILETYPE }, { .name = "global", .value = T_GLOBAL }, { .name = "index-file", .value = T_INDEXFILE }, @@ -579,42 +591,45 @@ static inline void process_line (char const *s, size_t const *word, size_t n, st parse_redirect(s, word, n, domain->s, domain->len, md) ; break ; case T_RPROXY : - parse_rproxy(s, word, n, domain->s, domain->len, md) ; + parse_rproxy_fastcgi(s, word, n, domain->s, domain->len, md, 0) ; + break ; + case T_FASTCGI : + parse_rproxy_fastcgi(s, word, n, domain->s, domain->len, md, 1) ; break ; case T_NOREDIRECT : parse_noredirect(s, word, n, domain->s, domain->len, md) ; break ; case T_CGI : - parse_bitattr(s, word, n, domain->s, domain->len, md, 0, 1) ; + parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_CGI, 1) ; break ; case T_NONCGI : - parse_bitattr(s, word, n, domain->s, domain->len, md, 0, 0) ; + parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_CGI, 0) ; break ; case T_NPH : - parse_bitattr(s, word, n, domain->s, domain->len, md, 1, 1) ; + parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_NPH, 1) ; break ; case T_NONNPH : - parse_bitattr(s, word, n, domain->s, domain->len, md, 1, 0) ; + parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_NPH, 0) ; break ; case T_BASICAUTH : strerr_warnw5x("file ", g.storage.s + md->filepos, " line ", md->linefmt, ": directive basic-auth not implemented in tipidee-" TIPIDEE_VERSION) ; - parse_bitattr(s, word, n, domain->s, domain->len, md, 2, 1) ; + parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_BA, 1) ; break ; case T_NOAUTH : strerr_warnw5x("file ", g.storage.s + md->filepos, " line ", md->linefmt, ": directive basic-auth not implemented in tipidee-" TIPIDEE_VERSION) ; - parse_bitattr(s, word, n, domain->s, domain->len, md, 2, 0) ; + parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_BA, 0) ; break ; case T_AUTOCHUNK : - parse_bitattr(s, word, n, domain->s, domain->len, md, 3, 1) ; + parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_AUTOCHUNK, 1) ; break ; case T_NOAUTOCHUNK : - parse_bitattr(s, word, n, domain->s, domain->len, md, 3, 0) ; + parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_AUTOCHUNK, 0) ; break ; case T_REALTIME : - parse_bitattr(s, word, n, domain->s, domain->len, md, 4, 1) ; + parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_REALTIME, 1) ; break ; case T_NOREALTIME : - parse_bitattr(s, word, n, domain->s, domain->len, md, 4, 0) ; + parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_REALTIME, 0) ; break ; case T_FILETYPE : parse_filetype(s, word, n, domain->s, domain->len, md) ; diff --git a/src/include/tipidee/conf.h b/src/include/tipidee/conf.h index a173d6a..95273d6 100644 --- a/src/include/tipidee/conf.h +++ b/src/include/tipidee/conf.h @@ -10,6 +10,7 @@ #include <skalibs/uint32.h> #include <skalibs/cdb.h> +#include <tipidee/redirection.h> #include <tipidee/resattr.h> #include <tipidee/uri.h> @@ -22,15 +23,6 @@ struct tipidee_conf_s } ; #define TIPIDEE_CONF_ZERO { .c = CDB_ZERO } -typedef struct tipidee_redirection_s tipidee_redirection, *tipidee_redirection_ref ; -struct tipidee_redirection_s -{ - char const *sub ; - char const *location ; - uint8_t type ; -} ; -#define TIPIDEE_REDIRECTION_ZERO { .sub = 0, .location = 0, .type = 0 } - extern void tipidee_conf_free (tipidee_conf *) ; extern int tipidee_conf_init (tipidee_conf *, char const *) ; diff --git a/src/include/tipidee/redirection.h b/src/include/tipidee/redirection.h new file mode 100644 index 0000000..6c8d7d1 --- /dev/null +++ b/src/include/tipidee/redirection.h @@ -0,0 +1,38 @@ +/* ISC license. */ + +#ifndef TIPIDEE_REDIRECTION_H +#define TIPIDEE_REDIRECTION_H + +#include <stdint.h> + +enum tipidee_redir_type_e +{ + TIPIDEE_REDIR_NONE, + TIPIDEE_REDIR_REDIRECT, + TIPIDEE_REDIR_RPROXY, + TIPIDEE_REDIR_FASTCGI +} ; + + + /* for redirect */ +#define TIPIDEE_REDIR_307 0x0 +#define TIPIDEE_REDIR_308 0x1 +#define TIPIDEE_REDIR_302 0x2 +#define TIPIDEE_REDIR_301 0x3 + + /* for rproxy or fastcgi */ +#define TIPIDEE_REDIR_ISINET 0x1 +#define TIPIDEE_REDIR_ISV6 0x2 + +typedef struct tipidee_redirection_s tipidee_redirection, *tipidee_redirection_ref ; +struct tipidee_redirection_s +{ + char const *sub ; + char const *addr ; + uint16_t port ; + uint8_t type : 4 ; + uint8_t flags : 4 ; +} ; +#define TIPIDEE_REDIRECTION_ZERO { .sub = 0, .addr = 0, .port = 0, .type = TIPIDEE_REDIR_NONE, .flags = 0 } + +#endif diff --git a/src/include/tipidee/tipidee.h b/src/include/tipidee/tipidee.h index 7c5154c..50ee7bf 100644 --- a/src/include/tipidee/tipidee.h +++ b/src/include/tipidee/tipidee.h @@ -8,6 +8,7 @@ #include <tipidee/headers.h> #include <tipidee/log.h> #include <tipidee/method.h> +#include <tipidee/redirection.h> #include <tipidee/resattr.h> #include <tipidee/response.h> #include <tipidee/rql.h> diff --git a/src/libtipidee/tipidee_conf_get_redirection.c b/src/libtipidee/tipidee_conf_get_redirection.c index a8397ec..9c2456a 100644 --- a/src/libtipidee/tipidee_conf_get_redirection.c +++ b/src/libtipidee/tipidee_conf_get_redirection.c @@ -1,35 +1,53 @@ /* ISC license. */ #include <errno.h> +#include <stdint.h> #include <string.h> +#include <skalibs/uint16.h> +#include <skalibs/cdb.h> + +#include <tipidee/redirection.h> #include <tipidee/conf.h> #include <skalibs/posixishard.h> -static int get_redir (tipidee_conf const *conf, size_t minl, char *key, size_t l, char const *path, tipidee_redirection *r) +static int get_redir (tipidee_conf const *conf, size_t minl, char *key, size_t l, char const *path, tipidee_redirection *rd) { - char const *v = 0 ; + cdb_data data ; + int r = 0 ; key[0] = 'R' ; key[l] = '/' ; errno = ENOENT ; - while (!v) + while (!r) { if (errno != ENOENT) return -1 ; while (l >= minl && key[l] != '/') l-- ; - if (l < minl) break ; + if (l < minl) return 0 ; key[l--] = 0 ; - v = tipidee_conf_get_string(conf, key) ; + r = tipidee_conf_get(conf, key, &data) ; key[0] = 'r' ; } - if (!v || ((unsigned char)v[0] & 128)) return 0 ; - r->type = v[0] ; - r->location = v+1 ; - r->sub = path + (l - minl + 1) ; + if (data.len < 5) return (errno = EILSEQ, -1) ; + rd->sub = path + (l - minl + 1) ; + rd->type = *data.s++ ; data.len-- ; + if (!rd->type) + return data.len ? (errno = EILSEQ, -1) : 1 ; + rd->flags = *data.s++ ; data.len-- ; + if (rd->type >= 2 && rd->flags & TIPIDEE_REDIR_ISINET) + { + if (data.len != (rd->flags & TIPIDEE_REDIR_ISV6 ? 18 : 6)) + return (errno = EILSEQ, -1) ; + uint16_unpack_big(data.s, &rd->port) ; + data.s += 2 ; data.len -= 2 ; + } + else if (data.s[data.len - 1]) + return (errno = EILSEQ, -1) ; + rd->addr = data.s ; return 1 ; } -int tipidee_conf_get_redirection (tipidee_conf const *conf, char const *docroot, size_t docrootlen, char const *path, tipidee_redirection *r) +int tipidee_conf_get_redirection (tipidee_conf const *conf, char const *docroot, size_t docrootlen, char const *path, tipidee_redirection *rd) { size_t pathlen = strlen(path) ; char key[docrootlen + pathlen + 3] ; @@ -37,7 +55,7 @@ int tipidee_conf_get_redirection (tipidee_conf const *conf, char const *docroot, memcpy(key + 2, docroot, docrootlen) ; memcpy(key + 2 + docrootlen, path, pathlen + 1) ; { - int e = get_redir(conf, 2 + docrootlen, key, 2 + docrootlen + pathlen, path, r) ; + int e = get_redir(conf, 2 + docrootlen, key, 2 + docrootlen + pathlen, path, rd) ; if (e) return e ; } { @@ -47,5 +65,5 @@ int tipidee_conf_get_redirection (tipidee_conf const *conf, char const *docroot, } memcpy(key + 2, docroot, docrootlen) ; memcpy(key + 2 + docrootlen, path, pathlen + 1) ; - return get_redir(conf, 2 + docrootlen, key, 2 + docrootlen + pathlen, path, r) ; + return get_redir(conf, 2 + docrootlen, key, 2 + docrootlen + pathlen, path, rd) ; } diff --git a/src/tipideed/deps-exe/tipideed b/src/tipideed/deps-exe/tipideed index c099ab9..bc32b06 100644 --- a/src/tipideed/deps-exe/tipideed +++ b/src/tipideed/deps-exe/tipideed @@ -1,6 +1,7 @@ cgi.o errors.o harden.o +fastcgi.o options.o regular.o redirection.o diff --git a/src/tipideed/fastcgi.c b/src/tipideed/fastcgi.c new file mode 100644 index 0000000..5d5debf --- /dev/null +++ b/src/tipideed/fastcgi.c @@ -0,0 +1,66 @@ +/* ISC license. */ + +#include <stdint.h> +#include <unistd.h> +#include <strings.h> + +#include <skalibs/uint16.h> +#include <skalibs/fmtscan.h> +#include <skalibs/tai.h> +#include <skalibs/buffer.h> +#include <skalibs/djbunix.h> +#include <skalibs/socket.h> +#include <skalibs/ip46.h> +#include <skalibs/unix-timed.h> + +#include <tipidee/tipidee.h> +#include "tipideed-internal.h" + +#define putit(b, s, deadline) if (buffer_timed_puts_g(b, s, deadline) == -1) die500sys(rql, 111, docroot, "write to ", fn) + +static void do_fastcgi (tipidee_rql const *rql, int fd, char const *sub, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen, tain const *deadline, char const *fn) +{ + char buf[4096] ; + buffer b = BUFFER_INIT(&buffer_write, fd, buf, 4096) ; + _exit(0) ; +} + +static void fastcgi_unix (tipidee_rql const *rql, char const *socketpath, char const *sub, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen) +{ + tain deadline ; + int fd = ipc_stream_nbcoe() ; + if (fd == -1) die500sys(rql, 111, docroot, "create socket") ; + tain_add_g(&deadline, &g.readtto) ; + if (!ipc_timed_connect_g(fd, socketpath, &deadline)) die500sys(rql, 111, docroot, "connect to ", socketpath) ; + do_fastcgi(rql, fd, sub, docroot, hdr, body, bodylen, &deadline, socketpath) ; + fd_close(fd) ; +} + +static inline void fastcgi_tcp (tipidee_rql const *rql, char const *ip, uint16_t port, int is6, char const *sub, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen) +{ + tain deadline ; + size_t m = 0 ; + int fd = socket_tcp46_nbcoe(is6) ; + char fmt[IP6_FMT + UINT16_FMT + 2] ; + if (fd == -1) die500sys(rql, 111, docroot, "create socket") ; + tain_add_g(&deadline, &g.readtto) ; + if (is6) fmt[m++] = '[' ; + m += is6 ? ip6_fmt(fmt + m, ip) : ip4_fmt(fmt + m, ip) ; + if (is6) fmt[m++] = ']' ; + fmt[m++] = ':' ; + m += uint16_fmt(fmt + m, port) ; + fmt[m++] = 0 ; + + if (!(is6 ? socket_deadlineconnstamp6_g(fd, ip, port, &deadline) : socket_deadlineconnstamp4_g(fd, ip, port, &deadline))) + die500sys(rql, 111, docroot, "connect to ", fmt) ; + do_fastcgi(rql, fd, sub, docroot, hdr, body, bodylen, &deadline, fmt) ; + fd_close(fd) ; +} + +void fastcgi (tipidee_rql const *rql, tipidee_redirection const *rd, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen) +{ + if (rd->flags & TIPIDEE_REDIR_ISINET) + fastcgi_tcp(rql, rd->addr, rd->port, !!(rd->flags & TIPIDEE_REDIR_ISV6), rd->sub, docroot, hdr, body, bodylen) ; + else + fastcgi_unix(rql, rd->addr, rd->sub, docroot, hdr, body, bodylen) ; +} diff --git a/src/tipideed/redirection.c b/src/tipideed/redirection.c index ce32e44..f13eabb 100644 --- a/src/tipideed/redirection.c +++ b/src/tipideed/redirection.c @@ -15,12 +15,12 @@ void respond_30x (tipidee_rql const *rql, tipidee_redirection const *rd) static unsigned int const status[4] = { 307, 308, 302, 301 } ; tipidee_defaulttext dt ; tain deadline ; - unsigned int type = rd->type & 3 ; + unsigned int type = rd->flags & 3 ; tipidee_util_defaulttext(status[type], &dt) ; tipidee_response_status(buffer_1, rql, status[type], dt.reason) ; tipidee_response_header_writeall_G(buffer_1, g.rhdr, g.rhdrn, 0) ; buffer_putsnoflush(buffer_1, "Content-Length: 0\r\nLocation: ") ; - buffer_putsnoflush(buffer_1, rd->location) ; + buffer_putsnoflush(buffer_1, rd->addr) ; if (rd->sub) buffer_putsnoflush(buffer_1, rd->sub) ; buffer_putnoflush(buffer_1, "\r\n\r\n", 4) ; tipidee_log_answer(g.logv, rql, status[type], 0) ; diff --git a/src/tipideed/rproxy.c b/src/tipideed/rproxy.c index 5b0ec29..10e9692 100644 --- a/src/tipideed/rproxy.c +++ b/src/tipideed/rproxy.c @@ -64,7 +64,7 @@ static void rproxy_unix (tipidee_rql const *rql, char const *socketpath, char co fd_close(fd) ; } -static void rproxy_tcp (tipidee_rql const *rql, char const *ip, uint16_t port, int is6, char const *sub, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen) +static inline void rproxy_tcp (tipidee_rql const *rql, char const *ip, uint16_t port, int is6, char const *sub, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen) { tain deadline ; size_t m = 0 ; @@ -87,11 +87,8 @@ static void rproxy_tcp (tipidee_rql const *rql, char const *ip, uint16_t port, i void rproxy (tipidee_rql const *rql, tipidee_redirection const *rd, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen) { - if (rd->type & 16) rproxy_unix(rql, rd->location, rd->sub, docroot, hdr, body, bodylen) ; + if (rd->flags & TIPIDEE_REDIR_ISINET) + rproxy_tcp(rql, rd->addr, rd->port, !!(rd->flags & TIPIDEE_REDIR_ISV6), rd->sub, docroot, hdr, body, bodylen) ; else - { - uint16_t port ; - uint16_unpack_big(rd->location, &port) ; - rproxy_tcp(rql, rd->location + 2, port, !!(rd->type & 8), rd->sub, docroot, hdr, body, bodylen) ; - } + rproxy_unix(rql, rd->addr, rd->sub, docroot, hdr, body, bodylen) ; } diff --git a/src/tipideed/tipideed-internal.h b/src/tipideed/tipideed-internal.h index e3e014c..2cc8186 100644 --- a/src/tipideed/tipideed-internal.h +++ b/src/tipideed/tipideed-internal.h @@ -129,6 +129,11 @@ extern void respond_30x (tipidee_rql const *, tipidee_redirection const *) ; extern void rproxy (tipidee_rql const *, tipidee_redirection const *, char const *, tipidee_headers const *, char const *, size_t) ; + /* fastcgi */ + +extern void fastcgi (tipidee_rql const *, tipidee_redirection const *, char const *, tipidee_headers const *, char const *, size_t) ; + + /* trace */ extern int respond_trace (tipidee_rql const *, tipidee_headers const *) ; diff --git a/src/tipideed/tipideed.c b/src/tipideed/tipideed.c index b5098af..402c59c 100644 --- a/src/tipideed/tipideed.c +++ b/src/tipideed/tipideed.c @@ -211,12 +211,12 @@ static inline void get_resattr (tipidee_rql const *rql, char const *docroot, cha static inline void force_redirect (tipidee_rql const *rql, char const *fn) { - tipidee_redirection rd = { .sub = 0, .type = 1 } ; + tipidee_redirection rd = { .sub = 0, .type = TIPIDEE_REDIR_REDIRECT, .flags = TIPIDEE_REDIR_308, .port = 0 } ; size_t len = strlen(fn) ; char location[len + 8 + g.ssl] ; memcpy(location, g.ssl ? "https://" : "http://", 7 + g.ssl) ; memcpy(location + 7 + g.ssl, fn, len + 1) ; - rd.location = location ; + rd.addr = location ; respond_30x(rql, &rd) ; } @@ -241,11 +241,13 @@ static inline int serve (tipidee_rql *rql, char const *docroot, char *uribuf, ti tipidee_redirection rd = TIPIDEE_REDIRECTION_ZERO ; int e = tipidee_conf_get_redirection(&g.conf, docroot, docrootlen, rql->uri.path, &rd) ; if (e == -1) die500sys(rql, 111, docroot, "get redirection data for ", fn) ; - if (e) + if (e) switch (rd.type) { - if (rd.type & 32) rproxy(rql, &rd, docroot, hdr, body, bodylen) ; - else respond_30x(rql, &rd) ; - return 0 ; + case TIPIDEE_REDIR_NONE : break ; + case TIPIDEE_REDIR_REDIRECT : respond_30x(rql, &rd) ; return 0 ; + case TIPIDEE_REDIR_RPROXY : rproxy(rql, &rd, docroot, hdr, body, bodylen) ; return 0 ; + case TIPIDEE_REDIR_FASTCGI : fastcgi(rql, &rd, docroot, hdr, body, bodylen) ; return 0 ; + default : strerr_dief(101, "can't happen: ", "unknown redirection type") ; } } |
