summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/proc_net_tcp.txt47
-rw-r--r--arch/i386/crypto/aes-i586-asm.S325
-rw-r--r--crypto/sha256.c10
-rw-r--r--crypto/sha512.c31
-rw-r--r--drivers/atm/horizon.c330
-rw-r--r--drivers/atm/horizon.h2
-rw-r--r--drivers/net/bonding/bond_main.c1
-rw-r--r--include/linux/atmdev.h1
-rw-r--r--include/linux/ipv6_route.h3
-rw-r--r--include/linux/net.h1
-rw-r--r--include/linux/netdevice.h2
-rw-r--r--include/linux/netfilter.h6
-rw-r--r--include/linux/netfilter_ipv4/ip_tables.h5
-rw-r--r--include/linux/netfilter_ipv6/ip6_tables.h12
-rw-r--r--include/linux/sctp.h6
-rw-r--r--include/net/addrconf.h3
-rw-r--r--include/net/dst.h4
-rw-r--r--include/net/ip.h4
-rw-r--r--include/net/ip6_route.h4
-rw-r--r--include/net/ipv6.h2
-rw-r--r--include/net/ndisc.h5
-rw-r--r--include/net/pkt_sched.h2
-rw-r--r--include/net/sctp/sctp.h2
-rw-r--r--include/net/sctp/structs.h6
-rw-r--r--include/net/sctp/ulpevent.h3
-rw-r--r--include/net/sctp/user.h2
-rw-r--r--include/net/sock.h2
-rw-r--r--include/net/tcp.h1
-rw-r--r--include/net/xfrm.h11
-rw-r--r--net/8021q/vlan.c10
-rw-r--r--net/atm/common.c3
-rw-r--r--net/bridge/br_netfilter.c2
-rw-r--r--net/bridge/netfilter/ebtables.c8
-rw-r--r--net/core/dev.c24
-rw-r--r--net/core/dst.c4
-rw-r--r--net/core/sock.c26
-rw-r--r--net/decnet/dn_nsp_in.c1
-rw-r--r--net/decnet/dn_route.c10
-rw-r--r--net/ipv4/af_inet.c2
-rw-r--r--net/ipv4/fib_semantics.c2
-rw-r--r--net/ipv4/ip_output.c7
-rw-r--r--net/ipv4/netfilter/arp_tables.c3
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c11
-rw-r--r--net/ipv4/netfilter/ip_fw_compat.c2
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c2
-rw-r--r--net/ipv4/netfilter/ip_tables.c3
-rw-r--r--net/ipv4/netfilter/ipt_CONNMARK.c2
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c2
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c49
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c6
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/route.c4
-rw-r--r--net/ipv4/tcp.c1
-rw-r--r--net/ipv4/tcp_input.c19
-rw-r--r--net/ipv4/tcp_ipv4.c5
-rw-r--r--net/ipv4/tcp_output.c7
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv4/xfrm4_output.c6
-rw-r--r--net/ipv6/addrconf.c26
-rw-r--r--net/ipv6/ip6_fib.c2
-rw-r--r--net/ipv6/ip6_output.c21
-rw-r--r--net/ipv6/ipv6_syms.c4
-rw-r--r--net/ipv6/ndisc.c66
-rw-r--r--net/ipv6/netfilter/ip6_tables.c251
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c279
-rw-r--r--net/ipv6/netfilter/ip6t_MARK.c2
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c269
-rw-r--r--net/ipv6/netfilter/ip6t_dst.c103
-rw-r--r--net/ipv6/netfilter/ip6t_esp.c91
-rw-r--r--net/ipv6/netfilter/ip6t_eui64.c3
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c63
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c101
-rw-r--r--net/ipv6/netfilter/ip6t_hl.c2
-rw-r--r--net/ipv6/netfilter/ip6t_ipv6header.c3
-rw-r--r--net/ipv6/netfilter/ip6t_length.c3
-rw-r--r--net/ipv6/netfilter/ip6t_limit.c3
-rw-r--r--net/ipv6/netfilter/ip6t_mac.c3
-rw-r--r--net/ipv6/netfilter/ip6t_mark.c3
-rw-r--r--net/ipv6/netfilter/ip6t_multiport.c34
-rw-r--r--net/ipv6/netfilter/ip6t_owner.c3
-rw-r--r--net/ipv6/netfilter/ip6t_physdev.c3
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c124
-rw-r--r--net/ipv6/raw.c2
-rw-r--r--net/ipv6/route.c23
-rw-r--r--net/ipv6/tcp_ipv6.c6
-rw-r--r--net/ipv6/udp.c2
-rw-r--r--net/ipv6/xfrm6_output.c6
-rw-r--r--net/sched/sch_api.c6
-rw-r--r--net/sctp/associola.c13
-rw-r--r--net/sctp/outqueue.c15
-rw-r--r--net/sctp/sm_make_chunk.c31
-rw-r--r--net/sctp/sm_statefuns.c59
-rw-r--r--net/sctp/socket.c49
-rw-r--r--net/sctp/transport.c27
-rw-r--r--net/sctp/ulpevent.c38
-rw-r--r--net/socket.c6
-rw-r--r--net/xfrm/xfrm_export.c8
-rw-r--r--net/xfrm/xfrm_policy.c9
-rw-r--r--net/xfrm/xfrm_state.c22
99 files changed, 1565 insertions, 1277 deletions
diff --git a/Documentation/networking/proc_net_tcp.txt b/Documentation/networking/proc_net_tcp.txt
new file mode 100644
index 000000000000..59cb915c3713
--- /dev/null
+++ b/Documentation/networking/proc_net_tcp.txt
@@ -0,0 +1,47 @@
+This document describes the interfaces /proc/net/tcp and /proc/net/tcp6.
+
+These /proc interfaces provide information about currently active TCP
+connections, and are implemented by tcp_get_info() in net/ipv4/tcp_ipv4.c and
+tcp6_get_info() in net/ipv6/tcp_ipv6.c, respectively.
+
+It will first list all listening TCP sockets, and next list all established
+TCP connections. A typical entry of /proc/net/tcp would look like this (split
+up into 3 parts because of the length of the line):
+
+ 46: 010310AC:9C4C 030310AC:1770 01
+ | | | | | |--> connection state
+ | | | | |------> remote TCP port number
+ | | | |-------------> remote IPv4 address
+ | | |--------------------> local TCP port number
+ | |---------------------------> local IPv4 address
+ |----------------------------------> number of entry
+
+ 00000150:00000000 01:00000019 00000000
+ | | | | |--> number of unrecovered RTO timeouts
+ | | | |----------> number of jiffies until timer expires
+ | | |----------------> timer_active (see below)
+ | |----------------------> receive-queue
+ |-------------------------------> transmit-queue
+
+ 1000 0 54165785 4 cd1e6040 25 4 27 3 -1
+ | | | | | | | | | |--> slow start size threshold,
+ | | | | | | | | | or -1 if the treshold
+ | | | | | | | | | is >= 0xFFFF
+ | | | | | | | | |----> sending congestion window
+ | | | | | | | |-------> (ack.quick<<1)|ack.pingpong
+ | | | | | | |---------> Predicted tick of soft clock
+ | | | | | | (delayed ACK control data)
+ | | | | | |------------> retransmit timeout
+ | | | | |------------------> location of socket in memory
+ | | | |-----------------------> socket reference count
+ | | |-----------------------------> inode
+ | |----------------------------------> unanswered 0-window probes
+ |---------------------------------------------> uid
+
+timer_active:
+ 0 no timer is pending
+ 1 retransmit-timer is pending
+ 2 another timer (e.g. delayed ack or keepalive) is pending
+ 3 this is a socket in TIME_WAIT state. Not all fields will contain
+ data (or even exist)
+ 4 zero window probe timer is pending
diff --git a/arch/i386/crypto/aes-i586-asm.S b/arch/i386/crypto/aes-i586-asm.S
index e8a04713df26..7b73c67cb4e8 100644
--- a/arch/i386/crypto/aes-i586-asm.S
+++ b/arch/i386/crypto/aes-i586-asm.S
@@ -61,7 +61,6 @@
#define r3 edx
#define r4 esi
#define r5 edi
-#define r6 ebp
#define eaxl al
#define eaxh ah
@@ -84,60 +83,63 @@
// output registers r0, r1, r4 or r5.
// Parameters:
+// table table base address
// %1 out_state[0]
// %2 out_state[1]
// %3 out_state[2]
// %4 out_state[3]
-// %5 table base address
-// %6 input register for the round (destroyed)
-// %7 scratch register for the round
-
-#define do_col(a1, a2, a3, a4, a5, a6, a7) \
- movzx %l(a6),%a7; \
- xor a5(,%a7,4),%a1; \
- movzx %h(a6),%a7; \
- shr $16,%a6; \
- xor a5+tlen(,%a7,4),%a2; \
- movzx %l(a6),%a7; \
- movzx %h(a6),%a6; \
- xor a5+2*tlen(,%a7,4),%a3; \
- xor a5+3*tlen(,%a6,4),%a4;
+// idx input register for the round (destroyed)
+// tmp scratch register for the round
+// sched key schedule
+
+#define do_col(table, a1,a2,a3,a4, idx, tmp) \
+ movzx %l(idx),%tmp; \
+ xor table(,%tmp,4),%a1; \
+ movzx %h(idx),%tmp; \
+ shr $16,%idx; \
+ xor table+tlen(,%tmp,4),%a2; \
+ movzx %l(idx),%tmp; \
+ movzx %h(idx),%idx; \
+ xor table+2*tlen(,%tmp,4),%a3; \
+ xor table+3*tlen(,%idx,4),%a4;
// initialise output registers from the key schedule
-
-#define do_fcol(a1, a2, a3, a4, a5, a6, a7, a8) \
- mov 0 a8,%a1; \
- movzx %l(a6),%a7; \
- mov 12 a8,%a2; \
- xor a5(,%a7,4),%a1; \
- mov 4 a8,%a4; \
- movzx %h(a6),%a7; \
- shr $16,%a6; \
- xor a5+tlen(,%a7,4),%a2; \
- movzx %l(a6),%a7; \
- movzx %h(a6),%a6; \
- xor a5+3*tlen(,%a6,4),%a4; \
- mov %a3,%a6; \
- mov 8 a8,%a3; \
- xor a5+2*tlen(,%a7,4),%a3;
+// NB1: original value of a3 is in idx on exit
+// NB2: original values of a1,a2,a4 aren't used
+#define do_fcol(table, a1,a2,a3,a4, idx, tmp, sched) \
+ mov 0 sched,%a1; \
+ movzx %l(idx),%tmp; \
+ mov 12 sched,%a2; \
+ xor table(,%tmp,4),%a1; \
+ mov 4 sched,%a4; \
+ movzx %h(idx),%tmp; \
+ shr $16,%idx; \
+ xor table+tlen(,%tmp,4),%a2; \
+ movzx %l(idx),%tmp; \
+ movzx %h(idx),%idx; \
+ xor table+3*tlen(,%idx,4),%a4; \
+ mov %a3,%idx; \
+ mov 8 sched,%a3; \
+ xor table+2*tlen(,%tmp,4),%a3;
// initialise output registers from the key schedule
-
-#define do_icol(a1, a2, a3, a4, a5, a6, a7, a8) \
- mov 0 a8,%a1; \
- movzx %l(a6),%a7; \
- mov 4 a8,%a2; \
- xor a5(,%a7,4),%a1; \
- mov 12 a8,%a4; \
- movzx %h(a6),%a7; \
- shr $16,%a6; \
- xor a5+tlen(,%a7,4),%a2; \
- movzx %l(a6),%a7; \
- movzx %h(a6),%a6; \
- xor a5+3*tlen(,%a6,4),%a4; \
- mov %a3,%a6; \
- mov 8 a8,%a3; \
- xor a5+2*tlen(,%a7,4),%a3;
+// NB1: original value of a3 is in idx on exit
+// NB2: original values of a1,a2,a4 aren't used
+#define do_icol(table, a1,a2,a3,a4, idx, tmp, sched) \
+ mov 0 sched,%a1; \
+ movzx %l(idx),%tmp; \
+ mov 4 sched,%a2; \
+ xor table(,%tmp,4),%a1; \
+ mov 12 sched,%a4; \
+ movzx %h(idx),%tmp; \
+ shr $16,%idx; \
+ xor table+tlen(,%tmp,4),%a2; \
+ movzx %l(idx),%tmp; \
+ movzx %h(idx),%idx; \
+ xor table+3*tlen(,%idx,4),%a4; \
+ mov %a3,%idx; \
+ mov 8 sched,%a3; \
+ xor table+2*tlen(,%tmp,4),%a3;
// original Gladman had conditional saves to MMX regs.
@@ -147,44 +149,75 @@
#define restore(a1, a2) \
mov 4*a2(%esp),%a1
-// This macro performs a forward encryption cycle. It is entered with
-// the first previous round column values in r0, r1, r4 and r5 and
-// exits with the final values in the same registers, using the MMX
-// registers mm0-mm1 or the stack for temporary storage
-
-// mov current column values into the MMX registers
-#define fwd_rnd(arg, table) \
- /* mov current column values into the MMX registers */ \
- mov %r0,%r2; \
- save (0,r1); \
- save (1,r5); \
- \
- /* compute new column values */ \
- do_fcol(r0,r5,r4,r1,table, r2,r3, arg); \
- do_col (r4,r1,r0,r5,table, r2,r3); \
- restore(r2,0); \
- do_col (r1,r0,r5,r4,table, r2,r3); \
- restore(r2,1); \
- do_col (r5,r4,r1,r0,table, r2,r3);
-
-// This macro performs an inverse encryption cycle. It is entered with
-// the first previous round column values in r0, r1, r4 and r5 and
-// exits with the final values in the same registers, using the MMX
-// registers mm0-mm1 or the stack for temporary storage
-
-#define inv_rnd(arg, table) \
- /* mov current column values into the MMX registers */ \
- mov %r0,%r2; \
- save (0,r1); \
- save (1,r5); \
- \
- /* compute new column values */ \
- do_icol(r0,r1,r4,r5, table, r2,r3, arg); \
- do_col (r4,r5,r0,r1, table, r2,r3); \
- restore(r2,0); \
- do_col (r1,r4,r5,r0, table, r2,r3); \
- restore(r2,1); \
- do_col (r5,r0,r1,r4, table, r2,r3);
+// These macros perform a forward encryption cycle. They are entered with
+// the first previous round column values in r0,r1,r4,r5 and
+// exit with the final values in the same registers, using stack
+// for temporary storage.
+
+// round column values
+// on entry: r0,r1,r4,r5
+// on exit: r2,r1,r4,r5
+#define fwd_rnd1(arg, table) \
+ save (0,r1); \
+ save (1,r5); \
+ \
+ /* compute new column values */ \
+ do_fcol(table, r2,r5,r4,r1, r0,r3, arg); /* idx=r0 */ \
+ do_col (table, r4,r1,r2,r5, r0,r3); /* idx=r4 */ \
+ restore(r0,0); \
+ do_col (table, r1,r2,r5,r4, r0,r3); /* idx=r1 */ \
+ restore(r0,1); \
+ do_col (table, r5,r4,r1,r2, r0,r3); /* idx=r5 */
+
+// round column values
+// on entry: r2,r1,r4,r5
+// on exit: r0,r1,r4,r5
+#define fwd_rnd2(arg, table) \
+ save (0,r1); \
+ save (1,r5); \
+ \
+ /* compute new column values */ \
+ do_fcol(table, r0,r5,r4,r1, r2,r3, arg); /* idx=r2 */ \
+ do_col (table, r4,r1,r0,r5, r2,r3); /* idx=r4 */ \
+ restore(r2,0); \
+ do_col (table, r1,r0,r5,r4, r2,r3); /* idx=r1 */ \
+ restore(r2,1); \
+ do_col (table, r5,r4,r1,r0, r2,r3); /* idx=r5 */
+
+// These macros performs an inverse encryption cycle. They are entered with
+// the first previous round column values in r0,r1,r4,r5 and
+// exit with the final values in the same registers, using stack
+// for temporary storage
+
+// round column values
+// on entry: r0,r1,r4,r5
+// on exit: r2,r1,r4,r5
+#define inv_rnd1(arg, table) \
+ save (0,r1); \
+ save (1,r5); \
+ \
+ /* compute new column values */ \
+ do_icol(table, r2,r1,r4,r5, r0,r3, arg); /* idx=r0 */ \
+ do_col (table, r4,r5,r2,r1, r0,r3); /* idx=r4 */ \
+ restore(r0,0); \
+ do_col (table, r1,r4,r5,r2, r0,r3); /* idx=r1 */ \
+ restore(r0,1); \
+ do_col (table, r5,r2,r1,r4, r0,r3); /* idx=r5 */
+
+// round column values
+// on entry: r2,r1,r4,r5
+// on exit: r0,r1,r4,r5
+#define inv_rnd2(arg, table) \
+ save (0,r1); \
+ save (1,r5); \
+ \
+ /* compute new column values */ \
+ do_icol(table, r0,r1,r4,r5, r2,r3, arg); /* idx=r2 */ \
+ do_col (table, r4,r5,r0,r1, r2,r3); /* idx=r4 */ \
+ restore(r2,0); \
+ do_col (table, r1,r4,r5,r0, r2,r3); /* idx=r1 */ \
+ restore(r2,1); \
+ do_col (table, r5,r0,r1,r4, r2,r3); /* idx=r5 */
// AES (Rijndael) Encryption Subroutine
@@ -198,7 +231,6 @@
aes_enc_blk:
push %ebp
mov ctx(%esp),%ebp // pointer to context
- xor %eax,%eax
// CAUTION: the order and the values used in these assigns
// rely on the register mappings
@@ -208,7 +240,9 @@ aes_enc_blk:
push %esi
mov nrnd(%ebp),%r3 // number of rounds
push %edi
- lea ekey(%ebp),%r6 // key pointer
+#if ekey != 0
+ lea ekey(%ebp),%ebp // key pointer
+#endif
// input four columns and xor in first round key
@@ -216,47 +250,47 @@ aes_enc_blk:
mov 4(%r2),%r1
mov 8(%r2),%r4
mov 12(%r2),%r5
- xor (%r6),%r0
- xor 4(%r6),%r1
- xor 8(%r6),%r4
- xor 12(%r6),%r5
+ xor (%ebp),%r0
+ xor 4(%ebp),%r1
+ xor 8(%ebp),%r4
+ xor 12(%ebp),%r5
sub $8,%esp // space for register saves on stack
- add $16,%r6 // increment to next round key
+ add $16,%ebp // increment to next round key
sub $10,%r3
je 4f // 10 rounds for 128-bit key
- add $32,%r6
+ add $32,%ebp
sub $2,%r3
je 3f // 12 rounds for 128-bit key
- add $32,%r6
-
-2: fwd_rnd( -64(%r6) ,ft_tab) // 14 rounds for 128-bit key
- fwd_rnd( -48(%r6) ,ft_tab)
-3: fwd_rnd( -32(%r6) ,ft_tab) // 12 rounds for 128-bit key
- fwd_rnd( -16(%r6) ,ft_tab)
-4: fwd_rnd( (%r6) ,ft_tab) // 10 rounds for 128-bit key
- fwd_rnd( +16(%r6) ,ft_tab)
- fwd_rnd( +32(%r6) ,ft_tab)
- fwd_rnd( +48(%r6) ,ft_tab)
- fwd_rnd( +64(%r6) ,ft_tab)
- fwd_rnd( +80(%r6) ,ft_tab)
- fwd_rnd( +96(%r6) ,ft_tab)
- fwd_rnd(+112(%r6) ,ft_tab)
- fwd_rnd(+128(%r6) ,ft_tab)
- fwd_rnd(+144(%r6) ,fl_tab) // last round uses a different table
+ add $32,%ebp
+
+2: fwd_rnd1( -64(%ebp) ,ft_tab) // 14 rounds for 128-bit key
+ fwd_rnd2( -48(%ebp) ,ft_tab)
+3: fwd_rnd1( -32(%ebp) ,ft_tab) // 12 rounds for 128-bit key
+ fwd_rnd2( -16(%ebp) ,ft_tab)
+4: fwd_rnd1( (%ebp) ,ft_tab) // 10 rounds for 128-bit key
+ fwd_rnd2( +16(%ebp) ,ft_tab)
+ fwd_rnd1( +32(%ebp) ,ft_tab)
+ fwd_rnd2( +48(%ebp) ,ft_tab)
+ fwd_rnd1( +64(%ebp) ,ft_tab)
+ fwd_rnd2( +80(%ebp) ,ft_tab)
+ fwd_rnd1( +96(%ebp) ,ft_tab)
+ fwd_rnd2(+112(%ebp) ,ft_tab)
+ fwd_rnd1(+128(%ebp) ,ft_tab)
+ fwd_rnd2(+144(%ebp) ,fl_tab) // last round uses a different table
// move final values to the output array. CAUTION: the
// order of these assigns rely on the register mappings
add $8,%esp
- mov out_blk+12(%esp),%r6
- mov %r5,12(%r6)
+ mov out_blk+12(%esp),%ebp
+ mov %r5,12(%ebp)
pop %edi
- mov %r4,8(%r6)
+ mov %r4,8(%ebp)
pop %esi
- mov %r1,4(%r6)
+ mov %r1,4(%ebp)
pop %ebx
- mov %r0,(%r6)
+ mov %r0,(%ebp)
pop %ebp
mov $1,%eax
ret
@@ -273,7 +307,6 @@ aes_enc_blk:
aes_dec_blk:
push %ebp
mov ctx(%esp),%ebp // pointer to context
- xor %eax,%eax
// CAUTION: the order and the values used in these assigns
// rely on the register mappings
@@ -283,10 +316,12 @@ aes_dec_blk:
push %esi
mov nrnd(%ebp),%r3 // number of rounds
push %edi
- lea dkey(%ebp),%r6 // key pointer
+#if dkey != 0
+ lea dkey(%ebp),%ebp // key pointer
+#endif
mov %r3,%r0
shl $4,%r0
- add %r0,%r6
+ add %r0,%ebp
// input four columns and xor in first round key
@@ -294,47 +329,47 @@ aes_dec_blk:
mov 4(%r2),%r1
mov 8(%r2),%r4
mov 12(%r2),%r5
- xor (%r6),%r0
- xor 4(%r6),%r1
- xor 8(%r6),%r4
- xor 12(%r6),%r5
+ xor (%ebp),%r0
+ xor 4(%ebp),%r1
+ xor 8(%ebp),%r4
+ xor 12(%ebp),%r5
- sub $8,%esp // space for register saves on stack
- sub $16,%r6 // increment to next round key
+ sub $8,%esp // space for register saves on stack
+ sub $16,%ebp // increment to next round key
sub $10,%r3
je 4f // 10 rounds for 128-bit key
- sub $32,%r6
+ sub $32,%ebp
sub $2,%r3
je 3f // 12 rounds for 128-bit key
- sub $32,%r6
-
-2: inv_rnd( +64(%r6), it_tab) // 14 rounds for 128-bit key
- inv_rnd( +48(%r6), it_tab)
-3: inv_rnd( +32(%r6), it_tab) // 12 rounds for 128-bit key
- inv_rnd( +16(%r6), it_tab)
-4: inv_rnd( (%r6), it_tab) // 10 rounds for 128-bit key
- inv_rnd( -16(%r6), it_tab)
- inv_rnd( -32(%r6), it_tab)
- inv_rnd( -48(%r6), it_tab)
- inv_rnd( -64(%r6), it_tab)
- inv_rnd( -80(%r6), it_tab)
- inv_rnd( -96(%r6), it_tab)
- inv_rnd(-112(%r6), it_tab)
- inv_rnd(-128(%r6), it_tab)
- inv_rnd(-144(%r6), il_tab) // last round uses a different table
+ sub $32,%ebp
+
+2: inv_rnd1( +64(%ebp), it_tab) // 14 rounds for 128-bit key
+ inv_rnd2( +48(%ebp), it_tab)
+3: inv_rnd1( +32(%ebp), it_tab) // 12 rounds for 128-bit key
+ inv_rnd2( +16(%ebp), it_tab)
+4: inv_rnd1( (%ebp), it_tab) // 10 rounds for 128-bit key
+ inv_rnd2( -16(%ebp), it_tab)
+ inv_rnd1( -32(%ebp), it_tab)
+ inv_rnd2( -48(%ebp), it_tab)
+ inv_rnd1( -64(%ebp), it_tab)
+ inv_rnd2( -80(%ebp), it_tab)
+ inv_rnd1( -96(%ebp), it_tab)
+ inv_rnd2(-112(%ebp), it_tab)
+ inv_rnd1(-128(%ebp), it_tab)
+ inv_rnd2(-144(%ebp), il_tab) // last round uses a different table
// move final values to the output array. CAUTION: the
// order of these assigns rely on the register mappings
add $8,%esp
- mov out_blk+12(%esp),%r6
- mov %r5,12(%r6)
+ mov out_blk+12(%esp),%ebp
+ mov %r5,12(%ebp)
pop %edi
- mov %r4,8(%r6)
+ mov %r4,8(%ebp)
pop %esi
- mov %r1,4(%r6)
+ mov %r1,4(%ebp)
pop %ebx
- mov %r0,(%r6)
+ mov %r0,(%ebp)
pop %ebp
mov $1,%eax
ret
diff --git a/crypto/sha256.c b/crypto/sha256.c
index e8adf150d593..39f5a654709e 100644
--- a/crypto/sha256.c
+++ b/crypto/sha256.c
@@ -63,15 +63,7 @@ static inline u32 RORu32(u32 x, u32 y)
static inline void LOAD_OP(int I, u32 *W, const u8 *input)
{
- u32 t1 = input[(4 * I)] & 0xff;
-
- t1 <<= 8;
- t1 |= input[(4 * I) + 1] & 0xff;
- t1 <<= 8;
- t1 |= input[(4 * I) + 2] & 0xff;
- t1 <<= 8;
- t1 |= input[(4 * I) + 3] & 0xff;
- W[I] = t1;
+ W[I] = __be32_to_cpu( ((u32*)(input))[I] );
}
static inline void BLEND_OP(int I, u32 *W)
diff --git a/crypto/sha512.c b/crypto/sha512.c
index f1a8dc0aec47..6acaea9b7e2b 100644
--- a/crypto/sha512.c
+++ b/crypto/sha512.c
@@ -30,6 +30,7 @@ struct sha512_ctx {
u64 state[8];
u32 count[4];
u8 buf[128];
+ u64 W[80];
};
static inline u64 Ch(u64 x, u64 y, u64 z)
@@ -104,34 +105,18 @@ const u64 sha512_K[80] = {
static inline void LOAD_OP(int I, u64 *W, const u8 *input)
{
- u64 t1 = input[(8*I) ] & 0xff;
- t1 <<= 8;
- t1 |= input[(8*I)+1] & 0xff;
- t1 <<= 8;
- t1 |= input[(8*I)+2] & 0xff;
- t1 <<= 8;
- t1 |= input[(8*I)+3] & 0xff;
- t1 <<= 8;
- t1 |= input[(8*I)+4] & 0xff;
- t1 <<= 8;
- t1 |= input[(8*I)+5] & 0xff;
- t1 <<= 8;
- t1 |= input[(8*I)+6] & 0xff;
- t1 <<= 8;
- t1 |= input[(8*I)+7] & 0xff;
- W[I] = t1;
+ W[I] = __be64_to_cpu( ((u64*)(input))[I] );
}
static inline void BLEND_OP(int I, u64 *W)
{
- W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+ W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
}
static void
-sha512_transform(u64 *state, const u8 *input)
+sha512_transform(u64 *state, u64 *W, const u8 *input)
{
u64 a, b, c, d, e, f, g, h, t1, t2;
- u64 W[80];
int i;
@@ -172,7 +157,6 @@ sha512_transform(u64 *state, const u8 *input)
/* erase our data */
a = b = c = d = e = f = g = h = t1 = t2 = 0;
- memset(W, 0, 80 * sizeof(u64));
}
static void
@@ -230,10 +214,10 @@ sha512_update(void *ctx, const u8 *data, unsigned int len)
/* Transform as many times as possible. */
if (len >= part_len) {
memcpy(&sctx->buf[index], data, part_len);
- sha512_transform(sctx->state, sctx->buf);
+ sha512_transform(sctx->state, sctx->W, sctx->buf);
for (i = part_len; i + 127 < len; i+=128)
- sha512_transform(sctx->state, &data[i]);
+ sha512_transform(sctx->state, sctx->W, &data[i]);
index = 0;
} else {
@@ -242,6 +226,9 @@ sha512_update(void *ctx, const u8 *data, unsigned int len)
/* Buffer remaining input */
memcpy(&sctx->buf[index], &data[i], len - i);
+
+ /* erase our data */
+ memset(sctx->W, 0, sizeof(sctx->W));
}
static void
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 9ae4121aef47..a3f3c2413f2f 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -354,8 +354,7 @@ static inline void __init show_version (void) {
/********** globals **********/
-static hrz_dev * hrz_devs = NULL;
-static struct timer_list housekeeping;
+static void do_housekeeping (unsigned long arg);
static unsigned short debug = 0;
static unsigned short vpi_bits = 0;
@@ -1386,7 +1385,7 @@ static inline void rx_data_av_handler (hrz_dev * dev) {
static irqreturn_t interrupt_handler(int irq, void *dev_id,
struct pt_regs *pt_regs) {
- hrz_dev * dev = hrz_devs;
+ hrz_dev * dev = (hrz_dev *) dev_id;
u32 int_source;
unsigned int irq_ok;
(void) pt_regs;
@@ -1397,16 +1396,6 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id,
PRINTD (DBG_IRQ|DBG_ERR, "irq with NULL dev_id: %d", irq);
return IRQ_NONE;
}
- // Did one of our cards generate the interrupt?
- while (dev) {
- if (dev == dev_id)
- break;
- dev = dev->prev;
- }
- if (!dev) {
- PRINTD (DBG_IRQ, "irq not for me: %d", irq);
- return IRQ_NONE;
- }
if (irq != dev->irq) {
PRINTD (DBG_IRQ|DBG_ERR, "irq mismatch: %d", irq);
return IRQ_NONE;
@@ -1462,28 +1451,18 @@ static irqreturn_t interrupt_handler(int irq, void *dev_id,
/********** housekeeping **********/
-static void set_timer (struct timer_list * timer, unsigned int delay) {
- timer->expires = jiffies + delay;
- add_timer (timer);
- return;
-}
-
static void do_housekeeping (unsigned long arg) {
// just stats at the moment
- hrz_dev * dev = hrz_devs;
- (void) arg;
- // data is set to zero at module unload
- if (housekeeping.data) {
- while (dev) {
- // collect device-specific (not driver/atm-linux) stats here
- dev->tx_cell_count += rd_regw (dev, TX_CELL_COUNT_OFF);
- dev->rx_cell_count += rd_regw (dev, RX_CELL_COUNT_OFF);
- dev->hec_error_count += rd_regw (dev, HEC_ERROR_COUNT_OFF);
- dev->unassigned_cell_count += rd_regw (dev, UNASSIGNED_CELL_COUNT_OFF);
- dev = dev->prev;
- }
- set_timer (&housekeeping, HZ/10);
- }
+ hrz_dev * dev = (hrz_dev *) arg;
+
+ // collect device-specific (not driver/atm-linux) stats here
+ dev->tx_cell_count += rd_regw (dev, TX_CELL_COUNT_OFF);
+ dev->rx_cell_count += rd_regw (dev, RX_CELL_COUNT_OFF);
+ dev->hec_error_count += rd_regw (dev, HEC_ERROR_COUNT_OFF);
+ dev->unassigned_cell_count += rd_regw (dev, UNASSIGNED_CELL_COUNT_OFF);
+
+ mod_timer (&dev->housekeeping, jiffies + HZ/10);
+
return;
}
@@ -2719,157 +2698,176 @@ static const struct atmdev_ops hrz_ops = {
.owner = THIS_MODULE,
};
-static int __init hrz_probe (void) {
- struct pci_dev * pci_dev;
- int devs;
-
- PRINTD (DBG_FLOW, "hrz_probe");
-
- devs = 0;
- pci_dev = NULL;
- while ((pci_dev = pci_find_device
- (PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_HORIZON, pci_dev)
- )) {
- hrz_dev * dev;
-
- // adapter slot free, read resources from PCI configuration space
- u32 iobase = pci_resource_start (pci_dev, 0);
- u32 * membase = bus_to_virt (pci_resource_start (pci_dev, 1));
- u8 irq = pci_dev->irq;
-
- /* XXX DEV_LABEL is a guess */
- if (!request_region (iobase, HRZ_IO_EXTENT, DEV_LABEL))
- continue;
+static int __devinit hrz_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
+{
+ hrz_dev * dev;
+ int err = 0;
- if (pci_enable_device (pci_dev))
- continue;
-
- dev = kmalloc (sizeof(hrz_dev), GFP_KERNEL);
- if (!dev) {
- // perhaps we should be nice: deregister all adapters and abort?
- PRINTD (DBG_ERR, "out of memory");
- continue;
- }
-
- memset (dev, 0, sizeof(hrz_dev));
-
- // grab IRQ and install handler - move this someplace more sensible
- if (request_irq (irq,
- interrupt_handler,
- SA_SHIRQ, /* irqflags guess */
- DEV_LABEL, /* name guess */
- dev)) {
- PRINTD (DBG_WARN, "request IRQ failed!");
- // free_irq is at "endif"
- } else {
-
- PRINTD (DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p",
- iobase, irq, membase);
-
- dev->atm_dev = atm_dev_register (DEV_LABEL, &hrz_ops, -1, NULL);
- if (!(dev->atm_dev)) {
- PRINTD (DBG_ERR, "failed to register Madge ATM adapter");
- } else {
+ // adapter slot free, read resources from PCI configuration space
+ u32 iobase = pci_resource_start (pci_dev, 0);
+ u32 * membase = bus_to_virt (pci_resource_start (pci_dev, 1));
+ u8 irq = pci_dev->irq;
unsigned char lat;
-
- PRINTD (DBG_INFO, "registered Madge ATM adapter (no. %d) (%p) at %p",
- dev->atm_dev->number, dev, dev->atm_dev);
+
+ PRINTD (DBG_FLOW, "hrz_probe");
+
+ /* XXX DEV_LABEL is a guess */
+ if (!request_region(iobase, HRZ_IO_EXTENT, DEV_LABEL))
+ return -EINVAL;
+
+ if (pci_enable_device(pci_dev)) {
+ err = -EINVAL;
+ goto out_release;
+ }
+
+ dev = kmalloc(sizeof(hrz_dev), GFP_KERNEL);
+ if (!dev) {
+ // perhaps we should be nice: deregister all adapters and abort?
+ PRINTD(DBG_ERR, "out of memory");
+ err = -ENOMEM;
+ goto out_disable;
+ }
+
+ memset(dev, 0, sizeof(hrz_dev));
+
+ pci_set_drvdata(pci_dev, dev);
+
+ // grab IRQ and install handler - move this someplace more sensible
+ if (request_irq(irq,
+ interrupt_handler,
+ SA_SHIRQ, /* irqflags guess */
+ DEV_LABEL, /* name guess */
+ dev)) {
+ PRINTD(DBG_WARN, "request IRQ failed!");
+ err = -EINVAL;
+ goto out_free;
+ }
+
+ PRINTD(DBG_INFO, "found Madge ATM adapter (hrz) at: IO %x, IRQ %u, MEM %p",
+ iobase, irq, membase);
+
+ dev->atm_dev = atm_dev_register(DEV_LABEL, &hrz_ops, -1, NULL);
+ if (!(dev->atm_dev)) {
+ PRINTD(DBG_ERR, "failed to register Madge ATM adapter");
+ err = -EINVAL;
+ goto out_free_irq;
+ }
+
+ PRINTD(DBG_INFO, "registered Madge ATM adapter (no. %d) (%p) at %p",
+ dev->atm_dev->number, dev, dev->atm_dev);
dev->atm_dev->dev_data = (void *) dev;
dev->pci_dev = pci_dev;
-
+
// enable bus master accesses
- pci_set_master (pci_dev);
-
+ pci_set_master(pci_dev);
+
// frobnicate latency (upwards, usually)
- pci_read_config_byte (pci_dev, PCI_LATENCY_TIMER, &lat);
+ pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &lat);
if (pci_lat) {
- PRINTD (DBG_INFO, "%s PCI latency timer from %hu to %hu",
- "changing", lat, pci_lat);
- pci_write_config_byte (pci_dev, PCI_LATENCY_TIMER, pci_lat);
+ PRINTD(DBG_INFO, "%s PCI latency timer from %hu to %hu",
+ "changing", lat, pci_lat);
+ pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, pci_lat);
} else if (lat < MIN_PCI_LATENCY) {
- PRINTK (KERN_INFO, "%s PCI latency timer from %hu to %hu",
- "increasing", lat, MIN_PCI_LATENCY);
- pci_write_config_byte (pci_dev, PCI_LATENCY_TIMER, MIN_PCI_LATENCY);
+ PRINTK(KERN_INFO, "%s PCI latency timer from %hu to %hu",
+ "increasing", lat, MIN_PCI_LATENCY);
+ pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, MIN_PCI_LATENCY);
}
-
+
dev->iobase = iobase;
dev->irq = irq;
dev->membase = membase;
-
+
dev->rx_q_entry = dev->rx_q_reset = &memmap->rx_q_entries[0];
dev->rx_q_wrap = &memmap->rx_q_entries[RX_CHANS-1];
-
+
// these next three are performance hacks
dev->last_vc = -1;
dev->tx_last = -1;
dev->tx_idle = 0;
-
+
dev->tx_regions = 0;
dev->tx_bytes = 0;
dev->tx_skb = NULL;
dev->tx_iovec = NULL;
-
+
dev->tx_cell_count = 0;
dev->rx_cell_count = 0;
dev->hec_error_count = 0;
dev->unassigned_cell_count = 0;
-
+
dev->noof_spare_buffers = 0;
-
+
{
- unsigned int i;
- for (i = 0; i < TX_CHANS; ++i)
- dev->tx_channel_record[i] = -1;
+ unsigned int i;
+ for (i = 0; i < TX_CHANS; ++i)
+ dev->tx_channel_record[i] = -1;
}
-
+
dev->flags = 0;
-
+
// Allocate cell rates and remember ASIC version
// Fibre: ATM_OC3_PCR = 1555200000/8/270*260/53 - 29/53
// Copper: (WRONG) we want 6 into the above, close to 25Mb/s
// Copper: (plagarise!) 25600000/8/270*260/53 - n/53
-
- if (hrz_init (dev)) {
- // to be really pedantic, this should be ATM_OC3c_PCR
- dev->tx_avail = ATM_OC3_PCR;
- dev->rx_avail = ATM_OC3_PCR;
- set_bit (ultra, &dev->flags); // NOT "|= ultra" !
+
+ if (hrz_init(dev)) {
+ // to be really pedantic, this should be ATM_OC3c_PCR
+ dev->tx_avail = ATM_OC3_PCR;
+ dev->rx_avail = ATM_OC3_PCR;
+ set_bit(ultra, &dev->flags); // NOT "|= ultra" !
} else {
- dev->tx_avail = ((25600000/8)*26)/(27*53);
- dev->rx_avail = ((25600000/8)*26)/(27*53);
- PRINTD (DBG_WARN, "Buggy ASIC: no TX bus-mastering.");
+ dev->tx_avail = ((25600000/8)*26)/(27*53);
+ dev->rx_avail = ((25600000/8)*26)/(27*53);
+ PRINTD(DBG_WARN, "Buggy ASIC: no TX bus-mastering.");
}
-
+
// rate changes spinlock
- spin_lock_init (&dev->rate_lock);
-
+ spin_lock_init(&dev->rate_lock);
+
// on-board memory access spinlock; we want atomic reads and
// writes to adapter memory (handles IRQ and SMP)
- spin_lock_init (&dev->mem_lock);
-
- init_waitqueue_head (&dev->tx_queue);
-
+ spin_lock_init(&dev->mem_lock);
+
+ init_waitqueue_head(&dev->tx_queue);
+
// vpi in 0..4, vci in 6..10
dev->atm_dev->ci_range.vpi_bits = vpi_bits;
dev->atm_dev->ci_range.vci_bits = 10-vpi_bits;
-
- // update count and linked list
- ++devs;
- dev->prev = hrz_devs;
- hrz_devs = dev;
- // success
- continue;
-
- /* not currently reached */
- atm_dev_deregister (dev->atm_dev);
- } /* atm_dev_register */
- free_irq (irq, dev);
-
- } /* request_irq */
- kfree (dev);
- release_region(iobase, HRZ_IO_EXTENT);
- } /* kmalloc and while */
- return devs;
+
+ init_timer(&dev->housekeeping);
+ dev->housekeeping.function = do_housekeeping;
+ dev->housekeeping.data = (unsigned long) dev;
+ mod_timer(&dev->housekeeping, jiffies);
+
+out:
+ return err;
+
+out_free_irq:
+ free_irq(dev->irq, dev);
+out_free:
+ kfree(dev);
+out_disable:
+ pci_disable_device(pci_dev);
+out_release:
+ release_region(iobase, HRZ_IO_EXTENT);
+ goto out;
+}
+
+static void __devexit hrz_remove_one(struct pci_dev *pci_dev)
+{
+ hrz_dev *dev;
+
+ dev = pci_get_drvdata(pci_dev);
+
+ PRINTD(DBG_INFO, "closing %p (atm_dev = %p)", dev, dev->atm_dev);
+ del_timer_sync(&dev->housekeeping);
+ hrz_reset(dev);
+ atm_dev_deregister(dev->atm_dev);
+ free_irq(dev->irq, dev);
+ release_region(dev->iobase, HRZ_IO_EXTENT);
+ kfree(dev);
+
+ pci_disable_device(pci_dev);
}
static void __init hrz_check_args (void) {
@@ -2909,11 +2907,22 @@ MODULE_PARM_DESC(max_tx_size, "maximum size of TX AAL5 frames");
MODULE_PARM_DESC(max_rx_size, "maximum size of RX AAL5 frames");
MODULE_PARM_DESC(pci_lat, "PCI latency in bus cycles");
+static struct pci_device_id hrz_pci_tbl[] = {
+ { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_HORIZON, PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, 0 },
+ { 0, }
+};
+
+static struct pci_driver hrz_driver = {
+ .name = "horizon",
+ .probe = hrz_probe,
+ .remove = __devexit_p(hrz_remove_one),
+ .id_table = hrz_pci_tbl,
+};
+
/********** module entry **********/
static int __init hrz_module_init (void) {
- int devs;
-
// sanity check - cast is needed since printk does not support %Zu
if (sizeof(struct MEMMAP) != 128*1024/4) {
PRINTK (KERN_ERR, "Fix struct MEMMAP (is %lu fakewords).",
@@ -2927,44 +2936,15 @@ static int __init hrz_module_init (void) {
hrz_check_args();
// get the juice
- devs = hrz_probe();
-
- if (devs) {
- init_timer (&housekeeping);
- housekeeping.function = do_housekeeping;
- // paranoia
- housekeeping.data = 1;
- set_timer (&housekeeping, 0);
- } else {
- PRINTK (KERN_ERR, "no (usable) adapters found");
- }
-
- return devs ? 0 : -ENODEV;
+ return pci_module_init(&hrz_driver);
}
/********** module exit **********/
static void __exit hrz_module_exit (void) {
- hrz_dev * dev;
PRINTD (DBG_FLOW, "cleanup_module");
- // paranoia
- housekeeping.data = 0;
- del_timer (&housekeeping);
-
- while (hrz_devs) {
- dev = hrz_devs;
- hrz_devs = dev->prev;
-
- PRINTD (DBG_INFO, "closing %p (atm_dev = %p)", dev, dev->atm_dev);
- hrz_reset (dev);
- atm_dev_deregister (dev->atm_dev);
- free_irq (dev->irq, dev);
- release_region (dev->iobase, HRZ_IO_EXTENT);
- kfree (dev);
- }
-
- return;
+ return pci_unregister_driver(&hrz_driver);
}
module_init(hrz_module_init);
diff --git a/drivers/atm/horizon.h b/drivers/atm/horizon.h
index ec5ba498df49..e2cc7020fa3b 100644
--- a/drivers/atm/horizon.h
+++ b/drivers/atm/horizon.h
@@ -457,7 +457,7 @@ struct hrz_dev {
unsigned long unassigned_cell_count;
struct pci_dev * pci_dev;
- struct hrz_dev * prev;
+ struct timer_list housekeeping;
};
typedef struct hrz_dev hrz_dev;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index e1097f90c883..5769fdc4fdb0 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4700,6 +4700,7 @@ static void __exit bonding_exit(void)
module_init(bonding_init);
module_exit(bonding_exit);
MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION(DRV_DESCRIPTION ", v" DRV_VERSION);
MODULE_AUTHOR("Thomas Davis, tadavis@lbl.gov and many others");
MODULE_SUPPORTED_DEVICE("most ethernet devices");
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 268da2732958..87a901c75370 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -395,7 +395,6 @@ struct atm_dev *atm_dev_lookup(int number);
void atm_dev_deregister(struct atm_dev *dev);
void shutdown_atm_dev(struct atm_dev *dev);
void vcc_insert_socket(struct sock *sk);
-void vcc_remove_socket(struct sock *sk);
/*
diff --git a/include/linux/ipv6_route.h b/include/linux/ipv6_route.h
index 46d8b7e8b1aa..e2f935038013 100644
--- a/include/linux/ipv6_route.h
+++ b/include/linux/ipv6_route.h
@@ -14,7 +14,8 @@
#define _LINUX_IPV6_ROUTE_H
#define RTF_DEFAULT 0x00010000 /* default - learned via ND */
-#define RTF_ALLONLINK 0x00020000 /* fallback, no routers on link */
+#define RTF_ALLONLINK 0x00020000 /* (deprecated and will be removed)
+ fallback, no routers on link */
#define RTF_ADDRCONF 0x00040000 /* addrconf route - RA */
#define RTF_PREFIX_RT 0x00080000 /* A prefix only route - RA */
diff --git a/include/linux/net.h b/include/linux/net.h
index 2c4572f630a1..368b0f9d3006 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -176,7 +176,6 @@ struct kvec;
extern int sock_wake_async(struct socket *sk, int how, int band);
extern int sock_register(struct net_proto_family *fam);
extern int sock_unregister(int family);
-extern struct socket *sock_alloc(void);
extern int sock_create(int family, int type, int proto,
struct socket **res);
extern int sock_create_kern(int family, int type, int proto,
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c102cdce2ebe..79c65e9ac5a1 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -937,7 +937,7 @@ extern int weight_p;
extern unsigned long netdev_fc_xoff;
extern atomic_t netdev_dropping;
extern int netdev_set_master(struct net_device *dev, struct net_device *master);
-extern int skb_checksum_help(struct sk_buff **pskb, int inward);
+extern int skb_checksum_help(struct sk_buff *skb, int inward);
#ifdef CONFIG_SYSCTL
extern char *net_sysctl_strdup(const char *s);
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index a9357be1ae41..ced66929126c 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -172,12 +172,6 @@ extern void nf_reinject(struct sk_buff *skb,
struct nf_info *info,
unsigned int verdict);
-extern inline struct ipt_target *
-ipt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
-extern inline struct ip6t_target *
-ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex);
-extern inline struct arpt_target *
-arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *);
#ifdef CONFIG_NETFILTER_DEBUG
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 02a006f17ac4..defc7bc472d9 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -407,11 +407,6 @@ struct ipt_target
struct module *me;
};
-extern struct ipt_target *
-ipt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
-extern struct arpt_target *
-arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex);
-
extern int ipt_register_target(struct ipt_target *target);
extern void ipt_unregister_target(struct ipt_target *target);
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 6f70cf3df39a..d6ac08c14dc1 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -355,13 +355,15 @@ struct ip6t_match
/* Return true or false: return FALSE and set *hotdrop = 1 to
force immediate packet drop. */
+ /* Arguments changed since 2.6.9, as this must now handle
+ non-linear skb, using skb_header_pointer and
+ skb_ip_make_writable. */
int (*match)(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop);
/* Called when user tries to insert an entry of this type. */
@@ -386,11 +388,13 @@ struct ip6t_target
const char name[IP6T_FUNCTION_MAXNAMELEN];
- /* Returns verdict. */
+ /* Returns verdict. Argument order changed since 2.6.9, as this
+ must now handle non-linear skbs, using skb_copy_bits and
+ skb_ip_make_writable. */
unsigned int (*target)(struct sk_buff **pskb,
- unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
+ unsigned int hooknum,
const void *targinfo,
void *userdata);
diff --git a/include/linux/sctp.h b/include/linux/sctp.h
index cff28345eacf..1ed3da0cb9d0 100644
--- a/include/linux/sctp.h
+++ b/include/linux/sctp.h
@@ -281,7 +281,11 @@ typedef struct sctp_ecn_capable_param {
sctp_paramhdr_t param_hdr;
} __attribute__((packed)) sctp_ecn_capable_param_t;
-
+/* ADDIP Section 3.2.6 Adaption Layer Indication */
+typedef struct sctp_adaption_ind_param {
+ struct sctp_paramhdr param_hdr;
+ __u32 adaption_ind;
+} __attribute__((packed)) sctp_adaption_ind_param_t;
/* RFC 2960. Section 3.3.3 Initiation Acknowledgement (INIT ACK) (2):
* The INIT ACK chunk is used to acknowledge the initiation of an SCTP
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 50f4c2c4df86..97c2a6121275 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -67,8 +67,7 @@ extern int ipv6_get_saddr(struct dst_entry *dst,
struct in6_addr *saddr);
extern int ipv6_dev_get_saddr(struct net_device *dev,
struct in6_addr *daddr,
- struct in6_addr *saddr,
- int onlink);
+ struct in6_addr *saddr);
extern int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *);
extern int ipv6_rcv_saddr_equal(const struct sock *sk,
const struct sock *sk2);
diff --git a/include/net/dst.h b/include/net/dst.h
index 16da04466554..7ffb470d0e9a 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -67,7 +67,7 @@ struct dst_entry
struct xfrm_state *xfrm;
int (*input)(struct sk_buff*);
- int (*output)(struct sk_buff**);
+ int (*output)(struct sk_buff*);
#ifdef CONFIG_NET_CLS_ROUTE
__u32 tclassid;
@@ -222,7 +222,7 @@ static inline int dst_output(struct sk_buff *skb)
int err;
for (;;) {
- err = skb->dst->output(&skb);
+ err = skb->dst->output(skb);
if (likely(err == 0))
return err;
diff --git a/include/net/ip.h b/include/net/ip.h
index 0f633ff0b9b4..15a1c6a2e534 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -89,8 +89,8 @@ extern int ip_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt);
extern int ip_local_deliver(struct sk_buff *skb);
extern int ip_mr_input(struct sk_buff *skb);
-extern int ip_output(struct sk_buff **pskb);
-extern int ip_mc_output(struct sk_buff **pskb);
+extern int ip_output(struct sk_buff *skb);
+extern int ip_mc_output(struct sk_buff *skb);
extern int ip_fragment(struct sk_buff *skb, int (*out)(struct sk_buff*));
extern int ip_do_nat(struct sk_buff *skb);
extern void ip_send_check(struct iphdr *ip);
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index d859c4160eaa..d5d1dd10cdb8 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -70,7 +70,7 @@ extern struct rt6_info *rt6_lookup(struct in6_addr *daddr,
extern struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
struct neighbour *neigh,
struct in6_addr *addr,
- int (*output)(struct sk_buff **));
+ int (*output)(struct sk_buff *));
extern int ndisc_dst_gc(int *more);
extern void fib6_force_start_gc(void);
@@ -87,7 +87,7 @@ extern struct rt6_info * rt6_get_dflt_router(struct in6_addr *addr,
extern struct rt6_info * rt6_add_dflt_router(struct in6_addr *gwaddr,
struct net_device *dev);
-extern void rt6_purge_dflt_routers(int lst_resort);
+extern void rt6_purge_dflt_routers(void);
extern void rt6_reset_dflt_pointer(struct rt6_info *rt);
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index a3f44754ac08..e0e3800a9560 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -355,7 +355,7 @@ extern int ip6_dst_lookup(struct sock *sk,
* skb processing functions
*/
-extern int ip6_output(struct sk_buff **pskb);
+extern int ip6_output(struct sk_buff *skb);
extern int ip6_forward(struct sk_buff *skb);
extern int ip6_input(struct sk_buff *skb);
extern int ip6_mc_input(struct sk_buff *skb);
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 61d7033bca7f..8f121905ea6d 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -45,6 +45,11 @@ struct nd_msg {
__u8 opt[0];
};
+struct rs_msg {
+ struct icmp6hdr icmph;
+ __u8 opt[0];
+};
+
struct ra_msg {
struct icmp6hdr icmph;
__u32 reachable_time;
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index 357be232a46c..d0ab0a3d10c5 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -79,7 +79,7 @@ struct Qdisc
unsigned flags;
#define TCQ_F_BUILTIN 1
#define TCQ_F_THROTTLED 2
-#define TCQ_F_INGRES 4
+#define TCQ_F_INGRESS 4
int padded;
struct Qdisc_ops *ops;
u32 handle;
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 053a0ac270f9..ac856c13d354 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -335,7 +335,7 @@ static inline void sctp_v6_exit(void) { return; }
/* Map an association to an assoc_id. */
static inline sctp_assoc_t sctp_assoc2id(const struct sctp_association *asoc)
{
- return (asoc?asoc->assoc_id:NULL);
+ return (asoc?asoc->assoc_id:0);
}
/* Look up the association by its id. */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 26c97aa3a3c7..3bd04bc5b002 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -266,6 +266,7 @@ struct sctp_opt {
__u8 disable_fragments;
__u8 pd_mode;
__u8 v4mapped;
+ __u32 adaption_ind;
/* Receive to here while partial delivery is in effect. */
struct sk_buff_head pd_lobby;
@@ -323,6 +324,8 @@ struct sctp_cookie {
__u8 prsctp_capable;
+ __u32 adaption_ind;
+
/* This is a shim for my peer's INIT packet, followed by
* a copy of the raw address list of the association.
* The length of the raw address list is saved in the
@@ -362,6 +365,7 @@ union sctp_params {
struct sctp_ipv4addr_param *v4;
struct sctp_ipv6addr_param *v6;
union sctp_addr_param *addr;
+ struct sctp_adaption_ind_param *aind;
};
/* RFC 2960. Section 3.3.5 Heartbeat.
@@ -1395,6 +1399,8 @@ struct sctp_association {
__u8 asconf_capable; /* Does peer support ADDIP? */
__u8 prsctp_capable; /* Can peer do PR-SCTP? */
+ __u32 adaption_ind; /* Adaption Code point. */
+
/* This mask is used to disable sending the ASCONF chunk
* with specified parameter to peer.
*/
diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h
index ff9c7573063c..46a974464a84 100644
--- a/include/net/sctp/ulpevent.h
+++ b/include/net/sctp/ulpevent.h
@@ -121,6 +121,9 @@ struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
const struct sctp_association *asoc,
__u32 indication, int gfp);
+struct sctp_ulpevent *sctp_ulpevent_make_adaption_indication(
+ const struct sctp_association *asoc, int gfp);
+
struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
struct sctp_chunk *chunk,
int gfp);
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 04e99178015f..aa95f0099e64 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -55,7 +55,7 @@
#include <linux/types.h>
#include <linux/socket.h>
-typedef void * sctp_assoc_t;
+typedef __s32 sctp_assoc_t;
/* The following symbols come from the Sockets API Extensions for
* SCTP <draft-ietf-tsvwg-sctpsocket-07.txt>.
diff --git a/include/net/sock.h b/include/net/sock.h
index 563096ab673a..bfad716ce409 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -746,7 +746,6 @@ extern void sk_send_sigurg(struct sock *sk);
* Functions to fill in entries in struct proto_ops when a protocol
* does not implement a particular function.
*/
-extern int sock_no_release(struct socket *);
extern int sock_no_bind(struct socket *,
struct sockaddr *, int);
extern int sock_no_connect(struct socket *,
@@ -1275,7 +1274,6 @@ static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb)
extern atomic_t netstamp_needed;
extern void sock_enable_timestamp(struct sock *sk);
-extern void sock_disable_timestamp(struct sock *sk);
static inline void net_timestamp(struct timeval *stamp)
{
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 28dca9b66467..4a7dc4157df4 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -159,7 +159,6 @@ extern struct tcp_bind_bucket *tcp_bucket_create(struct tcp_bind_hashbucket *hea
extern void tcp_bucket_destroy(struct tcp_bind_bucket *tb);
extern void tcp_bucket_unlock(struct sock *sk);
extern int tcp_port_rover;
-extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
/* These are AF independent. */
static __inline__ int tcp_bhashfn(__u16 lport)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 2c89b019388a..7078e743b732 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -178,8 +178,6 @@ struct xfrm_policy_afinfo {
extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
-extern struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
-extern void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
#define XFRM_ACQ_EXPIRES 30
@@ -200,8 +198,6 @@ struct xfrm_state_afinfo {
extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo);
extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo);
-extern struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
-extern void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
extern void xfrm_state_delete_tunnel(struct xfrm_state *x);
@@ -805,17 +801,15 @@ extern int xfrm_state_check_expire(struct xfrm_state *x);
extern void xfrm_state_insert(struct xfrm_state *x);
extern int xfrm_state_add(struct xfrm_state *x);
extern int xfrm_state_update(struct xfrm_state *x);
-extern int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb);
extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
extern void xfrm_state_delete(struct xfrm_state *x);
extern void xfrm_state_flush(u8 proto);
extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
-extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl);
extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
extern int xfrm4_rcv(struct sk_buff *skb);
-extern int xfrm4_output(struct sk_buff **pskb);
+extern int xfrm4_output(struct sk_buff *skb);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
extern int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi);
@@ -825,7 +819,7 @@ extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler);
extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr);
extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr);
extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr);
-extern int xfrm6_output(struct sk_buff **pskb);
+extern int xfrm6_output(struct sk_buff *skb);
#ifdef CONFIG_XFRM
extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type);
@@ -863,7 +857,6 @@ struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
xfrm_address_t *daddr, xfrm_address_t *saddr,
int create, unsigned short family);
extern void xfrm_policy_flush(void);
-extern void xfrm_policy_kill(struct xfrm_policy *);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
extern struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struct flowi *fl);
extern int xfrm_flush_bundles(void);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 3ee1dcd35e52..0d9ca98aee8f 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -35,6 +35,8 @@
#include "vlan.h"
#include "vlanproc.h"
+#define DRV_VERSION "1.8"
+
/* Global VLAN variables */
/* Our listing of VLAN group(s) */
@@ -42,8 +44,7 @@ struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
#define vlan_grp_hashfn(IDX) ((((IDX) >> VLAN_GRP_HASH_SHIFT) ^ (IDX)) & VLAN_GRP_HASH_MASK)
static char vlan_fullname[] = "802.1Q VLAN Support";
-static unsigned int vlan_version = 1;
-static unsigned int vlan_release = 8;
+static char vlan_version[] = DRV_VERSION;
static char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
static char vlan_buggyright[] = "David S. Miller <davem@redhat.com>";
@@ -84,8 +85,8 @@ static int __init vlan_proto_init(void)
{
int err;
- printk(VLAN_INF "%s v%u.%u %s\n",
- vlan_fullname, vlan_version, vlan_release, vlan_copyright);
+ printk(VLAN_INF "%s v%s %s\n",
+ vlan_fullname, vlan_version, vlan_copyright);
printk(VLAN_INF "All bugs added by %s\n",
vlan_buggyright);
@@ -735,3 +736,4 @@ static int vlan_ioctl_handler(void __user *arg)
}
MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/net/atm/common.c b/net/atm/common.c
index 56e34deef6c2..47f5413683c8 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -57,7 +57,7 @@ void vcc_insert_socket(struct sock *sk)
write_unlock_irq(&vcc_sklist_lock);
}
-void vcc_remove_socket(struct sock *sk)
+static void vcc_remove_socket(struct sock *sk)
{
write_lock_irq(&vcc_sklist_lock);
sk_del_node_init(sk);
@@ -86,7 +86,6 @@ static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
EXPORT_SYMBOL(vcc_hash);
EXPORT_SYMBOL(vcc_sklist_lock);
EXPORT_SYMBOL(vcc_insert_socket);
-EXPORT_SYMBOL(vcc_remove_socket);
static void vcc_sock_destruct(struct sock *sk)
{
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 50e4df3559aa..b240ad4a6308 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -197,7 +197,7 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
skb_pull(skb, VLAN_HLEN);
skb->nh.raw += VLAN_HLEN;
}
- skb->dst->output(&skb);
+ skb->dst->output(skb);
return 0;
}
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 8352eec5bec4..38f82829c12c 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -109,11 +109,17 @@ static inline int ebt_do_match (struct ebt_entry_match *m,
static inline int ebt_dev_check(char *entry, const struct net_device *device)
{
+ int i = 0;
+ char *devname = device->name;
+
if (*entry == '\0')
return 0;
if (!device)
return 1;
- return !!strcmp(entry, device->name);
+ /* 1 is the wildcard token */
+ while (entry[i] != '\0' && entry[i] != 1 && entry[i] == devname[i])
+ i++;
+ return (devname[i] != entry[i] && entry[i] != 1);
}
#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
diff --git a/net/core/dev.c b/net/core/dev.c
index df194c2067b8..9d39b2aa52ad 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1106,34 +1106,34 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
* Invalidate hardware checksum when packet is to be mangled, and
* complete checksum manually on outgoing path.
*/
-int skb_checksum_help(struct sk_buff **pskb, int inward)
+int skb_checksum_help(struct sk_buff *skb, int inward)
{
unsigned int csum;
- int ret = 0, offset = (*pskb)->h.raw - (*pskb)->data;
+ int ret = 0, offset = skb->h.raw - skb->data;
if (inward) {
- (*pskb)->ip_summed = CHECKSUM_NONE;
+ skb->ip_summed = CHECKSUM_NONE;
goto out;
}
- if (skb_cloned(*pskb)) {
- ret = pskb_expand_head(*pskb, 0, 0, GFP_ATOMIC);
+ if (skb_cloned(skb)) {
+ ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
if (ret)
goto out;
}
- if (offset > (int)(*pskb)->len)
+ if (offset > (int)skb->len)
BUG();
- csum = skb_checksum(*pskb, offset, (*pskb)->len-offset, 0);
+ csum = skb_checksum(skb, offset, skb->len-offset, 0);
- offset = (*pskb)->tail - (*pskb)->h.raw;
+ offset = skb->tail - skb->h.raw;
if (offset <= 0)
BUG();
- if ((*pskb)->csum + 2 > offset)
+ if (skb->csum + 2 > offset)
BUG();
- *(u16*)((*pskb)->h.raw + (*pskb)->csum) = csum_fold(csum);
- (*pskb)->ip_summed = CHECKSUM_NONE;
+ *(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
+ skb->ip_summed = CHECKSUM_NONE;
out:
return ret;
}
@@ -1282,7 +1282,7 @@ int dev_queue_xmit(struct sk_buff *skb)
(!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) &&
(!(dev->features & NETIF_F_IP_CSUM) ||
skb->protocol != htons(ETH_P_IP))))
- if (skb_checksum_help(&skb, 0))
+ if (skb_checksum_help(skb, 0))
goto out_kfree_skb;
diff --git a/net/core/dst.c b/net/core/dst.c
index 42aeae5959f5..8755f0de86dc 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -106,9 +106,9 @@ static int dst_discard_in(struct sk_buff *skb)
return 0;
}
-static int dst_discard_out(struct sk_buff **pskb)
+static int dst_discard_out(struct sk_buff *skb)
{
- kfree_skb(*pskb);
+ kfree_skb(skb);
return 0;
}
diff --git a/net/core/sock.c b/net/core/sock.c
index 3582a0f0ab3d..79d7e32e347a 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -175,6 +175,15 @@ static void sock_warn_obsolete_bsdism(const char *name)
}
}
+static void sock_disable_timestamp(struct sock *sk)
+{
+ if (sock_flag(sk, SOCK_TIMESTAMP)) {
+ sock_reset_flag(sk, SOCK_TIMESTAMP);
+ atomic_dec(&netstamp_needed);
+ }
+}
+
+
/*
* This is meant for all protocols to use and covers goings on
* at the socket level. Everything here is generic.
@@ -972,11 +981,6 @@ EXPORT_SYMBOL(sk_wait_data);
* function, some default processing is provided.
*/
-int sock_no_release(struct socket *sock)
-{
- return 0;
-}
-
int sock_no_bind(struct socket *sock, struct sockaddr *saddr, int len)
{
return -EOPNOTSUPP;
@@ -1247,15 +1251,6 @@ void sock_enable_timestamp(struct sock *sk)
}
EXPORT_SYMBOL(sock_enable_timestamp);
-void sock_disable_timestamp(struct sock *sk)
-{
- if (sock_flag(sk, SOCK_TIMESTAMP)) {
- sock_reset_flag(sk, SOCK_TIMESTAMP);
- atomic_dec(&netstamp_needed);
- }
-}
-EXPORT_SYMBOL(sock_disable_timestamp);
-
/*
* Get a socket option on an socket.
*
@@ -1371,7 +1366,6 @@ EXPORT_SYMBOL(sk_free);
EXPORT_SYMBOL(sk_send_sigurg);
EXPORT_SYMBOL(sock_alloc_send_pskb);
EXPORT_SYMBOL(sock_alloc_send_skb);
-EXPORT_SYMBOL(sock_getsockopt);
EXPORT_SYMBOL(sock_init_data);
EXPORT_SYMBOL(sock_kfree_s);
EXPORT_SYMBOL(sock_kmalloc);
@@ -1385,14 +1379,12 @@ EXPORT_SYMBOL(sock_no_listen);
EXPORT_SYMBOL(sock_no_mmap);
EXPORT_SYMBOL(sock_no_poll);
EXPORT_SYMBOL(sock_no_recvmsg);
-EXPORT_SYMBOL(sock_no_release);
EXPORT_SYMBOL(sock_no_sendmsg);
EXPORT_SYMBOL(sock_no_sendpage);
EXPORT_SYMBOL(sock_no_setsockopt);
EXPORT_SYMBOL(sock_no_shutdown);
EXPORT_SYMBOL(sock_no_socketpair);
EXPORT_SYMBOL(sock_rfree);
-EXPORT_SYMBOL(sock_rmalloc);
EXPORT_SYMBOL(sock_setsockopt);
EXPORT_SYMBOL(sock_wfree);
EXPORT_SYMBOL(sock_wmalloc);
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 05d84ed7e4e6..d8e24d47d044 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -419,6 +419,7 @@ static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb)
case DN_CI:
case DN_CD:
scp->state = DN_RJ;
+ sk->sk_err = ECONNREFUSED;
break;
case DN_RUN:
sk->sk_shutdown |= SHUTDOWN_MASK;
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 64bdf10b75b7..34f0b81e1784 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -683,9 +683,8 @@ out:
return NET_RX_DROP;
}
-static int dn_output(struct sk_buff **pskb)
+static int dn_output(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
struct dst_entry *dst = skb->dst;
struct dn_route *rt = (struct dn_route *)dst;
struct net_device *dev = dst->dev;
@@ -796,11 +795,6 @@ static int dn_rt_bug(struct sk_buff *skb)
return NET_RX_BAD;
}
-static int dn_rt_bug_out(struct sk_buff **pskb)
-{
- return dn_rt_bug(*pskb);
-}
-
static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
{
struct dn_fib_info *fi = res->fi;
@@ -1392,7 +1386,7 @@ make_route:
rt->u.dst.neighbour = neigh;
rt->u.dst.dev = out_dev;
rt->u.dst.lastuse = jiffies;
- rt->u.dst.output = dn_rt_bug_out;
+ rt->u.dst.output = dn_rt_bug;
switch(res.type) {
case RTN_UNICAST:
rt->u.dst.input = dn_forward;
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 57768575c82a..5befbf203fcf 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1165,8 +1165,6 @@ EXPORT_SYMBOL(inet_stream_connect);
EXPORT_SYMBOL(inet_stream_ops);
EXPORT_SYMBOL(inet_unregister_protosw);
EXPORT_SYMBOL(net_statistics);
-EXPORT_SYMBOL(tcp_protocol);
-EXPORT_SYMBOL(udp_protocol);
#ifdef INET_REFCNT_DEBUG
EXPORT_SYMBOL(inet_sock_nr);
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index ec1f08872f1d..a1349862a8ce 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -163,6 +163,8 @@ void fib_release_info(struct fib_info *fi)
if (fi->fib_prefsrc)
hlist_del(&fi->fib_lhash);
change_nexthops(fi) {
+ if (!nh->nh_dev)
+ continue;
hlist_del(&nh->nh_hash);
} endfor_nexthops(fi)
fi->fib_dead = 1;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 8ef2b82630a2..062981affa1c 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -224,9 +224,8 @@ int ip_finish_output(struct sk_buff *skb)
ip_finish_output2);
}
-int ip_mc_output(struct sk_buff **pskb)
+int ip_mc_output(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
struct sock *sk = skb->sk;
struct rtable *rt = (struct rtable*)skb->dst;
struct net_device *dev = rt->u.dst.dev;
@@ -285,10 +284,8 @@ int ip_mc_output(struct sk_buff **pskb)
return ip_finish_output(skb);
}
-int ip_output(struct sk_buff **pskb)
+int ip_output(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
-
IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);
if ((skb->len > dst_pmtu(skb->dst) || skb_shinfo(skb)->frag_list) &&
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index f2b3e7e5bb18..b0d4ce63e973 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -395,7 +395,7 @@ static inline struct arpt_table *arpt_find_table_lock(const char *name, int *err
return find_inlist_lock(&arpt_tables, name, "arptable_", error, mutex);
}
-struct arpt_target *arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex)
+static struct arpt_target *arpt_find_target_lock(const char *name, int *error, struct semaphore *mutex)
{
return find_inlist_lock(&arpt_target, name, "arpt_", error, mutex);
}
@@ -1325,7 +1325,6 @@ static void __exit fini(void)
EXPORT_SYMBOL(arpt_register_table);
EXPORT_SYMBOL(arpt_unregister_table);
EXPORT_SYMBOL(arpt_do_table);
-EXPORT_SYMBOL(arpt_find_target_lock);
EXPORT_SYMBOL(arpt_register_target);
EXPORT_SYMBOL(arpt_unregister_target);
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 39e02a0a93b2..b3a6e6427c00 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -352,16 +352,14 @@ __ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
{
struct ip_conntrack_tuple_hash *h;
unsigned int hash = hash_conntrack(tuple);
- /* use per_cpu() to avoid multiple calls to smp_processor_id() */
- unsigned int cpu = smp_processor_id();
MUST_BE_READ_LOCKED(&ip_conntrack_lock);
list_for_each_entry(h, &ip_conntrack_hash[hash], list) {
if (conntrack_tuple_cmp(h, tuple, ignored_conntrack)) {
- per_cpu(ip_conntrack_stat, cpu).found++;
+ CONNTRACK_STAT_INC(found);
return h;
}
- per_cpu(ip_conntrack_stat, cpu).searched++;
+ CONNTRACK_STAT_INC(searched);
}
return NULL;
@@ -436,13 +434,14 @@ __ip_conntrack_confirm(struct sk_buff *skb)
add_timer(&ct->timeout);
atomic_inc(&ct->ct_general.use);
set_bit(IPS_CONFIRMED_BIT, &ct->status);
- WRITE_UNLOCK(&ip_conntrack_lock);
CONNTRACK_STAT_INC(insert);
+ WRITE_UNLOCK(&ip_conntrack_lock);
return NF_ACCEPT;
}
- WRITE_UNLOCK(&ip_conntrack_lock);
CONNTRACK_STAT_INC(insert_failed);
+ WRITE_UNLOCK(&ip_conntrack_lock);
+
return NF_DROP;
}
diff --git a/net/ipv4/netfilter/ip_fw_compat.c b/net/ipv4/netfilter/ip_fw_compat.c
index f7146f31b6c3..840643de241f 100644
--- a/net/ipv4/netfilter/ip_fw_compat.c
+++ b/net/ipv4/netfilter/ip_fw_compat.c
@@ -69,7 +69,7 @@ fw_in(unsigned int hooknum,
/* Assume worse case: any hook could change packet */
(*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED;
if ((*pskb)->ip_summed == CHECKSUM_HW)
- if (skb_checksum_help(pskb, (out == NULL)))
+ if (skb_checksum_help(*pskb, (out == NULL)))
return NF_DROP;
switch (hooknum) {
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index e4e961225c5f..71bd2e05b0b2 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -86,7 +86,7 @@ ip_nat_fn(unsigned int hooknum,
/* If we had a hardware checksum before, it's now invalid */
if ((*pskb)->ip_summed == CHECKSUM_HW)
- if (skb_checksum_help(pskb, (out == NULL)))
+ if (skb_checksum_help(*pskb, (out == NULL)))
return NF_DROP;
ct = ip_conntrack_get(*pskb, &ctinfo);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 8da90bdb37c2..3e601a80d580 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -471,7 +471,7 @@ find_match_lock(const char *name, int *error, struct semaphore *mutex)
return find_inlist_lock(&ipt_match, name, "ipt_", error, mutex);
}
-struct ipt_target *
+static struct ipt_target *
ipt_find_target_lock(const char *name, int *error, struct semaphore *mutex)
{
return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
@@ -1877,7 +1877,6 @@ EXPORT_SYMBOL(ipt_unregister_match);
EXPORT_SYMBOL(ipt_do_table);
EXPORT_SYMBOL(ipt_register_target);
EXPORT_SYMBOL(ipt_unregister_target);
-EXPORT_SYMBOL(ipt_find_target_lock);
module_init(init);
module_exit(fini);
diff --git a/net/ipv4/netfilter/ipt_CONNMARK.c b/net/ipv4/netfilter/ipt_CONNMARK.c
index ef3d21703121..30ddd3e18eb7 100644
--- a/net/ipv4/netfilter/ipt_CONNMARK.c
+++ b/net/ipv4/netfilter/ipt_CONNMARK.c
@@ -60,7 +60,7 @@ target(struct sk_buff **pskb,
break;
case IPT_CONNMARK_RESTORE:
nfmark = (*pskb)->nfmark;
- diff = (ct->mark ^ nfmark & markinfo->mask);
+ diff = (ct->mark ^ nfmark) & markinfo->mask;
if (diff != 0) {
(*pskb)->nfmark = nfmark ^ diff;
(*pskb)->nfcache |= NFC_ALTERED;
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index 120109cd294d..f659ec3c9278 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -86,7 +86,7 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward)
memcpy((*pskb)->data + (*pskb)->nh.iph->ihl*4,
&_tcph, sizeof(_tcph));
if ((*pskb)->ip_summed == CHECKSUM_HW)
- if (skb_checksum_help(pskb, inward))
+ if (skb_checksum_help(*pskb, inward))
return 0;
(*pskb)->nfcache |= NFC_ALTERED;
}
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index ea02a12d7625..6beaec1e1f2b 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -81,8 +81,8 @@ masquerade_target(struct sk_buff **pskb,
enum ip_conntrack_info ctinfo;
const struct ip_nat_multi_range *mr;
struct ip_nat_multi_range newrange;
- u_int32_t newsrc;
struct rtable *rt;
+ u_int32_t newsrc;
IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
@@ -96,36 +96,13 @@ masquerade_target(struct sk_buff **pskb,
|| ctinfo == IP_CT_RELATED + IP_CT_IS_REPLY));
mr = targinfo;
-
- {
- struct flowi fl = { .nl_u = { .ip4_u =
- { .daddr = (*pskb)->nh.iph->daddr,
- .tos = (RT_TOS((*pskb)->nh.iph->tos) |
- RTO_CONN),
-#ifdef CONFIG_IP_ROUTE_FWMARK
- .fwmark = (*pskb)->nfmark
-#endif
- } } };
- if (ip_route_output_key(&rt, &fl) != 0) {
- /* Funky routing can do this. */
- if (net_ratelimit())
- printk("MASQUERADE:"
- " No route: Rusty's brain broke!\n");
- return NF_DROP;
- }
- if (rt->u.dst.dev != out) {
- if (net_ratelimit())
- printk("MASQUERADE:"
- " Route sent us somewhere else.\n");
- ip_rt_put(rt);
- return NF_DROP;
- }
+ rt = (struct rtable *)(*pskb)->dst;
+ newsrc = inet_select_addr(out, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+ if (!newsrc) {
+ printk("MASQUERADE: %s ate my IP address\n", out->name);
+ return NF_DROP;
}
- newsrc = rt->rt_src;
- DEBUGP("newsrc = %u.%u.%u.%u\n", NIPQUAD(newsrc));
- ip_rt_put(rt);
-
WRITE_LOCK(&masq_lock);
ct->nat.masq_index = out->ifindex;
WRITE_UNLOCK(&masq_lock);
@@ -157,6 +134,18 @@ device_cmp(const struct ip_conntrack *i, void *_ina)
return ret;
}
+static inline int
+connect_unassure(const struct ip_conntrack *i, void *_ina)
+{
+ struct in_ifaddr *ina = _ina;
+
+ /* We reset the ASSURED bit on all connections, so they will
+ * get reaped under memory pressure. */
+ if (i->nat.masq_index == ina->ifa_dev->dev->ifindex)
+ clear_bit(IPS_ASSURED_BIT, (unsigned long *)&i->status);
+ return 0;
+}
+
static int masq_inet_event(struct notifier_block *this,
unsigned long event,
void *ptr)
@@ -166,6 +155,8 @@ static int masq_inet_event(struct notifier_block *this,
* entries. */
if (event == NETDEV_UP)
ip_ct_selective_cleanup(device_cmp, ptr);
+ else if (event == NETDEV_DOWN)
+ ip_ct_selective_cleanup(connect_unassure, ptr);
return NOTIFY_DONE;
}
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 51d16d33bcbd..56d018940954 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -1,7 +1,7 @@
/*
* netfilter module for userspace packet logging daemons
*
- * (C) 2000-2002 by Harald Welte <laforge@netfilter.org>
+ * (C) 2000-2004 by Harald Welte <laforge@netfilter.org>
*
* 2000/09/22 ulog-cprange feature added
* 2001/01/04 in-kernel queue as proposed by Sebastian Zander
@@ -13,6 +13,8 @@
* 2002/07/07 remove broken nflog_rcv() function -HW
* 2002/08/29 fix shifted/unshifted nlgroup bug -HW
* 2002/10/30 fix uninitialized mac_len field - <Anders K. Pedersen>
+ * 2004/10/25 fix erroneous calculation of 'len' parameter to NLMSG_PUT
+ * resulting in bogus 'error during NLMSG_PUT' messages.
*
* (C) 1999-2001 Paul `Rusty' Russell
* (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
@@ -212,7 +214,7 @@ static void ipt_ulog_packet(unsigned int hooknum,
/* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */
nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT,
- size - sizeof(*nlh));
+ sizeof(*pm)+copy_len);
ub->qlen++;
pm = NLMSG_DATA(nlh);
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 08b45abff125..2ec51e2d2973 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -407,7 +407,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
printk(KERN_INFO "%s forgot to set AF_INET in "
"raw sendmsg. Fix it!\n",
current->comm);
- err = -EINVAL;
+ err = -EAFNOSUPPORT;
if (usin->sin_family)
goto out;
}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index fd023db82df9..27ce169f63b9 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1367,10 +1367,8 @@ static void ipv4_link_failure(struct sk_buff *skb)
dst_set_expires(&rt->u.dst, 0);
}
-static int ip_rt_bug(struct sk_buff **pskb)
+static int ip_rt_bug(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
-
printk(KERN_DEBUG "ip_rt_bug: %u.%u.%u.%u -> %u.%u.%u.%u, %s\n",
NIPQUAD(skb->nh.iph->saddr), NIPQUAD(skb->nh.iph->daddr),
skb->dev ? skb->dev->name : "?");
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 462cbda0277f..67ddd1d9e066 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2307,7 +2307,6 @@ void __init tcp_init(void)
EXPORT_SYMBOL(tcp_accept);
EXPORT_SYMBOL(tcp_close);
-EXPORT_SYMBOL(tcp_close_state);
EXPORT_SYMBOL(tcp_destroy_sock);
EXPORT_SYMBOL(tcp_disconnect);
EXPORT_SYMBOL(tcp_getsockopt);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ece320e60f71..e8769f30f0c6 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2369,25 +2369,19 @@ static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb,
{
struct tcp_opt *tp = tcp_sk(sk);
struct tcp_skb_cb *scb = TCP_SKB_CB(skb);
- __u32 mss = tcp_skb_mss(skb);
- __u32 snd_una = tp->snd_una;
- __u32 orig_seq, seq;
- __u32 packets_acked = 0;
+ __u32 seq = tp->snd_una;
+ __u32 packets_acked;
int acked = 0;
/* If we get here, the whole TSO packet has not been
* acked.
*/
- BUG_ON(!after(scb->end_seq, snd_una));
+ BUG_ON(!after(scb->end_seq, seq));
- seq = orig_seq = scb->seq;
- while (!after(seq + mss, snd_una)) {
- packets_acked++;
- seq += mss;
- }
-
- if (tcp_trim_head(sk, skb, (seq - orig_seq)))
+ packets_acked = tcp_skb_pcount(skb);
+ if (tcp_trim_head(sk, skb, seq - scb->seq))
return 0;
+ packets_acked -= tcp_skb_pcount(skb);
if (packets_acked) {
__u8 sacked = scb->sacked;
@@ -4963,7 +4957,6 @@ discard:
EXPORT_SYMBOL(sysctl_tcp_ecn);
EXPORT_SYMBOL(sysctl_tcp_reordering);
-EXPORT_SYMBOL(tcp_cwnd_application_limited);
EXPORT_SYMBOL(tcp_parse_options);
EXPORT_SYMBOL(tcp_rcv_established);
EXPORT_SYMBOL(tcp_rcv_state_process);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 96594f8a8088..3df3ada30e6c 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -448,8 +448,8 @@ static struct sock *__tcp_v4_lookup_listener(struct hlist_head *head, u32 daddr,
}
/* Optimize the common listener case. */
-inline struct sock *tcp_v4_lookup_listener(u32 daddr, unsigned short hnum,
- int dif)
+static inline struct sock *tcp_v4_lookup_listener(u32 daddr,
+ unsigned short hnum, int dif)
{
struct sock *sk = NULL;
struct hlist_head *head;
@@ -2653,7 +2653,6 @@ EXPORT_SYMBOL(tcp_unhash);
EXPORT_SYMBOL(tcp_v4_conn_request);
EXPORT_SYMBOL(tcp_v4_connect);
EXPORT_SYMBOL(tcp_v4_do_rcv);
-EXPORT_SYMBOL(tcp_v4_lookup_listener);
EXPORT_SYMBOL(tcp_v4_rebuild_header);
EXPORT_SYMBOL(tcp_v4_remember_stamp);
EXPORT_SYMBOL(tcp_v4_send_check);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 10c49d779487..0b08a3499b29 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -588,7 +588,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
/* Any change of skb->len requires recalculation of tso
* factor and mss.
*/
- if (tcp_skb_mss(skb))
+ if (tcp_skb_pcount(skb) > 1)
tcp_set_skb_tso_segs(skb, tcp_skb_mss(skb));
return 0;
@@ -1720,12 +1720,7 @@ void tcp_send_probe0(struct sock *sk)
}
}
-EXPORT_SYMBOL(tcp_acceptable_seq);
EXPORT_SYMBOL(tcp_connect);
-EXPORT_SYMBOL(tcp_connect_init);
EXPORT_SYMBOL(tcp_make_synack);
-EXPORT_SYMBOL(tcp_send_synack);
EXPORT_SYMBOL(tcp_simple_retransmit);
EXPORT_SYMBOL(tcp_sync_mss);
-EXPORT_SYMBOL(tcp_write_wakeup);
-EXPORT_SYMBOL(tcp_write_xmit);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 8a4c26ed9712..6bd005dbd80c 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -531,7 +531,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
return -EINVAL;
if (usin->sin_family != AF_INET) {
if (usin->sin_family != AF_UNSPEC)
- return -EINVAL;
+ return -EAFNOSUPPORT;
}
daddr = usin->sin_addr.s_addr;
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 21832dfc376e..3c70b08f908c 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -91,16 +91,14 @@ out:
return ret;
}
-int xfrm4_output(struct sk_buff **pskb)
+int xfrm4_output(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
int err;
if (skb->ip_summed == CHECKSUM_HW) {
- err = skb_checksum_help(pskb, 0);
- skb = *pskb;
+ err = skb_checksum_help(skb, 0);
if (err)
goto error_nolock;
}
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 737937e4471b..2fbe96226000 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -404,6 +404,7 @@ static struct inet6_dev * ipv6_find_idev(struct net_device *dev)
return idev;
}
+#ifdef CONFIG_SYSCTL
static void dev_forward_change(struct inet6_dev *idev)
{
struct net_device *dev;
@@ -449,7 +450,7 @@ static void addrconf_forward_change(void)
}
read_unlock(&dev_base_lock);
}
-
+#endif
/* Nobody refers to this ifaddr, destroy it */
@@ -760,7 +761,7 @@ static int inline ipv6_saddr_pref(const struct inet6_ifaddr *ifp, u8 invpref)
#endif
int ipv6_dev_get_saddr(struct net_device *dev,
- struct in6_addr *daddr, struct in6_addr *saddr, int onlink)
+ struct in6_addr *daddr, struct in6_addr *saddr)
{
struct inet6_ifaddr *ifp = NULL;
struct inet6_ifaddr *match = NULL;
@@ -769,10 +770,7 @@ int ipv6_dev_get_saddr(struct net_device *dev,
int err;
int hiscore = -1, score;
- if (!onlink)
- scope = ipv6_addr_scope(daddr);
- else
- scope = IFA_LINK;
+ scope = ipv6_addr_scope(daddr);
/*
* known dev
@@ -877,17 +875,7 @@ out:
int ipv6_get_saddr(struct dst_entry *dst,
struct in6_addr *daddr, struct in6_addr *saddr)
{
- struct rt6_info *rt;
- struct net_device *dev = NULL;
- int onlink;
-
- rt = (struct rt6_info *) dst;
- if (rt)
- dev = rt->rt6i_dev;
-
- onlink = (rt && (rt->rt6i_flags & RTF_ALLONLINK));
-
- return ipv6_dev_get_saddr(dev, daddr, saddr, onlink);
+ return ipv6_dev_get_saddr(dst ? dst->dev : NULL, daddr, saddr);
}
@@ -3042,7 +3030,7 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
addrconf_forward_change();
}
if (*valp)
- rt6_purge_dflt_routers(0);
+ rt6_purge_dflt_routers();
}
return ret;
@@ -3096,7 +3084,7 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table,
}
if (*valp)
- rt6_purge_dflt_routers(0);
+ rt6_purge_dflt_routers();
} else
*valp = new;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 1816b81ae454..d394bd2d0285 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -433,7 +433,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
if (fn->fn_flags&RTN_TL_ROOT &&
fn->leaf == &ip6_null_entry &&
- !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF | RTF_ALLONLINK)) ){
+ !(rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) ){
fn->leaf = rt;
rt->u.next = NULL;
goto out;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 33260cfacd35..e74a46201ef1 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -56,7 +56,7 @@
#include <net/xfrm.h>
#include <net/checksum.h>
-static int ip6_fragment(struct sk_buff **pskb, int (*output)(struct sk_buff**));
+static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
static __inline__ void ipv6_select_ident(struct sk_buff *skb, struct frag_hdr *fhdr)
{
@@ -108,9 +108,8 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb)
}
-static int ip6_output2(struct sk_buff **pskb)
+static int ip6_output2(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
struct dst_entry *dst = skb->dst;
struct net_device *dev = dst->dev;
@@ -146,14 +145,12 @@ static int ip6_output2(struct sk_buff **pskb)
return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb,NULL, skb->dev,ip6_output_finish);
}
-int ip6_output(struct sk_buff **pskb)
+int ip6_output(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
-
if ((skb->len > dst_pmtu(skb->dst) || skb_shinfo(skb)->frag_list))
- return ip6_fragment(pskb, ip6_output2);
+ return ip6_fragment(skb, ip6_output2);
else
- return ip6_output2(pskb);
+ return ip6_output2(skb);
}
#ifdef CONFIG_NETFILTER
@@ -518,10 +515,10 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
return offset;
}
-static int ip6_fragment(struct sk_buff **pskb, int (*output)(struct sk_buff**))
+static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
{
struct net_device *dev;
- struct sk_buff *frag, *skb = *pskb;
+ struct sk_buff *frag;
struct rt6_info *rt = (struct rt6_info*)skb->dst;
struct ipv6hdr *tmp_hdr;
struct frag_hdr *fh;
@@ -610,7 +607,7 @@ static int ip6_fragment(struct sk_buff **pskb, int (*output)(struct sk_buff**))
ip6_copy_metadata(frag, skb);
}
- err = output(&skb);
+ err = output(skb);
if (err || !frag)
break;
@@ -726,7 +723,7 @@ slow_path:
IP6_INC_STATS(IPSTATS_MIB_FRAGCREATES);
- err = output(&frag);
+ err = output(frag);
if (err)
goto fail;
}
diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c
index 122482817501..a2d9601f98d3 100644
--- a/net/ipv6/ipv6_syms.c
+++ b/net/ipv6/ipv6_syms.c
@@ -35,13 +35,9 @@ EXPORT_SYMBOL(ipv6_chk_addr);
EXPORT_SYMBOL(in6addr_any);
EXPORT_SYMBOL(in6addr_loopback);
EXPORT_SYMBOL(in6_dev_finish_destroy);
-EXPORT_SYMBOL(ip6_find_1stfragopt);
#ifdef CONFIG_XFRM
EXPORT_SYMBOL(xfrm6_rcv);
#endif
EXPORT_SYMBOL(rt6_lookup);
EXPORT_SYMBOL(fl6_sock_lookup);
-EXPORT_SYMBOL(ip6_append_data);
-EXPORT_SYMBOL(ip6_flush_pending_frames);
-EXPORT_SYMBOL(ip6_push_pending_frames);
EXPORT_SYMBOL(ipv6_push_nfrag_opts);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 685a02d2ebf5..30f77ff07781 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -396,7 +396,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
src_addr = solicited_addr;
in6_ifa_put(ifp);
} else {
- if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr, 0))
+ if (ipv6_dev_get_saddr(dev, daddr, &tmpaddr))
return;
src_addr = &tmpaddr;
}
@@ -921,6 +921,64 @@ static void ndisc_recv_na(struct sk_buff *skb)
}
}
+static void ndisc_recv_rs(struct sk_buff *skb)
+{
+ struct rs_msg *rs_msg = (struct rs_msg *) skb->h.raw;
+ unsigned long ndoptlen = skb->len - sizeof(*rs_msg);
+ struct neighbour *neigh;
+ struct inet6_dev *idev;
+ struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
+ struct ndisc_options ndopts;
+ u8 *lladdr = NULL;
+ int lladdrlen = 0;
+
+ if (skb->len < sizeof(*rs_msg))
+ return;
+
+ idev = in6_dev_get(skb->dev);
+ if (!idev) {
+ if (net_ratelimit())
+ ND_PRINTK1("ICMP6 RS: can't find in6 device\n");
+ return;
+ }
+
+ /* Don't accept RS if we're not in router mode */
+ if (!idev->cnf.forwarding || idev->cnf.accept_ra)
+ goto out;
+
+ /*
+ * Don't update NCE if src = ::;
+ * this implies that the source node has no ip address assigned yet.
+ */
+ if (ipv6_addr_any(saddr))
+ goto out;
+
+ /* Parse ND options */
+ if (!ndisc_parse_options(rs_msg->opt, ndoptlen, &ndopts)) {
+ if (net_ratelimit())
+ ND_PRINTK2("ICMP6 NS: invalid ND option, ignored\n");
+ goto out;
+ }
+
+ if (ndopts.nd_opts_src_lladdr) {
+ lladdr = (u8 *)(ndopts.nd_opts_src_lladdr + 1);
+ lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
+ if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len))
+ goto out;
+ }
+
+ neigh = __neigh_lookup(&nd_tbl, saddr, skb->dev, 1);
+ if (neigh) {
+ neigh_update(neigh, lladdr, NUD_STALE,
+ NEIGH_UPDATE_F_WEAK_OVERRIDE|
+ NEIGH_UPDATE_F_OVERRIDE|
+ NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
+ neigh_release(neigh);
+ }
+out:
+ in6_dev_put(idev);
+}
+
static void ndisc_router_discovery(struct sk_buff *skb)
{
struct ra_msg *ra_msg = (struct ra_msg *) skb->h.raw;
@@ -1026,7 +1084,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
* delete it
*/
- rt6_purge_dflt_routers(RTF_ALLONLINK);
+ rt6_purge_dflt_routers();
}
if (rt)
@@ -1395,6 +1453,10 @@ int ndisc_rcv(struct sk_buff *skb)
ndisc_recv_na(skb);
break;
+ case NDISC_ROUTER_SOLICITATION:
+ ndisc_recv_rs(skb);
+ break;
+
case NDISC_ROUTER_ADVERTISEMENT:
ndisc_router_discovery(skb);
break;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 0cef15b866f5..80b3e3d301c0 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -158,14 +158,15 @@ ip6t_ext_hdr(u8 nexthdr)
/* Returns whether matches rule or not. */
static inline int
ip6_packet_match(const struct sk_buff *skb,
- const struct ipv6hdr *ipv6,
const char *indev,
const char *outdev,
const struct ip6t_ip6 *ip6info,
- int isfrag)
+ unsigned int *protoff,
+ int *fragoff)
{
size_t i;
unsigned long ret;
+ const struct ipv6hdr *ipv6 = skb->nh.ipv6h;
#define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg))
@@ -216,9 +217,10 @@ ip6_packet_match(const struct sk_buff *skb,
/* look for the desired protocol header */
if((ip6info->flags & IP6T_F_PROTO)) {
u_int8_t currenthdr = ipv6->nexthdr;
- struct ipv6_opt_hdr *hdrptr;
+ struct ipv6_opt_hdr _hdr, *hp;
u_int16_t ptr; /* Header offset in skb */
u_int16_t hdrlen; /* Header */
+ u_int16_t _fragoff = 0, *fp = NULL;
ptr = IPV6_HDR_LEN;
@@ -234,23 +236,41 @@ ip6_packet_match(const struct sk_buff *skb,
(currenthdr == IPPROTO_ESP))
return 0;
- hdrptr = (struct ipv6_opt_hdr *)(skb->data + ptr);
+ hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+ BUG_ON(hp == NULL);
/* Size calculation */
if (currenthdr == IPPROTO_FRAGMENT) {
+ fp = skb_header_pointer(skb,
+ ptr+offsetof(struct frag_hdr,
+ frag_off),
+ sizeof(_fragoff),
+ &_fragoff);
+ if (fp == NULL)
+ return 0;
+
+ _fragoff = ntohs(*fp) & ~0x7;
hdrlen = 8;
} else if (currenthdr == IPPROTO_AH)
- hdrlen = (hdrptr->hdrlen+2)<<2;
+ hdrlen = (hp->hdrlen+2)<<2;
else
- hdrlen = ipv6_optlen(hdrptr);
+ hdrlen = ipv6_optlen(hp);
- currenthdr = hdrptr->nexthdr;
+ currenthdr = hp->nexthdr;
ptr += hdrlen;
/* ptr is too large */
if ( ptr > skb->len )
return 0;
+ if (_fragoff) {
+ if (ip6t_ext_hdr(currenthdr))
+ return 0;
+ break;
+ }
}
+ *protoff = ptr;
+ *fragoff = _fragoff;
+
/* currenthdr contains the protocol header */
dprintf("Packet protocol %hi ?= %s%hi.\n",
@@ -292,9 +312,9 @@ ip6_checkentry(const struct ip6t_ip6 *ipv6)
static unsigned int
ip6t_error(struct sk_buff **pskb,
- unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
+ unsigned int hooknum,
const void *targinfo,
void *userinfo)
{
@@ -310,13 +330,12 @@ int do_match(struct ip6t_entry_match *m,
const struct net_device *in,
const struct net_device *out,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
/* Stop iteration if it doesn't match */
if (!m->u.kernel.match->match(skb, in, out, m->data,
- offset, hdr, datalen, hotdrop))
+ offset, protoff, hotdrop))
return 1;
else
return 0;
@@ -338,10 +357,8 @@ ip6t_do_table(struct sk_buff **pskb,
void *userdata)
{
static const char nulldevname[IFNAMSIZ];
- u_int16_t offset = 0;
- struct ipv6hdr *ipv6;
- void *protohdr;
- u_int16_t datalen;
+ int offset = 0;
+ unsigned int protoff = 0;
int hotdrop = 0;
/* Initializing verdict to NF_DROP keeps gcc happy. */
unsigned int verdict = NF_DROP;
@@ -354,9 +371,6 @@ ip6t_do_table(struct sk_buff **pskb,
return NF_DROP;
/* Initialization */
- ipv6 = (*pskb)->nh.ipv6h;
- protohdr = (u_int32_t *)((char *)ipv6 + IPV6_HDR_LEN);
- datalen = (*pskb)->len - IPV6_HDR_LEN;
indev = in ? in->name : nulldevname;
outdev = out ? out->name : nulldevname;
@@ -393,17 +407,19 @@ ip6t_do_table(struct sk_buff **pskb,
IP_NF_ASSERT(e);
IP_NF_ASSERT(back);
(*pskb)->nfcache |= e->nfcache;
- if (ip6_packet_match(*pskb, ipv6, indev, outdev,
- &e->ipv6, offset)) {
+ if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6,
+ &protoff, &offset)) {
struct ip6t_entry_target *t;
if (IP6T_MATCH_ITERATE(e, do_match,
*pskb, in, out,
- offset, protohdr,
- datalen, &hotdrop) != 0)
+ offset, protoff, &hotdrop) != 0)
goto no_match;
- ADD_COUNTER(e->counters, ntohs(ipv6->payload_len) + IPV6_HDR_LEN, 1);
+ ADD_COUNTER(e->counters,
+ ntohs((*pskb)->nh.ipv6h->payload_len)
+ + IPV6_HDR_LEN,
+ 1);
t = ip6t_get_target(e);
IP_NF_ASSERT(t->u.kernel.target);
@@ -443,8 +459,8 @@ ip6t_do_table(struct sk_buff **pskb,
= 0xeeeeeeec;
#endif
verdict = t->u.kernel.target->target(pskb,
- hook,
in, out,
+ hook,
t->data,
userdata);
@@ -459,11 +475,6 @@ ip6t_do_table(struct sk_buff **pskb,
((struct ip6t_entry *)table_base)->comefrom
= 0x57acc001;
#endif
- /* Target might have changed stuff. */
- ipv6 = (*pskb)->nh.ipv6h;
- protohdr = (u_int32_t *)((void *)ipv6 + IPV6_HDR_LEN);
- datalen = (*pskb)->len - IPV6_HDR_LEN;
-
if (verdict == IP6T_CONTINUE)
e = (void *)e + e->next_offset;
else
@@ -554,7 +565,7 @@ find_match_lock(const char *name, int *error, struct semaphore *mutex)
return find_inlist_lock(&ip6t_match, name, "ip6t_", error, mutex);
}
-struct ip6t_target *
+static struct ip6t_target *
ip6t_find_target_lock(const char *name, int *error, struct semaphore *mutex)
{
return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
@@ -1535,26 +1546,31 @@ port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
static int
tcp_find_option(u_int8_t option,
- const struct tcphdr *tcp,
- u_int16_t datalen,
+ const struct sk_buff *skb,
+ unsigned int tcpoff,
+ unsigned int optlen,
int invert,
int *hotdrop)
{
- unsigned int i = sizeof(struct tcphdr);
- const u_int8_t *opt = (u_int8_t *)tcp;
+ /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */
+ u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
+ unsigned int i;
duprintf("tcp_match: finding option\n");
+ if (!optlen)
+ return invert;
/* If we don't have the whole header, drop packet. */
- if (tcp->doff * 4 < sizeof(struct tcphdr) ||
- tcp->doff * 4 > datalen) {
+ op = skb_header_pointer(skb, tcpoff + sizeof(struct tcphdr), optlen,
+ _opt);
+ if (op == NULL) {
*hotdrop = 1;
return 0;
}
- while (i < tcp->doff * 4) {
- if (opt[i] == option) return !invert;
- if (opt[i] < 2) i++;
- else i += opt[i+1]?:1;
+ for (i = 0; i < optlen; ) {
+ if (op[i] == option) return !invert;
+ if (op[i] < 2) i++;
+ else i += op[i+1]?:1;
}
return invert;
@@ -1566,27 +1582,31 @@ tcp_match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- const struct tcphdr *tcp;
+ struct tcphdr _tcph, *th;
const struct ip6t_tcp *tcpinfo = matchinfo;
- int tcpoff;
- u8 nexthdr = skb->nh.ipv6h->nexthdr;
-
- /* To quote Alan:
- Don't allow a fragment of TCP 8 bytes in. Nobody normal
- causes this. Its a cracker trying to break in by doing a
- flag overwrite to pass the direction checks.
- */
+ if (offset) {
+ /* To quote Alan:
- if (offset == 1) {
- duprintf("Dropping evil TCP offset=1 frag.\n");
- *hotdrop = 1;
+ Don't allow a fragment of TCP 8 bytes in. Nobody normal
+ causes this. Its a cracker trying to break in by doing a
+ flag overwrite to pass the direction checks.
+ */
+ if (offset == 1) {
+ duprintf("Dropping evil TCP offset=1 frag.\n");
+ *hotdrop = 1;
+ }
+ /* Must not be a fragment. */
return 0;
- } else if (offset == 0 && datalen < sizeof(struct tcphdr)) {
+ }
+
+#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
+
+ th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
+ if (th == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil TCP offset=0 tinygram.\n");
@@ -1594,45 +1614,30 @@ tcp_match(const struct sk_buff *skb,
return 0;
}
- tcpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
- tcpoff = ipv6_skip_exthdr(skb, tcpoff, &nexthdr, skb->len - tcpoff);
- if (tcpoff < 0 || tcpoff > skb->len) {
- duprintf("tcp_match: cannot skip exthdr. Dropping.\n");
- *hotdrop = 1;
+ if (!port_match(tcpinfo->spts[0], tcpinfo->spts[1],
+ ntohs(th->source),
+ !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT)))
return 0;
- } else if (nexthdr == IPPROTO_FRAGMENT)
+ if (!port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
+ ntohs(th->dest),
+ !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT)))
return 0;
- else if (nexthdr != IPPROTO_TCP ||
- skb->len - tcpoff < sizeof(struct tcphdr)) {
- /* cannot be occured */
- duprintf("tcp_match: cannot get TCP header. Dropping.\n");
- *hotdrop = 1;
+ if (!FWINVTCP((((unsigned char *)th)[13] & tcpinfo->flg_mask)
+ == tcpinfo->flg_cmp,
+ IP6T_TCP_INV_FLAGS))
return 0;
+ if (tcpinfo->option) {
+ if (th->doff * 4 < sizeof(_tcph)) {
+ *hotdrop = 1;
+ return 0;
+ }
+ if (!tcp_find_option(tcpinfo->option, skb, protoff,
+ th->doff*4 - sizeof(*th),
+ tcpinfo->invflags & IP6T_TCP_INV_OPTION,
+ hotdrop))
+ return 0;
}
-
- tcp = (struct tcphdr *)(skb->data + tcpoff);
-
- /* FIXME: Try tcp doff >> packet len against various stacks --RR */
-
-#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
-
- /* Must not be a fragment. */
- return !offset
- && port_match(tcpinfo->spts[0], tcpinfo->spts[1],
- ntohs(tcp->source),
- !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT))
- && port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
- ntohs(tcp->dest),
- !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT))
- && FWINVTCP((((unsigned char *)tcp)[13]
- & tcpinfo->flg_mask)
- == tcpinfo->flg_cmp,
- IP6T_TCP_INV_FLAGS)
- && (!tcpinfo->option
- || tcp_find_option(tcpinfo->option, tcp, datalen,
- tcpinfo->invflags
- & IP6T_TCP_INV_OPTION,
- hotdrop));
+ return 1;
}
/* Called when user tries to insert an entry of this type. */
@@ -1658,16 +1663,18 @@ udp_match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- const struct udphdr *udp;
+ struct udphdr _udph, *uh;
const struct ip6t_udp *udpinfo = matchinfo;
- int udpoff;
- u8 nexthdr = skb->nh.ipv6h->nexthdr;
- if (offset == 0 && datalen < sizeof(struct udphdr)) {
+ /* Must not be a fragment. */
+ if (offset)
+ return 0;
+
+ uh = skb_header_pointer(skb, protoff, sizeof(_udph), &_udph);
+ if (uh == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil UDP tinygram.\n");
@@ -1675,30 +1682,11 @@ udp_match(const struct sk_buff *skb,
return 0;
}
- udpoff = (u8*)(skb->nh.ipv6h + 1) - skb->data;
- udpoff = ipv6_skip_exthdr(skb, udpoff, &nexthdr, skb->len - udpoff);
- if (udpoff < 0 || udpoff > skb->len) {
- duprintf("udp_match: cannot skip exthdr. Dropping.\n");
- *hotdrop = 1;
- return 0;
- } else if (nexthdr == IPPROTO_FRAGMENT)
- return 0;
- else if (nexthdr != IPPROTO_UDP ||
- skb->len - udpoff < sizeof(struct udphdr)) {
- duprintf("udp_match: cannot get UDP header. Dropping.\n");
- *hotdrop = 1;
- return 0;
- }
-
- udp = (struct udphdr *)(skb->data + udpoff);
-
- /* Must not be a fragment. */
- return !offset
- && port_match(udpinfo->spts[0], udpinfo->spts[1],
- ntohs(udp->source),
- !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT))
+ return port_match(udpinfo->spts[0], udpinfo->spts[1],
+ ntohs(uh->source),
+ !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT))
&& port_match(udpinfo->dpts[0], udpinfo->dpts[1],
- ntohs(udp->dest),
+ ntohs(uh->dest),
!!(udpinfo->invflags & IP6T_UDP_INV_DSTPT));
}
@@ -1748,14 +1736,18 @@ icmp6_match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- const struct icmp6hdr *icmp = hdr;
+ struct icmp6hdr _icmp, *ic;
const struct ip6t_icmp *icmpinfo = matchinfo;
- if (offset == 0 && datalen < 2) {
+ /* Must not be a fragment. */
+ if (offset)
+ return 0;
+
+ ic = skb_header_pointer(skb, protoff, sizeof(_icmp), &_icmp);
+ if (ic == NULL) {
/* We've been asked to examine this packet, and we
can't. Hence, no choice but to drop. */
duprintf("Dropping evil ICMP tinygram.\n");
@@ -1763,13 +1755,11 @@ icmp6_match(const struct sk_buff *skb,
return 0;
}
- /* Must not be a fragment. */
- return !offset
- && icmp6_type_code_match(icmpinfo->type,
- icmpinfo->code[0],
- icmpinfo->code[1],
- icmp->icmp6_type, icmp->icmp6_code,
- !!(icmpinfo->invflags&IP6T_ICMP_INV));
+ return icmp6_type_code_match(icmpinfo->type,
+ icmpinfo->code[0],
+ icmpinfo->code[1],
+ ic->icmp6_type, ic->icmp6_code,
+ !!(icmpinfo->invflags&IP6T_ICMP_INV));
}
/* Called when user tries to insert an entry of this type. */
@@ -1972,7 +1962,6 @@ static void __exit fini(void)
EXPORT_SYMBOL(ip6t_register_table);
EXPORT_SYMBOL(ip6t_unregister_table);
EXPORT_SYMBOL(ip6t_do_table);
-EXPORT_SYMBOL(ip6t_find_target_lock);
EXPORT_SYMBOL(ip6t_register_match);
EXPORT_SYMBOL(ip6t_unregister_match);
EXPORT_SYMBOL(ip6t_register_target);
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 0fc6b1750a54..9f5cfdbe26a5 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -40,120 +40,166 @@ struct in_device;
#define DEBUGP(format, args...)
#endif
-struct esphdr {
- __u32 spi;
-}; /* FIXME evil kludge */
-
/* Use lock to serialize, so printks don't overlap */
static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
-/* takes in current header and pointer to the header */
-/* if another header exists, sets hdrptr to the next header
- and returns the new header value, else returns IPPROTO_NONE */
-static u_int8_t ip6_nexthdr(u_int8_t currenthdr, u_int8_t **hdrptr)
-{
- u_int8_t hdrlen, nexthdr = IPPROTO_NONE;
-
- switch(currenthdr){
- case IPPROTO_AH:
- /* whoever decided to do the length of AUTH for ipv6
- in 32bit units unlike other headers should be beaten...
- repeatedly...with a large stick...no, an even LARGER
- stick...no, you're still not thinking big enough */
- nexthdr = **hdrptr;
- hdrlen = (*hdrptr)[1] * 4 + 8;
- *hdrptr = *hdrptr + hdrlen;
- break;
- /*stupid rfc2402 */
- case IPPROTO_DSTOPTS:
- case IPPROTO_ROUTING:
- case IPPROTO_HOPOPTS:
- nexthdr = **hdrptr;
- hdrlen = (*hdrptr)[1] * 8 + 8;
- *hdrptr = *hdrptr + hdrlen;
- break;
- case IPPROTO_FRAGMENT:
- nexthdr = **hdrptr;
- *hdrptr = *hdrptr + 8;
- break;
- }
- return nexthdr;
-}
-
/* One level of recursion won't kill us */
static void dump_packet(const struct ip6t_log_info *info,
- struct ipv6hdr *ipv6h, int recurse)
+ const struct sk_buff *skb, unsigned int ip6hoff,
+ int recurse)
{
- u_int8_t currenthdr = ipv6h->nexthdr;
- u_int8_t *hdrptr;
+ u_int8_t currenthdr;
int fragment;
+ struct ipv6hdr _ip6h, *ih;
+ unsigned int ptr;
+ unsigned int hdrlen = 0;
+
+ ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
+ if (ih == NULL) {
+ printk("TRUNCATED");
+ return;
+ }
/* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000" */
- printk("SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->saddr));
- printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
+ printk("SRC=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->saddr));
+ printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ih->daddr));
/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
- ntohs(ipv6h->payload_len) + sizeof(struct ipv6hdr),
- (ntohl(*(u_int32_t *)ipv6h) & 0x0ff00000) >> 20,
- ipv6h->hop_limit,
- (ntohl(*(u_int32_t *)ipv6h) & 0x000fffff));
+ ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
+ (ntohl(*(u_int32_t *)ih) & 0x0ff00000) >> 20,
+ ih->hop_limit,
+ (ntohl(*(u_int32_t *)ih) & 0x000fffff));
fragment = 0;
- hdrptr = (u_int8_t *)(ipv6h + 1);
- while (currenthdr != IPPROTO_NONE) {
- if ((currenthdr == IPPROTO_TCP) ||
- (currenthdr == IPPROTO_UDP) ||
- (currenthdr == IPPROTO_ICMPV6))
- break;
+ ptr = ip6hoff + sizeof(struct ipv6hdr);
+ currenthdr = ih->nexthdr;
+ while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) {
+ struct ipv6_opt_hdr _hdr, *hp;
+
+ hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+ if (hp == NULL) {
+ printk("TRUNCATED");
+ return;
+ }
+
/* Max length: 48 "OPT (...) " */
- printk("OPT ( ");
+ if (info->logflags & IP6T_LOG_IPOPT)
+ printk("OPT ( ");
+
switch (currenthdr) {
case IPPROTO_FRAGMENT: {
- struct frag_hdr *fhdr = (struct frag_hdr *)hdrptr;
+ struct frag_hdr _fhdr, *fh;
+
+ printk("FRAG:");
+ fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
+ &_fhdr);
+ if (fh == NULL) {
+ printk("TRUNCATED ");
+ return;
+ }
- /* Max length: 11 "FRAG:65535 " */
- printk("FRAG:%u ", ntohs(fhdr->frag_off) & 0xFFF8);
+ /* Max length: 6 "65535 " */
+ printk("%u ", ntohs(fh->frag_off) & 0xFFF8);
/* Max length: 11 "INCOMPLETE " */
- if (fhdr->frag_off & htons(0x0001))
+ if (fh->frag_off & htons(0x0001))
printk("INCOMPLETE ");
- printk("ID:%08x ", fhdr->identification);
+ printk("ID:%08x ", ntohl(fh->identification));
- if (ntohs(fhdr->frag_off) & 0xFFF8)
+ if (ntohs(fh->frag_off) & 0xFFF8)
fragment = 1;
+ hdrlen = 8;
+
break;
}
case IPPROTO_DSTOPTS:
case IPPROTO_ROUTING:
case IPPROTO_HOPOPTS:
+ if (fragment) {
+ if (info->logflags & IP6T_LOG_IPOPT)
+ printk(")");
+ return;
+ }
+ hdrlen = ipv6_optlen(hp);
break;
/* Max Length */
case IPPROTO_AH:
+ if (info->logflags & IP6T_LOG_IPOPT) {
+ struct ip_auth_hdr _ahdr, *ah;
+
+ /* Max length: 3 "AH " */
+ printk("AH ");
+
+ if (fragment) {
+ printk(")");
+ return;
+ }
+
+ ah = skb_header_pointer(skb, ptr, sizeof(_ahdr),
+ &_ahdr);
+ if (ah == NULL) {
+ /*
+ * Max length: 26 "INCOMPLETE [65535
+ * bytes] )"
+ */
+ printk("INCOMPLETE [%u bytes] )",
+ skb->len - ptr);
+ return;
+ }
+
+ /* Length: 15 "SPI=0xF1234567 */
+ printk("SPI=0x%x ", ntohl(ah->spi));
+
+ }
+
+ hdrlen = (hp->hdrlen+2)<<2;
+ break;
case IPPROTO_ESP:
if (info->logflags & IP6T_LOG_IPOPT) {
- struct esphdr *esph = (struct esphdr *)hdrptr;
- int esp = (currenthdr == IPPROTO_ESP);
+ struct ip_esp_hdr _esph, *eh;
/* Max length: 4 "ESP " */
- printk("%s ",esp ? "ESP" : "AH");
+ printk("ESP ");
+
+ if (fragment) {
+ printk(")");
+ return;
+ }
+
+ /*
+ * Max length: 26 "INCOMPLETE [65535 bytes] )"
+ */
+ eh = skb_header_pointer(skb, ptr, sizeof(_esph),
+ &_esph);
+ if (eh == NULL) {
+ printk("INCOMPLETE [%u bytes] )",
+ skb->len - ptr);
+ return;
+ }
+
+ /* Length: 16 "SPI=0xF1234567 )" */
+ printk("SPI=0x%x )", ntohl(eh->spi) );
- /* Length: 15 "SPI=0xF1234567 " */
- printk("SPI=0x%x ", ntohl(esph->spi) );
- break;
}
+ return;
default:
- break;
+ /* Max length: 20 "Unknown Ext Hdr 255" */
+ printk("Unknown Ext Hdr %u", currenthdr);
+ return;
}
- printk(") ");
- currenthdr = ip6_nexthdr(currenthdr, &hdrptr);
+ if (info->logflags & IP6T_LOG_IPOPT)
+ printk(") ");
+
+ currenthdr = hp->nexthdr;
+ ptr += hdrlen;
}
switch (currenthdr) {
case IPPROTO_TCP: {
- struct tcphdr *tcph = (struct tcphdr *)hdrptr;
+ struct tcphdr _tcph, *th;
/* Max length: 10 "PROTO=TCP " */
printk("PROTO=TCP ");
@@ -161,51 +207,69 @@ static void dump_packet(const struct ip6t_log_info *info,
if (fragment)
break;
+ /* Max length: 25 "INCOMPLETE [65535 bytes] " */
+ th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph);
+ if (th == NULL) {
+ printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+ return;
+ }
+
/* Max length: 20 "SPT=65535 DPT=65535 " */
printk("SPT=%u DPT=%u ",
- ntohs(tcph->source), ntohs(tcph->dest));
+ ntohs(th->source), ntohs(th->dest));
/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
if (info->logflags & IP6T_LOG_TCPSEQ)
printk("SEQ=%u ACK=%u ",
- ntohl(tcph->seq), ntohl(tcph->ack_seq));
+ ntohl(th->seq), ntohl(th->ack_seq));
/* Max length: 13 "WINDOW=65535 " */
- printk("WINDOW=%u ", ntohs(tcph->window));
- /* Max length: 9 "RES=0x3F " */
- printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(tcph) & TCP_RESERVED_BITS) >> 22));
+ printk("WINDOW=%u ", ntohs(th->window));
+ /* Max length: 9 "RES=0x3C " */
+ printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22));
/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
- if (tcph->cwr)
+ if (th->cwr)
printk("CWR ");
- if (tcph->ece)
+ if (th->ece)
printk("ECE ");
- if (tcph->urg)
+ if (th->urg)
printk("URG ");
- if (tcph->ack)
+ if (th->ack)
printk("ACK ");
- if (tcph->psh)
+ if (th->psh)
printk("PSH ");
- if (tcph->rst)
+ if (th->rst)
printk("RST ");
- if (tcph->syn)
+ if (th->syn)
printk("SYN ");
- if (tcph->fin)
+ if (th->fin)
printk("FIN ");
/* Max length: 11 "URGP=65535 " */
- printk("URGP=%u ", ntohs(tcph->urg_ptr));
+ printk("URGP=%u ", ntohs(th->urg_ptr));
if ((info->logflags & IP6T_LOG_TCPOPT)
- && tcph->doff * 4 != sizeof(struct tcphdr)) {
+ && th->doff * 4 > sizeof(struct tcphdr)) {
+ u_int8_t _opt[60 - sizeof(struct tcphdr)], *op;
unsigned int i;
+ unsigned int optsize = th->doff * 4
+ - sizeof(struct tcphdr);
+
+ op = skb_header_pointer(skb,
+ ptr + sizeof(struct tcphdr),
+ optsize, _opt);
+ if (op == NULL) {
+ printk("OPT (TRUNCATED)");
+ return;
+ }
/* Max length: 127 "OPT (" 15*4*2chars ") " */
printk("OPT (");
- for (i =sizeof(struct tcphdr); i < tcph->doff * 4; i++)
- printk("%02X", ((u_int8_t *)tcph)[i]);
+ for (i =0; i < optsize; i++)
+ printk("%02X", op[i]);
printk(") ");
}
break;
}
case IPPROTO_UDP: {
- struct udphdr *udph = (struct udphdr *)hdrptr;
+ struct udphdr _udph, *uh;
/* Max length: 10 "PROTO=UDP " */
printk("PROTO=UDP ");
@@ -213,14 +277,21 @@ static void dump_packet(const struct ip6t_log_info *info,
if (fragment)
break;
+ /* Max length: 25 "INCOMPLETE [65535 bytes] " */
+ uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph);
+ if (uh == NULL) {
+ printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+ return;
+ }
+
/* Max length: 20 "SPT=65535 DPT=65535 " */
printk("SPT=%u DPT=%u LEN=%u ",
- ntohs(udph->source), ntohs(udph->dest),
- ntohs(udph->len));
+ ntohs(uh->source), ntohs(uh->dest),
+ ntohs(uh->len));
break;
}
case IPPROTO_ICMPV6: {
- struct icmp6hdr *icmp6h = (struct icmp6hdr *)hdrptr;
+ struct icmp6hdr _icmp6h, *ic;
/* Max length: 13 "PROTO=ICMPv6 " */
printk("PROTO=ICMPv6 ");
@@ -228,16 +299,23 @@ static void dump_packet(const struct ip6t_log_info *info,
if (fragment)
break;
+ /* Max length: 25 "INCOMPLETE [65535 bytes] " */
+ ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h);
+ if (ic == NULL) {
+ printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+ return;
+ }
+
/* Max length: 18 "TYPE=255 CODE=255 " */
- printk("TYPE=%u CODE=%u ", icmp6h->icmp6_type, icmp6h->icmp6_code);
+ printk("TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code);
- switch (icmp6h->icmp6_type) {
+ switch (ic->icmp6_type) {
case ICMPV6_ECHO_REQUEST:
case ICMPV6_ECHO_REPLY:
/* Max length: 19 "ID=65535 SEQ=65535 " */
printk("ID=%u SEQ=%u ",
- ntohs(icmp6h->icmp6_identifier),
- ntohs(icmp6h->icmp6_sequence));
+ ntohs(ic->icmp6_identifier),
+ ntohs(ic->icmp6_sequence));
break;
case ICMPV6_MGM_QUERY:
case ICMPV6_MGM_REPORT:
@@ -246,7 +324,7 @@ static void dump_packet(const struct ip6t_log_info *info,
case ICMPV6_PARAMPROB:
/* Max length: 17 "POINTER=ffffffff " */
- printk("POINTER=%08x ", ntohl(icmp6h->icmp6_pointer));
+ printk("POINTER=%08x ", ntohl(ic->icmp6_pointer));
/* Fall through */
case ICMPV6_DEST_UNREACH:
case ICMPV6_PKT_TOOBIG:
@@ -254,13 +332,14 @@ static void dump_packet(const struct ip6t_log_info *info,
/* Max length: 3+maxlen */
if (recurse) {
printk("[");
- dump_packet(info, (struct ipv6hdr *)(icmp6h + 1), 0);
+ dump_packet(info, skb, ptr + sizeof(_icmp6h),
+ 0);
printk("] ");
}
/* Max length: 10 "MTU=65535 " */
- if (icmp6h->icmp6_type == ICMPV6_PKT_TOOBIG)
- printk("MTU=%u ", ntohl(icmp6h->icmp6_mtu));
+ if (ic->icmp6_type == ICMPV6_PKT_TOOBIG)
+ printk("MTU=%u ", ntohl(ic->icmp6_mtu));
}
break;
}
@@ -328,16 +407,16 @@ ip6t_log_packet(unsigned int hooknum,
printk(" ");
}
- dump_packet(loginfo, ipv6h, 1);
+ dump_packet(loginfo, skb, (u8*)skb->nh.ipv6h - skb->data, 1);
printk("\n");
spin_unlock_bh(&log_lock);
}
static unsigned int
ip6t_log_target(struct sk_buff **pskb,
- unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
+ unsigned int hooknum,
const void *targinfo,
void *userinfo)
{
diff --git a/net/ipv6/netfilter/ip6t_MARK.c b/net/ipv6/netfilter/ip6t_MARK.c
index ce287d2bef64..d09ceb05013a 100644
--- a/net/ipv6/netfilter/ip6t_MARK.c
+++ b/net/ipv6/netfilter/ip6t_MARK.c
@@ -20,9 +20,9 @@ MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
static unsigned int
target(struct sk_buff **pskb,
- unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
+ unsigned int hooknum,
const void *targinfo,
void *userinfo)
{
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index f5b9efd12674..d5b94f142bba 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -31,12 +31,12 @@ MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
static inline int
spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
{
- int r=0;
- DEBUGP("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
- min,spi,max);
- r=(spi >= min && spi <= max) ^ invert;
- DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
- return r;
+ int r=0;
+ DEBUGP("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
+ min,spi,max);
+ r = (spi >= min && spi <= max) ^ invert;
+ DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
+ return r;
}
static int
@@ -45,125 +45,124 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- struct ip_auth_hdr *ah = NULL;
- const struct ip6t_ah *ahinfo = matchinfo;
- unsigned int temp;
- int len;
- u8 nexthdr;
- unsigned int ptr;
- unsigned int hdrlen = 0;
-
- /*DEBUGP("IPv6 AH entered\n");*/
- /* if (opt->auth == 0) return 0;
- * It does not filled on output */
-
- /* type of the 1st exthdr */
- nexthdr = skb->nh.ipv6h->nexthdr;
- /* pointer to the 1st exthdr */
- ptr = sizeof(struct ipv6hdr);
- /* available length */
- len = skb->len - ptr;
- temp = 0;
-
- while (ip6t_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr *hdr;
-
- DEBUGP("ipv6_ah header iteration \n");
-
- /* Is there enough space for the next ext header? */
- if (len < (int)sizeof(struct ipv6_opt_hdr))
- return 0;
- /* No more exthdr -> evaluate */
- if (nexthdr == NEXTHDR_NONE) {
- break;
- }
- /* ESP -> evaluate */
- if (nexthdr == NEXTHDR_ESP) {
- break;
- }
-
- hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
-
- /* Calculate the header length */
- if (nexthdr == NEXTHDR_FRAGMENT) {
- hdrlen = 8;
- } else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hdr->hdrlen+2)<<2;
- else
- hdrlen = ipv6_optlen(hdr);
-
- /* AH -> evaluate */
- if (nexthdr == NEXTHDR_AUTH) {
- temp |= MASK_AH;
- break;
- }
-
-
- /* set the flag */
- switch (nexthdr){
- case NEXTHDR_HOP:
- case NEXTHDR_ROUTING:
- case NEXTHDR_FRAGMENT:
- case NEXTHDR_AUTH:
- case NEXTHDR_DEST:
- break;
- default:
- DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr);
- return 0;
- break;
- }
-
- nexthdr = hdr->nexthdr;
- len -= hdrlen;
- ptr += hdrlen;
- if ( ptr > skb->len ) {
+ struct ip_auth_hdr *ah = NULL, _ah;
+ const struct ip6t_ah *ahinfo = matchinfo;
+ unsigned int temp;
+ int len;
+ u8 nexthdr;
+ unsigned int ptr;
+ unsigned int hdrlen = 0;
+
+ /*DEBUGP("IPv6 AH entered\n");*/
+ /* if (opt->auth == 0) return 0;
+ * It does not filled on output */
+
+ /* type of the 1st exthdr */
+ nexthdr = skb->nh.ipv6h->nexthdr;
+ /* pointer to the 1st exthdr */
+ ptr = sizeof(struct ipv6hdr);
+ /* available length */
+ len = skb->len - ptr;
+ temp = 0;
+
+ while (ip6t_ext_hdr(nexthdr)) {
+ struct ipv6_opt_hdr _hdr, *hp;
+
+ DEBUGP("ipv6_ah header iteration \n");
+
+ /* Is there enough space for the next ext header? */
+ if (len < sizeof(struct ipv6_opt_hdr))
+ return 0;
+ /* No more exthdr -> evaluate */
+ if (nexthdr == NEXTHDR_NONE)
+ break;
+ /* ESP -> evaluate */
+ if (nexthdr == NEXTHDR_ESP)
+ break;
+
+ hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+ BUG_ON(hp == NULL);
+
+ /* Calculate the header length */
+ if (nexthdr == NEXTHDR_FRAGMENT)
+ hdrlen = 8;
+ else if (nexthdr == NEXTHDR_AUTH)
+ hdrlen = (hp->hdrlen+2)<<2;
+ else
+ hdrlen = ipv6_optlen(hp);
+
+ /* AH -> evaluate */
+ if (nexthdr == NEXTHDR_AUTH) {
+ temp |= MASK_AH;
+ break;
+ }
+
+
+ /* set the flag */
+ switch (nexthdr) {
+ case NEXTHDR_HOP:
+ case NEXTHDR_ROUTING:
+ case NEXTHDR_FRAGMENT:
+ case NEXTHDR_AUTH:
+ case NEXTHDR_DEST:
+ break;
+ default:
+ DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr);
+ return 0;
+ }
+
+ nexthdr = hp->nexthdr;
+ len -= hdrlen;
+ ptr += hdrlen;
+ if (ptr > skb->len) {
DEBUGP("ipv6_ah: new pointer too large! \n");
break;
}
- }
-
- /* AH header not found */
- if ( temp != MASK_AH ) return 0;
-
- if (len < (int)sizeof(struct ip_auth_hdr)){
- *hotdrop = 1;
- return 0;
- }
-
- ah = (struct ip_auth_hdr *) (skb->data + ptr);
-
- DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
- DEBUGP("RES %04X ", ah->reserved);
- DEBUGP("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi));
-
- DEBUGP("IPv6 AH spi %02X ",
- (spi_match(ahinfo->spis[0], ahinfo->spis[1],
- ntohl(ah->spi),
- !!(ahinfo->invflags & IP6T_AH_INV_SPI))));
- DEBUGP("len %02X %04X %02X ",
- ahinfo->hdrlen, hdrlen,
- (!ahinfo->hdrlen ||
- (ahinfo->hdrlen == hdrlen) ^
- !!(ahinfo->invflags & IP6T_AH_INV_LEN)));
- DEBUGP("res %02X %04X %02X\n",
- ahinfo->hdrres, ah->reserved,
- !(ahinfo->hdrres && ah->reserved));
-
- return (ah != NULL)
- &&
- (spi_match(ahinfo->spis[0], ahinfo->spis[1],
- ntohl(ah->spi),
- !!(ahinfo->invflags & IP6T_AH_INV_SPI)))
- &&
- (!ahinfo->hdrlen ||
- (ahinfo->hdrlen == hdrlen) ^
- !!(ahinfo->invflags & IP6T_AH_INV_LEN))
- &&
- !(ahinfo->hdrres && ah->reserved);
+ }
+
+ /* AH header not found */
+ if (temp != MASK_AH)
+ return 0;
+
+ if (len < sizeof(struct ip_auth_hdr)){
+ *hotdrop = 1;
+ return 0;
+ }
+
+ ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
+ BUG_ON(ah == NULL);
+
+ DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
+ DEBUGP("RES %04X ", ah->reserved);
+ DEBUGP("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi));
+
+ DEBUGP("IPv6 AH spi %02X ",
+ (spi_match(ahinfo->spis[0], ahinfo->spis[1],
+ ntohl(ah->spi),
+ !!(ahinfo->invflags & IP6T_AH_INV_SPI))));
+ DEBUGP("len %02X %04X %02X ",
+ ahinfo->hdrlen, hdrlen,
+ (!ahinfo->hdrlen ||
+ (ahinfo->hdrlen == hdrlen) ^
+ !!(ahinfo->invflags & IP6T_AH_INV_LEN)));
+ DEBUGP("res %02X %04X %02X\n",
+ ahinfo->hdrres, ah->reserved,
+ !(ahinfo->hdrres && ah->reserved));
+
+ return (ah != NULL)
+ &&
+ (spi_match(ahinfo->spis[0], ahinfo->spis[1],
+ ntohl(ah->spi),
+ !!(ahinfo->invflags & IP6T_AH_INV_SPI)))
+ &&
+ (!ahinfo->hdrlen ||
+ (ahinfo->hdrlen == hdrlen) ^
+ !!(ahinfo->invflags & IP6T_AH_INV_LEN))
+ &&
+ !(ahinfo->hdrres && ah->reserved);
}
/* Called when user tries to insert an entry of this type. */
@@ -174,20 +173,18 @@ checkentry(const char *tablename,
unsigned int matchinfosize,
unsigned int hook_mask)
{
- const struct ip6t_ah *ahinfo = matchinfo;
-
- if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_ah))) {
- DEBUGP("ip6t_ah: matchsize %u != %u\n",
- matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_ah)));
- return 0;
- }
- if (ahinfo->invflags & ~IP6T_AH_INV_MASK) {
- DEBUGP("ip6t_ah: unknown flags %X\n",
- ahinfo->invflags);
- return 0;
- }
-
- return 1;
+ const struct ip6t_ah *ahinfo = matchinfo;
+
+ if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_ah))) {
+ DEBUGP("ip6t_ah: matchsize %u != %u\n",
+ matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_ah)));
+ return 0;
+ }
+ if (ahinfo->invflags & ~IP6T_AH_INV_MASK) {
+ DEBUGP("ip6t_ah: unknown flags %X\n", ahinfo->invflags);
+ return 0;
+ }
+ return 1;
}
static struct ip6t_match ah_match = {
@@ -199,12 +196,12 @@ static struct ip6t_match ah_match = {
static int __init init(void)
{
- return ip6t_register_match(&ah_match);
+ return ip6t_register_match(&ah_match);
}
static void __exit cleanup(void)
{
- ip6t_unregister_match(&ah_match);
+ ip6t_unregister_match(&ah_match);
}
module_init(init);
diff --git a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c
index 2d385038c663..540925e4a7a8 100644
--- a/net/ipv6/netfilter/ip6t_dst.c
+++ b/net/ipv6/netfilter/ip6t_dst.c
@@ -7,7 +7,6 @@
* published by the Free Software Foundation.
*/
-
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/ipv6.h>
@@ -20,8 +19,6 @@
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter_ipv6/ip6t_opts.h>
-#define LOW(n) (n & 0x00FF)
-
#define HOPBYHOP 0
MODULE_LICENSE("GPL");
@@ -48,8 +45,8 @@ MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
* 0 -> invariant
* 1 -> can change the routing
* (Type & 0x1F) Type
- * 0 -> PAD0 (only 1 byte!)
- * 1 -> PAD1 LENGTH info (total length = length + 2)
+ * 0 -> Pad1 (only 1 byte!)
+ * 1 -> PadN LENGTH info (total length = length + 2)
* C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k )
* 5 -> RTALERT 2 x x
*/
@@ -60,11 +57,10 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- struct ipv6_opt_hdr *optsh = NULL;
+ struct ipv6_opt_hdr _optsh, *oh;
const struct ip6t_opts *optinfo = matchinfo;
unsigned int temp;
unsigned int len;
@@ -72,7 +68,9 @@ match(const struct sk_buff *skb,
unsigned int ptr;
unsigned int hdrlen = 0;
unsigned int ret = 0;
- u_int16_t *optdesc = NULL;
+ u8 _opttype, *tp = NULL;
+ u8 _optlen, *lp = NULL;
+ unsigned int optlen;
/* type of the 1st exthdr */
nexthdr = skb->nh.ipv6h->nexthdr;
@@ -83,7 +81,7 @@ match(const struct sk_buff *skb,
temp = 0;
while (ip6t_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr *hdr;
+ struct ipv6_opt_hdr _hdr, *hp;
DEBUGP("ipv6_opts header iteration \n");
@@ -99,15 +97,16 @@ match(const struct sk_buff *skb,
break;
}
- hdr=(void *)(skb->data)+ptr;
+ hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+ BUG_ON(hp == NULL);
/* Calculate the header length */
if (nexthdr == NEXTHDR_FRAGMENT) {
hdrlen = 8;
} else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hdr->hdrlen+2)<<2;
+ hdrlen = (hp->hdrlen+2)<<2;
else
- hdrlen = ipv6_optlen(hdr);
+ hdrlen = ipv6_optlen(hp);
/* OPTS -> evaluate */
#if HOPBYHOP
@@ -135,7 +134,7 @@ match(const struct sk_buff *skb,
break;
}
- nexthdr = hdr->nexthdr;
+ nexthdr = hp->nexthdr;
len -= hdrlen;
ptr += hdrlen;
if ( ptr > skb->len ) {
@@ -161,9 +160,10 @@ match(const struct sk_buff *skb,
return 0;
}
- optsh=(void *)(skb->data)+ptr;
+ oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
+ BUG_ON(oh == NULL);
- DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, optsh->hdrlen);
+ DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
DEBUGP("len %02X %04X %02X ",
optinfo->hdrlen, hdrlen,
@@ -171,13 +171,12 @@ match(const struct sk_buff *skb,
((optinfo->hdrlen == hdrlen) ^
!!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
- ret = (optsh != NULL)
+ ret = (oh != NULL)
&&
(!(optinfo->flags & IP6T_OPTS_LEN) ||
((optinfo->hdrlen == hdrlen) ^
!!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
- temp = len = 0;
ptr += 2;
hdrlen -= 2;
if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){
@@ -188,48 +187,59 @@ match(const struct sk_buff *skb,
DEBUGP("Strict ");
DEBUGP("#%d ",optinfo->optsnr);
for(temp=0; temp<optinfo->optsnr; temp++){
- optdesc = (void *)(skb->data)+ptr;
+ /* type field exists ? */
+ if (hdrlen < 1)
+ break;
+ tp = skb_header_pointer(skb, ptr, sizeof(_opttype),
+ &_opttype);
+ if (tp == NULL)
+ break;
+
/* Type check */
- if ( (unsigned char)*optdesc !=
- (optinfo->opts[temp] & 0xFF00)>>8 ){
+ if (*tp != (optinfo->opts[temp] & 0xFF00)>>8){
DEBUGP("Tbad %02X %02X\n",
- (unsigned char)*optdesc,
- (optinfo->opts[temp] &
- 0xFF00)>>8);
+ *tp,
+ (optinfo->opts[temp] & 0xFF00)>>8);
return 0;
} else {
DEBUGP("Tok ");
}
/* Length check */
- if (((optinfo->opts[temp] & 0x00FF) != 0xFF) &&
- (unsigned char)*optdesc != 0){
- if ( ntohs((u16)*optdesc) !=
- optinfo->opts[temp] ){
- DEBUGP("Lbad %02X %04X %04X\n",
- (unsigned char)*optdesc,
- ntohs((u16)*optdesc),
- optinfo->opts[temp]);
+ if (*tp) {
+ u16 spec_len;
+
+ /* length field exists ? */
+ if (hdrlen < 2)
+ break;
+ lp = skb_header_pointer(skb, ptr + 1,
+ sizeof(_optlen),
+ &_optlen);
+ if (lp == NULL)
+ break;
+ spec_len = optinfo->opts[temp] & 0x00FF;
+
+ if (spec_len != 0x00FF && spec_len != *lp) {
+ DEBUGP("Lbad %02X %04X\n", *lp,
+ spec_len);
return 0;
- } else {
- DEBUGP("Lok ");
}
- }
- /* Step to the next */
- if ((unsigned char)*optdesc == 0){
- DEBUGP("PAD0 \n");
- ptr++;
- hdrlen--;
+ DEBUGP("Lok ");
+ optlen = *lp + 2;
} else {
- ptr += LOW(ntohs(*optdesc));
- hdrlen -= LOW(ntohs(*optdesc));
- DEBUGP("len%04X \n",
- LOW(ntohs(*optdesc)));
+ DEBUGP("Pad1\n");
+ optlen = 1;
}
- if (ptr > skb->len || ( !hdrlen &&
- (temp != optinfo->optsnr - 1))) {
+
+ /* Step to the next */
+ DEBUGP("len%04X \n", optlen);
+
+ if ((ptr > skb->len - optlen || hdrlen < optlen) &&
+ (temp < optinfo->optsnr - 1)) {
DEBUGP("new pointer is too large! \n");
break;
}
+ ptr += optlen;
+ hdrlen -= optlen;
}
if (temp == optinfo->optsnr)
return ret;
@@ -271,6 +281,7 @@ static struct ip6t_match opts_match = {
#endif
.match = &match,
.checkentry = &checkentry,
+ .me = THIS_MODULE,
};
static int __init init(void)
diff --git a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c
index ecdd48bba911..e39dd236fd8e 100644
--- a/net/ipv6/netfilter/ip6t_esp.c
+++ b/net/ipv6/netfilter/ip6t_esp.c
@@ -32,8 +32,8 @@ static inline int
spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
{
int r=0;
- DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
- min,spi,max);
+ DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
+ min,spi,max);
r=(spi >= min && spi <= max) ^ invert;
DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
return r;
@@ -45,11 +45,10 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- struct ip_esp_hdr *esp = NULL;
+ struct ip_esp_hdr _esp, *eh = NULL;
const struct ip6t_esp *espinfo = matchinfo;
unsigned int temp;
int len;
@@ -67,73 +66,74 @@ match(const struct sk_buff *skb,
len = skb->len - ptr;
temp = 0;
- while (ip6t_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr *hdr;
- int hdrlen;
+ while (ip6t_ext_hdr(nexthdr)) {
+ struct ipv6_opt_hdr _hdr, *hp;
+ int hdrlen;
DEBUGP("ipv6_esp header iteration \n");
/* Is there enough space for the next ext header? */
- if (len < (int)sizeof(struct ipv6_opt_hdr))
- return 0;
+ if (len < sizeof(struct ipv6_opt_hdr))
+ return 0;
/* No more exthdr -> evaluate */
- if (nexthdr == NEXTHDR_NONE) {
+ if (nexthdr == NEXTHDR_NONE)
break;
- }
/* ESP -> evaluate */
- if (nexthdr == NEXTHDR_ESP) {
+ if (nexthdr == NEXTHDR_ESP) {
temp |= MASK_ESP;
break;
}
- hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
+ hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+ BUG_ON(hp == NULL);
/* Calculate the header length */
- if (nexthdr == NEXTHDR_FRAGMENT) {
- hdrlen = 8;
- } else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hdr->hdrlen+2)<<2;
- else
- hdrlen = ipv6_optlen(hdr);
+ if (nexthdr == NEXTHDR_FRAGMENT)
+ hdrlen = 8;
+ else if (nexthdr == NEXTHDR_AUTH)
+ hdrlen = (hp->hdrlen+2)<<2;
+ else
+ hdrlen = ipv6_optlen(hp);
/* set the flag */
- switch (nexthdr){
- case NEXTHDR_HOP:
- case NEXTHDR_ROUTING:
- case NEXTHDR_FRAGMENT:
- case NEXTHDR_AUTH:
- case NEXTHDR_DEST:
- break;
- default:
- DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr);
- return 0;
- break;
+ switch (nexthdr) {
+ case NEXTHDR_HOP:
+ case NEXTHDR_ROUTING:
+ case NEXTHDR_FRAGMENT:
+ case NEXTHDR_AUTH:
+ case NEXTHDR_DEST:
+ break;
+ default:
+ DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr);
+ return 0;
}
- nexthdr = hdr->nexthdr;
- len -= hdrlen;
- ptr += hdrlen;
- if ( ptr > skb->len ) {
+ nexthdr = hp->nexthdr;
+ len -= hdrlen;
+ ptr += hdrlen;
+ if (ptr > skb->len) {
DEBUGP("ipv6_esp: new pointer too large! \n");
break;
}
- }
+ }
/* ESP header not found */
- if ( temp != MASK_ESP ) return 0;
+ if (temp != MASK_ESP)
+ return 0;
- if (len < (int)sizeof(struct ip_esp_hdr)){
- *hotdrop = 1;
- return 0;
- }
+ if (len < sizeof(struct ip_esp_hdr)) {
+ *hotdrop = 1;
+ return 0;
+ }
- esp = (struct ip_esp_hdr *) (skb->data + ptr);
+ eh = skb_header_pointer(skb, ptr, sizeof(_esp), &_esp);
+ BUG_ON(eh == NULL);
- DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(esp->spi), ntohl(esp->spi));
+ DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(eh->spi), ntohl(eh->spi));
- return (esp != NULL)
+ return (eh != NULL)
&& spi_match(espinfo->spis[0], espinfo->spis[1],
- ntohl(esp->spi),
+ ntohl(eh->spi),
!!(espinfo->invflags & IP6T_ESP_INV_SPI));
}
@@ -157,7 +157,6 @@ checkentry(const char *tablename,
espinfo->invflags);
return 0;
}
-
return 1;
}
diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c
index 3b1340d26b5e..6d1c4e87effc 100644
--- a/net/ipv6/netfilter/ip6t_eui64.c
+++ b/net/ipv6/netfilter/ip6t_eui64.c
@@ -24,8 +24,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 3496166b75e3..4bfa30a9bc80 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -45,11 +45,10 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- struct frag_hdr *frag = NULL;
+ struct frag_hdr _frag, *fh = NULL;
const struct ip6t_frag *fraginfo = matchinfo;
unsigned int temp;
int len;
@@ -66,7 +65,7 @@ match(const struct sk_buff *skb,
temp = 0;
while (ip6t_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr *hdr;
+ struct ipv6_opt_hdr _hdr, *hp;
DEBUGP("ipv6_frag header iteration \n");
@@ -82,15 +81,16 @@ match(const struct sk_buff *skb,
break;
}
- hdr=(struct ipv6_opt_hdr *)(skb->data+ptr);
+ hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+ BUG_ON(hp == NULL);
/* Calculate the header length */
if (nexthdr == NEXTHDR_FRAGMENT) {
hdrlen = 8;
} else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hdr->hdrlen+2)<<2;
+ hdrlen = (hp->hdrlen+2)<<2;
else
- hdrlen = ipv6_optlen(hdr);
+ hdrlen = ipv6_optlen(hp);
/* FRAG -> evaluate */
if (nexthdr == NEXTHDR_FRAGMENT) {
@@ -113,7 +113,7 @@ match(const struct sk_buff *skb,
break;
}
- nexthdr = hdr->nexthdr;
+ nexthdr = hp->nexthdr;
len -= hdrlen;
ptr += hdrlen;
if ( ptr > skb->len ) {
@@ -130,57 +130,58 @@ match(const struct sk_buff *skb,
return 0;
}
- frag = (struct frag_hdr *) (skb->data + ptr);
+ fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
+ BUG_ON(fh == NULL);
- DEBUGP("INFO %04X ", frag->frag_off);
- DEBUGP("OFFSET %04X ", ntohs(frag->frag_off) & ~0x7);
- DEBUGP("RES %02X %04X", frag->reserved, ntohs(frag->frag_off) & 0x6);
- DEBUGP("MF %04X ", frag->frag_off & htons(IP6_MF));
- DEBUGP("ID %u %08X\n", ntohl(frag->identification),
- ntohl(frag->identification));
+ DEBUGP("INFO %04X ", fh->frag_off);
+ DEBUGP("OFFSET %04X ", ntohs(fh->frag_off) & ~0x7);
+ DEBUGP("RES %02X %04X", fh->reserved, ntohs(fh->frag_off) & 0x6);
+ DEBUGP("MF %04X ", fh->frag_off & htons(IP6_MF));
+ DEBUGP("ID %u %08X\n", ntohl(fh->identification),
+ ntohl(fh->identification));
DEBUGP("IPv6 FRAG id %02X ",
(id_match(fraginfo->ids[0], fraginfo->ids[1],
- ntohl(frag->identification),
+ ntohl(fh->identification),
!!(fraginfo->invflags & IP6T_FRAG_INV_IDS))));
DEBUGP("res %02X %02X%04X %02X ",
- (fraginfo->flags & IP6T_FRAG_RES), frag->reserved,
- ntohs(frag->frag_off) & 0x6,
+ (fraginfo->flags & IP6T_FRAG_RES), fh->reserved,
+ ntohs(fh->frag_off) & 0x6,
!((fraginfo->flags & IP6T_FRAG_RES)
- && (frag->reserved || (ntohs(frag->frag_off) & 0x6))));
+ && (fh->reserved || (ntohs(fh->frag_off) & 0x06))));
DEBUGP("first %02X %02X %02X ",
(fraginfo->flags & IP6T_FRAG_FST),
- ntohs(frag->frag_off) & ~0x7,
+ ntohs(fh->frag_off) & ~0x7,
!((fraginfo->flags & IP6T_FRAG_FST)
- && (ntohs(frag->frag_off) & ~0x7)));
+ && (ntohs(fh->frag_off) & ~0x7)));
DEBUGP("mf %02X %02X %02X ",
(fraginfo->flags & IP6T_FRAG_MF),
- ntohs(frag->frag_off) & IP6_MF,
+ ntohs(fh->frag_off) & IP6_MF,
!((fraginfo->flags & IP6T_FRAG_MF)
- && !((ntohs(frag->frag_off) & IP6_MF))));
+ && !((ntohs(fh->frag_off) & IP6_MF))));
DEBUGP("last %02X %02X %02X\n",
(fraginfo->flags & IP6T_FRAG_NMF),
- ntohs(frag->frag_off) & IP6_MF,
+ ntohs(fh->frag_off) & IP6_MF,
!((fraginfo->flags & IP6T_FRAG_NMF)
- && (ntohs(frag->frag_off) & IP6_MF)));
+ && (ntohs(fh->frag_off) & IP6_MF)));
- return (frag != NULL)
+ return (fh != NULL)
&&
(id_match(fraginfo->ids[0], fraginfo->ids[1],
- ntohl(frag->identification),
+ ntohl(fh->identification),
!!(fraginfo->invflags & IP6T_FRAG_INV_IDS)))
&&
!((fraginfo->flags & IP6T_FRAG_RES)
- && (frag->reserved || (ntohs(frag->frag_off) & 0x6)))
+ && (fh->reserved || (ntohs(fh->frag_off) & 0x6)))
&&
!((fraginfo->flags & IP6T_FRAG_FST)
- && (ntohs(frag->frag_off) & ~0x7))
+ && (ntohs(fh->frag_off) & ~0x7))
&&
!((fraginfo->flags & IP6T_FRAG_MF)
- && !(ntohs(frag->frag_off) & IP6_MF))
+ && !(ntohs(fh->frag_off) & IP6_MF))
&&
!((fraginfo->flags & IP6T_FRAG_NMF)
- && (ntohs(frag->frag_off) & IP6_MF));
+ && (ntohs(fh->frag_off) & IP6_MF));
}
/* Called when user tries to insert an entry of this type. */
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index 6849122c37e9..27f3650d127e 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -19,8 +19,6 @@
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter_ipv6/ip6t_opts.h>
-#define LOW(n) (n & 0x00FF)
-
#define HOPBYHOP 1
MODULE_LICENSE("GPL");
@@ -47,8 +45,8 @@ MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
* 0 -> invariant
* 1 -> can change the routing
* (Type & 0x1F) Type
- * 0 -> PAD0 (only 1 byte!)
- * 1 -> PAD1 LENGTH info (total length = length + 2)
+ * 0 -> Pad1 (only 1 byte!)
+ * 1 -> PadN LENGTH info (total length = length + 2)
* C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k )
* 5 -> RTALERT 2 x x
*/
@@ -59,11 +57,10 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- struct ipv6_opt_hdr *optsh = NULL;
+ struct ipv6_opt_hdr _optsh, *oh;
const struct ip6t_opts *optinfo = matchinfo;
unsigned int temp;
unsigned int len;
@@ -71,7 +68,9 @@ match(const struct sk_buff *skb,
unsigned int ptr;
unsigned int hdrlen = 0;
unsigned int ret = 0;
- u_int16_t *optdesc = NULL;
+ u8 _opttype, *tp = NULL;
+ u8 _optlen, *lp = NULL;
+ unsigned int optlen;
/* type of the 1st exthdr */
nexthdr = skb->nh.ipv6h->nexthdr;
@@ -82,7 +81,7 @@ match(const struct sk_buff *skb,
temp = 0;
while (ip6t_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr *hdr;
+ struct ipv6_opt_hdr _hdr, *hp;
DEBUGP("ipv6_opts header iteration \n");
@@ -98,15 +97,16 @@ match(const struct sk_buff *skb,
break;
}
- hdr=(void *)(skb->data)+ptr;
+ hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+ BUG_ON(hp == NULL);
/* Calculate the header length */
if (nexthdr == NEXTHDR_FRAGMENT) {
hdrlen = 8;
} else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hdr->hdrlen+2)<<2;
+ hdrlen = (hp->hdrlen+2)<<2;
else
- hdrlen = ipv6_optlen(hdr);
+ hdrlen = ipv6_optlen(hp);
/* OPTS -> evaluate */
#if HOPBYHOP
@@ -134,7 +134,7 @@ match(const struct sk_buff *skb,
break;
}
- nexthdr = hdr->nexthdr;
+ nexthdr = hp->nexthdr;
len -= hdrlen;
ptr += hdrlen;
if ( ptr > skb->len ) {
@@ -160,9 +160,10 @@ match(const struct sk_buff *skb,
return 0;
}
- optsh=(void *)(skb->data)+ptr;
+ oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
+ BUG_ON(oh == NULL);
- DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, optsh->hdrlen);
+ DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, oh->hdrlen);
DEBUGP("len %02X %04X %02X ",
optinfo->hdrlen, hdrlen,
@@ -170,13 +171,12 @@ match(const struct sk_buff *skb,
((optinfo->hdrlen == hdrlen) ^
!!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
- ret = (optsh != NULL)
+ ret = (oh != NULL)
&&
(!(optinfo->flags & IP6T_OPTS_LEN) ||
((optinfo->hdrlen == hdrlen) ^
!!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
- temp = len = 0;
ptr += 2;
hdrlen -= 2;
if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){
@@ -187,48 +187,59 @@ match(const struct sk_buff *skb,
DEBUGP("Strict ");
DEBUGP("#%d ",optinfo->optsnr);
for(temp=0; temp<optinfo->optsnr; temp++){
- optdesc = (void *)(skb->data)+ptr;
+ /* type field exists ? */
+ if (hdrlen < 1)
+ break;
+ tp = skb_header_pointer(skb, ptr, sizeof(_opttype),
+ &_opttype);
+ if (tp == NULL)
+ break;
+
/* Type check */
- if ( (unsigned char)*optdesc !=
- (optinfo->opts[temp] & 0xFF00)>>8 ){
+ if (*tp != (optinfo->opts[temp] & 0xFF00)>>8){
DEBUGP("Tbad %02X %02X\n",
- (unsigned char)*optdesc,
- (optinfo->opts[temp] &
- 0xFF00)>>8);
+ *tp,
+ (optinfo->opts[temp] & 0xFF00)>>8);
return 0;
} else {
DEBUGP("Tok ");
}
/* Length check */
- if (((optinfo->opts[temp] & 0x00FF) != 0xFF) &&
- (unsigned char)*optdesc != 0){
- if ( ntohs((u16)*optdesc) !=
- optinfo->opts[temp] ){
- DEBUGP("Lbad %02X %04X %04X\n",
- (unsigned char)*optdesc,
- ntohs((u16)*optdesc),
- optinfo->opts[temp]);
+ if (*tp) {
+ u16 spec_len;
+
+ /* length field exists ? */
+ if (hdrlen < 2)
+ break;
+ lp = skb_header_pointer(skb, ptr + 1,
+ sizeof(_optlen),
+ &_optlen);
+ if (lp == NULL)
+ break;
+ spec_len = optinfo->opts[temp] & 0x00FF;
+
+ if (spec_len != 0x00FF && spec_len != *lp) {
+ DEBUGP("Lbad %02X %04X\n", *lp,
+ spec_len);
return 0;
- } else {
- DEBUGP("Lok ");
}
- }
- /* Step to the next */
- if ((unsigned char)*optdesc == 0){
- DEBUGP("PAD0 \n");
- ptr++;
- hdrlen--;
+ DEBUGP("Lok ");
+ optlen = *lp + 2;
} else {
- ptr += LOW(ntohs(*optdesc));
- hdrlen -= LOW(ntohs(*optdesc));
- DEBUGP("len%04X \n",
- LOW(ntohs(*optdesc)));
+ DEBUGP("Pad1\n");
+ optlen = 1;
}
- if (ptr > skb->len || ( !hdrlen &&
- (temp != optinfo->optsnr - 1))) {
+
+ /* Step to the next */
+ DEBUGP("len%04X \n", optlen);
+
+ if ((ptr > skb->len - optlen || hdrlen < optlen) &&
+ (temp < optinfo->optsnr - 1)) {
DEBUGP("new pointer is too large! \n");
break;
}
+ ptr += optlen;
+ hdrlen -= optlen;
}
if (temp == optinfo->optsnr)
return ret;
diff --git a/net/ipv6/netfilter/ip6t_hl.c b/net/ipv6/netfilter/ip6t_hl.c
index e538f14bb394..0beaff5471dd 100644
--- a/net/ipv6/netfilter/ip6t_hl.c
+++ b/net/ipv6/netfilter/ip6t_hl.c
@@ -20,7 +20,7 @@ MODULE_LICENSE("GPL");
static int match(const struct sk_buff *skb, const struct net_device *in,
const struct net_device *out, const void *matchinfo,
- int offset, const void *hdr, u_int16_t datalen,
+ int offset, unsigned int protoff,
int *hotdrop)
{
const struct ip6t_hl_info *info = matchinfo;
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c
index ae5d1c6c8002..b145beb0036e 100644
--- a/net/ipv6/netfilter/ip6t_ipv6header.c
+++ b/net/ipv6/netfilter/ip6t_ipv6header.c
@@ -31,8 +31,7 @@ ipv6header_match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
const struct ip6t_ipv6header_info *info = matchinfo;
diff --git a/net/ipv6/netfilter/ip6t_length.c b/net/ipv6/netfilter/ip6t_length.c
index 5a86722b1f0d..e0537d3811d5 100644
--- a/net/ipv6/netfilter/ip6t_length.c
+++ b/net/ipv6/netfilter/ip6t_length.c
@@ -23,8 +23,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
const struct ip6t_length_info *info = matchinfo;
diff --git a/net/ipv6/netfilter/ip6t_limit.c b/net/ipv6/netfilter/ip6t_limit.c
index 4780c3a9a9db..a462b771066a 100644
--- a/net/ipv6/netfilter/ip6t_limit.c
+++ b/net/ipv6/netfilter/ip6t_limit.c
@@ -57,8 +57,7 @@ ip6t_limit_match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
struct ip6t_rateinfo *r = ((struct ip6t_rateinfo *)matchinfo)->master;
diff --git a/net/ipv6/netfilter/ip6t_mac.c b/net/ipv6/netfilter/ip6t_mac.c
index ea874dd241dd..526d43e37234 100644
--- a/net/ipv6/netfilter/ip6t_mac.c
+++ b/net/ipv6/netfilter/ip6t_mac.c
@@ -25,8 +25,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
const struct ip6t_mac_info *info = matchinfo;
diff --git a/net/ipv6/netfilter/ip6t_mark.c b/net/ipv6/netfilter/ip6t_mark.c
index dc8484eee289..affc3de364fc 100644
--- a/net/ipv6/netfilter/ip6t_mark.c
+++ b/net/ipv6/netfilter/ip6t_mark.c
@@ -24,8 +24,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
const struct ip6t_mark_info *info = matchinfo;
diff --git a/net/ipv6/netfilter/ip6t_multiport.c b/net/ipv6/netfilter/ip6t_multiport.c
index 94c4dc3a957a..6e3246153fa3 100644
--- a/net/ipv6/netfilter/ip6t_multiport.c
+++ b/net/ipv6/netfilter/ip6t_multiport.c
@@ -53,28 +53,32 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- const struct udphdr *udp = hdr;
+ u16 _ports[2], *pptr;
const struct ip6t_multiport *multiinfo = matchinfo;
- /* Must be big enough to read ports. */
- if (offset == 0 && datalen < sizeof(struct udphdr)) {
+ /* Must not be a fragment. */
+ if (offset)
+ return 0;
+
+ /* Must be big enough to read ports (both UDP and TCP have
+ them at the start). */
+ pptr = skb_header_pointer(skb, protoff, sizeof(_ports), &_ports[0]);
+ if (pptr == NULL) {
/* We've been asked to examine this packet, and we
- can't. Hence, no choice but to drop. */
- duprintf("ip6t_multiport:"
- " Dropping evil offset=0 tinygram.\n");
- *hotdrop = 1;
- return 0;
+ * can't. Hence, no choice but to drop.
+ */
+ duprintf("ip6t_multiport:"
+ " Dropping evil offset=0 tinygram.\n");
+ *hotdrop = 1;
+ return 0;
}
- /* Must not be a fragment. */
- return !offset
- && ports_match(multiinfo->ports,
- multiinfo->flags, multiinfo->count,
- ntohs(udp->source), ntohs(udp->dest));
+ return ports_match(multiinfo->ports,
+ multiinfo->flags, multiinfo->count,
+ ntohs(pptr[0]), ntohs(pptr[1]));
}
/* Called when user tries to insert an entry of this type. */
diff --git a/net/ipv6/netfilter/ip6t_owner.c b/net/ipv6/netfilter/ip6t_owner.c
index 272257b3b637..ab0e32d3de46 100644
--- a/net/ipv6/netfilter/ip6t_owner.c
+++ b/net/ipv6/netfilter/ip6t_owner.c
@@ -92,8 +92,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
const struct ip6t_owner_info *info = matchinfo;
diff --git a/net/ipv6/netfilter/ip6t_physdev.c b/net/ipv6/netfilter/ip6t_physdev.c
index f4eebb43d219..71515c86ece1 100644
--- a/net/ipv6/netfilter/ip6t_physdev.c
+++ b/net/ipv6/netfilter/ip6t_physdev.c
@@ -26,8 +26,7 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *hdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
int i;
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index 4a7aae3a73c6..b5adc1057a9b 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -47,11 +47,10 @@ match(const struct sk_buff *skb,
const struct net_device *out,
const void *matchinfo,
int offset,
- const void *protohdr,
- u_int16_t datalen,
+ unsigned int protoff,
int *hotdrop)
{
- struct ipv6_rt_hdr *route = NULL;
+ struct ipv6_rt_hdr _route, *rh = NULL;
const struct ip6t_rt *rtinfo = matchinfo;
unsigned int temp;
unsigned int len;
@@ -59,6 +58,7 @@ match(const struct sk_buff *skb,
unsigned int ptr;
unsigned int hdrlen = 0;
unsigned int ret = 0;
+ struct in6_addr *ap, _addr;
/* type of the 1st exthdr */
nexthdr = skb->nh.ipv6h->nexthdr;
@@ -69,7 +69,7 @@ match(const struct sk_buff *skb,
temp = 0;
while (ip6t_ext_hdr(nexthdr)) {
- struct ipv6_opt_hdr *hdr;
+ struct ipv6_opt_hdr _hdr, *hp;
DEBUGP("ipv6_rt header iteration \n");
@@ -85,15 +85,16 @@ match(const struct sk_buff *skb,
break;
}
- hdr=(struct ipv6_opt_hdr *)(skb->data+ptr);
+ hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
+ BUG_ON(hp == NULL);
/* Calculate the header length */
if (nexthdr == NEXTHDR_FRAGMENT) {
hdrlen = 8;
} else if (nexthdr == NEXTHDR_AUTH)
- hdrlen = (hdr->hdrlen+2)<<2;
+ hdrlen = (hp->hdrlen+2)<<2;
else
- hdrlen = ipv6_optlen(hdr);
+ hdrlen = ipv6_optlen(hp);
/* ROUTING -> evaluate */
if (nexthdr == NEXTHDR_ROUTING) {
@@ -116,7 +117,7 @@ match(const struct sk_buff *skb,
break;
}
- nexthdr = hdr->nexthdr;
+ nexthdr = hp->nexthdr;
len -= hdrlen;
ptr += hdrlen;
if ( ptr > skb->len ) {
@@ -138,20 +139,21 @@ match(const struct sk_buff *skb,
return 0;
}
- route = (struct ipv6_rt_hdr *) (skb->data + ptr);
+ rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
+ BUG_ON(rh == NULL);
- DEBUGP("IPv6 RT LEN %u %u ", hdrlen, route->hdrlen);
- DEBUGP("TYPE %04X ", route->type);
- DEBUGP("SGS_LEFT %u %02X\n", route->segments_left, route->segments_left);
+ DEBUGP("IPv6 RT LEN %u %u ", hdrlen, rh->hdrlen);
+ DEBUGP("TYPE %04X ", rh->type);
+ DEBUGP("SGS_LEFT %u %02X\n", rh->segments_left, rh->segments_left);
DEBUGP("IPv6 RT segsleft %02X ",
(segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
- route->segments_left,
+ rh->segments_left,
!!(rtinfo->invflags & IP6T_RT_INV_SGS))));
DEBUGP("type %02X %02X %02X ",
- rtinfo->rt_type, route->type,
+ rtinfo->rt_type, rh->type,
(!(rtinfo->flags & IP6T_RT_TYP) ||
- ((rtinfo->rt_type == route->type) ^
+ ((rtinfo->rt_type == rh->type) ^
!!(rtinfo->invflags & IP6T_RT_INV_TYP))));
DEBUGP("len %02X %04X %02X ",
rtinfo->hdrlen, hdrlen,
@@ -159,13 +161,13 @@ match(const struct sk_buff *skb,
((rtinfo->hdrlen == hdrlen) ^
!!(rtinfo->invflags & IP6T_RT_INV_LEN))));
DEBUGP("res %02X %02X %02X ",
- (rtinfo->flags & IP6T_RT_RES), ((struct rt0_hdr *)route)->bitmap,
- !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)route)->bitmap)));
+ (rtinfo->flags & IP6T_RT_RES), ((struct rt0_hdr *)rh)->bitmap,
+ !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)rh)->bitmap)));
- ret = (route != NULL)
+ ret = (rh != NULL)
&&
(segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
- route->segments_left,
+ rh->segments_left,
!!(rtinfo->invflags & IP6T_RT_INV_SGS)))
&&
(!(rtinfo->flags & IP6T_RT_LEN) ||
@@ -173,13 +175,19 @@ match(const struct sk_buff *skb,
!!(rtinfo->invflags & IP6T_RT_INV_LEN)))
&&
(!(rtinfo->flags & IP6T_RT_TYP) ||
- ((rtinfo->rt_type == route->type) ^
- !!(rtinfo->invflags & IP6T_RT_INV_TYP)))
- &&
- !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)route)->bitmap));
+ ((rtinfo->rt_type == rh->type) ^
+ !!(rtinfo->invflags & IP6T_RT_INV_TYP)));
+
+ if (ret && (rtinfo->flags & IP6T_RT_RES)) {
+ u_int32_t *bp, _bitmap;
+ bp = skb_header_pointer(skb,
+ ptr + offsetof(struct rt0_hdr, bitmap),
+ sizeof(_bitmap), &_bitmap);
+
+ ret = (*bp == 0);
+ }
DEBUGP("#%d ",rtinfo->addrnr);
- temp = len = ptr = 0;
if ( !(rtinfo->flags & IP6T_RT_FST) ){
return ret;
} else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) {
@@ -188,32 +196,27 @@ match(const struct sk_buff *skb,
DEBUGP("There isn't enough space\n");
return 0;
} else {
+ unsigned int i = 0;
+
DEBUGP("#%d ",rtinfo->addrnr);
- ptr = 0;
for(temp=0; temp<(unsigned int)((hdrlen-8)/16); temp++){
- len = 0;
- while ((u8)(((struct rt0_hdr *)route)->
- addr[temp].s6_addr[len]) ==
- (u8)(rtinfo->addrs[ptr].s6_addr[len])){
- DEBUGP("%02X?%02X ",
- (u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]),
- (u8)(rtinfo->addrs[ptr].s6_addr[len]));
- len++;
- if ( len == 16 ) break;
- }
- if (len==16) {
- DEBUGP("ptr=%d temp=%d;\n",ptr,temp);
- ptr++;
- } else {
- DEBUGP("%02X?%02X ",
- (u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]),
- (u8)(rtinfo->addrs[ptr].s6_addr[len]));
- DEBUGP("!ptr=%d temp=%d;\n",ptr,temp);
+ ap = skb_header_pointer(skb,
+ ptr
+ + sizeof(struct rt0_hdr)
+ + temp * sizeof(_addr),
+ sizeof(_addr),
+ &_addr);
+
+ BUG_ON(ap == NULL);
+
+ if (!ipv6_addr_cmp(ap, &rtinfo->addrs[i])) {
+ DEBUGP("i=%d temp=%d;\n",i,temp);
+ i++;
}
- if (ptr==rtinfo->addrnr) break;
+ if (i==rtinfo->addrnr) break;
}
- DEBUGP("ptr=%d len=%d #%d\n",ptr,len, rtinfo->addrnr);
- if ( (len == 16) && (ptr == rtinfo->addrnr))
+ DEBUGP("i=%d #%d\n", i, rtinfo->addrnr);
+ if (i == rtinfo->addrnr)
return ret;
else return 0;
}
@@ -225,26 +228,19 @@ match(const struct sk_buff *skb,
} else {
DEBUGP("#%d ",rtinfo->addrnr);
for(temp=0; temp<rtinfo->addrnr; temp++){
- len = 0;
- while ((u8)(((struct rt0_hdr *)route)->
- addr[temp].s6_addr[len]) ==
- (u8)(rtinfo->addrs[temp].s6_addr[len])){
- DEBUGP("%02X?%02X ",
- (u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]),
- (u8)(rtinfo->addrs[temp].s6_addr[len]));
- len++;
- if ( len == 16 ) break;
- }
- if (len!=16) {
- DEBUGP("%02X?%02X ",
- (u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]),
- (u8)(rtinfo->addrs[temp].s6_addr[len]));
- DEBUGP("!len=%d temp=%d;\n",len,temp);
+ ap = skb_header_pointer(skb,
+ ptr
+ + sizeof(struct rt0_hdr)
+ + temp * sizeof(_addr),
+ sizeof(_addr),
+ &_addr);
+ BUG_ON(ap == NULL);
+
+ if (ipv6_addr_cmp(ap, &rtinfo->addrs[temp]))
break;
- }
}
- DEBUGP("temp=%d len=%d #%d\n",temp,len,rtinfo->addrnr);
- if ( (len == 16) && (temp == rtinfo->addrnr) && (temp == (unsigned int)((hdrlen-8)/16)))
+ DEBUGP("temp=%d #%d\n", temp, rtinfo->addrnr);
+ if ((temp == rtinfo->addrnr) && (temp == (unsigned int)((hdrlen-8)/16)))
return ret;
else return 0;
}
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index c73d720114fa..ff920c712d01 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -639,7 +639,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
return -EINVAL;
if (sin6->sin6_family && sin6->sin6_family != AF_INET6)
- return(-EINVAL);
+ return(-EAFNOSUPPORT);
/* port is the proto value [0..255] carried in nexthdr */
proto = ntohs(sin6->sin6_port);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 70b9bb44dd93..886b7ccb3c3b 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -88,7 +88,7 @@ static void ip6_dst_ifdown(struct dst_entry *, int how);
static int ip6_dst_gc(void);
static int ip6_pkt_discard(struct sk_buff *skb);
-static int ip6_pkt_discard_out(struct sk_buff **pskb);
+static int ip6_pkt_discard_out(struct sk_buff *skb);
static void ip6_link_failure(struct sk_buff *skb);
static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
@@ -638,7 +638,7 @@ static inline unsigned int ipv6_advmss(unsigned int mtu)
struct dst_entry *ndisc_dst_alloc(struct net_device *dev,
struct neighbour *neigh,
struct in6_addr *addr,
- int (*output)(struct sk_buff **))
+ int (*output)(struct sk_buff *))
{
struct rt6_info *rt;
struct inet6_dev *idev = in6_dev_get(dev);
@@ -1288,20 +1288,14 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
return rt6_get_dflt_router(gwaddr, dev);
}
-void rt6_purge_dflt_routers(int last_resort)
+void rt6_purge_dflt_routers(void)
{
struct rt6_info *rt;
- u32 flags;
-
- if (last_resort)
- flags = RTF_ALLONLINK;
- else
- flags = RTF_DEFAULT | RTF_ADDRCONF;
restart:
read_lock_bh(&rt6_lock);
for (rt = ip6_routing_table.leaf; rt; rt = rt->u.next) {
- if (rt->rt6i_flags & flags) {
+ if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) {
dst_hold(&rt->u.dst);
rt6_reset_dflt_pointer(NULL);
@@ -1362,11 +1356,10 @@ int ip6_pkt_discard(struct sk_buff *skb)
return 0;
}
-int ip6_pkt_discard_out(struct sk_buff **pskb)
+int ip6_pkt_discard_out(struct sk_buff *skb)
{
- (*pskb)->dev = (*pskb)->dst->dev;
- BUG_ON(!(*pskb)->dev);
- return ip6_pkt_discard(*pskb);
+ skb->dev = skb->dst->dev;
+ return ip6_pkt_discard(skb);
}
/*
@@ -1592,7 +1585,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
rtm->rtm_protocol = rt->rt6i_protocol;
if (rt->rt6i_flags&RTF_DYNAMIC)
rtm->rtm_protocol = RTPROT_REDIRECT;
- else if (rt->rt6i_flags&(RTF_ADDRCONF|RTF_ALLONLINK))
+ else if (rt->rt6i_flags & RTF_ADDRCONF)
rtm->rtm_protocol = RTPROT_KERNEL;
else if (rt->rt6i_flags&RTF_DEFAULT)
rtm->rtm_protocol = RTPROT_RA;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index fa13a74492ab..7112e8406a28 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1802,6 +1802,7 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
struct ipv6_pinfo *np = inet6_sk(sk);
struct flowi fl;
struct dst_entry *dst;
+ struct in6_addr *final_p = NULL, final;
memset(&fl, 0, sizeof(fl));
fl.proto = IPPROTO_TCP;
@@ -1815,7 +1816,9 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
+ ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
+ final_p = &final;
}
dst = __sk_dst_check(sk, np->dst_cookie);
@@ -1828,6 +1831,9 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
return err;
}
+ if (final_p)
+ ipv6_addr_copy(&fl.fl6_dst, final_p);
+
if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) {
sk->sk_route_caps = 0;
dst_release(dst);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index ff00dc49cdd8..8c18a474d5f0 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -699,7 +699,7 @@ do_udp_sendmsg:
if (likely(up->pending)) {
if (unlikely(up->pending != AF_INET6)) {
release_sock(sk);
- return -EINVAL;
+ return -EAFNOSUPPORT;
}
dst = NULL;
goto do_append_data;
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 40612ec54305..fbd3aa02d062 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -91,16 +91,14 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
return ret;
}
-int xfrm6_output(struct sk_buff **pskb)
+int xfrm6_output(struct sk_buff *skb)
{
- struct sk_buff *skb = *pskb;
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
int err;
if (skb->ip_summed == CHECKSUM_HW) {
- err = skb_checksum_help(pskb, 0);
- skb = *pskb;
+ err = skb_checksum_help(skb, 0);
if (err)
goto error_nolock;
}
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 4a1e9d237edc..551d8587c226 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -308,7 +308,7 @@ dev_graft_qdisc(struct net_device *dev, struct Qdisc *qdisc)
dev_deactivate(dev);
qdisc_lock_tree(dev);
- if (qdisc && qdisc->flags&TCQ_F_INGRES) {
+ if (qdisc && qdisc->flags&TCQ_F_INGRESS) {
oqdisc = dev->qdisc_ingress;
/* Prune old scheduler */
if (oqdisc && atomic_read(&oqdisc->refcnt) <= 1) {
@@ -357,7 +357,7 @@ int qdisc_graft(struct net_device *dev, struct Qdisc *parent, u32 classid,
if (parent == NULL) {
- if (q && q->flags&TCQ_F_INGRES) {
+ if (q && q->flags&TCQ_F_INGRESS) {
*old = dev_graft_qdisc(dev, q);
} else {
*old = dev_graft_qdisc(dev, new);
@@ -430,7 +430,7 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
skb_queue_head_init(&sch->q);
if (handle == TC_H_INGRESS)
- sch->flags |= TCQ_F_INGRES;
+ sch->flags |= TCQ_F_INGRESS;
sch->ops = ops;
sch->enqueue = ops->enqueue;
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 16b718fa5172..3a64c225cb37 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -271,7 +271,7 @@ struct sctp_association *sctp_association_init(struct sctp_association *asoc,
asoc->need_ecne = 0;
- asoc->assoc_id = (sctp_assoc_t)-1L;
+ asoc->assoc_id = 0;
/* Assume that peer would support both address types unless we are
* told otherwise.
@@ -374,9 +374,9 @@ static void sctp_association_destroy(struct sctp_association *asoc)
sctp_endpoint_put(asoc->ep);
sock_put(asoc->base.sk);
- if ((long)asoc->assoc_id != -1L) {
+ if (asoc->assoc_id != 0) {
spin_lock_bh(&sctp_assocs_id_lock);
- idr_remove(&sctp_assocs_id, (long)asoc->assoc_id);
+ idr_remove(&sctp_assocs_id, asoc->assoc_id);
spin_unlock_bh(&sctp_assocs_id_lock);
}
@@ -482,14 +482,15 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
/* 7.2.1 Slow-Start
*
- * o The initial cwnd before data transmission or after a
- * sufficiently long idle period MUST be <= 2*MTU.
+ * o The initial cwnd before DATA transmission or after a sufficiently
+ * long idle period MUST be set to
+ * min(4*MTU, max(2*MTU, 4380 bytes))
*
* o The initial value of ssthresh MAY be arbitrarily high
* (for example, implementations MAY use the size of the
* receiver advertised window).
*/
- peer->cwnd = asoc->pmtu * 2;
+ peer->cwnd = min(4*asoc->pmtu, max_t(__u32, 2*asoc->pmtu, 4380));
/* At this point, we may not have the receiver's advertised window,
* so initialize ssthresh to the default value and it will be set
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 13fda7792e7c..8f2d18263792 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -706,10 +706,19 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
if (!new_transport) {
new_transport = asoc->peer.active_path;
} else if (!new_transport->active) {
- /* If the chunk is Heartbeat, send it to
- * chunk->transport, even it's inactive.
+ /* If the chunk is Heartbeat or Heartbeat Ack,
+ * send it to chunk->transport, even if it's
+ * inactive.
+ *
+ * 3.3.6 Heartbeat Acknowledgement:
+ * ...
+ * A HEARTBEAT ACK is always sent to the source IP
+ * address of the IP datagram containing the
+ * HEARTBEAT chunk to which this ack is responding.
+ * ...
*/
- if (chunk->chunk_hdr->type != SCTP_CID_HEARTBEAT)
+ if (chunk->chunk_hdr->type != SCTP_CID_HEARTBEAT &&
+ chunk->chunk_hdr->type != SCTP_CID_HEARTBEAT_ACK)
new_transport = asoc->peer.active_path;
}
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index c2ca732595fa..1f0676d1ffbc 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -171,6 +171,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
struct sctp_opt *sp;
sctp_supported_addrs_param_t sat;
__u16 types[2];
+ sctp_adaption_ind_param_t aiparam;
/* RFC 2960 3.3.2 Initiation (INIT) (1)
*
@@ -196,6 +197,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
chunksize += sizeof(ecap_param);
if (sctp_prsctp_enable)
chunksize += sizeof(prsctp_param);
+ chunksize += sizeof(aiparam);
chunksize += vparam_len;
/* RFC 2960 3.3.2 Initiation (INIT) (1)
@@ -234,6 +236,10 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc,
sctp_addto_chunk(retval, sizeof(ecap_param), &ecap_param);
if (sctp_prsctp_enable)
sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);
+ aiparam.param_hdr.type = SCTP_PARAM_ADAPTION_LAYER_IND;
+ aiparam.param_hdr.length = htons(sizeof(aiparam));
+ aiparam.adaption_ind = htonl(sp->adaption_ind);
+ sctp_addto_chunk(retval, sizeof(aiparam), &aiparam);
nodata:
if (addrs.v)
kfree(addrs.v);
@@ -251,6 +257,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
sctp_cookie_param_t *cookie;
int cookie_len;
size_t chunksize;
+ sctp_adaption_ind_param_t aiparam;
retval = NULL;
@@ -284,6 +291,8 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
if (asoc->peer.prsctp_capable)
chunksize += sizeof(prsctp_param);
+ chunksize += sizeof(aiparam);
+
/* Now allocate and fill out the chunk. */
retval = sctp_make_chunk(asoc, SCTP_CID_INIT_ACK, 0, chunksize);
if (!retval)
@@ -302,6 +311,11 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
if (asoc->peer.prsctp_capable)
sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param);
+ aiparam.param_hdr.type = SCTP_PARAM_ADAPTION_LAYER_IND;
+ aiparam.param_hdr.length = htons(sizeof(aiparam));
+ aiparam.adaption_ind = htonl(sctp_sk(asoc->base.sk)->adaption_ind);
+ sctp_addto_chunk(retval, sizeof(aiparam), &aiparam);
+
/* We need to remove the const qualifier at this point. */
retval->asoc = (struct sctp_association *) asoc;
@@ -1297,6 +1311,9 @@ sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
/* Remember PR-SCTP capability. */
cookie->c.prsctp_capable = asoc->peer.prsctp_capable;
+ /* Save adaption indication in the cookie. */
+ cookie->c.adaption_ind = asoc->peer.adaption_ind;
+
/* Set an expiration time for the cookie. */
do_gettimeofday(&cookie->c.expiration);
TIMEVAL_ADD(asoc->cookie_life, cookie->c.expiration);
@@ -1455,6 +1472,7 @@ no_hmac:
retval->addip_serial = retval->c.initial_tsn;
retval->adv_peer_ack_point = retval->ctsn_ack_point;
retval->peer.prsctp_capable = retval->c.prsctp_capable;
+ retval->peer.adaption_ind = retval->c.adaption_ind;
/* The INIT stuff will be done by the side effects. */
return retval;
@@ -1661,6 +1679,7 @@ static int sctp_verify_param(const struct sctp_association *asoc,
case SCTP_PARAM_HEARTBEAT_INFO:
case SCTP_PARAM_UNRECOGNIZED_PARAMETERS:
case SCTP_PARAM_ECN_CAPABLE:
+ case SCTP_PARAM_ADAPTION_LAYER_IND:
break;
case SCTP_PARAM_HOST_NAME_ADDRESS:
@@ -1989,6 +2008,10 @@ int sctp_process_param(struct sctp_association *asoc, union sctp_params param,
asoc->peer.ecn_capable = 1;
break;
+ case SCTP_PARAM_ADAPTION_LAYER_IND:
+ asoc->peer.adaption_ind = param.aind->adaption_ind;
+ break;
+
case SCTP_PARAM_FWD_TSN_SUPPORT:
if (sctp_prsctp_enable) {
asoc->peer.prsctp_capable = 1;
@@ -2459,6 +2482,8 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
union sctp_addr addr;
struct sctp_bind_addr *bp = &asoc->base.bind_addr;
union sctp_addr_param *addr_param;
+ struct list_head *pos;
+ struct sctp_transport *transport;
int retval = 0;
addr_param = (union sctp_addr_param *)
@@ -2482,6 +2507,12 @@ static int sctp_asconf_param_success(struct sctp_association *asoc,
retval = sctp_del_bind_addr(bp, &addr);
sctp_write_unlock(&asoc->base.addr_lock);
sctp_local_bh_enable();
+ list_for_each(pos, &asoc->peer.transport_addr_list) {
+ transport = list_entry(pos, struct sctp_transport,
+ transports);
+ sctp_transport_route(transport, NULL,
+ sctp_sk(asoc->base.sk));
+ }
break;
default:
break;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index addb95d790cd..7871faa08378 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -629,6 +629,21 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+ /* Sockets API Draft Section 5.3.1.6
+ * When a peer sends a Adaption Layer Indication parameter , SCTP
+ * delivers this notification to inform the application that of the
+ * peers requested adaption layer.
+ */
+ if (new_asoc->peer.adaption_ind) {
+ ev = sctp_ulpevent_make_adaption_indication(new_asoc,
+ GFP_ATOMIC);
+ if (!ev)
+ goto nomem_ev;
+
+ sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+ SCTP_ULPEVENT(ev));
+ }
+
return SCTP_DISPOSITION_CONSUME;
nomem_ev:
@@ -713,6 +728,20 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+ /* Sockets API Draft Section 5.3.1.6
+ * When a peer sends a Adaption Layer Indication parameter , SCTP
+ * delivers this notification to inform the application that of the
+ * peers requested adaption layer.
+ */
+ if (asoc->peer.adaption_ind) {
+ ev = sctp_ulpevent_make_adaption_indication(asoc, GFP_ATOMIC);
+ if (!ev)
+ goto nomem;
+
+ sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+ SCTP_ULPEVENT(ev));
+ }
+
return SCTP_DISPOSITION_CONSUME;
nomem:
return SCTP_DISPOSITION_NOMEM;
@@ -1532,6 +1561,21 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,
goto nomem_ev;
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+
+ /* Sockets API Draft Section 5.3.1.6
+ * When a peer sends a Adaption Layer Indication parameter , SCTP
+ * delivers this notification to inform the application that of the
+ * peers requested adaption layer.
+ */
+ if (asoc->peer.adaption_ind) {
+ ev = sctp_ulpevent_make_adaption_indication(asoc, GFP_ATOMIC);
+ if (!ev)
+ goto nomem_ev;
+
+ sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+ SCTP_ULPEVENT(ev));
+ }
+
return SCTP_DISPOSITION_CONSUME;
nomem_ev:
@@ -1612,6 +1656,21 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,
goto nomem;
sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
SCTP_ULPEVENT(ev));
+
+ /* Sockets API Draft Section 5.3.1.6
+ * When a peer sends a Adaption Layer Indication parameter,
+ * SCTP delivers this notification to inform the application
+ * that of the peers requested adaption layer.
+ */
+ if (new_asoc->peer.adaption_ind) {
+ ev = sctp_ulpevent_make_adaption_indication(new_asoc,
+ GFP_ATOMIC);
+ if (!ev)
+ goto nomem;
+
+ sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
+ SCTP_ULPEVENT(ev));
+ }
}
sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 0d1bc4507d6b..6e61bce2f97a 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1063,7 +1063,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
struct sctp_sndrcvinfo default_sinfo = { 0 };
struct sctp_sndrcvinfo *sinfo;
struct sctp_initmsg *sinit;
- sctp_assoc_t associd = NULL;
+ sctp_assoc_t associd = 0;
sctp_cmsgs_t cmsgs = { NULL };
int err;
sctp_scope_t scope;
@@ -2120,6 +2120,20 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
return err;
}
+static int sctp_setsockopt_adaption_layer(struct sock *sk, char __user *optval,
+ int optlen)
+{
+ __u32 val;
+
+ if (optlen < sizeof(__u32))
+ return -EINVAL;
+ if (copy_from_user(&val, optval, sizeof(__u32)))
+ return -EFAULT;
+
+ sctp_sk(sk)->adaption_ind = val;
+
+ return 0;
+}
/* API 6.2 setsockopt(), getsockopt()
*
@@ -2219,6 +2233,10 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
case SCTP_MAXSEG:
retval = sctp_setsockopt_maxseg(sk, optval, optlen);
break;
+ case SCTP_ADAPTION_LAYER:
+ retval = sctp_setsockopt_adaption_layer(sk, optval, optlen);
+ break;
+
default:
retval = -ENOPROTOOPT;
break;
@@ -2518,6 +2536,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
/* User specified fragmentation limit. */
sp->user_frag = 0;
+ sp->adaption_ind = 0;
+
sp->pf = sctp_get_pf_specific(sk->sk_family);
/* Control variables for partial data delivery. */
@@ -3160,6 +3180,29 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
}
/*
+ * 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER)
+ *
+ * Requests that the local endpoint set the specified Adaption Layer
+ * Indication parameter for all future INIT and INIT-ACK exchanges.
+ */
+static int sctp_getsockopt_adaption_layer(struct sock *sk, int len,
+ char __user *optval, int __user *optlen)
+{
+ __u32 val;
+
+ if (len < sizeof(__u32))
+ return -EINVAL;
+
+ len = sizeof(__u32);
+ val = sctp_sk(sk)->adaption_ind;
+ if (put_user(len, optlen))
+ return -EFAULT;
+ if (copy_to_user(optval, &val, len))
+ return -EFAULT;
+ return 0;
+}
+
+/*
*
* 7.1.14 Set default send parameters (SCTP_DEFAULT_SEND_PARAM)
*
@@ -3515,6 +3558,10 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
retval = sctp_getsockopt_peer_addr_info(sk, len, optval,
optlen);
break;
+ case SCTP_ADAPTION_LAYER:
+ retval = sctp_getsockopt_adaption_layer(sk, len, optval,
+ optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 198ab7662c2e..c4a2370beb12 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -421,15 +421,15 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
{
switch (reason) {
case SCTP_LOWER_CWND_T3_RTX:
- /* RFC 2960 Section 7.2.3, sctpimpguide-05 Section 2.9.2
+ /* RFC 2960 Section 7.2.3, sctpimpguide
* When the T3-rtx timer expires on an address, SCTP should
* perform slow start by:
- * ssthresh = max(cwnd/2, 2*MTU)
+ * ssthresh = max(cwnd/2, 4*MTU)
* cwnd = 1*MTU
* partial_bytes_acked = 0
*/
transport->ssthresh = max(transport->cwnd/2,
- 2*transport->asoc->pmtu);
+ 4*transport->asoc->pmtu);
transport->cwnd = transport->asoc->pmtu;
break;
@@ -439,15 +439,15 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
* were last sent, according to the formula described in
* Section 7.2.3.
*
- * RFC 2960 7.2.3, sctpimpguide-05 2.9.2 Upon detection of
- * packet losses from SACK (see Section 7.2.4), An endpoint
+ * RFC 2960 7.2.3, sctpimpguide Upon detection of packet
+ * losses from SACK (see Section 7.2.4), An endpoint
* should do the following:
- * ssthresh = max(cwnd/2, 2*MTU)
+ * ssthresh = max(cwnd/2, 4*MTU)
* cwnd = ssthresh
* partial_bytes_acked = 0
*/
transport->ssthresh = max(transport->cwnd/2,
- 2*transport->asoc->pmtu);
+ 4*transport->asoc->pmtu);
transport->cwnd = transport->ssthresh;
break;
@@ -467,23 +467,24 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport,
if ((jiffies - transport->last_time_ecne_reduced) >
transport->rtt) {
transport->ssthresh = max(transport->cwnd/2,
- 2*transport->asoc->pmtu);
+ 4*transport->asoc->pmtu);
transport->cwnd = transport->ssthresh;
transport->last_time_ecne_reduced = jiffies;
}
break;
case SCTP_LOWER_CWND_INACTIVE:
- /* RFC 2960 Section 7.2.1, sctpimpguide-05 Section 2.14.2
- * When the association does not transmit data on a given
- * transport address within an RTO, the cwnd of the transport
- * address should be adjusted to 2*MTU.
+ /* RFC 2960 Section 7.2.1, sctpimpguide
+ * When the endpoint does not transmit data on a given
+ * transport address, the cwnd of the transport address
+ * should be adjusted to max(cwnd/2, 4*MTU) per RTO.
* NOTE: Although the draft recommends that this check needs
* to be done every RTO interval, we do it every hearbeat
* interval.
*/
if ((jiffies - transport->last_time_used) > transport->rto)
- transport->cwnd = 2*transport->asoc->pmtu;
+ transport->cwnd = max(transport->cwnd/2,
+ 4*transport->asoc->pmtu);
break;
};
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index e804d6ed8c0f..cd002b577e85 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -562,7 +562,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_shutdown_event(
struct sctp_shutdown_event *sse;
struct sk_buff *skb;
- event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
+ event = sctp_ulpevent_new(sizeof(struct sctp_shutdown_event),
MSG_NOTIFICATION, gfp);
if (!event)
goto fail;
@@ -613,6 +613,40 @@ fail:
return NULL;
}
+/* Create and initialize a SCTP_ADAPTION_INDICATION notification.
+ *
+ * Socket Extensions for SCTP
+ * 5.3.1.6 SCTP_ADAPTION_INDICATION
+ */
+struct sctp_ulpevent *sctp_ulpevent_make_adaption_indication(
+ const struct sctp_association *asoc, int gfp)
+{
+ struct sctp_ulpevent *event;
+ struct sctp_adaption_event *sai;
+ struct sk_buff *skb;
+
+ event = sctp_ulpevent_new(sizeof(struct sctp_adaption_event),
+ MSG_NOTIFICATION, gfp);
+ if (!event)
+ goto fail;
+
+ skb = sctp_event2skb(event);
+ sai = (struct sctp_adaption_event *)
+ skb_put(skb, sizeof(struct sctp_adaption_event));
+
+ sai->sai_type = SCTP_ADAPTION_INDICATION;
+ sai->sai_flags = 0;
+ sai->sai_length = sizeof(struct sctp_adaption_event);
+ sai->sai_adaption_ind = asoc->peer.adaption_ind;
+ sctp_ulpevent_set_owner(event, asoc);
+ sai->sai_assoc_id = sctp_assoc2id(asoc);
+
+ return event;
+
+fail:
+ return NULL;
+}
+
/* A message has been received. Package this message as a notification
* to pass it to the upper layers. Go ahead and calculate the sndrcvinfo
* even if filtered out later.
@@ -689,7 +723,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_pdapi(
struct sctp_pdapi_event *pd;
struct sk_buff *skb;
- event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
+ event = sctp_ulpevent_new(sizeof(struct sctp_pdapi_event),
MSG_NOTIFICATION, gfp);
if (!event)
goto fail;
diff --git a/net/socket.c b/net/socket.c
index 275d8cf6d3be..102d2737c269 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -459,7 +459,7 @@ struct socket *sockfd_lookup(int fd, int *err)
* NULL is returned.
*/
-struct socket *sock_alloc(void)
+static struct socket *sock_alloc(void)
{
struct inode * inode;
struct socket * sock;
@@ -1354,7 +1354,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _
if (!sock)
goto out;
- err = -EMFILE;
+ err = -ENFILE;
if (!(newsock = sock_alloc()))
goto out_put;
@@ -2089,8 +2089,6 @@ void socket_seq_show(struct seq_file *seq)
/* ABI emulation layers need these two */
EXPORT_SYMBOL(move_addr_to_kernel);
EXPORT_SYMBOL(move_addr_to_user);
-EXPORT_SYMBOL(sock_alloc);
-EXPORT_SYMBOL(sock_alloc_inode);
EXPORT_SYMBOL(sock_create);
EXPORT_SYMBOL(sock_create_kern);
EXPORT_SYMBOL(sock_create_lite);
diff --git a/net/xfrm/xfrm_export.c b/net/xfrm/xfrm_export.c
index 9f335640d254..24dbc9a99b1b 100644
--- a/net/xfrm/xfrm_export.c
+++ b/net/xfrm/xfrm_export.c
@@ -12,22 +12,17 @@ EXPORT_SYMBOL(__xfrm_policy_check);
EXPORT_SYMBOL(__xfrm_route_forward);
EXPORT_SYMBOL(xfrm_state_alloc);
EXPORT_SYMBOL(__xfrm_state_destroy);
-EXPORT_SYMBOL(xfrm_state_find);
EXPORT_SYMBOL(xfrm_state_insert);
EXPORT_SYMBOL(xfrm_state_add);
EXPORT_SYMBOL(xfrm_state_update);
EXPORT_SYMBOL(xfrm_state_check_expire);
-EXPORT_SYMBOL(xfrm_state_check_space);
EXPORT_SYMBOL(xfrm_state_check);
EXPORT_SYMBOL(xfrm_state_lookup);
EXPORT_SYMBOL(xfrm_state_register_afinfo);
EXPORT_SYMBOL(xfrm_state_unregister_afinfo);
-EXPORT_SYMBOL(xfrm_state_get_afinfo);
-EXPORT_SYMBOL(xfrm_state_put_afinfo);
EXPORT_SYMBOL(xfrm_state_delete_tunnel);
EXPORT_SYMBOL(xfrm_replay_check);
EXPORT_SYMBOL(xfrm_replay_advance);
-EXPORT_SYMBOL(xfrm_check_selectors);
EXPORT_SYMBOL(__secpath_destroy);
EXPORT_SYMBOL(secpath_dup);
EXPORT_SYMBOL(xfrm_get_acqseq);
@@ -44,7 +39,6 @@ EXPORT_SYMBOL(xfrm_find_acq_byseq);
EXPORT_SYMBOL(xfrm_find_acq);
EXPORT_SYMBOL(xfrm_alloc_spi);
EXPORT_SYMBOL(xfrm_state_flush);
-EXPORT_SYMBOL(xfrm_policy_kill);
EXPORT_SYMBOL(xfrm_policy_bysel);
EXPORT_SYMBOL(xfrm_policy_insert);
EXPORT_SYMBOL(xfrm_policy_walk);
@@ -54,8 +48,6 @@ EXPORT_SYMBOL(xfrm_policy_list);
EXPORT_SYMBOL(xfrm_dst_lookup);
EXPORT_SYMBOL(xfrm_policy_register_afinfo);
EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
-EXPORT_SYMBOL(xfrm_policy_get_afinfo);
-EXPORT_SYMBOL(xfrm_policy_put_afinfo);
EXPORT_SYMBOL_GPL(xfrm_probe_algs);
EXPORT_SYMBOL_GPL(xfrm_count_auth_supported);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 1708bf045a2b..452cb1647a8a 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -40,6 +40,9 @@ static struct list_head xfrm_policy_gc_list =
LIST_HEAD_INIT(xfrm_policy_gc_list);
static spinlock_t xfrm_policy_gc_lock = SPIN_LOCK_UNLOCKED;
+static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
+static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
+
int xfrm_register_type(struct xfrm_type *type, unsigned short family)
{
struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
@@ -286,7 +289,7 @@ static void xfrm_policy_gc_task(void *data)
* entry dead. The rule must be unlinked from lists to the moment.
*/
-void xfrm_policy_kill(struct xfrm_policy *policy)
+static void xfrm_policy_kill(struct xfrm_policy *policy)
{
write_lock_bh(&policy->lock);
if (policy->dead)
@@ -1187,7 +1190,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
return err;
}
-struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
+static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
{
struct xfrm_policy_afinfo *afinfo;
if (unlikely(family >= NPROTO))
@@ -1200,7 +1203,7 @@ struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family)
return afinfo;
}
-void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
+static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
{
if (unlikely(afinfo == NULL))
return;
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 2317ae179be9..93a7693aa7c5 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -48,6 +48,9 @@ static spinlock_t xfrm_state_gc_lock = SPIN_LOCK_UNLOCKED;
static void __xfrm_state_delete(struct xfrm_state *x);
+static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
+static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
+
static void xfrm_state_gc_destroy(struct xfrm_state *x)
{
if (del_timer(&x->timer))
@@ -526,7 +529,7 @@ int xfrm_state_check_expire(struct xfrm_state *x)
return 0;
}
-int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb)
+static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb)
{
int nhead = x->props.header_len + LL_RESERVED_SPACE(skb->dst->dev)
- skb_headroom(skb);
@@ -740,19 +743,6 @@ void xfrm_replay_advance(struct xfrm_state *x, u32 seq)
}
}
-int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl)
-{
- int i;
-
- for (i=0; i<n; i++) {
- int match;
- match = xfrm_selector_match(&x[i]->sel, fl, x[i]->props.family);
- if (!match)
- return -EINVAL;
- }
- return 0;
-}
-
static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);
static rwlock_t xfrm_km_lock = RW_LOCK_UNLOCKED;
@@ -914,7 +904,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo)
return err;
}
-struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
+static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
{
struct xfrm_state_afinfo *afinfo;
if (unlikely(family >= NPROTO))
@@ -927,7 +917,7 @@ struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family)
return afinfo;
}
-void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
+static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo)
{
if (unlikely(afinfo == NULL))
return;