]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/linux/linux-5.15.46-layer7.patch
Revert "kernel: update to 5.15.59"
[people/pmueller/ipfire-2.x.git] / src / patches / linux / linux-5.15.46-layer7.patch
CommitLineData
f25f1b55
PM
1diff -Naur linux-5.15.46.orig/include/linux/skbuff.h linux-5.15.46/include/linux/skbuff.h
2--- linux-5.15.46.orig/include/linux/skbuff.h 2022-06-11 14:51:47.639775333 +0000
3+++ linux-5.15.46/include/linux/skbuff.h 2022-06-11 14:53:07.977494189 +0000
4@@ -772,6 +772,9 @@
9b677b44 5 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
2e1fe3c8 6 unsigned long _nfct;
b2b44178 7 #endif
9b677b44
AF
8+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
9+ char layer7_flags[1];
b2b44178 10+#endif
c062c770
AF
11 unsigned int len,
12 data_len;
b2b44178 13 __u16 mac_len,
f25f1b55
PM
14diff -Naur linux-5.15.46.orig/include/net/netfilter/nf_conntrack.h linux-5.15.46/include/net/netfilter/nf_conntrack.h
15--- linux-5.15.46.orig/include/net/netfilter/nf_conntrack.h 2022-06-11 14:51:48.471834543 +0000
16+++ linux-5.15.46/include/net/netfilter/nf_conntrack.h 2022-06-11 14:53:07.977494189 +0000
db8639bb 17@@ -119,6 +119,23 @@
91648bd1
AF
18 /* Extensions */
19 struct nf_ct_ext *ext;
9d3616dc
AF
20
21+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || \
22+ defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
23+ struct {
24+ /*
25+ * e.g. "http". NULL before decision. "unknown" after decision
26+ * if no match.
27+ */
28+ char *app_proto;
29+ /*
30+ * application layer data so far. NULL after match decision.
31+ */
32+ char *app_data;
33+ unsigned int app_data_len;
9b677b44 34+ unsigned int packets;
9d3616dc
AF
35+ } layer7;
36+#endif
37+
38 /* Storage reserved for other modules, must be the last member */
39 union nf_conntrack_proto proto;
40 };
f25f1b55
PM
41diff -Naur linux-5.15.46.orig/include/uapi/linux/netfilter/xt_layer7.h linux-5.15.46/include/uapi/linux/netfilter/xt_layer7.h
42--- linux-5.15.46.orig/include/uapi/linux/netfilter/xt_layer7.h 1970-01-01 00:00:00.000000000 +0000
43+++ linux-5.15.46/include/uapi/linux/netfilter/xt_layer7.h 2022-06-11 14:53:07.977494189 +0000
3966b1e5
MT
44@@ -0,0 +1,13 @@
45+#ifndef _XT_LAYER7_H
46+#define _XT_LAYER7_H
47+
48+#define MAX_PATTERN_LEN 8192
49+#define MAX_PROTOCOL_LEN 256
50+
51+struct xt_layer7_info {
52+ char protocol[MAX_PROTOCOL_LEN];
53+ char pattern[MAX_PATTERN_LEN];
54+ u_int8_t invert;
55+};
56+
57+#endif /* _XT_LAYER7_H */
f25f1b55
PM
58diff -Naur linux-5.15.46.orig/net/netfilter/Kconfig linux-5.15.46/net/netfilter/Kconfig
59--- linux-5.15.46.orig/net/netfilter/Kconfig 2022-06-11 14:51:48.599843652 +0000
60+++ linux-5.15.46/net/netfilter/Kconfig 2022-06-11 14:53:07.977494189 +0000
b2b44178 61@@ -1389,6 +1389,26 @@
9d3616dc
AF
62
63 To compile it as a module, choose M here. If unsure, say N.
64
65+config NETFILTER_XT_MATCH_LAYER7
66+ tristate '"layer7" match support'
67+ depends on NETFILTER_XTABLES
68+ depends on NETFILTER_ADVANCED
69+ depends on NF_CONNTRACK
70+ help
71+ Say Y if you want to be able to classify connections (and their
72+ packets) based on regular expression matching of their application
73+ layer data. This is one way to classify applications such as
74+ peer-to-peer filesharing systems that do not always use the same
75+ port.
76+
77+ To compile it as a module, choose M here. If unsure, say N.
78+
79+config NETFILTER_XT_MATCH_LAYER7_DEBUG
80+ bool 'Layer 7 debugging output'
81+ depends on NETFILTER_XT_MATCH_LAYER7
82+ help
83+ Say Y to get lots of debugging output.
84+
85 config NETFILTER_XT_MATCH_LENGTH
86 tristate '"length" match support'
87 depends on NETFILTER_ADVANCED
f25f1b55
PM
88diff -Naur linux-5.15.46.orig/net/netfilter/Makefile linux-5.15.46/net/netfilter/Makefile
89--- linux-5.15.46.orig/net/netfilter/Makefile 2022-06-11 14:51:48.599843652 +0000
90+++ linux-5.15.46/net/netfilter/Makefile 2022-06-11 14:53:07.981494474 +0000
b2b44178 91@@ -201,6 +201,7 @@
9d3616dc
AF
92 obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
93 obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
94 obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
95+obj-$(CONFIG_NETFILTER_XT_MATCH_LAYER7) += xt_layer7.o
96 obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
97 obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
98 obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
f25f1b55
PM
99diff -Naur linux-5.15.46.orig/net/netfilter/nf_conntrack_core.c linux-5.15.46/net/netfilter/nf_conntrack_core.c
100--- linux-5.15.46.orig/net/netfilter/nf_conntrack_core.c 2022-06-11 14:51:48.599843652 +0000
101+++ linux-5.15.46/net/netfilter/nf_conntrack_core.c 2022-06-11 14:53:07.981494474 +0000
db8639bb 102@@ -648,6 +648,11 @@
ddc7b38c
AF
103 */
104 nf_ct_remove_expectations(ct);
9d3616dc
AF
105
106+#if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
9d3616dc
AF
107+ if(ct->layer7.app_data)
108+ kfree(ct->layer7.app_data);
109+#endif
110+
ddc7b38c 111 nf_ct_del_from_dying_or_unconfirmed_list(ct);
91648bd1 112
ddc7b38c 113 local_bh_enable();
f25f1b55
PM
114diff -Naur linux-5.15.46.orig/net/netfilter/nf_conntrack_standalone.c linux-5.15.46/net/netfilter/nf_conntrack_standalone.c
115--- linux-5.15.46.orig/net/netfilter/nf_conntrack_standalone.c 2022-06-11 14:51:48.603843938 +0000
116+++ linux-5.15.46/net/netfilter/nf_conntrack_standalone.c 2022-06-11 14:54:23.322859367 +0000
b2b44178 117@@ -370,6 +370,11 @@
91648bd1
AF
118 ct_show_zone(s, ct, NF_CT_DEFAULT_ZONE_DIR);
119 ct_show_delta_time(s, ct);
9d3616dc 120
db8639bb 121+ #if defined(CONFIG_NETFILTER_XT_MATCH_LAYER7) || defined(CONFIG_NETFILTER_XT_MATCH_LAYER7_MODULE)
91648bd1
AF
122+ if(ct->layer7.app_proto)
123+ seq_printf(s, "l7proto=%s ", ct->layer7.app_proto);
db8639bb 124+ #endif
9d3616dc 125+
db8639bb 126 seq_printf(s, "use=%u\n", refcount_read(&ct->ct_general.use));
9d3616dc 127
91648bd1 128 if (seq_has_overflowed(s))
f25f1b55
PM
129diff -Naur linux-5.15.46.orig/net/netfilter/regexp/regexp.c linux-5.15.46/net/netfilter/regexp/regexp.c
130--- linux-5.15.46.orig/net/netfilter/regexp/regexp.c 1970-01-01 00:00:00.000000000 +0000
131+++ linux-5.15.46/net/netfilter/regexp/regexp.c 2022-06-11 14:53:07.985494758 +0000
9d3616dc
AF
132@@ -0,0 +1,1197 @@
133+/*
134+ * regcomp and regexec -- regsub and regerror are elsewhere
135+ * @(#)regexp.c 1.3 of 18 April 87
136+ *
137+ * Copyright (c) 1986 by University of Toronto.
138+ * Written by Henry Spencer. Not derived from licensed software.
139+ *
140+ * Permission is granted to anyone to use this software for any
141+ * purpose on any computer system, and to redistribute it freely,
142+ * subject to the following restrictions:
143+ *
144+ * 1. The author is not responsible for the consequences of use of
145+ * this software, no matter how awful, even if they arise
146+ * from defects in it.
147+ *
148+ * 2. The origin of this software must not be misrepresented, either
149+ * by explicit claim or by omission.
150+ *
151+ * 3. Altered versions must be plainly marked as such, and must not
152+ * be misrepresented as being the original software.
153+ *
154+ * Beware that some of this code is subtly aware of the way operator
155+ * precedence is structured in regular expressions. Serious changes in
156+ * regular-expression syntax might require a total rethink.
157+ *
158+ * This code was modified by Ethan Sommer to work within the kernel
159+ * (it now uses kmalloc etc..)
160+ *
161+ * Modified slightly by Matthew Strait to use more modern C.
162+ */
163+
164+#include "regexp.h"
165+#include "regmagic.h"
166+
167+/* added by ethan and matt. Lets it work in both kernel and user space.
168+(So iptables can use it, for instance.) Yea, it goes both ways... */
169+#if __KERNEL__
170+ #define malloc(foo) kmalloc(foo,GFP_ATOMIC)
171+#else
172+ #define printk(format,args...) printf(format,##args)
173+#endif
174+
175+void regerror(char * s)
176+{
177+ printk("<3>Regexp: %s\n", s);
178+ /* NOTREACHED */
179+}
180+
181+/*
182+ * The "internal use only" fields in regexp.h are present to pass info from
183+ * compile to execute that permits the execute phase to run lots faster on
184+ * simple cases. They are:
185+ *
186+ * regstart char that must begin a match; '\0' if none obvious
187+ * reganch is the match anchored (at beginning-of-line only)?
188+ * regmust string (pointer into program) that match must include, or NULL
189+ * regmlen length of regmust string
190+ *
191+ * Regstart and reganch permit very fast decisions on suitable starting points
192+ * for a match, cutting down the work a lot. Regmust permits fast rejection
193+ * of lines that cannot possibly match. The regmust tests are costly enough
194+ * that regcomp() supplies a regmust only if the r.e. contains something
195+ * potentially expensive (at present, the only such thing detected is * or +
196+ * at the start of the r.e., which can involve a lot of backup). Regmlen is
197+ * supplied because the test in regexec() needs it and regcomp() is computing
198+ * it anyway.
199+ */
200+
201+/*
202+ * Structure for regexp "program". This is essentially a linear encoding
203+ * of a nondeterministic finite-state machine (aka syntax charts or
204+ * "railroad normal form" in parsing technology). Each node is an opcode
205+ * plus a "next" pointer, possibly plus an operand. "Next" pointers of
206+ * all nodes except BRANCH implement concatenation; a "next" pointer with
207+ * a BRANCH on both ends of it is connecting two alternatives. (Here we
208+ * have one of the subtle syntax dependencies: an individual BRANCH (as
209+ * opposed to a collection of them) is never concatenated with anything
210+ * because of operator precedence.) The operand of some types of node is
211+ * a literal string; for others, it is a node leading into a sub-FSM. In
212+ * particular, the operand of a BRANCH node is the first node of the branch.
213+ * (NB this is *not* a tree structure: the tail of the branch connects
214+ * to the thing following the set of BRANCHes.) The opcodes are:
215+ */
216+
217+/* definition number opnd? meaning */
218+#define END 0 /* no End of program. */
219+#define BOL 1 /* no Match "" at beginning of line. */
220+#define EOL 2 /* no Match "" at end of line. */
221+#define ANY 3 /* no Match any one character. */
222+#define ANYOF 4 /* str Match any character in this string. */
223+#define ANYBUT 5 /* str Match any character not in this string. */
224+#define BRANCH 6 /* node Match this alternative, or the next... */
225+#define BACK 7 /* no Match "", "next" ptr points backward. */
226+#define EXACTLY 8 /* str Match this string. */
227+#define NOTHING 9 /* no Match empty string. */
228+#define STAR 10 /* node Match this (simple) thing 0 or more times. */
229+#define PLUS 11 /* node Match this (simple) thing 1 or more times. */
230+#define OPEN 20 /* no Mark this point in input as start of #n. */
231+ /* OPEN+1 is number 1, etc. */
232+#define CLOSE 30 /* no Analogous to OPEN. */
233+
234+/*
235+ * Opcode notes:
236+ *
237+ * BRANCH The set of branches constituting a single choice are hooked
238+ * together with their "next" pointers, since precedence prevents
239+ * anything being concatenated to any individual branch. The
240+ * "next" pointer of the last BRANCH in a choice points to the
241+ * thing following the whole choice. This is also where the
242+ * final "next" pointer of each individual branch points; each
243+ * branch starts with the operand node of a BRANCH node.
244+ *
245+ * BACK Normal "next" pointers all implicitly point forward; BACK
246+ * exists to make loop structures possible.
247+ *
248+ * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
249+ * BRANCH structures using BACK. Simple cases (one character
250+ * per match) are implemented with STAR and PLUS for speed
251+ * and to minimize recursive plunges.
252+ *
253+ * OPEN,CLOSE ...are numbered at compile time.
254+ */
255+
256+/*
257+ * A node is one char of opcode followed by two chars of "next" pointer.
258+ * "Next" pointers are stored as two 8-bit pieces, high order first. The
259+ * value is a positive offset from the opcode of the node containing it.
260+ * An operand, if any, simply follows the node. (Note that much of the
261+ * code generation knows about this implicit relationship.)
262+ *
263+ * Using two bytes for the "next" pointer is vast overkill for most things,
264+ * but allows patterns to get big without disasters.
265+ */
266+#define OP(p) (*(p))
267+#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
268+#define OPERAND(p) ((p) + 3)
269+
270+/*
271+ * See regmagic.h for one further detail of program structure.
272+ */
273+
274+
275+/*
276+ * Utility definitions.
277+ */
278+#ifndef CHARBITS
279+#define UCHARAT(p) ((int)*(unsigned char *)(p))
280+#else
281+#define UCHARAT(p) ((int)*(p)&CHARBITS)
282+#endif
283+
284+#define FAIL(m) { regerror(m); return(NULL); }
285+#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
286+#define META "^$.[()|?+*\\"
287+
288+/*
289+ * Flags to be passed up and down.
290+ */
291+#define HASWIDTH 01 /* Known never to match null string. */
292+#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
293+#define SPSTART 04 /* Starts with * or +. */
294+#define WORST 0 /* Worst case. */
295+
296+/*
297+ * Global work variables for regcomp().
298+ */
299+struct match_globals {
300+char *reginput; /* String-input pointer. */
301+char *regbol; /* Beginning of input, for ^ check. */
302+char **regstartp; /* Pointer to startp array. */
303+char **regendp; /* Ditto for endp. */
304+char *regparse; /* Input-scan pointer. */
305+int regnpar; /* () count. */
306+char regdummy;
307+char *regcode; /* Code-emit pointer; &regdummy = don't. */
308+long regsize; /* Code size. */
309+};
310+
311+/*
312+ * Forward declarations for regcomp()'s friends.
313+ */
314+#ifndef STATIC
315+#define STATIC static
316+#endif
317+STATIC char *reg(struct match_globals *g, int paren,int *flagp);
318+STATIC char *regbranch(struct match_globals *g, int *flagp);
319+STATIC char *regpiece(struct match_globals *g, int *flagp);
320+STATIC char *regatom(struct match_globals *g, int *flagp);
321+STATIC char *regnode(struct match_globals *g, char op);
322+STATIC char *regnext(struct match_globals *g, char *p);
323+STATIC void regc(struct match_globals *g, char b);
324+STATIC void reginsert(struct match_globals *g, char op, char *opnd);
325+STATIC void regtail(struct match_globals *g, char *p, char *val);
326+STATIC void regoptail(struct match_globals *g, char *p, char *val);
327+
328+
329+__kernel_size_t my_strcspn(const char *s1,const char *s2)
330+{
331+ char *scan1;
332+ char *scan2;
333+ int count;
334+
335+ count = 0;
336+ for (scan1 = (char *)s1; *scan1 != '\0'; scan1++) {
337+ for (scan2 = (char *)s2; *scan2 != '\0';) /* ++ moved down. */
338+ if (*scan1 == *scan2++)
339+ return(count);
340+ count++;
341+ }
342+ return(count);
343+}
344+
345+/*
346+ - regcomp - compile a regular expression into internal code
347+ *
348+ * We can't allocate space until we know how big the compiled form will be,
349+ * but we can't compile it (and thus know how big it is) until we've got a
350+ * place to put the code. So we cheat: we compile it twice, once with code
351+ * generation turned off and size counting turned on, and once "for real".
352+ * This also means that we don't allocate space until we are sure that the
353+ * thing really will compile successfully, and we never have to move the
354+ * code and thus invalidate pointers into it. (Note that it has to be in
355+ * one piece because free() must be able to free it all.)
356+ *
357+ * Beware that the optimization-preparation code in here knows about some
358+ * of the structure of the compiled regexp.
359+ */
360+regexp *
361+regcomp(char *exp,int *patternsize)
362+{
363+ register regexp *r;
364+ register char *scan;
365+ register char *longest;
366+ register int len;
367+ int flags;
368+ struct match_globals g;
369+
370+ /* commented out by ethan
371+ extern char *malloc();
372+ */
373+
374+ if (exp == NULL)
375+ FAIL("NULL argument");
376+
377+ /* First pass: determine size, legality. */
378+ g.regparse = exp;
379+ g.regnpar = 1;
380+ g.regsize = 0L;
381+ g.regcode = &g.regdummy;
382+ regc(&g, MAGIC);
383+ if (reg(&g, 0, &flags) == NULL)
384+ return(NULL);
385+
386+ /* Small enough for pointer-storage convention? */
387+ if (g.regsize >= 32767L) /* Probably could be 65535L. */
388+ FAIL("regexp too big");
389+
390+ /* Allocate space. */
391+ *patternsize=sizeof(regexp) + (unsigned)g.regsize;
392+ r = (regexp *)malloc(sizeof(regexp) + (unsigned)g.regsize);
393+ if (r == NULL)
394+ FAIL("out of space");
395+
396+ /* Second pass: emit code. */
397+ g.regparse = exp;
398+ g.regnpar = 1;
399+ g.regcode = r->program;
400+ regc(&g, MAGIC);
401+ if (reg(&g, 0, &flags) == NULL)
402+ return(NULL);
403+
404+ /* Dig out information for optimizations. */
405+ r->regstart = '\0'; /* Worst-case defaults. */
406+ r->reganch = 0;
407+ r->regmust = NULL;
408+ r->regmlen = 0;
409+ scan = r->program+1; /* First BRANCH. */
410+ if (OP(regnext(&g, scan)) == END) { /* Only one top-level choice. */
411+ scan = OPERAND(scan);
412+
413+ /* Starting-point info. */
414+ if (OP(scan) == EXACTLY)
415+ r->regstart = *OPERAND(scan);
416+ else if (OP(scan) == BOL)
417+ r->reganch++;
418+
419+ /*
420+ * If there's something expensive in the r.e., find the
421+ * longest literal string that must appear and make it the
422+ * regmust. Resolve ties in favor of later strings, since
423+ * the regstart check works with the beginning of the r.e.
424+ * and avoiding duplication strengthens checking. Not a
425+ * strong reason, but sufficient in the absence of others.
426+ */
427+ if (flags&SPSTART) {
428+ longest = NULL;
429+ len = 0;
430+ for (; scan != NULL; scan = regnext(&g, scan))
431+ if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
432+ longest = OPERAND(scan);
433+ len = strlen(OPERAND(scan));
434+ }
435+ r->regmust = longest;
436+ r->regmlen = len;
437+ }
438+ }
439+
440+ return(r);
441+}
442+
443+/*
444+ - reg - regular expression, i.e. main body or parenthesized thing
445+ *
446+ * Caller must absorb opening parenthesis.
447+ *
448+ * Combining parenthesis handling with the base level of regular expression
449+ * is a trifle forced, but the need to tie the tails of the branches to what
450+ * follows makes it hard to avoid.
451+ */
452+static char *
453+reg(struct match_globals *g, int paren, int *flagp /* Parenthesized? */ )
454+{
455+ register char *ret;
456+ register char *br;
457+ register char *ender;
458+ register int parno = 0; /* 0 makes gcc happy */
459+ int flags;
460+
461+ *flagp = HASWIDTH; /* Tentatively. */
462+
463+ /* Make an OPEN node, if parenthesized. */
464+ if (paren) {
465+ if (g->regnpar >= NSUBEXP)
466+ FAIL("too many ()");
467+ parno = g->regnpar;
468+ g->regnpar++;
469+ ret = regnode(g, OPEN+parno);
470+ } else
471+ ret = NULL;
472+
473+ /* Pick up the branches, linking them together. */
474+ br = regbranch(g, &flags);
475+ if (br == NULL)
476+ return(NULL);
477+ if (ret != NULL)
478+ regtail(g, ret, br); /* OPEN -> first. */
479+ else
480+ ret = br;
481+ if (!(flags&HASWIDTH))
482+ *flagp &= ~HASWIDTH;
483+ *flagp |= flags&SPSTART;
484+ while (*g->regparse == '|') {
485+ g->regparse++;
486+ br = regbranch(g, &flags);
487+ if (br == NULL)
488+ return(NULL);
489+ regtail(g, ret, br); /* BRANCH -> BRANCH. */
490+ if (!(flags&HASWIDTH))
491+ *flagp &= ~HASWIDTH;
492+ *flagp |= flags&SPSTART;
493+ }
494+
495+ /* Make a closing node, and hook it on the end. */
496+ ender = regnode(g, (paren) ? CLOSE+parno : END);
497+ regtail(g, ret, ender);
498+
499+ /* Hook the tails of the branches to the closing node. */
500+ for (br = ret; br != NULL; br = regnext(g, br))
501+ regoptail(g, br, ender);
502+
503+ /* Check for proper termination. */
504+ if (paren && *g->regparse++ != ')') {
505+ FAIL("unmatched ()");
506+ } else if (!paren && *g->regparse != '\0') {
507+ if (*g->regparse == ')') {
508+ FAIL("unmatched ()");
509+ } else
510+ FAIL("junk on end"); /* "Can't happen". */
511+ /* NOTREACHED */
512+ }
513+
514+ return(ret);
515+}
516+
517+/*
518+ - regbranch - one alternative of an | operator
519+ *
520+ * Implements the concatenation operator.
521+ */
522+static char *
523+regbranch(struct match_globals *g, int *flagp)
524+{
525+ register char *ret;
526+ register char *chain;
527+ register char *latest;
528+ int flags;
529+
530+ *flagp = WORST; /* Tentatively. */
531+
532+ ret = regnode(g, BRANCH);
533+ chain = NULL;
534+ while (*g->regparse != '\0' && *g->regparse != '|' && *g->regparse != ')') {
535+ latest = regpiece(g, &flags);
536+ if (latest == NULL)
537+ return(NULL);
538+ *flagp |= flags&HASWIDTH;
539+ if (chain == NULL) /* First piece. */
540+ *flagp |= flags&SPSTART;
541+ else
542+ regtail(g, chain, latest);
543+ chain = latest;
544+ }
545+ if (chain == NULL) /* Loop ran zero times. */
546+ (void) regnode(g, NOTHING);
547+
548+ return(ret);
549+}
550+
551+/*
552+ - regpiece - something followed by possible [*+?]
553+ *
554+ * Note that the branching code sequences used for ? and the general cases
555+ * of * and + are somewhat optimized: they use the same NOTHING node as
556+ * both the endmarker for their branch list and the body of the last branch.
557+ * It might seem that this node could be dispensed with entirely, but the
558+ * endmarker role is not redundant.
559+ */
560+static char *
561+regpiece(struct match_globals *g, int *flagp)
562+{
563+ register char *ret;
564+ register char op;
565+ register char *next;
566+ int flags;
567+
568+ ret = regatom(g, &flags);
569+ if (ret == NULL)
570+ return(NULL);
571+
572+ op = *g->regparse;
573+ if (!ISMULT(op)) {
574+ *flagp = flags;
575+ return(ret);
576+ }
577+
578+ if (!(flags&HASWIDTH) && op != '?')
579+ FAIL("*+ operand could be empty");
580+ *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
581+
582+ if (op == '*' && (flags&SIMPLE))
583+ reginsert(g, STAR, ret);
584+ else if (op == '*') {
585+ /* Emit x* as (x&|), where & means "self". */
586+ reginsert(g, BRANCH, ret); /* Either x */
587+ regoptail(g, ret, regnode(g, BACK)); /* and loop */
588+ regoptail(g, ret, ret); /* back */
589+ regtail(g, ret, regnode(g, BRANCH)); /* or */
590+ regtail(g, ret, regnode(g, NOTHING)); /* null. */
591+ } else if (op == '+' && (flags&SIMPLE))
592+ reginsert(g, PLUS, ret);
593+ else if (op == '+') {
594+ /* Emit x+ as x(&|), where & means "self". */
595+ next = regnode(g, BRANCH); /* Either */
596+ regtail(g, ret, next);
597+ regtail(g, regnode(g, BACK), ret); /* loop back */
598+ regtail(g, next, regnode(g, BRANCH)); /* or */
599+ regtail(g, ret, regnode(g, NOTHING)); /* null. */
600+ } else if (op == '?') {
601+ /* Emit x? as (x|) */
602+ reginsert(g, BRANCH, ret); /* Either x */
603+ regtail(g, ret, regnode(g, BRANCH)); /* or */
604+ next = regnode(g, NOTHING); /* null. */
605+ regtail(g, ret, next);
606+ regoptail(g, ret, next);
607+ }
608+ g->regparse++;
609+ if (ISMULT(*g->regparse))
610+ FAIL("nested *?+");
611+
612+ return(ret);
613+}
614+
615+/*
616+ - regatom - the lowest level
617+ *
618+ * Optimization: gobbles an entire sequence of ordinary characters so that
619+ * it can turn them into a single node, which is smaller to store and
620+ * faster to run. Backslashed characters are exceptions, each becoming a
621+ * separate node; the code is simpler that way and it's not worth fixing.
622+ */
623+static char *
624+regatom(struct match_globals *g, int *flagp)
625+{
626+ register char *ret;
627+ int flags;
628+
629+ *flagp = WORST; /* Tentatively. */
630+
631+ switch (*g->regparse++) {
632+ case '^':
633+ ret = regnode(g, BOL);
634+ break;
635+ case '$':
636+ ret = regnode(g, EOL);
637+ break;
638+ case '.':
639+ ret = regnode(g, ANY);
640+ *flagp |= HASWIDTH|SIMPLE;
641+ break;
642+ case '[': {
643+ register int class;
644+ register int classend;
645+
646+ if (*g->regparse == '^') { /* Complement of range. */
647+ ret = regnode(g, ANYBUT);
648+ g->regparse++;
649+ } else
650+ ret = regnode(g, ANYOF);
651+ if (*g->regparse == ']' || *g->regparse == '-')
652+ regc(g, *g->regparse++);
653+ while (*g->regparse != '\0' && *g->regparse != ']') {
654+ if (*g->regparse == '-') {
655+ g->regparse++;
656+ if (*g->regparse == ']' || *g->regparse == '\0')
657+ regc(g, '-');
658+ else {
659+ class = UCHARAT(g->regparse-2)+1;
660+ classend = UCHARAT(g->regparse);
661+ if (class > classend+1)
662+ FAIL("invalid [] range");
663+ for (; class <= classend; class++)
664+ regc(g, class);
665+ g->regparse++;
666+ }
667+ } else
668+ regc(g, *g->regparse++);
669+ }
670+ regc(g, '\0');
671+ if (*g->regparse != ']')
672+ FAIL("unmatched []");
673+ g->regparse++;
674+ *flagp |= HASWIDTH|SIMPLE;
675+ }
676+ break;
677+ case '(':
678+ ret = reg(g, 1, &flags);
679+ if (ret == NULL)
680+ return(NULL);
681+ *flagp |= flags&(HASWIDTH|SPSTART);
682+ break;
683+ case '\0':
684+ case '|':
685+ case ')':
686+ FAIL("internal urp"); /* Supposed to be caught earlier. */
687+ break;
688+ case '?':
689+ case '+':
690+ case '*':
691+ FAIL("?+* follows nothing");
692+ break;
693+ case '\\':
694+ if (*g->regparse == '\0')
695+ FAIL("trailing \\");
696+ ret = regnode(g, EXACTLY);
697+ regc(g, *g->regparse++);
698+ regc(g, '\0');
699+ *flagp |= HASWIDTH|SIMPLE;
700+ break;
701+ default: {
702+ register int len;
703+ register char ender;
704+
705+ g->regparse--;
706+ len = my_strcspn((const char *)g->regparse, (const char *)META);
707+ if (len <= 0)
708+ FAIL("internal disaster");
709+ ender = *(g->regparse+len);
710+ if (len > 1 && ISMULT(ender))
711+ len--; /* Back off clear of ?+* operand. */
712+ *flagp |= HASWIDTH;
713+ if (len == 1)
714+ *flagp |= SIMPLE;
715+ ret = regnode(g, EXACTLY);
716+ while (len > 0) {
717+ regc(g, *g->regparse++);
718+ len--;
719+ }
720+ regc(g, '\0');
721+ }
722+ break;
723+ }
724+
725+ return(ret);
726+}
727+
728+/*
729+ - regnode - emit a node
730+ */
731+static char * /* Location. */
732+regnode(struct match_globals *g, char op)
733+{
734+ register char *ret;
735+ register char *ptr;
736+
737+ ret = g->regcode;
738+ if (ret == &g->regdummy) {
739+ g->regsize += 3;
740+ return(ret);
741+ }
742+
743+ ptr = ret;
744+ *ptr++ = op;
745+ *ptr++ = '\0'; /* Null "next" pointer. */
746+ *ptr++ = '\0';
747+ g->regcode = ptr;
748+
749+ return(ret);
750+}
751+
752+/*
753+ - regc - emit (if appropriate) a byte of code
754+ */
755+static void
756+regc(struct match_globals *g, char b)
757+{
758+ if (g->regcode != &g->regdummy)
759+ *g->regcode++ = b;
760+ else
761+ g->regsize++;
762+}
763+
764+/*
765+ - reginsert - insert an operator in front of already-emitted operand
766+ *
767+ * Means relocating the operand.
768+ */
769+static void
770+reginsert(struct match_globals *g, char op, char* opnd)
771+{
772+ register char *src;
773+ register char *dst;
774+ register char *place;
775+
776+ if (g->regcode == &g->regdummy) {
777+ g->regsize += 3;
778+ return;
779+ }
780+
781+ src = g->regcode;
782+ g->regcode += 3;
783+ dst = g->regcode;
784+ while (src > opnd)
785+ *--dst = *--src;
786+
787+ place = opnd; /* Op node, where operand used to be. */
788+ *place++ = op;
789+ *place++ = '\0';
790+ *place++ = '\0';
791+}
792+
793+/*
794+ - regtail - set the next-pointer at the end of a node chain
795+ */
796+static void
797+regtail(struct match_globals *g, char *p, char *val)
798+{
799+ register char *scan;
800+ register char *temp;
801+ register int offset;
802+
803+ if (p == &g->regdummy)
804+ return;
805+
806+ /* Find last node. */
807+ scan = p;
808+ for (;;) {
809+ temp = regnext(g, scan);
810+ if (temp == NULL)
811+ break;
812+ scan = temp;
813+ }
814+
815+ if (OP(scan) == BACK)
816+ offset = scan - val;
817+ else
818+ offset = val - scan;
819+ *(scan+1) = (offset>>8)&0377;
820+ *(scan+2) = offset&0377;
821+}
822+
823+/*
824+ - regoptail - regtail on operand of first argument; nop if operandless
825+ */
826+static void
827+regoptail(struct match_globals *g, char *p, char *val)
828+{
829+ /* "Operandless" and "op != BRANCH" are synonymous in practice. */
830+ if (p == NULL || p == &g->regdummy || OP(p) != BRANCH)
831+ return;
832+ regtail(g, OPERAND(p), val);
833+}
834+
835+/*
836+ * regexec and friends
837+ */
838+
839+
840+/*
841+ * Forwards.
842+ */
843+STATIC int regtry(struct match_globals *g, regexp *prog, char *string);
844+STATIC int regmatch(struct match_globals *g, char *prog);
845+STATIC int regrepeat(struct match_globals *g, char *p);
846+
847+#ifdef DEBUG
848+int regnarrate = 0;
849+void regdump();
850+STATIC char *regprop(char *op);
851+#endif
852+
853+/*
854+ - regexec - match a regexp against a string
855+ */
856+int
857+regexec(regexp *prog, char *string)
858+{
859+ register char *s;
860+ struct match_globals g;
861+
862+ /* Be paranoid... */
863+ if (prog == NULL || string == NULL) {
864+ printk("<3>Regexp: NULL parameter\n");
865+ return(0);
866+ }
867+
868+ /* Check validity of program. */
869+ if (UCHARAT(prog->program) != MAGIC) {
870+ printk("<3>Regexp: corrupted program\n");
871+ return(0);
872+ }
873+
874+ /* If there is a "must appear" string, look for it. */
875+ if (prog->regmust != NULL) {
876+ s = string;
877+ while ((s = strchr(s, prog->regmust[0])) != NULL) {
878+ if (strncmp(s, prog->regmust, prog->regmlen) == 0)
879+ break; /* Found it. */
880+ s++;
881+ }
882+ if (s == NULL) /* Not present. */
883+ return(0);
884+ }
885+
886+ /* Mark beginning of line for ^ . */
887+ g.regbol = string;
888+
889+ /* Simplest case: anchored match need be tried only once. */
890+ if (prog->reganch)
891+ return(regtry(&g, prog, string));
892+
893+ /* Messy cases: unanchored match. */
894+ s = string;
895+ if (prog->regstart != '\0')
896+ /* We know what char it must start with. */
897+ while ((s = strchr(s, prog->regstart)) != NULL) {
898+ if (regtry(&g, prog, s))
899+ return(1);
900+ s++;
901+ }
902+ else
903+ /* We don't -- general case. */
904+ do {
905+ if (regtry(&g, prog, s))
906+ return(1);
907+ } while (*s++ != '\0');
908+
909+ /* Failure. */
910+ return(0);
911+}
912+
913+/*
914+ - regtry - try match at specific point
915+ */
916+static int /* 0 failure, 1 success */
917+regtry(struct match_globals *g, regexp *prog, char *string)
918+{
919+ register int i;
920+ register char **sp;
921+ register char **ep;
922+
923+ g->reginput = string;
924+ g->regstartp = prog->startp;
925+ g->regendp = prog->endp;
926+
927+ sp = prog->startp;
928+ ep = prog->endp;
929+ for (i = NSUBEXP; i > 0; i--) {
930+ *sp++ = NULL;
931+ *ep++ = NULL;
932+ }
933+ if (regmatch(g, prog->program + 1)) {
934+ prog->startp[0] = string;
935+ prog->endp[0] = g->reginput;
936+ return(1);
937+ } else
938+ return(0);
939+}
940+
941+/*
942+ - regmatch - main matching routine
943+ *
944+ * Conceptually the strategy is simple: check to see whether the current
945+ * node matches, call self recursively to see whether the rest matches,
946+ * and then act accordingly. In practice we make some effort to avoid
947+ * recursion, in particular by going through "ordinary" nodes (that don't
948+ * need to know whether the rest of the match failed) by a loop instead of
949+ * by recursion.
950+ */
951+static int /* 0 failure, 1 success */
952+regmatch(struct match_globals *g, char *prog)
953+{
954+ register char *scan = prog; /* Current node. */
955+ char *next; /* Next node. */
956+
957+#ifdef DEBUG
958+ if (scan != NULL && regnarrate)
959+ fprintf(stderr, "%s(\n", regprop(scan));
960+#endif
961+ while (scan != NULL) {
962+#ifdef DEBUG
963+ if (regnarrate)
964+ fprintf(stderr, "%s...\n", regprop(scan));
965+#endif
966+ next = regnext(g, scan);
967+
968+ switch (OP(scan)) {
969+ case BOL:
970+ if (g->reginput != g->regbol)
971+ return(0);
972+ break;
973+ case EOL:
974+ if (*g->reginput != '\0')
975+ return(0);
976+ break;
977+ case ANY:
978+ if (*g->reginput == '\0')
979+ return(0);
980+ g->reginput++;
981+ break;
982+ case EXACTLY: {
983+ register int len;
984+ register char *opnd;
985+
986+ opnd = OPERAND(scan);
987+ /* Inline the first character, for speed. */
988+ if (*opnd != *g->reginput)
989+ return(0);
990+ len = strlen(opnd);
991+ if (len > 1 && strncmp(opnd, g->reginput, len) != 0)
992+ return(0);
993+ g->reginput += len;
994+ }
995+ break;
996+ case ANYOF:
997+ if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) == NULL)
998+ return(0);
999+ g->reginput++;
1000+ break;
1001+ case ANYBUT:
1002+ if (*g->reginput == '\0' || strchr(OPERAND(scan), *g->reginput) != NULL)
1003+ return(0);
1004+ g->reginput++;
1005+ break;
1006+ case NOTHING:
1007+ case BACK:
1008+ break;
1009+ case OPEN+1:
1010+ case OPEN+2:
1011+ case OPEN+3:
1012+ case OPEN+4:
1013+ case OPEN+5:
1014+ case OPEN+6:
1015+ case OPEN+7:
1016+ case OPEN+8:
1017+ case OPEN+9: {
1018+ register int no;
1019+ register char *save;
1020+
1021+ no = OP(scan) - OPEN;
1022+ save = g->reginput;
1023+
1024+ if (regmatch(g, next)) {
1025+ /*
1026+ * Don't set startp if some later
1027+ * invocation of the same parentheses
1028+ * already has.
1029+ */
1030+ if (g->regstartp[no] == NULL)
1031+ g->regstartp[no] = save;
1032+ return(1);
1033+ } else
1034+ return(0);
1035+ }
1036+ break;
1037+ case CLOSE+1:
1038+ case CLOSE+2:
1039+ case CLOSE+3:
1040+ case CLOSE+4:
1041+ case CLOSE+5:
1042+ case CLOSE+6:
1043+ case CLOSE+7:
1044+ case CLOSE+8:
1045+ case CLOSE+9:
1046+ {
1047+ register int no;
1048+ register char *save;
1049+
1050+ no = OP(scan) - CLOSE;
1051+ save = g->reginput;
1052+
1053+ if (regmatch(g, next)) {
1054+ /*
1055+ * Don't set endp if some later
1056+ * invocation of the same parentheses
1057+ * already has.
1058+ */
1059+ if (g->regendp[no] == NULL)
1060+ g->regendp[no] = save;
1061+ return(1);
1062+ } else
1063+ return(0);
1064+ }
1065+ break;
1066+ case BRANCH: {
1067+ register char *save;
1068+
1069+ if (OP(next) != BRANCH) /* No choice. */
1070+ next = OPERAND(scan); /* Avoid recursion. */
1071+ else {
1072+ do {
1073+ save = g->reginput;
1074+ if (regmatch(g, OPERAND(scan)))
1075+ return(1);
1076+ g->reginput = save;
1077+ scan = regnext(g, scan);
1078+ } while (scan != NULL && OP(scan) == BRANCH);
1079+ return(0);
1080+ /* NOTREACHED */
1081+ }
1082+ }
1083+ break;
1084+ case STAR:
1085+ case PLUS: {
1086+ register char nextch;
1087+ register int no;
1088+ register char *save;
1089+ register int min;
1090+
1091+ /*
1092+ * Lookahead to avoid useless match attempts
1093+ * when we know what character comes next.
1094+ */
1095+ nextch = '\0';
1096+ if (OP(next) == EXACTLY)
1097+ nextch = *OPERAND(next);
1098+ min = (OP(scan) == STAR) ? 0 : 1;
1099+ save = g->reginput;
1100+ no = regrepeat(g, OPERAND(scan));
1101+ while (no >= min) {
1102+ /* If it could work, try it. */
1103+ if (nextch == '\0' || *g->reginput == nextch)
1104+ if (regmatch(g, next))
1105+ return(1);
1106+ /* Couldn't or didn't -- back up. */
1107+ no--;
1108+ g->reginput = save + no;
1109+ }
1110+ return(0);
1111+ }
1112+ break;
1113+ case END:
1114+ return(1); /* Success! */
1115+ break;
1116+ default:
1117+ printk("<3>Regexp: memory corruption\n");
1118+ return(0);
1119+ break;
1120+ }
1121+
1122+ scan = next;
1123+ }
1124+
1125+ /*
1126+ * We get here only if there's trouble -- normally "case END" is
1127+ * the terminating point.
1128+ */
1129+ printk("<3>Regexp: corrupted pointers\n");
1130+ return(0);
1131+}
1132+
1133+/*
1134+ - regrepeat - repeatedly match something simple, report how many
1135+ */
1136+static int
1137+regrepeat(struct match_globals *g, char *p)
1138+{
1139+ register int count = 0;
1140+ register char *scan;
1141+ register char *opnd;
1142+
1143+ scan = g->reginput;
1144+ opnd = OPERAND(p);
1145+ switch (OP(p)) {
1146+ case ANY:
1147+ count = strlen(scan);
1148+ scan += count;
1149+ break;
1150+ case EXACTLY:
1151+ while (*opnd == *scan) {
1152+ count++;
1153+ scan++;
1154+ }
1155+ break;
1156+ case ANYOF:
1157+ while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
1158+ count++;
1159+ scan++;
1160+ }
1161+ break;
1162+ case ANYBUT:
1163+ while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
1164+ count++;
1165+ scan++;
1166+ }
1167+ break;
1168+ default: /* Oh dear. Called inappropriately. */
1169+ printk("<3>Regexp: internal foulup\n");
1170+ count = 0; /* Best compromise. */
1171+ break;
1172+ }
1173+ g->reginput = scan;
1174+
1175+ return(count);
1176+}
1177+
1178+/*
1179+ - regnext - dig the "next" pointer out of a node
1180+ */
1181+static char*
1182+regnext(struct match_globals *g, char *p)
1183+{
1184+ register int offset;
1185+
1186+ if (p == &g->regdummy)
1187+ return(NULL);
1188+
1189+ offset = NEXT(p);
1190+ if (offset == 0)
1191+ return(NULL);
1192+
1193+ if (OP(p) == BACK)
1194+ return(p-offset);
1195+ else
1196+ return(p+offset);
1197+}
1198+
1199+#ifdef DEBUG
1200+
1201+STATIC char *regprop();
1202+
1203+/*
1204+ - regdump - dump a regexp onto stdout in vaguely comprehensible form
1205+ */
1206+void
1207+regdump(regexp *r)
1208+{
1209+ register char *s;
1210+ register char op = EXACTLY; /* Arbitrary non-END op. */
1211+ register char *next;
1212+ /* extern char *strchr(); */
1213+
1214+
1215+ s = r->program + 1;
1216+ while (op != END) { /* While that wasn't END last time... */
1217+ op = OP(s);
1218+ printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */
1219+ next = regnext(s);
1220+ if (next == NULL) /* Next ptr. */
1221+ printf("(0)");
1222+ else
1223+ printf("(%d)", (s-r->program)+(next-s));
1224+ s += 3;
1225+ if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
1226+ /* Literal string, where present. */
1227+ while (*s != '\0') {
1228+ putchar(*s);
1229+ s++;
1230+ }
1231+ s++;
1232+ }
1233+ putchar('\n');
1234+ }
1235+
1236+ /* Header fields of interest. */
1237+ if (r->regstart != '\0')
1238+ printf("start `%c' ", r->regstart);
1239+ if (r->reganch)
1240+ printf("anchored ");
1241+ if (r->regmust != NULL)
1242+ printf("must have \"%s\"", r->regmust);
1243+ printf("\n");
1244+}
1245+
1246+/*
1247+ - regprop - printable representation of opcode
1248+ */
1249+static char *
1250+regprop(char *op)
1251+{
1252+#define BUFLEN 50
1253+ register char *p;
1254+ static char buf[BUFLEN];
1255+
1256+ strcpy(buf, ":");
1257+
1258+ switch (OP(op)) {
1259+ case BOL:
1260+ p = "BOL";
1261+ break;
1262+ case EOL:
1263+ p = "EOL";
1264+ break;
1265+ case ANY:
1266+ p = "ANY";
1267+ break;
1268+ case ANYOF:
1269+ p = "ANYOF";
1270+ break;
1271+ case ANYBUT:
1272+ p = "ANYBUT";
1273+ break;
1274+ case BRANCH:
1275+ p = "BRANCH";
1276+ break;
1277+ case EXACTLY:
1278+ p = "EXACTLY";
1279+ break;
1280+ case NOTHING:
1281+ p = "NOTHING";
1282+ break;
1283+ case BACK:
1284+ p = "BACK";
1285+ break;
1286+ case END:
1287+ p = "END";
1288+ break;
1289+ case OPEN+1:
1290+ case OPEN+2:
1291+ case OPEN+3:
1292+ case OPEN+4:
1293+ case OPEN+5:
1294+ case OPEN+6:
1295+ case OPEN+7:
1296+ case OPEN+8:
1297+ case OPEN+9:
1298+ snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "OPEN%d", OP(op)-OPEN);
1299+ p = NULL;
1300+ break;
1301+ case CLOSE+1:
1302+ case CLOSE+2:
1303+ case CLOSE+3:
1304+ case CLOSE+4:
1305+ case CLOSE+5:
1306+ case CLOSE+6:
1307+ case CLOSE+7:
1308+ case CLOSE+8:
1309+ case CLOSE+9:
1310+ snprintf(buf+strlen(buf),BUFLEN-strlen(buf), "CLOSE%d", OP(op)-CLOSE);
1311+ p = NULL;
1312+ break;
1313+ case STAR:
1314+ p = "STAR";
1315+ break;
1316+ case PLUS:
1317+ p = "PLUS";
1318+ break;
1319+ default:
1320+ printk("<3>Regexp: corrupted opcode\n");
1321+ break;
1322+ }
1323+ if (p != NULL)
1324+ strncat(buf, p, BUFLEN-strlen(buf));
1325+ return(buf);
1326+}
1327+#endif
1328+
1329+
f25f1b55
PM
1330diff -Naur linux-5.15.46.orig/net/netfilter/regexp/regexp.h linux-5.15.46/net/netfilter/regexp/regexp.h
1331--- linux-5.15.46.orig/net/netfilter/regexp/regexp.h 1970-01-01 00:00:00.000000000 +0000
1332+++ linux-5.15.46/net/netfilter/regexp/regexp.h 2022-06-11 14:53:07.985494758 +0000
9d3616dc
AF
1333@@ -0,0 +1,41 @@
1334+/*
1335+ * Definitions etc. for regexp(3) routines.
1336+ *
1337+ * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
1338+ * not the System V one.
1339+ */
1340+
1341+#ifndef REGEXP_H
1342+#define REGEXP_H
1343+
1344+
1345+/*
1346+http://www.opensource.apple.com/darwinsource/10.3/expect-1/expect/expect.h ,
1347+which contains a version of this library, says:
1348+
1349+ *
1350+ * NSUBEXP must be at least 10, and no greater than 117 or the parser
1351+ * will not work properly.
1352+ *
1353+
1354+However, it looks rather like this library is limited to 10. If you think
1355+otherwise, let us know.
1356+*/
1357+
1358+#define NSUBEXP 10
1359+typedef struct regexp {
1360+ char *startp[NSUBEXP];
1361+ char *endp[NSUBEXP];
1362+ char regstart; /* Internal use only. */
1363+ char reganch; /* Internal use only. */
1364+ char *regmust; /* Internal use only. */
1365+ int regmlen; /* Internal use only. */
1366+ char program[1]; /* Unwarranted chumminess with compiler. */
1367+} regexp;
1368+
1369+regexp * regcomp(char *exp, int *patternsize);
1370+int regexec(regexp *prog, char *string);
1371+void regsub(regexp *prog, char *source, char *dest);
1372+void regerror(char *s);
1373+
1374+#endif
f25f1b55
PM
1375diff -Naur linux-5.15.46.orig/net/netfilter/regexp/regmagic.h linux-5.15.46/net/netfilter/regexp/regmagic.h
1376--- linux-5.15.46.orig/net/netfilter/regexp/regmagic.h 1970-01-01 00:00:00.000000000 +0000
1377+++ linux-5.15.46/net/netfilter/regexp/regmagic.h 2022-06-11 14:53:07.985494758 +0000
9d3616dc
AF
1378@@ -0,0 +1,5 @@
1379+/*
1380+ * The first byte of the regexp internal "program" is actually this magic
1381+ * number; the start node begins in the second byte.
1382+ */
1383+#define MAGIC 0234
f25f1b55
PM
1384diff -Naur linux-5.15.46.orig/net/netfilter/regexp/regsub.c linux-5.15.46/net/netfilter/regexp/regsub.c
1385--- linux-5.15.46.orig/net/netfilter/regexp/regsub.c 1970-01-01 00:00:00.000000000 +0000
1386+++ linux-5.15.46/net/netfilter/regexp/regsub.c 2022-06-11 14:53:07.985494758 +0000
9d3616dc
AF
1387@@ -0,0 +1,95 @@
1388+/*
1389+ * regsub
1390+ * @(#)regsub.c 1.3 of 2 April 86
1391+ *
1392+ * Copyright (c) 1986 by University of Toronto.
1393+ * Written by Henry Spencer. Not derived from licensed software.
1394+ *
1395+ * Permission is granted to anyone to use this software for any
1396+ * purpose on any computer system, and to redistribute it freely,
1397+ * subject to the following restrictions:
1398+ *
1399+ * 1. The author is not responsible for the consequences of use of
1400+ * this software, no matter how awful, even if they arise
1401+ * from defects in it.
1402+ *
1403+ * 2. The origin of this software must not be misrepresented, either
1404+ * by explicit claim or by omission.
1405+ *
1406+ * 3. Altered versions must be plainly marked as such, and must not
1407+ * be misrepresented as being the original software.
1408+ *
1409+ *
1410+ * This code was modified by Ethan Sommer to work within the kernel
1411+ * (it now uses kmalloc etc..)
1412+ *
1413+ */
1414+#include "regexp.h"
1415+#include "regmagic.h"
1416+#include <linux/string.h>
1417+
1418+
1419+#ifndef CHARBITS
1420+#define UCHARAT(p) ((int)*(unsigned char *)(p))
1421+#else
1422+#define UCHARAT(p) ((int)*(p)&CHARBITS)
1423+#endif
1424+
1425+#if 0
1426+//void regerror(char * s)
1427+//{
1428+// printk("regexp(3): %s", s);
1429+// /* NOTREACHED */
1430+//}
1431+#endif
1432+
1433+/*
1434+ - regsub - perform substitutions after a regexp match
1435+ */
1436+void
1437+regsub(regexp * prog, char * source, char * dest)
1438+{
1439+ register char *src;
1440+ register char *dst;
1441+ register char c;
1442+ register int no;
1443+ register int len;
1444+
1445+ /* Not necessary and gcc doesn't like it -MLS */
1446+ /*extern char *strncpy();*/
1447+
1448+ if (prog == NULL || source == NULL || dest == NULL) {
1449+ regerror("NULL parm to regsub");
1450+ return;
1451+ }
1452+ if (UCHARAT(prog->program) != MAGIC) {
1453+ regerror("damaged regexp fed to regsub");
1454+ return;
1455+ }
1456+
1457+ src = source;
1458+ dst = dest;
1459+ while ((c = *src++) != '\0') {
1460+ if (c == '&')
1461+ no = 0;
1462+ else if (c == '\\' && '0' <= *src && *src <= '9')
1463+ no = *src++ - '0';
1464+ else
1465+ no = -1;
1466+
1467+ if (no < 0) { /* Ordinary character. */
1468+ if (c == '\\' && (*src == '\\' || *src == '&'))
1469+ c = *src++;
1470+ *dst++ = c;
1471+ } else if (prog->startp[no] != NULL && prog->endp[no] != NULL) {
1472+ len = prog->endp[no] - prog->startp[no];
1473+ (void) strncpy(dst, prog->startp[no], len);
1474+ dst += len;
1475+ if (len != 0 && *(dst-1) == '\0') { /* strncpy hit NUL. */
1476+ regerror("damaged match string");
1477+ return;
1478+ }
1479+ }
1480+ }
1481+ *dst++ = '\0';
1482+}
f25f1b55
PM
1483diff -Naur linux-5.15.46.orig/net/netfilter/xt_layer7.c linux-5.15.46/net/netfilter/xt_layer7.c
1484--- linux-5.15.46.orig/net/netfilter/xt_layer7.c 1970-01-01 00:00:00.000000000 +0000
1485+++ linux-5.15.46/net/netfilter/xt_layer7.c 2022-06-11 14:53:07.985494758 +0000
c062c770 1486@@ -0,0 +1,666 @@
9d3616dc
AF
1487+/*
1488+ Kernel module to match application layer (OSI layer 7) data in connections.
1489+
1490+ http://l7-filter.sf.net
1491+
1492+ (C) 2003-2009 Matthew Strait and Ethan Sommer.
1493+
1494+ This program is free software; you can redistribute it and/or
1495+ modify it under the terms of the GNU General Public License
1496+ as published by the Free Software Foundation; either version
1497+ 2 of the License, or (at your option) any later version.
1498+ http://www.gnu.org/licenses/gpl.txt
1499+
1500+ Based on ipt_string.c (C) 2000 Emmanuel Roger <winfield@freegates.be>,
1501+ xt_helper.c (C) 2002 Harald Welte and cls_layer7.c (C) 2003 Matthew Strait,
1502+ Ethan Sommer, Justin Levandoski.
1503+*/
1504+
1505+#include <linux/spinlock.h>
1506+#include <linux/version.h>
1507+#include <net/ip.h>
1508+#include <net/tcp.h>
1509+#include <linux/module.h>
9d3616dc
AF
1510+#include <linux/skbuff.h>
1511+#include <linux/netfilter.h>
1512+#include <net/netfilter/nf_conntrack.h>
1513+#include <net/netfilter/nf_conntrack_core.h>
91648bd1 1514+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
9d3616dc
AF
1515+#include <net/netfilter/nf_conntrack_extend.h>
1516+#include <net/netfilter/nf_conntrack_acct.h>
91648bd1 1517+#endif
9d3616dc
AF
1518+#include <linux/netfilter/x_tables.h>
1519+#include <linux/netfilter/xt_layer7.h>
1520+#include <linux/ctype.h>
1521+#include <linux/proc_fs.h>
1522+
1523+#include "regexp/regexp.c"
1524+
1525+MODULE_LICENSE("GPL");
ddc7b38c 1526+MODULE_AUTHOR("Matthew Strait <quadong@users.sf.net>, Ethan Sommer <sommere@users.sf.net>, Arne Fitzenreiter <arne_f@ipfire.org>");
9d3616dc
AF
1527+MODULE_DESCRIPTION("iptables application layer match module");
1528+MODULE_ALIAS("ipt_layer7");
ddc7b38c 1529+MODULE_VERSION("2.30");
9d3616dc
AF
1530+
1531+static int maxdatalen = 2048; // this is the default
1532+module_param(maxdatalen, int, 0444);
1533+MODULE_PARM_DESC(maxdatalen, "maximum bytes of data looked at by l7-filter");
1534+#ifdef CONFIG_NETFILTER_XT_MATCH_LAYER7_DEBUG
1535+ #define DPRINTK(format,args...) printk(format,##args)
1536+#else
1537+ #define DPRINTK(format,args...)
1538+#endif
1539+
1540+/* Number of packets whose data we look at.
1541+This can be modified through /proc/net/layer7_numpackets */
1542+static int num_packets = 10;
1543+
1544+static struct pattern_cache {
1545+ char * regex_string;
1546+ regexp * pattern;
1547+ struct pattern_cache * next;
1548+} * first_pattern_cache = NULL;
1549+
ddc7b38c
AF
1550+static struct proto_cache {
1551+ char * proto_string;
1552+ struct proto_cache * next;
1553+} * first_proto_cache = NULL;
1554+
9d3616dc
AF
1555+DEFINE_SPINLOCK(l7_lock);
1556+
9d3616dc
AF
1557+#ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
1558+/* Converts an unfriendly string into a friendly one by
1559+replacing unprintables with periods and all whitespace with " ". */
1560+static char * friendly_print(unsigned char * s)
1561+{
1562+ char * f = kmalloc(strlen(s) + 1, GFP_ATOMIC);
1563+ int i;
1564+
1565+ if(!f) {
1566+ if (net_ratelimit())
1567+ printk(KERN_ERR "layer7: out of memory in "
1568+ "friendly_print, bailing.\n");
1569+ return NULL;
1570+ }
1571+
1572+ for(i = 0; i < strlen(s); i++){
1573+ if(isprint(s[i]) && s[i] < 128) f[i] = s[i];
1574+ else if(isspace(s[i])) f[i] = ' ';
1575+ else f[i] = '.';
1576+ }
1577+ f[i] = '\0';
1578+ return f;
1579+}
1580+
1581+static char dec2hex(int i)
1582+{
1583+ switch (i) {
1584+ case 0 ... 9:
1585+ return (i + '0');
1586+ break;
1587+ case 10 ... 15:
1588+ return (i - 10 + 'a');
1589+ break;
1590+ default:
1591+ if (net_ratelimit())
1592+ printk("layer7: Problem in dec2hex\n");
1593+ return '\0';
1594+ }
1595+}
1596+
1597+static char * hex_print(unsigned char * s)
1598+{
1599+ char * g = kmalloc(strlen(s)*3 + 1, GFP_ATOMIC);
1600+ int i;
1601+
1602+ if(!g) {
1603+ if (net_ratelimit())
1604+ printk(KERN_ERR "layer7: out of memory in hex_print, "
1605+ "bailing.\n");
1606+ return NULL;
1607+ }
1608+
1609+ for(i = 0; i < strlen(s); i++) {
1610+ g[i*3 ] = dec2hex(s[i]/16);
1611+ g[i*3 + 1] = dec2hex(s[i]%16);
1612+ g[i*3 + 2] = ' ';
1613+ }
1614+ g[i*3] = '\0';
1615+
1616+ return g;
1617+}
1618+#endif // DEBUG
1619+
1620+/* Use instead of regcomp. As we expect to be seeing the same regexps over and
1621+over again, it make sense to cache the results. */
1622+static regexp * compile_and_cache(const char * regex_string,
1623+ const char * protocol)
1624+{
1625+ struct pattern_cache * node = first_pattern_cache;
1626+ struct pattern_cache * last_pattern_cache = first_pattern_cache;
1627+ struct pattern_cache * tmp;
1628+ unsigned int len;
1629+
1630+ while (node != NULL) {
1631+ if (!strcmp(node->regex_string, regex_string))
1632+ return node->pattern;
1633+
1634+ last_pattern_cache = node;/* points at the last non-NULL node */
1635+ node = node->next;
1636+ }
1637+
1638+ /* If we reach the end of the list, then we have not yet cached
1639+ the pattern for this regex. Let's do that now.
1640+ Be paranoid about running out of memory to avoid list corruption. */
1641+ tmp = kmalloc(sizeof(struct pattern_cache), GFP_ATOMIC);
1642+
1643+ if(!tmp) {
1644+ if (net_ratelimit())
1645+ printk(KERN_ERR "layer7: out of memory in "
1646+ "compile_and_cache, bailing.\n");
1647+ return NULL;
1648+ }
1649+
1650+ tmp->regex_string = kmalloc(strlen(regex_string) + 1, GFP_ATOMIC);
1651+ tmp->pattern = kmalloc(sizeof(struct regexp), GFP_ATOMIC);
1652+ tmp->next = NULL;
1653+
1654+ if(!tmp->regex_string || !tmp->pattern) {
1655+ if (net_ratelimit())
1656+ printk(KERN_ERR "layer7: out of memory in "
1657+ "compile_and_cache, bailing.\n");
1658+ kfree(tmp->regex_string);
1659+ kfree(tmp->pattern);
1660+ kfree(tmp);
1661+ return NULL;
1662+ }
1663+
1664+ /* Ok. The new node is all ready now. */
1665+ node = tmp;
1666+
1667+ if(first_pattern_cache == NULL) /* list is empty */
1668+ first_pattern_cache = node; /* make node the beginning */
1669+ else
1670+ last_pattern_cache->next = node; /* attach node to the end */
1671+
1672+ /* copy the string and compile the regex */
1673+ len = strlen(regex_string);
1674+ DPRINTK("About to compile this: \"%s\"\n", regex_string);
1675+ node->pattern = regcomp((char *)regex_string, &len);
1676+ if ( !node->pattern ) {
1677+ if (net_ratelimit())
1678+ printk(KERN_ERR "layer7: Error compiling regexp "
1679+ "\"%s\" (%s)\n",
1680+ regex_string, protocol);
1681+ /* pattern is now cached as NULL, so we won't try again. */
1682+ }
1683+
1684+ strcpy(node->regex_string, regex_string);
1685+ return node->pattern;
1686+}
1687+
ddc7b38c
AF
1688+static char * get_protostr_ptr(const char * protocol)
1689+{
1690+ struct proto_cache * node = first_proto_cache;
1691+ struct proto_cache * last_proto_cache = first_proto_cache;
1692+ struct proto_cache * tmp;
1693+
1694+ while (node != NULL) {
1695+ if (!strcmp(node->proto_string, protocol))
1696+ return node->proto_string;
1697+
1698+ last_proto_cache = node;/* points at the last non-NULL node */
1699+ node = node->next;
1700+ }
1701+
1702+ /* If we reach the end of the list, then we have not yet cached protocol
1703+ Be paranoid about running out of memory to avoid list corruption. */
1704+ tmp = kmalloc(sizeof(struct proto_cache), GFP_ATOMIC);
1705+
1706+ if(!tmp) {
1707+ if (net_ratelimit())
1708+ printk(KERN_ERR "layer7: out of memory in "
1709+ "proto_cache add, bailing.\n");
1710+ return NULL;
1711+ }
1712+
1713+ tmp->proto_string = kmalloc(strlen(protocol) + 1 , GFP_ATOMIC);
1714+ tmp->next = NULL;
1715+
1716+ if(!tmp->proto_string) {
1717+ if (net_ratelimit())
1718+ printk(KERN_ERR "layer7: out of memory in "
1719+ "proto_cache add, bailing.\n");
1720+ kfree(tmp->proto_string);
1721+ kfree(tmp);
1722+ return NULL;
1723+ }
1724+
1725+ /* Ok. The new node is all ready now. */
1726+ node = tmp;
1727+
1728+ if(first_proto_cache == NULL) /* list is empty */
1729+ first_proto_cache = node; /* make node the beginning */
1730+ else
1731+ last_proto_cache->next = node; /* attach node to the end */
1732+
1733+ strcpy(node->proto_string, protocol);
1734+ return node->proto_string;
1735+}
1736+
9d3616dc
AF
1737+static int can_handle(const struct sk_buff *skb)
1738+{
91648bd1 1739+ if(!ip_hdr(skb)) /* not IP */
9d3616dc 1740+ return 0;
91648bd1
AF
1741+ if(ip_hdr(skb)->protocol != IPPROTO_TCP &&
1742+ ip_hdr(skb)->protocol != IPPROTO_UDP &&
1743+ ip_hdr(skb)->protocol != IPPROTO_ICMP)
9d3616dc 1744+ return 0;
91648bd1 1745+ return 1;
9d3616dc
AF
1746+}
1747+
91648bd1 1748+/* Returns offset the into the skb->data that the application data starts */
9d3616dc
AF
1749+static int app_data_offset(const struct sk_buff *skb)
1750+{
91648bd1
AF
1751+ /* In case we are ported somewhere (ebtables?) where ip_hdr(skb)
1752+ isn't set, this can be gotten from 4*(skb->data[0] & 0x0f) as well. */
1753+ int ip_hl = 4*ip_hdr(skb)->ihl;
1754+
1755+ if( ip_hdr(skb)->protocol == IPPROTO_TCP ) {
1756+ /* 12 == offset into TCP header for the header length field.
1757+ Can't get this with skb->h.th->doff because the tcphdr
1758+ struct doesn't get set when routing (this is confirmed to be
1759+ true in Netfilter as well as QoS.) */
1760+ int tcp_hl = 4*(skb->data[ip_hl + 12] >> 4);
1761+
1762+ return ip_hl + tcp_hl;
1763+ } else if( ip_hdr(skb)->protocol == IPPROTO_UDP ) {
1764+ return ip_hl + 8; /* UDP header is always 8 bytes */
1765+ } else if( ip_hdr(skb)->protocol == IPPROTO_ICMP ) {
1766+ return ip_hl + 8; /* ICMP header is 8 bytes */
1767+ } else {
1768+ if (net_ratelimit())
1769+ printk(KERN_ERR "layer7: tried to handle unknown "
1770+ "protocol!\n");
1771+ return ip_hl + 8; /* something reasonable */
9d3616dc 1772+ }
9d3616dc
AF
1773+}
1774+
1775+/* handles whether there's a match when we aren't appending data anymore */
1776+static int match_no_append(struct nf_conn * conntrack,
1777+ struct nf_conn * master_conntrack,
1778+ enum ip_conntrack_info ctinfo,
1779+ enum ip_conntrack_info master_ctinfo,
1780+ const struct xt_layer7_info * info)
1781+{
1782+ /* If we're in here, throw the app data away */
1783+ if(master_conntrack->layer7.app_data != NULL) {
1784+
1785+ #ifdef CONFIG_IP_NF_MATCH_LAYER7_DEBUG
1786+ if(!master_conntrack->layer7.app_proto) {
1787+ char * f =
1788+ friendly_print(master_conntrack->layer7.app_data);
1789+ char * g =
1790+ hex_print(master_conntrack->layer7.app_data);
1791+ DPRINTK("\nl7-filter gave up after %d bytes "
1792+ "(%d packets):\n%s\n",
9b677b44 1793+ strlen(f), master_conntrack->layer7.packets, f);
9d3616dc
AF
1794+ kfree(f);
1795+ DPRINTK("In hex: %s\n", g);
1796+ kfree(g);
1797+ }
1798+ #endif
1799+
1800+ kfree(master_conntrack->layer7.app_data);
1801+ master_conntrack->layer7.app_data = NULL; /* don't free again */
1802+ }
1803+
1804+ if(master_conntrack->layer7.app_proto){
1805+ /* Here child connections set their .app_proto (for /proc) */
1806+ if(!conntrack->layer7.app_proto) {
ddc7b38c 1807+ conntrack->layer7.app_proto = master_conntrack->layer7.app_proto;
9d3616dc
AF
1808+ }
1809+
1810+ return (!strcmp(master_conntrack->layer7.app_proto,
1811+ info->protocol));
1812+ }
1813+ else {
1814+ /* If not classified, set to "unknown" to distinguish from
1815+ connections that are still being tested. */
ddc7b38c 1816+ master_conntrack->layer7.app_proto = get_protostr_ptr("unknown");
9d3616dc
AF
1817+ return 0;
1818+ }
1819+}
1820+
1821+/* add the new app data to the conntrack. Return number of bytes added. */
91648bd1
AF
1822+static int add_data(struct nf_conn * master_conntrack,
1823+ char * app_data, int appdatalen)
9d3616dc
AF
1824+{
1825+ int length = 0, i;
91648bd1
AF
1826+ int oldlength = master_conntrack->layer7.app_data_len;
1827+
1828+ /* This is a fix for a race condition by Deti Fliegl. However, I'm not
1829+ clear on whether the race condition exists or whether this really
1830+ fixes it. I might just be being dense... Anyway, if it's not really
1831+ a fix, all it does is waste a very small amount of time. */
1832+ if(!master_conntrack->layer7.app_data) return 0;
9d3616dc
AF
1833+
1834+ /* Strip nulls. Make everything lower case (our regex lib doesn't
1835+ do case insensitivity). Add it to the end of the current data. */
91648bd1
AF
1836+ for(i = 0; i < maxdatalen-oldlength-1 &&
1837+ i < appdatalen; i++) {
9d3616dc
AF
1838+ if(app_data[i] != '\0') {
1839+ /* the kernel version of tolower mungs 'upper ascii' */
91648bd1 1840+ master_conntrack->layer7.app_data[length+oldlength] =
9d3616dc
AF
1841+ isascii(app_data[i])?
1842+ tolower(app_data[i]) : app_data[i];
1843+ length++;
1844+ }
1845+ }
9d3616dc 1846+
91648bd1
AF
1847+ master_conntrack->layer7.app_data[length+oldlength] = '\0';
1848+ master_conntrack->layer7.app_data_len = length + oldlength;
9d3616dc
AF
1849+
1850+ return length;
1851+}
1852+
1853+/* taken from drivers/video/modedb.c */
1854+static int my_atoi(const char *s)
1855+{
1856+ int val = 0;
1857+
1858+ for (;; s++) {
1859+ switch (*s) {
1860+ case '0'...'9':
1861+ val = 10*val+(*s-'0');
1862+ break;
1863+ default:
1864+ return val;
1865+ }
1866+ }
1867+}
1868+
1869+static int layer7_numpackets_proc_show(struct seq_file *s, void *p) {
1870+ seq_printf(s, "%d\n", num_packets);
1871+
1872+ return 0;
1873+}
1874+
1875+static int layer7_numpackets_proc_open(struct inode *inode, struct file *file) {
1876+ return single_open(file, layer7_numpackets_proc_show, NULL);
1877+}
1878+
1879+/* Read in num_packets from userland */
1880+static ssize_t layer7_numpackets_write_proc(struct file* file, const char __user *buffer,
1881+ size_t count, loff_t *data) {
1882+ char value[1024];
1883+ int new_num_packets;
1884+
1885+ if (copy_from_user(&value, buffer, sizeof(value)))
1886+ return -EFAULT;
1887+
1888+ new_num_packets = my_atoi(value);
1889+
1890+ if ((new_num_packets < 1) || (new_num_packets > 99)) {
1891+ printk(KERN_WARNING "layer7: numpackets must be between 1 and 99\n");
1892+ return -EFAULT;
1893+ }
1894+
1895+ num_packets = new_num_packets;
1896+
1897+ return count;
1898+}
1899+
91648bd1
AF
1900+static bool
1901+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
1902+match(const struct sk_buff *skbin, struct xt_action_param *par)
1903+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
1904+match(const struct sk_buff *skbin, const struct xt_match_param *par)
1905+#else
1906+match(const struct sk_buff *skbin,
1907+ const struct net_device *in,
1908+ const struct net_device *out,
1909+ const struct xt_match *match,
1910+ const void *matchinfo,
1911+ int offset,
1912+ unsigned int protoff,
1913+ bool *hotdrop)
1914+#endif
9d3616dc
AF
1915+{
1916+ /* sidestep const without getting a compiler warning... */
91648bd1 1917+ struct sk_buff * skb = (struct sk_buff *)skbin;
9d3616dc 1918+
91648bd1
AF
1919+ const struct xt_layer7_info * info =
1920+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
1921+ par->matchinfo;
1922+ #else
1923+ matchinfo;
1924+ #endif
9d3616dc
AF
1925+
1926+ enum ip_conntrack_info master_ctinfo, ctinfo;
1927+ struct nf_conn *master_conntrack, *conntrack;
91648bd1
AF
1928+ unsigned char * app_data;
1929+ unsigned int pattern_result, appdatalen;
9d3616dc
AF
1930+ regexp * comppattern;
1931+
1932+ /* Be paranoid/incompetent - lock the entire match function. */
1933+ spin_lock_bh(&l7_lock);
1934+
91648bd1 1935+ if(!can_handle(skb)){
9d3616dc
AF
1936+ DPRINTK("layer7: This is some protocol I can't handle.\n");
1937+ spin_unlock_bh(&l7_lock);
1938+ return info->invert;
1939+ }
1940+
1941+ /* Treat parent & all its children together as one connection, except
1942+ for the purpose of setting conntrack->layer7.app_proto in the actual
1943+ connection. This makes /proc/net/ip_conntrack more satisfying. */
91648bd1
AF
1944+ if(!(conntrack = nf_ct_get(skb, &ctinfo)) ||
1945+ !(master_conntrack=nf_ct_get(skb,&master_ctinfo))){
9d3616dc
AF
1946+ DPRINTK("layer7: couldn't get conntrack.\n");
1947+ spin_unlock_bh(&l7_lock);
1948+ return info->invert;
1949+ }
1950+
1951+ /* Try to get a master conntrack (and its master etc) for FTP, etc. */
1952+ while (master_ct(master_conntrack) != NULL)
1953+ master_conntrack = master_ct(master_conntrack);
1954+
9b677b44
AF
1955+ /* free unused conntrack data if different master conntrack exists */
1956+ if (master_conntrack != conntrack) {
1957+ if (conntrack->layer7.app_data) {
1958+ DPRINTK("layer7: free unused conntrack memory.\n");
1959+ kfree(conntrack->layer7.app_data);
1960+ conntrack->layer7.app_data = NULL; /* don't free again */
1961+ }
1962+ }
1963+
9d3616dc 1964+ /* if we've classified it or seen too many packets */
9b677b44 1965+ if( master_conntrack->layer7.packets >= num_packets ||
91648bd1 1966+ master_conntrack->layer7.app_proto) {
9d3616dc
AF
1967+
1968+ pattern_result = match_no_append(conntrack, master_conntrack,
1969+ ctinfo, master_ctinfo, info);
1970+
9b677b44 1971+ skb->layer7_flags[0] = 1; /* marking it seen here's probably irrelevant */
9d3616dc
AF
1972+
1973+ spin_unlock_bh(&l7_lock);
1974+ return (pattern_result ^ info->invert);
1975+ }
1976+
91648bd1
AF
1977+ if(skb_is_nonlinear(skb)){
1978+ if(skb_linearize(skb) != 0){
9d3616dc 1979+ if (net_ratelimit())
91648bd1
AF
1980+ printk(KERN_ERR "layer7: failed to linearize "
1981+ "packet, bailing.\n");
1982+ spin_unlock_bh(&l7_lock);
9d3616dc
AF
1983+ return info->invert;
1984+ }
91648bd1 1985+ }
9d3616dc 1986+
91648bd1
AF
1987+ /* now that the skb is linearized, it's safe to set these. */
1988+ app_data = skb->data + app_data_offset(skb);
1989+ appdatalen = skb_tail_pointer(skb) - app_data;
9d3616dc 1990+
91648bd1
AF
1991+ /* the return value gets checked later, when we're ready to use it */
1992+ comppattern = compile_and_cache(info->pattern, info->protocol);
9d3616dc 1993+
a4f83ed8
AF
1994+ /* allocate space for app data if not done */
1995+ if(master_conntrack->layer7.packets < num_packets &&
1996+ !master_conntrack->layer7.app_data){
9d3616dc
AF
1997+ master_conntrack->layer7.app_data =
1998+ kmalloc(maxdatalen, GFP_ATOMIC);
1999+ if(!master_conntrack->layer7.app_data){
2000+ if (net_ratelimit())
2001+ printk(KERN_ERR "layer7: out of memory in "
2002+ "match, bailing.\n");
2003+ spin_unlock_bh(&l7_lock);
2004+ return info->invert;
2005+ }
2006+
2007+ master_conntrack->layer7.app_data[0] = '\0';
2008+ }
2009+
9b677b44 2010+ if(!skb->layer7_flags[0]){
9d3616dc 2011+ int newbytes;
a4f83ed8 2012+ master_conntrack->layer7.packets++;
91648bd1 2013+ newbytes = add_data(master_conntrack, app_data, appdatalen);
9d3616dc 2014+ if(newbytes == 0) { /* didn't add any data */
9b677b44 2015+ skb->layer7_flags[0] = 1;
9d3616dc
AF
2016+ /* Didn't match before, not going to match now */
2017+ spin_unlock_bh(&l7_lock);
2018+ return info->invert;
2019+ }
2020+ }
2021+
2022+ /* If looking for "unknown", then never match. "Unknown" means that
2023+ we've given up; we're still trying with these packets. */
2024+ if(!strcmp(info->protocol, "unknown")) {
2025+ pattern_result = 0;
2026+ /* If looking for "unset", then always match. "Unset" means that we
2027+ haven't yet classified the connection. */
2028+ } else if(!strcmp(info->protocol, "unset")) {
2029+ pattern_result = 2;
2030+ DPRINTK("layer7: matched unset: not yet classified "
2031+ "(%d/%d packets)\n",
9b677b44 2032+ master_conntrack->layer7.packets, num_packets);
9d3616dc
AF
2033+ /* If the regexp failed to compile, don't bother running it */
2034+ } else if(comppattern &&
2035+ regexec(comppattern, master_conntrack->layer7.app_data)){
2036+ DPRINTK("layer7: matched %s\n", info->protocol);
2037+ pattern_result = 1;
2038+ } else pattern_result = 0;
2039+
2040+ if(pattern_result == 1) {
ddc7b38c 2041+ master_conntrack->layer7.app_proto=get_protostr_ptr(info->protocol);
9d3616dc
AF
2042+ } else if(pattern_result > 1) { /* cleanup from "unset" */
2043+ pattern_result = 1;
2044+ }
2045+
2046+ /* mark the packet seen */
9b677b44 2047+ skb->layer7_flags[0] = 1;
9d3616dc
AF
2048+
2049+ spin_unlock_bh(&l7_lock);
2050+ return (pattern_result ^ info->invert);
2051+}
2052+
c062c770 2053+/*
9d3616dc 2054+// load nf_conntrack_ipv4
91648bd1
AF
2055+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
2056+static int
2057+#else
2058+static bool
2059+#endif
2060+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
2061+check(const struct xt_mtchk_param *par)
9d3616dc
AF
2062+{
2063+ if (nf_ct_l3proto_try_module_get(par->match->family) < 0) {
2064+ printk(KERN_WARNING "can't load conntrack support for "
2065+ "proto=%d\n", par->match->family);
91648bd1
AF
2066+#else
2067+check(const char *tablename, const void *inf,
2068+ const struct xt_match *match, void *matchinfo,
2069+ unsigned int hook_mask)
2070+{
2071+ if (nf_ct_l3proto_try_module_get(match->family) < 0) {
2072+ printk(KERN_WARNING "can't load conntrack support for "
2073+ "proto=%d\n", match->family);
2074+#endif
2075+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)
9d3616dc
AF
2076+ return -EINVAL;
2077+ }
2078+ return 0;
91648bd1
AF
2079+#else
2080+ return 0;
2081+ }
2082+ return 1;
2083+#endif
9d3616dc
AF
2084+}
2085+
2086+
91648bd1
AF
2087+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
2088+ static void destroy(const struct xt_mtdtor_param *par)
2089+ {
2090+ nf_ct_l3proto_module_put(par->match->family);
2091+ }
2092+#else
2093+ static void destroy(const struct xt_match *match, void *matchinfo)
2094+ {
2095+ nf_ct_l3proto_module_put(match->family);
2096+ }
2097+#endif
c062c770 2098+*/
9d3616dc
AF
2099+
2100+static struct xt_match xt_layer7_match[] __read_mostly = {
2101+{
2102+ .name = "layer7",
91648bd1 2103+ .family = NFPROTO_IPV4,
c062c770 2104+// .checkentry = check,
9d3616dc 2105+ .match = match,
c062c770 2106+// .destroy = destroy,
9d3616dc
AF
2107+ .matchsize = sizeof(struct xt_layer7_info),
2108+ .me = THIS_MODULE
2109+}
2110+};
2111+
c062c770
AF
2112+static const struct proc_ops layer7_numpackets_proc_fops = {
2113+ .proc_open = layer7_numpackets_proc_open,
2114+ .proc_read = seq_read,
2115+ .proc_lseek = seq_lseek,
2116+ .proc_release = single_release,
2117+ .proc_write = layer7_numpackets_write_proc,
9d3616dc
AF
2118+};
2119+
2120+static int __init xt_layer7_init(void)
2121+{
c062c770 2122+// need_conntrack();
9d3616dc
AF
2123+
2124+ // Register proc interface
2125+ proc_create_data("layer7_numpackets", 0644,
2126+ init_net.proc_net, &layer7_numpackets_proc_fops, NULL);
2127+
2128+ if(maxdatalen < 1) {
2129+ printk(KERN_WARNING "layer7: maxdatalen can't be < 1, "
2130+ "using 1\n");
2131+ maxdatalen = 1;
2132+ }
2133+ /* This is not a hard limit. It's just here to prevent people from
2134+ bringing their slow machines to a grinding halt. */
2135+ else if(maxdatalen > 65536) {
2136+ printk(KERN_WARNING "layer7: maxdatalen can't be > 65536, "
2137+ "using 65536\n");
2138+ maxdatalen = 65536;
2139+ }
2140+ return xt_register_matches(xt_layer7_match,
2141+ ARRAY_SIZE(xt_layer7_match));
2142+}
2143+
2144+static void __exit xt_layer7_fini(void)
2145+{
2146+ remove_proc_entry("layer7_numpackets", init_net.proc_net);
2147+ xt_unregister_matches(xt_layer7_match, ARRAY_SIZE(xt_layer7_match));
2148+}
2149+
2150+module_init(xt_layer7_init);
2151+module_exit(xt_layer7_fini);
91648bd1 2152+