1a79b7128SAlfred Perlstein /*- 2a79b7128SAlfred Perlstein * Copyright (c) 2000 Alfred Perlstein <alfred@FreeBSD.org> 3a79b7128SAlfred Perlstein * All rights reserved. 4a79b7128SAlfred Perlstein * 5a79b7128SAlfred Perlstein * Redistribution and use in source and binary forms, with or without 6a79b7128SAlfred Perlstein * modification, are permitted provided that the following conditions 7a79b7128SAlfred Perlstein * are met: 8a79b7128SAlfred Perlstein * 1. Redistributions of source code must retain the above copyright 9a79b7128SAlfred Perlstein * notice, this list of conditions and the following disclaimer. 10a79b7128SAlfred Perlstein * 2. Redistributions in binary form must reproduce the above copyright 11a79b7128SAlfred Perlstein * notice, this list of conditions and the following disclaimer in the 12a79b7128SAlfred Perlstein * documentation and/or other materials provided with the distribution. 13a79b7128SAlfred Perlstein * 14a79b7128SAlfred Perlstein * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15a79b7128SAlfred Perlstein * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16a79b7128SAlfred Perlstein * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17a79b7128SAlfred Perlstein * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18a79b7128SAlfred Perlstein * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19a79b7128SAlfred Perlstein * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20a79b7128SAlfred Perlstein * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21a79b7128SAlfred Perlstein * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22a79b7128SAlfred Perlstein * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23a79b7128SAlfred Perlstein * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24a79b7128SAlfred Perlstein * SUCH DAMAGE. 25a79b7128SAlfred Perlstein * 26a79b7128SAlfred Perlstein * $FreeBSD$ 27a79b7128SAlfred Perlstein */ 28a79b7128SAlfred Perlstein 29a79b7128SAlfred Perlstein #define ACCEPT_FILTER_MOD 30a79b7128SAlfred Perlstein 31a79b7128SAlfred Perlstein #include <sys/param.h> 32a79b7128SAlfred Perlstein #include <sys/systm.h> 33a79b7128SAlfred Perlstein #include <sys/sysproto.h> 34a79b7128SAlfred Perlstein #include <sys/kernel.h> 35a79b7128SAlfred Perlstein #include <sys/proc.h> 36a79b7128SAlfred Perlstein #include <sys/malloc.h> 37a79b7128SAlfred Perlstein #include <sys/unistd.h> 38a79b7128SAlfred Perlstein #include <sys/file.h> 39a79b7128SAlfred Perlstein #include <sys/fcntl.h> 40a79b7128SAlfred Perlstein #include <sys/protosw.h> 41a79b7128SAlfred Perlstein #include <sys/socket.h> 42a79b7128SAlfred Perlstein #include <sys/socketvar.h> 43a79b7128SAlfred Perlstein #include <sys/stat.h> 44a79b7128SAlfred Perlstein #include <sys/mbuf.h> 45a79b7128SAlfred Perlstein #include <sys/resource.h> 46a79b7128SAlfred Perlstein #include <sys/sysent.h> 47a79b7128SAlfred Perlstein #include <sys/resourcevar.h> 48a79b7128SAlfred Perlstein 49a79b7128SAlfred Perlstein /* 50a79b7128SAlfred Perlstein * XXX: doesn't work with 0.9 requests, make a seperate filter 51a79b7128SAlfred Perlstein * based on this one if you want to decode those. 52a79b7128SAlfred Perlstein */ 53a79b7128SAlfred Perlstein 54a79b7128SAlfred Perlstein /* check for GET */ 55a79b7128SAlfred Perlstein static void sohashttpget(struct socket *so, void *arg, int waitflag); 56a79b7128SAlfred Perlstein /* check for end of HTTP request */ 57a79b7128SAlfred Perlstein static void soishttpconnected(struct socket *so, void *arg, int waitflag); 58a79b7128SAlfred Perlstein static char sbindex(struct mbuf **mp, int *begin, int end); 59a79b7128SAlfred Perlstein 60a79b7128SAlfred Perlstein static struct accept_filter accf_http_filter = { 61a79b7128SAlfred Perlstein "httpready", 62a79b7128SAlfred Perlstein sohashttpget, 63a79b7128SAlfred Perlstein NULL, 64a79b7128SAlfred Perlstein NULL 65a79b7128SAlfred Perlstein }; 66a79b7128SAlfred Perlstein 67a79b7128SAlfred Perlstein static moduledata_t accf_http_mod = { 68a79b7128SAlfred Perlstein "accf_http", 69a79b7128SAlfred Perlstein accept_filt_generic_mod_event, 70a79b7128SAlfred Perlstein &accf_http_filter 71a79b7128SAlfred Perlstein }; 72a79b7128SAlfred Perlstein 73a79b7128SAlfred Perlstein DECLARE_MODULE(accf_http, accf_http_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); 74a79b7128SAlfred Perlstein 75a79b7128SAlfred Perlstein 76a79b7128SAlfred Perlstein static char 77a79b7128SAlfred Perlstein sbindex(struct mbuf **mp, int *begin, int end) 78a79b7128SAlfred Perlstein { 79a79b7128SAlfred Perlstein struct mbuf *m = *mp; 80a79b7128SAlfred Perlstein int diff = end - *begin + 1; 81a79b7128SAlfred Perlstein 82a79b7128SAlfred Perlstein while (m->m_len < diff) { 83a79b7128SAlfred Perlstein *begin += m->m_len; 84a79b7128SAlfred Perlstein diff -= m->m_len; 85a79b7128SAlfred Perlstein if (m->m_next) { 86a79b7128SAlfred Perlstein m = m->m_next; 87a79b7128SAlfred Perlstein } else if (m->m_nextpkt) { 88a79b7128SAlfred Perlstein m = m->m_nextpkt; 89a79b7128SAlfred Perlstein } else { 90a79b7128SAlfred Perlstein /* only happens if end > data in socket buffer */ 91a79b7128SAlfred Perlstein panic("sbindex: not enough data"); 92a79b7128SAlfred Perlstein } 93a79b7128SAlfred Perlstein } 94a79b7128SAlfred Perlstein *mp = m; 95a79b7128SAlfred Perlstein return *(mtod(m, char *) + diff - 1); 96a79b7128SAlfred Perlstein } 97a79b7128SAlfred Perlstein 98a79b7128SAlfred Perlstein static void 99a79b7128SAlfred Perlstein sohashttpget(struct socket *so, void *arg, int waitflag) 100a79b7128SAlfred Perlstein { 101a79b7128SAlfred Perlstein 102a79b7128SAlfred Perlstein if ((so->so_state & SS_CANTRCVMORE) == 0) { 103a79b7128SAlfred Perlstein struct mbuf *m; 104a79b7128SAlfred Perlstein 105a79b7128SAlfred Perlstein if (so->so_rcv.sb_cc < 6) 106a79b7128SAlfred Perlstein return; 107a79b7128SAlfred Perlstein m = so->so_rcv.sb_mb; 108a79b7128SAlfred Perlstein if (bcmp(mtod(m, char *), "GET ", 4) == 0) { 109a79b7128SAlfred Perlstein soishttpconnected(so, arg, waitflag); 110a79b7128SAlfred Perlstein return; 111a79b7128SAlfred Perlstein } 112a79b7128SAlfred Perlstein } 113a79b7128SAlfred Perlstein 114a79b7128SAlfred Perlstein so->so_upcall = NULL; 115a79b7128SAlfred Perlstein so->so_rcv.sb_flags &= ~SB_UPCALL; 116a79b7128SAlfred Perlstein soisconnected(so); 117a79b7128SAlfred Perlstein return; 118a79b7128SAlfred Perlstein } 119a79b7128SAlfred Perlstein 120a79b7128SAlfred Perlstein static void 121a79b7128SAlfred Perlstein soishttpconnected(struct socket *so, void *arg, int waitflag) 122a79b7128SAlfred Perlstein { 123a79b7128SAlfred Perlstein char a, b, c; 124a79b7128SAlfred Perlstein struct mbuf *y, *z; 125a79b7128SAlfred Perlstein 126a79b7128SAlfred Perlstein if ((so->so_state & SS_CANTRCVMORE) == 0) { 127a79b7128SAlfred Perlstein /* seek to end and keep track of next to last mbuf */ 128a79b7128SAlfred Perlstein y = so->so_rcv.sb_mb; 129a79b7128SAlfred Perlstein while (y->m_nextpkt) 130a79b7128SAlfred Perlstein y = y->m_nextpkt; 131a79b7128SAlfred Perlstein z = y; 132a79b7128SAlfred Perlstein while (y->m_next) { 133a79b7128SAlfred Perlstein z = y; 134a79b7128SAlfred Perlstein y = y->m_next; 135a79b7128SAlfred Perlstein } 136a79b7128SAlfred Perlstein 137a79b7128SAlfred Perlstein if (z->m_len + y->m_len > 2) { 138a79b7128SAlfred Perlstein int index = y->m_len - 1; 139a79b7128SAlfred Perlstein 140a79b7128SAlfred Perlstein c = *(mtod(y, char *) + index--); 141a79b7128SAlfred Perlstein switch (index) { 142a79b7128SAlfred Perlstein case -1: 143a79b7128SAlfred Perlstein y = z; 144a79b7128SAlfred Perlstein index = y->m_len - 1; 145a79b7128SAlfred Perlstein b = *(mtod(y, char *) + index--); 146a79b7128SAlfred Perlstein break; 147a79b7128SAlfred Perlstein case 0: 148a79b7128SAlfred Perlstein b = *(mtod(y, char *) + index--); 149a79b7128SAlfred Perlstein y = z; 150a79b7128SAlfred Perlstein index = y->m_len - 1; 151a79b7128SAlfred Perlstein break; 152a79b7128SAlfred Perlstein default: 153a79b7128SAlfred Perlstein b = *(mtod(y, char *) + index--); 154a79b7128SAlfred Perlstein break; 155a79b7128SAlfred Perlstein } 156a79b7128SAlfred Perlstein a = *(mtod(y, char *) + index--); 157a79b7128SAlfred Perlstein } else { 158a79b7128SAlfred Perlstein int begin = 0; 159a79b7128SAlfred Perlstein int end = so->so_rcv.sb_cc - 3; 160a79b7128SAlfred Perlstein 161a79b7128SAlfred Perlstein y = so->so_rcv.sb_mb; 162a79b7128SAlfred Perlstein a = sbindex(&y, &begin, end++); 163a79b7128SAlfred Perlstein b = sbindex(&y, &begin, end++); 164a79b7128SAlfred Perlstein c = sbindex(&y, &begin, end++); 165a79b7128SAlfred Perlstein } 166a79b7128SAlfred Perlstein 167a79b7128SAlfred Perlstein if (c == '\n' && (b == '\n' || (b == '\r' && a == '\n'))) { 168a79b7128SAlfred Perlstein /* we have all request headers */ 169a79b7128SAlfred Perlstein goto done; 170a79b7128SAlfred Perlstein } else { 171a79b7128SAlfred Perlstein /* still need more data */ 172a79b7128SAlfred Perlstein so->so_upcall = soishttpconnected; 173a79b7128SAlfred Perlstein so->so_rcv.sb_flags |= SB_UPCALL; 174a79b7128SAlfred Perlstein return; 175a79b7128SAlfred Perlstein } 176a79b7128SAlfred Perlstein } 177a79b7128SAlfred Perlstein 178a79b7128SAlfred Perlstein done: 179a79b7128SAlfred Perlstein so->so_upcall = NULL; 180a79b7128SAlfred Perlstein so->so_rcv.sb_flags &= ~SB_UPCALL; 181a79b7128SAlfred Perlstein soisconnected(so); 182a79b7128SAlfred Perlstein return; 183a79b7128SAlfred Perlstein } 184