Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
6ccc3e25
Commit
6ccc3e25
authored
Nov 13, 2002
by
Andy Grover
Browse files
Options
Browse Files
Download
Plain Diff
Merge groveronline.com:/root/bk/linux-2.5
into groveronline.com:/root/bk/linux-acpi
parents
8270dc79
2c0889e4
Changes
36
Hide whitespace changes
Inline
Side-by-side
Showing
36 changed files
with
1606 additions
and
295 deletions
+1606
-295
arch/i386/kernel/entry.S
arch/i386/kernel/entry.S
+24
-0
arch/sparc/kernel/module.c
arch/sparc/kernel/module.c
+2
-2
arch/sparc64/kernel/module.c
arch/sparc64/kernel/module.c
+114
-4
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/sys_sparc32.c
+6
-12
crypto/api.c
crypto/api.c
+1
-2
include/linux/in.h
include/linux/in.h
+1
-0
include/linux/module.h
include/linux/module.h
+9
-0
include/linux/udp.h
include/linux/udp.h
+0
-3
include/linux/xfrm.h
include/linux/xfrm.h
+50
-3
include/net/ip_fib.h
include/net/ip_fib.h
+0
-3
include/net/udp.h
include/net/udp.h
+0
-2
include/net/xfrm.h
include/net/xfrm.h
+3
-20
kernel/exec_domain.c
kernel/exec_domain.c
+2
-7
net/802/tr.c
net/802/tr.c
+1
-1
net/atm/mpc.c
net/atm/mpc.c
+1
-1
net/core/neighbour.c
net/core/neighbour.c
+1
-1
net/ipv4/Kconfig
net/ipv4/Kconfig
+8
-0
net/ipv4/Makefile
net/ipv4/Makefile
+1
-0
net/ipv4/af_inet.c
net/ipv4/af_inet.c
+10
-6
net/ipv4/ah.c
net/ipv4/ah.c
+1
-1
net/ipv4/esp.c
net/ipv4/esp.c
+15
-10
net/ipv4/fib_hash.c
net/ipv4/fib_hash.c
+0
-12
net/ipv4/ip_sockglue.c
net/ipv4/ip_sockglue.c
+1
-0
net/ipv4/netfilter/ip_nat_helper.c
net/ipv4/netfilter/ip_nat_helper.c
+3
-7
net/ipv4/proc.c
net/ipv4/proc.c
+113
-97
net/ipv4/raw.c
net/ipv4/raw.c
+156
-59
net/ipv4/udp.c
net/ipv4/udp.c
+1
-13
net/ipv4/xfrm_input.c
net/ipv4/xfrm_input.c
+1
-1
net/ipv4/xfrm_state.c
net/ipv4/xfrm_state.c
+5
-4
net/ipv4/xfrm_user.c
net/ipv4/xfrm_user.c
+1045
-0
net/ipv6/mcast.c
net/ipv6/mcast.c
+1
-0
net/irda/af_irda.c
net/irda/af_irda.c
+1
-0
net/key/af_key.c
net/key/af_key.c
+16
-7
net/llc/llc_main.c
net/llc/llc_main.c
+5
-0
net/sched/sch_sfq.c
net/sched/sch_sfq.c
+1
-1
net/socket.c
net/socket.c
+7
-16
No files found.
arch/i386/kernel/entry.S
View file @
6ccc3e25
...
...
@@ -66,7 +66,9 @@ OLDESP = 0x34
OLDSS
=
0x38
CF_MASK
=
0x00000001
TF_MASK
=
0x00000100
IF_MASK
=
0x00000200
DF_MASK
=
0x00000400
NT_MASK
=
0x00004000
VM_MASK
=
0x00020000
...
...
@@ -134,6 +136,17 @@ ENTRY(lcall7)
movl
%
eax
,
EFLAGS
(%
esp
)
#
movl
%
edx
,
EIP
(%
esp
)
#
Now
we
move
them
to
their
"normal"
places
movl
%
ecx
,
CS
(%
esp
)
#
#
#
Call
gates
don
't clear TF and NT in eflags like
#
traps
do
,
so
we
need
to
do
it
ourselves
.
#
%
eax
already
contains
eflags
(
but
it
may
have
#
DF
set
,
clear
that
also
)
#
andl
$~
(
DF_MASK
| TF_MASK |
NT_MASK
),%
eax
pushl
%
eax
popfl
movl
%
esp
,
%
ebx
pushl
%
ebx
andl
$
-
8192
,
%
ebx
#
GET_THREAD_INFO
...
...
@@ -156,6 +169,17 @@ ENTRY(lcall27)
movl
%
eax
,
EFLAGS
(%
esp
)
#
movl
%
edx
,
EIP
(%
esp
)
#
Now
we
move
them
to
their
"normal"
places
movl
%
ecx
,
CS
(%
esp
)
#
#
#
Call
gates
don
't clear TF and NT in eflags like
#
traps
do
,
so
we
need
to
do
it
ourselves
.
#
%
eax
already
contains
eflags
(
but
it
may
have
#
DF
set
,
clear
that
also
)
#
andl
$~
(
DF_MASK
| TF_MASK |
NT_MASK
),%
eax
pushl
%
eax
popfl
movl
%
esp
,
%
ebx
pushl
%
ebx
andl
$
-
8192
,
%
ebx
#
GET_THREAD_INFO
...
...
arch/sparc/kernel/module.c
View file @
6ccc3e25
...
...
@@ -90,7 +90,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
me
->
name
,
strtab
+
sym
->
st_name
);
return
-
ENOENT
;
}
v
+=
rel
->
r_addend
;
v
+=
rel
[
i
].
r_addend
;
switch
(
ELF32_R_TYPE
(
rel
[
i
].
r_info
))
{
case
R_SPARC_32
:
...
...
@@ -126,7 +126,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs,
me
->
name
,
(
int
)
(
ELF32_R_TYPE
(
rel
[
i
].
r_info
)
&
0xff
));
return
-
ENOEXEC
;
}
}
;
}
return
0
;
}
...
...
arch/sparc64/kernel/module.c
View file @
6ccc3e25
...
...
@@ -10,6 +10,113 @@
#include <linux/vmalloc.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
static
struct
vm_struct
*
modvmlist
=
NULL
;
static
void
module_unmap
(
void
*
addr
)
{
struct
vm_struct
**
p
,
*
tmp
;
int
i
;
if
(
!
addr
)
return
;
if
((
PAGE_SIZE
-
1
)
&
(
unsigned
long
)
addr
)
{
printk
(
"Trying to unmap module with bad address (%p)
\n
"
,
addr
);
return
;
}
for
(
p
=
&
modvmlist
;
(
tmp
=
*
p
)
;
p
=
&
tmp
->
next
)
{
if
(
tmp
->
addr
==
addr
)
{
*
p
=
tmp
->
next
;
goto
found
;
}
}
printk
(
"Trying to unmap nonexistent module vm area (%p)
\n
"
,
addr
);
return
;
found:
unmap_vm_area
(
tmp
);
for
(
i
=
0
;
i
<
tmp
->
nr_pages
;
i
++
)
{
if
(
unlikely
(
!
tmp
->
pages
[
i
]))
BUG
();
__free_page
(
tmp
->
pages
[
i
]);
}
kfree
(
tmp
->
pages
);
kfree
(
tmp
);
}
static
void
*
module_map
(
unsigned
long
size
)
{
struct
vm_struct
**
p
,
*
tmp
,
*
area
;
struct
page
**
pages
;
void
*
addr
;
unsigned
int
nr_pages
,
array_size
,
i
;
size
=
PAGE_ALIGN
(
size
);
if
(
!
size
||
size
>
MODULES_LEN
)
return
NULL
;
addr
=
(
void
*
)
MODULES_VADDR
;
for
(
p
=
&
modvmlist
;
(
tmp
=
*
p
)
;
p
=
&
tmp
->
next
)
{
if
(
size
+
(
unsigned
long
)
addr
<
(
unsigned
long
)
tmp
->
addr
)
break
;
addr
=
(
void
*
)
(
tmp
->
size
+
(
unsigned
long
)
tmp
->
addr
);
}
if
((
unsigned
long
)
addr
+
size
>=
MODULES_END
)
return
NULL
;
area
=
(
struct
vm_struct
*
)
kmalloc
(
sizeof
(
*
area
),
GFP_KERNEL
);
if
(
!
area
)
return
NULL
;
area
->
size
=
size
+
PAGE_SIZE
;
area
->
addr
=
addr
;
area
->
next
=
*
p
;
area
->
pages
=
NULL
;
area
->
nr_pages
=
0
;
area
->
phys_addr
=
0
;
*
p
=
area
;
nr_pages
=
size
>>
PAGE_SHIFT
;
array_size
=
(
nr_pages
*
sizeof
(
struct
page
*
));
area
->
nr_pages
=
nr_pages
;
area
->
pages
=
pages
=
kmalloc
(
array_size
,
GFP_KERNEL
);
if
(
!
area
->
pages
)
goto
fail
;
memset
(
area
->
pages
,
0
,
array_size
);
for
(
i
=
0
;
i
<
area
->
nr_pages
;
i
++
)
{
area
->
pages
[
i
]
=
alloc_page
(
GFP_KERNEL
);
if
(
unlikely
(
!
area
->
pages
[
i
]))
goto
fail
;
}
if
(
map_vm_area
(
area
,
PAGE_KERNEL
,
&
pages
))
{
unmap_vm_area
(
area
);
goto
fail
;
}
return
area
->
addr
;
fail:
if
(
area
->
pages
)
{
for
(
i
=
0
;
i
<
area
->
nr_pages
;
i
++
)
{
if
(
area
->
pages
[
i
])
__free_page
(
area
->
pages
[
i
]);
}
kfree
(
area
->
pages
);
}
kfree
(
area
);
return
NULL
;
}
static
void
*
alloc_and_zero
(
unsigned
long
size
)
{
...
...
@@ -19,7 +126,7 @@ static void *alloc_and_zero(unsigned long size)
if
(
size
==
0
)
return
NULL
;
ret
=
vmalloc
(
size
);
ret
=
module_map
(
size
);
if
(
!
ret
)
ret
=
ERR_PTR
(
-
ENOMEM
);
else
...
...
@@ -31,7 +138,7 @@ static void *alloc_and_zero(unsigned long size)
/* Free memory returned from module_core_alloc/module_init_alloc */
void
module_free
(
struct
module
*
mod
,
void
*
module_region
)
{
vfree
(
module_region
);
module_unmap
(
module_region
);
/* FIXME: If module_region == mod->init_region, trim exception
table entries. */
}
...
...
@@ -82,6 +189,9 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
location
=
(
u8
*
)
sechdrs
[
sechdrs
[
relsec
].
sh_info
].
sh_offset
+
rel
[
i
].
r_offset
;
loc32
=
(
u32
*
)
location
;
BUG_ON
(((
u64
)
location
>>
(
u64
)
32
)
!=
(
u64
)
0
);
/* This is the symbol it is referring to */
sym
=
(
Elf64_Sym
*
)
sechdrs
[
symindex
].
sh_offset
+
ELF64_R_SYM
(
rel
[
i
].
r_info
);
...
...
@@ -90,7 +200,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
me
->
name
,
strtab
+
sym
->
st_name
);
return
-
ENOENT
;
}
v
+=
rel
->
r_addend
;
v
+=
rel
[
i
].
r_addend
;
switch
(
ELF64_R_TYPE
(
rel
[
i
].
r_info
)
&
0xff
)
{
case
R_SPARC_64
:
...
...
@@ -137,7 +247,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
me
->
name
,
(
int
)
(
ELF64_R_TYPE
(
rel
[
i
].
r_info
)
&
0xff
));
return
-
ENOEXEC
;
}
}
;
}
return
0
;
}
...
...
arch/sparc64/kernel/sys_sparc32.c
View file @
6ccc3e25
...
...
@@ -3113,24 +3113,18 @@ asmlinkage int sparc32_execve(struct pt_regs *regs)
#ifdef CONFIG_MODULES
extern
asmlinkage
long
sys_init_module
(
const
char
*
name_user
,
struct
module
*
mod_user
);
extern
asmlinkage
long
sys_init_module
(
void
*
,
unsigned
long
,
const
char
*
);
/* Hey, when you're trying to init module, take time and prepare us a nice
* 64bit module structure, even if from 32bit modutils... Why to pollute
* kernel... :))
*/
asmlinkage
int
sys32_init_module
(
const
char
*
name_user
,
struct
module
*
mod_user
)
asmlinkage
int
sys32_init_module
(
void
*
umod
,
u32
len
,
const
char
*
uargs
)
{
return
sys_init_module
(
name_user
,
mod_user
);
return
sys_init_module
(
umod
,
len
,
uargs
);
}
extern
asmlinkage
long
sys_delete_module
(
const
char
*
name_user
);
extern
asmlinkage
long
sys_delete_module
(
const
char
*
,
unsigned
int
);
asmlinkage
int
sys32_delete_module
(
const
char
*
name_user
)
asmlinkage
int
sys32_delete_module
(
const
char
*
name_user
,
unsigned
int
flags
)
{
return
sys_delete_module
(
name_user
);
return
sys_delete_module
(
name_user
,
flags
);
}
#else
/* CONFIG_MODULES */
...
...
crypto/api.c
View file @
6ccc3e25
...
...
@@ -263,8 +263,7 @@ static int c_show(struct seq_file *m, void *p)
struct
crypto_alg
*
alg
=
(
struct
crypto_alg
*
)
p
;
seq_printf
(
m
,
"name : %s
\n
"
,
alg
->
cra_name
);
seq_printf
(
m
,
"module : %s
\n
"
,
alg
->
cra_module
?
alg
->
cra_module
->
name
:
"[static]"
);
seq_printf
(
m
,
"module : %s
\n
"
,
module_name
(
alg
->
cra_module
));
seq_printf
(
m
,
"blocksize : %u
\n
"
,
alg
->
cra_blocksize
);
switch
(
alg
->
cra_flags
&
CRYPTO_ALG_TYPE_MASK
)
{
...
...
include/linux/in.h
View file @
6ccc3e25
...
...
@@ -70,6 +70,7 @@ struct in_addr {
#define IP_MTU 14
#define IP_FREEBIND 15
#define IP_IPSEC_POLICY 16
#define IP_XFRM_POLICY 17
/* BSD compatibility */
#define IP_RECVRETOPTS IP_RETOPTS
...
...
include/linux/module.h
View file @
6ccc3e25
...
...
@@ -242,6 +242,13 @@ static inline void module_put(struct module *module)
#endif
/* CONFIG_MODULE_UNLOAD */
/* This is a #define so the string doesn't get put in every .o file */
#define module_name(mod) \
({ \
struct module *__mod = (mod); \
__mod ? __mod->name : "kernel"; \
})
#define __unsafe(mod) \
do { \
if (mod && !(mod)->unsafe) { \
...
...
@@ -265,6 +272,8 @@ do { \
#define try_module_get(module) 1
#define module_put(module) do { } while(0)
#define module_name(mod) "kernel"
#define __unsafe(mod)
#endif
/* CONFIG_MODULES */
...
...
include/linux/udp.h
View file @
6ccc3e25
...
...
@@ -57,7 +57,4 @@ struct udp_sock {
#define udp_sk(__sk) (&((struct udp_sock *)__sk)->udp)
extern
int
udp_proc_init
(
void
);
extern
void
udp_proc_exit
(
void
);
#endif
/* _LINUX_UDP_H */
include/linux/xfrm.h
View file @
6ccc3e25
...
...
@@ -91,6 +91,22 @@ struct xfrm_stats {
__u32
integrity_failed
;
};
enum
{
XFRM_POLICY_IN
=
0
,
XFRM_POLICY_OUT
=
1
,
XFRM_POLICY_FWD
=
2
,
XFRM_POLICY_MAX
=
3
};
enum
{
XFRM_SHARE_ANY
,
/* No limitations */
XFRM_SHARE_SESSION
,
/* For this session only */
XFRM_SHARE_USER
,
/* For this user only */
XFRM_SHARE_UNIQUE
/* Use once */
};
/* Netlink configuration messages. */
#define XFRM_MSG_BASE 0x10
...
...
@@ -104,8 +120,9 @@ struct xfrm_stats {
#define XFRM_MSG_ALLOCSPI (RTM_BASE + 6)
#define XFRM_MSG_ACQUIRE (RTM_BASE + 7)
#define XFRM_MSG_EXPIRE (RTM_BASE + 8)
#define XFRM_MSG_MAX (XFRM_MSG_
ACQU
IRE+1)
#define XFRM_MSG_MAX (XFRM_MSG_
EXP
IRE+1)
struct
xfrm_user_tmpl
{
struct
xfrm_id
id
;
...
...
@@ -113,6 +130,7 @@ struct xfrm_user_tmpl {
__u16
reqid
;
__u8
mode
;
__u8
share
;
__u8
optional
;
__u32
aalgos
;
__u32
ealgos
;
__u32
calgos
;
...
...
@@ -135,9 +153,9 @@ struct xfrm_usersa_info {
struct
xfrm_lifetime_cfg
lft
;
struct
xfrm_lifetime_cur
curlft
;
struct
xfrm_stats
stats
;
__u32
seq
;
__u16
family
;
__u16
reqid
;
__u8
sa_type
;
__u8
mode
;
/* 0=transport,1=tunnel */
__u8
replay_window
;
};
...
...
@@ -148,15 +166,26 @@ struct xfrm_usersa_id {
__u8
proto
;
};
struct
xfrm_userspi_info
{
struct
xfrm_usersa_info
info
;
u32
min
;
u32
max
;
};
struct
xfrm_userpolicy_info
{
struct
xfrm_selector
sel
;
struct
xfrm_id
id
;
struct
xfrm_lifetime_cfg
lft
;
struct
xfrm_lifetime_cur
curlft
;
__u32
priority
;
__u32
index
;
__u16
family
;
__u8
dir
;
__u8
action
;
#define XFRM_POLICY_ALLOW 0
#define XFRM_POLICY_BLOCK 1
__u8
flags
;
#define XFRM_POLICY_LOCALOK 1
/* Allow user to override global policy */
__u8
share
;
};
struct
xfrm_userpolicy_id
{
...
...
@@ -165,4 +194,22 @@ struct xfrm_userpolicy_id {
__u8
dir
;
};
struct
xfrm_user_acquire
{
struct
xfrm_id
id
;
xfrm_address_t
saddr
;
struct
xfrm_userpolicy_info
policy
;
__u32
aalgos
;
__u32
ealgos
;
__u32
calgos
;
__u32
seq
;
};
struct
xfrm_user_expire
{
struct
xfrm_usersa_info
state
;
__u8
hard
;
};
#define XFRMGRP_ACQUIRE 1
#define XFRMGRP_EXPIRE 2
#endif
/* _LINUX_XFRM_H */
include/net/ip_fib.h
View file @
6ccc3e25
...
...
@@ -276,7 +276,4 @@ static inline void fib_res_put(struct fib_result *res)
#endif
}
extern
int
fib_proc_init
(
void
);
extern
void
fib_proc_exit
(
void
);
#endif
/* _NET_FIB_H */
include/net/udp.h
View file @
6ccc3e25
...
...
@@ -76,6 +76,4 @@ extern struct udp_mib udp_statistics[NR_CPUS*2];
#define UDP_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_statistics, field)
#define UDP_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_statistics, field)
extern
int
udp_proc_init
(
void
);
#endif
/* _UDP_H */
include/net/xfrm.h
View file @
6ccc3e25
...
...
@@ -96,6 +96,7 @@ struct xfrm_state
u8
replay_window
;
u8
aalgo
,
ealgo
,
calgo
;
u16
reqid
;
u16
family
;
xfrm_address_t
saddr
;
int
header_len
;
int
trailer_len
;
...
...
@@ -187,22 +188,6 @@ struct xfrm_tmpl
#define XFRM_MAX_DEPTH 3
enum
{
XFRM_SHARE_ANY
,
/* No limitations */
XFRM_SHARE_SESSION
,
/* For this session only */
XFRM_SHARE_USER
,
/* For this user only */
XFRM_SHARE_UNIQUE
/* Use once */
};
enum
{
XFRM_POLICY_IN
=
0
,
XFRM_POLICY_OUT
=
1
,
XFRM_POLICY_FWD
=
2
,
XFRM_POLICY_MAX
=
3
};
struct
xfrm_policy
{
struct
xfrm_policy
*
next
;
...
...
@@ -217,11 +202,9 @@ struct xfrm_policy
struct
xfrm_lifetime_cfg
lft
;
struct
xfrm_lifetime_cur
curlft
;
struct
dst_entry
*
bundles
;
__u16
family
;
__u8
action
;
#define XFRM_POLICY_ALLOW 0
#define XFRM_POLICY_BLOCK 1
__u8
flags
;
#define XFRM_POLICY_LOCALOK 1
/* Allow user to override global policy */
__u8
dead
;
__u8
xfrm_nr
;
struct
xfrm_tmpl
xfrm_vec
[
XFRM_MAX_DEPTH
];
...
...
@@ -390,7 +373,7 @@ struct xfrm_policy *xfrm_policy_delete(int dir, struct xfrm_selector *sel);
struct
xfrm_policy
*
xfrm_policy_byid
(
int
dir
,
u32
id
,
int
delete
);
void
xfrm_policy_flush
(
void
);
void
xfrm_alloc_spi
(
struct
xfrm_state
*
x
,
u32
minspi
,
u32
maxspi
);
struct
xfrm_state
*
xfrm_find_acq
(
u8
mode
,
u16
reqid
,
u8
proto
,
u32
daddr
,
u32
saddr
);
struct
xfrm_state
*
xfrm_find_acq
(
u8
mode
,
u16
reqid
,
u8
proto
,
u32
daddr
,
u32
saddr
,
int
create
);
extern
void
xfrm_policy_flush
(
void
);
extern
void
xfrm_policy_kill
(
struct
xfrm_policy
*
);
extern
int
xfrm_sk_policy_insert
(
struct
sock
*
sk
,
int
dir
,
struct
xfrm_policy
*
pol
);
...
...
kernel/exec_domain.c
View file @
6ccc3e25
...
...
@@ -210,13 +210,8 @@ get_exec_domain_list(char *page)
read_lock
(
&
exec_domains_lock
);
for
(
ep
=
exec_domains
;
ep
&&
len
<
PAGE_SIZE
-
80
;
ep
=
ep
->
next
)
len
+=
sprintf
(
page
+
len
,
"%d-%d
\t
%-16s
\t
[%s]
\n
"
,
ep
->
pers_low
,
ep
->
pers_high
,
ep
->
name
,
#ifdef CONFIG_MODULES
ep
->
module
?
ep
->
module
->
name
:
"kernel"
#else
"kernel"
#endif
);
ep
->
pers_low
,
ep
->
pers_high
,
ep
->
name
,
module_name
(
ep
->
module
));
read_unlock
(
&
exec_domains_lock
);
return
(
len
);
}
...
...
net/802/tr.c
View file @
6ccc3e25
...
...
@@ -541,10 +541,10 @@ static int rif_get_info(char *buffer,char **start, off_t offset, int length)
static
int
__init
rif_init
(
void
)
{
init_timer
(
&
rif_timer
);
rif_timer
.
expires
=
RIF_TIMEOUT
;
rif_timer
.
data
=
0L
;
rif_timer
.
function
=
rif_check_expire
;
init_timer
(
&
rif_timer
);
add_timer
(
&
rif_timer
);
proc_net_create
(
"tr_rif"
,
0
,
rif_get_info
);
...
...
net/atm/mpc.c
View file @
6ccc3e25
...
...
@@ -104,7 +104,7 @@ extern void mpc_proc_clean(void);
struct
mpoa_client
*
mpcs
=
NULL
;
/* FIXME */
static
struct
atm_mpoa_qos
*
qos_head
=
NULL
;
static
struct
timer_list
mpc_timer
;
static
struct
timer_list
mpc_timer
=
TIMER_INITIALIZER
(
NULL
,
0
,
0
)
;
static
struct
mpoa_client
*
find_mpc_by_itfnum
(
int
itf
)
...
...
net/core/neighbour.c
View file @
6ccc3e25
...
...
@@ -1151,8 +1151,8 @@ void neigh_table_init(struct neigh_table *tbl)
tasklet_init
(
&
tbl
->
gc_task
,
SMP_TIMER_NAME
(
neigh_periodic_timer
),
(
unsigned
long
)
tbl
);
#endif
init_timer
(
&
tbl
->
gc_timer
);
tbl
->
lock
=
RW_LOCK_UNLOCKED
;
init_timer
(
&
tbl
->
gc_timer
);
tbl
->
gc_timer
.
data
=
(
unsigned
long
)
tbl
;
tbl
->
gc_timer
.
function
=
neigh_periodic_timer
;
tbl
->
gc_timer
.
expires
=
now
+
tbl
->
gc_interval
+
...
...
net/ipv4/Kconfig
View file @
6ccc3e25
...
...
@@ -362,5 +362,13 @@ config INET_ESP
If unsure, say Y.
config XFRM_USER
tristate "IP: IPsec user configuration interface"
---help---
Support for IPsec user configuration interface used
by native Linux tools.
If unsure, say Y.
source "net/ipv4/netfilter/Kconfig"
net/ipv4/Makefile
View file @
6ccc3e25
...
...
@@ -20,6 +20,7 @@ obj-$(CONFIG_INET_AH) += ah.o
obj-$(CONFIG_INET_ESP)
+=
esp.o
obj-$(CONFIG_IP_PNP)
+=
ipconfig.o
obj-$(CONFIG_NETFILTER)
+=
netfilter/
obj-$(CONFIG_XFRM_USER)
+=
xfrm_user.o
obj-y
+=
xfrm_policy.o xfrm_state.o xfrm_input.o
...
...
net/ipv4/af_inet.c
View file @
6ccc3e25
...
...
@@ -1160,16 +1160,20 @@ module_init(inet_init);
/* ------------------------------------------------------------------------ */
#ifdef CONFIG_PROC_FS
extern
int
ip_misc_proc_init
(
void
);
extern
int
raw_get_info
(
char
*
,
char
**
,
off_t
,
int
);
extern
int
tcp_get_info
(
char
*
,
char
**
,
off_t
,
int
);
extern
int
fib_proc_init
(
void
);
extern
void
fib_proc_exit
(
void
);
extern
int
ip_misc_proc_init
(
void
);
extern
int
raw_proc_init
(
void
);
extern
void
raw_proc_exit
(
void
);
extern
int
tcp_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
);
extern
int
udp_proc_init
(
void
);
extern
void
udp_proc_exit
(
void
);
int
__init
ipv4_proc_init
(
void
)
{
int
rc
=
0
;
if
(
!
proc_net_create
(
"raw"
,
0
,
raw_get_info
))
if
(
raw_proc_init
(
))
goto
out_raw
;
if
(
!
proc_net_create
(
"tcp"
,
0
,
tcp_get_info
))
goto
out_tcp
;
...
...
@@ -1188,7 +1192,7 @@ int __init ipv4_proc_init(void)
out_udp:
proc_net_remove
(
"tcp"
);
out_tcp:
proc_net_remove
(
"raw"
);
raw_proc_exit
(
);
out_raw:
rc
=
-
ENOMEM
;
goto
out
;
...
...
net/ipv4/ah.c
View file @
6ccc3e25
...
...
@@ -189,7 +189,7 @@ int ah_output(struct sk_buff *skb)
top_iph
->
saddr
=
x
->
props
.
saddr
.
xfrm4_addr
;
top_iph
->
daddr
=
x
->
id
.
daddr
.
xfrm4_addr
;
ah
=
(
struct
ip_auth_hdr
*
)(
top_iph
+
1
);
ah
->
nexthdr
=
IPPROTO_IP
;
ah
->
nexthdr
=
IPPROTO_IP
IP
;
}
else
{
memcpy
(
&
tmp_iph
,
skb
->
data
,
iph
->
ihl
*
4
);
top_iph
=
(
struct
iphdr
*
)
skb_push
(
skb
,
x
->
props
.
header_len
);
...
...
net/ipv4/esp.c
View file @
6ccc3e25
...
...
@@ -190,11 +190,10 @@ esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset,
struct
crypto_tfm
*
tfm
=
esp
->
auth
.
tfm
;
char
*
digest
=
esp
->
auth
.
work_digest
;
memset
(
auth_data
,
0
,
esp
->
auth
.
authlen
);
crypto_hmac_init
(
tfm
,
esp
->
auth
.
key
,
&
esp
->
auth
.
key_len
);
skb_digest_walk
(
skb
,
tfm
,
offset
,
len
);
crypto_hmac_final
(
tfm
,
esp
->
auth
.
key
,
&
esp
->
auth
.
key_len
,
digest
);
memcpy
(
auth_data
,
digest
,
crypto_tfm_alg_digestsize
(
tfm
)
);
memcpy
(
auth_data
,
digest
,
esp
->
auth
.
authlen
);
}
/* Check that skb data bits are writable. If they are not, copy data
...
...
@@ -370,7 +369,7 @@ int esp_output(struct sk_buff *skb)
if
(
x
->
props
.
mode
)
{
top_iph
=
(
struct
iphdr
*
)
skb_push
(
skb
,
x
->
props
.
header_len
);
esph
=
(
struct
ip_esp_hdr
*
)(
top_iph
+
1
);
*
(
u8
*
)(
trailer
->
tail
-
1
)
=
IPPROTO_IP
;
*
(
u8
*
)(
trailer
->
tail
-
1
)
=
IPPROTO_IP
IP
;
top_iph
->
ihl
=
5
;
top_iph
->
version
=
4
;
top_iph
->
tos
=
iph
->
tos
;
/* DS disclosed */
...
...
@@ -463,16 +462,16 @@ int esp_input(struct xfrm_state *x, struct sk_buff *skb)
/* If integrity check is required, do this. */
if
(
esp
->
auth
.
authlen
)
{
int
icvsize
=
crypto_tfm_alg_digestsize
(
esp
->
auth
.
tfm
);
u8
sum
[
icvsize
];
u8
sum1
[
icvsize
];
u8
sum
[
esp
->
auth
.
authlen
];
u8
sum1
[
esp
->
auth
.
authlen
];
esp
->
auth
.
digest
(
esp
,
skb
,
0
,
skb
->
len
-
esp
->
auth
.
authlen
,
sum
);
if
(
skb_copy_bits
(
skb
,
skb
->
len
-
esp
->
auth
.
authlen
,
sum1
,
icvsize
))
if
(
skb_copy_bits
(
skb
,
skb
->
len
-
esp
->
auth
.
authlen
,
sum1
,
esp
->
auth
.
authlen
))
BUG
();
if
(
unlikely
(
memcmp
(
sum
,
sum1
,
icvsize
)))
{
if
(
unlikely
(
memcmp
(
sum
,
sum1
,
esp
->
auth
.
authlen
)))
{
x
->
stats
.
integrity_failed
++
;
goto
out
;
}
...
...
@@ -605,14 +604,20 @@ int esp_init_state(struct xfrm_state *x, void *args)
memset
(
esp
,
0
,
sizeof
(
*
esp
));
if
(
x
->
aalg
)
{
int
digestsize
;
esp
->
auth
.
key
=
x
->
aalg
->
alg_key
;
esp
->
auth
.
key_len
=
(
x
->
aalg
->
alg_key_len
+
7
)
/
8
;
esp
->
auth
.
tfm
=
crypto_alloc_tfm
(
x
->
aalg
->
alg_name
,
0
);
if
(
esp
->
auth
.
tfm
==
NULL
)
goto
error
;
esp
->
auth
.
digest
=
esp_hmac_digest
;
esp
->
auth
.
authlen
=
crypto_tfm_alg_digestsize
(
esp
->
auth
.
tfm
);
esp
->
auth
.
work_digest
=
kmalloc
(
esp
->
auth
.
authlen
,
GFP_KERNEL
);
digestsize
=
crypto_tfm_alg_digestsize
(
esp
->
auth
.
tfm
);
/* XXX RFC2403 and RFC 2404 truncate auth to 96 bit */
esp
->
auth
.
authlen
=
12
;
if
(
esp
->
auth
.
authlen
>
digestsize
)
/* XXX */
BUG
();
esp
->
auth
.
work_digest
=
kmalloc
(
digestsize
,
GFP_KERNEL
);
if
(
!
esp
->
auth
.
work_digest
)
goto
error
;
}
...
...
net/ipv4/fib_hash.c
View file @
6ccc3e25
...
...
@@ -1092,16 +1092,4 @@ void __init fib_proc_exit(void)
{
remove_proc_entry
(
"route"
,
proc_net
);
}
#else
/* CONFIG_PROC_FS */
int
__init
fib_proc_init
(
void
)
{
return
0
;
}
void
__init
fib_proc_exit
(
void
)
{
return
0
;
}
#endif
/* CONFIG_PROC_FS */
net/ipv4/ip_sockglue.c
View file @
6ccc3e25
...
...
@@ -626,6 +626,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
break
;
case
IP_IPSEC_POLICY
:
case
IP_XFRM_POLICY
:
err
=
xfrm_user_policy
(
sk
,
optname
,
optval
,
optlen
);
break
;
...
...
net/ipv4/netfilter/ip_nat_helper.c
View file @
6ccc3e25
...
...
@@ -361,8 +361,6 @@ helper_cmp(const struct ip_nat_helper *helper,
return
ip_ct_tuple_mask_cmp
(
tuple
,
&
helper
->
tuple
,
&
helper
->
mask
);
}
#define MODULE_MAX_NAMELEN 32
int
ip_nat_helper_register
(
struct
ip_nat_helper
*
me
)
{
int
ret
=
0
;
...
...
@@ -374,14 +372,13 @@ int ip_nat_helper_register(struct ip_nat_helper *me)
&&
ct_helper
->
me
)
{
__MOD_INC_USE_COUNT
(
ct_helper
->
me
);
}
else
{
#ifdef CONFIG_MODULES
/* We are a NAT helper for protocol X. If we need
* respective conntrack helper for protoccol X, compute
* conntrack helper name and try to load module */
char
name
[
MODULE_
MAX_NAME
LEN
];
const
char
*
tmp
=
m
e
->
me
->
name
;
char
name
[
MODULE_
NAME_
LEN
];
const
char
*
tmp
=
m
odule_name
(
me
->
me
)
;
if
(
strlen
(
tmp
)
+
6
>
MODULE_
MAX_NAME
LEN
)
{
if
(
strlen
(
tmp
)
+
6
>
MODULE_
NAME_
LEN
)
{
printk
(
"%s: unable to "
"compute conntrack helper name "
"from %s
\n
"
,
__FUNCTION__
,
tmp
);
...
...
@@ -403,7 +400,6 @@ int ip_nat_helper_register(struct ip_nat_helper *me)
"because kernel was compiled without kernel "
"module loader support
\n
"
,
name
);
return
-
EBUSY
;
#endif
#endif
}
}
...
...
net/ipv4/proc.c
View file @
6ccc3e25
...
...
@@ -23,30 +23,21 @@
* Alan Cox : Handle dead sockets properly.
* Gerhard Koerting : Show both timers
* Alan Cox : Allow inode to be NULL (kernel socket)
* Andi Kleen : Add support for open_requests and
* Andi Kleen : Add support for open_requests and
* split functions for more readibility.
* Andi Kleen : Add support for /proc/net/netstat
* Arnaldo C. Melo : Convert to seq_file
*
* 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.
*/
#include <asm/system.h>
#include <linux/sched.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/un.h>
#include <linux/in.h>
#include <linux/param.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <net/ip.h>
#include <linux/types.h>
#include <net/icmp.h>
#include <net/protocol.h>
#include <net/tcp.h>
#include <net/udp.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/sock.h>
...
...
@@ -57,7 +48,7 @@ static int fold_prot_inuse(struct proto *proto)
int
res
=
0
;
int
cpu
;
for
(
cpu
=
0
;
cpu
<
NR_CPUS
;
cpu
++
)
for
(
cpu
=
0
;
cpu
<
NR_CPUS
;
cpu
++
)
res
+=
proto
->
stats
[
cpu
].
inuse
;
return
res
;
...
...
@@ -66,38 +57,35 @@ static int fold_prot_inuse(struct proto *proto)
/*
* Report socket allocation statistics [mea@utu.fi]
*/
int
afinet_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
static
int
sockstat_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
/* From net/socket.c */
extern
int
socket_get_info
(
char
*
,
char
**
,
off_t
,
int
);
int
len
=
socket_get_info
(
buffer
,
start
,
offset
,
length
);
len
+=
sprintf
(
buffer
+
len
,
"TCP: inuse %d orphan %d tw %d alloc %d mem %d
\n
"
,
fold_prot_inuse
(
&
tcp_prot
),
atomic_read
(
&
tcp_orphan_count
),
tcp_tw_count
,
atomic_read
(
&
tcp_sockets_allocated
),
atomic_read
(
&
tcp_memory_allocated
));
len
+=
sprintf
(
buffer
+
len
,
"UDP: inuse %d
\n
"
,
fold_prot_inuse
(
&
udp_prot
));
len
+=
sprintf
(
buffer
+
len
,
"RAW: inuse %d
\n
"
,
fold_prot_inuse
(
&
raw_prot
));
len
+=
sprintf
(
buffer
+
len
,
"FRAG: inuse %d memory %d
\n
"
,
ip_frag_nqueues
,
atomic_read
(
&
ip_frag_mem
));
if
(
offset
>=
len
)
{
*
start
=
buffer
;
return
0
;
}
*
start
=
buffer
+
offset
;
len
-=
offset
;
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
/* From net/socket.c */
extern
void
socket_seq_show
(
struct
seq_file
*
seq
);
socket_seq_show
(
seq
);
seq_printf
(
seq
,
"TCP: inuse %d orphan %d tw %d alloc %d mem %d
\n
"
,
fold_prot_inuse
(
&
tcp_prot
),
atomic_read
(
&
tcp_orphan_count
),
tcp_tw_count
,
atomic_read
(
&
tcp_sockets_allocated
),
atomic_read
(
&
tcp_memory_allocated
));
seq_printf
(
seq
,
"UDP: inuse %d
\n
"
,
fold_prot_inuse
(
&
udp_prot
));
seq_printf
(
seq
,
"RAW: inuse %d
\n
"
,
fold_prot_inuse
(
&
raw_prot
));
seq_printf
(
seq
,
"FRAG: inuse %d memory %d
\n
"
,
ip_frag_nqueues
,
atomic_read
(
&
ip_frag_mem
));
return
0
;
}
static
int
sockstat_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
sockstat_seq_show
,
NULL
);
}
static
struct
file_operations
sockstat_seq_fops
=
{
.
open
=
sockstat_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
};
static
unsigned
long
fold_field
(
unsigned
long
*
begin
,
int
sz
,
int
nr
)
{
unsigned
long
res
=
0
;
...
...
@@ -105,63 +93,84 @@ static unsigned long fold_field(unsigned long *begin, int sz, int nr)
sz
/=
sizeof
(
unsigned
long
);
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
{
res
+=
begin
[
2
*
i
*
sz
+
nr
];
res
+=
begin
[(
2
*
i
+
1
)
*
sz
+
nr
];
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
{
res
+=
begin
[
2
*
i
*
sz
+
nr
];
res
+=
begin
[(
2
*
i
+
1
)
*
sz
+
nr
];
}
return
res
;
}
/*
/*
* Called from the PROCfs module. This outputs /proc/net/snmp.
*/
int
snmp_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
static
int
snmp_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
extern
int
sysctl_ip_default_ttl
;
int
len
,
i
;
len
=
sprintf
(
buffer
,
"Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates
\n
"
"Ip: %d %d"
,
ipv4_devconf
.
forwarding
?
1
:
2
,
sysctl_ip_default_ttl
);
for
(
i
=
0
;
i
<
offsetof
(
struct
ip_mib
,
__pad
)
/
sizeof
(
unsigned
long
);
i
++
)
len
+=
sprintf
(
buffer
+
len
,
" %lu"
,
fold_field
((
unsigned
long
*
)
ip_statistics
,
sizeof
(
struct
ip_mib
),
i
));
len
+=
sprintf
(
buffer
+
len
,
"
\n
Icmp: InMsgs InErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps
\n
"
"Icmp:"
);
for
(
i
=
0
;
i
<
offsetof
(
struct
icmp_mib
,
dummy
)
/
sizeof
(
unsigned
long
);
i
++
)
len
+=
sprintf
(
buffer
+
len
,
" %lu"
,
fold_field
((
unsigned
long
*
)
icmp_statistics
,
sizeof
(
struct
icmp_mib
),
i
));
len
+=
sprintf
(
buffer
+
len
,
"
\n
Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts
\n
"
"Tcp:"
);
for
(
i
=
0
;
i
<
offsetof
(
struct
tcp_mib
,
__pad
)
/
sizeof
(
unsigned
long
);
i
++
)
len
+=
sprintf
(
buffer
+
len
,
" %lu"
,
fold_field
((
unsigned
long
*
)
tcp_statistics
,
sizeof
(
struct
tcp_mib
),
i
));
len
+=
sprintf
(
buffer
+
len
,
"
\n
Udp: InDatagrams NoPorts InErrors OutDatagrams
\n
"
"Udp:"
);
for
(
i
=
0
;
i
<
offsetof
(
struct
udp_mib
,
__pad
)
/
sizeof
(
unsigned
long
);
i
++
)
len
+=
sprintf
(
buffer
+
len
,
" %lu"
,
fold_field
((
unsigned
long
*
)
udp_statistics
,
sizeof
(
struct
udp_mib
),
i
));
len
+=
sprintf
(
buffer
+
len
,
"
\n
"
);
if
(
offset
>=
len
)
{
*
start
=
buffer
;
return
0
;
}
*
start
=
buffer
+
offset
;
len
-=
offset
;
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
int
i
;
seq_printf
(
seq
,
"Ip: Forwarding DefaultTTL InReceives InHdrErrors "
"InAddrErrors ForwDatagrams InUnknownProtos "
"InDiscards InDelivers OutRequests OutDiscards "
"OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs "
"ReasmFails FragOKs FragFails FragCreates
\n
Ip: %d %d"
,
ipv4_devconf
.
forwarding
?
1
:
2
,
sysctl_ip_default_ttl
);
for
(
i
=
0
;
i
<
offsetof
(
struct
ip_mib
,
__pad
)
/
sizeof
(
unsigned
long
);
i
++
)
seq_printf
(
seq
,
" %lu"
,
fold_field
((
unsigned
long
*
)
ip_statistics
,
sizeof
(
struct
ip_mib
),
i
));
seq_printf
(
seq
,
"
\n
Icmp: InMsgs InErrors InDestUnreachs InTimeExcds "
"InParmProbs InSrcQuenchs InRedirects InEchos "
"InEchoReps InTimestamps InTimestampReps InAddrMasks "
"InAddrMaskReps OutMsgs OutErrors OutDestUnreachs "
"OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects "
"OutEchos OutEchoReps OutTimestamps OutTimestampReps "
"OutAddrMasks OutAddrMaskReps
\n
Icmp:"
);
for
(
i
=
0
;
i
<
offsetof
(
struct
icmp_mib
,
dummy
)
/
sizeof
(
unsigned
long
);
i
++
)
seq_printf
(
seq
,
" %lu"
,
fold_field
((
unsigned
long
*
)
icmp_statistics
,
sizeof
(
struct
icmp_mib
),
i
));
seq_printf
(
seq
,
"
\n
Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens "
"PassiveOpens AttemptFails EstabResets CurrEstab "
"InSegs OutSegs RetransSegs InErrs OutRsts
\n
Tcp:"
);
for
(
i
=
0
;
i
<
offsetof
(
struct
tcp_mib
,
__pad
)
/
sizeof
(
unsigned
long
);
i
++
)
seq_printf
(
seq
,
" %lu"
,
fold_field
((
unsigned
long
*
)
tcp_statistics
,
sizeof
(
struct
tcp_mib
),
i
));
seq_printf
(
seq
,
"
\n
Udp: InDatagrams NoPorts InErrors OutDatagrams
\n
"
"Udp:"
);
for
(
i
=
0
;
i
<
offsetof
(
struct
udp_mib
,
__pad
)
/
sizeof
(
unsigned
long
);
i
++
)
seq_printf
(
seq
,
" %lu"
,
fold_field
((
unsigned
long
*
)
udp_statistics
,
sizeof
(
struct
udp_mib
),
i
));
seq_putc
(
seq
,
'\n'
);
return
0
;
}
static
int
snmp_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
snmp_seq_show
,
NULL
);
}
/*
static
struct
file_operations
snmp_seq_fops
=
{
.
open
=
snmp_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
};
/*
* Output /proc/net/netstat
*/
static
int
netstat_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
...
...
@@ -181,7 +190,8 @@ static int netstat_seq_show(struct seq_file *seq, void *v)
" TCPPureAcks TCPHPAcks"
" TCPRenoRecovery TCPSackRecovery"
" TCPSACKReneging"
" TCPFACKReorder TCPSACKReorder TCPRenoReorder TCPTSReorder"
" TCPFACKReorder TCPSACKReorder TCPRenoReorder"
" TCPTSReorder"
" TCPFullUndo TCPPartialUndo TCPDSACKUndo TCPLossUndo"
" TCPLoss TCPLostRetransmit"
" TCPRenoFailures TCPSackFailures TCPLossFailures"
...
...
@@ -189,14 +199,14 @@ static int netstat_seq_show(struct seq_file *seq, void *v)
" TCPTimeouts"
" TCPRenoRecoveryFail TCPSackRecoveryFail"
" TCPSchedulerFailed TCPRcvCollapsed"
" TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv TCPDSACKOfoRecv"
" TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv"
" TCPDSACKOfoRecv"
" TCPAbortOnSyn TCPAbortOnData TCPAbortOnClose"
" TCPAbortOnMemory TCPAbortOnTimeout TCPAbortOnLinger"
" TCPAbortFailed TCPMemoryPressures
\n
"
"TcpExt:"
);
for
(
i
=
0
;
i
<
offsetof
(
struct
linux_mib
,
__pad
)
/
sizeof
(
unsigned
long
);
i
++
)
i
<
offsetof
(
struct
linux_mib
,
__pad
)
/
sizeof
(
unsigned
long
);
i
++
)
seq_printf
(
seq
,
" %lu"
,
fold_field
((
unsigned
long
*
)
net_statistics
,
sizeof
(
struct
linux_mib
),
i
));
...
...
@@ -219,20 +229,26 @@ static struct file_operations netstat_seq_fops = {
int
__init
ip_misc_proc_init
(
void
)
{
int
rc
=
0
;
struct
proc_dir_entry
*
p
=
create_proc_entry
(
"netstat"
,
S_IRUGO
,
proc_net
)
;
struct
proc_dir_entry
*
p
;
p
=
create_proc_entry
(
"netstat"
,
S_IRUGO
,
proc_net
);
if
(
!
p
)
goto
out_netstat
;
p
->
proc_fops
=
&
netstat_seq_fops
;
if
(
!
proc_net_create
(
"snmp"
,
0
,
snmp_get_info
))
p
=
create_proc_entry
(
"snmp"
,
S_IRUGO
,
proc_net
);
if
(
!
p
)
goto
out_snmp
;
if
(
!
proc_net_create
(
"sockstat"
,
0
,
afinet_get_info
))
p
->
proc_fops
=
&
snmp_seq_fops
;
p
=
create_proc_entry
(
"sockstat"
,
S_IRUGO
,
proc_net
);
if
(
!
p
)
goto
out_sockstat
;
p
->
proc_fops
=
&
sockstat_seq_fops
;
out:
return
rc
;
out_sockstat:
proc_net_remove
(
"snmp"
);
remove_proc_entry
(
"snmp"
,
proc_net
);
out_snmp:
remove_proc_entry
(
"netstat"
,
proc_net
);
out_netstat:
...
...
net/ipv4/raw.c
View file @
6ccc3e25
...
...
@@ -40,31 +40,42 @@
*/
#include <linux/config.h>
#include <asm/system.h>
#include <asm/atomic.h>
#include <asm/byteorder.h>
#include <asm/current.h>
#include <asm/uaccess.h>
#include <asm/ioctls.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/stddef.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/aio.h>
#include <linux/kernel.h>
#include <linux/fcntl.h>
#include <linux/spinlock.h>
#include <linux/sockios.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/
m
route.h>
#include <
net/tcp
.h>
#include <
net/protocol
.h>
#include <linux/
in_
route.h>
#include <
linux/route
.h>
#include <
linux/tcp
.h>
#include <linux/skbuff.h>
#include <net/dst.h>
#include <net/sock.h>
#include <linux/gfp.h>
#include <linux/ip.h>
#include <net/ip.h>
#include <net/icmp.h>
#include <net/udp.h>
#include <net/raw.h>
#include <net/snmp.h>
#include <net/inet_common.h>
#include <net/checksum.h>
#include <net/xfrm.h>
#include <linux/rtnetlink.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
struct
sock
*
raw_v4_htable
[
RAWV4_HTABLE_SIZE
];
...
...
@@ -656,7 +667,95 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
}
}
static
void
get_raw_sock
(
struct
sock
*
sp
,
char
*
tmpbuf
,
int
i
)
struct
proto
raw_prot
=
{
.
name
=
"RAW"
,
.
close
=
raw_close
,
.
connect
=
udp_connect
,
.
disconnect
=
udp_disconnect
,
.
ioctl
=
raw_ioctl
,
.
init
=
raw_init
,
.
setsockopt
=
raw_setsockopt
,
.
getsockopt
=
raw_getsockopt
,
.
sendmsg
=
raw_sendmsg
,
.
recvmsg
=
raw_recvmsg
,
.
bind
=
raw_bind
,
.
backlog_rcv
=
raw_rcv_skb
,
.
hash
=
raw_v4_hash
,
.
unhash
=
raw_v4_unhash
,
};
#ifdef CONFIG_PROC_FS
struct
raw_iter_state
{
int
bucket
;
};
#define raw_seq_private(seq) ((struct raw_iter_state *)&seq->private)
static
struct
sock
*
raw_get_first
(
struct
seq_file
*
seq
)
{
struct
sock
*
sk
=
NULL
;
struct
raw_iter_state
*
state
=
raw_seq_private
(
seq
);
for
(
state
->
bucket
=
0
;
state
->
bucket
<
RAWV4_HTABLE_SIZE
;
++
state
->
bucket
)
{
sk
=
raw_v4_htable
[
state
->
bucket
];
while
(
sk
&&
sk
->
family
!=
PF_INET
)
sk
=
sk
->
next
;
if
(
sk
)
break
;
}
return
sk
;
}
static
struct
sock
*
raw_get_next
(
struct
seq_file
*
seq
,
struct
sock
*
sk
)
{
struct
raw_iter_state
*
state
=
raw_seq_private
(
seq
);
do
{
sk
=
sk
->
next
;
try_again:
}
while
(
sk
&&
sk
->
family
!=
PF_INET
);
if
(
!
sk
&&
++
state
->
bucket
<
RAWV4_HTABLE_SIZE
)
{
sk
=
raw_v4_htable
[
state
->
bucket
];
goto
try_again
;
}
return
sk
;
}
static
struct
sock
*
raw_get_idx
(
struct
seq_file
*
seq
,
loff_t
pos
)
{
struct
sock
*
sk
=
raw_get_first
(
seq
);
if
(
sk
)
while
(
pos
&&
(
sk
=
raw_get_next
(
seq
,
sk
))
!=
NULL
)
--
pos
;
return
pos
?
NULL
:
sk
;
}
static
void
*
raw_seq_start
(
struct
seq_file
*
seq
,
loff_t
*
pos
)
{
read_lock
(
&
raw_v4_lock
);
return
*
pos
?
raw_get_idx
(
seq
,
*
pos
)
:
(
void
*
)
1
;
}
static
void
*
raw_seq_next
(
struct
seq_file
*
seq
,
void
*
v
,
loff_t
*
pos
)
{
struct
sock
*
sk
;
if
(
v
==
(
void
*
)
1
)
sk
=
raw_get_first
(
seq
);
else
sk
=
raw_get_next
(
seq
,
v
);
++*
pos
;
return
sk
;
}
static
void
raw_seq_stop
(
struct
seq_file
*
seq
,
void
*
v
)
{
read_unlock
(
&
raw_v4_lock
);
}
static
__inline__
char
*
get_raw_sock
(
struct
sock
*
sp
,
char
*
tmpbuf
,
int
i
)
{
struct
inet_opt
*
inet
=
inet_sk
(
sp
);
unsigned
int
dest
=
inet
->
daddr
,
...
...
@@ -668,65 +767,63 @@ static void get_raw_sock(struct sock *sp, char *tmpbuf, int i)
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p"
,
i
,
src
,
srcp
,
dest
,
destp
,
sp
->
state
,
atomic_read
(
&
sp
->
wmem_alloc
),
atomic_read
(
&
sp
->
rmem_alloc
),
0
,
0L
,
0
,
sock_i_uid
(
sp
),
0
,
sock_i_ino
(
sp
),
0
,
0L
,
0
,
sock_i_uid
(
sp
),
0
,
sock_i_ino
(
sp
),
atomic_read
(
&
sp
->
refcnt
),
sp
);
return
tmpbuf
;
}
int
raw_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
static
int
raw_seq_show
(
struct
seq_file
*
seq
,
void
*
v
)
{
int
len
=
0
,
num
=
0
,
i
;
off_t
pos
=
128
;
off_t
begin
;
char
tmpbuf
[
129
];
if
(
offset
<
128
)
len
+=
sprintf
(
buffer
,
"%-127s
\n
"
,
if
(
v
==
(
void
*
)
1
)
seq_printf
(
seq
,
"%-127s
\n
"
,
" sl local_address rem_address st tx_queue "
"rx_queue tr tm->when retrnsmt uid timeout "
"inode"
);
read_lock
(
&
raw_v4_lock
);
for
(
i
=
0
;
i
<
RAWV4_HTABLE_SIZE
;
i
++
)
{
struct
sock
*
sk
;
for
(
sk
=
raw_v4_htable
[
i
];
sk
;
sk
=
sk
->
next
,
num
++
)
{
if
(
sk
->
family
!=
PF_INET
)
continue
;
pos
+=
128
;
if
(
pos
<=
offset
)
continue
;
get_raw_sock
(
sk
,
tmpbuf
,
i
);
len
+=
sprintf
(
buffer
+
len
,
"%-127s
\n
"
,
tmpbuf
);
if
(
len
>=
length
)
goto
out
;
}
else
{
struct
raw_iter_state
*
state
=
raw_seq_private
(
seq
);
seq_printf
(
seq
,
"%-127s
\n
"
,
get_raw_sock
(
v
,
tmpbuf
,
state
->
bucket
));
}
out:
read_unlock
(
&
raw_v4_lock
);
begin
=
len
-
(
pos
-
offset
);
*
start
=
buffer
+
begin
;
len
-=
begin
;
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
return
0
;
}
struct
proto
raw_prot
=
{
.
name
=
"RAW"
,
.
close
=
raw_close
,
.
connect
=
udp_connect
,
.
disconnect
=
udp_disconnect
,
.
ioctl
=
raw_ioctl
,
.
init
=
raw_init
,
.
setsockopt
=
raw_setsockopt
,
.
getsockopt
=
raw_getsockopt
,
.
sendmsg
=
raw_sendmsg
,
.
recvmsg
=
raw_recvmsg
,
.
bind
=
raw_bind
,
.
backlog_rcv
=
raw_rcv_skb
,
.
hash
=
raw_v4_hash
,
.
unhash
=
raw_v4_unhash
,
static
struct
seq_operations
raw_seq_ops
=
{
.
start
=
raw_seq_start
,
.
next
=
raw_seq_next
,
.
stop
=
raw_seq_stop
,
.
show
=
raw_seq_show
,
};
static
int
raw_seq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
seq_open
(
file
,
&
raw_seq_ops
);
}
static
struct
file_operations
raw_seq_fops
=
{
.
open
=
raw_seq_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
seq_release
,
};
int
__init
raw_proc_init
(
void
)
{
struct
proc_dir_entry
*
p
;
int
rc
=
0
;
p
=
create_proc_entry
(
"raw"
,
S_IRUGO
,
proc_net
);
if
(
p
)
p
->
proc_fops
=
&
raw_seq_fops
;
else
rc
=
-
ENOMEM
;
return
rc
;
}
void
__init
raw_proc_exit
(
void
)
{
remove_proc_entry
(
"raw"
,
proc_net
);
}
#endif
/* CONFIG_PROC_FS */
net/ipv4/udp.c
View file @
6ccc3e25
...
...
@@ -944,7 +944,7 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
/*
* Charge it to the socket, dropping if the queue is full.
*/
if
(
!
xfrm_policy_check
(
NULL
,
XFRM_POLICY_IN
,
skb
))
{
if
(
!
xfrm_policy_check
(
sk
,
XFRM_POLICY_IN
,
skb
))
{
kfree_skb
(
skb
);
return
-
1
;
}
...
...
@@ -1377,16 +1377,4 @@ void __init udp_proc_exit(void)
{
remove_proc_entry
(
"udp"
,
proc_net
);
}
#else
/* CONFIG_PROC_FS */
int
__init
udp_proc_init
(
void
)
{
return
0
;
}
void
__init
udp_proc_exit
(
void
)
{
return
0
;
}
#endif
/* CONFIG_PROC_FS */
net/ipv4/xfrm_input.c
View file @
6ccc3e25
...
...
@@ -91,7 +91,7 @@ int xfrm4_rcv(struct sk_buff *skb)
iph
=
skb
->
nh
.
iph
;
if
(
x
->
props
.
mode
)
{
if
(
iph
->
protocol
!=
IPPROTO_IP
)
if
(
iph
->
protocol
!=
IPPROTO_IP
IP
)
goto
drop
;
skb
->
nh
.
raw
=
skb
->
data
;
iph
=
skb
->
nh
.
iph
;
...
...
net/ipv4/xfrm_state.c
View file @
6ccc3e25
...
...
@@ -386,7 +386,7 @@ xfrm_state_lookup(u32 daddr, u32 spi, u8 proto)
}
struct
xfrm_state
*
xfrm_find_acq
(
u8
mode
,
u16
reqid
,
u8
proto
,
u32
daddr
,
u32
saddr
)
xfrm_find_acq
(
u8
mode
,
u16
reqid
,
u8
proto
,
u32
daddr
,
u32
saddr
,
int
create
)
{
struct
xfrm_state
*
x
,
*
x0
;
unsigned
h
=
ntohl
(
daddr
);
...
...
@@ -400,10 +400,11 @@ xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr)
mode
==
x
->
props
.
mode
&&
proto
==
x
->
id
.
proto
&&
saddr
==
x
->
props
.
saddr
.
xfrm4_addr
&&
reqid
==
x
->
props
.
reqid
)
{
reqid
==
x
->
props
.
reqid
&&
x
->
km
.
state
==
XFRM_STATE_ACQ
)
{
if
(
!
x0
)
x0
=
x
;
if
(
x
->
km
.
state
!=
XFRM_STATE_ACQ
)
if
(
x
->
id
.
spi
)
continue
;
x0
=
x
;
break
;
...
...
@@ -411,7 +412,7 @@ xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr)
}
if
(
x0
)
{
atomic_inc
(
&
x0
->
refcnt
);
}
else
if
((
x0
=
xfrm_state_alloc
())
!=
NULL
)
{
}
else
if
(
create
&&
(
x0
=
xfrm_state_alloc
())
!=
NULL
)
{
x0
->
sel
.
daddr
.
xfrm4_addr
=
daddr
;
x0
->
sel
.
daddr
.
xfrm4_mask
=
~
0
;
x0
->
sel
.
saddr
.
xfrm4_addr
=
saddr
;
...
...
net/ipv4/xfrm_user.c
0 → 100644
View file @
6ccc3e25
/* xfrm_user.c: User interface to configure xfrm engine.
*
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/socket.h>
#include <linux/string.h>
#include <linux/net.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/pfkeyv2.h>
#include <linux/ipsec.h>
#include <linux/init.h>
#include <net/sock.h>
#include <net/xfrm.h>
static
struct
sock
*
xfrm_nl
;
static
int
verify_one_alg
(
struct
rtattr
**
xfrma
,
enum
xfrm_attr_type_t
type
)
{
struct
rtattr
*
rt
=
xfrma
[
type
];
struct
xfrm_algo
*
algp
;
if
(
!
rt
)
return
0
;
if
((
rt
->
rta_len
-
sizeof
(
*
rt
))
<
sizeof
(
*
algp
))
return
-
EINVAL
;
algp
=
RTA_DATA
(
rt
);
switch
(
type
)
{
case
XFRMA_ALG_AUTH
:
case
XFRMA_ALG_CRYPT
:
if
(
!
algp
->
alg_key_len
)
return
-
EINVAL
;
break
;
case
XFRMA_ALG_COMP
:
/* Zero length keys are legal. */
break
;
default:
return
-
EINVAL
;
};
algp
->
alg_name
[
CRYPTO_MAX_ALG_NAME
-
1
]
=
'\0'
;
return
0
;
}
static
int
verify_newsa_info
(
struct
xfrm_usersa_info
*
p
,
struct
rtattr
**
xfrma
)
{
int
err
;
err
=
-
EINVAL
;
switch
(
p
->
family
)
{
case
AF_INET
:
break
;
case
AF_INET6
:
/* XXX */
err
=
-
EAFNOSUPPORT
;
/* fallthru */
default:
goto
out
;
};
err
=
-
EINVAL
;
switch
(
p
->
id
.
proto
)
{
case
IPPROTO_AH
:
if
(
!
xfrma
[
XFRMA_ALG_AUTH
]
||
xfrma
[
XFRMA_ALG_CRYPT
]
||
xfrma
[
XFRMA_ALG_COMP
])
goto
out
;
break
;
case
IPPROTO_ESP
:
if
((
!
xfrma
[
XFRMA_ALG_AUTH
]
&&
!
xfrma
[
XFRMA_ALG_CRYPT
])
||
xfrma
[
XFRMA_ALG_COMP
])
goto
out
;
break
;
case
IPPROTO_COMP
:
if
(
!
xfrma
[
XFRMA_ALG_COMP
]
||
xfrma
[
XFRMA_ALG_AUTH
]
||
xfrma
[
XFRMA_ALG_CRYPT
])
goto
out
;
break
;
default:
goto
out
;
};
if
((
err
=
verify_one_alg
(
xfrma
,
XFRMA_ALG_AUTH
)))
goto
out
;
if
((
err
=
verify_one_alg
(
xfrma
,
XFRMA_ALG_CRYPT
)))
goto
out
;
if
((
err
=
verify_one_alg
(
xfrma
,
XFRMA_ALG_COMP
)))
goto
out
;
err
=
-
EINVAL
;
switch
(
p
->
mode
)
{
case
0
:
case
1
:
break
;
default:
goto
out
;
};
err
=
0
;
out:
return
err
;
}
static
int
attach_one_algo
(
struct
xfrm_algo
**
algpp
,
struct
rtattr
*
u_arg
)
{
struct
rtattr
*
rta
=
u_arg
;
struct
xfrm_algo
*
p
,
*
ualg
;
if
(
!
rta
)
return
0
;
ualg
=
RTA_DATA
(
rta
);
p
=
kmalloc
(
sizeof
(
*
ualg
)
+
ualg
->
alg_key_len
,
GFP_KERNEL
);
if
(
!
p
)
return
-
ENOMEM
;
memcpy
(
p
,
ualg
,
sizeof
(
*
ualg
)
+
ualg
->
alg_key_len
);
*
algpp
=
p
;
return
0
;
}
static
void
copy_from_user_state
(
struct
xfrm_state
*
x
,
struct
xfrm_usersa_info
*
p
)
{
memcpy
(
&
x
->
id
,
&
p
->
id
,
sizeof
(
x
->
id
));
memcpy
(
&
x
->
sel
,
&
p
->
sel
,
sizeof
(
x
->
sel
));
memcpy
(
&
x
->
lft
,
&
p
->
lft
,
sizeof
(
x
->
lft
));
x
->
props
.
mode
=
p
->
mode
;
x
->
props
.
replay_window
=
p
->
replay_window
;
x
->
props
.
reqid
=
p
->
reqid
;
x
->
props
.
family
=
p
->
family
;
x
->
props
.
saddr
=
x
->
sel
.
saddr
;
}
static
struct
xfrm_state
*
xfrm_state_construct
(
struct
xfrm_usersa_info
*
p
,
struct
rtattr
**
xfrma
,
int
*
errp
)
{
struct
xfrm_state
*
x
=
xfrm_state_alloc
();
int
err
=
-
ENOMEM
;
if
(
!
x
)
goto
error_no_put
;
copy_from_user_state
(
x
,
p
);
if
((
err
=
attach_one_algo
(
&
x
->
aalg
,
xfrma
[
XFRMA_ALG_AUTH
])))
goto
error
;
if
((
err
=
attach_one_algo
(
&
x
->
ealg
,
xfrma
[
XFRMA_ALG_CRYPT
])))
goto
error
;
if
((
err
=
attach_one_algo
(
&
x
->
calg
,
xfrma
[
XFRMA_ALG_COMP
])))
goto
error
;
err
=
-
ENOENT
;
x
->
type
=
xfrm_get_type
(
x
->
id
.
proto
);
if
(
x
->
type
==
NULL
)
goto
error
;
err
=
x
->
type
->
init_state
(
x
,
NULL
);
if
(
err
)
goto
error
;
x
->
curlft
.
add_time
=
(
unsigned
long
)
xtime
.
tv_sec
;
x
->
km
.
state
=
XFRM_STATE_VALID
;
x
->
km
.
seq
=
p
->
seq
;
return
x
;
error:
xfrm_state_put
(
x
);
error_no_put:
*
errp
=
err
;
return
NULL
;
}
static
int
xfrm_add_sa
(
struct
sk_buff
*
skb
,
struct
nlmsghdr
*
nlh
,
void
**
xfrma
)
{
struct
xfrm_usersa_info
*
p
=
NLMSG_DATA
(
nlh
);
struct
xfrm_state
*
x
,
*
x1
;
int
err
;
err
=
verify_newsa_info
(
p
,
(
struct
rtattr
**
)
xfrma
);
if
(
err
)
return
err
;
x
=
xfrm_state_construct
(
p
,
(
struct
rtattr
**
)
xfrma
,
&
err
);
if
(
!
x
)
return
err
;
x1
=
xfrm_state_lookup
(
x
->
props
.
saddr
.
xfrm4_addr
,
x
->
id
.
spi
,
x
->
id
.
proto
);
if
(
x1
)
{
xfrm_state_put
(
x
);
xfrm_state_put
(
x1
);
return
-
EEXIST
;
}
xfrm_state_insert
(
x
);
return
0
;
}
static
int
xfrm_del_sa
(
struct
sk_buff
*
skb
,
struct
nlmsghdr
*
nlh
,
void
**
xfrma
)
{
struct
xfrm_state
*
x
;
struct
xfrm_usersa_id
*
p
=
NLMSG_DATA
(
nlh
);
x
=
xfrm_state_lookup
(
p
->
saddr
.
xfrm4_addr
,
p
->
spi
,
p
->
proto
);
if
(
x
==
NULL
)
return
-
ESRCH
;
xfrm_state_delete
(
x
);
xfrm_state_put
(
x
);
return
0
;
}
static
void
copy_to_user_state
(
struct
xfrm_state
*
x
,
struct
xfrm_usersa_info
*
p
)
{
memcpy
(
&
p
->
id
,
&
x
->
id
,
sizeof
(
p
->
id
));
memcpy
(
&
p
->
sel
,
&
x
->
sel
,
sizeof
(
p
->
sel
));
memcpy
(
&
p
->
lft
,
&
x
->
lft
,
sizeof
(
p
->
lft
));
memcpy
(
&
p
->
curlft
,
&
x
->
curlft
,
sizeof
(
p
->
curlft
));
memcpy
(
&
p
->
stats
,
&
x
->
stats
,
sizeof
(
p
->
stats
));
p
->
mode
=
x
->
props
.
mode
;
p
->
replay_window
=
x
->
props
.
replay_window
;
p
->
reqid
=
x
->
props
.
reqid
;
p
->
family
=
x
->
props
.
family
;
p
->
seq
=
x
->
km
.
seq
;
}
struct
xfrm_dump_info
{
struct
sk_buff
*
in_skb
;
struct
sk_buff
*
out_skb
;
u32
nlmsg_seq
;
int
start_idx
;
int
this_idx
;
};
static
int
dump_one_state
(
struct
xfrm_state
*
x
,
int
count
,
void
*
ptr
)
{
struct
xfrm_dump_info
*
sp
=
ptr
;
struct
sk_buff
*
in_skb
=
sp
->
in_skb
;
struct
sk_buff
*
skb
=
sp
->
out_skb
;
struct
xfrm_usersa_info
*
p
;
struct
nlmsghdr
*
nlh
;
unsigned
char
*
b
=
skb
->
tail
;
if
(
sp
->
this_idx
<
sp
->
start_idx
)
goto
out
;
nlh
=
NLMSG_PUT
(
skb
,
NETLINK_CB
(
in_skb
).
pid
,
sp
->
nlmsg_seq
,
XFRM_MSG_NEWSA
,
sizeof
(
*
p
));
nlh
->
nlmsg_flags
=
0
;
p
=
NLMSG_DATA
(
nlh
);
copy_to_user_state
(
x
,
p
);
if
(
x
->
aalg
)
RTA_PUT
(
skb
,
XFRMA_ALG_AUTH
,
sizeof
(
*
(
x
->
aalg
)),
x
->
aalg
);
if
(
x
->
ealg
)
RTA_PUT
(
skb
,
XFRMA_ALG_CRYPT
,
sizeof
(
*
(
x
->
ealg
)),
x
->
ealg
);
if
(
x
->
calg
)
RTA_PUT
(
skb
,
XFRMA_ALG_COMP
,
sizeof
(
*
(
x
->
calg
)),
x
->
calg
);
nlh
->
nlmsg_len
=
skb
->
tail
-
b
;
out:
sp
->
this_idx
++
;
return
0
;
nlmsg_failure:
rtattr_failure:
skb_trim
(
skb
,
b
-
skb
->
data
);
return
-
1
;
}
static
int
xfrm_dump_sa
(
struct
sk_buff
*
skb
,
struct
netlink_callback
*
cb
)
{
struct
xfrm_dump_info
info
;
info
.
in_skb
=
cb
->
skb
;
info
.
out_skb
=
skb
;
info
.
nlmsg_seq
=
cb
->
nlh
->
nlmsg_seq
;
info
.
this_idx
=
0
;
info
.
start_idx
=
cb
->
args
[
0
];
(
void
)
xfrm_state_walk
(
IPSEC_PROTO_ANY
,
dump_one_state
,
&
info
);
cb
->
args
[
0
]
=
info
.
this_idx
;
return
skb
->
len
;
}
static
struct
sk_buff
*
xfrm_state_netlink
(
struct
sk_buff
*
in_skb
,
struct
xfrm_state
*
x
,
u32
seq
)
{
struct
xfrm_dump_info
info
;
struct
sk_buff
*
skb
;
skb
=
alloc_skb
(
NLMSG_GOODSIZE
,
GFP_ATOMIC
);
if
(
!
skb
)
return
ERR_PTR
(
-
ENOMEM
);
NETLINK_CB
(
skb
).
dst_pid
=
NETLINK_CB
(
in_skb
).
pid
;
info
.
in_skb
=
in_skb
;
info
.
out_skb
=
skb
;
info
.
nlmsg_seq
=
seq
;
info
.
this_idx
=
info
.
start_idx
=
0
;
if
(
dump_one_state
(
x
,
0
,
&
info
))
{
kfree_skb
(
skb
);
return
NULL
;
}
return
skb
;
}
static
int
xfrm_get_sa
(
struct
sk_buff
*
skb
,
struct
nlmsghdr
*
nlh
,
void
**
xfrma
)
{
struct
xfrm_usersa_id
*
p
=
NLMSG_DATA
(
nlh
);
struct
xfrm_state
*
x
;
struct
sk_buff
*
resp_skb
;
int
err
;
x
=
xfrm_state_lookup
(
p
->
saddr
.
xfrm4_addr
,
p
->
spi
,
p
->
proto
);
err
=
-
ESRCH
;
if
(
x
==
NULL
)
goto
out_noput
;
resp_skb
=
xfrm_state_netlink
(
skb
,
x
,
nlh
->
nlmsg_seq
);
if
(
IS_ERR
(
resp_skb
))
{
err
=
PTR_ERR
(
resp_skb
);
}
else
{
err
=
netlink_unicast
(
xfrm_nl
,
resp_skb
,
NETLINK_CB
(
skb
).
pid
,
MSG_DONTWAIT
);
}
xfrm_state_put
(
x
);
out_noput:
return
err
;
}
static
int
verify_userspi_info
(
struct
xfrm_userspi_info
*
p
)
{
switch
(
p
->
info
.
id
.
proto
)
{
case
IPPROTO_AH
:
case
IPPROTO_ESP
:
break
;
case
IPPROTO_COMP
:
/* IPCOMP spi is 16-bits. */
if
(
p
->
min
>=
0x10000
||
p
->
max
>=
0x10000
)
return
-
EINVAL
;
default:
return
-
EINVAL
;
};
if
(
p
->
min
>
p
->
max
)
return
-
EINVAL
;
return
0
;
}
static
int
xfrm_alloc_userspi
(
struct
sk_buff
*
skb
,
struct
nlmsghdr
*
nlh
,
void
**
xfrma
)
{
struct
xfrm_state
*
x
;
struct
xfrm_userspi_info
*
p
;
struct
sk_buff
*
resp_skb
;
int
err
;
p
=
NLMSG_DATA
(
nlh
);
err
=
verify_userspi_info
(
p
);
if
(
err
)
goto
out_noput
;
x
=
xfrm_find_acq
(
p
->
info
.
mode
,
p
->
info
.
reqid
,
p
->
info
.
id
.
proto
,
p
->
info
.
sel
.
daddr
.
xfrm4_addr
,
p
->
info
.
sel
.
saddr
.
xfrm4_addr
,
1
);
err
=
-
ENOENT
;
if
(
x
==
NULL
)
goto
out_noput
;
resp_skb
=
ERR_PTR
(
-
ENOENT
);
spin_lock_bh
(
&
x
->
lock
);
if
(
x
->
km
.
state
!=
XFRM_STATE_DEAD
)
{
xfrm_alloc_spi
(
x
,
p
->
min
,
p
->
max
);
if
(
x
->
id
.
spi
)
resp_skb
=
xfrm_state_netlink
(
skb
,
x
,
nlh
->
nlmsg_seq
);
}
spin_unlock_bh
(
&
x
->
lock
);
if
(
IS_ERR
(
resp_skb
))
{
err
=
PTR_ERR
(
resp_skb
);
goto
out
;
}
err
=
netlink_unicast
(
xfrm_nl
,
resp_skb
,
NETLINK_CB
(
skb
).
pid
,
MSG_DONTWAIT
);
out:
xfrm_state_put
(
x
);
out_noput:
return
err
;
}
static
int
verify_policy_dir
(
__u8
dir
)
{
switch
(
dir
)
{
case
XFRM_POLICY_IN
:
case
XFRM_POLICY_OUT
:
case
XFRM_POLICY_FWD
:
break
;
default:
return
-
EINVAL
;
};
return
0
;
}
static
int
verify_newpolicy_info
(
struct
xfrm_userpolicy_info
*
p
)
{
switch
(
p
->
share
)
{
case
XFRM_SHARE_ANY
:
case
XFRM_SHARE_SESSION
:
case
XFRM_SHARE_USER
:
case
XFRM_SHARE_UNIQUE
:
break
;
default:
return
-
EINVAL
;
};
switch
(
p
->
action
)
{
case
XFRM_POLICY_ALLOW
:
case
XFRM_POLICY_BLOCK
:
break
;
default:
return
-
EINVAL
;
};
return
verify_policy_dir
(
p
->
dir
);
}
static
void
copy_templates
(
struct
xfrm_policy
*
xp
,
struct
xfrm_user_tmpl
*
ut
,
int
nr
)
{
int
i
;
xp
->
xfrm_nr
=
nr
;
for
(
i
=
0
;
i
<
nr
;
i
++
,
ut
++
)
{
struct
xfrm_tmpl
*
t
=
&
xp
->
xfrm_vec
[
i
];
memcpy
(
&
t
->
id
,
&
ut
->
id
,
sizeof
(
struct
xfrm_id
));
memcpy
(
&
t
->
saddr
,
&
ut
->
saddr
,
sizeof
(
xfrm_address_t
));
t
->
reqid
=
ut
->
reqid
;
t
->
mode
=
ut
->
mode
;
t
->
share
=
ut
->
share
;
t
->
optional
=
ut
->
optional
;
t
->
aalgos
=
ut
->
aalgos
;
t
->
ealgos
=
ut
->
ealgos
;
t
->
calgos
=
ut
->
calgos
;
}
}
static
int
copy_user_tmpl
(
struct
xfrm_policy
*
pol
,
struct
rtattr
**
xfrma
)
{
struct
rtattr
*
rt
=
xfrma
[
XFRMA_TMPL
];
struct
xfrm_user_tmpl
*
utmpl
;
int
nr
;
if
(
!
rt
)
{
pol
->
xfrm_nr
=
0
;
}
else
{
nr
=
(
rt
->
rta_len
-
sizeof
(
*
rt
))
/
sizeof
(
*
utmpl
);
if
(
nr
>
XFRM_MAX_DEPTH
)
return
-
EINVAL
;
copy_templates
(
pol
,
RTA_DATA
(
rt
),
nr
);
}
return
0
;
}
static
void
copy_from_user_policy
(
struct
xfrm_policy
*
xp
,
struct
xfrm_userpolicy_info
*
p
)
{
xp
->
priority
=
p
->
priority
;
xp
->
index
=
p
->
index
;
memcpy
(
&
xp
->
selector
,
&
p
->
sel
,
sizeof
(
xp
->
selector
));
memcpy
(
&
xp
->
lft
,
&
p
->
lft
,
sizeof
(
xp
->
lft
));
xp
->
action
=
p
->
action
;
xp
->
flags
=
p
->
flags
;
xp
->
family
=
p
->
family
;
/* XXX xp->share = p->share; */
}
static
void
copy_to_user_policy
(
struct
xfrm_policy
*
xp
,
struct
xfrm_userpolicy_info
*
p
,
int
dir
)
{
memcpy
(
&
p
->
sel
,
&
xp
->
selector
,
sizeof
(
p
->
sel
));
memcpy
(
&
p
->
lft
,
&
xp
->
lft
,
sizeof
(
p
->
lft
));
memcpy
(
&
p
->
curlft
,
&
xp
->
curlft
,
sizeof
(
p
->
curlft
));
p
->
priority
=
xp
->
priority
;
p
->
index
=
xp
->
index
;
p
->
family
=
xp
->
family
;
p
->
dir
=
dir
;
p
->
action
=
xp
->
action
;
p
->
flags
=
xp
->
flags
;
p
->
share
=
XFRM_SHARE_ANY
;
/* XXX xp->share */
}
static
struct
xfrm_policy
*
xfrm_policy_construct
(
struct
xfrm_userpolicy_info
*
p
,
struct
rtattr
**
xfrma
,
int
*
errp
)
{
struct
xfrm_policy
*
xp
=
xfrm_policy_alloc
(
GFP_KERNEL
);
int
err
;
if
(
!
xp
)
{
*
errp
=
-
ENOMEM
;
return
NULL
;
}
copy_from_user_policy
(
xp
,
p
);
err
=
copy_user_tmpl
(
xp
,
xfrma
);
if
(
err
)
{
*
errp
=
err
;
kfree
(
xp
);
xp
=
NULL
;
}
return
xp
;
}
static
int
xfrm_add_policy
(
struct
sk_buff
*
skb
,
struct
nlmsghdr
*
nlh
,
void
**
xfrma
)
{
struct
xfrm_userpolicy_info
*
p
=
NLMSG_DATA
(
nlh
);
struct
xfrm_policy
*
xp
;
int
err
;
err
=
verify_newpolicy_info
(
p
);
if
(
err
)
return
err
;
xp
=
xfrm_policy_construct
(
p
,
(
struct
rtattr
**
)
xfrma
,
&
err
);
if
(
!
xp
)
return
err
;
err
=
xfrm_policy_insert
(
p
->
dir
,
xp
,
1
);
if
(
err
)
{
kfree
(
xp
);
return
err
;
}
xfrm_pol_put
(
xp
);
return
0
;
}
static
int
xfrm_del_policy
(
struct
sk_buff
*
skb
,
struct
nlmsghdr
*
nlh
,
void
**
xfrma
)
{
struct
xfrm_policy
*
xp
;
struct
xfrm_userpolicy_id
*
p
;
int
err
;
p
=
NLMSG_DATA
(
nlh
);
err
=
verify_policy_dir
(
p
->
dir
);
if
(
err
)
return
err
;
xp
=
xfrm_policy_delete
(
p
->
dir
,
&
p
->
sel
);
if
(
xp
==
NULL
)
return
-
ENOENT
;
xfrm_policy_kill
(
xp
);
xfrm_pol_put
(
xp
);
return
0
;
}
static
int
dump_one_policy
(
struct
xfrm_policy
*
xp
,
int
dir
,
int
count
,
void
*
ptr
)
{
struct
xfrm_dump_info
*
sp
=
ptr
;
struct
xfrm_userpolicy_info
*
p
;
struct
sk_buff
*
in_skb
=
sp
->
in_skb
;
struct
sk_buff
*
skb
=
sp
->
out_skb
;
struct
nlmsghdr
*
nlh
;
unsigned
char
*
b
=
skb
->
tail
;
if
(
sp
->
this_idx
<
sp
->
start_idx
)
goto
out
;
nlh
=
NLMSG_PUT
(
skb
,
NETLINK_CB
(
in_skb
).
pid
,
sp
->
nlmsg_seq
,
XFRM_MSG_NEWPOLICY
,
sizeof
(
*
p
));
p
=
NLMSG_DATA
(
nlh
);
nlh
->
nlmsg_flags
=
0
;
copy_to_user_policy
(
xp
,
p
,
dir
);
if
(
xp
->
xfrm_nr
)
{
struct
xfrm_user_tmpl
vec
[
XFRM_MAX_DEPTH
];
int
i
;
for
(
i
=
0
;
i
<
xp
->
xfrm_nr
;
i
++
)
{
struct
xfrm_user_tmpl
*
up
=
&
vec
[
i
];
struct
xfrm_tmpl
*
kp
=
&
xp
->
xfrm_vec
[
i
];
memcpy
(
&
up
->
id
,
&
kp
->
id
,
sizeof
(
up
->
id
));
memcpy
(
&
up
->
saddr
,
&
kp
->
saddr
,
sizeof
(
up
->
saddr
));
up
->
reqid
=
kp
->
reqid
;
up
->
mode
=
kp
->
mode
;
up
->
share
=
kp
->
share
;
up
->
optional
=
kp
->
optional
;
up
->
aalgos
=
kp
->
aalgos
;
up
->
ealgos
=
kp
->
ealgos
;
up
->
calgos
=
kp
->
calgos
;
}
RTA_PUT
(
skb
,
XFRMA_TMPL
,
(
sizeof
(
struct
xfrm_user_tmpl
)
*
xp
->
xfrm_nr
),
vec
);
}
nlh
->
nlmsg_len
=
skb
->
tail
-
b
;
out:
sp
->
this_idx
++
;
return
0
;
nlmsg_failure:
rtattr_failure:
skb_trim
(
skb
,
b
-
skb
->
data
);
return
-
1
;
}
static
int
xfrm_dump_policy
(
struct
sk_buff
*
skb
,
struct
netlink_callback
*
cb
)
{
struct
xfrm_dump_info
info
;
info
.
in_skb
=
cb
->
skb
;
info
.
out_skb
=
skb
;
info
.
nlmsg_seq
=
cb
->
nlh
->
nlmsg_seq
;
info
.
start_idx
=
cb
->
args
[
0
];
(
void
)
xfrm_policy_walk
(
dump_one_policy
,
&
info
);
cb
->
args
[
0
]
=
info
.
this_idx
;
return
skb
->
len
;
}
static
struct
sk_buff
*
xfrm_policy_netlink
(
struct
sk_buff
*
in_skb
,
struct
xfrm_policy
*
xp
,
int
dir
,
u32
seq
)
{
struct
xfrm_dump_info
info
;
struct
sk_buff
*
skb
;
skb
=
alloc_skb
(
NLMSG_GOODSIZE
,
GFP_KERNEL
);
if
(
!
skb
)
return
ERR_PTR
(
-
ENOMEM
);
NETLINK_CB
(
skb
).
dst_pid
=
NETLINK_CB
(
in_skb
).
pid
;
info
.
in_skb
=
in_skb
;
info
.
out_skb
=
skb
;
info
.
nlmsg_seq
=
seq
;
info
.
this_idx
=
info
.
start_idx
=
0
;
if
(
dump_one_policy
(
xp
,
dir
,
0
,
&
info
)
<
0
)
{
kfree_skb
(
skb
);
return
NULL
;
}
return
skb
;
}
static
int
xfrm_get_policy
(
struct
sk_buff
*
skb
,
struct
nlmsghdr
*
nlh
,
void
**
xfrma
)
{
struct
xfrm_policy
*
xp
;
struct
xfrm_userpolicy_id
*
p
;
struct
sk_buff
*
resp_skb
;
int
err
;
p
=
NLMSG_DATA
(
nlh
);
xp
=
xfrm_policy_byid
(
p
->
dir
,
p
->
index
,
0
);
if
(
xp
==
NULL
)
return
-
ENOENT
;
resp_skb
=
xfrm_policy_netlink
(
skb
,
xp
,
p
->
dir
,
nlh
->
nlmsg_seq
);
if
(
IS_ERR
(
resp_skb
))
{
err
=
PTR_ERR
(
resp_skb
);
}
else
{
err
=
netlink_unicast
(
xfrm_nl
,
resp_skb
,
NETLINK_CB
(
skb
).
pid
,
MSG_DONTWAIT
);
}
xfrm_pol_put
(
xp
);
return
err
;
}
static
const
int
xfrm_msg_min
[(
XFRM_MSG_MAX
+
1
-
XFRM_MSG_BASE
)]
=
{
NLMSG_LENGTH
(
sizeof
(
struct
xfrm_usersa_info
)),
/* NEW SA */
NLMSG_LENGTH
(
sizeof
(
struct
xfrm_usersa_id
)),
/* DEL SA */
NLMSG_LENGTH
(
sizeof
(
struct
xfrm_usersa_id
)),
/* GET SA */
NLMSG_LENGTH
(
sizeof
(
struct
xfrm_userpolicy_info
)),
/* NEW POLICY */
NLMSG_LENGTH
(
sizeof
(
struct
xfrm_userpolicy_id
)),
/* DEL POLICY */
NLMSG_LENGTH
(
sizeof
(
struct
xfrm_userpolicy_id
)),
/* GET POLICY */
NLMSG_LENGTH
(
sizeof
(
struct
xfrm_userspi_info
)),
/* ALLOC SPI */
NLMSG_LENGTH
(
sizeof
(
struct
xfrm_user_acquire
)),
/* ACQUIRE */
NLMSG_LENGTH
(
sizeof
(
struct
xfrm_user_expire
)),
/* EXPIRE */
};
static
struct
xfrm_link
{
int
(
*
doit
)(
struct
sk_buff
*
,
struct
nlmsghdr
*
,
void
**
);
int
(
*
dump
)(
struct
sk_buff
*
,
struct
netlink_callback
*
);
}
xfrm_dispatch
[]
=
{
{
.
doit
=
xfrm_add_sa
,
},
{
.
doit
=
xfrm_del_sa
,
},
{
.
doit
=
xfrm_get_sa
,
.
dump
=
xfrm_dump_sa
,
},
{
.
doit
=
xfrm_add_policy
},
{
.
doit
=
xfrm_del_policy
},
{
.
doit
=
xfrm_get_policy
,
.
dump
=
xfrm_dump_policy
,
},
{
.
doit
=
xfrm_alloc_userspi
},
};
static
int
xfrm_done
(
struct
netlink_callback
*
cb
)
{
return
0
;
}
static
int
xfrm_user_rcv_msg
(
struct
sk_buff
*
skb
,
struct
nlmsghdr
*
nlh
,
int
*
errp
)
{
struct
rtattr
*
xfrma
[
XFRMA_MAX
];
struct
xfrm_link
*
link
;
int
type
,
min_len
,
kind
;
if
(
!
(
nlh
->
nlmsg_flags
&
NLM_F_REQUEST
))
return
0
;
type
=
nlh
->
nlmsg_type
;
/* A control message: ignore them */
if
(
type
<
XFRM_MSG_BASE
)
return
0
;
/* Unknown message: reply with EINVAL */
if
(
type
>
XFRM_MSG_MAX
)
goto
err_einval
;
type
-=
XFRM_MSG_BASE
;
kind
=
(
type
&
3
);
link
=
&
xfrm_dispatch
[
type
];
/* All operations require privileges, even GET */
if
(
!
cap_raised
(
NETLINK_CB
(
skb
).
eff_cap
,
CAP_NET_ADMIN
))
{
*
errp
=
-
EPERM
;
return
-
1
;
}
if
(
kind
==
2
&&
(
nlh
->
nlmsg_flags
&
NLM_F_DUMP
))
{
u32
rlen
;
if
(
link
->
dump
==
NULL
)
goto
err_einval
;
if
((
*
errp
=
netlink_dump_start
(
xfrm_nl
,
skb
,
nlh
,
link
->
dump
,
xfrm_done
))
!=
0
)
{
return
-
1
;
}
rlen
=
NLMSG_ALIGN
(
nlh
->
nlmsg_len
);
if
(
rlen
>
skb
->
len
)
rlen
=
skb
->
len
;
skb_pull
(
skb
,
rlen
);
return
-
1
;
}
memset
(
xfrma
,
0
,
sizeof
(
xfrma
));
if
(
nlh
->
nlmsg_len
<
(
min_len
=
xfrm_msg_min
[
type
]))
goto
err_einval
;
if
(
nlh
->
nlmsg_len
>
min_len
)
{
int
attrlen
=
nlh
->
nlmsg_len
-
NLMSG_ALIGN
(
min_len
);
struct
rtattr
*
attr
=
(
void
*
)
nlh
+
NLMSG_ALIGN
(
min_len
);
while
(
RTA_OK
(
attr
,
attrlen
))
{
unsigned
short
flavor
=
attr
->
rta_type
;
if
(
flavor
)
{
if
(
flavor
>
XFRMA_MAX
)
goto
err_einval
;
xfrma
[
flavor
-
1
]
=
attr
;
}
attr
=
RTA_NEXT
(
attr
,
attrlen
);
}
}
if
(
link
->
doit
==
NULL
)
goto
err_einval
;
*
errp
=
link
->
doit
(
skb
,
nlh
,
(
void
**
)
&
xfrma
);
return
*
errp
;
err_einval:
*
errp
=
-
EINVAL
;
return
-
1
;
}
static
int
xfrm_user_rcv_skb
(
struct
sk_buff
*
skb
)
{
int
err
;
struct
nlmsghdr
*
nlh
;
while
(
skb
->
len
>=
NLMSG_SPACE
(
0
))
{
u32
rlen
;
nlh
=
(
struct
nlmsghdr
*
)
skb
->
data
;
if
(
nlh
->
nlmsg_len
<
sizeof
(
*
nlh
)
||
skb
->
len
<
nlh
->
nlmsg_len
)
return
0
;
rlen
=
NLMSG_ALIGN
(
nlh
->
nlmsg_len
);
if
(
rlen
>
skb
->
len
)
rlen
=
skb
->
len
;
if
(
xfrm_user_rcv_msg
(
skb
,
nlh
,
&
err
))
{
if
(
err
==
0
)
return
-
1
;
netlink_ack
(
skb
,
nlh
,
err
);
}
else
if
(
nlh
->
nlmsg_flags
&
NLM_F_ACK
)
netlink_ack
(
skb
,
nlh
,
0
);
skb_pull
(
skb
,
rlen
);
}
return
0
;
}
static
void
xfrm_netlink_rcv
(
struct
sock
*
sk
,
int
len
)
{
do
{
struct
sk_buff
*
skb
;
down
(
&
xfrm_cfg_sem
);
while
((
skb
=
skb_dequeue
(
&
sk
->
receive_queue
))
!=
NULL
)
{
if
(
xfrm_user_rcv_skb
(
skb
))
{
if
(
skb
->
len
)
skb_queue_head
(
&
sk
->
receive_queue
,
skb
);
else
kfree_skb
(
skb
);
break
;
}
kfree_skb
(
skb
);
}
up
(
&
xfrm_cfg_sem
);
}
while
(
xfrm_nl
&&
xfrm_nl
->
receive_queue
.
qlen
);
}
static
int
build_expire
(
struct
sk_buff
*
skb
,
struct
xfrm_state
*
x
,
int
hard
)
{
struct
xfrm_user_expire
*
ue
;
struct
nlmsghdr
*
nlh
;
unsigned
char
*
b
=
skb
->
tail
;
nlh
=
NLMSG_PUT
(
skb
,
0
,
0
,
XFRM_MSG_EXPIRE
,
sizeof
(
*
ue
));
ue
=
NLMSG_DATA
(
nlh
);
nlh
->
nlmsg_flags
=
0
;
copy_to_user_state
(
x
,
&
ue
->
state
);
ue
->
hard
=
(
hard
!=
0
)
?
1
:
0
;
nlh
->
nlmsg_len
=
skb
->
tail
-
b
;
return
skb
->
len
;
nlmsg_failure:
skb_trim
(
skb
,
b
-
skb
->
data
);
return
-
1
;
}
static
int
xfrm_send_notify
(
struct
xfrm_state
*
x
,
int
hard
)
{
struct
sk_buff
*
skb
;
skb
=
alloc_skb
(
sizeof
(
struct
xfrm_user_expire
)
+
16
,
GFP_ATOMIC
);
if
(
skb
==
NULL
)
return
-
ENOMEM
;
if
(
build_expire
(
skb
,
x
,
hard
)
<
0
)
BUG
();
NETLINK_CB
(
skb
).
dst_groups
=
XFRMGRP_EXPIRE
;
netlink_broadcast
(
xfrm_nl
,
skb
,
0
,
XFRMGRP_EXPIRE
,
GFP_ATOMIC
);
return
0
;
}
/* XXX Make this xfrm_state.c:xfrm_get_acqseq() */
static
u32
get_acqseq
(
void
)
{
u32
res
;
static
u32
acqseq
;
static
spinlock_t
acqseq_lock
=
SPIN_LOCK_UNLOCKED
;
spin_lock_bh
(
&
acqseq_lock
);
res
=
(
++
acqseq
?
:
++
acqseq
);
spin_unlock_bh
(
&
acqseq_lock
);
return
res
;
}
static
int
build_acquire
(
struct
sk_buff
*
skb
,
struct
xfrm_state
*
x
,
struct
xfrm_tmpl
*
xt
,
struct
xfrm_policy
*
xp
,
int
dir
)
{
struct
xfrm_user_acquire
*
ua
;
struct
nlmsghdr
*
nlh
;
unsigned
char
*
b
=
skb
->
tail
;
__u32
seq
=
get_acqseq
();
nlh
=
NLMSG_PUT
(
skb
,
0
,
0
,
XFRM_MSG_ACQUIRE
,
sizeof
(
*
ua
));
ua
=
NLMSG_DATA
(
nlh
);
nlh
->
nlmsg_flags
=
0
;
memcpy
(
&
ua
->
id
,
&
x
->
id
,
sizeof
(
ua
->
id
));
memcpy
(
&
ua
->
saddr
,
&
x
->
props
.
saddr
,
sizeof
(
ua
->
saddr
));
copy_to_user_policy
(
xp
,
&
ua
->
policy
,
dir
);
ua
->
aalgos
=
xt
->
aalgos
;
ua
->
ealgos
=
xt
->
ealgos
;
ua
->
calgos
=
xt
->
calgos
;
ua
->
seq
=
x
->
km
.
seq
=
seq
;
nlh
->
nlmsg_len
=
skb
->
tail
-
b
;
return
skb
->
len
;
nlmsg_failure:
skb_trim
(
skb
,
b
-
skb
->
data
);
return
-
1
;
}
static
int
xfrm_send_acquire
(
struct
xfrm_state
*
x
,
struct
xfrm_tmpl
*
xt
,
struct
xfrm_policy
*
xp
,
int
dir
)
{
struct
sk_buff
*
skb
;
skb
=
alloc_skb
(
sizeof
(
struct
xfrm_user_acquire
)
+
16
,
GFP_ATOMIC
);
if
(
skb
==
NULL
)
return
-
ENOMEM
;
if
(
build_acquire
(
skb
,
x
,
xt
,
xp
,
dir
)
<
0
)
BUG
();
NETLINK_CB
(
skb
).
dst_groups
=
XFRMGRP_ACQUIRE
;
netlink_broadcast
(
xfrm_nl
,
skb
,
0
,
XFRMGRP_ACQUIRE
,
GFP_ATOMIC
);
return
0
;
}
/* User gives us xfrm_user_policy_info followed by an array of 0
* or more templates.
*/
struct
xfrm_policy
*
xfrm_compile_policy
(
int
opt
,
u8
*
data
,
int
len
,
int
*
dir
)
{
struct
xfrm_userpolicy_info
*
p
=
(
struct
xfrm_userpolicy_info
*
)
data
;
struct
xfrm_user_tmpl
*
ut
=
(
struct
xfrm_user_tmpl
*
)
(
p
+
1
);
struct
xfrm_policy
*
xp
;
int
nr
;
if
(
opt
!=
IP_XFRM_POLICY
)
{
*
dir
=
-
EOPNOTSUPP
;
return
NULL
;
}
*
dir
=
-
EINVAL
;
if
(
len
<
sizeof
(
*
p
)
||
verify_newpolicy_info
(
p
))
return
NULL
;
nr
=
((
len
-
sizeof
(
*
p
))
/
sizeof
(
*
ut
));
if
(
nr
>
XFRM_MAX_DEPTH
)
return
NULL
;
xp
=
xfrm_policy_alloc
(
GFP_KERNEL
);
if
(
xp
==
NULL
)
{
*
dir
=
-
ENOBUFS
;
return
NULL
;
}
copy_from_user_policy
(
xp
,
p
);
copy_templates
(
xp
,
ut
,
nr
);
*
dir
=
p
->
dir
;
return
xp
;
}
static
struct
xfrm_mgr
netlink_mgr
=
{
.
id
=
"netlink"
,
.
notify
=
xfrm_send_notify
,
.
acquire
=
xfrm_send_acquire
,
.
compile_policy
=
xfrm_compile_policy
,
};
static
int
__init
xfrm_user_init
(
void
)
{
printk
(
KERN_INFO
"Initializing IPsec netlink socket
\n
"
);
xfrm_nl
=
netlink_kernel_create
(
NETLINK_XFRM
,
xfrm_netlink_rcv
);
if
(
xfrm_nl
==
NULL
)
panic
(
"xfrm_user_init: cannot initialize xfrm_nl
\n
"
);
xfrm_register_km
(
&
netlink_mgr
);
return
0
;
}
static
void
__exit
xfrm_user_exit
(
void
)
{
xfrm_unregister_km
(
&
netlink_mgr
);
sock_release
(
xfrm_nl
->
socket
);
}
module_init
(
xfrm_user_init
);
module_exit
(
xfrm_user_exit
);
net/ipv6/mcast.c
View file @
6ccc3e25
...
...
@@ -296,6 +296,7 @@ int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
}
memset
(
mc
,
0
,
sizeof
(
struct
ifmcaddr6
));
init_timer
(
&
mc
->
mca_timer
);
mc
->
mca_timer
.
function
=
igmp6_timer_handler
;
mc
->
mca_timer
.
data
=
(
unsigned
long
)
mc
;
...
...
net/irda/af_irda.c
View file @
6ccc3e25
...
...
@@ -2364,6 +2364,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
/* Set watchdog timer to expire in <val> ms. */
self
->
errno
=
0
;
init_timer
(
&
self
->
watchdog
);
self
->
watchdog
.
function
=
irda_discovery_timeout
;
self
->
watchdog
.
data
=
(
unsigned
long
)
self
;
self
->
watchdog
.
expires
=
jiffies
+
(
val
*
HZ
/
1000
);
...
...
net/key/af_key.c
View file @
6ccc3e25
...
...
@@ -528,8 +528,7 @@ static struct xfrm_state *pfkey_xfrm_state_lookup(struct sadb_msg *hdr, void **
switch
(((
struct
sockaddr
*
)(
addr
+
1
))
->
sa_family
)
{
case
AF_INET
:
x
=
xfrm_state_lookup
(
((
struct
sockaddr_in
*
)(
addr
+
1
))
->
sin_addr
.
s_addr
,
x
=
xfrm_state_lookup
(((
struct
sockaddr_in
*
)(
addr
+
1
))
->
sin_addr
.
s_addr
,
sa
->
sadb_sa_spi
,
proto
);
break
;
case
AF_INET6
:
...
...
@@ -1043,7 +1042,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
daddr
=
(
struct
sockaddr_in
*
)(
addr
+
1
);
x
=
xfrm_find_acq
(
mode
,
reqid
,
proto
,
daddr
->
sin_addr
.
s_addr
,
saddr
->
sin_addr
.
s_addr
);
saddr
->
sin_addr
.
s_addr
,
1
);
if
(
x
==
NULL
)
return
-
ENOENT
;
...
...
@@ -1122,7 +1121,17 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
/* XXX there is race condition */
x1
=
pfkey_xfrm_state_lookup
(
hdr
,
ext_hdrs
);
if
(
x1
&&
hdr
->
sadb_msg_type
==
SADB_ADD
)
{
if
(
!
x1
)
{
x1
=
xfrm_find_acq
(
x
->
props
.
mode
,
x
->
props
.
reqid
,
x
->
id
.
proto
,
x
->
id
.
daddr
.
xfrm4_addr
,
x
->
props
.
saddr
.
xfrm4_addr
,
0
);
if
(
x1
&&
x1
->
id
.
spi
!=
x
->
id
.
spi
&&
x1
->
id
.
spi
)
{
xfrm_state_put
(
x1
);
x1
=
NULL
;
}
}
if
(
x1
&&
x1
->
id
.
spi
&&
hdr
->
sadb_msg_type
==
SADB_ADD
)
{
x
->
km
.
state
=
XFRM_STATE_DEAD
;
xfrm_state_put
(
x
);
xfrm_state_put
(
x1
);
...
...
@@ -1131,7 +1140,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
xfrm_state_insert
(
x
);
if
(
x1
&&
hdr
->
sadb_msg_type
!=
SADB_ADD
)
{
if
(
x1
)
{
xfrm_state_delete
(
x1
);
xfrm_state_put
(
x1
);
}
...
...
@@ -1225,7 +1234,7 @@ static struct sk_buff *compose_sadb_supported(struct sadb_msg *orig, int allocat
esp_len
+=
sizeof
(
struct
sadb_supported
);
len
=
esp_len
+
ah_len
+
sizeof
(
struct
sadb_msg
);
skb
=
alloc_skb
(
allocation
,
len
+
16
);
skb
=
alloc_skb
(
len
+
16
,
allocation
);
if
(
!
skb
)
goto
out_put_algs
;
...
...
@@ -2156,7 +2165,7 @@ static struct xfrm_policy *pfkey_compile_policy(int opt, u8 *data, int len, int
(
!
pol
->
sadb_x_policy_dir
||
pol
->
sadb_x_policy_dir
>
IPSEC_DIR_OUTBOUND
))
return
NULL
;
xp
=
xfrm_policy_alloc
(
GFP_
KERNEL
);
xp
=
xfrm_policy_alloc
(
GFP_
ATOMIC
);
if
(
xp
==
NULL
)
{
*
dir
=
-
ENOBUFS
;
return
NULL
;
...
...
net/llc/llc_main.c
View file @
6ccc3e25
...
...
@@ -181,18 +181,22 @@ int llc_sk_init(struct sock* sk)
llc
->
inc_cntr
=
llc
->
dec_cntr
=
2
;
llc
->
dec_step
=
llc
->
connect_step
=
1
;
init_timer
(
&
llc
->
ack_timer
);
llc
->
ack_timer
.
expire
=
LLC_ACK_TIME
;
llc
->
ack_timer
.
timer
.
data
=
(
unsigned
long
)
sk
;
llc
->
ack_timer
.
timer
.
function
=
llc_conn_ack_tmr_cb
;
init_timer
(
&
llc
->
pf_cycle_timer
);
llc
->
pf_cycle_timer
.
expire
=
LLC_P_TIME
;
llc
->
pf_cycle_timer
.
timer
.
data
=
(
unsigned
long
)
sk
;
llc
->
pf_cycle_timer
.
timer
.
function
=
llc_conn_pf_cycle_tmr_cb
;
init_timer
(
&
llc
->
rej_sent_timer
);
llc
->
rej_sent_timer
.
expire
=
LLC_REJ_TIME
;
llc
->
rej_sent_timer
.
timer
.
data
=
(
unsigned
long
)
sk
;
llc
->
rej_sent_timer
.
timer
.
function
=
llc_conn_rej_tmr_cb
;
init_timer
(
&
llc
->
busy_state_timer
);
llc
->
busy_state_timer
.
expire
=
LLC_BUSY_TIME
;
llc
->
busy_state_timer
.
timer
.
data
=
(
unsigned
long
)
sk
;
llc
->
busy_state_timer
.
timer
.
function
=
llc_conn_busy_tmr_cb
;
...
...
@@ -552,6 +556,7 @@ static int __init llc_init(void)
skb_queue_head_init
(
&
llc_main_station
.
mac_pdu_q
);
skb_queue_head_init
(
&
llc_main_station
.
ev_q
.
list
);
spin_lock_init
(
&
llc_main_station
.
ev_q
.
lock
);
init_timer
(
&
llc_main_station
.
ack_timer
);
llc_main_station
.
ack_timer
.
data
=
(
unsigned
long
)
&
llc_main_station
;
llc_main_station
.
ack_timer
.
function
=
llc_station_ack_tmr_cb
;
...
...
net/sched/sch_sfq.c
View file @
6ccc3e25
...
...
@@ -411,9 +411,9 @@ static int sfq_init(struct Qdisc *sch, struct rtattr *opt)
struct
sfq_sched_data
*
q
=
(
struct
sfq_sched_data
*
)
sch
->
data
;
int
i
;
init_timer
(
&
q
->
perturb_timer
);
q
->
perturb_timer
.
data
=
(
unsigned
long
)
sch
;
q
->
perturb_timer
.
function
=
sfq_perturbation
;
init_timer
(
&
q
->
perturb_timer
);
for
(
i
=
0
;
i
<
SFQ_HASH_DIVISOR
;
i
++
)
q
->
ht
[
i
]
=
SFQ_DEPTH
;
...
...
net/socket.c
View file @
6ccc3e25
...
...
@@ -66,6 +66,7 @@
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/wanrouter.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
...
...
@@ -1839,29 +1840,19 @@ void __init sock_init(void)
#endif
}
int
socket_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
#ifdef CONFIG_PROC_FS
void
socket_seq_show
(
struct
seq_file
*
seq
)
{
int
len
,
cpu
;
int
cpu
;
int
counter
=
0
;
for
(
cpu
=
0
;
cpu
<
NR_CPUS
;
cpu
++
)
for
(
cpu
=
0
;
cpu
<
NR_CPUS
;
cpu
++
)
counter
+=
sockets_in_use
[
cpu
].
counter
;
/* It can be negative, by the way. 8) */
if
(
counter
<
0
)
counter
=
0
;
len
=
sprintf
(
buffer
,
"sockets: used %d
\n
"
,
counter
);
if
(
offset
>=
len
)
{
*
start
=
buffer
;
return
0
;
}
*
start
=
buffer
+
offset
;
len
-=
offset
;
if
(
len
>
length
)
len
=
length
;
if
(
len
<
0
)
len
=
0
;
return
len
;
seq_printf
(
seq
,
"sockets: used %d
\n
"
,
counter
);
}
#endif
/* CONFIG_PROC_FS */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment