aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-01-13 18:28:10 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-13 18:28:10 -0500
commit69eebed240b32377b9034551f1b8c4ae2774ceb6 (patch)
tree6955dbf8110c6f03d64747fe55e1feb1d81e951f
parent67daf5f11f06b9b15f8320de1d237ccc2e74fe43 (diff)
parentdca80b962a811a0454d779ab6250b59446a8c86c (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
-rw-r--r--MAINTAINERS13
-rw-r--r--include/linux/kernel.h2
-rw-r--r--include/linux/netfilter/nf_conntrack_common.h3
-rw-r--r--include/linux/netfilter/x_tables.h224
-rw-r--r--include/linux/netfilter/xt_CLASSIFY.h8
-rw-r--r--include/linux/netfilter/xt_CONNMARK.h25
-rw-r--r--include/linux/netfilter/xt_MARK.h21
-rw-r--r--include/linux/netfilter/xt_NFQUEUE.h16
-rw-r--r--include/linux/netfilter/xt_comment.h10
-rw-r--r--include/linux/netfilter/xt_connbytes.h25
-rw-r--r--include/linux/netfilter/xt_connmark.h18
-rw-r--r--include/linux/netfilter/xt_conntrack.h63
-rw-r--r--include/linux/netfilter/xt_dccp.h23
-rw-r--r--include/linux/netfilter/xt_helper.h8
-rw-r--r--include/linux/netfilter/xt_length.h9
-rw-r--r--include/linux/netfilter/xt_limit.h21
-rw-r--r--include/linux/netfilter/xt_mac.h8
-rw-r--r--include/linux/netfilter/xt_mark.h9
-rw-r--r--include/linux/netfilter/xt_physdev.h24
-rw-r--r--include/linux/netfilter/xt_pkttype.h8
-rw-r--r--include/linux/netfilter/xt_realm.h10
-rw-r--r--include/linux/netfilter/xt_sctp.h107
-rw-r--r--include/linux/netfilter/xt_state.h13
-rw-r--r--include/linux/netfilter/xt_string.h18
-rw-r--r--include/linux/netfilter/xt_tcpmss.h9
-rw-r--r--include/linux/netfilter/xt_tcpudp.h36
-rw-r--r--include/linux/netfilter_arp/arp_tables.h123
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack.h3
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h217
-rw-r--r--include/linux/netfilter_ipv4/ipt_CLASSIFY.h5
-rw-r--r--include/linux/netfilter_ipv4/ipt_CONNMARK.h16
-rw-r--r--include/linux/netfilter_ipv4/ipt_MARK.h22
-rw-r--r--include/linux/netfilter_ipv4/ipt_NFQUEUE.h8
-rw-r--r--include/linux/netfilter_ipv4/ipt_comment.h8
-rw-r--r--include/linux/netfilter_ipv4/ipt_connbytes.h31
-rw-r--r--include/linux/netfilter_ipv4/ipt_connmark.h15
-rw-r--r--include/linux/netfilter_ipv4/ipt_conntrack.h66
-rw-r--r--include/linux/netfilter_ipv4/ipt_dccp.h22
-rw-r--r--include/linux/netfilter_ipv4/ipt_helper.h7
-rw-r--r--include/linux/netfilter_ipv4/ipt_length.h6
-rw-r--r--include/linux/netfilter_ipv4/ipt_limit.h19
-rw-r--r--include/linux/netfilter_ipv4/ipt_mac.h7
-rw-r--r--include/linux/netfilter_ipv4/ipt_mark.h8
-rw-r--r--include/linux/netfilter_ipv4/ipt_physdev.h27
-rw-r--r--include/linux/netfilter_ipv4/ipt_pkttype.h7
-rw-r--r--include/linux/netfilter_ipv4/ipt_realm.h7
-rw-r--r--include/linux/netfilter_ipv4/ipt_state.h16
-rw-r--r--include/linux/netfilter_ipv4/ipt_string.h16
-rw-r--r--include/linux/netfilter_ipv4/ipt_tcpmss.h6
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h208
-rw-r--r--include/linux/netfilter_ipv6/ip6t_MARK.h9
-rw-r--r--include/linux/netfilter_ipv6/ip6t_length.h6
-rw-r--r--include/linux/netfilter_ipv6/ip6t_limit.h21
-rw-r--r--include/linux/netfilter_ipv6/ip6t_mac.h9
-rw-r--r--include/linux/netfilter_ipv6/ip6t_mark.h8
-rw-r--r--include/linux/netfilter_ipv6/ip6t_physdev.h27
-rw-r--r--include/linux/socket.h3
-rw-r--r--include/linux/tipc.h212
-rw-r--r--include/linux/tipc_config.h407
-rw-r--r--include/net/genetlink.h1
-rw-r--r--include/net/netfilter/ipv4/nf_conntrack_ipv4.h3
-rw-r--r--include/net/netfilter/nf_conntrack.h3
-rw-r--r--include/net/netfilter/nf_conntrack_tuple.h2
-rw-r--r--include/net/sctp/sctp.h4
-rw-r--r--include/net/tipc/tipc.h257
-rw-r--r--include/net/tipc/tipc_bearer.h121
-rw-r--r--include/net/tipc/tipc_msg.h223
-rw-r--r--include/net/tipc/tipc_port.h108
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile1
-rw-r--r--net/bridge/netfilter/ebt_log.c1
-rw-r--r--net/core/filter.c10
-rw-r--r--net/ipv4/netfilter/Kconfig250
-rw-r--r--net/ipv4/netfilter/Makefile21
-rw-r--r--net/ipv4/netfilter/arp_tables.c444
-rw-r--r--net/ipv4/netfilter/arpt_mangle.c7
-rw-r--r--net/ipv4/netfilter/arptable_filter.c1
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c4
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c5
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c2
-rw-r--r--net/ipv4/netfilter/ip_tables.c842
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c3
-rw-r--r--net/ipv4/netfilter/ipt_DSCP.c2
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c3
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c2
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c2
-rw-r--r--net/ipv4/netfilter/ipt_NETMAP.c2
-rw-r--r--net/ipv4/netfilter/ipt_NFQUEUE.c70
-rw-r--r--net/ipv4/netfilter/ipt_REDIRECT.c2
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c3
-rw-r--r--net/ipv4/netfilter/ipt_SAME.c2
-rw-r--r--net/ipv4/netfilter/ipt_TCPMSS.c3
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c2
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c2
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c2
-rw-r--r--net/ipv4/netfilter/ipt_addrtype.c4
-rw-r--r--net/ipv4/netfilter/ipt_ah.c6
-rw-r--r--net/ipv4/netfilter/ipt_dscp.c4
-rw-r--r--net/ipv4/netfilter/ipt_ecn.c5
-rw-r--r--net/ipv4/netfilter/ipt_esp.c6
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c3
-rw-r--r--net/ipv4/netfilter/ipt_iprange.c4
-rw-r--r--net/ipv4/netfilter/ipt_length.c64
-rw-r--r--net/ipv4/netfilter/ipt_multiport.c10
-rw-r--r--net/ipv4/netfilter/ipt_owner.c3
-rw-r--r--net/ipv4/netfilter/ipt_physdev.c135
-rw-r--r--net/ipv4/netfilter/ipt_recent.c6
-rw-r--r--net/ipv4/netfilter/ipt_tos.c3
-rw-r--r--net/ipv4/netfilter/ipt_ttl.c4
-rw-r--r--net/ipv4/netfilter/iptable_filter.c3
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c1
-rw-r--r--net/ipv4/netfilter/iptable_raw.c3
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c7
-rw-r--r--net/ipv4/xfrm4_state.c15
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/ah6.c3
-rw-r--r--net/ipv6/anycast.c4
-rw-r--r--net/ipv6/esp6.c3
-rw-r--r--net/ipv6/icmp.c2
-rw-r--r--net/ipv6/ip6_flowlabel.c8
-rw-r--r--net/ipv6/ipcomp6.c3
-rw-r--r--net/ipv6/mcast.c9
-rw-r--r--net/ipv6/ndisc.c2
-rw-r--r--net/ipv6/netfilter/Kconfig72
-rw-r--r--net/ipv6/netfilter/Makefile6
-rw-r--r--net/ipv6/netfilter/ip6_tables.c828
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c2
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c7
-rw-r--r--net/ipv6/netfilter/ip6t_MARK.c81
-rw-r--r--net/ipv6/netfilter/ip6t_NFQUEUE.c70
-rw-r--r--net/ipv6/netfilter/ip6t_REJECT.c3
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c2
-rw-r--r--net/ipv6/netfilter/ip6t_dst.c2
-rw-r--r--net/ipv6/netfilter/ip6t_esp.c2
-rw-r--r--net/ipv6/netfilter/ip6t_eui64.c2
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c2
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c2
-rw-r--r--net/ipv6/netfilter/ip6t_hl.c2
-rw-r--r--net/ipv6/netfilter/ip6t_ipv6header.c2
-rw-r--r--net/ipv6/netfilter/ip6t_length.c66
-rw-r--r--net/ipv6/netfilter/ip6t_limit.c147
-rw-r--r--net/ipv6/netfilter/ip6t_mac.c81
-rw-r--r--net/ipv6/netfilter/ip6t_mark.c66
-rw-r--r--net/ipv6/netfilter/ip6t_multiport.c3
-rw-r--r--net/ipv6/netfilter/ip6t_owner.c2
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c2
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c1
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c1
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c5
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c10
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c45
-rw-r--r--net/ipv6/xfrm6_state.c17
-rw-r--r--net/ipv6/xfrm6_tunnel.c8
-rw-r--r--net/netfilter/Kconfig258
-rw-r--r--net/netfilter/Makefile37
-rw-r--r--net/netfilter/nf_conntrack_ftp.c4
-rw-r--r--net/netfilter/nf_conntrack_standalone.c4
-rw-r--r--net/netfilter/x_tables.c624
-rw-r--r--net/netfilter/xt_CLASSIFY.c (renamed from net/ipv4/netfilter/ipt_CLASSIFY.c)41
-rw-r--r--net/netfilter/xt_CONNMARK.c (renamed from net/ipv4/netfilter/ipt_CONNMARK.c)51
-rw-r--r--net/netfilter/xt_MARK.c (renamed from net/ipv4/netfilter/ipt_MARK.c)79
-rw-r--r--net/netfilter/xt_NFQUEUE.c107
-rw-r--r--net/netfilter/xt_NOTRACK.c (renamed from net/ipv4/netfilter/ipt_NOTRACK.c)38
-rw-r--r--net/netfilter/xt_comment.c (renamed from net/ipv4/netfilter/ipt_comment.c)35
-rw-r--r--net/netfilter/xt_connbytes.c (renamed from net/ipv4/netfilter/ipt_connbytes.c)73
-rw-r--r--net/netfilter/xt_connmark.c (renamed from net/ipv4/netfilter/ipt_connmark.c)41
-rw-r--r--net/netfilter/xt_conntrack.c (renamed from net/ipv4/netfilter/ipt_conntrack.c)110
-rw-r--r--net/netfilter/xt_dccp.c (renamed from net/ipv4/netfilter/ipt_dccp.c)105
-rw-r--r--net/netfilter/xt_helper.c (renamed from net/ipv4/netfilter/ipt_helper.c)56
-rw-r--r--net/netfilter/xt_length.c98
-rw-r--r--net/netfilter/xt_limit.c (renamed from net/ipv4/netfilter/ipt_limit.c)48
-rw-r--r--net/netfilter/xt_mac.c (renamed from net/ipv4/netfilter/ipt_mac.c)38
-rw-r--r--net/netfilter/xt_mark.c (renamed from net/ipv4/netfilter/ipt_mark.c)38
-rw-r--r--net/netfilter/xt_physdev.c (renamed from net/ipv6/netfilter/ip6t_physdev.c)82
-rw-r--r--net/netfilter/xt_pkttype.c (renamed from net/ipv4/netfilter/ipt_pkttype.c)46
-rw-r--r--net/netfilter/xt_realm.c (renamed from net/ipv4/netfilter/ipt_realm.c)25
-rw-r--r--net/netfilter/xt_sctp.c (renamed from net/ipv4/netfilter/ipt_sctp.c)109
-rw-r--r--net/netfilter/xt_state.c (renamed from net/ipv4/netfilter/ipt_state.c)50
-rw-r--r--net/netfilter/xt_string.c (renamed from net/ipv4/netfilter/ipt_string.c)40
-rw-r--r--net/netfilter/xt_tcpmss.c (renamed from net/ipv4/netfilter/ipt_tcpmss.c)69
-rw-r--r--net/netfilter/xt_tcpudp.c333
-rw-r--r--net/netlink/genetlink.c7
-rw-r--r--net/sched/Kconfig2
-rw-r--r--net/sched/act_ipt.c2
-rw-r--r--net/sctp/ipv6.c24
-rw-r--r--net/sctp/sm_statefuns.c4
-rw-r--r--net/tipc/Kconfig112
-rw-r--r--net/tipc/Makefile13
-rw-r--r--net/tipc/addr.c94
-rw-r--r--net/tipc/addr.h128
-rw-r--r--net/tipc/bcast.c806
-rw-r--r--net/tipc/bcast.h223
-rw-r--r--net/tipc/bearer.c692
-rw-r--r--net/tipc/bearer.h172
-rw-r--r--net/tipc/cluster.c576
-rw-r--r--net/tipc/cluster.h92
-rw-r--r--net/tipc/config.c718
-rw-r--r--net/tipc/config.h80
-rw-r--r--net/tipc/core.c285
-rw-r--r--net/tipc/core.h316
-rw-r--r--net/tipc/dbg.c395
-rw-r--r--net/tipc/dbg.h59
-rw-r--r--net/tipc/discover.c318
-rw-r--r--net/tipc/discover.h58
-rw-r--r--net/tipc/eth_media.c299
-rw-r--r--net/tipc/handler.c132
-rw-r--r--net/tipc/link.c3167
-rw-r--r--net/tipc/link.h296
-rw-r--r--net/tipc/msg.c334
-rw-r--r--net/tipc/msg.h818
-rw-r--r--net/tipc/name_distr.c309
-rw-r--r--net/tipc/name_distr.h48
-rw-r--r--net/tipc/name_table.c1079
-rw-r--r--net/tipc/name_table.h108
-rw-r--r--net/tipc/net.c311
-rw-r--r--net/tipc/net.h66
-rw-r--r--net/tipc/netlink.c112
-rw-r--r--net/tipc/node.c679
-rw-r--r--net/tipc/node.h144
-rw-r--r--net/tipc/node_subscr.c79
-rw-r--r--net/tipc/node_subscr.h63
-rw-r--r--net/tipc/port.c1708
-rw-r--r--net/tipc/port.h209
-rw-r--r--net/tipc/ref.c189
-rw-r--r--net/tipc/ref.h131
-rw-r--r--net/tipc/socket.c1726
-rw-r--r--net/tipc/subscr.c527
-rw-r--r--net/tipc/subscr.h80
-rw-r--r--net/tipc/user_reg.c265
-rw-r--r--net/tipc/user_reg.h48
-rw-r--r--net/tipc/zone.c169
-rw-r--r--net/tipc/zone.h71
-rw-r--r--security/selinux/avc.c5
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
2519M: roms@lpg.ticalc.org 2519M: roms@lpg.ticalc.org
2520S: Maintained 2520S: Maintained
2521 2521
2522TIPC NETWORK LAYER
2523P: Per Liden
2524M: per.liden@nospam.ericsson.com
2525P: Jon Maloy
2526M: jon.maloy@nospam.ericsson.com
2527P: Allan Stephens
2528M: allan.stephens@nospam.windriver.com
2529L: tipc-discussion@lists.sourceforge.net
2530W: http://tipc.sourceforge.net/
2531W: http://tipc.cslab.ericsson.net/
2532T: git tipc.cslab.ericsson.net:/pub/git/tipc.git
2533S: Maintained
2534
2522TLAN NETWORK DRIVER 2535TLAN NETWORK DRIVER
2523P: Samuel Chessman 2536P: Samuel Chessman
2524M: chessman@tux.org 2537M: 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. */
158extern 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. */
9struct 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
48struct xt_counters
49{
50 u_int64_t pcnt, bcnt; /* Packet and byte counters */
51};
52
53/* The argument to IPT_SO_ADD_COUNTERS. */
54struct 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
75struct 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. */
112struct 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... */
148struct 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 */
174struct 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
191extern int xt_register_target(int af, struct xt_target *target);
192extern void xt_unregister_target(int af, struct xt_target *target);
193extern int xt_register_match(int af, struct xt_match *target);
194extern void xt_unregister_match(int af, struct xt_match *target);
195
196extern int xt_register_table(struct xt_table *table,
197 struct xt_table_info *bootstrap,
198 struct xt_table_info *newinfo);
199extern void *xt_unregister_table(struct xt_table *table);
200
201extern 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
206extern struct xt_match *xt_find_match(int af, const char *name, u8 revision);
207extern struct xt_target *xt_find_target(int af, const char *name, u8 revision);
208extern struct xt_target *xt_request_find_target(int af, const char *name,
209 u8 revision);
210extern int xt_find_revision(int af, const char *name, u8 revision, int target,
211 int *err);
212
213extern struct xt_table *xt_find_table_lock(int af, const char *name);
214extern void xt_table_unlock(struct xt_table *t);
215
216extern int xt_proto_init(int af);
217extern void xt_proto_fini(int af);
218
219extern struct xt_table_info *xt_alloc_table_info(unsigned int size);
220extern 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
4struct 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
13enum {
14 XT_CONNMARK_SET = 0,
15 XT_CONNMARK_SAVE,
16 XT_CONNMARK_RESTORE
17};
18
19struct 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 */
5struct xt_mark_target_info {
6 unsigned long mark;
7};
8
9/* Version 1 */
10enum {
11 XT_MARK_SET=0,
12 XT_MARK_AND,
13 XT_MARK_OR,
14};
15
16struct 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 */
12struct 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
6struct 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
4enum xt_connbytes_what {
5 XT_CONNBYTES_PKTS,
6 XT_CONNBYTES_BYTES,
7 XT_CONNBYTES_AVGPKT,
8};
9
10enum xt_connbytes_direction {
11 XT_CONNBYTES_DIR_ORIGINAL,
12 XT_CONNBYTES_DIR_REPLY,
13 XT_CONNBYTES_DIR_BOTH,
14};
15
16struct 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
13struct 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. */
29struct 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
49struct 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
11struct 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
4struct 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
4struct 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. */
9struct 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
4struct 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
4struct 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
15struct 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
4struct 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
4struct 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
13struct 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
21struct 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
9struct 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
7struct 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
4struct 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 */
5struct 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 */
23struct 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
94struct 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 */
163struct arpt_getinfo 163struct 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. */
218struct 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. */
230struct arpt_get_entries 221struct 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. */
244struct 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 */
257static __inline__ struct arpt_entry_target *arpt_get_target(struct arpt_entry *e) 239static __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)
285struct 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
318extern int arpt_register_target(struct arpt_target *target);
319extern void arpt_unregister_target(struct arpt_target *target);
320
321/* Furniture shopping... */
322struct 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
342extern int arpt_register_table(struct arpt_table *table, 269extern 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. */
203extern void need_ip_conntrack(void);
204
205extern int invert_tuplepr(struct ip_conntrack_tuple *inverse, 202extern 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. */
32struct ipt_ip { 38struct ipt_ip {
@@ -102,10 +108,7 @@ struct ipt_standard_target
102 int verdict; 108 int verdict;
103}; 109};
104 110
105struct 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
173struct 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 */
191struct 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 */
204struct ipt_icmp 187struct 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. */
270struct 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. */
282struct ipt_get_entries 256struct 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. */
296struct 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 */
309static __inline__ struct ipt_entry_target * 274static __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>
357extern void ipt_init(void) __init; 322extern void ipt_init(void) __init;
358 323
359struct 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. */
395struct 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
430extern int ipt_register_target(struct ipt_target *target); 327#define ipt_register_match(mtch) xt_register_match(AF_INET, mtch)
431extern void ipt_unregister_target(struct ipt_target *target); 328#define ipt_unregister_match(mtch) xt_unregister_match(AF_INET, mtch)
432 329
433extern int ipt_register_match(struct ipt_match *match); 330//#define ipt_register_table(tbl, repl) xt_register_table(AF_INET, tbl, repl)
434extern 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... */ 333extern int ipt_register_table(struct ipt_table *table,
437struct ipt_table 334 const struct ipt_replace *repl);
438{ 335extern 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. */
458extern struct ipt_target *ipt_find_target(const char *name, u8 revision); 338extern 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
479extern int ipt_register_table(struct ipt_table *table,
480 const struct ipt_replace *repl);
481extern void ipt_unregister_table(struct ipt_table *table);
482extern unsigned int ipt_do_table(struct sk_buff **pskb, 359extern 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
4struct 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
13enum { 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
19struct 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 */
5struct 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 */
10enum { 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
16struct 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 */
12struct 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
6struct 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
4enum 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
10enum 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
16struct 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
13struct 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. */
26struct 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
46struct 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
11struct 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
4struct 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
4struct 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. */
9struct 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
4struct 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
4struct 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
15struct 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
4struct 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
4struct 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
9struct 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
7struct 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
4struct 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. */
32struct ip6t_ip6 { 39struct ip6t_ip6 {
@@ -104,10 +111,7 @@ struct ip6t_standard_target
104 int verdict; 111 int verdict;
105}; 112};
106 113
107struct 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 */
177struct 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 */
195struct 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 */
208struct ip6t_icmp 199struct 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. */
274struct 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. */
286struct ip6t_get_entries 268struct 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. */
300struct 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 */
313static __inline__ struct ip6t_entry_target * 286static __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>
362extern void ip6t_init(void) __init; 335extern void ip6t_init(void) __init;
363 336
364struct 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. */
401struct 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
436extern int ip6t_register_target(struct ip6t_target *target);
437extern void ip6t_unregister_target(struct ip6t_target *target);
438
439extern int ip6t_register_match(struct ip6t_match *match);
440extern 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)
443struct 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
463extern int ip6t_register_table(struct ip6t_table *table, 343extern 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
4struct 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
4struct 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. */
9struct 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
4struct 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
4struct 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
15struct 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
46struct tipc_portid {
47 __u32 ref;
48 __u32 node;
49};
50
51struct tipc_name {
52 __u32 type;
53 __u32 instance;
54};
55
56struct tipc_name_seq {
57 __u32 type;
58 __u32 lower;
59 __u32 upper;
60};
61
62static 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
69static inline unsigned int tipc_zone(__u32 addr)
70{
71 return addr >> 24;
72}
73
74static inline unsigned int tipc_cluster(__u32 addr)
75{
76 return (addr >> 12) & 0xfff;
77}
78
79static 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
141struct 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
152struct 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
181struct 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
193struct tipc_node_info {
194 __u32 addr; /* network address of node */
195 __u32 up; /* 0=down, 1= up */
196};
197
198struct 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
204struct 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
210struct tipc_link_config {
211 __u32 value;
212 char name[TIPC_MAX_LINK_NAME];
213};
214
215#define TIPC_NTQ_ALLTYPES 0x80000000
216
217struct 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 */
240struct tipc_link_create {
241 __u32 domain;
242 struct tipc_media_addr peer_addr;
243 char bearer_name[TIPC_MAX_BEARER_NAME];
244};
245
246struct 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
261struct 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
273static 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
288static 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
294static 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
313struct 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
318static 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
325static inline int TLV_LIST_EMPTY(struct tlv_list_desc *list)
326{
327 return (list->tlv_space == 0);
328}
329
330static 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
335static inline void *TLV_LIST_DATA(struct tlv_list_desc *list)
336{
337 return TLV_DATA(list->tlv_ptr);
338}
339
340static 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 */
359struct 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
375struct 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
391static 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 {
37struct sk_buff * 37struct sk_buff *
38nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb); 38nf_ct_ipv4_ct_gather_frags(struct sk_buff *skb);
39 39
40/* call to create an explicit dependency on nf_conntrack_l3proto_ipv4. */
41extern 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);
221extern struct nf_conntrack_helper * 221extern 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. */
225extern void need_nf_conntrack(void);
226
227extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse, 224extern 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) \
114DEBUGP("tuple %p: %u %u %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu -> %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x %hu\n", \ 114DEBUGP("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
53u32 tipc_get_addr(void);
54
55#define TIPC_NOT_RUNNING 0
56#define TIPC_NODE_MODE 1
57#define TIPC_NET_MODE 2
58
59typedef void (*tipc_mode_event)(void *usr_handle, int mode, u32 addr);
60
61int tipc_attach(unsigned int *userref, tipc_mode_event, void *usr_handle);
62
63void tipc_detach(unsigned int userref);
64
65int tipc_get_mode(void);
66
67/*
68 * TIPC port manipulation routines
69 */
70
71typedef 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
79typedef 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
87typedef 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
94typedef 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
102typedef 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
111typedef 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
117typedef void (*tipc_continue_event) (void *usr_handle,
118 u32 portref);
119
120int 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
132int tipc_deleteport(u32 portref);
133
134int tipc_ownidentity(u32 portref, struct tipc_portid *port);
135
136int tipc_portimportance(u32 portref, unsigned int *importance);
137int tipc_set_portimportance(u32 portref, unsigned int importance);
138
139int tipc_portunreliable(u32 portref, unsigned int *isunreliable);
140int tipc_set_portunreliable(u32 portref, unsigned int isunreliable);
141
142int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable);
143int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable);
144
145int tipc_publish(u32 portref, unsigned int scope,
146 struct tipc_name_seq const *name_seq);
147int tipc_withdraw(u32 portref, unsigned int scope,
148 struct tipc_name_seq const *name_seq); /* 0: all */
149
150int tipc_connect2port(u32 portref, struct tipc_portid const *port);
151
152int tipc_disconnect(u32 portref);
153
154int tipc_shutdown(u32 ref); /* Sends SHUTDOWN msg */
155
156int tipc_isconnected(u32 portref, int *isconnected);
157
158int tipc_peer(u32 portref, struct tipc_portid *peer);
159
160int 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
169int tipc_send(u32 portref,
170 unsigned int num_sect,
171 struct iovec const *msg_sect);
172
173int tipc_send_buf(u32 portref,
174 struct sk_buff *buf,
175 unsigned int dsz);
176
177int 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
183int tipc_send_buf2name(u32 portref,
184 struct tipc_name const *name,
185 u32 domain,
186 struct sk_buff *buf,
187 unsigned int dsz);
188
189int 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
197int 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
205int tipc_send2port(u32 portref,
206 struct tipc_portid const *dest,
207 unsigned int num_sect,
208 struct iovec const *msg_sect);
209
210int tipc_send_buf2port(u32 portref,
211 struct tipc_portid const *dest,
212 struct sk_buff *buf,
213 unsigned int dsz);
214
215int 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
222int 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
229int 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
236int 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
247int tipc_ispublished(struct tipc_name const *name);
248
249/*
250 * Get number of available nodes within specified domain (excluding own node)
251 */
252
253unsigned 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
52struct 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
85struct 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
95int 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
110void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
111
112int tipc_block_bearer(const char *name);
113void tipc_continue(struct tipc_bearer *tb_ptr);
114
115int tipc_enable_bearer(const char *bearer_name, u32 bcast_scope, u32 priority);
116int 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
42struct 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
88static inline u32 msg_word(struct tipc_msg *m, u32 pos)
89{
90 return ntohl(m->hdr[pos]);
91}
92
93static 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
98static inline u32 msg_importance(struct tipc_msg *m)
99{
100 return msg_bits(m, 0, 25, 0xf);
101}
102
103static inline u32 msg_hdr_sz(struct tipc_msg *m)
104{
105 return msg_bits(m, 0, 21, 0xf) << 2;
106}
107
108static inline int msg_short(struct tipc_msg *m)
109{
110 return (msg_hdr_sz(m) == 24);
111}
112
113static inline u32 msg_size(struct tipc_msg *m)
114{
115 return msg_bits(m, 0, 0, 0x1ffff);
116}
117
118static inline u32 msg_data_sz(struct tipc_msg *m)
119{
120 return (msg_size(m) - msg_hdr_sz(m));
121}
122
123static inline unchar *msg_data(struct tipc_msg *m)
124{
125 return ((unchar *)m) + msg_hdr_sz(m);
126}
127
128static inline u32 msg_type(struct tipc_msg *m)
129{
130 return msg_bits(m, 1, 29, 0x7);
131}
132
133static inline u32 msg_direct(struct tipc_msg *m)
134{
135 return (msg_type(m) == TIPC_DIRECT_MSG);
136}
137
138static inline u32 msg_named(struct tipc_msg *m)
139{
140 return (msg_type(m) == TIPC_NAMED_MSG);
141}
142
143static inline u32 msg_mcast(struct tipc_msg *m)
144{
145 return (msg_type(m) == TIPC_MCAST_MSG);
146}
147
148static inline u32 msg_connected(struct tipc_msg *m)
149{
150 return (msg_type(m) == TIPC_CONN_MSG);
151}
152
153static inline u32 msg_errcode(struct tipc_msg *m)
154{
155 return msg_bits(m, 1, 25, 0xf);
156}
157
158static inline u32 msg_prevnode(struct tipc_msg *m)
159{
160 return msg_word(m, 3);
161}
162
163static inline u32 msg_origport(struct tipc_msg *m)
164{
165 return msg_word(m, 4);
166}
167
168static inline u32 msg_destport(struct tipc_msg *m)
169{
170 return msg_word(m, 5);
171}
172
173static inline u32 msg_mc_netid(struct tipc_msg *m)
174{
175 return msg_word(m, 5);
176}
177
178static 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
185static inline u32 msg_destnode(struct tipc_msg *m)
186{
187 return msg_word(m, 7);
188}
189
190static inline u32 msg_nametype(struct tipc_msg *m)
191{
192 return msg_word(m, 8);
193}
194
195static inline u32 msg_nameinst(struct tipc_msg *m)
196{
197 return msg_word(m, 9);
198}
199
200static inline u32 msg_namelower(struct tipc_msg *m)
201{
202 return msg_nameinst(m);
203}
204
205static inline u32 msg_nameupper(struct tipc_msg *m)
206{
207 return msg_word(m, 10);
208}
209
210static 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
62struct 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
82u32 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 */
90int tipc_set_msg_option(struct tipc_port *tp_ptr,
91 const char *opt,
92 const u32 len);
93
94int tipc_reject_msg(struct sk_buff *buf, u32 err);
95
96int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode);
97
98void tipc_acknowledge(u32 port_ref,u32 ack);
99
100struct tipc_port *tipc_get_port(const u32 ref);
101
102void *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"
159source "drivers/net/appletalk/Kconfig" 159source "drivers/net/appletalk/Kconfig"
160source "net/x25/Kconfig" 160source "net/x25/Kconfig"
161source "net/lapb/Kconfig" 161source "net/lapb/Kconfig"
162source "net/tipc/Kconfig"
162 163
163config NET_DIVERT 164config 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/
45obj-$(CONFIG_IP_DCCP) += dccp/ 45obj-$(CONFIG_IP_DCCP) += dccp/
46obj-$(CONFIG_IP_SCTP) += sctp/ 46obj-$(CONFIG_IP_SCTP) += sctp/
47obj-$(CONFIG_IEEE80211) += ieee80211/ 47obj-$(CONFIG_IEEE80211) += ieee80211/
48obj-$(CONFIG_TIPC) += tipc/
48 49
49ifeq ($(CONFIG_NET),y) 50ifeq ($(CONFIG_NET),y)
50obj-$(CONFIG_SYSCTL) += sysctl_net.o 51obj-$(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 */
292int sk_chk_filter(struct sock_filter *filter, int flen) 294int 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
183config IP_NF_IPTABLES 183config 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.
194config 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
204config IP_NF_MATCH_IPRANGE 195config 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
213config 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
222config 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
234config 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
244config IP_NF_MATCH_MULTIPORT 204config 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
304config 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
313config IP_NF_MATCH_TTL 264config 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
322config 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
332config 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
342config 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
353config 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
366config IP_NF_MATCH_OWNER 273config 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
375config 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
384config IP_NF_MATCH_ADDRTYPE 282config 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
394config 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
408config 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
419config 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
430config 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
440config 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
452config 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
463config IP_NF_MATCH_HASHLIMIT 292config 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
477config 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
490config IP_NF_MATCH_POLICY 306config 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
575config 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
587config IP_NF_NAT 392config 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
738config 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
751config 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
763config IP_NF_TARGET_TTL 543config 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
777config 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
790config IP_NF_TARGET_CLUSTERIP 557config 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
813config 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
828config IP_NF_ARPTABLES 581config 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
49obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o 49obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
50obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
51obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o 50obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o
52obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o
53obj-$(CONFIG_IP_NF_MATCH_DCCP) += ipt_dccp.o
54obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
55obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
56obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o 51obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
57obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
58obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o 52obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
59obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o 53obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
60obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o 54obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
@@ -62,40 +56,25 @@ obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
62obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o 56obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
63obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o 57obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
64obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o 58obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
65obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
66obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o 59obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
67obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
68obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
69obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
70obj-$(CONFIG_IP_NF_MATCH_CONNBYTES) += ipt_connbytes.o
71obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
72obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
73obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o 60obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
74obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o
75obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o 61obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
76obj-$(CONFIG_IP_NF_MATCH_COMMENT) += ipt_comment.o
77obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
78 62
79# targets 63# targets
80obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o 64obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
81obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o 65obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
82obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o 66obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
83obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o 67obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
84obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
85obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o 68obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
86obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o 69obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
87obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o 70obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
88obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o 71obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
89obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
90obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o 72obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
91obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o 73obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
92obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
93obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o 74obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
94obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o 75obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
95obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
96obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o 76obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
97obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o 77obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
98obj-$(CONFIG_IP_NF_TARGET_NFQUEUE) += ipt_NFQUEUE.o
99 78
100# generic ARP tables 79# generic ARP tables
101obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o 80obj-$(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
29MODULE_LICENSE("GPL"); 30MODULE_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
60static 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
66struct 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
75static LIST_HEAD(arpt_target);
76static 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
80static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, 62static 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
225static unsigned int arpt_error(struct sk_buff **pskb, 207static 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. */
351static 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. */
367static 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
390struct 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
401static 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) */
418static 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. */
445static inline int unconditional(const struct arpt_arp *arp) 328static 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 */
459static int mark_source_chains(struct arpt_table_info *newinfo, 342static 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
624static inline int check_entry_size_and_hooks(struct arpt_entry *e, 507static 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 */
684static int translate_table(const char *name, 567static 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
767static 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. */
793static inline int add_entry_to_counter(const struct arpt_entry *e, 651static 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
803static inline int set_entry_to_counter(const struct arpt_entry *e, 661static 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
813static void get_counters(const struct arpt_table_info *t, 671static 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
935static 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
947static 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
976static int do_replace(void __user *user, unsigned int len) 794static 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 */
1080static inline int add_counter_to_entry(struct arpt_entry *e, 894static 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,
1091static int do_add_counters(void __user *user, unsigned int len) 905static 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. */
1262int 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
1276void arpt_unregister_target(struct arpt_target *target)
1277{
1278 down(&arpt_mutex);
1279 LIST_DELETE(&arpt_target, target);
1280 up(&arpt_mutex);
1281}
1282
1283int arpt_register_table(struct arpt_table *table, 1078int 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
1348void arpt_unregister_table(struct arpt_table *table) 1117void 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
1384static 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
1401static 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
1420static int __init init(void) 1151static 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)
1454static void __exit fini(void) 1172static 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
1462EXPORT_SYMBOL(arpt_register_table); 1178EXPORT_SYMBOL(arpt_register_table);
1463EXPORT_SYMBOL(arpt_unregister_table); 1179EXPORT_SYMBOL(arpt_unregister_table);
1464EXPORT_SYMBOL(arpt_do_table); 1180EXPORT_SYMBOL(arpt_do_table);
1465EXPORT_SYMBOL(arpt_register_target);
1466EXPORT_SYMBOL(arpt_unregister_target);
1467 1181
1468module_init(init); 1182module_init(init);
1469module_exit(fini); 1183module_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>");
8MODULE_DESCRIPTION("arptables arp payload mangle target"); 8MODULE_DESCRIPTION("arptables arp payload mangle target");
9 9
10static unsigned int 10static unsigned int
11target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in, 11target(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
66static int 67static int
67checkentry(const char *tablename, const struct arpt_entry *e, void *targinfo, 68checkentry(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. */
947void need_ip_conntrack(void) 947void need_conntrack(void)
948{ 948{
949} 949}
950 950
@@ -962,7 +962,7 @@ EXPORT_SYMBOL(ip_ct_get_tuple);
962EXPORT_SYMBOL(invert_tuplepr); 962EXPORT_SYMBOL(invert_tuplepr);
963EXPORT_SYMBOL(ip_conntrack_alter_reply); 963EXPORT_SYMBOL(ip_conntrack_alter_reply);
964EXPORT_SYMBOL(ip_conntrack_destroyed); 964EXPORT_SYMBOL(ip_conntrack_destroyed);
965EXPORT_SYMBOL(need_ip_conntrack); 965EXPORT_SYMBOL(need_conntrack);
966EXPORT_SYMBOL(ip_conntrack_helper_register); 966EXPORT_SYMBOL(ip_conntrack_helper_register);
967EXPORT_SYMBOL(ip_conntrack_helper_unregister); 967EXPORT_SYMBOL(ip_conntrack_helper_unregister);
968EXPORT_SYMBOL(ip_ct_iterate_cleanup); 968EXPORT_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
170static int ipt_snat_checkentry(const char *tablename, 171static 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
203static int ipt_dnat_checkentry(const char *tablename, 204static 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
35MODULE_LICENSE("GPL"); 36MODULE_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
67static 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 */
90struct 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
107static LIST_HEAD(ipt_target);
108static LIST_HEAD(ipt_match);
109static 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. */
120static inline int 83static inline int
121ip_packet_match(const struct iphdr *ip, 84ip_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. */
408static 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. */
423static 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. */
447static 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
470struct 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
481static 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
497static 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) */
514static 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. */
541static inline int 351static inline int
542unconditional(const struct ipt_ip *ip) 352unconditional(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. */
555static int 365static int
556mark_source_chains(struct ipt_table_info *newinfo, 366mark_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
782static inline int 593static inline int
783check_entry_size_and_hooks(struct ipt_entry *e, 594check_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)
845static int 656static int
846translate_table(const char *name, 657translate_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
925static struct ipt_table_info *
926replace_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. */
964static inline int 737static inline int
965add_entry_to_counter(const struct ipt_entry *e, 738add_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
986static void 759static void
987get_counters(const struct ipt_table_info *t, 760get_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
1132static 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
1144static 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
1171static int 907static int
1172do_replace(void __user *user, unsigned int len) 908do_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. */
1274static inline int 1006static inline int
1275add_counter_to_entry(struct ipt_entry *e, 1007add_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
1295do_add_counters(void __user *user, unsigned int len) 1027do_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. */ 1210int ipt_register_table(struct xt_table *table, const struct ipt_replace *repl)
1475int
1476ipt_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
1488void
1489ipt_unregister_target(struct ipt_target *target)
1490{
1491 down(&ipt_mutex);
1492 LIST_DELETE(&ipt_target, target);
1493 up(&ipt_mutex);
1494}
1495
1496int
1497ipt_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
1511void
1512ipt_unregister_match(struct ipt_match *match)
1513{
1514 down(&ipt_mutex);
1515 LIST_DELETE(&ipt_match, match);
1516 up(&ipt_mutex);
1517}
1518
1519int 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
1582void ipt_unregister_table(struct ipt_table *table) 1246void 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 */
1598static inline int
1599port_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
1607static int
1608tcp_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
1641static int
1642tcp_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. */
1706static int
1707tcp_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
1722static int
1723udp_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. */
1756static int
1757udp_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. */
1829static int 1303static int
1830icmp_checkentry(const char *tablename, 1304icmp_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
1865static struct ipt_match tcp_matchstruct = {
1866 .name = "tcp",
1867 .match = &tcp_match,
1868 .checkentry = &tcp_checkentry,
1869};
1870
1871static struct ipt_match udp_matchstruct = {
1872 .name = "udp",
1873 .match = &udp_match,
1874 .checkentry = &udp_checkentry,
1875};
1876
1877static struct ipt_match icmp_matchstruct = { 1340static 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
1884static 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
1902static 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
1911static 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
1929static 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
1946static 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
1963static 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
1970static int __init init(void) 1346static 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
2013static void __exit fini(void) 1368static 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
2025EXPORT_SYMBOL(ipt_register_table); 1379EXPORT_SYMBOL(ipt_register_table);
2026EXPORT_SYMBOL(ipt_unregister_table); 1380EXPORT_SYMBOL(ipt_unregister_table);
2027EXPORT_SYMBOL(ipt_register_match);
2028EXPORT_SYMBOL(ipt_unregister_match);
2029EXPORT_SYMBOL(ipt_do_table); 1381EXPORT_SYMBOL(ipt_do_table);
2030EXPORT_SYMBOL(ipt_register_target);
2031EXPORT_SYMBOL(ipt_unregister_target);
2032EXPORT_SYMBOL(ipt_find_target);
2033
2034module_init(init); 1382module_init(init);
2035module_exit(fini); 1383module_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
380static int 380static int
381checkentry(const char *tablename, 381checkentry(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
58static int 58static int
59checkentry(const char *tablename, 59checkentry(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
114static int 114static int
115checkentry(const char *tablename, 115checkentry(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
433static int ipt_log_checkentry(const char *tablename, 433static 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 */
41static int 41static int
42masquerade_check(const char *tablename, 42masquerade_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
32static int 32static int
33check(const char *tablename, 33check(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
18MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
19MODULE_DESCRIPTION("iptables NFQUEUE target");
20MODULE_LICENSE("GPL");
21
22static unsigned int
23target(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
35static int
36checkentry(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
52static struct ipt_target ipt_NFQ_reg = {
53 .name = "NFQUEUE",
54 .target = target,
55 .checkentry = checkentry,
56 .me = THIS_MODULE,
57};
58
59static int __init init(void)
60{
61 return ipt_register_target(&ipt_NFQ_reg);
62}
63
64static void __exit fini(void)
65{
66 ipt_unregister_target(&ipt_NFQ_reg);
67}
68
69module_init(init);
70module_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 */
34static int 34static int
35redirect_check(const char *tablename, 35redirect_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
284static int check(const char *tablename, 284static 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
50static int 50static int
51same_check(const char *tablename, 51same_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 */
211static int 211static int
212ipt_tcpmss_checkentry(const char *tablename, 212ipt_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
53static int 53static int
54checkentry(const char *tablename, 54checkentry(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
68static int ipt_ttl_checkentry(const char *tablename, 68static 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
332static int ipt_ulog_checkentry(const char *tablename, 332static 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
30static int match(const struct sk_buff *skb, const struct net_device *in, 30static 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
46static int checkentry(const char *tablename, const struct ipt_ip *ip, 46static 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. */
70static int 71static int
71checkentry(const char *tablename, 72checkentry(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
22static int match(const struct sk_buff *skb, const struct net_device *in, 22static 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
34static int checkentry(const char *tablename, const struct ipt_ip *ip, 34static 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
68static int match(const struct sk_buff *skb, const struct net_device *in, 68static 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
88static int checkentry(const char *tablename, const struct ipt_ip *ip, 88static 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. */
71static int 72static int
72checkentry(const char *tablename, 73checkentry(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
505static int 506static int
506hashlimit_checkentry(const char *tablename, 507hashlimit_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
65static int check(const char *tablename, 65static 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
15MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
16MODULE_DESCRIPTION("IP tables packet length matching module");
17MODULE_LICENSE("GPL");
18
19static int
20match(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
33static int
34checkentry(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
46static struct ipt_match length_match = {
47 .name = "length",
48 .match = &match,
49 .checkentry = &checkentry,
50 .me = THIS_MODULE,
51};
52
53static int __init init(void)
54{
55 return ipt_register_match(&length_match);
56}
57
58static void __exit fini(void)
59{
60 ipt_unregister_match(&length_match);
61}
62
63module_init(init);
64module_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. */
155static int 157static int
156checkentry(const char *tablename, 158checkentry(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
165static int 167static int
166checkentry_v1(const char *tablename, 168checkentry_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
52static int 53static int
53checkentry(const char *tablename, 54checkentry(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
20MODULE_LICENSE("GPL");
21MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
22MODULE_DESCRIPTION("iptables bridge physical device match module");
23
24static int
25match(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
86match_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
100static int
101checkentry(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
117static struct ipt_match physdev_match = {
118 .name = "physdev",
119 .match = &match,
120 .checkentry = &checkentry,
121 .me = THIS_MODULE,
122};
123
124static int __init init(void)
125{
126 return ipt_register_match(&physdev_match);
127}
128
129static void __exit fini(void)
130{
131 ipt_unregister_match(&physdev_match);
132}
133
134module_init(init);
135module_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);
323out_free_skb: 324out_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 */
655static int 657static int
656checkentry(const char *tablename, 658checkentry(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
33static int 34static int
34checkentry(const char *tablename, 35checkentry(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
22static int match(const struct sk_buff *skb, const struct net_device *in, 22static 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
50static int checkentry(const char *tablename, const struct ipt_ip *ip, 50static 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
576static int __init init(void) 576static 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)
587module_init(init); 587module_init(init);
588module_exit(fini); 588module_exit(fini);
589 589
590void need_ip_conntrack(void)
591{
592}
593
594EXPORT_SYMBOL(need_ip_conntrack);
595EXPORT_SYMBOL(nf_ct_ipv4_gather_frags); 590EXPORT_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)
647static int ip6fl_seq_show(struct seq_file *seq, void *v) 645static 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
42config IP6_NF_IPTABLES 42config 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.
53config 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
63config 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
72config IP6_NF_MATCH_RT 54config 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
127config 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
137config IP6_NF_MATCH_IPV6HEADER 109config 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
154config 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
163config IP6_NF_MATCH_EUI64 126config 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
173config 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
182config IP6_NF_MATCH_POLICY 136config 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
222config 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
233config IP6_NF_MANGLE 176config 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
243config 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
256config IP6_NF_TARGET_HL 186config 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.
6obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o 6obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
7obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
8obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
9obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o 7obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
10obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
11obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o 8obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
12obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o 9obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
13obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o 10obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
@@ -17,12 +14,9 @@ obj-$(CONFIG_IP6_NF_MATCH_POLICY) += ip6t_policy.o
17obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o 14obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
18obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o 15obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
19obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o 16obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
20obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o
21obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o 17obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
22obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o 18obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
23obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
24obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o 19obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
25obj-$(CONFIG_IP6_NF_TARGET_NFQUEUE) += ip6t_NFQUEUE.o
26obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o 20obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
27obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o 21obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
28obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o 22obj-$(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
37MODULE_LICENSE("GPL"); 39MODULE_LICENSE("GPL");
38MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 40MODULE_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
72static 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 */
95struct 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
112static LIST_HEAD(ip6t_target);
113static LIST_HEAD(ip6t_match);
114static 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. */
449static 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. */
464static 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. */
488static 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
511struct 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
522static 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
538static 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) */
555static 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. */
582static inline int 418static inline int
583unconditional(const struct ip6t_ip6 *ipv6) 419unconditional(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. */
596static int 432static int
597mark_source_chains(struct ip6t_table_info *newinfo, 433mark_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
823static inline int 660static inline int
824check_entry_size_and_hooks(struct ip6t_entry *e, 661check_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)
886static int 723static int
887translate_table(const char *name, 724translate_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
966static struct ip6t_table_info *
967replace_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. */
1005static inline int 804static inline int
1006add_entry_to_counter(const struct ip6t_entry *e, 805add_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
1027static void 826static void
1028get_counters(const struct ip6t_table_info *t, 827get_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
1061static int 860static int
1062copy_entries_to_user(unsigned int total_size, 861copy_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
1169static 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
1181static 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
1209static int 968static int
1210do_replace(void __user *user, unsigned int len) 969do_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. */
1308static inline int 1063static inline int
1309add_counter_to_entry(struct ip6t_entry *e, 1064add_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
1329do_add_counters(void __user *user, unsigned int len) 1084do_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. */ 1267int ip6t_register_table(struct xt_table *table,
1509int
1510ip6t_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
1522void
1523ip6t_unregister_target(struct ip6t_target *target)
1524{
1525 down(&ip6t_mutex);
1526 LIST_DELETE(&ip6t_target, target);
1527 up(&ip6t_mutex);
1528}
1529
1530int
1531ip6t_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
1545void
1546ip6t_unregister_match(struct ip6t_match *match)
1547{
1548 down(&ip6t_mutex);
1549 LIST_DELETE(&ip6t_match, match);
1550 up(&ip6t_mutex);
1551}
1552
1553int 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
1615void ip6t_unregister_table(struct ip6t_table *table) 1302void 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 */
1631static inline int
1632port_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
1640static int
1641tcp_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
1672static int
1673tcp_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. */
1737static int
1738tcp_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
1753static int
1754udp_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. */
1787static int
1788udp_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. */
1859static int 1358static int
1860icmp6_checkentry(const char *tablename, 1359icmp6_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
1895static struct ip6t_match tcp_matchstruct = {
1896 .name = "tcp",
1897 .match = &tcp_match,
1898 .checkentry = &tcp_checkentry,
1899};
1900
1901static struct ip6t_match udp_matchstruct = {
1902 .name = "udp",
1903 .match = &udp_match,
1904 .checkentry = &udp_checkentry,
1905};
1906
1907static struct ip6t_match icmp6_matchstruct = { 1395static 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
1914static 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
1932static 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
1941static 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
1959static 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
1976static 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
1993static 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
2000static int __init init(void) 1401static 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
2043static void __exit fini(void) 1424static 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,
2128EXPORT_SYMBOL(ip6t_register_table); 1506EXPORT_SYMBOL(ip6t_register_table);
2129EXPORT_SYMBOL(ip6t_unregister_table); 1507EXPORT_SYMBOL(ip6t_unregister_table);
2130EXPORT_SYMBOL(ip6t_do_table); 1508EXPORT_SYMBOL(ip6t_do_table);
2131EXPORT_SYMBOL(ip6t_register_match);
2132EXPORT_SYMBOL(ip6t_unregister_match);
2133EXPORT_SYMBOL(ip6t_register_target);
2134EXPORT_SYMBOL(ip6t_unregister_target);
2135EXPORT_SYMBOL(ip6t_ext_hdr); 1509EXPORT_SYMBOL(ip6t_ext_hdr);
2136EXPORT_SYMBOL(ipv6_find_hdr); 1510EXPORT_SYMBOL(ipv6_find_hdr);
2137EXPORT_SYMBOL(ip6_masked_addrcmp); 1511EXPORT_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
64static int ip6t_hl_checkentry(const char *tablename, 64static 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
446static int ip6t_log_checkentry(const char *tablename, 445static 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
18MODULE_LICENSE("GPL");
19MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
20
21static unsigned int
22target(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
37static int
38checkentry(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
59static struct ip6t_target ip6t_mark_reg = {
60 .name = "MARK",
61 .target = target,
62 .checkentry = checkentry,
63 .me = THIS_MODULE
64};
65
66static 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
75static void __exit fini(void)
76{
77 ip6t_unregister_target(&ip6t_mark_reg);
78}
79
80module_init(init);
81module_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
18MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
19MODULE_DESCRIPTION("ip6tables NFQUEUE target");
20MODULE_LICENSE("GPL");
21
22static unsigned int
23target(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
35static int
36checkentry(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
52static struct ip6t_target ipt_NFQ_reg = {
53 .name = "NFQUEUE",
54 .target = target,
55 .checkentry = checkentry,
56 .me = THIS_MODULE,
57};
58
59static int __init init(void)
60{
61 return ip6t_register_target(&ipt_NFQ_reg);
62}
63
64static void __exit fini(void)
65{
66 ip6t_unregister_target(&ipt_NFQ_reg);
67}
68
69module_init(init);
70module_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
220static int check(const char *tablename, 220static 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. */
99static int 99static int
100checkentry(const char *tablename, 100checkentry(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. */
179static int 179static int
180checkentry(const char *tablename, 180checkentry(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. */
77static int 77static int
78checkentry(const char *tablename, 78checkentry(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
63static int 63static int
64ip6t_eui64_checkentry(const char *tablename, 64ip6t_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. */
116static int 116static int
117checkentry(const char *tablename, 117checkentry(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. */
179static int 179static int
180checkentry(const char *tablename, 180checkentry(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
51static int checkentry(const char *tablename, const struct ip6t_ip6 *ip, 51static 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
125static int 125static int
126ipv6header_checkentry(const char *tablename, 126ipv6header_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
16MODULE_LICENSE("GPL");
17MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
18MODULE_DESCRIPTION("IPv6 packet length match");
19
20static int
21match(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
35static int
36checkentry(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
48static struct ip6t_match length_match = {
49 .name = "length",
50 .match = &match,
51 .checkentry = &checkentry,
52 .me = THIS_MODULE,
53};
54
55static int __init init(void)
56{
57 return ip6t_register_match(&length_match);
58}
59
60static void __exit fini(void)
61{
62 ip6t_unregister_match(&length_match);
63}
64
65module_init(init);
66module_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
24MODULE_LICENSE("GPL");
25MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>");
26MODULE_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
32static 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
54static int
55ip6t_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. */
83static u_int32_t
84user2credits(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
94static int
95ip6t_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
127static 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
134static int __init init(void)
135{
136 if (ip6t_register_match(&ip6t_limit_reg))
137 return -EINVAL;
138 return 0;
139}
140
141static void __exit fini(void)
142{
143 ip6t_unregister_match(&ip6t_limit_reg);
144}
145
146module_init(init);
147module_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
19MODULE_LICENSE("GPL");
20MODULE_DESCRIPTION("MAC address matching module for IPv6");
21MODULE_AUTHOR("Netfilter Core Teaam <coreteam@netfilter.org>");
22
23static int
24match(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
42static int
43ip6t_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
63static struct ip6t_match mac_match = {
64 .name = "mac",
65 .match = &match,
66 .checkentry = &ip6t_mac_checkentry,
67 .me = THIS_MODULE,
68};
69
70static int __init init(void)
71{
72 return ip6t_register_match(&mac_match);
73}
74
75static void __exit fini(void)
76{
77 ip6t_unregister_match(&mac_match);
78}
79
80module_init(init);
81module_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
17MODULE_LICENSE("GPL");
18MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
19MODULE_DESCRIPTION("ip6tables mark match");
20
21static int
22match(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
35static int
36checkentry(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
48static struct ip6t_match mark_match = {
49 .name = "mark",
50 .match = &match,
51 .checkentry = &checkentry,
52 .me = THIS_MODULE,
53};
54
55static int __init init(void)
56{
57 return ip6t_register_match(&mark_match);
58}
59
60static void __exit fini(void)
61{
62 ip6t_unregister_match(&mark_match);
63}
64
65module_init(init);
66module_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. */
85static int 85static int
86checkentry(const char *tablename, 86checkentry(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
54static int 54static int
55checkentry(const char *tablename, 55checkentry(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. */
184static int 184static int
185checkentry(const char *tablename, 185checkentry(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
109static struct ip6t_table packet_raw = { 109static 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,
74static int ipv6_print_tuple(struct seq_file *s, 74static 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
585static int __init init(void) 585static 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
596module_init(init); 596module_init(init);
597module_exit(fini); 597module_exit(fini);
598
599void need_ip6_conntrack(void)
600{
601}
602
603EXPORT_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
71struct nf_ct_frag6_queue 71struct 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
100static struct nf_ct_frag6_queue *nf_ct_frag6_hash[FRAG6Q_HASHSZ]; 99static struct hlist_head nf_ct_frag6_hash[FRAG6Q_HASHSZ];
101static DEFINE_RWLOCK(nf_ct_frag6_lock); 100static DEFINE_RWLOCK(nf_ct_frag6_lock);
102static u32 nf_ct_frag6_hash_rnd; 101static u32 nf_ct_frag6_hash_rnd;
103static LIST_HEAD(nf_ct_frag6_lru_list); 102static LIST_HEAD(nf_ct_frag6_lru_list);
@@ -105,9 +104,7 @@ int nf_ct_frag6_nqueues = 0;
105 104
106static __inline__ void __fq_unlink(struct nf_ct_frag6_queue *fq) 105static __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
318static struct nf_ct_frag6_queue *nf_ct_frag6_intern(unsigned int hash, 304static 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 *
384fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) 370fq_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
19static struct xfrm_state_afinfo xfrm6_state_afinfo; 20static 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;
261alloc_spi: 261alloc_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
105endmenu 105endmenu
106
107config 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
115config 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
127config 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
141config 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
154config 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
165config 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
179config 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
189config 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
200config 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
212config 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
225config 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
236config 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
246config 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
255config 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
265config 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
274config 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
284config 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
293config 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
305config 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
319config 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
330config 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
341config 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
354config 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 @@
1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o 1netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o
2nf_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
3obj-$(CONFIG_NETFILTER) = netfilter.o 4obj-$(CONFIG_NETFILTER) = netfilter.o
4 5
@@ -6,13 +7,43 @@ obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o
6obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o 7obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o
7obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o 8obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o
8 9
9nf_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
11obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o 11obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
12obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
13 12
14# SCTP protocol connection tracking 13# SCTP protocol connection tracking
15obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o 14obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
16 15
17# netlink interface for nf_conntrack 16# netlink interface for nf_conntrack
18obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o 17obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
18
19# connection tracking helpers
20obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
21
22# generic X tables
23obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
24
25# targets
26obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
27obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
28obj-$(CONFIG_NETFILTER_XT_TARGET_MARK) += xt_MARK.o
29obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
30obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
31
32# matches
33obj-$(CONFIG_NETFILTER_XT_MATCH_COMMENT) += xt_comment.o
34obj-$(CONFIG_NETFILTER_XT_MATCH_CONNBYTES) += xt_connbytes.o
35obj-$(CONFIG_NETFILTER_XT_MATCH_CONNMARK) += xt_connmark.o
36obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o
37obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o
38obj-$(CONFIG_NETFILTER_XT_MATCH_HELPER) += xt_helper.o
39obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o
40obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o
41obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o
42obj-$(CONFIG_NETFILTER_XT_MATCH_MARK) += xt_mark.o
43obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o
44obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
45obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
46obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
47obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
48obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o
49obj-$(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. */
824void need_nf_conntrack(void) 824void need_conntrack(void)
825{ 825{
826} 826}
827 827
@@ -841,7 +841,7 @@ EXPORT_SYMBOL(nf_conntrack_protocol_unregister);
841EXPORT_SYMBOL(nf_ct_invert_tuplepr); 841EXPORT_SYMBOL(nf_ct_invert_tuplepr);
842EXPORT_SYMBOL(nf_conntrack_alter_reply); 842EXPORT_SYMBOL(nf_conntrack_alter_reply);
843EXPORT_SYMBOL(nf_conntrack_destroyed); 843EXPORT_SYMBOL(nf_conntrack_destroyed);
844EXPORT_SYMBOL(need_nf_conntrack); 844EXPORT_SYMBOL(need_conntrack);
845EXPORT_SYMBOL(nf_conntrack_helper_register); 845EXPORT_SYMBOL(nf_conntrack_helper_register);
846EXPORT_SYMBOL(nf_conntrack_helper_unregister); 846EXPORT_SYMBOL(nf_conntrack_helper_unregister);
847EXPORT_SYMBOL(nf_ct_iterate_cleanup); 847EXPORT_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
28MODULE_LICENSE("GPL");
29MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
30MODULE_DESCRIPTION("[ip,ip6,arp]_tables backend module");
31
32#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
33
34struct xt_af {
35 struct semaphore mutex;
36 struct list_head match;
37 struct list_head target;
38 struct list_head tables;
39};
40
41static 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
49enum {
50 TABLE,
51 TARGET,
52 MATCH,
53};
54
55/* Registration hooks for targets. */
56int
57xt_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}
68EXPORT_SYMBOL(xt_register_target);
69
70void
71xt_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}
77EXPORT_SYMBOL(xt_unregister_target);
78
79int
80xt_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}
93EXPORT_SYMBOL(xt_register_match);
94
95void
96xt_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}
102EXPORT_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. */
112struct 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}
134EXPORT_SYMBOL(xt_find_match);
135
136/* Find target, grabs ref. Returns ERR_PTR() on error. */
137struct 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}
159EXPORT_SYMBOL(xt_find_target);
160
161static const char *xt_prefix[NPROTO] = {
162 [AF_INET] = "ipt_%s",
163 [AF_INET6] = "ip6t_%s",
164 [NF_ARP] = "arpt_%s",
165};
166
167struct 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}
177EXPORT_SYMBOL_GPL(xt_request_find_target);
178
179static 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
195static 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) */
212int 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}
238EXPORT_SYMBOL_GPL(xt_find_revision);
239
240struct 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}
272EXPORT_SYMBOL(xt_alloc_table_info);
273
274void 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}
286EXPORT_SYMBOL(xt_free_table_info);
287
288/* Find table by name, grabs mutex & ref. Returns ERR_PTR() on error. */
289struct 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}
302EXPORT_SYMBOL_GPL(xt_find_table_lock);
303
304void xt_table_unlock(struct xt_table *table)
305{
306 up(&xt[table->af].mutex);
307}
308EXPORT_SYMBOL_GPL(xt_table_unlock);
309
310
311struct xt_table_info *
312xt_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}
337EXPORT_SYMBOL_GPL(xt_replace_table);
338
339int 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}
375EXPORT_SYMBOL_GPL(xt_register_table);
376
377void *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}
388EXPORT_SYMBOL_GPL(xt_unregister_table);
389
390#ifdef CONFIG_PROC_FS
391static char *xt_proto_prefix[NPROTO] = {
392 [AF_INET] = "ip",
393 [AF_INET6] = "ip6",
394 [NF_ARP] = "arp",
395};
396
397static 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
412static 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
434static 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
454static 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
472static 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
480static 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
490static 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
497static 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
512static 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
526int 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
564out_remove_matches:
565 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
566 strlcat(buf, FORMAT_MATCHES, sizeof(buf));
567 proc_net_remove(buf);
568
569out_remove_tables:
570 strlcpy(buf, xt_proto_prefix[af], sizeof(buf));
571 strlcat(buf, FORMAT_TABLES, sizeof(buf));
572 proc_net_remove(buf);
573out:
574 return -1;
575#endif
576}
577EXPORT_SYMBOL_GPL(xt_proto_init);
578
579void 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}
597EXPORT_SYMBOL_GPL(xt_proto_fini);
598
599
600static 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
617static void __exit xt_fini(void)
618{
619 kfree(xt);
620}
621
622module_init(xt_init);
623module_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
21MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 21MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
22MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
23MODULE_DESCRIPTION("iptables qdisc classification target module"); 23MODULE_DESCRIPTION("iptables qdisc classification target module");
24MODULE_ALIAS("ipt_CLASSIFY");
24 25
25static unsigned int 26static unsigned int
26target(struct sk_buff **pskb, 27target(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
41static int 42static int
42checkentry(const char *tablename, 43checkentry(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
72static struct ipt_target ipt_classify_reg = { 73static struct xt_target classify_reg = {
74 .name = "CLASSIFY",
75 .target = target,
76 .checkentry = checkentry,
77 .me = THIS_MODULE,
78};
79static 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
79static int __init init(void) 87static 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
84static void __exit fini(void) 102static 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
89module_init(init); 108module_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 @@
26MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); 26MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
27MODULE_DESCRIPTION("IP tables CONNMARK matching module"); 27MODULE_DESCRIPTION("IP tables CONNMARK matching module");
28MODULE_LICENSE("GPL"); 28MODULE_LICENSE("GPL");
29MODULE_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
34static unsigned int 35static 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
73static int 74static int
74checkentry(const char *tablename, 75checkentry(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
103static struct ipt_target ipt_connmark_reg = { 104static struct xt_target connmark_reg = {
105 .name = "CONNMARK",
106 .target = &target,
107 .checkentry = &checkentry,
108 .me = THIS_MODULE
109};
110static 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
110static int __init init(void) 117static 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
116static void __exit fini(void) 134static 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
121module_init(init); 140module_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
18MODULE_LICENSE("GPL"); 18MODULE_LICENSE("GPL");
19MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 19MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
20MODULE_DESCRIPTION("iptables MARK modification module"); 20MODULE_DESCRIPTION("ip[6]tables MARK modification module");
21MODULE_ALIAS("ipt_MARK");
22MODULE_ALIAS("ip6t_MARK");
21 23
22static unsigned int 24static unsigned int
23target_v0(struct sk_buff **pskb, 25target_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
38static unsigned int 40static 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
70static int 72static int
71checkentry_v0(const char *tablename, 73checkentry_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
99static int 101static int
100checkentry_v1(const char *tablename, 102checkentry_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
136static struct ipt_target ipt_mark_reg_v0 = { 138static 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
144static struct ipt_target ipt_mark_reg_v1 = { 146static 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
154static 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
152static int __init init(void) 162static 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
165static void __exit fini(void) 183static 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
171module_init(init); 190module_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
19MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
20MODULE_DESCRIPTION("[ip,ip6,arp]_tables NFQUEUE target");
21MODULE_LICENSE("GPL");
22MODULE_ALIAS("ipt_NFQUEUE");
23MODULE_ALIAS("ip6t_NFQUEUE");
24MODULE_ALIAS("arpt_NFQUEUE");
25
26static unsigned int
27target(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
39static int
40checkentry(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
56static struct xt_target ipt_NFQ_reg = {
57 .name = "NFQUEUE",
58 .target = target,
59 .checkentry = checkentry,
60 .me = THIS_MODULE,
61};
62
63static struct xt_target ip6t_NFQ_reg = {
64 .name = "NFQUEUE",
65 .target = target,
66 .checkentry = checkentry,
67 .me = THIS_MODULE,
68};
69
70static struct xt_target arpt_NFQ_reg = {
71 .name = "NFQUEUE",
72 .target = target,
73 .checkentry = checkentry,
74 .me = THIS_MODULE,
75};
76
77static 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;
91out_ip6:
92 xt_unregister_target(AF_INET6, &ip6t_NFQ_reg);
93out_ip:
94 xt_unregister_target(AF_INET, &ipt_NFQ_reg);
95
96 return ret;
97}
98
99static 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
106module_init(init);
107module_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
10MODULE_LICENSE("GPL");
11MODULE_ALIAS("ipt_NOTRACK");
12
10static unsigned int 13static unsigned int
11target(struct sk_buff **pskb, 14target(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
33static int 36static int
34checkentry(const char *tablename, 37checkentry(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
54static struct ipt_target ipt_notrack_reg = { 57static 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};
63static struct xt_target notrack6_reg = {
64 .name = "NOTRACK",
65 .target = target,
66 .checkentry = checkentry,
67 .me = THIS_MODULE,
59}; 68};
60 69
61static int __init init(void) 70static 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, &notrack_reg);
75 if (ret)
76 return ret;
65 77
66 return 0; 78 ret = xt_register_target(AF_INET6, &notrack6_reg);
79 if (ret)
80 xt_unregister_target(AF_INET, &notrack_reg);
81
82 return ret;
67} 83}
68 84
69static void __exit fini(void) 85static void __exit fini(void)
70{ 86{
71 ipt_unregister_target(&ipt_notrack_reg); 87 xt_unregister_target(AF_INET6, &notrack6_reg);
88 xt_unregister_target(AF_INET, &notrack_reg);
72} 89}
73 90
74module_init(init); 91module_init(init);
75module_exit(fini); 92module_exit(fini);
76MODULE_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
12MODULE_AUTHOR("Brad Fisher <brad@info-link.net>"); 12MODULE_AUTHOR("Brad Fisher <brad@info-link.net>");
13MODULE_DESCRIPTION("iptables comment match module"); 13MODULE_DESCRIPTION("iptables comment match module");
14MODULE_LICENSE("GPL"); 14MODULE_LICENSE("GPL");
15MODULE_ALIAS("ipt_comment");
16MODULE_ALIAS("ip6t_comment");
15 17
16static int 18static int
17match(const struct sk_buff *skb, 19match(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
28static int 31static int
29checkentry(const char *tablename, 32checkentry(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
41static struct ipt_match comment_match = { 44static struct xt_match comment_match = {
45 .name = "comment",
46 .match = match,
47 .checkentry = checkentry,
48 .me = THIS_MODULE
49};
50
51static 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
48static int __init init(void) 58static 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
53static void __exit fini(void) 73static 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
58module_init(init); 79module_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 @@
20MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
21MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 23MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
22MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection"); 24MODULE_DESCRIPTION("iptables match for matching number of pkts/bytes per connection");
25MODULE_ALIAS("ipt_connbytes");
23 26
24/* 64bit divisor, dividend and result. dynamic precision */ 27/* 64bit divisor, dividend and result. dynamic precision */
25static u_int64_t div64_64(u_int64_t dividend, u_int64_t divisor) 28static 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
119static int check(const char *tablename, 123static 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
143static struct ipt_match state_match = { 147static struct xt_match connbytes_match = {
148 .name = "connbytes",
149 .match = &match,
150 .checkentry = &check,
151 .me = THIS_MODULE
152};
153static 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
150static int __init init(void) 160static 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
155static void __exit fini(void) 173static 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
160module_init(init); 179module_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 @@
25MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>"); 25MODULE_AUTHOR("Henrik Nordstrom <hno@marasytems.com>");
26MODULE_DESCRIPTION("IP tables connmark match module"); 26MODULE_DESCRIPTION("IP tables connmark match module");
27MODULE_LICENSE("GPL"); 27MODULE_LICENSE("GPL");
28MODULE_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
33static int 34static 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
50static int 52static int
51checkentry(const char *tablename, 53checkentry(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
70static struct ipt_match connmark_match = { 72static struct xt_match connmark_match = {
73 .name = "connmark",
74 .match = &match,
75 .checkentry = &checkentry,
76 .me = THIS_MODULE
77};
78static 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
77static int __init init(void) 86static 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
82static void __exit fini(void) 102static 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
87module_init(init); 108module_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
24MODULE_LICENSE("GPL"); 24MODULE_LICENSE("GPL");
25MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 25MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
26MODULE_DESCRIPTION("iptables connection tracking match module"); 26MODULE_DESCRIPTION("iptables connection tracking match module");
27MODULE_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
201static int check(const char *tablename, 204static 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
213static struct ipt_match conntrack_match = { 216static 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
220static int __init init(void) 223static 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
226static void __exit fini(void) 232static void __exit fini(void)
227{ 233{
228 ipt_unregister_match(&conntrack_match); 234 xt_unregister_match(AF_INET, &conntrack_match);
229} 235}
230 236
231module_init(init); 237module_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
23MODULE_LICENSE("GPL");
24MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
25MODULE_DESCRIPTION("Match for DCCP protocol packets");
26MODULE_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);
26static inline int 34static inline int
27dccp_find_option(u_int8_t option, 35dccp_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
80static inline int 87static inline int
81match_option(u_int8_t option, const struct sk_buff *skb, 88match_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
87static int 94static 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
120static int 129static int
121checkentry(const char *tablename, 130checkentry(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
139static struct ipt_match dccp_match = 149static int
150checkentry6(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
170static 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};
177static struct xt_match dccp6_match =
178{
179 .name = "dccp",
180 .match = &match,
181 .checkentry = &checkentry6,
182 .me = THIS_MODULE,
183};
184
146 185
147static int __init init(void) 186static 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
205out_unreg:
206 xt_unregister_match(AF_INET, &dccp_match);
207out_kfree:
208 kfree(dccp_optbuf);
160 209
161 return ret; 210 return ret;
162} 211}
163 212
164static void __exit fini(void) 213static 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
170module_init(init); 220module_init(init);
171module_exit(fini); 221module_exit(fini);
172
173MODULE_LICENSE("GPL");
174MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
175MODULE_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
29MODULE_LICENSE("GPL"); 28MODULE_LICENSE("GPL");
30MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>"); 29MODULE_AUTHOR("Martin Josefsson <gandalf@netfilter.org>");
31MODULE_DESCRIPTION("iptables helper match module"); 30MODULE_DESCRIPTION("iptables helper match module");
31MODULE_ALIAS("ipt_helper");
32MODULE_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
131static int check(const char *tablename, 134static 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
148static struct ipt_match helper_match = { 151static struct xt_match helper_match = {
152 .name = "helper",
153 .match = &match,
154 .checkentry = &check,
155 .me = THIS_MODULE,
156};
157static 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
155static int __init init(void) 164static 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
161static void __exit fini(void) 180static 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
166module_init(init); 186module_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
16MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
17MODULE_DESCRIPTION("IP tables packet length matching module");
18MODULE_LICENSE("GPL");
19MODULE_ALIAS("ipt_length");
20MODULE_ALIAS("ip6t_length");
21
22static int
23match(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
37static int
38match6(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
52static int
53checkentry(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
65static struct xt_match length_match = {
66 .name = "length",
67 .match = &match,
68 .checkentry = &checkentry,
69 .me = THIS_MODULE,
70};
71static struct xt_match length6_match = {
72 .name = "length",
73 .match = &match6,
74 .checkentry = &checkentry,
75 .me = THIS_MODULE,
76};
77
78static 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
91static void __exit fini(void)
92{
93 xt_unregister_match(AF_INET, &length_match);
94 xt_unregister_match(AF_INET6, &length6_match);
95}
96
97module_init(init);
98module_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
24MODULE_LICENSE("GPL"); 24MODULE_LICENSE("GPL");
25MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>"); 25MODULE_AUTHOR("Herve Eychenne <rv@wallfire.org>");
26MODULE_DESCRIPTION("iptables rate limit match"); 26MODULE_DESCRIPTION("iptables rate limit match");
27MODULE_ALIAS("ipt_limit");
28MODULE_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
104static int 107static int
105ipt_limit_checkentry(const char *tablename, 108ipt_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
137static struct ipt_match ipt_limit_reg = { 140static struct xt_match ipt_limit_reg = {
141 .name = "limit",
142 .match = ipt_limit_match,
143 .checkentry = ipt_limit_checkentry,
144 .me = THIS_MODULE,
145};
146static 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
144static int __init init(void) 153static 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
151static void __exit fini(void) 168static 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
156module_init(init); 174module_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
19MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 21MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
21MODULE_DESCRIPTION("iptables mac matching module"); 22MODULE_DESCRIPTION("iptables mac matching module");
23MODULE_ALIAS("ipt_mac");
24MODULE_ALIAS("ip6t_mac");
22 25
23static int 26static int
24match(const struct sk_buff *skb, 27match(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
41static int 45static int
42ipt_mac_checkentry(const char *tablename, 46ipt_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
62static struct ipt_match mac_match = { 66static struct xt_match mac_match = {
67 .name = "mac",
68 .match = &match,
69 .checkentry = &ipt_mac_checkentry,
70 .me = THIS_MODULE,
71};
72static 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
69static int __init init(void) 79static 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
74static void __exit fini(void) 93static 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
79module_init(init); 99module_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
16MODULE_LICENSE("GPL"); 16MODULE_LICENSE("GPL");
17MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 17MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
18MODULE_DESCRIPTION("iptables mark matching module"); 18MODULE_DESCRIPTION("iptables mark matching module");
19MODULE_ALIAS("ipt_mark");
20MODULE_ALIAS("ip6t_mark");
19 21
20static int 22static int
21match(const struct sk_buff *skb, 23match(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
33static int 36static int
34checkentry(const char *tablename, 37checkentry(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
53static struct ipt_match mark_match = { 56static struct xt_match mark_match = {
57 .name = "mark",
58 .match = &match,
59 .checkentry = &checkentry,
60 .me = THIS_MODULE,
61};
62
63static 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
60static int __init init(void) 70static 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
65static void __exit fini(void) 84static 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
70module_init(init); 90module_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 @@
19MODULE_LICENSE("GPL"); 19MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); 20MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
21MODULE_DESCRIPTION("iptables bridge physical device match module"); 21MODULE_DESCRIPTION("iptables bridge physical device match module");
22MODULE_ALIAS("ipt_physdev");
23MODULE_ALIAS("ip6t_physdev");
22 24
23static int 25static int
24match(const struct sk_buff *skb, 26match(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
86match_outdev: 88match_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
100static int 102static int
101checkentry(const char *tablename, 103checkentry(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
117static struct ip6t_match physdev_match = { 119static struct xt_match physdev_match = {
120 .name = "physdev",
121 .match = &match,
122 .checkentry = &checkentry,
123 .me = THIS_MODULE,
124};
125
126static 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
124static int __init init(void) 133static 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
129static void __exit fini(void) 148static 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
134module_init(init); 154module_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
16MODULE_LICENSE("GPL"); 16MODULE_LICENSE("GPL");
17MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>"); 17MODULE_AUTHOR("Michal Ludvig <michal@logix.cz>");
18MODULE_DESCRIPTION("IP tables match to match on linklayer packet type"); 18MODULE_DESCRIPTION("IP tables match to match on linklayer packet type");
19MODULE_ALIAS("ipt_pkttype");
20MODULE_ALIAS("ip6t_pkttype");
19 21
20static int match(const struct sk_buff *skb, 22static 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
32static int checkentry(const char *tablename, 35static 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
52static struct ipt_match pkttype_match = { 47static 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};
53static struct xt_match pkttype6_match = {
54 .name = "pkttype",
55 .match = &match,
56 .checkentry = &checkentry,
57 .me = THIS_MODULE,
58};
59
58 60
59static int __init init(void) 61static 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
64static void __exit fini(void) 75static 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
69module_init(init); 81module_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
20MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>"); 21MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
21MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
22MODULE_DESCRIPTION("iptables realm match"); 23MODULE_DESCRIPTION("X_tables realm match");
24MODULE_ALIAS("ipt_realm");
23 25
24static int 26static int
25match(const struct sk_buff *skb, 27match(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
38static int check(const char *tablename, 41static 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
58static struct ipt_match realm_match = { 61static 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
65static int __init init(void) 68static 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
70static void __exit fini(void) 73static void __exit fini(void)
71{ 74{
72 ipt_unregister_match(&realm_match); 75 xt_unregister_match(AF_INET, &realm_match);
73} 76}
74 77
75module_init(init); 78module_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
12MODULE_LICENSE("GPL");
13MODULE_AUTHOR("Kiran Kumar Immidi");
14MODULE_DESCRIPTION("Match for SCTP protocol packets");
15MODULE_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
18static int 26static int
19match_flags(const struct ipt_sctp_flag_info *flag_info, 27match_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
35static int 43static inline int
36match_packet(const struct sk_buff *skb, 44match_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
153static int 162static int
154checkentry(const char *tablename, 163checkentry(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
187static int
188checkentry6(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
177static struct ipt_match sctp_match = 212
213static 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};
220static 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
187static int __init init(void) 229static 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
192static void __exit fini(void) 243static 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
197module_init(init); 249module_init(init);
198module_exit(fini); 250module_exit(fini);
199
200MODULE_LICENSE("GPL");
201MODULE_AUTHOR("Kiran Kumar Immidi");
202MODULE_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
17MODULE_LICENSE("GPL"); 17MODULE_LICENSE("GPL");
18MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>"); 18MODULE_AUTHOR("Rusty Russell <rusty@rustcorp.com.au>");
19MODULE_DESCRIPTION("iptables connection tracking state match module"); 19MODULE_DESCRIPTION("ip[6]_tables connection tracking state match module");
20MODULE_ALIAS("ipt_state");
21MODULE_ALIAS("ip6t_state");
20 22
21static int 23static int
22match(const struct sk_buff *skb, 24match(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
43static int check(const char *tablename, 46static 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
55static struct ipt_match state_match = { 58static struct xt_match state_match = {
59 .name = "state",
60 .match = &match,
61 .checkentry = &check,
62 .me = THIS_MODULE,
63};
64
65static 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
62static int __init init(void) 72static 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
68static void __exit fini(void) 89static 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
73module_init(init); 95module_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
18MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>"); 18MODULE_AUTHOR("Pablo Neira Ayuso <pablo@eurodev.net>");
19MODULE_DESCRIPTION("IP tables string match module"); 19MODULE_DESCRIPTION("IP tables string match module");
20MODULE_LICENSE("GPL"); 20MODULE_LICENSE("GPL");
21MODULE_ALIAS("ipt_string");
22MODULE_ALIAS("ip6t_string");
21 23
22static int match(const struct sk_buff *skb, 24static 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
41static int checkentry(const char *tablename, 44static 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
72static struct ipt_match string_match = { 75static struct xt_match string_match = {
76 .name = "string",
77 .match = match,
78 .checkentry = checkentry,
79 .destroy = destroy,
80 .me = THIS_MODULE
81};
82static 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
80static int __init init(void) 90static 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
85static void __exit fini(void) 104static 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
90module_init(init); 110module_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
19MODULE_LICENSE("GPL"); 23MODULE_LICENSE("GPL");
20MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>"); 24MODULE_AUTHOR("Marc Boucher <marc@mbsi.ca>");
21MODULE_DESCRIPTION("iptables TCP MSS match module"); 25MODULE_DESCRIPTION("iptables TCP MSS match module");
26MODULE_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 */
24static inline int 29static inline int
25mssoption_match(u_int16_t min, u_int16_t max, 30mssoption_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
90static int 95static int
91checkentry(const char *tablename, 96checkentry(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
109static struct ipt_match tcpmss_match = { 115static int
116checkentry6(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
136static 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
143static struct xt_match tcpmss6_match = {
144 .name = "tcpmss",
145 .match = &match,
146 .checkentry = &checkentry6,
147 .me = THIS_MODULE,
148};
149
150
116static int __init init(void) 151static 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
121static void __exit fini(void) 165static 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
126module_init(init); 171module_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
12MODULE_DESCRIPTION("x_tables match for TCP and UDP, supports IPv4 and IPv6");
13MODULE_LICENSE("GPL");
14MODULE_ALIAS("xt_tcp");
15MODULE_ALIAS("xt_udp");
16MODULE_ALIAS("ipt_udp");
17MODULE_ALIAS("ipt_tcp");
18MODULE_ALIAS("ip6t_udp");
19MODULE_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 */
29static inline int
30port_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
38static int
39tcp_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
72static int
73tcp_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. */
137static int
138tcp_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. */
155static int
156tcp6_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
173static int
174udp_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. */
207static int
208udp_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. */
238static int
239udp6_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
268static struct xt_match tcp_matchstruct = {
269 .name = "tcp",
270 .match = &tcp_match,
271 .checkentry = &tcp_checkentry,
272 .me = THIS_MODULE,
273};
274static struct xt_match tcp6_matchstruct = {
275 .name = "tcp",
276 .match = &tcp_match,
277 .checkentry = &tcp6_checkentry,
278 .me = THIS_MODULE,
279};
280
281static struct xt_match udp_matchstruct = {
282 .name = "udp",
283 .match = &udp_match,
284 .checkentry = &udp_checkentry,
285 .me = THIS_MODULE,
286};
287static struct xt_match udp6_matchstruct = {
288 .name = "udp",
289 .match = &udp_match,
290 .checkentry = &udp6_checkentry,
291 .me = THIS_MODULE,
292};
293
294static 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
315out_unreg_udp:
316 xt_unregister_match(AF_INET, &tcp_matchstruct);
317out_unreg_tcp6:
318 xt_unregister_match(AF_INET6, &tcp6_matchstruct);
319out_unreg_tcp:
320 xt_unregister_match(AF_INET, &tcp_matchstruct);
321 return ret;
322}
323
324static 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
332module_init(init);
333module_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
541static int __init genl_init(void) 534static 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
45choice 45choice
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. */
676static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr) 671static 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
5menu "TIPC Configuration (EXPERIMENTAL)"
6 depends on INET && EXPERIMENTAL
7
8config 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
20config 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
29config 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
40config 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
55config 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
66config 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
79config 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
90config 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
102config 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
112endmenu
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
5obj-$(CONFIG_TIPC) := tipc.o
6
7tipc-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
44u32 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
58int 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
90int 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
40static inline u32 own_node(void)
41{
42 return tipc_node(tipc_own_addr);
43}
44
45static inline u32 own_cluster(void)
46{
47 return tipc_cluster(tipc_own_addr);
48}
49
50static inline u32 own_zone(void)
51{
52 return tipc_zone(tipc_own_addr);
53}
54
55static inline int in_own_cluster(u32 addr)
56{
57 return !((addr ^ tipc_own_addr) >> 12);
58}
59
60static inline int in_own_zone(u32 addr)
61{
62 return !((addr ^ tipc_own_addr) >> 24);
63}
64
65static inline int is_slave(u32 addr)
66{
67 return addr & 0x800;
68}
69
70static inline int may_route(u32 addr)
71{
72 return(addr ^ tipc_own_addr) >> 11;
73}
74
75static 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
90static 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
108static 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
118static 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
125int addr_domain_valid(u32);
126int 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
68struct 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
81struct 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
96struct bclink {
97 struct link link;
98 struct node node;
99};
100
101
102static struct bcbearer *bcbearer = NULL;
103static struct bclink *bclink = NULL;
104static struct link *bcl = NULL;
105static spinlock_t bc_lock = SPIN_LOCK_UNLOCKED;
106
107char bc_link_name[] = "multicast-link";
108
109
110static inline u32 buf_seqno(struct sk_buff *buf)
111{
112 return msg_seqno(buf_msg(buf));
113}
114
115static inline u32 bcbuf_acks(struct sk_buff *buf)
116{
117 return (u32)(unsigned long)TIPC_SKB_CB(buf)->handle;
118}
119
120static inline void bcbuf_set_acks(struct sk_buff *buf, u32 acks)
121{
122 TIPC_SKB_CB(buf)->handle = (void *)(unsigned long)acks;
123}
124
125static 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
137static 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
157static 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
171static 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
193void 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
241static 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
255static 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
299void 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
317void 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
374int 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
401void 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);
437receive:
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
503u32 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
512u32 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
528int 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 */
582swap:
583 bcbearer->bpairs[bp_index].primary = s;
584 bcbearer->bpairs[bp_index].secondary = p;
585update:
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
603void 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
664void 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
678int 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
724int 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
735int 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
748int 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
791void 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
49struct 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
64struct port_list {
65 int count;
66 struct port_list *next;
67 u32 ports[PLSIZE];
68};
69
70
71struct node;
72
73extern char bc_link_name[];
74
75
76/**
77 * nmap_get - determine if node exists in a node map
78 */
79
80static 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
93static 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
109static 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
125static 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
137static 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
162static 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
197static 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
209int bclink_init(void);
210void bclink_stop(void);
211void bclink_acknowledge(struct node *n_ptr, u32 acked);
212int bclink_send_msg(struct sk_buff *buf);
213void bclink_recv_pkt(struct sk_buff *buf);
214u32 bclink_get_last_sent(void);
215u32 bclink_acks_missing(struct node *n_ptr);
216void bclink_check_gap(struct node *n_ptr, u32 seqno);
217int bclink_stats(char *stats_buf, const u32 buf_size);
218int bclink_reset_stats(void);
219int bclink_set_queue_limits(u32 limit);
220void bcbearer_sort(void);
221void 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
48static struct media *media_list = 0;
49static u32 media_count = 0;
50
51struct 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
59static 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
73static 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
91int 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;
166exit:
167 write_unlock_bh(&net_lock);
168 return res;
169}
170
171/**
172 * media_addr_printf - record media address in print buffer
173 */
174
175void 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
206struct 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
233static 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
280static 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
296struct 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
316struct 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
342void 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
349void 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 */
364static 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
384void 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 */
400void 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
420static 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
433void 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 */
446int 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
466int 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
497restart:
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;
553failed:
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
563int 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
601static 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
636int 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
648int 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
670void 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
62struct 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
95struct 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
110struct bearer_name {
111 char media_name[TIPC_MAX_MEDIA_NAME];
112 char if_name[TIPC_MAX_IF_NAME];
113};
114
115struct link;
116
117extern struct bearer *bearers;
118
119void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a);
120struct sk_buff *media_get_names(void);
121
122struct sk_buff *bearer_get_names(void);
123void bearer_add_dest(struct bearer *b_ptr, u32 dest);
124void bearer_remove_dest(struct bearer *b_ptr, u32 dest);
125void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr);
126struct bearer *bearer_find_interface(const char *if_name);
127int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr);
128int bearer_init(void);
129void bearer_stop(void);
130int bearer_broadcast(struct sk_buff *buf, struct tipc_bearer *b_ptr,
131 struct tipc_media_addr *dest);
132void 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
153static 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
163static 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
47void cluster_multicast(struct cluster *c_ptr, struct sk_buff *buf,
48 u32 lower, u32 upper);
49struct sk_buff *cluster_prepare_routing_msg(u32 data_size, u32 dest);
50
51struct node **local_nodes = 0;
52struct node_map cluster_bcast_nodes = {0,{0,}};
53u32 highest_allowed_slave = 0;
54
55struct 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
100void 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
116u32 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
136void 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
157u32 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
199struct 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
232struct 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
246void 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
262void 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
278void 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
313void 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
347void 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
378void 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
470void 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
498void 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
533void 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 }
567exit:
568 buf_discard(buf);
569}
570
571int 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
54struct cluster {
55 u32 addr;
56 struct _zone *owner;
57 struct node **nodes;
58 u32 highest_node;
59 u32 highest_slave;
60};
61
62
63extern struct node **local_nodes;
64extern u32 highest_allowed_slave;
65extern struct node_map cluster_bcast_nodes;
66
67void cluster_remove_as_router(struct cluster *c_ptr, u32 router);
68void cluster_send_ext_routes(struct cluster *c_ptr, u32 dest);
69struct node *cluster_select_node(struct cluster *c_ptr, u32 selector);
70u32 cluster_select_router(struct cluster *c_ptr, u32 ref);
71void cluster_recv_routing_table(struct sk_buff *buf);
72struct cluster *cluster_create(u32 addr);
73void cluster_delete(struct cluster *c_ptr);
74void cluster_attach_node(struct cluster *c_ptr, struct node *n_ptr);
75void cluster_send_slave_routes(struct cluster *c_ptr, u32 dest);
76void cluster_broadcast(struct sk_buff *buf);
77int cluster_init(void);
78u32 cluster_next_node(struct cluster *c_ptr, u32 addr);
79void cluster_bcast_new_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
80void cluster_send_local_routes(struct cluster *c_ptr, u32 dest);
81void cluster_bcast_lost_route(struct cluster *c_ptr, u32 dest, u32 lo, u32 hi);
82
83static 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
49struct subscr_data {
50 char usr_handle[8];
51 u32 domain;
52 u32 port_ref;
53 struct list_head subd_list;
54};
55
56struct 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
64static struct manager mng = { 0};
65
66static spinlock_t config_lock = SPIN_LOCK_UNLOCKED;
67
68static const void *req_tlv_area; /* request message TLV area */
69static int req_tlv_space; /* request message TLV area size */
70static int rep_headroom; /* reply message headroom to use */
71
72
73void cfg_link_event(u32 addr, char *name, int up)
74{
75 /* TIPC DOESN'T HANDLE LINK EVENT SUBSCRIPTIONS AT THE MOMENT */
76}
77
78
79struct 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
89int 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
107struct 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
121struct 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
139int 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
183static 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
253static 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
269static 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
280static 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
306static 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
319static 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
335static 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
351static 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
384static 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
400static 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
414static 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
428static 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
442static 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
456static 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
475struct 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 */
628exit:
629 spin_unlock_bh(&config_lock);
630 return rep_tlv_buf;
631}
632
633static 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
678int 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
705failed:
706 err("Unable to create configuration service\n");
707 tipc_detach(mng.user_ref);
708 mng.user_ref = 0;
709 return res;
710}
711
712void 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
46struct sk_buff *cfg_reply_alloc(int payload_size);
47int cfg_append_tlv(struct sk_buff *buf, int tlv_type,
48 void *tlv_data, int tlv_data_size);
49struct sk_buff *cfg_reply_unsigned_type(u16 tlv_type, u32 value);
50struct sk_buff *cfg_reply_string_type(u16 tlv_type, char *string);
51
52static inline struct sk_buff *cfg_reply_none(void)
53{
54 return cfg_reply_alloc(0);
55}
56
57static inline struct sk_buff *cfg_reply_unsigned(u32 value)
58{
59 return cfg_reply_unsigned_type(TIPC_TLV_UNSIGNED, value);
60}
61
62static inline struct sk_buff *cfg_reply_error_string(char *string)
63{
64 return cfg_reply_string_type(TIPC_TLV_ERROR_STRING, string);
65}
66
67static inline struct sk_buff *cfg_reply_ultra_string(char *string)
68{
69 return cfg_reply_string_type(TIPC_TLV_ULTRA_STRING, string);
70}
71
72struct sk_buff *cfg_do_cmd(u32 orig_node, u16 cmd,
73 const void *req_tlv_area, int req_tlv_space,
74 int headroom);
75
76void cfg_link_event(u32 addr, char *name, int up);
77int cfg_init(void);
78void 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
52int eth_media_start(void);
53void eth_media_stop(void);
54int handler_start(void);
55void handler_stop(void);
56int socket_init(void);
57void socket_stop(void);
58int netlink_start(void);
59void 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
89int tipc_mode = TIPC_NOT_RUNNING;
90int tipc_random;
91atomic_t tipc_user_count = ATOMIC_INIT(0);
92
93const char tipc_alphabet[] =
94 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
95
96/* configurable TIPC parameters */
97
98u32 tipc_own_addr;
99int tipc_max_zones;
100int tipc_max_clusters;
101int tipc_max_nodes;
102int tipc_max_slaves;
103int tipc_max_ports;
104int tipc_max_subscriptions;
105int tipc_max_publications;
106int tipc_net_id;
107int tipc_remote_management;
108
109
110int tipc_get_mode(void)
111{
112 return tipc_mode;
113}
114
115/**
116 * stop_net - shut down TIPC networking sub-systems
117 */
118
119void 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
129int 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
144void 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
165int 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
190static 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
215static void __exit tipc_exit(void)
216{
217 stop_net();
218 stop_core();
219 info("Deactivated\n");
220 log_stop();
221}
222
223module_init(tipc_init);
224module_exit(tipc_exit);
225
226MODULE_DESCRIPTION("TIPC: Transparent Inter Process Communication");
227MODULE_LICENSE("Dual BSD/GPL");
228
229/* Native TIPC API for kernel-space applications (see tipc.h) */
230
231EXPORT_SYMBOL(tipc_attach);
232EXPORT_SYMBOL(tipc_detach);
233EXPORT_SYMBOL(tipc_get_addr);
234EXPORT_SYMBOL(tipc_get_mode);
235EXPORT_SYMBOL(tipc_createport);
236EXPORT_SYMBOL(tipc_deleteport);
237EXPORT_SYMBOL(tipc_ownidentity);
238EXPORT_SYMBOL(tipc_portimportance);
239EXPORT_SYMBOL(tipc_set_portimportance);
240EXPORT_SYMBOL(tipc_portunreliable);
241EXPORT_SYMBOL(tipc_set_portunreliable);
242EXPORT_SYMBOL(tipc_portunreturnable);
243EXPORT_SYMBOL(tipc_set_portunreturnable);
244EXPORT_SYMBOL(tipc_publish);
245EXPORT_SYMBOL(tipc_withdraw);
246EXPORT_SYMBOL(tipc_connect2port);
247EXPORT_SYMBOL(tipc_disconnect);
248EXPORT_SYMBOL(tipc_shutdown);
249EXPORT_SYMBOL(tipc_isconnected);
250EXPORT_SYMBOL(tipc_peer);
251EXPORT_SYMBOL(tipc_ref_valid);
252EXPORT_SYMBOL(tipc_send);
253EXPORT_SYMBOL(tipc_send_buf);
254EXPORT_SYMBOL(tipc_send2name);
255EXPORT_SYMBOL(tipc_forward2name);
256EXPORT_SYMBOL(tipc_send_buf2name);
257EXPORT_SYMBOL(tipc_forward_buf2name);
258EXPORT_SYMBOL(tipc_send2port);
259EXPORT_SYMBOL(tipc_forward2port);
260EXPORT_SYMBOL(tipc_send_buf2port);
261EXPORT_SYMBOL(tipc_forward_buf2port);
262EXPORT_SYMBOL(tipc_multicast);
263/* EXPORT_SYMBOL(tipc_multicast_buf); not available yet */
264EXPORT_SYMBOL(tipc_ispublished);
265EXPORT_SYMBOL(tipc_available_nodes);
266
267/* TIPC API for external bearers (see tipc_bearer.h) */
268
269EXPORT_SYMBOL(tipc_block_bearer);
270EXPORT_SYMBOL(tipc_continue);
271EXPORT_SYMBOL(tipc_disable_bearer);
272EXPORT_SYMBOL(tipc_enable_bearer);
273EXPORT_SYMBOL(tipc_recv_msg);
274EXPORT_SYMBOL(tipc_register_media);
275
276/* TIPC API for external APIs (see tipc_port.h) */
277
278EXPORT_SYMBOL(tipc_createport_raw);
279EXPORT_SYMBOL(tipc_set_msg_option);
280EXPORT_SYMBOL(tipc_reject_msg);
281EXPORT_SYMBOL(tipc_send_buf_fast);
282EXPORT_SYMBOL(tipc_acknowledge);
283EXPORT_SYMBOL(tipc_get_port);
284EXPORT_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
62struct tipc_msg;
63extern struct print_buf *CONS, *LOG;
64extern struct print_buf *TEE(struct print_buf *, struct print_buf *);
65void msg_print(struct print_buf*,struct tipc_msg *,const char*);
66void tipc_printf(struct print_buf *, const char *fmt, ...);
67void 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
140extern u32 tipc_own_addr;
141extern int tipc_max_zones;
142extern int tipc_max_clusters;
143extern int tipc_max_nodes;
144extern int tipc_max_slaves;
145extern int tipc_max_ports;
146extern int tipc_max_subscriptions;
147extern int tipc_max_publications;
148extern int tipc_net_id;
149extern int tipc_remote_management;
150
151/*
152 * Other global variables
153 */
154
155extern int tipc_mode;
156extern int tipc_random;
157extern const char tipc_alphabet[];
158extern atomic_t tipc_user_count;
159
160
161/*
162 * Routines available to privileged subsystems
163 */
164
165extern int start_core(void);
166extern void stop_core(void);
167extern int start_net(void);
168extern void stop_net(void);
169
170static 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
184typedef void (*Handler) (unsigned long);
185
186u32 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
197static 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
220static 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
237static 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
255static 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
270struct tipc_skb_cb {
271 void *handle;
272};
273
274#define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0]))
275
276
277static 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
289static 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
310static 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
43static char print_string[MAX_STRING];
44static spinlock_t print_lock = SPIN_LOCK_UNLOCKED;
45
46static struct print_buf cons_buf = { NULL, 0, NULL, NULL };
47struct print_buf *CONS = &cons_buf;
48
49static struct print_buf log_buf = { NULL, 0, NULL, NULL };
50struct 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
77void 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
93void 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
103int 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
117int 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
149void 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
189void 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
229struct 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
254static 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
274static 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
292void 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
316void 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
330void 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
347struct 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
367struct 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
40struct print_buf {
41 char *buf;
42 u32 size;
43 char *crs;
44 struct print_buf *next;
45};
46
47void printbuf_init(struct print_buf *pb, char *buf, u32 sz);
48void printbuf_reset(struct print_buf *pb);
49int printbuf_empty(struct print_buf *pb);
50int printbuf_validate(struct print_buf *pb);
51void printbuf_move(struct print_buf *pb_to, struct print_buf *pb_from);
52
53void log_reinit(int log_size);
54void log_stop(void);
55
56struct sk_buff *log_resize(const void *req_tlv_area, int req_tlv_space);
57struct 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 */
73struct 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
83int 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
96void 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
113struct 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
139void 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
219void 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
235void 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
262static 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
294struct 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
42struct link_req;
43
44struct 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);
48void disc_update_link_req(struct link_req *req);
49void disc_stop_link_req(struct link_req *req);
50
51void disc_recv_msg(struct sk_buff *buf);
52
53void disc_link_event(u32 addr, char *name, int up);
54#if 0
55int 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
56struct eth_bearer {
57 struct tipc_bearer *bearer;
58 struct net_device *dev;
59 struct packet_type tipc_packet_type;
60};
61
62static struct eth_bearer eth_bearers[MAX_ETH_BEARERS];
63static int eth_started = 0;
64static struct notifier_block notifier;
65
66/**
67 * send_msg - send a TIPC message out over an Ethernet interface
68 */
69
70static 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
96static 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
121static int enable_bearer(struct tipc_bearer *tb_ptr)
122{
123 struct net_device *dev = dev_base;
124 struct eth_bearer *eb_ptr = &eth_bearers[0];
125 struct eth_bearer *stop = &eth_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
172static 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
184static 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 = &eth_bearers[0];
189 struct eth_bearer *stop = &eth_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
230static 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
249int 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(&notifier);
270 if (!res)
271 eth_started = 1;
272 return res;
273}
274
275/**
276 * eth_media_stop - deactivate Ethernet bearer support
277 */
278
279void eth_media_stop(void)
280{
281 int i;
282
283 if (!eth_started)
284 return;
285
286 unregister_netdevice_notifier(&notifier);
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(&eth_bearers[i].tipc_packet_type);
294 dev_put(eth_bearers[i].dev);
295 }
296 }
297 memset(&eth_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
39struct queue_item {
40 struct list_head next_signal;
41 void (*handler) (unsigned long);
42 unsigned long data;
43};
44
45static kmem_cache_t *tipc_queue_item_cache;
46static struct list_head signal_queue_head;
47static spinlock_t qitem_lock = SPIN_LOCK_UNLOCKED;
48static int handler_enabled = 0;
49
50static void process_signal_queue(unsigned long dummy);
51
52static DECLARE_TASKLET_DISABLED(tipc_tasklet, process_signal_queue, 0);
53
54
55unsigned 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
79static 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
96int 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
110void 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
89struct 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
104struct 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
113static void link_handle_out_of_seq_msg(struct link *l_ptr,
114 struct sk_buff *buf);
115static void link_recv_proto_msg(struct link *l_ptr, struct sk_buff *buf);
116static int link_recv_changeover_msg(struct link **l_ptr, struct sk_buff **buf);
117static void link_set_supervision_props(struct link *l_ptr, u32 tolerance);
118static int link_send_sections_long(struct port *sender,
119 struct iovec const *msg_sect,
120 u32 num_sect, u32 destnode);
121static void link_check_defragm_bufs(struct link *l_ptr);
122static void link_state_event(struct link *l_ptr, u32 event);
123static void link_reset_statistics(struct link *l_ptr);
124static 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
160static 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
166static 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
182static inline unsigned int align(unsigned int i)
183{
184 return (i + 3) & ~3u;
185}
186
187static inline int link_working_working(struct link *l_ptr)
188{
189 return (l_ptr->state == WORKING_WORKING);
190}
191
192static inline int link_working_unknown(struct link *l_ptr)
193{
194 return (l_ptr->state == WORKING_UNKNOWN);
195}
196
197static inline int link_reset_unknown(struct link *l_ptr)
198{
199 return (l_ptr->state == RESET_UNKNOWN);
200}
201
202static inline int link_reset_reset(struct link *l_ptr)
203{
204 return (l_ptr->state == RESET_RESET);
205}
206
207static inline int link_blocked(struct link *l_ptr)
208{
209 return (l_ptr->exp_msg_count || l_ptr->blocked);
210}
211
212static inline int link_congested(struct link *l_ptr)
213{
214 return (l_ptr->out_queue_size >= l_ptr->queue_limit[0]);
215}
216
217static inline u32 link_max_pkt(struct link *l_ptr)
218{
219 return l_ptr->max_pkt;
220}
221
222static 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
239static 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
246static 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
255int 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
262int 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
276static 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
347static 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
399static 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
413struct 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
495void 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
518void 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
534static 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++;
550exit:
551 port_unlock(p_ptr);
552 }
553 spin_unlock_bh(&port_list_lock);
554 return -ELINKCONG;
555}
556
557void 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
585exit:
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
594static 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
613void 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
631void 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
660static void link_recv_event(struct link_event *ev)
661{
662 ev->fcn(ev->addr, ev->name, ev->up);
663 kfree(ev);
664}
665
666static 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
689void 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
756static 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
772static 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
978static 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
1007static 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
1031int 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
1127int 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
1159static 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 */
1194int 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 */
1233int 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
1247again:
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);
1267exit:
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 */
1331static 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
1348again:
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)) {
1401error:
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 {
1465reject:
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 */
1502u32 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 */
1592void 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
1607void 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
1661static 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
1675static 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
1693void 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
1763protocol_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))) {
1771deliver:
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);
1849cont:
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
1861u32 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
1914static 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 */
1955void 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
2071static 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 }
2195exit:
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 */
2204void 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
2235void 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
2293void 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
2341static 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
2358static 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 }
2430exit:
2431 *buf = 0;
2432 buf_discard(tunnel_buf);
2433 return 0;
2434}
2435
2436/*
2437 * Bundler functionality:
2438 */
2439void 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 */
2474int 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 }
2532exit:
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
2544static inline u32 get_long_msg_seqno(struct sk_buff *buf)
2545{
2546 return msg_seqno(buf_msg(buf));
2547}
2548
2549static inline void set_long_msg_seqno(struct sk_buff *buf, u32 seqno)
2550{
2551 msg_set_seqno(buf_msg(buf), seqno);
2552}
2553
2554static inline u32 get_fragm_size(struct sk_buff *buf)
2555{
2556 return msg_ack(buf_msg(buf));
2557}
2558
2559static inline void set_fragm_size(struct sk_buff *buf, u32 sz)
2560{
2561 msg_set_ack(buf_msg(buf), sz);
2562}
2563
2564static inline u32 get_expected_frags(struct sk_buff *buf)
2565{
2566 return msg_bcast_ack(buf_msg(buf));
2567}
2568
2569static inline void set_expected_frags(struct sk_buff *buf, u32 exp)
2570{
2571 msg_set_bcast_ack(buf_msg(buf), exp);
2572}
2573
2574static inline u32 get_timer_cnt(struct sk_buff *buf)
2575{
2576 return msg_reroute_cnt(buf_msg(buf));
2577}
2578
2579static 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 */
2588int 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
2673static 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
2708static 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
2717void 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
2748static 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
2772struct 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
2844static 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
2851struct 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
2885static 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
2899static 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
2985struct 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
3014int 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
3059u32 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
3082static 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
3103static 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
3116static 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
114struct 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
222struct port;
223
224struct link *link_create(struct bearer *b_ptr, const u32 peer,
225 const struct tipc_media_addr *media_addr);
226void link_delete(struct link *l_ptr);
227void link_changeover(struct link *l_ptr);
228void link_send_duplicate(struct link *l_ptr, struct link *dest);
229void link_reset_fragments(struct link *l_ptr);
230int link_is_up(struct link *l_ptr);
231int link_is_active(struct link *l_ptr);
232void link_start(struct link *l_ptr);
233u32 link_push_packet(struct link *l_ptr);
234void link_stop(struct link *l_ptr);
235struct sk_buff *link_cmd_config(const void *req_tlv_area, int req_tlv_space, u16 cmd);
236struct sk_buff *link_cmd_show_stats(const void *req_tlv_area, int req_tlv_space);
237struct sk_buff *link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_space);
238void link_reset(struct link *l_ptr);
239int link_send(struct sk_buff *buf, u32 dest, u32 selector);
240int link_send_buf(struct link *l_ptr, struct sk_buff *buf);
241u32 link_get_max_pkt(u32 dest,u32 selector);
242int link_send_sections_fast(struct port* sender,
243 struct iovec const *msg_sect,
244 const u32 num_sect,
245 u32 destnode);
246
247int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf);
248void link_tunnel(struct link *l_ptr, struct tipc_msg *tnl_hdr,
249 struct tipc_msg *msg, u32 selector);
250void link_recv_bundle(struct sk_buff *buf);
251int link_recv_fragment(struct sk_buff **pending,
252 struct sk_buff **fb,
253 struct tipc_msg **msg);
254void link_send_proto_msg(struct link *l_ptr, u32 msg_typ, int prob, u32 gap,
255 u32 tolerance, u32 priority, u32 acked_mtu);
256void link_push_queue(struct link *l_ptr);
257u32 link_defer_pkt(struct sk_buff **head, struct sk_buff **tail,
258 struct sk_buff *buf);
259void link_wakeup_ports(struct link *l_ptr, int all);
260void link_set_queue_limits(struct link *l_ptr, u32 window);
261void 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
267static inline u32 mod(u32 x)
268{
269 return x & 0xffffu;
270}
271
272static 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
281static inline int less_eq(u32 left, u32 right)
282{
283 return (mod(right - left) < 32768u);
284}
285
286static inline int less(u32 left, u32 right)
287{
288 return (less_eq(left, right) && (mod(right) != mod(left)));
289}
290
291static 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
44void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a)
45{
46 memcpy(&((int *)m)[5], a, sizeof(*a));
47}
48
49void 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
55void 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
66static inline void msg_set_word(struct tipc_msg *m, u32 w, u32 val)
67{
68 m->hdr[w] = htonl(val);
69}
70
71static 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
82static inline u32 msg_version(struct tipc_msg *m)
83{
84 return msg_bits(m, 0, 29, 7);
85}
86
87static inline void msg_set_version(struct tipc_msg *m)
88{
89 msg_set_bits(m, 0, 29, 0xf, TIPC_VERSION);
90}
91
92static inline u32 msg_user(struct tipc_msg *m)
93{
94 return msg_bits(m, 0, 25, 0xf);
95}
96
97static inline u32 msg_isdata(struct tipc_msg *m)
98{
99 return (msg_user(m) <= DATA_CRITICAL);
100}
101
102static inline void msg_set_user(struct tipc_msg *m, u32 n)
103{
104 msg_set_bits(m, 0, 25, 0xf, n);
105}
106
107static inline void msg_set_importance(struct tipc_msg *m, u32 i)
108{
109 msg_set_user(m, i);
110}
111
112static 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
117static inline int msg_non_seq(struct tipc_msg *m)
118{
119 return msg_bits(m, 0, 20, 1);
120}
121
122static inline void msg_set_non_seq(struct tipc_msg *m)
123{
124 msg_set_bits(m, 0, 20, 1, 1);
125}
126
127static inline int msg_dest_droppable(struct tipc_msg *m)
128{
129 return msg_bits(m, 0, 19, 1);
130}
131
132static inline void msg_set_dest_droppable(struct tipc_msg *m, u32 d)
133{
134 msg_set_bits(m, 0, 19, 1, d);
135}
136
137static inline int msg_src_droppable(struct tipc_msg *m)
138{
139 return msg_bits(m, 0, 18, 1);
140}
141
142static inline void msg_set_src_droppable(struct tipc_msg *m, u32 d)
143{
144 msg_set_bits(m, 0, 18, 1, d);
145}
146
147static 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
157static inline void msg_set_type(struct tipc_msg *m, u32 n)
158{
159 msg_set_bits(m, 1, 29, 0x7, n);
160}
161
162static inline void msg_set_errcode(struct tipc_msg *m, u32 err)
163{
164 msg_set_bits(m, 1, 25, 0xf, err);
165}
166
167static inline u32 msg_reroute_cnt(struct tipc_msg *m)
168{
169 return msg_bits(m, 1, 21, 0xf);
170}
171
172static 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
177static inline void msg_reset_reroute_cnt(struct tipc_msg *m)
178{
179 msg_set_bits(m, 1, 21, 0xf, 0);
180}
181
182static inline u32 msg_lookup_scope(struct tipc_msg *m)
183{
184 return msg_bits(m, 1, 19, 0x3);
185}
186
187static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n)
188{
189 msg_set_bits(m, 1, 19, 0x3, n);
190}
191
192static 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
204static inline u32 msg_bcast_ack(struct tipc_msg *m)
205{
206 return msg_bits(m, 1, 0, 0xffff);
207}
208
209static 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
219static inline u32 msg_ack(struct tipc_msg *m)
220{
221 return msg_bits(m, 2, 16, 0xffff);
222}
223
224static inline void msg_set_ack(struct tipc_msg *m, u32 n)
225{
226 msg_set_bits(m, 2, 16, 0xffff, n);
227}
228
229static inline u32 msg_seqno(struct tipc_msg *m)
230{
231 return msg_bits(m, 2, 0, 0xffff);
232}
233
234static 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
245static inline void msg_set_prevnode(struct tipc_msg *m, u32 a)
246{
247 msg_set_word(m, 3, a);
248}
249
250static inline void msg_set_origport(struct tipc_msg *m, u32 p)
251{
252 msg_set_word(m, 4, p);
253}
254
255static inline void msg_set_destport(struct tipc_msg *m, u32 p)
256{
257 msg_set_word(m, 5, p);
258}
259
260static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p)
261{
262 msg_set_word(m, 5, p);
263}
264
265static inline void msg_set_orignode(struct tipc_msg *m, u32 a)
266{
267 msg_set_word(m, 6, a);
268}
269
270static inline void msg_set_destnode(struct tipc_msg *m, u32 a)
271{
272 msg_set_word(m, 7, a);
273}
274
275static inline int msg_is_dest(struct tipc_msg *m, u32 d)
276{
277 return(msg_short(m) || (msg_destnode(m) == d));
278}
279
280static 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
287static inline void msg_set_nametype(struct tipc_msg *m, u32 n)
288{
289 msg_set_word(m, 8, n);
290}
291
292static inline u32 msg_transp_seqno(struct tipc_msg *m)
293{
294 return msg_word(m, 8);
295}
296
297static inline void msg_set_timestamp(struct tipc_msg *m, u32 n)
298{
299 msg_set_word(m, 8, n);
300}
301
302static inline u32 msg_timestamp(struct tipc_msg *m)
303{
304 return msg_word(m, 8);
305}
306
307static inline void msg_set_transp_seqno(struct tipc_msg *m, u32 n)
308{
309 msg_set_word(m, 8, n);
310}
311
312static inline void msg_set_namelower(struct tipc_msg *m, u32 n)
313{
314 msg_set_word(m, 9, n);
315}
316
317static inline void msg_set_nameinst(struct tipc_msg *m, u32 n)
318{
319 msg_set_namelower(m, n);
320}
321
322static inline void msg_set_nameupper(struct tipc_msg *m, u32 n)
323{
324 msg_set_word(m, 10, n);
325}
326
327static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m)
328{
329 return (struct tipc_msg *)msg_data(m);
330}
331
332static 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
413static inline u32 msg_seq_gap(struct tipc_msg *m)
414{
415 return msg_bits(m, 1, 16, 0xff);
416}
417
418static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n)
419{
420 msg_set_bits(m, 1, 16, 0xff, n);
421}
422
423static inline u32 msg_req_links(struct tipc_msg *m)
424{
425 return msg_bits(m, 1, 16, 0xfff);
426}
427
428static 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
438static inline u32 msg_dest_domain(struct tipc_msg *m)
439{
440 return msg_word(m, 2);
441}
442
443static inline void msg_set_dest_domain(struct tipc_msg *m, u32 n)
444{
445 msg_set_word(m, 2, n);
446}
447
448static inline u32 msg_bcgap_after(struct tipc_msg *m)
449{
450 return msg_bits(m, 2, 16, 0xffff);
451}
452
453static inline void msg_set_bcgap_after(struct tipc_msg *m, u32 n)
454{
455 msg_set_bits(m, 2, 16, 0xffff, n);
456}
457
458static inline u32 msg_bcgap_to(struct tipc_msg *m)
459{
460 return msg_bits(m, 2, 0, 0xffff);
461}
462
463static 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
473static inline u32 msg_last_bcast(struct tipc_msg *m)
474{
475 return msg_bits(m, 4, 16, 0xffff);
476}
477
478static 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
484static inline u32 msg_fragm_no(struct tipc_msg *m)
485{
486 return msg_bits(m, 4, 16, 0xffff);
487}
488
489static 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
495static inline u32 msg_next_sent(struct tipc_msg *m)
496{
497 return msg_bits(m, 4, 0, 0xffff);
498}
499
500static 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
506static inline u32 msg_long_msgno(struct tipc_msg *m)
507{
508 return msg_bits(m, 4, 0, 0xffff);
509}
510
511static inline void msg_set_long_msgno(struct tipc_msg *m, u32 n)
512{
513 msg_set_bits(m, 4, 0, 0xffff, n);
514}
515
516static inline u32 msg_bc_netid(struct tipc_msg *m)
517{
518 return msg_word(m, 4);
519}
520
521static inline void msg_set_bc_netid(struct tipc_msg *m, u32 id)
522{
523 msg_set_word(m, 4, id);
524}
525
526static inline u32 msg_link_selector(struct tipc_msg *m)
527{
528 return msg_bits(m, 4, 0, 1);
529}
530
531static 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
540static inline u32 msg_session(struct tipc_msg *m)
541{
542 return msg_bits(m, 5, 16, 0xffff);
543}
544
545static inline void msg_set_session(struct tipc_msg *m, u32 n)
546{
547 msg_set_bits(m, 5, 16, 0xffff, n);
548}
549
550static inline u32 msg_probe(struct tipc_msg *m)
551{
552 return msg_bits(m, 5, 0, 1);
553}
554
555static inline void msg_set_probe(struct tipc_msg *m, u32 val)
556{
557 msg_set_bits(m, 5, 0, 1, (val & 1));
558}
559
560static inline char msg_net_plane(struct tipc_msg *m)
561{
562 return msg_bits(m, 5, 1, 7) + 'A';
563}
564
565static 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
570static inline u32 msg_linkprio(struct tipc_msg *m)
571{
572 return msg_bits(m, 5, 4, 0x1f);
573}
574
575static inline void msg_set_linkprio(struct tipc_msg *m, u32 n)
576{
577 msg_set_bits(m, 5, 4, 0x1f, n);
578}
579
580static inline u32 msg_bearer_id(struct tipc_msg *m)
581{
582 return msg_bits(m, 5, 9, 0x7);
583}
584
585static inline void msg_set_bearer_id(struct tipc_msg *m, u32 n)
586{
587 msg_set_bits(m, 5, 9, 0x7, n);
588}
589
590static inline u32 msg_redundant_link(struct tipc_msg *m)
591{
592 return msg_bits(m, 5, 12, 0x1);
593}
594
595static inline void msg_set_redundant_link(struct tipc_msg *m)
596{
597 msg_set_bits(m, 5, 12, 0x1, 1);
598}
599
600static 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
610static inline u32 msg_msgcnt(struct tipc_msg *m)
611{
612 return msg_bits(m, 9, 16, 0xffff);
613}
614
615static inline void msg_set_msgcnt(struct tipc_msg *m, u32 n)
616{
617 msg_set_bits(m, 9, 16, 0xffff, n);
618}
619
620static inline u32 msg_bcast_tag(struct tipc_msg *m)
621{
622 return msg_bits(m, 9, 16, 0xffff);
623}
624
625static inline void msg_set_bcast_tag(struct tipc_msg *m, u32 n)
626{
627 msg_set_bits(m, 9, 16, 0xffff, n);
628}
629
630static inline u32 msg_max_pkt(struct tipc_msg *m)
631{
632 return (msg_bits(m, 9, 16, 0xffff) * 4);
633}
634
635static 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
640static inline u32 msg_link_tolerance(struct tipc_msg *m)
641{
642 return msg_bits(m, 9, 0, 0xffff);
643}
644
645static 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
655static inline u32 msg_remote_node(struct tipc_msg *m)
656{
657 return msg_word(m, msg_hdr_sz(m)/4);
658}
659
660static 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
665static inline int msg_dataoctet(struct tipc_msg *m, u32 pos)
666{
667 return(msg_data(m)[pos + 4] != 0);
668}
669
670static 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
713static 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
727static 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
748static 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
766static 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
809struct tipc_media_addr;
810
811extern void msg_set_media_addr(struct tipc_msg *m,
812 struct tipc_media_addr *a);
813
814extern 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
68struct 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
81static LIST_HEAD(publ_root);
82static u32 publ_cnt = 0;
83
84/**
85 * publ_to_item - add publication info to a publication message
86 */
87
88static 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
102static 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
120void 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
144void 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
168void 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 }
206exit:
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
221static 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
240void 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
298void 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
42void named_publish(struct publication *publ);
43void named_withdraw(struct publication *publ);
44void named_node_up(unsigned long node);
45void named_recv(struct sk_buff *buf);
46void 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
49int 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
60struct 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
80struct 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
97struct name_table {
98 struct hlist_head *types;
99 u32 local_publ_count;
100};
101
102struct name_table table = { NULL } ;
103static atomic_t rsv_publ_ok = ATOMIC_INIT(0);
104rwlock_t nametbl_lock = RW_LOCK_UNLOCKED;
105
106
107static 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
116static 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
145struct 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
161struct 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
193static 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
223static 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
246struct 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
372struct 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
490void 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
521static 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
541struct 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
566struct 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
594u32 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;
618found:
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);
658not_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
677int 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);
711exit:
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
720int 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
735struct 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
766int 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
790void
791nametbl_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
816void
817nametbl_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
841static 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
886static 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
912static 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
939static 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
986void 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
996struct 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
1026void nametbl_dump(void)
1027{
1028 nametbl_list(CONS, 0, 0, 0, 0);
1029}
1030
1031int 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
1046void 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
42struct subscription;
43struct 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
71struct 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
88extern rwlock_t nametbl_lock;
89
90struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space);
91u32 nametbl_translate(u32 type, u32 instance, u32 *node);
92int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
93 struct port_list *dports);
94int nametbl_publish_rsv(u32 ref, unsigned int scope,
95 struct tipc_name_seq const *seq);
96struct publication *nametbl_publish(u32 type, u32 lower, u32 upper,
97 u32 scope, u32 port_ref, u32 key);
98int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key);
99struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper,
100 u32 scope, u32 node, u32 ref, u32 key);
101struct publication *nametbl_remove_publ(u32 type, u32 lower,
102 u32 node, u32 ref, u32 key);
103void nametbl_subscribe(struct subscription *s);
104void nametbl_unsubscribe(struct subscription *s);
105int nametbl_init(void);
106void 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
118rwlock_t net_lock = RW_LOCK_UNLOCKED;
119struct network net = { 0 };
120
121struct 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
126u32 net_select_router(u32 addr, u32 ref)
127{
128 return zone_select_router(net.zones[tipc_zone(addr)], addr, ref);
129}
130
131
132u32 net_next_node(u32 a)
133{
134 if (net.zones[tipc_zone(a)])
135 return zone_next_node(a);
136 return 0;
137}
138
139void 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
150void 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
160int 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
173void 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
187static 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
213void 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
271int 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
299void 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
40struct _zone;
41
42/**
43 * struct network - TIPC network structure
44 * @zones: array of pointers to all zones within network
45 */
46
47struct network {
48 struct _zone **zones;
49};
50
51
52extern struct network net;
53extern rwlock_t net_lock;
54
55int net_init(void);
56void net_stop(void);
57void net_remove_as_router(u32 router);
58void net_send_external_routes(u32 dest);
59void net_route_msg(struct sk_buff *buf);
60struct node *net_select_remote_node(u32 addr, u32 ref);
61u32 net_select_router(u32 addr, u32 ref);
62
63int tipc_start_net(void);
64void 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
41static 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
69static 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
77static struct genl_ops ops = {
78 .cmd = TIPC_GENL_CMD,
79 .doit = handle_cmd,
80};
81
82static int family_registered = 0;
83
84int 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
106void 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
50void node_print(struct print_buf *buf, struct node *n_ptr, char *str);
51static void node_lost_contact(struct node *n_ptr);
52static void node_established_contact(struct node *n_ptr);
53
54struct node *nodes = NULL; /* sorted list of nodes within cluster */
55
56u32 tipc_own_tag = 0;
57
58struct 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
96void 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
122void 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
153static 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
181void 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
206int 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
212int 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
218int node_has_active_routes(struct node *n_ptr)
219{
220 return (n_ptr && (n_ptr->last_router >= 0));
221}
222
223int node_is_up(struct node *n_ptr)
224{
225 return (node_has_active_links(n_ptr) || node_has_active_routes(n_ptr));
226}
227
228struct 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
260void 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
313static 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
359static 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
441struct 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
488u32 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
526void 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
537void 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
555void 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
570u32 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
584struct 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
625struct 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
70struct 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
95extern struct node *nodes;
96extern u32 tipc_own_tag;
97
98struct node *node_create(u32 addr);
99void node_delete(struct node *n_ptr);
100struct node *node_attach_link(struct link *l_ptr);
101void node_detach_link(struct node *n_ptr, struct link *l_ptr);
102void node_link_down(struct node *n_ptr, struct link *l_ptr);
103void node_link_up(struct node *n_ptr, struct link *l_ptr);
104int node_has_active_links(struct node *n_ptr);
105int node_has_redundant_links(struct node *n_ptr);
106u32 node_select_router(struct node *n_ptr, u32 ref);
107struct node *node_select_next_hop(u32 addr, u32 selector);
108int node_is_up(struct node *n_ptr);
109void node_add_router(struct node *n_ptr, u32 router);
110void node_remove_router(struct node *n_ptr, u32 router);
111struct sk_buff *node_get_links(const void *req_tlv_area, int req_tlv_space);
112struct sk_buff *node_get_nodes(const void *req_tlv_area, int req_tlv_space);
113
114static 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
127static 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
134static inline void node_lock(struct node *n_ptr)
135{
136 spin_lock_bh(&n_ptr->lock);
137}
138
139static 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
47void 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
71void 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
42typedef 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
52struct 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
59void nodesub_subscribe(struct node_subscr *node_sub, u32 addr,
60 void *usr_handle, net_ev_handler handle_down);
61void 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
57static struct sk_buff *msg_queue_head = 0;
58static struct sk_buff *msg_queue_tail = 0;
59
60spinlock_t port_list_lock = SPIN_LOCK_UNLOCKED;
61static spinlock_t queue_lock = SPIN_LOCK_UNLOCKED;
62
63LIST_HEAD(ports);
64static void port_handle_node_down(unsigned long ref);
65static struct sk_buff* port_build_self_abort_msg(struct port *,u32 err);
66static struct sk_buff* port_build_peer_abort_msg(struct port *,u32 err);
67static void port_timeout(unsigned long ref);
68
69
70static inline u32 port_peernode(struct port *p_ptr)
71{
72 return msg_destnode(&p_ptr->publ.phdr);
73}
74
75static inline u32 port_peerport(struct port *p_ptr)
76{
77 return msg_destport(&p_ptr->publ.phdr);
78}
79
80static inline u32 port_out_seqno(struct port *p_ptr)
81{
82 return msg_transp_seqno(&p_ptr->publ.phdr);
83}
84
85static 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
90static 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
103int 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
169void 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 }
215exit:
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
226u32 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
276int 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
316struct 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
325void *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
338static inline int port_unreliable(struct port *p_ptr)
339{
340 return msg_src_droppable(&p_ptr->publ.phdr);
341}
342
343int 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
355int 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
367static inline int port_unreturnable(struct port *p_ptr)
368{
369 return msg_dest_droppable(&p_ptr->publ.phdr);
370}
371
372int 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
384int 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 */
401static 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
424int 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
431int 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
495int 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
510static 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
540static 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
553static 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
573static 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
592void 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);
660exit:
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
668static 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
707struct 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
740struct 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
780void 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
801static 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;
906err:
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;
959reject:
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
970static 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
990static 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
1011static void port_wakeup(struct tipc_port *p_ptr)
1012{
1013 k_signal((Handler)port_wakeup_sh, p_ptr->ref);
1014}
1015
1016void 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
1045int 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
1091int 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
1098int 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
1110int 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
1126int 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 }
1158exit:
1159 port_unlock(p_ptr);
1160 return res;
1161}
1162
1163int 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;
1201exit:
1202 port_unlock(p_ptr);
1203 return res;
1204}
1205
1206int 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;
1241exit:
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
1252int 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 */
1273int 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
1301int 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
1313int 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
1331int 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
1343int 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
1360int 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
1398int 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
1447int 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
1501int 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
1519int 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
1575int 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
1593int 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
1634int 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 */
1650int 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
1696int 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
56struct 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
92struct 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
113extern spinlock_t port_list_lock;
114struct port_list;
115
116int port_recv_sections(struct port *p_ptr, u32 num_sect,
117 struct iovec const *msg_sect);
118int port_reject_sections(struct port *p_ptr, struct tipc_msg *hdr,
119 struct iovec const *msg_sect, u32 num_sect,
120 int err);
121struct sk_buff *port_get_ports(void);
122struct sk_buff *port_show_stats(const void *req_tlv_area, int req_tlv_space);
123void port_recv_proto_msg(struct sk_buff *buf);
124void port_recv_mcast(struct sk_buff *buf, struct port_list *dp);
125void port_reinit(void);
126
127/**
128 * port_lock - lock port instance referred to and return its pointer
129 */
130
131static 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
142static inline void port_unlock(struct port *p_ptr)
143{
144 spin_unlock_bh(p_ptr->publ.lock);
145}
146
147static inline struct port* port_deref(u32 ref)
148{
149 return (struct port *)ref_deref(ref);
150}
151
152static inline u32 peer_port(struct port *p_ptr)
153{
154 return msg_destport(&p_ptr->publ.phdr);
155}
156
157static inline u32 peer_node(struct port *p_ptr)
158{
159 return msg_destnode(&p_ptr->publ.phdr);
160}
161
162static 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
171static 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 }
204reject:
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
64struct ref_table ref_table = { 0 };
65
66rwlock_t reftbl_lock = RW_LOCK_UNLOCKED;
67
68/**
69 * ref_table_init - create reference table for objects
70 */
71
72int 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
105void 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
122u32 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
159void 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
47struct 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
64struct ref_table {
65 struct reference *entries;
66 u32 index_mask;
67 u32 first_free;
68 u32 last_free;
69};
70
71extern struct ref_table ref_table;
72
73int ref_table_init(u32 requested_size, u32 start);
74void ref_table_stop(void);
75
76u32 ref_acquire(void *object, spinlock_t **lock);
77void ref_discard(u32 ref);
78
79
80/**
81 * ref_lock - lock referenced object and return pointer to it
82 */
83
84static 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
102static 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
119static 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
65struct 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
73static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
74static void wakeupdispatch(struct tipc_port *tport);
75
76static struct proto_ops packet_ops;
77static struct proto_ops stream_ops;
78static struct proto_ops msg_ops;
79
80static struct proto tipc_proto;
81
82static int sockets_enabled = 0;
83
84static 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 */
93static 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 */
101static 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
124static 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
149static 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 */
167static 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
248static 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
314static 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);
350exit:
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
365static 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
398static 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
417static 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
452static 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)) {
522exit:
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
550static 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)) {
577exit:
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
606static 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
674static 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
700static 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
726static 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
793static 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
827restart:
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 }
907exit:
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
925static 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
962restart:
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
1054exit:
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
1068static 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
1093static 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
1108static 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
1209static 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
1226static 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
1301static 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
1322static 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 }
1383exit:
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
1398static 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);
1417restart:
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
1474static 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
1530static 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
1587static int ioctl(struct socket *s, u32 cmd, unsigned long arg)
1588{
1589 return -EINVAL;
1590}
1591
1592static int no_mmap(struct file *file, struct socket *sock,
1593 struct vm_area_struct *vma)
1594{
1595 return -EINVAL;
1596}
1597static ssize_t no_sendpage(struct socket *sock, struct page *page,
1598 int offset, size_t size, int flags)
1599{
1600 return -EINVAL;
1601}
1602
1603static 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
1612static 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
1633static 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
1654static 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
1675static struct net_proto_family tipc_family_ops = {
1676 .owner = THIS_MODULE,
1677 .family = AF_TIPC,
1678 .create = tipc_create
1679};
1680
1681static 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 */
1692int 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 */
1717void 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
53struct 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
71struct 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
79static 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
89static inline u32 htohl(u32 in, int swap)
90{
91 char *c = (char *)&in;
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
100static 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
126int 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
146void 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
167static 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
212static 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
261static 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
325static 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
348static 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
374static 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
454int 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
491failed:
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
499void 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
521int 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
52struct 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
63int subscr_overlap(struct subscription * sub,
64 u32 found_lower,
65 u32 found_upper);
66
67void 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
75int subscr_start(void);
76
77void 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
58struct 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
68static struct tipc_user *users = 0;
69static u32 next_free_user = MAX_USERID + 1;
70static 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
79static int reg_init(void)
80{
81 u32 i;
82
83 spin_lock_bh(&reg_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(&reg_lock);
95 return users ? TIPC_OK : -ENOMEM;
96}
97
98/**
99 * reg_callback - inform TIPC user about current operating mode
100 */
101
102static void reg_callback(struct tipc_user *user_ptr)
103{
104 tipc_mode_event cb;
105 void *arg;
106
107 spin_lock_bh(&reg_lock);
108 cb = user_ptr->callback;
109 arg = user_ptr->usr_handle;
110 spin_unlock_bh(&reg_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
120int 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
140void 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
161int 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(&reg_lock);
171 if (!next_free_user) {
172 spin_unlock_bh(&reg_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(&reg_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
195void 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(&reg_lock);
205 if ((!users) || (users[userid].next >= 0)) {
206 spin_unlock_bh(&reg_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(&reg_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
229int 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(&reg_lock);
241 user_ptr = &users[up_ptr->user_ref];
242 list_add(&up_ptr->uport_list, &user_ptr->ports);
243 spin_unlock_bh(&reg_lock);
244 return TIPC_OK;
245}
246
247/**
248 * reg_remove_port - deregister a user's driver port
249 */
250
251int 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(&reg_lock);
261 list_del_init(&up_ptr->uport_list);
262 spin_unlock_bh(&reg_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
42int reg_start(void);
43void reg_stop(void);
44
45int reg_add_port(struct user_port *up_ptr);
46int 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
45struct _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
63void 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
75void 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
85void 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
97void 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
110struct 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
137u32 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
161u32 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
51struct _zone {
52 u32 addr;
53 struct cluster *clusters[2]; /* currently limited to just 1 cluster */
54 u32 links;
55};
56
57struct node *zone_select_remote_node(struct _zone *z_ptr, u32 addr, u32 ref);
58u32 zone_select_router(struct _zone *z_ptr, u32 addr, u32 ref);
59void zone_remove_as_router(struct _zone *z_ptr, u32 router);
60void zone_send_external_routes(struct _zone *z_ptr, u32 dest);
61struct _zone *zone_create(u32 addr);
62void zone_delete(struct _zone *z_ptr);
63void zone_attach_cluster(struct _zone *z_ptr, struct cluster *c_ptr);
64u32 zone_next_node(u32 addr);
65
66static 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}