Commit 9cb52295 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linux-dj.bkbits.net/agpgart

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 4823db34 02538d82
...@@ -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:
......
...@@ -126,10 +126,9 @@ VM_MASK = 0x00020000 ...@@ -126,10 +126,9 @@ VM_MASK = 0x00020000
addl $4, %esp; \ addl $4, %esp; \
1: iret; \ 1: iret; \
.section .fixup,"ax"; \ .section .fixup,"ax"; \
2: pushl %ss; \ 2: movl $(__USER_DS), %edx; \
popl %ds; \ movl %edx, %ds; \
pushl %ss; \ movl %edx, %es; \
popl %es; \
pushl $11; \ pushl $11; \
call do_exit; \ call do_exit; \
.previous; \ .previous; \
...@@ -225,7 +224,7 @@ need_resched: ...@@ -225,7 +224,7 @@ need_resched:
movl TI_FLAGS(%ebp), %ecx # need_resched set ? movl TI_FLAGS(%ebp), %ecx # need_resched set ?
testb $_TIF_NEED_RESCHED, %cl testb $_TIF_NEED_RESCHED, %cl
jz restore_all jz restore_all
testl $IF_MASK,EFLAGS(%esp) # interrupts off (execption path) ? testl $IF_MASK,EFLAGS(%esp) # interrupts off (exception path) ?
jz restore_all jz restore_all
movl $PREEMPT_ACTIVE,TI_PRE_COUNT(%ebp) movl $PREEMPT_ACTIVE,TI_PRE_COUNT(%ebp)
sti sti
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -342,7 +343,7 @@ void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("ke ...@@ -342,7 +343,7 @@ void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) __asm__ ("ke
void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn) void kernel_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
{ {
unsigned long g2 = regs->u_regs [UREG_G2]; unsigned long g2 = regs->u_regs [UREG_G2];
unsigned long fixup = search_exception_table (regs->pc, &g2); unsigned long fixup = search_extables_range(regs->pc, &g2);
if (!fixup) { if (!fixup) {
unsigned long address = compute_effective_address(regs, insn); unsigned long address = compute_effective_address(regs, insn);
......
...@@ -6,13 +6,11 @@ ...@@ -6,13 +6,11 @@
#include <linux/module.h> #include <linux/module.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
extern const struct exception_table_entry __start___ex_table[]; /* Caller knows they are in a range if ret->fixup == 0 */
extern const struct exception_table_entry __stop___ex_table[]; const struct exception_table_entry *
search_extable(const struct exception_table_entry *start,
static unsigned long const struct exception_table_entry *last,
search_one_table(const struct exception_table_entry *start, unsigned long value)
const struct exception_table_entry *end,
unsigned long value, unsigned long *g2)
{ {
const struct exception_table_entry *walk; const struct exception_table_entry *walk;
...@@ -30,7 +28,7 @@ search_one_table(const struct exception_table_entry *start, ...@@ -30,7 +28,7 @@ search_one_table(const struct exception_table_entry *start,
*/ */
/* 1. Try to find an exact match. */ /* 1. Try to find an exact match. */
for (walk = start; walk <= end; walk++) { for (walk = start; walk <= last; walk++) {
if (walk->fixup == 0) { if (walk->fixup == 0) {
/* A range entry, skip both parts. */ /* A range entry, skip both parts. */
walk++; walk++;
...@@ -38,55 +36,37 @@ search_one_table(const struct exception_table_entry *start, ...@@ -38,55 +36,37 @@ search_one_table(const struct exception_table_entry *start,
} }
if (walk->insn == value) if (walk->insn == value)
return walk->fixup; return walk;
} }
/* 2. Try to find a range match. */ /* 2. Try to find a range match. */
for (walk = start; walk <= (end - 1); walk++) { for (walk = start; walk <= (last - 1); walk++) {
if (walk->fixup) if (walk->fixup)
continue; continue;
if (walk[0].insn <= value && if (walk[0].insn <= value && walk[1].insn > value)
walk[1].insn > value) { return walk;
*g2 = (value - walk[0].insn) / 4;
return walk[1].fixup;
}
walk++; walk++;
} }
return 0; return NULL;
} }
extern spinlock_t modlist_lock; /* Special extable search, which handles ranges. Returns fixup */
unsigned long search_extables_range(unsigned long addr, unsigned long *g2)
unsigned long
search_exception_table(unsigned long addr, unsigned long *g2)
{ {
unsigned long ret = 0; const struct exception_table_entry *entry;
#ifndef CONFIG_MODULES entry = search_exception_tables(addr);
/* There is only the kernel to search. */ if (!entry)
ret = search_one_table(__start___ex_table, return 0;
__stop___ex_table-1, addr, g2);
return ret;
#else
unsigned long flags;
struct list_head *i;
/* The kernel is the last "module" -- no need to treat it special. */ /* Inside range? Fix g2 and return correct fixup */
spin_lock_irqsave(&modlist_lock, flags); if (!entry->fixup) {
list_for_each(i, &extables) { *g2 = (addr - entry->insn) / 4;
struct exception_table *ex = return (entry + 1)->fixup;
list_entry(i, struct exception_table, list);
if (ex->num_entries == 0)
continue;
ret = search_one_table(ex->entry,
ex->entry + ex->num_entries - 1,
addr, g2);
if (ret)
break;
} }
spin_unlock_irqrestore(&modlist_lock, flags);
return ret; return entry->fixup;
#endif
} }
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/segment.h> #include <asm/segment.h>
...@@ -161,7 +162,7 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, ...@@ -161,7 +162,7 @@ asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc,
unsigned int insn; unsigned int insn;
int i; int i;
i = search_exception_table(ret_pc, &g2); i = search_extables_range(ret_pc, &g2);
switch (i) { switch (i) {
case 3: case 3:
/* load & store will be handled by fixup */ /* load & store will be handled by fixup */
...@@ -316,7 +317,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, ...@@ -316,7 +317,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
/* Is this in ex_table? */ /* Is this in ex_table? */
no_context: no_context:
g2 = regs->u_regs[UREG_G2]; g2 = regs->u_regs[UREG_G2];
if (!from_user && (fixup = search_exception_table (regs->pc, &g2))) { if (!from_user && (fixup = search_extables_range(regs->pc, &g2))) {
if (fixup > 10) { /* Values below are reserved for other things */ if (fixup > 10) { /* Values below are reserved for other things */
extern const unsigned __memset_start[]; extern const unsigned __memset_start[];
extern const unsigned __memset_end[]; extern const unsigned __memset_end[];
......
...@@ -12,10 +12,16 @@ CONFIG_EXPERIMENTAL=y ...@@ -12,10 +12,16 @@ CONFIG_EXPERIMENTAL=y
# #
# General setup # General setup
# #
CONFIG_NET=y
CONFIG_SYSVIPC=y CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y CONFIG_SYSCTL=y
# CONFIG_LOG_BUF_SHIFT_17 is not set
# CONFIG_LOG_BUF_SHIFT_16 is not set
CONFIG_LOG_BUF_SHIFT_15=y
# CONFIG_LOG_BUF_SHIFT_14 is not set
# CONFIG_LOG_BUF_SHIFT_13 is not set
# CONFIG_LOG_BUF_SHIFT_12 is not set
CONFIG_LOG_BUF_SHIFT=15
# #
# Loadable module support # Loadable module support
...@@ -23,6 +29,7 @@ CONFIG_SYSCTL=y ...@@ -23,6 +29,7 @@ CONFIG_SYSCTL=y
CONFIG_MODULES=y CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_OBSOLETE_MODPARM=y
CONFIG_KMOD=y CONFIG_KMOD=y
# #
...@@ -47,6 +54,7 @@ CONFIG_SUN_AUXIO=y ...@@ -47,6 +54,7 @@ CONFIG_SUN_AUXIO=y
CONFIG_SUN_IO=y CONFIG_SUN_IO=y
CONFIG_PCI=y CONFIG_PCI=y
CONFIG_RTC=y CONFIG_RTC=y
# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_NAMES is not set # CONFIG_PCI_NAMES is not set
CONFIG_SUN_OPENPROMFS=m CONFIG_SUN_OPENPROMFS=m
CONFIG_KCORE_ELF=y CONFIG_KCORE_ELF=y
...@@ -76,45 +84,17 @@ CONFIG_WATCHDOG_CP1XXX=m ...@@ -76,45 +84,17 @@ CONFIG_WATCHDOG_CP1XXX=m
CONFIG_WATCHDOG_RIO=m CONFIG_WATCHDOG_RIO=m
# #
# Console drivers # Graphics support
# #
CONFIG_PROM_CONSOLE=y # CONFIG_FB is not set
# #
# Frame-buffer support # Console display driver support
# #
CONFIG_FB=y # CONFIG_VGA_CONSOLE is not set
# CONFIG_MDA_CONSOLE is not set
CONFIG_PROM_CONSOLE=y
CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE=y
# CONFIG_FB_CLGEN is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
CONFIG_FB_ATY=y
CONFIG_FB_ATY_GX=y
# CONFIG_FB_BWTWO is not set
# CONFIG_FB_CGTHREE is not set
CONFIG_FB_CGSIX=y
# CONFIG_FB_RIVA is not set
# CONFIG_FB_MATROX is not set
CONFIG_FB_ATY_CT=y
# CONFIG_FB_RADEON is not set
# CONFIG_FB_ATY128 is not set
# CONFIG_FB_SIS is not set
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_TRIDENT is not set
# CONFIG_FB_PM3 is not set
CONFIG_FB_SBUS=y
CONFIG_FB_CREATOR=y
# CONFIG_FB_LEO is not set
CONFIG_FB_PCI=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set
CONFIG_FBCON_CFB24=y
CONFIG_FBCON_ACCEL=y
CONFIG_FBCON_FONTWIDTH8_ONLY=y
CONFIG_FONT_SUN8x16=y
# CONFIG_FBCON_FONTS is not set
# #
# Serial drivers # Serial drivers
...@@ -260,7 +240,11 @@ CONFIG_SCSI_QLOGICPTI=m ...@@ -260,7 +240,11 @@ CONFIG_SCSI_QLOGICPTI=m
CONFIG_SCSI_AIC7XXX=m CONFIG_SCSI_AIC7XXX=m
CONFIG_AIC7XXX_CMDS_PER_DEVICE=253 CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
CONFIG_AIC7XXX_RESET_DELAY_MS=5000 CONFIG_AIC7XXX_RESET_DELAY_MS=5000
# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
CONFIG_AIC7XXX_DEBUG_MASK=0
# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
CONFIG_SCSI_AIC7XXX_OLD=m CONFIG_SCSI_AIC7XXX_OLD=m
CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y
CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=8 CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=8
...@@ -305,6 +289,11 @@ CONFIG_FUSION_LAN=m ...@@ -305,6 +289,11 @@ CONFIG_FUSION_LAN=m
# #
# CONFIG_IEEE1394 is not set # CONFIG_IEEE1394 is not set
#
# Networking support
#
CONFIG_NET=y
# #
# Networking options # Networking options
# #
...@@ -387,10 +376,6 @@ CONFIG_NET_CLS_POLICE=y ...@@ -387,10 +376,6 @@ CONFIG_NET_CLS_POLICE=y
# Network testing # Network testing
# #
CONFIG_NET_PKTGEN=m CONFIG_NET_PKTGEN=m
#
# Network device support
#
CONFIG_NETDEVICES=y CONFIG_NETDEVICES=y
# #
...@@ -414,8 +399,6 @@ CONFIG_SUNQE=m ...@@ -414,8 +399,6 @@ CONFIG_SUNQE=m
CONFIG_SUNGEM=y CONFIG_SUNGEM=y
CONFIG_NET_VENDOR_3COM=y CONFIG_NET_VENDOR_3COM=y
CONFIG_VORTEX=m CONFIG_VORTEX=m
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
# #
# Tulip family network device support # Tulip family network device support
...@@ -431,6 +414,7 @@ CONFIG_WINBOND_840=m ...@@ -431,6 +414,7 @@ CONFIG_WINBOND_840=m
# CONFIG_HP100 is not set # CONFIG_HP100 is not set
CONFIG_NET_PCI=y CONFIG_NET_PCI=y
CONFIG_PCNET32=m CONFIG_PCNET32=m
# CONFIG_AMD8111_ETH is not set
CONFIG_ADAPTEC_STARFIRE=m CONFIG_ADAPTEC_STARFIRE=m
CONFIG_B44=m CONFIG_B44=m
CONFIG_DGRS=m CONFIG_DGRS=m
...@@ -452,7 +436,6 @@ CONFIG_SUNDANCE_MMIO=y ...@@ -452,7 +436,6 @@ CONFIG_SUNDANCE_MMIO=y
# CONFIG_TLAN is not set # CONFIG_TLAN is not set
CONFIG_VIA_RHINE=m CONFIG_VIA_RHINE=m
# CONFIG_VIA_RHINE_MMIO is not set # CONFIG_VIA_RHINE_MMIO is not set
# CONFIG_NET_POCKET is not set
# #
# Ethernet (1000 Mbit) # Ethernet (1000 Mbit)
...@@ -819,7 +802,10 @@ CONFIG_USB_UHCI_HCD=m ...@@ -819,7 +802,10 @@ CONFIG_USB_UHCI_HCD=m
# USB Device Class drivers # USB Device Class drivers
# #
# CONFIG_USB_AUDIO is not set # CONFIG_USB_AUDIO is not set
CONFIG_USB_BLUETOOTH_TTY=m
#
# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
#
# CONFIG_USB_MIDI is not set # CONFIG_USB_MIDI is not set
CONFIG_USB_ACM=m CONFIG_USB_ACM=m
CONFIG_USB_PRINTER=m CONFIG_USB_PRINTER=m
...@@ -910,6 +896,7 @@ CONFIG_USB_SERIAL_KEYSPAN=m ...@@ -910,6 +896,7 @@ CONFIG_USB_SERIAL_KEYSPAN=m
# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set # CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
CONFIG_USB_SERIAL_KLSI=m CONFIG_USB_SERIAL_KLSI=m
# CONFIG_USB_SERIAL_KOBIL_SCT is not set
CONFIG_USB_SERIAL_MCT_U232=m CONFIG_USB_SERIAL_MCT_U232=m
CONFIG_USB_SERIAL_PL2303=m CONFIG_USB_SERIAL_PL2303=m
# CONFIG_USB_SERIAL_SAFE is not set # CONFIG_USB_SERIAL_SAFE is not set
...@@ -992,6 +979,7 @@ CONFIG_CRYPTO_DES=y ...@@ -992,6 +979,7 @@ CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_AES=m
# CONFIG_CRYPTO_TEST is not set # CONFIG_CRYPTO_TEST is not set
# #
......
...@@ -1729,8 +1729,7 @@ asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_times ...@@ -1729,8 +1729,7 @@ asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, struct compat_times
set_fs (KERNEL_DS); set_fs (KERNEL_DS);
ret = sys_sched_rr_get_interval(pid, &t); ret = sys_sched_rr_get_interval(pid, &t);
set_fs (old_fs); set_fs (old_fs);
if (put_user (t.tv_sec, &interval->tv_sec) || if (put_compat_timespec(&t, interval))
__put_user (t.tv_nsec, &interval->tv_nsec))
return -EFAULT; return -EFAULT;
return ret; return ret;
} }
...@@ -1861,8 +1860,7 @@ sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo, ...@@ -1861,8 +1860,7 @@ sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
signotset(&these); signotset(&these);
if (uts) { if (uts) {
if (get_user (ts.tv_sec, &uts->tv_sec) || if (get_compat_timespec(&ts, uts))
get_user (ts.tv_nsec, &uts->tv_nsec))
return -EINVAL; return -EINVAL;
if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0 if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
|| ts.tv_sec < 0) || ts.tv_sec < 0)
......
...@@ -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
......
...@@ -72,6 +72,7 @@ ...@@ -72,6 +72,7 @@
#endif #endif
#include <linux/module.h> #include <linux/module.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/io.h>
#ifndef KERNEL_VERSION #ifndef KERNEL_VERSION
#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) #define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
......
...@@ -924,7 +924,7 @@ sunzilog_set_termios(struct uart_port *port, struct termios *termios, ...@@ -924,7 +924,7 @@ sunzilog_set_termios(struct uart_port *port, struct termios *termios,
unsigned long flags; unsigned long flags;
int baud, brg; int baud, brg;
baud = uart_get_baud_rate(port, termios); baud = uart_get_baud_rate(port, termios, old, 1200, 76800);
spin_lock_irqsave(&up->port.lock, flags); spin_lock_irqsave(&up->port.lock, flags);
......
...@@ -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())
......
...@@ -78,7 +78,7 @@ struct exception_table_entry ...@@ -78,7 +78,7 @@ struct exception_table_entry
}; };
/* Returns 0 if exception not found and fixup otherwise. */ /* Returns 0 if exception not found and fixup otherwise. */
extern unsigned long search_exception_table(unsigned long, unsigned long *); extern unsigned long search_extables_range(unsigned long addr, unsigned long *g2);
extern void __ret_efault(void); extern void __ret_efault(void);
......
...@@ -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;
......
...@@ -46,7 +46,7 @@ const char *kallsyms_lookup(unsigned long addr, ...@@ -46,7 +46,7 @@ const char *kallsyms_lookup(unsigned long addr,
} }
/* Grab name */ /* Grab name */
for (i = 0; i < best; i++) { for (i = 0; i <= best; i++) {
unsigned prefix = *name++; unsigned prefix = *name++;
strncpy(namebuf + prefix, name, 127 - prefix); strncpy(namebuf + prefix, name, 127 - prefix);
name += strlen(name) + 1; name += strlen(name) + 1;
......
...@@ -2108,7 +2108,7 @@ static int migration_thread(void * data) ...@@ -2108,7 +2108,7 @@ static int migration_thread(void * data)
spin_unlock_irqrestore(&rq->lock, flags); spin_unlock_irqrestore(&rq->lock, flags);
p = req->task; p = req->task;
cpu_dest = __ffs(p->cpus_allowed); cpu_dest = __ffs(p->cpus_allowed & cpu_online_map);
rq_dest = cpu_rq(cpu_dest); rq_dest = cpu_rq(cpu_dest);
repeat: repeat:
cpu_src = task_cpu(p); cpu_src = task_cpu(p);
......
...@@ -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