134b94e8bSAlfred Perlstein /* 234b94e8bSAlfred Perlstein * Copyright (c) 2000 Paycounter, Inc. 334b94e8bSAlfred Perlstein * Author: Alfred Perlstein <alfred@paycounter.com>, <alfred@FreeBSD.org> 4a79b7128SAlfred Perlstein * All rights reserved. 5a79b7128SAlfred Perlstein * 6a79b7128SAlfred Perlstein * Redistribution and use in source and binary forms, with or without 7a79b7128SAlfred Perlstein * modification, are permitted provided that the following conditions 8a79b7128SAlfred Perlstein * are met: 9a79b7128SAlfred Perlstein * 1. Redistributions of source code must retain the above copyright 10a79b7128SAlfred Perlstein * notice, this list of conditions and the following disclaimer. 11a79b7128SAlfred Perlstein * 2. Redistributions in binary form must reproduce the above copyright 12a79b7128SAlfred Perlstein * notice, this list of conditions and the following disclaimer in the 13a79b7128SAlfred Perlstein * documentation and/or other materials provided with the distribution. 14a79b7128SAlfred Perlstein * 15a79b7128SAlfred Perlstein * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16a79b7128SAlfred Perlstein * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17a79b7128SAlfred Perlstein * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18a79b7128SAlfred Perlstein * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19a79b7128SAlfred Perlstein * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20a79b7128SAlfred Perlstein * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21a79b7128SAlfred Perlstein * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22a79b7128SAlfred Perlstein * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23a79b7128SAlfred Perlstein * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24a79b7128SAlfred Perlstein * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25a79b7128SAlfred Perlstein * SUCH DAMAGE. 26a79b7128SAlfred Perlstein * 27a79b7128SAlfred Perlstein * $FreeBSD$ 28a79b7128SAlfred Perlstein */ 29a79b7128SAlfred Perlstein 30a79b7128SAlfred Perlstein #define ACCEPT_FILTER_MOD 31a79b7128SAlfred Perlstein 32a79b7128SAlfred Perlstein #include <sys/param.h> 33a79b7128SAlfred Perlstein #include <sys/systm.h> 34a79b7128SAlfred Perlstein #include <sys/sysproto.h> 35a79b7128SAlfred Perlstein #include <sys/kernel.h> 36a79b7128SAlfred Perlstein #include <sys/proc.h> 37a79b7128SAlfred Perlstein #include <sys/malloc.h> 38a79b7128SAlfred Perlstein #include <sys/unistd.h> 39a79b7128SAlfred Perlstein #include <sys/file.h> 40a79b7128SAlfred Perlstein #include <sys/fcntl.h> 41a79b7128SAlfred Perlstein #include <sys/protosw.h> 4234b94e8bSAlfred Perlstein #include <sys/sysctl.h> 43a79b7128SAlfred Perlstein #include <sys/socket.h> 44a79b7128SAlfred Perlstein #include <sys/socketvar.h> 45a79b7128SAlfred Perlstein #include <sys/stat.h> 46a79b7128SAlfred Perlstein #include <sys/mbuf.h> 47a79b7128SAlfred Perlstein #include <sys/resource.h> 48a79b7128SAlfred Perlstein #include <sys/sysent.h> 49a79b7128SAlfred Perlstein #include <sys/resourcevar.h> 50a79b7128SAlfred Perlstein 5134b94e8bSAlfred Perlstein /* check for GET/HEAD */ 52a79b7128SAlfred Perlstein static void sohashttpget(struct socket *so, void *arg, int waitflag); 5334b94e8bSAlfred Perlstein /* check for HTTP/1.0 or HTTP/1.1 */ 5434b94e8bSAlfred Perlstein static void soparsehttpvers(struct socket *so, void *arg, int waitflag); 5534b94e8bSAlfred Perlstein /* check for end of HTTP/1.x request */ 56a79b7128SAlfred Perlstein static void soishttpconnected(struct socket *so, void *arg, int waitflag); 5734b94e8bSAlfred Perlstein /* strcmp on an mbuf chain */ 5834b94e8bSAlfred Perlstein static int mbufstrcmp(struct mbuf *m, struct mbuf *npkt, int offset, char *cmp); 5934b94e8bSAlfred Perlstein /* strncmp on an mbuf chain */ 6034b94e8bSAlfred Perlstein static int mbufstrncmp(struct mbuf *m, struct mbuf *npkt, int offset, 6134b94e8bSAlfred Perlstein int max, char *cmp); 6234b94e8bSAlfred Perlstein /* socketbuffer is full */ 6334b94e8bSAlfred Perlstein static int sbfull(struct sockbuf *sb); 64a79b7128SAlfred Perlstein 65a79b7128SAlfred Perlstein static struct accept_filter accf_http_filter = { 66a79b7128SAlfred Perlstein "httpready", 67a79b7128SAlfred Perlstein sohashttpget, 68a79b7128SAlfred Perlstein NULL, 69a79b7128SAlfred Perlstein NULL 70a79b7128SAlfred Perlstein }; 71a79b7128SAlfred Perlstein 72a79b7128SAlfred Perlstein static moduledata_t accf_http_mod = { 73a79b7128SAlfred Perlstein "accf_http", 74a79b7128SAlfred Perlstein accept_filt_generic_mod_event, 75a79b7128SAlfred Perlstein &accf_http_filter 76a79b7128SAlfred Perlstein }; 77a79b7128SAlfred Perlstein 78a79b7128SAlfred Perlstein DECLARE_MODULE(accf_http, accf_http_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); 79a79b7128SAlfred Perlstein 8034b94e8bSAlfred Perlstein static int parse_http_version = 1; 81a79b7128SAlfred Perlstein 8234b94e8bSAlfred Perlstein SYSCTL_NODE(_net_inet_accf, OID_AUTO, http, CTLFLAG_RW, 0, 8334b94e8bSAlfred Perlstein "HTTP accept filter"); 8434b94e8bSAlfred Perlstein SYSCTL_INT(_net_inet_accf_http, OID_AUTO, parsehttpversion, CTLFLAG_RW, 8534b94e8bSAlfred Perlstein &parse_http_version, 1, 8634b94e8bSAlfred Perlstein "Parse http version so that non 1.x requests work"); 8734b94e8bSAlfred Perlstein 8834b94e8bSAlfred Perlstein #ifdef ACCF_HTTP_DEBUG 8934b94e8bSAlfred Perlstein #define DPRINT(fmt, args...) \ 9034b94e8bSAlfred Perlstein do { \ 9134b94e8bSAlfred Perlstein printf("%s:%d: " fmt "\n", __func__, __LINE__ , ##args); \ 9234b94e8bSAlfred Perlstein } while (0) 9334b94e8bSAlfred Perlstein #else 9434b94e8bSAlfred Perlstein #define DPRINT(fmt, args...) 9534b94e8bSAlfred Perlstein #endif 9634b94e8bSAlfred Perlstein 9734b94e8bSAlfred Perlstein static int 9834b94e8bSAlfred Perlstein sbfull(struct sockbuf *sb) 99a79b7128SAlfred Perlstein { 100a79b7128SAlfred Perlstein 10134b94e8bSAlfred Perlstein DPRINT("sbfull, cc(%ld) >= hiwat(%ld): %d, mbcnt(%ld) >= mbmax(%ld): %d", 10234b94e8bSAlfred Perlstein sb->sb_cc, sb->sb_hiwat, sb->sb_cc >= sb->sb_hiwat, 10334b94e8bSAlfred Perlstein sb->sb_mbcnt, sb->sb_mbmax, sb->sb_mbcnt >= sb->sb_mbmax); 10434b94e8bSAlfred Perlstein return(sb->sb_cc >= sb->sb_hiwat || sb->sb_mbcnt >= sb->sb_mbmax); 10534b94e8bSAlfred Perlstein } 10634b94e8bSAlfred Perlstein 10734b94e8bSAlfred Perlstein /* 10834b94e8bSAlfred Perlstein * start at mbuf m, (must provide npkt if exists) 10934b94e8bSAlfred Perlstein * starting at offset in m compare characters in mbuf chain for 'cmp' 11034b94e8bSAlfred Perlstein */ 11134b94e8bSAlfred Perlstein static int 11234b94e8bSAlfred Perlstein mbufstrcmp(struct mbuf *m, struct mbuf *npkt, int offset, char *cmp) 11334b94e8bSAlfred Perlstein { 11434b94e8bSAlfred Perlstein struct mbuf *n; 11534b94e8bSAlfred Perlstein 11634b94e8bSAlfred Perlstein for (;m != NULL; m = n) { 11734b94e8bSAlfred Perlstein n = npkt; 11834b94e8bSAlfred Perlstein if (npkt) 11934b94e8bSAlfred Perlstein npkt = npkt->m_nextpkt; 12034b94e8bSAlfred Perlstein for (; m; m = m->m_next) { 12134b94e8bSAlfred Perlstein for (; offset < m->m_len; offset++, cmp++) { 12234b94e8bSAlfred Perlstein if (*cmp == '\0') { 12334b94e8bSAlfred Perlstein return (1); 12434b94e8bSAlfred Perlstein } else if (*cmp != *(mtod(m, char *) + offset)) { 12534b94e8bSAlfred Perlstein return (0); 126a79b7128SAlfred Perlstein } 127a79b7128SAlfred Perlstein } 12834b94e8bSAlfred Perlstein offset = 0; 129a79b7128SAlfred Perlstein } 13034b94e8bSAlfred Perlstein } 13134b94e8bSAlfred Perlstein return (0); 13234b94e8bSAlfred Perlstein } 13334b94e8bSAlfred Perlstein 13434b94e8bSAlfred Perlstein /* 13534b94e8bSAlfred Perlstein * start at mbuf m, (must provide npkt if exists) 13634b94e8bSAlfred Perlstein * starting at offset in m compare characters in mbuf chain for 'cmp' 13734b94e8bSAlfred Perlstein * stop at 'max' characters 13834b94e8bSAlfred Perlstein */ 13934b94e8bSAlfred Perlstein static int 14034b94e8bSAlfred Perlstein mbufstrncmp(struct mbuf *m, struct mbuf *npkt, int offset, int max, char *cmp) 14134b94e8bSAlfred Perlstein { 14234b94e8bSAlfred Perlstein struct mbuf *n; 14334b94e8bSAlfred Perlstein 14434b94e8bSAlfred Perlstein for (;m != NULL; m = n) { 14534b94e8bSAlfred Perlstein n = npkt; 14634b94e8bSAlfred Perlstein if (npkt) 14734b94e8bSAlfred Perlstein npkt = npkt->m_nextpkt; 14834b94e8bSAlfred Perlstein for (; m; m = m->m_next) { 14934b94e8bSAlfred Perlstein for (; offset < m->m_len; offset++, cmp++, max--) { 15034b94e8bSAlfred Perlstein if (max == 0 || *cmp == '\0') { 15134b94e8bSAlfred Perlstein return (1); 15234b94e8bSAlfred Perlstein } else if (*cmp != *(mtod(m, char *) + offset)) { 15334b94e8bSAlfred Perlstein return (0); 15434b94e8bSAlfred Perlstein } 15534b94e8bSAlfred Perlstein } 15634b94e8bSAlfred Perlstein offset = 0; 15734b94e8bSAlfred Perlstein } 15834b94e8bSAlfred Perlstein } 15934b94e8bSAlfred Perlstein return (0); 16034b94e8bSAlfred Perlstein } 16134b94e8bSAlfred Perlstein 16234b94e8bSAlfred Perlstein #define STRSETUP(sptr, slen, str) \ 16334b94e8bSAlfred Perlstein do { \ 16434b94e8bSAlfred Perlstein sptr = str; \ 16534b94e8bSAlfred Perlstein slen = sizeof(str) - 1; \ 16634b94e8bSAlfred Perlstein } while(0) 167a79b7128SAlfred Perlstein 168a79b7128SAlfred Perlstein static void 169a79b7128SAlfred Perlstein sohashttpget(struct socket *so, void *arg, int waitflag) 170a79b7128SAlfred Perlstein { 171a79b7128SAlfred Perlstein 17234b94e8bSAlfred Perlstein if ((so->so_state & SS_CANTRCVMORE) == 0 || !sbfull(&so->so_rcv)) { 173a79b7128SAlfred Perlstein struct mbuf *m; 17434b94e8bSAlfred Perlstein char *cmp; 17534b94e8bSAlfred Perlstein int cmplen, cc; 176a79b7128SAlfred Perlstein 177a79b7128SAlfred Perlstein m = so->so_rcv.sb_mb; 17834b94e8bSAlfred Perlstein cc = so->so_rcv.sb_cc - 1; 17934b94e8bSAlfred Perlstein if (cc < 1) 18034b94e8bSAlfred Perlstein return; 18134b94e8bSAlfred Perlstein switch (*mtod(m, char *)) { 18234b94e8bSAlfred Perlstein case 'G': 18334b94e8bSAlfred Perlstein STRSETUP(cmp, cmplen, "ET "); 18434b94e8bSAlfred Perlstein break; 18534b94e8bSAlfred Perlstein case 'H': 18634b94e8bSAlfred Perlstein STRSETUP(cmp, cmplen, "EAD "); 18734b94e8bSAlfred Perlstein break; 18834b94e8bSAlfred Perlstein default: 18934b94e8bSAlfred Perlstein goto fallout; 19034b94e8bSAlfred Perlstein } 19134b94e8bSAlfred Perlstein if (cc < cmplen) { 19234b94e8bSAlfred Perlstein if (mbufstrncmp(m, m->m_nextpkt, 1, cc, cmp) == 1) { 19334b94e8bSAlfred Perlstein DPRINT("short cc (%d) but mbufstrncmp ok", cc); 19434b94e8bSAlfred Perlstein return; 19534b94e8bSAlfred Perlstein } else { 19634b94e8bSAlfred Perlstein DPRINT("short cc (%d) mbufstrncmp failed", cc); 19734b94e8bSAlfred Perlstein goto fallout; 19834b94e8bSAlfred Perlstein } 19934b94e8bSAlfred Perlstein } 20034b94e8bSAlfred Perlstein if (mbufstrcmp(m, m->m_nextpkt, 1, cmp) == 1) { 20134b94e8bSAlfred Perlstein DPRINT("mbufstrcmp ok"); 20234b94e8bSAlfred Perlstein if (parse_http_version == 0) 203a79b7128SAlfred Perlstein soishttpconnected(so, arg, waitflag); 20434b94e8bSAlfred Perlstein else 20534b94e8bSAlfred Perlstein soparsehttpvers(so, arg, waitflag); 206a79b7128SAlfred Perlstein return; 207a79b7128SAlfred Perlstein } 20834b94e8bSAlfred Perlstein DPRINT("mbufstrcmp bad"); 209a79b7128SAlfred Perlstein } 210a79b7128SAlfred Perlstein 21134b94e8bSAlfred Perlstein fallout: 21234b94e8bSAlfred Perlstein DPRINT("fallout"); 213a79b7128SAlfred Perlstein so->so_upcall = NULL; 214a79b7128SAlfred Perlstein so->so_rcv.sb_flags &= ~SB_UPCALL; 215a79b7128SAlfred Perlstein soisconnected(so); 216a79b7128SAlfred Perlstein return; 217a79b7128SAlfred Perlstein } 218a79b7128SAlfred Perlstein 219a79b7128SAlfred Perlstein static void 22034b94e8bSAlfred Perlstein soparsehttpvers(struct socket *so, void *arg, int waitflag) 22134b94e8bSAlfred Perlstein { 22234b94e8bSAlfred Perlstein struct mbuf *m, *n; 22334b94e8bSAlfred Perlstein int i, cc, spaces, inspaces; 22434b94e8bSAlfred Perlstein 22534b94e8bSAlfred Perlstein if ((so->so_state & SS_CANTRCVMORE) != 0 || sbfull(&so->so_rcv)) 22634b94e8bSAlfred Perlstein goto fallout; 22734b94e8bSAlfred Perlstein 22834b94e8bSAlfred Perlstein m = so->so_rcv.sb_mb; 22934b94e8bSAlfred Perlstein cc = so->so_rcv.sb_cc; 23034b94e8bSAlfred Perlstein inspaces = spaces = 0; 23134b94e8bSAlfred Perlstein for (m = so->so_rcv.sb_mb; m; m = n) { 23234b94e8bSAlfred Perlstein n = m->m_nextpkt; 23334b94e8bSAlfred Perlstein for (; m; m = m->m_next) { 23434b94e8bSAlfred Perlstein for (i = 0; i < m->m_len; i++, cc--) { 23534b94e8bSAlfred Perlstein switch (*(mtod(m, char *) + i)) { 23634b94e8bSAlfred Perlstein case ' ': 23734b94e8bSAlfred Perlstein if (!inspaces) { 23834b94e8bSAlfred Perlstein spaces++; 23934b94e8bSAlfred Perlstein inspaces = 1; 24034b94e8bSAlfred Perlstein } 24134b94e8bSAlfred Perlstein break; 24234b94e8bSAlfred Perlstein case '\r': 24334b94e8bSAlfred Perlstein case '\n': 24434b94e8bSAlfred Perlstein DPRINT("newline"); 24534b94e8bSAlfred Perlstein goto fallout; 24634b94e8bSAlfred Perlstein default: 24734b94e8bSAlfred Perlstein if (spaces == 2) { 24834b94e8bSAlfred Perlstein /* make sure we have enough data left */ 24934b94e8bSAlfred Perlstein if (cc < sizeof("HTTP/1.0") - 1) { 25034b94e8bSAlfred Perlstein if (mbufstrncmp(m, n, i, cc, "HTTP/1.") == 1) { 25134b94e8bSAlfred Perlstein DPRINT("mbufstrncmp ok"); 25234b94e8bSAlfred Perlstein goto readmore; 25334b94e8bSAlfred Perlstein } else { 25434b94e8bSAlfred Perlstein DPRINT("mbufstrncmp bad"); 25534b94e8bSAlfred Perlstein goto fallout; 25634b94e8bSAlfred Perlstein } 25734b94e8bSAlfred Perlstein } else if (mbufstrcmp(m, n, i, "HTTP/1.0") == 1 || 25834b94e8bSAlfred Perlstein mbufstrcmp(m, n, i, "HTTP/1.1") == 1) { 25934b94e8bSAlfred Perlstein DPRINT("mbufstrcmp ok"); 26034b94e8bSAlfred Perlstein soishttpconnected(so, arg, waitflag); 26134b94e8bSAlfred Perlstein return; 26234b94e8bSAlfred Perlstein } else { 26334b94e8bSAlfred Perlstein DPRINT("mbufstrcmp bad"); 26434b94e8bSAlfred Perlstein goto fallout; 26534b94e8bSAlfred Perlstein } 26634b94e8bSAlfred Perlstein } 26734b94e8bSAlfred Perlstein inspaces = 0; 26834b94e8bSAlfred Perlstein break; 26934b94e8bSAlfred Perlstein } 27034b94e8bSAlfred Perlstein } 27134b94e8bSAlfred Perlstein } 27234b94e8bSAlfred Perlstein } 27334b94e8bSAlfred Perlstein readmore: 27434b94e8bSAlfred Perlstein DPRINT("readmore"); 27534b94e8bSAlfred Perlstein /* 27634b94e8bSAlfred Perlstein * if we hit here we haven't hit something 27734b94e8bSAlfred Perlstein * we don't understand or a newline, so try again 27834b94e8bSAlfred Perlstein */ 27934b94e8bSAlfred Perlstein so->so_upcall = soparsehttpvers; 28034b94e8bSAlfred Perlstein so->so_rcv.sb_flags |= SB_UPCALL; 28134b94e8bSAlfred Perlstein return; 28234b94e8bSAlfred Perlstein 28334b94e8bSAlfred Perlstein fallout: 28434b94e8bSAlfred Perlstein DPRINT("fallout"); 28534b94e8bSAlfred Perlstein so->so_upcall = NULL; 28634b94e8bSAlfred Perlstein so->so_rcv.sb_flags &= ~SB_UPCALL; 28734b94e8bSAlfred Perlstein soisconnected(so); 28834b94e8bSAlfred Perlstein return; 28934b94e8bSAlfred Perlstein } 29034b94e8bSAlfred Perlstein 29134b94e8bSAlfred Perlstein 29234b94e8bSAlfred Perlstein #define NCHRS 3 29334b94e8bSAlfred Perlstein 29434b94e8bSAlfred Perlstein static void 295a79b7128SAlfred Perlstein soishttpconnected(struct socket *so, void *arg, int waitflag) 296a79b7128SAlfred Perlstein { 297a79b7128SAlfred Perlstein char a, b, c; 29834b94e8bSAlfred Perlstein struct mbuf *m, *n; 29934b94e8bSAlfred Perlstein int ccleft, copied; 300a79b7128SAlfred Perlstein 30134b94e8bSAlfred Perlstein DPRINT("start"); 30234b94e8bSAlfred Perlstein if ((so->so_state & SS_CANTRCVMORE) != 0 || sbfull(&so->so_rcv)) 30334b94e8bSAlfred Perlstein goto gotit; 304a79b7128SAlfred Perlstein 30534b94e8bSAlfred Perlstein /* 30634b94e8bSAlfred Perlstein * Walk the socketbuffer and copy the last NCHRS (3) into a, b, and c 30734b94e8bSAlfred Perlstein * copied - how much we've copied so far 30834b94e8bSAlfred Perlstein * ccleft - how many bytes remaining in the socketbuffer 30934b94e8bSAlfred Perlstein * just loop over the mbufs subtracting from 'ccleft' until we only 31034b94e8bSAlfred Perlstein * have NCHRS left 31134b94e8bSAlfred Perlstein */ 31234b94e8bSAlfred Perlstein copied = 0; 31334b94e8bSAlfred Perlstein ccleft = so->so_rcv.sb_cc; 31434b94e8bSAlfred Perlstein if (ccleft < NCHRS) 31534b94e8bSAlfred Perlstein goto readmore; 31634b94e8bSAlfred Perlstein a = b = c = '\0'; 31734b94e8bSAlfred Perlstein for (m = so->so_rcv.sb_mb; m; m = n) { 31834b94e8bSAlfred Perlstein n = m->m_nextpkt; 31934b94e8bSAlfred Perlstein for (; m; m = m->m_next) { 32034b94e8bSAlfred Perlstein ccleft -= m->m_len; 32134b94e8bSAlfred Perlstein if (ccleft <= NCHRS) { 32234b94e8bSAlfred Perlstein char *src; 32334b94e8bSAlfred Perlstein int tocopy; 324a79b7128SAlfred Perlstein 32534b94e8bSAlfred Perlstein tocopy = (NCHRS - ccleft) - copied; 32634b94e8bSAlfred Perlstein src = mtod(m, char *) + (m->m_len - tocopy); 32734b94e8bSAlfred Perlstein 32834b94e8bSAlfred Perlstein while (tocopy--) { 32934b94e8bSAlfred Perlstein switch (copied++) { 330a79b7128SAlfred Perlstein case 0: 33134b94e8bSAlfred Perlstein a = *src++; 332a79b7128SAlfred Perlstein break; 33334b94e8bSAlfred Perlstein case 1: 33434b94e8bSAlfred Perlstein b = *src++; 33534b94e8bSAlfred Perlstein break; 33634b94e8bSAlfred Perlstein case 2: 33734b94e8bSAlfred Perlstein c = *src++; 338a79b7128SAlfred Perlstein break; 339a79b7128SAlfred Perlstein } 340a79b7128SAlfred Perlstein } 34134b94e8bSAlfred Perlstein } 34234b94e8bSAlfred Perlstein } 34334b94e8bSAlfred Perlstein } 344a79b7128SAlfred Perlstein if (c == '\n' && (b == '\n' || (b == '\r' && a == '\n'))) { 345a79b7128SAlfred Perlstein /* we have all request headers */ 34634b94e8bSAlfred Perlstein goto gotit; 34734b94e8bSAlfred Perlstein } 34834b94e8bSAlfred Perlstein 34934b94e8bSAlfred Perlstein readmore: 350a79b7128SAlfred Perlstein so->so_upcall = soishttpconnected; 351a79b7128SAlfred Perlstein so->so_rcv.sb_flags |= SB_UPCALL; 352a79b7128SAlfred Perlstein return; 353a79b7128SAlfred Perlstein 35434b94e8bSAlfred Perlstein gotit: 355a79b7128SAlfred Perlstein so->so_upcall = NULL; 356a79b7128SAlfred Perlstein so->so_rcv.sb_flags &= ~SB_UPCALL; 357a79b7128SAlfred Perlstein soisconnected(so); 358a79b7128SAlfred Perlstein return; 359a79b7128SAlfred Perlstein } 360