Commit 3a8fc53a45c444400259e2e285ba414a87061e3d

Authored by Pablo Neira Ayuso
1 parent d0daebc3d6

netfilter: nf_ct_helper: allocate 16 bytes for the helper and policy names

This patch modifies the struct nf_conntrack_helper to allocate
the room for the helper name. The maximum length is 16 bytes
(this was already introduced in 2.6.24).

For the maximum length for expectation policy names, I have
also selected 16 bytes.

This patch is required by the follow-up patch to support
user-space connection tracking helpers.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

Showing 7 changed files with 14 additions and 31 deletions Inline Diff

include/net/netfilter/nf_conntrack_expect.h
1 /* 1 /*
2 * connection tracking expectations. 2 * connection tracking expectations.
3 */ 3 */
4 4
5 #ifndef _NF_CONNTRACK_EXPECT_H 5 #ifndef _NF_CONNTRACK_EXPECT_H
6 #define _NF_CONNTRACK_EXPECT_H 6 #define _NF_CONNTRACK_EXPECT_H
7 #include <net/netfilter/nf_conntrack.h> 7 #include <net/netfilter/nf_conntrack.h>
8 8
9 extern unsigned int nf_ct_expect_hsize; 9 extern unsigned int nf_ct_expect_hsize;
10 extern unsigned int nf_ct_expect_max; 10 extern unsigned int nf_ct_expect_max;
11 11
12 struct nf_conntrack_expect { 12 struct nf_conntrack_expect {
13 /* Conntrack expectation list member */ 13 /* Conntrack expectation list member */
14 struct hlist_node lnode; 14 struct hlist_node lnode;
15 15
16 /* Hash member */ 16 /* Hash member */
17 struct hlist_node hnode; 17 struct hlist_node hnode;
18 18
19 /* We expect this tuple, with the following mask */ 19 /* We expect this tuple, with the following mask */
20 struct nf_conntrack_tuple tuple; 20 struct nf_conntrack_tuple tuple;
21 struct nf_conntrack_tuple_mask mask; 21 struct nf_conntrack_tuple_mask mask;
22 22
23 /* Function to call after setup and insertion */ 23 /* Function to call after setup and insertion */
24 void (*expectfn)(struct nf_conn *new, 24 void (*expectfn)(struct nf_conn *new,
25 struct nf_conntrack_expect *this); 25 struct nf_conntrack_expect *this);
26 26
27 /* Helper to assign to new connection */ 27 /* Helper to assign to new connection */
28 struct nf_conntrack_helper *helper; 28 struct nf_conntrack_helper *helper;
29 29
30 /* The conntrack of the master connection */ 30 /* The conntrack of the master connection */
31 struct nf_conn *master; 31 struct nf_conn *master;
32 32
33 /* Timer function; deletes the expectation. */ 33 /* Timer function; deletes the expectation. */
34 struct timer_list timeout; 34 struct timer_list timeout;
35 35
36 /* Usage count. */ 36 /* Usage count. */
37 atomic_t use; 37 atomic_t use;
38 38
39 /* Flags */ 39 /* Flags */
40 unsigned int flags; 40 unsigned int flags;
41 41
42 /* Expectation class */ 42 /* Expectation class */
43 unsigned int class; 43 unsigned int class;
44 44
45 #ifdef CONFIG_NF_NAT_NEEDED 45 #ifdef CONFIG_NF_NAT_NEEDED
46 __be32 saved_ip; 46 __be32 saved_ip;
47 /* This is the original per-proto part, used to map the 47 /* This is the original per-proto part, used to map the
48 * expected connection the way the recipient expects. */ 48 * expected connection the way the recipient expects. */
49 union nf_conntrack_man_proto saved_proto; 49 union nf_conntrack_man_proto saved_proto;
50 /* Direction relative to the master connection. */ 50 /* Direction relative to the master connection. */
51 enum ip_conntrack_dir dir; 51 enum ip_conntrack_dir dir;
52 #endif 52 #endif
53 53
54 struct rcu_head rcu; 54 struct rcu_head rcu;
55 }; 55 };
56 56
57 static inline struct net *nf_ct_exp_net(struct nf_conntrack_expect *exp) 57 static inline struct net *nf_ct_exp_net(struct nf_conntrack_expect *exp)
58 { 58 {
59 return nf_ct_net(exp->master); 59 return nf_ct_net(exp->master);
60 } 60 }
61 61
62 #define NF_CT_EXP_POLICY_NAME_LEN 16
63
62 struct nf_conntrack_expect_policy { 64 struct nf_conntrack_expect_policy {
63 unsigned int max_expected; 65 unsigned int max_expected;
64 unsigned int timeout; 66 unsigned int timeout;
65 const char *name; 67 char name[NF_CT_EXP_POLICY_NAME_LEN];
66 }; 68 };
67 69
68 #define NF_CT_EXPECT_CLASS_DEFAULT 0 70 #define NF_CT_EXPECT_CLASS_DEFAULT 0
69 71
70 int nf_conntrack_expect_init(struct net *net); 72 int nf_conntrack_expect_init(struct net *net);
71 void nf_conntrack_expect_fini(struct net *net); 73 void nf_conntrack_expect_fini(struct net *net);
72 74
73 struct nf_conntrack_expect * 75 struct nf_conntrack_expect *
74 __nf_ct_expect_find(struct net *net, u16 zone, 76 __nf_ct_expect_find(struct net *net, u16 zone,
75 const struct nf_conntrack_tuple *tuple); 77 const struct nf_conntrack_tuple *tuple);
76 78
77 struct nf_conntrack_expect * 79 struct nf_conntrack_expect *
78 nf_ct_expect_find_get(struct net *net, u16 zone, 80 nf_ct_expect_find_get(struct net *net, u16 zone,
79 const struct nf_conntrack_tuple *tuple); 81 const struct nf_conntrack_tuple *tuple);
80 82
81 struct nf_conntrack_expect * 83 struct nf_conntrack_expect *
82 nf_ct_find_expectation(struct net *net, u16 zone, 84 nf_ct_find_expectation(struct net *net, u16 zone,
83 const struct nf_conntrack_tuple *tuple); 85 const struct nf_conntrack_tuple *tuple);
84 86
85 void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, 87 void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
86 u32 pid, int report); 88 u32 pid, int report);
87 static inline void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) 89 static inline void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
88 { 90 {
89 nf_ct_unlink_expect_report(exp, 0, 0); 91 nf_ct_unlink_expect_report(exp, 0, 0);
90 } 92 }
91 93
92 void nf_ct_remove_expectations(struct nf_conn *ct); 94 void nf_ct_remove_expectations(struct nf_conn *ct);
93 void nf_ct_unexpect_related(struct nf_conntrack_expect *exp); 95 void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
94 96
95 /* Allocate space for an expectation: this is mandatory before calling 97 /* Allocate space for an expectation: this is mandatory before calling
96 nf_ct_expect_related. You will have to call put afterwards. */ 98 nf_ct_expect_related. You will have to call put afterwards. */
97 struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me); 99 struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me);
98 void nf_ct_expect_init(struct nf_conntrack_expect *, unsigned int, u_int8_t, 100 void nf_ct_expect_init(struct nf_conntrack_expect *, unsigned int, u_int8_t,
99 const union nf_inet_addr *, 101 const union nf_inet_addr *,
100 const union nf_inet_addr *, 102 const union nf_inet_addr *,
101 u_int8_t, const __be16 *, const __be16 *); 103 u_int8_t, const __be16 *, const __be16 *);
102 void nf_ct_expect_put(struct nf_conntrack_expect *exp); 104 void nf_ct_expect_put(struct nf_conntrack_expect *exp);
103 int nf_ct_expect_related_report(struct nf_conntrack_expect *expect, 105 int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
104 u32 pid, int report); 106 u32 pid, int report);
105 static inline int nf_ct_expect_related(struct nf_conntrack_expect *expect) 107 static inline int nf_ct_expect_related(struct nf_conntrack_expect *expect)
106 { 108 {
107 return nf_ct_expect_related_report(expect, 0, 0); 109 return nf_ct_expect_related_report(expect, 0, 0);
108 } 110 }
109 111
110 #endif /*_NF_CONNTRACK_EXPECT_H*/ 112 #endif /*_NF_CONNTRACK_EXPECT_H*/
111 113
112 114
include/net/netfilter/nf_conntrack_helper.h
1 /* 1 /*
2 * connection tracking helpers. 2 * connection tracking helpers.
3 * 3 *
4 * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> 4 * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
5 * - generalize L3 protocol dependent part. 5 * - generalize L3 protocol dependent part.
6 * 6 *
7 * Derived from include/linux/netfiter_ipv4/ip_conntrack_helper.h 7 * Derived from include/linux/netfiter_ipv4/ip_conntrack_helper.h
8 */ 8 */
9 9
10 #ifndef _NF_CONNTRACK_HELPER_H 10 #ifndef _NF_CONNTRACK_HELPER_H
11 #define _NF_CONNTRACK_HELPER_H 11 #define _NF_CONNTRACK_HELPER_H
12 #include <net/netfilter/nf_conntrack.h> 12 #include <net/netfilter/nf_conntrack.h>
13 #include <net/netfilter/nf_conntrack_extend.h> 13 #include <net/netfilter/nf_conntrack_extend.h>
14 14
15 struct module; 15 struct module;
16 16
17 #define NF_CT_HELPER_NAME_LEN 16 17 #define NF_CT_HELPER_NAME_LEN 16
18 18
19 struct nf_conntrack_helper { 19 struct nf_conntrack_helper {
20 struct hlist_node hnode; /* Internal use. */ 20 struct hlist_node hnode; /* Internal use. */
21 21
22 const char *name; /* name of the module */ 22 char name[NF_CT_HELPER_NAME_LEN]; /* name of the module */
23 struct module *me; /* pointer to self */ 23 struct module *me; /* pointer to self */
24 const struct nf_conntrack_expect_policy *expect_policy; 24 const struct nf_conntrack_expect_policy *expect_policy;
25 25
26 /* Tuple of things we will help (compared against server response) */ 26 /* Tuple of things we will help (compared against server response) */
27 struct nf_conntrack_tuple tuple; 27 struct nf_conntrack_tuple tuple;
28 28
29 /* Function to call when data passes; return verdict, or -1 to 29 /* Function to call when data passes; return verdict, or -1 to
30 invalidate. */ 30 invalidate. */
31 int (*help)(struct sk_buff *skb, 31 int (*help)(struct sk_buff *skb,
32 unsigned int protoff, 32 unsigned int protoff,
33 struct nf_conn *ct, 33 struct nf_conn *ct,
34 enum ip_conntrack_info conntrackinfo); 34 enum ip_conntrack_info conntrackinfo);
35 35
36 void (*destroy)(struct nf_conn *ct); 36 void (*destroy)(struct nf_conn *ct);
37 37
38 int (*to_nlattr)(struct sk_buff *skb, const struct nf_conn *ct); 38 int (*to_nlattr)(struct sk_buff *skb, const struct nf_conn *ct);
39 unsigned int expect_class_max; 39 unsigned int expect_class_max;
40 }; 40 };
41 41
42 extern struct nf_conntrack_helper * 42 extern struct nf_conntrack_helper *
43 __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum); 43 __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum);
44 44
45 extern struct nf_conntrack_helper * 45 extern struct nf_conntrack_helper *
46 nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum); 46 nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum);
47 47
48 extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); 48 extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
49 extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); 49 extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
50 50
51 extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp); 51 extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp);
52 52
53 extern int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, 53 extern int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
54 gfp_t flags); 54 gfp_t flags);
55 55
56 extern void nf_ct_helper_destroy(struct nf_conn *ct); 56 extern void nf_ct_helper_destroy(struct nf_conn *ct);
57 57
58 static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) 58 static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
59 { 59 {
60 return nf_ct_ext_find(ct, NF_CT_EXT_HELPER); 60 return nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
61 } 61 }
62 62
63 extern int nf_conntrack_helper_init(struct net *net); 63 extern int nf_conntrack_helper_init(struct net *net);
64 extern void nf_conntrack_helper_fini(struct net *net); 64 extern void nf_conntrack_helper_fini(struct net *net);
65 65
66 extern int nf_conntrack_broadcast_help(struct sk_buff *skb, 66 extern int nf_conntrack_broadcast_help(struct sk_buff *skb,
67 unsigned int protoff, 67 unsigned int protoff,
68 struct nf_conn *ct, 68 struct nf_conn *ct,
69 enum ip_conntrack_info ctinfo, 69 enum ip_conntrack_info ctinfo,
70 unsigned int timeout); 70 unsigned int timeout);
71 71
72 struct nf_ct_helper_expectfn { 72 struct nf_ct_helper_expectfn {
73 struct list_head head; 73 struct list_head head;
74 const char *name; 74 const char *name;
75 void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp); 75 void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
76 }; 76 };
77 77
78 void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n); 78 void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n);
79 void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n); 79 void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n);
80 struct nf_ct_helper_expectfn * 80 struct nf_ct_helper_expectfn *
81 nf_ct_helper_expectfn_find_by_name(const char *name); 81 nf_ct_helper_expectfn_find_by_name(const char *name);
82 struct nf_ct_helper_expectfn * 82 struct nf_ct_helper_expectfn *
83 nf_ct_helper_expectfn_find_by_symbol(const void *symbol); 83 nf_ct_helper_expectfn_find_by_symbol(const void *symbol);
84 84
85 #endif /*_NF_CONNTRACK_HELPER_H*/ 85 #endif /*_NF_CONNTRACK_HELPER_H*/
86 86
net/netfilter/nf_conntrack_ftp.c
1 /* FTP extension for connection tracking. */ 1 /* FTP extension for connection tracking. */
2 2
3 /* (C) 1999-2001 Paul `Rusty' Russell 3 /* (C) 1999-2001 Paul `Rusty' Russell
4 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> 4 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
5 * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org> 5 * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 */ 10 */
11 11
12 #include <linux/module.h> 12 #include <linux/module.h>
13 #include <linux/moduleparam.h> 13 #include <linux/moduleparam.h>
14 #include <linux/netfilter.h> 14 #include <linux/netfilter.h>
15 #include <linux/ip.h> 15 #include <linux/ip.h>
16 #include <linux/slab.h> 16 #include <linux/slab.h>
17 #include <linux/ipv6.h> 17 #include <linux/ipv6.h>
18 #include <linux/ctype.h> 18 #include <linux/ctype.h>
19 #include <linux/inet.h> 19 #include <linux/inet.h>
20 #include <net/checksum.h> 20 #include <net/checksum.h>
21 #include <net/tcp.h> 21 #include <net/tcp.h>
22 22
23 #include <net/netfilter/nf_conntrack.h> 23 #include <net/netfilter/nf_conntrack.h>
24 #include <net/netfilter/nf_conntrack_expect.h> 24 #include <net/netfilter/nf_conntrack_expect.h>
25 #include <net/netfilter/nf_conntrack_ecache.h> 25 #include <net/netfilter/nf_conntrack_ecache.h>
26 #include <net/netfilter/nf_conntrack_helper.h> 26 #include <net/netfilter/nf_conntrack_helper.h>
27 #include <linux/netfilter/nf_conntrack_ftp.h> 27 #include <linux/netfilter/nf_conntrack_ftp.h>
28 28
29 MODULE_LICENSE("GPL"); 29 MODULE_LICENSE("GPL");
30 MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>"); 30 MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
31 MODULE_DESCRIPTION("ftp connection tracking helper"); 31 MODULE_DESCRIPTION("ftp connection tracking helper");
32 MODULE_ALIAS("ip_conntrack_ftp"); 32 MODULE_ALIAS("ip_conntrack_ftp");
33 MODULE_ALIAS_NFCT_HELPER("ftp"); 33 MODULE_ALIAS_NFCT_HELPER("ftp");
34 34
35 /* This is slow, but it's simple. --RR */ 35 /* This is slow, but it's simple. --RR */
36 static char *ftp_buffer; 36 static char *ftp_buffer;
37 37
38 static DEFINE_SPINLOCK(nf_ftp_lock); 38 static DEFINE_SPINLOCK(nf_ftp_lock);
39 39
40 #define MAX_PORTS 8 40 #define MAX_PORTS 8
41 static u_int16_t ports[MAX_PORTS]; 41 static u_int16_t ports[MAX_PORTS];
42 static unsigned int ports_c; 42 static unsigned int ports_c;
43 module_param_array(ports, ushort, &ports_c, 0400); 43 module_param_array(ports, ushort, &ports_c, 0400);
44 44
45 static bool loose; 45 static bool loose;
46 module_param(loose, bool, 0600); 46 module_param(loose, bool, 0600);
47 47
48 unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb, 48 unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb,
49 enum ip_conntrack_info ctinfo, 49 enum ip_conntrack_info ctinfo,
50 enum nf_ct_ftp_type type, 50 enum nf_ct_ftp_type type,
51 unsigned int matchoff, 51 unsigned int matchoff,
52 unsigned int matchlen, 52 unsigned int matchlen,
53 struct nf_conntrack_expect *exp); 53 struct nf_conntrack_expect *exp);
54 EXPORT_SYMBOL_GPL(nf_nat_ftp_hook); 54 EXPORT_SYMBOL_GPL(nf_nat_ftp_hook);
55 55
56 static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char); 56 static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char);
57 static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char); 57 static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char);
58 static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *, 58 static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *,
59 char); 59 char);
60 60
61 static struct ftp_search { 61 static struct ftp_search {
62 const char *pattern; 62 const char *pattern;
63 size_t plen; 63 size_t plen;
64 char skip; 64 char skip;
65 char term; 65 char term;
66 enum nf_ct_ftp_type ftptype; 66 enum nf_ct_ftp_type ftptype;
67 int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char); 67 int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char);
68 } search[IP_CT_DIR_MAX][2] = { 68 } search[IP_CT_DIR_MAX][2] = {
69 [IP_CT_DIR_ORIGINAL] = { 69 [IP_CT_DIR_ORIGINAL] = {
70 { 70 {
71 .pattern = "PORT", 71 .pattern = "PORT",
72 .plen = sizeof("PORT") - 1, 72 .plen = sizeof("PORT") - 1,
73 .skip = ' ', 73 .skip = ' ',
74 .term = '\r', 74 .term = '\r',
75 .ftptype = NF_CT_FTP_PORT, 75 .ftptype = NF_CT_FTP_PORT,
76 .getnum = try_rfc959, 76 .getnum = try_rfc959,
77 }, 77 },
78 { 78 {
79 .pattern = "EPRT", 79 .pattern = "EPRT",
80 .plen = sizeof("EPRT") - 1, 80 .plen = sizeof("EPRT") - 1,
81 .skip = ' ', 81 .skip = ' ',
82 .term = '\r', 82 .term = '\r',
83 .ftptype = NF_CT_FTP_EPRT, 83 .ftptype = NF_CT_FTP_EPRT,
84 .getnum = try_eprt, 84 .getnum = try_eprt,
85 }, 85 },
86 }, 86 },
87 [IP_CT_DIR_REPLY] = { 87 [IP_CT_DIR_REPLY] = {
88 { 88 {
89 .pattern = "227 ", 89 .pattern = "227 ",
90 .plen = sizeof("227 ") - 1, 90 .plen = sizeof("227 ") - 1,
91 .skip = '(', 91 .skip = '(',
92 .term = ')', 92 .term = ')',
93 .ftptype = NF_CT_FTP_PASV, 93 .ftptype = NF_CT_FTP_PASV,
94 .getnum = try_rfc959, 94 .getnum = try_rfc959,
95 }, 95 },
96 { 96 {
97 .pattern = "229 ", 97 .pattern = "229 ",
98 .plen = sizeof("229 ") - 1, 98 .plen = sizeof("229 ") - 1,
99 .skip = '(', 99 .skip = '(',
100 .term = ')', 100 .term = ')',
101 .ftptype = NF_CT_FTP_EPSV, 101 .ftptype = NF_CT_FTP_EPSV,
102 .getnum = try_epsv_response, 102 .getnum = try_epsv_response,
103 }, 103 },
104 }, 104 },
105 }; 105 };
106 106
107 static int 107 static int
108 get_ipv6_addr(const char *src, size_t dlen, struct in6_addr *dst, u_int8_t term) 108 get_ipv6_addr(const char *src, size_t dlen, struct in6_addr *dst, u_int8_t term)
109 { 109 {
110 const char *end; 110 const char *end;
111 int ret = in6_pton(src, min_t(size_t, dlen, 0xffff), (u8 *)dst, term, &end); 111 int ret = in6_pton(src, min_t(size_t, dlen, 0xffff), (u8 *)dst, term, &end);
112 if (ret > 0) 112 if (ret > 0)
113 return (int)(end - src); 113 return (int)(end - src);
114 return 0; 114 return 0;
115 } 115 }
116 116
117 static int try_number(const char *data, size_t dlen, u_int32_t array[], 117 static int try_number(const char *data, size_t dlen, u_int32_t array[],
118 int array_size, char sep, char term) 118 int array_size, char sep, char term)
119 { 119 {
120 u_int32_t i, len; 120 u_int32_t i, len;
121 121
122 memset(array, 0, sizeof(array[0])*array_size); 122 memset(array, 0, sizeof(array[0])*array_size);
123 123
124 /* Keep data pointing at next char. */ 124 /* Keep data pointing at next char. */
125 for (i = 0, len = 0; len < dlen && i < array_size; len++, data++) { 125 for (i = 0, len = 0; len < dlen && i < array_size; len++, data++) {
126 if (*data >= '0' && *data <= '9') { 126 if (*data >= '0' && *data <= '9') {
127 array[i] = array[i]*10 + *data - '0'; 127 array[i] = array[i]*10 + *data - '0';
128 } 128 }
129 else if (*data == sep) 129 else if (*data == sep)
130 i++; 130 i++;
131 else { 131 else {
132 /* Unexpected character; true if it's the 132 /* Unexpected character; true if it's the
133 terminator and we're finished. */ 133 terminator and we're finished. */
134 if (*data == term && i == array_size - 1) 134 if (*data == term && i == array_size - 1)
135 return len; 135 return len;
136 136
137 pr_debug("Char %u (got %u nums) `%u' unexpected\n", 137 pr_debug("Char %u (got %u nums) `%u' unexpected\n",
138 len, i, *data); 138 len, i, *data);
139 return 0; 139 return 0;
140 } 140 }
141 } 141 }
142 pr_debug("Failed to fill %u numbers separated by %c\n", 142 pr_debug("Failed to fill %u numbers separated by %c\n",
143 array_size, sep); 143 array_size, sep);
144 return 0; 144 return 0;
145 } 145 }
146 146
147 /* Returns 0, or length of numbers: 192,168,1,1,5,6 */ 147 /* Returns 0, or length of numbers: 192,168,1,1,5,6 */
148 static int try_rfc959(const char *data, size_t dlen, 148 static int try_rfc959(const char *data, size_t dlen,
149 struct nf_conntrack_man *cmd, char term) 149 struct nf_conntrack_man *cmd, char term)
150 { 150 {
151 int length; 151 int length;
152 u_int32_t array[6]; 152 u_int32_t array[6];
153 153
154 length = try_number(data, dlen, array, 6, ',', term); 154 length = try_number(data, dlen, array, 6, ',', term);
155 if (length == 0) 155 if (length == 0)
156 return 0; 156 return 0;
157 157
158 cmd->u3.ip = htonl((array[0] << 24) | (array[1] << 16) | 158 cmd->u3.ip = htonl((array[0] << 24) | (array[1] << 16) |
159 (array[2] << 8) | array[3]); 159 (array[2] << 8) | array[3]);
160 cmd->u.tcp.port = htons((array[4] << 8) | array[5]); 160 cmd->u.tcp.port = htons((array[4] << 8) | array[5]);
161 return length; 161 return length;
162 } 162 }
163 163
164 /* Grab port: number up to delimiter */ 164 /* Grab port: number up to delimiter */
165 static int get_port(const char *data, int start, size_t dlen, char delim, 165 static int get_port(const char *data, int start, size_t dlen, char delim,
166 __be16 *port) 166 __be16 *port)
167 { 167 {
168 u_int16_t tmp_port = 0; 168 u_int16_t tmp_port = 0;
169 int i; 169 int i;
170 170
171 for (i = start; i < dlen; i++) { 171 for (i = start; i < dlen; i++) {
172 /* Finished? */ 172 /* Finished? */
173 if (data[i] == delim) { 173 if (data[i] == delim) {
174 if (tmp_port == 0) 174 if (tmp_port == 0)
175 break; 175 break;
176 *port = htons(tmp_port); 176 *port = htons(tmp_port);
177 pr_debug("get_port: return %d\n", tmp_port); 177 pr_debug("get_port: return %d\n", tmp_port);
178 return i + 1; 178 return i + 1;
179 } 179 }
180 else if (data[i] >= '0' && data[i] <= '9') 180 else if (data[i] >= '0' && data[i] <= '9')
181 tmp_port = tmp_port*10 + data[i] - '0'; 181 tmp_port = tmp_port*10 + data[i] - '0';
182 else { /* Some other crap */ 182 else { /* Some other crap */
183 pr_debug("get_port: invalid char.\n"); 183 pr_debug("get_port: invalid char.\n");
184 break; 184 break;
185 } 185 }
186 } 186 }
187 return 0; 187 return 0;
188 } 188 }
189 189
190 /* Returns 0, or length of numbers: |1|132.235.1.2|6275| or |2|3ffe::1|6275| */ 190 /* Returns 0, or length of numbers: |1|132.235.1.2|6275| or |2|3ffe::1|6275| */
191 static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd, 191 static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd,
192 char term) 192 char term)
193 { 193 {
194 char delim; 194 char delim;
195 int length; 195 int length;
196 196
197 /* First character is delimiter, then "1" for IPv4 or "2" for IPv6, 197 /* First character is delimiter, then "1" for IPv4 or "2" for IPv6,
198 then delimiter again. */ 198 then delimiter again. */
199 if (dlen <= 3) { 199 if (dlen <= 3) {
200 pr_debug("EPRT: too short\n"); 200 pr_debug("EPRT: too short\n");
201 return 0; 201 return 0;
202 } 202 }
203 delim = data[0]; 203 delim = data[0];
204 if (isdigit(delim) || delim < 33 || delim > 126 || data[2] != delim) { 204 if (isdigit(delim) || delim < 33 || delim > 126 || data[2] != delim) {
205 pr_debug("try_eprt: invalid delimitter.\n"); 205 pr_debug("try_eprt: invalid delimitter.\n");
206 return 0; 206 return 0;
207 } 207 }
208 208
209 if ((cmd->l3num == PF_INET && data[1] != '1') || 209 if ((cmd->l3num == PF_INET && data[1] != '1') ||
210 (cmd->l3num == PF_INET6 && data[1] != '2')) { 210 (cmd->l3num == PF_INET6 && data[1] != '2')) {
211 pr_debug("EPRT: invalid protocol number.\n"); 211 pr_debug("EPRT: invalid protocol number.\n");
212 return 0; 212 return 0;
213 } 213 }
214 214
215 pr_debug("EPRT: Got %c%c%c\n", delim, data[1], delim); 215 pr_debug("EPRT: Got %c%c%c\n", delim, data[1], delim);
216 216
217 if (data[1] == '1') { 217 if (data[1] == '1') {
218 u_int32_t array[4]; 218 u_int32_t array[4];
219 219
220 /* Now we have IP address. */ 220 /* Now we have IP address. */
221 length = try_number(data + 3, dlen - 3, array, 4, '.', delim); 221 length = try_number(data + 3, dlen - 3, array, 4, '.', delim);
222 if (length != 0) 222 if (length != 0)
223 cmd->u3.ip = htonl((array[0] << 24) | (array[1] << 16) 223 cmd->u3.ip = htonl((array[0] << 24) | (array[1] << 16)
224 | (array[2] << 8) | array[3]); 224 | (array[2] << 8) | array[3]);
225 } else { 225 } else {
226 /* Now we have IPv6 address. */ 226 /* Now we have IPv6 address. */
227 length = get_ipv6_addr(data + 3, dlen - 3, 227 length = get_ipv6_addr(data + 3, dlen - 3,
228 (struct in6_addr *)cmd->u3.ip6, delim); 228 (struct in6_addr *)cmd->u3.ip6, delim);
229 } 229 }
230 230
231 if (length == 0) 231 if (length == 0)
232 return 0; 232 return 0;
233 pr_debug("EPRT: Got IP address!\n"); 233 pr_debug("EPRT: Got IP address!\n");
234 /* Start offset includes initial "|1|", and trailing delimiter */ 234 /* Start offset includes initial "|1|", and trailing delimiter */
235 return get_port(data, 3 + length + 1, dlen, delim, &cmd->u.tcp.port); 235 return get_port(data, 3 + length + 1, dlen, delim, &cmd->u.tcp.port);
236 } 236 }
237 237
238 /* Returns 0, or length of numbers: |||6446| */ 238 /* Returns 0, or length of numbers: |||6446| */
239 static int try_epsv_response(const char *data, size_t dlen, 239 static int try_epsv_response(const char *data, size_t dlen,
240 struct nf_conntrack_man *cmd, char term) 240 struct nf_conntrack_man *cmd, char term)
241 { 241 {
242 char delim; 242 char delim;
243 243
244 /* Three delimiters. */ 244 /* Three delimiters. */
245 if (dlen <= 3) return 0; 245 if (dlen <= 3) return 0;
246 delim = data[0]; 246 delim = data[0];
247 if (isdigit(delim) || delim < 33 || delim > 126 || 247 if (isdigit(delim) || delim < 33 || delim > 126 ||
248 data[1] != delim || data[2] != delim) 248 data[1] != delim || data[2] != delim)
249 return 0; 249 return 0;
250 250
251 return get_port(data, 3, dlen, delim, &cmd->u.tcp.port); 251 return get_port(data, 3, dlen, delim, &cmd->u.tcp.port);
252 } 252 }
253 253
254 /* Return 1 for match, 0 for accept, -1 for partial. */ 254 /* Return 1 for match, 0 for accept, -1 for partial. */
255 static int find_pattern(const char *data, size_t dlen, 255 static int find_pattern(const char *data, size_t dlen,
256 const char *pattern, size_t plen, 256 const char *pattern, size_t plen,
257 char skip, char term, 257 char skip, char term,
258 unsigned int *numoff, 258 unsigned int *numoff,
259 unsigned int *numlen, 259 unsigned int *numlen,
260 struct nf_conntrack_man *cmd, 260 struct nf_conntrack_man *cmd,
261 int (*getnum)(const char *, size_t, 261 int (*getnum)(const char *, size_t,
262 struct nf_conntrack_man *, char)) 262 struct nf_conntrack_man *, char))
263 { 263 {
264 size_t i; 264 size_t i;
265 265
266 pr_debug("find_pattern `%s': dlen = %Zu\n", pattern, dlen); 266 pr_debug("find_pattern `%s': dlen = %Zu\n", pattern, dlen);
267 if (dlen == 0) 267 if (dlen == 0)
268 return 0; 268 return 0;
269 269
270 if (dlen <= plen) { 270 if (dlen <= plen) {
271 /* Short packet: try for partial? */ 271 /* Short packet: try for partial? */
272 if (strnicmp(data, pattern, dlen) == 0) 272 if (strnicmp(data, pattern, dlen) == 0)
273 return -1; 273 return -1;
274 else return 0; 274 else return 0;
275 } 275 }
276 276
277 if (strnicmp(data, pattern, plen) != 0) { 277 if (strnicmp(data, pattern, plen) != 0) {
278 #if 0 278 #if 0
279 size_t i; 279 size_t i;
280 280
281 pr_debug("ftp: string mismatch\n"); 281 pr_debug("ftp: string mismatch\n");
282 for (i = 0; i < plen; i++) { 282 for (i = 0; i < plen; i++) {
283 pr_debug("ftp:char %u `%c'(%u) vs `%c'(%u)\n", 283 pr_debug("ftp:char %u `%c'(%u) vs `%c'(%u)\n",
284 i, data[i], data[i], 284 i, data[i], data[i],
285 pattern[i], pattern[i]); 285 pattern[i], pattern[i]);
286 } 286 }
287 #endif 287 #endif
288 return 0; 288 return 0;
289 } 289 }
290 290
291 pr_debug("Pattern matches!\n"); 291 pr_debug("Pattern matches!\n");
292 /* Now we've found the constant string, try to skip 292 /* Now we've found the constant string, try to skip
293 to the 'skip' character */ 293 to the 'skip' character */
294 for (i = plen; data[i] != skip; i++) 294 for (i = plen; data[i] != skip; i++)
295 if (i == dlen - 1) return -1; 295 if (i == dlen - 1) return -1;
296 296
297 /* Skip over the last character */ 297 /* Skip over the last character */
298 i++; 298 i++;
299 299
300 pr_debug("Skipped up to `%c'!\n", skip); 300 pr_debug("Skipped up to `%c'!\n", skip);
301 301
302 *numoff = i; 302 *numoff = i;
303 *numlen = getnum(data + i, dlen - i, cmd, term); 303 *numlen = getnum(data + i, dlen - i, cmd, term);
304 if (!*numlen) 304 if (!*numlen)
305 return -1; 305 return -1;
306 306
307 pr_debug("Match succeeded!\n"); 307 pr_debug("Match succeeded!\n");
308 return 1; 308 return 1;
309 } 309 }
310 310
311 /* Look up to see if we're just after a \n. */ 311 /* Look up to see if we're just after a \n. */
312 static int find_nl_seq(u32 seq, const struct nf_ct_ftp_master *info, int dir) 312 static int find_nl_seq(u32 seq, const struct nf_ct_ftp_master *info, int dir)
313 { 313 {
314 unsigned int i; 314 unsigned int i;
315 315
316 for (i = 0; i < info->seq_aft_nl_num[dir]; i++) 316 for (i = 0; i < info->seq_aft_nl_num[dir]; i++)
317 if (info->seq_aft_nl[dir][i] == seq) 317 if (info->seq_aft_nl[dir][i] == seq)
318 return 1; 318 return 1;
319 return 0; 319 return 0;
320 } 320 }
321 321
322 /* We don't update if it's older than what we have. */ 322 /* We don't update if it's older than what we have. */
323 static void update_nl_seq(struct nf_conn *ct, u32 nl_seq, 323 static void update_nl_seq(struct nf_conn *ct, u32 nl_seq,
324 struct nf_ct_ftp_master *info, int dir, 324 struct nf_ct_ftp_master *info, int dir,
325 struct sk_buff *skb) 325 struct sk_buff *skb)
326 { 326 {
327 unsigned int i, oldest; 327 unsigned int i, oldest;
328 328
329 /* Look for oldest: if we find exact match, we're done. */ 329 /* Look for oldest: if we find exact match, we're done. */
330 for (i = 0; i < info->seq_aft_nl_num[dir]; i++) { 330 for (i = 0; i < info->seq_aft_nl_num[dir]; i++) {
331 if (info->seq_aft_nl[dir][i] == nl_seq) 331 if (info->seq_aft_nl[dir][i] == nl_seq)
332 return; 332 return;
333 } 333 }
334 334
335 if (info->seq_aft_nl_num[dir] < NUM_SEQ_TO_REMEMBER) { 335 if (info->seq_aft_nl_num[dir] < NUM_SEQ_TO_REMEMBER) {
336 info->seq_aft_nl[dir][info->seq_aft_nl_num[dir]++] = nl_seq; 336 info->seq_aft_nl[dir][info->seq_aft_nl_num[dir]++] = nl_seq;
337 } else { 337 } else {
338 if (before(info->seq_aft_nl[dir][0], info->seq_aft_nl[dir][1])) 338 if (before(info->seq_aft_nl[dir][0], info->seq_aft_nl[dir][1]))
339 oldest = 0; 339 oldest = 0;
340 else 340 else
341 oldest = 1; 341 oldest = 1;
342 342
343 if (after(nl_seq, info->seq_aft_nl[dir][oldest])) 343 if (after(nl_seq, info->seq_aft_nl[dir][oldest]))
344 info->seq_aft_nl[dir][oldest] = nl_seq; 344 info->seq_aft_nl[dir][oldest] = nl_seq;
345 } 345 }
346 } 346 }
347 347
348 static int help(struct sk_buff *skb, 348 static int help(struct sk_buff *skb,
349 unsigned int protoff, 349 unsigned int protoff,
350 struct nf_conn *ct, 350 struct nf_conn *ct,
351 enum ip_conntrack_info ctinfo) 351 enum ip_conntrack_info ctinfo)
352 { 352 {
353 unsigned int dataoff, datalen; 353 unsigned int dataoff, datalen;
354 const struct tcphdr *th; 354 const struct tcphdr *th;
355 struct tcphdr _tcph; 355 struct tcphdr _tcph;
356 const char *fb_ptr; 356 const char *fb_ptr;
357 int ret; 357 int ret;
358 u32 seq; 358 u32 seq;
359 int dir = CTINFO2DIR(ctinfo); 359 int dir = CTINFO2DIR(ctinfo);
360 unsigned int uninitialized_var(matchlen), uninitialized_var(matchoff); 360 unsigned int uninitialized_var(matchlen), uninitialized_var(matchoff);
361 struct nf_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info; 361 struct nf_ct_ftp_master *ct_ftp_info = &nfct_help(ct)->help.ct_ftp_info;
362 struct nf_conntrack_expect *exp; 362 struct nf_conntrack_expect *exp;
363 union nf_inet_addr *daddr; 363 union nf_inet_addr *daddr;
364 struct nf_conntrack_man cmd = {}; 364 struct nf_conntrack_man cmd = {};
365 unsigned int i; 365 unsigned int i;
366 int found = 0, ends_in_nl; 366 int found = 0, ends_in_nl;
367 typeof(nf_nat_ftp_hook) nf_nat_ftp; 367 typeof(nf_nat_ftp_hook) nf_nat_ftp;
368 368
369 /* Until there's been traffic both ways, don't look in packets. */ 369 /* Until there's been traffic both ways, don't look in packets. */
370 if (ctinfo != IP_CT_ESTABLISHED && 370 if (ctinfo != IP_CT_ESTABLISHED &&
371 ctinfo != IP_CT_ESTABLISHED_REPLY) { 371 ctinfo != IP_CT_ESTABLISHED_REPLY) {
372 pr_debug("ftp: Conntrackinfo = %u\n", ctinfo); 372 pr_debug("ftp: Conntrackinfo = %u\n", ctinfo);
373 return NF_ACCEPT; 373 return NF_ACCEPT;
374 } 374 }
375 375
376 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); 376 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
377 if (th == NULL) 377 if (th == NULL)
378 return NF_ACCEPT; 378 return NF_ACCEPT;
379 379
380 dataoff = protoff + th->doff * 4; 380 dataoff = protoff + th->doff * 4;
381 /* No data? */ 381 /* No data? */
382 if (dataoff >= skb->len) { 382 if (dataoff >= skb->len) {
383 pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff, 383 pr_debug("ftp: dataoff(%u) >= skblen(%u)\n", dataoff,
384 skb->len); 384 skb->len);
385 return NF_ACCEPT; 385 return NF_ACCEPT;
386 } 386 }
387 datalen = skb->len - dataoff; 387 datalen = skb->len - dataoff;
388 388
389 spin_lock_bh(&nf_ftp_lock); 389 spin_lock_bh(&nf_ftp_lock);
390 fb_ptr = skb_header_pointer(skb, dataoff, datalen, ftp_buffer); 390 fb_ptr = skb_header_pointer(skb, dataoff, datalen, ftp_buffer);
391 BUG_ON(fb_ptr == NULL); 391 BUG_ON(fb_ptr == NULL);
392 392
393 ends_in_nl = (fb_ptr[datalen - 1] == '\n'); 393 ends_in_nl = (fb_ptr[datalen - 1] == '\n');
394 seq = ntohl(th->seq) + datalen; 394 seq = ntohl(th->seq) + datalen;
395 395
396 /* Look up to see if we're just after a \n. */ 396 /* Look up to see if we're just after a \n. */
397 if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) { 397 if (!find_nl_seq(ntohl(th->seq), ct_ftp_info, dir)) {
398 /* Now if this ends in \n, update ftp info. */ 398 /* Now if this ends in \n, update ftp info. */
399 pr_debug("nf_conntrack_ftp: wrong seq pos %s(%u) or %s(%u)\n", 399 pr_debug("nf_conntrack_ftp: wrong seq pos %s(%u) or %s(%u)\n",
400 ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)", 400 ct_ftp_info->seq_aft_nl_num[dir] > 0 ? "" : "(UNSET)",
401 ct_ftp_info->seq_aft_nl[dir][0], 401 ct_ftp_info->seq_aft_nl[dir][0],
402 ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)", 402 ct_ftp_info->seq_aft_nl_num[dir] > 1 ? "" : "(UNSET)",
403 ct_ftp_info->seq_aft_nl[dir][1]); 403 ct_ftp_info->seq_aft_nl[dir][1]);
404 ret = NF_ACCEPT; 404 ret = NF_ACCEPT;
405 goto out_update_nl; 405 goto out_update_nl;
406 } 406 }
407 407
408 /* Initialize IP/IPv6 addr to expected address (it's not mentioned 408 /* Initialize IP/IPv6 addr to expected address (it's not mentioned
409 in EPSV responses) */ 409 in EPSV responses) */
410 cmd.l3num = nf_ct_l3num(ct); 410 cmd.l3num = nf_ct_l3num(ct);
411 memcpy(cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all, 411 memcpy(cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
412 sizeof(cmd.u3.all)); 412 sizeof(cmd.u3.all));
413 413
414 for (i = 0; i < ARRAY_SIZE(search[dir]); i++) { 414 for (i = 0; i < ARRAY_SIZE(search[dir]); i++) {
415 found = find_pattern(fb_ptr, datalen, 415 found = find_pattern(fb_ptr, datalen,
416 search[dir][i].pattern, 416 search[dir][i].pattern,
417 search[dir][i].plen, 417 search[dir][i].plen,
418 search[dir][i].skip, 418 search[dir][i].skip,
419 search[dir][i].term, 419 search[dir][i].term,
420 &matchoff, &matchlen, 420 &matchoff, &matchlen,
421 &cmd, 421 &cmd,
422 search[dir][i].getnum); 422 search[dir][i].getnum);
423 if (found) break; 423 if (found) break;
424 } 424 }
425 if (found == -1) { 425 if (found == -1) {
426 /* We don't usually drop packets. After all, this is 426 /* We don't usually drop packets. After all, this is
427 connection tracking, not packet filtering. 427 connection tracking, not packet filtering.
428 However, it is necessary for accurate tracking in 428 However, it is necessary for accurate tracking in
429 this case. */ 429 this case. */
430 pr_debug("conntrack_ftp: partial %s %u+%u\n", 430 pr_debug("conntrack_ftp: partial %s %u+%u\n",
431 search[dir][i].pattern, ntohl(th->seq), datalen); 431 search[dir][i].pattern, ntohl(th->seq), datalen);
432 ret = NF_DROP; 432 ret = NF_DROP;
433 goto out; 433 goto out;
434 } else if (found == 0) { /* No match */ 434 } else if (found == 0) { /* No match */
435 ret = NF_ACCEPT; 435 ret = NF_ACCEPT;
436 goto out_update_nl; 436 goto out_update_nl;
437 } 437 }
438 438
439 pr_debug("conntrack_ftp: match `%.*s' (%u bytes at %u)\n", 439 pr_debug("conntrack_ftp: match `%.*s' (%u bytes at %u)\n",
440 matchlen, fb_ptr + matchoff, 440 matchlen, fb_ptr + matchoff,
441 matchlen, ntohl(th->seq) + matchoff); 441 matchlen, ntohl(th->seq) + matchoff);
442 442
443 exp = nf_ct_expect_alloc(ct); 443 exp = nf_ct_expect_alloc(ct);
444 if (exp == NULL) { 444 if (exp == NULL) {
445 ret = NF_DROP; 445 ret = NF_DROP;
446 goto out; 446 goto out;
447 } 447 }
448 448
449 /* We refer to the reverse direction ("!dir") tuples here, 449 /* We refer to the reverse direction ("!dir") tuples here,
450 * because we're expecting something in the other direction. 450 * because we're expecting something in the other direction.
451 * Doesn't matter unless NAT is happening. */ 451 * Doesn't matter unless NAT is happening. */
452 daddr = &ct->tuplehash[!dir].tuple.dst.u3; 452 daddr = &ct->tuplehash[!dir].tuple.dst.u3;
453 453
454 /* Update the ftp info */ 454 /* Update the ftp info */
455 if ((cmd.l3num == nf_ct_l3num(ct)) && 455 if ((cmd.l3num == nf_ct_l3num(ct)) &&
456 memcmp(&cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all, 456 memcmp(&cmd.u3.all, &ct->tuplehash[dir].tuple.src.u3.all,
457 sizeof(cmd.u3.all))) { 457 sizeof(cmd.u3.all))) {
458 /* Enrico Scholz's passive FTP to partially RNAT'd ftp 458 /* Enrico Scholz's passive FTP to partially RNAT'd ftp
459 server: it really wants us to connect to a 459 server: it really wants us to connect to a
460 different IP address. Simply don't record it for 460 different IP address. Simply don't record it for
461 NAT. */ 461 NAT. */
462 if (cmd.l3num == PF_INET) { 462 if (cmd.l3num == PF_INET) {
463 pr_debug("conntrack_ftp: NOT RECORDING: %pI4 != %pI4\n", 463 pr_debug("conntrack_ftp: NOT RECORDING: %pI4 != %pI4\n",
464 &cmd.u3.ip, 464 &cmd.u3.ip,
465 &ct->tuplehash[dir].tuple.src.u3.ip); 465 &ct->tuplehash[dir].tuple.src.u3.ip);
466 } else { 466 } else {
467 pr_debug("conntrack_ftp: NOT RECORDING: %pI6 != %pI6\n", 467 pr_debug("conntrack_ftp: NOT RECORDING: %pI6 != %pI6\n",
468 cmd.u3.ip6, 468 cmd.u3.ip6,
469 ct->tuplehash[dir].tuple.src.u3.ip6); 469 ct->tuplehash[dir].tuple.src.u3.ip6);
470 } 470 }
471 471
472 /* Thanks to Cristiano Lincoln Mattos 472 /* Thanks to Cristiano Lincoln Mattos
473 <lincoln@cesar.org.br> for reporting this potential 473 <lincoln@cesar.org.br> for reporting this potential
474 problem (DMZ machines opening holes to internal 474 problem (DMZ machines opening holes to internal
475 networks, or the packet filter itself). */ 475 networks, or the packet filter itself). */
476 if (!loose) { 476 if (!loose) {
477 ret = NF_ACCEPT; 477 ret = NF_ACCEPT;
478 goto out_put_expect; 478 goto out_put_expect;
479 } 479 }
480 daddr = &cmd.u3; 480 daddr = &cmd.u3;
481 } 481 }
482 482
483 nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, cmd.l3num, 483 nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, cmd.l3num,
484 &ct->tuplehash[!dir].tuple.src.u3, daddr, 484 &ct->tuplehash[!dir].tuple.src.u3, daddr,
485 IPPROTO_TCP, NULL, &cmd.u.tcp.port); 485 IPPROTO_TCP, NULL, &cmd.u.tcp.port);
486 486
487 /* Now, NAT might want to mangle the packet, and register the 487 /* Now, NAT might want to mangle the packet, and register the
488 * (possibly changed) expectation itself. */ 488 * (possibly changed) expectation itself. */
489 nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook); 489 nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook);
490 if (nf_nat_ftp && ct->status & IPS_NAT_MASK) 490 if (nf_nat_ftp && ct->status & IPS_NAT_MASK)
491 ret = nf_nat_ftp(skb, ctinfo, search[dir][i].ftptype, 491 ret = nf_nat_ftp(skb, ctinfo, search[dir][i].ftptype,
492 matchoff, matchlen, exp); 492 matchoff, matchlen, exp);
493 else { 493 else {
494 /* Can't expect this? Best to drop packet now. */ 494 /* Can't expect this? Best to drop packet now. */
495 if (nf_ct_expect_related(exp) != 0) 495 if (nf_ct_expect_related(exp) != 0)
496 ret = NF_DROP; 496 ret = NF_DROP;
497 else 497 else
498 ret = NF_ACCEPT; 498 ret = NF_ACCEPT;
499 } 499 }
500 500
501 out_put_expect: 501 out_put_expect:
502 nf_ct_expect_put(exp); 502 nf_ct_expect_put(exp);
503 503
504 out_update_nl: 504 out_update_nl:
505 /* Now if this ends in \n, update ftp info. Seq may have been 505 /* Now if this ends in \n, update ftp info. Seq may have been
506 * adjusted by NAT code. */ 506 * adjusted by NAT code. */
507 if (ends_in_nl) 507 if (ends_in_nl)
508 update_nl_seq(ct, seq, ct_ftp_info, dir, skb); 508 update_nl_seq(ct, seq, ct_ftp_info, dir, skb);
509 out: 509 out:
510 spin_unlock_bh(&nf_ftp_lock); 510 spin_unlock_bh(&nf_ftp_lock);
511 return ret; 511 return ret;
512 } 512 }
513 513
514 static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly; 514 static struct nf_conntrack_helper ftp[MAX_PORTS][2] __read_mostly;
515 static char ftp_names[MAX_PORTS][2][sizeof("ftp-65535")] __read_mostly;
516 515
517 static const struct nf_conntrack_expect_policy ftp_exp_policy = { 516 static const struct nf_conntrack_expect_policy ftp_exp_policy = {
518 .max_expected = 1, 517 .max_expected = 1,
519 .timeout = 5 * 60, 518 .timeout = 5 * 60,
520 }; 519 };
521 520
522 /* don't make this __exit, since it's called from __init ! */ 521 /* don't make this __exit, since it's called from __init ! */
523 static void nf_conntrack_ftp_fini(void) 522 static void nf_conntrack_ftp_fini(void)
524 { 523 {
525 int i, j; 524 int i, j;
526 for (i = 0; i < ports_c; i++) { 525 for (i = 0; i < ports_c; i++) {
527 for (j = 0; j < 2; j++) { 526 for (j = 0; j < 2; j++) {
528 if (ftp[i][j].me == NULL) 527 if (ftp[i][j].me == NULL)
529 continue; 528 continue;
530 529
531 pr_debug("nf_ct_ftp: unregistering helper for pf: %d " 530 pr_debug("nf_ct_ftp: unregistering helper for pf: %d "
532 "port: %d\n", 531 "port: %d\n",
533 ftp[i][j].tuple.src.l3num, ports[i]); 532 ftp[i][j].tuple.src.l3num, ports[i]);
534 nf_conntrack_helper_unregister(&ftp[i][j]); 533 nf_conntrack_helper_unregister(&ftp[i][j]);
535 } 534 }
536 } 535 }
537 536
538 kfree(ftp_buffer); 537 kfree(ftp_buffer);
539 } 538 }
540 539
541 static int __init nf_conntrack_ftp_init(void) 540 static int __init nf_conntrack_ftp_init(void)
542 { 541 {
543 int i, j = -1, ret = 0; 542 int i, j = -1, ret = 0;
544 char *tmpname;
545 543
546 ftp_buffer = kmalloc(65536, GFP_KERNEL); 544 ftp_buffer = kmalloc(65536, GFP_KERNEL);
547 if (!ftp_buffer) 545 if (!ftp_buffer)
548 return -ENOMEM; 546 return -ENOMEM;
549 547
550 if (ports_c == 0) 548 if (ports_c == 0)
551 ports[ports_c++] = FTP_PORT; 549 ports[ports_c++] = FTP_PORT;
552 550
553 /* FIXME should be configurable whether IPv4 and IPv6 FTP connections 551 /* FIXME should be configurable whether IPv4 and IPv6 FTP connections
554 are tracked or not - YK */ 552 are tracked or not - YK */
555 for (i = 0; i < ports_c; i++) { 553 for (i = 0; i < ports_c; i++) {
556 ftp[i][0].tuple.src.l3num = PF_INET; 554 ftp[i][0].tuple.src.l3num = PF_INET;
557 ftp[i][1].tuple.src.l3num = PF_INET6; 555 ftp[i][1].tuple.src.l3num = PF_INET6;
558 for (j = 0; j < 2; j++) { 556 for (j = 0; j < 2; j++) {
559 ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]); 557 ftp[i][j].tuple.src.u.tcp.port = htons(ports[i]);
560 ftp[i][j].tuple.dst.protonum = IPPROTO_TCP; 558 ftp[i][j].tuple.dst.protonum = IPPROTO_TCP;
561 ftp[i][j].expect_policy = &ftp_exp_policy; 559 ftp[i][j].expect_policy = &ftp_exp_policy;
562 ftp[i][j].me = THIS_MODULE; 560 ftp[i][j].me = THIS_MODULE;
563 ftp[i][j].help = help; 561 ftp[i][j].help = help;
564 tmpname = &ftp_names[i][j][0];
565 if (ports[i] == FTP_PORT) 562 if (ports[i] == FTP_PORT)
566 sprintf(tmpname, "ftp"); 563 sprintf(ftp[i][j].name, "ftp");
567 else 564 else
568 sprintf(tmpname, "ftp-%d", ports[i]); 565 sprintf(ftp[i][j].name, "ftp-%d", ports[i]);
569 ftp[i][j].name = tmpname;
570 566
571 pr_debug("nf_ct_ftp: registering helper for pf: %d " 567 pr_debug("nf_ct_ftp: registering helper for pf: %d "
572 "port: %d\n", 568 "port: %d\n",
573 ftp[i][j].tuple.src.l3num, ports[i]); 569 ftp[i][j].tuple.src.l3num, ports[i]);
574 ret = nf_conntrack_helper_register(&ftp[i][j]); 570 ret = nf_conntrack_helper_register(&ftp[i][j]);
575 if (ret) { 571 if (ret) {
576 printk(KERN_ERR "nf_ct_ftp: failed to register" 572 printk(KERN_ERR "nf_ct_ftp: failed to register"
577 " helper for pf: %d port: %d\n", 573 " helper for pf: %d port: %d\n",
578 ftp[i][j].tuple.src.l3num, ports[i]); 574 ftp[i][j].tuple.src.l3num, ports[i]);
579 nf_conntrack_ftp_fini(); 575 nf_conntrack_ftp_fini();
580 return ret; 576 return ret;
581 } 577 }
582 } 578 }
583 } 579 }
584 580
585 return 0; 581 return 0;
586 } 582 }
587 583
588 module_init(nf_conntrack_ftp_init); 584 module_init(nf_conntrack_ftp_init);
589 module_exit(nf_conntrack_ftp_fini); 585 module_exit(nf_conntrack_ftp_fini);
590 586
net/netfilter/nf_conntrack_irc.c
1 /* IRC extension for IP connection tracking, Version 1.21 1 /* IRC extension for IP connection tracking, Version 1.21
2 * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org> 2 * (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
3 * based on RR's ip_conntrack_ftp.c 3 * based on RR's ip_conntrack_ftp.c
4 * 4 *
5 * This program is free software; you can redistribute it and/or 5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License 6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version. 8 * 2 of the License, or (at your option) any later version.
9 */ 9 */
10 10
11 #include <linux/module.h> 11 #include <linux/module.h>
12 #include <linux/moduleparam.h> 12 #include <linux/moduleparam.h>
13 #include <linux/skbuff.h> 13 #include <linux/skbuff.h>
14 #include <linux/in.h> 14 #include <linux/in.h>
15 #include <linux/ip.h> 15 #include <linux/ip.h>
16 #include <linux/tcp.h> 16 #include <linux/tcp.h>
17 #include <linux/netfilter.h> 17 #include <linux/netfilter.h>
18 #include <linux/slab.h> 18 #include <linux/slab.h>
19 19
20 #include <net/netfilter/nf_conntrack.h> 20 #include <net/netfilter/nf_conntrack.h>
21 #include <net/netfilter/nf_conntrack_expect.h> 21 #include <net/netfilter/nf_conntrack_expect.h>
22 #include <net/netfilter/nf_conntrack_helper.h> 22 #include <net/netfilter/nf_conntrack_helper.h>
23 #include <linux/netfilter/nf_conntrack_irc.h> 23 #include <linux/netfilter/nf_conntrack_irc.h>
24 24
25 #define MAX_PORTS 8 25 #define MAX_PORTS 8
26 static unsigned short ports[MAX_PORTS]; 26 static unsigned short ports[MAX_PORTS];
27 static unsigned int ports_c; 27 static unsigned int ports_c;
28 static unsigned int max_dcc_channels = 8; 28 static unsigned int max_dcc_channels = 8;
29 static unsigned int dcc_timeout __read_mostly = 300; 29 static unsigned int dcc_timeout __read_mostly = 300;
30 /* This is slow, but it's simple. --RR */ 30 /* This is slow, but it's simple. --RR */
31 static char *irc_buffer; 31 static char *irc_buffer;
32 static DEFINE_SPINLOCK(irc_buffer_lock); 32 static DEFINE_SPINLOCK(irc_buffer_lock);
33 33
34 unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb, 34 unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb,
35 enum ip_conntrack_info ctinfo, 35 enum ip_conntrack_info ctinfo,
36 unsigned int matchoff, 36 unsigned int matchoff,
37 unsigned int matchlen, 37 unsigned int matchlen,
38 struct nf_conntrack_expect *exp) __read_mostly; 38 struct nf_conntrack_expect *exp) __read_mostly;
39 EXPORT_SYMBOL_GPL(nf_nat_irc_hook); 39 EXPORT_SYMBOL_GPL(nf_nat_irc_hook);
40 40
41 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 41 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
42 MODULE_DESCRIPTION("IRC (DCC) connection tracking helper"); 42 MODULE_DESCRIPTION("IRC (DCC) connection tracking helper");
43 MODULE_LICENSE("GPL"); 43 MODULE_LICENSE("GPL");
44 MODULE_ALIAS("ip_conntrack_irc"); 44 MODULE_ALIAS("ip_conntrack_irc");
45 MODULE_ALIAS_NFCT_HELPER("irc"); 45 MODULE_ALIAS_NFCT_HELPER("irc");
46 46
47 module_param_array(ports, ushort, &ports_c, 0400); 47 module_param_array(ports, ushort, &ports_c, 0400);
48 MODULE_PARM_DESC(ports, "port numbers of IRC servers"); 48 MODULE_PARM_DESC(ports, "port numbers of IRC servers");
49 module_param(max_dcc_channels, uint, 0400); 49 module_param(max_dcc_channels, uint, 0400);
50 MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per " 50 MODULE_PARM_DESC(max_dcc_channels, "max number of expected DCC channels per "
51 "IRC session"); 51 "IRC session");
52 module_param(dcc_timeout, uint, 0400); 52 module_param(dcc_timeout, uint, 0400);
53 MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels"); 53 MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
54 54
55 static const char *const dccprotos[] = { 55 static const char *const dccprotos[] = {
56 "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " 56 "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT "
57 }; 57 };
58 58
59 #define MINMATCHLEN 5 59 #define MINMATCHLEN 5
60 60
61 /* tries to get the ip_addr and port out of a dcc command 61 /* tries to get the ip_addr and port out of a dcc command
62 * return value: -1 on failure, 0 on success 62 * return value: -1 on failure, 0 on success
63 * data pointer to first byte of DCC command data 63 * data pointer to first byte of DCC command data
64 * data_end pointer to last byte of dcc command data 64 * data_end pointer to last byte of dcc command data
65 * ip returns parsed ip of dcc command 65 * ip returns parsed ip of dcc command
66 * port returns parsed port of dcc command 66 * port returns parsed port of dcc command
67 * ad_beg_p returns pointer to first byte of addr data 67 * ad_beg_p returns pointer to first byte of addr data
68 * ad_end_p returns pointer to last byte of addr data 68 * ad_end_p returns pointer to last byte of addr data
69 */ 69 */
70 static int parse_dcc(char *data, const char *data_end, __be32 *ip, 70 static int parse_dcc(char *data, const char *data_end, __be32 *ip,
71 u_int16_t *port, char **ad_beg_p, char **ad_end_p) 71 u_int16_t *port, char **ad_beg_p, char **ad_end_p)
72 { 72 {
73 char *tmp; 73 char *tmp;
74 74
75 /* at least 12: "AAAAAAAA P\1\n" */ 75 /* at least 12: "AAAAAAAA P\1\n" */
76 while (*data++ != ' ') 76 while (*data++ != ' ')
77 if (data > data_end - 12) 77 if (data > data_end - 12)
78 return -1; 78 return -1;
79 79
80 /* Make sure we have a newline character within the packet boundaries 80 /* Make sure we have a newline character within the packet boundaries
81 * because simple_strtoul parses until the first invalid character. */ 81 * because simple_strtoul parses until the first invalid character. */
82 for (tmp = data; tmp <= data_end; tmp++) 82 for (tmp = data; tmp <= data_end; tmp++)
83 if (*tmp == '\n') 83 if (*tmp == '\n')
84 break; 84 break;
85 if (tmp > data_end || *tmp != '\n') 85 if (tmp > data_end || *tmp != '\n')
86 return -1; 86 return -1;
87 87
88 *ad_beg_p = data; 88 *ad_beg_p = data;
89 *ip = cpu_to_be32(simple_strtoul(data, &data, 10)); 89 *ip = cpu_to_be32(simple_strtoul(data, &data, 10));
90 90
91 /* skip blanks between ip and port */ 91 /* skip blanks between ip and port */
92 while (*data == ' ') { 92 while (*data == ' ') {
93 if (data >= data_end) 93 if (data >= data_end)
94 return -1; 94 return -1;
95 data++; 95 data++;
96 } 96 }
97 97
98 *port = simple_strtoul(data, &data, 10); 98 *port = simple_strtoul(data, &data, 10);
99 *ad_end_p = data; 99 *ad_end_p = data;
100 100
101 return 0; 101 return 0;
102 } 102 }
103 103
104 static int help(struct sk_buff *skb, unsigned int protoff, 104 static int help(struct sk_buff *skb, unsigned int protoff,
105 struct nf_conn *ct, enum ip_conntrack_info ctinfo) 105 struct nf_conn *ct, enum ip_conntrack_info ctinfo)
106 { 106 {
107 unsigned int dataoff; 107 unsigned int dataoff;
108 const struct iphdr *iph; 108 const struct iphdr *iph;
109 const struct tcphdr *th; 109 const struct tcphdr *th;
110 struct tcphdr _tcph; 110 struct tcphdr _tcph;
111 const char *data_limit; 111 const char *data_limit;
112 char *data, *ib_ptr; 112 char *data, *ib_ptr;
113 int dir = CTINFO2DIR(ctinfo); 113 int dir = CTINFO2DIR(ctinfo);
114 struct nf_conntrack_expect *exp; 114 struct nf_conntrack_expect *exp;
115 struct nf_conntrack_tuple *tuple; 115 struct nf_conntrack_tuple *tuple;
116 __be32 dcc_ip; 116 __be32 dcc_ip;
117 u_int16_t dcc_port; 117 u_int16_t dcc_port;
118 __be16 port; 118 __be16 port;
119 int i, ret = NF_ACCEPT; 119 int i, ret = NF_ACCEPT;
120 char *addr_beg_p, *addr_end_p; 120 char *addr_beg_p, *addr_end_p;
121 typeof(nf_nat_irc_hook) nf_nat_irc; 121 typeof(nf_nat_irc_hook) nf_nat_irc;
122 122
123 /* If packet is coming from IRC server */ 123 /* If packet is coming from IRC server */
124 if (dir == IP_CT_DIR_REPLY) 124 if (dir == IP_CT_DIR_REPLY)
125 return NF_ACCEPT; 125 return NF_ACCEPT;
126 126
127 /* Until there's been traffic both ways, don't look in packets. */ 127 /* Until there's been traffic both ways, don't look in packets. */
128 if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY) 128 if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED_REPLY)
129 return NF_ACCEPT; 129 return NF_ACCEPT;
130 130
131 /* Not a full tcp header? */ 131 /* Not a full tcp header? */
132 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); 132 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
133 if (th == NULL) 133 if (th == NULL)
134 return NF_ACCEPT; 134 return NF_ACCEPT;
135 135
136 /* No data? */ 136 /* No data? */
137 dataoff = protoff + th->doff*4; 137 dataoff = protoff + th->doff*4;
138 if (dataoff >= skb->len) 138 if (dataoff >= skb->len)
139 return NF_ACCEPT; 139 return NF_ACCEPT;
140 140
141 spin_lock_bh(&irc_buffer_lock); 141 spin_lock_bh(&irc_buffer_lock);
142 ib_ptr = skb_header_pointer(skb, dataoff, skb->len - dataoff, 142 ib_ptr = skb_header_pointer(skb, dataoff, skb->len - dataoff,
143 irc_buffer); 143 irc_buffer);
144 BUG_ON(ib_ptr == NULL); 144 BUG_ON(ib_ptr == NULL);
145 145
146 data = ib_ptr; 146 data = ib_ptr;
147 data_limit = ib_ptr + skb->len - dataoff; 147 data_limit = ib_ptr + skb->len - dataoff;
148 148
149 /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24 149 /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24
150 * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */ 150 * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
151 while (data < data_limit - (19 + MINMATCHLEN)) { 151 while (data < data_limit - (19 + MINMATCHLEN)) {
152 if (memcmp(data, "\1DCC ", 5)) { 152 if (memcmp(data, "\1DCC ", 5)) {
153 data++; 153 data++;
154 continue; 154 continue;
155 } 155 }
156 data += 5; 156 data += 5;
157 /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */ 157 /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
158 158
159 iph = ip_hdr(skb); 159 iph = ip_hdr(skb);
160 pr_debug("DCC found in master %pI4:%u %pI4:%u\n", 160 pr_debug("DCC found in master %pI4:%u %pI4:%u\n",
161 &iph->saddr, ntohs(th->source), 161 &iph->saddr, ntohs(th->source),
162 &iph->daddr, ntohs(th->dest)); 162 &iph->daddr, ntohs(th->dest));
163 163
164 for (i = 0; i < ARRAY_SIZE(dccprotos); i++) { 164 for (i = 0; i < ARRAY_SIZE(dccprotos); i++) {
165 if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) { 165 if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) {
166 /* no match */ 166 /* no match */
167 continue; 167 continue;
168 } 168 }
169 data += strlen(dccprotos[i]); 169 data += strlen(dccprotos[i]);
170 pr_debug("DCC %s detected\n", dccprotos[i]); 170 pr_debug("DCC %s detected\n", dccprotos[i]);
171 171
172 /* we have at least 172 /* we have at least
173 * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid 173 * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
174 * data left (== 14/13 bytes) */ 174 * data left (== 14/13 bytes) */
175 if (parse_dcc(data, data_limit, &dcc_ip, 175 if (parse_dcc(data, data_limit, &dcc_ip,
176 &dcc_port, &addr_beg_p, &addr_end_p)) { 176 &dcc_port, &addr_beg_p, &addr_end_p)) {
177 pr_debug("unable to parse dcc command\n"); 177 pr_debug("unable to parse dcc command\n");
178 continue; 178 continue;
179 } 179 }
180 180
181 pr_debug("DCC bound ip/port: %pI4:%u\n", 181 pr_debug("DCC bound ip/port: %pI4:%u\n",
182 &dcc_ip, dcc_port); 182 &dcc_ip, dcc_port);
183 183
184 /* dcc_ip can be the internal OR external (NAT'ed) IP */ 184 /* dcc_ip can be the internal OR external (NAT'ed) IP */
185 tuple = &ct->tuplehash[dir].tuple; 185 tuple = &ct->tuplehash[dir].tuple;
186 if (tuple->src.u3.ip != dcc_ip && 186 if (tuple->src.u3.ip != dcc_ip &&
187 tuple->dst.u3.ip != dcc_ip) { 187 tuple->dst.u3.ip != dcc_ip) {
188 net_warn_ratelimited("Forged DCC command from %pI4: %pI4:%u\n", 188 net_warn_ratelimited("Forged DCC command from %pI4: %pI4:%u\n",
189 &tuple->src.u3.ip, 189 &tuple->src.u3.ip,
190 &dcc_ip, dcc_port); 190 &dcc_ip, dcc_port);
191 continue; 191 continue;
192 } 192 }
193 193
194 exp = nf_ct_expect_alloc(ct); 194 exp = nf_ct_expect_alloc(ct);
195 if (exp == NULL) { 195 if (exp == NULL) {
196 ret = NF_DROP; 196 ret = NF_DROP;
197 goto out; 197 goto out;
198 } 198 }
199 tuple = &ct->tuplehash[!dir].tuple; 199 tuple = &ct->tuplehash[!dir].tuple;
200 port = htons(dcc_port); 200 port = htons(dcc_port);
201 nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, 201 nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
202 tuple->src.l3num, 202 tuple->src.l3num,
203 NULL, &tuple->dst.u3, 203 NULL, &tuple->dst.u3,
204 IPPROTO_TCP, NULL, &port); 204 IPPROTO_TCP, NULL, &port);
205 205
206 nf_nat_irc = rcu_dereference(nf_nat_irc_hook); 206 nf_nat_irc = rcu_dereference(nf_nat_irc_hook);
207 if (nf_nat_irc && ct->status & IPS_NAT_MASK) 207 if (nf_nat_irc && ct->status & IPS_NAT_MASK)
208 ret = nf_nat_irc(skb, ctinfo, 208 ret = nf_nat_irc(skb, ctinfo,
209 addr_beg_p - ib_ptr, 209 addr_beg_p - ib_ptr,
210 addr_end_p - addr_beg_p, 210 addr_end_p - addr_beg_p,
211 exp); 211 exp);
212 else if (nf_ct_expect_related(exp) != 0) 212 else if (nf_ct_expect_related(exp) != 0)
213 ret = NF_DROP; 213 ret = NF_DROP;
214 nf_ct_expect_put(exp); 214 nf_ct_expect_put(exp);
215 goto out; 215 goto out;
216 } 216 }
217 } 217 }
218 out: 218 out:
219 spin_unlock_bh(&irc_buffer_lock); 219 spin_unlock_bh(&irc_buffer_lock);
220 return ret; 220 return ret;
221 } 221 }
222 222
223 static struct nf_conntrack_helper irc[MAX_PORTS] __read_mostly; 223 static struct nf_conntrack_helper irc[MAX_PORTS] __read_mostly;
224 static char irc_names[MAX_PORTS][sizeof("irc-65535")] __read_mostly;
225 static struct nf_conntrack_expect_policy irc_exp_policy; 224 static struct nf_conntrack_expect_policy irc_exp_policy;
226 225
227 static void nf_conntrack_irc_fini(void); 226 static void nf_conntrack_irc_fini(void);
228 227
229 static int __init nf_conntrack_irc_init(void) 228 static int __init nf_conntrack_irc_init(void)
230 { 229 {
231 int i, ret; 230 int i, ret;
232 char *tmpname;
233 231
234 if (max_dcc_channels < 1) { 232 if (max_dcc_channels < 1) {
235 printk(KERN_ERR "nf_ct_irc: max_dcc_channels must not be zero\n"); 233 printk(KERN_ERR "nf_ct_irc: max_dcc_channels must not be zero\n");
236 return -EINVAL; 234 return -EINVAL;
237 } 235 }
238 236
239 irc_exp_policy.max_expected = max_dcc_channels; 237 irc_exp_policy.max_expected = max_dcc_channels;
240 irc_exp_policy.timeout = dcc_timeout; 238 irc_exp_policy.timeout = dcc_timeout;
241 239
242 irc_buffer = kmalloc(65536, GFP_KERNEL); 240 irc_buffer = kmalloc(65536, GFP_KERNEL);
243 if (!irc_buffer) 241 if (!irc_buffer)
244 return -ENOMEM; 242 return -ENOMEM;
245 243
246 /* If no port given, default to standard irc port */ 244 /* If no port given, default to standard irc port */
247 if (ports_c == 0) 245 if (ports_c == 0)
248 ports[ports_c++] = IRC_PORT; 246 ports[ports_c++] = IRC_PORT;
249 247
250 for (i = 0; i < ports_c; i++) { 248 for (i = 0; i < ports_c; i++) {
251 irc[i].tuple.src.l3num = AF_INET; 249 irc[i].tuple.src.l3num = AF_INET;
252 irc[i].tuple.src.u.tcp.port = htons(ports[i]); 250 irc[i].tuple.src.u.tcp.port = htons(ports[i]);
253 irc[i].tuple.dst.protonum = IPPROTO_TCP; 251 irc[i].tuple.dst.protonum = IPPROTO_TCP;
254 irc[i].expect_policy = &irc_exp_policy; 252 irc[i].expect_policy = &irc_exp_policy;
255 irc[i].me = THIS_MODULE; 253 irc[i].me = THIS_MODULE;
256 irc[i].help = help; 254 irc[i].help = help;
257 255
258 tmpname = &irc_names[i][0];
259 if (ports[i] == IRC_PORT) 256 if (ports[i] == IRC_PORT)
260 sprintf(tmpname, "irc"); 257 sprintf(irc[i].name, "irc");
261 else 258 else
262 sprintf(tmpname, "irc-%u", i); 259 sprintf(irc[i].name, "irc-%u", i);
263 irc[i].name = tmpname;
264 260
265 ret = nf_conntrack_helper_register(&irc[i]); 261 ret = nf_conntrack_helper_register(&irc[i]);
266 if (ret) { 262 if (ret) {
267 printk(KERN_ERR "nf_ct_irc: failed to register helper " 263 printk(KERN_ERR "nf_ct_irc: failed to register helper "
268 "for pf: %u port: %u\n", 264 "for pf: %u port: %u\n",
269 irc[i].tuple.src.l3num, ports[i]); 265 irc[i].tuple.src.l3num, ports[i]);
270 nf_conntrack_irc_fini(); 266 nf_conntrack_irc_fini();
271 return ret; 267 return ret;
272 } 268 }
273 } 269 }
274 return 0; 270 return 0;
275 } 271 }
276 272
277 /* This function is intentionally _NOT_ defined as __exit, because 273 /* This function is intentionally _NOT_ defined as __exit, because
278 * it is needed by the init function */ 274 * it is needed by the init function */
279 static void nf_conntrack_irc_fini(void) 275 static void nf_conntrack_irc_fini(void)
280 { 276 {
281 int i; 277 int i;
282 278
283 for (i = 0; i < ports_c; i++) 279 for (i = 0; i < ports_c; i++)
284 nf_conntrack_helper_unregister(&irc[i]); 280 nf_conntrack_helper_unregister(&irc[i]);
285 kfree(irc_buffer); 281 kfree(irc_buffer);
286 } 282 }
287 283
288 module_init(nf_conntrack_irc_init); 284 module_init(nf_conntrack_irc_init);
289 module_exit(nf_conntrack_irc_fini); 285 module_exit(nf_conntrack_irc_fini);
290 286
net/netfilter/nf_conntrack_sane.c
1 /* SANE connection tracking helper 1 /* SANE connection tracking helper
2 * (SANE = Scanner Access Now Easy) 2 * (SANE = Scanner Access Now Easy)
3 * For documentation about the SANE network protocol see 3 * For documentation about the SANE network protocol see
4 * http://www.sane-project.org/html/doc015.html 4 * http://www.sane-project.org/html/doc015.html
5 */ 5 */
6 6
7 /* Copyright (C) 2007 Red Hat, Inc. 7 /* Copyright (C) 2007 Red Hat, Inc.
8 * Author: Michal Schmidt <mschmidt@redhat.com> 8 * Author: Michal Schmidt <mschmidt@redhat.com>
9 * Based on the FTP conntrack helper (net/netfilter/nf_conntrack_ftp.c): 9 * Based on the FTP conntrack helper (net/netfilter/nf_conntrack_ftp.c):
10 * (C) 1999-2001 Paul `Rusty' Russell 10 * (C) 1999-2001 Paul `Rusty' Russell
11 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> 11 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
12 * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org> 12 * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
13 * (C) 2003 Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> 13 * (C) 2003 Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
14 * 14 *
15 * This program is free software; you can redistribute it and/or modify 15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2 as 16 * it under the terms of the GNU General Public License version 2 as
17 * published by the Free Software Foundation. 17 * published by the Free Software Foundation.
18 */ 18 */
19 19
20 #include <linux/module.h> 20 #include <linux/module.h>
21 #include <linux/moduleparam.h> 21 #include <linux/moduleparam.h>
22 #include <linux/netfilter.h> 22 #include <linux/netfilter.h>
23 #include <linux/slab.h> 23 #include <linux/slab.h>
24 #include <linux/in.h> 24 #include <linux/in.h>
25 #include <linux/tcp.h> 25 #include <linux/tcp.h>
26 #include <net/netfilter/nf_conntrack.h> 26 #include <net/netfilter/nf_conntrack.h>
27 #include <net/netfilter/nf_conntrack_helper.h> 27 #include <net/netfilter/nf_conntrack_helper.h>
28 #include <net/netfilter/nf_conntrack_expect.h> 28 #include <net/netfilter/nf_conntrack_expect.h>
29 #include <linux/netfilter/nf_conntrack_sane.h> 29 #include <linux/netfilter/nf_conntrack_sane.h>
30 30
31 MODULE_LICENSE("GPL"); 31 MODULE_LICENSE("GPL");
32 MODULE_AUTHOR("Michal Schmidt <mschmidt@redhat.com>"); 32 MODULE_AUTHOR("Michal Schmidt <mschmidt@redhat.com>");
33 MODULE_DESCRIPTION("SANE connection tracking helper"); 33 MODULE_DESCRIPTION("SANE connection tracking helper");
34 MODULE_ALIAS_NFCT_HELPER("sane"); 34 MODULE_ALIAS_NFCT_HELPER("sane");
35 35
36 static char *sane_buffer; 36 static char *sane_buffer;
37 37
38 static DEFINE_SPINLOCK(nf_sane_lock); 38 static DEFINE_SPINLOCK(nf_sane_lock);
39 39
40 #define MAX_PORTS 8 40 #define MAX_PORTS 8
41 static u_int16_t ports[MAX_PORTS]; 41 static u_int16_t ports[MAX_PORTS];
42 static unsigned int ports_c; 42 static unsigned int ports_c;
43 module_param_array(ports, ushort, &ports_c, 0400); 43 module_param_array(ports, ushort, &ports_c, 0400);
44 44
45 struct sane_request { 45 struct sane_request {
46 __be32 RPC_code; 46 __be32 RPC_code;
47 #define SANE_NET_START 7 /* RPC code */ 47 #define SANE_NET_START 7 /* RPC code */
48 48
49 __be32 handle; 49 __be32 handle;
50 }; 50 };
51 51
52 struct sane_reply_net_start { 52 struct sane_reply_net_start {
53 __be32 status; 53 __be32 status;
54 #define SANE_STATUS_SUCCESS 0 54 #define SANE_STATUS_SUCCESS 0
55 55
56 __be16 zero; 56 __be16 zero;
57 __be16 port; 57 __be16 port;
58 /* other fields aren't interesting for conntrack */ 58 /* other fields aren't interesting for conntrack */
59 }; 59 };
60 60
61 static int help(struct sk_buff *skb, 61 static int help(struct sk_buff *skb,
62 unsigned int protoff, 62 unsigned int protoff,
63 struct nf_conn *ct, 63 struct nf_conn *ct,
64 enum ip_conntrack_info ctinfo) 64 enum ip_conntrack_info ctinfo)
65 { 65 {
66 unsigned int dataoff, datalen; 66 unsigned int dataoff, datalen;
67 const struct tcphdr *th; 67 const struct tcphdr *th;
68 struct tcphdr _tcph; 68 struct tcphdr _tcph;
69 void *sb_ptr; 69 void *sb_ptr;
70 int ret = NF_ACCEPT; 70 int ret = NF_ACCEPT;
71 int dir = CTINFO2DIR(ctinfo); 71 int dir = CTINFO2DIR(ctinfo);
72 struct nf_ct_sane_master *ct_sane_info; 72 struct nf_ct_sane_master *ct_sane_info;
73 struct nf_conntrack_expect *exp; 73 struct nf_conntrack_expect *exp;
74 struct nf_conntrack_tuple *tuple; 74 struct nf_conntrack_tuple *tuple;
75 struct sane_request *req; 75 struct sane_request *req;
76 struct sane_reply_net_start *reply; 76 struct sane_reply_net_start *reply;
77 77
78 ct_sane_info = &nfct_help(ct)->help.ct_sane_info; 78 ct_sane_info = &nfct_help(ct)->help.ct_sane_info;
79 /* Until there's been traffic both ways, don't look in packets. */ 79 /* Until there's been traffic both ways, don't look in packets. */
80 if (ctinfo != IP_CT_ESTABLISHED && 80 if (ctinfo != IP_CT_ESTABLISHED &&
81 ctinfo != IP_CT_ESTABLISHED_REPLY) 81 ctinfo != IP_CT_ESTABLISHED_REPLY)
82 return NF_ACCEPT; 82 return NF_ACCEPT;
83 83
84 /* Not a full tcp header? */ 84 /* Not a full tcp header? */
85 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); 85 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
86 if (th == NULL) 86 if (th == NULL)
87 return NF_ACCEPT; 87 return NF_ACCEPT;
88 88
89 /* No data? */ 89 /* No data? */
90 dataoff = protoff + th->doff * 4; 90 dataoff = protoff + th->doff * 4;
91 if (dataoff >= skb->len) 91 if (dataoff >= skb->len)
92 return NF_ACCEPT; 92 return NF_ACCEPT;
93 93
94 datalen = skb->len - dataoff; 94 datalen = skb->len - dataoff;
95 95
96 spin_lock_bh(&nf_sane_lock); 96 spin_lock_bh(&nf_sane_lock);
97 sb_ptr = skb_header_pointer(skb, dataoff, datalen, sane_buffer); 97 sb_ptr = skb_header_pointer(skb, dataoff, datalen, sane_buffer);
98 BUG_ON(sb_ptr == NULL); 98 BUG_ON(sb_ptr == NULL);
99 99
100 if (dir == IP_CT_DIR_ORIGINAL) { 100 if (dir == IP_CT_DIR_ORIGINAL) {
101 if (datalen != sizeof(struct sane_request)) 101 if (datalen != sizeof(struct sane_request))
102 goto out; 102 goto out;
103 103
104 req = sb_ptr; 104 req = sb_ptr;
105 if (req->RPC_code != htonl(SANE_NET_START)) { 105 if (req->RPC_code != htonl(SANE_NET_START)) {
106 /* Not an interesting command */ 106 /* Not an interesting command */
107 ct_sane_info->state = SANE_STATE_NORMAL; 107 ct_sane_info->state = SANE_STATE_NORMAL;
108 goto out; 108 goto out;
109 } 109 }
110 110
111 /* We're interested in the next reply */ 111 /* We're interested in the next reply */
112 ct_sane_info->state = SANE_STATE_START_REQUESTED; 112 ct_sane_info->state = SANE_STATE_START_REQUESTED;
113 goto out; 113 goto out;
114 } 114 }
115 115
116 /* Is it a reply to an uninteresting command? */ 116 /* Is it a reply to an uninteresting command? */
117 if (ct_sane_info->state != SANE_STATE_START_REQUESTED) 117 if (ct_sane_info->state != SANE_STATE_START_REQUESTED)
118 goto out; 118 goto out;
119 119
120 /* It's a reply to SANE_NET_START. */ 120 /* It's a reply to SANE_NET_START. */
121 ct_sane_info->state = SANE_STATE_NORMAL; 121 ct_sane_info->state = SANE_STATE_NORMAL;
122 122
123 if (datalen < sizeof(struct sane_reply_net_start)) { 123 if (datalen < sizeof(struct sane_reply_net_start)) {
124 pr_debug("nf_ct_sane: NET_START reply too short\n"); 124 pr_debug("nf_ct_sane: NET_START reply too short\n");
125 goto out; 125 goto out;
126 } 126 }
127 127
128 reply = sb_ptr; 128 reply = sb_ptr;
129 if (reply->status != htonl(SANE_STATUS_SUCCESS)) { 129 if (reply->status != htonl(SANE_STATUS_SUCCESS)) {
130 /* saned refused the command */ 130 /* saned refused the command */
131 pr_debug("nf_ct_sane: unsuccessful SANE_STATUS = %u\n", 131 pr_debug("nf_ct_sane: unsuccessful SANE_STATUS = %u\n",
132 ntohl(reply->status)); 132 ntohl(reply->status));
133 goto out; 133 goto out;
134 } 134 }
135 135
136 /* Invalid saned reply? Ignore it. */ 136 /* Invalid saned reply? Ignore it. */
137 if (reply->zero != 0) 137 if (reply->zero != 0)
138 goto out; 138 goto out;
139 139
140 exp = nf_ct_expect_alloc(ct); 140 exp = nf_ct_expect_alloc(ct);
141 if (exp == NULL) { 141 if (exp == NULL) {
142 ret = NF_DROP; 142 ret = NF_DROP;
143 goto out; 143 goto out;
144 } 144 }
145 145
146 tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; 146 tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
147 nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct), 147 nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
148 &tuple->src.u3, &tuple->dst.u3, 148 &tuple->src.u3, &tuple->dst.u3,
149 IPPROTO_TCP, NULL, &reply->port); 149 IPPROTO_TCP, NULL, &reply->port);
150 150
151 pr_debug("nf_ct_sane: expect: "); 151 pr_debug("nf_ct_sane: expect: ");
152 nf_ct_dump_tuple(&exp->tuple); 152 nf_ct_dump_tuple(&exp->tuple);
153 153
154 /* Can't expect this? Best to drop packet now. */ 154 /* Can't expect this? Best to drop packet now. */
155 if (nf_ct_expect_related(exp) != 0) 155 if (nf_ct_expect_related(exp) != 0)
156 ret = NF_DROP; 156 ret = NF_DROP;
157 157
158 nf_ct_expect_put(exp); 158 nf_ct_expect_put(exp);
159 159
160 out: 160 out:
161 spin_unlock_bh(&nf_sane_lock); 161 spin_unlock_bh(&nf_sane_lock);
162 return ret; 162 return ret;
163 } 163 }
164 164
165 static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly; 165 static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly;
166 static char sane_names[MAX_PORTS][2][sizeof("sane-65535")] __read_mostly;
167 166
168 static const struct nf_conntrack_expect_policy sane_exp_policy = { 167 static const struct nf_conntrack_expect_policy sane_exp_policy = {
169 .max_expected = 1, 168 .max_expected = 1,
170 .timeout = 5 * 60, 169 .timeout = 5 * 60,
171 }; 170 };
172 171
173 /* don't make this __exit, since it's called from __init ! */ 172 /* don't make this __exit, since it's called from __init ! */
174 static void nf_conntrack_sane_fini(void) 173 static void nf_conntrack_sane_fini(void)
175 { 174 {
176 int i, j; 175 int i, j;
177 176
178 for (i = 0; i < ports_c; i++) { 177 for (i = 0; i < ports_c; i++) {
179 for (j = 0; j < 2; j++) { 178 for (j = 0; j < 2; j++) {
180 pr_debug("nf_ct_sane: unregistering helper for pf: %d " 179 pr_debug("nf_ct_sane: unregistering helper for pf: %d "
181 "port: %d\n", 180 "port: %d\n",
182 sane[i][j].tuple.src.l3num, ports[i]); 181 sane[i][j].tuple.src.l3num, ports[i]);
183 nf_conntrack_helper_unregister(&sane[i][j]); 182 nf_conntrack_helper_unregister(&sane[i][j]);
184 } 183 }
185 } 184 }
186 185
187 kfree(sane_buffer); 186 kfree(sane_buffer);
188 } 187 }
189 188
190 static int __init nf_conntrack_sane_init(void) 189 static int __init nf_conntrack_sane_init(void)
191 { 190 {
192 int i, j = -1, ret = 0; 191 int i, j = -1, ret = 0;
193 char *tmpname;
194 192
195 sane_buffer = kmalloc(65536, GFP_KERNEL); 193 sane_buffer = kmalloc(65536, GFP_KERNEL);
196 if (!sane_buffer) 194 if (!sane_buffer)
197 return -ENOMEM; 195 return -ENOMEM;
198 196
199 if (ports_c == 0) 197 if (ports_c == 0)
200 ports[ports_c++] = SANE_PORT; 198 ports[ports_c++] = SANE_PORT;
201 199
202 /* FIXME should be configurable whether IPv4 and IPv6 connections 200 /* FIXME should be configurable whether IPv4 and IPv6 connections
203 are tracked or not - YK */ 201 are tracked or not - YK */
204 for (i = 0; i < ports_c; i++) { 202 for (i = 0; i < ports_c; i++) {
205 sane[i][0].tuple.src.l3num = PF_INET; 203 sane[i][0].tuple.src.l3num = PF_INET;
206 sane[i][1].tuple.src.l3num = PF_INET6; 204 sane[i][1].tuple.src.l3num = PF_INET6;
207 for (j = 0; j < 2; j++) { 205 for (j = 0; j < 2; j++) {
208 sane[i][j].tuple.src.u.tcp.port = htons(ports[i]); 206 sane[i][j].tuple.src.u.tcp.port = htons(ports[i]);
209 sane[i][j].tuple.dst.protonum = IPPROTO_TCP; 207 sane[i][j].tuple.dst.protonum = IPPROTO_TCP;
210 sane[i][j].expect_policy = &sane_exp_policy; 208 sane[i][j].expect_policy = &sane_exp_policy;
211 sane[i][j].me = THIS_MODULE; 209 sane[i][j].me = THIS_MODULE;
212 sane[i][j].help = help; 210 sane[i][j].help = help;
213 tmpname = &sane_names[i][j][0];
214 if (ports[i] == SANE_PORT) 211 if (ports[i] == SANE_PORT)
215 sprintf(tmpname, "sane"); 212 sprintf(sane[i][j].name, "sane");
216 else 213 else
217 sprintf(tmpname, "sane-%d", ports[i]); 214 sprintf(sane[i][j].name, "sane-%d", ports[i]);
218 sane[i][j].name = tmpname;
219 215
220 pr_debug("nf_ct_sane: registering helper for pf: %d " 216 pr_debug("nf_ct_sane: registering helper for pf: %d "
221 "port: %d\n", 217 "port: %d\n",
222 sane[i][j].tuple.src.l3num, ports[i]); 218 sane[i][j].tuple.src.l3num, ports[i]);
223 ret = nf_conntrack_helper_register(&sane[i][j]); 219 ret = nf_conntrack_helper_register(&sane[i][j]);
224 if (ret) { 220 if (ret) {
225 printk(KERN_ERR "nf_ct_sane: failed to " 221 printk(KERN_ERR "nf_ct_sane: failed to "
226 "register helper for pf: %d port: %d\n", 222 "register helper for pf: %d port: %d\n",
227 sane[i][j].tuple.src.l3num, ports[i]); 223 sane[i][j].tuple.src.l3num, ports[i]);
228 nf_conntrack_sane_fini(); 224 nf_conntrack_sane_fini();
229 return ret; 225 return ret;
230 } 226 }
231 } 227 }
232 } 228 }
233 229
234 return 0; 230 return 0;
235 } 231 }
236 232
237 module_init(nf_conntrack_sane_init); 233 module_init(nf_conntrack_sane_init);
238 module_exit(nf_conntrack_sane_fini); 234 module_exit(nf_conntrack_sane_fini);
239 235
net/netfilter/nf_conntrack_sip.c
1 /* SIP extension for IP connection tracking. 1 /* SIP extension for IP connection tracking.
2 * 2 *
3 * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar> 3 * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
4 * based on RR's ip_conntrack_ftp.c and other modules. 4 * based on RR's ip_conntrack_ftp.c and other modules.
5 * (C) 2007 United Security Providers 5 * (C) 2007 United Security Providers
6 * (C) 2007, 2008 Patrick McHardy <kaber@trash.net> 6 * (C) 2007, 2008 Patrick McHardy <kaber@trash.net>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
11 */ 11 */
12 12
13 #include <linux/module.h> 13 #include <linux/module.h>
14 #include <linux/ctype.h> 14 #include <linux/ctype.h>
15 #include <linux/skbuff.h> 15 #include <linux/skbuff.h>
16 #include <linux/inet.h> 16 #include <linux/inet.h>
17 #include <linux/in.h> 17 #include <linux/in.h>
18 #include <linux/udp.h> 18 #include <linux/udp.h>
19 #include <linux/tcp.h> 19 #include <linux/tcp.h>
20 #include <linux/netfilter.h> 20 #include <linux/netfilter.h>
21 21
22 #include <net/netfilter/nf_conntrack.h> 22 #include <net/netfilter/nf_conntrack.h>
23 #include <net/netfilter/nf_conntrack_core.h> 23 #include <net/netfilter/nf_conntrack_core.h>
24 #include <net/netfilter/nf_conntrack_expect.h> 24 #include <net/netfilter/nf_conntrack_expect.h>
25 #include <net/netfilter/nf_conntrack_helper.h> 25 #include <net/netfilter/nf_conntrack_helper.h>
26 #include <net/netfilter/nf_conntrack_zones.h> 26 #include <net/netfilter/nf_conntrack_zones.h>
27 #include <linux/netfilter/nf_conntrack_sip.h> 27 #include <linux/netfilter/nf_conntrack_sip.h>
28 28
29 MODULE_LICENSE("GPL"); 29 MODULE_LICENSE("GPL");
30 MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>"); 30 MODULE_AUTHOR("Christian Hentschel <chentschel@arnet.com.ar>");
31 MODULE_DESCRIPTION("SIP connection tracking helper"); 31 MODULE_DESCRIPTION("SIP connection tracking helper");
32 MODULE_ALIAS("ip_conntrack_sip"); 32 MODULE_ALIAS("ip_conntrack_sip");
33 MODULE_ALIAS_NFCT_HELPER("sip"); 33 MODULE_ALIAS_NFCT_HELPER("sip");
34 34
35 #define MAX_PORTS 8 35 #define MAX_PORTS 8
36 static unsigned short ports[MAX_PORTS]; 36 static unsigned short ports[MAX_PORTS];
37 static unsigned int ports_c; 37 static unsigned int ports_c;
38 module_param_array(ports, ushort, &ports_c, 0400); 38 module_param_array(ports, ushort, &ports_c, 0400);
39 MODULE_PARM_DESC(ports, "port numbers of SIP servers"); 39 MODULE_PARM_DESC(ports, "port numbers of SIP servers");
40 40
41 static unsigned int sip_timeout __read_mostly = SIP_TIMEOUT; 41 static unsigned int sip_timeout __read_mostly = SIP_TIMEOUT;
42 module_param(sip_timeout, uint, 0600); 42 module_param(sip_timeout, uint, 0600);
43 MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session"); 43 MODULE_PARM_DESC(sip_timeout, "timeout for the master SIP session");
44 44
45 static int sip_direct_signalling __read_mostly = 1; 45 static int sip_direct_signalling __read_mostly = 1;
46 module_param(sip_direct_signalling, int, 0600); 46 module_param(sip_direct_signalling, int, 0600);
47 MODULE_PARM_DESC(sip_direct_signalling, "expect incoming calls from registrar " 47 MODULE_PARM_DESC(sip_direct_signalling, "expect incoming calls from registrar "
48 "only (default 1)"); 48 "only (default 1)");
49 49
50 static int sip_direct_media __read_mostly = 1; 50 static int sip_direct_media __read_mostly = 1;
51 module_param(sip_direct_media, int, 0600); 51 module_param(sip_direct_media, int, 0600);
52 MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling " 52 MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling "
53 "endpoints only (default 1)"); 53 "endpoints only (default 1)");
54 54
55 unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, unsigned int dataoff, 55 unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, unsigned int dataoff,
56 const char **dptr, 56 const char **dptr,
57 unsigned int *datalen) __read_mostly; 57 unsigned int *datalen) __read_mostly;
58 EXPORT_SYMBOL_GPL(nf_nat_sip_hook); 58 EXPORT_SYMBOL_GPL(nf_nat_sip_hook);
59 59
60 void (*nf_nat_sip_seq_adjust_hook)(struct sk_buff *skb, s16 off) __read_mostly; 60 void (*nf_nat_sip_seq_adjust_hook)(struct sk_buff *skb, s16 off) __read_mostly;
61 EXPORT_SYMBOL_GPL(nf_nat_sip_seq_adjust_hook); 61 EXPORT_SYMBOL_GPL(nf_nat_sip_seq_adjust_hook);
62 62
63 unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, 63 unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
64 unsigned int dataoff, 64 unsigned int dataoff,
65 const char **dptr, 65 const char **dptr,
66 unsigned int *datalen, 66 unsigned int *datalen,
67 struct nf_conntrack_expect *exp, 67 struct nf_conntrack_expect *exp,
68 unsigned int matchoff, 68 unsigned int matchoff,
69 unsigned int matchlen) __read_mostly; 69 unsigned int matchlen) __read_mostly;
70 EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook); 70 EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook);
71 71
72 unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, unsigned int dataoff, 72 unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, unsigned int dataoff,
73 const char **dptr, 73 const char **dptr,
74 unsigned int *datalen, 74 unsigned int *datalen,
75 unsigned int sdpoff, 75 unsigned int sdpoff,
76 enum sdp_header_types type, 76 enum sdp_header_types type,
77 enum sdp_header_types term, 77 enum sdp_header_types term,
78 const union nf_inet_addr *addr) 78 const union nf_inet_addr *addr)
79 __read_mostly; 79 __read_mostly;
80 EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook); 80 EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook);
81 81
82 unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, unsigned int dataoff, 82 unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, unsigned int dataoff,
83 const char **dptr, 83 const char **dptr,
84 unsigned int *datalen, 84 unsigned int *datalen,
85 unsigned int matchoff, 85 unsigned int matchoff,
86 unsigned int matchlen, 86 unsigned int matchlen,
87 u_int16_t port) __read_mostly; 87 u_int16_t port) __read_mostly;
88 EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook); 88 EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook);
89 89
90 unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb, 90 unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,
91 unsigned int dataoff, 91 unsigned int dataoff,
92 const char **dptr, 92 const char **dptr,
93 unsigned int *datalen, 93 unsigned int *datalen,
94 unsigned int sdpoff, 94 unsigned int sdpoff,
95 const union nf_inet_addr *addr) 95 const union nf_inet_addr *addr)
96 __read_mostly; 96 __read_mostly;
97 EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook); 97 EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook);
98 98
99 unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, unsigned int dataoff, 99 unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, unsigned int dataoff,
100 const char **dptr, 100 const char **dptr,
101 unsigned int *datalen, 101 unsigned int *datalen,
102 struct nf_conntrack_expect *rtp_exp, 102 struct nf_conntrack_expect *rtp_exp,
103 struct nf_conntrack_expect *rtcp_exp, 103 struct nf_conntrack_expect *rtcp_exp,
104 unsigned int mediaoff, 104 unsigned int mediaoff,
105 unsigned int medialen, 105 unsigned int medialen,
106 union nf_inet_addr *rtp_addr) 106 union nf_inet_addr *rtp_addr)
107 __read_mostly; 107 __read_mostly;
108 EXPORT_SYMBOL_GPL(nf_nat_sdp_media_hook); 108 EXPORT_SYMBOL_GPL(nf_nat_sdp_media_hook);
109 109
110 static int string_len(const struct nf_conn *ct, const char *dptr, 110 static int string_len(const struct nf_conn *ct, const char *dptr,
111 const char *limit, int *shift) 111 const char *limit, int *shift)
112 { 112 {
113 int len = 0; 113 int len = 0;
114 114
115 while (dptr < limit && isalpha(*dptr)) { 115 while (dptr < limit && isalpha(*dptr)) {
116 dptr++; 116 dptr++;
117 len++; 117 len++;
118 } 118 }
119 return len; 119 return len;
120 } 120 }
121 121
122 static int digits_len(const struct nf_conn *ct, const char *dptr, 122 static int digits_len(const struct nf_conn *ct, const char *dptr,
123 const char *limit, int *shift) 123 const char *limit, int *shift)
124 { 124 {
125 int len = 0; 125 int len = 0;
126 while (dptr < limit && isdigit(*dptr)) { 126 while (dptr < limit && isdigit(*dptr)) {
127 dptr++; 127 dptr++;
128 len++; 128 len++;
129 } 129 }
130 return len; 130 return len;
131 } 131 }
132 132
133 static int iswordc(const char c) 133 static int iswordc(const char c)
134 { 134 {
135 if (isalnum(c) || c == '!' || c == '"' || c == '%' || 135 if (isalnum(c) || c == '!' || c == '"' || c == '%' ||
136 (c >= '(' && c <= '/') || c == ':' || c == '<' || c == '>' || 136 (c >= '(' && c <= '/') || c == ':' || c == '<' || c == '>' ||
137 c == '?' || (c >= '[' && c <= ']') || c == '_' || c == '`' || 137 c == '?' || (c >= '[' && c <= ']') || c == '_' || c == '`' ||
138 c == '{' || c == '}' || c == '~') 138 c == '{' || c == '}' || c == '~')
139 return 1; 139 return 1;
140 return 0; 140 return 0;
141 } 141 }
142 142
143 static int word_len(const char *dptr, const char *limit) 143 static int word_len(const char *dptr, const char *limit)
144 { 144 {
145 int len = 0; 145 int len = 0;
146 while (dptr < limit && iswordc(*dptr)) { 146 while (dptr < limit && iswordc(*dptr)) {
147 dptr++; 147 dptr++;
148 len++; 148 len++;
149 } 149 }
150 return len; 150 return len;
151 } 151 }
152 152
153 static int callid_len(const struct nf_conn *ct, const char *dptr, 153 static int callid_len(const struct nf_conn *ct, const char *dptr,
154 const char *limit, int *shift) 154 const char *limit, int *shift)
155 { 155 {
156 int len, domain_len; 156 int len, domain_len;
157 157
158 len = word_len(dptr, limit); 158 len = word_len(dptr, limit);
159 dptr += len; 159 dptr += len;
160 if (!len || dptr == limit || *dptr != '@') 160 if (!len || dptr == limit || *dptr != '@')
161 return len; 161 return len;
162 dptr++; 162 dptr++;
163 len++; 163 len++;
164 164
165 domain_len = word_len(dptr, limit); 165 domain_len = word_len(dptr, limit);
166 if (!domain_len) 166 if (!domain_len)
167 return 0; 167 return 0;
168 return len + domain_len; 168 return len + domain_len;
169 } 169 }
170 170
171 /* get media type + port length */ 171 /* get media type + port length */
172 static int media_len(const struct nf_conn *ct, const char *dptr, 172 static int media_len(const struct nf_conn *ct, const char *dptr,
173 const char *limit, int *shift) 173 const char *limit, int *shift)
174 { 174 {
175 int len = string_len(ct, dptr, limit, shift); 175 int len = string_len(ct, dptr, limit, shift);
176 176
177 dptr += len; 177 dptr += len;
178 if (dptr >= limit || *dptr != ' ') 178 if (dptr >= limit || *dptr != ' ')
179 return 0; 179 return 0;
180 len++; 180 len++;
181 dptr++; 181 dptr++;
182 182
183 return len + digits_len(ct, dptr, limit, shift); 183 return len + digits_len(ct, dptr, limit, shift);
184 } 184 }
185 185
186 static int parse_addr(const struct nf_conn *ct, const char *cp, 186 static int parse_addr(const struct nf_conn *ct, const char *cp,
187 const char **endp, union nf_inet_addr *addr, 187 const char **endp, union nf_inet_addr *addr,
188 const char *limit) 188 const char *limit)
189 { 189 {
190 const char *end; 190 const char *end;
191 int ret = 0; 191 int ret = 0;
192 192
193 if (!ct) 193 if (!ct)
194 return 0; 194 return 0;
195 195
196 memset(addr, 0, sizeof(*addr)); 196 memset(addr, 0, sizeof(*addr));
197 switch (nf_ct_l3num(ct)) { 197 switch (nf_ct_l3num(ct)) {
198 case AF_INET: 198 case AF_INET:
199 ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); 199 ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end);
200 break; 200 break;
201 case AF_INET6: 201 case AF_INET6:
202 ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); 202 ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end);
203 break; 203 break;
204 default: 204 default:
205 BUG(); 205 BUG();
206 } 206 }
207 207
208 if (ret == 0 || end == cp) 208 if (ret == 0 || end == cp)
209 return 0; 209 return 0;
210 if (endp) 210 if (endp)
211 *endp = end; 211 *endp = end;
212 return 1; 212 return 1;
213 } 213 }
214 214
215 /* skip ip address. returns its length. */ 215 /* skip ip address. returns its length. */
216 static int epaddr_len(const struct nf_conn *ct, const char *dptr, 216 static int epaddr_len(const struct nf_conn *ct, const char *dptr,
217 const char *limit, int *shift) 217 const char *limit, int *shift)
218 { 218 {
219 union nf_inet_addr addr; 219 union nf_inet_addr addr;
220 const char *aux = dptr; 220 const char *aux = dptr;
221 221
222 if (!parse_addr(ct, dptr, &dptr, &addr, limit)) { 222 if (!parse_addr(ct, dptr, &dptr, &addr, limit)) {
223 pr_debug("ip: %s parse failed.!\n", dptr); 223 pr_debug("ip: %s parse failed.!\n", dptr);
224 return 0; 224 return 0;
225 } 225 }
226 226
227 /* Port number */ 227 /* Port number */
228 if (*dptr == ':') { 228 if (*dptr == ':') {
229 dptr++; 229 dptr++;
230 dptr += digits_len(ct, dptr, limit, shift); 230 dptr += digits_len(ct, dptr, limit, shift);
231 } 231 }
232 return dptr - aux; 232 return dptr - aux;
233 } 233 }
234 234
235 /* get address length, skiping user info. */ 235 /* get address length, skiping user info. */
236 static int skp_epaddr_len(const struct nf_conn *ct, const char *dptr, 236 static int skp_epaddr_len(const struct nf_conn *ct, const char *dptr,
237 const char *limit, int *shift) 237 const char *limit, int *shift)
238 { 238 {
239 const char *start = dptr; 239 const char *start = dptr;
240 int s = *shift; 240 int s = *shift;
241 241
242 /* Search for @, but stop at the end of the line. 242 /* Search for @, but stop at the end of the line.
243 * We are inside a sip: URI, so we don't need to worry about 243 * We are inside a sip: URI, so we don't need to worry about
244 * continuation lines. */ 244 * continuation lines. */
245 while (dptr < limit && 245 while (dptr < limit &&
246 *dptr != '@' && *dptr != '\r' && *dptr != '\n') { 246 *dptr != '@' && *dptr != '\r' && *dptr != '\n') {
247 (*shift)++; 247 (*shift)++;
248 dptr++; 248 dptr++;
249 } 249 }
250 250
251 if (dptr < limit && *dptr == '@') { 251 if (dptr < limit && *dptr == '@') {
252 dptr++; 252 dptr++;
253 (*shift)++; 253 (*shift)++;
254 } else { 254 } else {
255 dptr = start; 255 dptr = start;
256 *shift = s; 256 *shift = s;
257 } 257 }
258 258
259 return epaddr_len(ct, dptr, limit, shift); 259 return epaddr_len(ct, dptr, limit, shift);
260 } 260 }
261 261
262 /* Parse a SIP request line of the form: 262 /* Parse a SIP request line of the form:
263 * 263 *
264 * Request-Line = Method SP Request-URI SP SIP-Version CRLF 264 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
265 * 265 *
266 * and return the offset and length of the address contained in the Request-URI. 266 * and return the offset and length of the address contained in the Request-URI.
267 */ 267 */
268 int ct_sip_parse_request(const struct nf_conn *ct, 268 int ct_sip_parse_request(const struct nf_conn *ct,
269 const char *dptr, unsigned int datalen, 269 const char *dptr, unsigned int datalen,
270 unsigned int *matchoff, unsigned int *matchlen, 270 unsigned int *matchoff, unsigned int *matchlen,
271 union nf_inet_addr *addr, __be16 *port) 271 union nf_inet_addr *addr, __be16 *port)
272 { 272 {
273 const char *start = dptr, *limit = dptr + datalen, *end; 273 const char *start = dptr, *limit = dptr + datalen, *end;
274 unsigned int mlen; 274 unsigned int mlen;
275 unsigned int p; 275 unsigned int p;
276 int shift = 0; 276 int shift = 0;
277 277
278 /* Skip method and following whitespace */ 278 /* Skip method and following whitespace */
279 mlen = string_len(ct, dptr, limit, NULL); 279 mlen = string_len(ct, dptr, limit, NULL);
280 if (!mlen) 280 if (!mlen)
281 return 0; 281 return 0;
282 dptr += mlen; 282 dptr += mlen;
283 if (++dptr >= limit) 283 if (++dptr >= limit)
284 return 0; 284 return 0;
285 285
286 /* Find SIP URI */ 286 /* Find SIP URI */
287 for (; dptr < limit - strlen("sip:"); dptr++) { 287 for (; dptr < limit - strlen("sip:"); dptr++) {
288 if (*dptr == '\r' || *dptr == '\n') 288 if (*dptr == '\r' || *dptr == '\n')
289 return -1; 289 return -1;
290 if (strnicmp(dptr, "sip:", strlen("sip:")) == 0) { 290 if (strnicmp(dptr, "sip:", strlen("sip:")) == 0) {
291 dptr += strlen("sip:"); 291 dptr += strlen("sip:");
292 break; 292 break;
293 } 293 }
294 } 294 }
295 if (!skp_epaddr_len(ct, dptr, limit, &shift)) 295 if (!skp_epaddr_len(ct, dptr, limit, &shift))
296 return 0; 296 return 0;
297 dptr += shift; 297 dptr += shift;
298 298
299 if (!parse_addr(ct, dptr, &end, addr, limit)) 299 if (!parse_addr(ct, dptr, &end, addr, limit))
300 return -1; 300 return -1;
301 if (end < limit && *end == ':') { 301 if (end < limit && *end == ':') {
302 end++; 302 end++;
303 p = simple_strtoul(end, (char **)&end, 10); 303 p = simple_strtoul(end, (char **)&end, 10);
304 if (p < 1024 || p > 65535) 304 if (p < 1024 || p > 65535)
305 return -1; 305 return -1;
306 *port = htons(p); 306 *port = htons(p);
307 } else 307 } else
308 *port = htons(SIP_PORT); 308 *port = htons(SIP_PORT);
309 309
310 if (end == dptr) 310 if (end == dptr)
311 return 0; 311 return 0;
312 *matchoff = dptr - start; 312 *matchoff = dptr - start;
313 *matchlen = end - dptr; 313 *matchlen = end - dptr;
314 return 1; 314 return 1;
315 } 315 }
316 EXPORT_SYMBOL_GPL(ct_sip_parse_request); 316 EXPORT_SYMBOL_GPL(ct_sip_parse_request);
317 317
318 /* SIP header parsing: SIP headers are located at the beginning of a line, but 318 /* SIP header parsing: SIP headers are located at the beginning of a line, but
319 * may span several lines, in which case the continuation lines begin with a 319 * may span several lines, in which case the continuation lines begin with a
320 * whitespace character. RFC 2543 allows lines to be terminated with CR, LF or 320 * whitespace character. RFC 2543 allows lines to be terminated with CR, LF or
321 * CRLF, RFC 3261 allows only CRLF, we support both. 321 * CRLF, RFC 3261 allows only CRLF, we support both.
322 * 322 *
323 * Headers are followed by (optionally) whitespace, a colon, again (optionally) 323 * Headers are followed by (optionally) whitespace, a colon, again (optionally)
324 * whitespace and the values. Whitespace in this context means any amount of 324 * whitespace and the values. Whitespace in this context means any amount of
325 * tabs, spaces and continuation lines, which are treated as a single whitespace 325 * tabs, spaces and continuation lines, which are treated as a single whitespace
326 * character. 326 * character.
327 * 327 *
328 * Some headers may appear multiple times. A comma separated list of values is 328 * Some headers may appear multiple times. A comma separated list of values is
329 * equivalent to multiple headers. 329 * equivalent to multiple headers.
330 */ 330 */
331 static const struct sip_header ct_sip_hdrs[] = { 331 static const struct sip_header ct_sip_hdrs[] = {
332 [SIP_HDR_CSEQ] = SIP_HDR("CSeq", NULL, NULL, digits_len), 332 [SIP_HDR_CSEQ] = SIP_HDR("CSeq", NULL, NULL, digits_len),
333 [SIP_HDR_FROM] = SIP_HDR("From", "f", "sip:", skp_epaddr_len), 333 [SIP_HDR_FROM] = SIP_HDR("From", "f", "sip:", skp_epaddr_len),
334 [SIP_HDR_TO] = SIP_HDR("To", "t", "sip:", skp_epaddr_len), 334 [SIP_HDR_TO] = SIP_HDR("To", "t", "sip:", skp_epaddr_len),
335 [SIP_HDR_CONTACT] = SIP_HDR("Contact", "m", "sip:", skp_epaddr_len), 335 [SIP_HDR_CONTACT] = SIP_HDR("Contact", "m", "sip:", skp_epaddr_len),
336 [SIP_HDR_VIA_UDP] = SIP_HDR("Via", "v", "UDP ", epaddr_len), 336 [SIP_HDR_VIA_UDP] = SIP_HDR("Via", "v", "UDP ", epaddr_len),
337 [SIP_HDR_VIA_TCP] = SIP_HDR("Via", "v", "TCP ", epaddr_len), 337 [SIP_HDR_VIA_TCP] = SIP_HDR("Via", "v", "TCP ", epaddr_len),
338 [SIP_HDR_EXPIRES] = SIP_HDR("Expires", NULL, NULL, digits_len), 338 [SIP_HDR_EXPIRES] = SIP_HDR("Expires", NULL, NULL, digits_len),
339 [SIP_HDR_CONTENT_LENGTH] = SIP_HDR("Content-Length", "l", NULL, digits_len), 339 [SIP_HDR_CONTENT_LENGTH] = SIP_HDR("Content-Length", "l", NULL, digits_len),
340 [SIP_HDR_CALL_ID] = SIP_HDR("Call-Id", "i", NULL, callid_len), 340 [SIP_HDR_CALL_ID] = SIP_HDR("Call-Id", "i", NULL, callid_len),
341 }; 341 };
342 342
343 static const char *sip_follow_continuation(const char *dptr, const char *limit) 343 static const char *sip_follow_continuation(const char *dptr, const char *limit)
344 { 344 {
345 /* Walk past newline */ 345 /* Walk past newline */
346 if (++dptr >= limit) 346 if (++dptr >= limit)
347 return NULL; 347 return NULL;
348 348
349 /* Skip '\n' in CR LF */ 349 /* Skip '\n' in CR LF */
350 if (*(dptr - 1) == '\r' && *dptr == '\n') { 350 if (*(dptr - 1) == '\r' && *dptr == '\n') {
351 if (++dptr >= limit) 351 if (++dptr >= limit)
352 return NULL; 352 return NULL;
353 } 353 }
354 354
355 /* Continuation line? */ 355 /* Continuation line? */
356 if (*dptr != ' ' && *dptr != '\t') 356 if (*dptr != ' ' && *dptr != '\t')
357 return NULL; 357 return NULL;
358 358
359 /* skip leading whitespace */ 359 /* skip leading whitespace */
360 for (; dptr < limit; dptr++) { 360 for (; dptr < limit; dptr++) {
361 if (*dptr != ' ' && *dptr != '\t') 361 if (*dptr != ' ' && *dptr != '\t')
362 break; 362 break;
363 } 363 }
364 return dptr; 364 return dptr;
365 } 365 }
366 366
367 static const char *sip_skip_whitespace(const char *dptr, const char *limit) 367 static const char *sip_skip_whitespace(const char *dptr, const char *limit)
368 { 368 {
369 for (; dptr < limit; dptr++) { 369 for (; dptr < limit; dptr++) {
370 if (*dptr == ' ') 370 if (*dptr == ' ')
371 continue; 371 continue;
372 if (*dptr != '\r' && *dptr != '\n') 372 if (*dptr != '\r' && *dptr != '\n')
373 break; 373 break;
374 dptr = sip_follow_continuation(dptr, limit); 374 dptr = sip_follow_continuation(dptr, limit);
375 if (dptr == NULL) 375 if (dptr == NULL)
376 return NULL; 376 return NULL;
377 } 377 }
378 return dptr; 378 return dptr;
379 } 379 }
380 380
381 /* Search within a SIP header value, dealing with continuation lines */ 381 /* Search within a SIP header value, dealing with continuation lines */
382 static const char *ct_sip_header_search(const char *dptr, const char *limit, 382 static const char *ct_sip_header_search(const char *dptr, const char *limit,
383 const char *needle, unsigned int len) 383 const char *needle, unsigned int len)
384 { 384 {
385 for (limit -= len; dptr < limit; dptr++) { 385 for (limit -= len; dptr < limit; dptr++) {
386 if (*dptr == '\r' || *dptr == '\n') { 386 if (*dptr == '\r' || *dptr == '\n') {
387 dptr = sip_follow_continuation(dptr, limit); 387 dptr = sip_follow_continuation(dptr, limit);
388 if (dptr == NULL) 388 if (dptr == NULL)
389 break; 389 break;
390 continue; 390 continue;
391 } 391 }
392 392
393 if (strnicmp(dptr, needle, len) == 0) 393 if (strnicmp(dptr, needle, len) == 0)
394 return dptr; 394 return dptr;
395 } 395 }
396 return NULL; 396 return NULL;
397 } 397 }
398 398
399 int ct_sip_get_header(const struct nf_conn *ct, const char *dptr, 399 int ct_sip_get_header(const struct nf_conn *ct, const char *dptr,
400 unsigned int dataoff, unsigned int datalen, 400 unsigned int dataoff, unsigned int datalen,
401 enum sip_header_types type, 401 enum sip_header_types type,
402 unsigned int *matchoff, unsigned int *matchlen) 402 unsigned int *matchoff, unsigned int *matchlen)
403 { 403 {
404 const struct sip_header *hdr = &ct_sip_hdrs[type]; 404 const struct sip_header *hdr = &ct_sip_hdrs[type];
405 const char *start = dptr, *limit = dptr + datalen; 405 const char *start = dptr, *limit = dptr + datalen;
406 int shift = 0; 406 int shift = 0;
407 407
408 for (dptr += dataoff; dptr < limit; dptr++) { 408 for (dptr += dataoff; dptr < limit; dptr++) {
409 /* Find beginning of line */ 409 /* Find beginning of line */
410 if (*dptr != '\r' && *dptr != '\n') 410 if (*dptr != '\r' && *dptr != '\n')
411 continue; 411 continue;
412 if (++dptr >= limit) 412 if (++dptr >= limit)
413 break; 413 break;
414 if (*(dptr - 1) == '\r' && *dptr == '\n') { 414 if (*(dptr - 1) == '\r' && *dptr == '\n') {
415 if (++dptr >= limit) 415 if (++dptr >= limit)
416 break; 416 break;
417 } 417 }
418 418
419 /* Skip continuation lines */ 419 /* Skip continuation lines */
420 if (*dptr == ' ' || *dptr == '\t') 420 if (*dptr == ' ' || *dptr == '\t')
421 continue; 421 continue;
422 422
423 /* Find header. Compact headers must be followed by a 423 /* Find header. Compact headers must be followed by a
424 * non-alphabetic character to avoid mismatches. */ 424 * non-alphabetic character to avoid mismatches. */
425 if (limit - dptr >= hdr->len && 425 if (limit - dptr >= hdr->len &&
426 strnicmp(dptr, hdr->name, hdr->len) == 0) 426 strnicmp(dptr, hdr->name, hdr->len) == 0)
427 dptr += hdr->len; 427 dptr += hdr->len;
428 else if (hdr->cname && limit - dptr >= hdr->clen + 1 && 428 else if (hdr->cname && limit - dptr >= hdr->clen + 1 &&
429 strnicmp(dptr, hdr->cname, hdr->clen) == 0 && 429 strnicmp(dptr, hdr->cname, hdr->clen) == 0 &&
430 !isalpha(*(dptr + hdr->clen))) 430 !isalpha(*(dptr + hdr->clen)))
431 dptr += hdr->clen; 431 dptr += hdr->clen;
432 else 432 else
433 continue; 433 continue;
434 434
435 /* Find and skip colon */ 435 /* Find and skip colon */
436 dptr = sip_skip_whitespace(dptr, limit); 436 dptr = sip_skip_whitespace(dptr, limit);
437 if (dptr == NULL) 437 if (dptr == NULL)
438 break; 438 break;
439 if (*dptr != ':' || ++dptr >= limit) 439 if (*dptr != ':' || ++dptr >= limit)
440 break; 440 break;
441 441
442 /* Skip whitespace after colon */ 442 /* Skip whitespace after colon */
443 dptr = sip_skip_whitespace(dptr, limit); 443 dptr = sip_skip_whitespace(dptr, limit);
444 if (dptr == NULL) 444 if (dptr == NULL)
445 break; 445 break;
446 446
447 *matchoff = dptr - start; 447 *matchoff = dptr - start;
448 if (hdr->search) { 448 if (hdr->search) {
449 dptr = ct_sip_header_search(dptr, limit, hdr->search, 449 dptr = ct_sip_header_search(dptr, limit, hdr->search,
450 hdr->slen); 450 hdr->slen);
451 if (!dptr) 451 if (!dptr)
452 return -1; 452 return -1;
453 dptr += hdr->slen; 453 dptr += hdr->slen;
454 } 454 }
455 455
456 *matchlen = hdr->match_len(ct, dptr, limit, &shift); 456 *matchlen = hdr->match_len(ct, dptr, limit, &shift);
457 if (!*matchlen) 457 if (!*matchlen)
458 return -1; 458 return -1;
459 *matchoff = dptr - start + shift; 459 *matchoff = dptr - start + shift;
460 return 1; 460 return 1;
461 } 461 }
462 return 0; 462 return 0;
463 } 463 }
464 EXPORT_SYMBOL_GPL(ct_sip_get_header); 464 EXPORT_SYMBOL_GPL(ct_sip_get_header);
465 465
466 /* Get next header field in a list of comma separated values */ 466 /* Get next header field in a list of comma separated values */
467 static int ct_sip_next_header(const struct nf_conn *ct, const char *dptr, 467 static int ct_sip_next_header(const struct nf_conn *ct, const char *dptr,
468 unsigned int dataoff, unsigned int datalen, 468 unsigned int dataoff, unsigned int datalen,
469 enum sip_header_types type, 469 enum sip_header_types type,
470 unsigned int *matchoff, unsigned int *matchlen) 470 unsigned int *matchoff, unsigned int *matchlen)
471 { 471 {
472 const struct sip_header *hdr = &ct_sip_hdrs[type]; 472 const struct sip_header *hdr = &ct_sip_hdrs[type];
473 const char *start = dptr, *limit = dptr + datalen; 473 const char *start = dptr, *limit = dptr + datalen;
474 int shift = 0; 474 int shift = 0;
475 475
476 dptr += dataoff; 476 dptr += dataoff;
477 477
478 dptr = ct_sip_header_search(dptr, limit, ",", strlen(",")); 478 dptr = ct_sip_header_search(dptr, limit, ",", strlen(","));
479 if (!dptr) 479 if (!dptr)
480 return 0; 480 return 0;
481 481
482 dptr = ct_sip_header_search(dptr, limit, hdr->search, hdr->slen); 482 dptr = ct_sip_header_search(dptr, limit, hdr->search, hdr->slen);
483 if (!dptr) 483 if (!dptr)
484 return 0; 484 return 0;
485 dptr += hdr->slen; 485 dptr += hdr->slen;
486 486
487 *matchoff = dptr - start; 487 *matchoff = dptr - start;
488 *matchlen = hdr->match_len(ct, dptr, limit, &shift); 488 *matchlen = hdr->match_len(ct, dptr, limit, &shift);
489 if (!*matchlen) 489 if (!*matchlen)
490 return -1; 490 return -1;
491 *matchoff += shift; 491 *matchoff += shift;
492 return 1; 492 return 1;
493 } 493 }
494 494
495 /* Walk through headers until a parsable one is found or no header of the 495 /* Walk through headers until a parsable one is found or no header of the
496 * given type is left. */ 496 * given type is left. */
497 static int ct_sip_walk_headers(const struct nf_conn *ct, const char *dptr, 497 static int ct_sip_walk_headers(const struct nf_conn *ct, const char *dptr,
498 unsigned int dataoff, unsigned int datalen, 498 unsigned int dataoff, unsigned int datalen,
499 enum sip_header_types type, int *in_header, 499 enum sip_header_types type, int *in_header,
500 unsigned int *matchoff, unsigned int *matchlen) 500 unsigned int *matchoff, unsigned int *matchlen)
501 { 501 {
502 int ret; 502 int ret;
503 503
504 if (in_header && *in_header) { 504 if (in_header && *in_header) {
505 while (1) { 505 while (1) {
506 ret = ct_sip_next_header(ct, dptr, dataoff, datalen, 506 ret = ct_sip_next_header(ct, dptr, dataoff, datalen,
507 type, matchoff, matchlen); 507 type, matchoff, matchlen);
508 if (ret > 0) 508 if (ret > 0)
509 return ret; 509 return ret;
510 if (ret == 0) 510 if (ret == 0)
511 break; 511 break;
512 dataoff += *matchoff; 512 dataoff += *matchoff;
513 } 513 }
514 *in_header = 0; 514 *in_header = 0;
515 } 515 }
516 516
517 while (1) { 517 while (1) {
518 ret = ct_sip_get_header(ct, dptr, dataoff, datalen, 518 ret = ct_sip_get_header(ct, dptr, dataoff, datalen,
519 type, matchoff, matchlen); 519 type, matchoff, matchlen);
520 if (ret > 0) 520 if (ret > 0)
521 break; 521 break;
522 if (ret == 0) 522 if (ret == 0)
523 return ret; 523 return ret;
524 dataoff += *matchoff; 524 dataoff += *matchoff;
525 } 525 }
526 526
527 if (in_header) 527 if (in_header)
528 *in_header = 1; 528 *in_header = 1;
529 return 1; 529 return 1;
530 } 530 }
531 531
532 /* Locate a SIP header, parse the URI and return the offset and length of 532 /* Locate a SIP header, parse the URI and return the offset and length of
533 * the address as well as the address and port themselves. A stream of 533 * the address as well as the address and port themselves. A stream of
534 * headers can be parsed by handing in a non-NULL datalen and in_header 534 * headers can be parsed by handing in a non-NULL datalen and in_header
535 * pointer. 535 * pointer.
536 */ 536 */
537 int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr, 537 int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr,
538 unsigned int *dataoff, unsigned int datalen, 538 unsigned int *dataoff, unsigned int datalen,
539 enum sip_header_types type, int *in_header, 539 enum sip_header_types type, int *in_header,
540 unsigned int *matchoff, unsigned int *matchlen, 540 unsigned int *matchoff, unsigned int *matchlen,
541 union nf_inet_addr *addr, __be16 *port) 541 union nf_inet_addr *addr, __be16 *port)
542 { 542 {
543 const char *c, *limit = dptr + datalen; 543 const char *c, *limit = dptr + datalen;
544 unsigned int p; 544 unsigned int p;
545 int ret; 545 int ret;
546 546
547 ret = ct_sip_walk_headers(ct, dptr, dataoff ? *dataoff : 0, datalen, 547 ret = ct_sip_walk_headers(ct, dptr, dataoff ? *dataoff : 0, datalen,
548 type, in_header, matchoff, matchlen); 548 type, in_header, matchoff, matchlen);
549 WARN_ON(ret < 0); 549 WARN_ON(ret < 0);
550 if (ret == 0) 550 if (ret == 0)
551 return ret; 551 return ret;
552 552
553 if (!parse_addr(ct, dptr + *matchoff, &c, addr, limit)) 553 if (!parse_addr(ct, dptr + *matchoff, &c, addr, limit))
554 return -1; 554 return -1;
555 if (*c == ':') { 555 if (*c == ':') {
556 c++; 556 c++;
557 p = simple_strtoul(c, (char **)&c, 10); 557 p = simple_strtoul(c, (char **)&c, 10);
558 if (p < 1024 || p > 65535) 558 if (p < 1024 || p > 65535)
559 return -1; 559 return -1;
560 *port = htons(p); 560 *port = htons(p);
561 } else 561 } else
562 *port = htons(SIP_PORT); 562 *port = htons(SIP_PORT);
563 563
564 if (dataoff) 564 if (dataoff)
565 *dataoff = c - dptr; 565 *dataoff = c - dptr;
566 return 1; 566 return 1;
567 } 567 }
568 EXPORT_SYMBOL_GPL(ct_sip_parse_header_uri); 568 EXPORT_SYMBOL_GPL(ct_sip_parse_header_uri);
569 569
570 static int ct_sip_parse_param(const struct nf_conn *ct, const char *dptr, 570 static int ct_sip_parse_param(const struct nf_conn *ct, const char *dptr,
571 unsigned int dataoff, unsigned int datalen, 571 unsigned int dataoff, unsigned int datalen,
572 const char *name, 572 const char *name,
573 unsigned int *matchoff, unsigned int *matchlen) 573 unsigned int *matchoff, unsigned int *matchlen)
574 { 574 {
575 const char *limit = dptr + datalen; 575 const char *limit = dptr + datalen;
576 const char *start; 576 const char *start;
577 const char *end; 577 const char *end;
578 578
579 limit = ct_sip_header_search(dptr + dataoff, limit, ",", strlen(",")); 579 limit = ct_sip_header_search(dptr + dataoff, limit, ",", strlen(","));
580 if (!limit) 580 if (!limit)
581 limit = dptr + datalen; 581 limit = dptr + datalen;
582 582
583 start = ct_sip_header_search(dptr + dataoff, limit, name, strlen(name)); 583 start = ct_sip_header_search(dptr + dataoff, limit, name, strlen(name));
584 if (!start) 584 if (!start)
585 return 0; 585 return 0;
586 start += strlen(name); 586 start += strlen(name);
587 587
588 end = ct_sip_header_search(start, limit, ";", strlen(";")); 588 end = ct_sip_header_search(start, limit, ";", strlen(";"));
589 if (!end) 589 if (!end)
590 end = limit; 590 end = limit;
591 591
592 *matchoff = start - dptr; 592 *matchoff = start - dptr;
593 *matchlen = end - start; 593 *matchlen = end - start;
594 return 1; 594 return 1;
595 } 595 }
596 596
597 /* Parse address from header parameter and return address, offset and length */ 597 /* Parse address from header parameter and return address, offset and length */
598 int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr, 598 int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr,
599 unsigned int dataoff, unsigned int datalen, 599 unsigned int dataoff, unsigned int datalen,
600 const char *name, 600 const char *name,
601 unsigned int *matchoff, unsigned int *matchlen, 601 unsigned int *matchoff, unsigned int *matchlen,
602 union nf_inet_addr *addr) 602 union nf_inet_addr *addr)
603 { 603 {
604 const char *limit = dptr + datalen; 604 const char *limit = dptr + datalen;
605 const char *start, *end; 605 const char *start, *end;
606 606
607 limit = ct_sip_header_search(dptr + dataoff, limit, ",", strlen(",")); 607 limit = ct_sip_header_search(dptr + dataoff, limit, ",", strlen(","));
608 if (!limit) 608 if (!limit)
609 limit = dptr + datalen; 609 limit = dptr + datalen;
610 610
611 start = ct_sip_header_search(dptr + dataoff, limit, name, strlen(name)); 611 start = ct_sip_header_search(dptr + dataoff, limit, name, strlen(name));
612 if (!start) 612 if (!start)
613 return 0; 613 return 0;
614 614
615 start += strlen(name); 615 start += strlen(name);
616 if (!parse_addr(ct, start, &end, addr, limit)) 616 if (!parse_addr(ct, start, &end, addr, limit))
617 return 0; 617 return 0;
618 *matchoff = start - dptr; 618 *matchoff = start - dptr;
619 *matchlen = end - start; 619 *matchlen = end - start;
620 return 1; 620 return 1;
621 } 621 }
622 EXPORT_SYMBOL_GPL(ct_sip_parse_address_param); 622 EXPORT_SYMBOL_GPL(ct_sip_parse_address_param);
623 623
624 /* Parse numerical header parameter and return value, offset and length */ 624 /* Parse numerical header parameter and return value, offset and length */
625 int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr, 625 int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr,
626 unsigned int dataoff, unsigned int datalen, 626 unsigned int dataoff, unsigned int datalen,
627 const char *name, 627 const char *name,
628 unsigned int *matchoff, unsigned int *matchlen, 628 unsigned int *matchoff, unsigned int *matchlen,
629 unsigned int *val) 629 unsigned int *val)
630 { 630 {
631 const char *limit = dptr + datalen; 631 const char *limit = dptr + datalen;
632 const char *start; 632 const char *start;
633 char *end; 633 char *end;
634 634
635 limit = ct_sip_header_search(dptr + dataoff, limit, ",", strlen(",")); 635 limit = ct_sip_header_search(dptr + dataoff, limit, ",", strlen(","));
636 if (!limit) 636 if (!limit)
637 limit = dptr + datalen; 637 limit = dptr + datalen;
638 638
639 start = ct_sip_header_search(dptr + dataoff, limit, name, strlen(name)); 639 start = ct_sip_header_search(dptr + dataoff, limit, name, strlen(name));
640 if (!start) 640 if (!start)
641 return 0; 641 return 0;
642 642
643 start += strlen(name); 643 start += strlen(name);
644 *val = simple_strtoul(start, &end, 0); 644 *val = simple_strtoul(start, &end, 0);
645 if (start == end) 645 if (start == end)
646 return 0; 646 return 0;
647 if (matchoff && matchlen) { 647 if (matchoff && matchlen) {
648 *matchoff = start - dptr; 648 *matchoff = start - dptr;
649 *matchlen = end - start; 649 *matchlen = end - start;
650 } 650 }
651 return 1; 651 return 1;
652 } 652 }
653 EXPORT_SYMBOL_GPL(ct_sip_parse_numerical_param); 653 EXPORT_SYMBOL_GPL(ct_sip_parse_numerical_param);
654 654
655 static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr, 655 static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr,
656 unsigned int dataoff, unsigned int datalen, 656 unsigned int dataoff, unsigned int datalen,
657 u8 *proto) 657 u8 *proto)
658 { 658 {
659 unsigned int matchoff, matchlen; 659 unsigned int matchoff, matchlen;
660 660
661 if (ct_sip_parse_param(ct, dptr, dataoff, datalen, "transport=", 661 if (ct_sip_parse_param(ct, dptr, dataoff, datalen, "transport=",
662 &matchoff, &matchlen)) { 662 &matchoff, &matchlen)) {
663 if (!strnicmp(dptr + matchoff, "TCP", strlen("TCP"))) 663 if (!strnicmp(dptr + matchoff, "TCP", strlen("TCP")))
664 *proto = IPPROTO_TCP; 664 *proto = IPPROTO_TCP;
665 else if (!strnicmp(dptr + matchoff, "UDP", strlen("UDP"))) 665 else if (!strnicmp(dptr + matchoff, "UDP", strlen("UDP")))
666 *proto = IPPROTO_UDP; 666 *proto = IPPROTO_UDP;
667 else 667 else
668 return 0; 668 return 0;
669 669
670 if (*proto != nf_ct_protonum(ct)) 670 if (*proto != nf_ct_protonum(ct))
671 return 0; 671 return 0;
672 } else 672 } else
673 *proto = nf_ct_protonum(ct); 673 *proto = nf_ct_protonum(ct);
674 674
675 return 1; 675 return 1;
676 } 676 }
677 677
678 /* SDP header parsing: a SDP session description contains an ordered set of 678 /* SDP header parsing: a SDP session description contains an ordered set of
679 * headers, starting with a section containing general session parameters, 679 * headers, starting with a section containing general session parameters,
680 * optionally followed by multiple media descriptions. 680 * optionally followed by multiple media descriptions.
681 * 681 *
682 * SDP headers always start at the beginning of a line. According to RFC 2327: 682 * SDP headers always start at the beginning of a line. According to RFC 2327:
683 * "The sequence CRLF (0x0d0a) is used to end a record, although parsers should 683 * "The sequence CRLF (0x0d0a) is used to end a record, although parsers should
684 * be tolerant and also accept records terminated with a single newline 684 * be tolerant and also accept records terminated with a single newline
685 * character". We handle both cases. 685 * character". We handle both cases.
686 */ 686 */
687 static const struct sip_header ct_sdp_hdrs[] = { 687 static const struct sip_header ct_sdp_hdrs[] = {
688 [SDP_HDR_VERSION] = SDP_HDR("v=", NULL, digits_len), 688 [SDP_HDR_VERSION] = SDP_HDR("v=", NULL, digits_len),
689 [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", epaddr_len), 689 [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", epaddr_len),
690 [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", epaddr_len), 690 [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", epaddr_len),
691 [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", epaddr_len), 691 [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", epaddr_len),
692 [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", epaddr_len), 692 [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", epaddr_len),
693 [SDP_HDR_MEDIA] = SDP_HDR("m=", NULL, media_len), 693 [SDP_HDR_MEDIA] = SDP_HDR("m=", NULL, media_len),
694 }; 694 };
695 695
696 /* Linear string search within SDP header values */ 696 /* Linear string search within SDP header values */
697 static const char *ct_sdp_header_search(const char *dptr, const char *limit, 697 static const char *ct_sdp_header_search(const char *dptr, const char *limit,
698 const char *needle, unsigned int len) 698 const char *needle, unsigned int len)
699 { 699 {
700 for (limit -= len; dptr < limit; dptr++) { 700 for (limit -= len; dptr < limit; dptr++) {
701 if (*dptr == '\r' || *dptr == '\n') 701 if (*dptr == '\r' || *dptr == '\n')
702 break; 702 break;
703 if (strncmp(dptr, needle, len) == 0) 703 if (strncmp(dptr, needle, len) == 0)
704 return dptr; 704 return dptr;
705 } 705 }
706 return NULL; 706 return NULL;
707 } 707 }
708 708
709 /* Locate a SDP header (optionally a substring within the header value), 709 /* Locate a SDP header (optionally a substring within the header value),
710 * optionally stopping at the first occurrence of the term header, parse 710 * optionally stopping at the first occurrence of the term header, parse
711 * it and return the offset and length of the data we're interested in. 711 * it and return the offset and length of the data we're interested in.
712 */ 712 */
713 int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr, 713 int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr,
714 unsigned int dataoff, unsigned int datalen, 714 unsigned int dataoff, unsigned int datalen,
715 enum sdp_header_types type, 715 enum sdp_header_types type,
716 enum sdp_header_types term, 716 enum sdp_header_types term,
717 unsigned int *matchoff, unsigned int *matchlen) 717 unsigned int *matchoff, unsigned int *matchlen)
718 { 718 {
719 const struct sip_header *hdr = &ct_sdp_hdrs[type]; 719 const struct sip_header *hdr = &ct_sdp_hdrs[type];
720 const struct sip_header *thdr = &ct_sdp_hdrs[term]; 720 const struct sip_header *thdr = &ct_sdp_hdrs[term];
721 const char *start = dptr, *limit = dptr + datalen; 721 const char *start = dptr, *limit = dptr + datalen;
722 int shift = 0; 722 int shift = 0;
723 723
724 for (dptr += dataoff; dptr < limit; dptr++) { 724 for (dptr += dataoff; dptr < limit; dptr++) {
725 /* Find beginning of line */ 725 /* Find beginning of line */
726 if (*dptr != '\r' && *dptr != '\n') 726 if (*dptr != '\r' && *dptr != '\n')
727 continue; 727 continue;
728 if (++dptr >= limit) 728 if (++dptr >= limit)
729 break; 729 break;
730 if (*(dptr - 1) == '\r' && *dptr == '\n') { 730 if (*(dptr - 1) == '\r' && *dptr == '\n') {
731 if (++dptr >= limit) 731 if (++dptr >= limit)
732 break; 732 break;
733 } 733 }
734 734
735 if (term != SDP_HDR_UNSPEC && 735 if (term != SDP_HDR_UNSPEC &&
736 limit - dptr >= thdr->len && 736 limit - dptr >= thdr->len &&
737 strnicmp(dptr, thdr->name, thdr->len) == 0) 737 strnicmp(dptr, thdr->name, thdr->len) == 0)
738 break; 738 break;
739 else if (limit - dptr >= hdr->len && 739 else if (limit - dptr >= hdr->len &&
740 strnicmp(dptr, hdr->name, hdr->len) == 0) 740 strnicmp(dptr, hdr->name, hdr->len) == 0)
741 dptr += hdr->len; 741 dptr += hdr->len;
742 else 742 else
743 continue; 743 continue;
744 744
745 *matchoff = dptr - start; 745 *matchoff = dptr - start;
746 if (hdr->search) { 746 if (hdr->search) {
747 dptr = ct_sdp_header_search(dptr, limit, hdr->search, 747 dptr = ct_sdp_header_search(dptr, limit, hdr->search,
748 hdr->slen); 748 hdr->slen);
749 if (!dptr) 749 if (!dptr)
750 return -1; 750 return -1;
751 dptr += hdr->slen; 751 dptr += hdr->slen;
752 } 752 }
753 753
754 *matchlen = hdr->match_len(ct, dptr, limit, &shift); 754 *matchlen = hdr->match_len(ct, dptr, limit, &shift);
755 if (!*matchlen) 755 if (!*matchlen)
756 return -1; 756 return -1;
757 *matchoff = dptr - start + shift; 757 *matchoff = dptr - start + shift;
758 return 1; 758 return 1;
759 } 759 }
760 return 0; 760 return 0;
761 } 761 }
762 EXPORT_SYMBOL_GPL(ct_sip_get_sdp_header); 762 EXPORT_SYMBOL_GPL(ct_sip_get_sdp_header);
763 763
764 static int ct_sip_parse_sdp_addr(const struct nf_conn *ct, const char *dptr, 764 static int ct_sip_parse_sdp_addr(const struct nf_conn *ct, const char *dptr,
765 unsigned int dataoff, unsigned int datalen, 765 unsigned int dataoff, unsigned int datalen,
766 enum sdp_header_types type, 766 enum sdp_header_types type,
767 enum sdp_header_types term, 767 enum sdp_header_types term,
768 unsigned int *matchoff, unsigned int *matchlen, 768 unsigned int *matchoff, unsigned int *matchlen,
769 union nf_inet_addr *addr) 769 union nf_inet_addr *addr)
770 { 770 {
771 int ret; 771 int ret;
772 772
773 ret = ct_sip_get_sdp_header(ct, dptr, dataoff, datalen, type, term, 773 ret = ct_sip_get_sdp_header(ct, dptr, dataoff, datalen, type, term,
774 matchoff, matchlen); 774 matchoff, matchlen);
775 if (ret <= 0) 775 if (ret <= 0)
776 return ret; 776 return ret;
777 777
778 if (!parse_addr(ct, dptr + *matchoff, NULL, addr, 778 if (!parse_addr(ct, dptr + *matchoff, NULL, addr,
779 dptr + *matchoff + *matchlen)) 779 dptr + *matchoff + *matchlen))
780 return -1; 780 return -1;
781 return 1; 781 return 1;
782 } 782 }
783 783
784 static int refresh_signalling_expectation(struct nf_conn *ct, 784 static int refresh_signalling_expectation(struct nf_conn *ct,
785 union nf_inet_addr *addr, 785 union nf_inet_addr *addr,
786 u8 proto, __be16 port, 786 u8 proto, __be16 port,
787 unsigned int expires) 787 unsigned int expires)
788 { 788 {
789 struct nf_conn_help *help = nfct_help(ct); 789 struct nf_conn_help *help = nfct_help(ct);
790 struct nf_conntrack_expect *exp; 790 struct nf_conntrack_expect *exp;
791 struct hlist_node *n, *next; 791 struct hlist_node *n, *next;
792 int found = 0; 792 int found = 0;
793 793
794 spin_lock_bh(&nf_conntrack_lock); 794 spin_lock_bh(&nf_conntrack_lock);
795 hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) { 795 hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
796 if (exp->class != SIP_EXPECT_SIGNALLING || 796 if (exp->class != SIP_EXPECT_SIGNALLING ||
797 !nf_inet_addr_cmp(&exp->tuple.dst.u3, addr) || 797 !nf_inet_addr_cmp(&exp->tuple.dst.u3, addr) ||
798 exp->tuple.dst.protonum != proto || 798 exp->tuple.dst.protonum != proto ||
799 exp->tuple.dst.u.udp.port != port) 799 exp->tuple.dst.u.udp.port != port)
800 continue; 800 continue;
801 if (!del_timer(&exp->timeout)) 801 if (!del_timer(&exp->timeout))
802 continue; 802 continue;
803 exp->flags &= ~NF_CT_EXPECT_INACTIVE; 803 exp->flags &= ~NF_CT_EXPECT_INACTIVE;
804 exp->timeout.expires = jiffies + expires * HZ; 804 exp->timeout.expires = jiffies + expires * HZ;
805 add_timer(&exp->timeout); 805 add_timer(&exp->timeout);
806 found = 1; 806 found = 1;
807 break; 807 break;
808 } 808 }
809 spin_unlock_bh(&nf_conntrack_lock); 809 spin_unlock_bh(&nf_conntrack_lock);
810 return found; 810 return found;
811 } 811 }
812 812
813 static void flush_expectations(struct nf_conn *ct, bool media) 813 static void flush_expectations(struct nf_conn *ct, bool media)
814 { 814 {
815 struct nf_conn_help *help = nfct_help(ct); 815 struct nf_conn_help *help = nfct_help(ct);
816 struct nf_conntrack_expect *exp; 816 struct nf_conntrack_expect *exp;
817 struct hlist_node *n, *next; 817 struct hlist_node *n, *next;
818 818
819 spin_lock_bh(&nf_conntrack_lock); 819 spin_lock_bh(&nf_conntrack_lock);
820 hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) { 820 hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
821 if ((exp->class != SIP_EXPECT_SIGNALLING) ^ media) 821 if ((exp->class != SIP_EXPECT_SIGNALLING) ^ media)
822 continue; 822 continue;
823 if (!del_timer(&exp->timeout)) 823 if (!del_timer(&exp->timeout))
824 continue; 824 continue;
825 nf_ct_unlink_expect(exp); 825 nf_ct_unlink_expect(exp);
826 nf_ct_expect_put(exp); 826 nf_ct_expect_put(exp);
827 if (!media) 827 if (!media)
828 break; 828 break;
829 } 829 }
830 spin_unlock_bh(&nf_conntrack_lock); 830 spin_unlock_bh(&nf_conntrack_lock);
831 } 831 }
832 832
833 static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff, 833 static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff,
834 const char **dptr, unsigned int *datalen, 834 const char **dptr, unsigned int *datalen,
835 union nf_inet_addr *daddr, __be16 port, 835 union nf_inet_addr *daddr, __be16 port,
836 enum sip_expectation_classes class, 836 enum sip_expectation_classes class,
837 unsigned int mediaoff, unsigned int medialen) 837 unsigned int mediaoff, unsigned int medialen)
838 { 838 {
839 struct nf_conntrack_expect *exp, *rtp_exp, *rtcp_exp; 839 struct nf_conntrack_expect *exp, *rtp_exp, *rtcp_exp;
840 enum ip_conntrack_info ctinfo; 840 enum ip_conntrack_info ctinfo;
841 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 841 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
842 struct net *net = nf_ct_net(ct); 842 struct net *net = nf_ct_net(ct);
843 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 843 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
844 union nf_inet_addr *saddr; 844 union nf_inet_addr *saddr;
845 struct nf_conntrack_tuple tuple; 845 struct nf_conntrack_tuple tuple;
846 int direct_rtp = 0, skip_expect = 0, ret = NF_DROP; 846 int direct_rtp = 0, skip_expect = 0, ret = NF_DROP;
847 u_int16_t base_port; 847 u_int16_t base_port;
848 __be16 rtp_port, rtcp_port; 848 __be16 rtp_port, rtcp_port;
849 typeof(nf_nat_sdp_port_hook) nf_nat_sdp_port; 849 typeof(nf_nat_sdp_port_hook) nf_nat_sdp_port;
850 typeof(nf_nat_sdp_media_hook) nf_nat_sdp_media; 850 typeof(nf_nat_sdp_media_hook) nf_nat_sdp_media;
851 851
852 saddr = NULL; 852 saddr = NULL;
853 if (sip_direct_media) { 853 if (sip_direct_media) {
854 if (!nf_inet_addr_cmp(daddr, &ct->tuplehash[dir].tuple.src.u3)) 854 if (!nf_inet_addr_cmp(daddr, &ct->tuplehash[dir].tuple.src.u3))
855 return NF_ACCEPT; 855 return NF_ACCEPT;
856 saddr = &ct->tuplehash[!dir].tuple.src.u3; 856 saddr = &ct->tuplehash[!dir].tuple.src.u3;
857 } 857 }
858 858
859 /* We need to check whether the registration exists before attempting 859 /* We need to check whether the registration exists before attempting
860 * to register it since we can see the same media description multiple 860 * to register it since we can see the same media description multiple
861 * times on different connections in case multiple endpoints receive 861 * times on different connections in case multiple endpoints receive
862 * the same call. 862 * the same call.
863 * 863 *
864 * RTP optimization: if we find a matching media channel expectation 864 * RTP optimization: if we find a matching media channel expectation
865 * and both the expectation and this connection are SNATed, we assume 865 * and both the expectation and this connection are SNATed, we assume
866 * both sides can reach each other directly and use the final 866 * both sides can reach each other directly and use the final
867 * destination address from the expectation. We still need to keep 867 * destination address from the expectation. We still need to keep
868 * the NATed expectations for media that might arrive from the 868 * the NATed expectations for media that might arrive from the
869 * outside, and additionally need to expect the direct RTP stream 869 * outside, and additionally need to expect the direct RTP stream
870 * in case it passes through us even without NAT. 870 * in case it passes through us even without NAT.
871 */ 871 */
872 memset(&tuple, 0, sizeof(tuple)); 872 memset(&tuple, 0, sizeof(tuple));
873 if (saddr) 873 if (saddr)
874 tuple.src.u3 = *saddr; 874 tuple.src.u3 = *saddr;
875 tuple.src.l3num = nf_ct_l3num(ct); 875 tuple.src.l3num = nf_ct_l3num(ct);
876 tuple.dst.protonum = IPPROTO_UDP; 876 tuple.dst.protonum = IPPROTO_UDP;
877 tuple.dst.u3 = *daddr; 877 tuple.dst.u3 = *daddr;
878 tuple.dst.u.udp.port = port; 878 tuple.dst.u.udp.port = port;
879 879
880 rcu_read_lock(); 880 rcu_read_lock();
881 do { 881 do {
882 exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple); 882 exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple);
883 883
884 if (!exp || exp->master == ct || 884 if (!exp || exp->master == ct ||
885 nfct_help(exp->master)->helper != nfct_help(ct)->helper || 885 nfct_help(exp->master)->helper != nfct_help(ct)->helper ||
886 exp->class != class) 886 exp->class != class)
887 break; 887 break;
888 #ifdef CONFIG_NF_NAT_NEEDED 888 #ifdef CONFIG_NF_NAT_NEEDED
889 if (exp->tuple.src.l3num == AF_INET && !direct_rtp && 889 if (exp->tuple.src.l3num == AF_INET && !direct_rtp &&
890 (exp->saved_ip != exp->tuple.dst.u3.ip || 890 (exp->saved_ip != exp->tuple.dst.u3.ip ||
891 exp->saved_proto.udp.port != exp->tuple.dst.u.udp.port) && 891 exp->saved_proto.udp.port != exp->tuple.dst.u.udp.port) &&
892 ct->status & IPS_NAT_MASK) { 892 ct->status & IPS_NAT_MASK) {
893 daddr->ip = exp->saved_ip; 893 daddr->ip = exp->saved_ip;
894 tuple.dst.u3.ip = exp->saved_ip; 894 tuple.dst.u3.ip = exp->saved_ip;
895 tuple.dst.u.udp.port = exp->saved_proto.udp.port; 895 tuple.dst.u.udp.port = exp->saved_proto.udp.port;
896 direct_rtp = 1; 896 direct_rtp = 1;
897 } else 897 } else
898 #endif 898 #endif
899 skip_expect = 1; 899 skip_expect = 1;
900 } while (!skip_expect); 900 } while (!skip_expect);
901 rcu_read_unlock(); 901 rcu_read_unlock();
902 902
903 base_port = ntohs(tuple.dst.u.udp.port) & ~1; 903 base_port = ntohs(tuple.dst.u.udp.port) & ~1;
904 rtp_port = htons(base_port); 904 rtp_port = htons(base_port);
905 rtcp_port = htons(base_port + 1); 905 rtcp_port = htons(base_port + 1);
906 906
907 if (direct_rtp) { 907 if (direct_rtp) {
908 nf_nat_sdp_port = rcu_dereference(nf_nat_sdp_port_hook); 908 nf_nat_sdp_port = rcu_dereference(nf_nat_sdp_port_hook);
909 if (nf_nat_sdp_port && 909 if (nf_nat_sdp_port &&
910 !nf_nat_sdp_port(skb, dataoff, dptr, datalen, 910 !nf_nat_sdp_port(skb, dataoff, dptr, datalen,
911 mediaoff, medialen, ntohs(rtp_port))) 911 mediaoff, medialen, ntohs(rtp_port)))
912 goto err1; 912 goto err1;
913 } 913 }
914 914
915 if (skip_expect) 915 if (skip_expect)
916 return NF_ACCEPT; 916 return NF_ACCEPT;
917 917
918 rtp_exp = nf_ct_expect_alloc(ct); 918 rtp_exp = nf_ct_expect_alloc(ct);
919 if (rtp_exp == NULL) 919 if (rtp_exp == NULL)
920 goto err1; 920 goto err1;
921 nf_ct_expect_init(rtp_exp, class, nf_ct_l3num(ct), saddr, daddr, 921 nf_ct_expect_init(rtp_exp, class, nf_ct_l3num(ct), saddr, daddr,
922 IPPROTO_UDP, NULL, &rtp_port); 922 IPPROTO_UDP, NULL, &rtp_port);
923 923
924 rtcp_exp = nf_ct_expect_alloc(ct); 924 rtcp_exp = nf_ct_expect_alloc(ct);
925 if (rtcp_exp == NULL) 925 if (rtcp_exp == NULL)
926 goto err2; 926 goto err2;
927 nf_ct_expect_init(rtcp_exp, class, nf_ct_l3num(ct), saddr, daddr, 927 nf_ct_expect_init(rtcp_exp, class, nf_ct_l3num(ct), saddr, daddr,
928 IPPROTO_UDP, NULL, &rtcp_port); 928 IPPROTO_UDP, NULL, &rtcp_port);
929 929
930 nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook); 930 nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook);
931 if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp) 931 if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp)
932 ret = nf_nat_sdp_media(skb, dataoff, dptr, datalen, 932 ret = nf_nat_sdp_media(skb, dataoff, dptr, datalen,
933 rtp_exp, rtcp_exp, 933 rtp_exp, rtcp_exp,
934 mediaoff, medialen, daddr); 934 mediaoff, medialen, daddr);
935 else { 935 else {
936 if (nf_ct_expect_related(rtp_exp) == 0) { 936 if (nf_ct_expect_related(rtp_exp) == 0) {
937 if (nf_ct_expect_related(rtcp_exp) != 0) 937 if (nf_ct_expect_related(rtcp_exp) != 0)
938 nf_ct_unexpect_related(rtp_exp); 938 nf_ct_unexpect_related(rtp_exp);
939 else 939 else
940 ret = NF_ACCEPT; 940 ret = NF_ACCEPT;
941 } 941 }
942 } 942 }
943 nf_ct_expect_put(rtcp_exp); 943 nf_ct_expect_put(rtcp_exp);
944 err2: 944 err2:
945 nf_ct_expect_put(rtp_exp); 945 nf_ct_expect_put(rtp_exp);
946 err1: 946 err1:
947 return ret; 947 return ret;
948 } 948 }
949 949
950 static const struct sdp_media_type sdp_media_types[] = { 950 static const struct sdp_media_type sdp_media_types[] = {
951 SDP_MEDIA_TYPE("audio ", SIP_EXPECT_AUDIO), 951 SDP_MEDIA_TYPE("audio ", SIP_EXPECT_AUDIO),
952 SDP_MEDIA_TYPE("video ", SIP_EXPECT_VIDEO), 952 SDP_MEDIA_TYPE("video ", SIP_EXPECT_VIDEO),
953 SDP_MEDIA_TYPE("image ", SIP_EXPECT_IMAGE), 953 SDP_MEDIA_TYPE("image ", SIP_EXPECT_IMAGE),
954 }; 954 };
955 955
956 static const struct sdp_media_type *sdp_media_type(const char *dptr, 956 static const struct sdp_media_type *sdp_media_type(const char *dptr,
957 unsigned int matchoff, 957 unsigned int matchoff,
958 unsigned int matchlen) 958 unsigned int matchlen)
959 { 959 {
960 const struct sdp_media_type *t; 960 const struct sdp_media_type *t;
961 unsigned int i; 961 unsigned int i;
962 962
963 for (i = 0; i < ARRAY_SIZE(sdp_media_types); i++) { 963 for (i = 0; i < ARRAY_SIZE(sdp_media_types); i++) {
964 t = &sdp_media_types[i]; 964 t = &sdp_media_types[i];
965 if (matchlen < t->len || 965 if (matchlen < t->len ||
966 strncmp(dptr + matchoff, t->name, t->len)) 966 strncmp(dptr + matchoff, t->name, t->len))
967 continue; 967 continue;
968 return t; 968 return t;
969 } 969 }
970 return NULL; 970 return NULL;
971 } 971 }
972 972
973 static int process_sdp(struct sk_buff *skb, unsigned int dataoff, 973 static int process_sdp(struct sk_buff *skb, unsigned int dataoff,
974 const char **dptr, unsigned int *datalen, 974 const char **dptr, unsigned int *datalen,
975 unsigned int cseq) 975 unsigned int cseq)
976 { 976 {
977 enum ip_conntrack_info ctinfo; 977 enum ip_conntrack_info ctinfo;
978 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 978 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
979 unsigned int matchoff, matchlen; 979 unsigned int matchoff, matchlen;
980 unsigned int mediaoff, medialen; 980 unsigned int mediaoff, medialen;
981 unsigned int sdpoff; 981 unsigned int sdpoff;
982 unsigned int caddr_len, maddr_len; 982 unsigned int caddr_len, maddr_len;
983 unsigned int i; 983 unsigned int i;
984 union nf_inet_addr caddr, maddr, rtp_addr; 984 union nf_inet_addr caddr, maddr, rtp_addr;
985 unsigned int port; 985 unsigned int port;
986 enum sdp_header_types c_hdr; 986 enum sdp_header_types c_hdr;
987 const struct sdp_media_type *t; 987 const struct sdp_media_type *t;
988 int ret = NF_ACCEPT; 988 int ret = NF_ACCEPT;
989 typeof(nf_nat_sdp_addr_hook) nf_nat_sdp_addr; 989 typeof(nf_nat_sdp_addr_hook) nf_nat_sdp_addr;
990 typeof(nf_nat_sdp_session_hook) nf_nat_sdp_session; 990 typeof(nf_nat_sdp_session_hook) nf_nat_sdp_session;
991 991
992 nf_nat_sdp_addr = rcu_dereference(nf_nat_sdp_addr_hook); 992 nf_nat_sdp_addr = rcu_dereference(nf_nat_sdp_addr_hook);
993 c_hdr = nf_ct_l3num(ct) == AF_INET ? SDP_HDR_CONNECTION_IP4 : 993 c_hdr = nf_ct_l3num(ct) == AF_INET ? SDP_HDR_CONNECTION_IP4 :
994 SDP_HDR_CONNECTION_IP6; 994 SDP_HDR_CONNECTION_IP6;
995 995
996 /* Find beginning of session description */ 996 /* Find beginning of session description */
997 if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen, 997 if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen,
998 SDP_HDR_VERSION, SDP_HDR_UNSPEC, 998 SDP_HDR_VERSION, SDP_HDR_UNSPEC,
999 &matchoff, &matchlen) <= 0) 999 &matchoff, &matchlen) <= 0)
1000 return NF_ACCEPT; 1000 return NF_ACCEPT;
1001 sdpoff = matchoff; 1001 sdpoff = matchoff;
1002 1002
1003 /* The connection information is contained in the session description 1003 /* The connection information is contained in the session description
1004 * and/or once per media description. The first media description marks 1004 * and/or once per media description. The first media description marks
1005 * the end of the session description. */ 1005 * the end of the session description. */
1006 caddr_len = 0; 1006 caddr_len = 0;
1007 if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen, 1007 if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen,
1008 c_hdr, SDP_HDR_MEDIA, 1008 c_hdr, SDP_HDR_MEDIA,
1009 &matchoff, &matchlen, &caddr) > 0) 1009 &matchoff, &matchlen, &caddr) > 0)
1010 caddr_len = matchlen; 1010 caddr_len = matchlen;
1011 1011
1012 mediaoff = sdpoff; 1012 mediaoff = sdpoff;
1013 for (i = 0; i < ARRAY_SIZE(sdp_media_types); ) { 1013 for (i = 0; i < ARRAY_SIZE(sdp_media_types); ) {
1014 if (ct_sip_get_sdp_header(ct, *dptr, mediaoff, *datalen, 1014 if (ct_sip_get_sdp_header(ct, *dptr, mediaoff, *datalen,
1015 SDP_HDR_MEDIA, SDP_HDR_UNSPEC, 1015 SDP_HDR_MEDIA, SDP_HDR_UNSPEC,
1016 &mediaoff, &medialen) <= 0) 1016 &mediaoff, &medialen) <= 0)
1017 break; 1017 break;
1018 1018
1019 /* Get media type and port number. A media port value of zero 1019 /* Get media type and port number. A media port value of zero
1020 * indicates an inactive stream. */ 1020 * indicates an inactive stream. */
1021 t = sdp_media_type(*dptr, mediaoff, medialen); 1021 t = sdp_media_type(*dptr, mediaoff, medialen);
1022 if (!t) { 1022 if (!t) {
1023 mediaoff += medialen; 1023 mediaoff += medialen;
1024 continue; 1024 continue;
1025 } 1025 }
1026 mediaoff += t->len; 1026 mediaoff += t->len;
1027 medialen -= t->len; 1027 medialen -= t->len;
1028 1028
1029 port = simple_strtoul(*dptr + mediaoff, NULL, 10); 1029 port = simple_strtoul(*dptr + mediaoff, NULL, 10);
1030 if (port == 0) 1030 if (port == 0)
1031 continue; 1031 continue;
1032 if (port < 1024 || port > 65535) 1032 if (port < 1024 || port > 65535)
1033 return NF_DROP; 1033 return NF_DROP;
1034 1034
1035 /* The media description overrides the session description. */ 1035 /* The media description overrides the session description. */
1036 maddr_len = 0; 1036 maddr_len = 0;
1037 if (ct_sip_parse_sdp_addr(ct, *dptr, mediaoff, *datalen, 1037 if (ct_sip_parse_sdp_addr(ct, *dptr, mediaoff, *datalen,
1038 c_hdr, SDP_HDR_MEDIA, 1038 c_hdr, SDP_HDR_MEDIA,
1039 &matchoff, &matchlen, &maddr) > 0) { 1039 &matchoff, &matchlen, &maddr) > 0) {
1040 maddr_len = matchlen; 1040 maddr_len = matchlen;
1041 memcpy(&rtp_addr, &maddr, sizeof(rtp_addr)); 1041 memcpy(&rtp_addr, &maddr, sizeof(rtp_addr));
1042 } else if (caddr_len) 1042 } else if (caddr_len)
1043 memcpy(&rtp_addr, &caddr, sizeof(rtp_addr)); 1043 memcpy(&rtp_addr, &caddr, sizeof(rtp_addr));
1044 else 1044 else
1045 return NF_DROP; 1045 return NF_DROP;
1046 1046
1047 ret = set_expected_rtp_rtcp(skb, dataoff, dptr, datalen, 1047 ret = set_expected_rtp_rtcp(skb, dataoff, dptr, datalen,
1048 &rtp_addr, htons(port), t->class, 1048 &rtp_addr, htons(port), t->class,
1049 mediaoff, medialen); 1049 mediaoff, medialen);
1050 if (ret != NF_ACCEPT) 1050 if (ret != NF_ACCEPT)
1051 return ret; 1051 return ret;
1052 1052
1053 /* Update media connection address if present */ 1053 /* Update media connection address if present */
1054 if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) { 1054 if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) {
1055 ret = nf_nat_sdp_addr(skb, dataoff, dptr, datalen, 1055 ret = nf_nat_sdp_addr(skb, dataoff, dptr, datalen,
1056 mediaoff, c_hdr, SDP_HDR_MEDIA, 1056 mediaoff, c_hdr, SDP_HDR_MEDIA,
1057 &rtp_addr); 1057 &rtp_addr);
1058 if (ret != NF_ACCEPT) 1058 if (ret != NF_ACCEPT)
1059 return ret; 1059 return ret;
1060 } 1060 }
1061 i++; 1061 i++;
1062 } 1062 }
1063 1063
1064 /* Update session connection and owner addresses */ 1064 /* Update session connection and owner addresses */
1065 nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook); 1065 nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook);
1066 if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK) 1066 if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK)
1067 ret = nf_nat_sdp_session(skb, dataoff, dptr, datalen, sdpoff, 1067 ret = nf_nat_sdp_session(skb, dataoff, dptr, datalen, sdpoff,
1068 &rtp_addr); 1068 &rtp_addr);
1069 1069
1070 return ret; 1070 return ret;
1071 } 1071 }
1072 static int process_invite_response(struct sk_buff *skb, unsigned int dataoff, 1072 static int process_invite_response(struct sk_buff *skb, unsigned int dataoff,
1073 const char **dptr, unsigned int *datalen, 1073 const char **dptr, unsigned int *datalen,
1074 unsigned int cseq, unsigned int code) 1074 unsigned int cseq, unsigned int code)
1075 { 1075 {
1076 enum ip_conntrack_info ctinfo; 1076 enum ip_conntrack_info ctinfo;
1077 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1077 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1078 struct nf_conn_help *help = nfct_help(ct); 1078 struct nf_conn_help *help = nfct_help(ct);
1079 1079
1080 if ((code >= 100 && code <= 199) || 1080 if ((code >= 100 && code <= 199) ||
1081 (code >= 200 && code <= 299)) 1081 (code >= 200 && code <= 299))
1082 return process_sdp(skb, dataoff, dptr, datalen, cseq); 1082 return process_sdp(skb, dataoff, dptr, datalen, cseq);
1083 else if (help->help.ct_sip_info.invite_cseq == cseq) 1083 else if (help->help.ct_sip_info.invite_cseq == cseq)
1084 flush_expectations(ct, true); 1084 flush_expectations(ct, true);
1085 return NF_ACCEPT; 1085 return NF_ACCEPT;
1086 } 1086 }
1087 1087
1088 static int process_update_response(struct sk_buff *skb, unsigned int dataoff, 1088 static int process_update_response(struct sk_buff *skb, unsigned int dataoff,
1089 const char **dptr, unsigned int *datalen, 1089 const char **dptr, unsigned int *datalen,
1090 unsigned int cseq, unsigned int code) 1090 unsigned int cseq, unsigned int code)
1091 { 1091 {
1092 enum ip_conntrack_info ctinfo; 1092 enum ip_conntrack_info ctinfo;
1093 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1093 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1094 struct nf_conn_help *help = nfct_help(ct); 1094 struct nf_conn_help *help = nfct_help(ct);
1095 1095
1096 if ((code >= 100 && code <= 199) || 1096 if ((code >= 100 && code <= 199) ||
1097 (code >= 200 && code <= 299)) 1097 (code >= 200 && code <= 299))
1098 return process_sdp(skb, dataoff, dptr, datalen, cseq); 1098 return process_sdp(skb, dataoff, dptr, datalen, cseq);
1099 else if (help->help.ct_sip_info.invite_cseq == cseq) 1099 else if (help->help.ct_sip_info.invite_cseq == cseq)
1100 flush_expectations(ct, true); 1100 flush_expectations(ct, true);
1101 return NF_ACCEPT; 1101 return NF_ACCEPT;
1102 } 1102 }
1103 1103
1104 static int process_prack_response(struct sk_buff *skb, unsigned int dataoff, 1104 static int process_prack_response(struct sk_buff *skb, unsigned int dataoff,
1105 const char **dptr, unsigned int *datalen, 1105 const char **dptr, unsigned int *datalen,
1106 unsigned int cseq, unsigned int code) 1106 unsigned int cseq, unsigned int code)
1107 { 1107 {
1108 enum ip_conntrack_info ctinfo; 1108 enum ip_conntrack_info ctinfo;
1109 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1109 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1110 struct nf_conn_help *help = nfct_help(ct); 1110 struct nf_conn_help *help = nfct_help(ct);
1111 1111
1112 if ((code >= 100 && code <= 199) || 1112 if ((code >= 100 && code <= 199) ||
1113 (code >= 200 && code <= 299)) 1113 (code >= 200 && code <= 299))
1114 return process_sdp(skb, dataoff, dptr, datalen, cseq); 1114 return process_sdp(skb, dataoff, dptr, datalen, cseq);
1115 else if (help->help.ct_sip_info.invite_cseq == cseq) 1115 else if (help->help.ct_sip_info.invite_cseq == cseq)
1116 flush_expectations(ct, true); 1116 flush_expectations(ct, true);
1117 return NF_ACCEPT; 1117 return NF_ACCEPT;
1118 } 1118 }
1119 1119
1120 static int process_invite_request(struct sk_buff *skb, unsigned int dataoff, 1120 static int process_invite_request(struct sk_buff *skb, unsigned int dataoff,
1121 const char **dptr, unsigned int *datalen, 1121 const char **dptr, unsigned int *datalen,
1122 unsigned int cseq) 1122 unsigned int cseq)
1123 { 1123 {
1124 enum ip_conntrack_info ctinfo; 1124 enum ip_conntrack_info ctinfo;
1125 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1125 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1126 struct nf_conn_help *help = nfct_help(ct); 1126 struct nf_conn_help *help = nfct_help(ct);
1127 unsigned int ret; 1127 unsigned int ret;
1128 1128
1129 flush_expectations(ct, true); 1129 flush_expectations(ct, true);
1130 ret = process_sdp(skb, dataoff, dptr, datalen, cseq); 1130 ret = process_sdp(skb, dataoff, dptr, datalen, cseq);
1131 if (ret == NF_ACCEPT) 1131 if (ret == NF_ACCEPT)
1132 help->help.ct_sip_info.invite_cseq = cseq; 1132 help->help.ct_sip_info.invite_cseq = cseq;
1133 return ret; 1133 return ret;
1134 } 1134 }
1135 1135
1136 static int process_bye_request(struct sk_buff *skb, unsigned int dataoff, 1136 static int process_bye_request(struct sk_buff *skb, unsigned int dataoff,
1137 const char **dptr, unsigned int *datalen, 1137 const char **dptr, unsigned int *datalen,
1138 unsigned int cseq) 1138 unsigned int cseq)
1139 { 1139 {
1140 enum ip_conntrack_info ctinfo; 1140 enum ip_conntrack_info ctinfo;
1141 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1141 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1142 1142
1143 flush_expectations(ct, true); 1143 flush_expectations(ct, true);
1144 return NF_ACCEPT; 1144 return NF_ACCEPT;
1145 } 1145 }
1146 1146
1147 /* Parse a REGISTER request and create a permanent expectation for incoming 1147 /* Parse a REGISTER request and create a permanent expectation for incoming
1148 * signalling connections. The expectation is marked inactive and is activated 1148 * signalling connections. The expectation is marked inactive and is activated
1149 * when receiving a response indicating success from the registrar. 1149 * when receiving a response indicating success from the registrar.
1150 */ 1150 */
1151 static int process_register_request(struct sk_buff *skb, unsigned int dataoff, 1151 static int process_register_request(struct sk_buff *skb, unsigned int dataoff,
1152 const char **dptr, unsigned int *datalen, 1152 const char **dptr, unsigned int *datalen,
1153 unsigned int cseq) 1153 unsigned int cseq)
1154 { 1154 {
1155 enum ip_conntrack_info ctinfo; 1155 enum ip_conntrack_info ctinfo;
1156 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1156 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1157 struct nf_conn_help *help = nfct_help(ct); 1157 struct nf_conn_help *help = nfct_help(ct);
1158 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 1158 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
1159 unsigned int matchoff, matchlen; 1159 unsigned int matchoff, matchlen;
1160 struct nf_conntrack_expect *exp; 1160 struct nf_conntrack_expect *exp;
1161 union nf_inet_addr *saddr, daddr; 1161 union nf_inet_addr *saddr, daddr;
1162 __be16 port; 1162 __be16 port;
1163 u8 proto; 1163 u8 proto;
1164 unsigned int expires = 0; 1164 unsigned int expires = 0;
1165 int ret; 1165 int ret;
1166 typeof(nf_nat_sip_expect_hook) nf_nat_sip_expect; 1166 typeof(nf_nat_sip_expect_hook) nf_nat_sip_expect;
1167 1167
1168 /* Expected connections can not register again. */ 1168 /* Expected connections can not register again. */
1169 if (ct->status & IPS_EXPECTED) 1169 if (ct->status & IPS_EXPECTED)
1170 return NF_ACCEPT; 1170 return NF_ACCEPT;
1171 1171
1172 /* We must check the expiration time: a value of zero signals the 1172 /* We must check the expiration time: a value of zero signals the
1173 * registrar to release the binding. We'll remove our expectation 1173 * registrar to release the binding. We'll remove our expectation
1174 * when receiving the new bindings in the response, but we don't 1174 * when receiving the new bindings in the response, but we don't
1175 * want to create new ones. 1175 * want to create new ones.
1176 * 1176 *
1177 * The expiration time may be contained in Expires: header, the 1177 * The expiration time may be contained in Expires: header, the
1178 * Contact: header parameters or the URI parameters. 1178 * Contact: header parameters or the URI parameters.
1179 */ 1179 */
1180 if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_EXPIRES, 1180 if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_EXPIRES,
1181 &matchoff, &matchlen) > 0) 1181 &matchoff, &matchlen) > 0)
1182 expires = simple_strtoul(*dptr + matchoff, NULL, 10); 1182 expires = simple_strtoul(*dptr + matchoff, NULL, 10);
1183 1183
1184 ret = ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, 1184 ret = ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
1185 SIP_HDR_CONTACT, NULL, 1185 SIP_HDR_CONTACT, NULL,
1186 &matchoff, &matchlen, &daddr, &port); 1186 &matchoff, &matchlen, &daddr, &port);
1187 if (ret < 0) 1187 if (ret < 0)
1188 return NF_DROP; 1188 return NF_DROP;
1189 else if (ret == 0) 1189 else if (ret == 0)
1190 return NF_ACCEPT; 1190 return NF_ACCEPT;
1191 1191
1192 /* We don't support third-party registrations */ 1192 /* We don't support third-party registrations */
1193 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, &daddr)) 1193 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, &daddr))
1194 return NF_ACCEPT; 1194 return NF_ACCEPT;
1195 1195
1196 if (ct_sip_parse_transport(ct, *dptr, matchoff + matchlen, *datalen, 1196 if (ct_sip_parse_transport(ct, *dptr, matchoff + matchlen, *datalen,
1197 &proto) == 0) 1197 &proto) == 0)
1198 return NF_ACCEPT; 1198 return NF_ACCEPT;
1199 1199
1200 if (ct_sip_parse_numerical_param(ct, *dptr, 1200 if (ct_sip_parse_numerical_param(ct, *dptr,
1201 matchoff + matchlen, *datalen, 1201 matchoff + matchlen, *datalen,
1202 "expires=", NULL, NULL, &expires) < 0) 1202 "expires=", NULL, NULL, &expires) < 0)
1203 return NF_DROP; 1203 return NF_DROP;
1204 1204
1205 if (expires == 0) { 1205 if (expires == 0) {
1206 ret = NF_ACCEPT; 1206 ret = NF_ACCEPT;
1207 goto store_cseq; 1207 goto store_cseq;
1208 } 1208 }
1209 1209
1210 exp = nf_ct_expect_alloc(ct); 1210 exp = nf_ct_expect_alloc(ct);
1211 if (!exp) 1211 if (!exp)
1212 return NF_DROP; 1212 return NF_DROP;
1213 1213
1214 saddr = NULL; 1214 saddr = NULL;
1215 if (sip_direct_signalling) 1215 if (sip_direct_signalling)
1216 saddr = &ct->tuplehash[!dir].tuple.src.u3; 1216 saddr = &ct->tuplehash[!dir].tuple.src.u3;
1217 1217
1218 nf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, nf_ct_l3num(ct), 1218 nf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, nf_ct_l3num(ct),
1219 saddr, &daddr, proto, NULL, &port); 1219 saddr, &daddr, proto, NULL, &port);
1220 exp->timeout.expires = sip_timeout * HZ; 1220 exp->timeout.expires = sip_timeout * HZ;
1221 exp->helper = nfct_help(ct)->helper; 1221 exp->helper = nfct_help(ct)->helper;
1222 exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE; 1222 exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE;
1223 1223
1224 nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook); 1224 nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook);
1225 if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK) 1225 if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK)
1226 ret = nf_nat_sip_expect(skb, dataoff, dptr, datalen, exp, 1226 ret = nf_nat_sip_expect(skb, dataoff, dptr, datalen, exp,
1227 matchoff, matchlen); 1227 matchoff, matchlen);
1228 else { 1228 else {
1229 if (nf_ct_expect_related(exp) != 0) 1229 if (nf_ct_expect_related(exp) != 0)
1230 ret = NF_DROP; 1230 ret = NF_DROP;
1231 else 1231 else
1232 ret = NF_ACCEPT; 1232 ret = NF_ACCEPT;
1233 } 1233 }
1234 nf_ct_expect_put(exp); 1234 nf_ct_expect_put(exp);
1235 1235
1236 store_cseq: 1236 store_cseq:
1237 if (ret == NF_ACCEPT) 1237 if (ret == NF_ACCEPT)
1238 help->help.ct_sip_info.register_cseq = cseq; 1238 help->help.ct_sip_info.register_cseq = cseq;
1239 return ret; 1239 return ret;
1240 } 1240 }
1241 1241
1242 static int process_register_response(struct sk_buff *skb, unsigned int dataoff, 1242 static int process_register_response(struct sk_buff *skb, unsigned int dataoff,
1243 const char **dptr, unsigned int *datalen, 1243 const char **dptr, unsigned int *datalen,
1244 unsigned int cseq, unsigned int code) 1244 unsigned int cseq, unsigned int code)
1245 { 1245 {
1246 enum ip_conntrack_info ctinfo; 1246 enum ip_conntrack_info ctinfo;
1247 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1247 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1248 struct nf_conn_help *help = nfct_help(ct); 1248 struct nf_conn_help *help = nfct_help(ct);
1249 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 1249 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
1250 union nf_inet_addr addr; 1250 union nf_inet_addr addr;
1251 __be16 port; 1251 __be16 port;
1252 u8 proto; 1252 u8 proto;
1253 unsigned int matchoff, matchlen, coff = 0; 1253 unsigned int matchoff, matchlen, coff = 0;
1254 unsigned int expires = 0; 1254 unsigned int expires = 0;
1255 int in_contact = 0, ret; 1255 int in_contact = 0, ret;
1256 1256
1257 /* According to RFC 3261, "UAs MUST NOT send a new registration until 1257 /* According to RFC 3261, "UAs MUST NOT send a new registration until
1258 * they have received a final response from the registrar for the 1258 * they have received a final response from the registrar for the
1259 * previous one or the previous REGISTER request has timed out". 1259 * previous one or the previous REGISTER request has timed out".
1260 * 1260 *
1261 * However, some servers fail to detect retransmissions and send late 1261 * However, some servers fail to detect retransmissions and send late
1262 * responses, so we store the sequence number of the last valid 1262 * responses, so we store the sequence number of the last valid
1263 * request and compare it here. 1263 * request and compare it here.
1264 */ 1264 */
1265 if (help->help.ct_sip_info.register_cseq != cseq) 1265 if (help->help.ct_sip_info.register_cseq != cseq)
1266 return NF_ACCEPT; 1266 return NF_ACCEPT;
1267 1267
1268 if (code >= 100 && code <= 199) 1268 if (code >= 100 && code <= 199)
1269 return NF_ACCEPT; 1269 return NF_ACCEPT;
1270 if (code < 200 || code > 299) 1270 if (code < 200 || code > 299)
1271 goto flush; 1271 goto flush;
1272 1272
1273 if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_EXPIRES, 1273 if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_EXPIRES,
1274 &matchoff, &matchlen) > 0) 1274 &matchoff, &matchlen) > 0)
1275 expires = simple_strtoul(*dptr + matchoff, NULL, 10); 1275 expires = simple_strtoul(*dptr + matchoff, NULL, 10);
1276 1276
1277 while (1) { 1277 while (1) {
1278 unsigned int c_expires = expires; 1278 unsigned int c_expires = expires;
1279 1279
1280 ret = ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen, 1280 ret = ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen,
1281 SIP_HDR_CONTACT, &in_contact, 1281 SIP_HDR_CONTACT, &in_contact,
1282 &matchoff, &matchlen, 1282 &matchoff, &matchlen,
1283 &addr, &port); 1283 &addr, &port);
1284 if (ret < 0) 1284 if (ret < 0)
1285 return NF_DROP; 1285 return NF_DROP;
1286 else if (ret == 0) 1286 else if (ret == 0)
1287 break; 1287 break;
1288 1288
1289 /* We don't support third-party registrations */ 1289 /* We don't support third-party registrations */
1290 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, &addr)) 1290 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, &addr))
1291 continue; 1291 continue;
1292 1292
1293 if (ct_sip_parse_transport(ct, *dptr, matchoff + matchlen, 1293 if (ct_sip_parse_transport(ct, *dptr, matchoff + matchlen,
1294 *datalen, &proto) == 0) 1294 *datalen, &proto) == 0)
1295 continue; 1295 continue;
1296 1296
1297 ret = ct_sip_parse_numerical_param(ct, *dptr, 1297 ret = ct_sip_parse_numerical_param(ct, *dptr,
1298 matchoff + matchlen, 1298 matchoff + matchlen,
1299 *datalen, "expires=", 1299 *datalen, "expires=",
1300 NULL, NULL, &c_expires); 1300 NULL, NULL, &c_expires);
1301 if (ret < 0) 1301 if (ret < 0)
1302 return NF_DROP; 1302 return NF_DROP;
1303 if (c_expires == 0) 1303 if (c_expires == 0)
1304 break; 1304 break;
1305 if (refresh_signalling_expectation(ct, &addr, proto, port, 1305 if (refresh_signalling_expectation(ct, &addr, proto, port,
1306 c_expires)) 1306 c_expires))
1307 return NF_ACCEPT; 1307 return NF_ACCEPT;
1308 } 1308 }
1309 1309
1310 flush: 1310 flush:
1311 flush_expectations(ct, false); 1311 flush_expectations(ct, false);
1312 return NF_ACCEPT; 1312 return NF_ACCEPT;
1313 } 1313 }
1314 1314
1315 static const struct sip_handler sip_handlers[] = { 1315 static const struct sip_handler sip_handlers[] = {
1316 SIP_HANDLER("INVITE", process_invite_request, process_invite_response), 1316 SIP_HANDLER("INVITE", process_invite_request, process_invite_response),
1317 SIP_HANDLER("UPDATE", process_sdp, process_update_response), 1317 SIP_HANDLER("UPDATE", process_sdp, process_update_response),
1318 SIP_HANDLER("ACK", process_sdp, NULL), 1318 SIP_HANDLER("ACK", process_sdp, NULL),
1319 SIP_HANDLER("PRACK", process_sdp, process_prack_response), 1319 SIP_HANDLER("PRACK", process_sdp, process_prack_response),
1320 SIP_HANDLER("BYE", process_bye_request, NULL), 1320 SIP_HANDLER("BYE", process_bye_request, NULL),
1321 SIP_HANDLER("REGISTER", process_register_request, process_register_response), 1321 SIP_HANDLER("REGISTER", process_register_request, process_register_response),
1322 }; 1322 };
1323 1323
1324 static int process_sip_response(struct sk_buff *skb, unsigned int dataoff, 1324 static int process_sip_response(struct sk_buff *skb, unsigned int dataoff,
1325 const char **dptr, unsigned int *datalen) 1325 const char **dptr, unsigned int *datalen)
1326 { 1326 {
1327 enum ip_conntrack_info ctinfo; 1327 enum ip_conntrack_info ctinfo;
1328 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1328 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1329 unsigned int matchoff, matchlen, matchend; 1329 unsigned int matchoff, matchlen, matchend;
1330 unsigned int code, cseq, i; 1330 unsigned int code, cseq, i;
1331 1331
1332 if (*datalen < strlen("SIP/2.0 200")) 1332 if (*datalen < strlen("SIP/2.0 200"))
1333 return NF_ACCEPT; 1333 return NF_ACCEPT;
1334 code = simple_strtoul(*dptr + strlen("SIP/2.0 "), NULL, 10); 1334 code = simple_strtoul(*dptr + strlen("SIP/2.0 "), NULL, 10);
1335 if (!code) 1335 if (!code)
1336 return NF_DROP; 1336 return NF_DROP;
1337 1337
1338 if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ, 1338 if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ,
1339 &matchoff, &matchlen) <= 0) 1339 &matchoff, &matchlen) <= 0)
1340 return NF_DROP; 1340 return NF_DROP;
1341 cseq = simple_strtoul(*dptr + matchoff, NULL, 10); 1341 cseq = simple_strtoul(*dptr + matchoff, NULL, 10);
1342 if (!cseq) 1342 if (!cseq)
1343 return NF_DROP; 1343 return NF_DROP;
1344 matchend = matchoff + matchlen + 1; 1344 matchend = matchoff + matchlen + 1;
1345 1345
1346 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { 1346 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
1347 const struct sip_handler *handler; 1347 const struct sip_handler *handler;
1348 1348
1349 handler = &sip_handlers[i]; 1349 handler = &sip_handlers[i];
1350 if (handler->response == NULL) 1350 if (handler->response == NULL)
1351 continue; 1351 continue;
1352 if (*datalen < matchend + handler->len || 1352 if (*datalen < matchend + handler->len ||
1353 strnicmp(*dptr + matchend, handler->method, handler->len)) 1353 strnicmp(*dptr + matchend, handler->method, handler->len))
1354 continue; 1354 continue;
1355 return handler->response(skb, dataoff, dptr, datalen, 1355 return handler->response(skb, dataoff, dptr, datalen,
1356 cseq, code); 1356 cseq, code);
1357 } 1357 }
1358 return NF_ACCEPT; 1358 return NF_ACCEPT;
1359 } 1359 }
1360 1360
1361 static int process_sip_request(struct sk_buff *skb, unsigned int dataoff, 1361 static int process_sip_request(struct sk_buff *skb, unsigned int dataoff,
1362 const char **dptr, unsigned int *datalen) 1362 const char **dptr, unsigned int *datalen)
1363 { 1363 {
1364 enum ip_conntrack_info ctinfo; 1364 enum ip_conntrack_info ctinfo;
1365 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1365 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1366 unsigned int matchoff, matchlen; 1366 unsigned int matchoff, matchlen;
1367 unsigned int cseq, i; 1367 unsigned int cseq, i;
1368 1368
1369 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { 1369 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
1370 const struct sip_handler *handler; 1370 const struct sip_handler *handler;
1371 1371
1372 handler = &sip_handlers[i]; 1372 handler = &sip_handlers[i];
1373 if (handler->request == NULL) 1373 if (handler->request == NULL)
1374 continue; 1374 continue;
1375 if (*datalen < handler->len || 1375 if (*datalen < handler->len ||
1376 strnicmp(*dptr, handler->method, handler->len)) 1376 strnicmp(*dptr, handler->method, handler->len))
1377 continue; 1377 continue;
1378 1378
1379 if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ, 1379 if (ct_sip_get_header(ct, *dptr, 0, *datalen, SIP_HDR_CSEQ,
1380 &matchoff, &matchlen) <= 0) 1380 &matchoff, &matchlen) <= 0)
1381 return NF_DROP; 1381 return NF_DROP;
1382 cseq = simple_strtoul(*dptr + matchoff, NULL, 10); 1382 cseq = simple_strtoul(*dptr + matchoff, NULL, 10);
1383 if (!cseq) 1383 if (!cseq)
1384 return NF_DROP; 1384 return NF_DROP;
1385 1385
1386 return handler->request(skb, dataoff, dptr, datalen, cseq); 1386 return handler->request(skb, dataoff, dptr, datalen, cseq);
1387 } 1387 }
1388 return NF_ACCEPT; 1388 return NF_ACCEPT;
1389 } 1389 }
1390 1390
1391 static int process_sip_msg(struct sk_buff *skb, struct nf_conn *ct, 1391 static int process_sip_msg(struct sk_buff *skb, struct nf_conn *ct,
1392 unsigned int dataoff, const char **dptr, 1392 unsigned int dataoff, const char **dptr,
1393 unsigned int *datalen) 1393 unsigned int *datalen)
1394 { 1394 {
1395 typeof(nf_nat_sip_hook) nf_nat_sip; 1395 typeof(nf_nat_sip_hook) nf_nat_sip;
1396 int ret; 1396 int ret;
1397 1397
1398 if (strnicmp(*dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0) 1398 if (strnicmp(*dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0)
1399 ret = process_sip_request(skb, dataoff, dptr, datalen); 1399 ret = process_sip_request(skb, dataoff, dptr, datalen);
1400 else 1400 else
1401 ret = process_sip_response(skb, dataoff, dptr, datalen); 1401 ret = process_sip_response(skb, dataoff, dptr, datalen);
1402 1402
1403 if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { 1403 if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) {
1404 nf_nat_sip = rcu_dereference(nf_nat_sip_hook); 1404 nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
1405 if (nf_nat_sip && !nf_nat_sip(skb, dataoff, dptr, datalen)) 1405 if (nf_nat_sip && !nf_nat_sip(skb, dataoff, dptr, datalen))
1406 ret = NF_DROP; 1406 ret = NF_DROP;
1407 } 1407 }
1408 1408
1409 return ret; 1409 return ret;
1410 } 1410 }
1411 1411
1412 static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, 1412 static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
1413 struct nf_conn *ct, enum ip_conntrack_info ctinfo) 1413 struct nf_conn *ct, enum ip_conntrack_info ctinfo)
1414 { 1414 {
1415 struct tcphdr *th, _tcph; 1415 struct tcphdr *th, _tcph;
1416 unsigned int dataoff, datalen; 1416 unsigned int dataoff, datalen;
1417 unsigned int matchoff, matchlen, clen; 1417 unsigned int matchoff, matchlen, clen;
1418 unsigned int msglen, origlen; 1418 unsigned int msglen, origlen;
1419 const char *dptr, *end; 1419 const char *dptr, *end;
1420 s16 diff, tdiff = 0; 1420 s16 diff, tdiff = 0;
1421 int ret = NF_ACCEPT; 1421 int ret = NF_ACCEPT;
1422 bool term; 1422 bool term;
1423 typeof(nf_nat_sip_seq_adjust_hook) nf_nat_sip_seq_adjust; 1423 typeof(nf_nat_sip_seq_adjust_hook) nf_nat_sip_seq_adjust;
1424 1424
1425 if (ctinfo != IP_CT_ESTABLISHED && 1425 if (ctinfo != IP_CT_ESTABLISHED &&
1426 ctinfo != IP_CT_ESTABLISHED_REPLY) 1426 ctinfo != IP_CT_ESTABLISHED_REPLY)
1427 return NF_ACCEPT; 1427 return NF_ACCEPT;
1428 1428
1429 /* No Data ? */ 1429 /* No Data ? */
1430 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); 1430 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
1431 if (th == NULL) 1431 if (th == NULL)
1432 return NF_ACCEPT; 1432 return NF_ACCEPT;
1433 dataoff = protoff + th->doff * 4; 1433 dataoff = protoff + th->doff * 4;
1434 if (dataoff >= skb->len) 1434 if (dataoff >= skb->len)
1435 return NF_ACCEPT; 1435 return NF_ACCEPT;
1436 1436
1437 nf_ct_refresh(ct, skb, sip_timeout * HZ); 1437 nf_ct_refresh(ct, skb, sip_timeout * HZ);
1438 1438
1439 if (unlikely(skb_linearize(skb))) 1439 if (unlikely(skb_linearize(skb)))
1440 return NF_DROP; 1440 return NF_DROP;
1441 1441
1442 dptr = skb->data + dataoff; 1442 dptr = skb->data + dataoff;
1443 datalen = skb->len - dataoff; 1443 datalen = skb->len - dataoff;
1444 if (datalen < strlen("SIP/2.0 200")) 1444 if (datalen < strlen("SIP/2.0 200"))
1445 return NF_ACCEPT; 1445 return NF_ACCEPT;
1446 1446
1447 while (1) { 1447 while (1) {
1448 if (ct_sip_get_header(ct, dptr, 0, datalen, 1448 if (ct_sip_get_header(ct, dptr, 0, datalen,
1449 SIP_HDR_CONTENT_LENGTH, 1449 SIP_HDR_CONTENT_LENGTH,
1450 &matchoff, &matchlen) <= 0) 1450 &matchoff, &matchlen) <= 0)
1451 break; 1451 break;
1452 1452
1453 clen = simple_strtoul(dptr + matchoff, (char **)&end, 10); 1453 clen = simple_strtoul(dptr + matchoff, (char **)&end, 10);
1454 if (dptr + matchoff == end) 1454 if (dptr + matchoff == end)
1455 break; 1455 break;
1456 1456
1457 term = false; 1457 term = false;
1458 for (; end + strlen("\r\n\r\n") <= dptr + datalen; end++) { 1458 for (; end + strlen("\r\n\r\n") <= dptr + datalen; end++) {
1459 if (end[0] == '\r' && end[1] == '\n' && 1459 if (end[0] == '\r' && end[1] == '\n' &&
1460 end[2] == '\r' && end[3] == '\n') { 1460 end[2] == '\r' && end[3] == '\n') {
1461 term = true; 1461 term = true;
1462 break; 1462 break;
1463 } 1463 }
1464 } 1464 }
1465 if (!term) 1465 if (!term)
1466 break; 1466 break;
1467 end += strlen("\r\n\r\n") + clen; 1467 end += strlen("\r\n\r\n") + clen;
1468 1468
1469 msglen = origlen = end - dptr; 1469 msglen = origlen = end - dptr;
1470 if (msglen > datalen) 1470 if (msglen > datalen)
1471 return NF_DROP; 1471 return NF_DROP;
1472 1472
1473 ret = process_sip_msg(skb, ct, dataoff, &dptr, &msglen); 1473 ret = process_sip_msg(skb, ct, dataoff, &dptr, &msglen);
1474 if (ret != NF_ACCEPT) 1474 if (ret != NF_ACCEPT)
1475 break; 1475 break;
1476 diff = msglen - origlen; 1476 diff = msglen - origlen;
1477 tdiff += diff; 1477 tdiff += diff;
1478 1478
1479 dataoff += msglen; 1479 dataoff += msglen;
1480 dptr += msglen; 1480 dptr += msglen;
1481 datalen = datalen + diff - msglen; 1481 datalen = datalen + diff - msglen;
1482 } 1482 }
1483 1483
1484 if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { 1484 if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) {
1485 nf_nat_sip_seq_adjust = rcu_dereference(nf_nat_sip_seq_adjust_hook); 1485 nf_nat_sip_seq_adjust = rcu_dereference(nf_nat_sip_seq_adjust_hook);
1486 if (nf_nat_sip_seq_adjust) 1486 if (nf_nat_sip_seq_adjust)
1487 nf_nat_sip_seq_adjust(skb, tdiff); 1487 nf_nat_sip_seq_adjust(skb, tdiff);
1488 } 1488 }
1489 1489
1490 return ret; 1490 return ret;
1491 } 1491 }
1492 1492
1493 static int sip_help_udp(struct sk_buff *skb, unsigned int protoff, 1493 static int sip_help_udp(struct sk_buff *skb, unsigned int protoff,
1494 struct nf_conn *ct, enum ip_conntrack_info ctinfo) 1494 struct nf_conn *ct, enum ip_conntrack_info ctinfo)
1495 { 1495 {
1496 unsigned int dataoff, datalen; 1496 unsigned int dataoff, datalen;
1497 const char *dptr; 1497 const char *dptr;
1498 1498
1499 /* No Data ? */ 1499 /* No Data ? */
1500 dataoff = protoff + sizeof(struct udphdr); 1500 dataoff = protoff + sizeof(struct udphdr);
1501 if (dataoff >= skb->len) 1501 if (dataoff >= skb->len)
1502 return NF_ACCEPT; 1502 return NF_ACCEPT;
1503 1503
1504 nf_ct_refresh(ct, skb, sip_timeout * HZ); 1504 nf_ct_refresh(ct, skb, sip_timeout * HZ);
1505 1505
1506 if (unlikely(skb_linearize(skb))) 1506 if (unlikely(skb_linearize(skb)))
1507 return NF_DROP; 1507 return NF_DROP;
1508 1508
1509 dptr = skb->data + dataoff; 1509 dptr = skb->data + dataoff;
1510 datalen = skb->len - dataoff; 1510 datalen = skb->len - dataoff;
1511 if (datalen < strlen("SIP/2.0 200")) 1511 if (datalen < strlen("SIP/2.0 200"))
1512 return NF_ACCEPT; 1512 return NF_ACCEPT;
1513 1513
1514 return process_sip_msg(skb, ct, dataoff, &dptr, &datalen); 1514 return process_sip_msg(skb, ct, dataoff, &dptr, &datalen);
1515 } 1515 }
1516 1516
1517 static struct nf_conntrack_helper sip[MAX_PORTS][4] __read_mostly; 1517 static struct nf_conntrack_helper sip[MAX_PORTS][4] __read_mostly;
1518 static char sip_names[MAX_PORTS][4][sizeof("sip-65535")] __read_mostly; 1518 static char sip_names[MAX_PORTS][4][sizeof("sip-65535")] __read_mostly;
1519 1519
1520 static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = { 1520 static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = {
1521 [SIP_EXPECT_SIGNALLING] = { 1521 [SIP_EXPECT_SIGNALLING] = {
1522 .name = "signalling", 1522 .name = "signalling",
1523 .max_expected = 1, 1523 .max_expected = 1,
1524 .timeout = 3 * 60, 1524 .timeout = 3 * 60,
1525 }, 1525 },
1526 [SIP_EXPECT_AUDIO] = { 1526 [SIP_EXPECT_AUDIO] = {
1527 .name = "audio", 1527 .name = "audio",
1528 .max_expected = 2 * IP_CT_DIR_MAX, 1528 .max_expected = 2 * IP_CT_DIR_MAX,
1529 .timeout = 3 * 60, 1529 .timeout = 3 * 60,
1530 }, 1530 },
1531 [SIP_EXPECT_VIDEO] = { 1531 [SIP_EXPECT_VIDEO] = {
1532 .name = "video", 1532 .name = "video",
1533 .max_expected = 2 * IP_CT_DIR_MAX, 1533 .max_expected = 2 * IP_CT_DIR_MAX,
1534 .timeout = 3 * 60, 1534 .timeout = 3 * 60,
1535 }, 1535 },
1536 [SIP_EXPECT_IMAGE] = { 1536 [SIP_EXPECT_IMAGE] = {
1537 .name = "image", 1537 .name = "image",
1538 .max_expected = IP_CT_DIR_MAX, 1538 .max_expected = IP_CT_DIR_MAX,
1539 .timeout = 3 * 60, 1539 .timeout = 3 * 60,
1540 }, 1540 },
1541 }; 1541 };
1542 1542
1543 static void nf_conntrack_sip_fini(void) 1543 static void nf_conntrack_sip_fini(void)
1544 { 1544 {
1545 int i, j; 1545 int i, j;
1546 1546
1547 for (i = 0; i < ports_c; i++) { 1547 for (i = 0; i < ports_c; i++) {
1548 for (j = 0; j < ARRAY_SIZE(sip[i]); j++) { 1548 for (j = 0; j < ARRAY_SIZE(sip[i]); j++) {
1549 if (sip[i][j].me == NULL) 1549 if (sip[i][j].me == NULL)
1550 continue; 1550 continue;
1551 nf_conntrack_helper_unregister(&sip[i][j]); 1551 nf_conntrack_helper_unregister(&sip[i][j]);
1552 } 1552 }
1553 } 1553 }
1554 } 1554 }
1555 1555
1556 static int __init nf_conntrack_sip_init(void) 1556 static int __init nf_conntrack_sip_init(void)
1557 { 1557 {
1558 int i, j, ret; 1558 int i, j, ret;
1559 char *tmpname;
1560 1559
1561 if (ports_c == 0) 1560 if (ports_c == 0)
1562 ports[ports_c++] = SIP_PORT; 1561 ports[ports_c++] = SIP_PORT;
1563 1562
1564 for (i = 0; i < ports_c; i++) { 1563 for (i = 0; i < ports_c; i++) {
1565 memset(&sip[i], 0, sizeof(sip[i])); 1564 memset(&sip[i], 0, sizeof(sip[i]));
1566 1565
1567 sip[i][0].tuple.src.l3num = AF_INET; 1566 sip[i][0].tuple.src.l3num = AF_INET;
1568 sip[i][0].tuple.dst.protonum = IPPROTO_UDP; 1567 sip[i][0].tuple.dst.protonum = IPPROTO_UDP;
1569 sip[i][0].help = sip_help_udp; 1568 sip[i][0].help = sip_help_udp;
1570 sip[i][1].tuple.src.l3num = AF_INET; 1569 sip[i][1].tuple.src.l3num = AF_INET;
1571 sip[i][1].tuple.dst.protonum = IPPROTO_TCP; 1570 sip[i][1].tuple.dst.protonum = IPPROTO_TCP;
1572 sip[i][1].help = sip_help_tcp; 1571 sip[i][1].help = sip_help_tcp;
1573 1572
1574 sip[i][2].tuple.src.l3num = AF_INET6; 1573 sip[i][2].tuple.src.l3num = AF_INET6;
1575 sip[i][2].tuple.dst.protonum = IPPROTO_UDP; 1574 sip[i][2].tuple.dst.protonum = IPPROTO_UDP;
1576 sip[i][2].help = sip_help_udp; 1575 sip[i][2].help = sip_help_udp;
1577 sip[i][3].tuple.src.l3num = AF_INET6; 1576 sip[i][3].tuple.src.l3num = AF_INET6;
1578 sip[i][3].tuple.dst.protonum = IPPROTO_TCP; 1577 sip[i][3].tuple.dst.protonum = IPPROTO_TCP;
1579 sip[i][3].help = sip_help_tcp; 1578 sip[i][3].help = sip_help_tcp;
1580 1579
1581 for (j = 0; j < ARRAY_SIZE(sip[i]); j++) { 1580 for (j = 0; j < ARRAY_SIZE(sip[i]); j++) {
1582 sip[i][j].tuple.src.u.udp.port = htons(ports[i]); 1581 sip[i][j].tuple.src.u.udp.port = htons(ports[i]);
1583 sip[i][j].expect_policy = sip_exp_policy; 1582 sip[i][j].expect_policy = sip_exp_policy;
1584 sip[i][j].expect_class_max = SIP_EXPECT_MAX; 1583 sip[i][j].expect_class_max = SIP_EXPECT_MAX;
1585 sip[i][j].me = THIS_MODULE; 1584 sip[i][j].me = THIS_MODULE;
1586 1585
1587 tmpname = &sip_names[i][j][0];
1588 if (ports[i] == SIP_PORT) 1586 if (ports[i] == SIP_PORT)
1589 sprintf(tmpname, "sip"); 1587 sprintf(sip_names[i][j], "sip");
1590 else 1588 else
1591 sprintf(tmpname, "sip-%u", i); 1589 sprintf(sip_names[i][j], "sip-%u", i);
1592 sip[i][j].name = tmpname;
1593 1590
1594 pr_debug("port #%u: %u\n", i, ports[i]); 1591 pr_debug("port #%u: %u\n", i, ports[i]);
1595 1592
1596 ret = nf_conntrack_helper_register(&sip[i][j]); 1593 ret = nf_conntrack_helper_register(&sip[i][j]);
1597 if (ret) { 1594 if (ret) {
1598 printk(KERN_ERR "nf_ct_sip: failed to register" 1595 printk(KERN_ERR "nf_ct_sip: failed to register"
1599 " helper for pf: %u port: %u\n", 1596 " helper for pf: %u port: %u\n",
1600 sip[i][j].tuple.src.l3num, ports[i]); 1597 sip[i][j].tuple.src.l3num, ports[i]);
1601 nf_conntrack_sip_fini(); 1598 nf_conntrack_sip_fini();
1602 return ret; 1599 return ret;
1603 } 1600 }
1604 } 1601 }
1605 } 1602 }
1606 return 0; 1603 return 0;
1607 } 1604 }
1608 1605
1609 module_init(nf_conntrack_sip_init); 1606 module_init(nf_conntrack_sip_init);
1610 module_exit(nf_conntrack_sip_fini); 1607 module_exit(nf_conntrack_sip_fini);
1611 1608
net/netfilter/nf_conntrack_tftp.c
1 /* (C) 2001-2002 Magnus Boden <mb@ozaba.mine.nu> 1 /* (C) 2001-2002 Magnus Boden <mb@ozaba.mine.nu>
2 * 2 *
3 * This program is free software; you can redistribute it and/or modify 3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as 4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation. 5 * published by the Free Software Foundation.
6 */ 6 */
7 7
8 #include <linux/module.h> 8 #include <linux/module.h>
9 #include <linux/moduleparam.h> 9 #include <linux/moduleparam.h>
10 #include <linux/in.h> 10 #include <linux/in.h>
11 #include <linux/udp.h> 11 #include <linux/udp.h>
12 #include <linux/netfilter.h> 12 #include <linux/netfilter.h>
13 13
14 #include <net/netfilter/nf_conntrack.h> 14 #include <net/netfilter/nf_conntrack.h>
15 #include <net/netfilter/nf_conntrack_tuple.h> 15 #include <net/netfilter/nf_conntrack_tuple.h>
16 #include <net/netfilter/nf_conntrack_expect.h> 16 #include <net/netfilter/nf_conntrack_expect.h>
17 #include <net/netfilter/nf_conntrack_ecache.h> 17 #include <net/netfilter/nf_conntrack_ecache.h>
18 #include <net/netfilter/nf_conntrack_helper.h> 18 #include <net/netfilter/nf_conntrack_helper.h>
19 #include <linux/netfilter/nf_conntrack_tftp.h> 19 #include <linux/netfilter/nf_conntrack_tftp.h>
20 20
21 MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>"); 21 MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
22 MODULE_DESCRIPTION("TFTP connection tracking helper"); 22 MODULE_DESCRIPTION("TFTP connection tracking helper");
23 MODULE_LICENSE("GPL"); 23 MODULE_LICENSE("GPL");
24 MODULE_ALIAS("ip_conntrack_tftp"); 24 MODULE_ALIAS("ip_conntrack_tftp");
25 MODULE_ALIAS_NFCT_HELPER("tftp"); 25 MODULE_ALIAS_NFCT_HELPER("tftp");
26 26
27 #define MAX_PORTS 8 27 #define MAX_PORTS 8
28 static unsigned short ports[MAX_PORTS]; 28 static unsigned short ports[MAX_PORTS];
29 static unsigned int ports_c; 29 static unsigned int ports_c;
30 module_param_array(ports, ushort, &ports_c, 0400); 30 module_param_array(ports, ushort, &ports_c, 0400);
31 MODULE_PARM_DESC(ports, "Port numbers of TFTP servers"); 31 MODULE_PARM_DESC(ports, "Port numbers of TFTP servers");
32 32
33 unsigned int (*nf_nat_tftp_hook)(struct sk_buff *skb, 33 unsigned int (*nf_nat_tftp_hook)(struct sk_buff *skb,
34 enum ip_conntrack_info ctinfo, 34 enum ip_conntrack_info ctinfo,
35 struct nf_conntrack_expect *exp) __read_mostly; 35 struct nf_conntrack_expect *exp) __read_mostly;
36 EXPORT_SYMBOL_GPL(nf_nat_tftp_hook); 36 EXPORT_SYMBOL_GPL(nf_nat_tftp_hook);
37 37
38 static int tftp_help(struct sk_buff *skb, 38 static int tftp_help(struct sk_buff *skb,
39 unsigned int protoff, 39 unsigned int protoff,
40 struct nf_conn *ct, 40 struct nf_conn *ct,
41 enum ip_conntrack_info ctinfo) 41 enum ip_conntrack_info ctinfo)
42 { 42 {
43 const struct tftphdr *tfh; 43 const struct tftphdr *tfh;
44 struct tftphdr _tftph; 44 struct tftphdr _tftph;
45 struct nf_conntrack_expect *exp; 45 struct nf_conntrack_expect *exp;
46 struct nf_conntrack_tuple *tuple; 46 struct nf_conntrack_tuple *tuple;
47 unsigned int ret = NF_ACCEPT; 47 unsigned int ret = NF_ACCEPT;
48 typeof(nf_nat_tftp_hook) nf_nat_tftp; 48 typeof(nf_nat_tftp_hook) nf_nat_tftp;
49 49
50 tfh = skb_header_pointer(skb, protoff + sizeof(struct udphdr), 50 tfh = skb_header_pointer(skb, protoff + sizeof(struct udphdr),
51 sizeof(_tftph), &_tftph); 51 sizeof(_tftph), &_tftph);
52 if (tfh == NULL) 52 if (tfh == NULL)
53 return NF_ACCEPT; 53 return NF_ACCEPT;
54 54
55 switch (ntohs(tfh->opcode)) { 55 switch (ntohs(tfh->opcode)) {
56 case TFTP_OPCODE_READ: 56 case TFTP_OPCODE_READ:
57 case TFTP_OPCODE_WRITE: 57 case TFTP_OPCODE_WRITE:
58 /* RRQ and WRQ works the same way */ 58 /* RRQ and WRQ works the same way */
59 nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); 59 nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
60 nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); 60 nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
61 61
62 exp = nf_ct_expect_alloc(ct); 62 exp = nf_ct_expect_alloc(ct);
63 if (exp == NULL) 63 if (exp == NULL)
64 return NF_DROP; 64 return NF_DROP;
65 tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; 65 tuple = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
66 nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, 66 nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT,
67 nf_ct_l3num(ct), 67 nf_ct_l3num(ct),
68 &tuple->src.u3, &tuple->dst.u3, 68 &tuple->src.u3, &tuple->dst.u3,
69 IPPROTO_UDP, NULL, &tuple->dst.u.udp.port); 69 IPPROTO_UDP, NULL, &tuple->dst.u.udp.port);
70 70
71 pr_debug("expect: "); 71 pr_debug("expect: ");
72 nf_ct_dump_tuple(&exp->tuple); 72 nf_ct_dump_tuple(&exp->tuple);
73 73
74 nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook); 74 nf_nat_tftp = rcu_dereference(nf_nat_tftp_hook);
75 if (nf_nat_tftp && ct->status & IPS_NAT_MASK) 75 if (nf_nat_tftp && ct->status & IPS_NAT_MASK)
76 ret = nf_nat_tftp(skb, ctinfo, exp); 76 ret = nf_nat_tftp(skb, ctinfo, exp);
77 else if (nf_ct_expect_related(exp) != 0) 77 else if (nf_ct_expect_related(exp) != 0)
78 ret = NF_DROP; 78 ret = NF_DROP;
79 nf_ct_expect_put(exp); 79 nf_ct_expect_put(exp);
80 break; 80 break;
81 case TFTP_OPCODE_DATA: 81 case TFTP_OPCODE_DATA:
82 case TFTP_OPCODE_ACK: 82 case TFTP_OPCODE_ACK:
83 pr_debug("Data/ACK opcode\n"); 83 pr_debug("Data/ACK opcode\n");
84 break; 84 break;
85 case TFTP_OPCODE_ERROR: 85 case TFTP_OPCODE_ERROR:
86 pr_debug("Error opcode\n"); 86 pr_debug("Error opcode\n");
87 break; 87 break;
88 default: 88 default:
89 pr_debug("Unknown opcode\n"); 89 pr_debug("Unknown opcode\n");
90 } 90 }
91 return ret; 91 return ret;
92 } 92 }
93 93
94 static struct nf_conntrack_helper tftp[MAX_PORTS][2] __read_mostly; 94 static struct nf_conntrack_helper tftp[MAX_PORTS][2] __read_mostly;
95 static char tftp_names[MAX_PORTS][2][sizeof("tftp-65535")] __read_mostly;
96 95
97 static const struct nf_conntrack_expect_policy tftp_exp_policy = { 96 static const struct nf_conntrack_expect_policy tftp_exp_policy = {
98 .max_expected = 1, 97 .max_expected = 1,
99 .timeout = 5 * 60, 98 .timeout = 5 * 60,
100 }; 99 };
101 100
102 static void nf_conntrack_tftp_fini(void) 101 static void nf_conntrack_tftp_fini(void)
103 { 102 {
104 int i, j; 103 int i, j;
105 104
106 for (i = 0; i < ports_c; i++) { 105 for (i = 0; i < ports_c; i++) {
107 for (j = 0; j < 2; j++) 106 for (j = 0; j < 2; j++)
108 nf_conntrack_helper_unregister(&tftp[i][j]); 107 nf_conntrack_helper_unregister(&tftp[i][j]);
109 } 108 }
110 } 109 }
111 110
112 static int __init nf_conntrack_tftp_init(void) 111 static int __init nf_conntrack_tftp_init(void)
113 { 112 {
114 int i, j, ret; 113 int i, j, ret;
115 char *tmpname;
116 114
117 if (ports_c == 0) 115 if (ports_c == 0)
118 ports[ports_c++] = TFTP_PORT; 116 ports[ports_c++] = TFTP_PORT;
119 117
120 for (i = 0; i < ports_c; i++) { 118 for (i = 0; i < ports_c; i++) {
121 memset(&tftp[i], 0, sizeof(tftp[i])); 119 memset(&tftp[i], 0, sizeof(tftp[i]));
122 120
123 tftp[i][0].tuple.src.l3num = AF_INET; 121 tftp[i][0].tuple.src.l3num = AF_INET;
124 tftp[i][1].tuple.src.l3num = AF_INET6; 122 tftp[i][1].tuple.src.l3num = AF_INET6;
125 for (j = 0; j < 2; j++) { 123 for (j = 0; j < 2; j++) {
126 tftp[i][j].tuple.dst.protonum = IPPROTO_UDP; 124 tftp[i][j].tuple.dst.protonum = IPPROTO_UDP;
127 tftp[i][j].tuple.src.u.udp.port = htons(ports[i]); 125 tftp[i][j].tuple.src.u.udp.port = htons(ports[i]);
128 tftp[i][j].expect_policy = &tftp_exp_policy; 126 tftp[i][j].expect_policy = &tftp_exp_policy;
129 tftp[i][j].me = THIS_MODULE; 127 tftp[i][j].me = THIS_MODULE;
130 tftp[i][j].help = tftp_help; 128 tftp[i][j].help = tftp_help;
131 129
132 tmpname = &tftp_names[i][j][0];
133 if (ports[i] == TFTP_PORT) 130 if (ports[i] == TFTP_PORT)
134 sprintf(tmpname, "tftp"); 131 sprintf(tftp[i][j].name, "tftp");
135 else 132 else
136 sprintf(tmpname, "tftp-%u", i); 133 sprintf(tftp[i][j].name, "tftp-%u", i);
137 tftp[i][j].name = tmpname;
138 134
139 ret = nf_conntrack_helper_register(&tftp[i][j]); 135 ret = nf_conntrack_helper_register(&tftp[i][j]);
140 if (ret) { 136 if (ret) {
141 printk(KERN_ERR "nf_ct_tftp: failed to register" 137 printk(KERN_ERR "nf_ct_tftp: failed to register"
142 " helper for pf: %u port: %u\n", 138 " helper for pf: %u port: %u\n",
143 tftp[i][j].tuple.src.l3num, ports[i]); 139 tftp[i][j].tuple.src.l3num, ports[i]);
144 nf_conntrack_tftp_fini(); 140 nf_conntrack_tftp_fini();
145 return ret; 141 return ret;
146 } 142 }
147 } 143 }
148 } 144 }
149 return 0; 145 return 0;
150 } 146 }
151 147
152 module_init(nf_conntrack_tftp_init); 148 module_init(nf_conntrack_tftp_init);
153 module_exit(nf_conntrack_tftp_fini); 149 module_exit(nf_conntrack_tftp_fini);
154 150