33#define ACCEPT_FILTER_MOD
36#include <sys/kernel.h>
38#include <sys/module.h>
39#include <sys/signalvar.h>
40#include <sys/sysctl.h>
41#include <sys/socketvar.h>
44static int sohashttpget(
struct socket *so,
void *arg,
int waitflag);
50static int mbufstrcmp(
struct mbuf *m,
struct mbuf *npkt,
int offset,
char *cmp);
52static int mbufstrncmp(
struct mbuf *m,
struct mbuf *npkt,
int offset,
55static int sbfull(
struct sockbuf *sb);
62 CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
63 "HTTP accept filter");
64SYSCTL_INT(_net_inet_accf_http, OID_AUTO, parsehttpversion, CTLFLAG_RW,
66 "Parse http version so that non 1.x requests work");
69#define DPRINT(fmt, args...) \
71 printf("%s:%d: " fmt "\n", __func__, __LINE__, ##args); \
74#define DPRINT(fmt, args...)
81 DPRINT(
"sbfull, cc(%ld) >= hiwat(%ld): %d, "
82 "mbcnt(%ld) >= mbmax(%ld): %d",
83 sb->sb_cc, sb->sb_hiwat, sb->sb_cc >= sb->sb_hiwat,
84 sb->sb_mbcnt, sb->sb_mbmax, sb->sb_mbcnt >= sb->sb_mbmax);
85 return (sbused(sb) >= sb->sb_hiwat || sb->sb_mbcnt >= sb->sb_mbmax);
93mbufstrcmp(
struct mbuf *m,
struct mbuf *npkt,
int offset,
char *cmp)
97 for (; m != NULL; m = n) {
100 npkt = npkt->m_nextpkt;
101 for (; m; m = m->m_next) {
102 for (; offset < m->m_len; offset++, cmp++) {
105 else if (*cmp != *(mtod(m,
char *) + offset))
122mbufstrncmp(
struct mbuf *m,
struct mbuf *npkt,
int offset,
int max,
char *cmp)
126 for (; m != NULL; m = n) {
129 npkt = npkt->m_nextpkt;
130 for (; m; m = m->m_next) {
131 for (; offset < m->m_len; offset++, cmp++, max--) {
132 if (max == 0 || *cmp ==
'\0')
134 else if (*cmp != *(mtod(m,
char *) + offset))
137 if (max == 0 || *cmp ==
'\0')
145#define STRSETUP(sptr, slen, str) \
148 slen = sizeof(str) - 1; \
155 if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) == 0 &&
161 m = so->so_rcv.sb_mb;
162 cc = sbavail(&so->so_rcv) - 1;
165 switch (*mtod(m,
char *)) {
176 if (
mbufstrncmp(m, m->m_nextpkt, 1, cc, cmp) == 1) {
177 DPRINT(
"short cc (%d) but mbufstrncmp ok", cc);
180 DPRINT(
"short cc (%d) mbufstrncmp failed", cc);
184 if (
mbufstrcmp(m, m->m_nextpkt, 1, cmp) == 1) {
196 return (SU_ISCONNECTED);
203 int i, cc, spaces, inspaces;
205 if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) != 0 ||
sbfull(&so->so_rcv))
208 m = so->so_rcv.sb_mb;
209 cc = sbavail(&so->so_rcv);
210 inspaces = spaces = 0;
211 for (m = so->so_rcv.sb_mb; m; m = n) {
213 for (; m; m = m->m_next) {
214 for (i = 0; i < m->m_len; i++, cc--) {
215 switch (*(mtod(m,
char *) + i)) {
239 if (cc <
sizeof(
"HTTP/1.0") - 1) {
273 return (SU_ISCONNECTED);
286 if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) != 0 ||
sbfull(&so->so_rcv))
297 ccleft = sbavail(&so->so_rcv);
301 for (m = so->so_rcv.sb_mb; m; m = n) {
303 for (; m; m = m->m_next) {
305 if (ccleft <=
NCHRS) {
309 tocopy = (
NCHRS - ccleft) - copied;
310 src = mtod(m,
char *) + (m->m_len - tocopy);
328 if (c ==
'\n' && (b ==
'\n' || (b ==
'\r' && a ==
'\n'))) {
338 return (SU_ISCONNECTED);
#define DPRINT(fmt, args...)
static int soishttpconnected(struct socket *so, void *arg, int waitflag)
static int mbufstrncmp(struct mbuf *m, struct mbuf *npkt, int offset, int max, char *cmp)
SYSCTL_INT(_net_inet_accf_http, OID_AUTO, parsehttpversion, CTLFLAG_RW, &parse_http_version, 1, "Parse http version so that non 1.x requests work")
#define STRSETUP(sptr, slen, str)
static int soparsehttpvers(struct socket *so, void *arg, int waitflag)
static int parse_http_version
ACCEPT_FILTER_DEFINE(accf_http, "httpready", sohashttpget, NULL, NULL, 1)
static int sohashttpget(struct socket *so, void *arg, int waitflag)
static int mbufstrcmp(struct mbuf *m, struct mbuf *npkt, int offset, char *cmp)
static int sbfull(struct sockbuf *sb)
static SYSCTL_NODE(_net_inet_accf, OID_AUTO, http, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "HTTP accept filter")