From adb994129686d781a08c2e7178bc2dc723f6a72a Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 31 May 2012 15:29:18 +0200 Subject: [PATCH] Cleanup HTTP request handling. Answer 405 when relevant --- miniupnpd/Changelog.txt | 5 +- miniupnpd/upnphttp.c | 112 ++++++++++++++++++++++++++-------------- miniupnpd/upnphttp.h | 6 ++- 3 files changed, 82 insertions(+), 41 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 650d1ef..76dff86 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,4 +1,7 @@ -$Id: Changelog.txt,v 1.286 2012/05/27 22:35:10 nanard Exp $ +$Id: Changelog.txt,v 1.288 2012/05/31 09:32:39 nanard Exp $ + +2012/05/28: + Cleanup HTTP request handling. Answer 405 when relevant VERSION 1.7 : released the 2012/05/28 diff --git a/miniupnpd/upnphttp.c b/miniupnpd/upnphttp.c index 2db3148..933e94e 100644 --- a/miniupnpd/upnphttp.c +++ b/miniupnpd/upnphttp.c @@ -1,4 +1,4 @@ -/* $Id: upnphttp.c,v 1.71 2012/04/30 13:46:29 nanard Exp $ */ +/* $Id: upnphttp.c,v 1.73 2012/05/28 13:26:58 nanard Exp $ */ /* Project : miniupnp * Website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author : Thomas Bernard @@ -173,6 +173,20 @@ Send404(struct upnphttp * h) SendRespAndClose_upnphttp(h); } +static void +Send405(struct upnphttp * h) +{ + static const char body405[] = + "405 Method Not Allowed" + "

Method Not Allowed

The HTTP Method " + "is not allowed on this resource.\r\n"; + + h->respflags |= FLAG_HTML; + BuildResp2_upnphttp(h, 405, "Method Not Allowed", + body405, sizeof(body405) - 1); + SendRespAndClose_upnphttp(h); +} + /* very minimalistic 501 error message */ static void Send501(struct upnphttp * h) @@ -417,6 +431,27 @@ ProcessHTTPUnSubscribe_upnphttp(struct upnphttp * h, const char * path) static void ProcessHttpQuery_upnphttp(struct upnphttp * h) { + static const struct { + const char * path; + char * (* f)(int *); + } path_desc[] = { + { ROOTDESC_PATH, genRootDesc}, + { WANIPC_PATH, genWANIPCn}, + { WANCFG_PATH, genWANCfg}, +#ifdef HAS_DUMMY_SERVICE + { DUMMY_PATH, NULL}, +#endif +#ifdef ENABLE_L3F_SERVICE + { L3F_PATH, genL3F}, +#endif +#ifdef ENABLE_6FC_SERVICE + { WANIP6FC_PATH, gen6FC}, +#endif +#ifdef ENABLE_DP_SERVICE + { DP_PATH, genDP}, +#endif + { NULL, NULL} + }; char HttpCommand[16]; char HttpUrl[128]; char * HttpVer; @@ -450,47 +485,37 @@ ProcessHttpQuery_upnphttp(struct upnphttp * h) else if(strcmp("GET", HttpCommand) == 0) { h->req_command = EGet; - if(strcasecmp(ROOTDESC_PATH, HttpUrl) == 0) - { - sendXMLdesc(h, genRootDesc); - } - else if(strcasecmp(WANIPC_PATH, HttpUrl) == 0) - { - sendXMLdesc(h, genWANIPCn); - } - else if(strcasecmp(WANCFG_PATH, HttpUrl) == 0) - { - sendXMLdesc(h, genWANCfg); - } + for(i=0; path_desc[i].path; i++) { + if(strcasecmp(path_desc[i].path, HttpUrl) == 0) { + if(path_desc[i].f) + sendXMLdesc(h, path_desc[i].f); + else #ifdef HAS_DUMMY_SERVICE - else if(strcasecmp(DUMMY_PATH, HttpUrl) == 0) - { - sendDummyDesc(h); + sendDummyDesc(h); +#else + continue; +#endif + return; + } + } + if(0 == memcmp(HttpUrl, "/ctl/", 5)) { + /* 405 Method Not Allowed + * Allow: POST */ + h->respflags = FLAG_ALLOW_POST; + Send405(h); + return; + } +#ifdef ENABLE_EVENTS + if(0 == memcmp(HttpUrl, "/evt/", 5)) { + /* 405 Method Not Allowed + * Allow: SUBSCRIBE, UNSUBSCRIBE */ + h->respflags = FLAG_ALLOW_SUB_UNSUB; + Send405(h); + return; } #endif -#ifdef ENABLE_L3F_SERVICE - else if(strcasecmp(L3F_PATH, HttpUrl) == 0) - { - sendXMLdesc(h, genL3F); - } -#endif -#ifdef ENABLE_6FC_SERVICE - else if(strcasecmp(WANIP6FC_PATH, HttpUrl) == 0) - { - sendXMLdesc(h, gen6FC); - } -#endif -#ifdef ENABLE_DP_SERVICE - else if(strcasecmp(DP_PATH, HttpUrl) == 0) - { - sendXMLdesc(h, genDP); - } -#endif - else - { - syslog(LOG_NOTICE, "%s not found, responding ERROR 404", HttpUrl); - Send404(h); - } + syslog(LOG_NOTICE, "%s not found, responding ERROR 404", HttpUrl); + Send404(h); } #ifdef ENABLE_EVENTS else if(strcmp("SUBSCRIBE", HttpCommand) == 0) @@ -674,6 +699,15 @@ BuildHeader_upnphttp(struct upnphttp * h, int respcode, "SID: %s\r\n", h->res_SID); } #endif + if(h->respflags & FLAG_ALLOW_POST) { + h->res_buflen += snprintf(h->res_buf + h->res_buflen, + h->res_buf_alloclen - h->res_buflen, + "Allow: %s\r\n", "POST"); + } else if(h->respflags & FLAG_ALLOW_SUB_UNSUB) { + h->res_buflen += snprintf(h->res_buf + h->res_buflen, + h->res_buf_alloclen - h->res_buflen, + "Allow: %s\r\n", "SUBSCRIBE, UNSUBSCRIBE"); + } h->res_buf[h->res_buflen++] = '\r'; h->res_buf[h->res_buflen++] = '\n'; if(h->res_buf_alloclen < (h->res_buflen + bodylen)) diff --git a/miniupnpd/upnphttp.h b/miniupnpd/upnphttp.h index fb7b054..85cb525 100644 --- a/miniupnpd/upnphttp.h +++ b/miniupnpd/upnphttp.h @@ -1,4 +1,4 @@ -/* $Id: upnphttp.h,v 1.30 2012/04/25 22:26:05 nanard Exp $ */ +/* $Id: upnphttp.h,v 1.31 2012/05/28 11:00:44 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2012 Thomas Bernard @@ -88,6 +88,10 @@ struct upnphttp { /* If set, the Content-Type is set to text/xml, otherwise it is text/xml */ #define FLAG_HTML 0x80 +/* If set, the corresponding Allow: header is set */ +#define FLAG_ALLOW_POST 0x100 +#define FLAG_ALLOW_SUB_UNSUB 0x200 + /* New_upnphttp() */ struct upnphttp * New_upnphttp(int);