diff options
233 files changed, 23340 insertions, 4222 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 0db72a36e245..71693c5c3137 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -2519,6 +2519,19 @@ P: Romain Lievin | |||
2519 | M: roms@lpg.ticalc.org | 2519 | M: roms@lpg.ticalc.org |
2520 | S: Maintained | 2520 | S: Maintained |
2521 | 2521 | ||
2522 | TIPC NETWORK LAYER | ||
2523 | P: Per Liden | ||
2524 | M: per.liden@nospam.ericsson.com | ||
2525 | P: Jon Maloy | ||
2526 | M: jon.maloy@nospam.ericsson.com | ||
2527 | P: Allan Stephens | ||
2528 | M: allan.stephens@nospam.windriver.com | ||
2529 | L: tipc-discussion@lists.sourceforge.net | ||
2530 | W: http://tipc.sourceforge.net/ | ||
2531 | W: http://tipc.cslab.ericsson.net/ | ||
2532 | T: git tipc.cslab.ericsson.net:/pub/git/tipc.git | ||
2533 | S: Maintained | ||
2534 | |||
2522 | TLAN NETWORK DRIVER | 2535 | TLAN NETWORK DRIVER |
2523 | P: Samuel Chessman | 2536 | P: Samuel Chessman |
2524 | M: chessman@tux.org | 2537 | M: chessman@tux.org |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index e6ee2d95da7a..323924edb26a 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
@@ -216,6 +216,7 @@ extern void dump_stack(void); | |||
216 | ((unsigned char *)&addr)[1], \ | 216 | ((unsigned char *)&addr)[1], \ |
217 | ((unsigned char *)&addr)[2], \ | 217 | ((unsigned char *)&addr)[2], \ |
218 | ((unsigned char *)&addr)[3] | 218 | ((unsigned char *)&addr)[3] |
219 | #define NIPQUAD_FMT "%u.%u.%u.%u" | ||
219 | 220 | ||
220 | #define NIP6(addr) \ | 221 | #define NIP6(addr) \ |
221 | ntohs((addr).s6_addr16[0]), \ | 222 | ntohs((addr).s6_addr16[0]), \ |
@@ -226,6 +227,7 @@ extern void dump_stack(void); | |||
226 | ntohs((addr).s6_addr16[5]), \ | 227 | ntohs((addr).s6_addr16[5]), \ |
227 | ntohs((addr).s6_addr16[6]), \ | 228 | ntohs((addr).s6_addr16[6]), \ |
228 | ntohs((addr).s6_addr16[7]) | 229 | ntohs((addr).s6_addr16[7]) |
230 | #define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" | ||
229 | 231 | ||
230 | #if defined(__LITTLE_ENDIAN) | 232 | #if defined(__LITTLE_ENDIAN) |
231 | #define HIPQUAD(addr) \ | 233 | #define HIPQUAD(addr) \ |
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h index 6d39b518486b..3ff88c878308 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux/netfilter/nf_conntrack_common.h | |||
@@ -154,6 +154,9 @@ struct ip_conntrack_stat | |||
154 | unsigned int expect_delete; | 154 | unsigned int expect_delete; |
155 | }; | 155 | }; |
156 | 156 | ||
157 | /* call to create an explicit dependency on nf_conntrack. */ | ||
158 | extern void need_conntrack(void); | ||
159 | |||
157 | #endif /* __KERNEL__ */ | 160 | #endif /* __KERNEL__ */ |
158 | 161 | ||
159 | #endif /* _NF_CONNTRACK_COMMON_H */ | 162 | #endif /* _NF_CONNTRACK_COMMON_H */ |
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h new file mode 100644 index 000000000000..472f04834809 --- /dev/null +++ b/include/linux/netfilter/x_tables.h | |||
@@ -0,0 +1,224 @@ | |||
1 | #ifndef _X_TABLES_H | ||
2 | #define _X_TABLES_H | ||
3 | |||
4 | #define XT_FUNCTION_MAXNAMELEN 30 | ||
5 | #define XT_TABLE_MAXNAMELEN 32 | ||
6 | |||
7 | /* The argument to IPT_SO_GET_REVISION_*. Returns highest revision | ||
8 | * kernel supports, if >= revision. */ | ||
9 | struct xt_get_revision | ||
10 | { | ||
11 | char name[XT_FUNCTION_MAXNAMELEN-1]; | ||
12 | |||
13 | u_int8_t revision; | ||
14 | }; | ||
15 | |||
16 | /* CONTINUE verdict for targets */ | ||
17 | #define XT_CONTINUE 0xFFFFFFFF | ||
18 | |||
19 | /* For standard target */ | ||
20 | #define XT_RETURN (-NF_REPEAT - 1) | ||
21 | |||
22 | #define XT_ALIGN(s) (((s) + (__alignof__(void *)-1)) & ~(__alignof__(void *)-1)) | ||
23 | |||
24 | /* Standard return verdict, or do jump. */ | ||
25 | #define XT_STANDARD_TARGET "" | ||
26 | /* Error verdict. */ | ||
27 | #define XT_ERROR_TARGET "ERROR" | ||
28 | |||
29 | /* | ||
30 | * New IP firewall options for [gs]etsockopt at the RAW IP level. | ||
31 | * Unlike BSD Linux inherits IP options so you don't have to use a raw | ||
32 | * socket for this. Instead we check rights in the calls. */ | ||
33 | #define XT_BASE_CTL 64 /* base for firewall socket options */ | ||
34 | |||
35 | #define XT_SO_SET_REPLACE (XT_BASE_CTL) | ||
36 | #define XT_SO_SET_ADD_COUNTERS (XT_BASE_CTL + 1) | ||
37 | #define XT_SO_SET_MAX XT_SO_SET_ADD_COUNTERS | ||
38 | |||
39 | #define XT_SO_GET_INFO (XT_BASE_CTL) | ||
40 | #define XT_SO_GET_ENTRIES (XT_BASE_CTL + 1) | ||
41 | #define XT_SO_GET_REVISION_MATCH (XT_BASE_CTL + 2) | ||
42 | #define XT_SO_GET_REVISION_TARGET (XT_BASE_CTL + 3) | ||
43 | #define XT_SO_GET_MAX XT_SO_GET_REVISION_TARGET | ||
44 | |||
45 | #define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) | ||
46 | #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) | ||
47 | |||
48 | struct xt_counters | ||
49 | { | ||
50 | u_int64_t pcnt, bcnt; /* Packet and byte counters */ | ||
51 | }; | ||
52 | |||
53 | /* The argument to IPT_SO_ADD_COUNTERS. */ | ||
54 | struct xt_counters_info | ||
55 | { | ||
56 | /* Which table. */ | ||
57 | char name[XT_TABLE_MAXNAMELEN]; | ||
58 | |||
59 | unsigned int num_counters; | ||
60 | |||
61 | /* The counters (actually `number' of these). */ | ||
62 | struct xt_counters counters[0]; | ||
63 | }; | ||
64 | |||
65 | #define XT_INV_PROTO 0x40 /* Invert the sense of PROTO. */ | ||
66 | |||
67 | #ifdef __KERNEL__ | ||
68 | |||
69 | #include <linux/netdevice.h> | ||
70 | |||
71 | #define ASSERT_READ_LOCK(x) | ||
72 | #define ASSERT_WRITE_LOCK(x) | ||
73 | #include <linux/netfilter_ipv4/listhelp.h> | ||
74 | |||
75 | struct xt_match | ||
76 | { | ||
77 | struct list_head list; | ||
78 | |||
79 | const char name[XT_FUNCTION_MAXNAMELEN-1]; | ||
80 | |||
81 | u_int8_t revision; | ||
82 | |||
83 | /* Return true or false: return FALSE and set *hotdrop = 1 to | ||
84 | force immediate packet drop. */ | ||
85 | /* Arguments changed since 2.6.9, as this must now handle | ||
86 | non-linear skb, using skb_header_pointer and | ||
87 | skb_ip_make_writable. */ | ||
88 | int (*match)(const struct sk_buff *skb, | ||
89 | const struct net_device *in, | ||
90 | const struct net_device *out, | ||
91 | const void *matchinfo, | ||
92 | int offset, | ||
93 | unsigned int protoff, | ||
94 | int *hotdrop); | ||
95 | |||
96 | /* Called when user tries to insert an entry of this type. */ | ||
97 | /* Should return true or false. */ | ||
98 | int (*checkentry)(const char *tablename, | ||
99 | const void *ip, | ||
100 | void *matchinfo, | ||
101 | unsigned int matchinfosize, | ||
102 | unsigned int hook_mask); | ||
103 | |||
104 | /* Called when entry of this type deleted. */ | ||
105 | void (*destroy)(void *matchinfo, unsigned int matchinfosize); | ||
106 | |||
107 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
108 | struct module *me; | ||
109 | }; | ||
110 | |||
111 | /* Registration hooks for targets. */ | ||
112 | struct xt_target | ||
113 | { | ||
114 | struct list_head list; | ||
115 | |||
116 | const char name[XT_FUNCTION_MAXNAMELEN-1]; | ||
117 | |||
118 | u_int8_t revision; | ||
119 | |||
120 | /* Returns verdict. Argument order changed since 2.6.9, as this | ||
121 | must now handle non-linear skbs, using skb_copy_bits and | ||
122 | skb_ip_make_writable. */ | ||
123 | unsigned int (*target)(struct sk_buff **pskb, | ||
124 | const struct net_device *in, | ||
125 | const struct net_device *out, | ||
126 | unsigned int hooknum, | ||
127 | const void *targinfo, | ||
128 | void *userdata); | ||
129 | |||
130 | /* Called when user tries to insert an entry of this type: | ||
131 | hook_mask is a bitmask of hooks from which it can be | ||
132 | called. */ | ||
133 | /* Should return true or false. */ | ||
134 | int (*checkentry)(const char *tablename, | ||
135 | const void *entry, | ||
136 | void *targinfo, | ||
137 | unsigned int targinfosize, | ||
138 | unsigned int hook_mask); | ||
139 | |||
140 | /* Called when entry of this type deleted. */ | ||
141 | void (*destroy)(void *targinfo, unsigned int targinfosize); | ||
142 | |||
143 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
144 | struct module *me; | ||
145 | }; | ||
146 | |||
147 | /* Furniture shopping... */ | ||
148 | struct xt_table | ||
149 | { | ||
150 | struct list_head list; | ||
151 | |||
152 | /* A unique name... */ | ||
153 | char name[XT_TABLE_MAXNAMELEN]; | ||
154 | |||
155 | /* What hooks you will enter on */ | ||
156 | unsigned int valid_hooks; | ||
157 | |||
158 | /* Lock for the curtain */ | ||
159 | rwlock_t lock; | ||
160 | |||
161 | /* Man behind the curtain... */ | ||
162 | //struct ip6t_table_info *private; | ||
163 | void *private; | ||
164 | |||
165 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
166 | struct module *me; | ||
167 | |||
168 | int af; /* address/protocol family */ | ||
169 | }; | ||
170 | |||
171 | #include <linux/netfilter_ipv4.h> | ||
172 | |||
173 | /* The table itself */ | ||
174 | struct xt_table_info | ||
175 | { | ||
176 | /* Size per table */ | ||
177 | unsigned int size; | ||
178 | /* Number of entries: FIXME. --RR */ | ||
179 | unsigned int number; | ||
180 | /* Initial number of entries. Needed for module usage count */ | ||
181 | unsigned int initial_entries; | ||
182 | |||
183 | /* Entry points and underflows */ | ||
184 | unsigned int hook_entry[NF_IP_NUMHOOKS]; | ||
185 | unsigned int underflow[NF_IP_NUMHOOKS]; | ||
186 | |||
187 | /* ipt_entry tables: one per CPU */ | ||
188 | char *entries[NR_CPUS]; | ||
189 | }; | ||
190 | |||
191 | extern int xt_register_target(int af, struct xt_target *target); | ||
192 | extern void xt_unregister_target(int af, struct xt_target *target); | ||
193 | extern int xt_register_match(int af, struct xt_match *target); | ||
194 | extern void xt_unregister_match(int af, struct xt_match *target); | ||
195 | |||
196 | extern int xt_register_table(struct xt_table *table, | ||
197 | struct xt_table_info *bootstrap, | ||
198 | struct xt_table_info *newinfo); | ||
199 | extern void *xt_unregister_table(struct xt_table *table); | ||
200 | |||
201 | extern struct xt_table_info *xt_replace_table(struct xt_table *table, | ||
202 | unsigned int num_counters, | ||
203 | struct xt_table_info *newinfo, | ||
204 | int *error); | ||
205 | |||
206 | extern struct xt_match *xt_find_match(int af, const char *name, u8 revision); | ||
207 | extern struct xt_target *xt_find_target(int af, const char *name, u8 revision); | ||
208 | extern struct xt_target *xt_request_find_target(int af, const char *name, | ||
209 | u8 revision); | ||
210 | extern int xt_find_revision(int af, const char *name, u8 revision, int target, | ||
211 | int *err); | ||
212 | |||
213 | extern struct xt_table *xt_find_table_lock(int af, const char *name); | ||
214 | extern void xt_table_unlock(struct xt_table *t); | ||
215 | |||
216 | extern int xt_proto_init(int af); | ||
217 | extern void xt_proto_fini(int af); | ||
218 | |||
219 | extern struct xt_table_info *xt_alloc_table_info(unsigned int size); | ||
220 | extern void xt_free_table_info(struct xt_table_info *info); | ||
221 | |||
222 | #endif /* __KERNEL__ */ | ||
223 | |||
224 | #endif /* _X_TABLES_H */ | ||
diff --git a/include/linux/netfilter/xt_CLASSIFY.h b/include/linux/netfilter/xt_CLASSIFY.h new file mode 100644 index 000000000000..58111355255d --- /dev/null +++ b/include/linux/netfilter/xt_CLASSIFY.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _XT_CLASSIFY_H | ||
2 | #define _XT_CLASSIFY_H | ||
3 | |||
4 | struct xt_classify_target_info { | ||
5 | u_int32_t priority; | ||
6 | }; | ||
7 | |||
8 | #endif /*_XT_CLASSIFY_H */ | ||
diff --git a/include/linux/netfilter/xt_CONNMARK.h b/include/linux/netfilter/xt_CONNMARK.h new file mode 100644 index 000000000000..9f744689fffc --- /dev/null +++ b/include/linux/netfilter/xt_CONNMARK.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef _XT_CONNMARK_H_target | ||
2 | #define _XT_CONNMARK_H_target | ||
3 | |||
4 | /* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> | ||
5 | * by Henrik Nordstrom <hno@marasystems.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | enum { | ||
14 | XT_CONNMARK_SET = 0, | ||
15 | XT_CONNMARK_SAVE, | ||
16 | XT_CONNMARK_RESTORE | ||
17 | }; | ||
18 | |||
19 | struct xt_connmark_target_info { | ||
20 | unsigned long mark; | ||
21 | unsigned long mask; | ||
22 | u_int8_t mode; | ||
23 | }; | ||
24 | |||
25 | #endif /*_XT_CONNMARK_H_target*/ | ||
diff --git a/include/linux/netfilter/xt_MARK.h b/include/linux/netfilter/xt_MARK.h new file mode 100644 index 000000000000..b021e93ee5d6 --- /dev/null +++ b/include/linux/netfilter/xt_MARK.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef _XT_MARK_H_target | ||
2 | #define _XT_MARK_H_target | ||
3 | |||
4 | /* Version 0 */ | ||
5 | struct xt_mark_target_info { | ||
6 | unsigned long mark; | ||
7 | }; | ||
8 | |||
9 | /* Version 1 */ | ||
10 | enum { | ||
11 | XT_MARK_SET=0, | ||
12 | XT_MARK_AND, | ||
13 | XT_MARK_OR, | ||
14 | }; | ||
15 | |||
16 | struct xt_mark_target_info_v1 { | ||
17 | unsigned long mark; | ||
18 | u_int8_t mode; | ||
19 | }; | ||
20 | |||
21 | #endif /*_XT_MARK_H_target */ | ||
diff --git a/include/linux/netfilter/xt_NFQUEUE.h b/include/linux/netfilter/xt_NFQUEUE.h new file mode 100644 index 000000000000..9a9af79f74d2 --- /dev/null +++ b/include/linux/netfilter/xt_NFQUEUE.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* iptables module for using NFQUEUE mechanism | ||
2 | * | ||
3 | * (C) 2005 Harald Welte <laforge@netfilter.org> | ||
4 | * | ||
5 | * This software is distributed under GNU GPL v2, 1991 | ||
6 | * | ||
7 | */ | ||
8 | #ifndef _XT_NFQ_TARGET_H | ||
9 | #define _XT_NFQ_TARGET_H | ||
10 | |||
11 | /* target info */ | ||
12 | struct xt_NFQ_info { | ||
13 | u_int16_t queuenum; | ||
14 | }; | ||
15 | |||
16 | #endif /* _XT_NFQ_TARGET_H */ | ||
diff --git a/include/linux/netfilter/xt_comment.h b/include/linux/netfilter/xt_comment.h new file mode 100644 index 000000000000..eacfedc6b5d0 --- /dev/null +++ b/include/linux/netfilter/xt_comment.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef _XT_COMMENT_H | ||
2 | #define _XT_COMMENT_H | ||
3 | |||
4 | #define XT_MAX_COMMENT_LEN 256 | ||
5 | |||
6 | struct xt_comment_info { | ||
7 | unsigned char comment[XT_MAX_COMMENT_LEN]; | ||
8 | }; | ||
9 | |||
10 | #endif /* XT_COMMENT_H */ | ||
diff --git a/include/linux/netfilter/xt_connbytes.h b/include/linux/netfilter/xt_connbytes.h new file mode 100644 index 000000000000..c022c989754d --- /dev/null +++ b/include/linux/netfilter/xt_connbytes.h | |||
@@ -0,0 +1,25 @@ | |||
1 | #ifndef _XT_CONNBYTES_H | ||
2 | #define _XT_CONNBYTES_H | ||
3 | |||
4 | enum xt_connbytes_what { | ||
5 | XT_CONNBYTES_PKTS, | ||
6 | XT_CONNBYTES_BYTES, | ||
7 | XT_CONNBYTES_AVGPKT, | ||
8 | }; | ||
9 | |||
10 | enum xt_connbytes_direction { | ||
11 | XT_CONNBYTES_DIR_ORIGINAL, | ||
12 | XT_CONNBYTES_DIR_REPLY, | ||
13 | XT_CONNBYTES_DIR_BOTH, | ||
14 | }; | ||
15 | |||
16 | struct xt_connbytes_info | ||
17 | { | ||
18 | struct { | ||
19 | aligned_u64 from; /* count to be matched */ | ||
20 | aligned_u64 to; /* count to be matched */ | ||
21 | } count; | ||
22 | u_int8_t what; /* ipt_connbytes_what */ | ||
23 | u_int8_t direction; /* ipt_connbytes_direction */ | ||
24 | }; | ||
25 | #endif | ||
diff --git a/include/linux/netfilter/xt_connmark.h b/include/linux/netfilter/xt_connmark.h new file mode 100644 index 000000000000..c592f6ae0883 --- /dev/null +++ b/include/linux/netfilter/xt_connmark.h | |||
@@ -0,0 +1,18 @@ | |||
1 | #ifndef _XT_CONNMARK_H | ||
2 | #define _XT_CONNMARK_H | ||
3 | |||
4 | /* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> | ||
5 | * by Henrik Nordstrom <hno@marasystems.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | struct xt_connmark_info { | ||
14 | unsigned long mark, mask; | ||
15 | u_int8_t invert; | ||
16 | }; | ||
17 | |||
18 | #endif /*_XT_CONNMARK_H*/ | ||
diff --git a/include/linux/netfilter/xt_conntrack.h b/include/linux/netfilter/xt_conntrack.h new file mode 100644 index 000000000000..34f63cf2e293 --- /dev/null +++ b/include/linux/netfilter/xt_conntrack.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* Header file for kernel module to match connection tracking information. | ||
2 | * GPL (C) 2001 Marc Boucher (marc@mbsi.ca). | ||
3 | */ | ||
4 | |||
5 | #ifndef _XT_CONNTRACK_H | ||
6 | #define _XT_CONNTRACK_H | ||
7 | |||
8 | #include <linux/netfilter/nf_conntrack_tuple_common.h> | ||
9 | #include <linux/in.h> | ||
10 | |||
11 | #define XT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) | ||
12 | #define XT_CONNTRACK_STATE_INVALID (1 << 0) | ||
13 | |||
14 | #define XT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1)) | ||
15 | #define XT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2)) | ||
16 | #define XT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3)) | ||
17 | |||
18 | /* flags, invflags: */ | ||
19 | #define XT_CONNTRACK_STATE 0x01 | ||
20 | #define XT_CONNTRACK_PROTO 0x02 | ||
21 | #define XT_CONNTRACK_ORIGSRC 0x04 | ||
22 | #define XT_CONNTRACK_ORIGDST 0x08 | ||
23 | #define XT_CONNTRACK_REPLSRC 0x10 | ||
24 | #define XT_CONNTRACK_REPLDST 0x20 | ||
25 | #define XT_CONNTRACK_STATUS 0x40 | ||
26 | #define XT_CONNTRACK_EXPIRES 0x80 | ||
27 | |||
28 | /* This is exposed to userspace, so remains frozen in time. */ | ||
29 | struct ip_conntrack_old_tuple | ||
30 | { | ||
31 | struct { | ||
32 | __u32 ip; | ||
33 | union { | ||
34 | __u16 all; | ||
35 | } u; | ||
36 | } src; | ||
37 | |||
38 | struct { | ||
39 | __u32 ip; | ||
40 | union { | ||
41 | __u16 all; | ||
42 | } u; | ||
43 | |||
44 | /* The protocol. */ | ||
45 | u16 protonum; | ||
46 | } dst; | ||
47 | }; | ||
48 | |||
49 | struct xt_conntrack_info | ||
50 | { | ||
51 | unsigned int statemask, statusmask; | ||
52 | |||
53 | struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX]; | ||
54 | struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX]; | ||
55 | |||
56 | unsigned long expires_min, expires_max; | ||
57 | |||
58 | /* Flags word */ | ||
59 | u_int8_t flags; | ||
60 | /* Inverse flags */ | ||
61 | u_int8_t invflags; | ||
62 | }; | ||
63 | #endif /*_XT_CONNTRACK_H*/ | ||
diff --git a/include/linux/netfilter/xt_dccp.h b/include/linux/netfilter/xt_dccp.h new file mode 100644 index 000000000000..e0221b9d32cb --- /dev/null +++ b/include/linux/netfilter/xt_dccp.h | |||
@@ -0,0 +1,23 @@ | |||
1 | #ifndef _XT_DCCP_H_ | ||
2 | #define _XT_DCCP_H_ | ||
3 | |||
4 | #define XT_DCCP_SRC_PORTS 0x01 | ||
5 | #define XT_DCCP_DEST_PORTS 0x02 | ||
6 | #define XT_DCCP_TYPE 0x04 | ||
7 | #define XT_DCCP_OPTION 0x08 | ||
8 | |||
9 | #define XT_DCCP_VALID_FLAGS 0x0f | ||
10 | |||
11 | struct xt_dccp_info { | ||
12 | u_int16_t dpts[2]; /* Min, Max */ | ||
13 | u_int16_t spts[2]; /* Min, Max */ | ||
14 | |||
15 | u_int16_t flags; | ||
16 | u_int16_t invflags; | ||
17 | |||
18 | u_int16_t typemask; | ||
19 | u_int8_t option; | ||
20 | }; | ||
21 | |||
22 | #endif /* _XT_DCCP_H_ */ | ||
23 | |||
diff --git a/include/linux/netfilter/xt_helper.h b/include/linux/netfilter/xt_helper.h new file mode 100644 index 000000000000..6b42763f999d --- /dev/null +++ b/include/linux/netfilter/xt_helper.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _XT_HELPER_H | ||
2 | #define _XT_HELPER_H | ||
3 | |||
4 | struct xt_helper_info { | ||
5 | int invert; | ||
6 | char name[30]; | ||
7 | }; | ||
8 | #endif /* _XT_HELPER_H */ | ||
diff --git a/include/linux/netfilter/xt_length.h b/include/linux/netfilter/xt_length.h new file mode 100644 index 000000000000..7c2b439f73fe --- /dev/null +++ b/include/linux/netfilter/xt_length.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _XT_LENGTH_H | ||
2 | #define _XT_LENGTH_H | ||
3 | |||
4 | struct xt_length_info { | ||
5 | u_int16_t min, max; | ||
6 | u_int8_t invert; | ||
7 | }; | ||
8 | |||
9 | #endif /*_XT_LENGTH_H*/ | ||
diff --git a/include/linux/netfilter/xt_limit.h b/include/linux/netfilter/xt_limit.h new file mode 100644 index 000000000000..b3ce65375ecb --- /dev/null +++ b/include/linux/netfilter/xt_limit.h | |||
@@ -0,0 +1,21 @@ | |||
1 | #ifndef _XT_RATE_H | ||
2 | #define _XT_RATE_H | ||
3 | |||
4 | /* timings are in milliseconds. */ | ||
5 | #define XT_LIMIT_SCALE 10000 | ||
6 | |||
7 | /* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 | ||
8 | seconds, or one every 59 hours. */ | ||
9 | struct xt_rateinfo { | ||
10 | u_int32_t avg; /* Average secs between packets * scale */ | ||
11 | u_int32_t burst; /* Period multiplier for upper limit. */ | ||
12 | |||
13 | /* Used internally by the kernel */ | ||
14 | unsigned long prev; | ||
15 | u_int32_t credit; | ||
16 | u_int32_t credit_cap, cost; | ||
17 | |||
18 | /* Ugly, ugly fucker. */ | ||
19 | struct xt_rateinfo *master; | ||
20 | }; | ||
21 | #endif /*_XT_RATE_H*/ | ||
diff --git a/include/linux/netfilter/xt_mac.h b/include/linux/netfilter/xt_mac.h new file mode 100644 index 000000000000..b892cdc67e06 --- /dev/null +++ b/include/linux/netfilter/xt_mac.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _XT_MAC_H | ||
2 | #define _XT_MAC_H | ||
3 | |||
4 | struct xt_mac_info { | ||
5 | unsigned char srcaddr[ETH_ALEN]; | ||
6 | int invert; | ||
7 | }; | ||
8 | #endif /*_XT_MAC_H*/ | ||
diff --git a/include/linux/netfilter/xt_mark.h b/include/linux/netfilter/xt_mark.h new file mode 100644 index 000000000000..802dd4842caf --- /dev/null +++ b/include/linux/netfilter/xt_mark.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _XT_MARK_H | ||
2 | #define _XT_MARK_H | ||
3 | |||
4 | struct xt_mark_info { | ||
5 | unsigned long mark, mask; | ||
6 | u_int8_t invert; | ||
7 | }; | ||
8 | |||
9 | #endif /*_XT_MARK_H*/ | ||
diff --git a/include/linux/netfilter/xt_physdev.h b/include/linux/netfilter/xt_physdev.h new file mode 100644 index 000000000000..25a7a1815b5b --- /dev/null +++ b/include/linux/netfilter/xt_physdev.h | |||
@@ -0,0 +1,24 @@ | |||
1 | #ifndef _XT_PHYSDEV_H | ||
2 | #define _XT_PHYSDEV_H | ||
3 | |||
4 | #ifdef __KERNEL__ | ||
5 | #include <linux/if.h> | ||
6 | #endif | ||
7 | |||
8 | #define XT_PHYSDEV_OP_IN 0x01 | ||
9 | #define XT_PHYSDEV_OP_OUT 0x02 | ||
10 | #define XT_PHYSDEV_OP_BRIDGED 0x04 | ||
11 | #define XT_PHYSDEV_OP_ISIN 0x08 | ||
12 | #define XT_PHYSDEV_OP_ISOUT 0x10 | ||
13 | #define XT_PHYSDEV_OP_MASK (0x20 - 1) | ||
14 | |||
15 | struct xt_physdev_info { | ||
16 | char physindev[IFNAMSIZ]; | ||
17 | char in_mask[IFNAMSIZ]; | ||
18 | char physoutdev[IFNAMSIZ]; | ||
19 | char out_mask[IFNAMSIZ]; | ||
20 | u_int8_t invert; | ||
21 | u_int8_t bitmask; | ||
22 | }; | ||
23 | |||
24 | #endif /*_XT_PHYSDEV_H*/ | ||
diff --git a/include/linux/netfilter/xt_pkttype.h b/include/linux/netfilter/xt_pkttype.h new file mode 100644 index 000000000000..f265cf52faea --- /dev/null +++ b/include/linux/netfilter/xt_pkttype.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef _XT_PKTTYPE_H | ||
2 | #define _XT_PKTTYPE_H | ||
3 | |||
4 | struct xt_pkttype_info { | ||
5 | int pkttype; | ||
6 | int invert; | ||
7 | }; | ||
8 | #endif /*_XT_PKTTYPE_H*/ | ||
diff --git a/include/linux/netfilter/xt_realm.h b/include/linux/netfilter/xt_realm.h new file mode 100644 index 000000000000..220e87245716 --- /dev/null +++ b/include/linux/netfilter/xt_realm.h | |||
@@ -0,0 +1,10 @@ | |||
1 | #ifndef _XT_REALM_H | ||
2 | #define _XT_REALM_H | ||
3 | |||
4 | struct xt_realm_info { | ||
5 | u_int32_t id; | ||
6 | u_int32_t mask; | ||
7 | u_int8_t invert; | ||
8 | }; | ||
9 | |||
10 | #endif /* _XT_REALM_H */ | ||
diff --git a/include/linux/netfilter/xt_sctp.h b/include/linux/netfilter/xt_sctp.h new file mode 100644 index 000000000000..b157897e7792 --- /dev/null +++ b/include/linux/netfilter/xt_sctp.h | |||
@@ -0,0 +1,107 @@ | |||
1 | #ifndef _XT_SCTP_H_ | ||
2 | #define _XT_SCTP_H_ | ||
3 | |||
4 | #define XT_SCTP_SRC_PORTS 0x01 | ||
5 | #define XT_SCTP_DEST_PORTS 0x02 | ||
6 | #define XT_SCTP_CHUNK_TYPES 0x04 | ||
7 | |||
8 | #define XT_SCTP_VALID_FLAGS 0x07 | ||
9 | |||
10 | #define ELEMCOUNT(x) (sizeof(x)/sizeof(x[0])) | ||
11 | |||
12 | |||
13 | struct xt_sctp_flag_info { | ||
14 | u_int8_t chunktype; | ||
15 | u_int8_t flag; | ||
16 | u_int8_t flag_mask; | ||
17 | }; | ||
18 | |||
19 | #define XT_NUM_SCTP_FLAGS 4 | ||
20 | |||
21 | struct xt_sctp_info { | ||
22 | u_int16_t dpts[2]; /* Min, Max */ | ||
23 | u_int16_t spts[2]; /* Min, Max */ | ||
24 | |||
25 | u_int32_t chunkmap[256 / sizeof (u_int32_t)]; /* Bit mask of chunks to be matched according to RFC 2960 */ | ||
26 | |||
27 | #define SCTP_CHUNK_MATCH_ANY 0x01 /* Match if any of the chunk types are present */ | ||
28 | #define SCTP_CHUNK_MATCH_ALL 0x02 /* Match if all of the chunk types are present */ | ||
29 | #define SCTP_CHUNK_MATCH_ONLY 0x04 /* Match if these are the only chunk types present */ | ||
30 | |||
31 | u_int32_t chunk_match_type; | ||
32 | struct xt_sctp_flag_info flag_info[XT_NUM_SCTP_FLAGS]; | ||
33 | int flag_count; | ||
34 | |||
35 | u_int32_t flags; | ||
36 | u_int32_t invflags; | ||
37 | }; | ||
38 | |||
39 | #define bytes(type) (sizeof(type) * 8) | ||
40 | |||
41 | #define SCTP_CHUNKMAP_SET(chunkmap, type) \ | ||
42 | do { \ | ||
43 | chunkmap[type / bytes(u_int32_t)] |= \ | ||
44 | 1 << (type % bytes(u_int32_t)); \ | ||
45 | } while (0) | ||
46 | |||
47 | #define SCTP_CHUNKMAP_CLEAR(chunkmap, type) \ | ||
48 | do { \ | ||
49 | chunkmap[type / bytes(u_int32_t)] &= \ | ||
50 | ~(1 << (type % bytes(u_int32_t))); \ | ||
51 | } while (0) | ||
52 | |||
53 | #define SCTP_CHUNKMAP_IS_SET(chunkmap, type) \ | ||
54 | ({ \ | ||
55 | (chunkmap[type / bytes (u_int32_t)] & \ | ||
56 | (1 << (type % bytes (u_int32_t)))) ? 1: 0; \ | ||
57 | }) | ||
58 | |||
59 | #define SCTP_CHUNKMAP_RESET(chunkmap) \ | ||
60 | do { \ | ||
61 | int i; \ | ||
62 | for (i = 0; i < ELEMCOUNT(chunkmap); i++) \ | ||
63 | chunkmap[i] = 0; \ | ||
64 | } while (0) | ||
65 | |||
66 | #define SCTP_CHUNKMAP_SET_ALL(chunkmap) \ | ||
67 | do { \ | ||
68 | int i; \ | ||
69 | for (i = 0; i < ELEMCOUNT(chunkmap); i++) \ | ||
70 | chunkmap[i] = ~0; \ | ||
71 | } while (0) | ||
72 | |||
73 | #define SCTP_CHUNKMAP_COPY(destmap, srcmap) \ | ||
74 | do { \ | ||
75 | int i; \ | ||
76 | for (i = 0; i < ELEMCOUNT(chunkmap); i++) \ | ||
77 | destmap[i] = srcmap[i]; \ | ||
78 | } while (0) | ||
79 | |||
80 | #define SCTP_CHUNKMAP_IS_CLEAR(chunkmap) \ | ||
81 | ({ \ | ||
82 | int i; \ | ||
83 | int flag = 1; \ | ||
84 | for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \ | ||
85 | if (chunkmap[i]) { \ | ||
86 | flag = 0; \ | ||
87 | break; \ | ||
88 | } \ | ||
89 | } \ | ||
90 | flag; \ | ||
91 | }) | ||
92 | |||
93 | #define SCTP_CHUNKMAP_IS_ALL_SET(chunkmap) \ | ||
94 | ({ \ | ||
95 | int i; \ | ||
96 | int flag = 1; \ | ||
97 | for (i = 0; i < ELEMCOUNT(chunkmap); i++) { \ | ||
98 | if (chunkmap[i] != ~0) { \ | ||
99 | flag = 0; \ | ||
100 | break; \ | ||
101 | } \ | ||
102 | } \ | ||
103 | flag; \ | ||
104 | }) | ||
105 | |||
106 | #endif /* _XT_SCTP_H_ */ | ||
107 | |||
diff --git a/include/linux/netfilter/xt_state.h b/include/linux/netfilter/xt_state.h new file mode 100644 index 000000000000..c06f32edee07 --- /dev/null +++ b/include/linux/netfilter/xt_state.h | |||
@@ -0,0 +1,13 @@ | |||
1 | #ifndef _XT_STATE_H | ||
2 | #define _XT_STATE_H | ||
3 | |||
4 | #define XT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) | ||
5 | #define XT_STATE_INVALID (1 << 0) | ||
6 | |||
7 | #define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) | ||
8 | |||
9 | struct xt_state_info | ||
10 | { | ||
11 | unsigned int statemask; | ||
12 | }; | ||
13 | #endif /*_XT_STATE_H*/ | ||
diff --git a/include/linux/netfilter/xt_string.h b/include/linux/netfilter/xt_string.h new file mode 100644 index 000000000000..3b3419f2637d --- /dev/null +++ b/include/linux/netfilter/xt_string.h | |||
@@ -0,0 +1,18 @@ | |||
1 | #ifndef _XT_STRING_H | ||
2 | #define _XT_STRING_H | ||
3 | |||
4 | #define XT_STRING_MAX_PATTERN_SIZE 128 | ||
5 | #define XT_STRING_MAX_ALGO_NAME_SIZE 16 | ||
6 | |||
7 | struct xt_string_info | ||
8 | { | ||
9 | u_int16_t from_offset; | ||
10 | u_int16_t to_offset; | ||
11 | char algo[XT_STRING_MAX_ALGO_NAME_SIZE]; | ||
12 | char pattern[XT_STRING_MAX_PATTERN_SIZE]; | ||
13 | u_int8_t patlen; | ||
14 | u_int8_t invert; | ||
15 | struct ts_config __attribute__((aligned(8))) *config; | ||
16 | }; | ||
17 | |||
18 | #endif /*_XT_STRING_H*/ | ||
diff --git a/include/linux/netfilter/xt_tcpmss.h b/include/linux/netfilter/xt_tcpmss.h new file mode 100644 index 000000000000..e03274c4c790 --- /dev/null +++ b/include/linux/netfilter/xt_tcpmss.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _XT_TCPMSS_MATCH_H | ||
2 | #define _XT_TCPMSS_MATCH_H | ||
3 | |||
4 | struct xt_tcpmss_match_info { | ||
5 | u_int16_t mss_min, mss_max; | ||
6 | u_int8_t invert; | ||
7 | }; | ||
8 | |||
9 | #endif /*_XT_TCPMSS_MATCH_H*/ | ||
diff --git a/include/linux/netfilter/xt_tcpudp.h b/include/linux/netfilter/xt_tcpudp.h new file mode 100644 index 000000000000..78bc65f11adf --- /dev/null +++ b/include/linux/netfilter/xt_tcpudp.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef _XT_TCPUDP_H | ||
2 | #define _XT_TCPUDP_H | ||
3 | |||
4 | /* TCP matching stuff */ | ||
5 | struct xt_tcp | ||
6 | { | ||
7 | u_int16_t spts[2]; /* Source port range. */ | ||
8 | u_int16_t dpts[2]; /* Destination port range. */ | ||
9 | u_int8_t option; /* TCP Option iff non-zero*/ | ||
10 | u_int8_t flg_mask; /* TCP flags mask byte */ | ||
11 | u_int8_t flg_cmp; /* TCP flags compare byte */ | ||
12 | u_int8_t invflags; /* Inverse flags */ | ||
13 | }; | ||
14 | |||
15 | /* Values for "inv" field in struct ipt_tcp. */ | ||
16 | #define XT_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ | ||
17 | #define XT_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ | ||
18 | #define XT_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ | ||
19 | #define XT_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ | ||
20 | #define XT_TCP_INV_MASK 0x0F /* All possible flags. */ | ||
21 | |||
22 | /* UDP matching stuff */ | ||
23 | struct xt_udp | ||
24 | { | ||
25 | u_int16_t spts[2]; /* Source port range. */ | ||
26 | u_int16_t dpts[2]; /* Destination port range. */ | ||
27 | u_int8_t invflags; /* Inverse flags */ | ||
28 | }; | ||
29 | |||
30 | /* Values for "invflags" field in struct ipt_udp. */ | ||
31 | #define XT_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ | ||
32 | #define XT_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ | ||
33 | #define XT_UDP_INV_MASK 0x03 /* All possible flags. */ | ||
34 | |||
35 | |||
36 | #endif | ||
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index e98a870a20be..fd21796e5131 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h | |||
@@ -19,8 +19,12 @@ | |||
19 | #include <linux/compiler.h> | 19 | #include <linux/compiler.h> |
20 | #include <linux/netfilter_arp.h> | 20 | #include <linux/netfilter_arp.h> |
21 | 21 | ||
22 | #define ARPT_FUNCTION_MAXNAMELEN 30 | 22 | #include <linux/netfilter/x_tables.h> |
23 | #define ARPT_TABLE_MAXNAMELEN 32 | 23 | |
24 | #define ARPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN | ||
25 | #define ARPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN | ||
26 | #define arpt_target xt_target | ||
27 | #define arpt_table xt_table | ||
24 | 28 | ||
25 | #define ARPT_DEV_ADDR_LEN_MAX 16 | 29 | #define ARPT_DEV_ADDR_LEN_MAX 16 |
26 | 30 | ||
@@ -91,11 +95,6 @@ struct arpt_standard_target | |||
91 | int verdict; | 95 | int verdict; |
92 | }; | 96 | }; |
93 | 97 | ||
94 | struct arpt_counters | ||
95 | { | ||
96 | u_int64_t pcnt, bcnt; /* Packet and byte counters */ | ||
97 | }; | ||
98 | |||
99 | /* Values for "flag" field in struct arpt_ip (general arp structure). | 98 | /* Values for "flag" field in struct arpt_ip (general arp structure). |
100 | * No flags defined yet. | 99 | * No flags defined yet. |
101 | */ | 100 | */ |
@@ -130,7 +129,7 @@ struct arpt_entry | |||
130 | unsigned int comefrom; | 129 | unsigned int comefrom; |
131 | 130 | ||
132 | /* Packet and byte counters. */ | 131 | /* Packet and byte counters. */ |
133 | struct arpt_counters counters; | 132 | struct xt_counters counters; |
134 | 133 | ||
135 | /* The matches (if any), then the target. */ | 134 | /* The matches (if any), then the target. */ |
136 | unsigned char elems[0]; | 135 | unsigned char elems[0]; |
@@ -141,23 +140,24 @@ struct arpt_entry | |||
141 | * Unlike BSD Linux inherits IP options so you don't have to use a raw | 140 | * Unlike BSD Linux inherits IP options so you don't have to use a raw |
142 | * socket for this. Instead we check rights in the calls. | 141 | * socket for this. Instead we check rights in the calls. |
143 | */ | 142 | */ |
144 | #define ARPT_BASE_CTL 96 /* base for firewall socket options */ | 143 | #define ARPT_CTL_OFFSET 32 |
144 | #define ARPT_BASE_CTL (XT_BASE_CTL+ARPT_CTL_OFFSET) | ||
145 | 145 | ||
146 | #define ARPT_SO_SET_REPLACE (ARPT_BASE_CTL) | 146 | #define ARPT_SO_SET_REPLACE (XT_SO_SET_REPLACE+ARPT_CTL_OFFSET) |
147 | #define ARPT_SO_SET_ADD_COUNTERS (ARPT_BASE_CTL + 1) | 147 | #define ARPT_SO_SET_ADD_COUNTERS (XT_SO_SET_ADD_COUNTERS+ARPT_CTL_OFFSET) |
148 | #define ARPT_SO_SET_MAX ARPT_SO_SET_ADD_COUNTERS | 148 | #define ARPT_SO_SET_MAX (XT_SO_SET_MAX+ARPT_CTL_OFFSET) |
149 | 149 | ||
150 | #define ARPT_SO_GET_INFO (ARPT_BASE_CTL) | 150 | #define ARPT_SO_GET_INFO (XT_SO_GET_INFO+ARPT_CTL_OFFSET) |
151 | #define ARPT_SO_GET_ENTRIES (ARPT_BASE_CTL + 1) | 151 | #define ARPT_SO_GET_ENTRIES (XT_SO_GET_ENTRIES+ARPT_CTL_OFFSET) |
152 | /* #define ARPT_SO_GET_REVISION_MATCH (ARPT_BASE_CTL + 2)*/ | 152 | /* #define ARPT_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH */ |
153 | #define ARPT_SO_GET_REVISION_TARGET (ARPT_BASE_CTL + 3) | 153 | #define ARPT_SO_GET_REVISION_TARGET (XT_SO_GET_REVISION_TARGET+ARPT_CTL_OFFSET) |
154 | #define ARPT_SO_GET_MAX ARPT_SO_GET_REVISION_TARGET | 154 | #define ARPT_SO_GET_MAX (XT_SO_GET_REVISION_TARGET+ARPT_CTL_OFFSET) |
155 | 155 | ||
156 | /* CONTINUE verdict for targets */ | 156 | /* CONTINUE verdict for targets */ |
157 | #define ARPT_CONTINUE 0xFFFFFFFF | 157 | #define ARPT_CONTINUE XT_CONTINUE |
158 | 158 | ||
159 | /* For standard target */ | 159 | /* For standard target */ |
160 | #define ARPT_RETURN (-NF_REPEAT - 1) | 160 | #define ARPT_RETURN XT_RETURN |
161 | 161 | ||
162 | /* The argument to ARPT_SO_GET_INFO */ | 162 | /* The argument to ARPT_SO_GET_INFO */ |
163 | struct arpt_getinfo | 163 | struct arpt_getinfo |
@@ -208,23 +208,14 @@ struct arpt_replace | |||
208 | /* Number of counters (must be equal to current number of entries). */ | 208 | /* Number of counters (must be equal to current number of entries). */ |
209 | unsigned int num_counters; | 209 | unsigned int num_counters; |
210 | /* The old entries' counters. */ | 210 | /* The old entries' counters. */ |
211 | struct arpt_counters __user *counters; | 211 | struct xt_counters __user *counters; |
212 | 212 | ||
213 | /* The entries (hang off end: not really an array). */ | 213 | /* The entries (hang off end: not really an array). */ |
214 | struct arpt_entry entries[0]; | 214 | struct arpt_entry entries[0]; |
215 | }; | 215 | }; |
216 | 216 | ||
217 | /* The argument to ARPT_SO_ADD_COUNTERS. */ | 217 | /* The argument to ARPT_SO_ADD_COUNTERS. */ |
218 | struct arpt_counters_info | 218 | #define arpt_counters_info xt_counters_info |
219 | { | ||
220 | /* Which table. */ | ||
221 | char name[ARPT_TABLE_MAXNAMELEN]; | ||
222 | |||
223 | unsigned int num_counters; | ||
224 | |||
225 | /* The counters (actually `number' of these). */ | ||
226 | struct arpt_counters counters[0]; | ||
227 | }; | ||
228 | 219 | ||
229 | /* The argument to ARPT_SO_GET_ENTRIES. */ | 220 | /* The argument to ARPT_SO_GET_ENTRIES. */ |
230 | struct arpt_get_entries | 221 | struct arpt_get_entries |
@@ -239,19 +230,10 @@ struct arpt_get_entries | |||
239 | struct arpt_entry entrytable[0]; | 230 | struct arpt_entry entrytable[0]; |
240 | }; | 231 | }; |
241 | 232 | ||
242 | /* The argument to ARPT_SO_GET_REVISION_*. Returns highest revision | ||
243 | * kernel supports, if >= revision. */ | ||
244 | struct arpt_get_revision | ||
245 | { | ||
246 | char name[ARPT_FUNCTION_MAXNAMELEN-1]; | ||
247 | |||
248 | u_int8_t revision; | ||
249 | }; | ||
250 | |||
251 | /* Standard return verdict, or do jump. */ | 233 | /* Standard return verdict, or do jump. */ |
252 | #define ARPT_STANDARD_TARGET "" | 234 | #define ARPT_STANDARD_TARGET XT_STANDARD_TARGET |
253 | /* Error verdict. */ | 235 | /* Error verdict. */ |
254 | #define ARPT_ERROR_TARGET "ERROR" | 236 | #define ARPT_ERROR_TARGET XT_ERROR_TARGET |
255 | 237 | ||
256 | /* Helper functions */ | 238 | /* Helper functions */ |
257 | static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e) | 239 | static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e) |
@@ -281,63 +263,8 @@ static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e | |||
281 | */ | 263 | */ |
282 | #ifdef __KERNEL__ | 264 | #ifdef __KERNEL__ |
283 | 265 | ||
284 | /* Registration hooks for targets. */ | 266 | #define arpt_register_target(tgt) xt_register_target(NF_ARP, tgt) |
285 | struct arpt_target | 267 | #define arpt_unregister_target(tgt) xt_unregister_target(NF_ARP, tgt) |
286 | { | ||
287 | struct list_head list; | ||
288 | |||
289 | const char name[ARPT_FUNCTION_MAXNAMELEN-1]; | ||
290 | |||
291 | u_int8_t revision; | ||
292 | |||
293 | /* Returns verdict. */ | ||
294 | unsigned int (*target)(struct sk_buff **pskb, | ||
295 | unsigned int hooknum, | ||
296 | const struct net_device *in, | ||
297 | const struct net_device *out, | ||
298 | const void *targinfo, | ||
299 | void *userdata); | ||
300 | |||
301 | /* Called when user tries to insert an entry of this type: | ||
302 | hook_mask is a bitmask of hooks from which it can be | ||
303 | called. */ | ||
304 | /* Should return true or false. */ | ||
305 | int (*checkentry)(const char *tablename, | ||
306 | const struct arpt_entry *e, | ||
307 | void *targinfo, | ||
308 | unsigned int targinfosize, | ||
309 | unsigned int hook_mask); | ||
310 | |||
311 | /* Called when entry of this type deleted. */ | ||
312 | void (*destroy)(void *targinfo, unsigned int targinfosize); | ||
313 | |||
314 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
315 | struct module *me; | ||
316 | }; | ||
317 | |||
318 | extern int arpt_register_target(struct arpt_target *target); | ||
319 | extern void arpt_unregister_target(struct arpt_target *target); | ||
320 | |||
321 | /* Furniture shopping... */ | ||
322 | struct arpt_table | ||
323 | { | ||
324 | struct list_head list; | ||
325 | |||
326 | /* A unique name... */ | ||
327 | char name[ARPT_TABLE_MAXNAMELEN]; | ||
328 | |||
329 | /* What hooks you will enter on */ | ||
330 | unsigned int valid_hooks; | ||
331 | |||
332 | /* Lock for the curtain */ | ||
333 | rwlock_t lock; | ||
334 | |||
335 | /* Man behind the curtain... */ | ||
336 | struct arpt_table_info *private; | ||
337 | |||
338 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
339 | struct module *me; | ||
340 | }; | ||
341 | 268 | ||
342 | extern int arpt_register_table(struct arpt_table *table, | 269 | extern int arpt_register_table(struct arpt_table *table, |
343 | const struct arpt_replace *repl); | 270 | const struct arpt_replace *repl); |
diff --git a/include/linux/netfilter_ipv4/ip_conntrack.h b/include/linux/netfilter_ipv4/ip_conntrack.h index b3432ab59a17..215765f043e6 100644 --- a/include/linux/netfilter_ipv4/ip_conntrack.h +++ b/include/linux/netfilter_ipv4/ip_conntrack.h | |||
@@ -199,9 +199,6 @@ ip_conntrack_put(struct ip_conntrack *ct) | |||
199 | nf_conntrack_put(&ct->ct_general); | 199 | nf_conntrack_put(&ct->ct_general); |
200 | } | 200 | } |
201 | 201 | ||
202 | /* call to create an explicit dependency on ip_conntrack. */ | ||
203 | extern void need_ip_conntrack(void); | ||
204 | |||
205 | extern int invert_tuplepr(struct ip_conntrack_tuple *inverse, | 202 | extern int invert_tuplepr(struct ip_conntrack_tuple *inverse, |
206 | const struct ip_conntrack_tuple *orig); | 203 | const struct ip_conntrack_tuple *orig); |
207 | 204 | ||
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index d19d65cf4530..76ba24b68515 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h | |||
@@ -25,8 +25,14 @@ | |||
25 | #include <linux/compiler.h> | 25 | #include <linux/compiler.h> |
26 | #include <linux/netfilter_ipv4.h> | 26 | #include <linux/netfilter_ipv4.h> |
27 | 27 | ||
28 | #define IPT_FUNCTION_MAXNAMELEN 30 | 28 | #include <linux/netfilter/x_tables.h> |
29 | #define IPT_TABLE_MAXNAMELEN 32 | 29 | |
30 | #define IPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN | ||
31 | #define IPT_TABLE_MAXNAMELEN XT_FUNCTION_MAXNAMELEN | ||
32 | #define ipt_match xt_match | ||
33 | #define ipt_target xt_target | ||
34 | #define ipt_table xt_table | ||
35 | #define ipt_get_revision xt_get_revision | ||
30 | 36 | ||
31 | /* Yes, Virginia, you have to zero the padding. */ | 37 | /* Yes, Virginia, you have to zero the padding. */ |
32 | struct ipt_ip { | 38 | struct ipt_ip { |
@@ -102,10 +108,7 @@ struct ipt_standard_target | |||
102 | int verdict; | 108 | int verdict; |
103 | }; | 109 | }; |
104 | 110 | ||
105 | struct ipt_counters | 111 | #define ipt_counters xt_counters |
106 | { | ||
107 | u_int64_t pcnt, bcnt; /* Packet and byte counters */ | ||
108 | }; | ||
109 | 112 | ||
110 | /* Values for "flag" field in struct ipt_ip (general ip structure). */ | 113 | /* Values for "flag" field in struct ipt_ip (general ip structure). */ |
111 | #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ | 114 | #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ |
@@ -119,7 +122,7 @@ struct ipt_counters | |||
119 | #define IPT_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ | 122 | #define IPT_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ |
120 | #define IPT_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ | 123 | #define IPT_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ |
121 | #define IPT_INV_FRAG 0x20 /* Invert the sense of FRAG. */ | 124 | #define IPT_INV_FRAG 0x20 /* Invert the sense of FRAG. */ |
122 | #define IPT_INV_PROTO 0x40 /* Invert the sense of PROTO. */ | 125 | #define IPT_INV_PROTO XT_INV_PROTO |
123 | #define IPT_INV_MASK 0x7F /* All possible flag bits mask. */ | 126 | #define IPT_INV_MASK 0x7F /* All possible flag bits mask. */ |
124 | 127 | ||
125 | /* This structure defines each of the firewall rules. Consists of 3 | 128 | /* This structure defines each of the firewall rules. Consists of 3 |
@@ -141,7 +144,7 @@ struct ipt_entry | |||
141 | unsigned int comefrom; | 144 | unsigned int comefrom; |
142 | 145 | ||
143 | /* Packet and byte counters. */ | 146 | /* Packet and byte counters. */ |
144 | struct ipt_counters counters; | 147 | struct xt_counters counters; |
145 | 148 | ||
146 | /* The matches (if any), then the target. */ | 149 | /* The matches (if any), then the target. */ |
147 | unsigned char elems[0]; | 150 | unsigned char elems[0]; |
@@ -151,54 +154,34 @@ struct ipt_entry | |||
151 | * New IP firewall options for [gs]etsockopt at the RAW IP level. | 154 | * New IP firewall options for [gs]etsockopt at the RAW IP level. |
152 | * Unlike BSD Linux inherits IP options so you don't have to use a raw | 155 | * Unlike BSD Linux inherits IP options so you don't have to use a raw |
153 | * socket for this. Instead we check rights in the calls. */ | 156 | * socket for this. Instead we check rights in the calls. */ |
154 | #define IPT_BASE_CTL 64 /* base for firewall socket options */ | 157 | #define IPT_BASE_CTL XT_BASE_CTL |
155 | 158 | ||
156 | #define IPT_SO_SET_REPLACE (IPT_BASE_CTL) | 159 | #define IPT_SO_SET_REPLACE XT_SO_SET_REPLACE |
157 | #define IPT_SO_SET_ADD_COUNTERS (IPT_BASE_CTL + 1) | 160 | #define IPT_SO_SET_ADD_COUNTERS XT_SO_SET_ADD_COUNTERS |
158 | #define IPT_SO_SET_MAX IPT_SO_SET_ADD_COUNTERS | 161 | #define IPT_SO_SET_MAX XT_SO_SET_MAX |
159 | 162 | ||
160 | #define IPT_SO_GET_INFO (IPT_BASE_CTL) | 163 | #define IPT_SO_GET_INFO XT_SO_GET_INFO |
161 | #define IPT_SO_GET_ENTRIES (IPT_BASE_CTL + 1) | 164 | #define IPT_SO_GET_ENTRIES XT_SO_GET_ENTRIES |
162 | #define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2) | 165 | #define IPT_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH |
163 | #define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3) | 166 | #define IPT_SO_GET_REVISION_TARGET XT_SO_GET_REVISION_TARGET |
164 | #define IPT_SO_GET_MAX IPT_SO_GET_REVISION_TARGET | 167 | #define IPT_SO_GET_MAX XT_SO_GET_REVISION_TARGET |
165 | 168 | ||
166 | /* CONTINUE verdict for targets */ | 169 | #define IPT_CONTINUE XT_CONTINUE |
167 | #define IPT_CONTINUE 0xFFFFFFFF | 170 | #define IPT_RETURN XT_RETURN |
168 | 171 | ||
169 | /* For standard target */ | 172 | #include <linux/netfilter/xt_tcpudp.h> |
170 | #define IPT_RETURN (-NF_REPEAT - 1) | 173 | #define ipt_udp xt_udp |
174 | #define ipt_tcp xt_tcp | ||
171 | 175 | ||
172 | /* TCP matching stuff */ | 176 | #define IPT_TCP_INV_SRCPT XT_TCP_INV_SRCPT |
173 | struct ipt_tcp | 177 | #define IPT_TCP_INV_DSTPT XT_TCP_INV_DSTPT |
174 | { | 178 | #define IPT_TCP_INV_FLAGS XT_TCP_INV_FLAGS |
175 | u_int16_t spts[2]; /* Source port range. */ | 179 | #define IPT_TCP_INV_OPTION XT_TCP_INV_OPTION |
176 | u_int16_t dpts[2]; /* Destination port range. */ | 180 | #define IPT_TCP_INV_MASK XT_TCP_INV_MASK |
177 | u_int8_t option; /* TCP Option iff non-zero*/ | ||
178 | u_int8_t flg_mask; /* TCP flags mask byte */ | ||
179 | u_int8_t flg_cmp; /* TCP flags compare byte */ | ||
180 | u_int8_t invflags; /* Inverse flags */ | ||
181 | }; | ||
182 | |||
183 | /* Values for "inv" field in struct ipt_tcp. */ | ||
184 | #define IPT_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ | ||
185 | #define IPT_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ | ||
186 | #define IPT_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ | ||
187 | #define IPT_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ | ||
188 | #define IPT_TCP_INV_MASK 0x0F /* All possible flags. */ | ||
189 | |||
190 | /* UDP matching stuff */ | ||
191 | struct ipt_udp | ||
192 | { | ||
193 | u_int16_t spts[2]; /* Source port range. */ | ||
194 | u_int16_t dpts[2]; /* Destination port range. */ | ||
195 | u_int8_t invflags; /* Inverse flags */ | ||
196 | }; | ||
197 | 181 | ||
198 | /* Values for "invflags" field in struct ipt_udp. */ | 182 | #define IPT_UDP_INV_SRCPT XT_UDP_INV_SRCPT |
199 | #define IPT_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ | 183 | #define IPT_UDP_INV_DSTPT XT_UDP_INV_DSTPT |
200 | #define IPT_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ | 184 | #define IPT_UDP_INV_MASK XT_UDP_INV_MASK |
201 | #define IPT_UDP_INV_MASK 0x03 /* All possible flags. */ | ||
202 | 185 | ||
203 | /* ICMP matching stuff */ | 186 | /* ICMP matching stuff */ |
204 | struct ipt_icmp | 187 | struct ipt_icmp |
@@ -260,23 +243,14 @@ struct ipt_replace | |||
260 | /* Number of counters (must be equal to current number of entries). */ | 243 | /* Number of counters (must be equal to current number of entries). */ |
261 | unsigned int num_counters; | 244 | unsigned int num_counters; |
262 | /* The old entries' counters. */ | 245 | /* The old entries' counters. */ |
263 | struct ipt_counters __user *counters; | 246 | struct xt_counters __user *counters; |
264 | 247 | ||
265 | /* The entries (hang off end: not really an array). */ | 248 | /* The entries (hang off end: not really an array). */ |
266 | struct ipt_entry entries[0]; | 249 | struct ipt_entry entries[0]; |
267 | }; | 250 | }; |
268 | 251 | ||
269 | /* The argument to IPT_SO_ADD_COUNTERS. */ | 252 | /* The argument to IPT_SO_ADD_COUNTERS. */ |
270 | struct ipt_counters_info | 253 | #define ipt_counters_info xt_counters_info |
271 | { | ||
272 | /* Which table. */ | ||
273 | char name[IPT_TABLE_MAXNAMELEN]; | ||
274 | |||
275 | unsigned int num_counters; | ||
276 | |||
277 | /* The counters (actually `number' of these). */ | ||
278 | struct ipt_counters counters[0]; | ||
279 | }; | ||
280 | 254 | ||
281 | /* The argument to IPT_SO_GET_ENTRIES. */ | 255 | /* The argument to IPT_SO_GET_ENTRIES. */ |
282 | struct ipt_get_entries | 256 | struct ipt_get_entries |
@@ -291,19 +265,10 @@ struct ipt_get_entries | |||
291 | struct ipt_entry entrytable[0]; | 265 | struct ipt_entry entrytable[0]; |
292 | }; | 266 | }; |
293 | 267 | ||
294 | /* The argument to IPT_SO_GET_REVISION_*. Returns highest revision | ||
295 | * kernel supports, if >= revision. */ | ||
296 | struct ipt_get_revision | ||
297 | { | ||
298 | char name[IPT_FUNCTION_MAXNAMELEN-1]; | ||
299 | |||
300 | u_int8_t revision; | ||
301 | }; | ||
302 | |||
303 | /* Standard return verdict, or do jump. */ | 268 | /* Standard return verdict, or do jump. */ |
304 | #define IPT_STANDARD_TARGET "" | 269 | #define IPT_STANDARD_TARGET XT_STANDARD_TARGET |
305 | /* Error verdict. */ | 270 | /* Error verdict. */ |
306 | #define IPT_ERROR_TARGET "ERROR" | 271 | #define IPT_ERROR_TARGET XT_ERROR_TARGET |
307 | 272 | ||
308 | /* Helper functions */ | 273 | /* Helper functions */ |
309 | static __inline__ struct ipt_entry_target * | 274 | static __inline__ struct ipt_entry_target * |
@@ -356,103 +321,18 @@ ipt_get_target(struct ipt_entry *e) | |||
356 | #include <linux/init.h> | 321 | #include <linux/init.h> |
357 | extern void ipt_init(void) __init; | 322 | extern void ipt_init(void) __init; |
358 | 323 | ||
359 | struct ipt_match | 324 | #define ipt_register_target(tgt) xt_register_target(AF_INET, tgt) |
360 | { | 325 | #define ipt_unregister_target(tgt) xt_unregister_target(AF_INET, tgt) |
361 | struct list_head list; | ||
362 | |||
363 | const char name[IPT_FUNCTION_MAXNAMELEN-1]; | ||
364 | |||
365 | u_int8_t revision; | ||
366 | |||
367 | /* Return true or false: return FALSE and set *hotdrop = 1 to | ||
368 | force immediate packet drop. */ | ||
369 | /* Arguments changed since 2.4, as this must now handle | ||
370 | non-linear skbs, using skb_copy_bits and | ||
371 | skb_ip_make_writable. */ | ||
372 | int (*match)(const struct sk_buff *skb, | ||
373 | const struct net_device *in, | ||
374 | const struct net_device *out, | ||
375 | const void *matchinfo, | ||
376 | int offset, | ||
377 | int *hotdrop); | ||
378 | |||
379 | /* Called when user tries to insert an entry of this type. */ | ||
380 | /* Should return true or false. */ | ||
381 | int (*checkentry)(const char *tablename, | ||
382 | const struct ipt_ip *ip, | ||
383 | void *matchinfo, | ||
384 | unsigned int matchinfosize, | ||
385 | unsigned int hook_mask); | ||
386 | |||
387 | /* Called when entry of this type deleted. */ | ||
388 | void (*destroy)(void *matchinfo, unsigned int matchinfosize); | ||
389 | |||
390 | /* Set this to THIS_MODULE. */ | ||
391 | struct module *me; | ||
392 | }; | ||
393 | |||
394 | /* Registration hooks for targets. */ | ||
395 | struct ipt_target | ||
396 | { | ||
397 | struct list_head list; | ||
398 | |||
399 | const char name[IPT_FUNCTION_MAXNAMELEN-1]; | ||
400 | |||
401 | u_int8_t revision; | ||
402 | |||
403 | /* Called when user tries to insert an entry of this type: | ||
404 | hook_mask is a bitmask of hooks from which it can be | ||
405 | called. */ | ||
406 | /* Should return true or false. */ | ||
407 | int (*checkentry)(const char *tablename, | ||
408 | const struct ipt_entry *e, | ||
409 | void *targinfo, | ||
410 | unsigned int targinfosize, | ||
411 | unsigned int hook_mask); | ||
412 | |||
413 | /* Called when entry of this type deleted. */ | ||
414 | void (*destroy)(void *targinfo, unsigned int targinfosize); | ||
415 | |||
416 | /* Returns verdict. Argument order changed since 2.4, as this | ||
417 | must now handle non-linear skbs, using skb_copy_bits and | ||
418 | skb_ip_make_writable. */ | ||
419 | unsigned int (*target)(struct sk_buff **pskb, | ||
420 | const struct net_device *in, | ||
421 | const struct net_device *out, | ||
422 | unsigned int hooknum, | ||
423 | const void *targinfo, | ||
424 | void *userdata); | ||
425 | |||
426 | /* Set this to THIS_MODULE. */ | ||
427 | struct module *me; | ||
428 | }; | ||
429 | 326 | ||
430 | extern int ipt_register_target(struct ipt_target *target); | 327 | #define ipt_register_match(mtch) xt_register_match(AF_INET, mtch) |
431 | extern void ipt_unregister_target(struct ipt_target *target); | 328 | #define ipt_unregister_match(mtch) xt_unregister_match(AF_INET, mtch) |
432 | 329 | ||
433 | extern int ipt_register_match(struct ipt_match *match); | 330 | //#define ipt_register_table(tbl, repl) xt_register_table(AF_INET, tbl, repl) |
434 | extern void ipt_unregister_match(struct ipt_match *match); | 331 | //#define ipt_unregister_table(tbl) xt_unregister_table(AF_INET, tbl) |
435 | 332 | ||
436 | /* Furniture shopping... */ | 333 | extern int ipt_register_table(struct ipt_table *table, |
437 | struct ipt_table | 334 | const struct ipt_replace *repl); |
438 | { | 335 | extern void ipt_unregister_table(struct ipt_table *table); |
439 | struct list_head list; | ||
440 | |||
441 | /* A unique name... */ | ||
442 | char name[IPT_TABLE_MAXNAMELEN]; | ||
443 | |||
444 | /* What hooks you will enter on */ | ||
445 | unsigned int valid_hooks; | ||
446 | |||
447 | /* Lock for the curtain */ | ||
448 | rwlock_t lock; | ||
449 | |||
450 | /* Man behind the curtain... */ | ||
451 | struct ipt_table_info *private; | ||
452 | |||
453 | /* Set to THIS_MODULE. */ | ||
454 | struct module *me; | ||
455 | }; | ||
456 | 336 | ||
457 | /* net/sched/ipt.c: Gimme access to your targets! Gets target->me. */ | 337 | /* net/sched/ipt.c: Gimme access to your targets! Gets target->me. */ |
458 | extern struct ipt_target *ipt_find_target(const char *name, u8 revision); | 338 | extern struct ipt_target *ipt_find_target(const char *name, u8 revision); |
@@ -476,9 +356,6 @@ struct ipt_error | |||
476 | struct ipt_error_target target; | 356 | struct ipt_error_target target; |
477 | }; | 357 | }; |
478 | 358 | ||
479 | extern int ipt_register_table(struct ipt_table *table, | ||
480 | const struct ipt_replace *repl); | ||
481 | extern void ipt_unregister_table(struct ipt_table *table); | ||
482 | extern unsigned int ipt_do_table(struct sk_buff **pskb, | 359 | extern unsigned int ipt_do_table(struct sk_buff **pskb, |
483 | unsigned int hook, | 360 | unsigned int hook, |
484 | const struct net_device *in, | 361 | const struct net_device *in, |
@@ -486,6 +363,6 @@ extern unsigned int ipt_do_table(struct sk_buff **pskb, | |||
486 | struct ipt_table *table, | 363 | struct ipt_table *table, |
487 | void *userdata); | 364 | void *userdata); |
488 | 365 | ||
489 | #define IPT_ALIGN(s) (((s) + (__alignof__(struct ipt_entry)-1)) & ~(__alignof__(struct ipt_entry)-1)) | 366 | #define IPT_ALIGN(s) XT_ALIGN(s) |
490 | #endif /*__KERNEL__*/ | 367 | #endif /*__KERNEL__*/ |
491 | #endif /* _IPTABLES_H */ | 368 | #endif /* _IPTABLES_H */ |
diff --git a/include/linux/netfilter_ipv4/ipt_CLASSIFY.h b/include/linux/netfilter_ipv4/ipt_CLASSIFY.h index 7596e3dd00ca..a46d511b5c36 100644 --- a/include/linux/netfilter_ipv4/ipt_CLASSIFY.h +++ b/include/linux/netfilter_ipv4/ipt_CLASSIFY.h | |||
@@ -1,8 +1,7 @@ | |||
1 | #ifndef _IPT_CLASSIFY_H | 1 | #ifndef _IPT_CLASSIFY_H |
2 | #define _IPT_CLASSIFY_H | 2 | #define _IPT_CLASSIFY_H |
3 | 3 | ||
4 | struct ipt_classify_target_info { | 4 | #include <linux/netfilter/xt_CLASSIFY.h> |
5 | u_int32_t priority; | 5 | #define ipt_classify_target_info xt_classify_target_info |
6 | }; | ||
7 | 6 | ||
8 | #endif /*_IPT_CLASSIFY_H */ | 7 | #endif /*_IPT_CLASSIFY_H */ |
diff --git a/include/linux/netfilter_ipv4/ipt_CONNMARK.h b/include/linux/netfilter_ipv4/ipt_CONNMARK.h index d3c02536fc4c..9ecfee0a9e33 100644 --- a/include/linux/netfilter_ipv4/ipt_CONNMARK.h +++ b/include/linux/netfilter_ipv4/ipt_CONNMARK.h | |||
@@ -9,17 +9,11 @@ | |||
9 | * the Free Software Foundation; either version 2 of the License, or | 9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. | 10 | * (at your option) any later version. |
11 | */ | 11 | */ |
12 | #include <linux/netfilter/xt_CONNMARK.h> | ||
13 | #define IPT_CONNMARK_SET XT_CONNMARK_SET | ||
14 | #define IPT_CONNMARK_SAVE XT_CONNMARK_SAVE | ||
15 | #define IPT_CONNMARK_RESTORE XT_CONNMARK_RESTORE | ||
12 | 16 | ||
13 | enum { | 17 | #define ipt_connmark_target_info xt_connmark_target_info |
14 | IPT_CONNMARK_SET = 0, | ||
15 | IPT_CONNMARK_SAVE, | ||
16 | IPT_CONNMARK_RESTORE | ||
17 | }; | ||
18 | |||
19 | struct ipt_connmark_target_info { | ||
20 | unsigned long mark; | ||
21 | unsigned long mask; | ||
22 | u_int8_t mode; | ||
23 | }; | ||
24 | 18 | ||
25 | #endif /*_IPT_CONNMARK_H_target*/ | 19 | #endif /*_IPT_CONNMARK_H_target*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_MARK.h b/include/linux/netfilter_ipv4/ipt_MARK.h index f47485790ed4..697a486a96d3 100644 --- a/include/linux/netfilter_ipv4/ipt_MARK.h +++ b/include/linux/netfilter_ipv4/ipt_MARK.h | |||
@@ -1,20 +1,18 @@ | |||
1 | #ifndef _IPT_MARK_H_target | 1 | #ifndef _IPT_MARK_H_target |
2 | #define _IPT_MARK_H_target | 2 | #define _IPT_MARK_H_target |
3 | 3 | ||
4 | /* Backwards compatibility for old userspace */ | ||
5 | |||
6 | #include <linux/netfilter/xt_MARK.h> | ||
7 | |||
4 | /* Version 0 */ | 8 | /* Version 0 */ |
5 | struct ipt_mark_target_info { | 9 | #define ipt_mark_target_info xt_mark_target_info |
6 | unsigned long mark; | ||
7 | }; | ||
8 | 10 | ||
9 | /* Version 1 */ | 11 | /* Version 1 */ |
10 | enum { | 12 | #define IPT_MARK_SET XT_MARK_SET |
11 | IPT_MARK_SET=0, | 13 | #define IPT_MARK_AND XT_MARK_AND |
12 | IPT_MARK_AND, | 14 | #define IPT_MARK_OR XT_MARK_OR |
13 | IPT_MARK_OR | 15 | |
14 | }; | 16 | #define ipt_mark_target_info_v1 xt_mark_target_info_v1 |
15 | 17 | ||
16 | struct ipt_mark_target_info_v1 { | ||
17 | unsigned long mark; | ||
18 | u_int8_t mode; | ||
19 | }; | ||
20 | #endif /*_IPT_MARK_H_target*/ | 18 | #endif /*_IPT_MARK_H_target*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_NFQUEUE.h b/include/linux/netfilter_ipv4/ipt_NFQUEUE.h index b5b2943b0c66..97a2a7557cb9 100644 --- a/include/linux/netfilter_ipv4/ipt_NFQUEUE.h +++ b/include/linux/netfilter_ipv4/ipt_NFQUEUE.h | |||
@@ -8,9 +8,9 @@ | |||
8 | #ifndef _IPT_NFQ_TARGET_H | 8 | #ifndef _IPT_NFQ_TARGET_H |
9 | #define _IPT_NFQ_TARGET_H | 9 | #define _IPT_NFQ_TARGET_H |
10 | 10 | ||
11 | /* target info */ | 11 | /* Backwards compatibility for old userspace */ |
12 | struct ipt_NFQ_info { | 12 | #include <linux/netfilter/xt_NFQUEUE.h> |
13 | u_int16_t queuenum; | 13 | |
14 | }; | 14 | #define ipt_NFQ_info xt_NFQ_info |
15 | 15 | ||
16 | #endif /* _IPT_DSCP_TARGET_H */ | 16 | #endif /* _IPT_DSCP_TARGET_H */ |
diff --git a/include/linux/netfilter_ipv4/ipt_comment.h b/include/linux/netfilter_ipv4/ipt_comment.h index 85c1123c29ce..ae2afc2f7481 100644 --- a/include/linux/netfilter_ipv4/ipt_comment.h +++ b/include/linux/netfilter_ipv4/ipt_comment.h | |||
@@ -1,10 +1,10 @@ | |||
1 | #ifndef _IPT_COMMENT_H | 1 | #ifndef _IPT_COMMENT_H |
2 | #define _IPT_COMMENT_H | 2 | #define _IPT_COMMENT_H |
3 | 3 | ||
4 | #define IPT_MAX_COMMENT_LEN 256 | 4 | #include <linux/netfilter/xt_comment.h> |
5 | 5 | ||
6 | struct ipt_comment_info { | 6 | #define IPT_MAX_COMMENT_LEN XT_MAX_COMMENT_LEN |
7 | unsigned char comment[IPT_MAX_COMMENT_LEN]; | 7 | |
8 | }; | 8 | #define ipt_comment_info xt_comment_info |
9 | 9 | ||
10 | #endif /* _IPT_COMMENT_H */ | 10 | #endif /* _IPT_COMMENT_H */ |
diff --git a/include/linux/netfilter_ipv4/ipt_connbytes.h b/include/linux/netfilter_ipv4/ipt_connbytes.h index 9e5532f8d8ac..b04dfa3083c9 100644 --- a/include/linux/netfilter_ipv4/ipt_connbytes.h +++ b/include/linux/netfilter_ipv4/ipt_connbytes.h | |||
@@ -1,25 +1,18 @@ | |||
1 | #ifndef _IPT_CONNBYTES_H | 1 | #ifndef _IPT_CONNBYTES_H |
2 | #define _IPT_CONNBYTES_H | 2 | #define _IPT_CONNBYTES_H |
3 | 3 | ||
4 | enum ipt_connbytes_what { | 4 | #include <net/netfilter/xt_connbytes.h> |
5 | IPT_CONNBYTES_PKTS, | 5 | #define ipt_connbytes_what xt_connbytes_what |
6 | IPT_CONNBYTES_BYTES, | ||
7 | IPT_CONNBYTES_AVGPKT, | ||
8 | }; | ||
9 | 6 | ||
10 | enum ipt_connbytes_direction { | 7 | #define IPT_CONNBYTES_PKTS XT_CONNBYTES_PACKETS |
11 | IPT_CONNBYTES_DIR_ORIGINAL, | 8 | #define IPT_CONNBYTES_BYTES XT_CONNBYTES_BYTES |
12 | IPT_CONNBYTES_DIR_REPLY, | 9 | #define IPT_CONNBYTES_AVGPKT XT_CONNBYTES_AVGPKT |
13 | IPT_CONNBYTES_DIR_BOTH, | 10 | |
14 | }; | 11 | #define ipt_connbytes_direction xt_connbytes_direction |
12 | #define IPT_CONNBYTES_DIR_ORIGINAL XT_CONNBYTES_DIR_ORIGINAL | ||
13 | #define IPT_CONNBYTES_DIR_REPLY XT_CONNBYTES_DIR_REPLY | ||
14 | #define IPT_CONNBYTES_DIR_BOTH XT_CONNBYTES_DIR_BOTH | ||
15 | |||
16 | #define ipt_connbytes_info xt_connbytes_info | ||
15 | 17 | ||
16 | struct ipt_connbytes_info | ||
17 | { | ||
18 | struct { | ||
19 | aligned_u64 from; /* count to be matched */ | ||
20 | aligned_u64 to; /* count to be matched */ | ||
21 | } count; | ||
22 | u_int8_t what; /* ipt_connbytes_what */ | ||
23 | u_int8_t direction; /* ipt_connbytes_direction */ | ||
24 | }; | ||
25 | #endif | 18 | #endif |
diff --git a/include/linux/netfilter_ipv4/ipt_connmark.h b/include/linux/netfilter_ipv4/ipt_connmark.h index 46573270d9aa..c7ba6560d44c 100644 --- a/include/linux/netfilter_ipv4/ipt_connmark.h +++ b/include/linux/netfilter_ipv4/ipt_connmark.h | |||
@@ -1,18 +1,7 @@ | |||
1 | #ifndef _IPT_CONNMARK_H | 1 | #ifndef _IPT_CONNMARK_H |
2 | #define _IPT_CONNMARK_H | 2 | #define _IPT_CONNMARK_H |
3 | 3 | ||
4 | /* Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com> | 4 | #include <linux/netfilter/xt_connmark.h> |
5 | * by Henrik Nordstrom <hno@marasystems.com> | 5 | #define ipt_connmark_info xt_connmark_info |
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | struct ipt_connmark_info { | ||
14 | unsigned long mark, mask; | ||
15 | u_int8_t invert; | ||
16 | }; | ||
17 | 6 | ||
18 | #endif /*_IPT_CONNMARK_H*/ | 7 | #endif /*_IPT_CONNMARK_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_conntrack.h b/include/linux/netfilter_ipv4/ipt_conntrack.h index 413c5658bd3a..cde6762949c5 100644 --- a/include/linux/netfilter_ipv4/ipt_conntrack.h +++ b/include/linux/netfilter_ipv4/ipt_conntrack.h | |||
@@ -5,56 +5,24 @@ | |||
5 | #ifndef _IPT_CONNTRACK_H | 5 | #ifndef _IPT_CONNTRACK_H |
6 | #define _IPT_CONNTRACK_H | 6 | #define _IPT_CONNTRACK_H |
7 | 7 | ||
8 | #define IPT_CONNTRACK_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) | 8 | #include <linux/netfilter/xt_conntrack.h> |
9 | #define IPT_CONNTRACK_STATE_INVALID (1 << 0) | ||
10 | 9 | ||
11 | #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1)) | 10 | #define IPT_CONNTRACK_STATE_BIT(ctinfo) XT_CONNTRACK_STATE_BIT(ctinfo) |
12 | #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2)) | 11 | #define IPT_CONNTRACK_STATE_INVALID XT_CONNTRACK_STATE_INVALID |
13 | #define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 3)) | ||
14 | 12 | ||
15 | /* flags, invflags: */ | 13 | #define IPT_CONNTRACK_STATE_SNAT XT_CONNTRACK_STATE_SNAT |
16 | #define IPT_CONNTRACK_STATE 0x01 | 14 | #define IPT_CONNTRACK_STATE_DNAT XT_CONNTRACK_STATE_DNAT |
17 | #define IPT_CONNTRACK_PROTO 0x02 | 15 | #define IPT_CONNTRACK_STATE_UNTRACKED XT_CONNTRACK_STATE_UNTRACKED |
18 | #define IPT_CONNTRACK_ORIGSRC 0x04 | ||
19 | #define IPT_CONNTRACK_ORIGDST 0x08 | ||
20 | #define IPT_CONNTRACK_REPLSRC 0x10 | ||
21 | #define IPT_CONNTRACK_REPLDST 0x20 | ||
22 | #define IPT_CONNTRACK_STATUS 0x40 | ||
23 | #define IPT_CONNTRACK_EXPIRES 0x80 | ||
24 | |||
25 | /* This is exposed to userspace, so remains frozen in time. */ | ||
26 | struct ip_conntrack_old_tuple | ||
27 | { | ||
28 | struct { | ||
29 | __u32 ip; | ||
30 | union { | ||
31 | __u16 all; | ||
32 | } u; | ||
33 | } src; | ||
34 | |||
35 | struct { | ||
36 | __u32 ip; | ||
37 | union { | ||
38 | __u16 all; | ||
39 | } u; | ||
40 | |||
41 | /* The protocol. */ | ||
42 | u16 protonum; | ||
43 | } dst; | ||
44 | }; | ||
45 | 16 | ||
46 | struct ipt_conntrack_info | 17 | /* flags, invflags: */ |
47 | { | 18 | #define IPT_CONNTRACK_STATE XT_CONNTRACK_STATE |
48 | unsigned int statemask, statusmask; | 19 | #define IPT_CONNTRACK_PROTO XT_CONNTRACK_PROTO |
49 | 20 | #define IPT_CONNTRACK_ORIGSRC XT_CONNTRACK_ORIGSRC | |
50 | struct ip_conntrack_old_tuple tuple[IP_CT_DIR_MAX]; | 21 | #define IPT_CONNTRACK_ORIGDST XT_CONNTRACK_ORIGDST |
51 | struct in_addr sipmsk[IP_CT_DIR_MAX], dipmsk[IP_CT_DIR_MAX]; | 22 | #define IPT_CONNTRACK_REPLSRC XT_CONNTRACK_REPLSRC |
52 | 23 | #define IPT_CONNTRACK_REPLDST XT_CONNTRACK_REPLDST | |
53 | unsigned long expires_min, expires_max; | 24 | #define IPT_CONNTRACK_STATUS XT_CONNTRACK_STATUS |
54 | 25 | #define IPT_CONNTRACK_EXPIRES XT_CONNTRACK_EXPIRES | |
55 | /* Flags word */ | 26 | |
56 | u_int8_t flags; | 27 | #define ipt_conntrack_info xt_conntrack_info |
57 | /* Inverse flags */ | ||
58 | u_int8_t invflags; | ||
59 | }; | ||
60 | #endif /*_IPT_CONNTRACK_H*/ | 28 | #endif /*_IPT_CONNTRACK_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_dccp.h b/include/linux/netfilter_ipv4/ipt_dccp.h index 3cb3a522e62b..e70d11e1f53c 100644 --- a/include/linux/netfilter_ipv4/ipt_dccp.h +++ b/include/linux/netfilter_ipv4/ipt_dccp.h | |||
@@ -1,23 +1,15 @@ | |||
1 | #ifndef _IPT_DCCP_H_ | 1 | #ifndef _IPT_DCCP_H_ |
2 | #define _IPT_DCCP_H_ | 2 | #define _IPT_DCCP_H_ |
3 | 3 | ||
4 | #define IPT_DCCP_SRC_PORTS 0x01 | 4 | #include <linux/netfilter/xt_dccp.h> |
5 | #define IPT_DCCP_DEST_PORTS 0x02 | 5 | #define IPT_DCCP_SRC_PORTS XT_DCCP_SRC_PORTS |
6 | #define IPT_DCCP_TYPE 0x04 | 6 | #define IPT_DCCP_DEST_PORTS XT_DCCP_DEST_PORTS |
7 | #define IPT_DCCP_OPTION 0x08 | 7 | #define IPT_DCCP_TYPE XT_DCCP_TYPE |
8 | #define IPT_DCCP_OPTION XT_DCCP_OPTION | ||
8 | 9 | ||
9 | #define IPT_DCCP_VALID_FLAGS 0x0f | 10 | #define IPT_DCCP_VALID_FLAGS XT_DCCP_VALID_FLAGS |
10 | 11 | ||
11 | struct ipt_dccp_info { | 12 | #define ipt_dccp_info xt_dccp_info |
12 | u_int16_t dpts[2]; /* Min, Max */ | ||
13 | u_int16_t spts[2]; /* Min, Max */ | ||
14 | |||
15 | u_int16_t flags; | ||
16 | u_int16_t invflags; | ||
17 | |||
18 | u_int16_t typemask; | ||
19 | u_int8_t option; | ||
20 | }; | ||
21 | 13 | ||
22 | #endif /* _IPT_DCCP_H_ */ | 14 | #endif /* _IPT_DCCP_H_ */ |
23 | 15 | ||
diff --git a/include/linux/netfilter_ipv4/ipt_helper.h b/include/linux/netfilter_ipv4/ipt_helper.h index 6f12ecb8c93d..80452c218551 100644 --- a/include/linux/netfilter_ipv4/ipt_helper.h +++ b/include/linux/netfilter_ipv4/ipt_helper.h | |||
@@ -1,8 +1,7 @@ | |||
1 | #ifndef _IPT_HELPER_H | 1 | #ifndef _IPT_HELPER_H |
2 | #define _IPT_HELPER_H | 2 | #define _IPT_HELPER_H |
3 | 3 | ||
4 | struct ipt_helper_info { | 4 | #include <linux/netfilter/xt_helper.h> |
5 | int invert; | 5 | #define ipt_helper_info xt_helper_info |
6 | char name[30]; | 6 | |
7 | }; | ||
8 | #endif /* _IPT_HELPER_H */ | 7 | #endif /* _IPT_HELPER_H */ |
diff --git a/include/linux/netfilter_ipv4/ipt_length.h b/include/linux/netfilter_ipv4/ipt_length.h index 6e0885229615..9b45206ffcef 100644 --- a/include/linux/netfilter_ipv4/ipt_length.h +++ b/include/linux/netfilter_ipv4/ipt_length.h | |||
@@ -1,9 +1,7 @@ | |||
1 | #ifndef _IPT_LENGTH_H | 1 | #ifndef _IPT_LENGTH_H |
2 | #define _IPT_LENGTH_H | 2 | #define _IPT_LENGTH_H |
3 | 3 | ||
4 | struct ipt_length_info { | 4 | #include <linux/netfilter/xt_length.h> |
5 | u_int16_t min, max; | 5 | #define ipt_length_info xt_length_info |
6 | u_int8_t invert; | ||
7 | }; | ||
8 | 6 | ||
9 | #endif /*_IPT_LENGTH_H*/ | 7 | #endif /*_IPT_LENGTH_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_limit.h b/include/linux/netfilter_ipv4/ipt_limit.h index 256453409e21..92f5cd07bbc4 100644 --- a/include/linux/netfilter_ipv4/ipt_limit.h +++ b/include/linux/netfilter_ipv4/ipt_limit.h | |||
@@ -1,21 +1,8 @@ | |||
1 | #ifndef _IPT_RATE_H | 1 | #ifndef _IPT_RATE_H |
2 | #define _IPT_RATE_H | 2 | #define _IPT_RATE_H |
3 | 3 | ||
4 | /* timings are in milliseconds. */ | 4 | #include <linux/netfilter/xt_limit.h> |
5 | #define IPT_LIMIT_SCALE 10000 | 5 | #define IPT_LIMIT_SCALE XT_LIMIT_SCALE |
6 | #define ipt_rateinfo xt_rateinfo | ||
6 | 7 | ||
7 | /* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 | ||
8 | seconds, or one every 59 hours. */ | ||
9 | struct ipt_rateinfo { | ||
10 | u_int32_t avg; /* Average secs between packets * scale */ | ||
11 | u_int32_t burst; /* Period multiplier for upper limit. */ | ||
12 | |||
13 | /* Used internally by the kernel */ | ||
14 | unsigned long prev; | ||
15 | u_int32_t credit; | ||
16 | u_int32_t credit_cap, cost; | ||
17 | |||
18 | /* Ugly, ugly fucker. */ | ||
19 | struct ipt_rateinfo *master; | ||
20 | }; | ||
21 | #endif /*_IPT_RATE_H*/ | 8 | #endif /*_IPT_RATE_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_mac.h b/include/linux/netfilter_ipv4/ipt_mac.h index f8d5b8e7ccdb..b186008a3c47 100644 --- a/include/linux/netfilter_ipv4/ipt_mac.h +++ b/include/linux/netfilter_ipv4/ipt_mac.h | |||
@@ -1,8 +1,7 @@ | |||
1 | #ifndef _IPT_MAC_H | 1 | #ifndef _IPT_MAC_H |
2 | #define _IPT_MAC_H | 2 | #define _IPT_MAC_H |
3 | 3 | ||
4 | struct ipt_mac_info { | 4 | #include <linux/netfilter/xt_mac.h> |
5 | unsigned char srcaddr[ETH_ALEN]; | 5 | #define ipt_mac_info xt_mac_info |
6 | int invert; | 6 | |
7 | }; | ||
8 | #endif /*_IPT_MAC_H*/ | 7 | #endif /*_IPT_MAC_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_mark.h b/include/linux/netfilter_ipv4/ipt_mark.h index f3952b563d4c..bfde67c61224 100644 --- a/include/linux/netfilter_ipv4/ipt_mark.h +++ b/include/linux/netfilter_ipv4/ipt_mark.h | |||
@@ -1,9 +1,9 @@ | |||
1 | #ifndef _IPT_MARK_H | 1 | #ifndef _IPT_MARK_H |
2 | #define _IPT_MARK_H | 2 | #define _IPT_MARK_H |
3 | 3 | ||
4 | struct ipt_mark_info { | 4 | /* Backwards compatibility for old userspace */ |
5 | unsigned long mark, mask; | 5 | #include <linux/netfilter/xt_mark.h> |
6 | u_int8_t invert; | 6 | |
7 | }; | 7 | #define ipt_mark_info xt_mark_info |
8 | 8 | ||
9 | #endif /*_IPT_MARK_H*/ | 9 | #endif /*_IPT_MARK_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_physdev.h b/include/linux/netfilter_ipv4/ipt_physdev.h index 7538c8655ec0..2400e7140f26 100644 --- a/include/linux/netfilter_ipv4/ipt_physdev.h +++ b/include/linux/netfilter_ipv4/ipt_physdev.h | |||
@@ -1,24 +1,17 @@ | |||
1 | #ifndef _IPT_PHYSDEV_H | 1 | #ifndef _IPT_PHYSDEV_H |
2 | #define _IPT_PHYSDEV_H | 2 | #define _IPT_PHYSDEV_H |
3 | 3 | ||
4 | #ifdef __KERNEL__ | 4 | /* Backwards compatibility for old userspace */ |
5 | #include <linux/if.h> | ||
6 | #endif | ||
7 | 5 | ||
8 | #define IPT_PHYSDEV_OP_IN 0x01 | 6 | #include <linux/netfilter/xt_physdev.h> |
9 | #define IPT_PHYSDEV_OP_OUT 0x02 | ||
10 | #define IPT_PHYSDEV_OP_BRIDGED 0x04 | ||
11 | #define IPT_PHYSDEV_OP_ISIN 0x08 | ||
12 | #define IPT_PHYSDEV_OP_ISOUT 0x10 | ||
13 | #define IPT_PHYSDEV_OP_MASK (0x20 - 1) | ||
14 | 7 | ||
15 | struct ipt_physdev_info { | 8 | #define IPT_PHYSDEV_OP_IN XT_PHYSDEV_OP_IN |
16 | char physindev[IFNAMSIZ]; | 9 | #define IPT_PHYSDEV_OP_OUT XT_PHYSDEV_OP_OUT |
17 | char in_mask[IFNAMSIZ]; | 10 | #define IPT_PHYSDEV_OP_BRIDGED XT_PHYSDEV_OP_BRIDGED |
18 | char physoutdev[IFNAMSIZ]; | 11 | #define IPT_PHYSDEV_OP_ISIN XT_PHYSDEV_OP_ISIN |
19 | char out_mask[IFNAMSIZ]; | 12 | #define IPT_PHYSDEV_OP_ISOUT XT_PHYSDEV_OP_ISOUT |
20 | u_int8_t invert; | 13 | #define IPT_PHYSDEV_OP_MASK XT_PHYSDEV_OP_MASK |
21 | u_int8_t bitmask; | 14 | |
22 | }; | 15 | #define ipt_physdev_info xt_physdev_info |
23 | 16 | ||
24 | #endif /*_IPT_PHYSDEV_H*/ | 17 | #endif /*_IPT_PHYSDEV_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_pkttype.h b/include/linux/netfilter_ipv4/ipt_pkttype.h index d53a65848683..ff1fbc949a0c 100644 --- a/include/linux/netfilter_ipv4/ipt_pkttype.h +++ b/include/linux/netfilter_ipv4/ipt_pkttype.h | |||
@@ -1,8 +1,7 @@ | |||
1 | #ifndef _IPT_PKTTYPE_H | 1 | #ifndef _IPT_PKTTYPE_H |
2 | #define _IPT_PKTTYPE_H | 2 | #define _IPT_PKTTYPE_H |
3 | 3 | ||
4 | struct ipt_pkttype_info { | 4 | #include <linux/netfilter/xt_pkttype.h> |
5 | int pkttype; | 5 | #define ipt_pkttype_info xt_pkttype_info |
6 | int invert; | 6 | |
7 | }; | ||
8 | #endif /*_IPT_PKTTYPE_H*/ | 7 | #endif /*_IPT_PKTTYPE_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_realm.h b/include/linux/netfilter_ipv4/ipt_realm.h index a4d6698723ac..b3996eaa0188 100644 --- a/include/linux/netfilter_ipv4/ipt_realm.h +++ b/include/linux/netfilter_ipv4/ipt_realm.h | |||
@@ -1,10 +1,7 @@ | |||
1 | #ifndef _IPT_REALM_H | 1 | #ifndef _IPT_REALM_H |
2 | #define _IPT_REALM_H | 2 | #define _IPT_REALM_H |
3 | 3 | ||
4 | struct ipt_realm_info { | 4 | #include <linux/netfilter/xt_realm.h> |
5 | u_int32_t id; | 5 | #define ipt_realm_info xt_realm_info |
6 | u_int32_t mask; | ||
7 | u_int8_t invert; | ||
8 | }; | ||
9 | 6 | ||
10 | #endif /* _IPT_REALM_H */ | 7 | #endif /* _IPT_REALM_H */ |
diff --git a/include/linux/netfilter_ipv4/ipt_state.h b/include/linux/netfilter_ipv4/ipt_state.h index 5df37868933d..a44a99cc28cc 100644 --- a/include/linux/netfilter_ipv4/ipt_state.h +++ b/include/linux/netfilter_ipv4/ipt_state.h | |||
@@ -1,13 +1,15 @@ | |||
1 | #ifndef _IPT_STATE_H | 1 | #ifndef _IPT_STATE_H |
2 | #define _IPT_STATE_H | 2 | #define _IPT_STATE_H |
3 | 3 | ||
4 | #define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1)) | 4 | /* Backwards compatibility for old userspace */ |
5 | #define IPT_STATE_INVALID (1 << 0) | ||
6 | 5 | ||
7 | #define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) | 6 | #include <linux/netfilter/xt_state.h> |
7 | |||
8 | #define IPT_STATE_BIT XT_STATE_BIT | ||
9 | #define IPT_STATE_INVALID XT_STATE_INVALID | ||
10 | |||
11 | #define IPT_STATE_UNTRACKED XT_STATE_UNTRACKED | ||
12 | |||
13 | #define ipt_state_info xt_state_info | ||
8 | 14 | ||
9 | struct ipt_state_info | ||
10 | { | ||
11 | unsigned int statemask; | ||
12 | }; | ||
13 | #endif /*_IPT_STATE_H*/ | 15 | #endif /*_IPT_STATE_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_string.h b/include/linux/netfilter_ipv4/ipt_string.h index a265f6e44eab..c26de3059903 100644 --- a/include/linux/netfilter_ipv4/ipt_string.h +++ b/include/linux/netfilter_ipv4/ipt_string.h | |||
@@ -1,18 +1,10 @@ | |||
1 | #ifndef _IPT_STRING_H | 1 | #ifndef _IPT_STRING_H |
2 | #define _IPT_STRING_H | 2 | #define _IPT_STRING_H |
3 | 3 | ||
4 | #define IPT_STRING_MAX_PATTERN_SIZE 128 | 4 | #include <linux/netfilter/xt_string.h> |
5 | #define IPT_STRING_MAX_ALGO_NAME_SIZE 16 | ||
6 | 5 | ||
7 | struct ipt_string_info | 6 | #define IPT_STRING_MAX_PATTERN_SIZE XT_STRING_MAX_PATTERN_SIZE |
8 | { | 7 | #define IPT_STRING_MAX_ALGO_NAME_SIZE XT_STRING_MAX_ALGO_NAME_SIZE |
9 | u_int16_t from_offset; | 8 | #define ipt_string_info xt_string_info |
10 | u_int16_t to_offset; | ||
11 | char algo[IPT_STRING_MAX_ALGO_NAME_SIZE]; | ||
12 | char pattern[IPT_STRING_MAX_PATTERN_SIZE]; | ||
13 | u_int8_t patlen; | ||
14 | u_int8_t invert; | ||
15 | struct ts_config __attribute__((aligned(8))) *config; | ||
16 | }; | ||
17 | 9 | ||
18 | #endif /*_IPT_STRING_H*/ | 10 | #endif /*_IPT_STRING_H*/ |
diff --git a/include/linux/netfilter_ipv4/ipt_tcpmss.h b/include/linux/netfilter_ipv4/ipt_tcpmss.h index e2b14397f701..18bbc8e8e009 100644 --- a/include/linux/netfilter_ipv4/ipt_tcpmss.h +++ b/include/linux/netfilter_ipv4/ipt_tcpmss.h | |||
@@ -1,9 +1,7 @@ | |||
1 | #ifndef _IPT_TCPMSS_MATCH_H | 1 | #ifndef _IPT_TCPMSS_MATCH_H |
2 | #define _IPT_TCPMSS_MATCH_H | 2 | #define _IPT_TCPMSS_MATCH_H |
3 | 3 | ||
4 | struct ipt_tcpmss_match_info { | 4 | #include <linux/netfilter/xt_tcpmss.h> |
5 | u_int16_t mss_min, mss_max; | 5 | #define ipt_tcpmss_match_info xt_tcpmss_match_info |
6 | u_int8_t invert; | ||
7 | }; | ||
8 | 6 | ||
9 | #endif /*_IPT_TCPMSS_MATCH_H*/ | 7 | #endif /*_IPT_TCPMSS_MATCH_H*/ |
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index c163ba31aab7..f249b574f0fa 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h | |||
@@ -25,8 +25,15 @@ | |||
25 | #include <linux/compiler.h> | 25 | #include <linux/compiler.h> |
26 | #include <linux/netfilter_ipv6.h> | 26 | #include <linux/netfilter_ipv6.h> |
27 | 27 | ||
28 | #define IP6T_FUNCTION_MAXNAMELEN 30 | 28 | #include <linux/netfilter/x_tables.h> |
29 | #define IP6T_TABLE_MAXNAMELEN 32 | 29 | |
30 | #define IP6T_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN | ||
31 | #define IP6T_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN | ||
32 | |||
33 | #define ip6t_match xt_match | ||
34 | #define ip6t_target xt_target | ||
35 | #define ip6t_table xt_table | ||
36 | #define ip6t_get_revision xt_get_revision | ||
30 | 37 | ||
31 | /* Yes, Virginia, you have to zero the padding. */ | 38 | /* Yes, Virginia, you have to zero the padding. */ |
32 | struct ip6t_ip6 { | 39 | struct ip6t_ip6 { |
@@ -104,10 +111,7 @@ struct ip6t_standard_target | |||
104 | int verdict; | 111 | int verdict; |
105 | }; | 112 | }; |
106 | 113 | ||
107 | struct ip6t_counters | 114 | #define ip6t_counters xt_counters |
108 | { | ||
109 | u_int64_t pcnt, bcnt; /* Packet and byte counters */ | ||
110 | }; | ||
111 | 115 | ||
112 | /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */ | 116 | /* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */ |
113 | #define IP6T_F_PROTO 0x01 /* Set if rule cares about upper | 117 | #define IP6T_F_PROTO 0x01 /* Set if rule cares about upper |
@@ -123,7 +127,7 @@ struct ip6t_counters | |||
123 | #define IP6T_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ | 127 | #define IP6T_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ |
124 | #define IP6T_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ | 128 | #define IP6T_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ |
125 | #define IP6T_INV_FRAG 0x20 /* Invert the sense of FRAG. */ | 129 | #define IP6T_INV_FRAG 0x20 /* Invert the sense of FRAG. */ |
126 | #define IP6T_INV_PROTO 0x40 /* Invert the sense of PROTO. */ | 130 | #define IP6T_INV_PROTO XT_INV_PROTO |
127 | #define IP6T_INV_MASK 0x7F /* All possible flag bits mask. */ | 131 | #define IP6T_INV_MASK 0x7F /* All possible flag bits mask. */ |
128 | 132 | ||
129 | /* This structure defines each of the firewall rules. Consists of 3 | 133 | /* This structure defines each of the firewall rules. Consists of 3 |
@@ -145,7 +149,7 @@ struct ip6t_entry | |||
145 | unsigned int comefrom; | 149 | unsigned int comefrom; |
146 | 150 | ||
147 | /* Packet and byte counters. */ | 151 | /* Packet and byte counters. */ |
148 | struct ip6t_counters counters; | 152 | struct xt_counters counters; |
149 | 153 | ||
150 | /* The matches (if any), then the target. */ | 154 | /* The matches (if any), then the target. */ |
151 | unsigned char elems[0]; | 155 | unsigned char elems[0]; |
@@ -155,54 +159,41 @@ struct ip6t_entry | |||
155 | * New IP firewall options for [gs]etsockopt at the RAW IP level. | 159 | * New IP firewall options for [gs]etsockopt at the RAW IP level. |
156 | * Unlike BSD Linux inherits IP options so you don't have to use | 160 | * Unlike BSD Linux inherits IP options so you don't have to use |
157 | * a raw socket for this. Instead we check rights in the calls. */ | 161 | * a raw socket for this. Instead we check rights in the calls. */ |
158 | #define IP6T_BASE_CTL 64 /* base for firewall socket options */ | 162 | #define IP6T_BASE_CTL XT_BASE_CTL |
159 | 163 | ||
160 | #define IP6T_SO_SET_REPLACE (IP6T_BASE_CTL) | 164 | #define IP6T_SO_SET_REPLACE XT_SO_SET_REPLACE |
161 | #define IP6T_SO_SET_ADD_COUNTERS (IP6T_BASE_CTL + 1) | 165 | #define IP6T_SO_SET_ADD_COUNTERS XT_SO_SET_ADD_COUNTERS |
162 | #define IP6T_SO_SET_MAX IP6T_SO_SET_ADD_COUNTERS | 166 | #define IP6T_SO_SET_MAX XT_SO_SET_MAX |
163 | 167 | ||
164 | #define IP6T_SO_GET_INFO (IP6T_BASE_CTL) | 168 | #define IP6T_SO_GET_INFO XT_SO_GET_INFO |
165 | #define IP6T_SO_GET_ENTRIES (IP6T_BASE_CTL + 1) | 169 | #define IP6T_SO_GET_ENTRIES XT_SO_GET_ENTRIES |
166 | #define IP6T_SO_GET_REVISION_MATCH (IP6T_BASE_CTL + 2) | 170 | #define IP6T_SO_GET_REVISION_MATCH XT_SO_GET_REVISION_MATCH |
167 | #define IP6T_SO_GET_REVISION_TARGET (IP6T_BASE_CTL + 3) | 171 | #define IP6T_SO_GET_REVISION_TARGET XT_SO_GET_REVISION_TARGET |
168 | #define IP6T_SO_GET_MAX IP6T_SO_GET_REVISION_TARGET | 172 | #define IP6T_SO_GET_MAX XT_SO_GET_REVISION_TARGET |
169 | 173 | ||
170 | /* CONTINUE verdict for targets */ | 174 | /* CONTINUE verdict for targets */ |
171 | #define IP6T_CONTINUE 0xFFFFFFFF | 175 | #define IP6T_CONTINUE XT_CONTINUE |
172 | 176 | ||
173 | /* For standard target */ | 177 | /* For standard target */ |
174 | #define IP6T_RETURN (-NF_REPEAT - 1) | 178 | #define IP6T_RETURN XT_RETURN |
175 | 179 | ||
176 | /* TCP matching stuff */ | 180 | /* TCP/UDP matching stuff */ |
177 | struct ip6t_tcp | 181 | #include <linux/netfilter/xt_tcpudp.h> |
178 | { | 182 | |
179 | u_int16_t spts[2]; /* Source port range. */ | 183 | #define ip6t_tcp xt_tcp |
180 | u_int16_t dpts[2]; /* Destination port range. */ | 184 | #define ip6t_udp xt_udp |
181 | u_int8_t option; /* TCP Option iff non-zero*/ | ||
182 | u_int8_t flg_mask; /* TCP flags mask byte */ | ||
183 | u_int8_t flg_cmp; /* TCP flags compare byte */ | ||
184 | u_int8_t invflags; /* Inverse flags */ | ||
185 | }; | ||
186 | 185 | ||
187 | /* Values for "inv" field in struct ipt_tcp. */ | 186 | /* Values for "inv" field in struct ipt_tcp. */ |
188 | #define IP6T_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ | 187 | #define IP6T_TCP_INV_SRCPT XT_TCP_INV_SRCPT |
189 | #define IP6T_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ | 188 | #define IP6T_TCP_INV_DSTPT XT_TCP_INV_DSTPT |
190 | #define IP6T_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ | 189 | #define IP6T_TCP_INV_FLAGS XT_TCP_INV_FLAGS |
191 | #define IP6T_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ | 190 | #define IP6T_TCP_INV_OPTION XT_TCP_INV_OPTION |
192 | #define IP6T_TCP_INV_MASK 0x0F /* All possible flags. */ | 191 | #define IP6T_TCP_INV_MASK XT_TCP_INV_MASK |
193 | |||
194 | /* UDP matching stuff */ | ||
195 | struct ip6t_udp | ||
196 | { | ||
197 | u_int16_t spts[2]; /* Source port range. */ | ||
198 | u_int16_t dpts[2]; /* Destination port range. */ | ||
199 | u_int8_t invflags; /* Inverse flags */ | ||
200 | }; | ||
201 | 192 | ||
202 | /* Values for "invflags" field in struct ipt_udp. */ | 193 | /* Values for "invflags" field in struct ipt_udp. */ |
203 | #define IP6T_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ | 194 | #define IP6T_UDP_INV_SRCPT XT_UDP_INV_SRCPT |
204 | #define IP6T_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ | 195 | #define IP6T_UDP_INV_DSTPT XT_UDP_INV_DSTPT |
205 | #define IP6T_UDP_INV_MASK 0x03 /* All possible flags. */ | 196 | #define IP6T_UDP_INV_MASK XT_UDP_INV_MASK |
206 | 197 | ||
207 | /* ICMP matching stuff */ | 198 | /* ICMP matching stuff */ |
208 | struct ip6t_icmp | 199 | struct ip6t_icmp |
@@ -264,23 +255,14 @@ struct ip6t_replace | |||
264 | /* Number of counters (must be equal to current number of entries). */ | 255 | /* Number of counters (must be equal to current number of entries). */ |
265 | unsigned int num_counters; | 256 | unsigned int num_counters; |
266 | /* The old entries' counters. */ | 257 | /* The old entries' counters. */ |
267 | struct ip6t_counters __user *counters; | 258 | struct xt_counters __user *counters; |
268 | 259 | ||
269 | /* The entries (hang off end: not really an array). */ | 260 | /* The entries (hang off end: not really an array). */ |
270 | struct ip6t_entry entries[0]; | 261 | struct ip6t_entry entries[0]; |
271 | }; | 262 | }; |
272 | 263 | ||
273 | /* The argument to IP6T_SO_ADD_COUNTERS. */ | 264 | /* The argument to IP6T_SO_ADD_COUNTERS. */ |
274 | struct ip6t_counters_info | 265 | #define ip6t_counters_info xt_counters_info |
275 | { | ||
276 | /* Which table. */ | ||
277 | char name[IP6T_TABLE_MAXNAMELEN]; | ||
278 | |||
279 | unsigned int num_counters; | ||
280 | |||
281 | /* The counters (actually `number' of these). */ | ||
282 | struct ip6t_counters counters[0]; | ||
283 | }; | ||
284 | 266 | ||
285 | /* The argument to IP6T_SO_GET_ENTRIES. */ | 267 | /* The argument to IP6T_SO_GET_ENTRIES. */ |
286 | struct ip6t_get_entries | 268 | struct ip6t_get_entries |
@@ -295,19 +277,10 @@ struct ip6t_get_entries | |||
295 | struct ip6t_entry entrytable[0]; | 277 | struct ip6t_entry entrytable[0]; |
296 | }; | 278 | }; |
297 | 279 | ||
298 | /* The argument to IP6T_SO_GET_REVISION_*. Returns highest revision | ||
299 | * kernel supports, if >= revision. */ | ||
300 | struct ip6t_get_revision | ||
301 | { | ||
302 | char name[IP6T_FUNCTION_MAXNAMELEN-1]; | ||
303 | |||
304 | u_int8_t revision; | ||
305 | }; | ||
306 | |||
307 | /* Standard return verdict, or do jump. */ | 280 | /* Standard return verdict, or do jump. */ |
308 | #define IP6T_STANDARD_TARGET "" | 281 | #define IP6T_STANDARD_TARGET XT_STANDARD_TARGET |
309 | /* Error verdict. */ | 282 | /* Error verdict. */ |
310 | #define IP6T_ERROR_TARGET "ERROR" | 283 | #define IP6T_ERROR_TARGET XT_ERROR_TARGET |
311 | 284 | ||
312 | /* Helper functions */ | 285 | /* Helper functions */ |
313 | static __inline__ struct ip6t_entry_target * | 286 | static __inline__ struct ip6t_entry_target * |
@@ -361,104 +334,11 @@ ip6t_get_target(struct ip6t_entry *e) | |||
361 | #include <linux/init.h> | 334 | #include <linux/init.h> |
362 | extern void ip6t_init(void) __init; | 335 | extern void ip6t_init(void) __init; |
363 | 336 | ||
364 | struct ip6t_match | 337 | #define ip6t_register_target(tgt) xt_register_target(AF_INET6, tgt) |
365 | { | 338 | #define ip6t_unregister_target(tgt) xt_unregister_target(AF_INET6, tgt) |
366 | struct list_head list; | ||
367 | |||
368 | const char name[IP6T_FUNCTION_MAXNAMELEN-1]; | ||
369 | |||
370 | u_int8_t revision; | ||
371 | |||
372 | /* Return true or false: return FALSE and set *hotdrop = 1 to | ||
373 | force immediate packet drop. */ | ||
374 | /* Arguments changed since 2.6.9, as this must now handle | ||
375 | non-linear skb, using skb_header_pointer and | ||
376 | skb_ip_make_writable. */ | ||
377 | int (*match)(const struct sk_buff *skb, | ||
378 | const struct net_device *in, | ||
379 | const struct net_device *out, | ||
380 | const void *matchinfo, | ||
381 | int offset, | ||
382 | unsigned int protoff, | ||
383 | int *hotdrop); | ||
384 | |||
385 | /* Called when user tries to insert an entry of this type. */ | ||
386 | /* Should return true or false. */ | ||
387 | int (*checkentry)(const char *tablename, | ||
388 | const struct ip6t_ip6 *ip, | ||
389 | void *matchinfo, | ||
390 | unsigned int matchinfosize, | ||
391 | unsigned int hook_mask); | ||
392 | |||
393 | /* Called when entry of this type deleted. */ | ||
394 | void (*destroy)(void *matchinfo, unsigned int matchinfosize); | ||
395 | |||
396 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
397 | struct module *me; | ||
398 | }; | ||
399 | |||
400 | /* Registration hooks for targets. */ | ||
401 | struct ip6t_target | ||
402 | { | ||
403 | struct list_head list; | ||
404 | |||
405 | const char name[IP6T_FUNCTION_MAXNAMELEN-1]; | ||
406 | |||
407 | u_int8_t revision; | ||
408 | |||
409 | /* Returns verdict. Argument order changed since 2.6.9, as this | ||
410 | must now handle non-linear skbs, using skb_copy_bits and | ||
411 | skb_ip_make_writable. */ | ||
412 | unsigned int (*target)(struct sk_buff **pskb, | ||
413 | const struct net_device *in, | ||
414 | const struct net_device *out, | ||
415 | unsigned int hooknum, | ||
416 | const void *targinfo, | ||
417 | void *userdata); | ||
418 | |||
419 | /* Called when user tries to insert an entry of this type: | ||
420 | hook_mask is a bitmask of hooks from which it can be | ||
421 | called. */ | ||
422 | /* Should return true or false. */ | ||
423 | int (*checkentry)(const char *tablename, | ||
424 | const struct ip6t_entry *e, | ||
425 | void *targinfo, | ||
426 | unsigned int targinfosize, | ||
427 | unsigned int hook_mask); | ||
428 | |||
429 | /* Called when entry of this type deleted. */ | ||
430 | void (*destroy)(void *targinfo, unsigned int targinfosize); | ||
431 | |||
432 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
433 | struct module *me; | ||
434 | }; | ||
435 | |||
436 | extern int ip6t_register_target(struct ip6t_target *target); | ||
437 | extern void ip6t_unregister_target(struct ip6t_target *target); | ||
438 | |||
439 | extern int ip6t_register_match(struct ip6t_match *match); | ||
440 | extern void ip6t_unregister_match(struct ip6t_match *match); | ||
441 | 339 | ||
442 | /* Furniture shopping... */ | 340 | #define ip6t_register_match(match) xt_register_match(AF_INET6, match) |
443 | struct ip6t_table | 341 | #define ip6t_unregister_match(match) xt_unregister_match(AF_INET6, match) |
444 | { | ||
445 | struct list_head list; | ||
446 | |||
447 | /* A unique name... */ | ||
448 | char name[IP6T_TABLE_MAXNAMELEN]; | ||
449 | |||
450 | /* What hooks you will enter on */ | ||
451 | unsigned int valid_hooks; | ||
452 | |||
453 | /* Lock for the curtain */ | ||
454 | rwlock_t lock; | ||
455 | |||
456 | /* Man behind the curtain... */ | ||
457 | struct ip6t_table_info *private; | ||
458 | |||
459 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | ||
460 | struct module *me; | ||
461 | }; | ||
462 | 342 | ||
463 | extern int ip6t_register_table(struct ip6t_table *table, | 343 | extern int ip6t_register_table(struct ip6t_table *table, |
464 | const struct ip6t_replace *repl); | 344 | const struct ip6t_replace *repl); |
diff --git a/include/linux/netfilter_ipv6/ip6t_MARK.h b/include/linux/netfilter_ipv6/ip6t_MARK.h index 7ade8d8f5246..7cf629a8ab92 100644 --- a/include/linux/netfilter_ipv6/ip6t_MARK.h +++ b/include/linux/netfilter_ipv6/ip6t_MARK.h | |||
@@ -1,8 +1,9 @@ | |||
1 | #ifndef _IP6T_MARK_H_target | 1 | #ifndef _IP6T_MARK_H_target |
2 | #define _IP6T_MARK_H_target | 2 | #define _IP6T_MARK_H_target |
3 | 3 | ||
4 | struct ip6t_mark_target_info { | 4 | /* Backwards compatibility for old userspace */ |
5 | unsigned long mark; | 5 | #include <linux/netfilter/xt_MARK.h> |
6 | }; | ||
7 | 6 | ||
8 | #endif /*_IPT_MARK_H_target*/ | 7 | #define ip6t_mark_target_info xt_mark_target_info |
8 | |||
9 | #endif /*_IP6T_MARK_H_target*/ | ||
diff --git a/include/linux/netfilter_ipv6/ip6t_length.h b/include/linux/netfilter_ipv6/ip6t_length.h index 7fc09f9f9d63..9e9689d03ed7 100644 --- a/include/linux/netfilter_ipv6/ip6t_length.h +++ b/include/linux/netfilter_ipv6/ip6t_length.h | |||
@@ -1,10 +1,8 @@ | |||
1 | #ifndef _IP6T_LENGTH_H | 1 | #ifndef _IP6T_LENGTH_H |
2 | #define _IP6T_LENGTH_H | 2 | #define _IP6T_LENGTH_H |
3 | 3 | ||
4 | struct ip6t_length_info { | 4 | #include <linux/netfilter/xt_length.h> |
5 | u_int16_t min, max; | 5 | #define ip6t_length_info xt_length_info |
6 | u_int8_t invert; | ||
7 | }; | ||
8 | 6 | ||
9 | #endif /*_IP6T_LENGTH_H*/ | 7 | #endif /*_IP6T_LENGTH_H*/ |
10 | 8 | ||
diff --git a/include/linux/netfilter_ipv6/ip6t_limit.h b/include/linux/netfilter_ipv6/ip6t_limit.h index f2866e50f3b4..487e5ea342c6 100644 --- a/include/linux/netfilter_ipv6/ip6t_limit.h +++ b/include/linux/netfilter_ipv6/ip6t_limit.h | |||
@@ -1,21 +1,8 @@ | |||
1 | #ifndef _IP6T_RATE_H | 1 | #ifndef _IP6T_RATE_H |
2 | #define _IP6T_RATE_H | 2 | #define _IP6T_RATE_H |
3 | 3 | ||
4 | /* timings are in milliseconds. */ | 4 | #include <linux/netfilter/xt_limit.h> |
5 | #define IP6T_LIMIT_SCALE 10000 | 5 | #define IP6T_LIMIT_SCALE XT_LIMIT_SCALE |
6 | #define ip6t_rateinfo xt_rateinfo | ||
6 | 7 | ||
7 | /* 1/10,000 sec period => max of 10,000/sec. Min rate is then 429490 | 8 | #endif /*_IP6T_RATE_H*/ |
8 | seconds, or one every 59 hours. */ | ||
9 | struct ip6t_rateinfo { | ||
10 | u_int32_t avg; /* Average secs between packets * scale */ | ||
11 | u_int32_t burst; /* Period multiplier for upper limit. */ | ||
12 | |||
13 | /* Used internally by the kernel */ | ||
14 | unsigned long prev; | ||
15 | u_int32_t credit; | ||
16 | u_int32_t credit_cap, cost; | ||
17 | |||
18 | /* Ugly, ugly fucker. */ | ||
19 | struct ip6t_rateinfo *master; | ||
20 | }; | ||
21 | #endif /*_IPT_RATE_H*/ | ||
diff --git a/include/linux/netfilter_ipv6/ip6t_mac.h b/include/linux/netfilter_ipv6/ip6t_mac.h index 87c088c21848..ac58e83e9423 100644 --- a/include/linux/netfilter_ipv6/ip6t_mac.h +++ b/include/linux/netfilter_ipv6/ip6t_mac.h | |||
@@ -1,8 +1,7 @@ | |||
1 | #ifndef _IP6T_MAC_H | 1 | #ifndef _IP6T_MAC_H |
2 | #define _IP6T_MAC_H | 2 | #define _IP6T_MAC_H |
3 | 3 | ||
4 | struct ip6t_mac_info { | 4 | #include <linux/netfilter/xt_mac.h> |
5 | unsigned char srcaddr[ETH_ALEN]; | 5 | #define ip6t_mac_info xt_mac_info |
6 | int invert; | 6 | |
7 | }; | 7 | #endif /*_IP6T_MAC_H*/ |
8 | #endif /*_IPT_MAC_H*/ | ||
diff --git a/include/linux/netfilter_ipv6/ip6t_mark.h b/include/linux/netfilter_ipv6/ip6t_mark.h index a734441e1c19..ff204951ddc3 100644 --- a/include/linux/netfilter_ipv6/ip6t_mark.h +++ b/include/linux/netfilter_ipv6/ip6t_mark.h | |||
@@ -1,9 +1,9 @@ | |||
1 | #ifndef _IP6T_MARK_H | 1 | #ifndef _IP6T_MARK_H |
2 | #define _IP6T_MARK_H | 2 | #define _IP6T_MARK_H |
3 | 3 | ||
4 | struct ip6t_mark_info { | 4 | /* Backwards compatibility for old userspace */ |
5 | unsigned long mark, mask; | 5 | #include <linux/netfilter/xt_mark.h> |
6 | u_int8_t invert; | 6 | |
7 | }; | 7 | #define ip6t_mark_info xt_mark_info |
8 | 8 | ||
9 | #endif /*_IPT_MARK_H*/ | 9 | #endif /*_IPT_MARK_H*/ |
diff --git a/include/linux/netfilter_ipv6/ip6t_physdev.h b/include/linux/netfilter_ipv6/ip6t_physdev.h index c234731cd66b..c161c0a81b55 100644 --- a/include/linux/netfilter_ipv6/ip6t_physdev.h +++ b/include/linux/netfilter_ipv6/ip6t_physdev.h | |||
@@ -1,24 +1,17 @@ | |||
1 | #ifndef _IP6T_PHYSDEV_H | 1 | #ifndef _IP6T_PHYSDEV_H |
2 | #define _IP6T_PHYSDEV_H | 2 | #define _IP6T_PHYSDEV_H |
3 | 3 | ||
4 | #ifdef __KERNEL__ | 4 | /* Backwards compatibility for old userspace */ |
5 | #include <linux/if.h> | ||
6 | #endif | ||
7 | 5 | ||
8 | #define IP6T_PHYSDEV_OP_IN 0x01 | 6 | #include <linux/netfilter/xt_physdev.h> |
9 | #define IP6T_PHYSDEV_OP_OUT 0x02 | ||
10 | #define IP6T_PHYSDEV_OP_BRIDGED 0x04 | ||
11 | #define IP6T_PHYSDEV_OP_ISIN 0x08 | ||
12 | #define IP6T_PHYSDEV_OP_ISOUT 0x10 | ||
13 | #define IP6T_PHYSDEV_OP_MASK (0x20 - 1) | ||
14 | 7 | ||
15 | struct ip6t_physdev_info { | 8 | #define IP6T_PHYSDEV_OP_IN XT_PHYSDEV_OP_IN |
16 | char physindev[IFNAMSIZ]; | 9 | #define IP6T_PHYSDEV_OP_OUT XT_PHYSDEV_OP_OUT |
17 | char in_mask[IFNAMSIZ]; | 10 | #define IP6T_PHYSDEV_OP_BRIDGED XT_PHYSDEV_OP_BRIDGED |
18 | char physoutdev[IFNAMSIZ]; | 11 | #define IP6T_PHYSDEV_OP_ISIN XT_PHYSDEV_OP_ISIN |
19 | char out_mask[IFNAMSIZ]; | 12 | #define IP6T_PHYSDEV_OP_ISOUT XT_PHYSDEV_OP_ISOUT |
20 | u_int8_t invert; | 13 | #define IP6T_PHYSDEV_OP_MASK XT_PHYSDEV_OP_MASK |
21 | u_int8_t bitmask; | 14 | |
22 | }; | 15 | #define ip6t_physdev_info xt_physdev_info |
23 | 16 | ||
24 | #endif /*_IP6T_PHYSDEV_H*/ | 17 | #endif /*_IP6T_PHYSDEV_H*/ |
diff --git a/include/linux/socket.h b/include/linux/socket.h index 9f4019156fd8..b02dda4ee83d 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h | |||
@@ -186,6 +186,7 @@ struct ucred { | |||
186 | #define AF_PPPOX 24 /* PPPoX sockets */ | 186 | #define AF_PPPOX 24 /* PPPoX sockets */ |
187 | #define AF_WANPIPE 25 /* Wanpipe API Sockets */ | 187 | #define AF_WANPIPE 25 /* Wanpipe API Sockets */ |
188 | #define AF_LLC 26 /* Linux LLC */ | 188 | #define AF_LLC 26 /* Linux LLC */ |
189 | #define AF_TIPC 30 /* TIPC sockets */ | ||
189 | #define AF_BLUETOOTH 31 /* Bluetooth sockets */ | 190 | #define AF_BLUETOOTH 31 /* Bluetooth sockets */ |
190 | #define AF_MAX 32 /* For now.. */ | 191 | #define AF_MAX 32 /* For now.. */ |
191 | 192 | ||
@@ -218,6 +219,7 @@ struct ucred { | |||
218 | #define PF_PPPOX AF_PPPOX | 219 | #define PF_PPPOX AF_PPPOX |
219 | #define PF_WANPIPE AF_WANPIPE | 220 | #define PF_WANPIPE AF_WANPIPE |
220 | #define PF_LLC AF_LLC | 221 | #define PF_LLC AF_LLC |
222 | #define PF_TIPC AF_TIPC | ||
221 | #define PF_BLUETOOTH AF_BLUETOOTH | 223 | #define PF_BLUETOOTH AF_BLUETOOTH |
222 | #define PF_MAX AF_MAX | 224 | #define PF_MAX AF_MAX |
223 | 225 | ||
@@ -279,6 +281,7 @@ struct ucred { | |||
279 | #define SOL_LLC 268 | 281 | #define SOL_LLC 268 |
280 | #define SOL_DCCP 269 | 282 | #define SOL_DCCP 269 |
281 | #define SOL_NETLINK 270 | 283 | #define SOL_NETLINK 270 |
284 | #define SOL_TIPC 271 | ||
282 | 285 | ||
283 | /* IPX options */ | 286 | /* IPX options */ |
284 | #define IPX_TYPE 1 | 287 | #define IPX_TYPE 1 |
diff --git a/include/linux/tipc.h b/include/linux/tipc.h new file mode 100644 index 000000000000..243a15f54002 --- /dev/null +++ b/include/linux/tipc.h | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | * include/linux/tipc.h: Include file for TIPC socket interface | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _LINUX_TIPC_H_ | ||
38 | #define _LINUX_TIPC_H_ | ||
39 | |||
40 | #include <linux/types.h> | ||
41 | |||
42 | /* | ||
43 | * TIPC addressing primitives | ||
44 | */ | ||
45 | |||
46 | struct tipc_portid { | ||
47 | __u32 ref; | ||
48 | __u32 node; | ||
49 | }; | ||
50 | |||
51 | struct tipc_name { | ||
52 | __u32 type; | ||
53 | __u32 instance; | ||
54 | }; | ||
55 | |||
56 | struct tipc_name_seq { | ||
57 | __u32 type; | ||
58 | __u32 lower; | ||
59 | __u32 upper; | ||
60 | }; | ||
61 | |||
62 | static inline __u32 tipc_addr(unsigned int zone, | ||
63 | unsigned int cluster, | ||
64 | unsigned int node) | ||
65 | { | ||
66 | return (zone << 24) | (cluster << 12) | node; | ||
67 | } | ||
68 | |||
69 | static inline unsigned int tipc_zone(__u32 addr) | ||
70 | { | ||
71 | return addr >> 24; | ||
72 | } | ||
73 | |||
74 | static inline unsigned int tipc_cluster(__u32 addr) | ||
75 | { | ||
76 | return (addr >> 12) & 0xfff; | ||
77 | } | ||
78 | |||
79 | static inline unsigned int tipc_node(__u32 addr) | ||
80 | { | ||
81 | return addr & 0xfff; | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * Application-accessible port name types | ||
86 | */ | ||
87 | |||
88 | #define TIPC_CFG_SRV 0 /* configuration service name type */ | ||
89 | #define TIPC_TOP_SRV 1 /* topology service name type */ | ||
90 | #define TIPC_RESERVED_TYPES 64 /* lowest user-publishable name type */ | ||
91 | |||
92 | /* | ||
93 | * Publication scopes when binding port names and port name sequences | ||
94 | */ | ||
95 | |||
96 | #define TIPC_ZONE_SCOPE 1 | ||
97 | #define TIPC_CLUSTER_SCOPE 2 | ||
98 | #define TIPC_NODE_SCOPE 3 | ||
99 | |||
100 | /* | ||
101 | * Limiting values for messages | ||
102 | */ | ||
103 | |||
104 | #define TIPC_MAX_USER_MSG_SIZE 66000 | ||
105 | |||
106 | /* | ||
107 | * Message importance levels | ||
108 | */ | ||
109 | |||
110 | #define TIPC_LOW_IMPORTANCE 0 /* default */ | ||
111 | #define TIPC_MEDIUM_IMPORTANCE 1 | ||
112 | #define TIPC_HIGH_IMPORTANCE 2 | ||
113 | #define TIPC_CRITICAL_IMPORTANCE 3 | ||
114 | |||
115 | /* | ||
116 | * Msg rejection/connection shutdown reasons | ||
117 | */ | ||
118 | |||
119 | #define TIPC_OK 0 | ||
120 | #define TIPC_ERR_NO_NAME 1 | ||
121 | #define TIPC_ERR_NO_PORT 2 | ||
122 | #define TIPC_ERR_NO_NODE 3 | ||
123 | #define TIPC_ERR_OVERLOAD 4 | ||
124 | #define TIPC_CONN_SHUTDOWN 5 | ||
125 | |||
126 | /* | ||
127 | * TIPC topology subscription service definitions | ||
128 | */ | ||
129 | |||
130 | #define TIPC_SUB_PORTS 0x01 /* filter for port availability */ | ||
131 | #define TIPC_SUB_SERVICE 0x02 /* filter for service availability */ | ||
132 | #if 0 | ||
133 | /* The following filter options are not currently implemented */ | ||
134 | #define TIPC_SUB_NO_BIND_EVTS 0x04 /* filter out "publish" events */ | ||
135 | #define TIPC_SUB_NO_UNBIND_EVTS 0x08 /* filter out "withdraw" events */ | ||
136 | #define TIPC_SUB_SINGLE_EVT 0x10 /* expire after first event */ | ||
137 | #endif | ||
138 | |||
139 | #define TIPC_WAIT_FOREVER ~0 /* timeout for permanent subscription */ | ||
140 | |||
141 | struct tipc_subscr { | ||
142 | struct tipc_name_seq seq; /* name sequence of interest */ | ||
143 | __u32 timeout; /* subscription duration (in ms) */ | ||
144 | __u32 filter; /* bitmask of filter options */ | ||
145 | char usr_handle[8]; /* available for subscriber use */ | ||
146 | }; | ||
147 | |||
148 | #define TIPC_PUBLISHED 1 /* publication event */ | ||
149 | #define TIPC_WITHDRAWN 2 /* withdraw event */ | ||
150 | #define TIPC_SUBSCR_TIMEOUT 3 /* subscription timeout event */ | ||
151 | |||
152 | struct tipc_event { | ||
153 | __u32 event; /* event type */ | ||
154 | __u32 found_lower; /* matching name seq instances */ | ||
155 | __u32 found_upper; /* " " " " */ | ||
156 | struct tipc_portid port; /* associated port */ | ||
157 | struct tipc_subscr s; /* associated subscription */ | ||
158 | }; | ||
159 | |||
160 | /* | ||
161 | * Socket API | ||
162 | */ | ||
163 | |||
164 | #ifndef AF_TIPC | ||
165 | #define AF_TIPC 30 | ||
166 | #endif | ||
167 | |||
168 | #ifndef PF_TIPC | ||
169 | #define PF_TIPC AF_TIPC | ||
170 | #endif | ||
171 | |||
172 | #ifndef SOL_TIPC | ||
173 | #define SOL_TIPC 271 | ||
174 | #endif | ||
175 | |||
176 | #define TIPC_ADDR_NAMESEQ 1 | ||
177 | #define TIPC_ADDR_MCAST 1 | ||
178 | #define TIPC_ADDR_NAME 2 | ||
179 | #define TIPC_ADDR_ID 3 | ||
180 | |||
181 | struct sockaddr_tipc { | ||
182 | unsigned short family; | ||
183 | unsigned char addrtype; | ||
184 | signed char scope; | ||
185 | union { | ||
186 | struct tipc_portid id; | ||
187 | struct tipc_name_seq nameseq; | ||
188 | struct { | ||
189 | struct tipc_name name; | ||
190 | __u32 domain; /* 0: own zone */ | ||
191 | } name; | ||
192 | } addr; | ||
193 | }; | ||
194 | |||
195 | /* | ||
196 | * Ancillary data objects supported by recvmsg() | ||
197 | */ | ||
198 | |||
199 | #define TIPC_ERRINFO 1 /* error info */ | ||
200 | #define TIPC_RETDATA 2 /* returned data */ | ||
201 | #define TIPC_DESTNAME 3 /* destination name */ | ||
202 | |||
203 | /* | ||
204 | * TIPC-specific socket option values | ||
205 | */ | ||
206 | |||
207 | #define TIPC_IMPORTANCE 127 /* Default: TIPC_LOW_IMPORTANCE */ | ||
208 | #define TIPC_SRC_DROPPABLE 128 /* Default: 0 (resend congested msg) */ | ||
209 | #define TIPC_DEST_DROPPABLE 129 /* Default: based on socket type */ | ||
210 | #define TIPC_CONN_TIMEOUT 130 /* Default: 8000 (ms) */ | ||
211 | |||
212 | #endif | ||
diff --git a/include/linux/tipc_config.h b/include/linux/tipc_config.h new file mode 100644 index 000000000000..a52c8c64a5a3 --- /dev/null +++ b/include/linux/tipc_config.h | |||
@@ -0,0 +1,407 @@ | |||
1 | /* | ||
2 | * include/linux/tipc_config.h: Include file for TIPC configuration interface | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _LINUX_TIPC_CONFIG_H_ | ||
38 | #define _LINUX_TIPC_CONFIG_H_ | ||
39 | |||
40 | #include <linux/types.h> | ||
41 | #include <linux/string.h> | ||
42 | #include <asm/byteorder.h> | ||
43 | |||
44 | /* | ||
45 | * Configuration | ||
46 | * | ||
47 | * All configuration management messaging involves sending a request message | ||
48 | * to the TIPC configuration service on a node, which sends a reply message | ||
49 | * back. (In the future multi-message replies may be supported.) | ||
50 | * | ||
51 | * Both request and reply messages consist of a transport header and payload. | ||
52 | * The transport header contains info about the desired operation; | ||
53 | * the payload consists of zero or more type/length/value (TLV) items | ||
54 | * which specify parameters or results for the operation. | ||
55 | * | ||
56 | * For many operations, the request and reply messages have a fixed number | ||
57 | * of TLVs (usually zero or one); however, some reply messages may return | ||
58 | * a variable number of TLVs. A failed request is denoted by the presence | ||
59 | * of an "error string" TLV in the reply message instead of the TLV(s) the | ||
60 | * reply should contain if the request succeeds. | ||
61 | */ | ||
62 | |||
63 | /* | ||
64 | * Public commands: | ||
65 | * May be issued by any process. | ||
66 | * Accepted by own node, or by remote node only if remote management enabled. | ||
67 | */ | ||
68 | |||
69 | #define TIPC_CMD_NOOP 0x0000 /* tx none, rx none */ | ||
70 | #define TIPC_CMD_GET_NODES 0x0001 /* tx net_addr, rx node_info(s) */ | ||
71 | #define TIPC_CMD_GET_MEDIA_NAMES 0x0002 /* tx none, rx media_name(s) */ | ||
72 | #define TIPC_CMD_GET_BEARER_NAMES 0x0003 /* tx none, rx bearer_name(s) */ | ||
73 | #define TIPC_CMD_GET_LINKS 0x0004 /* tx net_addr, rx link_info(s) */ | ||
74 | #define TIPC_CMD_SHOW_NAME_TABLE 0x0005 /* tx name_tbl_query, rx ultra_string */ | ||
75 | #define TIPC_CMD_SHOW_PORTS 0x0006 /* tx none, rx ultra_string */ | ||
76 | #define TIPC_CMD_SHOW_LINK_STATS 0x000B /* tx link_name, rx ultra_string */ | ||
77 | |||
78 | #if 0 | ||
79 | #define TIPC_CMD_SHOW_PORT_STATS 0x0008 /* tx port_ref, rx ultra_string */ | ||
80 | #define TIPC_CMD_RESET_PORT_STATS 0x0009 /* tx port_ref, rx none */ | ||
81 | #define TIPC_CMD_GET_ROUTES 0x000A /* tx ?, rx ? */ | ||
82 | #define TIPC_CMD_GET_LINK_PEER 0x000D /* tx link_name, rx ? */ | ||
83 | #endif | ||
84 | |||
85 | /* | ||
86 | * Protected commands: | ||
87 | * May only be issued by "network administration capable" process. | ||
88 | * Accepted by own node, or by remote node only if remote management enabled | ||
89 | * and this node is zone manager. | ||
90 | */ | ||
91 | |||
92 | #define TIPC_CMD_GET_REMOTE_MNG 0x4003 /* tx none, rx unsigned */ | ||
93 | #define TIPC_CMD_GET_MAX_PORTS 0x4004 /* tx none, rx unsigned */ | ||
94 | #define TIPC_CMD_GET_MAX_PUBL 0x4005 /* tx none, rx unsigned */ | ||
95 | #define TIPC_CMD_GET_MAX_SUBSCR 0x4006 /* tx none, rx unsigned */ | ||
96 | #define TIPC_CMD_GET_MAX_ZONES 0x4007 /* tx none, rx unsigned */ | ||
97 | #define TIPC_CMD_GET_MAX_CLUSTERS 0x4008 /* tx none, rx unsigned */ | ||
98 | #define TIPC_CMD_GET_MAX_NODES 0x4009 /* tx none, rx unsigned */ | ||
99 | #define TIPC_CMD_GET_MAX_SLAVES 0x400A /* tx none, rx unsigned */ | ||
100 | #define TIPC_CMD_GET_NETID 0x400B /* tx none, rx unsigned */ | ||
101 | |||
102 | #define TIPC_CMD_ENABLE_BEARER 0x4101 /* tx bearer_config, rx none */ | ||
103 | #define TIPC_CMD_DISABLE_BEARER 0x4102 /* tx bearer_name, rx none */ | ||
104 | #define TIPC_CMD_SET_LINK_TOL 0x4107 /* tx link_config, rx none */ | ||
105 | #define TIPC_CMD_SET_LINK_PRI 0x4108 /* tx link_config, rx none */ | ||
106 | #define TIPC_CMD_SET_LINK_WINDOW 0x4109 /* tx link_config, rx none */ | ||
107 | #define TIPC_CMD_SET_LOG_SIZE 0x410A /* tx unsigned, rx none */ | ||
108 | #define TIPC_CMD_DUMP_LOG 0x410B /* tx none, rx ultra_string */ | ||
109 | #define TIPC_CMD_RESET_LINK_STATS 0x410C /* tx link_name, rx none */ | ||
110 | |||
111 | #if 0 | ||
112 | #define TIPC_CMD_CREATE_LINK 0x4103 /* tx link_create, rx none */ | ||
113 | #define TIPC_CMD_REMOVE_LINK 0x4104 /* tx link_name, rx none */ | ||
114 | #define TIPC_CMD_BLOCK_LINK 0x4105 /* tx link_name, rx none */ | ||
115 | #define TIPC_CMD_UNBLOCK_LINK 0x4106 /* tx link_name, rx none */ | ||
116 | #endif | ||
117 | |||
118 | /* | ||
119 | * Private commands: | ||
120 | * May only be issued by "network administration capable" process. | ||
121 | * Accepted by own node only; cannot be used on a remote node. | ||
122 | */ | ||
123 | |||
124 | #define TIPC_CMD_SET_NODE_ADDR 0x8001 /* tx net_addr, rx none */ | ||
125 | #if 0 | ||
126 | #define TIPC_CMD_SET_ZONE_MASTER 0x8002 /* tx none, rx none */ | ||
127 | #endif | ||
128 | #define TIPC_CMD_SET_REMOTE_MNG 0x8003 /* tx unsigned, rx none */ | ||
129 | #define TIPC_CMD_SET_MAX_PORTS 0x8004 /* tx unsigned, rx none */ | ||
130 | #define TIPC_CMD_SET_MAX_PUBL 0x8005 /* tx unsigned, rx none */ | ||
131 | #define TIPC_CMD_SET_MAX_SUBSCR 0x8006 /* tx unsigned, rx none */ | ||
132 | #define TIPC_CMD_SET_MAX_ZONES 0x8007 /* tx unsigned, rx none */ | ||
133 | #define TIPC_CMD_SET_MAX_CLUSTERS 0x8008 /* tx unsigned, rx none */ | ||
134 | #define TIPC_CMD_SET_MAX_NODES 0x8009 /* tx unsigned, rx none */ | ||
135 | #define TIPC_CMD_SET_MAX_SLAVES 0x800A /* tx unsigned, rx none */ | ||
136 | #define TIPC_CMD_SET_NETID 0x800B /* tx unsigned, rx none */ | ||
137 | |||
138 | /* | ||
139 | * TLV types defined for TIPC | ||
140 | */ | ||
141 | |||
142 | #define TIPC_TLV_NONE 0 /* no TLV present */ | ||
143 | #define TIPC_TLV_VOID 1 /* empty TLV (0 data bytes)*/ | ||
144 | #define TIPC_TLV_UNSIGNED 2 /* 32-bit integer */ | ||
145 | #define TIPC_TLV_STRING 3 /* char[128] (max) */ | ||
146 | #define TIPC_TLV_LARGE_STRING 4 /* char[2048] (max) */ | ||
147 | #define TIPC_TLV_ULTRA_STRING 5 /* char[32768] (max) */ | ||
148 | |||
149 | #define TIPC_TLV_ERROR_STRING 16 /* char[128] containing "error code" */ | ||
150 | #define TIPC_TLV_NET_ADDR 17 /* 32-bit integer denoting <Z.C.N> */ | ||
151 | #define TIPC_TLV_MEDIA_NAME 18 /* char[TIPC_MAX_MEDIA_NAME] */ | ||
152 | #define TIPC_TLV_BEARER_NAME 19 /* char[TIPC_MAX_BEARER_NAME] */ | ||
153 | #define TIPC_TLV_LINK_NAME 20 /* char[TIPC_MAX_LINK_NAME] */ | ||
154 | #define TIPC_TLV_NODE_INFO 21 /* struct tipc_node_info */ | ||
155 | #define TIPC_TLV_LINK_INFO 22 /* struct tipc_link_info */ | ||
156 | #define TIPC_TLV_BEARER_CONFIG 23 /* struct tipc_bearer_config */ | ||
157 | #define TIPC_TLV_LINK_CONFIG 24 /* struct tipc_link_config */ | ||
158 | #define TIPC_TLV_NAME_TBL_QUERY 25 /* struct tipc_name_table_query */ | ||
159 | #define TIPC_TLV_PORT_REF 26 /* 32-bit port reference */ | ||
160 | |||
161 | /* | ||
162 | * Maximum sizes of TIPC bearer-related names (including terminating NUL) | ||
163 | */ | ||
164 | |||
165 | #define TIPC_MAX_MEDIA_NAME 16 /* format = media */ | ||
166 | #define TIPC_MAX_IF_NAME 16 /* format = interface */ | ||
167 | #define TIPC_MAX_BEARER_NAME 32 /* format = media:interface */ | ||
168 | #define TIPC_MAX_LINK_NAME 60 /* format = Z.C.N:interface-Z.C.N:interface */ | ||
169 | |||
170 | /* | ||
171 | * Link priority limits (range from 0 to # priorities - 1) | ||
172 | */ | ||
173 | |||
174 | #define TIPC_NUM_LINK_PRI 32 | ||
175 | |||
176 | /* | ||
177 | * Link tolerance limits (min, default, max), in ms | ||
178 | */ | ||
179 | |||
180 | #define TIPC_MIN_LINK_TOL 50 | ||
181 | #define TIPC_DEF_LINK_TOL 1500 | ||
182 | #define TIPC_MAX_LINK_TOL 30000 | ||
183 | |||
184 | /* | ||
185 | * Link window limits (min, default, max), in packets | ||
186 | */ | ||
187 | |||
188 | #define TIPC_MIN_LINK_WIN 16 | ||
189 | #define TIPC_DEF_LINK_WIN 50 | ||
190 | #define TIPC_MAX_LINK_WIN 150 | ||
191 | |||
192 | |||
193 | struct tipc_node_info { | ||
194 | __u32 addr; /* network address of node */ | ||
195 | __u32 up; /* 0=down, 1= up */ | ||
196 | }; | ||
197 | |||
198 | struct tipc_link_info { | ||
199 | __u32 dest; /* network address of peer node */ | ||
200 | __u32 up; /* 0=down, 1=up */ | ||
201 | char str[TIPC_MAX_LINK_NAME]; /* link name */ | ||
202 | }; | ||
203 | |||
204 | struct tipc_bearer_config { | ||
205 | __u32 priority; /* Range [1,31]. Override per link */ | ||
206 | __u32 detect_scope; | ||
207 | char name[TIPC_MAX_BEARER_NAME]; | ||
208 | }; | ||
209 | |||
210 | struct tipc_link_config { | ||
211 | __u32 value; | ||
212 | char name[TIPC_MAX_LINK_NAME]; | ||
213 | }; | ||
214 | |||
215 | #define TIPC_NTQ_ALLTYPES 0x80000000 | ||
216 | |||
217 | struct tipc_name_table_query { | ||
218 | __u32 depth; /* 1:type, 2:+name info, 3:+port info, 4+:+debug info */ | ||
219 | __u32 type; /* {t,l,u} info ignored if high bit of "depth" is set */ | ||
220 | __u32 lowbound; /* (i.e. displays all entries of name table) */ | ||
221 | __u32 upbound; | ||
222 | }; | ||
223 | |||
224 | /* | ||
225 | * The error string TLV is a null-terminated string describing the cause | ||
226 | * of the request failure. To simplify error processing (and to save space) | ||
227 | * the first character of the string can be a special error code character | ||
228 | * (lying by the range 0x80 to 0xFF) which represents a pre-defined reason. | ||
229 | */ | ||
230 | |||
231 | #define TIPC_CFG_TLV_ERROR "\x80" /* request contains incorrect TLV(s) */ | ||
232 | #define TIPC_CFG_NOT_NET_ADMIN "\x81" /* must be network administrator */ | ||
233 | #define TIPC_CFG_NOT_ZONE_MSTR "\x82" /* must be zone master */ | ||
234 | #define TIPC_CFG_NO_REMOTE "\x83" /* remote management not enabled */ | ||
235 | #define TIPC_CFG_NOT_SUPPORTED "\x84" /* request is not supported by TIPC */ | ||
236 | #define TIPC_CFG_INVALID_VALUE "\x85" /* request has invalid argument value */ | ||
237 | |||
238 | #if 0 | ||
239 | /* prototypes TLV structures for proposed commands */ | ||
240 | struct tipc_link_create { | ||
241 | __u32 domain; | ||
242 | struct tipc_media_addr peer_addr; | ||
243 | char bearer_name[TIPC_MAX_BEARER_NAME]; | ||
244 | }; | ||
245 | |||
246 | struct tipc_route_info { | ||
247 | __u32 dest; | ||
248 | __u32 router; | ||
249 | }; | ||
250 | #endif | ||
251 | |||
252 | /* | ||
253 | * A TLV consists of a descriptor, followed by the TLV value. | ||
254 | * TLV descriptor fields are stored in network byte order; | ||
255 | * TLV values must also be stored in network byte order (where applicable). | ||
256 | * TLV descriptors must be aligned to addresses which are multiple of 4, | ||
257 | * so up to 3 bytes of padding may exist at the end of the TLV value area. | ||
258 | * There must not be any padding between the TLV descriptor and its value. | ||
259 | */ | ||
260 | |||
261 | struct tlv_desc { | ||
262 | __u16 tlv_len; /* TLV length (descriptor + value) */ | ||
263 | __u16 tlv_type; /* TLV identifier */ | ||
264 | }; | ||
265 | |||
266 | #define TLV_ALIGNTO 4 | ||
267 | |||
268 | #define TLV_ALIGN(datalen) (((datalen)+(TLV_ALIGNTO-1)) & ~(TLV_ALIGNTO-1)) | ||
269 | #define TLV_LENGTH(datalen) (sizeof(struct tlv_desc) + (datalen)) | ||
270 | #define TLV_SPACE(datalen) (TLV_ALIGN(TLV_LENGTH(datalen))) | ||
271 | #define TLV_DATA(tlv) ((void *)((char *)(tlv) + TLV_LENGTH(0))) | ||
272 | |||
273 | static inline int TLV_OK(const void *tlv, __u16 space) | ||
274 | { | ||
275 | /* | ||
276 | * Would also like to check that "tlv" is a multiple of 4, | ||
277 | * but don't know how to do this in a portable way. | ||
278 | * - Tried doing (!(tlv & (TLV_ALIGNTO-1))), but GCC compiler | ||
279 | * won't allow binary "&" with a pointer. | ||
280 | * - Tried casting "tlv" to integer type, but causes warning about size | ||
281 | * mismatch when pointer is bigger than chosen type (int, long, ...). | ||
282 | */ | ||
283 | |||
284 | return (space >= TLV_SPACE(0)) && | ||
285 | (ntohs(((struct tlv_desc *)tlv)->tlv_len) <= space); | ||
286 | } | ||
287 | |||
288 | static inline int TLV_CHECK(const void *tlv, __u16 space, __u16 exp_type) | ||
289 | { | ||
290 | return TLV_OK(tlv, space) && | ||
291 | (ntohs(((struct tlv_desc *)tlv)->tlv_type) == exp_type); | ||
292 | } | ||
293 | |||
294 | static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len) | ||
295 | { | ||
296 | struct tlv_desc *tlv_ptr; | ||
297 | int tlv_len; | ||
298 | |||
299 | tlv_len = TLV_LENGTH(len); | ||
300 | tlv_ptr = (struct tlv_desc *)tlv; | ||
301 | tlv_ptr->tlv_type = htons(type); | ||
302 | tlv_ptr->tlv_len = htons(tlv_len); | ||
303 | if (len && data) | ||
304 | memcpy(TLV_DATA(tlv_ptr), data, tlv_len); | ||
305 | return TLV_SPACE(len); | ||
306 | } | ||
307 | |||
308 | /* | ||
309 | * A TLV list descriptor simplifies processing of messages | ||
310 | * containing multiple TLVs. | ||
311 | */ | ||
312 | |||
313 | struct tlv_list_desc { | ||
314 | struct tlv_desc *tlv_ptr; /* ptr to current TLV */ | ||
315 | __u32 tlv_space; /* # bytes from curr TLV to list end */ | ||
316 | }; | ||
317 | |||
318 | static inline void TLV_LIST_INIT(struct tlv_list_desc *list, | ||
319 | void *data, __u32 space) | ||
320 | { | ||
321 | list->tlv_ptr = (struct tlv_desc *)data; | ||
322 | list->tlv_space = space; | ||
323 | } | ||
324 | |||
325 | static inline int TLV_LIST_EMPTY(struct tlv_list_desc *list) | ||
326 | { | ||
327 | return (list->tlv_space == 0); | ||
328 | } | ||
329 | |||
330 | static inline int TLV_LIST_CHECK(struct tlv_list_desc *list, __u16 exp_type) | ||
331 | { | ||
332 | return TLV_CHECK(list->tlv_ptr, list->tlv_space, exp_type); | ||
333 | } | ||
334 | |||
335 | static inline void *TLV_LIST_DATA(struct tlv_list_desc *list) | ||
336 | { | ||
337 | return TLV_DATA(list->tlv_ptr); | ||
338 | } | ||
339 | |||
340 | static inline void TLV_LIST_STEP(struct tlv_list_desc *list) | ||
341 | { | ||
342 | __u16 tlv_space = TLV_ALIGN(ntohs(list->tlv_ptr->tlv_len)); | ||
343 | |||
344 | list->tlv_ptr = (struct tlv_desc *)((char *)list->tlv_ptr + tlv_space); | ||
345 | list->tlv_space -= tlv_space; | ||
346 | } | ||
347 | |||
348 | /* | ||
349 | * Configuration messages exchanged via NETLINK_GENERIC use the following | ||
350 | * family id, name, version and command. | ||
351 | */ | ||
352 | #define TIPC_GENL_NAME "TIPC" | ||
353 | #define TIPC_GENL_VERSION 0x1 | ||
354 | #define TIPC_GENL_CMD 0x1 | ||
355 | |||
356 | /* | ||
357 | * TIPC specific header used in NETLINK_GENERIC requests. | ||
358 | */ | ||
359 | struct tipc_genlmsghdr { | ||
360 | __u32 dest; /* Destination address */ | ||
361 | __u16 cmd; /* Command */ | ||
362 | __u16 reserved; /* Unused */ | ||
363 | }; | ||
364 | |||
365 | #define TIPC_GENL_HDRLEN NLMSG_ALIGN(sizeof(struct tipc_genlmsghdr)) | ||
366 | |||
367 | /* | ||
368 | * Configuration messages exchanged via TIPC sockets use the TIPC configuration | ||
369 | * message header, which is defined below. This structure is analogous | ||
370 | * to the Netlink message header, but fields are stored in network byte order | ||
371 | * and no padding is permitted between the header and the message data | ||
372 | * that follows. | ||
373 | */ | ||
374 | |||
375 | struct tipc_cfg_msg_hdr | ||
376 | { | ||
377 | __u32 tcm_len; /* Message length (including header) */ | ||
378 | __u16 tcm_type; /* Command type */ | ||
379 | __u16 tcm_flags; /* Additional flags */ | ||
380 | char tcm_reserved[8]; /* Unused */ | ||
381 | }; | ||
382 | |||
383 | #define TCM_F_REQUEST 0x1 /* Flag: Request message */ | ||
384 | #define TCM_F_MORE 0x2 /* Flag: Message to be continued */ | ||
385 | |||
386 | #define TCM_ALIGN(datalen) (((datalen)+3) & ~3) | ||
387 | #define TCM_LENGTH(datalen) (sizeof(struct tipc_cfg_msg_hdr) + datalen) | ||
388 | #define TCM_SPACE(datalen) (TCM_ALIGN(TCM_LENGTH(datalen))) | ||
389 | #define TCM_DATA(tcm_hdr) ((void *)((char *)(tcm_hdr) + TCM_LENGTH(0))) | ||
390 | |||
391 | static inline int TCM_SET(void *msg, __u16 cmd, __u16 flags, | ||
392 | void *data, __u16 data_len) | ||
393 | { | ||
394 | struct tipc_cfg_msg_hdr *tcm_hdr; | ||
395 | int msg_len; | ||
396 | |||
397 | msg_len = TCM_LENGTH(data_len); | ||
398 | tcm_hdr = (struct tipc_cfg_msg_hdr *)msg; | ||
399 | tcm_hdr->tcm_len = htonl(msg_len); | ||
400 | tcm_hdr->tcm_type = htons(cmd); | ||
401 | tcm_hdr->tcm_flags = htons(flags); | ||
402 | if (data_len && data) | ||
403 | memcpy(TCM_DATA(msg), data, data_len); | ||
404 | return TCM_SPACE(data_len); | ||
405 | } | ||
406 | |||
407 | #endif | ||
diff --git a/include/net/genetlink.h b/include/net/genetlink.h index c5b96b2b8155..805de50df00d 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h | |||
@@ -22,7 +22,6 @@ struct genl_family | |||
22 | char name[GENL_NAMSIZ]; | 22 | char name[GENL_NAMSIZ]; |
23 | unsigned int version; | 23 | unsigned int version; |
24 | unsigned int maxattr; | 24 | unsigned int maxattr; |
25 | struct module * owner; | ||
26 | struct nlattr ** attrbuf; /* private */ | 25 | struct nlattr ** attrbuf; /* private */ |
27 | struct list_head ops_list; /* private */ | 26 | struct list_head ops_list; /* private */ |
28 | struct list_head family_list; /* private */ | 27 | struct list_head family_list; /* private */ |
diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h index 25b081a730e6..91684436af8e 100644 --- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h +++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h | |||
@@ -37,7 +37,4 @@ struct nf_conntrack_ipv4 { | |||
37 | struct sk_buff * | 37 | struct sk_buff * |
38 | nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb); | 38 | nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb); |
39 | 39 | ||
40 | /* call to create an explicit dependency on nf_conntrack_l3proto_ipv4. */ | ||
41 | extern void need_ip_conntrack(void); | ||
42 | |||
43 | #endif /*_NF_CONNTRACK_IPV4_H*/ | 40 | #endif /*_NF_CONNTRACK_IPV4_H*/ |
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index 64b82b74a650..6d075ca16e6e 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h | |||
@@ -221,9 +221,6 @@ extern void nf_ct_helper_put(struct nf_conntrack_helper *helper); | |||
221 | extern struct nf_conntrack_helper * | 221 | extern struct nf_conntrack_helper * |
222 | __nf_conntrack_helper_find_byname(const char *name); | 222 | __nf_conntrack_helper_find_byname(const char *name); |
223 | 223 | ||
224 | /* call to create an explicit dependency on nf_conntrack. */ | ||
225 | extern void need_nf_conntrack(void); | ||
226 | |||
227 | extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, | 224 | extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, |
228 | const struct nf_conntrack_tuple *orig); | 225 | const struct nf_conntrack_tuple *orig); |
229 | 226 | ||
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index 14ce790e5c65..530ef1f75283 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h | |||
@@ -111,7 +111,7 @@ struct nf_conntrack_tuple | |||
111 | #ifdef __KERNEL__ | 111 | #ifdef __KERNEL__ |
112 | 112 | ||
113 | #define NF_CT_DUMP_TUPLE(tp) \ | 113 | #define NF_CT_DUMP_TUPLE(tp) \ |
114 | DEBUGP("tuple %p: %u %u %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu -> %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu\n", \ | 114 | DEBUGP("tuple %p: %u %u " NIP6_FMT " %hu -> " NIP6_FMT " %hu\n", \ |
115 | (tp), (tp)->src.l3num, (tp)->dst.protonum, \ | 115 | (tp), (tp)->src.l3num, (tp)->dst.protonum, \ |
116 | NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \ | 116 | NIP6(*(struct in6_addr *)(tp)->src.u3.all), ntohs((tp)->src.u.all), \ |
117 | NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all)) | 117 | NIP6(*(struct in6_addr *)(tp)->dst.u3.all), ntohs((tp)->dst.u.all)) |
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 8f241216f46b..a553f39f6aee 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
@@ -225,13 +225,13 @@ extern int sctp_debug_flag; | |||
225 | if (sctp_debug_flag) { \ | 225 | if (sctp_debug_flag) { \ |
226 | if (saddr->sa.sa_family == AF_INET6) { \ | 226 | if (saddr->sa.sa_family == AF_INET6) { \ |
227 | printk(KERN_DEBUG \ | 227 | printk(KERN_DEBUG \ |
228 | lead "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" trail, \ | 228 | lead NIP6_FMT trail, \ |
229 | leadparm, \ | 229 | leadparm, \ |
230 | NIP6(saddr->v6.sin6_addr), \ | 230 | NIP6(saddr->v6.sin6_addr), \ |
231 | otherparms); \ | 231 | otherparms); \ |
232 | } else { \ | 232 | } else { \ |
233 | printk(KERN_DEBUG \ | 233 | printk(KERN_DEBUG \ |
234 | lead "%u.%u.%u.%u" trail, \ | 234 | lead NIPQUAD_FMT trail, \ |
235 | leadparm, \ | 235 | leadparm, \ |
236 | NIPQUAD(saddr->v4.sin_addr.s_addr), \ | 236 | NIPQUAD(saddr->v4.sin_addr.s_addr), \ |
237 | otherparms); \ | 237 | otherparms); \ |
diff --git a/include/net/tipc/tipc.h b/include/net/tipc/tipc.h new file mode 100644 index 000000000000..9566608c88cf --- /dev/null +++ b/include/net/tipc/tipc.h | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | * include/net/tipc/tipc.h: Main include file for TIPC users | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _NET_TIPC_H_ | ||
38 | #define _NET_TIPC_H_ | ||
39 | |||
40 | #ifdef __KERNEL__ | ||
41 | |||
42 | #include <linux/tipc.h> | ||
43 | #include <linux/skbuff.h> | ||
44 | |||
45 | /* | ||
46 | * Native API | ||
47 | */ | ||
48 | |||
49 | /* | ||
50 | * TIPC operating mode routines | ||
51 | */ | ||
52 | |||
53 | u32 tipc_get_addr(void); | ||
54 | |||
55 | #define TIPC_NOT_RUNNING 0 | ||
56 | #define TIPC_NODE_MODE 1 | ||
57 | #define TIPC_NET_MODE 2 | ||
58 | |||
59 | typedef void (*tipc_mode_event)(void *usr_handle, int mode, u32 addr); | ||
60 | |||
61 | int tipc_attach(unsigned int *userref, tipc_mode_event, void *usr_handle); | ||
62 | |||
63 | void tipc_detach(unsigned int userref); | ||
64 | |||
65 | int tipc_get_mode(void); | ||
66 | |||
67 | /* | ||
68 | * TIPC port manipulation routines | ||
69 | */ | ||
70 | |||
71 | typedef void (*tipc_msg_err_event) (void *usr_handle, | ||
72 | u32 portref, | ||
73 | struct sk_buff **buf, | ||
74 | unsigned char const *data, | ||
75 | unsigned int size, | ||
76 | int reason, | ||
77 | struct tipc_portid const *attmpt_destid); | ||
78 | |||
79 | typedef void (*tipc_named_msg_err_event) (void *usr_handle, | ||
80 | u32 portref, | ||
81 | struct sk_buff **buf, | ||
82 | unsigned char const *data, | ||
83 | unsigned int size, | ||
84 | int reason, | ||
85 | struct tipc_name_seq const *attmpt_dest); | ||
86 | |||
87 | typedef void (*tipc_conn_shutdown_event) (void *usr_handle, | ||
88 | u32 portref, | ||
89 | struct sk_buff **buf, | ||
90 | unsigned char const *data, | ||
91 | unsigned int size, | ||
92 | int reason); | ||
93 | |||
94 | typedef void (*tipc_msg_event) (void *usr_handle, | ||
95 | u32 portref, | ||
96 | struct sk_buff **buf, | ||
97 | unsigned char const *data, | ||
98 | unsigned int size, | ||
99 | unsigned int importance, | ||
100 | struct tipc_portid const *origin); | ||
101 | |||
102 | typedef void (*tipc_named_msg_event) (void *usr_handle, | ||
103 | u32 portref, | ||
104 | struct sk_buff **buf, | ||
105 | unsigned char const *data, | ||
106 | unsigned int size, | ||
107 | unsigned int importance, | ||
108 | struct tipc_portid const *orig, | ||
109 | struct tipc_name_seq const *dest); | ||
110 | |||
111 | typedef void (*tipc_conn_msg_event) (void *usr_handle, | ||
112 | u32 portref, | ||
113 | struct sk_buff **buf, | ||
114 | unsigned char const *data, | ||
115 | unsigned int size); | ||
116 | |||
117 | typedef void (*tipc_continue_event) (void *usr_handle, | ||
118 | u32 portref); | ||
119 | |||
120 | int tipc_createport(unsigned int tipc_user, | ||
121 | void *usr_handle, | ||
122 | unsigned int importance, | ||
123 | tipc_msg_err_event error_cb, | ||
124 | tipc_named_msg_err_event named_error_cb, | ||
125 | tipc_conn_shutdown_event conn_error_cb, | ||
126 | tipc_msg_event message_cb, | ||
127 | tipc_named_msg_event named_message_cb, | ||
128 | tipc_conn_msg_event conn_message_cb, | ||
129 | tipc_continue_event continue_event_cb,/* May be zero */ | ||
130 | u32 *portref); | ||
131 | |||
132 | int tipc_deleteport(u32 portref); | ||
133 | |||
134 | int tipc_ownidentity(u32 portref, struct tipc_portid *port); | ||
135 | |||
136 | int tipc_portimportance(u32 portref, unsigned int *importance); | ||
137 | int tipc_set_portimportance(u32 portref, unsigned int importance); | ||
138 | |||
139 | int tipc_portunreliable(u32 portref, unsigned int *isunreliable); | ||
140 | int tipc_set_portunreliable(u32 portref, unsigned int isunreliable); | ||
141 | |||
142 | int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable); | ||
143 | int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable); | ||
144 | |||
145 | int tipc_publish(u32 portref, unsigned int scope, | ||
146 | struct tipc_name_seq const *name_seq); | ||
147 | int tipc_withdraw(u32 portref, unsigned int scope, | ||
148 | struct tipc_name_seq const *name_seq); /* 0: all */ | ||
149 | |||
150 | int tipc_connect2port(u32 portref, struct tipc_portid const *port); | ||
151 | |||
152 | int tipc_disconnect(u32 portref); | ||
153 | |||
154 | int tipc_shutdown(u32 ref); /* Sends SHUTDOWN msg */ | ||
155 | |||
156 | int tipc_isconnected(u32 portref, int *isconnected); | ||
157 | |||
158 | int tipc_peer(u32 portref, struct tipc_portid *peer); | ||
159 | |||
160 | int tipc_ref_valid(u32 portref); | ||
161 | |||
162 | /* | ||
163 | * TIPC messaging routines | ||
164 | */ | ||
165 | |||
166 | #define TIPC_PORT_IMPORTANCE 100 /* send using current port setting */ | ||
167 | |||
168 | |||
169 | int tipc_send(u32 portref, | ||
170 | unsigned int num_sect, | ||
171 | struct iovec const *msg_sect); | ||
172 | |||
173 | int tipc_send_buf(u32 portref, | ||
174 | struct sk_buff *buf, | ||
175 | unsigned int dsz); | ||
176 | |||
177 | int tipc_send2name(u32 portref, | ||
178 | struct tipc_name const *name, | ||
179 | u32 domain, /* 0:own zone */ | ||
180 | unsigned int num_sect, | ||
181 | struct iovec const *msg_sect); | ||
182 | |||
183 | int tipc_send_buf2name(u32 portref, | ||
184 | struct tipc_name const *name, | ||
185 | u32 domain, | ||
186 | struct sk_buff *buf, | ||
187 | unsigned int dsz); | ||
188 | |||
189 | int tipc_forward2name(u32 portref, | ||
190 | struct tipc_name const *name, | ||
191 | u32 domain, /*0: own zone */ | ||
192 | unsigned int section_count, | ||
193 | struct iovec const *msg_sect, | ||
194 | struct tipc_portid const *origin, | ||
195 | unsigned int importance); | ||
196 | |||
197 | int tipc_forward_buf2name(u32 portref, | ||
198 | struct tipc_name const *name, | ||
199 | u32 domain, | ||
200 | struct sk_buff *buf, | ||
201 | unsigned int dsz, | ||
202 | struct tipc_portid const *orig, | ||
203 | unsigned int importance); | ||
204 | |||
205 | int tipc_send2port(u32 portref, | ||
206 | struct tipc_portid const *dest, | ||
207 | unsigned int num_sect, | ||
208 | struct iovec const *msg_sect); | ||
209 | |||
210 | int tipc_send_buf2port(u32 portref, | ||
211 | struct tipc_portid const *dest, | ||
212 | struct sk_buff *buf, | ||
213 | unsigned int dsz); | ||
214 | |||
215 | int tipc_forward2port(u32 portref, | ||
216 | struct tipc_portid const *dest, | ||
217 | unsigned int num_sect, | ||
218 | struct iovec const *msg_sect, | ||
219 | struct tipc_portid const *origin, | ||
220 | unsigned int importance); | ||
221 | |||
222 | int tipc_forward_buf2port(u32 portref, | ||
223 | struct tipc_portid const *dest, | ||
224 | struct sk_buff *buf, | ||
225 | unsigned int dsz, | ||
226 | struct tipc_portid const *orig, | ||
227 | unsigned int importance); | ||
228 | |||
229 | int tipc_multicast(u32 portref, | ||
230 | struct tipc_name_seq const *seq, | ||
231 | u32 domain, /* 0:own zone */ | ||
232 | unsigned int section_count, | ||
233 | struct iovec const *msg); | ||
234 | |||
235 | #if 0 | ||
236 | int tipc_multicast_buf(u32 portref, | ||
237 | struct tipc_name_seq const *seq, | ||
238 | u32 domain, /* 0:own zone */ | ||
239 | void *buf, | ||
240 | unsigned int size); | ||
241 | #endif | ||
242 | |||
243 | /* | ||
244 | * TIPC subscription routines | ||
245 | */ | ||
246 | |||
247 | int tipc_ispublished(struct tipc_name const *name); | ||
248 | |||
249 | /* | ||
250 | * Get number of available nodes within specified domain (excluding own node) | ||
251 | */ | ||
252 | |||
253 | unsigned int tipc_available_nodes(const u32 domain); | ||
254 | |||
255 | #endif | ||
256 | |||
257 | #endif | ||
diff --git a/include/net/tipc/tipc_bearer.h b/include/net/tipc/tipc_bearer.h new file mode 100644 index 000000000000..098607cd4b78 --- /dev/null +++ b/include/net/tipc/tipc_bearer.h | |||
@@ -0,0 +1,121 @@ | |||
1 | /* | ||
2 | * include/net/tipc/tipc_bearer.h: Include file for privileged access to TIPC bearers | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _NET_TIPC_BEARER_H_ | ||
38 | #define _NET_TIPC_BEARER_H_ | ||
39 | |||
40 | #ifdef __KERNEL__ | ||
41 | |||
42 | #include <linux/tipc_config.h> | ||
43 | #include <linux/skbuff.h> | ||
44 | #include <linux/spinlock.h> | ||
45 | |||
46 | /* | ||
47 | * Identifiers of supported TIPC media types | ||
48 | */ | ||
49 | |||
50 | #define TIPC_MEDIA_TYPE_ETH 1 | ||
51 | |||
52 | struct tipc_media_addr { | ||
53 | __u32 type; | ||
54 | union { | ||
55 | __u8 eth_addr[6]; /* Ethernet bearer */ | ||
56 | #if 0 | ||
57 | /* Prototypes for other possible bearer types */ | ||
58 | |||
59 | struct { | ||
60 | __u16 sin_family; | ||
61 | __u16 sin_port; | ||
62 | struct { | ||
63 | __u32 s_addr; | ||
64 | } sin_addr; | ||
65 | char pad[4]; | ||
66 | } addr_in; /* IP-based bearer */ | ||
67 | __u16 sock_descr; /* generic socket bearer */ | ||
68 | #endif | ||
69 | } dev_addr; | ||
70 | }; | ||
71 | |||
72 | /** | ||
73 | * struct tipc_bearer - TIPC bearer info available to privileged users | ||
74 | * @usr_handle: pointer to additional user-defined information about bearer | ||
75 | * @mtu: max packet size bearer can support | ||
76 | * @blocked: non-zero if bearer is blocked | ||
77 | * @lock: spinlock for controlling access to bearer | ||
78 | * @addr: media-specific address associated with bearer | ||
79 | * @name: bearer name (format = media:interface) | ||
80 | * | ||
81 | * Note: TIPC initializes "name" and "lock" fields; user is responsible for | ||
82 | * initialization all other fields when a bearer is enabled. | ||
83 | */ | ||
84 | |||
85 | struct tipc_bearer { | ||
86 | void *usr_handle; | ||
87 | u32 mtu; | ||
88 | int blocked; | ||
89 | spinlock_t lock; | ||
90 | struct tipc_media_addr addr; | ||
91 | char name[TIPC_MAX_BEARER_NAME]; | ||
92 | }; | ||
93 | |||
94 | |||
95 | int tipc_register_media(u32 media_type, | ||
96 | char *media_name, | ||
97 | int (*enable)(struct tipc_bearer *), | ||
98 | void (*disable)(struct tipc_bearer *), | ||
99 | int (*send_msg)(struct sk_buff *, | ||
100 | struct tipc_bearer *, | ||
101 | struct tipc_media_addr *), | ||
102 | char *(*addr2str)(struct tipc_media_addr *a, | ||
103 | char *str_buf, | ||
104 | int str_size), | ||
105 | struct tipc_media_addr *bcast_addr, | ||
106 | const u32 bearer_priority, | ||
107 | const u32 link_tolerance, /* [ms] */ | ||
108 | const u32 send_window_limit); | ||
109 | |||
110 | void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr); | ||
111 | |||
112 | int tipc_block_bearer(const char *name); | ||
113 | void tipc_continue(struct tipc_bearer *tb_ptr); | ||
114 | |||
115 | int tipc_enable_bearer(const char *bearer_name, u32 bcast_scope, u32 priority); | ||
116 | int tipc_disable_bearer(const char *name); | ||
117 | |||
118 | |||
119 | #endif | ||
120 | |||
121 | #endif | ||
diff --git a/include/net/tipc/tipc_msg.h b/include/net/tipc/tipc_msg.h new file mode 100644 index 000000000000..4d096eebc93f --- /dev/null +++ b/include/net/tipc/tipc_msg.h | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * include/net/tipc/tipc_msg.h: Include file for privileged access to TIPC message headers | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _NET_TIPC_MSG_H_ | ||
38 | #define _NET_TIPC_MSG_H_ | ||
39 | |||
40 | #ifdef __KERNEL__ | ||
41 | |||
42 | struct tipc_msg { | ||
43 | u32 hdr[15]; | ||
44 | }; | ||
45 | |||
46 | |||
47 | /* | ||
48 | TIPC user data message header format, version 2: | ||
49 | |||
50 | |||
51 | 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 | ||
52 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
53 | w0:|vers | user |hdr sz |n|d|s|-| message size | | ||
54 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
55 | w1:|mstyp| error |rer cnt|lsc|opt p| broadcast ack no | | ||
56 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
57 | w2:| link level ack no | broadcast/link level seq no | | ||
58 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
59 | w3:| previous node | | ||
60 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
61 | w4:| originating port | | ||
62 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
63 | w5:| destination port | | ||
64 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
65 | w6:| originating node | | ||
66 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
67 | w7:| destination node | | ||
68 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
69 | w8:| name type / transport sequence number | | ||
70 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
71 | w9:| name instance/multicast lower bound | | ||
72 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
73 | wA:| multicast upper bound | | ||
74 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
75 | / / | ||
76 | \ options \ | ||
77 | / / | ||
78 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
79 | |||
80 | */ | ||
81 | |||
82 | #define TIPC_CONN_MSG 0 | ||
83 | #define TIPC_MCAST_MSG 1 | ||
84 | #define TIPC_NAMED_MSG 2 | ||
85 | #define TIPC_DIRECT_MSG 3 | ||
86 | |||
87 | |||
88 | static inline u32 msg_word(struct tipc_msg *m, u32 pos) | ||
89 | { | ||
90 | return ntohl(m->hdr[pos]); | ||
91 | } | ||
92 | |||
93 | static inline u32 msg_bits(struct tipc_msg *m, u32 w, u32 pos, u32 mask) | ||
94 | { | ||
95 | return (msg_word(m, w) >> pos) & mask; | ||
96 | } | ||
97 | |||
98 | static inline u32 msg_importance(struct tipc_msg *m) | ||
99 | { | ||
100 | return msg_bits(m, 0, 25, 0xf); | ||
101 | } | ||
102 | |||
103 | static inline u32 msg_hdr_sz(struct tipc_msg *m) | ||
104 | { | ||
105 | return msg_bits(m, 0, 21, 0xf) << 2; | ||
106 | } | ||
107 | |||
108 | static inline int msg_short(struct tipc_msg *m) | ||
109 | { | ||
110 | return (msg_hdr_sz(m) == 24); | ||
111 | } | ||
112 | |||
113 | static inline u32 msg_size(struct tipc_msg *m) | ||
114 | { | ||
115 | return msg_bits(m, 0, 0, 0x1ffff); | ||
116 | } | ||
117 | |||
118 | static inline u32 msg_data_sz(struct tipc_msg *m) | ||
119 | { | ||
120 | return (msg_size(m) - msg_hdr_sz(m)); | ||
121 | } | ||
122 | |||
123 | static inline unchar *msg_data(struct tipc_msg *m) | ||
124 | { | ||
125 | return ((unchar *)m) + msg_hdr_sz(m); | ||
126 | } | ||
127 | |||
128 | static inline u32 msg_type(struct tipc_msg *m) | ||
129 | { | ||
130 | return msg_bits(m, 1, 29, 0x7); | ||
131 | } | ||
132 | |||
133 | static inline u32 msg_direct(struct tipc_msg *m) | ||
134 | { | ||
135 | return (msg_type(m) == TIPC_DIRECT_MSG); | ||
136 | } | ||
137 | |||
138 | static inline u32 msg_named(struct tipc_msg *m) | ||
139 | { | ||
140 | return (msg_type(m) == TIPC_NAMED_MSG); | ||
141 | } | ||
142 | |||
143 | static inline u32 msg_mcast(struct tipc_msg *m) | ||
144 | { | ||
145 | return (msg_type(m) == TIPC_MCAST_MSG); | ||
146 | } | ||
147 | |||
148 | static inline u32 msg_connected(struct tipc_msg *m) | ||
149 | { | ||
150 | return (msg_type(m) == TIPC_CONN_MSG); | ||
151 | } | ||
152 | |||
153 | static inline u32 msg_errcode(struct tipc_msg *m) | ||
154 | { | ||
155 | return msg_bits(m, 1, 25, 0xf); | ||
156 | } | ||
157 | |||
158 | static inline u32 msg_prevnode(struct tipc_msg *m) | ||
159 | { | ||
160 | return msg_word(m, 3); | ||
161 | } | ||
162 | |||
163 | static inline u32 msg_origport(struct tipc_msg *m) | ||
164 | { | ||
165 | return msg_word(m, 4); | ||
166 | } | ||
167 | |||
168 | static inline u32 msg_destport(struct tipc_msg *m) | ||
169 | { | ||
170 | return msg_word(m, 5); | ||
171 | } | ||
172 | |||
173 | static inline u32 msg_mc_netid(struct tipc_msg *m) | ||
174 | { | ||
175 | return msg_word(m, 5); | ||
176 | } | ||
177 | |||
178 | static inline u32 msg_orignode(struct tipc_msg *m) | ||
179 | { | ||
180 | if (likely(msg_short(m))) | ||
181 | return msg_prevnode(m); | ||
182 | return msg_word(m, 6); | ||
183 | } | ||
184 | |||
185 | static inline u32 msg_destnode(struct tipc_msg *m) | ||
186 | { | ||
187 | return msg_word(m, 7); | ||
188 | } | ||
189 | |||
190 | static inline u32 msg_nametype(struct tipc_msg *m) | ||
191 | { | ||
192 | return msg_word(m, 8); | ||
193 | } | ||
194 | |||
195 | static inline u32 msg_nameinst(struct tipc_msg *m) | ||
196 | { | ||
197 | return msg_word(m, 9); | ||
198 | } | ||
199 | |||
200 | static inline u32 msg_namelower(struct tipc_msg *m) | ||
201 | { | ||
202 | return msg_nameinst(m); | ||
203 | } | ||
204 | |||
205 | static inline u32 msg_nameupper(struct tipc_msg *m) | ||
206 | { | ||
207 | return msg_word(m, 10); | ||
208 | } | ||
209 | |||
210 | static inline char *msg_options(struct tipc_msg *m, u32 *len) | ||
211 | { | ||
212 | u32 pos = msg_bits(m, 1, 16, 0x7); | ||
213 | |||
214 | if (!pos) | ||
215 | return 0; | ||
216 | pos = (pos * 4) + 28; | ||
217 | *len = msg_hdr_sz(m) - pos; | ||
218 | return (char *)&m->hdr[pos/4]; | ||
219 | } | ||
220 | |||
221 | #endif | ||
222 | |||
223 | #endif | ||
diff --git a/include/net/tipc/tipc_port.h b/include/net/tipc/tipc_port.h new file mode 100644 index 000000000000..333bba6dc522 --- /dev/null +++ b/include/net/tipc/tipc_port.h | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * include/net/tipc/tipc_port.h: Include file for privileged access to TIPC ports | ||
3 | * | ||
4 | * Copyright (c) 1994-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _NET_TIPC_PORT_H_ | ||
38 | #define _NET_TIPC_PORT_H_ | ||
39 | |||
40 | #ifdef __KERNEL__ | ||
41 | |||
42 | #include <linux/tipc.h> | ||
43 | #include <linux/skbuff.h> | ||
44 | #include <net/tipc/tipc_msg.h> | ||
45 | |||
46 | #define TIPC_FLOW_CONTROL_WIN 512 | ||
47 | |||
48 | /** | ||
49 | * struct tipc_port - native TIPC port info available to privileged users | ||
50 | * @usr_handle: pointer to additional user-defined information about port | ||
51 | * @lock: pointer to spinlock for controlling access to port | ||
52 | * @connected: non-zero if port is currently connected to a peer port | ||
53 | * @conn_type: TIPC type used when connection was established | ||
54 | * @conn_instance: TIPC instance used when connection was established | ||
55 | * @conn_unacked: number of unacknowledged messages received from peer port | ||
56 | * @published: non-zero if port has one or more associated names | ||
57 | * @congested: non-zero if cannot send because of link or port congestion | ||
58 | * @ref: unique reference to port in TIPC object registry | ||
59 | * @phdr: preformatted message header used when sending messages | ||
60 | */ | ||
61 | |||
62 | struct tipc_port { | ||
63 | void *usr_handle; | ||
64 | spinlock_t *lock; | ||
65 | int connected; | ||
66 | u32 conn_type; | ||
67 | u32 conn_instance; | ||
68 | u32 conn_unacked; | ||
69 | int published; | ||
70 | u32 congested; | ||
71 | u32 ref; | ||
72 | struct tipc_msg phdr; | ||
73 | }; | ||
74 | |||
75 | |||
76 | /** | ||
77 | * tipc_createport_raw - create a native TIPC port and return it's reference | ||
78 | * | ||
79 | * Note: 'dispatcher' and 'wakeup' deliver a locked port. | ||
80 | */ | ||
81 | |||
82 | u32 tipc_createport_raw(void *usr_handle, | ||
83 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), | ||
84 | void (*wakeup)(struct tipc_port *), | ||
85 | const u32 importance); | ||
86 | |||
87 | /* | ||
88 | * tipc_set_msg_option(): port must be locked. | ||
89 | */ | ||
90 | int tipc_set_msg_option(struct tipc_port *tp_ptr, | ||
91 | const char *opt, | ||
92 | const u32 len); | ||
93 | |||
94 | int tipc_reject_msg(struct sk_buff *buf, u32 err); | ||
95 | |||
96 | int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode); | ||
97 | |||
98 | void tipc_acknowledge(u32 port_ref,u32 ack); | ||
99 | |||
100 | struct tipc_port *tipc_get_port(const u32 ref); | ||
101 | |||
102 | void *tipc_get_handle(const u32 ref); | ||
103 | |||
104 | |||
105 | #endif | ||
106 | |||
107 | #endif | ||
108 | |||
diff --git a/net/Kconfig b/net/Kconfig index 60f6f321bd76..9296b269d675 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -159,6 +159,7 @@ source "net/ipx/Kconfig" | |||
159 | source "drivers/net/appletalk/Kconfig" | 159 | source "drivers/net/appletalk/Kconfig" |
160 | source "net/x25/Kconfig" | 160 | source "net/x25/Kconfig" |
161 | source "net/lapb/Kconfig" | 161 | source "net/lapb/Kconfig" |
162 | source "net/tipc/Kconfig" | ||
162 | 163 | ||
163 | config NET_DIVERT | 164 | config NET_DIVERT |
164 | bool "Frame Diverter (EXPERIMENTAL)" | 165 | bool "Frame Diverter (EXPERIMENTAL)" |
diff --git a/net/Makefile b/net/Makefile index f5141b9d4f38..065796f5fb17 100644 --- a/net/Makefile +++ b/net/Makefile | |||
@@ -45,6 +45,7 @@ obj-$(CONFIG_VLAN_8021Q) += 8021q/ | |||
45 | obj-$(CONFIG_IP_DCCP) += dccp/ | 45 | obj-$(CONFIG_IP_DCCP) += dccp/ |
46 | obj-$(CONFIG_IP_SCTP) += sctp/ | 46 | obj-$(CONFIG_IP_SCTP) += sctp/ |
47 | obj-$(CONFIG_IEEE80211) += ieee80211/ | 47 | obj-$(CONFIG_IEEE80211) += ieee80211/ |
48 | obj-$(CONFIG_TIPC) += tipc/ | ||
48 | 49 | ||
49 | ifeq ($(CONFIG_NET),y) | 50 | ifeq ($(CONFIG_NET),y) |
50 | obj-$(CONFIG_SYSCTL) += sysctl_net.o | 51 | obj-$(CONFIG_SYSCTL) += sysctl_net.o |
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 9f6e0193ae10..a29c1232c420 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/netfilter.h> | 15 | #include <linux/netfilter.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/ip.h> | 17 | #include <linux/ip.h> |
18 | #include <linux/in.h> | ||
18 | #include <linux/if_arp.h> | 19 | #include <linux/if_arp.h> |
19 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
20 | 21 | ||
diff --git a/net/core/filter.c b/net/core/filter.c index 9eb9d0017a01..a52665f75224 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -287,7 +287,9 @@ load_b: | |||
287 | * no references or jumps that are out of range, no illegal | 287 | * no references or jumps that are out of range, no illegal |
288 | * instructions, and must end with a RET instruction. | 288 | * instructions, and must end with a RET instruction. |
289 | * | 289 | * |
290 | * Returns 0 if the rule set is legal or a negative errno code if not. | 290 | * All jumps are forward as they are not signed. |
291 | * | ||
292 | * Returns 0 if the rule set is legal or -EINVAL if not. | ||
291 | */ | 293 | */ |
292 | int sk_chk_filter(struct sock_filter *filter, int flen) | 294 | int sk_chk_filter(struct sock_filter *filter, int flen) |
293 | { | 295 | { |
@@ -299,7 +301,6 @@ int sk_chk_filter(struct sock_filter *filter, int flen) | |||
299 | 301 | ||
300 | /* check the filter code now */ | 302 | /* check the filter code now */ |
301 | for (pc = 0; pc < flen; pc++) { | 303 | for (pc = 0; pc < flen; pc++) { |
302 | /* all jumps are forward as they are not signed */ | ||
303 | ftest = &filter[pc]; | 304 | ftest = &filter[pc]; |
304 | 305 | ||
305 | /* Only allow valid instructions */ | 306 | /* Only allow valid instructions */ |
@@ -383,11 +384,6 @@ int sk_chk_filter(struct sock_filter *filter, int flen) | |||
383 | } | 384 | } |
384 | } | 385 | } |
385 | 386 | ||
386 | /* | ||
387 | * The program must end with a return. We don't care where they | ||
388 | * jumped within the script (its always forwards) but in the end | ||
389 | * they _will_ hit this. | ||
390 | */ | ||
391 | return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; | 387 | return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; |
392 | } | 388 | } |
393 | 389 | ||
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index a9893ec03e02..db783036e4d8 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -182,6 +182,7 @@ config IP_NF_QUEUE | |||
182 | 182 | ||
183 | config IP_NF_IPTABLES | 183 | config IP_NF_IPTABLES |
184 | tristate "IP tables support (required for filtering/masq/NAT)" | 184 | tristate "IP tables support (required for filtering/masq/NAT)" |
185 | depends on NETFILTER_XTABLES | ||
185 | help | 186 | help |
186 | iptables is a general, extensible packet identification framework. | 187 | iptables is a general, extensible packet identification framework. |
187 | The packet filtering and full NAT (masquerading, port forwarding, | 188 | The packet filtering and full NAT (masquerading, port forwarding, |
@@ -191,16 +192,6 @@ config IP_NF_IPTABLES | |||
191 | To compile it as a module, choose M here. If unsure, say N. | 192 | To compile it as a module, choose M here. If unsure, say N. |
192 | 193 | ||
193 | # The matches. | 194 | # The matches. |
194 | config IP_NF_MATCH_LIMIT | ||
195 | tristate "limit match support" | ||
196 | depends on IP_NF_IPTABLES | ||
197 | help | ||
198 | limit matching allows you to control the rate at which a rule can be | ||
199 | matched: mainly useful in combination with the LOG target ("LOG | ||
200 | target support", below) and to avoid some Denial of Service attacks. | ||
201 | |||
202 | To compile it as a module, choose M here. If unsure, say N. | ||
203 | |||
204 | config IP_NF_MATCH_IPRANGE | 195 | config IP_NF_MATCH_IPRANGE |
205 | tristate "IP range match support" | 196 | tristate "IP range match support" |
206 | depends on IP_NF_IPTABLES | 197 | depends on IP_NF_IPTABLES |
@@ -210,37 +201,6 @@ config IP_NF_MATCH_IPRANGE | |||
210 | 201 | ||
211 | To compile it as a module, choose M here. If unsure, say N. | 202 | To compile it as a module, choose M here. If unsure, say N. |
212 | 203 | ||
213 | config IP_NF_MATCH_MAC | ||
214 | tristate "MAC address match support" | ||
215 | depends on IP_NF_IPTABLES | ||
216 | help | ||
217 | MAC matching allows you to match packets based on the source | ||
218 | Ethernet address of the packet. | ||
219 | |||
220 | To compile it as a module, choose M here. If unsure, say N. | ||
221 | |||
222 | config IP_NF_MATCH_PKTTYPE | ||
223 | tristate "Packet type match support" | ||
224 | depends on IP_NF_IPTABLES | ||
225 | help | ||
226 | Packet type matching allows you to match a packet by | ||
227 | its "class", eg. BROADCAST, MULTICAST, ... | ||
228 | |||
229 | Typical usage: | ||
230 | iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG | ||
231 | |||
232 | To compile it as a module, choose M here. If unsure, say N. | ||
233 | |||
234 | config IP_NF_MATCH_MARK | ||
235 | tristate "netfilter MARK match support" | ||
236 | depends on IP_NF_IPTABLES | ||
237 | help | ||
238 | Netfilter mark matching allows you to match packets based on the | ||
239 | `nfmark' value in the packet. This can be set by the MARK target | ||
240 | (see below). | ||
241 | |||
242 | To compile it as a module, choose M here. If unsure, say N. | ||
243 | |||
244 | config IP_NF_MATCH_MULTIPORT | 204 | config IP_NF_MATCH_MULTIPORT |
245 | tristate "Multiple port match support" | 205 | tristate "Multiple port match support" |
246 | depends on IP_NF_IPTABLES | 206 | depends on IP_NF_IPTABLES |
@@ -301,15 +261,6 @@ config IP_NF_MATCH_AH_ESP | |||
301 | 261 | ||
302 | To compile it as a module, choose M here. If unsure, say N. | 262 | To compile it as a module, choose M here. If unsure, say N. |
303 | 263 | ||
304 | config IP_NF_MATCH_LENGTH | ||
305 | tristate "LENGTH match support" | ||
306 | depends on IP_NF_IPTABLES | ||
307 | help | ||
308 | This option allows you to match the length of a packet against a | ||
309 | specific value or range of values. | ||
310 | |||
311 | To compile it as a module, choose M here. If unsure, say N. | ||
312 | |||
313 | config IP_NF_MATCH_TTL | 264 | config IP_NF_MATCH_TTL |
314 | tristate "TTL match support" | 265 | tristate "TTL match support" |
315 | depends on IP_NF_IPTABLES | 266 | depends on IP_NF_IPTABLES |
@@ -319,50 +270,6 @@ config IP_NF_MATCH_TTL | |||
319 | 270 | ||
320 | To compile it as a module, choose M here. If unsure, say N. | 271 | To compile it as a module, choose M here. If unsure, say N. |
321 | 272 | ||
322 | config IP_NF_MATCH_TCPMSS | ||
323 | tristate "tcpmss match support" | ||
324 | depends on IP_NF_IPTABLES | ||
325 | help | ||
326 | This option adds a `tcpmss' match, which allows you to examine the | ||
327 | MSS value of TCP SYN packets, which control the maximum packet size | ||
328 | for that connection. | ||
329 | |||
330 | To compile it as a module, choose M here. If unsure, say N. | ||
331 | |||
332 | config IP_NF_MATCH_HELPER | ||
333 | tristate "Helper match support" | ||
334 | depends on IP_NF_IPTABLES | ||
335 | depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 | ||
336 | help | ||
337 | Helper matching allows you to match packets in dynamic connections | ||
338 | tracked by a conntrack-helper, ie. ip_conntrack_ftp | ||
339 | |||
340 | To compile it as a module, choose M here. If unsure, say Y. | ||
341 | |||
342 | config IP_NF_MATCH_STATE | ||
343 | tristate "Connection state match support" | ||
344 | depends on IP_NF_IPTABLES | ||
345 | depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 | ||
346 | help | ||
347 | Connection state matching allows you to match packets based on their | ||
348 | relationship to a tracked connection (ie. previous packets). This | ||
349 | is a powerful tool for packet classification. | ||
350 | |||
351 | To compile it as a module, choose M here. If unsure, say N. | ||
352 | |||
353 | config IP_NF_MATCH_CONNTRACK | ||
354 | tristate "Connection tracking match support" | ||
355 | depends on IP_NF_IPTABLES | ||
356 | depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 | ||
357 | help | ||
358 | This is a general conntrack match module, a superset of the state match. | ||
359 | |||
360 | It allows matching on additional conntrack information, which is | ||
361 | useful in complex configurations, such as NAT gateways with multiple | ||
362 | internet links or tunnels. | ||
363 | |||
364 | To compile it as a module, choose M here. If unsure, say N. | ||
365 | |||
366 | config IP_NF_MATCH_OWNER | 273 | config IP_NF_MATCH_OWNER |
367 | tristate "Owner match support" | 274 | tristate "Owner match support" |
368 | depends on IP_NF_IPTABLES | 275 | depends on IP_NF_IPTABLES |
@@ -372,15 +279,6 @@ config IP_NF_MATCH_OWNER | |||
372 | 279 | ||
373 | To compile it as a module, choose M here. If unsure, say N. | 280 | To compile it as a module, choose M here. If unsure, say N. |
374 | 281 | ||
375 | config IP_NF_MATCH_PHYSDEV | ||
376 | tristate "Physdev match support" | ||
377 | depends on IP_NF_IPTABLES && BRIDGE_NETFILTER | ||
378 | help | ||
379 | Physdev packet matching matches against the physical bridge ports | ||
380 | the IP packet arrived on or will leave by. | ||
381 | |||
382 | To compile it as a module, choose M here. If unsure, say N. | ||
383 | |||
384 | config IP_NF_MATCH_ADDRTYPE | 282 | config IP_NF_MATCH_ADDRTYPE |
385 | tristate 'address type match support' | 283 | tristate 'address type match support' |
386 | depends on IP_NF_IPTABLES | 284 | depends on IP_NF_IPTABLES |
@@ -391,75 +289,6 @@ config IP_NF_MATCH_ADDRTYPE | |||
391 | If you want to compile it as a module, say M here and read | 289 | If you want to compile it as a module, say M here and read |
392 | <file:Documentation/modules.txt>. If unsure, say `N'. | 290 | <file:Documentation/modules.txt>. If unsure, say `N'. |
393 | 291 | ||
394 | config IP_NF_MATCH_REALM | ||
395 | tristate 'realm match support' | ||
396 | depends on IP_NF_IPTABLES | ||
397 | select NET_CLS_ROUTE | ||
398 | help | ||
399 | This option adds a `realm' match, which allows you to use the realm | ||
400 | key from the routing subsystem inside iptables. | ||
401 | |||
402 | This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option | ||
403 | in tc world. | ||
404 | |||
405 | If you want to compile it as a module, say M here and read | ||
406 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
407 | |||
408 | config IP_NF_MATCH_SCTP | ||
409 | tristate 'SCTP protocol match support' | ||
410 | depends on IP_NF_IPTABLES | ||
411 | help | ||
412 | With this option enabled, you will be able to use the iptables | ||
413 | `sctp' match in order to match on SCTP source/destination ports | ||
414 | and SCTP chunk types. | ||
415 | |||
416 | If you want to compile it as a module, say M here and read | ||
417 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
418 | |||
419 | config IP_NF_MATCH_DCCP | ||
420 | tristate 'DCCP protocol match support' | ||
421 | depends on IP_NF_IPTABLES | ||
422 | help | ||
423 | With this option enabled, you will be able to use the iptables | ||
424 | `dccp' match in order to match on DCCP source/destination ports | ||
425 | and DCCP flags. | ||
426 | |||
427 | If you want to compile it as a module, say M here and read | ||
428 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
429 | |||
430 | config IP_NF_MATCH_COMMENT | ||
431 | tristate 'comment match support' | ||
432 | depends on IP_NF_IPTABLES | ||
433 | help | ||
434 | This option adds a `comment' dummy-match, which allows you to put | ||
435 | comments in your iptables ruleset. | ||
436 | |||
437 | If you want to compile it as a module, say M here and read | ||
438 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
439 | |||
440 | config IP_NF_MATCH_CONNMARK | ||
441 | tristate 'Connection mark match support' | ||
442 | depends on IP_NF_IPTABLES | ||
443 | depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) | ||
444 | help | ||
445 | This option adds a `connmark' match, which allows you to match the | ||
446 | connection mark value previously set for the session by `CONNMARK'. | ||
447 | |||
448 | If you want to compile it as a module, say M here and read | ||
449 | <file:Documentation/modules.txt>. The module will be called | ||
450 | ipt_connmark.o. If unsure, say `N'. | ||
451 | |||
452 | config IP_NF_MATCH_CONNBYTES | ||
453 | tristate 'Connection byte/packet counter match support' | ||
454 | depends on IP_NF_IPTABLES | ||
455 | depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || (NF_CT_ACCT && NF_CONNTRACK_IPV4) | ||
456 | help | ||
457 | This option adds a `connbytes' match, which allows you to match the | ||
458 | number of bytes and/or packets for each direction within a connection. | ||
459 | |||
460 | If you want to compile it as a module, say M here and read | ||
461 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
462 | |||
463 | config IP_NF_MATCH_HASHLIMIT | 292 | config IP_NF_MATCH_HASHLIMIT |
464 | tristate 'hashlimit match support' | 293 | tristate 'hashlimit match support' |
465 | depends on IP_NF_IPTABLES | 294 | depends on IP_NF_IPTABLES |
@@ -474,19 +303,6 @@ config IP_NF_MATCH_HASHLIMIT | |||
474 | destination IP' or `500pps from any given source IP' with a single | 303 | destination IP' or `500pps from any given source IP' with a single |
475 | IPtables rule. | 304 | IPtables rule. |
476 | 305 | ||
477 | config IP_NF_MATCH_STRING | ||
478 | tristate 'string match support' | ||
479 | depends on IP_NF_IPTABLES | ||
480 | select TEXTSEARCH | ||
481 | select TEXTSEARCH_KMP | ||
482 | select TEXTSEARCH_BM | ||
483 | select TEXTSEARCH_FSM | ||
484 | help | ||
485 | This option adds a `string' match, which allows you to look for | ||
486 | pattern matchings in packets. | ||
487 | |||
488 | To compile it as a module, choose M here. If unsure, say N. | ||
489 | |||
490 | config IP_NF_MATCH_POLICY | 306 | config IP_NF_MATCH_POLICY |
491 | tristate "IPsec policy match support" | 307 | tristate "IPsec policy match support" |
492 | depends on IP_NF_IPTABLES && XFRM | 308 | depends on IP_NF_IPTABLES && XFRM |
@@ -572,17 +388,6 @@ config IP_NF_TARGET_TCPMSS | |||
572 | 388 | ||
573 | To compile it as a module, choose M here. If unsure, say N. | 389 | To compile it as a module, choose M here. If unsure, say N. |
574 | 390 | ||
575 | config IP_NF_TARGET_NFQUEUE | ||
576 | tristate "NFQUEUE Target Support" | ||
577 | depends on IP_NF_IPTABLES | ||
578 | help | ||
579 | This Target replaced the old obsolete QUEUE target. | ||
580 | |||
581 | As opposed to QUEUE, it supports 65535 different queues, | ||
582 | not just one. | ||
583 | |||
584 | To compile it as a module, choose M here. If unsure, say N. | ||
585 | |||
586 | # NAT + specific targets | 391 | # NAT + specific targets |
587 | config IP_NF_NAT | 392 | config IP_NF_NAT |
588 | tristate "Full NAT" | 393 | tristate "Full NAT" |
@@ -735,31 +540,6 @@ config IP_NF_TARGET_DSCP | |||
735 | 540 | ||
736 | To compile it as a module, choose M here. If unsure, say N. | 541 | To compile it as a module, choose M here. If unsure, say N. |
737 | 542 | ||
738 | config IP_NF_TARGET_MARK | ||
739 | tristate "MARK target support" | ||
740 | depends on IP_NF_MANGLE | ||
741 | help | ||
742 | This option adds a `MARK' target, which allows you to create rules | ||
743 | in the `mangle' table which alter the netfilter mark (nfmark) field | ||
744 | associated with the packet prior to routing. This can change | ||
745 | the routing method (see `Use netfilter MARK value as routing | ||
746 | key') and can also be used by other subsystems to change their | ||
747 | behavior. | ||
748 | |||
749 | To compile it as a module, choose M here. If unsure, say N. | ||
750 | |||
751 | config IP_NF_TARGET_CLASSIFY | ||
752 | tristate "CLASSIFY target support" | ||
753 | depends on IP_NF_MANGLE | ||
754 | help | ||
755 | This option adds a `CLASSIFY' target, which enables the user to set | ||
756 | the priority of a packet. Some qdiscs can use this value for | ||
757 | classification, among these are: | ||
758 | |||
759 | atm, cbq, dsmark, pfifo_fast, htb, prio | ||
760 | |||
761 | To compile it as a module, choose M here. If unsure, say N. | ||
762 | |||
763 | config IP_NF_TARGET_TTL | 543 | config IP_NF_TARGET_TTL |
764 | tristate 'TTL target support' | 544 | tristate 'TTL target support' |
765 | depends on IP_NF_MANGLE | 545 | depends on IP_NF_MANGLE |
@@ -774,19 +554,6 @@ config IP_NF_TARGET_TTL | |||
774 | 554 | ||
775 | To compile it as a module, choose M here. If unsure, say N. | 555 | To compile it as a module, choose M here. If unsure, say N. |
776 | 556 | ||
777 | config IP_NF_TARGET_CONNMARK | ||
778 | tristate 'CONNMARK target support' | ||
779 | depends on IP_NF_MANGLE | ||
780 | depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) | ||
781 | help | ||
782 | This option adds a `CONNMARK' target, which allows one to manipulate | ||
783 | the connection mark value. Similar to the MARK target, but | ||
784 | affects the connection mark value rather than the packet mark value. | ||
785 | |||
786 | If you want to compile it as a module, say M here and read | ||
787 | <file:Documentation/modules.txt>. The module will be called | ||
788 | ipt_CONNMARK.o. If unsure, say `N'. | ||
789 | |||
790 | config IP_NF_TARGET_CLUSTERIP | 557 | config IP_NF_TARGET_CLUSTERIP |
791 | tristate "CLUSTERIP target support (EXPERIMENTAL)" | 558 | tristate "CLUSTERIP target support (EXPERIMENTAL)" |
792 | depends on IP_NF_MANGLE && EXPERIMENTAL | 559 | depends on IP_NF_MANGLE && EXPERIMENTAL |
@@ -810,23 +577,10 @@ config IP_NF_RAW | |||
810 | If you want to compile it as a module, say M here and read | 577 | If you want to compile it as a module, say M here and read |
811 | <file:Documentation/modules.txt>. If unsure, say `N'. | 578 | <file:Documentation/modules.txt>. If unsure, say `N'. |
812 | 579 | ||
813 | config IP_NF_TARGET_NOTRACK | ||
814 | tristate 'NOTRACK target support' | ||
815 | depends on IP_NF_RAW | ||
816 | depends on IP_NF_CONNTRACK || NF_CONNTRACK_IPV4 | ||
817 | help | ||
818 | The NOTRACK target allows a select rule to specify | ||
819 | which packets *not* to enter the conntrack/NAT | ||
820 | subsystem with all the consequences (no ICMP error tracking, | ||
821 | no protocol helpers for the selected packets). | ||
822 | |||
823 | If you want to compile it as a module, say M here and read | ||
824 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
825 | |||
826 | |||
827 | # ARP tables | 580 | # ARP tables |
828 | config IP_NF_ARPTABLES | 581 | config IP_NF_ARPTABLES |
829 | tristate "ARP tables support" | 582 | tristate "ARP tables support" |
583 | depends on NETFILTER_XTABLES | ||
830 | help | 584 | help |
831 | arptables is a general, extensible packet identification framework. | 585 | arptables is a general, extensible packet identification framework. |
832 | The ARP packet filtering and mangling (manipulation)subsystems | 586 | The ARP packet filtering and mangling (manipulation)subsystems |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 549b01a648b3..bcefe64b9317 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -47,14 +47,8 @@ obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o | |||
47 | 47 | ||
48 | # matches | 48 | # matches |
49 | obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o | 49 | obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o |
50 | obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o | ||
51 | obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o | 50 | obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o |
52 | obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o | ||
53 | obj-$(CONFIG_IP_NF_MATCH_DCCP) += ipt_dccp.o | ||
54 | obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o | ||
55 | obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o | ||
56 | obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o | 51 | obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o |
57 | obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o | ||
58 | obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o | 52 | obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o |
59 | obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o | 53 | obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o |
60 | obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o | 54 | obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o |
@@ -62,40 +56,25 @@ obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o | |||
62 | obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o | 56 | obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o |
63 | obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o | 57 | obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o |
64 | obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o | 58 | obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o |
65 | obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o | ||
66 | obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o | 59 | obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o |
67 | obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o | ||
68 | obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o | ||
69 | obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o | ||
70 | obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o | ||
71 | obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o | ||
72 | obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o | ||
73 | obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o | 60 | obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o |
74 | obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o | ||
75 | obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o | 61 | obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o |
76 | obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o | ||
77 | obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o | ||
78 | 62 | ||
79 | # targets | 63 | # targets |
80 | obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o | 64 | obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o |
81 | obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o | 65 | obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o |
82 | obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o | 66 | obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o |
83 | obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o | 67 | obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o |
84 | obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o | ||
85 | obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o | 68 | obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o |
86 | obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o | 69 | obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o |
87 | obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o | 70 | obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o |
88 | obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o | 71 | obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o |
89 | obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o | ||
90 | obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o | 72 | obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o |
91 | obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o | 73 | obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o |
92 | obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o | ||
93 | obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o | 74 | obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o |
94 | obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o | 75 | obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o |
95 | obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o | ||
96 | obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o | 76 | obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o |
97 | obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o | 77 | obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o |
98 | obj-$(CONFIG_IP_NF_TARGET_NFQUEUE) += ipt_NFQUEUE.o | ||
99 | 78 | ||
100 | # generic ARP tables | 79 | # generic ARP tables |
101 | obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o | 80 | obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index b6d5284c8020..afe3d8f8177d 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
25 | #include <asm/semaphore.h> | 25 | #include <asm/semaphore.h> |
26 | 26 | ||
27 | #include <linux/netfilter/x_tables.h> | ||
27 | #include <linux/netfilter_arp/arp_tables.h> | 28 | #include <linux/netfilter_arp/arp_tables.h> |
28 | 29 | ||
29 | MODULE_LICENSE("GPL"); | 30 | MODULE_LICENSE("GPL"); |
@@ -55,28 +56,9 @@ do { \ | |||
55 | #else | 56 | #else |
56 | #define ARP_NF_ASSERT(x) | 57 | #define ARP_NF_ASSERT(x) |
57 | #endif | 58 | #endif |
58 | #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) | ||
59 | 59 | ||
60 | static DECLARE_MUTEX(arpt_mutex); | ||
61 | |||
62 | #define ASSERT_READ_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0) | ||
63 | #define ASSERT_WRITE_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0) | ||
64 | #include <linux/netfilter_ipv4/listhelp.h> | 60 | #include <linux/netfilter_ipv4/listhelp.h> |
65 | 61 | ||
66 | struct arpt_table_info { | ||
67 | unsigned int size; | ||
68 | unsigned int number; | ||
69 | unsigned int initial_entries; | ||
70 | unsigned int hook_entry[NF_ARP_NUMHOOKS]; | ||
71 | unsigned int underflow[NF_ARP_NUMHOOKS]; | ||
72 | void *entries[NR_CPUS]; | ||
73 | }; | ||
74 | |||
75 | static LIST_HEAD(arpt_target); | ||
76 | static LIST_HEAD(arpt_tables); | ||
77 | #define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) | ||
78 | #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) | ||
79 | |||
80 | static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, | 62 | static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, |
81 | char *hdr_addr, int len) | 63 | char *hdr_addr, int len) |
82 | { | 64 | { |
@@ -223,9 +205,9 @@ static inline int arp_checkentry(const struct arpt_arp *arp) | |||
223 | } | 205 | } |
224 | 206 | ||
225 | static unsigned int arpt_error(struct sk_buff **pskb, | 207 | static unsigned int arpt_error(struct sk_buff **pskb, |
226 | unsigned int hooknum, | ||
227 | const struct net_device *in, | 208 | const struct net_device *in, |
228 | const struct net_device *out, | 209 | const struct net_device *out, |
210 | unsigned int hooknum, | ||
229 | const void *targinfo, | 211 | const void *targinfo, |
230 | void *userinfo) | 212 | void *userinfo) |
231 | { | 213 | { |
@@ -254,6 +236,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
254 | struct arpt_entry *e, *back; | 236 | struct arpt_entry *e, *back; |
255 | const char *indev, *outdev; | 237 | const char *indev, *outdev; |
256 | void *table_base; | 238 | void *table_base; |
239 | struct xt_table_info *private = table->private; | ||
257 | 240 | ||
258 | /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ | 241 | /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ |
259 | if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + | 242 | if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + |
@@ -265,9 +248,9 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
265 | outdev = out ? out->name : nulldevname; | 248 | outdev = out ? out->name : nulldevname; |
266 | 249 | ||
267 | read_lock_bh(&table->lock); | 250 | read_lock_bh(&table->lock); |
268 | table_base = (void *)table->private->entries[smp_processor_id()]; | 251 | table_base = (void *)private->entries[smp_processor_id()]; |
269 | e = get_entry(table_base, table->private->hook_entry[hook]); | 252 | e = get_entry(table_base, private->hook_entry[hook]); |
270 | back = get_entry(table_base, table->private->underflow[hook]); | 253 | back = get_entry(table_base, private->underflow[hook]); |
271 | 254 | ||
272 | arp = (*pskb)->nh.arph; | 255 | arp = (*pskb)->nh.arph; |
273 | do { | 256 | do { |
@@ -315,8 +298,8 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
315 | * abs. verdicts | 298 | * abs. verdicts |
316 | */ | 299 | */ |
317 | verdict = t->u.kernel.target->target(pskb, | 300 | verdict = t->u.kernel.target->target(pskb, |
318 | hook, | ||
319 | in, out, | 301 | in, out, |
302 | hook, | ||
320 | t->data, | 303 | t->data, |
321 | userdata); | 304 | userdata); |
322 | 305 | ||
@@ -341,106 +324,6 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
341 | return verdict; | 324 | return verdict; |
342 | } | 325 | } |
343 | 326 | ||
344 | /* | ||
345 | * These are weird, but module loading must not be done with mutex | ||
346 | * held (since they will register), and we have to have a single | ||
347 | * function to use try_then_request_module(). | ||
348 | */ | ||
349 | |||
350 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ | ||
351 | static inline struct arpt_table *find_table_lock(const char *name) | ||
352 | { | ||
353 | struct arpt_table *t; | ||
354 | |||
355 | if (down_interruptible(&arpt_mutex) != 0) | ||
356 | return ERR_PTR(-EINTR); | ||
357 | |||
358 | list_for_each_entry(t, &arpt_tables, list) | ||
359 | if (strcmp(t->name, name) == 0 && try_module_get(t->me)) | ||
360 | return t; | ||
361 | up(&arpt_mutex); | ||
362 | return NULL; | ||
363 | } | ||
364 | |||
365 | |||
366 | /* Find target, grabs ref. Returns ERR_PTR() on error. */ | ||
367 | static inline struct arpt_target *find_target(const char *name, u8 revision) | ||
368 | { | ||
369 | struct arpt_target *t; | ||
370 | int err = 0; | ||
371 | |||
372 | if (down_interruptible(&arpt_mutex) != 0) | ||
373 | return ERR_PTR(-EINTR); | ||
374 | |||
375 | list_for_each_entry(t, &arpt_target, list) { | ||
376 | if (strcmp(t->name, name) == 0) { | ||
377 | if (t->revision == revision) { | ||
378 | if (try_module_get(t->me)) { | ||
379 | up(&arpt_mutex); | ||
380 | return t; | ||
381 | } | ||
382 | } else | ||
383 | err = -EPROTOTYPE; /* Found something. */ | ||
384 | } | ||
385 | } | ||
386 | up(&arpt_mutex); | ||
387 | return ERR_PTR(err); | ||
388 | } | ||
389 | |||
390 | struct arpt_target *arpt_find_target(const char *name, u8 revision) | ||
391 | { | ||
392 | struct arpt_target *target; | ||
393 | |||
394 | target = try_then_request_module(find_target(name, revision), | ||
395 | "arpt_%s", name); | ||
396 | if (IS_ERR(target) || !target) | ||
397 | return NULL; | ||
398 | return target; | ||
399 | } | ||
400 | |||
401 | static int target_revfn(const char *name, u8 revision, int *bestp) | ||
402 | { | ||
403 | struct arpt_target *t; | ||
404 | int have_rev = 0; | ||
405 | |||
406 | list_for_each_entry(t, &arpt_target, list) { | ||
407 | if (strcmp(t->name, name) == 0) { | ||
408 | if (t->revision > *bestp) | ||
409 | *bestp = t->revision; | ||
410 | if (t->revision == revision) | ||
411 | have_rev =1; | ||
412 | } | ||
413 | } | ||
414 | return have_rev; | ||
415 | } | ||
416 | |||
417 | /* Returns true or false (if no such extension at all) */ | ||
418 | static inline int find_revision(const char *name, u8 revision, | ||
419 | int (*revfn)(const char *, u8, int *), | ||
420 | int *err) | ||
421 | { | ||
422 | int have_rev, best = -1; | ||
423 | |||
424 | if (down_interruptible(&arpt_mutex) != 0) { | ||
425 | *err = -EINTR; | ||
426 | return 1; | ||
427 | } | ||
428 | have_rev = revfn(name, revision, &best); | ||
429 | up(&arpt_mutex); | ||
430 | |||
431 | /* Nothing at all? Return 0 to try loading module. */ | ||
432 | if (best == -1) { | ||
433 | *err = -ENOENT; | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | *err = best; | ||
438 | if (!have_rev) | ||
439 | *err = -EPROTONOSUPPORT; | ||
440 | return 1; | ||
441 | } | ||
442 | |||
443 | |||
444 | /* All zeroes == unconditional rule. */ | 327 | /* All zeroes == unconditional rule. */ |
445 | static inline int unconditional(const struct arpt_arp *arp) | 328 | static inline int unconditional(const struct arpt_arp *arp) |
446 | { | 329 | { |
@@ -456,7 +339,7 @@ static inline int unconditional(const struct arpt_arp *arp) | |||
456 | /* Figures out from what hook each rule can be called: returns 0 if | 339 | /* Figures out from what hook each rule can be called: returns 0 if |
457 | * there are loops. Puts hook bitmask in comefrom. | 340 | * there are loops. Puts hook bitmask in comefrom. |
458 | */ | 341 | */ |
459 | static int mark_source_chains(struct arpt_table_info *newinfo, | 342 | static int mark_source_chains(struct xt_table_info *newinfo, |
460 | unsigned int valid_hooks, void *entry0) | 343 | unsigned int valid_hooks, void *entry0) |
461 | { | 344 | { |
462 | unsigned int hook; | 345 | unsigned int hook; |
@@ -587,8 +470,8 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i | |||
587 | } | 470 | } |
588 | 471 | ||
589 | t = arpt_get_target(e); | 472 | t = arpt_get_target(e); |
590 | target = try_then_request_module(find_target(t->u.user.name, | 473 | target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name, |
591 | t->u.user.revision), | 474 | t->u.user.revision), |
592 | "arpt_%s", t->u.user.name); | 475 | "arpt_%s", t->u.user.name); |
593 | if (IS_ERR(target) || !target) { | 476 | if (IS_ERR(target) || !target) { |
594 | duprintf("check_entry: `%s' not found\n", t->u.user.name); | 477 | duprintf("check_entry: `%s' not found\n", t->u.user.name); |
@@ -622,7 +505,7 @@ out: | |||
622 | } | 505 | } |
623 | 506 | ||
624 | static inline int check_entry_size_and_hooks(struct arpt_entry *e, | 507 | static inline int check_entry_size_and_hooks(struct arpt_entry *e, |
625 | struct arpt_table_info *newinfo, | 508 | struct xt_table_info *newinfo, |
626 | unsigned char *base, | 509 | unsigned char *base, |
627 | unsigned char *limit, | 510 | unsigned char *limit, |
628 | const unsigned int *hook_entries, | 511 | const unsigned int *hook_entries, |
@@ -656,7 +539,7 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e, | |||
656 | < 0 (not ARPT_RETURN). --RR */ | 539 | < 0 (not ARPT_RETURN). --RR */ |
657 | 540 | ||
658 | /* Clear counters and comefrom */ | 541 | /* Clear counters and comefrom */ |
659 | e->counters = ((struct arpt_counters) { 0, 0 }); | 542 | e->counters = ((struct xt_counters) { 0, 0 }); |
660 | e->comefrom = 0; | 543 | e->comefrom = 0; |
661 | 544 | ||
662 | (*i)++; | 545 | (*i)++; |
@@ -683,7 +566,7 @@ static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i) | |||
683 | */ | 566 | */ |
684 | static int translate_table(const char *name, | 567 | static int translate_table(const char *name, |
685 | unsigned int valid_hooks, | 568 | unsigned int valid_hooks, |
686 | struct arpt_table_info *newinfo, | 569 | struct xt_table_info *newinfo, |
687 | void *entry0, | 570 | void *entry0, |
688 | unsigned int size, | 571 | unsigned int size, |
689 | unsigned int number, | 572 | unsigned int number, |
@@ -764,34 +647,9 @@ static int translate_table(const char *name, | |||
764 | return ret; | 647 | return ret; |
765 | } | 648 | } |
766 | 649 | ||
767 | static struct arpt_table_info *replace_table(struct arpt_table *table, | ||
768 | unsigned int num_counters, | ||
769 | struct arpt_table_info *newinfo, | ||
770 | int *error) | ||
771 | { | ||
772 | struct arpt_table_info *oldinfo; | ||
773 | |||
774 | /* Do the substitution. */ | ||
775 | write_lock_bh(&table->lock); | ||
776 | /* Check inside lock: is the old number correct? */ | ||
777 | if (num_counters != table->private->number) { | ||
778 | duprintf("num_counters != table->private->number (%u/%u)\n", | ||
779 | num_counters, table->private->number); | ||
780 | write_unlock_bh(&table->lock); | ||
781 | *error = -EAGAIN; | ||
782 | return NULL; | ||
783 | } | ||
784 | oldinfo = table->private; | ||
785 | table->private = newinfo; | ||
786 | newinfo->initial_entries = oldinfo->initial_entries; | ||
787 | write_unlock_bh(&table->lock); | ||
788 | |||
789 | return oldinfo; | ||
790 | } | ||
791 | |||
792 | /* Gets counters. */ | 650 | /* Gets counters. */ |
793 | static inline int add_entry_to_counter(const struct arpt_entry *e, | 651 | static inline int add_entry_to_counter(const struct arpt_entry *e, |
794 | struct arpt_counters total[], | 652 | struct xt_counters total[], |
795 | unsigned int *i) | 653 | unsigned int *i) |
796 | { | 654 | { |
797 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); | 655 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); |
@@ -801,7 +659,7 @@ static inline int add_entry_to_counter(const struct arpt_entry *e, | |||
801 | } | 659 | } |
802 | 660 | ||
803 | static inline int set_entry_to_counter(const struct arpt_entry *e, | 661 | static inline int set_entry_to_counter(const struct arpt_entry *e, |
804 | struct arpt_counters total[], | 662 | struct xt_counters total[], |
805 | unsigned int *i) | 663 | unsigned int *i) |
806 | { | 664 | { |
807 | SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); | 665 | SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); |
@@ -810,8 +668,8 @@ static inline int set_entry_to_counter(const struct arpt_entry *e, | |||
810 | return 0; | 668 | return 0; |
811 | } | 669 | } |
812 | 670 | ||
813 | static void get_counters(const struct arpt_table_info *t, | 671 | static void get_counters(const struct xt_table_info *t, |
814 | struct arpt_counters counters[]) | 672 | struct xt_counters counters[]) |
815 | { | 673 | { |
816 | unsigned int cpu; | 674 | unsigned int cpu; |
817 | unsigned int i; | 675 | unsigned int i; |
@@ -849,7 +707,8 @@ static int copy_entries_to_user(unsigned int total_size, | |||
849 | { | 707 | { |
850 | unsigned int off, num, countersize; | 708 | unsigned int off, num, countersize; |
851 | struct arpt_entry *e; | 709 | struct arpt_entry *e; |
852 | struct arpt_counters *counters; | 710 | struct xt_counters *counters; |
711 | struct xt_table_info *private = table->private; | ||
853 | int ret = 0; | 712 | int ret = 0; |
854 | void *loc_cpu_entry; | 713 | void *loc_cpu_entry; |
855 | 714 | ||
@@ -857,18 +716,18 @@ static int copy_entries_to_user(unsigned int total_size, | |||
857 | * (other than comefrom, which userspace doesn't care | 716 | * (other than comefrom, which userspace doesn't care |
858 | * about). | 717 | * about). |
859 | */ | 718 | */ |
860 | countersize = sizeof(struct arpt_counters) * table->private->number; | 719 | countersize = sizeof(struct xt_counters) * private->number; |
861 | counters = vmalloc(countersize); | 720 | counters = vmalloc_node(countersize, numa_node_id()); |
862 | 721 | ||
863 | if (counters == NULL) | 722 | if (counters == NULL) |
864 | return -ENOMEM; | 723 | return -ENOMEM; |
865 | 724 | ||
866 | /* First, sum counters... */ | 725 | /* First, sum counters... */ |
867 | write_lock_bh(&table->lock); | 726 | write_lock_bh(&table->lock); |
868 | get_counters(table->private, counters); | 727 | get_counters(private, counters); |
869 | write_unlock_bh(&table->lock); | 728 | write_unlock_bh(&table->lock); |
870 | 729 | ||
871 | loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; | 730 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
872 | /* ... then copy entire thing ... */ | 731 | /* ... then copy entire thing ... */ |
873 | if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { | 732 | if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { |
874 | ret = -EFAULT; | 733 | ret = -EFAULT; |
@@ -911,75 +770,34 @@ static int get_entries(const struct arpt_get_entries *entries, | |||
911 | int ret; | 770 | int ret; |
912 | struct arpt_table *t; | 771 | struct arpt_table *t; |
913 | 772 | ||
914 | t = find_table_lock(entries->name); | 773 | t = xt_find_table_lock(NF_ARP, entries->name); |
915 | if (t || !IS_ERR(t)) { | 774 | if (t || !IS_ERR(t)) { |
775 | struct xt_table_info *private = t->private; | ||
916 | duprintf("t->private->number = %u\n", | 776 | duprintf("t->private->number = %u\n", |
917 | t->private->number); | 777 | private->number); |
918 | if (entries->size == t->private->size) | 778 | if (entries->size == private->size) |
919 | ret = copy_entries_to_user(t->private->size, | 779 | ret = copy_entries_to_user(private->size, |
920 | t, uptr->entrytable); | 780 | t, uptr->entrytable); |
921 | else { | 781 | else { |
922 | duprintf("get_entries: I've got %u not %u!\n", | 782 | duprintf("get_entries: I've got %u not %u!\n", |
923 | t->private->size, | 783 | private->size, entries->size); |
924 | entries->size); | ||
925 | ret = -EINVAL; | 784 | ret = -EINVAL; |
926 | } | 785 | } |
927 | module_put(t->me); | 786 | module_put(t->me); |
928 | up(&arpt_mutex); | 787 | xt_table_unlock(t); |
929 | } else | 788 | } else |
930 | ret = t ? PTR_ERR(t) : -ENOENT; | 789 | ret = t ? PTR_ERR(t) : -ENOENT; |
931 | 790 | ||
932 | return ret; | 791 | return ret; |
933 | } | 792 | } |
934 | 793 | ||
935 | static void free_table_info(struct arpt_table_info *info) | ||
936 | { | ||
937 | int cpu; | ||
938 | for_each_cpu(cpu) { | ||
939 | if (info->size <= PAGE_SIZE) | ||
940 | kfree(info->entries[cpu]); | ||
941 | else | ||
942 | vfree(info->entries[cpu]); | ||
943 | } | ||
944 | kfree(info); | ||
945 | } | ||
946 | |||
947 | static struct arpt_table_info *alloc_table_info(unsigned int size) | ||
948 | { | ||
949 | struct arpt_table_info *newinfo; | ||
950 | int cpu; | ||
951 | |||
952 | newinfo = kzalloc(sizeof(struct arpt_table_info), GFP_KERNEL); | ||
953 | if (!newinfo) | ||
954 | return NULL; | ||
955 | |||
956 | newinfo->size = size; | ||
957 | |||
958 | for_each_cpu(cpu) { | ||
959 | if (size <= PAGE_SIZE) | ||
960 | newinfo->entries[cpu] = kmalloc_node(size, | ||
961 | GFP_KERNEL, | ||
962 | cpu_to_node(cpu)); | ||
963 | else | ||
964 | newinfo->entries[cpu] = vmalloc_node(size, | ||
965 | cpu_to_node(cpu)); | ||
966 | |||
967 | if (newinfo->entries[cpu] == NULL) { | ||
968 | free_table_info(newinfo); | ||
969 | return NULL; | ||
970 | } | ||
971 | } | ||
972 | |||
973 | return newinfo; | ||
974 | } | ||
975 | |||
976 | static int do_replace(void __user *user, unsigned int len) | 794 | static int do_replace(void __user *user, unsigned int len) |
977 | { | 795 | { |
978 | int ret; | 796 | int ret; |
979 | struct arpt_replace tmp; | 797 | struct arpt_replace tmp; |
980 | struct arpt_table *t; | 798 | struct arpt_table *t; |
981 | struct arpt_table_info *newinfo, *oldinfo; | 799 | struct xt_table_info *newinfo, *oldinfo; |
982 | struct arpt_counters *counters; | 800 | struct xt_counters *counters; |
983 | void *loc_cpu_entry, *loc_cpu_old_entry; | 801 | void *loc_cpu_entry, *loc_cpu_old_entry; |
984 | 802 | ||
985 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 803 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
@@ -989,11 +807,7 @@ static int do_replace(void __user *user, unsigned int len) | |||
989 | if (len != sizeof(tmp) + tmp.size) | 807 | if (len != sizeof(tmp) + tmp.size) |
990 | return -ENOPROTOOPT; | 808 | return -ENOPROTOOPT; |
991 | 809 | ||
992 | /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ | 810 | newinfo = xt_alloc_table_info(tmp.size); |
993 | if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) | ||
994 | return -ENOMEM; | ||
995 | |||
996 | newinfo = alloc_table_info(tmp.size); | ||
997 | if (!newinfo) | 811 | if (!newinfo) |
998 | return -ENOMEM; | 812 | return -ENOMEM; |
999 | 813 | ||
@@ -1005,7 +819,7 @@ static int do_replace(void __user *user, unsigned int len) | |||
1005 | goto free_newinfo; | 819 | goto free_newinfo; |
1006 | } | 820 | } |
1007 | 821 | ||
1008 | counters = vmalloc(tmp.num_counters * sizeof(struct arpt_counters)); | 822 | counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); |
1009 | if (!counters) { | 823 | if (!counters) { |
1010 | ret = -ENOMEM; | 824 | ret = -ENOMEM; |
1011 | goto free_newinfo; | 825 | goto free_newinfo; |
@@ -1019,7 +833,7 @@ static int do_replace(void __user *user, unsigned int len) | |||
1019 | 833 | ||
1020 | duprintf("arp_tables: Translated table\n"); | 834 | duprintf("arp_tables: Translated table\n"); |
1021 | 835 | ||
1022 | t = try_then_request_module(find_table_lock(tmp.name), | 836 | t = try_then_request_module(xt_find_table_lock(NF_ARP, tmp.name), |
1023 | "arptable_%s", tmp.name); | 837 | "arptable_%s", tmp.name); |
1024 | if (!t || IS_ERR(t)) { | 838 | if (!t || IS_ERR(t)) { |
1025 | ret = t ? PTR_ERR(t) : -ENOENT; | 839 | ret = t ? PTR_ERR(t) : -ENOENT; |
@@ -1034,7 +848,7 @@ static int do_replace(void __user *user, unsigned int len) | |||
1034 | goto put_module; | 848 | goto put_module; |
1035 | } | 849 | } |
1036 | 850 | ||
1037 | oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); | 851 | oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); |
1038 | if (!oldinfo) | 852 | if (!oldinfo) |
1039 | goto put_module; | 853 | goto put_module; |
1040 | 854 | ||
@@ -1054,23 +868,23 @@ static int do_replace(void __user *user, unsigned int len) | |||
1054 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | 868 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; |
1055 | ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); | 869 | ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); |
1056 | 870 | ||
1057 | free_table_info(oldinfo); | 871 | xt_free_table_info(oldinfo); |
1058 | if (copy_to_user(tmp.counters, counters, | 872 | if (copy_to_user(tmp.counters, counters, |
1059 | sizeof(struct arpt_counters) * tmp.num_counters) != 0) | 873 | sizeof(struct xt_counters) * tmp.num_counters) != 0) |
1060 | ret = -EFAULT; | 874 | ret = -EFAULT; |
1061 | vfree(counters); | 875 | vfree(counters); |
1062 | up(&arpt_mutex); | 876 | xt_table_unlock(t); |
1063 | return ret; | 877 | return ret; |
1064 | 878 | ||
1065 | put_module: | 879 | put_module: |
1066 | module_put(t->me); | 880 | module_put(t->me); |
1067 | up(&arpt_mutex); | 881 | xt_table_unlock(t); |
1068 | free_newinfo_counters_untrans: | 882 | free_newinfo_counters_untrans: |
1069 | ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); | 883 | ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); |
1070 | free_newinfo_counters: | 884 | free_newinfo_counters: |
1071 | vfree(counters); | 885 | vfree(counters); |
1072 | free_newinfo: | 886 | free_newinfo: |
1073 | free_table_info(newinfo); | 887 | xt_free_table_info(newinfo); |
1074 | return ret; | 888 | return ret; |
1075 | } | 889 | } |
1076 | 890 | ||
@@ -1078,7 +892,7 @@ static int do_replace(void __user *user, unsigned int len) | |||
1078 | * and everything is OK. | 892 | * and everything is OK. |
1079 | */ | 893 | */ |
1080 | static inline int add_counter_to_entry(struct arpt_entry *e, | 894 | static inline int add_counter_to_entry(struct arpt_entry *e, |
1081 | const struct arpt_counters addme[], | 895 | const struct xt_counters addme[], |
1082 | unsigned int *i) | 896 | unsigned int *i) |
1083 | { | 897 | { |
1084 | 898 | ||
@@ -1091,15 +905,16 @@ static inline int add_counter_to_entry(struct arpt_entry *e, | |||
1091 | static int do_add_counters(void __user *user, unsigned int len) | 905 | static int do_add_counters(void __user *user, unsigned int len) |
1092 | { | 906 | { |
1093 | unsigned int i; | 907 | unsigned int i; |
1094 | struct arpt_counters_info tmp, *paddc; | 908 | struct xt_counters_info tmp, *paddc; |
1095 | struct arpt_table *t; | 909 | struct arpt_table *t; |
910 | struct xt_table_info *private; | ||
1096 | int ret = 0; | 911 | int ret = 0; |
1097 | void *loc_cpu_entry; | 912 | void *loc_cpu_entry; |
1098 | 913 | ||
1099 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 914 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
1100 | return -EFAULT; | 915 | return -EFAULT; |
1101 | 916 | ||
1102 | if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct arpt_counters)) | 917 | if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) |
1103 | return -EINVAL; | 918 | return -EINVAL; |
1104 | 919 | ||
1105 | paddc = vmalloc(len); | 920 | paddc = vmalloc(len); |
@@ -1111,29 +926,30 @@ static int do_add_counters(void __user *user, unsigned int len) | |||
1111 | goto free; | 926 | goto free; |
1112 | } | 927 | } |
1113 | 928 | ||
1114 | t = find_table_lock(tmp.name); | 929 | t = xt_find_table_lock(NF_ARP, tmp.name); |
1115 | if (!t || IS_ERR(t)) { | 930 | if (!t || IS_ERR(t)) { |
1116 | ret = t ? PTR_ERR(t) : -ENOENT; | 931 | ret = t ? PTR_ERR(t) : -ENOENT; |
1117 | goto free; | 932 | goto free; |
1118 | } | 933 | } |
1119 | 934 | ||
1120 | write_lock_bh(&t->lock); | 935 | write_lock_bh(&t->lock); |
1121 | if (t->private->number != paddc->num_counters) { | 936 | private = t->private; |
937 | if (private->number != paddc->num_counters) { | ||
1122 | ret = -EINVAL; | 938 | ret = -EINVAL; |
1123 | goto unlock_up_free; | 939 | goto unlock_up_free; |
1124 | } | 940 | } |
1125 | 941 | ||
1126 | i = 0; | 942 | i = 0; |
1127 | /* Choose the copy that is on our node */ | 943 | /* Choose the copy that is on our node */ |
1128 | loc_cpu_entry = t->private->entries[smp_processor_id()]; | 944 | loc_cpu_entry = private->entries[smp_processor_id()]; |
1129 | ARPT_ENTRY_ITERATE(loc_cpu_entry, | 945 | ARPT_ENTRY_ITERATE(loc_cpu_entry, |
1130 | t->private->size, | 946 | private->size, |
1131 | add_counter_to_entry, | 947 | add_counter_to_entry, |
1132 | paddc->counters, | 948 | paddc->counters, |
1133 | &i); | 949 | &i); |
1134 | unlock_up_free: | 950 | unlock_up_free: |
1135 | write_unlock_bh(&t->lock); | 951 | write_unlock_bh(&t->lock); |
1136 | up(&arpt_mutex); | 952 | xt_table_unlock(t); |
1137 | module_put(t->me); | 953 | module_put(t->me); |
1138 | free: | 954 | free: |
1139 | vfree(paddc); | 955 | vfree(paddc); |
@@ -1190,25 +1006,26 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len | |||
1190 | } | 1006 | } |
1191 | name[ARPT_TABLE_MAXNAMELEN-1] = '\0'; | 1007 | name[ARPT_TABLE_MAXNAMELEN-1] = '\0'; |
1192 | 1008 | ||
1193 | t = try_then_request_module(find_table_lock(name), | 1009 | t = try_then_request_module(xt_find_table_lock(NF_ARP, name), |
1194 | "arptable_%s", name); | 1010 | "arptable_%s", name); |
1195 | if (t && !IS_ERR(t)) { | 1011 | if (t && !IS_ERR(t)) { |
1196 | struct arpt_getinfo info; | 1012 | struct arpt_getinfo info; |
1013 | struct xt_table_info *private = t->private; | ||
1197 | 1014 | ||
1198 | info.valid_hooks = t->valid_hooks; | 1015 | info.valid_hooks = t->valid_hooks; |
1199 | memcpy(info.hook_entry, t->private->hook_entry, | 1016 | memcpy(info.hook_entry, private->hook_entry, |
1200 | sizeof(info.hook_entry)); | 1017 | sizeof(info.hook_entry)); |
1201 | memcpy(info.underflow, t->private->underflow, | 1018 | memcpy(info.underflow, private->underflow, |
1202 | sizeof(info.underflow)); | 1019 | sizeof(info.underflow)); |
1203 | info.num_entries = t->private->number; | 1020 | info.num_entries = private->number; |
1204 | info.size = t->private->size; | 1021 | info.size = private->size; |
1205 | strcpy(info.name, name); | 1022 | strcpy(info.name, name); |
1206 | 1023 | ||
1207 | if (copy_to_user(user, &info, *len) != 0) | 1024 | if (copy_to_user(user, &info, *len) != 0) |
1208 | ret = -EFAULT; | 1025 | ret = -EFAULT; |
1209 | else | 1026 | else |
1210 | ret = 0; | 1027 | ret = 0; |
1211 | up(&arpt_mutex); | 1028 | xt_table_unlock(t); |
1212 | module_put(t->me); | 1029 | module_put(t->me); |
1213 | } else | 1030 | } else |
1214 | ret = t ? PTR_ERR(t) : -ENOENT; | 1031 | ret = t ? PTR_ERR(t) : -ENOENT; |
@@ -1233,7 +1050,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len | |||
1233 | } | 1050 | } |
1234 | 1051 | ||
1235 | case ARPT_SO_GET_REVISION_TARGET: { | 1052 | case ARPT_SO_GET_REVISION_TARGET: { |
1236 | struct arpt_get_revision rev; | 1053 | struct xt_get_revision rev; |
1237 | 1054 | ||
1238 | if (*len != sizeof(rev)) { | 1055 | if (*len != sizeof(rev)) { |
1239 | ret = -EINVAL; | 1056 | ret = -EINVAL; |
@@ -1244,8 +1061,8 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len | |||
1244 | break; | 1061 | break; |
1245 | } | 1062 | } |
1246 | 1063 | ||
1247 | try_then_request_module(find_revision(rev.name, rev.revision, | 1064 | try_then_request_module(xt_find_revision(NF_ARP, rev.name, |
1248 | target_revfn, &ret), | 1065 | rev.revision, 1, &ret), |
1249 | "arpt_%s", rev.name); | 1066 | "arpt_%s", rev.name); |
1250 | break; | 1067 | break; |
1251 | } | 1068 | } |
@@ -1258,38 +1075,16 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len | |||
1258 | return ret; | 1075 | return ret; |
1259 | } | 1076 | } |
1260 | 1077 | ||
1261 | /* Registration hooks for targets. */ | ||
1262 | int arpt_register_target(struct arpt_target *target) | ||
1263 | { | ||
1264 | int ret; | ||
1265 | |||
1266 | ret = down_interruptible(&arpt_mutex); | ||
1267 | if (ret != 0) | ||
1268 | return ret; | ||
1269 | |||
1270 | list_add(&target->list, &arpt_target); | ||
1271 | up(&arpt_mutex); | ||
1272 | |||
1273 | return ret; | ||
1274 | } | ||
1275 | |||
1276 | void arpt_unregister_target(struct arpt_target *target) | ||
1277 | { | ||
1278 | down(&arpt_mutex); | ||
1279 | LIST_DELETE(&arpt_target, target); | ||
1280 | up(&arpt_mutex); | ||
1281 | } | ||
1282 | |||
1283 | int arpt_register_table(struct arpt_table *table, | 1078 | int arpt_register_table(struct arpt_table *table, |
1284 | const struct arpt_replace *repl) | 1079 | const struct arpt_replace *repl) |
1285 | { | 1080 | { |
1286 | int ret; | 1081 | int ret; |
1287 | struct arpt_table_info *newinfo; | 1082 | struct xt_table_info *newinfo; |
1288 | static struct arpt_table_info bootstrap | 1083 | static struct xt_table_info bootstrap |
1289 | = { 0, 0, 0, { 0 }, { 0 }, { } }; | 1084 | = { 0, 0, 0, { 0 }, { 0 }, { } }; |
1290 | void *loc_cpu_entry; | 1085 | void *loc_cpu_entry; |
1291 | 1086 | ||
1292 | newinfo = alloc_table_info(repl->size); | 1087 | newinfo = xt_alloc_table_info(repl->size); |
1293 | if (!newinfo) { | 1088 | if (!newinfo) { |
1294 | ret = -ENOMEM; | 1089 | ret = -ENOMEM; |
1295 | return ret; | 1090 | return ret; |
@@ -1304,60 +1099,33 @@ int arpt_register_table(struct arpt_table *table, | |||
1304 | repl->num_entries, | 1099 | repl->num_entries, |
1305 | repl->hook_entry, | 1100 | repl->hook_entry, |
1306 | repl->underflow); | 1101 | repl->underflow); |
1102 | |||
1307 | duprintf("arpt_register_table: translate table gives %d\n", ret); | 1103 | duprintf("arpt_register_table: translate table gives %d\n", ret); |
1308 | if (ret != 0) { | 1104 | if (ret != 0) { |
1309 | free_table_info(newinfo); | 1105 | xt_free_table_info(newinfo); |
1310 | return ret; | 1106 | return ret; |
1311 | } | 1107 | } |
1312 | 1108 | ||
1313 | ret = down_interruptible(&arpt_mutex); | 1109 | if (xt_register_table(table, &bootstrap, newinfo) != 0) { |
1314 | if (ret != 0) { | 1110 | xt_free_table_info(newinfo); |
1315 | free_table_info(newinfo); | ||
1316 | return ret; | 1111 | return ret; |
1317 | } | 1112 | } |
1318 | 1113 | ||
1319 | /* Don't autoload: we'd eat our tail... */ | 1114 | return 0; |
1320 | if (list_named_find(&arpt_tables, table->name)) { | ||
1321 | ret = -EEXIST; | ||
1322 | goto free_unlock; | ||
1323 | } | ||
1324 | |||
1325 | /* Simplifies replace_table code. */ | ||
1326 | table->private = &bootstrap; | ||
1327 | if (!replace_table(table, 0, newinfo, &ret)) | ||
1328 | goto free_unlock; | ||
1329 | |||
1330 | duprintf("table->private->number = %u\n", | ||
1331 | table->private->number); | ||
1332 | |||
1333 | /* save number of initial entries */ | ||
1334 | table->private->initial_entries = table->private->number; | ||
1335 | |||
1336 | rwlock_init(&table->lock); | ||
1337 | list_prepend(&arpt_tables, table); | ||
1338 | |||
1339 | unlock: | ||
1340 | up(&arpt_mutex); | ||
1341 | return ret; | ||
1342 | |||
1343 | free_unlock: | ||
1344 | free_table_info(newinfo); | ||
1345 | goto unlock; | ||
1346 | } | 1115 | } |
1347 | 1116 | ||
1348 | void arpt_unregister_table(struct arpt_table *table) | 1117 | void arpt_unregister_table(struct arpt_table *table) |
1349 | { | 1118 | { |
1119 | struct xt_table_info *private; | ||
1350 | void *loc_cpu_entry; | 1120 | void *loc_cpu_entry; |
1351 | 1121 | ||
1352 | down(&arpt_mutex); | 1122 | private = xt_unregister_table(table); |
1353 | LIST_DELETE(&arpt_tables, table); | ||
1354 | up(&arpt_mutex); | ||
1355 | 1123 | ||
1356 | /* Decrease module usage counts and free resources */ | 1124 | /* Decrease module usage counts and free resources */ |
1357 | loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; | 1125 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
1358 | ARPT_ENTRY_ITERATE(loc_cpu_entry, table->private->size, | 1126 | ARPT_ENTRY_ITERATE(loc_cpu_entry, private->size, |
1359 | cleanup_entry, NULL); | 1127 | cleanup_entry, NULL); |
1360 | free_table_info(table->private); | 1128 | xt_free_table_info(private); |
1361 | } | 1129 | } |
1362 | 1130 | ||
1363 | /* The built-in targets: standard (NULL) and error. */ | 1131 | /* The built-in targets: standard (NULL) and error. */ |
@@ -1380,52 +1148,15 @@ static struct nf_sockopt_ops arpt_sockopts = { | |||
1380 | .get = do_arpt_get_ctl, | 1148 | .get = do_arpt_get_ctl, |
1381 | }; | 1149 | }; |
1382 | 1150 | ||
1383 | #ifdef CONFIG_PROC_FS | ||
1384 | static inline int print_name(const struct arpt_table *t, | ||
1385 | off_t start_offset, char *buffer, int length, | ||
1386 | off_t *pos, unsigned int *count) | ||
1387 | { | ||
1388 | if ((*count)++ >= start_offset) { | ||
1389 | unsigned int namelen; | ||
1390 | |||
1391 | namelen = sprintf(buffer + *pos, "%s\n", t->name); | ||
1392 | if (*pos + namelen > length) { | ||
1393 | /* Stop iterating */ | ||
1394 | return 1; | ||
1395 | } | ||
1396 | *pos += namelen; | ||
1397 | } | ||
1398 | return 0; | ||
1399 | } | ||
1400 | |||
1401 | static int arpt_get_tables(char *buffer, char **start, off_t offset, int length) | ||
1402 | { | ||
1403 | off_t pos = 0; | ||
1404 | unsigned int count = 0; | ||
1405 | |||
1406 | if (down_interruptible(&arpt_mutex) != 0) | ||
1407 | return 0; | ||
1408 | |||
1409 | LIST_FIND(&arpt_tables, print_name, struct arpt_table *, | ||
1410 | offset, buffer, length, &pos, &count); | ||
1411 | |||
1412 | up(&arpt_mutex); | ||
1413 | |||
1414 | /* `start' hack - see fs/proc/generic.c line ~105 */ | ||
1415 | *start=(char *)((unsigned long)count-offset); | ||
1416 | return pos; | ||
1417 | } | ||
1418 | #endif /*CONFIG_PROC_FS*/ | ||
1419 | |||
1420 | static int __init init(void) | 1151 | static int __init init(void) |
1421 | { | 1152 | { |
1422 | int ret; | 1153 | int ret; |
1423 | 1154 | ||
1155 | xt_proto_init(NF_ARP); | ||
1156 | |||
1424 | /* Noone else will be downing sem now, so we won't sleep */ | 1157 | /* Noone else will be downing sem now, so we won't sleep */ |
1425 | down(&arpt_mutex); | 1158 | xt_register_target(NF_ARP, &arpt_standard_target); |
1426 | list_append(&arpt_target, &arpt_standard_target); | 1159 | xt_register_target(NF_ARP, &arpt_error_target); |
1427 | list_append(&arpt_target, &arpt_error_target); | ||
1428 | up(&arpt_mutex); | ||
1429 | 1160 | ||
1430 | /* Register setsockopt */ | 1161 | /* Register setsockopt */ |
1431 | ret = nf_register_sockopt(&arpt_sockopts); | 1162 | ret = nf_register_sockopt(&arpt_sockopts); |
@@ -1434,19 +1165,6 @@ static int __init init(void) | |||
1434 | return ret; | 1165 | return ret; |
1435 | } | 1166 | } |
1436 | 1167 | ||
1437 | #ifdef CONFIG_PROC_FS | ||
1438 | { | ||
1439 | struct proc_dir_entry *proc; | ||
1440 | |||
1441 | proc = proc_net_create("arp_tables_names", 0, arpt_get_tables); | ||
1442 | if (!proc) { | ||
1443 | nf_unregister_sockopt(&arpt_sockopts); | ||
1444 | return -ENOMEM; | ||
1445 | } | ||
1446 | proc->owner = THIS_MODULE; | ||
1447 | } | ||
1448 | #endif | ||
1449 | |||
1450 | printk("arp_tables: (C) 2002 David S. Miller\n"); | 1168 | printk("arp_tables: (C) 2002 David S. Miller\n"); |
1451 | return 0; | 1169 | return 0; |
1452 | } | 1170 | } |
@@ -1454,16 +1172,12 @@ static int __init init(void) | |||
1454 | static void __exit fini(void) | 1172 | static void __exit fini(void) |
1455 | { | 1173 | { |
1456 | nf_unregister_sockopt(&arpt_sockopts); | 1174 | nf_unregister_sockopt(&arpt_sockopts); |
1457 | #ifdef CONFIG_PROC_FS | 1175 | xt_proto_fini(NF_ARP); |
1458 | proc_net_remove("arp_tables_names"); | ||
1459 | #endif | ||
1460 | } | 1176 | } |
1461 | 1177 | ||
1462 | EXPORT_SYMBOL(arpt_register_table); | 1178 | EXPORT_SYMBOL(arpt_register_table); |
1463 | EXPORT_SYMBOL(arpt_unregister_table); | 1179 | EXPORT_SYMBOL(arpt_unregister_table); |
1464 | EXPORT_SYMBOL(arpt_do_table); | 1180 | EXPORT_SYMBOL(arpt_do_table); |
1465 | EXPORT_SYMBOL(arpt_register_target); | ||
1466 | EXPORT_SYMBOL(arpt_unregister_target); | ||
1467 | 1181 | ||
1468 | module_init(init); | 1182 | module_init(init); |
1469 | module_exit(fini); | 1183 | module_exit(fini); |
diff --git a/net/ipv4/netfilter/arpt_mangle.c b/net/ipv4/netfilter/arpt_mangle.c index 3e592ec86482..c97650a16a5b 100644 --- a/net/ipv4/netfilter/arpt_mangle.c +++ b/net/ipv4/netfilter/arpt_mangle.c | |||
@@ -8,8 +8,9 @@ MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); | |||
8 | MODULE_DESCRIPTION("arptables arp payload mangle target"); | 8 | MODULE_DESCRIPTION("arptables arp payload mangle target"); |
9 | 9 | ||
10 | static unsigned int | 10 | static unsigned int |
11 | target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, | 11 | target(struct sk_buff **pskb, const struct net_device *in, |
12 | const struct net_device *out, const void *targinfo, void *userinfo) | 12 | const struct net_device *out, unsigned int hooknum, const void *targinfo, |
13 | void *userinfo) | ||
13 | { | 14 | { |
14 | const struct arpt_mangle *mangle = targinfo; | 15 | const struct arpt_mangle *mangle = targinfo; |
15 | struct arphdr *arp; | 16 | struct arphdr *arp; |
@@ -64,7 +65,7 @@ target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, | |||
64 | } | 65 | } |
65 | 66 | ||
66 | static int | 67 | static int |
67 | checkentry(const char *tablename, const struct arpt_entry *e, void *targinfo, | 68 | checkentry(const char *tablename, const void *e, void *targinfo, |
68 | unsigned int targinfosize, unsigned int hook_mask) | 69 | unsigned int targinfosize, unsigned int hook_mask) |
69 | { | 70 | { |
70 | const struct arpt_mangle *mangle = targinfo; | 71 | const struct arpt_mangle *mangle = targinfo; |
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index 0d759f5a4ef0..f6ab45f48681 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c | |||
@@ -145,6 +145,7 @@ static struct arpt_table packet_filter = { | |||
145 | .lock = RW_LOCK_UNLOCKED, | 145 | .lock = RW_LOCK_UNLOCKED, |
146 | .private = NULL, | 146 | .private = NULL, |
147 | .me = THIS_MODULE, | 147 | .me = THIS_MODULE, |
148 | .af = NF_ARP, | ||
148 | }; | 149 | }; |
149 | 150 | ||
150 | /* The work comes in here from netfilter.c */ | 151 | /* The work comes in here from netfilter.c */ |
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 9dec1293f67a..833fcb4be5e7 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c | |||
@@ -944,7 +944,7 @@ module_exit(fini); | |||
944 | 944 | ||
945 | /* Some modules need us, but don't depend directly on any symbol. | 945 | /* Some modules need us, but don't depend directly on any symbol. |
946 | They should call this. */ | 946 | They should call this. */ |
947 | void need_ip_conntrack(void) | 947 | void need_conntrack(void) |
948 | { | 948 | { |
949 | } | 949 | } |
950 | 950 | ||
@@ -962,7 +962,7 @@ EXPORT_SYMBOL(ip_ct_get_tuple); | |||
962 | EXPORT_SYMBOL(invert_tuplepr); | 962 | EXPORT_SYMBOL(invert_tuplepr); |
963 | EXPORT_SYMBOL(ip_conntrack_alter_reply); | 963 | EXPORT_SYMBOL(ip_conntrack_alter_reply); |
964 | EXPORT_SYMBOL(ip_conntrack_destroyed); | 964 | EXPORT_SYMBOL(ip_conntrack_destroyed); |
965 | EXPORT_SYMBOL(need_ip_conntrack); | 965 | EXPORT_SYMBOL(need_conntrack); |
966 | EXPORT_SYMBOL(ip_conntrack_helper_register); | 966 | EXPORT_SYMBOL(ip_conntrack_helper_register); |
967 | EXPORT_SYMBOL(ip_conntrack_helper_unregister); | 967 | EXPORT_SYMBOL(ip_conntrack_helper_unregister); |
968 | EXPORT_SYMBOL(ip_ct_iterate_cleanup); | 968 | EXPORT_SYMBOL(ip_ct_iterate_cleanup); |
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c index cb66b8bddeb3..1de86282d232 100644 --- a/net/ipv4/netfilter/ip_nat_rule.c +++ b/net/ipv4/netfilter/ip_nat_rule.c | |||
@@ -95,6 +95,7 @@ static struct ipt_table nat_table = { | |||
95 | .valid_hooks = NAT_VALID_HOOKS, | 95 | .valid_hooks = NAT_VALID_HOOKS, |
96 | .lock = RW_LOCK_UNLOCKED, | 96 | .lock = RW_LOCK_UNLOCKED, |
97 | .me = THIS_MODULE, | 97 | .me = THIS_MODULE, |
98 | .af = AF_INET, | ||
98 | }; | 99 | }; |
99 | 100 | ||
100 | /* Source NAT */ | 101 | /* Source NAT */ |
@@ -168,7 +169,7 @@ static unsigned int ipt_dnat_target(struct sk_buff **pskb, | |||
168 | } | 169 | } |
169 | 170 | ||
170 | static int ipt_snat_checkentry(const char *tablename, | 171 | static int ipt_snat_checkentry(const char *tablename, |
171 | const struct ipt_entry *e, | 172 | const void *entry, |
172 | void *targinfo, | 173 | void *targinfo, |
173 | unsigned int targinfosize, | 174 | unsigned int targinfosize, |
174 | unsigned int hook_mask) | 175 | unsigned int hook_mask) |
@@ -201,7 +202,7 @@ static int ipt_snat_checkentry(const char *tablename, | |||
201 | } | 202 | } |
202 | 203 | ||
203 | static int ipt_dnat_checkentry(const char *tablename, | 204 | static int ipt_dnat_checkentry(const char *tablename, |
204 | const struct ipt_entry *e, | 205 | const void *entry, |
205 | void *targinfo, | 206 | void *targinfo, |
206 | unsigned int targinfosize, | 207 | unsigned int targinfosize, |
207 | unsigned int hook_mask) | 208 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 8b8a1f00bbf4..ad438fb185b8 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c | |||
@@ -364,7 +364,7 @@ static int init_or_cleanup(int init) | |||
364 | { | 364 | { |
365 | int ret = 0; | 365 | int ret = 0; |
366 | 366 | ||
367 | need_ip_conntrack(); | 367 | need_conntrack(); |
368 | 368 | ||
369 | if (!init) goto cleanup; | 369 | if (!init) goto cleanup; |
370 | 370 | ||
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 877bc96d3336..2371b2062c2d 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Packet matching code. | 2 | * Packet matching code. |
3 | * | 3 | * |
4 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling | 4 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling |
5 | * Copyright (C) 2000-2004 Netfilter Core Team <coreteam@netfilter.org> | 5 | * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.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 |
@@ -11,6 +11,8 @@ | |||
11 | * 19 Jan 2002 Harald Welte <laforge@gnumonks.org> | 11 | * 19 Jan 2002 Harald Welte <laforge@gnumonks.org> |
12 | * - increase module usage count as soon as we have rules inside | 12 | * - increase module usage count as soon as we have rules inside |
13 | * a table | 13 | * a table |
14 | * 08 Oct 2005 Harald Welte <lafore@netfilter.org> | ||
15 | * - Generalize into "x_tables" layer and "{ip,ip6,arp}_tables" | ||
14 | */ | 16 | */ |
15 | #include <linux/config.h> | 17 | #include <linux/config.h> |
16 | #include <linux/cache.h> | 18 | #include <linux/cache.h> |
@@ -20,8 +22,6 @@ | |||
20 | #include <linux/vmalloc.h> | 22 | #include <linux/vmalloc.h> |
21 | #include <linux/netdevice.h> | 23 | #include <linux/netdevice.h> |
22 | #include <linux/module.h> | 24 | #include <linux/module.h> |
23 | #include <linux/tcp.h> | ||
24 | #include <linux/udp.h> | ||
25 | #include <linux/icmp.h> | 25 | #include <linux/icmp.h> |
26 | #include <net/ip.h> | 26 | #include <net/ip.h> |
27 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/err.h> | 30 | #include <linux/err.h> |
31 | #include <linux/cpumask.h> | 31 | #include <linux/cpumask.h> |
32 | 32 | ||
33 | #include <linux/netfilter/x_tables.h> | ||
33 | #include <linux/netfilter_ipv4/ip_tables.h> | 34 | #include <linux/netfilter_ipv4/ip_tables.h> |
34 | 35 | ||
35 | MODULE_LICENSE("GPL"); | 36 | MODULE_LICENSE("GPL"); |
@@ -62,14 +63,6 @@ do { \ | |||
62 | #else | 63 | #else |
63 | #define IP_NF_ASSERT(x) | 64 | #define IP_NF_ASSERT(x) |
64 | #endif | 65 | #endif |
65 | #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) | ||
66 | |||
67 | static DECLARE_MUTEX(ipt_mutex); | ||
68 | |||
69 | /* Must have mutex */ | ||
70 | #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) | ||
71 | #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) | ||
72 | #include <linux/netfilter_ipv4/listhelp.h> | ||
73 | 66 | ||
74 | #if 0 | 67 | #if 0 |
75 | /* All the better to debug you with... */ | 68 | /* All the better to debug you with... */ |
@@ -86,36 +79,6 @@ static DECLARE_MUTEX(ipt_mutex); | |||
86 | 79 | ||
87 | Hence the start of any table is given by get_table() below. */ | 80 | Hence the start of any table is given by get_table() below. */ |
88 | 81 | ||
89 | /* The table itself */ | ||
90 | struct ipt_table_info | ||
91 | { | ||
92 | /* Size per table */ | ||
93 | unsigned int size; | ||
94 | /* Number of entries: FIXME. --RR */ | ||
95 | unsigned int number; | ||
96 | /* Initial number of entries. Needed for module usage count */ | ||
97 | unsigned int initial_entries; | ||
98 | |||
99 | /* Entry points and underflows */ | ||
100 | unsigned int hook_entry[NF_IP_NUMHOOKS]; | ||
101 | unsigned int underflow[NF_IP_NUMHOOKS]; | ||
102 | |||
103 | /* ipt_entry tables: one per CPU */ | ||
104 | void *entries[NR_CPUS]; | ||
105 | }; | ||
106 | |||
107 | static LIST_HEAD(ipt_target); | ||
108 | static LIST_HEAD(ipt_match); | ||
109 | static LIST_HEAD(ipt_tables); | ||
110 | #define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) | ||
111 | #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) | ||
112 | |||
113 | #if 0 | ||
114 | #define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) | ||
115 | #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) | ||
116 | #define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0) | ||
117 | #endif | ||
118 | |||
119 | /* Returns whether matches rule or not. */ | 82 | /* Returns whether matches rule or not. */ |
120 | static inline int | 83 | static inline int |
121 | ip_packet_match(const struct iphdr *ip, | 84 | ip_packet_match(const struct iphdr *ip, |
@@ -234,7 +197,8 @@ int do_match(struct ipt_entry_match *m, | |||
234 | int *hotdrop) | 197 | int *hotdrop) |
235 | { | 198 | { |
236 | /* Stop iteration if it doesn't match */ | 199 | /* Stop iteration if it doesn't match */ |
237 | if (!m->u.kernel.match->match(skb, in, out, m->data, offset, hotdrop)) | 200 | if (!m->u.kernel.match->match(skb, in, out, m->data, offset, |
201 | skb->nh.iph->ihl*4, hotdrop)) | ||
238 | return 1; | 202 | return 1; |
239 | else | 203 | else |
240 | return 0; | 204 | return 0; |
@@ -265,6 +229,7 @@ ipt_do_table(struct sk_buff **pskb, | |||
265 | const char *indev, *outdev; | 229 | const char *indev, *outdev; |
266 | void *table_base; | 230 | void *table_base; |
267 | struct ipt_entry *e, *back; | 231 | struct ipt_entry *e, *back; |
232 | struct xt_table_info *private = table->private; | ||
268 | 233 | ||
269 | /* Initialization */ | 234 | /* Initialization */ |
270 | ip = (*pskb)->nh.iph; | 235 | ip = (*pskb)->nh.iph; |
@@ -281,24 +246,11 @@ ipt_do_table(struct sk_buff **pskb, | |||
281 | 246 | ||
282 | read_lock_bh(&table->lock); | 247 | read_lock_bh(&table->lock); |
283 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 248 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
284 | table_base = (void *)table->private->entries[smp_processor_id()]; | 249 | table_base = (void *)private->entries[smp_processor_id()]; |
285 | e = get_entry(table_base, table->private->hook_entry[hook]); | 250 | e = get_entry(table_base, private->hook_entry[hook]); |
286 | |||
287 | #ifdef CONFIG_NETFILTER_DEBUG | ||
288 | /* Check noone else using our table */ | ||
289 | if (((struct ipt_entry *)table_base)->comefrom != 0xdead57ac | ||
290 | && ((struct ipt_entry *)table_base)->comefrom != 0xeeeeeeec) { | ||
291 | printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n", | ||
292 | smp_processor_id(), | ||
293 | table->name, | ||
294 | &((struct ipt_entry *)table_base)->comefrom, | ||
295 | ((struct ipt_entry *)table_base)->comefrom); | ||
296 | } | ||
297 | ((struct ipt_entry *)table_base)->comefrom = 0x57acc001; | ||
298 | #endif | ||
299 | 251 | ||
300 | /* For return from builtin chain */ | 252 | /* For return from builtin chain */ |
301 | back = get_entry(table_base, table->private->underflow[hook]); | 253 | back = get_entry(table_base, private->underflow[hook]); |
302 | 254 | ||
303 | do { | 255 | do { |
304 | IP_NF_ASSERT(e); | 256 | IP_NF_ASSERT(e); |
@@ -384,9 +336,6 @@ ipt_do_table(struct sk_buff **pskb, | |||
384 | } | 336 | } |
385 | } while (!hotdrop); | 337 | } while (!hotdrop); |
386 | 338 | ||
387 | #ifdef CONFIG_NETFILTER_DEBUG | ||
388 | ((struct ipt_entry *)table_base)->comefrom = 0xdead57ac; | ||
389 | #endif | ||
390 | read_unlock_bh(&table->lock); | 339 | read_unlock_bh(&table->lock); |
391 | 340 | ||
392 | #ifdef DEBUG_ALLOW_ALL | 341 | #ifdef DEBUG_ALLOW_ALL |
@@ -398,145 +347,6 @@ ipt_do_table(struct sk_buff **pskb, | |||
398 | #endif | 347 | #endif |
399 | } | 348 | } |
400 | 349 | ||
401 | /* | ||
402 | * These are weird, but module loading must not be done with mutex | ||
403 | * held (since they will register), and we have to have a single | ||
404 | * function to use try_then_request_module(). | ||
405 | */ | ||
406 | |||
407 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ | ||
408 | static inline struct ipt_table *find_table_lock(const char *name) | ||
409 | { | ||
410 | struct ipt_table *t; | ||
411 | |||
412 | if (down_interruptible(&ipt_mutex) != 0) | ||
413 | return ERR_PTR(-EINTR); | ||
414 | |||
415 | list_for_each_entry(t, &ipt_tables, list) | ||
416 | if (strcmp(t->name, name) == 0 && try_module_get(t->me)) | ||
417 | return t; | ||
418 | up(&ipt_mutex); | ||
419 | return NULL; | ||
420 | } | ||
421 | |||
422 | /* Find match, grabs ref. Returns ERR_PTR() on error. */ | ||
423 | static inline struct ipt_match *find_match(const char *name, u8 revision) | ||
424 | { | ||
425 | struct ipt_match *m; | ||
426 | int err = 0; | ||
427 | |||
428 | if (down_interruptible(&ipt_mutex) != 0) | ||
429 | return ERR_PTR(-EINTR); | ||
430 | |||
431 | list_for_each_entry(m, &ipt_match, list) { | ||
432 | if (strcmp(m->name, name) == 0) { | ||
433 | if (m->revision == revision) { | ||
434 | if (try_module_get(m->me)) { | ||
435 | up(&ipt_mutex); | ||
436 | return m; | ||
437 | } | ||
438 | } else | ||
439 | err = -EPROTOTYPE; /* Found something. */ | ||
440 | } | ||
441 | } | ||
442 | up(&ipt_mutex); | ||
443 | return ERR_PTR(err); | ||
444 | } | ||
445 | |||
446 | /* Find target, grabs ref. Returns ERR_PTR() on error. */ | ||
447 | static inline struct ipt_target *find_target(const char *name, u8 revision) | ||
448 | { | ||
449 | struct ipt_target *t; | ||
450 | int err = 0; | ||
451 | |||
452 | if (down_interruptible(&ipt_mutex) != 0) | ||
453 | return ERR_PTR(-EINTR); | ||
454 | |||
455 | list_for_each_entry(t, &ipt_target, list) { | ||
456 | if (strcmp(t->name, name) == 0) { | ||
457 | if (t->revision == revision) { | ||
458 | if (try_module_get(t->me)) { | ||
459 | up(&ipt_mutex); | ||
460 | return t; | ||
461 | } | ||
462 | } else | ||
463 | err = -EPROTOTYPE; /* Found something. */ | ||
464 | } | ||
465 | } | ||
466 | up(&ipt_mutex); | ||
467 | return ERR_PTR(err); | ||
468 | } | ||
469 | |||
470 | struct ipt_target *ipt_find_target(const char *name, u8 revision) | ||
471 | { | ||
472 | struct ipt_target *target; | ||
473 | |||
474 | target = try_then_request_module(find_target(name, revision), | ||
475 | "ipt_%s", name); | ||
476 | if (IS_ERR(target) || !target) | ||
477 | return NULL; | ||
478 | return target; | ||
479 | } | ||
480 | |||
481 | static int match_revfn(const char *name, u8 revision, int *bestp) | ||
482 | { | ||
483 | struct ipt_match *m; | ||
484 | int have_rev = 0; | ||
485 | |||
486 | list_for_each_entry(m, &ipt_match, list) { | ||
487 | if (strcmp(m->name, name) == 0) { | ||
488 | if (m->revision > *bestp) | ||
489 | *bestp = m->revision; | ||
490 | if (m->revision == revision) | ||
491 | have_rev = 1; | ||
492 | } | ||
493 | } | ||
494 | return have_rev; | ||
495 | } | ||
496 | |||
497 | static int target_revfn(const char *name, u8 revision, int *bestp) | ||
498 | { | ||
499 | struct ipt_target *t; | ||
500 | int have_rev = 0; | ||
501 | |||
502 | list_for_each_entry(t, &ipt_target, list) { | ||
503 | if (strcmp(t->name, name) == 0) { | ||
504 | if (t->revision > *bestp) | ||
505 | *bestp = t->revision; | ||
506 | if (t->revision == revision) | ||
507 | have_rev = 1; | ||
508 | } | ||
509 | } | ||
510 | return have_rev; | ||
511 | } | ||
512 | |||
513 | /* Returns true or false (if no such extension at all) */ | ||
514 | static inline int find_revision(const char *name, u8 revision, | ||
515 | int (*revfn)(const char *, u8, int *), | ||
516 | int *err) | ||
517 | { | ||
518 | int have_rev, best = -1; | ||
519 | |||
520 | if (down_interruptible(&ipt_mutex) != 0) { | ||
521 | *err = -EINTR; | ||
522 | return 1; | ||
523 | } | ||
524 | have_rev = revfn(name, revision, &best); | ||
525 | up(&ipt_mutex); | ||
526 | |||
527 | /* Nothing at all? Return 0 to try loading module. */ | ||
528 | if (best == -1) { | ||
529 | *err = -ENOENT; | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | *err = best; | ||
534 | if (!have_rev) | ||
535 | *err = -EPROTONOSUPPORT; | ||
536 | return 1; | ||
537 | } | ||
538 | |||
539 | |||
540 | /* All zeroes == unconditional rule. */ | 350 | /* All zeroes == unconditional rule. */ |
541 | static inline int | 351 | static inline int |
542 | unconditional(const struct ipt_ip *ip) | 352 | unconditional(const struct ipt_ip *ip) |
@@ -553,7 +363,7 @@ unconditional(const struct ipt_ip *ip) | |||
553 | /* Figures out from what hook each rule can be called: returns 0 if | 363 | /* Figures out from what hook each rule can be called: returns 0 if |
554 | there are loops. Puts hook bitmask in comefrom. */ | 364 | there are loops. Puts hook bitmask in comefrom. */ |
555 | static int | 365 | static int |
556 | mark_source_chains(struct ipt_table_info *newinfo, | 366 | mark_source_chains(struct xt_table_info *newinfo, |
557 | unsigned int valid_hooks, void *entry0) | 367 | unsigned int valid_hooks, void *entry0) |
558 | { | 368 | { |
559 | unsigned int hook; | 369 | unsigned int hook; |
@@ -699,7 +509,7 @@ check_match(struct ipt_entry_match *m, | |||
699 | { | 509 | { |
700 | struct ipt_match *match; | 510 | struct ipt_match *match; |
701 | 511 | ||
702 | match = try_then_request_module(find_match(m->u.user.name, | 512 | match = try_then_request_module(xt_find_match(AF_INET, m->u.user.name, |
703 | m->u.user.revision), | 513 | m->u.user.revision), |
704 | "ipt_%s", m->u.user.name); | 514 | "ipt_%s", m->u.user.name); |
705 | if (IS_ERR(match) || !match) { | 515 | if (IS_ERR(match) || !match) { |
@@ -744,7 +554,8 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, | |||
744 | goto cleanup_matches; | 554 | goto cleanup_matches; |
745 | 555 | ||
746 | t = ipt_get_target(e); | 556 | t = ipt_get_target(e); |
747 | target = try_then_request_module(find_target(t->u.user.name, | 557 | target = try_then_request_module(xt_find_target(AF_INET, |
558 | t->u.user.name, | ||
748 | t->u.user.revision), | 559 | t->u.user.revision), |
749 | "ipt_%s", t->u.user.name); | 560 | "ipt_%s", t->u.user.name); |
750 | if (IS_ERR(target) || !target) { | 561 | if (IS_ERR(target) || !target) { |
@@ -781,7 +592,7 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, | |||
781 | 592 | ||
782 | static inline int | 593 | static inline int |
783 | check_entry_size_and_hooks(struct ipt_entry *e, | 594 | check_entry_size_and_hooks(struct ipt_entry *e, |
784 | struct ipt_table_info *newinfo, | 595 | struct xt_table_info *newinfo, |
785 | unsigned char *base, | 596 | unsigned char *base, |
786 | unsigned char *limit, | 597 | unsigned char *limit, |
787 | const unsigned int *hook_entries, | 598 | const unsigned int *hook_entries, |
@@ -815,7 +626,7 @@ check_entry_size_and_hooks(struct ipt_entry *e, | |||
815 | < 0 (not IPT_RETURN). --RR */ | 626 | < 0 (not IPT_RETURN). --RR */ |
816 | 627 | ||
817 | /* Clear counters and comefrom */ | 628 | /* Clear counters and comefrom */ |
818 | e->counters = ((struct ipt_counters) { 0, 0 }); | 629 | e->counters = ((struct xt_counters) { 0, 0 }); |
819 | e->comefrom = 0; | 630 | e->comefrom = 0; |
820 | 631 | ||
821 | (*i)++; | 632 | (*i)++; |
@@ -845,7 +656,7 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i) | |||
845 | static int | 656 | static int |
846 | translate_table(const char *name, | 657 | translate_table(const char *name, |
847 | unsigned int valid_hooks, | 658 | unsigned int valid_hooks, |
848 | struct ipt_table_info *newinfo, | 659 | struct xt_table_info *newinfo, |
849 | void *entry0, | 660 | void *entry0, |
850 | unsigned int size, | 661 | unsigned int size, |
851 | unsigned int number, | 662 | unsigned int number, |
@@ -922,48 +733,10 @@ translate_table(const char *name, | |||
922 | return ret; | 733 | return ret; |
923 | } | 734 | } |
924 | 735 | ||
925 | static struct ipt_table_info * | ||
926 | replace_table(struct ipt_table *table, | ||
927 | unsigned int num_counters, | ||
928 | struct ipt_table_info *newinfo, | ||
929 | int *error) | ||
930 | { | ||
931 | struct ipt_table_info *oldinfo; | ||
932 | |||
933 | #ifdef CONFIG_NETFILTER_DEBUG | ||
934 | { | ||
935 | int cpu; | ||
936 | |||
937 | for_each_cpu(cpu) { | ||
938 | struct ipt_entry *table_base = newinfo->entries[cpu]; | ||
939 | if (table_base) | ||
940 | table_base->comefrom = 0xdead57ac; | ||
941 | } | ||
942 | } | ||
943 | #endif | ||
944 | |||
945 | /* Do the substitution. */ | ||
946 | write_lock_bh(&table->lock); | ||
947 | /* Check inside lock: is the old number correct? */ | ||
948 | if (num_counters != table->private->number) { | ||
949 | duprintf("num_counters != table->private->number (%u/%u)\n", | ||
950 | num_counters, table->private->number); | ||
951 | write_unlock_bh(&table->lock); | ||
952 | *error = -EAGAIN; | ||
953 | return NULL; | ||
954 | } | ||
955 | oldinfo = table->private; | ||
956 | table->private = newinfo; | ||
957 | newinfo->initial_entries = oldinfo->initial_entries; | ||
958 | write_unlock_bh(&table->lock); | ||
959 | |||
960 | return oldinfo; | ||
961 | } | ||
962 | |||
963 | /* Gets counters. */ | 736 | /* Gets counters. */ |
964 | static inline int | 737 | static inline int |
965 | add_entry_to_counter(const struct ipt_entry *e, | 738 | add_entry_to_counter(const struct ipt_entry *e, |
966 | struct ipt_counters total[], | 739 | struct xt_counters total[], |
967 | unsigned int *i) | 740 | unsigned int *i) |
968 | { | 741 | { |
969 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); | 742 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); |
@@ -984,8 +757,8 @@ set_entry_to_counter(const struct ipt_entry *e, | |||
984 | } | 757 | } |
985 | 758 | ||
986 | static void | 759 | static void |
987 | get_counters(const struct ipt_table_info *t, | 760 | get_counters(const struct xt_table_info *t, |
988 | struct ipt_counters counters[]) | 761 | struct xt_counters counters[]) |
989 | { | 762 | { |
990 | unsigned int cpu; | 763 | unsigned int cpu; |
991 | unsigned int i; | 764 | unsigned int i; |
@@ -1024,14 +797,15 @@ copy_entries_to_user(unsigned int total_size, | |||
1024 | { | 797 | { |
1025 | unsigned int off, num, countersize; | 798 | unsigned int off, num, countersize; |
1026 | struct ipt_entry *e; | 799 | struct ipt_entry *e; |
1027 | struct ipt_counters *counters; | 800 | struct xt_counters *counters; |
801 | struct xt_table_info *private = table->private; | ||
1028 | int ret = 0; | 802 | int ret = 0; |
1029 | void *loc_cpu_entry; | 803 | void *loc_cpu_entry; |
1030 | 804 | ||
1031 | /* We need atomic snapshot of counters: rest doesn't change | 805 | /* We need atomic snapshot of counters: rest doesn't change |
1032 | (other than comefrom, which userspace doesn't care | 806 | (other than comefrom, which userspace doesn't care |
1033 | about). */ | 807 | about). */ |
1034 | countersize = sizeof(struct ipt_counters) * table->private->number; | 808 | countersize = sizeof(struct xt_counters) * private->number; |
1035 | counters = vmalloc_node(countersize, numa_node_id()); | 809 | counters = vmalloc_node(countersize, numa_node_id()); |
1036 | 810 | ||
1037 | if (counters == NULL) | 811 | if (counters == NULL) |
@@ -1039,14 +813,14 @@ copy_entries_to_user(unsigned int total_size, | |||
1039 | 813 | ||
1040 | /* First, sum counters... */ | 814 | /* First, sum counters... */ |
1041 | write_lock_bh(&table->lock); | 815 | write_lock_bh(&table->lock); |
1042 | get_counters(table->private, counters); | 816 | get_counters(private, counters); |
1043 | write_unlock_bh(&table->lock); | 817 | write_unlock_bh(&table->lock); |
1044 | 818 | ||
1045 | /* choose the copy that is on our node/cpu, ... | 819 | /* choose the copy that is on our node/cpu, ... |
1046 | * This choice is lazy (because current thread is | 820 | * This choice is lazy (because current thread is |
1047 | * allowed to migrate to another cpu) | 821 | * allowed to migrate to another cpu) |
1048 | */ | 822 | */ |
1049 | loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; | 823 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
1050 | /* ... then copy entire thing ... */ | 824 | /* ... then copy entire thing ... */ |
1051 | if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { | 825 | if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { |
1052 | ret = -EFAULT; | 826 | ret = -EFAULT; |
@@ -1108,74 +882,36 @@ get_entries(const struct ipt_get_entries *entries, | |||
1108 | int ret; | 882 | int ret; |
1109 | struct ipt_table *t; | 883 | struct ipt_table *t; |
1110 | 884 | ||
1111 | t = find_table_lock(entries->name); | 885 | t = xt_find_table_lock(AF_INET, entries->name); |
1112 | if (t && !IS_ERR(t)) { | 886 | if (t && !IS_ERR(t)) { |
887 | struct xt_table_info *private = t->private; | ||
1113 | duprintf("t->private->number = %u\n", | 888 | duprintf("t->private->number = %u\n", |
1114 | t->private->number); | 889 | private->number); |
1115 | if (entries->size == t->private->size) | 890 | if (entries->size == private->size) |
1116 | ret = copy_entries_to_user(t->private->size, | 891 | ret = copy_entries_to_user(private->size, |
1117 | t, uptr->entrytable); | 892 | t, uptr->entrytable); |
1118 | else { | 893 | else { |
1119 | duprintf("get_entries: I've got %u not %u!\n", | 894 | duprintf("get_entries: I've got %u not %u!\n", |
1120 | t->private->size, | 895 | private->size, |
1121 | entries->size); | 896 | entries->size); |
1122 | ret = -EINVAL; | 897 | ret = -EINVAL; |
1123 | } | 898 | } |
1124 | module_put(t->me); | 899 | module_put(t->me); |
1125 | up(&ipt_mutex); | 900 | xt_table_unlock(t); |
1126 | } else | 901 | } else |
1127 | ret = t ? PTR_ERR(t) : -ENOENT; | 902 | ret = t ? PTR_ERR(t) : -ENOENT; |
1128 | 903 | ||
1129 | return ret; | 904 | return ret; |
1130 | } | 905 | } |
1131 | 906 | ||
1132 | static void free_table_info(struct ipt_table_info *info) | ||
1133 | { | ||
1134 | int cpu; | ||
1135 | for_each_cpu(cpu) { | ||
1136 | if (info->size <= PAGE_SIZE) | ||
1137 | kfree(info->entries[cpu]); | ||
1138 | else | ||
1139 | vfree(info->entries[cpu]); | ||
1140 | } | ||
1141 | kfree(info); | ||
1142 | } | ||
1143 | |||
1144 | static struct ipt_table_info *alloc_table_info(unsigned int size) | ||
1145 | { | ||
1146 | struct ipt_table_info *newinfo; | ||
1147 | int cpu; | ||
1148 | |||
1149 | newinfo = kzalloc(sizeof(struct ipt_table_info), GFP_KERNEL); | ||
1150 | if (!newinfo) | ||
1151 | return NULL; | ||
1152 | |||
1153 | newinfo->size = size; | ||
1154 | |||
1155 | for_each_cpu(cpu) { | ||
1156 | if (size <= PAGE_SIZE) | ||
1157 | newinfo->entries[cpu] = kmalloc_node(size, | ||
1158 | GFP_KERNEL, | ||
1159 | cpu_to_node(cpu)); | ||
1160 | else | ||
1161 | newinfo->entries[cpu] = vmalloc_node(size, cpu_to_node(cpu)); | ||
1162 | if (newinfo->entries[cpu] == 0) { | ||
1163 | free_table_info(newinfo); | ||
1164 | return NULL; | ||
1165 | } | ||
1166 | } | ||
1167 | |||
1168 | return newinfo; | ||
1169 | } | ||
1170 | |||
1171 | static int | 907 | static int |
1172 | do_replace(void __user *user, unsigned int len) | 908 | do_replace(void __user *user, unsigned int len) |
1173 | { | 909 | { |
1174 | int ret; | 910 | int ret; |
1175 | struct ipt_replace tmp; | 911 | struct ipt_replace tmp; |
1176 | struct ipt_table *t; | 912 | struct ipt_table *t; |
1177 | struct ipt_table_info *newinfo, *oldinfo; | 913 | struct xt_table_info *newinfo, *oldinfo; |
1178 | struct ipt_counters *counters; | 914 | struct xt_counters *counters; |
1179 | void *loc_cpu_entry, *loc_cpu_old_entry; | 915 | void *loc_cpu_entry, *loc_cpu_old_entry; |
1180 | 916 | ||
1181 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 917 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
@@ -1185,11 +921,7 @@ do_replace(void __user *user, unsigned int len) | |||
1185 | if (len != sizeof(tmp) + tmp.size) | 921 | if (len != sizeof(tmp) + tmp.size) |
1186 | return -ENOPROTOOPT; | 922 | return -ENOPROTOOPT; |
1187 | 923 | ||
1188 | /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ | 924 | newinfo = xt_alloc_table_info(tmp.size); |
1189 | if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) | ||
1190 | return -ENOMEM; | ||
1191 | |||
1192 | newinfo = alloc_table_info(tmp.size); | ||
1193 | if (!newinfo) | 925 | if (!newinfo) |
1194 | return -ENOMEM; | 926 | return -ENOMEM; |
1195 | 927 | ||
@@ -1201,7 +933,7 @@ do_replace(void __user *user, unsigned int len) | |||
1201 | goto free_newinfo; | 933 | goto free_newinfo; |
1202 | } | 934 | } |
1203 | 935 | ||
1204 | counters = vmalloc(tmp.num_counters * sizeof(struct ipt_counters)); | 936 | counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); |
1205 | if (!counters) { | 937 | if (!counters) { |
1206 | ret = -ENOMEM; | 938 | ret = -ENOMEM; |
1207 | goto free_newinfo; | 939 | goto free_newinfo; |
@@ -1215,7 +947,7 @@ do_replace(void __user *user, unsigned int len) | |||
1215 | 947 | ||
1216 | duprintf("ip_tables: Translated table\n"); | 948 | duprintf("ip_tables: Translated table\n"); |
1217 | 949 | ||
1218 | t = try_then_request_module(find_table_lock(tmp.name), | 950 | t = try_then_request_module(xt_find_table_lock(AF_INET, tmp.name), |
1219 | "iptable_%s", tmp.name); | 951 | "iptable_%s", tmp.name); |
1220 | if (!t || IS_ERR(t)) { | 952 | if (!t || IS_ERR(t)) { |
1221 | ret = t ? PTR_ERR(t) : -ENOENT; | 953 | ret = t ? PTR_ERR(t) : -ENOENT; |
@@ -1230,7 +962,7 @@ do_replace(void __user *user, unsigned int len) | |||
1230 | goto put_module; | 962 | goto put_module; |
1231 | } | 963 | } |
1232 | 964 | ||
1233 | oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); | 965 | oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); |
1234 | if (!oldinfo) | 966 | if (!oldinfo) |
1235 | goto put_module; | 967 | goto put_module; |
1236 | 968 | ||
@@ -1249,23 +981,23 @@ do_replace(void __user *user, unsigned int len) | |||
1249 | /* Decrease module usage counts and free resource */ | 981 | /* Decrease module usage counts and free resource */ |
1250 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | 982 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; |
1251 | IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); | 983 | IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); |
1252 | free_table_info(oldinfo); | 984 | xt_free_table_info(oldinfo); |
1253 | if (copy_to_user(tmp.counters, counters, | 985 | if (copy_to_user(tmp.counters, counters, |
1254 | sizeof(struct ipt_counters) * tmp.num_counters) != 0) | 986 | sizeof(struct xt_counters) * tmp.num_counters) != 0) |
1255 | ret = -EFAULT; | 987 | ret = -EFAULT; |
1256 | vfree(counters); | 988 | vfree(counters); |
1257 | up(&ipt_mutex); | 989 | xt_table_unlock(t); |
1258 | return ret; | 990 | return ret; |
1259 | 991 | ||
1260 | put_module: | 992 | put_module: |
1261 | module_put(t->me); | 993 | module_put(t->me); |
1262 | up(&ipt_mutex); | 994 | xt_table_unlock(t); |
1263 | free_newinfo_counters_untrans: | 995 | free_newinfo_counters_untrans: |
1264 | IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); | 996 | IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); |
1265 | free_newinfo_counters: | 997 | free_newinfo_counters: |
1266 | vfree(counters); | 998 | vfree(counters); |
1267 | free_newinfo: | 999 | free_newinfo: |
1268 | free_table_info(newinfo); | 1000 | xt_free_table_info(newinfo); |
1269 | return ret; | 1001 | return ret; |
1270 | } | 1002 | } |
1271 | 1003 | ||
@@ -1273,7 +1005,7 @@ do_replace(void __user *user, unsigned int len) | |||
1273 | * and everything is OK. */ | 1005 | * and everything is OK. */ |
1274 | static inline int | 1006 | static inline int |
1275 | add_counter_to_entry(struct ipt_entry *e, | 1007 | add_counter_to_entry(struct ipt_entry *e, |
1276 | const struct ipt_counters addme[], | 1008 | const struct xt_counters addme[], |
1277 | unsigned int *i) | 1009 | unsigned int *i) |
1278 | { | 1010 | { |
1279 | #if 0 | 1011 | #if 0 |
@@ -1295,15 +1027,16 @@ static int | |||
1295 | do_add_counters(void __user *user, unsigned int len) | 1027 | do_add_counters(void __user *user, unsigned int len) |
1296 | { | 1028 | { |
1297 | unsigned int i; | 1029 | unsigned int i; |
1298 | struct ipt_counters_info tmp, *paddc; | 1030 | struct xt_counters_info tmp, *paddc; |
1299 | struct ipt_table *t; | 1031 | struct ipt_table *t; |
1032 | struct xt_table_info *private; | ||
1300 | int ret = 0; | 1033 | int ret = 0; |
1301 | void *loc_cpu_entry; | 1034 | void *loc_cpu_entry; |
1302 | 1035 | ||
1303 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 1036 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
1304 | return -EFAULT; | 1037 | return -EFAULT; |
1305 | 1038 | ||
1306 | if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ipt_counters)) | 1039 | if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) |
1307 | return -EINVAL; | 1040 | return -EINVAL; |
1308 | 1041 | ||
1309 | paddc = vmalloc_node(len, numa_node_id()); | 1042 | paddc = vmalloc_node(len, numa_node_id()); |
@@ -1315,29 +1048,30 @@ do_add_counters(void __user *user, unsigned int len) | |||
1315 | goto free; | 1048 | goto free; |
1316 | } | 1049 | } |
1317 | 1050 | ||
1318 | t = find_table_lock(tmp.name); | 1051 | t = xt_find_table_lock(AF_INET, tmp.name); |
1319 | if (!t || IS_ERR(t)) { | 1052 | if (!t || IS_ERR(t)) { |
1320 | ret = t ? PTR_ERR(t) : -ENOENT; | 1053 | ret = t ? PTR_ERR(t) : -ENOENT; |
1321 | goto free; | 1054 | goto free; |
1322 | } | 1055 | } |
1323 | 1056 | ||
1324 | write_lock_bh(&t->lock); | 1057 | write_lock_bh(&t->lock); |
1325 | if (t->private->number != paddc->num_counters) { | 1058 | private = t->private; |
1059 | if (private->number != paddc->num_counters) { | ||
1326 | ret = -EINVAL; | 1060 | ret = -EINVAL; |
1327 | goto unlock_up_free; | 1061 | goto unlock_up_free; |
1328 | } | 1062 | } |
1329 | 1063 | ||
1330 | i = 0; | 1064 | i = 0; |
1331 | /* Choose the copy that is on our node */ | 1065 | /* Choose the copy that is on our node */ |
1332 | loc_cpu_entry = t->private->entries[raw_smp_processor_id()]; | 1066 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
1333 | IPT_ENTRY_ITERATE(loc_cpu_entry, | 1067 | IPT_ENTRY_ITERATE(loc_cpu_entry, |
1334 | t->private->size, | 1068 | private->size, |
1335 | add_counter_to_entry, | 1069 | add_counter_to_entry, |
1336 | paddc->counters, | 1070 | paddc->counters, |
1337 | &i); | 1071 | &i); |
1338 | unlock_up_free: | 1072 | unlock_up_free: |
1339 | write_unlock_bh(&t->lock); | 1073 | write_unlock_bh(&t->lock); |
1340 | up(&ipt_mutex); | 1074 | xt_table_unlock(t); |
1341 | module_put(t->me); | 1075 | module_put(t->me); |
1342 | free: | 1076 | free: |
1343 | vfree(paddc); | 1077 | vfree(paddc); |
@@ -1396,25 +1130,26 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1396 | } | 1130 | } |
1397 | name[IPT_TABLE_MAXNAMELEN-1] = '\0'; | 1131 | name[IPT_TABLE_MAXNAMELEN-1] = '\0'; |
1398 | 1132 | ||
1399 | t = try_then_request_module(find_table_lock(name), | 1133 | t = try_then_request_module(xt_find_table_lock(AF_INET, name), |
1400 | "iptable_%s", name); | 1134 | "iptable_%s", name); |
1401 | if (t && !IS_ERR(t)) { | 1135 | if (t && !IS_ERR(t)) { |
1402 | struct ipt_getinfo info; | 1136 | struct ipt_getinfo info; |
1137 | struct xt_table_info *private = t->private; | ||
1403 | 1138 | ||
1404 | info.valid_hooks = t->valid_hooks; | 1139 | info.valid_hooks = t->valid_hooks; |
1405 | memcpy(info.hook_entry, t->private->hook_entry, | 1140 | memcpy(info.hook_entry, private->hook_entry, |
1406 | sizeof(info.hook_entry)); | 1141 | sizeof(info.hook_entry)); |
1407 | memcpy(info.underflow, t->private->underflow, | 1142 | memcpy(info.underflow, private->underflow, |
1408 | sizeof(info.underflow)); | 1143 | sizeof(info.underflow)); |
1409 | info.num_entries = t->private->number; | 1144 | info.num_entries = private->number; |
1410 | info.size = t->private->size; | 1145 | info.size = private->size; |
1411 | memcpy(info.name, name, sizeof(info.name)); | 1146 | memcpy(info.name, name, sizeof(info.name)); |
1412 | 1147 | ||
1413 | if (copy_to_user(user, &info, *len) != 0) | 1148 | if (copy_to_user(user, &info, *len) != 0) |
1414 | ret = -EFAULT; | 1149 | ret = -EFAULT; |
1415 | else | 1150 | else |
1416 | ret = 0; | 1151 | ret = 0; |
1417 | up(&ipt_mutex); | 1152 | xt_table_unlock(t); |
1418 | module_put(t->me); | 1153 | module_put(t->me); |
1419 | } else | 1154 | } else |
1420 | ret = t ? PTR_ERR(t) : -ENOENT; | 1155 | ret = t ? PTR_ERR(t) : -ENOENT; |
@@ -1441,7 +1176,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1441 | case IPT_SO_GET_REVISION_MATCH: | 1176 | case IPT_SO_GET_REVISION_MATCH: |
1442 | case IPT_SO_GET_REVISION_TARGET: { | 1177 | case IPT_SO_GET_REVISION_TARGET: { |
1443 | struct ipt_get_revision rev; | 1178 | struct ipt_get_revision rev; |
1444 | int (*revfn)(const char *, u8, int *); | 1179 | int target; |
1445 | 1180 | ||
1446 | if (*len != sizeof(rev)) { | 1181 | if (*len != sizeof(rev)) { |
1447 | ret = -EINVAL; | 1182 | ret = -EINVAL; |
@@ -1453,12 +1188,13 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1453 | } | 1188 | } |
1454 | 1189 | ||
1455 | if (cmd == IPT_SO_GET_REVISION_TARGET) | 1190 | if (cmd == IPT_SO_GET_REVISION_TARGET) |
1456 | revfn = target_revfn; | 1191 | target = 1; |
1457 | else | 1192 | else |
1458 | revfn = match_revfn; | 1193 | target = 0; |
1459 | 1194 | ||
1460 | try_then_request_module(find_revision(rev.name, rev.revision, | 1195 | try_then_request_module(xt_find_revision(AF_INET, rev.name, |
1461 | revfn, &ret), | 1196 | rev.revision, |
1197 | target, &ret), | ||
1462 | "ipt_%s", rev.name); | 1198 | "ipt_%s", rev.name); |
1463 | break; | 1199 | break; |
1464 | } | 1200 | } |
@@ -1471,60 +1207,15 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1471 | return ret; | 1207 | return ret; |
1472 | } | 1208 | } |
1473 | 1209 | ||
1474 | /* Registration hooks for targets. */ | 1210 | int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl) |
1475 | int | ||
1476 | ipt_register_target(struct ipt_target *target) | ||
1477 | { | 1211 | { |
1478 | int ret; | 1212 | int ret; |
1479 | 1213 | struct xt_table_info *newinfo; | |
1480 | ret = down_interruptible(&ipt_mutex); | 1214 | static struct xt_table_info bootstrap |
1481 | if (ret != 0) | ||
1482 | return ret; | ||
1483 | list_add(&target->list, &ipt_target); | ||
1484 | up(&ipt_mutex); | ||
1485 | return ret; | ||
1486 | } | ||
1487 | |||
1488 | void | ||
1489 | ipt_unregister_target(struct ipt_target *target) | ||
1490 | { | ||
1491 | down(&ipt_mutex); | ||
1492 | LIST_DELETE(&ipt_target, target); | ||
1493 | up(&ipt_mutex); | ||
1494 | } | ||
1495 | |||
1496 | int | ||
1497 | ipt_register_match(struct ipt_match *match) | ||
1498 | { | ||
1499 | int ret; | ||
1500 | |||
1501 | ret = down_interruptible(&ipt_mutex); | ||
1502 | if (ret != 0) | ||
1503 | return ret; | ||
1504 | |||
1505 | list_add(&match->list, &ipt_match); | ||
1506 | up(&ipt_mutex); | ||
1507 | |||
1508 | return ret; | ||
1509 | } | ||
1510 | |||
1511 | void | ||
1512 | ipt_unregister_match(struct ipt_match *match) | ||
1513 | { | ||
1514 | down(&ipt_mutex); | ||
1515 | LIST_DELETE(&ipt_match, match); | ||
1516 | up(&ipt_mutex); | ||
1517 | } | ||
1518 | |||
1519 | int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl) | ||
1520 | { | ||
1521 | int ret; | ||
1522 | struct ipt_table_info *newinfo; | ||
1523 | static struct ipt_table_info bootstrap | ||
1524 | = { 0, 0, 0, { 0 }, { 0 }, { } }; | 1215 | = { 0, 0, 0, { 0 }, { 0 }, { } }; |
1525 | void *loc_cpu_entry; | 1216 | void *loc_cpu_entry; |
1526 | 1217 | ||
1527 | newinfo = alloc_table_info(repl->size); | 1218 | newinfo = xt_alloc_table_info(repl->size); |
1528 | if (!newinfo) | 1219 | if (!newinfo) |
1529 | return -ENOMEM; | 1220 | return -ENOMEM; |
1530 | 1221 | ||
@@ -1540,246 +1231,29 @@ int ipt_register_table(struct ipt_table *table, const struct ipt_replace *repl) | |||
1540 | repl->hook_entry, | 1231 | repl->hook_entry, |
1541 | repl->underflow); | 1232 | repl->underflow); |
1542 | if (ret != 0) { | 1233 | if (ret != 0) { |
1543 | free_table_info(newinfo); | 1234 | xt_free_table_info(newinfo); |
1544 | return ret; | 1235 | return ret; |
1545 | } | 1236 | } |
1546 | 1237 | ||
1547 | ret = down_interruptible(&ipt_mutex); | 1238 | if (xt_register_table(table, &bootstrap, newinfo) != 0) { |
1548 | if (ret != 0) { | 1239 | xt_free_table_info(newinfo); |
1549 | free_table_info(newinfo); | ||
1550 | return ret; | 1240 | return ret; |
1551 | } | 1241 | } |
1552 | 1242 | ||
1553 | /* Don't autoload: we'd eat our tail... */ | 1243 | return 0; |
1554 | if (list_named_find(&ipt_tables, table->name)) { | ||
1555 | ret = -EEXIST; | ||
1556 | goto free_unlock; | ||
1557 | } | ||
1558 | |||
1559 | /* Simplifies replace_table code. */ | ||
1560 | table->private = &bootstrap; | ||
1561 | if (!replace_table(table, 0, newinfo, &ret)) | ||
1562 | goto free_unlock; | ||
1563 | |||
1564 | duprintf("table->private->number = %u\n", | ||
1565 | table->private->number); | ||
1566 | |||
1567 | /* save number of initial entries */ | ||
1568 | table->private->initial_entries = table->private->number; | ||
1569 | |||
1570 | rwlock_init(&table->lock); | ||
1571 | list_prepend(&ipt_tables, table); | ||
1572 | |||
1573 | unlock: | ||
1574 | up(&ipt_mutex); | ||
1575 | return ret; | ||
1576 | |||
1577 | free_unlock: | ||
1578 | free_table_info(newinfo); | ||
1579 | goto unlock; | ||
1580 | } | 1244 | } |
1581 | 1245 | ||
1582 | void ipt_unregister_table(struct ipt_table *table) | 1246 | void ipt_unregister_table(struct ipt_table *table) |
1583 | { | 1247 | { |
1248 | struct xt_table_info *private; | ||
1584 | void *loc_cpu_entry; | 1249 | void *loc_cpu_entry; |
1585 | 1250 | ||
1586 | down(&ipt_mutex); | 1251 | private = xt_unregister_table(table); |
1587 | LIST_DELETE(&ipt_tables, table); | ||
1588 | up(&ipt_mutex); | ||
1589 | 1252 | ||
1590 | /* Decrease module usage counts and free resources */ | 1253 | /* Decrease module usage counts and free resources */ |
1591 | loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; | 1254 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
1592 | IPT_ENTRY_ITERATE(loc_cpu_entry, table->private->size, | 1255 | IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); |
1593 | cleanup_entry, NULL); | 1256 | xt_free_table_info(private); |
1594 | free_table_info(table->private); | ||
1595 | } | ||
1596 | |||
1597 | /* Returns 1 if the port is matched by the range, 0 otherwise */ | ||
1598 | static inline int | ||
1599 | port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) | ||
1600 | { | ||
1601 | int ret; | ||
1602 | |||
1603 | ret = (port >= min && port <= max) ^ invert; | ||
1604 | return ret; | ||
1605 | } | ||
1606 | |||
1607 | static int | ||
1608 | tcp_find_option(u_int8_t option, | ||
1609 | const struct sk_buff *skb, | ||
1610 | unsigned int optlen, | ||
1611 | int invert, | ||
1612 | int *hotdrop) | ||
1613 | { | ||
1614 | /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ | ||
1615 | u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; | ||
1616 | unsigned int i; | ||
1617 | |||
1618 | duprintf("tcp_match: finding option\n"); | ||
1619 | |||
1620 | if (!optlen) | ||
1621 | return invert; | ||
1622 | |||
1623 | /* If we don't have the whole header, drop packet. */ | ||
1624 | op = skb_header_pointer(skb, | ||
1625 | skb->nh.iph->ihl*4 + sizeof(struct tcphdr), | ||
1626 | optlen, _opt); | ||
1627 | if (op == NULL) { | ||
1628 | *hotdrop = 1; | ||
1629 | return 0; | ||
1630 | } | ||
1631 | |||
1632 | for (i = 0; i < optlen; ) { | ||
1633 | if (op[i] == option) return !invert; | ||
1634 | if (op[i] < 2) i++; | ||
1635 | else i += op[i+1]?:1; | ||
1636 | } | ||
1637 | |||
1638 | return invert; | ||
1639 | } | ||
1640 | |||
1641 | static int | ||
1642 | tcp_match(const struct sk_buff *skb, | ||
1643 | const struct net_device *in, | ||
1644 | const struct net_device *out, | ||
1645 | const void *matchinfo, | ||
1646 | int offset, | ||
1647 | int *hotdrop) | ||
1648 | { | ||
1649 | struct tcphdr _tcph, *th; | ||
1650 | const struct ipt_tcp *tcpinfo = matchinfo; | ||
1651 | |||
1652 | if (offset) { | ||
1653 | /* To quote Alan: | ||
1654 | |||
1655 | Don't allow a fragment of TCP 8 bytes in. Nobody normal | ||
1656 | causes this. Its a cracker trying to break in by doing a | ||
1657 | flag overwrite to pass the direction checks. | ||
1658 | */ | ||
1659 | if (offset == 1) { | ||
1660 | duprintf("Dropping evil TCP offset=1 frag.\n"); | ||
1661 | *hotdrop = 1; | ||
1662 | } | ||
1663 | /* Must not be a fragment. */ | ||
1664 | return 0; | ||
1665 | } | ||
1666 | |||
1667 | #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) | ||
1668 | |||
1669 | th = skb_header_pointer(skb, skb->nh.iph->ihl*4, | ||
1670 | sizeof(_tcph), &_tcph); | ||
1671 | if (th == NULL) { | ||
1672 | /* We've been asked to examine this packet, and we | ||
1673 | can't. Hence, no choice but to drop. */ | ||
1674 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); | ||
1675 | *hotdrop = 1; | ||
1676 | return 0; | ||
1677 | } | ||
1678 | |||
1679 | if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], | ||
1680 | ntohs(th->source), | ||
1681 | !!(tcpinfo->invflags & IPT_TCP_INV_SRCPT))) | ||
1682 | return 0; | ||
1683 | if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], | ||
1684 | ntohs(th->dest), | ||
1685 | !!(tcpinfo->invflags & IPT_TCP_INV_DSTPT))) | ||
1686 | return 0; | ||
1687 | if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) | ||
1688 | == tcpinfo->flg_cmp, | ||
1689 | IPT_TCP_INV_FLAGS)) | ||
1690 | return 0; | ||
1691 | if (tcpinfo->option) { | ||
1692 | if (th->doff * 4 < sizeof(_tcph)) { | ||
1693 | *hotdrop = 1; | ||
1694 | return 0; | ||
1695 | } | ||
1696 | if (!tcp_find_option(tcpinfo->option, skb, | ||
1697 | th->doff*4 - sizeof(_tcph), | ||
1698 | tcpinfo->invflags & IPT_TCP_INV_OPTION, | ||
1699 | hotdrop)) | ||
1700 | return 0; | ||
1701 | } | ||
1702 | return 1; | ||
1703 | } | ||
1704 | |||
1705 | /* Called when user tries to insert an entry of this type. */ | ||
1706 | static int | ||
1707 | tcp_checkentry(const char *tablename, | ||
1708 | const struct ipt_ip *ip, | ||
1709 | void *matchinfo, | ||
1710 | unsigned int matchsize, | ||
1711 | unsigned int hook_mask) | ||
1712 | { | ||
1713 | const struct ipt_tcp *tcpinfo = matchinfo; | ||
1714 | |||
1715 | /* Must specify proto == TCP, and no unknown invflags */ | ||
1716 | return ip->proto == IPPROTO_TCP | ||
1717 | && !(ip->invflags & IPT_INV_PROTO) | ||
1718 | && matchsize == IPT_ALIGN(sizeof(struct ipt_tcp)) | ||
1719 | && !(tcpinfo->invflags & ~IPT_TCP_INV_MASK); | ||
1720 | } | ||
1721 | |||
1722 | static int | ||
1723 | udp_match(const struct sk_buff *skb, | ||
1724 | const struct net_device *in, | ||
1725 | const struct net_device *out, | ||
1726 | const void *matchinfo, | ||
1727 | int offset, | ||
1728 | int *hotdrop) | ||
1729 | { | ||
1730 | struct udphdr _udph, *uh; | ||
1731 | const struct ipt_udp *udpinfo = matchinfo; | ||
1732 | |||
1733 | /* Must not be a fragment. */ | ||
1734 | if (offset) | ||
1735 | return 0; | ||
1736 | |||
1737 | uh = skb_header_pointer(skb, skb->nh.iph->ihl*4, | ||
1738 | sizeof(_udph), &_udph); | ||
1739 | if (uh == NULL) { | ||
1740 | /* We've been asked to examine this packet, and we | ||
1741 | can't. Hence, no choice but to drop. */ | ||
1742 | duprintf("Dropping evil UDP tinygram.\n"); | ||
1743 | *hotdrop = 1; | ||
1744 | return 0; | ||
1745 | } | ||
1746 | |||
1747 | return port_match(udpinfo->spts[0], udpinfo->spts[1], | ||
1748 | ntohs(uh->source), | ||
1749 | !!(udpinfo->invflags & IPT_UDP_INV_SRCPT)) | ||
1750 | && port_match(udpinfo->dpts[0], udpinfo->dpts[1], | ||
1751 | ntohs(uh->dest), | ||
1752 | !!(udpinfo->invflags & IPT_UDP_INV_DSTPT)); | ||
1753 | } | ||
1754 | |||
1755 | /* Called when user tries to insert an entry of this type. */ | ||
1756 | static int | ||
1757 | udp_checkentry(const char *tablename, | ||
1758 | const struct ipt_ip *ip, | ||
1759 | void *matchinfo, | ||
1760 | unsigned int matchinfosize, | ||
1761 | unsigned int hook_mask) | ||
1762 | { | ||
1763 | const struct ipt_udp *udpinfo = matchinfo; | ||
1764 | |||
1765 | /* Must specify proto == UDP, and no unknown invflags */ | ||
1766 | if (ip->proto != IPPROTO_UDP || (ip->invflags & IPT_INV_PROTO)) { | ||
1767 | duprintf("ipt_udp: Protocol %u != %u\n", ip->proto, | ||
1768 | IPPROTO_UDP); | ||
1769 | return 0; | ||
1770 | } | ||
1771 | if (matchinfosize != IPT_ALIGN(sizeof(struct ipt_udp))) { | ||
1772 | duprintf("ipt_udp: matchsize %u != %u\n", | ||
1773 | matchinfosize, IPT_ALIGN(sizeof(struct ipt_udp))); | ||
1774 | return 0; | ||
1775 | } | ||
1776 | if (udpinfo->invflags & ~IPT_UDP_INV_MASK) { | ||
1777 | duprintf("ipt_udp: unknown flags %X\n", | ||
1778 | udpinfo->invflags); | ||
1779 | return 0; | ||
1780 | } | ||
1781 | |||
1782 | return 1; | ||
1783 | } | 1257 | } |
1784 | 1258 | ||
1785 | /* Returns 1 if the type and code is matched by the range, 0 otherwise */ | 1259 | /* Returns 1 if the type and code is matched by the range, 0 otherwise */ |
@@ -1798,6 +1272,7 @@ icmp_match(const struct sk_buff *skb, | |||
1798 | const struct net_device *out, | 1272 | const struct net_device *out, |
1799 | const void *matchinfo, | 1273 | const void *matchinfo, |
1800 | int offset, | 1274 | int offset, |
1275 | unsigned int protoff, | ||
1801 | int *hotdrop) | 1276 | int *hotdrop) |
1802 | { | 1277 | { |
1803 | struct icmphdr _icmph, *ic; | 1278 | struct icmphdr _icmph, *ic; |
@@ -1807,8 +1282,7 @@ icmp_match(const struct sk_buff *skb, | |||
1807 | if (offset) | 1282 | if (offset) |
1808 | return 0; | 1283 | return 0; |
1809 | 1284 | ||
1810 | ic = skb_header_pointer(skb, skb->nh.iph->ihl*4, | 1285 | ic = skb_header_pointer(skb, protoff, sizeof(_icmph), &_icmph); |
1811 | sizeof(_icmph), &_icmph); | ||
1812 | if (ic == NULL) { | 1286 | if (ic == NULL) { |
1813 | /* We've been asked to examine this packet, and we | 1287 | /* We've been asked to examine this packet, and we |
1814 | * can't. Hence, no choice but to drop. | 1288 | * can't. Hence, no choice but to drop. |
@@ -1828,11 +1302,12 @@ icmp_match(const struct sk_buff *skb, | |||
1828 | /* Called when user tries to insert an entry of this type. */ | 1302 | /* Called when user tries to insert an entry of this type. */ |
1829 | static int | 1303 | static int |
1830 | icmp_checkentry(const char *tablename, | 1304 | icmp_checkentry(const char *tablename, |
1831 | const struct ipt_ip *ip, | 1305 | const void *info, |
1832 | void *matchinfo, | 1306 | void *matchinfo, |
1833 | unsigned int matchsize, | 1307 | unsigned int matchsize, |
1834 | unsigned int hook_mask) | 1308 | unsigned int hook_mask) |
1835 | { | 1309 | { |
1310 | const struct ipt_ip *ip = info; | ||
1836 | const struct ipt_icmp *icmpinfo = matchinfo; | 1311 | const struct ipt_icmp *icmpinfo = matchinfo; |
1837 | 1312 | ||
1838 | /* Must specify proto == ICMP, and no unknown invflags */ | 1313 | /* Must specify proto == ICMP, and no unknown invflags */ |
@@ -1862,123 +1337,22 @@ static struct nf_sockopt_ops ipt_sockopts = { | |||
1862 | .get = do_ipt_get_ctl, | 1337 | .get = do_ipt_get_ctl, |
1863 | }; | 1338 | }; |
1864 | 1339 | ||
1865 | static struct ipt_match tcp_matchstruct = { | ||
1866 | .name = "tcp", | ||
1867 | .match = &tcp_match, | ||
1868 | .checkentry = &tcp_checkentry, | ||
1869 | }; | ||
1870 | |||
1871 | static struct ipt_match udp_matchstruct = { | ||
1872 | .name = "udp", | ||
1873 | .match = &udp_match, | ||
1874 | .checkentry = &udp_checkentry, | ||
1875 | }; | ||
1876 | |||
1877 | static struct ipt_match icmp_matchstruct = { | 1340 | static struct ipt_match icmp_matchstruct = { |
1878 | .name = "icmp", | 1341 | .name = "icmp", |
1879 | .match = &icmp_match, | 1342 | .match = &icmp_match, |
1880 | .checkentry = &icmp_checkentry, | 1343 | .checkentry = &icmp_checkentry, |
1881 | }; | 1344 | }; |
1882 | 1345 | ||
1883 | #ifdef CONFIG_PROC_FS | ||
1884 | static inline int print_name(const char *i, | ||
1885 | off_t start_offset, char *buffer, int length, | ||
1886 | off_t *pos, unsigned int *count) | ||
1887 | { | ||
1888 | if ((*count)++ >= start_offset) { | ||
1889 | unsigned int namelen; | ||
1890 | |||
1891 | namelen = sprintf(buffer + *pos, "%s\n", | ||
1892 | i + sizeof(struct list_head)); | ||
1893 | if (*pos + namelen > length) { | ||
1894 | /* Stop iterating */ | ||
1895 | return 1; | ||
1896 | } | ||
1897 | *pos += namelen; | ||
1898 | } | ||
1899 | return 0; | ||
1900 | } | ||
1901 | |||
1902 | static inline int print_target(const struct ipt_target *t, | ||
1903 | off_t start_offset, char *buffer, int length, | ||
1904 | off_t *pos, unsigned int *count) | ||
1905 | { | ||
1906 | if (t == &ipt_standard_target || t == &ipt_error_target) | ||
1907 | return 0; | ||
1908 | return print_name((char *)t, start_offset, buffer, length, pos, count); | ||
1909 | } | ||
1910 | |||
1911 | static int ipt_get_tables(char *buffer, char **start, off_t offset, int length) | ||
1912 | { | ||
1913 | off_t pos = 0; | ||
1914 | unsigned int count = 0; | ||
1915 | |||
1916 | if (down_interruptible(&ipt_mutex) != 0) | ||
1917 | return 0; | ||
1918 | |||
1919 | LIST_FIND(&ipt_tables, print_name, void *, | ||
1920 | offset, buffer, length, &pos, &count); | ||
1921 | |||
1922 | up(&ipt_mutex); | ||
1923 | |||
1924 | /* `start' hack - see fs/proc/generic.c line ~105 */ | ||
1925 | *start=(char *)((unsigned long)count-offset); | ||
1926 | return pos; | ||
1927 | } | ||
1928 | |||
1929 | static int ipt_get_targets(char *buffer, char **start, off_t offset, int length) | ||
1930 | { | ||
1931 | off_t pos = 0; | ||
1932 | unsigned int count = 0; | ||
1933 | |||
1934 | if (down_interruptible(&ipt_mutex) != 0) | ||
1935 | return 0; | ||
1936 | |||
1937 | LIST_FIND(&ipt_target, print_target, struct ipt_target *, | ||
1938 | offset, buffer, length, &pos, &count); | ||
1939 | |||
1940 | up(&ipt_mutex); | ||
1941 | |||
1942 | *start = (char *)((unsigned long)count - offset); | ||
1943 | return pos; | ||
1944 | } | ||
1945 | |||
1946 | static int ipt_get_matches(char *buffer, char **start, off_t offset, int length) | ||
1947 | { | ||
1948 | off_t pos = 0; | ||
1949 | unsigned int count = 0; | ||
1950 | |||
1951 | if (down_interruptible(&ipt_mutex) != 0) | ||
1952 | return 0; | ||
1953 | |||
1954 | LIST_FIND(&ipt_match, print_name, void *, | ||
1955 | offset, buffer, length, &pos, &count); | ||
1956 | |||
1957 | up(&ipt_mutex); | ||
1958 | |||
1959 | *start = (char *)((unsigned long)count - offset); | ||
1960 | return pos; | ||
1961 | } | ||
1962 | |||
1963 | static const struct { char *name; get_info_t *get_info; } ipt_proc_entry[] = | ||
1964 | { { "ip_tables_names", ipt_get_tables }, | ||
1965 | { "ip_tables_targets", ipt_get_targets }, | ||
1966 | { "ip_tables_matches", ipt_get_matches }, | ||
1967 | { NULL, NULL} }; | ||
1968 | #endif /*CONFIG_PROC_FS*/ | ||
1969 | |||
1970 | static int __init init(void) | 1346 | static int __init init(void) |
1971 | { | 1347 | { |
1972 | int ret; | 1348 | int ret; |
1973 | 1349 | ||
1350 | xt_proto_init(AF_INET); | ||
1351 | |||
1974 | /* Noone else will be downing sem now, so we won't sleep */ | 1352 | /* Noone else will be downing sem now, so we won't sleep */ |
1975 | down(&ipt_mutex); | 1353 | xt_register_target(AF_INET, &ipt_standard_target); |
1976 | list_append(&ipt_target, &ipt_standard_target); | 1354 | xt_register_target(AF_INET, &ipt_error_target); |
1977 | list_append(&ipt_target, &ipt_error_target); | 1355 | xt_register_match(AF_INET, &icmp_matchstruct); |
1978 | list_append(&ipt_match, &tcp_matchstruct); | ||
1979 | list_append(&ipt_match, &udp_matchstruct); | ||
1980 | list_append(&ipt_match, &icmp_matchstruct); | ||
1981 | up(&ipt_mutex); | ||
1982 | 1356 | ||
1983 | /* Register setsockopt */ | 1357 | /* Register setsockopt */ |
1984 | ret = nf_register_sockopt(&ipt_sockopts); | 1358 | ret = nf_register_sockopt(&ipt_sockopts); |
@@ -1987,49 +1361,23 @@ static int __init init(void) | |||
1987 | return ret; | 1361 | return ret; |
1988 | } | 1362 | } |
1989 | 1363 | ||
1990 | #ifdef CONFIG_PROC_FS | 1364 | printk("ip_tables: (C) 2000-2006 Netfilter Core Team\n"); |
1991 | { | ||
1992 | struct proc_dir_entry *proc; | ||
1993 | int i; | ||
1994 | |||
1995 | for (i = 0; ipt_proc_entry[i].name; i++) { | ||
1996 | proc = proc_net_create(ipt_proc_entry[i].name, 0, | ||
1997 | ipt_proc_entry[i].get_info); | ||
1998 | if (!proc) { | ||
1999 | while (--i >= 0) | ||
2000 | proc_net_remove(ipt_proc_entry[i].name); | ||
2001 | nf_unregister_sockopt(&ipt_sockopts); | ||
2002 | return -ENOMEM; | ||
2003 | } | ||
2004 | proc->owner = THIS_MODULE; | ||
2005 | } | ||
2006 | } | ||
2007 | #endif | ||
2008 | |||
2009 | printk("ip_tables: (C) 2000-2002 Netfilter core team\n"); | ||
2010 | return 0; | 1365 | return 0; |
2011 | } | 1366 | } |
2012 | 1367 | ||
2013 | static void __exit fini(void) | 1368 | static void __exit fini(void) |
2014 | { | 1369 | { |
2015 | nf_unregister_sockopt(&ipt_sockopts); | 1370 | nf_unregister_sockopt(&ipt_sockopts); |
2016 | #ifdef CONFIG_PROC_FS | 1371 | |
2017 | { | 1372 | xt_unregister_match(AF_INET, &icmp_matchstruct); |
2018 | int i; | 1373 | xt_unregister_target(AF_INET, &ipt_error_target); |
2019 | for (i = 0; ipt_proc_entry[i].name; i++) | 1374 | xt_unregister_target(AF_INET, &ipt_standard_target); |
2020 | proc_net_remove(ipt_proc_entry[i].name); | 1375 | |
2021 | } | 1376 | xt_proto_fini(AF_INET); |
2022 | #endif | ||
2023 | } | 1377 | } |
2024 | 1378 | ||
2025 | EXPORT_SYMBOL(ipt_register_table); | 1379 | EXPORT_SYMBOL(ipt_register_table); |
2026 | EXPORT_SYMBOL(ipt_unregister_table); | 1380 | EXPORT_SYMBOL(ipt_unregister_table); |
2027 | EXPORT_SYMBOL(ipt_register_match); | ||
2028 | EXPORT_SYMBOL(ipt_unregister_match); | ||
2029 | EXPORT_SYMBOL(ipt_do_table); | 1381 | EXPORT_SYMBOL(ipt_do_table); |
2030 | EXPORT_SYMBOL(ipt_register_target); | ||
2031 | EXPORT_SYMBOL(ipt_unregister_target); | ||
2032 | EXPORT_SYMBOL(ipt_find_target); | ||
2033 | |||
2034 | module_init(init); | 1382 | module_init(init); |
2035 | module_exit(fini); | 1383 | module_exit(fini); |
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c index 45c52d8f4d99..d9bc971f03af 100644 --- a/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c | |||
@@ -379,12 +379,13 @@ target(struct sk_buff **pskb, | |||
379 | 379 | ||
380 | static int | 380 | static int |
381 | checkentry(const char *tablename, | 381 | checkentry(const char *tablename, |
382 | const struct ipt_entry *e, | 382 | const void *e_void, |
383 | void *targinfo, | 383 | void *targinfo, |
384 | unsigned int targinfosize, | 384 | unsigned int targinfosize, |
385 | unsigned int hook_mask) | 385 | unsigned int hook_mask) |
386 | { | 386 | { |
387 | struct ipt_clusterip_tgt_info *cipinfo = targinfo; | 387 | struct ipt_clusterip_tgt_info *cipinfo = targinfo; |
388 | const struct ipt_entry *e = e_void; | ||
388 | 389 | ||
389 | struct clusterip_config *config; | 390 | struct clusterip_config *config; |
390 | 391 | ||
diff --git a/net/ipv4/netfilter/ipt_DSCP.c b/net/ipv4/netfilter/ipt_DSCP.c index 6e319570a28c..898cdf79ce18 100644 --- a/net/ipv4/netfilter/ipt_DSCP.c +++ b/net/ipv4/netfilter/ipt_DSCP.c | |||
@@ -57,7 +57,7 @@ target(struct sk_buff **pskb, | |||
57 | 57 | ||
58 | static int | 58 | static int |
59 | checkentry(const char *tablename, | 59 | checkentry(const char *tablename, |
60 | const struct ipt_entry *e, | 60 | const void *e_void, |
61 | void *targinfo, | 61 | void *targinfo, |
62 | unsigned int targinfosize, | 62 | unsigned int targinfosize, |
63 | unsigned int hook_mask) | 63 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index a1319693f648..706445426a6d 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c | |||
@@ -113,12 +113,13 @@ target(struct sk_buff **pskb, | |||
113 | 113 | ||
114 | static int | 114 | static int |
115 | checkentry(const char *tablename, | 115 | checkentry(const char *tablename, |
116 | const struct ipt_entry *e, | 116 | const void *e_void, |
117 | void *targinfo, | 117 | void *targinfo, |
118 | unsigned int targinfosize, | 118 | unsigned int targinfosize, |
119 | unsigned int hook_mask) | 119 | unsigned int hook_mask) |
120 | { | 120 | { |
121 | const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; | 121 | const struct ipt_ECN_info *einfo = (struct ipt_ECN_info *)targinfo; |
122 | const struct ipt_entry *e = e_void; | ||
122 | 123 | ||
123 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) { | 124 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ECN_info))) { |
124 | printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n", | 125 | printk(KERN_WARNING "ECN: targinfosize %u != %Zu\n", |
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 30be0f1dae37..6606ddb66a29 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c | |||
@@ -431,7 +431,7 @@ ipt_log_target(struct sk_buff **pskb, | |||
431 | } | 431 | } |
432 | 432 | ||
433 | static int ipt_log_checkentry(const char *tablename, | 433 | static int ipt_log_checkentry(const char *tablename, |
434 | const struct ipt_entry *e, | 434 | const void *e, |
435 | void *targinfo, | 435 | void *targinfo, |
436 | unsigned int targinfosize, | 436 | unsigned int targinfosize, |
437 | unsigned int hook_mask) | 437 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 27860510ca6d..12c56d3343ca 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c | |||
@@ -40,7 +40,7 @@ static DEFINE_RWLOCK(masq_lock); | |||
40 | /* FIXME: Multiple targets. --RR */ | 40 | /* FIXME: Multiple targets. --RR */ |
41 | static int | 41 | static int |
42 | masquerade_check(const char *tablename, | 42 | masquerade_check(const char *tablename, |
43 | const struct ipt_entry *e, | 43 | const void *e, |
44 | void *targinfo, | 44 | void *targinfo, |
45 | unsigned int targinfosize, | 45 | unsigned int targinfosize, |
46 | unsigned int hook_mask) | 46 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c index e6e7b6095363..b074467fe67b 100644 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ b/net/ipv4/netfilter/ipt_NETMAP.c | |||
@@ -31,7 +31,7 @@ MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target"); | |||
31 | 31 | ||
32 | static int | 32 | static int |
33 | check(const char *tablename, | 33 | check(const char *tablename, |
34 | const struct ipt_entry *e, | 34 | const void *e, |
35 | void *targinfo, | 35 | void *targinfo, |
36 | unsigned int targinfosize, | 36 | unsigned int targinfosize, |
37 | unsigned int hook_mask) | 37 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_NFQUEUE.c b/net/ipv4/netfilter/ipt_NFQUEUE.c deleted file mode 100644 index 3cedc9be8807..000000000000 --- a/net/ipv4/netfilter/ipt_NFQUEUE.c +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | /* iptables module for using new netfilter netlink queue | ||
2 | * | ||
3 | * (C) 2005 by Harald Welte <laforge@netfilter.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | |||
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
16 | #include <linux/netfilter_ipv4/ipt_NFQUEUE.h> | ||
17 | |||
18 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
19 | MODULE_DESCRIPTION("iptables NFQUEUE target"); | ||
20 | MODULE_LICENSE("GPL"); | ||
21 | |||
22 | static unsigned int | ||
23 | target(struct sk_buff **pskb, | ||
24 | const struct net_device *in, | ||
25 | const struct net_device *out, | ||
26 | unsigned int hooknum, | ||
27 | const void *targinfo, | ||
28 | void *userinfo) | ||
29 | { | ||
30 | const struct ipt_NFQ_info *tinfo = targinfo; | ||
31 | |||
32 | return NF_QUEUE_NR(tinfo->queuenum); | ||
33 | } | ||
34 | |||
35 | static int | ||
36 | checkentry(const char *tablename, | ||
37 | const struct ipt_entry *e, | ||
38 | void *targinfo, | ||
39 | unsigned int targinfosize, | ||
40 | unsigned int hook_mask) | ||
41 | { | ||
42 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_NFQ_info))) { | ||
43 | printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n", | ||
44 | targinfosize, | ||
45 | IPT_ALIGN(sizeof(struct ipt_NFQ_info))); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | return 1; | ||
50 | } | ||
51 | |||
52 | static struct ipt_target ipt_NFQ_reg = { | ||
53 | .name = "NFQUEUE", | ||
54 | .target = target, | ||
55 | .checkentry = checkentry, | ||
56 | .me = THIS_MODULE, | ||
57 | }; | ||
58 | |||
59 | static int __init init(void) | ||
60 | { | ||
61 | return ipt_register_target(&ipt_NFQ_reg); | ||
62 | } | ||
63 | |||
64 | static void __exit fini(void) | ||
65 | { | ||
66 | ipt_unregister_target(&ipt_NFQ_reg); | ||
67 | } | ||
68 | |||
69 | module_init(init); | ||
70 | module_exit(fini); | ||
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index 5245bfd33d52..140be51f2f01 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c | |||
@@ -33,7 +33,7 @@ MODULE_DESCRIPTION("iptables REDIRECT target module"); | |||
33 | /* FIXME: Take multiple ranges --RR */ | 33 | /* FIXME: Take multiple ranges --RR */ |
34 | static int | 34 | static int |
35 | redirect_check(const char *tablename, | 35 | redirect_check(const char *tablename, |
36 | const struct ipt_entry *e, | 36 | const void *e, |
37 | void *targinfo, | 37 | void *targinfo, |
38 | unsigned int targinfosize, | 38 | unsigned int targinfosize, |
39 | unsigned int hook_mask) | 39 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 6693526ae128..3eb47aae78c5 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
@@ -282,12 +282,13 @@ static unsigned int reject(struct sk_buff **pskb, | |||
282 | } | 282 | } |
283 | 283 | ||
284 | static int check(const char *tablename, | 284 | static int check(const char *tablename, |
285 | const struct ipt_entry *e, | 285 | const void *e_void, |
286 | void *targinfo, | 286 | void *targinfo, |
287 | unsigned int targinfosize, | 287 | unsigned int targinfosize, |
288 | unsigned int hook_mask) | 288 | unsigned int hook_mask) |
289 | { | 289 | { |
290 | const struct ipt_reject_info *rejinfo = targinfo; | 290 | const struct ipt_reject_info *rejinfo = targinfo; |
291 | const struct ipt_entry *e = e_void; | ||
291 | 292 | ||
292 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) { | 293 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) { |
293 | DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize); | 294 | DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize); |
diff --git a/net/ipv4/netfilter/ipt_SAME.c b/net/ipv4/netfilter/ipt_SAME.c index 7a0536d864ac..a22de59bba0e 100644 --- a/net/ipv4/netfilter/ipt_SAME.c +++ b/net/ipv4/netfilter/ipt_SAME.c | |||
@@ -49,7 +49,7 @@ MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip"); | |||
49 | 49 | ||
50 | static int | 50 | static int |
51 | same_check(const char *tablename, | 51 | same_check(const char *tablename, |
52 | const struct ipt_entry *e, | 52 | const void *e, |
53 | void *targinfo, | 53 | void *targinfo, |
54 | unsigned int targinfosize, | 54 | unsigned int targinfosize, |
55 | unsigned int hook_mask) | 55 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c index 8db70d6908c3..c122841e182c 100644 --- a/net/ipv4/netfilter/ipt_TCPMSS.c +++ b/net/ipv4/netfilter/ipt_TCPMSS.c | |||
@@ -210,12 +210,13 @@ static inline int find_syn_match(const struct ipt_entry_match *m) | |||
210 | /* Must specify -p tcp --syn/--tcp-flags SYN */ | 210 | /* Must specify -p tcp --syn/--tcp-flags SYN */ |
211 | static int | 211 | static int |
212 | ipt_tcpmss_checkentry(const char *tablename, | 212 | ipt_tcpmss_checkentry(const char *tablename, |
213 | const struct ipt_entry *e, | 213 | const void *e_void, |
214 | void *targinfo, | 214 | void *targinfo, |
215 | unsigned int targinfosize, | 215 | unsigned int targinfosize, |
216 | unsigned int hook_mask) | 216 | unsigned int hook_mask) |
217 | { | 217 | { |
218 | const struct ipt_tcpmss_info *tcpmssinfo = targinfo; | 218 | const struct ipt_tcpmss_info *tcpmssinfo = targinfo; |
219 | const struct ipt_entry *e = e_void; | ||
219 | 220 | ||
220 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) { | 221 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_tcpmss_info))) { |
221 | DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n", | 222 | DEBUGP("ipt_tcpmss_checkentry: targinfosize %u != %u\n", |
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c index deadb36d4428..3a44a56db239 100644 --- a/net/ipv4/netfilter/ipt_TOS.c +++ b/net/ipv4/netfilter/ipt_TOS.c | |||
@@ -52,7 +52,7 @@ target(struct sk_buff **pskb, | |||
52 | 52 | ||
53 | static int | 53 | static int |
54 | checkentry(const char *tablename, | 54 | checkentry(const char *tablename, |
55 | const struct ipt_entry *e, | 55 | const void *e_void, |
56 | void *targinfo, | 56 | void *targinfo, |
57 | unsigned int targinfosize, | 57 | unsigned int targinfosize, |
58 | unsigned int hook_mask) | 58 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c index b9ae6a9382f3..b769eb231970 100644 --- a/net/ipv4/netfilter/ipt_TTL.c +++ b/net/ipv4/netfilter/ipt_TTL.c | |||
@@ -66,7 +66,7 @@ ipt_ttl_target(struct sk_buff **pskb, const struct net_device *in, | |||
66 | } | 66 | } |
67 | 67 | ||
68 | static int ipt_ttl_checkentry(const char *tablename, | 68 | static int ipt_ttl_checkentry(const char *tablename, |
69 | const struct ipt_entry *e, | 69 | const void *e, |
70 | void *targinfo, | 70 | void *targinfo, |
71 | unsigned int targinfosize, | 71 | unsigned int targinfosize, |
72 | unsigned int hook_mask) | 72 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c index 38641cd06123..641dbc477650 100644 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ b/net/ipv4/netfilter/ipt_ULOG.c | |||
@@ -330,7 +330,7 @@ static void ipt_logfn(unsigned int pf, | |||
330 | } | 330 | } |
331 | 331 | ||
332 | static int ipt_ulog_checkentry(const char *tablename, | 332 | static int ipt_ulog_checkentry(const char *tablename, |
333 | const struct ipt_entry *e, | 333 | const void *e, |
334 | void *targinfo, | 334 | void *targinfo, |
335 | unsigned int targinfosize, | 335 | unsigned int targinfosize, |
336 | unsigned int hookmask) | 336 | unsigned int hookmask) |
diff --git a/net/ipv4/netfilter/ipt_addrtype.c b/net/ipv4/netfilter/ipt_addrtype.c index e19c2a52d00c..d6b83a976518 100644 --- a/net/ipv4/netfilter/ipt_addrtype.c +++ b/net/ipv4/netfilter/ipt_addrtype.c | |||
@@ -29,7 +29,7 @@ static inline int match_type(u_int32_t addr, u_int16_t mask) | |||
29 | 29 | ||
30 | static int match(const struct sk_buff *skb, const struct net_device *in, | 30 | static int match(const struct sk_buff *skb, const struct net_device *in, |
31 | const struct net_device *out, const void *matchinfo, | 31 | const struct net_device *out, const void *matchinfo, |
32 | int offset, int *hotdrop) | 32 | int offset, unsigned int protoff, int *hotdrop) |
33 | { | 33 | { |
34 | const struct ipt_addrtype_info *info = matchinfo; | 34 | const struct ipt_addrtype_info *info = matchinfo; |
35 | const struct iphdr *iph = skb->nh.iph; | 35 | const struct iphdr *iph = skb->nh.iph; |
@@ -43,7 +43,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, | |||
43 | return ret; | 43 | return ret; |
44 | } | 44 | } |
45 | 45 | ||
46 | static int checkentry(const char *tablename, const struct ipt_ip *ip, | 46 | static int checkentry(const char *tablename, const void *ip, |
47 | void *matchinfo, unsigned int matchsize, | 47 | void *matchinfo, unsigned int matchsize, |
48 | unsigned int hook_mask) | 48 | unsigned int hook_mask) |
49 | { | 49 | { |
diff --git a/net/ipv4/netfilter/ipt_ah.c b/net/ipv4/netfilter/ipt_ah.c index a0fea847cb72..144adfec13cc 100644 --- a/net/ipv4/netfilter/ipt_ah.c +++ b/net/ipv4/netfilter/ipt_ah.c | |||
@@ -41,6 +41,7 @@ match(const struct sk_buff *skb, | |||
41 | const struct net_device *out, | 41 | const struct net_device *out, |
42 | const void *matchinfo, | 42 | const void *matchinfo, |
43 | int offset, | 43 | int offset, |
44 | unsigned int protoff, | ||
44 | int *hotdrop) | 45 | int *hotdrop) |
45 | { | 46 | { |
46 | struct ip_auth_hdr _ahdr, *ah; | 47 | struct ip_auth_hdr _ahdr, *ah; |
@@ -50,7 +51,7 @@ match(const struct sk_buff *skb, | |||
50 | if (offset) | 51 | if (offset) |
51 | return 0; | 52 | return 0; |
52 | 53 | ||
53 | ah = skb_header_pointer(skb, skb->nh.iph->ihl * 4, | 54 | ah = skb_header_pointer(skb, protoff, |
54 | sizeof(_ahdr), &_ahdr); | 55 | sizeof(_ahdr), &_ahdr); |
55 | if (ah == NULL) { | 56 | if (ah == NULL) { |
56 | /* We've been asked to examine this packet, and we | 57 | /* We've been asked to examine this packet, and we |
@@ -69,12 +70,13 @@ match(const struct sk_buff *skb, | |||
69 | /* Called when user tries to insert an entry of this type. */ | 70 | /* Called when user tries to insert an entry of this type. */ |
70 | static int | 71 | static int |
71 | checkentry(const char *tablename, | 72 | checkentry(const char *tablename, |
72 | const struct ipt_ip *ip, | 73 | const void *ip_void, |
73 | void *matchinfo, | 74 | void *matchinfo, |
74 | unsigned int matchinfosize, | 75 | unsigned int matchinfosize, |
75 | unsigned int hook_mask) | 76 | unsigned int hook_mask) |
76 | { | 77 | { |
77 | const struct ipt_ah *ahinfo = matchinfo; | 78 | const struct ipt_ah *ahinfo = matchinfo; |
79 | const struct ipt_ip *ip = ip_void; | ||
78 | 80 | ||
79 | /* Must specify proto == AH, and no unknown invflags */ | 81 | /* Must specify proto == AH, and no unknown invflags */ |
80 | if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) { | 82 | if (ip->proto != IPPROTO_AH || (ip->invflags & IPT_INV_PROTO)) { |
diff --git a/net/ipv4/netfilter/ipt_dscp.c b/net/ipv4/netfilter/ipt_dscp.c index 5df52a64a5d4..92063b4f8602 100644 --- a/net/ipv4/netfilter/ipt_dscp.c +++ b/net/ipv4/netfilter/ipt_dscp.c | |||
@@ -21,7 +21,7 @@ MODULE_LICENSE("GPL"); | |||
21 | 21 | ||
22 | static int match(const struct sk_buff *skb, const struct net_device *in, | 22 | static int match(const struct sk_buff *skb, const struct net_device *in, |
23 | const struct net_device *out, const void *matchinfo, | 23 | const struct net_device *out, const void *matchinfo, |
24 | int offset, int *hotdrop) | 24 | int offset, unsigned int protoff, int *hotdrop) |
25 | { | 25 | { |
26 | const struct ipt_dscp_info *info = matchinfo; | 26 | const struct ipt_dscp_info *info = matchinfo; |
27 | const struct iphdr *iph = skb->nh.iph; | 27 | const struct iphdr *iph = skb->nh.iph; |
@@ -31,7 +31,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, | |||
31 | return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert; | 31 | return ((iph->tos&IPT_DSCP_MASK) == sh_dscp) ^ info->invert; |
32 | } | 32 | } |
33 | 33 | ||
34 | static int checkentry(const char *tablename, const struct ipt_ip *ip, | 34 | static int checkentry(const char *tablename, const void *ip, |
35 | void *matchinfo, unsigned int matchsize, | 35 | void *matchinfo, unsigned int matchsize, |
36 | unsigned int hook_mask) | 36 | unsigned int hook_mask) |
37 | { | 37 | { |
diff --git a/net/ipv4/netfilter/ipt_ecn.c b/net/ipv4/netfilter/ipt_ecn.c index b6f7181e89cc..e68b0c7981f0 100644 --- a/net/ipv4/netfilter/ipt_ecn.c +++ b/net/ipv4/netfilter/ipt_ecn.c | |||
@@ -67,7 +67,7 @@ static inline int match_tcp(const struct sk_buff *skb, | |||
67 | 67 | ||
68 | static int match(const struct sk_buff *skb, const struct net_device *in, | 68 | static int match(const struct sk_buff *skb, const struct net_device *in, |
69 | const struct net_device *out, const void *matchinfo, | 69 | const struct net_device *out, const void *matchinfo, |
70 | int offset, int *hotdrop) | 70 | int offset, unsigned int protoff, int *hotdrop) |
71 | { | 71 | { |
72 | const struct ipt_ecn_info *info = matchinfo; | 72 | const struct ipt_ecn_info *info = matchinfo; |
73 | 73 | ||
@@ -85,11 +85,12 @@ static int match(const struct sk_buff *skb, const struct net_device *in, | |||
85 | return 1; | 85 | return 1; |
86 | } | 86 | } |
87 | 87 | ||
88 | static int checkentry(const char *tablename, const struct ipt_ip *ip, | 88 | static int checkentry(const char *tablename, const void *ip_void, |
89 | void *matchinfo, unsigned int matchsize, | 89 | void *matchinfo, unsigned int matchsize, |
90 | unsigned int hook_mask) | 90 | unsigned int hook_mask) |
91 | { | 91 | { |
92 | const struct ipt_ecn_info *info = matchinfo; | 92 | const struct ipt_ecn_info *info = matchinfo; |
93 | const struct ipt_ip *ip = ip_void; | ||
93 | 94 | ||
94 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info))) | 95 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_ecn_info))) |
95 | return 0; | 96 | return 0; |
diff --git a/net/ipv4/netfilter/ipt_esp.c b/net/ipv4/netfilter/ipt_esp.c index e1d0dd31e117..9de191a8162d 100644 --- a/net/ipv4/netfilter/ipt_esp.c +++ b/net/ipv4/netfilter/ipt_esp.c | |||
@@ -42,6 +42,7 @@ match(const struct sk_buff *skb, | |||
42 | const struct net_device *out, | 42 | const struct net_device *out, |
43 | const void *matchinfo, | 43 | const void *matchinfo, |
44 | int offset, | 44 | int offset, |
45 | unsigned int protoff, | ||
45 | int *hotdrop) | 46 | int *hotdrop) |
46 | { | 47 | { |
47 | struct ip_esp_hdr _esp, *eh; | 48 | struct ip_esp_hdr _esp, *eh; |
@@ -51,7 +52,7 @@ match(const struct sk_buff *skb, | |||
51 | if (offset) | 52 | if (offset) |
52 | return 0; | 53 | return 0; |
53 | 54 | ||
54 | eh = skb_header_pointer(skb, skb->nh.iph->ihl * 4, | 55 | eh = skb_header_pointer(skb, protoff, |
55 | sizeof(_esp), &_esp); | 56 | sizeof(_esp), &_esp); |
56 | if (eh == NULL) { | 57 | if (eh == NULL) { |
57 | /* We've been asked to examine this packet, and we | 58 | /* We've been asked to examine this packet, and we |
@@ -70,12 +71,13 @@ match(const struct sk_buff *skb, | |||
70 | /* Called when user tries to insert an entry of this type. */ | 71 | /* Called when user tries to insert an entry of this type. */ |
71 | static int | 72 | static int |
72 | checkentry(const char *tablename, | 73 | checkentry(const char *tablename, |
73 | const struct ipt_ip *ip, | 74 | const void *ip_void, |
74 | void *matchinfo, | 75 | void *matchinfo, |
75 | unsigned int matchinfosize, | 76 | unsigned int matchinfosize, |
76 | unsigned int hook_mask) | 77 | unsigned int hook_mask) |
77 | { | 78 | { |
78 | const struct ipt_esp *espinfo = matchinfo; | 79 | const struct ipt_esp *espinfo = matchinfo; |
80 | const struct ipt_ip *ip = ip_void; | ||
79 | 81 | ||
80 | /* Must specify proto == ESP, and no unknown invflags */ | 82 | /* Must specify proto == ESP, and no unknown invflags */ |
81 | if (ip->proto != IPPROTO_ESP || (ip->invflags & IPT_INV_PROTO)) { | 83 | if (ip->proto != IPPROTO_ESP || (ip->invflags & IPT_INV_PROTO)) { |
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c index 2dd1cccbdab9..4fe48c1bd5f3 100644 --- a/net/ipv4/netfilter/ipt_hashlimit.c +++ b/net/ipv4/netfilter/ipt_hashlimit.c | |||
@@ -429,6 +429,7 @@ hashlimit_match(const struct sk_buff *skb, | |||
429 | const struct net_device *out, | 429 | const struct net_device *out, |
430 | const void *matchinfo, | 430 | const void *matchinfo, |
431 | int offset, | 431 | int offset, |
432 | unsigned int protoff, | ||
432 | int *hotdrop) | 433 | int *hotdrop) |
433 | { | 434 | { |
434 | struct ipt_hashlimit_info *r = | 435 | struct ipt_hashlimit_info *r = |
@@ -504,7 +505,7 @@ hashlimit_match(const struct sk_buff *skb, | |||
504 | 505 | ||
505 | static int | 506 | static int |
506 | hashlimit_checkentry(const char *tablename, | 507 | hashlimit_checkentry(const char *tablename, |
507 | const struct ipt_ip *ip, | 508 | const void *inf, |
508 | void *matchinfo, | 509 | void *matchinfo, |
509 | unsigned int matchsize, | 510 | unsigned int matchsize, |
510 | unsigned int hook_mask) | 511 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_iprange.c b/net/ipv4/netfilter/ipt_iprange.c index b835b7b2e560..13fb16fb7892 100644 --- a/net/ipv4/netfilter/ipt_iprange.c +++ b/net/ipv4/netfilter/ipt_iprange.c | |||
@@ -28,7 +28,7 @@ match(const struct sk_buff *skb, | |||
28 | const struct net_device *in, | 28 | const struct net_device *in, |
29 | const struct net_device *out, | 29 | const struct net_device *out, |
30 | const void *matchinfo, | 30 | const void *matchinfo, |
31 | int offset, int *hotdrop) | 31 | int offset, unsigned int protoff, int *hotdrop) |
32 | { | 32 | { |
33 | const struct ipt_iprange_info *info = matchinfo; | 33 | const struct ipt_iprange_info *info = matchinfo; |
34 | const struct iphdr *iph = skb->nh.iph; | 34 | const struct iphdr *iph = skb->nh.iph; |
@@ -63,7 +63,7 @@ match(const struct sk_buff *skb, | |||
63 | } | 63 | } |
64 | 64 | ||
65 | static int check(const char *tablename, | 65 | static int check(const char *tablename, |
66 | const struct ipt_ip *ip, | 66 | const void *inf, |
67 | void *matchinfo, | 67 | void *matchinfo, |
68 | unsigned int matchsize, | 68 | unsigned int matchsize, |
69 | unsigned int hook_mask) | 69 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_length.c b/net/ipv4/netfilter/ipt_length.c deleted file mode 100644 index 4eabcfbda9d1..000000000000 --- a/net/ipv4/netfilter/ipt_length.c +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | /* Kernel module to match packet length. */ | ||
2 | /* (C) 1999-2001 James Morris <jmorros@intercode.com.au> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/skbuff.h> | ||
11 | |||
12 | #include <linux/netfilter_ipv4/ipt_length.h> | ||
13 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
14 | |||
15 | MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); | ||
16 | MODULE_DESCRIPTION("IP tables packet length matching module"); | ||
17 | MODULE_LICENSE("GPL"); | ||
18 | |||
19 | static int | ||
20 | match(const struct sk_buff *skb, | ||
21 | const struct net_device *in, | ||
22 | const struct net_device *out, | ||
23 | const void *matchinfo, | ||
24 | int offset, | ||
25 | int *hotdrop) | ||
26 | { | ||
27 | const struct ipt_length_info *info = matchinfo; | ||
28 | u_int16_t pktlen = ntohs(skb->nh.iph->tot_len); | ||
29 | |||
30 | return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; | ||
31 | } | ||
32 | |||
33 | static int | ||
34 | checkentry(const char *tablename, | ||
35 | const struct ipt_ip *ip, | ||
36 | void *matchinfo, | ||
37 | unsigned int matchsize, | ||
38 | unsigned int hook_mask) | ||
39 | { | ||
40 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_length_info))) | ||
41 | return 0; | ||
42 | |||
43 | return 1; | ||
44 | } | ||
45 | |||
46 | static struct ipt_match length_match = { | ||
47 | .name = "length", | ||
48 | .match = &match, | ||
49 | .checkentry = &checkentry, | ||
50 | .me = THIS_MODULE, | ||
51 | }; | ||
52 | |||
53 | static int __init init(void) | ||
54 | { | ||
55 | return ipt_register_match(&length_match); | ||
56 | } | ||
57 | |||
58 | static void __exit fini(void) | ||
59 | { | ||
60 | ipt_unregister_match(&length_match); | ||
61 | } | ||
62 | |||
63 | module_init(init); | ||
64 | module_exit(fini); | ||
diff --git a/net/ipv4/netfilter/ipt_multiport.c b/net/ipv4/netfilter/ipt_multiport.c index 99e8188162e2..2d52326553f1 100644 --- a/net/ipv4/netfilter/ipt_multiport.c +++ b/net/ipv4/netfilter/ipt_multiport.c | |||
@@ -97,6 +97,7 @@ match(const struct sk_buff *skb, | |||
97 | const struct net_device *out, | 97 | const struct net_device *out, |
98 | const void *matchinfo, | 98 | const void *matchinfo, |
99 | int offset, | 99 | int offset, |
100 | unsigned int protoff, | ||
100 | int *hotdrop) | 101 | int *hotdrop) |
101 | { | 102 | { |
102 | u16 _ports[2], *pptr; | 103 | u16 _ports[2], *pptr; |
@@ -105,7 +106,7 @@ match(const struct sk_buff *skb, | |||
105 | if (offset) | 106 | if (offset) |
106 | return 0; | 107 | return 0; |
107 | 108 | ||
108 | pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4, | 109 | pptr = skb_header_pointer(skb, protoff, |
109 | sizeof(_ports), _ports); | 110 | sizeof(_ports), _ports); |
110 | if (pptr == NULL) { | 111 | if (pptr == NULL) { |
111 | /* We've been asked to examine this packet, and we | 112 | /* We've been asked to examine this packet, and we |
@@ -128,6 +129,7 @@ match_v1(const struct sk_buff *skb, | |||
128 | const struct net_device *out, | 129 | const struct net_device *out, |
129 | const void *matchinfo, | 130 | const void *matchinfo, |
130 | int offset, | 131 | int offset, |
132 | unsigned int protoff, | ||
131 | int *hotdrop) | 133 | int *hotdrop) |
132 | { | 134 | { |
133 | u16 _ports[2], *pptr; | 135 | u16 _ports[2], *pptr; |
@@ -136,7 +138,7 @@ match_v1(const struct sk_buff *skb, | |||
136 | if (offset) | 138 | if (offset) |
137 | return 0; | 139 | return 0; |
138 | 140 | ||
139 | pptr = skb_header_pointer(skb, skb->nh.iph->ihl * 4, | 141 | pptr = skb_header_pointer(skb, protoff, |
140 | sizeof(_ports), _ports); | 142 | sizeof(_ports), _ports); |
141 | if (pptr == NULL) { | 143 | if (pptr == NULL) { |
142 | /* We've been asked to examine this packet, and we | 144 | /* We've been asked to examine this packet, and we |
@@ -154,7 +156,7 @@ match_v1(const struct sk_buff *skb, | |||
154 | /* Called when user tries to insert an entry of this type. */ | 156 | /* Called when user tries to insert an entry of this type. */ |
155 | static int | 157 | static int |
156 | checkentry(const char *tablename, | 158 | checkentry(const char *tablename, |
157 | const struct ipt_ip *ip, | 159 | const void *ip, |
158 | void *matchinfo, | 160 | void *matchinfo, |
159 | unsigned int matchsize, | 161 | unsigned int matchsize, |
160 | unsigned int hook_mask) | 162 | unsigned int hook_mask) |
@@ -164,7 +166,7 @@ checkentry(const char *tablename, | |||
164 | 166 | ||
165 | static int | 167 | static int |
166 | checkentry_v1(const char *tablename, | 168 | checkentry_v1(const char *tablename, |
167 | const struct ipt_ip *ip, | 169 | const void *ip, |
168 | void *matchinfo, | 170 | void *matchinfo, |
169 | unsigned int matchsize, | 171 | unsigned int matchsize, |
170 | unsigned int hook_mask) | 172 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_owner.c b/net/ipv4/netfilter/ipt_owner.c index 0cee2862ed85..4843d0c9734f 100644 --- a/net/ipv4/netfilter/ipt_owner.c +++ b/net/ipv4/netfilter/ipt_owner.c | |||
@@ -27,6 +27,7 @@ match(const struct sk_buff *skb, | |||
27 | const struct net_device *out, | 27 | const struct net_device *out, |
28 | const void *matchinfo, | 28 | const void *matchinfo, |
29 | int offset, | 29 | int offset, |
30 | unsigned int protoff, | ||
30 | int *hotdrop) | 31 | int *hotdrop) |
31 | { | 32 | { |
32 | const struct ipt_owner_info *info = matchinfo; | 33 | const struct ipt_owner_info *info = matchinfo; |
@@ -51,7 +52,7 @@ match(const struct sk_buff *skb, | |||
51 | 52 | ||
52 | static int | 53 | static int |
53 | checkentry(const char *tablename, | 54 | checkentry(const char *tablename, |
54 | const struct ipt_ip *ip, | 55 | const void *ip, |
55 | void *matchinfo, | 56 | void *matchinfo, |
56 | unsigned int matchsize, | 57 | unsigned int matchsize, |
57 | unsigned int hook_mask) | 58 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_physdev.c b/net/ipv4/netfilter/ipt_physdev.c deleted file mode 100644 index 03f554857a4d..000000000000 --- a/net/ipv4/netfilter/ipt_physdev.c +++ /dev/null | |||
@@ -1,135 +0,0 @@ | |||
1 | /* Kernel module to match the bridge port in and | ||
2 | * out device for IP packets coming into contact with a bridge. */ | ||
3 | |||
4 | /* (C) 2001-2003 Bart De Schuymer <bdschuym@pandora.be> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/netdevice.h> | ||
13 | #include <linux/skbuff.h> | ||
14 | #include <linux/netfilter_ipv4/ipt_physdev.h> | ||
15 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
16 | #include <linux/netfilter_bridge.h> | ||
17 | #define MATCH 1 | ||
18 | #define NOMATCH 0 | ||
19 | |||
20 | MODULE_LICENSE("GPL"); | ||
21 | MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); | ||
22 | MODULE_DESCRIPTION("iptables bridge physical device match module"); | ||
23 | |||
24 | static int | ||
25 | match(const struct sk_buff *skb, | ||
26 | const struct net_device *in, | ||
27 | const struct net_device *out, | ||
28 | const void *matchinfo, | ||
29 | int offset, | ||
30 | int *hotdrop) | ||
31 | { | ||
32 | int i; | ||
33 | static const char nulldevname[IFNAMSIZ]; | ||
34 | const struct ipt_physdev_info *info = matchinfo; | ||
35 | unsigned int ret; | ||
36 | const char *indev, *outdev; | ||
37 | struct nf_bridge_info *nf_bridge; | ||
38 | |||
39 | /* Not a bridged IP packet or no info available yet: | ||
40 | * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if | ||
41 | * the destination device will be a bridge. */ | ||
42 | if (!(nf_bridge = skb->nf_bridge)) { | ||
43 | /* Return MATCH if the invert flags of the used options are on */ | ||
44 | if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) && | ||
45 | !(info->invert & IPT_PHYSDEV_OP_BRIDGED)) | ||
46 | return NOMATCH; | ||
47 | if ((info->bitmask & IPT_PHYSDEV_OP_ISIN) && | ||
48 | !(info->invert & IPT_PHYSDEV_OP_ISIN)) | ||
49 | return NOMATCH; | ||
50 | if ((info->bitmask & IPT_PHYSDEV_OP_ISOUT) && | ||
51 | !(info->invert & IPT_PHYSDEV_OP_ISOUT)) | ||
52 | return NOMATCH; | ||
53 | if ((info->bitmask & IPT_PHYSDEV_OP_IN) && | ||
54 | !(info->invert & IPT_PHYSDEV_OP_IN)) | ||
55 | return NOMATCH; | ||
56 | if ((info->bitmask & IPT_PHYSDEV_OP_OUT) && | ||
57 | !(info->invert & IPT_PHYSDEV_OP_OUT)) | ||
58 | return NOMATCH; | ||
59 | return MATCH; | ||
60 | } | ||
61 | |||
62 | /* This only makes sense in the FORWARD and POSTROUTING chains */ | ||
63 | if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) && | ||
64 | (!!(nf_bridge->mask & BRNF_BRIDGED) ^ | ||
65 | !(info->invert & IPT_PHYSDEV_OP_BRIDGED))) | ||
66 | return NOMATCH; | ||
67 | |||
68 | if ((info->bitmask & IPT_PHYSDEV_OP_ISIN && | ||
69 | (!nf_bridge->physindev ^ !!(info->invert & IPT_PHYSDEV_OP_ISIN))) || | ||
70 | (info->bitmask & IPT_PHYSDEV_OP_ISOUT && | ||
71 | (!nf_bridge->physoutdev ^ !!(info->invert & IPT_PHYSDEV_OP_ISOUT)))) | ||
72 | return NOMATCH; | ||
73 | |||
74 | if (!(info->bitmask & IPT_PHYSDEV_OP_IN)) | ||
75 | goto match_outdev; | ||
76 | indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; | ||
77 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { | ||
78 | ret |= (((const unsigned int *)indev)[i] | ||
79 | ^ ((const unsigned int *)info->physindev)[i]) | ||
80 | & ((const unsigned int *)info->in_mask)[i]; | ||
81 | } | ||
82 | |||
83 | if ((ret == 0) ^ !(info->invert & IPT_PHYSDEV_OP_IN)) | ||
84 | return NOMATCH; | ||
85 | |||
86 | match_outdev: | ||
87 | if (!(info->bitmask & IPT_PHYSDEV_OP_OUT)) | ||
88 | return MATCH; | ||
89 | outdev = nf_bridge->physoutdev ? | ||
90 | nf_bridge->physoutdev->name : nulldevname; | ||
91 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { | ||
92 | ret |= (((const unsigned int *)outdev)[i] | ||
93 | ^ ((const unsigned int *)info->physoutdev)[i]) | ||
94 | & ((const unsigned int *)info->out_mask)[i]; | ||
95 | } | ||
96 | |||
97 | return (ret != 0) ^ !(info->invert & IPT_PHYSDEV_OP_OUT); | ||
98 | } | ||
99 | |||
100 | static int | ||
101 | checkentry(const char *tablename, | ||
102 | const struct ipt_ip *ip, | ||
103 | void *matchinfo, | ||
104 | unsigned int matchsize, | ||
105 | unsigned int hook_mask) | ||
106 | { | ||
107 | const struct ipt_physdev_info *info = matchinfo; | ||
108 | |||
109 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_physdev_info))) | ||
110 | return 0; | ||
111 | if (!(info->bitmask & IPT_PHYSDEV_OP_MASK) || | ||
112 | info->bitmask & ~IPT_PHYSDEV_OP_MASK) | ||
113 | return 0; | ||
114 | return 1; | ||
115 | } | ||
116 | |||
117 | static struct ipt_match physdev_match = { | ||
118 | .name = "physdev", | ||
119 | .match = &match, | ||
120 | .checkentry = &checkentry, | ||
121 | .me = THIS_MODULE, | ||
122 | }; | ||
123 | |||
124 | static int __init init(void) | ||
125 | { | ||
126 | return ipt_register_match(&physdev_match); | ||
127 | } | ||
128 | |||
129 | static void __exit fini(void) | ||
130 | { | ||
131 | ipt_unregister_match(&physdev_match); | ||
132 | } | ||
133 | |||
134 | module_init(init); | ||
135 | module_exit(fini); | ||
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c index 5ddccb18c65e..44611d6d14f5 100644 --- a/net/ipv4/netfilter/ipt_recent.c +++ b/net/ipv4/netfilter/ipt_recent.c | |||
@@ -104,6 +104,7 @@ match(const struct sk_buff *skb, | |||
104 | const struct net_device *out, | 104 | const struct net_device *out, |
105 | const void *matchinfo, | 105 | const void *matchinfo, |
106 | int offset, | 106 | int offset, |
107 | unsigned int protoff, | ||
107 | int *hotdrop); | 108 | int *hotdrop); |
108 | 109 | ||
109 | /* Function to hash a given address into the hash table of table_size size */ | 110 | /* Function to hash a given address into the hash table of table_size size */ |
@@ -317,7 +318,7 @@ static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned | |||
317 | skb->nh.iph->daddr = 0; | 318 | skb->nh.iph->daddr = 0; |
318 | /* Clear ttl since we have no way of knowing it */ | 319 | /* Clear ttl since we have no way of knowing it */ |
319 | skb->nh.iph->ttl = 0; | 320 | skb->nh.iph->ttl = 0; |
320 | match(skb,NULL,NULL,info,0,NULL); | 321 | match(skb,NULL,NULL,info,0,0,NULL); |
321 | 322 | ||
322 | kfree(skb->nh.iph); | 323 | kfree(skb->nh.iph); |
323 | out_free_skb: | 324 | out_free_skb: |
@@ -357,6 +358,7 @@ match(const struct sk_buff *skb, | |||
357 | const struct net_device *out, | 358 | const struct net_device *out, |
358 | const void *matchinfo, | 359 | const void *matchinfo, |
359 | int offset, | 360 | int offset, |
361 | unsigned int protoff, | ||
360 | int *hotdrop) | 362 | int *hotdrop) |
361 | { | 363 | { |
362 | int pkt_count, hits_found, ans; | 364 | int pkt_count, hits_found, ans; |
@@ -654,7 +656,7 @@ match(const struct sk_buff *skb, | |||
654 | */ | 656 | */ |
655 | static int | 657 | static int |
656 | checkentry(const char *tablename, | 658 | checkentry(const char *tablename, |
657 | const struct ipt_ip *ip, | 659 | const void *ip, |
658 | void *matchinfo, | 660 | void *matchinfo, |
659 | unsigned int matchsize, | 661 | unsigned int matchsize, |
660 | unsigned int hook_mask) | 662 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_tos.c b/net/ipv4/netfilter/ipt_tos.c index 086a1bb61e3e..9ab765e126f2 100644 --- a/net/ipv4/netfilter/ipt_tos.c +++ b/net/ipv4/netfilter/ipt_tos.c | |||
@@ -23,6 +23,7 @@ match(const struct sk_buff *skb, | |||
23 | const struct net_device *out, | 23 | const struct net_device *out, |
24 | const void *matchinfo, | 24 | const void *matchinfo, |
25 | int offset, | 25 | int offset, |
26 | unsigned int protoff, | ||
26 | int *hotdrop) | 27 | int *hotdrop) |
27 | { | 28 | { |
28 | const struct ipt_tos_info *info = matchinfo; | 29 | const struct ipt_tos_info *info = matchinfo; |
@@ -32,7 +33,7 @@ match(const struct sk_buff *skb, | |||
32 | 33 | ||
33 | static int | 34 | static int |
34 | checkentry(const char *tablename, | 35 | checkentry(const char *tablename, |
35 | const struct ipt_ip *ip, | 36 | const void *ip, |
36 | void *matchinfo, | 37 | void *matchinfo, |
37 | unsigned int matchsize, | 38 | unsigned int matchsize, |
38 | unsigned int hook_mask) | 39 | unsigned int hook_mask) |
diff --git a/net/ipv4/netfilter/ipt_ttl.c b/net/ipv4/netfilter/ipt_ttl.c index 219aa9de88cc..82da53f430ab 100644 --- a/net/ipv4/netfilter/ipt_ttl.c +++ b/net/ipv4/netfilter/ipt_ttl.c | |||
@@ -21,7 +21,7 @@ MODULE_LICENSE("GPL"); | |||
21 | 21 | ||
22 | static int match(const struct sk_buff *skb, const struct net_device *in, | 22 | static int match(const struct sk_buff *skb, const struct net_device *in, |
23 | const struct net_device *out, const void *matchinfo, | 23 | const struct net_device *out, const void *matchinfo, |
24 | int offset, int *hotdrop) | 24 | int offset, unsigned int protoff, int *hotdrop) |
25 | { | 25 | { |
26 | const struct ipt_ttl_info *info = matchinfo; | 26 | const struct ipt_ttl_info *info = matchinfo; |
27 | 27 | ||
@@ -47,7 +47,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, | |||
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
49 | 49 | ||
50 | static int checkentry(const char *tablename, const struct ipt_ip *ip, | 50 | static int checkentry(const char *tablename, const void *ip, |
51 | void *matchinfo, unsigned int matchsize, | 51 | void *matchinfo, unsigned int matchsize, |
52 | unsigned int hook_mask) | 52 | unsigned int hook_mask) |
53 | { | 53 | { |
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 260a4f0a2a90..212a3079085b 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c | |||
@@ -78,7 +78,8 @@ static struct ipt_table packet_filter = { | |||
78 | .name = "filter", | 78 | .name = "filter", |
79 | .valid_hooks = FILTER_VALID_HOOKS, | 79 | .valid_hooks = FILTER_VALID_HOOKS, |
80 | .lock = RW_LOCK_UNLOCKED, | 80 | .lock = RW_LOCK_UNLOCKED, |
81 | .me = THIS_MODULE | 81 | .me = THIS_MODULE, |
82 | .af = AF_INET, | ||
82 | }; | 83 | }; |
83 | 84 | ||
84 | /* The work comes in here from netfilter.c. */ | 85 | /* The work comes in here from netfilter.c. */ |
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index 160eb11b6e2f..3212a5cc4b6b 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
@@ -109,6 +109,7 @@ static struct ipt_table packet_mangler = { | |||
109 | .valid_hooks = MANGLE_VALID_HOOKS, | 109 | .valid_hooks = MANGLE_VALID_HOOKS, |
110 | .lock = RW_LOCK_UNLOCKED, | 110 | .lock = RW_LOCK_UNLOCKED, |
111 | .me = THIS_MODULE, | 111 | .me = THIS_MODULE, |
112 | .af = AF_INET, | ||
112 | }; | 113 | }; |
113 | 114 | ||
114 | /* The work comes in here from netfilter.c. */ | 115 | /* The work comes in here from netfilter.c. */ |
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 47449ba83eb9..fdb9e9c81e81 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c | |||
@@ -83,7 +83,8 @@ static struct ipt_table packet_raw = { | |||
83 | .name = "raw", | 83 | .name = "raw", |
84 | .valid_hooks = RAW_VALID_HOOKS, | 84 | .valid_hooks = RAW_VALID_HOOKS, |
85 | .lock = RW_LOCK_UNLOCKED, | 85 | .lock = RW_LOCK_UNLOCKED, |
86 | .me = THIS_MODULE | 86 | .me = THIS_MODULE, |
87 | .af = AF_INET, | ||
87 | }; | 88 | }; |
88 | 89 | ||
89 | /* The work comes in here from netfilter.c. */ | 90 | /* The work comes in here from netfilter.c. */ |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 0c56c52a3831..167619f638c6 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -575,7 +575,7 @@ MODULE_LICENSE("GPL"); | |||
575 | 575 | ||
576 | static int __init init(void) | 576 | static int __init init(void) |
577 | { | 577 | { |
578 | need_nf_conntrack(); | 578 | need_conntrack(); |
579 | return init_or_cleanup(1); | 579 | return init_or_cleanup(1); |
580 | } | 580 | } |
581 | 581 | ||
@@ -587,9 +587,4 @@ static void __exit fini(void) | |||
587 | module_init(init); | 587 | module_init(init); |
588 | module_exit(fini); | 588 | module_exit(fini); |
589 | 589 | ||
590 | void need_ip_conntrack(void) | ||
591 | { | ||
592 | } | ||
593 | |||
594 | EXPORT_SYMBOL(need_ip_conntrack); | ||
595 | EXPORT_SYMBOL(nf_ct_ipv4_gather_frags); | 590 | EXPORT_SYMBOL(nf_ct_ipv4_gather_frags); |
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index d23e07fc81fa..dbabf81a9b7b 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
@@ -42,6 +42,21 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
42 | x->props.saddr = tmpl->saddr; | 42 | x->props.saddr = tmpl->saddr; |
43 | if (x->props.saddr.a4 == 0) | 43 | if (x->props.saddr.a4 == 0) |
44 | x->props.saddr.a4 = saddr->a4; | 44 | x->props.saddr.a4 = saddr->a4; |
45 | if (tmpl->mode && x->props.saddr.a4 == 0) { | ||
46 | struct rtable *rt; | ||
47 | struct flowi fl_tunnel = { | ||
48 | .nl_u = { | ||
49 | .ip4_u = { | ||
50 | .daddr = x->id.daddr.a4, | ||
51 | } | ||
52 | } | ||
53 | }; | ||
54 | if (!xfrm_dst_lookup((struct xfrm_dst **)&rt, | ||
55 | &fl_tunnel, AF_INET)) { | ||
56 | x->props.saddr.a4 = rt->rt_src; | ||
57 | dst_release(&rt->u.dst); | ||
58 | } | ||
59 | } | ||
45 | x->props.mode = tmpl->mode; | 60 | x->props.mode = tmpl->mode; |
46 | x->props.reqid = tmpl->reqid; | 61 | x->props.reqid = tmpl->reqid; |
47 | x->props.family = AF_INET; | 62 | x->props.family = AF_INET; |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 7129d4239755..dfb4f145a139 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -2644,7 +2644,7 @@ static int if6_seq_show(struct seq_file *seq, void *v) | |||
2644 | { | 2644 | { |
2645 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v; | 2645 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v; |
2646 | seq_printf(seq, | 2646 | seq_printf(seq, |
2647 | "%04x%04x%04x%04x%04x%04x%04x%04x %02x %02x %02x %02x %8s\n", | 2647 | NIP6_FMT " %02x %02x %02x %02x %8s\n", |
2648 | NIP6(ifp->addr), | 2648 | NIP6(ifp->addr), |
2649 | ifp->idev->dev->ifindex, | 2649 | ifp->idev->dev->ifindex, |
2650 | ifp->prefix_len, | 2650 | ifp->prefix_len, |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 13cc7f895583..c7932cb420a5 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -332,8 +332,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
332 | if (!x) | 332 | if (!x) |
333 | return; | 333 | return; |
334 | 334 | ||
335 | NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/" | 335 | NETDEBUG(KERN_DEBUG "pmtu discovery on SA AH/%08x/" NIP6_FMT "\n", |
336 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
337 | ntohl(ah->spi), NIP6(iph->daddr)); | 336 | ntohl(ah->spi), NIP6(iph->daddr)); |
338 | 337 | ||
339 | xfrm_state_put(x); | 338 | xfrm_state_put(x); |
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 65e73ac0d6d0..72bd08af2dfb 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -532,9 +532,7 @@ static int ac6_seq_show(struct seq_file *seq, void *v) | |||
532 | struct ac6_iter_state *state = ac6_seq_private(seq); | 532 | struct ac6_iter_state *state = ac6_seq_private(seq); |
533 | 533 | ||
534 | seq_printf(seq, | 534 | seq_printf(seq, |
535 | "%-4d %-15s " | 535 | "%-4d %-15s " NIP6_FMT " %5d\n", |
536 | "%04x%04x%04x%04x%04x%04x%04x%04x " | ||
537 | "%5d\n", | ||
538 | state->dev->ifindex, state->dev->name, | 536 | state->dev->ifindex, state->dev->name, |
539 | NIP6(im->aca_addr), | 537 | NIP6(im->aca_addr), |
540 | im->aca_users); | 538 | im->aca_users); |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 6de8ee1a5ad9..7b5b94f13902 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -266,8 +266,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
266 | x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); | 266 | x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); |
267 | if (!x) | 267 | if (!x) |
268 | return; | 268 | return; |
269 | printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/" | 269 | printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/" NIP6_FMT "\n", |
270 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
271 | ntohl(esph->spi), NIP6(iph->daddr)); | 270 | ntohl(esph->spi), NIP6(iph->daddr)); |
272 | xfrm_state_put(x); | 271 | xfrm_state_put(x); |
273 | } | 272 | } |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 53c81fcd20ba..fcf883183cef 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -607,7 +607,7 @@ static int icmpv6_rcv(struct sk_buff **pskb) | |||
607 | skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len, | 607 | skb->csum = ~csum_ipv6_magic(saddr, daddr, skb->len, |
608 | IPPROTO_ICMPV6, 0); | 608 | IPPROTO_ICMPV6, 0); |
609 | if (__skb_checksum_complete(skb)) { | 609 | if (__skb_checksum_complete(skb)) { |
610 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x > %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]\n", | 610 | LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [" NIP6_FMT " > " NIP6_FMT "]\n", |
611 | NIP6(*saddr), NIP6(*daddr)); | 611 | NIP6(*saddr), NIP6(*daddr)); |
612 | goto discard_it; | 612 | goto discard_it; |
613 | } | 613 | } |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 964ad9d1276d..4183c8dac7f6 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -629,9 +629,7 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) | |||
629 | { | 629 | { |
630 | while(fl) { | 630 | while(fl) { |
631 | seq_printf(seq, | 631 | seq_printf(seq, |
632 | "%05X %-1d %-6d %-6d %-6ld %-8ld " | 632 | "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_FMT " %-4d\n", |
633 | "%02x%02x%02x%02x%02x%02x%02x%02x " | ||
634 | "%-4d\n", | ||
635 | (unsigned)ntohl(fl->label), | 633 | (unsigned)ntohl(fl->label), |
636 | fl->share, | 634 | fl->share, |
637 | (unsigned)fl->owner, | 635 | (unsigned)fl->owner, |
@@ -647,8 +645,8 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) | |||
647 | static int ip6fl_seq_show(struct seq_file *seq, void *v) | 645 | static int ip6fl_seq_show(struct seq_file *seq, void *v) |
648 | { | 646 | { |
649 | if (v == SEQ_START_TOKEN) | 647 | if (v == SEQ_START_TOKEN) |
650 | seq_puts(seq, "Label S Owner Users Linger Expires " | 648 | seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-39s %s\n", |
651 | "Dst Opt\n"); | 649 | "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); |
652 | else | 650 | else |
653 | ip6fl_fl_seq_show(seq, v); | 651 | ip6fl_fl_seq_show(seq, v); |
654 | return 0; | 652 | return 0; |
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 626dd39685f2..d511a884dad0 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -212,8 +212,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
212 | if (!x) | 212 | if (!x) |
213 | return; | 213 | return; |
214 | 214 | ||
215 | printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/" | 215 | printk(KERN_DEBUG "pmtu discovery on SA IPCOMP/%08x/" NIP6_FMT "\n", |
216 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
217 | spi, NIP6(iph->daddr)); | 216 | spi, NIP6(iph->daddr)); |
218 | xfrm_state_put(x); | 217 | xfrm_state_put(x); |
219 | } | 218 | } |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index cc3e9f560867..0e03eabfb9da 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -2373,7 +2373,7 @@ static int igmp6_mc_seq_show(struct seq_file *seq, void *v) | |||
2373 | struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); | 2373 | struct igmp6_mc_iter_state *state = igmp6_mc_seq_private(seq); |
2374 | 2374 | ||
2375 | seq_printf(seq, | 2375 | seq_printf(seq, |
2376 | "%-4d %-15s %04x%04x%04x%04x%04x%04x%04x%04x %5d %08X %ld\n", | 2376 | "%-4d %-15s " NIP6_FMT " %5d %08X %ld\n", |
2377 | state->dev->ifindex, state->dev->name, | 2377 | state->dev->ifindex, state->dev->name, |
2378 | NIP6(im->mca_addr), | 2378 | NIP6(im->mca_addr), |
2379 | im->mca_users, im->mca_flags, | 2379 | im->mca_users, im->mca_flags, |
@@ -2542,15 +2542,12 @@ static int igmp6_mcf_seq_show(struct seq_file *seq, void *v) | |||
2542 | if (v == SEQ_START_TOKEN) { | 2542 | if (v == SEQ_START_TOKEN) { |
2543 | seq_printf(seq, | 2543 | seq_printf(seq, |
2544 | "%3s %6s " | 2544 | "%3s %6s " |
2545 | "%32s %32s %6s %6s\n", "Idx", | 2545 | "%39s %39s %6s %6s\n", "Idx", |
2546 | "Device", "Multicast Address", | 2546 | "Device", "Multicast Address", |
2547 | "Source Address", "INC", "EXC"); | 2547 | "Source Address", "INC", "EXC"); |
2548 | } else { | 2548 | } else { |
2549 | seq_printf(seq, | 2549 | seq_printf(seq, |
2550 | "%3d %6.6s " | 2550 | "%3d %6.6s " NIP6_FMT " " NIP6_FMT " %6lu %6lu\n", |
2551 | "%04x%04x%04x%04x%04x%04x%04x%04x " | ||
2552 | "%04x%04x%04x%04x%04x%04x%04x%04x " | ||
2553 | "%6lu %6lu\n", | ||
2554 | state->dev->ifindex, state->dev->name, | 2551 | state->dev->ifindex, state->dev->name, |
2555 | NIP6(state->im->mca_addr), | 2552 | NIP6(state->im->mca_addr), |
2556 | NIP6(psf->sf_addr), | 2553 | NIP6(psf->sf_addr), |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 305d9ee6d7db..cb8856b1d951 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -692,7 +692,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
692 | if (!(neigh->nud_state & NUD_VALID)) { | 692 | if (!(neigh->nud_state & NUD_VALID)) { |
693 | ND_PRINTK1(KERN_DEBUG | 693 | ND_PRINTK1(KERN_DEBUG |
694 | "%s(): trying to ucast probe in NUD_INVALID: " | 694 | "%s(): trying to ucast probe in NUD_INVALID: " |
695 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | 695 | NIP6_FMT "\n", |
696 | __FUNCTION__, | 696 | __FUNCTION__, |
697 | NIP6(*target)); | 697 | NIP6(*target)); |
698 | } | 698 | } |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 105dd69ee9fb..2d6f8ecbc27b 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -41,6 +41,7 @@ config IP6_NF_QUEUE | |||
41 | 41 | ||
42 | config IP6_NF_IPTABLES | 42 | config IP6_NF_IPTABLES |
43 | tristate "IP6 tables support (required for filtering/masq/NAT)" | 43 | tristate "IP6 tables support (required for filtering/masq/NAT)" |
44 | depends on NETFILTER_XTABLES | ||
44 | help | 45 | help |
45 | ip6tables is a general, extensible packet identification framework. | 46 | ip6tables is a general, extensible packet identification framework. |
46 | Currently only the packet filtering and packet mangling subsystem | 47 | Currently only the packet filtering and packet mangling subsystem |
@@ -50,25 +51,6 @@ config IP6_NF_IPTABLES | |||
50 | To compile it as a module, choose M here. If unsure, say N. | 51 | To compile it as a module, choose M here. If unsure, say N. |
51 | 52 | ||
52 | # The simple matches. | 53 | # The simple matches. |
53 | config IP6_NF_MATCH_LIMIT | ||
54 | tristate "limit match support" | ||
55 | depends on IP6_NF_IPTABLES | ||
56 | help | ||
57 | limit matching allows you to control the rate at which a rule can be | ||
58 | matched: mainly useful in combination with the LOG target ("LOG | ||
59 | target support", below) and to avoid some Denial of Service attacks. | ||
60 | |||
61 | To compile it as a module, choose M here. If unsure, say N. | ||
62 | |||
63 | config IP6_NF_MATCH_MAC | ||
64 | tristate "MAC address match support" | ||
65 | depends on IP6_NF_IPTABLES | ||
66 | help | ||
67 | mac matching allows you to match packets based on the source | ||
68 | Ethernet address of the packet. | ||
69 | |||
70 | To compile it as a module, choose M here. If unsure, say N. | ||
71 | |||
72 | config IP6_NF_MATCH_RT | 54 | config IP6_NF_MATCH_RT |
73 | tristate "Routing header match support" | 55 | tristate "Routing header match support" |
74 | depends on IP6_NF_IPTABLES | 56 | depends on IP6_NF_IPTABLES |
@@ -124,16 +106,6 @@ config IP6_NF_MATCH_OWNER | |||
124 | 106 | ||
125 | To compile it as a module, choose M here. If unsure, say N. | 107 | To compile it as a module, choose M here. If unsure, say N. |
126 | 108 | ||
127 | config IP6_NF_MATCH_MARK | ||
128 | tristate "netfilter MARK match support" | ||
129 | depends on IP6_NF_IPTABLES | ||
130 | help | ||
131 | Netfilter mark matching allows you to match packets based on the | ||
132 | `nfmark' value in the packet. This can be set by the MARK target | ||
133 | (see below). | ||
134 | |||
135 | To compile it as a module, choose M here. If unsure, say N. | ||
136 | |||
137 | config IP6_NF_MATCH_IPV6HEADER | 109 | config IP6_NF_MATCH_IPV6HEADER |
138 | tristate "IPv6 Extension Headers Match" | 110 | tristate "IPv6 Extension Headers Match" |
139 | depends on IP6_NF_IPTABLES | 111 | depends on IP6_NF_IPTABLES |
@@ -151,15 +123,6 @@ config IP6_NF_MATCH_AHESP | |||
151 | 123 | ||
152 | To compile it as a module, choose M here. If unsure, say N. | 124 | To compile it as a module, choose M here. If unsure, say N. |
153 | 125 | ||
154 | config IP6_NF_MATCH_LENGTH | ||
155 | tristate "Packet Length match support" | ||
156 | depends on IP6_NF_IPTABLES | ||
157 | help | ||
158 | This option allows you to match the length of a packet against a | ||
159 | specific value or range of values. | ||
160 | |||
161 | To compile it as a module, choose M here. If unsure, say N. | ||
162 | |||
163 | config IP6_NF_MATCH_EUI64 | 126 | config IP6_NF_MATCH_EUI64 |
164 | tristate "EUI64 address check" | 127 | tristate "EUI64 address check" |
165 | depends on IP6_NF_IPTABLES | 128 | depends on IP6_NF_IPTABLES |
@@ -170,15 +133,6 @@ config IP6_NF_MATCH_EUI64 | |||
170 | 133 | ||
171 | To compile it as a module, choose M here. If unsure, say N. | 134 | To compile it as a module, choose M here. If unsure, say N. |
172 | 135 | ||
173 | config IP6_NF_MATCH_PHYSDEV | ||
174 | tristate "Physdev match support" | ||
175 | depends on IP6_NF_IPTABLES && BRIDGE_NETFILTER | ||
176 | help | ||
177 | Physdev packet matching matches against the physical bridge ports | ||
178 | the IP packet arrived on or will leave by. | ||
179 | |||
180 | To compile it as a module, choose M here. If unsure, say N. | ||
181 | |||
182 | config IP6_NF_MATCH_POLICY | 136 | config IP6_NF_MATCH_POLICY |
183 | tristate "IPsec policy match support" | 137 | tristate "IPsec policy match support" |
184 | depends on IP6_NF_IPTABLES && XFRM | 138 | depends on IP6_NF_IPTABLES && XFRM |
@@ -219,17 +173,6 @@ config IP6_NF_TARGET_REJECT | |||
219 | 173 | ||
220 | To compile it as a module, choose M here. If unsure, say N. | 174 | To compile it as a module, choose M here. If unsure, say N. |
221 | 175 | ||
222 | config IP6_NF_TARGET_NFQUEUE | ||
223 | tristate "NFQUEUE Target Support" | ||
224 | depends on IP6_NF_IPTABLES | ||
225 | help | ||
226 | This Target replaced the old obsolete QUEUE target. | ||
227 | |||
228 | As opposed to QUEUE, it supports 65535 different queues, | ||
229 | not just one. | ||
230 | |||
231 | To compile it as a module, choose M here. If unsure, say N. | ||
232 | |||
233 | config IP6_NF_MANGLE | 176 | config IP6_NF_MANGLE |
234 | tristate "Packet mangling" | 177 | tristate "Packet mangling" |
235 | depends on IP6_NF_IPTABLES | 178 | depends on IP6_NF_IPTABLES |
@@ -240,19 +183,6 @@ config IP6_NF_MANGLE | |||
240 | 183 | ||
241 | To compile it as a module, choose M here. If unsure, say N. | 184 | To compile it as a module, choose M here. If unsure, say N. |
242 | 185 | ||
243 | config IP6_NF_TARGET_MARK | ||
244 | tristate "MARK target support" | ||
245 | depends on IP6_NF_MANGLE | ||
246 | help | ||
247 | This option adds a `MARK' target, which allows you to create rules | ||
248 | in the `mangle' table which alter the netfilter mark (nfmark) field | ||
249 | associated with the packet packet prior to routing. This can change | ||
250 | the routing method (see `Use netfilter MARK value as routing | ||
251 | key') and can also be used by other subsystems to change their | ||
252 | behavior. | ||
253 | |||
254 | To compile it as a module, choose M here. If unsure, say N. | ||
255 | |||
256 | config IP6_NF_TARGET_HL | 186 | config IP6_NF_TARGET_HL |
257 | tristate 'HL (hoplimit) target support' | 187 | tristate 'HL (hoplimit) target support' |
258 | depends on IP6_NF_MANGLE | 188 | depends on IP6_NF_MANGLE |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index c0c809b426e8..663b4749820d 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -4,10 +4,7 @@ | |||
4 | 4 | ||
5 | # Link order matters here. | 5 | # Link order matters here. |
6 | obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o | 6 | obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o |
7 | obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o | ||
8 | obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o | ||
9 | obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o | 7 | obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o |
10 | obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o | ||
11 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o | 8 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o |
12 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o | 9 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o |
13 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o | 10 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o |
@@ -17,12 +14,9 @@ obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o | |||
17 | obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o | 14 | obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o |
18 | obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o | 15 | obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o |
19 | obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o | 16 | obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o |
20 | obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o | ||
21 | obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o | 17 | obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o |
22 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o | 18 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o |
23 | obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o | ||
24 | obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o | 19 | obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o |
25 | obj-$(CONFIG_IP6_NF_TARGET_NFQUEUE) += ip6t_NFQUEUE.o | ||
26 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o | 20 | obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o |
27 | obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o | 21 | obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o |
28 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o | 22 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 1390370186d9..847068fd3367 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -13,6 +13,9 @@ | |||
13 | * a table | 13 | * a table |
14 | * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu> | 14 | * 06 Jun 2002 Andras Kis-Szabo <kisza@sch.bme.hu> |
15 | * - new extension header parser code | 15 | * - new extension header parser code |
16 | * 15 Oct 2005 Harald Welte <laforge@netfilter.org> | ||
17 | * - Unification of {ip,ip6}_tables into x_tables | ||
18 | * - Removed tcp and udp code, since it's not ipv6 specific | ||
16 | */ | 19 | */ |
17 | 20 | ||
18 | #include <linux/capability.h> | 21 | #include <linux/capability.h> |
@@ -23,8 +26,6 @@ | |||
23 | #include <linux/vmalloc.h> | 26 | #include <linux/vmalloc.h> |
24 | #include <linux/netdevice.h> | 27 | #include <linux/netdevice.h> |
25 | #include <linux/module.h> | 28 | #include <linux/module.h> |
26 | #include <linux/tcp.h> | ||
27 | #include <linux/udp.h> | ||
28 | #include <linux/icmpv6.h> | 29 | #include <linux/icmpv6.h> |
29 | #include <net/ipv6.h> | 30 | #include <net/ipv6.h> |
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
@@ -33,6 +34,7 @@ | |||
33 | #include <linux/cpumask.h> | 34 | #include <linux/cpumask.h> |
34 | 35 | ||
35 | #include <linux/netfilter_ipv6/ip6_tables.h> | 36 | #include <linux/netfilter_ipv6/ip6_tables.h> |
37 | #include <linux/netfilter/x_tables.h> | ||
36 | 38 | ||
37 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
38 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 40 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
@@ -67,13 +69,8 @@ do { \ | |||
67 | #else | 69 | #else |
68 | #define IP_NF_ASSERT(x) | 70 | #define IP_NF_ASSERT(x) |
69 | #endif | 71 | #endif |
70 | #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) | ||
71 | 72 | ||
72 | static DECLARE_MUTEX(ip6t_mutex); | ||
73 | 73 | ||
74 | /* Must have mutex */ | ||
75 | #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0) | ||
76 | #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0) | ||
77 | #include <linux/netfilter_ipv4/listhelp.h> | 74 | #include <linux/netfilter_ipv4/listhelp.h> |
78 | 75 | ||
79 | #if 0 | 76 | #if 0 |
@@ -91,30 +88,6 @@ static DECLARE_MUTEX(ip6t_mutex); | |||
91 | 88 | ||
92 | Hence the start of any table is given by get_table() below. */ | 89 | Hence the start of any table is given by get_table() below. */ |
93 | 90 | ||
94 | /* The table itself */ | ||
95 | struct ip6t_table_info | ||
96 | { | ||
97 | /* Size per table */ | ||
98 | unsigned int size; | ||
99 | /* Number of entries: FIXME. --RR */ | ||
100 | unsigned int number; | ||
101 | /* Initial number of entries. Needed for module usage count */ | ||
102 | unsigned int initial_entries; | ||
103 | |||
104 | /* Entry points and underflows */ | ||
105 | unsigned int hook_entry[NF_IP6_NUMHOOKS]; | ||
106 | unsigned int underflow[NF_IP6_NUMHOOKS]; | ||
107 | |||
108 | /* ip6t_entry tables: one per CPU */ | ||
109 | void *entries[NR_CPUS]; | ||
110 | }; | ||
111 | |||
112 | static LIST_HEAD(ip6t_target); | ||
113 | static LIST_HEAD(ip6t_match); | ||
114 | static LIST_HEAD(ip6t_tables); | ||
115 | #define SET_COUNTER(c,b,p) do { (c).bcnt = (b); (c).pcnt = (p); } while(0) | ||
116 | #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) | ||
117 | |||
118 | #if 0 | 91 | #if 0 |
119 | #define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) | 92 | #define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0) |
120 | #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) | 93 | #define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; }) |
@@ -297,7 +270,7 @@ ip6t_do_table(struct sk_buff **pskb, | |||
297 | unsigned int hook, | 270 | unsigned int hook, |
298 | const struct net_device *in, | 271 | const struct net_device *in, |
299 | const struct net_device *out, | 272 | const struct net_device *out, |
300 | struct ip6t_table *table, | 273 | struct xt_table *table, |
301 | void *userdata) | 274 | void *userdata) |
302 | { | 275 | { |
303 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); | 276 | static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long)))); |
@@ -309,6 +282,7 @@ ip6t_do_table(struct sk_buff **pskb, | |||
309 | const char *indev, *outdev; | 282 | const char *indev, *outdev; |
310 | void *table_base; | 283 | void *table_base; |
311 | struct ip6t_entry *e, *back; | 284 | struct ip6t_entry *e, *back; |
285 | struct xt_table_info *private; | ||
312 | 286 | ||
313 | /* Initialization */ | 287 | /* Initialization */ |
314 | indev = in ? in->name : nulldevname; | 288 | indev = in ? in->name : nulldevname; |
@@ -321,9 +295,10 @@ ip6t_do_table(struct sk_buff **pskb, | |||
321 | * match it. */ | 295 | * match it. */ |
322 | 296 | ||
323 | read_lock_bh(&table->lock); | 297 | read_lock_bh(&table->lock); |
298 | private = table->private; | ||
324 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 299 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
325 | table_base = (void *)table->private->entries[smp_processor_id()]; | 300 | table_base = (void *)private->entries[smp_processor_id()]; |
326 | e = get_entry(table_base, table->private->hook_entry[hook]); | 301 | e = get_entry(table_base, private->hook_entry[hook]); |
327 | 302 | ||
328 | #ifdef CONFIG_NETFILTER_DEBUG | 303 | #ifdef CONFIG_NETFILTER_DEBUG |
329 | /* Check noone else using our table */ | 304 | /* Check noone else using our table */ |
@@ -339,7 +314,7 @@ ip6t_do_table(struct sk_buff **pskb, | |||
339 | #endif | 314 | #endif |
340 | 315 | ||
341 | /* For return from builtin chain */ | 316 | /* For return from builtin chain */ |
342 | back = get_entry(table_base, table->private->underflow[hook]); | 317 | back = get_entry(table_base, private->underflow[hook]); |
343 | 318 | ||
344 | do { | 319 | do { |
345 | IP_NF_ASSERT(e); | 320 | IP_NF_ASSERT(e); |
@@ -439,145 +414,6 @@ ip6t_do_table(struct sk_buff **pskb, | |||
439 | #endif | 414 | #endif |
440 | } | 415 | } |
441 | 416 | ||
442 | /* | ||
443 | * These are weird, but module loading must not be done with mutex | ||
444 | * held (since they will register), and we have to have a single | ||
445 | * function to use try_then_request_module(). | ||
446 | */ | ||
447 | |||
448 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ | ||
449 | static inline struct ip6t_table *find_table_lock(const char *name) | ||
450 | { | ||
451 | struct ip6t_table *t; | ||
452 | |||
453 | if (down_interruptible(&ip6t_mutex) != 0) | ||
454 | return ERR_PTR(-EINTR); | ||
455 | |||
456 | list_for_each_entry(t, &ip6t_tables, list) | ||
457 | if (strcmp(t->name, name) == 0 && try_module_get(t->me)) | ||
458 | return t; | ||
459 | up(&ip6t_mutex); | ||
460 | return NULL; | ||
461 | } | ||
462 | |||
463 | /* Find match, grabs ref. Returns ERR_PTR() on error. */ | ||
464 | static inline struct ip6t_match *find_match(const char *name, u8 revision) | ||
465 | { | ||
466 | struct ip6t_match *m; | ||
467 | int err = 0; | ||
468 | |||
469 | if (down_interruptible(&ip6t_mutex) != 0) | ||
470 | return ERR_PTR(-EINTR); | ||
471 | |||
472 | list_for_each_entry(m, &ip6t_match, list) { | ||
473 | if (strcmp(m->name, name) == 0) { | ||
474 | if (m->revision == revision) { | ||
475 | if (try_module_get(m->me)) { | ||
476 | up(&ip6t_mutex); | ||
477 | return m; | ||
478 | } | ||
479 | } else | ||
480 | err = -EPROTOTYPE; /* Found something. */ | ||
481 | } | ||
482 | } | ||
483 | up(&ip6t_mutex); | ||
484 | return ERR_PTR(err); | ||
485 | } | ||
486 | |||
487 | /* Find target, grabs ref. Returns ERR_PTR() on error. */ | ||
488 | static inline struct ip6t_target *find_target(const char *name, u8 revision) | ||
489 | { | ||
490 | struct ip6t_target *t; | ||
491 | int err = 0; | ||
492 | |||
493 | if (down_interruptible(&ip6t_mutex) != 0) | ||
494 | return ERR_PTR(-EINTR); | ||
495 | |||
496 | list_for_each_entry(t, &ip6t_target, list) { | ||
497 | if (strcmp(t->name, name) == 0) { | ||
498 | if (t->revision == revision) { | ||
499 | if (try_module_get(t->me)) { | ||
500 | up(&ip6t_mutex); | ||
501 | return t; | ||
502 | } | ||
503 | } else | ||
504 | err = -EPROTOTYPE; /* Found something. */ | ||
505 | } | ||
506 | } | ||
507 | up(&ip6t_mutex); | ||
508 | return ERR_PTR(err); | ||
509 | } | ||
510 | |||
511 | struct ip6t_target *ip6t_find_target(const char *name, u8 revision) | ||
512 | { | ||
513 | struct ip6t_target *target; | ||
514 | |||
515 | target = try_then_request_module(find_target(name, revision), | ||
516 | "ip6t_%s", name); | ||
517 | if (IS_ERR(target) || !target) | ||
518 | return NULL; | ||
519 | return target; | ||
520 | } | ||
521 | |||
522 | static int match_revfn(const char *name, u8 revision, int *bestp) | ||
523 | { | ||
524 | struct ip6t_match *m; | ||
525 | int have_rev = 0; | ||
526 | |||
527 | list_for_each_entry(m, &ip6t_match, list) { | ||
528 | if (strcmp(m->name, name) == 0) { | ||
529 | if (m->revision > *bestp) | ||
530 | *bestp = m->revision; | ||
531 | if (m->revision == revision) | ||
532 | have_rev = 1; | ||
533 | } | ||
534 | } | ||
535 | return have_rev; | ||
536 | } | ||
537 | |||
538 | static int target_revfn(const char *name, u8 revision, int *bestp) | ||
539 | { | ||
540 | struct ip6t_target *t; | ||
541 | int have_rev = 0; | ||
542 | |||
543 | list_for_each_entry(t, &ip6t_target, list) { | ||
544 | if (strcmp(t->name, name) == 0) { | ||
545 | if (t->revision > *bestp) | ||
546 | *bestp = t->revision; | ||
547 | if (t->revision == revision) | ||
548 | have_rev = 1; | ||
549 | } | ||
550 | } | ||
551 | return have_rev; | ||
552 | } | ||
553 | |||
554 | /* Returns true or fals (if no such extension at all) */ | ||
555 | static inline int find_revision(const char *name, u8 revision, | ||
556 | int (*revfn)(const char *, u8, int *), | ||
557 | int *err) | ||
558 | { | ||
559 | int have_rev, best = -1; | ||
560 | |||
561 | if (down_interruptible(&ip6t_mutex) != 0) { | ||
562 | *err = -EINTR; | ||
563 | return 1; | ||
564 | } | ||
565 | have_rev = revfn(name, revision, &best); | ||
566 | up(&ip6t_mutex); | ||
567 | |||
568 | /* Nothing at all? Return 0 to try loading module. */ | ||
569 | if (best == -1) { | ||
570 | *err = -ENOENT; | ||
571 | return 0; | ||
572 | } | ||
573 | |||
574 | *err = best; | ||
575 | if (!have_rev) | ||
576 | *err = -EPROTONOSUPPORT; | ||
577 | return 1; | ||
578 | } | ||
579 | |||
580 | |||
581 | /* All zeroes == unconditional rule. */ | 417 | /* All zeroes == unconditional rule. */ |
582 | static inline int | 418 | static inline int |
583 | unconditional(const struct ip6t_ip6 *ipv6) | 419 | unconditional(const struct ip6t_ip6 *ipv6) |
@@ -594,7 +430,7 @@ unconditional(const struct ip6t_ip6 *ipv6) | |||
594 | /* Figures out from what hook each rule can be called: returns 0 if | 430 | /* Figures out from what hook each rule can be called: returns 0 if |
595 | there are loops. Puts hook bitmask in comefrom. */ | 431 | there are loops. Puts hook bitmask in comefrom. */ |
596 | static int | 432 | static int |
597 | mark_source_chains(struct ip6t_table_info *newinfo, | 433 | mark_source_chains(struct xt_table_info *newinfo, |
598 | unsigned int valid_hooks, void *entry0) | 434 | unsigned int valid_hooks, void *entry0) |
599 | { | 435 | { |
600 | unsigned int hook; | 436 | unsigned int hook; |
@@ -740,11 +576,11 @@ check_match(struct ip6t_entry_match *m, | |||
740 | { | 576 | { |
741 | struct ip6t_match *match; | 577 | struct ip6t_match *match; |
742 | 578 | ||
743 | match = try_then_request_module(find_match(m->u.user.name, | 579 | match = try_then_request_module(xt_find_match(AF_INET6, m->u.user.name, |
744 | m->u.user.revision), | 580 | m->u.user.revision), |
745 | "ip6t_%s", m->u.user.name); | 581 | "ip6t_%s", m->u.user.name); |
746 | if (IS_ERR(match) || !match) { | 582 | if (IS_ERR(match) || !match) { |
747 | duprintf("check_match: `%s' not found\n", m->u.user.name); | 583 | duprintf("check_match: `%s' not found\n", m->u.user.name); |
748 | return match ? PTR_ERR(match) : -ENOENT; | 584 | return match ? PTR_ERR(match) : -ENOENT; |
749 | } | 585 | } |
750 | m->u.kernel.match = match; | 586 | m->u.kernel.match = match; |
@@ -785,8 +621,9 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, | |||
785 | goto cleanup_matches; | 621 | goto cleanup_matches; |
786 | 622 | ||
787 | t = ip6t_get_target(e); | 623 | t = ip6t_get_target(e); |
788 | target = try_then_request_module(find_target(t->u.user.name, | 624 | target = try_then_request_module(xt_find_target(AF_INET6, |
789 | t->u.user.revision), | 625 | t->u.user.name, |
626 | t->u.user.revision), | ||
790 | "ip6t_%s", t->u.user.name); | 627 | "ip6t_%s", t->u.user.name); |
791 | if (IS_ERR(target) || !target) { | 628 | if (IS_ERR(target) || !target) { |
792 | duprintf("check_entry: `%s' not found\n", t->u.user.name); | 629 | duprintf("check_entry: `%s' not found\n", t->u.user.name); |
@@ -822,7 +659,7 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, | |||
822 | 659 | ||
823 | static inline int | 660 | static inline int |
824 | check_entry_size_and_hooks(struct ip6t_entry *e, | 661 | check_entry_size_and_hooks(struct ip6t_entry *e, |
825 | struct ip6t_table_info *newinfo, | 662 | struct xt_table_info *newinfo, |
826 | unsigned char *base, | 663 | unsigned char *base, |
827 | unsigned char *limit, | 664 | unsigned char *limit, |
828 | const unsigned int *hook_entries, | 665 | const unsigned int *hook_entries, |
@@ -856,7 +693,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e, | |||
856 | < 0 (not IP6T_RETURN). --RR */ | 693 | < 0 (not IP6T_RETURN). --RR */ |
857 | 694 | ||
858 | /* Clear counters and comefrom */ | 695 | /* Clear counters and comefrom */ |
859 | e->counters = ((struct ip6t_counters) { 0, 0 }); | 696 | e->counters = ((struct xt_counters) { 0, 0 }); |
860 | e->comefrom = 0; | 697 | e->comefrom = 0; |
861 | 698 | ||
862 | (*i)++; | 699 | (*i)++; |
@@ -886,7 +723,7 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i) | |||
886 | static int | 723 | static int |
887 | translate_table(const char *name, | 724 | translate_table(const char *name, |
888 | unsigned int valid_hooks, | 725 | unsigned int valid_hooks, |
889 | struct ip6t_table_info *newinfo, | 726 | struct xt_table_info *newinfo, |
890 | void *entry0, | 727 | void *entry0, |
891 | unsigned int size, | 728 | unsigned int size, |
892 | unsigned int number, | 729 | unsigned int number, |
@@ -963,48 +800,10 @@ translate_table(const char *name, | |||
963 | return ret; | 800 | return ret; |
964 | } | 801 | } |
965 | 802 | ||
966 | static struct ip6t_table_info * | ||
967 | replace_table(struct ip6t_table *table, | ||
968 | unsigned int num_counters, | ||
969 | struct ip6t_table_info *newinfo, | ||
970 | int *error) | ||
971 | { | ||
972 | struct ip6t_table_info *oldinfo; | ||
973 | |||
974 | #ifdef CONFIG_NETFILTER_DEBUG | ||
975 | { | ||
976 | int cpu; | ||
977 | |||
978 | for_each_cpu(cpu) { | ||
979 | struct ip6t_entry *table_base = newinfo->entries[cpu]; | ||
980 | if (table_base) | ||
981 | table_base->comefrom = 0xdead57ac; | ||
982 | } | ||
983 | } | ||
984 | #endif | ||
985 | |||
986 | /* Do the substitution. */ | ||
987 | write_lock_bh(&table->lock); | ||
988 | /* Check inside lock: is the old number correct? */ | ||
989 | if (num_counters != table->private->number) { | ||
990 | duprintf("num_counters != table->private->number (%u/%u)\n", | ||
991 | num_counters, table->private->number); | ||
992 | write_unlock_bh(&table->lock); | ||
993 | *error = -EAGAIN; | ||
994 | return NULL; | ||
995 | } | ||
996 | oldinfo = table->private; | ||
997 | table->private = newinfo; | ||
998 | newinfo->initial_entries = oldinfo->initial_entries; | ||
999 | write_unlock_bh(&table->lock); | ||
1000 | |||
1001 | return oldinfo; | ||
1002 | } | ||
1003 | |||
1004 | /* Gets counters. */ | 803 | /* Gets counters. */ |
1005 | static inline int | 804 | static inline int |
1006 | add_entry_to_counter(const struct ip6t_entry *e, | 805 | add_entry_to_counter(const struct ip6t_entry *e, |
1007 | struct ip6t_counters total[], | 806 | struct xt_counters total[], |
1008 | unsigned int *i) | 807 | unsigned int *i) |
1009 | { | 808 | { |
1010 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); | 809 | ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt); |
@@ -1025,8 +824,8 @@ set_entry_to_counter(const struct ip6t_entry *e, | |||
1025 | } | 824 | } |
1026 | 825 | ||
1027 | static void | 826 | static void |
1028 | get_counters(const struct ip6t_table_info *t, | 827 | get_counters(const struct xt_table_info *t, |
1029 | struct ip6t_counters counters[]) | 828 | struct xt_counters counters[]) |
1030 | { | 829 | { |
1031 | unsigned int cpu; | 830 | unsigned int cpu; |
1032 | unsigned int i; | 831 | unsigned int i; |
@@ -1060,19 +859,20 @@ get_counters(const struct ip6t_table_info *t, | |||
1060 | 859 | ||
1061 | static int | 860 | static int |
1062 | copy_entries_to_user(unsigned int total_size, | 861 | copy_entries_to_user(unsigned int total_size, |
1063 | struct ip6t_table *table, | 862 | struct xt_table *table, |
1064 | void __user *userptr) | 863 | void __user *userptr) |
1065 | { | 864 | { |
1066 | unsigned int off, num, countersize; | 865 | unsigned int off, num, countersize; |
1067 | struct ip6t_entry *e; | 866 | struct ip6t_entry *e; |
1068 | struct ip6t_counters *counters; | 867 | struct xt_counters *counters; |
868 | struct xt_table_info *private = table->private; | ||
1069 | int ret = 0; | 869 | int ret = 0; |
1070 | void *loc_cpu_entry; | 870 | void *loc_cpu_entry; |
1071 | 871 | ||
1072 | /* We need atomic snapshot of counters: rest doesn't change | 872 | /* We need atomic snapshot of counters: rest doesn't change |
1073 | (other than comefrom, which userspace doesn't care | 873 | (other than comefrom, which userspace doesn't care |
1074 | about). */ | 874 | about). */ |
1075 | countersize = sizeof(struct ip6t_counters) * table->private->number; | 875 | countersize = sizeof(struct xt_counters) * private->number; |
1076 | counters = vmalloc(countersize); | 876 | counters = vmalloc(countersize); |
1077 | 877 | ||
1078 | if (counters == NULL) | 878 | if (counters == NULL) |
@@ -1080,11 +880,11 @@ copy_entries_to_user(unsigned int total_size, | |||
1080 | 880 | ||
1081 | /* First, sum counters... */ | 881 | /* First, sum counters... */ |
1082 | write_lock_bh(&table->lock); | 882 | write_lock_bh(&table->lock); |
1083 | get_counters(table->private, counters); | 883 | get_counters(private, counters); |
1084 | write_unlock_bh(&table->lock); | 884 | write_unlock_bh(&table->lock); |
1085 | 885 | ||
1086 | /* choose the copy that is on ourc node/cpu */ | 886 | /* choose the copy that is on ourc node/cpu */ |
1087 | loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; | 887 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
1088 | if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { | 888 | if (copy_to_user(userptr, loc_cpu_entry, total_size) != 0) { |
1089 | ret = -EFAULT; | 889 | ret = -EFAULT; |
1090 | goto free_counters; | 890 | goto free_counters; |
@@ -1143,87 +943,42 @@ get_entries(const struct ip6t_get_entries *entries, | |||
1143 | struct ip6t_get_entries __user *uptr) | 943 | struct ip6t_get_entries __user *uptr) |
1144 | { | 944 | { |
1145 | int ret; | 945 | int ret; |
1146 | struct ip6t_table *t; | 946 | struct xt_table *t; |
1147 | 947 | ||
1148 | t = find_table_lock(entries->name); | 948 | t = xt_find_table_lock(AF_INET6, entries->name); |
1149 | if (t && !IS_ERR(t)) { | 949 | if (t && !IS_ERR(t)) { |
1150 | duprintf("t->private->number = %u\n", | 950 | struct xt_table_info *private = t->private; |
1151 | t->private->number); | 951 | duprintf("t->private->number = %u\n", private->number); |
1152 | if (entries->size == t->private->size) | 952 | if (entries->size == private->size) |
1153 | ret = copy_entries_to_user(t->private->size, | 953 | ret = copy_entries_to_user(private->size, |
1154 | t, uptr->entrytable); | 954 | t, uptr->entrytable); |
1155 | else { | 955 | else { |
1156 | duprintf("get_entries: I've got %u not %u!\n", | 956 | duprintf("get_entries: I've got %u not %u!\n", |
1157 | t->private->size, | 957 | private->size, entries->size); |
1158 | entries->size); | ||
1159 | ret = -EINVAL; | 958 | ret = -EINVAL; |
1160 | } | 959 | } |
1161 | module_put(t->me); | 960 | module_put(t->me); |
1162 | up(&ip6t_mutex); | 961 | xt_table_unlock(t); |
1163 | } else | 962 | } else |
1164 | ret = t ? PTR_ERR(t) : -ENOENT; | 963 | ret = t ? PTR_ERR(t) : -ENOENT; |
1165 | 964 | ||
1166 | return ret; | 965 | return ret; |
1167 | } | 966 | } |
1168 | 967 | ||
1169 | static void free_table_info(struct ip6t_table_info *info) | ||
1170 | { | ||
1171 | int cpu; | ||
1172 | for_each_cpu(cpu) { | ||
1173 | if (info->size <= PAGE_SIZE) | ||
1174 | kfree(info->entries[cpu]); | ||
1175 | else | ||
1176 | vfree(info->entries[cpu]); | ||
1177 | } | ||
1178 | kfree(info); | ||
1179 | } | ||
1180 | |||
1181 | static struct ip6t_table_info *alloc_table_info(unsigned int size) | ||
1182 | { | ||
1183 | struct ip6t_table_info *newinfo; | ||
1184 | int cpu; | ||
1185 | |||
1186 | newinfo = kzalloc(sizeof(struct ip6t_table_info), GFP_KERNEL); | ||
1187 | if (!newinfo) | ||
1188 | return NULL; | ||
1189 | |||
1190 | newinfo->size = size; | ||
1191 | |||
1192 | for_each_cpu(cpu) { | ||
1193 | if (size <= PAGE_SIZE) | ||
1194 | newinfo->entries[cpu] = kmalloc_node(size, | ||
1195 | GFP_KERNEL, | ||
1196 | cpu_to_node(cpu)); | ||
1197 | else | ||
1198 | newinfo->entries[cpu] = vmalloc_node(size, | ||
1199 | cpu_to_node(cpu)); | ||
1200 | if (newinfo->entries[cpu] == NULL) { | ||
1201 | free_table_info(newinfo); | ||
1202 | return NULL; | ||
1203 | } | ||
1204 | } | ||
1205 | |||
1206 | return newinfo; | ||
1207 | } | ||
1208 | |||
1209 | static int | 968 | static int |
1210 | do_replace(void __user *user, unsigned int len) | 969 | do_replace(void __user *user, unsigned int len) |
1211 | { | 970 | { |
1212 | int ret; | 971 | int ret; |
1213 | struct ip6t_replace tmp; | 972 | struct ip6t_replace tmp; |
1214 | struct ip6t_table *t; | 973 | struct xt_table *t; |
1215 | struct ip6t_table_info *newinfo, *oldinfo; | 974 | struct xt_table_info *newinfo, *oldinfo; |
1216 | struct ip6t_counters *counters; | 975 | struct xt_counters *counters; |
1217 | void *loc_cpu_entry, *loc_cpu_old_entry; | 976 | void *loc_cpu_entry, *loc_cpu_old_entry; |
1218 | 977 | ||
1219 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 978 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
1220 | return -EFAULT; | 979 | return -EFAULT; |
1221 | 980 | ||
1222 | /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ | 981 | newinfo = xt_alloc_table_info(tmp.size); |
1223 | if ((SMP_ALIGN(tmp.size) >> PAGE_SHIFT) + 2 > num_physpages) | ||
1224 | return -ENOMEM; | ||
1225 | |||
1226 | newinfo = alloc_table_info(tmp.size); | ||
1227 | if (!newinfo) | 982 | if (!newinfo) |
1228 | return -ENOMEM; | 983 | return -ENOMEM; |
1229 | 984 | ||
@@ -1235,7 +990,7 @@ do_replace(void __user *user, unsigned int len) | |||
1235 | goto free_newinfo; | 990 | goto free_newinfo; |
1236 | } | 991 | } |
1237 | 992 | ||
1238 | counters = vmalloc(tmp.num_counters * sizeof(struct ip6t_counters)); | 993 | counters = vmalloc(tmp.num_counters * sizeof(struct xt_counters)); |
1239 | if (!counters) { | 994 | if (!counters) { |
1240 | ret = -ENOMEM; | 995 | ret = -ENOMEM; |
1241 | goto free_newinfo; | 996 | goto free_newinfo; |
@@ -1249,7 +1004,7 @@ do_replace(void __user *user, unsigned int len) | |||
1249 | 1004 | ||
1250 | duprintf("ip_tables: Translated table\n"); | 1005 | duprintf("ip_tables: Translated table\n"); |
1251 | 1006 | ||
1252 | t = try_then_request_module(find_table_lock(tmp.name), | 1007 | t = try_then_request_module(xt_find_table_lock(AF_INET6, tmp.name), |
1253 | "ip6table_%s", tmp.name); | 1008 | "ip6table_%s", tmp.name); |
1254 | if (!t || IS_ERR(t)) { | 1009 | if (!t || IS_ERR(t)) { |
1255 | ret = t ? PTR_ERR(t) : -ENOENT; | 1010 | ret = t ? PTR_ERR(t) : -ENOENT; |
@@ -1264,7 +1019,7 @@ do_replace(void __user *user, unsigned int len) | |||
1264 | goto put_module; | 1019 | goto put_module; |
1265 | } | 1020 | } |
1266 | 1021 | ||
1267 | oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret); | 1022 | oldinfo = xt_replace_table(t, tmp.num_counters, newinfo, &ret); |
1268 | if (!oldinfo) | 1023 | if (!oldinfo) |
1269 | goto put_module; | 1024 | goto put_module; |
1270 | 1025 | ||
@@ -1283,23 +1038,23 @@ do_replace(void __user *user, unsigned int len) | |||
1283 | /* Decrease module usage counts and free resource */ | 1038 | /* Decrease module usage counts and free resource */ |
1284 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; | 1039 | loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; |
1285 | IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); | 1040 | IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,NULL); |
1286 | free_table_info(oldinfo); | 1041 | xt_free_table_info(oldinfo); |
1287 | if (copy_to_user(tmp.counters, counters, | 1042 | if (copy_to_user(tmp.counters, counters, |
1288 | sizeof(struct ip6t_counters) * tmp.num_counters) != 0) | 1043 | sizeof(struct xt_counters) * tmp.num_counters) != 0) |
1289 | ret = -EFAULT; | 1044 | ret = -EFAULT; |
1290 | vfree(counters); | 1045 | vfree(counters); |
1291 | up(&ip6t_mutex); | 1046 | xt_table_unlock(t); |
1292 | return ret; | 1047 | return ret; |
1293 | 1048 | ||
1294 | put_module: | 1049 | put_module: |
1295 | module_put(t->me); | 1050 | module_put(t->me); |
1296 | up(&ip6t_mutex); | 1051 | xt_table_unlock(t); |
1297 | free_newinfo_counters_untrans: | 1052 | free_newinfo_counters_untrans: |
1298 | IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); | 1053 | IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry,NULL); |
1299 | free_newinfo_counters: | 1054 | free_newinfo_counters: |
1300 | vfree(counters); | 1055 | vfree(counters); |
1301 | free_newinfo: | 1056 | free_newinfo: |
1302 | free_table_info(newinfo); | 1057 | xt_free_table_info(newinfo); |
1303 | return ret; | 1058 | return ret; |
1304 | } | 1059 | } |
1305 | 1060 | ||
@@ -1307,7 +1062,7 @@ do_replace(void __user *user, unsigned int len) | |||
1307 | * and everything is OK. */ | 1062 | * and everything is OK. */ |
1308 | static inline int | 1063 | static inline int |
1309 | add_counter_to_entry(struct ip6t_entry *e, | 1064 | add_counter_to_entry(struct ip6t_entry *e, |
1310 | const struct ip6t_counters addme[], | 1065 | const struct xt_counters addme[], |
1311 | unsigned int *i) | 1066 | unsigned int *i) |
1312 | { | 1067 | { |
1313 | #if 0 | 1068 | #if 0 |
@@ -1329,15 +1084,16 @@ static int | |||
1329 | do_add_counters(void __user *user, unsigned int len) | 1084 | do_add_counters(void __user *user, unsigned int len) |
1330 | { | 1085 | { |
1331 | unsigned int i; | 1086 | unsigned int i; |
1332 | struct ip6t_counters_info tmp, *paddc; | 1087 | struct xt_counters_info tmp, *paddc; |
1333 | struct ip6t_table *t; | 1088 | struct xt_table_info *private; |
1089 | struct xt_table *t; | ||
1334 | int ret = 0; | 1090 | int ret = 0; |
1335 | void *loc_cpu_entry; | 1091 | void *loc_cpu_entry; |
1336 | 1092 | ||
1337 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) | 1093 | if (copy_from_user(&tmp, user, sizeof(tmp)) != 0) |
1338 | return -EFAULT; | 1094 | return -EFAULT; |
1339 | 1095 | ||
1340 | if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ip6t_counters)) | 1096 | if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct xt_counters)) |
1341 | return -EINVAL; | 1097 | return -EINVAL; |
1342 | 1098 | ||
1343 | paddc = vmalloc(len); | 1099 | paddc = vmalloc(len); |
@@ -1349,29 +1105,30 @@ do_add_counters(void __user *user, unsigned int len) | |||
1349 | goto free; | 1105 | goto free; |
1350 | } | 1106 | } |
1351 | 1107 | ||
1352 | t = find_table_lock(tmp.name); | 1108 | t = xt_find_table_lock(AF_INET6, tmp.name); |
1353 | if (!t || IS_ERR(t)) { | 1109 | if (!t || IS_ERR(t)) { |
1354 | ret = t ? PTR_ERR(t) : -ENOENT; | 1110 | ret = t ? PTR_ERR(t) : -ENOENT; |
1355 | goto free; | 1111 | goto free; |
1356 | } | 1112 | } |
1357 | 1113 | ||
1358 | write_lock_bh(&t->lock); | 1114 | write_lock_bh(&t->lock); |
1359 | if (t->private->number != paddc->num_counters) { | 1115 | private = t->private; |
1116 | if (private->number != paddc->num_counters) { | ||
1360 | ret = -EINVAL; | 1117 | ret = -EINVAL; |
1361 | goto unlock_up_free; | 1118 | goto unlock_up_free; |
1362 | } | 1119 | } |
1363 | 1120 | ||
1364 | i = 0; | 1121 | i = 0; |
1365 | /* Choose the copy that is on our node */ | 1122 | /* Choose the copy that is on our node */ |
1366 | loc_cpu_entry = t->private->entries[smp_processor_id()]; | 1123 | loc_cpu_entry = private->entries[smp_processor_id()]; |
1367 | IP6T_ENTRY_ITERATE(loc_cpu_entry, | 1124 | IP6T_ENTRY_ITERATE(loc_cpu_entry, |
1368 | t->private->size, | 1125 | private->size, |
1369 | add_counter_to_entry, | 1126 | add_counter_to_entry, |
1370 | paddc->counters, | 1127 | paddc->counters, |
1371 | &i); | 1128 | &i); |
1372 | unlock_up_free: | 1129 | unlock_up_free: |
1373 | write_unlock_bh(&t->lock); | 1130 | write_unlock_bh(&t->lock); |
1374 | up(&ip6t_mutex); | 1131 | xt_table_unlock(t); |
1375 | module_put(t->me); | 1132 | module_put(t->me); |
1376 | free: | 1133 | free: |
1377 | vfree(paddc); | 1134 | vfree(paddc); |
@@ -1415,7 +1172,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1415 | switch (cmd) { | 1172 | switch (cmd) { |
1416 | case IP6T_SO_GET_INFO: { | 1173 | case IP6T_SO_GET_INFO: { |
1417 | char name[IP6T_TABLE_MAXNAMELEN]; | 1174 | char name[IP6T_TABLE_MAXNAMELEN]; |
1418 | struct ip6t_table *t; | 1175 | struct xt_table *t; |
1419 | 1176 | ||
1420 | if (*len != sizeof(struct ip6t_getinfo)) { | 1177 | if (*len != sizeof(struct ip6t_getinfo)) { |
1421 | duprintf("length %u != %u\n", *len, | 1178 | duprintf("length %u != %u\n", *len, |
@@ -1430,25 +1187,26 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1430 | } | 1187 | } |
1431 | name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; | 1188 | name[IP6T_TABLE_MAXNAMELEN-1] = '\0'; |
1432 | 1189 | ||
1433 | t = try_then_request_module(find_table_lock(name), | 1190 | t = try_then_request_module(xt_find_table_lock(AF_INET6, name), |
1434 | "ip6table_%s", name); | 1191 | "ip6table_%s", name); |
1435 | if (t && !IS_ERR(t)) { | 1192 | if (t && !IS_ERR(t)) { |
1436 | struct ip6t_getinfo info; | 1193 | struct ip6t_getinfo info; |
1194 | struct xt_table_info *private = t->private; | ||
1437 | 1195 | ||
1438 | info.valid_hooks = t->valid_hooks; | 1196 | info.valid_hooks = t->valid_hooks; |
1439 | memcpy(info.hook_entry, t->private->hook_entry, | 1197 | memcpy(info.hook_entry, private->hook_entry, |
1440 | sizeof(info.hook_entry)); | 1198 | sizeof(info.hook_entry)); |
1441 | memcpy(info.underflow, t->private->underflow, | 1199 | memcpy(info.underflow, private->underflow, |
1442 | sizeof(info.underflow)); | 1200 | sizeof(info.underflow)); |
1443 | info.num_entries = t->private->number; | 1201 | info.num_entries = private->number; |
1444 | info.size = t->private->size; | 1202 | info.size = private->size; |
1445 | memcpy(info.name, name, sizeof(info.name)); | 1203 | memcpy(info.name, name, sizeof(info.name)); |
1446 | 1204 | ||
1447 | if (copy_to_user(user, &info, *len) != 0) | 1205 | if (copy_to_user(user, &info, *len) != 0) |
1448 | ret = -EFAULT; | 1206 | ret = -EFAULT; |
1449 | else | 1207 | else |
1450 | ret = 0; | 1208 | ret = 0; |
1451 | up(&ip6t_mutex); | 1209 | xt_table_unlock(t); |
1452 | module_put(t->me); | 1210 | module_put(t->me); |
1453 | } else | 1211 | } else |
1454 | ret = t ? PTR_ERR(t) : -ENOENT; | 1212 | ret = t ? PTR_ERR(t) : -ENOENT; |
@@ -1475,7 +1233,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1475 | case IP6T_SO_GET_REVISION_MATCH: | 1233 | case IP6T_SO_GET_REVISION_MATCH: |
1476 | case IP6T_SO_GET_REVISION_TARGET: { | 1234 | case IP6T_SO_GET_REVISION_TARGET: { |
1477 | struct ip6t_get_revision rev; | 1235 | struct ip6t_get_revision rev; |
1478 | int (*revfn)(const char *, u8, int *); | 1236 | int target; |
1479 | 1237 | ||
1480 | if (*len != sizeof(rev)) { | 1238 | if (*len != sizeof(rev)) { |
1481 | ret = -EINVAL; | 1239 | ret = -EINVAL; |
@@ -1487,12 +1245,13 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1487 | } | 1245 | } |
1488 | 1246 | ||
1489 | if (cmd == IP6T_SO_GET_REVISION_TARGET) | 1247 | if (cmd == IP6T_SO_GET_REVISION_TARGET) |
1490 | revfn = target_revfn; | 1248 | target = 1; |
1491 | else | 1249 | else |
1492 | revfn = match_revfn; | 1250 | target = 0; |
1493 | 1251 | ||
1494 | try_then_request_module(find_revision(rev.name, rev.revision, | 1252 | try_then_request_module(xt_find_revision(AF_INET6, rev.name, |
1495 | revfn, &ret), | 1253 | rev.revision, |
1254 | target, &ret), | ||
1496 | "ip6t_%s", rev.name); | 1255 | "ip6t_%s", rev.name); |
1497 | break; | 1256 | break; |
1498 | } | 1257 | } |
@@ -1505,61 +1264,16 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
1505 | return ret; | 1264 | return ret; |
1506 | } | 1265 | } |
1507 | 1266 | ||
1508 | /* Registration hooks for targets. */ | 1267 | int ip6t_register_table(struct xt_table *table, |
1509 | int | ||
1510 | ip6t_register_target(struct ip6t_target *target) | ||
1511 | { | ||
1512 | int ret; | ||
1513 | |||
1514 | ret = down_interruptible(&ip6t_mutex); | ||
1515 | if (ret != 0) | ||
1516 | return ret; | ||
1517 | list_add(&target->list, &ip6t_target); | ||
1518 | up(&ip6t_mutex); | ||
1519 | return ret; | ||
1520 | } | ||
1521 | |||
1522 | void | ||
1523 | ip6t_unregister_target(struct ip6t_target *target) | ||
1524 | { | ||
1525 | down(&ip6t_mutex); | ||
1526 | LIST_DELETE(&ip6t_target, target); | ||
1527 | up(&ip6t_mutex); | ||
1528 | } | ||
1529 | |||
1530 | int | ||
1531 | ip6t_register_match(struct ip6t_match *match) | ||
1532 | { | ||
1533 | int ret; | ||
1534 | |||
1535 | ret = down_interruptible(&ip6t_mutex); | ||
1536 | if (ret != 0) | ||
1537 | return ret; | ||
1538 | |||
1539 | list_add(&match->list, &ip6t_match); | ||
1540 | up(&ip6t_mutex); | ||
1541 | |||
1542 | return ret; | ||
1543 | } | ||
1544 | |||
1545 | void | ||
1546 | ip6t_unregister_match(struct ip6t_match *match) | ||
1547 | { | ||
1548 | down(&ip6t_mutex); | ||
1549 | LIST_DELETE(&ip6t_match, match); | ||
1550 | up(&ip6t_mutex); | ||
1551 | } | ||
1552 | |||
1553 | int ip6t_register_table(struct ip6t_table *table, | ||
1554 | const struct ip6t_replace *repl) | 1268 | const struct ip6t_replace *repl) |
1555 | { | 1269 | { |
1556 | int ret; | 1270 | int ret; |
1557 | struct ip6t_table_info *newinfo; | 1271 | struct xt_table_info *newinfo; |
1558 | static struct ip6t_table_info bootstrap | 1272 | static struct xt_table_info bootstrap |
1559 | = { 0, 0, 0, { 0 }, { 0 }, { } }; | 1273 | = { 0, 0, 0, { 0 }, { 0 }, { } }; |
1560 | void *loc_cpu_entry; | 1274 | void *loc_cpu_entry; |
1561 | 1275 | ||
1562 | newinfo = alloc_table_info(repl->size); | 1276 | newinfo = xt_alloc_table_info(repl->size); |
1563 | if (!newinfo) | 1277 | if (!newinfo) |
1564 | return -ENOMEM; | 1278 | return -ENOMEM; |
1565 | 1279 | ||
@@ -1573,244 +1287,29 @@ int ip6t_register_table(struct ip6t_table *table, | |||
1573 | repl->hook_entry, | 1287 | repl->hook_entry, |
1574 | repl->underflow); | 1288 | repl->underflow); |
1575 | if (ret != 0) { | 1289 | if (ret != 0) { |
1576 | free_table_info(newinfo); | 1290 | xt_free_table_info(newinfo); |
1577 | return ret; | 1291 | return ret; |
1578 | } | 1292 | } |
1579 | 1293 | ||
1580 | ret = down_interruptible(&ip6t_mutex); | 1294 | if (xt_register_table(table, &bootstrap, newinfo) != 0) { |
1581 | if (ret != 0) { | 1295 | xt_free_table_info(newinfo); |
1582 | free_table_info(newinfo); | ||
1583 | return ret; | 1296 | return ret; |
1584 | } | 1297 | } |
1585 | 1298 | ||
1586 | /* Don't autoload: we'd eat our tail... */ | 1299 | return 0; |
1587 | if (list_named_find(&ip6t_tables, table->name)) { | ||
1588 | ret = -EEXIST; | ||
1589 | goto free_unlock; | ||
1590 | } | ||
1591 | |||
1592 | /* Simplifies replace_table code. */ | ||
1593 | table->private = &bootstrap; | ||
1594 | if (!replace_table(table, 0, newinfo, &ret)) | ||
1595 | goto free_unlock; | ||
1596 | |||
1597 | duprintf("table->private->number = %u\n", | ||
1598 | table->private->number); | ||
1599 | |||
1600 | /* save number of initial entries */ | ||
1601 | table->private->initial_entries = table->private->number; | ||
1602 | |||
1603 | rwlock_init(&table->lock); | ||
1604 | list_prepend(&ip6t_tables, table); | ||
1605 | |||
1606 | unlock: | ||
1607 | up(&ip6t_mutex); | ||
1608 | return ret; | ||
1609 | |||
1610 | free_unlock: | ||
1611 | free_table_info(newinfo); | ||
1612 | goto unlock; | ||
1613 | } | 1300 | } |
1614 | 1301 | ||
1615 | void ip6t_unregister_table(struct ip6t_table *table) | 1302 | void ip6t_unregister_table(struct xt_table *table) |
1616 | { | 1303 | { |
1304 | struct xt_table_info *private; | ||
1617 | void *loc_cpu_entry; | 1305 | void *loc_cpu_entry; |
1618 | 1306 | ||
1619 | down(&ip6t_mutex); | 1307 | private = xt_unregister_table(table); |
1620 | LIST_DELETE(&ip6t_tables, table); | ||
1621 | up(&ip6t_mutex); | ||
1622 | 1308 | ||
1623 | /* Decrease module usage counts and free resources */ | 1309 | /* Decrease module usage counts and free resources */ |
1624 | loc_cpu_entry = table->private->entries[raw_smp_processor_id()]; | 1310 | loc_cpu_entry = private->entries[raw_smp_processor_id()]; |
1625 | IP6T_ENTRY_ITERATE(loc_cpu_entry, table->private->size, | 1311 | IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); |
1626 | cleanup_entry, NULL); | 1312 | xt_free_table_info(private); |
1627 | free_table_info(table->private); | ||
1628 | } | ||
1629 | |||
1630 | /* Returns 1 if the port is matched by the range, 0 otherwise */ | ||
1631 | static inline int | ||
1632 | port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) | ||
1633 | { | ||
1634 | int ret; | ||
1635 | |||
1636 | ret = (port >= min && port <= max) ^ invert; | ||
1637 | return ret; | ||
1638 | } | ||
1639 | |||
1640 | static int | ||
1641 | tcp_find_option(u_int8_t option, | ||
1642 | const struct sk_buff *skb, | ||
1643 | unsigned int tcpoff, | ||
1644 | unsigned int optlen, | ||
1645 | int invert, | ||
1646 | int *hotdrop) | ||
1647 | { | ||
1648 | /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ | ||
1649 | u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; | ||
1650 | unsigned int i; | ||
1651 | |||
1652 | duprintf("tcp_match: finding option\n"); | ||
1653 | if (!optlen) | ||
1654 | return invert; | ||
1655 | /* If we don't have the whole header, drop packet. */ | ||
1656 | op = skb_header_pointer(skb, tcpoff + sizeof(struct tcphdr), optlen, | ||
1657 | _opt); | ||
1658 | if (op == NULL) { | ||
1659 | *hotdrop = 1; | ||
1660 | return 0; | ||
1661 | } | ||
1662 | |||
1663 | for (i = 0; i < optlen; ) { | ||
1664 | if (op[i] == option) return !invert; | ||
1665 | if (op[i] < 2) i++; | ||
1666 | else i += op[i+1]?:1; | ||
1667 | } | ||
1668 | |||
1669 | return invert; | ||
1670 | } | ||
1671 | |||
1672 | static int | ||
1673 | tcp_match(const struct sk_buff *skb, | ||
1674 | const struct net_device *in, | ||
1675 | const struct net_device *out, | ||
1676 | const void *matchinfo, | ||
1677 | int offset, | ||
1678 | unsigned int protoff, | ||
1679 | int *hotdrop) | ||
1680 | { | ||
1681 | struct tcphdr _tcph, *th; | ||
1682 | const struct ip6t_tcp *tcpinfo = matchinfo; | ||
1683 | |||
1684 | if (offset) { | ||
1685 | /* To quote Alan: | ||
1686 | |||
1687 | Don't allow a fragment of TCP 8 bytes in. Nobody normal | ||
1688 | causes this. Its a cracker trying to break in by doing a | ||
1689 | flag overwrite to pass the direction checks. | ||
1690 | */ | ||
1691 | if (offset == 1) { | ||
1692 | duprintf("Dropping evil TCP offset=1 frag.\n"); | ||
1693 | *hotdrop = 1; | ||
1694 | } | ||
1695 | /* Must not be a fragment. */ | ||
1696 | return 0; | ||
1697 | } | ||
1698 | |||
1699 | #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) | ||
1700 | |||
1701 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); | ||
1702 | if (th == NULL) { | ||
1703 | /* We've been asked to examine this packet, and we | ||
1704 | can't. Hence, no choice but to drop. */ | ||
1705 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); | ||
1706 | *hotdrop = 1; | ||
1707 | return 0; | ||
1708 | } | ||
1709 | |||
1710 | if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], | ||
1711 | ntohs(th->source), | ||
1712 | !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT))) | ||
1713 | return 0; | ||
1714 | if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], | ||
1715 | ntohs(th->dest), | ||
1716 | !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT))) | ||
1717 | return 0; | ||
1718 | if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) | ||
1719 | == tcpinfo->flg_cmp, | ||
1720 | IP6T_TCP_INV_FLAGS)) | ||
1721 | return 0; | ||
1722 | if (tcpinfo->option) { | ||
1723 | if (th->doff * 4 < sizeof(_tcph)) { | ||
1724 | *hotdrop = 1; | ||
1725 | return 0; | ||
1726 | } | ||
1727 | if (!tcp_find_option(tcpinfo->option, skb, protoff, | ||
1728 | th->doff*4 - sizeof(*th), | ||
1729 | tcpinfo->invflags & IP6T_TCP_INV_OPTION, | ||
1730 | hotdrop)) | ||
1731 | return 0; | ||
1732 | } | ||
1733 | return 1; | ||
1734 | } | ||
1735 | |||
1736 | /* Called when user tries to insert an entry of this type. */ | ||
1737 | static int | ||
1738 | tcp_checkentry(const char *tablename, | ||
1739 | const struct ip6t_ip6 *ipv6, | ||
1740 | void *matchinfo, | ||
1741 | unsigned int matchsize, | ||
1742 | unsigned int hook_mask) | ||
1743 | { | ||
1744 | const struct ip6t_tcp *tcpinfo = matchinfo; | ||
1745 | |||
1746 | /* Must specify proto == TCP, and no unknown invflags */ | ||
1747 | return ipv6->proto == IPPROTO_TCP | ||
1748 | && !(ipv6->invflags & IP6T_INV_PROTO) | ||
1749 | && matchsize == IP6T_ALIGN(sizeof(struct ip6t_tcp)) | ||
1750 | && !(tcpinfo->invflags & ~IP6T_TCP_INV_MASK); | ||
1751 | } | ||
1752 | |||
1753 | static int | ||
1754 | udp_match(const struct sk_buff *skb, | ||
1755 | const struct net_device *in, | ||
1756 | const struct net_device *out, | ||
1757 | const void *matchinfo, | ||
1758 | int offset, | ||
1759 | unsigned int protoff, | ||
1760 | int *hotdrop) | ||
1761 | { | ||
1762 | struct udphdr _udph, *uh; | ||
1763 | const struct ip6t_udp *udpinfo = matchinfo; | ||
1764 | |||
1765 | /* Must not be a fragment. */ | ||
1766 | if (offset) | ||
1767 | return 0; | ||
1768 | |||
1769 | uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph); | ||
1770 | if (uh == NULL) { | ||
1771 | /* We've been asked to examine this packet, and we | ||
1772 | can't. Hence, no choice but to drop. */ | ||
1773 | duprintf("Dropping evil UDP tinygram.\n"); | ||
1774 | *hotdrop = 1; | ||
1775 | return 0; | ||
1776 | } | ||
1777 | |||
1778 | return port_match(udpinfo->spts[0], udpinfo->spts[1], | ||
1779 | ntohs(uh->source), | ||
1780 | !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT)) | ||
1781 | && port_match(udpinfo->dpts[0], udpinfo->dpts[1], | ||
1782 | ntohs(uh->dest), | ||
1783 | !!(udpinfo->invflags & IP6T_UDP_INV_DSTPT)); | ||
1784 | } | ||
1785 | |||
1786 | /* Called when user tries to insert an entry of this type. */ | ||
1787 | static int | ||
1788 | udp_checkentry(const char *tablename, | ||
1789 | const struct ip6t_ip6 *ipv6, | ||
1790 | void *matchinfo, | ||
1791 | unsigned int matchinfosize, | ||
1792 | unsigned int hook_mask) | ||
1793 | { | ||
1794 | const struct ip6t_udp *udpinfo = matchinfo; | ||
1795 | |||
1796 | /* Must specify proto == UDP, and no unknown invflags */ | ||
1797 | if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & IP6T_INV_PROTO)) { | ||
1798 | duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto, | ||
1799 | IPPROTO_UDP); | ||
1800 | return 0; | ||
1801 | } | ||
1802 | if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_udp))) { | ||
1803 | duprintf("ip6t_udp: matchsize %u != %u\n", | ||
1804 | matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_udp))); | ||
1805 | return 0; | ||
1806 | } | ||
1807 | if (udpinfo->invflags & ~IP6T_UDP_INV_MASK) { | ||
1808 | duprintf("ip6t_udp: unknown flags %X\n", | ||
1809 | udpinfo->invflags); | ||
1810 | return 0; | ||
1811 | } | ||
1812 | |||
1813 | return 1; | ||
1814 | } | 1313 | } |
1815 | 1314 | ||
1816 | /* Returns 1 if the type and code is matched by the range, 0 otherwise */ | 1315 | /* Returns 1 if the type and code is matched by the range, 0 otherwise */ |
@@ -1858,11 +1357,12 @@ icmp6_match(const struct sk_buff *skb, | |||
1858 | /* Called when user tries to insert an entry of this type. */ | 1357 | /* Called when user tries to insert an entry of this type. */ |
1859 | static int | 1358 | static int |
1860 | icmp6_checkentry(const char *tablename, | 1359 | icmp6_checkentry(const char *tablename, |
1861 | const struct ip6t_ip6 *ipv6, | 1360 | const void *entry, |
1862 | void *matchinfo, | 1361 | void *matchinfo, |
1863 | unsigned int matchsize, | 1362 | unsigned int matchsize, |
1864 | unsigned int hook_mask) | 1363 | unsigned int hook_mask) |
1865 | { | 1364 | { |
1365 | const struct ip6t_ip6 *ipv6 = entry; | ||
1866 | const struct ip6t_icmp *icmpinfo = matchinfo; | 1366 | const struct ip6t_icmp *icmpinfo = matchinfo; |
1867 | 1367 | ||
1868 | /* Must specify proto == ICMP, and no unknown invflags */ | 1368 | /* Must specify proto == ICMP, and no unknown invflags */ |
@@ -1892,164 +1392,42 @@ static struct nf_sockopt_ops ip6t_sockopts = { | |||
1892 | .get = do_ip6t_get_ctl, | 1392 | .get = do_ip6t_get_ctl, |
1893 | }; | 1393 | }; |
1894 | 1394 | ||
1895 | static struct ip6t_match tcp_matchstruct = { | ||
1896 | .name = "tcp", | ||
1897 | .match = &tcp_match, | ||
1898 | .checkentry = &tcp_checkentry, | ||
1899 | }; | ||
1900 | |||
1901 | static struct ip6t_match udp_matchstruct = { | ||
1902 | .name = "udp", | ||
1903 | .match = &udp_match, | ||
1904 | .checkentry = &udp_checkentry, | ||
1905 | }; | ||
1906 | |||
1907 | static struct ip6t_match icmp6_matchstruct = { | 1395 | static struct ip6t_match icmp6_matchstruct = { |
1908 | .name = "icmp6", | 1396 | .name = "icmp6", |
1909 | .match = &icmp6_match, | 1397 | .match = &icmp6_match, |
1910 | .checkentry = &icmp6_checkentry, | 1398 | .checkentry = &icmp6_checkentry, |
1911 | }; | 1399 | }; |
1912 | 1400 | ||
1913 | #ifdef CONFIG_PROC_FS | ||
1914 | static inline int print_name(const char *i, | ||
1915 | off_t start_offset, char *buffer, int length, | ||
1916 | off_t *pos, unsigned int *count) | ||
1917 | { | ||
1918 | if ((*count)++ >= start_offset) { | ||
1919 | unsigned int namelen; | ||
1920 | |||
1921 | namelen = sprintf(buffer + *pos, "%s\n", | ||
1922 | i + sizeof(struct list_head)); | ||
1923 | if (*pos + namelen > length) { | ||
1924 | /* Stop iterating */ | ||
1925 | return 1; | ||
1926 | } | ||
1927 | *pos += namelen; | ||
1928 | } | ||
1929 | return 0; | ||
1930 | } | ||
1931 | |||
1932 | static inline int print_target(const struct ip6t_target *t, | ||
1933 | off_t start_offset, char *buffer, int length, | ||
1934 | off_t *pos, unsigned int *count) | ||
1935 | { | ||
1936 | if (t == &ip6t_standard_target || t == &ip6t_error_target) | ||
1937 | return 0; | ||
1938 | return print_name((char *)t, start_offset, buffer, length, pos, count); | ||
1939 | } | ||
1940 | |||
1941 | static int ip6t_get_tables(char *buffer, char **start, off_t offset, int length) | ||
1942 | { | ||
1943 | off_t pos = 0; | ||
1944 | unsigned int count = 0; | ||
1945 | |||
1946 | if (down_interruptible(&ip6t_mutex) != 0) | ||
1947 | return 0; | ||
1948 | |||
1949 | LIST_FIND(&ip6t_tables, print_name, char *, | ||
1950 | offset, buffer, length, &pos, &count); | ||
1951 | |||
1952 | up(&ip6t_mutex); | ||
1953 | |||
1954 | /* `start' hack - see fs/proc/generic.c line ~105 */ | ||
1955 | *start=(char *)((unsigned long)count-offset); | ||
1956 | return pos; | ||
1957 | } | ||
1958 | |||
1959 | static int ip6t_get_targets(char *buffer, char **start, off_t offset, int length) | ||
1960 | { | ||
1961 | off_t pos = 0; | ||
1962 | unsigned int count = 0; | ||
1963 | |||
1964 | if (down_interruptible(&ip6t_mutex) != 0) | ||
1965 | return 0; | ||
1966 | |||
1967 | LIST_FIND(&ip6t_target, print_target, struct ip6t_target *, | ||
1968 | offset, buffer, length, &pos, &count); | ||
1969 | |||
1970 | up(&ip6t_mutex); | ||
1971 | |||
1972 | *start = (char *)((unsigned long)count - offset); | ||
1973 | return pos; | ||
1974 | } | ||
1975 | |||
1976 | static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length) | ||
1977 | { | ||
1978 | off_t pos = 0; | ||
1979 | unsigned int count = 0; | ||
1980 | |||
1981 | if (down_interruptible(&ip6t_mutex) != 0) | ||
1982 | return 0; | ||
1983 | |||
1984 | LIST_FIND(&ip6t_match, print_name, char *, | ||
1985 | offset, buffer, length, &pos, &count); | ||
1986 | |||
1987 | up(&ip6t_mutex); | ||
1988 | |||
1989 | *start = (char *)((unsigned long)count - offset); | ||
1990 | return pos; | ||
1991 | } | ||
1992 | |||
1993 | static const struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] = | ||
1994 | { { "ip6_tables_names", ip6t_get_tables }, | ||
1995 | { "ip6_tables_targets", ip6t_get_targets }, | ||
1996 | { "ip6_tables_matches", ip6t_get_matches }, | ||
1997 | { NULL, NULL} }; | ||
1998 | #endif /*CONFIG_PROC_FS*/ | ||
1999 | |||
2000 | static int __init init(void) | 1401 | static int __init init(void) |
2001 | { | 1402 | { |
2002 | int ret; | 1403 | int ret; |
2003 | 1404 | ||
1405 | xt_proto_init(AF_INET6); | ||
1406 | |||
2004 | /* Noone else will be downing sem now, so we won't sleep */ | 1407 | /* Noone else will be downing sem now, so we won't sleep */ |
2005 | down(&ip6t_mutex); | 1408 | xt_register_target(AF_INET6, &ip6t_standard_target); |
2006 | list_append(&ip6t_target, &ip6t_standard_target); | 1409 | xt_register_target(AF_INET6, &ip6t_error_target); |
2007 | list_append(&ip6t_target, &ip6t_error_target); | 1410 | xt_register_match(AF_INET6, &icmp6_matchstruct); |
2008 | list_append(&ip6t_match, &tcp_matchstruct); | ||
2009 | list_append(&ip6t_match, &udp_matchstruct); | ||
2010 | list_append(&ip6t_match, &icmp6_matchstruct); | ||
2011 | up(&ip6t_mutex); | ||
2012 | 1411 | ||
2013 | /* Register setsockopt */ | 1412 | /* Register setsockopt */ |
2014 | ret = nf_register_sockopt(&ip6t_sockopts); | 1413 | ret = nf_register_sockopt(&ip6t_sockopts); |
2015 | if (ret < 0) { | 1414 | if (ret < 0) { |
2016 | duprintf("Unable to register sockopts.\n"); | 1415 | duprintf("Unable to register sockopts.\n"); |
1416 | xt_proto_fini(AF_INET6); | ||
2017 | return ret; | 1417 | return ret; |
2018 | } | 1418 | } |
2019 | 1419 | ||
2020 | #ifdef CONFIG_PROC_FS | 1420 | printk("ip6_tables: (C) 2000-2006 Netfilter Core Team\n"); |
2021 | { | ||
2022 | struct proc_dir_entry *proc; | ||
2023 | int i; | ||
2024 | |||
2025 | for (i = 0; ip6t_proc_entry[i].name; i++) { | ||
2026 | proc = proc_net_create(ip6t_proc_entry[i].name, 0, | ||
2027 | ip6t_proc_entry[i].get_info); | ||
2028 | if (!proc) { | ||
2029 | while (--i >= 0) | ||
2030 | proc_net_remove(ip6t_proc_entry[i].name); | ||
2031 | nf_unregister_sockopt(&ip6t_sockopts); | ||
2032 | return -ENOMEM; | ||
2033 | } | ||
2034 | proc->owner = THIS_MODULE; | ||
2035 | } | ||
2036 | } | ||
2037 | #endif | ||
2038 | |||
2039 | printk("ip6_tables: (C) 2000-2002 Netfilter core team\n"); | ||
2040 | return 0; | 1421 | return 0; |
2041 | } | 1422 | } |
2042 | 1423 | ||
2043 | static void __exit fini(void) | 1424 | static void __exit fini(void) |
2044 | { | 1425 | { |
2045 | nf_unregister_sockopt(&ip6t_sockopts); | 1426 | nf_unregister_sockopt(&ip6t_sockopts); |
2046 | #ifdef CONFIG_PROC_FS | 1427 | xt_unregister_match(AF_INET6, &icmp6_matchstruct); |
2047 | { | 1428 | xt_unregister_target(AF_INET6, &ip6t_error_target); |
2048 | int i; | 1429 | xt_unregister_target(AF_INET6, &ip6t_standard_target); |
2049 | for (i = 0; ip6t_proc_entry[i].name; i++) | 1430 | xt_proto_fini(AF_INET6); |
2050 | proc_net_remove(ip6t_proc_entry[i].name); | ||
2051 | } | ||
2052 | #endif | ||
2053 | } | 1431 | } |
2054 | 1432 | ||
2055 | /* | 1433 | /* |
@@ -2128,10 +1506,6 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, | |||
2128 | EXPORT_SYMBOL(ip6t_register_table); | 1506 | EXPORT_SYMBOL(ip6t_register_table); |
2129 | EXPORT_SYMBOL(ip6t_unregister_table); | 1507 | EXPORT_SYMBOL(ip6t_unregister_table); |
2130 | EXPORT_SYMBOL(ip6t_do_table); | 1508 | EXPORT_SYMBOL(ip6t_do_table); |
2131 | EXPORT_SYMBOL(ip6t_register_match); | ||
2132 | EXPORT_SYMBOL(ip6t_unregister_match); | ||
2133 | EXPORT_SYMBOL(ip6t_register_target); | ||
2134 | EXPORT_SYMBOL(ip6t_unregister_target); | ||
2135 | EXPORT_SYMBOL(ip6t_ext_hdr); | 1509 | EXPORT_SYMBOL(ip6t_ext_hdr); |
2136 | EXPORT_SYMBOL(ipv6_find_hdr); | 1510 | EXPORT_SYMBOL(ipv6_find_hdr); |
2137 | EXPORT_SYMBOL(ip6_masked_addrcmp); | 1511 | EXPORT_SYMBOL(ip6_masked_addrcmp); |
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c index 8f5549b72720..306200c35057 100644 --- a/net/ipv6/netfilter/ip6t_HL.c +++ b/net/ipv6/netfilter/ip6t_HL.c | |||
@@ -62,7 +62,7 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb, | |||
62 | } | 62 | } |
63 | 63 | ||
64 | static int ip6t_hl_checkentry(const char *tablename, | 64 | static int ip6t_hl_checkentry(const char *tablename, |
65 | const struct ip6t_entry *e, | 65 | const void *entry, |
66 | void *targinfo, | 66 | void *targinfo, |
67 | unsigned int targinfosize, | 67 | unsigned int targinfosize, |
68 | unsigned int hook_mask) | 68 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c index ae4653bfd654..77c725832dec 100644 --- a/net/ipv6/netfilter/ip6t_LOG.c +++ b/net/ipv6/netfilter/ip6t_LOG.c | |||
@@ -63,9 +63,8 @@ static void dump_packet(const struct nf_loginfo *info, | |||
63 | return; | 63 | return; |
64 | } | 64 | } |
65 | 65 | ||
66 | /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000" */ | 66 | /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ |
67 | printk("SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->saddr)); | 67 | printk("SRC=" NIP6_FMT " DST=" NIP6_FMT " ", NIP6(ih->saddr), NIP6(ih->daddr)); |
68 | printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->daddr)); | ||
69 | 68 | ||
70 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ | 69 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ |
71 | printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", | 70 | printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", |
@@ -444,7 +443,7 @@ ip6t_log_target(struct sk_buff **pskb, | |||
444 | 443 | ||
445 | 444 | ||
446 | static int ip6t_log_checkentry(const char *tablename, | 445 | static int ip6t_log_checkentry(const char *tablename, |
447 | const struct ip6t_entry *e, | 446 | const void *entry, |
448 | void *targinfo, | 447 | void *targinfo, |
449 | unsigned int targinfosize, | 448 | unsigned int targinfosize, |
450 | unsigned int hook_mask) | 449 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c deleted file mode 100644 index eab8fb864ee0..000000000000 --- a/net/ipv6/netfilter/ip6t_MARK.c +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /* This is a module which is used for setting the NFMARK field of an skb. */ | ||
2 | |||
3 | /* (C) 1999-2001 Marc Boucher <marc@mbsi.ca> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/skbuff.h> | ||
12 | #include <linux/ip.h> | ||
13 | #include <net/checksum.h> | ||
14 | |||
15 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
16 | #include <linux/netfilter_ipv6/ip6t_MARK.h> | ||
17 | |||
18 | MODULE_LICENSE("GPL"); | ||
19 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | ||
20 | |||
21 | static unsigned int | ||
22 | target(struct sk_buff **pskb, | ||
23 | const struct net_device *in, | ||
24 | const struct net_device *out, | ||
25 | unsigned int hooknum, | ||
26 | const void *targinfo, | ||
27 | void *userinfo) | ||
28 | { | ||
29 | const struct ip6t_mark_target_info *markinfo = targinfo; | ||
30 | |||
31 | if((*pskb)->nfmark != markinfo->mark) | ||
32 | (*pskb)->nfmark = markinfo->mark; | ||
33 | |||
34 | return IP6T_CONTINUE; | ||
35 | } | ||
36 | |||
37 | static int | ||
38 | checkentry(const char *tablename, | ||
39 | const struct ip6t_entry *e, | ||
40 | void *targinfo, | ||
41 | unsigned int targinfosize, | ||
42 | unsigned int hook_mask) | ||
43 | { | ||
44 | if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))) { | ||
45 | printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", | ||
46 | targinfosize, | ||
47 | IP6T_ALIGN(sizeof(struct ip6t_mark_target_info))); | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | if (strcmp(tablename, "mangle") != 0) { | ||
52 | printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename); | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | return 1; | ||
57 | } | ||
58 | |||
59 | static struct ip6t_target ip6t_mark_reg = { | ||
60 | .name = "MARK", | ||
61 | .target = target, | ||
62 | .checkentry = checkentry, | ||
63 | .me = THIS_MODULE | ||
64 | }; | ||
65 | |||
66 | static int __init init(void) | ||
67 | { | ||
68 | printk(KERN_DEBUG "registering ipv6 mark target\n"); | ||
69 | if (ip6t_register_target(&ip6t_mark_reg)) | ||
70 | return -EINVAL; | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static void __exit fini(void) | ||
76 | { | ||
77 | ip6t_unregister_target(&ip6t_mark_reg); | ||
78 | } | ||
79 | |||
80 | module_init(init); | ||
81 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_NFQUEUE.c b/net/ipv6/netfilter/ip6t_NFQUEUE.c deleted file mode 100644 index c6e3730e7409..000000000000 --- a/net/ipv6/netfilter/ip6t_NFQUEUE.c +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | /* ip6tables module for using new netfilter netlink queue | ||
2 | * | ||
3 | * (C) 2005 by Harald Welte <laforge@netfilter.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | |||
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
16 | #include <linux/netfilter_ipv4/ipt_NFQUEUE.h> | ||
17 | |||
18 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
19 | MODULE_DESCRIPTION("ip6tables NFQUEUE target"); | ||
20 | MODULE_LICENSE("GPL"); | ||
21 | |||
22 | static unsigned int | ||
23 | target(struct sk_buff **pskb, | ||
24 | const struct net_device *in, | ||
25 | const struct net_device *out, | ||
26 | unsigned int hooknum, | ||
27 | const void *targinfo, | ||
28 | void *userinfo) | ||
29 | { | ||
30 | const struct ipt_NFQ_info *tinfo = targinfo; | ||
31 | |||
32 | return NF_QUEUE_NR(tinfo->queuenum); | ||
33 | } | ||
34 | |||
35 | static int | ||
36 | checkentry(const char *tablename, | ||
37 | const struct ip6t_entry *e, | ||
38 | void *targinfo, | ||
39 | unsigned int targinfosize, | ||
40 | unsigned int hook_mask) | ||
41 | { | ||
42 | if (targinfosize != IP6T_ALIGN(sizeof(struct ipt_NFQ_info))) { | ||
43 | printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n", | ||
44 | targinfosize, | ||
45 | IP6T_ALIGN(sizeof(struct ipt_NFQ_info))); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | return 1; | ||
50 | } | ||
51 | |||
52 | static struct ip6t_target ipt_NFQ_reg = { | ||
53 | .name = "NFQUEUE", | ||
54 | .target = target, | ||
55 | .checkentry = checkentry, | ||
56 | .me = THIS_MODULE, | ||
57 | }; | ||
58 | |||
59 | static int __init init(void) | ||
60 | { | ||
61 | return ip6t_register_target(&ipt_NFQ_reg); | ||
62 | } | ||
63 | |||
64 | static void __exit fini(void) | ||
65 | { | ||
66 | ip6t_unregister_target(&ipt_NFQ_reg); | ||
67 | } | ||
68 | |||
69 | module_init(init); | ||
70 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index b03e87adca93..c745717b4ce2 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -218,12 +218,13 @@ static unsigned int reject6_target(struct sk_buff **pskb, | |||
218 | } | 218 | } |
219 | 219 | ||
220 | static int check(const char *tablename, | 220 | static int check(const char *tablename, |
221 | const struct ip6t_entry *e, | 221 | const void *entry, |
222 | void *targinfo, | 222 | void *targinfo, |
223 | unsigned int targinfosize, | 223 | unsigned int targinfosize, |
224 | unsigned int hook_mask) | 224 | unsigned int hook_mask) |
225 | { | 225 | { |
226 | const struct ip6t_reject_info *rejinfo = targinfo; | 226 | const struct ip6t_reject_info *rejinfo = targinfo; |
227 | const struct ip6t_entry *e = entry; | ||
227 | 228 | ||
228 | if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) { | 229 | if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) { |
229 | DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize); | 230 | DEBUGP("ip6t_REJECT: targinfosize %u != 0\n", targinfosize); |
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c index f5c1a7ff4a1f..219a30365dff 100644 --- a/net/ipv6/netfilter/ip6t_ah.c +++ b/net/ipv6/netfilter/ip6t_ah.c | |||
@@ -98,7 +98,7 @@ match(const struct sk_buff *skb, | |||
98 | /* Called when user tries to insert an entry of this type. */ | 98 | /* Called when user tries to insert an entry of this type. */ |
99 | static int | 99 | static int |
100 | checkentry(const char *tablename, | 100 | checkentry(const char *tablename, |
101 | const struct ip6t_ip6 *ip, | 101 | const void *entry, |
102 | void *matchinfo, | 102 | void *matchinfo, |
103 | unsigned int matchinfosize, | 103 | unsigned int matchinfosize, |
104 | unsigned int hook_mask) | 104 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c index 48cf5f9efc95..80fe82669ce2 100644 --- a/net/ipv6/netfilter/ip6t_dst.c +++ b/net/ipv6/netfilter/ip6t_dst.c | |||
@@ -178,7 +178,7 @@ match(const struct sk_buff *skb, | |||
178 | /* Called when user tries to insert an entry of this type. */ | 178 | /* Called when user tries to insert an entry of this type. */ |
179 | static int | 179 | static int |
180 | checkentry(const char *tablename, | 180 | checkentry(const char *tablename, |
181 | const struct ip6t_ip6 *ip, | 181 | const void *info, |
182 | void *matchinfo, | 182 | void *matchinfo, |
183 | unsigned int matchinfosize, | 183 | unsigned int matchinfosize, |
184 | unsigned int hook_mask) | 184 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c index e1828f6d0a40..724285df8711 100644 --- a/net/ipv6/netfilter/ip6t_esp.c +++ b/net/ipv6/netfilter/ip6t_esp.c | |||
@@ -76,7 +76,7 @@ match(const struct sk_buff *skb, | |||
76 | /* Called when user tries to insert an entry of this type. */ | 76 | /* Called when user tries to insert an entry of this type. */ |
77 | static int | 77 | static int |
78 | checkentry(const char *tablename, | 78 | checkentry(const char *tablename, |
79 | const struct ip6t_ip6 *ip, | 79 | const void *ip, |
80 | void *matchinfo, | 80 | void *matchinfo, |
81 | unsigned int matchinfosize, | 81 | unsigned int matchinfosize, |
82 | unsigned int hook_mask) | 82 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c index 616c2cbcd54d..ddf5f571909c 100644 --- a/net/ipv6/netfilter/ip6t_eui64.c +++ b/net/ipv6/netfilter/ip6t_eui64.c | |||
@@ -62,7 +62,7 @@ match(const struct sk_buff *skb, | |||
62 | 62 | ||
63 | static int | 63 | static int |
64 | ip6t_eui64_checkentry(const char *tablename, | 64 | ip6t_eui64_checkentry(const char *tablename, |
65 | const struct ip6t_ip6 *ip, | 65 | const void *ip, |
66 | void *matchinfo, | 66 | void *matchinfo, |
67 | unsigned int matchsize, | 67 | unsigned int matchsize, |
68 | unsigned int hook_mask) | 68 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c index d1549b268669..a9964b946ed5 100644 --- a/net/ipv6/netfilter/ip6t_frag.c +++ b/net/ipv6/netfilter/ip6t_frag.c | |||
@@ -115,7 +115,7 @@ match(const struct sk_buff *skb, | |||
115 | /* Called when user tries to insert an entry of this type. */ | 115 | /* Called when user tries to insert an entry of this type. */ |
116 | static int | 116 | static int |
117 | checkentry(const char *tablename, | 117 | checkentry(const char *tablename, |
118 | const struct ip6t_ip6 *ip, | 118 | const void *ip, |
119 | void *matchinfo, | 119 | void *matchinfo, |
120 | unsigned int matchinfosize, | 120 | unsigned int matchinfosize, |
121 | unsigned int hook_mask) | 121 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c index e3bc8e2700e7..ed8ded18bbd4 100644 --- a/net/ipv6/netfilter/ip6t_hbh.c +++ b/net/ipv6/netfilter/ip6t_hbh.c | |||
@@ -178,7 +178,7 @@ match(const struct sk_buff *skb, | |||
178 | /* Called when user tries to insert an entry of this type. */ | 178 | /* Called when user tries to insert an entry of this type. */ |
179 | static int | 179 | static int |
180 | checkentry(const char *tablename, | 180 | checkentry(const char *tablename, |
181 | const struct ip6t_ip6 *ip, | 181 | const void *entry, |
182 | void *matchinfo, | 182 | void *matchinfo, |
183 | unsigned int matchinfosize, | 183 | unsigned int matchinfosize, |
184 | unsigned int hook_mask) | 184 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c index 0beaff5471dd..c5d9079f2d9d 100644 --- a/net/ipv6/netfilter/ip6t_hl.c +++ b/net/ipv6/netfilter/ip6t_hl.c | |||
@@ -48,7 +48,7 @@ static int match(const struct sk_buff *skb, const struct net_device *in, | |||
48 | return 0; | 48 | return 0; |
49 | } | 49 | } |
50 | 50 | ||
51 | static int checkentry(const char *tablename, const struct ip6t_ip6 *ip, | 51 | static int checkentry(const char *tablename, const void *entry, |
52 | void *matchinfo, unsigned int matchsize, | 52 | void *matchinfo, unsigned int matchsize, |
53 | unsigned int hook_mask) | 53 | unsigned int hook_mask) |
54 | { | 54 | { |
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c index 32e67f05845b..fda1ceaf5a29 100644 --- a/net/ipv6/netfilter/ip6t_ipv6header.c +++ b/net/ipv6/netfilter/ip6t_ipv6header.c | |||
@@ -124,7 +124,7 @@ ipv6header_match(const struct sk_buff *skb, | |||
124 | 124 | ||
125 | static int | 125 | static int |
126 | ipv6header_checkentry(const char *tablename, | 126 | ipv6header_checkentry(const char *tablename, |
127 | const struct ip6t_ip6 *ip, | 127 | const void *ip, |
128 | void *matchinfo, | 128 | void *matchinfo, |
129 | unsigned int matchsize, | 129 | unsigned int matchsize, |
130 | unsigned int hook_mask) | 130 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_length.c b/net/ipv6/netfilter/ip6t_length.c deleted file mode 100644 index e0537d3811d5..000000000000 --- a/net/ipv6/netfilter/ip6t_length.c +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | /* Length Match - IPv6 Port */ | ||
2 | |||
3 | /* (C) 1999-2001 James Morris <jmorros@intercode.com.au> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | #include <linux/netfilter_ipv6/ip6t_length.h> | ||
14 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
15 | |||
16 | MODULE_LICENSE("GPL"); | ||
17 | MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); | ||
18 | MODULE_DESCRIPTION("IPv6 packet length match"); | ||
19 | |||
20 | static int | ||
21 | match(const struct sk_buff *skb, | ||
22 | const struct net_device *in, | ||
23 | const struct net_device *out, | ||
24 | const void *matchinfo, | ||
25 | int offset, | ||
26 | unsigned int protoff, | ||
27 | int *hotdrop) | ||
28 | { | ||
29 | const struct ip6t_length_info *info = matchinfo; | ||
30 | u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr); | ||
31 | |||
32 | return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; | ||
33 | } | ||
34 | |||
35 | static int | ||
36 | checkentry(const char *tablename, | ||
37 | const struct ip6t_ip6 *ip, | ||
38 | void *matchinfo, | ||
39 | unsigned int matchsize, | ||
40 | unsigned int hook_mask) | ||
41 | { | ||
42 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_length_info))) | ||
43 | return 0; | ||
44 | |||
45 | return 1; | ||
46 | } | ||
47 | |||
48 | static struct ip6t_match length_match = { | ||
49 | .name = "length", | ||
50 | .match = &match, | ||
51 | .checkentry = &checkentry, | ||
52 | .me = THIS_MODULE, | ||
53 | }; | ||
54 | |||
55 | static int __init init(void) | ||
56 | { | ||
57 | return ip6t_register_match(&length_match); | ||
58 | } | ||
59 | |||
60 | static void __exit fini(void) | ||
61 | { | ||
62 | ip6t_unregister_match(&length_match); | ||
63 | } | ||
64 | |||
65 | module_init(init); | ||
66 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_limit.c b/net/ipv6/netfilter/ip6t_limit.c deleted file mode 100644 index fb782f610be2..000000000000 --- a/net/ipv6/netfilter/ip6t_limit.c +++ /dev/null | |||
@@ -1,147 +0,0 @@ | |||
1 | /* Kernel module to control the rate | ||
2 | * | ||
3 | * 2 September 1999: Changed from the target RATE to the match | ||
4 | * `limit', removed logging. Did I mention that | ||
5 | * Alexey is a fucking genius? | ||
6 | * Rusty Russell (rusty@rustcorp.com.au). */ | ||
7 | |||
8 | /* (C) 1999 Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr> | ||
9 | * (C) 1999 Hervé Eychenne <eychenne@info.enserb.u-bordeaux.fr> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/skbuff.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | |||
21 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
22 | #include <linux/netfilter_ipv6/ip6t_limit.h> | ||
23 | |||
24 | MODULE_LICENSE("GPL"); | ||
25 | MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>"); | ||
26 | MODULE_DESCRIPTION("rate limiting within ip6tables"); | ||
27 | |||
28 | /* The algorithm used is the Simple Token Bucket Filter (TBF) | ||
29 | * see net/sched/sch_tbf.c in the linux source tree | ||
30 | */ | ||
31 | |||
32 | static DEFINE_SPINLOCK(limit_lock); | ||
33 | |||
34 | /* Rusty: This is my (non-mathematically-inclined) understanding of | ||
35 | this algorithm. The `average rate' in jiffies becomes your initial | ||
36 | amount of credit `credit' and the most credit you can ever have | ||
37 | `credit_cap'. The `peak rate' becomes the cost of passing the | ||
38 | test, `cost'. | ||
39 | |||
40 | `prev' tracks the last packet hit: you gain one credit per jiffy. | ||
41 | If you get credit balance more than this, the extra credit is | ||
42 | discarded. Every time the match passes, you lose `cost' credits; | ||
43 | if you don't have that many, the test fails. | ||
44 | |||
45 | See Alexey's formal explanation in net/sched/sch_tbf.c. | ||
46 | |||
47 | To avoid underflow, we multiply by 128 (ie. you get 128 credits per | ||
48 | jiffy). Hence a cost of 2^32-1, means one pass per 32768 seconds | ||
49 | at 1024HZ (or one every 9 hours). A cost of 1 means 12800 passes | ||
50 | per second at 100HZ. */ | ||
51 | |||
52 | #define CREDITS_PER_JIFFY 128 | ||
53 | |||
54 | static int | ||
55 | ip6t_limit_match(const struct sk_buff *skb, | ||
56 | const struct net_device *in, | ||
57 | const struct net_device *out, | ||
58 | const void *matchinfo, | ||
59 | int offset, | ||
60 | unsigned int protoff, | ||
61 | int *hotdrop) | ||
62 | { | ||
63 | struct ip6t_rateinfo *r = ((struct ip6t_rateinfo *)matchinfo)->master; | ||
64 | unsigned long now = jiffies; | ||
65 | |||
66 | spin_lock_bh(&limit_lock); | ||
67 | r->credit += (now - xchg(&r->prev, now)) * CREDITS_PER_JIFFY; | ||
68 | if (r->credit > r->credit_cap) | ||
69 | r->credit = r->credit_cap; | ||
70 | |||
71 | if (r->credit >= r->cost) { | ||
72 | /* We're not limited. */ | ||
73 | r->credit -= r->cost; | ||
74 | spin_unlock_bh(&limit_lock); | ||
75 | return 1; | ||
76 | } | ||
77 | |||
78 | spin_unlock_bh(&limit_lock); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | /* Precision saver. */ | ||
83 | static u_int32_t | ||
84 | user2credits(u_int32_t user) | ||
85 | { | ||
86 | /* If multiplying would overflow... */ | ||
87 | if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) | ||
88 | /* Divide first. */ | ||
89 | return (user / IP6T_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; | ||
90 | |||
91 | return (user * HZ * CREDITS_PER_JIFFY) / IP6T_LIMIT_SCALE; | ||
92 | } | ||
93 | |||
94 | static int | ||
95 | ip6t_limit_checkentry(const char *tablename, | ||
96 | const struct ip6t_ip6 *ip, | ||
97 | void *matchinfo, | ||
98 | unsigned int matchsize, | ||
99 | unsigned int hook_mask) | ||
100 | { | ||
101 | struct ip6t_rateinfo *r = matchinfo; | ||
102 | |||
103 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rateinfo))) | ||
104 | return 0; | ||
105 | |||
106 | /* Check for overflow. */ | ||
107 | if (r->burst == 0 | ||
108 | || user2credits(r->avg * r->burst) < user2credits(r->avg)) { | ||
109 | printk("Call rusty: overflow in ip6t_limit: %u/%u\n", | ||
110 | r->avg, r->burst); | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | /* User avg in seconds * IP6T_LIMIT_SCALE: convert to jiffies * | ||
115 | 128. */ | ||
116 | r->prev = jiffies; | ||
117 | r->credit = user2credits(r->avg * r->burst); /* Credits full. */ | ||
118 | r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ | ||
119 | r->cost = user2credits(r->avg); | ||
120 | |||
121 | /* For SMP, we only want to use one set of counters. */ | ||
122 | r->master = r; | ||
123 | |||
124 | return 1; | ||
125 | } | ||
126 | |||
127 | static struct ip6t_match ip6t_limit_reg = { | ||
128 | .name = "limit", | ||
129 | .match = ip6t_limit_match, | ||
130 | .checkentry = ip6t_limit_checkentry, | ||
131 | .me = THIS_MODULE, | ||
132 | }; | ||
133 | |||
134 | static int __init init(void) | ||
135 | { | ||
136 | if (ip6t_register_match(&ip6t_limit_reg)) | ||
137 | return -EINVAL; | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static void __exit fini(void) | ||
142 | { | ||
143 | ip6t_unregister_match(&ip6t_limit_reg); | ||
144 | } | ||
145 | |||
146 | module_init(init); | ||
147 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c deleted file mode 100644 index c848152315bc..000000000000 --- a/net/ipv6/netfilter/ip6t_mac.c +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /* Kernel module to match MAC address parameters. */ | ||
2 | |||
3 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
4 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | #include <linux/if_ether.h> | ||
14 | #include <linux/etherdevice.h> | ||
15 | |||
16 | #include <linux/netfilter_ipv6/ip6t_mac.h> | ||
17 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
18 | |||
19 | MODULE_LICENSE("GPL"); | ||
20 | MODULE_DESCRIPTION("MAC address matching module for IPv6"); | ||
21 | MODULE_AUTHOR("Netfilter Core Teaam <coreteam@netfilter.org>"); | ||
22 | |||
23 | static int | ||
24 | match(const struct sk_buff *skb, | ||
25 | const struct net_device *in, | ||
26 | const struct net_device *out, | ||
27 | const void *matchinfo, | ||
28 | int offset, | ||
29 | unsigned int protoff, | ||
30 | int *hotdrop) | ||
31 | { | ||
32 | const struct ip6t_mac_info *info = matchinfo; | ||
33 | |||
34 | /* Is mac pointer valid? */ | ||
35 | return (skb->mac.raw >= skb->head | ||
36 | && (skb->mac.raw + ETH_HLEN) <= skb->data | ||
37 | /* If so, compare... */ | ||
38 | && ((!compare_ether_addr(eth_hdr(skb)->h_source, info->srcaddr)) | ||
39 | ^ info->invert)); | ||
40 | } | ||
41 | |||
42 | static int | ||
43 | ip6t_mac_checkentry(const char *tablename, | ||
44 | const struct ip6t_ip6 *ip, | ||
45 | void *matchinfo, | ||
46 | unsigned int matchsize, | ||
47 | unsigned int hook_mask) | ||
48 | { | ||
49 | if (hook_mask | ||
50 | & ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) | ||
51 | | (1 << NF_IP6_FORWARD))) { | ||
52 | printk("ip6t_mac: only valid for PRE_ROUTING, LOCAL_IN or" | ||
53 | " FORWARD\n"); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mac_info))) | ||
58 | return 0; | ||
59 | |||
60 | return 1; | ||
61 | } | ||
62 | |||
63 | static struct ip6t_match mac_match = { | ||
64 | .name = "mac", | ||
65 | .match = &match, | ||
66 | .checkentry = &ip6t_mac_checkentry, | ||
67 | .me = THIS_MODULE, | ||
68 | }; | ||
69 | |||
70 | static int __init init(void) | ||
71 | { | ||
72 | return ip6t_register_match(&mac_match); | ||
73 | } | ||
74 | |||
75 | static void __exit fini(void) | ||
76 | { | ||
77 | ip6t_unregister_match(&mac_match); | ||
78 | } | ||
79 | |||
80 | module_init(init); | ||
81 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_mark.c b/net/ipv6/netfilter/ip6t_mark.c deleted file mode 100644 index affc3de364fc..000000000000 --- a/net/ipv6/netfilter/ip6t_mark.c +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | /* Kernel module to match NFMARK values. */ | ||
2 | |||
3 | /* (C) 1999-2001 Marc Boucher <marc@mbsi.ca> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | |||
14 | #include <linux/netfilter_ipv6/ip6t_mark.h> | ||
15 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
16 | |||
17 | MODULE_LICENSE("GPL"); | ||
18 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | ||
19 | MODULE_DESCRIPTION("ip6tables mark match"); | ||
20 | |||
21 | static int | ||
22 | match(const struct sk_buff *skb, | ||
23 | const struct net_device *in, | ||
24 | const struct net_device *out, | ||
25 | const void *matchinfo, | ||
26 | int offset, | ||
27 | unsigned int protoff, | ||
28 | int *hotdrop) | ||
29 | { | ||
30 | const struct ip6t_mark_info *info = matchinfo; | ||
31 | |||
32 | return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; | ||
33 | } | ||
34 | |||
35 | static int | ||
36 | checkentry(const char *tablename, | ||
37 | const struct ip6t_ip6 *ip, | ||
38 | void *matchinfo, | ||
39 | unsigned int matchsize, | ||
40 | unsigned int hook_mask) | ||
41 | { | ||
42 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_mark_info))) | ||
43 | return 0; | ||
44 | |||
45 | return 1; | ||
46 | } | ||
47 | |||
48 | static struct ip6t_match mark_match = { | ||
49 | .name = "mark", | ||
50 | .match = &match, | ||
51 | .checkentry = &checkentry, | ||
52 | .me = THIS_MODULE, | ||
53 | }; | ||
54 | |||
55 | static int __init init(void) | ||
56 | { | ||
57 | return ip6t_register_match(&mark_match); | ||
58 | } | ||
59 | |||
60 | static void __exit fini(void) | ||
61 | { | ||
62 | ip6t_unregister_match(&mark_match); | ||
63 | } | ||
64 | |||
65 | module_init(init); | ||
66 | module_exit(fini); | ||
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c index 6e3246153fa3..49f7829dfbc2 100644 --- a/net/ipv6/netfilter/ip6t_multiport.c +++ b/net/ipv6/netfilter/ip6t_multiport.c | |||
@@ -84,11 +84,12 @@ match(const struct sk_buff *skb, | |||
84 | /* Called when user tries to insert an entry of this type. */ | 84 | /* Called when user tries to insert an entry of this type. */ |
85 | static int | 85 | static int |
86 | checkentry(const char *tablename, | 86 | checkentry(const char *tablename, |
87 | const struct ip6t_ip6 *ip, | 87 | const void *info, |
88 | void *matchinfo, | 88 | void *matchinfo, |
89 | unsigned int matchsize, | 89 | unsigned int matchsize, |
90 | unsigned int hook_mask) | 90 | unsigned int hook_mask) |
91 | { | 91 | { |
92 | const struct ip6t_ip6 *ip = info; | ||
92 | const struct ip6t_multiport *multiinfo = matchinfo; | 93 | const struct ip6t_multiport *multiinfo = matchinfo; |
93 | 94 | ||
94 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport))) | 95 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport))) |
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c index 4de4cdad4b7d..5409b375b512 100644 --- a/net/ipv6/netfilter/ip6t_owner.c +++ b/net/ipv6/netfilter/ip6t_owner.c | |||
@@ -53,7 +53,7 @@ match(const struct sk_buff *skb, | |||
53 | 53 | ||
54 | static int | 54 | static int |
55 | checkentry(const char *tablename, | 55 | checkentry(const char *tablename, |
56 | const struct ip6t_ip6 *ip, | 56 | const void *ip, |
57 | void *matchinfo, | 57 | void *matchinfo, |
58 | unsigned int matchsize, | 58 | unsigned int matchsize, |
59 | unsigned int hook_mask) | 59 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index c1e770e45543..8465b4375855 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c | |||
@@ -183,7 +183,7 @@ match(const struct sk_buff *skb, | |||
183 | /* Called when user tries to insert an entry of this type. */ | 183 | /* Called when user tries to insert an entry of this type. */ |
184 | static int | 184 | static int |
185 | checkentry(const char *tablename, | 185 | checkentry(const char *tablename, |
186 | const struct ip6t_ip6 *ip, | 186 | const void *entry, |
187 | void *matchinfo, | 187 | void *matchinfo, |
188 | unsigned int matchinfosize, | 188 | unsigned int matchinfosize, |
189 | unsigned int hook_mask) | 189 | unsigned int hook_mask) |
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 4c0028671c20..ce4a968e1f70 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -97,6 +97,7 @@ static struct ip6t_table packet_filter = { | |||
97 | .valid_hooks = FILTER_VALID_HOOKS, | 97 | .valid_hooks = FILTER_VALID_HOOKS, |
98 | .lock = RW_LOCK_UNLOCKED, | 98 | .lock = RW_LOCK_UNLOCKED, |
99 | .me = THIS_MODULE, | 99 | .me = THIS_MODULE, |
100 | .af = AF_INET6, | ||
100 | }; | 101 | }; |
101 | 102 | ||
102 | /* The work comes in here from netfilter.c. */ | 103 | /* The work comes in here from netfilter.c. */ |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 85c1e6eada19..30a4627e000d 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -127,6 +127,7 @@ static struct ip6t_table packet_mangler = { | |||
127 | .valid_hooks = MANGLE_VALID_HOOKS, | 127 | .valid_hooks = MANGLE_VALID_HOOKS, |
128 | .lock = RW_LOCK_UNLOCKED, | 128 | .lock = RW_LOCK_UNLOCKED, |
129 | .me = THIS_MODULE, | 129 | .me = THIS_MODULE, |
130 | .af = AF_INET6, | ||
130 | }; | 131 | }; |
131 | 132 | ||
132 | /* The work comes in here from netfilter.c. */ | 133 | /* The work comes in here from netfilter.c. */ |
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index c2982efd14af..db28ba3855e2 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c | |||
@@ -106,11 +106,12 @@ static struct | |||
106 | } | 106 | } |
107 | }; | 107 | }; |
108 | 108 | ||
109 | static struct ip6t_table packet_raw = { | 109 | static struct xt_table packet_raw = { |
110 | .name = "raw", | 110 | .name = "raw", |
111 | .valid_hooks = RAW_VALID_HOOKS, | 111 | .valid_hooks = RAW_VALID_HOOKS, |
112 | .lock = RW_LOCK_UNLOCKED, | 112 | .lock = RW_LOCK_UNLOCKED, |
113 | .me = THIS_MODULE | 113 | .me = THIS_MODULE, |
114 | .af = AF_INET6, | ||
114 | }; | 115 | }; |
115 | 116 | ||
116 | /* The work comes in here from netfilter.c. */ | 117 | /* The work comes in here from netfilter.c. */ |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index e57d6fc9957a..ac702a29dd16 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -74,7 +74,7 @@ static int ipv6_invert_tuple(struct nf_conntrack_tuple *tuple, | |||
74 | static int ipv6_print_tuple(struct seq_file *s, | 74 | static int ipv6_print_tuple(struct seq_file *s, |
75 | const struct nf_conntrack_tuple *tuple) | 75 | const struct nf_conntrack_tuple *tuple) |
76 | { | 76 | { |
77 | return seq_printf(s, "src=%x:%x:%x:%x:%x:%x:%x:%x dst=%x:%x:%x:%x:%x:%x:%x:%x ", | 77 | return seq_printf(s, "src=" NIP6_FMT " dst=" NIP6_FMT " ", |
78 | NIP6(*((struct in6_addr *)tuple->src.u3.ip6)), | 78 | NIP6(*((struct in6_addr *)tuple->src.u3.ip6)), |
79 | NIP6(*((struct in6_addr *)tuple->dst.u3.ip6))); | 79 | NIP6(*((struct in6_addr *)tuple->dst.u3.ip6))); |
80 | } | 80 | } |
@@ -584,7 +584,7 @@ MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>"); | |||
584 | 584 | ||
585 | static int __init init(void) | 585 | static int __init init(void) |
586 | { | 586 | { |
587 | need_nf_conntrack(); | 587 | need_conntrack(); |
588 | return init_or_cleanup(1); | 588 | return init_or_cleanup(1); |
589 | } | 589 | } |
590 | 590 | ||
@@ -595,9 +595,3 @@ static void __exit fini(void) | |||
595 | 595 | ||
596 | module_init(init); | 596 | module_init(init); |
597 | module_exit(fini); | 597 | module_exit(fini); |
598 | |||
599 | void need_ip6_conntrack(void) | ||
600 | { | ||
601 | } | ||
602 | |||
603 | EXPORT_SYMBOL(need_ip6_conntrack); | ||
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index f3e5ffbd592f..84ef9a13108d 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -70,8 +70,8 @@ struct nf_ct_frag6_skb_cb | |||
70 | 70 | ||
71 | struct nf_ct_frag6_queue | 71 | struct nf_ct_frag6_queue |
72 | { | 72 | { |
73 | struct nf_ct_frag6_queue *next; | 73 | struct hlist_node list; |
74 | struct list_head lru_list; /* lru list member */ | 74 | struct list_head lru_list; /* lru list member */ |
75 | 75 | ||
76 | __u32 id; /* fragment id */ | 76 | __u32 id; /* fragment id */ |
77 | struct in6_addr saddr; | 77 | struct in6_addr saddr; |
@@ -90,14 +90,13 @@ struct nf_ct_frag6_queue | |||
90 | #define FIRST_IN 2 | 90 | #define FIRST_IN 2 |
91 | #define LAST_IN 1 | 91 | #define LAST_IN 1 |
92 | __u16 nhoffset; | 92 | __u16 nhoffset; |
93 | struct nf_ct_frag6_queue **pprev; | ||
94 | }; | 93 | }; |
95 | 94 | ||
96 | /* Hash table. */ | 95 | /* Hash table. */ |
97 | 96 | ||
98 | #define FRAG6Q_HASHSZ 64 | 97 | #define FRAG6Q_HASHSZ 64 |
99 | 98 | ||
100 | static struct nf_ct_frag6_queue *nf_ct_frag6_hash[FRAG6Q_HASHSZ]; | 99 | static struct hlist_head nf_ct_frag6_hash[FRAG6Q_HASHSZ]; |
101 | static DEFINE_RWLOCK(nf_ct_frag6_lock); | 100 | static DEFINE_RWLOCK(nf_ct_frag6_lock); |
102 | static u32 nf_ct_frag6_hash_rnd; | 101 | static u32 nf_ct_frag6_hash_rnd; |
103 | static LIST_HEAD(nf_ct_frag6_lru_list); | 102 | static LIST_HEAD(nf_ct_frag6_lru_list); |
@@ -105,9 +104,7 @@ int nf_ct_frag6_nqueues = 0; | |||
105 | 104 | ||
106 | static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq) | 105 | static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq) |
107 | { | 106 | { |
108 | if (fq->next) | 107 | hlist_del(&fq->list); |
109 | fq->next->pprev = fq->pprev; | ||
110 | *fq->pprev = fq->next; | ||
111 | list_del(&fq->lru_list); | 108 | list_del(&fq->lru_list); |
112 | nf_ct_frag6_nqueues--; | 109 | nf_ct_frag6_nqueues--; |
113 | } | 110 | } |
@@ -158,28 +155,18 @@ static void nf_ct_frag6_secret_rebuild(unsigned long dummy) | |||
158 | get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32)); | 155 | get_random_bytes(&nf_ct_frag6_hash_rnd, sizeof(u32)); |
159 | for (i = 0; i < FRAG6Q_HASHSZ; i++) { | 156 | for (i = 0; i < FRAG6Q_HASHSZ; i++) { |
160 | struct nf_ct_frag6_queue *q; | 157 | struct nf_ct_frag6_queue *q; |
158 | struct hlist_node *p, *n; | ||
161 | 159 | ||
162 | q = nf_ct_frag6_hash[i]; | 160 | hlist_for_each_entry_safe(q, p, n, &nf_ct_frag6_hash[i], list) { |
163 | while (q) { | ||
164 | struct nf_ct_frag6_queue *next = q->next; | ||
165 | unsigned int hval = ip6qhashfn(q->id, | 161 | unsigned int hval = ip6qhashfn(q->id, |
166 | &q->saddr, | 162 | &q->saddr, |
167 | &q->daddr); | 163 | &q->daddr); |
168 | |||
169 | if (hval != i) { | 164 | if (hval != i) { |
170 | /* Unlink. */ | 165 | hlist_del(&q->list); |
171 | if (q->next) | ||
172 | q->next->pprev = q->pprev; | ||
173 | *q->pprev = q->next; | ||
174 | |||
175 | /* Relink to new hash chain. */ | 166 | /* Relink to new hash chain. */ |
176 | if ((q->next = nf_ct_frag6_hash[hval]) != NULL) | 167 | hlist_add_head(&q->list, |
177 | q->next->pprev = &q->next; | 168 | &nf_ct_frag6_hash[hval]); |
178 | nf_ct_frag6_hash[hval] = q; | ||
179 | q->pprev = &nf_ct_frag6_hash[hval]; | ||
180 | } | 169 | } |
181 | |||
182 | q = next; | ||
183 | } | 170 | } |
184 | } | 171 | } |
185 | write_unlock(&nf_ct_frag6_lock); | 172 | write_unlock(&nf_ct_frag6_lock); |
@@ -314,15 +301,17 @@ out: | |||
314 | 301 | ||
315 | /* Creation primitives. */ | 302 | /* Creation primitives. */ |
316 | 303 | ||
317 | |||
318 | static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, | 304 | static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, |
319 | struct nf_ct_frag6_queue *fq_in) | 305 | struct nf_ct_frag6_queue *fq_in) |
320 | { | 306 | { |
321 | struct nf_ct_frag6_queue *fq; | 307 | struct nf_ct_frag6_queue *fq; |
308 | #ifdef CONFIG_SMP | ||
309 | struct hlist_node *n; | ||
310 | #endif | ||
322 | 311 | ||
323 | write_lock(&nf_ct_frag6_lock); | 312 | write_lock(&nf_ct_frag6_lock); |
324 | #ifdef CONFIG_SMP | 313 | #ifdef CONFIG_SMP |
325 | for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { | 314 | hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { |
326 | if (fq->id == fq_in->id && | 315 | if (fq->id == fq_in->id && |
327 | !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) && | 316 | !ipv6_addr_cmp(&fq_in->saddr, &fq->saddr) && |
328 | !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) { | 317 | !ipv6_addr_cmp(&fq_in->daddr, &fq->daddr)) { |
@@ -340,10 +329,7 @@ static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, | |||
340 | atomic_inc(&fq->refcnt); | 329 | atomic_inc(&fq->refcnt); |
341 | 330 | ||
342 | atomic_inc(&fq->refcnt); | 331 | atomic_inc(&fq->refcnt); |
343 | if ((fq->next = nf_ct_frag6_hash[hash]) != NULL) | 332 | hlist_add_head(&fq->list, &nf_ct_frag6_hash[hash]); |
344 | fq->next->pprev = &fq->next; | ||
345 | nf_ct_frag6_hash[hash] = fq; | ||
346 | fq->pprev = &nf_ct_frag6_hash[hash]; | ||
347 | INIT_LIST_HEAD(&fq->lru_list); | 333 | INIT_LIST_HEAD(&fq->lru_list); |
348 | list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list); | 334 | list_add_tail(&fq->lru_list, &nf_ct_frag6_lru_list); |
349 | nf_ct_frag6_nqueues++; | 335 | nf_ct_frag6_nqueues++; |
@@ -384,10 +370,11 @@ static __inline__ struct nf_ct_frag6_queue * | |||
384 | fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) | 370 | fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) |
385 | { | 371 | { |
386 | struct nf_ct_frag6_queue *fq; | 372 | struct nf_ct_frag6_queue *fq; |
373 | struct hlist_node *n; | ||
387 | unsigned int hash = ip6qhashfn(id, src, dst); | 374 | unsigned int hash = ip6qhashfn(id, src, dst); |
388 | 375 | ||
389 | read_lock(&nf_ct_frag6_lock); | 376 | read_lock(&nf_ct_frag6_lock); |
390 | for (fq = nf_ct_frag6_hash[hash]; fq; fq = fq->next) { | 377 | hlist_for_each_entry(fq, n, &nf_ct_frag6_hash[hash], list) { |
391 | if (fq->id == id && | 378 | if (fq->id == id && |
392 | !ipv6_addr_cmp(src, &fq->saddr) && | 379 | !ipv6_addr_cmp(src, &fq->saddr) && |
393 | !ipv6_addr_cmp(dst, &fq->daddr)) { | 380 | !ipv6_addr_cmp(dst, &fq->daddr)) { |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index bf0d0abc3871..a5723024d3b3 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/pfkeyv2.h> | 15 | #include <linux/pfkeyv2.h> |
16 | #include <linux/ipsec.h> | 16 | #include <linux/ipsec.h> |
17 | #include <net/ipv6.h> | 17 | #include <net/ipv6.h> |
18 | #include <net/addrconf.h> | ||
18 | 19 | ||
19 | static struct xfrm_state_afinfo xfrm6_state_afinfo; | 20 | static struct xfrm_state_afinfo xfrm6_state_afinfo; |
20 | 21 | ||
@@ -41,6 +42,22 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
41 | memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); | 42 | memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); |
42 | if (ipv6_addr_any((struct in6_addr*)&x->props.saddr)) | 43 | if (ipv6_addr_any((struct in6_addr*)&x->props.saddr)) |
43 | memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); | 44 | memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); |
45 | if (tmpl->mode && ipv6_addr_any((struct in6_addr*)&x->props.saddr)) { | ||
46 | struct rt6_info *rt; | ||
47 | struct flowi fl_tunnel = { | ||
48 | .nl_u = { | ||
49 | .ip6_u = { | ||
50 | .daddr = *(struct in6_addr *)daddr, | ||
51 | } | ||
52 | } | ||
53 | }; | ||
54 | if (!xfrm_dst_lookup((struct xfrm_dst **)&rt, | ||
55 | &fl_tunnel, AF_INET6)) { | ||
56 | ipv6_get_saddr(&rt->u.dst, (struct in6_addr *)daddr, | ||
57 | (struct in6_addr *)&x->props.saddr); | ||
58 | dst_release(&rt->u.dst); | ||
59 | } | ||
60 | } | ||
44 | x->props.mode = tmpl->mode; | 61 | x->props.mode = tmpl->mode; |
45 | x->props.reqid = tmpl->reqid; | 62 | x->props.reqid = tmpl->reqid; |
46 | x->props.family = AF_INET6; | 63 | x->props.family = AF_INET6; |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index da09ff258648..8cfc58b96fc2 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -259,8 +259,7 @@ try_next_2:; | |||
259 | spi = 0; | 259 | spi = 0; |
260 | goto out; | 260 | goto out; |
261 | alloc_spi: | 261 | alloc_spi: |
262 | X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for " | 262 | X6TPRINTK3(KERN_DEBUG "%s(): allocate new spi for " NIP6_FMT "\n", |
263 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
264 | __FUNCTION__, | 263 | __FUNCTION__, |
265 | NIP6(*(struct in6_addr *)saddr)); | 264 | NIP6(*(struct in6_addr *)saddr)); |
266 | x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC); | 265 | x6spi = kmem_cache_alloc(xfrm6_tunnel_spi_kmem, SLAB_ATOMIC); |
@@ -323,9 +322,8 @@ void xfrm6_tunnel_free_spi(xfrm_address_t *saddr) | |||
323 | list_byaddr) | 322 | list_byaddr) |
324 | { | 323 | { |
325 | if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) { | 324 | if (memcmp(&x6spi->addr, saddr, sizeof(x6spi->addr)) == 0) { |
326 | X6TPRINTK3(KERN_DEBUG "%s(): x6spi object " | 325 | X6TPRINTK3(KERN_DEBUG "%s(): x6spi object for " NIP6_FMT |
327 | "for %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " | 326 | " found at %p\n", |
328 | "found at %p\n", | ||
329 | __FUNCTION__, | 327 | __FUNCTION__, |
330 | NIP6(*(struct in6_addr *)saddr), | 328 | NIP6(*(struct in6_addr *)saddr), |
331 | x6spi); | 329 | x6spi); |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 7d55f9cbd853..99c0a0fa4a97 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -103,3 +103,261 @@ config NF_CT_NETLINK | |||
103 | This option enables support for a netlink-based userspace interface | 103 | This option enables support for a netlink-based userspace interface |
104 | 104 | ||
105 | endmenu | 105 | endmenu |
106 | |||
107 | config NETFILTER_XTABLES | ||
108 | tristate "Netfilter Xtables support (required for ip_tables)" | ||
109 | help | ||
110 | This is required if you intend to use any of ip_tables, | ||
111 | ip6_tables or arp_tables. | ||
112 | |||
113 | # alphabetically ordered list of targets | ||
114 | |||
115 | config NETFILTER_XT_TARGET_CLASSIFY | ||
116 | tristate '"CLASSIFY" target support' | ||
117 | depends on NETFILTER_XTABLES | ||
118 | help | ||
119 | This option adds a `CLASSIFY' target, which enables the user to set | ||
120 | the priority of a packet. Some qdiscs can use this value for | ||
121 | classification, among these are: | ||
122 | |||
123 | atm, cbq, dsmark, pfifo_fast, htb, prio | ||
124 | |||
125 | To compile it as a module, choose M here. If unsure, say N. | ||
126 | |||
127 | config NETFILTER_XT_TARGET_CONNMARK | ||
128 | tristate '"CONNMARK" target support' | ||
129 | depends on NETFILTER_XTABLES | ||
130 | depends on IP_NF_MANGLE || IP6_NF_MANGLE | ||
131 | depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || (NF_CONNTRACK_MARK && NF_CONNTRACK_IPV4) | ||
132 | help | ||
133 | This option adds a `CONNMARK' target, which allows one to manipulate | ||
134 | the connection mark value. Similar to the MARK target, but | ||
135 | affects the connection mark value rather than the packet mark value. | ||
136 | |||
137 | If you want to compile it as a module, say M here and read | ||
138 | <file:Documentation/modules.txt>. The module will be called | ||
139 | ipt_CONNMARK.o. If unsure, say `N'. | ||
140 | |||
141 | config NETFILTER_XT_TARGET_MARK | ||
142 | tristate '"MARK" target support' | ||
143 | depends on NETFILTER_XTABLES | ||
144 | help | ||
145 | This option adds a `MARK' target, which allows you to create rules | ||
146 | in the `mangle' table which alter the netfilter mark (nfmark) field | ||
147 | associated with the packet prior to routing. This can change | ||
148 | the routing method (see `Use netfilter MARK value as routing | ||
149 | key') and can also be used by other subsystems to change their | ||
150 | behavior. | ||
151 | |||
152 | To compile it as a module, choose M here. If unsure, say N. | ||
153 | |||
154 | config NETFILTER_XT_TARGET_NFQUEUE | ||
155 | tristate '"NFQUEUE" target Support' | ||
156 | depends on NETFILTER_XTABLES | ||
157 | help | ||
158 | This Target replaced the old obsolete QUEUE target. | ||
159 | |||
160 | As opposed to QUEUE, it supports 65535 different queues, | ||
161 | not just one. | ||
162 | |||
163 | To compile it as a module, choose M here. If unsure, say N. | ||
164 | |||
165 | config NETFILTER_XT_TARGET_NOTRACK | ||
166 | tristate '"NOTRACK" target support' | ||
167 | depends on NETFILTER_XTABLES | ||
168 | depends on IP_NF_RAW || IP6_NF_RAW | ||
169 | depends on IP_NF_CONNTRACK || NF_CONNTRACK | ||
170 | help | ||
171 | The NOTRACK target allows a select rule to specify | ||
172 | which packets *not* to enter the conntrack/NAT | ||
173 | subsystem with all the consequences (no ICMP error tracking, | ||
174 | no protocol helpers for the selected packets). | ||
175 | |||
176 | If you want to compile it as a module, say M here and read | ||
177 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
178 | |||
179 | config NETFILTER_XT_MATCH_COMMENT | ||
180 | tristate '"comment" match support' | ||
181 | depends on NETFILTER_XTABLES | ||
182 | help | ||
183 | This option adds a `comment' dummy-match, which allows you to put | ||
184 | comments in your iptables ruleset. | ||
185 | |||
186 | If you want to compile it as a module, say M here and read | ||
187 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
188 | |||
189 | config NETFILTER_XT_MATCH_CONNBYTES | ||
190 | tristate '"connbytes" per-connection counter match support' | ||
191 | depends on NETFILTER_XTABLES | ||
192 | depends on (IP_NF_CONNTRACK && IP_NF_CT_ACCT) || NF_CT_ACCT | ||
193 | help | ||
194 | This option adds a `connbytes' match, which allows you to match the | ||
195 | number of bytes and/or packets for each direction within a connection. | ||
196 | |||
197 | If you want to compile it as a module, say M here and read | ||
198 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
199 | |||
200 | config NETFILTER_XT_MATCH_CONNMARK | ||
201 | tristate '"connmark" connection mark match support' | ||
202 | depends on NETFILTER_XTABLES | ||
203 | depends on (IP_NF_CONNTRACK && IP_NF_CONNTRACK_MARK) || NF_CONNTRACK_MARK | ||
204 | help | ||
205 | This option adds a `connmark' match, which allows you to match the | ||
206 | connection mark value previously set for the session by `CONNMARK'. | ||
207 | |||
208 | If you want to compile it as a module, say M here and read | ||
209 | <file:Documentation/modules.txt>. The module will be called | ||
210 | ipt_connmark.o. If unsure, say `N'. | ||
211 | |||
212 | config NETFILTER_XT_MATCH_CONNTRACK | ||
213 | tristate '"conntrack" connection tracking match support' | ||
214 | depends on NETFILTER_XTABLES | ||
215 | depends on IP_NF_CONNTRACK || NF_CONNTRACK | ||
216 | help | ||
217 | This is a general conntrack match module, a superset of the state match. | ||
218 | |||
219 | It allows matching on additional conntrack information, which is | ||
220 | useful in complex configurations, such as NAT gateways with multiple | ||
221 | internet links or tunnels. | ||
222 | |||
223 | To compile it as a module, choose M here. If unsure, say N. | ||
224 | |||
225 | config NETFILTER_XT_MATCH_DCCP | ||
226 | tristate '"DCCP" protocol match support' | ||
227 | depends on NETFILTER_XTABLES | ||
228 | help | ||
229 | With this option enabled, you will be able to use the iptables | ||
230 | `dccp' match in order to match on DCCP source/destination ports | ||
231 | and DCCP flags. | ||
232 | |||
233 | If you want to compile it as a module, say M here and read | ||
234 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
235 | |||
236 | config NETFILTER_XT_MATCH_HELPER | ||
237 | tristate '"helper" match support' | ||
238 | depends on NETFILTER_XTABLES | ||
239 | depends on IP_NF_CONNTRACK || NF_CONNTRACK | ||
240 | help | ||
241 | Helper matching allows you to match packets in dynamic connections | ||
242 | tracked by a conntrack-helper, ie. ip_conntrack_ftp | ||
243 | |||
244 | To compile it as a module, choose M here. If unsure, say Y. | ||
245 | |||
246 | config NETFILTER_XT_MATCH_LENGTH | ||
247 | tristate '"length" match support' | ||
248 | depends on NETFILTER_XTABLES | ||
249 | help | ||
250 | This option allows you to match the length of a packet against a | ||
251 | specific value or range of values. | ||
252 | |||
253 | To compile it as a module, choose M here. If unsure, say N. | ||
254 | |||
255 | config NETFILTER_XT_MATCH_LIMIT | ||
256 | tristate '"limit" match support' | ||
257 | depends on NETFILTER_XTABLES | ||
258 | help | ||
259 | limit matching allows you to control the rate at which a rule can be | ||
260 | matched: mainly useful in combination with the LOG target ("LOG | ||
261 | target support", below) and to avoid some Denial of Service attacks. | ||
262 | |||
263 | To compile it as a module, choose M here. If unsure, say N. | ||
264 | |||
265 | config NETFILTER_XT_MATCH_MAC | ||
266 | tristate '"mac" address match support' | ||
267 | depends on NETFILTER_XTABLES | ||
268 | help | ||
269 | MAC matching allows you to match packets based on the source | ||
270 | Ethernet address of the packet. | ||
271 | |||
272 | To compile it as a module, choose M here. If unsure, say N. | ||
273 | |||
274 | config NETFILTER_XT_MATCH_MARK | ||
275 | tristate '"mark" match support' | ||
276 | depends on NETFILTER_XTABLES | ||
277 | help | ||
278 | Netfilter mark matching allows you to match packets based on the | ||
279 | `nfmark' value in the packet. This can be set by the MARK target | ||
280 | (see below). | ||
281 | |||
282 | To compile it as a module, choose M here. If unsure, say N. | ||
283 | |||
284 | config NETFILTER_XT_MATCH_PHYSDEV | ||
285 | tristate '"physdev" match support' | ||
286 | depends on NETFILTER_XTABLES && BRIDGE_NETFILTER | ||
287 | help | ||
288 | Physdev packet matching matches against the physical bridge ports | ||
289 | the IP packet arrived on or will leave by. | ||
290 | |||
291 | To compile it as a module, choose M here. If unsure, say N. | ||
292 | |||
293 | config NETFILTER_XT_MATCH_PKTTYPE | ||
294 | tristate '"pkttype" packet type match support' | ||
295 | depends on NETFILTER_XTABLES | ||
296 | help | ||
297 | Packet type matching allows you to match a packet by | ||
298 | its "class", eg. BROADCAST, MULTICAST, ... | ||
299 | |||
300 | Typical usage: | ||
301 | iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG | ||
302 | |||
303 | To compile it as a module, choose M here. If unsure, say N. | ||
304 | |||
305 | config NETFILTER_XT_MATCH_REALM | ||
306 | tristate '"realm" match support' | ||
307 | depends on NETFILTER_XTABLES | ||
308 | select NET_CLS_ROUTE | ||
309 | help | ||
310 | This option adds a `realm' match, which allows you to use the realm | ||
311 | key from the routing subsystem inside iptables. | ||
312 | |||
313 | This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option | ||
314 | in tc world. | ||
315 | |||
316 | If you want to compile it as a module, say M here and read | ||
317 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
318 | |||
319 | config NETFILTER_XT_MATCH_SCTP | ||
320 | tristate '"sctp" protocol match support' | ||
321 | depends on NETFILTER_XTABLES | ||
322 | help | ||
323 | With this option enabled, you will be able to use the | ||
324 | `sctp' match in order to match on SCTP source/destination ports | ||
325 | and SCTP chunk types. | ||
326 | |||
327 | If you want to compile it as a module, say M here and read | ||
328 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
329 | |||
330 | config NETFILTER_XT_MATCH_STATE | ||
331 | tristate '"state" match support' | ||
332 | depends on NETFILTER_XTABLES | ||
333 | depends on IP_NF_CONNTRACK || NF_CONNTRACK | ||
334 | help | ||
335 | Connection state matching allows you to match packets based on their | ||
336 | relationship to a tracked connection (ie. previous packets). This | ||
337 | is a powerful tool for packet classification. | ||
338 | |||
339 | To compile it as a module, choose M here. If unsure, say N. | ||
340 | |||
341 | config NETFILTER_XT_MATCH_STRING | ||
342 | tristate '"string" match support' | ||
343 | depends on NETFILTER_XTABLES | ||
344 | select TEXTSEARCH | ||
345 | select TEXTSEARCH_KMP | ||
346 | select TEXTSEARCH_BM | ||
347 | select TEXTSEARCH_FSM | ||
348 | help | ||
349 | This option adds a `string' match, which allows you to look for | ||
350 | pattern matchings in packets. | ||
351 | |||
352 | To compile it as a module, choose M here. If unsure, say N. | ||
353 | |||
354 | config NETFILTER_XT_MATCH_TCPMSS | ||
355 | tristate '"tcpmss" match support' | ||
356 | depends on NETFILTER_XTABLES | ||
357 | help | ||
358 | This option adds a `tcpmss' match, which allows you to examine the | ||
359 | MSS value of TCP SYN packets, which control the maximum packet size | ||
360 | for that connection. | ||
361 | |||
362 | To compile it as a module, choose M here. If unsure, say N. | ||
363 | |||
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index cb2183145c37..746172ebc91b 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -1,4 +1,5 @@ | |||
1 | netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o | 1 | netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o |
2 | nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o | ||
2 | 3 | ||
3 | obj-$(CONFIG_NETFILTER) = netfilter.o | 4 | obj-$(CONFIG_NETFILTER) = netfilter.o |
4 | 5 | ||
@@ -6,13 +7,43 @@ obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o | |||
6 | obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o | 7 | obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o |
7 | obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o | 8 | obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o |
8 | 9 | ||
9 | nf_conntrack-objs := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o | 10 | # connection tracking |
10 | |||
11 | obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o | 11 | obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o |
12 | obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o | ||
13 | 12 | ||
14 | # SCTP protocol connection tracking | 13 | # SCTP protocol connection tracking |
15 | obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o | 14 | obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o |
16 | 15 | ||
17 | # netlink interface for nf_conntrack | 16 | # netlink interface for nf_conntrack |
18 | obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o | 17 | obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o |
18 | |||
19 | # connection tracking helpers | ||
20 | obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o | ||
21 | |||
22 | # generic X tables | ||
23 | obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o | ||
24 | |||
25 | # targets | ||
26 | obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o | ||
27 | obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o | ||
28 | obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o | ||
29 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o | ||
30 | obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o | ||
31 | |||
32 | # matches | ||
33 | obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o | ||
34 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o | ||
35 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o | ||
36 | obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o | ||
37 | obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o | ||
38 | obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o | ||
39 | obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o | ||
40 | obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o | ||
41 | obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o | ||
42 | obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o | ||
43 | obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o | ||
44 | obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o | ||
45 | obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o | ||
46 | obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o | ||
47 | obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o | ||
48 | obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o | ||
49 | obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o | ||
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index d5a6eaf4a1de..ab0c920f0d30 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c | |||
@@ -545,11 +545,11 @@ static int help(struct sk_buff **pskb, | |||
545 | different IP address. Simply don't record it for | 545 | different IP address. Simply don't record it for |
546 | NAT. */ | 546 | NAT. */ |
547 | if (cmd.l3num == PF_INET) { | 547 | if (cmd.l3num == PF_INET) { |
548 | DEBUGP("conntrack_ftp: NOT RECORDING: %u,%u,%u,%u != %u.%u.%u.%u\n", | 548 | DEBUGP("conntrack_ftp: NOT RECORDING: " NIPQUAD_FMT " != " NIPQUAD_FMT "\n", |
549 | NIPQUAD(cmd.u3.ip), | 549 | NIPQUAD(cmd.u3.ip), |
550 | NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip)); | 550 | NIPQUAD(ct->tuplehash[dir].tuple.src.u3.ip)); |
551 | } else { | 551 | } else { |
552 | DEBUGP("conntrack_ftp: NOT RECORDING: %x:%x:%x:%x:%x:%x:%x:%x != %x:%x:%x:%x:%x:%x:%x:%x\n", | 552 | DEBUGP("conntrack_ftp: NOT RECORDING: " NIP6_FMT " != " NIP6_FMT "\n", |
553 | NIP6(*((struct in6_addr *)cmd.u3.ip6)), | 553 | NIP6(*((struct in6_addr *)cmd.u3.ip6)), |
554 | NIP6(*((struct in6_addr *)ct->tuplehash[dir] | 554 | NIP6(*((struct in6_addr *)ct->tuplehash[dir] |
555 | .tuple.src.u3.ip6))); | 555 | .tuple.src.u3.ip6))); |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 3531d142f693..617599aeeead 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
@@ -821,7 +821,7 @@ module_exit(fini); | |||
821 | 821 | ||
822 | /* Some modules need us, but don't depend directly on any symbol. | 822 | /* Some modules need us, but don't depend directly on any symbol. |
823 | They should call this. */ | 823 | They should call this. */ |
824 | void need_nf_conntrack(void) | 824 | void need_conntrack(void) |
825 | { | 825 | { |
826 | } | 826 | } |
827 | 827 | ||
@@ -841,7 +841,7 @@ EXPORT_SYMBOL(nf_conntrack_protocol_unregister); | |||
841 | EXPORT_SYMBOL(nf_ct_invert_tuplepr); | 841 | EXPORT_SYMBOL(nf_ct_invert_tuplepr); |
842 | EXPORT_SYMBOL(nf_conntrack_alter_reply); | 842 | EXPORT_SYMBOL(nf_conntrack_alter_reply); |
843 | EXPORT_SYMBOL(nf_conntrack_destroyed); | 843 | EXPORT_SYMBOL(nf_conntrack_destroyed); |
844 | EXPORT_SYMBOL(need_nf_conntrack); | 844 | EXPORT_SYMBOL(need_conntrack); |
845 | EXPORT_SYMBOL(nf_conntrack_helper_register); | 845 | EXPORT_SYMBOL(nf_conntrack_helper_register); |
846 | EXPORT_SYMBOL(nf_conntrack_helper_unregister); | 846 | EXPORT_SYMBOL(nf_conntrack_helper_unregister); |
847 | EXPORT_SYMBOL(nf_ct_iterate_cleanup); | 847 | EXPORT_SYMBOL(nf_ct_iterate_cleanup); |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c new file mode 100644 index 000000000000..d7817afc6b96 --- /dev/null +++ b/net/netfilter/x_tables.c | |||
@@ -0,0 +1,624 @@ | |||
1 | /* | ||
2 | * x_tables core - Backend for {ip,ip6,arp}_tables | ||
3 | * | ||
4 | * Copyright (C) 2006-2006 Harald Welte <laforge@netfilter.org> | ||
5 | * | ||
6 | * Based on existing ip_tables code which is | ||
7 | * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling | ||
8 | * Copyright (C) 2000-2005 Netfilter Core Team <coreteam@netfilter.org> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/socket.h> | ||
19 | #include <linux/net.h> | ||
20 | #include <linux/proc_fs.h> | ||
21 | #include <linux/seq_file.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/vmalloc.h> | ||
24 | |||
25 | #include <linux/netfilter/x_tables.h> | ||
26 | #include <linux/netfilter_arp.h> | ||
27 | |||
28 | MODULE_LICENSE("GPL"); | ||
29 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
30 | MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module"); | ||
31 | |||
32 | #define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1)) | ||
33 | |||
34 | struct xt_af { | ||
35 | struct semaphore mutex; | ||
36 | struct list_head match; | ||
37 | struct list_head target; | ||
38 | struct list_head tables; | ||
39 | }; | ||
40 | |||
41 | static struct xt_af *xt; | ||
42 | |||
43 | #ifdef DEBUG_IP_FIREWALL_USER | ||
44 | #define duprintf(format, args...) printk(format , ## args) | ||
45 | #else | ||
46 | #define duprintf(format, args...) | ||
47 | #endif | ||
48 | |||
49 | enum { | ||
50 | TABLE, | ||
51 | TARGET, | ||
52 | MATCH, | ||
53 | }; | ||
54 | |||
55 | /* Registration hooks for targets. */ | ||
56 | int | ||
57 | xt_register_target(int af, struct xt_target *target) | ||
58 | { | ||
59 | int ret; | ||
60 | |||
61 | ret = down_interruptible(&xt[af].mutex); | ||
62 | if (ret != 0) | ||
63 | return ret; | ||
64 | list_add(&target->list, &xt[af].target); | ||
65 | up(&xt[af].mutex); | ||
66 | return ret; | ||
67 | } | ||
68 | EXPORT_SYMBOL(xt_register_target); | ||
69 | |||
70 | void | ||
71 | xt_unregister_target(int af, struct xt_target *target) | ||
72 | { | ||
73 | down(&xt[af].mutex); | ||
74 | LIST_DELETE(&xt[af].target, target); | ||
75 | up(&xt[af].mutex); | ||
76 | } | ||
77 | EXPORT_SYMBOL(xt_unregister_target); | ||
78 | |||
79 | int | ||
80 | xt_register_match(int af, struct xt_match *match) | ||
81 | { | ||
82 | int ret; | ||
83 | |||
84 | ret = down_interruptible(&xt[af].mutex); | ||
85 | if (ret != 0) | ||
86 | return ret; | ||
87 | |||
88 | list_add(&match->list, &xt[af].match); | ||
89 | up(&xt[af].mutex); | ||
90 | |||
91 | return ret; | ||
92 | } | ||
93 | EXPORT_SYMBOL(xt_register_match); | ||
94 | |||
95 | void | ||
96 | xt_unregister_match(int af, struct xt_match *match) | ||
97 | { | ||
98 | down(&xt[af].mutex); | ||
99 | LIST_DELETE(&xt[af].match, match); | ||
100 | up(&xt[af].mutex); | ||
101 | } | ||
102 | EXPORT_SYMBOL(xt_unregister_match); | ||
103 | |||
104 | |||
105 | /* | ||
106 | * These are weird, but module loading must not be done with mutex | ||
107 | * held (since they will register), and we have to have a single | ||
108 | * function to use try_then_request_module(). | ||
109 | */ | ||
110 | |||
111 | /* Find match, grabs ref. Returns ERR_PTR() on error. */ | ||
112 | struct xt_match *xt_find_match(int af, const char *name, u8 revision) | ||
113 | { | ||
114 | struct xt_match *m; | ||
115 | int err = 0; | ||
116 | |||
117 | if (down_interruptible(&xt[af].mutex) != 0) | ||
118 | return ERR_PTR(-EINTR); | ||
119 | |||
120 | list_for_each_entry(m, &xt[af].match, list) { | ||
121 | if (strcmp(m->name, name) == 0) { | ||
122 | if (m->revision == revision) { | ||
123 | if (try_module_get(m->me)) { | ||
124 | up(&xt[af].mutex); | ||
125 | return m; | ||
126 | } | ||
127 | } else | ||
128 | err = -EPROTOTYPE; /* Found something. */ | ||
129 | } | ||
130 | } | ||
131 | up(&xt[af].mutex); | ||
132 | return ERR_PTR(err); | ||
133 | } | ||
134 | EXPORT_SYMBOL(xt_find_match); | ||
135 | |||
136 | /* Find target, grabs ref. Returns ERR_PTR() on error. */ | ||
137 | struct xt_target *xt_find_target(int af, const char *name, u8 revision) | ||
138 | { | ||
139 | struct xt_target *t; | ||
140 | int err = 0; | ||
141 | |||
142 | if (down_interruptible(&xt[af].mutex) != 0) | ||
143 | return ERR_PTR(-EINTR); | ||
144 | |||
145 | list_for_each_entry(t, &xt[af].target, list) { | ||
146 | if (strcmp(t->name, name) == 0) { | ||
147 | if (t->revision == revision) { | ||
148 | if (try_module_get(t->me)) { | ||
149 | up(&xt[af].mutex); | ||
150 | return t; | ||
151 | } | ||
152 | } else | ||
153 | err = -EPROTOTYPE; /* Found something. */ | ||
154 | } | ||
155 | } | ||
156 | up(&xt[af].mutex); | ||
157 | return ERR_PTR(err); | ||
158 | } | ||
159 | EXPORT_SYMBOL(xt_find_target); | ||
160 | |||
161 | static const char *xt_prefix[NPROTO] = { | ||
162 | [AF_INET] = "ipt_%s", | ||
163 | [AF_INET6] = "ip6t_%s", | ||
164 | [NF_ARP] = "arpt_%s", | ||
165 | }; | ||
166 | |||
167 | struct xt_target *xt_request_find_target(int af, const char *name, u8 revision) | ||
168 | { | ||
169 | struct xt_target *target; | ||
170 | |||
171 | target = try_then_request_module(xt_find_target(af, name, revision), | ||
172 | xt_prefix[af], name); | ||
173 | if (IS_ERR(target) || !target) | ||
174 | return NULL; | ||
175 | return target; | ||
176 | } | ||
177 | EXPORT_SYMBOL_GPL(xt_request_find_target); | ||
178 | |||
179 | static int match_revfn(int af, const char *name, u8 revision, int *bestp) | ||
180 | { | ||
181 | struct xt_match *m; | ||
182 | int have_rev = 0; | ||
183 | |||
184 | list_for_each_entry(m, &xt[af].match, list) { | ||
185 | if (strcmp(m->name, name) == 0) { | ||
186 | if (m->revision > *bestp) | ||
187 | *bestp = m->revision; | ||
188 | if (m->revision == revision) | ||
189 | have_rev = 1; | ||
190 | } | ||
191 | } | ||
192 | return have_rev; | ||
193 | } | ||
194 | |||
195 | static int target_revfn(int af, const char *name, u8 revision, int *bestp) | ||
196 | { | ||
197 | struct xt_target *t; | ||
198 | int have_rev = 0; | ||
199 | |||
200 | list_for_each_entry(t, &xt[af].target, list) { | ||
201 | if (strcmp(t->name, name) == 0) { | ||
202 | if (t->revision > *bestp) | ||
203 | *bestp = t->revision; | ||
204 | if (t->revision == revision) | ||
205 | have_rev = 1; | ||
206 | } | ||
207 | } | ||
208 | return have_rev; | ||
209 | } | ||
210 | |||
211 | /* Returns true or false (if no such extension at all) */ | ||
212 | int xt_find_revision(int af, const char *name, u8 revision, int target, | ||
213 | int *err) | ||
214 | { | ||
215 | int have_rev, best = -1; | ||
216 | |||
217 | if (down_interruptible(&xt[af].mutex) != 0) { | ||
218 | *err = -EINTR; | ||
219 | return 1; | ||
220 | } | ||
221 | if (target == 1) | ||
222 | have_rev = target_revfn(af, name, revision, &best); | ||
223 | else | ||
224 | have_rev = match_revfn(af, name, revision, &best); | ||
225 | up(&xt[af].mutex); | ||
226 | |||
227 | /* Nothing at all? Return 0 to try loading module. */ | ||
228 | if (best == -1) { | ||
229 | *err = -ENOENT; | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | *err = best; | ||
234 | if (!have_rev) | ||
235 | *err = -EPROTONOSUPPORT; | ||
236 | return 1; | ||
237 | } | ||
238 | EXPORT_SYMBOL_GPL(xt_find_revision); | ||
239 | |||
240 | struct xt_table_info *xt_alloc_table_info(unsigned int size) | ||
241 | { | ||
242 | struct xt_table_info *newinfo; | ||
243 | int cpu; | ||
244 | |||
245 | /* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */ | ||
246 | if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > num_physpages) | ||
247 | return NULL; | ||
248 | |||
249 | newinfo = kzalloc(sizeof(struct xt_table_info), GFP_KERNEL); | ||
250 | if (!newinfo) | ||
251 | return NULL; | ||
252 | |||
253 | newinfo->size = size; | ||
254 | |||
255 | for_each_cpu(cpu) { | ||
256 | if (size <= PAGE_SIZE) | ||
257 | newinfo->entries[cpu] = kmalloc_node(size, | ||
258 | GFP_KERNEL, | ||
259 | cpu_to_node(cpu)); | ||
260 | else | ||
261 | newinfo->entries[cpu] = vmalloc_node(size, | ||
262 | cpu_to_node(cpu)); | ||
263 | |||
264 | if (newinfo->entries[cpu] == NULL) { | ||
265 | xt_free_table_info(newinfo); | ||
266 | return NULL; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | return newinfo; | ||
271 | } | ||
272 | EXPORT_SYMBOL(xt_alloc_table_info); | ||
273 | |||
274 | void xt_free_table_info(struct xt_table_info *info) | ||
275 | { | ||
276 | int cpu; | ||
277 | |||
278 | for_each_cpu(cpu) { | ||
279 | if (info->size <= PAGE_SIZE) | ||
280 | kfree(info->entries[cpu]); | ||
281 | else | ||
282 | vfree(info->entries[cpu]); | ||
283 | } | ||
284 | kfree(info); | ||
285 | } | ||
286 | EXPORT_SYMBOL(xt_free_table_info); | ||
287 | |||
288 | /* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */ | ||
289 | struct xt_table *xt_find_table_lock(int af, const char *name) | ||
290 | { | ||
291 | struct xt_table *t; | ||
292 | |||
293 | if (down_interruptible(&xt[af].mutex) != 0) | ||
294 | return ERR_PTR(-EINTR); | ||
295 | |||
296 | list_for_each_entry(t, &xt[af].tables, list) | ||
297 | if (strcmp(t->name, name) == 0 && try_module_get(t->me)) | ||
298 | return t; | ||
299 | up(&xt[af].mutex); | ||
300 | return NULL; | ||
301 | } | ||
302 | EXPORT_SYMBOL_GPL(xt_find_table_lock); | ||
303 | |||
304 | void xt_table_unlock(struct xt_table *table) | ||
305 | { | ||
306 | up(&xt[table->af].mutex); | ||
307 | } | ||
308 | EXPORT_SYMBOL_GPL(xt_table_unlock); | ||
309 | |||
310 | |||
311 | struct xt_table_info * | ||
312 | xt_replace_table(struct xt_table *table, | ||
313 | unsigned int num_counters, | ||
314 | struct xt_table_info *newinfo, | ||
315 | int *error) | ||
316 | { | ||
317 | struct xt_table_info *oldinfo, *private; | ||
318 | |||
319 | /* Do the substitution. */ | ||
320 | write_lock_bh(&table->lock); | ||
321 | private = table->private; | ||
322 | /* Check inside lock: is the old number correct? */ | ||
323 | if (num_counters != private->number) { | ||
324 | duprintf("num_counters != table->private->number (%u/%u)\n", | ||
325 | num_counters, private->number); | ||
326 | write_unlock_bh(&table->lock); | ||
327 | *error = -EAGAIN; | ||
328 | return NULL; | ||
329 | } | ||
330 | oldinfo = private; | ||
331 | table->private = newinfo; | ||
332 | newinfo->initial_entries = oldinfo->initial_entries; | ||
333 | write_unlock_bh(&table->lock); | ||
334 | |||
335 | return oldinfo; | ||
336 | } | ||
337 | EXPORT_SYMBOL_GPL(xt_replace_table); | ||
338 | |||
339 | int xt_register_table(struct xt_table *table, | ||
340 | struct xt_table_info *bootstrap, | ||
341 | struct xt_table_info *newinfo) | ||
342 | { | ||
343 | int ret; | ||
344 | struct xt_table_info *private; | ||
345 | |||
346 | ret = down_interruptible(&xt[table->af].mutex); | ||
347 | if (ret != 0) | ||
348 | return ret; | ||
349 | |||
350 | /* Don't autoload: we'd eat our tail... */ | ||
351 | if (list_named_find(&xt[table->af].tables, table->name)) { | ||
352 | ret = -EEXIST; | ||
353 | goto unlock; | ||
354 | } | ||
355 | |||
356 | /* Simplifies replace_table code. */ | ||
357 | table->private = bootstrap; | ||
358 | if (!xt_replace_table(table, 0, newinfo, &ret)) | ||
359 | goto unlock; | ||
360 | |||
361 | private = table->private; | ||
362 | duprintf("table->private->number = %u\n", private->number); | ||
363 | |||
364 | /* save number of initial entries */ | ||
365 | private->initial_entries = private->number; | ||
366 | |||
367 | rwlock_init(&table->lock); | ||
368 | list_prepend(&xt[table->af].tables, table); | ||
369 | |||
370 | ret = 0; | ||
371 | unlock: | ||
372 | up(&xt[table->af].mutex); | ||
373 | return ret; | ||
374 | } | ||
375 | EXPORT_SYMBOL_GPL(xt_register_table); | ||
376 | |||
377 | void *xt_unregister_table(struct xt_table *table) | ||
378 | { | ||
379 | struct xt_table_info *private; | ||
380 | |||
381 | down(&xt[table->af].mutex); | ||
382 | private = table->private; | ||
383 | LIST_DELETE(&xt[table->af].tables, table); | ||
384 | up(&xt[table->af].mutex); | ||
385 | |||
386 | return private; | ||
387 | } | ||
388 | EXPORT_SYMBOL_GPL(xt_unregister_table); | ||
389 | |||
390 | #ifdef CONFIG_PROC_FS | ||
391 | static char *xt_proto_prefix[NPROTO] = { | ||
392 | [AF_INET] = "ip", | ||
393 | [AF_INET6] = "ip6", | ||
394 | [NF_ARP] = "arp", | ||
395 | }; | ||
396 | |||
397 | static struct list_head *xt_get_idx(struct list_head *list, struct seq_file *seq, loff_t pos) | ||
398 | { | ||
399 | struct list_head *head = list->next; | ||
400 | |||
401 | if (!head || list_empty(list)) | ||
402 | return NULL; | ||
403 | |||
404 | while (pos && (head = head->next)) { | ||
405 | if (head == list) | ||
406 | return NULL; | ||
407 | pos--; | ||
408 | } | ||
409 | return pos ? NULL : head; | ||
410 | } | ||
411 | |||
412 | static struct list_head *type2list(u_int16_t af, u_int16_t type) | ||
413 | { | ||
414 | struct list_head *list; | ||
415 | |||
416 | switch (type) { | ||
417 | case TARGET: | ||
418 | list = &xt[af].target; | ||
419 | break; | ||
420 | case MATCH: | ||
421 | list = &xt[af].match; | ||
422 | break; | ||
423 | case TABLE: | ||
424 | list = &xt[af].tables; | ||
425 | break; | ||
426 | default: | ||
427 | list = NULL; | ||
428 | break; | ||
429 | } | ||
430 | |||
431 | return list; | ||
432 | } | ||
433 | |||
434 | static void *xt_tgt_seq_start(struct seq_file *seq, loff_t *pos) | ||
435 | { | ||
436 | struct proc_dir_entry *pde = (struct proc_dir_entry *) seq->private; | ||
437 | u_int16_t af = (unsigned long)pde->data & 0xffff; | ||
438 | u_int16_t type = (unsigned long)pde->data >> 16; | ||
439 | struct list_head *list; | ||
440 | |||
441 | if (af >= NPROTO) | ||
442 | return NULL; | ||
443 | |||
444 | list = type2list(af, type); | ||
445 | if (!list) | ||
446 | return NULL; | ||
447 | |||
448 | if (down_interruptible(&xt[af].mutex) != 0) | ||
449 | return NULL; | ||
450 | |||
451 | return xt_get_idx(list, seq, *pos); | ||
452 | } | ||
453 | |||
454 | static void *xt_tgt_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
455 | { | ||
456 | struct proc_dir_entry *pde = seq->private; | ||
457 | u_int16_t af = (unsigned long)pde->data & 0xffff; | ||
458 | u_int16_t type = (unsigned long)pde->data >> 16; | ||
459 | struct list_head *list; | ||
460 | |||
461 | if (af >= NPROTO) | ||
462 | return NULL; | ||
463 | |||
464 | list = type2list(af, type); | ||
465 | if (!list) | ||
466 | return NULL; | ||
467 | |||
468 | (*pos)++; | ||
469 | return xt_get_idx(list, seq, *pos); | ||
470 | } | ||
471 | |||
472 | static void xt_tgt_seq_stop(struct seq_file *seq, void *v) | ||
473 | { | ||
474 | struct proc_dir_entry *pde = seq->private; | ||
475 | u_int16_t af = (unsigned long)pde->data & 0xffff; | ||
476 | |||
477 | up(&xt[af].mutex); | ||
478 | } | ||
479 | |||
480 | static int xt_name_seq_show(struct seq_file *seq, void *v) | ||
481 | { | ||
482 | char *name = (char *)v + sizeof(struct list_head); | ||
483 | |||
484 | if (strlen(name)) | ||
485 | return seq_printf(seq, "%s\n", name); | ||
486 | else | ||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static struct seq_operations xt_tgt_seq_ops = { | ||
491 | .start = xt_tgt_seq_start, | ||
492 | .next = xt_tgt_seq_next, | ||
493 | .stop = xt_tgt_seq_stop, | ||
494 | .show = xt_name_seq_show, | ||
495 | }; | ||
496 | |||
497 | static int xt_tgt_open(struct inode *inode, struct file *file) | ||
498 | { | ||
499 | int ret; | ||
500 | |||
501 | ret = seq_open(file, &xt_tgt_seq_ops); | ||
502 | if (!ret) { | ||
503 | struct seq_file *seq = file->private_data; | ||
504 | struct proc_dir_entry *pde = PDE(inode); | ||
505 | |||
506 | seq->private = pde; | ||
507 | } | ||
508 | |||
509 | return ret; | ||
510 | } | ||
511 | |||
512 | static struct file_operations xt_file_ops = { | ||
513 | .owner = THIS_MODULE, | ||
514 | .open = xt_tgt_open, | ||
515 | .read = seq_read, | ||
516 | .llseek = seq_lseek, | ||
517 | .release = seq_release, | ||
518 | }; | ||
519 | |||
520 | #define FORMAT_TABLES "_tables_names" | ||
521 | #define FORMAT_MATCHES "_tables_matches" | ||
522 | #define FORMAT_TARGETS "_tables_targets" | ||
523 | |||
524 | #endif /* CONFIG_PROC_FS */ | ||
525 | |||
526 | int xt_proto_init(int af) | ||
527 | { | ||
528 | #ifdef CONFIG_PROC_FS | ||
529 | char buf[XT_FUNCTION_MAXNAMELEN]; | ||
530 | struct proc_dir_entry *proc; | ||
531 | #endif | ||
532 | |||
533 | if (af >= NPROTO) | ||
534 | return -EINVAL; | ||
535 | |||
536 | |||
537 | #ifdef CONFIG_PROC_FS | ||
538 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
539 | strlcat(buf, FORMAT_TABLES, sizeof(buf)); | ||
540 | proc = proc_net_fops_create(buf, 0440, &xt_file_ops); | ||
541 | if (!proc) | ||
542 | goto out; | ||
543 | proc->data = (void *) ((unsigned long) af | (TABLE << 16)); | ||
544 | |||
545 | |||
546 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
547 | strlcat(buf, FORMAT_MATCHES, sizeof(buf)); | ||
548 | proc = proc_net_fops_create(buf, 0440, &xt_file_ops); | ||
549 | if (!proc) | ||
550 | goto out_remove_tables; | ||
551 | proc->data = (void *) ((unsigned long) af | (MATCH << 16)); | ||
552 | |||
553 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
554 | strlcat(buf, FORMAT_TARGETS, sizeof(buf)); | ||
555 | proc = proc_net_fops_create(buf, 0440, &xt_file_ops); | ||
556 | if (!proc) | ||
557 | goto out_remove_matches; | ||
558 | proc->data = (void *) ((unsigned long) af | (TARGET << 16)); | ||
559 | #endif | ||
560 | |||
561 | return 0; | ||
562 | |||
563 | #ifdef CONFIG_PROC_FS | ||
564 | out_remove_matches: | ||
565 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
566 | strlcat(buf, FORMAT_MATCHES, sizeof(buf)); | ||
567 | proc_net_remove(buf); | ||
568 | |||
569 | out_remove_tables: | ||
570 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
571 | strlcat(buf, FORMAT_TABLES, sizeof(buf)); | ||
572 | proc_net_remove(buf); | ||
573 | out: | ||
574 | return -1; | ||
575 | #endif | ||
576 | } | ||
577 | EXPORT_SYMBOL_GPL(xt_proto_init); | ||
578 | |||
579 | void xt_proto_fini(int af) | ||
580 | { | ||
581 | #ifdef CONFIG_PROC_FS | ||
582 | char buf[XT_FUNCTION_MAXNAMELEN]; | ||
583 | |||
584 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
585 | strlcat(buf, FORMAT_TABLES, sizeof(buf)); | ||
586 | proc_net_remove(buf); | ||
587 | |||
588 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
589 | strlcat(buf, FORMAT_TARGETS, sizeof(buf)); | ||
590 | proc_net_remove(buf); | ||
591 | |||
592 | strlcpy(buf, xt_proto_prefix[af], sizeof(buf)); | ||
593 | strlcat(buf, FORMAT_MATCHES, sizeof(buf)); | ||
594 | proc_net_remove(buf); | ||
595 | #endif /*CONFIG_PROC_FS*/ | ||
596 | } | ||
597 | EXPORT_SYMBOL_GPL(xt_proto_fini); | ||
598 | |||
599 | |||
600 | static int __init xt_init(void) | ||
601 | { | ||
602 | int i; | ||
603 | |||
604 | xt = kmalloc(sizeof(struct xt_af) * NPROTO, GFP_KERNEL); | ||
605 | if (!xt) | ||
606 | return -ENOMEM; | ||
607 | |||
608 | for (i = 0; i < NPROTO; i++) { | ||
609 | init_MUTEX(&xt[i].mutex); | ||
610 | INIT_LIST_HEAD(&xt[i].target); | ||
611 | INIT_LIST_HEAD(&xt[i].match); | ||
612 | INIT_LIST_HEAD(&xt[i].tables); | ||
613 | } | ||
614 | return 0; | ||
615 | } | ||
616 | |||
617 | static void __exit xt_fini(void) | ||
618 | { | ||
619 | kfree(xt); | ||
620 | } | ||
621 | |||
622 | module_init(xt_init); | ||
623 | module_exit(xt_fini); | ||
624 | |||
diff --git a/net/ipv4/netfilter/ipt_CLASSIFY.c b/net/netfilter/xt_CLASSIFY.c index dab78d8bd494..78ee266a12ee 100644 --- a/net/ipv4/netfilter/ipt_CLASSIFY.c +++ b/net/netfilter/xt_CLASSIFY.c | |||
@@ -15,12 +15,13 @@ | |||
15 | #include <linux/ip.h> | 15 | #include <linux/ip.h> |
16 | #include <net/checksum.h> | 16 | #include <net/checksum.h> |
17 | 17 | ||
18 | #include <linux/netfilter_ipv4/ip_tables.h> | 18 | #include <linux/netfilter/x_tables.h> |
19 | #include <linux/netfilter_ipv4/ipt_CLASSIFY.h> | 19 | #include <linux/netfilter/xt_CLASSIFY.h> |
20 | 20 | ||
21 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | 21 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); |
22 | MODULE_LICENSE("GPL"); | 22 | MODULE_LICENSE("GPL"); |
23 | MODULE_DESCRIPTION("iptables qdisc classification target module"); | 23 | MODULE_DESCRIPTION("iptables qdisc classification target module"); |
24 | MODULE_ALIAS("ipt_CLASSIFY"); | ||
24 | 25 | ||
25 | static unsigned int | 26 | static unsigned int |
26 | target(struct sk_buff **pskb, | 27 | target(struct sk_buff **pskb, |
@@ -30,25 +31,25 @@ target(struct sk_buff **pskb, | |||
30 | const void *targinfo, | 31 | const void *targinfo, |
31 | void *userinfo) | 32 | void *userinfo) |
32 | { | 33 | { |
33 | const struct ipt_classify_target_info *clinfo = targinfo; | 34 | const struct xt_classify_target_info *clinfo = targinfo; |
34 | 35 | ||
35 | if((*pskb)->priority != clinfo->priority) | 36 | if ((*pskb)->priority != clinfo->priority) |
36 | (*pskb)->priority = clinfo->priority; | 37 | (*pskb)->priority = clinfo->priority; |
37 | 38 | ||
38 | return IPT_CONTINUE; | 39 | return XT_CONTINUE; |
39 | } | 40 | } |
40 | 41 | ||
41 | static int | 42 | static int |
42 | checkentry(const char *tablename, | 43 | checkentry(const char *tablename, |
43 | const struct ipt_entry *e, | 44 | const void *e, |
44 | void *targinfo, | 45 | void *targinfo, |
45 | unsigned int targinfosize, | 46 | unsigned int targinfosize, |
46 | unsigned int hook_mask) | 47 | unsigned int hook_mask) |
47 | { | 48 | { |
48 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_classify_target_info))){ | 49 | if (targinfosize != XT_ALIGN(sizeof(struct xt_classify_target_info))){ |
49 | printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n", | 50 | printk(KERN_ERR "CLASSIFY: invalid size (%u != %Zu).\n", |
50 | targinfosize, | 51 | targinfosize, |
51 | IPT_ALIGN(sizeof(struct ipt_classify_target_info))); | 52 | XT_ALIGN(sizeof(struct xt_classify_target_info))); |
52 | return 0; | 53 | return 0; |
53 | } | 54 | } |
54 | 55 | ||
@@ -69,21 +70,39 @@ checkentry(const char *tablename, | |||
69 | return 1; | 70 | return 1; |
70 | } | 71 | } |
71 | 72 | ||
72 | static struct ipt_target ipt_classify_reg = { | 73 | static struct xt_target classify_reg = { |
74 | .name = "CLASSIFY", | ||
75 | .target = target, | ||
76 | .checkentry = checkentry, | ||
77 | .me = THIS_MODULE, | ||
78 | }; | ||
79 | static struct xt_target classify6_reg = { | ||
73 | .name = "CLASSIFY", | 80 | .name = "CLASSIFY", |
74 | .target = target, | 81 | .target = target, |
75 | .checkentry = checkentry, | 82 | .checkentry = checkentry, |
76 | .me = THIS_MODULE, | 83 | .me = THIS_MODULE, |
77 | }; | 84 | }; |
78 | 85 | ||
86 | |||
79 | static int __init init(void) | 87 | static int __init init(void) |
80 | { | 88 | { |
81 | return ipt_register_target(&ipt_classify_reg); | 89 | int ret; |
90 | |||
91 | ret = xt_register_target(AF_INET, &classify_reg); | ||
92 | if (ret) | ||
93 | return ret; | ||
94 | |||
95 | ret = xt_register_target(AF_INET6, &classify6_reg); | ||
96 | if (ret) | ||
97 | xt_unregister_target(AF_INET, &classify_reg); | ||
98 | |||
99 | return ret; | ||
82 | } | 100 | } |
83 | 101 | ||
84 | static void __exit fini(void) | 102 | static void __exit fini(void) |
85 | { | 103 | { |
86 | ipt_unregister_target(&ipt_classify_reg); | 104 | xt_unregister_target(AF_INET, &classify_reg); |
105 | xt_unregister_target(AF_INET6, &classify6_reg); | ||
87 | } | 106 | } |
88 | 107 | ||
89 | module_init(init); | 108 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_CONNMARK.c b/net/netfilter/xt_CONNMARK.c index 8acac5a40a92..22506e376be5 100644 --- a/net/ipv4/netfilter/ipt_CONNMARK.c +++ b/net/netfilter/xt_CONNMARK.c | |||
@@ -26,9 +26,10 @@ | |||
26 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); | 26 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); |
27 | MODULE_DESCRIPTION("IP tables CONNMARK matching module"); | 27 | MODULE_DESCRIPTION("IP tables CONNMARK matching module"); |
28 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
29 | MODULE_ALIAS("ipt_CONNMARK"); | ||
29 | 30 | ||
30 | #include <linux/netfilter_ipv4/ip_tables.h> | 31 | #include <linux/netfilter/x_tables.h> |
31 | #include <linux/netfilter_ipv4/ipt_CONNMARK.h> | 32 | #include <linux/netfilter/xt_CONNMARK.h> |
32 | #include <net/netfilter/nf_conntrack_compat.h> | 33 | #include <net/netfilter/nf_conntrack_compat.h> |
33 | 34 | ||
34 | static unsigned int | 35 | static unsigned int |
@@ -39,7 +40,7 @@ target(struct sk_buff **pskb, | |||
39 | const void *targinfo, | 40 | const void *targinfo, |
40 | void *userinfo) | 41 | void *userinfo) |
41 | { | 42 | { |
42 | const struct ipt_connmark_target_info *markinfo = targinfo; | 43 | const struct xt_connmark_target_info *markinfo = targinfo; |
43 | u_int32_t diff; | 44 | u_int32_t diff; |
44 | u_int32_t nfmark; | 45 | u_int32_t nfmark; |
45 | u_int32_t newmark; | 46 | u_int32_t newmark; |
@@ -48,17 +49,17 @@ target(struct sk_buff **pskb, | |||
48 | 49 | ||
49 | if (ctmark) { | 50 | if (ctmark) { |
50 | switch(markinfo->mode) { | 51 | switch(markinfo->mode) { |
51 | case IPT_CONNMARK_SET: | 52 | case XT_CONNMARK_SET: |
52 | newmark = (*ctmark & ~markinfo->mask) | markinfo->mark; | 53 | newmark = (*ctmark & ~markinfo->mask) | markinfo->mark; |
53 | if (newmark != *ctmark) | 54 | if (newmark != *ctmark) |
54 | *ctmark = newmark; | 55 | *ctmark = newmark; |
55 | break; | 56 | break; |
56 | case IPT_CONNMARK_SAVE: | 57 | case XT_CONNMARK_SAVE: |
57 | newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); | 58 | newmark = (*ctmark & ~markinfo->mask) | ((*pskb)->nfmark & markinfo->mask); |
58 | if (*ctmark != newmark) | 59 | if (*ctmark != newmark) |
59 | *ctmark = newmark; | 60 | *ctmark = newmark; |
60 | break; | 61 | break; |
61 | case IPT_CONNMARK_RESTORE: | 62 | case XT_CONNMARK_RESTORE: |
62 | nfmark = (*pskb)->nfmark; | 63 | nfmark = (*pskb)->nfmark; |
63 | diff = (*ctmark ^ nfmark) & markinfo->mask; | 64 | diff = (*ctmark ^ nfmark) & markinfo->mask; |
64 | if (diff != 0) | 65 | if (diff != 0) |
@@ -67,25 +68,25 @@ target(struct sk_buff **pskb, | |||
67 | } | 68 | } |
68 | } | 69 | } |
69 | 70 | ||
70 | return IPT_CONTINUE; | 71 | return XT_CONTINUE; |
71 | } | 72 | } |
72 | 73 | ||
73 | static int | 74 | static int |
74 | checkentry(const char *tablename, | 75 | checkentry(const char *tablename, |
75 | const struct ipt_entry *e, | 76 | const void *entry, |
76 | void *targinfo, | 77 | void *targinfo, |
77 | unsigned int targinfosize, | 78 | unsigned int targinfosize, |
78 | unsigned int hook_mask) | 79 | unsigned int hook_mask) |
79 | { | 80 | { |
80 | struct ipt_connmark_target_info *matchinfo = targinfo; | 81 | struct xt_connmark_target_info *matchinfo = targinfo; |
81 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) { | 82 | if (targinfosize != XT_ALIGN(sizeof(struct xt_connmark_target_info))) { |
82 | printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n", | 83 | printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n", |
83 | targinfosize, | 84 | targinfosize, |
84 | IPT_ALIGN(sizeof(struct ipt_connmark_target_info))); | 85 | XT_ALIGN(sizeof(struct xt_connmark_target_info))); |
85 | return 0; | 86 | return 0; |
86 | } | 87 | } |
87 | 88 | ||
88 | if (matchinfo->mode == IPT_CONNMARK_RESTORE) { | 89 | if (matchinfo->mode == XT_CONNMARK_RESTORE) { |
89 | if (strcmp(tablename, "mangle") != 0) { | 90 | if (strcmp(tablename, "mangle") != 0) { |
90 | printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename); | 91 | printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename); |
91 | return 0; | 92 | return 0; |
@@ -100,7 +101,13 @@ checkentry(const char *tablename, | |||
100 | return 1; | 101 | return 1; |
101 | } | 102 | } |
102 | 103 | ||
103 | static struct ipt_target ipt_connmark_reg = { | 104 | static struct xt_target connmark_reg = { |
105 | .name = "CONNMARK", | ||
106 | .target = &target, | ||
107 | .checkentry = &checkentry, | ||
108 | .me = THIS_MODULE | ||
109 | }; | ||
110 | static struct xt_target connmark6_reg = { | ||
104 | .name = "CONNMARK", | 111 | .name = "CONNMARK", |
105 | .target = &target, | 112 | .target = &target, |
106 | .checkentry = &checkentry, | 113 | .checkentry = &checkentry, |
@@ -109,13 +116,25 @@ static struct ipt_target ipt_connmark_reg = { | |||
109 | 116 | ||
110 | static int __init init(void) | 117 | static int __init init(void) |
111 | { | 118 | { |
112 | need_ip_conntrack(); | 119 | int ret; |
113 | return ipt_register_target(&ipt_connmark_reg); | 120 | |
121 | need_conntrack(); | ||
122 | |||
123 | ret = xt_register_target(AF_INET, &connmark_reg); | ||
124 | if (ret) | ||
125 | return ret; | ||
126 | |||
127 | ret = xt_register_target(AF_INET6, &connmark6_reg); | ||
128 | if (ret) | ||
129 | xt_unregister_target(AF_INET, &connmark_reg); | ||
130 | |||
131 | return ret; | ||
114 | } | 132 | } |
115 | 133 | ||
116 | static void __exit fini(void) | 134 | static void __exit fini(void) |
117 | { | 135 | { |
118 | ipt_unregister_target(&ipt_connmark_reg); | 136 | xt_unregister_target(AF_INET, &connmark_reg); |
137 | xt_unregister_target(AF_INET6, &connmark6_reg); | ||
119 | } | 138 | } |
120 | 139 | ||
121 | module_init(init); | 140 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_MARK.c b/net/netfilter/xt_MARK.c index 52b4f2c296bf..0c11ee9550f3 100644 --- a/net/ipv4/netfilter/ipt_MARK.c +++ b/net/netfilter/xt_MARK.c | |||
@@ -12,12 +12,14 @@ | |||
12 | #include <linux/ip.h> | 12 | #include <linux/ip.h> |
13 | #include <net/checksum.h> | 13 | #include <net/checksum.h> |
14 | 14 | ||
15 | #include <linux/netfilter_ipv4/ip_tables.h> | 15 | #include <linux/netfilter/x_tables.h> |
16 | #include <linux/netfilter_ipv4/ipt_MARK.h> | 16 | #include <linux/netfilter/xt_MARK.h> |
17 | 17 | ||
18 | MODULE_LICENSE("GPL"); | 18 | MODULE_LICENSE("GPL"); |
19 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | 19 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); |
20 | MODULE_DESCRIPTION("iptables MARK modification module"); | 20 | MODULE_DESCRIPTION("ip[6]tables MARK modification module"); |
21 | MODULE_ALIAS("ipt_MARK"); | ||
22 | MODULE_ALIAS("ip6t_MARK"); | ||
21 | 23 | ||
22 | static unsigned int | 24 | static unsigned int |
23 | target_v0(struct sk_buff **pskb, | 25 | target_v0(struct sk_buff **pskb, |
@@ -27,12 +29,12 @@ target_v0(struct sk_buff **pskb, | |||
27 | const void *targinfo, | 29 | const void *targinfo, |
28 | void *userinfo) | 30 | void *userinfo) |
29 | { | 31 | { |
30 | const struct ipt_mark_target_info *markinfo = targinfo; | 32 | const struct xt_mark_target_info *markinfo = targinfo; |
31 | 33 | ||
32 | if((*pskb)->nfmark != markinfo->mark) | 34 | if((*pskb)->nfmark != markinfo->mark) |
33 | (*pskb)->nfmark = markinfo->mark; | 35 | (*pskb)->nfmark = markinfo->mark; |
34 | 36 | ||
35 | return IPT_CONTINUE; | 37 | return XT_CONTINUE; |
36 | } | 38 | } |
37 | 39 | ||
38 | static unsigned int | 40 | static unsigned int |
@@ -43,19 +45,19 @@ target_v1(struct sk_buff **pskb, | |||
43 | const void *targinfo, | 45 | const void *targinfo, |
44 | void *userinfo) | 46 | void *userinfo) |
45 | { | 47 | { |
46 | const struct ipt_mark_target_info_v1 *markinfo = targinfo; | 48 | const struct xt_mark_target_info_v1 *markinfo = targinfo; |
47 | int mark = 0; | 49 | int mark = 0; |
48 | 50 | ||
49 | switch (markinfo->mode) { | 51 | switch (markinfo->mode) { |
50 | case IPT_MARK_SET: | 52 | case XT_MARK_SET: |
51 | mark = markinfo->mark; | 53 | mark = markinfo->mark; |
52 | break; | 54 | break; |
53 | 55 | ||
54 | case IPT_MARK_AND: | 56 | case XT_MARK_AND: |
55 | mark = (*pskb)->nfmark & markinfo->mark; | 57 | mark = (*pskb)->nfmark & markinfo->mark; |
56 | break; | 58 | break; |
57 | 59 | ||
58 | case IPT_MARK_OR: | 60 | case XT_MARK_OR: |
59 | mark = (*pskb)->nfmark | markinfo->mark; | 61 | mark = (*pskb)->nfmark | markinfo->mark; |
60 | break; | 62 | break; |
61 | } | 63 | } |
@@ -63,23 +65,23 @@ target_v1(struct sk_buff **pskb, | |||
63 | if((*pskb)->nfmark != mark) | 65 | if((*pskb)->nfmark != mark) |
64 | (*pskb)->nfmark = mark; | 66 | (*pskb)->nfmark = mark; |
65 | 67 | ||
66 | return IPT_CONTINUE; | 68 | return XT_CONTINUE; |
67 | } | 69 | } |
68 | 70 | ||
69 | 71 | ||
70 | static int | 72 | static int |
71 | checkentry_v0(const char *tablename, | 73 | checkentry_v0(const char *tablename, |
72 | const struct ipt_entry *e, | 74 | const void *entry, |
73 | void *targinfo, | 75 | void *targinfo, |
74 | unsigned int targinfosize, | 76 | unsigned int targinfosize, |
75 | unsigned int hook_mask) | 77 | unsigned int hook_mask) |
76 | { | 78 | { |
77 | struct ipt_mark_target_info *markinfo = targinfo; | 79 | struct xt_mark_target_info *markinfo = targinfo; |
78 | 80 | ||
79 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) { | 81 | if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info))) { |
80 | printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", | 82 | printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", |
81 | targinfosize, | 83 | targinfosize, |
82 | IPT_ALIGN(sizeof(struct ipt_mark_target_info))); | 84 | XT_ALIGN(sizeof(struct xt_mark_target_info))); |
83 | return 0; | 85 | return 0; |
84 | } | 86 | } |
85 | 87 | ||
@@ -98,17 +100,17 @@ checkentry_v0(const char *tablename, | |||
98 | 100 | ||
99 | static int | 101 | static int |
100 | checkentry_v1(const char *tablename, | 102 | checkentry_v1(const char *tablename, |
101 | const struct ipt_entry *e, | 103 | const void *entry, |
102 | void *targinfo, | 104 | void *targinfo, |
103 | unsigned int targinfosize, | 105 | unsigned int targinfosize, |
104 | unsigned int hook_mask) | 106 | unsigned int hook_mask) |
105 | { | 107 | { |
106 | struct ipt_mark_target_info_v1 *markinfo = targinfo; | 108 | struct xt_mark_target_info_v1 *markinfo = targinfo; |
107 | 109 | ||
108 | if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))){ | 110 | if (targinfosize != XT_ALIGN(sizeof(struct xt_mark_target_info_v1))){ |
109 | printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", | 111 | printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n", |
110 | targinfosize, | 112 | targinfosize, |
111 | IPT_ALIGN(sizeof(struct ipt_mark_target_info_v1))); | 113 | XT_ALIGN(sizeof(struct xt_mark_target_info_v1))); |
112 | return 0; | 114 | return 0; |
113 | } | 115 | } |
114 | 116 | ||
@@ -117,9 +119,9 @@ checkentry_v1(const char *tablename, | |||
117 | return 0; | 119 | return 0; |
118 | } | 120 | } |
119 | 121 | ||
120 | if (markinfo->mode != IPT_MARK_SET | 122 | if (markinfo->mode != XT_MARK_SET |
121 | && markinfo->mode != IPT_MARK_AND | 123 | && markinfo->mode != XT_MARK_AND |
122 | && markinfo->mode != IPT_MARK_OR) { | 124 | && markinfo->mode != XT_MARK_OR) { |
123 | printk(KERN_WARNING "MARK: unknown mode %u\n", | 125 | printk(KERN_WARNING "MARK: unknown mode %u\n", |
124 | markinfo->mode); | 126 | markinfo->mode); |
125 | return 0; | 127 | return 0; |
@@ -133,7 +135,7 @@ checkentry_v1(const char *tablename, | |||
133 | return 1; | 135 | return 1; |
134 | } | 136 | } |
135 | 137 | ||
136 | static struct ipt_target ipt_mark_reg_v0 = { | 138 | static struct xt_target ipt_mark_reg_v0 = { |
137 | .name = "MARK", | 139 | .name = "MARK", |
138 | .target = target_v0, | 140 | .target = target_v0, |
139 | .checkentry = checkentry_v0, | 141 | .checkentry = checkentry_v0, |
@@ -141,7 +143,7 @@ static struct ipt_target ipt_mark_reg_v0 = { | |||
141 | .revision = 0, | 143 | .revision = 0, |
142 | }; | 144 | }; |
143 | 145 | ||
144 | static struct ipt_target ipt_mark_reg_v1 = { | 146 | static struct xt_target ipt_mark_reg_v1 = { |
145 | .name = "MARK", | 147 | .name = "MARK", |
146 | .target = target_v1, | 148 | .target = target_v1, |
147 | .checkentry = checkentry_v1, | 149 | .checkentry = checkentry_v1, |
@@ -149,23 +151,40 @@ static struct ipt_target ipt_mark_reg_v1 = { | |||
149 | .revision = 1, | 151 | .revision = 1, |
150 | }; | 152 | }; |
151 | 153 | ||
154 | static struct xt_target ip6t_mark_reg_v0 = { | ||
155 | .name = "MARK", | ||
156 | .target = target_v0, | ||
157 | .checkentry = checkentry_v0, | ||
158 | .me = THIS_MODULE, | ||
159 | .revision = 0, | ||
160 | }; | ||
161 | |||
152 | static int __init init(void) | 162 | static int __init init(void) |
153 | { | 163 | { |
154 | int err; | 164 | int err; |
155 | 165 | ||
156 | err = ipt_register_target(&ipt_mark_reg_v0); | 166 | err = xt_register_target(AF_INET, &ipt_mark_reg_v0); |
157 | if (!err) { | 167 | if (err) |
158 | err = ipt_register_target(&ipt_mark_reg_v1); | 168 | return err; |
159 | if (err) | 169 | |
160 | ipt_unregister_target(&ipt_mark_reg_v0); | 170 | err = xt_register_target(AF_INET, &ipt_mark_reg_v1); |
171 | if (err) | ||
172 | xt_unregister_target(AF_INET, &ipt_mark_reg_v0); | ||
173 | |||
174 | err = xt_register_target(AF_INET6, &ip6t_mark_reg_v0); | ||
175 | if (err) { | ||
176 | xt_unregister_target(AF_INET, &ipt_mark_reg_v0); | ||
177 | xt_unregister_target(AF_INET, &ipt_mark_reg_v1); | ||
161 | } | 178 | } |
179 | |||
162 | return err; | 180 | return err; |
163 | } | 181 | } |
164 | 182 | ||
165 | static void __exit fini(void) | 183 | static void __exit fini(void) |
166 | { | 184 | { |
167 | ipt_unregister_target(&ipt_mark_reg_v0); | 185 | xt_unregister_target(AF_INET, &ipt_mark_reg_v0); |
168 | ipt_unregister_target(&ipt_mark_reg_v1); | 186 | xt_unregister_target(AF_INET, &ipt_mark_reg_v1); |
187 | xt_unregister_target(AF_INET6, &ip6t_mark_reg_v0); | ||
169 | } | 188 | } |
170 | 189 | ||
171 | module_init(init); | 190 | module_init(init); |
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c new file mode 100644 index 000000000000..8b76b6f8d1e4 --- /dev/null +++ b/net/netfilter/xt_NFQUEUE.c | |||
@@ -0,0 +1,107 @@ | |||
1 | /* iptables module for using new netfilter netlink queue | ||
2 | * | ||
3 | * (C) 2005 by Harald Welte <laforge@netfilter.org> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | |||
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter_arp.h> | ||
16 | #include <linux/netfilter/x_tables.h> | ||
17 | #include <linux/netfilter/xt_NFQUEUE.h> | ||
18 | |||
19 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
20 | MODULE_DESCRIPTION("[ip,ip6,arp]_tables NFQUEUE target"); | ||
21 | MODULE_LICENSE("GPL"); | ||
22 | MODULE_ALIAS("ipt_NFQUEUE"); | ||
23 | MODULE_ALIAS("ip6t_NFQUEUE"); | ||
24 | MODULE_ALIAS("arpt_NFQUEUE"); | ||
25 | |||
26 | static unsigned int | ||
27 | target(struct sk_buff **pskb, | ||
28 | const struct net_device *in, | ||
29 | const struct net_device *out, | ||
30 | unsigned int hooknum, | ||
31 | const void *targinfo, | ||
32 | void *userinfo) | ||
33 | { | ||
34 | const struct xt_NFQ_info *tinfo = targinfo; | ||
35 | |||
36 | return NF_QUEUE_NR(tinfo->queuenum); | ||
37 | } | ||
38 | |||
39 | static int | ||
40 | checkentry(const char *tablename, | ||
41 | const void *entry, | ||
42 | void *targinfo, | ||
43 | unsigned int targinfosize, | ||
44 | unsigned int hook_mask) | ||
45 | { | ||
46 | if (targinfosize != XT_ALIGN(sizeof(struct xt_NFQ_info))) { | ||
47 | printk(KERN_WARNING "NFQUEUE: targinfosize %u != %Zu\n", | ||
48 | targinfosize, | ||
49 | XT_ALIGN(sizeof(struct xt_NFQ_info))); | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | return 1; | ||
54 | } | ||
55 | |||
56 | static struct xt_target ipt_NFQ_reg = { | ||
57 | .name = "NFQUEUE", | ||
58 | .target = target, | ||
59 | .checkentry = checkentry, | ||
60 | .me = THIS_MODULE, | ||
61 | }; | ||
62 | |||
63 | static struct xt_target ip6t_NFQ_reg = { | ||
64 | .name = "NFQUEUE", | ||
65 | .target = target, | ||
66 | .checkentry = checkentry, | ||
67 | .me = THIS_MODULE, | ||
68 | }; | ||
69 | |||
70 | static struct xt_target arpt_NFQ_reg = { | ||
71 | .name = "NFQUEUE", | ||
72 | .target = target, | ||
73 | .checkentry = checkentry, | ||
74 | .me = THIS_MODULE, | ||
75 | }; | ||
76 | |||
77 | static int __init init(void) | ||
78 | { | ||
79 | int ret; | ||
80 | ret = xt_register_target(AF_INET, &ipt_NFQ_reg); | ||
81 | if (ret) | ||
82 | return ret; | ||
83 | ret = xt_register_target(AF_INET6, &ip6t_NFQ_reg); | ||
84 | if (ret) | ||
85 | goto out_ip; | ||
86 | ret = xt_register_target(NF_ARP, &arpt_NFQ_reg); | ||
87 | if (ret) | ||
88 | goto out_ip6; | ||
89 | |||
90 | return ret; | ||
91 | out_ip6: | ||
92 | xt_unregister_target(AF_INET6, &ip6t_NFQ_reg); | ||
93 | out_ip: | ||
94 | xt_unregister_target(AF_INET, &ipt_NFQ_reg); | ||
95 | |||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | static void __exit fini(void) | ||
100 | { | ||
101 | xt_unregister_target(NF_ARP, &arpt_NFQ_reg); | ||
102 | xt_unregister_target(AF_INET6, &ip6t_NFQ_reg); | ||
103 | xt_unregister_target(AF_INET, &ipt_NFQ_reg); | ||
104 | } | ||
105 | |||
106 | module_init(init); | ||
107 | module_exit(fini); | ||
diff --git a/net/ipv4/netfilter/ipt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c index e3c69d072c6e..24d477afa939 100644 --- a/net/ipv4/netfilter/ipt_NOTRACK.c +++ b/net/netfilter/xt_NOTRACK.c | |||
@@ -4,9 +4,12 @@ | |||
4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
5 | #include <linux/skbuff.h> | 5 | #include <linux/skbuff.h> |
6 | 6 | ||
7 | #include <linux/netfilter_ipv4/ip_tables.h> | 7 | #include <linux/netfilter/x_tables.h> |
8 | #include <net/netfilter/nf_conntrack_compat.h> | 8 | #include <net/netfilter/nf_conntrack_compat.h> |
9 | 9 | ||
10 | MODULE_LICENSE("GPL"); | ||
11 | MODULE_ALIAS("ipt_NOTRACK"); | ||
12 | |||
10 | static unsigned int | 13 | static unsigned int |
11 | target(struct sk_buff **pskb, | 14 | target(struct sk_buff **pskb, |
12 | const struct net_device *in, | 15 | const struct net_device *in, |
@@ -17,7 +20,7 @@ target(struct sk_buff **pskb, | |||
17 | { | 20 | { |
18 | /* Previously seen (loopback)? Ignore. */ | 21 | /* Previously seen (loopback)? Ignore. */ |
19 | if ((*pskb)->nfct != NULL) | 22 | if ((*pskb)->nfct != NULL) |
20 | return IPT_CONTINUE; | 23 | return XT_CONTINUE; |
21 | 24 | ||
22 | /* Attach fake conntrack entry. | 25 | /* Attach fake conntrack entry. |
23 | If there is a real ct entry correspondig to this packet, | 26 | If there is a real ct entry correspondig to this packet, |
@@ -27,12 +30,12 @@ target(struct sk_buff **pskb, | |||
27 | (*pskb)->nfctinfo = IP_CT_NEW; | 30 | (*pskb)->nfctinfo = IP_CT_NEW; |
28 | nf_conntrack_get((*pskb)->nfct); | 31 | nf_conntrack_get((*pskb)->nfct); |
29 | 32 | ||
30 | return IPT_CONTINUE; | 33 | return XT_CONTINUE; |
31 | } | 34 | } |
32 | 35 | ||
33 | static int | 36 | static int |
34 | checkentry(const char *tablename, | 37 | checkentry(const char *tablename, |
35 | const struct ipt_entry *e, | 38 | const void *entry, |
36 | void *targinfo, | 39 | void *targinfo, |
37 | unsigned int targinfosize, | 40 | unsigned int targinfosize, |
38 | unsigned int hook_mask) | 41 | unsigned int hook_mask) |
@@ -51,26 +54,39 @@ checkentry(const char *tablename, | |||
51 | return 1; | 54 | return 1; |
52 | } | 55 | } |
53 | 56 | ||
54 | static struct ipt_target ipt_notrack_reg = { | 57 | static struct xt_target notrack_reg = { |
55 | .name = "NOTRACK", | 58 | .name = "NOTRACK", |
56 | .target = target, | 59 | .target = target, |
57 | .checkentry = checkentry, | 60 | .checkentry = checkentry, |
58 | .me = THIS_MODULE | 61 | .me = THIS_MODULE, |
62 | }; | ||
63 | static struct xt_target notrack6_reg = { | ||
64 | .name = "NOTRACK", | ||
65 | .target = target, | ||
66 | .checkentry = checkentry, | ||
67 | .me = THIS_MODULE, | ||
59 | }; | 68 | }; |
60 | 69 | ||
61 | static int __init init(void) | 70 | static int __init init(void) |
62 | { | 71 | { |
63 | if (ipt_register_target(&ipt_notrack_reg)) | 72 | int ret; |
64 | return -EINVAL; | 73 | |
74 | ret = xt_register_target(AF_INET, ¬rack_reg); | ||
75 | if (ret) | ||
76 | return ret; | ||
65 | 77 | ||
66 | return 0; | 78 | ret = xt_register_target(AF_INET6, ¬rack6_reg); |
79 | if (ret) | ||
80 | xt_unregister_target(AF_INET, ¬rack_reg); | ||
81 | |||
82 | return ret; | ||
67 | } | 83 | } |
68 | 84 | ||
69 | static void __exit fini(void) | 85 | static void __exit fini(void) |
70 | { | 86 | { |
71 | ipt_unregister_target(&ipt_notrack_reg); | 87 | xt_unregister_target(AF_INET6, ¬rack6_reg); |
88 | xt_unregister_target(AF_INET, ¬rack_reg); | ||
72 | } | 89 | } |
73 | 90 | ||
74 | module_init(init); | 91 | module_init(init); |
75 | module_exit(fini); | 92 | module_exit(fini); |
76 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv4/netfilter/ipt_comment.c b/net/netfilter/xt_comment.c index 6b76a1ea5245..4ba6fd65c6e9 100644 --- a/net/ipv4/netfilter/ipt_comment.c +++ b/net/netfilter/xt_comment.c | |||
@@ -6,12 +6,14 @@ | |||
6 | 6 | ||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/skbuff.h> | 8 | #include <linux/skbuff.h> |
9 | #include <linux/netfilter_ipv4/ip_tables.h> | 9 | #include <linux/netfilter/x_tables.h> |
10 | #include <linux/netfilter_ipv4/ipt_comment.h> | 10 | #include <linux/netfilter/xt_comment.h> |
11 | 11 | ||
12 | MODULE_AUTHOR("Brad Fisher <brad@info-link.net>"); | 12 | MODULE_AUTHOR("Brad Fisher <brad@info-link.net>"); |
13 | MODULE_DESCRIPTION("iptables comment match module"); | 13 | MODULE_DESCRIPTION("iptables comment match module"); |
14 | MODULE_LICENSE("GPL"); | 14 | MODULE_LICENSE("GPL"); |
15 | MODULE_ALIAS("ipt_comment"); | ||
16 | MODULE_ALIAS("ip6t_comment"); | ||
15 | 17 | ||
16 | static int | 18 | static int |
17 | match(const struct sk_buff *skb, | 19 | match(const struct sk_buff *skb, |
@@ -19,6 +21,7 @@ match(const struct sk_buff *skb, | |||
19 | const struct net_device *out, | 21 | const struct net_device *out, |
20 | const void *matchinfo, | 22 | const void *matchinfo, |
21 | int offset, | 23 | int offset, |
24 | unsigned int protooff, | ||
22 | int *hotdrop) | 25 | int *hotdrop) |
23 | { | 26 | { |
24 | /* We always match */ | 27 | /* We always match */ |
@@ -27,18 +30,25 @@ match(const struct sk_buff *skb, | |||
27 | 30 | ||
28 | static int | 31 | static int |
29 | checkentry(const char *tablename, | 32 | checkentry(const char *tablename, |
30 | const struct ipt_ip *ip, | 33 | const void *ip, |
31 | void *matchinfo, | 34 | void *matchinfo, |
32 | unsigned int matchsize, | 35 | unsigned int matchsize, |
33 | unsigned int hook_mask) | 36 | unsigned int hook_mask) |
34 | { | 37 | { |
35 | /* Check the size */ | 38 | /* Check the size */ |
36 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_comment_info))) | 39 | if (matchsize != XT_ALIGN(sizeof(struct xt_comment_info))) |
37 | return 0; | 40 | return 0; |
38 | return 1; | 41 | return 1; |
39 | } | 42 | } |
40 | 43 | ||
41 | static struct ipt_match comment_match = { | 44 | static struct xt_match comment_match = { |
45 | .name = "comment", | ||
46 | .match = match, | ||
47 | .checkentry = checkentry, | ||
48 | .me = THIS_MODULE | ||
49 | }; | ||
50 | |||
51 | static struct xt_match comment6_match = { | ||
42 | .name = "comment", | 52 | .name = "comment", |
43 | .match = match, | 53 | .match = match, |
44 | .checkentry = checkentry, | 54 | .checkentry = checkentry, |
@@ -47,12 +57,23 @@ static struct ipt_match comment_match = { | |||
47 | 57 | ||
48 | static int __init init(void) | 58 | static int __init init(void) |
49 | { | 59 | { |
50 | return ipt_register_match(&comment_match); | 60 | int ret; |
61 | |||
62 | ret = xt_register_match(AF_INET, &comment_match); | ||
63 | if (ret) | ||
64 | return ret; | ||
65 | |||
66 | ret = xt_register_match(AF_INET6, &comment6_match); | ||
67 | if (ret) | ||
68 | xt_unregister_match(AF_INET, &comment_match); | ||
69 | |||
70 | return ret; | ||
51 | } | 71 | } |
52 | 72 | ||
53 | static void __exit fini(void) | 73 | static void __exit fini(void) |
54 | { | 74 | { |
55 | ipt_unregister_match(&comment_match); | 75 | xt_unregister_match(AF_INET, &comment_match); |
76 | xt_unregister_match(AF_INET6, &comment6_match); | ||
56 | } | 77 | } |
57 | 78 | ||
58 | module_init(init); | 79 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_connbytes.c b/net/netfilter/xt_connbytes.c index d68a048b7176..150d2a4b0f71 100644 --- a/net/ipv4/netfilter/ipt_connbytes.c +++ b/net/netfilter/xt_connbytes.c | |||
@@ -6,13 +6,15 @@ | |||
6 | * - add functionality to match number of packets | 6 | * - add functionality to match number of packets |
7 | * - add functionality to match average packet size | 7 | * - add functionality to match average packet size |
8 | * - add support to match directions seperately | 8 | * - add support to match directions seperately |
9 | * 2005-10-16 Harald Welte <laforge@netfilter.org> | ||
10 | * - Port to x_tables | ||
9 | * | 11 | * |
10 | */ | 12 | */ |
11 | #include <linux/module.h> | 13 | #include <linux/module.h> |
12 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
13 | #include <net/netfilter/nf_conntrack_compat.h> | 15 | #include <net/netfilter/nf_conntrack_compat.h> |
14 | #include <linux/netfilter_ipv4/ip_tables.h> | 16 | #include <linux/netfilter/x_tables.h> |
15 | #include <linux/netfilter_ipv4/ipt_connbytes.h> | 17 | #include <linux/netfilter/xt_connbytes.h> |
16 | 18 | ||
17 | #include <asm/div64.h> | 19 | #include <asm/div64.h> |
18 | #include <asm/bitops.h> | 20 | #include <asm/bitops.h> |
@@ -20,6 +22,7 @@ | |||
20 | MODULE_LICENSE("GPL"); | 22 | MODULE_LICENSE("GPL"); |
21 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | 23 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); |
22 | MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection"); | 24 | MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection"); |
25 | MODULE_ALIAS("ipt_connbytes"); | ||
23 | 26 | ||
24 | /* 64bit divisor, dividend and result. dynamic precision */ | 27 | /* 64bit divisor, dividend and result. dynamic precision */ |
25 | static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor) | 28 | static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor) |
@@ -43,9 +46,10 @@ match(const struct sk_buff *skb, | |||
43 | const struct net_device *out, | 46 | const struct net_device *out, |
44 | const void *matchinfo, | 47 | const void *matchinfo, |
45 | int offset, | 48 | int offset, |
49 | unsigned int protoff, | ||
46 | int *hotdrop) | 50 | int *hotdrop) |
47 | { | 51 | { |
48 | const struct ipt_connbytes_info *sinfo = matchinfo; | 52 | const struct xt_connbytes_info *sinfo = matchinfo; |
49 | u_int64_t what = 0; /* initialize to make gcc happy */ | 53 | u_int64_t what = 0; /* initialize to make gcc happy */ |
50 | const struct ip_conntrack_counter *counters; | 54 | const struct ip_conntrack_counter *counters; |
51 | 55 | ||
@@ -53,45 +57,45 @@ match(const struct sk_buff *skb, | |||
53 | return 0; /* no match */ | 57 | return 0; /* no match */ |
54 | 58 | ||
55 | switch (sinfo->what) { | 59 | switch (sinfo->what) { |
56 | case IPT_CONNBYTES_PKTS: | 60 | case XT_CONNBYTES_PKTS: |
57 | switch (sinfo->direction) { | 61 | switch (sinfo->direction) { |
58 | case IPT_CONNBYTES_DIR_ORIGINAL: | 62 | case XT_CONNBYTES_DIR_ORIGINAL: |
59 | what = counters[IP_CT_DIR_ORIGINAL].packets; | 63 | what = counters[IP_CT_DIR_ORIGINAL].packets; |
60 | break; | 64 | break; |
61 | case IPT_CONNBYTES_DIR_REPLY: | 65 | case XT_CONNBYTES_DIR_REPLY: |
62 | what = counters[IP_CT_DIR_REPLY].packets; | 66 | what = counters[IP_CT_DIR_REPLY].packets; |
63 | break; | 67 | break; |
64 | case IPT_CONNBYTES_DIR_BOTH: | 68 | case XT_CONNBYTES_DIR_BOTH: |
65 | what = counters[IP_CT_DIR_ORIGINAL].packets; | 69 | what = counters[IP_CT_DIR_ORIGINAL].packets; |
66 | what += counters[IP_CT_DIR_REPLY].packets; | 70 | what += counters[IP_CT_DIR_REPLY].packets; |
67 | break; | 71 | break; |
68 | } | 72 | } |
69 | break; | 73 | break; |
70 | case IPT_CONNBYTES_BYTES: | 74 | case XT_CONNBYTES_BYTES: |
71 | switch (sinfo->direction) { | 75 | switch (sinfo->direction) { |
72 | case IPT_CONNBYTES_DIR_ORIGINAL: | 76 | case XT_CONNBYTES_DIR_ORIGINAL: |
73 | what = counters[IP_CT_DIR_ORIGINAL].bytes; | 77 | what = counters[IP_CT_DIR_ORIGINAL].bytes; |
74 | break; | 78 | break; |
75 | case IPT_CONNBYTES_DIR_REPLY: | 79 | case XT_CONNBYTES_DIR_REPLY: |
76 | what = counters[IP_CT_DIR_REPLY].bytes; | 80 | what = counters[IP_CT_DIR_REPLY].bytes; |
77 | break; | 81 | break; |
78 | case IPT_CONNBYTES_DIR_BOTH: | 82 | case XT_CONNBYTES_DIR_BOTH: |
79 | what = counters[IP_CT_DIR_ORIGINAL].bytes; | 83 | what = counters[IP_CT_DIR_ORIGINAL].bytes; |
80 | what += counters[IP_CT_DIR_REPLY].bytes; | 84 | what += counters[IP_CT_DIR_REPLY].bytes; |
81 | break; | 85 | break; |
82 | } | 86 | } |
83 | break; | 87 | break; |
84 | case IPT_CONNBYTES_AVGPKT: | 88 | case XT_CONNBYTES_AVGPKT: |
85 | switch (sinfo->direction) { | 89 | switch (sinfo->direction) { |
86 | case IPT_CONNBYTES_DIR_ORIGINAL: | 90 | case XT_CONNBYTES_DIR_ORIGINAL: |
87 | what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes, | 91 | what = div64_64(counters[IP_CT_DIR_ORIGINAL].bytes, |
88 | counters[IP_CT_DIR_ORIGINAL].packets); | 92 | counters[IP_CT_DIR_ORIGINAL].packets); |
89 | break; | 93 | break; |
90 | case IPT_CONNBYTES_DIR_REPLY: | 94 | case XT_CONNBYTES_DIR_REPLY: |
91 | what = div64_64(counters[IP_CT_DIR_REPLY].bytes, | 95 | what = div64_64(counters[IP_CT_DIR_REPLY].bytes, |
92 | counters[IP_CT_DIR_REPLY].packets); | 96 | counters[IP_CT_DIR_REPLY].packets); |
93 | break; | 97 | break; |
94 | case IPT_CONNBYTES_DIR_BOTH: | 98 | case XT_CONNBYTES_DIR_BOTH: |
95 | { | 99 | { |
96 | u_int64_t bytes; | 100 | u_int64_t bytes; |
97 | u_int64_t pkts; | 101 | u_int64_t pkts; |
@@ -117,30 +121,36 @@ match(const struct sk_buff *skb, | |||
117 | } | 121 | } |
118 | 122 | ||
119 | static int check(const char *tablename, | 123 | static int check(const char *tablename, |
120 | const struct ipt_ip *ip, | 124 | const void *ip, |
121 | void *matchinfo, | 125 | void *matchinfo, |
122 | unsigned int matchsize, | 126 | unsigned int matchsize, |
123 | unsigned int hook_mask) | 127 | unsigned int hook_mask) |
124 | { | 128 | { |
125 | const struct ipt_connbytes_info *sinfo = matchinfo; | 129 | const struct xt_connbytes_info *sinfo = matchinfo; |
126 | 130 | ||
127 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_connbytes_info))) | 131 | if (matchsize != XT_ALIGN(sizeof(struct xt_connbytes_info))) |
128 | return 0; | 132 | return 0; |
129 | 133 | ||
130 | if (sinfo->what != IPT_CONNBYTES_PKTS && | 134 | if (sinfo->what != XT_CONNBYTES_PKTS && |
131 | sinfo->what != IPT_CONNBYTES_BYTES && | 135 | sinfo->what != XT_CONNBYTES_BYTES && |
132 | sinfo->what != IPT_CONNBYTES_AVGPKT) | 136 | sinfo->what != XT_CONNBYTES_AVGPKT) |
133 | return 0; | 137 | return 0; |
134 | 138 | ||
135 | if (sinfo->direction != IPT_CONNBYTES_DIR_ORIGINAL && | 139 | if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL && |
136 | sinfo->direction != IPT_CONNBYTES_DIR_REPLY && | 140 | sinfo->direction != XT_CONNBYTES_DIR_REPLY && |
137 | sinfo->direction != IPT_CONNBYTES_DIR_BOTH) | 141 | sinfo->direction != XT_CONNBYTES_DIR_BOTH) |
138 | return 0; | 142 | return 0; |
139 | 143 | ||
140 | return 1; | 144 | return 1; |
141 | } | 145 | } |
142 | 146 | ||
143 | static struct ipt_match state_match = { | 147 | static struct xt_match connbytes_match = { |
148 | .name = "connbytes", | ||
149 | .match = &match, | ||
150 | .checkentry = &check, | ||
151 | .me = THIS_MODULE | ||
152 | }; | ||
153 | static struct xt_match connbytes6_match = { | ||
144 | .name = "connbytes", | 154 | .name = "connbytes", |
145 | .match = &match, | 155 | .match = &match, |
146 | .checkentry = &check, | 156 | .checkentry = &check, |
@@ -149,12 +159,21 @@ static struct ipt_match state_match = { | |||
149 | 159 | ||
150 | static int __init init(void) | 160 | static int __init init(void) |
151 | { | 161 | { |
152 | return ipt_register_match(&state_match); | 162 | int ret; |
163 | ret = xt_register_match(AF_INET, &connbytes_match); | ||
164 | if (ret) | ||
165 | return ret; | ||
166 | |||
167 | ret = xt_register_match(AF_INET6, &connbytes6_match); | ||
168 | if (ret) | ||
169 | xt_unregister_match(AF_INET, &connbytes_match); | ||
170 | return ret; | ||
153 | } | 171 | } |
154 | 172 | ||
155 | static void __exit fini(void) | 173 | static void __exit fini(void) |
156 | { | 174 | { |
157 | ipt_unregister_match(&state_match); | 175 | xt_unregister_match(AF_INET, &connbytes_match); |
176 | xt_unregister_match(AF_INET6, &connbytes6_match); | ||
158 | } | 177 | } |
159 | 178 | ||
160 | module_init(init); | 179 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_connmark.c b/net/netfilter/xt_connmark.c index 5306ef293b92..d06e925032da 100644 --- a/net/ipv4/netfilter/ipt_connmark.c +++ b/net/netfilter/xt_connmark.c | |||
@@ -25,9 +25,10 @@ | |||
25 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); | 25 | MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); |
26 | MODULE_DESCRIPTION("IP tables connmark match module"); | 26 | MODULE_DESCRIPTION("IP tables connmark match module"); |
27 | MODULE_LICENSE("GPL"); | 27 | MODULE_LICENSE("GPL"); |
28 | MODULE_ALIAS("ipt_connmark"); | ||
28 | 29 | ||
29 | #include <linux/netfilter_ipv4/ip_tables.h> | 30 | #include <linux/netfilter/x_tables.h> |
30 | #include <linux/netfilter_ipv4/ipt_connmark.h> | 31 | #include <linux/netfilter/xt_connmark.h> |
31 | #include <net/netfilter/nf_conntrack_compat.h> | 32 | #include <net/netfilter/nf_conntrack_compat.h> |
32 | 33 | ||
33 | static int | 34 | static int |
@@ -36,9 +37,10 @@ match(const struct sk_buff *skb, | |||
36 | const struct net_device *out, | 37 | const struct net_device *out, |
37 | const void *matchinfo, | 38 | const void *matchinfo, |
38 | int offset, | 39 | int offset, |
40 | unsigned int protoff, | ||
39 | int *hotdrop) | 41 | int *hotdrop) |
40 | { | 42 | { |
41 | const struct ipt_connmark_info *info = matchinfo; | 43 | const struct xt_connmark_info *info = matchinfo; |
42 | u_int32_t ctinfo; | 44 | u_int32_t ctinfo; |
43 | const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo); | 45 | const u_int32_t *ctmark = nf_ct_get_mark(skb, &ctinfo); |
44 | if (!ctmark) | 46 | if (!ctmark) |
@@ -49,14 +51,14 @@ match(const struct sk_buff *skb, | |||
49 | 51 | ||
50 | static int | 52 | static int |
51 | checkentry(const char *tablename, | 53 | checkentry(const char *tablename, |
52 | const struct ipt_ip *ip, | 54 | const void *ip, |
53 | void *matchinfo, | 55 | void *matchinfo, |
54 | unsigned int matchsize, | 56 | unsigned int matchsize, |
55 | unsigned int hook_mask) | 57 | unsigned int hook_mask) |
56 | { | 58 | { |
57 | struct ipt_connmark_info *cm = | 59 | struct xt_connmark_info *cm = |
58 | (struct ipt_connmark_info *)matchinfo; | 60 | (struct xt_connmark_info *)matchinfo; |
59 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info))) | 61 | if (matchsize != XT_ALIGN(sizeof(struct xt_connmark_info))) |
60 | return 0; | 62 | return 0; |
61 | 63 | ||
62 | if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { | 64 | if (cm->mark > 0xffffffff || cm->mask > 0xffffffff) { |
@@ -67,21 +69,40 @@ checkentry(const char *tablename, | |||
67 | return 1; | 69 | return 1; |
68 | } | 70 | } |
69 | 71 | ||
70 | static struct ipt_match connmark_match = { | 72 | static struct xt_match connmark_match = { |
73 | .name = "connmark", | ||
74 | .match = &match, | ||
75 | .checkentry = &checkentry, | ||
76 | .me = THIS_MODULE | ||
77 | }; | ||
78 | static struct xt_match connmark6_match = { | ||
71 | .name = "connmark", | 79 | .name = "connmark", |
72 | .match = &match, | 80 | .match = &match, |
73 | .checkentry = &checkentry, | 81 | .checkentry = &checkentry, |
74 | .me = THIS_MODULE | 82 | .me = THIS_MODULE |
75 | }; | 83 | }; |
76 | 84 | ||
85 | |||
77 | static int __init init(void) | 86 | static int __init init(void) |
78 | { | 87 | { |
79 | return ipt_register_match(&connmark_match); | 88 | int ret; |
89 | |||
90 | need_conntrack(); | ||
91 | |||
92 | ret = xt_register_match(AF_INET, &connmark_match); | ||
93 | if (ret) | ||
94 | return ret; | ||
95 | |||
96 | ret = xt_register_match(AF_INET6, &connmark6_match); | ||
97 | if (ret) | ||
98 | xt_unregister_match(AF_INET, &connmark_match); | ||
99 | return ret; | ||
80 | } | 100 | } |
81 | 101 | ||
82 | static void __exit fini(void) | 102 | static void __exit fini(void) |
83 | { | 103 | { |
84 | ipt_unregister_match(&connmark_match); | 104 | xt_unregister_match(AF_INET6, &connmark6_match); |
105 | xt_unregister_match(AF_INET, &connmark_match); | ||
85 | } | 106 | } |
86 | 107 | ||
87 | module_init(init); | 108 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_conntrack.c b/net/netfilter/xt_conntrack.c index c8d18705469b..ffdebc95eb95 100644 --- a/net/ipv4/netfilter/ipt_conntrack.c +++ b/net/netfilter/xt_conntrack.c | |||
@@ -18,12 +18,13 @@ | |||
18 | #include <net/netfilter/nf_conntrack.h> | 18 | #include <net/netfilter/nf_conntrack.h> |
19 | #endif | 19 | #endif |
20 | 20 | ||
21 | #include <linux/netfilter_ipv4/ip_tables.h> | 21 | #include <linux/netfilter/x_tables.h> |
22 | #include <linux/netfilter_ipv4/ipt_conntrack.h> | 22 | #include <linux/netfilter/xt_conntrack.h> |
23 | 23 | ||
24 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
25 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | 25 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); |
26 | MODULE_DESCRIPTION("iptables connection tracking match module"); | 26 | MODULE_DESCRIPTION("iptables connection tracking match module"); |
27 | MODULE_ALIAS("ipt_conntrack"); | ||
27 | 28 | ||
28 | #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) | 29 | #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) |
29 | 30 | ||
@@ -33,9 +34,10 @@ match(const struct sk_buff *skb, | |||
33 | const struct net_device *out, | 34 | const struct net_device *out, |
34 | const void *matchinfo, | 35 | const void *matchinfo, |
35 | int offset, | 36 | int offset, |
37 | unsigned int protoff, | ||
36 | int *hotdrop) | 38 | int *hotdrop) |
37 | { | 39 | { |
38 | const struct ipt_conntrack_info *sinfo = matchinfo; | 40 | const struct xt_conntrack_info *sinfo = matchinfo; |
39 | struct ip_conntrack *ct; | 41 | struct ip_conntrack *ct; |
40 | enum ip_conntrack_info ctinfo; | 42 | enum ip_conntrack_info ctinfo; |
41 | unsigned int statebit; | 43 | unsigned int statebit; |
@@ -45,58 +47,58 @@ match(const struct sk_buff *skb, | |||
45 | #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) | 47 | #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) |
46 | 48 | ||
47 | if (ct == &ip_conntrack_untracked) | 49 | if (ct == &ip_conntrack_untracked) |
48 | statebit = IPT_CONNTRACK_STATE_UNTRACKED; | 50 | statebit = XT_CONNTRACK_STATE_UNTRACKED; |
49 | else if (ct) | 51 | else if (ct) |
50 | statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); | 52 | statebit = XT_CONNTRACK_STATE_BIT(ctinfo); |
51 | else | 53 | else |
52 | statebit = IPT_CONNTRACK_STATE_INVALID; | 54 | statebit = XT_CONNTRACK_STATE_INVALID; |
53 | 55 | ||
54 | if(sinfo->flags & IPT_CONNTRACK_STATE) { | 56 | if(sinfo->flags & XT_CONNTRACK_STATE) { |
55 | if (ct) { | 57 | if (ct) { |
56 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != | 58 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip != |
57 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) | 59 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) |
58 | statebit |= IPT_CONNTRACK_STATE_SNAT; | 60 | statebit |= XT_CONNTRACK_STATE_SNAT; |
59 | 61 | ||
60 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip != | 62 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip != |
61 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip) | 63 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip) |
62 | statebit |= IPT_CONNTRACK_STATE_DNAT; | 64 | statebit |= XT_CONNTRACK_STATE_DNAT; |
63 | } | 65 | } |
64 | 66 | ||
65 | if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) | 67 | if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE)) |
66 | return 0; | 68 | return 0; |
67 | } | 69 | } |
68 | 70 | ||
69 | if(sinfo->flags & IPT_CONNTRACK_PROTO) { | 71 | if(sinfo->flags & XT_CONNTRACK_PROTO) { |
70 | if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) | 72 | if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO)) |
71 | return 0; | 73 | return 0; |
72 | } | 74 | } |
73 | 75 | ||
74 | if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { | 76 | if(sinfo->flags & XT_CONNTRACK_ORIGSRC) { |
75 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) | 77 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC)) |
76 | return 0; | 78 | return 0; |
77 | } | 79 | } |
78 | 80 | ||
79 | if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { | 81 | if(sinfo->flags & XT_CONNTRACK_ORIGDST) { |
80 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) | 82 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST)) |
81 | return 0; | 83 | return 0; |
82 | } | 84 | } |
83 | 85 | ||
84 | if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { | 86 | if(sinfo->flags & XT_CONNTRACK_REPLSRC) { |
85 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) | 87 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC)) |
86 | return 0; | 88 | return 0; |
87 | } | 89 | } |
88 | 90 | ||
89 | if(sinfo->flags & IPT_CONNTRACK_REPLDST) { | 91 | if(sinfo->flags & XT_CONNTRACK_REPLDST) { |
90 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) | 92 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST)) |
91 | return 0; | 93 | return 0; |
92 | } | 94 | } |
93 | 95 | ||
94 | if(sinfo->flags & IPT_CONNTRACK_STATUS) { | 96 | if(sinfo->flags & XT_CONNTRACK_STATUS) { |
95 | if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) | 97 | if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS)) |
96 | return 0; | 98 | return 0; |
97 | } | 99 | } |
98 | 100 | ||
99 | if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { | 101 | if(sinfo->flags & XT_CONNTRACK_EXPIRES) { |
100 | unsigned long expires; | 102 | unsigned long expires; |
101 | 103 | ||
102 | if(!ct) | 104 | if(!ct) |
@@ -104,7 +106,7 @@ match(const struct sk_buff *skb, | |||
104 | 106 | ||
105 | expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; | 107 | expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; |
106 | 108 | ||
107 | if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) | 109 | if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES)) |
108 | return 0; | 110 | return 0; |
109 | } | 111 | } |
110 | 112 | ||
@@ -118,9 +120,10 @@ match(const struct sk_buff *skb, | |||
118 | const struct net_device *out, | 120 | const struct net_device *out, |
119 | const void *matchinfo, | 121 | const void *matchinfo, |
120 | int offset, | 122 | int offset, |
123 | unsigned int protoff, | ||
121 | int *hotdrop) | 124 | int *hotdrop) |
122 | { | 125 | { |
123 | const struct ipt_conntrack_info *sinfo = matchinfo; | 126 | const struct xt_conntrack_info *sinfo = matchinfo; |
124 | struct nf_conn *ct; | 127 | struct nf_conn *ct; |
125 | enum ip_conntrack_info ctinfo; | 128 | enum ip_conntrack_info ctinfo; |
126 | unsigned int statebit; | 129 | unsigned int statebit; |
@@ -130,58 +133,58 @@ match(const struct sk_buff *skb, | |||
130 | #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) | 133 | #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg)) |
131 | 134 | ||
132 | if (ct == &nf_conntrack_untracked) | 135 | if (ct == &nf_conntrack_untracked) |
133 | statebit = IPT_CONNTRACK_STATE_UNTRACKED; | 136 | statebit = XT_CONNTRACK_STATE_UNTRACKED; |
134 | else if (ct) | 137 | else if (ct) |
135 | statebit = IPT_CONNTRACK_STATE_BIT(ctinfo); | 138 | statebit = XT_CONNTRACK_STATE_BIT(ctinfo); |
136 | else | 139 | else |
137 | statebit = IPT_CONNTRACK_STATE_INVALID; | 140 | statebit = XT_CONNTRACK_STATE_INVALID; |
138 | 141 | ||
139 | if(sinfo->flags & IPT_CONNTRACK_STATE) { | 142 | if(sinfo->flags & XT_CONNTRACK_STATE) { |
140 | if (ct) { | 143 | if (ct) { |
141 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip != | 144 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip != |
142 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip) | 145 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip) |
143 | statebit |= IPT_CONNTRACK_STATE_SNAT; | 146 | statebit |= XT_CONNTRACK_STATE_SNAT; |
144 | 147 | ||
145 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip != | 148 | if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip != |
146 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip) | 149 | ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip) |
147 | statebit |= IPT_CONNTRACK_STATE_DNAT; | 150 | statebit |= XT_CONNTRACK_STATE_DNAT; |
148 | } | 151 | } |
149 | 152 | ||
150 | if (FWINV((statebit & sinfo->statemask) == 0, IPT_CONNTRACK_STATE)) | 153 | if (FWINV((statebit & sinfo->statemask) == 0, XT_CONNTRACK_STATE)) |
151 | return 0; | 154 | return 0; |
152 | } | 155 | } |
153 | 156 | ||
154 | if(sinfo->flags & IPT_CONNTRACK_PROTO) { | 157 | if(sinfo->flags & XT_CONNTRACK_PROTO) { |
155 | if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, IPT_CONNTRACK_PROTO)) | 158 | if (!ct || FWINV(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.protonum, XT_CONNTRACK_PROTO)) |
156 | return 0; | 159 | return 0; |
157 | } | 160 | } |
158 | 161 | ||
159 | if(sinfo->flags & IPT_CONNTRACK_ORIGSRC) { | 162 | if(sinfo->flags & XT_CONNTRACK_ORIGSRC) { |
160 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, IPT_CONNTRACK_ORIGSRC)) | 163 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].src.ip, XT_CONNTRACK_ORIGSRC)) |
161 | return 0; | 164 | return 0; |
162 | } | 165 | } |
163 | 166 | ||
164 | if(sinfo->flags & IPT_CONNTRACK_ORIGDST) { | 167 | if(sinfo->flags & XT_CONNTRACK_ORIGDST) { |
165 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, IPT_CONNTRACK_ORIGDST)) | 168 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_ORIGINAL].s_addr) != sinfo->tuple[IP_CT_DIR_ORIGINAL].dst.ip, XT_CONNTRACK_ORIGDST)) |
166 | return 0; | 169 | return 0; |
167 | } | 170 | } |
168 | 171 | ||
169 | if(sinfo->flags & IPT_CONNTRACK_REPLSRC) { | 172 | if(sinfo->flags & XT_CONNTRACK_REPLSRC) { |
170 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, IPT_CONNTRACK_REPLSRC)) | 173 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip&sinfo->sipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].src.ip, XT_CONNTRACK_REPLSRC)) |
171 | return 0; | 174 | return 0; |
172 | } | 175 | } |
173 | 176 | ||
174 | if(sinfo->flags & IPT_CONNTRACK_REPLDST) { | 177 | if(sinfo->flags & XT_CONNTRACK_REPLDST) { |
175 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, IPT_CONNTRACK_REPLDST)) | 178 | if (!ct || FWINV((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip&sinfo->dipmsk[IP_CT_DIR_REPLY].s_addr) != sinfo->tuple[IP_CT_DIR_REPLY].dst.ip, XT_CONNTRACK_REPLDST)) |
176 | return 0; | 179 | return 0; |
177 | } | 180 | } |
178 | 181 | ||
179 | if(sinfo->flags & IPT_CONNTRACK_STATUS) { | 182 | if(sinfo->flags & XT_CONNTRACK_STATUS) { |
180 | if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, IPT_CONNTRACK_STATUS)) | 183 | if (!ct || FWINV((ct->status & sinfo->statusmask) == 0, XT_CONNTRACK_STATUS)) |
181 | return 0; | 184 | return 0; |
182 | } | 185 | } |
183 | 186 | ||
184 | if(sinfo->flags & IPT_CONNTRACK_EXPIRES) { | 187 | if(sinfo->flags & XT_CONNTRACK_EXPIRES) { |
185 | unsigned long expires; | 188 | unsigned long expires; |
186 | 189 | ||
187 | if(!ct) | 190 | if(!ct) |
@@ -189,7 +192,7 @@ match(const struct sk_buff *skb, | |||
189 | 192 | ||
190 | expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; | 193 | expires = timer_pending(&ct->timeout) ? (ct->timeout.expires - jiffies)/HZ : 0; |
191 | 194 | ||
192 | if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), IPT_CONNTRACK_EXPIRES)) | 195 | if (FWINV(!(expires >= sinfo->expires_min && expires <= sinfo->expires_max), XT_CONNTRACK_EXPIRES)) |
193 | return 0; | 196 | return 0; |
194 | } | 197 | } |
195 | 198 | ||
@@ -199,18 +202,18 @@ match(const struct sk_buff *skb, | |||
199 | #endif /* CONFIG_NF_IP_CONNTRACK */ | 202 | #endif /* CONFIG_NF_IP_CONNTRACK */ |
200 | 203 | ||
201 | static int check(const char *tablename, | 204 | static int check(const char *tablename, |
202 | const struct ipt_ip *ip, | 205 | const void *ip, |
203 | void *matchinfo, | 206 | void *matchinfo, |
204 | unsigned int matchsize, | 207 | unsigned int matchsize, |
205 | unsigned int hook_mask) | 208 | unsigned int hook_mask) |
206 | { | 209 | { |
207 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_conntrack_info))) | 210 | if (matchsize != XT_ALIGN(sizeof(struct xt_conntrack_info))) |
208 | return 0; | 211 | return 0; |
209 | 212 | ||
210 | return 1; | 213 | return 1; |
211 | } | 214 | } |
212 | 215 | ||
213 | static struct ipt_match conntrack_match = { | 216 | static struct xt_match conntrack_match = { |
214 | .name = "conntrack", | 217 | .name = "conntrack", |
215 | .match = &match, | 218 | .match = &match, |
216 | .checkentry = &check, | 219 | .checkentry = &check, |
@@ -219,13 +222,16 @@ static struct ipt_match conntrack_match = { | |||
219 | 222 | ||
220 | static int __init init(void) | 223 | static int __init init(void) |
221 | { | 224 | { |
222 | need_ip_conntrack(); | 225 | int ret; |
223 | return ipt_register_match(&conntrack_match); | 226 | need_conntrack(); |
227 | ret = xt_register_match(AF_INET, &conntrack_match); | ||
228 | |||
229 | return ret; | ||
224 | } | 230 | } |
225 | 231 | ||
226 | static void __exit fini(void) | 232 | static void __exit fini(void) |
227 | { | 233 | { |
228 | ipt_unregister_match(&conntrack_match); | 234 | xt_unregister_match(AF_INET, &conntrack_match); |
229 | } | 235 | } |
230 | 236 | ||
231 | module_init(init); | 237 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_dccp.c b/net/netfilter/xt_dccp.c index ad3278bba6c1..779f42fc9524 100644 --- a/net/ipv4/netfilter/ipt_dccp.c +++ b/net/netfilter/xt_dccp.c | |||
@@ -14,8 +14,16 @@ | |||
14 | #include <net/ip.h> | 14 | #include <net/ip.h> |
15 | #include <linux/dccp.h> | 15 | #include <linux/dccp.h> |
16 | 16 | ||
17 | #include <linux/netfilter/x_tables.h> | ||
18 | #include <linux/netfilter/xt_dccp.h> | ||
19 | |||
17 | #include <linux/netfilter_ipv4/ip_tables.h> | 20 | #include <linux/netfilter_ipv4/ip_tables.h> |
18 | #include <linux/netfilter_ipv4/ipt_dccp.h> | 21 | #include <linux/netfilter_ipv6/ip6_tables.h> |
22 | |||
23 | MODULE_LICENSE("GPL"); | ||
24 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
25 | MODULE_DESCRIPTION("Match for DCCP protocol packets"); | ||
26 | MODULE_ALIAS("ipt_dccp"); | ||
19 | 27 | ||
20 | #define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ | 28 | #define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ |
21 | || (!!((invflag) & (option)) ^ (cond))) | 29 | || (!!((invflag) & (option)) ^ (cond))) |
@@ -26,6 +34,7 @@ static DEFINE_SPINLOCK(dccp_buflock); | |||
26 | static inline int | 34 | static inline int |
27 | dccp_find_option(u_int8_t option, | 35 | dccp_find_option(u_int8_t option, |
28 | const struct sk_buff *skb, | 36 | const struct sk_buff *skb, |
37 | unsigned int protoff, | ||
29 | const struct dccp_hdr *dh, | 38 | const struct dccp_hdr *dh, |
30 | int *hotdrop) | 39 | int *hotdrop) |
31 | { | 40 | { |
@@ -44,9 +53,7 @@ dccp_find_option(u_int8_t option, | |||
44 | return 0; | 53 | return 0; |
45 | 54 | ||
46 | spin_lock_bh(&dccp_buflock); | 55 | spin_lock_bh(&dccp_buflock); |
47 | op = skb_header_pointer(skb, | 56 | op = skb_header_pointer(skb, protoff + optoff, optlen, dccp_optbuf); |
48 | skb->nh.iph->ihl*4 + optoff, | ||
49 | optlen, dccp_optbuf); | ||
50 | if (op == NULL) { | 57 | if (op == NULL) { |
51 | /* If we don't have the whole header, drop packet. */ | 58 | /* If we don't have the whole header, drop packet. */ |
52 | spin_unlock_bh(&dccp_buflock); | 59 | spin_unlock_bh(&dccp_buflock); |
@@ -78,10 +85,10 @@ match_types(const struct dccp_hdr *dh, u_int16_t typemask) | |||
78 | } | 85 | } |
79 | 86 | ||
80 | static inline int | 87 | static inline int |
81 | match_option(u_int8_t option, const struct sk_buff *skb, | 88 | match_option(u_int8_t option, const struct sk_buff *skb, unsigned int protoff, |
82 | const struct dccp_hdr *dh, int *hotdrop) | 89 | const struct dccp_hdr *dh, int *hotdrop) |
83 | { | 90 | { |
84 | return dccp_find_option(option, skb, dh, hotdrop); | 91 | return dccp_find_option(option, skb, protoff, dh, hotdrop); |
85 | } | 92 | } |
86 | 93 | ||
87 | static int | 94 | static int |
@@ -90,16 +97,17 @@ match(const struct sk_buff *skb, | |||
90 | const struct net_device *out, | 97 | const struct net_device *out, |
91 | const void *matchinfo, | 98 | const void *matchinfo, |
92 | int offset, | 99 | int offset, |
100 | unsigned int protoff, | ||
93 | int *hotdrop) | 101 | int *hotdrop) |
94 | { | 102 | { |
95 | const struct ipt_dccp_info *info = | 103 | const struct xt_dccp_info *info = |
96 | (const struct ipt_dccp_info *)matchinfo; | 104 | (const struct xt_dccp_info *)matchinfo; |
97 | struct dccp_hdr _dh, *dh; | 105 | struct dccp_hdr _dh, *dh; |
98 | 106 | ||
99 | if (offset) | 107 | if (offset) |
100 | return 0; | 108 | return 0; |
101 | 109 | ||
102 | dh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_dh), &_dh); | 110 | dh = skb_header_pointer(skb, protoff, sizeof(_dh), &_dh); |
103 | if (dh == NULL) { | 111 | if (dh == NULL) { |
104 | *hotdrop = 1; | 112 | *hotdrop = 1; |
105 | return 0; | 113 | return 0; |
@@ -107,42 +115,73 @@ match(const struct sk_buff *skb, | |||
107 | 115 | ||
108 | return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0]) | 116 | return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0]) |
109 | && (ntohs(dh->dccph_sport) <= info->spts[1])), | 117 | && (ntohs(dh->dccph_sport) <= info->spts[1])), |
110 | IPT_DCCP_SRC_PORTS, info->flags, info->invflags) | 118 | XT_DCCP_SRC_PORTS, info->flags, info->invflags) |
111 | && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0]) | 119 | && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0]) |
112 | && (ntohs(dh->dccph_dport) <= info->dpts[1])), | 120 | && (ntohs(dh->dccph_dport) <= info->dpts[1])), |
113 | IPT_DCCP_DEST_PORTS, info->flags, info->invflags) | 121 | XT_DCCP_DEST_PORTS, info->flags, info->invflags) |
114 | && DCCHECK(match_types(dh, info->typemask), | 122 | && DCCHECK(match_types(dh, info->typemask), |
115 | IPT_DCCP_TYPE, info->flags, info->invflags) | 123 | XT_DCCP_TYPE, info->flags, info->invflags) |
116 | && DCCHECK(match_option(info->option, skb, dh, hotdrop), | 124 | && DCCHECK(match_option(info->option, skb, protoff, dh, |
117 | IPT_DCCP_OPTION, info->flags, info->invflags); | 125 | hotdrop), |
126 | XT_DCCP_OPTION, info->flags, info->invflags); | ||
118 | } | 127 | } |
119 | 128 | ||
120 | static int | 129 | static int |
121 | checkentry(const char *tablename, | 130 | checkentry(const char *tablename, |
122 | const struct ipt_ip *ip, | 131 | const void *inf, |
123 | void *matchinfo, | 132 | void *matchinfo, |
124 | unsigned int matchsize, | 133 | unsigned int matchsize, |
125 | unsigned int hook_mask) | 134 | unsigned int hook_mask) |
126 | { | 135 | { |
127 | const struct ipt_dccp_info *info; | 136 | const struct ipt_ip *ip = inf; |
137 | const struct xt_dccp_info *info; | ||
128 | 138 | ||
129 | info = (const struct ipt_dccp_info *)matchinfo; | 139 | info = (const struct xt_dccp_info *)matchinfo; |
130 | 140 | ||
131 | return ip->proto == IPPROTO_DCCP | 141 | return ip->proto == IPPROTO_DCCP |
132 | && !(ip->invflags & IPT_INV_PROTO) | 142 | && !(ip->invflags & XT_INV_PROTO) |
133 | && matchsize == IPT_ALIGN(sizeof(struct ipt_dccp_info)) | 143 | && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info)) |
134 | && !(info->flags & ~IPT_DCCP_VALID_FLAGS) | 144 | && !(info->flags & ~XT_DCCP_VALID_FLAGS) |
135 | && !(info->invflags & ~IPT_DCCP_VALID_FLAGS) | 145 | && !(info->invflags & ~XT_DCCP_VALID_FLAGS) |
136 | && !(info->invflags & ~info->flags); | 146 | && !(info->invflags & ~info->flags); |
137 | } | 147 | } |
138 | 148 | ||
139 | static struct ipt_match dccp_match = | 149 | static int |
150 | checkentry6(const char *tablename, | ||
151 | const void *inf, | ||
152 | void *matchinfo, | ||
153 | unsigned int matchsize, | ||
154 | unsigned int hook_mask) | ||
155 | { | ||
156 | const struct ip6t_ip6 *ip = inf; | ||
157 | const struct xt_dccp_info *info; | ||
158 | |||
159 | info = (const struct xt_dccp_info *)matchinfo; | ||
160 | |||
161 | return ip->proto == IPPROTO_DCCP | ||
162 | && !(ip->invflags & XT_INV_PROTO) | ||
163 | && matchsize == XT_ALIGN(sizeof(struct xt_dccp_info)) | ||
164 | && !(info->flags & ~XT_DCCP_VALID_FLAGS) | ||
165 | && !(info->invflags & ~XT_DCCP_VALID_FLAGS) | ||
166 | && !(info->invflags & ~info->flags); | ||
167 | } | ||
168 | |||
169 | |||
170 | static struct xt_match dccp_match = | ||
140 | { | 171 | { |
141 | .name = "dccp", | 172 | .name = "dccp", |
142 | .match = &match, | 173 | .match = &match, |
143 | .checkentry = &checkentry, | 174 | .checkentry = &checkentry, |
144 | .me = THIS_MODULE, | 175 | .me = THIS_MODULE, |
145 | }; | 176 | }; |
177 | static struct xt_match dccp6_match = | ||
178 | { | ||
179 | .name = "dccp", | ||
180 | .match = &match, | ||
181 | .checkentry = &checkentry6, | ||
182 | .me = THIS_MODULE, | ||
183 | }; | ||
184 | |||
146 | 185 | ||
147 | static int __init init(void) | 186 | static int __init init(void) |
148 | { | 187 | { |
@@ -154,23 +193,29 @@ static int __init init(void) | |||
154 | dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL); | 193 | dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL); |
155 | if (!dccp_optbuf) | 194 | if (!dccp_optbuf) |
156 | return -ENOMEM; | 195 | return -ENOMEM; |
157 | ret = ipt_register_match(&dccp_match); | 196 | ret = xt_register_match(AF_INET, &dccp_match); |
158 | if (ret) | 197 | if (ret) |
159 | kfree(dccp_optbuf); | 198 | goto out_kfree; |
199 | ret = xt_register_match(AF_INET6, &dccp6_match); | ||
200 | if (ret) | ||
201 | goto out_unreg; | ||
202 | |||
203 | return ret; | ||
204 | |||
205 | out_unreg: | ||
206 | xt_unregister_match(AF_INET, &dccp_match); | ||
207 | out_kfree: | ||
208 | kfree(dccp_optbuf); | ||
160 | 209 | ||
161 | return ret; | 210 | return ret; |
162 | } | 211 | } |
163 | 212 | ||
164 | static void __exit fini(void) | 213 | static void __exit fini(void) |
165 | { | 214 | { |
166 | ipt_unregister_match(&dccp_match); | 215 | xt_unregister_match(AF_INET6, &dccp6_match); |
216 | xt_unregister_match(AF_INET, &dccp_match); | ||
167 | kfree(dccp_optbuf); | 217 | kfree(dccp_optbuf); |
168 | } | 218 | } |
169 | 219 | ||
170 | module_init(init); | 220 | module_init(init); |
171 | module_exit(fini); | 221 | module_exit(fini); |
172 | |||
173 | MODULE_LICENSE("GPL"); | ||
174 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
175 | MODULE_DESCRIPTION("Match for DCCP protocol packets"); | ||
176 | |||
diff --git a/net/ipv4/netfilter/ipt_helper.c b/net/netfilter/xt_helper.c index aef649e393af..38b6715e1db4 100644 --- a/net/ipv4/netfilter/ipt_helper.c +++ b/net/netfilter/xt_helper.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/netfilter.h> | 15 | #include <linux/netfilter.h> |
16 | #include <linux/interrupt.h> | ||
17 | #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) | 16 | #if defined(CONFIG_IP_NF_CONNTRACK) || defined(CONFIG_IP_NF_CONNTRACK_MODULE) |
18 | #include <linux/netfilter_ipv4/ip_conntrack.h> | 17 | #include <linux/netfilter_ipv4/ip_conntrack.h> |
19 | #include <linux/netfilter_ipv4/ip_conntrack_core.h> | 18 | #include <linux/netfilter_ipv4/ip_conntrack_core.h> |
@@ -23,12 +22,14 @@ | |||
23 | #include <net/netfilter/nf_conntrack_core.h> | 22 | #include <net/netfilter/nf_conntrack_core.h> |
24 | #include <net/netfilter/nf_conntrack_helper.h> | 23 | #include <net/netfilter/nf_conntrack_helper.h> |
25 | #endif | 24 | #endif |
26 | #include <linux/netfilter_ipv4/ip_tables.h> | 25 | #include <linux/netfilter/x_tables.h> |
27 | #include <linux/netfilter_ipv4/ipt_helper.h> | 26 | #include <linux/netfilter/xt_helper.h> |
28 | 27 | ||
29 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
30 | MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>"); | 29 | MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>"); |
31 | MODULE_DESCRIPTION("iptables helper match module"); | 30 | MODULE_DESCRIPTION("iptables helper match module"); |
31 | MODULE_ALIAS("ipt_helper"); | ||
32 | MODULE_ALIAS("ip6t_helper"); | ||
32 | 33 | ||
33 | #if 0 | 34 | #if 0 |
34 | #define DEBUGP printk | 35 | #define DEBUGP printk |
@@ -43,27 +44,28 @@ match(const struct sk_buff *skb, | |||
43 | const struct net_device *out, | 44 | const struct net_device *out, |
44 | const void *matchinfo, | 45 | const void *matchinfo, |
45 | int offset, | 46 | int offset, |
47 | unsigned int protoff, | ||
46 | int *hotdrop) | 48 | int *hotdrop) |
47 | { | 49 | { |
48 | const struct ipt_helper_info *info = matchinfo; | 50 | const struct xt_helper_info *info = matchinfo; |
49 | struct ip_conntrack *ct; | 51 | struct ip_conntrack *ct; |
50 | enum ip_conntrack_info ctinfo; | 52 | enum ip_conntrack_info ctinfo; |
51 | int ret = info->invert; | 53 | int ret = info->invert; |
52 | 54 | ||
53 | ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); | 55 | ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo); |
54 | if (!ct) { | 56 | if (!ct) { |
55 | DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); | 57 | DEBUGP("xt_helper: Eek! invalid conntrack?\n"); |
56 | return ret; | 58 | return ret; |
57 | } | 59 | } |
58 | 60 | ||
59 | if (!ct->master) { | 61 | if (!ct->master) { |
60 | DEBUGP("ipt_helper: conntrack %p has no master\n", ct); | 62 | DEBUGP("xt_helper: conntrack %p has no master\n", ct); |
61 | return ret; | 63 | return ret; |
62 | } | 64 | } |
63 | 65 | ||
64 | read_lock_bh(&ip_conntrack_lock); | 66 | read_lock_bh(&ip_conntrack_lock); |
65 | if (!ct->master->helper) { | 67 | if (!ct->master->helper) { |
66 | DEBUGP("ipt_helper: master ct %p has no helper\n", | 68 | DEBUGP("xt_helper: master ct %p has no helper\n", |
67 | exp->expectant); | 69 | exp->expectant); |
68 | goto out_unlock; | 70 | goto out_unlock; |
69 | } | 71 | } |
@@ -89,27 +91,28 @@ match(const struct sk_buff *skb, | |||
89 | const struct net_device *out, | 91 | const struct net_device *out, |
90 | const void *matchinfo, | 92 | const void *matchinfo, |
91 | int offset, | 93 | int offset, |
94 | unsigned int protoff, | ||
92 | int *hotdrop) | 95 | int *hotdrop) |
93 | { | 96 | { |
94 | const struct ipt_helper_info *info = matchinfo; | 97 | const struct xt_helper_info *info = matchinfo; |
95 | struct nf_conn *ct; | 98 | struct nf_conn *ct; |
96 | enum ip_conntrack_info ctinfo; | 99 | enum ip_conntrack_info ctinfo; |
97 | int ret = info->invert; | 100 | int ret = info->invert; |
98 | 101 | ||
99 | ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); | 102 | ct = nf_ct_get((struct sk_buff *)skb, &ctinfo); |
100 | if (!ct) { | 103 | if (!ct) { |
101 | DEBUGP("ipt_helper: Eek! invalid conntrack?\n"); | 104 | DEBUGP("xt_helper: Eek! invalid conntrack?\n"); |
102 | return ret; | 105 | return ret; |
103 | } | 106 | } |
104 | 107 | ||
105 | if (!ct->master) { | 108 | if (!ct->master) { |
106 | DEBUGP("ipt_helper: conntrack %p has no master\n", ct); | 109 | DEBUGP("xt_helper: conntrack %p has no master\n", ct); |
107 | return ret; | 110 | return ret; |
108 | } | 111 | } |
109 | 112 | ||
110 | read_lock_bh(&nf_conntrack_lock); | 113 | read_lock_bh(&nf_conntrack_lock); |
111 | if (!ct->master->helper) { | 114 | if (!ct->master->helper) { |
112 | DEBUGP("ipt_helper: master ct %p has no helper\n", | 115 | DEBUGP("xt_helper: master ct %p has no helper\n", |
113 | exp->expectant); | 116 | exp->expectant); |
114 | goto out_unlock; | 117 | goto out_unlock; |
115 | } | 118 | } |
@@ -129,23 +132,29 @@ out_unlock: | |||
129 | #endif | 132 | #endif |
130 | 133 | ||
131 | static int check(const char *tablename, | 134 | static int check(const char *tablename, |
132 | const struct ipt_ip *ip, | 135 | const void *inf, |
133 | void *matchinfo, | 136 | void *matchinfo, |
134 | unsigned int matchsize, | 137 | unsigned int matchsize, |
135 | unsigned int hook_mask) | 138 | unsigned int hook_mask) |
136 | { | 139 | { |
137 | struct ipt_helper_info *info = matchinfo; | 140 | struct xt_helper_info *info = matchinfo; |
138 | 141 | ||
139 | info->name[29] = '\0'; | 142 | info->name[29] = '\0'; |
140 | 143 | ||
141 | /* verify size */ | 144 | /* verify size */ |
142 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_helper_info))) | 145 | if (matchsize != XT_ALIGN(sizeof(struct xt_helper_info))) |
143 | return 0; | 146 | return 0; |
144 | 147 | ||
145 | return 1; | 148 | return 1; |
146 | } | 149 | } |
147 | 150 | ||
148 | static struct ipt_match helper_match = { | 151 | static struct xt_match helper_match = { |
152 | .name = "helper", | ||
153 | .match = &match, | ||
154 | .checkentry = &check, | ||
155 | .me = THIS_MODULE, | ||
156 | }; | ||
157 | static struct xt_match helper6_match = { | ||
149 | .name = "helper", | 158 | .name = "helper", |
150 | .match = &match, | 159 | .match = &match, |
151 | .checkentry = &check, | 160 | .checkentry = &check, |
@@ -154,13 +163,24 @@ static struct ipt_match helper_match = { | |||
154 | 163 | ||
155 | static int __init init(void) | 164 | static int __init init(void) |
156 | { | 165 | { |
157 | need_ip_conntrack(); | 166 | int ret; |
158 | return ipt_register_match(&helper_match); | 167 | need_conntrack(); |
168 | |||
169 | ret = xt_register_match(AF_INET, &helper_match); | ||
170 | if (ret < 0) | ||
171 | return ret; | ||
172 | |||
173 | ret = xt_register_match(AF_INET6, &helper6_match); | ||
174 | if (ret < 0) | ||
175 | xt_unregister_match(AF_INET, &helper_match); | ||
176 | |||
177 | return ret; | ||
159 | } | 178 | } |
160 | 179 | ||
161 | static void __exit fini(void) | 180 | static void __exit fini(void) |
162 | { | 181 | { |
163 | ipt_unregister_match(&helper_match); | 182 | xt_unregister_match(AF_INET, &helper_match); |
183 | xt_unregister_match(AF_INET6, &helper6_match); | ||
164 | } | 184 | } |
165 | 185 | ||
166 | module_init(init); | 186 | module_init(init); |
diff --git a/net/netfilter/xt_length.c b/net/netfilter/xt_length.c new file mode 100644 index 000000000000..ab6c710cf88f --- /dev/null +++ b/net/netfilter/xt_length.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* Kernel module to match packet length. */ | ||
2 | /* (C) 1999-2001 James Morris <jmorros@intercode.com.au> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/skbuff.h> | ||
11 | #include <net/ip.h> | ||
12 | |||
13 | #include <linux/netfilter/xt_length.h> | ||
14 | #include <linux/netfilter/x_tables.h> | ||
15 | |||
16 | MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); | ||
17 | MODULE_DESCRIPTION("IP tables packet length matching module"); | ||
18 | MODULE_LICENSE("GPL"); | ||
19 | MODULE_ALIAS("ipt_length"); | ||
20 | MODULE_ALIAS("ip6t_length"); | ||
21 | |||
22 | static int | ||
23 | match(const struct sk_buff *skb, | ||
24 | const struct net_device *in, | ||
25 | const struct net_device *out, | ||
26 | const void *matchinfo, | ||
27 | int offset, | ||
28 | unsigned int protoff, | ||
29 | int *hotdrop) | ||
30 | { | ||
31 | const struct xt_length_info *info = matchinfo; | ||
32 | u_int16_t pktlen = ntohs(skb->nh.iph->tot_len); | ||
33 | |||
34 | return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; | ||
35 | } | ||
36 | |||
37 | static int | ||
38 | match6(const struct sk_buff *skb, | ||
39 | const struct net_device *in, | ||
40 | const struct net_device *out, | ||
41 | const void *matchinfo, | ||
42 | int offset, | ||
43 | unsigned int protoff, | ||
44 | int *hotdrop) | ||
45 | { | ||
46 | const struct xt_length_info *info = matchinfo; | ||
47 | u_int16_t pktlen = ntohs(skb->nh.ipv6h->payload_len) + sizeof(struct ipv6hdr); | ||
48 | |||
49 | return (pktlen >= info->min && pktlen <= info->max) ^ info->invert; | ||
50 | } | ||
51 | |||
52 | static int | ||
53 | checkentry(const char *tablename, | ||
54 | const void *ip, | ||
55 | void *matchinfo, | ||
56 | unsigned int matchsize, | ||
57 | unsigned int hook_mask) | ||
58 | { | ||
59 | if (matchsize != XT_ALIGN(sizeof(struct xt_length_info))) | ||
60 | return 0; | ||
61 | |||
62 | return 1; | ||
63 | } | ||
64 | |||
65 | static struct xt_match length_match = { | ||
66 | .name = "length", | ||
67 | .match = &match, | ||
68 | .checkentry = &checkentry, | ||
69 | .me = THIS_MODULE, | ||
70 | }; | ||
71 | static struct xt_match length6_match = { | ||
72 | .name = "length", | ||
73 | .match = &match6, | ||
74 | .checkentry = &checkentry, | ||
75 | .me = THIS_MODULE, | ||
76 | }; | ||
77 | |||
78 | static int __init init(void) | ||
79 | { | ||
80 | int ret; | ||
81 | ret = xt_register_match(AF_INET, &length_match); | ||
82 | if (ret) | ||
83 | return ret; | ||
84 | ret = xt_register_match(AF_INET6, &length6_match); | ||
85 | if (ret) | ||
86 | xt_unregister_match(AF_INET, &length_match); | ||
87 | |||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | static void __exit fini(void) | ||
92 | { | ||
93 | xt_unregister_match(AF_INET, &length_match); | ||
94 | xt_unregister_match(AF_INET6, &length6_match); | ||
95 | } | ||
96 | |||
97 | module_init(init); | ||
98 | module_exit(fini); | ||
diff --git a/net/ipv4/netfilter/ipt_limit.c b/net/netfilter/xt_limit.c index 0c24dcc703a5..15e40506bc3a 100644 --- a/net/ipv4/netfilter/ipt_limit.c +++ b/net/netfilter/xt_limit.c | |||
@@ -18,12 +18,14 @@ | |||
18 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | 20 | ||
21 | #include <linux/netfilter_ipv4/ip_tables.h> | 21 | #include <linux/netfilter/x_tables.h> |
22 | #include <linux/netfilter_ipv4/ipt_limit.h> | 22 | #include <linux/netfilter/xt_limit.h> |
23 | 23 | ||
24 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
25 | MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>"); | 25 | MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>"); |
26 | MODULE_DESCRIPTION("iptables rate limit match"); | 26 | MODULE_DESCRIPTION("iptables rate limit match"); |
27 | MODULE_ALIAS("ipt_limit"); | ||
28 | MODULE_ALIAS("ip6t_limit"); | ||
27 | 29 | ||
28 | /* The algorithm used is the Simple Token Bucket Filter (TBF) | 30 | /* The algorithm used is the Simple Token Bucket Filter (TBF) |
29 | * see net/sched/sch_tbf.c in the linux source tree | 31 | * see net/sched/sch_tbf.c in the linux source tree |
@@ -68,9 +70,10 @@ ipt_limit_match(const struct sk_buff *skb, | |||
68 | const struct net_device *out, | 70 | const struct net_device *out, |
69 | const void *matchinfo, | 71 | const void *matchinfo, |
70 | int offset, | 72 | int offset, |
73 | unsigned int protoff, | ||
71 | int *hotdrop) | 74 | int *hotdrop) |
72 | { | 75 | { |
73 | struct ipt_rateinfo *r = ((struct ipt_rateinfo *)matchinfo)->master; | 76 | struct xt_rateinfo *r = ((struct xt_rateinfo *)matchinfo)->master; |
74 | unsigned long now = jiffies; | 77 | unsigned long now = jiffies; |
75 | 78 | ||
76 | spin_lock_bh(&limit_lock); | 79 | spin_lock_bh(&limit_lock); |
@@ -96,32 +99,32 @@ user2credits(u_int32_t user) | |||
96 | /* If multiplying would overflow... */ | 99 | /* If multiplying would overflow... */ |
97 | if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) | 100 | if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) |
98 | /* Divide first. */ | 101 | /* Divide first. */ |
99 | return (user / IPT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; | 102 | return (user / XT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY; |
100 | 103 | ||
101 | return (user * HZ * CREDITS_PER_JIFFY) / IPT_LIMIT_SCALE; | 104 | return (user * HZ * CREDITS_PER_JIFFY) / XT_LIMIT_SCALE; |
102 | } | 105 | } |
103 | 106 | ||
104 | static int | 107 | static int |
105 | ipt_limit_checkentry(const char *tablename, | 108 | ipt_limit_checkentry(const char *tablename, |
106 | const struct ipt_ip *ip, | 109 | const void *inf, |
107 | void *matchinfo, | 110 | void *matchinfo, |
108 | unsigned int matchsize, | 111 | unsigned int matchsize, |
109 | unsigned int hook_mask) | 112 | unsigned int hook_mask) |
110 | { | 113 | { |
111 | struct ipt_rateinfo *r = matchinfo; | 114 | struct xt_rateinfo *r = matchinfo; |
112 | 115 | ||
113 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_rateinfo))) | 116 | if (matchsize != XT_ALIGN(sizeof(struct xt_rateinfo))) |
114 | return 0; | 117 | return 0; |
115 | 118 | ||
116 | /* Check for overflow. */ | 119 | /* Check for overflow. */ |
117 | if (r->burst == 0 | 120 | if (r->burst == 0 |
118 | || user2credits(r->avg * r->burst) < user2credits(r->avg)) { | 121 | || user2credits(r->avg * r->burst) < user2credits(r->avg)) { |
119 | printk("Overflow in ipt_limit, try lower: %u/%u\n", | 122 | printk("Overflow in xt_limit, try lower: %u/%u\n", |
120 | r->avg, r->burst); | 123 | r->avg, r->burst); |
121 | return 0; | 124 | return 0; |
122 | } | 125 | } |
123 | 126 | ||
124 | /* User avg in seconds * IPT_LIMIT_SCALE: convert to jiffies * | 127 | /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * |
125 | 128. */ | 128 | 128. */ |
126 | r->prev = jiffies; | 129 | r->prev = jiffies; |
127 | r->credit = user2credits(r->avg * r->burst); /* Credits full. */ | 130 | r->credit = user2credits(r->avg * r->burst); /* Credits full. */ |
@@ -134,7 +137,13 @@ ipt_limit_checkentry(const char *tablename, | |||
134 | return 1; | 137 | return 1; |
135 | } | 138 | } |
136 | 139 | ||
137 | static struct ipt_match ipt_limit_reg = { | 140 | static struct xt_match ipt_limit_reg = { |
141 | .name = "limit", | ||
142 | .match = ipt_limit_match, | ||
143 | .checkentry = ipt_limit_checkentry, | ||
144 | .me = THIS_MODULE, | ||
145 | }; | ||
146 | static struct xt_match limit6_reg = { | ||
138 | .name = "limit", | 147 | .name = "limit", |
139 | .match = ipt_limit_match, | 148 | .match = ipt_limit_match, |
140 | .checkentry = ipt_limit_checkentry, | 149 | .checkentry = ipt_limit_checkentry, |
@@ -143,14 +152,23 @@ static struct ipt_match ipt_limit_reg = { | |||
143 | 152 | ||
144 | static int __init init(void) | 153 | static int __init init(void) |
145 | { | 154 | { |
146 | if (ipt_register_match(&ipt_limit_reg)) | 155 | int ret; |
147 | return -EINVAL; | 156 | |
148 | return 0; | 157 | ret = xt_register_match(AF_INET, &ipt_limit_reg); |
158 | if (ret) | ||
159 | return ret; | ||
160 | |||
161 | ret = xt_register_match(AF_INET6, &limit6_reg); | ||
162 | if (ret) | ||
163 | xt_unregister_match(AF_INET, &ipt_limit_reg); | ||
164 | |||
165 | return ret; | ||
149 | } | 166 | } |
150 | 167 | ||
151 | static void __exit fini(void) | 168 | static void __exit fini(void) |
152 | { | 169 | { |
153 | ipt_unregister_match(&ipt_limit_reg); | 170 | xt_unregister_match(AF_INET, &ipt_limit_reg); |
171 | xt_unregister_match(AF_INET6, &limit6_reg); | ||
154 | } | 172 | } |
155 | 173 | ||
156 | module_init(init); | 174 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_mac.c b/net/netfilter/xt_mac.c index 1b9bb4559f80..0461dcb5fc7a 100644 --- a/net/ipv4/netfilter/ipt_mac.c +++ b/net/netfilter/xt_mac.c | |||
@@ -13,12 +13,15 @@ | |||
13 | #include <linux/if_ether.h> | 13 | #include <linux/if_ether.h> |
14 | #include <linux/etherdevice.h> | 14 | #include <linux/etherdevice.h> |
15 | 15 | ||
16 | #include <linux/netfilter_ipv4/ipt_mac.h> | 16 | #include <linux/netfilter_ipv4.h> |
17 | #include <linux/netfilter_ipv4/ip_tables.h> | 17 | #include <linux/netfilter/xt_mac.h> |
18 | #include <linux/netfilter/x_tables.h> | ||
18 | 19 | ||
19 | MODULE_LICENSE("GPL"); | 20 | MODULE_LICENSE("GPL"); |
20 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 21 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
21 | MODULE_DESCRIPTION("iptables mac matching module"); | 22 | MODULE_DESCRIPTION("iptables mac matching module"); |
23 | MODULE_ALIAS("ipt_mac"); | ||
24 | MODULE_ALIAS("ip6t_mac"); | ||
22 | 25 | ||
23 | static int | 26 | static int |
24 | match(const struct sk_buff *skb, | 27 | match(const struct sk_buff *skb, |
@@ -26,9 +29,10 @@ match(const struct sk_buff *skb, | |||
26 | const struct net_device *out, | 29 | const struct net_device *out, |
27 | const void *matchinfo, | 30 | const void *matchinfo, |
28 | int offset, | 31 | int offset, |
32 | unsigned int protoff, | ||
29 | int *hotdrop) | 33 | int *hotdrop) |
30 | { | 34 | { |
31 | const struct ipt_mac_info *info = matchinfo; | 35 | const struct xt_mac_info *info = matchinfo; |
32 | 36 | ||
33 | /* Is mac pointer valid? */ | 37 | /* Is mac pointer valid? */ |
34 | return (skb->mac.raw >= skb->head | 38 | return (skb->mac.raw >= skb->head |
@@ -40,7 +44,7 @@ match(const struct sk_buff *skb, | |||
40 | 44 | ||
41 | static int | 45 | static int |
42 | ipt_mac_checkentry(const char *tablename, | 46 | ipt_mac_checkentry(const char *tablename, |
43 | const struct ipt_ip *ip, | 47 | const void *inf, |
44 | void *matchinfo, | 48 | void *matchinfo, |
45 | unsigned int matchsize, | 49 | unsigned int matchsize, |
46 | unsigned int hook_mask) | 50 | unsigned int hook_mask) |
@@ -49,17 +53,23 @@ ipt_mac_checkentry(const char *tablename, | |||
49 | if (hook_mask | 53 | if (hook_mask |
50 | & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | 54 | & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) |
51 | | (1 << NF_IP_FORWARD))) { | 55 | | (1 << NF_IP_FORWARD))) { |
52 | printk("ipt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); | 56 | printk("xt_mac: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); |
53 | return 0; | 57 | return 0; |
54 | } | 58 | } |
55 | 59 | ||
56 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_mac_info))) | 60 | if (matchsize != XT_ALIGN(sizeof(struct xt_mac_info))) |
57 | return 0; | 61 | return 0; |
58 | 62 | ||
59 | return 1; | 63 | return 1; |
60 | } | 64 | } |
61 | 65 | ||
62 | static struct ipt_match mac_match = { | 66 | static struct xt_match mac_match = { |
67 | .name = "mac", | ||
68 | .match = &match, | ||
69 | .checkentry = &ipt_mac_checkentry, | ||
70 | .me = THIS_MODULE, | ||
71 | }; | ||
72 | static struct xt_match mac6_match = { | ||
63 | .name = "mac", | 73 | .name = "mac", |
64 | .match = &match, | 74 | .match = &match, |
65 | .checkentry = &ipt_mac_checkentry, | 75 | .checkentry = &ipt_mac_checkentry, |
@@ -68,12 +78,22 @@ static struct ipt_match mac_match = { | |||
68 | 78 | ||
69 | static int __init init(void) | 79 | static int __init init(void) |
70 | { | 80 | { |
71 | return ipt_register_match(&mac_match); | 81 | int ret; |
82 | ret = xt_register_match(AF_INET, &mac_match); | ||
83 | if (ret) | ||
84 | return ret; | ||
85 | |||
86 | ret = xt_register_match(AF_INET6, &mac6_match); | ||
87 | if (ret) | ||
88 | xt_unregister_match(AF_INET, &mac_match); | ||
89 | |||
90 | return ret; | ||
72 | } | 91 | } |
73 | 92 | ||
74 | static void __exit fini(void) | 93 | static void __exit fini(void) |
75 | { | 94 | { |
76 | ipt_unregister_match(&mac_match); | 95 | xt_unregister_match(AF_INET, &mac_match); |
96 | xt_unregister_match(AF_INET6, &mac6_match); | ||
77 | } | 97 | } |
78 | 98 | ||
79 | module_init(init); | 99 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_mark.c b/net/netfilter/xt_mark.c index 00bef6cdd3f8..2a0ac62b72c8 100644 --- a/net/ipv4/netfilter/ipt_mark.c +++ b/net/netfilter/xt_mark.c | |||
@@ -10,12 +10,14 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | 12 | ||
13 | #include <linux/netfilter_ipv4/ipt_mark.h> | 13 | #include <linux/netfilter/xt_mark.h> |
14 | #include <linux/netfilter_ipv4/ip_tables.h> | 14 | #include <linux/netfilter/x_tables.h> |
15 | 15 | ||
16 | MODULE_LICENSE("GPL"); | 16 | MODULE_LICENSE("GPL"); |
17 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | 17 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); |
18 | MODULE_DESCRIPTION("iptables mark matching module"); | 18 | MODULE_DESCRIPTION("iptables mark matching module"); |
19 | MODULE_ALIAS("ipt_mark"); | ||
20 | MODULE_ALIAS("ip6t_mark"); | ||
19 | 21 | ||
20 | static int | 22 | static int |
21 | match(const struct sk_buff *skb, | 23 | match(const struct sk_buff *skb, |
@@ -23,23 +25,24 @@ match(const struct sk_buff *skb, | |||
23 | const struct net_device *out, | 25 | const struct net_device *out, |
24 | const void *matchinfo, | 26 | const void *matchinfo, |
25 | int offset, | 27 | int offset, |
28 | unsigned int protoff, | ||
26 | int *hotdrop) | 29 | int *hotdrop) |
27 | { | 30 | { |
28 | const struct ipt_mark_info *info = matchinfo; | 31 | const struct xt_mark_info *info = matchinfo; |
29 | 32 | ||
30 | return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; | 33 | return ((skb->nfmark & info->mask) == info->mark) ^ info->invert; |
31 | } | 34 | } |
32 | 35 | ||
33 | static int | 36 | static int |
34 | checkentry(const char *tablename, | 37 | checkentry(const char *tablename, |
35 | const struct ipt_ip *ip, | 38 | const void *entry, |
36 | void *matchinfo, | 39 | void *matchinfo, |
37 | unsigned int matchsize, | 40 | unsigned int matchsize, |
38 | unsigned int hook_mask) | 41 | unsigned int hook_mask) |
39 | { | 42 | { |
40 | struct ipt_mark_info *minfo = (struct ipt_mark_info *) matchinfo; | 43 | struct xt_mark_info *minfo = (struct xt_mark_info *) matchinfo; |
41 | 44 | ||
42 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_mark_info))) | 45 | if (matchsize != XT_ALIGN(sizeof(struct xt_mark_info))) |
43 | return 0; | 46 | return 0; |
44 | 47 | ||
45 | if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) { | 48 | if (minfo->mark > 0xffffffff || minfo->mask > 0xffffffff) { |
@@ -50,7 +53,14 @@ checkentry(const char *tablename, | |||
50 | return 1; | 53 | return 1; |
51 | } | 54 | } |
52 | 55 | ||
53 | static struct ipt_match mark_match = { | 56 | static struct xt_match mark_match = { |
57 | .name = "mark", | ||
58 | .match = &match, | ||
59 | .checkentry = &checkentry, | ||
60 | .me = THIS_MODULE, | ||
61 | }; | ||
62 | |||
63 | static struct xt_match mark6_match = { | ||
54 | .name = "mark", | 64 | .name = "mark", |
55 | .match = &match, | 65 | .match = &match, |
56 | .checkentry = &checkentry, | 66 | .checkentry = &checkentry, |
@@ -59,12 +69,22 @@ static struct ipt_match mark_match = { | |||
59 | 69 | ||
60 | static int __init init(void) | 70 | static int __init init(void) |
61 | { | 71 | { |
62 | return ipt_register_match(&mark_match); | 72 | int ret; |
73 | ret = xt_register_match(AF_INET, &mark_match); | ||
74 | if (ret) | ||
75 | return ret; | ||
76 | |||
77 | ret = xt_register_match(AF_INET6, &mark6_match); | ||
78 | if (ret) | ||
79 | xt_unregister_match(AF_INET, &mark_match); | ||
80 | |||
81 | return ret; | ||
63 | } | 82 | } |
64 | 83 | ||
65 | static void __exit fini(void) | 84 | static void __exit fini(void) |
66 | { | 85 | { |
67 | ipt_unregister_match(&mark_match); | 86 | xt_unregister_match(AF_INET, &mark_match); |
87 | xt_unregister_match(AF_INET6, &mark6_match); | ||
68 | } | 88 | } |
69 | 89 | ||
70 | module_init(init); | 90 | module_init(init); |
diff --git a/net/ipv6/netfilter/ip6t_physdev.c b/net/netfilter/xt_physdev.c index 71515c86ece1..19bb57c14dfe 100644 --- a/net/ipv6/netfilter/ip6t_physdev.c +++ b/net/netfilter/xt_physdev.c | |||
@@ -10,8 +10,8 @@ | |||
10 | 10 | ||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
13 | #include <linux/netfilter_ipv6/ip6t_physdev.h> | 13 | #include <linux/netfilter/xt_physdev.h> |
14 | #include <linux/netfilter_ipv6/ip6_tables.h> | 14 | #include <linux/netfilter/x_tables.h> |
15 | #include <linux/netfilter_bridge.h> | 15 | #include <linux/netfilter_bridge.h> |
16 | #define MATCH 1 | 16 | #define MATCH 1 |
17 | #define NOMATCH 0 | 17 | #define NOMATCH 0 |
@@ -19,6 +19,8 @@ | |||
19 | MODULE_LICENSE("GPL"); | 19 | MODULE_LICENSE("GPL"); |
20 | MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); | 20 | MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); |
21 | MODULE_DESCRIPTION("iptables bridge physical device match module"); | 21 | MODULE_DESCRIPTION("iptables bridge physical device match module"); |
22 | MODULE_ALIAS("ipt_physdev"); | ||
23 | MODULE_ALIAS("ip6t_physdev"); | ||
22 | 24 | ||
23 | static int | 25 | static int |
24 | match(const struct sk_buff *skb, | 26 | match(const struct sk_buff *skb, |
@@ -31,7 +33,7 @@ match(const struct sk_buff *skb, | |||
31 | { | 33 | { |
32 | int i; | 34 | int i; |
33 | static const char nulldevname[IFNAMSIZ]; | 35 | static const char nulldevname[IFNAMSIZ]; |
34 | const struct ip6t_physdev_info *info = matchinfo; | 36 | const struct xt_physdev_info *info = matchinfo; |
35 | unsigned int ret; | 37 | unsigned int ret; |
36 | const char *indev, *outdev; | 38 | const char *indev, *outdev; |
37 | struct nf_bridge_info *nf_bridge; | 39 | struct nf_bridge_info *nf_bridge; |
@@ -41,37 +43,37 @@ match(const struct sk_buff *skb, | |||
41 | * the destination device will be a bridge. */ | 43 | * the destination device will be a bridge. */ |
42 | if (!(nf_bridge = skb->nf_bridge)) { | 44 | if (!(nf_bridge = skb->nf_bridge)) { |
43 | /* Return MATCH if the invert flags of the used options are on */ | 45 | /* Return MATCH if the invert flags of the used options are on */ |
44 | if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) && | 46 | if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && |
45 | !(info->invert & IP6T_PHYSDEV_OP_BRIDGED)) | 47 | !(info->invert & XT_PHYSDEV_OP_BRIDGED)) |
46 | return NOMATCH; | 48 | return NOMATCH; |
47 | if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN) && | 49 | if ((info->bitmask & XT_PHYSDEV_OP_ISIN) && |
48 | !(info->invert & IP6T_PHYSDEV_OP_ISIN)) | 50 | !(info->invert & XT_PHYSDEV_OP_ISIN)) |
49 | return NOMATCH; | 51 | return NOMATCH; |
50 | if ((info->bitmask & IP6T_PHYSDEV_OP_ISOUT) && | 52 | if ((info->bitmask & XT_PHYSDEV_OP_ISOUT) && |
51 | !(info->invert & IP6T_PHYSDEV_OP_ISOUT)) | 53 | !(info->invert & XT_PHYSDEV_OP_ISOUT)) |
52 | return NOMATCH; | 54 | return NOMATCH; |
53 | if ((info->bitmask & IP6T_PHYSDEV_OP_IN) && | 55 | if ((info->bitmask & XT_PHYSDEV_OP_IN) && |
54 | !(info->invert & IP6T_PHYSDEV_OP_IN)) | 56 | !(info->invert & XT_PHYSDEV_OP_IN)) |
55 | return NOMATCH; | 57 | return NOMATCH; |
56 | if ((info->bitmask & IP6T_PHYSDEV_OP_OUT) && | 58 | if ((info->bitmask & XT_PHYSDEV_OP_OUT) && |
57 | !(info->invert & IP6T_PHYSDEV_OP_OUT)) | 59 | !(info->invert & XT_PHYSDEV_OP_OUT)) |
58 | return NOMATCH; | 60 | return NOMATCH; |
59 | return MATCH; | 61 | return MATCH; |
60 | } | 62 | } |
61 | 63 | ||
62 | /* This only makes sense in the FORWARD and POSTROUTING chains */ | 64 | /* This only makes sense in the FORWARD and POSTROUTING chains */ |
63 | if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) && | 65 | if ((info->bitmask & XT_PHYSDEV_OP_BRIDGED) && |
64 | (!!(nf_bridge->mask & BRNF_BRIDGED) ^ | 66 | (!!(nf_bridge->mask & BRNF_BRIDGED) ^ |
65 | !(info->invert & IP6T_PHYSDEV_OP_BRIDGED))) | 67 | !(info->invert & XT_PHYSDEV_OP_BRIDGED))) |
66 | return NOMATCH; | 68 | return NOMATCH; |
67 | 69 | ||
68 | if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN && | 70 | if ((info->bitmask & XT_PHYSDEV_OP_ISIN && |
69 | (!nf_bridge->physindev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISIN))) || | 71 | (!nf_bridge->physindev ^ !!(info->invert & XT_PHYSDEV_OP_ISIN))) || |
70 | (info->bitmask & IP6T_PHYSDEV_OP_ISOUT && | 72 | (info->bitmask & XT_PHYSDEV_OP_ISOUT && |
71 | (!nf_bridge->physoutdev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISOUT)))) | 73 | (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT)))) |
72 | return NOMATCH; | 74 | return NOMATCH; |
73 | 75 | ||
74 | if (!(info->bitmask & IP6T_PHYSDEV_OP_IN)) | 76 | if (!(info->bitmask & XT_PHYSDEV_OP_IN)) |
75 | goto match_outdev; | 77 | goto match_outdev; |
76 | indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; | 78 | indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; |
77 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { | 79 | for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) { |
@@ -80,11 +82,11 @@ match(const struct sk_buff *skb, | |||
80 | & ((const unsigned int *)info->in_mask)[i]; | 82 | & ((const unsigned int *)info->in_mask)[i]; |
81 | } | 83 | } |
82 | 84 | ||
83 | if ((ret == 0) ^ !(info->invert & IP6T_PHYSDEV_OP_IN)) | 85 | if ((ret == 0) ^ !(info->invert & XT_PHYSDEV_OP_IN)) |
84 | return NOMATCH; | 86 | return NOMATCH; |
85 | 87 | ||
86 | match_outdev: | 88 | match_outdev: |
87 | if (!(info->bitmask & IP6T_PHYSDEV_OP_OUT)) | 89 | if (!(info->bitmask & XT_PHYSDEV_OP_OUT)) |
88 | return MATCH; | 90 | return MATCH; |
89 | outdev = nf_bridge->physoutdev ? | 91 | outdev = nf_bridge->physoutdev ? |
90 | nf_bridge->physoutdev->name : nulldevname; | 92 | nf_bridge->physoutdev->name : nulldevname; |
@@ -94,27 +96,34 @@ match_outdev: | |||
94 | & ((const unsigned int *)info->out_mask)[i]; | 96 | & ((const unsigned int *)info->out_mask)[i]; |
95 | } | 97 | } |
96 | 98 | ||
97 | return (ret != 0) ^ !(info->invert & IP6T_PHYSDEV_OP_OUT); | 99 | return (ret != 0) ^ !(info->invert & XT_PHYSDEV_OP_OUT); |
98 | } | 100 | } |
99 | 101 | ||
100 | static int | 102 | static int |
101 | checkentry(const char *tablename, | 103 | checkentry(const char *tablename, |
102 | const struct ip6t_ip6 *ip, | 104 | const void *ip, |
103 | void *matchinfo, | 105 | void *matchinfo, |
104 | unsigned int matchsize, | 106 | unsigned int matchsize, |
105 | unsigned int hook_mask) | 107 | unsigned int hook_mask) |
106 | { | 108 | { |
107 | const struct ip6t_physdev_info *info = matchinfo; | 109 | const struct xt_physdev_info *info = matchinfo; |
108 | 110 | ||
109 | if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_physdev_info))) | 111 | if (matchsize != XT_ALIGN(sizeof(struct xt_physdev_info))) |
110 | return 0; | 112 | return 0; |
111 | if (!(info->bitmask & IP6T_PHYSDEV_OP_MASK) || | 113 | if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || |
112 | info->bitmask & ~IP6T_PHYSDEV_OP_MASK) | 114 | info->bitmask & ~XT_PHYSDEV_OP_MASK) |
113 | return 0; | 115 | return 0; |
114 | return 1; | 116 | return 1; |
115 | } | 117 | } |
116 | 118 | ||
117 | static struct ip6t_match physdev_match = { | 119 | static struct xt_match physdev_match = { |
120 | .name = "physdev", | ||
121 | .match = &match, | ||
122 | .checkentry = &checkentry, | ||
123 | .me = THIS_MODULE, | ||
124 | }; | ||
125 | |||
126 | static struct xt_match physdev6_match = { | ||
118 | .name = "physdev", | 127 | .name = "physdev", |
119 | .match = &match, | 128 | .match = &match, |
120 | .checkentry = &checkentry, | 129 | .checkentry = &checkentry, |
@@ -123,12 +132,23 @@ static struct ip6t_match physdev_match = { | |||
123 | 132 | ||
124 | static int __init init(void) | 133 | static int __init init(void) |
125 | { | 134 | { |
126 | return ip6t_register_match(&physdev_match); | 135 | int ret; |
136 | |||
137 | ret = xt_register_match(AF_INET, &physdev_match); | ||
138 | if (ret < 0) | ||
139 | return ret; | ||
140 | |||
141 | ret = xt_register_match(AF_INET6, &physdev6_match); | ||
142 | if (ret < 0) | ||
143 | xt_unregister_match(AF_INET, &physdev_match); | ||
144 | |||
145 | return ret; | ||
127 | } | 146 | } |
128 | 147 | ||
129 | static void __exit fini(void) | 148 | static void __exit fini(void) |
130 | { | 149 | { |
131 | ip6t_unregister_match(&physdev_match); | 150 | xt_unregister_match(AF_INET, &physdev_match); |
151 | xt_unregister_match(AF_INET6, &physdev6_match); | ||
132 | } | 152 | } |
133 | 153 | ||
134 | module_init(init); | 154 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_pkttype.c b/net/netfilter/xt_pkttype.c index 8ddb1dc5e5ae..ab1b2630f97d 100644 --- a/net/ipv4/netfilter/ipt_pkttype.c +++ b/net/netfilter/xt_pkttype.c | |||
@@ -10,60 +10,72 @@ | |||
10 | #include <linux/if_ether.h> | 10 | #include <linux/if_ether.h> |
11 | #include <linux/if_packet.h> | 11 | #include <linux/if_packet.h> |
12 | 12 | ||
13 | #include <linux/netfilter_ipv4/ipt_pkttype.h> | 13 | #include <linux/netfilter/xt_pkttype.h> |
14 | #include <linux/netfilter_ipv4/ip_tables.h> | 14 | #include <linux/netfilter/x_tables.h> |
15 | 15 | ||
16 | MODULE_LICENSE("GPL"); | 16 | MODULE_LICENSE("GPL"); |
17 | MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>"); | 17 | MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>"); |
18 | MODULE_DESCRIPTION("IP tables match to match on linklayer packet type"); | 18 | MODULE_DESCRIPTION("IP tables match to match on linklayer packet type"); |
19 | MODULE_ALIAS("ipt_pkttype"); | ||
20 | MODULE_ALIAS("ip6t_pkttype"); | ||
19 | 21 | ||
20 | static int match(const struct sk_buff *skb, | 22 | static int match(const struct sk_buff *skb, |
21 | const struct net_device *in, | 23 | const struct net_device *in, |
22 | const struct net_device *out, | 24 | const struct net_device *out, |
23 | const void *matchinfo, | 25 | const void *matchinfo, |
24 | int offset, | 26 | int offset, |
27 | unsigned int protoff, | ||
25 | int *hotdrop) | 28 | int *hotdrop) |
26 | { | 29 | { |
27 | const struct ipt_pkttype_info *info = matchinfo; | 30 | const struct xt_pkttype_info *info = matchinfo; |
28 | 31 | ||
29 | return (skb->pkt_type == info->pkttype) ^ info->invert; | 32 | return (skb->pkt_type == info->pkttype) ^ info->invert; |
30 | } | 33 | } |
31 | 34 | ||
32 | static int checkentry(const char *tablename, | 35 | static int checkentry(const char *tablename, |
33 | const struct ipt_ip *ip, | 36 | const void *ip, |
34 | void *matchinfo, | 37 | void *matchinfo, |
35 | unsigned int matchsize, | 38 | unsigned int matchsize, |
36 | unsigned int hook_mask) | 39 | unsigned int hook_mask) |
37 | { | 40 | { |
38 | /* | 41 | if (matchsize != XT_ALIGN(sizeof(struct xt_pkttype_info))) |
39 | if (hook_mask | ||
40 | & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | ||
41 | | (1 << NF_IP_FORWARD))) { | ||
42 | printk("ipt_pkttype: only valid for PRE_ROUTING, LOCAL_IN or FORWARD.\n"); | ||
43 | return 0; | ||
44 | } | ||
45 | */ | ||
46 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_pkttype_info))) | ||
47 | return 0; | 42 | return 0; |
48 | 43 | ||
49 | return 1; | 44 | return 1; |
50 | } | 45 | } |
51 | 46 | ||
52 | static struct ipt_match pkttype_match = { | 47 | static struct xt_match pkttype_match = { |
53 | .name = "pkttype", | 48 | .name = "pkttype", |
54 | .match = &match, | 49 | .match = &match, |
55 | .checkentry = &checkentry, | 50 | .checkentry = &checkentry, |
56 | .me = THIS_MODULE, | 51 | .me = THIS_MODULE, |
57 | }; | 52 | }; |
53 | static struct xt_match pkttype6_match = { | ||
54 | .name = "pkttype", | ||
55 | .match = &match, | ||
56 | .checkentry = &checkentry, | ||
57 | .me = THIS_MODULE, | ||
58 | }; | ||
59 | |||
58 | 60 | ||
59 | static int __init init(void) | 61 | static int __init init(void) |
60 | { | 62 | { |
61 | return ipt_register_match(&pkttype_match); | 63 | int ret; |
64 | ret = xt_register_match(AF_INET, &pkttype_match); | ||
65 | if (ret) | ||
66 | return ret; | ||
67 | |||
68 | ret = xt_register_match(AF_INET6, &pkttype6_match); | ||
69 | if (ret) | ||
70 | xt_unregister_match(AF_INET, &pkttype_match); | ||
71 | |||
72 | return ret; | ||
62 | } | 73 | } |
63 | 74 | ||
64 | static void __exit fini(void) | 75 | static void __exit fini(void) |
65 | { | 76 | { |
66 | ipt_unregister_match(&pkttype_match); | 77 | xt_unregister_match(AF_INET, &pkttype_match); |
78 | xt_unregister_match(AF_INET6, &pkttype6_match); | ||
67 | } | 79 | } |
68 | 80 | ||
69 | module_init(init); | 81 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_realm.c b/net/netfilter/xt_realm.c index 54a6897ebaa6..2b7e1781d34d 100644 --- a/net/ipv4/netfilter/ipt_realm.c +++ b/net/netfilter/xt_realm.c | |||
@@ -14,12 +14,14 @@ | |||
14 | #include <linux/netdevice.h> | 14 | #include <linux/netdevice.h> |
15 | #include <net/route.h> | 15 | #include <net/route.h> |
16 | 16 | ||
17 | #include <linux/netfilter_ipv4/ipt_realm.h> | 17 | #include <linux/netfilter_ipv4.h> |
18 | #include <linux/netfilter_ipv4/ip_tables.h> | 18 | #include <linux/netfilter/xt_realm.h> |
19 | #include <linux/netfilter/x_tables.h> | ||
19 | 20 | ||
20 | MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>"); | 21 | MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>"); |
21 | MODULE_LICENSE("GPL"); | 22 | MODULE_LICENSE("GPL"); |
22 | MODULE_DESCRIPTION("iptables realm match"); | 23 | MODULE_DESCRIPTION("X_tables realm match"); |
24 | MODULE_ALIAS("ipt_realm"); | ||
23 | 25 | ||
24 | static int | 26 | static int |
25 | match(const struct sk_buff *skb, | 27 | match(const struct sk_buff *skb, |
@@ -27,16 +29,17 @@ match(const struct sk_buff *skb, | |||
27 | const struct net_device *out, | 29 | const struct net_device *out, |
28 | const void *matchinfo, | 30 | const void *matchinfo, |
29 | int offset, | 31 | int offset, |
32 | unsigned int protoff, | ||
30 | int *hotdrop) | 33 | int *hotdrop) |
31 | { | 34 | { |
32 | const struct ipt_realm_info *info = matchinfo; | 35 | const struct xt_realm_info *info = matchinfo; |
33 | struct dst_entry *dst = skb->dst; | 36 | struct dst_entry *dst = skb->dst; |
34 | 37 | ||
35 | return (info->id == (dst->tclassid & info->mask)) ^ info->invert; | 38 | return (info->id == (dst->tclassid & info->mask)) ^ info->invert; |
36 | } | 39 | } |
37 | 40 | ||
38 | static int check(const char *tablename, | 41 | static int check(const char *tablename, |
39 | const struct ipt_ip *ip, | 42 | const void *ip, |
40 | void *matchinfo, | 43 | void *matchinfo, |
41 | unsigned int matchsize, | 44 | unsigned int matchsize, |
42 | unsigned int hook_mask) | 45 | unsigned int hook_mask) |
@@ -44,18 +47,18 @@ static int check(const char *tablename, | |||
44 | if (hook_mask | 47 | if (hook_mask |
45 | & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) | | 48 | & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) | |
46 | (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) { | 49 | (1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_LOCAL_IN))) { |
47 | printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, " | 50 | printk("xt_realm: only valid for POST_ROUTING, LOCAL_OUT, " |
48 | "LOCAL_IN or FORWARD.\n"); | 51 | "LOCAL_IN or FORWARD.\n"); |
49 | return 0; | 52 | return 0; |
50 | } | 53 | } |
51 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info))) { | 54 | if (matchsize != XT_ALIGN(sizeof(struct xt_realm_info))) { |
52 | printk("ipt_realm: invalid matchsize.\n"); | 55 | printk("xt_realm: invalid matchsize.\n"); |
53 | return 0; | 56 | return 0; |
54 | } | 57 | } |
55 | return 1; | 58 | return 1; |
56 | } | 59 | } |
57 | 60 | ||
58 | static struct ipt_match realm_match = { | 61 | static struct xt_match realm_match = { |
59 | .name = "realm", | 62 | .name = "realm", |
60 | .match = match, | 63 | .match = match, |
61 | .checkentry = check, | 64 | .checkentry = check, |
@@ -64,12 +67,12 @@ static struct ipt_match realm_match = { | |||
64 | 67 | ||
65 | static int __init init(void) | 68 | static int __init init(void) |
66 | { | 69 | { |
67 | return ipt_register_match(&realm_match); | 70 | return xt_register_match(AF_INET, &realm_match); |
68 | } | 71 | } |
69 | 72 | ||
70 | static void __exit fini(void) | 73 | static void __exit fini(void) |
71 | { | 74 | { |
72 | ipt_unregister_match(&realm_match); | 75 | xt_unregister_match(AF_INET, &realm_match); |
73 | } | 76 | } |
74 | 77 | ||
75 | module_init(init); | 78 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_sctp.c b/net/netfilter/xt_sctp.c index fe2b327bcaa4..10fbfc5ba758 100644 --- a/net/ipv4/netfilter/ipt_sctp.c +++ b/net/netfilter/xt_sctp.c | |||
@@ -1,10 +1,18 @@ | |||
1 | #include <linux/module.h> | 1 | #include <linux/module.h> |
2 | #include <linux/skbuff.h> | 2 | #include <linux/skbuff.h> |
3 | #include <net/ip.h> | 3 | #include <net/ip.h> |
4 | #include <net/ipv6.h> | ||
4 | #include <linux/sctp.h> | 5 | #include <linux/sctp.h> |
5 | 6 | ||
7 | #include <linux/netfilter/x_tables.h> | ||
8 | #include <linux/netfilter/xt_sctp.h> | ||
6 | #include <linux/netfilter_ipv4/ip_tables.h> | 9 | #include <linux/netfilter_ipv4/ip_tables.h> |
7 | #include <linux/netfilter_ipv4/ipt_sctp.h> | 10 | #include <linux/netfilter_ipv6/ip6_tables.h> |
11 | |||
12 | MODULE_LICENSE("GPL"); | ||
13 | MODULE_AUTHOR("Kiran Kumar Immidi"); | ||
14 | MODULE_DESCRIPTION("Match for SCTP protocol packets"); | ||
15 | MODULE_ALIAS("ipt_sctp"); | ||
8 | 16 | ||
9 | #ifdef DEBUG_SCTP | 17 | #ifdef DEBUG_SCTP |
10 | #define duprintf(format, args...) printk(format , ## args) | 18 | #define duprintf(format, args...) printk(format , ## args) |
@@ -16,7 +24,7 @@ | |||
16 | || (!!((invflag) & (option)) ^ (cond))) | 24 | || (!!((invflag) & (option)) ^ (cond))) |
17 | 25 | ||
18 | static int | 26 | static int |
19 | match_flags(const struct ipt_sctp_flag_info *flag_info, | 27 | match_flags(const struct xt_sctp_flag_info *flag_info, |
20 | const int flag_count, | 28 | const int flag_count, |
21 | u_int8_t chunktype, | 29 | u_int8_t chunktype, |
22 | u_int8_t chunkflags) | 30 | u_int8_t chunkflags) |
@@ -32,15 +40,15 @@ match_flags(const struct ipt_sctp_flag_info *flag_info, | |||
32 | return 1; | 40 | return 1; |
33 | } | 41 | } |
34 | 42 | ||
35 | static int | 43 | static inline int |
36 | match_packet(const struct sk_buff *skb, | 44 | match_packet(const struct sk_buff *skb, |
45 | unsigned int offset, | ||
37 | const u_int32_t *chunkmap, | 46 | const u_int32_t *chunkmap, |
38 | int chunk_match_type, | 47 | int chunk_match_type, |
39 | const struct ipt_sctp_flag_info *flag_info, | 48 | const struct xt_sctp_flag_info *flag_info, |
40 | const int flag_count, | 49 | const int flag_count, |
41 | int *hotdrop) | 50 | int *hotdrop) |
42 | { | 51 | { |
43 | int offset; | ||
44 | u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)]; | 52 | u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)]; |
45 | sctp_chunkhdr_t _sch, *sch; | 53 | sctp_chunkhdr_t _sch, *sch; |
46 | 54 | ||
@@ -52,7 +60,6 @@ match_packet(const struct sk_buff *skb, | |||
52 | SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap); | 60 | SCTP_CHUNKMAP_COPY(chunkmapcopy, chunkmap); |
53 | } | 61 | } |
54 | 62 | ||
55 | offset = skb->nh.iph->ihl * 4 + sizeof (sctp_sctphdr_t); | ||
56 | do { | 63 | do { |
57 | sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); | 64 | sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); |
58 | if (sch == NULL) { | 65 | if (sch == NULL) { |
@@ -118,19 +125,20 @@ match(const struct sk_buff *skb, | |||
118 | const struct net_device *out, | 125 | const struct net_device *out, |
119 | const void *matchinfo, | 126 | const void *matchinfo, |
120 | int offset, | 127 | int offset, |
128 | unsigned int protoff, | ||
121 | int *hotdrop) | 129 | int *hotdrop) |
122 | { | 130 | { |
123 | const struct ipt_sctp_info *info; | 131 | const struct xt_sctp_info *info; |
124 | sctp_sctphdr_t _sh, *sh; | 132 | sctp_sctphdr_t _sh, *sh; |
125 | 133 | ||
126 | info = (const struct ipt_sctp_info *)matchinfo; | 134 | info = (const struct xt_sctp_info *)matchinfo; |
127 | 135 | ||
128 | if (offset) { | 136 | if (offset) { |
129 | duprintf("Dropping non-first fragment.. FIXME\n"); | 137 | duprintf("Dropping non-first fragment.. FIXME\n"); |
130 | return 0; | 138 | return 0; |
131 | } | 139 | } |
132 | 140 | ||
133 | sh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_sh), &_sh); | 141 | sh = skb_header_pointer(skb, protoff, sizeof(_sh), &_sh); |
134 | if (sh == NULL) { | 142 | if (sh == NULL) { |
135 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); | 143 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); |
136 | *hotdrop = 1; | 144 | *hotdrop = 1; |
@@ -140,64 +148,103 @@ match(const struct sk_buff *skb, | |||
140 | 148 | ||
141 | return SCCHECK(((ntohs(sh->source) >= info->spts[0]) | 149 | return SCCHECK(((ntohs(sh->source) >= info->spts[0]) |
142 | && (ntohs(sh->source) <= info->spts[1])), | 150 | && (ntohs(sh->source) <= info->spts[1])), |
143 | IPT_SCTP_SRC_PORTS, info->flags, info->invflags) | 151 | XT_SCTP_SRC_PORTS, info->flags, info->invflags) |
144 | && SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) | 152 | && SCCHECK(((ntohs(sh->dest) >= info->dpts[0]) |
145 | && (ntohs(sh->dest) <= info->dpts[1])), | 153 | && (ntohs(sh->dest) <= info->dpts[1])), |
146 | IPT_SCTP_DEST_PORTS, info->flags, info->invflags) | 154 | XT_SCTP_DEST_PORTS, info->flags, info->invflags) |
147 | && SCCHECK(match_packet(skb, info->chunkmap, info->chunk_match_type, | 155 | && SCCHECK(match_packet(skb, protoff, |
156 | info->chunkmap, info->chunk_match_type, | ||
148 | info->flag_info, info->flag_count, | 157 | info->flag_info, info->flag_count, |
149 | hotdrop), | 158 | hotdrop), |
150 | IPT_SCTP_CHUNK_TYPES, info->flags, info->invflags); | 159 | XT_SCTP_CHUNK_TYPES, info->flags, info->invflags); |
151 | } | 160 | } |
152 | 161 | ||
153 | static int | 162 | static int |
154 | checkentry(const char *tablename, | 163 | checkentry(const char *tablename, |
155 | const struct ipt_ip *ip, | 164 | const void *inf, |
165 | void *matchinfo, | ||
166 | unsigned int matchsize, | ||
167 | unsigned int hook_mask) | ||
168 | { | ||
169 | const struct xt_sctp_info *info; | ||
170 | const struct ipt_ip *ip = inf; | ||
171 | |||
172 | info = (const struct xt_sctp_info *)matchinfo; | ||
173 | |||
174 | return ip->proto == IPPROTO_SCTP | ||
175 | && !(ip->invflags & XT_INV_PROTO) | ||
176 | && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info)) | ||
177 | && !(info->flags & ~XT_SCTP_VALID_FLAGS) | ||
178 | && !(info->invflags & ~XT_SCTP_VALID_FLAGS) | ||
179 | && !(info->invflags & ~info->flags) | ||
180 | && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) || | ||
181 | (info->chunk_match_type & | ||
182 | (SCTP_CHUNK_MATCH_ALL | ||
183 | | SCTP_CHUNK_MATCH_ANY | ||
184 | | SCTP_CHUNK_MATCH_ONLY))); | ||
185 | } | ||
186 | |||
187 | static int | ||
188 | checkentry6(const char *tablename, | ||
189 | const void *inf, | ||
156 | void *matchinfo, | 190 | void *matchinfo, |
157 | unsigned int matchsize, | 191 | unsigned int matchsize, |
158 | unsigned int hook_mask) | 192 | unsigned int hook_mask) |
159 | { | 193 | { |
160 | const struct ipt_sctp_info *info; | 194 | const struct xt_sctp_info *info; |
195 | const struct ip6t_ip6 *ip = inf; | ||
161 | 196 | ||
162 | info = (const struct ipt_sctp_info *)matchinfo; | 197 | info = (const struct xt_sctp_info *)matchinfo; |
163 | 198 | ||
164 | return ip->proto == IPPROTO_SCTP | 199 | return ip->proto == IPPROTO_SCTP |
165 | && !(ip->invflags & IPT_INV_PROTO) | 200 | && !(ip->invflags & XT_INV_PROTO) |
166 | && matchsize == IPT_ALIGN(sizeof(struct ipt_sctp_info)) | 201 | && matchsize == XT_ALIGN(sizeof(struct xt_sctp_info)) |
167 | && !(info->flags & ~IPT_SCTP_VALID_FLAGS) | 202 | && !(info->flags & ~XT_SCTP_VALID_FLAGS) |
168 | && !(info->invflags & ~IPT_SCTP_VALID_FLAGS) | 203 | && !(info->invflags & ~XT_SCTP_VALID_FLAGS) |
169 | && !(info->invflags & ~info->flags) | 204 | && !(info->invflags & ~info->flags) |
170 | && ((!(info->flags & IPT_SCTP_CHUNK_TYPES)) || | 205 | && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) || |
171 | (info->chunk_match_type & | 206 | (info->chunk_match_type & |
172 | (SCTP_CHUNK_MATCH_ALL | 207 | (SCTP_CHUNK_MATCH_ALL |
173 | | SCTP_CHUNK_MATCH_ANY | 208 | | SCTP_CHUNK_MATCH_ANY |
174 | | SCTP_CHUNK_MATCH_ONLY))); | 209 | | SCTP_CHUNK_MATCH_ONLY))); |
175 | } | 210 | } |
176 | 211 | ||
177 | static struct ipt_match sctp_match = | 212 | |
213 | static struct xt_match sctp_match = | ||
178 | { | 214 | { |
179 | .list = { NULL, NULL}, | ||
180 | .name = "sctp", | 215 | .name = "sctp", |
181 | .match = &match, | 216 | .match = &match, |
182 | .checkentry = &checkentry, | 217 | .checkentry = &checkentry, |
183 | .destroy = NULL, | 218 | .me = THIS_MODULE |
219 | }; | ||
220 | static struct xt_match sctp6_match = | ||
221 | { | ||
222 | .name = "sctp", | ||
223 | .match = &match, | ||
224 | .checkentry = &checkentry6, | ||
184 | .me = THIS_MODULE | 225 | .me = THIS_MODULE |
185 | }; | 226 | }; |
186 | 227 | ||
228 | |||
187 | static int __init init(void) | 229 | static int __init init(void) |
188 | { | 230 | { |
189 | return ipt_register_match(&sctp_match); | 231 | int ret; |
232 | ret = xt_register_match(AF_INET, &sctp_match); | ||
233 | if (ret) | ||
234 | return ret; | ||
235 | |||
236 | ret = xt_register_match(AF_INET6, &sctp6_match); | ||
237 | if (ret) | ||
238 | xt_unregister_match(AF_INET, &sctp_match); | ||
239 | |||
240 | return ret; | ||
190 | } | 241 | } |
191 | 242 | ||
192 | static void __exit fini(void) | 243 | static void __exit fini(void) |
193 | { | 244 | { |
194 | ipt_unregister_match(&sctp_match); | 245 | xt_unregister_match(AF_INET6, &sctp6_match); |
246 | xt_unregister_match(AF_INET, &sctp_match); | ||
195 | } | 247 | } |
196 | 248 | ||
197 | module_init(init); | 249 | module_init(init); |
198 | module_exit(fini); | 250 | module_exit(fini); |
199 | |||
200 | MODULE_LICENSE("GPL"); | ||
201 | MODULE_AUTHOR("Kiran Kumar Immidi"); | ||
202 | MODULE_DESCRIPTION("Match for SCTP protocol packets"); | ||
203 | |||
diff --git a/net/ipv4/netfilter/ipt_state.c b/net/netfilter/xt_state.c index 4d7f16b70cec..39ce808d40ef 100644 --- a/net/ipv4/netfilter/ipt_state.c +++ b/net/netfilter/xt_state.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* Kernel module to match connection tracking information. */ | 1 | /* Kernel module to match connection tracking information. */ |
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-2005 Netfilter Core Team <coreteam@netfilter.org> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
@@ -11,12 +11,14 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
13 | #include <net/netfilter/nf_conntrack_compat.h> | 13 | #include <net/netfilter/nf_conntrack_compat.h> |
14 | #include <linux/netfilter_ipv4/ip_tables.h> | 14 | #include <linux/netfilter/x_tables.h> |
15 | #include <linux/netfilter_ipv4/ipt_state.h> | 15 | #include <linux/netfilter/xt_state.h> |
16 | 16 | ||
17 | MODULE_LICENSE("GPL"); | 17 | MODULE_LICENSE("GPL"); |
18 | MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>"); | 18 | MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>"); |
19 | MODULE_DESCRIPTION("iptables connection tracking state match module"); | 19 | MODULE_DESCRIPTION("ip[6]_tables connection tracking state match module"); |
20 | MODULE_ALIAS("ipt_state"); | ||
21 | MODULE_ALIAS("ip6t_state"); | ||
20 | 22 | ||
21 | static int | 23 | static int |
22 | match(const struct sk_buff *skb, | 24 | match(const struct sk_buff *skb, |
@@ -24,35 +26,43 @@ match(const struct sk_buff *skb, | |||
24 | const struct net_device *out, | 26 | const struct net_device *out, |
25 | const void *matchinfo, | 27 | const void *matchinfo, |
26 | int offset, | 28 | int offset, |
29 | unsigned int protoff, | ||
27 | int *hotdrop) | 30 | int *hotdrop) |
28 | { | 31 | { |
29 | const struct ipt_state_info *sinfo = matchinfo; | 32 | const struct xt_state_info *sinfo = matchinfo; |
30 | enum ip_conntrack_info ctinfo; | 33 | enum ip_conntrack_info ctinfo; |
31 | unsigned int statebit; | 34 | unsigned int statebit; |
32 | 35 | ||
33 | if (nf_ct_is_untracked(skb)) | 36 | if (nf_ct_is_untracked(skb)) |
34 | statebit = IPT_STATE_UNTRACKED; | 37 | statebit = XT_STATE_UNTRACKED; |
35 | else if (!nf_ct_get_ctinfo(skb, &ctinfo)) | 38 | else if (!nf_ct_get_ctinfo(skb, &ctinfo)) |
36 | statebit = IPT_STATE_INVALID; | 39 | statebit = XT_STATE_INVALID; |
37 | else | 40 | else |
38 | statebit = IPT_STATE_BIT(ctinfo); | 41 | statebit = XT_STATE_BIT(ctinfo); |
39 | 42 | ||
40 | return (sinfo->statemask & statebit); | 43 | return (sinfo->statemask & statebit); |
41 | } | 44 | } |
42 | 45 | ||
43 | static int check(const char *tablename, | 46 | static int check(const char *tablename, |
44 | const struct ipt_ip *ip, | 47 | const void *ip, |
45 | void *matchinfo, | 48 | void *matchinfo, |
46 | unsigned int matchsize, | 49 | unsigned int matchsize, |
47 | unsigned int hook_mask) | 50 | unsigned int hook_mask) |
48 | { | 51 | { |
49 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_state_info))) | 52 | if (matchsize != XT_ALIGN(sizeof(struct xt_state_info))) |
50 | return 0; | 53 | return 0; |
51 | 54 | ||
52 | return 1; | 55 | return 1; |
53 | } | 56 | } |
54 | 57 | ||
55 | static struct ipt_match state_match = { | 58 | static struct xt_match state_match = { |
59 | .name = "state", | ||
60 | .match = &match, | ||
61 | .checkentry = &check, | ||
62 | .me = THIS_MODULE, | ||
63 | }; | ||
64 | |||
65 | static struct xt_match state6_match = { | ||
56 | .name = "state", | 66 | .name = "state", |
57 | .match = &match, | 67 | .match = &match, |
58 | .checkentry = &check, | 68 | .checkentry = &check, |
@@ -61,13 +71,25 @@ static struct ipt_match state_match = { | |||
61 | 71 | ||
62 | static int __init init(void) | 72 | static int __init init(void) |
63 | { | 73 | { |
64 | need_ip_conntrack(); | 74 | int ret; |
65 | return ipt_register_match(&state_match); | 75 | |
76 | need_conntrack(); | ||
77 | |||
78 | ret = xt_register_match(AF_INET, &state_match); | ||
79 | if (ret < 0) | ||
80 | return ret; | ||
81 | |||
82 | ret = xt_register_match(AF_INET6, &state6_match); | ||
83 | if (ret < 0) | ||
84 | xt_unregister_match(AF_INET,&state_match); | ||
85 | |||
86 | return ret; | ||
66 | } | 87 | } |
67 | 88 | ||
68 | static void __exit fini(void) | 89 | static void __exit fini(void) |
69 | { | 90 | { |
70 | ipt_unregister_match(&state_match); | 91 | xt_unregister_match(AF_INET, &state_match); |
92 | xt_unregister_match(AF_INET6, &state6_match); | ||
71 | } | 93 | } |
72 | 94 | ||
73 | module_init(init); | 95 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_string.c b/net/netfilter/xt_string.c index b5def204d798..7c7d5c8807d6 100644 --- a/net/ipv4/netfilter/ipt_string.c +++ b/net/netfilter/xt_string.c | |||
@@ -11,23 +11,26 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/skbuff.h> | 13 | #include <linux/skbuff.h> |
14 | #include <linux/netfilter_ipv4/ip_tables.h> | 14 | #include <linux/netfilter/x_tables.h> |
15 | #include <linux/netfilter_ipv4/ipt_string.h> | 15 | #include <linux/netfilter/xt_string.h> |
16 | #include <linux/textsearch.h> | 16 | #include <linux/textsearch.h> |
17 | 17 | ||
18 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>"); | 18 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>"); |
19 | MODULE_DESCRIPTION("IP tables string match module"); | 19 | MODULE_DESCRIPTION("IP tables string match module"); |
20 | MODULE_LICENSE("GPL"); | 20 | MODULE_LICENSE("GPL"); |
21 | MODULE_ALIAS("ipt_string"); | ||
22 | MODULE_ALIAS("ip6t_string"); | ||
21 | 23 | ||
22 | static int match(const struct sk_buff *skb, | 24 | static int match(const struct sk_buff *skb, |
23 | const struct net_device *in, | 25 | const struct net_device *in, |
24 | const struct net_device *out, | 26 | const struct net_device *out, |
25 | const void *matchinfo, | 27 | const void *matchinfo, |
26 | int offset, | 28 | int offset, |
29 | unsigned int protoff, | ||
27 | int *hotdrop) | 30 | int *hotdrop) |
28 | { | 31 | { |
29 | struct ts_state state; | 32 | struct ts_state state; |
30 | struct ipt_string_info *conf = (struct ipt_string_info *) matchinfo; | 33 | struct xt_string_info *conf = (struct xt_string_info *) matchinfo; |
31 | 34 | ||
32 | memset(&state, 0, sizeof(struct ts_state)); | 35 | memset(&state, 0, sizeof(struct ts_state)); |
33 | 36 | ||
@@ -36,18 +39,18 @@ static int match(const struct sk_buff *skb, | |||
36 | != UINT_MAX) && !conf->invert; | 39 | != UINT_MAX) && !conf->invert; |
37 | } | 40 | } |
38 | 41 | ||
39 | #define STRING_TEXT_PRIV(m) ((struct ipt_string_info *) m) | 42 | #define STRING_TEXT_PRIV(m) ((struct xt_string_info *) m) |
40 | 43 | ||
41 | static int checkentry(const char *tablename, | 44 | static int checkentry(const char *tablename, |
42 | const struct ipt_ip *ip, | 45 | const void *ip, |
43 | void *matchinfo, | 46 | void *matchinfo, |
44 | unsigned int matchsize, | 47 | unsigned int matchsize, |
45 | unsigned int hook_mask) | 48 | unsigned int hook_mask) |
46 | { | 49 | { |
47 | struct ipt_string_info *conf = matchinfo; | 50 | struct xt_string_info *conf = matchinfo; |
48 | struct ts_config *ts_conf; | 51 | struct ts_config *ts_conf; |
49 | 52 | ||
50 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info))) | 53 | if (matchsize != XT_ALIGN(sizeof(struct xt_string_info))) |
51 | return 0; | 54 | return 0; |
52 | 55 | ||
53 | /* Damn, can't handle this case properly with iptables... */ | 56 | /* Damn, can't handle this case properly with iptables... */ |
@@ -69,7 +72,14 @@ static void destroy(void *matchinfo, unsigned int matchsize) | |||
69 | textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config); | 72 | textsearch_destroy(STRING_TEXT_PRIV(matchinfo)->config); |
70 | } | 73 | } |
71 | 74 | ||
72 | static struct ipt_match string_match = { | 75 | static struct xt_match string_match = { |
76 | .name = "string", | ||
77 | .match = match, | ||
78 | .checkentry = checkentry, | ||
79 | .destroy = destroy, | ||
80 | .me = THIS_MODULE | ||
81 | }; | ||
82 | static struct xt_match string6_match = { | ||
73 | .name = "string", | 83 | .name = "string", |
74 | .match = match, | 84 | .match = match, |
75 | .checkentry = checkentry, | 85 | .checkentry = checkentry, |
@@ -79,12 +89,22 @@ static struct ipt_match string_match = { | |||
79 | 89 | ||
80 | static int __init init(void) | 90 | static int __init init(void) |
81 | { | 91 | { |
82 | return ipt_register_match(&string_match); | 92 | int ret; |
93 | |||
94 | ret = xt_register_match(AF_INET, &string_match); | ||
95 | if (ret) | ||
96 | return ret; | ||
97 | ret = xt_register_match(AF_INET6, &string6_match); | ||
98 | if (ret) | ||
99 | xt_unregister_match(AF_INET, &string_match); | ||
100 | |||
101 | return ret; | ||
83 | } | 102 | } |
84 | 103 | ||
85 | static void __exit fini(void) | 104 | static void __exit fini(void) |
86 | { | 105 | { |
87 | ipt_unregister_match(&string_match); | 106 | xt_unregister_match(AF_INET, &string_match); |
107 | xt_unregister_match(AF_INET6, &string6_match); | ||
88 | } | 108 | } |
89 | 109 | ||
90 | module_init(init); | 110 | module_init(init); |
diff --git a/net/ipv4/netfilter/ipt_tcpmss.c b/net/netfilter/xt_tcpmss.c index 4dc9b16ab4a3..acf7f533e9f1 100644 --- a/net/ipv4/netfilter/ipt_tcpmss.c +++ b/net/netfilter/xt_tcpmss.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* Kernel module to match TCP MSS values. */ | 1 | /* Kernel module to match TCP MSS values. */ |
2 | 2 | ||
3 | /* Copyright (C) 2000 Marc Boucher <marc@mbsi.ca> | 3 | /* Copyright (C) 2000 Marc Boucher <marc@mbsi.ca> |
4 | * Portions (C) 2005 by Harald Welte <laforge@netfilter.org> | ||
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
@@ -11,19 +12,24 @@ | |||
11 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
12 | #include <net/tcp.h> | 13 | #include <net/tcp.h> |
13 | 14 | ||
14 | #include <linux/netfilter_ipv4/ipt_tcpmss.h> | 15 | #include <linux/netfilter/xt_tcpmss.h> |
16 | #include <linux/netfilter/x_tables.h> | ||
17 | |||
15 | #include <linux/netfilter_ipv4/ip_tables.h> | 18 | #include <linux/netfilter_ipv4/ip_tables.h> |
19 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
16 | 20 | ||
17 | #define TH_SYN 0x02 | 21 | #define TH_SYN 0x02 |
18 | 22 | ||
19 | MODULE_LICENSE("GPL"); | 23 | MODULE_LICENSE("GPL"); |
20 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); | 24 | MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); |
21 | MODULE_DESCRIPTION("iptables TCP MSS match module"); | 25 | MODULE_DESCRIPTION("iptables TCP MSS match module"); |
26 | MODULE_ALIAS("ipt_tcpmss"); | ||
22 | 27 | ||
23 | /* Returns 1 if the mss option is set and matched by the range, 0 otherwise */ | 28 | /* Returns 1 if the mss option is set and matched by the range, 0 otherwise */ |
24 | static inline int | 29 | static inline int |
25 | mssoption_match(u_int16_t min, u_int16_t max, | 30 | mssoption_match(u_int16_t min, u_int16_t max, |
26 | const struct sk_buff *skb, | 31 | const struct sk_buff *skb, |
32 | unsigned int protoff, | ||
27 | int invert, | 33 | int invert, |
28 | int *hotdrop) | 34 | int *hotdrop) |
29 | { | 35 | { |
@@ -33,8 +39,7 @@ mssoption_match(u_int16_t min, u_int16_t max, | |||
33 | unsigned int i, optlen; | 39 | unsigned int i, optlen; |
34 | 40 | ||
35 | /* If we don't have the whole header, drop packet. */ | 41 | /* If we don't have the whole header, drop packet. */ |
36 | th = skb_header_pointer(skb, skb->nh.iph->ihl * 4, | 42 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); |
37 | sizeof(_tcph), &_tcph); | ||
38 | if (th == NULL) | 43 | if (th == NULL) |
39 | goto dropit; | 44 | goto dropit; |
40 | 45 | ||
@@ -47,8 +52,7 @@ mssoption_match(u_int16_t min, u_int16_t max, | |||
47 | goto out; | 52 | goto out; |
48 | 53 | ||
49 | /* Truncated options. */ | 54 | /* Truncated options. */ |
50 | op = skb_header_pointer(skb, skb->nh.iph->ihl * 4 + sizeof(*th), | 55 | op = skb_header_pointer(skb, protoff + sizeof(*th), optlen, _opt); |
51 | optlen, _opt); | ||
52 | if (op == NULL) | 56 | if (op == NULL) |
53 | goto dropit; | 57 | goto dropit; |
54 | 58 | ||
@@ -79,22 +83,24 @@ match(const struct sk_buff *skb, | |||
79 | const struct net_device *out, | 83 | const struct net_device *out, |
80 | const void *matchinfo, | 84 | const void *matchinfo, |
81 | int offset, | 85 | int offset, |
86 | unsigned int protoff, | ||
82 | int *hotdrop) | 87 | int *hotdrop) |
83 | { | 88 | { |
84 | const struct ipt_tcpmss_match_info *info = matchinfo; | 89 | const struct xt_tcpmss_match_info *info = matchinfo; |
85 | 90 | ||
86 | return mssoption_match(info->mss_min, info->mss_max, skb, | 91 | return mssoption_match(info->mss_min, info->mss_max, skb, protoff, |
87 | info->invert, hotdrop); | 92 | info->invert, hotdrop); |
88 | } | 93 | } |
89 | 94 | ||
90 | static int | 95 | static int |
91 | checkentry(const char *tablename, | 96 | checkentry(const char *tablename, |
92 | const struct ipt_ip *ip, | 97 | const void *ipinfo, |
93 | void *matchinfo, | 98 | void *matchinfo, |
94 | unsigned int matchsize, | 99 | unsigned int matchsize, |
95 | unsigned int hook_mask) | 100 | unsigned int hook_mask) |
96 | { | 101 | { |
97 | if (matchsize != IPT_ALIGN(sizeof(struct ipt_tcpmss_match_info))) | 102 | const struct ipt_ip *ip = ipinfo; |
103 | if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info))) | ||
98 | return 0; | 104 | return 0; |
99 | 105 | ||
100 | /* Must specify -p tcp */ | 106 | /* Must specify -p tcp */ |
@@ -106,21 +112,60 @@ checkentry(const char *tablename, | |||
106 | return 1; | 112 | return 1; |
107 | } | 113 | } |
108 | 114 | ||
109 | static struct ipt_match tcpmss_match = { | 115 | static int |
116 | checkentry6(const char *tablename, | ||
117 | const void *ipinfo, | ||
118 | void *matchinfo, | ||
119 | unsigned int matchsize, | ||
120 | unsigned int hook_mask) | ||
121 | { | ||
122 | const struct ip6t_ip6 *ip = ipinfo; | ||
123 | |||
124 | if (matchsize != XT_ALIGN(sizeof(struct xt_tcpmss_match_info))) | ||
125 | return 0; | ||
126 | |||
127 | /* Must specify -p tcp */ | ||
128 | if (ip->proto != IPPROTO_TCP || (ip->invflags & XT_INV_PROTO)) { | ||
129 | printk("tcpmss: Only works on TCP packets\n"); | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | return 1; | ||
134 | } | ||
135 | |||
136 | static struct xt_match tcpmss_match = { | ||
110 | .name = "tcpmss", | 137 | .name = "tcpmss", |
111 | .match = &match, | 138 | .match = &match, |
112 | .checkentry = &checkentry, | 139 | .checkentry = &checkentry, |
113 | .me = THIS_MODULE, | 140 | .me = THIS_MODULE, |
114 | }; | 141 | }; |
115 | 142 | ||
143 | static struct xt_match tcpmss6_match = { | ||
144 | .name = "tcpmss", | ||
145 | .match = &match, | ||
146 | .checkentry = &checkentry6, | ||
147 | .me = THIS_MODULE, | ||
148 | }; | ||
149 | |||
150 | |||
116 | static int __init init(void) | 151 | static int __init init(void) |
117 | { | 152 | { |
118 | return ipt_register_match(&tcpmss_match); | 153 | int ret; |
154 | ret = xt_register_match(AF_INET, &tcpmss_match); | ||
155 | if (ret) | ||
156 | return ret; | ||
157 | |||
158 | ret = xt_register_match(AF_INET6, &tcpmss6_match); | ||
159 | if (ret) | ||
160 | xt_unregister_match(AF_INET, &tcpmss_match); | ||
161 | |||
162 | return ret; | ||
119 | } | 163 | } |
120 | 164 | ||
121 | static void __exit fini(void) | 165 | static void __exit fini(void) |
122 | { | 166 | { |
123 | ipt_unregister_match(&tcpmss_match); | 167 | xt_unregister_match(AF_INET6, &tcpmss6_match); |
168 | xt_unregister_match(AF_INET, &tcpmss_match); | ||
124 | } | 169 | } |
125 | 170 | ||
126 | module_init(init); | 171 | module_init(init); |
diff --git a/net/netfilter/xt_tcpudp.c b/net/netfilter/xt_tcpudp.c new file mode 100644 index 000000000000..33f86fd6f3e6 --- /dev/null +++ b/net/netfilter/xt_tcpudp.c | |||
@@ -0,0 +1,333 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/module.h> | ||
3 | #include <net/ip.h> | ||
4 | #include <net/ipv6.h> | ||
5 | #include <net/tcp.h> | ||
6 | #include <net/udp.h> | ||
7 | #include <linux/netfilter/x_tables.h> | ||
8 | #include <linux/netfilter/xt_tcpudp.h> | ||
9 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
10 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
11 | |||
12 | MODULE_DESCRIPTION("x_tables match for TCP and UDP, supports IPv4 and IPv6"); | ||
13 | MODULE_LICENSE("GPL"); | ||
14 | MODULE_ALIAS("xt_tcp"); | ||
15 | MODULE_ALIAS("xt_udp"); | ||
16 | MODULE_ALIAS("ipt_udp"); | ||
17 | MODULE_ALIAS("ipt_tcp"); | ||
18 | MODULE_ALIAS("ip6t_udp"); | ||
19 | MODULE_ALIAS("ip6t_tcp"); | ||
20 | |||
21 | #ifdef DEBUG_IP_FIREWALL_USER | ||
22 | #define duprintf(format, args...) printk(format , ## args) | ||
23 | #else | ||
24 | #define duprintf(format, args...) | ||
25 | #endif | ||
26 | |||
27 | |||
28 | /* Returns 1 if the port is matched by the range, 0 otherwise */ | ||
29 | static inline int | ||
30 | port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert) | ||
31 | { | ||
32 | int ret; | ||
33 | |||
34 | ret = (port >= min && port <= max) ^ invert; | ||
35 | return ret; | ||
36 | } | ||
37 | |||
38 | static int | ||
39 | tcp_find_option(u_int8_t option, | ||
40 | const struct sk_buff *skb, | ||
41 | unsigned int protoff, | ||
42 | unsigned int optlen, | ||
43 | int invert, | ||
44 | int *hotdrop) | ||
45 | { | ||
46 | /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ | ||
47 | u_int8_t _opt[60 - sizeof(struct tcphdr)], *op; | ||
48 | unsigned int i; | ||
49 | |||
50 | duprintf("tcp_match: finding option\n"); | ||
51 | |||
52 | if (!optlen) | ||
53 | return invert; | ||
54 | |||
55 | /* If we don't have the whole header, drop packet. */ | ||
56 | op = skb_header_pointer(skb, protoff + sizeof(struct tcphdr), | ||
57 | optlen, _opt); | ||
58 | if (op == NULL) { | ||
59 | *hotdrop = 1; | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | for (i = 0; i < optlen; ) { | ||
64 | if (op[i] == option) return !invert; | ||
65 | if (op[i] < 2) i++; | ||
66 | else i += op[i+1]?:1; | ||
67 | } | ||
68 | |||
69 | return invert; | ||
70 | } | ||
71 | |||
72 | static int | ||
73 | tcp_match(const struct sk_buff *skb, | ||
74 | const struct net_device *in, | ||
75 | const struct net_device *out, | ||
76 | const void *matchinfo, | ||
77 | int offset, | ||
78 | unsigned int protoff, | ||
79 | int *hotdrop) | ||
80 | { | ||
81 | struct tcphdr _tcph, *th; | ||
82 | const struct xt_tcp *tcpinfo = matchinfo; | ||
83 | |||
84 | if (offset) { | ||
85 | /* To quote Alan: | ||
86 | |||
87 | Don't allow a fragment of TCP 8 bytes in. Nobody normal | ||
88 | causes this. Its a cracker trying to break in by doing a | ||
89 | flag overwrite to pass the direction checks. | ||
90 | */ | ||
91 | if (offset == 1) { | ||
92 | duprintf("Dropping evil TCP offset=1 frag.\n"); | ||
93 | *hotdrop = 1; | ||
94 | } | ||
95 | /* Must not be a fragment. */ | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | #define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg)) | ||
100 | |||
101 | th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); | ||
102 | if (th == NULL) { | ||
103 | /* We've been asked to examine this packet, and we | ||
104 | can't. Hence, no choice but to drop. */ | ||
105 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); | ||
106 | *hotdrop = 1; | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1], | ||
111 | ntohs(th->source), | ||
112 | !!(tcpinfo->invflags & XT_TCP_INV_SRCPT))) | ||
113 | return 0; | ||
114 | if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1], | ||
115 | ntohs(th->dest), | ||
116 | !!(tcpinfo->invflags & XT_TCP_INV_DSTPT))) | ||
117 | return 0; | ||
118 | if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask) | ||
119 | == tcpinfo->flg_cmp, | ||
120 | XT_TCP_INV_FLAGS)) | ||
121 | return 0; | ||
122 | if (tcpinfo->option) { | ||
123 | if (th->doff * 4 < sizeof(_tcph)) { | ||
124 | *hotdrop = 1; | ||
125 | return 0; | ||
126 | } | ||
127 | if (!tcp_find_option(tcpinfo->option, skb, protoff, | ||
128 | th->doff*4 - sizeof(_tcph), | ||
129 | tcpinfo->invflags & XT_TCP_INV_OPTION, | ||
130 | hotdrop)) | ||
131 | return 0; | ||
132 | } | ||
133 | return 1; | ||
134 | } | ||
135 | |||
136 | /* Called when user tries to insert an entry of this type. */ | ||
137 | static int | ||
138 | tcp_checkentry(const char *tablename, | ||
139 | const void *info, | ||
140 | void *matchinfo, | ||
141 | unsigned int matchsize, | ||
142 | unsigned int hook_mask) | ||
143 | { | ||
144 | const struct ipt_ip *ip = info; | ||
145 | const struct xt_tcp *tcpinfo = matchinfo; | ||
146 | |||
147 | /* Must specify proto == TCP, and no unknown invflags */ | ||
148 | return ip->proto == IPPROTO_TCP | ||
149 | && !(ip->invflags & XT_INV_PROTO) | ||
150 | && matchsize == XT_ALIGN(sizeof(struct xt_tcp)) | ||
151 | && !(tcpinfo->invflags & ~XT_TCP_INV_MASK); | ||
152 | } | ||
153 | |||
154 | /* Called when user tries to insert an entry of this type. */ | ||
155 | static int | ||
156 | tcp6_checkentry(const char *tablename, | ||
157 | const void *entry, | ||
158 | void *matchinfo, | ||
159 | unsigned int matchsize, | ||
160 | unsigned int hook_mask) | ||
161 | { | ||
162 | const struct ip6t_ip6 *ipv6 = entry; | ||
163 | const struct xt_tcp *tcpinfo = matchinfo; | ||
164 | |||
165 | /* Must specify proto == TCP, and no unknown invflags */ | ||
166 | return ipv6->proto == IPPROTO_TCP | ||
167 | && !(ipv6->invflags & XT_INV_PROTO) | ||
168 | && matchsize == XT_ALIGN(sizeof(struct xt_tcp)) | ||
169 | && !(tcpinfo->invflags & ~XT_TCP_INV_MASK); | ||
170 | } | ||
171 | |||
172 | |||
173 | static int | ||
174 | udp_match(const struct sk_buff *skb, | ||
175 | const struct net_device *in, | ||
176 | const struct net_device *out, | ||
177 | const void *matchinfo, | ||
178 | int offset, | ||
179 | unsigned int protoff, | ||
180 | int *hotdrop) | ||
181 | { | ||
182 | struct udphdr _udph, *uh; | ||
183 | const struct xt_udp *udpinfo = matchinfo; | ||
184 | |||
185 | /* Must not be a fragment. */ | ||
186 | if (offset) | ||
187 | return 0; | ||
188 | |||
189 | uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph); | ||
190 | if (uh == NULL) { | ||
191 | /* We've been asked to examine this packet, and we | ||
192 | can't. Hence, no choice but to drop. */ | ||
193 | duprintf("Dropping evil UDP tinygram.\n"); | ||
194 | *hotdrop = 1; | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | return port_match(udpinfo->spts[0], udpinfo->spts[1], | ||
199 | ntohs(uh->source), | ||
200 | !!(udpinfo->invflags & XT_UDP_INV_SRCPT)) | ||
201 | && port_match(udpinfo->dpts[0], udpinfo->dpts[1], | ||
202 | ntohs(uh->dest), | ||
203 | !!(udpinfo->invflags & XT_UDP_INV_DSTPT)); | ||
204 | } | ||
205 | |||
206 | /* Called when user tries to insert an entry of this type. */ | ||
207 | static int | ||
208 | udp_checkentry(const char *tablename, | ||
209 | const void *info, | ||
210 | void *matchinfo, | ||
211 | unsigned int matchinfosize, | ||
212 | unsigned int hook_mask) | ||
213 | { | ||
214 | const struct ipt_ip *ip = info; | ||
215 | const struct xt_udp *udpinfo = matchinfo; | ||
216 | |||
217 | /* Must specify proto == UDP, and no unknown invflags */ | ||
218 | if (ip->proto != IPPROTO_UDP || (ip->invflags & XT_INV_PROTO)) { | ||
219 | duprintf("ipt_udp: Protocol %u != %u\n", ip->proto, | ||
220 | IPPROTO_UDP); | ||
221 | return 0; | ||
222 | } | ||
223 | if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) { | ||
224 | duprintf("ipt_udp: matchsize %u != %u\n", | ||
225 | matchinfosize, XT_ALIGN(sizeof(struct xt_udp))); | ||
226 | return 0; | ||
227 | } | ||
228 | if (udpinfo->invflags & ~XT_UDP_INV_MASK) { | ||
229 | duprintf("ipt_udp: unknown flags %X\n", | ||
230 | udpinfo->invflags); | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | return 1; | ||
235 | } | ||
236 | |||
237 | /* Called when user tries to insert an entry of this type. */ | ||
238 | static int | ||
239 | udp6_checkentry(const char *tablename, | ||
240 | const void *entry, | ||
241 | void *matchinfo, | ||
242 | unsigned int matchinfosize, | ||
243 | unsigned int hook_mask) | ||
244 | { | ||
245 | const struct ip6t_ip6 *ipv6 = entry; | ||
246 | const struct xt_udp *udpinfo = matchinfo; | ||
247 | |||
248 | /* Must specify proto == UDP, and no unknown invflags */ | ||
249 | if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & XT_INV_PROTO)) { | ||
250 | duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto, | ||
251 | IPPROTO_UDP); | ||
252 | return 0; | ||
253 | } | ||
254 | if (matchinfosize != XT_ALIGN(sizeof(struct xt_udp))) { | ||
255 | duprintf("ip6t_udp: matchsize %u != %u\n", | ||
256 | matchinfosize, XT_ALIGN(sizeof(struct xt_udp))); | ||
257 | return 0; | ||
258 | } | ||
259 | if (udpinfo->invflags & ~XT_UDP_INV_MASK) { | ||
260 | duprintf("ip6t_udp: unknown flags %X\n", | ||
261 | udpinfo->invflags); | ||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | return 1; | ||
266 | } | ||
267 | |||
268 | static struct xt_match tcp_matchstruct = { | ||
269 | .name = "tcp", | ||
270 | .match = &tcp_match, | ||
271 | .checkentry = &tcp_checkentry, | ||
272 | .me = THIS_MODULE, | ||
273 | }; | ||
274 | static struct xt_match tcp6_matchstruct = { | ||
275 | .name = "tcp", | ||
276 | .match = &tcp_match, | ||
277 | .checkentry = &tcp6_checkentry, | ||
278 | .me = THIS_MODULE, | ||
279 | }; | ||
280 | |||
281 | static struct xt_match udp_matchstruct = { | ||
282 | .name = "udp", | ||
283 | .match = &udp_match, | ||
284 | .checkentry = &udp_checkentry, | ||
285 | .me = THIS_MODULE, | ||
286 | }; | ||
287 | static struct xt_match udp6_matchstruct = { | ||
288 | .name = "udp", | ||
289 | .match = &udp_match, | ||
290 | .checkentry = &udp6_checkentry, | ||
291 | .me = THIS_MODULE, | ||
292 | }; | ||
293 | |||
294 | static int __init init(void) | ||
295 | { | ||
296 | int ret; | ||
297 | ret = xt_register_match(AF_INET, &tcp_matchstruct); | ||
298 | if (ret) | ||
299 | return ret; | ||
300 | |||
301 | ret = xt_register_match(AF_INET6, &tcp6_matchstruct); | ||
302 | if (ret) | ||
303 | goto out_unreg_tcp; | ||
304 | |||
305 | ret = xt_register_match(AF_INET, &udp_matchstruct); | ||
306 | if (ret) | ||
307 | goto out_unreg_tcp6; | ||
308 | |||
309 | ret = xt_register_match(AF_INET6, &udp6_matchstruct); | ||
310 | if (ret) | ||
311 | goto out_unreg_udp; | ||
312 | |||
313 | return ret; | ||
314 | |||
315 | out_unreg_udp: | ||
316 | xt_unregister_match(AF_INET, &tcp_matchstruct); | ||
317 | out_unreg_tcp6: | ||
318 | xt_unregister_match(AF_INET6, &tcp6_matchstruct); | ||
319 | out_unreg_tcp: | ||
320 | xt_unregister_match(AF_INET, &tcp_matchstruct); | ||
321 | return ret; | ||
322 | } | ||
323 | |||
324 | static void __exit fini(void) | ||
325 | { | ||
326 | xt_unregister_match(AF_INET6, &udp6_matchstruct); | ||
327 | xt_unregister_match(AF_INET, &udp_matchstruct); | ||
328 | xt_unregister_match(AF_INET6, &tcp6_matchstruct); | ||
329 | xt_unregister_match(AF_INET, &tcp_matchstruct); | ||
330 | } | ||
331 | |||
332 | module_init(init); | ||
333 | module_exit(fini); | ||
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 3b1378498d50..4ae1538c54a9 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c | |||
@@ -222,11 +222,6 @@ int genl_register_family(struct genl_family *family) | |||
222 | goto errout_locked; | 222 | goto errout_locked; |
223 | } | 223 | } |
224 | 224 | ||
225 | if (!try_module_get(family->owner)) { | ||
226 | err = -EBUSY; | ||
227 | goto errout_locked; | ||
228 | } | ||
229 | |||
230 | if (family->id == GENL_ID_GENERATE) { | 225 | if (family->id == GENL_ID_GENERATE) { |
231 | u16 newid = genl_generate_id(); | 226 | u16 newid = genl_generate_id(); |
232 | 227 | ||
@@ -283,7 +278,6 @@ int genl_unregister_family(struct genl_family *family) | |||
283 | INIT_LIST_HEAD(&family->ops_list); | 278 | INIT_LIST_HEAD(&family->ops_list); |
284 | genl_unlock(); | 279 | genl_unlock(); |
285 | 280 | ||
286 | module_put(family->owner); | ||
287 | kfree(family->attrbuf); | 281 | kfree(family->attrbuf); |
288 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family); | 282 | genl_ctrl_event(CTRL_CMD_DELFAMILY, family); |
289 | return 0; | 283 | return 0; |
@@ -535,7 +529,6 @@ static struct genl_family genl_ctrl = { | |||
535 | .name = "nlctrl", | 529 | .name = "nlctrl", |
536 | .version = 0x1, | 530 | .version = 0x1, |
537 | .maxattr = CTRL_ATTR_MAX, | 531 | .maxattr = CTRL_ATTR_MAX, |
538 | .owner = THIS_MODULE, | ||
539 | }; | 532 | }; |
540 | 533 | ||
541 | static int __init genl_init(void) | 534 | static int __init genl_init(void) |
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index 8a260d43ceef..778b1e5a4b50 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
@@ -44,7 +44,7 @@ if NET_SCHED | |||
44 | 44 | ||
45 | choice | 45 | choice |
46 | prompt "Packet scheduler clock source" | 46 | prompt "Packet scheduler clock source" |
47 | default NET_SCH_CLK_JIFFIES | 47 | default NET_SCH_CLK_GETTIMEOFDAY |
48 | ---help--- | 48 | ---help--- |
49 | Packet schedulers need a monotonic clock that increments at a static | 49 | Packet schedulers need a monotonic clock that increments at a static |
50 | rate. The kernel provides several suitable interfaces, each with | 50 | rate. The kernel provides several suitable interfaces, each with |
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index b5001939b74b..39a22a3ffe78 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
@@ -62,7 +62,7 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) | |||
62 | struct ipt_target *target; | 62 | struct ipt_target *target; |
63 | int ret = 0; | 63 | int ret = 0; |
64 | 64 | ||
65 | target = ipt_find_target(t->u.user.name, t->u.user.revision); | 65 | target = xt_find_target(AF_INET, t->u.user.name, t->u.user.revision); |
66 | if (!target) | 66 | if (!target) |
67 | return -ENOENT; | 67 | return -ENOENT; |
68 | 68 | ||
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 04c7fab4edc4..2e266129a764 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -180,8 +180,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport, | |||
180 | } | 180 | } |
181 | 181 | ||
182 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, " | 182 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, " |
183 | "src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " | 183 | "src:" NIP6_FMT " dst:" NIP6_FMT "\n", |
184 | "dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
185 | __FUNCTION__, skb, skb->len, | 184 | __FUNCTION__, skb, skb->len, |
186 | NIP6(fl.fl6_src), NIP6(fl.fl6_dst)); | 185 | NIP6(fl.fl6_src), NIP6(fl.fl6_dst)); |
187 | 186 | ||
@@ -206,13 +205,13 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, | |||
206 | fl.oif = daddr->v6.sin6_scope_id; | 205 | fl.oif = daddr->v6.sin6_scope_id; |
207 | 206 | ||
208 | 207 | ||
209 | SCTP_DEBUG_PRINTK("%s: DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", | 208 | SCTP_DEBUG_PRINTK("%s: DST=" NIP6_FMT " ", |
210 | __FUNCTION__, NIP6(fl.fl6_dst)); | 209 | __FUNCTION__, NIP6(fl.fl6_dst)); |
211 | 210 | ||
212 | if (saddr) { | 211 | if (saddr) { |
213 | ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr); | 212 | ipv6_addr_copy(&fl.fl6_src, &saddr->v6.sin6_addr); |
214 | SCTP_DEBUG_PRINTK( | 213 | SCTP_DEBUG_PRINTK( |
215 | "SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x - ", | 214 | "SRC=" NIP6_FMT " - ", |
216 | NIP6(fl.fl6_src)); | 215 | NIP6(fl.fl6_src)); |
217 | } | 216 | } |
218 | 217 | ||
@@ -221,8 +220,7 @@ static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, | |||
221 | struct rt6_info *rt; | 220 | struct rt6_info *rt; |
222 | rt = (struct rt6_info *)dst; | 221 | rt = (struct rt6_info *)dst; |
223 | SCTP_DEBUG_PRINTK( | 222 | SCTP_DEBUG_PRINTK( |
224 | "rt6_dst:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x " | 223 | "rt6_dst:" NIP6_FMT " rt6_src:" NIP6_FMT "\n", |
225 | "rt6_src:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
226 | NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr)); | 224 | NIP6(rt->rt6i_dst.addr), NIP6(rt->rt6i_src.addr)); |
227 | } else { | 225 | } else { |
228 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); | 226 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); |
@@ -271,13 +269,12 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, | |||
271 | __u8 bmatchlen; | 269 | __u8 bmatchlen; |
272 | 270 | ||
273 | SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p " | 271 | SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p " |
274 | "daddr:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", | 272 | "daddr:" NIP6_FMT " ", |
275 | __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr)); | 273 | __FUNCTION__, asoc, dst, NIP6(daddr->v6.sin6_addr)); |
276 | 274 | ||
277 | if (!asoc) { | 275 | if (!asoc) { |
278 | ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr); | 276 | ipv6_get_saddr(dst, &daddr->v6.sin6_addr,&saddr->v6.sin6_addr); |
279 | SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " | 277 | SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: " NIP6_FMT "\n", |
280 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
281 | NIP6(saddr->v6.sin6_addr)); | 278 | NIP6(saddr->v6.sin6_addr)); |
282 | return; | 279 | return; |
283 | } | 280 | } |
@@ -305,13 +302,11 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, | |||
305 | 302 | ||
306 | if (baddr) { | 303 | if (baddr) { |
307 | memcpy(saddr, baddr, sizeof(union sctp_addr)); | 304 | memcpy(saddr, baddr, sizeof(union sctp_addr)); |
308 | SCTP_DEBUG_PRINTK("saddr: " | 305 | SCTP_DEBUG_PRINTK("saddr: " NIP6_FMT "\n", |
309 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
310 | NIP6(saddr->v6.sin6_addr)); | 306 | NIP6(saddr->v6.sin6_addr)); |
311 | } else { | 307 | } else { |
312 | printk(KERN_ERR "%s: asoc:%p Could not find a valid source " | 308 | printk(KERN_ERR "%s: asoc:%p Could not find a valid source " |
313 | "address for the " | 309 | "address for the dest:" NIP6_FMT "\n", |
314 | "dest:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | ||
315 | __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr)); | 310 | __FUNCTION__, asoc, NIP6(daddr->v6.sin6_addr)); |
316 | } | 311 | } |
317 | 312 | ||
@@ -675,8 +670,7 @@ static int sctp_v6_is_ce(const struct sk_buff *skb) | |||
675 | /* Dump the v6 addr to the seq file. */ | 670 | /* Dump the v6 addr to the seq file. */ |
676 | static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) | 671 | static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) |
677 | { | 672 | { |
678 | seq_printf(seq, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", | 673 | seq_printf(seq, NIP6_FMT " ", NIP6(addr->v6.sin6_addr)); |
679 | NIP6(addr->v6.sin6_addr)); | ||
680 | } | 674 | } |
681 | 675 | ||
682 | /* Initialize a PF_INET6 socket msg_name. */ | 676 | /* Initialize a PF_INET6 socket msg_name. */ |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 557a7d90b92a..477d7f80dba6 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -1036,14 +1036,14 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | |||
1036 | if (from_addr.sa.sa_family == AF_INET6) { | 1036 | if (from_addr.sa.sa_family == AF_INET6) { |
1037 | printk(KERN_WARNING | 1037 | printk(KERN_WARNING |
1038 | "%s association %p could not find address " | 1038 | "%s association %p could not find address " |
1039 | "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", | 1039 | NIP6_FMT "\n", |
1040 | __FUNCTION__, | 1040 | __FUNCTION__, |
1041 | asoc, | 1041 | asoc, |
1042 | NIP6(from_addr.v6.sin6_addr)); | 1042 | NIP6(from_addr.v6.sin6_addr)); |
1043 | } else { | 1043 | } else { |
1044 | printk(KERN_WARNING | 1044 | printk(KERN_WARNING |
1045 | "%s association %p could not find address " | 1045 | "%s association %p could not find address " |
1046 | "%u.%u.%u.%u\n", | 1046 | NIPQUAD_FMT "\n", |
1047 | __FUNCTION__, | 1047 | __FUNCTION__, |
1048 | asoc, | 1048 | asoc, |
1049 | NIPQUAD(from_addr.v4.sin_addr.s_addr)); | 1049 | NIPQUAD(from_addr.v4.sin_addr.s_addr)); |
diff --git a/net/tipc/Kconfig b/net/tipc/Kconfig new file mode 100644 index 000000000000..05ab18e62dee --- /dev/null +++ b/net/tipc/Kconfig | |||
@@ -0,0 +1,112 @@ | |||
1 | # | ||
2 | # TIPC configuration | ||
3 | # | ||
4 | |||
5 | menu "TIPC Configuration (EXPERIMENTAL)" | ||
6 | depends on INET && EXPERIMENTAL | ||
7 | |||
8 | config TIPC | ||
9 | tristate "The TIPC Protocol (EXPERIMENTAL)" | ||
10 | ---help--- | ||
11 | TBD. | ||
12 | |||
13 | This protocol support is also available as a module ( = code which | ||
14 | can be inserted in and removed from the running kernel whenever you | ||
15 | want). The module will be called tipc. If you want to compile it | ||
16 | as a module, say M here and read <file:Documentation/modules.txt>. | ||
17 | |||
18 | If in doubt, say N. | ||
19 | |||
20 | config TIPC_ADVANCED | ||
21 | bool "TIPC: Advanced configuration" | ||
22 | depends on TIPC | ||
23 | default n | ||
24 | help | ||
25 | Saying Y here will open some advanced configuration | ||
26 | for TIPC. Most users do not need to bother, so if | ||
27 | unsure, just say N. | ||
28 | |||
29 | config TIPC_ZONES | ||
30 | int "Maximum number of zones in network" | ||
31 | depends on TIPC && TIPC_ADVANCED | ||
32 | default "3" | ||
33 | help | ||
34 | Max number of zones inside TIPC network. Max supported value | ||
35 | is 255 zones, minimum is 1 | ||
36 | |||
37 | Default is 3 zones in a network; setting this to higher | ||
38 | allows more zones but might use more memory. | ||
39 | |||
40 | config TIPC_CLUSTERS | ||
41 | int "Maximum number of clusters in a zone" | ||
42 | depends on TIPC && TIPC_ADVANCED | ||
43 | default "1" | ||
44 | help | ||
45 | ***Only 1 (one cluster in a zone) is supported by current code. | ||
46 | Any value set here will be overridden.*** | ||
47 | |||
48 | (Max number of clusters inside TIPC zone. Max supported | ||
49 | value is 4095 clusters, minimum is 1. | ||
50 | |||
51 | Default is 1; setting this to smaller value might save | ||
52 | some memory, setting it to higher | ||
53 | allows more clusters and might consume more memory.) | ||
54 | |||
55 | config TIPC_NODES | ||
56 | int "Maximum number of nodes in cluster" | ||
57 | depends on TIPC && TIPC_ADVANCED | ||
58 | default "255" | ||
59 | help | ||
60 | Maximum number of nodes inside a TIPC cluster. Maximum | ||
61 | supported value is 2047 nodes, minimum is 8. | ||
62 | |||
63 | Setting this to a smaller value saves some memory, | ||
64 | setting it to higher allows more nodes. | ||
65 | |||
66 | config TIPC_SLAVE_NODES | ||
67 | int "Maximum number of slave nodes in cluster" | ||
68 | depends on TIPC && TIPC_ADVANCED | ||
69 | default "0" | ||
70 | help | ||
71 | ***This capability is not supported by current code.*** | ||
72 | |||
73 | Maximum number of slave nodes inside a TIPC cluster. Maximum | ||
74 | supported value is 2047 nodes, minimum is 0. | ||
75 | |||
76 | Setting this to a smaller value saves some memory, | ||
77 | setting it to higher allows more nodes. | ||
78 | |||
79 | config TIPC_PORTS | ||
80 | int "Maximum number of ports in a node" | ||
81 | depends on TIPC && TIPC_ADVANCED | ||
82 | default "8191" | ||
83 | help | ||
84 | Maximum number of ports within a node. Maximum | ||
85 | supported value is 64535 nodes, minimum is 127. | ||
86 | |||
87 | Setting this to a smaller value saves some memory, | ||
88 | setting it to higher allows more ports. | ||
89 | |||
90 | config TIPC_LOG | ||
91 | int "Size of log buffer" | ||
92 | depends on TIPC && TIPC_ADVANCED | ||
93 | default 0 | ||
94 | help | ||
95 | Size (in bytes) of TIPC's internal log buffer, which records the | ||
96 | occurrence of significant events. Maximum supported value | ||
97 | is 32768 bytes, minimum is 0. | ||
98 | |||
99 | There is no need to enable the log buffer unless the node will be | ||
100 | managed remotely via TIPC. | ||
101 | |||
102 | config TIPC_DEBUG | ||
103 | bool "Enable debugging support" | ||
104 | depends on TIPC | ||
105 | default n | ||
106 | help | ||
107 | This will enable debugging of TIPC. | ||
108 | |||
109 | Only say Y here if you are having trouble with TIPC. It will | ||
110 | enable the display of detailed information about what is going on. | ||
111 | |||
112 | endmenu | ||
diff --git a/net/tipc/Makefile b/net/tipc/Makefile new file mode 100644 index 000000000000..dceb7027946c --- /dev/null +++ b/net/tipc/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | # | ||
2 | # Makefile for the Linux TIPC layer | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_TIPC) := tipc.o | ||
6 | |||
7 | tipc-y += addr.o bcast.o bearer.o config.o cluster.o \ | ||
8 | core.o handler.o link.o discover.o msg.o \ | ||
9 | name_distr.o subscr.o name_table.o net.o \ | ||
10 | netlink.o node.o node_subscr.o port.o ref.o \ | ||
11 | socket.o user_reg.o zone.o dbg.o eth_media.o | ||
12 | |||
13 | # End of file | ||
diff --git a/net/tipc/addr.c b/net/tipc/addr.c new file mode 100644 index 000000000000..eca22260c98c --- /dev/null +++ b/net/tipc/addr.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * net/tipc/addr.c: TIPC address utility routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "dbg.h" | ||
39 | #include "addr.h" | ||
40 | #include "zone.h" | ||
41 | #include "cluster.h" | ||
42 | #include "net.h" | ||
43 | |||
44 | u32 tipc_get_addr(void) | ||
45 | { | ||
46 | return tipc_own_addr; | ||
47 | } | ||
48 | |||
49 | /** | ||
50 | * addr_domain_valid - validates a network domain address | ||
51 | * | ||
52 | * Accepts <Z.C.N>, <Z.C.0>, <Z.0.0>, and <0.0.0>, | ||
53 | * where Z, C, and N are non-zero and do not exceed the configured limits. | ||
54 | * | ||
55 | * Returns 1 if domain address is valid, otherwise 0 | ||
56 | */ | ||
57 | |||
58 | int addr_domain_valid(u32 addr) | ||
59 | { | ||
60 | u32 n = tipc_node(addr); | ||
61 | u32 c = tipc_cluster(addr); | ||
62 | u32 z = tipc_zone(addr); | ||
63 | u32 max_nodes = tipc_max_nodes; | ||
64 | |||
65 | if (is_slave(addr)) | ||
66 | max_nodes = LOWEST_SLAVE + tipc_max_slaves; | ||
67 | if (n > max_nodes) | ||
68 | return 0; | ||
69 | if (c > tipc_max_clusters) | ||
70 | return 0; | ||
71 | if (z > tipc_max_zones) | ||
72 | return 0; | ||
73 | |||
74 | if (n && (!z || !c)) | ||
75 | return 0; | ||
76 | if (c && !z) | ||
77 | return 0; | ||
78 | return 1; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * addr_node_valid - validates a proposed network address for this node | ||
83 | * | ||
84 | * Accepts <Z.C.N>, where Z, C, and N are non-zero and do not exceed | ||
85 | * the configured limits. | ||
86 | * | ||
87 | * Returns 1 if address can be used, otherwise 0 | ||
88 | */ | ||
89 | |||
90 | int addr_node_valid(u32 addr) | ||
91 | { | ||
92 | return (addr_domain_valid(addr) && tipc_node(addr)); | ||
93 | } | ||
94 | |||
diff --git a/net/tipc/addr.h b/net/tipc/addr.h new file mode 100644 index 000000000000..02ca71783e2e --- /dev/null +++ b/net/tipc/addr.h | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * net/tipc/addr.h: Include file for TIPC address utility routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_ADDR_H | ||
38 | #define _TIPC_ADDR_H | ||
39 | |||
40 | static inline u32 own_node(void) | ||
41 | { | ||
42 | return tipc_node(tipc_own_addr); | ||
43 | } | ||
44 | |||
45 | static inline u32 own_cluster(void) | ||
46 | { | ||
47 | return tipc_cluster(tipc_own_addr); | ||
48 | } | ||
49 | |||
50 | static inline u32 own_zone(void) | ||
51 | { | ||
52 | return tipc_zone(tipc_own_addr); | ||
53 | } | ||
54 | |||
55 | static inline int in_own_cluster(u32 addr) | ||
56 | { | ||
57 | return !((addr ^ tipc_own_addr) >> 12); | ||
58 | } | ||
59 | |||
60 | static inline int in_own_zone(u32 addr) | ||
61 | { | ||
62 | return !((addr ^ tipc_own_addr) >> 24); | ||
63 | } | ||
64 | |||
65 | static inline int is_slave(u32 addr) | ||
66 | { | ||
67 | return addr & 0x800; | ||
68 | } | ||
69 | |||
70 | static inline int may_route(u32 addr) | ||
71 | { | ||
72 | return(addr ^ tipc_own_addr) >> 11; | ||
73 | } | ||
74 | |||
75 | static inline int in_scope(u32 domain, u32 addr) | ||
76 | { | ||
77 | if (!domain || (domain == addr)) | ||
78 | return 1; | ||
79 | if (domain == (addr & 0xfffff000u)) /* domain <Z.C.0> */ | ||
80 | return 1; | ||
81 | if (domain == (addr & 0xff000000u)) /* domain <Z.0.0> */ | ||
82 | return 1; | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * addr_scope - convert message lookup domain to equivalent 2-bit scope value | ||
88 | */ | ||
89 | |||
90 | static inline int addr_scope(u32 domain) | ||
91 | { | ||
92 | if (likely(!domain)) | ||
93 | return TIPC_ZONE_SCOPE; | ||
94 | if (tipc_node(domain)) | ||
95 | return TIPC_NODE_SCOPE; | ||
96 | if (tipc_cluster(domain)) | ||
97 | return TIPC_CLUSTER_SCOPE; | ||
98 | return TIPC_ZONE_SCOPE; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * addr_domain - convert 2-bit scope value to equivalent message lookup domain | ||
103 | * | ||
104 | * Needed when address of a named message must be looked up a second time | ||
105 | * after a network hop. | ||
106 | */ | ||
107 | |||
108 | static inline int addr_domain(int sc) | ||
109 | { | ||
110 | if (likely(sc == TIPC_NODE_SCOPE)) | ||
111 | return tipc_own_addr; | ||
112 | if (sc == TIPC_CLUSTER_SCOPE) | ||
113 | return tipc_addr(tipc_zone(tipc_own_addr), | ||
114 | tipc_cluster(tipc_own_addr), 0); | ||
115 | return tipc_addr(tipc_zone(tipc_own_addr), 0, 0); | ||
116 | } | ||
117 | |||
118 | static inline char *addr_string_fill(char *string, u32 addr) | ||
119 | { | ||
120 | snprintf(string, 16, "<%u.%u.%u>", | ||
121 | tipc_zone(addr), tipc_cluster(addr), tipc_node(addr)); | ||
122 | return string; | ||
123 | } | ||
124 | |||
125 | int addr_domain_valid(u32); | ||
126 | int addr_node_valid(u32 addr); | ||
127 | |||
128 | #endif | ||
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c new file mode 100644 index 000000000000..9713d622efb8 --- /dev/null +++ b/net/tipc/bcast.c | |||
@@ -0,0 +1,806 @@ | |||
1 | /* | ||
2 | * net/tipc/bcast.c: TIPC broadcast code | ||
3 | * | ||
4 | * Copyright (c) 2004-2006, Ericsson AB | ||
5 | * Copyright (c) 2004, Intel Corporation. | ||
6 | * Copyright (c) 2005, Wind River Systems | ||
7 | * All rights reserved. | ||
8 | * | ||
9 | * Redistribution and use in source and binary forms, with or without | ||
10 | * modification, are permitted provided that the following conditions are met: | ||
11 | * | ||
12 | * 1. Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * 2. Redistributions in binary form must reproduce the above copyright | ||
15 | * notice, this list of conditions and the following disclaimer in the | ||
16 | * documentation and/or other materials provided with the distribution. | ||
17 | * 3. Neither the names of the copyright holders nor the names of its | ||
18 | * contributors may be used to endorse or promote products derived from | ||
19 | * this software without specific prior written permission. | ||
20 | * | ||
21 | * Alternatively, this software may be distributed under the terms of the | ||
22 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
23 | * Software Foundation. | ||
24 | * | ||
25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
26 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
29 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
35 | * POSSIBILITY OF SUCH DAMAGE. | ||
36 | */ | ||
37 | |||
38 | #include "core.h" | ||
39 | #include "msg.h" | ||
40 | #include "dbg.h" | ||
41 | #include "link.h" | ||
42 | #include "net.h" | ||
43 | #include "node.h" | ||
44 | #include "port.h" | ||
45 | #include "addr.h" | ||
46 | #include "node_subscr.h" | ||
47 | #include "name_distr.h" | ||
48 | #include "bearer.h" | ||
49 | #include "name_table.h" | ||
50 | #include "bcast.h" | ||
51 | |||
52 | |||
53 | #define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ | ||
54 | |||
55 | #define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ | ||
56 | |||
57 | #define BCLINK_LOG_BUF_SIZE 0 | ||
58 | |||
59 | /** | ||
60 | * struct bcbearer_pair - a pair of bearers used by broadcast link | ||
61 | * @primary: pointer to primary bearer | ||
62 | * @secondary: pointer to secondary bearer | ||
63 | * | ||
64 | * Bearers must have same priority and same set of reachable destinations | ||
65 | * to be paired. | ||
66 | */ | ||
67 | |||
68 | struct bcbearer_pair { | ||
69 | struct bearer *primary; | ||
70 | struct bearer *secondary; | ||
71 | }; | ||
72 | |||
73 | /** | ||
74 | * struct bcbearer - bearer used by broadcast link | ||
75 | * @bearer: (non-standard) broadcast bearer structure | ||
76 | * @media: (non-standard) broadcast media structure | ||
77 | * @bpairs: array of bearer pairs | ||
78 | * @bpairs_temp: array of bearer pairs used during creation of "bpairs" | ||
79 | */ | ||
80 | |||
81 | struct bcbearer { | ||
82 | struct bearer bearer; | ||
83 | struct media media; | ||
84 | struct bcbearer_pair bpairs[MAX_BEARERS]; | ||
85 | struct bcbearer_pair bpairs_temp[TIPC_NUM_LINK_PRI]; | ||
86 | }; | ||
87 | |||
88 | /** | ||
89 | * struct bclink - link used for broadcast messages | ||
90 | * @link: (non-standard) broadcast link structure | ||
91 | * @node: (non-standard) node structure representing b'cast link's peer node | ||
92 | * | ||
93 | * Handles sequence numbering, fragmentation, bundling, etc. | ||
94 | */ | ||
95 | |||
96 | struct bclink { | ||
97 | struct link link; | ||
98 | struct node node; | ||
99 | }; | ||
100 | |||
101 | |||
102 | static struct bcbearer *bcbearer = NULL; | ||
103 | static struct bclink *bclink = NULL; | ||
104 | static struct link *bcl = NULL; | ||
105 | static spinlock_t bc_lock = SPIN_LOCK_UNLOCKED; | ||
106 | |||
107 | char bc_link_name[] = "multicast-link"; | ||
108 | |||
109 | |||
110 | static inline u32 buf_seqno(struct sk_buff *buf) | ||
111 | { | ||
112 | return msg_seqno(buf_msg(buf)); | ||
113 | } | ||
114 | |||
115 | static inline u32 bcbuf_acks(struct sk_buff *buf) | ||
116 | { | ||
117 | return (u32)(unsigned long)TIPC_SKB_CB(buf)->handle; | ||
118 | } | ||
119 | |||
120 | static inline void bcbuf_set_acks(struct sk_buff *buf, u32 acks) | ||
121 | { | ||
122 | TIPC_SKB_CB(buf)->handle = (void *)(unsigned long)acks; | ||
123 | } | ||
124 | |||
125 | static inline void bcbuf_decr_acks(struct sk_buff *buf) | ||
126 | { | ||
127 | bcbuf_set_acks(buf, bcbuf_acks(buf) - 1); | ||
128 | } | ||
129 | |||
130 | |||
131 | /** | ||
132 | * bclink_set_gap - set gap according to contents of current deferred pkt queue | ||
133 | * | ||
134 | * Called with 'node' locked, bc_lock unlocked | ||
135 | */ | ||
136 | |||
137 | static inline void bclink_set_gap(struct node *n_ptr) | ||
138 | { | ||
139 | struct sk_buff *buf = n_ptr->bclink.deferred_head; | ||
140 | |||
141 | n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = | ||
142 | mod(n_ptr->bclink.last_in); | ||
143 | if (unlikely(buf != NULL)) | ||
144 | n_ptr->bclink.gap_to = mod(buf_seqno(buf) - 1); | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * bclink_ack_allowed - test if ACK or NACK message can be sent at this moment | ||
149 | * | ||
150 | * This mechanism endeavours to prevent all nodes in network from trying | ||
151 | * to ACK or NACK at the same time. | ||
152 | * | ||
153 | * Note: TIPC uses a different trigger to distribute ACKs than it does to | ||
154 | * distribute NACKs, but tries to use the same spacing (divide by 16). | ||
155 | */ | ||
156 | |||
157 | static inline int bclink_ack_allowed(u32 n) | ||
158 | { | ||
159 | return((n % TIPC_MIN_LINK_WIN) == tipc_own_tag); | ||
160 | } | ||
161 | |||
162 | |||
163 | /** | ||
164 | * bclink_retransmit_pkt - retransmit broadcast packets | ||
165 | * @after: sequence number of last packet to *not* retransmit | ||
166 | * @to: sequence number of last packet to retransmit | ||
167 | * | ||
168 | * Called with 'node' locked, bc_lock unlocked | ||
169 | */ | ||
170 | |||
171 | static void bclink_retransmit_pkt(u32 after, u32 to) | ||
172 | { | ||
173 | struct sk_buff *buf; | ||
174 | |||
175 | spin_lock_bh(&bc_lock); | ||
176 | buf = bcl->first_out; | ||
177 | while (buf && less_eq(buf_seqno(buf), after)) { | ||
178 | buf = buf->next; | ||
179 | } | ||
180 | if (buf != NULL) | ||
181 | link_retransmit(bcl, buf, mod(to - after)); | ||
182 | spin_unlock_bh(&bc_lock); | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * bclink_acknowledge - handle acknowledgement of broadcast packets | ||
187 | * @n_ptr: node that sent acknowledgement info | ||
188 | * @acked: broadcast sequence # that has been acknowledged | ||
189 | * | ||
190 | * Node is locked, bc_lock unlocked. | ||
191 | */ | ||
192 | |||
193 | void bclink_acknowledge(struct node *n_ptr, u32 acked) | ||
194 | { | ||
195 | struct sk_buff *crs; | ||
196 | struct sk_buff *next; | ||
197 | unsigned int released = 0; | ||
198 | |||
199 | if (less_eq(acked, n_ptr->bclink.acked)) | ||
200 | return; | ||
201 | |||
202 | spin_lock_bh(&bc_lock); | ||
203 | |||
204 | /* Skip over packets that node has previously acknowledged */ | ||
205 | |||
206 | crs = bcl->first_out; | ||
207 | while (crs && less_eq(buf_seqno(crs), n_ptr->bclink.acked)) { | ||
208 | crs = crs->next; | ||
209 | } | ||
210 | |||
211 | /* Update packets that node is now acknowledging */ | ||
212 | |||
213 | while (crs && less_eq(buf_seqno(crs), acked)) { | ||
214 | next = crs->next; | ||
215 | bcbuf_decr_acks(crs); | ||
216 | if (bcbuf_acks(crs) == 0) { | ||
217 | bcl->first_out = next; | ||
218 | bcl->out_queue_size--; | ||
219 | buf_discard(crs); | ||
220 | released = 1; | ||
221 | } | ||
222 | crs = next; | ||
223 | } | ||
224 | n_ptr->bclink.acked = acked; | ||
225 | |||
226 | /* Try resolving broadcast link congestion, if necessary */ | ||
227 | |||
228 | if (unlikely(bcl->next_out)) | ||
229 | link_push_queue(bcl); | ||
230 | if (unlikely(released && !list_empty(&bcl->waiting_ports))) | ||
231 | link_wakeup_ports(bcl, 0); | ||
232 | spin_unlock_bh(&bc_lock); | ||
233 | } | ||
234 | |||
235 | /** | ||
236 | * bclink_send_ack - unicast an ACK msg | ||
237 | * | ||
238 | * net_lock and node lock set | ||
239 | */ | ||
240 | |||
241 | static void bclink_send_ack(struct node *n_ptr) | ||
242 | { | ||
243 | struct link *l_ptr = n_ptr->active_links[n_ptr->addr & 1]; | ||
244 | |||
245 | if (l_ptr != NULL) | ||
246 | link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); | ||
247 | } | ||
248 | |||
249 | /** | ||
250 | * bclink_send_nack- broadcast a NACK msg | ||
251 | * | ||
252 | * net_lock and node lock set | ||
253 | */ | ||
254 | |||
255 | static void bclink_send_nack(struct node *n_ptr) | ||
256 | { | ||
257 | struct sk_buff *buf; | ||
258 | struct tipc_msg *msg; | ||
259 | |||
260 | if (!less(n_ptr->bclink.gap_after, n_ptr->bclink.gap_to)) | ||
261 | return; | ||
262 | |||
263 | buf = buf_acquire(INT_H_SIZE); | ||
264 | if (buf) { | ||
265 | msg = buf_msg(buf); | ||
266 | msg_init(msg, BCAST_PROTOCOL, STATE_MSG, | ||
267 | TIPC_OK, INT_H_SIZE, n_ptr->addr); | ||
268 | msg_set_mc_netid(msg, tipc_net_id); | ||
269 | msg_set_bcast_ack(msg, mod(n_ptr->bclink.last_in)); | ||
270 | msg_set_bcgap_after(msg, n_ptr->bclink.gap_after); | ||
271 | msg_set_bcgap_to(msg, n_ptr->bclink.gap_to); | ||
272 | msg_set_bcast_tag(msg, tipc_own_tag); | ||
273 | |||
274 | if (bearer_send(&bcbearer->bearer, buf, 0)) { | ||
275 | bcl->stats.sent_nacks++; | ||
276 | buf_discard(buf); | ||
277 | } else { | ||
278 | bearer_schedule(bcl->b_ptr, bcl); | ||
279 | bcl->proto_msg_queue = buf; | ||
280 | bcl->stats.bearer_congs++; | ||
281 | } | ||
282 | |||
283 | /* | ||
284 | * Ensure we doesn't send another NACK msg to the node | ||
285 | * until 16 more deferred messages arrive from it | ||
286 | * (i.e. helps prevent all nodes from NACK'ing at same time) | ||
287 | */ | ||
288 | |||
289 | n_ptr->bclink.nack_sync = tipc_own_tag; | ||
290 | } | ||
291 | } | ||
292 | |||
293 | /** | ||
294 | * bclink_check_gap - send a NACK if a sequence gap exists | ||
295 | * | ||
296 | * net_lock and node lock set | ||
297 | */ | ||
298 | |||
299 | void bclink_check_gap(struct node *n_ptr, u32 last_sent) | ||
300 | { | ||
301 | if (!n_ptr->bclink.supported || | ||
302 | less_eq(last_sent, mod(n_ptr->bclink.last_in))) | ||
303 | return; | ||
304 | |||
305 | bclink_set_gap(n_ptr); | ||
306 | if (n_ptr->bclink.gap_after == n_ptr->bclink.gap_to) | ||
307 | n_ptr->bclink.gap_to = last_sent; | ||
308 | bclink_send_nack(n_ptr); | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * bclink_peek_nack - process a NACK msg meant for another node | ||
313 | * | ||
314 | * Only net_lock set. | ||
315 | */ | ||
316 | |||
317 | void bclink_peek_nack(u32 dest, u32 sender_tag, u32 gap_after, u32 gap_to) | ||
318 | { | ||
319 | struct node *n_ptr = node_find(dest); | ||
320 | u32 my_after, my_to; | ||
321 | |||
322 | if (unlikely(!n_ptr || !node_is_up(n_ptr))) | ||
323 | return; | ||
324 | node_lock(n_ptr); | ||
325 | /* | ||
326 | * Modify gap to suppress unnecessary NACKs from this node | ||
327 | */ | ||
328 | my_after = n_ptr->bclink.gap_after; | ||
329 | my_to = n_ptr->bclink.gap_to; | ||
330 | |||
331 | if (less_eq(gap_after, my_after)) { | ||
332 | if (less(my_after, gap_to) && less(gap_to, my_to)) | ||
333 | n_ptr->bclink.gap_after = gap_to; | ||
334 | else if (less_eq(my_to, gap_to)) | ||
335 | n_ptr->bclink.gap_to = n_ptr->bclink.gap_after; | ||
336 | } else if (less_eq(gap_after, my_to)) { | ||
337 | if (less_eq(my_to, gap_to)) | ||
338 | n_ptr->bclink.gap_to = gap_after; | ||
339 | } else { | ||
340 | /* | ||
341 | * Expand gap if missing bufs not in deferred queue: | ||
342 | */ | ||
343 | struct sk_buff *buf = n_ptr->bclink.deferred_head; | ||
344 | u32 prev = n_ptr->bclink.gap_to; | ||
345 | |||
346 | for (; buf; buf = buf->next) { | ||
347 | u32 seqno = buf_seqno(buf); | ||
348 | |||
349 | if (mod(seqno - prev) != 1) | ||
350 | buf = NULL; | ||
351 | if (seqno == gap_after) | ||
352 | break; | ||
353 | prev = seqno; | ||
354 | } | ||
355 | if (buf == NULL) | ||
356 | n_ptr->bclink.gap_to = gap_after; | ||
357 | } | ||
358 | /* | ||
359 | * Some nodes may send a complementary NACK now: | ||
360 | */ | ||
361 | if (bclink_ack_allowed(sender_tag + 1)) { | ||
362 | if (n_ptr->bclink.gap_to != n_ptr->bclink.gap_after) { | ||
363 | bclink_send_nack(n_ptr); | ||
364 | bclink_set_gap(n_ptr); | ||
365 | } | ||
366 | } | ||
367 | node_unlock(n_ptr); | ||
368 | } | ||
369 | |||
370 | /** | ||
371 | * bclink_send_msg - broadcast a packet to all nodes in cluster | ||
372 | */ | ||
373 | |||
374 | int bclink_send_msg(struct sk_buff *buf) | ||
375 | { | ||
376 | int res; | ||
377 | |||
378 | spin_lock_bh(&bc_lock); | ||
379 | |||
380 | res = link_send_buf(bcl, buf); | ||
381 | if (unlikely(res == -ELINKCONG)) | ||
382 | buf_discard(buf); | ||
383 | else | ||
384 | bcl->stats.sent_info++; | ||
385 | |||
386 | if (bcl->out_queue_size > bcl->stats.max_queue_sz) | ||
387 | bcl->stats.max_queue_sz = bcl->out_queue_size; | ||
388 | bcl->stats.queue_sz_counts++; | ||
389 | bcl->stats.accu_queue_sz += bcl->out_queue_size; | ||
390 | |||
391 | spin_unlock_bh(&bc_lock); | ||
392 | return res; | ||
393 | } | ||
394 | |||
395 | /** | ||
396 | * bclink_recv_pkt - receive a broadcast packet, and deliver upwards | ||
397 | * | ||
398 | * net_lock is read_locked, no other locks set | ||
399 | */ | ||
400 | |||
401 | void bclink_recv_pkt(struct sk_buff *buf) | ||
402 | { | ||
403 | struct tipc_msg *msg = buf_msg(buf); | ||
404 | struct node* node = node_find(msg_prevnode(msg)); | ||
405 | u32 next_in; | ||
406 | u32 seqno; | ||
407 | struct sk_buff *deferred; | ||
408 | |||
409 | msg_dbg(msg, "<BC<<<"); | ||
410 | |||
411 | if (unlikely(!node || !node_is_up(node) || !node->bclink.supported || | ||
412 | (msg_mc_netid(msg) != tipc_net_id))) { | ||
413 | buf_discard(buf); | ||
414 | return; | ||
415 | } | ||
416 | |||
417 | if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) { | ||
418 | msg_dbg(msg, "<BCNACK<<<"); | ||
419 | if (msg_destnode(msg) == tipc_own_addr) { | ||
420 | node_lock(node); | ||
421 | bclink_acknowledge(node, msg_bcast_ack(msg)); | ||
422 | node_unlock(node); | ||
423 | bcl->stats.recv_nacks++; | ||
424 | bclink_retransmit_pkt(msg_bcgap_after(msg), | ||
425 | msg_bcgap_to(msg)); | ||
426 | } else { | ||
427 | bclink_peek_nack(msg_destnode(msg), | ||
428 | msg_bcast_tag(msg), | ||
429 | msg_bcgap_after(msg), | ||
430 | msg_bcgap_to(msg)); | ||
431 | } | ||
432 | buf_discard(buf); | ||
433 | return; | ||
434 | } | ||
435 | |||
436 | node_lock(node); | ||
437 | receive: | ||
438 | deferred = node->bclink.deferred_head; | ||
439 | next_in = mod(node->bclink.last_in + 1); | ||
440 | seqno = msg_seqno(msg); | ||
441 | |||
442 | if (likely(seqno == next_in)) { | ||
443 | bcl->stats.recv_info++; | ||
444 | node->bclink.last_in++; | ||
445 | bclink_set_gap(node); | ||
446 | if (unlikely(bclink_ack_allowed(seqno))) { | ||
447 | bclink_send_ack(node); | ||
448 | bcl->stats.sent_acks++; | ||
449 | } | ||
450 | if (likely(msg_isdata(msg))) { | ||
451 | node_unlock(node); | ||
452 | port_recv_mcast(buf, NULL); | ||
453 | } else if (msg_user(msg) == MSG_BUNDLER) { | ||
454 | bcl->stats.recv_bundles++; | ||
455 | bcl->stats.recv_bundled += msg_msgcnt(msg); | ||
456 | node_unlock(node); | ||
457 | link_recv_bundle(buf); | ||
458 | } else if (msg_user(msg) == MSG_FRAGMENTER) { | ||
459 | bcl->stats.recv_fragments++; | ||
460 | if (link_recv_fragment(&node->bclink.defragm, | ||
461 | &buf, &msg)) | ||
462 | bcl->stats.recv_fragmented++; | ||
463 | node_unlock(node); | ||
464 | net_route_msg(buf); | ||
465 | } else { | ||
466 | node_unlock(node); | ||
467 | net_route_msg(buf); | ||
468 | } | ||
469 | if (deferred && (buf_seqno(deferred) == mod(next_in + 1))) { | ||
470 | node_lock(node); | ||
471 | buf = deferred; | ||
472 | msg = buf_msg(buf); | ||
473 | node->bclink.deferred_head = deferred->next; | ||
474 | goto receive; | ||
475 | } | ||
476 | return; | ||
477 | } else if (less(next_in, seqno)) { | ||
478 | u32 gap_after = node->bclink.gap_after; | ||
479 | u32 gap_to = node->bclink.gap_to; | ||
480 | |||
481 | if (link_defer_pkt(&node->bclink.deferred_head, | ||
482 | &node->bclink.deferred_tail, | ||
483 | buf)) { | ||
484 | node->bclink.nack_sync++; | ||
485 | bcl->stats.deferred_recv++; | ||
486 | if (seqno == mod(gap_after + 1)) | ||
487 | node->bclink.gap_after = seqno; | ||
488 | else if (less(gap_after, seqno) && less(seqno, gap_to)) | ||
489 | node->bclink.gap_to = seqno; | ||
490 | } | ||
491 | if (bclink_ack_allowed(node->bclink.nack_sync)) { | ||
492 | if (gap_to != gap_after) | ||
493 | bclink_send_nack(node); | ||
494 | bclink_set_gap(node); | ||
495 | } | ||
496 | } else { | ||
497 | bcl->stats.duplicates++; | ||
498 | buf_discard(buf); | ||
499 | } | ||
500 | node_unlock(node); | ||
501 | } | ||
502 | |||
503 | u32 bclink_get_last_sent(void) | ||
504 | { | ||
505 | u32 last_sent = mod(bcl->next_out_no - 1); | ||
506 | |||
507 | if (bcl->next_out) | ||
508 | last_sent = mod(buf_seqno(bcl->next_out) - 1); | ||
509 | return last_sent; | ||
510 | } | ||
511 | |||
512 | u32 bclink_acks_missing(struct node *n_ptr) | ||
513 | { | ||
514 | return (n_ptr->bclink.supported && | ||
515 | (bclink_get_last_sent() != n_ptr->bclink.acked)); | ||
516 | } | ||
517 | |||
518 | |||
519 | /** | ||
520 | * bcbearer_send - send a packet through the broadcast pseudo-bearer | ||
521 | * | ||
522 | * Send through as many bearers as necessary to reach all nodes | ||
523 | * that support TIPC multicasting. | ||
524 | * | ||
525 | * Returns 0 if packet sent successfully, non-zero if not | ||
526 | */ | ||
527 | |||
528 | int bcbearer_send(struct sk_buff *buf, | ||
529 | struct tipc_bearer *unused1, | ||
530 | struct tipc_media_addr *unused2) | ||
531 | { | ||
532 | static int send_count = 0; | ||
533 | |||
534 | struct node_map remains; | ||
535 | struct node_map remains_new; | ||
536 | int bp_index; | ||
537 | int swap_time; | ||
538 | |||
539 | /* Prepare buffer for broadcasting (if first time trying to send it) */ | ||
540 | |||
541 | if (likely(!msg_non_seq(buf_msg(buf)))) { | ||
542 | struct tipc_msg *msg; | ||
543 | |||
544 | assert(cluster_bcast_nodes.count != 0); | ||
545 | bcbuf_set_acks(buf, cluster_bcast_nodes.count); | ||
546 | msg = buf_msg(buf); | ||
547 | msg_set_non_seq(msg); | ||
548 | msg_set_mc_netid(msg, tipc_net_id); | ||
549 | } | ||
550 | |||
551 | /* Determine if bearer pairs should be swapped following this attempt */ | ||
552 | |||
553 | if ((swap_time = (++send_count >= 10))) | ||
554 | send_count = 0; | ||
555 | |||
556 | /* Send buffer over bearers until all targets reached */ | ||
557 | |||
558 | remains = cluster_bcast_nodes; | ||
559 | |||
560 | for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { | ||
561 | struct bearer *p = bcbearer->bpairs[bp_index].primary; | ||
562 | struct bearer *s = bcbearer->bpairs[bp_index].secondary; | ||
563 | |||
564 | if (!p) | ||
565 | break; /* no more bearers to try */ | ||
566 | |||
567 | nmap_diff(&remains, &p->nodes, &remains_new); | ||
568 | if (remains_new.count == remains.count) | ||
569 | continue; /* bearer pair doesn't add anything */ | ||
570 | |||
571 | if (!p->publ.blocked && | ||
572 | !p->media->send_msg(buf, &p->publ, &p->media->bcast_addr)) { | ||
573 | if (swap_time && s && !s->publ.blocked) | ||
574 | goto swap; | ||
575 | else | ||
576 | goto update; | ||
577 | } | ||
578 | |||
579 | if (!s || s->publ.blocked || | ||
580 | s->media->send_msg(buf, &s->publ, &s->media->bcast_addr)) | ||
581 | continue; /* unable to send using bearer pair */ | ||
582 | swap: | ||
583 | bcbearer->bpairs[bp_index].primary = s; | ||
584 | bcbearer->bpairs[bp_index].secondary = p; | ||
585 | update: | ||
586 | if (remains_new.count == 0) | ||
587 | return TIPC_OK; | ||
588 | |||
589 | remains = remains_new; | ||
590 | } | ||
591 | |||
592 | /* Unable to reach all targets */ | ||
593 | |||
594 | bcbearer->bearer.publ.blocked = 1; | ||
595 | bcl->stats.bearer_congs++; | ||
596 | return ~TIPC_OK; | ||
597 | } | ||
598 | |||
599 | /** | ||
600 | * bcbearer_sort - create sets of bearer pairs used by broadcast bearer | ||
601 | */ | ||
602 | |||
603 | void bcbearer_sort(void) | ||
604 | { | ||
605 | struct bcbearer_pair *bp_temp = bcbearer->bpairs_temp; | ||
606 | struct bcbearer_pair *bp_curr; | ||
607 | int b_index; | ||
608 | int pri; | ||
609 | |||
610 | spin_lock_bh(&bc_lock); | ||
611 | |||
612 | /* Group bearers by priority (can assume max of two per priority) */ | ||
613 | |||
614 | memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp)); | ||
615 | |||
616 | for (b_index = 0; b_index < MAX_BEARERS; b_index++) { | ||
617 | struct bearer *b = &bearers[b_index]; | ||
618 | |||
619 | if (!b->active || !b->nodes.count) | ||
620 | continue; | ||
621 | |||
622 | if (!bp_temp[b->priority].primary) | ||
623 | bp_temp[b->priority].primary = b; | ||
624 | else | ||
625 | bp_temp[b->priority].secondary = b; | ||
626 | } | ||
627 | |||
628 | /* Create array of bearer pairs for broadcasting */ | ||
629 | |||
630 | bp_curr = bcbearer->bpairs; | ||
631 | memset(bcbearer->bpairs, 0, sizeof(bcbearer->bpairs)); | ||
632 | |||
633 | for (pri = (TIPC_NUM_LINK_PRI - 1); pri >= 0; pri--) { | ||
634 | |||
635 | if (!bp_temp[pri].primary) | ||
636 | continue; | ||
637 | |||
638 | bp_curr->primary = bp_temp[pri].primary; | ||
639 | |||
640 | if (bp_temp[pri].secondary) { | ||
641 | if (nmap_equal(&bp_temp[pri].primary->nodes, | ||
642 | &bp_temp[pri].secondary->nodes)) { | ||
643 | bp_curr->secondary = bp_temp[pri].secondary; | ||
644 | } else { | ||
645 | bp_curr++; | ||
646 | bp_curr->primary = bp_temp[pri].secondary; | ||
647 | } | ||
648 | } | ||
649 | |||
650 | bp_curr++; | ||
651 | } | ||
652 | |||
653 | spin_unlock_bh(&bc_lock); | ||
654 | } | ||
655 | |||
656 | /** | ||
657 | * bcbearer_push - resolve bearer congestion | ||
658 | * | ||
659 | * Forces bclink to push out any unsent packets, until all packets are gone | ||
660 | * or congestion reoccurs. | ||
661 | * No locks set when function called | ||
662 | */ | ||
663 | |||
664 | void bcbearer_push(void) | ||
665 | { | ||
666 | struct bearer *b_ptr; | ||
667 | |||
668 | spin_lock_bh(&bc_lock); | ||
669 | b_ptr = &bcbearer->bearer; | ||
670 | if (b_ptr->publ.blocked) { | ||
671 | b_ptr->publ.blocked = 0; | ||
672 | bearer_lock_push(b_ptr); | ||
673 | } | ||
674 | spin_unlock_bh(&bc_lock); | ||
675 | } | ||
676 | |||
677 | |||
678 | int bclink_stats(char *buf, const u32 buf_size) | ||
679 | { | ||
680 | struct print_buf pb; | ||
681 | |||
682 | if (!bcl) | ||
683 | return 0; | ||
684 | |||
685 | printbuf_init(&pb, buf, buf_size); | ||
686 | |||
687 | spin_lock_bh(&bc_lock); | ||
688 | |||
689 | tipc_printf(&pb, "Link <%s>\n" | ||
690 | " Window:%u packets\n", | ||
691 | bcl->name, bcl->queue_limit[0]); | ||
692 | tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
693 | bcl->stats.recv_info, | ||
694 | bcl->stats.recv_fragments, | ||
695 | bcl->stats.recv_fragmented, | ||
696 | bcl->stats.recv_bundles, | ||
697 | bcl->stats.recv_bundled); | ||
698 | tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
699 | bcl->stats.sent_info, | ||
700 | bcl->stats.sent_fragments, | ||
701 | bcl->stats.sent_fragmented, | ||
702 | bcl->stats.sent_bundles, | ||
703 | bcl->stats.sent_bundled); | ||
704 | tipc_printf(&pb, " RX naks:%u defs:%u dups:%u\n", | ||
705 | bcl->stats.recv_nacks, | ||
706 | bcl->stats.deferred_recv, | ||
707 | bcl->stats.duplicates); | ||
708 | tipc_printf(&pb, " TX naks:%u acks:%u dups:%u\n", | ||
709 | bcl->stats.sent_nacks, | ||
710 | bcl->stats.sent_acks, | ||
711 | bcl->stats.retransmitted); | ||
712 | tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n", | ||
713 | bcl->stats.bearer_congs, | ||
714 | bcl->stats.link_congs, | ||
715 | bcl->stats.max_queue_sz, | ||
716 | bcl->stats.queue_sz_counts | ||
717 | ? (bcl->stats.accu_queue_sz / bcl->stats.queue_sz_counts) | ||
718 | : 0); | ||
719 | |||
720 | spin_unlock_bh(&bc_lock); | ||
721 | return printbuf_validate(&pb); | ||
722 | } | ||
723 | |||
724 | int bclink_reset_stats(void) | ||
725 | { | ||
726 | if (!bcl) | ||
727 | return -ENOPROTOOPT; | ||
728 | |||
729 | spin_lock_bh(&bc_lock); | ||
730 | memset(&bcl->stats, 0, sizeof(bcl->stats)); | ||
731 | spin_unlock_bh(&bc_lock); | ||
732 | return TIPC_OK; | ||
733 | } | ||
734 | |||
735 | int bclink_set_queue_limits(u32 limit) | ||
736 | { | ||
737 | if (!bcl) | ||
738 | return -ENOPROTOOPT; | ||
739 | if ((limit < TIPC_MIN_LINK_WIN) || (limit > TIPC_MAX_LINK_WIN)) | ||
740 | return -EINVAL; | ||
741 | |||
742 | spin_lock_bh(&bc_lock); | ||
743 | link_set_queue_limits(bcl, limit); | ||
744 | spin_unlock_bh(&bc_lock); | ||
745 | return TIPC_OK; | ||
746 | } | ||
747 | |||
748 | int bclink_init(void) | ||
749 | { | ||
750 | bcbearer = kmalloc(sizeof(*bcbearer), GFP_ATOMIC); | ||
751 | bclink = kmalloc(sizeof(*bclink), GFP_ATOMIC); | ||
752 | if (!bcbearer || !bclink) { | ||
753 | nomem: | ||
754 | warn("Memory squeeze; Failed to create multicast link\n"); | ||
755 | kfree(bcbearer); | ||
756 | bcbearer = NULL; | ||
757 | kfree(bclink); | ||
758 | bclink = NULL; | ||
759 | return -ENOMEM; | ||
760 | } | ||
761 | |||
762 | memset(bcbearer, 0, sizeof(struct bcbearer)); | ||
763 | INIT_LIST_HEAD(&bcbearer->bearer.cong_links); | ||
764 | bcbearer->bearer.media = &bcbearer->media; | ||
765 | bcbearer->media.send_msg = bcbearer_send; | ||
766 | sprintf(bcbearer->media.name, "tipc-multicast"); | ||
767 | |||
768 | bcl = &bclink->link; | ||
769 | memset(bclink, 0, sizeof(struct bclink)); | ||
770 | INIT_LIST_HEAD(&bcl->waiting_ports); | ||
771 | bcl->next_out_no = 1; | ||
772 | bclink->node.lock = SPIN_LOCK_UNLOCKED; | ||
773 | bcl->owner = &bclink->node; | ||
774 | bcl->max_pkt = MAX_PKT_DEFAULT_MCAST; | ||
775 | link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); | ||
776 | bcl->b_ptr = &bcbearer->bearer; | ||
777 | bcl->state = WORKING_WORKING; | ||
778 | sprintf(bcl->name, bc_link_name); | ||
779 | |||
780 | if (BCLINK_LOG_BUF_SIZE) { | ||
781 | char *pb = kmalloc(BCLINK_LOG_BUF_SIZE, GFP_ATOMIC); | ||
782 | |||
783 | if (!pb) | ||
784 | goto nomem; | ||
785 | printbuf_init(&bcl->print_buf, pb, BCLINK_LOG_BUF_SIZE); | ||
786 | } | ||
787 | |||
788 | return TIPC_OK; | ||
789 | } | ||
790 | |||
791 | void bclink_stop(void) | ||
792 | { | ||
793 | spin_lock_bh(&bc_lock); | ||
794 | if (bcbearer) { | ||
795 | link_stop(bcl); | ||
796 | if (BCLINK_LOG_BUF_SIZE) | ||
797 | kfree(bcl->print_buf.buf); | ||
798 | bcl = NULL; | ||
799 | kfree(bclink); | ||
800 | bclink = NULL; | ||
801 | kfree(bcbearer); | ||
802 | bcbearer = NULL; | ||
803 | } | ||
804 | spin_unlock_bh(&bc_lock); | ||
805 | } | ||
806 | |||
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h new file mode 100644 index 000000000000..5430e524b4f9 --- /dev/null +++ b/net/tipc/bcast.h | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * net/tipc/bcast.h: Include file for TIPC broadcast code | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_BCAST_H | ||
38 | #define _TIPC_BCAST_H | ||
39 | |||
40 | #define MAX_NODES 4096 | ||
41 | #define WSIZE 32 | ||
42 | |||
43 | /** | ||
44 | * struct node_map - set of node identifiers | ||
45 | * @count: # of nodes in set | ||
46 | * @map: bitmap of node identifiers that are in the set | ||
47 | */ | ||
48 | |||
49 | struct node_map { | ||
50 | u32 count; | ||
51 | u32 map[MAX_NODES / WSIZE]; | ||
52 | }; | ||
53 | |||
54 | |||
55 | #define PLSIZE 32 | ||
56 | |||
57 | /** | ||
58 | * struct port_list - set of node local destination ports | ||
59 | * @count: # of ports in set (only valid for first entry in list) | ||
60 | * @next: pointer to next entry in list | ||
61 | * @ports: array of port references | ||
62 | */ | ||
63 | |||
64 | struct port_list { | ||
65 | int count; | ||
66 | struct port_list *next; | ||
67 | u32 ports[PLSIZE]; | ||
68 | }; | ||
69 | |||
70 | |||
71 | struct node; | ||
72 | |||
73 | extern char bc_link_name[]; | ||
74 | |||
75 | |||
76 | /** | ||
77 | * nmap_get - determine if node exists in a node map | ||
78 | */ | ||
79 | |||
80 | static inline int nmap_get(struct node_map *nm_ptr, u32 node) | ||
81 | { | ||
82 | int n = tipc_node(node); | ||
83 | int w = n / WSIZE; | ||
84 | int b = n % WSIZE; | ||
85 | |||
86 | return nm_ptr->map[w] & (1 << b); | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * nmap_add - add a node to a node map | ||
91 | */ | ||
92 | |||
93 | static inline void nmap_add(struct node_map *nm_ptr, u32 node) | ||
94 | { | ||
95 | int n = tipc_node(node); | ||
96 | int w = n / WSIZE; | ||
97 | u32 mask = (1 << (n % WSIZE)); | ||
98 | |||
99 | if ((nm_ptr->map[w] & mask) == 0) { | ||
100 | nm_ptr->count++; | ||
101 | nm_ptr->map[w] |= mask; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * nmap_remove - remove a node from a node map | ||
107 | */ | ||
108 | |||
109 | static inline void nmap_remove(struct node_map *nm_ptr, u32 node) | ||
110 | { | ||
111 | int n = tipc_node(node); | ||
112 | int w = n / WSIZE; | ||
113 | u32 mask = (1 << (n % WSIZE)); | ||
114 | |||
115 | if ((nm_ptr->map[w] & mask) != 0) { | ||
116 | nm_ptr->map[w] &= ~mask; | ||
117 | nm_ptr->count--; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * nmap_equal - test for equality of node maps | ||
123 | */ | ||
124 | |||
125 | static inline int nmap_equal(struct node_map *nm_a, struct node_map *nm_b) | ||
126 | { | ||
127 | return !memcmp(nm_a, nm_b, sizeof(*nm_a)); | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * nmap_diff - find differences between node maps | ||
132 | * @nm_a: input node map A | ||
133 | * @nm_b: input node map B | ||
134 | * @nm_diff: output node map A-B (i.e. nodes of A that are not in B) | ||
135 | */ | ||
136 | |||
137 | static inline void nmap_diff(struct node_map *nm_a, struct node_map *nm_b, | ||
138 | struct node_map *nm_diff) | ||
139 | { | ||
140 | int stop = sizeof(nm_a->map) / sizeof(u32); | ||
141 | int w; | ||
142 | int b; | ||
143 | u32 map; | ||
144 | |||
145 | memset(nm_diff, 0, sizeof(*nm_diff)); | ||
146 | for (w = 0; w < stop; w++) { | ||
147 | map = nm_a->map[w] ^ (nm_a->map[w] & nm_b->map[w]); | ||
148 | nm_diff->map[w] = map; | ||
149 | if (map != 0) { | ||
150 | for (b = 0 ; b < WSIZE; b++) { | ||
151 | if (map & (1 << b)) | ||
152 | nm_diff->count++; | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | |||
158 | /** | ||
159 | * port_list_add - add a port to a port list, ensuring no duplicates | ||
160 | */ | ||
161 | |||
162 | static inline void port_list_add(struct port_list *pl_ptr, u32 port) | ||
163 | { | ||
164 | struct port_list *item = pl_ptr; | ||
165 | int i; | ||
166 | int item_sz = PLSIZE; | ||
167 | int cnt = pl_ptr->count; | ||
168 | |||
169 | for (; ; cnt -= item_sz, item = item->next) { | ||
170 | if (cnt < PLSIZE) | ||
171 | item_sz = cnt; | ||
172 | for (i = 0; i < item_sz; i++) | ||
173 | if (item->ports[i] == port) | ||
174 | return; | ||
175 | if (i < PLSIZE) { | ||
176 | item->ports[i] = port; | ||
177 | pl_ptr->count++; | ||
178 | return; | ||
179 | } | ||
180 | if (!item->next) { | ||
181 | item->next = kmalloc(sizeof(*item), GFP_ATOMIC); | ||
182 | if (!item->next) { | ||
183 | warn("Memory squeeze: multicast destination port list is incomplete\n"); | ||
184 | return; | ||
185 | } | ||
186 | item->next->next = NULL; | ||
187 | } | ||
188 | } | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * port_list_free - free dynamically created entries in port_list chain | ||
193 | * | ||
194 | * Note: First item is on stack, so it doesn't need to be released | ||
195 | */ | ||
196 | |||
197 | static inline void port_list_free(struct port_list *pl_ptr) | ||
198 | { | ||
199 | struct port_list *item; | ||
200 | struct port_list *next; | ||
201 | |||
202 | for (item = pl_ptr->next; item; item = next) { | ||
203 | next = item->next; | ||
204 | kfree(item); | ||
205 | } | ||
206 | } | ||
207 | |||
208 | |||
209 | int bclink_init(void); | ||
210 | void bclink_stop(void); | ||
211 | void bclink_acknowledge(struct node *n_ptr, u32 acked); | ||
212 | int bclink_send_msg(struct sk_buff *buf); | ||
213 | void bclink_recv_pkt(struct sk_buff *buf); | ||
214 | u32 bclink_get_last_sent(void); | ||
215 | u32 bclink_acks_missing(struct node *n_ptr); | ||
216 | void bclink_check_gap(struct node *n_ptr, u32 seqno); | ||
217 | int bclink_stats(char *stats_buf, const u32 buf_size); | ||
218 | int bclink_reset_stats(void); | ||
219 | int bclink_set_queue_limits(u32 limit); | ||
220 | void bcbearer_sort(void); | ||
221 | void bcbearer_push(void); | ||
222 | |||
223 | #endif | ||
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c new file mode 100644 index 000000000000..3dd19fdc5a2c --- /dev/null +++ b/net/tipc/bearer.c | |||
@@ -0,0 +1,692 @@ | |||
1 | /* | ||
2 | * net/tipc/bearer.c: TIPC bearer code | ||
3 | * | ||
4 | * Copyright (c) 1996-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "config.h" | ||
39 | #include "dbg.h" | ||
40 | #include "bearer.h" | ||
41 | #include "link.h" | ||
42 | #include "port.h" | ||
43 | #include "discover.h" | ||
44 | #include "bcast.h" | ||
45 | |||
46 | #define MAX_ADDR_STR 32 | ||
47 | |||
48 | static struct media *media_list = 0; | ||
49 | static u32 media_count = 0; | ||
50 | |||
51 | struct bearer *bearers = 0; | ||
52 | |||
53 | /** | ||
54 | * media_name_valid - validate media name | ||
55 | * | ||
56 | * Returns 1 if media name is valid, otherwise 0. | ||
57 | */ | ||
58 | |||
59 | static int media_name_valid(const char *name) | ||
60 | { | ||
61 | u32 len; | ||
62 | |||
63 | len = strlen(name); | ||
64 | if ((len + 1) > TIPC_MAX_MEDIA_NAME) | ||
65 | return 0; | ||
66 | return (strspn(name, tipc_alphabet) == len); | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * media_find - locates specified media object by name | ||
71 | */ | ||
72 | |||
73 | static struct media *media_find(const char *name) | ||
74 | { | ||
75 | struct media *m_ptr; | ||
76 | u32 i; | ||
77 | |||
78 | for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { | ||
79 | if (!strcmp(m_ptr->name, name)) | ||
80 | return m_ptr; | ||
81 | } | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * tipc_register_media - register a media type | ||
87 | * | ||
88 | * Bearers for this media type must be activated separately at a later stage. | ||
89 | */ | ||
90 | |||
91 | int tipc_register_media(u32 media_type, | ||
92 | char *name, | ||
93 | int (*enable)(struct tipc_bearer *), | ||
94 | void (*disable)(struct tipc_bearer *), | ||
95 | int (*send_msg)(struct sk_buff *, | ||
96 | struct tipc_bearer *, | ||
97 | struct tipc_media_addr *), | ||
98 | char *(*addr2str)(struct tipc_media_addr *a, | ||
99 | char *str_buf, int str_size), | ||
100 | struct tipc_media_addr *bcast_addr, | ||
101 | const u32 bearer_priority, | ||
102 | const u32 link_tolerance, /* [ms] */ | ||
103 | const u32 send_window_limit) | ||
104 | { | ||
105 | struct media *m_ptr; | ||
106 | u32 media_id; | ||
107 | u32 i; | ||
108 | int res = -EINVAL; | ||
109 | |||
110 | write_lock_bh(&net_lock); | ||
111 | if (!media_list) | ||
112 | goto exit; | ||
113 | |||
114 | if (!media_name_valid(name)) { | ||
115 | warn("Media registration error: illegal name <%s>\n", name); | ||
116 | goto exit; | ||
117 | } | ||
118 | if (!bcast_addr) { | ||
119 | warn("Media registration error: no broadcast address supplied\n"); | ||
120 | goto exit; | ||
121 | } | ||
122 | if (bearer_priority >= TIPC_NUM_LINK_PRI) { | ||
123 | warn("Media registration error: priority %u\n", bearer_priority); | ||
124 | goto exit; | ||
125 | } | ||
126 | if ((link_tolerance < TIPC_MIN_LINK_TOL) || | ||
127 | (link_tolerance > TIPC_MAX_LINK_TOL)) { | ||
128 | warn("Media registration error: tolerance %u\n", link_tolerance); | ||
129 | goto exit; | ||
130 | } | ||
131 | |||
132 | media_id = media_count++; | ||
133 | if (media_id >= MAX_MEDIA) { | ||
134 | warn("Attempt to register more than %u media\n", MAX_MEDIA); | ||
135 | media_count--; | ||
136 | goto exit; | ||
137 | } | ||
138 | for (i = 0; i < media_id; i++) { | ||
139 | if (media_list[i].type_id == media_type) { | ||
140 | warn("Attempt to register second media with type %u\n", | ||
141 | media_type); | ||
142 | media_count--; | ||
143 | goto exit; | ||
144 | } | ||
145 | if (!strcmp(name, media_list[i].name)) { | ||
146 | warn("Attempt to re-register media name <%s>\n", name); | ||
147 | media_count--; | ||
148 | goto exit; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | m_ptr = &media_list[media_id]; | ||
153 | m_ptr->type_id = media_type; | ||
154 | m_ptr->send_msg = send_msg; | ||
155 | m_ptr->enable_bearer = enable; | ||
156 | m_ptr->disable_bearer = disable; | ||
157 | m_ptr->addr2str = addr2str; | ||
158 | memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr)); | ||
159 | m_ptr->bcast = 1; | ||
160 | strcpy(m_ptr->name, name); | ||
161 | m_ptr->priority = bearer_priority; | ||
162 | m_ptr->tolerance = link_tolerance; | ||
163 | m_ptr->window = send_window_limit; | ||
164 | dbg("Media <%s> registered\n", name); | ||
165 | res = 0; | ||
166 | exit: | ||
167 | write_unlock_bh(&net_lock); | ||
168 | return res; | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * media_addr_printf - record media address in print buffer | ||
173 | */ | ||
174 | |||
175 | void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a) | ||
176 | { | ||
177 | struct media *m_ptr; | ||
178 | u32 media_type; | ||
179 | u32 i; | ||
180 | |||
181 | media_type = ntohl(a->type); | ||
182 | for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { | ||
183 | if (m_ptr->type_id == media_type) | ||
184 | break; | ||
185 | } | ||
186 | |||
187 | if ((i < media_count) && (m_ptr->addr2str != NULL)) { | ||
188 | char addr_str[MAX_ADDR_STR]; | ||
189 | |||
190 | tipc_printf(pb, "%s(%s) ", m_ptr->name, | ||
191 | m_ptr->addr2str(a, addr_str, sizeof(addr_str))); | ||
192 | } else { | ||
193 | unchar *addr = (unchar *)&a->dev_addr; | ||
194 | |||
195 | tipc_printf(pb, "UNKNOWN(%u):", media_type); | ||
196 | for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) { | ||
197 | tipc_printf(pb, "%02x ", addr[i]); | ||
198 | } | ||
199 | } | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * media_get_names - record names of registered media in buffer | ||
204 | */ | ||
205 | |||
206 | struct sk_buff *media_get_names(void) | ||
207 | { | ||
208 | struct sk_buff *buf; | ||
209 | struct media *m_ptr; | ||
210 | int i; | ||
211 | |||
212 | buf = cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME)); | ||
213 | if (!buf) | ||
214 | return NULL; | ||
215 | |||
216 | read_lock_bh(&net_lock); | ||
217 | for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { | ||
218 | cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name, | ||
219 | strlen(m_ptr->name) + 1); | ||
220 | } | ||
221 | read_unlock_bh(&net_lock); | ||
222 | return buf; | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * bearer_name_validate - validate & (optionally) deconstruct bearer name | ||
227 | * @name - ptr to bearer name string | ||
228 | * @name_parts - ptr to area for bearer name components (or NULL if not needed) | ||
229 | * | ||
230 | * Returns 1 if bearer name is valid, otherwise 0. | ||
231 | */ | ||
232 | |||
233 | static int bearer_name_validate(const char *name, | ||
234 | struct bearer_name *name_parts) | ||
235 | { | ||
236 | char name_copy[TIPC_MAX_BEARER_NAME]; | ||
237 | char *media_name; | ||
238 | char *if_name; | ||
239 | u32 media_len; | ||
240 | u32 if_len; | ||
241 | |||
242 | /* copy bearer name & ensure length is OK */ | ||
243 | |||
244 | name_copy[TIPC_MAX_BEARER_NAME - 1] = 0; | ||
245 | /* need above in case non-Posix strncpy() doesn't pad with nulls */ | ||
246 | strncpy(name_copy, name, TIPC_MAX_BEARER_NAME); | ||
247 | if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0) | ||
248 | return 0; | ||
249 | |||
250 | /* ensure all component parts of bearer name are present */ | ||
251 | |||
252 | media_name = name_copy; | ||
253 | if ((if_name = strchr(media_name, ':')) == NULL) | ||
254 | return 0; | ||
255 | *(if_name++) = 0; | ||
256 | media_len = if_name - media_name; | ||
257 | if_len = strlen(if_name) + 1; | ||
258 | |||
259 | /* validate component parts of bearer name */ | ||
260 | |||
261 | if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) || | ||
262 | (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME) || | ||
263 | (strspn(media_name, tipc_alphabet) != (media_len - 1)) || | ||
264 | (strspn(if_name, tipc_alphabet) != (if_len - 1))) | ||
265 | return 0; | ||
266 | |||
267 | /* return bearer name components, if necessary */ | ||
268 | |||
269 | if (name_parts) { | ||
270 | strcpy(name_parts->media_name, media_name); | ||
271 | strcpy(name_parts->if_name, if_name); | ||
272 | } | ||
273 | return 1; | ||
274 | } | ||
275 | |||
276 | /** | ||
277 | * bearer_find - locates bearer object with matching bearer name | ||
278 | */ | ||
279 | |||
280 | static struct bearer *bearer_find(const char *name) | ||
281 | { | ||
282 | struct bearer *b_ptr; | ||
283 | u32 i; | ||
284 | |||
285 | for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) { | ||
286 | if (b_ptr->active && (!strcmp(b_ptr->publ.name, name))) | ||
287 | return b_ptr; | ||
288 | } | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | /** | ||
293 | * bearer_find - locates bearer object with matching interface name | ||
294 | */ | ||
295 | |||
296 | struct bearer *bearer_find_interface(const char *if_name) | ||
297 | { | ||
298 | struct bearer *b_ptr; | ||
299 | char *b_if_name; | ||
300 | u32 i; | ||
301 | |||
302 | for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) { | ||
303 | if (!b_ptr->active) | ||
304 | continue; | ||
305 | b_if_name = strchr(b_ptr->publ.name, ':') + 1; | ||
306 | if (!strcmp(b_if_name, if_name)) | ||
307 | return b_ptr; | ||
308 | } | ||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | /** | ||
313 | * bearer_get_names - record names of bearers in buffer | ||
314 | */ | ||
315 | |||
316 | struct sk_buff *bearer_get_names(void) | ||
317 | { | ||
318 | struct sk_buff *buf; | ||
319 | struct media *m_ptr; | ||
320 | struct bearer *b_ptr; | ||
321 | int i, j; | ||
322 | |||
323 | buf = cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME)); | ||
324 | if (!buf) | ||
325 | return NULL; | ||
326 | |||
327 | read_lock_bh(&net_lock); | ||
328 | for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) { | ||
329 | for (j = 0; j < MAX_BEARERS; j++) { | ||
330 | b_ptr = &bearers[j]; | ||
331 | if (b_ptr->active && (b_ptr->media == m_ptr)) { | ||
332 | cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, | ||
333 | b_ptr->publ.name, | ||
334 | strlen(b_ptr->publ.name) + 1); | ||
335 | } | ||
336 | } | ||
337 | } | ||
338 | read_unlock_bh(&net_lock); | ||
339 | return buf; | ||
340 | } | ||
341 | |||
342 | void bearer_add_dest(struct bearer *b_ptr, u32 dest) | ||
343 | { | ||
344 | nmap_add(&b_ptr->nodes, dest); | ||
345 | disc_update_link_req(b_ptr->link_req); | ||
346 | bcbearer_sort(); | ||
347 | } | ||
348 | |||
349 | void bearer_remove_dest(struct bearer *b_ptr, u32 dest) | ||
350 | { | ||
351 | nmap_remove(&b_ptr->nodes, dest); | ||
352 | disc_update_link_req(b_ptr->link_req); | ||
353 | bcbearer_sort(); | ||
354 | } | ||
355 | |||
356 | /* | ||
357 | * bearer_push(): Resolve bearer congestion. Force the waiting | ||
358 | * links to push out their unsent packets, one packet per link | ||
359 | * per iteration, until all packets are gone or congestion reoccurs. | ||
360 | * 'net_lock' is read_locked when this function is called | ||
361 | * bearer.lock must be taken before calling | ||
362 | * Returns binary true(1) ore false(0) | ||
363 | */ | ||
364 | static int bearer_push(struct bearer *b_ptr) | ||
365 | { | ||
366 | u32 res = TIPC_OK; | ||
367 | struct link *ln, *tln; | ||
368 | |||
369 | if (b_ptr->publ.blocked) | ||
370 | return 0; | ||
371 | |||
372 | while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) { | ||
373 | list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) { | ||
374 | res = link_push_packet(ln); | ||
375 | if (res == PUSH_FAILED) | ||
376 | break; | ||
377 | if (res == PUSH_FINISHED) | ||
378 | list_move_tail(&ln->link_list, &b_ptr->links); | ||
379 | } | ||
380 | } | ||
381 | return list_empty(&b_ptr->cong_links); | ||
382 | } | ||
383 | |||
384 | void bearer_lock_push(struct bearer *b_ptr) | ||
385 | { | ||
386 | int res; | ||
387 | |||
388 | spin_lock_bh(&b_ptr->publ.lock); | ||
389 | res = bearer_push(b_ptr); | ||
390 | spin_unlock_bh(&b_ptr->publ.lock); | ||
391 | if (res) | ||
392 | bcbearer_push(); | ||
393 | } | ||
394 | |||
395 | |||
396 | /* | ||
397 | * Interrupt enabling new requests after bearer congestion or blocking: | ||
398 | * See bearer_send(). | ||
399 | */ | ||
400 | void tipc_continue(struct tipc_bearer *tb_ptr) | ||
401 | { | ||
402 | struct bearer *b_ptr = (struct bearer *)tb_ptr; | ||
403 | |||
404 | spin_lock_bh(&b_ptr->publ.lock); | ||
405 | b_ptr->continue_count++; | ||
406 | if (!list_empty(&b_ptr->cong_links)) | ||
407 | k_signal((Handler)bearer_lock_push, (unsigned long)b_ptr); | ||
408 | b_ptr->publ.blocked = 0; | ||
409 | spin_unlock_bh(&b_ptr->publ.lock); | ||
410 | } | ||
411 | |||
412 | /* | ||
413 | * Schedule link for sending of messages after the bearer | ||
414 | * has been deblocked by 'continue()'. This method is called | ||
415 | * when somebody tries to send a message via this link while | ||
416 | * the bearer is congested. 'net_lock' is in read_lock here | ||
417 | * bearer.lock is busy | ||
418 | */ | ||
419 | |||
420 | static void bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr) | ||
421 | { | ||
422 | list_move_tail(&l_ptr->link_list, &b_ptr->cong_links); | ||
423 | } | ||
424 | |||
425 | /* | ||
426 | * Schedule link for sending of messages after the bearer | ||
427 | * has been deblocked by 'continue()'. This method is called | ||
428 | * when somebody tries to send a message via this link while | ||
429 | * the bearer is congested. 'net_lock' is in read_lock here, | ||
430 | * bearer.lock is free | ||
431 | */ | ||
432 | |||
433 | void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr) | ||
434 | { | ||
435 | spin_lock_bh(&b_ptr->publ.lock); | ||
436 | bearer_schedule_unlocked(b_ptr, l_ptr); | ||
437 | spin_unlock_bh(&b_ptr->publ.lock); | ||
438 | } | ||
439 | |||
440 | |||
441 | /* | ||
442 | * bearer_resolve_congestion(): Check if there is bearer congestion, | ||
443 | * and if there is, try to resolve it before returning. | ||
444 | * 'net_lock' is read_locked when this function is called | ||
445 | */ | ||
446 | int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr) | ||
447 | { | ||
448 | int res = 1; | ||
449 | |||
450 | if (list_empty(&b_ptr->cong_links)) | ||
451 | return 1; | ||
452 | spin_lock_bh(&b_ptr->publ.lock); | ||
453 | if (!bearer_push(b_ptr)) { | ||
454 | bearer_schedule_unlocked(b_ptr, l_ptr); | ||
455 | res = 0; | ||
456 | } | ||
457 | spin_unlock_bh(&b_ptr->publ.lock); | ||
458 | return res; | ||
459 | } | ||
460 | |||
461 | |||
462 | /** | ||
463 | * tipc_enable_bearer - enable bearer with the given name | ||
464 | */ | ||
465 | |||
466 | int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority) | ||
467 | { | ||
468 | struct bearer *b_ptr; | ||
469 | struct media *m_ptr; | ||
470 | struct bearer_name b_name; | ||
471 | char addr_string[16]; | ||
472 | u32 bearer_id; | ||
473 | u32 with_this_prio; | ||
474 | u32 i; | ||
475 | int res = -EINVAL; | ||
476 | |||
477 | if (tipc_mode != TIPC_NET_MODE) | ||
478 | return -ENOPROTOOPT; | ||
479 | if (!bearer_name_validate(name, &b_name) || | ||
480 | !addr_domain_valid(bcast_scope) || | ||
481 | !in_scope(bcast_scope, tipc_own_addr) || | ||
482 | (priority > TIPC_NUM_LINK_PRI)) | ||
483 | return -EINVAL; | ||
484 | |||
485 | write_lock_bh(&net_lock); | ||
486 | if (!bearers) | ||
487 | goto failed; | ||
488 | |||
489 | m_ptr = media_find(b_name.media_name); | ||
490 | if (!m_ptr) { | ||
491 | warn("No media <%s>\n", b_name.media_name); | ||
492 | goto failed; | ||
493 | } | ||
494 | if (priority == TIPC_NUM_LINK_PRI) | ||
495 | priority = m_ptr->priority; | ||
496 | |||
497 | restart: | ||
498 | bearer_id = MAX_BEARERS; | ||
499 | with_this_prio = 1; | ||
500 | for (i = MAX_BEARERS; i-- != 0; ) { | ||
501 | if (!bearers[i].active) { | ||
502 | bearer_id = i; | ||
503 | continue; | ||
504 | } | ||
505 | if (!strcmp(name, bearers[i].publ.name)) { | ||
506 | warn("Bearer <%s> already enabled\n", name); | ||
507 | goto failed; | ||
508 | } | ||
509 | if ((bearers[i].priority == priority) && | ||
510 | (++with_this_prio > 2)) { | ||
511 | if (priority-- == 0) { | ||
512 | warn("Third bearer <%s> with priority %u, unable to lower to %u\n", | ||
513 | name, priority + 1, priority); | ||
514 | goto failed; | ||
515 | } | ||
516 | warn("Third bearer <%s> with priority %u, lowering to %u\n", | ||
517 | name, priority + 1, priority); | ||
518 | goto restart; | ||
519 | } | ||
520 | } | ||
521 | if (bearer_id >= MAX_BEARERS) { | ||
522 | warn("Attempt to enable more than %d bearers\n", MAX_BEARERS); | ||
523 | goto failed; | ||
524 | } | ||
525 | |||
526 | b_ptr = &bearers[bearer_id]; | ||
527 | memset(b_ptr, 0, sizeof(struct bearer)); | ||
528 | |||
529 | strcpy(b_ptr->publ.name, name); | ||
530 | res = m_ptr->enable_bearer(&b_ptr->publ); | ||
531 | if (res) { | ||
532 | warn("Failed to enable bearer <%s>\n", name); | ||
533 | goto failed; | ||
534 | } | ||
535 | |||
536 | b_ptr->identity = bearer_id; | ||
537 | b_ptr->media = m_ptr; | ||
538 | b_ptr->net_plane = bearer_id + 'A'; | ||
539 | b_ptr->active = 1; | ||
540 | b_ptr->detect_scope = bcast_scope; | ||
541 | b_ptr->priority = priority; | ||
542 | INIT_LIST_HEAD(&b_ptr->cong_links); | ||
543 | INIT_LIST_HEAD(&b_ptr->links); | ||
544 | if (m_ptr->bcast) { | ||
545 | b_ptr->link_req = disc_init_link_req(b_ptr, &m_ptr->bcast_addr, | ||
546 | bcast_scope, 2); | ||
547 | } | ||
548 | b_ptr->publ.lock = SPIN_LOCK_UNLOCKED; | ||
549 | write_unlock_bh(&net_lock); | ||
550 | info("Enabled bearer <%s>, discovery domain %s\n", | ||
551 | name, addr_string_fill(addr_string, bcast_scope)); | ||
552 | return 0; | ||
553 | failed: | ||
554 | write_unlock_bh(&net_lock); | ||
555 | return res; | ||
556 | } | ||
557 | |||
558 | /** | ||
559 | * tipc_block_bearer(): Block the bearer with the given name, | ||
560 | * and reset all its links | ||
561 | */ | ||
562 | |||
563 | int tipc_block_bearer(const char *name) | ||
564 | { | ||
565 | struct bearer *b_ptr = 0; | ||
566 | struct link *l_ptr; | ||
567 | struct link *temp_l_ptr; | ||
568 | |||
569 | if (tipc_mode != TIPC_NET_MODE) | ||
570 | return -ENOPROTOOPT; | ||
571 | |||
572 | read_lock_bh(&net_lock); | ||
573 | b_ptr = bearer_find(name); | ||
574 | if (!b_ptr) { | ||
575 | warn("Attempt to block unknown bearer <%s>\n", name); | ||
576 | read_unlock_bh(&net_lock); | ||
577 | return -EINVAL; | ||
578 | } | ||
579 | |||
580 | spin_lock_bh(&b_ptr->publ.lock); | ||
581 | b_ptr->publ.blocked = 1; | ||
582 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | ||
583 | struct node *n_ptr = l_ptr->owner; | ||
584 | |||
585 | spin_lock_bh(&n_ptr->lock); | ||
586 | link_reset(l_ptr); | ||
587 | spin_unlock_bh(&n_ptr->lock); | ||
588 | } | ||
589 | spin_unlock_bh(&b_ptr->publ.lock); | ||
590 | read_unlock_bh(&net_lock); | ||
591 | info("Blocked bearer <%s>\n", name); | ||
592 | return TIPC_OK; | ||
593 | } | ||
594 | |||
595 | /** | ||
596 | * bearer_disable - | ||
597 | * | ||
598 | * Note: This routine assumes caller holds net_lock. | ||
599 | */ | ||
600 | |||
601 | static int bearer_disable(const char *name) | ||
602 | { | ||
603 | struct bearer *b_ptr; | ||
604 | struct link *l_ptr; | ||
605 | struct link *temp_l_ptr; | ||
606 | |||
607 | if (tipc_mode != TIPC_NET_MODE) | ||
608 | return -ENOPROTOOPT; | ||
609 | |||
610 | b_ptr = bearer_find(name); | ||
611 | if (!b_ptr) { | ||
612 | warn("Attempt to disable unknown bearer <%s>\n", name); | ||
613 | return -EINVAL; | ||
614 | } | ||
615 | |||
616 | disc_stop_link_req(b_ptr->link_req); | ||
617 | spin_lock_bh(&b_ptr->publ.lock); | ||
618 | b_ptr->link_req = NULL; | ||
619 | b_ptr->publ.blocked = 1; | ||
620 | if (b_ptr->media->disable_bearer) { | ||
621 | spin_unlock_bh(&b_ptr->publ.lock); | ||
622 | write_unlock_bh(&net_lock); | ||
623 | b_ptr->media->disable_bearer(&b_ptr->publ); | ||
624 | write_lock_bh(&net_lock); | ||
625 | spin_lock_bh(&b_ptr->publ.lock); | ||
626 | } | ||
627 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | ||
628 | link_delete(l_ptr); | ||
629 | } | ||
630 | spin_unlock_bh(&b_ptr->publ.lock); | ||
631 | info("Disabled bearer <%s>\n", name); | ||
632 | memset(b_ptr, 0, sizeof(struct bearer)); | ||
633 | return TIPC_OK; | ||
634 | } | ||
635 | |||
636 | int tipc_disable_bearer(const char *name) | ||
637 | { | ||
638 | int res; | ||
639 | |||
640 | write_lock_bh(&net_lock); | ||
641 | res = bearer_disable(name); | ||
642 | write_unlock_bh(&net_lock); | ||
643 | return res; | ||
644 | } | ||
645 | |||
646 | |||
647 | |||
648 | int bearer_init(void) | ||
649 | { | ||
650 | int res; | ||
651 | |||
652 | write_lock_bh(&net_lock); | ||
653 | bearers = kmalloc(MAX_BEARERS * sizeof(struct bearer), GFP_ATOMIC); | ||
654 | media_list = kmalloc(MAX_MEDIA * sizeof(struct media), GFP_ATOMIC); | ||
655 | if (bearers && media_list) { | ||
656 | memset(bearers, 0, MAX_BEARERS * sizeof(struct bearer)); | ||
657 | memset(media_list, 0, MAX_MEDIA * sizeof(struct media)); | ||
658 | res = TIPC_OK; | ||
659 | } else { | ||
660 | kfree(bearers); | ||
661 | kfree(media_list); | ||
662 | bearers = 0; | ||
663 | media_list = 0; | ||
664 | res = -ENOMEM; | ||
665 | } | ||
666 | write_unlock_bh(&net_lock); | ||
667 | return res; | ||
668 | } | ||
669 | |||
670 | void bearer_stop(void) | ||
671 | { | ||
672 | u32 i; | ||
673 | |||
674 | if (!bearers) | ||
675 | return; | ||
676 | |||
677 | for (i = 0; i < MAX_BEARERS; i++) { | ||
678 | if (bearers[i].active) | ||
679 | bearers[i].publ.blocked = 1; | ||
680 | } | ||
681 | for (i = 0; i < MAX_BEARERS; i++) { | ||
682 | if (bearers[i].active) | ||
683 | bearer_disable(bearers[i].publ.name); | ||
684 | } | ||
685 | kfree(bearers); | ||
686 | kfree(media_list); | ||
687 | bearers = 0; | ||
688 | media_list = 0; | ||
689 | media_count = 0; | ||
690 | } | ||
691 | |||
692 | |||
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h new file mode 100644 index 000000000000..21e63d3f0183 --- /dev/null +++ b/net/tipc/bearer.h | |||
@@ -0,0 +1,172 @@ | |||
1 | /* | ||
2 | * net/tipc/bearer.h: Include file for TIPC bearer code | ||
3 | * | ||
4 | * Copyright (c) 1996-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_BEARER_H | ||
38 | #define _TIPC_BEARER_H | ||
39 | |||
40 | #include <net/tipc/tipc_bearer.h> | ||
41 | #include "bcast.h" | ||
42 | |||
43 | #define MAX_BEARERS 8 | ||
44 | #define MAX_MEDIA 4 | ||
45 | |||
46 | |||
47 | /** | ||
48 | * struct media - TIPC media information available to internal users | ||
49 | * @send_msg: routine which handles buffer transmission | ||
50 | * @enable_bearer: routine which enables a bearer | ||
51 | * @disable_bearer: routine which disables a bearer | ||
52 | * @addr2str: routine which converts bearer's address to string form | ||
53 | * @bcast_addr: media address used in broadcasting | ||
54 | * @bcast: non-zero if media supports broadcasting [currently mandatory] | ||
55 | * @priority: default link (and bearer) priority | ||
56 | * @tolerance: default time (in ms) before declaring link failure | ||
57 | * @window: default window (in packets) before declaring link congestion | ||
58 | * @type_id: TIPC media identifier [defined in tipc_bearer.h] | ||
59 | * @name: media name | ||
60 | */ | ||
61 | |||
62 | struct media { | ||
63 | int (*send_msg)(struct sk_buff *buf, | ||
64 | struct tipc_bearer *b_ptr, | ||
65 | struct tipc_media_addr *dest); | ||
66 | int (*enable_bearer)(struct tipc_bearer *b_ptr); | ||
67 | void (*disable_bearer)(struct tipc_bearer *b_ptr); | ||
68 | char *(*addr2str)(struct tipc_media_addr *a, | ||
69 | char *str_buf, int str_size); | ||
70 | struct tipc_media_addr bcast_addr; | ||
71 | int bcast; | ||
72 | u32 priority; | ||
73 | u32 tolerance; | ||
74 | u32 window; | ||
75 | u32 type_id; | ||
76 | char name[TIPC_MAX_MEDIA_NAME]; | ||
77 | }; | ||
78 | |||
79 | /** | ||
80 | * struct bearer - TIPC bearer information available to internal users | ||
81 | * @publ: bearer information available to privileged users | ||
82 | * @media: ptr to media structure associated with bearer | ||
83 | * @priority: default link priority for bearer | ||
84 | * @detect_scope: network address mask used during automatic link creation | ||
85 | * @identity: array index of this bearer within TIPC bearer array | ||
86 | * @link_req: ptr to (optional) structure making periodic link setup requests | ||
87 | * @links: list of non-congested links associated with bearer | ||
88 | * @cong_links: list of congested links associated with bearer | ||
89 | * @continue_count: # of times bearer has resumed after congestion or blocking | ||
90 | * @active: non-zero if bearer structure is represents a bearer | ||
91 | * @net_plane: network plane ('A' through 'H') currently associated with bearer | ||
92 | * @nodes: indicates which nodes in cluster can be reached through bearer | ||
93 | */ | ||
94 | |||
95 | struct bearer { | ||
96 | struct tipc_bearer publ; | ||
97 | struct media *media; | ||
98 | u32 priority; | ||
99 | u32 detect_scope; | ||
100 | u32 identity; | ||
101 | struct link_req *link_req; | ||
102 | struct list_head links; | ||
103 | struct list_head cong_links; | ||
104 | u32 continue_count; | ||
105 | int active; | ||
106 | char net_plane; | ||
107 | struct node_map nodes; | ||
108 | }; | ||
109 | |||
110 | struct bearer_name { | ||
111 | char media_name[TIPC_MAX_MEDIA_NAME]; | ||
112 | char if_name[TIPC_MAX_IF_NAME]; | ||
113 | }; | ||
114 | |||
115 | struct link; | ||
116 | |||
117 | extern struct bearer *bearers; | ||
118 | |||
119 | void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a); | ||
120 | struct sk_buff *media_get_names(void); | ||
121 | |||
122 | struct sk_buff *bearer_get_names(void); | ||
123 | void bearer_add_dest(struct bearer *b_ptr, u32 dest); | ||
124 | void bearer_remove_dest(struct bearer *b_ptr, u32 dest); | ||
125 | void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr); | ||
126 | struct bearer *bearer_find_interface(const char *if_name); | ||
127 | int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr); | ||
128 | int bearer_init(void); | ||
129 | void bearer_stop(void); | ||
130 | int bearer_broadcast(struct sk_buff *buf, struct tipc_bearer *b_ptr, | ||
131 | struct tipc_media_addr *dest); | ||
132 | void bearer_lock_push(struct bearer *b_ptr); | ||
133 | |||
134 | |||
135 | /** | ||
136 | * bearer_send- sends buffer to destination over bearer | ||
137 | * | ||
138 | * Returns true (1) if successful, or false (0) if unable to send | ||
139 | * | ||
140 | * IMPORTANT: | ||
141 | * The media send routine must not alter the buffer being passed in | ||
142 | * as it may be needed for later retransmission! | ||
143 | * | ||
144 | * If the media send routine returns a non-zero value (indicating that | ||
145 | * it was unable to send the buffer), it must: | ||
146 | * 1) mark the bearer as blocked, | ||
147 | * 2) call tipc_continue() once the bearer is able to send again. | ||
148 | * Media types that are unable to meet these two critera must ensure their | ||
149 | * send routine always returns success -- even if the buffer was not sent -- | ||
150 | * and let TIPC's link code deal with the undelivered message. | ||
151 | */ | ||
152 | |||
153 | static inline int bearer_send(struct bearer *b_ptr, struct sk_buff *buf, | ||
154 | struct tipc_media_addr *dest) | ||
155 | { | ||
156 | return !b_ptr->media->send_msg(buf, &b_ptr->publ, dest); | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * bearer_congested - determines if bearer is currently congested | ||
161 | */ | ||
162 | |||
163 | static inline int bearer_congested(struct bearer *b_ptr, struct link *l_ptr) | ||
164 | { | ||
165 | if (unlikely(b_ptr->publ.blocked)) | ||
166 | return 1; | ||
167 | if (likely(list_empty(&b_ptr->cong_links))) | ||
168 | return 0; | ||
169 | return !bearer_resolve_congestion(b_ptr, l_ptr); | ||
170 | } | ||
171 | |||
172 | #endif | ||
diff --git a/net/tipc/cluster.c b/net/tipc/cluster.c new file mode 100644 index 000000000000..f0f7bac51d41 --- /dev/null +++ b/net/tipc/cluster.c | |||
@@ -0,0 +1,576 @@ | |||
1 | /* | ||
2 | * net/tipc/cluster.c: TIPC cluster management routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "cluster.h" | ||
39 | #include "addr.h" | ||
40 | #include "node_subscr.h" | ||
41 | #include "link.h" | ||
42 | #include "node.h" | ||
43 | #include "net.h" | ||
44 | #include "msg.h" | ||
45 | #include "bearer.h" | ||
46 | |||
47 | void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf, | ||
48 | u32 lower, u32 upper); | ||
49 | struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest); | ||
50 | |||
51 | struct node **local_nodes = 0; | ||
52 | struct node_map cluster_bcast_nodes = {0,{0,}}; | ||
53 | u32 highest_allowed_slave = 0; | ||
54 | |||
55 | struct cluster *cluster_create(u32 addr) | ||
56 | { | ||
57 | struct _zone *z_ptr; | ||
58 | struct cluster *c_ptr; | ||
59 | int max_nodes; | ||
60 | int alloc; | ||
61 | |||
62 | c_ptr = (struct cluster *)kmalloc(sizeof(*c_ptr), GFP_ATOMIC); | ||
63 | if (c_ptr == NULL) | ||
64 | return 0; | ||
65 | memset(c_ptr, 0, sizeof(*c_ptr)); | ||
66 | |||
67 | c_ptr->addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); | ||
68 | if (in_own_cluster(addr)) | ||
69 | max_nodes = LOWEST_SLAVE + tipc_max_slaves; | ||
70 | else | ||
71 | max_nodes = tipc_max_nodes + 1; | ||
72 | alloc = sizeof(void *) * (max_nodes + 1); | ||
73 | c_ptr->nodes = (struct node **)kmalloc(alloc, GFP_ATOMIC); | ||
74 | if (c_ptr->nodes == NULL) { | ||
75 | kfree(c_ptr); | ||
76 | return 0; | ||
77 | } | ||
78 | memset(c_ptr->nodes, 0, alloc); | ||
79 | if (in_own_cluster(addr)) | ||
80 | local_nodes = c_ptr->nodes; | ||
81 | c_ptr->highest_slave = LOWEST_SLAVE - 1; | ||
82 | c_ptr->highest_node = 0; | ||
83 | |||
84 | z_ptr = zone_find(tipc_zone(addr)); | ||
85 | if (z_ptr == NULL) { | ||
86 | z_ptr = zone_create(addr); | ||
87 | } | ||
88 | if (z_ptr != NULL) { | ||
89 | zone_attach_cluster(z_ptr, c_ptr); | ||
90 | c_ptr->owner = z_ptr; | ||
91 | } | ||
92 | else { | ||
93 | kfree(c_ptr); | ||
94 | c_ptr = 0; | ||
95 | } | ||
96 | |||
97 | return c_ptr; | ||
98 | } | ||
99 | |||
100 | void cluster_delete(struct cluster *c_ptr) | ||
101 | { | ||
102 | u32 n_num; | ||
103 | |||
104 | if (!c_ptr) | ||
105 | return; | ||
106 | for (n_num = 1; n_num <= c_ptr->highest_node; n_num++) { | ||
107 | node_delete(c_ptr->nodes[n_num]); | ||
108 | } | ||
109 | for (n_num = LOWEST_SLAVE; n_num <= c_ptr->highest_slave; n_num++) { | ||
110 | node_delete(c_ptr->nodes[n_num]); | ||
111 | } | ||
112 | kfree(c_ptr->nodes); | ||
113 | kfree(c_ptr); | ||
114 | } | ||
115 | |||
116 | u32 cluster_next_node(struct cluster *c_ptr, u32 addr) | ||
117 | { | ||
118 | struct node *n_ptr; | ||
119 | u32 n_num = tipc_node(addr) + 1; | ||
120 | |||
121 | if (!c_ptr) | ||
122 | return addr; | ||
123 | for (; n_num <= c_ptr->highest_node; n_num++) { | ||
124 | n_ptr = c_ptr->nodes[n_num]; | ||
125 | if (n_ptr && node_has_active_links(n_ptr)) | ||
126 | return n_ptr->addr; | ||
127 | } | ||
128 | for (n_num = 1; n_num < tipc_node(addr); n_num++) { | ||
129 | n_ptr = c_ptr->nodes[n_num]; | ||
130 | if (n_ptr && node_has_active_links(n_ptr)) | ||
131 | return n_ptr->addr; | ||
132 | } | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr) | ||
137 | { | ||
138 | u32 n_num = tipc_node(n_ptr->addr); | ||
139 | u32 max_n_num = tipc_max_nodes; | ||
140 | |||
141 | if (in_own_cluster(n_ptr->addr)) | ||
142 | max_n_num = highest_allowed_slave; | ||
143 | assert(n_num > 0); | ||
144 | assert(n_num <= max_n_num); | ||
145 | assert(c_ptr->nodes[n_num] == 0); | ||
146 | c_ptr->nodes[n_num] = n_ptr; | ||
147 | if (n_num > c_ptr->highest_node) | ||
148 | c_ptr->highest_node = n_num; | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * cluster_select_router - select router to a cluster | ||
153 | * | ||
154 | * Uses deterministic and fair algorithm. | ||
155 | */ | ||
156 | |||
157 | u32 cluster_select_router(struct cluster *c_ptr, u32 ref) | ||
158 | { | ||
159 | u32 n_num; | ||
160 | u32 ulim = c_ptr->highest_node; | ||
161 | u32 mask; | ||
162 | u32 tstart; | ||
163 | |||
164 | assert(!in_own_cluster(c_ptr->addr)); | ||
165 | if (!ulim) | ||
166 | return 0; | ||
167 | |||
168 | /* Start entry must be random */ | ||
169 | mask = tipc_max_nodes; | ||
170 | while (mask > ulim) | ||
171 | mask >>= 1; | ||
172 | tstart = ref & mask; | ||
173 | n_num = tstart; | ||
174 | |||
175 | /* Lookup upwards with wrap-around */ | ||
176 | do { | ||
177 | if (node_is_up(c_ptr->nodes[n_num])) | ||
178 | break; | ||
179 | } while (++n_num <= ulim); | ||
180 | if (n_num > ulim) { | ||
181 | n_num = 1; | ||
182 | do { | ||
183 | if (node_is_up(c_ptr->nodes[n_num])) | ||
184 | break; | ||
185 | } while (++n_num < tstart); | ||
186 | if (n_num == tstart) | ||
187 | return 0; | ||
188 | } | ||
189 | assert(n_num <= ulim); | ||
190 | return node_select_router(c_ptr->nodes[n_num], ref); | ||
191 | } | ||
192 | |||
193 | /** | ||
194 | * cluster_select_node - select destination node within a remote cluster | ||
195 | * | ||
196 | * Uses deterministic and fair algorithm. | ||
197 | */ | ||
198 | |||
199 | struct node *cluster_select_node(struct cluster *c_ptr, u32 selector) | ||
200 | { | ||
201 | u32 n_num; | ||
202 | u32 mask = tipc_max_nodes; | ||
203 | u32 start_entry; | ||
204 | |||
205 | assert(!in_own_cluster(c_ptr->addr)); | ||
206 | if (!c_ptr->highest_node) | ||
207 | return 0; | ||
208 | |||
209 | /* Start entry must be random */ | ||
210 | while (mask > c_ptr->highest_node) { | ||
211 | mask >>= 1; | ||
212 | } | ||
213 | start_entry = (selector & mask) ? selector & mask : 1u; | ||
214 | assert(start_entry <= c_ptr->highest_node); | ||
215 | |||
216 | /* Lookup upwards with wrap-around */ | ||
217 | for (n_num = start_entry; n_num <= c_ptr->highest_node; n_num++) { | ||
218 | if (node_has_active_links(c_ptr->nodes[n_num])) | ||
219 | return c_ptr->nodes[n_num]; | ||
220 | } | ||
221 | for (n_num = 1; n_num < start_entry; n_num++) { | ||
222 | if (node_has_active_links(c_ptr->nodes[n_num])) | ||
223 | return c_ptr->nodes[n_num]; | ||
224 | } | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | /* | ||
229 | * Routing table management: See description in node.c | ||
230 | */ | ||
231 | |||
232 | struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest) | ||
233 | { | ||
234 | u32 size = INT_H_SIZE + data_size; | ||
235 | struct sk_buff *buf = buf_acquire(size); | ||
236 | struct tipc_msg *msg; | ||
237 | |||
238 | if (buf) { | ||
239 | msg = buf_msg(buf); | ||
240 | memset((char *)msg, 0, size); | ||
241 | msg_init(msg, ROUTE_DISTRIBUTOR, 0, TIPC_OK, INT_H_SIZE, dest); | ||
242 | } | ||
243 | return buf; | ||
244 | } | ||
245 | |||
246 | void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest, | ||
247 | u32 lower, u32 upper) | ||
248 | { | ||
249 | struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr); | ||
250 | struct tipc_msg *msg; | ||
251 | |||
252 | if (buf) { | ||
253 | msg = buf_msg(buf); | ||
254 | msg_set_remote_node(msg, dest); | ||
255 | msg_set_type(msg, ROUTE_ADDITION); | ||
256 | cluster_multicast(c_ptr, buf, lower, upper); | ||
257 | } else { | ||
258 | warn("Memory squeeze: broadcast of new route failed\n"); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest, | ||
263 | u32 lower, u32 upper) | ||
264 | { | ||
265 | struct sk_buff *buf = cluster_prepare_routing_msg(0, c_ptr->addr); | ||
266 | struct tipc_msg *msg; | ||
267 | |||
268 | if (buf) { | ||
269 | msg = buf_msg(buf); | ||
270 | msg_set_remote_node(msg, dest); | ||
271 | msg_set_type(msg, ROUTE_REMOVAL); | ||
272 | cluster_multicast(c_ptr, buf, lower, upper); | ||
273 | } else { | ||
274 | warn("Memory squeeze: broadcast of lost route failed\n"); | ||
275 | } | ||
276 | } | ||
277 | |||
278 | void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest) | ||
279 | { | ||
280 | struct sk_buff *buf; | ||
281 | struct tipc_msg *msg; | ||
282 | u32 highest = c_ptr->highest_slave; | ||
283 | u32 n_num; | ||
284 | int send = 0; | ||
285 | |||
286 | assert(!is_slave(dest)); | ||
287 | assert(in_own_cluster(dest)); | ||
288 | assert(in_own_cluster(c_ptr->addr)); | ||
289 | if (highest <= LOWEST_SLAVE) | ||
290 | return; | ||
291 | buf = cluster_prepare_routing_msg(highest - LOWEST_SLAVE + 1, | ||
292 | c_ptr->addr); | ||
293 | if (buf) { | ||
294 | msg = buf_msg(buf); | ||
295 | msg_set_remote_node(msg, c_ptr->addr); | ||
296 | msg_set_type(msg, SLAVE_ROUTING_TABLE); | ||
297 | for (n_num = LOWEST_SLAVE; n_num <= highest; n_num++) { | ||
298 | if (c_ptr->nodes[n_num] && | ||
299 | node_has_active_links(c_ptr->nodes[n_num])) { | ||
300 | send = 1; | ||
301 | msg_set_dataoctet(msg, n_num); | ||
302 | } | ||
303 | } | ||
304 | if (send) | ||
305 | link_send(buf, dest, dest); | ||
306 | else | ||
307 | buf_discard(buf); | ||
308 | } else { | ||
309 | warn("Memory squeeze: broadcast of lost route failed\n"); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest) | ||
314 | { | ||
315 | struct sk_buff *buf; | ||
316 | struct tipc_msg *msg; | ||
317 | u32 highest = c_ptr->highest_node; | ||
318 | u32 n_num; | ||
319 | int send = 0; | ||
320 | |||
321 | if (in_own_cluster(c_ptr->addr)) | ||
322 | return; | ||
323 | assert(!is_slave(dest)); | ||
324 | assert(in_own_cluster(dest)); | ||
325 | highest = c_ptr->highest_node; | ||
326 | buf = cluster_prepare_routing_msg(highest + 1, c_ptr->addr); | ||
327 | if (buf) { | ||
328 | msg = buf_msg(buf); | ||
329 | msg_set_remote_node(msg, c_ptr->addr); | ||
330 | msg_set_type(msg, EXT_ROUTING_TABLE); | ||
331 | for (n_num = 1; n_num <= highest; n_num++) { | ||
332 | if (c_ptr->nodes[n_num] && | ||
333 | node_has_active_links(c_ptr->nodes[n_num])) { | ||
334 | send = 1; | ||
335 | msg_set_dataoctet(msg, n_num); | ||
336 | } | ||
337 | } | ||
338 | if (send) | ||
339 | link_send(buf, dest, dest); | ||
340 | else | ||
341 | buf_discard(buf); | ||
342 | } else { | ||
343 | warn("Memory squeeze: broadcast of external route failed\n"); | ||
344 | } | ||
345 | } | ||
346 | |||
347 | void cluster_send_local_routes(struct cluster *c_ptr, u32 dest) | ||
348 | { | ||
349 | struct sk_buff *buf; | ||
350 | struct tipc_msg *msg; | ||
351 | u32 highest = c_ptr->highest_node; | ||
352 | u32 n_num; | ||
353 | int send = 0; | ||
354 | |||
355 | assert(is_slave(dest)); | ||
356 | assert(in_own_cluster(c_ptr->addr)); | ||
357 | buf = cluster_prepare_routing_msg(highest, c_ptr->addr); | ||
358 | if (buf) { | ||
359 | msg = buf_msg(buf); | ||
360 | msg_set_remote_node(msg, c_ptr->addr); | ||
361 | msg_set_type(msg, LOCAL_ROUTING_TABLE); | ||
362 | for (n_num = 1; n_num <= highest; n_num++) { | ||
363 | if (c_ptr->nodes[n_num] && | ||
364 | node_has_active_links(c_ptr->nodes[n_num])) { | ||
365 | send = 1; | ||
366 | msg_set_dataoctet(msg, n_num); | ||
367 | } | ||
368 | } | ||
369 | if (send) | ||
370 | link_send(buf, dest, dest); | ||
371 | else | ||
372 | buf_discard(buf); | ||
373 | } else { | ||
374 | warn("Memory squeeze: broadcast of local route failed\n"); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | void cluster_recv_routing_table(struct sk_buff *buf) | ||
379 | { | ||
380 | struct tipc_msg *msg = buf_msg(buf); | ||
381 | struct cluster *c_ptr; | ||
382 | struct node *n_ptr; | ||
383 | unchar *node_table; | ||
384 | u32 table_size; | ||
385 | u32 router; | ||
386 | u32 rem_node = msg_remote_node(msg); | ||
387 | u32 z_num; | ||
388 | u32 c_num; | ||
389 | u32 n_num; | ||
390 | |||
391 | c_ptr = cluster_find(rem_node); | ||
392 | if (!c_ptr) { | ||
393 | c_ptr = cluster_create(rem_node); | ||
394 | if (!c_ptr) { | ||
395 | buf_discard(buf); | ||
396 | return; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | node_table = buf->data + msg_hdr_sz(msg); | ||
401 | table_size = msg_size(msg) - msg_hdr_sz(msg); | ||
402 | router = msg_prevnode(msg); | ||
403 | z_num = tipc_zone(rem_node); | ||
404 | c_num = tipc_cluster(rem_node); | ||
405 | |||
406 | switch (msg_type(msg)) { | ||
407 | case LOCAL_ROUTING_TABLE: | ||
408 | assert(is_slave(tipc_own_addr)); | ||
409 | case EXT_ROUTING_TABLE: | ||
410 | for (n_num = 1; n_num < table_size; n_num++) { | ||
411 | if (node_table[n_num]) { | ||
412 | u32 addr = tipc_addr(z_num, c_num, n_num); | ||
413 | n_ptr = c_ptr->nodes[n_num]; | ||
414 | if (!n_ptr) { | ||
415 | n_ptr = node_create(addr); | ||
416 | } | ||
417 | if (n_ptr) | ||
418 | node_add_router(n_ptr, router); | ||
419 | } | ||
420 | } | ||
421 | break; | ||
422 | case SLAVE_ROUTING_TABLE: | ||
423 | assert(!is_slave(tipc_own_addr)); | ||
424 | assert(in_own_cluster(c_ptr->addr)); | ||
425 | for (n_num = 1; n_num < table_size; n_num++) { | ||
426 | if (node_table[n_num]) { | ||
427 | u32 slave_num = n_num + LOWEST_SLAVE; | ||
428 | u32 addr = tipc_addr(z_num, c_num, slave_num); | ||
429 | n_ptr = c_ptr->nodes[slave_num]; | ||
430 | if (!n_ptr) { | ||
431 | n_ptr = node_create(addr); | ||
432 | } | ||
433 | if (n_ptr) | ||
434 | node_add_router(n_ptr, router); | ||
435 | } | ||
436 | } | ||
437 | break; | ||
438 | case ROUTE_ADDITION: | ||
439 | if (!is_slave(tipc_own_addr)) { | ||
440 | assert(!in_own_cluster(c_ptr->addr) | ||
441 | || is_slave(rem_node)); | ||
442 | } else { | ||
443 | assert(in_own_cluster(c_ptr->addr) | ||
444 | && !is_slave(rem_node)); | ||
445 | } | ||
446 | n_ptr = c_ptr->nodes[tipc_node(rem_node)]; | ||
447 | if (!n_ptr) | ||
448 | n_ptr = node_create(rem_node); | ||
449 | if (n_ptr) | ||
450 | node_add_router(n_ptr, router); | ||
451 | break; | ||
452 | case ROUTE_REMOVAL: | ||
453 | if (!is_slave(tipc_own_addr)) { | ||
454 | assert(!in_own_cluster(c_ptr->addr) | ||
455 | || is_slave(rem_node)); | ||
456 | } else { | ||
457 | assert(in_own_cluster(c_ptr->addr) | ||
458 | && !is_slave(rem_node)); | ||
459 | } | ||
460 | n_ptr = c_ptr->nodes[tipc_node(rem_node)]; | ||
461 | if (n_ptr) | ||
462 | node_remove_router(n_ptr, router); | ||
463 | break; | ||
464 | default: | ||
465 | assert(!"Illegal routing manager message received\n"); | ||
466 | } | ||
467 | buf_discard(buf); | ||
468 | } | ||
469 | |||
470 | void cluster_remove_as_router(struct cluster *c_ptr, u32 router) | ||
471 | { | ||
472 | u32 start_entry; | ||
473 | u32 tstop; | ||
474 | u32 n_num; | ||
475 | |||
476 | if (is_slave(router)) | ||
477 | return; /* Slave nodes can not be routers */ | ||
478 | |||
479 | if (in_own_cluster(c_ptr->addr)) { | ||
480 | start_entry = LOWEST_SLAVE; | ||
481 | tstop = c_ptr->highest_slave; | ||
482 | } else { | ||
483 | start_entry = 1; | ||
484 | tstop = c_ptr->highest_node; | ||
485 | } | ||
486 | |||
487 | for (n_num = start_entry; n_num <= tstop; n_num++) { | ||
488 | if (c_ptr->nodes[n_num]) { | ||
489 | node_remove_router(c_ptr->nodes[n_num], router); | ||
490 | } | ||
491 | } | ||
492 | } | ||
493 | |||
494 | /** | ||
495 | * cluster_multicast - multicast message to local nodes | ||
496 | */ | ||
497 | |||
498 | void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf, | ||
499 | u32 lower, u32 upper) | ||
500 | { | ||
501 | struct sk_buff *buf_copy; | ||
502 | struct node *n_ptr; | ||
503 | u32 n_num; | ||
504 | u32 tstop; | ||
505 | |||
506 | assert(lower <= upper); | ||
507 | assert(((lower >= 1) && (lower <= tipc_max_nodes)) || | ||
508 | ((lower >= LOWEST_SLAVE) && (lower <= highest_allowed_slave))); | ||
509 | assert(((upper >= 1) && (upper <= tipc_max_nodes)) || | ||
510 | ((upper >= LOWEST_SLAVE) && (upper <= highest_allowed_slave))); | ||
511 | assert(in_own_cluster(c_ptr->addr)); | ||
512 | |||
513 | tstop = is_slave(upper) ? c_ptr->highest_slave : c_ptr->highest_node; | ||
514 | if (tstop > upper) | ||
515 | tstop = upper; | ||
516 | for (n_num = lower; n_num <= tstop; n_num++) { | ||
517 | n_ptr = c_ptr->nodes[n_num]; | ||
518 | if (n_ptr && node_has_active_links(n_ptr)) { | ||
519 | buf_copy = skb_copy(buf, GFP_ATOMIC); | ||
520 | if (buf_copy == NULL) | ||
521 | break; | ||
522 | msg_set_destnode(buf_msg(buf_copy), n_ptr->addr); | ||
523 | link_send(buf_copy, n_ptr->addr, n_ptr->addr); | ||
524 | } | ||
525 | } | ||
526 | buf_discard(buf); | ||
527 | } | ||
528 | |||
529 | /** | ||
530 | * cluster_broadcast - broadcast message to all nodes within cluster | ||
531 | */ | ||
532 | |||
533 | void cluster_broadcast(struct sk_buff *buf) | ||
534 | { | ||
535 | struct sk_buff *buf_copy; | ||
536 | struct cluster *c_ptr; | ||
537 | struct node *n_ptr; | ||
538 | u32 n_num; | ||
539 | u32 tstart; | ||
540 | u32 tstop; | ||
541 | u32 node_type; | ||
542 | |||
543 | if (tipc_mode == TIPC_NET_MODE) { | ||
544 | c_ptr = cluster_find(tipc_own_addr); | ||
545 | assert(in_own_cluster(c_ptr->addr)); /* For now */ | ||
546 | |||
547 | /* Send to standard nodes, then repeat loop sending to slaves */ | ||
548 | tstart = 1; | ||
549 | tstop = c_ptr->highest_node; | ||
550 | for (node_type = 1; node_type <= 2; node_type++) { | ||
551 | for (n_num = tstart; n_num <= tstop; n_num++) { | ||
552 | n_ptr = c_ptr->nodes[n_num]; | ||
553 | if (n_ptr && node_has_active_links(n_ptr)) { | ||
554 | buf_copy = skb_copy(buf, GFP_ATOMIC); | ||
555 | if (buf_copy == NULL) | ||
556 | goto exit; | ||
557 | msg_set_destnode(buf_msg(buf_copy), | ||
558 | n_ptr->addr); | ||
559 | link_send(buf_copy, n_ptr->addr, | ||
560 | n_ptr->addr); | ||
561 | } | ||
562 | } | ||
563 | tstart = LOWEST_SLAVE; | ||
564 | tstop = c_ptr->highest_slave; | ||
565 | } | ||
566 | } | ||
567 | exit: | ||
568 | buf_discard(buf); | ||
569 | } | ||
570 | |||
571 | int cluster_init(void) | ||
572 | { | ||
573 | highest_allowed_slave = LOWEST_SLAVE + tipc_max_slaves; | ||
574 | return cluster_create(tipc_own_addr) ? TIPC_OK : -ENOMEM; | ||
575 | } | ||
576 | |||
diff --git a/net/tipc/cluster.h b/net/tipc/cluster.h new file mode 100644 index 000000000000..1ffb095991df --- /dev/null +++ b/net/tipc/cluster.h | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * net/tipc/cluster.h: Include file for TIPC cluster management routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_CLUSTER_H | ||
38 | #define _TIPC_CLUSTER_H | ||
39 | |||
40 | #include "addr.h" | ||
41 | #include "zone.h" | ||
42 | |||
43 | #define LOWEST_SLAVE 2048u | ||
44 | |||
45 | /** | ||
46 | * struct cluster - TIPC cluster structure | ||
47 | * @addr: network address of cluster | ||
48 | * @owner: pointer to zone that cluster belongs to | ||
49 | * @nodes: array of pointers to all nodes within cluster | ||
50 | * @highest_node: id of highest numbered node within cluster | ||
51 | * @highest_slave: (used for secondary node support) | ||
52 | */ | ||
53 | |||
54 | struct cluster { | ||
55 | u32 addr; | ||
56 | struct _zone *owner; | ||
57 | struct node **nodes; | ||
58 | u32 highest_node; | ||
59 | u32 highest_slave; | ||
60 | }; | ||
61 | |||
62 | |||
63 | extern struct node **local_nodes; | ||
64 | extern u32 highest_allowed_slave; | ||
65 | extern struct node_map cluster_bcast_nodes; | ||
66 | |||
67 | void cluster_remove_as_router(struct cluster *c_ptr, u32 router); | ||
68 | void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest); | ||
69 | struct node *cluster_select_node(struct cluster *c_ptr, u32 selector); | ||
70 | u32 cluster_select_router(struct cluster *c_ptr, u32 ref); | ||
71 | void cluster_recv_routing_table(struct sk_buff *buf); | ||
72 | struct cluster *cluster_create(u32 addr); | ||
73 | void cluster_delete(struct cluster *c_ptr); | ||
74 | void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr); | ||
75 | void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest); | ||
76 | void cluster_broadcast(struct sk_buff *buf); | ||
77 | int cluster_init(void); | ||
78 | u32 cluster_next_node(struct cluster *c_ptr, u32 addr); | ||
79 | void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); | ||
80 | void cluster_send_local_routes(struct cluster *c_ptr, u32 dest); | ||
81 | void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi); | ||
82 | |||
83 | static inline struct cluster *cluster_find(u32 addr) | ||
84 | { | ||
85 | struct _zone *z_ptr = zone_find(addr); | ||
86 | |||
87 | if (z_ptr) | ||
88 | return z_ptr->clusters[1]; | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | #endif | ||
diff --git a/net/tipc/config.c b/net/tipc/config.c new file mode 100644 index 000000000000..8ddef4fce2c2 --- /dev/null +++ b/net/tipc/config.c | |||
@@ -0,0 +1,718 @@ | |||
1 | /* | ||
2 | * net/tipc/config.c: TIPC configuration management code | ||
3 | * | ||
4 | * Copyright (c) 2002-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "dbg.h" | ||
39 | #include "bearer.h" | ||
40 | #include "port.h" | ||
41 | #include "link.h" | ||
42 | #include "zone.h" | ||
43 | #include "addr.h" | ||
44 | #include "name_table.h" | ||
45 | #include "node.h" | ||
46 | #include "config.h" | ||
47 | #include "discover.h" | ||
48 | |||
49 | struct subscr_data { | ||
50 | char usr_handle[8]; | ||
51 | u32 domain; | ||
52 | u32 port_ref; | ||
53 | struct list_head subd_list; | ||
54 | }; | ||
55 | |||
56 | struct manager { | ||
57 | u32 user_ref; | ||
58 | u32 port_ref; | ||
59 | u32 subscr_ref; | ||
60 | u32 link_subscriptions; | ||
61 | struct list_head link_subscribers; | ||
62 | }; | ||
63 | |||
64 | static struct manager mng = { 0}; | ||
65 | |||
66 | static spinlock_t config_lock = SPIN_LOCK_UNLOCKED; | ||
67 | |||
68 | static const void *req_tlv_area; /* request message TLV area */ | ||
69 | static int req_tlv_space; /* request message TLV area size */ | ||
70 | static int rep_headroom; /* reply message headroom to use */ | ||
71 | |||
72 | |||
73 | void cfg_link_event(u32 addr, char *name, int up) | ||
74 | { | ||
75 | /* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */ | ||
76 | } | ||
77 | |||
78 | |||
79 | struct sk_buff *cfg_reply_alloc(int payload_size) | ||
80 | { | ||
81 | struct sk_buff *buf; | ||
82 | |||
83 | buf = alloc_skb(rep_headroom + payload_size, GFP_ATOMIC); | ||
84 | if (buf) | ||
85 | skb_reserve(buf, rep_headroom); | ||
86 | return buf; | ||
87 | } | ||
88 | |||
89 | int cfg_append_tlv(struct sk_buff *buf, int tlv_type, | ||
90 | void *tlv_data, int tlv_data_size) | ||
91 | { | ||
92 | struct tlv_desc *tlv = (struct tlv_desc *)buf->tail; | ||
93 | int new_tlv_space = TLV_SPACE(tlv_data_size); | ||
94 | |||
95 | if (skb_tailroom(buf) < new_tlv_space) { | ||
96 | dbg("cfg_append_tlv unable to append TLV\n"); | ||
97 | return 0; | ||
98 | } | ||
99 | skb_put(buf, new_tlv_space); | ||
100 | tlv->tlv_type = htons(tlv_type); | ||
101 | tlv->tlv_len = htons(TLV_LENGTH(tlv_data_size)); | ||
102 | if (tlv_data_size && tlv_data) | ||
103 | memcpy(TLV_DATA(tlv), tlv_data, tlv_data_size); | ||
104 | return 1; | ||
105 | } | ||
106 | |||
107 | struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value) | ||
108 | { | ||
109 | struct sk_buff *buf; | ||
110 | u32 value_net; | ||
111 | |||
112 | buf = cfg_reply_alloc(TLV_SPACE(sizeof(value))); | ||
113 | if (buf) { | ||
114 | value_net = htonl(value); | ||
115 | cfg_append_tlv(buf, tlv_type, &value_net, | ||
116 | sizeof(value_net)); | ||
117 | } | ||
118 | return buf; | ||
119 | } | ||
120 | |||
121 | struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string) | ||
122 | { | ||
123 | struct sk_buff *buf; | ||
124 | int string_len = strlen(string) + 1; | ||
125 | |||
126 | buf = cfg_reply_alloc(TLV_SPACE(string_len)); | ||
127 | if (buf) | ||
128 | cfg_append_tlv(buf, tlv_type, string, string_len); | ||
129 | return buf; | ||
130 | } | ||
131 | |||
132 | |||
133 | |||
134 | |||
135 | #if 0 | ||
136 | |||
137 | /* Now obsolete code for handling commands not yet implemented the new way */ | ||
138 | |||
139 | int tipc_cfg_cmd(const struct tipc_cmd_msg * msg, | ||
140 | char *data, | ||
141 | u32 sz, | ||
142 | u32 *ret_size, | ||
143 | struct tipc_portid *orig) | ||
144 | { | ||
145 | int rv = -EINVAL; | ||
146 | u32 cmd = msg->cmd; | ||
147 | |||
148 | *ret_size = 0; | ||
149 | switch (cmd) { | ||
150 | case TIPC_REMOVE_LINK: | ||
151 | case TIPC_CMD_BLOCK_LINK: | ||
152 | case TIPC_CMD_UNBLOCK_LINK: | ||
153 | if (!cfg_check_connection(orig)) | ||
154 | rv = link_control(msg->argv.link_name, msg->cmd, 0); | ||
155 | break; | ||
156 | case TIPC_ESTABLISH: | ||
157 | { | ||
158 | int connected; | ||
159 | |||
160 | tipc_isconnected(mng.conn_port_ref, &connected); | ||
161 | if (connected || !orig) { | ||
162 | rv = TIPC_FAILURE; | ||
163 | break; | ||
164 | } | ||
165 | rv = tipc_connect2port(mng.conn_port_ref, orig); | ||
166 | if (rv == TIPC_OK) | ||
167 | orig = 0; | ||
168 | break; | ||
169 | } | ||
170 | case TIPC_GET_PEER_ADDRESS: | ||
171 | *ret_size = link_peer_addr(msg->argv.link_name, data, sz); | ||
172 | break; | ||
173 | case TIPC_GET_ROUTES: | ||
174 | rv = TIPC_OK; | ||
175 | break; | ||
176 | default: {} | ||
177 | } | ||
178 | if (*ret_size) | ||
179 | rv = TIPC_OK; | ||
180 | return rv; | ||
181 | } | ||
182 | |||
183 | static void cfg_cmd_event(struct tipc_cmd_msg *msg, | ||
184 | char *data, | ||
185 | u32 sz, | ||
186 | struct tipc_portid const *orig) | ||
187 | { | ||
188 | int rv = -EINVAL; | ||
189 | struct tipc_cmd_result_msg rmsg; | ||
190 | struct iovec msg_sect[2]; | ||
191 | int *arg; | ||
192 | |||
193 | msg->cmd = ntohl(msg->cmd); | ||
194 | |||
195 | cfg_prepare_res_msg(msg->cmd, msg->usr_handle, rv, &rmsg, msg_sect, | ||
196 | data, 0); | ||
197 | if (ntohl(msg->magic) != TIPC_MAGIC) | ||
198 | goto exit; | ||
199 | |||
200 | switch (msg->cmd) { | ||
201 | case TIPC_CREATE_LINK: | ||
202 | if (!cfg_check_connection(orig)) | ||
203 | rv = disc_create_link(&msg->argv.create_link); | ||
204 | break; | ||
205 | case TIPC_LINK_SUBSCRIBE: | ||
206 | { | ||
207 | struct subscr_data *sub; | ||
208 | |||
209 | if (mng.link_subscriptions > 64) | ||
210 | break; | ||
211 | sub = (struct subscr_data *)kmalloc(sizeof(*sub), | ||
212 | GFP_ATOMIC); | ||
213 | if (sub == NULL) { | ||
214 | warn("Memory squeeze; dropped remote link subscription\n"); | ||
215 | break; | ||
216 | } | ||
217 | INIT_LIST_HEAD(&sub->subd_list); | ||
218 | tipc_createport(mng.user_ref, | ||
219 | (void *)sub, | ||
220 | TIPC_HIGH_IMPORTANCE, | ||
221 | 0, | ||
222 | 0, | ||
223 | (tipc_conn_shutdown_event)cfg_linksubscr_cancel, | ||
224 | 0, | ||
225 | 0, | ||
226 | (tipc_conn_msg_event)cfg_linksubscr_cancel, | ||
227 | 0, | ||
228 | &sub->port_ref); | ||
229 | if (!sub->port_ref) { | ||
230 | kfree(sub); | ||
231 | break; | ||
232 | } | ||
233 | memcpy(sub->usr_handle,msg->usr_handle, | ||
234 | sizeof(sub->usr_handle)); | ||
235 | sub->domain = msg->argv.domain; | ||
236 | list_add_tail(&sub->subd_list, &mng.link_subscribers); | ||
237 | tipc_connect2port(sub->port_ref, orig); | ||
238 | rmsg.retval = TIPC_OK; | ||
239 | tipc_send(sub->port_ref, 2u, msg_sect); | ||
240 | mng.link_subscriptions++; | ||
241 | return; | ||
242 | } | ||
243 | default: | ||
244 | rv = tipc_cfg_cmd(msg, data, sz, (u32 *)&msg_sect[1].iov_len, orig); | ||
245 | } | ||
246 | exit: | ||
247 | rmsg.result_len = htonl(msg_sect[1].iov_len); | ||
248 | rmsg.retval = htonl(rv); | ||
249 | cfg_respond(msg_sect, 2u, orig); | ||
250 | } | ||
251 | #endif | ||
252 | |||
253 | static struct sk_buff *cfg_enable_bearer(void) | ||
254 | { | ||
255 | struct tipc_bearer_config *args; | ||
256 | |||
257 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_CONFIG)) | ||
258 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
259 | |||
260 | args = (struct tipc_bearer_config *)TLV_DATA(req_tlv_area); | ||
261 | if (tipc_enable_bearer(args->name, | ||
262 | ntohl(args->detect_scope), | ||
263 | ntohl(args->priority))) | ||
264 | return cfg_reply_error_string("unable to enable bearer"); | ||
265 | |||
266 | return cfg_reply_none(); | ||
267 | } | ||
268 | |||
269 | static struct sk_buff *cfg_disable_bearer(void) | ||
270 | { | ||
271 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_BEARER_NAME)) | ||
272 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
273 | |||
274 | if (tipc_disable_bearer((char *)TLV_DATA(req_tlv_area))) | ||
275 | return cfg_reply_error_string("unable to disable bearer"); | ||
276 | |||
277 | return cfg_reply_none(); | ||
278 | } | ||
279 | |||
280 | static struct sk_buff *cfg_set_own_addr(void) | ||
281 | { | ||
282 | u32 addr; | ||
283 | |||
284 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) | ||
285 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
286 | |||
287 | addr = *(u32 *)TLV_DATA(req_tlv_area); | ||
288 | addr = ntohl(addr); | ||
289 | if (addr == tipc_own_addr) | ||
290 | return cfg_reply_none(); | ||
291 | if (!addr_node_valid(addr)) | ||
292 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
293 | " (node address)"); | ||
294 | if (tipc_own_addr) | ||
295 | return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
296 | " (cannot change node address once assigned)"); | ||
297 | |||
298 | spin_unlock_bh(&config_lock); | ||
299 | stop_net(); | ||
300 | tipc_own_addr = addr; | ||
301 | start_net(); | ||
302 | spin_lock_bh(&config_lock); | ||
303 | return cfg_reply_none(); | ||
304 | } | ||
305 | |||
306 | static struct sk_buff *cfg_set_remote_mng(void) | ||
307 | { | ||
308 | u32 value; | ||
309 | |||
310 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
311 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
312 | |||
313 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
314 | value = ntohl(value); | ||
315 | tipc_remote_management = (value != 0); | ||
316 | return cfg_reply_none(); | ||
317 | } | ||
318 | |||
319 | static struct sk_buff *cfg_set_max_publications(void) | ||
320 | { | ||
321 | u32 value; | ||
322 | |||
323 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
324 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
325 | |||
326 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
327 | value = ntohl(value); | ||
328 | if (value != delimit(value, 1, 65535)) | ||
329 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
330 | " (max publications must be 1-65535)"); | ||
331 | tipc_max_publications = value; | ||
332 | return cfg_reply_none(); | ||
333 | } | ||
334 | |||
335 | static struct sk_buff *cfg_set_max_subscriptions(void) | ||
336 | { | ||
337 | u32 value; | ||
338 | |||
339 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
340 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
341 | |||
342 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
343 | value = ntohl(value); | ||
344 | if (value != delimit(value, 1, 65535)) | ||
345 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
346 | " (max subscriptions must be 1-65535"); | ||
347 | tipc_max_subscriptions = value; | ||
348 | return cfg_reply_none(); | ||
349 | } | ||
350 | |||
351 | static struct sk_buff *cfg_set_max_ports(void) | ||
352 | { | ||
353 | int orig_mode; | ||
354 | u32 value; | ||
355 | |||
356 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
357 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
358 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
359 | value = ntohl(value); | ||
360 | if (value != delimit(value, 127, 65535)) | ||
361 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
362 | " (max ports must be 127-65535)"); | ||
363 | |||
364 | if (value == tipc_max_ports) | ||
365 | return cfg_reply_none(); | ||
366 | |||
367 | if (atomic_read(&tipc_user_count) > 2) | ||
368 | return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
369 | " (cannot change max ports while TIPC users exist)"); | ||
370 | |||
371 | spin_unlock_bh(&config_lock); | ||
372 | orig_mode = tipc_get_mode(); | ||
373 | if (orig_mode == TIPC_NET_MODE) | ||
374 | stop_net(); | ||
375 | stop_core(); | ||
376 | tipc_max_ports = value; | ||
377 | start_core(); | ||
378 | if (orig_mode == TIPC_NET_MODE) | ||
379 | start_net(); | ||
380 | spin_lock_bh(&config_lock); | ||
381 | return cfg_reply_none(); | ||
382 | } | ||
383 | |||
384 | static struct sk_buff *set_net_max(int value, int *parameter) | ||
385 | { | ||
386 | int orig_mode; | ||
387 | |||
388 | if (value != *parameter) { | ||
389 | orig_mode = tipc_get_mode(); | ||
390 | if (orig_mode == TIPC_NET_MODE) | ||
391 | stop_net(); | ||
392 | *parameter = value; | ||
393 | if (orig_mode == TIPC_NET_MODE) | ||
394 | start_net(); | ||
395 | } | ||
396 | |||
397 | return cfg_reply_none(); | ||
398 | } | ||
399 | |||
400 | static struct sk_buff *cfg_set_max_zones(void) | ||
401 | { | ||
402 | u32 value; | ||
403 | |||
404 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
405 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
406 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
407 | value = ntohl(value); | ||
408 | if (value != delimit(value, 1, 255)) | ||
409 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
410 | " (max zones must be 1-255)"); | ||
411 | return set_net_max(value, &tipc_max_zones); | ||
412 | } | ||
413 | |||
414 | static struct sk_buff *cfg_set_max_clusters(void) | ||
415 | { | ||
416 | u32 value; | ||
417 | |||
418 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
419 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
420 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
421 | value = ntohl(value); | ||
422 | if (value != 1) | ||
423 | return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
424 | " (max clusters fixed at 1)"); | ||
425 | return cfg_reply_none(); | ||
426 | } | ||
427 | |||
428 | static struct sk_buff *cfg_set_max_nodes(void) | ||
429 | { | ||
430 | u32 value; | ||
431 | |||
432 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
433 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
434 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
435 | value = ntohl(value); | ||
436 | if (value != delimit(value, 8, 2047)) | ||
437 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
438 | " (max nodes must be 8-2047)"); | ||
439 | return set_net_max(value, &tipc_max_nodes); | ||
440 | } | ||
441 | |||
442 | static struct sk_buff *cfg_set_max_slaves(void) | ||
443 | { | ||
444 | u32 value; | ||
445 | |||
446 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
447 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
448 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
449 | value = ntohl(value); | ||
450 | if (value != 0) | ||
451 | return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
452 | " (max secondary nodes fixed at 0)"); | ||
453 | return cfg_reply_none(); | ||
454 | } | ||
455 | |||
456 | static struct sk_buff *cfg_set_netid(void) | ||
457 | { | ||
458 | u32 value; | ||
459 | |||
460 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
461 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
462 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
463 | value = ntohl(value); | ||
464 | if (value != delimit(value, 1, 9999)) | ||
465 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
466 | " (network id must be 1-9999)"); | ||
467 | |||
468 | if (tipc_own_addr) | ||
469 | return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
470 | " (cannot change network id once part of network)"); | ||
471 | |||
472 | return set_net_max(value, &tipc_net_id); | ||
473 | } | ||
474 | |||
475 | struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area, | ||
476 | int request_space, int reply_headroom) | ||
477 | { | ||
478 | struct sk_buff *rep_tlv_buf; | ||
479 | |||
480 | spin_lock_bh(&config_lock); | ||
481 | |||
482 | /* Save request and reply details in a well-known location */ | ||
483 | |||
484 | req_tlv_area = request_area; | ||
485 | req_tlv_space = request_space; | ||
486 | rep_headroom = reply_headroom; | ||
487 | |||
488 | /* Check command authorization */ | ||
489 | |||
490 | if (likely(orig_node == tipc_own_addr)) { | ||
491 | /* command is permitted */ | ||
492 | } else if (cmd >= 0x8000) { | ||
493 | rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
494 | " (cannot be done remotely)"); | ||
495 | goto exit; | ||
496 | } else if (!tipc_remote_management) { | ||
497 | rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NO_REMOTE); | ||
498 | goto exit; | ||
499 | } | ||
500 | else if (cmd >= 0x4000) { | ||
501 | u32 domain = 0; | ||
502 | |||
503 | if ((nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) || | ||
504 | (domain != orig_node)) { | ||
505 | rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR); | ||
506 | goto exit; | ||
507 | } | ||
508 | } | ||
509 | |||
510 | /* Call appropriate processing routine */ | ||
511 | |||
512 | switch (cmd) { | ||
513 | case TIPC_CMD_NOOP: | ||
514 | rep_tlv_buf = cfg_reply_none(); | ||
515 | break; | ||
516 | case TIPC_CMD_GET_NODES: | ||
517 | rep_tlv_buf = node_get_nodes(req_tlv_area, req_tlv_space); | ||
518 | break; | ||
519 | case TIPC_CMD_GET_LINKS: | ||
520 | rep_tlv_buf = node_get_links(req_tlv_area, req_tlv_space); | ||
521 | break; | ||
522 | case TIPC_CMD_SHOW_LINK_STATS: | ||
523 | rep_tlv_buf = link_cmd_show_stats(req_tlv_area, req_tlv_space); | ||
524 | break; | ||
525 | case TIPC_CMD_RESET_LINK_STATS: | ||
526 | rep_tlv_buf = link_cmd_reset_stats(req_tlv_area, req_tlv_space); | ||
527 | break; | ||
528 | case TIPC_CMD_SHOW_NAME_TABLE: | ||
529 | rep_tlv_buf = nametbl_get(req_tlv_area, req_tlv_space); | ||
530 | break; | ||
531 | case TIPC_CMD_GET_BEARER_NAMES: | ||
532 | rep_tlv_buf = bearer_get_names(); | ||
533 | break; | ||
534 | case TIPC_CMD_GET_MEDIA_NAMES: | ||
535 | rep_tlv_buf = media_get_names(); | ||
536 | break; | ||
537 | case TIPC_CMD_SHOW_PORTS: | ||
538 | rep_tlv_buf = port_get_ports(); | ||
539 | break; | ||
540 | #if 0 | ||
541 | case TIPC_CMD_SHOW_PORT_STATS: | ||
542 | rep_tlv_buf = port_show_stats(req_tlv_area, req_tlv_space); | ||
543 | break; | ||
544 | case TIPC_CMD_RESET_PORT_STATS: | ||
545 | rep_tlv_buf = cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED); | ||
546 | break; | ||
547 | #endif | ||
548 | case TIPC_CMD_SET_LOG_SIZE: | ||
549 | rep_tlv_buf = log_resize(req_tlv_area, req_tlv_space); | ||
550 | break; | ||
551 | case TIPC_CMD_DUMP_LOG: | ||
552 | rep_tlv_buf = log_dump(); | ||
553 | break; | ||
554 | case TIPC_CMD_SET_LINK_TOL: | ||
555 | case TIPC_CMD_SET_LINK_PRI: | ||
556 | case TIPC_CMD_SET_LINK_WINDOW: | ||
557 | rep_tlv_buf = link_cmd_config(req_tlv_area, req_tlv_space, cmd); | ||
558 | break; | ||
559 | case TIPC_CMD_ENABLE_BEARER: | ||
560 | rep_tlv_buf = cfg_enable_bearer(); | ||
561 | break; | ||
562 | case TIPC_CMD_DISABLE_BEARER: | ||
563 | rep_tlv_buf = cfg_disable_bearer(); | ||
564 | break; | ||
565 | case TIPC_CMD_SET_NODE_ADDR: | ||
566 | rep_tlv_buf = cfg_set_own_addr(); | ||
567 | break; | ||
568 | case TIPC_CMD_SET_REMOTE_MNG: | ||
569 | rep_tlv_buf = cfg_set_remote_mng(); | ||
570 | break; | ||
571 | case TIPC_CMD_SET_MAX_PORTS: | ||
572 | rep_tlv_buf = cfg_set_max_ports(); | ||
573 | break; | ||
574 | case TIPC_CMD_SET_MAX_PUBL: | ||
575 | rep_tlv_buf = cfg_set_max_publications(); | ||
576 | break; | ||
577 | case TIPC_CMD_SET_MAX_SUBSCR: | ||
578 | rep_tlv_buf = cfg_set_max_subscriptions(); | ||
579 | break; | ||
580 | case TIPC_CMD_SET_MAX_ZONES: | ||
581 | rep_tlv_buf = cfg_set_max_zones(); | ||
582 | break; | ||
583 | case TIPC_CMD_SET_MAX_CLUSTERS: | ||
584 | rep_tlv_buf = cfg_set_max_clusters(); | ||
585 | break; | ||
586 | case TIPC_CMD_SET_MAX_NODES: | ||
587 | rep_tlv_buf = cfg_set_max_nodes(); | ||
588 | break; | ||
589 | case TIPC_CMD_SET_MAX_SLAVES: | ||
590 | rep_tlv_buf = cfg_set_max_slaves(); | ||
591 | break; | ||
592 | case TIPC_CMD_SET_NETID: | ||
593 | rep_tlv_buf = cfg_set_netid(); | ||
594 | break; | ||
595 | case TIPC_CMD_GET_REMOTE_MNG: | ||
596 | rep_tlv_buf = cfg_reply_unsigned(tipc_remote_management); | ||
597 | break; | ||
598 | case TIPC_CMD_GET_MAX_PORTS: | ||
599 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_ports); | ||
600 | break; | ||
601 | case TIPC_CMD_GET_MAX_PUBL: | ||
602 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_publications); | ||
603 | break; | ||
604 | case TIPC_CMD_GET_MAX_SUBSCR: | ||
605 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_subscriptions); | ||
606 | break; | ||
607 | case TIPC_CMD_GET_MAX_ZONES: | ||
608 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_zones); | ||
609 | break; | ||
610 | case TIPC_CMD_GET_MAX_CLUSTERS: | ||
611 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_clusters); | ||
612 | break; | ||
613 | case TIPC_CMD_GET_MAX_NODES: | ||
614 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_nodes); | ||
615 | break; | ||
616 | case TIPC_CMD_GET_MAX_SLAVES: | ||
617 | rep_tlv_buf = cfg_reply_unsigned(tipc_max_slaves); | ||
618 | break; | ||
619 | case TIPC_CMD_GET_NETID: | ||
620 | rep_tlv_buf = cfg_reply_unsigned(tipc_net_id); | ||
621 | break; | ||
622 | default: | ||
623 | rep_tlv_buf = NULL; | ||
624 | break; | ||
625 | } | ||
626 | |||
627 | /* Return reply buffer */ | ||
628 | exit: | ||
629 | spin_unlock_bh(&config_lock); | ||
630 | return rep_tlv_buf; | ||
631 | } | ||
632 | |||
633 | static void cfg_named_msg_event(void *userdata, | ||
634 | u32 port_ref, | ||
635 | struct sk_buff **buf, | ||
636 | const unchar *msg, | ||
637 | u32 size, | ||
638 | u32 importance, | ||
639 | struct tipc_portid const *orig, | ||
640 | struct tipc_name_seq const *dest) | ||
641 | { | ||
642 | struct tipc_cfg_msg_hdr *req_hdr; | ||
643 | struct tipc_cfg_msg_hdr *rep_hdr; | ||
644 | struct sk_buff *rep_buf; | ||
645 | |||
646 | /* Validate configuration message header (ignore invalid message) */ | ||
647 | |||
648 | req_hdr = (struct tipc_cfg_msg_hdr *)msg; | ||
649 | if ((size < sizeof(*req_hdr)) || | ||
650 | (size != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || | ||
651 | (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { | ||
652 | warn("discarded invalid configuration message\n"); | ||
653 | return; | ||
654 | } | ||
655 | |||
656 | /* Generate reply for request (if can't, return request) */ | ||
657 | |||
658 | rep_buf = cfg_do_cmd(orig->node, | ||
659 | ntohs(req_hdr->tcm_type), | ||
660 | msg + sizeof(*req_hdr), | ||
661 | size - sizeof(*req_hdr), | ||
662 | BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr)); | ||
663 | if (rep_buf) { | ||
664 | skb_push(rep_buf, sizeof(*rep_hdr)); | ||
665 | rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data; | ||
666 | memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); | ||
667 | rep_hdr->tcm_len = htonl(rep_buf->len); | ||
668 | rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); | ||
669 | } else { | ||
670 | rep_buf = *buf; | ||
671 | *buf = NULL; | ||
672 | } | ||
673 | |||
674 | /* NEED TO ADD CODE TO HANDLE FAILED SEND (SUCH AS CONGESTION) */ | ||
675 | tipc_send_buf2port(port_ref, orig, rep_buf, rep_buf->len); | ||
676 | } | ||
677 | |||
678 | int cfg_init(void) | ||
679 | { | ||
680 | struct tipc_name_seq seq; | ||
681 | int res; | ||
682 | |||
683 | memset(&mng, 0, sizeof(mng)); | ||
684 | INIT_LIST_HEAD(&mng.link_subscribers); | ||
685 | |||
686 | res = tipc_attach(&mng.user_ref, 0, 0); | ||
687 | if (res) | ||
688 | goto failed; | ||
689 | |||
690 | res = tipc_createport(mng.user_ref, 0, TIPC_CRITICAL_IMPORTANCE, | ||
691 | NULL, NULL, NULL, | ||
692 | NULL, cfg_named_msg_event, NULL, | ||
693 | NULL, &mng.port_ref); | ||
694 | if (res) | ||
695 | goto failed; | ||
696 | |||
697 | seq.type = TIPC_CFG_SRV; | ||
698 | seq.lower = seq.upper = tipc_own_addr; | ||
699 | res = nametbl_publish_rsv(mng.port_ref, TIPC_ZONE_SCOPE, &seq); | ||
700 | if (res) | ||
701 | goto failed; | ||
702 | |||
703 | return 0; | ||
704 | |||
705 | failed: | ||
706 | err("Unable to create configuration service\n"); | ||
707 | tipc_detach(mng.user_ref); | ||
708 | mng.user_ref = 0; | ||
709 | return res; | ||
710 | } | ||
711 | |||
712 | void cfg_stop(void) | ||
713 | { | ||
714 | if (mng.user_ref) { | ||
715 | tipc_detach(mng.user_ref); | ||
716 | mng.user_ref = 0; | ||
717 | } | ||
718 | } | ||
diff --git a/net/tipc/config.h b/net/tipc/config.h new file mode 100644 index 000000000000..646377d40454 --- /dev/null +++ b/net/tipc/config.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * net/tipc/config.h: Include file for TIPC configuration service code | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_CONFIG_H | ||
38 | #define _TIPC_CONFIG_H | ||
39 | |||
40 | /* ---------------------------------------------------------------------- */ | ||
41 | |||
42 | #include <linux/tipc.h> | ||
43 | #include <linux/tipc_config.h> | ||
44 | #include "link.h" | ||
45 | |||
46 | struct sk_buff *cfg_reply_alloc(int payload_size); | ||
47 | int cfg_append_tlv(struct sk_buff *buf, int tlv_type, | ||
48 | void *tlv_data, int tlv_data_size); | ||
49 | struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value); | ||
50 | struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string); | ||
51 | |||
52 | static inline struct sk_buff *cfg_reply_none(void) | ||
53 | { | ||
54 | return cfg_reply_alloc(0); | ||
55 | } | ||
56 | |||
57 | static inline struct sk_buff *cfg_reply_unsigned(u32 value) | ||
58 | { | ||
59 | return cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value); | ||
60 | } | ||
61 | |||
62 | static inline struct sk_buff *cfg_reply_error_string(char *string) | ||
63 | { | ||
64 | return cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string); | ||
65 | } | ||
66 | |||
67 | static inline struct sk_buff *cfg_reply_ultra_string(char *string) | ||
68 | { | ||
69 | return cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string); | ||
70 | } | ||
71 | |||
72 | struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd, | ||
73 | const void *req_tlv_area, int req_tlv_space, | ||
74 | int headroom); | ||
75 | |||
76 | void cfg_link_event(u32 addr, char *name, int up); | ||
77 | int cfg_init(void); | ||
78 | void cfg_stop(void); | ||
79 | |||
80 | #endif | ||
diff --git a/net/tipc/core.c b/net/tipc/core.c new file mode 100644 index 000000000000..e83ac06e31ba --- /dev/null +++ b/net/tipc/core.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /* | ||
2 | * net/tipc/core.c: TIPC module code | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include <linux/init.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/version.h> | ||
41 | #include <linux/random.h> | ||
42 | |||
43 | #include "core.h" | ||
44 | #include "dbg.h" | ||
45 | #include "ref.h" | ||
46 | #include "net.h" | ||
47 | #include "user_reg.h" | ||
48 | #include "name_table.h" | ||
49 | #include "subscr.h" | ||
50 | #include "config.h" | ||
51 | |||
52 | int eth_media_start(void); | ||
53 | void eth_media_stop(void); | ||
54 | int handler_start(void); | ||
55 | void handler_stop(void); | ||
56 | int socket_init(void); | ||
57 | void socket_stop(void); | ||
58 | int netlink_start(void); | ||
59 | void netlink_stop(void); | ||
60 | |||
61 | #define MOD_NAME "tipc_start: " | ||
62 | |||
63 | #ifndef CONFIG_TIPC_ZONES | ||
64 | #define CONFIG_TIPC_ZONES 3 | ||
65 | #endif | ||
66 | |||
67 | #ifndef CONFIG_TIPC_CLUSTERS | ||
68 | #define CONFIG_TIPC_CLUSTERS 1 | ||
69 | #endif | ||
70 | |||
71 | #ifndef CONFIG_TIPC_NODES | ||
72 | #define CONFIG_TIPC_NODES 255 | ||
73 | #endif | ||
74 | |||
75 | #ifndef CONFIG_TIPC_SLAVE_NODES | ||
76 | #define CONFIG_TIPC_SLAVE_NODES 0 | ||
77 | #endif | ||
78 | |||
79 | #ifndef CONFIG_TIPC_PORTS | ||
80 | #define CONFIG_TIPC_PORTS 8191 | ||
81 | #endif | ||
82 | |||
83 | #ifndef CONFIG_TIPC_LOG | ||
84 | #define CONFIG_TIPC_LOG 0 | ||
85 | #endif | ||
86 | |||
87 | /* global variables used by multiple sub-systems within TIPC */ | ||
88 | |||
89 | int tipc_mode = TIPC_NOT_RUNNING; | ||
90 | int tipc_random; | ||
91 | atomic_t tipc_user_count = ATOMIC_INIT(0); | ||
92 | |||
93 | const char tipc_alphabet[] = | ||
94 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; | ||
95 | |||
96 | /* configurable TIPC parameters */ | ||
97 | |||
98 | u32 tipc_own_addr; | ||
99 | int tipc_max_zones; | ||
100 | int tipc_max_clusters; | ||
101 | int tipc_max_nodes; | ||
102 | int tipc_max_slaves; | ||
103 | int tipc_max_ports; | ||
104 | int tipc_max_subscriptions; | ||
105 | int tipc_max_publications; | ||
106 | int tipc_net_id; | ||
107 | int tipc_remote_management; | ||
108 | |||
109 | |||
110 | int tipc_get_mode(void) | ||
111 | { | ||
112 | return tipc_mode; | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * stop_net - shut down TIPC networking sub-systems | ||
117 | */ | ||
118 | |||
119 | void stop_net(void) | ||
120 | { | ||
121 | eth_media_stop(); | ||
122 | tipc_stop_net(); | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * start_net - start TIPC networking sub-systems | ||
127 | */ | ||
128 | |||
129 | int start_net(void) | ||
130 | { | ||
131 | int res; | ||
132 | |||
133 | if ((res = tipc_start_net()) || | ||
134 | (res = eth_media_start())) { | ||
135 | stop_net(); | ||
136 | } | ||
137 | return res; | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * stop_core - switch TIPC from SINGLE NODE to NOT RUNNING mode | ||
142 | */ | ||
143 | |||
144 | void stop_core(void) | ||
145 | { | ||
146 | if (tipc_mode != TIPC_NODE_MODE) | ||
147 | return; | ||
148 | |||
149 | tipc_mode = TIPC_NOT_RUNNING; | ||
150 | |||
151 | netlink_stop(); | ||
152 | handler_stop(); | ||
153 | cfg_stop(); | ||
154 | subscr_stop(); | ||
155 | reg_stop(); | ||
156 | nametbl_stop(); | ||
157 | ref_table_stop(); | ||
158 | socket_stop(); | ||
159 | } | ||
160 | |||
161 | /** | ||
162 | * start_core - switch TIPC from NOT RUNNING to SINGLE NODE mode | ||
163 | */ | ||
164 | |||
165 | int start_core(void) | ||
166 | { | ||
167 | int res; | ||
168 | |||
169 | if (tipc_mode != TIPC_NOT_RUNNING) | ||
170 | return -ENOPROTOOPT; | ||
171 | |||
172 | get_random_bytes(&tipc_random, sizeof(tipc_random)); | ||
173 | tipc_mode = TIPC_NODE_MODE; | ||
174 | |||
175 | if ((res = handler_start()) || | ||
176 | (res = ref_table_init(tipc_max_ports + tipc_max_subscriptions, | ||
177 | tipc_random)) || | ||
178 | (res = reg_start()) || | ||
179 | (res = nametbl_init()) || | ||
180 | (res = k_signal((Handler)subscr_start, 0)) || | ||
181 | (res = k_signal((Handler)cfg_init, 0)) || | ||
182 | (res = netlink_start()) || | ||
183 | (res = socket_init())) { | ||
184 | stop_core(); | ||
185 | } | ||
186 | return res; | ||
187 | } | ||
188 | |||
189 | |||
190 | static int __init tipc_init(void) | ||
191 | { | ||
192 | int res; | ||
193 | |||
194 | log_reinit(CONFIG_TIPC_LOG); | ||
195 | info("Activated (compiled " __DATE__ " " __TIME__ ")\n"); | ||
196 | |||
197 | tipc_own_addr = 0; | ||
198 | tipc_remote_management = 1; | ||
199 | tipc_max_publications = 10000; | ||
200 | tipc_max_subscriptions = 2000; | ||
201 | tipc_max_ports = delimit(CONFIG_TIPC_PORTS, 127, 65536); | ||
202 | tipc_max_zones = delimit(CONFIG_TIPC_ZONES, 1, 511); | ||
203 | tipc_max_clusters = delimit(CONFIG_TIPC_CLUSTERS, 1, 1); | ||
204 | tipc_max_nodes = delimit(CONFIG_TIPC_NODES, 8, 2047); | ||
205 | tipc_max_slaves = delimit(CONFIG_TIPC_SLAVE_NODES, 0, 2047); | ||
206 | tipc_net_id = 4711; | ||
207 | |||
208 | if ((res = start_core())) | ||
209 | err("Unable to start in single node mode\n"); | ||
210 | else | ||
211 | info("Started in single node mode\n"); | ||
212 | return res; | ||
213 | } | ||
214 | |||
215 | static void __exit tipc_exit(void) | ||
216 | { | ||
217 | stop_net(); | ||
218 | stop_core(); | ||
219 | info("Deactivated\n"); | ||
220 | log_stop(); | ||
221 | } | ||
222 | |||
223 | module_init(tipc_init); | ||
224 | module_exit(tipc_exit); | ||
225 | |||
226 | MODULE_DESCRIPTION("TIPC: Transparent Inter Process Communication"); | ||
227 | MODULE_LICENSE("Dual BSD/GPL"); | ||
228 | |||
229 | /* Native TIPC API for kernel-space applications (see tipc.h) */ | ||
230 | |||
231 | EXPORT_SYMBOL(tipc_attach); | ||
232 | EXPORT_SYMBOL(tipc_detach); | ||
233 | EXPORT_SYMBOL(tipc_get_addr); | ||
234 | EXPORT_SYMBOL(tipc_get_mode); | ||
235 | EXPORT_SYMBOL(tipc_createport); | ||
236 | EXPORT_SYMBOL(tipc_deleteport); | ||
237 | EXPORT_SYMBOL(tipc_ownidentity); | ||
238 | EXPORT_SYMBOL(tipc_portimportance); | ||
239 | EXPORT_SYMBOL(tipc_set_portimportance); | ||
240 | EXPORT_SYMBOL(tipc_portunreliable); | ||
241 | EXPORT_SYMBOL(tipc_set_portunreliable); | ||
242 | EXPORT_SYMBOL(tipc_portunreturnable); | ||
243 | EXPORT_SYMBOL(tipc_set_portunreturnable); | ||
244 | EXPORT_SYMBOL(tipc_publish); | ||
245 | EXPORT_SYMBOL(tipc_withdraw); | ||
246 | EXPORT_SYMBOL(tipc_connect2port); | ||
247 | EXPORT_SYMBOL(tipc_disconnect); | ||
248 | EXPORT_SYMBOL(tipc_shutdown); | ||
249 | EXPORT_SYMBOL(tipc_isconnected); | ||
250 | EXPORT_SYMBOL(tipc_peer); | ||
251 | EXPORT_SYMBOL(tipc_ref_valid); | ||
252 | EXPORT_SYMBOL(tipc_send); | ||
253 | EXPORT_SYMBOL(tipc_send_buf); | ||
254 | EXPORT_SYMBOL(tipc_send2name); | ||
255 | EXPORT_SYMBOL(tipc_forward2name); | ||
256 | EXPORT_SYMBOL(tipc_send_buf2name); | ||
257 | EXPORT_SYMBOL(tipc_forward_buf2name); | ||
258 | EXPORT_SYMBOL(tipc_send2port); | ||
259 | EXPORT_SYMBOL(tipc_forward2port); | ||
260 | EXPORT_SYMBOL(tipc_send_buf2port); | ||
261 | EXPORT_SYMBOL(tipc_forward_buf2port); | ||
262 | EXPORT_SYMBOL(tipc_multicast); | ||
263 | /* EXPORT_SYMBOL(tipc_multicast_buf); not available yet */ | ||
264 | EXPORT_SYMBOL(tipc_ispublished); | ||
265 | EXPORT_SYMBOL(tipc_available_nodes); | ||
266 | |||
267 | /* TIPC API for external bearers (see tipc_bearer.h) */ | ||
268 | |||
269 | EXPORT_SYMBOL(tipc_block_bearer); | ||
270 | EXPORT_SYMBOL(tipc_continue); | ||
271 | EXPORT_SYMBOL(tipc_disable_bearer); | ||
272 | EXPORT_SYMBOL(tipc_enable_bearer); | ||
273 | EXPORT_SYMBOL(tipc_recv_msg); | ||
274 | EXPORT_SYMBOL(tipc_register_media); | ||
275 | |||
276 | /* TIPC API for external APIs (see tipc_port.h) */ | ||
277 | |||
278 | EXPORT_SYMBOL(tipc_createport_raw); | ||
279 | EXPORT_SYMBOL(tipc_set_msg_option); | ||
280 | EXPORT_SYMBOL(tipc_reject_msg); | ||
281 | EXPORT_SYMBOL(tipc_send_buf_fast); | ||
282 | EXPORT_SYMBOL(tipc_acknowledge); | ||
283 | EXPORT_SYMBOL(tipc_get_port); | ||
284 | EXPORT_SYMBOL(tipc_get_handle); | ||
285 | |||
diff --git a/net/tipc/core.h b/net/tipc/core.h new file mode 100644 index 000000000000..b69b60b2cc86 --- /dev/null +++ b/net/tipc/core.h | |||
@@ -0,0 +1,316 @@ | |||
1 | /* | ||
2 | * net/tipc/core.h: Include file for TIPC global declarations | ||
3 | * | ||
4 | * Copyright (c) 2005-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_CORE_H | ||
38 | #define _TIPC_CORE_H | ||
39 | |||
40 | #include <net/tipc/tipc.h> | ||
41 | #include <linux/types.h> | ||
42 | #include <linux/kernel.h> | ||
43 | #include <linux/errno.h> | ||
44 | #include <linux/mm.h> | ||
45 | #include <linux/timer.h> | ||
46 | #include <linux/string.h> | ||
47 | #include <asm/uaccess.h> | ||
48 | #include <linux/interrupt.h> | ||
49 | #include <asm/atomic.h> | ||
50 | #include <asm/hardirq.h> | ||
51 | #include <linux/netdevice.h> | ||
52 | #include <linux/in.h> | ||
53 | #include <linux/list.h> | ||
54 | #include <linux/vmalloc.h> | ||
55 | |||
56 | /* | ||
57 | * TIPC debugging code | ||
58 | */ | ||
59 | |||
60 | #define assert(i) BUG_ON(!(i)) | ||
61 | |||
62 | struct tipc_msg; | ||
63 | extern struct print_buf *CONS, *LOG; | ||
64 | extern struct print_buf *TEE(struct print_buf *, struct print_buf *); | ||
65 | void msg_print(struct print_buf*,struct tipc_msg *,const char*); | ||
66 | void tipc_printf(struct print_buf *, const char *fmt, ...); | ||
67 | void tipc_dump(struct print_buf*,const char *fmt, ...); | ||
68 | |||
69 | #ifdef CONFIG_TIPC_DEBUG | ||
70 | |||
71 | /* | ||
72 | * TIPC debug support included: | ||
73 | * - system messages are printed to TIPC_OUTPUT print buffer | ||
74 | * - debug messages are printed to DBG_OUTPUT print buffer | ||
75 | */ | ||
76 | |||
77 | #define err(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_ERR "TIPC: " fmt, ## arg) | ||
78 | #define warn(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_WARNING "TIPC: " fmt, ## arg) | ||
79 | #define info(fmt, arg...) tipc_printf(TIPC_OUTPUT, KERN_NOTICE "TIPC: " fmt, ## arg) | ||
80 | |||
81 | #define dbg(fmt, arg...) do {if (DBG_OUTPUT) tipc_printf(DBG_OUTPUT, fmt, ## arg);} while(0) | ||
82 | #define msg_dbg(msg, txt) do {if (DBG_OUTPUT) msg_print(DBG_OUTPUT, msg, txt);} while(0) | ||
83 | #define dump(fmt, arg...) do {if (DBG_OUTPUT) tipc_dump(DBG_OUTPUT, fmt, ##arg);} while(0) | ||
84 | |||
85 | |||
86 | /* | ||
87 | * By default, TIPC_OUTPUT is defined to be system console and TIPC log buffer, | ||
88 | * while DBG_OUTPUT is the null print buffer. These defaults can be changed | ||
89 | * here, or on a per .c file basis, by redefining these symbols. The following | ||
90 | * print buffer options are available: | ||
91 | * | ||
92 | * NULL : Output to null print buffer (i.e. print nowhere) | ||
93 | * CONS : Output to system console | ||
94 | * LOG : Output to TIPC log buffer | ||
95 | * &buf : Output to user-defined buffer (struct print_buf *) | ||
96 | * TEE(&buf_a,&buf_b) : Output to two print buffers (eg. TEE(CONS,LOG) ) | ||
97 | */ | ||
98 | |||
99 | #ifndef TIPC_OUTPUT | ||
100 | #define TIPC_OUTPUT TEE(CONS,LOG) | ||
101 | #endif | ||
102 | |||
103 | #ifndef DBG_OUTPUT | ||
104 | #define DBG_OUTPUT NULL | ||
105 | #endif | ||
106 | |||
107 | #else | ||
108 | |||
109 | #ifndef DBG_OUTPUT | ||
110 | #define DBG_OUTPUT NULL | ||
111 | #endif | ||
112 | |||
113 | /* | ||
114 | * TIPC debug support not included: | ||
115 | * - system messages are printed to system console | ||
116 | * - debug messages are not printed | ||
117 | */ | ||
118 | |||
119 | #define err(fmt, arg...) printk(KERN_ERR "TIPC: " fmt , ## arg) | ||
120 | #define info(fmt, arg...) printk(KERN_INFO "TIPC: " fmt , ## arg) | ||
121 | #define warn(fmt, arg...) printk(KERN_WARNING "TIPC: " fmt , ## arg) | ||
122 | |||
123 | #define dbg(fmt, arg...) do {} while (0) | ||
124 | #define msg_dbg(msg,txt) do {} while (0) | ||
125 | #define dump(fmt,arg...) do {} while (0) | ||
126 | |||
127 | #endif | ||
128 | |||
129 | |||
130 | /* | ||
131 | * TIPC-specific error codes | ||
132 | */ | ||
133 | |||
134 | #define ELINKCONG EAGAIN /* link congestion <=> resource unavailable */ | ||
135 | |||
136 | /* | ||
137 | * Global configuration variables | ||
138 | */ | ||
139 | |||
140 | extern u32 tipc_own_addr; | ||
141 | extern int tipc_max_zones; | ||
142 | extern int tipc_max_clusters; | ||
143 | extern int tipc_max_nodes; | ||
144 | extern int tipc_max_slaves; | ||
145 | extern int tipc_max_ports; | ||
146 | extern int tipc_max_subscriptions; | ||
147 | extern int tipc_max_publications; | ||
148 | extern int tipc_net_id; | ||
149 | extern int tipc_remote_management; | ||
150 | |||
151 | /* | ||
152 | * Other global variables | ||
153 | */ | ||
154 | |||
155 | extern int tipc_mode; | ||
156 | extern int tipc_random; | ||
157 | extern const char tipc_alphabet[]; | ||
158 | extern atomic_t tipc_user_count; | ||
159 | |||
160 | |||
161 | /* | ||
162 | * Routines available to privileged subsystems | ||
163 | */ | ||
164 | |||
165 | extern int start_core(void); | ||
166 | extern void stop_core(void); | ||
167 | extern int start_net(void); | ||
168 | extern void stop_net(void); | ||
169 | |||
170 | static inline int delimit(int val, int min, int max) | ||
171 | { | ||
172 | if (val > max) | ||
173 | return max; | ||
174 | if (val < min) | ||
175 | return min; | ||
176 | return val; | ||
177 | } | ||
178 | |||
179 | |||
180 | /* | ||
181 | * TIPC timer and signal code | ||
182 | */ | ||
183 | |||
184 | typedef void (*Handler) (unsigned long); | ||
185 | |||
186 | u32 k_signal(Handler routine, unsigned long argument); | ||
187 | |||
188 | /** | ||
189 | * k_init_timer - initialize a timer | ||
190 | * @timer: pointer to timer structure | ||
191 | * @routine: pointer to routine to invoke when timer expires | ||
192 | * @argument: value to pass to routine when timer expires | ||
193 | * | ||
194 | * Timer must be initialized before use (and terminated when no longer needed). | ||
195 | */ | ||
196 | |||
197 | static inline void k_init_timer(struct timer_list *timer, Handler routine, | ||
198 | unsigned long argument) | ||
199 | { | ||
200 | dbg("initializing timer %p\n", timer); | ||
201 | init_timer(timer); | ||
202 | timer->function = routine; | ||
203 | timer->data = argument; | ||
204 | } | ||
205 | |||
206 | /** | ||
207 | * k_start_timer - start a timer | ||
208 | * @timer: pointer to timer structure | ||
209 | * @msec: time to delay (in ms) | ||
210 | * | ||
211 | * Schedules a previously initialized timer for later execution. | ||
212 | * If timer is already running, the new timeout overrides the previous request. | ||
213 | * | ||
214 | * To ensure the timer doesn't expire before the specified delay elapses, | ||
215 | * the amount of delay is rounded up when converting to the jiffies | ||
216 | * then an additional jiffy is added to account for the fact that | ||
217 | * the starting time may be in the middle of the current jiffy. | ||
218 | */ | ||
219 | |||
220 | static inline void k_start_timer(struct timer_list *timer, unsigned long msec) | ||
221 | { | ||
222 | dbg("starting timer %p for %u\n", timer, msec); | ||
223 | mod_timer(timer, jiffies + msecs_to_jiffies(msec) + 1); | ||
224 | } | ||
225 | |||
226 | /** | ||
227 | * k_cancel_timer - cancel a timer | ||
228 | * @timer: pointer to timer structure | ||
229 | * | ||
230 | * Cancels a previously initialized timer. | ||
231 | * Can be called safely even if the timer is already inactive. | ||
232 | * | ||
233 | * WARNING: Must not be called when holding locks required by the timer's | ||
234 | * timeout routine, otherwise deadlock can occur on SMP systems! | ||
235 | */ | ||
236 | |||
237 | static inline void k_cancel_timer(struct timer_list *timer) | ||
238 | { | ||
239 | dbg("cancelling timer %p\n", timer); | ||
240 | del_timer_sync(timer); | ||
241 | } | ||
242 | |||
243 | /** | ||
244 | * k_term_timer - terminate a timer | ||
245 | * @timer: pointer to timer structure | ||
246 | * | ||
247 | * Prevents further use of a previously initialized timer. | ||
248 | * | ||
249 | * WARNING: Caller must ensure timer isn't currently running. | ||
250 | * | ||
251 | * (Do not "enhance" this routine to automatically cancel an active timer, | ||
252 | * otherwise deadlock can arise when a timeout routine calls k_term_timer.) | ||
253 | */ | ||
254 | |||
255 | static inline void k_term_timer(struct timer_list *timer) | ||
256 | { | ||
257 | dbg("terminating timer %p\n", timer); | ||
258 | } | ||
259 | |||
260 | |||
261 | /* | ||
262 | * TIPC message buffer code | ||
263 | * | ||
264 | * TIPC message buffer headroom leaves room for 14 byte Ethernet header, | ||
265 | * while ensuring TIPC header is word aligned for quicker access | ||
266 | */ | ||
267 | |||
268 | #define BUF_HEADROOM 16u | ||
269 | |||
270 | struct tipc_skb_cb { | ||
271 | void *handle; | ||
272 | }; | ||
273 | |||
274 | #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) | ||
275 | |||
276 | |||
277 | static inline struct tipc_msg *buf_msg(struct sk_buff *skb) | ||
278 | { | ||
279 | return (struct tipc_msg *)skb->data; | ||
280 | } | ||
281 | |||
282 | /** | ||
283 | * buf_acquire - creates a TIPC message buffer | ||
284 | * @size: message size (including TIPC header) | ||
285 | * | ||
286 | * Returns a new buffer. Space is reserved for a data link header. | ||
287 | */ | ||
288 | |||
289 | static inline struct sk_buff *buf_acquire(u32 size) | ||
290 | { | ||
291 | struct sk_buff *skb; | ||
292 | unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; | ||
293 | |||
294 | skb = alloc_skb(buf_size, GFP_ATOMIC); | ||
295 | if (skb) { | ||
296 | skb_reserve(skb, BUF_HEADROOM); | ||
297 | skb_put(skb, size); | ||
298 | skb->next = NULL; | ||
299 | } | ||
300 | return skb; | ||
301 | } | ||
302 | |||
303 | /** | ||
304 | * buf_discard - frees a TIPC message buffer | ||
305 | * @skb: message buffer | ||
306 | * | ||
307 | * Frees a new buffer. If passed NULL, just returns. | ||
308 | */ | ||
309 | |||
310 | static inline void buf_discard(struct sk_buff *skb) | ||
311 | { | ||
312 | if (likely(skb != NULL)) | ||
313 | kfree_skb(skb); | ||
314 | } | ||
315 | |||
316 | #endif | ||
diff --git a/net/tipc/dbg.c b/net/tipc/dbg.c new file mode 100644 index 000000000000..7ed60a1cfbb8 --- /dev/null +++ b/net/tipc/dbg.c | |||
@@ -0,0 +1,395 @@ | |||
1 | /* | ||
2 | * net/tipc/dbg.c: TIPC print buffer routines for debuggign | ||
3 | * | ||
4 | * Copyright (c) 1996-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "config.h" | ||
39 | #include "dbg.h" | ||
40 | |||
41 | #define MAX_STRING 512 | ||
42 | |||
43 | static char print_string[MAX_STRING]; | ||
44 | static spinlock_t print_lock = SPIN_LOCK_UNLOCKED; | ||
45 | |||
46 | static struct print_buf cons_buf = { NULL, 0, NULL, NULL }; | ||
47 | struct print_buf *CONS = &cons_buf; | ||
48 | |||
49 | static struct print_buf log_buf = { NULL, 0, NULL, NULL }; | ||
50 | struct print_buf *LOG = &log_buf; | ||
51 | |||
52 | |||
53 | #define FORMAT(PTR,LEN,FMT) \ | ||
54 | {\ | ||
55 | va_list args;\ | ||
56 | va_start(args, FMT);\ | ||
57 | LEN = vsprintf(PTR, FMT, args);\ | ||
58 | va_end(args);\ | ||
59 | *(PTR + LEN) = '\0';\ | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * Locking policy when using print buffers. | ||
64 | * | ||
65 | * 1) Routines of the form printbuf_XXX() rely on the caller to prevent | ||
66 | * simultaneous use of the print buffer(s) being manipulated. | ||
67 | * 2) tipc_printf() uses 'print_lock' to prevent simultaneous use of | ||
68 | * 'print_string' and to protect its print buffer(s). | ||
69 | * 3) TEE() uses 'print_lock' to protect its print buffer(s). | ||
70 | * 4) Routines of the form log_XXX() uses 'print_lock' to protect LOG. | ||
71 | */ | ||
72 | |||
73 | /** | ||
74 | * printbuf_init - initialize print buffer to empty | ||
75 | */ | ||
76 | |||
77 | void printbuf_init(struct print_buf *pb, char *raw, u32 sz) | ||
78 | { | ||
79 | if (!pb || !raw || (sz < (MAX_STRING + 1))) | ||
80 | return; | ||
81 | |||
82 | pb->crs = pb->buf = raw; | ||
83 | pb->size = sz; | ||
84 | pb->next = 0; | ||
85 | pb->buf[0] = 0; | ||
86 | pb->buf[sz-1] = ~0; | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * printbuf_reset - reinitialize print buffer to empty state | ||
91 | */ | ||
92 | |||
93 | void printbuf_reset(struct print_buf *pb) | ||
94 | { | ||
95 | if (pb && pb->buf) | ||
96 | printbuf_init(pb, pb->buf, pb->size); | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * printbuf_empty - test if print buffer is in empty state | ||
101 | */ | ||
102 | |||
103 | int printbuf_empty(struct print_buf *pb) | ||
104 | { | ||
105 | return (!pb || !pb->buf || (pb->crs == pb->buf)); | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * printbuf_validate - check for print buffer overflow | ||
110 | * | ||
111 | * Verifies that a print buffer has captured all data written to it. | ||
112 | * If data has been lost, linearize buffer and prepend an error message | ||
113 | * | ||
114 | * Returns length of print buffer data string (including trailing NULL) | ||
115 | */ | ||
116 | |||
117 | int printbuf_validate(struct print_buf *pb) | ||
118 | { | ||
119 | char *err = " *** PRINT BUFFER WRAPPED AROUND ***\n"; | ||
120 | char *cp_buf; | ||
121 | struct print_buf cb; | ||
122 | |||
123 | if (!pb || !pb->buf) | ||
124 | return 0; | ||
125 | |||
126 | if (pb->buf[pb->size - 1] == '\0') { | ||
127 | cp_buf = kmalloc(pb->size, GFP_ATOMIC); | ||
128 | if (cp_buf != NULL){ | ||
129 | printbuf_init(&cb, cp_buf, pb->size); | ||
130 | printbuf_move(&cb, pb); | ||
131 | printbuf_move(pb, &cb); | ||
132 | kfree(cp_buf); | ||
133 | memcpy(pb->buf, err, strlen(err)); | ||
134 | } else { | ||
135 | printbuf_reset(pb); | ||
136 | tipc_printf(pb, err); | ||
137 | } | ||
138 | } | ||
139 | return (pb->crs - pb->buf + 1); | ||
140 | } | ||
141 | |||
142 | /** | ||
143 | * printbuf_move - move print buffer contents to another print buffer | ||
144 | * | ||
145 | * Current contents of destination print buffer (if any) are discarded. | ||
146 | * Source print buffer becomes empty if a successful move occurs. | ||
147 | */ | ||
148 | |||
149 | void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from) | ||
150 | { | ||
151 | int len; | ||
152 | |||
153 | /* Handle the cases where contents can't be moved */ | ||
154 | |||
155 | if (!pb_to || !pb_to->buf) | ||
156 | return; | ||
157 | |||
158 | if (!pb_from || !pb_from->buf) { | ||
159 | printbuf_reset(pb_to); | ||
160 | return; | ||
161 | } | ||
162 | |||
163 | if (pb_to->size < pb_from->size) { | ||
164 | printbuf_reset(pb_to); | ||
165 | tipc_printf(pb_to, "*** PRINT BUFFER OVERFLOW ***"); | ||
166 | return; | ||
167 | } | ||
168 | |||
169 | /* Copy data from char after cursor to end (if used) */ | ||
170 | len = pb_from->buf + pb_from->size - pb_from->crs - 2; | ||
171 | if ((pb_from->buf[pb_from->size-1] == 0) && (len > 0)) { | ||
172 | strcpy(pb_to->buf, pb_from->crs + 1); | ||
173 | pb_to->crs = pb_to->buf + len; | ||
174 | } else | ||
175 | pb_to->crs = pb_to->buf; | ||
176 | |||
177 | /* Copy data from start to cursor (always) */ | ||
178 | len = pb_from->crs - pb_from->buf; | ||
179 | strcpy(pb_to->crs, pb_from->buf); | ||
180 | pb_to->crs += len; | ||
181 | |||
182 | printbuf_reset(pb_from); | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * tipc_printf - append formatted output to print buffer chain | ||
187 | */ | ||
188 | |||
189 | void tipc_printf(struct print_buf *pb, const char *fmt, ...) | ||
190 | { | ||
191 | int chars_to_add; | ||
192 | int chars_left; | ||
193 | char save_char; | ||
194 | struct print_buf *pb_next; | ||
195 | |||
196 | spin_lock_bh(&print_lock); | ||
197 | FORMAT(print_string, chars_to_add, fmt); | ||
198 | if (chars_to_add >= MAX_STRING) | ||
199 | strcpy(print_string, "*** STRING TOO LONG ***"); | ||
200 | |||
201 | while (pb) { | ||
202 | if (pb == CONS) | ||
203 | printk(print_string); | ||
204 | else if (pb->buf) { | ||
205 | chars_left = pb->buf + pb->size - pb->crs - 1; | ||
206 | if (chars_to_add <= chars_left) { | ||
207 | strcpy(pb->crs, print_string); | ||
208 | pb->crs += chars_to_add; | ||
209 | } else { | ||
210 | strcpy(pb->buf, print_string + chars_left); | ||
211 | save_char = print_string[chars_left]; | ||
212 | print_string[chars_left] = 0; | ||
213 | strcpy(pb->crs, print_string); | ||
214 | print_string[chars_left] = save_char; | ||
215 | pb->crs = pb->buf + chars_to_add - chars_left; | ||
216 | } | ||
217 | } | ||
218 | pb_next = pb->next; | ||
219 | pb->next = 0; | ||
220 | pb = pb_next; | ||
221 | } | ||
222 | spin_unlock_bh(&print_lock); | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * TEE - perform next output operation on both print buffers | ||
227 | */ | ||
228 | |||
229 | struct print_buf *TEE(struct print_buf *b0, struct print_buf *b1) | ||
230 | { | ||
231 | struct print_buf *pb = b0; | ||
232 | |||
233 | if (!b0 || (b0 == b1)) | ||
234 | return b1; | ||
235 | if (!b1) | ||
236 | return b0; | ||
237 | |||
238 | spin_lock_bh(&print_lock); | ||
239 | while (pb->next) { | ||
240 | if ((pb->next == b1) || (pb->next == b0)) | ||
241 | pb->next = pb->next->next; | ||
242 | else | ||
243 | pb = pb->next; | ||
244 | } | ||
245 | pb->next = b1; | ||
246 | spin_unlock_bh(&print_lock); | ||
247 | return b0; | ||
248 | } | ||
249 | |||
250 | /** | ||
251 | * print_to_console - write string of bytes to console in multiple chunks | ||
252 | */ | ||
253 | |||
254 | static void print_to_console(char *crs, int len) | ||
255 | { | ||
256 | int rest = len; | ||
257 | |||
258 | while (rest > 0) { | ||
259 | int sz = rest < MAX_STRING ? rest : MAX_STRING; | ||
260 | char c = crs[sz]; | ||
261 | |||
262 | crs[sz] = 0; | ||
263 | printk((const char *)crs); | ||
264 | crs[sz] = c; | ||
265 | rest -= sz; | ||
266 | crs += sz; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | /** | ||
271 | * printbuf_dump - write print buffer contents to console | ||
272 | */ | ||
273 | |||
274 | static void printbuf_dump(struct print_buf *pb) | ||
275 | { | ||
276 | int len; | ||
277 | |||
278 | /* Dump print buffer from char after cursor to end (if used) */ | ||
279 | len = pb->buf + pb->size - pb->crs - 2; | ||
280 | if ((pb->buf[pb->size - 1] == 0) && (len > 0)) | ||
281 | print_to_console(pb->crs + 1, len); | ||
282 | |||
283 | /* Dump print buffer from start to cursor (always) */ | ||
284 | len = pb->crs - pb->buf; | ||
285 | print_to_console(pb->buf, len); | ||
286 | } | ||
287 | |||
288 | /** | ||
289 | * tipc_dump - dump non-console print buffer(s) to console | ||
290 | */ | ||
291 | |||
292 | void tipc_dump(struct print_buf *pb, const char *fmt, ...) | ||
293 | { | ||
294 | int len; | ||
295 | |||
296 | spin_lock_bh(&print_lock); | ||
297 | FORMAT(CONS->buf, len, fmt); | ||
298 | printk(CONS->buf); | ||
299 | |||
300 | for (; pb; pb = pb->next) { | ||
301 | if (pb == CONS) | ||
302 | continue; | ||
303 | printk("\n---- Start of dump,%s log ----\n\n", | ||
304 | (pb == LOG) ? "global" : "local"); | ||
305 | printbuf_dump(pb); | ||
306 | printbuf_reset(pb); | ||
307 | printk("\n-------- End of dump --------\n"); | ||
308 | } | ||
309 | spin_unlock_bh(&print_lock); | ||
310 | } | ||
311 | |||
312 | /** | ||
313 | * log_stop - free up TIPC log print buffer | ||
314 | */ | ||
315 | |||
316 | void log_stop(void) | ||
317 | { | ||
318 | spin_lock_bh(&print_lock); | ||
319 | if (LOG->buf) { | ||
320 | kfree(LOG->buf); | ||
321 | LOG->buf = NULL; | ||
322 | } | ||
323 | spin_unlock_bh(&print_lock); | ||
324 | } | ||
325 | |||
326 | /** | ||
327 | * log_reinit - set TIPC log print buffer to specified size | ||
328 | */ | ||
329 | |||
330 | void log_reinit(int log_size) | ||
331 | { | ||
332 | log_stop(); | ||
333 | |||
334 | if (log_size) { | ||
335 | if (log_size <= MAX_STRING) | ||
336 | log_size = MAX_STRING + 1; | ||
337 | spin_lock_bh(&print_lock); | ||
338 | printbuf_init(LOG, kmalloc(log_size, GFP_ATOMIC), log_size); | ||
339 | spin_unlock_bh(&print_lock); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | /** | ||
344 | * log_resize - reconfigure size of TIPC log buffer | ||
345 | */ | ||
346 | |||
347 | struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space) | ||
348 | { | ||
349 | u32 value; | ||
350 | |||
351 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
352 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
353 | |||
354 | value = *(u32 *)TLV_DATA(req_tlv_area); | ||
355 | value = ntohl(value); | ||
356 | if (value != delimit(value, 0, 32768)) | ||
357 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
358 | " (log size must be 0-32768)"); | ||
359 | log_reinit(value); | ||
360 | return cfg_reply_none(); | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * log_dump - capture TIPC log buffer contents in configuration message | ||
365 | */ | ||
366 | |||
367 | struct sk_buff *log_dump(void) | ||
368 | { | ||
369 | struct sk_buff *reply; | ||
370 | |||
371 | spin_lock_bh(&print_lock); | ||
372 | if (!LOG->buf) | ||
373 | reply = cfg_reply_ultra_string("log not activated\n"); | ||
374 | else if (printbuf_empty(LOG)) | ||
375 | reply = cfg_reply_ultra_string("log is empty\n"); | ||
376 | else { | ||
377 | struct tlv_desc *rep_tlv; | ||
378 | struct print_buf pb; | ||
379 | int str_len; | ||
380 | |||
381 | str_len = min(LOG->size, 32768u); | ||
382 | reply = cfg_reply_alloc(TLV_SPACE(str_len)); | ||
383 | if (reply) { | ||
384 | rep_tlv = (struct tlv_desc *)reply->data; | ||
385 | printbuf_init(&pb, TLV_DATA(rep_tlv), str_len); | ||
386 | printbuf_move(&pb, LOG); | ||
387 | str_len = strlen(TLV_DATA(rep_tlv)) + 1; | ||
388 | skb_put(reply, TLV_SPACE(str_len)); | ||
389 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | ||
390 | } | ||
391 | } | ||
392 | spin_unlock_bh(&print_lock); | ||
393 | return reply; | ||
394 | } | ||
395 | |||
diff --git a/net/tipc/dbg.h b/net/tipc/dbg.h new file mode 100644 index 000000000000..c6b2a64c224f --- /dev/null +++ b/net/tipc/dbg.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * net/tipc/dbg.h: Include file for TIPC print buffer routines | ||
3 | * | ||
4 | * Copyright (c) 1997-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_DBG_H | ||
38 | #define _TIPC_DBG_H | ||
39 | |||
40 | struct print_buf { | ||
41 | char *buf; | ||
42 | u32 size; | ||
43 | char *crs; | ||
44 | struct print_buf *next; | ||
45 | }; | ||
46 | |||
47 | void printbuf_init(struct print_buf *pb, char *buf, u32 sz); | ||
48 | void printbuf_reset(struct print_buf *pb); | ||
49 | int printbuf_empty(struct print_buf *pb); | ||
50 | int printbuf_validate(struct print_buf *pb); | ||
51 | void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from); | ||
52 | |||
53 | void log_reinit(int log_size); | ||
54 | void log_stop(void); | ||
55 | |||
56 | struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space); | ||
57 | struct sk_buff *log_dump(void); | ||
58 | |||
59 | #endif | ||
diff --git a/net/tipc/discover.c b/net/tipc/discover.c new file mode 100644 index 000000000000..b106ef1621cc --- /dev/null +++ b/net/tipc/discover.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* | ||
2 | * net/tipc/discover.c | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "dbg.h" | ||
39 | #include "link.h" | ||
40 | #include "zone.h" | ||
41 | #include "discover.h" | ||
42 | #include "port.h" | ||
43 | #include "name_table.h" | ||
44 | |||
45 | #define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */ | ||
46 | #define TIPC_LINK_REQ_FAST 2000 /* normal delay if bearer has no links */ | ||
47 | #define TIPC_LINK_REQ_SLOW 600000 /* normal delay if bearer has links */ | ||
48 | |||
49 | #if 0 | ||
50 | #define GET_NODE_INFO 300 | ||
51 | #define GET_NODE_INFO_RESULT 301 | ||
52 | #define FORWARD_LINK_PROBE 302 | ||
53 | #define LINK_REQUEST_REJECTED 303 | ||
54 | #define LINK_REQUEST_ACCEPTED 304 | ||
55 | #define DROP_LINK_REQUEST 305 | ||
56 | #define CHECK_LINK_COUNT 306 | ||
57 | #endif | ||
58 | |||
59 | /* | ||
60 | * TODO: Most of the inter-cluster setup stuff should be | ||
61 | * rewritten, and be made conformant with specification. | ||
62 | */ | ||
63 | |||
64 | |||
65 | /** | ||
66 | * struct link_req - information about an ongoing link setup request | ||
67 | * @bearer: bearer issuing requests | ||
68 | * @dest: destination address for request messages | ||
69 | * @buf: request message to be (repeatedly) sent | ||
70 | * @timer: timer governing period between requests | ||
71 | * @timer_intv: current interval between requests (in ms) | ||
72 | */ | ||
73 | struct link_req { | ||
74 | struct bearer *bearer; | ||
75 | struct tipc_media_addr dest; | ||
76 | struct sk_buff *buf; | ||
77 | struct timer_list timer; | ||
78 | unsigned int timer_intv; | ||
79 | }; | ||
80 | |||
81 | |||
82 | #if 0 | ||
83 | int disc_create_link(const struct tipc_link_create *argv) | ||
84 | { | ||
85 | /* | ||
86 | * Code for inter cluster link setup here | ||
87 | */ | ||
88 | return TIPC_OK; | ||
89 | } | ||
90 | #endif | ||
91 | |||
92 | /* | ||
93 | * disc_lost_link(): A link has lost contact | ||
94 | */ | ||
95 | |||
96 | void disc_link_event(u32 addr, char *name, int up) | ||
97 | { | ||
98 | if (in_own_cluster(addr)) | ||
99 | return; | ||
100 | /* | ||
101 | * Code for inter cluster link setup here | ||
102 | */ | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * disc_init_msg - initialize a link setup message | ||
107 | * @type: message type (request or response) | ||
108 | * @req_links: number of links associated with message | ||
109 | * @dest_domain: network domain of node(s) which should respond to message | ||
110 | * @b_ptr: ptr to bearer issuing message | ||
111 | */ | ||
112 | |||
113 | struct sk_buff *disc_init_msg(u32 type, | ||
114 | u32 req_links, | ||
115 | u32 dest_domain, | ||
116 | struct bearer *b_ptr) | ||
117 | { | ||
118 | struct sk_buff *buf = buf_acquire(DSC_H_SIZE); | ||
119 | struct tipc_msg *msg; | ||
120 | |||
121 | if (buf) { | ||
122 | msg = buf_msg(buf); | ||
123 | msg_init(msg, LINK_CONFIG, type, TIPC_OK, DSC_H_SIZE, | ||
124 | dest_domain); | ||
125 | msg_set_non_seq(msg); | ||
126 | msg_set_req_links(msg, req_links); | ||
127 | msg_set_dest_domain(msg, dest_domain); | ||
128 | msg_set_bc_netid(msg, tipc_net_id); | ||
129 | msg_set_media_addr(msg, &b_ptr->publ.addr); | ||
130 | } | ||
131 | return buf; | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * disc_recv_msg - handle incoming link setup message (request or response) | ||
136 | * @buf: buffer containing message | ||
137 | */ | ||
138 | |||
139 | void disc_recv_msg(struct sk_buff *buf) | ||
140 | { | ||
141 | struct bearer *b_ptr = (struct bearer *)TIPC_SKB_CB(buf)->handle; | ||
142 | struct link *link; | ||
143 | struct tipc_media_addr media_addr; | ||
144 | struct tipc_msg *msg = buf_msg(buf); | ||
145 | u32 dest = msg_dest_domain(msg); | ||
146 | u32 orig = msg_prevnode(msg); | ||
147 | u32 net_id = msg_bc_netid(msg); | ||
148 | u32 type = msg_type(msg); | ||
149 | |||
150 | msg_get_media_addr(msg,&media_addr); | ||
151 | msg_dbg(msg, "RECV:"); | ||
152 | buf_discard(buf); | ||
153 | |||
154 | if (net_id != tipc_net_id) | ||
155 | return; | ||
156 | if (!addr_domain_valid(dest)) | ||
157 | return; | ||
158 | if (!addr_node_valid(orig)) | ||
159 | return; | ||
160 | if (orig == tipc_own_addr) | ||
161 | return; | ||
162 | if (!in_scope(dest, tipc_own_addr)) | ||
163 | return; | ||
164 | if (is_slave(tipc_own_addr) && is_slave(orig)) | ||
165 | return; | ||
166 | if (is_slave(orig) && !in_own_cluster(orig)) | ||
167 | return; | ||
168 | if (in_own_cluster(orig)) { | ||
169 | /* Always accept link here */ | ||
170 | struct sk_buff *rbuf; | ||
171 | struct tipc_media_addr *addr; | ||
172 | struct node *n_ptr = node_find(orig); | ||
173 | int link_up; | ||
174 | dbg(" in own cluster\n"); | ||
175 | if (n_ptr == NULL) { | ||
176 | n_ptr = node_create(orig); | ||
177 | } | ||
178 | if (n_ptr == NULL) { | ||
179 | warn("Memory squeeze; Failed to create node\n"); | ||
180 | return; | ||
181 | } | ||
182 | spin_lock_bh(&n_ptr->lock); | ||
183 | link = n_ptr->links[b_ptr->identity]; | ||
184 | if (!link) { | ||
185 | dbg("creating link\n"); | ||
186 | link = link_create(b_ptr, orig, &media_addr); | ||
187 | if (!link) { | ||
188 | spin_unlock_bh(&n_ptr->lock); | ||
189 | return; | ||
190 | } | ||
191 | } | ||
192 | addr = &link->media_addr; | ||
193 | if (memcmp(addr, &media_addr, sizeof(*addr))) { | ||
194 | char addr_string[16]; | ||
195 | |||
196 | warn("New bearer address for %s\n", | ||
197 | addr_string_fill(addr_string, orig)); | ||
198 | memcpy(addr, &media_addr, sizeof(*addr)); | ||
199 | link_reset(link); | ||
200 | } | ||
201 | link_up = link_is_up(link); | ||
202 | spin_unlock_bh(&n_ptr->lock); | ||
203 | if ((type == DSC_RESP_MSG) || link_up) | ||
204 | return; | ||
205 | rbuf = disc_init_msg(DSC_RESP_MSG, 1, orig, b_ptr); | ||
206 | if (rbuf != NULL) { | ||
207 | msg_dbg(buf_msg(rbuf),"SEND:"); | ||
208 | b_ptr->media->send_msg(rbuf, &b_ptr->publ, &media_addr); | ||
209 | buf_discard(rbuf); | ||
210 | } | ||
211 | } | ||
212 | } | ||
213 | |||
214 | /** | ||
215 | * disc_stop_link_req - stop sending periodic link setup requests | ||
216 | * @req: ptr to link request structure | ||
217 | */ | ||
218 | |||
219 | void disc_stop_link_req(struct link_req *req) | ||
220 | { | ||
221 | if (!req) | ||
222 | return; | ||
223 | |||
224 | k_cancel_timer(&req->timer); | ||
225 | k_term_timer(&req->timer); | ||
226 | buf_discard(req->buf); | ||
227 | kfree(req); | ||
228 | } | ||
229 | |||
230 | /** | ||
231 | * disc_update_link_req - update frequency of periodic link setup requests | ||
232 | * @req: ptr to link request structure | ||
233 | */ | ||
234 | |||
235 | void disc_update_link_req(struct link_req *req) | ||
236 | { | ||
237 | if (!req) | ||
238 | return; | ||
239 | |||
240 | if (req->timer_intv == TIPC_LINK_REQ_SLOW) { | ||
241 | if (!req->bearer->nodes.count) { | ||
242 | req->timer_intv = TIPC_LINK_REQ_FAST; | ||
243 | k_start_timer(&req->timer, req->timer_intv); | ||
244 | } | ||
245 | } else if (req->timer_intv == TIPC_LINK_REQ_FAST) { | ||
246 | if (req->bearer->nodes.count) { | ||
247 | req->timer_intv = TIPC_LINK_REQ_SLOW; | ||
248 | k_start_timer(&req->timer, req->timer_intv); | ||
249 | } | ||
250 | } else { | ||
251 | /* leave timer "as is" if haven't yet reached a "normal" rate */ | ||
252 | } | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * disc_timeout - send a periodic link setup request | ||
257 | * @req: ptr to link request structure | ||
258 | * | ||
259 | * Called whenever a link setup request timer associated with a bearer expires. | ||
260 | */ | ||
261 | |||
262 | static void disc_timeout(struct link_req *req) | ||
263 | { | ||
264 | spin_lock_bh(&req->bearer->publ.lock); | ||
265 | |||
266 | req->bearer->media->send_msg(req->buf, &req->bearer->publ, &req->dest); | ||
267 | |||
268 | if ((req->timer_intv == TIPC_LINK_REQ_SLOW) || | ||
269 | (req->timer_intv == TIPC_LINK_REQ_FAST)) { | ||
270 | /* leave timer interval "as is" if already at a "normal" rate */ | ||
271 | } else { | ||
272 | req->timer_intv *= 2; | ||
273 | if (req->timer_intv > TIPC_LINK_REQ_SLOW) | ||
274 | req->timer_intv = TIPC_LINK_REQ_SLOW; | ||
275 | if ((req->timer_intv == TIPC_LINK_REQ_FAST) && | ||
276 | (req->bearer->nodes.count)) | ||
277 | req->timer_intv = TIPC_LINK_REQ_SLOW; | ||
278 | } | ||
279 | k_start_timer(&req->timer, req->timer_intv); | ||
280 | |||
281 | spin_unlock_bh(&req->bearer->publ.lock); | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * disc_init_link_req - start sending periodic link setup requests | ||
286 | * @b_ptr: ptr to bearer issuing requests | ||
287 | * @dest: destination address for request messages | ||
288 | * @dest_domain: network domain of node(s) which should respond to message | ||
289 | * @req_links: max number of desired links | ||
290 | * | ||
291 | * Returns pointer to link request structure, or NULL if unable to create. | ||
292 | */ | ||
293 | |||
294 | struct link_req *disc_init_link_req(struct bearer *b_ptr, | ||
295 | const struct tipc_media_addr *dest, | ||
296 | u32 dest_domain, | ||
297 | u32 req_links) | ||
298 | { | ||
299 | struct link_req *req; | ||
300 | |||
301 | req = (struct link_req *)kmalloc(sizeof(*req), GFP_ATOMIC); | ||
302 | if (!req) | ||
303 | return NULL; | ||
304 | |||
305 | req->buf = disc_init_msg(DSC_REQ_MSG, req_links, dest_domain, b_ptr); | ||
306 | if (!req->buf) { | ||
307 | kfree(req); | ||
308 | return NULL; | ||
309 | } | ||
310 | |||
311 | memcpy(&req->dest, dest, sizeof(*dest)); | ||
312 | req->bearer = b_ptr; | ||
313 | req->timer_intv = TIPC_LINK_REQ_INIT; | ||
314 | k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); | ||
315 | k_start_timer(&req->timer, req->timer_intv); | ||
316 | return req; | ||
317 | } | ||
318 | |||
diff --git a/net/tipc/discover.h b/net/tipc/discover.h new file mode 100644 index 000000000000..2a6114d91626 --- /dev/null +++ b/net/tipc/discover.h | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * net/tipc/discover.h | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_DISCOVER_H | ||
38 | #define _TIPC_DISCOVER_H | ||
39 | |||
40 | #include <linux/tipc.h> | ||
41 | |||
42 | struct link_req; | ||
43 | |||
44 | struct link_req *disc_init_link_req(struct bearer *b_ptr, | ||
45 | const struct tipc_media_addr *dest, | ||
46 | u32 dest_domain, | ||
47 | u32 req_links); | ||
48 | void disc_update_link_req(struct link_req *req); | ||
49 | void disc_stop_link_req(struct link_req *req); | ||
50 | |||
51 | void disc_recv_msg(struct sk_buff *buf); | ||
52 | |||
53 | void disc_link_event(u32 addr, char *name, int up); | ||
54 | #if 0 | ||
55 | int disc_create_link(const struct tipc_link_create *argv); | ||
56 | #endif | ||
57 | |||
58 | #endif | ||
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c new file mode 100644 index 000000000000..34d0462db3aa --- /dev/null +++ b/net/tipc/eth_media.c | |||
@@ -0,0 +1,299 @@ | |||
1 | /* | ||
2 | * net/tipc/eth_media.c: Ethernet bearer support for TIPC | ||
3 | * | ||
4 | * Copyright (c) 2001-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include <net/tipc/tipc.h> | ||
38 | #include <net/tipc/tipc_bearer.h> | ||
39 | #include <net/tipc/tipc_msg.h> | ||
40 | #include <linux/netdevice.h> | ||
41 | #include <linux/version.h> | ||
42 | |||
43 | #define MAX_ETH_BEARERS 2 | ||
44 | #define TIPC_PROTOCOL 0x88ca | ||
45 | #define ETH_LINK_PRIORITY 10 | ||
46 | #define ETH_LINK_TOLERANCE TIPC_DEF_LINK_TOL | ||
47 | |||
48 | |||
49 | /** | ||
50 | * struct eth_bearer - Ethernet bearer data structure | ||
51 | * @bearer: ptr to associated "generic" bearer structure | ||
52 | * @dev: ptr to associated Ethernet network device | ||
53 | * @tipc_packet_type: used in binding TIPC to Ethernet driver | ||
54 | */ | ||
55 | |||
56 | struct eth_bearer { | ||
57 | struct tipc_bearer *bearer; | ||
58 | struct net_device *dev; | ||
59 | struct packet_type tipc_packet_type; | ||
60 | }; | ||
61 | |||
62 | static struct eth_bearer eth_bearers[MAX_ETH_BEARERS]; | ||
63 | static int eth_started = 0; | ||
64 | static struct notifier_block notifier; | ||
65 | |||
66 | /** | ||
67 | * send_msg - send a TIPC message out over an Ethernet interface | ||
68 | */ | ||
69 | |||
70 | static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, | ||
71 | struct tipc_media_addr *dest) | ||
72 | { | ||
73 | struct sk_buff *clone; | ||
74 | struct net_device *dev; | ||
75 | |||
76 | clone = skb_clone(buf, GFP_ATOMIC); | ||
77 | if (clone) { | ||
78 | clone->nh.raw = clone->data; | ||
79 | dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev; | ||
80 | clone->dev = dev; | ||
81 | dev->hard_header(clone, dev, TIPC_PROTOCOL, | ||
82 | &dest->dev_addr.eth_addr, | ||
83 | dev->dev_addr, clone->len); | ||
84 | dev_queue_xmit(clone); | ||
85 | } | ||
86 | return TIPC_OK; | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * recv_msg - handle incoming TIPC message from an Ethernet interface | ||
91 | * | ||
92 | * Routine truncates any Ethernet padding/CRC appended to the message, | ||
93 | * and ensures message size matches actual length | ||
94 | */ | ||
95 | |||
96 | static int recv_msg(struct sk_buff *buf, struct net_device *dev, | ||
97 | struct packet_type *pt, struct net_device *orig_dev) | ||
98 | { | ||
99 | struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv; | ||
100 | u32 size; | ||
101 | |||
102 | if (likely(eb_ptr->bearer)) { | ||
103 | size = msg_size((struct tipc_msg *)buf->data); | ||
104 | skb_trim(buf, size); | ||
105 | if (likely(buf->len == size)) { | ||
106 | buf->next = NULL; | ||
107 | tipc_recv_msg(buf, eb_ptr->bearer); | ||
108 | } else { | ||
109 | kfree_skb(buf); | ||
110 | } | ||
111 | } else { | ||
112 | kfree_skb(buf); | ||
113 | } | ||
114 | return TIPC_OK; | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * enable_bearer - attach TIPC bearer to an Ethernet interface | ||
119 | */ | ||
120 | |||
121 | static int enable_bearer(struct tipc_bearer *tb_ptr) | ||
122 | { | ||
123 | struct net_device *dev = dev_base; | ||
124 | struct eth_bearer *eb_ptr = ð_bearers[0]; | ||
125 | struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS]; | ||
126 | char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; | ||
127 | |||
128 | /* Find device with specified name */ | ||
129 | |||
130 | while (dev && dev->name && | ||
131 | (memcmp(dev->name, driver_name, strlen(dev->name)))) { | ||
132 | dev = dev->next; | ||
133 | } | ||
134 | if (!dev) | ||
135 | return -ENODEV; | ||
136 | |||
137 | /* Find Ethernet bearer for device (or create one) */ | ||
138 | |||
139 | for (;(eb_ptr != stop) && eb_ptr->dev && (eb_ptr->dev != dev); eb_ptr++); | ||
140 | if (eb_ptr == stop) | ||
141 | return -EDQUOT; | ||
142 | if (!eb_ptr->dev) { | ||
143 | eb_ptr->dev = dev; | ||
144 | eb_ptr->tipc_packet_type.type = __constant_htons(TIPC_PROTOCOL); | ||
145 | eb_ptr->tipc_packet_type.dev = dev; | ||
146 | eb_ptr->tipc_packet_type.func = recv_msg; | ||
147 | eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr; | ||
148 | INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list)); | ||
149 | dev_hold(dev); | ||
150 | dev_add_pack(&eb_ptr->tipc_packet_type); | ||
151 | } | ||
152 | |||
153 | /* Associate TIPC bearer with Ethernet bearer */ | ||
154 | |||
155 | eb_ptr->bearer = tb_ptr; | ||
156 | tb_ptr->usr_handle = (void *)eb_ptr; | ||
157 | tb_ptr->mtu = dev->mtu; | ||
158 | tb_ptr->blocked = 0; | ||
159 | tb_ptr->addr.type = htonl(TIPC_MEDIA_TYPE_ETH); | ||
160 | memcpy(&tb_ptr->addr.dev_addr, &dev->dev_addr, ETH_ALEN); | ||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * disable_bearer - detach TIPC bearer from an Ethernet interface | ||
166 | * | ||
167 | * We really should do dev_remove_pack() here, but this function can not be | ||
168 | * called at tasklet level. => Use eth_bearer->bearer as a flag to throw away | ||
169 | * incoming buffers, & postpone dev_remove_pack() to eth_media_stop() on exit. | ||
170 | */ | ||
171 | |||
172 | static void disable_bearer(struct tipc_bearer *tb_ptr) | ||
173 | { | ||
174 | ((struct eth_bearer *)tb_ptr->usr_handle)->bearer = 0; | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * recv_notification - handle device updates from OS | ||
179 | * | ||
180 | * Change the state of the Ethernet bearer (if any) associated with the | ||
181 | * specified device. | ||
182 | */ | ||
183 | |||
184 | static int recv_notification(struct notifier_block *nb, unsigned long evt, | ||
185 | void *dv) | ||
186 | { | ||
187 | struct net_device *dev = (struct net_device *)dv; | ||
188 | struct eth_bearer *eb_ptr = ð_bearers[0]; | ||
189 | struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS]; | ||
190 | |||
191 | while ((eb_ptr->dev != dev)) { | ||
192 | if (++eb_ptr == stop) | ||
193 | return NOTIFY_DONE; /* couldn't find device */ | ||
194 | } | ||
195 | if (!eb_ptr->bearer) | ||
196 | return NOTIFY_DONE; /* bearer had been disabled */ | ||
197 | |||
198 | eb_ptr->bearer->mtu = dev->mtu; | ||
199 | |||
200 | switch (evt) { | ||
201 | case NETDEV_CHANGE: | ||
202 | if (netif_carrier_ok(dev)) | ||
203 | tipc_continue(eb_ptr->bearer); | ||
204 | else | ||
205 | tipc_block_bearer(eb_ptr->bearer->name); | ||
206 | break; | ||
207 | case NETDEV_UP: | ||
208 | tipc_continue(eb_ptr->bearer); | ||
209 | break; | ||
210 | case NETDEV_DOWN: | ||
211 | tipc_block_bearer(eb_ptr->bearer->name); | ||
212 | break; | ||
213 | case NETDEV_CHANGEMTU: | ||
214 | case NETDEV_CHANGEADDR: | ||
215 | tipc_block_bearer(eb_ptr->bearer->name); | ||
216 | tipc_continue(eb_ptr->bearer); | ||
217 | break; | ||
218 | case NETDEV_UNREGISTER: | ||
219 | case NETDEV_CHANGENAME: | ||
220 | tipc_disable_bearer(eb_ptr->bearer->name); | ||
221 | break; | ||
222 | } | ||
223 | return NOTIFY_OK; | ||
224 | } | ||
225 | |||
226 | /** | ||
227 | * eth_addr2str - convert Ethernet address to string | ||
228 | */ | ||
229 | |||
230 | static char *eth_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size) | ||
231 | { | ||
232 | unchar *addr = (unchar *)&a->dev_addr; | ||
233 | |||
234 | if (str_size < 18) | ||
235 | *str_buf = '\0'; | ||
236 | else | ||
237 | sprintf(str_buf, "%02x:%02x:%02x:%02x:%02x:%02x", | ||
238 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); | ||
239 | return str_buf; | ||
240 | } | ||
241 | |||
242 | /** | ||
243 | * eth_media_start - activate Ethernet bearer support | ||
244 | * | ||
245 | * Register Ethernet media type with TIPC bearer code. Also register | ||
246 | * with OS for notifications about device state changes. | ||
247 | */ | ||
248 | |||
249 | int eth_media_start(void) | ||
250 | { | ||
251 | struct tipc_media_addr bcast_addr; | ||
252 | int res; | ||
253 | |||
254 | if (eth_started) | ||
255 | return -EINVAL; | ||
256 | |||
257 | memset(&bcast_addr, 0xff, sizeof(bcast_addr)); | ||
258 | memset(eth_bearers, 0, sizeof(eth_bearers)); | ||
259 | |||
260 | res = tipc_register_media(TIPC_MEDIA_TYPE_ETH, "eth", | ||
261 | enable_bearer, disable_bearer, send_msg, | ||
262 | eth_addr2str, &bcast_addr, ETH_LINK_PRIORITY, | ||
263 | ETH_LINK_TOLERANCE, TIPC_DEF_LINK_WIN); | ||
264 | if (res) | ||
265 | return res; | ||
266 | |||
267 | notifier.notifier_call = &recv_notification; | ||
268 | notifier.priority = 0; | ||
269 | res = register_netdevice_notifier(¬ifier); | ||
270 | if (!res) | ||
271 | eth_started = 1; | ||
272 | return res; | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * eth_media_stop - deactivate Ethernet bearer support | ||
277 | */ | ||
278 | |||
279 | void eth_media_stop(void) | ||
280 | { | ||
281 | int i; | ||
282 | |||
283 | if (!eth_started) | ||
284 | return; | ||
285 | |||
286 | unregister_netdevice_notifier(¬ifier); | ||
287 | for (i = 0; i < MAX_ETH_BEARERS ; i++) { | ||
288 | if (eth_bearers[i].bearer) { | ||
289 | eth_bearers[i].bearer->blocked = 1; | ||
290 | eth_bearers[i].bearer = 0; | ||
291 | } | ||
292 | if (eth_bearers[i].dev) { | ||
293 | dev_remove_pack(ð_bearers[i].tipc_packet_type); | ||
294 | dev_put(eth_bearers[i].dev); | ||
295 | } | ||
296 | } | ||
297 | memset(ð_bearers, 0, sizeof(eth_bearers)); | ||
298 | eth_started = 0; | ||
299 | } | ||
diff --git a/net/tipc/handler.c b/net/tipc/handler.c new file mode 100644 index 000000000000..f320010f8a65 --- /dev/null +++ b/net/tipc/handler.c | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * net/tipc/handler.c: TIPC signal handling | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | |||
39 | struct queue_item { | ||
40 | struct list_head next_signal; | ||
41 | void (*handler) (unsigned long); | ||
42 | unsigned long data; | ||
43 | }; | ||
44 | |||
45 | static kmem_cache_t *tipc_queue_item_cache; | ||
46 | static struct list_head signal_queue_head; | ||
47 | static spinlock_t qitem_lock = SPIN_LOCK_UNLOCKED; | ||
48 | static int handler_enabled = 0; | ||
49 | |||
50 | static void process_signal_queue(unsigned long dummy); | ||
51 | |||
52 | static DECLARE_TASKLET_DISABLED(tipc_tasklet, process_signal_queue, 0); | ||
53 | |||
54 | |||
55 | unsigned int k_signal(Handler routine, unsigned long argument) | ||
56 | { | ||
57 | struct queue_item *item; | ||
58 | |||
59 | if (!handler_enabled) { | ||
60 | err("Signal request ignored by handler\n"); | ||
61 | return -ENOPROTOOPT; | ||
62 | } | ||
63 | |||
64 | spin_lock_bh(&qitem_lock); | ||
65 | item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC); | ||
66 | if (!item) { | ||
67 | err("Signal queue out of memory\n"); | ||
68 | spin_unlock_bh(&qitem_lock); | ||
69 | return -ENOMEM; | ||
70 | } | ||
71 | item->handler = routine; | ||
72 | item->data = argument; | ||
73 | list_add_tail(&item->next_signal, &signal_queue_head); | ||
74 | spin_unlock_bh(&qitem_lock); | ||
75 | tasklet_schedule(&tipc_tasklet); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static void process_signal_queue(unsigned long dummy) | ||
80 | { | ||
81 | struct queue_item *__volatile__ item; | ||
82 | struct list_head *l, *n; | ||
83 | |||
84 | spin_lock_bh(&qitem_lock); | ||
85 | list_for_each_safe(l, n, &signal_queue_head) { | ||
86 | item = list_entry(l, struct queue_item, next_signal); | ||
87 | list_del(&item->next_signal); | ||
88 | spin_unlock_bh(&qitem_lock); | ||
89 | item->handler(item->data); | ||
90 | spin_lock_bh(&qitem_lock); | ||
91 | kmem_cache_free(tipc_queue_item_cache, item); | ||
92 | } | ||
93 | spin_unlock_bh(&qitem_lock); | ||
94 | } | ||
95 | |||
96 | int handler_start(void) | ||
97 | { | ||
98 | tipc_queue_item_cache = | ||
99 | kmem_cache_create("tipc_queue_items", sizeof(struct queue_item), | ||
100 | 0, SLAB_HWCACHE_ALIGN, NULL, NULL); | ||
101 | if (!tipc_queue_item_cache) | ||
102 | return -ENOMEM; | ||
103 | |||
104 | INIT_LIST_HEAD(&signal_queue_head); | ||
105 | tasklet_enable(&tipc_tasklet); | ||
106 | handler_enabled = 1; | ||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | void handler_stop(void) | ||
111 | { | ||
112 | struct list_head *l, *n; | ||
113 | struct queue_item *item; | ||
114 | |||
115 | if (!handler_enabled) | ||
116 | return; | ||
117 | |||
118 | handler_enabled = 0; | ||
119 | tasklet_disable(&tipc_tasklet); | ||
120 | tasklet_kill(&tipc_tasklet); | ||
121 | |||
122 | spin_lock_bh(&qitem_lock); | ||
123 | list_for_each_safe(l, n, &signal_queue_head) { | ||
124 | item = list_entry(l, struct queue_item, next_signal); | ||
125 | list_del(&item->next_signal); | ||
126 | kmem_cache_free(tipc_queue_item_cache, item); | ||
127 | } | ||
128 | spin_unlock_bh(&qitem_lock); | ||
129 | |||
130 | kmem_cache_destroy(tipc_queue_item_cache); | ||
131 | } | ||
132 | |||
diff --git a/net/tipc/link.c b/net/tipc/link.c new file mode 100644 index 000000000000..7265f4be4766 --- /dev/null +++ b/net/tipc/link.c | |||
@@ -0,0 +1,3167 @@ | |||
1 | /* | ||
2 | * net/tipc/link.c: TIPC link code | ||
3 | * | ||
4 | * Copyright (c) 1996-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "dbg.h" | ||
39 | #include "link.h" | ||
40 | #include "net.h" | ||
41 | #include "node.h" | ||
42 | #include "port.h" | ||
43 | #include "addr.h" | ||
44 | #include "node_subscr.h" | ||
45 | #include "name_distr.h" | ||
46 | #include "bearer.h" | ||
47 | #include "name_table.h" | ||
48 | #include "discover.h" | ||
49 | #include "config.h" | ||
50 | #include "bcast.h" | ||
51 | |||
52 | |||
53 | /* | ||
54 | * Limit for deferred reception queue: | ||
55 | */ | ||
56 | |||
57 | #define DEF_QUEUE_LIMIT 256u | ||
58 | |||
59 | /* | ||
60 | * Link state events: | ||
61 | */ | ||
62 | |||
63 | #define STARTING_EVT 856384768 /* link processing trigger */ | ||
64 | #define TRAFFIC_MSG_EVT 560815u /* rx'd ??? */ | ||
65 | #define TIMEOUT_EVT 560817u /* link timer expired */ | ||
66 | |||
67 | /* | ||
68 | * The following two 'message types' is really just implementation | ||
69 | * data conveniently stored in the message header. | ||
70 | * They must not be considered part of the protocol | ||
71 | */ | ||
72 | #define OPEN_MSG 0 | ||
73 | #define CLOSED_MSG 1 | ||
74 | |||
75 | /* | ||
76 | * State value stored in 'exp_msg_count' | ||
77 | */ | ||
78 | |||
79 | #define START_CHANGEOVER 100000u | ||
80 | |||
81 | /** | ||
82 | * struct link_name - deconstructed link name | ||
83 | * @addr_local: network address of node at this end | ||
84 | * @if_local: name of interface at this end | ||
85 | * @addr_peer: network address of node at far end | ||
86 | * @if_peer: name of interface at far end | ||
87 | */ | ||
88 | |||
89 | struct link_name { | ||
90 | u32 addr_local; | ||
91 | char if_local[TIPC_MAX_IF_NAME]; | ||
92 | u32 addr_peer; | ||
93 | char if_peer[TIPC_MAX_IF_NAME]; | ||
94 | }; | ||
95 | |||
96 | #if 0 | ||
97 | |||
98 | /* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */ | ||
99 | |||
100 | /** | ||
101 | * struct link_event - link up/down event notification | ||
102 | */ | ||
103 | |||
104 | struct link_event { | ||
105 | u32 addr; | ||
106 | int up; | ||
107 | void (*fcn)(u32, char *, int); | ||
108 | char name[TIPC_MAX_LINK_NAME]; | ||
109 | }; | ||
110 | |||
111 | #endif | ||
112 | |||
113 | static void link_handle_out_of_seq_msg(struct link *l_ptr, | ||
114 | struct sk_buff *buf); | ||
115 | static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf); | ||
116 | static int link_recv_changeover_msg(struct link **l_ptr, struct sk_buff **buf); | ||
117 | static void link_set_supervision_props(struct link *l_ptr, u32 tolerance); | ||
118 | static int link_send_sections_long(struct port *sender, | ||
119 | struct iovec const *msg_sect, | ||
120 | u32 num_sect, u32 destnode); | ||
121 | static void link_check_defragm_bufs(struct link *l_ptr); | ||
122 | static void link_state_event(struct link *l_ptr, u32 event); | ||
123 | static void link_reset_statistics(struct link *l_ptr); | ||
124 | static void link_print(struct link *l_ptr, struct print_buf *buf, | ||
125 | const char *str); | ||
126 | |||
127 | /* | ||
128 | * Debugging code used by link routines only | ||
129 | * | ||
130 | * When debugging link problems on a system that has multiple links, | ||
131 | * the standard TIPC debugging routines may not be useful since they | ||
132 | * allow the output from multiple links to be intermixed. For this reason | ||
133 | * routines of the form "dbg_link_XXX()" have been created that will capture | ||
134 | * debug info into a link's personal print buffer, which can then be dumped | ||
135 | * into the TIPC system log (LOG) upon request. | ||
136 | * | ||
137 | * To enable per-link debugging, use LINK_LOG_BUF_SIZE to specify the size | ||
138 | * of the print buffer used by each link. If LINK_LOG_BUF_SIZE is set to 0, | ||
139 | * the dbg_link_XXX() routines simply send their output to the standard | ||
140 | * debug print buffer (DBG_OUTPUT), if it has been defined; this can be useful | ||
141 | * when there is only a single link in the system being debugged. | ||
142 | * | ||
143 | * Notes: | ||
144 | * - When enabled, LINK_LOG_BUF_SIZE should be set to at least 1000 (bytes) | ||
145 | * - "l_ptr" must be valid when using dbg_link_XXX() macros | ||
146 | */ | ||
147 | |||
148 | #define LINK_LOG_BUF_SIZE 0 | ||
149 | |||
150 | #define dbg_link(fmt, arg...) do {if (LINK_LOG_BUF_SIZE) tipc_printf(&l_ptr->print_buf, fmt, ## arg); } while(0) | ||
151 | #define dbg_link_msg(msg, txt) do {if (LINK_LOG_BUF_SIZE) msg_print(&l_ptr->print_buf, msg, txt); } while(0) | ||
152 | #define dbg_link_state(txt) do {if (LINK_LOG_BUF_SIZE) link_print(l_ptr, &l_ptr->print_buf, txt); } while(0) | ||
153 | #define dbg_link_dump() do { \ | ||
154 | if (LINK_LOG_BUF_SIZE) { \ | ||
155 | tipc_printf(LOG, "\n\nDumping link <%s>:\n", l_ptr->name); \ | ||
156 | printbuf_move(LOG, &l_ptr->print_buf); \ | ||
157 | } \ | ||
158 | } while (0) | ||
159 | |||
160 | static inline void dbg_print_link(struct link *l_ptr, const char *str) | ||
161 | { | ||
162 | if (DBG_OUTPUT) | ||
163 | link_print(l_ptr, DBG_OUTPUT, str); | ||
164 | } | ||
165 | |||
166 | static inline void dbg_print_buf_chain(struct sk_buff *root_buf) | ||
167 | { | ||
168 | if (DBG_OUTPUT) { | ||
169 | struct sk_buff *buf = root_buf; | ||
170 | |||
171 | while (buf) { | ||
172 | msg_dbg(buf_msg(buf), "In chain: "); | ||
173 | buf = buf->next; | ||
174 | } | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * Simple inlined link routines | ||
180 | */ | ||
181 | |||
182 | static inline unsigned int align(unsigned int i) | ||
183 | { | ||
184 | return (i + 3) & ~3u; | ||
185 | } | ||
186 | |||
187 | static inline int link_working_working(struct link *l_ptr) | ||
188 | { | ||
189 | return (l_ptr->state == WORKING_WORKING); | ||
190 | } | ||
191 | |||
192 | static inline int link_working_unknown(struct link *l_ptr) | ||
193 | { | ||
194 | return (l_ptr->state == WORKING_UNKNOWN); | ||
195 | } | ||
196 | |||
197 | static inline int link_reset_unknown(struct link *l_ptr) | ||
198 | { | ||
199 | return (l_ptr->state == RESET_UNKNOWN); | ||
200 | } | ||
201 | |||
202 | static inline int link_reset_reset(struct link *l_ptr) | ||
203 | { | ||
204 | return (l_ptr->state == RESET_RESET); | ||
205 | } | ||
206 | |||
207 | static inline int link_blocked(struct link *l_ptr) | ||
208 | { | ||
209 | return (l_ptr->exp_msg_count || l_ptr->blocked); | ||
210 | } | ||
211 | |||
212 | static inline int link_congested(struct link *l_ptr) | ||
213 | { | ||
214 | return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]); | ||
215 | } | ||
216 | |||
217 | static inline u32 link_max_pkt(struct link *l_ptr) | ||
218 | { | ||
219 | return l_ptr->max_pkt; | ||
220 | } | ||
221 | |||
222 | static inline void link_init_max_pkt(struct link *l_ptr) | ||
223 | { | ||
224 | u32 max_pkt; | ||
225 | |||
226 | max_pkt = (l_ptr->b_ptr->publ.mtu & ~3); | ||
227 | if (max_pkt > MAX_MSG_SIZE) | ||
228 | max_pkt = MAX_MSG_SIZE; | ||
229 | |||
230 | l_ptr->max_pkt_target = max_pkt; | ||
231 | if (l_ptr->max_pkt_target < MAX_PKT_DEFAULT) | ||
232 | l_ptr->max_pkt = l_ptr->max_pkt_target; | ||
233 | else | ||
234 | l_ptr->max_pkt = MAX_PKT_DEFAULT; | ||
235 | |||
236 | l_ptr->max_pkt_probes = 0; | ||
237 | } | ||
238 | |||
239 | static inline u32 link_next_sent(struct link *l_ptr) | ||
240 | { | ||
241 | if (l_ptr->next_out) | ||
242 | return msg_seqno(buf_msg(l_ptr->next_out)); | ||
243 | return mod(l_ptr->next_out_no); | ||
244 | } | ||
245 | |||
246 | static inline u32 link_last_sent(struct link *l_ptr) | ||
247 | { | ||
248 | return mod(link_next_sent(l_ptr) - 1); | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * Simple non-inlined link routines (i.e. referenced outside this file) | ||
253 | */ | ||
254 | |||
255 | int link_is_up(struct link *l_ptr) | ||
256 | { | ||
257 | if (!l_ptr) | ||
258 | return 0; | ||
259 | return (link_working_working(l_ptr) || link_working_unknown(l_ptr)); | ||
260 | } | ||
261 | |||
262 | int link_is_active(struct link *l_ptr) | ||
263 | { | ||
264 | return ((l_ptr->owner->active_links[0] == l_ptr) || | ||
265 | (l_ptr->owner->active_links[1] == l_ptr)); | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * link_name_validate - validate & (optionally) deconstruct link name | ||
270 | * @name - ptr to link name string | ||
271 | * @name_parts - ptr to area for link name components (or NULL if not needed) | ||
272 | * | ||
273 | * Returns 1 if link name is valid, otherwise 0. | ||
274 | */ | ||
275 | |||
276 | static int link_name_validate(const char *name, struct link_name *name_parts) | ||
277 | { | ||
278 | char name_copy[TIPC_MAX_LINK_NAME]; | ||
279 | char *addr_local; | ||
280 | char *if_local; | ||
281 | char *addr_peer; | ||
282 | char *if_peer; | ||
283 | char dummy; | ||
284 | u32 z_local, c_local, n_local; | ||
285 | u32 z_peer, c_peer, n_peer; | ||
286 | u32 if_local_len; | ||
287 | u32 if_peer_len; | ||
288 | |||
289 | /* copy link name & ensure length is OK */ | ||
290 | |||
291 | name_copy[TIPC_MAX_LINK_NAME - 1] = 0; | ||
292 | /* need above in case non-Posix strncpy() doesn't pad with nulls */ | ||
293 | strncpy(name_copy, name, TIPC_MAX_LINK_NAME); | ||
294 | if (name_copy[TIPC_MAX_LINK_NAME - 1] != 0) | ||
295 | return 0; | ||
296 | |||
297 | /* ensure all component parts of link name are present */ | ||
298 | |||
299 | addr_local = name_copy; | ||
300 | if ((if_local = strchr(addr_local, ':')) == NULL) | ||
301 | return 0; | ||
302 | *(if_local++) = 0; | ||
303 | if ((addr_peer = strchr(if_local, '-')) == NULL) | ||
304 | return 0; | ||
305 | *(addr_peer++) = 0; | ||
306 | if_local_len = addr_peer - if_local; | ||
307 | if ((if_peer = strchr(addr_peer, ':')) == NULL) | ||
308 | return 0; | ||
309 | *(if_peer++) = 0; | ||
310 | if_peer_len = strlen(if_peer) + 1; | ||
311 | |||
312 | /* validate component parts of link name */ | ||
313 | |||
314 | if ((sscanf(addr_local, "%u.%u.%u%c", | ||
315 | &z_local, &c_local, &n_local, &dummy) != 3) || | ||
316 | (sscanf(addr_peer, "%u.%u.%u%c", | ||
317 | &z_peer, &c_peer, &n_peer, &dummy) != 3) || | ||
318 | (z_local > 255) || (c_local > 4095) || (n_local > 4095) || | ||
319 | (z_peer > 255) || (c_peer > 4095) || (n_peer > 4095) || | ||
320 | (if_local_len <= 1) || (if_local_len > TIPC_MAX_IF_NAME) || | ||
321 | (if_peer_len <= 1) || (if_peer_len > TIPC_MAX_IF_NAME) || | ||
322 | (strspn(if_local, tipc_alphabet) != (if_local_len - 1)) || | ||
323 | (strspn(if_peer, tipc_alphabet) != (if_peer_len - 1))) | ||
324 | return 0; | ||
325 | |||
326 | /* return link name components, if necessary */ | ||
327 | |||
328 | if (name_parts) { | ||
329 | name_parts->addr_local = tipc_addr(z_local, c_local, n_local); | ||
330 | strcpy(name_parts->if_local, if_local); | ||
331 | name_parts->addr_peer = tipc_addr(z_peer, c_peer, n_peer); | ||
332 | strcpy(name_parts->if_peer, if_peer); | ||
333 | } | ||
334 | return 1; | ||
335 | } | ||
336 | |||
337 | /** | ||
338 | * link_timeout - handle expiration of link timer | ||
339 | * @l_ptr: pointer to link | ||
340 | * | ||
341 | * This routine must not grab "net_lock" to avoid a potential deadlock conflict | ||
342 | * with link_delete(). (There is no risk that the node will be deleted by | ||
343 | * another thread because link_delete() always cancels the link timer before | ||
344 | * node_delete() is called.) | ||
345 | */ | ||
346 | |||
347 | static void link_timeout(struct link *l_ptr) | ||
348 | { | ||
349 | node_lock(l_ptr->owner); | ||
350 | |||
351 | /* update counters used in statistical profiling of send traffic */ | ||
352 | |||
353 | l_ptr->stats.accu_queue_sz += l_ptr->out_queue_size; | ||
354 | l_ptr->stats.queue_sz_counts++; | ||
355 | |||
356 | if (l_ptr->out_queue_size > l_ptr->stats.max_queue_sz) | ||
357 | l_ptr->stats.max_queue_sz = l_ptr->out_queue_size; | ||
358 | |||
359 | if (l_ptr->first_out) { | ||
360 | struct tipc_msg *msg = buf_msg(l_ptr->first_out); | ||
361 | u32 length = msg_size(msg); | ||
362 | |||
363 | if ((msg_user(msg) == MSG_FRAGMENTER) | ||
364 | && (msg_type(msg) == FIRST_FRAGMENT)) { | ||
365 | length = msg_size(msg_get_wrapped(msg)); | ||
366 | } | ||
367 | if (length) { | ||
368 | l_ptr->stats.msg_lengths_total += length; | ||
369 | l_ptr->stats.msg_length_counts++; | ||
370 | if (length <= 64) | ||
371 | l_ptr->stats.msg_length_profile[0]++; | ||
372 | else if (length <= 256) | ||
373 | l_ptr->stats.msg_length_profile[1]++; | ||
374 | else if (length <= 1024) | ||
375 | l_ptr->stats.msg_length_profile[2]++; | ||
376 | else if (length <= 4096) | ||
377 | l_ptr->stats.msg_length_profile[3]++; | ||
378 | else if (length <= 16384) | ||
379 | l_ptr->stats.msg_length_profile[4]++; | ||
380 | else if (length <= 32768) | ||
381 | l_ptr->stats.msg_length_profile[5]++; | ||
382 | else | ||
383 | l_ptr->stats.msg_length_profile[6]++; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | /* do all other link processing performed on a periodic basis */ | ||
388 | |||
389 | link_check_defragm_bufs(l_ptr); | ||
390 | |||
391 | link_state_event(l_ptr, TIMEOUT_EVT); | ||
392 | |||
393 | if (l_ptr->next_out) | ||
394 | link_push_queue(l_ptr); | ||
395 | |||
396 | node_unlock(l_ptr->owner); | ||
397 | } | ||
398 | |||
399 | static inline void link_set_timer(struct link *l_ptr, u32 time) | ||
400 | { | ||
401 | k_start_timer(&l_ptr->timer, time); | ||
402 | } | ||
403 | |||
404 | /** | ||
405 | * link_create - create a new link | ||
406 | * @b_ptr: pointer to associated bearer | ||
407 | * @peer: network address of node at other end of link | ||
408 | * @media_addr: media address to use when sending messages over link | ||
409 | * | ||
410 | * Returns pointer to link. | ||
411 | */ | ||
412 | |||
413 | struct link *link_create(struct bearer *b_ptr, const u32 peer, | ||
414 | const struct tipc_media_addr *media_addr) | ||
415 | { | ||
416 | struct link *l_ptr; | ||
417 | struct tipc_msg *msg; | ||
418 | char *if_name; | ||
419 | |||
420 | l_ptr = (struct link *)kmalloc(sizeof(*l_ptr), GFP_ATOMIC); | ||
421 | if (!l_ptr) { | ||
422 | warn("Memory squeeze; Failed to create link\n"); | ||
423 | return NULL; | ||
424 | } | ||
425 | memset(l_ptr, 0, sizeof(*l_ptr)); | ||
426 | |||
427 | l_ptr->addr = peer; | ||
428 | if_name = strchr(b_ptr->publ.name, ':') + 1; | ||
429 | sprintf(l_ptr->name, "%u.%u.%u:%s-%u.%u.%u:", | ||
430 | tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), | ||
431 | tipc_node(tipc_own_addr), | ||
432 | if_name, | ||
433 | tipc_zone(peer), tipc_cluster(peer), tipc_node(peer)); | ||
434 | /* note: peer i/f is appended to link name by reset/activate */ | ||
435 | memcpy(&l_ptr->media_addr, media_addr, sizeof(*media_addr)); | ||
436 | k_init_timer(&l_ptr->timer, (Handler)link_timeout, (unsigned long)l_ptr); | ||
437 | list_add_tail(&l_ptr->link_list, &b_ptr->links); | ||
438 | l_ptr->checkpoint = 1; | ||
439 | l_ptr->b_ptr = b_ptr; | ||
440 | link_set_supervision_props(l_ptr, b_ptr->media->tolerance); | ||
441 | l_ptr->state = RESET_UNKNOWN; | ||
442 | |||
443 | l_ptr->pmsg = (struct tipc_msg *)&l_ptr->proto_msg; | ||
444 | msg = l_ptr->pmsg; | ||
445 | msg_init(msg, LINK_PROTOCOL, RESET_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); | ||
446 | msg_set_size(msg, sizeof(l_ptr->proto_msg)); | ||
447 | msg_set_session(msg, tipc_random); | ||
448 | msg_set_bearer_id(msg, b_ptr->identity); | ||
449 | strcpy((char *)msg_data(msg), if_name); | ||
450 | |||
451 | l_ptr->priority = b_ptr->priority; | ||
452 | link_set_queue_limits(l_ptr, b_ptr->media->window); | ||
453 | |||
454 | link_init_max_pkt(l_ptr); | ||
455 | |||
456 | l_ptr->next_out_no = 1; | ||
457 | INIT_LIST_HEAD(&l_ptr->waiting_ports); | ||
458 | |||
459 | link_reset_statistics(l_ptr); | ||
460 | |||
461 | l_ptr->owner = node_attach_link(l_ptr); | ||
462 | if (!l_ptr->owner) { | ||
463 | kfree(l_ptr); | ||
464 | return NULL; | ||
465 | } | ||
466 | |||
467 | if (LINK_LOG_BUF_SIZE) { | ||
468 | char *pb = kmalloc(LINK_LOG_BUF_SIZE, GFP_ATOMIC); | ||
469 | |||
470 | if (!pb) { | ||
471 | kfree(l_ptr); | ||
472 | warn("Memory squeeze; Failed to create link\n"); | ||
473 | return NULL; | ||
474 | } | ||
475 | printbuf_init(&l_ptr->print_buf, pb, LINK_LOG_BUF_SIZE); | ||
476 | } | ||
477 | |||
478 | k_signal((Handler)link_start, (unsigned long)l_ptr); | ||
479 | |||
480 | dbg("link_create(): tolerance = %u,cont intv = %u, abort_limit = %u\n", | ||
481 | l_ptr->tolerance, l_ptr->continuity_interval, l_ptr->abort_limit); | ||
482 | |||
483 | return l_ptr; | ||
484 | } | ||
485 | |||
486 | /** | ||
487 | * link_delete - delete a link | ||
488 | * @l_ptr: pointer to link | ||
489 | * | ||
490 | * Note: 'net_lock' is write_locked, bearer is locked. | ||
491 | * This routine must not grab the node lock until after link timer cancellation | ||
492 | * to avoid a potential deadlock situation. | ||
493 | */ | ||
494 | |||
495 | void link_delete(struct link *l_ptr) | ||
496 | { | ||
497 | if (!l_ptr) { | ||
498 | err("Attempt to delete non-existent link\n"); | ||
499 | return; | ||
500 | } | ||
501 | |||
502 | dbg("link_delete()\n"); | ||
503 | |||
504 | k_cancel_timer(&l_ptr->timer); | ||
505 | |||
506 | node_lock(l_ptr->owner); | ||
507 | link_reset(l_ptr); | ||
508 | node_detach_link(l_ptr->owner, l_ptr); | ||
509 | link_stop(l_ptr); | ||
510 | list_del_init(&l_ptr->link_list); | ||
511 | if (LINK_LOG_BUF_SIZE) | ||
512 | kfree(l_ptr->print_buf.buf); | ||
513 | node_unlock(l_ptr->owner); | ||
514 | k_term_timer(&l_ptr->timer); | ||
515 | kfree(l_ptr); | ||
516 | } | ||
517 | |||
518 | void link_start(struct link *l_ptr) | ||
519 | { | ||
520 | dbg("link_start %x\n", l_ptr); | ||
521 | link_state_event(l_ptr, STARTING_EVT); | ||
522 | } | ||
523 | |||
524 | /** | ||
525 | * link_schedule_port - schedule port for deferred sending | ||
526 | * @l_ptr: pointer to link | ||
527 | * @origport: reference to sending port | ||
528 | * @sz: amount of data to be sent | ||
529 | * | ||
530 | * Schedules port for renewed sending of messages after link congestion | ||
531 | * has abated. | ||
532 | */ | ||
533 | |||
534 | static int link_schedule_port(struct link *l_ptr, u32 origport, u32 sz) | ||
535 | { | ||
536 | struct port *p_ptr; | ||
537 | |||
538 | spin_lock_bh(&port_list_lock); | ||
539 | p_ptr = port_lock(origport); | ||
540 | if (p_ptr) { | ||
541 | if (!p_ptr->wakeup) | ||
542 | goto exit; | ||
543 | if (!list_empty(&p_ptr->wait_list)) | ||
544 | goto exit; | ||
545 | p_ptr->congested_link = l_ptr; | ||
546 | p_ptr->publ.congested = 1; | ||
547 | p_ptr->waiting_pkts = 1 + ((sz - 1) / link_max_pkt(l_ptr)); | ||
548 | list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports); | ||
549 | l_ptr->stats.link_congs++; | ||
550 | exit: | ||
551 | port_unlock(p_ptr); | ||
552 | } | ||
553 | spin_unlock_bh(&port_list_lock); | ||
554 | return -ELINKCONG; | ||
555 | } | ||
556 | |||
557 | void link_wakeup_ports(struct link *l_ptr, int all) | ||
558 | { | ||
559 | struct port *p_ptr; | ||
560 | struct port *temp_p_ptr; | ||
561 | int win = l_ptr->queue_limit[0] - l_ptr->out_queue_size; | ||
562 | |||
563 | if (all) | ||
564 | win = 100000; | ||
565 | if (win <= 0) | ||
566 | return; | ||
567 | if (!spin_trylock_bh(&port_list_lock)) | ||
568 | return; | ||
569 | if (link_congested(l_ptr)) | ||
570 | goto exit; | ||
571 | list_for_each_entry_safe(p_ptr, temp_p_ptr, &l_ptr->waiting_ports, | ||
572 | wait_list) { | ||
573 | if (win <= 0) | ||
574 | break; | ||
575 | list_del_init(&p_ptr->wait_list); | ||
576 | p_ptr->congested_link = 0; | ||
577 | assert(p_ptr->wakeup); | ||
578 | spin_lock_bh(p_ptr->publ.lock); | ||
579 | p_ptr->publ.congested = 0; | ||
580 | p_ptr->wakeup(&p_ptr->publ); | ||
581 | win -= p_ptr->waiting_pkts; | ||
582 | spin_unlock_bh(p_ptr->publ.lock); | ||
583 | } | ||
584 | |||
585 | exit: | ||
586 | spin_unlock_bh(&port_list_lock); | ||
587 | } | ||
588 | |||
589 | /** | ||
590 | * link_release_outqueue - purge link's outbound message queue | ||
591 | * @l_ptr: pointer to link | ||
592 | */ | ||
593 | |||
594 | static void link_release_outqueue(struct link *l_ptr) | ||
595 | { | ||
596 | struct sk_buff *buf = l_ptr->first_out; | ||
597 | struct sk_buff *next; | ||
598 | |||
599 | while (buf) { | ||
600 | next = buf->next; | ||
601 | buf_discard(buf); | ||
602 | buf = next; | ||
603 | } | ||
604 | l_ptr->first_out = NULL; | ||
605 | l_ptr->out_queue_size = 0; | ||
606 | } | ||
607 | |||
608 | /** | ||
609 | * link_reset_fragments - purge link's inbound message fragments queue | ||
610 | * @l_ptr: pointer to link | ||
611 | */ | ||
612 | |||
613 | void link_reset_fragments(struct link *l_ptr) | ||
614 | { | ||
615 | struct sk_buff *buf = l_ptr->defragm_buf; | ||
616 | struct sk_buff *next; | ||
617 | |||
618 | while (buf) { | ||
619 | next = buf->next; | ||
620 | buf_discard(buf); | ||
621 | buf = next; | ||
622 | } | ||
623 | l_ptr->defragm_buf = NULL; | ||
624 | } | ||
625 | |||
626 | /** | ||
627 | * link_stop - purge all inbound and outbound messages associated with link | ||
628 | * @l_ptr: pointer to link | ||
629 | */ | ||
630 | |||
631 | void link_stop(struct link *l_ptr) | ||
632 | { | ||
633 | struct sk_buff *buf; | ||
634 | struct sk_buff *next; | ||
635 | |||
636 | buf = l_ptr->oldest_deferred_in; | ||
637 | while (buf) { | ||
638 | next = buf->next; | ||
639 | buf_discard(buf); | ||
640 | buf = next; | ||
641 | } | ||
642 | |||
643 | buf = l_ptr->first_out; | ||
644 | while (buf) { | ||
645 | next = buf->next; | ||
646 | buf_discard(buf); | ||
647 | buf = next; | ||
648 | } | ||
649 | |||
650 | link_reset_fragments(l_ptr); | ||
651 | |||
652 | buf_discard(l_ptr->proto_msg_queue); | ||
653 | l_ptr->proto_msg_queue = NULL; | ||
654 | } | ||
655 | |||
656 | #if 0 | ||
657 | |||
658 | /* LINK EVENT CODE IS NOT SUPPORTED AT PRESENT */ | ||
659 | |||
660 | static void link_recv_event(struct link_event *ev) | ||
661 | { | ||
662 | ev->fcn(ev->addr, ev->name, ev->up); | ||
663 | kfree(ev); | ||
664 | } | ||
665 | |||
666 | static void link_send_event(void (*fcn)(u32 a, char *n, int up), | ||
667 | struct link *l_ptr, int up) | ||
668 | { | ||
669 | struct link_event *ev; | ||
670 | |||
671 | ev = kmalloc(sizeof(*ev), GFP_ATOMIC); | ||
672 | if (!ev) { | ||
673 | warn("Link event allocation failure\n"); | ||
674 | return; | ||
675 | } | ||
676 | ev->addr = l_ptr->addr; | ||
677 | ev->up = up; | ||
678 | ev->fcn = fcn; | ||
679 | memcpy(ev->name, l_ptr->name, TIPC_MAX_LINK_NAME); | ||
680 | k_signal((Handler)link_recv_event, (unsigned long)ev); | ||
681 | } | ||
682 | |||
683 | #else | ||
684 | |||
685 | #define link_send_event(fcn, l_ptr, up) do { } while (0) | ||
686 | |||
687 | #endif | ||
688 | |||
689 | void link_reset(struct link *l_ptr) | ||
690 | { | ||
691 | struct sk_buff *buf; | ||
692 | u32 prev_state = l_ptr->state; | ||
693 | u32 checkpoint = l_ptr->next_in_no; | ||
694 | |||
695 | msg_set_session(l_ptr->pmsg, msg_session(l_ptr->pmsg) + 1); | ||
696 | |||
697 | /* Link is down, accept any session: */ | ||
698 | l_ptr->peer_session = 0; | ||
699 | |||
700 | /* Prepare for max packet size negotiation */ | ||
701 | link_init_max_pkt(l_ptr); | ||
702 | |||
703 | l_ptr->state = RESET_UNKNOWN; | ||
704 | dbg_link_state("Resetting Link\n"); | ||
705 | |||
706 | if ((prev_state == RESET_UNKNOWN) || (prev_state == RESET_RESET)) | ||
707 | return; | ||
708 | |||
709 | node_link_down(l_ptr->owner, l_ptr); | ||
710 | bearer_remove_dest(l_ptr->b_ptr, l_ptr->addr); | ||
711 | #if 0 | ||
712 | tipc_printf(CONS, "\nReset link <%s>\n", l_ptr->name); | ||
713 | dbg_link_dump(); | ||
714 | #endif | ||
715 | if (node_has_active_links(l_ptr->owner) && | ||
716 | l_ptr->owner->permit_changeover) { | ||
717 | l_ptr->reset_checkpoint = checkpoint; | ||
718 | l_ptr->exp_msg_count = START_CHANGEOVER; | ||
719 | } | ||
720 | |||
721 | /* Clean up all queues: */ | ||
722 | |||
723 | link_release_outqueue(l_ptr); | ||
724 | buf_discard(l_ptr->proto_msg_queue); | ||
725 | l_ptr->proto_msg_queue = NULL; | ||
726 | buf = l_ptr->oldest_deferred_in; | ||
727 | while (buf) { | ||
728 | struct sk_buff *next = buf->next; | ||
729 | buf_discard(buf); | ||
730 | buf = next; | ||
731 | } | ||
732 | if (!list_empty(&l_ptr->waiting_ports)) | ||
733 | link_wakeup_ports(l_ptr, 1); | ||
734 | |||
735 | l_ptr->retransm_queue_head = 0; | ||
736 | l_ptr->retransm_queue_size = 0; | ||
737 | l_ptr->last_out = NULL; | ||
738 | l_ptr->first_out = NULL; | ||
739 | l_ptr->next_out = NULL; | ||
740 | l_ptr->unacked_window = 0; | ||
741 | l_ptr->checkpoint = 1; | ||
742 | l_ptr->next_out_no = 1; | ||
743 | l_ptr->deferred_inqueue_sz = 0; | ||
744 | l_ptr->oldest_deferred_in = NULL; | ||
745 | l_ptr->newest_deferred_in = NULL; | ||
746 | l_ptr->fsm_msg_cnt = 0; | ||
747 | l_ptr->stale_count = 0; | ||
748 | link_reset_statistics(l_ptr); | ||
749 | |||
750 | link_send_event(cfg_link_event, l_ptr, 0); | ||
751 | if (!in_own_cluster(l_ptr->addr)) | ||
752 | link_send_event(disc_link_event, l_ptr, 0); | ||
753 | } | ||
754 | |||
755 | |||
756 | static void link_activate(struct link *l_ptr) | ||
757 | { | ||
758 | l_ptr->next_in_no = 1; | ||
759 | node_link_up(l_ptr->owner, l_ptr); | ||
760 | bearer_add_dest(l_ptr->b_ptr, l_ptr->addr); | ||
761 | link_send_event(cfg_link_event, l_ptr, 1); | ||
762 | if (!in_own_cluster(l_ptr->addr)) | ||
763 | link_send_event(disc_link_event, l_ptr, 1); | ||
764 | } | ||
765 | |||
766 | /** | ||
767 | * link_state_event - link finite state machine | ||
768 | * @l_ptr: pointer to link | ||
769 | * @event: state machine event to process | ||
770 | */ | ||
771 | |||
772 | static void link_state_event(struct link *l_ptr, unsigned event) | ||
773 | { | ||
774 | struct link *other; | ||
775 | u32 cont_intv = l_ptr->continuity_interval; | ||
776 | |||
777 | if (!l_ptr->started && (event != STARTING_EVT)) | ||
778 | return; /* Not yet. */ | ||
779 | |||
780 | if (link_blocked(l_ptr)) { | ||
781 | if (event == TIMEOUT_EVT) { | ||
782 | link_set_timer(l_ptr, cont_intv); | ||
783 | } | ||
784 | return; /* Changeover going on */ | ||
785 | } | ||
786 | dbg_link("STATE_EV: <%s> ", l_ptr->name); | ||
787 | |||
788 | switch (l_ptr->state) { | ||
789 | case WORKING_WORKING: | ||
790 | dbg_link("WW/"); | ||
791 | switch (event) { | ||
792 | case TRAFFIC_MSG_EVT: | ||
793 | dbg_link("TRF-"); | ||
794 | /* fall through */ | ||
795 | case ACTIVATE_MSG: | ||
796 | dbg_link("ACT\n"); | ||
797 | break; | ||
798 | case TIMEOUT_EVT: | ||
799 | dbg_link("TIM "); | ||
800 | if (l_ptr->next_in_no != l_ptr->checkpoint) { | ||
801 | l_ptr->checkpoint = l_ptr->next_in_no; | ||
802 | if (bclink_acks_missing(l_ptr->owner)) { | ||
803 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
804 | 0, 0, 0, 0, 0); | ||
805 | l_ptr->fsm_msg_cnt++; | ||
806 | } else if (l_ptr->max_pkt < l_ptr->max_pkt_target) { | ||
807 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
808 | 1, 0, 0, 0, 0); | ||
809 | l_ptr->fsm_msg_cnt++; | ||
810 | } | ||
811 | link_set_timer(l_ptr, cont_intv); | ||
812 | break; | ||
813 | } | ||
814 | dbg_link(" -> WU\n"); | ||
815 | l_ptr->state = WORKING_UNKNOWN; | ||
816 | l_ptr->fsm_msg_cnt = 0; | ||
817 | link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); | ||
818 | l_ptr->fsm_msg_cnt++; | ||
819 | link_set_timer(l_ptr, cont_intv / 4); | ||
820 | break; | ||
821 | case RESET_MSG: | ||
822 | dbg_link("RES -> RR\n"); | ||
823 | link_reset(l_ptr); | ||
824 | l_ptr->state = RESET_RESET; | ||
825 | l_ptr->fsm_msg_cnt = 0; | ||
826 | link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); | ||
827 | l_ptr->fsm_msg_cnt++; | ||
828 | link_set_timer(l_ptr, cont_intv); | ||
829 | break; | ||
830 | default: | ||
831 | err("Unknown link event %u in WW state\n", event); | ||
832 | } | ||
833 | break; | ||
834 | case WORKING_UNKNOWN: | ||
835 | dbg_link("WU/"); | ||
836 | switch (event) { | ||
837 | case TRAFFIC_MSG_EVT: | ||
838 | dbg_link("TRF-"); | ||
839 | case ACTIVATE_MSG: | ||
840 | dbg_link("ACT -> WW\n"); | ||
841 | l_ptr->state = WORKING_WORKING; | ||
842 | l_ptr->fsm_msg_cnt = 0; | ||
843 | link_set_timer(l_ptr, cont_intv); | ||
844 | break; | ||
845 | case RESET_MSG: | ||
846 | dbg_link("RES -> RR\n"); | ||
847 | link_reset(l_ptr); | ||
848 | l_ptr->state = RESET_RESET; | ||
849 | l_ptr->fsm_msg_cnt = 0; | ||
850 | link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); | ||
851 | l_ptr->fsm_msg_cnt++; | ||
852 | link_set_timer(l_ptr, cont_intv); | ||
853 | break; | ||
854 | case TIMEOUT_EVT: | ||
855 | dbg_link("TIM "); | ||
856 | if (l_ptr->next_in_no != l_ptr->checkpoint) { | ||
857 | dbg_link("-> WW \n"); | ||
858 | l_ptr->state = WORKING_WORKING; | ||
859 | l_ptr->fsm_msg_cnt = 0; | ||
860 | l_ptr->checkpoint = l_ptr->next_in_no; | ||
861 | if (bclink_acks_missing(l_ptr->owner)) { | ||
862 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
863 | 0, 0, 0, 0, 0); | ||
864 | l_ptr->fsm_msg_cnt++; | ||
865 | } | ||
866 | link_set_timer(l_ptr, cont_intv); | ||
867 | } else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) { | ||
868 | dbg_link("Probing %u/%u,timer = %u ms)\n", | ||
869 | l_ptr->fsm_msg_cnt, l_ptr->abort_limit, | ||
870 | cont_intv / 4); | ||
871 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
872 | 1, 0, 0, 0, 0); | ||
873 | l_ptr->fsm_msg_cnt++; | ||
874 | link_set_timer(l_ptr, cont_intv / 4); | ||
875 | } else { /* Link has failed */ | ||
876 | dbg_link("-> RU (%u probes unanswered)\n", | ||
877 | l_ptr->fsm_msg_cnt); | ||
878 | link_reset(l_ptr); | ||
879 | l_ptr->state = RESET_UNKNOWN; | ||
880 | l_ptr->fsm_msg_cnt = 0; | ||
881 | link_send_proto_msg(l_ptr, RESET_MSG, | ||
882 | 0, 0, 0, 0, 0); | ||
883 | l_ptr->fsm_msg_cnt++; | ||
884 | link_set_timer(l_ptr, cont_intv); | ||
885 | } | ||
886 | break; | ||
887 | default: | ||
888 | err("Unknown link event %u in WU state\n", event); | ||
889 | } | ||
890 | break; | ||
891 | case RESET_UNKNOWN: | ||
892 | dbg_link("RU/"); | ||
893 | switch (event) { | ||
894 | case TRAFFIC_MSG_EVT: | ||
895 | dbg_link("TRF-\n"); | ||
896 | break; | ||
897 | case ACTIVATE_MSG: | ||
898 | other = l_ptr->owner->active_links[0]; | ||
899 | if (other && link_working_unknown(other)) { | ||
900 | dbg_link("ACT\n"); | ||
901 | break; | ||
902 | } | ||
903 | dbg_link("ACT -> WW\n"); | ||
904 | l_ptr->state = WORKING_WORKING; | ||
905 | l_ptr->fsm_msg_cnt = 0; | ||
906 | link_activate(l_ptr); | ||
907 | link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); | ||
908 | l_ptr->fsm_msg_cnt++; | ||
909 | link_set_timer(l_ptr, cont_intv); | ||
910 | break; | ||
911 | case RESET_MSG: | ||
912 | dbg_link("RES \n"); | ||
913 | dbg_link(" -> RR\n"); | ||
914 | l_ptr->state = RESET_RESET; | ||
915 | l_ptr->fsm_msg_cnt = 0; | ||
916 | link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0); | ||
917 | l_ptr->fsm_msg_cnt++; | ||
918 | link_set_timer(l_ptr, cont_intv); | ||
919 | break; | ||
920 | case STARTING_EVT: | ||
921 | dbg_link("START-"); | ||
922 | l_ptr->started = 1; | ||
923 | /* fall through */ | ||
924 | case TIMEOUT_EVT: | ||
925 | dbg_link("TIM \n"); | ||
926 | link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); | ||
927 | l_ptr->fsm_msg_cnt++; | ||
928 | link_set_timer(l_ptr, cont_intv); | ||
929 | break; | ||
930 | default: | ||
931 | err("Unknown link event %u in RU state\n", event); | ||
932 | } | ||
933 | break; | ||
934 | case RESET_RESET: | ||
935 | dbg_link("RR/ "); | ||
936 | switch (event) { | ||
937 | case TRAFFIC_MSG_EVT: | ||
938 | dbg_link("TRF-"); | ||
939 | /* fall through */ | ||
940 | case ACTIVATE_MSG: | ||
941 | other = l_ptr->owner->active_links[0]; | ||
942 | if (other && link_working_unknown(other)) { | ||
943 | dbg_link("ACT\n"); | ||
944 | break; | ||
945 | } | ||
946 | dbg_link("ACT -> WW\n"); | ||
947 | l_ptr->state = WORKING_WORKING; | ||
948 | l_ptr->fsm_msg_cnt = 0; | ||
949 | link_activate(l_ptr); | ||
950 | link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); | ||
951 | l_ptr->fsm_msg_cnt++; | ||
952 | link_set_timer(l_ptr, cont_intv); | ||
953 | break; | ||
954 | case RESET_MSG: | ||
955 | dbg_link("RES\n"); | ||
956 | break; | ||
957 | case TIMEOUT_EVT: | ||
958 | dbg_link("TIM\n"); | ||
959 | link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); | ||
960 | l_ptr->fsm_msg_cnt++; | ||
961 | link_set_timer(l_ptr, cont_intv); | ||
962 | dbg_link("fsm_msg_cnt %u\n", l_ptr->fsm_msg_cnt); | ||
963 | break; | ||
964 | default: | ||
965 | err("Unknown link event %u in RR state\n", event); | ||
966 | } | ||
967 | break; | ||
968 | default: | ||
969 | err("Unknown link state %u/%u\n", l_ptr->state, event); | ||
970 | } | ||
971 | } | ||
972 | |||
973 | /* | ||
974 | * link_bundle_buf(): Append contents of a buffer to | ||
975 | * the tail of an existing one. | ||
976 | */ | ||
977 | |||
978 | static int link_bundle_buf(struct link *l_ptr, | ||
979 | struct sk_buff *bundler, | ||
980 | struct sk_buff *buf) | ||
981 | { | ||
982 | struct tipc_msg *bundler_msg = buf_msg(bundler); | ||
983 | struct tipc_msg *msg = buf_msg(buf); | ||
984 | u32 size = msg_size(msg); | ||
985 | u32 to_pos = align(msg_size(bundler_msg)); | ||
986 | u32 rest = link_max_pkt(l_ptr) - to_pos; | ||
987 | |||
988 | if (msg_user(bundler_msg) != MSG_BUNDLER) | ||
989 | return 0; | ||
990 | if (msg_type(bundler_msg) != OPEN_MSG) | ||
991 | return 0; | ||
992 | if (rest < align(size)) | ||
993 | return 0; | ||
994 | |||
995 | skb_put(bundler, (to_pos - msg_size(bundler_msg)) + size); | ||
996 | memcpy(bundler->data + to_pos, buf->data, size); | ||
997 | msg_set_size(bundler_msg, to_pos + size); | ||
998 | msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1); | ||
999 | dbg("Packed msg # %u(%u octets) into pos %u in buf(#%u)\n", | ||
1000 | msg_msgcnt(bundler_msg), size, to_pos, msg_seqno(bundler_msg)); | ||
1001 | msg_dbg(msg, "PACKD:"); | ||
1002 | buf_discard(buf); | ||
1003 | l_ptr->stats.sent_bundled++; | ||
1004 | return 1; | ||
1005 | } | ||
1006 | |||
1007 | static inline void link_add_to_outqueue(struct link *l_ptr, | ||
1008 | struct sk_buff *buf, | ||
1009 | struct tipc_msg *msg) | ||
1010 | { | ||
1011 | u32 ack = mod(l_ptr->next_in_no - 1); | ||
1012 | u32 seqno = mod(l_ptr->next_out_no++); | ||
1013 | |||
1014 | msg_set_word(msg, 2, ((ack << 16) | seqno)); | ||
1015 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | ||
1016 | buf->next = NULL; | ||
1017 | if (l_ptr->first_out) { | ||
1018 | l_ptr->last_out->next = buf; | ||
1019 | l_ptr->last_out = buf; | ||
1020 | } else | ||
1021 | l_ptr->first_out = l_ptr->last_out = buf; | ||
1022 | l_ptr->out_queue_size++; | ||
1023 | } | ||
1024 | |||
1025 | /* | ||
1026 | * link_send_buf() is the 'full path' for messages, called from | ||
1027 | * inside TIPC when the 'fast path' in tipc_send_buf | ||
1028 | * has failed, and from link_send() | ||
1029 | */ | ||
1030 | |||
1031 | int link_send_buf(struct link *l_ptr, struct sk_buff *buf) | ||
1032 | { | ||
1033 | struct tipc_msg *msg = buf_msg(buf); | ||
1034 | u32 size = msg_size(msg); | ||
1035 | u32 dsz = msg_data_sz(msg); | ||
1036 | u32 queue_size = l_ptr->out_queue_size; | ||
1037 | u32 imp = msg_tot_importance(msg); | ||
1038 | u32 queue_limit = l_ptr->queue_limit[imp]; | ||
1039 | u32 max_packet = link_max_pkt(l_ptr); | ||
1040 | |||
1041 | msg_set_prevnode(msg, tipc_own_addr); /* If routed message */ | ||
1042 | |||
1043 | /* Match msg importance against queue limits: */ | ||
1044 | |||
1045 | if (unlikely(queue_size >= queue_limit)) { | ||
1046 | if (imp <= TIPC_CRITICAL_IMPORTANCE) { | ||
1047 | return link_schedule_port(l_ptr, msg_origport(msg), | ||
1048 | size); | ||
1049 | } | ||
1050 | msg_dbg(msg, "TIPC: Congestion, throwing away\n"); | ||
1051 | buf_discard(buf); | ||
1052 | if (imp > CONN_MANAGER) { | ||
1053 | warn("Resetting <%s>, send queue full", l_ptr->name); | ||
1054 | link_reset(l_ptr); | ||
1055 | } | ||
1056 | return dsz; | ||
1057 | } | ||
1058 | |||
1059 | /* Fragmentation needed ? */ | ||
1060 | |||
1061 | if (size > max_packet) | ||
1062 | return link_send_long_buf(l_ptr, buf); | ||
1063 | |||
1064 | /* Packet can be queued or sent: */ | ||
1065 | |||
1066 | if (queue_size > l_ptr->stats.max_queue_sz) | ||
1067 | l_ptr->stats.max_queue_sz = queue_size; | ||
1068 | |||
1069 | if (likely(!bearer_congested(l_ptr->b_ptr, l_ptr) && | ||
1070 | !link_congested(l_ptr))) { | ||
1071 | link_add_to_outqueue(l_ptr, buf, msg); | ||
1072 | |||
1073 | if (likely(bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr))) { | ||
1074 | l_ptr->unacked_window = 0; | ||
1075 | } else { | ||
1076 | bearer_schedule(l_ptr->b_ptr, l_ptr); | ||
1077 | l_ptr->stats.bearer_congs++; | ||
1078 | l_ptr->next_out = buf; | ||
1079 | } | ||
1080 | return dsz; | ||
1081 | } | ||
1082 | /* Congestion: can message be bundled ?: */ | ||
1083 | |||
1084 | if ((msg_user(msg) != CHANGEOVER_PROTOCOL) && | ||
1085 | (msg_user(msg) != MSG_FRAGMENTER)) { | ||
1086 | |||
1087 | /* Try adding message to an existing bundle */ | ||
1088 | |||
1089 | if (l_ptr->next_out && | ||
1090 | link_bundle_buf(l_ptr, l_ptr->last_out, buf)) { | ||
1091 | bearer_resolve_congestion(l_ptr->b_ptr, l_ptr); | ||
1092 | return dsz; | ||
1093 | } | ||
1094 | |||
1095 | /* Try creating a new bundle */ | ||
1096 | |||
1097 | if (size <= max_packet * 2 / 3) { | ||
1098 | struct sk_buff *bundler = buf_acquire(max_packet); | ||
1099 | struct tipc_msg bundler_hdr; | ||
1100 | |||
1101 | if (bundler) { | ||
1102 | msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG, | ||
1103 | TIPC_OK, INT_H_SIZE, l_ptr->addr); | ||
1104 | memcpy(bundler->data, (unchar *)&bundler_hdr, | ||
1105 | INT_H_SIZE); | ||
1106 | skb_trim(bundler, INT_H_SIZE); | ||
1107 | link_bundle_buf(l_ptr, bundler, buf); | ||
1108 | buf = bundler; | ||
1109 | msg = buf_msg(buf); | ||
1110 | l_ptr->stats.sent_bundles++; | ||
1111 | } | ||
1112 | } | ||
1113 | } | ||
1114 | if (!l_ptr->next_out) | ||
1115 | l_ptr->next_out = buf; | ||
1116 | link_add_to_outqueue(l_ptr, buf, msg); | ||
1117 | bearer_resolve_congestion(l_ptr->b_ptr, l_ptr); | ||
1118 | return dsz; | ||
1119 | } | ||
1120 | |||
1121 | /* | ||
1122 | * link_send(): same as link_send_buf(), but the link to use has | ||
1123 | * not been selected yet, and the the owner node is not locked | ||
1124 | * Called by TIPC internal users, e.g. the name distributor | ||
1125 | */ | ||
1126 | |||
1127 | int link_send(struct sk_buff *buf, u32 dest, u32 selector) | ||
1128 | { | ||
1129 | struct link *l_ptr; | ||
1130 | struct node *n_ptr; | ||
1131 | int res = -ELINKCONG; | ||
1132 | |||
1133 | read_lock_bh(&net_lock); | ||
1134 | n_ptr = node_select(dest, selector); | ||
1135 | if (n_ptr) { | ||
1136 | node_lock(n_ptr); | ||
1137 | l_ptr = n_ptr->active_links[selector & 1]; | ||
1138 | dbg("link_send: found link %x for dest %x\n", l_ptr, dest); | ||
1139 | if (l_ptr) { | ||
1140 | res = link_send_buf(l_ptr, buf); | ||
1141 | } | ||
1142 | node_unlock(n_ptr); | ||
1143 | } else { | ||
1144 | dbg("Attempt to send msg to unknown node:\n"); | ||
1145 | msg_dbg(buf_msg(buf),">>>"); | ||
1146 | buf_discard(buf); | ||
1147 | } | ||
1148 | read_unlock_bh(&net_lock); | ||
1149 | return res; | ||
1150 | } | ||
1151 | |||
1152 | /* | ||
1153 | * link_send_buf_fast: Entry for data messages where the | ||
1154 | * destination link is known and the header is complete, | ||
1155 | * inclusive total message length. Very time critical. | ||
1156 | * Link is locked. Returns user data length. | ||
1157 | */ | ||
1158 | |||
1159 | static inline int link_send_buf_fast(struct link *l_ptr, struct sk_buff *buf, | ||
1160 | u32 *used_max_pkt) | ||
1161 | { | ||
1162 | struct tipc_msg *msg = buf_msg(buf); | ||
1163 | int res = msg_data_sz(msg); | ||
1164 | |||
1165 | if (likely(!link_congested(l_ptr))) { | ||
1166 | if (likely(msg_size(msg) <= link_max_pkt(l_ptr))) { | ||
1167 | if (likely(list_empty(&l_ptr->b_ptr->cong_links))) { | ||
1168 | link_add_to_outqueue(l_ptr, buf, msg); | ||
1169 | if (likely(bearer_send(l_ptr->b_ptr, buf, | ||
1170 | &l_ptr->media_addr))) { | ||
1171 | l_ptr->unacked_window = 0; | ||
1172 | msg_dbg(msg,"SENT_FAST:"); | ||
1173 | return res; | ||
1174 | } | ||
1175 | dbg("failed sent fast...\n"); | ||
1176 | bearer_schedule(l_ptr->b_ptr, l_ptr); | ||
1177 | l_ptr->stats.bearer_congs++; | ||
1178 | l_ptr->next_out = buf; | ||
1179 | return res; | ||
1180 | } | ||
1181 | } | ||
1182 | else | ||
1183 | *used_max_pkt = link_max_pkt(l_ptr); | ||
1184 | } | ||
1185 | return link_send_buf(l_ptr, buf); /* All other cases */ | ||
1186 | } | ||
1187 | |||
1188 | /* | ||
1189 | * tipc_send_buf_fast: Entry for data messages where the | ||
1190 | * destination node is known and the header is complete, | ||
1191 | * inclusive total message length. | ||
1192 | * Returns user data length. | ||
1193 | */ | ||
1194 | int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode) | ||
1195 | { | ||
1196 | struct link *l_ptr; | ||
1197 | struct node *n_ptr; | ||
1198 | int res; | ||
1199 | u32 selector = msg_origport(buf_msg(buf)) & 1; | ||
1200 | u32 dummy; | ||
1201 | |||
1202 | if (destnode == tipc_own_addr) | ||
1203 | return port_recv_msg(buf); | ||
1204 | |||
1205 | read_lock_bh(&net_lock); | ||
1206 | n_ptr = node_select(destnode, selector); | ||
1207 | if (likely(n_ptr)) { | ||
1208 | node_lock(n_ptr); | ||
1209 | l_ptr = n_ptr->active_links[selector]; | ||
1210 | dbg("send_fast: buf %x selected %x, destnode = %x\n", | ||
1211 | buf, l_ptr, destnode); | ||
1212 | if (likely(l_ptr)) { | ||
1213 | res = link_send_buf_fast(l_ptr, buf, &dummy); | ||
1214 | node_unlock(n_ptr); | ||
1215 | read_unlock_bh(&net_lock); | ||
1216 | return res; | ||
1217 | } | ||
1218 | node_unlock(n_ptr); | ||
1219 | } | ||
1220 | read_unlock_bh(&net_lock); | ||
1221 | res = msg_data_sz(buf_msg(buf)); | ||
1222 | tipc_reject_msg(buf, TIPC_ERR_NO_NODE); | ||
1223 | return res; | ||
1224 | } | ||
1225 | |||
1226 | |||
1227 | /* | ||
1228 | * link_send_sections_fast: Entry for messages where the | ||
1229 | * destination processor is known and the header is complete, | ||
1230 | * except for total message length. | ||
1231 | * Returns user data length or errno. | ||
1232 | */ | ||
1233 | int link_send_sections_fast(struct port *sender, | ||
1234 | struct iovec const *msg_sect, | ||
1235 | const u32 num_sect, | ||
1236 | u32 destaddr) | ||
1237 | { | ||
1238 | struct tipc_msg *hdr = &sender->publ.phdr; | ||
1239 | struct link *l_ptr; | ||
1240 | struct sk_buff *buf; | ||
1241 | struct node *node; | ||
1242 | int res; | ||
1243 | u32 selector = msg_origport(hdr) & 1; | ||
1244 | |||
1245 | assert(destaddr != tipc_own_addr); | ||
1246 | |||
1247 | again: | ||
1248 | /* | ||
1249 | * Try building message using port's max_pkt hint. | ||
1250 | * (Must not hold any locks while building message.) | ||
1251 | */ | ||
1252 | |||
1253 | res = msg_build(hdr, msg_sect, num_sect, sender->max_pkt, | ||
1254 | !sender->user_port, &buf); | ||
1255 | |||
1256 | read_lock_bh(&net_lock); | ||
1257 | node = node_select(destaddr, selector); | ||
1258 | if (likely(node)) { | ||
1259 | node_lock(node); | ||
1260 | l_ptr = node->active_links[selector]; | ||
1261 | if (likely(l_ptr)) { | ||
1262 | if (likely(buf)) { | ||
1263 | res = link_send_buf_fast(l_ptr, buf, | ||
1264 | &sender->max_pkt); | ||
1265 | if (unlikely(res < 0)) | ||
1266 | buf_discard(buf); | ||
1267 | exit: | ||
1268 | node_unlock(node); | ||
1269 | read_unlock_bh(&net_lock); | ||
1270 | return res; | ||
1271 | } | ||
1272 | |||
1273 | /* Exit if build request was invalid */ | ||
1274 | |||
1275 | if (unlikely(res < 0)) | ||
1276 | goto exit; | ||
1277 | |||
1278 | /* Exit if link (or bearer) is congested */ | ||
1279 | |||
1280 | if (link_congested(l_ptr) || | ||
1281 | !list_empty(&l_ptr->b_ptr->cong_links)) { | ||
1282 | res = link_schedule_port(l_ptr, | ||
1283 | sender->publ.ref, res); | ||
1284 | goto exit; | ||
1285 | } | ||
1286 | |||
1287 | /* | ||
1288 | * Message size exceeds max_pkt hint; update hint, | ||
1289 | * then re-try fast path or fragment the message | ||
1290 | */ | ||
1291 | |||
1292 | sender->max_pkt = link_max_pkt(l_ptr); | ||
1293 | node_unlock(node); | ||
1294 | read_unlock_bh(&net_lock); | ||
1295 | |||
1296 | |||
1297 | if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) | ||
1298 | goto again; | ||
1299 | |||
1300 | return link_send_sections_long(sender, msg_sect, | ||
1301 | num_sect, destaddr); | ||
1302 | } | ||
1303 | node_unlock(node); | ||
1304 | } | ||
1305 | read_unlock_bh(&net_lock); | ||
1306 | |||
1307 | /* Couldn't find a link to the destination node */ | ||
1308 | |||
1309 | if (buf) | ||
1310 | return tipc_reject_msg(buf, TIPC_ERR_NO_NODE); | ||
1311 | if (res >= 0) | ||
1312 | return port_reject_sections(sender, hdr, msg_sect, num_sect, | ||
1313 | TIPC_ERR_NO_NODE); | ||
1314 | return res; | ||
1315 | } | ||
1316 | |||
1317 | /* | ||
1318 | * link_send_sections_long(): Entry for long messages where the | ||
1319 | * destination node is known and the header is complete, | ||
1320 | * inclusive total message length. | ||
1321 | * Link and bearer congestion status have been checked to be ok, | ||
1322 | * and are ignored if they change. | ||
1323 | * | ||
1324 | * Note that fragments do not use the full link MTU so that they won't have | ||
1325 | * to undergo refragmentation if link changeover causes them to be sent | ||
1326 | * over another link with an additional tunnel header added as prefix. | ||
1327 | * (Refragmentation will still occur if the other link has a smaller MTU.) | ||
1328 | * | ||
1329 | * Returns user data length or errno. | ||
1330 | */ | ||
1331 | static int link_send_sections_long(struct port *sender, | ||
1332 | struct iovec const *msg_sect, | ||
1333 | u32 num_sect, | ||
1334 | u32 destaddr) | ||
1335 | { | ||
1336 | struct link *l_ptr; | ||
1337 | struct node *node; | ||
1338 | struct tipc_msg *hdr = &sender->publ.phdr; | ||
1339 | u32 dsz = msg_data_sz(hdr); | ||
1340 | u32 max_pkt,fragm_sz,rest; | ||
1341 | struct tipc_msg fragm_hdr; | ||
1342 | struct sk_buff *buf,*buf_chain,*prev; | ||
1343 | u32 fragm_crs,fragm_rest,hsz,sect_rest; | ||
1344 | const unchar *sect_crs; | ||
1345 | int curr_sect; | ||
1346 | u32 fragm_no; | ||
1347 | |||
1348 | again: | ||
1349 | fragm_no = 1; | ||
1350 | max_pkt = sender->max_pkt - INT_H_SIZE; | ||
1351 | /* leave room for tunnel header in case of link changeover */ | ||
1352 | fragm_sz = max_pkt - INT_H_SIZE; | ||
1353 | /* leave room for fragmentation header in each fragment */ | ||
1354 | rest = dsz; | ||
1355 | fragm_crs = 0; | ||
1356 | fragm_rest = 0; | ||
1357 | sect_rest = 0; | ||
1358 | sect_crs = 0; | ||
1359 | curr_sect = -1; | ||
1360 | |||
1361 | /* Prepare reusable fragment header: */ | ||
1362 | |||
1363 | msg_dbg(hdr, ">FRAGMENTING>"); | ||
1364 | msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | ||
1365 | TIPC_OK, INT_H_SIZE, msg_destnode(hdr)); | ||
1366 | msg_set_link_selector(&fragm_hdr, sender->publ.ref); | ||
1367 | msg_set_size(&fragm_hdr, max_pkt); | ||
1368 | msg_set_fragm_no(&fragm_hdr, 1); | ||
1369 | |||
1370 | /* Prepare header of first fragment: */ | ||
1371 | |||
1372 | buf_chain = buf = buf_acquire(max_pkt); | ||
1373 | if (!buf) | ||
1374 | return -ENOMEM; | ||
1375 | buf->next = NULL; | ||
1376 | memcpy(buf->data, (unchar *)&fragm_hdr, INT_H_SIZE); | ||
1377 | hsz = msg_hdr_sz(hdr); | ||
1378 | memcpy(buf->data + INT_H_SIZE, (unchar *)hdr, hsz); | ||
1379 | msg_dbg(buf_msg(buf), ">BUILD>"); | ||
1380 | |||
1381 | /* Chop up message: */ | ||
1382 | |||
1383 | fragm_crs = INT_H_SIZE + hsz; | ||
1384 | fragm_rest = fragm_sz - hsz; | ||
1385 | |||
1386 | do { /* For all sections */ | ||
1387 | u32 sz; | ||
1388 | |||
1389 | if (!sect_rest) { | ||
1390 | sect_rest = msg_sect[++curr_sect].iov_len; | ||
1391 | sect_crs = (const unchar *)msg_sect[curr_sect].iov_base; | ||
1392 | } | ||
1393 | |||
1394 | if (sect_rest < fragm_rest) | ||
1395 | sz = sect_rest; | ||
1396 | else | ||
1397 | sz = fragm_rest; | ||
1398 | |||
1399 | if (likely(!sender->user_port)) { | ||
1400 | if (copy_from_user(buf->data + fragm_crs, sect_crs, sz)) { | ||
1401 | error: | ||
1402 | for (; buf_chain; buf_chain = buf) { | ||
1403 | buf = buf_chain->next; | ||
1404 | buf_discard(buf_chain); | ||
1405 | } | ||
1406 | return -EFAULT; | ||
1407 | } | ||
1408 | } else | ||
1409 | memcpy(buf->data + fragm_crs, sect_crs, sz); | ||
1410 | |||
1411 | sect_crs += sz; | ||
1412 | sect_rest -= sz; | ||
1413 | fragm_crs += sz; | ||
1414 | fragm_rest -= sz; | ||
1415 | rest -= sz; | ||
1416 | |||
1417 | if (!fragm_rest && rest) { | ||
1418 | |||
1419 | /* Initiate new fragment: */ | ||
1420 | if (rest <= fragm_sz) { | ||
1421 | fragm_sz = rest; | ||
1422 | msg_set_type(&fragm_hdr,LAST_FRAGMENT); | ||
1423 | } else { | ||
1424 | msg_set_type(&fragm_hdr, FRAGMENT); | ||
1425 | } | ||
1426 | msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); | ||
1427 | msg_set_fragm_no(&fragm_hdr, ++fragm_no); | ||
1428 | prev = buf; | ||
1429 | buf = buf_acquire(fragm_sz + INT_H_SIZE); | ||
1430 | if (!buf) | ||
1431 | goto error; | ||
1432 | |||
1433 | buf->next = NULL; | ||
1434 | prev->next = buf; | ||
1435 | memcpy(buf->data, (unchar *)&fragm_hdr, INT_H_SIZE); | ||
1436 | fragm_crs = INT_H_SIZE; | ||
1437 | fragm_rest = fragm_sz; | ||
1438 | msg_dbg(buf_msg(buf)," >BUILD>"); | ||
1439 | } | ||
1440 | } | ||
1441 | while (rest > 0); | ||
1442 | |||
1443 | /* | ||
1444 | * Now we have a buffer chain. Select a link and check | ||
1445 | * that packet size is still OK | ||
1446 | */ | ||
1447 | node = node_select(destaddr, sender->publ.ref & 1); | ||
1448 | if (likely(node)) { | ||
1449 | node_lock(node); | ||
1450 | l_ptr = node->active_links[sender->publ.ref & 1]; | ||
1451 | if (!l_ptr) { | ||
1452 | node_unlock(node); | ||
1453 | goto reject; | ||
1454 | } | ||
1455 | if (link_max_pkt(l_ptr) < max_pkt) { | ||
1456 | sender->max_pkt = link_max_pkt(l_ptr); | ||
1457 | node_unlock(node); | ||
1458 | for (; buf_chain; buf_chain = buf) { | ||
1459 | buf = buf_chain->next; | ||
1460 | buf_discard(buf_chain); | ||
1461 | } | ||
1462 | goto again; | ||
1463 | } | ||
1464 | } else { | ||
1465 | reject: | ||
1466 | for (; buf_chain; buf_chain = buf) { | ||
1467 | buf = buf_chain->next; | ||
1468 | buf_discard(buf_chain); | ||
1469 | } | ||
1470 | return port_reject_sections(sender, hdr, msg_sect, num_sect, | ||
1471 | TIPC_ERR_NO_NODE); | ||
1472 | } | ||
1473 | |||
1474 | /* Append whole chain to send queue: */ | ||
1475 | |||
1476 | buf = buf_chain; | ||
1477 | l_ptr->long_msg_seq_no = mod(l_ptr->long_msg_seq_no + 1); | ||
1478 | if (!l_ptr->next_out) | ||
1479 | l_ptr->next_out = buf_chain; | ||
1480 | l_ptr->stats.sent_fragmented++; | ||
1481 | while (buf) { | ||
1482 | struct sk_buff *next = buf->next; | ||
1483 | struct tipc_msg *msg = buf_msg(buf); | ||
1484 | |||
1485 | l_ptr->stats.sent_fragments++; | ||
1486 | msg_set_long_msgno(msg, l_ptr->long_msg_seq_no); | ||
1487 | link_add_to_outqueue(l_ptr, buf, msg); | ||
1488 | msg_dbg(msg, ">ADD>"); | ||
1489 | buf = next; | ||
1490 | } | ||
1491 | |||
1492 | /* Send it, if possible: */ | ||
1493 | |||
1494 | link_push_queue(l_ptr); | ||
1495 | node_unlock(node); | ||
1496 | return dsz; | ||
1497 | } | ||
1498 | |||
1499 | /* | ||
1500 | * link_push_packet: Push one unsent packet to the media | ||
1501 | */ | ||
1502 | u32 link_push_packet(struct link *l_ptr) | ||
1503 | { | ||
1504 | struct sk_buff *buf = l_ptr->first_out; | ||
1505 | u32 r_q_size = l_ptr->retransm_queue_size; | ||
1506 | u32 r_q_head = l_ptr->retransm_queue_head; | ||
1507 | |||
1508 | /* Step to position where retransmission failed, if any, */ | ||
1509 | /* consider that buffers may have been released in meantime */ | ||
1510 | |||
1511 | if (r_q_size && buf) { | ||
1512 | u32 last = lesser(mod(r_q_head + r_q_size), | ||
1513 | link_last_sent(l_ptr)); | ||
1514 | u32 first = msg_seqno(buf_msg(buf)); | ||
1515 | |||
1516 | while (buf && less(first, r_q_head)) { | ||
1517 | first = mod(first + 1); | ||
1518 | buf = buf->next; | ||
1519 | } | ||
1520 | l_ptr->retransm_queue_head = r_q_head = first; | ||
1521 | l_ptr->retransm_queue_size = r_q_size = mod(last - first); | ||
1522 | } | ||
1523 | |||
1524 | /* Continue retransmission now, if there is anything: */ | ||
1525 | |||
1526 | if (r_q_size && buf && !skb_cloned(buf)) { | ||
1527 | msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); | ||
1528 | msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in); | ||
1529 | if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | ||
1530 | msg_dbg(buf_msg(buf), ">DEF-RETR>"); | ||
1531 | l_ptr->retransm_queue_head = mod(++r_q_head); | ||
1532 | l_ptr->retransm_queue_size = --r_q_size; | ||
1533 | l_ptr->stats.retransmitted++; | ||
1534 | return TIPC_OK; | ||
1535 | } else { | ||
1536 | l_ptr->stats.bearer_congs++; | ||
1537 | msg_dbg(buf_msg(buf), "|>DEF-RETR>"); | ||
1538 | return PUSH_FAILED; | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1542 | /* Send deferred protocol message, if any: */ | ||
1543 | |||
1544 | buf = l_ptr->proto_msg_queue; | ||
1545 | if (buf) { | ||
1546 | msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1)); | ||
1547 | msg_set_bcast_ack(buf_msg(buf),l_ptr->owner->bclink.last_in); | ||
1548 | if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | ||
1549 | msg_dbg(buf_msg(buf), ">DEF-PROT>"); | ||
1550 | l_ptr->unacked_window = 0; | ||
1551 | buf_discard(buf); | ||
1552 | l_ptr->proto_msg_queue = 0; | ||
1553 | return TIPC_OK; | ||
1554 | } else { | ||
1555 | msg_dbg(buf_msg(buf), "|>DEF-PROT>"); | ||
1556 | l_ptr->stats.bearer_congs++; | ||
1557 | return PUSH_FAILED; | ||
1558 | } | ||
1559 | } | ||
1560 | |||
1561 | /* Send one deferred data message, if send window not full: */ | ||
1562 | |||
1563 | buf = l_ptr->next_out; | ||
1564 | if (buf) { | ||
1565 | struct tipc_msg *msg = buf_msg(buf); | ||
1566 | u32 next = msg_seqno(msg); | ||
1567 | u32 first = msg_seqno(buf_msg(l_ptr->first_out)); | ||
1568 | |||
1569 | if (mod(next - first) < l_ptr->queue_limit[0]) { | ||
1570 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | ||
1571 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | ||
1572 | if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | ||
1573 | if (msg_user(msg) == MSG_BUNDLER) | ||
1574 | msg_set_type(msg, CLOSED_MSG); | ||
1575 | msg_dbg(msg, ">PUSH-DATA>"); | ||
1576 | l_ptr->next_out = buf->next; | ||
1577 | return TIPC_OK; | ||
1578 | } else { | ||
1579 | msg_dbg(msg, "|PUSH-DATA|"); | ||
1580 | l_ptr->stats.bearer_congs++; | ||
1581 | return PUSH_FAILED; | ||
1582 | } | ||
1583 | } | ||
1584 | } | ||
1585 | return PUSH_FINISHED; | ||
1586 | } | ||
1587 | |||
1588 | /* | ||
1589 | * push_queue(): push out the unsent messages of a link where | ||
1590 | * congestion has abated. Node is locked | ||
1591 | */ | ||
1592 | void link_push_queue(struct link *l_ptr) | ||
1593 | { | ||
1594 | u32 res; | ||
1595 | |||
1596 | if (bearer_congested(l_ptr->b_ptr, l_ptr)) | ||
1597 | return; | ||
1598 | |||
1599 | do { | ||
1600 | res = link_push_packet(l_ptr); | ||
1601 | } | ||
1602 | while (res == TIPC_OK); | ||
1603 | if (res == PUSH_FAILED) | ||
1604 | bearer_schedule(l_ptr->b_ptr, l_ptr); | ||
1605 | } | ||
1606 | |||
1607 | void link_retransmit(struct link *l_ptr, struct sk_buff *buf, | ||
1608 | u32 retransmits) | ||
1609 | { | ||
1610 | struct tipc_msg *msg; | ||
1611 | |||
1612 | dbg("Retransmitting %u in link %x\n", retransmits, l_ptr); | ||
1613 | |||
1614 | if (bearer_congested(l_ptr->b_ptr, l_ptr) && buf && !skb_cloned(buf)) { | ||
1615 | msg_dbg(buf_msg(buf), ">NO_RETR->BCONG>"); | ||
1616 | dbg_print_link(l_ptr, " "); | ||
1617 | l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf)); | ||
1618 | l_ptr->retransm_queue_size = retransmits; | ||
1619 | return; | ||
1620 | } | ||
1621 | while (retransmits && (buf != l_ptr->next_out) && buf && !skb_cloned(buf)) { | ||
1622 | msg = buf_msg(buf); | ||
1623 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | ||
1624 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | ||
1625 | if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | ||
1626 | /* Catch if retransmissions fail repeatedly: */ | ||
1627 | if (l_ptr->last_retransmitted == msg_seqno(msg)) { | ||
1628 | if (++l_ptr->stale_count > 100) { | ||
1629 | msg_print(CONS, buf_msg(buf), ">RETR>"); | ||
1630 | info("...Retransmitted %u times\n", | ||
1631 | l_ptr->stale_count); | ||
1632 | link_print(l_ptr, CONS, "Resetting Link\n");; | ||
1633 | link_reset(l_ptr); | ||
1634 | break; | ||
1635 | } | ||
1636 | } else { | ||
1637 | l_ptr->stale_count = 0; | ||
1638 | } | ||
1639 | l_ptr->last_retransmitted = msg_seqno(msg); | ||
1640 | |||
1641 | msg_dbg(buf_msg(buf), ">RETR>"); | ||
1642 | buf = buf->next; | ||
1643 | retransmits--; | ||
1644 | l_ptr->stats.retransmitted++; | ||
1645 | } else { | ||
1646 | bearer_schedule(l_ptr->b_ptr, l_ptr); | ||
1647 | l_ptr->stats.bearer_congs++; | ||
1648 | l_ptr->retransm_queue_head = msg_seqno(buf_msg(buf)); | ||
1649 | l_ptr->retransm_queue_size = retransmits; | ||
1650 | return; | ||
1651 | } | ||
1652 | } | ||
1653 | l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0; | ||
1654 | } | ||
1655 | |||
1656 | /* | ||
1657 | * link_recv_non_seq: Receive packets which are outside | ||
1658 | * the link sequence flow | ||
1659 | */ | ||
1660 | |||
1661 | static void link_recv_non_seq(struct sk_buff *buf) | ||
1662 | { | ||
1663 | struct tipc_msg *msg = buf_msg(buf); | ||
1664 | |||
1665 | if (msg_user(msg) == LINK_CONFIG) | ||
1666 | disc_recv_msg(buf); | ||
1667 | else | ||
1668 | bclink_recv_pkt(buf); | ||
1669 | } | ||
1670 | |||
1671 | /** | ||
1672 | * link_insert_deferred_queue - insert deferred messages back into receive chain | ||
1673 | */ | ||
1674 | |||
1675 | static struct sk_buff *link_insert_deferred_queue(struct link *l_ptr, | ||
1676 | struct sk_buff *buf) | ||
1677 | { | ||
1678 | u32 seq_no; | ||
1679 | |||
1680 | if (l_ptr->oldest_deferred_in == NULL) | ||
1681 | return buf; | ||
1682 | |||
1683 | seq_no = msg_seqno(buf_msg(l_ptr->oldest_deferred_in)); | ||
1684 | if (seq_no == mod(l_ptr->next_in_no)) { | ||
1685 | l_ptr->newest_deferred_in->next = buf; | ||
1686 | buf = l_ptr->oldest_deferred_in; | ||
1687 | l_ptr->oldest_deferred_in = NULL; | ||
1688 | l_ptr->deferred_inqueue_sz = 0; | ||
1689 | } | ||
1690 | return buf; | ||
1691 | } | ||
1692 | |||
1693 | void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *tb_ptr) | ||
1694 | { | ||
1695 | read_lock_bh(&net_lock); | ||
1696 | while (head) { | ||
1697 | struct bearer *b_ptr; | ||
1698 | struct node *n_ptr; | ||
1699 | struct link *l_ptr; | ||
1700 | struct sk_buff *crs; | ||
1701 | struct sk_buff *buf = head; | ||
1702 | struct tipc_msg *msg = buf_msg(buf); | ||
1703 | u32 seq_no = msg_seqno(msg); | ||
1704 | u32 ackd = msg_ack(msg); | ||
1705 | u32 released = 0; | ||
1706 | int type; | ||
1707 | |||
1708 | b_ptr = (struct bearer *)tb_ptr; | ||
1709 | TIPC_SKB_CB(buf)->handle = b_ptr; | ||
1710 | |||
1711 | head = head->next; | ||
1712 | if (unlikely(msg_version(msg) != TIPC_VERSION)) | ||
1713 | goto cont; | ||
1714 | #if 0 | ||
1715 | if (msg_user(msg) != LINK_PROTOCOL) | ||
1716 | #endif | ||
1717 | msg_dbg(msg,"<REC<"); | ||
1718 | |||
1719 | if (unlikely(msg_non_seq(msg))) { | ||
1720 | link_recv_non_seq(buf); | ||
1721 | continue; | ||
1722 | } | ||
1723 | n_ptr = node_find(msg_prevnode(msg)); | ||
1724 | if (unlikely(!n_ptr)) | ||
1725 | goto cont; | ||
1726 | |||
1727 | node_lock(n_ptr); | ||
1728 | l_ptr = n_ptr->links[b_ptr->identity]; | ||
1729 | if (unlikely(!l_ptr)) { | ||
1730 | node_unlock(n_ptr); | ||
1731 | goto cont; | ||
1732 | } | ||
1733 | /* | ||
1734 | * Release acked messages | ||
1735 | */ | ||
1736 | if (less(n_ptr->bclink.acked, msg_bcast_ack(msg))) { | ||
1737 | if (node_is_up(n_ptr) && n_ptr->bclink.supported) | ||
1738 | bclink_acknowledge(n_ptr, msg_bcast_ack(msg)); | ||
1739 | } | ||
1740 | |||
1741 | crs = l_ptr->first_out; | ||
1742 | while ((crs != l_ptr->next_out) && | ||
1743 | less_eq(msg_seqno(buf_msg(crs)), ackd)) { | ||
1744 | struct sk_buff *next = crs->next; | ||
1745 | |||
1746 | buf_discard(crs); | ||
1747 | crs = next; | ||
1748 | released++; | ||
1749 | } | ||
1750 | if (released) { | ||
1751 | l_ptr->first_out = crs; | ||
1752 | l_ptr->out_queue_size -= released; | ||
1753 | } | ||
1754 | if (unlikely(l_ptr->next_out)) | ||
1755 | link_push_queue(l_ptr); | ||
1756 | if (unlikely(!list_empty(&l_ptr->waiting_ports))) | ||
1757 | link_wakeup_ports(l_ptr, 0); | ||
1758 | if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) { | ||
1759 | l_ptr->stats.sent_acks++; | ||
1760 | link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); | ||
1761 | } | ||
1762 | |||
1763 | protocol_check: | ||
1764 | if (likely(link_working_working(l_ptr))) { | ||
1765 | if (likely(seq_no == mod(l_ptr->next_in_no))) { | ||
1766 | l_ptr->next_in_no++; | ||
1767 | if (unlikely(l_ptr->oldest_deferred_in)) | ||
1768 | head = link_insert_deferred_queue(l_ptr, | ||
1769 | head); | ||
1770 | if (likely(msg_is_dest(msg, tipc_own_addr))) { | ||
1771 | deliver: | ||
1772 | if (likely(msg_isdata(msg))) { | ||
1773 | node_unlock(n_ptr); | ||
1774 | port_recv_msg(buf); | ||
1775 | continue; | ||
1776 | } | ||
1777 | switch (msg_user(msg)) { | ||
1778 | case MSG_BUNDLER: | ||
1779 | l_ptr->stats.recv_bundles++; | ||
1780 | l_ptr->stats.recv_bundled += | ||
1781 | msg_msgcnt(msg); | ||
1782 | node_unlock(n_ptr); | ||
1783 | link_recv_bundle(buf); | ||
1784 | continue; | ||
1785 | case ROUTE_DISTRIBUTOR: | ||
1786 | node_unlock(n_ptr); | ||
1787 | cluster_recv_routing_table(buf); | ||
1788 | continue; | ||
1789 | case NAME_DISTRIBUTOR: | ||
1790 | node_unlock(n_ptr); | ||
1791 | named_recv(buf); | ||
1792 | continue; | ||
1793 | case CONN_MANAGER: | ||
1794 | node_unlock(n_ptr); | ||
1795 | port_recv_proto_msg(buf); | ||
1796 | continue; | ||
1797 | case MSG_FRAGMENTER: | ||
1798 | l_ptr->stats.recv_fragments++; | ||
1799 | if (link_recv_fragment( | ||
1800 | &l_ptr->defragm_buf, | ||
1801 | &buf, &msg)) { | ||
1802 | l_ptr->stats.recv_fragmented++; | ||
1803 | goto deliver; | ||
1804 | } | ||
1805 | break; | ||
1806 | case CHANGEOVER_PROTOCOL: | ||
1807 | type = msg_type(msg); | ||
1808 | if (link_recv_changeover_msg( | ||
1809 | &l_ptr, &buf)) { | ||
1810 | msg = buf_msg(buf); | ||
1811 | seq_no = msg_seqno(msg); | ||
1812 | TIPC_SKB_CB(buf)->handle | ||
1813 | = b_ptr; | ||
1814 | if (type == ORIGINAL_MSG) | ||
1815 | goto deliver; | ||
1816 | goto protocol_check; | ||
1817 | } | ||
1818 | break; | ||
1819 | } | ||
1820 | } | ||
1821 | node_unlock(n_ptr); | ||
1822 | net_route_msg(buf); | ||
1823 | continue; | ||
1824 | } | ||
1825 | link_handle_out_of_seq_msg(l_ptr, buf); | ||
1826 | head = link_insert_deferred_queue(l_ptr, head); | ||
1827 | node_unlock(n_ptr); | ||
1828 | continue; | ||
1829 | } | ||
1830 | |||
1831 | if (msg_user(msg) == LINK_PROTOCOL) { | ||
1832 | link_recv_proto_msg(l_ptr, buf); | ||
1833 | head = link_insert_deferred_queue(l_ptr, head); | ||
1834 | node_unlock(n_ptr); | ||
1835 | continue; | ||
1836 | } | ||
1837 | msg_dbg(msg,"NSEQ<REC<"); | ||
1838 | link_state_event(l_ptr, TRAFFIC_MSG_EVT); | ||
1839 | |||
1840 | if (link_working_working(l_ptr)) { | ||
1841 | /* Re-insert in front of queue */ | ||
1842 | msg_dbg(msg,"RECV-REINS:"); | ||
1843 | buf->next = head; | ||
1844 | head = buf; | ||
1845 | node_unlock(n_ptr); | ||
1846 | continue; | ||
1847 | } | ||
1848 | node_unlock(n_ptr); | ||
1849 | cont: | ||
1850 | buf_discard(buf); | ||
1851 | } | ||
1852 | read_unlock_bh(&net_lock); | ||
1853 | } | ||
1854 | |||
1855 | /* | ||
1856 | * link_defer_buf(): Sort a received out-of-sequence packet | ||
1857 | * into the deferred reception queue. | ||
1858 | * Returns the increase of the queue length,i.e. 0 or 1 | ||
1859 | */ | ||
1860 | |||
1861 | u32 link_defer_pkt(struct sk_buff **head, | ||
1862 | struct sk_buff **tail, | ||
1863 | struct sk_buff *buf) | ||
1864 | { | ||
1865 | struct sk_buff *prev = 0; | ||
1866 | struct sk_buff *crs = *head; | ||
1867 | u32 seq_no = msg_seqno(buf_msg(buf)); | ||
1868 | |||
1869 | buf->next = NULL; | ||
1870 | |||
1871 | /* Empty queue ? */ | ||
1872 | if (*head == NULL) { | ||
1873 | *head = *tail = buf; | ||
1874 | return 1; | ||
1875 | } | ||
1876 | |||
1877 | /* Last ? */ | ||
1878 | if (less(msg_seqno(buf_msg(*tail)), seq_no)) { | ||
1879 | (*tail)->next = buf; | ||
1880 | *tail = buf; | ||
1881 | return 1; | ||
1882 | } | ||
1883 | |||
1884 | /* Scan through queue and sort it in */ | ||
1885 | do { | ||
1886 | struct tipc_msg *msg = buf_msg(crs); | ||
1887 | |||
1888 | if (less(seq_no, msg_seqno(msg))) { | ||
1889 | buf->next = crs; | ||
1890 | if (prev) | ||
1891 | prev->next = buf; | ||
1892 | else | ||
1893 | *head = buf; | ||
1894 | return 1; | ||
1895 | } | ||
1896 | if (seq_no == msg_seqno(msg)) { | ||
1897 | break; | ||
1898 | } | ||
1899 | prev = crs; | ||
1900 | crs = crs->next; | ||
1901 | } | ||
1902 | while (crs); | ||
1903 | |||
1904 | /* Message is a duplicate of an existing message */ | ||
1905 | |||
1906 | buf_discard(buf); | ||
1907 | return 0; | ||
1908 | } | ||
1909 | |||
1910 | /** | ||
1911 | * link_handle_out_of_seq_msg - handle arrival of out-of-sequence packet | ||
1912 | */ | ||
1913 | |||
1914 | static void link_handle_out_of_seq_msg(struct link *l_ptr, | ||
1915 | struct sk_buff *buf) | ||
1916 | { | ||
1917 | u32 seq_no = msg_seqno(buf_msg(buf)); | ||
1918 | |||
1919 | if (likely(msg_user(buf_msg(buf)) == LINK_PROTOCOL)) { | ||
1920 | link_recv_proto_msg(l_ptr, buf); | ||
1921 | return; | ||
1922 | } | ||
1923 | |||
1924 | dbg("rx OOS msg: seq_no %u, expecting %u (%u)\n", | ||
1925 | seq_no, mod(l_ptr->next_in_no), l_ptr->next_in_no); | ||
1926 | |||
1927 | /* Record OOS packet arrival (force mismatch on next timeout) */ | ||
1928 | |||
1929 | l_ptr->checkpoint--; | ||
1930 | |||
1931 | /* | ||
1932 | * Discard packet if a duplicate; otherwise add it to deferred queue | ||
1933 | * and notify peer of gap as per protocol specification | ||
1934 | */ | ||
1935 | |||
1936 | if (less(seq_no, mod(l_ptr->next_in_no))) { | ||
1937 | l_ptr->stats.duplicates++; | ||
1938 | buf_discard(buf); | ||
1939 | return; | ||
1940 | } | ||
1941 | |||
1942 | if (link_defer_pkt(&l_ptr->oldest_deferred_in, | ||
1943 | &l_ptr->newest_deferred_in, buf)) { | ||
1944 | l_ptr->deferred_inqueue_sz++; | ||
1945 | l_ptr->stats.deferred_recv++; | ||
1946 | if ((l_ptr->deferred_inqueue_sz % 16) == 1) | ||
1947 | link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); | ||
1948 | } else | ||
1949 | l_ptr->stats.duplicates++; | ||
1950 | } | ||
1951 | |||
1952 | /* | ||
1953 | * Send protocol message to the other endpoint. | ||
1954 | */ | ||
1955 | void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int probe_msg, | ||
1956 | u32 gap, u32 tolerance, u32 priority, u32 ack_mtu) | ||
1957 | { | ||
1958 | struct sk_buff *buf = 0; | ||
1959 | struct tipc_msg *msg = l_ptr->pmsg; | ||
1960 | u32 msg_size = sizeof(l_ptr->proto_msg); | ||
1961 | |||
1962 | if (link_blocked(l_ptr)) | ||
1963 | return; | ||
1964 | msg_set_type(msg, msg_typ); | ||
1965 | msg_set_net_plane(msg, l_ptr->b_ptr->net_plane); | ||
1966 | msg_set_bcast_ack(msg, mod(l_ptr->owner->bclink.last_in)); | ||
1967 | msg_set_last_bcast(msg, bclink_get_last_sent()); | ||
1968 | |||
1969 | if (msg_typ == STATE_MSG) { | ||
1970 | u32 next_sent = mod(l_ptr->next_out_no); | ||
1971 | |||
1972 | if (!link_is_up(l_ptr)) | ||
1973 | return; | ||
1974 | if (l_ptr->next_out) | ||
1975 | next_sent = msg_seqno(buf_msg(l_ptr->next_out)); | ||
1976 | msg_set_next_sent(msg, next_sent); | ||
1977 | if (l_ptr->oldest_deferred_in) { | ||
1978 | u32 rec = msg_seqno(buf_msg(l_ptr->oldest_deferred_in)); | ||
1979 | gap = mod(rec - mod(l_ptr->next_in_no)); | ||
1980 | } | ||
1981 | msg_set_seq_gap(msg, gap); | ||
1982 | if (gap) | ||
1983 | l_ptr->stats.sent_nacks++; | ||
1984 | msg_set_link_tolerance(msg, tolerance); | ||
1985 | msg_set_linkprio(msg, priority); | ||
1986 | msg_set_max_pkt(msg, ack_mtu); | ||
1987 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); | ||
1988 | msg_set_probe(msg, probe_msg != 0); | ||
1989 | if (probe_msg) { | ||
1990 | u32 mtu = l_ptr->max_pkt; | ||
1991 | |||
1992 | if ((mtu < l_ptr->max_pkt_target) && | ||
1993 | link_working_working(l_ptr) && | ||
1994 | l_ptr->fsm_msg_cnt) { | ||
1995 | msg_size = (mtu + (l_ptr->max_pkt_target - mtu)/2 + 2) & ~3; | ||
1996 | if (l_ptr->max_pkt_probes == 10) { | ||
1997 | l_ptr->max_pkt_target = (msg_size - 4); | ||
1998 | l_ptr->max_pkt_probes = 0; | ||
1999 | msg_size = (mtu + (l_ptr->max_pkt_target - mtu)/2 + 2) & ~3; | ||
2000 | } | ||
2001 | l_ptr->max_pkt_probes++; | ||
2002 | } | ||
2003 | |||
2004 | l_ptr->stats.sent_probes++; | ||
2005 | } | ||
2006 | l_ptr->stats.sent_states++; | ||
2007 | } else { /* RESET_MSG or ACTIVATE_MSG */ | ||
2008 | msg_set_ack(msg, mod(l_ptr->reset_checkpoint - 1)); | ||
2009 | msg_set_seq_gap(msg, 0); | ||
2010 | msg_set_next_sent(msg, 1); | ||
2011 | msg_set_link_tolerance(msg, l_ptr->tolerance); | ||
2012 | msg_set_linkprio(msg, l_ptr->priority); | ||
2013 | msg_set_max_pkt(msg, l_ptr->max_pkt_target); | ||
2014 | } | ||
2015 | |||
2016 | if (node_has_redundant_links(l_ptr->owner)) { | ||
2017 | msg_set_redundant_link(msg); | ||
2018 | } else { | ||
2019 | msg_clear_redundant_link(msg); | ||
2020 | } | ||
2021 | msg_set_linkprio(msg, l_ptr->priority); | ||
2022 | |||
2023 | /* Ensure sequence number will not fit : */ | ||
2024 | |||
2025 | msg_set_seqno(msg, mod(l_ptr->next_out_no + (0xffff/2))); | ||
2026 | |||
2027 | /* Congestion? */ | ||
2028 | |||
2029 | if (bearer_congested(l_ptr->b_ptr, l_ptr)) { | ||
2030 | if (!l_ptr->proto_msg_queue) { | ||
2031 | l_ptr->proto_msg_queue = | ||
2032 | buf_acquire(sizeof(l_ptr->proto_msg)); | ||
2033 | } | ||
2034 | buf = l_ptr->proto_msg_queue; | ||
2035 | if (!buf) | ||
2036 | return; | ||
2037 | memcpy(buf->data, (unchar *)msg, sizeof(l_ptr->proto_msg)); | ||
2038 | return; | ||
2039 | } | ||
2040 | msg_set_timestamp(msg, jiffies_to_msecs(jiffies)); | ||
2041 | |||
2042 | /* Message can be sent */ | ||
2043 | |||
2044 | msg_dbg(msg, ">>"); | ||
2045 | |||
2046 | buf = buf_acquire(msg_size); | ||
2047 | if (!buf) | ||
2048 | return; | ||
2049 | |||
2050 | memcpy(buf->data, (unchar *)msg, sizeof(l_ptr->proto_msg)); | ||
2051 | msg_set_size(buf_msg(buf), msg_size); | ||
2052 | |||
2053 | if (bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) { | ||
2054 | l_ptr->unacked_window = 0; | ||
2055 | buf_discard(buf); | ||
2056 | return; | ||
2057 | } | ||
2058 | |||
2059 | /* New congestion */ | ||
2060 | bearer_schedule(l_ptr->b_ptr, l_ptr); | ||
2061 | l_ptr->proto_msg_queue = buf; | ||
2062 | l_ptr->stats.bearer_congs++; | ||
2063 | } | ||
2064 | |||
2065 | /* | ||
2066 | * Receive protocol message : | ||
2067 | * Note that network plane id propagates through the network, and may | ||
2068 | * change at any time. The node with lowest address rules | ||
2069 | */ | ||
2070 | |||
2071 | static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf) | ||
2072 | { | ||
2073 | u32 rec_gap = 0; | ||
2074 | u32 max_pkt_info; | ||
2075 | u32 max_pkt_ack; | ||
2076 | u32 msg_tol; | ||
2077 | struct tipc_msg *msg = buf_msg(buf); | ||
2078 | |||
2079 | dbg("AT(%u):", jiffies_to_msecs(jiffies)); | ||
2080 | msg_dbg(msg, "<<"); | ||
2081 | if (link_blocked(l_ptr)) | ||
2082 | goto exit; | ||
2083 | |||
2084 | /* record unnumbered packet arrival (force mismatch on next timeout) */ | ||
2085 | |||
2086 | l_ptr->checkpoint--; | ||
2087 | |||
2088 | if (l_ptr->b_ptr->net_plane != msg_net_plane(msg)) | ||
2089 | if (tipc_own_addr > msg_prevnode(msg)) | ||
2090 | l_ptr->b_ptr->net_plane = msg_net_plane(msg); | ||
2091 | |||
2092 | l_ptr->owner->permit_changeover = msg_redundant_link(msg); | ||
2093 | |||
2094 | switch (msg_type(msg)) { | ||
2095 | |||
2096 | case RESET_MSG: | ||
2097 | if (!link_working_unknown(l_ptr) && l_ptr->peer_session) { | ||
2098 | if (msg_session(msg) == l_ptr->peer_session) { | ||
2099 | dbg("Duplicate RESET: %u<->%u\n", | ||
2100 | msg_session(msg), l_ptr->peer_session); | ||
2101 | break; /* duplicate: ignore */ | ||
2102 | } | ||
2103 | } | ||
2104 | /* fall thru' */ | ||
2105 | case ACTIVATE_MSG: | ||
2106 | /* Update link settings according other endpoint's values */ | ||
2107 | |||
2108 | strcpy((strrchr(l_ptr->name, ':') + 1), (char *)msg_data(msg)); | ||
2109 | |||
2110 | if ((msg_tol = msg_link_tolerance(msg)) && | ||
2111 | (msg_tol > l_ptr->tolerance)) | ||
2112 | link_set_supervision_props(l_ptr, msg_tol); | ||
2113 | |||
2114 | if (msg_linkprio(msg) > l_ptr->priority) | ||
2115 | l_ptr->priority = msg_linkprio(msg); | ||
2116 | |||
2117 | max_pkt_info = msg_max_pkt(msg); | ||
2118 | if (max_pkt_info) { | ||
2119 | if (max_pkt_info < l_ptr->max_pkt_target) | ||
2120 | l_ptr->max_pkt_target = max_pkt_info; | ||
2121 | if (l_ptr->max_pkt > l_ptr->max_pkt_target) | ||
2122 | l_ptr->max_pkt = l_ptr->max_pkt_target; | ||
2123 | } else { | ||
2124 | l_ptr->max_pkt = l_ptr->max_pkt_target; | ||
2125 | } | ||
2126 | l_ptr->owner->bclink.supported = (max_pkt_info != 0); | ||
2127 | |||
2128 | link_state_event(l_ptr, msg_type(msg)); | ||
2129 | |||
2130 | l_ptr->peer_session = msg_session(msg); | ||
2131 | l_ptr->peer_bearer_id = msg_bearer_id(msg); | ||
2132 | |||
2133 | /* Synchronize broadcast sequence numbers */ | ||
2134 | if (!node_has_redundant_links(l_ptr->owner)) { | ||
2135 | l_ptr->owner->bclink.last_in = mod(msg_last_bcast(msg)); | ||
2136 | } | ||
2137 | break; | ||
2138 | case STATE_MSG: | ||
2139 | |||
2140 | if ((msg_tol = msg_link_tolerance(msg))) | ||
2141 | link_set_supervision_props(l_ptr, msg_tol); | ||
2142 | |||
2143 | if (msg_linkprio(msg) && | ||
2144 | (msg_linkprio(msg) != l_ptr->priority)) { | ||
2145 | warn("Changing prio <%s>: %u->%u\n", | ||
2146 | l_ptr->name, l_ptr->priority, msg_linkprio(msg)); | ||
2147 | l_ptr->priority = msg_linkprio(msg); | ||
2148 | link_reset(l_ptr); /* Enforce change to take effect */ | ||
2149 | break; | ||
2150 | } | ||
2151 | link_state_event(l_ptr, TRAFFIC_MSG_EVT); | ||
2152 | l_ptr->stats.recv_states++; | ||
2153 | if (link_reset_unknown(l_ptr)) | ||
2154 | break; | ||
2155 | |||
2156 | if (less_eq(mod(l_ptr->next_in_no), msg_next_sent(msg))) { | ||
2157 | rec_gap = mod(msg_next_sent(msg) - | ||
2158 | mod(l_ptr->next_in_no)); | ||
2159 | } | ||
2160 | |||
2161 | max_pkt_ack = msg_max_pkt(msg); | ||
2162 | if (max_pkt_ack > l_ptr->max_pkt) { | ||
2163 | dbg("Link <%s> updated MTU %u -> %u\n", | ||
2164 | l_ptr->name, l_ptr->max_pkt, max_pkt_ack); | ||
2165 | l_ptr->max_pkt = max_pkt_ack; | ||
2166 | l_ptr->max_pkt_probes = 0; | ||
2167 | } | ||
2168 | |||
2169 | max_pkt_ack = 0; | ||
2170 | if (msg_probe(msg)) { | ||
2171 | l_ptr->stats.recv_probes++; | ||
2172 | if (msg_size(msg) > sizeof(l_ptr->proto_msg)) { | ||
2173 | max_pkt_ack = msg_size(msg); | ||
2174 | } | ||
2175 | } | ||
2176 | |||
2177 | /* Protocol message before retransmits, reduce loss risk */ | ||
2178 | |||
2179 | bclink_check_gap(l_ptr->owner, msg_last_bcast(msg)); | ||
2180 | |||
2181 | if (rec_gap || (msg_probe(msg))) { | ||
2182 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
2183 | 0, rec_gap, 0, 0, max_pkt_ack); | ||
2184 | } | ||
2185 | if (msg_seq_gap(msg)) { | ||
2186 | msg_dbg(msg, "With Gap:"); | ||
2187 | l_ptr->stats.recv_nacks++; | ||
2188 | link_retransmit(l_ptr, l_ptr->first_out, | ||
2189 | msg_seq_gap(msg)); | ||
2190 | } | ||
2191 | break; | ||
2192 | default: | ||
2193 | msg_dbg(buf_msg(buf), "<DISCARDING UNKNOWN<"); | ||
2194 | } | ||
2195 | exit: | ||
2196 | buf_discard(buf); | ||
2197 | } | ||
2198 | |||
2199 | |||
2200 | /* | ||
2201 | * link_tunnel(): Send one message via a link belonging to | ||
2202 | * another bearer. Owner node is locked. | ||
2203 | */ | ||
2204 | void link_tunnel(struct link *l_ptr, | ||
2205 | struct tipc_msg *tunnel_hdr, | ||
2206 | struct tipc_msg *msg, | ||
2207 | u32 selector) | ||
2208 | { | ||
2209 | struct link *tunnel; | ||
2210 | struct sk_buff *buf; | ||
2211 | u32 length = msg_size(msg); | ||
2212 | |||
2213 | tunnel = l_ptr->owner->active_links[selector & 1]; | ||
2214 | if (!link_is_up(tunnel)) | ||
2215 | return; | ||
2216 | msg_set_size(tunnel_hdr, length + INT_H_SIZE); | ||
2217 | buf = buf_acquire(length + INT_H_SIZE); | ||
2218 | if (!buf) | ||
2219 | return; | ||
2220 | memcpy(buf->data, (unchar *)tunnel_hdr, INT_H_SIZE); | ||
2221 | memcpy(buf->data + INT_H_SIZE, (unchar *)msg, length); | ||
2222 | dbg("%c->%c:", l_ptr->b_ptr->net_plane, tunnel->b_ptr->net_plane); | ||
2223 | msg_dbg(buf_msg(buf), ">SEND>"); | ||
2224 | assert(tunnel); | ||
2225 | link_send_buf(tunnel, buf); | ||
2226 | } | ||
2227 | |||
2228 | |||
2229 | |||
2230 | /* | ||
2231 | * changeover(): Send whole message queue via the remaining link | ||
2232 | * Owner node is locked. | ||
2233 | */ | ||
2234 | |||
2235 | void link_changeover(struct link *l_ptr) | ||
2236 | { | ||
2237 | u32 msgcount = l_ptr->out_queue_size; | ||
2238 | struct sk_buff *crs = l_ptr->first_out; | ||
2239 | struct link *tunnel = l_ptr->owner->active_links[0]; | ||
2240 | int split_bundles = node_has_redundant_links(l_ptr->owner); | ||
2241 | struct tipc_msg tunnel_hdr; | ||
2242 | |||
2243 | if (!tunnel) | ||
2244 | return; | ||
2245 | |||
2246 | if (!l_ptr->owner->permit_changeover) | ||
2247 | return; | ||
2248 | |||
2249 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, | ||
2250 | ORIGINAL_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); | ||
2251 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); | ||
2252 | msg_set_msgcnt(&tunnel_hdr, msgcount); | ||
2253 | if (!l_ptr->first_out) { | ||
2254 | struct sk_buff *buf; | ||
2255 | |||
2256 | assert(!msgcount); | ||
2257 | buf = buf_acquire(INT_H_SIZE); | ||
2258 | if (buf) { | ||
2259 | memcpy(buf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); | ||
2260 | msg_set_size(&tunnel_hdr, INT_H_SIZE); | ||
2261 | dbg("%c->%c:", l_ptr->b_ptr->net_plane, | ||
2262 | tunnel->b_ptr->net_plane); | ||
2263 | msg_dbg(&tunnel_hdr, "EMPTY>SEND>"); | ||
2264 | link_send_buf(tunnel, buf); | ||
2265 | } else { | ||
2266 | warn("Memory squeeze; link changeover failed\n"); | ||
2267 | } | ||
2268 | return; | ||
2269 | } | ||
2270 | while (crs) { | ||
2271 | struct tipc_msg *msg = buf_msg(crs); | ||
2272 | |||
2273 | if ((msg_user(msg) == MSG_BUNDLER) && split_bundles) { | ||
2274 | u32 msgcount = msg_msgcnt(msg); | ||
2275 | struct tipc_msg *m = msg_get_wrapped(msg); | ||
2276 | unchar* pos = (unchar*)m; | ||
2277 | |||
2278 | while (msgcount--) { | ||
2279 | msg_set_seqno(m,msg_seqno(msg)); | ||
2280 | link_tunnel(l_ptr, &tunnel_hdr, m, | ||
2281 | msg_link_selector(m)); | ||
2282 | pos += align(msg_size(m)); | ||
2283 | m = (struct tipc_msg *)pos; | ||
2284 | } | ||
2285 | } else { | ||
2286 | link_tunnel(l_ptr, &tunnel_hdr, msg, | ||
2287 | msg_link_selector(msg)); | ||
2288 | } | ||
2289 | crs = crs->next; | ||
2290 | } | ||
2291 | } | ||
2292 | |||
2293 | void link_send_duplicate(struct link *l_ptr, struct link *tunnel) | ||
2294 | { | ||
2295 | struct sk_buff *iter; | ||
2296 | struct tipc_msg tunnel_hdr; | ||
2297 | |||
2298 | msg_init(&tunnel_hdr, CHANGEOVER_PROTOCOL, | ||
2299 | DUPLICATE_MSG, TIPC_OK, INT_H_SIZE, l_ptr->addr); | ||
2300 | msg_set_msgcnt(&tunnel_hdr, l_ptr->out_queue_size); | ||
2301 | msg_set_bearer_id(&tunnel_hdr, l_ptr->peer_bearer_id); | ||
2302 | iter = l_ptr->first_out; | ||
2303 | while (iter) { | ||
2304 | struct sk_buff *outbuf; | ||
2305 | struct tipc_msg *msg = buf_msg(iter); | ||
2306 | u32 length = msg_size(msg); | ||
2307 | |||
2308 | if (msg_user(msg) == MSG_BUNDLER) | ||
2309 | msg_set_type(msg, CLOSED_MSG); | ||
2310 | msg_set_ack(msg, mod(l_ptr->next_in_no - 1)); /* Update */ | ||
2311 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | ||
2312 | msg_set_size(&tunnel_hdr, length + INT_H_SIZE); | ||
2313 | outbuf = buf_acquire(length + INT_H_SIZE); | ||
2314 | if (outbuf == NULL) { | ||
2315 | warn("Memory squeeze; buffer duplication failed\n"); | ||
2316 | return; | ||
2317 | } | ||
2318 | memcpy(outbuf->data, (unchar *)&tunnel_hdr, INT_H_SIZE); | ||
2319 | memcpy(outbuf->data + INT_H_SIZE, iter->data, length); | ||
2320 | dbg("%c->%c:", l_ptr->b_ptr->net_plane, | ||
2321 | tunnel->b_ptr->net_plane); | ||
2322 | msg_dbg(buf_msg(outbuf), ">SEND>"); | ||
2323 | link_send_buf(tunnel, outbuf); | ||
2324 | if (!link_is_up(l_ptr)) | ||
2325 | return; | ||
2326 | iter = iter->next; | ||
2327 | } | ||
2328 | } | ||
2329 | |||
2330 | |||
2331 | |||
2332 | /** | ||
2333 | * buf_extract - extracts embedded TIPC message from another message | ||
2334 | * @skb: encapsulating message buffer | ||
2335 | * @from_pos: offset to extract from | ||
2336 | * | ||
2337 | * Returns a new message buffer containing an embedded message. The | ||
2338 | * encapsulating message itself is left unchanged. | ||
2339 | */ | ||
2340 | |||
2341 | static struct sk_buff *buf_extract(struct sk_buff *skb, u32 from_pos) | ||
2342 | { | ||
2343 | struct tipc_msg *msg = (struct tipc_msg *)(skb->data + from_pos); | ||
2344 | u32 size = msg_size(msg); | ||
2345 | struct sk_buff *eb; | ||
2346 | |||
2347 | eb = buf_acquire(size); | ||
2348 | if (eb) | ||
2349 | memcpy(eb->data, (unchar *)msg, size); | ||
2350 | return eb; | ||
2351 | } | ||
2352 | |||
2353 | /* | ||
2354 | * link_recv_changeover_msg(): Receive tunneled packet sent | ||
2355 | * via other link. Node is locked. Return extracted buffer. | ||
2356 | */ | ||
2357 | |||
2358 | static int link_recv_changeover_msg(struct link **l_ptr, | ||
2359 | struct sk_buff **buf) | ||
2360 | { | ||
2361 | struct sk_buff *tunnel_buf = *buf; | ||
2362 | struct link *dest_link; | ||
2363 | struct tipc_msg *msg; | ||
2364 | struct tipc_msg *tunnel_msg = buf_msg(tunnel_buf); | ||
2365 | u32 msg_typ = msg_type(tunnel_msg); | ||
2366 | u32 msg_count = msg_msgcnt(tunnel_msg); | ||
2367 | |||
2368 | dest_link = (*l_ptr)->owner->links[msg_bearer_id(tunnel_msg)]; | ||
2369 | assert(dest_link != *l_ptr); | ||
2370 | if (!dest_link) { | ||
2371 | msg_dbg(tunnel_msg, "NOLINK/<REC<"); | ||
2372 | goto exit; | ||
2373 | } | ||
2374 | dbg("%c<-%c:", dest_link->b_ptr->net_plane, | ||
2375 | (*l_ptr)->b_ptr->net_plane); | ||
2376 | *l_ptr = dest_link; | ||
2377 | msg = msg_get_wrapped(tunnel_msg); | ||
2378 | |||
2379 | if (msg_typ == DUPLICATE_MSG) { | ||
2380 | if (less(msg_seqno(msg), mod(dest_link->next_in_no))) { | ||
2381 | msg_dbg(tunnel_msg, "DROP/<REC<"); | ||
2382 | goto exit; | ||
2383 | } | ||
2384 | *buf = buf_extract(tunnel_buf,INT_H_SIZE); | ||
2385 | if (*buf == NULL) { | ||
2386 | warn("Memory squeeze; failed to extract msg\n"); | ||
2387 | goto exit; | ||
2388 | } | ||
2389 | msg_dbg(tunnel_msg, "TNL<REC<"); | ||
2390 | buf_discard(tunnel_buf); | ||
2391 | return 1; | ||
2392 | } | ||
2393 | |||
2394 | /* First original message ?: */ | ||
2395 | |||
2396 | if (link_is_up(dest_link)) { | ||
2397 | msg_dbg(tunnel_msg, "UP/FIRST/<REC<"); | ||
2398 | link_reset(dest_link); | ||
2399 | dest_link->exp_msg_count = msg_count; | ||
2400 | if (!msg_count) | ||
2401 | goto exit; | ||
2402 | } else if (dest_link->exp_msg_count == START_CHANGEOVER) { | ||
2403 | msg_dbg(tunnel_msg, "BLK/FIRST/<REC<"); | ||
2404 | dest_link->exp_msg_count = msg_count; | ||
2405 | if (!msg_count) | ||
2406 | goto exit; | ||
2407 | } | ||
2408 | |||
2409 | /* Receive original message */ | ||
2410 | |||
2411 | if (dest_link->exp_msg_count == 0) { | ||
2412 | msg_dbg(tunnel_msg, "OVERDUE/DROP/<REC<"); | ||
2413 | dbg_print_link(dest_link, "LINK:"); | ||
2414 | goto exit; | ||
2415 | } | ||
2416 | dest_link->exp_msg_count--; | ||
2417 | if (less(msg_seqno(msg), dest_link->reset_checkpoint)) { | ||
2418 | msg_dbg(tunnel_msg, "DROP/DUPL/<REC<"); | ||
2419 | goto exit; | ||
2420 | } else { | ||
2421 | *buf = buf_extract(tunnel_buf, INT_H_SIZE); | ||
2422 | if (*buf != NULL) { | ||
2423 | msg_dbg(tunnel_msg, "TNL<REC<"); | ||
2424 | buf_discard(tunnel_buf); | ||
2425 | return 1; | ||
2426 | } else { | ||
2427 | warn("Memory squeeze; dropped incoming msg\n"); | ||
2428 | } | ||
2429 | } | ||
2430 | exit: | ||
2431 | *buf = 0; | ||
2432 | buf_discard(tunnel_buf); | ||
2433 | return 0; | ||
2434 | } | ||
2435 | |||
2436 | /* | ||
2437 | * Bundler functionality: | ||
2438 | */ | ||
2439 | void link_recv_bundle(struct sk_buff *buf) | ||
2440 | { | ||
2441 | u32 msgcount = msg_msgcnt(buf_msg(buf)); | ||
2442 | u32 pos = INT_H_SIZE; | ||
2443 | struct sk_buff *obuf; | ||
2444 | |||
2445 | msg_dbg(buf_msg(buf), "<BNDL<: "); | ||
2446 | while (msgcount--) { | ||
2447 | obuf = buf_extract(buf, pos); | ||
2448 | if (obuf == NULL) { | ||
2449 | char addr_string[16]; | ||
2450 | |||
2451 | warn("Buffer allocation failure;\n"); | ||
2452 | warn(" incoming message(s) from %s lost\n", | ||
2453 | addr_string_fill(addr_string, | ||
2454 | msg_orignode(buf_msg(buf)))); | ||
2455 | return; | ||
2456 | }; | ||
2457 | pos += align(msg_size(buf_msg(obuf))); | ||
2458 | msg_dbg(buf_msg(obuf), " /"); | ||
2459 | net_route_msg(obuf); | ||
2460 | } | ||
2461 | buf_discard(buf); | ||
2462 | } | ||
2463 | |||
2464 | /* | ||
2465 | * Fragmentation/defragmentation: | ||
2466 | */ | ||
2467 | |||
2468 | |||
2469 | /* | ||
2470 | * link_send_long_buf: Entry for buffers needing fragmentation. | ||
2471 | * The buffer is complete, inclusive total message length. | ||
2472 | * Returns user data length. | ||
2473 | */ | ||
2474 | int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) | ||
2475 | { | ||
2476 | struct tipc_msg *inmsg = buf_msg(buf); | ||
2477 | struct tipc_msg fragm_hdr; | ||
2478 | u32 insize = msg_size(inmsg); | ||
2479 | u32 dsz = msg_data_sz(inmsg); | ||
2480 | unchar *crs = buf->data; | ||
2481 | u32 rest = insize; | ||
2482 | u32 pack_sz = link_max_pkt(l_ptr); | ||
2483 | u32 fragm_sz = pack_sz - INT_H_SIZE; | ||
2484 | u32 fragm_no = 1; | ||
2485 | u32 destaddr = msg_destnode(inmsg); | ||
2486 | |||
2487 | if (msg_short(inmsg)) | ||
2488 | destaddr = l_ptr->addr; | ||
2489 | |||
2490 | if (msg_routed(inmsg)) | ||
2491 | msg_set_prevnode(inmsg, tipc_own_addr); | ||
2492 | |||
2493 | /* Prepare reusable fragment header: */ | ||
2494 | |||
2495 | msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | ||
2496 | TIPC_OK, INT_H_SIZE, destaddr); | ||
2497 | msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg)); | ||
2498 | msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++)); | ||
2499 | msg_set_fragm_no(&fragm_hdr, fragm_no); | ||
2500 | l_ptr->stats.sent_fragmented++; | ||
2501 | |||
2502 | /* Chop up message: */ | ||
2503 | |||
2504 | while (rest > 0) { | ||
2505 | struct sk_buff *fragm; | ||
2506 | |||
2507 | if (rest <= fragm_sz) { | ||
2508 | fragm_sz = rest; | ||
2509 | msg_set_type(&fragm_hdr, LAST_FRAGMENT); | ||
2510 | } | ||
2511 | fragm = buf_acquire(fragm_sz + INT_H_SIZE); | ||
2512 | if (fragm == NULL) { | ||
2513 | warn("Memory squeeze; failed to fragment msg\n"); | ||
2514 | dsz = -ENOMEM; | ||
2515 | goto exit; | ||
2516 | } | ||
2517 | msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); | ||
2518 | memcpy(fragm->data, (unchar *)&fragm_hdr, INT_H_SIZE); | ||
2519 | memcpy(fragm->data + INT_H_SIZE, crs, fragm_sz); | ||
2520 | |||
2521 | /* Send queued messages first, if any: */ | ||
2522 | |||
2523 | l_ptr->stats.sent_fragments++; | ||
2524 | link_send_buf(l_ptr, fragm); | ||
2525 | if (!link_is_up(l_ptr)) | ||
2526 | return dsz; | ||
2527 | msg_set_fragm_no(&fragm_hdr, ++fragm_no); | ||
2528 | rest -= fragm_sz; | ||
2529 | crs += fragm_sz; | ||
2530 | msg_set_type(&fragm_hdr, FRAGMENT); | ||
2531 | } | ||
2532 | exit: | ||
2533 | buf_discard(buf); | ||
2534 | return dsz; | ||
2535 | } | ||
2536 | |||
2537 | /* | ||
2538 | * A pending message being re-assembled must store certain values | ||
2539 | * to handle subsequent fragments correctly. The following functions | ||
2540 | * help storing these values in unused, available fields in the | ||
2541 | * pending message. This makes dynamic memory allocation unecessary. | ||
2542 | */ | ||
2543 | |||
2544 | static inline u32 get_long_msg_seqno(struct sk_buff *buf) | ||
2545 | { | ||
2546 | return msg_seqno(buf_msg(buf)); | ||
2547 | } | ||
2548 | |||
2549 | static inline void set_long_msg_seqno(struct sk_buff *buf, u32 seqno) | ||
2550 | { | ||
2551 | msg_set_seqno(buf_msg(buf), seqno); | ||
2552 | } | ||
2553 | |||
2554 | static inline u32 get_fragm_size(struct sk_buff *buf) | ||
2555 | { | ||
2556 | return msg_ack(buf_msg(buf)); | ||
2557 | } | ||
2558 | |||
2559 | static inline void set_fragm_size(struct sk_buff *buf, u32 sz) | ||
2560 | { | ||
2561 | msg_set_ack(buf_msg(buf), sz); | ||
2562 | } | ||
2563 | |||
2564 | static inline u32 get_expected_frags(struct sk_buff *buf) | ||
2565 | { | ||
2566 | return msg_bcast_ack(buf_msg(buf)); | ||
2567 | } | ||
2568 | |||
2569 | static inline void set_expected_frags(struct sk_buff *buf, u32 exp) | ||
2570 | { | ||
2571 | msg_set_bcast_ack(buf_msg(buf), exp); | ||
2572 | } | ||
2573 | |||
2574 | static inline u32 get_timer_cnt(struct sk_buff *buf) | ||
2575 | { | ||
2576 | return msg_reroute_cnt(buf_msg(buf)); | ||
2577 | } | ||
2578 | |||
2579 | static inline void incr_timer_cnt(struct sk_buff *buf) | ||
2580 | { | ||
2581 | msg_incr_reroute_cnt(buf_msg(buf)); | ||
2582 | } | ||
2583 | |||
2584 | /* | ||
2585 | * link_recv_fragment(): Called with node lock on. Returns | ||
2586 | * the reassembled buffer if message is complete. | ||
2587 | */ | ||
2588 | int link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb, | ||
2589 | struct tipc_msg **m) | ||
2590 | { | ||
2591 | struct sk_buff *prev = 0; | ||
2592 | struct sk_buff *fbuf = *fb; | ||
2593 | struct tipc_msg *fragm = buf_msg(fbuf); | ||
2594 | struct sk_buff *pbuf = *pending; | ||
2595 | u32 long_msg_seq_no = msg_long_msgno(fragm); | ||
2596 | |||
2597 | *fb = 0; | ||
2598 | msg_dbg(fragm,"FRG<REC<"); | ||
2599 | |||
2600 | /* Is there an incomplete message waiting for this fragment? */ | ||
2601 | |||
2602 | while (pbuf && ((msg_seqno(buf_msg(pbuf)) != long_msg_seq_no) | ||
2603 | || (msg_orignode(fragm) != msg_orignode(buf_msg(pbuf))))) { | ||
2604 | prev = pbuf; | ||
2605 | pbuf = pbuf->next; | ||
2606 | } | ||
2607 | |||
2608 | if (!pbuf && (msg_type(fragm) == FIRST_FRAGMENT)) { | ||
2609 | struct tipc_msg *imsg = (struct tipc_msg *)msg_data(fragm); | ||
2610 | u32 msg_sz = msg_size(imsg); | ||
2611 | u32 fragm_sz = msg_data_sz(fragm); | ||
2612 | u32 exp_fragm_cnt = msg_sz/fragm_sz + !!(msg_sz % fragm_sz); | ||
2613 | u32 max = TIPC_MAX_USER_MSG_SIZE + LONG_H_SIZE; | ||
2614 | if (msg_type(imsg) == TIPC_MCAST_MSG) | ||
2615 | max = TIPC_MAX_USER_MSG_SIZE + MCAST_H_SIZE; | ||
2616 | if (msg_size(imsg) > max) { | ||
2617 | msg_dbg(fragm,"<REC<Oversized: "); | ||
2618 | buf_discard(fbuf); | ||
2619 | return 0; | ||
2620 | } | ||
2621 | pbuf = buf_acquire(msg_size(imsg)); | ||
2622 | if (pbuf != NULL) { | ||
2623 | pbuf->next = *pending; | ||
2624 | *pending = pbuf; | ||
2625 | memcpy(pbuf->data, (unchar *)imsg, msg_data_sz(fragm)); | ||
2626 | |||
2627 | /* Prepare buffer for subsequent fragments. */ | ||
2628 | |||
2629 | set_long_msg_seqno(pbuf, long_msg_seq_no); | ||
2630 | set_fragm_size(pbuf,fragm_sz); | ||
2631 | set_expected_frags(pbuf,exp_fragm_cnt - 1); | ||
2632 | } else { | ||
2633 | warn("Memory squeeze; got no defragmenting buffer\n"); | ||
2634 | } | ||
2635 | buf_discard(fbuf); | ||
2636 | return 0; | ||
2637 | } else if (pbuf && (msg_type(fragm) != FIRST_FRAGMENT)) { | ||
2638 | u32 dsz = msg_data_sz(fragm); | ||
2639 | u32 fsz = get_fragm_size(pbuf); | ||
2640 | u32 crs = ((msg_fragm_no(fragm) - 1) * fsz); | ||
2641 | u32 exp_frags = get_expected_frags(pbuf) - 1; | ||
2642 | memcpy(pbuf->data + crs, msg_data(fragm), dsz); | ||
2643 | buf_discard(fbuf); | ||
2644 | |||
2645 | /* Is message complete? */ | ||
2646 | |||
2647 | if (exp_frags == 0) { | ||
2648 | if (prev) | ||
2649 | prev->next = pbuf->next; | ||
2650 | else | ||
2651 | *pending = pbuf->next; | ||
2652 | msg_reset_reroute_cnt(buf_msg(pbuf)); | ||
2653 | *fb = pbuf; | ||
2654 | *m = buf_msg(pbuf); | ||
2655 | return 1; | ||
2656 | } | ||
2657 | set_expected_frags(pbuf,exp_frags); | ||
2658 | return 0; | ||
2659 | } | ||
2660 | dbg(" Discarding orphan fragment %x\n",fbuf); | ||
2661 | msg_dbg(fragm,"ORPHAN:"); | ||
2662 | dbg("Pending long buffers:\n"); | ||
2663 | dbg_print_buf_chain(*pending); | ||
2664 | buf_discard(fbuf); | ||
2665 | return 0; | ||
2666 | } | ||
2667 | |||
2668 | /** | ||
2669 | * link_check_defragm_bufs - flush stale incoming message fragments | ||
2670 | * @l_ptr: pointer to link | ||
2671 | */ | ||
2672 | |||
2673 | static void link_check_defragm_bufs(struct link *l_ptr) | ||
2674 | { | ||
2675 | struct sk_buff *prev = 0; | ||
2676 | struct sk_buff *next = 0; | ||
2677 | struct sk_buff *buf = l_ptr->defragm_buf; | ||
2678 | |||
2679 | if (!buf) | ||
2680 | return; | ||
2681 | if (!link_working_working(l_ptr)) | ||
2682 | return; | ||
2683 | while (buf) { | ||
2684 | u32 cnt = get_timer_cnt(buf); | ||
2685 | |||
2686 | next = buf->next; | ||
2687 | if (cnt < 4) { | ||
2688 | incr_timer_cnt(buf); | ||
2689 | prev = buf; | ||
2690 | } else { | ||
2691 | dbg(" Discarding incomplete long buffer\n"); | ||
2692 | msg_dbg(buf_msg(buf), "LONG:"); | ||
2693 | dbg_print_link(l_ptr, "curr:"); | ||
2694 | dbg("Pending long buffers:\n"); | ||
2695 | dbg_print_buf_chain(l_ptr->defragm_buf); | ||
2696 | if (prev) | ||
2697 | prev->next = buf->next; | ||
2698 | else | ||
2699 | l_ptr->defragm_buf = buf->next; | ||
2700 | buf_discard(buf); | ||
2701 | } | ||
2702 | buf = next; | ||
2703 | } | ||
2704 | } | ||
2705 | |||
2706 | |||
2707 | |||
2708 | static void link_set_supervision_props(struct link *l_ptr, u32 tolerance) | ||
2709 | { | ||
2710 | l_ptr->tolerance = tolerance; | ||
2711 | l_ptr->continuity_interval = | ||
2712 | ((tolerance / 4) > 500) ? 500 : tolerance / 4; | ||
2713 | l_ptr->abort_limit = tolerance / (l_ptr->continuity_interval / 4); | ||
2714 | } | ||
2715 | |||
2716 | |||
2717 | void link_set_queue_limits(struct link *l_ptr, u32 window) | ||
2718 | { | ||
2719 | /* Data messages from this node, inclusive FIRST_FRAGM */ | ||
2720 | l_ptr->queue_limit[DATA_LOW] = window; | ||
2721 | l_ptr->queue_limit[DATA_MEDIUM] = (window / 3) * 4; | ||
2722 | l_ptr->queue_limit[DATA_HIGH] = (window / 3) * 5; | ||
2723 | l_ptr->queue_limit[DATA_CRITICAL] = (window / 3) * 6; | ||
2724 | /* Transiting data messages,inclusive FIRST_FRAGM */ | ||
2725 | l_ptr->queue_limit[DATA_LOW + 4] = 300; | ||
2726 | l_ptr->queue_limit[DATA_MEDIUM + 4] = 600; | ||
2727 | l_ptr->queue_limit[DATA_HIGH + 4] = 900; | ||
2728 | l_ptr->queue_limit[DATA_CRITICAL + 4] = 1200; | ||
2729 | l_ptr->queue_limit[CONN_MANAGER] = 1200; | ||
2730 | l_ptr->queue_limit[ROUTE_DISTRIBUTOR] = 1200; | ||
2731 | l_ptr->queue_limit[CHANGEOVER_PROTOCOL] = 2500; | ||
2732 | l_ptr->queue_limit[NAME_DISTRIBUTOR] = 3000; | ||
2733 | /* FRAGMENT and LAST_FRAGMENT packets */ | ||
2734 | l_ptr->queue_limit[MSG_FRAGMENTER] = 4000; | ||
2735 | } | ||
2736 | |||
2737 | /** | ||
2738 | * link_find_link - locate link by name | ||
2739 | * @name - ptr to link name string | ||
2740 | * @node - ptr to area to be filled with ptr to associated node | ||
2741 | * | ||
2742 | * Caller must hold 'net_lock' to ensure node and bearer are not deleted; | ||
2743 | * this also prevents link deletion. | ||
2744 | * | ||
2745 | * Returns pointer to link (or 0 if invalid link name). | ||
2746 | */ | ||
2747 | |||
2748 | static struct link *link_find_link(const char *name, struct node **node) | ||
2749 | { | ||
2750 | struct link_name link_name_parts; | ||
2751 | struct bearer *b_ptr; | ||
2752 | struct link *l_ptr; | ||
2753 | |||
2754 | if (!link_name_validate(name, &link_name_parts)) | ||
2755 | return 0; | ||
2756 | |||
2757 | b_ptr = bearer_find_interface(link_name_parts.if_local); | ||
2758 | if (!b_ptr) | ||
2759 | return 0; | ||
2760 | |||
2761 | *node = node_find(link_name_parts.addr_peer); | ||
2762 | if (!*node) | ||
2763 | return 0; | ||
2764 | |||
2765 | l_ptr = (*node)->links[b_ptr->identity]; | ||
2766 | if (!l_ptr || strcmp(l_ptr->name, name)) | ||
2767 | return 0; | ||
2768 | |||
2769 | return l_ptr; | ||
2770 | } | ||
2771 | |||
2772 | struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, | ||
2773 | u16 cmd) | ||
2774 | { | ||
2775 | struct tipc_link_config *args; | ||
2776 | u32 new_value; | ||
2777 | struct link *l_ptr; | ||
2778 | struct node *node; | ||
2779 | int res; | ||
2780 | |||
2781 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_CONFIG)) | ||
2782 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
2783 | |||
2784 | args = (struct tipc_link_config *)TLV_DATA(req_tlv_area); | ||
2785 | new_value = ntohl(args->value); | ||
2786 | |||
2787 | if (!strcmp(args->name, bc_link_name)) { | ||
2788 | if ((cmd == TIPC_CMD_SET_LINK_WINDOW) && | ||
2789 | (bclink_set_queue_limits(new_value) == 0)) | ||
2790 | return cfg_reply_none(); | ||
2791 | return cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | ||
2792 | " (cannot change setting on broadcast link)"); | ||
2793 | } | ||
2794 | |||
2795 | read_lock_bh(&net_lock); | ||
2796 | l_ptr = link_find_link(args->name, &node); | ||
2797 | if (!l_ptr) { | ||
2798 | read_unlock_bh(&net_lock); | ||
2799 | return cfg_reply_error_string("link not found"); | ||
2800 | } | ||
2801 | |||
2802 | node_lock(node); | ||
2803 | res = -EINVAL; | ||
2804 | switch (cmd) { | ||
2805 | case TIPC_CMD_SET_LINK_TOL: | ||
2806 | if ((new_value >= TIPC_MIN_LINK_TOL) && | ||
2807 | (new_value <= TIPC_MAX_LINK_TOL)) { | ||
2808 | link_set_supervision_props(l_ptr, new_value); | ||
2809 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
2810 | 0, 0, new_value, 0, 0); | ||
2811 | res = TIPC_OK; | ||
2812 | } | ||
2813 | break; | ||
2814 | case TIPC_CMD_SET_LINK_PRI: | ||
2815 | if (new_value < TIPC_NUM_LINK_PRI) { | ||
2816 | l_ptr->priority = new_value; | ||
2817 | link_send_proto_msg(l_ptr, STATE_MSG, | ||
2818 | 0, 0, 0, new_value, 0); | ||
2819 | res = TIPC_OK; | ||
2820 | } | ||
2821 | break; | ||
2822 | case TIPC_CMD_SET_LINK_WINDOW: | ||
2823 | if ((new_value >= TIPC_MIN_LINK_WIN) && | ||
2824 | (new_value <= TIPC_MAX_LINK_WIN)) { | ||
2825 | link_set_queue_limits(l_ptr, new_value); | ||
2826 | res = TIPC_OK; | ||
2827 | } | ||
2828 | break; | ||
2829 | } | ||
2830 | node_unlock(node); | ||
2831 | |||
2832 | read_unlock_bh(&net_lock); | ||
2833 | if (res) | ||
2834 | return cfg_reply_error_string("cannot change link setting"); | ||
2835 | |||
2836 | return cfg_reply_none(); | ||
2837 | } | ||
2838 | |||
2839 | /** | ||
2840 | * link_reset_statistics - reset link statistics | ||
2841 | * @l_ptr: pointer to link | ||
2842 | */ | ||
2843 | |||
2844 | static void link_reset_statistics(struct link *l_ptr) | ||
2845 | { | ||
2846 | memset(&l_ptr->stats, 0, sizeof(l_ptr->stats)); | ||
2847 | l_ptr->stats.sent_info = l_ptr->next_out_no; | ||
2848 | l_ptr->stats.recv_info = l_ptr->next_in_no; | ||
2849 | } | ||
2850 | |||
2851 | struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space) | ||
2852 | { | ||
2853 | char *link_name; | ||
2854 | struct link *l_ptr; | ||
2855 | struct node *node; | ||
2856 | |||
2857 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) | ||
2858 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
2859 | |||
2860 | link_name = (char *)TLV_DATA(req_tlv_area); | ||
2861 | if (!strcmp(link_name, bc_link_name)) { | ||
2862 | if (bclink_reset_stats()) | ||
2863 | return cfg_reply_error_string("link not found"); | ||
2864 | return cfg_reply_none(); | ||
2865 | } | ||
2866 | |||
2867 | read_lock_bh(&net_lock); | ||
2868 | l_ptr = link_find_link(link_name, &node); | ||
2869 | if (!l_ptr) { | ||
2870 | read_unlock_bh(&net_lock); | ||
2871 | return cfg_reply_error_string("link not found"); | ||
2872 | } | ||
2873 | |||
2874 | node_lock(node); | ||
2875 | link_reset_statistics(l_ptr); | ||
2876 | node_unlock(node); | ||
2877 | read_unlock_bh(&net_lock); | ||
2878 | return cfg_reply_none(); | ||
2879 | } | ||
2880 | |||
2881 | /** | ||
2882 | * percent - convert count to a percentage of total (rounding up or down) | ||
2883 | */ | ||
2884 | |||
2885 | static u32 percent(u32 count, u32 total) | ||
2886 | { | ||
2887 | return (count * 100 + (total / 2)) / total; | ||
2888 | } | ||
2889 | |||
2890 | /** | ||
2891 | * link_stats - print link statistics | ||
2892 | * @name: link name | ||
2893 | * @buf: print buffer area | ||
2894 | * @buf_size: size of print buffer area | ||
2895 | * | ||
2896 | * Returns length of print buffer data string (or 0 if error) | ||
2897 | */ | ||
2898 | |||
2899 | static int link_stats(const char *name, char *buf, const u32 buf_size) | ||
2900 | { | ||
2901 | struct print_buf pb; | ||
2902 | struct link *l_ptr; | ||
2903 | struct node *node; | ||
2904 | char *status; | ||
2905 | u32 profile_total = 0; | ||
2906 | |||
2907 | if (!strcmp(name, bc_link_name)) | ||
2908 | return bclink_stats(buf, buf_size); | ||
2909 | |||
2910 | printbuf_init(&pb, buf, buf_size); | ||
2911 | |||
2912 | read_lock_bh(&net_lock); | ||
2913 | l_ptr = link_find_link(name, &node); | ||
2914 | if (!l_ptr) { | ||
2915 | read_unlock_bh(&net_lock); | ||
2916 | return 0; | ||
2917 | } | ||
2918 | node_lock(node); | ||
2919 | |||
2920 | if (link_is_active(l_ptr)) | ||
2921 | status = "ACTIVE"; | ||
2922 | else if (link_is_up(l_ptr)) | ||
2923 | status = "STANDBY"; | ||
2924 | else | ||
2925 | status = "DEFUNCT"; | ||
2926 | tipc_printf(&pb, "Link <%s>\n" | ||
2927 | " %s MTU:%u Priority:%u Tolerance:%u ms" | ||
2928 | " Window:%u packets\n", | ||
2929 | l_ptr->name, status, link_max_pkt(l_ptr), | ||
2930 | l_ptr->priority, l_ptr->tolerance, l_ptr->queue_limit[0]); | ||
2931 | tipc_printf(&pb, " RX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
2932 | l_ptr->next_in_no - l_ptr->stats.recv_info, | ||
2933 | l_ptr->stats.recv_fragments, | ||
2934 | l_ptr->stats.recv_fragmented, | ||
2935 | l_ptr->stats.recv_bundles, | ||
2936 | l_ptr->stats.recv_bundled); | ||
2937 | tipc_printf(&pb, " TX packets:%u fragments:%u/%u bundles:%u/%u\n", | ||
2938 | l_ptr->next_out_no - l_ptr->stats.sent_info, | ||
2939 | l_ptr->stats.sent_fragments, | ||
2940 | l_ptr->stats.sent_fragmented, | ||
2941 | l_ptr->stats.sent_bundles, | ||
2942 | l_ptr->stats.sent_bundled); | ||
2943 | profile_total = l_ptr->stats.msg_length_counts; | ||
2944 | if (!profile_total) | ||
2945 | profile_total = 1; | ||
2946 | tipc_printf(&pb, " TX profile sample:%u packets average:%u octets\n" | ||
2947 | " 0-64:%u%% -256:%u%% -1024:%u%% -4096:%u%% " | ||
2948 | "-16354:%u%% -32768:%u%% -66000:%u%%\n", | ||
2949 | l_ptr->stats.msg_length_counts, | ||
2950 | l_ptr->stats.msg_lengths_total / profile_total, | ||
2951 | percent(l_ptr->stats.msg_length_profile[0], profile_total), | ||
2952 | percent(l_ptr->stats.msg_length_profile[1], profile_total), | ||
2953 | percent(l_ptr->stats.msg_length_profile[2], profile_total), | ||
2954 | percent(l_ptr->stats.msg_length_profile[3], profile_total), | ||
2955 | percent(l_ptr->stats.msg_length_profile[4], profile_total), | ||
2956 | percent(l_ptr->stats.msg_length_profile[5], profile_total), | ||
2957 | percent(l_ptr->stats.msg_length_profile[6], profile_total)); | ||
2958 | tipc_printf(&pb, " RX states:%u probes:%u naks:%u defs:%u dups:%u\n", | ||
2959 | l_ptr->stats.recv_states, | ||
2960 | l_ptr->stats.recv_probes, | ||
2961 | l_ptr->stats.recv_nacks, | ||
2962 | l_ptr->stats.deferred_recv, | ||
2963 | l_ptr->stats.duplicates); | ||
2964 | tipc_printf(&pb, " TX states:%u probes:%u naks:%u acks:%u dups:%u\n", | ||
2965 | l_ptr->stats.sent_states, | ||
2966 | l_ptr->stats.sent_probes, | ||
2967 | l_ptr->stats.sent_nacks, | ||
2968 | l_ptr->stats.sent_acks, | ||
2969 | l_ptr->stats.retransmitted); | ||
2970 | tipc_printf(&pb, " Congestion bearer:%u link:%u Send queue max:%u avg:%u\n", | ||
2971 | l_ptr->stats.bearer_congs, | ||
2972 | l_ptr->stats.link_congs, | ||
2973 | l_ptr->stats.max_queue_sz, | ||
2974 | l_ptr->stats.queue_sz_counts | ||
2975 | ? (l_ptr->stats.accu_queue_sz / l_ptr->stats.queue_sz_counts) | ||
2976 | : 0); | ||
2977 | |||
2978 | node_unlock(node); | ||
2979 | read_unlock_bh(&net_lock); | ||
2980 | return printbuf_validate(&pb); | ||
2981 | } | ||
2982 | |||
2983 | #define MAX_LINK_STATS_INFO 2000 | ||
2984 | |||
2985 | struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space) | ||
2986 | { | ||
2987 | struct sk_buff *buf; | ||
2988 | struct tlv_desc *rep_tlv; | ||
2989 | int str_len; | ||
2990 | |||
2991 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) | ||
2992 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
2993 | |||
2994 | buf = cfg_reply_alloc(TLV_SPACE(MAX_LINK_STATS_INFO)); | ||
2995 | if (!buf) | ||
2996 | return NULL; | ||
2997 | |||
2998 | rep_tlv = (struct tlv_desc *)buf->data; | ||
2999 | |||
3000 | str_len = link_stats((char *)TLV_DATA(req_tlv_area), | ||
3001 | (char *)TLV_DATA(rep_tlv), MAX_LINK_STATS_INFO); | ||
3002 | if (!str_len) { | ||
3003 | buf_discard(buf); | ||
3004 | return cfg_reply_error_string("link not found"); | ||
3005 | } | ||
3006 | |||
3007 | skb_put(buf, TLV_SPACE(str_len)); | ||
3008 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | ||
3009 | |||
3010 | return buf; | ||
3011 | } | ||
3012 | |||
3013 | #if 0 | ||
3014 | int link_control(const char *name, u32 op, u32 val) | ||
3015 | { | ||
3016 | int res = -EINVAL; | ||
3017 | struct link *l_ptr; | ||
3018 | u32 bearer_id; | ||
3019 | struct node * node; | ||
3020 | u32 a; | ||
3021 | |||
3022 | a = link_name2addr(name, &bearer_id); | ||
3023 | read_lock_bh(&net_lock); | ||
3024 | node = node_find(a); | ||
3025 | if (node) { | ||
3026 | node_lock(node); | ||
3027 | l_ptr = node->links[bearer_id]; | ||
3028 | if (l_ptr) { | ||
3029 | if (op == TIPC_REMOVE_LINK) { | ||
3030 | struct bearer *b_ptr = l_ptr->b_ptr; | ||
3031 | spin_lock_bh(&b_ptr->publ.lock); | ||
3032 | link_delete(l_ptr); | ||
3033 | spin_unlock_bh(&b_ptr->publ.lock); | ||
3034 | } | ||
3035 | if (op == TIPC_CMD_BLOCK_LINK) { | ||
3036 | link_reset(l_ptr); | ||
3037 | l_ptr->blocked = 1; | ||
3038 | } | ||
3039 | if (op == TIPC_CMD_UNBLOCK_LINK) { | ||
3040 | l_ptr->blocked = 0; | ||
3041 | } | ||
3042 | res = TIPC_OK; | ||
3043 | } | ||
3044 | node_unlock(node); | ||
3045 | } | ||
3046 | read_unlock_bh(&net_lock); | ||
3047 | return res; | ||
3048 | } | ||
3049 | #endif | ||
3050 | |||
3051 | /** | ||
3052 | * link_get_max_pkt - get maximum packet size to use when sending to destination | ||
3053 | * @dest: network address of destination node | ||
3054 | * @selector: used to select from set of active links | ||
3055 | * | ||
3056 | * If no active link can be found, uses default maximum packet size. | ||
3057 | */ | ||
3058 | |||
3059 | u32 link_get_max_pkt(u32 dest, u32 selector) | ||
3060 | { | ||
3061 | struct node *n_ptr; | ||
3062 | struct link *l_ptr; | ||
3063 | u32 res = MAX_PKT_DEFAULT; | ||
3064 | |||
3065 | if (dest == tipc_own_addr) | ||
3066 | return MAX_MSG_SIZE; | ||
3067 | |||
3068 | read_lock_bh(&net_lock); | ||
3069 | n_ptr = node_select(dest, selector); | ||
3070 | if (n_ptr) { | ||
3071 | node_lock(n_ptr); | ||
3072 | l_ptr = n_ptr->active_links[selector & 1]; | ||
3073 | if (l_ptr) | ||
3074 | res = link_max_pkt(l_ptr); | ||
3075 | node_unlock(n_ptr); | ||
3076 | } | ||
3077 | read_unlock_bh(&net_lock); | ||
3078 | return res; | ||
3079 | } | ||
3080 | |||
3081 | #if 0 | ||
3082 | static void link_dump_rec_queue(struct link *l_ptr) | ||
3083 | { | ||
3084 | struct sk_buff *crs; | ||
3085 | |||
3086 | if (!l_ptr->oldest_deferred_in) { | ||
3087 | info("Reception queue empty\n"); | ||
3088 | return; | ||
3089 | } | ||
3090 | info("Contents of Reception queue:\n"); | ||
3091 | crs = l_ptr->oldest_deferred_in; | ||
3092 | while (crs) { | ||
3093 | if (crs->data == (void *)0x0000a3a3) { | ||
3094 | info("buffer %x invalid\n", crs); | ||
3095 | return; | ||
3096 | } | ||
3097 | msg_dbg(buf_msg(crs), "In rec queue: \n"); | ||
3098 | crs = crs->next; | ||
3099 | } | ||
3100 | } | ||
3101 | #endif | ||
3102 | |||
3103 | static void link_dump_send_queue(struct link *l_ptr) | ||
3104 | { | ||
3105 | if (l_ptr->next_out) { | ||
3106 | info("\nContents of unsent queue:\n"); | ||
3107 | dbg_print_buf_chain(l_ptr->next_out); | ||
3108 | } | ||
3109 | info("\nContents of send queue:\n"); | ||
3110 | if (l_ptr->first_out) { | ||
3111 | dbg_print_buf_chain(l_ptr->first_out); | ||
3112 | } | ||
3113 | info("Empty send queue\n"); | ||
3114 | } | ||
3115 | |||
3116 | static void link_print(struct link *l_ptr, struct print_buf *buf, | ||
3117 | const char *str) | ||
3118 | { | ||
3119 | tipc_printf(buf, str); | ||
3120 | if (link_reset_reset(l_ptr) || link_reset_unknown(l_ptr)) | ||
3121 | return; | ||
3122 | tipc_printf(buf, "Link %x<%s>:", | ||
3123 | l_ptr->addr, l_ptr->b_ptr->publ.name); | ||
3124 | tipc_printf(buf, ": NXO(%u):", mod(l_ptr->next_out_no)); | ||
3125 | tipc_printf(buf, "NXI(%u):", mod(l_ptr->next_in_no)); | ||
3126 | tipc_printf(buf, "SQUE"); | ||
3127 | if (l_ptr->first_out) { | ||
3128 | tipc_printf(buf, "[%u..", msg_seqno(buf_msg(l_ptr->first_out))); | ||
3129 | if (l_ptr->next_out) | ||
3130 | tipc_printf(buf, "%u..", | ||
3131 | msg_seqno(buf_msg(l_ptr->next_out))); | ||
3132 | tipc_printf(buf, "%u]", | ||
3133 | msg_seqno(buf_msg | ||
3134 | (l_ptr->last_out)), l_ptr->out_queue_size); | ||
3135 | if ((mod(msg_seqno(buf_msg(l_ptr->last_out)) - | ||
3136 | msg_seqno(buf_msg(l_ptr->first_out))) | ||
3137 | != (l_ptr->out_queue_size - 1)) | ||
3138 | || (l_ptr->last_out->next != 0)) { | ||
3139 | tipc_printf(buf, "\nSend queue inconsistency\n"); | ||
3140 | tipc_printf(buf, "first_out= %x ", l_ptr->first_out); | ||
3141 | tipc_printf(buf, "next_out= %x ", l_ptr->next_out); | ||
3142 | tipc_printf(buf, "last_out= %x ", l_ptr->last_out); | ||
3143 | link_dump_send_queue(l_ptr); | ||
3144 | } | ||
3145 | } else | ||
3146 | tipc_printf(buf, "[]"); | ||
3147 | tipc_printf(buf, "SQSIZ(%u)", l_ptr->out_queue_size); | ||
3148 | if (l_ptr->oldest_deferred_in) { | ||
3149 | u32 o = msg_seqno(buf_msg(l_ptr->oldest_deferred_in)); | ||
3150 | u32 n = msg_seqno(buf_msg(l_ptr->newest_deferred_in)); | ||
3151 | tipc_printf(buf, ":RQUE[%u..%u]", o, n); | ||
3152 | if (l_ptr->deferred_inqueue_sz != mod((n + 1) - o)) { | ||
3153 | tipc_printf(buf, ":RQSIZ(%u)", | ||
3154 | l_ptr->deferred_inqueue_sz); | ||
3155 | } | ||
3156 | } | ||
3157 | if (link_working_unknown(l_ptr)) | ||
3158 | tipc_printf(buf, ":WU"); | ||
3159 | if (link_reset_reset(l_ptr)) | ||
3160 | tipc_printf(buf, ":RR"); | ||
3161 | if (link_reset_unknown(l_ptr)) | ||
3162 | tipc_printf(buf, ":RU"); | ||
3163 | if (link_working_working(l_ptr)) | ||
3164 | tipc_printf(buf, ":WW"); | ||
3165 | tipc_printf(buf, "\n"); | ||
3166 | } | ||
3167 | |||
diff --git a/net/tipc/link.h b/net/tipc/link.h new file mode 100644 index 000000000000..c2553f073757 --- /dev/null +++ b/net/tipc/link.h | |||
@@ -0,0 +1,296 @@ | |||
1 | /* | ||
2 | * net/tipc/link.h: Include file for TIPC link code | ||
3 | * | ||
4 | * Copyright (c) 1995-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_LINK_H | ||
38 | #define _TIPC_LINK_H | ||
39 | |||
40 | #include "dbg.h" | ||
41 | #include "msg.h" | ||
42 | #include "bearer.h" | ||
43 | #include "node.h" | ||
44 | |||
45 | #define PUSH_FAILED 1 | ||
46 | #define PUSH_FINISHED 2 | ||
47 | |||
48 | /* | ||
49 | * Link states | ||
50 | */ | ||
51 | |||
52 | #define WORKING_WORKING 560810u | ||
53 | #define WORKING_UNKNOWN 560811u | ||
54 | #define RESET_UNKNOWN 560812u | ||
55 | #define RESET_RESET 560813u | ||
56 | |||
57 | /* | ||
58 | * Starting value for maximum packet size negotiation on unicast links | ||
59 | * (unless bearer MTU is less) | ||
60 | */ | ||
61 | |||
62 | #define MAX_PKT_DEFAULT 1500 | ||
63 | |||
64 | /** | ||
65 | * struct link - TIPC link data structure | ||
66 | * @addr: network address of link's peer node | ||
67 | * @name: link name character string | ||
68 | * @media_addr: media address to use when sending messages over link | ||
69 | * @timer: link timer | ||
70 | * @owner: pointer to peer node | ||
71 | * @link_list: adjacent links in bearer's list of links | ||
72 | * @started: indicates if link has been started | ||
73 | * @checkpoint: reference point for triggering link continuity checking | ||
74 | * @peer_session: link session # being used by peer end of link | ||
75 | * @peer_bearer_id: bearer id used by link's peer endpoint | ||
76 | * @b_ptr: pointer to bearer used by link | ||
77 | * @tolerance: minimum link continuity loss needed to reset link [in ms] | ||
78 | * @continuity_interval: link continuity testing interval [in ms] | ||
79 | * @abort_limit: # of unacknowledged continuity probes needed to reset link | ||
80 | * @state: current state of link FSM | ||
81 | * @blocked: indicates if link has been administratively blocked | ||
82 | * @fsm_msg_cnt: # of protocol messages link FSM has sent in current state | ||
83 | * @proto_msg: template for control messages generated by link | ||
84 | * @pmsg: convenience pointer to "proto_msg" field | ||
85 | * @priority: current link priority | ||
86 | * @queue_limit: outbound message queue congestion thresholds (indexed by user) | ||
87 | * @exp_msg_count: # of tunnelled messages expected during link changeover | ||
88 | * @reset_checkpoint: seq # of last acknowledged message at time of link reset | ||
89 | * @max_pkt: current maximum packet size for this link | ||
90 | * @max_pkt_target: desired maximum packet size for this link | ||
91 | * @max_pkt_probes: # of probes based on current (max_pkt, max_pkt_target) | ||
92 | * @out_queue_size: # of messages in outbound message queue | ||
93 | * @first_out: ptr to first outbound message in queue | ||
94 | * @last_out: ptr to last outbound message in queue | ||
95 | * @next_out_no: next sequence number to use for outbound messages | ||
96 | * @last_retransmitted: sequence number of most recently retransmitted message | ||
97 | * @stale_count: # of identical retransmit requests made by peer | ||
98 | * @next_in_no: next sequence number to expect for inbound messages | ||
99 | * @deferred_inqueue_sz: # of messages in inbound message queue | ||
100 | * @oldest_deferred_in: ptr to first inbound message in queue | ||
101 | * @newest_deferred_in: ptr to last inbound message in queue | ||
102 | * @unacked_window: # of inbound messages rx'd without ack'ing back to peer | ||
103 | * @proto_msg_queue: ptr to (single) outbound control message | ||
104 | * @retransm_queue_size: number of messages to retransmit | ||
105 | * @retransm_queue_head: sequence number of first message to retransmit | ||
106 | * @next_out: ptr to first unsent outbound message in queue | ||
107 | * @waiting_ports: linked list of ports waiting for link congestion to abate | ||
108 | * @long_msg_seq_no: next identifier to use for outbound fragmented messages | ||
109 | * @defragm_buf: list of partially reassembled inbound message fragments | ||
110 | * @stats: collects statistics regarding link activity | ||
111 | * @print_buf: print buffer used to log link activity | ||
112 | */ | ||
113 | |||
114 | struct link { | ||
115 | u32 addr; | ||
116 | char name[TIPC_MAX_LINK_NAME]; | ||
117 | struct tipc_media_addr media_addr; | ||
118 | struct timer_list timer; | ||
119 | struct node *owner; | ||
120 | struct list_head link_list; | ||
121 | |||
122 | /* Management and link supervision data */ | ||
123 | int started; | ||
124 | u32 checkpoint; | ||
125 | u32 peer_session; | ||
126 | u32 peer_bearer_id; | ||
127 | struct bearer *b_ptr; | ||
128 | u32 tolerance; | ||
129 | u32 continuity_interval; | ||
130 | u32 abort_limit; | ||
131 | int state; | ||
132 | int blocked; | ||
133 | u32 fsm_msg_cnt; | ||
134 | struct { | ||
135 | unchar hdr[INT_H_SIZE]; | ||
136 | unchar body[TIPC_MAX_IF_NAME]; | ||
137 | } proto_msg; | ||
138 | struct tipc_msg *pmsg; | ||
139 | u32 priority; | ||
140 | u32 queue_limit[15]; /* queue_limit[0]==window limit */ | ||
141 | |||
142 | /* Changeover */ | ||
143 | u32 exp_msg_count; | ||
144 | u32 reset_checkpoint; | ||
145 | |||
146 | /* Max packet negotiation */ | ||
147 | u32 max_pkt; | ||
148 | u32 max_pkt_target; | ||
149 | u32 max_pkt_probes; | ||
150 | |||
151 | /* Sending */ | ||
152 | u32 out_queue_size; | ||
153 | struct sk_buff *first_out; | ||
154 | struct sk_buff *last_out; | ||
155 | u32 next_out_no; | ||
156 | u32 last_retransmitted; | ||
157 | u32 stale_count; | ||
158 | |||
159 | /* Reception */ | ||
160 | u32 next_in_no; | ||
161 | u32 deferred_inqueue_sz; | ||
162 | struct sk_buff *oldest_deferred_in; | ||
163 | struct sk_buff *newest_deferred_in; | ||
164 | u32 unacked_window; | ||
165 | |||
166 | /* Congestion handling */ | ||
167 | struct sk_buff *proto_msg_queue; | ||
168 | u32 retransm_queue_size; | ||
169 | u32 retransm_queue_head; | ||
170 | struct sk_buff *next_out; | ||
171 | struct list_head waiting_ports; | ||
172 | |||
173 | /* Fragmentation/defragmentation */ | ||
174 | u32 long_msg_seq_no; | ||
175 | struct sk_buff *defragm_buf; | ||
176 | |||
177 | /* Statistics */ | ||
178 | struct { | ||
179 | u32 sent_info; /* used in counting # sent packets */ | ||
180 | u32 recv_info; /* used in counting # recv'd packets */ | ||
181 | u32 sent_states; | ||
182 | u32 recv_states; | ||
183 | u32 sent_probes; | ||
184 | u32 recv_probes; | ||
185 | u32 sent_nacks; | ||
186 | u32 recv_nacks; | ||
187 | u32 sent_acks; | ||
188 | u32 sent_bundled; | ||
189 | u32 sent_bundles; | ||
190 | u32 recv_bundled; | ||
191 | u32 recv_bundles; | ||
192 | u32 retransmitted; | ||
193 | u32 sent_fragmented; | ||
194 | u32 sent_fragments; | ||
195 | u32 recv_fragmented; | ||
196 | u32 recv_fragments; | ||
197 | u32 link_congs; /* # port sends blocked by congestion */ | ||
198 | u32 bearer_congs; | ||
199 | u32 deferred_recv; | ||
200 | u32 duplicates; | ||
201 | |||
202 | /* for statistical profiling of send queue size */ | ||
203 | |||
204 | u32 max_queue_sz; | ||
205 | u32 accu_queue_sz; | ||
206 | u32 queue_sz_counts; | ||
207 | |||
208 | /* for statistical profiling of message lengths */ | ||
209 | |||
210 | u32 msg_length_counts; | ||
211 | u32 msg_lengths_total; | ||
212 | u32 msg_length_profile[7]; | ||
213 | #if 0 | ||
214 | u32 sent_tunneled; | ||
215 | u32 recv_tunneled; | ||
216 | #endif | ||
217 | } stats; | ||
218 | |||
219 | struct print_buf print_buf; | ||
220 | }; | ||
221 | |||
222 | struct port; | ||
223 | |||
224 | struct link *link_create(struct bearer *b_ptr, const u32 peer, | ||
225 | const struct tipc_media_addr *media_addr); | ||
226 | void link_delete(struct link *l_ptr); | ||
227 | void link_changeover(struct link *l_ptr); | ||
228 | void link_send_duplicate(struct link *l_ptr, struct link *dest); | ||
229 | void link_reset_fragments(struct link *l_ptr); | ||
230 | int link_is_up(struct link *l_ptr); | ||
231 | int link_is_active(struct link *l_ptr); | ||
232 | void link_start(struct link *l_ptr); | ||
233 | u32 link_push_packet(struct link *l_ptr); | ||
234 | void link_stop(struct link *l_ptr); | ||
235 | struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd); | ||
236 | struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space); | ||
237 | struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space); | ||
238 | void link_reset(struct link *l_ptr); | ||
239 | int link_send(struct sk_buff *buf, u32 dest, u32 selector); | ||
240 | int link_send_buf(struct link *l_ptr, struct sk_buff *buf); | ||
241 | u32 link_get_max_pkt(u32 dest,u32 selector); | ||
242 | int link_send_sections_fast(struct port* sender, | ||
243 | struct iovec const *msg_sect, | ||
244 | const u32 num_sect, | ||
245 | u32 destnode); | ||
246 | |||
247 | int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf); | ||
248 | void link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr, | ||
249 | struct tipc_msg *msg, u32 selector); | ||
250 | void link_recv_bundle(struct sk_buff *buf); | ||
251 | int link_recv_fragment(struct sk_buff **pending, | ||
252 | struct sk_buff **fb, | ||
253 | struct tipc_msg **msg); | ||
254 | void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int prob, u32 gap, | ||
255 | u32 tolerance, u32 priority, u32 acked_mtu); | ||
256 | void link_push_queue(struct link *l_ptr); | ||
257 | u32 link_defer_pkt(struct sk_buff **head, struct sk_buff **tail, | ||
258 | struct sk_buff *buf); | ||
259 | void link_wakeup_ports(struct link *l_ptr, int all); | ||
260 | void link_set_queue_limits(struct link *l_ptr, u32 window); | ||
261 | void link_retransmit(struct link *l_ptr, struct sk_buff *start, u32 retransmits); | ||
262 | |||
263 | /* | ||
264 | * Link sequence number manipulation routines (uses modulo 2**16 arithmetic) | ||
265 | */ | ||
266 | |||
267 | static inline u32 mod(u32 x) | ||
268 | { | ||
269 | return x & 0xffffu; | ||
270 | } | ||
271 | |||
272 | static inline int between(u32 lower, u32 upper, u32 n) | ||
273 | { | ||
274 | if ((lower < n) && (n < upper)) | ||
275 | return 1; | ||
276 | if ((upper < lower) && ((n > lower) || (n < upper))) | ||
277 | return 1; | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static inline int less_eq(u32 left, u32 right) | ||
282 | { | ||
283 | return (mod(right - left) < 32768u); | ||
284 | } | ||
285 | |||
286 | static inline int less(u32 left, u32 right) | ||
287 | { | ||
288 | return (less_eq(left, right) && (mod(right) != mod(left))); | ||
289 | } | ||
290 | |||
291 | static inline u32 lesser(u32 left, u32 right) | ||
292 | { | ||
293 | return less_eq(left, right) ? left : right; | ||
294 | } | ||
295 | |||
296 | #endif | ||
diff --git a/net/tipc/msg.c b/net/tipc/msg.c new file mode 100644 index 000000000000..03dbc55cb04c --- /dev/null +++ b/net/tipc/msg.c | |||
@@ -0,0 +1,334 @@ | |||
1 | /* | ||
2 | * net/tipc/msg.c: TIPC message header routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "addr.h" | ||
39 | #include "dbg.h" | ||
40 | #include "msg.h" | ||
41 | #include "bearer.h" | ||
42 | |||
43 | |||
44 | void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) | ||
45 | { | ||
46 | memcpy(&((int *)m)[5], a, sizeof(*a)); | ||
47 | } | ||
48 | |||
49 | void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) | ||
50 | { | ||
51 | memcpy(a, &((int*)m)[5], sizeof(*a)); | ||
52 | } | ||
53 | |||
54 | |||
55 | void msg_print(struct print_buf *buf, struct tipc_msg *msg, const char *str) | ||
56 | { | ||
57 | u32 usr = msg_user(msg); | ||
58 | tipc_printf(buf, str); | ||
59 | |||
60 | switch (usr) { | ||
61 | case MSG_BUNDLER: | ||
62 | tipc_printf(buf, "BNDL::"); | ||
63 | tipc_printf(buf, "MSGS(%u):", msg_msgcnt(msg)); | ||
64 | break; | ||
65 | case BCAST_PROTOCOL: | ||
66 | tipc_printf(buf, "BCASTP::"); | ||
67 | break; | ||
68 | case MSG_FRAGMENTER: | ||
69 | tipc_printf(buf, "FRAGM::"); | ||
70 | switch (msg_type(msg)) { | ||
71 | case FIRST_FRAGMENT: | ||
72 | tipc_printf(buf, "FIRST:"); | ||
73 | break; | ||
74 | case FRAGMENT: | ||
75 | tipc_printf(buf, "BODY:"); | ||
76 | break; | ||
77 | case LAST_FRAGMENT: | ||
78 | tipc_printf(buf, "LAST:"); | ||
79 | break; | ||
80 | default: | ||
81 | tipc_printf(buf, "UNKNOWN:%x",msg_type(msg)); | ||
82 | |||
83 | } | ||
84 | tipc_printf(buf, "NO(%u/%u):",msg_long_msgno(msg), | ||
85 | msg_fragm_no(msg)); | ||
86 | break; | ||
87 | case DATA_LOW: | ||
88 | case DATA_MEDIUM: | ||
89 | case DATA_HIGH: | ||
90 | case DATA_CRITICAL: | ||
91 | tipc_printf(buf, "DAT%u:", msg_user(msg)); | ||
92 | if (msg_short(msg)) { | ||
93 | tipc_printf(buf, "CON:"); | ||
94 | break; | ||
95 | } | ||
96 | switch (msg_type(msg)) { | ||
97 | case TIPC_CONN_MSG: | ||
98 | tipc_printf(buf, "CON:"); | ||
99 | break; | ||
100 | case TIPC_MCAST_MSG: | ||
101 | tipc_printf(buf, "MCST:"); | ||
102 | break; | ||
103 | case TIPC_NAMED_MSG: | ||
104 | tipc_printf(buf, "NAM:"); | ||
105 | break; | ||
106 | case TIPC_DIRECT_MSG: | ||
107 | tipc_printf(buf, "DIR:"); | ||
108 | break; | ||
109 | default: | ||
110 | tipc_printf(buf, "UNKNOWN TYPE %u",msg_type(msg)); | ||
111 | } | ||
112 | if (msg_routed(msg) && !msg_non_seq(msg)) | ||
113 | tipc_printf(buf, "ROUT:"); | ||
114 | if (msg_reroute_cnt(msg)) | ||
115 | tipc_printf(buf, "REROUTED(%u):", | ||
116 | msg_reroute_cnt(msg)); | ||
117 | break; | ||
118 | case NAME_DISTRIBUTOR: | ||
119 | tipc_printf(buf, "NMD::"); | ||
120 | switch (msg_type(msg)) { | ||
121 | case PUBLICATION: | ||
122 | tipc_printf(buf, "PUBL(%u):", (msg_size(msg) - msg_hdr_sz(msg)) / 20); /* Items */ | ||
123 | break; | ||
124 | case WITHDRAWAL: | ||
125 | tipc_printf(buf, "WDRW:"); | ||
126 | break; | ||
127 | default: | ||
128 | tipc_printf(buf, "UNKNOWN:%x",msg_type(msg)); | ||
129 | } | ||
130 | if (msg_routed(msg)) | ||
131 | tipc_printf(buf, "ROUT:"); | ||
132 | if (msg_reroute_cnt(msg)) | ||
133 | tipc_printf(buf, "REROUTED(%u):", | ||
134 | msg_reroute_cnt(msg)); | ||
135 | break; | ||
136 | case CONN_MANAGER: | ||
137 | tipc_printf(buf, "CONN_MNG:"); | ||
138 | switch (msg_type(msg)) { | ||
139 | case CONN_PROBE: | ||
140 | tipc_printf(buf, "PROBE:"); | ||
141 | break; | ||
142 | case CONN_PROBE_REPLY: | ||
143 | tipc_printf(buf, "PROBE_REPLY:"); | ||
144 | break; | ||
145 | case CONN_ACK: | ||
146 | tipc_printf(buf, "CONN_ACK:"); | ||
147 | tipc_printf(buf, "ACK(%u):",msg_msgcnt(msg)); | ||
148 | break; | ||
149 | default: | ||
150 | tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); | ||
151 | } | ||
152 | if (msg_routed(msg)) | ||
153 | tipc_printf(buf, "ROUT:"); | ||
154 | if (msg_reroute_cnt(msg)) | ||
155 | tipc_printf(buf, "REROUTED(%u):",msg_reroute_cnt(msg)); | ||
156 | break; | ||
157 | case LINK_PROTOCOL: | ||
158 | tipc_printf(buf, "PROT:TIM(%u):",msg_timestamp(msg)); | ||
159 | switch (msg_type(msg)) { | ||
160 | case STATE_MSG: | ||
161 | tipc_printf(buf, "STATE:"); | ||
162 | tipc_printf(buf, "%s:",msg_probe(msg) ? "PRB" :""); | ||
163 | tipc_printf(buf, "NXS(%u):",msg_next_sent(msg)); | ||
164 | tipc_printf(buf, "GAP(%u):",msg_seq_gap(msg)); | ||
165 | tipc_printf(buf, "LSTBC(%u):",msg_last_bcast(msg)); | ||
166 | break; | ||
167 | case RESET_MSG: | ||
168 | tipc_printf(buf, "RESET:"); | ||
169 | if (msg_size(msg) != msg_hdr_sz(msg)) | ||
170 | tipc_printf(buf, "BEAR:%s:",msg_data(msg)); | ||
171 | break; | ||
172 | case ACTIVATE_MSG: | ||
173 | tipc_printf(buf, "ACTIVATE:"); | ||
174 | break; | ||
175 | default: | ||
176 | tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); | ||
177 | } | ||
178 | tipc_printf(buf, "PLANE(%c):",msg_net_plane(msg)); | ||
179 | tipc_printf(buf, "SESS(%u):",msg_session(msg)); | ||
180 | break; | ||
181 | case CHANGEOVER_PROTOCOL: | ||
182 | tipc_printf(buf, "TUNL:"); | ||
183 | switch (msg_type(msg)) { | ||
184 | case DUPLICATE_MSG: | ||
185 | tipc_printf(buf, "DUPL:"); | ||
186 | break; | ||
187 | case ORIGINAL_MSG: | ||
188 | tipc_printf(buf, "ORIG:"); | ||
189 | tipc_printf(buf, "EXP(%u)",msg_msgcnt(msg)); | ||
190 | break; | ||
191 | default: | ||
192 | tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); | ||
193 | } | ||
194 | break; | ||
195 | case ROUTE_DISTRIBUTOR: | ||
196 | tipc_printf(buf, "ROUTING_MNG:"); | ||
197 | switch (msg_type(msg)) { | ||
198 | case EXT_ROUTING_TABLE: | ||
199 | tipc_printf(buf, "EXT_TBL:"); | ||
200 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); | ||
201 | break; | ||
202 | case LOCAL_ROUTING_TABLE: | ||
203 | tipc_printf(buf, "LOCAL_TBL:"); | ||
204 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); | ||
205 | break; | ||
206 | case SLAVE_ROUTING_TABLE: | ||
207 | tipc_printf(buf, "DP_TBL:"); | ||
208 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); | ||
209 | break; | ||
210 | case ROUTE_ADDITION: | ||
211 | tipc_printf(buf, "ADD:"); | ||
212 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); | ||
213 | break; | ||
214 | case ROUTE_REMOVAL: | ||
215 | tipc_printf(buf, "REMOVE:"); | ||
216 | tipc_printf(buf, "TO:%x:",msg_remote_node(msg)); | ||
217 | break; | ||
218 | default: | ||
219 | tipc_printf(buf, "UNKNOWN TYPE:%x",msg_type(msg)); | ||
220 | } | ||
221 | break; | ||
222 | case LINK_CONFIG: | ||
223 | tipc_printf(buf, "CFG:"); | ||
224 | switch (msg_type(msg)) { | ||
225 | case DSC_REQ_MSG: | ||
226 | tipc_printf(buf, "DSC_REQ:"); | ||
227 | break; | ||
228 | case DSC_RESP_MSG: | ||
229 | tipc_printf(buf, "DSC_RESP:"); | ||
230 | break; | ||
231 | default: | ||
232 | tipc_printf(buf, "UNKNOWN TYPE:%x:",msg_type(msg)); | ||
233 | break; | ||
234 | } | ||
235 | break; | ||
236 | default: | ||
237 | tipc_printf(buf, "UNKNOWN USER:"); | ||
238 | } | ||
239 | |||
240 | switch (usr) { | ||
241 | case CONN_MANAGER: | ||
242 | case NAME_DISTRIBUTOR: | ||
243 | case DATA_LOW: | ||
244 | case DATA_MEDIUM: | ||
245 | case DATA_HIGH: | ||
246 | case DATA_CRITICAL: | ||
247 | if (msg_short(msg)) | ||
248 | break; /* No error */ | ||
249 | switch (msg_errcode(msg)) { | ||
250 | case TIPC_OK: | ||
251 | break; | ||
252 | case TIPC_ERR_NO_NAME: | ||
253 | tipc_printf(buf, "NO_NAME:"); | ||
254 | break; | ||
255 | case TIPC_ERR_NO_PORT: | ||
256 | tipc_printf(buf, "NO_PORT:"); | ||
257 | break; | ||
258 | case TIPC_ERR_NO_NODE: | ||
259 | tipc_printf(buf, "NO_PROC:"); | ||
260 | break; | ||
261 | case TIPC_ERR_OVERLOAD: | ||
262 | tipc_printf(buf, "OVERLOAD:"); | ||
263 | break; | ||
264 | case TIPC_CONN_SHUTDOWN: | ||
265 | tipc_printf(buf, "SHUTDOWN:"); | ||
266 | break; | ||
267 | default: | ||
268 | tipc_printf(buf, "UNKNOWN ERROR(%x):", | ||
269 | msg_errcode(msg)); | ||
270 | } | ||
271 | default:{} | ||
272 | } | ||
273 | |||
274 | tipc_printf(buf, "HZ(%u):", msg_hdr_sz(msg)); | ||
275 | tipc_printf(buf, "SZ(%u):", msg_size(msg)); | ||
276 | tipc_printf(buf, "SQNO(%u):", msg_seqno(msg)); | ||
277 | |||
278 | if (msg_non_seq(msg)) | ||
279 | tipc_printf(buf, "NOSEQ:"); | ||
280 | else { | ||
281 | tipc_printf(buf, "ACK(%u):", msg_ack(msg)); | ||
282 | } | ||
283 | tipc_printf(buf, "BACK(%u):", msg_bcast_ack(msg)); | ||
284 | tipc_printf(buf, "PRND(%x)", msg_prevnode(msg)); | ||
285 | |||
286 | if (msg_isdata(msg)) { | ||
287 | if (msg_named(msg)) { | ||
288 | tipc_printf(buf, "NTYP(%u):", msg_nametype(msg)); | ||
289 | tipc_printf(buf, "NINST(%u)", msg_nameinst(msg)); | ||
290 | } | ||
291 | } | ||
292 | |||
293 | if ((usr != LINK_PROTOCOL) && (usr != LINK_CONFIG) && | ||
294 | (usr != MSG_BUNDLER)) { | ||
295 | if (!msg_short(msg)) { | ||
296 | tipc_printf(buf, ":ORIG(%x:%u):", | ||
297 | msg_orignode(msg), msg_origport(msg)); | ||
298 | tipc_printf(buf, ":DEST(%x:%u):", | ||
299 | msg_destnode(msg), msg_destport(msg)); | ||
300 | } else { | ||
301 | tipc_printf(buf, ":OPRT(%u):", msg_origport(msg)); | ||
302 | tipc_printf(buf, ":DPRT(%u):", msg_destport(msg)); | ||
303 | } | ||
304 | if (msg_routed(msg) && !msg_non_seq(msg)) | ||
305 | tipc_printf(buf, ":TSEQN(%u)", msg_transp_seqno(msg)); | ||
306 | } | ||
307 | if (msg_user(msg) == NAME_DISTRIBUTOR) { | ||
308 | tipc_printf(buf, ":ONOD(%x):", msg_orignode(msg)); | ||
309 | tipc_printf(buf, ":DNOD(%x):", msg_destnode(msg)); | ||
310 | if (msg_routed(msg)) { | ||
311 | tipc_printf(buf, ":CSEQN(%u)", msg_transp_seqno(msg)); | ||
312 | } | ||
313 | } | ||
314 | |||
315 | if (msg_user(msg) == LINK_CONFIG) { | ||
316 | u32* raw = (u32*)msg; | ||
317 | struct tipc_media_addr* orig = (struct tipc_media_addr*)&raw[5]; | ||
318 | tipc_printf(buf, ":REQL(%u):", msg_req_links(msg)); | ||
319 | tipc_printf(buf, ":DDOM(%x):", msg_dest_domain(msg)); | ||
320 | tipc_printf(buf, ":NETID(%u):", msg_bc_netid(msg)); | ||
321 | media_addr_printf(buf, orig); | ||
322 | } | ||
323 | if (msg_user(msg) == BCAST_PROTOCOL) { | ||
324 | tipc_printf(buf, "BCNACK:AFTER(%u):", msg_bcgap_after(msg)); | ||
325 | tipc_printf(buf, "TO(%u):", msg_bcgap_to(msg)); | ||
326 | } | ||
327 | tipc_printf(buf, "\n"); | ||
328 | if ((usr == CHANGEOVER_PROTOCOL) && (msg_msgcnt(msg))) { | ||
329 | msg_print(buf,msg_get_wrapped(msg)," /"); | ||
330 | } | ||
331 | if ((usr == MSG_FRAGMENTER) && (msg_type(msg) == FIRST_FRAGMENT)) { | ||
332 | msg_print(buf,msg_get_wrapped(msg)," /"); | ||
333 | } | ||
334 | } | ||
diff --git a/net/tipc/msg.h b/net/tipc/msg.h new file mode 100644 index 000000000000..662c81862a0c --- /dev/null +++ b/net/tipc/msg.h | |||
@@ -0,0 +1,818 @@ | |||
1 | /* | ||
2 | * net/tipc/msg.h: Include file for TIPC message header routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_MSG_H | ||
38 | #define _TIPC_MSG_H | ||
39 | |||
40 | #include <net/tipc/tipc_msg.h> | ||
41 | |||
42 | #define TIPC_VERSION 2 | ||
43 | #define DATA_LOW TIPC_LOW_IMPORTANCE | ||
44 | #define DATA_MEDIUM TIPC_MEDIUM_IMPORTANCE | ||
45 | #define DATA_HIGH TIPC_HIGH_IMPORTANCE | ||
46 | #define DATA_CRITICAL TIPC_CRITICAL_IMPORTANCE | ||
47 | #define SHORT_H_SIZE 24 /* Connected,in cluster */ | ||
48 | #define DIR_MSG_H_SIZE 32 /* Directly addressed messages */ | ||
49 | #define CONN_MSG_H_SIZE 36 /* Routed connected msgs*/ | ||
50 | #define LONG_H_SIZE 40 /* Named Messages */ | ||
51 | #define MCAST_H_SIZE 44 /* Multicast messages */ | ||
52 | #define MAX_H_SIZE 60 /* Inclusive full options */ | ||
53 | #define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE) | ||
54 | #define LINK_CONFIG 13 | ||
55 | |||
56 | |||
57 | /* | ||
58 | TIPC user data message header format, version 2 | ||
59 | |||
60 | - Fundamental definitions available to privileged TIPC users | ||
61 | are located in tipc_msg.h. | ||
62 | - Remaining definitions available to TIPC internal users appear below. | ||
63 | */ | ||
64 | |||
65 | |||
66 | static inline void msg_set_word(struct tipc_msg *m, u32 w, u32 val) | ||
67 | { | ||
68 | m->hdr[w] = htonl(val); | ||
69 | } | ||
70 | |||
71 | static inline void msg_set_bits(struct tipc_msg *m, u32 w, | ||
72 | u32 pos, u32 mask, u32 val) | ||
73 | { | ||
74 | u32 word = msg_word(m,w) & ~(mask << pos); | ||
75 | msg_set_word(m, w, (word |= (val << pos))); | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * Word 0 | ||
80 | */ | ||
81 | |||
82 | static inline u32 msg_version(struct tipc_msg *m) | ||
83 | { | ||
84 | return msg_bits(m, 0, 29, 7); | ||
85 | } | ||
86 | |||
87 | static inline void msg_set_version(struct tipc_msg *m) | ||
88 | { | ||
89 | msg_set_bits(m, 0, 29, 0xf, TIPC_VERSION); | ||
90 | } | ||
91 | |||
92 | static inline u32 msg_user(struct tipc_msg *m) | ||
93 | { | ||
94 | return msg_bits(m, 0, 25, 0xf); | ||
95 | } | ||
96 | |||
97 | static inline u32 msg_isdata(struct tipc_msg *m) | ||
98 | { | ||
99 | return (msg_user(m) <= DATA_CRITICAL); | ||
100 | } | ||
101 | |||
102 | static inline void msg_set_user(struct tipc_msg *m, u32 n) | ||
103 | { | ||
104 | msg_set_bits(m, 0, 25, 0xf, n); | ||
105 | } | ||
106 | |||
107 | static inline void msg_set_importance(struct tipc_msg *m, u32 i) | ||
108 | { | ||
109 | msg_set_user(m, i); | ||
110 | } | ||
111 | |||
112 | static inline void msg_set_hdr_sz(struct tipc_msg *m,u32 n) | ||
113 | { | ||
114 | msg_set_bits(m, 0, 21, 0xf, n>>2); | ||
115 | } | ||
116 | |||
117 | static inline int msg_non_seq(struct tipc_msg *m) | ||
118 | { | ||
119 | return msg_bits(m, 0, 20, 1); | ||
120 | } | ||
121 | |||
122 | static inline void msg_set_non_seq(struct tipc_msg *m) | ||
123 | { | ||
124 | msg_set_bits(m, 0, 20, 1, 1); | ||
125 | } | ||
126 | |||
127 | static inline int msg_dest_droppable(struct tipc_msg *m) | ||
128 | { | ||
129 | return msg_bits(m, 0, 19, 1); | ||
130 | } | ||
131 | |||
132 | static inline void msg_set_dest_droppable(struct tipc_msg *m, u32 d) | ||
133 | { | ||
134 | msg_set_bits(m, 0, 19, 1, d); | ||
135 | } | ||
136 | |||
137 | static inline int msg_src_droppable(struct tipc_msg *m) | ||
138 | { | ||
139 | return msg_bits(m, 0, 18, 1); | ||
140 | } | ||
141 | |||
142 | static inline void msg_set_src_droppable(struct tipc_msg *m, u32 d) | ||
143 | { | ||
144 | msg_set_bits(m, 0, 18, 1, d); | ||
145 | } | ||
146 | |||
147 | static inline void msg_set_size(struct tipc_msg *m, u32 sz) | ||
148 | { | ||
149 | m->hdr[0] = htonl((msg_word(m, 0) & ~0x1ffff) | sz); | ||
150 | } | ||
151 | |||
152 | |||
153 | /* | ||
154 | * Word 1 | ||
155 | */ | ||
156 | |||
157 | static inline void msg_set_type(struct tipc_msg *m, u32 n) | ||
158 | { | ||
159 | msg_set_bits(m, 1, 29, 0x7, n); | ||
160 | } | ||
161 | |||
162 | static inline void msg_set_errcode(struct tipc_msg *m, u32 err) | ||
163 | { | ||
164 | msg_set_bits(m, 1, 25, 0xf, err); | ||
165 | } | ||
166 | |||
167 | static inline u32 msg_reroute_cnt(struct tipc_msg *m) | ||
168 | { | ||
169 | return msg_bits(m, 1, 21, 0xf); | ||
170 | } | ||
171 | |||
172 | static inline void msg_incr_reroute_cnt(struct tipc_msg *m) | ||
173 | { | ||
174 | msg_set_bits(m, 1, 21, 0xf, msg_reroute_cnt(m) + 1); | ||
175 | } | ||
176 | |||
177 | static inline void msg_reset_reroute_cnt(struct tipc_msg *m) | ||
178 | { | ||
179 | msg_set_bits(m, 1, 21, 0xf, 0); | ||
180 | } | ||
181 | |||
182 | static inline u32 msg_lookup_scope(struct tipc_msg *m) | ||
183 | { | ||
184 | return msg_bits(m, 1, 19, 0x3); | ||
185 | } | ||
186 | |||
187 | static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n) | ||
188 | { | ||
189 | msg_set_bits(m, 1, 19, 0x3, n); | ||
190 | } | ||
191 | |||
192 | static inline void msg_set_options(struct tipc_msg *m, const char *opt, u32 sz) | ||
193 | { | ||
194 | u32 hsz = msg_hdr_sz(m); | ||
195 | char *to = (char *)&m->hdr[hsz/4]; | ||
196 | |||
197 | if ((hsz < DIR_MSG_H_SIZE) || ((hsz + sz) > MAX_H_SIZE)) | ||
198 | return; | ||
199 | msg_set_bits(m, 1, 16, 0x7, (hsz - 28)/4); | ||
200 | msg_set_hdr_sz(m, hsz + sz); | ||
201 | memcpy(to, opt, sz); | ||
202 | } | ||
203 | |||
204 | static inline u32 msg_bcast_ack(struct tipc_msg *m) | ||
205 | { | ||
206 | return msg_bits(m, 1, 0, 0xffff); | ||
207 | } | ||
208 | |||
209 | static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n) | ||
210 | { | ||
211 | msg_set_bits(m, 1, 0, 0xffff, n); | ||
212 | } | ||
213 | |||
214 | |||
215 | /* | ||
216 | * Word 2 | ||
217 | */ | ||
218 | |||
219 | static inline u32 msg_ack(struct tipc_msg *m) | ||
220 | { | ||
221 | return msg_bits(m, 2, 16, 0xffff); | ||
222 | } | ||
223 | |||
224 | static inline void msg_set_ack(struct tipc_msg *m, u32 n) | ||
225 | { | ||
226 | msg_set_bits(m, 2, 16, 0xffff, n); | ||
227 | } | ||
228 | |||
229 | static inline u32 msg_seqno(struct tipc_msg *m) | ||
230 | { | ||
231 | return msg_bits(m, 2, 0, 0xffff); | ||
232 | } | ||
233 | |||
234 | static inline void msg_set_seqno(struct tipc_msg *m, u32 n) | ||
235 | { | ||
236 | msg_set_bits(m, 2, 0, 0xffff, n); | ||
237 | } | ||
238 | |||
239 | |||
240 | /* | ||
241 | * Words 3-10 | ||
242 | */ | ||
243 | |||
244 | |||
245 | static inline void msg_set_prevnode(struct tipc_msg *m, u32 a) | ||
246 | { | ||
247 | msg_set_word(m, 3, a); | ||
248 | } | ||
249 | |||
250 | static inline void msg_set_origport(struct tipc_msg *m, u32 p) | ||
251 | { | ||
252 | msg_set_word(m, 4, p); | ||
253 | } | ||
254 | |||
255 | static inline void msg_set_destport(struct tipc_msg *m, u32 p) | ||
256 | { | ||
257 | msg_set_word(m, 5, p); | ||
258 | } | ||
259 | |||
260 | static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p) | ||
261 | { | ||
262 | msg_set_word(m, 5, p); | ||
263 | } | ||
264 | |||
265 | static inline void msg_set_orignode(struct tipc_msg *m, u32 a) | ||
266 | { | ||
267 | msg_set_word(m, 6, a); | ||
268 | } | ||
269 | |||
270 | static inline void msg_set_destnode(struct tipc_msg *m, u32 a) | ||
271 | { | ||
272 | msg_set_word(m, 7, a); | ||
273 | } | ||
274 | |||
275 | static inline int msg_is_dest(struct tipc_msg *m, u32 d) | ||
276 | { | ||
277 | return(msg_short(m) || (msg_destnode(m) == d)); | ||
278 | } | ||
279 | |||
280 | static inline u32 msg_routed(struct tipc_msg *m) | ||
281 | { | ||
282 | if (likely(msg_short(m))) | ||
283 | return 0; | ||
284 | return(msg_destnode(m) ^ msg_orignode(m)) >> 11; | ||
285 | } | ||
286 | |||
287 | static inline void msg_set_nametype(struct tipc_msg *m, u32 n) | ||
288 | { | ||
289 | msg_set_word(m, 8, n); | ||
290 | } | ||
291 | |||
292 | static inline u32 msg_transp_seqno(struct tipc_msg *m) | ||
293 | { | ||
294 | return msg_word(m, 8); | ||
295 | } | ||
296 | |||
297 | static inline void msg_set_timestamp(struct tipc_msg *m, u32 n) | ||
298 | { | ||
299 | msg_set_word(m, 8, n); | ||
300 | } | ||
301 | |||
302 | static inline u32 msg_timestamp(struct tipc_msg *m) | ||
303 | { | ||
304 | return msg_word(m, 8); | ||
305 | } | ||
306 | |||
307 | static inline void msg_set_transp_seqno(struct tipc_msg *m, u32 n) | ||
308 | { | ||
309 | msg_set_word(m, 8, n); | ||
310 | } | ||
311 | |||
312 | static inline void msg_set_namelower(struct tipc_msg *m, u32 n) | ||
313 | { | ||
314 | msg_set_word(m, 9, n); | ||
315 | } | ||
316 | |||
317 | static inline void msg_set_nameinst(struct tipc_msg *m, u32 n) | ||
318 | { | ||
319 | msg_set_namelower(m, n); | ||
320 | } | ||
321 | |||
322 | static inline void msg_set_nameupper(struct tipc_msg *m, u32 n) | ||
323 | { | ||
324 | msg_set_word(m, 10, n); | ||
325 | } | ||
326 | |||
327 | static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) | ||
328 | { | ||
329 | return (struct tipc_msg *)msg_data(m); | ||
330 | } | ||
331 | |||
332 | static inline void msg_expand(struct tipc_msg *m, u32 destnode) | ||
333 | { | ||
334 | if (!msg_short(m)) | ||
335 | return; | ||
336 | msg_set_hdr_sz(m, LONG_H_SIZE); | ||
337 | msg_set_orignode(m, msg_prevnode(m)); | ||
338 | msg_set_destnode(m, destnode); | ||
339 | memset(&m->hdr[8], 0, 12); | ||
340 | } | ||
341 | |||
342 | |||
343 | |||
344 | /* | ||
345 | TIPC internal message header format, version 2 | ||
346 | |||
347 | 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 | ||
348 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
349 | w0:|vers |msg usr|hdr sz |n|resrv| packet size | | ||
350 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
351 | w1:|m typ|rsv=0| sequence gap | broadcast ack no | | ||
352 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
353 | w2:| link level ack no/bc_gap_from | seq no / bcast_gap_to | | ||
354 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
355 | w3:| previous node | | ||
356 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
357 | w4:| next sent broadcast/fragm no | next sent pkt/ fragm msg no | | ||
358 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
359 | w5:| session no |rsv=0|r|berid|link prio|netpl|p| | ||
360 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
361 | w6:| originating node | | ||
362 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
363 | w7:| destination node | | ||
364 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
365 | w8:| transport sequence number | | ||
366 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
367 | w9:| msg count / bcast tag | link tolerance | | ||
368 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
369 | \ \ | ||
370 | / User Specific Data / | ||
371 | \ \ | ||
372 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
373 | |||
374 | NB: CONN_MANAGER use data message format. LINK_CONFIG has own format. | ||
375 | */ | ||
376 | |||
377 | /* | ||
378 | * Internal users | ||
379 | */ | ||
380 | |||
381 | #define BCAST_PROTOCOL 5 | ||
382 | #define MSG_BUNDLER 6 | ||
383 | #define LINK_PROTOCOL 7 | ||
384 | #define CONN_MANAGER 8 | ||
385 | #define ROUTE_DISTRIBUTOR 9 | ||
386 | #define CHANGEOVER_PROTOCOL 10 | ||
387 | #define NAME_DISTRIBUTOR 11 | ||
388 | #define MSG_FRAGMENTER 12 | ||
389 | #define LINK_CONFIG 13 | ||
390 | #define INT_H_SIZE 40 | ||
391 | #define DSC_H_SIZE 40 | ||
392 | |||
393 | /* | ||
394 | * Connection management protocol messages | ||
395 | */ | ||
396 | |||
397 | #define CONN_PROBE 0 | ||
398 | #define CONN_PROBE_REPLY 1 | ||
399 | #define CONN_ACK 2 | ||
400 | |||
401 | /* | ||
402 | * Name distributor messages | ||
403 | */ | ||
404 | |||
405 | #define PUBLICATION 0 | ||
406 | #define WITHDRAWAL 1 | ||
407 | |||
408 | |||
409 | /* | ||
410 | * Word 1 | ||
411 | */ | ||
412 | |||
413 | static inline u32 msg_seq_gap(struct tipc_msg *m) | ||
414 | { | ||
415 | return msg_bits(m, 1, 16, 0xff); | ||
416 | } | ||
417 | |||
418 | static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n) | ||
419 | { | ||
420 | msg_set_bits(m, 1, 16, 0xff, n); | ||
421 | } | ||
422 | |||
423 | static inline u32 msg_req_links(struct tipc_msg *m) | ||
424 | { | ||
425 | return msg_bits(m, 1, 16, 0xfff); | ||
426 | } | ||
427 | |||
428 | static inline void msg_set_req_links(struct tipc_msg *m, u32 n) | ||
429 | { | ||
430 | msg_set_bits(m, 1, 16, 0xfff, n); | ||
431 | } | ||
432 | |||
433 | |||
434 | /* | ||
435 | * Word 2 | ||
436 | */ | ||
437 | |||
438 | static inline u32 msg_dest_domain(struct tipc_msg *m) | ||
439 | { | ||
440 | return msg_word(m, 2); | ||
441 | } | ||
442 | |||
443 | static inline void msg_set_dest_domain(struct tipc_msg *m, u32 n) | ||
444 | { | ||
445 | msg_set_word(m, 2, n); | ||
446 | } | ||
447 | |||
448 | static inline u32 msg_bcgap_after(struct tipc_msg *m) | ||
449 | { | ||
450 | return msg_bits(m, 2, 16, 0xffff); | ||
451 | } | ||
452 | |||
453 | static inline void msg_set_bcgap_after(struct tipc_msg *m, u32 n) | ||
454 | { | ||
455 | msg_set_bits(m, 2, 16, 0xffff, n); | ||
456 | } | ||
457 | |||
458 | static inline u32 msg_bcgap_to(struct tipc_msg *m) | ||
459 | { | ||
460 | return msg_bits(m, 2, 0, 0xffff); | ||
461 | } | ||
462 | |||
463 | static inline void msg_set_bcgap_to(struct tipc_msg *m, u32 n) | ||
464 | { | ||
465 | msg_set_bits(m, 2, 0, 0xffff, n); | ||
466 | } | ||
467 | |||
468 | |||
469 | /* | ||
470 | * Word 4 | ||
471 | */ | ||
472 | |||
473 | static inline u32 msg_last_bcast(struct tipc_msg *m) | ||
474 | { | ||
475 | return msg_bits(m, 4, 16, 0xffff); | ||
476 | } | ||
477 | |||
478 | static inline void msg_set_last_bcast(struct tipc_msg *m, u32 n) | ||
479 | { | ||
480 | msg_set_bits(m, 4, 16, 0xffff, n); | ||
481 | } | ||
482 | |||
483 | |||
484 | static inline u32 msg_fragm_no(struct tipc_msg *m) | ||
485 | { | ||
486 | return msg_bits(m, 4, 16, 0xffff); | ||
487 | } | ||
488 | |||
489 | static inline void msg_set_fragm_no(struct tipc_msg *m, u32 n) | ||
490 | { | ||
491 | msg_set_bits(m, 4, 16, 0xffff, n); | ||
492 | } | ||
493 | |||
494 | |||
495 | static inline u32 msg_next_sent(struct tipc_msg *m) | ||
496 | { | ||
497 | return msg_bits(m, 4, 0, 0xffff); | ||
498 | } | ||
499 | |||
500 | static inline void msg_set_next_sent(struct tipc_msg *m, u32 n) | ||
501 | { | ||
502 | msg_set_bits(m, 4, 0, 0xffff, n); | ||
503 | } | ||
504 | |||
505 | |||
506 | static inline u32 msg_long_msgno(struct tipc_msg *m) | ||
507 | { | ||
508 | return msg_bits(m, 4, 0, 0xffff); | ||
509 | } | ||
510 | |||
511 | static inline void msg_set_long_msgno(struct tipc_msg *m, u32 n) | ||
512 | { | ||
513 | msg_set_bits(m, 4, 0, 0xffff, n); | ||
514 | } | ||
515 | |||
516 | static inline u32 msg_bc_netid(struct tipc_msg *m) | ||
517 | { | ||
518 | return msg_word(m, 4); | ||
519 | } | ||
520 | |||
521 | static inline void msg_set_bc_netid(struct tipc_msg *m, u32 id) | ||
522 | { | ||
523 | msg_set_word(m, 4, id); | ||
524 | } | ||
525 | |||
526 | static inline u32 msg_link_selector(struct tipc_msg *m) | ||
527 | { | ||
528 | return msg_bits(m, 4, 0, 1); | ||
529 | } | ||
530 | |||
531 | static inline void msg_set_link_selector(struct tipc_msg *m, u32 n) | ||
532 | { | ||
533 | msg_set_bits(m, 4, 0, 1, (n & 1)); | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | * Word 5 | ||
538 | */ | ||
539 | |||
540 | static inline u32 msg_session(struct tipc_msg *m) | ||
541 | { | ||
542 | return msg_bits(m, 5, 16, 0xffff); | ||
543 | } | ||
544 | |||
545 | static inline void msg_set_session(struct tipc_msg *m, u32 n) | ||
546 | { | ||
547 | msg_set_bits(m, 5, 16, 0xffff, n); | ||
548 | } | ||
549 | |||
550 | static inline u32 msg_probe(struct tipc_msg *m) | ||
551 | { | ||
552 | return msg_bits(m, 5, 0, 1); | ||
553 | } | ||
554 | |||
555 | static inline void msg_set_probe(struct tipc_msg *m, u32 val) | ||
556 | { | ||
557 | msg_set_bits(m, 5, 0, 1, (val & 1)); | ||
558 | } | ||
559 | |||
560 | static inline char msg_net_plane(struct tipc_msg *m) | ||
561 | { | ||
562 | return msg_bits(m, 5, 1, 7) + 'A'; | ||
563 | } | ||
564 | |||
565 | static inline void msg_set_net_plane(struct tipc_msg *m, char n) | ||
566 | { | ||
567 | msg_set_bits(m, 5, 1, 7, (n - 'A')); | ||
568 | } | ||
569 | |||
570 | static inline u32 msg_linkprio(struct tipc_msg *m) | ||
571 | { | ||
572 | return msg_bits(m, 5, 4, 0x1f); | ||
573 | } | ||
574 | |||
575 | static inline void msg_set_linkprio(struct tipc_msg *m, u32 n) | ||
576 | { | ||
577 | msg_set_bits(m, 5, 4, 0x1f, n); | ||
578 | } | ||
579 | |||
580 | static inline u32 msg_bearer_id(struct tipc_msg *m) | ||
581 | { | ||
582 | return msg_bits(m, 5, 9, 0x7); | ||
583 | } | ||
584 | |||
585 | static inline void msg_set_bearer_id(struct tipc_msg *m, u32 n) | ||
586 | { | ||
587 | msg_set_bits(m, 5, 9, 0x7, n); | ||
588 | } | ||
589 | |||
590 | static inline u32 msg_redundant_link(struct tipc_msg *m) | ||
591 | { | ||
592 | return msg_bits(m, 5, 12, 0x1); | ||
593 | } | ||
594 | |||
595 | static inline void msg_set_redundant_link(struct tipc_msg *m) | ||
596 | { | ||
597 | msg_set_bits(m, 5, 12, 0x1, 1); | ||
598 | } | ||
599 | |||
600 | static inline void msg_clear_redundant_link(struct tipc_msg *m) | ||
601 | { | ||
602 | msg_set_bits(m, 5, 12, 0x1, 0); | ||
603 | } | ||
604 | |||
605 | |||
606 | /* | ||
607 | * Word 9 | ||
608 | */ | ||
609 | |||
610 | static inline u32 msg_msgcnt(struct tipc_msg *m) | ||
611 | { | ||
612 | return msg_bits(m, 9, 16, 0xffff); | ||
613 | } | ||
614 | |||
615 | static inline void msg_set_msgcnt(struct tipc_msg *m, u32 n) | ||
616 | { | ||
617 | msg_set_bits(m, 9, 16, 0xffff, n); | ||
618 | } | ||
619 | |||
620 | static inline u32 msg_bcast_tag(struct tipc_msg *m) | ||
621 | { | ||
622 | return msg_bits(m, 9, 16, 0xffff); | ||
623 | } | ||
624 | |||
625 | static inline void msg_set_bcast_tag(struct tipc_msg *m, u32 n) | ||
626 | { | ||
627 | msg_set_bits(m, 9, 16, 0xffff, n); | ||
628 | } | ||
629 | |||
630 | static inline u32 msg_max_pkt(struct tipc_msg *m) | ||
631 | { | ||
632 | return (msg_bits(m, 9, 16, 0xffff) * 4); | ||
633 | } | ||
634 | |||
635 | static inline void msg_set_max_pkt(struct tipc_msg *m, u32 n) | ||
636 | { | ||
637 | msg_set_bits(m, 9, 16, 0xffff, (n / 4)); | ||
638 | } | ||
639 | |||
640 | static inline u32 msg_link_tolerance(struct tipc_msg *m) | ||
641 | { | ||
642 | return msg_bits(m, 9, 0, 0xffff); | ||
643 | } | ||
644 | |||
645 | static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n) | ||
646 | { | ||
647 | msg_set_bits(m, 9, 0, 0xffff, n); | ||
648 | } | ||
649 | |||
650 | /* | ||
651 | * Routing table message data | ||
652 | */ | ||
653 | |||
654 | |||
655 | static inline u32 msg_remote_node(struct tipc_msg *m) | ||
656 | { | ||
657 | return msg_word(m, msg_hdr_sz(m)/4); | ||
658 | } | ||
659 | |||
660 | static inline void msg_set_remote_node(struct tipc_msg *m, u32 a) | ||
661 | { | ||
662 | msg_set_word(m, msg_hdr_sz(m)/4, a); | ||
663 | } | ||
664 | |||
665 | static inline int msg_dataoctet(struct tipc_msg *m, u32 pos) | ||
666 | { | ||
667 | return(msg_data(m)[pos + 4] != 0); | ||
668 | } | ||
669 | |||
670 | static inline void msg_set_dataoctet(struct tipc_msg *m, u32 pos) | ||
671 | { | ||
672 | msg_data(m)[pos + 4] = 1; | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * Segmentation message types | ||
677 | */ | ||
678 | |||
679 | #define FIRST_FRAGMENT 0 | ||
680 | #define FRAGMENT 1 | ||
681 | #define LAST_FRAGMENT 2 | ||
682 | |||
683 | /* | ||
684 | * Link management protocol message types | ||
685 | */ | ||
686 | |||
687 | #define STATE_MSG 0 | ||
688 | #define RESET_MSG 1 | ||
689 | #define ACTIVATE_MSG 2 | ||
690 | |||
691 | /* | ||
692 | * Changeover tunnel message types | ||
693 | */ | ||
694 | #define DUPLICATE_MSG 0 | ||
695 | #define ORIGINAL_MSG 1 | ||
696 | |||
697 | /* | ||
698 | * Routing table message types | ||
699 | */ | ||
700 | #define EXT_ROUTING_TABLE 0 | ||
701 | #define LOCAL_ROUTING_TABLE 1 | ||
702 | #define SLAVE_ROUTING_TABLE 2 | ||
703 | #define ROUTE_ADDITION 3 | ||
704 | #define ROUTE_REMOVAL 4 | ||
705 | |||
706 | /* | ||
707 | * Config protocol message types | ||
708 | */ | ||
709 | |||
710 | #define DSC_REQ_MSG 0 | ||
711 | #define DSC_RESP_MSG 1 | ||
712 | |||
713 | static inline u32 msg_tot_importance(struct tipc_msg *m) | ||
714 | { | ||
715 | if (likely(msg_isdata(m))) { | ||
716 | if (likely(msg_orignode(m) == tipc_own_addr)) | ||
717 | return msg_importance(m); | ||
718 | return msg_importance(m) + 4; | ||
719 | } | ||
720 | if ((msg_user(m) == MSG_FRAGMENTER) && | ||
721 | (msg_type(m) == FIRST_FRAGMENT)) | ||
722 | return msg_importance(msg_get_wrapped(m)); | ||
723 | return msg_importance(m); | ||
724 | } | ||
725 | |||
726 | |||
727 | static inline void msg_init(struct tipc_msg *m, u32 user, u32 type, | ||
728 | u32 err, u32 hsize, u32 destnode) | ||
729 | { | ||
730 | memset(m, 0, hsize); | ||
731 | msg_set_version(m); | ||
732 | msg_set_user(m, user); | ||
733 | msg_set_hdr_sz(m, hsize); | ||
734 | msg_set_size(m, hsize); | ||
735 | msg_set_prevnode(m, tipc_own_addr); | ||
736 | msg_set_type(m, type); | ||
737 | msg_set_errcode(m, err); | ||
738 | if (!msg_short(m)) { | ||
739 | msg_set_orignode(m, tipc_own_addr); | ||
740 | msg_set_destnode(m, destnode); | ||
741 | } | ||
742 | } | ||
743 | |||
744 | /** | ||
745 | * msg_calc_data_size - determine total data size for message | ||
746 | */ | ||
747 | |||
748 | static inline int msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) | ||
749 | { | ||
750 | int dsz = 0; | ||
751 | int i; | ||
752 | |||
753 | for (i = 0; i < num_sect; i++) | ||
754 | dsz += msg_sect[i].iov_len; | ||
755 | return dsz; | ||
756 | } | ||
757 | |||
758 | /** | ||
759 | * msg_build - create message using specified header and data | ||
760 | * | ||
761 | * Note: Caller must not hold any locks in case copy_from_user() is interrupted! | ||
762 | * | ||
763 | * Returns message data size or errno | ||
764 | */ | ||
765 | |||
766 | static inline int msg_build(struct tipc_msg *hdr, | ||
767 | struct iovec const *msg_sect, u32 num_sect, | ||
768 | int max_size, int usrmem, struct sk_buff** buf) | ||
769 | { | ||
770 | int dsz, sz, hsz, pos, res, cnt; | ||
771 | |||
772 | dsz = msg_calc_data_size(msg_sect, num_sect); | ||
773 | if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) { | ||
774 | *buf = NULL; | ||
775 | return -EINVAL; | ||
776 | } | ||
777 | |||
778 | pos = hsz = msg_hdr_sz(hdr); | ||
779 | sz = hsz + dsz; | ||
780 | msg_set_size(hdr, sz); | ||
781 | if (unlikely(sz > max_size)) { | ||
782 | *buf = NULL; | ||
783 | return dsz; | ||
784 | } | ||
785 | |||
786 | *buf = buf_acquire(sz); | ||
787 | if (!(*buf)) | ||
788 | return -ENOMEM; | ||
789 | memcpy((*buf)->data, (unchar *)hdr, hsz); | ||
790 | for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { | ||
791 | if (likely(usrmem)) | ||
792 | res = !copy_from_user((*buf)->data + pos, | ||
793 | msg_sect[cnt].iov_base, | ||
794 | msg_sect[cnt].iov_len); | ||
795 | else | ||
796 | memcpy((*buf)->data + pos, msg_sect[cnt].iov_base, | ||
797 | msg_sect[cnt].iov_len); | ||
798 | pos += msg_sect[cnt].iov_len; | ||
799 | } | ||
800 | if (likely(res)) | ||
801 | return dsz; | ||
802 | |||
803 | buf_discard(*buf); | ||
804 | *buf = NULL; | ||
805 | return -EFAULT; | ||
806 | } | ||
807 | |||
808 | |||
809 | struct tipc_media_addr; | ||
810 | |||
811 | extern void msg_set_media_addr(struct tipc_msg *m, | ||
812 | struct tipc_media_addr *a); | ||
813 | |||
814 | extern void msg_get_media_addr(struct tipc_msg *m, | ||
815 | struct tipc_media_addr *a); | ||
816 | |||
817 | |||
818 | #endif | ||
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c new file mode 100644 index 000000000000..41cbaf1a4a73 --- /dev/null +++ b/net/tipc/name_distr.c | |||
@@ -0,0 +1,309 @@ | |||
1 | /* | ||
2 | * net/tipc/name_distr.c: TIPC name distribution code | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "cluster.h" | ||
39 | #include "dbg.h" | ||
40 | #include "link.h" | ||
41 | #include "msg.h" | ||
42 | #include "name_distr.h" | ||
43 | |||
44 | #undef DBG_OUTPUT | ||
45 | #define DBG_OUTPUT NULL | ||
46 | |||
47 | #define ITEM_SIZE sizeof(struct distr_item) | ||
48 | |||
49 | /** | ||
50 | * struct distr_item - publication info distributed to other nodes | ||
51 | * @type: name sequence type | ||
52 | * @lower: name sequence lower bound | ||
53 | * @upper: name sequence upper bound | ||
54 | * @ref: publishing port reference | ||
55 | * @key: publication key | ||
56 | * | ||
57 | * ===> All fields are stored in network byte order. <=== | ||
58 | * | ||
59 | * First 3 fields identify (name or) name sequence being published. | ||
60 | * Reference field uniquely identifies port that published name sequence. | ||
61 | * Key field uniquely identifies publication, in the event a port has | ||
62 | * multiple publications of the same name sequence. | ||
63 | * | ||
64 | * Note: There is no field that identifies the publishing node because it is | ||
65 | * the same for all items contained within a publication message. | ||
66 | */ | ||
67 | |||
68 | struct distr_item { | ||
69 | u32 type; | ||
70 | u32 lower; | ||
71 | u32 upper; | ||
72 | u32 ref; | ||
73 | u32 key; | ||
74 | }; | ||
75 | |||
76 | /** | ||
77 | * List of externally visible publications by this node -- | ||
78 | * that is, all publications having scope > TIPC_NODE_SCOPE. | ||
79 | */ | ||
80 | |||
81 | static LIST_HEAD(publ_root); | ||
82 | static u32 publ_cnt = 0; | ||
83 | |||
84 | /** | ||
85 | * publ_to_item - add publication info to a publication message | ||
86 | */ | ||
87 | |||
88 | static void publ_to_item(struct distr_item *i, struct publication *p) | ||
89 | { | ||
90 | i->type = htonl(p->type); | ||
91 | i->lower = htonl(p->lower); | ||
92 | i->upper = htonl(p->upper); | ||
93 | i->ref = htonl(p->ref); | ||
94 | i->key = htonl(p->key); | ||
95 | dbg("publ_to_item: %u, %u, %u\n", p->type, p->lower, p->upper); | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * named_prepare_buf - allocate & initialize a publication message | ||
100 | */ | ||
101 | |||
102 | static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest) | ||
103 | { | ||
104 | struct sk_buff *buf = buf_acquire(LONG_H_SIZE + size); | ||
105 | struct tipc_msg *msg; | ||
106 | |||
107 | if (buf != NULL) { | ||
108 | msg = buf_msg(buf); | ||
109 | msg_init(msg, NAME_DISTRIBUTOR, type, TIPC_OK, | ||
110 | LONG_H_SIZE, dest); | ||
111 | msg_set_size(msg, LONG_H_SIZE + size); | ||
112 | } | ||
113 | return buf; | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * named_publish - tell other nodes about a new publication by this node | ||
118 | */ | ||
119 | |||
120 | void named_publish(struct publication *publ) | ||
121 | { | ||
122 | struct sk_buff *buf; | ||
123 | struct distr_item *item; | ||
124 | |||
125 | list_add(&publ->local_list, &publ_root); | ||
126 | publ_cnt++; | ||
127 | |||
128 | buf = named_prepare_buf(PUBLICATION, ITEM_SIZE, 0); | ||
129 | if (!buf) { | ||
130 | warn("Memory squeeze; failed to distribute publication\n"); | ||
131 | return; | ||
132 | } | ||
133 | |||
134 | item = (struct distr_item *)msg_data(buf_msg(buf)); | ||
135 | publ_to_item(item, publ); | ||
136 | dbg("named_withdraw: broadcasting publish msg\n"); | ||
137 | cluster_broadcast(buf); | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * named_withdraw - tell other nodes about a withdrawn publication by this node | ||
142 | */ | ||
143 | |||
144 | void named_withdraw(struct publication *publ) | ||
145 | { | ||
146 | struct sk_buff *buf; | ||
147 | struct distr_item *item; | ||
148 | |||
149 | list_del(&publ->local_list); | ||
150 | publ_cnt--; | ||
151 | |||
152 | buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0); | ||
153 | if (!buf) { | ||
154 | warn("Memory squeeze; failed to distribute withdrawal\n"); | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | item = (struct distr_item *)msg_data(buf_msg(buf)); | ||
159 | publ_to_item(item, publ); | ||
160 | dbg("named_withdraw: broadcasting withdraw msg\n"); | ||
161 | cluster_broadcast(buf); | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * named_node_up - tell specified node about all publications by this node | ||
166 | */ | ||
167 | |||
168 | void named_node_up(unsigned long node) | ||
169 | { | ||
170 | struct publication *publ; | ||
171 | struct distr_item *item = 0; | ||
172 | struct sk_buff *buf = 0; | ||
173 | u32 left = 0; | ||
174 | u32 rest; | ||
175 | u32 max_item_buf; | ||
176 | |||
177 | assert(in_own_cluster(node)); | ||
178 | read_lock_bh(&nametbl_lock); | ||
179 | max_item_buf = TIPC_MAX_USER_MSG_SIZE / ITEM_SIZE; | ||
180 | max_item_buf *= ITEM_SIZE; | ||
181 | rest = publ_cnt * ITEM_SIZE; | ||
182 | |||
183 | list_for_each_entry(publ, &publ_root, local_list) { | ||
184 | if (!buf) { | ||
185 | left = (rest <= max_item_buf) ? rest : max_item_buf; | ||
186 | rest -= left; | ||
187 | buf = named_prepare_buf(PUBLICATION, left, node); | ||
188 | if (buf == NULL) { | ||
189 | warn("Memory Squeeze; could not send publication\n"); | ||
190 | goto exit; | ||
191 | } | ||
192 | item = (struct distr_item *)msg_data(buf_msg(buf)); | ||
193 | } | ||
194 | publ_to_item(item, publ); | ||
195 | item++; | ||
196 | left -= ITEM_SIZE; | ||
197 | if (!left) { | ||
198 | msg_set_link_selector(buf_msg(buf), node); | ||
199 | dbg("named_node_up: sending publish msg to " | ||
200 | "<%u.%u.%u>\n", tipc_zone(node), | ||
201 | tipc_cluster(node), tipc_node(node)); | ||
202 | link_send(buf, node, node); | ||
203 | buf = 0; | ||
204 | } | ||
205 | } | ||
206 | exit: | ||
207 | read_unlock_bh(&nametbl_lock); | ||
208 | } | ||
209 | |||
210 | /** | ||
211 | * node_is_down - remove publication associated with a failed node | ||
212 | * | ||
213 | * Invoked for each publication issued by a newly failed node. | ||
214 | * Removes publication structure from name table & deletes it. | ||
215 | * In rare cases the link may have come back up again when this | ||
216 | * function is called, and we have two items representing the same | ||
217 | * publication. Nudge this item's key to distinguish it from the other. | ||
218 | * (Note: Publication's node subscription is already unsubscribed.) | ||
219 | */ | ||
220 | |||
221 | static void node_is_down(struct publication *publ) | ||
222 | { | ||
223 | struct publication *p; | ||
224 | write_lock_bh(&nametbl_lock); | ||
225 | dbg("node_is_down: withdrawing %u, %u, %u\n", | ||
226 | publ->type, publ->lower, publ->upper); | ||
227 | publ->key += 1222345; | ||
228 | p = nametbl_remove_publ(publ->type, publ->lower, | ||
229 | publ->node, publ->ref, publ->key); | ||
230 | assert(p == publ); | ||
231 | write_unlock_bh(&nametbl_lock); | ||
232 | if (publ) | ||
233 | kfree(publ); | ||
234 | } | ||
235 | |||
236 | /** | ||
237 | * named_recv - process name table update message sent by another node | ||
238 | */ | ||
239 | |||
240 | void named_recv(struct sk_buff *buf) | ||
241 | { | ||
242 | struct publication *publ; | ||
243 | struct tipc_msg *msg = buf_msg(buf); | ||
244 | struct distr_item *item = (struct distr_item *)msg_data(msg); | ||
245 | u32 count = msg_data_sz(msg) / ITEM_SIZE; | ||
246 | |||
247 | write_lock_bh(&nametbl_lock); | ||
248 | while (count--) { | ||
249 | if (msg_type(msg) == PUBLICATION) { | ||
250 | dbg("named_recv: got publication for %u, %u, %u\n", | ||
251 | ntohl(item->type), ntohl(item->lower), | ||
252 | ntohl(item->upper)); | ||
253 | publ = nametbl_insert_publ(ntohl(item->type), | ||
254 | ntohl(item->lower), | ||
255 | ntohl(item->upper), | ||
256 | TIPC_CLUSTER_SCOPE, | ||
257 | msg_orignode(msg), | ||
258 | ntohl(item->ref), | ||
259 | ntohl(item->key)); | ||
260 | if (publ) { | ||
261 | nodesub_subscribe(&publ->subscr, | ||
262 | msg_orignode(msg), | ||
263 | publ, | ||
264 | (net_ev_handler)node_is_down); | ||
265 | } | ||
266 | } else if (msg_type(msg) == WITHDRAWAL) { | ||
267 | dbg("named_recv: got withdrawl for %u, %u, %u\n", | ||
268 | ntohl(item->type), ntohl(item->lower), | ||
269 | ntohl(item->upper)); | ||
270 | publ = nametbl_remove_publ(ntohl(item->type), | ||
271 | ntohl(item->lower), | ||
272 | msg_orignode(msg), | ||
273 | ntohl(item->ref), | ||
274 | ntohl(item->key)); | ||
275 | |||
276 | if (publ) { | ||
277 | nodesub_unsubscribe(&publ->subscr); | ||
278 | kfree(publ); | ||
279 | } | ||
280 | } else { | ||
281 | warn("named_recv: unknown msg\n"); | ||
282 | } | ||
283 | item++; | ||
284 | } | ||
285 | write_unlock_bh(&nametbl_lock); | ||
286 | buf_discard(buf); | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * named_reinit - re-initialize local publication list | ||
291 | * | ||
292 | * This routine is called whenever TIPC networking is (re)enabled. | ||
293 | * All existing publications by this node that have "cluster" or "zone" scope | ||
294 | * are updated to reflect the node's current network address. | ||
295 | * (If the node's address is unchanged, the update loop terminates immediately.) | ||
296 | */ | ||
297 | |||
298 | void named_reinit(void) | ||
299 | { | ||
300 | struct publication *publ; | ||
301 | |||
302 | write_lock_bh(&nametbl_lock); | ||
303 | list_for_each_entry(publ, &publ_root, local_list) { | ||
304 | if (publ->node == tipc_own_addr) | ||
305 | break; | ||
306 | publ->node = tipc_own_addr; | ||
307 | } | ||
308 | write_unlock_bh(&nametbl_lock); | ||
309 | } | ||
diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h new file mode 100644 index 000000000000..a04bdeac84ea --- /dev/null +++ b/net/tipc/name_distr.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * net/tipc/name_distr.h: Include file for TIPC name distribution code | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_NAME_DISTR_H | ||
38 | #define _TIPC_NAME_DISTR_H | ||
39 | |||
40 | #include "name_table.h" | ||
41 | |||
42 | void named_publish(struct publication *publ); | ||
43 | void named_withdraw(struct publication *publ); | ||
44 | void named_node_up(unsigned long node); | ||
45 | void named_recv(struct sk_buff *buf); | ||
46 | void named_reinit(void); | ||
47 | |||
48 | #endif | ||
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c new file mode 100644 index 000000000000..972c83eb83b4 --- /dev/null +++ b/net/tipc/name_table.c | |||
@@ -0,0 +1,1079 @@ | |||
1 | /* | ||
2 | * net/tipc/name_table.c: TIPC name table code | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "config.h" | ||
39 | #include "dbg.h" | ||
40 | #include "name_table.h" | ||
41 | #include "name_distr.h" | ||
42 | #include "addr.h" | ||
43 | #include "node_subscr.h" | ||
44 | #include "subscr.h" | ||
45 | #include "port.h" | ||
46 | #include "cluster.h" | ||
47 | #include "bcast.h" | ||
48 | |||
49 | int tipc_nametbl_size = 1024; /* must be a power of 2 */ | ||
50 | |||
51 | /** | ||
52 | * struct sub_seq - container for all published instances of a name sequence | ||
53 | * @lower: name sequence lower bound | ||
54 | * @upper: name sequence upper bound | ||
55 | * @node_list: circular list of matching publications with >= node scope | ||
56 | * @cluster_list: circular list of matching publications with >= cluster scope | ||
57 | * @zone_list: circular list of matching publications with >= zone scope | ||
58 | */ | ||
59 | |||
60 | struct sub_seq { | ||
61 | u32 lower; | ||
62 | u32 upper; | ||
63 | struct publication *node_list; | ||
64 | struct publication *cluster_list; | ||
65 | struct publication *zone_list; | ||
66 | }; | ||
67 | |||
68 | /** | ||
69 | * struct name_seq - container for all published instances of a name type | ||
70 | * @type: 32 bit 'type' value for name sequence | ||
71 | * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type'; | ||
72 | * sub-sequences are sorted in ascending order | ||
73 | * @alloc: number of sub-sequences currently in array | ||
74 | * @first_free: upper bound of highest sub-sequence + 1 | ||
75 | * @ns_list: links to adjacent name sequences in hash chain | ||
76 | * @subscriptions: list of subscriptions for this 'type' | ||
77 | * @lock: spinlock controlling access to name sequence structure | ||
78 | */ | ||
79 | |||
80 | struct name_seq { | ||
81 | u32 type; | ||
82 | struct sub_seq *sseqs; | ||
83 | u32 alloc; | ||
84 | u32 first_free; | ||
85 | struct hlist_node ns_list; | ||
86 | struct list_head subscriptions; | ||
87 | spinlock_t lock; | ||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * struct name_table - table containing all existing port name publications | ||
92 | * @types: pointer to fixed-sized array of name sequence lists, | ||
93 | * accessed via hashing on 'type'; name sequence lists are *not* sorted | ||
94 | * @local_publ_count: number of publications issued by this node | ||
95 | */ | ||
96 | |||
97 | struct name_table { | ||
98 | struct hlist_head *types; | ||
99 | u32 local_publ_count; | ||
100 | }; | ||
101 | |||
102 | struct name_table table = { NULL } ; | ||
103 | static atomic_t rsv_publ_ok = ATOMIC_INIT(0); | ||
104 | rwlock_t nametbl_lock = RW_LOCK_UNLOCKED; | ||
105 | |||
106 | |||
107 | static inline int hash(int x) | ||
108 | { | ||
109 | return(x & (tipc_nametbl_size - 1)); | ||
110 | } | ||
111 | |||
112 | /** | ||
113 | * publ_create - create a publication structure | ||
114 | */ | ||
115 | |||
116 | static struct publication *publ_create(u32 type, u32 lower, u32 upper, | ||
117 | u32 scope, u32 node, u32 port_ref, | ||
118 | u32 key) | ||
119 | { | ||
120 | struct publication *publ = | ||
121 | (struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC); | ||
122 | if (publ == NULL) { | ||
123 | warn("Memory squeeze; failed to create publication\n"); | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | memset(publ, 0, sizeof(*publ)); | ||
128 | publ->type = type; | ||
129 | publ->lower = lower; | ||
130 | publ->upper = upper; | ||
131 | publ->scope = scope; | ||
132 | publ->node = node; | ||
133 | publ->ref = port_ref; | ||
134 | publ->key = key; | ||
135 | INIT_LIST_HEAD(&publ->local_list); | ||
136 | INIT_LIST_HEAD(&publ->pport_list); | ||
137 | INIT_LIST_HEAD(&publ->subscr.nodesub_list); | ||
138 | return publ; | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * subseq_alloc - allocate a specified number of sub-sequence structures | ||
143 | */ | ||
144 | |||
145 | struct sub_seq *subseq_alloc(u32 cnt) | ||
146 | { | ||
147 | u32 sz = cnt * sizeof(struct sub_seq); | ||
148 | struct sub_seq *sseq = (struct sub_seq *)kmalloc(sz, GFP_ATOMIC); | ||
149 | |||
150 | if (sseq) | ||
151 | memset(sseq, 0, sz); | ||
152 | return sseq; | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * nameseq_create - create a name sequence structure for the specified 'type' | ||
157 | * | ||
158 | * Allocates a single sub-sequence structure and sets it to all 0's. | ||
159 | */ | ||
160 | |||
161 | struct name_seq *nameseq_create(u32 type, struct hlist_head *seq_head) | ||
162 | { | ||
163 | struct name_seq *nseq = | ||
164 | (struct name_seq *)kmalloc(sizeof(*nseq), GFP_ATOMIC); | ||
165 | struct sub_seq *sseq = subseq_alloc(1); | ||
166 | |||
167 | if (!nseq || !sseq) { | ||
168 | warn("Memory squeeze; failed to create name sequence\n"); | ||
169 | kfree(nseq); | ||
170 | kfree(sseq); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | memset(nseq, 0, sizeof(*nseq)); | ||
175 | nseq->lock = SPIN_LOCK_UNLOCKED; | ||
176 | nseq->type = type; | ||
177 | nseq->sseqs = sseq; | ||
178 | dbg("nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n", | ||
179 | nseq, type, nseq->sseqs, nseq->first_free); | ||
180 | nseq->alloc = 1; | ||
181 | INIT_HLIST_NODE(&nseq->ns_list); | ||
182 | INIT_LIST_HEAD(&nseq->subscriptions); | ||
183 | hlist_add_head(&nseq->ns_list, seq_head); | ||
184 | return nseq; | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * nameseq_find_subseq - find sub-sequence (if any) matching a name instance | ||
189 | * | ||
190 | * Very time-critical, so binary searches through sub-sequence array. | ||
191 | */ | ||
192 | |||
193 | static inline struct sub_seq *nameseq_find_subseq(struct name_seq *nseq, | ||
194 | u32 instance) | ||
195 | { | ||
196 | struct sub_seq *sseqs = nseq->sseqs; | ||
197 | int low = 0; | ||
198 | int high = nseq->first_free - 1; | ||
199 | int mid; | ||
200 | |||
201 | while (low <= high) { | ||
202 | mid = (low + high) / 2; | ||
203 | if (instance < sseqs[mid].lower) | ||
204 | high = mid - 1; | ||
205 | else if (instance > sseqs[mid].upper) | ||
206 | low = mid + 1; | ||
207 | else | ||
208 | return &sseqs[mid]; | ||
209 | } | ||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | /** | ||
214 | * nameseq_locate_subseq - determine position of name instance in sub-sequence | ||
215 | * | ||
216 | * Returns index in sub-sequence array of the entry that contains the specified | ||
217 | * instance value; if no entry contains that value, returns the position | ||
218 | * where a new entry for it would be inserted in the array. | ||
219 | * | ||
220 | * Note: Similar to binary search code for locating a sub-sequence. | ||
221 | */ | ||
222 | |||
223 | static u32 nameseq_locate_subseq(struct name_seq *nseq, u32 instance) | ||
224 | { | ||
225 | struct sub_seq *sseqs = nseq->sseqs; | ||
226 | int low = 0; | ||
227 | int high = nseq->first_free - 1; | ||
228 | int mid; | ||
229 | |||
230 | while (low <= high) { | ||
231 | mid = (low + high) / 2; | ||
232 | if (instance < sseqs[mid].lower) | ||
233 | high = mid - 1; | ||
234 | else if (instance > sseqs[mid].upper) | ||
235 | low = mid + 1; | ||
236 | else | ||
237 | return mid; | ||
238 | } | ||
239 | return low; | ||
240 | } | ||
241 | |||
242 | /** | ||
243 | * nameseq_insert_publ - | ||
244 | */ | ||
245 | |||
246 | struct publication *nameseq_insert_publ(struct name_seq *nseq, | ||
247 | u32 type, u32 lower, u32 upper, | ||
248 | u32 scope, u32 node, u32 port, u32 key) | ||
249 | { | ||
250 | struct subscription *s; | ||
251 | struct subscription *st; | ||
252 | struct publication *publ; | ||
253 | struct sub_seq *sseq; | ||
254 | int created_subseq = 0; | ||
255 | |||
256 | assert(nseq->first_free <= nseq->alloc); | ||
257 | sseq = nameseq_find_subseq(nseq, lower); | ||
258 | dbg("nameseq_ins: for seq %x,<%u,%u>, found sseq %x\n", | ||
259 | nseq, type, lower, sseq); | ||
260 | if (sseq) { | ||
261 | |||
262 | /* Lower end overlaps existing entry => need an exact match */ | ||
263 | |||
264 | if ((sseq->lower != lower) || (sseq->upper != upper)) { | ||
265 | warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); | ||
266 | return 0; | ||
267 | } | ||
268 | } else { | ||
269 | u32 inspos; | ||
270 | struct sub_seq *freesseq; | ||
271 | |||
272 | /* Find where lower end should be inserted */ | ||
273 | |||
274 | inspos = nameseq_locate_subseq(nseq, lower); | ||
275 | |||
276 | /* Fail if upper end overlaps into an existing entry */ | ||
277 | |||
278 | if ((inspos < nseq->first_free) && | ||
279 | (upper >= nseq->sseqs[inspos].lower)) { | ||
280 | warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); | ||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | /* Ensure there is space for new sub-sequence */ | ||
285 | |||
286 | if (nseq->first_free == nseq->alloc) { | ||
287 | struct sub_seq *sseqs = nseq->sseqs; | ||
288 | nseq->sseqs = subseq_alloc(nseq->alloc * 2); | ||
289 | if (nseq->sseqs != NULL) { | ||
290 | memcpy(nseq->sseqs, sseqs, | ||
291 | nseq->alloc * sizeof (struct sub_seq)); | ||
292 | kfree(sseqs); | ||
293 | dbg("Allocated %u sseqs\n", nseq->alloc); | ||
294 | nseq->alloc *= 2; | ||
295 | } else { | ||
296 | warn("Memory squeeze; failed to create sub-sequence\n"); | ||
297 | return 0; | ||
298 | } | ||
299 | } | ||
300 | dbg("Have %u sseqs for type %u\n", nseq->alloc, type); | ||
301 | |||
302 | /* Insert new sub-sequence */ | ||
303 | |||
304 | dbg("ins in pos %u, ff = %u\n", inspos, nseq->first_free); | ||
305 | sseq = &nseq->sseqs[inspos]; | ||
306 | freesseq = &nseq->sseqs[nseq->first_free]; | ||
307 | memmove(sseq + 1, sseq, (freesseq - sseq) * sizeof (*sseq)); | ||
308 | memset(sseq, 0, sizeof (*sseq)); | ||
309 | nseq->first_free++; | ||
310 | sseq->lower = lower; | ||
311 | sseq->upper = upper; | ||
312 | created_subseq = 1; | ||
313 | } | ||
314 | dbg("inserting (%u %u %u) from %x:%u into sseq %x(%u,%u) of seq %x\n", | ||
315 | type, lower, upper, node, port, sseq, | ||
316 | sseq->lower, sseq->upper, nseq); | ||
317 | |||
318 | /* Insert a publication: */ | ||
319 | |||
320 | publ = publ_create(type, lower, upper, scope, node, port, key); | ||
321 | if (!publ) | ||
322 | return 0; | ||
323 | dbg("inserting publ %x, node=%x publ->node=%x, subscr->node=%x\n", | ||
324 | publ, node, publ->node, publ->subscr.node); | ||
325 | |||
326 | if (!sseq->zone_list) | ||
327 | sseq->zone_list = publ->zone_list_next = publ; | ||
328 | else { | ||
329 | publ->zone_list_next = sseq->zone_list->zone_list_next; | ||
330 | sseq->zone_list->zone_list_next = publ; | ||
331 | } | ||
332 | |||
333 | if (in_own_cluster(node)) { | ||
334 | if (!sseq->cluster_list) | ||
335 | sseq->cluster_list = publ->cluster_list_next = publ; | ||
336 | else { | ||
337 | publ->cluster_list_next = | ||
338 | sseq->cluster_list->cluster_list_next; | ||
339 | sseq->cluster_list->cluster_list_next = publ; | ||
340 | } | ||
341 | } | ||
342 | |||
343 | if (node == tipc_own_addr) { | ||
344 | if (!sseq->node_list) | ||
345 | sseq->node_list = publ->node_list_next = publ; | ||
346 | else { | ||
347 | publ->node_list_next = sseq->node_list->node_list_next; | ||
348 | sseq->node_list->node_list_next = publ; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | /* | ||
353 | * Any subscriptions waiting for notification? | ||
354 | */ | ||
355 | list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { | ||
356 | dbg("calling report_overlap()\n"); | ||
357 | subscr_report_overlap(s, | ||
358 | publ->lower, | ||
359 | publ->upper, | ||
360 | TIPC_PUBLISHED, | ||
361 | publ->ref, | ||
362 | publ->node, | ||
363 | created_subseq); | ||
364 | } | ||
365 | return publ; | ||
366 | } | ||
367 | |||
368 | /** | ||
369 | * nameseq_remove_publ - | ||
370 | */ | ||
371 | |||
372 | struct publication *nameseq_remove_publ(struct name_seq *nseq, u32 inst, | ||
373 | u32 node, u32 ref, u32 key) | ||
374 | { | ||
375 | struct publication *publ; | ||
376 | struct publication *prev; | ||
377 | struct sub_seq *sseq = nameseq_find_subseq(nseq, inst); | ||
378 | struct sub_seq *free; | ||
379 | struct subscription *s, *st; | ||
380 | int removed_subseq = 0; | ||
381 | |||
382 | assert(nseq); | ||
383 | |||
384 | if (!sseq) { | ||
385 | int i; | ||
386 | |||
387 | warn("Withdraw unknown <%u,%u>?\n", nseq->type, inst); | ||
388 | assert(nseq->sseqs); | ||
389 | dbg("Dumping subseqs %x for %x, alloc = %u,ff=%u\n", | ||
390 | nseq->sseqs, nseq, nseq->alloc, | ||
391 | nseq->first_free); | ||
392 | for (i = 0; i < nseq->first_free; i++) { | ||
393 | dbg("Subseq %u(%x): lower = %u,upper = %u\n", | ||
394 | i, &nseq->sseqs[i], nseq->sseqs[i].lower, | ||
395 | nseq->sseqs[i].upper); | ||
396 | } | ||
397 | return 0; | ||
398 | } | ||
399 | dbg("nameseq_remove: seq: %x, sseq %x, <%u,%u> key %u\n", | ||
400 | nseq, sseq, nseq->type, inst, key); | ||
401 | |||
402 | prev = sseq->zone_list; | ||
403 | publ = sseq->zone_list->zone_list_next; | ||
404 | while ((publ->key != key) || (publ->ref != ref) || | ||
405 | (publ->node && (publ->node != node))) { | ||
406 | prev = publ; | ||
407 | publ = publ->zone_list_next; | ||
408 | assert(prev != sseq->zone_list); | ||
409 | } | ||
410 | if (publ != sseq->zone_list) | ||
411 | prev->zone_list_next = publ->zone_list_next; | ||
412 | else if (publ->zone_list_next != publ) { | ||
413 | prev->zone_list_next = publ->zone_list_next; | ||
414 | sseq->zone_list = publ->zone_list_next; | ||
415 | } else { | ||
416 | sseq->zone_list = 0; | ||
417 | } | ||
418 | |||
419 | if (in_own_cluster(node)) { | ||
420 | prev = sseq->cluster_list; | ||
421 | publ = sseq->cluster_list->cluster_list_next; | ||
422 | while ((publ->key != key) || (publ->ref != ref) || | ||
423 | (publ->node && (publ->node != node))) { | ||
424 | prev = publ; | ||
425 | publ = publ->cluster_list_next; | ||
426 | assert(prev != sseq->cluster_list); | ||
427 | } | ||
428 | if (publ != sseq->cluster_list) | ||
429 | prev->cluster_list_next = publ->cluster_list_next; | ||
430 | else if (publ->cluster_list_next != publ) { | ||
431 | prev->cluster_list_next = publ->cluster_list_next; | ||
432 | sseq->cluster_list = publ->cluster_list_next; | ||
433 | } else { | ||
434 | sseq->cluster_list = 0; | ||
435 | } | ||
436 | } | ||
437 | |||
438 | if (node == tipc_own_addr) { | ||
439 | prev = sseq->node_list; | ||
440 | publ = sseq->node_list->node_list_next; | ||
441 | while ((publ->key != key) || (publ->ref != ref) || | ||
442 | (publ->node && (publ->node != node))) { | ||
443 | prev = publ; | ||
444 | publ = publ->node_list_next; | ||
445 | assert(prev != sseq->node_list); | ||
446 | } | ||
447 | if (publ != sseq->node_list) | ||
448 | prev->node_list_next = publ->node_list_next; | ||
449 | else if (publ->node_list_next != publ) { | ||
450 | prev->node_list_next = publ->node_list_next; | ||
451 | sseq->node_list = publ->node_list_next; | ||
452 | } else { | ||
453 | sseq->node_list = 0; | ||
454 | } | ||
455 | } | ||
456 | assert(!publ->node || (publ->node == node)); | ||
457 | assert(publ->ref == ref); | ||
458 | assert(publ->key == key); | ||
459 | |||
460 | /* | ||
461 | * Contract subseq list if no more publications: | ||
462 | */ | ||
463 | if (!sseq->node_list && !sseq->cluster_list && !sseq->zone_list) { | ||
464 | free = &nseq->sseqs[nseq->first_free--]; | ||
465 | memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq)); | ||
466 | removed_subseq = 1; | ||
467 | } | ||
468 | |||
469 | /* | ||
470 | * Any subscriptions waiting ? | ||
471 | */ | ||
472 | list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { | ||
473 | subscr_report_overlap(s, | ||
474 | publ->lower, | ||
475 | publ->upper, | ||
476 | TIPC_WITHDRAWN, | ||
477 | publ->ref, | ||
478 | publ->node, | ||
479 | removed_subseq); | ||
480 | } | ||
481 | return publ; | ||
482 | } | ||
483 | |||
484 | /** | ||
485 | * nameseq_subscribe: attach a subscription, and issue | ||
486 | * the prescribed number of events if there is any sub- | ||
487 | * sequence overlapping with the requested sequence | ||
488 | */ | ||
489 | |||
490 | void nameseq_subscribe(struct name_seq *nseq, struct subscription *s) | ||
491 | { | ||
492 | struct sub_seq *sseq = nseq->sseqs; | ||
493 | |||
494 | list_add(&s->nameseq_list, &nseq->subscriptions); | ||
495 | |||
496 | if (!sseq) | ||
497 | return; | ||
498 | |||
499 | while (sseq != &nseq->sseqs[nseq->first_free]) { | ||
500 | struct publication *zl = sseq->zone_list; | ||
501 | if (zl && subscr_overlap(s,sseq->lower,sseq->upper)) { | ||
502 | struct publication *crs = zl; | ||
503 | int must_report = 1; | ||
504 | |||
505 | do { | ||
506 | subscr_report_overlap(s, | ||
507 | sseq->lower, | ||
508 | sseq->upper, | ||
509 | TIPC_PUBLISHED, | ||
510 | crs->ref, | ||
511 | crs->node, | ||
512 | must_report); | ||
513 | must_report = 0; | ||
514 | crs = crs->zone_list_next; | ||
515 | } while (crs != zl); | ||
516 | } | ||
517 | sseq++; | ||
518 | } | ||
519 | } | ||
520 | |||
521 | static struct name_seq *nametbl_find_seq(u32 type) | ||
522 | { | ||
523 | struct hlist_head *seq_head; | ||
524 | struct hlist_node *seq_node; | ||
525 | struct name_seq *ns; | ||
526 | |||
527 | dbg("find_seq %u,(%u,0x%x) table = %p, hash[type] = %u\n", | ||
528 | type, ntohl(type), type, table.types, hash(type)); | ||
529 | |||
530 | seq_head = &table.types[hash(type)]; | ||
531 | hlist_for_each_entry(ns, seq_node, seq_head, ns_list) { | ||
532 | if (ns->type == type) { | ||
533 | dbg("found %x\n", ns); | ||
534 | return ns; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | return 0; | ||
539 | }; | ||
540 | |||
541 | struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper, | ||
542 | u32 scope, u32 node, u32 port, u32 key) | ||
543 | { | ||
544 | struct name_seq *seq = nametbl_find_seq(type); | ||
545 | |||
546 | dbg("ins_publ: <%u,%x,%x> found %x\n", type, lower, upper, seq); | ||
547 | if (lower > upper) { | ||
548 | warn("Failed to publish illegal <%u,%u,%u>\n", | ||
549 | type, lower, upper); | ||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node); | ||
554 | if (!seq) { | ||
555 | seq = nameseq_create(type, &table.types[hash(type)]); | ||
556 | dbg("nametbl_insert_publ: created %x\n", seq); | ||
557 | } | ||
558 | if (!seq) | ||
559 | return 0; | ||
560 | |||
561 | assert(seq->type == type); | ||
562 | return nameseq_insert_publ(seq, type, lower, upper, | ||
563 | scope, node, port, key); | ||
564 | } | ||
565 | |||
566 | struct publication *nametbl_remove_publ(u32 type, u32 lower, | ||
567 | u32 node, u32 ref, u32 key) | ||
568 | { | ||
569 | struct publication *publ; | ||
570 | struct name_seq *seq = nametbl_find_seq(type); | ||
571 | |||
572 | if (!seq) | ||
573 | return 0; | ||
574 | |||
575 | dbg("Withdrawing <%u,%u> from %x\n", type, lower, node); | ||
576 | publ = nameseq_remove_publ(seq, lower, node, ref, key); | ||
577 | |||
578 | if (!seq->first_free && list_empty(&seq->subscriptions)) { | ||
579 | hlist_del_init(&seq->ns_list); | ||
580 | kfree(seq->sseqs); | ||
581 | kfree(seq); | ||
582 | } | ||
583 | return publ; | ||
584 | } | ||
585 | |||
586 | /* | ||
587 | * nametbl_translate(): Translate tipc_name -> tipc_portid. | ||
588 | * Very time-critical. | ||
589 | * | ||
590 | * Note: on entry 'destnode' is the search domain used during translation; | ||
591 | * on exit it passes back the node address of the matching port (if any) | ||
592 | */ | ||
593 | |||
594 | u32 nametbl_translate(u32 type, u32 instance, u32 *destnode) | ||
595 | { | ||
596 | struct sub_seq *sseq; | ||
597 | struct publication *publ = 0; | ||
598 | struct name_seq *seq; | ||
599 | u32 ref; | ||
600 | |||
601 | if (!in_scope(*destnode, tipc_own_addr)) | ||
602 | return 0; | ||
603 | |||
604 | read_lock_bh(&nametbl_lock); | ||
605 | seq = nametbl_find_seq(type); | ||
606 | if (unlikely(!seq)) | ||
607 | goto not_found; | ||
608 | sseq = nameseq_find_subseq(seq, instance); | ||
609 | if (unlikely(!sseq)) | ||
610 | goto not_found; | ||
611 | spin_lock_bh(&seq->lock); | ||
612 | |||
613 | /* Closest-First Algorithm: */ | ||
614 | if (likely(!*destnode)) { | ||
615 | publ = sseq->node_list; | ||
616 | if (publ) { | ||
617 | sseq->node_list = publ->node_list_next; | ||
618 | found: | ||
619 | ref = publ->ref; | ||
620 | *destnode = publ->node; | ||
621 | spin_unlock_bh(&seq->lock); | ||
622 | read_unlock_bh(&nametbl_lock); | ||
623 | return ref; | ||
624 | } | ||
625 | publ = sseq->cluster_list; | ||
626 | if (publ) { | ||
627 | sseq->cluster_list = publ->cluster_list_next; | ||
628 | goto found; | ||
629 | } | ||
630 | publ = sseq->zone_list; | ||
631 | if (publ) { | ||
632 | sseq->zone_list = publ->zone_list_next; | ||
633 | goto found; | ||
634 | } | ||
635 | } | ||
636 | |||
637 | /* Round-Robin Algorithm: */ | ||
638 | else if (*destnode == tipc_own_addr) { | ||
639 | publ = sseq->node_list; | ||
640 | if (publ) { | ||
641 | sseq->node_list = publ->node_list_next; | ||
642 | goto found; | ||
643 | } | ||
644 | } else if (in_own_cluster(*destnode)) { | ||
645 | publ = sseq->cluster_list; | ||
646 | if (publ) { | ||
647 | sseq->cluster_list = publ->cluster_list_next; | ||
648 | goto found; | ||
649 | } | ||
650 | } else { | ||
651 | publ = sseq->zone_list; | ||
652 | if (publ) { | ||
653 | sseq->zone_list = publ->zone_list_next; | ||
654 | goto found; | ||
655 | } | ||
656 | } | ||
657 | spin_unlock_bh(&seq->lock); | ||
658 | not_found: | ||
659 | *destnode = 0; | ||
660 | read_unlock_bh(&nametbl_lock); | ||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | /** | ||
665 | * nametbl_mc_translate - find multicast destinations | ||
666 | * | ||
667 | * Creates list of all local ports that overlap the given multicast address; | ||
668 | * also determines if any off-node ports overlap. | ||
669 | * | ||
670 | * Note: Publications with a scope narrower than 'limit' are ignored. | ||
671 | * (i.e. local node-scope publications mustn't receive messages arriving | ||
672 | * from another node, even if the multcast link brought it here) | ||
673 | * | ||
674 | * Returns non-zero if any off-node ports overlap | ||
675 | */ | ||
676 | |||
677 | int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, | ||
678 | struct port_list *dports) | ||
679 | { | ||
680 | struct name_seq *seq; | ||
681 | struct sub_seq *sseq; | ||
682 | struct sub_seq *sseq_stop; | ||
683 | int res = 0; | ||
684 | |||
685 | read_lock_bh(&nametbl_lock); | ||
686 | seq = nametbl_find_seq(type); | ||
687 | if (!seq) | ||
688 | goto exit; | ||
689 | |||
690 | spin_lock_bh(&seq->lock); | ||
691 | |||
692 | sseq = seq->sseqs + nameseq_locate_subseq(seq, lower); | ||
693 | sseq_stop = seq->sseqs + seq->first_free; | ||
694 | for (; sseq != sseq_stop; sseq++) { | ||
695 | struct publication *publ; | ||
696 | |||
697 | if (sseq->lower > upper) | ||
698 | break; | ||
699 | publ = sseq->cluster_list; | ||
700 | if (publ && (publ->scope <= limit)) | ||
701 | do { | ||
702 | if (publ->node == tipc_own_addr) | ||
703 | port_list_add(dports, publ->ref); | ||
704 | else | ||
705 | res = 1; | ||
706 | publ = publ->cluster_list_next; | ||
707 | } while (publ != sseq->cluster_list); | ||
708 | } | ||
709 | |||
710 | spin_unlock_bh(&seq->lock); | ||
711 | exit: | ||
712 | read_unlock_bh(&nametbl_lock); | ||
713 | return res; | ||
714 | } | ||
715 | |||
716 | /** | ||
717 | * nametbl_publish_rsv - publish port name using a reserved name type | ||
718 | */ | ||
719 | |||
720 | int nametbl_publish_rsv(u32 ref, unsigned int scope, | ||
721 | struct tipc_name_seq const *seq) | ||
722 | { | ||
723 | int res; | ||
724 | |||
725 | atomic_inc(&rsv_publ_ok); | ||
726 | res = tipc_publish(ref, scope, seq); | ||
727 | atomic_dec(&rsv_publ_ok); | ||
728 | return res; | ||
729 | } | ||
730 | |||
731 | /** | ||
732 | * nametbl_publish - add name publication to network name tables | ||
733 | */ | ||
734 | |||
735 | struct publication *nametbl_publish(u32 type, u32 lower, u32 upper, | ||
736 | u32 scope, u32 port_ref, u32 key) | ||
737 | { | ||
738 | struct publication *publ; | ||
739 | |||
740 | if (table.local_publ_count >= tipc_max_publications) { | ||
741 | warn("Failed publish: max %u local publication\n", | ||
742 | tipc_max_publications); | ||
743 | return 0; | ||
744 | } | ||
745 | if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) { | ||
746 | warn("Failed to publish reserved name <%u,%u,%u>\n", | ||
747 | type, lower, upper); | ||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | write_lock_bh(&nametbl_lock); | ||
752 | table.local_publ_count++; | ||
753 | publ = nametbl_insert_publ(type, lower, upper, scope, | ||
754 | tipc_own_addr, port_ref, key); | ||
755 | if (publ && (scope != TIPC_NODE_SCOPE)) { | ||
756 | named_publish(publ); | ||
757 | } | ||
758 | write_unlock_bh(&nametbl_lock); | ||
759 | return publ; | ||
760 | } | ||
761 | |||
762 | /** | ||
763 | * nametbl_withdraw - withdraw name publication from network name tables | ||
764 | */ | ||
765 | |||
766 | int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) | ||
767 | { | ||
768 | struct publication *publ; | ||
769 | |||
770 | dbg("nametbl_withdraw:<%d,%d,%d>\n", type, lower, key); | ||
771 | write_lock_bh(&nametbl_lock); | ||
772 | publ = nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); | ||
773 | if (publ) { | ||
774 | table.local_publ_count--; | ||
775 | if (publ->scope != TIPC_NODE_SCOPE) | ||
776 | named_withdraw(publ); | ||
777 | write_unlock_bh(&nametbl_lock); | ||
778 | list_del_init(&publ->pport_list); | ||
779 | kfree(publ); | ||
780 | return 1; | ||
781 | } | ||
782 | write_unlock_bh(&nametbl_lock); | ||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | /** | ||
787 | * nametbl_subscribe - add a subscription object to the name table | ||
788 | */ | ||
789 | |||
790 | void | ||
791 | nametbl_subscribe(struct subscription *s) | ||
792 | { | ||
793 | u32 type = s->seq.type; | ||
794 | struct name_seq *seq; | ||
795 | |||
796 | write_lock_bh(&nametbl_lock); | ||
797 | seq = nametbl_find_seq(type); | ||
798 | if (!seq) { | ||
799 | seq = nameseq_create(type, &table.types[hash(type)]); | ||
800 | } | ||
801 | if (seq){ | ||
802 | spin_lock_bh(&seq->lock); | ||
803 | dbg("nametbl_subscribe:found %x for <%u,%u,%u>\n", | ||
804 | seq, type, s->seq.lower, s->seq.upper); | ||
805 | assert(seq->type == type); | ||
806 | nameseq_subscribe(seq, s); | ||
807 | spin_unlock_bh(&seq->lock); | ||
808 | } | ||
809 | write_unlock_bh(&nametbl_lock); | ||
810 | } | ||
811 | |||
812 | /** | ||
813 | * nametbl_unsubscribe - remove a subscription object from name table | ||
814 | */ | ||
815 | |||
816 | void | ||
817 | nametbl_unsubscribe(struct subscription *s) | ||
818 | { | ||
819 | struct name_seq *seq; | ||
820 | |||
821 | write_lock_bh(&nametbl_lock); | ||
822 | seq = nametbl_find_seq(s->seq.type); | ||
823 | if (seq != NULL){ | ||
824 | spin_lock_bh(&seq->lock); | ||
825 | list_del_init(&s->nameseq_list); | ||
826 | spin_unlock_bh(&seq->lock); | ||
827 | if ((seq->first_free == 0) && list_empty(&seq->subscriptions)) { | ||
828 | hlist_del_init(&seq->ns_list); | ||
829 | kfree(seq->sseqs); | ||
830 | kfree(seq); | ||
831 | } | ||
832 | } | ||
833 | write_unlock_bh(&nametbl_lock); | ||
834 | } | ||
835 | |||
836 | |||
837 | /** | ||
838 | * subseq_list: print specified sub-sequence contents into the given buffer | ||
839 | */ | ||
840 | |||
841 | static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, | ||
842 | u32 index) | ||
843 | { | ||
844 | char portIdStr[27]; | ||
845 | char *scopeStr; | ||
846 | struct publication *publ = sseq->zone_list; | ||
847 | |||
848 | tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper); | ||
849 | |||
850 | if (depth == 2 || !publ) { | ||
851 | tipc_printf(buf, "\n"); | ||
852 | return; | ||
853 | } | ||
854 | |||
855 | do { | ||
856 | sprintf (portIdStr, "<%u.%u.%u:%u>", | ||
857 | tipc_zone(publ->node), tipc_cluster(publ->node), | ||
858 | tipc_node(publ->node), publ->ref); | ||
859 | tipc_printf(buf, "%-26s ", portIdStr); | ||
860 | if (depth > 3) { | ||
861 | if (publ->node != tipc_own_addr) | ||
862 | scopeStr = ""; | ||
863 | else if (publ->scope == TIPC_NODE_SCOPE) | ||
864 | scopeStr = "node"; | ||
865 | else if (publ->scope == TIPC_CLUSTER_SCOPE) | ||
866 | scopeStr = "cluster"; | ||
867 | else | ||
868 | scopeStr = "zone"; | ||
869 | tipc_printf(buf, "%-10u %s", publ->key, scopeStr); | ||
870 | } | ||
871 | |||
872 | publ = publ->zone_list_next; | ||
873 | if (publ == sseq->zone_list) | ||
874 | break; | ||
875 | |||
876 | tipc_printf(buf, "\n%33s", " "); | ||
877 | } while (1); | ||
878 | |||
879 | tipc_printf(buf, "\n"); | ||
880 | } | ||
881 | |||
882 | /** | ||
883 | * nameseq_list: print specified name sequence contents into the given buffer | ||
884 | */ | ||
885 | |||
886 | static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth, | ||
887 | u32 type, u32 lowbound, u32 upbound, u32 index) | ||
888 | { | ||
889 | struct sub_seq *sseq; | ||
890 | char typearea[11]; | ||
891 | |||
892 | sprintf(typearea, "%-10u", seq->type); | ||
893 | |||
894 | if (depth == 1) { | ||
895 | tipc_printf(buf, "%s\n", typearea); | ||
896 | return; | ||
897 | } | ||
898 | |||
899 | for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) { | ||
900 | if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) { | ||
901 | tipc_printf(buf, "%s ", typearea); | ||
902 | subseq_list(sseq, buf, depth, index); | ||
903 | sprintf(typearea, "%10s", " "); | ||
904 | } | ||
905 | } | ||
906 | } | ||
907 | |||
908 | /** | ||
909 | * nametbl_header - print name table header into the given buffer | ||
910 | */ | ||
911 | |||
912 | static void nametbl_header(struct print_buf *buf, u32 depth) | ||
913 | { | ||
914 | tipc_printf(buf, "Type "); | ||
915 | |||
916 | if (depth > 1) | ||
917 | tipc_printf(buf, "Lower Upper "); | ||
918 | if (depth > 2) | ||
919 | tipc_printf(buf, "Port Identity "); | ||
920 | if (depth > 3) | ||
921 | tipc_printf(buf, "Publication"); | ||
922 | |||
923 | tipc_printf(buf, "\n-----------"); | ||
924 | |||
925 | if (depth > 1) | ||
926 | tipc_printf(buf, "--------------------- "); | ||
927 | if (depth > 2) | ||
928 | tipc_printf(buf, "-------------------------- "); | ||
929 | if (depth > 3) | ||
930 | tipc_printf(buf, "------------------"); | ||
931 | |||
932 | tipc_printf(buf, "\n"); | ||
933 | } | ||
934 | |||
935 | /** | ||
936 | * nametbl_list - print specified name table contents into the given buffer | ||
937 | */ | ||
938 | |||
939 | static void nametbl_list(struct print_buf *buf, u32 depth_info, | ||
940 | u32 type, u32 lowbound, u32 upbound) | ||
941 | { | ||
942 | struct hlist_head *seq_head; | ||
943 | struct hlist_node *seq_node; | ||
944 | struct name_seq *seq; | ||
945 | int all_types; | ||
946 | u32 depth; | ||
947 | u32 i; | ||
948 | |||
949 | all_types = (depth_info & TIPC_NTQ_ALLTYPES); | ||
950 | depth = (depth_info & ~TIPC_NTQ_ALLTYPES); | ||
951 | |||
952 | if (depth == 0) | ||
953 | return; | ||
954 | |||
955 | if (all_types) { | ||
956 | /* display all entries in name table to specified depth */ | ||
957 | nametbl_header(buf, depth); | ||
958 | lowbound = 0; | ||
959 | upbound = ~0; | ||
960 | for (i = 0; i < tipc_nametbl_size; i++) { | ||
961 | seq_head = &table.types[i]; | ||
962 | hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { | ||
963 | nameseq_list(seq, buf, depth, seq->type, | ||
964 | lowbound, upbound, i); | ||
965 | } | ||
966 | } | ||
967 | } else { | ||
968 | /* display only the sequence that matches the specified type */ | ||
969 | if (upbound < lowbound) { | ||
970 | tipc_printf(buf, "invalid name sequence specified\n"); | ||
971 | return; | ||
972 | } | ||
973 | nametbl_header(buf, depth); | ||
974 | i = hash(type); | ||
975 | seq_head = &table.types[i]; | ||
976 | hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { | ||
977 | if (seq->type == type) { | ||
978 | nameseq_list(seq, buf, depth, type, | ||
979 | lowbound, upbound, i); | ||
980 | break; | ||
981 | } | ||
982 | } | ||
983 | } | ||
984 | } | ||
985 | |||
986 | void nametbl_print(struct print_buf *buf, const char *str) | ||
987 | { | ||
988 | tipc_printf(buf, str); | ||
989 | read_lock_bh(&nametbl_lock); | ||
990 | nametbl_list(buf, 0, 0, 0, 0); | ||
991 | read_unlock_bh(&nametbl_lock); | ||
992 | } | ||
993 | |||
994 | #define MAX_NAME_TBL_QUERY 32768 | ||
995 | |||
996 | struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space) | ||
997 | { | ||
998 | struct sk_buff *buf; | ||
999 | struct tipc_name_table_query *argv; | ||
1000 | struct tlv_desc *rep_tlv; | ||
1001 | struct print_buf b; | ||
1002 | int str_len; | ||
1003 | |||
1004 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY)) | ||
1005 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
1006 | |||
1007 | buf = cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY)); | ||
1008 | if (!buf) | ||
1009 | return NULL; | ||
1010 | |||
1011 | rep_tlv = (struct tlv_desc *)buf->data; | ||
1012 | printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY); | ||
1013 | argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area); | ||
1014 | read_lock_bh(&nametbl_lock); | ||
1015 | nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type), | ||
1016 | ntohl(argv->lowbound), ntohl(argv->upbound)); | ||
1017 | read_unlock_bh(&nametbl_lock); | ||
1018 | str_len = printbuf_validate(&b); | ||
1019 | |||
1020 | skb_put(buf, TLV_SPACE(str_len)); | ||
1021 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | ||
1022 | |||
1023 | return buf; | ||
1024 | } | ||
1025 | |||
1026 | void nametbl_dump(void) | ||
1027 | { | ||
1028 | nametbl_list(CONS, 0, 0, 0, 0); | ||
1029 | } | ||
1030 | |||
1031 | int nametbl_init(void) | ||
1032 | { | ||
1033 | int array_size = sizeof(struct hlist_head) * tipc_nametbl_size; | ||
1034 | |||
1035 | table.types = (struct hlist_head *)kmalloc(array_size, GFP_ATOMIC); | ||
1036 | if (!table.types) | ||
1037 | return -ENOMEM; | ||
1038 | |||
1039 | write_lock_bh(&nametbl_lock); | ||
1040 | memset(table.types, 0, array_size); | ||
1041 | table.local_publ_count = 0; | ||
1042 | write_unlock_bh(&nametbl_lock); | ||
1043 | return 0; | ||
1044 | } | ||
1045 | |||
1046 | void nametbl_stop(void) | ||
1047 | { | ||
1048 | struct hlist_head *seq_head; | ||
1049 | struct hlist_node *seq_node; | ||
1050 | struct hlist_node *tmp; | ||
1051 | struct name_seq *seq; | ||
1052 | u32 i; | ||
1053 | |||
1054 | if (!table.types) | ||
1055 | return; | ||
1056 | |||
1057 | write_lock_bh(&nametbl_lock); | ||
1058 | for (i = 0; i < tipc_nametbl_size; i++) { | ||
1059 | seq_head = &table.types[i]; | ||
1060 | hlist_for_each_entry_safe(seq, seq_node, tmp, seq_head, ns_list) { | ||
1061 | struct sub_seq *sseq = seq->sseqs; | ||
1062 | |||
1063 | for (; sseq != &seq->sseqs[seq->first_free]; sseq++) { | ||
1064 | struct publication *publ = sseq->zone_list; | ||
1065 | assert(publ); | ||
1066 | do { | ||
1067 | struct publication *next = | ||
1068 | publ->zone_list_next; | ||
1069 | kfree(publ); | ||
1070 | publ = next; | ||
1071 | } | ||
1072 | while (publ != sseq->zone_list); | ||
1073 | } | ||
1074 | } | ||
1075 | } | ||
1076 | kfree(table.types); | ||
1077 | table.types = NULL; | ||
1078 | write_unlock_bh(&nametbl_lock); | ||
1079 | } | ||
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h new file mode 100644 index 000000000000..f82693384f60 --- /dev/null +++ b/net/tipc/name_table.h | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * net/tipc/name_table.h: Include file for TIPC name table code | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_NAME_TABLE_H | ||
38 | #define _TIPC_NAME_TABLE_H | ||
39 | |||
40 | #include "node_subscr.h" | ||
41 | |||
42 | struct subscription; | ||
43 | struct port_list; | ||
44 | |||
45 | /* | ||
46 | * TIPC name types reserved for internal TIPC use (both current and planned) | ||
47 | */ | ||
48 | |||
49 | #define TIPC_ZM_SRV 3 /* zone master service name type */ | ||
50 | |||
51 | |||
52 | /** | ||
53 | * struct publication - info about a published (name or) name sequence | ||
54 | * @type: name sequence type | ||
55 | * @lower: name sequence lower bound | ||
56 | * @upper: name sequence upper bound | ||
57 | * @scope: scope of publication | ||
58 | * @node: network address of publishing port's node | ||
59 | * @ref: publishing port | ||
60 | * @key: publication key | ||
61 | * @subscr: subscription to "node down" event (for off-node publications only) | ||
62 | * @local_list: adjacent entries in list of publications made by this node | ||
63 | * @pport_list: adjacent entries in list of publications made by this port | ||
64 | * @node_list: next matching name seq publication with >= node scope | ||
65 | * @cluster_list: next matching name seq publication with >= cluster scope | ||
66 | * @zone_list: next matching name seq publication with >= zone scope | ||
67 | * | ||
68 | * Note that the node list, cluster list, and zone list are circular lists. | ||
69 | */ | ||
70 | |||
71 | struct publication { | ||
72 | u32 type; | ||
73 | u32 lower; | ||
74 | u32 upper; | ||
75 | u32 scope; | ||
76 | u32 node; | ||
77 | u32 ref; | ||
78 | u32 key; | ||
79 | struct node_subscr subscr; | ||
80 | struct list_head local_list; | ||
81 | struct list_head pport_list; | ||
82 | struct publication *node_list_next; | ||
83 | struct publication *cluster_list_next; | ||
84 | struct publication *zone_list_next; | ||
85 | }; | ||
86 | |||
87 | |||
88 | extern rwlock_t nametbl_lock; | ||
89 | |||
90 | struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space); | ||
91 | u32 nametbl_translate(u32 type, u32 instance, u32 *node); | ||
92 | int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, | ||
93 | struct port_list *dports); | ||
94 | int nametbl_publish_rsv(u32 ref, unsigned int scope, | ||
95 | struct tipc_name_seq const *seq); | ||
96 | struct publication *nametbl_publish(u32 type, u32 lower, u32 upper, | ||
97 | u32 scope, u32 port_ref, u32 key); | ||
98 | int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key); | ||
99 | struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper, | ||
100 | u32 scope, u32 node, u32 ref, u32 key); | ||
101 | struct publication *nametbl_remove_publ(u32 type, u32 lower, | ||
102 | u32 node, u32 ref, u32 key); | ||
103 | void nametbl_subscribe(struct subscription *s); | ||
104 | void nametbl_unsubscribe(struct subscription *s); | ||
105 | int nametbl_init(void); | ||
106 | void nametbl_stop(void); | ||
107 | |||
108 | #endif | ||
diff --git a/net/tipc/net.c b/net/tipc/net.c new file mode 100644 index 000000000000..6826b493c1d6 --- /dev/null +++ b/net/tipc/net.c | |||
@@ -0,0 +1,311 @@ | |||
1 | /* | ||
2 | * net/tipc/net.c: TIPC network routing code | ||
3 | * | ||
4 | * Copyright (c) 1995-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "bearer.h" | ||
39 | #include "net.h" | ||
40 | #include "zone.h" | ||
41 | #include "addr.h" | ||
42 | #include "name_table.h" | ||
43 | #include "name_distr.h" | ||
44 | #include "subscr.h" | ||
45 | #include "link.h" | ||
46 | #include "msg.h" | ||
47 | #include "port.h" | ||
48 | #include "bcast.h" | ||
49 | #include "discover.h" | ||
50 | #include "config.h" | ||
51 | |||
52 | /* | ||
53 | * The TIPC locking policy is designed to ensure a very fine locking | ||
54 | * granularity, permitting complete parallel access to individual | ||
55 | * port and node/link instances. The code consists of three major | ||
56 | * locking domains, each protected with their own disjunct set of locks. | ||
57 | * | ||
58 | * 1: The routing hierarchy. | ||
59 | * Comprises the structures 'zone', 'cluster', 'node', 'link' | ||
60 | * and 'bearer'. The whole hierarchy is protected by a big | ||
61 | * read/write lock, net_lock, to enssure that nothing is added | ||
62 | * or removed while code is accessing any of these structures. | ||
63 | * This layer must not be called from the two others while they | ||
64 | * hold any of their own locks. | ||
65 | * Neither must it itself do any upcalls to the other two before | ||
66 | * it has released net_lock and other protective locks. | ||
67 | * | ||
68 | * Within the net_lock domain there are two sub-domains;'node' and | ||
69 | * 'bearer', where local write operations are permitted, | ||
70 | * provided that those are protected by individual spin_locks | ||
71 | * per instance. Code holding net_lock(read) and a node spin_lock | ||
72 | * is permitted to poke around in both the node itself and its | ||
73 | * subordinate links. I.e, it can update link counters and queues, | ||
74 | * change link state, send protocol messages, and alter the | ||
75 | * "active_links" array in the node; but it can _not_ remove a link | ||
76 | * or a node from the overall structure. | ||
77 | * Correspondingly, individual bearers may change status within a | ||
78 | * net_lock(read), protected by an individual spin_lock ber bearer | ||
79 | * instance, but it needs net_lock(write) to remove/add any bearers. | ||
80 | * | ||
81 | * | ||
82 | * 2: The transport level of the protocol. | ||
83 | * This consists of the structures port, (and its user level | ||
84 | * representations, such as user_port and tipc_sock), reference and | ||
85 | * tipc_user (port.c, reg.c, socket.c). | ||
86 | * | ||
87 | * This layer has four different locks: | ||
88 | * - The tipc_port spin_lock. This is protecting each port instance | ||
89 | * from parallel data access and removal. Since we can not place | ||
90 | * this lock in the port itself, it has been placed in the | ||
91 | * corresponding reference table entry, which has the same life | ||
92 | * cycle as the module. This entry is difficult to access from | ||
93 | * outside the TIPC core, however, so a pointer to the lock has | ||
94 | * been added in the port instance, -to be used for unlocking | ||
95 | * only. | ||
96 | * - A read/write lock to protect the reference table itself (teg.c). | ||
97 | * (Nobody is using read-only access to this, so it can just as | ||
98 | * well be changed to a spin_lock) | ||
99 | * - A spin lock to protect the registry of kernel/driver users (reg.c) | ||
100 | * - A global spin_lock (port_lock), which only task is to ensure | ||
101 | * consistency where more than one port is involved in an operation, | ||
102 | * i.e., whe a port is part of a linked list of ports. | ||
103 | * There are two such lists; 'port_list', which is used for management, | ||
104 | * and 'wait_list', which is used to queue ports during congestion. | ||
105 | * | ||
106 | * 3: The name table (name_table.c, name_distr.c, subscription.c) | ||
107 | * - There is one big read/write-lock (nametbl_lock) protecting the | ||
108 | * overall name table structure. Nothing must be added/removed to | ||
109 | * this structure without holding write access to it. | ||
110 | * - There is one local spin_lock per sub_sequence, which can be seen | ||
111 | * as a sub-domain to the nametbl_lock domain. It is used only | ||
112 | * for translation operations, and is needed because a translation | ||
113 | * steps the root of the 'publication' linked list between each lookup. | ||
114 | * This is always used within the scope of a nametbl_lock(read). | ||
115 | * - A local spin_lock protecting the queue of subscriber events. | ||
116 | */ | ||
117 | |||
118 | rwlock_t net_lock = RW_LOCK_UNLOCKED; | ||
119 | struct network net = { 0 }; | ||
120 | |||
121 | struct node *net_select_remote_node(u32 addr, u32 ref) | ||
122 | { | ||
123 | return zone_select_remote_node(net.zones[tipc_zone(addr)], addr, ref); | ||
124 | } | ||
125 | |||
126 | u32 net_select_router(u32 addr, u32 ref) | ||
127 | { | ||
128 | return zone_select_router(net.zones[tipc_zone(addr)], addr, ref); | ||
129 | } | ||
130 | |||
131 | |||
132 | u32 net_next_node(u32 a) | ||
133 | { | ||
134 | if (net.zones[tipc_zone(a)]) | ||
135 | return zone_next_node(a); | ||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | void net_remove_as_router(u32 router) | ||
140 | { | ||
141 | u32 z_num; | ||
142 | |||
143 | for (z_num = 1; z_num <= tipc_max_zones; z_num++) { | ||
144 | if (!net.zones[z_num]) | ||
145 | continue; | ||
146 | zone_remove_as_router(net.zones[z_num], router); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | void net_send_external_routes(u32 dest) | ||
151 | { | ||
152 | u32 z_num; | ||
153 | |||
154 | for (z_num = 1; z_num <= tipc_max_zones; z_num++) { | ||
155 | if (net.zones[z_num]) | ||
156 | zone_send_external_routes(net.zones[z_num], dest); | ||
157 | } | ||
158 | } | ||
159 | |||
160 | int net_init(void) | ||
161 | { | ||
162 | u32 sz = sizeof(struct _zone *) * (tipc_max_zones + 1); | ||
163 | |||
164 | memset(&net, 0, sizeof(net)); | ||
165 | net.zones = (struct _zone **)kmalloc(sz, GFP_ATOMIC); | ||
166 | if (!net.zones) { | ||
167 | return -ENOMEM; | ||
168 | } | ||
169 | memset(net.zones, 0, sz); | ||
170 | return TIPC_OK; | ||
171 | } | ||
172 | |||
173 | void net_stop(void) | ||
174 | { | ||
175 | u32 z_num; | ||
176 | |||
177 | if (!net.zones) | ||
178 | return; | ||
179 | |||
180 | for (z_num = 1; z_num <= tipc_max_zones; z_num++) { | ||
181 | zone_delete(net.zones[z_num]); | ||
182 | } | ||
183 | kfree(net.zones); | ||
184 | net.zones = 0; | ||
185 | } | ||
186 | |||
187 | static void net_route_named_msg(struct sk_buff *buf) | ||
188 | { | ||
189 | struct tipc_msg *msg = buf_msg(buf); | ||
190 | u32 dnode; | ||
191 | u32 dport; | ||
192 | |||
193 | if (!msg_named(msg)) { | ||
194 | msg_dbg(msg, "net->drop_nam:"); | ||
195 | buf_discard(buf); | ||
196 | return; | ||
197 | } | ||
198 | |||
199 | dnode = addr_domain(msg_lookup_scope(msg)); | ||
200 | dport = nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode); | ||
201 | dbg("net->lookup<%u,%u>-><%u,%x>\n", | ||
202 | msg_nametype(msg), msg_nameinst(msg), dport, dnode); | ||
203 | if (dport) { | ||
204 | msg_set_destnode(msg, dnode); | ||
205 | msg_set_destport(msg, dport); | ||
206 | net_route_msg(buf); | ||
207 | return; | ||
208 | } | ||
209 | msg_dbg(msg, "net->rej:NO NAME: "); | ||
210 | tipc_reject_msg(buf, TIPC_ERR_NO_NAME); | ||
211 | } | ||
212 | |||
213 | void net_route_msg(struct sk_buff *buf) | ||
214 | { | ||
215 | struct tipc_msg *msg; | ||
216 | u32 dnode; | ||
217 | |||
218 | if (!buf) | ||
219 | return; | ||
220 | msg = buf_msg(buf); | ||
221 | |||
222 | msg_incr_reroute_cnt(msg); | ||
223 | if (msg_reroute_cnt(msg) > 6) { | ||
224 | if (msg_errcode(msg)) { | ||
225 | msg_dbg(msg, "NET>DISC>:"); | ||
226 | buf_discard(buf); | ||
227 | } else { | ||
228 | msg_dbg(msg, "NET>REJ>:"); | ||
229 | tipc_reject_msg(buf, msg_destport(msg) ? | ||
230 | TIPC_ERR_NO_PORT : TIPC_ERR_NO_NAME); | ||
231 | } | ||
232 | return; | ||
233 | } | ||
234 | |||
235 | msg_dbg(msg, "net->rout: "); | ||
236 | |||
237 | /* Handle message for this node */ | ||
238 | dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg); | ||
239 | if (in_scope(dnode, tipc_own_addr)) { | ||
240 | if (msg_isdata(msg)) { | ||
241 | if (msg_mcast(msg)) | ||
242 | port_recv_mcast(buf, NULL); | ||
243 | else if (msg_destport(msg)) | ||
244 | port_recv_msg(buf); | ||
245 | else | ||
246 | net_route_named_msg(buf); | ||
247 | return; | ||
248 | } | ||
249 | switch (msg_user(msg)) { | ||
250 | case ROUTE_DISTRIBUTOR: | ||
251 | cluster_recv_routing_table(buf); | ||
252 | break; | ||
253 | case NAME_DISTRIBUTOR: | ||
254 | named_recv(buf); | ||
255 | break; | ||
256 | case CONN_MANAGER: | ||
257 | port_recv_proto_msg(buf); | ||
258 | break; | ||
259 | default: | ||
260 | msg_dbg(msg,"DROP/NET/<REC<"); | ||
261 | buf_discard(buf); | ||
262 | } | ||
263 | return; | ||
264 | } | ||
265 | |||
266 | /* Handle message for another node */ | ||
267 | msg_dbg(msg, "NET>SEND>: "); | ||
268 | link_send(buf, dnode, msg_link_selector(msg)); | ||
269 | } | ||
270 | |||
271 | int tipc_start_net(void) | ||
272 | { | ||
273 | char addr_string[16]; | ||
274 | int res; | ||
275 | |||
276 | if (tipc_mode != TIPC_NODE_MODE) | ||
277 | return -ENOPROTOOPT; | ||
278 | |||
279 | tipc_mode = TIPC_NET_MODE; | ||
280 | named_reinit(); | ||
281 | port_reinit(); | ||
282 | |||
283 | if ((res = bearer_init()) || | ||
284 | (res = net_init()) || | ||
285 | (res = cluster_init()) || | ||
286 | (res = bclink_init())) { | ||
287 | return res; | ||
288 | } | ||
289 | subscr_stop(); | ||
290 | cfg_stop(); | ||
291 | k_signal((Handler)subscr_start, 0); | ||
292 | k_signal((Handler)cfg_init, 0); | ||
293 | info("Started in network mode\n"); | ||
294 | info("Own node address %s, network identity %u\n", | ||
295 | addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); | ||
296 | return TIPC_OK; | ||
297 | } | ||
298 | |||
299 | void tipc_stop_net(void) | ||
300 | { | ||
301 | if (tipc_mode != TIPC_NET_MODE) | ||
302 | return; | ||
303 | write_lock_bh(&net_lock); | ||
304 | bearer_stop(); | ||
305 | tipc_mode = TIPC_NODE_MODE; | ||
306 | bclink_stop(); | ||
307 | net_stop(); | ||
308 | write_unlock_bh(&net_lock); | ||
309 | info("Left network mode \n"); | ||
310 | } | ||
311 | |||
diff --git a/net/tipc/net.h b/net/tipc/net.h new file mode 100644 index 000000000000..948c6d42102c --- /dev/null +++ b/net/tipc/net.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * net/tipc/net.h: Include file for TIPC network routing code | ||
3 | * | ||
4 | * Copyright (c) 1995-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_NET_H | ||
38 | #define _TIPC_NET_H | ||
39 | |||
40 | struct _zone; | ||
41 | |||
42 | /** | ||
43 | * struct network - TIPC network structure | ||
44 | * @zones: array of pointers to all zones within network | ||
45 | */ | ||
46 | |||
47 | struct network { | ||
48 | struct _zone **zones; | ||
49 | }; | ||
50 | |||
51 | |||
52 | extern struct network net; | ||
53 | extern rwlock_t net_lock; | ||
54 | |||
55 | int net_init(void); | ||
56 | void net_stop(void); | ||
57 | void net_remove_as_router(u32 router); | ||
58 | void net_send_external_routes(u32 dest); | ||
59 | void net_route_msg(struct sk_buff *buf); | ||
60 | struct node *net_select_remote_node(u32 addr, u32 ref); | ||
61 | u32 net_select_router(u32 addr, u32 ref); | ||
62 | |||
63 | int tipc_start_net(void); | ||
64 | void tipc_stop_net(void); | ||
65 | |||
66 | #endif | ||
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c new file mode 100644 index 000000000000..19b3f4022532 --- /dev/null +++ b/net/tipc/netlink.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * net/tipc/netlink.c: TIPC configuration handling | ||
3 | * | ||
4 | * Copyright (c) 2005-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "config.h" | ||
39 | #include <net/genetlink.h> | ||
40 | |||
41 | static int handle_cmd(struct sk_buff *skb, struct genl_info *info) | ||
42 | { | ||
43 | struct sk_buff *rep_buf; | ||
44 | struct nlmsghdr *rep_nlh; | ||
45 | struct nlmsghdr *req_nlh = info->nlhdr; | ||
46 | struct tipc_genlmsghdr *req_userhdr = info->userhdr; | ||
47 | int hdr_space = NLMSG_SPACE(GENL_HDRLEN + TIPC_GENL_HDRLEN); | ||
48 | |||
49 | if ((req_userhdr->cmd & 0xC000) && (!capable(CAP_NET_ADMIN))) | ||
50 | rep_buf = cfg_reply_error_string(TIPC_CFG_NOT_NET_ADMIN); | ||
51 | else | ||
52 | rep_buf = cfg_do_cmd(req_userhdr->dest, | ||
53 | req_userhdr->cmd, | ||
54 | NLMSG_DATA(req_nlh) + GENL_HDRLEN + TIPC_GENL_HDRLEN, | ||
55 | NLMSG_PAYLOAD(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN), | ||
56 | hdr_space); | ||
57 | |||
58 | if (rep_buf) { | ||
59 | skb_push(rep_buf, hdr_space); | ||
60 | rep_nlh = (struct nlmsghdr *)rep_buf->data; | ||
61 | memcpy(rep_nlh, req_nlh, hdr_space); | ||
62 | rep_nlh->nlmsg_len = rep_buf->len; | ||
63 | genlmsg_unicast(rep_buf, req_nlh->nlmsg_pid); | ||
64 | } | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static struct genl_family family = { | ||
70 | .id = GENL_ID_GENERATE, | ||
71 | .name = TIPC_GENL_NAME, | ||
72 | .version = TIPC_GENL_VERSION, | ||
73 | .hdrsize = TIPC_GENL_HDRLEN, | ||
74 | .maxattr = 0, | ||
75 | }; | ||
76 | |||
77 | static struct genl_ops ops = { | ||
78 | .cmd = TIPC_GENL_CMD, | ||
79 | .doit = handle_cmd, | ||
80 | }; | ||
81 | |||
82 | static int family_registered = 0; | ||
83 | |||
84 | int netlink_start(void) | ||
85 | { | ||
86 | |||
87 | |||
88 | if (genl_register_family(&family)) | ||
89 | goto err; | ||
90 | |||
91 | family_registered = 1; | ||
92 | |||
93 | if (genl_register_ops(&family, &ops)) | ||
94 | goto err_unregister; | ||
95 | |||
96 | return 0; | ||
97 | |||
98 | err_unregister: | ||
99 | genl_unregister_family(&family); | ||
100 | family_registered = 0; | ||
101 | err: | ||
102 | err("Failed to register netlink interface\n"); | ||
103 | return -EFAULT; | ||
104 | } | ||
105 | |||
106 | void netlink_stop(void) | ||
107 | { | ||
108 | if (family_registered) { | ||
109 | genl_unregister_family(&family); | ||
110 | family_registered = 0; | ||
111 | } | ||
112 | } | ||
diff --git a/net/tipc/node.c b/net/tipc/node.c new file mode 100644 index 000000000000..05688d01138b --- /dev/null +++ b/net/tipc/node.c | |||
@@ -0,0 +1,679 @@ | |||
1 | /* | ||
2 | * net/tipc/node.c: TIPC node management routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "config.h" | ||
39 | #include "node.h" | ||
40 | #include "cluster.h" | ||
41 | #include "net.h" | ||
42 | #include "addr.h" | ||
43 | #include "node_subscr.h" | ||
44 | #include "link.h" | ||
45 | #include "port.h" | ||
46 | #include "bearer.h" | ||
47 | #include "name_distr.h" | ||
48 | #include "net.h" | ||
49 | |||
50 | void node_print(struct print_buf *buf, struct node *n_ptr, char *str); | ||
51 | static void node_lost_contact(struct node *n_ptr); | ||
52 | static void node_established_contact(struct node *n_ptr); | ||
53 | |||
54 | struct node *nodes = NULL; /* sorted list of nodes within cluster */ | ||
55 | |||
56 | u32 tipc_own_tag = 0; | ||
57 | |||
58 | struct node *node_create(u32 addr) | ||
59 | { | ||
60 | struct cluster *c_ptr; | ||
61 | struct node *n_ptr; | ||
62 | struct node **curr_node; | ||
63 | |||
64 | n_ptr = kmalloc(sizeof(*n_ptr),GFP_ATOMIC); | ||
65 | if (n_ptr != NULL) { | ||
66 | memset(n_ptr, 0, sizeof(*n_ptr)); | ||
67 | n_ptr->addr = addr; | ||
68 | n_ptr->lock = SPIN_LOCK_UNLOCKED; | ||
69 | INIT_LIST_HEAD(&n_ptr->nsub); | ||
70 | |||
71 | c_ptr = cluster_find(addr); | ||
72 | if (c_ptr == NULL) | ||
73 | c_ptr = cluster_create(addr); | ||
74 | if (c_ptr != NULL) { | ||
75 | n_ptr->owner = c_ptr; | ||
76 | cluster_attach_node(c_ptr, n_ptr); | ||
77 | n_ptr->last_router = -1; | ||
78 | |||
79 | /* Insert node into ordered list */ | ||
80 | for (curr_node = &nodes; *curr_node; | ||
81 | curr_node = &(*curr_node)->next) { | ||
82 | if (addr < (*curr_node)->addr) { | ||
83 | n_ptr->next = *curr_node; | ||
84 | break; | ||
85 | } | ||
86 | } | ||
87 | (*curr_node) = n_ptr; | ||
88 | } else { | ||
89 | kfree(n_ptr); | ||
90 | n_ptr = NULL; | ||
91 | } | ||
92 | } | ||
93 | return n_ptr; | ||
94 | } | ||
95 | |||
96 | void node_delete(struct node *n_ptr) | ||
97 | { | ||
98 | if (!n_ptr) | ||
99 | return; | ||
100 | |||
101 | #if 0 | ||
102 | /* Not needed because links are already deleted via bearer_stop() */ | ||
103 | |||
104 | u32 l_num; | ||
105 | |||
106 | for (l_num = 0; l_num < MAX_BEARERS; l_num++) { | ||
107 | link_delete(n_ptr->links[l_num]); | ||
108 | } | ||
109 | #endif | ||
110 | |||
111 | dbg("node %x deleted\n", n_ptr->addr); | ||
112 | kfree(n_ptr); | ||
113 | } | ||
114 | |||
115 | |||
116 | /** | ||
117 | * node_link_up - handle addition of link | ||
118 | * | ||
119 | * Link becomes active (alone or shared) or standby, depending on its priority. | ||
120 | */ | ||
121 | |||
122 | void node_link_up(struct node *n_ptr, struct link *l_ptr) | ||
123 | { | ||
124 | struct link **active = &n_ptr->active_links[0]; | ||
125 | |||
126 | info("Established link <%s> on network plane %c\n", | ||
127 | l_ptr->name, l_ptr->b_ptr->net_plane); | ||
128 | |||
129 | if (!active[0]) { | ||
130 | dbg(" link %x into %x/%x\n", l_ptr, &active[0], &active[1]); | ||
131 | active[0] = active[1] = l_ptr; | ||
132 | node_established_contact(n_ptr); | ||
133 | return; | ||
134 | } | ||
135 | if (l_ptr->priority < active[0]->priority) { | ||
136 | info("Link is standby\n"); | ||
137 | return; | ||
138 | } | ||
139 | link_send_duplicate(active[0], l_ptr); | ||
140 | if (l_ptr->priority == active[0]->priority) { | ||
141 | active[0] = l_ptr; | ||
142 | return; | ||
143 | } | ||
144 | info("Link <%s> on network plane %c becomes standby\n", | ||
145 | active[0]->name, active[0]->b_ptr->net_plane); | ||
146 | active[0] = active[1] = l_ptr; | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * node_select_active_links - select active link | ||
151 | */ | ||
152 | |||
153 | static void node_select_active_links(struct node *n_ptr) | ||
154 | { | ||
155 | struct link **active = &n_ptr->active_links[0]; | ||
156 | u32 i; | ||
157 | u32 highest_prio = 0; | ||
158 | |||
159 | active[0] = active[1] = 0; | ||
160 | |||
161 | for (i = 0; i < MAX_BEARERS; i++) { | ||
162 | struct link *l_ptr = n_ptr->links[i]; | ||
163 | |||
164 | if (!l_ptr || !link_is_up(l_ptr) || | ||
165 | (l_ptr->priority < highest_prio)) | ||
166 | continue; | ||
167 | |||
168 | if (l_ptr->priority > highest_prio) { | ||
169 | highest_prio = l_ptr->priority; | ||
170 | active[0] = active[1] = l_ptr; | ||
171 | } else { | ||
172 | active[1] = l_ptr; | ||
173 | } | ||
174 | } | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * node_link_down - handle loss of link | ||
179 | */ | ||
180 | |||
181 | void node_link_down(struct node *n_ptr, struct link *l_ptr) | ||
182 | { | ||
183 | struct link **active; | ||
184 | |||
185 | if (!link_is_active(l_ptr)) { | ||
186 | info("Lost standby link <%s> on network plane %c\n", | ||
187 | l_ptr->name, l_ptr->b_ptr->net_plane); | ||
188 | return; | ||
189 | } | ||
190 | info("Lost link <%s> on network plane %c\n", | ||
191 | l_ptr->name, l_ptr->b_ptr->net_plane); | ||
192 | |||
193 | active = &n_ptr->active_links[0]; | ||
194 | if (active[0] == l_ptr) | ||
195 | active[0] = active[1]; | ||
196 | if (active[1] == l_ptr) | ||
197 | active[1] = active[0]; | ||
198 | if (active[0] == l_ptr) | ||
199 | node_select_active_links(n_ptr); | ||
200 | if (node_is_up(n_ptr)) | ||
201 | link_changeover(l_ptr); | ||
202 | else | ||
203 | node_lost_contact(n_ptr); | ||
204 | } | ||
205 | |||
206 | int node_has_active_links(struct node *n_ptr) | ||
207 | { | ||
208 | return (n_ptr && | ||
209 | ((n_ptr->active_links[0]) || (n_ptr->active_links[1]))); | ||
210 | } | ||
211 | |||
212 | int node_has_redundant_links(struct node *n_ptr) | ||
213 | { | ||
214 | return (node_has_active_links(n_ptr) && | ||
215 | (n_ptr->active_links[0] != n_ptr->active_links[1])); | ||
216 | } | ||
217 | |||
218 | int node_has_active_routes(struct node *n_ptr) | ||
219 | { | ||
220 | return (n_ptr && (n_ptr->last_router >= 0)); | ||
221 | } | ||
222 | |||
223 | int node_is_up(struct node *n_ptr) | ||
224 | { | ||
225 | return (node_has_active_links(n_ptr) || node_has_active_routes(n_ptr)); | ||
226 | } | ||
227 | |||
228 | struct node *node_attach_link(struct link *l_ptr) | ||
229 | { | ||
230 | struct node *n_ptr = node_find(l_ptr->addr); | ||
231 | |||
232 | if (!n_ptr) | ||
233 | n_ptr = node_create(l_ptr->addr); | ||
234 | if (n_ptr) { | ||
235 | u32 bearer_id = l_ptr->b_ptr->identity; | ||
236 | char addr_string[16]; | ||
237 | |||
238 | assert(bearer_id < MAX_BEARERS); | ||
239 | if (n_ptr->link_cnt >= 2) { | ||
240 | char addr_string[16]; | ||
241 | |||
242 | err("Attempt to create third link to %s\n", | ||
243 | addr_string_fill(addr_string, n_ptr->addr)); | ||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | if (!n_ptr->links[bearer_id]) { | ||
248 | n_ptr->links[bearer_id] = l_ptr; | ||
249 | net.zones[tipc_zone(l_ptr->addr)]->links++; | ||
250 | n_ptr->link_cnt++; | ||
251 | return n_ptr; | ||
252 | } | ||
253 | err("Attempt to establish second link on <%s> to <%s> \n", | ||
254 | l_ptr->b_ptr->publ.name, | ||
255 | addr_string_fill(addr_string, l_ptr->addr)); | ||
256 | } | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | void node_detach_link(struct node *n_ptr, struct link *l_ptr) | ||
261 | { | ||
262 | n_ptr->links[l_ptr->b_ptr->identity] = 0; | ||
263 | net.zones[tipc_zone(l_ptr->addr)]->links--; | ||
264 | n_ptr->link_cnt--; | ||
265 | } | ||
266 | |||
267 | /* | ||
268 | * Routing table management - five cases to handle: | ||
269 | * | ||
270 | * 1: A link towards a zone/cluster external node comes up. | ||
271 | * => Send a multicast message updating routing tables of all | ||
272 | * system nodes within own cluster that the new destination | ||
273 | * can be reached via this node. | ||
274 | * (node.establishedContact()=>cluster.multicastNewRoute()) | ||
275 | * | ||
276 | * 2: A link towards a slave node comes up. | ||
277 | * => Send a multicast message updating routing tables of all | ||
278 | * system nodes within own cluster that the new destination | ||
279 | * can be reached via this node. | ||
280 | * (node.establishedContact()=>cluster.multicastNewRoute()) | ||
281 | * => Send a message to the slave node about existence | ||
282 | * of all system nodes within cluster: | ||
283 | * (node.establishedContact()=>cluster.sendLocalRoutes()) | ||
284 | * | ||
285 | * 3: A new cluster local system node becomes available. | ||
286 | * => Send message(s) to this particular node containing | ||
287 | * information about all cluster external and slave | ||
288 | * nodes which can be reached via this node. | ||
289 | * (node.establishedContact()==>network.sendExternalRoutes()) | ||
290 | * (node.establishedContact()==>network.sendSlaveRoutes()) | ||
291 | * => Send messages to all directly connected slave nodes | ||
292 | * containing information about the existence of the new node | ||
293 | * (node.establishedContact()=>cluster.multicastNewRoute()) | ||
294 | * | ||
295 | * 4: The link towards a zone/cluster external node or slave | ||
296 | * node goes down. | ||
297 | * => Send a multcast message updating routing tables of all | ||
298 | * nodes within cluster that the new destination can not any | ||
299 | * longer be reached via this node. | ||
300 | * (node.lostAllLinks()=>cluster.bcastLostRoute()) | ||
301 | * | ||
302 | * 5: A cluster local system node becomes unavailable. | ||
303 | * => Remove all references to this node from the local | ||
304 | * routing tables. Note: This is a completely node | ||
305 | * local operation. | ||
306 | * (node.lostAllLinks()=>network.removeAsRouter()) | ||
307 | * => Send messages to all directly connected slave nodes | ||
308 | * containing information about loss of the node | ||
309 | * (node.establishedContact()=>cluster.multicastLostRoute()) | ||
310 | * | ||
311 | */ | ||
312 | |||
313 | static void node_established_contact(struct node *n_ptr) | ||
314 | { | ||
315 | struct cluster *c_ptr; | ||
316 | |||
317 | dbg("node_established_contact:-> %x\n", n_ptr->addr); | ||
318 | if (!node_has_active_routes(n_ptr)) { | ||
319 | k_signal((Handler)named_node_up, n_ptr->addr); | ||
320 | } | ||
321 | |||
322 | /* Syncronize broadcast acks */ | ||
323 | n_ptr->bclink.acked = bclink_get_last_sent(); | ||
324 | |||
325 | if (is_slave(tipc_own_addr)) | ||
326 | return; | ||
327 | if (!in_own_cluster(n_ptr->addr)) { | ||
328 | /* Usage case 1 (see above) */ | ||
329 | c_ptr = cluster_find(tipc_own_addr); | ||
330 | if (!c_ptr) | ||
331 | c_ptr = cluster_create(tipc_own_addr); | ||
332 | if (c_ptr) | ||
333 | cluster_bcast_new_route(c_ptr, n_ptr->addr, 1, | ||
334 | tipc_max_nodes); | ||
335 | return; | ||
336 | } | ||
337 | |||
338 | c_ptr = n_ptr->owner; | ||
339 | if (is_slave(n_ptr->addr)) { | ||
340 | /* Usage case 2 (see above) */ | ||
341 | cluster_bcast_new_route(c_ptr, n_ptr->addr, 1, tipc_max_nodes); | ||
342 | cluster_send_local_routes(c_ptr, n_ptr->addr); | ||
343 | return; | ||
344 | } | ||
345 | |||
346 | if (n_ptr->bclink.supported) { | ||
347 | nmap_add(&cluster_bcast_nodes, n_ptr->addr); | ||
348 | if (n_ptr->addr < tipc_own_addr) | ||
349 | tipc_own_tag++; | ||
350 | } | ||
351 | |||
352 | /* Case 3 (see above) */ | ||
353 | net_send_external_routes(n_ptr->addr); | ||
354 | cluster_send_slave_routes(c_ptr, n_ptr->addr); | ||
355 | cluster_bcast_new_route(c_ptr, n_ptr->addr, LOWEST_SLAVE, | ||
356 | highest_allowed_slave); | ||
357 | } | ||
358 | |||
359 | static void node_lost_contact(struct node *n_ptr) | ||
360 | { | ||
361 | struct cluster *c_ptr; | ||
362 | struct node_subscr *ns, *tns; | ||
363 | char addr_string[16]; | ||
364 | u32 i; | ||
365 | |||
366 | /* Clean up broadcast reception remains */ | ||
367 | n_ptr->bclink.gap_after = n_ptr->bclink.gap_to = 0; | ||
368 | while (n_ptr->bclink.deferred_head) { | ||
369 | struct sk_buff* buf = n_ptr->bclink.deferred_head; | ||
370 | n_ptr->bclink.deferred_head = buf->next; | ||
371 | buf_discard(buf); | ||
372 | } | ||
373 | if (n_ptr->bclink.defragm) { | ||
374 | buf_discard(n_ptr->bclink.defragm); | ||
375 | n_ptr->bclink.defragm = NULL; | ||
376 | } | ||
377 | if (in_own_cluster(n_ptr->addr) && n_ptr->bclink.supported) { | ||
378 | bclink_acknowledge(n_ptr, mod(n_ptr->bclink.acked + 10000)); | ||
379 | } | ||
380 | |||
381 | /* Update routing tables */ | ||
382 | if (is_slave(tipc_own_addr)) { | ||
383 | net_remove_as_router(n_ptr->addr); | ||
384 | } else { | ||
385 | if (!in_own_cluster(n_ptr->addr)) { | ||
386 | /* Case 4 (see above) */ | ||
387 | c_ptr = cluster_find(tipc_own_addr); | ||
388 | cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1, | ||
389 | tipc_max_nodes); | ||
390 | } else { | ||
391 | /* Case 5 (see above) */ | ||
392 | c_ptr = cluster_find(n_ptr->addr); | ||
393 | if (is_slave(n_ptr->addr)) { | ||
394 | cluster_bcast_lost_route(c_ptr, n_ptr->addr, 1, | ||
395 | tipc_max_nodes); | ||
396 | } else { | ||
397 | if (n_ptr->bclink.supported) { | ||
398 | nmap_remove(&cluster_bcast_nodes, | ||
399 | n_ptr->addr); | ||
400 | if (n_ptr->addr < tipc_own_addr) | ||
401 | tipc_own_tag--; | ||
402 | } | ||
403 | net_remove_as_router(n_ptr->addr); | ||
404 | cluster_bcast_lost_route(c_ptr, n_ptr->addr, | ||
405 | LOWEST_SLAVE, | ||
406 | highest_allowed_slave); | ||
407 | } | ||
408 | } | ||
409 | } | ||
410 | if (node_has_active_routes(n_ptr)) | ||
411 | return; | ||
412 | |||
413 | info("Lost contact with %s\n", | ||
414 | addr_string_fill(addr_string, n_ptr->addr)); | ||
415 | |||
416 | /* Abort link changeover */ | ||
417 | for (i = 0; i < MAX_BEARERS; i++) { | ||
418 | struct link *l_ptr = n_ptr->links[i]; | ||
419 | if (!l_ptr) | ||
420 | continue; | ||
421 | l_ptr->reset_checkpoint = l_ptr->next_in_no; | ||
422 | l_ptr->exp_msg_count = 0; | ||
423 | link_reset_fragments(l_ptr); | ||
424 | } | ||
425 | |||
426 | /* Notify subscribers */ | ||
427 | list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) { | ||
428 | ns->node = 0; | ||
429 | list_del_init(&ns->nodesub_list); | ||
430 | k_signal((Handler)ns->handle_node_down, | ||
431 | (unsigned long)ns->usr_handle); | ||
432 | } | ||
433 | } | ||
434 | |||
435 | /** | ||
436 | * node_select_next_hop - find the next-hop node for a message | ||
437 | * | ||
438 | * Called by when cluster local lookup has failed. | ||
439 | */ | ||
440 | |||
441 | struct node *node_select_next_hop(u32 addr, u32 selector) | ||
442 | { | ||
443 | struct node *n_ptr; | ||
444 | u32 router_addr; | ||
445 | |||
446 | if (!addr_domain_valid(addr)) | ||
447 | return 0; | ||
448 | |||
449 | /* Look for direct link to destination processsor */ | ||
450 | n_ptr = node_find(addr); | ||
451 | if (n_ptr && node_has_active_links(n_ptr)) | ||
452 | return n_ptr; | ||
453 | |||
454 | /* Cluster local system nodes *must* have direct links */ | ||
455 | if (!is_slave(addr) && in_own_cluster(addr)) | ||
456 | return 0; | ||
457 | |||
458 | /* Look for cluster local router with direct link to node */ | ||
459 | router_addr = node_select_router(n_ptr, selector); | ||
460 | if (router_addr) | ||
461 | return node_select(router_addr, selector); | ||
462 | |||
463 | /* Slave nodes can only be accessed within own cluster via a | ||
464 | known router with direct link -- if no router was found,give up */ | ||
465 | if (is_slave(addr)) | ||
466 | return 0; | ||
467 | |||
468 | /* Inter zone/cluster -- find any direct link to remote cluster */ | ||
469 | addr = tipc_addr(tipc_zone(addr), tipc_cluster(addr), 0); | ||
470 | n_ptr = net_select_remote_node(addr, selector); | ||
471 | if (n_ptr && node_has_active_links(n_ptr)) | ||
472 | return n_ptr; | ||
473 | |||
474 | /* Last resort -- look for any router to anywhere in remote zone */ | ||
475 | router_addr = net_select_router(addr, selector); | ||
476 | if (router_addr) | ||
477 | return node_select(router_addr, selector); | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | /** | ||
483 | * node_select_router - select router to reach specified node | ||
484 | * | ||
485 | * Uses a deterministic and fair algorithm for selecting router node. | ||
486 | */ | ||
487 | |||
488 | u32 node_select_router(struct node *n_ptr, u32 ref) | ||
489 | { | ||
490 | u32 ulim; | ||
491 | u32 mask; | ||
492 | u32 start; | ||
493 | u32 r; | ||
494 | |||
495 | if (!n_ptr) | ||
496 | return 0; | ||
497 | |||
498 | if (n_ptr->last_router < 0) | ||
499 | return 0; | ||
500 | ulim = ((n_ptr->last_router + 1) * 32) - 1; | ||
501 | |||
502 | /* Start entry must be random */ | ||
503 | mask = tipc_max_nodes; | ||
504 | while (mask > ulim) | ||
505 | mask >>= 1; | ||
506 | start = ref & mask; | ||
507 | r = start; | ||
508 | |||
509 | /* Lookup upwards with wrap-around */ | ||
510 | do { | ||
511 | if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) | ||
512 | break; | ||
513 | } while (++r <= ulim); | ||
514 | if (r > ulim) { | ||
515 | r = 1; | ||
516 | do { | ||
517 | if (((n_ptr->routers[r / 32]) >> (r % 32)) & 1) | ||
518 | break; | ||
519 | } while (++r < start); | ||
520 | assert(r != start); | ||
521 | } | ||
522 | assert(r && (r <= ulim)); | ||
523 | return tipc_addr(own_zone(), own_cluster(), r); | ||
524 | } | ||
525 | |||
526 | void node_add_router(struct node *n_ptr, u32 router) | ||
527 | { | ||
528 | u32 r_num = tipc_node(router); | ||
529 | |||
530 | n_ptr->routers[r_num / 32] = | ||
531 | ((1 << (r_num % 32)) | n_ptr->routers[r_num / 32]); | ||
532 | n_ptr->last_router = tipc_max_nodes / 32; | ||
533 | while ((--n_ptr->last_router >= 0) && | ||
534 | !n_ptr->routers[n_ptr->last_router]); | ||
535 | } | ||
536 | |||
537 | void node_remove_router(struct node *n_ptr, u32 router) | ||
538 | { | ||
539 | u32 r_num = tipc_node(router); | ||
540 | |||
541 | if (n_ptr->last_router < 0) | ||
542 | return; /* No routes */ | ||
543 | |||
544 | n_ptr->routers[r_num / 32] = | ||
545 | ((~(1 << (r_num % 32))) & (n_ptr->routers[r_num / 32])); | ||
546 | n_ptr->last_router = tipc_max_nodes / 32; | ||
547 | while ((--n_ptr->last_router >= 0) && | ||
548 | !n_ptr->routers[n_ptr->last_router]); | ||
549 | |||
550 | if (!node_is_up(n_ptr)) | ||
551 | node_lost_contact(n_ptr); | ||
552 | } | ||
553 | |||
554 | #if 0 | ||
555 | void node_print(struct print_buf *buf, struct node *n_ptr, char *str) | ||
556 | { | ||
557 | u32 i; | ||
558 | |||
559 | tipc_printf(buf, "\n\n%s", str); | ||
560 | for (i = 0; i < MAX_BEARERS; i++) { | ||
561 | if (!n_ptr->links[i]) | ||
562 | continue; | ||
563 | tipc_printf(buf, "Links[%u]: %x, ", i, n_ptr->links[i]); | ||
564 | } | ||
565 | tipc_printf(buf, "Active links: [%x,%x]\n", | ||
566 | n_ptr->active_links[0], n_ptr->active_links[1]); | ||
567 | } | ||
568 | #endif | ||
569 | |||
570 | u32 tipc_available_nodes(const u32 domain) | ||
571 | { | ||
572 | struct node *n_ptr; | ||
573 | u32 cnt = 0; | ||
574 | |||
575 | for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) { | ||
576 | if (!in_scope(domain, n_ptr->addr)) | ||
577 | continue; | ||
578 | if (node_is_up(n_ptr)) | ||
579 | cnt++; | ||
580 | } | ||
581 | return cnt; | ||
582 | } | ||
583 | |||
584 | struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space) | ||
585 | { | ||
586 | u32 domain; | ||
587 | struct sk_buff *buf; | ||
588 | struct node *n_ptr; | ||
589 | struct tipc_node_info node_info; | ||
590 | |||
591 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) | ||
592 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
593 | |||
594 | domain = *(u32 *)TLV_DATA(req_tlv_area); | ||
595 | domain = ntohl(domain); | ||
596 | if (!addr_domain_valid(domain)) | ||
597 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
598 | " (network address)"); | ||
599 | |||
600 | if (!nodes) | ||
601 | return cfg_reply_none(); | ||
602 | |||
603 | /* For now, get space for all other nodes | ||
604 | (will need to modify this when slave nodes are supported */ | ||
605 | |||
606 | buf = cfg_reply_alloc(TLV_SPACE(sizeof(node_info)) * | ||
607 | (tipc_max_nodes - 1)); | ||
608 | if (!buf) | ||
609 | return NULL; | ||
610 | |||
611 | /* Add TLVs for all nodes in scope */ | ||
612 | |||
613 | for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) { | ||
614 | if (!in_scope(domain, n_ptr->addr)) | ||
615 | continue; | ||
616 | node_info.addr = htonl(n_ptr->addr); | ||
617 | node_info.up = htonl(node_is_up(n_ptr)); | ||
618 | cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, | ||
619 | &node_info, sizeof(node_info)); | ||
620 | } | ||
621 | |||
622 | return buf; | ||
623 | } | ||
624 | |||
625 | struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space) | ||
626 | { | ||
627 | u32 domain; | ||
628 | struct sk_buff *buf; | ||
629 | struct node *n_ptr; | ||
630 | struct tipc_link_info link_info; | ||
631 | |||
632 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NET_ADDR)) | ||
633 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
634 | |||
635 | domain = *(u32 *)TLV_DATA(req_tlv_area); | ||
636 | domain = ntohl(domain); | ||
637 | if (!addr_domain_valid(domain)) | ||
638 | return cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
639 | " (network address)"); | ||
640 | |||
641 | if (!nodes) | ||
642 | return cfg_reply_none(); | ||
643 | |||
644 | /* For now, get space for 2 links to all other nodes + bcast link | ||
645 | (will need to modify this when slave nodes are supported */ | ||
646 | |||
647 | buf = cfg_reply_alloc(TLV_SPACE(sizeof(link_info)) * | ||
648 | (2 * (tipc_max_nodes - 1) + 1)); | ||
649 | if (!buf) | ||
650 | return NULL; | ||
651 | |||
652 | /* Add TLV for broadcast link */ | ||
653 | |||
654 | link_info.dest = tipc_own_addr & 0xfffff00; | ||
655 | link_info.dest = htonl(link_info.dest); | ||
656 | link_info.up = htonl(1); | ||
657 | sprintf(link_info.str, bc_link_name); | ||
658 | cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); | ||
659 | |||
660 | /* Add TLVs for any other links in scope */ | ||
661 | |||
662 | for (n_ptr = nodes; n_ptr; n_ptr = n_ptr->next) { | ||
663 | u32 i; | ||
664 | |||
665 | if (!in_scope(domain, n_ptr->addr)) | ||
666 | continue; | ||
667 | for (i = 0; i < MAX_BEARERS; i++) { | ||
668 | if (!n_ptr->links[i]) | ||
669 | continue; | ||
670 | link_info.dest = htonl(n_ptr->addr); | ||
671 | link_info.up = htonl(link_is_up(n_ptr->links[i])); | ||
672 | strcpy(link_info.str, n_ptr->links[i]->name); | ||
673 | cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, | ||
674 | &link_info, sizeof(link_info)); | ||
675 | } | ||
676 | } | ||
677 | |||
678 | return buf; | ||
679 | } | ||
diff --git a/net/tipc/node.h b/net/tipc/node.h new file mode 100644 index 000000000000..b39442badccf --- /dev/null +++ b/net/tipc/node.h | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * net/tipc/node.h: Include file for TIPC node management routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_NODE_H | ||
38 | #define _TIPC_NODE_H | ||
39 | |||
40 | #include "node_subscr.h" | ||
41 | #include "addr.h" | ||
42 | #include "cluster.h" | ||
43 | #include "bearer.h" | ||
44 | |||
45 | /** | ||
46 | * struct node - TIPC node structure | ||
47 | * @addr: network address of node | ||
48 | * @lock: spinlock governing access to structure | ||
49 | * @owner: pointer to cluster that node belongs to | ||
50 | * @next: pointer to next node in sorted list of cluster's nodes | ||
51 | * @nsub: list of "node down" subscriptions monitoring node | ||
52 | * @active_links: pointers to active links to node | ||
53 | * @links: pointers to all links to node | ||
54 | * @link_cnt: number of links to node | ||
55 | * @permit_changeover: non-zero if node has redundant links to this system | ||
56 | * @routers: bitmap (used for multicluster communication) | ||
57 | * @last_router: (used for multicluster communication) | ||
58 | * @bclink: broadcast-related info | ||
59 | * @supported: non-zero if node supports TIPC b'cast capability | ||
60 | * @acked: sequence # of last outbound b'cast message acknowledged by node | ||
61 | * @last_in: sequence # of last in-sequence b'cast message received from node | ||
62 | * @gap_after: sequence # of last message not requiring a NAK request | ||
63 | * @gap_to: sequence # of last message requiring a NAK request | ||
64 | * @nack_sync: counter that determines when NAK requests should be sent | ||
65 | * @deferred_head: oldest OOS b'cast message received from node | ||
66 | * @deferred_tail: newest OOS b'cast message received from node | ||
67 | * @defragm: list of partially reassembled b'cast message fragments from node | ||
68 | */ | ||
69 | |||
70 | struct node { | ||
71 | u32 addr; | ||
72 | spinlock_t lock; | ||
73 | struct cluster *owner; | ||
74 | struct node *next; | ||
75 | struct list_head nsub; | ||
76 | struct link *active_links[2]; | ||
77 | struct link *links[MAX_BEARERS]; | ||
78 | int link_cnt; | ||
79 | int permit_changeover; | ||
80 | u32 routers[512/32]; | ||
81 | int last_router; | ||
82 | struct { | ||
83 | int supported; | ||
84 | u32 acked; | ||
85 | u32 last_in; | ||
86 | u32 gap_after; | ||
87 | u32 gap_to; | ||
88 | u32 nack_sync; | ||
89 | struct sk_buff *deferred_head; | ||
90 | struct sk_buff *deferred_tail; | ||
91 | struct sk_buff *defragm; | ||
92 | } bclink; | ||
93 | }; | ||
94 | |||
95 | extern struct node *nodes; | ||
96 | extern u32 tipc_own_tag; | ||
97 | |||
98 | struct node *node_create(u32 addr); | ||
99 | void node_delete(struct node *n_ptr); | ||
100 | struct node *node_attach_link(struct link *l_ptr); | ||
101 | void node_detach_link(struct node *n_ptr, struct link *l_ptr); | ||
102 | void node_link_down(struct node *n_ptr, struct link *l_ptr); | ||
103 | void node_link_up(struct node *n_ptr, struct link *l_ptr); | ||
104 | int node_has_active_links(struct node *n_ptr); | ||
105 | int node_has_redundant_links(struct node *n_ptr); | ||
106 | u32 node_select_router(struct node *n_ptr, u32 ref); | ||
107 | struct node *node_select_next_hop(u32 addr, u32 selector); | ||
108 | int node_is_up(struct node *n_ptr); | ||
109 | void node_add_router(struct node *n_ptr, u32 router); | ||
110 | void node_remove_router(struct node *n_ptr, u32 router); | ||
111 | struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space); | ||
112 | struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space); | ||
113 | |||
114 | static inline struct node *node_find(u32 addr) | ||
115 | { | ||
116 | if (likely(in_own_cluster(addr))) | ||
117 | return local_nodes[tipc_node(addr)]; | ||
118 | else if (addr_domain_valid(addr)) { | ||
119 | struct cluster *c_ptr = cluster_find(addr); | ||
120 | |||
121 | if (c_ptr) | ||
122 | return c_ptr->nodes[tipc_node(addr)]; | ||
123 | } | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static inline struct node *node_select(u32 addr, u32 selector) | ||
128 | { | ||
129 | if (likely(in_own_cluster(addr))) | ||
130 | return local_nodes[tipc_node(addr)]; | ||
131 | return node_select_next_hop(addr, selector); | ||
132 | } | ||
133 | |||
134 | static inline void node_lock(struct node *n_ptr) | ||
135 | { | ||
136 | spin_lock_bh(&n_ptr->lock); | ||
137 | } | ||
138 | |||
139 | static inline void node_unlock(struct node *n_ptr) | ||
140 | { | ||
141 | spin_unlock_bh(&n_ptr->lock); | ||
142 | } | ||
143 | |||
144 | #endif | ||
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c new file mode 100644 index 000000000000..79375927916f --- /dev/null +++ b/net/tipc/node_subscr.c | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * net/tipc/node_subscr.c: TIPC "node down" subscription handling | ||
3 | * | ||
4 | * Copyright (c) 1995-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "dbg.h" | ||
39 | #include "node_subscr.h" | ||
40 | #include "node.h" | ||
41 | #include "addr.h" | ||
42 | |||
43 | /** | ||
44 | * nodesub_subscribe - create "node down" subscription for specified node | ||
45 | */ | ||
46 | |||
47 | void nodesub_subscribe(struct node_subscr *node_sub, u32 addr, | ||
48 | void *usr_handle, net_ev_handler handle_down) | ||
49 | { | ||
50 | node_sub->node = 0; | ||
51 | if (addr == tipc_own_addr) | ||
52 | return; | ||
53 | if (!addr_node_valid(addr)) { | ||
54 | warn("node_subscr with illegal %x\n", addr); | ||
55 | return; | ||
56 | } | ||
57 | |||
58 | node_sub->handle_node_down = handle_down; | ||
59 | node_sub->usr_handle = usr_handle; | ||
60 | node_sub->node = node_find(addr); | ||
61 | assert(node_sub->node); | ||
62 | node_lock(node_sub->node); | ||
63 | list_add_tail(&node_sub->nodesub_list, &node_sub->node->nsub); | ||
64 | node_unlock(node_sub->node); | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * nodesub_unsubscribe - cancel "node down" subscription (if any) | ||
69 | */ | ||
70 | |||
71 | void nodesub_unsubscribe(struct node_subscr *node_sub) | ||
72 | { | ||
73 | if (!node_sub->node) | ||
74 | return; | ||
75 | |||
76 | node_lock(node_sub->node); | ||
77 | list_del_init(&node_sub->nodesub_list); | ||
78 | node_unlock(node_sub->node); | ||
79 | } | ||
diff --git a/net/tipc/node_subscr.h b/net/tipc/node_subscr.h new file mode 100644 index 000000000000..a3b87ac4859b --- /dev/null +++ b/net/tipc/node_subscr.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * net/tipc/node_subscr.h: Include file for TIPC "node down" subscription handling | ||
3 | * | ||
4 | * Copyright (c) 1995-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_NODE_SUBSCR_H | ||
38 | #define _TIPC_NODE_SUBSCR_H | ||
39 | |||
40 | #include "addr.h" | ||
41 | |||
42 | typedef void (*net_ev_handler) (void *usr_handle); | ||
43 | |||
44 | /** | ||
45 | * struct node_subscr - "node down" subscription entry | ||
46 | * @node: ptr to node structure of interest (or NULL, if none) | ||
47 | * @handle_node_down: routine to invoke when node fails | ||
48 | * @usr_handle: argument to pass to routine when node fails | ||
49 | * @nodesub_list: adjacent entries in list of subscriptions for the node | ||
50 | */ | ||
51 | |||
52 | struct node_subscr { | ||
53 | struct node *node; | ||
54 | net_ev_handler handle_node_down; | ||
55 | void *usr_handle; | ||
56 | struct list_head nodesub_list; | ||
57 | }; | ||
58 | |||
59 | void nodesub_subscribe(struct node_subscr *node_sub, u32 addr, | ||
60 | void *usr_handle, net_ev_handler handle_down); | ||
61 | void nodesub_unsubscribe(struct node_subscr *node_sub); | ||
62 | |||
63 | #endif | ||
diff --git a/net/tipc/port.c b/net/tipc/port.c new file mode 100644 index 000000000000..66caca7abe92 --- /dev/null +++ b/net/tipc/port.c | |||
@@ -0,0 +1,1708 @@ | |||
1 | /* | ||
2 | * net/tipc/port.c: TIPC port code | ||
3 | * | ||
4 | * Copyright (c) 1992-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "config.h" | ||
39 | #include "dbg.h" | ||
40 | #include "port.h" | ||
41 | #include "addr.h" | ||
42 | #include "link.h" | ||
43 | #include "node.h" | ||
44 | #include "port.h" | ||
45 | #include "name_table.h" | ||
46 | #include "user_reg.h" | ||
47 | #include "msg.h" | ||
48 | #include "bcast.h" | ||
49 | |||
50 | /* Connection management: */ | ||
51 | #define PROBING_INTERVAL 3600000 /* [ms] => 1 h */ | ||
52 | #define CONFIRMED 0 | ||
53 | #define PROBING 1 | ||
54 | |||
55 | #define MAX_REJECT_SIZE 1024 | ||
56 | |||
57 | static struct sk_buff *msg_queue_head = 0; | ||
58 | static struct sk_buff *msg_queue_tail = 0; | ||
59 | |||
60 | spinlock_t port_list_lock = SPIN_LOCK_UNLOCKED; | ||
61 | static spinlock_t queue_lock = SPIN_LOCK_UNLOCKED; | ||
62 | |||
63 | LIST_HEAD(ports); | ||
64 | static void port_handle_node_down(unsigned long ref); | ||
65 | static struct sk_buff* port_build_self_abort_msg(struct port *,u32 err); | ||
66 | static struct sk_buff* port_build_peer_abort_msg(struct port *,u32 err); | ||
67 | static void port_timeout(unsigned long ref); | ||
68 | |||
69 | |||
70 | static inline u32 port_peernode(struct port *p_ptr) | ||
71 | { | ||
72 | return msg_destnode(&p_ptr->publ.phdr); | ||
73 | } | ||
74 | |||
75 | static inline u32 port_peerport(struct port *p_ptr) | ||
76 | { | ||
77 | return msg_destport(&p_ptr->publ.phdr); | ||
78 | } | ||
79 | |||
80 | static inline u32 port_out_seqno(struct port *p_ptr) | ||
81 | { | ||
82 | return msg_transp_seqno(&p_ptr->publ.phdr); | ||
83 | } | ||
84 | |||
85 | static inline void port_set_out_seqno(struct port *p_ptr, u32 seqno) | ||
86 | { | ||
87 | msg_set_transp_seqno(&p_ptr->publ.phdr,seqno); | ||
88 | } | ||
89 | |||
90 | static inline void port_incr_out_seqno(struct port *p_ptr) | ||
91 | { | ||
92 | struct tipc_msg *m = &p_ptr->publ.phdr; | ||
93 | |||
94 | if (likely(!msg_routed(m))) | ||
95 | return; | ||
96 | msg_set_transp_seqno(m, (msg_transp_seqno(m) + 1)); | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * tipc_multicast - send a multicast message to local and remote destinations | ||
101 | */ | ||
102 | |||
103 | int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, u32 domain, | ||
104 | u32 num_sect, struct iovec const *msg_sect) | ||
105 | { | ||
106 | struct tipc_msg *hdr; | ||
107 | struct sk_buff *buf; | ||
108 | struct sk_buff *ibuf = NULL; | ||
109 | struct port_list dports = {0, NULL, }; | ||
110 | struct port *oport = port_deref(ref); | ||
111 | int ext_targets; | ||
112 | int res; | ||
113 | |||
114 | if (unlikely(!oport)) | ||
115 | return -EINVAL; | ||
116 | |||
117 | /* Create multicast message */ | ||
118 | |||
119 | hdr = &oport->publ.phdr; | ||
120 | msg_set_type(hdr, TIPC_MCAST_MSG); | ||
121 | msg_set_nametype(hdr, seq->type); | ||
122 | msg_set_namelower(hdr, seq->lower); | ||
123 | msg_set_nameupper(hdr, seq->upper); | ||
124 | msg_set_hdr_sz(hdr, MCAST_H_SIZE); | ||
125 | res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, | ||
126 | !oport->user_port, &buf); | ||
127 | if (unlikely(!buf)) | ||
128 | return res; | ||
129 | |||
130 | /* Figure out where to send multicast message */ | ||
131 | |||
132 | ext_targets = nametbl_mc_translate(seq->type, seq->lower, seq->upper, | ||
133 | TIPC_NODE_SCOPE, &dports); | ||
134 | |||
135 | /* Send message to destinations (duplicate it only if necessary) */ | ||
136 | |||
137 | if (ext_targets) { | ||
138 | if (dports.count != 0) { | ||
139 | ibuf = skb_copy(buf, GFP_ATOMIC); | ||
140 | if (ibuf == NULL) { | ||
141 | port_list_free(&dports); | ||
142 | buf_discard(buf); | ||
143 | return -ENOMEM; | ||
144 | } | ||
145 | } | ||
146 | res = bclink_send_msg(buf); | ||
147 | if ((res < 0) && (dports.count != 0)) { | ||
148 | buf_discard(ibuf); | ||
149 | } | ||
150 | } else { | ||
151 | ibuf = buf; | ||
152 | } | ||
153 | |||
154 | if (res >= 0) { | ||
155 | if (ibuf) | ||
156 | port_recv_mcast(ibuf, &dports); | ||
157 | } else { | ||
158 | port_list_free(&dports); | ||
159 | } | ||
160 | return res; | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * port_recv_mcast - deliver multicast message to all destination ports | ||
165 | * | ||
166 | * If there is no port list, perform a lookup to create one | ||
167 | */ | ||
168 | |||
169 | void port_recv_mcast(struct sk_buff *buf, struct port_list *dp) | ||
170 | { | ||
171 | struct tipc_msg* msg; | ||
172 | struct port_list dports = {0, NULL, }; | ||
173 | struct port_list *item = dp; | ||
174 | int cnt = 0; | ||
175 | |||
176 | assert(buf); | ||
177 | msg = buf_msg(buf); | ||
178 | |||
179 | /* Create destination port list, if one wasn't supplied */ | ||
180 | |||
181 | if (dp == NULL) { | ||
182 | nametbl_mc_translate(msg_nametype(msg), | ||
183 | msg_namelower(msg), | ||
184 | msg_nameupper(msg), | ||
185 | TIPC_CLUSTER_SCOPE, | ||
186 | &dports); | ||
187 | item = dp = &dports; | ||
188 | } | ||
189 | |||
190 | /* Deliver a copy of message to each destination port */ | ||
191 | |||
192 | if (dp->count != 0) { | ||
193 | if (dp->count == 1) { | ||
194 | msg_set_destport(msg, dp->ports[0]); | ||
195 | port_recv_msg(buf); | ||
196 | port_list_free(dp); | ||
197 | return; | ||
198 | } | ||
199 | for (; cnt < dp->count; cnt++) { | ||
200 | int index = cnt % PLSIZE; | ||
201 | struct sk_buff *b = skb_clone(buf, GFP_ATOMIC); | ||
202 | |||
203 | if (b == NULL) { | ||
204 | warn("Buffer allocation failure\n"); | ||
205 | msg_dbg(msg, "LOST:"); | ||
206 | goto exit; | ||
207 | } | ||
208 | if ((index == 0) && (cnt != 0)) { | ||
209 | item = item->next; | ||
210 | } | ||
211 | msg_set_destport(buf_msg(b),item->ports[index]); | ||
212 | port_recv_msg(b); | ||
213 | } | ||
214 | } | ||
215 | exit: | ||
216 | buf_discard(buf); | ||
217 | port_list_free(dp); | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * tipc_createport_raw - create a native TIPC port | ||
222 | * | ||
223 | * Returns local port reference | ||
224 | */ | ||
225 | |||
226 | u32 tipc_createport_raw(void *usr_handle, | ||
227 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *), | ||
228 | void (*wakeup)(struct tipc_port *), | ||
229 | const u32 importance) | ||
230 | { | ||
231 | struct port *p_ptr; | ||
232 | struct tipc_msg *msg; | ||
233 | u32 ref; | ||
234 | |||
235 | p_ptr = kmalloc(sizeof(*p_ptr), GFP_ATOMIC); | ||
236 | if (p_ptr == NULL) { | ||
237 | warn("Memory squeeze; failed to create port\n"); | ||
238 | return 0; | ||
239 | } | ||
240 | memset(p_ptr, 0, sizeof(*p_ptr)); | ||
241 | ref = ref_acquire(p_ptr, &p_ptr->publ.lock); | ||
242 | if (!ref) { | ||
243 | warn("Reference Table Exhausted\n"); | ||
244 | kfree(p_ptr); | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | port_lock(ref); | ||
249 | p_ptr->publ.ref = ref; | ||
250 | msg = &p_ptr->publ.phdr; | ||
251 | msg_init(msg, DATA_LOW, TIPC_NAMED_MSG, TIPC_OK, LONG_H_SIZE, 0); | ||
252 | msg_set_orignode(msg, tipc_own_addr); | ||
253 | msg_set_prevnode(msg, tipc_own_addr); | ||
254 | msg_set_origport(msg, ref); | ||
255 | msg_set_importance(msg,importance); | ||
256 | p_ptr->last_in_seqno = 41; | ||
257 | p_ptr->sent = 1; | ||
258 | p_ptr->publ.usr_handle = usr_handle; | ||
259 | INIT_LIST_HEAD(&p_ptr->wait_list); | ||
260 | INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); | ||
261 | p_ptr->congested_link = 0; | ||
262 | p_ptr->max_pkt = MAX_PKT_DEFAULT; | ||
263 | p_ptr->dispatcher = dispatcher; | ||
264 | p_ptr->wakeup = wakeup; | ||
265 | p_ptr->user_port = 0; | ||
266 | k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref); | ||
267 | spin_lock_bh(&port_list_lock); | ||
268 | INIT_LIST_HEAD(&p_ptr->publications); | ||
269 | INIT_LIST_HEAD(&p_ptr->port_list); | ||
270 | list_add_tail(&p_ptr->port_list, &ports); | ||
271 | spin_unlock_bh(&port_list_lock); | ||
272 | port_unlock(p_ptr); | ||
273 | return ref; | ||
274 | } | ||
275 | |||
276 | int tipc_deleteport(u32 ref) | ||
277 | { | ||
278 | struct port *p_ptr; | ||
279 | struct sk_buff *buf = 0; | ||
280 | |||
281 | tipc_withdraw(ref, 0, 0); | ||
282 | p_ptr = port_lock(ref); | ||
283 | if (!p_ptr) | ||
284 | return -EINVAL; | ||
285 | |||
286 | ref_discard(ref); | ||
287 | port_unlock(p_ptr); | ||
288 | |||
289 | k_cancel_timer(&p_ptr->timer); | ||
290 | if (p_ptr->publ.connected) { | ||
291 | buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT); | ||
292 | nodesub_unsubscribe(&p_ptr->subscription); | ||
293 | } | ||
294 | if (p_ptr->user_port) { | ||
295 | reg_remove_port(p_ptr->user_port); | ||
296 | kfree(p_ptr->user_port); | ||
297 | } | ||
298 | |||
299 | spin_lock_bh(&port_list_lock); | ||
300 | list_del(&p_ptr->port_list); | ||
301 | list_del(&p_ptr->wait_list); | ||
302 | spin_unlock_bh(&port_list_lock); | ||
303 | k_term_timer(&p_ptr->timer); | ||
304 | kfree(p_ptr); | ||
305 | dbg("Deleted port %u\n", ref); | ||
306 | net_route_msg(buf); | ||
307 | return TIPC_OK; | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * tipc_get_port() - return port associated with 'ref' | ||
312 | * | ||
313 | * Note: Port is not locked. | ||
314 | */ | ||
315 | |||
316 | struct tipc_port *tipc_get_port(const u32 ref) | ||
317 | { | ||
318 | return (struct tipc_port *)ref_deref(ref); | ||
319 | } | ||
320 | |||
321 | /** | ||
322 | * tipc_get_handle - return user handle associated to port 'ref' | ||
323 | */ | ||
324 | |||
325 | void *tipc_get_handle(const u32 ref) | ||
326 | { | ||
327 | struct port *p_ptr; | ||
328 | void * handle; | ||
329 | |||
330 | p_ptr = port_lock(ref); | ||
331 | if (!p_ptr) | ||
332 | return 0; | ||
333 | handle = p_ptr->publ.usr_handle; | ||
334 | port_unlock(p_ptr); | ||
335 | return handle; | ||
336 | } | ||
337 | |||
338 | static inline int port_unreliable(struct port *p_ptr) | ||
339 | { | ||
340 | return msg_src_droppable(&p_ptr->publ.phdr); | ||
341 | } | ||
342 | |||
343 | int tipc_portunreliable(u32 ref, unsigned int *isunreliable) | ||
344 | { | ||
345 | struct port *p_ptr; | ||
346 | |||
347 | p_ptr = port_lock(ref); | ||
348 | if (!p_ptr) | ||
349 | return -EINVAL; | ||
350 | *isunreliable = port_unreliable(p_ptr); | ||
351 | spin_unlock_bh(p_ptr->publ.lock); | ||
352 | return TIPC_OK; | ||
353 | } | ||
354 | |||
355 | int tipc_set_portunreliable(u32 ref, unsigned int isunreliable) | ||
356 | { | ||
357 | struct port *p_ptr; | ||
358 | |||
359 | p_ptr = port_lock(ref); | ||
360 | if (!p_ptr) | ||
361 | return -EINVAL; | ||
362 | msg_set_src_droppable(&p_ptr->publ.phdr, (isunreliable != 0)); | ||
363 | port_unlock(p_ptr); | ||
364 | return TIPC_OK; | ||
365 | } | ||
366 | |||
367 | static inline int port_unreturnable(struct port *p_ptr) | ||
368 | { | ||
369 | return msg_dest_droppable(&p_ptr->publ.phdr); | ||
370 | } | ||
371 | |||
372 | int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable) | ||
373 | { | ||
374 | struct port *p_ptr; | ||
375 | |||
376 | p_ptr = port_lock(ref); | ||
377 | if (!p_ptr) | ||
378 | return -EINVAL; | ||
379 | *isunrejectable = port_unreturnable(p_ptr); | ||
380 | spin_unlock_bh(p_ptr->publ.lock); | ||
381 | return TIPC_OK; | ||
382 | } | ||
383 | |||
384 | int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable) | ||
385 | { | ||
386 | struct port *p_ptr; | ||
387 | |||
388 | p_ptr = port_lock(ref); | ||
389 | if (!p_ptr) | ||
390 | return -EINVAL; | ||
391 | msg_set_dest_droppable(&p_ptr->publ.phdr, (isunrejectable != 0)); | ||
392 | port_unlock(p_ptr); | ||
393 | return TIPC_OK; | ||
394 | } | ||
395 | |||
396 | /* | ||
397 | * port_build_proto_msg(): build a port level protocol | ||
398 | * or a connection abortion message. Called with | ||
399 | * tipc_port lock on. | ||
400 | */ | ||
401 | static struct sk_buff *port_build_proto_msg(u32 destport, u32 destnode, | ||
402 | u32 origport, u32 orignode, | ||
403 | u32 usr, u32 type, u32 err, | ||
404 | u32 seqno, u32 ack) | ||
405 | { | ||
406 | struct sk_buff *buf; | ||
407 | struct tipc_msg *msg; | ||
408 | |||
409 | buf = buf_acquire(LONG_H_SIZE); | ||
410 | if (buf) { | ||
411 | msg = buf_msg(buf); | ||
412 | msg_init(msg, usr, type, err, LONG_H_SIZE, destnode); | ||
413 | msg_set_destport(msg, destport); | ||
414 | msg_set_origport(msg, origport); | ||
415 | msg_set_destnode(msg, destnode); | ||
416 | msg_set_orignode(msg, orignode); | ||
417 | msg_set_transp_seqno(msg, seqno); | ||
418 | msg_set_msgcnt(msg, ack); | ||
419 | msg_dbg(msg, "PORT>SEND>:"); | ||
420 | } | ||
421 | return buf; | ||
422 | } | ||
423 | |||
424 | int tipc_set_msg_option(struct tipc_port *tp_ptr, const char *opt, const u32 sz) | ||
425 | { | ||
426 | msg_expand(&tp_ptr->phdr, msg_destnode(&tp_ptr->phdr)); | ||
427 | msg_set_options(&tp_ptr->phdr, opt, sz); | ||
428 | return TIPC_OK; | ||
429 | } | ||
430 | |||
431 | int tipc_reject_msg(struct sk_buff *buf, u32 err) | ||
432 | { | ||
433 | struct tipc_msg *msg = buf_msg(buf); | ||
434 | struct sk_buff *rbuf; | ||
435 | struct tipc_msg *rmsg; | ||
436 | int hdr_sz; | ||
437 | u32 imp = msg_importance(msg); | ||
438 | u32 data_sz = msg_data_sz(msg); | ||
439 | |||
440 | if (data_sz > MAX_REJECT_SIZE) | ||
441 | data_sz = MAX_REJECT_SIZE; | ||
442 | if (msg_connected(msg) && (imp < TIPC_CRITICAL_IMPORTANCE)) | ||
443 | imp++; | ||
444 | msg_dbg(msg, "port->rej: "); | ||
445 | |||
446 | /* discard rejected message if it shouldn't be returned to sender */ | ||
447 | if (msg_errcode(msg) || msg_dest_droppable(msg)) { | ||
448 | buf_discard(buf); | ||
449 | return data_sz; | ||
450 | } | ||
451 | |||
452 | /* construct rejected message */ | ||
453 | if (msg_mcast(msg)) | ||
454 | hdr_sz = MCAST_H_SIZE; | ||
455 | else | ||
456 | hdr_sz = LONG_H_SIZE; | ||
457 | rbuf = buf_acquire(data_sz + hdr_sz); | ||
458 | if (rbuf == NULL) { | ||
459 | buf_discard(buf); | ||
460 | return data_sz; | ||
461 | } | ||
462 | rmsg = buf_msg(rbuf); | ||
463 | msg_init(rmsg, imp, msg_type(msg), err, hdr_sz, msg_orignode(msg)); | ||
464 | msg_set_destport(rmsg, msg_origport(msg)); | ||
465 | msg_set_prevnode(rmsg, tipc_own_addr); | ||
466 | msg_set_origport(rmsg, msg_destport(msg)); | ||
467 | if (msg_short(msg)) | ||
468 | msg_set_orignode(rmsg, tipc_own_addr); | ||
469 | else | ||
470 | msg_set_orignode(rmsg, msg_destnode(msg)); | ||
471 | msg_set_size(rmsg, data_sz + hdr_sz); | ||
472 | msg_set_nametype(rmsg, msg_nametype(msg)); | ||
473 | msg_set_nameinst(rmsg, msg_nameinst(msg)); | ||
474 | memcpy(rbuf->data + hdr_sz, msg_data(msg), data_sz); | ||
475 | |||
476 | /* send self-abort message when rejecting on a connected port */ | ||
477 | if (msg_connected(msg)) { | ||
478 | struct sk_buff *abuf = 0; | ||
479 | struct port *p_ptr = port_lock(msg_destport(msg)); | ||
480 | |||
481 | if (p_ptr) { | ||
482 | if (p_ptr->publ.connected) | ||
483 | abuf = port_build_self_abort_msg(p_ptr, err); | ||
484 | port_unlock(p_ptr); | ||
485 | } | ||
486 | net_route_msg(abuf); | ||
487 | } | ||
488 | |||
489 | /* send rejected message */ | ||
490 | buf_discard(buf); | ||
491 | net_route_msg(rbuf); | ||
492 | return data_sz; | ||
493 | } | ||
494 | |||
495 | int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, | ||
496 | struct iovec const *msg_sect, u32 num_sect, | ||
497 | int err) | ||
498 | { | ||
499 | struct sk_buff *buf; | ||
500 | int res; | ||
501 | |||
502 | res = msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, | ||
503 | !p_ptr->user_port, &buf); | ||
504 | if (!buf) | ||
505 | return res; | ||
506 | |||
507 | return tipc_reject_msg(buf, err); | ||
508 | } | ||
509 | |||
510 | static void port_timeout(unsigned long ref) | ||
511 | { | ||
512 | struct port *p_ptr = port_lock(ref); | ||
513 | struct sk_buff *buf = 0; | ||
514 | |||
515 | if (!p_ptr || !p_ptr->publ.connected) | ||
516 | return; | ||
517 | |||
518 | /* Last probe answered ? */ | ||
519 | if (p_ptr->probing_state == PROBING) { | ||
520 | buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT); | ||
521 | } else { | ||
522 | buf = port_build_proto_msg(port_peerport(p_ptr), | ||
523 | port_peernode(p_ptr), | ||
524 | p_ptr->publ.ref, | ||
525 | tipc_own_addr, | ||
526 | CONN_MANAGER, | ||
527 | CONN_PROBE, | ||
528 | TIPC_OK, | ||
529 | port_out_seqno(p_ptr), | ||
530 | 0); | ||
531 | port_incr_out_seqno(p_ptr); | ||
532 | p_ptr->probing_state = PROBING; | ||
533 | k_start_timer(&p_ptr->timer, p_ptr->probing_interval); | ||
534 | } | ||
535 | port_unlock(p_ptr); | ||
536 | net_route_msg(buf); | ||
537 | } | ||
538 | |||
539 | |||
540 | static void port_handle_node_down(unsigned long ref) | ||
541 | { | ||
542 | struct port *p_ptr = port_lock(ref); | ||
543 | struct sk_buff* buf = 0; | ||
544 | |||
545 | if (!p_ptr) | ||
546 | return; | ||
547 | buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_NODE); | ||
548 | port_unlock(p_ptr); | ||
549 | net_route_msg(buf); | ||
550 | } | ||
551 | |||
552 | |||
553 | static struct sk_buff *port_build_self_abort_msg(struct port *p_ptr, u32 err) | ||
554 | { | ||
555 | u32 imp = msg_importance(&p_ptr->publ.phdr); | ||
556 | |||
557 | if (!p_ptr->publ.connected) | ||
558 | return 0; | ||
559 | if (imp < TIPC_CRITICAL_IMPORTANCE) | ||
560 | imp++; | ||
561 | return port_build_proto_msg(p_ptr->publ.ref, | ||
562 | tipc_own_addr, | ||
563 | port_peerport(p_ptr), | ||
564 | port_peernode(p_ptr), | ||
565 | imp, | ||
566 | TIPC_CONN_MSG, | ||
567 | err, | ||
568 | p_ptr->last_in_seqno + 1, | ||
569 | 0); | ||
570 | } | ||
571 | |||
572 | |||
573 | static struct sk_buff *port_build_peer_abort_msg(struct port *p_ptr, u32 err) | ||
574 | { | ||
575 | u32 imp = msg_importance(&p_ptr->publ.phdr); | ||
576 | |||
577 | if (!p_ptr->publ.connected) | ||
578 | return 0; | ||
579 | if (imp < TIPC_CRITICAL_IMPORTANCE) | ||
580 | imp++; | ||
581 | return port_build_proto_msg(port_peerport(p_ptr), | ||
582 | port_peernode(p_ptr), | ||
583 | p_ptr->publ.ref, | ||
584 | tipc_own_addr, | ||
585 | imp, | ||
586 | TIPC_CONN_MSG, | ||
587 | err, | ||
588 | port_out_seqno(p_ptr), | ||
589 | 0); | ||
590 | } | ||
591 | |||
592 | void port_recv_proto_msg(struct sk_buff *buf) | ||
593 | { | ||
594 | struct tipc_msg *msg = buf_msg(buf); | ||
595 | struct port *p_ptr = port_lock(msg_destport(msg)); | ||
596 | u32 err = TIPC_OK; | ||
597 | struct sk_buff *r_buf = 0; | ||
598 | struct sk_buff *abort_buf = 0; | ||
599 | |||
600 | msg_dbg(msg, "PORT<RECV<:"); | ||
601 | |||
602 | if (!p_ptr) { | ||
603 | err = TIPC_ERR_NO_PORT; | ||
604 | } else if (p_ptr->publ.connected) { | ||
605 | if (port_peernode(p_ptr) != msg_orignode(msg)) | ||
606 | err = TIPC_ERR_NO_PORT; | ||
607 | if (port_peerport(p_ptr) != msg_origport(msg)) | ||
608 | err = TIPC_ERR_NO_PORT; | ||
609 | if (!err && msg_routed(msg)) { | ||
610 | u32 seqno = msg_transp_seqno(msg); | ||
611 | u32 myno = ++p_ptr->last_in_seqno; | ||
612 | if (seqno != myno) { | ||
613 | err = TIPC_ERR_NO_PORT; | ||
614 | abort_buf = port_build_self_abort_msg(p_ptr, err); | ||
615 | } | ||
616 | } | ||
617 | if (msg_type(msg) == CONN_ACK) { | ||
618 | int wakeup = port_congested(p_ptr) && | ||
619 | p_ptr->publ.congested && | ||
620 | p_ptr->wakeup; | ||
621 | p_ptr->acked += msg_msgcnt(msg); | ||
622 | if (port_congested(p_ptr)) | ||
623 | goto exit; | ||
624 | p_ptr->publ.congested = 0; | ||
625 | if (!wakeup) | ||
626 | goto exit; | ||
627 | p_ptr->wakeup(&p_ptr->publ); | ||
628 | goto exit; | ||
629 | } | ||
630 | } else if (p_ptr->publ.published) { | ||
631 | err = TIPC_ERR_NO_PORT; | ||
632 | } | ||
633 | if (err) { | ||
634 | r_buf = port_build_proto_msg(msg_origport(msg), | ||
635 | msg_orignode(msg), | ||
636 | msg_destport(msg), | ||
637 | tipc_own_addr, | ||
638 | DATA_HIGH, | ||
639 | TIPC_CONN_MSG, | ||
640 | err, | ||
641 | 0, | ||
642 | 0); | ||
643 | goto exit; | ||
644 | } | ||
645 | |||
646 | /* All is fine */ | ||
647 | if (msg_type(msg) == CONN_PROBE) { | ||
648 | r_buf = port_build_proto_msg(msg_origport(msg), | ||
649 | msg_orignode(msg), | ||
650 | msg_destport(msg), | ||
651 | tipc_own_addr, | ||
652 | CONN_MANAGER, | ||
653 | CONN_PROBE_REPLY, | ||
654 | TIPC_OK, | ||
655 | port_out_seqno(p_ptr), | ||
656 | 0); | ||
657 | } | ||
658 | p_ptr->probing_state = CONFIRMED; | ||
659 | port_incr_out_seqno(p_ptr); | ||
660 | exit: | ||
661 | if (p_ptr) | ||
662 | port_unlock(p_ptr); | ||
663 | net_route_msg(r_buf); | ||
664 | net_route_msg(abort_buf); | ||
665 | buf_discard(buf); | ||
666 | } | ||
667 | |||
668 | static void port_print(struct port *p_ptr, struct print_buf *buf, int full_id) | ||
669 | { | ||
670 | struct publication *publ; | ||
671 | |||
672 | if (full_id) | ||
673 | tipc_printf(buf, "<%u.%u.%u:%u>:", | ||
674 | tipc_zone(tipc_own_addr), tipc_cluster(tipc_own_addr), | ||
675 | tipc_node(tipc_own_addr), p_ptr->publ.ref); | ||
676 | else | ||
677 | tipc_printf(buf, "%-10u:", p_ptr->publ.ref); | ||
678 | |||
679 | if (p_ptr->publ.connected) { | ||
680 | u32 dport = port_peerport(p_ptr); | ||
681 | u32 destnode = port_peernode(p_ptr); | ||
682 | |||
683 | tipc_printf(buf, " connected to <%u.%u.%u:%u>", | ||
684 | tipc_zone(destnode), tipc_cluster(destnode), | ||
685 | tipc_node(destnode), dport); | ||
686 | if (p_ptr->publ.conn_type != 0) | ||
687 | tipc_printf(buf, " via {%u,%u}", | ||
688 | p_ptr->publ.conn_type, | ||
689 | p_ptr->publ.conn_instance); | ||
690 | } | ||
691 | else if (p_ptr->publ.published) { | ||
692 | tipc_printf(buf, " bound to"); | ||
693 | list_for_each_entry(publ, &p_ptr->publications, pport_list) { | ||
694 | if (publ->lower == publ->upper) | ||
695 | tipc_printf(buf, " {%u,%u}", publ->type, | ||
696 | publ->lower); | ||
697 | else | ||
698 | tipc_printf(buf, " {%u,%u,%u}", publ->type, | ||
699 | publ->lower, publ->upper); | ||
700 | } | ||
701 | } | ||
702 | tipc_printf(buf, "\n"); | ||
703 | } | ||
704 | |||
705 | #define MAX_PORT_QUERY 32768 | ||
706 | |||
707 | struct sk_buff *port_get_ports(void) | ||
708 | { | ||
709 | struct sk_buff *buf; | ||
710 | struct tlv_desc *rep_tlv; | ||
711 | struct print_buf pb; | ||
712 | struct port *p_ptr; | ||
713 | int str_len; | ||
714 | |||
715 | buf = cfg_reply_alloc(TLV_SPACE(MAX_PORT_QUERY)); | ||
716 | if (!buf) | ||
717 | return NULL; | ||
718 | rep_tlv = (struct tlv_desc *)buf->data; | ||
719 | |||
720 | printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_QUERY); | ||
721 | spin_lock_bh(&port_list_lock); | ||
722 | list_for_each_entry(p_ptr, &ports, port_list) { | ||
723 | spin_lock_bh(p_ptr->publ.lock); | ||
724 | port_print(p_ptr, &pb, 0); | ||
725 | spin_unlock_bh(p_ptr->publ.lock); | ||
726 | } | ||
727 | spin_unlock_bh(&port_list_lock); | ||
728 | str_len = printbuf_validate(&pb); | ||
729 | |||
730 | skb_put(buf, TLV_SPACE(str_len)); | ||
731 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | ||
732 | |||
733 | return buf; | ||
734 | } | ||
735 | |||
736 | #if 0 | ||
737 | |||
738 | #define MAX_PORT_STATS 2000 | ||
739 | |||
740 | struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space) | ||
741 | { | ||
742 | u32 ref; | ||
743 | struct port *p_ptr; | ||
744 | struct sk_buff *buf; | ||
745 | struct tlv_desc *rep_tlv; | ||
746 | struct print_buf pb; | ||
747 | int str_len; | ||
748 | |||
749 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_PORT_REF)) | ||
750 | return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
751 | |||
752 | ref = *(u32 *)TLV_DATA(req_tlv_area); | ||
753 | ref = ntohl(ref); | ||
754 | |||
755 | p_ptr = port_lock(ref); | ||
756 | if (!p_ptr) | ||
757 | return cfg_reply_error_string("port not found"); | ||
758 | |||
759 | buf = cfg_reply_alloc(TLV_SPACE(MAX_PORT_STATS)); | ||
760 | if (!buf) { | ||
761 | port_unlock(p_ptr); | ||
762 | return NULL; | ||
763 | } | ||
764 | rep_tlv = (struct tlv_desc *)buf->data; | ||
765 | |||
766 | printbuf_init(&pb, TLV_DATA(rep_tlv), MAX_PORT_STATS); | ||
767 | port_print(p_ptr, &pb, 1); | ||
768 | /* NEED TO FILL IN ADDITIONAL PORT STATISTICS HERE */ | ||
769 | port_unlock(p_ptr); | ||
770 | str_len = printbuf_validate(&pb); | ||
771 | |||
772 | skb_put(buf, TLV_SPACE(str_len)); | ||
773 | TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); | ||
774 | |||
775 | return buf; | ||
776 | } | ||
777 | |||
778 | #endif | ||
779 | |||
780 | void port_reinit(void) | ||
781 | { | ||
782 | struct port *p_ptr; | ||
783 | struct tipc_msg *msg; | ||
784 | |||
785 | spin_lock_bh(&port_list_lock); | ||
786 | list_for_each_entry(p_ptr, &ports, port_list) { | ||
787 | msg = &p_ptr->publ.phdr; | ||
788 | if (msg_orignode(msg) == tipc_own_addr) | ||
789 | break; | ||
790 | msg_set_orignode(msg, tipc_own_addr); | ||
791 | } | ||
792 | spin_unlock_bh(&port_list_lock); | ||
793 | } | ||
794 | |||
795 | |||
796 | /* | ||
797 | * port_dispatcher_sigh(): Signal handler for messages destinated | ||
798 | * to the tipc_port interface. | ||
799 | */ | ||
800 | |||
801 | static void port_dispatcher_sigh(void *dummy) | ||
802 | { | ||
803 | struct sk_buff *buf; | ||
804 | |||
805 | spin_lock_bh(&queue_lock); | ||
806 | buf = msg_queue_head; | ||
807 | msg_queue_head = 0; | ||
808 | spin_unlock_bh(&queue_lock); | ||
809 | |||
810 | while (buf) { | ||
811 | struct port *p_ptr; | ||
812 | struct user_port *up_ptr; | ||
813 | struct tipc_portid orig; | ||
814 | struct tipc_name_seq dseq; | ||
815 | void *usr_handle; | ||
816 | int connected; | ||
817 | int published; | ||
818 | |||
819 | struct sk_buff *next = buf->next; | ||
820 | struct tipc_msg *msg = buf_msg(buf); | ||
821 | u32 dref = msg_destport(msg); | ||
822 | |||
823 | p_ptr = port_lock(dref); | ||
824 | if (!p_ptr) { | ||
825 | /* Port deleted while msg in queue */ | ||
826 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); | ||
827 | buf = next; | ||
828 | continue; | ||
829 | } | ||
830 | orig.ref = msg_origport(msg); | ||
831 | orig.node = msg_orignode(msg); | ||
832 | up_ptr = p_ptr->user_port; | ||
833 | usr_handle = up_ptr->usr_handle; | ||
834 | connected = p_ptr->publ.connected; | ||
835 | published = p_ptr->publ.published; | ||
836 | |||
837 | if (unlikely(msg_errcode(msg))) | ||
838 | goto err; | ||
839 | |||
840 | switch (msg_type(msg)) { | ||
841 | |||
842 | case TIPC_CONN_MSG:{ | ||
843 | tipc_conn_msg_event cb = up_ptr->conn_msg_cb; | ||
844 | u32 peer_port = port_peerport(p_ptr); | ||
845 | u32 peer_node = port_peernode(p_ptr); | ||
846 | |||
847 | spin_unlock_bh(p_ptr->publ.lock); | ||
848 | if (unlikely(!connected)) { | ||
849 | if (unlikely(published)) | ||
850 | goto reject; | ||
851 | tipc_connect2port(dref,&orig); | ||
852 | } | ||
853 | if (unlikely(msg_origport(msg) != peer_port)) | ||
854 | goto reject; | ||
855 | if (unlikely(msg_orignode(msg) != peer_node)) | ||
856 | goto reject; | ||
857 | if (unlikely(!cb)) | ||
858 | goto reject; | ||
859 | if (unlikely(++p_ptr->publ.conn_unacked >= | ||
860 | TIPC_FLOW_CONTROL_WIN)) | ||
861 | tipc_acknowledge(dref, | ||
862 | p_ptr->publ.conn_unacked); | ||
863 | skb_pull(buf, msg_hdr_sz(msg)); | ||
864 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
865 | msg_data_sz(msg)); | ||
866 | break; | ||
867 | } | ||
868 | case TIPC_DIRECT_MSG:{ | ||
869 | tipc_msg_event cb = up_ptr->msg_cb; | ||
870 | |||
871 | spin_unlock_bh(p_ptr->publ.lock); | ||
872 | if (unlikely(connected)) | ||
873 | goto reject; | ||
874 | if (unlikely(!cb)) | ||
875 | goto reject; | ||
876 | skb_pull(buf, msg_hdr_sz(msg)); | ||
877 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
878 | msg_data_sz(msg), msg_importance(msg), | ||
879 | &orig); | ||
880 | break; | ||
881 | } | ||
882 | case TIPC_NAMED_MSG:{ | ||
883 | tipc_named_msg_event cb = up_ptr->named_msg_cb; | ||
884 | |||
885 | spin_unlock_bh(p_ptr->publ.lock); | ||
886 | if (unlikely(connected)) | ||
887 | goto reject; | ||
888 | if (unlikely(!cb)) | ||
889 | goto reject; | ||
890 | if (unlikely(!published)) | ||
891 | goto reject; | ||
892 | dseq.type = msg_nametype(msg); | ||
893 | dseq.lower = msg_nameinst(msg); | ||
894 | dseq.upper = dseq.lower; | ||
895 | skb_pull(buf, msg_hdr_sz(msg)); | ||
896 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
897 | msg_data_sz(msg), msg_importance(msg), | ||
898 | &orig, &dseq); | ||
899 | break; | ||
900 | } | ||
901 | } | ||
902 | if (buf) | ||
903 | buf_discard(buf); | ||
904 | buf = next; | ||
905 | continue; | ||
906 | err: | ||
907 | switch (msg_type(msg)) { | ||
908 | |||
909 | case TIPC_CONN_MSG:{ | ||
910 | tipc_conn_shutdown_event cb = | ||
911 | up_ptr->conn_err_cb; | ||
912 | u32 peer_port = port_peerport(p_ptr); | ||
913 | u32 peer_node = port_peernode(p_ptr); | ||
914 | |||
915 | spin_unlock_bh(p_ptr->publ.lock); | ||
916 | if (!connected || !cb) | ||
917 | break; | ||
918 | if (msg_origport(msg) != peer_port) | ||
919 | break; | ||
920 | if (msg_orignode(msg) != peer_node) | ||
921 | break; | ||
922 | tipc_disconnect(dref); | ||
923 | skb_pull(buf, msg_hdr_sz(msg)); | ||
924 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
925 | msg_data_sz(msg), msg_errcode(msg)); | ||
926 | break; | ||
927 | } | ||
928 | case TIPC_DIRECT_MSG:{ | ||
929 | tipc_msg_err_event cb = up_ptr->err_cb; | ||
930 | |||
931 | spin_unlock_bh(p_ptr->publ.lock); | ||
932 | if (connected || !cb) | ||
933 | break; | ||
934 | skb_pull(buf, msg_hdr_sz(msg)); | ||
935 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
936 | msg_data_sz(msg), msg_errcode(msg), &orig); | ||
937 | break; | ||
938 | } | ||
939 | case TIPC_NAMED_MSG:{ | ||
940 | tipc_named_msg_err_event cb = | ||
941 | up_ptr->named_err_cb; | ||
942 | |||
943 | spin_unlock_bh(p_ptr->publ.lock); | ||
944 | if (connected || !cb) | ||
945 | break; | ||
946 | dseq.type = msg_nametype(msg); | ||
947 | dseq.lower = msg_nameinst(msg); | ||
948 | dseq.upper = dseq.lower; | ||
949 | skb_pull(buf, msg_hdr_sz(msg)); | ||
950 | cb(usr_handle, dref, &buf, msg_data(msg), | ||
951 | msg_data_sz(msg), msg_errcode(msg), &dseq); | ||
952 | break; | ||
953 | } | ||
954 | } | ||
955 | if (buf) | ||
956 | buf_discard(buf); | ||
957 | buf = next; | ||
958 | continue; | ||
959 | reject: | ||
960 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); | ||
961 | buf = next; | ||
962 | } | ||
963 | } | ||
964 | |||
965 | /* | ||
966 | * port_dispatcher(): Dispatcher for messages destinated | ||
967 | * to the tipc_port interface. Called with port locked. | ||
968 | */ | ||
969 | |||
970 | static u32 port_dispatcher(struct tipc_port *dummy, struct sk_buff *buf) | ||
971 | { | ||
972 | buf->next = NULL; | ||
973 | spin_lock_bh(&queue_lock); | ||
974 | if (msg_queue_head) { | ||
975 | msg_queue_tail->next = buf; | ||
976 | msg_queue_tail = buf; | ||
977 | } else { | ||
978 | msg_queue_tail = msg_queue_head = buf; | ||
979 | k_signal((Handler)port_dispatcher_sigh, 0); | ||
980 | } | ||
981 | spin_unlock_bh(&queue_lock); | ||
982 | return TIPC_OK; | ||
983 | } | ||
984 | |||
985 | /* | ||
986 | * Wake up port after congestion: Called with port locked, | ||
987 | * | ||
988 | */ | ||
989 | |||
990 | static void port_wakeup_sh(unsigned long ref) | ||
991 | { | ||
992 | struct port *p_ptr; | ||
993 | struct user_port *up_ptr; | ||
994 | tipc_continue_event cb = 0; | ||
995 | void *uh = 0; | ||
996 | |||
997 | p_ptr = port_lock(ref); | ||
998 | if (p_ptr) { | ||
999 | up_ptr = p_ptr->user_port; | ||
1000 | if (up_ptr) { | ||
1001 | cb = up_ptr->continue_event_cb; | ||
1002 | uh = up_ptr->usr_handle; | ||
1003 | } | ||
1004 | port_unlock(p_ptr); | ||
1005 | } | ||
1006 | if (cb) | ||
1007 | cb(uh, ref); | ||
1008 | } | ||
1009 | |||
1010 | |||
1011 | static void port_wakeup(struct tipc_port *p_ptr) | ||
1012 | { | ||
1013 | k_signal((Handler)port_wakeup_sh, p_ptr->ref); | ||
1014 | } | ||
1015 | |||
1016 | void tipc_acknowledge(u32 ref, u32 ack) | ||
1017 | { | ||
1018 | struct port *p_ptr; | ||
1019 | struct sk_buff *buf = 0; | ||
1020 | |||
1021 | p_ptr = port_lock(ref); | ||
1022 | if (!p_ptr) | ||
1023 | return; | ||
1024 | if (p_ptr->publ.connected) { | ||
1025 | p_ptr->publ.conn_unacked -= ack; | ||
1026 | buf = port_build_proto_msg(port_peerport(p_ptr), | ||
1027 | port_peernode(p_ptr), | ||
1028 | ref, | ||
1029 | tipc_own_addr, | ||
1030 | CONN_MANAGER, | ||
1031 | CONN_ACK, | ||
1032 | TIPC_OK, | ||
1033 | port_out_seqno(p_ptr), | ||
1034 | ack); | ||
1035 | } | ||
1036 | port_unlock(p_ptr); | ||
1037 | net_route_msg(buf); | ||
1038 | } | ||
1039 | |||
1040 | /* | ||
1041 | * tipc_createport(): user level call. Will add port to | ||
1042 | * registry if non-zero user_ref. | ||
1043 | */ | ||
1044 | |||
1045 | int tipc_createport(u32 user_ref, | ||
1046 | void *usr_handle, | ||
1047 | unsigned int importance, | ||
1048 | tipc_msg_err_event error_cb, | ||
1049 | tipc_named_msg_err_event named_error_cb, | ||
1050 | tipc_conn_shutdown_event conn_error_cb, | ||
1051 | tipc_msg_event msg_cb, | ||
1052 | tipc_named_msg_event named_msg_cb, | ||
1053 | tipc_conn_msg_event conn_msg_cb, | ||
1054 | tipc_continue_event continue_event_cb,/* May be zero */ | ||
1055 | u32 *portref) | ||
1056 | { | ||
1057 | struct user_port *up_ptr; | ||
1058 | struct port *p_ptr; | ||
1059 | u32 ref; | ||
1060 | |||
1061 | up_ptr = (struct user_port *)kmalloc(sizeof(*up_ptr), GFP_ATOMIC); | ||
1062 | if (up_ptr == NULL) { | ||
1063 | return -ENOMEM; | ||
1064 | } | ||
1065 | ref = tipc_createport_raw(0, port_dispatcher, port_wakeup, importance); | ||
1066 | p_ptr = port_lock(ref); | ||
1067 | if (!p_ptr) { | ||
1068 | kfree(up_ptr); | ||
1069 | return -ENOMEM; | ||
1070 | } | ||
1071 | |||
1072 | p_ptr->user_port = up_ptr; | ||
1073 | up_ptr->user_ref = user_ref; | ||
1074 | up_ptr->usr_handle = usr_handle; | ||
1075 | up_ptr->ref = p_ptr->publ.ref; | ||
1076 | up_ptr->err_cb = error_cb; | ||
1077 | up_ptr->named_err_cb = named_error_cb; | ||
1078 | up_ptr->conn_err_cb = conn_error_cb; | ||
1079 | up_ptr->msg_cb = msg_cb; | ||
1080 | up_ptr->named_msg_cb = named_msg_cb; | ||
1081 | up_ptr->conn_msg_cb = conn_msg_cb; | ||
1082 | up_ptr->continue_event_cb = continue_event_cb; | ||
1083 | INIT_LIST_HEAD(&up_ptr->uport_list); | ||
1084 | reg_add_port(up_ptr); | ||
1085 | *portref = p_ptr->publ.ref; | ||
1086 | dbg(" tipc_createport: %x with ref %u\n", p_ptr, p_ptr->publ.ref); | ||
1087 | port_unlock(p_ptr); | ||
1088 | return TIPC_OK; | ||
1089 | } | ||
1090 | |||
1091 | int tipc_ownidentity(u32 ref, struct tipc_portid *id) | ||
1092 | { | ||
1093 | id->ref = ref; | ||
1094 | id->node = tipc_own_addr; | ||
1095 | return TIPC_OK; | ||
1096 | } | ||
1097 | |||
1098 | int tipc_portimportance(u32 ref, unsigned int *importance) | ||
1099 | { | ||
1100 | struct port *p_ptr; | ||
1101 | |||
1102 | p_ptr = port_lock(ref); | ||
1103 | if (!p_ptr) | ||
1104 | return -EINVAL; | ||
1105 | *importance = (unsigned int)msg_importance(&p_ptr->publ.phdr); | ||
1106 | spin_unlock_bh(p_ptr->publ.lock); | ||
1107 | return TIPC_OK; | ||
1108 | } | ||
1109 | |||
1110 | int tipc_set_portimportance(u32 ref, unsigned int imp) | ||
1111 | { | ||
1112 | struct port *p_ptr; | ||
1113 | |||
1114 | if (imp > TIPC_CRITICAL_IMPORTANCE) | ||
1115 | return -EINVAL; | ||
1116 | |||
1117 | p_ptr = port_lock(ref); | ||
1118 | if (!p_ptr) | ||
1119 | return -EINVAL; | ||
1120 | msg_set_importance(&p_ptr->publ.phdr, (u32)imp); | ||
1121 | spin_unlock_bh(p_ptr->publ.lock); | ||
1122 | return TIPC_OK; | ||
1123 | } | ||
1124 | |||
1125 | |||
1126 | int tipc_publish(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) | ||
1127 | { | ||
1128 | struct port *p_ptr; | ||
1129 | struct publication *publ; | ||
1130 | u32 key; | ||
1131 | int res = -EINVAL; | ||
1132 | |||
1133 | p_ptr = port_lock(ref); | ||
1134 | dbg("tipc_publ %u, p_ptr = %x, conn = %x, scope = %x, " | ||
1135 | "lower = %u, upper = %u\n", | ||
1136 | ref, p_ptr, p_ptr->publ.connected, scope, seq->lower, seq->upper); | ||
1137 | if (!p_ptr) | ||
1138 | return -EINVAL; | ||
1139 | if (p_ptr->publ.connected) | ||
1140 | goto exit; | ||
1141 | if (seq->lower > seq->upper) | ||
1142 | goto exit; | ||
1143 | if ((scope < TIPC_ZONE_SCOPE) || (scope > TIPC_NODE_SCOPE)) | ||
1144 | goto exit; | ||
1145 | key = ref + p_ptr->pub_count + 1; | ||
1146 | if (key == ref) { | ||
1147 | res = -EADDRINUSE; | ||
1148 | goto exit; | ||
1149 | } | ||
1150 | publ = nametbl_publish(seq->type, seq->lower, seq->upper, | ||
1151 | scope, p_ptr->publ.ref, key); | ||
1152 | if (publ) { | ||
1153 | list_add(&publ->pport_list, &p_ptr->publications); | ||
1154 | p_ptr->pub_count++; | ||
1155 | p_ptr->publ.published = 1; | ||
1156 | res = TIPC_OK; | ||
1157 | } | ||
1158 | exit: | ||
1159 | port_unlock(p_ptr); | ||
1160 | return res; | ||
1161 | } | ||
1162 | |||
1163 | int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq) | ||
1164 | { | ||
1165 | struct port *p_ptr; | ||
1166 | struct publication *publ; | ||
1167 | struct publication *tpubl; | ||
1168 | int res = -EINVAL; | ||
1169 | |||
1170 | p_ptr = port_lock(ref); | ||
1171 | if (!p_ptr) | ||
1172 | return -EINVAL; | ||
1173 | if (!p_ptr->publ.published) | ||
1174 | goto exit; | ||
1175 | if (!seq) { | ||
1176 | list_for_each_entry_safe(publ, tpubl, | ||
1177 | &p_ptr->publications, pport_list) { | ||
1178 | nametbl_withdraw(publ->type, publ->lower, | ||
1179 | publ->ref, publ->key); | ||
1180 | } | ||
1181 | res = TIPC_OK; | ||
1182 | } else { | ||
1183 | list_for_each_entry_safe(publ, tpubl, | ||
1184 | &p_ptr->publications, pport_list) { | ||
1185 | if (publ->scope != scope) | ||
1186 | continue; | ||
1187 | if (publ->type != seq->type) | ||
1188 | continue; | ||
1189 | if (publ->lower != seq->lower) | ||
1190 | continue; | ||
1191 | if (publ->upper != seq->upper) | ||
1192 | break; | ||
1193 | nametbl_withdraw(publ->type, publ->lower, | ||
1194 | publ->ref, publ->key); | ||
1195 | res = TIPC_OK; | ||
1196 | break; | ||
1197 | } | ||
1198 | } | ||
1199 | if (list_empty(&p_ptr->publications)) | ||
1200 | p_ptr->publ.published = 0; | ||
1201 | exit: | ||
1202 | port_unlock(p_ptr); | ||
1203 | return res; | ||
1204 | } | ||
1205 | |||
1206 | int tipc_connect2port(u32 ref, struct tipc_portid const *peer) | ||
1207 | { | ||
1208 | struct port *p_ptr; | ||
1209 | struct tipc_msg *msg; | ||
1210 | int res = -EINVAL; | ||
1211 | |||
1212 | p_ptr = port_lock(ref); | ||
1213 | if (!p_ptr) | ||
1214 | return -EINVAL; | ||
1215 | if (p_ptr->publ.published || p_ptr->publ.connected) | ||
1216 | goto exit; | ||
1217 | if (!peer->ref) | ||
1218 | goto exit; | ||
1219 | |||
1220 | msg = &p_ptr->publ.phdr; | ||
1221 | msg_set_destnode(msg, peer->node); | ||
1222 | msg_set_destport(msg, peer->ref); | ||
1223 | msg_set_orignode(msg, tipc_own_addr); | ||
1224 | msg_set_origport(msg, p_ptr->publ.ref); | ||
1225 | msg_set_transp_seqno(msg, 42); | ||
1226 | msg_set_type(msg, TIPC_CONN_MSG); | ||
1227 | if (!may_route(peer->node)) | ||
1228 | msg_set_hdr_sz(msg, SHORT_H_SIZE); | ||
1229 | else | ||
1230 | msg_set_hdr_sz(msg, LONG_H_SIZE); | ||
1231 | |||
1232 | p_ptr->probing_interval = PROBING_INTERVAL; | ||
1233 | p_ptr->probing_state = CONFIRMED; | ||
1234 | p_ptr->publ.connected = 1; | ||
1235 | k_start_timer(&p_ptr->timer, p_ptr->probing_interval); | ||
1236 | |||
1237 | nodesub_subscribe(&p_ptr->subscription,peer->node, | ||
1238 | (void *)(unsigned long)ref, | ||
1239 | (net_ev_handler)port_handle_node_down); | ||
1240 | res = TIPC_OK; | ||
1241 | exit: | ||
1242 | port_unlock(p_ptr); | ||
1243 | p_ptr->max_pkt = link_get_max_pkt(peer->node, ref); | ||
1244 | return res; | ||
1245 | } | ||
1246 | |||
1247 | /* | ||
1248 | * tipc_disconnect(): Disconnect port form peer. | ||
1249 | * This is a node local operation. | ||
1250 | */ | ||
1251 | |||
1252 | int tipc_disconnect(u32 ref) | ||
1253 | { | ||
1254 | struct port *p_ptr; | ||
1255 | int res = -ENOTCONN; | ||
1256 | |||
1257 | p_ptr = port_lock(ref); | ||
1258 | if (!p_ptr) | ||
1259 | return -EINVAL; | ||
1260 | if (p_ptr->publ.connected) { | ||
1261 | p_ptr->publ.connected = 0; | ||
1262 | /* let timer expire on it's own to avoid deadlock! */ | ||
1263 | nodesub_unsubscribe(&p_ptr->subscription); | ||
1264 | res = TIPC_OK; | ||
1265 | } | ||
1266 | port_unlock(p_ptr); | ||
1267 | return res; | ||
1268 | } | ||
1269 | |||
1270 | /* | ||
1271 | * tipc_shutdown(): Send a SHUTDOWN msg to peer and disconnect | ||
1272 | */ | ||
1273 | int tipc_shutdown(u32 ref) | ||
1274 | { | ||
1275 | struct port *p_ptr; | ||
1276 | struct sk_buff *buf = 0; | ||
1277 | |||
1278 | p_ptr = port_lock(ref); | ||
1279 | if (!p_ptr) | ||
1280 | return -EINVAL; | ||
1281 | |||
1282 | if (p_ptr->publ.connected) { | ||
1283 | u32 imp = msg_importance(&p_ptr->publ.phdr); | ||
1284 | if (imp < TIPC_CRITICAL_IMPORTANCE) | ||
1285 | imp++; | ||
1286 | buf = port_build_proto_msg(port_peerport(p_ptr), | ||
1287 | port_peernode(p_ptr), | ||
1288 | ref, | ||
1289 | tipc_own_addr, | ||
1290 | imp, | ||
1291 | TIPC_CONN_MSG, | ||
1292 | TIPC_CONN_SHUTDOWN, | ||
1293 | port_out_seqno(p_ptr), | ||
1294 | 0); | ||
1295 | } | ||
1296 | port_unlock(p_ptr); | ||
1297 | net_route_msg(buf); | ||
1298 | return tipc_disconnect(ref); | ||
1299 | } | ||
1300 | |||
1301 | int tipc_isconnected(u32 ref, int *isconnected) | ||
1302 | { | ||
1303 | struct port *p_ptr; | ||
1304 | |||
1305 | p_ptr = port_lock(ref); | ||
1306 | if (!p_ptr) | ||
1307 | return -EINVAL; | ||
1308 | *isconnected = p_ptr->publ.connected; | ||
1309 | port_unlock(p_ptr); | ||
1310 | return TIPC_OK; | ||
1311 | } | ||
1312 | |||
1313 | int tipc_peer(u32 ref, struct tipc_portid *peer) | ||
1314 | { | ||
1315 | struct port *p_ptr; | ||
1316 | int res; | ||
1317 | |||
1318 | p_ptr = port_lock(ref); | ||
1319 | if (!p_ptr) | ||
1320 | return -EINVAL; | ||
1321 | if (p_ptr->publ.connected) { | ||
1322 | peer->ref = port_peerport(p_ptr); | ||
1323 | peer->node = port_peernode(p_ptr); | ||
1324 | res = TIPC_OK; | ||
1325 | } else | ||
1326 | res = -ENOTCONN; | ||
1327 | port_unlock(p_ptr); | ||
1328 | return res; | ||
1329 | } | ||
1330 | |||
1331 | int tipc_ref_valid(u32 ref) | ||
1332 | { | ||
1333 | /* Works irrespective of type */ | ||
1334 | return !!ref_deref(ref); | ||
1335 | } | ||
1336 | |||
1337 | |||
1338 | /* | ||
1339 | * port_recv_sections(): Concatenate and deliver sectioned | ||
1340 | * message for this node. | ||
1341 | */ | ||
1342 | |||
1343 | int port_recv_sections(struct port *sender, unsigned int num_sect, | ||
1344 | struct iovec const *msg_sect) | ||
1345 | { | ||
1346 | struct sk_buff *buf; | ||
1347 | int res; | ||
1348 | |||
1349 | res = msg_build(&sender->publ.phdr, msg_sect, num_sect, | ||
1350 | MAX_MSG_SIZE, !sender->user_port, &buf); | ||
1351 | if (likely(buf)) | ||
1352 | port_recv_msg(buf); | ||
1353 | return res; | ||
1354 | } | ||
1355 | |||
1356 | /** | ||
1357 | * tipc_send - send message sections on connection | ||
1358 | */ | ||
1359 | |||
1360 | int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) | ||
1361 | { | ||
1362 | struct port *p_ptr; | ||
1363 | u32 destnode; | ||
1364 | int res; | ||
1365 | |||
1366 | p_ptr = port_deref(ref); | ||
1367 | if (!p_ptr || !p_ptr->publ.connected) | ||
1368 | return -EINVAL; | ||
1369 | |||
1370 | p_ptr->publ.congested = 1; | ||
1371 | if (!port_congested(p_ptr)) { | ||
1372 | destnode = port_peernode(p_ptr); | ||
1373 | if (likely(destnode != tipc_own_addr)) | ||
1374 | res = link_send_sections_fast(p_ptr, msg_sect, num_sect, | ||
1375 | destnode); | ||
1376 | else | ||
1377 | res = port_recv_sections(p_ptr, num_sect, msg_sect); | ||
1378 | |||
1379 | if (likely(res != -ELINKCONG)) { | ||
1380 | port_incr_out_seqno(p_ptr); | ||
1381 | p_ptr->publ.congested = 0; | ||
1382 | p_ptr->sent++; | ||
1383 | return res; | ||
1384 | } | ||
1385 | } | ||
1386 | if (port_unreliable(p_ptr)) { | ||
1387 | p_ptr->publ.congested = 0; | ||
1388 | /* Just calculate msg length and return */ | ||
1389 | return msg_calc_data_size(msg_sect, num_sect); | ||
1390 | } | ||
1391 | return -ELINKCONG; | ||
1392 | } | ||
1393 | |||
1394 | /** | ||
1395 | * tipc_send_buf - send message buffer on connection | ||
1396 | */ | ||
1397 | |||
1398 | int tipc_send_buf(u32 ref, struct sk_buff *buf, unsigned int dsz) | ||
1399 | { | ||
1400 | struct port *p_ptr; | ||
1401 | struct tipc_msg *msg; | ||
1402 | u32 destnode; | ||
1403 | u32 hsz; | ||
1404 | u32 sz; | ||
1405 | u32 res; | ||
1406 | |||
1407 | p_ptr = port_deref(ref); | ||
1408 | if (!p_ptr || !p_ptr->publ.connected) | ||
1409 | return -EINVAL; | ||
1410 | |||
1411 | msg = &p_ptr->publ.phdr; | ||
1412 | hsz = msg_hdr_sz(msg); | ||
1413 | sz = hsz + dsz; | ||
1414 | msg_set_size(msg, sz); | ||
1415 | if (skb_cow(buf, hsz)) | ||
1416 | return -ENOMEM; | ||
1417 | |||
1418 | skb_push(buf, hsz); | ||
1419 | memcpy(buf->data, (unchar *)msg, hsz); | ||
1420 | destnode = msg_destnode(msg); | ||
1421 | p_ptr->publ.congested = 1; | ||
1422 | if (!port_congested(p_ptr)) { | ||
1423 | if (likely(destnode != tipc_own_addr)) | ||
1424 | res = tipc_send_buf_fast(buf, destnode); | ||
1425 | else { | ||
1426 | port_recv_msg(buf); | ||
1427 | res = sz; | ||
1428 | } | ||
1429 | if (likely(res != -ELINKCONG)) { | ||
1430 | port_incr_out_seqno(p_ptr); | ||
1431 | p_ptr->sent++; | ||
1432 | p_ptr->publ.congested = 0; | ||
1433 | return res; | ||
1434 | } | ||
1435 | } | ||
1436 | if (port_unreliable(p_ptr)) { | ||
1437 | p_ptr->publ.congested = 0; | ||
1438 | return dsz; | ||
1439 | } | ||
1440 | return -ELINKCONG; | ||
1441 | } | ||
1442 | |||
1443 | /** | ||
1444 | * tipc_forward2name - forward message sections to port name | ||
1445 | */ | ||
1446 | |||
1447 | int tipc_forward2name(u32 ref, | ||
1448 | struct tipc_name const *name, | ||
1449 | u32 domain, | ||
1450 | u32 num_sect, | ||
1451 | struct iovec const *msg_sect, | ||
1452 | struct tipc_portid const *orig, | ||
1453 | unsigned int importance) | ||
1454 | { | ||
1455 | struct port *p_ptr; | ||
1456 | struct tipc_msg *msg; | ||
1457 | u32 destnode = domain; | ||
1458 | u32 destport = 0; | ||
1459 | int res; | ||
1460 | |||
1461 | p_ptr = port_deref(ref); | ||
1462 | if (!p_ptr || p_ptr->publ.connected) | ||
1463 | return -EINVAL; | ||
1464 | |||
1465 | msg = &p_ptr->publ.phdr; | ||
1466 | msg_set_type(msg, TIPC_NAMED_MSG); | ||
1467 | msg_set_orignode(msg, orig->node); | ||
1468 | msg_set_origport(msg, orig->ref); | ||
1469 | msg_set_hdr_sz(msg, LONG_H_SIZE); | ||
1470 | msg_set_nametype(msg, name->type); | ||
1471 | msg_set_nameinst(msg, name->instance); | ||
1472 | msg_set_lookup_scope(msg, addr_scope(domain)); | ||
1473 | if (importance <= TIPC_CRITICAL_IMPORTANCE) | ||
1474 | msg_set_importance(msg,importance); | ||
1475 | destport = nametbl_translate(name->type, name->instance, &destnode); | ||
1476 | msg_set_destnode(msg, destnode); | ||
1477 | msg_set_destport(msg, destport); | ||
1478 | |||
1479 | if (likely(destport || destnode)) { | ||
1480 | p_ptr->sent++; | ||
1481 | if (likely(destnode == tipc_own_addr)) | ||
1482 | return port_recv_sections(p_ptr, num_sect, msg_sect); | ||
1483 | res = link_send_sections_fast(p_ptr, msg_sect, num_sect, | ||
1484 | destnode); | ||
1485 | if (likely(res != -ELINKCONG)) | ||
1486 | return res; | ||
1487 | if (port_unreliable(p_ptr)) { | ||
1488 | /* Just calculate msg length and return */ | ||
1489 | return msg_calc_data_size(msg_sect, num_sect); | ||
1490 | } | ||
1491 | return -ELINKCONG; | ||
1492 | } | ||
1493 | return port_reject_sections(p_ptr, msg, msg_sect, num_sect, | ||
1494 | TIPC_ERR_NO_NAME); | ||
1495 | } | ||
1496 | |||
1497 | /** | ||
1498 | * tipc_send2name - send message sections to port name | ||
1499 | */ | ||
1500 | |||
1501 | int tipc_send2name(u32 ref, | ||
1502 | struct tipc_name const *name, | ||
1503 | unsigned int domain, | ||
1504 | unsigned int num_sect, | ||
1505 | struct iovec const *msg_sect) | ||
1506 | { | ||
1507 | struct tipc_portid orig; | ||
1508 | |||
1509 | orig.ref = ref; | ||
1510 | orig.node = tipc_own_addr; | ||
1511 | return tipc_forward2name(ref, name, domain, num_sect, msg_sect, &orig, | ||
1512 | TIPC_PORT_IMPORTANCE); | ||
1513 | } | ||
1514 | |||
1515 | /** | ||
1516 | * tipc_forward_buf2name - forward message buffer to port name | ||
1517 | */ | ||
1518 | |||
1519 | int tipc_forward_buf2name(u32 ref, | ||
1520 | struct tipc_name const *name, | ||
1521 | u32 domain, | ||
1522 | struct sk_buff *buf, | ||
1523 | unsigned int dsz, | ||
1524 | struct tipc_portid const *orig, | ||
1525 | unsigned int importance) | ||
1526 | { | ||
1527 | struct port *p_ptr; | ||
1528 | struct tipc_msg *msg; | ||
1529 | u32 destnode = domain; | ||
1530 | u32 destport = 0; | ||
1531 | int res; | ||
1532 | |||
1533 | p_ptr = (struct port *)ref_deref(ref); | ||
1534 | if (!p_ptr || p_ptr->publ.connected) | ||
1535 | return -EINVAL; | ||
1536 | |||
1537 | msg = &p_ptr->publ.phdr; | ||
1538 | if (importance <= TIPC_CRITICAL_IMPORTANCE) | ||
1539 | msg_set_importance(msg, importance); | ||
1540 | msg_set_type(msg, TIPC_NAMED_MSG); | ||
1541 | msg_set_orignode(msg, orig->node); | ||
1542 | msg_set_origport(msg, orig->ref); | ||
1543 | msg_set_nametype(msg, name->type); | ||
1544 | msg_set_nameinst(msg, name->instance); | ||
1545 | msg_set_lookup_scope(msg, addr_scope(domain)); | ||
1546 | msg_set_hdr_sz(msg, LONG_H_SIZE); | ||
1547 | msg_set_size(msg, LONG_H_SIZE + dsz); | ||
1548 | destport = nametbl_translate(name->type, name->instance, &destnode); | ||
1549 | msg_set_destnode(msg, destnode); | ||
1550 | msg_set_destport(msg, destport); | ||
1551 | msg_dbg(msg, "forw2name ==> "); | ||
1552 | if (skb_cow(buf, LONG_H_SIZE)) | ||
1553 | return -ENOMEM; | ||
1554 | skb_push(buf, LONG_H_SIZE); | ||
1555 | memcpy(buf->data, (unchar *)msg, LONG_H_SIZE); | ||
1556 | msg_dbg(buf_msg(buf),"PREP:"); | ||
1557 | if (likely(destport || destnode)) { | ||
1558 | p_ptr->sent++; | ||
1559 | if (destnode == tipc_own_addr) | ||
1560 | return port_recv_msg(buf); | ||
1561 | res = tipc_send_buf_fast(buf, destnode); | ||
1562 | if (likely(res != -ELINKCONG)) | ||
1563 | return res; | ||
1564 | if (port_unreliable(p_ptr)) | ||
1565 | return dsz; | ||
1566 | return -ELINKCONG; | ||
1567 | } | ||
1568 | return tipc_reject_msg(buf, TIPC_ERR_NO_NAME); | ||
1569 | } | ||
1570 | |||
1571 | /** | ||
1572 | * tipc_send_buf2name - send message buffer to port name | ||
1573 | */ | ||
1574 | |||
1575 | int tipc_send_buf2name(u32 ref, | ||
1576 | struct tipc_name const *dest, | ||
1577 | u32 domain, | ||
1578 | struct sk_buff *buf, | ||
1579 | unsigned int dsz) | ||
1580 | { | ||
1581 | struct tipc_portid orig; | ||
1582 | |||
1583 | orig.ref = ref; | ||
1584 | orig.node = tipc_own_addr; | ||
1585 | return tipc_forward_buf2name(ref, dest, domain, buf, dsz, &orig, | ||
1586 | TIPC_PORT_IMPORTANCE); | ||
1587 | } | ||
1588 | |||
1589 | /** | ||
1590 | * tipc_forward2port - forward message sections to port identity | ||
1591 | */ | ||
1592 | |||
1593 | int tipc_forward2port(u32 ref, | ||
1594 | struct tipc_portid const *dest, | ||
1595 | unsigned int num_sect, | ||
1596 | struct iovec const *msg_sect, | ||
1597 | struct tipc_portid const *orig, | ||
1598 | unsigned int importance) | ||
1599 | { | ||
1600 | struct port *p_ptr; | ||
1601 | struct tipc_msg *msg; | ||
1602 | int res; | ||
1603 | |||
1604 | p_ptr = port_deref(ref); | ||
1605 | if (!p_ptr || p_ptr->publ.connected) | ||
1606 | return -EINVAL; | ||
1607 | |||
1608 | msg = &p_ptr->publ.phdr; | ||
1609 | msg_set_type(msg, TIPC_DIRECT_MSG); | ||
1610 | msg_set_orignode(msg, orig->node); | ||
1611 | msg_set_origport(msg, orig->ref); | ||
1612 | msg_set_destnode(msg, dest->node); | ||
1613 | msg_set_destport(msg, dest->ref); | ||
1614 | msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); | ||
1615 | if (importance <= TIPC_CRITICAL_IMPORTANCE) | ||
1616 | msg_set_importance(msg, importance); | ||
1617 | p_ptr->sent++; | ||
1618 | if (dest->node == tipc_own_addr) | ||
1619 | return port_recv_sections(p_ptr, num_sect, msg_sect); | ||
1620 | res = link_send_sections_fast(p_ptr, msg_sect, num_sect, dest->node); | ||
1621 | if (likely(res != -ELINKCONG)) | ||
1622 | return res; | ||
1623 | if (port_unreliable(p_ptr)) { | ||
1624 | /* Just calculate msg length and return */ | ||
1625 | return msg_calc_data_size(msg_sect, num_sect); | ||
1626 | } | ||
1627 | return -ELINKCONG; | ||
1628 | } | ||
1629 | |||
1630 | /** | ||
1631 | * tipc_send2port - send message sections to port identity | ||
1632 | */ | ||
1633 | |||
1634 | int tipc_send2port(u32 ref, | ||
1635 | struct tipc_portid const *dest, | ||
1636 | unsigned int num_sect, | ||
1637 | struct iovec const *msg_sect) | ||
1638 | { | ||
1639 | struct tipc_portid orig; | ||
1640 | |||
1641 | orig.ref = ref; | ||
1642 | orig.node = tipc_own_addr; | ||
1643 | return tipc_forward2port(ref, dest, num_sect, msg_sect, &orig, | ||
1644 | TIPC_PORT_IMPORTANCE); | ||
1645 | } | ||
1646 | |||
1647 | /** | ||
1648 | * tipc_forward_buf2port - forward message buffer to port identity | ||
1649 | */ | ||
1650 | int tipc_forward_buf2port(u32 ref, | ||
1651 | struct tipc_portid const *dest, | ||
1652 | struct sk_buff *buf, | ||
1653 | unsigned int dsz, | ||
1654 | struct tipc_portid const *orig, | ||
1655 | unsigned int importance) | ||
1656 | { | ||
1657 | struct port *p_ptr; | ||
1658 | struct tipc_msg *msg; | ||
1659 | int res; | ||
1660 | |||
1661 | p_ptr = (struct port *)ref_deref(ref); | ||
1662 | if (!p_ptr || p_ptr->publ.connected) | ||
1663 | return -EINVAL; | ||
1664 | |||
1665 | msg = &p_ptr->publ.phdr; | ||
1666 | msg_set_type(msg, TIPC_DIRECT_MSG); | ||
1667 | msg_set_orignode(msg, orig->node); | ||
1668 | msg_set_origport(msg, orig->ref); | ||
1669 | msg_set_destnode(msg, dest->node); | ||
1670 | msg_set_destport(msg, dest->ref); | ||
1671 | msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); | ||
1672 | if (importance <= TIPC_CRITICAL_IMPORTANCE) | ||
1673 | msg_set_importance(msg, importance); | ||
1674 | msg_set_size(msg, DIR_MSG_H_SIZE + dsz); | ||
1675 | if (skb_cow(buf, DIR_MSG_H_SIZE)) | ||
1676 | return -ENOMEM; | ||
1677 | |||
1678 | skb_push(buf, DIR_MSG_H_SIZE); | ||
1679 | memcpy(buf->data, (unchar *)msg, DIR_MSG_H_SIZE); | ||
1680 | msg_dbg(msg, "buf2port: "); | ||
1681 | p_ptr->sent++; | ||
1682 | if (dest->node == tipc_own_addr) | ||
1683 | return port_recv_msg(buf); | ||
1684 | res = tipc_send_buf_fast(buf, dest->node); | ||
1685 | if (likely(res != -ELINKCONG)) | ||
1686 | return res; | ||
1687 | if (port_unreliable(p_ptr)) | ||
1688 | return dsz; | ||
1689 | return -ELINKCONG; | ||
1690 | } | ||
1691 | |||
1692 | /** | ||
1693 | * tipc_send_buf2port - send message buffer to port identity | ||
1694 | */ | ||
1695 | |||
1696 | int tipc_send_buf2port(u32 ref, | ||
1697 | struct tipc_portid const *dest, | ||
1698 | struct sk_buff *buf, | ||
1699 | unsigned int dsz) | ||
1700 | { | ||
1701 | struct tipc_portid orig; | ||
1702 | |||
1703 | orig.ref = ref; | ||
1704 | orig.node = tipc_own_addr; | ||
1705 | return tipc_forward_buf2port(ref, dest, buf, dsz, &orig, | ||
1706 | TIPC_PORT_IMPORTANCE); | ||
1707 | } | ||
1708 | |||
diff --git a/net/tipc/port.h b/net/tipc/port.h new file mode 100644 index 000000000000..e829a99d3b7f --- /dev/null +++ b/net/tipc/port.h | |||
@@ -0,0 +1,209 @@ | |||
1 | /* | ||
2 | * net/tipc/port.h: Include file for TIPC port code | ||
3 | * | ||
4 | * Copyright (c) 1994-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_PORT_H | ||
38 | #define _TIPC_PORT_H | ||
39 | |||
40 | #include <net/tipc/tipc_port.h> | ||
41 | #include "ref.h" | ||
42 | #include "net.h" | ||
43 | #include "msg.h" | ||
44 | #include "dbg.h" | ||
45 | #include "node_subscr.h" | ||
46 | |||
47 | /** | ||
48 | * struct user_port - TIPC user port (used with native API) | ||
49 | * @user_ref: id of user who created user port | ||
50 | * @usr_handle: user-specified field | ||
51 | * @ref: object reference to associated TIPC port | ||
52 | * <various callback routines> | ||
53 | * @uport_list: adjacent user ports in list of ports held by user | ||
54 | */ | ||
55 | |||
56 | struct user_port { | ||
57 | u32 user_ref; | ||
58 | void *usr_handle; | ||
59 | u32 ref; | ||
60 | tipc_msg_err_event err_cb; | ||
61 | tipc_named_msg_err_event named_err_cb; | ||
62 | tipc_conn_shutdown_event conn_err_cb; | ||
63 | tipc_msg_event msg_cb; | ||
64 | tipc_named_msg_event named_msg_cb; | ||
65 | tipc_conn_msg_event conn_msg_cb; | ||
66 | tipc_continue_event continue_event_cb; | ||
67 | struct list_head uport_list; | ||
68 | }; | ||
69 | |||
70 | /** | ||
71 | * struct port - TIPC port structure | ||
72 | * @publ: TIPC port info available to privileged users | ||
73 | * @port_list: adjacent ports in TIPC's global list of ports | ||
74 | * @dispatcher: ptr to routine which handles received messages | ||
75 | * @wakeup: ptr to routine to call when port is no longer congested | ||
76 | * @user_port: ptr to user port associated with port (if any) | ||
77 | * @wait_list: adjacent ports in list of ports waiting on link congestion | ||
78 | * @congested_link: ptr to congested link port is waiting on | ||
79 | * @waiting_pkts: | ||
80 | * @sent: | ||
81 | * @acked: | ||
82 | * @publications: list of publications for port | ||
83 | * @pub_count: total # of publications port has made during its lifetime | ||
84 | * @max_pkt: maximum packet size "hint" used when building messages sent by port | ||
85 | * @probing_state: | ||
86 | * @probing_interval: | ||
87 | * @last_in_seqno: | ||
88 | * @timer_ref: | ||
89 | * @subscription: "node down" subscription used to terminate failed connections | ||
90 | */ | ||
91 | |||
92 | struct port { | ||
93 | struct tipc_port publ; | ||
94 | struct list_head port_list; | ||
95 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *); | ||
96 | void (*wakeup)(struct tipc_port *); | ||
97 | struct user_port *user_port; | ||
98 | struct list_head wait_list; | ||
99 | struct link *congested_link; | ||
100 | u32 waiting_pkts; | ||
101 | u32 sent; | ||
102 | u32 acked; | ||
103 | struct list_head publications; | ||
104 | u32 pub_count; | ||
105 | u32 max_pkt; | ||
106 | u32 probing_state; | ||
107 | u32 probing_interval; | ||
108 | u32 last_in_seqno; | ||
109 | struct timer_list timer; | ||
110 | struct node_subscr subscription; | ||
111 | }; | ||
112 | |||
113 | extern spinlock_t port_list_lock; | ||
114 | struct port_list; | ||
115 | |||
116 | int port_recv_sections(struct port *p_ptr, u32 num_sect, | ||
117 | struct iovec const *msg_sect); | ||
118 | int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr, | ||
119 | struct iovec const *msg_sect, u32 num_sect, | ||
120 | int err); | ||
121 | struct sk_buff *port_get_ports(void); | ||
122 | struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space); | ||
123 | void port_recv_proto_msg(struct sk_buff *buf); | ||
124 | void port_recv_mcast(struct sk_buff *buf, struct port_list *dp); | ||
125 | void port_reinit(void); | ||
126 | |||
127 | /** | ||
128 | * port_lock - lock port instance referred to and return its pointer | ||
129 | */ | ||
130 | |||
131 | static inline struct port *port_lock(u32 ref) | ||
132 | { | ||
133 | return (struct port *)ref_lock(ref); | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * port_unlock - unlock a port instance | ||
138 | * | ||
139 | * Can use pointer instead of ref_unlock() since port is already locked. | ||
140 | */ | ||
141 | |||
142 | static inline void port_unlock(struct port *p_ptr) | ||
143 | { | ||
144 | spin_unlock_bh(p_ptr->publ.lock); | ||
145 | } | ||
146 | |||
147 | static inline struct port* port_deref(u32 ref) | ||
148 | { | ||
149 | return (struct port *)ref_deref(ref); | ||
150 | } | ||
151 | |||
152 | static inline u32 peer_port(struct port *p_ptr) | ||
153 | { | ||
154 | return msg_destport(&p_ptr->publ.phdr); | ||
155 | } | ||
156 | |||
157 | static inline u32 peer_node(struct port *p_ptr) | ||
158 | { | ||
159 | return msg_destnode(&p_ptr->publ.phdr); | ||
160 | } | ||
161 | |||
162 | static inline int port_congested(struct port *p_ptr) | ||
163 | { | ||
164 | return((p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2)); | ||
165 | } | ||
166 | |||
167 | /** | ||
168 | * port_recv_msg - receive message from lower layer and deliver to port user | ||
169 | */ | ||
170 | |||
171 | static inline int port_recv_msg(struct sk_buff *buf) | ||
172 | { | ||
173 | struct port *p_ptr; | ||
174 | struct tipc_msg *msg = buf_msg(buf); | ||
175 | u32 destport = msg_destport(msg); | ||
176 | u32 dsz = msg_data_sz(msg); | ||
177 | u32 err; | ||
178 | |||
179 | /* forward unresolved named message */ | ||
180 | if (unlikely(!destport)) { | ||
181 | net_route_msg(buf); | ||
182 | return dsz; | ||
183 | } | ||
184 | |||
185 | /* validate destination & pass to port, otherwise reject message */ | ||
186 | p_ptr = port_lock(destport); | ||
187 | if (likely(p_ptr)) { | ||
188 | if (likely(p_ptr->publ.connected)) { | ||
189 | if ((unlikely(msg_origport(msg) != peer_port(p_ptr))) || | ||
190 | (unlikely(msg_orignode(msg) != peer_node(p_ptr))) || | ||
191 | (unlikely(!msg_connected(msg)))) { | ||
192 | err = TIPC_ERR_NO_PORT; | ||
193 | port_unlock(p_ptr); | ||
194 | goto reject; | ||
195 | } | ||
196 | } | ||
197 | err = p_ptr->dispatcher(&p_ptr->publ, buf); | ||
198 | port_unlock(p_ptr); | ||
199 | if (likely(!err)) | ||
200 | return dsz; | ||
201 | } else { | ||
202 | err = TIPC_ERR_NO_PORT; | ||
203 | } | ||
204 | reject: | ||
205 | dbg("port->rejecting, err = %x..\n",err); | ||
206 | return tipc_reject_msg(buf, err); | ||
207 | } | ||
208 | |||
209 | #endif | ||
diff --git a/net/tipc/ref.c b/net/tipc/ref.c new file mode 100644 index 000000000000..944093fe246f --- /dev/null +++ b/net/tipc/ref.c | |||
@@ -0,0 +1,189 @@ | |||
1 | /* | ||
2 | * net/tipc/ref.c: TIPC object registry code | ||
3 | * | ||
4 | * Copyright (c) 1991-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "ref.h" | ||
39 | #include "port.h" | ||
40 | #include "subscr.h" | ||
41 | #include "name_distr.h" | ||
42 | #include "name_table.h" | ||
43 | #include "config.h" | ||
44 | #include "discover.h" | ||
45 | #include "bearer.h" | ||
46 | #include "node.h" | ||
47 | #include "bcast.h" | ||
48 | |||
49 | /* | ||
50 | * Object reference table consists of 2**N entries. | ||
51 | * | ||
52 | * A used entry has object ptr != 0, reference == XXXX|own index | ||
53 | * (XXXX changes each time entry is acquired) | ||
54 | * A free entry has object ptr == 0, reference == YYYY|next free index | ||
55 | * (YYYY is one more than last used XXXX) | ||
56 | * | ||
57 | * Free list is initially chained from entry (2**N)-1 to entry 1. | ||
58 | * Entry 0 is not used to allow index 0 to indicate the end of the free list. | ||
59 | * | ||
60 | * Note: Any accidental reference of the form XXXX|0--0 won't match entry 0 | ||
61 | * because entry 0's reference field has the form XXXX|1--1. | ||
62 | */ | ||
63 | |||
64 | struct ref_table ref_table = { 0 }; | ||
65 | |||
66 | rwlock_t reftbl_lock = RW_LOCK_UNLOCKED; | ||
67 | |||
68 | /** | ||
69 | * ref_table_init - create reference table for objects | ||
70 | */ | ||
71 | |||
72 | int ref_table_init(u32 requested_size, u32 start) | ||
73 | { | ||
74 | struct reference *table; | ||
75 | u32 sz = 1 << 4; | ||
76 | u32 index_mask; | ||
77 | int i; | ||
78 | |||
79 | while (sz < requested_size) { | ||
80 | sz <<= 1; | ||
81 | } | ||
82 | table = (struct reference *)vmalloc(sz * sizeof(struct reference)); | ||
83 | if (table == NULL) | ||
84 | return -ENOMEM; | ||
85 | |||
86 | write_lock_bh(&reftbl_lock); | ||
87 | index_mask = sz - 1; | ||
88 | for (i = sz - 1; i >= 0; i--) { | ||
89 | table[i].object = 0; | ||
90 | table[i].lock = SPIN_LOCK_UNLOCKED; | ||
91 | table[i].data.next_plus_upper = (start & ~index_mask) + i - 1; | ||
92 | } | ||
93 | ref_table.entries = table; | ||
94 | ref_table.index_mask = index_mask; | ||
95 | ref_table.first_free = sz - 1; | ||
96 | ref_table.last_free = 1; | ||
97 | write_unlock_bh(&reftbl_lock); | ||
98 | return TIPC_OK; | ||
99 | } | ||
100 | |||
101 | /** | ||
102 | * ref_table_stop - destroy reference table for objects | ||
103 | */ | ||
104 | |||
105 | void ref_table_stop(void) | ||
106 | { | ||
107 | if (!ref_table.entries) | ||
108 | return; | ||
109 | |||
110 | vfree(ref_table.entries); | ||
111 | ref_table.entries = 0; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * ref_acquire - create reference to an object | ||
116 | * | ||
117 | * Return a unique reference value which can be translated back to the pointer | ||
118 | * 'object' at a later time. Also, pass back a pointer to the lock protecting | ||
119 | * the object, but without locking it. | ||
120 | */ | ||
121 | |||
122 | u32 ref_acquire(void *object, spinlock_t **lock) | ||
123 | { | ||
124 | struct reference *entry; | ||
125 | u32 index; | ||
126 | u32 index_mask; | ||
127 | u32 next_plus_upper; | ||
128 | u32 reference = 0; | ||
129 | |||
130 | assert(ref_table.entries && object); | ||
131 | |||
132 | write_lock_bh(&reftbl_lock); | ||
133 | if (ref_table.first_free) { | ||
134 | index = ref_table.first_free; | ||
135 | entry = &(ref_table.entries[index]); | ||
136 | index_mask = ref_table.index_mask; | ||
137 | /* take lock in case a previous user of entry still holds it */ | ||
138 | spin_lock_bh(&entry->lock); | ||
139 | next_plus_upper = entry->data.next_plus_upper; | ||
140 | ref_table.first_free = next_plus_upper & index_mask; | ||
141 | reference = (next_plus_upper & ~index_mask) + index; | ||
142 | entry->data.reference = reference; | ||
143 | entry->object = object; | ||
144 | if (lock != 0) | ||
145 | *lock = &entry->lock; | ||
146 | spin_unlock_bh(&entry->lock); | ||
147 | } | ||
148 | write_unlock_bh(&reftbl_lock); | ||
149 | return reference; | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * ref_discard - invalidate references to an object | ||
154 | * | ||
155 | * Disallow future references to an object and free up the entry for re-use. | ||
156 | * Note: The entry's spin_lock may still be busy after discard | ||
157 | */ | ||
158 | |||
159 | void ref_discard(u32 ref) | ||
160 | { | ||
161 | struct reference *entry; | ||
162 | u32 index; | ||
163 | u32 index_mask; | ||
164 | |||
165 | assert(ref_table.entries); | ||
166 | assert(ref != 0); | ||
167 | |||
168 | write_lock_bh(&reftbl_lock); | ||
169 | index_mask = ref_table.index_mask; | ||
170 | index = ref & index_mask; | ||
171 | entry = &(ref_table.entries[index]); | ||
172 | assert(entry->object != 0); | ||
173 | assert(entry->data.reference == ref); | ||
174 | |||
175 | /* mark entry as unused */ | ||
176 | entry->object = 0; | ||
177 | if (ref_table.first_free == 0) | ||
178 | ref_table.first_free = index; | ||
179 | else | ||
180 | /* next_plus_upper is always XXXX|0--0 for last free entry */ | ||
181 | ref_table.entries[ref_table.last_free].data.next_plus_upper | ||
182 | |= index; | ||
183 | ref_table.last_free = index; | ||
184 | |||
185 | /* increment upper bits of entry to invalidate subsequent references */ | ||
186 | entry->data.next_plus_upper = (ref & ~index_mask) + (index_mask + 1); | ||
187 | write_unlock_bh(&reftbl_lock); | ||
188 | } | ||
189 | |||
diff --git a/net/tipc/ref.h b/net/tipc/ref.h new file mode 100644 index 000000000000..429cde57228a --- /dev/null +++ b/net/tipc/ref.h | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * net/tipc/ref.h: Include file for TIPC object registry code | ||
3 | * | ||
4 | * Copyright (c) 1991-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_REF_H | ||
38 | #define _TIPC_REF_H | ||
39 | |||
40 | /** | ||
41 | * struct reference - TIPC object reference entry | ||
42 | * @object: pointer to object associated with reference entry | ||
43 | * @lock: spinlock controlling access to object | ||
44 | * @data: reference value associated with object (or link to next unused entry) | ||
45 | */ | ||
46 | |||
47 | struct reference { | ||
48 | void *object; | ||
49 | spinlock_t lock; | ||
50 | union { | ||
51 | u32 next_plus_upper; | ||
52 | u32 reference; | ||
53 | } data; | ||
54 | }; | ||
55 | |||
56 | /** | ||
57 | * struct ref_table - table of TIPC object reference entries | ||
58 | * @entries: pointer to array of reference entries | ||
59 | * @index_mask: bitmask for array index portion of reference values | ||
60 | * @first_free: array index of first unused object reference entry | ||
61 | * @last_free: array index of last unused object reference entry | ||
62 | */ | ||
63 | |||
64 | struct ref_table { | ||
65 | struct reference *entries; | ||
66 | u32 index_mask; | ||
67 | u32 first_free; | ||
68 | u32 last_free; | ||
69 | }; | ||
70 | |||
71 | extern struct ref_table ref_table; | ||
72 | |||
73 | int ref_table_init(u32 requested_size, u32 start); | ||
74 | void ref_table_stop(void); | ||
75 | |||
76 | u32 ref_acquire(void *object, spinlock_t **lock); | ||
77 | void ref_discard(u32 ref); | ||
78 | |||
79 | |||
80 | /** | ||
81 | * ref_lock - lock referenced object and return pointer to it | ||
82 | */ | ||
83 | |||
84 | static inline void *ref_lock(u32 ref) | ||
85 | { | ||
86 | if (likely(ref_table.entries)) { | ||
87 | struct reference *r = | ||
88 | &ref_table.entries[ref & ref_table.index_mask]; | ||
89 | |||
90 | spin_lock_bh(&r->lock); | ||
91 | if (likely(r->data.reference == ref)) | ||
92 | return r->object; | ||
93 | spin_unlock_bh(&r->lock); | ||
94 | } | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * ref_unlock - unlock referenced object | ||
100 | */ | ||
101 | |||
102 | static inline void ref_unlock(u32 ref) | ||
103 | { | ||
104 | if (likely(ref_table.entries)) { | ||
105 | struct reference *r = | ||
106 | &ref_table.entries[ref & ref_table.index_mask]; | ||
107 | |||
108 | if (likely(r->data.reference == ref)) | ||
109 | spin_unlock_bh(&r->lock); | ||
110 | else | ||
111 | err("ref_unlock() invoked using obsolete reference\n"); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * ref_deref - return pointer referenced object (without locking it) | ||
117 | */ | ||
118 | |||
119 | static inline void *ref_deref(u32 ref) | ||
120 | { | ||
121 | if (likely(ref_table.entries)) { | ||
122 | struct reference *r = | ||
123 | &ref_table.entries[ref & ref_table.index_mask]; | ||
124 | |||
125 | if (likely(r->data.reference == ref)) | ||
126 | return r->object; | ||
127 | } | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | #endif | ||
diff --git a/net/tipc/socket.c b/net/tipc/socket.c new file mode 100644 index 000000000000..d21f8c0cd25a --- /dev/null +++ b/net/tipc/socket.c | |||
@@ -0,0 +1,1726 @@ | |||
1 | /* | ||
2 | * net/tipc/socket.c: TIPC socket API | ||
3 | * | ||
4 | * Copyright (c) 2001-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include <linux/module.h> | ||
38 | #include <linux/types.h> | ||
39 | #include <linux/net.h> | ||
40 | #include <linux/socket.h> | ||
41 | #include <linux/errno.h> | ||
42 | #include <linux/mm.h> | ||
43 | #include <linux/slab.h> | ||
44 | #include <linux/poll.h> | ||
45 | #include <linux/version.h> | ||
46 | #include <linux/fcntl.h> | ||
47 | #include <linux/version.h> | ||
48 | #include <asm/semaphore.h> | ||
49 | #include <asm/string.h> | ||
50 | #include <asm/atomic.h> | ||
51 | #include <net/sock.h> | ||
52 | |||
53 | #include <linux/tipc.h> | ||
54 | #include <linux/tipc_config.h> | ||
55 | #include <net/tipc/tipc_msg.h> | ||
56 | #include <net/tipc/tipc_port.h> | ||
57 | |||
58 | #include "core.h" | ||
59 | |||
60 | #define SS_LISTENING -1 /* socket is listening */ | ||
61 | #define SS_READY -2 /* socket is connectionless */ | ||
62 | |||
63 | #define OVERLOAD_LIMIT_BASE 5000 | ||
64 | |||
65 | struct tipc_sock { | ||
66 | struct sock sk; | ||
67 | struct tipc_port *p; | ||
68 | struct semaphore sem; | ||
69 | }; | ||
70 | |||
71 | #define tipc_sk(sk) ((struct tipc_sock*)sk) | ||
72 | |||
73 | static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); | ||
74 | static void wakeupdispatch(struct tipc_port *tport); | ||
75 | |||
76 | static struct proto_ops packet_ops; | ||
77 | static struct proto_ops stream_ops; | ||
78 | static struct proto_ops msg_ops; | ||
79 | |||
80 | static struct proto tipc_proto; | ||
81 | |||
82 | static int sockets_enabled = 0; | ||
83 | |||
84 | static atomic_t tipc_queue_size = ATOMIC_INIT(0); | ||
85 | |||
86 | |||
87 | /* | ||
88 | * sock_lock(): Lock a port/socket pair. lock_sock() can | ||
89 | * not be used here, since the same lock must protect ports | ||
90 | * with non-socket interfaces. | ||
91 | * See net.c for description of locking policy. | ||
92 | */ | ||
93 | static inline void sock_lock(struct tipc_sock* tsock) | ||
94 | { | ||
95 | spin_lock_bh(tsock->p->lock); | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * sock_unlock(): Unlock a port/socket pair | ||
100 | */ | ||
101 | static inline void sock_unlock(struct tipc_sock* tsock) | ||
102 | { | ||
103 | spin_unlock_bh(tsock->p->lock); | ||
104 | } | ||
105 | |||
106 | /** | ||
107 | * pollmask - determine the current set of poll() events for a socket | ||
108 | * @sock: socket structure | ||
109 | * | ||
110 | * TIPC sets the returned events as follows: | ||
111 | * a) POLLRDNORM and POLLIN are set if the socket's receive queue is non-empty | ||
112 | * or if a connection-oriented socket is does not have an active connection | ||
113 | * (i.e. a read operation will not block). | ||
114 | * b) POLLOUT is set except when a socket's connection has been terminated | ||
115 | * (i.e. a write operation will not block). | ||
116 | * c) POLLHUP is set when a socket's connection has been terminated. | ||
117 | * | ||
118 | * IMPORTANT: The fact that a read or write operation will not block does NOT | ||
119 | * imply that the operation will succeed! | ||
120 | * | ||
121 | * Returns pollmask value | ||
122 | */ | ||
123 | |||
124 | static inline u32 pollmask(struct socket *sock) | ||
125 | { | ||
126 | u32 mask; | ||
127 | |||
128 | if ((skb_queue_len(&sock->sk->sk_receive_queue) != 0) || | ||
129 | (sock->state == SS_UNCONNECTED) || | ||
130 | (sock->state == SS_DISCONNECTING)) | ||
131 | mask = (POLLRDNORM | POLLIN); | ||
132 | else | ||
133 | mask = 0; | ||
134 | |||
135 | if (sock->state == SS_DISCONNECTING) | ||
136 | mask |= POLLHUP; | ||
137 | else | ||
138 | mask |= POLLOUT; | ||
139 | |||
140 | return mask; | ||
141 | } | ||
142 | |||
143 | |||
144 | /** | ||
145 | * advance_queue - discard first buffer in queue | ||
146 | * @tsock: TIPC socket | ||
147 | */ | ||
148 | |||
149 | static inline void advance_queue(struct tipc_sock *tsock) | ||
150 | { | ||
151 | sock_lock(tsock); | ||
152 | buf_discard(skb_dequeue(&tsock->sk.sk_receive_queue)); | ||
153 | sock_unlock(tsock); | ||
154 | atomic_dec(&tipc_queue_size); | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * tipc_create - create a TIPC socket | ||
159 | * @sock: pre-allocated socket structure | ||
160 | * @protocol: protocol indicator (must be 0) | ||
161 | * | ||
162 | * This routine creates and attaches a 'struct sock' to the 'struct socket', | ||
163 | * then create and attaches a TIPC port to the 'struct sock' part. | ||
164 | * | ||
165 | * Returns 0 on success, errno otherwise | ||
166 | */ | ||
167 | static int tipc_create(struct socket *sock, int protocol) | ||
168 | { | ||
169 | struct tipc_sock *tsock; | ||
170 | struct tipc_port *port; | ||
171 | struct sock *sk; | ||
172 | u32 ref; | ||
173 | |||
174 | if ((sock->type != SOCK_STREAM) && | ||
175 | (sock->type != SOCK_SEQPACKET) && | ||
176 | (sock->type != SOCK_DGRAM) && | ||
177 | (sock->type != SOCK_RDM)) | ||
178 | return -EPROTOTYPE; | ||
179 | |||
180 | if (unlikely(protocol != 0)) | ||
181 | return -EPROTONOSUPPORT; | ||
182 | |||
183 | ref = tipc_createport_raw(0, &dispatch, &wakeupdispatch, TIPC_LOW_IMPORTANCE); | ||
184 | if (unlikely(!ref)) | ||
185 | return -ENOMEM; | ||
186 | |||
187 | sock->state = SS_UNCONNECTED; | ||
188 | |||
189 | switch (sock->type) { | ||
190 | case SOCK_STREAM: | ||
191 | sock->ops = &stream_ops; | ||
192 | break; | ||
193 | case SOCK_SEQPACKET: | ||
194 | sock->ops = &packet_ops; | ||
195 | break; | ||
196 | case SOCK_DGRAM: | ||
197 | tipc_set_portunreliable(ref, 1); | ||
198 | /* fall through */ | ||
199 | case SOCK_RDM: | ||
200 | tipc_set_portunreturnable(ref, 1); | ||
201 | sock->ops = &msg_ops; | ||
202 | sock->state = SS_READY; | ||
203 | break; | ||
204 | } | ||
205 | |||
206 | sk = sk_alloc(AF_TIPC, GFP_KERNEL, &tipc_proto, 1); | ||
207 | if (!sk) { | ||
208 | tipc_deleteport(ref); | ||
209 | return -ENOMEM; | ||
210 | } | ||
211 | |||
212 | sock_init_data(sock, sk); | ||
213 | init_waitqueue_head(sk->sk_sleep); | ||
214 | sk->sk_rcvtimeo = 8 * HZ; /* default connect timeout = 8s */ | ||
215 | |||
216 | tsock = tipc_sk(sk); | ||
217 | port = tipc_get_port(ref); | ||
218 | |||
219 | tsock->p = port; | ||
220 | port->usr_handle = tsock; | ||
221 | |||
222 | init_MUTEX(&tsock->sem); | ||
223 | |||
224 | dbg("sock_create: %x\n",tsock); | ||
225 | |||
226 | atomic_inc(&tipc_user_count); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | /** | ||
232 | * release - destroy a TIPC socket | ||
233 | * @sock: socket to destroy | ||
234 | * | ||
235 | * This routine cleans up any messages that are still queued on the socket. | ||
236 | * For DGRAM and RDM socket types, all queued messages are rejected. | ||
237 | * For SEQPACKET and STREAM socket types, the first message is rejected | ||
238 | * and any others are discarded. (If the first message on a STREAM socket | ||
239 | * is partially-read, it is discarded and the next one is rejected instead.) | ||
240 | * | ||
241 | * NOTE: Rejected messages are not necessarily returned to the sender! They | ||
242 | * are returned or discarded according to the "destination droppable" setting | ||
243 | * specified for the message by the sender. | ||
244 | * | ||
245 | * Returns 0 on success, errno otherwise | ||
246 | */ | ||
247 | |||
248 | static int release(struct socket *sock) | ||
249 | { | ||
250 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
251 | struct sock *sk = sock->sk; | ||
252 | int res = TIPC_OK; | ||
253 | struct sk_buff *buf; | ||
254 | |||
255 | dbg("sock_delete: %x\n",tsock); | ||
256 | if (!tsock) | ||
257 | return 0; | ||
258 | down_interruptible(&tsock->sem); | ||
259 | if (!sock->sk) { | ||
260 | up(&tsock->sem); | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | /* Reject unreceived messages, unless no longer connected */ | ||
265 | |||
266 | while (sock->state != SS_DISCONNECTING) { | ||
267 | sock_lock(tsock); | ||
268 | buf = skb_dequeue(&sk->sk_receive_queue); | ||
269 | if (!buf) | ||
270 | tsock->p->usr_handle = 0; | ||
271 | sock_unlock(tsock); | ||
272 | if (!buf) | ||
273 | break; | ||
274 | if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) | ||
275 | buf_discard(buf); | ||
276 | else | ||
277 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); | ||
278 | atomic_dec(&tipc_queue_size); | ||
279 | } | ||
280 | |||
281 | /* Delete TIPC port */ | ||
282 | |||
283 | res = tipc_deleteport(tsock->p->ref); | ||
284 | sock->sk = NULL; | ||
285 | |||
286 | /* Discard any remaining messages */ | ||
287 | |||
288 | while ((buf = skb_dequeue(&sk->sk_receive_queue))) { | ||
289 | buf_discard(buf); | ||
290 | atomic_dec(&tipc_queue_size); | ||
291 | } | ||
292 | |||
293 | up(&tsock->sem); | ||
294 | |||
295 | sock_put(sk); | ||
296 | |||
297 | atomic_dec(&tipc_user_count); | ||
298 | return res; | ||
299 | } | ||
300 | |||
301 | /** | ||
302 | * bind - associate or disassocate TIPC name(s) with a socket | ||
303 | * @sock: socket structure | ||
304 | * @uaddr: socket address describing name(s) and desired operation | ||
305 | * @uaddr_len: size of socket address data structure | ||
306 | * | ||
307 | * Name and name sequence binding is indicated using a positive scope value; | ||
308 | * a negative scope value unbinds the specified name. Specifying no name | ||
309 | * (i.e. a socket address length of 0) unbinds all names from the socket. | ||
310 | * | ||
311 | * Returns 0 on success, errno otherwise | ||
312 | */ | ||
313 | |||
314 | static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) | ||
315 | { | ||
316 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
317 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; | ||
318 | int res; | ||
319 | |||
320 | if (down_interruptible(&tsock->sem)) | ||
321 | return -ERESTARTSYS; | ||
322 | |||
323 | if (unlikely(!uaddr_len)) { | ||
324 | res = tipc_withdraw(tsock->p->ref, 0, 0); | ||
325 | goto exit; | ||
326 | } | ||
327 | |||
328 | if (uaddr_len < sizeof(struct sockaddr_tipc)) { | ||
329 | res = -EINVAL; | ||
330 | goto exit; | ||
331 | } | ||
332 | |||
333 | if (addr->family != AF_TIPC) { | ||
334 | res = -EAFNOSUPPORT; | ||
335 | goto exit; | ||
336 | } | ||
337 | if (addr->addrtype == TIPC_ADDR_NAME) | ||
338 | addr->addr.nameseq.upper = addr->addr.nameseq.lower; | ||
339 | else if (addr->addrtype != TIPC_ADDR_NAMESEQ) { | ||
340 | res = -EAFNOSUPPORT; | ||
341 | goto exit; | ||
342 | } | ||
343 | |||
344 | if (addr->scope > 0) | ||
345 | res = tipc_publish(tsock->p->ref, addr->scope, | ||
346 | &addr->addr.nameseq); | ||
347 | else | ||
348 | res = tipc_withdraw(tsock->p->ref, -addr->scope, | ||
349 | &addr->addr.nameseq); | ||
350 | exit: | ||
351 | up(&tsock->sem); | ||
352 | return res; | ||
353 | } | ||
354 | |||
355 | /** | ||
356 | * get_name - get port ID of socket or peer socket | ||
357 | * @sock: socket structure | ||
358 | * @uaddr: area for returned socket address | ||
359 | * @uaddr_len: area for returned length of socket address | ||
360 | * @peer: 0 to obtain socket name, 1 to obtain peer socket name | ||
361 | * | ||
362 | * Returns 0 on success, errno otherwise | ||
363 | */ | ||
364 | |||
365 | static int get_name(struct socket *sock, struct sockaddr *uaddr, | ||
366 | int *uaddr_len, int peer) | ||
367 | { | ||
368 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
369 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; | ||
370 | u32 res; | ||
371 | |||
372 | if (down_interruptible(&tsock->sem)) | ||
373 | return -ERESTARTSYS; | ||
374 | |||
375 | *uaddr_len = sizeof(*addr); | ||
376 | addr->addrtype = TIPC_ADDR_ID; | ||
377 | addr->family = AF_TIPC; | ||
378 | addr->scope = 0; | ||
379 | if (peer) | ||
380 | res = tipc_peer(tsock->p->ref, &addr->addr.id); | ||
381 | else | ||
382 | res = tipc_ownidentity(tsock->p->ref, &addr->addr.id); | ||
383 | addr->addr.name.domain = 0; | ||
384 | |||
385 | up(&tsock->sem); | ||
386 | return res; | ||
387 | } | ||
388 | |||
389 | /** | ||
390 | * poll - read and possibly block on pollmask | ||
391 | * @file: file structure associated with the socket | ||
392 | * @sock: socket for which to calculate the poll bits | ||
393 | * @wait: ??? | ||
394 | * | ||
395 | * Returns the pollmask | ||
396 | */ | ||
397 | |||
398 | static unsigned int poll(struct file *file, struct socket *sock, | ||
399 | poll_table *wait) | ||
400 | { | ||
401 | poll_wait(file, sock->sk->sk_sleep, wait); | ||
402 | /* NEED LOCK HERE? */ | ||
403 | return pollmask(sock); | ||
404 | } | ||
405 | |||
406 | /** | ||
407 | * dest_name_check - verify user is permitted to send to specified port name | ||
408 | * @dest: destination address | ||
409 | * @m: descriptor for message to be sent | ||
410 | * | ||
411 | * Prevents restricted configuration commands from being issued by | ||
412 | * unauthorized users. | ||
413 | * | ||
414 | * Returns 0 if permission is granted, otherwise errno | ||
415 | */ | ||
416 | |||
417 | static inline int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) | ||
418 | { | ||
419 | struct tipc_cfg_msg_hdr hdr; | ||
420 | |||
421 | if (likely(dest->addr.name.name.type >= TIPC_RESERVED_TYPES)) | ||
422 | return 0; | ||
423 | if (likely(dest->addr.name.name.type == TIPC_TOP_SRV)) | ||
424 | return 0; | ||
425 | |||
426 | if (likely(dest->addr.name.name.type != TIPC_CFG_SRV)) | ||
427 | return -EACCES; | ||
428 | |||
429 | if (copy_from_user(&hdr, m->msg_iov[0].iov_base, sizeof(hdr))) | ||
430 | return -EFAULT; | ||
431 | if ((ntohs(hdr.tcm_type) & 0xC000) & (!capable(CAP_NET_ADMIN))) | ||
432 | return -EACCES; | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | /** | ||
438 | * send_msg - send message in connectionless manner | ||
439 | * @iocb: (unused) | ||
440 | * @sock: socket structure | ||
441 | * @m: message to send | ||
442 | * @total_len: (unused) | ||
443 | * | ||
444 | * Message must have an destination specified explicitly. | ||
445 | * Used for SOCK_RDM and SOCK_DGRAM messages, | ||
446 | * and for 'SYN' messages on SOCK_SEQPACKET and SOCK_STREAM connections. | ||
447 | * (Note: 'SYN+' is prohibited on SOCK_STREAM.) | ||
448 | * | ||
449 | * Returns the number of bytes sent on success, or errno otherwise | ||
450 | */ | ||
451 | |||
452 | static int send_msg(struct kiocb *iocb, struct socket *sock, | ||
453 | struct msghdr *m, size_t total_len) | ||
454 | { | ||
455 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
456 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | ||
457 | struct sk_buff *buf; | ||
458 | int needs_conn; | ||
459 | int res = -EINVAL; | ||
460 | |||
461 | if (unlikely(!dest)) | ||
462 | return -EDESTADDRREQ; | ||
463 | if (unlikely(dest->family != AF_TIPC)) | ||
464 | return -EINVAL; | ||
465 | |||
466 | needs_conn = (sock->state != SS_READY); | ||
467 | if (unlikely(needs_conn)) { | ||
468 | if (sock->state == SS_LISTENING) | ||
469 | return -EPIPE; | ||
470 | if (sock->state != SS_UNCONNECTED) | ||
471 | return -EISCONN; | ||
472 | if ((tsock->p->published) || | ||
473 | ((sock->type == SOCK_STREAM) && (total_len != 0))) | ||
474 | return -EOPNOTSUPP; | ||
475 | } | ||
476 | |||
477 | if (down_interruptible(&tsock->sem)) | ||
478 | return -ERESTARTSYS; | ||
479 | |||
480 | if (needs_conn) { | ||
481 | |||
482 | /* Abort any pending connection attempts (very unlikely) */ | ||
483 | |||
484 | while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) { | ||
485 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); | ||
486 | atomic_dec(&tipc_queue_size); | ||
487 | } | ||
488 | |||
489 | sock->state = SS_CONNECTING; | ||
490 | } | ||
491 | |||
492 | do { | ||
493 | if (dest->addrtype == TIPC_ADDR_NAME) { | ||
494 | if ((res = dest_name_check(dest, m))) | ||
495 | goto exit; | ||
496 | res = tipc_send2name(tsock->p->ref, | ||
497 | &dest->addr.name.name, | ||
498 | dest->addr.name.domain, | ||
499 | m->msg_iovlen, | ||
500 | m->msg_iov); | ||
501 | } | ||
502 | else if (dest->addrtype == TIPC_ADDR_ID) { | ||
503 | res = tipc_send2port(tsock->p->ref, | ||
504 | &dest->addr.id, | ||
505 | m->msg_iovlen, | ||
506 | m->msg_iov); | ||
507 | } | ||
508 | else if (dest->addrtype == TIPC_ADDR_MCAST) { | ||
509 | if (needs_conn) { | ||
510 | res = -EOPNOTSUPP; | ||
511 | goto exit; | ||
512 | } | ||
513 | if ((res = dest_name_check(dest, m))) | ||
514 | goto exit; | ||
515 | res = tipc_multicast(tsock->p->ref, | ||
516 | &dest->addr.nameseq, | ||
517 | 0, | ||
518 | m->msg_iovlen, | ||
519 | m->msg_iov); | ||
520 | } | ||
521 | if (likely(res != -ELINKCONG)) { | ||
522 | exit: | ||
523 | up(&tsock->sem); | ||
524 | return res; | ||
525 | } | ||
526 | if (m->msg_flags & MSG_DONTWAIT) { | ||
527 | res = -EWOULDBLOCK; | ||
528 | goto exit; | ||
529 | } | ||
530 | if (wait_event_interruptible(*sock->sk->sk_sleep, | ||
531 | !tsock->p->congested)) { | ||
532 | res = -ERESTARTSYS; | ||
533 | goto exit; | ||
534 | } | ||
535 | } while (1); | ||
536 | } | ||
537 | |||
538 | /** | ||
539 | * send_packet - send a connection-oriented message | ||
540 | * @iocb: (unused) | ||
541 | * @sock: socket structure | ||
542 | * @m: message to send | ||
543 | * @total_len: (unused) | ||
544 | * | ||
545 | * Used for SOCK_SEQPACKET messages and SOCK_STREAM data. | ||
546 | * | ||
547 | * Returns the number of bytes sent on success, or errno otherwise | ||
548 | */ | ||
549 | |||
550 | static int send_packet(struct kiocb *iocb, struct socket *sock, | ||
551 | struct msghdr *m, size_t total_len) | ||
552 | { | ||
553 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
554 | struct sockaddr_tipc *dest = (struct sockaddr_tipc *)m->msg_name; | ||
555 | int res; | ||
556 | |||
557 | /* Handle implied connection establishment */ | ||
558 | |||
559 | if (unlikely(dest)) | ||
560 | return send_msg(iocb, sock, m, total_len); | ||
561 | |||
562 | if (down_interruptible(&tsock->sem)) { | ||
563 | return -ERESTARTSYS; | ||
564 | } | ||
565 | |||
566 | if (unlikely(sock->state != SS_CONNECTED)) { | ||
567 | if (sock->state == SS_DISCONNECTING) | ||
568 | res = -EPIPE; | ||
569 | else | ||
570 | res = -ENOTCONN; | ||
571 | goto exit; | ||
572 | } | ||
573 | |||
574 | do { | ||
575 | res = tipc_send(tsock->p->ref, m->msg_iovlen, m->msg_iov); | ||
576 | if (likely(res != -ELINKCONG)) { | ||
577 | exit: | ||
578 | up(&tsock->sem); | ||
579 | return res; | ||
580 | } | ||
581 | if (m->msg_flags & MSG_DONTWAIT) { | ||
582 | res = -EWOULDBLOCK; | ||
583 | goto exit; | ||
584 | } | ||
585 | if (wait_event_interruptible(*sock->sk->sk_sleep, | ||
586 | !tsock->p->congested)) { | ||
587 | res = -ERESTARTSYS; | ||
588 | goto exit; | ||
589 | } | ||
590 | } while (1); | ||
591 | } | ||
592 | |||
593 | /** | ||
594 | * send_stream - send stream-oriented data | ||
595 | * @iocb: (unused) | ||
596 | * @sock: socket structure | ||
597 | * @m: data to send | ||
598 | * @total_len: total length of data to be sent | ||
599 | * | ||
600 | * Used for SOCK_STREAM data. | ||
601 | * | ||
602 | * Returns the number of bytes sent on success, or errno otherwise | ||
603 | */ | ||
604 | |||
605 | |||
606 | static int send_stream(struct kiocb *iocb, struct socket *sock, | ||
607 | struct msghdr *m, size_t total_len) | ||
608 | { | ||
609 | struct msghdr my_msg; | ||
610 | struct iovec my_iov; | ||
611 | struct iovec *curr_iov; | ||
612 | int curr_iovlen; | ||
613 | char __user *curr_start; | ||
614 | int curr_left; | ||
615 | int bytes_to_send; | ||
616 | int res; | ||
617 | |||
618 | if (likely(total_len <= TIPC_MAX_USER_MSG_SIZE)) | ||
619 | return send_packet(iocb, sock, m, total_len); | ||
620 | |||
621 | /* Can only send large data streams if already connected */ | ||
622 | |||
623 | if (unlikely(sock->state != SS_CONNECTED)) { | ||
624 | if (sock->state == SS_DISCONNECTING) | ||
625 | return -EPIPE; | ||
626 | else | ||
627 | return -ENOTCONN; | ||
628 | } | ||
629 | |||
630 | /* | ||
631 | * Send each iovec entry using one or more messages | ||
632 | * | ||
633 | * Note: This algorithm is good for the most likely case | ||
634 | * (i.e. one large iovec entry), but could be improved to pass sets | ||
635 | * of small iovec entries into send_packet(). | ||
636 | */ | ||
637 | |||
638 | my_msg = *m; | ||
639 | curr_iov = my_msg.msg_iov; | ||
640 | curr_iovlen = my_msg.msg_iovlen; | ||
641 | my_msg.msg_iov = &my_iov; | ||
642 | my_msg.msg_iovlen = 1; | ||
643 | |||
644 | while (curr_iovlen--) { | ||
645 | curr_start = curr_iov->iov_base; | ||
646 | curr_left = curr_iov->iov_len; | ||
647 | |||
648 | while (curr_left) { | ||
649 | bytes_to_send = (curr_left < TIPC_MAX_USER_MSG_SIZE) | ||
650 | ? curr_left : TIPC_MAX_USER_MSG_SIZE; | ||
651 | my_iov.iov_base = curr_start; | ||
652 | my_iov.iov_len = bytes_to_send; | ||
653 | if ((res = send_packet(iocb, sock, &my_msg, 0)) < 0) | ||
654 | return res; | ||
655 | curr_left -= bytes_to_send; | ||
656 | curr_start += bytes_to_send; | ||
657 | } | ||
658 | |||
659 | curr_iov++; | ||
660 | } | ||
661 | |||
662 | return total_len; | ||
663 | } | ||
664 | |||
665 | /** | ||
666 | * auto_connect - complete connection setup to a remote port | ||
667 | * @sock: socket structure | ||
668 | * @tsock: TIPC-specific socket structure | ||
669 | * @msg: peer's response message | ||
670 | * | ||
671 | * Returns 0 on success, errno otherwise | ||
672 | */ | ||
673 | |||
674 | static int auto_connect(struct socket *sock, struct tipc_sock *tsock, | ||
675 | struct tipc_msg *msg) | ||
676 | { | ||
677 | struct tipc_portid peer; | ||
678 | |||
679 | if (msg_errcode(msg)) { | ||
680 | sock->state = SS_DISCONNECTING; | ||
681 | return -ECONNREFUSED; | ||
682 | } | ||
683 | |||
684 | peer.ref = msg_origport(msg); | ||
685 | peer.node = msg_orignode(msg); | ||
686 | tipc_connect2port(tsock->p->ref, &peer); | ||
687 | tipc_set_portimportance(tsock->p->ref, msg_importance(msg)); | ||
688 | sock->state = SS_CONNECTED; | ||
689 | return 0; | ||
690 | } | ||
691 | |||
692 | /** | ||
693 | * set_orig_addr - capture sender's address for received message | ||
694 | * @m: descriptor for message info | ||
695 | * @msg: received message header | ||
696 | * | ||
697 | * Note: Address is not captured if not requested by receiver. | ||
698 | */ | ||
699 | |||
700 | static inline void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) | ||
701 | { | ||
702 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)m->msg_name; | ||
703 | |||
704 | if (addr) { | ||
705 | addr->family = AF_TIPC; | ||
706 | addr->addrtype = TIPC_ADDR_ID; | ||
707 | addr->addr.id.ref = msg_origport(msg); | ||
708 | addr->addr.id.node = msg_orignode(msg); | ||
709 | addr->addr.name.domain = 0; /* could leave uninitialized */ | ||
710 | addr->scope = 0; /* could leave uninitialized */ | ||
711 | m->msg_namelen = sizeof(struct sockaddr_tipc); | ||
712 | } | ||
713 | } | ||
714 | |||
715 | /** | ||
716 | * anc_data_recv - optionally capture ancillary data for received message | ||
717 | * @m: descriptor for message info | ||
718 | * @msg: received message header | ||
719 | * @tport: TIPC port associated with message | ||
720 | * | ||
721 | * Note: Ancillary data is not captured if not requested by receiver. | ||
722 | * | ||
723 | * Returns 0 if successful, otherwise errno | ||
724 | */ | ||
725 | |||
726 | static inline int anc_data_recv(struct msghdr *m, struct tipc_msg *msg, | ||
727 | struct tipc_port *tport) | ||
728 | { | ||
729 | u32 anc_data[3]; | ||
730 | u32 err; | ||
731 | u32 dest_type; | ||
732 | int res; | ||
733 | |||
734 | if (likely(m->msg_controllen == 0)) | ||
735 | return 0; | ||
736 | |||
737 | /* Optionally capture errored message object(s) */ | ||
738 | |||
739 | err = msg ? msg_errcode(msg) : 0; | ||
740 | if (unlikely(err)) { | ||
741 | anc_data[0] = err; | ||
742 | anc_data[1] = msg_data_sz(msg); | ||
743 | if ((res = put_cmsg(m, SOL_SOCKET, TIPC_ERRINFO, 8, anc_data))) | ||
744 | return res; | ||
745 | if (anc_data[1] && | ||
746 | (res = put_cmsg(m, SOL_SOCKET, TIPC_RETDATA, anc_data[1], | ||
747 | msg_data(msg)))) | ||
748 | return res; | ||
749 | } | ||
750 | |||
751 | /* Optionally capture message destination object */ | ||
752 | |||
753 | dest_type = msg ? msg_type(msg) : TIPC_DIRECT_MSG; | ||
754 | switch (dest_type) { | ||
755 | case TIPC_NAMED_MSG: | ||
756 | anc_data[0] = msg_nametype(msg); | ||
757 | anc_data[1] = msg_namelower(msg); | ||
758 | anc_data[2] = msg_namelower(msg); | ||
759 | break; | ||
760 | case TIPC_MCAST_MSG: | ||
761 | anc_data[0] = msg_nametype(msg); | ||
762 | anc_data[1] = msg_namelower(msg); | ||
763 | anc_data[2] = msg_nameupper(msg); | ||
764 | break; | ||
765 | case TIPC_CONN_MSG: | ||
766 | anc_data[0] = tport->conn_type; | ||
767 | anc_data[1] = tport->conn_instance; | ||
768 | anc_data[2] = tport->conn_instance; | ||
769 | break; | ||
770 | default: | ||
771 | anc_data[0] = 0; | ||
772 | } | ||
773 | if (anc_data[0] && | ||
774 | (res = put_cmsg(m, SOL_SOCKET, TIPC_DESTNAME, 12, anc_data))) | ||
775 | return res; | ||
776 | |||
777 | return 0; | ||
778 | } | ||
779 | |||
780 | /** | ||
781 | * recv_msg - receive packet-oriented message | ||
782 | * @iocb: (unused) | ||
783 | * @m: descriptor for message info | ||
784 | * @buf_len: total size of user buffer area | ||
785 | * @flags: receive flags | ||
786 | * | ||
787 | * Used for SOCK_DGRAM, SOCK_RDM, and SOCK_SEQPACKET messages. | ||
788 | * If the complete message doesn't fit in user area, truncate it. | ||
789 | * | ||
790 | * Returns size of returned message data, errno otherwise | ||
791 | */ | ||
792 | |||
793 | static int recv_msg(struct kiocb *iocb, struct socket *sock, | ||
794 | struct msghdr *m, size_t buf_len, int flags) | ||
795 | { | ||
796 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
797 | struct sk_buff *buf; | ||
798 | struct tipc_msg *msg; | ||
799 | unsigned int q_len; | ||
800 | unsigned int sz; | ||
801 | u32 err; | ||
802 | int res; | ||
803 | |||
804 | /* Currently doesn't support receiving into multiple iovec entries */ | ||
805 | |||
806 | if (m->msg_iovlen != 1) | ||
807 | return -EOPNOTSUPP; | ||
808 | |||
809 | /* Catch invalid receive attempts */ | ||
810 | |||
811 | if (unlikely(!buf_len)) | ||
812 | return -EINVAL; | ||
813 | |||
814 | if (sock->type == SOCK_SEQPACKET) { | ||
815 | if (unlikely(sock->state == SS_UNCONNECTED)) | ||
816 | return -ENOTCONN; | ||
817 | if (unlikely((sock->state == SS_DISCONNECTING) && | ||
818 | (skb_queue_len(&sock->sk->sk_receive_queue) == 0))) | ||
819 | return -ENOTCONN; | ||
820 | } | ||
821 | |||
822 | /* Look for a message in receive queue; wait if necessary */ | ||
823 | |||
824 | if (unlikely(down_interruptible(&tsock->sem))) | ||
825 | return -ERESTARTSYS; | ||
826 | |||
827 | restart: | ||
828 | if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && | ||
829 | (flags & MSG_DONTWAIT))) { | ||
830 | res = -EWOULDBLOCK; | ||
831 | goto exit; | ||
832 | } | ||
833 | |||
834 | if ((res = wait_event_interruptible( | ||
835 | *sock->sk->sk_sleep, | ||
836 | ((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) || | ||
837 | (sock->state == SS_DISCONNECTING))) )) { | ||
838 | goto exit; | ||
839 | } | ||
840 | |||
841 | /* Catch attempt to receive on an already terminated connection */ | ||
842 | /* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */ | ||
843 | |||
844 | if (!q_len) { | ||
845 | res = -ENOTCONN; | ||
846 | goto exit; | ||
847 | } | ||
848 | |||
849 | /* Get access to first message in receive queue */ | ||
850 | |||
851 | buf = skb_peek(&sock->sk->sk_receive_queue); | ||
852 | msg = buf_msg(buf); | ||
853 | sz = msg_data_sz(msg); | ||
854 | err = msg_errcode(msg); | ||
855 | |||
856 | /* Complete connection setup for an implied connect */ | ||
857 | |||
858 | if (unlikely(sock->state == SS_CONNECTING)) { | ||
859 | if ((res = auto_connect(sock, tsock, msg))) | ||
860 | goto exit; | ||
861 | } | ||
862 | |||
863 | /* Discard an empty non-errored message & try again */ | ||
864 | |||
865 | if ((!sz) && (!err)) { | ||
866 | advance_queue(tsock); | ||
867 | goto restart; | ||
868 | } | ||
869 | |||
870 | /* Capture sender's address (optional) */ | ||
871 | |||
872 | set_orig_addr(m, msg); | ||
873 | |||
874 | /* Capture ancillary data (optional) */ | ||
875 | |||
876 | if ((res = anc_data_recv(m, msg, tsock->p))) | ||
877 | goto exit; | ||
878 | |||
879 | /* Capture message data (if valid) & compute return value (always) */ | ||
880 | |||
881 | if (!err) { | ||
882 | if (unlikely(buf_len < sz)) { | ||
883 | sz = buf_len; | ||
884 | m->msg_flags |= MSG_TRUNC; | ||
885 | } | ||
886 | if (unlikely(copy_to_user(m->msg_iov->iov_base, msg_data(msg), | ||
887 | sz))) { | ||
888 | res = -EFAULT; | ||
889 | goto exit; | ||
890 | } | ||
891 | res = sz; | ||
892 | } else { | ||
893 | if ((sock->state == SS_READY) || | ||
894 | ((err == TIPC_CONN_SHUTDOWN) || m->msg_control)) | ||
895 | res = 0; | ||
896 | else | ||
897 | res = -ECONNRESET; | ||
898 | } | ||
899 | |||
900 | /* Consume received message (optional) */ | ||
901 | |||
902 | if (likely(!(flags & MSG_PEEK))) { | ||
903 | if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) | ||
904 | tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked); | ||
905 | advance_queue(tsock); | ||
906 | } | ||
907 | exit: | ||
908 | up(&tsock->sem); | ||
909 | return res; | ||
910 | } | ||
911 | |||
912 | /** | ||
913 | * recv_stream - receive stream-oriented data | ||
914 | * @iocb: (unused) | ||
915 | * @m: descriptor for message info | ||
916 | * @buf_len: total size of user buffer area | ||
917 | * @flags: receive flags | ||
918 | * | ||
919 | * Used for SOCK_STREAM messages only. If not enough data is available | ||
920 | * will optionally wait for more; never truncates data. | ||
921 | * | ||
922 | * Returns size of returned message data, errno otherwise | ||
923 | */ | ||
924 | |||
925 | static int recv_stream(struct kiocb *iocb, struct socket *sock, | ||
926 | struct msghdr *m, size_t buf_len, int flags) | ||
927 | { | ||
928 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
929 | struct sk_buff *buf; | ||
930 | struct tipc_msg *msg; | ||
931 | unsigned int q_len; | ||
932 | unsigned int sz; | ||
933 | int sz_to_copy; | ||
934 | int sz_copied = 0; | ||
935 | int needed; | ||
936 | char *crs = m->msg_iov->iov_base; | ||
937 | unsigned char *buf_crs; | ||
938 | u32 err; | ||
939 | int res; | ||
940 | |||
941 | /* Currently doesn't support receiving into multiple iovec entries */ | ||
942 | |||
943 | if (m->msg_iovlen != 1) | ||
944 | return -EOPNOTSUPP; | ||
945 | |||
946 | /* Catch invalid receive attempts */ | ||
947 | |||
948 | if (unlikely(!buf_len)) | ||
949 | return -EINVAL; | ||
950 | |||
951 | if (unlikely(sock->state == SS_DISCONNECTING)) { | ||
952 | if (skb_queue_len(&sock->sk->sk_receive_queue) == 0) | ||
953 | return -ENOTCONN; | ||
954 | } else if (unlikely(sock->state != SS_CONNECTED)) | ||
955 | return -ENOTCONN; | ||
956 | |||
957 | /* Look for a message in receive queue; wait if necessary */ | ||
958 | |||
959 | if (unlikely(down_interruptible(&tsock->sem))) | ||
960 | return -ERESTARTSYS; | ||
961 | |||
962 | restart: | ||
963 | if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && | ||
964 | (flags & MSG_DONTWAIT))) { | ||
965 | res = (sz_copied == 0) ? -EWOULDBLOCK : 0; | ||
966 | goto exit; | ||
967 | } | ||
968 | |||
969 | if ((res = wait_event_interruptible( | ||
970 | *sock->sk->sk_sleep, | ||
971 | ((q_len = skb_queue_len(&sock->sk->sk_receive_queue)) || | ||
972 | (sock->state == SS_DISCONNECTING))) )) { | ||
973 | goto exit; | ||
974 | } | ||
975 | |||
976 | /* Catch attempt to receive on an already terminated connection */ | ||
977 | /* [THIS CHECK MAY OVERLAP WITH AN EARLIER CHECK] */ | ||
978 | |||
979 | if (!q_len) { | ||
980 | res = -ENOTCONN; | ||
981 | goto exit; | ||
982 | } | ||
983 | |||
984 | /* Get access to first message in receive queue */ | ||
985 | |||
986 | buf = skb_peek(&sock->sk->sk_receive_queue); | ||
987 | msg = buf_msg(buf); | ||
988 | sz = msg_data_sz(msg); | ||
989 | err = msg_errcode(msg); | ||
990 | |||
991 | /* Discard an empty non-errored message & try again */ | ||
992 | |||
993 | if ((!sz) && (!err)) { | ||
994 | advance_queue(tsock); | ||
995 | goto restart; | ||
996 | } | ||
997 | |||
998 | /* Optionally capture sender's address & ancillary data of first msg */ | ||
999 | |||
1000 | if (sz_copied == 0) { | ||
1001 | set_orig_addr(m, msg); | ||
1002 | if ((res = anc_data_recv(m, msg, tsock->p))) | ||
1003 | goto exit; | ||
1004 | } | ||
1005 | |||
1006 | /* Capture message data (if valid) & compute return value (always) */ | ||
1007 | |||
1008 | if (!err) { | ||
1009 | buf_crs = (unsigned char *)(TIPC_SKB_CB(buf)->handle); | ||
1010 | sz = buf->tail - buf_crs; | ||
1011 | |||
1012 | needed = (buf_len - sz_copied); | ||
1013 | sz_to_copy = (sz <= needed) ? sz : needed; | ||
1014 | if (unlikely(copy_to_user(crs, buf_crs, sz_to_copy))) { | ||
1015 | res = -EFAULT; | ||
1016 | goto exit; | ||
1017 | } | ||
1018 | sz_copied += sz_to_copy; | ||
1019 | |||
1020 | if (sz_to_copy < sz) { | ||
1021 | if (!(flags & MSG_PEEK)) | ||
1022 | TIPC_SKB_CB(buf)->handle = buf_crs + sz_to_copy; | ||
1023 | goto exit; | ||
1024 | } | ||
1025 | |||
1026 | crs += sz_to_copy; | ||
1027 | } else { | ||
1028 | if (sz_copied != 0) | ||
1029 | goto exit; /* can't add error msg to valid data */ | ||
1030 | |||
1031 | if ((err == TIPC_CONN_SHUTDOWN) || m->msg_control) | ||
1032 | res = 0; | ||
1033 | else | ||
1034 | res = -ECONNRESET; | ||
1035 | } | ||
1036 | |||
1037 | /* Consume received message (optional) */ | ||
1038 | |||
1039 | if (likely(!(flags & MSG_PEEK))) { | ||
1040 | if (unlikely(++tsock->p->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) | ||
1041 | tipc_acknowledge(tsock->p->ref, tsock->p->conn_unacked); | ||
1042 | advance_queue(tsock); | ||
1043 | } | ||
1044 | |||
1045 | /* Loop around if more data is required */ | ||
1046 | |||
1047 | if ((sz_copied < buf_len) /* didn't get all requested data */ | ||
1048 | && (flags & MSG_WAITALL) /* ... and need to wait for more */ | ||
1049 | && (!(flags & MSG_PEEK)) /* ... and aren't just peeking at data */ | ||
1050 | && (!err) /* ... and haven't reached a FIN */ | ||
1051 | ) | ||
1052 | goto restart; | ||
1053 | |||
1054 | exit: | ||
1055 | up(&tsock->sem); | ||
1056 | return res ? res : sz_copied; | ||
1057 | } | ||
1058 | |||
1059 | /** | ||
1060 | * queue_overloaded - test if queue overload condition exists | ||
1061 | * @queue_size: current size of queue | ||
1062 | * @base: nominal maximum size of queue | ||
1063 | * @msg: message to be added to queue | ||
1064 | * | ||
1065 | * Returns 1 if queue is currently overloaded, 0 otherwise | ||
1066 | */ | ||
1067 | |||
1068 | static int queue_overloaded(u32 queue_size, u32 base, struct tipc_msg *msg) | ||
1069 | { | ||
1070 | u32 threshold; | ||
1071 | u32 imp = msg_importance(msg); | ||
1072 | |||
1073 | if (imp == TIPC_LOW_IMPORTANCE) | ||
1074 | threshold = base; | ||
1075 | else if (imp == TIPC_MEDIUM_IMPORTANCE) | ||
1076 | threshold = base * 2; | ||
1077 | else if (imp == TIPC_HIGH_IMPORTANCE) | ||
1078 | threshold = base * 100; | ||
1079 | else | ||
1080 | return 0; | ||
1081 | |||
1082 | if (msg_connected(msg)) | ||
1083 | threshold *= 4; | ||
1084 | |||
1085 | return (queue_size > threshold); | ||
1086 | } | ||
1087 | |||
1088 | /** | ||
1089 | * async_disconnect - wrapper function used to disconnect port | ||
1090 | * @portref: TIPC port reference (passed as pointer-sized value) | ||
1091 | */ | ||
1092 | |||
1093 | static void async_disconnect(unsigned long portref) | ||
1094 | { | ||
1095 | tipc_disconnect((u32)portref); | ||
1096 | } | ||
1097 | |||
1098 | /** | ||
1099 | * dispatch - handle arriving message | ||
1100 | * @tport: TIPC port that received message | ||
1101 | * @buf: message | ||
1102 | * | ||
1103 | * Called with port locked. Must not take socket lock to avoid deadlock risk. | ||
1104 | * | ||
1105 | * Returns TIPC error status code (TIPC_OK if message is not to be rejected) | ||
1106 | */ | ||
1107 | |||
1108 | static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf) | ||
1109 | { | ||
1110 | struct tipc_msg *msg = buf_msg(buf); | ||
1111 | struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle; | ||
1112 | struct socket *sock; | ||
1113 | u32 recv_q_len; | ||
1114 | |||
1115 | /* Reject message if socket is closing */ | ||
1116 | |||
1117 | if (!tsock) | ||
1118 | return TIPC_ERR_NO_PORT; | ||
1119 | |||
1120 | /* Reject message if it is wrong sort of message for socket */ | ||
1121 | |||
1122 | /* | ||
1123 | * WOULD IT BE BETTER TO JUST DISCARD THESE MESSAGES INSTEAD? | ||
1124 | * "NO PORT" ISN'T REALLY THE RIGHT ERROR CODE, AND THERE MAY | ||
1125 | * BE SECURITY IMPLICATIONS INHERENT IN REJECTING INVALID TRAFFIC | ||
1126 | */ | ||
1127 | sock = tsock->sk.sk_socket; | ||
1128 | if (sock->state == SS_READY) { | ||
1129 | if (msg_connected(msg)) { | ||
1130 | msg_dbg(msg, "dispatch filter 1\n"); | ||
1131 | return TIPC_ERR_NO_PORT; | ||
1132 | } | ||
1133 | } else { | ||
1134 | if (msg_mcast(msg)) { | ||
1135 | msg_dbg(msg, "dispatch filter 2\n"); | ||
1136 | return TIPC_ERR_NO_PORT; | ||
1137 | } | ||
1138 | if (sock->state == SS_CONNECTED) { | ||
1139 | if (!msg_connected(msg)) { | ||
1140 | msg_dbg(msg, "dispatch filter 3\n"); | ||
1141 | return TIPC_ERR_NO_PORT; | ||
1142 | } | ||
1143 | } | ||
1144 | else if (sock->state == SS_CONNECTING) { | ||
1145 | if (!msg_connected(msg) && (msg_errcode(msg) == 0)) { | ||
1146 | msg_dbg(msg, "dispatch filter 4\n"); | ||
1147 | return TIPC_ERR_NO_PORT; | ||
1148 | } | ||
1149 | } | ||
1150 | else if (sock->state == SS_LISTENING) { | ||
1151 | if (msg_connected(msg) || msg_errcode(msg)) { | ||
1152 | msg_dbg(msg, "dispatch filter 5\n"); | ||
1153 | return TIPC_ERR_NO_PORT; | ||
1154 | } | ||
1155 | } | ||
1156 | else if (sock->state == SS_DISCONNECTING) { | ||
1157 | msg_dbg(msg, "dispatch filter 6\n"); | ||
1158 | return TIPC_ERR_NO_PORT; | ||
1159 | } | ||
1160 | else /* (sock->state == SS_UNCONNECTED) */ { | ||
1161 | if (msg_connected(msg) || msg_errcode(msg)) { | ||
1162 | msg_dbg(msg, "dispatch filter 7\n"); | ||
1163 | return TIPC_ERR_NO_PORT; | ||
1164 | } | ||
1165 | } | ||
1166 | } | ||
1167 | |||
1168 | /* Reject message if there isn't room to queue it */ | ||
1169 | |||
1170 | if (unlikely((u32)atomic_read(&tipc_queue_size) > | ||
1171 | OVERLOAD_LIMIT_BASE)) { | ||
1172 | if (queue_overloaded(atomic_read(&tipc_queue_size), | ||
1173 | OVERLOAD_LIMIT_BASE, msg)) | ||
1174 | return TIPC_ERR_OVERLOAD; | ||
1175 | } | ||
1176 | recv_q_len = skb_queue_len(&tsock->sk.sk_receive_queue); | ||
1177 | if (unlikely(recv_q_len > (OVERLOAD_LIMIT_BASE / 2))) { | ||
1178 | if (queue_overloaded(recv_q_len, | ||
1179 | OVERLOAD_LIMIT_BASE / 2, msg)) | ||
1180 | return TIPC_ERR_OVERLOAD; | ||
1181 | } | ||
1182 | |||
1183 | /* Initiate connection termination for an incoming 'FIN' */ | ||
1184 | |||
1185 | if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) { | ||
1186 | sock->state = SS_DISCONNECTING; | ||
1187 | /* Note: Use signal since port lock is already taken! */ | ||
1188 | k_signal((Handler)async_disconnect, tport->ref); | ||
1189 | } | ||
1190 | |||
1191 | /* Enqueue message (finally!) */ | ||
1192 | |||
1193 | msg_dbg(msg,"<DISP<: "); | ||
1194 | TIPC_SKB_CB(buf)->handle = msg_data(msg); | ||
1195 | atomic_inc(&tipc_queue_size); | ||
1196 | skb_queue_tail(&sock->sk->sk_receive_queue, buf); | ||
1197 | |||
1198 | wake_up_interruptible(sock->sk->sk_sleep); | ||
1199 | return TIPC_OK; | ||
1200 | } | ||
1201 | |||
1202 | /** | ||
1203 | * wakeupdispatch - wake up port after congestion | ||
1204 | * @tport: port to wakeup | ||
1205 | * | ||
1206 | * Called with port lock on. | ||
1207 | */ | ||
1208 | |||
1209 | static void wakeupdispatch(struct tipc_port *tport) | ||
1210 | { | ||
1211 | struct tipc_sock *tsock = (struct tipc_sock *)tport->usr_handle; | ||
1212 | |||
1213 | wake_up_interruptible(tsock->sk.sk_sleep); | ||
1214 | } | ||
1215 | |||
1216 | /** | ||
1217 | * connect - establish a connection to another TIPC port | ||
1218 | * @sock: socket structure | ||
1219 | * @dest: socket address for destination port | ||
1220 | * @destlen: size of socket address data structure | ||
1221 | * @flags: (unused) | ||
1222 | * | ||
1223 | * Returns 0 on success, errno otherwise | ||
1224 | */ | ||
1225 | |||
1226 | static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | ||
1227 | int flags) | ||
1228 | { | ||
1229 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
1230 | struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; | ||
1231 | struct msghdr m = {0,}; | ||
1232 | struct sk_buff *buf; | ||
1233 | struct tipc_msg *msg; | ||
1234 | int res; | ||
1235 | |||
1236 | /* For now, TIPC does not allow use of connect() with DGRAM or RDM types */ | ||
1237 | |||
1238 | if (sock->state == SS_READY) | ||
1239 | return -EOPNOTSUPP; | ||
1240 | |||
1241 | /* MOVE THE REST OF THIS ERROR CHECKING TO send_msg()? */ | ||
1242 | if (sock->state == SS_LISTENING) | ||
1243 | return -EOPNOTSUPP; | ||
1244 | if (sock->state == SS_CONNECTING) | ||
1245 | return -EALREADY; | ||
1246 | if (sock->state != SS_UNCONNECTED) | ||
1247 | return -EISCONN; | ||
1248 | |||
1249 | if ((dst->family != AF_TIPC) || | ||
1250 | ((dst->addrtype != TIPC_ADDR_NAME) && (dst->addrtype != TIPC_ADDR_ID))) | ||
1251 | return -EINVAL; | ||
1252 | |||
1253 | /* Send a 'SYN-' to destination */ | ||
1254 | |||
1255 | m.msg_name = dest; | ||
1256 | if ((res = send_msg(0, sock, &m, 0)) < 0) { | ||
1257 | sock->state = SS_DISCONNECTING; | ||
1258 | return res; | ||
1259 | } | ||
1260 | |||
1261 | if (down_interruptible(&tsock->sem)) | ||
1262 | return -ERESTARTSYS; | ||
1263 | |||
1264 | /* Wait for destination's 'ACK' response */ | ||
1265 | |||
1266 | res = wait_event_interruptible_timeout(*sock->sk->sk_sleep, | ||
1267 | skb_queue_len(&sock->sk->sk_receive_queue), | ||
1268 | sock->sk->sk_rcvtimeo); | ||
1269 | buf = skb_peek(&sock->sk->sk_receive_queue); | ||
1270 | if (res > 0) { | ||
1271 | msg = buf_msg(buf); | ||
1272 | res = auto_connect(sock, tsock, msg); | ||
1273 | if (!res) { | ||
1274 | if (dst->addrtype == TIPC_ADDR_NAME) { | ||
1275 | tsock->p->conn_type = dst->addr.name.name.type; | ||
1276 | tsock->p->conn_instance = dst->addr.name.name.instance; | ||
1277 | } | ||
1278 | if (!msg_data_sz(msg)) | ||
1279 | advance_queue(tsock); | ||
1280 | } | ||
1281 | } else { | ||
1282 | if (res == 0) { | ||
1283 | res = -ETIMEDOUT; | ||
1284 | } else | ||
1285 | { /* leave "res" unchanged */ } | ||
1286 | sock->state = SS_DISCONNECTING; | ||
1287 | } | ||
1288 | |||
1289 | up(&tsock->sem); | ||
1290 | return res; | ||
1291 | } | ||
1292 | |||
1293 | /** | ||
1294 | * listen - allow socket to listen for incoming connections | ||
1295 | * @sock: socket structure | ||
1296 | * @len: (unused) | ||
1297 | * | ||
1298 | * Returns 0 on success, errno otherwise | ||
1299 | */ | ||
1300 | |||
1301 | static int listen(struct socket *sock, int len) | ||
1302 | { | ||
1303 | /* REQUIRES SOCKET LOCKING OF SOME SORT? */ | ||
1304 | |||
1305 | if (sock->state == SS_READY) | ||
1306 | return -EOPNOTSUPP; | ||
1307 | if (sock->state != SS_UNCONNECTED) | ||
1308 | return -EINVAL; | ||
1309 | sock->state = SS_LISTENING; | ||
1310 | return 0; | ||
1311 | } | ||
1312 | |||
1313 | /** | ||
1314 | * accept - wait for connection request | ||
1315 | * @sock: listening socket | ||
1316 | * @newsock: new socket that is to be connected | ||
1317 | * @flags: file-related flags associated with socket | ||
1318 | * | ||
1319 | * Returns 0 on success, errno otherwise | ||
1320 | */ | ||
1321 | |||
1322 | static int accept(struct socket *sock, struct socket *newsock, int flags) | ||
1323 | { | ||
1324 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
1325 | struct sk_buff *buf; | ||
1326 | int res = -EFAULT; | ||
1327 | |||
1328 | if (sock->state == SS_READY) | ||
1329 | return -EOPNOTSUPP; | ||
1330 | if (sock->state != SS_LISTENING) | ||
1331 | return -EINVAL; | ||
1332 | |||
1333 | if (unlikely((skb_queue_len(&sock->sk->sk_receive_queue) == 0) && | ||
1334 | (flags & O_NONBLOCK))) | ||
1335 | return -EWOULDBLOCK; | ||
1336 | |||
1337 | if (down_interruptible(&tsock->sem)) | ||
1338 | return -ERESTARTSYS; | ||
1339 | |||
1340 | if (wait_event_interruptible(*sock->sk->sk_sleep, | ||
1341 | skb_queue_len(&sock->sk->sk_receive_queue))) { | ||
1342 | res = -ERESTARTSYS; | ||
1343 | goto exit; | ||
1344 | } | ||
1345 | buf = skb_peek(&sock->sk->sk_receive_queue); | ||
1346 | |||
1347 | res = tipc_create(newsock, 0); | ||
1348 | if (!res) { | ||
1349 | struct tipc_sock *new_tsock = tipc_sk(newsock->sk); | ||
1350 | struct tipc_portid id; | ||
1351 | struct tipc_msg *msg = buf_msg(buf); | ||
1352 | u32 new_ref = new_tsock->p->ref; | ||
1353 | |||
1354 | id.ref = msg_origport(msg); | ||
1355 | id.node = msg_orignode(msg); | ||
1356 | tipc_connect2port(new_ref, &id); | ||
1357 | newsock->state = SS_CONNECTED; | ||
1358 | |||
1359 | tipc_set_portimportance(new_ref, msg_importance(msg)); | ||
1360 | if (msg_named(msg)) { | ||
1361 | new_tsock->p->conn_type = msg_nametype(msg); | ||
1362 | new_tsock->p->conn_instance = msg_nameinst(msg); | ||
1363 | } | ||
1364 | |||
1365 | /* | ||
1366 | * Respond to 'SYN-' by discarding it & returning 'ACK'-. | ||
1367 | * Respond to 'SYN+' by queuing it on new socket. | ||
1368 | */ | ||
1369 | |||
1370 | msg_dbg(msg,"<ACC<: "); | ||
1371 | if (!msg_data_sz(msg)) { | ||
1372 | struct msghdr m = {0,}; | ||
1373 | |||
1374 | send_packet(0, newsock, &m, 0); | ||
1375 | advance_queue(tsock); | ||
1376 | } else { | ||
1377 | sock_lock(tsock); | ||
1378 | skb_dequeue(&sock->sk->sk_receive_queue); | ||
1379 | sock_unlock(tsock); | ||
1380 | skb_queue_head(&newsock->sk->sk_receive_queue, buf); | ||
1381 | } | ||
1382 | } | ||
1383 | exit: | ||
1384 | up(&tsock->sem); | ||
1385 | return res; | ||
1386 | } | ||
1387 | |||
1388 | /** | ||
1389 | * shutdown - shutdown socket connection | ||
1390 | * @sock: socket structure | ||
1391 | * @how: direction to close (always treated as read + write) | ||
1392 | * | ||
1393 | * Terminates connection (if necessary), then purges socket's receive queue. | ||
1394 | * | ||
1395 | * Returns 0 on success, errno otherwise | ||
1396 | */ | ||
1397 | |||
1398 | static int shutdown(struct socket *sock, int how) | ||
1399 | { | ||
1400 | struct tipc_sock* tsock = tipc_sk(sock->sk); | ||
1401 | struct sk_buff *buf; | ||
1402 | int res; | ||
1403 | |||
1404 | /* Could return -EINVAL for an invalid "how", but why bother? */ | ||
1405 | |||
1406 | if (down_interruptible(&tsock->sem)) | ||
1407 | return -ERESTARTSYS; | ||
1408 | |||
1409 | sock_lock(tsock); | ||
1410 | |||
1411 | switch (sock->state) { | ||
1412 | case SS_CONNECTED: | ||
1413 | |||
1414 | /* Send 'FIN+' or 'FIN-' message to peer */ | ||
1415 | |||
1416 | sock_unlock(tsock); | ||
1417 | restart: | ||
1418 | if ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) { | ||
1419 | atomic_dec(&tipc_queue_size); | ||
1420 | if (TIPC_SKB_CB(buf)->handle != msg_data(buf_msg(buf))) { | ||
1421 | buf_discard(buf); | ||
1422 | goto restart; | ||
1423 | } | ||
1424 | tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN); | ||
1425 | } | ||
1426 | else { | ||
1427 | tipc_shutdown(tsock->p->ref); | ||
1428 | } | ||
1429 | sock_lock(tsock); | ||
1430 | |||
1431 | /* fall through */ | ||
1432 | |||
1433 | case SS_DISCONNECTING: | ||
1434 | |||
1435 | /* Discard any unreceived messages */ | ||
1436 | |||
1437 | while ((buf = skb_dequeue(&sock->sk->sk_receive_queue))) { | ||
1438 | atomic_dec(&tipc_queue_size); | ||
1439 | buf_discard(buf); | ||
1440 | } | ||
1441 | tsock->p->conn_unacked = 0; | ||
1442 | |||
1443 | /* fall through */ | ||
1444 | |||
1445 | case SS_CONNECTING: | ||
1446 | sock->state = SS_DISCONNECTING; | ||
1447 | res = 0; | ||
1448 | break; | ||
1449 | |||
1450 | default: | ||
1451 | res = -ENOTCONN; | ||
1452 | } | ||
1453 | |||
1454 | sock_unlock(tsock); | ||
1455 | |||
1456 | up(&tsock->sem); | ||
1457 | return res; | ||
1458 | } | ||
1459 | |||
1460 | /** | ||
1461 | * setsockopt - set socket option | ||
1462 | * @sock: socket structure | ||
1463 | * @lvl: option level | ||
1464 | * @opt: option identifier | ||
1465 | * @ov: pointer to new option value | ||
1466 | * @ol: length of option value | ||
1467 | * | ||
1468 | * For stream sockets only, accepts and ignores all IPPROTO_TCP options | ||
1469 | * (to ease compatibility). | ||
1470 | * | ||
1471 | * Returns 0 on success, errno otherwise | ||
1472 | */ | ||
1473 | |||
1474 | static int setsockopt(struct socket *sock, int lvl, int opt, char *ov, int ol) | ||
1475 | { | ||
1476 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
1477 | u32 value; | ||
1478 | int res; | ||
1479 | |||
1480 | if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) | ||
1481 | return 0; | ||
1482 | if (lvl != SOL_TIPC) | ||
1483 | return -ENOPROTOOPT; | ||
1484 | if (ol < sizeof(value)) | ||
1485 | return -EINVAL; | ||
1486 | if ((res = get_user(value, (u32 *)ov))) | ||
1487 | return res; | ||
1488 | |||
1489 | if (down_interruptible(&tsock->sem)) | ||
1490 | return -ERESTARTSYS; | ||
1491 | |||
1492 | switch (opt) { | ||
1493 | case TIPC_IMPORTANCE: | ||
1494 | res = tipc_set_portimportance(tsock->p->ref, value); | ||
1495 | break; | ||
1496 | case TIPC_SRC_DROPPABLE: | ||
1497 | if (sock->type != SOCK_STREAM) | ||
1498 | res = tipc_set_portunreliable(tsock->p->ref, value); | ||
1499 | else | ||
1500 | res = -ENOPROTOOPT; | ||
1501 | break; | ||
1502 | case TIPC_DEST_DROPPABLE: | ||
1503 | res = tipc_set_portunreturnable(tsock->p->ref, value); | ||
1504 | break; | ||
1505 | case TIPC_CONN_TIMEOUT: | ||
1506 | sock->sk->sk_rcvtimeo = (value * HZ / 1000); | ||
1507 | break; | ||
1508 | default: | ||
1509 | res = -EINVAL; | ||
1510 | } | ||
1511 | |||
1512 | up(&tsock->sem); | ||
1513 | return res; | ||
1514 | } | ||
1515 | |||
1516 | /** | ||
1517 | * getsockopt - get socket option | ||
1518 | * @sock: socket structure | ||
1519 | * @lvl: option level | ||
1520 | * @opt: option identifier | ||
1521 | * @ov: receptacle for option value | ||
1522 | * @ol: receptacle for length of option value | ||
1523 | * | ||
1524 | * For stream sockets only, returns 0 length result for all IPPROTO_TCP options | ||
1525 | * (to ease compatibility). | ||
1526 | * | ||
1527 | * Returns 0 on success, errno otherwise | ||
1528 | */ | ||
1529 | |||
1530 | static int getsockopt(struct socket *sock, int lvl, int opt, char *ov, int *ol) | ||
1531 | { | ||
1532 | struct tipc_sock *tsock = tipc_sk(sock->sk); | ||
1533 | int len; | ||
1534 | u32 value; | ||
1535 | int res; | ||
1536 | |||
1537 | if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) | ||
1538 | return put_user(0, ol); | ||
1539 | if (lvl != SOL_TIPC) | ||
1540 | return -ENOPROTOOPT; | ||
1541 | if ((res = get_user(len, ol))) | ||
1542 | return res; | ||
1543 | |||
1544 | if (down_interruptible(&tsock->sem)) | ||
1545 | return -ERESTARTSYS; | ||
1546 | |||
1547 | switch (opt) { | ||
1548 | case TIPC_IMPORTANCE: | ||
1549 | res = tipc_portimportance(tsock->p->ref, &value); | ||
1550 | break; | ||
1551 | case TIPC_SRC_DROPPABLE: | ||
1552 | res = tipc_portunreliable(tsock->p->ref, &value); | ||
1553 | break; | ||
1554 | case TIPC_DEST_DROPPABLE: | ||
1555 | res = tipc_portunreturnable(tsock->p->ref, &value); | ||
1556 | break; | ||
1557 | case TIPC_CONN_TIMEOUT: | ||
1558 | value = (sock->sk->sk_rcvtimeo * 1000) / HZ; | ||
1559 | break; | ||
1560 | default: | ||
1561 | res = -EINVAL; | ||
1562 | } | ||
1563 | |||
1564 | if (res) { | ||
1565 | /* "get" failed */ | ||
1566 | } | ||
1567 | else if (len < sizeof(value)) { | ||
1568 | res = -EINVAL; | ||
1569 | } | ||
1570 | else if ((res = copy_to_user(ov, &value, sizeof(value)))) { | ||
1571 | /* couldn't return value */ | ||
1572 | } | ||
1573 | else { | ||
1574 | res = put_user(sizeof(value), ol); | ||
1575 | } | ||
1576 | |||
1577 | up(&tsock->sem); | ||
1578 | return res; | ||
1579 | } | ||
1580 | |||
1581 | /** | ||
1582 | * Placeholders for non-implemented functionality | ||
1583 | * | ||
1584 | * Returns error code (POSIX-compliant where defined) | ||
1585 | */ | ||
1586 | |||
1587 | static int ioctl(struct socket *s, u32 cmd, unsigned long arg) | ||
1588 | { | ||
1589 | return -EINVAL; | ||
1590 | } | ||
1591 | |||
1592 | static int no_mmap(struct file *file, struct socket *sock, | ||
1593 | struct vm_area_struct *vma) | ||
1594 | { | ||
1595 | return -EINVAL; | ||
1596 | } | ||
1597 | static ssize_t no_sendpage(struct socket *sock, struct page *page, | ||
1598 | int offset, size_t size, int flags) | ||
1599 | { | ||
1600 | return -EINVAL; | ||
1601 | } | ||
1602 | |||
1603 | static int no_skpair(struct socket *s1, struct socket *s2) | ||
1604 | { | ||
1605 | return -EOPNOTSUPP; | ||
1606 | } | ||
1607 | |||
1608 | /** | ||
1609 | * Protocol switches for the various types of TIPC sockets | ||
1610 | */ | ||
1611 | |||
1612 | static struct proto_ops msg_ops = { | ||
1613 | .owner = THIS_MODULE, | ||
1614 | .family = AF_TIPC, | ||
1615 | .release = release, | ||
1616 | .bind = bind, | ||
1617 | .connect = connect, | ||
1618 | .socketpair = no_skpair, | ||
1619 | .accept = accept, | ||
1620 | .getname = get_name, | ||
1621 | .poll = poll, | ||
1622 | .ioctl = ioctl, | ||
1623 | .listen = listen, | ||
1624 | .shutdown = shutdown, | ||
1625 | .setsockopt = setsockopt, | ||
1626 | .getsockopt = getsockopt, | ||
1627 | .sendmsg = send_msg, | ||
1628 | .recvmsg = recv_msg, | ||
1629 | .mmap = no_mmap, | ||
1630 | .sendpage = no_sendpage | ||
1631 | }; | ||
1632 | |||
1633 | static struct proto_ops packet_ops = { | ||
1634 | .owner = THIS_MODULE, | ||
1635 | .family = AF_TIPC, | ||
1636 | .release = release, | ||
1637 | .bind = bind, | ||
1638 | .connect = connect, | ||
1639 | .socketpair = no_skpair, | ||
1640 | .accept = accept, | ||
1641 | .getname = get_name, | ||
1642 | .poll = poll, | ||
1643 | .ioctl = ioctl, | ||
1644 | .listen = listen, | ||
1645 | .shutdown = shutdown, | ||
1646 | .setsockopt = setsockopt, | ||
1647 | .getsockopt = getsockopt, | ||
1648 | .sendmsg = send_packet, | ||
1649 | .recvmsg = recv_msg, | ||
1650 | .mmap = no_mmap, | ||
1651 | .sendpage = no_sendpage | ||
1652 | }; | ||
1653 | |||
1654 | static struct proto_ops stream_ops = { | ||
1655 | .owner = THIS_MODULE, | ||
1656 | .family = AF_TIPC, | ||
1657 | .release = release, | ||
1658 | .bind = bind, | ||
1659 | .connect = connect, | ||
1660 | .socketpair = no_skpair, | ||
1661 | .accept = accept, | ||
1662 | .getname = get_name, | ||
1663 | .poll = poll, | ||
1664 | .ioctl = ioctl, | ||
1665 | .listen = listen, | ||
1666 | .shutdown = shutdown, | ||
1667 | .setsockopt = setsockopt, | ||
1668 | .getsockopt = getsockopt, | ||
1669 | .sendmsg = send_stream, | ||
1670 | .recvmsg = recv_stream, | ||
1671 | .mmap = no_mmap, | ||
1672 | .sendpage = no_sendpage | ||
1673 | }; | ||
1674 | |||
1675 | static struct net_proto_family tipc_family_ops = { | ||
1676 | .owner = THIS_MODULE, | ||
1677 | .family = AF_TIPC, | ||
1678 | .create = tipc_create | ||
1679 | }; | ||
1680 | |||
1681 | static struct proto tipc_proto = { | ||
1682 | .name = "TIPC", | ||
1683 | .owner = THIS_MODULE, | ||
1684 | .obj_size = sizeof(struct tipc_sock) | ||
1685 | }; | ||
1686 | |||
1687 | /** | ||
1688 | * socket_init - initialize TIPC socket interface | ||
1689 | * | ||
1690 | * Returns 0 on success, errno otherwise | ||
1691 | */ | ||
1692 | int socket_init(void) | ||
1693 | { | ||
1694 | int res; | ||
1695 | |||
1696 | res = proto_register(&tipc_proto, 1); | ||
1697 | if (res) { | ||
1698 | err("Failed to register TIPC protocol type\n"); | ||
1699 | goto out; | ||
1700 | } | ||
1701 | |||
1702 | res = sock_register(&tipc_family_ops); | ||
1703 | if (res) { | ||
1704 | err("Failed to register TIPC socket type\n"); | ||
1705 | proto_unregister(&tipc_proto); | ||
1706 | goto out; | ||
1707 | } | ||
1708 | |||
1709 | sockets_enabled = 1; | ||
1710 | out: | ||
1711 | return res; | ||
1712 | } | ||
1713 | |||
1714 | /** | ||
1715 | * sock_stop - stop TIPC socket interface | ||
1716 | */ | ||
1717 | void socket_stop(void) | ||
1718 | { | ||
1719 | if (!sockets_enabled) | ||
1720 | return; | ||
1721 | |||
1722 | sockets_enabled = 0; | ||
1723 | sock_unregister(tipc_family_ops.family); | ||
1724 | proto_unregister(&tipc_proto); | ||
1725 | } | ||
1726 | |||
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c new file mode 100644 index 000000000000..80e219ba527d --- /dev/null +++ b/net/tipc/subscr.c | |||
@@ -0,0 +1,527 @@ | |||
1 | /* | ||
2 | * net/tipc/subscr.c: TIPC subscription service | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "dbg.h" | ||
39 | #include "subscr.h" | ||
40 | #include "name_table.h" | ||
41 | #include "ref.h" | ||
42 | |||
43 | /** | ||
44 | * struct subscriber - TIPC network topology subscriber | ||
45 | * @ref: object reference to subscriber object itself | ||
46 | * @lock: pointer to spinlock controlling access to subscriber object | ||
47 | * @subscriber_list: adjacent subscribers in top. server's list of subscribers | ||
48 | * @subscription_list: list of subscription objects for this subscriber | ||
49 | * @port_ref: object reference to port used to communicate with subscriber | ||
50 | * @swap: indicates if subscriber uses opposite endianness in its messages | ||
51 | */ | ||
52 | |||
53 | struct subscriber { | ||
54 | u32 ref; | ||
55 | spinlock_t *lock; | ||
56 | struct list_head subscriber_list; | ||
57 | struct list_head subscription_list; | ||
58 | u32 port_ref; | ||
59 | int swap; | ||
60 | }; | ||
61 | |||
62 | /** | ||
63 | * struct top_srv - TIPC network topology subscription service | ||
64 | * @user_ref: TIPC userid of subscription service | ||
65 | * @setup_port: reference to TIPC port that handles subscription requests | ||
66 | * @subscription_count: number of active subscriptions (not subscribers!) | ||
67 | * @subscriber_list: list of ports subscribing to service | ||
68 | * @lock: spinlock govering access to subscriber list | ||
69 | */ | ||
70 | |||
71 | struct top_srv { | ||
72 | u32 user_ref; | ||
73 | u32 setup_port; | ||
74 | atomic_t subscription_count; | ||
75 | struct list_head subscriber_list; | ||
76 | spinlock_t lock; | ||
77 | }; | ||
78 | |||
79 | static struct top_srv topsrv = { 0 }; | ||
80 | |||
81 | /** | ||
82 | * htohl - convert value to endianness used by destination | ||
83 | * @in: value to convert | ||
84 | * @swap: non-zero if endianness must be reversed | ||
85 | * | ||
86 | * Returns converted value | ||
87 | */ | ||
88 | |||
89 | static inline u32 htohl(u32 in, int swap) | ||
90 | { | ||
91 | char *c = (char *)∈ | ||
92 | |||
93 | return swap ? ((c[3] << 3) + (c[2] << 2) + (c[1] << 1) + c[0]) : in; | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * subscr_send_event - send a message containing a tipc_event to the subscriber | ||
98 | */ | ||
99 | |||
100 | static void subscr_send_event(struct subscription *sub, | ||
101 | u32 found_lower, | ||
102 | u32 found_upper, | ||
103 | u32 event, | ||
104 | u32 port_ref, | ||
105 | u32 node) | ||
106 | { | ||
107 | struct iovec msg_sect; | ||
108 | |||
109 | msg_sect.iov_base = (void *)&sub->evt; | ||
110 | msg_sect.iov_len = sizeof(struct tipc_event); | ||
111 | |||
112 | sub->evt.event = htohl(event, sub->owner->swap); | ||
113 | sub->evt.found_lower = htohl(found_lower, sub->owner->swap); | ||
114 | sub->evt.found_upper = htohl(found_upper, sub->owner->swap); | ||
115 | sub->evt.port.ref = htohl(port_ref, sub->owner->swap); | ||
116 | sub->evt.port.node = htohl(node, sub->owner->swap); | ||
117 | tipc_send(sub->owner->port_ref, 1, &msg_sect); | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * subscr_overlap - test for subscription overlap with the given values | ||
122 | * | ||
123 | * Returns 1 if there is overlap, otherwise 0. | ||
124 | */ | ||
125 | |||
126 | int subscr_overlap(struct subscription *sub, | ||
127 | u32 found_lower, | ||
128 | u32 found_upper) | ||
129 | |||
130 | { | ||
131 | if (found_lower < sub->seq.lower) | ||
132 | found_lower = sub->seq.lower; | ||
133 | if (found_upper > sub->seq.upper) | ||
134 | found_upper = sub->seq.upper; | ||
135 | if (found_lower > found_upper) | ||
136 | return 0; | ||
137 | return 1; | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * subscr_report_overlap - issue event if there is subscription overlap | ||
142 | * | ||
143 | * Protected by nameseq.lock in name_table.c | ||
144 | */ | ||
145 | |||
146 | void subscr_report_overlap(struct subscription *sub, | ||
147 | u32 found_lower, | ||
148 | u32 found_upper, | ||
149 | u32 event, | ||
150 | u32 port_ref, | ||
151 | u32 node, | ||
152 | int must) | ||
153 | { | ||
154 | dbg("Rep overlap %u:%u,%u<->%u,%u\n", sub->seq.type, sub->seq.lower, | ||
155 | sub->seq.upper, found_lower, found_upper); | ||
156 | if (!subscr_overlap(sub, found_lower, found_upper)) | ||
157 | return; | ||
158 | if (!must && (sub->filter != TIPC_SUB_PORTS)) | ||
159 | return; | ||
160 | subscr_send_event(sub, found_lower, found_upper, event, port_ref, node); | ||
161 | } | ||
162 | |||
163 | /** | ||
164 | * subscr_timeout - subscription timeout has occurred | ||
165 | */ | ||
166 | |||
167 | static void subscr_timeout(struct subscription *sub) | ||
168 | { | ||
169 | struct subscriber *subscriber; | ||
170 | u32 subscriber_ref; | ||
171 | |||
172 | /* Validate subscriber reference (in case subscriber is terminating) */ | ||
173 | |||
174 | subscriber_ref = sub->owner->ref; | ||
175 | subscriber = (struct subscriber *)ref_lock(subscriber_ref); | ||
176 | if (subscriber == NULL) | ||
177 | return; | ||
178 | |||
179 | /* Unlink subscription from name table */ | ||
180 | |||
181 | nametbl_unsubscribe(sub); | ||
182 | |||
183 | /* Notify subscriber of timeout, then unlink subscription */ | ||
184 | |||
185 | subscr_send_event(sub, | ||
186 | sub->evt.s.seq.lower, | ||
187 | sub->evt.s.seq.upper, | ||
188 | TIPC_SUBSCR_TIMEOUT, | ||
189 | 0, | ||
190 | 0); | ||
191 | list_del(&sub->subscription_list); | ||
192 | |||
193 | /* Now destroy subscription */ | ||
194 | |||
195 | ref_unlock(subscriber_ref); | ||
196 | k_term_timer(&sub->timer); | ||
197 | kfree(sub); | ||
198 | atomic_dec(&topsrv.subscription_count); | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * subscr_terminate - terminate communication with a subscriber | ||
203 | * | ||
204 | * Called with subscriber locked. Routine must temporarily release this lock | ||
205 | * to enable subscription timeout routine(s) to finish without deadlocking; | ||
206 | * the lock is then reclaimed to allow caller to release it upon return. | ||
207 | * (This should work even in the unlikely event some other thread creates | ||
208 | * a new object reference in the interim that uses this lock; this routine will | ||
209 | * simply wait for it to be released, then claim it.) | ||
210 | */ | ||
211 | |||
212 | static void subscr_terminate(struct subscriber *subscriber) | ||
213 | { | ||
214 | struct subscription *sub; | ||
215 | struct subscription *sub_temp; | ||
216 | |||
217 | /* Invalidate subscriber reference */ | ||
218 | |||
219 | ref_discard(subscriber->ref); | ||
220 | spin_unlock_bh(subscriber->lock); | ||
221 | |||
222 | /* Destroy any existing subscriptions for subscriber */ | ||
223 | |||
224 | list_for_each_entry_safe(sub, sub_temp, &subscriber->subscription_list, | ||
225 | subscription_list) { | ||
226 | if (sub->timeout != TIPC_WAIT_FOREVER) { | ||
227 | k_cancel_timer(&sub->timer); | ||
228 | k_term_timer(&sub->timer); | ||
229 | } | ||
230 | nametbl_unsubscribe(sub); | ||
231 | list_del(&sub->subscription_list); | ||
232 | dbg("Term: Removed sub %u,%u,%u from subscriber %x list\n", | ||
233 | sub->seq.type, sub->seq.lower, sub->seq.upper, subscriber); | ||
234 | kfree(sub); | ||
235 | atomic_dec(&topsrv.subscription_count); | ||
236 | } | ||
237 | |||
238 | /* Sever connection to subscriber */ | ||
239 | |||
240 | tipc_shutdown(subscriber->port_ref); | ||
241 | tipc_deleteport(subscriber->port_ref); | ||
242 | |||
243 | /* Remove subscriber from topology server's subscriber list */ | ||
244 | |||
245 | spin_lock_bh(&topsrv.lock); | ||
246 | list_del(&subscriber->subscriber_list); | ||
247 | spin_unlock_bh(&topsrv.lock); | ||
248 | |||
249 | /* Now destroy subscriber */ | ||
250 | |||
251 | spin_lock_bh(subscriber->lock); | ||
252 | kfree(subscriber); | ||
253 | } | ||
254 | |||
255 | /** | ||
256 | * subscr_subscribe - create subscription for subscriber | ||
257 | * | ||
258 | * Called with subscriber locked | ||
259 | */ | ||
260 | |||
261 | static void subscr_subscribe(struct tipc_subscr *s, | ||
262 | struct subscriber *subscriber) | ||
263 | { | ||
264 | struct subscription *sub; | ||
265 | |||
266 | /* Refuse subscription if global limit exceeded */ | ||
267 | |||
268 | if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) { | ||
269 | warn("Failed: max %u subscriptions\n", tipc_max_subscriptions); | ||
270 | subscr_terminate(subscriber); | ||
271 | return; | ||
272 | } | ||
273 | |||
274 | /* Allocate subscription object */ | ||
275 | |||
276 | sub = kmalloc(sizeof(*sub), GFP_ATOMIC); | ||
277 | if (sub == NULL) { | ||
278 | warn("Memory squeeze; ignoring subscription\n"); | ||
279 | subscr_terminate(subscriber); | ||
280 | return; | ||
281 | } | ||
282 | |||
283 | /* Determine/update subscriber's endianness */ | ||
284 | |||
285 | if ((s->filter == TIPC_SUB_PORTS) || (s->filter == TIPC_SUB_SERVICE)) | ||
286 | subscriber->swap = 0; | ||
287 | else | ||
288 | subscriber->swap = 1; | ||
289 | |||
290 | /* Initialize subscription object */ | ||
291 | |||
292 | memset(sub, 0, sizeof(*sub)); | ||
293 | sub->seq.type = htohl(s->seq.type, subscriber->swap); | ||
294 | sub->seq.lower = htohl(s->seq.lower, subscriber->swap); | ||
295 | sub->seq.upper = htohl(s->seq.upper, subscriber->swap); | ||
296 | sub->timeout = htohl(s->timeout, subscriber->swap); | ||
297 | sub->filter = htohl(s->filter, subscriber->swap); | ||
298 | if ((((sub->filter != TIPC_SUB_PORTS) | ||
299 | && (sub->filter != TIPC_SUB_SERVICE))) | ||
300 | || (sub->seq.lower > sub->seq.upper)) { | ||
301 | warn("Rejecting illegal subscription %u,%u,%u\n", | ||
302 | sub->seq.type, sub->seq.lower, sub->seq.upper); | ||
303 | kfree(sub); | ||
304 | subscr_terminate(subscriber); | ||
305 | return; | ||
306 | } | ||
307 | memcpy(&sub->evt.s, s, sizeof(struct tipc_subscr)); | ||
308 | INIT_LIST_HEAD(&sub->subscription_list); | ||
309 | INIT_LIST_HEAD(&sub->nameseq_list); | ||
310 | list_add(&sub->subscription_list, &subscriber->subscription_list); | ||
311 | atomic_inc(&topsrv.subscription_count); | ||
312 | if (sub->timeout != TIPC_WAIT_FOREVER) { | ||
313 | k_init_timer(&sub->timer, | ||
314 | (Handler)subscr_timeout, (unsigned long)sub); | ||
315 | k_start_timer(&sub->timer, sub->timeout); | ||
316 | } | ||
317 | sub->owner = subscriber; | ||
318 | nametbl_subscribe(sub); | ||
319 | } | ||
320 | |||
321 | /** | ||
322 | * subscr_conn_shutdown_event - handle termination request from subscriber | ||
323 | */ | ||
324 | |||
325 | static void subscr_conn_shutdown_event(void *usr_handle, | ||
326 | u32 portref, | ||
327 | struct sk_buff **buf, | ||
328 | unsigned char const *data, | ||
329 | unsigned int size, | ||
330 | int reason) | ||
331 | { | ||
332 | struct subscriber *subscriber; | ||
333 | spinlock_t *subscriber_lock; | ||
334 | |||
335 | subscriber = ref_lock((u32)(unsigned long)usr_handle); | ||
336 | if (subscriber == NULL) | ||
337 | return; | ||
338 | |||
339 | subscriber_lock = subscriber->lock; | ||
340 | subscr_terminate(subscriber); | ||
341 | spin_unlock_bh(subscriber_lock); | ||
342 | } | ||
343 | |||
344 | /** | ||
345 | * subscr_conn_msg_event - handle new subscription request from subscriber | ||
346 | */ | ||
347 | |||
348 | static void subscr_conn_msg_event(void *usr_handle, | ||
349 | u32 port_ref, | ||
350 | struct sk_buff **buf, | ||
351 | const unchar *data, | ||
352 | u32 size) | ||
353 | { | ||
354 | struct subscriber *subscriber; | ||
355 | spinlock_t *subscriber_lock; | ||
356 | |||
357 | subscriber = ref_lock((u32)(unsigned long)usr_handle); | ||
358 | if (subscriber == NULL) | ||
359 | return; | ||
360 | |||
361 | subscriber_lock = subscriber->lock; | ||
362 | if (size != sizeof(struct tipc_subscr)) | ||
363 | subscr_terminate(subscriber); | ||
364 | else | ||
365 | subscr_subscribe((struct tipc_subscr *)data, subscriber); | ||
366 | |||
367 | spin_unlock_bh(subscriber_lock); | ||
368 | } | ||
369 | |||
370 | /** | ||
371 | * subscr_named_msg_event - handle request to establish a new subscriber | ||
372 | */ | ||
373 | |||
374 | static void subscr_named_msg_event(void *usr_handle, | ||
375 | u32 port_ref, | ||
376 | struct sk_buff **buf, | ||
377 | const unchar *data, | ||
378 | u32 size, | ||
379 | u32 importance, | ||
380 | struct tipc_portid const *orig, | ||
381 | struct tipc_name_seq const *dest) | ||
382 | { | ||
383 | struct subscriber *subscriber; | ||
384 | struct iovec msg_sect = {0, 0}; | ||
385 | spinlock_t *subscriber_lock; | ||
386 | |||
387 | dbg("subscr_named_msg_event: orig = %x own = %x,\n", | ||
388 | orig->node, tipc_own_addr); | ||
389 | if (size && (size != sizeof(struct tipc_subscr))) { | ||
390 | warn("Received tipc_subscr of invalid size\n"); | ||
391 | return; | ||
392 | } | ||
393 | |||
394 | /* Create subscriber object */ | ||
395 | |||
396 | subscriber = kmalloc(sizeof(struct subscriber), GFP_ATOMIC); | ||
397 | if (subscriber == NULL) { | ||
398 | warn("Memory squeeze; ignoring subscriber setup\n"); | ||
399 | return; | ||
400 | } | ||
401 | memset(subscriber, 0, sizeof(struct subscriber)); | ||
402 | INIT_LIST_HEAD(&subscriber->subscription_list); | ||
403 | INIT_LIST_HEAD(&subscriber->subscriber_list); | ||
404 | subscriber->ref = ref_acquire(subscriber, &subscriber->lock); | ||
405 | if (subscriber->ref == 0) { | ||
406 | warn("Failed to acquire subscriber reference\n"); | ||
407 | kfree(subscriber); | ||
408 | return; | ||
409 | } | ||
410 | |||
411 | /* Establish a connection to subscriber */ | ||
412 | |||
413 | tipc_createport(topsrv.user_ref, | ||
414 | (void *)(unsigned long)subscriber->ref, | ||
415 | importance, | ||
416 | 0, | ||
417 | 0, | ||
418 | subscr_conn_shutdown_event, | ||
419 | 0, | ||
420 | 0, | ||
421 | subscr_conn_msg_event, | ||
422 | 0, | ||
423 | &subscriber->port_ref); | ||
424 | if (subscriber->port_ref == 0) { | ||
425 | warn("Memory squeeze; failed to create subscription port\n"); | ||
426 | ref_discard(subscriber->ref); | ||
427 | kfree(subscriber); | ||
428 | return; | ||
429 | } | ||
430 | tipc_connect2port(subscriber->port_ref, orig); | ||
431 | |||
432 | |||
433 | /* Add subscriber to topology server's subscriber list */ | ||
434 | |||
435 | ref_lock(subscriber->ref); | ||
436 | spin_lock_bh(&topsrv.lock); | ||
437 | list_add(&subscriber->subscriber_list, &topsrv.subscriber_list); | ||
438 | spin_unlock_bh(&topsrv.lock); | ||
439 | |||
440 | /* | ||
441 | * Subscribe now if message contains a subscription, | ||
442 | * otherwise send an empty response to complete connection handshaking | ||
443 | */ | ||
444 | |||
445 | subscriber_lock = subscriber->lock; | ||
446 | if (size) | ||
447 | subscr_subscribe((struct tipc_subscr *)data, subscriber); | ||
448 | else | ||
449 | tipc_send(subscriber->port_ref, 1, &msg_sect); | ||
450 | |||
451 | spin_unlock_bh(subscriber_lock); | ||
452 | } | ||
453 | |||
454 | int subscr_start(void) | ||
455 | { | ||
456 | struct tipc_name_seq seq = {TIPC_TOP_SRV, TIPC_TOP_SRV, TIPC_TOP_SRV}; | ||
457 | int res = -1; | ||
458 | |||
459 | memset(&topsrv, 0, sizeof (topsrv)); | ||
460 | topsrv.lock = SPIN_LOCK_UNLOCKED; | ||
461 | INIT_LIST_HEAD(&topsrv.subscriber_list); | ||
462 | |||
463 | spin_lock_bh(&topsrv.lock); | ||
464 | res = tipc_attach(&topsrv.user_ref, 0, 0); | ||
465 | if (res) { | ||
466 | spin_unlock_bh(&topsrv.lock); | ||
467 | return res; | ||
468 | } | ||
469 | |||
470 | res = tipc_createport(topsrv.user_ref, | ||
471 | 0, | ||
472 | TIPC_CRITICAL_IMPORTANCE, | ||
473 | 0, | ||
474 | 0, | ||
475 | 0, | ||
476 | 0, | ||
477 | subscr_named_msg_event, | ||
478 | 0, | ||
479 | 0, | ||
480 | &topsrv.setup_port); | ||
481 | if (res) | ||
482 | goto failed; | ||
483 | |||
484 | res = nametbl_publish_rsv(topsrv.setup_port, TIPC_NODE_SCOPE, &seq); | ||
485 | if (res) | ||
486 | goto failed; | ||
487 | |||
488 | spin_unlock_bh(&topsrv.lock); | ||
489 | return 0; | ||
490 | |||
491 | failed: | ||
492 | err("Failed to create subscription service\n"); | ||
493 | tipc_detach(topsrv.user_ref); | ||
494 | topsrv.user_ref = 0; | ||
495 | spin_unlock_bh(&topsrv.lock); | ||
496 | return res; | ||
497 | } | ||
498 | |||
499 | void subscr_stop(void) | ||
500 | { | ||
501 | struct subscriber *subscriber; | ||
502 | struct subscriber *subscriber_temp; | ||
503 | spinlock_t *subscriber_lock; | ||
504 | |||
505 | if (topsrv.user_ref) { | ||
506 | tipc_deleteport(topsrv.setup_port); | ||
507 | list_for_each_entry_safe(subscriber, subscriber_temp, | ||
508 | &topsrv.subscriber_list, | ||
509 | subscriber_list) { | ||
510 | ref_lock(subscriber->ref); | ||
511 | subscriber_lock = subscriber->lock; | ||
512 | subscr_terminate(subscriber); | ||
513 | spin_unlock_bh(subscriber_lock); | ||
514 | } | ||
515 | tipc_detach(topsrv.user_ref); | ||
516 | topsrv.user_ref = 0; | ||
517 | } | ||
518 | } | ||
519 | |||
520 | |||
521 | int tipc_ispublished(struct tipc_name const *name) | ||
522 | { | ||
523 | u32 domain = 0; | ||
524 | |||
525 | return(nametbl_translate(name->type, name->instance,&domain) != 0); | ||
526 | } | ||
527 | |||
diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h new file mode 100644 index 000000000000..ccff4efcb755 --- /dev/null +++ b/net/tipc/subscr.h | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * net/tipc/subscr.h: Include file for TIPC subscription service | ||
3 | * | ||
4 | * Copyright (c) 2003-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_SUBSCR_H | ||
38 | #define _TIPC_SUBSCR_H | ||
39 | |||
40 | /** | ||
41 | * struct subscription - TIPC network topology subscription object | ||
42 | * @seq: name sequence associated with subscription | ||
43 | * @timeout: duration of subscription (in ms) | ||
44 | * @filter: event filtering to be done for subscription | ||
45 | * @evt: template for events generated by subscription | ||
46 | * @subscription_list: adjacent subscriptions in subscriber's subscription list | ||
47 | * @nameseq_list: adjacent subscriptions in name sequence's subscription list | ||
48 | * @timer_ref: reference to timer governing subscription duration (may be NULL) | ||
49 | * @owner: pointer to subscriber object associated with this subscription | ||
50 | */ | ||
51 | |||
52 | struct subscription { | ||
53 | struct tipc_name_seq seq; | ||
54 | u32 timeout; | ||
55 | u32 filter; | ||
56 | struct tipc_event evt; | ||
57 | struct list_head subscription_list; | ||
58 | struct list_head nameseq_list; | ||
59 | struct timer_list timer; | ||
60 | struct subscriber *owner; | ||
61 | }; | ||
62 | |||
63 | int subscr_overlap(struct subscription * sub, | ||
64 | u32 found_lower, | ||
65 | u32 found_upper); | ||
66 | |||
67 | void subscr_report_overlap(struct subscription * sub, | ||
68 | u32 found_lower, | ||
69 | u32 found_upper, | ||
70 | u32 event, | ||
71 | u32 port_ref, | ||
72 | u32 node, | ||
73 | int must_report); | ||
74 | |||
75 | int subscr_start(void); | ||
76 | |||
77 | void subscr_stop(void); | ||
78 | |||
79 | |||
80 | #endif | ||
diff --git a/net/tipc/user_reg.c b/net/tipc/user_reg.c new file mode 100644 index 000000000000..35ec7dc8211d --- /dev/null +++ b/net/tipc/user_reg.c | |||
@@ -0,0 +1,265 @@ | |||
1 | /* | ||
2 | * net/tipc/user_reg.c: TIPC user registry code | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2004-2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "user_reg.h" | ||
39 | |||
40 | /* | ||
41 | * TIPC user registry keeps track of users of the tipc_port interface. | ||
42 | * | ||
43 | * The registry utilizes an array of "TIPC user" entries; | ||
44 | * a user's ID is the index of their associated array entry. | ||
45 | * Array entry 0 is not used, so userid 0 is not valid; | ||
46 | * TIPC sometimes uses this value to denote an anonymous user. | ||
47 | * The list of free entries is initially chained from last entry to entry 1. | ||
48 | */ | ||
49 | |||
50 | /** | ||
51 | * struct tipc_user - registered TIPC user info | ||
52 | * @next: index of next free registry entry (or -1 for an allocated entry) | ||
53 | * @callback: ptr to routine to call when TIPC mode changes (NULL if none) | ||
54 | * @usr_handle: user-defined value passed to callback routine | ||
55 | * @ports: list of user ports owned by the user | ||
56 | */ | ||
57 | |||
58 | struct tipc_user { | ||
59 | int next; | ||
60 | tipc_mode_event callback; | ||
61 | void *usr_handle; | ||
62 | struct list_head ports; | ||
63 | }; | ||
64 | |||
65 | #define MAX_USERID 64 | ||
66 | #define USER_LIST_SIZE ((MAX_USERID + 1) * sizeof(struct tipc_user)) | ||
67 | |||
68 | static struct tipc_user *users = 0; | ||
69 | static u32 next_free_user = MAX_USERID + 1; | ||
70 | static spinlock_t reg_lock = SPIN_LOCK_UNLOCKED; | ||
71 | |||
72 | /** | ||
73 | * reg_init - create TIPC user registry (but don't activate it) | ||
74 | * | ||
75 | * If registry has been pre-initialized it is left "as is". | ||
76 | * NOTE: This routine may be called when TIPC is inactive. | ||
77 | */ | ||
78 | |||
79 | static int reg_init(void) | ||
80 | { | ||
81 | u32 i; | ||
82 | |||
83 | spin_lock_bh(®_lock); | ||
84 | if (!users) { | ||
85 | users = (struct tipc_user *)kmalloc(USER_LIST_SIZE, GFP_ATOMIC); | ||
86 | if (users) { | ||
87 | memset(users, 0, USER_LIST_SIZE); | ||
88 | for (i = 1; i <= MAX_USERID; i++) { | ||
89 | users[i].next = i - 1; | ||
90 | } | ||
91 | next_free_user = MAX_USERID; | ||
92 | } | ||
93 | } | ||
94 | spin_unlock_bh(®_lock); | ||
95 | return users ? TIPC_OK : -ENOMEM; | ||
96 | } | ||
97 | |||
98 | /** | ||
99 | * reg_callback - inform TIPC user about current operating mode | ||
100 | */ | ||
101 | |||
102 | static void reg_callback(struct tipc_user *user_ptr) | ||
103 | { | ||
104 | tipc_mode_event cb; | ||
105 | void *arg; | ||
106 | |||
107 | spin_lock_bh(®_lock); | ||
108 | cb = user_ptr->callback; | ||
109 | arg = user_ptr->usr_handle; | ||
110 | spin_unlock_bh(®_lock); | ||
111 | |||
112 | if (cb) | ||
113 | cb(arg, tipc_mode, tipc_own_addr); | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * reg_start - activate TIPC user registry | ||
118 | */ | ||
119 | |||
120 | int reg_start(void) | ||
121 | { | ||
122 | u32 u; | ||
123 | int res; | ||
124 | |||
125 | if ((res = reg_init())) | ||
126 | return res; | ||
127 | |||
128 | for (u = 1; u <= MAX_USERID; u++) { | ||
129 | if (users[u].callback) | ||
130 | k_signal((Handler)reg_callback, | ||
131 | (unsigned long)&users[u]); | ||
132 | } | ||
133 | return TIPC_OK; | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * reg_stop - shut down & delete TIPC user registry | ||
138 | */ | ||
139 | |||
140 | void reg_stop(void) | ||
141 | { | ||
142 | int id; | ||
143 | |||
144 | if (!users) | ||
145 | return; | ||
146 | |||
147 | for (id = 1; id <= MAX_USERID; id++) { | ||
148 | if (users[id].callback) | ||
149 | reg_callback(&users[id]); | ||
150 | } | ||
151 | kfree(users); | ||
152 | users = 0; | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * tipc_attach - register a TIPC user | ||
157 | * | ||
158 | * NOTE: This routine may be called when TIPC is inactive. | ||
159 | */ | ||
160 | |||
161 | int tipc_attach(u32 *userid, tipc_mode_event cb, void *usr_handle) | ||
162 | { | ||
163 | struct tipc_user *user_ptr; | ||
164 | |||
165 | if ((tipc_mode == TIPC_NOT_RUNNING) && !cb) | ||
166 | return -ENOPROTOOPT; | ||
167 | if (!users) | ||
168 | reg_init(); | ||
169 | |||
170 | spin_lock_bh(®_lock); | ||
171 | if (!next_free_user) { | ||
172 | spin_unlock_bh(®_lock); | ||
173 | return -EBUSY; | ||
174 | } | ||
175 | user_ptr = &users[next_free_user]; | ||
176 | *userid = next_free_user; | ||
177 | next_free_user = user_ptr->next; | ||
178 | user_ptr->next = -1; | ||
179 | spin_unlock_bh(®_lock); | ||
180 | |||
181 | user_ptr->callback = cb; | ||
182 | user_ptr->usr_handle = usr_handle; | ||
183 | INIT_LIST_HEAD(&user_ptr->ports); | ||
184 | atomic_inc(&tipc_user_count); | ||
185 | |||
186 | if (cb && (tipc_mode != TIPC_NOT_RUNNING)) | ||
187 | k_signal((Handler)reg_callback, (unsigned long)user_ptr); | ||
188 | return TIPC_OK; | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * tipc_detach - deregister a TIPC user | ||
193 | */ | ||
194 | |||
195 | void tipc_detach(u32 userid) | ||
196 | { | ||
197 | struct tipc_user *user_ptr; | ||
198 | struct list_head ports_temp; | ||
199 | struct user_port *up_ptr, *temp_up_ptr; | ||
200 | |||
201 | if ((userid == 0) || (userid > MAX_USERID)) | ||
202 | return; | ||
203 | |||
204 | spin_lock_bh(®_lock); | ||
205 | if ((!users) || (users[userid].next >= 0)) { | ||
206 | spin_unlock_bh(®_lock); | ||
207 | return; | ||
208 | } | ||
209 | |||
210 | user_ptr = &users[userid]; | ||
211 | user_ptr->callback = NULL; | ||
212 | INIT_LIST_HEAD(&ports_temp); | ||
213 | list_splice(&user_ptr->ports, &ports_temp); | ||
214 | user_ptr->next = next_free_user; | ||
215 | next_free_user = userid; | ||
216 | spin_unlock_bh(®_lock); | ||
217 | |||
218 | atomic_dec(&tipc_user_count); | ||
219 | |||
220 | list_for_each_entry_safe(up_ptr, temp_up_ptr, &ports_temp, uport_list) { | ||
221 | tipc_deleteport(up_ptr->ref); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | /** | ||
226 | * reg_add_port - register a user's driver port | ||
227 | */ | ||
228 | |||
229 | int reg_add_port(struct user_port *up_ptr) | ||
230 | { | ||
231 | struct tipc_user *user_ptr; | ||
232 | |||
233 | if (up_ptr->user_ref == 0) | ||
234 | return TIPC_OK; | ||
235 | if (up_ptr->user_ref > MAX_USERID) | ||
236 | return -EINVAL; | ||
237 | if ((tipc_mode == TIPC_NOT_RUNNING) || !users ) | ||
238 | return -ENOPROTOOPT; | ||
239 | |||
240 | spin_lock_bh(®_lock); | ||
241 | user_ptr = &users[up_ptr->user_ref]; | ||
242 | list_add(&up_ptr->uport_list, &user_ptr->ports); | ||
243 | spin_unlock_bh(®_lock); | ||
244 | return TIPC_OK; | ||
245 | } | ||
246 | |||
247 | /** | ||
248 | * reg_remove_port - deregister a user's driver port | ||
249 | */ | ||
250 | |||
251 | int reg_remove_port(struct user_port *up_ptr) | ||
252 | { | ||
253 | if (up_ptr->user_ref == 0) | ||
254 | return TIPC_OK; | ||
255 | if (up_ptr->user_ref > MAX_USERID) | ||
256 | return -EINVAL; | ||
257 | if (!users ) | ||
258 | return -ENOPROTOOPT; | ||
259 | |||
260 | spin_lock_bh(®_lock); | ||
261 | list_del_init(&up_ptr->uport_list); | ||
262 | spin_unlock_bh(®_lock); | ||
263 | return TIPC_OK; | ||
264 | } | ||
265 | |||
diff --git a/net/tipc/user_reg.h b/net/tipc/user_reg.h new file mode 100644 index 000000000000..122ca9be3671 --- /dev/null +++ b/net/tipc/user_reg.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * net/tipc/user_reg.h: Include file for TIPC user registry code | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_USER_REG_H | ||
38 | #define _TIPC_USER_REG_H | ||
39 | |||
40 | #include "port.h" | ||
41 | |||
42 | int reg_start(void); | ||
43 | void reg_stop(void); | ||
44 | |||
45 | int reg_add_port(struct user_port *up_ptr); | ||
46 | int reg_remove_port(struct user_port *up_ptr); | ||
47 | |||
48 | #endif | ||
diff --git a/net/tipc/zone.c b/net/tipc/zone.c new file mode 100644 index 000000000000..4eaef662d568 --- /dev/null +++ b/net/tipc/zone.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * net/tipc/zone.c: TIPC zone management routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #include "core.h" | ||
38 | #include "zone.h" | ||
39 | #include "net.h" | ||
40 | #include "addr.h" | ||
41 | #include "node_subscr.h" | ||
42 | #include "cluster.h" | ||
43 | #include "node.h" | ||
44 | |||
45 | struct _zone *zone_create(u32 addr) | ||
46 | { | ||
47 | struct _zone *z_ptr = 0; | ||
48 | u32 z_num; | ||
49 | |||
50 | if (!addr_domain_valid(addr)) | ||
51 | return 0; | ||
52 | |||
53 | z_ptr = (struct _zone *)kmalloc(sizeof(*z_ptr), GFP_ATOMIC); | ||
54 | if (z_ptr != NULL) { | ||
55 | memset(z_ptr, 0, sizeof(*z_ptr)); | ||
56 | z_num = tipc_zone(addr); | ||
57 | z_ptr->addr = tipc_addr(z_num, 0, 0); | ||
58 | net.zones[z_num] = z_ptr; | ||
59 | } | ||
60 | return z_ptr; | ||
61 | } | ||
62 | |||
63 | void zone_delete(struct _zone *z_ptr) | ||
64 | { | ||
65 | u32 c_num; | ||
66 | |||
67 | if (!z_ptr) | ||
68 | return; | ||
69 | for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { | ||
70 | cluster_delete(z_ptr->clusters[c_num]); | ||
71 | } | ||
72 | kfree(z_ptr); | ||
73 | } | ||
74 | |||
75 | void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr) | ||
76 | { | ||
77 | u32 c_num = tipc_cluster(c_ptr->addr); | ||
78 | |||
79 | assert(c_ptr->addr); | ||
80 | assert(c_num <= tipc_max_clusters); | ||
81 | assert(z_ptr->clusters[c_num] == 0); | ||
82 | z_ptr->clusters[c_num] = c_ptr; | ||
83 | } | ||
84 | |||
85 | void zone_remove_as_router(struct _zone *z_ptr, u32 router) | ||
86 | { | ||
87 | u32 c_num; | ||
88 | |||
89 | for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { | ||
90 | if (z_ptr->clusters[c_num]) { | ||
91 | cluster_remove_as_router(z_ptr->clusters[c_num], | ||
92 | router); | ||
93 | } | ||
94 | } | ||
95 | } | ||
96 | |||
97 | void zone_send_external_routes(struct _zone *z_ptr, u32 dest) | ||
98 | { | ||
99 | u32 c_num; | ||
100 | |||
101 | for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { | ||
102 | if (z_ptr->clusters[c_num]) { | ||
103 | if (in_own_cluster(z_ptr->addr)) | ||
104 | continue; | ||
105 | cluster_send_ext_routes(z_ptr->clusters[c_num], dest); | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | |||
110 | struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref) | ||
111 | { | ||
112 | struct cluster *c_ptr; | ||
113 | struct node *n_ptr; | ||
114 | u32 c_num; | ||
115 | |||
116 | if (!z_ptr) | ||
117 | return 0; | ||
118 | c_ptr = z_ptr->clusters[tipc_cluster(addr)]; | ||
119 | if (!c_ptr) | ||
120 | return 0; | ||
121 | n_ptr = cluster_select_node(c_ptr, ref); | ||
122 | if (n_ptr) | ||
123 | return n_ptr; | ||
124 | |||
125 | /* Links to any other clusters within this zone ? */ | ||
126 | for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { | ||
127 | c_ptr = z_ptr->clusters[c_num]; | ||
128 | if (!c_ptr) | ||
129 | return 0; | ||
130 | n_ptr = cluster_select_node(c_ptr, ref); | ||
131 | if (n_ptr) | ||
132 | return n_ptr; | ||
133 | } | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref) | ||
138 | { | ||
139 | struct cluster *c_ptr; | ||
140 | u32 c_num; | ||
141 | u32 router; | ||
142 | |||
143 | if (!z_ptr) | ||
144 | return 0; | ||
145 | c_ptr = z_ptr->clusters[tipc_cluster(addr)]; | ||
146 | router = c_ptr ? cluster_select_router(c_ptr, ref) : 0; | ||
147 | if (router) | ||
148 | return router; | ||
149 | |||
150 | /* Links to any other clusters within the zone? */ | ||
151 | for (c_num = 1; c_num <= tipc_max_clusters; c_num++) { | ||
152 | c_ptr = z_ptr->clusters[c_num]; | ||
153 | router = c_ptr ? cluster_select_router(c_ptr, ref) : 0; | ||
154 | if (router) | ||
155 | return router; | ||
156 | } | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | |||
161 | u32 zone_next_node(u32 addr) | ||
162 | { | ||
163 | struct cluster *c_ptr = cluster_find(addr); | ||
164 | |||
165 | if (c_ptr) | ||
166 | return cluster_next_node(c_ptr, addr); | ||
167 | return 0; | ||
168 | } | ||
169 | |||
diff --git a/net/tipc/zone.h b/net/tipc/zone.h new file mode 100644 index 000000000000..4326f78d8292 --- /dev/null +++ b/net/tipc/zone.h | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * net/tipc/zone.h: Include file for TIPC zone management routines | ||
3 | * | ||
4 | * Copyright (c) 2000-2006, Ericsson AB | ||
5 | * Copyright (c) 2005, Wind River Systems | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions are met: | ||
10 | * | ||
11 | * 1. Redistributions of source code must retain the above copyright | ||
12 | * notice, this list of conditions and the following disclaimer. | ||
13 | * 2. Redistributions in binary form must reproduce the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer in the | ||
15 | * documentation and/or other materials provided with the distribution. | ||
16 | * 3. Neither the names of the copyright holders nor the names of its | ||
17 | * contributors may be used to endorse or promote products derived from | ||
18 | * this software without specific prior written permission. | ||
19 | * | ||
20 | * Alternatively, this software may be distributed under the terms of the | ||
21 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
22 | * Software Foundation. | ||
23 | * | ||
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
28 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
29 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
34 | * POSSIBILITY OF SUCH DAMAGE. | ||
35 | */ | ||
36 | |||
37 | #ifndef _TIPC_ZONE_H | ||
38 | #define _TIPC_ZONE_H | ||
39 | |||
40 | #include "node_subscr.h" | ||
41 | #include "net.h" | ||
42 | |||
43 | |||
44 | /** | ||
45 | * struct _zone - TIPC zone structure | ||
46 | * @addr: network address of zone | ||
47 | * @clusters: array of pointers to all clusters within zone | ||
48 | * @links: (used for inter-zone communication) | ||
49 | */ | ||
50 | |||
51 | struct _zone { | ||
52 | u32 addr; | ||
53 | struct cluster *clusters[2]; /* currently limited to just 1 cluster */ | ||
54 | u32 links; | ||
55 | }; | ||
56 | |||
57 | struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref); | ||
58 | u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref); | ||
59 | void zone_remove_as_router(struct _zone *z_ptr, u32 router); | ||
60 | void zone_send_external_routes(struct _zone *z_ptr, u32 dest); | ||
61 | struct _zone *zone_create(u32 addr); | ||
62 | void zone_delete(struct _zone *z_ptr); | ||
63 | void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr); | ||
64 | u32 zone_next_node(u32 addr); | ||
65 | |||
66 | static inline struct _zone *zone_find(u32 addr) | ||
67 | { | ||
68 | return net.zones[tipc_zone(addr)]; | ||
69 | } | ||
70 | |||
71 | #endif | ||
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 12e4fb72bf0f..53d6c7bbf564 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -494,8 +494,7 @@ static inline void avc_print_ipv6_addr(struct audit_buffer *ab, | |||
494 | char *name1, char *name2) | 494 | char *name1, char *name2) |
495 | { | 495 | { |
496 | if (!ipv6_addr_any(addr)) | 496 | if (!ipv6_addr_any(addr)) |
497 | audit_log_format(ab, " %s=%04x:%04x:%04x:%04x:%04x:" | 497 | audit_log_format(ab, " %s=" NIP6_FMT, name1, NIP6(*addr)); |
498 | "%04x:%04x:%04x", name1, NIP6(*addr)); | ||
499 | if (port) | 498 | if (port) |
500 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 499 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); |
501 | } | 500 | } |
@@ -504,7 +503,7 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr, | |||
504 | __be16 port, char *name1, char *name2) | 503 | __be16 port, char *name1, char *name2) |
505 | { | 504 | { |
506 | if (addr) | 505 | if (addr) |
507 | audit_log_format(ab, " %s=%d.%d.%d.%d", name1, NIPQUAD(addr)); | 506 | audit_log_format(ab, " %s=" NIPQUAD_FMT, name1, NIPQUAD(addr)); |
508 | if (port) | 507 | if (port) |
509 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 508 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); |
510 | } | 509 | } |