Commit f63dc6c8 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/sparc-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 941071f4 6e27cd69
...@@ -206,6 +206,8 @@ SHA256 algorithm contributors: ...@@ -206,6 +206,8 @@ SHA256 algorithm contributors:
AES algorithm contributors: AES algorithm contributors:
Alexander Kjeldaas Alexander Kjeldaas
Herbert Valerio Riedel
Kyle McMartin
Adam J. Richter Adam J. Richter
Please send any credits updates or corrections to: Please send any credits updates or corrections to:
......
...@@ -721,6 +721,23 @@ might come in, we attempt to re-add ourselves to the poll list. ...@@ -721,6 +721,23 @@ might come in, we attempt to re-add ourselves to the poll list.
APPENDIX 3: Scheduling issues.
==============================
As seen NAPI moves processing to softirq level. Linux uses the ksoftirqd as the
general solution to schedule softirq's to run before next interrupt and by putting
them under scheduler control. Also this prevents consecutive softirq's from
monopolize the CPU. This also have the effect that the priority of ksoftirq needs
to be considered when running very CPU-intensive applications and networking to
get the proper balance of softirq/user balance. Increasing ksoftirq priority to 0
(eventually more) is reported cure problems with low network performance at high
CPU load.
Most used processes in a GIGE router:
USER PID %CPU %MEM SIZE RSS TTY STAT START TIME COMMAND
root 3 0.2 0.0 0 0 ? RWN Aug 15 602:00 (ksoftirqd_CPU0)
root 232 0.0 7.9 41400 40884 ? S Aug 15 74:12 gated
-------------------------------------------------------------------- --------------------------------------------------------------------
relevant sites: relevant sites:
......
...@@ -6,12 +6,14 @@ menu "Cryptographic options" ...@@ -6,12 +6,14 @@ menu "Cryptographic options"
config CRYPTO config CRYPTO
bool "Cryptographic API" bool "Cryptographic API"
default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m
help help
This option provides the core Cryptographic API. This option provides the core Cryptographic API.
config CRYPTO_HMAC config CRYPTO_HMAC
bool "HMAC support" bool "HMAC support"
depends on CRYPTO depends on CRYPTO
default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m
help help
HMAC: Keyed-Hashing for Message Authentication (RFC2104). HMAC: Keyed-Hashing for Message Authentication (RFC2104).
This is required for IPSec. This is required for IPSec.
...@@ -31,12 +33,14 @@ config CRYPTO_MD4 ...@@ -31,12 +33,14 @@ config CRYPTO_MD4
config CRYPTO_MD5 config CRYPTO_MD5
tristate "MD5 digest algorithm" tristate "MD5 digest algorithm"
depends on CRYPTO depends on CRYPTO
default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m
help help
MD5 message digest algorithm (RFC1321). MD5 message digest algorithm (RFC1321).
config CRYPTO_SHA1 config CRYPTO_SHA1
tristate "SHA1 digest algorithm" tristate "SHA1 digest algorithm"
depends on CRYPTO depends on CRYPTO
default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m
help help
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
...@@ -52,6 +56,7 @@ config CRYPTO_SHA256 ...@@ -52,6 +56,7 @@ config CRYPTO_SHA256
config CRYPTO_DES config CRYPTO_DES
tristate "DES and Triple DES EDE cipher algorithms" tristate "DES and Triple DES EDE cipher algorithms"
depends on CRYPTO depends on CRYPTO
default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m
help help
DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* *
* Linux developers: * Linux developers:
* Alexander Kjeldaas <astor@fast.no> * Alexander Kjeldaas <astor@fast.no>
* Herbert Valerio Riedel <hvr@hvrlab.org>
* Kyle McMartin <kyle@debian.org>
* Adam J. Richter <adam@yggdrasil.com> (conversion to 2.5 API). * Adam J. Richter <adam@yggdrasil.com> (conversion to 2.5 API).
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
......
...@@ -497,6 +497,7 @@ int kernel_read(struct file *file, unsigned long offset, ...@@ -497,6 +497,7 @@ int kernel_read(struct file *file, unsigned long offset,
static int exec_mmap(struct mm_struct *mm) static int exec_mmap(struct mm_struct *mm)
{ {
struct task_struct *tsk;
struct mm_struct * old_mm, *active_mm; struct mm_struct * old_mm, *active_mm;
/* Add it to the list of mm's */ /* Add it to the list of mm's */
...@@ -505,14 +506,17 @@ static int exec_mmap(struct mm_struct *mm) ...@@ -505,14 +506,17 @@ static int exec_mmap(struct mm_struct *mm)
mmlist_nr++; mmlist_nr++;
spin_unlock(&mmlist_lock); spin_unlock(&mmlist_lock);
task_lock(current); /* Notify parent that we're no longer interested in the old VM */
tsk = current;
old_mm = current->mm; old_mm = current->mm;
active_mm = current->active_mm; mm_release(tsk, old_mm);
current->mm = mm;
current->active_mm = mm; task_lock(tsk);
active_mm = tsk->active_mm;
tsk->mm = mm;
tsk->active_mm = mm;
activate_mm(active_mm, mm); activate_mm(active_mm, mm);
task_unlock(current); task_unlock(tsk);
mm_release();
if (old_mm) { if (old_mm) {
if (active_mm != old_mm) BUG(); if (active_mm != old_mm) BUG();
mmput(old_mm); mmput(old_mm);
......
...@@ -209,6 +209,8 @@ ev4_activate_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm) ...@@ -209,6 +209,8 @@ ev4_activate_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm)
tbiap(); tbiap();
} }
#define deactivate_mm(tsk,mm) do { } while (0)
#ifdef CONFIG_ALPHA_GENERIC #ifdef CONFIG_ALPHA_GENERIC
# define switch_mm(a,b,c,d) alpha_mv.mv_switch_mm((a),(b),(c),(d)) # define switch_mm(a,b,c,d) alpha_mv.mv_switch_mm((a),(b),(c),(d))
# define activate_mm(x,y) alpha_mv.mv_activate_mm((x),(y)) # define activate_mm(x,y) alpha_mv.mv_activate_mm((x),(y))
......
...@@ -47,6 +47,8 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, ...@@ -47,6 +47,8 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
} }
} }
#define deactivate_mm(tsk,mm) do { } while (0)
static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
{ {
cpu_switch_mm(next->pgd, next); cpu_switch_mm(next->pgd, next);
......
...@@ -7,6 +7,8 @@ extern void destroy_context(struct mm_struct *mm); ...@@ -7,6 +7,8 @@ extern void destroy_context(struct mm_struct *mm);
extern void switch_mm(struct mm_struct *prev, struct mm_struct *next, extern void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk, int cpu); struct task_struct *tsk, int cpu);
#define deactivate_mm(tsk,mm) do { } while (0)
#define activate_mm(prev,next) switch_mm((prev),(next),NULL,smp_processor_id()) #define activate_mm(prev,next) switch_mm((prev),(next),NULL,smp_processor_id())
/* current active pgd - this is similar to other processors pgd /* current active pgd - this is similar to other processors pgd
......
...@@ -62,6 +62,9 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str ...@@ -62,6 +62,9 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str
#endif #endif
} }
#define deactivate_mm(tsk, mm) \
asm("movl %0,%%fs ; movl %0,%%gs": :"r" (0))
#define activate_mm(prev, next) \ #define activate_mm(prev, next) \
switch_mm((prev),(next),NULL,smp_processor_id()) switch_mm((prev),(next),NULL,smp_processor_id())
......
...@@ -143,6 +143,8 @@ activate_context (struct mm_struct *mm) ...@@ -143,6 +143,8 @@ activate_context (struct mm_struct *mm)
} while (unlikely(context != mm->context)); } while (unlikely(context != mm->context));
} }
#define deactivate_mm(tsk,mm) do { } while (0)
/* /*
* Switch from address space PREV to address space NEXT. * Switch from address space PREV to address space NEXT.
*/ */
......
...@@ -89,6 +89,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str ...@@ -89,6 +89,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str
} }
} }
#define deactivate_mm(tsk,mm) do { } while (0)
extern inline void activate_mm(struct mm_struct *prev_mm, extern inline void activate_mm(struct mm_struct *prev_mm,
struct mm_struct *next_mm) struct mm_struct *next_mm)
{ {
......
...@@ -23,6 +23,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str ...@@ -23,6 +23,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str
{ {
} }
#define deactivate_mm(tsk,mm) do { } while (0)
extern inline void activate_mm(struct mm_struct *prev_mm, extern inline void activate_mm(struct mm_struct *prev_mm,
struct mm_struct *next_mm) struct mm_struct *next_mm)
{ {
......
...@@ -98,6 +98,8 @@ extern inline void destroy_context(struct mm_struct *mm) ...@@ -98,6 +98,8 @@ extern inline void destroy_context(struct mm_struct *mm)
/* Nothing to do. */ /* Nothing to do. */
} }
#define deactivate_mm(tsk,mm) do { } while (0)
/* /*
* After we have set current->mm to a new value, this activates * After we have set current->mm to a new value, this activates
* the context for the new mm so we see the new mappings. * the context for the new mm so we see the new mappings.
......
...@@ -111,6 +111,8 @@ extern inline void destroy_context(struct mm_struct *mm) ...@@ -111,6 +111,8 @@ extern inline void destroy_context(struct mm_struct *mm)
#endif #endif
} }
#define deactivate_mm(tsk,mm) do { } while (0)
/* /*
* After we have set current->mm to a new value, this activates * After we have set current->mm to a new value, this activates
* the context for the new mm so we see the new mappings. * the context for the new mm so we see the new mappings.
......
...@@ -52,6 +52,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str ...@@ -52,6 +52,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str
} }
} }
#define deactivate_mm(tsk,mm) do { } while (0)
static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
{ {
/* /*
......
...@@ -160,6 +160,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, ...@@ -160,6 +160,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
set_context(next->context, next->pgd); set_context(next->context, next->pgd);
} }
#define deactivate_mm(tsk,mm) do { } while (0)
/* /*
* After we have set current->mm to a new value, this activates * After we have set current->mm to a new value, this activates
* the context for the new mm so we see the new mappings. * the context for the new mm so we see the new mappings.
......
...@@ -146,6 +146,8 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, ...@@ -146,6 +146,8 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
set_bit(cpu, &next->cpu_vm_mask); set_bit(cpu, &next->cpu_vm_mask);
} }
#define deactivate_mm(tsk,mm) do { } while (0)
/* /*
* After we have set current->mm to a new value, this activates * After we have set current->mm to a new value, this activates
* the context for the new mm so we see the new mappings. * the context for the new mm so we see the new mappings.
......
...@@ -37,6 +37,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, ...@@ -37,6 +37,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
set_bit(cpu, &next->cpu_vm_mask); set_bit(cpu, &next->cpu_vm_mask);
} }
#define deactivate_mm(tsk,mm) do { } while (0)
extern inline void activate_mm(struct mm_struct *prev, extern inline void activate_mm(struct mm_struct *prev,
struct mm_struct *next) struct mm_struct *next)
{ {
......
...@@ -36,6 +36,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, ...@@ -36,6 +36,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
set_bit(cpu, &next->cpu_vm_mask); set_bit(cpu, &next->cpu_vm_mask);
} }
#define deactivate_mm(tsk,mm) do { } while (0)
extern inline void activate_mm(struct mm_struct *prev, extern inline void activate_mm(struct mm_struct *prev,
struct mm_struct *next) struct mm_struct *next)
{ {
......
...@@ -178,6 +178,8 @@ static __inline__ void switch_mm(struct mm_struct *prev, ...@@ -178,6 +178,8 @@ static __inline__ void switch_mm(struct mm_struct *prev,
} }
} }
#define deactivate_mm(tsk,mm) do { } while (0)
#define activate_mm(prev, next) \ #define activate_mm(prev, next) \
switch_mm((prev),(next),NULL,smp_processor_id()) switch_mm((prev),(next),NULL,smp_processor_id())
......
...@@ -30,6 +30,8 @@ BTFIXUPDEF_CALL(void, switch_mm, struct mm_struct *, struct mm_struct *, struct ...@@ -30,6 +30,8 @@ BTFIXUPDEF_CALL(void, switch_mm, struct mm_struct *, struct mm_struct *, struct
#define switch_mm(old_mm, mm, tsk, cpu) BTFIXUP_CALL(switch_mm)(old_mm, mm, tsk, cpu) #define switch_mm(old_mm, mm, tsk, cpu) BTFIXUP_CALL(switch_mm)(old_mm, mm, tsk, cpu)
#define deactivate_mm(tsk,mm) do { } while (0)
/* Activate a new MM instance for the current task. */ /* Activate a new MM instance for the current task. */
#define activate_mm(active_mm, mm) switch_mm((active_mm), (mm), NULL, smp_processor_id()) #define activate_mm(active_mm, mm) switch_mm((active_mm), (mm), NULL, smp_processor_id())
......
...@@ -143,6 +143,8 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str ...@@ -143,6 +143,8 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str
extern void __flush_tlb_mm(unsigned long, unsigned long); extern void __flush_tlb_mm(unsigned long, unsigned long);
#define deactivate_mm(tsk,mm) do { } while (0)
/* Activate a new MM instance for the current task. */ /* Activate a new MM instance for the current task. */
static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm) static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm)
{ {
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#define get_mmu_context(task) do ; while(0) #define get_mmu_context(task) do ; while(0)
#define activate_context(tsk) do ; while(0) #define activate_context(tsk) do ; while(0)
#define deactivate_mm(tsk,mm) do { } while (0)
static inline void activate_mm(struct mm_struct *old, struct mm_struct *new) static inline void activate_mm(struct mm_struct *old, struct mm_struct *new)
{ {
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#define destroy_context(mm) ((void)0) #define destroy_context(mm) ((void)0)
#define init_new_context(tsk,mm) 0 #define init_new_context(tsk,mm) 0
#define switch_mm(prev,next,tsk,cpu) ((void)0) #define switch_mm(prev,next,tsk,cpu) ((void)0)
#define deactivate_mm(tsk,mm) do { } while (0)
#define activate_mm(prev,next) ((void)0) #define activate_mm(prev,next) ((void)0)
#define enter_lazy_tlb(mm,tsk,cpu) ((void)0) #define enter_lazy_tlb(mm,tsk,cpu) ((void)0)
......
...@@ -62,6 +62,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, ...@@ -62,6 +62,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
#endif #endif
} }
#define deactivate_mm(tsk,mm) do { } while (0)
#define activate_mm(prev, next) \ #define activate_mm(prev, next) \
switch_mm((prev),(next),NULL,smp_processor_id()) switch_mm((prev),(next),NULL,smp_processor_id())
......
...@@ -50,6 +50,13 @@ extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb, ...@@ -50,6 +50,13 @@ extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb,
unsigned int match_len, unsigned int match_len,
char *rep_buffer, char *rep_buffer,
unsigned int rep_len); unsigned int rep_len);
extern int ip_nat_mangle_udp_packet(struct sk_buff **skb,
struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned int match_offset,
unsigned int match_len,
char *rep_buffer,
unsigned int rep_len);
extern int ip_nat_seq_adjust(struct sk_buff *skb, extern int ip_nat_seq_adjust(struct sk_buff *skb,
struct ip_conntrack *ct, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo); enum ip_conntrack_info ctinfo);
......
...@@ -566,7 +566,7 @@ static inline void mmdrop(struct mm_struct * mm) ...@@ -566,7 +566,7 @@ static inline void mmdrop(struct mm_struct * mm)
/* mmput gets rid of the mappings and all user-space */ /* mmput gets rid of the mappings and all user-space */
extern void mmput(struct mm_struct *); extern void mmput(struct mm_struct *);
/* Remove the current tasks stale references to the old mm_struct */ /* Remove the current tasks stale references to the old mm_struct */
extern void mm_release(void); extern void mm_release(struct task_struct *, struct mm_struct *);
extern int copy_thread(int, unsigned long, unsigned long, unsigned long, struct task_struct *, struct pt_regs *); extern int copy_thread(int, unsigned long, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
extern void flush_thread(void); extern void flush_thread(void);
......
...@@ -419,7 +419,7 @@ static inline void __exit_mm(struct task_struct * tsk) ...@@ -419,7 +419,7 @@ static inline void __exit_mm(struct task_struct * tsk)
{ {
struct mm_struct *mm = tsk->mm; struct mm_struct *mm = tsk->mm;
mm_release(); mm_release(tsk, mm);
if (!mm) if (!mm)
return; return;
/* /*
......
...@@ -399,17 +399,19 @@ void mmput(struct mm_struct *mm) ...@@ -399,17 +399,19 @@ void mmput(struct mm_struct *mm)
* restoring the old one. . . * restoring the old one. . .
* Eric Biederman 10 January 1998 * Eric Biederman 10 January 1998
*/ */
void mm_release(void) void mm_release(struct task_struct *tsk, struct mm_struct *mm)
{ {
struct task_struct *tsk = current;
struct completion *vfork_done = tsk->vfork_done; struct completion *vfork_done = tsk->vfork_done;
/* Get rid of any cached register state */
deactivate_mm(tsk, mm);
/* notify parent sleeping on vfork() */ /* notify parent sleeping on vfork() */
if (vfork_done) { if (vfork_done) {
tsk->vfork_done = NULL; tsk->vfork_done = NULL;
complete(vfork_done); complete(vfork_done);
} }
if (tsk->clear_child_tid) { if (tsk->clear_child_tid && atomic_read(&mm->mm_users) > 1) {
int * tidptr = tsk->clear_child_tid; int * tidptr = tsk->clear_child_tid;
tsk->clear_child_tid = NULL; tsk->clear_child_tid = NULL;
......
...@@ -967,23 +967,28 @@ int ip_conntrack_expect_related(struct ip_conntrack *related_to, ...@@ -967,23 +967,28 @@ int ip_conntrack_expect_related(struct ip_conntrack *related_to,
related_to->expecting >= related_to->helper->max_expected) { related_to->expecting >= related_to->helper->max_expected) {
struct list_head *cur_item; struct list_head *cur_item;
/* old == NULL */ /* old == NULL */
if (net_ratelimit())
printk(KERN_WARNING
"ip_conntrack: max number of expected "
"connections %i of %s reached for "
"%u.%u.%u.%u->%u.%u.%u.%u%s\n",
related_to->helper->max_expected,
related_to->helper->name,
NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
related_to->helper->flags & IP_CT_HELPER_F_REUSE_EXPECT ?
", reusing" : "");
if (!(related_to->helper->flags & if (!(related_to->helper->flags &
IP_CT_HELPER_F_REUSE_EXPECT)) { IP_CT_HELPER_F_REUSE_EXPECT)) {
WRITE_UNLOCK(&ip_conntrack_lock); WRITE_UNLOCK(&ip_conntrack_lock);
if (net_ratelimit())
printk(KERN_WARNING
"ip_conntrack: max number of expected "
"connections %i of %s reached for "
"%u.%u.%u.%u->%u.%u.%u.%u\n",
related_to->helper->max_expected,
related_to->helper->name,
NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
return -EPERM; return -EPERM;
} }
DEBUGP("ip_conntrack: max number of expected "
"connections %i of %s reached for "
"%u.%u.%u.%u->%u.%u.%u.%u, reusing\n",
related_to->helper->max_expected,
related_to->helper->name,
NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
/* choose the the oldest expectation to evict */ /* choose the the oldest expectation to evict */
list_for_each(cur_item, &related_to->sibling_list) { list_for_each(cur_item, &related_to->sibling_list) {
struct ip_conntrack_expect *cur; struct ip_conntrack_expect *cur;
......
...@@ -200,9 +200,9 @@ static int find_pattern(const char *data, size_t dlen, ...@@ -200,9 +200,9 @@ static int find_pattern(const char *data, size_t dlen,
DEBUGP("ftp: string mismatch\n"); DEBUGP("ftp: string mismatch\n");
for (i = 0; i < plen; i++) { for (i = 0; i < plen; i++) {
DEBUGFTP("ftp:char %u `%c'(%u) vs `%c'(%u)\n", DEBUGP("ftp:char %u `%c'(%u) vs `%c'(%u)\n",
i, data[i], data[i], i, data[i], data[i],
pattern[i], pattern[i]); pattern[i], pattern[i]);
} }
#endif #endif
return 0; return 0;
......
...@@ -186,13 +186,13 @@ static int tcp_packet(struct ip_conntrack *conntrack, ...@@ -186,13 +186,13 @@ static int tcp_packet(struct ip_conntrack *conntrack,
&& tcph->syn && tcph->ack) && tcph->syn && tcph->ack)
conntrack->proto.tcp.handshake_ack conntrack->proto.tcp.handshake_ack
= htonl(ntohl(tcph->seq) + 1); = htonl(ntohl(tcph->seq) + 1);
WRITE_UNLOCK(&tcp_lock);
/* If only reply is a RST, we can consider ourselves not to /* If only reply is a RST, we can consider ourselves not to
have an established connection: this is a fairly common have an established connection: this is a fairly common
problem case, so we can delete the conntrack problem case, so we can delete the conntrack
immediately. --RR */ immediately. --RR */
if (!(conntrack->status & IPS_SEEN_REPLY) && tcph->rst) { if (!(conntrack->status & IPS_SEEN_REPLY) && tcph->rst) {
WRITE_UNLOCK(&tcp_lock);
if (del_timer(&conntrack->timeout)) if (del_timer(&conntrack->timeout))
conntrack->timeout.function((unsigned long)conntrack); conntrack->timeout.function((unsigned long)conntrack);
} else { } else {
...@@ -203,6 +203,7 @@ static int tcp_packet(struct ip_conntrack *conntrack, ...@@ -203,6 +203,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
&& tcph->ack_seq == conntrack->proto.tcp.handshake_ack) && tcph->ack_seq == conntrack->proto.tcp.handshake_ack)
set_bit(IPS_ASSURED_BIT, &conntrack->status); set_bit(IPS_ASSURED_BIT, &conntrack->status);
WRITE_UNLOCK(&tcp_lock);
ip_ct_refresh(conntrack, tcp_timeouts[newconntrack]); ip_ct_refresh(conntrack, tcp_timeouts[newconntrack]);
} }
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
* - add support for SACK adjustment * - add support for SACK adjustment
* 14 Mar 2002 Harald Welte <laforge@gnumonks.org>: * 14 Mar 2002 Harald Welte <laforge@gnumonks.org>:
* - merge SACK support into newnat API * - merge SACK support into newnat API
* 16 Aug 2002 Brian J. Murrell <netfilter@interlinx.bc.ca>:
* - make ip_nat_resize_packet more generic (TCP and UDP)
* - add ip_nat_mangle_udp_packet
*/ */
#include <linux/version.h> #include <linux/version.h>
#include <linux/config.h> #include <linux/config.h>
...@@ -22,6 +25,7 @@ ...@@ -22,6 +25,7 @@
#include <net/icmp.h> #include <net/icmp.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/tcp.h> #include <net/tcp.h>
#include <net/udp.h>
#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock) #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock) #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
...@@ -51,18 +55,12 @@ ip_nat_resize_packet(struct sk_buff **skb, ...@@ -51,18 +55,12 @@ ip_nat_resize_packet(struct sk_buff **skb,
int new_size) int new_size)
{ {
struct iphdr *iph; struct iphdr *iph;
struct tcphdr *tcph;
void *data;
int dir; int dir;
struct ip_nat_seq *this_way, *other_way; struct ip_nat_seq *this_way, *other_way;
DEBUGP("ip_nat_resize_packet: old_size = %u, new_size = %u\n", DEBUGP("ip_nat_resize_packet: old_size = %u, new_size = %u\n",
(*skb)->len, new_size); (*skb)->len, new_size);
iph = (*skb)->nh.iph;
tcph = (void *)iph + iph->ihl*4;
data = (void *)tcph + tcph->doff*4;
dir = CTINFO2DIR(ctinfo); dir = CTINFO2DIR(ctinfo);
this_way = &ct->nat.info.seq[dir]; this_way = &ct->nat.info.seq[dir];
...@@ -84,37 +82,41 @@ ip_nat_resize_packet(struct sk_buff **skb, ...@@ -84,37 +82,41 @@ ip_nat_resize_packet(struct sk_buff **skb,
} }
iph = (*skb)->nh.iph; iph = (*skb)->nh.iph;
tcph = (void *)iph + iph->ihl*4; if (iph->protocol == IPPROTO_TCP) {
data = (void *)tcph + tcph->doff*4; struct tcphdr *tcph = (void *)iph + iph->ihl*4;
void *data = (void *)tcph + tcph->doff*4;
DEBUGP("ip_nat_resize_packet: Seq_offset before: ");
DUMP_OFFSET(this_way); DEBUGP("ip_nat_resize_packet: Seq_offset before: ");
DUMP_OFFSET(this_way);
LOCK_BH(&ip_nat_seqofs_lock);
LOCK_BH(&ip_nat_seqofs_lock);
/* SYN adjust. If it's uninitialized, of this is after last
* correction, record it: we don't handle more than one /* SYN adjust. If it's uninitialized, of this is after last
* adjustment in the window, but do deal with common case of a * correction, record it: we don't handle more than one
* retransmit */ * adjustment in the window, but do deal with common case of a
if (this_way->offset_before == this_way->offset_after * retransmit */
|| before(this_way->correction_pos, ntohl(tcph->seq))) { if (this_way->offset_before == this_way->offset_after
this_way->correction_pos = ntohl(tcph->seq); || before(this_way->correction_pos, ntohl(tcph->seq))) {
this_way->offset_before = this_way->offset_after; this_way->correction_pos = ntohl(tcph->seq);
this_way->offset_after = (int32_t) this_way->offset_before = this_way->offset_after;
this_way->offset_before + new_size - (*skb)->len; this_way->offset_after = (int32_t)
} this_way->offset_before + new_size -
(*skb)->len;
}
UNLOCK_BH(&ip_nat_seqofs_lock); UNLOCK_BH(&ip_nat_seqofs_lock);
DEBUGP("ip_nat_resize_packet: Seq_offset after: "); DEBUGP("ip_nat_resize_packet: Seq_offset after: ");
DUMP_OFFSET(this_way); DUMP_OFFSET(this_way);
}
return 1; return 1;
} }
/* Generic function for mangling variable-length address changes inside /* Generic function for mangling variable-length address changes inside
* NATed connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX command in FTP). * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
* command in FTP).
* *
* Takes care about all the nasty sequence number changes, checksumming, * Takes care about all the nasty sequence number changes, checksumming,
* skb enlargement, ... * skb enlargement, ...
...@@ -174,10 +176,11 @@ ip_nat_mangle_tcp_packet(struct sk_buff **skb, ...@@ -174,10 +176,11 @@ ip_nat_mangle_tcp_packet(struct sk_buff **skb,
tcph = (void *)iph + iph->ihl*4; tcph = (void *)iph + iph->ihl*4;
data = (void *)tcph + tcph->doff*4; data = (void *)tcph + tcph->doff*4;
/* move post-replacement */ if (rep_len != match_len)
memmove(data + match_offset + rep_len, /* move post-replacement */
data + match_offset + match_len, memmove(data + match_offset + rep_len,
(*skb)->tail - (data + match_offset + match_len)); data + match_offset + match_len,
(*skb)->tail - (data + match_offset + match_len));
/* insert data from buffer */ /* insert data from buffer */
memcpy(data + match_offset, rep_buffer, rep_len); memcpy(data + match_offset, rep_buffer, rep_len);
...@@ -207,6 +210,114 @@ ip_nat_mangle_tcp_packet(struct sk_buff **skb, ...@@ -207,6 +210,114 @@ ip_nat_mangle_tcp_packet(struct sk_buff **skb,
return 1; return 1;
} }
/* Generic function for mangling variable-length address changes inside
* NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
* command in the Amanda protocol)
*
* Takes care about all the nasty sequence number changes, checksumming,
* skb enlargement, ...
*
* XXX - This function could be merged with ip_nat_mangle_tcp_packet which
* should be fairly easy to do.
*/
int
ip_nat_mangle_udp_packet(struct sk_buff **skb,
struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo,
unsigned int match_offset,
unsigned int match_len,
char *rep_buffer,
unsigned int rep_len)
{
struct iphdr *iph = (*skb)->nh.iph;
struct udphdr *udph = (void *)iph + iph->ihl * 4;
unsigned char *data;
u_int32_t udplen, newlen, newudplen;
udplen = (*skb)->len - iph->ihl*4;
newudplen = udplen - match_len + rep_len;
newlen = iph->ihl*4 + newudplen;
if (newlen > 65535) {
if (net_ratelimit())
printk("ip_nat_mangle_udp_packet: nat'ed packet "
"exceeds maximum packet size\n");
return 0;
}
if ((*skb)->len != newlen) {
if (!ip_nat_resize_packet(skb, ct, ctinfo, newlen)) {
printk("resize_packet failed!!\n");
return 0;
}
}
/* Alexey says: if a hook changes _data_ ... it can break
original packet sitting in tcp queue and this is fatal */
if (skb_cloned(*skb)) {
struct sk_buff *nskb = skb_copy(*skb, GFP_ATOMIC);
if (!nskb) {
if (net_ratelimit())
printk("Out of memory cloning TCP packet\n");
return 0;
}
/* Rest of kernel will get very unhappy if we pass it
a suddenly-orphaned skbuff */
if ((*skb)->sk)
skb_set_owner_w(nskb, (*skb)->sk);
kfree_skb(*skb);
*skb = nskb;
}
/* skb may be copied !! */
iph = (*skb)->nh.iph;
udph = (void *)iph + iph->ihl*4;
data = (void *)udph + sizeof(struct udphdr);
if (rep_len != match_len)
/* move post-replacement */
memmove(data + match_offset + rep_len,
data + match_offset + match_len,
(*skb)->tail - (data + match_offset + match_len));
/* insert data from buffer */
memcpy(data + match_offset, rep_buffer, rep_len);
/* update skb info */
if (newlen > (*skb)->len) {
DEBUGP("ip_nat_mangle_udp_packet: Extending packet by "
"%u to %u bytes\n", newlen - (*skb)->len, newlen);
skb_put(*skb, newlen - (*skb)->len);
} else {
DEBUGP("ip_nat_mangle_udp_packet: Shrinking packet from "
"%u to %u bytes\n", (*skb)->len, newlen);
skb_trim(*skb, newlen);
}
/* update the length of the UDP and IP packets to the new values*/
udph->len = htons((*skb)->len - iph->ihl*4);
iph->tot_len = htons(newlen);
/* fix udp checksum if udp checksum was previously calculated */
if ((*skb)->csum != 0) {
(*skb)->csum = csum_partial((char *)udph +
sizeof(struct udphdr),
newudplen - sizeof(struct udphdr),
0);
udph->check = 0;
udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
newudplen, IPPROTO_UDP,
csum_partial((char *)udph,
sizeof(struct udphdr),
(*skb)->csum));
}
ip_send_check(iph);
return 1;
}
/* Adjust one found SACK option including checksum correction */ /* Adjust one found SACK option including checksum correction */
static void static void
......
...@@ -359,5 +359,6 @@ EXPORT_SYMBOL(ip_nat_helper_register); ...@@ -359,5 +359,6 @@ EXPORT_SYMBOL(ip_nat_helper_register);
EXPORT_SYMBOL(ip_nat_helper_unregister); EXPORT_SYMBOL(ip_nat_helper_unregister);
EXPORT_SYMBOL(ip_nat_cheat_check); EXPORT_SYMBOL(ip_nat_cheat_check);
EXPORT_SYMBOL(ip_nat_mangle_tcp_packet); EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
EXPORT_SYMBOL(ip_nat_used_tuple); EXPORT_SYMBOL(ip_nat_used_tuple);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -88,8 +88,8 @@ set_ect_tcp(struct sk_buff **pskb, struct iphdr *iph, ...@@ -88,8 +88,8 @@ set_ect_tcp(struct sk_buff **pskb, struct iphdr *iph,
} }
if (diffs[0] != *tcpflags) { if (diffs[0] != *tcpflags) {
diffs[0] = htons(diffs[0]) ^ 0xFFFF; diffs[0] = diffs[0] ^ 0xFFFF;
diffs[1] = htons(*tcpflags); diffs[1] = *tcpflags;
tcph->check = csum_fold(csum_partial((char *)diffs, tcph->check = csum_fold(csum_partial((char *)diffs,
sizeof(diffs), sizeof(diffs),
tcph->check^0xFFFF)); tcph->check^0xFFFF));
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/udp.h>
#include <linux/icmp.h>
#include <net/icmp.h> #include <net/icmp.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/tcp.h> #include <net/tcp.h>
...@@ -164,6 +166,7 @@ static void send_reset(struct sk_buff *oldskb, int local) ...@@ -164,6 +166,7 @@ static void send_reset(struct sk_buff *oldskb, int local)
static void send_unreach(struct sk_buff *skb_in, int code) static void send_unreach(struct sk_buff *skb_in, int code)
{ {
struct iphdr *iph; struct iphdr *iph;
struct udphdr *udph;
struct icmphdr *icmph; struct icmphdr *icmph;
struct sk_buff *nskb; struct sk_buff *nskb;
u32 saddr; u32 saddr;
...@@ -193,6 +196,19 @@ static void send_unreach(struct sk_buff *skb_in, int code) ...@@ -193,6 +196,19 @@ static void send_unreach(struct sk_buff *skb_in, int code)
if (iph->frag_off&htons(IP_OFFSET)) if (iph->frag_off&htons(IP_OFFSET))
return; return;
/* if UDP checksum is set, verify it's correct */
if (iph->protocol == IPPROTO_UDP
&& skb_in->tail-(u8*)iph >= sizeof(struct udphdr)) {
int datalen = skb_in->len - (iph->ihl<<2);
udph = (struct udphdr *)((char *)iph + (iph->ihl<<2));
if (udph->check
&& csum_tcpudp_magic(iph->saddr, iph->daddr,
datalen, IPPROTO_UDP,
csum_partial((char *)udph, datalen,
0)) != 0)
return;
}
/* If we send an ICMP error to an ICMP error a mess would result.. */ /* If we send an ICMP error to an ICMP error a mess would result.. */
if (iph->protocol == IPPROTO_ICMP if (iph->protocol == IPPROTO_ICMP
&& skb_in->tail-(u8*)iph >= sizeof(struct icmphdr)) { && skb_in->tail-(u8*)iph >= sizeof(struct icmphdr)) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* module loadtime -HW * module loadtime -HW
* 2002/07/07 remove broken nflog_rcv() function -HW * 2002/07/07 remove broken nflog_rcv() function -HW
* 2002/08/29 fix shifted/unshifted nlgroup bug -HW * 2002/08/29 fix shifted/unshifted nlgroup bug -HW
* 2002/10/30 fix uninitialized mac_len field - <Anders K. Pedersen>
* *
* Released under the terms of the GPL * Released under the terms of the GPL
* *
...@@ -31,7 +32,7 @@ ...@@ -31,7 +32,7 @@
* Specify, after how many clock ticks (intel: 100 per second) the queue * Specify, after how many clock ticks (intel: 100 per second) the queue
* should be flushed even if it is not full yet. * should be flushed even if it is not full yet.
* *
* ipt_ULOG.c,v 1.21 2002/08/29 10:54:34 laforge Exp * ipt_ULOG.c,v 1.22 2002/10/30 09:07:31 laforge Exp
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -224,7 +225,8 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb, ...@@ -224,7 +225,8 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
&& in->hard_header_len <= ULOG_MAC_LEN) { && in->hard_header_len <= ULOG_MAC_LEN) {
memcpy(pm->mac, (*pskb)->mac.raw, in->hard_header_len); memcpy(pm->mac, (*pskb)->mac.raw, in->hard_header_len);
pm->mac_len = in->hard_header_len; pm->mac_len = in->hard_header_len;
} } else
pm->mac_len = 0;
if (in) if (in)
strncpy(pm->indev_name, in->name, sizeof(pm->indev_name)); strncpy(pm->indev_name, in->name, sizeof(pm->indev_name));
......
...@@ -78,7 +78,7 @@ checkentry(const char *tablename, ...@@ -78,7 +78,7 @@ checkentry(const char *tablename,
/* Must specify proto == TCP/UDP, no unknown flags or bad count */ /* Must specify proto == TCP/UDP, no unknown flags or bad count */
return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP) return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
&& !(ip->flags & IPT_INV_PROTO) && !(ip->invflags & IPT_INV_PROTO)
&& matchsize == IPT_ALIGN(sizeof(struct ipt_multiport)) && matchsize == IPT_ALIGN(sizeof(struct ipt_multiport))
&& (multiinfo->flags == IPT_MULTIPORT_SOURCE && (multiinfo->flags == IPT_MULTIPORT_SOURCE
|| multiinfo->flags == IPT_MULTIPORT_DESTINATION || multiinfo->flags == IPT_MULTIPORT_DESTINATION
......
...@@ -310,6 +310,7 @@ struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx) ...@@ -310,6 +310,7 @@ struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx)
*/ */
void xfrm_probe_algs(void) void xfrm_probe_algs(void)
{ {
#ifdef CONFIG_CRYPTO
int i, status; int i, status;
BUG_ON(in_softirq()); BUG_ON(in_softirq());
...@@ -325,6 +326,7 @@ void xfrm_probe_algs(void) ...@@ -325,6 +326,7 @@ void xfrm_probe_algs(void)
if (ealg_list[i].available != status) if (ealg_list[i].available != status)
ealg_list[i].available = status; ealg_list[i].available = status;
} }
#endif
} }
int xfrm_count_auth_supported(void) int xfrm_count_auth_supported(void)
......
...@@ -684,7 +684,7 @@ static int __init init_ipv6_mibs(void) ...@@ -684,7 +684,7 @@ static int __init init_ipv6_mibs(void)
} }
static void __exit cleanup_ipv6_mibs(void) static void cleanup_ipv6_mibs(void)
{ {
kfree_percpu(ipv6_statistics[0]); kfree_percpu(ipv6_statistics[0]);
kfree_percpu(ipv6_statistics[1]); kfree_percpu(ipv6_statistics[1]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment