diff --git a/[refs] b/[refs] index 132bb86d3121..255c936b0fd8 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 4a4f8fdba6f5a34ca90f426021e17491a30202da +refs/heads/master: 8005aba69a6440a535a4cc2aed99ffca580847e0 diff --git a/trunk/arch/sparc64/solaris/socket.c b/trunk/arch/sparc64/solaris/socket.c index ec8e074c4eac..06740582717e 100644 --- a/trunk/arch/sparc64/solaris/socket.c +++ b/trunk/arch/sparc64/solaris/socket.c @@ -317,8 +317,10 @@ asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsi unsigned long *kcmsg; compat_size_t cmlen; - if(kern_msg.msg_controllen > sizeof(ctl) && - kern_msg.msg_controllen <= 256) { + if (kern_msg.msg_controllen <= sizeof(compat_size_t)) + return -EINVAL; + + if(kern_msg.msg_controllen > sizeof(ctl)) { err = -ENOBUFS; ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL); if(!ctl_buf) diff --git a/trunk/fs/Kconfig b/trunk/fs/Kconfig index 178e27494b74..6a4ad4bb7a54 100644 --- a/trunk/fs/Kconfig +++ b/trunk/fs/Kconfig @@ -741,6 +741,56 @@ config SYSFS Designers of embedded systems may wish to say N here to conserve space. +config DEVFS_FS + bool "/dev file system support (OBSOLETE)" + depends on EXPERIMENTAL + help + This is support for devfs, a virtual file system (like /proc) which + provides the file system interface to device drivers, normally found + in /dev. Devfs does not depend on major and minor number + allocations. Device drivers register entries in /dev which then + appear automatically, which means that the system administrator does + not have to create character and block special device files in the + /dev directory using the mknod command (or MAKEDEV script) anymore. + + This is work in progress. If you want to use this, you *must* read + the material in , especially + the file README there. + + Note that devfs no longer manages /dev/pts! If you are using UNIX98 + ptys, you will also need to mount the /dev/pts filesystem (devpts). + + Note that devfs has been obsoleted by udev, + . + It has been stripped down to a bare minimum and is only provided for + legacy installations that use its naming scheme which is + unfortunately different from the names normal Linux installations + use. + + If unsure, say N. + +config DEVFS_MOUNT + bool "Automatically mount at boot" + depends on DEVFS_FS + help + This option appears if you have CONFIG_DEVFS_FS enabled. Setting + this to 'Y' will make the kernel automatically mount devfs onto /dev + when the system is booted, before the init thread is started. + You can override this with the "devfs=nomount" boot option. + + If unsure, say N. + +config DEVFS_DEBUG + bool "Debug devfs" + depends on DEVFS_FS + help + If you say Y here, then the /dev file system code will generate + debugging messages. See the file + for more + details. + + If unsure, say N. + config DEVPTS_FS_XATTR bool "/dev/pts Extended Attributes" depends on UNIX98_PTYS diff --git a/trunk/fs/jfs/acl.c b/trunk/fs/jfs/acl.c index 30a2bf9eeda5..8d2a9ab981d4 100644 --- a/trunk/fs/jfs/acl.c +++ b/trunk/fs/jfs/acl.c @@ -70,7 +70,8 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type) if (!IS_ERR(acl)) *p_acl = posix_acl_dup(acl); } - kfree(value); + if (value) + kfree(value); return acl; } @@ -111,7 +112,8 @@ static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl) } rc = __jfs_setxattr(inode, ea_name, value, size, 0); out: - kfree(value); + if (value) + kfree(value); if (!rc) { if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED)) diff --git a/trunk/fs/jfs/file.c b/trunk/fs/jfs/file.c index c2c19c9ed9a4..a87b06fa8ff8 100644 --- a/trunk/fs/jfs/file.c +++ b/trunk/fs/jfs/file.c @@ -1,6 +1,6 @@ /* - * Copyright (C) International Business Machines Corp., 2000-2002 - * Portions Copyright (C) Christoph Hellwig, 2001-2002 + * Copyright (c) International Business Machines Corp., 2000-2002 + * Portions Copyright (c) Christoph Hellwig, 2001-2002 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,13 +19,16 @@ #include #include "jfs_incore.h" -#include "jfs_inode.h" #include "jfs_dmap.h" #include "jfs_txnmgr.h" #include "jfs_xattr.h" #include "jfs_acl.h" #include "jfs_debug.h" + +extern int jfs_commit_inode(struct inode *, int); +extern void jfs_truncate(struct inode *); + int jfs_fsync(struct file *file, struct dentry *dentry, int datasync) { struct inode *inode = dentry->d_inode; diff --git a/trunk/fs/jfs/inode.c b/trunk/fs/jfs/inode.c index 2137138c59b0..24a689179af2 100644 --- a/trunk/fs/jfs/inode.c +++ b/trunk/fs/jfs/inode.c @@ -23,7 +23,6 @@ #include #include #include "jfs_incore.h" -#include "jfs_inode.h" #include "jfs_filsys.h" #include "jfs_imap.h" #include "jfs_extent.h" @@ -31,6 +30,14 @@ #include "jfs_debug.h" +extern struct inode_operations jfs_dir_inode_operations; +extern struct inode_operations jfs_file_inode_operations; +extern struct inode_operations jfs_symlink_inode_operations; +extern struct file_operations jfs_dir_operations; +extern struct file_operations jfs_file_operations; +struct address_space_operations jfs_aops; +extern int freeZeroLink(struct inode *); + void jfs_read_inode(struct inode *inode) { if (diRead(inode)) { @@ -129,7 +136,7 @@ void jfs_delete_inode(struct inode *inode) jfs_info("In jfs_delete_inode, inode = 0x%p", inode); if (test_cflag(COMMIT_Freewmap, inode)) - jfs_free_zero_link(inode); + freeZeroLink(inode); diFree(inode); diff --git a/trunk/fs/jfs/jfs_debug.c b/trunk/fs/jfs/jfs_debug.c index 4caea6b43b92..91a0a889ebc5 100644 --- a/trunk/fs/jfs/jfs_debug.c +++ b/trunk/fs/jfs/jfs_debug.c @@ -58,6 +58,8 @@ void dump_mem(char *label, void *data, int length) static struct proc_dir_entry *base; #ifdef CONFIG_JFS_DEBUG +extern read_proc_t jfs_txanchor_read; + static int loglevel_read(char *page, char **start, off_t off, int count, int *eof, void *data) { @@ -95,6 +97,14 @@ static int loglevel_write(struct file *file, const char __user *buffer, } #endif + +#ifdef CONFIG_JFS_STATISTICS +extern read_proc_t jfs_lmstats_read; +extern read_proc_t jfs_txstats_read; +extern read_proc_t jfs_xtstat_read; +extern read_proc_t jfs_mpstat_read; +#endif + static struct { const char *name; read_proc_t *read_fn; diff --git a/trunk/fs/jfs/jfs_debug.h b/trunk/fs/jfs/jfs_debug.h index ddffbbd4d955..a38079ae1e00 100644 --- a/trunk/fs/jfs/jfs_debug.h +++ b/trunk/fs/jfs/jfs_debug.h @@ -1,6 +1,6 @@ /* - * Copyright (C) International Business Machines Corp., 2000-2002 - * Portions Copyright (C) Christoph Hellwig, 2001-2002 + * Copyright (c) International Business Machines Corp., 2000-2002 + * Portions Copyright (c) Christoph Hellwig, 2001-2002 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,9 +31,7 @@ * CONFIG_JFS_DEBUG or CONFIG_JFS_STATISTICS is defined */ #if defined(CONFIG_PROC_FS) && (defined(CONFIG_JFS_DEBUG) || defined(CONFIG_JFS_STATISTICS)) -#define PROC_FS_JFS -extern void jfs_proc_init(void); -extern void jfs_proc_clean(void); + #define PROC_FS_JFS #endif /* @@ -67,8 +65,8 @@ extern void jfs_proc_clean(void); extern int jfsloglevel; +/* dump memory contents */ extern void dump_mem(char *label, void *data, int length); -extern int jfs_txanchor_read(char *, char **, off_t, int, int *, void *); /* information message: e.g., configuration, major event */ #define jfs_info(fmt, arg...) do { \ @@ -112,11 +110,6 @@ extern int jfs_txanchor_read(char *, char **, off_t, int, int *, void *); * ---------- */ #ifdef CONFIG_JFS_STATISTICS -extern int jfs_lmstats_read(char *, char **, off_t, int, int *, void *); -extern int jfs_txstats_read(char *, char **, off_t, int, int *, void *); -extern int jfs_mpstat_read(char *, char **, off_t, int, int *, void *); -extern int jfs_xtstat_read(char *, char **, off_t, int, int *, void *); - #define INCREMENT(x) ((x)++) #define DECREMENT(x) ((x)--) #define HIGHWATERMARK(x,y) ((x) = max((x), (y))) diff --git a/trunk/fs/jfs/jfs_dmap.c b/trunk/fs/jfs/jfs_dmap.c index cced2fed9d0f..69007fd546ef 100644 --- a/trunk/fs/jfs/jfs_dmap.c +++ b/trunk/fs/jfs/jfs_dmap.c @@ -272,6 +272,7 @@ int dbMount(struct inode *ipbmap) int dbUnmount(struct inode *ipbmap, int mounterror) { struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap; + int i; if (!(mounterror || isReadOnly(ipbmap))) dbSync(ipbmap); @@ -281,6 +282,14 @@ int dbUnmount(struct inode *ipbmap, int mounterror) */ truncate_inode_pages(ipbmap->i_mapping, 0); + /* + * Sanity Check + */ + for (i = 0; i < bmp->db_numag; i++) + if (atomic_read(&bmp->db_active[i])) + printk(KERN_ERR "dbUnmount: db_active[%d] = %d\n", + i, atomic_read(&bmp->db_active[i])); + /* free the memory for the in-memory bmap. */ kfree(bmp); diff --git a/trunk/fs/jfs/jfs_dtree.c b/trunk/fs/jfs/jfs_dtree.c index 8676aee3ae48..ac41f72d6d50 100644 --- a/trunk/fs/jfs/jfs_dtree.c +++ b/trunk/fs/jfs/jfs_dtree.c @@ -2931,9 +2931,6 @@ static void add_missing_indices(struct inode *inode, s64 bn) ASSERT(p->header.flag & BT_LEAF); tlck = txLock(tid, inode, mp, tlckDTREE | tlckENTRY); - if (BT_IS_ROOT(mp)) - tlck->type |= tlckBTROOT; - dtlck = (struct dt_lock *) &tlck->lock; stbl = DT_GETSTBL(p); diff --git a/trunk/fs/jfs/jfs_extent.c b/trunk/fs/jfs/jfs_extent.c index 4879603daa1c..1953acb79266 100644 --- a/trunk/fs/jfs/jfs_extent.c +++ b/trunk/fs/jfs/jfs_extent.c @@ -19,7 +19,6 @@ #include #include #include "jfs_incore.h" -#include "jfs_inode.h" #include "jfs_superblock.h" #include "jfs_dmap.h" #include "jfs_extent.h" @@ -34,6 +33,12 @@ static int extBrealloc(struct inode *, s64, s64, s64 *, s64 *); #endif static s64 extRoundDown(s64 nb); +/* + * external references + */ +extern int jfs_commit_inode(struct inode *, int); + + #define DPD(a) (printk("(a): %d\n",(a))) #define DPC(a) (printk("(a): %c\n",(a))) #define DPL1(a) \ diff --git a/trunk/fs/jfs/jfs_imap.c b/trunk/fs/jfs/jfs_imap.c index 971af2977eff..7acff2ce3c80 100644 --- a/trunk/fs/jfs/jfs_imap.c +++ b/trunk/fs/jfs/jfs_imap.c @@ -47,7 +47,6 @@ #include #include "jfs_incore.h" -#include "jfs_inode.h" #include "jfs_filsys.h" #include "jfs_dinode.h" #include "jfs_dmap.h" @@ -69,6 +68,11 @@ #define AG_LOCK(imap,agno) down(&imap->im_aglock[agno]) #define AG_UNLOCK(imap,agno) up(&imap->im_aglock[agno]) +/* + * external references + */ +extern struct address_space_operations jfs_aops; + /* * forward references */ diff --git a/trunk/fs/jfs/jfs_inode.c b/trunk/fs/jfs/jfs_inode.c index 2af5efbfd06f..84f2459b2191 100644 --- a/trunk/fs/jfs/jfs_inode.c +++ b/trunk/fs/jfs/jfs_inode.c @@ -19,7 +19,6 @@ #include #include #include "jfs_incore.h" -#include "jfs_inode.h" #include "jfs_filsys.h" #include "jfs_imap.h" #include "jfs_dinode.h" diff --git a/trunk/fs/jfs/jfs_inode.h b/trunk/fs/jfs/jfs_inode.h index b54bac576cb3..3df91fbfe781 100644 --- a/trunk/fs/jfs/jfs_inode.h +++ b/trunk/fs/jfs/jfs_inode.h @@ -1,5 +1,5 @@ /* - * Copyright (C) International Business Machines Corp., 2000-2001 + * Copyright (c) International Business Machines Corp., 2000-2001 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,22 +19,5 @@ #define _H_JFS_INODE extern struct inode *ialloc(struct inode *, umode_t); -extern int jfs_fsync(struct file *, struct dentry *, int); -extern void jfs_read_inode(struct inode *); -extern int jfs_commit_inode(struct inode *, int); -extern int jfs_write_inode(struct inode*, int); -extern void jfs_delete_inode(struct inode *); -extern void jfs_dirty_inode(struct inode *); -extern void jfs_truncate(struct inode *); -extern void jfs_truncate_nolock(struct inode *, loff_t); -extern void jfs_free_zero_link(struct inode *); -extern struct dentry *jfs_get_parent(struct dentry *dentry); -extern struct address_space_operations jfs_aops; -extern struct inode_operations jfs_dir_inode_operations; -extern struct file_operations jfs_dir_operations; -extern struct inode_operations jfs_file_inode_operations; -extern struct file_operations jfs_file_operations; -extern struct inode_operations jfs_symlink_inode_operations; -extern struct dentry_operations jfs_ci_dentry_operations; #endif /* _H_JFS_INODE */ diff --git a/trunk/fs/jfs/jfs_logmgr.c b/trunk/fs/jfs/jfs_logmgr.c index 7c8387ed4192..dfa1200daa61 100644 --- a/trunk/fs/jfs/jfs_logmgr.c +++ b/trunk/fs/jfs/jfs_logmgr.c @@ -71,7 +71,6 @@ #include "jfs_incore.h" #include "jfs_filsys.h" #include "jfs_metapage.h" -#include "jfs_superblock.h" #include "jfs_txnmgr.h" #include "jfs_debug.h" @@ -167,6 +166,14 @@ static LIST_HEAD(jfs_external_logs); static struct jfs_log *dummy_log = NULL; static DECLARE_MUTEX(jfs_log_sem); +/* + * external references + */ +extern void txLazyUnlock(struct tblock * tblk); +extern int jfs_stop_threads; +extern struct completion jfsIOwait; +extern int jfs_tlocks_low; + /* * forward references */ @@ -1617,8 +1624,6 @@ void jfs_flush_journal(struct jfs_log *log, int wait) } } assert(list_empty(&log->cqueue)); - -#ifdef CONFIG_JFS_DEBUG if (!list_empty(&log->synclist)) { struct logsyncblk *lp; @@ -1633,8 +1638,9 @@ void jfs_flush_journal(struct jfs_log *log, int wait) dump_mem("orphan tblock", lp, sizeof(struct tblock)); } +// current->state = TASK_INTERRUPTIBLE; +// schedule(); } -#endif //assert(list_empty(&log->synclist)); clear_bit(log_FLUSH, &log->flag); } diff --git a/trunk/fs/jfs/jfs_logmgr.h b/trunk/fs/jfs/jfs_logmgr.h index 747114cd38b8..51291fbc420c 100644 --- a/trunk/fs/jfs/jfs_logmgr.h +++ b/trunk/fs/jfs/jfs_logmgr.h @@ -507,8 +507,6 @@ extern int lmLogClose(struct super_block *sb); extern int lmLogShutdown(struct jfs_log * log); extern int lmLogInit(struct jfs_log * log); extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize); -extern int lmGroupCommit(struct jfs_log *, struct tblock *); -extern int jfsIOWait(void *); extern void jfs_flush_journal(struct jfs_log * log, int wait); extern void jfs_syncpt(struct jfs_log *log); diff --git a/trunk/fs/jfs/jfs_metapage.c b/trunk/fs/jfs/jfs_metapage.c index 6c5485d16c39..41bf078dce05 100644 --- a/trunk/fs/jfs/jfs_metapage.c +++ b/trunk/fs/jfs/jfs_metapage.c @@ -198,7 +198,7 @@ static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) } } -static inline struct metapage *alloc_metapage(unsigned int gfp_mask) +static inline struct metapage *alloc_metapage(int gfp_mask) { return mempool_alloc(metapage_mempool, gfp_mask); } @@ -726,12 +726,12 @@ void force_metapage(struct metapage *mp) page_cache_release(page); } -void hold_metapage(struct metapage *mp) +extern void hold_metapage(struct metapage *mp) { lock_page(mp->page); } -void put_metapage(struct metapage *mp) +extern void put_metapage(struct metapage *mp) { if (mp->count || mp->nohomeok) { /* Someone else will release this */ diff --git a/trunk/fs/jfs/jfs_metapage.h b/trunk/fs/jfs/jfs_metapage.h index f0b7d3282b07..991e9fb84c75 100644 --- a/trunk/fs/jfs/jfs_metapage.h +++ b/trunk/fs/jfs/jfs_metapage.h @@ -1,6 +1,6 @@ /* - * Copyright (C) International Business Machines Corp., 2000-2002 - * Portions Copyright (C) Christoph Hellwig, 2001-2002 + * Copyright (c) International Business Machines Corp., 2000-2002 + * Portions Copyright (c) Christoph Hellwig, 2001-2002 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,8 +58,6 @@ struct metapage { #define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag) /* function prototypes */ -extern int metapage_init(void); -extern void metapage_exit(void); extern struct metapage *__get_metapage(struct inode *inode, unsigned long lblock, unsigned int size, int absolute, unsigned long new); diff --git a/trunk/fs/jfs/jfs_superblock.h b/trunk/fs/jfs/jfs_superblock.h index fcf781bf31cb..ab0566f70cfa 100644 --- a/trunk/fs/jfs/jfs_superblock.h +++ b/trunk/fs/jfs/jfs_superblock.h @@ -109,16 +109,5 @@ struct jfs_superblock { extern int readSuper(struct super_block *, struct buffer_head **); extern int updateSuper(struct super_block *, uint); extern void jfs_error(struct super_block *, const char *, ...); -extern int jfs_mount(struct super_block *); -extern int jfs_mount_rw(struct super_block *, int); -extern int jfs_umount(struct super_block *); -extern int jfs_umount_rw(struct super_block *); - -extern int jfs_stop_threads; -extern struct completion jfsIOwait; -extern wait_queue_head_t jfs_IO_thread_wait; -extern wait_queue_head_t jfs_commit_thread_wait; -extern wait_queue_head_t jfs_sync_thread_wait; -extern int jfs_extendfs(struct super_block *, s64, int); #endif /*_H_JFS_SUPERBLOCK */ diff --git a/trunk/fs/jfs/jfs_txnmgr.c b/trunk/fs/jfs/jfs_txnmgr.c index 8cbaaff1d5fa..e93d01aa12c4 100644 --- a/trunk/fs/jfs/jfs_txnmgr.c +++ b/trunk/fs/jfs/jfs_txnmgr.c @@ -42,6 +42,7 @@ * hold on to mp+lock thru update of maps */ + #include #include #include @@ -50,7 +51,6 @@ #include #include #include "jfs_incore.h" -#include "jfs_inode.h" #include "jfs_filsys.h" #include "jfs_metapage.h" #include "jfs_dinode.h" @@ -109,6 +109,7 @@ static int TxLockHWM; /* High water mark for number of txLocks used */ static int TxLockVHWM; /* Very High water mark */ struct tlock *TxLock; /* transaction lock table */ + /* * transaction management lock */ @@ -148,6 +149,7 @@ static inline void TXN_SLEEP_DROP_LOCK(wait_queue_head_t * event) #define TXN_WAKEUP(event) wake_up_all(event) + /* * statistics */ @@ -159,6 +161,16 @@ static struct { int waitlock; /* 4: # of tlock wait */ } stattx; + +/* + * external references + */ +extern int lmGroupCommit(struct jfs_log *, struct tblock *); +extern int jfs_commit_inode(struct inode *, int); +extern int jfs_stop_threads; + +extern struct completion jfsIOwait; + /* * forward references */ @@ -346,6 +358,7 @@ void txExit(void) TxBlock = NULL; } + /* * NAME: txBegin() * @@ -447,6 +460,7 @@ tid_t txBegin(struct super_block *sb, int flag) return t; } + /* * NAME: txBeginAnon() * @@ -489,6 +503,7 @@ void txBeginAnon(struct super_block *sb) TXN_UNLOCK(); } + /* * txEnd() * @@ -577,6 +592,7 @@ void txEnd(tid_t tid) TXN_WAKEUP(&TxAnchor.freewait); } + /* * txLock() * @@ -852,6 +868,7 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, return NULL; } + /* * NAME: txRelease() * @@ -891,6 +908,7 @@ static void txRelease(struct tblock * tblk) TXN_UNLOCK(); } + /* * NAME: txUnlock() * @@ -978,6 +996,7 @@ static void txUnlock(struct tblock * tblk) } } + /* * txMaplock() * @@ -1050,6 +1069,7 @@ struct tlock *txMaplock(tid_t tid, struct inode *ip, int type) return tlck; } + /* * txLinelock() * @@ -1083,6 +1103,8 @@ struct linelock *txLinelock(struct linelock * tlock) return linelock; } + + /* * transaction commit management * ----------------------------- @@ -1351,6 +1373,7 @@ int txCommit(tid_t tid, /* transaction identifier */ return rc; } + /* * NAME: txLog() * @@ -1414,6 +1437,7 @@ static int txLog(struct jfs_log * log, struct tblock * tblk, struct commit * cd) return rc; } + /* * diLog() * @@ -1441,6 +1465,7 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, if (tlck->type & tlckENTRY) { /* log after-image for logredo(): */ lrd->type = cpu_to_le16(LOG_REDOPAGE); +// *pxd = mp->cm_pxd; PXDaddress(pxd, mp->index); PXDlength(pxd, mp->logical_size >> tblk->sb->s_blocksize_bits); @@ -1527,6 +1552,7 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, return rc; } + /* * dataLog() * @@ -1573,6 +1599,7 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, return 0; } + /* * dtLog() * @@ -1612,6 +1639,7 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, lrd->log.redopage.type |= cpu_to_le16(LOG_EXTEND); else lrd->log.redopage.type |= cpu_to_le16(LOG_NEW); +// *pxd = mp->cm_pxd; PXDaddress(pxd, mp->index); PXDlength(pxd, mp->logical_size >> tblk->sb->s_blocksize_bits); @@ -1676,6 +1704,7 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, return; } + /* * xtLog() * @@ -1731,6 +1760,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, * applying the after-image to the meta-data page. */ lrd->type = cpu_to_le16(LOG_REDOPAGE); +// *page_pxd = mp->cm_pxd; PXDaddress(page_pxd, mp->index); PXDlength(page_pxd, mp->logical_size >> tblk->sb->s_blocksize_bits); @@ -2063,6 +2093,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, return; } + /* * mapLog() * @@ -2149,6 +2180,7 @@ void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, } } + /* * txEA() * @@ -2201,6 +2233,7 @@ void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea) } } + /* * txForce() * @@ -2267,6 +2300,7 @@ void txForce(struct tblock * tblk) } } + /* * txUpdateMap() * @@ -2403,6 +2437,7 @@ static void txUpdateMap(struct tblock * tblk) } } + /* * txAllocPMap() * @@ -2474,6 +2509,7 @@ static void txAllocPMap(struct inode *ip, struct maplock * maplock, } } + /* * txFreeMap() * @@ -2575,6 +2611,7 @@ void txFreeMap(struct inode *ip, } } + /* * txFreelock() * @@ -2615,6 +2652,7 @@ void txFreelock(struct inode *ip) TXN_UNLOCK(); } + /* * txAbort() * diff --git a/trunk/fs/jfs/jfs_txnmgr.h b/trunk/fs/jfs/jfs_txnmgr.h index 59ad0f6b7231..b71b82c2df04 100644 --- a/trunk/fs/jfs/jfs_txnmgr.h +++ b/trunk/fs/jfs/jfs_txnmgr.h @@ -285,26 +285,34 @@ struct commit { /* * external declarations */ -extern int jfs_tlocks_low; - -extern int txInit(void); -extern void txExit(void); -extern struct tlock *txLock(tid_t, struct inode *, struct metapage *, int); -extern struct tlock *txMaplock(tid_t, struct inode *, int); -extern int txCommit(tid_t, int, struct inode **, int); -extern tid_t txBegin(struct super_block *, int); -extern void txBeginAnon(struct super_block *); -extern void txEnd(tid_t); -extern void txAbort(tid_t, int); -extern struct linelock *txLinelock(struct linelock *); -extern void txFreeMap(struct inode *, struct maplock *, struct tblock *, int); -extern void txEA(tid_t, struct inode *, dxd_t *, dxd_t *); -extern void txFreelock(struct inode *); -extern int lmLog(struct jfs_log *, struct tblock *, struct lrd *, - struct tlock *); -extern void txQuiesce(struct super_block *); -extern void txResume(struct super_block *); -extern void txLazyUnlock(struct tblock *); -extern int jfs_lazycommit(void *); -extern int jfs_sync(void *); +extern struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage *mp, + int flag); + +extern struct tlock *txMaplock(tid_t tid, struct inode *ip, int flag); + +extern int txCommit(tid_t tid, int nip, struct inode **iplist, int flag); + +extern tid_t txBegin(struct super_block *sb, int flag); + +extern void txBeginAnon(struct super_block *sb); + +extern void txEnd(tid_t tid); + +extern void txAbort(tid_t tid, int dirty); + +extern struct linelock *txLinelock(struct linelock * tlock); + +extern void txFreeMap(struct inode *ip, struct maplock * maplock, + struct tblock * tblk, int maptype); + +extern void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea); + +extern void txFreelock(struct inode *ip); + +extern int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, + struct tlock * tlck); + +extern void txQuiesce(struct super_block *sb); + +extern void txResume(struct super_block *sb); #endif /* _H_JFS_TXNMGR */ diff --git a/trunk/fs/jfs/namei.c b/trunk/fs/jfs/namei.c index 1cae14e741eb..8413a368f449 100644 --- a/trunk/fs/jfs/namei.c +++ b/trunk/fs/jfs/namei.c @@ -31,9 +31,20 @@ #include "jfs_acl.h" #include "jfs_debug.h" +extern struct inode_operations jfs_file_inode_operations; +extern struct inode_operations jfs_symlink_inode_operations; +extern struct file_operations jfs_file_operations; +extern struct address_space_operations jfs_aops; + +extern int jfs_fsync(struct file *, struct dentry *, int); +extern void jfs_truncate_nolock(struct inode *, loff_t); +extern int jfs_init_acl(struct inode *, struct inode *); + /* * forward references */ +struct inode_operations jfs_dir_inode_operations; +struct file_operations jfs_dir_operations; struct dentry_operations jfs_ci_dentry_operations; static s64 commitZeroLink(tid_t, struct inode *); @@ -644,7 +655,7 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip) /* - * NAME: jfs_free_zero_link() + * NAME: freeZeroLink() * * FUNCTION: for non-directory, called by iClose(), * free resources of a file from cache and WORKING map @@ -652,12 +663,15 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip) * while associated with a pager object, * * PARAMETER: ip - pointer to inode of file. + * + * RETURN: 0 -ok */ -void jfs_free_zero_link(struct inode *ip) +int freeZeroLink(struct inode *ip) { + int rc = 0; int type; - jfs_info("jfs_free_zero_link: ip = 0x%p", ip); + jfs_info("freeZeroLink: ip = 0x%p", ip); /* return if not reg or symbolic link or if size is * already ok. @@ -670,10 +684,10 @@ void jfs_free_zero_link(struct inode *ip) case S_IFLNK: /* if its contained in inode nothing to do */ if (ip->i_size < IDATASIZE) - return; + return 0; break; default: - return; + return 0; } /* @@ -723,7 +737,9 @@ void jfs_free_zero_link(struct inode *ip) * free xtree/data blocks from working block map; */ if (ip->i_size) - xtTruncate(0, ip, 0, COMMIT_WMAP); + rc = xtTruncate(0, ip, 0, COMMIT_WMAP); + + return rc; } /* diff --git a/trunk/fs/jfs/super.c b/trunk/fs/jfs/super.c index 810a3653d8b3..5e774ed7fb64 100644 --- a/trunk/fs/jfs/super.c +++ b/trunk/fs/jfs/super.c @@ -28,7 +28,6 @@ #include "jfs_incore.h" #include "jfs_filsys.h" -#include "jfs_inode.h" #include "jfs_metapage.h" #include "jfs_superblock.h" #include "jfs_dmap.h" @@ -63,6 +62,37 @@ module_param(jfsloglevel, int, 0644); MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)"); #endif +/* + * External declarations + */ +extern int jfs_mount(struct super_block *); +extern int jfs_mount_rw(struct super_block *, int); +extern int jfs_umount(struct super_block *); +extern int jfs_umount_rw(struct super_block *); + +extern int jfsIOWait(void *); +extern int jfs_lazycommit(void *); +extern int jfs_sync(void *); + +extern void jfs_read_inode(struct inode *inode); +extern void jfs_dirty_inode(struct inode *inode); +extern void jfs_delete_inode(struct inode *inode); +extern int jfs_write_inode(struct inode *inode, int wait); + +extern struct dentry *jfs_get_parent(struct dentry *dentry); +extern int jfs_extendfs(struct super_block *, s64, int); + +extern struct dentry_operations jfs_ci_dentry_operations; + +#ifdef PROC_FS_JFS /* see jfs_debug.h */ +extern void jfs_proc_init(void); +extern void jfs_proc_clean(void); +#endif + +extern wait_queue_head_t jfs_IO_thread_wait; +extern wait_queue_head_t jfs_commit_thread_wait; +extern wait_queue_head_t jfs_sync_thread_wait; + static void jfs_handle_error(struct super_block *sb) { struct jfs_sb_info *sbi = JFS_SBI(sb); @@ -563,6 +593,11 @@ static struct file_system_type jfs_fs_type = { .fs_flags = FS_REQUIRES_DEV, }; +extern int metapage_init(void); +extern int txInit(void); +extern void txExit(void); +extern void metapage_exit(void); + static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags) { struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo; diff --git a/trunk/fs/jfs/symlink.c b/trunk/fs/jfs/symlink.c index 287d8d6c3cfd..ef4c07ee92b2 100644 --- a/trunk/fs/jfs/symlink.c +++ b/trunk/fs/jfs/symlink.c @@ -1,5 +1,5 @@ /* - * Copyright (C) Christoph Hellwig, 2001-2002 + * Copyright (c) Christoph Hellwig, 2001-2002 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,6 @@ #include #include #include "jfs_incore.h" -#include "jfs_inode.h" #include "jfs_xattr.h" static int jfs_follow_link(struct dentry *dentry, struct nameidata *nd) diff --git a/trunk/fs/jfs/xattr.c b/trunk/fs/jfs/xattr.c index 6016373701a3..7a9ffd5d03dc 100644 --- a/trunk/fs/jfs/xattr.c +++ b/trunk/fs/jfs/xattr.c @@ -946,7 +946,8 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value, out: up_write(&JFS_IP(inode)->xattr_sem); - kfree(os2name); + if (os2name) + kfree(os2name); return rc; } @@ -1041,7 +1042,8 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data, out: up_read(&JFS_IP(inode)->xattr_sem); - kfree(os2name); + if (os2name) + kfree(os2name); return size; } diff --git a/trunk/include/linux/netfilter_ipv4.h b/trunk/include/linux/netfilter_ipv4.h index 3ebc36afae1a..9e5750079e09 100644 --- a/trunk/include/linux/netfilter_ipv4.h +++ b/trunk/include/linux/netfilter_ipv4.h @@ -75,6 +75,12 @@ enum nf_ip_hook_priorities { #define SO_ORIGINAL_DST 80 #ifdef __KERNEL__ +#ifdef CONFIG_NETFILTER_DEBUG +void nf_debug_ip_local_deliver(struct sk_buff *skb); +void nf_debug_ip_loopback_xmit(struct sk_buff *newskb); +void nf_debug_ip_finish_output2(struct sk_buff *skb); +#endif /*CONFIG_NETFILTER_DEBUG*/ + extern int ip_route_me_harder(struct sk_buff **pskb); /* Call this before modifying an existing IP packet: ensures it is diff --git a/trunk/include/linux/netfilter_ipv4/ip_conntrack_core.h b/trunk/include/linux/netfilter_ipv4/ip_conntrack_core.h index 694aec9b4784..d84be02cb4fc 100644 --- a/trunk/include/linux/netfilter_ipv4/ip_conntrack_core.h +++ b/trunk/include/linux/netfilter_ipv4/ip_conntrack_core.h @@ -1,6 +1,7 @@ #ifndef _IP_CONNTRACK_CORE_H #define _IP_CONNTRACK_CORE_H #include +#include /* This header is used to share core functionality between the standalone connection tracking module, and the compatibility layer's use @@ -46,6 +47,6 @@ static inline int ip_conntrack_confirm(struct sk_buff **pskb) extern struct list_head *ip_conntrack_hash; extern struct list_head ip_conntrack_expect_list; -extern rwlock_t ip_conntrack_lock; +DECLARE_RWLOCK_EXTERN(ip_conntrack_lock); #endif /* _IP_CONNTRACK_CORE_H */ diff --git a/trunk/include/linux/netfilter_ipv4/ip_nat.h b/trunk/include/linux/netfilter_ipv4/ip_nat.h index e201ec6e9905..2b72b86176f0 100644 --- a/trunk/include/linux/netfilter_ipv4/ip_nat.h +++ b/trunk/include/linux/netfilter_ipv4/ip_nat.h @@ -50,9 +50,10 @@ struct ip_nat_multi_range_compat #ifdef __KERNEL__ #include +#include /* Protects NAT hash tables, and NAT-private part of conntracks. */ -extern rwlock_t ip_nat_lock; +DECLARE_RWLOCK_EXTERN(ip_nat_lock); /* The structure embedded in the conntrack structure. */ struct ip_nat_info diff --git a/trunk/include/linux/netfilter_ipv4/listhelp.h b/trunk/include/linux/netfilter_ipv4/listhelp.h index 360429f48737..f2ae7c5e57bb 100644 --- a/trunk/include/linux/netfilter_ipv4/listhelp.h +++ b/trunk/include/linux/netfilter_ipv4/listhelp.h @@ -2,6 +2,7 @@ #define _LISTHELP_H #include #include +#include /* Header to do more comprehensive job than linux/list.h; assume list is first entry in structure. */ diff --git a/trunk/include/linux/netfilter_ipv4/lockhelp.h b/trunk/include/linux/netfilter_ipv4/lockhelp.h new file mode 100644 index 000000000000..a3288633ab46 --- /dev/null +++ b/trunk/include/linux/netfilter_ipv4/lockhelp.h @@ -0,0 +1,129 @@ +#ifndef _LOCKHELP_H +#define _LOCKHELP_H +#include + +#include +#include +#include +#include + +/* Header to do help in lock debugging. */ + +#ifdef CONFIG_NETFILTER_DEBUG +struct spinlock_debug +{ + spinlock_t l; + atomic_t locked_by; +}; + +struct rwlock_debug +{ + rwlock_t l; + long read_locked_map; + long write_locked_map; +}; + +#define DECLARE_LOCK(l) \ +struct spinlock_debug l = { SPIN_LOCK_UNLOCKED, ATOMIC_INIT(-1) } +#define DECLARE_LOCK_EXTERN(l) \ +extern struct spinlock_debug l +#define DECLARE_RWLOCK(l) \ +struct rwlock_debug l = { RW_LOCK_UNLOCKED, 0, 0 } +#define DECLARE_RWLOCK_EXTERN(l) \ +extern struct rwlock_debug l + +#define MUST_BE_LOCKED(l) \ +do { if (atomic_read(&(l)->locked_by) != smp_processor_id()) \ + printk("ASSERT %s:%u %s unlocked\n", __FILE__, __LINE__, #l); \ +} while(0) + +#define MUST_BE_UNLOCKED(l) \ +do { if (atomic_read(&(l)->locked_by) == smp_processor_id()) \ + printk("ASSERT %s:%u %s locked\n", __FILE__, __LINE__, #l); \ +} while(0) + +/* Write locked OK as well. */ +#define MUST_BE_READ_LOCKED(l) \ +do { if (!((l)->read_locked_map & (1UL << smp_processor_id())) \ + && !((l)->write_locked_map & (1UL << smp_processor_id()))) \ + printk("ASSERT %s:%u %s not readlocked\n", __FILE__, __LINE__, #l); \ +} while(0) + +#define MUST_BE_WRITE_LOCKED(l) \ +do { if (!((l)->write_locked_map & (1UL << smp_processor_id()))) \ + printk("ASSERT %s:%u %s not writelocked\n", __FILE__, __LINE__, #l); \ +} while(0) + +#define MUST_BE_READ_WRITE_UNLOCKED(l) \ +do { if ((l)->read_locked_map & (1UL << smp_processor_id())) \ + printk("ASSERT %s:%u %s readlocked\n", __FILE__, __LINE__, #l); \ + else if ((l)->write_locked_map & (1UL << smp_processor_id())) \ + printk("ASSERT %s:%u %s writelocked\n", __FILE__, __LINE__, #l); \ +} while(0) + +#define LOCK_BH(lk) \ +do { \ + MUST_BE_UNLOCKED(lk); \ + spin_lock_bh(&(lk)->l); \ + atomic_set(&(lk)->locked_by, smp_processor_id()); \ +} while(0) + +#define UNLOCK_BH(lk) \ +do { \ + MUST_BE_LOCKED(lk); \ + atomic_set(&(lk)->locked_by, -1); \ + spin_unlock_bh(&(lk)->l); \ +} while(0) + +#define READ_LOCK(lk) \ +do { \ + MUST_BE_READ_WRITE_UNLOCKED(lk); \ + read_lock_bh(&(lk)->l); \ + set_bit(smp_processor_id(), &(lk)->read_locked_map); \ +} while(0) + +#define WRITE_LOCK(lk) \ +do { \ + MUST_BE_READ_WRITE_UNLOCKED(lk); \ + write_lock_bh(&(lk)->l); \ + set_bit(smp_processor_id(), &(lk)->write_locked_map); \ +} while(0) + +#define READ_UNLOCK(lk) \ +do { \ + if (!((lk)->read_locked_map & (1UL << smp_processor_id()))) \ + printk("ASSERT: %s:%u %s not readlocked\n", \ + __FILE__, __LINE__, #lk); \ + clear_bit(smp_processor_id(), &(lk)->read_locked_map); \ + read_unlock_bh(&(lk)->l); \ +} while(0) + +#define WRITE_UNLOCK(lk) \ +do { \ + MUST_BE_WRITE_LOCKED(lk); \ + clear_bit(smp_processor_id(), &(lk)->write_locked_map); \ + write_unlock_bh(&(lk)->l); \ +} while(0) + +#else +#define DECLARE_LOCK(l) spinlock_t l = SPIN_LOCK_UNLOCKED +#define DECLARE_LOCK_EXTERN(l) extern spinlock_t l +#define DECLARE_RWLOCK(l) rwlock_t l = RW_LOCK_UNLOCKED +#define DECLARE_RWLOCK_EXTERN(l) extern rwlock_t l + +#define MUST_BE_LOCKED(l) +#define MUST_BE_UNLOCKED(l) +#define MUST_BE_READ_LOCKED(l) +#define MUST_BE_WRITE_LOCKED(l) +#define MUST_BE_READ_WRITE_UNLOCKED(l) + +#define LOCK_BH(l) spin_lock_bh(l) +#define UNLOCK_BH(l) spin_unlock_bh(l) + +#define READ_LOCK(l) read_lock_bh(l) +#define WRITE_LOCK(l) write_lock_bh(l) +#define READ_UNLOCK(l) read_unlock_bh(l) +#define WRITE_UNLOCK(l) write_unlock_bh(l) +#endif /*CONFIG_NETFILTER_DEBUG*/ + +#endif /* _LOCKHELP_H */ diff --git a/trunk/include/linux/netlink.h b/trunk/include/linux/netlink.h index 3029cad63a01..561d4dc75836 100644 --- a/trunk/include/linux/netlink.h +++ b/trunk/include/linux/netlink.h @@ -147,7 +147,7 @@ struct netlink_callback int (*dump)(struct sk_buff * skb, struct netlink_callback *cb); int (*done)(struct netlink_callback *cb); int family; - long args[5]; + long args[4]; }; struct netlink_notify diff --git a/trunk/include/linux/skbuff.h b/trunk/include/linux/skbuff.h index d7c839a21842..cc04f5cd2286 100644 --- a/trunk/include/linux/skbuff.h +++ b/trunk/include/linux/skbuff.h @@ -193,6 +193,7 @@ struct skb_shared_info { * @nfcache: Cache info * @nfct: Associated connection, if any * @nfctinfo: Relationship of this skb to the connection + * @nf_debug: Netfilter debugging * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c * @private: Data which is private to the HIPPI implementation * @tc_index: Traffic control index @@ -263,6 +264,9 @@ struct sk_buff { __u32 nfcache; __u32 nfctinfo; struct nf_conntrack *nfct; +#ifdef CONFIG_NETFILTER_DEBUG + unsigned int nf_debug; +#endif #ifdef CONFIG_BRIDGE_NETFILTER struct nf_bridge_info *nf_bridge; #endif @@ -1215,6 +1219,15 @@ static inline void nf_reset(struct sk_buff *skb) { nf_conntrack_put(skb->nfct); skb->nfct = NULL; +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug = 0; +#endif +} +static inline void nf_reset_debug(struct sk_buff *skb) +{ +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug = 0; +#endif } #ifdef CONFIG_BRIDGE_NETFILTER diff --git a/trunk/include/net/ip6_fib.h b/trunk/include/net/ip6_fib.h index a66e9de16a6c..319904518194 100644 --- a/trunk/include/net/ip6_fib.h +++ b/trunk/include/net/ip6_fib.h @@ -167,17 +167,14 @@ extern int fib6_walk_continue(struct fib6_walker_t *w); extern int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh, - void *rtattr, - struct netlink_skb_parms *req); + void *rtattr); extern int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, - void *rtattr, - struct netlink_skb_parms *req); + void *rtattr); extern void inet6_rt_notify(int event, struct rt6_info *rt, - struct nlmsghdr *nlh, - struct netlink_skb_parms *req); + struct nlmsghdr *nlh); extern void fib6_run_gc(unsigned long dummy); diff --git a/trunk/include/net/ip6_route.h b/trunk/include/net/ip6_route.h index f920706d526b..d5d1dd10cdb8 100644 --- a/trunk/include/net/ip6_route.h +++ b/trunk/include/net/ip6_route.h @@ -41,16 +41,13 @@ extern int ipv6_route_ioctl(unsigned int cmd, void __user *arg); extern int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *, - void *rtattr, - struct netlink_skb_parms *req); + void *rtattr); extern int ip6_ins_rt(struct rt6_info *, struct nlmsghdr *, - void *rtattr, - struct netlink_skb_parms *req); + void *rtattr); extern int ip6_del_rt(struct rt6_info *, struct nlmsghdr *, - void *rtattr, - struct netlink_skb_parms *req); + void *rtattr); extern int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev, diff --git a/trunk/net/bridge/br_forward.c b/trunk/net/bridge/br_forward.c index 069253f830c1..ef9f2095f96e 100644 --- a/trunk/net/bridge/br_forward.c +++ b/trunk/net/bridge/br_forward.c @@ -57,6 +57,9 @@ int br_forward_finish(struct sk_buff *skb) static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) { skb->dev = to->dev; +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug = 0; +#endif NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, br_forward_finish); } diff --git a/trunk/net/bridge/br_input.c b/trunk/net/bridge/br_input.c index 9a45e6279c57..8f5f2e730992 100644 --- a/trunk/net/bridge/br_input.c +++ b/trunk/net/bridge/br_input.c @@ -23,7 +23,11 @@ const unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; static int br_pass_frame_up_finish(struct sk_buff *skb) { +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug = 0; +#endif netif_receive_skb(skb); + return 0; } diff --git a/trunk/net/bridge/br_netfilter.c b/trunk/net/bridge/br_netfilter.c index 03ae4edddac3..be03d3ad2648 100644 --- a/trunk/net/bridge/br_netfilter.c +++ b/trunk/net/bridge/br_netfilter.c @@ -102,6 +102,10 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) { struct nf_bridge_info *nf_bridge = skb->nf_bridge; +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING); +#endif + if (nf_bridge->mask & BRNF_PKT_TYPE) { skb->pkt_type = PACKET_OTHERHOST; nf_bridge->mask ^= BRNF_PKT_TYPE; @@ -178,6 +182,10 @@ static void __br_dnat_complain(void) * --Bart, 20021007 (updated) */ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) { +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug |= (1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_FORWARD); +#endif + if (skb->pkt_type == PACKET_OTHERHOST) { skb->pkt_type = PACKET_HOST; skb->nf_bridge->mask |= BRNF_PKT_TYPE; @@ -199,6 +207,10 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) struct iphdr *iph = skb->nh.iph; struct nf_bridge_info *nf_bridge = skb->nf_bridge; +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING); +#endif + if (nf_bridge->mask & BRNF_PKT_TYPE) { skb->pkt_type = PACKET_OTHERHOST; nf_bridge->mask ^= BRNF_PKT_TYPE; @@ -370,6 +382,9 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb)) goto inhdr_error; +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug ^= (1 << NF_IP6_PRE_ROUTING); +#endif if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) return NF_DROP; setup_pre_routing(skb); @@ -453,6 +468,9 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb, skb->ip_summed = CHECKSUM_NONE; } +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug ^= (1 << NF_IP_PRE_ROUTING); +#endif if ((nf_bridge = nf_bridge_alloc(skb)) == NULL) return NF_DROP; setup_pre_routing(skb); @@ -499,6 +517,10 @@ static int br_nf_forward_finish(struct sk_buff *skb) struct net_device *in; struct vlan_ethhdr *hdr = vlan_eth_hdr(skb); +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug ^= (1 << NF_BR_FORWARD); +#endif + if (skb->protocol != __constant_htons(ETH_P_ARP) && !IS_VLAN_ARP) { in = nf_bridge->physindev; if (nf_bridge->mask & BRNF_PKT_TYPE) { @@ -544,6 +566,9 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb, (*pskb)->nh.raw += VLAN_HLEN; } +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug ^= (1 << NF_BR_FORWARD); +#endif nf_bridge = skb->nf_bridge; if (skb->pkt_type == PACKET_OTHERHOST) { skb->pkt_type = PACKET_HOST; @@ -580,6 +605,10 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, (*pskb)->nh.raw += VLAN_HLEN; } +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug ^= (1 << NF_BR_FORWARD); +#endif + if (skb->nh.arph->ar_pln != 4) { if (IS_VLAN_ARP) { skb_push(*pskb, VLAN_HLEN); @@ -598,6 +627,9 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb, /* PF_BRIDGE/LOCAL_OUT ***********************************************/ static int br_nf_local_out_finish(struct sk_buff *skb) { +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug &= ~(1 << NF_BR_LOCAL_OUT); +#endif if (skb->protocol == __constant_htons(ETH_P_8021Q)) { skb_push(skb, VLAN_HLEN); skb->nh.raw -= VLAN_HLEN; @@ -699,6 +731,10 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb, realoutdev, br_nf_local_out_finish, NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1); } else { +#ifdef CONFIG_NETFILTER_DEBUG + skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT); +#endif + NF_HOOK_THRESH(pf, NF_IP_LOCAL_OUT, skb, realindev, realoutdev, br_nf_local_out_finish, NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1); @@ -743,6 +779,8 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb, printk(KERN_CRIT "br_netfilter: skb->dst == NULL."); goto print_error; } + + skb->nf_debug ^= (1 << NF_IP_POST_ROUTING); #endif /* We assume any code from br_dev_queue_push_xmit onwards doesn't care diff --git a/trunk/net/core/netfilter.c b/trunk/net/core/netfilter.c index 076c156d5eda..22a8f127c4aa 100644 --- a/trunk/net/core/netfilter.c +++ b/trunk/net/core/netfilter.c @@ -141,6 +141,136 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg) up(&nf_sockopt_mutex); } +#ifdef CONFIG_NETFILTER_DEBUG +#include +#include +#include + +static void debug_print_hooks_ip(unsigned int nf_debug) +{ + if (nf_debug & (1 << NF_IP_PRE_ROUTING)) { + printk("PRE_ROUTING "); + nf_debug ^= (1 << NF_IP_PRE_ROUTING); + } + if (nf_debug & (1 << NF_IP_LOCAL_IN)) { + printk("LOCAL_IN "); + nf_debug ^= (1 << NF_IP_LOCAL_IN); + } + if (nf_debug & (1 << NF_IP_FORWARD)) { + printk("FORWARD "); + nf_debug ^= (1 << NF_IP_FORWARD); + } + if (nf_debug & (1 << NF_IP_LOCAL_OUT)) { + printk("LOCAL_OUT "); + nf_debug ^= (1 << NF_IP_LOCAL_OUT); + } + if (nf_debug & (1 << NF_IP_POST_ROUTING)) { + printk("POST_ROUTING "); + nf_debug ^= (1 << NF_IP_POST_ROUTING); + } + if (nf_debug) + printk("Crap bits: 0x%04X", nf_debug); + printk("\n"); +} + +static void nf_dump_skb(int pf, struct sk_buff *skb) +{ + printk("skb: pf=%i %s dev=%s len=%u\n", + pf, + skb->sk ? "(owned)" : "(unowned)", + skb->dev ? skb->dev->name : "(no dev)", + skb->len); + switch (pf) { + case PF_INET: { + const struct iphdr *ip = skb->nh.iph; + __u32 *opt = (__u32 *) (ip + 1); + int opti; + __u16 src_port = 0, dst_port = 0; + + if (ip->protocol == IPPROTO_TCP + || ip->protocol == IPPROTO_UDP) { + struct tcphdr *tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl); + src_port = ntohs(tcp->source); + dst_port = ntohs(tcp->dest); + } + + printk("PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu" + " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu", + ip->protocol, NIPQUAD(ip->saddr), + src_port, NIPQUAD(ip->daddr), + dst_port, + ntohs(ip->tot_len), ip->tos, ntohs(ip->id), + ntohs(ip->frag_off), ip->ttl); + + for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++) + printk(" O=0x%8.8X", *opt++); + printk("\n"); + } + } +} + +void nf_debug_ip_local_deliver(struct sk_buff *skb) +{ + /* If it's a loopback packet, it must have come through + * NF_IP_LOCAL_OUT, NF_IP_RAW_INPUT, NF_IP_PRE_ROUTING and + * NF_IP_LOCAL_IN. Otherwise, must have gone through + * NF_IP_RAW_INPUT and NF_IP_PRE_ROUTING. */ + if (!skb->dev) { + printk("ip_local_deliver: skb->dev is NULL.\n"); + } else { + if (skb->nf_debug != ((1<nf_debug); + nf_dump_skb(PF_INET, skb); + } + } +} + +void nf_debug_ip_loopback_xmit(struct sk_buff *newskb) +{ + if (newskb->nf_debug != ((1 << NF_IP_LOCAL_OUT) + | (1 << NF_IP_POST_ROUTING))) { + printk("ip_dev_loopback_xmit: bad owned skb = %p: ", + newskb); + debug_print_hooks_ip(newskb->nf_debug); + nf_dump_skb(PF_INET, newskb); + } +} + +void nf_debug_ip_finish_output2(struct sk_buff *skb) +{ + /* If it's owned, it must have gone through the + * NF_IP_LOCAL_OUT and NF_IP_POST_ROUTING. + * Otherwise, must have gone through + * NF_IP_PRE_ROUTING, NF_IP_FORWARD and NF_IP_POST_ROUTING. + */ + if (skb->sk) { + if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT) + | (1 << NF_IP_POST_ROUTING))) { + printk("ip_finish_output: bad owned skb = %p: ", skb); + debug_print_hooks_ip(skb->nf_debug); + nf_dump_skb(PF_INET, skb); + } + } else { + if (skb->nf_debug != ((1 << NF_IP_PRE_ROUTING) + | (1 << NF_IP_FORWARD) + | (1 << NF_IP_POST_ROUTING))) { + /* Fragments, entunnelled packets, TCP RSTs + generated by ipt_REJECT will have no + owners, but still may be local */ + if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT) + | (1 << NF_IP_POST_ROUTING))){ + printk("ip_finish_output:" + " bad unowned skb = %p: ",skb); + debug_print_hooks_ip(skb->nf_debug); + nf_dump_skb(PF_INET, skb); + } + } + } +} +#endif /*CONFIG_NETFILTER_DEBUG*/ + /* Call get/setsockopt() */ static int nf_sockopt(struct sock *sk, int pf, int val, char __user *opt, int *len, int get) @@ -358,6 +488,14 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb, /* We may already have this, but read-locks nest anyway */ rcu_read_lock(); +#ifdef CONFIG_NETFILTER_DEBUG + if (unlikely((*pskb)->nf_debug & (1 << hook))) { + printk("nf_hook: hook %i already set.\n", hook); + nf_dump_skb(pf, *pskb); + } + (*pskb)->nf_debug |= (1 << hook); +#endif + elem = &nf_hooks[pf][hook]; next_hook: verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev, diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index 6d68c03bc051..f65b3de590a9 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -365,6 +365,9 @@ struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask) C(nfct); nf_conntrack_get(skb->nfct); C(nfctinfo); +#ifdef CONFIG_NETFILTER_DEBUG + C(nf_debug); +#endif #ifdef CONFIG_BRIDGE_NETFILTER C(nf_bridge); nf_bridge_get(skb->nf_bridge); @@ -429,6 +432,9 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) new->nfct = old->nfct; nf_conntrack_get(old->nfct); new->nfctinfo = old->nfctinfo; +#ifdef CONFIG_NETFILTER_DEBUG + new->nf_debug = old->nf_debug; +#endif #ifdef CONFIG_BRIDGE_NETFILTER new->nf_bridge = old->nf_bridge; nf_bridge_get(old->nf_bridge); diff --git a/trunk/net/ipv4/Kconfig b/trunk/net/ipv4/Kconfig index 05107e0dc145..6d3e8b1bd1f2 100644 --- a/trunk/net/ipv4/Kconfig +++ b/trunk/net/ipv4/Kconfig @@ -1,32 +1,6 @@ # # IP configuration # -choice - prompt "Choose IP: FIB lookup"" - depends on INET - default IP_FIB_HASH - -config IP_FIB_HASH - bool "FIB_HASH" - ---help--- - Current FIB is very proven and good enough for most users. - -config IP_FIB_TRIE - bool "FIB_TRIE" - ---help--- - Use new experimental LC-trie as FIB lookup algoritm. - This improves lookup performance - - LC-trie is described in: - - IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson - IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, June 1999 - An experimental study of compression methods for dynamic tries - Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002. - http://www.nada.kth.se/~snilsson/public/papers/dyntrie2/ - -endchoice - config IP_MULTICAST bool "IP: multicasting" depends on INET diff --git a/trunk/net/ipv4/Makefile b/trunk/net/ipv4/Makefile index 65d57d8e1add..8b379627ebb6 100644 --- a/trunk/net/ipv4/Makefile +++ b/trunk/net/ipv4/Makefile @@ -7,10 +7,8 @@ obj-y := utils.o route.o inetpeer.o protocol.o \ ip_output.o ip_sockglue.o \ tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o tcp_minisocks.o \ datagram.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \ - sysctl_net_ipv4.o fib_frontend.o fib_semantics.o + sysctl_net_ipv4.o fib_frontend.o fib_semantics.o fib_hash.o -obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o -obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o obj-$(CONFIG_IP_MROUTE) += ipmr.o diff --git a/trunk/net/ipv4/af_inet.c b/trunk/net/ipv4/af_inet.c index 658e7977924d..03942f133944 100644 --- a/trunk/net/ipv4/af_inet.c +++ b/trunk/net/ipv4/af_inet.c @@ -1119,10 +1119,6 @@ module_init(inet_init); #ifdef CONFIG_PROC_FS extern int fib_proc_init(void); extern void fib_proc_exit(void); -#ifdef CONFIG_IP_FIB_TRIE -extern int fib_stat_proc_init(void); -extern void fib_stat_proc_exit(void); -#endif extern int ip_misc_proc_init(void); extern int raw_proc_init(void); extern void raw_proc_exit(void); @@ -1143,19 +1139,11 @@ static int __init ipv4_proc_init(void) goto out_udp; if (fib_proc_init()) goto out_fib; -#ifdef CONFIG_IP_FIB_TRIE - if (fib_stat_proc_init()) - goto out_fib_stat; - #endif if (ip_misc_proc_init()) goto out_misc; out: return rc; out_misc: -#ifdef CONFIG_IP_FIB_TRIE - fib_stat_proc_exit(); -out_fib_stat: -#endif fib_proc_exit(); out_fib: udp4_proc_exit(); diff --git a/trunk/net/ipv4/fib_trie.c b/trunk/net/ipv4/fib_trie.c deleted file mode 100644 index 0671569ee6f0..000000000000 --- a/trunk/net/ipv4/fib_trie.c +++ /dev/null @@ -1,2454 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Robert Olsson Uppsala Universitet - * & Swedish University of Agricultural Sciences. - * - * Jens Laas Swedish University of - * Agricultural Sciences. - * - * Hans Liss Uppsala Universitet - * - * This work is based on the LPC-trie which is originally descibed in: - * - * An experimental study of compression methods for dynamic tries - * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002. - * http://www.nada.kth.se/~snilsson/public/papers/dyntrie2/ - * - * - * IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson - * IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, June 1999 - * - * Version: $Id: fib_trie.c,v 1.3 2005/06/08 14:20:01 robert Exp $ - * - * - * Code from fib_hash has been reused which includes the following header: - * - * - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * IPv4 FIB: lookup engine and maintenance routines. - * - * - * Authors: Alexey Kuznetsov, - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#define VERSION "0.323" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "fib_lookup.h" - -#undef CONFIG_IP_FIB_TRIE_STATS -#define MAX_CHILDS 16384 - -#define EXTRACT(p, n, str) ((str)<<(p)>>(32-(n))) -#define KEYLENGTH (8*sizeof(t_key)) -#define MASK_PFX(k, l) (((l)==0)?0:(k >> (KEYLENGTH-l)) << (KEYLENGTH-l)) -#define TKEY_GET_MASK(offset, bits) (((bits)==0)?0:((t_key)(-1) << (KEYLENGTH - bits) >> offset)) - -static DEFINE_RWLOCK(fib_lock); - -typedef unsigned int t_key; - -#define T_TNODE 0 -#define T_LEAF 1 -#define NODE_TYPE_MASK 0x1UL -#define NODE_PARENT(_node) \ -((struct tnode *)((_node)->_parent & ~NODE_TYPE_MASK)) -#define NODE_SET_PARENT(_node, _ptr) \ -((_node)->_parent = (((unsigned long)(_ptr)) | \ - ((_node)->_parent & NODE_TYPE_MASK))) -#define NODE_INIT_PARENT(_node, _type) \ -((_node)->_parent = (_type)) -#define NODE_TYPE(_node) \ -((_node)->_parent & NODE_TYPE_MASK) - -#define IS_TNODE(n) (!(n->_parent & T_LEAF)) -#define IS_LEAF(n) (n->_parent & T_LEAF) - -struct node { - t_key key; - unsigned long _parent; -}; - -struct leaf { - t_key key; - unsigned long _parent; - struct hlist_head list; -}; - -struct leaf_info { - struct hlist_node hlist; - int plen; - struct list_head falh; -}; - -struct tnode { - t_key key; - unsigned long _parent; - unsigned short pos:5; /* 2log(KEYLENGTH) bits needed */ - unsigned short bits:5; /* 2log(KEYLENGTH) bits needed */ - unsigned short full_children; /* KEYLENGTH bits needed */ - unsigned short empty_children; /* KEYLENGTH bits needed */ - struct node *child[0]; -}; - -#ifdef CONFIG_IP_FIB_TRIE_STATS -struct trie_use_stats { - unsigned int gets; - unsigned int backtrack; - unsigned int semantic_match_passed; - unsigned int semantic_match_miss; - unsigned int null_node_hit; -}; -#endif - -struct trie_stat { - unsigned int totdepth; - unsigned int maxdepth; - unsigned int tnodes; - unsigned int leaves; - unsigned int nullpointers; - unsigned int nodesizes[MAX_CHILDS]; -}; - -struct trie { - struct node *trie; -#ifdef CONFIG_IP_FIB_TRIE_STATS - struct trie_use_stats stats; -#endif - int size; - unsigned int revision; -}; - -static int trie_debug = 0; - -static int tnode_full(struct tnode *tn, struct node *n); -static void put_child(struct trie *t, struct tnode *tn, int i, struct node *n); -static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull); -static int tnode_child_length(struct tnode *tn); -static struct node *resize(struct trie *t, struct tnode *tn); -static struct tnode *inflate(struct trie *t, struct tnode *tn); -static struct tnode *halve(struct trie *t, struct tnode *tn); -static void tnode_free(struct tnode *tn); -static void trie_dump_seq(struct seq_file *seq, struct trie *t); -extern struct fib_alias *fib_find_alias(struct list_head *fah, u8 tos, u32 prio); -extern int fib_detect_death(struct fib_info *fi, int order, - struct fib_info **last_resort, int *last_idx, int *dflt); - -extern void rtmsg_fib(int event, u32 key, struct fib_alias *fa, int z, int tb_id, - struct nlmsghdr *n, struct netlink_skb_parms *req); - -static kmem_cache_t *fn_alias_kmem; -static struct trie *trie_local = NULL, *trie_main = NULL; - -static void trie_bug(char *err) -{ - printk("Trie Bug: %s\n", err); - BUG(); -} - -static inline struct node *tnode_get_child(struct tnode *tn, int i) -{ - if (i >= 1<bits) - trie_bug("tnode_get_child"); - - return tn->child[i]; -} - -static inline int tnode_child_length(struct tnode *tn) -{ - return 1<bits; -} - -/* - _________________________________________________________________ - | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C | - ---------------------------------------------------------------- - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - - _________________________________________________________________ - | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u | - ----------------------------------------------------------------- - 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 - - tp->pos = 7 - tp->bits = 3 - n->pos = 15 - n->bits=4 - KEYLENGTH=32 -*/ - -static inline t_key tkey_extract_bits(t_key a, int offset, int bits) -{ - if (offset < KEYLENGTH) - return ((t_key)(a << offset)) >> (KEYLENGTH - bits); - else - return 0; -} - -static inline int tkey_equals(t_key a, t_key b) -{ - return a == b; -} - -static inline int tkey_sub_equals(t_key a, int offset, int bits, t_key b) -{ - if (bits == 0 || offset >= KEYLENGTH) - return 1; - bits = bits > KEYLENGTH ? KEYLENGTH : bits; - return ((a ^ b) << offset) >> (KEYLENGTH - bits) == 0; -} - -static inline int tkey_mismatch(t_key a, int offset, t_key b) -{ - t_key diff = a ^ b; - int i = offset; - - if(!diff) - return 0; - while((diff << i) >> (KEYLENGTH-1) == 0) - i++; - return i; -} - -/* Candiate for fib_semantics */ - -static void fn_free_alias(struct fib_alias *fa) -{ - fib_release_info(fa->fa_info); - kmem_cache_free(fn_alias_kmem, fa); -} - -/* - To understand this stuff, an understanding of keys and all their bits is - necessary. Every node in the trie has a key associated with it, but not - all of the bits in that key are significant. - - Consider a node 'n' and its parent 'tp'. - - If n is a leaf, every bit in its key is significant. Its presence is - necessitaded by path compression, since during a tree traversal (when - searching for a leaf - unless we are doing an insertion) we will completely - ignore all skipped bits we encounter. Thus we need to verify, at the end of - a potentially successful search, that we have indeed been walking the - correct key path. - - Note that we can never "miss" the correct key in the tree if present by - following the wrong path. Path compression ensures that segments of the key - that are the same for all keys with a given prefix are skipped, but the - skipped part *is* identical for each node in the subtrie below the skipped - bit! trie_insert() in this implementation takes care of that - note the - call to tkey_sub_equals() in trie_insert(). - - if n is an internal node - a 'tnode' here, the various parts of its key - have many different meanings. - - Example: - _________________________________________________________________ - | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C | - ----------------------------------------------------------------- - 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - - _________________________________________________________________ - | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u | - ----------------------------------------------------------------- - 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 - - tp->pos = 7 - tp->bits = 3 - n->pos = 15 - n->bits=4 - - First, let's just ignore the bits that come before the parent tp, that is - the bits from 0 to (tp->pos-1). They are *known* but at this point we do - not use them for anything. - - The bits from (tp->pos) to (tp->pos + tp->bits - 1) - "N", above - are the - index into the parent's child array. That is, they will be used to find - 'n' among tp's children. - - The bits from (tp->pos + tp->bits) to (n->pos - 1) - "S" - are skipped bits - for the node n. - - All the bits we have seen so far are significant to the node n. The rest - of the bits are really not needed or indeed known in n->key. - - The bits from (n->pos) to (n->pos + n->bits - 1) - "C" - are the index into - n's child array, and will of course be different for each child. - - The rest of the bits, from (n->pos + n->bits) onward, are completely unknown - at this point. - -*/ - -static void check_tnode(struct tnode *tn) -{ - if(tn && tn->pos+tn->bits > 32) { - printk("TNODE ERROR tn=%p, pos=%d, bits=%d\n", tn, tn->pos, tn->bits); - } -} - -static int halve_threshold = 25; -static int inflate_threshold = 50; - -static struct leaf *leaf_new(void) -{ - struct leaf *l = kmalloc(sizeof(struct leaf), GFP_KERNEL); - if(l) { - NODE_INIT_PARENT(l, T_LEAF); - INIT_HLIST_HEAD(&l->list); - } - return l; -} - -static struct leaf_info *leaf_info_new(int plen) -{ - struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL); - li->plen = plen; - INIT_LIST_HEAD(&li->falh); - return li; -} - -static inline void free_leaf(struct leaf *l) -{ - kfree(l); -} - -static inline void free_leaf_info(struct leaf_info *li) -{ - kfree(li); -} - -static struct tnode* tnode_new(t_key key, int pos, int bits) -{ - int nchildren = 1<pos = pos; - tn->bits = bits; - tn->key = key; - tn->full_children = 0; - tn->empty_children = 1< 0) - printk("AT %p s=%u %u\n", tn, (unsigned int) sizeof(struct tnode), - (unsigned int) (sizeof(struct node) * 1< 0 ) - printk("FL %p \n", tn); - } - else if(IS_TNODE(tn)) { - kfree(tn); - if(trie_debug > 0 ) - printk("FT %p \n", tn); - } - else { - trie_bug("tnode_free\n"); - } -} - -/* - * Check whether a tnode 'n' is "full", i.e. it is an internal node - * and no bits are skipped. See discussion in dyntree paper p. 6 - */ - -static inline int tnode_full(struct tnode *tn, struct node *n) -{ - if(n == NULL || IS_LEAF(n)) - return 0; - - return ((struct tnode *) n)->pos == tn->pos + tn->bits; -} - -static inline void put_child(struct trie *t, struct tnode *tn, int i, struct node *n) -{ - tnode_put_child_reorg(tn, i, n, -1); -} - - /* - * Add a child at position i overwriting the old value. - * Update the value of full_children and empty_children. - */ - -static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull) -{ - struct node *chi; - int isfull; - - if(i >= 1<bits) { - printk("bits=%d, i=%d\n", tn->bits, i); - trie_bug("tnode_put_child_reorg bits"); - } - write_lock_bh(&fib_lock); - chi = tn->child[i]; - - /* update emptyChildren */ - if (n == NULL && chi != NULL) - tn->empty_children++; - else if (n != NULL && chi == NULL) - tn->empty_children--; - - /* update fullChildren */ - if (wasfull == -1) - wasfull = tnode_full(tn, chi); - - isfull = tnode_full(tn, n); - if (wasfull && !isfull) - tn->full_children--; - - else if (!wasfull && isfull) - tn->full_children++; - if(n) - NODE_SET_PARENT(n, tn); - - tn->child[i] = n; - write_unlock_bh(&fib_lock); -} - -static struct node *resize(struct trie *t, struct tnode *tn) -{ - int i; - - if (!tn) - return NULL; - - if(trie_debug) - printk("In tnode_resize %p inflate_threshold=%d threshold=%d\n", - tn, inflate_threshold, halve_threshold); - - /* No children */ - if (tn->empty_children == tnode_child_length(tn)) { - tnode_free(tn); - return NULL; - } - /* One child */ - if (tn->empty_children == tnode_child_length(tn) - 1) - for (i = 0; i < tnode_child_length(tn); i++) { - - write_lock_bh(&fib_lock); - if (tn->child[i] != NULL) { - - /* compress one level */ - struct node *n = tn->child[i]; - if(n) - NODE_INIT_PARENT(n, NODE_TYPE(n)); - - write_unlock_bh(&fib_lock); - tnode_free(tn); - return n; - } - write_unlock_bh(&fib_lock); - } - /* - * Double as long as the resulting node has a number of - * nonempty nodes that are above the threshold. - */ - - /* - * From "Implementing a dynamic compressed trie" by Stefan Nilsson of - * the Helsinki University of Technology and Matti Tikkanen of Nokia - * Telecommunications, page 6: - * "A node is doubled if the ratio of non-empty children to all - * children in the *doubled* node is at least 'high'." - * - * 'high' in this instance is the variable 'inflate_threshold'. It - * is expressed as a percentage, so we multiply it with - * tnode_child_length() and instead of multiplying by 2 (since the - * child array will be doubled by inflate()) and multiplying - * the left-hand side by 100 (to handle the percentage thing) we - * multiply the left-hand side by 50. - * - * The left-hand side may look a bit weird: tnode_child_length(tn) - * - tn->empty_children is of course the number of non-null children - * in the current node. tn->full_children is the number of "full" - * children, that is non-null tnodes with a skip value of 0. - * All of those will be doubled in the resulting inflated tnode, so - * we just count them one extra time here. - * - * A clearer way to write this would be: - * - * to_be_doubled = tn->full_children; - * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children - - * tn->full_children; - * - * new_child_length = tnode_child_length(tn) * 2; - * - * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) / - * new_child_length; - * if (new_fill_factor >= inflate_threshold) - * - * ...and so on, tho it would mess up the while() loop. - * - * anyway, - * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >= - * inflate_threshold - * - * avoid a division: - * 100 * (not_to_be_doubled + 2*to_be_doubled) >= - * inflate_threshold * new_child_length - * - * expand not_to_be_doubled and to_be_doubled, and shorten: - * 100 * (tnode_child_length(tn) - tn->empty_children + - * tn->full_children ) >= inflate_threshold * new_child_length - * - * expand new_child_length: - * 100 * (tnode_child_length(tn) - tn->empty_children + - * tn->full_children ) >= - * inflate_threshold * tnode_child_length(tn) * 2 - * - * shorten again: - * 50 * (tn->full_children + tnode_child_length(tn) - - * tn->empty_children ) >= inflate_threshold * - * tnode_child_length(tn) - * - */ - - check_tnode(tn); - - while ((tn->full_children > 0 && - 50 * (tn->full_children + tnode_child_length(tn) - tn->empty_children) >= - inflate_threshold * tnode_child_length(tn))) { - - tn = inflate(t, tn); - } - - check_tnode(tn); - - /* - * Halve as long as the number of empty children in this - * node is above threshold. - */ - while (tn->bits > 1 && - 100 * (tnode_child_length(tn) - tn->empty_children) < - halve_threshold * tnode_child_length(tn)) - - tn = halve(t, tn); - - /* Only one child remains */ - - if (tn->empty_children == tnode_child_length(tn) - 1) - for (i = 0; i < tnode_child_length(tn); i++) { - - write_lock_bh(&fib_lock); - if (tn->child[i] != NULL) { - /* compress one level */ - struct node *n = tn->child[i]; - - if(n) - NODE_INIT_PARENT(n, NODE_TYPE(n)); - - write_unlock_bh(&fib_lock); - tnode_free(tn); - return n; - } - write_unlock_bh(&fib_lock); - } - - return (struct node *) tn; -} - -static struct tnode *inflate(struct trie *t, struct tnode *tn) -{ - struct tnode *inode; - struct tnode *oldtnode = tn; - int olen = tnode_child_length(tn); - int i; - - if(trie_debug) - printk("In inflate\n"); - - tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits + 1); - - if (!tn) - trie_bug("tnode_new failed"); - - for(i = 0; i < olen; i++) { - struct node *node = tnode_get_child(oldtnode, i); - - /* An empty child */ - if (node == NULL) - continue; - - /* A leaf or an internal node with skipped bits */ - - if(IS_LEAF(node) || ((struct tnode *) node)->pos > - tn->pos + tn->bits - 1) { - if(tkey_extract_bits(node->key, tn->pos + tn->bits - 1, - 1) == 0) - put_child(t, tn, 2*i, node); - else - put_child(t, tn, 2*i+1, node); - continue; - } - - /* An internal node with two children */ - inode = (struct tnode *) node; - - if (inode->bits == 1) { - put_child(t, tn, 2*i, inode->child[0]); - put_child(t, tn, 2*i+1, inode->child[1]); - - tnode_free(inode); - } - - /* An internal node with more than two children */ - else { - struct tnode *left, *right; - int size, j; - - /* We will replace this node 'inode' with two new - * ones, 'left' and 'right', each with half of the - * original children. The two new nodes will have - * a position one bit further down the key and this - * means that the "significant" part of their keys - * (see the discussion near the top of this file) - * will differ by one bit, which will be "0" in - * left's key and "1" in right's key. Since we are - * moving the key position by one step, the bit that - * we are moving away from - the bit at position - * (inode->pos) - is the one that will differ between - * left and right. So... we synthesize that bit in the - * two new keys. - * The mask 'm' below will be a single "one" bit at - * the position (inode->pos) - */ - - t_key m = TKEY_GET_MASK(inode->pos, 1); - - /* Use the old key, but set the new significant - * bit to zero. - */ - left = tnode_new(inode->key&(~m), inode->pos + 1, - inode->bits - 1); - - if(!left) - trie_bug("tnode_new failed"); - - - /* Use the old key, but set the new significant - * bit to one. - */ - right = tnode_new(inode->key|m, inode->pos + 1, - inode->bits - 1); - - if(!right) - trie_bug("tnode_new failed"); - - size = tnode_child_length(left); - for(j = 0; j < size; j++) { - put_child(t, left, j, inode->child[j]); - put_child(t, right, j, inode->child[j + size]); - } - put_child(t, tn, 2*i, resize(t, left)); - put_child(t, tn, 2*i+1, resize(t, right)); - - tnode_free(inode); - } - } - tnode_free(oldtnode); - return tn; -} - -static struct tnode *halve(struct trie *t, struct tnode *tn) -{ - struct tnode *oldtnode = tn; - struct node *left, *right; - int i; - int olen = tnode_child_length(tn); - - if(trie_debug) printk("In halve\n"); - - tn=tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits - 1); - - if(!tn) - trie_bug("tnode_new failed"); - - for(i = 0; i < olen; i += 2) { - left = tnode_get_child(oldtnode, i); - right = tnode_get_child(oldtnode, i+1); - - /* At least one of the children is empty */ - if (left == NULL) { - if (right == NULL) /* Both are empty */ - continue; - put_child(t, tn, i/2, right); - } else if (right == NULL) - put_child(t, tn, i/2, left); - - /* Two nonempty children */ - else { - struct tnode *newBinNode = - tnode_new(left->key, tn->pos + tn->bits, 1); - - if(!newBinNode) - trie_bug("tnode_new failed"); - - put_child(t, newBinNode, 0, left); - put_child(t, newBinNode, 1, right); - put_child(t, tn, i/2, resize(t, newBinNode)); - } - } - tnode_free(oldtnode); - return tn; -} - -static void *trie_init(struct trie *t) -{ - if(t) { - t->size = 0; - t->trie = NULL; - t->revision = 0; -#ifdef CONFIG_IP_FIB_TRIE_STATS - memset(&t->stats, 0, sizeof(struct trie_use_stats)); -#endif - } - return t; -} - -static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen) -{ - struct hlist_node *node; - struct leaf_info *li; - - hlist_for_each_entry(li, node, head, hlist) { - - if ( li->plen == plen ) - return li; - } - return NULL; -} - -static inline struct list_head * get_fa_head(struct leaf *l, int plen) -{ - struct list_head *fa_head=NULL; - struct leaf_info *li = find_leaf_info(&l->list, plen); - - if(li) - fa_head = &li->falh; - - return fa_head; -} - -static void insert_leaf_info(struct hlist_head *head, struct leaf_info *new) -{ - struct leaf_info *li=NULL, *last=NULL; - struct hlist_node *node, *tmp; - - write_lock_bh(&fib_lock); - - if(hlist_empty(head)) - hlist_add_head(&new->hlist, head); - else { - hlist_for_each_entry_safe(li, node, tmp, head, hlist) { - - if (new->plen > li->plen) - break; - - last = li; - } - if(last) - hlist_add_after(&last->hlist, &new->hlist); - else - hlist_add_before(&new->hlist, &li->hlist); - } - write_unlock_bh(&fib_lock); -} - -static struct leaf * -fib_find_node(struct trie *t, u32 key) -{ - int pos; - struct tnode *tn; - struct node *n; - - pos = 0; - n=t->trie; - - while (n != NULL && NODE_TYPE(n) == T_TNODE) { - tn = (struct tnode *) n; - - check_tnode(tn); - - if(tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) { - pos=tn->pos + tn->bits; - n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits)); - } - else - break; - } - /* Case we have found a leaf. Compare prefixes */ - - if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) { - struct leaf *l = (struct leaf *) n; - return l; - } - return NULL; -} - -static struct node *trie_rebalance(struct trie *t, struct tnode *tn) -{ - int i = 0; - int wasfull; - t_key cindex, key; - struct tnode *tp = NULL; - - if(!tn) - BUG(); - - key = tn->key; - i = 0; - - while (tn != NULL && NODE_PARENT(tn) != NULL) { - - if( i > 10 ) { - printk("Rebalance tn=%p \n", tn); - if(tn) printk("tn->parent=%p \n", NODE_PARENT(tn)); - - printk("Rebalance tp=%p \n", tp); - if(tp) printk("tp->parent=%p \n", NODE_PARENT(tp)); - } - - if( i > 12 ) BUG(); - i++; - - tp = NODE_PARENT(tn); - cindex = tkey_extract_bits(key, tp->pos, tp->bits); - wasfull = tnode_full(tp, tnode_get_child(tp, cindex)); - tn = (struct tnode *) resize (t, (struct tnode *)tn); - tnode_put_child_reorg((struct tnode *)tp, cindex,(struct node*)tn, wasfull); - - if(!NODE_PARENT(tn)) - break; - - tn = NODE_PARENT(tn); - } - /* Handle last (top) tnode */ - if (IS_TNODE(tn)) - tn = (struct tnode*) resize(t, (struct tnode *)tn); - - return (struct node*) tn; -} - -static struct list_head * -fib_insert_node(struct trie *t, u32 key, int plen) -{ - int pos, newpos; - struct tnode *tp = NULL, *tn = NULL; - struct node *n; - struct leaf *l; - int missbit; - struct list_head *fa_head=NULL; - struct leaf_info *li; - t_key cindex; - - pos = 0; - n=t->trie; - - /* If we point to NULL, stop. Either the tree is empty and we should - * just put a new leaf in if, or we have reached an empty child slot, - * and we should just put our new leaf in that. - * If we point to a T_TNODE, check if it matches our key. Note that - * a T_TNODE might be skipping any number of bits - its 'pos' need - * not be the parent's 'pos'+'bits'! - * - * If it does match the current key, get pos/bits from it, extract - * the index from our key, push the T_TNODE and walk the tree. - * - * If it doesn't, we have to replace it with a new T_TNODE. - * - * If we point to a T_LEAF, it might or might not have the same key - * as we do. If it does, just change the value, update the T_LEAF's - * value, and return it. - * If it doesn't, we need to replace it with a T_TNODE. - */ - - while (n != NULL && NODE_TYPE(n) == T_TNODE) { - tn = (struct tnode *) n; - - check_tnode(tn); - - if(tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) { - tp = tn; - pos=tn->pos + tn->bits; - n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits)); - - if(n && NODE_PARENT(n) != tn) { - printk("BUG tn=%p, n->parent=%p\n", tn, NODE_PARENT(n)); - BUG(); - } - } - else - break; - } - - /* - * n ----> NULL, LEAF or TNODE - * - * tp is n's (parent) ----> NULL or TNODE - */ - - if(tp && IS_LEAF(tp)) - BUG(); - - t->revision++; - - /* Case 1: n is a leaf. Compare prefixes */ - - if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) { - struct leaf *l = ( struct leaf *) n; - - li = leaf_info_new(plen); - - if(! li) - BUG(); - - fa_head = &li->falh; - insert_leaf_info(&l->list, li); - goto done; - } - t->size++; - l = leaf_new(); - - if(! l) - BUG(); - - l->key = key; - li = leaf_info_new(plen); - - if(! li) - BUG(); - - fa_head = &li->falh; - insert_leaf_info(&l->list, li); - - /* Case 2: n is NULL, and will just insert a new leaf */ - if (t->trie && n == NULL) { - - NODE_SET_PARENT(l, tp); - - if (!tp) - BUG(); - - else { - cindex = tkey_extract_bits(key, tp->pos, tp->bits); - put_child(t, (struct tnode *)tp, cindex, (struct node *)l); - } - } - /* Case 3: n is a LEAF or a TNODE and the key doesn't match. */ - else { - /* - * Add a new tnode here - * first tnode need some special handling - */ - - if (tp) - pos=tp->pos+tp->bits; - else - pos=0; - if(n) { - newpos = tkey_mismatch(key, pos, n->key); - tn = tnode_new(n->key, newpos, 1); - } - else { - newpos = 0; - tn = tnode_new(key, newpos, 1); /* First tnode */ - } - if(!tn) - trie_bug("tnode_pfx_new failed"); - - NODE_SET_PARENT(tn, tp); - - missbit=tkey_extract_bits(key, newpos, 1); - put_child(t, tn, missbit, (struct node *)l); - put_child(t, tn, 1-missbit, n); - - if(tp) { - cindex = tkey_extract_bits(key, tp->pos, tp->bits); - put_child(t, (struct tnode *)tp, cindex, (struct node *)tn); - } - else { - t->trie = (struct node*) tn; /* First tnode */ - tp = tn; - } - } - if(tp && tp->pos+tp->bits > 32) { - printk("ERROR tp=%p pos=%d, bits=%d, key=%0x plen=%d\n", - tp, tp->pos, tp->bits, key, plen); - } - /* Rebalance the trie */ - t->trie = trie_rebalance(t, tp); -done:; - return fa_head; -} - -static int -fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta, - struct nlmsghdr *nlhdr, struct netlink_skb_parms *req) -{ - struct trie *t = (struct trie *) tb->tb_data; - struct fib_alias *fa, *new_fa; - struct list_head *fa_head=NULL; - struct fib_info *fi; - int plen = r->rtm_dst_len; - int type = r->rtm_type; - u8 tos = r->rtm_tos; - u32 key, mask; - int err; - struct leaf *l; - - if (plen > 32) - return -EINVAL; - - key = 0; - if (rta->rta_dst) - memcpy(&key, rta->rta_dst, 4); - - key = ntohl(key); - - if(trie_debug) - printk("Insert table=%d %08x/%d\n", tb->tb_id, key, plen); - - mask = ntohl( inet_make_mask(plen) ); - - if(key & ~mask) - return -EINVAL; - - key = key & mask; - - if ((fi = fib_create_info(r, rta, nlhdr, &err)) == NULL) - goto err; - - l = fib_find_node(t, key); - fa = NULL; - - if(l) { - fa_head = get_fa_head(l, plen); - fa = fib_find_alias(fa_head, tos, fi->fib_priority); - } - - /* Now fa, if non-NULL, points to the first fib alias - * with the same keys [prefix,tos,priority], if such key already - * exists or to the node before which we will insert new one. - * - * If fa is NULL, we will need to allocate a new one and - * insert to the head of f. - * - * If f is NULL, no fib node matched the destination key - * and we need to allocate a new one of those as well. - */ - - if (fa && - fa->fa_info->fib_priority == fi->fib_priority) { - struct fib_alias *fa_orig; - - err = -EEXIST; - if (nlhdr->nlmsg_flags & NLM_F_EXCL) - goto out; - - if (nlhdr->nlmsg_flags & NLM_F_REPLACE) { - struct fib_info *fi_drop; - u8 state; - - write_lock_bh(&fib_lock); - - fi_drop = fa->fa_info; - fa->fa_info = fi; - fa->fa_type = type; - fa->fa_scope = r->rtm_scope; - state = fa->fa_state; - fa->fa_state &= ~FA_S_ACCESSED; - - write_unlock_bh(&fib_lock); - - fib_release_info(fi_drop); - if (state & FA_S_ACCESSED) - rt_cache_flush(-1); - - goto succeeded; - } - /* Error if we find a perfect match which - * uses the same scope, type, and nexthop - * information. - */ - fa_orig = fa; - list_for_each_entry(fa, fa_orig->fa_list.prev, fa_list) { - if (fa->fa_tos != tos) - break; - if (fa->fa_info->fib_priority != fi->fib_priority) - break; - if (fa->fa_type == type && - fa->fa_scope == r->rtm_scope && - fa->fa_info == fi) { - goto out; - } - } - if (!(nlhdr->nlmsg_flags & NLM_F_APPEND)) - fa = fa_orig; - } - err = -ENOENT; - if (!(nlhdr->nlmsg_flags&NLM_F_CREATE)) - goto out; - - err = -ENOBUFS; - new_fa = kmem_cache_alloc(fn_alias_kmem, SLAB_KERNEL); - if (new_fa == NULL) - goto out; - - new_fa->fa_info = fi; - new_fa->fa_tos = tos; - new_fa->fa_type = type; - new_fa->fa_scope = r->rtm_scope; - new_fa->fa_state = 0; -#if 0 - new_fa->dst = NULL; -#endif - /* - * Insert new entry to the list. - */ - - if(!fa_head) - fa_head = fib_insert_node(t, key, plen); - - write_lock_bh(&fib_lock); - - list_add_tail(&new_fa->fa_list, - (fa ? &fa->fa_list : fa_head)); - - write_unlock_bh(&fib_lock); - - rt_cache_flush(-1); - rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req); -succeeded: - return 0; -out: - fib_release_info(fi); -err:; - return err; -} - -static inline int check_leaf(struct trie *t, struct leaf *l, t_key key, int *plen, const struct flowi *flp, - struct fib_result *res, int *err) -{ - int i; - t_key mask; - struct leaf_info *li; - struct hlist_head *hhead = &l->list; - struct hlist_node *node; - - hlist_for_each_entry(li, node, hhead, hlist) { - - i = li->plen; - mask = ntohl(inet_make_mask(i)); - if (l->key != (key & mask)) - continue; - - if (((*err) = fib_semantic_match(&li->falh, flp, res, l->key, mask, i)) == 0) { - *plen = i; -#ifdef CONFIG_IP_FIB_TRIE_STATS - t->stats.semantic_match_passed++; -#endif - return 1; - } -#ifdef CONFIG_IP_FIB_TRIE_STATS - t->stats.semantic_match_miss++; -#endif - } - return 0; -} - -static int -fn_trie_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result *res) -{ - struct trie *t = (struct trie *) tb->tb_data; - int plen, ret = 0; - struct node *n; - struct tnode *pn; - int pos, bits; - t_key key=ntohl(flp->fl4_dst); - int chopped_off; - t_key cindex = 0; - int current_prefix_length = KEYLENGTH; - n = t->trie; - - read_lock(&fib_lock); - if(!n) - goto failed; - -#ifdef CONFIG_IP_FIB_TRIE_STATS - t->stats.gets++; -#endif - - /* Just a leaf? */ - if (IS_LEAF(n)) { - if( check_leaf(t, (struct leaf *)n, key, &plen, flp, res, &ret) ) - goto found; - goto failed; - } - pn = (struct tnode *) n; - chopped_off = 0; - - while (pn) { - - pos = pn->pos; - bits = pn->bits; - - if(!chopped_off) - cindex = tkey_extract_bits(MASK_PFX(key, current_prefix_length), pos, bits); - - n = tnode_get_child(pn, cindex); - - if (n == NULL) { -#ifdef CONFIG_IP_FIB_TRIE_STATS - t->stats.null_node_hit++; -#endif - goto backtrace; - } - - if (IS_TNODE(n)) { -#define HL_OPTIMIZE -#ifdef HL_OPTIMIZE - struct tnode *cn = (struct tnode *)n; - t_key node_prefix, key_prefix, pref_mismatch; - int mp; - - /* - * It's a tnode, and we can do some extra checks here if we - * like, to avoid descending into a dead-end branch. - * This tnode is in the parent's child array at index - * key[p_pos..p_pos+p_bits] but potentially with some bits - * chopped off, so in reality the index may be just a - * subprefix, padded with zero at the end. - * We can also take a look at any skipped bits in this - * tnode - everything up to p_pos is supposed to be ok, - * and the non-chopped bits of the index (se previous - * paragraph) are also guaranteed ok, but the rest is - * considered unknown. - * - * The skipped bits are key[pos+bits..cn->pos]. - */ - - /* If current_prefix_length < pos+bits, we are already doing - * actual prefix matching, which means everything from - * pos+(bits-chopped_off) onward must be zero along some - * branch of this subtree - otherwise there is *no* valid - * prefix present. Here we can only check the skipped - * bits. Remember, since we have already indexed into the - * parent's child array, we know that the bits we chopped of - * *are* zero. - */ - - /* NOTA BENE: CHECKING ONLY SKIPPED BITS FOR THE NEW NODE HERE */ - - if (current_prefix_length < pos+bits) { - if (tkey_extract_bits(cn->key, current_prefix_length, - cn->pos - current_prefix_length) != 0 || - !(cn->child[0])) - goto backtrace; - } - - /* - * If chopped_off=0, the index is fully validated and we - * only need to look at the skipped bits for this, the new, - * tnode. What we actually want to do is to find out if - * these skipped bits match our key perfectly, or if we will - * have to count on finding a matching prefix further down, - * because if we do, we would like to have some way of - * verifying the existence of such a prefix at this point. - */ - - /* The only thing we can do at this point is to verify that - * any such matching prefix can indeed be a prefix to our - * key, and if the bits in the node we are inspecting that - * do not match our key are not ZERO, this cannot be true. - * Thus, find out where there is a mismatch (before cn->pos) - * and verify that all the mismatching bits are zero in the - * new tnode's key. - */ - - /* Note: We aren't very concerned about the piece of the key - * that precede pn->pos+pn->bits, since these have already been - * checked. The bits after cn->pos aren't checked since these are - * by definition "unknown" at this point. Thus, what we want to - * see is if we are about to enter the "prefix matching" state, - * and in that case verify that the skipped bits that will prevail - * throughout this subtree are zero, as they have to be if we are - * to find a matching prefix. - */ - - node_prefix = MASK_PFX(cn->key, cn->pos); - key_prefix = MASK_PFX(key, cn->pos); - pref_mismatch = key_prefix^node_prefix; - mp = 0; - - /* In short: If skipped bits in this node do not match the search - * key, enter the "prefix matching" state.directly. - */ - if (pref_mismatch) { - while (!(pref_mismatch & (1<<(KEYLENGTH-1)))) { - mp++; - pref_mismatch = pref_mismatch <<1; - } - key_prefix = tkey_extract_bits(cn->key, mp, cn->pos-mp); - - if (key_prefix != 0) - goto backtrace; - - if (current_prefix_length >= cn->pos) - current_prefix_length=mp; - } -#endif - pn = (struct tnode *)n; /* Descend */ - chopped_off = 0; - continue; - } - if (IS_LEAF(n)) { - if( check_leaf(t, (struct leaf *)n, key, &plen, flp, res, &ret)) - goto found; - } -backtrace: - chopped_off++; - - /* As zero don't change the child key (cindex) */ - while ((chopped_off <= pn->bits) && !(cindex & (1<<(chopped_off-1)))) { - chopped_off++; - } - - /* Decrease current_... with bits chopped off */ - if (current_prefix_length > pn->pos + pn->bits - chopped_off) - current_prefix_length = pn->pos + pn->bits - chopped_off; - - /* - * Either we do the actual chop off according or if we have - * chopped off all bits in this tnode walk up to our parent. - */ - - if(chopped_off <= pn->bits) - cindex &= ~(1 << (chopped_off-1)); - else { - if( NODE_PARENT(pn) == NULL) - goto failed; - - /* Get Child's index */ - cindex = tkey_extract_bits(pn->key, NODE_PARENT(pn)->pos, NODE_PARENT(pn)->bits); - pn = NODE_PARENT(pn); - chopped_off = 0; - -#ifdef CONFIG_IP_FIB_TRIE_STATS - t->stats.backtrack++; -#endif - goto backtrace; - } - } -failed: - ret = 1; -found: - read_unlock(&fib_lock); - return ret; -} - -static int trie_leaf_remove(struct trie *t, t_key key) -{ - t_key cindex; - struct tnode *tp = NULL; - struct node *n = t->trie; - struct leaf *l; - - if(trie_debug) - printk("entering trie_leaf_remove(%p)\n", n); - - /* Note that in the case skipped bits, those bits are *not* checked! - * When we finish this, we will have NULL or a T_LEAF, and the - * T_LEAF may or may not match our key. - */ - - while (n != NULL && IS_TNODE(n)) { - struct tnode *tn = (struct tnode *) n; - check_tnode(tn); - n = tnode_get_child(tn ,tkey_extract_bits(key, tn->pos, tn->bits)); - - if(n && NODE_PARENT(n) != tn) { - printk("BUG tn=%p, n->parent=%p\n", tn, NODE_PARENT(n)); - BUG(); - } - } - l = (struct leaf *) n; - - if(!n || !tkey_equals(l->key, key)) - return 0; - - /* - * Key found. - * Remove the leaf and rebalance the tree - */ - - t->revision++; - t->size--; - - tp = NODE_PARENT(n); - tnode_free((struct tnode *) n); - - if(tp) { - cindex = tkey_extract_bits(key, tp->pos, tp->bits); - put_child(t, (struct tnode *)tp, cindex, NULL); - t->trie = trie_rebalance(t, tp); - } - else - t->trie = NULL; - - return 1; -} - -static int -fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta, - struct nlmsghdr *nlhdr, struct netlink_skb_parms *req) -{ - struct trie *t = (struct trie *) tb->tb_data; - u32 key, mask; - int plen = r->rtm_dst_len; - u8 tos = r->rtm_tos; - struct fib_alias *fa, *fa_to_delete; - struct list_head *fa_head; - struct leaf *l; - - if (plen > 32) - return -EINVAL; - - key = 0; - if (rta->rta_dst) - memcpy(&key, rta->rta_dst, 4); - - key = ntohl(key); - mask = ntohl( inet_make_mask(plen) ); - - if(key & ~mask) - return -EINVAL; - - key = key & mask; - l = fib_find_node(t, key); - - if(!l) - return -ESRCH; - - fa_head = get_fa_head(l, plen); - fa = fib_find_alias(fa_head, tos, 0); - - if (!fa) - return -ESRCH; - - if (trie_debug) - printk("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t); - - fa_to_delete = NULL; - fa_head = fa->fa_list.prev; - list_for_each_entry(fa, fa_head, fa_list) { - struct fib_info *fi = fa->fa_info; - - if (fa->fa_tos != tos) - break; - - if ((!r->rtm_type || - fa->fa_type == r->rtm_type) && - (r->rtm_scope == RT_SCOPE_NOWHERE || - fa->fa_scope == r->rtm_scope) && - (!r->rtm_protocol || - fi->fib_protocol == r->rtm_protocol) && - fib_nh_match(r, nlhdr, rta, fi) == 0) { - fa_to_delete = fa; - break; - } - } - - if (fa_to_delete) { - int kill_li = 0; - struct leaf_info *li; - - fa = fa_to_delete; - rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req); - - l = fib_find_node(t, key); - li = find_leaf_info(&l->list, plen); - - write_lock_bh(&fib_lock); - - list_del(&fa->fa_list); - - if(list_empty(fa_head)) { - hlist_del(&li->hlist); - kill_li = 1; - } - write_unlock_bh(&fib_lock); - - if(kill_li) - free_leaf_info(li); - - if(hlist_empty(&l->list)) - trie_leaf_remove(t, key); - - if (fa->fa_state & FA_S_ACCESSED) - rt_cache_flush(-1); - - fn_free_alias(fa); - return 0; - } - return -ESRCH; -} - -static int trie_flush_list(struct trie *t, struct list_head *head) -{ - struct fib_alias *fa, *fa_node; - int found = 0; - - list_for_each_entry_safe(fa, fa_node, head, fa_list) { - struct fib_info *fi = fa->fa_info; - - if (fi && (fi->fib_flags&RTNH_F_DEAD)) { - - write_lock_bh(&fib_lock); - list_del(&fa->fa_list); - write_unlock_bh(&fib_lock); - - fn_free_alias(fa); - found++; - } - } - return found; -} - -static int trie_flush_leaf(struct trie *t, struct leaf *l) -{ - int found = 0; - struct hlist_head *lih = &l->list; - struct hlist_node *node, *tmp; - struct leaf_info *li = NULL; - - hlist_for_each_entry_safe(li, node, tmp, lih, hlist) { - - found += trie_flush_list(t, &li->falh); - - if (list_empty(&li->falh)) { - - write_lock_bh(&fib_lock); - hlist_del(&li->hlist); - write_unlock_bh(&fib_lock); - - free_leaf_info(li); - } - } - return found; -} - -static struct leaf *nextleaf(struct trie *t, struct leaf *thisleaf) -{ - struct node *c = (struct node *) thisleaf; - struct tnode *p; - int idx; - - if(c == NULL) { - if(t->trie == NULL) - return NULL; - - if (IS_LEAF(t->trie)) /* trie w. just a leaf */ - return (struct leaf *) t->trie; - - p = (struct tnode*) t->trie; /* Start */ - } - else - p = (struct tnode *) NODE_PARENT(c); - while (p) { - int pos, last; - - /* Find the next child of the parent */ - if(c) - pos = 1 + tkey_extract_bits(c->key, p->pos, p->bits); - else - pos = 0; - - last = 1 << p->bits; - for(idx = pos; idx < last ; idx++) { - if( p->child[idx]) { - - /* Decend if tnode */ - - while (IS_TNODE(p->child[idx])) { - p = (struct tnode*) p->child[idx]; - idx = 0; - - /* Rightmost non-NULL branch */ - if( p && IS_TNODE(p) ) - while ( p->child[idx] == NULL && idx < (1 << p->bits) ) idx++; - - /* Done with this tnode? */ - if( idx >= (1 << p->bits) || p->child[idx] == NULL ) - goto up; - } - return (struct leaf*) p->child[idx]; - } - } -up: - /* No more children go up one step */ - c = (struct node*) p; - p = (struct tnode *) NODE_PARENT(p); - } - return NULL; /* Ready. Root of trie */ -} - -static int fn_trie_flush(struct fib_table *tb) -{ - struct trie *t = (struct trie *) tb->tb_data; - struct leaf *ll = NULL, *l = NULL; - int found = 0, h; - - t->revision++; - - for (h=0; (l = nextleaf(t, l)) != NULL; h++) { - found += trie_flush_leaf(t, l); - - if (ll && hlist_empty(&ll->list)) - trie_leaf_remove(t, ll->key); - ll = l; - } - - if (ll && hlist_empty(&ll->list)) - trie_leaf_remove(t, ll->key); - - if(trie_debug) - printk("trie_flush found=%d\n", found); - return found; -} - -static int trie_last_dflt=-1; - -static void -fn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res) -{ - struct trie *t = (struct trie *) tb->tb_data; - int order, last_idx; - struct fib_info *fi = NULL; - struct fib_info *last_resort; - struct fib_alias *fa = NULL; - struct list_head *fa_head; - struct leaf *l; - - last_idx = -1; - last_resort = NULL; - order = -1; - - read_lock(&fib_lock); - - l = fib_find_node(t, 0); - if(!l) - goto out; - - fa_head = get_fa_head(l, 0); - if(!fa_head) - goto out; - - if (list_empty(fa_head)) - goto out; - - list_for_each_entry(fa, fa_head, fa_list) { - struct fib_info *next_fi = fa->fa_info; - - if (fa->fa_scope != res->scope || - fa->fa_type != RTN_UNICAST) - continue; - - if (next_fi->fib_priority > res->fi->fib_priority) - break; - if (!next_fi->fib_nh[0].nh_gw || - next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK) - continue; - fa->fa_state |= FA_S_ACCESSED; - - if (fi == NULL) { - if (next_fi != res->fi) - break; - } else if (!fib_detect_death(fi, order, &last_resort, - &last_idx, &trie_last_dflt)) { - if (res->fi) - fib_info_put(res->fi); - res->fi = fi; - atomic_inc(&fi->fib_clntref); - trie_last_dflt = order; - goto out; - } - fi = next_fi; - order++; - } - if (order <= 0 || fi == NULL) { - trie_last_dflt = -1; - goto out; - } - - if (!fib_detect_death(fi, order, &last_resort, &last_idx, &trie_last_dflt)) { - if (res->fi) - fib_info_put(res->fi); - res->fi = fi; - atomic_inc(&fi->fib_clntref); - trie_last_dflt = order; - goto out; - } - if (last_idx >= 0) { - if (res->fi) - fib_info_put(res->fi); - res->fi = last_resort; - if (last_resort) - atomic_inc(&last_resort->fib_clntref); - } - trie_last_dflt = last_idx; - out:; - read_unlock(&fib_lock); -} - -static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fib_table *tb, - struct sk_buff *skb, struct netlink_callback *cb) -{ - int i, s_i; - struct fib_alias *fa; - - u32 xkey=htonl(key); - - s_i=cb->args[3]; - i = 0; - - list_for_each_entry(fa, fah, fa_list) { - if (i < s_i) { - i++; - continue; - } - if (fa->fa_info->fib_nh == NULL) { - printk("Trie error _fib_nh=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen); - i++; - continue; - } - if (fa->fa_info == NULL) { - printk("Trie error fa_info=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen); - i++; - continue; - } - - if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid, - cb->nlh->nlmsg_seq, - RTM_NEWROUTE, - tb->tb_id, - fa->fa_type, - fa->fa_scope, - &xkey, - plen, - fa->fa_tos, - fa->fa_info, 0) < 0) { - cb->args[3] = i; - return -1; - } - i++; - } - cb->args[3]=i; - return skb->len; -} - -static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, struct sk_buff *skb, - struct netlink_callback *cb) -{ - int h, s_h; - struct list_head *fa_head; - struct leaf *l = NULL; - s_h=cb->args[2]; - - for (h=0; (l = nextleaf(t, l)) != NULL; h++) { - - if (h < s_h) - continue; - if (h > s_h) - memset(&cb->args[3], 0, - sizeof(cb->args) - 3*sizeof(cb->args[0])); - - fa_head = get_fa_head(l, plen); - - if(!fa_head) - continue; - - if(list_empty(fa_head)) - continue; - - if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb)<0) { - cb->args[2]=h; - return -1; - } - } - cb->args[2]=h; - return skb->len; -} - -static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, struct netlink_callback *cb) -{ - int m, s_m; - struct trie *t = (struct trie *) tb->tb_data; - - s_m = cb->args[1]; - - read_lock(&fib_lock); - for (m=0; m<=32; m++) { - - if (m < s_m) - continue; - if (m > s_m) - memset(&cb->args[2], 0, - sizeof(cb->args) - 2*sizeof(cb->args[0])); - - if (fn_trie_dump_plen(t, 32-m, tb, skb, cb)<0) { - cb->args[1] = m; - goto out; - } - } - read_unlock(&fib_lock); - cb->args[1] = m; - return skb->len; - out: - read_unlock(&fib_lock); - return -1; -} - -/* Fix more generic FIB names for init later */ - -#ifdef CONFIG_IP_MULTIPLE_TABLES -struct fib_table * fib_hash_init(int id) -#else -struct fib_table * __init fib_hash_init(int id) -#endif -{ - struct fib_table *tb; - struct trie *t; - - if (fn_alias_kmem == NULL) - fn_alias_kmem = kmem_cache_create("ip_fib_alias", - sizeof(struct fib_alias), - 0, SLAB_HWCACHE_ALIGN, - NULL, NULL); - - tb = kmalloc(sizeof(struct fib_table) + sizeof(struct trie), - GFP_KERNEL); - if (tb == NULL) - return NULL; - - tb->tb_id = id; - tb->tb_lookup = fn_trie_lookup; - tb->tb_insert = fn_trie_insert; - tb->tb_delete = fn_trie_delete; - tb->tb_flush = fn_trie_flush; - tb->tb_select_default = fn_trie_select_default; - tb->tb_dump = fn_trie_dump; - memset(tb->tb_data, 0, sizeof(struct trie)); - - t = (struct trie *) tb->tb_data; - - trie_init(t); - - if (id == RT_TABLE_LOCAL) - trie_local=t; - else if (id == RT_TABLE_MAIN) - trie_main=t; - - if (id == RT_TABLE_LOCAL) - printk("IPv4 FIB: Using LC-trie version %s\n", VERSION); - - return tb; -} - -/* Trie dump functions */ - -static void putspace_seq(struct seq_file *seq, int n) -{ - while (n--) seq_printf(seq, " "); -} - -static void printbin_seq(struct seq_file *seq, unsigned int v, int bits) -{ - while (bits--) - seq_printf(seq, "%s", (v & (1<: "); - seq_printf(seq, "%s:%p ", IS_LEAF(n)?"Leaf":"Internal node", n); - - if (IS_LEAF(n)) - seq_printf(seq, "key=%d.%d.%d.%d\n", - n->key >> 24, (n->key >> 16) % 256, (n->key >> 8) % 256, n->key % 256); - else { - int plen=((struct tnode *)n)->pos; - t_key prf=MASK_PFX(n->key, plen); - seq_printf(seq, "key=%d.%d.%d.%d/%d\n", - prf >> 24, (prf >> 16) % 256, (prf >> 8) % 256, prf % 256, plen); - } - if (IS_LEAF(n)) { - struct leaf *l=(struct leaf *)n; - struct fib_alias *fa; - int i; - for (i=32; i>=0; i--) - if(find_leaf_info(&l->list, i)) { - - struct list_head *fa_head = get_fa_head(l, i); - - if(!fa_head) - continue; - - if(list_empty(fa_head)) - continue; - - putspace_seq(seq, indent+2); - seq_printf(seq, "{/%d...dumping}\n", i); - - - list_for_each_entry(fa, fa_head, fa_list) { - putspace_seq(seq, indent+2); - if (fa->fa_info->fib_nh == NULL) { - seq_printf(seq, "Error _fib_nh=NULL\n"); - continue; - } - if (fa->fa_info == NULL) { - seq_printf(seq, "Error fa_info=NULL\n"); - continue; - } - - seq_printf(seq, "{type=%d scope=%d TOS=%d}\n", - fa->fa_type, - fa->fa_scope, - fa->fa_tos); - } - } - } - else if (IS_TNODE(n)) { - struct tnode *tn=(struct tnode *)n; - putspace_seq(seq, indent); seq_printf(seq, "| "); - seq_printf(seq, "{key prefix=%08x/", tn->key&TKEY_GET_MASK(0, tn->pos)); - printbin_seq(seq, tkey_extract_bits(tn->key, 0, tn->pos), tn->pos); - seq_printf(seq, "}\n"); - putspace_seq(seq, indent); seq_printf(seq, "| "); - seq_printf(seq, "{pos=%d", tn->pos); - seq_printf(seq, " (skip=%d bits)", tn->pos - pend); - seq_printf(seq, " bits=%d (%u children)}\n", tn->bits, (1 << tn->bits)); - putspace_seq(seq, indent); seq_printf(seq, "| "); - seq_printf(seq, "{empty=%d full=%d}\n", tn->empty_children, tn->full_children); - } -} - -static void trie_dump_seq(struct seq_file *seq, struct trie *t) -{ - struct node *n=t->trie; - int cindex=0; - int indent=1; - int pend=0; - int depth = 0; - - read_lock(&fib_lock); - - seq_printf(seq, "------ trie_dump of t=%p ------\n", t); - if (n) { - printnode_seq(seq, indent, n, pend, cindex, 0); - if (IS_TNODE(n)) { - struct tnode *tn=(struct tnode *)n; - pend = tn->pos+tn->bits; - putspace_seq(seq, indent); seq_printf(seq, "\\--\n"); - indent += 3; - depth++; - - while (tn && cindex < (1 << tn->bits)) { - if (tn->child[cindex]) { - - /* Got a child */ - - printnode_seq(seq, indent, tn->child[cindex], pend, cindex, tn->bits); - if (IS_LEAF(tn->child[cindex])) { - cindex++; - - } - else { - /* - * New tnode. Decend one level - */ - - depth++; - n=tn->child[cindex]; - tn=(struct tnode *)n; - pend=tn->pos+tn->bits; - putspace_seq(seq, indent); seq_printf(seq, "\\--\n"); - indent+=3; - cindex=0; - } - } - else - cindex++; - - /* - * Test if we are done - */ - - while (cindex >= (1 << tn->bits)) { - - /* - * Move upwards and test for root - * pop off all traversed nodes - */ - - if (NODE_PARENT(tn) == NULL) { - tn = NULL; - n = NULL; - break; - } - else { - cindex = tkey_extract_bits(tn->key, NODE_PARENT(tn)->pos, NODE_PARENT(tn)->bits); - tn = NODE_PARENT(tn); - cindex++; - n=(struct node *)tn; - pend=tn->pos+tn->bits; - indent-=3; - depth--; - } - } - } - } - else n = NULL; - } - else seq_printf(seq, "------ trie is empty\n"); - - read_unlock(&fib_lock); -} - -static struct trie_stat *trie_stat_new(void) -{ - struct trie_stat *s = kmalloc(sizeof(struct trie_stat), GFP_KERNEL); - int i; - - if(s) { - s->totdepth = 0; - s->maxdepth = 0; - s->tnodes = 0; - s->leaves = 0; - s->nullpointers = 0; - - for(i=0; i< MAX_CHILDS; i++) - s->nodesizes[i] = 0; - } - return s; -} - -static struct trie_stat *trie_collect_stats(struct trie *t) -{ - struct node *n=t->trie; - struct trie_stat *s = trie_stat_new(); - int cindex = 0; - int indent = 1; - int pend = 0; - int depth = 0; - - read_lock(&fib_lock); - - if (s) { - if (n) { - if (IS_TNODE(n)) { - struct tnode *tn = (struct tnode *)n; - pend=tn->pos+tn->bits; - indent += 3; - s->nodesizes[tn->bits]++; - depth++; - - while (tn && cindex < (1 << tn->bits)) { - if (tn->child[cindex]) { - /* Got a child */ - - if (IS_LEAF(tn->child[cindex])) { - cindex++; - - /* stats */ - if (depth > s->maxdepth) - s->maxdepth = depth; - s->totdepth += depth; - s->leaves++; - } - - else { - /* - * New tnode. Decend one level - */ - - s->tnodes++; - s->nodesizes[tn->bits]++; - depth++; - - n = tn->child[cindex]; - tn = (struct tnode *)n; - pend = tn->pos+tn->bits; - - indent += 3; - cindex = 0; - } - } - else { - cindex++; - s->nullpointers++; - } - - /* - * Test if we are done - */ - - while (cindex >= (1 << tn->bits)) { - - /* - * Move upwards and test for root - * pop off all traversed nodes - */ - - - if (NODE_PARENT(tn) == NULL) { - tn = NULL; - n = NULL; - break; - } - else { - cindex = tkey_extract_bits(tn->key, NODE_PARENT(tn)->pos, NODE_PARENT(tn)->bits); - tn = NODE_PARENT(tn); - cindex++; - n = (struct node *)tn; - pend=tn->pos+tn->bits; - indent -= 3; - depth--; - } - } - } - } - else n = NULL; - } - } - - read_unlock(&fib_lock); - return s; -} - -#ifdef CONFIG_PROC_FS - -static struct fib_alias *fib_triestat_get_first(struct seq_file *seq) -{ - return NULL; -} - -static struct fib_alias *fib_triestat_get_next(struct seq_file *seq) -{ - return NULL; -} - -static void *fib_triestat_seq_start(struct seq_file *seq, loff_t *pos) -{ - void *v = NULL; - - if (ip_fib_main_table) - v = *pos ? fib_triestat_get_next(seq) : SEQ_START_TOKEN; - return v; -} - -static void *fib_triestat_seq_next(struct seq_file *seq, void *v, loff_t *pos) -{ - ++*pos; - return v == SEQ_START_TOKEN ? fib_triestat_get_first(seq) : fib_triestat_get_next(seq); -} - -static void fib_triestat_seq_stop(struct seq_file *seq, void *v) -{ - -} - -/* - * This outputs /proc/net/fib_triestats - * - * It always works in backward compatibility mode. - * The format of the file is not supposed to be changed. - */ - -static void collect_and_show(struct trie *t, struct seq_file *seq) -{ - int bytes = 0; /* How many bytes are used, a ref is 4 bytes */ - int i, max, pointers; - struct trie_stat *stat; - int avdepth; - - stat = trie_collect_stats(t); - - bytes=0; - seq_printf(seq, "trie=%p\n", t); - - if (stat) { - if (stat->leaves) - avdepth=stat->totdepth*100 / stat->leaves; - else - avdepth=0; - seq_printf(seq, "Aver depth: %d.%02d\n", avdepth / 100, avdepth % 100 ); - seq_printf(seq, "Max depth: %4d\n", stat->maxdepth); - - seq_printf(seq, "Leaves: %d\n", stat->leaves); - bytes += sizeof(struct leaf) * stat->leaves; - seq_printf(seq, "Internal nodes: %d\n", stat->tnodes); - bytes += sizeof(struct tnode) * stat->tnodes; - - max = MAX_CHILDS-1; - - while (max >= 0 && stat->nodesizes[max] == 0) - max--; - pointers = 0; - - for (i = 1; i <= max; i++) - if (stat->nodesizes[i] != 0) { - seq_printf(seq, " %d: %d", i, stat->nodesizes[i]); - pointers += (1<nodesizes[i]; - } - seq_printf(seq, "\n"); - seq_printf(seq, "Pointers: %d\n", pointers); - bytes += sizeof(struct node *) * pointers; - seq_printf(seq, "Null ptrs: %d\n", stat->nullpointers); - seq_printf(seq, "Total size: %d kB\n", bytes / 1024); - - kfree(stat); - } - -#ifdef CONFIG_IP_FIB_TRIE_STATS - seq_printf(seq, "Counters:\n---------\n"); - seq_printf(seq,"gets = %d\n", t->stats.gets); - seq_printf(seq,"backtracks = %d\n", t->stats.backtrack); - seq_printf(seq,"semantic match passed = %d\n", t->stats.semantic_match_passed); - seq_printf(seq,"semantic match miss = %d\n", t->stats.semantic_match_miss); - seq_printf(seq,"null node hit= %d\n", t->stats.null_node_hit); -#ifdef CLEAR_STATS - memset(&(t->stats), 0, sizeof(t->stats)); -#endif -#endif /* CONFIG_IP_FIB_TRIE_STATS */ -} - -static int fib_triestat_seq_show(struct seq_file *seq, void *v) -{ - char bf[128]; - - if (v == SEQ_START_TOKEN) { - seq_printf(seq, "Basic info: size of leaf: %Zd bytes, size of tnode: %Zd bytes.\n", - sizeof(struct leaf), sizeof(struct tnode)); - if (trie_local) - collect_and_show(trie_local, seq); - - if (trie_main) - collect_and_show(trie_main, seq); - } - else { - snprintf(bf, sizeof(bf), - "*\t%08X\t%08X", 200, 400); - - seq_printf(seq, "%-127s\n", bf); - } - return 0; -} - -static struct seq_operations fib_triestat_seq_ops = { - .start = fib_triestat_seq_start, - .next = fib_triestat_seq_next, - .stop = fib_triestat_seq_stop, - .show = fib_triestat_seq_show, -}; - -static int fib_triestat_seq_open(struct inode *inode, struct file *file) -{ - struct seq_file *seq; - int rc = -ENOMEM; - - rc = seq_open(file, &fib_triestat_seq_ops); - if (rc) - goto out_kfree; - - seq = file->private_data; -out: - return rc; -out_kfree: - goto out; -} - -static struct file_operations fib_triestat_seq_fops = { - .owner = THIS_MODULE, - .open = fib_triestat_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release_private, -}; - -int __init fib_stat_proc_init(void) -{ - if (!proc_net_fops_create("fib_triestat", S_IRUGO, &fib_triestat_seq_fops)) - return -ENOMEM; - return 0; -} - -void __init fib_stat_proc_exit(void) -{ - proc_net_remove("fib_triestat"); -} - -static struct fib_alias *fib_trie_get_first(struct seq_file *seq) -{ - return NULL; -} - -static struct fib_alias *fib_trie_get_next(struct seq_file *seq) -{ - return NULL; -} - -static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos) -{ - void *v = NULL; - - if (ip_fib_main_table) - v = *pos ? fib_trie_get_next(seq) : SEQ_START_TOKEN; - return v; -} - -static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos) -{ - ++*pos; - return v == SEQ_START_TOKEN ? fib_trie_get_first(seq) : fib_trie_get_next(seq); -} - -static void fib_trie_seq_stop(struct seq_file *seq, void *v) -{ - -} - -/* - * This outputs /proc/net/fib_trie. - * - * It always works in backward compatibility mode. - * The format of the file is not supposed to be changed. - */ - -static int fib_trie_seq_show(struct seq_file *seq, void *v) -{ - char bf[128]; - - if (v == SEQ_START_TOKEN) { - if (trie_local) - trie_dump_seq(seq, trie_local); - - if (trie_main) - trie_dump_seq(seq, trie_main); - } - - else { - snprintf(bf, sizeof(bf), - "*\t%08X\t%08X", 200, 400); - seq_printf(seq, "%-127s\n", bf); - } - - return 0; -} - -static struct seq_operations fib_trie_seq_ops = { - .start = fib_trie_seq_start, - .next = fib_trie_seq_next, - .stop = fib_trie_seq_stop, - .show = fib_trie_seq_show, -}; - -static int fib_trie_seq_open(struct inode *inode, struct file *file) -{ - struct seq_file *seq; - int rc = -ENOMEM; - - rc = seq_open(file, &fib_trie_seq_ops); - if (rc) - goto out_kfree; - - seq = file->private_data; -out: - return rc; -out_kfree: - goto out; -} - -static struct file_operations fib_trie_seq_fops = { - .owner = THIS_MODULE, - .open = fib_trie_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release_private, -}; - -int __init fib_proc_init(void) -{ - if (!proc_net_fops_create("fib_trie", S_IRUGO, &fib_trie_seq_fops)) - return -ENOMEM; - return 0; -} - -void __init fib_proc_exit(void) -{ - proc_net_remove("fib_trie"); -} - -#endif /* CONFIG_PROC_FS */ diff --git a/trunk/net/ipv4/ip_input.c b/trunk/net/ipv4/ip_input.c index af2ec88bbb2f..4e47a2658c7c 100644 --- a/trunk/net/ipv4/ip_input.c +++ b/trunk/net/ipv4/ip_input.c @@ -184,7 +184,6 @@ int ip_call_ra_chain(struct sk_buff *skb) raw_rcv(last, skb2); } last = sk; - nf_reset(skb); } } @@ -201,6 +200,10 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb) { int ihl = skb->nh.iph->ihl*4; +#ifdef CONFIG_NETFILTER_DEBUG + nf_debug_ip_local_deliver(skb); +#endif /*CONFIG_NETFILTER_DEBUG*/ + __skb_pull(skb, ihl); /* Free reference early: we don't need it any more, and it may diff --git a/trunk/net/ipv4/ip_output.c b/trunk/net/ipv4/ip_output.c index ee07aec215a0..760dc8238d65 100644 --- a/trunk/net/ipv4/ip_output.c +++ b/trunk/net/ipv4/ip_output.c @@ -107,6 +107,10 @@ static int ip_dev_loopback_xmit(struct sk_buff *newskb) newskb->pkt_type = PACKET_LOOPBACK; newskb->ip_summed = CHECKSUM_UNNECESSARY; BUG_TRAP(newskb->dst); + +#ifdef CONFIG_NETFILTER_DEBUG + nf_debug_ip_loopback_xmit(newskb); +#endif nf_reset(newskb); netif_rx(newskb); return 0; @@ -188,6 +192,10 @@ static inline int ip_finish_output2(struct sk_buff *skb) skb = skb2; } +#ifdef CONFIG_NETFILTER_DEBUG + nf_debug_ip_finish_output2(skb); +#endif /*CONFIG_NETFILTER_DEBUG*/ + nf_reset(skb); if (hh) { @@ -407,6 +415,9 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) to->nf_bridge = from->nf_bridge; nf_bridge_get(to->nf_bridge); #endif +#ifdef CONFIG_NETFILTER_DEBUG + to->nf_debug = from->nf_debug; +#endif #endif } diff --git a/trunk/net/ipv4/ipmr.c b/trunk/net/ipv4/ipmr.c index e4f809a93f47..e21c049ec62a 100644 --- a/trunk/net/ipv4/ipmr.c +++ b/trunk/net/ipv4/ipmr.c @@ -1350,7 +1350,6 @@ int ip_mr_input(struct sk_buff *skb) */ read_lock(&mrt_lock); if (mroute_socket) { - nf_reset(skb); raw_rcv(mroute_socket, skb); read_unlock(&mrt_lock); return 0; diff --git a/trunk/net/ipv4/ipvs/ip_vs_xmit.c b/trunk/net/ipv4/ipvs/ip_vs_xmit.c index a8512a3fd08a..de21da00057f 100644 --- a/trunk/net/ipv4/ipvs/ip_vs_xmit.c +++ b/trunk/net/ipv4/ipvs/ip_vs_xmit.c @@ -127,6 +127,7 @@ ip_vs_dst_reset(struct ip_vs_dest *dest) #define IP_VS_XMIT(skb, rt) \ do { \ + nf_reset_debug(skb); \ (skb)->nfcache |= NFC_IPVS_PROPERTY; \ (skb)->ip_summed = CHECKSUM_NONE; \ NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, (skb), NULL, \ diff --git a/trunk/net/ipv4/netfilter/arp_tables.c b/trunk/net/ipv4/netfilter/arp_tables.c index fa1634256680..df79f5ed6a0a 100644 --- a/trunk/net/ipv4/netfilter/arp_tables.c +++ b/trunk/net/ipv4/netfilter/arp_tables.c @@ -60,6 +60,7 @@ static DECLARE_MUTEX(arpt_mutex); #define ASSERT_READ_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0) #define ASSERT_WRITE_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0) +#include #include struct arpt_table_info { diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_amanda.c b/trunk/net/ipv4/netfilter/ip_conntrack_amanda.c index a78a320eee08..3dbddd062605 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_amanda.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_amanda.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -41,7 +42,7 @@ static char *conns[] = { "DATA ", "MESG ", "INDEX " }; /* This is slow, but it's simple. --RR */ static char amanda_buffer[65536]; -static DEFINE_SPINLOCK(amanda_buffer_lock); +static DECLARE_LOCK(amanda_buffer_lock); unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, @@ -75,7 +76,7 @@ static int help(struct sk_buff **pskb, return NF_ACCEPT; } - spin_lock_bh(&amanda_buffer_lock); + LOCK_BH(&amanda_buffer_lock); skb_copy_bits(*pskb, dataoff, amanda_buffer, (*pskb)->len - dataoff); data = amanda_buffer; data_limit = amanda_buffer + (*pskb)->len - dataoff; @@ -133,7 +134,7 @@ static int help(struct sk_buff **pskb, } out: - spin_unlock_bh(&amanda_buffer_lock); + UNLOCK_BH(&amanda_buffer_lock); return ret; } diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_core.c b/trunk/net/ipv4/netfilter/ip_conntrack_core.c index 4b78ebeb6635..09e824622977 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_core.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_core.c @@ -38,10 +38,10 @@ #include #include -/* ip_conntrack_lock protects the main hash table, protocol/helper/expected +/* This rwlock protects the main hash table, protocol/helper/expected registrations, conntrack timers*/ -#define ASSERT_READ_LOCK(x) -#define ASSERT_WRITE_LOCK(x) +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock) +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock) #include #include @@ -57,7 +57,7 @@ #define DEBUGP(format, args...) #endif -DEFINE_RWLOCK(ip_conntrack_lock); +DECLARE_RWLOCK(ip_conntrack_lock); /* ip_conntrack_standalone needs this */ atomic_t ip_conntrack_count = ATOMIC_INIT(0); @@ -147,7 +147,7 @@ static void destroy_expect(struct ip_conntrack_expect *exp) static void unlink_expect(struct ip_conntrack_expect *exp) { - ASSERT_WRITE_LOCK(&ip_conntrack_lock); + MUST_BE_WRITE_LOCKED(&ip_conntrack_lock); list_del(&exp->list); /* Logically in destroy_expect, but we hold the lock here. */ exp->master->expecting--; @@ -157,9 +157,9 @@ static void expectation_timed_out(unsigned long ul_expect) { struct ip_conntrack_expect *exp = (void *)ul_expect; - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); unlink_expect(exp); - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); destroy_expect(exp); } @@ -209,7 +209,7 @@ clean_from_lists(struct ip_conntrack *ct) unsigned int ho, hr; DEBUGP("clean_from_lists(%p)\n", ct); - ASSERT_WRITE_LOCK(&ip_conntrack_lock); + MUST_BE_WRITE_LOCKED(&ip_conntrack_lock); ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); @@ -240,7 +240,7 @@ destroy_conntrack(struct nf_conntrack *nfct) if (ip_conntrack_destroyed) ip_conntrack_destroyed(ct); - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); /* Expectations will have been removed in clean_from_lists, * except TFTP can create an expectation on the first packet, * before connection is in the list, so we need to clean here, @@ -254,7 +254,7 @@ destroy_conntrack(struct nf_conntrack *nfct) } CONNTRACK_STAT_INC(delete); - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); if (ct->master) ip_conntrack_put(ct->master); @@ -268,12 +268,12 @@ static void death_by_timeout(unsigned long ul_conntrack) { struct ip_conntrack *ct = (void *)ul_conntrack; - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); /* Inside lock so preempt is disabled on module removal path. * Otherwise we can get spurious warnings. */ CONNTRACK_STAT_INC(delete_list); clean_from_lists(ct); - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); ip_conntrack_put(ct); } @@ -282,7 +282,7 @@ conntrack_tuple_cmp(const struct ip_conntrack_tuple_hash *i, const struct ip_conntrack_tuple *tuple, const struct ip_conntrack *ignored_conntrack) { - ASSERT_READ_LOCK(&ip_conntrack_lock); + MUST_BE_READ_LOCKED(&ip_conntrack_lock); return tuplehash_to_ctrack(i) != ignored_conntrack && ip_ct_tuple_equal(tuple, &i->tuple); } @@ -294,7 +294,7 @@ __ip_conntrack_find(const struct ip_conntrack_tuple *tuple, struct ip_conntrack_tuple_hash *h; unsigned int hash = hash_conntrack(tuple); - ASSERT_READ_LOCK(&ip_conntrack_lock); + MUST_BE_READ_LOCKED(&ip_conntrack_lock); list_for_each_entry(h, &ip_conntrack_hash[hash], list) { if (conntrack_tuple_cmp(h, tuple, ignored_conntrack)) { CONNTRACK_STAT_INC(found); @@ -313,11 +313,11 @@ ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple, { struct ip_conntrack_tuple_hash *h; - read_lock_bh(&ip_conntrack_lock); + READ_LOCK(&ip_conntrack_lock); h = __ip_conntrack_find(tuple, ignored_conntrack); if (h) atomic_inc(&tuplehash_to_ctrack(h)->ct_general.use); - read_unlock_bh(&ip_conntrack_lock); + READ_UNLOCK(&ip_conntrack_lock); return h; } @@ -352,7 +352,7 @@ __ip_conntrack_confirm(struct sk_buff **pskb) IP_NF_ASSERT(!is_confirmed(ct)); DEBUGP("Confirming conntrack %p\n", ct); - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); /* See if there's one in the list already, including reverse: NAT could have grabbed it without realizing, since we're @@ -380,12 +380,12 @@ __ip_conntrack_confirm(struct sk_buff **pskb) atomic_inc(&ct->ct_general.use); set_bit(IPS_CONFIRMED_BIT, &ct->status); CONNTRACK_STAT_INC(insert); - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); return NF_ACCEPT; } CONNTRACK_STAT_INC(insert_failed); - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); return NF_DROP; } @@ -398,9 +398,9 @@ ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple, { struct ip_conntrack_tuple_hash *h; - read_lock_bh(&ip_conntrack_lock); + READ_LOCK(&ip_conntrack_lock); h = __ip_conntrack_find(tuple, ignored_conntrack); - read_unlock_bh(&ip_conntrack_lock); + READ_UNLOCK(&ip_conntrack_lock); return h != NULL; } @@ -419,13 +419,13 @@ static int early_drop(struct list_head *chain) struct ip_conntrack *ct = NULL; int dropped = 0; - read_lock_bh(&ip_conntrack_lock); + READ_LOCK(&ip_conntrack_lock); h = LIST_FIND_B(chain, unreplied, struct ip_conntrack_tuple_hash *); if (h) { ct = tuplehash_to_ctrack(h); atomic_inc(&ct->ct_general.use); } - read_unlock_bh(&ip_conntrack_lock); + READ_UNLOCK(&ip_conntrack_lock); if (!ct) return dropped; @@ -508,7 +508,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple, conntrack->timeout.data = (unsigned long)conntrack; conntrack->timeout.function = death_by_timeout; - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); exp = find_expectation(tuple); if (exp) { @@ -532,7 +532,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple, list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed); atomic_inc(&ip_conntrack_count); - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); if (exp) { if (exp->expectfn) @@ -723,17 +723,17 @@ void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp) { struct ip_conntrack_expect *i; - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); /* choose the the oldest expectation to evict */ list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) { if (expect_matches(i, exp) && del_timer(&i->timeout)) { unlink_expect(i); - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); destroy_expect(i); return; } } - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); } struct ip_conntrack_expect *ip_conntrack_expect_alloc(void) @@ -760,11 +760,15 @@ static void ip_conntrack_expect_insert(struct ip_conntrack_expect *exp) exp->master->expecting++; list_add(&exp->list, &ip_conntrack_expect_list); - init_timer(&exp->timeout); - exp->timeout.data = (unsigned long)exp; - exp->timeout.function = expectation_timed_out; - exp->timeout.expires = jiffies + exp->master->helper->timeout * HZ; - add_timer(&exp->timeout); + if (exp->master->helper->timeout) { + init_timer(&exp->timeout); + exp->timeout.data = (unsigned long)exp; + exp->timeout.function = expectation_timed_out; + exp->timeout.expires + = jiffies + exp->master->helper->timeout * HZ; + add_timer(&exp->timeout); + } else + exp->timeout.function = NULL; CONNTRACK_STAT_INC(expect_create); } @@ -804,7 +808,7 @@ int ip_conntrack_expect_related(struct ip_conntrack_expect *expect) DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple); DEBUGP("mask: "); DUMP_TUPLE(&expect->mask); - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); list_for_each_entry(i, &ip_conntrack_expect_list, list) { if (expect_matches(i, expect)) { /* Refresh timer: if it's dying, ignore.. */ @@ -828,7 +832,7 @@ int ip_conntrack_expect_related(struct ip_conntrack_expect *expect) ip_conntrack_expect_insert(expect); ret = 0; out: - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); return ret; } @@ -837,7 +841,7 @@ int ip_conntrack_expect_related(struct ip_conntrack_expect *expect) void ip_conntrack_alter_reply(struct ip_conntrack *conntrack, const struct ip_conntrack_tuple *newreply) { - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); /* Should be unconfirmed, so not in hash table yet */ IP_NF_ASSERT(!is_confirmed(conntrack)); @@ -847,15 +851,15 @@ void ip_conntrack_alter_reply(struct ip_conntrack *conntrack, conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply; if (!conntrack->master && conntrack->expecting == 0) conntrack->helper = ip_ct_find_helper(newreply); - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); } int ip_conntrack_helper_register(struct ip_conntrack_helper *me) { BUG_ON(me->timeout == 0); - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); list_prepend(&helpers, me); - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); return 0; } @@ -874,7 +878,7 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me) struct ip_conntrack_expect *exp, *tmp; /* Need write lock here, to delete helper. */ - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); LIST_DELETE(&helpers, me); /* Get rid of expectations */ @@ -889,7 +893,7 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me) for (i = 0; i < ip_conntrack_htable_size; i++) LIST_FIND_W(&ip_conntrack_hash[i], unhelp, struct ip_conntrack_tuple_hash *, me); - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); /* Someone could be still looking at the helper in a bh. */ synchronize_net(); @@ -921,14 +925,14 @@ void ip_ct_refresh_acct(struct ip_conntrack *ct, ct->timeout.expires = extra_jiffies; ct_add_counters(ct, ctinfo, skb); } else { - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); /* Need del_timer for race avoidance (may already be dying). */ if (del_timer(&ct->timeout)) { ct->timeout.expires = jiffies + extra_jiffies; add_timer(&ct->timeout); } ct_add_counters(ct, ctinfo, skb); - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); } } @@ -936,6 +940,10 @@ void ip_ct_refresh_acct(struct ip_conntrack *ct, struct sk_buff * ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user) { +#ifdef CONFIG_NETFILTER_DEBUG + unsigned int olddebug = skb->nf_debug; +#endif + skb_orphan(skb); local_bh_disable(); @@ -945,7 +953,12 @@ ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user) if (skb) { ip_send_check(skb->nh.iph); skb->nfcache |= NFC_ALTERED; +#ifdef CONFIG_NETFILTER_DEBUG + /* Packet path as if nothing had happened. */ + skb->nf_debug = olddebug; +#endif } + return skb; } @@ -984,7 +997,7 @@ get_next_corpse(int (*iter)(struct ip_conntrack *i, void *data), { struct ip_conntrack_tuple_hash *h = NULL; - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); for (; *bucket < ip_conntrack_htable_size; (*bucket)++) { h = LIST_FIND_W(&ip_conntrack_hash[*bucket], do_iter, struct ip_conntrack_tuple_hash *, iter, data); @@ -996,7 +1009,7 @@ get_next_corpse(int (*iter)(struct ip_conntrack *i, void *data), struct ip_conntrack_tuple_hash *, iter, data); if (h) atomic_inc(&tuplehash_to_ctrack(h)->ct_general.use); - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); return h; } @@ -1188,14 +1201,14 @@ int __init ip_conntrack_init(void) } /* Don't NEED lock here, but good form anyway. */ - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); for (i = 0; i < MAX_IP_CT_PROTO; i++) ip_ct_protos[i] = &ip_conntrack_generic_protocol; /* Sew in builtin protocols. */ ip_ct_protos[IPPROTO_TCP] = &ip_conntrack_protocol_tcp; ip_ct_protos[IPPROTO_UDP] = &ip_conntrack_protocol_udp; ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp; - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); for (i = 0; i < ip_conntrack_htable_size; i++) INIT_LIST_HEAD(&ip_conntrack_hash[i]); diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_ftp.c b/trunk/net/ipv4/netfilter/ip_conntrack_ftp.c index fea6dd2a00b6..dd86503aa788 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_ftp.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_ftp.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -27,7 +28,7 @@ MODULE_DESCRIPTION("ftp connection tracking helper"); /* This is slow, but it's simple. --RR */ static char ftp_buffer[65536]; -static DEFINE_SPINLOCK(ip_ftp_lock); +static DECLARE_LOCK(ip_ftp_lock); #define MAX_PORTS 8 static int ports[MAX_PORTS]; @@ -318,7 +319,7 @@ static int help(struct sk_buff **pskb, } datalen = (*pskb)->len - dataoff; - spin_lock_bh(&ip_ftp_lock); + LOCK_BH(&ip_ftp_lock); fb_ptr = skb_header_pointer(*pskb, dataoff, (*pskb)->len - dataoff, ftp_buffer); BUG_ON(fb_ptr == NULL); @@ -441,7 +442,7 @@ static int help(struct sk_buff **pskb, if (ends_in_nl) update_nl_seq(seq, ct_ftp_info,dir); out: - spin_unlock_bh(&ip_ftp_lock); + UNLOCK_BH(&ip_ftp_lock); return ret; } diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_irc.c b/trunk/net/ipv4/netfilter/ip_conntrack_irc.c index cd98772cc332..33cc7348b6ee 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_irc.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_irc.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -40,7 +41,7 @@ static int max_dcc_channels = 8; static unsigned int dcc_timeout = 300; /* This is slow, but it's simple. --RR */ static char irc_buffer[65536]; -static DEFINE_SPINLOCK(irc_buffer_lock); +static DECLARE_LOCK(irc_buffer_lock); unsigned int (*ip_nat_irc_hook)(struct sk_buff **pskb, enum ip_conntrack_info ctinfo, @@ -140,7 +141,7 @@ static int help(struct sk_buff **pskb, if (dataoff >= (*pskb)->len) return NF_ACCEPT; - spin_lock_bh(&irc_buffer_lock); + LOCK_BH(&irc_buffer_lock); ib_ptr = skb_header_pointer(*pskb, dataoff, (*pskb)->len - dataoff, irc_buffer); BUG_ON(ib_ptr == NULL); @@ -236,7 +237,7 @@ static int help(struct sk_buff **pskb, } /* while data < ... */ out: - spin_unlock_bh(&irc_buffer_lock); + UNLOCK_BH(&irc_buffer_lock); return ret; } diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c index 31d75390bf12..ff8c34a860ff 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_proto_sctp.c @@ -26,6 +26,7 @@ #include #include +#include #if 0 #define DEBUGP(format, ...) printk(format, ## __VA_ARGS__) @@ -34,7 +35,7 @@ #endif /* Protects conntrack->proto.sctp */ -static DEFINE_RWLOCK(sctp_lock); +static DECLARE_RWLOCK(sctp_lock); /* FIXME: Examine ipfilter's timeouts and conntrack transitions more closely. They're more complex. --RR @@ -198,9 +199,9 @@ static int sctp_print_conntrack(struct seq_file *s, DEBUGP(__FUNCTION__); DEBUGP("\n"); - read_lock_bh(&sctp_lock); + READ_LOCK(&sctp_lock); state = conntrack->proto.sctp.state; - read_unlock_bh(&sctp_lock); + READ_UNLOCK(&sctp_lock); return seq_printf(s, "%s ", sctp_conntrack_names[state]); } @@ -342,13 +343,13 @@ static int sctp_packet(struct ip_conntrack *conntrack, oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX; for_each_sctp_chunk (skb, sch, _sch, offset, count) { - write_lock_bh(&sctp_lock); + WRITE_LOCK(&sctp_lock); /* Special cases of Verification tag check (Sec 8.5.1) */ if (sch->type == SCTP_CID_INIT) { /* Sec 8.5.1 (A) */ if (sh->vtag != 0) { - write_unlock_bh(&sctp_lock); + WRITE_UNLOCK(&sctp_lock); return -1; } } else if (sch->type == SCTP_CID_ABORT) { @@ -356,7 +357,7 @@ static int sctp_packet(struct ip_conntrack *conntrack, if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)]) && !(sh->vtag == conntrack->proto.sctp.vtag [1 - CTINFO2DIR(ctinfo)])) { - write_unlock_bh(&sctp_lock); + WRITE_UNLOCK(&sctp_lock); return -1; } } else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) { @@ -365,13 +366,13 @@ static int sctp_packet(struct ip_conntrack *conntrack, && !(sh->vtag == conntrack->proto.sctp.vtag [1 - CTINFO2DIR(ctinfo)] && (sch->flags & 1))) { - write_unlock_bh(&sctp_lock); + WRITE_UNLOCK(&sctp_lock); return -1; } } else if (sch->type == SCTP_CID_COOKIE_ECHO) { /* Sec 8.5.1 (D) */ if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) { - write_unlock_bh(&sctp_lock); + WRITE_UNLOCK(&sctp_lock); return -1; } } @@ -383,7 +384,7 @@ static int sctp_packet(struct ip_conntrack *conntrack, if (newconntrack == SCTP_CONNTRACK_MAX) { DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n", CTINFO2DIR(ctinfo), sch->type, oldsctpstate); - write_unlock_bh(&sctp_lock); + WRITE_UNLOCK(&sctp_lock); return -1; } @@ -395,7 +396,7 @@ static int sctp_packet(struct ip_conntrack *conntrack, ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t), sizeof(_inithdr), &_inithdr); if (ih == NULL) { - write_unlock_bh(&sctp_lock); + WRITE_UNLOCK(&sctp_lock); return -1; } DEBUGP("Setting vtag %x for dir %d\n", @@ -404,7 +405,7 @@ static int sctp_packet(struct ip_conntrack *conntrack, } conntrack->proto.sctp.state = newconntrack; - write_unlock_bh(&sctp_lock); + WRITE_UNLOCK(&sctp_lock); } ip_ct_refresh_acct(conntrack, ctinfo, skb, *sctp_timeouts[newconntrack]); diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index 809dfed766d4..721ddbf522b4 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -36,6 +36,7 @@ #include #include #include +#include #if 0 #define DEBUGP printk @@ -45,7 +46,7 @@ #endif /* Protects conntrack->proto.tcp */ -static DEFINE_RWLOCK(tcp_lock); +static DECLARE_RWLOCK(tcp_lock); /* "Be conservative in what you do, be liberal in what you accept from others." @@ -329,9 +330,9 @@ static int tcp_print_conntrack(struct seq_file *s, { enum tcp_conntrack state; - read_lock_bh(&tcp_lock); + READ_LOCK(&tcp_lock); state = conntrack->proto.tcp.state; - read_unlock_bh(&tcp_lock); + READ_UNLOCK(&tcp_lock); return seq_printf(s, "%s ", tcp_conntrack_names[state]); } @@ -737,14 +738,14 @@ void ip_conntrack_tcp_update(struct sk_buff *skb, end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, iph, tcph); - write_lock_bh(&tcp_lock); + WRITE_LOCK(&tcp_lock); /* * We have to worry for the ack in the reply packet only... */ if (after(end, conntrack->proto.tcp.seen[dir].td_end)) conntrack->proto.tcp.seen[dir].td_end = end; conntrack->proto.tcp.last_end = end; - write_unlock_bh(&tcp_lock); + WRITE_UNLOCK(&tcp_lock); DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i " "receiver end=%u maxend=%u maxwin=%u scale=%i\n", sender->td_end, sender->td_maxend, sender->td_maxwin, @@ -856,7 +857,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, sizeof(_tcph), &_tcph); BUG_ON(th == NULL); - write_lock_bh(&tcp_lock); + WRITE_LOCK(&tcp_lock); old_state = conntrack->proto.tcp.state; dir = CTINFO2DIR(ctinfo); index = get_conntrack_index(th); @@ -878,7 +879,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, * that the client cannot but retransmit its SYN and * thus initiate a clean new session. */ - write_unlock_bh(&tcp_lock); + WRITE_UNLOCK(&tcp_lock); if (LOG_INVALID(IPPROTO_TCP)) nf_log_packet(PF_INET, 0, skb, NULL, NULL, "ip_ct_tcp: killing out of sync session "); @@ -893,7 +894,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, conntrack->proto.tcp.last_end = segment_seq_plus_len(ntohl(th->seq), skb->len, iph, th); - write_unlock_bh(&tcp_lock); + WRITE_UNLOCK(&tcp_lock); if (LOG_INVALID(IPPROTO_TCP)) nf_log_packet(PF_INET, 0, skb, NULL, NULL, "ip_ct_tcp: invalid packet ignored "); @@ -903,7 +904,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, DEBUGP("ip_ct_tcp: Invalid dir=%i index=%u ostate=%u\n", dir, get_conntrack_index(th), old_state); - write_unlock_bh(&tcp_lock); + WRITE_UNLOCK(&tcp_lock); if (LOG_INVALID(IPPROTO_TCP)) nf_log_packet(PF_INET, 0, skb, NULL, NULL, "ip_ct_tcp: invalid state "); @@ -917,13 +918,13 @@ static int tcp_packet(struct ip_conntrack *conntrack, conntrack->proto.tcp.seen[dir].td_end)) { /* Attempt to reopen a closed connection. * Delete this connection and look up again. */ - write_unlock_bh(&tcp_lock); + WRITE_UNLOCK(&tcp_lock); if (del_timer(&conntrack->timeout)) conntrack->timeout.function((unsigned long) conntrack); return -NF_REPEAT; } else { - write_unlock_bh(&tcp_lock); + WRITE_UNLOCK(&tcp_lock); if (LOG_INVALID(IPPROTO_TCP)) nf_log_packet(PF_INET, 0, skb, NULL, NULL, "ip_ct_tcp: invalid SYN"); @@ -948,7 +949,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, if (!tcp_in_window(&conntrack->proto.tcp, dir, index, skb, iph, th)) { - write_unlock_bh(&tcp_lock); + WRITE_UNLOCK(&tcp_lock); return -NF_ACCEPT; } in_window: @@ -971,7 +972,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, timeout = conntrack->proto.tcp.retrans >= ip_ct_tcp_max_retrans && *tcp_timeouts[new_state] > ip_ct_tcp_timeout_max_retrans ? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state]; - write_unlock_bh(&tcp_lock); + WRITE_UNLOCK(&tcp_lock); if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) { /* If only reply is a RST, we can consider ourselves not to diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/trunk/net/ipv4/netfilter/ip_conntrack_proto_udp.c index 8c1eaba098d4..5bc28a224623 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_proto_udp.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_proto_udp.c @@ -120,7 +120,6 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo, * and moreover root might send raw packets. * FIXME: Source route IP option packets --RR */ if (hooknum == NF_IP_PRE_ROUTING - && skb->ip_summed != CHECKSUM_UNNECESSARY && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP, skb->ip_summed == CHECKSUM_HW ? skb->csum : skb_checksum(skb, iph->ihl*4, udplen, 0))) { diff --git a/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c b/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c index 42dc95102873..bc59f7b39805 100644 --- a/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/trunk/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -28,8 +28,8 @@ #include #include -#define ASSERT_READ_LOCK(x) -#define ASSERT_WRITE_LOCK(x) +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock) +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock) #include #include @@ -119,7 +119,7 @@ static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos) static void *ct_seq_start(struct seq_file *seq, loff_t *pos) { - read_lock_bh(&ip_conntrack_lock); + READ_LOCK(&ip_conntrack_lock); return ct_get_idx(seq, *pos); } @@ -131,7 +131,7 @@ static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos) static void ct_seq_stop(struct seq_file *s, void *v) { - read_unlock_bh(&ip_conntrack_lock); + READ_UNLOCK(&ip_conntrack_lock); } static int ct_seq_show(struct seq_file *s, void *v) @@ -140,7 +140,7 @@ static int ct_seq_show(struct seq_file *s, void *v) const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash); struct ip_conntrack_protocol *proto; - ASSERT_READ_LOCK(&ip_conntrack_lock); + MUST_BE_READ_LOCKED(&ip_conntrack_lock); IP_NF_ASSERT(conntrack); /* we only want to print DIR_ORIGINAL */ @@ -239,7 +239,7 @@ static void *exp_seq_start(struct seq_file *s, loff_t *pos) /* strange seq_file api calls stop even if we fail, * thus we need to grab lock since stop unlocks */ - read_lock_bh(&ip_conntrack_lock); + READ_LOCK(&ip_conntrack_lock); if (list_empty(e)) return NULL; @@ -267,7 +267,7 @@ static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) static void exp_seq_stop(struct seq_file *s, void *v) { - read_unlock_bh(&ip_conntrack_lock); + READ_UNLOCK(&ip_conntrack_lock); } static int exp_seq_show(struct seq_file *s, void *v) @@ -921,22 +921,22 @@ int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto) { int ret = 0; - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) { ret = -EBUSY; goto out; } ip_ct_protos[proto->proto] = proto; out: - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); return ret; } void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto) { - write_lock_bh(&ip_conntrack_lock); + WRITE_LOCK(&ip_conntrack_lock); ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol; - write_unlock_bh(&ip_conntrack_lock); + WRITE_UNLOCK(&ip_conntrack_lock); /* Somebody could be still looking at the proto in bh. */ synchronize_net(); diff --git a/trunk/net/ipv4/netfilter/ip_nat_core.c b/trunk/net/ipv4/netfilter/ip_nat_core.c index 739b6dde1c82..9fc6f93af0dd 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_core.c +++ b/trunk/net/ipv4/netfilter/ip_nat_core.c @@ -22,8 +22,8 @@ #include #include -#define ASSERT_READ_LOCK(x) -#define ASSERT_WRITE_LOCK(x) +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock) +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock) #include #include @@ -41,7 +41,7 @@ #define DEBUGP(format, args...) #endif -DEFINE_RWLOCK(ip_nat_lock); +DECLARE_RWLOCK(ip_nat_lock); /* Calculated at init based on memory size */ static unsigned int ip_nat_htable_size; @@ -65,9 +65,9 @@ static void ip_nat_cleanup_conntrack(struct ip_conntrack *conn) if (!(conn->status & IPS_NAT_DONE_MASK)) return; - write_lock_bh(&ip_nat_lock); + WRITE_LOCK(&ip_nat_lock); list_del(&conn->nat.info.bysource); - write_unlock_bh(&ip_nat_lock); + WRITE_UNLOCK(&ip_nat_lock); } /* We do checksum mangling, so if they were wrong before they're still @@ -142,7 +142,7 @@ find_appropriate_src(const struct ip_conntrack_tuple *tuple, unsigned int h = hash_by_src(tuple); struct ip_conntrack *ct; - read_lock_bh(&ip_nat_lock); + READ_LOCK(&ip_nat_lock); list_for_each_entry(ct, &bysource[h], nat.info.bysource) { if (same_src(ct, tuple)) { /* Copy source part from reply tuple. */ @@ -151,12 +151,12 @@ find_appropriate_src(const struct ip_conntrack_tuple *tuple, result->dst = tuple->dst; if (in_range(result, range)) { - read_unlock_bh(&ip_nat_lock); + READ_UNLOCK(&ip_nat_lock); return 1; } } } - read_unlock_bh(&ip_nat_lock); + READ_UNLOCK(&ip_nat_lock); return 0; } @@ -297,9 +297,9 @@ ip_nat_setup_info(struct ip_conntrack *conntrack, unsigned int srchash = hash_by_src(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL] .tuple); - write_lock_bh(&ip_nat_lock); + WRITE_LOCK(&ip_nat_lock); list_add(&info->bysource, &bysource[srchash]); - write_unlock_bh(&ip_nat_lock); + WRITE_UNLOCK(&ip_nat_lock); } /* It's done. */ @@ -474,23 +474,23 @@ int ip_nat_protocol_register(struct ip_nat_protocol *proto) { int ret = 0; - write_lock_bh(&ip_nat_lock); + WRITE_LOCK(&ip_nat_lock); if (ip_nat_protos[proto->protonum] != &ip_nat_unknown_protocol) { ret = -EBUSY; goto out; } ip_nat_protos[proto->protonum] = proto; out: - write_unlock_bh(&ip_nat_lock); + WRITE_UNLOCK(&ip_nat_lock); return ret; } /* Noone stores the protocol anywhere; simply delete it. */ void ip_nat_protocol_unregister(struct ip_nat_protocol *proto) { - write_lock_bh(&ip_nat_lock); + WRITE_LOCK(&ip_nat_lock); ip_nat_protos[proto->protonum] = &ip_nat_unknown_protocol; - write_unlock_bh(&ip_nat_lock); + WRITE_UNLOCK(&ip_nat_lock); /* Someone could be still looking at the proto in a bh. */ synchronize_net(); @@ -509,13 +509,13 @@ int __init ip_nat_init(void) return -ENOMEM; /* Sew in builtin protocols. */ - write_lock_bh(&ip_nat_lock); + WRITE_LOCK(&ip_nat_lock); for (i = 0; i < MAX_IP_NAT_PROTO; i++) ip_nat_protos[i] = &ip_nat_unknown_protocol; ip_nat_protos[IPPROTO_TCP] = &ip_nat_protocol_tcp; ip_nat_protos[IPPROTO_UDP] = &ip_nat_protocol_udp; ip_nat_protos[IPPROTO_ICMP] = &ip_nat_protocol_icmp; - write_unlock_bh(&ip_nat_lock); + WRITE_UNLOCK(&ip_nat_lock); for (i = 0; i < ip_nat_htable_size; i++) { INIT_LIST_HEAD(&bysource[i]); diff --git a/trunk/net/ipv4/netfilter/ip_nat_helper.c b/trunk/net/ipv4/netfilter/ip_nat_helper.c index 158f34f32c04..1637b96d8c01 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_helper.c +++ b/trunk/net/ipv4/netfilter/ip_nat_helper.c @@ -28,8 +28,8 @@ #include #include -#define ASSERT_READ_LOCK(x) -#define ASSERT_WRITE_LOCK(x) +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock) +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock) #include #include @@ -47,7 +47,7 @@ #define DUMP_OFFSET(x) #endif -static DEFINE_SPINLOCK(ip_nat_seqofs_lock); +static DECLARE_LOCK(ip_nat_seqofs_lock); /* Setup TCP sequence correction given this change at this sequence */ static inline void @@ -70,7 +70,7 @@ adjust_tcp_sequence(u32 seq, DEBUGP("ip_nat_resize_packet: Seq_offset before: "); DUMP_OFFSET(this_way); - spin_lock_bh(&ip_nat_seqofs_lock); + LOCK_BH(&ip_nat_seqofs_lock); /* SYN adjust. If it's uninitialized, or this is after last * correction, record it: we don't handle more than one @@ -82,7 +82,7 @@ adjust_tcp_sequence(u32 seq, this_way->offset_before = this_way->offset_after; this_way->offset_after += sizediff; } - spin_unlock_bh(&ip_nat_seqofs_lock); + UNLOCK_BH(&ip_nat_seqofs_lock); DEBUGP("ip_nat_resize_packet: Seq_offset after: "); DUMP_OFFSET(this_way); @@ -142,6 +142,9 @@ static int enlarge_skb(struct sk_buff **pskb, unsigned int extra) /* Transfer socket to new skb. */ if ((*pskb)->sk) skb_set_owner_w(nskb, (*pskb)->sk); +#ifdef CONFIG_NETFILTER_DEBUG + nskb->nf_debug = (*pskb)->nf_debug; +#endif kfree_skb(*pskb); *pskb = nskb; return 1; diff --git a/trunk/net/ipv4/netfilter/ip_nat_rule.c b/trunk/net/ipv4/netfilter/ip_nat_rule.c index 60d70fa41a15..581f097f5a24 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_rule.c +++ b/trunk/net/ipv4/netfilter/ip_nat_rule.c @@ -19,8 +19,8 @@ #include #include -#define ASSERT_READ_LOCK(x) -#define ASSERT_WRITE_LOCK(x) +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock) +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock) #include #include diff --git a/trunk/net/ipv4/netfilter/ip_nat_standalone.c b/trunk/net/ipv4/netfilter/ip_nat_standalone.c index bc59d0d6e89e..79f56f662b33 100644 --- a/trunk/net/ipv4/netfilter/ip_nat_standalone.c +++ b/trunk/net/ipv4/netfilter/ip_nat_standalone.c @@ -31,8 +31,8 @@ #include #include -#define ASSERT_READ_LOCK(x) -#define ASSERT_WRITE_LOCK(x) +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock) +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock) #include #include @@ -373,6 +373,7 @@ static int init_or_cleanup(int init) cleanup_rule_init: ip_nat_rule_cleanup(); cleanup_nothing: + MUST_BE_READ_WRITE_UNLOCKED(&ip_nat_lock); return ret; } diff --git a/trunk/net/ipv4/netfilter/ip_tables.c b/trunk/net/ipv4/netfilter/ip_tables.c index c88dfcd38c56..8a54f92b8496 100644 --- a/trunk/net/ipv4/netfilter/ip_tables.c +++ b/trunk/net/ipv4/netfilter/ip_tables.c @@ -67,6 +67,7 @@ static DECLARE_MUTEX(ipt_mutex); /* Must have mutex */ #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0) +#include #include #if 0 diff --git a/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c b/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c index dc4362b57cfa..0f12e3a3dc73 100644 --- a/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c +++ b/trunk/net/ipv4/netfilter/ipt_CLUSTERIP.c @@ -29,6 +29,7 @@ #include #include #include +#include #define CLUSTERIP_VERSION "0.6" @@ -40,8 +41,6 @@ #define DEBUGP #endif -#define ASSERT_READ_LOCK(x) - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Harald Welte "); MODULE_DESCRIPTION("iptables target for CLUSTERIP"); @@ -68,7 +67,7 @@ static LIST_HEAD(clusterip_configs); /* clusterip_lock protects the clusterip_configs list _AND_ the configurable * data within all structurses (num_local_nodes, local_nodes[]) */ -static DEFINE_RWLOCK(clusterip_lock); +static DECLARE_RWLOCK(clusterip_lock); #ifdef CONFIG_PROC_FS static struct file_operations clusterip_proc_fops; @@ -83,9 +82,9 @@ clusterip_config_get(struct clusterip_config *c) { static inline void clusterip_config_put(struct clusterip_config *c) { if (atomic_dec_and_test(&c->refcount)) { - write_lock_bh(&clusterip_lock); + WRITE_LOCK(&clusterip_lock); list_del(&c->list); - write_unlock_bh(&clusterip_lock); + WRITE_UNLOCK(&clusterip_lock); dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0); dev_put(c->dev); kfree(c); @@ -98,7 +97,7 @@ __clusterip_config_find(u_int32_t clusterip) { struct list_head *pos; - ASSERT_READ_LOCK(&clusterip_lock); + MUST_BE_READ_LOCKED(&clusterip_lock); list_for_each(pos, &clusterip_configs) { struct clusterip_config *c = list_entry(pos, struct clusterip_config, list); @@ -115,14 +114,14 @@ clusterip_config_find_get(u_int32_t clusterip) { struct clusterip_config *c; - read_lock_bh(&clusterip_lock); + READ_LOCK(&clusterip_lock); c = __clusterip_config_find(clusterip); if (!c) { - read_unlock_bh(&clusterip_lock); + READ_UNLOCK(&clusterip_lock); return NULL; } atomic_inc(&c->refcount); - read_unlock_bh(&clusterip_lock); + READ_UNLOCK(&clusterip_lock); return c; } @@ -161,9 +160,9 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip, c->pde->data = c; #endif - write_lock_bh(&clusterip_lock); + WRITE_LOCK(&clusterip_lock); list_add(&c->list, &clusterip_configs); - write_unlock_bh(&clusterip_lock); + WRITE_UNLOCK(&clusterip_lock); return c; } @@ -173,25 +172,25 @@ clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum) { int i; - write_lock_bh(&clusterip_lock); + WRITE_LOCK(&clusterip_lock); if (c->num_local_nodes >= CLUSTERIP_MAX_NODES || nodenum > CLUSTERIP_MAX_NODES) { - write_unlock_bh(&clusterip_lock); + WRITE_UNLOCK(&clusterip_lock); return 1; } /* check if we alrady have this number in our array */ for (i = 0; i < c->num_local_nodes; i++) { if (c->local_nodes[i] == nodenum) { - write_unlock_bh(&clusterip_lock); + WRITE_UNLOCK(&clusterip_lock); return 1; } } c->local_nodes[c->num_local_nodes++] = nodenum; - write_unlock_bh(&clusterip_lock); + WRITE_UNLOCK(&clusterip_lock); return 0; } @@ -200,10 +199,10 @@ clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum) { int i; - write_lock_bh(&clusterip_lock); + WRITE_LOCK(&clusterip_lock); if (c->num_local_nodes <= 1 || nodenum > CLUSTERIP_MAX_NODES) { - write_unlock_bh(&clusterip_lock); + WRITE_UNLOCK(&clusterip_lock); return 1; } @@ -212,12 +211,12 @@ clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum) int size = sizeof(u_int16_t)*(c->num_local_nodes-(i+1)); memmove(&c->local_nodes[i], &c->local_nodes[i+1], size); c->num_local_nodes--; - write_unlock_bh(&clusterip_lock); + WRITE_UNLOCK(&clusterip_lock); return 0; } } - write_unlock_bh(&clusterip_lock); + WRITE_UNLOCK(&clusterip_lock); return 1; } @@ -287,21 +286,21 @@ clusterip_responsible(struct clusterip_config *config, u_int32_t hash) { int i; - read_lock_bh(&clusterip_lock); + READ_LOCK(&clusterip_lock); if (config->num_local_nodes == 0) { - read_unlock_bh(&clusterip_lock); + READ_UNLOCK(&clusterip_lock); return 0; } for (i = 0; i < config->num_local_nodes; i++) { if (config->local_nodes[i] == hash) { - read_unlock_bh(&clusterip_lock); + READ_UNLOCK(&clusterip_lock); return 1; } } - read_unlock_bh(&clusterip_lock); + READ_UNLOCK(&clusterip_lock); return 0; } @@ -579,7 +578,7 @@ static void *clusterip_seq_start(struct seq_file *s, loff_t *pos) struct clusterip_config *c = pde->data; unsigned int *nodeidx; - read_lock_bh(&clusterip_lock); + READ_LOCK(&clusterip_lock); if (*pos >= c->num_local_nodes) return NULL; @@ -609,7 +608,7 @@ static void clusterip_seq_stop(struct seq_file *s, void *v) { kfree(v); - read_unlock_bh(&clusterip_lock); + READ_UNLOCK(&clusterip_lock); } static int clusterip_seq_show(struct seq_file *s, void *v) diff --git a/trunk/net/ipv4/netfilter/ipt_MASQUERADE.c b/trunk/net/ipv4/netfilter/ipt_MASQUERADE.c index 91e74502c3d3..57e9f6cf1c36 100644 --- a/trunk/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/trunk/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -33,7 +33,7 @@ MODULE_DESCRIPTION("iptables MASQUERADE target module"); #endif /* Lock protects masq region inside conntrack */ -static DEFINE_RWLOCK(masq_lock); +static DECLARE_RWLOCK(masq_lock); /* FIXME: Multiple targets. --RR */ static int @@ -103,9 +103,9 @@ masquerade_target(struct sk_buff **pskb, return NF_DROP; } - write_lock_bh(&masq_lock); + WRITE_LOCK(&masq_lock); ct->nat.masq_index = out->ifindex; - write_unlock_bh(&masq_lock); + WRITE_UNLOCK(&masq_lock); /* Transfer from original range. */ newrange = ((struct ip_nat_range) @@ -122,9 +122,9 @@ device_cmp(struct ip_conntrack *i, void *ifindex) { int ret; - read_lock_bh(&masq_lock); + READ_LOCK(&masq_lock); ret = (i->nat.masq_index == (int)(long)ifindex); - read_unlock_bh(&masq_lock); + READ_UNLOCK(&masq_lock); return ret; } diff --git a/trunk/net/ipv4/netfilter/ipt_REJECT.c b/trunk/net/ipv4/netfilter/ipt_REJECT.c index 915696446020..266d64979286 100644 --- a/trunk/net/ipv4/netfilter/ipt_REJECT.c +++ b/trunk/net/ipv4/netfilter/ipt_REJECT.c @@ -104,12 +104,10 @@ static inline struct rtable *route_reverse(struct sk_buff *skb, static void send_reset(struct sk_buff *oldskb, int hook) { struct sk_buff *nskb; - struct iphdr *iph = oldskb->nh.iph; struct tcphdr _otcph, *oth, *tcph; struct rtable *rt; u_int16_t tmp_port; u_int32_t tmp_addr; - unsigned int tcplen; int needs_ack; int hh_len; @@ -126,16 +124,7 @@ static void send_reset(struct sk_buff *oldskb, int hook) if (oth->rst) return; - /* Check checksum */ - tcplen = oldskb->len - iph->ihl * 4; - if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) || - (hook == NF_IP_LOCAL_IN && - oldskb->ip_summed != CHECKSUM_UNNECESSARY)) && - csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP, - oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum : - skb_checksum(oldskb, iph->ihl * 4, tcplen, 0))) - return; - + /* FIXME: Check checksum --RR */ if ((rt = route_reverse(oldskb, oth, hook)) == NULL) return; diff --git a/trunk/net/ipv4/netfilter/ipt_ULOG.c b/trunk/net/ipv4/netfilter/ipt_ULOG.c index 52a0076302a7..6f2cefbe16cd 100644 --- a/trunk/net/ipv4/netfilter/ipt_ULOG.c +++ b/trunk/net/ipv4/netfilter/ipt_ULOG.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -98,8 +99,8 @@ typedef struct { static ulog_buff_t ulog_buffers[ULOG_MAXNLGROUPS]; /* array of buffers */ -static struct sock *nflognl; /* our socket */ -static DEFINE_SPINLOCK(ulog_lock); /* spinlock */ +static struct sock *nflognl; /* our socket */ +static DECLARE_LOCK(ulog_lock); /* spinlock */ /* send one ulog_buff_t to userspace */ static void ulog_send(unsigned int nlgroupnum) @@ -134,9 +135,9 @@ static void ulog_timer(unsigned long data) /* lock to protect against somebody modifying our structure * from ipt_ulog_target at the same time */ - spin_lock_bh(&ulog_lock); + LOCK_BH(&ulog_lock); ulog_send(data); - spin_unlock_bh(&ulog_lock); + UNLOCK_BH(&ulog_lock); } static struct sk_buff *ulog_alloc_skb(unsigned int size) @@ -192,7 +193,7 @@ static void ipt_ulog_packet(unsigned int hooknum, ub = &ulog_buffers[groupnum]; - spin_lock_bh(&ulog_lock); + LOCK_BH(&ulog_lock); if (!ub->skb) { if (!(ub->skb = ulog_alloc_skb(size))) @@ -277,7 +278,7 @@ static void ipt_ulog_packet(unsigned int hooknum, ulog_send(groupnum); } - spin_unlock_bh(&ulog_lock); + UNLOCK_BH(&ulog_lock); return; @@ -287,7 +288,7 @@ static void ipt_ulog_packet(unsigned int hooknum, alloc_failure: PRINTR("ipt_ULOG: Error building netlink message\n"); - spin_unlock_bh(&ulog_lock); + UNLOCK_BH(&ulog_lock); } static unsigned int ipt_ulog_target(struct sk_buff **pskb, diff --git a/trunk/net/ipv4/netfilter/ipt_hashlimit.c b/trunk/net/ipv4/netfilter/ipt_hashlimit.c index 564b49bfebcf..f1937190cd77 100644 --- a/trunk/net/ipv4/netfilter/ipt_hashlimit.c +++ b/trunk/net/ipv4/netfilter/ipt_hashlimit.c @@ -37,6 +37,7 @@ #include #include +#include /* FIXME: this is just for IP_NF_ASSERRT */ #include @@ -91,7 +92,7 @@ struct ipt_hashlimit_htable { struct hlist_head hash[0]; /* hashtable itself */ }; -static DEFINE_SPINLOCK(hashlimit_lock); /* protects htables list */ +static DECLARE_LOCK(hashlimit_lock); /* protects htables list */ static DECLARE_MUTEX(hlimit_mutex); /* additional checkentry protection */ static HLIST_HEAD(hashlimit_htables); static kmem_cache_t *hashlimit_cachep; @@ -232,9 +233,9 @@ static int htable_create(struct ipt_hashlimit_info *minfo) hinfo->timer.function = htable_gc; add_timer(&hinfo->timer); - spin_lock_bh(&hashlimit_lock); + LOCK_BH(&hashlimit_lock); hlist_add_head(&hinfo->node, &hashlimit_htables); - spin_unlock_bh(&hashlimit_lock); + UNLOCK_BH(&hashlimit_lock); return 0; } @@ -300,15 +301,15 @@ static struct ipt_hashlimit_htable *htable_find_get(char *name) struct ipt_hashlimit_htable *hinfo; struct hlist_node *pos; - spin_lock_bh(&hashlimit_lock); + LOCK_BH(&hashlimit_lock); hlist_for_each_entry(hinfo, pos, &hashlimit_htables, node) { if (!strcmp(name, hinfo->pde->name)) { atomic_inc(&hinfo->use); - spin_unlock_bh(&hashlimit_lock); + UNLOCK_BH(&hashlimit_lock); return hinfo; } } - spin_unlock_bh(&hashlimit_lock); + UNLOCK_BH(&hashlimit_lock); return NULL; } @@ -316,9 +317,9 @@ static struct ipt_hashlimit_htable *htable_find_get(char *name) static void htable_put(struct ipt_hashlimit_htable *hinfo) { if (atomic_dec_and_test(&hinfo->use)) { - spin_lock_bh(&hashlimit_lock); + LOCK_BH(&hashlimit_lock); hlist_del(&hinfo->node); - spin_unlock_bh(&hashlimit_lock); + UNLOCK_BH(&hashlimit_lock); htable_destroy(hinfo); } } diff --git a/trunk/net/ipv4/netfilter/ipt_helper.c b/trunk/net/ipv4/netfilter/ipt_helper.c index 3e7dd014de43..33fdf364d3d3 100644 --- a/trunk/net/ipv4/netfilter/ipt_helper.c +++ b/trunk/net/ipv4/netfilter/ipt_helper.c @@ -53,7 +53,7 @@ match(const struct sk_buff *skb, return ret; } - read_lock_bh(&ip_conntrack_lock); + READ_LOCK(&ip_conntrack_lock); if (!ct->master->helper) { DEBUGP("ipt_helper: master ct %p has no helper\n", exp->expectant); @@ -69,7 +69,7 @@ match(const struct sk_buff *skb, ret ^= !strncmp(ct->master->helper->name, info->name, strlen(ct->master->helper->name)); out_unlock: - read_unlock_bh(&ip_conntrack_lock); + READ_UNLOCK(&ip_conntrack_lock); return ret; } diff --git a/trunk/net/ipv6/addrconf.c b/trunk/net/ipv6/addrconf.c index 14f5c53235fe..47a30c3188ea 100644 --- a/trunk/net/ipv6/addrconf.c +++ b/trunk/net/ipv6/addrconf.c @@ -695,7 +695,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { if (onlink == 0) { - ip6_del_rt(rt, NULL, NULL, NULL); + ip6_del_rt(rt, NULL, NULL); rt = NULL; } else if (!(rt->rt6i_flags & RTF_EXPIRES)) { rt->rt6i_expires = expires; @@ -1340,7 +1340,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT)) rtmsg.rtmsg_flags |= RTF_NONEXTHOP; - ip6_route_add(&rtmsg, NULL, NULL, NULL); + ip6_route_add(&rtmsg, NULL, NULL); } /* Create "default" multicast route to the interface */ @@ -1357,7 +1357,7 @@ static void addrconf_add_mroute(struct net_device *dev) rtmsg.rtmsg_ifindex = dev->ifindex; rtmsg.rtmsg_flags = RTF_UP; rtmsg.rtmsg_type = RTMSG_NEWROUTE; - ip6_route_add(&rtmsg, NULL, NULL, NULL); + ip6_route_add(&rtmsg, NULL, NULL); } static void sit_route_add(struct net_device *dev) @@ -1374,7 +1374,7 @@ static void sit_route_add(struct net_device *dev) rtmsg.rtmsg_flags = RTF_UP|RTF_NONEXTHOP; rtmsg.rtmsg_ifindex = dev->ifindex; - ip6_route_add(&rtmsg, NULL, NULL, NULL); + ip6_route_add(&rtmsg, NULL, NULL); } static void addrconf_add_lroute(struct net_device *dev) @@ -1467,7 +1467,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { if (rt->rt6i_flags&RTF_EXPIRES) { if (valid_lft == 0) { - ip6_del_rt(rt, NULL, NULL, NULL); + ip6_del_rt(rt, NULL, NULL); rt = NULL; } else { rt->rt6i_expires = rt_expires; @@ -3094,7 +3094,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) switch (event) { case RTM_NEWADDR: dst_hold(&ifp->rt->u.dst); - if (ip6_ins_rt(ifp->rt, NULL, NULL, NULL)) + if (ip6_ins_rt(ifp->rt, NULL, NULL)) dst_release(&ifp->rt->u.dst); if (ifp->idev->cnf.forwarding) addrconf_join_anycast(ifp); @@ -3104,7 +3104,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) addrconf_leave_anycast(ifp); addrconf_leave_solict(ifp->idev, &ifp->addr); dst_hold(&ifp->rt->u.dst); - if (ip6_del_rt(ifp->rt, NULL, NULL, NULL)) + if (ip6_del_rt(ifp->rt, NULL, NULL)) dst_free(&ifp->rt->u.dst); else dst_release(&ifp->rt->u.dst); diff --git a/trunk/net/ipv6/anycast.c b/trunk/net/ipv6/anycast.c index 6b7294047238..5d22ca3cca2e 100644 --- a/trunk/net/ipv6/anycast.c +++ b/trunk/net/ipv6/anycast.c @@ -337,7 +337,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr) write_unlock_bh(&idev->lock); dst_hold(&rt->u.dst); - if (ip6_ins_rt(rt, NULL, NULL, NULL)) + if (ip6_ins_rt(rt, NULL, NULL)) dst_release(&rt->u.dst); addrconf_join_solict(dev, &aca->aca_addr); @@ -380,7 +380,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr) addrconf_leave_solict(idev, &aca->aca_addr); dst_hold(&aca->aca_rt->u.dst); - if (ip6_del_rt(aca->aca_rt, NULL, NULL, NULL)) + if (ip6_del_rt(aca->aca_rt, NULL, NULL)) dst_free(&aca->aca_rt->u.dst); else dst_release(&aca->aca_rt->u.dst); diff --git a/trunk/net/ipv6/ip6_fib.c b/trunk/net/ipv6/ip6_fib.c index 1b354aa97934..405740b75abb 100644 --- a/trunk/net/ipv6/ip6_fib.c +++ b/trunk/net/ipv6/ip6_fib.c @@ -394,7 +394,7 @@ static struct fib6_node * fib6_add_1(struct fib6_node *root, void *addr, */ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, - struct nlmsghdr *nlh, struct netlink_skb_parms *req) + struct nlmsghdr *nlh) { struct rt6_info *iter = NULL; struct rt6_info **ins; @@ -449,7 +449,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, *ins = rt; rt->rt6i_node = fn; atomic_inc(&rt->rt6i_ref); - inet6_rt_notify(RTM_NEWROUTE, rt, nlh, req); + inet6_rt_notify(RTM_NEWROUTE, rt, nlh); rt6_stats.fib_rt_entries++; if ((fn->fn_flags & RTN_RTINFO) == 0) { @@ -479,8 +479,7 @@ void fib6_force_start_gc(void) * with source addr info in sub-trees */ -int fib6_add(struct fib6_node *root, struct rt6_info *rt, - struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) +int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr) { struct fib6_node *fn; int err = -ENOMEM; @@ -553,7 +552,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, } #endif - err = fib6_add_rt2node(fn, rt, nlh, req); + err = fib6_add_rt2node(fn, rt, nlh); if (err == 0) { fib6_start_gc(rt); @@ -860,7 +859,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn) } static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, - struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) + struct nlmsghdr *nlh, void *_rtattr) { struct fib6_walker_t *w; struct rt6_info *rt = *rtp; @@ -916,11 +915,11 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp, if (atomic_read(&rt->rt6i_ref) != 1) BUG(); } - inet6_rt_notify(RTM_DELROUTE, rt, nlh, req); + inet6_rt_notify(RTM_DELROUTE, rt, nlh); rt6_release(rt); } -int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) +int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr) { struct fib6_node *fn = rt->rt6i_node; struct rt6_info **rtp; @@ -945,7 +944,7 @@ int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct ne for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) { if (*rtp == rt) { - fib6_del_route(fn, rtp, nlh, _rtattr, req); + fib6_del_route(fn, rtp, nlh, _rtattr); return 0; } } @@ -1074,7 +1073,7 @@ static int fib6_clean_node(struct fib6_walker_t *w) res = c->func(rt, c->arg); if (res < 0) { w->leaf = rt; - res = fib6_del(rt, NULL, NULL, NULL); + res = fib6_del(rt, NULL, NULL); if (res) { #if RT6_DEBUG >= 2 printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res); diff --git a/trunk/net/ipv6/ip6_output.c b/trunk/net/ipv6/ip6_output.c index 06e7cdaeedc5..b78a53586804 100644 --- a/trunk/net/ipv6/ip6_output.c +++ b/trunk/net/ipv6/ip6_output.c @@ -484,6 +484,9 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) to->nf_bridge = from->nf_bridge; nf_bridge_get(to->nf_bridge); #endif +#ifdef CONFIG_NETFILTER_DEBUG + to->nf_debug = from->nf_debug; +#endif #endif } diff --git a/trunk/net/ipv6/ipv6_sockglue.c b/trunk/net/ipv6/ipv6_sockglue.c index f3ef4c38d315..279ab86be662 100644 --- a/trunk/net/ipv6/ipv6_sockglue.c +++ b/trunk/net/ipv6/ipv6_sockglue.c @@ -423,12 +423,11 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, psin6 = (struct sockaddr_in6 *)&greqs.gsr_group; retv = ipv6_sock_mc_join(sk, greqs.gsr_interface, &psin6->sin6_addr); - /* prior join w/ different source is ok */ - if (retv && retv != -EADDRINUSE) + if (retv) break; omode = MCAST_INCLUDE; add = 1; - } else /* MCAST_LEAVE_SOURCE_GROUP */ { + } else /*IP_DROP_SOURCE_MEMBERSHIP */ { omode = MCAST_INCLUDE; add = 0; } diff --git a/trunk/net/ipv6/mcast.c b/trunk/net/ipv6/mcast.c index 562fcd14fdea..393b6e6f50a9 100644 --- a/trunk/net/ipv6/mcast.c +++ b/trunk/net/ipv6/mcast.c @@ -188,16 +188,6 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr) if (!ipv6_addr_is_multicast(addr)) return -EINVAL; - read_lock_bh(&ipv6_sk_mc_lock); - for (mc_lst=np->ipv6_mc_list; mc_lst; mc_lst=mc_lst->next) { - if ((ifindex == 0 || mc_lst->ifindex == ifindex) && - ipv6_addr_equal(&mc_lst->addr, addr)) { - read_unlock_bh(&ipv6_sk_mc_lock); - return -EADDRINUSE; - } - } - read_unlock_bh(&ipv6_sk_mc_lock); - mc_lst = sock_kmalloc(sk, sizeof(struct ipv6_mc_socklist), GFP_KERNEL); if (mc_lst == NULL) @@ -359,7 +349,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk, struct ipv6_pinfo *inet6 = inet6_sk(sk); struct ip6_sf_socklist *psl; int i, j, rv; - int leavegroup = 0; int err; if (pgsr->gsr_group.ss_family != AF_INET6 || @@ -379,7 +368,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk, err = -EADDRNOTAVAIL; - read_lock_bh(&ipv6_sk_mc_lock); for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) { if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface) continue; @@ -413,12 +401,6 @@ int ip6_mc_source(int add, int omode, struct sock *sk, if (rv) /* source not found */ goto done; - /* special case - (INCLUDE, empty) == LEAVE_GROUP */ - if (psl->sl_count == 1 && omode == MCAST_INCLUDE) { - leavegroup = 1; - goto done; - } - /* update the interface filter */ ip6_mc_del_src(idev, group, omode, 1, source, 1); @@ -471,12 +453,9 @@ int ip6_mc_source(int add, int omode, struct sock *sk, /* update the interface list */ ip6_mc_add_src(idev, group, omode, 1, source, 1); done: - read_unlock_bh(&ipv6_sk_mc_lock); read_unlock_bh(&idev->lock); in6_dev_put(idev); dev_put(dev); - if (leavegroup) - return ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group); return err; } @@ -1301,6 +1280,15 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) return NULL; skb_reserve(skb, LL_RESERVED_SPACE(dev)); + if (dev->hard_header) { + unsigned char ha[MAX_ADDR_LEN]; + + ndisc_mc_map(&mld2_all_mcr, ha, dev, 1); + if (dev->hard_header(skb, dev, ETH_P_IPV6,ha,NULL,size) < 0) { + kfree_skb(skb); + return NULL; + } + } if (ipv6_get_lladdr(dev, &addr_buf)) { /* : @@ -1324,30 +1312,6 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) return skb; } -static inline int mld_dev_queue_xmit2(struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - - if (dev->hard_header) { - unsigned char ha[MAX_ADDR_LEN]; - int err; - - ndisc_mc_map(&skb->nh.ipv6h->daddr, ha, dev, 1); - err = dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len); - if (err < 0) { - kfree_skb(skb); - return err; - } - } - return dev_queue_xmit(skb); -} - -static inline int mld_dev_queue_xmit(struct sk_buff *skb) -{ - return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dev, - mld_dev_queue_xmit2); -} - static void mld_sendpack(struct sk_buff *skb) { struct ipv6hdr *pip6 = skb->nh.ipv6h; @@ -1365,7 +1329,7 @@ static void mld_sendpack(struct sk_buff *skb) pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen, IPPROTO_ICMPV6, csum_partial(skb->h.raw, mldlen, 0)); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev, - mld_dev_queue_xmit); + dev_queue_xmit); if (!err) { ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS); IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS); @@ -1671,6 +1635,12 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) } skb_reserve(skb, LL_RESERVED_SPACE(dev)); + if (dev->hard_header) { + unsigned char ha[MAX_ADDR_LEN]; + ndisc_mc_map(snd_addr, ha, dev, 1); + if (dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, full_len) < 0) + goto out; + } if (ipv6_get_lladdr(dev, &addr_buf)) { /* : @@ -1698,7 +1668,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) idev = in6_dev_get(skb->dev); err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev, - mld_dev_queue_xmit); + dev_queue_xmit); if (!err) { if (type == ICMPV6_MGM_REDUCTION) ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBREDUCTIONS); @@ -1712,6 +1682,10 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) if (likely(idev != NULL)) in6_dev_put(idev); return; + +out: + IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS); + kfree_skb(skb); } static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, diff --git a/trunk/net/ipv6/ndisc.c b/trunk/net/ipv6/ndisc.c index 7ae72d4c9bd2..7c291f4e9edc 100644 --- a/trunk/net/ipv6/ndisc.c +++ b/trunk/net/ipv6/ndisc.c @@ -955,7 +955,7 @@ static void ndisc_recv_na(struct sk_buff *skb) struct rt6_info *rt; rt = rt6_get_dflt_router(saddr, dev); if (rt) - ip6_del_rt(rt, NULL, NULL, NULL); + ip6_del_rt(rt, NULL, NULL); } out: @@ -1096,7 +1096,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) if (rt && lifetime == 0) { neigh_clone(neigh); - ip6_del_rt(rt, NULL, NULL, NULL); + ip6_del_rt(rt, NULL, NULL); rt = NULL; } diff --git a/trunk/net/ipv6/netfilter/ip6_tables.c b/trunk/net/ipv6/netfilter/ip6_tables.c index 73034511c8db..c735276fdd5f 100644 --- a/trunk/net/ipv6/netfilter/ip6_tables.c +++ b/trunk/net/ipv6/netfilter/ip6_tables.c @@ -71,6 +71,7 @@ static DECLARE_MUTEX(ip6t_mutex); /* Must have mutex */ #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0) #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0) +#include #include #if 0 diff --git a/trunk/net/ipv6/netfilter/ip6t_LOG.c b/trunk/net/ipv6/netfilter/ip6t_LOG.c index c44685e391b7..bfc3d0185d19 100644 --- a/trunk/net/ipv6/netfilter/ip6t_LOG.c +++ b/trunk/net/ipv6/netfilter/ip6t_LOG.c @@ -366,6 +366,8 @@ ip6t_log_packet(unsigned int hooknum, const char *level_string, const char *prefix) { + struct ipv6hdr *ipv6h = skb->nh.ipv6h; + spin_lock_bh(&log_lock); printk(level_string); printk("%sIN=%s OUT=%s ", @@ -375,25 +377,39 @@ ip6t_log_packet(unsigned int hooknum, if (in && !out) { /* MAC logging for input chain only. */ printk("MAC="); - if (skb->dev && skb->dev->hard_header_len && - skb->mac.raw != skb->nh.raw) { - unsigned char *p = skb->mac.raw; - int i; - - if (skb->dev->type == ARPHRD_SIT && - (p -= ETH_HLEN) < skb->head) - p = NULL; - - if (p != NULL) - for (i = 0; i < skb->dev->hard_header_len; i++) - printk("%02x", p[i]); - printk(" "); - - if (skb->dev->type == ARPHRD_SIT) { - struct iphdr *iph = (struct iphdr *)skb->mac.raw; - printk("TUNNEL=%u.%u.%u.%u->%u.%u.%u.%u ", - NIPQUAD(iph->saddr), - NIPQUAD(iph->daddr)); + if (skb->dev && skb->dev->hard_header_len && skb->mac.raw != (void*)ipv6h) { + if (skb->dev->type != ARPHRD_SIT){ + int i; + unsigned char *p = skb->mac.raw; + for (i = 0; i < skb->dev->hard_header_len; i++,p++) + printk("%02x%c", *p, + i==skb->dev->hard_header_len - 1 + ? ' ':':'); + } else { + int i; + unsigned char *p = skb->mac.raw; + if ( p - (ETH_ALEN*2+2) > skb->head ){ + p -= (ETH_ALEN+2); + for (i = 0; i < (ETH_ALEN); i++,p++) + printk("%02x%s", *p, + i == ETH_ALEN-1 ? "->" : ":"); + p -= (ETH_ALEN*2); + for (i = 0; i < (ETH_ALEN); i++,p++) + printk("%02x%c", *p, + i == ETH_ALEN-1 ? ' ' : ':'); + } + + if ((skb->dev->addr_len == 4) && + skb->dev->hard_header_len > 20){ + printk("TUNNEL="); + p = skb->mac.raw + 12; + for (i = 0; i < 4; i++,p++) + printk("%3d%s", *p, + i == 3 ? "->" : "."); + for (i = 0; i < 4; i++,p++) + printk("%3d%c", *p, + i == 3 ? ' ' : '.'); + } } } else printk(" "); diff --git a/trunk/net/ipv6/netfilter/ip6table_raw.c b/trunk/net/ipv6/netfilter/ip6table_raw.c index c2982efd14af..71407beaf790 100644 --- a/trunk/net/ipv6/netfilter/ip6table_raw.c +++ b/trunk/net/ipv6/netfilter/ip6table_raw.c @@ -129,15 +129,13 @@ static struct nf_hook_ops ip6t_ops[] = { .hook = ip6t_hook, .pf = PF_INET6, .hooknum = NF_IP6_PRE_ROUTING, - .priority = NF_IP6_PRI_FIRST, - .owner = THIS_MODULE, + .priority = NF_IP6_PRI_FIRST }, { .hook = ip6t_hook, .pf = PF_INET6, .hooknum = NF_IP6_LOCAL_OUT, - .priority = NF_IP6_PRI_FIRST, - .owner = THIS_MODULE, + .priority = NF_IP6_PRI_FIRST }, }; diff --git a/trunk/net/ipv6/route.c b/trunk/net/ipv6/route.c index 878789b3122d..1f5b226c3573 100644 --- a/trunk/net/ipv6/route.c +++ b/trunk/net/ipv6/route.c @@ -384,13 +384,12 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr, be destroyed. */ -int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, - void *_rtattr, struct netlink_skb_parms *req) +int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr) { int err; write_lock_bh(&rt6_lock); - err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr, req); + err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr); write_unlock_bh(&rt6_lock); return err; @@ -401,7 +400,7 @@ int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, */ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr, - struct in6_addr *saddr, struct netlink_skb_parms *req) + struct in6_addr *saddr) { int err; struct rt6_info *rt; @@ -433,7 +432,7 @@ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr, dst_hold(&rt->u.dst); - err = ip6_ins_rt(rt, NULL, NULL, req); + err = ip6_ins_rt(rt, NULL, NULL); if (err == 0) return rt; @@ -492,8 +491,7 @@ void ip6_route_input(struct sk_buff *skb) read_unlock_bh(&rt6_lock); nrt = rt6_cow(rt, &skb->nh.ipv6h->daddr, - &skb->nh.ipv6h->saddr, - &NETLINK_CB(skb)); + &skb->nh.ipv6h->saddr); dst_release(&rt->u.dst); rt = nrt; @@ -553,7 +551,7 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) dst_hold(&rt->u.dst); read_unlock_bh(&rt6_lock); - nrt = rt6_cow(rt, &fl->fl6_dst, &fl->fl6_src, NULL); + nrt = rt6_cow(rt, &fl->fl6_dst, &fl->fl6_src); dst_release(&rt->u.dst); rt = nrt; @@ -600,7 +598,7 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst) if (rt) { if (rt->rt6i_flags & RTF_CACHE) - ip6_del_rt(rt, NULL, NULL, NULL); + ip6_del_rt(rt, NULL, NULL); else dst_release(dst); } @@ -789,8 +787,7 @@ int ipv6_get_hoplimit(struct net_device *dev) * */ -int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, - void *_rtattr, struct netlink_skb_parms *req) +int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr) { int err; struct rtmsg *r; @@ -977,7 +974,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst)); rt->u.dst.dev = dev; rt->rt6i_idev = idev; - return ip6_ins_rt(rt, nlh, _rtattr, req); + return ip6_ins_rt(rt, nlh, _rtattr); out: if (dev) @@ -989,7 +986,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, return err; } -int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) +int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr) { int err; @@ -997,7 +994,7 @@ int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct rt6_reset_dflt_pointer(NULL); - err = fib6_del(rt, nlh, _rtattr, req); + err = fib6_del(rt, nlh, _rtattr); dst_release(&rt->u.dst); write_unlock_bh(&rt6_lock); @@ -1005,7 +1002,7 @@ int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct return err; } -static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req) +static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr) { struct fib6_node *fn; struct rt6_info *rt; @@ -1032,7 +1029,7 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_r dst_hold(&rt->u.dst); read_unlock_bh(&rt6_lock); - return ip6_del_rt(rt, nlh, _rtattr, req); + return ip6_del_rt(rt, nlh, _rtattr); } } read_unlock_bh(&rt6_lock); @@ -1139,11 +1136,11 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst)); - if (ip6_ins_rt(nrt, NULL, NULL, NULL)) + if (ip6_ins_rt(nrt, NULL, NULL)) goto out; if (rt->rt6i_flags&RTF_CACHE) { - ip6_del_rt(rt, NULL, NULL, NULL); + ip6_del_rt(rt, NULL, NULL); return; } @@ -1207,7 +1204,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, 2. It is gatewayed route or NONEXTHOP route. Action: clone it. */ if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { - nrt = rt6_cow(rt, daddr, saddr, NULL); + nrt = rt6_cow(rt, daddr, saddr); if (!nrt->u.dst.error) { nrt->u.dst.metrics[RTAX_MTU-1] = pmtu; if (allfrag) @@ -1235,7 +1232,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, nrt->u.dst.metrics[RTAX_MTU-1] = pmtu; if (allfrag) nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; - ip6_ins_rt(nrt, NULL, NULL, NULL); + ip6_ins_rt(nrt, NULL, NULL); } out: @@ -1308,7 +1305,7 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, rtmsg.rtmsg_ifindex = dev->ifindex; - ip6_route_add(&rtmsg, NULL, NULL, NULL); + ip6_route_add(&rtmsg, NULL, NULL); return rt6_get_dflt_router(gwaddr, dev); } @@ -1326,7 +1323,7 @@ void rt6_purge_dflt_routers(void) read_unlock_bh(&rt6_lock); - ip6_del_rt(rt, NULL, NULL, NULL); + ip6_del_rt(rt, NULL, NULL); goto restart; } @@ -1352,10 +1349,10 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg) rtnl_lock(); switch (cmd) { case SIOCADDRT: - err = ip6_route_add(&rtmsg, NULL, NULL, NULL); + err = ip6_route_add(&rtmsg, NULL, NULL); break; case SIOCDELRT: - err = ip6_route_del(&rtmsg, NULL, NULL, NULL); + err = ip6_route_del(&rtmsg, NULL, NULL); break; default: err = -EINVAL; @@ -1549,7 +1546,7 @@ int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) return -EINVAL; - return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb)); + return ip6_route_del(&rtmsg, nlh, arg); } int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) @@ -1559,7 +1556,7 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) if (inet6_rtm_to_rtmsg(r, arg, &rtmsg)) return -EINVAL; - return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb)); + return ip6_route_add(&rtmsg, nlh, arg); } struct rt6_rtnl_dump_arg @@ -1569,9 +1566,12 @@ struct rt6_rtnl_dump_arg }; static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, - struct in6_addr *dst, struct in6_addr *src, - int iif, int type, u32 pid, u32 seq, - int prefix, unsigned int flags) + struct in6_addr *dst, + struct in6_addr *src, + int iif, + int type, u32 pid, u32 seq, + struct nlmsghdr *in_nlh, int prefix, + unsigned int flags) { struct rtmsg *rtm; struct nlmsghdr *nlh; @@ -1585,6 +1585,10 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, } } + if (!pid && in_nlh) { + pid = in_nlh->nlmsg_pid; + } + nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*rtm), flags); rtm = NLMSG_DATA(nlh); rtm->rtm_family = AF_INET6; @@ -1671,7 +1675,7 @@ static int rt6_dump_route(struct rt6_info *rt, void *p_arg) return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, - prefix, NLM_F_MULTI); + NULL, prefix, NLM_F_MULTI); } static int fib6_dump_node(struct fib6_walker_t *w) @@ -1819,7 +1823,7 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) &fl.fl6_dst, &fl.fl6_src, iif, RTM_NEWROUTE, NETLINK_CB(in_skb).pid, - nlh->nlmsg_seq, 0, 0); + nlh->nlmsg_seq, nlh, 0, 0); if (err < 0) { err = -EMSGSIZE; goto out_free; @@ -1835,25 +1839,17 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) goto out; } -void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh, - struct netlink_skb_parms *req) +void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh) { struct sk_buff *skb; int size = NLMSG_SPACE(sizeof(struct rtmsg)+256); - u32 pid = current->pid; - u32 seq = 0; - if (req) - pid = req->pid; - if (nlh) - seq = nlh->nlmsg_seq; - skb = alloc_skb(size, gfp_any()); if (!skb) { netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS); return; } - if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0) < 0) { + if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0, nlh, 0, 0) < 0) { kfree_skb(skb); netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL); return;