CVSROOT: /home/cvs
Module name: linux
Changes by: ralf@ftp.linux-mips.org 05/01/20 02:19:27
Modified files:
. : Tag: linux_2_4 Makefile
Documentation : Tag: linux_2_4 Changes Configure.help
arch/i386 : Tag: linux_2_4 defconfig
arch/mips : Tag: linux_2_4 defconfig-bosporus
defconfig-mtx-1
arch/mips64 : Tag: linux_2_4 defconfig defconfig-ip27
arch/ppc : Tag: linux_2_4 defconfig
arch/ppc/configs: Tag: linux_2_4 apus_defconfig briq_defconfig
common_defconfig ibmchrp_defconfig
pal4_defconfig pmac_defconfig pplus_defconfig
prpmc750_defconfig
arch/s390 : Tag: linux_2_4 defconfig
arch/sparc64 : Tag: linux_2_4 defconfig
drivers/char : Tag: linux_2_4 tty_io.c
drivers/net : Tag: linux_2_4 tg3.c
include/linux : Tag: linux_2_4 if_arp.h if_ether.h netfilter.h
sctp.h
include/linux/netfilter_ipv4: Tag: linux_2_4 ip_conntrack_core.h
ip_nat.h
include/net : Tag: linux_2_4 inet_ecn.h ip.h ip_vs.h
include/net/sctp: Tag: linux_2_4 command.h compat.h constants.h
sctp.h sm.h structs.h tsnmap.h ulpevent.h
ulpqueue.h
init : Tag: linux_2_4 do_mounts.c
net : Tag: linux_2_4 netsyms.c
net/core : Tag: linux_2_4 neighbour.c netfilter.c
net/ipv4 : Tag: linux_2_4 icmp.c ip_output.c raw.c udp.c
net/ipv4/ipvs : Tag: linux_2_4 ip_vs_core.c ip_vs_ctl.c
ip_vs_sync.c
net/ipv4/netfilter: Tag: linux_2_4 Config.in ip_conntrack_core.c
ip_conntrack_standalone.c
ip_fw_compat_masq.c ip_nat_core.c
ip_nat_rule.c ip_nat_standalone.c
ip_tables.c ipt_MASQUERADE.c ipt_REJECT.c
net/ipv6 : Tag: linux_2_4 sit.c
net/ipv6/netfilter: Tag: linux_2_4 ip6_tables.c ip6t_LOG.c
ip6t_dst.c ip6t_esp.c ip6t_eui64.c
ip6t_frag.c ip6t_hbh.c ip6t_ipv6header.c
ip6t_multiport.c ip6t_rt.c
net/sched : Tag: linux_2_4 sch_dsmark.c
net/sctp : Tag: linux_2_4 associola.c bind_addr.c chunk.c
command.c debug.c endpointola.c input.c
inqueue.c ipv6.c objcnt.c output.c outqueue.c
proc.c protocol.c sm_make_chunk.c
sm_sideeffect.c sm_statefuns.c sm_statetable.c
socket.c ssnmap.c transport.c tsnmap.c
ulpevent.c ulpqueue.c
Log message:
Merge with Linux 2.4.29.
diff -urN linux/Makefile linux/Makefile
--- linux/Makefile 2005/01/13 10:59:02 1.119.2.32
+++ linux/Makefile 2005/01/20 02:19:21 1.119.2.33
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 29
-EXTRAVERSION = -rc2
+EXTRAVERSION =
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
diff -urN linux/Documentation/Changes linux/Documentation/Changes
--- linux/Documentation/Changes 2003/12/15 18:19:48 1.49.2.5
+++ linux/Documentation/Changes 2005/01/20 02:19:21 1.49.2.6
@@ -52,7 +52,7 @@
o Gnu make 3.77 # make --version
o binutils 2.9.1.0.25 # ld -v
o util-linux 2.10o # fdformat --version
-o modutils 2.4.2 # insmod -V
+o modutils 2.4.10 # insmod -V
o e2fsprogs 1.25 # tune2fs
o jfsutils 1.0.12 # fsck.jfs -V
o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep
reiserfsprogs
@@ -159,8 +159,8 @@
Upgrade to recent modutils to fix various outstanding bugs which are
seen more frequently under 2.4.x, and to enable auto-loading of USB
modules. In addition, the layout of modules under
-/lib/modules/`uname -r`/ has been made more sane. This change also
-requires that you upgrade to a recent modutils.
+/lib/modules/`uname -r`/ has been made more sane, and EXPORT_SYMBOL_GPL
+also requires that you upgrade to a recent modutils.
Mkinitrd
--------
diff -urN linux/Documentation/Configure.help linux/Documentation/Configure.help
--- linux/Documentation/Attic/Configure.help 2004/12/27 04:13:37
1.109.2.54
+++ linux/Documentation/Attic/Configure.help 2005/01/20 02:19:21
1.109.2.55
@@ -3042,19 +3042,6 @@
If you want to compile it as a module, say M here and read
<file:Documentation/modules.txt>. If unsure, say `N'.
-Local NAT support
-CONFIG_IP_NF_NAT_LOCAL
- This option enables support for NAT of locally originated connections.
- Enable this if you need to use destination NAT on connections
- originating from local processes on the nat box itself.
-
- Please note that you will need a recent version (>= 1.2.6a)
- of the iptables userspace program in order to use this feature.
- See <http://www.iptables.org/> for download instructions.
-
- If unsure, say 'N'.
-
-
Full NAT (Network Address Translation)
CONFIG_IP_NF_NAT
The Full NAT option allows masquerading, port forwarding and other
diff -urN linux/arch/i386/defconfig linux/arch/i386/defconfig
--- linux/arch/i386/defconfig 2004/11/19 00:28:31 1.76.2.8
+++ linux/arch/i386/defconfig 2005/01/20 02:19:22 1.76.2.9
@@ -200,11 +200,6 @@
#
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_DEV_APPLETALK is not set
# CONFIG_DECNET is not set
# CONFIG_BRIDGE is not set
@@ -240,10 +235,12 @@
#
# CONFIG_BLK_DEV_HD_IDE is not set
# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDEDISK_MULTI_MODE=y
# CONFIG_IDEDISK_STROKE is not set
# CONFIG_BLK_DEV_IDECS is not set
+# CONFIG_BLK_DEV_DELKIN is not set
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDETAPE is not set
# CONFIG_BLK_DEV_IDEFLOPPY is not set
@@ -346,11 +343,15 @@
# CONFIG_SCSI_MEGARAID is not set
# CONFIG_SCSI_MEGARAID2 is not set
# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_SATA_AHCI is not set
# CONFIG_SCSI_SATA_SVW is not set
+# CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_NV is not set
# CONFIG_SCSI_SATA_PROMISE is not set
# CONFIG_SCSI_SATA_SX4 is not set
# CONFIG_SCSI_SATA_SIL is not set
# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
# CONFIG_SCSI_SATA_VIA is not set
# CONFIG_SCSI_SATA_VITESSE is not set
# CONFIG_SCSI_BUSLOGIC is not set
diff -urN linux/arch/mips/defconfig-bosporus linux/arch/mips/defconfig-bosporus
--- linux/arch/mips/Attic/defconfig-bosporus 2005/01/09 19:33:59 1.1.2.40
+++ linux/arch/mips/Attic/defconfig-bosporus 2005/01/20 02:19:22 1.1.2.41
@@ -341,7 +341,6 @@
CONFIG_IP_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_NAT_LOCAL=y
CONFIG_IP_NF_NAT_SNMP_BASIC=m
CONFIG_IP_NF_MANGLE=m
# CONFIG_IP_NF_TARGET_TOS is not set
diff -urN linux/arch/mips/defconfig-mtx-1 linux/arch/mips/defconfig-mtx-1
--- linux/arch/mips/Attic/defconfig-mtx-1 2005/01/09 19:33:59 1.1.2.31
+++ linux/arch/mips/Attic/defconfig-mtx-1 2005/01/20 02:19:22 1.1.2.32
@@ -335,7 +335,6 @@
CONFIG_IP_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
diff -urN linux/arch/mips64/defconfig linux/arch/mips64/defconfig
--- linux/arch/mips64/Attic/defconfig 2004/11/29 17:47:15 1.73.2.76
+++ linux/arch/mips64/Attic/defconfig 2005/01/20 02:19:22 1.73.2.77
@@ -265,7 +265,6 @@
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_NAT_LOCAL=y
# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
diff -urN linux/arch/mips64/defconfig-ip27 linux/arch/mips64/defconfig-ip27
--- linux/arch/mips64/Attic/defconfig-ip27 2004/11/29 17:47:15
1.67.2.77
+++ linux/arch/mips64/Attic/defconfig-ip27 2005/01/20 02:19:22
1.67.2.78
@@ -265,7 +265,6 @@
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_NAT_LOCAL=y
# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
diff -urN linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- linux/arch/ppc/Attic/defconfig 2004/11/19 00:28:33 1.37.2.8
+++ linux/arch/ppc/Attic/defconfig 2005/01/20 02:19:22 1.37.2.9
@@ -180,7 +180,6 @@
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
CONFIG_IP_NF_NAT_SNMP_BASIC=m
CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
diff -urN linux/arch/ppc/configs/apus_defconfig
linux/arch/ppc/configs/apus_defconfig
--- linux/arch/ppc/configs/apus_defconfig 2004/02/20 01:22:13 1.9.2.8
+++ linux/arch/ppc/configs/apus_defconfig 2005/01/20 02:19:23 1.9.2.9
@@ -199,7 +199,6 @@
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
CONFIG_IP_NF_NAT_SNMP_BASIC=m
CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
diff -urN linux/arch/ppc/configs/briq_defconfig
linux/arch/ppc/configs/briq_defconfig
--- linux/arch/ppc/configs/Attic/briq_defconfig 2004/02/20 01:22:13 1.1.2.5
+++ linux/arch/ppc/configs/Attic/briq_defconfig 2005/01/20 02:19:23 1.1.2.6
@@ -175,7 +175,6 @@
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
CONFIG_IP_NF_NAT_SNMP_BASIC=m
CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
diff -urN linux/arch/ppc/configs/common_defconfig
linux/arch/ppc/configs/common_defconfig
--- linux/arch/ppc/configs/common_defconfig 2004/02/20 01:22:13 1.20.2.8
+++ linux/arch/ppc/configs/common_defconfig 2005/01/20 02:19:23 1.20.2.9
@@ -180,7 +180,6 @@
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
CONFIG_IP_NF_NAT_SNMP_BASIC=m
CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
diff -urN linux/arch/ppc/configs/ibmchrp_defconfig
linux/arch/ppc/configs/ibmchrp_defconfig
--- linux/arch/ppc/configs/ibmchrp_defconfig 2004/02/20 01:22:13 1.6.2.8
+++ linux/arch/ppc/configs/ibmchrp_defconfig 2005/01/20 02:19:23 1.6.2.9
@@ -173,7 +173,6 @@
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
CONFIG_IP_NF_NAT_SNMP_BASIC=m
CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
diff -urN linux/arch/ppc/configs/pal4_defconfig
linux/arch/ppc/configs/pal4_defconfig
--- linux/arch/ppc/configs/Attic/pal4_defconfig 2004/02/20 01:22:13 1.1.2.6
+++ linux/arch/ppc/configs/Attic/pal4_defconfig 2005/01/20 02:19:23 1.1.2.7
@@ -172,7 +172,6 @@
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
CONFIG_IP_NF_NAT_SNMP_BASIC=m
CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
diff -urN linux/arch/ppc/configs/pmac_defconfig
linux/arch/ppc/configs/pmac_defconfig
--- linux/arch/ppc/configs/pmac_defconfig 2004/02/20 01:22:13 1.3.2.8
+++ linux/arch/ppc/configs/pmac_defconfig 2005/01/20 02:19:23 1.3.2.9
@@ -183,7 +183,6 @@
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
CONFIG_IP_NF_NAT_SNMP_BASIC=m
CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
diff -urN linux/arch/ppc/configs/pplus_defconfig
linux/arch/ppc/configs/pplus_defconfig
--- linux/arch/ppc/configs/pplus_defconfig 2004/02/20 01:22:13 1.11.2.3
+++ linux/arch/ppc/configs/pplus_defconfig 2005/01/20 02:19:23 1.11.2.4
@@ -175,7 +175,6 @@
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
CONFIG_IP_NF_NAT_SNMP_BASIC=m
CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
diff -urN linux/arch/ppc/configs/prpmc750_defconfig
linux/arch/ppc/configs/prpmc750_defconfig
--- linux/arch/ppc/configs/prpmc750_defconfig 2004/02/20 01:22:13 1.7.2.2
+++ linux/arch/ppc/configs/prpmc750_defconfig 2005/01/20 02:19:23 1.7.2.3
@@ -183,7 +183,6 @@
CONFIG_IP_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
CONFIG_IP_NF_NAT_FTP=m
# CONFIG_IP_NF_MANGLE is not set
diff -urN linux/arch/s390/defconfig linux/arch/s390/defconfig
--- linux/arch/s390/defconfig 2004/11/19 00:28:34 1.7.2.7
+++ linux/arch/s390/defconfig 2005/01/20 02:19:23 1.7.2.8
@@ -199,7 +199,6 @@
CONFIG_IP_NF_NAT_NEEDED=y
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_NAT_LOCAL=y
# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
diff -urN linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- linux/arch/sparc64/defconfig 2004/12/27 04:13:40 1.60.2.16
+++ linux/arch/sparc64/defconfig 2005/01/20 02:19:23 1.60.2.17
@@ -253,7 +253,6 @@
CONFIG_IP_NF_TARGET_MASQUERADE=m
CONFIG_IP_NF_TARGET_REDIRECT=m
CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_NAT_LOCAL is not set
CONFIG_IP_NF_NAT_SNMP_BASIC=m
CONFIG_IP_NF_NAT_IRC=m
CONFIG_IP_NF_NAT_FTP=m
diff -urN linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- linux/drivers/char/tty_io.c 2005/01/13 10:59:03 1.62.2.17
+++ linux/drivers/char/tty_io.c 2005/01/20 02:19:23 1.62.2.18
@@ -718,7 +718,12 @@
wake_up_interruptible(&tty->write_wait);
}
-EXPORT_SYMBOL_GPL(tty_wakeup);
+/*
+ * tty_wakeup/tty_ldisc_flush are actually _GPL exports but we can't do
+ * that in 2.4 for modutils compat reasons.
+ */
+EXPORT_SYMBOL(tty_wakeup);
+
void tty_ldisc_flush(struct tty_struct *tty)
{
@@ -730,7 +735,12 @@
}
}
-EXPORT_SYMBOL_GPL(tty_ldisc_flush);
+
+/*
+ * tty_wakeup/tty_ldisc_flush are actually _GPL exports but we can't do
+ * that in 2.4 for modutils compat reasons.
+ */
+EXPORT_SYMBOL(tty_ldisc_flush);
void do_tty_hangup(void *data)
{
diff -urN linux/drivers/net/tg3.c linux/drivers/net/tg3.c
--- linux/drivers/net/tg3.c 2004/11/19 00:28:39 1.1.2.17
+++ linux/drivers/net/tg3.c 2005/01/20 02:19:23 1.1.2.18
@@ -59,8 +59,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.14"
-#define DRV_MODULE_RELDATE "November 15, 2004"
+#define DRV_MODULE_VERSION "3.15"
+#define DRV_MODULE_RELDATE "January 6, 2005"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -477,7 +477,8 @@
static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
{
u32 frame_val;
- int loops, ret;
+ unsigned int loops;
+ int ret;
if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
tw32_f(MAC_MI_MODE,
@@ -485,7 +486,7 @@
udelay(80);
}
- *val = 0xffffffff;
+ *val = 0x0;
frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
MI_COM_PHY_ADDR_MASK);
@@ -496,7 +497,7 @@
tw32_f(MAC_MI_COM, frame_val);
loops = PHY_BUSY_LOOPS;
- while (loops-- > 0) {
+ while (loops != 0) {
udelay(10);
frame_val = tr32(MAC_MI_COM);
@@ -505,10 +506,11 @@
frame_val = tr32(MAC_MI_COM);
break;
}
+ loops -= 1;
}
ret = -EBUSY;
- if (loops > 0) {
+ if (loops != 0) {
*val = frame_val & MI_COM_DATA_MASK;
ret = 0;
}
@@ -524,7 +526,8 @@
static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
{
u32 frame_val;
- int loops, ret;
+ unsigned int loops;
+ int ret;
if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
tw32_f(MAC_MI_MODE,
@@ -542,7 +545,7 @@
tw32_f(MAC_MI_COM, frame_val);
loops = PHY_BUSY_LOOPS;
- while (loops-- > 0) {
+ while (loops != 0) {
udelay(10);
frame_val = tr32(MAC_MI_COM);
if ((frame_val & MI_COM_BUSY) == 0) {
@@ -550,10 +553,11 @@
frame_val = tr32(MAC_MI_COM);
break;
}
+ loops -= 1;
}
ret = -EBUSY;
- if (loops > 0)
+ if (loops != 0)
ret = 0;
if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
diff -urN linux/include/linux/if_arp.h linux/include/linux/if_arp.h
--- linux/include/linux/if_arp.h 2004/08/14 18:39:03 1.17.2.2
+++ linux/include/linux/if_arp.h 2005/01/20 02:19:24 1.17.2.3
@@ -40,6 +40,7 @@
#define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id)
*/
#define ARPHRD_IEEE1394 24 /* IEEE 1394 IPv4 - RFC 2734
*/
#define ARPHRD_EUI64 27 /* EUI-64 */
+#define ARPHRD_INFINIBAND 32 /* InfiniBand
*/
/* Dummy types for non ARP hardware */
#define ARPHRD_SLIP 256
diff -urN linux/include/linux/if_ether.h linux/include/linux/if_ether.h
--- linux/include/linux/if_ether.h 2003/08/13 17:19:29 1.10.2.3
+++ linux/include/linux/if_ether.h 2005/01/20 02:19:24 1.10.2.4
@@ -61,6 +61,8 @@
#define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */
#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */
#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */
+#define ETH_P_MPLS_UC 0x8847 /* MPLS Unicast traffic */
+#define ETH_P_MPLS_MC 0x8848 /* MPLS Multicast traffic */
#define ETH_P_ATMMPOA 0x884c /* MultiProtocol Over ATM */
#define ETH_P_ATMFATE 0x8884 /* Frame-based ATM Transport
* over Ethernet
diff -urN linux/include/linux/netfilter.h linux/include/linux/netfilter.h
--- linux/include/linux/netfilter.h 2004/08/14 18:39:03 1.7.2.2
+++ linux/include/linux/netfilter.h 2005/01/20 02:19:24 1.7.2.3
@@ -153,6 +153,7 @@
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 nf_ct_info *);
+extern void nf_ct_attach(struct sk_buff *, struct sk_buff *);
#ifdef CONFIG_NETFILTER_DEBUG
extern void nf_dump_skb(int pf, struct sk_buff *skb);
@@ -163,6 +164,7 @@
#else /* !CONFIG_NETFILTER */
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
+static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
#endif /*CONFIG_NETFILTER*/
/* From arch/i386/kernel/smp.c:
diff -urN linux/include/linux/sctp.h linux/include/linux/sctp.h
--- linux/include/linux/sctp.h 2004/11/19 00:28:51 1.6.2.4
+++ linux/include/linux/sctp.h 2005/01/20 02:19:24 1.6.2.5
@@ -364,7 +364,7 @@
*/
typedef struct sctp_abort_chunk {
sctp_chunkhdr_t uh;
-} __attribute__((packed)) sctp_abort_chunkt_t;
+} __attribute__((packed)) sctp_abort_chunk_t;
/* For the graceful shutdown we must carry the tag (in common header)
diff -urN linux/include/linux/netfilter_ipv4/ip_conntrack_core.h
linux/include/linux/netfilter_ipv4/ip_conntrack_core.h
--- linux/include/linux/netfilter_ipv4/ip_conntrack_core.h 2003/08/13
17:19:29 1.4.2.3
+++ linux/include/linux/netfilter_ipv4/ip_conntrack_core.h 2005/01/20
02:19:24 1.4.2.4
@@ -25,9 +25,9 @@
extern struct ip_conntrack *icmp_error_track(struct sk_buff *skb,
enum ip_conntrack_info *ctinfo,
unsigned int hooknum);
-extern int get_tuple(const struct iphdr *iph, size_t len,
- struct ip_conntrack_tuple *tuple,
- struct ip_conntrack_protocol *protocol);
+extern int ip_ct_get_tuple(const struct iphdr *iph, size_t len,
+ struct ip_conntrack_tuple *tuple,
+ struct ip_conntrack_protocol *protocol);
/* Find a connection corresponding to a tuple. */
struct ip_conntrack_tuple_hash *
diff -urN linux/include/linux/netfilter_ipv4/ip_nat.h
linux/include/linux/netfilter_ipv4/ip_nat.h
--- linux/include/linux/netfilter_ipv4/ip_nat.h 2004/04/16 03:14:21 1.2.2.3
+++ linux/include/linux/netfilter_ipv4/ip_nat.h 2005/01/20 02:19:24 1.2.2.4
@@ -11,13 +11,8 @@
IP_NAT_MANIP_DST
};
-#ifndef CONFIG_IP_NF_NAT_LOCAL
-/* SRC manip occurs only on POST_ROUTING */
-#define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING)
-#else
/* SRC manip occurs POST_ROUTING or LOCAL_IN */
#define HOOK2MANIP(hooknum) ((hooknum) != NF_IP_POST_ROUTING && (hooknum) !=
NF_IP_LOCAL_IN)
-#endif
/* 2.3.19 (I hope) will define this in linux/netfilter_ipv4.h. */
#ifndef SO_ORIGINAL_DST
diff -urN linux/include/net/inet_ecn.h linux/include/net/inet_ecn.h
--- linux/include/net/inet_ecn.h 2001/11/06 07:56:15 1.2
+++ linux/include/net/inet_ecn.h 2005/01/20 02:19:24 1.2.2.1
@@ -1,6 +1,14 @@
#ifndef _INET_ECN_H_
#define _INET_ECN_H_
+enum {
+ INET_ECN_NOT_ECT = 0,
+ INET_ECN_ECT_1 = 1,
+ INET_ECN_ECT_0 = 2,
+ INET_ECN_CE = 3,
+ INET_ECN_MASK = 3,
+};
+
static inline int INET_ECN_is_ce(__u8 dsfield)
{
return (dsfield&3) == 3;
diff -urN linux/include/net/ip.h linux/include/net/ip.h
--- linux/include/net/ip.h 2004/11/19 00:28:51 1.20.2.3
+++ linux/include/net/ip.h 2005/01/20 02:19:24 1.20.2.4
@@ -102,7 +102,8 @@
int getfrag (const void *,
char *,
unsigned int,
- unsigned int),
+ unsigned int,
+ struct sk_buff *),
const void *frag,
unsigned length,
struct ipcm_cookie *ipc,
diff -urN linux/include/net/ip_vs.h linux/include/net/ip_vs.h
--- linux/include/net/ip_vs.h 2004/12/27 04:13:54 1.3.2.4
+++ linux/include/net/ip_vs.h 2005/01/20 02:19:24 1.3.2.5
@@ -97,6 +97,7 @@
int state; /* sync daemon state */
char mcast_ifn[IP_VS_IFNAME_MAXLEN];
/* multicast interface name */
+ int syncid;
/* virtual service options */
u_int16_t protocol;
@@ -213,8 +214,9 @@
/* The argument to IP_VS_SO_GET_DAEMON */
struct ip_vs_daemon_user {
- int state; /* sync daemon state */
- char mcast_ifn[IP_VS_IFNAME_MAXLEN]; /* multicast interface name */
+ int state; /* sync daemon state */
+ char mcast_master_ifn[IP_VS_IFNAME_MAXLEN]; /* mcast master
interface name */
+ char mcast_backup_ifn[IP_VS_IFNAME_MAXLEN]; /* mcast backup
interface name */
};
@@ -726,9 +728,10 @@
* (from ip_vs_sync.c)
*/
extern volatile int ip_vs_sync_state;
-extern char ip_vs_mcast_ifn[IP_VS_IFNAME_MAXLEN];
-extern int start_sync_thread(int state, char *mcast_ifn);
-extern int stop_sync_thread(void);
+extern char ip_vs_mcast_master_ifn[IP_VS_IFNAME_MAXLEN];
+extern char ip_vs_mcast_backup_ifn[IP_VS_IFNAME_MAXLEN];
+extern int start_sync_thread(int state, char *mcast_ifn, __u8 syncid);
+extern int stop_sync_thread(int state);
extern void ip_vs_sync_conn(struct ip_vs_conn *cp);
diff -urN linux/include/net/sctp/command.h linux/include/net/sctp/command.h
--- linux/include/net/sctp/command.h 2004/11/19 00:28:51 1.8.2.4
+++ linux/include/net/sctp/command.h 2005/01/20 02:19:24 1.8.2.5
@@ -189,11 +189,6 @@
} sctp_cmd_seq_t;
-/* Create a new sctp_command_sequence.
- * Return NULL if creating a new sequence fails.
- */
-sctp_cmd_seq_t *sctp_new_cmd_seq(int gfp);
-
/* Initialize a block of memory as a command sequence.
* Return 0 if the initialization fails.
*/
@@ -207,18 +202,10 @@
*/
int sctp_add_cmd(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj);
-/* Rewind an sctp_cmd_seq_t to iterate from the start.
- * Return 0 if the rewind fails.
- */
-int sctp_rewind_sequence(sctp_cmd_seq_t *seq);
-
/* Return the next command structure in an sctp_cmd_seq.
* Return NULL at the end of the sequence.
*/
sctp_cmd_t *sctp_next_cmd(sctp_cmd_seq_t *seq);
-/* Dispose of a command sequence. */
-void sctp_free_cmd_seq(sctp_cmd_seq_t *seq);
-
#endif /* __net_sctp_command_h__ */
diff -urN linux/include/net/sctp/compat.h linux/include/net/sctp/compat.h
--- linux/include/net/sctp/Attic/compat.h 2004/11/19 00:28:51 1.1.2.3
+++ linux/include/net/sctp/Attic/compat.h 2005/01/20 02:19:24 1.1.2.4
@@ -64,37 +64,6 @@
#define __unsafe(x)
#define dst_pmtu(x) ((x)->pmtu)
-#define sk_family family
-#define sk_state state
-#define sk_type type
-#define sk_socket socket
-#define sk_prot prot
-#define sk_rcvbuf rcvbuf
-#define sk_sndbuf sndbuf
-#define sk_ack_backlog ack_backlog
-#define sk_max_ack_backlog max_ack_backlog
-#define sk_write_space write_space
-#define sk_use_write_queue use_write_queue
-#define sk_err err
-#define sk_err_soft err_soft
-#define sk_error_report error_report
-#define sk_error_queue error_queue
-#define sk_shutdown shutdown
-#define sk_state_change state_change
-#define sk_receive_queue receive_queue
-#define sk_data_ready data_ready
-#define sk_no_check no_check
-#define sk_reuse reuse
-#define sk_destruct destruct
-#define sk_zapped zapped
-#define sk_protocol protocol
-#define sk_backlog_rcv backlog_rcv
-#define sk_allocation allocation
-#define sk_lingertime lingertime
-#define sk_sleep sleep
-#define sk_wmem_queued wmem_queued
-#define sk_bound_dev_if bound_dev_if
-
/*
* find last bit set.
*/
diff -urN linux/include/net/sctp/constants.h linux/include/net/sctp/constants.h
--- linux/include/net/sctp/constants.h 2004/11/19 00:28:51 1.8.2.4
+++ linux/include/net/sctp/constants.h 2005/01/20 02:19:24 1.8.2.5
@@ -105,9 +105,10 @@
typedef enum {
SCTP_EVENT_NO_PENDING_TSN = 0,
+ SCTP_EVENT_ICMP_PROTO_UNREACH,
} sctp_event_other_t;
-#define SCTP_EVENT_OTHER_MAX SCTP_EVENT_NO_PENDING_TSN
+#define SCTP_EVENT_OTHER_MAX SCTP_EVENT_ICMP_PROTO_UNREACH
#define SCTP_NUM_OTHER_TYPES (SCTP_EVENT_OTHER_MAX + 1)
/* These are primitive requests from the ULP. */
@@ -155,10 +156,6 @@
- (unsigned long)(c->chunk_hdr)\
- sizeof(sctp_data_chunk_t)))
-/* This is a table of printable names of sctp_param_t's. */
-extern const char *sctp_param_tbl[];
-
-
#define SCTP_MAX_ERROR_CAUSE SCTP_ERROR_NONEXIST_IP
#define SCTP_NUM_ERROR_CAUSE 10
@@ -179,6 +176,7 @@
SCTP_IERROR_IGNORE_TSN,
SCTP_IERROR_NO_DATA,
SCTP_IERROR_BAD_STREAM,
+ SCTP_IERROR_BAD_PORTS,
} sctp_ierror_t;
diff -urN linux/include/net/sctp/sctp.h linux/include/net/sctp/sctp.h
--- linux/include/net/sctp/sctp.h 2004/08/14 18:39:03 1.18.2.4
+++ linux/include/net/sctp/sctp.h 2005/01/20 02:19:24 1.18.2.5
@@ -166,17 +166,9 @@
int sctp_rcv(struct sk_buff *skb);
void sctp_v4_err(struct sk_buff *skb, u32 info);
void sctp_hash_established(struct sctp_association *);
-void __sctp_hash_established(struct sctp_association *);
void sctp_unhash_established(struct sctp_association *);
-void __sctp_unhash_established(struct sctp_association *);
void sctp_hash_endpoint(struct sctp_endpoint *);
-void __sctp_hash_endpoint(struct sctp_endpoint *);
void sctp_unhash_endpoint(struct sctp_endpoint *);
-void __sctp_unhash_endpoint(struct sctp_endpoint *);
-struct sctp_association *__sctp_lookup_association(
- const union sctp_addr *,
- const union sctp_addr *,
- struct sctp_transport **);
struct sock *sctp_err_lookup(int family, struct sk_buff *,
struct sctphdr *, struct sctp_endpoint **,
struct sctp_association **,
@@ -185,6 +177,10 @@
struct sctp_association *);
void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
struct sctp_transport *t, __u32 pmtu);
+void sctp_icmp_proto_unreachable(struct sock *sk,
+ struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ struct sctp_transport *t);
/*
* Section: Macros, externs, and inlines
@@ -332,8 +328,6 @@
int sctp_v6_init(void);
void sctp_v6_exit(void);
-void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info);
#else /* #ifdef defined(CONFIG_IPV6) */
@@ -477,7 +471,8 @@
#define _sctp_walk_params(pos, chunk, end, member)\
for (pos.v = chunk->member;\
pos.v <= (void *)chunk + end - sizeof(sctp_paramhdr_t) &&\
- pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)); \
+ pos.v <= (void *)chunk + end - WORD_ROUND(ntohs(pos.p->length)) &&\
+ ntohs(pos.p->length) >= sizeof(sctp_paramhdr_t);\
pos.v += WORD_ROUND(ntohs(pos.p->length)))
#define sctp_walk_errors(err, chunk_hdr)\
@@ -487,10 +482,9 @@
for (err = (sctp_errhdr_t *)((void *)chunk_hdr + \
sizeof(sctp_chunkhdr_t));\
(void *)err <= (void *)chunk_hdr + end - sizeof(sctp_errhdr_t) &&\
- (void *)err <= (void *)chunk_hdr + end - \
- WORD_ROUND(ntohs(err->length));\
- err = (sctp_errhdr_t *)((void *)err + \
- WORD_ROUND(ntohs(err->length))))
+ (void *)err <= (void *)chunk_hdr + end - WORD_ROUND(ntohs(err->length))
&&\
+ ntohs(err->length) >= sizeof(sctp_errhdr_t); \
+ err = (sctp_errhdr_t *)((void *)err + WORD_ROUND(ntohs(err->length))))
#define sctp_walk_fwdtsn(pos, chunk)\
_sctp_walk_fwdtsn((pos), (chunk), ntohs((chunk)->chunk_hdr->length) -
sizeof(struct sctp_fwdtsn_chunk))
@@ -622,7 +616,7 @@
#define sctp_sstate(sk, state) __sctp_sstate((sk), (SCTP_SS_##state))
int static inline __sctp_sstate(const struct sock *sk, sctp_sock_state_t state)
{
- return sk->sk_state == state;
+ return sk->state == state;
}
/* Map v4-mapped v6 address back to v4 address */
diff -urN linux/include/net/sctp/sm.h linux/include/net/sctp/sm.h
--- linux/include/net/sctp/sm.h 2004/11/19 00:28:51 1.16.2.4
+++ linux/include/net/sctp/sm.h 2005/01/20 02:19:24 1.16.2.5
@@ -128,9 +128,9 @@
sctp_state_fn_t sctp_sf_do_ecn_cwr;
sctp_state_fn_t sctp_sf_do_ecne;
sctp_state_fn_t sctp_sf_ootb;
-sctp_state_fn_t sctp_sf_shut_8_4_5;
sctp_state_fn_t sctp_sf_pdiscard;
sctp_state_fn_t sctp_sf_violation;
+sctp_state_fn_t sctp_sf_violation_chunklen;
sctp_state_fn_t sctp_sf_discard_chunk;
sctp_state_fn_t sctp_sf_do_5_2_1_siminit;
sctp_state_fn_t sctp_sf_do_5_2_2_dupinit;
@@ -138,7 +138,6 @@
sctp_state_fn_t sctp_sf_unk_chunk;
sctp_state_fn_t sctp_sf_do_8_5_1_E_sa;
sctp_state_fn_t sctp_sf_cookie_echoed_err;
-sctp_state_fn_t sctp_sf_do_5_2_6_stale;
sctp_state_fn_t sctp_sf_do_asconf;
sctp_state_fn_t sctp_sf_do_asconf_ack;
sctp_state_fn_t sctp_sf_do_9_2_reshutack;
@@ -167,6 +166,7 @@
sctp_state_fn_t sctp_sf_do_9_2_start_shutdown;
sctp_state_fn_t sctp_sf_do_9_2_shutdown_ack;
sctp_state_fn_t sctp_sf_ignore_other;
+sctp_state_fn_t sctp_sf_cookie_wait_icmp_abort;
/* Prototypes for timeout event state functions. */
sctp_state_fn_t sctp_sf_do_6_3_3_rtx;
@@ -200,19 +200,10 @@
struct sctp_chunk *sctp_make_cwr(const struct sctp_association *,
const __u32 lowest_tsn,
const struct sctp_chunk *);
-struct sctp_chunk *sctp_make_datafrag(struct sctp_association *,
- const struct sctp_sndrcvinfo *sinfo,
- int len, const __u8 *data,
- __u8 flags, __u16 ssn);
struct sctp_chunk * sctp_make_datafrag_empty(struct sctp_association *,
const struct sctp_sndrcvinfo *sinfo,
int len, const __u8 flags,
__u16 ssn);
-struct sctp_chunk *sctp_make_data(struct sctp_association *,
- const struct sctp_sndrcvinfo *sinfo,
- int len, const __u8 *data);
-struct sctp_chunk *sctp_make_data_empty(struct sctp_association *,
- const struct sctp_sndrcvinfo *, int len);
struct sctp_chunk *sctp_make_ecne(const struct sctp_association *,
const __u32);
struct sctp_chunk *sctp_make_sack(const struct sctp_association *);
@@ -232,6 +223,10 @@
struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *,
const struct sctp_chunk *,
const struct msghdr *);
+struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *,
+ const struct sctp_chunk *,
+ const __u8 *,
+ const size_t );
struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,
const struct sctp_transport *,
const void *payload,
@@ -246,17 +241,12 @@
const void *payload,
size_t paylen);
-struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
- union sctp_addr *addr,
- int vparam_len);
struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
union sctp_addr *,
struct sockaddr *,
int, __u16);
struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
union sctp_addr *addr);
-struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *asoc,
- __u32 serial, int vparam_len);
struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
struct sctp_chunk *asconf);
int sctp_process_asconf_ack(struct sctp_association *asoc,
@@ -268,6 +258,8 @@
void sctp_chunk_assign_tsn(struct sctp_chunk *);
void sctp_chunk_assign_ssn(struct sctp_chunk *);
+void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error);
+
/* Prototypes for statetable processing. */
int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
@@ -277,71 +269,26 @@
void *event_arg,
int gfp);
-int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
- sctp_state_t state,
- struct sctp_endpoint *,
- struct sctp_association *asoc,
- void *event_arg,
- sctp_disposition_t status,
- sctp_cmd_seq_t *commands,
- int gfp);
-
/* 2nd level prototypes */
-int sctp_cmd_interpreter(sctp_event_t, sctp_subtype_t, sctp_state_t,
- struct sctp_endpoint *, struct sctp_association *,
- void *event_arg, sctp_disposition_t,
- sctp_cmd_seq_t *retval, int gfp);
-
-
-int sctp_gen_sack(struct sctp_association *, int force, sctp_cmd_seq_t *);
void sctp_generate_t3_rtx_event(unsigned long peer);
void sctp_generate_heartbeat_event(unsigned long peer);
-sctp_sackhdr_t *sctp_sm_pull_sack(struct sctp_chunk *);
-struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *,
- const struct sctp_association *,
- struct sctp_chunk *chunk,
- const void *payload,
- size_t paylen);
-struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *,
- const struct sctp_chunk *);
void sctp_ootb_pkt_free(struct sctp_packet *);
-struct sctp_cookie_param *
-sctp_pack_cookie(const struct sctp_endpoint *, const struct sctp_association *,
- const struct sctp_chunk *, int *cookie_len,
- const __u8 *, int addrs_len);
struct sctp_association *sctp_unpack_cookie(const struct sctp_endpoint *,
const struct sctp_association *,
struct sctp_chunk *, int gfp, int *err,
struct sctp_chunk **err_chk_p);
int sctp_addip_addr_config(struct sctp_association *, sctp_param_t,
struct sockaddr_storage*, int);
-void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
- const struct sctp_association *asoc,
- const struct sctp_chunk *chunk,
- sctp_cmd_seq_t *commands,
- struct sctp_chunk *err_chunk);
-int sctp_eat_data(const struct sctp_association *asoc,
- struct sctp_chunk *chunk,
- sctp_cmd_seq_t *commands);
/* 3rd level prototypes */
__u32 sctp_generate_tag(const struct sctp_endpoint *);
__u32 sctp_generate_tsn(const struct sctp_endpoint *);
/* Extern declarations for major data structures. */
-const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t, sctp_state_t);
-extern const sctp_sm_table_entry_t
-primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES];
-extern const sctp_sm_table_entry_t
-other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES];
-extern const sctp_sm_table_entry_t
-timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES];
extern sctp_timer_event_t *sctp_timer_events[SCTP_NUM_TIMEOUT_TYPES];
-/* These are some handy utility macros... */
-
/* Get the size of a DATA chunk payload. */
static inline __u16 sctp_data_size(struct sctp_chunk *chunk)
diff -urN linux/include/net/sctp/structs.h linux/include/net/sctp/structs.h
--- linux/include/net/sctp/structs.h 2004/11/19 00:28:52 1.22.2.4
+++ linux/include/net/sctp/structs.h 2005/01/20 02:19:24 1.22.2.5
@@ -322,10 +322,19 @@
/* This holds the originating address of the INIT packet. */
union sctp_addr peer_addr;
+ /* IG Section 2.35.3
+ * Include the source port of the INIT-ACK
+ */
+ __u16 my_port;
+
__u8 prsctp_capable;
+ /* Padding for future use */
+ __u8 padding;
+
__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
@@ -406,7 +415,6 @@
int malloced;
};
-struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *, __u16, __u16);
struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, int gfp);
void sctp_ssnmap_free(struct sctp_ssnmap *map);
void sctp_ssnmap_clear(struct sctp_ssnmap *map);
@@ -538,12 +546,9 @@
struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *,
struct sctp_sndrcvinfo *,
struct msghdr *, int len);
-struct sctp_datamsg *sctp_datamsg_new(int gfp);
void sctp_datamsg_put(struct sctp_datamsg *);
-void sctp_datamsg_hold(struct sctp_datamsg *);
void sctp_datamsg_free(struct sctp_datamsg *);
void sctp_datamsg_track(struct sctp_chunk *);
-void sctp_datamsg_assign(struct sctp_datamsg *, struct sctp_chunk *);
void sctp_chunk_fail(struct sctp_chunk *, int error);
int sctp_chunk_abandoned(struct sctp_chunk *);
@@ -651,8 +656,6 @@
void sctp_chunk_put(struct sctp_chunk *);
int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len,
struct iovec *data);
-struct sctp_chunk *sctp_make_chunk(const struct sctp_association *, __u8 type,
- __u8 flags, int size);
void sctp_chunk_free(struct sctp_chunk *);
void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data);
struct sctp_chunk *sctp_chunkify(struct sk_buff *,
@@ -853,12 +856,6 @@
/* Error count : The current error count for this destination. */
unsigned short error_count;
- /* Error : Current error threshold for this destination
- * Threshold : i.e. what value marks the destination down if
- * : errorCount reaches this value.
- */
- unsigned short error_threshold;
-
/* This is the max_retrans value for the transport and will
* be initialized to proto.max_retrans.path. This can be changed
* using SCTP_SET_PEER_ADDR_PARAMS socket option.
@@ -922,15 +919,12 @@
};
struct sctp_transport *sctp_transport_new(const union sctp_addr *, int);
-struct sctp_transport *sctp_transport_init(struct sctp_transport *,
- const union sctp_addr *, int);
void sctp_transport_set_owner(struct sctp_transport *,
struct sctp_association *);
void sctp_transport_route(struct sctp_transport *, union sctp_addr *,
struct sctp_opt *);
void sctp_transport_pmtu(struct sctp_transport *);
void sctp_transport_free(struct sctp_transport *);
-void sctp_transport_destroy(struct sctp_transport *);
void sctp_transport_reset_timers(struct sctp_transport *);
void sctp_transport_hold(struct sctp_transport *);
void sctp_transport_put(struct sctp_transport *);
@@ -961,7 +955,6 @@
int malloced; /* Is this structure kfree()able? */
};
-struct sctp_inq *sctp_inq_new(void);
void sctp_inq_init(struct sctp_inq *);
void sctp_inq_free(struct sctp_inq *);
void sctp_inq_push(struct sctp_inq *, struct sctp_chunk *packet);
@@ -1029,7 +1022,6 @@
char malloced;
};
-struct sctp_outq *sctp_outq_new(struct sctp_association *);
void sctp_outq_init(struct sctp_association *, struct sctp_outq *);
void sctp_outq_teardown(struct sctp_outq *);
void sctp_outq_free(struct sctp_outq*);
@@ -1070,7 +1062,6 @@
int malloced; /* Are we kfree()able? */
};
-struct sctp_bind_addr *sctp_bind_addr_new(int gfp_mask);
void sctp_bind_addr_init(struct sctp_bind_addr *, __u16 port);
void sctp_bind_addr_free(struct sctp_bind_addr *);
int sctp_bind_addr_copy(struct sctp_bind_addr *dest,
@@ -1220,8 +1211,6 @@
/* These are function signatures for manipulating endpoints. */
struct sctp_endpoint *sctp_endpoint_new(struct sock *, int);
-struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *,
- struct sock *, int gfp);
void sctp_endpoint_free(struct sctp_endpoint *);
void sctp_endpoint_put(struct sctp_endpoint *);
void sctp_endpoint_hold(struct sctp_endpoint *);
@@ -1243,8 +1232,6 @@
int sctp_process_init(struct sctp_association *, sctp_cid_t cid,
const union sctp_addr *peer,
sctp_init_chunk_t *init, int gfp);
-int sctp_process_param(struct sctp_association *, union sctp_params param,
- const union sctp_addr *from, int gfp);
__u32 sctp_generate_tag(const struct sctp_endpoint *);
__u32 sctp_generate_tsn(const struct sctp_endpoint *);
@@ -1693,10 +1680,6 @@
struct sctp_association *
sctp_association_new(const struct sctp_endpoint *, const struct sock *,
sctp_scope_t scope, int gfp);
-struct sctp_association *
-sctp_association_init(struct sctp_association *, const struct sctp_endpoint *,
- const struct sock *, sctp_scope_t scope,
- int gfp);
void sctp_association_free(struct sctp_association *);
void sctp_association_put(struct sctp_association *);
void sctp_association_hold(struct sctp_association *);
@@ -1725,7 +1708,6 @@
struct sctp_association *new);
__u32 sctp_association_get_next_tsn(struct sctp_association *);
-__u32 sctp_association_get_tsn_block(struct sctp_association *, int);
void sctp_assoc_sync_pmtu(struct sctp_association *);
void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned);
@@ -1739,7 +1721,6 @@
int sctp_cmp_addr_exact(const union sctp_addr *ss1,
const union sctp_addr *ss2);
struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc);
-struct sctp_chunk *sctp_get_no_prepend(struct sctp_association *asoc);
/* A convenience structure to parse out SCTP specific CMSGs. */
typedef struct sctp_cmsgs {
diff -urN linux/include/net/sctp/tsnmap.h linux/include/net/sctp/tsnmap.h
--- linux/include/net/sctp/tsnmap.h 2004/08/14 18:39:03 1.4.2.3
+++ linux/include/net/sctp/tsnmap.h 2005/01/20 02:19:24 1.4.2.4
@@ -120,12 +120,6 @@
__u32 start;
};
-/* Create a new tsnmap. */
-struct sctp_tsnmap *sctp_tsnmap_new(__u16 len, __u32 init_tsn, int gfp);
-
-/* Dispose of a tsnmap. */
-void sctp_tsnmap_free(struct sctp_tsnmap *);
-
/* This macro assists in creation of external storage for variable length
* internal buffers. We double allocate so the overflow map works.
*/
@@ -210,14 +204,4 @@
/* Is there a gap in the TSN map? */
int sctp_tsnmap_has_gap(const struct sctp_tsnmap *);
-/* Initialize a gap ack block interator from user-provided memory. */
-void sctp_tsnmap_iter_init(const struct sctp_tsnmap *,
- struct sctp_tsnmap_iter *);
-
-/* Get the next gap ack blocks. We return 0 if there are no more
- * gap ack blocks.
- */
-int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *,
- struct sctp_tsnmap_iter *,__u16 *start, __u16 *end);
-
#endif /* __sctp_tsnmap_h__ */
diff -urN linux/include/net/sctp/ulpevent.h linux/include/net/sctp/ulpevent.h
--- linux/include/net/sctp/ulpevent.h 2004/11/19 00:28:52 1.5.2.4
+++ linux/include/net/sctp/ulpevent.h 2005/01/20 02:19:24 1.5.2.5
@@ -77,8 +77,6 @@
return (struct sctp_ulpevent *)skb->cb;
}
-struct sctp_ulpevent *sctp_ulpevent_new(int size, int flags, int gfp);
-void sctp_ulpevent_init(struct sctp_ulpevent *, int flags);
void sctp_ulpevent_free(struct sctp_ulpevent *);
int sctp_ulpevent_is_notification(const struct sctp_ulpevent *);
void sctp_queue_purge_ulpevents(struct sk_buff_head *list);
diff -urN linux/include/net/sctp/ulpqueue.h linux/include/net/sctp/ulpqueue.h
--- linux/include/net/sctp/ulpqueue.h 2004/08/14 18:39:03 1.5.2.2
+++ linux/include/net/sctp/ulpqueue.h 2005/01/20 02:19:24 1.5.2.3
@@ -57,7 +57,6 @@
};
/* Prototypes. */
-struct sctp_ulpq *sctp_ulpq_new(struct sctp_association *asoc, int gfp);
struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *,
struct sctp_association *);
void sctp_ulpq_free(struct sctp_ulpq *);
diff -urN linux/init/do_mounts.c linux/init/do_mounts.c
--- linux/init/do_mounts.c 2004/12/27 04:13:54 1.1.2.9
+++ linux/init/do_mounts.c 2005/01/20 02:19:24 1.1.2.10
@@ -348,7 +348,6 @@
{
char *fs_names = __getname();
char *p;
- int tries = 10;
get_fs_names(fs_names);
retry:
@@ -368,18 +367,11 @@
* Allow the user to distinguish between failed open
* and bad superblock on root device.
*/
- if (--tries) {
- printk ("VFS: Cannot open root device \"%s\" or %s, "
- "retrying in 1s.\n",
- root_device_name, kdevname (ROOT_DEV));
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ);
- goto retry;
- }
printk ("VFS: Cannot open root device \"%s\" or %s\n",
root_device_name, kdevname (ROOT_DEV));
printk ("Please append a correct \"root=\" boot option\n");
- break;
+ panic("VFS: Unable to mount root fs on %s",
+ kdevname(ROOT_DEV));
}
panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV));
out:
diff -urN linux/net/netsyms.c linux/net/netsyms.c
--- linux/net/Attic/netsyms.c 2004/12/27 04:13:55 1.53.2.13
+++ linux/net/Attic/netsyms.c 2005/01/20 02:19:24 1.53.2.14
@@ -607,6 +607,7 @@
EXPORT_SYMBOL(nf_setsockopt);
EXPORT_SYMBOL(nf_getsockopt);
EXPORT_SYMBOL(ip_ct_attach);
+EXPORT_SYMBOL(nf_ct_attach);
#ifdef CONFIG_INET
#include <linux/netfilter_ipv4.h>
EXPORT_SYMBOL(ip_route_me_harder);
diff -urN linux/net/core/neighbour.c linux/net/core/neighbour.c
--- linux/net/core/neighbour.c 2004/11/19 00:28:53 1.18.2.6
+++ linux/net/core/neighbour.c 2005/01/20 02:19:25 1.18.2.7
@@ -427,11 +427,12 @@
n->confirmed = jiffies - (n->parms->base_reachable_time<<1);
- hash_val = tbl->hash(pkey, dev) & tbl->hash_mask;
-
write_lock_bh(&tbl->lock);
if (atomic_read(&tbl->entries) > (tbl->hash_mask + 1))
neigh_hash_grow(tbl, (tbl->hash_mask + 1) << 1);
+
+ hash_val = tbl->hash(pkey, dev) & tbl->hash_mask;
+
for (n1 = tbl->hash_buckets[hash_val]; n1; n1 = n1->next) {
if (dev == n1->dev &&
memcmp(n1->primary_key, pkey, key_len) == 0) {
diff -urN linux/net/core/netfilter.c linux/net/core/netfilter.c
--- linux/net/core/netfilter.c 2003/08/13 17:19:30 1.12.2.3
+++ linux/net/core/netfilter.c 2005/01/20 02:19:25 1.12.2.4
@@ -622,12 +622,21 @@
}
#endif /*CONFIG_INET*/
-/* This does not belong here, but ipt_REJECT needs it if connection
- tracking in use: without this, connection may not be in hash table,
- and hence manufactured ICMP or RST packets will not be associated
- with it. */
+/* This does not belong here, but locally generated errors need it if
connection
+ tracking in use: without this, connection may not be in hash table, and
hence
+ manufactured ICMP or RST packets will not be associated with it. */
void (*ip_ct_attach)(struct sk_buff *, struct nf_ct_info *);
+void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
+{
+ void (*attach)(struct sk_buff *, struct nf_ct_info *);
+
+ if (skb->nfct && (attach = ip_ct_attach) != NULL) {
+ mb(); /* Just to be sure: must be read before executing this */
+ attach(new, skb->nfct);
+ }
+}
+
void __init netfilter_init(void)
{
int i, h;
diff -urN linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- linux/net/ipv4/icmp.c 2004/04/16 03:14:22 1.30.2.7
+++ linux/net/ipv4/icmp.c 2005/01/20 02:19:25 1.30.2.8
@@ -281,12 +281,16 @@
* Checksum each fragment, and on the first include the headers and final
checksum.
*/
-static int icmp_glue_bits(const void *p, char *to, unsigned int offset,
unsigned int fraglen)
+static int icmp_glue_bits(const void *p, char *to, unsigned int offset,
+ unsigned int fraglen, struct sk_buff *skb)
{
struct icmp_bxm *icmp_param = (struct icmp_bxm *)p;
struct icmphdr *icmph;
unsigned int csum;
+ if (icmp_pointers[icmp_param->data.icmph.type].error)
+ nf_ct_attach(skb, icmp_param->skb);
+
if (offset) {
icmp_param->csum=skb_copy_and_csum_bits(icmp_param->skb,
icmp_param->offset+(offset-icmp_param->head_len),
diff -urN linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- linux/net/ipv4/ip_output.c 2004/11/19 00:28:53 1.33.2.6
+++ linux/net/ipv4/ip_output.c 2005/01/20 02:19:25 1.33.2.7
@@ -438,7 +438,8 @@
int getfrag (const void *,
char *,
unsigned int,
- unsigned int),
+ unsigned int,
+ struct sk_buff *),
const void *frag,
unsigned length,
struct ipcm_cookie *ipc,
@@ -607,7 +608,7 @@
* User data callback
*/
- if (getfrag(frag, data, offset, fraglen-fragheaderlen)) {
+ if (getfrag(frag, data, offset, fraglen-fragheaderlen, skb)) {
err = -EFAULT;
kfree_skb(skb);
goto error;
@@ -647,7 +648,8 @@
int getfrag (const void *,
char *,
unsigned int,
- unsigned int),
+ unsigned int,
+ struct sk_buff *),
const void *frag,
unsigned length,
struct ipcm_cookie *ipc,
@@ -721,10 +723,10 @@
iph->daddr=rt->rt_dst;
iph->check=0;
iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
- err = getfrag(frag, ((char *)iph)+iph->ihl*4,0,
length-iph->ihl*4);
+ err = getfrag(frag, ((char *)iph)+iph->ihl*4,0,
length-iph->ihl*4, skb);
}
else
- err = getfrag(frag, (void *)iph, 0, length);
+ err = getfrag(frag, (void *)iph, 0, length, skb);
if (err)
goto error_fault;
@@ -921,7 +923,7 @@
* Fetch data from kernel space and fill in checksum if needed.
*/
static int ip_reply_glue_bits(const void *dptr, char *to, unsigned int offset,
- unsigned int fraglen)
+ unsigned int fraglen, struct sk_buff *skb)
{
struct ip_reply_arg *dp = (struct ip_reply_arg*)dptr;
u16 *pktp = (u16 *)to;
diff -urN linux/net/ipv4/raw.c linux/net/ipv4/raw.c
--- linux/net/ipv4/raw.c 2004/08/14 18:39:04 1.27.2.3
+++ linux/net/ipv4/raw.c 2005/01/20 02:19:25 1.27.2.4
@@ -266,7 +266,7 @@
*/
static int raw_getfrag(const void *p, char *to, unsigned int offset,
- unsigned int fraglen)
+ unsigned int fraglen, struct sk_buff *skb)
{
struct rawfakehdr *rfh = (struct rawfakehdr *) p;
return memcpy_fromiovecend(to, rfh->iov, offset, fraglen);
@@ -277,7 +277,7 @@
*/
static int raw_getrawfrag(const void *p, char *to, unsigned int offset,
- unsigned int fraglen)
+ unsigned int fraglen, struct sk_buff *skb)
{
struct rawfakehdr *rfh = (struct rawfakehdr *) p;
diff -urN linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- linux/net/ipv4/udp.c 2004/12/27 04:13:56 1.35.2.8
+++ linux/net/ipv4/udp.c 2005/01/20 02:19:25 1.35.2.9
@@ -389,7 +389,8 @@
* Copy and checksum a UDP packet from user space into a buffer.
*/
-static int udp_getfrag(const void *p, char * to, unsigned int offset, unsigned
int fraglen)
+static int udp_getfrag(const void *p, char * to, unsigned int offset,
+ unsigned int fraglen, struct sk_buff *skb)
{
struct udpfakehdr *ufh = (struct udpfakehdr *)p;
if (offset==0) {
@@ -416,7 +417,8 @@
* Copy a UDP packet from user space into a buffer without checksumming.
*/
-static int udp_getfrag_nosum(const void *p, char * to, unsigned int offset,
unsigned int fraglen)
+static int udp_getfrag_nosum(const void *p, char * to, unsigned int offset,
+ unsigned int fraglen, struct sk_buff *skb)
{
struct udpfakehdr *ufh = (struct udpfakehdr *)p;
diff -urN linux/net/ipv4/ipvs/ip_vs_core.c linux/net/ipv4/ipvs/ip_vs_core.c
--- linux/net/ipv4/ipvs/ip_vs_core.c 2003/11/17 01:07:47 1.4.2.1
+++ linux/net/ipv4/ipvs/ip_vs_core.c 2005/01/20 02:19:25 1.4.2.2
@@ -1131,7 +1131,7 @@
/* increase its packet counter and check if it is needed
to be synchronized */
atomic_inc(&cp->in_pkts);
- if (ip_vs_sync_state == IP_VS_STATE_MASTER &&
+ if (ip_vs_sync_state & IP_VS_STATE_MASTER &&
(cp->protocol != IPPROTO_TCP ||
cp->state == IP_VS_S_ESTABLISHED) &&
(atomic_read(&cp->in_pkts) % 50 == sysctl_ip_vs_sync_threshold))
diff -urN linux/net/ipv4/ipvs/ip_vs_ctl.c linux/net/ipv4/ipvs/ip_vs_ctl.c
--- linux/net/ipv4/ipvs/ip_vs_ctl.c 2004/12/27 04:13:56 1.6.2.3
+++ linux/net/ipv4/ipvs/ip_vs_ctl.c 2005/01/20 02:19:25 1.6.2.4
@@ -1731,10 +1731,11 @@
ret = ip_vs_set_timeouts(urule);
goto out_unlock;
} else if (cmd == IP_VS_SO_SET_STARTDAEMON) {
- ret = start_sync_thread(urule->state, urule->mcast_ifn);
+ ret = start_sync_thread(urule->state, urule->mcast_ifn,
+ urule->syncid);
goto out_unlock;
} else if (cmd == IP_VS_SO_SET_STOPDAEMON) {
- ret = stop_sync_thread();
+ ret = stop_sync_thread(urule->state);
goto out_unlock;
} else if (cmd == IP_VS_SO_SET_ZERO) {
/* if no service address is set, zero counters in all */
@@ -2082,7 +2083,10 @@
goto out;
}
u.state = ip_vs_sync_state;
- strcpy(u.mcast_ifn, ip_vs_mcast_ifn);
+ if (ip_vs_sync_state & IP_VS_STATE_MASTER)
+ strcpy(u.mcast_master_ifn, ip_vs_mcast_master_ifn);
+ if (ip_vs_sync_state & IP_VS_STATE_BACKUP)
+ strcpy(u.mcast_backup_ifn, ip_vs_mcast_backup_ifn);
if (copy_to_user(user, &u, sizeof(u)) != 0)
ret = -EFAULT;
}
diff -urN linux/net/ipv4/ipvs/ip_vs_sync.c linux/net/ipv4/ipvs/ip_vs_sync.c
--- linux/net/ipv4/ipvs/ip_vs_sync.c 2004/11/19 00:29:04 1.4.2.3
+++ linux/net/ipv4/ipvs/ip_vs_sync.c 2005/01/20 02:19:25 1.4.2.4
@@ -13,6 +13,9 @@
* through multicast
*
* Changes:
+ * Alexandre Cassen : Added master & backup support at a time.
+ * Alexandre Cassen : Added SyncID support for incoming sync
+ * messages filtering.
* Justin Ossevoort : Fix endian problem on sync message size.
*/
@@ -74,7 +77,7 @@
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Count Conns | Reserved | Size |
+ | Count Conns | Sync ID | Size |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| IPVS Sync Connection (1) |
@@ -86,11 +89,16 @@
| |
| IPVS Sync Connection (n) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Count Conns : Number of IPVS sync Connection entries.
+ Sync ID : IPVS sync group we belong to.
+ Size : Size of packet.
+
*/
#define SYNC_MESG_MAX_SIZE (24*50+4)
struct ip_vs_sync_mesg {
__u8 nr_conns;
- __u8 reserved;
+ __u8 syncid;
__u16 size;
/* ip_vs_sync_conn entries start here */
@@ -116,6 +124,18 @@
static struct ip_vs_sync_buff *curr_sb = NULL;
static spinlock_t curr_sb_lock = SPIN_LOCK_UNLOCKED;
+/* ipvs sync daemon state */
+volatile int ip_vs_sync_state = IP_VS_STATE_NONE;
+volatile int ip_vs_master_syncid = 0;
+volatile int ip_vs_backup_syncid = 0;
+
+/* multicast interface name */
+char ip_vs_mcast_master_ifn[IP_VS_IFNAME_MAXLEN];
+char ip_vs_mcast_backup_ifn[IP_VS_IFNAME_MAXLEN];
+
+/* multicast addr */
+static struct sockaddr_in mcast_addr;
+
static inline void sb_queue_tail(struct ip_vs_sync_buff *sb)
{
spin_lock(&ip_vs_sync_lock);
@@ -153,6 +173,7 @@
return NULL;
}
sb->mesg->nr_conns = 0;
+ sb->mesg->syncid = ip_vs_master_syncid;
sb->mesg->size = 4;
sb->head = (unsigned char *)sb->mesg + 4;
sb->end = (unsigned char *)sb->mesg + SYNC_MESG_MAX_SIZE;
@@ -265,6 +286,13 @@
return;
}
+ /* SyncID sanity check */
+ if (ip_vs_backup_syncid != 0 && m->syncid != ip_vs_backup_syncid) {
+ IP_VS_DBG(7, "Ignoring incoming msg with syncid = %d\n",
+ m->syncid);
+ return;
+ }
+
p = (char *)buffer + sizeof(struct ip_vs_sync_mesg);
for (i=0; i<m->nr_conns; i++) {
s = (struct ip_vs_sync_conn *)p;
@@ -308,16 +336,6 @@
}
-/* ipvs sync daemon state */
-volatile int ip_vs_sync_state = IP_VS_STATE_NONE;
-
-/* multicast interface name */
-char ip_vs_mcast_ifn[IP_VS_IFNAME_MAXLEN];
-
-/* multicast addr */
-static struct sockaddr_in mcast_addr;
-
-
/*
* Setup loopback of outgoing multicasts on a sending socket
*/
@@ -429,7 +447,7 @@
return NULL;
}
- if (set_mcast_if(sock->sk, ip_vs_mcast_ifn) < 0) {
+ if (set_mcast_if(sock->sk, ip_vs_mcast_master_ifn) < 0) {
IP_VS_ERR("Error setting outbound mcast interface\n");
goto error;
}
@@ -437,7 +455,7 @@
set_mcast_loop(sock->sk, 0);
set_mcast_ttl(sock->sk, 1);
- if (bind_mcastif_addr(sock, ip_vs_mcast_ifn) < 0) {
+ if (bind_mcastif_addr(sock, ip_vs_mcast_master_ifn) < 0) {
IP_VS_ERR("Error binding address of the mcast interface\n");
goto error;
}
@@ -483,7 +501,7 @@
/* join the multicast group */
if (join_mcast_group(sock->sk,
(struct in_addr*)&mcast_addr.sin_addr,
- ip_vs_mcast_ifn) < 0) {
+ ip_vs_mcast_backup_ifn) < 0) {
IP_VS_ERR("Error joining to the multicast group\n");
goto error;
}
@@ -571,10 +589,12 @@
static DECLARE_WAIT_QUEUE_HEAD(sync_wait);
-static pid_t sync_pid = 0;
+static pid_t sync_master_pid = 0;
+static pid_t sync_backup_pid = 0;
static DECLARE_WAIT_QUEUE_HEAD(stop_sync_wait);
-static int stop_sync = 0;
+static int stop_master_sync = 0;
+static int stop_backup_sync = 0;
static void sync_master_loop(void)
{
@@ -586,6 +606,10 @@
if (!sock)
return;
+ IP_VS_INFO("sync thread started: state = MASTER, mcast_ifn = %s, "
+ "syncid = %d\n",
+ ip_vs_mcast_master_ifn, ip_vs_master_syncid);
+
for (;;) {
while ((sb=sb_dequeue())) {
ip_vs_send_sync_msg(sock, sb->mesg);
@@ -598,7 +622,7 @@
ip_vs_sync_buff_release(sb);
}
- if (stop_sync)
+ if (stop_master_sync)
break;
__set_current_state(TASK_INTERRUPTIBLE);
@@ -637,6 +661,10 @@
if (!sock)
goto out;
+ IP_VS_INFO("sync thread started: state = BACKUP, mcast_ifn = %s, "
+ "syncid = %d\n",
+ ip_vs_mcast_backup_ifn, ip_vs_backup_syncid);
+
for (;;) {
/* do you have data now? */
while (!skb_queue_empty(&(sock->sk->receive_queue))) {
@@ -652,7 +680,7 @@
local_bh_enable();
}
- if (stop_sync)
+ if (stop_backup_sync)
break;
__set_current_state(TASK_INTERRUPTIBLE);
@@ -667,12 +695,31 @@
kfree(buf);
}
+static void sync_pid_set(int sync_state, pid_t sync_pid)
+{
+ if (sync_state == IP_VS_STATE_MASTER)
+ sync_master_pid = sync_pid;
+ else if (sync_state == IP_VS_STATE_BACKUP)
+ sync_backup_pid = sync_pid;
+}
+
+static void sync_stop_set(int sync_state, int set)
+{
+ if (sync_state == IP_VS_STATE_MASTER)
+ stop_master_sync = set;
+ else if (sync_state == IP_VS_STATE_BACKUP)
+ stop_backup_sync = set;
+ else {
+ stop_master_sync = set;
+ stop_backup_sync = set;
+ }
+}
static int sync_thread(void *startup)
{
DECLARE_WAITQUEUE(wait, current);
mm_segment_t oldmm;
- int state;
+ int state = IP_VS_STATE_NONE;
MOD_INC_USE_COUNT;
daemonize();
@@ -680,12 +727,15 @@
oldmm = get_fs();
set_fs(KERNEL_DS);
- if (ip_vs_sync_state == IP_VS_STATE_MASTER)
+ if (ip_vs_sync_state & IP_VS_STATE_MASTER && !sync_master_pid) {
+ state = IP_VS_STATE_MASTER;
sprintf(current->comm, "ipvs_syncmaster");
- else if (ip_vs_sync_state == IP_VS_STATE_BACKUP)
+ } else if (ip_vs_sync_state & IP_VS_STATE_BACKUP) {
+ state = IP_VS_STATE_BACKUP;
sprintf(current->comm, "ipvs_syncbackup");
- else IP_VS_BUG();
+ } else IP_VS_BUG();
+ /* Block all signals */
spin_lock_irq(¤t->sigmask_lock);
siginitsetinv(¤t->blocked, 0);
recalc_sigpending(current);
@@ -698,9 +748,7 @@
add_wait_queue(&sync_wait, &wait);
- state = ip_vs_sync_state;
- sync_pid = current->pid;
- IP_VS_INFO("sync thread started.\n");
+ sync_pid_set(state, current->pid);
complete((struct completion *)startup);
/* processing master/backup loop here */
@@ -713,13 +761,13 @@
remove_wait_queue(&sync_wait, &wait);
/* thread exits */
- sync_pid = 0;
+ sync_pid_set(state, 0);
IP_VS_INFO("sync thread stopped!\n");
set_fs(oldmm);
MOD_DEC_USE_COUNT;
- stop_sync = 0;
+ sync_stop_set(state, 0);
wake_up(&stop_sync_wait);
return 0;
@@ -745,20 +793,27 @@
}
-int start_sync_thread(int state, char *mcast_ifn)
+int start_sync_thread(int state, char *mcast_ifn, __u8 syncid)
{
DECLARE_COMPLETION(startup);
pid_t pid;
- if (sync_pid)
+ if ((state == IP_VS_STATE_MASTER && sync_master_pid) ||
+ (state == IP_VS_STATE_BACKUP && sync_backup_pid))
return -EEXIST;
IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid);
IP_VS_DBG(7, "Each ip_vs_sync_conn entry need %d bytes\n",
sizeof(struct ip_vs_sync_conn));
- ip_vs_sync_state = state;
- strcpy(ip_vs_mcast_ifn, mcast_ifn);
+ ip_vs_sync_state |= state;
+ if (state == IP_VS_STATE_MASTER) {
+ strcpy(ip_vs_mcast_master_ifn, mcast_ifn);
+ ip_vs_master_syncid = syncid;
+ } else {
+ strcpy(ip_vs_mcast_backup_ifn, mcast_ifn);
+ ip_vs_backup_syncid = syncid;
+ }
repeat:
if ((pid = kernel_thread(fork_sync_thread, &startup, 0)) < 0) {
@@ -775,20 +830,22 @@
}
-int stop_sync_thread(void)
+int stop_sync_thread(int state)
{
DECLARE_WAITQUEUE(wait, current);
- if (!sync_pid)
+ if ((state == IP_VS_STATE_MASTER && !sync_master_pid) ||
+ (state == IP_VS_STATE_BACKUP && !sync_backup_pid))
return -ESRCH;
IP_VS_DBG(7, "%s: pid %d\n", __FUNCTION__, current->pid);
- IP_VS_INFO("stopping sync thread %d ...\n", sync_pid);
+ IP_VS_INFO("stopping sync thread %d ...\n",
+ (state == IP_VS_STATE_MASTER) ? sync_master_pid :
sync_backup_pid);
__set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&stop_sync_wait, &wait);
- ip_vs_sync_state = IP_VS_STATE_NONE;
- stop_sync = 1;
+ sync_stop_set(state, 1);
+ ip_vs_sync_state -= state;
wake_up(&sync_wait);
schedule();
__set_current_state(TASK_RUNNING);
@@ -797,7 +854,8 @@
/* Note: no need to reap the sync thread, because its parent
process is the init process */
- if (stop_sync)
+ if ((state == IP_VS_STATE_MASTER && stop_master_sync) ||
+ (state == IP_VS_STATE_BACKUP && stop_backup_sync))
IP_VS_BUG();
return 0;
diff -urN linux/net/ipv4/netfilter/Config.in linux/net/ipv4/netfilter/Config.in
--- linux/net/ipv4/netfilter/Attic/Config.in 2003/08/13 17:19:30 1.5.2.6
+++ linux/net/ipv4/netfilter/Attic/Config.in 2005/01/20 02:19:25 1.5.2.7
@@ -66,7 +66,6 @@
define_tristate CONFIG_IP_NF_NAT_AMANDA $CONFIG_IP_NF_NAT
fi
fi
- bool ' NAT of local connections (READ HELP)' CONFIG_IP_NF_NAT_LOCAL
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
dep_tristate ' Basic SNMP-ALG support (EXPERIMENTAL)'
CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT
fi
diff -urN linux/net/ipv4/netfilter/ip_conntrack_core.c
linux/net/ipv4/netfilter/ip_conntrack_core.c
--- linux/net/ipv4/netfilter/ip_conntrack_core.c 2004/11/19 00:29:04
1.13.2.11
+++ linux/net/ipv4/netfilter/ip_conntrack_core.c 2005/01/20 02:19:25
1.13.2.12
@@ -122,9 +122,9 @@
}
inline int
-get_tuple(const struct iphdr *iph, size_t len,
- struct ip_conntrack_tuple *tuple,
- struct ip_conntrack_protocol *protocol)
+ip_ct_get_tuple(const struct iphdr *iph, size_t len,
+ struct ip_conntrack_tuple *tuple,
+ struct ip_conntrack_protocol *protocol)
{
int ret;
@@ -546,7 +546,7 @@
innerproto = ip_ct_find_proto(inner->protocol);
/* Are they talking about one of our connections? */
if (inner->ihl * 4 + 8 > datalen
- || !get_tuple(inner, datalen, &origtuple, innerproto)) {
+ || !ip_ct_get_tuple(inner, datalen, &origtuple, innerproto)) {
DEBUGP("icmp_error: ! get_tuple p=%u (%u*4+%u dlen=%u)\n",
inner->protocol, inner->ihl, 8,
datalen);
@@ -757,7 +757,7 @@
IP_NF_ASSERT((skb->nh.iph->frag_off & htons(IP_OFFSET)) == 0);
- if (!get_tuple(skb->nh.iph, skb->len, &tuple, proto))
+ if (!ip_ct_get_tuple(skb->nh.iph, skb->len, &tuple, proto))
return NULL;
/* look for tuple match */
diff -urN linux/net/ipv4/netfilter/ip_conntrack_standalone.c
linux/net/ipv4/netfilter/ip_conntrack_standalone.c
--- linux/net/ipv4/netfilter/ip_conntrack_standalone.c 2004/11/19 00:29:04
1.11.2.10
+++ linux/net/ipv4/netfilter/ip_conntrack_standalone.c 2005/01/20 02:19:25
1.11.2.11
@@ -468,6 +468,7 @@
EXPORT_SYMBOL(ip_conntrack_protocol_register);
EXPORT_SYMBOL(ip_conntrack_protocol_unregister);
EXPORT_SYMBOL(invert_tuplepr);
+EXPORT_SYMBOL(ip_ct_get_tuple);
EXPORT_SYMBOL(ip_conntrack_alter_reply);
EXPORT_SYMBOL(ip_conntrack_destroyed);
EXPORT_SYMBOL(ip_conntrack_get);
diff -urN linux/net/ipv4/netfilter/ip_fw_compat_masq.c
linux/net/ipv4/netfilter/ip_fw_compat_masq.c
--- linux/net/ipv4/netfilter/Attic/ip_fw_compat_masq.c 2004/08/14 18:39:05
1.7.2.4
+++ linux/net/ipv4/netfilter/Attic/ip_fw_compat_masq.c 2005/01/20 02:19:25
1.7.2.5
@@ -157,7 +157,7 @@
case IPPROTO_UDP:
IP_NF_ASSERT(((*pskb)->nh.iph->frag_off & htons(IP_OFFSET)) ==
0);
- if (!get_tuple(iph, (*pskb)->len, &tuple, protocol)) {
+ if (!ip_ct_get_tuple(iph, (*pskb)->len, &tuple, protocol)) {
if (net_ratelimit())
printk("ip_fw_compat_masq: Can't get tuple\n");
return NF_ACCEPT;
diff -urN linux/net/ipv4/netfilter/ip_nat_core.c
linux/net/ipv4/netfilter/ip_nat_core.c
--- linux/net/ipv4/netfilter/ip_nat_core.c 2004/08/14 18:39:05 1.9.2.10
+++ linux/net/ipv4/netfilter/ip_nat_core.c 2005/01/20 02:19:25 1.9.2.11
@@ -198,7 +198,6 @@
return NULL;
}
-#ifdef CONFIG_IP_NF_NAT_LOCAL
/* If it's really a local destination manip, it may need to do a
source manip too. */
static int
@@ -217,7 +216,6 @@
ip_rt_put(rt);
return 1;
}
-#endif
/* Simple way to iterate through all. */
static inline int fake_cmp(const struct ip_nat_hash *i,
@@ -317,7 +315,6 @@
* do_extra_mangle last time. */
*other_ipp = saved_ip;
-#ifdef CONFIG_IP_NF_NAT_LOCAL
if (hooknum == NF_IP_LOCAL_OUT
&& *var_ipp != orig_dstip
&& !do_extra_mangle(*var_ipp, other_ipp)) {
@@ -328,7 +325,6 @@
* anyway. */
continue;
}
-#endif
/* Count how many others map onto this. */
score = count_maps(tuple->src.ip, tuple->dst.ip,
@@ -372,13 +368,11 @@
else {
/* Only do extra mangle when required (breaks
socket binding) */
-#ifdef CONFIG_IP_NF_NAT_LOCAL
if (tuple->dst.ip != mr->range[0].min_ip
&& hooknum == NF_IP_LOCAL_OUT
&& !do_extra_mangle(mr->range[0].min_ip,
&tuple->src.ip))
return NULL;
-#endif
tuple->dst.ip = mr->range[0].min_ip;
}
}
@@ -501,10 +495,8 @@
static unsigned int opposite_hook[NF_IP_NUMHOOKS]
= { [NF_IP_PRE_ROUTING] = NF_IP_POST_ROUTING,
[NF_IP_POST_ROUTING] = NF_IP_PRE_ROUTING,
-#ifdef CONFIG_IP_NF_NAT_LOCAL
[NF_IP_LOCAL_OUT] = NF_IP_LOCAL_IN,
[NF_IP_LOCAL_IN] = NF_IP_LOCAL_OUT,
-#endif
};
unsigned int
@@ -868,6 +860,23 @@
/* not reached */
}
+static inline int tuple_src_equal_dst(const struct ip_conntrack_tuple *t1,
+ const struct ip_conntrack_tuple *t2)
+{
+ if (t1->dst.protonum != t2->dst.protonum || t1->src.ip != t2->dst.ip)
+ return 0;
+ if (t1->dst.protonum != IPPROTO_ICMP)
+ return t1->src.u.all == t2->dst.u.all;
+ else {
+ struct ip_conntrack_tuple inv;
+
+ /* ICMP tuples are asymetric */
+ invert_tuplepr(&inv, t1);
+ return inv.src.u.all == t2->src.u.all &&
+ inv.dst.u.all == t2->dst.u.all;
+ }
+}
+
unsigned int
icmp_reply_translation(struct sk_buff *skb,
struct ip_conntrack *conntrack,
@@ -880,6 +889,7 @@
size_t datalen = skb->len - ((void *)inner - (void *)iph);
unsigned int i;
struct ip_nat_info *info = &conntrack->nat.info;
+ struct ip_conntrack_tuple *cttuple, innertuple;
IP_NF_ASSERT(skb->len >= iph->ihl*4 + sizeof(struct icmphdr));
/* Must be RELATED */
@@ -914,6 +924,11 @@
such addresses are not too uncommon, as Alan Cox points
out) */
+ if (!ip_ct_get_tuple(inner, datalen, &innertuple,
+ ip_ct_find_proto(inner->protocol)))
+ return 0;
+ cttuple = &conntrack->tuplehash[dir].tuple;
+
READ_LOCK(&ip_nat_lock);
for (i = 0; i < info->num_manips; i++) {
DEBUGP("icmp_reply: manip %u dir %s hook %u\n",
@@ -923,35 +938,49 @@
if (info->manips[i].direction != dir)
continue;
- /* Mapping the inner packet is just like a normal
- packet, except it was never src/dst reversed, so
- where we would normally apply a dst manip, we apply
- a src, and vice versa. */
- if (info->manips[i].hooknum == hooknum) {
- DEBUGP("icmp_reply: inner %s -> %u.%u.%u.%u %u\n",
- info->manips[i].maniptype == IP_NAT_MANIP_SRC
- ? "DST" : "SRC",
- NIPQUAD(info->manips[i].manip.ip),
- ntohs(info->manips[i].manip.u.udp.port));
- manip_pkt(inner->protocol, inner,
- skb->len - ((void *)inner - (void *)iph),
- &info->manips[i].manip,
- !info->manips[i].maniptype,
- &skb->nfcache);
- /* Outer packet needs to have IP header NATed like
- it's a reply. */
-
- /* Use mapping to map outer packet: 0 give no
- per-proto mapping */
- DEBUGP("icmp_reply: outer %s -> %u.%u.%u.%u\n",
- info->manips[i].maniptype == IP_NAT_MANIP_SRC
- ? "SRC" : "DST",
- NIPQUAD(info->manips[i].manip.ip));
- manip_pkt(0, iph, skb->len,
- &info->manips[i].manip,
- info->manips[i].maniptype,
- &skb->nfcache);
+ /* Mapping the inner packet is just like a normal packet, except
+ * it was never src/dst reversed, so where we would normally
+ * apply a dst manip, we apply a src, and vice versa. */
+
+ /* Only true for forwarded packets, locally generated packets
+ * never hit PRE_ROUTING, we need to apply their PRE_ROUTING
+ * manips in LOCAL_OUT. */
+ if (hooknum == NF_IP_LOCAL_OUT &&
+ info->manips[i].hooknum == NF_IP_PRE_ROUTING)
+ hooknum = info->manips[i].hooknum;
+
+ if (info->manips[i].hooknum != hooknum)
+ continue;
+
+ /* ICMP errors may be generated locally for packets that
+ * don't have all NAT manips applied yet. Verify manips
+ * have been applied before reversing them */
+ if (info->manips[i].maniptype == IP_NAT_MANIP_SRC) {
+ if (!tuple_src_equal_dst(cttuple, &innertuple))
+ continue;
+ } else {
+ if (!tuple_src_equal_dst(&innertuple, cttuple))
+ continue;
}
+
+ DEBUGP("icmp_reply: inner %s -> %u.%u.%u.%u %u\n",
+ info->manips[i].maniptype == IP_NAT_MANIP_SRC
+ ? "DST" : "SRC", NIPQUAD(info->manips[i].manip.ip),
+ ntohs(info->manips[i].manip.u.udp.port));
+ manip_pkt(inner->protocol, inner,
+ skb->len - ((void *)inner - (void *)iph),
+ &info->manips[i].manip, !info->manips[i].maniptype,
+ &skb->nfcache);
+ /* Outer packet needs to have IP header NATed like
+ it's a reply. */
+
+ /* Use mapping to map outer packet: 0 give no
+ per-proto mapping */
+ DEBUGP("icmp_reply: outer %s -> %u.%u.%u.%u\n",
+ info->manips[i].maniptype == IP_NAT_MANIP_SRC
+ ? "SRC" : "DST", NIPQUAD(info->manips[i].manip.ip));
+ manip_pkt(0, iph, skb->len, &info->manips[i].manip,
+ info->manips[i].maniptype, &skb->nfcache);
}
READ_UNLOCK(&ip_nat_lock);
diff -urN linux/net/ipv4/netfilter/ip_nat_rule.c
linux/net/ipv4/netfilter/ip_nat_rule.c
--- linux/net/ipv4/netfilter/ip_nat_rule.c 2004/08/14 18:39:05 1.4.2.6
+++ linux/net/ipv4/netfilter/ip_nat_rule.c 2005/01/20 02:19:25 1.4.2.7
@@ -138,12 +138,8 @@
struct ip_conntrack *ct;
enum ip_conntrack_info ctinfo;
-#ifdef CONFIG_IP_NF_NAT_LOCAL
IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
|| hooknum == NF_IP_LOCAL_OUT);
-#else
- IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING);
-#endif
ct = ip_conntrack_get(*pskb, &ctinfo);
@@ -221,13 +217,6 @@
return 0;
}
-#ifndef CONFIG_IP_NF_NAT_LOCAL
- if (hook_mask & (1 << NF_IP_LOCAL_OUT)) {
- DEBUGP("DNAT: CONFIG_IP_NF_NAT_LOCAL not enabled\n");
- return 0;
- }
-#endif
-
return 1;
}
diff -urN linux/net/ipv4/netfilter/ip_nat_standalone.c
linux/net/ipv4/netfilter/ip_nat_standalone.c
--- linux/net/ipv4/netfilter/ip_nat_standalone.c 2004/04/16 03:14:22
1.12.2.9
+++ linux/net/ipv4/netfilter/ip_nat_standalone.c 2005/01/20 02:19:25
1.12.2.10
@@ -114,16 +114,7 @@
WRITE_LOCK(&ip_nat_lock);
/* Seen it before? This can happen for loopback, retrans,
or local packets.. */
- if (!(info->initialized & (1 << maniptype))
-#ifndef CONFIG_IP_NF_NAT_LOCAL
- /* If this session has already been confirmed we must not
- * touch it again even if there is no mapping set up.
- * Can only happen on local->local traffic with
- * CONFIG_IP_NF_NAT_LOCAL disabled.
- */
- && !(ct->status & IPS_CONFIRMED)
-#endif
- ) {
+ if (!(info->initialized & (1 << maniptype))) {
unsigned int ret;
if (ct->master
@@ -132,15 +123,14 @@
ret = call_expect(master_ct(ct), pskb,
hooknum, ct, info);
} else {
-#ifdef CONFIG_IP_NF_NAT_LOCAL
/* LOCAL_IN hook doesn't have a chain! */
if (hooknum == NF_IP_LOCAL_IN)
ret = alloc_null_binding(ct, info,
hooknum);
else
-#endif
- ret = ip_nat_rule_find(pskb, hooknum, in, out,
- ct, info);
+ ret = ip_nat_rule_find(pskb, hooknum,
+ in, out,
+ ct, info);
}
if (ret != NF_ACCEPT) {
@@ -166,6 +156,29 @@
}
static unsigned int
+ip_nat_in(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ u_int32_t saddr, daddr;
+ unsigned int ret;
+
+ saddr = (*pskb)->nh.iph->saddr;
+ daddr = (*pskb)->nh.iph->daddr;
+
+ ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
+ if (ret != NF_DROP && ret != NF_STOLEN
+ && ((*pskb)->nh.iph->saddr != saddr
+ || (*pskb)->nh.iph->daddr != daddr)) {
+ dst_release((*pskb)->dst);
+ (*pskb)->dst = NULL;
+ }
+ return ret;
+}
+
+static unsigned int
ip_nat_out(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
@@ -197,7 +210,6 @@
return ip_nat_fn(hooknum, pskb, in, out, okfn);
}
-#ifdef CONFIG_IP_NF_NAT_LOCAL
static unsigned int
ip_nat_local_fn(unsigned int hooknum,
struct sk_buff **pskb,
@@ -223,25 +235,21 @@
return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
return ret;
}
-#endif
/* We must be after connection tracking and before packet filtering. */
/* Before packet filtering, change destination */
static struct nf_hook_ops ip_nat_in_ops
-= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_NAT_DST };
+= { { NULL, NULL }, ip_nat_in, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_NAT_DST };
/* After packet filtering, change source */
static struct nf_hook_ops ip_nat_out_ops
= { { NULL, NULL }, ip_nat_out, PF_INET, NF_IP_POST_ROUTING,
NF_IP_PRI_NAT_SRC};
-
-#ifdef CONFIG_IP_NF_NAT_LOCAL
/* Before packet filtering, change destination */
static struct nf_hook_ops ip_nat_local_out_ops
= { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT,
NF_IP_PRI_NAT_DST };
/* After packet filtering, change source for reply packets of LOCAL_OUT DNAT */
static struct nf_hook_ops ip_nat_local_in_ops
= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_NAT_SRC };
-#endif
/* Protocol registration. */
int ip_nat_protocol_register(struct ip_nat_protocol *proto)
@@ -306,7 +314,6 @@
printk("ip_nat_init: can't register out hook.\n");
goto cleanup_inops;
}
-#ifdef CONFIG_IP_NF_NAT_LOCAL
ret = nf_register_hook(&ip_nat_local_out_ops);
if (ret < 0) {
printk("ip_nat_init: can't register local out hook.\n");
@@ -317,16 +324,13 @@
printk("ip_nat_init: can't register local in hook.\n");
goto cleanup_localoutops;
}
-#endif
return ret;
cleanup:
-#ifdef CONFIG_IP_NF_NAT_LOCAL
nf_unregister_hook(&ip_nat_local_in_ops);
cleanup_localoutops:
nf_unregister_hook(&ip_nat_local_out_ops);
cleanup_outops:
-#endif
nf_unregister_hook(&ip_nat_out_ops);
cleanup_inops:
nf_unregister_hook(&ip_nat_in_ops);
diff -urN linux/net/ipv4/netfilter/ip_tables.c
linux/net/ipv4/netfilter/ip_tables.c
--- linux/net/ipv4/netfilter/ip_tables.c 2004/08/14 18:39:05 1.14.2.8
+++ linux/net/ipv4/netfilter/ip_tables.c 2005/01/20 02:19:25 1.14.2.9
@@ -1274,7 +1274,7 @@
sizeof(info.underflow));
info.num_entries = t->private->number;
info.size = t->private->size;
- strcpy(info.name, name);
+ memcpy(info.name, name, sizeof(info.name));
if (copy_to_user(user, &info, *len) != 0)
ret = -EFAULT;
diff -urN linux/net/ipv4/netfilter/ipt_MASQUERADE.c
linux/net/ipv4/netfilter/ipt_MASQUERADE.c
--- linux/net/ipv4/netfilter/ipt_MASQUERADE.c 2004/08/14 18:39:05 1.9.2.4
+++ linux/net/ipv4/netfilter/ipt_MASQUERADE.c 2005/01/20 02:19:25 1.9.2.5
@@ -125,35 +125,58 @@
}
static inline int
-device_cmp(const struct ip_conntrack *i, void *_ina)
+device_cmp(const struct ip_conntrack *i, void *ifindex)
{
- int ret = 0;
- struct in_ifaddr *ina = _ina;
+ int ret;
READ_LOCK(&masq_lock);
- /* If it's masquerading out this interface with a different address,
- * or we don't know the new address of this interface. */
- if (i->nat.masq_index == ina->ifa_dev->dev->ifindex
- && i->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip != ina->ifa_address)
- ret = 1;
+ ret = (i->nat.masq_index == (int)(long)ifindex);
READ_UNLOCK(&masq_lock);
return ret;
}
+static int masq_device_event(struct notifier_block *this,
+ unsigned long event,
+ void *ptr)
+{
+ struct net_device *dev = ptr;
+
+ if (event == NETDEV_DOWN) {
+ /* Device was downed. Search entire table for
+ conntracks which were associated with that device,
+ and forget them. */
+ IP_NF_ASSERT(dev->ifindex != 0);
+
+ ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
+ }
+
+ return NOTIFY_DONE;
+}
+
+
static int masq_inet_event(struct notifier_block *this,
unsigned long event,
void *ptr)
{
- /* For some configurations, interfaces often come back with
- * the same address. If not, clean up old conntrack
- * entries. */
- if (event == NETDEV_UP)
- ip_ct_selective_cleanup(device_cmp, ptr);
+ struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
+
+ if (event == NETDEV_DOWN) {
+ /* IP address was deleted. Search entire table for
+ conntracks which were associated with that device,
+ and forget them. */
+ IP_NF_ASSERT(dev->ifindex != 0);
+
+ ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
+ }
return NOTIFY_DONE;
}
+static struct notifier_block masq_dev_notifier = {
+ .notifier_call = masq_device_event,
+};
+
static struct notifier_block masq_inet_notifier = {
.notifier_call = masq_inet_event
};
@@ -168,9 +191,12 @@
ret = ipt_register_target(&masquerade);
- if (ret == 0)
+ if (ret == 0) {
+ /* Register for device down reports */
+ register_netdevice_notifier(&masq_dev_notifier);
/* Register IP address change reports */
register_inetaddr_notifier(&masq_inet_notifier);
+ }
return ret;
}
@@ -178,6 +204,7 @@
static void __exit fini(void)
{
ipt_unregister_target(&masquerade);
+ unregister_netdevice_notifier(&masq_dev_notifier);
unregister_inetaddr_notifier(&masq_inet_notifier);
}
diff -urN linux/net/ipv4/netfilter/ipt_REJECT.c
linux/net/ipv4/netfilter/ipt_REJECT.c
--- linux/net/ipv4/netfilter/ipt_REJECT.c 2004/08/14 18:39:05 1.13.2.7
+++ linux/net/ipv4/netfilter/ipt_REJECT.c 2005/01/20 02:19:25 1.13.2.8
@@ -22,18 +22,6 @@
#define DEBUGP(format, args...)
#endif
-/* If the original packet is part of a connection, but the connection
- is not confirmed, our manufactured reply will not be associated
- with it, so we need to do this manually. */
-static void connection_attach(struct sk_buff *new_skb, struct nf_ct_info *nfct)
-{
- void (*attach)(struct sk_buff *, struct nf_ct_info *);
-
- /* Avoid module unload race with ip_ct_attach being NULLed out */
- if (nfct && (attach = ip_ct_attach) != NULL)
- attach(new_skb, nfct);
-}
-
static inline struct rtable *route_reverse(struct sk_buff *skb, int hook)
{
struct iphdr *iph = skb->nh.iph;
@@ -187,7 +175,7 @@
if (nskb->len > nskb->dst->pmtu)
goto free_nskb;
- connection_attach(nskb, oldskb->nfct);
+ nf_ct_attach(nskb, oldskb);
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
ip_finish_output);
@@ -323,7 +311,7 @@
icmph->checksum = ip_compute_csum((unsigned char *)icmph,
length - sizeof(struct iphdr));
- connection_attach(nskb, skb_in->nfct);
+ nf_ct_attach(nskb, skb_in);
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
ip_finish_output);
diff -urN linux/net/ipv6/sit.c linux/net/ipv6/sit.c
--- linux/net/ipv6/sit.c 2004/11/19 00:29:05 1.23.2.7
+++ linux/net/ipv6/sit.c 2005/01/20 02:19:25 1.23.2.8
@@ -139,10 +139,10 @@
{
struct ip_tunnel **tp = ipip6_bucket(t);
- write_lock_bh(&ipip6_lock);
t->next = *tp;
- write_unlock_bh(&ipip6_lock);
+ write_lock_bh(&ipip6_lock);
*tp = t;
+ write_unlock_bh(&ipip6_lock);
}
struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int
create)
diff -urN linux/net/ipv6/netfilter/ip6_tables.c
linux/net/ipv6/netfilter/ip6_tables.c
--- linux/net/ipv6/netfilter/ip6_tables.c 2004/08/14 18:39:05 1.9.2.8
+++ linux/net/ipv6/netfilter/ip6_tables.c 2005/01/20 02:19:25 1.9.2.9
@@ -149,14 +149,15 @@
/* 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))
@@ -210,6 +211,7 @@
struct ipv6_opt_hdr *hdrptr;
u_int16_t ptr; /* Header offset in skb */
u_int16_t hdrlen; /* Header */
+ u_int16_t foff = 0;
ptr = IPV6_HDR_LEN;
@@ -229,6 +231,16 @@
/* Size calculation */
if (currenthdr == IPPROTO_FRAGMENT) {
+ unsigned int foff_off;
+
+ foff_off = ptr + offsetof(struct frag_hdr,
+ frag_off);
+ if (skb->len - foff_off < sizeof(foff))
+ return 0;
+
+ foff = ntohs(*(u_int16_t *)(skb->data
+ + foff_off))
+ & ~0x7;
hdrlen = 8;
} else if (currenthdr == IPPROTO_AH)
hdrlen = (hdrptr->hdrlen+2)<<2;
@@ -240,8 +252,16 @@
/* ptr is too large */
if ( ptr > skb->len )
return 0;
+ if (foff) {
+ if (ip6t_ext_hdr(currenthdr))
+ return 0;
+ break;
+ }
}
+ *protoff = ptr;
+ *fragoff = foff;
+
/* currenthdr contains the protocol header */
dprintf("Packet protocol %hi ?= %s%hi.\n",
@@ -329,10 +349,8 @@
void *userdata)
{
static const char nulldevname[IFNAMSIZ] = { 0 };
- 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;
@@ -341,9 +359,6 @@
struct ip6t_entry *e, *back;
/* 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;
@@ -381,17 +396,20 @@
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,
+ (void *)((*pskb)->data
+ + protoff),
+ (*pskb)->len - 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);
@@ -447,11 +465,6 @@
((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
@@ -1343,7 +1356,7 @@
sizeof(info.underflow));
info.num_entries = t->private->number;
info.size = t->private->size;
- strcpy(info.name, name);
+ memcpy(info.name, name, sizeof(info.name));
if (copy_to_user(user, &info, *len) != 0)
ret = -EFAULT;
@@ -1567,10 +1580,8 @@
u_int16_t datalen,
int *hotdrop)
{
- const struct tcphdr *tcp;
+ const struct tcphdr *tcp = hdr;
const struct ip6t_tcp *tcpinfo = matchinfo;
- int tcpoff;
- u8 nexthdr = skb->nh.ipv6h->nexthdr;
/* To quote Alan:
@@ -1591,24 +1602,6 @@
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;
- return 0;
- } else if (nexthdr == IPPROTO_FRAGMENT)
- 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;
- 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))
@@ -1659,10 +1652,8 @@
u_int16_t datalen,
int *hotdrop)
{
- const struct udphdr *udp;
+ const struct udphdr *udp = hdr;
const struct ip6t_udp *udpinfo = matchinfo;
- int udpoff;
- u8 nexthdr = skb->nh.ipv6h->nexthdr;
if (offset == 0 && datalen < sizeof(struct udphdr)) {
/* We've been asked to examine this packet, and we
@@ -1672,23 +1663,6 @@
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],
diff -urN linux/net/ipv6/netfilter/ip6t_LOG.c
linux/net/ipv6/netfilter/ip6t_LOG.c
--- linux/net/ipv6/netfilter/ip6t_LOG.c 2004/11/19 00:29:05 1.1.2.3
+++ linux/net/ipv6/netfilter/ip6t_LOG.c 2005/01/20 02:19:25 1.1.2.4
@@ -35,54 +35,40 @@
ntohs((addr).s6_addr16[6]), \
ntohs((addr).s6_addr16[7])
-struct esphdr {
- __u32 spi;
-}; /* FIXME evil kludge */
-
-/* Use lock to serialize, so printks don't overlap */
-static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
+/* FIXME evil kludge */
-/* 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 0 */
-static u_int8_t ip6_nexthdr(u_int8_t currenthdr, u_int8_t **hdrptr)
-{
- u_int8_t hdrlen, nexthdr = 0;
+struct ahhdr {
+ __u8 nexthdr;
+ __u8 hdrlen;
+ __u16 reserved;
+ __u32 spi;
+ __u32 seq_no;
+};
- 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;
+struct esphdr {
+ __u32 spi;
+ __u32 seq_no;
+};
-}
+/* Use lock to serialize, so printks don't overlap */
+static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
/* 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 *ipv6h;
+ unsigned int ptr;
+ unsigned int hdrlen = 0;
+
+ if (skb->len - ip6hoff < sizeof(*ipv6h)) {
+ printk("TRUNCATED");
+ return;
+ }
+ ipv6h = (struct ipv6hdr *)(skb->data + ip6hoff);
/* 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));
@@ -96,60 +82,131 @@
(ntohl(*(u_int32_t *)ipv6h) & 0x000fffff));
fragment = 0;
- hdrptr = (u_int8_t *)(ipv6h + 1);
- while (currenthdr) {
- if ((currenthdr == IPPROTO_TCP) ||
- (currenthdr == IPPROTO_UDP) ||
- (currenthdr == IPPROTO_ICMPV6))
- break;
+ ptr = ip6hoff + sizeof(struct ipv6hdr);
+ currenthdr = ipv6h->nexthdr;
+ while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) {
+ struct ipv6_opt_hdr *hdr;
+
+ if (skb->len - ptr < sizeof(*hdr)) {
+ printk("TRUNCATED");
+ return;
+ }
+ hdr = (struct ipv6_opt_hdr *)(skb->data + ptr);
+
/* 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;
- /* Max length: 11 "FRAG:65535 " */
- printk("FRAG:%u ", ntohs(fhdr->frag_off) & 0xFFF8);
+ printk("FRAG:");
+ if (skb->len - ptr < sizeof(*fhdr)) {
+ printk("TRUNCATED ");
+ return;
+ }
+ fhdr = (struct frag_hdr *)(skb->data + ptr);
+
+ /* Max length: 6 "65535 " */
+ printk("%u ", ntohs(fhdr->frag_off) & 0xFFF8);
/* Max length: 11 "INCOMPLETE " */
if (fhdr->frag_off & htons(0x0001))
printk("INCOMPLETE ");
- printk("ID:%08x ", fhdr->identification);
+ printk("ID:%08x ", ntohl(fhdr->identification));
if (ntohs(fhdr->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(hdr);
break;
/* Max Length */
case IPPROTO_AH:
+ if (info->logflags & IP6T_LOG_IPOPT) {
+ struct ahhdr *ah;
+
+ /* Max length: 3 "AH " */
+ printk("AH ");
+
+ if (fragment) {
+ printk(")");
+ return;
+ }
+
+ if (skb->len - ptr < sizeof(*ah)) {
+ /*
+ * Max length: 26 "INCOMPLETE [65535
+ * bytes] )"
+ */
+ printk("INCOMPLETE [%u bytes] )",
+ skb->len - ptr);
+ return;
+ }
+ ah = (struct ahhdr *)(skb->data + ptr);
+
+ /* Length: 15 "SPI=0xF1234567 */
+ printk("SPI=0x%x ", ntohl(ah->spi));
+
+ }
+
+ hdrlen = (hdr->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 esphdr *esph;
/* Max length: 4 "ESP " */
- printk("%s ",esp ? "ESP" : "AH");
+ printk("ESP ");
+
+ if (fragment) {
+ printk(")");
+ return;
+ }
+
+ /*
+ * Max length: 26 "INCOMPLETE [65535 bytes] )"
+ */
+ if (skb->len - ptr < sizeof(*esph)) {
+ printk("INCOMPLETE [%u bytes] )",
+ skb->len - ptr);
+ return;
+ }
+ esph = (struct esphdr *)(skb->data + ptr);
+
+ /* Length: 16 "SPI=0xF1234567 )" */
+ printk("SPI=0x%x )", ntohl(esph->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 = hdr->nexthdr;
+ ptr += hdrlen;
}
switch (currenthdr) {
case IPPROTO_TCP: {
- struct tcphdr *tcph = (struct tcphdr *)hdrptr;
+ struct tcphdr *tcph;
/* Max length: 10 "PROTO=TCP " */
printk("PROTO=TCP ");
@@ -157,6 +214,13 @@
if (fragment)
break;
+ /* Max length: 25 "INCOMPLETE [65535 bytes] " */
+ if (skb->len - ptr < sizeof(*tcph)) {
+ printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+ return;
+ }
+ tcph = (struct tcphdr *)(skb->data + ptr);
+
/* Max length: 20 "SPT=65535 DPT=65535 " */
printk("SPT=%u DPT=%u ",
ntohs(tcph->source), ntohs(tcph->dest));
@@ -166,7 +230,7 @@
ntohl(tcph->seq), ntohl(tcph->ack_seq));
/* Max length: 13 "WINDOW=65535 " */
printk("WINDOW=%u ", ntohs(tcph->window));
- /* Max length: 9 "RES=0x3F " */
+ /* Max length: 9 "RES=0x3C " */
printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(tcph) &
TCP_RESERVED_BITS) >> 22));
/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
if (tcph->cwr)
@@ -189,19 +253,29 @@
printk("URGP=%u ", ntohs(tcph->urg_ptr));
if ((info->logflags & IP6T_LOG_TCPOPT)
- && tcph->doff * 4 != sizeof(struct tcphdr)) {
+ && tcph->doff * 4 > sizeof(struct tcphdr)) {
+ u_int8_t *op;
unsigned int i;
+ unsigned int optsize = tcph->doff * 4
+ - sizeof(struct tcphdr);
+
+ if (skb->len - ptr - sizeof(struct tcphdr) < optsize) {
+ printk("OPT (TRUNCATED)");
+ return;
+ }
+ op = (u_int8_t *)(skb->data + ptr
+ + sizeof(struct tcphdr));
/* 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;
/* Max length: 10 "PROTO=UDP " */
printk("PROTO=UDP ");
@@ -209,6 +283,13 @@
if (fragment)
break;
+ /* Max length: 25 "INCOMPLETE [65535 bytes] " */
+ if (skb->len - ptr < sizeof(*udph)) {
+ printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+ return;
+ }
+ udph = (struct udphdr *)(skb->data + ptr);
+
/* Max length: 20 "SPT=65535 DPT=65535 " */
printk("SPT=%u DPT=%u LEN=%u ",
ntohs(udph->source), ntohs(udph->dest),
@@ -216,7 +297,7 @@
break;
}
case IPPROTO_ICMPV6: {
- struct icmp6hdr *icmp6h = (struct icmp6hdr *)hdrptr;
+ struct icmp6hdr *icmp6h;
/* Max length: 13 "PROTO=ICMPv6 " */
printk("PROTO=ICMPv6 ");
@@ -224,6 +305,13 @@
if (fragment)
break;
+ /* Max length: 25 "INCOMPLETE [65535 bytes] " */
+ if (skb->len - ptr < sizeof(*icmp6h)) {
+ printk("INCOMPLETE [%u bytes] ", skb->len - ptr);
+ return;
+ }
+ icmp6h = (struct icmp6hdr *)(skb->data + ptr);
+
/* Max length: 18 "TYPE=255 CODE=255 " */
printk("TYPE=%u CODE=%u ", icmp6h->icmp6_type,
icmp6h->icmp6_code);
@@ -250,7 +338,8 @@
/* Max length: 3+maxlen */
if (recurse) {
printk("[");
- dump_packet(info, (struct ipv6hdr *)(icmp6h +
1), 0);
+ dump_packet(info, skb, ptr + sizeof(*icmp6h),
+ 0);
printk("] ");
}
@@ -260,7 +349,7 @@
}
break;
}
- /* Max length: 10 "PROTO 255 " */
+ /* Max length: 10 "PROTO=255 " */
default:
printk("PROTO=%u ", currenthdr);
}
@@ -326,7 +415,8 @@
printk(" ");
}
- dump_packet(loginfo, ipv6h, 1);
+ dump_packet(loginfo, (*pskb), (u8*)(*pskb)->nh.ipv6h - (*pskb)->data,
+ 1);
printk("\n");
spin_unlock_bh(&log_lock);
diff -urN linux/net/ipv6/netfilter/ip6t_dst.c
linux/net/ipv6/netfilter/ip6t_dst.c
--- linux/net/ipv6/netfilter/ip6t_dst.c 2003/07/05 03:23:48 1.3.2.1
+++ linux/net/ipv6/netfilter/ip6t_dst.c 2005/01/20 02:19:25 1.3.2.2
@@ -11,8 +11,6 @@
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter_ipv6/ip6t_opts.h>
-#define LOW(n) (n & 0x00FF)
-
#define HOPBYHOP 0
EXPORT_NO_SYMBOLS;
@@ -40,8 +38,8 @@
* 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
*/
@@ -64,7 +62,8 @@
unsigned int ptr;
unsigned int hdrlen = 0;
unsigned int ret = 0;
- u_int16_t *optdesc = NULL;
+ u8 *opttype = NULL;
+ unsigned int optlen;
/* type of the 1st exthdr */
nexthdr = skb->nh.ipv6h->nexthdr;
@@ -91,7 +90,7 @@
break;
}
- hdr=(void *)(skb->data)+ptr;
+ hdr = (void *)(skb->data + ptr);
/* Calculate the header length */
if (nexthdr == NEXTHDR_FRAGMENT) {
@@ -153,7 +152,7 @@
return 0;
}
- optsh=(void *)(skb->data)+ptr;
+ optsh = (void *)(skb->data + ptr);
DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, optsh->hdrlen);
@@ -169,7 +168,6 @@
((optinfo->hdrlen == hdrlen) ^
!!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
- temp = len = 0;
ptr += 2;
hdrlen -= 2;
if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){
@@ -180,48 +178,52 @@
DEBUGP("Strict ");
DEBUGP("#%d ",optinfo->optsnr);
for(temp=0; temp<optinfo->optsnr; temp++){
- optdesc = (void *)(skb->data)+ptr;
+ /* type field exists ? */
+ if (ptr > skb->len - 1 || hdrlen < 1)
+ break;
+ opttype = (void *)(skb->data + ptr);
+
/* Type check */
- if ( (unsigned char)*optdesc !=
- (optinfo->opts[temp] & 0xFF00)>>8 ){
+ if (*opttype != (optinfo->opts[temp] & 0xFF00)>>8){
DEBUGP("Tbad %02X %02X\n",
- (unsigned char)*optdesc,
- (optinfo->opts[temp] &
- 0xFF00)>>8);
+ *opttype,
+ (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 (*opttype) {
+ u16 spec_len;
+
+ /* length field exists ? */
+ if (ptr > skb->len - 2 || hdrlen < 2)
+ break;
+ optlen = *((u8 *)(skb->data + ptr + 1));
+ spec_len = optinfo->opts[temp] & 0x00FF;
+
+ if (spec_len != 0x00FF && spec_len != optlen) {
+ DEBUGP("Lbad %02X %04X\n", optlen,
+ spec_len);
return 0;
- } else {
- DEBUGP("Lok ");
}
- }
- /* Step to the next */
- if ((unsigned char)*optdesc == 0){
- DEBUGP("PAD0 \n");
- ptr++;
- hdrlen--;
+ DEBUGP("Lok ");
+ optlen += 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 -urN linux/net/ipv6/netfilter/ip6t_esp.c
linux/net/ipv6/netfilter/ip6t_esp.c
--- linux/net/ipv6/netfilter/ip6t_esp.c 2003/08/13 17:19:31 1.4.2.2
+++ linux/net/ipv6/netfilter/ip6t_esp.c 2005/01/20 02:19:25 1.4.2.3
@@ -22,6 +22,7 @@
struct esphdr {
__u32 spi;
+ __u32 seq_no;
};
/* Returns 1 if the spi is matched by the range, 0 otherwise */
diff -urN linux/net/ipv6/netfilter/ip6t_eui64.c
linux/net/ipv6/netfilter/ip6t_eui64.c
--- linux/net/ipv6/netfilter/ip6t_eui64.c 2002/09/11 12:45:45 1.1.2.1
+++ linux/net/ipv6/netfilter/ip6t_eui64.c 2005/01/20 02:19:25 1.1.2.2
@@ -58,7 +58,7 @@
{
if (hook_mask
& ~((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_IN) |
- (1 << NF_IP6_PRE_ROUTING) )) {
+ (1 << NF_IP6_FORWARD))) {
printk("ip6t_eui64: only valid for PRE_ROUTING, LOCAL_IN or
FORWARD.\n");
return 0;
}
diff -urN linux/net/ipv6/netfilter/ip6t_frag.c
linux/net/ipv6/netfilter/ip6t_frag.c
--- linux/net/ipv6/netfilter/ip6t_frag.c 2003/08/13 17:19:31 1.4.2.2
+++ linux/net/ipv6/netfilter/ip6t_frag.c 2005/01/20 02:19:25 1.4.2.3
@@ -6,8 +6,6 @@
#include <net/checksum.h>
#include <net/ipv6.h>
-#include <asm/byteorder.h>
-
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter_ipv6/ip6t_frag.h>
@@ -22,28 +20,7 @@
#define DEBUGP(format, args...)
#endif
-#if 0
-#if BYTE_ORDER == BIG_ENDIAN
-#define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */
-#define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */
-#define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */
-#else /* BYTE_ORDER == LITTLE_ENDIAN */
-#define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */
-#define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */
-#define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */
-#endif
-#endif
-
-#define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */
-#define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */
-#define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */
-
-struct fraghdr {
- __u8 nexthdr;
- __u8 hdrlen;
- __u16 info;
- __u32 id;
-};
+#define IP6_MF 0x0001
/* Returns 1 if the id is matched by the range, 0 otherwise */
static inline int
@@ -67,7 +44,7 @@
u_int16_t datalen,
int *hotdrop)
{
- struct fraghdr *frag = NULL;
+ struct frag_hdr *frag = NULL;
const struct ip6t_frag *fraginfo = matchinfo;
unsigned int temp;
int len;
@@ -100,7 +77,7 @@
break;
}
- hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
+ hdr=(struct ipv6_opt_hdr *)(skb->data+ptr);
/* Calculate the header length */
if (nexthdr == NEXTHDR_FRAGMENT) {
@@ -143,59 +120,62 @@
/* FRAG header not found */
if ( temp != MASK_FRAGMENT ) return 0;
- if (len < (int)sizeof(struct fraghdr)){
+ if (len < sizeof(struct frag_hdr)){
*hotdrop = 1;
return 0;
}
- frag = (struct fraghdr *) (skb->data + ptr);
+ frag = (struct frag_hdr *) (skb->data + ptr);
- DEBUGP("IPv6 FRAG LEN %u %u ", hdrlen, frag->hdrlen);
- DEBUGP("INFO %04X ", frag->info);
- DEBUGP("OFFSET %04X ", frag->info & IP6F_OFF_MASK);
- DEBUGP("RES %04X ", frag->info & IP6F_RESERVED_MASK);
- DEBUGP("MF %04X ", frag->info & IP6F_MORE_FRAG);
- DEBUGP("ID %u %08X\n", ntohl(frag->id), ntohl(frag->id));
+ 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("IPv6 FRAG id %02X ",
(id_match(fraginfo->ids[0], fraginfo->ids[1],
- ntohl(frag->id),
+ ntohl(frag->identification),
!!(fraginfo->invflags & IP6T_FRAG_INV_IDS))));
- DEBUGP("len %02X %04X %02X ",
- fraginfo->hdrlen, hdrlen,
- (!fraginfo->hdrlen ||
- (fraginfo->hdrlen == hdrlen) ^
- !!(fraginfo->invflags & IP6T_FRAG_INV_LEN)));
- DEBUGP("res %02X %02X %02X ",
- (fraginfo->flags & IP6T_FRAG_RES), frag->info &
IP6F_RESERVED_MASK,
- !((fraginfo->flags & IP6T_FRAG_RES) && (frag->info &
IP6F_RESERVED_MASK)));
+ DEBUGP("res %02X %02X%04X %02X ",
+ (fraginfo->flags & IP6T_FRAG_RES), frag->reserved,
+ ntohs(frag->frag_off) & 0x6,
+ !((fraginfo->flags & IP6T_FRAG_RES)
+ && (frag->reserved || (ntohs(frag->frag_off) & 0x6))));
DEBUGP("first %02X %02X %02X ",
- (fraginfo->flags & IP6T_FRAG_FST), frag->info &
IP6F_OFF_MASK,
- !((fraginfo->flags & IP6T_FRAG_FST) && (frag->info &
IP6F_OFF_MASK)));
+ (fraginfo->flags & IP6T_FRAG_FST),
+ ntohs(frag->frag_off) & ~0x7,
+ !((fraginfo->flags & IP6T_FRAG_FST)
+ && (ntohs(frag->frag_off) & ~0x7)));
DEBUGP("mf %02X %02X %02X ",
- (fraginfo->flags & IP6T_FRAG_MF), frag->info &
IP6F_MORE_FRAG,
- !((fraginfo->flags & IP6T_FRAG_MF) && !((frag->info &
IP6F_MORE_FRAG))));
+ (fraginfo->flags & IP6T_FRAG_MF),
+ ntohs(frag->frag_off) & IP6_MF,
+ !((fraginfo->flags & IP6T_FRAG_MF)
+ && !((ntohs(frag->frag_off) & IP6_MF))));
DEBUGP("last %02X %02X %02X\n",
- (fraginfo->flags & IP6T_FRAG_NMF), frag->info &
IP6F_MORE_FRAG,
- !((fraginfo->flags & IP6T_FRAG_NMF) && (frag->info &
IP6F_MORE_FRAG)));
+ (fraginfo->flags & IP6T_FRAG_NMF),
+ ntohs(frag->frag_off) & IP6_MF,
+ !((fraginfo->flags & IP6T_FRAG_NMF)
+ && (ntohs(frag->frag_off) & IP6_MF)));
return (frag != NULL)
&&
(id_match(fraginfo->ids[0], fraginfo->ids[1],
- ntohl(frag->id),
+ ntohl(frag->identification),
!!(fraginfo->invflags & IP6T_FRAG_INV_IDS)))
&&
- (!fraginfo->hdrlen ||
- (fraginfo->hdrlen == hdrlen) ^
- !!(fraginfo->invflags & IP6T_FRAG_INV_LEN))
- &&
- !((fraginfo->flags & IP6T_FRAG_RES) && (frag->info &
IP6F_RESERVED_MASK))
+ !((fraginfo->flags & IP6T_FRAG_RES)
+ && (frag->reserved || (ntohs(frag->frag_off) & 0x6)))
&&
- !((fraginfo->flags & IP6T_FRAG_FST) && (frag->info &
IP6F_OFF_MASK))
+ !((fraginfo->flags & IP6T_FRAG_FST)
+ && (ntohs(frag->frag_off) & ~0x7))
&&
- !((fraginfo->flags & IP6T_FRAG_MF) && !((frag->info &
IP6F_MORE_FRAG)))
+ !((fraginfo->flags & IP6T_FRAG_MF)
+ && !(ntohs(frag->frag_off) & IP6_MF))
&&
- !((fraginfo->flags & IP6T_FRAG_NMF) && (frag->info &
IP6F_MORE_FRAG));
+ !((fraginfo->flags & IP6T_FRAG_NMF)
+ && (ntohs(frag->frag_off) & IP6_MF));
}
/* Called when user tries to insert an entry of this type. */
diff -urN linux/net/ipv6/netfilter/ip6t_hbh.c
linux/net/ipv6/netfilter/ip6t_hbh.c
--- linux/net/ipv6/netfilter/ip6t_hbh.c 2003/07/05 03:23:48 1.3.2.1
+++ linux/net/ipv6/netfilter/ip6t_hbh.c 2005/01/20 02:19:25 1.3.2.2
@@ -11,8 +11,6 @@
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <linux/netfilter_ipv6/ip6t_opts.h>
-#define LOW(n) (n & 0x00FF)
-
#define HOPBYHOP 1
EXPORT_NO_SYMBOLS;
@@ -40,8 +38,8 @@
* 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
*/
@@ -64,7 +62,8 @@
unsigned int ptr;
unsigned int hdrlen = 0;
unsigned int ret = 0;
- u_int16_t *optdesc = NULL;
+ u8 *opttype = NULL;
+ unsigned int optlen;
/* type of the 1st exthdr */
nexthdr = skb->nh.ipv6h->nexthdr;
@@ -91,7 +90,7 @@
break;
}
- hdr=(void *)(skb->data)+ptr;
+ hdr = (void *)(skb->data + ptr);
/* Calculate the header length */
if (nexthdr == NEXTHDR_FRAGMENT) {
@@ -153,7 +152,7 @@
return 0;
}
- optsh=(void *)(skb->data)+ptr;
+ optsh = (void *)(skb->data + ptr);
DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, optsh->hdrlen);
@@ -169,7 +168,6 @@
((optinfo->hdrlen == hdrlen) ^
!!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
- temp = len = 0;
ptr += 2;
hdrlen -= 2;
if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){
@@ -180,48 +178,52 @@
DEBUGP("Strict ");
DEBUGP("#%d ",optinfo->optsnr);
for(temp=0; temp<optinfo->optsnr; temp++){
- optdesc = (void *)(skb->data)+ptr;
+ /* type field exists ? */
+ if (ptr > skb->len - 1 || hdrlen < 1)
+ break;
+ opttype = (void *)(skb->data + ptr);
+
/* Type check */
- if ( (unsigned char)*optdesc !=
- (optinfo->opts[temp] & 0xFF00)>>8 ){
+ if (*opttype != (optinfo->opts[temp] & 0xFF00)>>8){
DEBUGP("Tbad %02X %02X\n",
- (unsigned char)*optdesc,
- (optinfo->opts[temp] &
- 0xFF00)>>8);
+ *opttype,
+ (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 (*opttype) {
+ u16 spec_len;
+
+ /* length field exists ? */
+ if (ptr > skb->len - 2 || hdrlen < 2)
+ break;
+ optlen = *((u8 *)(skb->data + ptr + 1));
+ spec_len = optinfo->opts[temp] & 0x00FF;
+
+ if (spec_len != 0x00FF && spec_len != optlen) {
+ DEBUGP("Lbad %02X %04X\n", optlen,
+ spec_len);
return 0;
- } else {
- DEBUGP("Lok ");
}
- }
- /* Step to the next */
- if ((unsigned char)*optdesc == 0){
- DEBUGP("PAD0 \n");
- ptr++;
- hdrlen--;
+ DEBUGP("Lok ");
+ optlen += 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 -urN linux/net/ipv6/netfilter/ip6t_ipv6header.c
linux/net/ipv6/netfilter/ip6t_ipv6header.c
--- linux/net/ipv6/netfilter/ip6t_ipv6header.c 2003/11/17 01:07:48 1.4.2.3
+++ linux/net/ipv6/netfilter/ip6t_ipv6header.c 2005/01/20 02:19:25 1.4.2.4
@@ -63,7 +63,7 @@
break;
}
- hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
+ hdr=(struct ipv6_opt_hdr *)(skb->data+ptr);
/* Calculate the header length */
if (nexthdr == NEXTHDR_FRAGMENT) {
@@ -107,10 +107,14 @@
temp |= MASK_PROTO;
if (info->modeflag)
- return (!( (temp & info->matchflags)
- ^ info->matchflags) ^ info->invflags);
- else
- return (!( temp ^ info->matchflags) ^ info->invflags);
+ return !((temp ^ info->matchflags ^ info->invflags)
+ & info->matchflags);
+ else {
+ if (info->invflags)
+ return temp != info->matchflags;
+ else
+ return temp == info->matchflags;
+ }
}
static int
@@ -120,11 +124,17 @@
unsigned int matchsize,
unsigned int hook_mask)
{
+ const struct ip6t_ipv6header_info *info = matchinfo;
+
/* Check for obvious errors */
/* This match is valid in all hooks! */
- if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info))) {
+ if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info)))
+ return 0;
+
+ /* invflags is 0 or 0xff in hard mode */
+ if ((!info->modeflag) && info->invflags != 0x00
+ && info->invflags != 0xFF)
return 0;
- }
return 1;
}
diff -urN linux/net/ipv6/netfilter/ip6t_multiport.c
linux/net/ipv6/netfilter/ip6t_multiport.c
--- linux/net/ipv6/netfilter/ip6t_multiport.c 2001/11/06 07:56:17 1.2
+++ linux/net/ipv6/netfilter/ip6t_multiport.c 2005/01/20 02:19:25 1.2.2.1
@@ -74,9 +74,12 @@
{
const struct ip6t_multiport *multiinfo = matchinfo;
+ if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_multiport)))
+ return 0;
+
/* Must specify proto == TCP/UDP, no unknown flags or bad count */
return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
- && !(ip->flags & IP6T_INV_PROTO)
+ && !(ip->invflags & IP6T_INV_PROTO)
&& matchsize == IP6T_ALIGN(sizeof(struct ip6t_multiport))
&& (multiinfo->flags == IP6T_MULTIPORT_SOURCE
|| multiinfo->flags == IP6T_MULTIPORT_DESTINATION
diff -urN linux/net/ipv6/netfilter/ip6t_rt.c linux/net/ipv6/netfilter/ip6t_rt.c
--- linux/net/ipv6/netfilter/ip6t_rt.c 2003/08/13 17:19:31 1.4.2.2
+++ linux/net/ipv6/netfilter/ip6t_rt.c 2005/01/20 02:19:25 1.4.2.3
@@ -78,7 +78,7 @@
break;
}
- hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
+ hdr=(struct ipv6_opt_hdr *)(skb->data+ptr);
/* Calculate the header length */
if (nexthdr == NEXTHDR_FRAGMENT) {
@@ -135,11 +135,11 @@
DEBUGP("IPv6 RT LEN %u %u ", hdrlen, route->hdrlen);
DEBUGP("TYPE %04X ", route->type);
- DEBUGP("SGS_LEFT %u %08X\n", ntohl(route->segments_left),
ntohl(route->segments_left));
+ DEBUGP("SGS_LEFT %u %02X\n", route->segments_left,
route->segments_left);
DEBUGP("IPv6 RT segsleft %02X ",
(segsleft_match(rtinfo->segsleft[0],
rtinfo->segsleft[1],
- ntohl(route->segments_left),
+ route->segments_left,
!!(rtinfo->invflags & IP6T_RT_INV_SGS))));
DEBUGP("type %02X %02X %02X ",
rtinfo->rt_type, route->type,
@@ -158,7 +158,7 @@
ret = (route != NULL)
&&
(segsleft_match(rtinfo->segsleft[0],
rtinfo->segsleft[1],
- ntohl(route->segments_left),
+ route->segments_left,
!!(rtinfo->invflags & IP6T_RT_INV_SGS)))
&&
(!(rtinfo->flags & IP6T_RT_LEN) ||
diff -urN linux/net/sched/sch_dsmark.c linux/net/sched/sch_dsmark.c
--- linux/net/sched/sch_dsmark.c 2004/11/19 00:29:09 1.7.2.6
+++ linux/net/sched/sch_dsmark.c 2005/01/20 02:19:26 1.7.2.7
@@ -13,6 +13,7 @@
#include <linux/rtnetlink.h>
#include <net/pkt_sched.h>
#include <net/dsfield.h>
+#include <net/inet_ecn.h>
#include <asm/byteorder.h>
@@ -196,10 +197,12 @@
if (p->set_tc_index) {
switch (skb->protocol) {
case __constant_htons(ETH_P_IP):
- skb->tc_index = ipv4_get_dsfield(skb->nh.iph);
+ skb->tc_index = ipv4_get_dsfield(skb->nh.iph)
+ & ~INET_ECN_MASK;
break;
case __constant_htons(ETH_P_IPV6):
- skb->tc_index = ipv6_get_dsfield(skb->nh.ipv6h);
+ skb->tc_index = ipv6_get_dsfield(skb->nh.ipv6h)
+ & ~INET_ECN_MASK;
break;
default:
skb->tc_index = 0;
diff -urN linux/net/sctp/associola.c linux/net/sctp/associola.c
--- linux/net/sctp/associola.c 2004/11/19 00:29:09 1.19.2.5
+++ linux/net/sctp/associola.c 2005/01/20 02:19:26 1.19.2.6
@@ -66,33 +66,8 @@
/* 1st Level Abstractions. */
-/* Allocate and initialize a new association */
-struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep,
- const struct sock *sk,
- sctp_scope_t scope, int gfp)
-{
- struct sctp_association *asoc;
-
- asoc = t_new(struct sctp_association, gfp);
- if (!asoc)
- goto fail;
-
- if (!sctp_association_init(asoc, ep, sk, scope, gfp))
- goto fail_init;
-
- asoc->base.malloced = 1;
- SCTP_DBG_OBJCNT_INC(assoc);
-
- return asoc;
-
-fail_init:
- kfree(asoc);
-fail:
- return NULL;
-}
-
/* Initialize a new association from provided memory. */
-struct sctp_association *sctp_association_init(struct sctp_association *asoc,
+static struct sctp_association *sctp_association_init(struct sctp_association
*asoc,
const struct sctp_endpoint *ep,
const struct sock *sk,
sctp_scope_t scope,
@@ -182,10 +157,10 @@
* RFC 6 - A SCTP receiver MUST be able to receive a minimum of
* 1500 bytes in one SCTP packet.
*/
- if (sk->sk_rcvbuf < SCTP_DEFAULT_MINWINDOW)
+ if (sk->rcvbuf < SCTP_DEFAULT_MINWINDOW)
asoc->rwnd = SCTP_DEFAULT_MINWINDOW;
else
- asoc->rwnd = sk->sk_rcvbuf;
+ asoc->rwnd = sk->rcvbuf;
asoc->a_rwnd = asoc->rwnd;
@@ -204,6 +179,7 @@
asoc->c.peer_vtag = 0;
asoc->c.my_ttag = 0;
asoc->c.peer_ttag = 0;
+ asoc->c.my_port = ep->base.bind_addr.port;
asoc->c.initial_tsn = sctp_generate_tsn(ep);
@@ -296,6 +272,31 @@
return NULL;
}
+/* Allocate and initialize a new association */
+struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep,
+ const struct sock *sk,
+ sctp_scope_t scope, int gfp)
+{
+ struct sctp_association *asoc;
+
+ asoc = t_new(struct sctp_association, gfp);
+ if (!asoc)
+ goto fail;
+
+ if (!sctp_association_init(asoc, ep, sk, scope, gfp))
+ goto fail_init;
+
+ asoc->base.malloced = 1;
+ SCTP_DBG_OBJCNT_INC(assoc);
+
+ return asoc;
+
+fail_init:
+ kfree(asoc);
+fail:
+ return NULL;
+}
+
/* Free this association if possible. There may still be users, so
* the actual deallocation may be delayed.
*/
@@ -310,7 +311,7 @@
/* Decrement the backlog value for a TCP-style listening socket. */
if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
- sk->sk_ack_backlog--;
+ sk->ack_backlog--;
/* Mark as dead, so other users can know this structure is
* going away.
@@ -496,7 +497,6 @@
peer->partial_bytes_acked = 0;
peer->flight_size = 0;
- peer->error_threshold = peer->max_retrans;
/* By default, enable heartbeat for peer address. */
peer->hb_allowed = 1;
@@ -507,7 +507,7 @@
peer->hb_interval =
SCTP_MSECS_TO_JIFFIES(sp->paddrparam.spp_hbinterval);
/* Set the path max_retrans. */
- peer->max_retrans = asoc->max_retrans;
+ peer->max_retrans = sp->paddrparam.spp_pathmaxrxt;
/* Set the transport's RTO.initial value */
peer->rto = asoc->rto_initial;
@@ -710,18 +710,6 @@
return retval;
}
-/* Allocate 'num' TSNs by incrementing the association's TSN by num. */
-__u32 sctp_association_get_tsn_block(struct sctp_association *asoc, int num)
-{
- __u32 retval = asoc->next_tsn;
-
- asoc->next_tsn += num;
- asoc->unack_data += num;
-
- return retval;
-}
-
-
/* Compare two addresses to see if they match. Wildcard addresses
* only match themselves.
*/
@@ -756,14 +744,6 @@
return chunk;
}
-/* Use this function for the packet prepend callback when no ECNE
- * packet is desired (e.g. some packets don't like to be bundled).
- */
-struct sctp_chunk *sctp_get_no_prepend(struct sctp_association *asoc)
-{
- return NULL;
-}
-
/*
* Find which transport this TSN was sent on.
*/
@@ -877,7 +857,8 @@
struct sctp_chunk *chunk;
struct sock *sk;
struct sctp_inq *inqueue;
- int state, subtype;
+ int state;
+ sctp_subtype_t subtype;
int error = 0;
/* The association should be held so we should be safe. */
@@ -887,7 +868,7 @@
inqueue = &asoc->base.inqueue;
while (NULL != (chunk = sctp_inq_pop(inqueue))) {
state = asoc->state;
- subtype = chunk->chunk_hdr->type;
+ subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
/* Remember where the last DATA chunk came from so we
* know where to send the SACK.
@@ -901,7 +882,7 @@
chunk->transport->last_time_heard = jiffies;
/* Run through the state machine. */
- error = sctp_do_sm(SCTP_EVENT_T_CHUNK, SCTP_ST_CHUNK(subtype),
+ error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype,
state, ep, asoc, chunk, GFP_ATOMIC);
/* Check to see if the association is freed in response to
@@ -930,7 +911,7 @@
/* Decrement the backlog value for a TCP-style socket. */
if (sctp_style(oldsk, TCP))
- oldsk->sk_ack_backlog--;
+ oldsk->ack_backlog--;
/* Release references to the old endpoint and the sock. */
sctp_endpoint_put(assoc->ep);
@@ -1112,7 +1093,7 @@
case SCTP_STATE_SHUTDOWN_SENT:
if ((asoc->rwnd > asoc->a_rwnd) &&
((asoc->rwnd - asoc->a_rwnd) >=
- min_t(__u32, (asoc->base.sk->sk_rcvbuf >> 1), asoc->pmtu)))
+ min_t(__u32, (asoc->base.sk->rcvbuf >> 1), asoc->pmtu)))
return 1;
break;
default:
@@ -1195,7 +1176,7 @@
* the endpoint.
*/
scope = sctp_scope(&asoc->peer.active_path->ipaddr);
- flags = (PF_INET6 == asoc->base.sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0;
+ flags = (PF_INET6 == asoc->base.sk->family) ? SCTP_ADDR6_ALLOWED : 0;
if (asoc->peer.ipv4_address)
flags |= SCTP_ADDR4_PEERSUPP;
if (asoc->peer.ipv6_address)
diff -urN linux/net/sctp/bind_addr.c linux/net/sctp/bind_addr.c
--- linux/net/sctp/bind_addr.c 2004/04/16 03:14:22 1.13.2.2
+++ linux/net/sctp/bind_addr.c 2005/01/20 02:19:26 1.13.2.3
@@ -104,23 +104,6 @@
return error;
}
-/* Create a new SCTP_bind_addr from nothing. */
-struct sctp_bind_addr *sctp_bind_addr_new(int gfp)
-{
- struct sctp_bind_addr *retval;
-
- retval = t_new(struct sctp_bind_addr, gfp);
- if (!retval)
- goto nomem;
-
- sctp_bind_addr_init(retval, 0);
- retval->malloced = 1;
- SCTP_DBG_OBJCNT_INC(bind_addr);
-
-nomem:
- return retval;
-}
-
/* Initialize the SCTP_bind_addr structure for either an endpoint or
* an association.
*/
diff -urN linux/net/sctp/chunk.c linux/net/sctp/chunk.c
--- linux/net/sctp/chunk.c 2004/08/14 18:39:05 1.2.2.2
+++ linux/net/sctp/chunk.c 2005/01/20 02:19:26 1.2.2.3
@@ -51,7 +51,7 @@
*/
/* Initialize datamsg from memory. */
-void sctp_datamsg_init(struct sctp_datamsg *msg)
+static void sctp_datamsg_init(struct sctp_datamsg *msg)
{
atomic_set(&msg->refcnt, 1);
msg->send_failed = 0;
@@ -62,7 +62,7 @@
}
/* Allocate and initialize datamsg. */
-struct sctp_datamsg *sctp_datamsg_new(int gfp)
+SCTP_STATIC struct sctp_datamsg *sctp_datamsg_new(int gfp)
{
struct sctp_datamsg *msg;
msg = kmalloc(sizeof(struct sctp_datamsg), gfp);
@@ -124,7 +124,7 @@
}
/* Hold a reference. */
-void sctp_datamsg_hold(struct sctp_datamsg *msg)
+static void sctp_datamsg_hold(struct sctp_datamsg *msg)
{
atomic_inc(&msg->refcnt);
}
@@ -151,7 +151,7 @@
}
/* Assign a chunk to this datamsg. */
-void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk *chunk)
+static void sctp_datamsg_assign(struct sctp_datamsg *msg, struct sctp_chunk
*chunk)
{
sctp_datamsg_hold(msg);
chunk->msg = msg;
diff -urN linux/net/sctp/command.c linux/net/sctp/command.c
--- linux/net/sctp/command.c 2003/11/17 01:07:48 1.4.2.1
+++ linux/net/sctp/command.c 2005/01/20 02:19:26 1.4.2.2
@@ -42,17 +42,6 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
-/* Create a new sctp_command_sequence. */
-sctp_cmd_seq_t *sctp_new_cmd_seq(int gfp)
-{
- sctp_cmd_seq_t *retval = t_new(sctp_cmd_seq_t, gfp);
-
- if (retval)
- sctp_init_cmd_seq(retval);
-
- return retval;
-}
-
/* Initialize a block of memory as a command sequence. */
int sctp_init_cmd_seq(sctp_cmd_seq_t *seq)
{
@@ -77,13 +66,6 @@
return 0;
}
-/* Rewind an sctp_cmd_seq_t to iterate from the start. */
-int sctp_rewind_sequence(sctp_cmd_seq_t *seq)
-{
- seq->next_cmd = 0;
- return 1; /* We always succeed. */
-}
-
/* Return the next command structure in a sctp_cmd_seq.
* Returns NULL at the end of the sequence.
*/
@@ -97,8 +79,3 @@
return retval;
}
-/* Dispose of a command sequence. */
-void sctp_free_cmd_seq(sctp_cmd_seq_t *seq)
-{
- kfree(seq);
-}
diff -urN linux/net/sctp/debug.c linux/net/sctp/debug.c
--- linux/net/sctp/debug.c 2004/08/14 18:39:05 1.5.2.3
+++ linux/net/sctp/debug.c 2005/01/20 02:19:26 1.5.2.4
@@ -98,23 +98,6 @@
return "unknown chunk";
}
-/* These are printable form of variable-length parameters. */
-const char *sctp_param_tbl[SCTP_PARAM_ECN_CAPABLE + 1] = {
- "",
- "PARAM_HEARTBEAT_INFO",
- "",
- "",
- "",
- "PARAM_IPV4_ADDRESS",
- "PARAM_IPV6_ADDRESS",
- "PARAM_STATE_COOKIE",
- "PARAM_UNRECOGNIZED_PARAMETERS",
- "PARAM_COOKIE_PRESERVATIVE",
- "",
- "PARAM_HOST_NAME_ADDRESS",
- "PARAM_SUPPORTED_ADDRESS_TYPES",
-};
-
/* These are printable forms of the states. */
const char *sctp_state_tbl[SCTP_STATE_NUM_STATES] = {
"STATE_EMPTY",
@@ -171,6 +154,7 @@
static const char *sctp_other_tbl[] = {
"NO_PENDING_TSN",
+ "ICMP_PROTO_UNREACH",
};
/* Lookup "other" debug name. */
@@ -178,7 +162,7 @@
{
if (id.other < 0)
return "illegal 'other' event";
- if (id.other < SCTP_EVENT_OTHER_MAX)
+ if (id.other <= SCTP_EVENT_OTHER_MAX)
return sctp_other_tbl[id.other];
return "unknown 'other' event";
}
diff -urN linux/net/sctp/endpointola.c linux/net/sctp/endpointola.c
--- linux/net/sctp/endpointola.c 2004/04/16 03:14:22 1.14.2.2
+++ linux/net/sctp/endpointola.c 2005/01/20 02:19:26 1.14.2.3
@@ -63,34 +63,11 @@
/* Forward declarations for internal helpers. */
static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep);
-/* Create a sctp_endpoint with all that boring stuff initialized.
- * Returns NULL if there isn't enough memory.
- */
-struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, int gfp)
-{
- struct sctp_endpoint *ep;
-
- /* Build a local endpoint. */
- ep = t_new(struct sctp_endpoint, gfp);
- if (!ep)
- goto fail;
- if (!sctp_endpoint_init(ep, sk, gfp))
- goto fail_init;
- ep->base.malloced = 1;
- SCTP_DBG_OBJCNT_INC(ep);
- return ep;
-
-fail_init:
- kfree(ep);
-fail:
- return NULL;
-}
-
/*
* Initialize the base fields of the endpoint structure.
*/
-struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
- struct sock *sk, int gfp)
+static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
+ struct sock *sk, int gfp)
{
struct sctp_opt *sp = sctp_sk(sk);
memset(ep, 0, sizeof(struct sctp_endpoint));
@@ -148,8 +125,8 @@
sp->autoclose * HZ;
/* Use SCTP specific send buffer space queues. */
- sk->sk_write_space = sctp_write_space;
- sk->sk_use_write_queue = 1;
+ sk->write_space = sctp_write_space;
+ sk->use_write_queue = 1;
/* Initialize the secret key used with cookie. */
get_random_bytes(&ep->secret_key[0], SCTP_SECRET_SIZE);
@@ -160,6 +137,29 @@
return ep;
}
+/* Create a sctp_endpoint with all that boring stuff initialized.
+ * Returns NULL if there isn't enough memory.
+ */
+struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, int gfp)
+{
+ struct sctp_endpoint *ep;
+
+ /* Build a local endpoint. */
+ ep = t_new(struct sctp_endpoint, gfp);
+ if (!ep)
+ goto fail;
+ if (!sctp_endpoint_init(ep, sk, gfp))
+ goto fail_init;
+ ep->base.malloced = 1;
+ SCTP_DBG_OBJCNT_INC(ep);
+ return ep;
+
+fail_init:
+ kfree(ep);
+fail:
+ return NULL;
+}
+
/* Add an association to an endpoint. */
void sctp_endpoint_add_asoc(struct sctp_endpoint *ep,
struct sctp_association *asoc)
@@ -171,7 +171,7 @@
/* Increment the backlog value for a TCP-style listening socket. */
if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))
- sk->sk_ack_backlog++;
+ sk->ack_backlog++;
}
/* Free the endpoint structure. Delay cleanup until
@@ -184,11 +184,11 @@
}
/* Final destructor for endpoint. */
-void sctp_endpoint_destroy(struct sctp_endpoint *ep)
+static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
{
SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);
- ep->base.sk->sk_state = SCTP_SS_CLOSED;
+ ep->base.sk->state = SCTP_SS_CLOSED;
/* Unlink this endpoint, so we can't find it again! */
sctp_unhash_endpoint(ep);
@@ -257,7 +257,7 @@
* We do a linear search of the associations for this endpoint.
* We return the matching transport address too.
*/
-struct sctp_association *__sctp_endpoint_lookup_assoc(
+static struct sctp_association *__sctp_endpoint_lookup_assoc(
const struct sctp_endpoint *ep,
const union sctp_addr *paddr,
struct sctp_transport **transport)
@@ -345,7 +345,7 @@
sk = ep->base.sk;
while (NULL != (chunk = sctp_inq_pop(inqueue))) {
- subtype.chunk = chunk->chunk_hdr->type;
+ subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
/* We might have grown an association since last we
* looked, so try again.
diff -urN linux/net/sctp/input.c linux/net/sctp/input.c
--- linux/net/sctp/input.c 2004/04/16 03:14:22 1.17.2.2
+++ linux/net/sctp/input.c 2005/01/20 02:19:26 1.17.2.3
@@ -63,11 +63,15 @@
/* Forward declarations for internal helpers. */
static int sctp_rcv_ootb(struct sk_buff *);
-struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
const union sctp_addr *laddr,
const union sctp_addr *paddr,
struct sctp_transport **transportp);
-struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr);
+static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr
*laddr);
+static struct sctp_association *__sctp_lookup_association(
+ const union sctp_addr *local,
+ const union sctp_addr *peer,
+ struct sctp_transport **pt);
/* Calculate the SCTP checksum of an SCTP packet. */
@@ -130,6 +134,10 @@
skb_pull(skb, sizeof(struct sctphdr));
+ /* Make sure we at least have chunk headers worth of data left. */
+ if (skb->len < sizeof(struct sctp_chunkhdr))
+ goto discard_it;
+
family = ipver2af(skb->nh.iph->version);
af = sctp_get_af_specific(family);
if (unlikely(!af))
@@ -278,6 +286,31 @@
}
}
+/*
+ * SCTP Implementer's Guide, 2.37 ICMP handling procedures
+ *
+ * ICMP8) If the ICMP code is a "Unrecognized next header type encountered"
+ * or a "Protocol Unreachable" treat this message as an abort
+ * with the T bit set.
+ *
+ * This function sends an event to the state machine, which will abort the
+ * association.
+ *
+ */
+void sctp_icmp_proto_unreachable(struct sock *sk,
+ struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ struct sctp_transport *t)
+{
+ SCTP_DEBUG_PRINTK("%s\n", __FUNCTION__);
+
+ sctp_do_sm(SCTP_EVENT_T_OTHER,
+ SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
+ asoc->state, asoc->ep, asoc, NULL,
+ GFP_ATOMIC);
+
+}
+
/* Common lookup code for icmp/icmpv6 error handler. */
struct sock *sctp_err_lookup(int family, struct sk_buff *skb,
struct sctphdr *sctphdr,
@@ -320,11 +353,12 @@
}
if (asoc) {
+ sk = asoc->base.sk;
+
if (ntohl(sctphdr->vtag) != asoc->c.peer_vtag) {
ICMP_INC_STATS_BH(IcmpInErrors);
goto out;
}
- sk = asoc->base.sk;
} else
sk = ep->base.sk;
@@ -426,7 +460,13 @@
sctp_icmp_frag_needed(sk, asoc, transport, info);
goto out_unlock;
}
-
+ else {
+ if (ICMP_PROT_UNREACH == code) {
+ sctp_icmp_proto_unreachable(sk, ep, asoc,
+ transport);
+ goto out_unlock;
+ }
+ }
err = icmp_err_convert[code].errno;
break;
case ICMP_TIME_EXCEEDED:
@@ -444,10 +484,10 @@
inet = inet_sk(sk);
if (!sock_owned_by_user(sk) && inet->recverr) {
- sk->sk_err = err;
- sk->sk_error_report(sk);
+ sk->err = err;
+ sk->error_report(sk);
} else { /* Only an error on timeout */
- sk->sk_err_soft = err;
+ sk->err_soft = err;
}
out_unlock:
@@ -473,10 +513,10 @@
sctp_errhdr_t *err;
ch = (sctp_chunkhdr_t *) skb->data;
+ ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
/* Scan through all the chunks in the packet. */
- do {
- ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
+ while (ch_end > (__u8 *)ch && ch_end < skb->tail) {
/* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the
* receiver MUST silently discard the OOTB packet and take no
@@ -507,7 +547,8 @@
}
ch = (sctp_chunkhdr_t *) ch_end;
- } while (ch_end < skb->tail);
+ ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
+ }
return 0;
@@ -516,7 +557,7 @@
}
/* Insert endpoint into the hash table. */
-void __sctp_hash_endpoint(struct sctp_endpoint *ep)
+static void __sctp_hash_endpoint(struct sctp_endpoint *ep)
{
struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
@@ -546,7 +587,7 @@
}
/* Remove endpoint from the hash table. */
-void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
+static void __sctp_unhash_endpoint(struct sctp_endpoint *ep)
{
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
@@ -578,7 +619,7 @@
}
/* Look up an endpoint. */
-struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr)
+static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr
*laddr)
{
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
@@ -604,16 +645,8 @@
return ep;
}
-/* Add an association to the hash. Local BH-safe. */
-void sctp_hash_established(struct sctp_association *asoc)
-{
- sctp_local_bh_disable();
- __sctp_hash_established(asoc);
- sctp_local_bh_enable();
-}
-
/* Insert association into the hash table. */
-void __sctp_hash_established(struct sctp_association *asoc)
+static void __sctp_hash_established(struct sctp_association *asoc)
{
struct sctp_ep_common **epp;
struct sctp_ep_common *epb;
@@ -636,16 +669,16 @@
sctp_write_unlock(&head->lock);
}
-/* Remove association from the hash table. Local BH-safe. */
-void sctp_unhash_established(struct sctp_association *asoc)
+/* Add an association to the hash. Local BH-safe. */
+void sctp_hash_established(struct sctp_association *asoc)
{
sctp_local_bh_disable();
- __sctp_unhash_established(asoc);
+ __sctp_hash_established(asoc);
sctp_local_bh_enable();
}
/* Remove association from the hash table. */
-void __sctp_unhash_established(struct sctp_association *asoc)
+static void __sctp_unhash_established(struct sctp_association *asoc)
{
struct sctp_hashbucket *head;
struct sctp_ep_common *epb;
@@ -669,8 +702,16 @@
sctp_write_unlock(&head->lock);
}
+/* Remove association from the hash table. Local BH-safe. */
+void sctp_unhash_established(struct sctp_association *asoc)
+{
+ sctp_local_bh_disable();
+ __sctp_unhash_established(asoc);
+ sctp_local_bh_enable();
+}
+
/* Look up an association. */
-struct sctp_association *__sctp_lookup_association(
+static struct sctp_association *__sctp_lookup_association(
const union sctp_addr *local,
const union sctp_addr *peer,
struct sctp_transport **pt)
@@ -707,8 +748,9 @@
}
/* Look up an association. BH-safe. */
+SCTP_STATIC
struct sctp_association *sctp_lookup_association(const union sctp_addr *laddr,
- const union sctp_addr *paddr,
+ const union sctp_addr *paddr,
struct sctp_transport **transportp)
{
struct sctp_association *asoc;
@@ -778,6 +820,14 @@
return NULL;
}
+ /* The code below will attempt to walk the chunk and extract
+ * parameter information. Before we do that, we need to verify
+ * that the chunk length doesn't cause overflow. Otherwise, we'll
+ * walk off the end.
+ */
+ if (WORD_ROUND(ntohs(ch->length)) > skb->len)
+ return NULL;
+
/*
* This code will NOT touch anything inside the chunk--it is
* strictly READ-ONLY.
@@ -815,7 +865,7 @@
}
/* Lookup an association for an inbound skb. */
-struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
+static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb,
const union sctp_addr *paddr,
const union sctp_addr *laddr,
struct sctp_transport **transportp)
diff -urN linux/net/sctp/inqueue.c linux/net/sctp/inqueue.c
--- linux/net/sctp/inqueue.c 2004/11/19 00:29:09 1.4.2.3
+++ linux/net/sctp/inqueue.c 2005/01/20 02:19:26 1.4.2.4
@@ -62,19 +62,6 @@
queue->malloced = 0;
}
-/* Create an initialized sctp_inq. */
-struct sctp_inq *sctp_inq_new(void)
-{
- struct sctp_inq *retval;
-
- retval = t_new(struct sctp_inq, GFP_ATOMIC);
- if (retval) {
- sctp_inq_init(retval);
- retval->malloced = 1;
- }
- return retval;
-}
-
/* Release the memory associated with an SCTP inqueue. */
void sctp_inq_free(struct sctp_inq *queue)
{
@@ -160,14 +147,36 @@
}
chunk->chunk_hdr = ch;
- chunk->chunk_end = ((__u8 *) ch)
- + WORD_ROUND(ntohs(ch->length));
+ chunk->chunk_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
+ /* In the unlikely case of an IP reassembly, the skb could be
+ * non-linear. If so, update chunk_end so that it doesn't go past
+ * the skb->tail.
+ */
+ if (unlikely(skb_is_nonlinear(chunk->skb))) {
+ if (chunk->chunk_end > chunk->skb->tail)
+ chunk->chunk_end = chunk->skb->tail;
+ }
skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t));
chunk->subh.v = NULL; /* Subheader is no longer valid. */
if (chunk->chunk_end < chunk->skb->tail) {
/* This is not a singleton */
chunk->singleton = 0;
+ } else if (chunk->chunk_end > chunk->skb->tail) {
+ /* RFC 2960, Section 6.10 Bundling
+ *
+ * Partial chunks MUST NOT be placed in an SCTP packet.
+ * If the receiver detects a partial chunk, it MUST drop
+ * the chunk.
+ *
+ * Since the end of the chunk is past the end of our buffer
+ * (which contains the whole packet, we can freely discard
+ * the whole packet.
+ */
+ sctp_chunk_free(chunk);
+ chunk = queue->in_progress = NULL;
+
+ return NULL;
} else {
/* We are at the end of the packet, so mark the chunk
* in case we need to send a SACK.
diff -urN linux/net/sctp/ipv6.c linux/net/sctp/ipv6.c
--- linux/net/sctp/ipv6.c 2004/11/19 00:29:09 1.19.2.4
+++ linux/net/sctp/ipv6.c 2005/01/20 02:19:26 1.19.2.5
@@ -95,8 +95,8 @@
ntohs((addr)->s6_addr16[7])
/* ICMP error handler. */
-void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
- int type, int code, int offset, __u32 info)
+SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ int type, int code, int offset, __u32 info)
{
struct inet6_dev *idev;
struct ipv6hdr *iph = (struct ipv6hdr *)skb->data;
@@ -133,6 +133,12 @@
case ICMPV6_PKT_TOOBIG:
sctp_icmp_frag_needed(sk, asoc, transport, ntohl(info));
goto out_unlock;
+ case ICMPV6_PARAMPROB:
+ if (ICMPV6_UNK_NEXTHDR == code) {
+ sctp_icmp_proto_unreachable(sk, ep, asoc, transport);
+ goto out_unlock;
+ }
+ break;
default:
break;
}
@@ -140,10 +146,10 @@
np = inet6_sk(sk);
icmpv6_err_convert(type, code, &err);
if (!sock_owned_by_user(sk) && np->recverr) {
- sk->sk_err = err;
- sk->sk_error_report(sk);
+ sk->err = err;
+ sk->error_report(sk);
} else { /* Only an error on timeout */
- sk->sk_err_soft = err;
+ sk->err_soft = err;
}
out_unlock:
@@ -163,7 +169,7 @@
memset(&fl, 0, sizeof(fl));
- fl.proto = sk->sk_protocol;
+ fl.proto = sk->protocol;
/* Fill in the dest address from the route entry passed with the skb
* and the source address from the transport.
@@ -176,7 +182,7 @@
if (ipv6_addr_type(fl.fl6_src) & IPV6_ADDR_LINKLOCAL)
fl.oif = transport->saddr.v6.sin6_scope_id;
else
- fl.oif = sk->sk_bound_dev_if;
+ fl.oif = sk->bound_dev_if;
fl.uli_u.ports.sport = sk->sport;
fl.uli_u.ports.dport = transport->ipaddr.v6.sin6_port;
@@ -199,9 +205,9 @@
/* Returns the dst cache entry for the given source and destination ip
* addresses.
*/
-struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
- union sctp_addr *daddr,
- union sctp_addr *saddr)
+static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc,
+ union sctp_addr *daddr,
+ union sctp_addr *saddr)
{
struct dst_entry *dst;
struct flowi fl;
@@ -262,8 +268,10 @@
/* Fills in the source address(saddr) based on the destination address(daddr)
* and asoc's bind address list.
*/
-void sctp_v6_get_saddr(struct sctp_association *asoc, struct dst_entry *dst,
- union sctp_addr *daddr, union sctp_addr *saddr)
+static void sctp_v6_get_saddr(struct sctp_association *asoc,
+ struct dst_entry *dst,
+ union sctp_addr *daddr,
+ union sctp_addr *saddr)
{
struct sctp_bind_addr *bp;
rwlock_t *addr_lock;
@@ -588,8 +596,8 @@
}
/* Create and initialize a new sk for the socket to be returned by accept(). */
-struct sock *sctp_v6_create_accept_sk(struct sock *sk,
- struct sctp_association *asoc)
+static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
+ struct sctp_association *asoc)
{
struct sock *newsk;
struct inet_opt *newinet;
@@ -602,18 +610,18 @@
sock_init_data(NULL, newsk);
sk_set_owner(newsk, THIS_MODULE);
- newsk->sk_type = SOCK_STREAM;
+ newsk->type = SOCK_STREAM;
- newsk->sk_prot = sk->sk_prot;
- newsk->sk_no_check = sk->sk_no_check;
- newsk->sk_reuse = sk->sk_reuse;
-
- newsk->sk_destruct = inet_sock_destruct;
- newsk->sk_zapped = 0;
- newsk->sk_family = PF_INET6;
- newsk->sk_protocol = IPPROTO_SCTP;
- newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
- newsk->sk_shutdown = sk->sk_shutdown;
+ newsk->prot = sk->prot;
+ newsk->no_check = sk->no_check;
+ newsk->reuse = sk->reuse;
+
+ newsk->destruct = inet_sock_destruct;
+ newsk->zapped = 0;
+ newsk->family = PF_INET6;
+ newsk->protocol = IPPROTO_SCTP;
+ newsk->backlog_rcv = sk->prot->backlog_rcv;
+ newsk->shutdown = sk->shutdown;
newinet = inet_sk(newsk);
newnp = inet6_sk(newsk);
@@ -648,7 +656,7 @@
atomic_inc(&inet_sock_nr);
#endif
- if (newsk->sk_prot->init(newsk)) {
+ if (newsk->prot->init(newsk)) {
inet_sock_release(newsk);
newsk = NULL;
}
@@ -823,8 +831,8 @@
*/
if (addr->v6.sin6_scope_id)
- sk->sk_bound_dev_if = addr->v6.sin6_scope_id;
- if (!sk->sk_bound_dev_if)
+ sk->bound_dev_if = addr->v6.sin6_scope_id;
+ if (!sk->bound_dev_if)
return 0;
}
af = opt->pf->af;
@@ -853,8 +861,8 @@
*/
if (addr->v6.sin6_scope_id)
- sk->sk_bound_dev_if = addr->v6.sin6_scope_id;
- if (!sk->sk_bound_dev_if)
+ sk->bound_dev_if = addr->v6.sin6_scope_id;
+ if (!sk->bound_dev_if)
return 0;
}
af = opt->pf->af;
diff -urN linux/net/sctp/objcnt.c linux/net/sctp/objcnt.c
--- linux/net/sctp/objcnt.c 2004/08/14 18:39:05 1.4.2.3
+++ linux/net/sctp/objcnt.c 2005/01/20 02:19:26 1.4.2.4
@@ -61,7 +61,7 @@
/* An array to make it easy to pretty print the debug information
* to the proc fs.
*/
-sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = {
+static sctp_dbg_objcnt_entry_t sctp_dbg_objcnt[] = {
SCTP_DBG_OBJCNT_ENTRY(sock),
SCTP_DBG_OBJCNT_ENTRY(ep),
SCTP_DBG_OBJCNT_ENTRY(assoc),
diff -urN linux/net/sctp/output.c linux/net/sctp/output.c
--- linux/net/sctp/output.c 2004/11/19 00:29:09 1.13.2.4
+++ linux/net/sctp/output.c 2005/01/20 02:19:26 1.13.2.5
@@ -161,7 +161,7 @@
if (!packet->has_cookie_echo) {
error = sctp_packet_transmit(packet);
if (error < 0)
- chunk->skb->sk->sk_err = -error;
+ chunk->skb->sk->err = -error;
/* If we have an empty packet, then we can NOT ever
* return PMTU_FULL.
diff -urN linux/net/sctp/outqueue.c linux/net/sctp/outqueue.c
--- linux/net/sctp/outqueue.c 2004/11/19 00:29:09 1.15.2.5
+++ linux/net/sctp/outqueue.c 2005/01/20 02:19:26 1.15.2.6
@@ -200,19 +200,6 @@
return 0;
}
-/* Generate a new outqueue. */
-struct sctp_outq *sctp_outq_new(struct sctp_association *asoc)
-{
- struct sctp_outq *q;
-
- q = t_new(struct sctp_outq, GFP_KERNEL);
- if (q) {
- sctp_outq_init(asoc, q);
- q->malloced = 1;
- }
- return q;
-}
-
/* Initialize an existing sctp_outq. This does the boring stuff.
* You still need to define handlers if you really want to DO
* something with this structure...
@@ -372,7 +359,7 @@
/* Insert a chunk into the sorted list based on the TSNs. The retransmit list
* and the abandoned list are in ascending order.
*/
-void sctp_insert_list(struct list_head *head, struct list_head *new)
+static void sctp_insert_list(struct list_head *head, struct list_head *new)
{
struct list_head *pos;
struct sctp_chunk *nchunk, *lchunk;
@@ -510,7 +497,7 @@
error = sctp_outq_flush(q, /* rtx_timeout */ 1);
if (error)
- q->asoc->base.sk->sk_err = -error;
+ q->asoc->base.sk->err = -error;
}
/*
diff -urN linux/net/sctp/proc.c linux/net/sctp/proc.c
--- linux/net/sctp/proc.c 2004/04/16 03:14:22 1.5.2.2
+++ linux/net/sctp/proc.c 2005/01/20 02:19:26 1.5.2.3
@@ -177,7 +177,7 @@
ep = sctp_ep(epb);
sk = epb->sk;
seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d ", ep, sk,
- sctp_sk(sk)->type, sk->sk_state, hash,
+ sctp_sk(sk)->type, sk->state, hash,
epb->bind_addr.port);
sctp_seq_dump_local_addrs(seq, epb);
seq_printf(seq, "\n");
@@ -240,7 +240,7 @@
sk = epb->sk;
seq_printf(seq,
"%8p %8p %-3d %-3d %-2d %-4d %-5d %-5d ",
- assoc, sk, sctp_sk(sk)->type, sk->sk_state,
+ assoc, sk, sctp_sk(sk)->type, sk->state,
assoc->state, hash, epb->bind_addr.port,
assoc->peer.port);
sctp_seq_dump_local_addrs(seq, epb);
diff -urN linux/net/sctp/protocol.c linux/net/sctp/protocol.c
--- linux/net/sctp/protocol.c 2004/11/19 00:29:09 1.22.2.4
+++ linux/net/sctp/protocol.c 2005/01/20 02:19:26 1.22.2.5
@@ -93,7 +93,7 @@
}
/* Set up the proc fs entry for the SCTP protocol. */
-__init int sctp_proc_init(void)
+static __init int sctp_proc_init(void)
{
if (!proc_net_sctp) {
struct proc_dir_entry *ent;
@@ -122,7 +122,7 @@
* Note: Do not make this __exit as it is used in the init error
* path.
*/
-void sctp_proc_exit(void)
+static void sctp_proc_exit(void)
{
sctp_snmp_proc_exit();
sctp_eps_proc_exit();
@@ -428,9 +428,9 @@
* addresses. If an association is passed, trys to get a dst entry with a
* source address that matches an address in the bind address list.
*/
-struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
- union sctp_addr *daddr,
- union sctp_addr *saddr)
+static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
+ union sctp_addr *daddr,
+ union sctp_addr *saddr)
{
struct rtable *rt;
struct rt_key key;
@@ -520,10 +520,10 @@
/* For v4, the source address is cached in the route entry(dst). So no need
* to cache it separately and hence this is an empty routine.
*/
-void sctp_v4_get_saddr(struct sctp_association *asoc,
- struct dst_entry *dst,
- union sctp_addr *daddr,
- union sctp_addr *saddr)
+static void sctp_v4_get_saddr(struct sctp_association *asoc,
+ struct dst_entry *dst,
+ union sctp_addr *daddr,
+ union sctp_addr *saddr)
{
struct rtable *rt = (struct rtable *)dst;
@@ -547,8 +547,8 @@
}
/* Create and initialize a new sk for the socket returned by accept(). */
-struct sock *sctp_v4_create_accept_sk(struct sock *sk,
- struct sctp_association *asoc)
+static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
+ struct sctp_association *asoc)
{
struct sock *newsk;
struct inet_opt *inet = inet_sk(sk);
@@ -561,18 +561,18 @@
sock_init_data(NULL, newsk);
sk_set_owner(newsk, THIS_MODULE);
- newsk->sk_type = SOCK_STREAM;
+ newsk->type = SOCK_STREAM;
- newsk->sk_prot = sk->sk_prot;
- newsk->sk_no_check = sk->sk_no_check;
- newsk->sk_reuse = sk->sk_reuse;
- newsk->sk_shutdown = sk->sk_shutdown;
-
- newsk->sk_destruct = inet_sock_destruct;
- newsk->sk_zapped = 0;
- newsk->sk_family = PF_INET;
- newsk->sk_protocol = IPPROTO_SCTP;
- newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
+ newsk->prot = sk->prot;
+ newsk->no_check = sk->no_check;
+ newsk->reuse = sk->reuse;
+ newsk->shutdown = sk->shutdown;
+
+ newsk->destruct = inet_sock_destruct;
+ newsk->zapped = 0;
+ newsk->family = PF_INET;
+ newsk->protocol = IPPROTO_SCTP;
+ newsk->backlog_rcv = sk->prot->backlog_rcv;
newinet = inet_sk(newsk);
@@ -597,7 +597,7 @@
atomic_inc(&inet_sock_nr);
#endif
- if (newsk->sk_prot->init(newsk)) {
+ if (newsk->prot->init(newsk)) {
inet_sock_release(newsk);
newsk = NULL;
}
@@ -638,7 +638,7 @@
* Initialize the control inode/socket with a control endpoint data
* structure. This endpoint is reserved exclusively for the OOTB processing.
*/
-int sctp_ctl_sock_init(void)
+static int sctp_ctl_sock_init(void)
{
int err;
sa_family_t family;
@@ -655,7 +655,7 @@
"SCTP: Failed to create the SCTP control socket.\n");
return err;
}
- sctp_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
+ sctp_ctl_socket->sk->allocation = GFP_ATOMIC;
inet_sk(sctp_ctl_socket->sk)->ttl = MAXTTL;
return 0;
@@ -807,7 +807,7 @@
return ip_queue_xmit(skb, ipfragok);
}
-struct sctp_af sctp_ipv4_specific;
+static struct sctp_af sctp_ipv4_specific;
static struct sctp_pf sctp_pf_inet = {
.event_msgname = sctp_inet_event_msgname,
@@ -828,7 +828,7 @@
};
/* Socket operations. */
-struct proto_ops inet_seqpacket_ops = {
+static struct proto_ops inet_seqpacket_ops = {
.family = PF_INET,
.release = inet_release, /* Needs to be wrapped... */
.bind = inet_bind,
@@ -877,7 +877,7 @@
};
/* IPv4 address related functions. */
-struct sctp_af sctp_ipv4_specific = {
+static struct sctp_af sctp_ipv4_specific = {
.sctp_xmit = sctp_v4_xmit,
.setsockopt = ip_setsockopt,
.getsockopt = ip_getsockopt,
@@ -948,7 +948,7 @@
}
/* Initialize the universe into something sensible. */
-__init int sctp_init(void)
+SCTP_STATIC __init int sctp_init(void)
{
int i;
int status = 0;
@@ -1161,7 +1161,7 @@
}
/* Exit handler for the SCTP protocol. */
-__exit void sctp_exit(void)
+SCTP_STATIC __exit void sctp_exit(void)
{
/* BUG. This should probably do something useful like clean
* up all the remaining associations and all that memory.
diff -urN linux/net/sctp/sm_make_chunk.c linux/net/sctp/sm_make_chunk.c
--- linux/net/sctp/sm_make_chunk.c 2004/11/19 00:29:09 1.20.2.4
+++ linux/net/sctp/sm_make_chunk.c 2005/01/20 02:19:26 1.20.2.5
@@ -67,6 +67,19 @@
extern kmem_cache_t *sctp_chunk_cachep;
+SCTP_STATIC
+struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
+ __u8 type, __u8 flags, int paylen);
+static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const struct sctp_chunk *init_chunk,
+ int *cookie_len,
+ const __u8 *raw_addrs, int addrs_len);
+static int sctp_process_param(struct sctp_association *asoc,
+ union sctp_params param,
+ const union sctp_addr *peer_addr,
+ int gfp);
+
/* What was the inbound interface for this chunk? */
int sctp_chunk_iif(const struct sctp_chunk *chunk)
{
@@ -559,52 +572,6 @@
return retval;
}
-/* Make a DATA chunk for the given association. Populate the data
- * payload.
- */
-struct sctp_chunk *sctp_make_datafrag(struct sctp_association *asoc,
- const struct sctp_sndrcvinfo *sinfo,
- int data_len, const __u8 *data,
- __u8 flags, __u16 ssn)
-{
- struct sctp_chunk *retval;
-
- retval = sctp_make_datafrag_empty(asoc, sinfo, data_len, flags, ssn);
- if (retval)
- sctp_addto_chunk(retval, data_len, data);
-
- return retval;
-}
-
-/* Make a DATA chunk for the given association to ride on stream id
- * 'stream', with a payload id of 'payload', and a body of 'data'.
- */
-struct sctp_chunk *sctp_make_data(struct sctp_association *asoc,
- const struct sctp_sndrcvinfo *sinfo,
- int data_len, const __u8 *data)
-{
- struct sctp_chunk *retval = NULL;
-
- retval = sctp_make_data_empty(asoc, sinfo, data_len);
- if (retval)
- sctp_addto_chunk(retval, data_len, data);
- return retval;
-}
-
-/* Make a DATA chunk for the given association to ride on stream id
- * 'stream', with a payload id of 'payload', and a body big enough to
- * hold 'data_len' octets of data. We use this version when we need
- * to build the message AFTER allocating memory.
- */
-struct sctp_chunk *sctp_make_data_empty(struct sctp_association *asoc,
- const struct sctp_sndrcvinfo *sinfo,
- int data_len)
-{
- __u8 flags = SCTP_DATA_NOT_FRAG;
-
- return sctp_make_datafrag_empty(asoc, sinfo, data_len, flags, 0);
-}
-
/* Create a selective ackowledgement (SACK) for the given
* association. This reports on which TSN's we've seen to date,
* including duplicates and gaps.
@@ -881,6 +848,31 @@
return retval;
}
+/* Make an ABORT chunk with a PROTOCOL VIOLATION cause code. */
+struct sctp_chunk *sctp_make_abort_violation(
+ const struct sctp_association *asoc,
+ const struct sctp_chunk *chunk,
+ const __u8 *payload,
+ const size_t paylen)
+{
+ struct sctp_chunk *retval;
+ struct sctp_paramhdr phdr;
+
+ retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen
+ + sizeof(sctp_chunkhdr_t));
+ if (!retval)
+ goto end;
+
+ sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, payload, paylen);
+
+ phdr.type = htons(chunk->chunk_hdr->type);
+ phdr.length = chunk->chunk_hdr->length;
+ sctp_addto_chunk(retval, sizeof(sctp_paramhdr_t), &phdr);
+
+end:
+ return retval;
+}
+
/* Make a HEARTBEAT chunk. */
struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc,
const struct sctp_transport *transport,
@@ -933,7 +925,7 @@
/* Create an Operation Error chunk with the specified space reserved.
* This routine can be used for containing multiple causes in the chunk.
*/
-struct sctp_chunk *sctp_make_op_error_space(
+static struct sctp_chunk *sctp_make_op_error_space(
const struct sctp_association *asoc,
const struct sctp_chunk *chunk,
size_t size)
@@ -1034,7 +1026,6 @@
SCTP_DBG_OBJCNT_INC(chunk);
atomic_set(&retval->refcnt, 1);
-
nodata:
return retval;
}
@@ -1062,6 +1053,7 @@
/* Create a new chunk, setting the type and flags headers from the
* arguments, reserving enough space for a 'paylen' byte payload.
*/
+SCTP_STATIC
struct sctp_chunk *sctp_make_chunk(const struct sctp_association *asoc,
__u8 type, __u8 flags, int paylen)
{
@@ -1261,7 +1253,7 @@
/* Build a cookie representing asoc.
* This INCLUDES the param header needed to put the cookie in the INIT ACK.
*/
-sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
+static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const struct sctp_chunk *init_chunk,
int *cookie_len,
@@ -1409,6 +1401,24 @@
}
no_hmac:
+ /* IG Section 2.35.2:
+ * 3) Compare the port numbers and the verification tag contained
+ * within the COOKIE ECHO chunk to the actual port numbers and the
+ * verification tag within the SCTP common header of the received
+ * packet. If these values do not match the packet MUST be silently
+ * discarded,
+ */
+ if (ntohl(chunk->sctp_hdr->vtag) != bear_cookie->my_vtag) {
+ *error = -SCTP_IERROR_BAD_TAG;
+ goto fail;
+ }
+
+ if (ntohs(chunk->sctp_hdr->source) !=
bear_cookie->peer_addr.v4.sin_port ||
+ ntohs(chunk->sctp_hdr->dest) != bear_cookie->my_port) {
+ *error = -SCTP_IERROR_BAD_PORTS;
+ goto fail;
+ }
+
/* Check to see if the cookie is stale. If there is already
* an association, there is no need to check cookie's expiration
* for init collision case of lost COOKIE ACK.
@@ -1547,6 +1557,30 @@
return 0;
}
+static int sctp_process_inv_paramlength(const struct sctp_association *asoc,
+ struct sctp_paramhdr *param,
+ const struct sctp_chunk *chunk,
+ struct sctp_chunk **errp)
+{
+ char error[] = "The following parameter had invalid length:";
+ size_t payload_len = WORD_ROUND(sizeof(error)) +
+ sizeof(sctp_paramhdr_t);
+
+
+ /* Create an error chunk and fill it in with our payload. */
+ if (!*errp)
+ *errp = sctp_make_op_error_space(asoc, chunk, payload_len);
+
+ if (*errp) {
+ sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, error,
+ sizeof(error));
+ sctp_addto_chunk(*errp, sizeof(sctp_paramhdr_t), param);
+ }
+
+ return 0;
+}
+
+
/* Do not attempt to handle the HOST_NAME parm. However, do
* send back an indicator to the peer.
*/
@@ -1725,6 +1759,18 @@
} /* for (loop through all parameters) */
+ /* There is a possibility that a parameter length was bad and
+ * in that case we would have stoped walking the parameters.
+ * The current param.p would point at the bad one.
+ * Current consensus on the mailing list is to generate a PROTOCOL
+ * VIOLATION error. We build the ERROR chunk here and let the normal
+ * error handling code build and send the packet.
+ */
+ if (param.v < (void*)chunk->chunk_end - sizeof(sctp_paramhdr_t)) {
+ sctp_process_inv_paramlength(asoc, param.p, chunk, errp);
+ return 0;
+ }
+
/* The only missing mandatory param possible today is
* the state cookie for an INIT-ACK chunk.
*/
@@ -1896,8 +1942,10 @@
* work we do. In particular, we should not build transport
* structures for the addresses.
*/
-int sctp_process_param(struct sctp_association *asoc, union sctp_params param,
- const union sctp_addr *peer_addr, int gfp)
+static int sctp_process_param(struct sctp_association *asoc,
+ union sctp_params param,
+ const union sctp_addr *peer_addr,
+ int gfp)
{
union sctp_addr addr;
int i;
@@ -1913,7 +1961,7 @@
*/
switch (param.p->type) {
case SCTP_PARAM_IPV6_ADDRESS:
- if (PF_INET6 != asoc->base.sk->sk_family)
+ if (PF_INET6 != asoc->base.sk->family)
break;
/* Fall through. */
case SCTP_PARAM_IPV4_ADDRESS:
@@ -2062,8 +2110,9 @@
*
* Address Parameter and other parameter will not be wrapped in this function
*/
-struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
- union sctp_addr *addr, int vparam_len)
+static struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
+ union sctp_addr *addr,
+ int vparam_len)
{
sctp_addiphdr_t asconf;
struct sctp_chunk *retval;
@@ -2232,8 +2281,8 @@
*
* Create an ASCONF_ACK chunk with enough space for the parameter responses.
*/
-struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association *asoc,
- __u32 serial, int vparam_len)
+static struct sctp_chunk *sctp_make_asconf_ack(const struct sctp_association
*asoc,
+ __u32 serial, int vparam_len)
{
sctp_addiphdr_t asconf;
struct sctp_chunk *retval;
diff -urN linux/net/sctp/sm_sideeffect.c linux/net/sctp/sm_sideeffect.c
--- linux/net/sctp/sm_sideeffect.c 2004/11/19 00:29:09 1.20.2.4
+++ linux/net/sctp/sm_sideeffect.c 2005/01/20 02:19:26 1.20.2.5
@@ -55,6 +55,24 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
+static int sctp_cmd_interpreter(sctp_event_t event_type,
+ sctp_subtype_t subtype,
+ sctp_state_t state,
+ struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ void *event_arg,
+ sctp_disposition_t status,
+ sctp_cmd_seq_t *commands,
+ int gfp);
+static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
+ sctp_state_t state,
+ struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ void *event_arg,
+ sctp_disposition_t status,
+ sctp_cmd_seq_t *commands,
+ int gfp);
+
/********************************************************************
* Helper functions
********************************************************************/
@@ -134,8 +152,8 @@
}
/* Generate SACK if necessary. We call this at the end of a packet. */
-int sctp_gen_sack(struct sctp_association *asoc, int force,
- sctp_cmd_seq_t *commands)
+static int sctp_gen_sack(struct sctp_association *asoc, int force,
+ sctp_cmd_seq_t *commands)
{
__u32 ctsn, max_tsn_seen;
struct sctp_chunk *sack;
@@ -229,7 +247,7 @@
transport, GFP_ATOMIC);
if (error)
- asoc->base.sk->sk_err = -error;
+ asoc->base.sk->err = -error;
out_unlock:
sctp_bh_unlock_sock(asoc->base.sk);
@@ -269,38 +287,38 @@
(void *)timeout_type, GFP_ATOMIC);
if (error)
- asoc->base.sk->sk_err = -error;
+ asoc->base.sk->err = -error;
out_unlock:
sctp_bh_unlock_sock(asoc->base.sk);
sctp_association_put(asoc);
}
-void sctp_generate_t1_cookie_event(unsigned long data)
+static void sctp_generate_t1_cookie_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *) data;
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T1_COOKIE);
}
-void sctp_generate_t1_init_event(unsigned long data)
+static void sctp_generate_t1_init_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *) data;
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T1_INIT);
}
-void sctp_generate_t2_shutdown_event(unsigned long data)
+static void sctp_generate_t2_shutdown_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *) data;
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T2_SHUTDOWN);
}
-void sctp_generate_t4_rto_event(unsigned long data)
+static void sctp_generate_t4_rto_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *) data;
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_T4_RTO);
}
-void sctp_generate_t5_shutdown_guard_event(unsigned long data)
+static void sctp_generate_t5_shutdown_guard_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *)data;
sctp_generate_timeout_event(asoc,
@@ -308,7 +326,7 @@
} /* sctp_generate_t5_shutdown_guard_event() */
-void sctp_generate_autoclose_event(unsigned long data)
+static void sctp_generate_autoclose_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *) data;
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_AUTOCLOSE);
@@ -345,7 +363,7 @@
transport, GFP_ATOMIC);
if (error)
- asoc->base.sk->sk_err = -error;
+ asoc->base.sk->err = -error;
out_unlock:
sctp_bh_unlock_sock(asoc->base.sk);
@@ -353,7 +371,7 @@
}
/* Inject a SACK Timeout event into the state machine. */
-void sctp_generate_sack_event(unsigned long data)
+static void sctp_generate_sack_event(unsigned long data)
{
struct sctp_association *asoc = (struct sctp_association *) data;
sctp_generate_timeout_event(asoc, SCTP_EVENT_TIMEOUT_SACK);
@@ -397,7 +415,7 @@
asoc->overall_error_count++;
if (transport->active &&
- (transport->error_count++ >= transport->error_threshold)) {
+ (transport->error_count++ >= transport->max_retrans)) {
SCTP_DEBUG_PRINTK("transport_strike: transport "
"IP:%d.%d.%d.%d failed.\n",
NIPQUAD(transport->ipaddr.v4.sin_addr));
@@ -460,9 +478,9 @@
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
- /* Set sk_err to ECONNRESET on a 1-1 style socket. */
+ /* Set sk->err to ECONNRESET on a 1-1 style socket. */
if (!sctp_style(asoc->base.sk, UDP))
- asoc->base.sk->sk_err = ECONNRESET;
+ asoc->base.sk->err = ECONNRESET;
/* SEND_FAILED sent later when cleaning up the association. */
asoc->outqueue.error = error;
@@ -648,16 +666,16 @@
asoc->state = state;
if (sctp_style(sk, TCP)) {
- /* Change the sk->sk_state of a TCP-style socket that has
+ /* Change the sk->state of a TCP-style socket that has
* sucessfully completed a connect() call.
*/
if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED))
- sk->sk_state = SCTP_SS_ESTABLISHED;
+ sk->state = SCTP_SS_ESTABLISHED;
/* Set the RCV_SHUTDOWN flag when a SHUTDOWN is received. */
if (sctp_state(asoc, SHUTDOWN_RECEIVED) &&
sctp_sstate(sk, ESTABLISHED))
- sk->sk_shutdown |= RCV_SHUTDOWN;
+ sk->shutdown |= RCV_SHUTDOWN;
}
if (sctp_state(asoc, ESTABLISHED) ||
@@ -676,7 +694,7 @@
* notifications.
*/
if (!sctp_style(sk, UDP))
- sk->sk_state_change(sk);
+ sk->state_change(sk);
}
}
@@ -691,7 +709,7 @@
* can pick it up later.
*/
if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING) &&
- (!asoc->temp) && (sk->sk_shutdown != SHUTDOWN_MASK))
+ (!asoc->temp) && (sk->shutdown != SHUTDOWN_MASK))
return;
sctp_unhash_established(asoc);
@@ -857,14 +875,14 @@
/*****************************************************************
* This the master state function side effect processing function.
*****************************************************************/
-int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
- sctp_state_t state,
- struct sctp_endpoint *ep,
- struct sctp_association *asoc,
- void *event_arg,
- sctp_disposition_t status,
- sctp_cmd_seq_t *commands,
- int gfp)
+static int sctp_side_effects(sctp_event_t event_type, sctp_subtype_t subtype,
+ sctp_state_t state,
+ struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ void *event_arg,
+ sctp_disposition_t status,
+ sctp_cmd_seq_t *commands,
+ int gfp)
{
int error;
@@ -944,11 +962,15 @@
********************************************************************/
/* This is the side-effect interpreter. */
-int sctp_cmd_interpreter(sctp_event_t event_type, sctp_subtype_t subtype,
- sctp_state_t state, struct sctp_endpoint *ep,
- struct sctp_association *asoc, void *event_arg,
- sctp_disposition_t status, sctp_cmd_seq_t *commands,
- int gfp)
+static int sctp_cmd_interpreter(sctp_event_t event_type,
+ sctp_subtype_t subtype,
+ sctp_state_t state,
+ struct sctp_endpoint *ep,
+ struct sctp_association *asoc,
+ void *event_arg,
+ sctp_disposition_t status,
+ sctp_cmd_seq_t *commands,
+ int gfp)
{
int error = 0;
int force;
diff -urN linux/net/sctp/sm_statefuns.c linux/net/sctp/sm_statefuns.c
--- linux/net/sctp/sm_statefuns.c 2004/11/19 00:29:09 1.20.2.4
+++ linux/net/sctp/sm_statefuns.c 2005/01/20 02:19:26 1.20.2.5
@@ -65,6 +65,53 @@
#include <net/sctp/sm.h>
#include <net/sctp/structs.h>
+static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ struct sctp_chunk *chunk,
+ const void *payload,
+ size_t paylen);
+static int sctp_eat_data(const struct sctp_association *asoc,
+ struct sctp_chunk *chunk,
+ sctp_cmd_seq_t *commands);
+static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association
*asoc,
+ const struct sctp_chunk *chunk);
+static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const struct sctp_chunk *chunk,
+ sctp_cmd_seq_t *commands,
+ struct sctp_chunk *err_chunk);
+static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint
*ep,
+ const struct sctp_association
*asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands);
+static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
+ const struct sctp_association
*asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands);
+static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk);
+
+
+/* Small helper function that checks if the chunk length
+ * is of the appropriate length. The 'required_length' argument
+ * is set to be the size of a specific chunk we are testing.
+ * Return Values: 1 = Valid length
+ * 0 = Invalid length
+ *
+ */
+static inline int
+sctp_chunk_length_valid(struct sctp_chunk *chunk,
+ __u16 required_length)
+{
+ __u16 chunk_length = ntohs(chunk->chunk_hdr->length);
+
+ if (unlikely(chunk_length < required_length))
+ return 0;
+
+ return 1;
+}
+
/**********************************************************
* These are the state functions for handling chunk events.
**********************************************************/
@@ -199,9 +246,14 @@
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
+ *
+ * IG Section 2.11.2
+ * Furthermore, we require that the receiver of an INIT chunk MUST
+ * enforce these rules by silently discarding an arriving packet
+ * with an INIT chunk that is bundled with other chunks.
*/
if (!chunk->singleton)
- return SCTP_DISPOSITION_VIOLATION;
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
/* If the packet is an OOTB packet which is temporarily on the
* control endpoint, respond with an ABORT.
@@ -216,7 +268,7 @@
*/
if (!sctp_sstate(sk, LISTENING) ||
(sctp_style(sk, TCP) &&
- (sk->sk_ack_backlog >= sk->sk_max_ack_backlog)))
+ (sk->ack_backlog >= sk->max_ack_backlog)))
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
@@ -225,6 +277,14 @@
if (chunk->sctp_hdr->vtag != 0)
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+ /* Make sure that the INIT chunk has a valid length.
+ * Normally, this would cause an ABORT with a Protocol Violation
+ * error, but since we don't have an association, we'll
+ * just discard the packet.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_init_chunk_t)))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
/* Verify the INIT chunk before processing it. */
err_chunk = NULL;
if (!sctp_verify_init(asoc, chunk->chunk_hdr->type,
@@ -376,6 +436,13 @@
struct sctp_packet *packet;
sctp_disposition_t ret;
+ if (!sctp_vtag_verify(chunk, asoc))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
+ /* Make sure that the INIT-ACK chunk has a valid length */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_initack_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
@@ -383,9 +450,6 @@
if (!chunk->singleton)
return SCTP_DISPOSITION_VIOLATION;
- if (!sctp_vtag_verify(chunk, asoc))
- return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
-
/* Grab the INIT header. */
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
@@ -542,6 +606,14 @@
if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
return sctp_sf_ootb(ep, asoc, type, arg, commands);
+ /* Make sure that the COOKIE_ECHO chunk has a valid length.
+ * In this case, we check that we have enough for at least a
+ * chunk header. More detailed verification is done
+ * in sctp_unpack_cookie().
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
/* "Decode" the chunk. We have no optional parameters so we
* are in good shape.
*/
@@ -687,6 +759,13 @@
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ /* Verify that the chunk length for the COOKIE-ACK is OK.
+ * If we don't do this, any bundled chunks may be junked.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
/* Reset init error count upon receipt of COOKIE-ACK,
* to avoid problems with the managemement of this
* counter in stale cookie situations when a transition back
@@ -748,11 +827,11 @@
}
/* Generate and sendout a heartbeat packet. */
-sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep,
- const struct sctp_association *asoc,
- const sctp_subtype_t type,
- void *arg,
- sctp_cmd_seq_t *commands)
+static sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands)
{
struct sctp_transport *transport = (struct sctp_transport *) arg;
struct sctp_chunk *reply;
@@ -859,6 +938,11 @@
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ /* Make sure that the HEARTBEAT chunk has a valid length. */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_heartbeat_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
/* 8.3 The receiver of the HEARTBEAT should immediately
* respond with a HEARTBEAT ACK that contains the Heartbeat
* Information field copied from the received HEARTBEAT chunk.
@@ -922,6 +1006,11 @@
if (!sctp_vtag_verify(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ /* Make sure that the HEARTBEAT-ACK chunk has a valid length. */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_heartbeat_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;
from_addr = hbinfo->daddr;
link = sctp_assoc_lookup_paddr(asoc, &from_addr);
@@ -1165,9 +1254,14 @@
/* 6.10 Bundling
* An endpoint MUST NOT bundle INIT, INIT ACK or
* SHUTDOWN COMPLETE with any other chunks.
+ *
+ * IG Section 2.11.2
+ * Furthermore, we require that the receiver of an INIT chunk MUST
+ * enforce these rules by silently discarding an arriving packet
+ * with an INIT chunk that is bundled with other chunks.
*/
if (!chunk->singleton)
- return SCTP_DISPOSITION_VIOLATION;
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
/* 3.1 A packet containing an INIT chunk MUST have a zero Verification
* Tag.
@@ -1175,6 +1269,13 @@
if (chunk->sctp_hdr->vtag != 0)
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
+ /* Make sure that the INIT chunk has a valid length.
+ * In this case, we generate a protocol violation since we have
+ * an association established.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_init_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
/* Grab the INIT header. */
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
@@ -1718,6 +1819,15 @@
char action;
struct sctp_chunk *err_chk_p;
+ /* Make sure that the chunk has a valid length from the protocol
+ * perspective. In this case check to make sure we have at least
+ * enough for the chunk header. Cookie length verification is
+ * done later.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
/* "Decode" the chunk. We have no optional parameters so we
* are in good shape.
*/
@@ -1815,6 +1925,19 @@
if (!sctp_vtag_verify_either(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ /* Make sure that the ABORT chunk has a valid length.
+ * Since this is an ABORT chunk, we have to discard it
+ * because of the following text:
+ * RFC 2960, Section 3.3.7
+ * If an endpoint receives an ABORT with a format error or for an
+ * association that doesn't exist, it MUST silently discard it.
+ * Becasue the length is "invalid", we can't really discard just
+ * as we do not know its true length. So, to be safe, discard the
+ * packet.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
/* Stop the T5-shutdown guard timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));
@@ -1838,6 +1961,19 @@
if (!sctp_vtag_verify_either(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+ /* Make sure that the ABORT chunk has a valid length.
+ * Since this is an ABORT chunk, we have to discard it
+ * because of the following text:
+ * RFC 2960, Section 3.3.7
+ * If an endpoint receives an ABORT with a format error or for an
+ * association that doesn't exist, it MUST silently discard it.
+ * Becasue the length is "invalid", we can't really discard just
+ * as we do not know its true length. So, to be safe, discard the
+ * packet.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
/* Stop the T2-shutdown timer. */
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
@@ -1890,6 +2026,16 @@
struct sctp_chunk *chunk = arg;
sctp_errhdr_t *err;
+ if (!sctp_vtag_verify(chunk, asoc))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
+ /* Make sure that the ERROR chunk has a valid length.
+ * The parameter walking depends on this as well.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_operr_chunk_t)))
+ return sctp_sf_violation_chunklen(ep, asoc, type, arg,
+ commands);
+
/* Process the error here */
/* FUTURE FIXME: When PR-SCTP related and other optional
* parms are emitted, this will have to change to handle multiple
@@ -1900,6 +2046,12 @@
return sctp_sf_do_5_2_6_stale(ep, asoc, type,
arg, commands);
}
+
+ /* It is possible to have malformed error causes, and that
+ * will cause us to end the walk early. However, since
+ * we are discarding the packet, there should be no adverse
+ * affects.
+ */
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
}
@@ -1928,11 +2080,11 @@
*
* The return value is the disposition of the chunk.
*/
-sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
- const struct sctp_association *asoc,
- const sctp_subtype_t type,
- void *arg,
- sctp_cmd_seq_t *commands)
+static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint
*ep,
+ const struct sctp_association
*asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands)
{
struct sctp_chunk *chunk = arg;
time_t stale;
@@ -2064,12 +2216,24 @@
if (!sctp_vtag_verify_either(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
- /* Check that chunk header looks valid. */
+ /* Make sure that the ABORT chunk has a valid length.
+ * Since this is an ABORT chunk, we have to discard it
+ * because of the following text:
+ * RFC 2960, Section 3.3.7
+ * If an endpoint receives an ABORT with a format error or for an
+ * association that doesn't exist, it MUST silently discard it.
+ * Becasue the length is "invalid", we can't really discard just
+ * as we do not know its true length. So, to be safe, discard the
+ * packet.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
+
+ /* See if we have an error cause code in the chunk. */
len = ntohs(chunk->chunk_hdr->length);
if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
-
/* ASSOC_FAILED will DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error));
SCTP_INC_STATS(SctpAborteds);
@@ -2096,27 +2260,44 @@
if (!sctp_vtag_verify_either(chunk, asoc))
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
- sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
- SCTP_STATE(SCTP_STATE_CLOSED));
- SCTP_INC_STATS(SctpAborteds);
- sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
- SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+ /* Make sure that the ABORT chunk has a valid length.
+ * Since this is an ABORT chunk, we have to discard it
+ * because of the following text:
+ * RFC 2960, Section 3.3.7
+ * If an endpoint receives an ABORT with a format error or for an
+ * association that doesn't exist, it MUST silently discard it.
+ * Becasue the length is "invalid", we can't really discard just
+ * as we do not know its true length. So, to be safe, discard the
+ * packet.
+ */
+ if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))
+ return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
- /* Check that chunk header looks valid. */
+ /* See if we have an error cause code in the chunk. */
len = ntohs(chunk->chunk_hdr->length);
if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
- /* CMD_INIT_FAILED will DELETE_TCB. */
- sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_U32(error));
+ sctp_stop_t1_and_abort(commands, error);
return SCTP_DISPOSITION_ABORT;
}
/*
+ * Process an incoming ICMP as an ABORT. (COOKIE-WAIT state)
+ */
+sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint
*ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands)
+{
+ sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR);
+ return SCTP_DISPOSITION_ABORT;
+}
+
+/*
* Process an ABORT. (COOKIE-ECHOED state)
[%d lines skipped]
436diff -urN linux/net/sctp/sm_statetable.c linux/net/sctp/sm_statetable.c
--- linux/net/sctp/sm_statetable.c 2004/08/14 18:39:05 1.10.2.3
+++ linux/net/sctp/sm_statetable.c 2005/01/20 02:19:26 1.10.2.4
@@ -50,6 +50,17 @@
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
+static const sctp_sm_table_entry_t
+primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES];
+static const sctp_sm_table_entry_t
+other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES];
+static const sctp_sm_table_entry_t
+timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES];
+
+static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
+ sctp_state_t state);
+
+
static const sctp_sm_table_entry_t bug = {
.fn = sctp_sf_bug,
.name = "sctp_sf_bug"
@@ -419,7 +430,7 @@
*
* For base protocol (RFC 2960).
*/
-const sctp_sm_table_entry_t
chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
+static const sctp_sm_table_entry_t
chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_DATA,
TYPE_SCTP_INIT,
TYPE_SCTP_INIT_ACK,
@@ -482,7 +493,7 @@
/* The primary index for this table is the chunk type.
* The secondary index for this table is the state.
*/
-const sctp_sm_table_entry_t
addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
+static const sctp_sm_table_entry_t
addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_ASCONF,
TYPE_SCTP_ASCONF_ACK,
}; /*state_fn_t addip_chunk_event_table[][] */
@@ -511,7 +522,7 @@
/* The primary index for this table is the chunk type.
* The secondary index for this table is the state.
*/
-const sctp_sm_table_entry_t
prsctp_chunk_event_table[SCTP_NUM_PRSCTP_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
+static const sctp_sm_table_entry_t
prsctp_chunk_event_table[SCTP_NUM_PRSCTP_CHUNK_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_FWD_TSN,
}; /*state_fn_t prsctp_chunk_event_table[][] */
@@ -684,7 +695,7 @@
/* The primary index for this table is the primitive type.
* The secondary index for this table is the state.
*/
-const sctp_sm_table_entry_t
primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES] = {
+static const sctp_sm_table_entry_t
primitive_event_table[SCTP_NUM_PRIMITIVE_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_PRIMITIVE_ASSOCIATE,
TYPE_SCTP_PRIMITIVE_SHUTDOWN,
TYPE_SCTP_PRIMITIVE_ABORT,
@@ -716,8 +727,31 @@
{.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
}
-const sctp_sm_table_entry_t
other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES] = {
+#define TYPE_SCTP_OTHER_ICMP_PROTO_UNREACH { \
+ /* SCTP_STATE_EMPTY */ \
+ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
+ /* SCTP_STATE_CLOSED */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ /* SCTP_STATE_COOKIE_WAIT */ \
+ {.fn = sctp_sf_cookie_wait_icmp_abort, \
+ .name = "sctp_sf_cookie_wait_icmp_abort"}, \
+ /* SCTP_STATE_COOKIE_ECHOED */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ /* SCTP_STATE_ESTABLISHED */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ /* SCTP_STATE_SHUTDOWN_PENDING */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ /* SCTP_STATE_SHUTDOWN_SENT */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ /* SCTP_STATE_SHUTDOWN_RECEIVED */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
+ {.fn = sctp_sf_ignore_other, .name = "sctp_sf_ignore_other"}, \
+}
+
+static const sctp_sm_table_entry_t
other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_OTHER_NO_PENDING_TSN,
+ TYPE_SCTP_OTHER_ICMP_PROTO_UNREACH,
};
#define TYPE_SCTP_EVENT_TIMEOUT_NONE { \
@@ -931,7 +965,7 @@
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
}
-const sctp_sm_table_entry_t
timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = {
+static const sctp_sm_table_entry_t
timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES] = {
TYPE_SCTP_EVENT_TIMEOUT_NONE,
TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE,
TYPE_SCTP_EVENT_TIMEOUT_T1_INIT,
@@ -944,8 +978,8 @@
TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE,
};
-const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
- sctp_state_t state)
+static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid,
+ sctp_state_t state)
{
if (state > SCTP_STATE_MAX)
return &bug;
diff -urN linux/net/sctp/socket.c linux/net/sctp/socket.c
--- linux/net/sctp/socket.c 2004/12/27 04:13:57 1.23.2.6
+++ linux/net/sctp/socket.c 2005/01/20 02:19:26 1.23.2.7
@@ -116,7 +116,7 @@
struct sock *sk = asoc->base.sk;
int amt = 0;
- amt = sk->sk_sndbuf - asoc->sndbuf_used;
+ amt = sk->sndbuf - asoc->sndbuf_used;
if (amt < 0)
amt = 0;
return amt;
@@ -144,7 +144,7 @@
*((struct sctp_chunk **)(chunk->skb->cb)) = chunk;
asoc->sndbuf_used += SCTP_DATA_SNDSIZE(chunk);
- sk->sk_wmem_queued += SCTP_DATA_SNDSIZE(chunk);
+ sk->wmem_queued += SCTP_DATA_SNDSIZE(chunk);
}
/* Verify that this is a valid address. */
@@ -203,7 +203,7 @@
* id are specified, the associations matching the address and the id should be
* the same.
*/
-struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
+static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
struct sockaddr_storage *addr,
sctp_assoc_t id)
{
@@ -224,7 +224,7 @@
if (id_asoc && (id_asoc != addr_asoc))
return NULL;
- sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
+ sctp_get_pf_specific(sk->family)->addr_v4map(sctp_sk(sk),
(union sctp_addr *)addr);
return transport;
@@ -240,7 +240,7 @@
* sockaddr_in6 [RFC 2553]),
* addr_len - the size of the address structure.
*/
-int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int
addr_len)
{
int retval = 0;
@@ -338,8 +338,8 @@
}
/* Refresh ephemeral port. */
- if (!snum)
- snum = sk->num;
+ if (!bp->port)
+ bp->port = sk->num;
/* Add the address to the bind address list. */
sctp_local_bh_disable();
@@ -349,8 +349,6 @@
addr->v4.sin_port = ntohs(addr->v4.sin_port);
ret = sctp_add_bind_addr(bp, addr, GFP_ATOMIC);
addr->v4.sin_port = htons(addr->v4.sin_port);
- if (!ret && !bp->port)
- bp->port = snum;
sctp_write_unlock(&ep->base.addr_lock);
sctp_local_bh_enable();
@@ -612,7 +610,7 @@
}
/* FIXME - There is probably a need to check if sk->sk_saddr and
- * sk->sk_rcv_addr are currently set to one of the addresses to
+ * sk->rcv_addr are currently set to one of the addresses to
* be removed. This is something which needs to be looked into
* when we are fixing the outstanding issues with multi-homing
* socket routing and failover schemes. Refer to comments in
@@ -951,7 +949,7 @@
SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout);
sctp_lock_sock(sk);
- sk->sk_shutdown = SHUTDOWN_MASK;
+ sk->shutdown = SHUTDOWN_MASK;
ep = sctp_sk(sk)->ep;
@@ -969,7 +967,7 @@
sctp_unhash_established(asoc);
sctp_association_free(asoc);
- } else if (sk->linger && !sk->sk_lingertime)
+ } else if (sk->linger && !sk->lingertime)
sctp_primitive_ABORT(asoc, NULL);
else
sctp_primitive_SHUTDOWN(asoc, NULL);
@@ -978,7 +976,7 @@
}
/* Clean up any skbs sitting on the receive queue. */
- sctp_queue_purge_ulpevents(&sk->sk_receive_queue);
+ sctp_queue_purge_ulpevents(&sk->receive_queue);
sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby);
/* On a TCP-style socket, block for at most linger_time if set. */
@@ -1314,7 +1312,7 @@
/* API 7.1.7, the sndbuf size per association bounds the
* maximum size of data that can be sent in a single send call.
*/
- if (msg_len > sk->sk_sndbuf) {
+ if (msg_len > sk->sndbuf) {
err = -EMSGSIZE;
goto out_free;
}
@@ -1551,7 +1549,7 @@
if (flags & MSG_PEEK)
goto out_free;
sctp_skb_pull(skb, copied);
- skb_queue_head(&sk->sk_receive_queue, skb);
+ skb_queue_head(&sk->receive_queue, skb);
/* When only partial message is copied to the user, increase
* rwnd by that amount. If all the data in the skb is read,
@@ -1704,10 +1702,13 @@
/* update default value for endpoint (all future associations) */
if (!params.spp_assoc_id &&
sctp_is_any(( union sctp_addr *)¶ms.spp_address)) {
- if (params.spp_hbinterval)
+ /* Manual heartbeat on an endpoint is invalid. */
+ if (0xffffffff == params.spp_hbinterval)
+ return -EINVAL;
+ else if (params.spp_hbinterval)
sctp_sk(sk)->paddrparam.spp_hbinterval =
params.spp_hbinterval;
- if (sctp_max_retrans_path)
+ if (params.spp_pathmaxrxt)
sctp_sk(sk)->paddrparam.spp_pathmaxrxt =
params.spp_pathmaxrxt;
return 0;
@@ -1749,7 +1750,8 @@
/* spp_pathmaxrxt contains the maximum number of retransmissions
* before this address shall be considered unreachable.
*/
- trans->error_threshold = params.spp_pathmaxrxt;
+ if (params.spp_pathmaxrxt)
+ trans->max_retrans = params.spp_pathmaxrxt;
return 0;
}
@@ -2355,7 +2357,7 @@
af = sctp_get_af_specific(to.sa.sa_family);
af->to_sk_daddr(&to, sk);
- timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
+ timeo = sock_sndtimeo(sk, sk->socket->file->f_flags & O_NONBLOCK);
err = sctp_wait_for_connect(asoc, &timeo);
out_unlock:
@@ -2401,7 +2403,7 @@
goto out;
}
- timeo = sock_rcvtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
+ timeo = sock_rcvtimeo(sk, sk->socket->file->f_flags & O_NONBLOCK);
error = sctp_wait_for_accept(sk, timeo);
if (error)
@@ -2449,7 +2451,7 @@
sp = sctp_sk(sk);
/* Initialize the SCTP per socket area. */
- switch (sk->sk_type) {
+ switch (sk->type) {
case SOCK_SEQPACKET:
sp->type = SCTP_SOCKET_UDP;
break;
@@ -2529,7 +2531,7 @@
sp->adaption_ind = 0;
- sp->pf = sctp_get_pf_specific(sk->sk_family);
+ sp->pf = sctp_get_pf_specific(sk->family);
/* Control variables for partial data delivery. */
sp->pd_mode = 0;
@@ -2646,7 +2648,7 @@
memcpy(&status.sstat_primary.spinfo_address,
&(transport->ipaddr), sizeof(union sctp_addr));
/* Map ipv4 address into v4-mapped-on-v6 address. */
- sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
+ sctp_get_pf_specific(sk->family)->addr_v4map(sctp_sk(sk),
(union sctp_addr *)&status.sstat_primary.spinfo_address);
status.sstat_primary.spinfo_state = transport->active;
status.sstat_primary.spinfo_cwnd = transport->cwnd;
@@ -2800,7 +2802,7 @@
return -EINVAL;
/* Create a new socket. */
- err = sock_create(sk->sk_family, SOCK_SEQPACKET, IPPROTO_SCTP, &sock);
+ err = sock_create(sk->family, SOCK_SEQPACKET, IPPROTO_SCTP, &sock);
if (err < 0)
return err;
@@ -2926,7 +2928,7 @@
/* spp_pathmaxrxt contains the maximum number of retransmissions
* before this address shall be considered unreachable.
*/
- params.spp_pathmaxrxt = trans->error_threshold;
+ params.spp_pathmaxrxt = trans->max_retrans;
done:
if (copy_to_user(optval, ¶ms, len))
@@ -3014,8 +3016,8 @@
list_for_each(pos, &asoc->peer.transport_addr_list) {
from = list_entry(pos, struct sctp_transport, transports);
memcpy(&temp, &from->ipaddr, sizeof(temp));
- sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
- addrlen = sctp_get_af_specific(sk->sk_family)->sockaddr_len;
+ sctp_get_pf_specific(sk->family)->addr_v4map(sp, &temp);
+ addrlen = sctp_get_af_specific(sk->family)->sockaddr_len;
temp.v4.sin_port = htons(temp.v4.sin_port);
if (copy_to_user(to, &temp, addrlen))
return -EFAULT;
@@ -3037,6 +3039,9 @@
struct sctp_bind_addr *bp;
struct sctp_association *asoc;
struct list_head *pos;
+ struct sctp_sockaddr_entry *addr;
+ rwlock_t *addr_lock;
+ unsigned long flags;
int cnt = 0;
if (len != sizeof(sctp_assoc_t))
@@ -3053,33 +3058,103 @@
*/
if (0 == id) {
bp = &sctp_sk(sk)->ep->base.bind_addr;
+ addr_lock = &sctp_sk(sk)->ep->base.addr_lock;
} else {
asoc = sctp_id2assoc(sk, id);
if (!asoc)
return -EINVAL;
bp = &asoc->base.bind_addr;
+ addr_lock = &asoc->base.addr_lock;
}
+ sctp_read_lock(addr_lock);
+
+ /* If the endpoint is bound to 0.0.0.0 or ::0, count the valid
+ * addresses from the global local address list.
+ */
+ if (sctp_list_single_entry(&bp->address_list)) {
+ addr = list_entry(bp->address_list.next,
+ struct sctp_sockaddr_entry, list);
+ if (sctp_is_any(&addr->a)) {
+ sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
+ list_for_each(pos, &sctp_local_addr_list) {
+ addr = list_entry(pos,
+ struct sctp_sockaddr_entry,
+ list);
+ if ((PF_INET == sk->family) &&
+ (AF_INET6 == addr->a.sa.sa_family))
+ continue;
+ cnt++;
+ }
+ sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
+ flags);
+ } else {
+ cnt = 1;
+ }
+ goto done;
+ }
+
list_for_each(pos, &bp->address_list) {
cnt ++;
}
+done:
+ sctp_read_unlock(addr_lock);
+ return cnt;
+}
+
+/* Helper function that copies local addresses to user and returns the number
+ * of addresses copied.
+ */
+static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, int max_addrs,
+ void __user *to)
+{
+ struct list_head *pos;
+ struct sctp_sockaddr_entry *addr;
+ unsigned long flags;
+ union sctp_addr temp;
+ int cnt = 0;
+ int addrlen;
+
+ sctp_spin_lock_irqsave(&sctp_local_addr_lock, flags);
+ list_for_each(pos, &sctp_local_addr_list) {
+ addr = list_entry(pos, struct sctp_sockaddr_entry, list);
+ if ((PF_INET == sk->family) &&
+ (AF_INET6 == addr->a.sa.sa_family))
+ continue;
+ memcpy(&temp, &addr->a, sizeof(temp));
+ sctp_get_pf_specific(sk->family)->addr_v4map(sctp_sk(sk),
+ &temp);
+ addrlen =
sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
temp.v4.sin_port = htons(port);
+ if (copy_to_user(to, &temp, addrlen)) {
+ sctp_spin_unlock_irqrestore(&sctp_local_addr_lock,
+ flags);
+ return -EFAULT;
+ }
+ to += addrlen;
+ cnt ++;
+ if (cnt >= max_addrs) break;
+ }
+ sctp_spin_unlock_irqrestore(&sctp_local_addr_lock, flags);
+
return cnt;
}
static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
- char *optval, int *optlen)
+ char *optval, int *optlen)
{
struct sctp_bind_addr *bp;
struct sctp_association *asoc;
struct list_head *pos;
int cnt = 0;
struct sctp_getaddrs getaddrs;
- struct sctp_sockaddr_entry *from;
+ struct sctp_sockaddr_entry *addr;
void *to;
union sctp_addr temp;
struct sctp_opt *sp = sctp_sk(sk);
int addrlen;
+ rwlock_t *addr_lock;
+ int err = 0;
if (len != sizeof(struct sctp_getaddrs))
return -EINVAL;
@@ -3096,33 +3171,59 @@
*/
if (0 == getaddrs.assoc_id) {
bp = &sctp_sk(sk)->ep->base.bind_addr;
+ addr_lock = &sctp_sk(sk)->ep->base.addr_lock;
} else {
asoc = sctp_id2assoc(sk, getaddrs.assoc_id);
if (!asoc)
return -EINVAL;
bp = &asoc->base.bind_addr;
+ addr_lock = &asoc->base.addr_lock;
}
to = (void *)getaddrs.addrs;
+
+ sctp_read_lock(addr_lock);
+
+ /* If the endpoint is bound to 0.0.0.0 or ::0, get the valid
+ * addresses from the global local address list.
+ */
+ if (sctp_list_single_entry(&bp->address_list)) {
+ addr = list_entry(bp->address_list.next,
+ struct sctp_sockaddr_entry, list);
+ if (sctp_is_any(&addr->a)) {
+ cnt = sctp_copy_laddrs_to_user(sk, bp->port,
+ getaddrs.addr_num, to);
+ if (cnt < 0) {
+ err = cnt;
+ goto unlock;
+ }
+ goto copy_getaddrs;
+ }
+ }
+
list_for_each(pos, &bp->address_list) {
- from = list_entry(pos,
- struct sctp_sockaddr_entry,
- list);
- memcpy(&temp, &from->a, sizeof(temp));
- sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
+ addr = list_entry(pos, struct sctp_sockaddr_entry, list);
+ memcpy(&temp, &addr->a, sizeof(temp));
+ sctp_get_pf_specific(sk->family)->addr_v4map(sp, &temp);
addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
temp.v4.sin_port = htons(temp.v4.sin_port);
- if (copy_to_user(to, &temp, addrlen))
- return -EFAULT;
+ if (copy_to_user(to, &temp, addrlen)) {
+ err = -EFAULT;
+ goto unlock;
+ }
to += addrlen;
cnt ++;
if (cnt >= getaddrs.addr_num) break;
}
+
+copy_getaddrs:
getaddrs.addr_num = cnt;
if (copy_to_user(optval, &getaddrs, sizeof(struct sctp_getaddrs)))
- return -EFAULT;
+ err = -EFAULT;
- return 0;
[%d lines skipped]
355diff -urN linux/net/sctp/ssnmap.c linux/net/sctp/ssnmap.c
--- linux/net/sctp/ssnmap.c 2004/04/16 03:14:22 1.2.2.2
+++ linux/net/sctp/ssnmap.c 2005/01/20 02:19:26 1.2.2.3
@@ -42,6 +42,9 @@
#define MAX_KMALLOC_SIZE 131072
+static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
+ __u16 out);
+
/* Storage size needed for map includes 2 headers and then the
* specific needs of in or out streams.
*/
@@ -87,8 +90,8 @@
/* Initialize a block of memory as a ssnmap. */
-struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
- __u16 out)
+static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,
+ __u16 out)
{
memset(map, 0x00, sctp_ssnmap_size(in, out));
diff -urN linux/net/sctp/transport.c linux/net/sctp/transport.c
--- linux/net/sctp/transport.c 2004/11/19 00:29:09 1.11.2.5
+++ linux/net/sctp/transport.c 2005/01/20 02:19:26 1.11.2.6
@@ -54,34 +54,10 @@
/* 1st Level Abstractions. */
-/* Allocate and initialize a new transport. */
-struct sctp_transport *sctp_transport_new(const union sctp_addr *addr, int gfp)
-{
- struct sctp_transport *transport;
-
- transport = t_new(struct sctp_transport, gfp);
- if (!transport)
- goto fail;
-
- if (!sctp_transport_init(transport, addr, gfp))
- goto fail_init;
-
- transport->malloced = 1;
- SCTP_DBG_OBJCNT_INC(transport);
-
- return transport;
-
-fail_init:
- kfree(transport);
-
-fail:
- return NULL;
-}
-
/* Initialize a new transport from provided memory. */
-struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
- const union sctp_addr *addr,
- int gfp)
+static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
+ const union sctp_addr *addr,
+ int gfp)
{
/* Copy in the address. */
peer->ipaddr = *addr;
@@ -112,7 +88,6 @@
/* Initialize the default path max_retrans. */
peer->max_retrans = sctp_max_retrans_path;
- peer->error_threshold = 0;
peer->error_count = 0;
INIT_LIST_HEAD(&peer->transmitted);
@@ -144,6 +119,30 @@
return peer;
}
+/* Allocate and initialize a new transport. */
+struct sctp_transport *sctp_transport_new(const union sctp_addr *addr, int gfp)
+{
+ struct sctp_transport *transport;
+
+ transport = t_new(struct sctp_transport, gfp);
+ if (!transport)
+ goto fail;
+
+ if (!sctp_transport_init(transport, addr, gfp))
+ goto fail_init;
+
+ transport->malloced = 1;
+ SCTP_DBG_OBJCNT_INC(transport);
+
+ return transport;
+
+fail_init:
+ kfree(transport);
+
+fail:
+ return NULL;
+}
+
/* This transport is no longer needed. Free up if possible, or
* delay until it last reference count.
*/
@@ -155,13 +154,23 @@
if (del_timer(&transport->hb_timer))
sctp_transport_put(transport);
+ /* Delete the T3_rtx timer if it's active.
+ * There is no point in not doing this now and letting
+ * structure hang around in memory since we know
+ * the tranport is going away.
+ */
+ if (timer_pending(&transport->T3_rtx_timer) &&
+ del_timer(&transport->T3_rtx_timer))
+ sctp_transport_put(transport);
+
+
sctp_transport_put(transport);
}
/* Destroy the transport data structure.
* Assumes there are no more users of this structure.
*/
-void sctp_transport_destroy(struct sctp_transport *transport)
+static void sctp_transport_destroy(struct sctp_transport *transport)
{
SCTP_ASSERT(transport->dead, "Transport is not dead", return);
diff -urN linux/net/sctp/tsnmap.c linux/net/sctp/tsnmap.c
--- linux/net/sctp/tsnmap.c 2004/08/14 18:39:05 1.5.2.3
+++ linux/net/sctp/tsnmap.c 2005/01/20 02:19:26 1.5.2.4
@@ -52,29 +52,6 @@
int *started, __u16 *start,
int *ended, __u16 *end);
-/* Create a new sctp_tsnmap.
- * Allocate room to store at least 'len' contiguous TSNs.
- */
-struct sctp_tsnmap *sctp_tsnmap_new(__u16 len, __u32 initial_tsn, int gfp)
-{
- struct sctp_tsnmap *retval;
-
- retval = kmalloc(sizeof(struct sctp_tsnmap) +
- sctp_tsnmap_storage_size(len), gfp);
- if (!retval)
- goto fail;
-
- if (!sctp_tsnmap_init(retval, len, initial_tsn))
- goto fail_map;
- retval->malloced = 1;
- return retval;
-
-fail_map:
- kfree(retval);
-fail:
- return NULL;
-}
-
/* Initialize a block of memory as a tsnmap. */
struct sctp_tsnmap *sctp_tsnmap_init(struct sctp_tsnmap *map, __u16 len,
__u32 initial_tsn)
@@ -168,16 +145,9 @@
}
-/* Dispose of a tsnmap. */
-void sctp_tsnmap_free(struct sctp_tsnmap *map)
-{
- if (map->malloced)
- kfree(map);
-}
-
/* Initialize a Gap Ack Block iterator from memory being provided. */
-void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map,
- struct sctp_tsnmap_iter *iter)
+SCTP_STATIC void sctp_tsnmap_iter_init(const struct sctp_tsnmap *map,
+ struct sctp_tsnmap_iter *iter)
{
/* Only start looking one past the Cumulative TSN Ack Point. */
iter->start = map->cumulative_tsn_ack_point + 1;
@@ -186,8 +156,9 @@
/* Get the next Gap Ack Blocks. Returns 0 if there was not another block
* to get.
*/
-int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map,
- struct sctp_tsnmap_iter *iter, __u16 *start, __u16 *end)
+SCTP_STATIC int sctp_tsnmap_next_gap_ack(const struct sctp_tsnmap *map,
+ struct sctp_tsnmap_iter *iter,
+ __u16 *start, __u16 *end)
{
int started, ended;
__u16 _start, _end, offset;
diff -urN linux/net/sctp/ulpevent.c linux/net/sctp/ulpevent.c
--- linux/net/sctp/ulpevent.c 2004/11/19 00:29:09 1.8.2.4
+++ linux/net/sctp/ulpevent.c 2005/01/20 02:19:26 1.8.2.5
@@ -65,8 +65,16 @@
*/
}
+/* Initialize an ULP event from an given skb. */
+SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags)
+{
+ memset(event, 0, sizeof(struct sctp_ulpevent));
+ event->msg_flags = msg_flags;
+}
+
/* Create a new sctp_ulpevent. */
-struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags, int gfp)
+SCTP_STATIC struct sctp_ulpevent *sctp_ulpevent_new(int size, int msg_flags,
+ int gfp)
{
struct sctp_ulpevent *event;
struct sk_buff *skb;
@@ -84,13 +92,6 @@
return NULL;
}
-/* Initialize an ULP event from an given skb. */
-void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags)
-{
- memset(event, 0, sizeof(struct sctp_ulpevent));
- event->msg_flags = msg_flags;
-}
-
/* Is this a MSG_NOTIFICATION? */
int sctp_ulpevent_is_notification(const struct sctp_ulpevent *event)
{
@@ -322,7 +323,7 @@
memcpy(&spc->spc_aaddr, aaddr, sizeof(struct sockaddr_storage));
/* Map ipv4 address into v4-mapped-on-v6 address. */
- sctp_get_pf_specific(asoc->base.sk->sk_family)->addr_v4map(
+ sctp_get_pf_specific(asoc->base.sk->family)->addr_v4map(
sctp_sk(asoc->base.sk),
(union sctp_addr *)&spc->spc_aaddr);
diff -urN linux/net/sctp/ulpqueue.c linux/net/sctp/ulpqueue.c
--- linux/net/sctp/ulpqueue.c 2004/11/19 00:29:09 1.10.2.4
+++ linux/net/sctp/ulpqueue.c 2005/01/20 02:19:26 1.10.2.5
@@ -56,25 +56,6 @@
/* 1st Level Abstractions */
-/* Create a new ULP queue. */
-struct sctp_ulpq *sctp_ulpq_new(struct sctp_association *asoc, int gfp)
-{
- struct sctp_ulpq *ulpq;
-
- ulpq = kmalloc(sizeof(struct sctp_ulpq), gfp);
- if (!ulpq)
- goto fail;
- if (!sctp_ulpq_init(ulpq, asoc))
- goto fail_init;
- ulpq->malloced = 1;
- return ulpq;
-
-fail_init:
- kfree(ulpq);
-fail:
- return NULL;
-}
-
/* Initialize a ULP queue from a block of memory. */
struct sctp_ulpq *sctp_ulpq_init(struct sctp_ulpq *ulpq,
struct sctp_association *asoc)
@@ -92,7 +73,7 @@
/* Flush the reassembly and ordering queues. */
-void sctp_ulpq_flush(struct sctp_ulpq *ulpq)
+static void sctp_ulpq_flush(struct sctp_ulpq *ulpq)
{
struct sk_buff *skb;
struct sctp_ulpevent *event;
@@ -163,7 +144,7 @@
sp->pd_mode = 0;
if (!skb_queue_empty(&sp->pd_lobby)) {
struct list_head *list;
- sctp_skb_list_tail(&sp->pd_lobby, &sk->sk_receive_queue);
+ sctp_skb_list_tail(&sp->pd_lobby, &sk->receive_queue);
list = (struct list_head *)&sctp_sk(sk)->pd_lobby;
INIT_LIST_HEAD(list);
return 1;
@@ -189,7 +170,7 @@
/* If the socket is just going to throw this away, do not
* even try to deliver it.
*/
- if (sk->dead || (sk->sk_shutdown & RCV_SHUTDOWN))
+ if (sk->dead || (sk->shutdown & RCV_SHUTDOWN))
goto out_free;
/* Check if the user wishes to receive this event. */
@@ -202,13 +183,13 @@
*/
if (!sctp_sk(sk)->pd_mode) {
- queue = &sk->sk_receive_queue;
+ queue = &sk->receive_queue;
} else if (ulpq->pd_mode) {
if (event->msg_flags & MSG_NOTIFICATION)
queue = &sctp_sk(sk)->pd_lobby;
else {
clear_pd = event->msg_flags & MSG_EOR;
- queue = &sk->sk_receive_queue;
+ queue = &sk->receive_queue;
}
} else
queue = &sctp_sk(sk)->pd_lobby;
@@ -229,8 +210,8 @@
if (clear_pd)
sctp_ulpq_clear_pd(ulpq);
- if (queue == &sk->sk_receive_queue)
- sk->sk_data_ready(sk, 0);
+ if (queue == &sk->receive_queue)
+ sk->data_ready(sk, 0);
return 1;
out_free:
@@ -837,7 +818,7 @@
freed = 0;
- if (skb_queue_empty(&asoc->base.sk->sk_receive_queue)) {
+ if (skb_queue_empty(&asoc->base.sk->receive_queue)) {
freed = sctp_ulpq_renege_order(ulpq, needed);
if (freed < needed) {
freed += sctp_ulpq_renege_frags(ulpq, needed - freed);
@@ -876,9 +857,9 @@
SCTP_PARTIAL_DELIVERY_ABORTED,
gfp);
if (ev)
- __skb_queue_tail(&sk->sk_receive_queue, sctp_event2skb(ev));
+ __skb_queue_tail(&sk->receive_queue, sctp_event2skb(ev));
/* If there is data waiting, send it up the socket now. */
if (sctp_ulpq_clear_pd(ulpq) || ev)
- sk->sk_data_ready(sk, 0);
+ sk->data_ready(sk, 0);
}
|