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
Kirill Smelkov
linux
Commits
ac3ebbfb
Commit
ac3ebbfb
authored
Oct 08, 2002
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge nuts.ninka.net:/home/davem/src/BK/network-2.5
into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents
225e7f58
e442c99d
Changes
31
Hide whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
781 additions
and
613 deletions
+781
-613
Documentation/networking/decnet.txt
Documentation/networking/decnet.txt
+70
-5
include/net/dn.h
include/net/dn.h
+0
-1
include/net/dn_dev.h
include/net/dn_dev.h
+5
-3
include/net/dn_route.h
include/net/dn_route.h
+2
-2
include/net/protocol.h
include/net/protocol.h
+5
-15
include/net/raw.h
include/net/raw.h
+1
-1
include/net/rawv6.h
include/net/rawv6.h
+1
-3
net/decnet/TODO
net/decnet/TODO
+3
-4
net/decnet/af_decnet.c
net/decnet/af_decnet.c
+64
-72
net/decnet/dn_dev.c
net/decnet/dn_dev.c
+258
-46
net/decnet/dn_neigh.c
net/decnet/dn_neigh.c
+4
-1
net/decnet/dn_route.c
net/decnet/dn_route.c
+23
-6
net/decnet/sysctl_net_decnet.c
net/decnet/sysctl_net_decnet.c
+139
-51
net/ipv4/af_inet.c
net/ipv4/af_inet.c
+30
-9
net/ipv4/icmp.c
net/ipv4/icmp.c
+3
-16
net/ipv4/ip_gre.c
net/ipv4/ip_gre.c
+8
-9
net/ipv4/ip_input.c
net/ipv4/ip_input.c
+19
-54
net/ipv4/ipip.c
net/ipv4/ipip.c
+8
-6
net/ipv4/ipmr.c
net/ipv4/ipmr.c
+12
-14
net/ipv4/protocol.c
net/ipv4/protocol.c
+24
-106
net/ipv4/raw.c
net/ipv4/raw.c
+8
-18
net/ipv6/addrconf.c
net/ipv6/addrconf.c
+6
-6
net/ipv6/icmp.c
net/ipv6/icmp.c
+12
-20
net/ipv6/ip6_input.c
net/ipv6/ip6_input.c
+15
-31
net/ipv6/protocol.c
net/ipv6/protocol.c
+20
-55
net/ipv6/raw.c
net/ipv6/raw.c
+11
-21
net/ipv6/sit.c
net/ipv6/sit.c
+8
-9
net/ipv6/tcp_ipv6.c
net/ipv6/tcp_ipv6.c
+5
-7
net/ipv6/udp.c
net/ipv6/udp.c
+4
-5
net/sctp/ipv6.c
net/sctp/ipv6.c
+5
-8
net/sctp/protocol.c
net/sctp/protocol.c
+8
-9
No files found.
Documentation/networking/decnet.txt
View file @
ac3ebbfb
...
...
@@ -28,8 +28,36 @@ Don't turn on SIOCGIFCONF support for DECnet unless you are really sure
that you need it, in general you won't and it can cause ifconfig to
malfunction.
Run time configuration has changed slightly from the 2.4 system. If you
want to configure an endnode, then the simplified procedure is as follows:
o Set the MAC address on your ethernet card before starting _any_ other
network protocols.
As soon as your network card is brought into the UP state, DECnet should
start working. If you need something more complicated or are unsure how
to set the MAC address, see the next section. Also all configurations which
worked with 2.4 will work under 2.5 with no change.
3) Command line options
You can set a DECnet address on the kernel command line for compatibility
with the 2.4 configuration procedure, but in general its not needed any more.
If you do st a DECnet address on the command line, it has only one purpose
which is that its added to the addresses on the loopback device.
With 2.4 kernels, DECnet would only recognise addresses as local if they
were added to the loopback device. In 2.5, any local interface address
can be used to loop back to the local machine. Of course this does not
prevent you adding further addresses to the loopback device if you
want to.
N.B. Since the address list of an interface determines the addresses for
which "hello" messages are sent, if you don't set an address on the loopback
interface then you won't see any entries in /proc/net/neigh for the local
host until such time as you start a connection. This doesn't affect the
operation of the local communications in any other way though.
The kernel command line takes options looking like the following:
decnet=1,2
...
...
@@ -51,7 +79,7 @@ parameters.
Currently the only supported devices are ethernet and ip_gre. The
ethernet address of your ethernet card has to be set according to the DECnet
address of the node in order for it to be
recognised (and thus
appear in
address of the node in order for it to be
autoconfigured (and then
appear in
/proc/net/decnet_dev). There is a utility available at the above
FTP sites called dn2ethaddr which can compute the correct ethernet
address to use. The address can be set by ifconfig either before at
...
...
@@ -61,14 +89,22 @@ add the line:
MACADDR=AA:00:04:00:03:04
or something similar, to /etc/sysconfig/network-scripts/ifcfg-eth0 or
wherever your network card's configuration lives.
wherever your network card's configuration lives. Setting the MAC address
of your ethernet card to an address starting with "hi-ord" will cause a
DECnet address which matches to be added to the interface (which you can
verify with iproute2).
You will also need to set /proc/sys/net/decnet/default_device to the
The default device for routing can be set through the /proc filesystem
by setting /proc/sys/net/decnet/default_device to the
device you want DECnet to route packets out of when no specific route
is available. Usually this will be eth0, for example:
echo -n "eth0" >/proc/sys/net/decnet/default_device
If you don't set the default device, then it will default to the first
ethernet card which has been autoconfigured as described above. You can
confirm that by looking in the default_device file of course.
There is a list of what the other files under /proc/sys/net/decnet/ do
on the kernel patch web site (shown above).
...
...
@@ -149,7 +185,36 @@ information (_most_ of which _is_ _essential_) includes:
You may also need to increase the length grabbed with the -s flag. The
-e flag also provides very useful information (ethernet MAC addresses))
7) Mailing list
7) MAC FAQ
A quick FAQ on ethernet MAC addresses to explain how Linux and DECnet
interact and how to get the best performance from your hardware.
Ethernet cards are designed to normally only pass received network frames
to a host computer when they are addressed to it, or to the broadcast address.
Linux has an interface which allows the setting of extra addresses for
an ethernet card to listen to. If the ethernet card supports it, the
filtering operation will be done in hardware, if not the extra unwanted packets
received will be discarded by the host computer. In the latter case,
significant processor time and bus bandwidth can be used up on a busy
network (see the NAPI documentation for a longer explanation of these
effects).
DECnet makes use of this interface to allow running DECnet on an ethernet
card which has already been configured using TCP/IP (presumably using the
built in MAC address of the card, as usual) and/or to allow multiple DECnet
addresses on each physical interface. If you do this, be aware that if your
ethernet card doesn't support perfect hashing in its MAC address filter
then your computer will be doing more work than required. Some cards
will simply set themselves into promiscuous mode in order to receive
packets from the DECnet specified addresses. So if you have one of these
cards its better to set the MAC address of the card as described above
to gain the best efficiency. Better still is to use a card which supports
NAPI as well.
8) Mailing list
If you are keen to get involved in development, or want to ask questions
about configuration, or even just report bugs, then there is a mailing
...
...
@@ -157,7 +222,7 @@ list that you can join, details are at:
http://sourceforge.net/mail/?group_id=4993
8
) Legal Info
9
) Legal Info
The Linux DECnet project team have placed their code under the GPL. The
software is provided "as is" and without warranty express or implied.
...
...
include/net/dn.h
View file @
ac3ebbfb
...
...
@@ -211,7 +211,6 @@ extern void dn_start_fast_timer(struct sock *sk);
extern
void
dn_stop_fast_timer
(
struct
sock
*
sk
);
extern
dn_address
decnet_address
;
extern
unsigned
char
decnet_ether_address
[
6
];
extern
int
decnet_debug_level
;
extern
int
decnet_time_wait
;
extern
int
decnet_dn_count
;
...
...
include/net/dn_dev.h
View file @
ac3ebbfb
...
...
@@ -57,7 +57,7 @@ struct dn_ifaddr {
* up() - Called to initialize device, return value can veto use of
* device with DECnet.
* down() - Called to turn device off when it goes down
* timer3() - Called when timer 3 goes off
* timer3() - Called
once for each ifaddr
when timer 3 goes off
*
* sysctl - Hook for sysctl things
*
...
...
@@ -78,7 +78,7 @@ struct dn_dev_parms {
int
ctl_name
;
/* Index for sysctl */
int
(
*
up
)(
struct
net_device
*
);
void
(
*
down
)(
struct
net_device
*
);
void
(
*
timer3
)(
struct
net_device
*
);
void
(
*
timer3
)(
struct
net_device
*
,
struct
dn_ifaddr
*
ifa
);
void
*
sysctl
;
};
...
...
@@ -167,7 +167,9 @@ extern void dn_dev_hello(struct sk_buff *skb);
extern
void
dn_dev_up
(
struct
net_device
*
);
extern
void
dn_dev_down
(
struct
net_device
*
);
extern
struct
net_device
*
decnet_default_device
;
extern
int
dn_dev_set_default
(
struct
net_device
*
dev
,
int
force
);
extern
struct
net_device
*
dn_dev_get_default
(
void
);
extern
int
dn_dev_bind_default
(
dn_address
*
addr
);
static
__inline__
int
dn_dev_islocal
(
struct
net_device
*
dev
,
dn_address
addr
)
{
...
...
include/net/dn_route.h
View file @
ac3ebbfb
...
...
@@ -96,7 +96,7 @@ static inline void dn_rt_send(struct sk_buff *skb)
dev_queue_xmit
(
skb
);
}
static
inline
void
dn_rt_finish_output
(
struct
sk_buff
*
skb
,
char
*
dst
)
static
inline
void
dn_rt_finish_output
(
struct
sk_buff
*
skb
,
char
*
dst
,
char
*
src
)
{
struct
net_device
*
dev
=
skb
->
dev
;
...
...
@@ -104,7 +104,7 @@ static inline void dn_rt_finish_output(struct sk_buff *skb, char *dst)
dst
=
NULL
;
if
(
!
dev
->
hard_header
||
(
dev
->
hard_header
(
skb
,
dev
,
ETH_P_DNA_RT
,
dst
,
NULL
,
skb
->
len
)
>=
0
))
dst
,
src
,
skb
->
len
)
>=
0
))
dn_rt_send
(
skb
);
else
kfree_skb
(
skb
);
...
...
include/net/protocol.h
View file @
ac3ebbfb
...
...
@@ -30,7 +30,7 @@
#include <linux/ipv6.h>
#endif
#define MAX_INET_PROTOS
32
/* Must be a power of 2 */
#define MAX_INET_PROTOS
256
/* Must be a power of 2 */
/* This is used to register protocols. */
...
...
@@ -38,11 +38,6 @@ struct inet_protocol
{
int
(
*
handler
)(
struct
sk_buff
*
skb
);
void
(
*
err_handler
)(
struct
sk_buff
*
skb
,
u32
info
);
struct
inet_protocol
*
next
;
unsigned
char
protocol
;
unsigned
char
copy
:
1
;
void
*
data
;
const
char
*
name
;
};
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
...
...
@@ -54,11 +49,6 @@ struct inet6_protocol
struct
inet6_skb_parm
*
opt
,
int
type
,
int
code
,
int
offset
,
__u32
info
);
struct
inet6_protocol
*
next
;
unsigned
char
protocol
;
unsigned
char
copy
:
1
;
void
*
data
;
const
char
*
name
;
};
#endif
...
...
@@ -93,14 +83,14 @@ extern struct inet6_protocol *inet6_protos[MAX_INET_PROTOS];
extern
struct
list_head
inetsw6
[
SOCK_MAX
];
#endif
extern
void
inet_add_protocol
(
struct
inet_protocol
*
prot
);
extern
int
inet_del_protocol
(
struct
inet_protocol
*
prot
);
extern
int
inet_add_protocol
(
struct
inet_protocol
*
prot
,
unsigned
char
num
);
extern
int
inet_del_protocol
(
struct
inet_protocol
*
prot
,
unsigned
char
num
);
extern
void
inet_register_protosw
(
struct
inet_protosw
*
p
);
extern
void
inet_unregister_protosw
(
struct
inet_protosw
*
p
);
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
extern
void
inet6_add_protocol
(
struct
inet6_protocol
*
prot
);
extern
int
inet6_del_protocol
(
struct
inet6_protocol
*
prot
);
extern
int
inet6_add_protocol
(
struct
inet6_protocol
*
prot
,
unsigned
char
num
);
extern
int
inet6_del_protocol
(
struct
inet6_protocol
*
prot
,
unsigned
char
num
);
extern
void
inet6_register_protosw
(
struct
inet_protosw
*
p
);
extern
void
inet6_unregister_protosw
(
struct
inet_protosw
*
p
);
#endif
...
...
include/net/raw.h
View file @
ac3ebbfb
...
...
@@ -37,6 +37,6 @@ extern struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
unsigned
long
raddr
,
unsigned
long
laddr
,
int
dif
);
extern
struct
sock
*
raw_v4_input
(
struct
sk_buff
*
skb
,
struct
iphdr
*
iph
,
int
hash
);
extern
void
raw_v4_input
(
struct
sk_buff
*
skb
,
struct
iphdr
*
iph
,
int
hash
);
#endif
/* _RAW_H */
include/net/rawv6.h
View file @
ac3ebbfb
...
...
@@ -7,9 +7,7 @@
extern
struct
sock
*
raw_v6_htable
[
RAWV6_HTABLE_SIZE
];
extern
rwlock_t
raw_v6_lock
;
extern
struct
sock
*
ipv6_raw_deliver
(
struct
sk_buff
*
skb
,
int
nexthdr
);
extern
void
ipv6_raw_deliver
(
struct
sk_buff
*
skb
,
int
nexthdr
);
extern
struct
sock
*
__raw_v6_lookup
(
struct
sock
*
sk
,
unsigned
short
num
,
struct
in6_addr
*
loc_addr
,
struct
in6_addr
*
rmt_addr
);
...
...
net/decnet/TODO
View file @
ac3ebbfb
...
...
@@ -35,14 +35,11 @@ Steve's quick list of things that need finishing off:
file)
o Find all the commonality between DECnet and IPv4 routing code and extract
it into a small library of routines. [probably a project for 2.
5
.xx]
it into a small library of routines. [probably a project for 2.
7
.xx]
o Test ip_gre tunneling works... it did the last time I tested it and it
will have to if I'm to test routing properly.
o Hello messages should be generated for each primary address on each
interface.
o Add the routing message grabbing netfilter module [written, tested,
awaiting merge]
...
...
@@ -55,3 +52,5 @@ Steve's quick list of things that need finishing off:
o DECnet sendpages() function
o AIO for DECnet
net/decnet/af_decnet.c
View file @
ac3ebbfb
...
...
@@ -100,6 +100,7 @@ Version 0.0.6 2.1.110 07-aug-98 Eduardo Marcelo Serrat
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
...
...
@@ -131,21 +132,20 @@ Version 0.0.6 2.1.110 07-aug-98 Eduardo Marcelo Serrat
#include <net/dn_fib.h>
#include <net/dn_neigh.h>
static
void
dn_keepalive
(
struct
sock
*
sk
);
struct
dn_sock
{
struct
sock
sk
;
struct
dn_scp
scp
;
};
/*
* decnet_address is kept in network order, decnet_ether_address is kept
* as a string of bytes.
*/
dn_address
decnet_address
=
0
;
unsigned
char
decnet_ether_address
[
ETH_ALEN
]
=
{
0xAA
,
0x00
,
0x04
,
0x00
,
0x00
,
0x00
};
static
void
dn_keepalive
(
struct
sock
*
sk
);
#define DN_SK_HASH_SHIFT 8
#define DN_SK_HASH_SIZE (1 << DN_SK_HASH_SHIFT)
#define DN_SK_HASH_MASK (DN_SK_HASH_SIZE - 1)
static
kmem_cache_t
*
dn_sk_cachep
;
static
struct
proto_ops
dn_proto_ops
;
rwlock_t
dn_hash_lock
=
RW_LOCK_UNLOCKED
;
static
rwlock_t
dn_hash_lock
=
RW_LOCK_UNLOCKED
;
static
struct
sock
*
dn_sk_hash
[
DN_SK_HASH_SIZE
];
static
struct
sock
*
dn_wild_sk
;
...
...
@@ -473,17 +473,16 @@ struct sock *dn_alloc_sock(struct socket *sock, int gfp)
struct
sock
*
sk
;
struct
dn_scp
*
scp
;
if
((
sk
=
sk_alloc
(
PF_DECnet
,
gfp
,
1
,
NULL
))
==
NULL
)
if
((
sk
=
sk_alloc
(
PF_DECnet
,
gfp
,
sizeof
(
struct
dn_sock
),
dn_sk_cachep
))
==
NULL
)
goto
no_sock
;
scp
=
kmalloc
(
sizeof
(
*
scp
),
gfp
);
if
(
!
scp
)
goto
free_sock
;
scp
=
(
struct
dn_scp
*
)(
sk
+
1
);
DN_SK
(
sk
)
=
scp
;
if
(
sock
)
{
sock
->
ops
=
&
dn_proto_ops
;
}
sock_init_data
(
sock
,
sk
);
DN_SK
(
sk
)
=
scp
;
sk
->
backlog_rcv
=
dn_nsp_backlog_rcv
;
sk
->
destruct
=
dn_destruct
;
...
...
@@ -544,8 +543,7 @@ struct sock *dn_alloc_sock(struct socket *sock, int gfp)
MOD_INC_USE_COUNT
;
return
sk
;
free_sock:
sk_free
(
sk
);
no_sock:
return
NULL
;
}
...
...
@@ -771,9 +769,6 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
struct
net_device
*
dev
;
int
rv
;
if
(
sk
->
zapped
==
0
)
return
-
EINVAL
;
if
(
addr_len
!=
sizeof
(
struct
sockaddr_dn
))
return
-
EINVAL
;
...
...
@@ -783,19 +778,30 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
if
(
dn_ntohs
(
saddr
->
sdn_nodeaddrl
)
&&
(
dn_ntohs
(
saddr
->
sdn_nodeaddrl
)
!=
2
))
return
-
EINVAL
;
if
(
saddr
->
sdn_objnum
&&
!
capable
(
CAP_NET_BIND_SERVICE
))
return
-
EPERM
;
if
(
dn_ntohs
(
saddr
->
sdn_objnamel
)
>
DN_MAXOBJL
)
return
-
EINVAL
;
if
(
saddr
->
sdn_flags
&
~
SDF_WILD
)
return
-
EINVAL
;
if
(
saddr
->
sdn_flags
&
SDF_WILD
)
{
if
(
!
capable
(
CAP_NET_BIND_SERVICE
))
return
-
EPERM
;
}
else
{
#if 1
if
((
!
capable
(
CAP_NET_BIND_SERVICE
)
&&
saddr
->
sdn_objnum
)
||
(
saddr
->
sdn_flags
&
SDF_WILD
))
return
-
EACCES
;
#else
/*
* Maybe put the default actions in the default security ops for
* dn_prot_sock ? Would be nice if the capable call would go there
* too.
*/
if
(
security_ops
->
dn_prot_sock
(
saddr
)
&&
!
capable
(
CAP_NET_BIND_SERVICE
)
||
saddr
->
sdn_objnum
||
(
saddr
->
sdn_flags
&
SDF_WILD
))
return
-
EACCES
;
#endif
if
(
!
(
saddr
->
sdn_flags
&
SDF_WILD
))
{
if
(
dn_ntohs
(
saddr
->
sdn_nodeaddrl
))
{
read_lock
(
&
dev_base_lock
);
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
...
...
@@ -810,12 +816,18 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
}
}
rv
=
-
EINVAL
;
lock_sock
(
sk
);
if
(
sk
->
zapped
!=
0
)
{
memcpy
(
&
scp
->
addr
,
saddr
,
addr_len
);
sk
->
zapped
=
0
;
memcpy
(
&
scp
->
addr
,
saddr
,
addr_len
);
sk
->
zapped
=
0
;
if
((
rv
=
dn_hash_sock
(
sk
))
!=
0
)
sk
->
zapped
=
1
;
rv
=
dn_hash_sock
(
sk
);
if
(
rv
)
{
sk
->
zapped
=
1
;
}
}
release_sock
(
sk
);
return
rv
;
}
...
...
@@ -825,6 +837,7 @@ static int dn_auto_bind(struct socket *sock)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
dn_scp
*
scp
=
DN_SK
(
sk
);
int
rv
;
sk
->
zapped
=
0
;
...
...
@@ -844,13 +857,18 @@ static int dn_auto_bind(struct socket *sock)
scp
->
accessdata
.
acc_accl
=
0
;
memset
(
scp
->
accessdata
.
acc_acc
,
0
,
40
);
}
/* End of compatibility stuff */
scp
->
addr
.
sdn_add
.
a_len
=
dn_htons
(
2
);
*
(
dn_address
*
)
scp
->
addr
.
sdn_add
.
a_addr
=
decnet_address
;
dn_hash_sock
(
sk
);
rv
=
dn_dev_bind_default
((
dn_address
*
)
scp
->
addr
.
sdn_add
.
a_addr
);
if
(
rv
==
0
)
{
rv
=
dn_hash_sock
(
sk
);
if
(
rv
)
{
sk
->
zapped
=
1
;
}
}
return
0
;
return
rv
;
}
...
...
@@ -1209,6 +1227,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return
dn_fib_ioctl
(
sock
,
cmd
,
arg
);
#endif
/* CONFIG_DECNET_ROUTER */
#if 0
case OSIOCSNETADDR:
if (!capable(CAP_NET_ADMIN)) {
err = -EPERM;
...
...
@@ -1218,7 +1237,6 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
dn_dev_devices_off();
decnet_address = (unsigned short)arg;
dn_dn2eth
(
decnet_ether_address
,
dn_ntohs
(
decnet_address
));
dn_dev_devices_on();
err = 0;
...
...
@@ -1227,6 +1245,7 @@ static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case OSIOCGNETADDR:
err = put_user(decnet_address, (unsigned short *)arg);
break;
#endif
case
SIOCGIFCONF
:
case
SIOCGIFFLAGS
:
case
SIOCGIFBRDADDR
:
...
...
@@ -2227,38 +2246,24 @@ void dn_unregister_sysctl(void);
#endif
#ifdef MODULE
MODULE_DESCRIPTION
(
"The Linux DECnet Network Protocol"
);
MODULE_AUTHOR
(
"Linux DECnet Project Team"
);
MODULE_LICENSE
(
"GPL"
);
static
int
addr
[
2
]
=
{
0
,
0
};
MODULE_PARM
(
addr
,
"2i"
);
MODULE_PARM_DESC
(
addr
,
"The DECnet address of this machine: area,node"
);
#endif
static
char
banner
[]
__initdata
=
KERN_INFO
"NET4: DECnet for Linux: V.2.
4.20-pre1
s (C) 1995-2002 Linux DECnet Project Team
\n
"
;
static
char
banner
[]
__initdata
=
KERN_INFO
"NET4: DECnet for Linux: V.2.
5.40
s (C) 1995-2002 Linux DECnet Project Team
\n
"
;
static
int
__init
decnet_init
(
void
)
{
#ifdef MODULE
if
(
addr
[
0
]
>
63
||
addr
[
0
]
<
0
)
{
printk
(
KERN_ERR
"DECnet: Area must be between 0 and 63"
);
return
1
;
}
if
(
addr
[
1
]
>
1023
||
addr
[
1
]
<
0
)
{
printk
(
KERN_ERR
"DECnet: Node must be between 0 and 1023"
);
return
1
;
}
decnet_address
=
dn_htons
((
addr
[
0
]
<<
10
)
|
addr
[
1
]);
dn_dn2eth
(
decnet_ether_address
,
dn_ntohs
(
decnet_address
));
#endif
printk
(
banner
);
dn_sk_cachep
=
kmem_cache_create
(
"decnet_socket_cache"
,
sizeof
(
struct
dn_sock
),
0
,
SLAB_HWCACHE_ALIGN
,
NULL
,
NULL
);
if
(
!
dn_sk_cachep
)
return
-
ENOMEM
;
sock_register
(
&
dn_family_ops
);
dev_add_pack
(
&
dn_dix_packet_type
);
register_netdevice_notifier
(
&
dn_dev_notifier
);
...
...
@@ -2288,21 +2293,6 @@ static int __init decnet_init(void)
}
#ifndef MODULE
static
int
__init
decnet_setup
(
char
*
str
)
{
unsigned
short
area
=
simple_strtoul
(
str
,
&
str
,
0
);
unsigned
short
node
=
simple_strtoul
(
*
str
>
0
?
++
str
:
str
,
&
str
,
0
);
decnet_address
=
dn_htons
(
area
<<
10
|
node
);
dn_dn2eth
(
decnet_ether_address
,
dn_ntohs
(
decnet_address
));
return
1
;
}
__setup
(
"decnet="
,
decnet_setup
);
#endif
static
void
__exit
decnet_exit
(
void
)
{
sock_unregister
(
AF_DECnet
);
...
...
@@ -2323,6 +2313,8 @@ static void __exit decnet_exit(void)
#endif
/* CONFIG_DECNET_ROUTER */
proc_net_remove
(
"decnet"
);
kmem_cache_destroy
(
dn_sk_cachep
);
}
module_init
(
decnet_init
);
...
...
net/decnet/dn_dev.c
View file @
ac3ebbfb
...
...
@@ -23,6 +23,8 @@
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/net.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
...
...
@@ -52,16 +54,23 @@ static unsigned char dn_eco_version[3] = {0x02,0x00,0x00};
extern
struct
neigh_table
dn_neigh_table
;
struct
net_device
*
decnet_default_device
;
/*
* decnet_address is kept in network order.
*/
dn_address
decnet_address
=
0
;
static
rwlock_t
dndev_lock
=
RW_LOCK_UNLOCKED
;
static
struct
net_device
*
decnet_default_device
;
static
struct
dn_dev
*
dn_dev_create
(
struct
net_device
*
dev
,
int
*
err
);
static
void
dn_dev_delete
(
struct
net_device
*
dev
);
static
void
rtmsg_ifa
(
int
event
,
struct
dn_ifaddr
*
ifa
);
static
int
dn_eth_up
(
struct
net_device
*
);
static
void
dn_send_brd_hello
(
struct
net_device
*
dev
);
static
void
dn_eth_down
(
struct
net_device
*
);
static
void
dn_send_brd_hello
(
struct
net_device
*
dev
,
struct
dn_ifaddr
*
ifa
);
#if 0
static void dn_send_ptp_hello(struct net_device *dev);
static void dn_send_ptp_hello(struct net_device *dev
, struct dn_ifaddr *ifa
);
#endif
static
struct
dn_dev_parms
dn_dev_list
[]
=
{
...
...
@@ -75,6 +84,7 @@ static struct dn_dev_parms dn_dev_list[] = {
.
name
=
"ethernet"
,
.
ctl_name
=
NET_DECNET_CONF_ETHER
,
.
up
=
dn_eth_up
,
.
down
=
dn_eth_down
,
.
timer3
=
dn_send_brd_hello
,
},
{
...
...
@@ -249,6 +259,51 @@ static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
}
}
struct
net_device
*
dn_dev_get_default
(
void
)
{
struct
net_device
*
dev
;
read_lock
(
&
dndev_lock
);
dev
=
decnet_default_device
;
if
(
dev
)
{
if
(
dev
->
dn_ptr
)
dev_hold
(
dev
);
else
dev
=
NULL
;
}
read_unlock
(
&
dndev_lock
);
return
dev
;
}
int
dn_dev_set_default
(
struct
net_device
*
dev
,
int
force
)
{
struct
net_device
*
old
=
NULL
;
int
rv
=
-
EBUSY
;
if
(
!
dev
->
dn_ptr
)
return
-
ENODEV
;
write_lock
(
&
dndev_lock
);
if
(
force
||
decnet_default_device
==
NULL
)
{
old
=
decnet_default_device
;
decnet_default_device
=
dev
;
rv
=
0
;
}
write_unlock
(
&
dndev_lock
);
if
(
old
)
dev_put
(
dev
);
return
rv
;
}
static
void
dn_dev_check_default
(
struct
net_device
*
dev
)
{
write_lock
(
&
dndev_lock
);
if
(
dev
==
decnet_default_device
)
{
decnet_default_device
=
NULL
;
}
else
{
dev
=
NULL
;
}
write_unlock
(
&
dndev_lock
);
if
(
dev
)
dev_put
(
dev
);
}
static
int
dn_forwarding_proc
(
ctl_table
*
table
,
int
write
,
struct
file
*
filep
,
...
...
@@ -364,9 +419,20 @@ static __inline__ void dn_dev_free_ifa(struct dn_ifaddr *ifa)
static
void
dn_dev_del_ifa
(
struct
dn_dev
*
dn_db
,
struct
dn_ifaddr
**
ifap
,
int
destroy
)
{
struct
dn_ifaddr
*
ifa1
=
*
ifap
;
unsigned
char
mac_addr
[
6
];
struct
net_device
*
dev
=
dn_db
->
dev
;
ASSERT_RTNL
();
*
ifap
=
ifa1
->
ifa_next
;
if
(
dn_db
->
dev
->
type
==
ARPHRD_ETHER
)
{
if
(
ifa1
->
ifa_local
!=
dn_htons
(
dn_eth2dn
(
dev
->
dev_addr
)))
{
dn_dn2eth
(
mac_addr
,
ifa1
->
ifa_local
);
dev_mc_delete
(
dev
,
mac_addr
,
ETH_ALEN
,
0
);
}
}
rtmsg_ifa
(
RTM_DELADDR
,
ifa1
);
if
(
destroy
)
{
...
...
@@ -379,9 +445,25 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de
static
int
dn_dev_insert_ifa
(
struct
dn_dev
*
dn_db
,
struct
dn_ifaddr
*
ifa
)
{
/*
* FIXME: Duplicate check here.
*/
struct
net_device
*
dev
=
dn_db
->
dev
;
struct
dn_ifaddr
*
ifa1
;
unsigned
char
mac_addr
[
6
];
ASSERT_RTNL
();
/* Check for duplicates */
for
(
ifa1
=
dn_db
->
ifa_list
;
ifa1
;
ifa1
=
ifa1
->
ifa_next
)
{
if
(
ifa1
->
ifa_local
==
ifa
->
ifa_local
)
return
-
EEXIST
;
}
if
(
dev
->
type
==
ARPHRD_ETHER
)
{
if
(
ifa
->
ifa_local
!=
dn_htons
(
dn_eth2dn
(
dev
->
dev_addr
)))
{
dn_dn2eth
(
mac_addr
,
ifa
->
ifa_local
);
dev_mc_add
(
dev
,
mac_addr
,
ETH_ALEN
,
0
);
dev_mc_upload
(
dev
);
}
}
ifa
->
ifa_next
=
dn_db
->
ifa_list
;
dn_db
->
ifa_list
=
ifa
;
...
...
@@ -394,6 +476,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
static
int
dn_dev_set_ifa
(
struct
net_device
*
dev
,
struct
dn_ifaddr
*
ifa
)
{
struct
dn_dev
*
dn_db
=
dev
->
dn_ptr
;
int
rv
;
if
(
dn_db
==
NULL
)
{
int
err
;
...
...
@@ -407,7 +490,10 @@ static int dn_dev_set_ifa(struct net_device *dev, struct dn_ifaddr *ifa)
if
(
dev
->
flags
&
IFF_LOOPBACK
)
ifa
->
ifa_scope
=
RT_SCOPE_HOST
;
return
dn_dev_insert_ifa
(
dn_db
,
ifa
);
rv
=
dn_dev_insert_ifa
(
dn_db
,
ifa
);
if
(
rv
)
dn_dev_free_ifa
(
ifa
);
return
rv
;
}
...
...
@@ -538,6 +624,7 @@ static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a
struct
dn_dev
*
dn_db
;
struct
ifaddrmsg
*
ifm
=
NLMSG_DATA
(
nlh
);
struct
dn_ifaddr
*
ifa
;
int
rv
;
if
(
rta
[
IFA_LOCAL
-
1
]
==
NULL
)
return
-
EINVAL
;
...
...
@@ -564,7 +651,10 @@ static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a
else
memcpy
(
ifa
->
ifa_label
,
dev
->
name
,
IFNAMSIZ
);
return
dn_dev_insert_ifa
(
dn_db
,
ifa
);
rv
=
dn_dev_insert_ifa
(
dn_db
,
ifa
);
if
(
rv
)
dn_dev_free_ifa
(
ifa
);
return
rv
;
}
static
int
dn_dev_fill_ifaddr
(
struct
sk_buff
*
skb
,
struct
dn_ifaddr
*
ifa
,
...
...
@@ -651,7 +741,52 @@ static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
return
skb
->
len
;
}
static
void
dn_send_endnode_hello
(
struct
net_device
*
dev
)
static
int
dn_dev_get_first
(
struct
net_device
*
dev
,
dn_address
*
addr
)
{
struct
dn_dev
*
dn_db
=
(
struct
dn_dev
*
)
dev
->
dn_ptr
;
struct
dn_ifaddr
*
ifa
;
int
rv
=
-
ENODEV
;
if
(
dn_db
==
NULL
)
goto
out
;
ifa
=
dn_db
->
ifa_list
;
if
(
ifa
!=
NULL
)
{
*
addr
=
ifa
->
ifa_local
;
rv
=
0
;
}
out:
return
rv
;
}
/*
* Find a default address to bind to.
*
* This is one of those areas where the initial VMS concepts don't really
* map onto the Linux concepts, and since we introduced multiple addresses
* per interface we have to cope with slightly odd ways of finding out what
* "our address" really is. Mostly its not a problem; for this we just guess
* a sensible default. Eventually the routing code will take care of all the
* nasties for us I hope.
*/
int
dn_dev_bind_default
(
dn_address
*
addr
)
{
struct
net_device
*
dev
;
int
rv
;
dev
=
dn_dev_get_default
();
last_chance:
if
(
dev
)
{
read_lock
(
&
dev_base_lock
);
rv
=
dn_dev_get_first
(
dev
,
addr
);
read_unlock
(
&
dev_base_lock
);
dev_put
(
dev
);
if
(
rv
==
0
||
dev
==
&
loopback_dev
)
return
rv
;
}
dev
=
&
loopback_dev
;
dev_hold
(
dev
);
goto
last_chance
;
}
static
void
dn_send_endnode_hello
(
struct
net_device
*
dev
,
struct
dn_ifaddr
*
ifa
)
{
struct
endnode_hello_message
*
msg
;
struct
sk_buff
*
skb
=
NULL
;
...
...
@@ -667,7 +802,7 @@ static void dn_send_endnode_hello(struct net_device *dev)
msg
->
msgflg
=
0x0D
;
memcpy
(
msg
->
tiver
,
dn_eco_version
,
3
);
memcpy
(
msg
->
id
,
decnet_ether_address
,
6
);
dn_dn2eth
(
msg
->
id
,
ifa
->
ifa_local
);
msg
->
iinfo
=
DN_RT_INFO_ENDN
;
msg
->
blksize
=
dn_htons
(
dn_db
->
parms
.
blksize
);
msg
->
area
=
0x00
;
...
...
@@ -689,7 +824,7 @@ static void dn_send_endnode_hello(struct net_device *dev)
skb
->
nh
.
raw
=
skb
->
data
;
dn_rt_finish_output
(
skb
,
dn_rt_all_rt_mcast
);
dn_rt_finish_output
(
skb
,
dn_rt_all_rt_mcast
,
msg
->
id
);
}
...
...
@@ -697,7 +832,7 @@ static void dn_send_endnode_hello(struct net_device *dev)
#define DRDELAY (5 * HZ)
static
int
dn_am_i_a_router
(
struct
dn_neigh
*
dn
,
struct
dn_dev
*
dn_db
)
static
int
dn_am_i_a_router
(
struct
dn_neigh
*
dn
,
struct
dn_dev
*
dn_db
,
struct
dn_ifaddr
*
ifa
)
{
/* First check time since device went up */
if
((
jiffies
-
dn_db
->
uptime
)
<
DRDELAY
)
...
...
@@ -715,13 +850,13 @@ static int dn_am_i_a_router(struct dn_neigh *dn, struct dn_dev *dn_db)
if
(
dn
->
priority
!=
dn_db
->
parms
.
priority
)
return
0
;
if
(
dn_ntohs
(
dn
->
addr
)
<
dn_ntohs
(
decnet_address
))
if
(
dn_ntohs
(
dn
->
addr
)
<
dn_ntohs
(
ifa
->
ifa_local
))
return
1
;
return
0
;
}
static
void
dn_send_router_hello
(
struct
net_device
*
dev
)
static
void
dn_send_router_hello
(
struct
net_device
*
dev
,
struct
dn_ifaddr
*
ifa
)
{
int
n
;
struct
dn_dev
*
dn_db
=
dev
->
dn_ptr
;
...
...
@@ -731,6 +866,7 @@ static void dn_send_router_hello(struct net_device *dev)
unsigned
char
*
ptr
;
unsigned
char
*
i1
,
*
i2
;
unsigned
short
*
pktlen
;
char
*
src
;
if
(
dn_db
->
parms
.
blksize
<
(
26
+
7
))
return
;
...
...
@@ -753,7 +889,8 @@ static void dn_send_router_hello(struct net_device *dev)
*
ptr
++
=
2
;
/* ECO */
*
ptr
++
=
0
;
*
ptr
++
=
0
;
memcpy
(
ptr
,
decnet_ether_address
,
ETH_ALEN
);
dn_dn2eth
(
ptr
,
ifa
->
ifa_local
);
src
=
ptr
;
ptr
+=
ETH_ALEN
;
*
ptr
++
=
dn_db
->
parms
.
forwarding
==
1
?
DN_RT_INFO_L1RT
:
DN_RT_INFO_L2RT
;
...
...
@@ -781,34 +918,34 @@ static void dn_send_router_hello(struct net_device *dev)
skb
->
nh
.
raw
=
skb
->
data
;
if
(
dn_am_i_a_router
(
dn
,
dn_db
))
{
if
(
dn_am_i_a_router
(
dn
,
dn_db
,
ifa
))
{
struct
sk_buff
*
skb2
=
skb_copy
(
skb
,
GFP_ATOMIC
);
if
(
skb2
)
{
dn_rt_finish_output
(
skb2
,
dn_rt_all_end_mcast
);
dn_rt_finish_output
(
skb2
,
dn_rt_all_end_mcast
,
src
);
}
}
dn_rt_finish_output
(
skb
,
dn_rt_all_rt_mcast
);
dn_rt_finish_output
(
skb
,
dn_rt_all_rt_mcast
,
src
);
}
static
void
dn_send_brd_hello
(
struct
net_device
*
dev
)
static
void
dn_send_brd_hello
(
struct
net_device
*
dev
,
struct
dn_ifaddr
*
ifa
)
{
struct
dn_dev
*
dn_db
=
(
struct
dn_dev
*
)
dev
->
dn_ptr
;
if
(
dn_db
->
parms
.
forwarding
==
0
)
dn_send_endnode_hello
(
dev
);
dn_send_endnode_hello
(
dev
,
ifa
);
else
dn_send_router_hello
(
dev
);
dn_send_router_hello
(
dev
,
ifa
);
}
#else
static
void
dn_send_brd_hello
(
struct
net_device
*
dev
)
static
void
dn_send_brd_hello
(
struct
net_device
*
dev
,
struct
dn_ifaddr
*
ifa
)
{
dn_send_endnode_hello
(
dev
);
dn_send_endnode_hello
(
dev
,
ifa
);
}
#endif
#if 0
static void dn_send_ptp_hello(struct net_device *dev)
static void dn_send_ptp_hello(struct net_device *dev
, struct dn_ifaddr *ifa
)
{
int tdlen = 16;
int size = dev->hard_header_len + 2 + 4 + tdlen;
...
...
@@ -817,6 +954,7 @@ static void dn_send_ptp_hello(struct net_device *dev)
int i;
unsigned char *ptr;
struct dn_neigh *dn = (struct dn_neigh *)dn_db->router;
char src[ETH_ALEN];
if (skb == NULL)
return ;
...
...
@@ -826,21 +964,15 @@ static void dn_send_ptp_hello(struct net_device *dev)
ptr = skb_put(skb, 2 + 4 + tdlen);
*ptr++ = DN_RT_PKT_HELO;
*((dn_address *)ptr) =
decnet_address
;
*((dn_address *)ptr) =
ifa->ifa_local
;
ptr += 2;
*ptr++ = tdlen;
for(i = 0; i < tdlen; i++)
*ptr++ = 0252;
if (dn_am_i_a_router(dn, dn_db)) {
struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
if (skb2) {
dn_rt_finish_output(skb2, dn_rt_all_end_mcast);
}
}
dn_rt_finish_output(skb, dn_rt_all_rt_mcast);
dn_dn2eth(src, ifa->ifa_local);
dn_rt_finish_output(skb, dn_rt_all_rt_mcast, src);
}
#endif
...
...
@@ -860,16 +992,31 @@ static int dn_eth_up(struct net_device *dev)
return
0
;
}
static
void
dn_eth_down
(
struct
net_device
*
dev
)
{
struct
dn_dev
*
dn_db
=
dev
->
dn_ptr
;
if
(
dn_db
->
parms
.
forwarding
==
0
)
dev_mc_delete
(
dev
,
dn_rt_all_end_mcast
,
ETH_ALEN
,
0
);
else
dev_mc_delete
(
dev
,
dn_rt_all_rt_mcast
,
ETH_ALEN
,
0
);
}
static
void
dn_dev_set_timer
(
struct
net_device
*
dev
);
static
void
dn_dev_timer_func
(
unsigned
long
arg
)
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
arg
;
struct
dn_dev
*
dn_db
=
dev
->
dn_ptr
;
struct
dn_ifaddr
*
ifa
;
if
(
dn_db
->
t3
<=
dn_db
->
parms
.
t2
)
{
if
(
dn_db
->
parms
.
timer3
)
dn_db
->
parms
.
timer3
(
dev
);
if
(
dn_db
->
parms
.
timer3
)
{
for
(
ifa
=
dn_db
->
ifa_list
;
ifa
;
ifa
=
ifa
->
ifa_next
)
{
if
(
!
(
ifa
->
ifa_flags
&
IFA_F_SECONDARY
))
dn_db
->
parms
.
timer3
(
dev
,
ifa
);
}
}
dn_db
->
t3
=
dn_db
->
parms
.
t3
;
}
else
{
dn_db
->
t3
-=
dn_db
->
parms
.
t2
;
...
...
@@ -917,8 +1064,6 @@ struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
dn_db
->
dev
=
dev
;
init_timer
(
&
dn_db
->
timer
);
memcpy
(
dn_db
->
addr
,
decnet_ether_address
,
ETH_ALEN
);
/* To go... */
dn_db
->
uptime
=
jiffies
;
if
(
dn_db
->
parms
.
up
)
{
if
(
dn_db
->
parms
.
up
(
dev
)
<
0
)
{
...
...
@@ -929,7 +1074,6 @@ struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
}
dn_db
->
neigh_parms
=
neigh_parms_alloc
(
dev
,
&
dn_neigh_table
);
/* dn_db->neigh_parms->neigh_setup = dn_db->parms.neigh_setup; */
dn_dev_sysctl_register
(
dev
,
&
dn_db
->
parms
);
...
...
@@ -945,27 +1089,64 @@ struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
* the loopback device & ethernet devices with correct
* MAC addreses automatically. Others must be started
* specifically.
*
* FIXME: How should we configure the loopback address ? If we could dispense
* with using decnet_address here and for autobind, it will be one less thing
* for users to worry about setting up.
*/
void
dn_dev_up
(
struct
net_device
*
dev
)
{
struct
dn_ifaddr
*
ifa
;
dn_address
addr
=
decnet_address
;
int
maybe_default
=
0
;
struct
dn_dev
*
dn_db
=
(
struct
dn_dev
*
)
dev
->
dn_ptr
;
if
((
dev
->
type
!=
ARPHRD_ETHER
)
&&
(
dev
->
type
!=
ARPHRD_LOOPBACK
))
return
;
if
(
dev
->
type
==
ARPHRD_ETHER
)
if
(
memcmp
(
dev
->
dev_addr
,
decnet_ether_address
,
ETH_ALEN
)
!=
0
)
/*
* Need to ensure that loopback device has a dn_db attached to it
* to allow creation of neighbours against it, even though it might
* not have a local address of its own. Might as well do the same for
* all autoconfigured interfaces.
*/
if
(
dn_db
==
NULL
)
{
int
err
;
dn_db
=
dn_dev_create
(
dev
,
&
err
);
if
(
dn_db
==
NULL
)
return
;
}
if
(
dev
->
type
==
ARPHRD_ETHER
)
{
if
(
memcmp
(
dev
->
dev_addr
,
dn_hiord
,
4
)
!=
0
)
return
;
addr
=
dn_htons
(
dn_eth2dn
(
dev
->
dev_addr
));
maybe_default
=
1
;
}
if
(
addr
==
0
)
return
;
if
((
ifa
=
dn_dev_alloc_ifa
())
==
NULL
)
return
;
ifa
->
ifa_local
=
decnet_address
;
ifa
->
ifa_local
=
addr
;
ifa
->
ifa_flags
=
0
;
ifa
->
ifa_scope
=
RT_SCOPE_UNIVERSE
;
strcpy
(
ifa
->
ifa_label
,
dev
->
name
);
dn_dev_set_ifa
(
dev
,
ifa
);
/*
* Automagically set the default device to the first automatically
* configured ethernet card in the system.
*/
if
(
maybe_default
)
{
dev_hold
(
dev
);
if
(
dn_dev_set_default
(
dev
,
0
))
dev_put
(
dev
);
}
}
static
void
dn_dev_delete
(
struct
net_device
*
dev
)
...
...
@@ -976,14 +1157,10 @@ static void dn_dev_delete(struct net_device *dev)
return
;
del_timer_sync
(
&
dn_db
->
timer
);
dn_dev_sysctl_unregister
(
&
dn_db
->
parms
);
dn_dev_check_default
(
dev
);
neigh_ifdown
(
&
dn_neigh_table
,
dev
);
if
(
dev
==
decnet_default_device
)
decnet_default_device
=
NULL
;
if
(
dn_db
->
parms
.
down
)
dn_db
->
parms
.
down
(
dev
);
...
...
@@ -1204,8 +1381,28 @@ static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
#endif
};
#ifdef MODULE
static
int
addr
[
2
]
=
{
0
,
0
};
MODULE_PARM
(
addr
,
"2i"
);
MODULE_PARM_DESC
(
addr
,
"The DECnet address of this machine: area,node"
);
#endif
void
__init
dn_dev_init
(
void
)
{
#ifdef MODULE
if
(
addr
[
0
]
>
63
||
addr
[
0
]
<
0
)
{
printk
(
KERN_ERR
"DECnet: Area must be between 0 and 63"
);
return
;
}
if
(
addr
[
1
]
>
1023
||
addr
[
1
]
<
0
)
{
printk
(
KERN_ERR
"DECnet: Node must be between 0 and 1023"
);
return
;
}
decnet_address
=
dn_htons
((
addr
[
0
]
<<
10
)
|
addr
[
1
]);
#endif
dn_dev_devices_on
();
#ifdef CONFIG_DECNET_SIOCGIFCONF
...
...
@@ -1247,3 +1444,18 @@ void __exit dn_dev_cleanup(void)
dn_dev_devices_off
();
}
#ifndef MODULE
static
int
__init
decnet_setup
(
char
*
str
)
{
unsigned
short
area
=
simple_strtoul
(
str
,
&
str
,
0
);
unsigned
short
node
=
simple_strtoul
(
*
str
>
0
?
++
str
:
str
,
&
str
,
0
);
decnet_address
=
dn_htons
(
area
<<
10
|
node
);
return
1
;
}
__setup
(
"decnet="
,
decnet_setup
);
#endif
net/decnet/dn_neigh.c
View file @
ac3ebbfb
...
...
@@ -181,10 +181,13 @@ static void dn_short_error_report(struct neighbour *neigh, struct sk_buff *skb)
static
int
dn_neigh_output_packet
(
struct
sk_buff
*
skb
)
{
struct
dst_entry
*
dst
=
skb
->
dst
;
struct
dn_route
*
rt
=
(
struct
dn_route
*
)
dst
;
struct
neighbour
*
neigh
=
dst
->
neighbour
;
struct
net_device
*
dev
=
neigh
->
dev
;
char
mac_addr
[
ETH_ALEN
];
if
(
!
dev
->
hard_header
||
dev
->
hard_header
(
skb
,
dev
,
ntohs
(
skb
->
protocol
),
neigh
->
ha
,
NULL
,
skb
->
len
)
>=
0
)
dn_dn2eth
(
mac_addr
,
rt
->
rt_saddr
);
if
(
!
dev
->
hard_header
||
dev
->
hard_header
(
skb
,
dev
,
ntohs
(
skb
->
protocol
),
neigh
->
ha
,
mac_addr
,
skb
->
len
)
>=
0
)
return
neigh
->
ops
->
queue_xmit
(
skb
);
if
(
net_ratelimit
())
...
...
net/decnet/dn_route.c
View file @
ac3ebbfb
...
...
@@ -334,7 +334,7 @@ static int dn_return_short(struct sk_buff *skb)
*
dst
=
tmp
;
skb
->
pkt_type
=
PACKET_OUTGOING
;
dn_rt_finish_output
(
skb
,
NULL
);
dn_rt_finish_output
(
skb
,
NULL
,
NULL
);
return
NET_RX_SUCCESS
;
}
...
...
@@ -380,7 +380,7 @@ static int dn_return_long(struct sk_buff *skb)
memcpy
(
dst_addr
,
tmp
,
ETH_ALEN
);
skb
->
pkt_type
=
PACKET_OUTGOING
;
dn_rt_finish_output
(
skb
,
tmp
);
dn_rt_finish_output
(
skb
,
dst_addr
,
src_addr
);
return
NET_RX_SUCCESS
;
}
...
...
@@ -641,7 +641,9 @@ static int dn_forward(struct sk_buff *skb)
struct
dn_skb_cb
*
cb
=
DN_SKB_CB
(
skb
);
struct
dst_entry
*
dst
=
skb
->
dst
;
struct
neighbour
*
neigh
;
#ifdef CONFIG_NETFILTER
struct
net_device
*
dev
=
skb
->
dev
;
#endif
int
err
=
-
EINVAL
;
if
((
neigh
=
dst
->
neighbour
)
==
NULL
)
...
...
@@ -711,10 +713,11 @@ static int dn_rt_bug(struct sk_buff *skb)
static
int
dn_route_output_slow
(
struct
dst_entry
**
pprt
,
dn_address
dst
,
dn_address
src
,
int
flags
)
{
struct
dn_route
*
rt
=
NULL
;
struct
net_device
*
dev
=
decnet_default_device
;
struct
net_device
*
dev
=
NULL
;
struct
neighbour
*
neigh
=
NULL
;
struct
dn_dev
*
dn_db
;
unsigned
hash
;
#ifdef CONFIG_DECNET_ROUTER
struct
dn_fib_key
key
;
struct
dn_fib_res
res
;
...
...
@@ -765,13 +768,25 @@ static int dn_route_output_slow(struct dst_entry **pprt, dn_address dst, dn_addr
goto
got_route
;
}
dev
=
dn_dev_get_default
();
if
(
dev
==
NULL
)
return
-
EINVAL
;
dn_db
=
dev
->
dn_ptr
;
if
(
dn_db
==
NULL
)
/* Check to see if its one of our own local addresses */
if
(
dn_dev_islocal
(
dev
,
dst
))
{
struct
net_device
*
lo
=
&
loopback_dev
;
if
(
lo
->
dn_ptr
)
{
neigh
=
__neigh_lookup
(
&
dn_neigh_table
,
&
dst
,
lo
,
1
);
if
(
neigh
)
goto
got_route
;
}
if
(
net_ratelimit
())
printk
(
"dn_route_output_slow: Dest is local interface address, but loopback device is not up
\n
"
);
dev_put
(
dev
);
return
-
EINVAL
;
}
/* Try default router */
if
((
neigh
=
neigh_clone
(
dn_db
->
router
))
!=
NULL
)
...
...
@@ -781,10 +796,12 @@ static int dn_route_output_slow(struct dst_entry **pprt, dn_address dst, dn_addr
if
((
neigh
=
__neigh_lookup
(
&
dn_neigh_table
,
&
dst
,
dev
,
1
))
!=
NULL
)
goto
got_route
;
dev_put
(
dev
);
return
-
EINVAL
;
got_route:
if
(
dev
)
dev_put
(
dev
);
if
((
rt
=
dst_alloc
(
&
dn_dst_ops
))
==
NULL
)
{
neigh_release
(
neigh
);
...
...
@@ -809,7 +826,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, dn_address dst, dn_addr
rt
->
u
.
dst
.
output
=
dn_output
;
rt
->
u
.
dst
.
input
=
dn_rt_bug
;
if
(
dn_dev_islocal
(
neigh
->
dev
,
rt
->
rt_daddr
)
)
if
(
neigh
->
dev
->
flags
&
IFF_LOOPBACK
)
rt
->
u
.
dst
.
input
=
dn_nsp_rx
;
hash
=
dn_hash
(
rt
->
key
.
saddr
,
rt
->
key
.
daddr
);
...
...
net/decnet/sysctl_net_decnet.c
View file @
ac3ebbfb
...
...
@@ -9,6 +9,7 @@
*
*
* Changes:
* Steve Whitehouse - C99 changes and default device handling
*
*/
#include <linux/config.h>
...
...
@@ -152,7 +153,6 @@ static int dn_node_address_strategy(ctl_table *table, int *name, int nlen,
dn_dev_devices_off
();
decnet_address
=
addr
;
dn_dn2eth
(
decnet_ether_address
,
dn_ntohs
(
decnet_address
));
dn_dev_devices_on
();
}
...
...
@@ -187,7 +187,6 @@ static int dn_node_address_handler(ctl_table *table, int write,
dn_dev_devices_off
();
decnet_address
=
dnaddr
;
dn_dn2eth
(
decnet_ether_address
,
dn_ntohs
(
decnet_address
));
dn_dev_devices_on
();
...
...
@@ -218,9 +217,10 @@ static int dn_def_dev_strategy(ctl_table *table, int *name, int nlen,
void
**
context
)
{
size_t
len
;
struct
net_device
*
dev
=
decnet_default_device
;
struct
net_device
*
dev
;
char
devname
[
17
];
size_t
namel
;
int
rv
=
0
;
devname
[
0
]
=
0
;
...
...
@@ -228,8 +228,11 @@ static int dn_def_dev_strategy(ctl_table *table, int *name, int nlen,
if
(
get_user
(
len
,
oldlenp
))
return
-
EFAULT
;
if
(
len
)
{
if
(
dev
)
dev
=
dn_dev_get_default
();
if
(
dev
)
{
strcpy
(
devname
,
dev
->
name
);
dev_put
(
dev
);
}
namel
=
strlen
(
devname
)
+
1
;
if
(
len
>
namel
)
len
=
namel
;
...
...
@@ -251,16 +254,19 @@ static int dn_def_dev_strategy(ctl_table *table, int *name, int nlen,
devname
[
newlen
]
=
0
;
if
((
dev
=
__dev_get_by_name
(
devname
))
==
NULL
)
dev
=
dev_get_by_name
(
devname
);
if
(
dev
==
NULL
)
return
-
ENODEV
;
if
(
dev
->
dn_ptr
==
NULL
)
return
-
ENODEV
;
decnet_default_device
=
dev
;
rv
=
-
ENODEV
;
if
(
dev
->
dn_ptr
!=
NULL
)
{
rv
=
dn_dev_set_default
(
dev
,
1
);
if
(
rv
)
dev_put
(
dev
);
}
}
return
0
;
return
rv
;
}
...
...
@@ -269,7 +275,7 @@ static int dn_def_dev_handler(ctl_table *table, int write,
void
*
buffer
,
size_t
*
lenp
)
{
size_t
len
;
struct
net_device
*
dev
=
decnet_default_device
;
struct
net_device
*
dev
;
char
devname
[
17
];
if
(
!*
lenp
||
(
filp
->
f_pos
&&
!
write
))
{
...
...
@@ -287,24 +293,32 @@ static int dn_def_dev_handler(ctl_table *table, int write,
devname
[
*
lenp
]
=
0
;
strip_it
(
devname
);
if
((
dev
=
__dev_get_by_name
(
devname
))
==
NULL
)
dev
=
dev_get_by_name
(
devname
);
if
(
dev
==
NULL
)
return
-
ENODEV
;
if
(
dev
->
dn_ptr
==
NULL
)
if
(
dev
->
dn_ptr
==
NULL
)
{
dev_put
(
dev
);
return
-
ENODEV
;
}
decnet_default_device
=
dev
;
if
(
dn_dev_set_default
(
dev
,
1
))
{
dev_put
(
dev
);
return
-
ENODEV
;
}
filp
->
f_pos
+=
*
lenp
;
return
0
;
}
dev
=
dn_dev_get_default
();
if
(
dev
==
NULL
)
{
*
lenp
=
0
;
return
0
;
}
strcpy
(
devname
,
dev
->
name
);
dev_put
(
dev
);
len
=
strlen
(
devname
);
devname
[
len
++
]
=
'\n'
;
...
...
@@ -320,51 +334,125 @@ static int dn_def_dev_handler(ctl_table *table, int write,
}
static
ctl_table
dn_table
[]
=
{
{
NET_DECNET_NODE_ADDRESS
,
"node_address"
,
NULL
,
7
,
0644
,
NULL
,
dn_node_address_handler
,
dn_node_address_strategy
,
NULL
,
NULL
,
NULL
},
{
NET_DECNET_NODE_NAME
,
"node_name"
,
node_name
,
7
,
0644
,
NULL
,
&
proc_dostring
,
&
sysctl_string
,
NULL
,
NULL
,
NULL
},
{
NET_DECNET_DEFAULT_DEVICE
,
"default_device"
,
NULL
,
16
,
0644
,
NULL
,
dn_def_dev_handler
,
dn_def_dev_strategy
,
NULL
,
NULL
,
NULL
},
{
NET_DECNET_TIME_WAIT
,
"time_wait"
,
&
decnet_time_wait
,
sizeof
(
int
),
0644
,
NULL
,
&
proc_dointvec_minmax
,
&
sysctl_intvec
,
NULL
,
&
min_decnet_time_wait
,
&
max_decnet_time_wait
},
{
NET_DECNET_DN_COUNT
,
"dn_count"
,
&
decnet_dn_count
,
sizeof
(
int
),
0644
,
NULL
,
&
proc_dointvec_minmax
,
&
sysctl_intvec
,
NULL
,
&
min_state_count
,
&
max_state_count
},
{
NET_DECNET_DI_COUNT
,
"di_count"
,
&
decnet_di_count
,
sizeof
(
int
),
0644
,
NULL
,
&
proc_dointvec_minmax
,
&
sysctl_intvec
,
NULL
,
&
min_state_count
,
&
max_state_count
},
{
NET_DECNET_DR_COUNT
,
"dr_count"
,
&
decnet_dr_count
,
sizeof
(
int
),
0644
,
NULL
,
&
proc_dointvec_minmax
,
&
sysctl_intvec
,
NULL
,
&
min_state_count
,
&
max_state_count
},
{
NET_DECNET_DST_GC_INTERVAL
,
"dst_gc_interval"
,
&
decnet_dst_gc_interval
,
sizeof
(
int
),
0644
,
NULL
,
&
proc_dointvec_minmax
,
&
sysctl_intvec
,
NULL
,
&
min_decnet_dst_gc_interval
,
&
max_decnet_dst_gc_interval
},
{
NET_DECNET_NO_FC_MAX_CWND
,
"no_fc_max_cwnd"
,
&
decnet_no_fc_max_cwnd
,
sizeof
(
int
),
0644
,
NULL
,
&
proc_dointvec_minmax
,
&
sysctl_intvec
,
NULL
,
&
min_decnet_no_fc_max_cwnd
,
&
max_decnet_no_fc_max_cwnd
},
{
NET_DECNET_DEBUG_LEVEL
,
"debug"
,
&
decnet_debug_level
,
sizeof
(
int
),
0644
,
NULL
,
&
proc_dointvec
,
&
sysctl_intvec
,
NULL
,
NULL
,
NULL
},
{
.
ctl_name
=
NET_DECNET_NODE_ADDRESS
,
.
procname
=
"node_address"
,
.
maxlen
=
7
,
.
mode
=
0644
,
.
proc_handler
=
dn_node_address_handler
,
.
strategy
=
dn_node_address_strategy
,
},
{
.
ctl_name
=
NET_DECNET_NODE_NAME
,
.
procname
=
"node_name"
,
.
data
=
node_name
,
.
maxlen
=
7
,
.
mode
=
0644
,
.
proc_handler
=
&
proc_dostring
,
.
strategy
=
&
sysctl_string
,
},
{
.
ctl_name
=
NET_DECNET_DEFAULT_DEVICE
,
.
procname
=
"default_device"
,
.
maxlen
=
16
,
.
mode
=
0644
,
.
proc_handler
=
dn_def_dev_handler
,
.
strategy
=
dn_def_dev_strategy
,
},
{
.
ctl_name
=
NET_DECNET_TIME_WAIT
,
.
procname
=
"time_wait"
,
.
data
=
&
decnet_time_wait
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec_minmax
,
.
strategy
=
&
sysctl_intvec
,
.
extra1
=
&
min_decnet_time_wait
,
.
extra2
=
&
max_decnet_time_wait
},
{
.
ctl_name
=
NET_DECNET_DN_COUNT
,
.
procname
=
"dn_count"
,
.
data
=
&
decnet_dn_count
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec_minmax
,
.
strategy
=
&
sysctl_intvec
,
.
extra1
=
&
min_state_count
,
.
extra2
=
&
max_state_count
},
{
.
ctl_name
=
NET_DECNET_DI_COUNT
,
.
procname
=
"di_count"
,
.
data
=
&
decnet_di_count
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec_minmax
,
.
strategy
=
&
sysctl_intvec
,
.
extra1
=
&
min_state_count
,
.
extra2
=
&
max_state_count
},
{
.
ctl_name
=
NET_DECNET_DR_COUNT
,
.
procname
=
"dr_count"
,
.
data
=
&
decnet_dr_count
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec_minmax
,
.
strategy
=
&
sysctl_intvec
,
.
extra1
=
&
min_state_count
,
.
extra2
=
&
max_state_count
},
{
.
ctl_name
=
NET_DECNET_DST_GC_INTERVAL
,
.
procname
=
"dst_gc_interval"
,
.
data
=
&
decnet_dst_gc_interval
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec_minmax
,
.
strategy
=
&
sysctl_intvec
,
.
extra1
=
&
min_decnet_dst_gc_interval
,
.
extra2
=
&
max_decnet_dst_gc_interval
},
{
.
ctl_name
=
NET_DECNET_NO_FC_MAX_CWND
,
.
procname
=
"no_fc_max_cwnd"
,
.
data
=
&
decnet_no_fc_max_cwnd
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec_minmax
,
.
strategy
=
&
sysctl_intvec
,
.
extra1
=
&
min_decnet_no_fc_max_cwnd
,
.
extra2
=
&
max_decnet_no_fc_max_cwnd
},
{
.
ctl_name
=
NET_DECNET_DEBUG_LEVEL
,
.
procname
=
"debug"
,
.
data
=
&
decnet_debug_level
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec
,
.
strategy
=
&
sysctl_intvec
,
},
{
0
}
};
static
ctl_table
dn_dir_table
[]
=
{
{
NET_DECNET
,
"decnet"
,
NULL
,
0
,
0555
,
dn_table
},
{
.
ctl_name
=
NET_DECNET
,
.
procname
=
"decnet"
,
.
mode
=
0555
,
.
child
=
dn_table
},
{
0
}
};
static
ctl_table
dn_root_table
[]
=
{
{
CTL_NET
,
"net"
,
NULL
,
0
,
0555
,
dn_dir_table
},
{
.
ctl_name
=
CTL_NET
,
.
procname
=
"net"
,
.
mode
=
0555
,
.
child
=
dn_dir_table
},
{
0
}
};
...
...
net/ipv4/af_inet.c
View file @
ac3ebbfb
...
...
@@ -1093,6 +1093,25 @@ void inet_unregister_protosw(struct inet_protosw *p)
}
}
#ifdef CONFIG_IP_MULTICAST
static
struct
inet_protocol
igmp_protocol
=
{
.
handler
=
igmp_rcv
,
};
#endif
static
struct
inet_protocol
tcp_protocol
=
{
.
handler
=
tcp_v4_rcv
,
.
err_handler
=
tcp_v4_err
,
};
static
struct
inet_protocol
udp_protocol
=
{
.
handler
=
udp_rcv
,
.
err_handler
=
udp_err
,
};
static
struct
inet_protocol
icmp_protocol
=
{
.
handler
=
icmp_rcv
,
};
/*
* Called by socket.c on kernel startup.
...
...
@@ -1101,7 +1120,6 @@ void inet_unregister_protosw(struct inet_protosw *p)
static
int
__init
inet_init
(
void
)
{
struct
sk_buff
*
dummy_skb
;
struct
inet_protocol
*
p
;
struct
inet_protosw
*
q
;
struct
list_head
*
r
;
...
...
@@ -1131,16 +1149,19 @@ static int __init inet_init(void)
(
void
)
sock_register
(
&
inet_family_ops
);
/*
* Add all the
protocols.
* Add all the
base protocols.
*/
printk
(
KERN_INFO
"IP Protocols: "
);
for
(
p
=
inet_protocol_base
;
p
;)
{
struct
inet_protocol
*
tmp
=
(
struct
inet_protocol
*
)
p
->
next
;
inet_add_protocol
(
p
);
printk
(
"%s%s"
,
p
->
name
,
tmp
?
", "
:
"
\n
"
);
p
=
tmp
;
}
if
(
inet_add_protocol
(
&
icmp_protocol
,
IPPROTO_ICMP
)
<
0
)
printk
(
KERN_CRIT
"inet_init: Cannot add ICMP protocol
\n
"
);
if
(
inet_add_protocol
(
&
udp_protocol
,
IPPROTO_UDP
)
<
0
)
printk
(
KERN_CRIT
"inet_init: Cannot add UDP protocol
\n
"
);
if
(
inet_add_protocol
(
&
tcp_protocol
,
IPPROTO_TCP
)
<
0
)
printk
(
KERN_CRIT
"inet_init: Cannot add TCP protocol
\n
"
);
#ifdef CONFIG_IP_MULTICAST
if
(
inet_add_protocol
(
&
igmp_protocol
,
IPPROTO_IGMP
)
<
0
)
printk
(
KERN_CRIT
"inet_init: Cannot add TCP protocol
\n
"
);
#endif
/* Register the socket-side information for inet_create. */
for
(
r
=
&
inetsw
[
0
];
r
<
&
inetsw
[
SOCK_MAX
];
++
r
)
...
...
net/ipv4/icmp.c
View file @
ac3ebbfb
...
...
@@ -719,23 +719,10 @@ static void icmp_unreach(struct sk_buff *skb)
* we are OK.
*/
ipprot
=
(
struct
inet_protocol
*
)
inet_protos
[
hash
];
while
(
ipprot
)
{
struct
inet_protocol
*
nextip
;
ipprot
=
inet_protos
[
hash
];
if
(
ipprot
&&
ipprot
->
err_handler
)
ipprot
->
err_handler
(
skb
,
info
)
;
nextip
=
(
struct
inet_protocol
*
)
ipprot
->
next
;
/*
* Pass it off to everyone who wants it.
*/
/* RFC1122: OK. Passes appropriate ICMP errors to the */
/* appropriate protocol layer (MUST), as per 3.2.2. */
if
(
protocol
==
ipprot
->
protocol
&&
ipprot
->
err_handler
)
ipprot
->
err_handler
(
skb
,
info
);
ipprot
=
nextip
;
}
out:
return
;
out_err:
...
...
net/ipv4/ip_gre.c
View file @
ac3ebbfb
...
...
@@ -1259,13 +1259,8 @@ int __init ipgre_fb_tunnel_init(struct net_device *dev)
static
struct
inet_protocol
ipgre_protocol
=
{
ipgre_rcv
,
/* GRE handler */
ipgre_err
,
/* TUNNEL error control */
0
,
/* next */
IPPROTO_GRE
,
/* protocol ID */
0
,
/* copy */
NULL
,
/* data */
"GRE"
/* name */
.
handler
=
ipgre_rcv
,
.
err_handler
=
ipgre_err
,
};
...
...
@@ -1281,9 +1276,13 @@ int __init ipgre_init(void)
{
printk
(
KERN_INFO
"GRE over IPv4 tunneling driver
\n
"
);
if
(
inet_add_protocol
(
&
ipgre_protocol
,
IPPROTO_GRE
)
<
0
)
{
printk
(
KERN_INFO
"ipgre init: can't add protocol
\n
"
);
return
-
EAGAIN
;
}
ipgre_fb_tunnel_dev
.
priv
=
(
void
*
)
&
ipgre_fb_tunnel
;
register_netdev
(
&
ipgre_fb_tunnel_dev
);
inet_add_protocol
(
&
ipgre_protocol
);
return
0
;
}
...
...
@@ -1291,7 +1290,7 @@ int __init ipgre_init(void)
void
cleanup_module
(
void
)
{
if
(
inet_del_protocol
(
&
ipgre_protocol
)
<
0
)
if
(
inet_del_protocol
(
&
ipgre_protocol
,
IPPROTO_GRE
)
<
0
)
printk
(
KERN_INFO
"ipgre close: can't remove protocol
\n
"
);
unregister_netdev
(
&
ipgre_fb_tunnel_dev
);
...
...
net/ipv4/ip_input.c
View file @
ac3ebbfb
...
...
@@ -194,28 +194,6 @@ int ip_call_ra_chain(struct sk_buff *skb)
return
0
;
}
/* Handle this out of line, it is rare. */
static
int
ip_run_ipprot
(
struct
sk_buff
*
skb
,
struct
iphdr
*
iph
,
struct
inet_protocol
*
ipprot
,
int
force_copy
)
{
int
ret
=
0
;
do
{
if
(
ipprot
->
protocol
==
iph
->
protocol
)
{
struct
sk_buff
*
skb2
=
skb
;
if
(
ipprot
->
copy
||
force_copy
)
skb2
=
skb_clone
(
skb
,
GFP_ATOMIC
);
if
(
skb2
!=
NULL
)
{
ret
=
1
;
ipprot
->
handler
(
skb2
);
}
}
ipprot
=
(
struct
inet_protocol
*
)
ipprot
->
next
;
}
while
(
ipprot
!=
NULL
);
return
ret
;
}
static
inline
int
ip_local_deliver_finish
(
struct
sk_buff
*
skb
)
{
int
ihl
=
skb
->
nh
.
iph
->
ihl
*
4
;
...
...
@@ -239,44 +217,31 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb)
{
/* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */
int
protocol
=
skb
->
nh
.
iph
->
protocol
;
int
hash
=
protocol
&
(
MAX_INET_PROTOS
-
1
)
;
struct
sock
*
raw_sk
=
raw_v4_htable
[
hash
]
;
int
hash
;
struct
sock
*
raw_sk
;
struct
inet_protocol
*
ipprot
;
int
flag
;
resubmit:
hash
=
protocol
&
(
MAX_INET_PROTOS
-
1
);
raw_sk
=
raw_v4_htable
[
hash
];
/* If there maybe a raw socket we must check - if not we
* don't care less
*/
if
(
raw_sk
!=
NULL
)
raw_sk
=
raw_v4_input
(
skb
,
skb
->
nh
.
iph
,
hash
);
ipprot
=
(
struct
inet_protocol
*
)
inet_protos
[
hash
];
flag
=
0
;
if
(
ipprot
!=
NULL
)
{
if
(
raw_sk
==
NULL
&&
ipprot
->
next
==
NULL
&&
ipprot
->
protocol
==
protocol
)
{
int
ret
;
/* Fast path... */
ret
=
ipprot
->
handler
(
skb
);
return
ret
;
}
else
{
flag
=
ip_run_ipprot
(
skb
,
skb
->
nh
.
iph
,
ipprot
,
(
raw_sk
!=
NULL
));
if
(
raw_sk
)
raw_v4_input
(
skb
,
skb
->
nh
.
iph
,
hash
);
if
((
ipprot
=
inet_protos
[
hash
])
!=
NULL
)
{
int
ret
=
ipprot
->
handler
(
skb
);
if
(
ret
<
0
)
{
protocol
=
-
ret
;
goto
resubmit
;
}
}
else
{
if
(
!
raw_sk
)
{
icmp_send
(
skb
,
ICMP_DEST_UNREACH
,
ICMP_PROT_UNREACH
,
0
);
}
}
/* All protocols checked.
* If this packet was a broadcast, we may *not* reply to it, since that
* causes (proven, grin) ARP storms and a leakage of memory (i.e. all
* ICMP reply messages get queued up for transmission...)
*/
if
(
raw_sk
!=
NULL
)
{
/* Shift to last raw user */
raw_rcv
(
raw_sk
,
skb
);
sock_put
(
raw_sk
);
}
else
if
(
!
flag
)
{
/* Free and report errors */
icmp_send
(
skb
,
ICMP_DEST_UNREACH
,
ICMP_PROT_UNREACH
,
0
);
kfree_skb
(
skb
);
}
}
...
...
net/ipv4/ipip.c
View file @
ac3ebbfb
...
...
@@ -877,10 +877,8 @@ int __init ipip_fb_tunnel_init(struct net_device *dev)
}
static
struct
inet_protocol
ipip_protocol
=
{
.
handler
=
ipip_rcv
,
.
err_handler
=
ipip_err
,
.
protocol
=
IPPROTO_IPIP
,
.
name
=
"IPIP"
.
handler
=
ipip_rcv
,
.
err_handler
=
ipip_err
,
};
static
char
banner
[]
__initdata
=
...
...
@@ -890,15 +888,19 @@ int __init ipip_init(void)
{
printk
(
banner
);
if
(
inet_add_protocol
(
&
ipip_protocol
,
IPPROTO_IPIP
)
<
0
)
{
printk
(
KERN_INFO
"ipip init: can't add protocol
\n
"
);
return
-
EAGAIN
;
}
ipip_fb_tunnel_dev
.
priv
=
(
void
*
)
&
ipip_fb_tunnel
;
register_netdev
(
&
ipip_fb_tunnel_dev
);
inet_add_protocol
(
&
ipip_protocol
);
return
0
;
}
static
void
__exit
ipip_fini
(
void
)
{
if
(
inet_del_protocol
(
&
ipip_protocol
)
<
0
)
if
(
inet_del_protocol
(
&
ipip_protocol
,
IPPROTO_IPIP
)
<
0
)
printk
(
KERN_INFO
"ipip close: can't remove protocol
\n
"
);
unregister_netdev
(
&
ipip_fb_tunnel_dev
);
...
...
net/ipv4/ipmr.c
View file @
ac3ebbfb
...
...
@@ -108,7 +108,7 @@ static int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local
static
int
ipmr_cache_report
(
struct
sk_buff
*
pkt
,
vifi_t
vifi
,
int
assert
);
static
int
ipmr_fill_mroute
(
struct
sk_buff
*
skb
,
struct
mfc_cache
*
c
,
struct
rtmsg
*
rtm
);
extern
struct
inet_protocol
pim_protocol
;
static
struct
inet_protocol
pim_protocol
;
static
struct
timer_list
ipmr_expire_timer
;
...
...
@@ -928,23 +928,28 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
#ifdef CONFIG_IP_PIMSM
case
MRT_PIM
:
{
int
v
;
int
v
,
ret
;
if
(
get_user
(
v
,(
int
*
)
optval
))
return
-
EFAULT
;
v
=
(
v
)
?
1
:
0
;
rtnl_lock
();
ret
=
0
;
if
(
v
!=
mroute_do_pim
)
{
mroute_do_pim
=
v
;
mroute_do_assert
=
v
;
#ifdef CONFIG_IP_PIMSM_V2
if
(
mroute_do_pim
)
inet_add_protocol
(
&
pim_protocol
);
ret
=
inet_add_protocol
(
&
pim_protocol
,
IPPROTO_PIM
);
else
inet_del_protocol
(
&
pim_protocol
);
ret
=
inet_del_protocol
(
&
pim_protocol
,
IPPROTO_PIM
);
if
(
ret
<
0
)
ret
=
-
EAGAIN
;
#endif
}
rtnl_unlock
();
return
0
;
return
ret
;
}
#endif
/*
...
...
@@ -1727,15 +1732,8 @@ static int ipmr_mfc_info(char *buffer, char **start, off_t offset, int length)
#endif
#ifdef CONFIG_IP_PIMSM_V2
struct
inet_protocol
pim_protocol
=
{
pim_rcv
,
/* PIM handler */
NULL
,
/* PIM error control */
NULL
,
/* next */
IPPROTO_PIM
,
/* protocol ID */
0
,
/* copy */
NULL
,
/* data */
"PIM"
/* name */
static
struct
inet_protocol
pim_protocol
=
{
.
handler
=
pim_rcv
,
};
#endif
...
...
net/ipv4/protocol.c
View file @
ac3ebbfb
...
...
@@ -48,134 +48,52 @@
#include <net/ipip.h>
#include <linux/igmp.h>
#define IPPROTO_PREVIOUS NULL
#ifdef CONFIG_IP_MULTICAST
static
struct
inet_protocol
igmp_protocol
=
{
.
handler
=
igmp_rcv
,
.
next
=
IPPROTO_PREVIOUS
,
.
protocol
=
IPPROTO_IGMP
,
.
name
=
"IGMP"
};
#undef IPPROTO_PREVIOUS
#define IPPROTO_PREVIOUS &igmp_protocol
#endif
static
struct
inet_protocol
tcp_protocol
=
{
.
handler
=
tcp_v4_rcv
,
.
err_handler
=
tcp_v4_err
,
.
next
=
IPPROTO_PREVIOUS
,
.
protocol
=
IPPROTO_TCP
,
.
name
=
"TCP"
};
#undef IPPROTO_PREVIOUS
#define IPPROTO_PREVIOUS &tcp_protocol
static
struct
inet_protocol
udp_protocol
=
{
.
handler
=
udp_rcv
,
.
err_handler
=
udp_err
,
.
next
=
IPPROTO_PREVIOUS
,
.
protocol
=
IPPROTO_UDP
,
.
name
=
"UDP"
};
#undef IPPROTO_PREVIOUS
#define IPPROTO_PREVIOUS &udp_protocol
static
struct
inet_protocol
icmp_protocol
=
{
.
handler
=
icmp_rcv
,
.
next
=
IPPROTO_PREVIOUS
,
.
protocol
=
IPPROTO_ICMP
,
.
name
=
"ICMP"
};
#undef IPPROTO_PREVIOUS
#define IPPROTO_PREVIOUS &icmp_protocol
struct
inet_protocol
*
inet_protocol_base
=
IPPROTO_PREVIOUS
;
struct
inet_protocol
*
inet_protos
[
MAX_INET_PROTOS
];
/*
* Add a protocol handler to the hash tables
*/
void
inet_add_protocol
(
struct
inet_protocol
*
prot
)
int
inet_add_protocol
(
struct
inet_protocol
*
prot
,
unsigned
char
protocol
)
{
unsigned
char
hash
;
struct
inet_protocol
*
p2
;
int
hash
,
ret
;
hash
=
protocol
&
(
MAX_INET_PROTOS
-
1
);
hash
=
prot
->
protocol
&
(
MAX_INET_PROTOS
-
1
);
br_write_lock_bh
(
BR_NETPROTO_LOCK
);
prot
->
next
=
inet_protos
[
hash
];
inet_protos
[
hash
]
=
prot
;
prot
->
copy
=
0
;
/*
* Set the copy bit if we need to.
*/
p2
=
(
struct
inet_protocol
*
)
prot
->
next
;
while
(
p2
)
{
if
(
p2
->
protocol
==
prot
->
protocol
)
{
prot
->
copy
=
1
;
break
;
}
p2
=
(
struct
inet_protocol
*
)
p2
->
next
;
if
(
inet_protos
[
hash
])
{
ret
=
-
1
;
}
else
{
inet_protos
[
hash
]
=
prot
;
ret
=
0
;
}
br_write_unlock_bh
(
BR_NETPROTO_LOCK
);
return
ret
;
}
/*
* Remove a protocol from the hash tables.
*/
int
inet_del_protocol
(
struct
inet_protocol
*
prot
)
int
inet_del_protocol
(
struct
inet_protocol
*
prot
,
unsigned
char
protocol
)
{
struct
inet_protocol
*
p
;
struct
inet_protocol
*
lp
=
NULL
;
unsigned
char
hash
;
int
hash
,
ret
;
hash
=
prot
->
protocol
&
(
MAX_INET_PROTOS
-
1
);
br_write_lock_bh
(
BR_NETPROTO_LOCK
);
if
(
prot
==
inet_protos
[
hash
])
{
inet_protos
[
hash
]
=
(
struct
inet_protocol
*
)
inet_protos
[
hash
]
->
next
;
br_write_unlock_bh
(
BR_NETPROTO_LOCK
);
return
0
;
}
hash
=
protocol
&
(
MAX_INET_PROTOS
-
1
);
p
=
(
struct
inet_protocol
*
)
inet_protos
[
hash
];
if
(
p
!=
NULL
&&
p
->
protocol
==
prot
->
protocol
)
lp
=
p
;
while
(
p
)
{
/*
* We have to worry if the protocol being deleted is
* the last one on the list, then we may need to reset
* someone's copied bit.
*/
if
(
p
->
next
&&
p
->
next
==
prot
)
{
/*
* if we are the last one with this protocol and
* there is a previous one, reset its copy bit.
*/
if
(
prot
->
copy
==
0
&&
lp
!=
NULL
)
lp
->
copy
=
0
;
p
->
next
=
prot
->
next
;
br_write_unlock_bh
(
BR_NETPROTO_LOCK
);
return
0
;
}
if
(
p
->
next
!=
NULL
&&
p
->
next
->
protocol
==
prot
->
protocol
)
lp
=
p
->
next
;
br_write_lock_bh
(
BR_NETPROTO_LOCK
);
p
=
(
struct
inet_protocol
*
)
p
->
next
;
if
(
inet_protos
[
hash
]
==
prot
)
{
inet_protos
[
hash
]
=
NULL
;
ret
=
0
;
}
else
{
ret
=
-
1
;
}
br_write_unlock_bh
(
BR_NETPROTO_LOCK
);
return
-
1
;
return
ret
;
}
net/ipv4/raw.c
View file @
ac3ebbfb
...
...
@@ -135,13 +135,12 @@ static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb)
}
/* IP input processing comes here for RAW socket delivery.
* This is fun as to avoid copies we want to make no surplus
* copies.
* Caller owns SKB, so we must make clones.
*
* RFC 1122: SHOULD pass TOS value up to the transport layer.
* -> It does. And not only TOS, but all IP header.
*/
struct
sock
*
raw_v4_input
(
struct
sk_buff
*
skb
,
struct
iphdr
*
iph
,
int
hash
)
void
raw_v4_input
(
struct
sk_buff
*
skb
,
struct
iphdr
*
iph
,
int
hash
)
{
struct
sock
*
sk
;
...
...
@@ -153,28 +152,19 @@ struct sock *raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
skb
->
dev
->
ifindex
);
while
(
sk
)
{
struct
sock
*
sknext
=
__raw_v4_lookup
(
sk
->
next
,
iph
->
protocol
,
iph
->
saddr
,
iph
->
daddr
,
skb
->
dev
->
ifindex
);
if
(
iph
->
protocol
!=
IPPROTO_ICMP
||
!
icmp_filter
(
sk
,
skb
))
{
struct
sk_buff
*
clone
;
if
(
!
sknext
)
break
;
clone
=
skb_clone
(
skb
,
GFP_ATOMIC
);
if
(
iph
->
protocol
!=
IPPROTO_ICMP
||
!
icmp_filter
(
sk
,
skb
))
{
struct
sk_buff
*
clone
=
skb_clone
(
skb
,
GFP_ATOMIC
);
/* Not releasing hash table! */
if
(
clone
)
raw_rcv
(
sk
,
clone
);
}
sk
=
sknext
;
sk
=
__raw_v4_lookup
(
sk
->
next
,
iph
->
protocol
,
iph
->
saddr
,
iph
->
daddr
,
skb
->
dev
->
ifindex
);
}
out:
if
(
sk
)
sock_hold
(
sk
);
read_unlock
(
&
raw_v4_lock
);
return
sk
;
}
void
raw_err
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
,
u32
info
)
...
...
net/ipv6/addrconf.c
View file @
ac3ebbfb
...
...
@@ -152,15 +152,15 @@ int ipv6_addr_type(struct in6_addr *addr)
int
type
=
IPV6_ADDR_MULTICAST
;
switch
((
st
&
htonl
(
0x00FF0000
)))
{
case
htonl
(
0x00010000
):
case
__constant_
htonl
(
0x00010000
):
type
|=
IPV6_ADDR_LOOPBACK
;
break
;
case
htonl
(
0x00020000
):
case
__constant_
htonl
(
0x00020000
):
type
|=
IPV6_ADDR_LINKLOCAL
;
break
;
case
htonl
(
0x00050000
):
case
__constant_
htonl
(
0x00050000
):
type
|=
IPV6_ADDR_SITELOCAL
;
break
;
};
...
...
@@ -786,7 +786,7 @@ static void addrconf_add_lroute(struct net_device *dev)
struct
in6_addr
addr
;
ipv6_addr_set
(
&
addr
,
htonl
(
0xFE800000
),
0
,
0
,
0
);
addrconf_prefix_route
(
&
addr
,
10
,
dev
,
0
,
RTF_ADDRCONF
);
addrconf_prefix_route
(
&
addr
,
64
,
dev
,
0
,
RTF_ADDRCONF
);
}
static
struct
inet6_dev
*
addrconf_add_dev
(
struct
net_device
*
dev
)
...
...
@@ -1161,7 +1161,7 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
flag
|=
IFA_HOST
;
}
if
(
idev
->
dev
->
flags
&
IFF_POINTOPOINT
)
plen
=
10
;
plen
=
64
;
else
plen
=
96
;
...
...
@@ -1211,7 +1211,7 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr
{
struct
inet6_ifaddr
*
ifp
;
ifp
=
ipv6_add_addr
(
idev
,
addr
,
10
,
IFA_LINK
,
IFA_F_PERMANENT
);
ifp
=
ipv6_add_addr
(
idev
,
addr
,
64
,
IFA_LINK
,
IFA_F_PERMANENT
);
if
(
ifp
)
{
addrconf_dad_start
(
ifp
);
in6_ifa_put
(
ifp
);
...
...
net/ipv6/icmp.c
View file @
ac3ebbfb
...
...
@@ -70,15 +70,8 @@ struct socket *icmpv6_socket;
static
int
icmpv6_rcv
(
struct
sk_buff
*
skb
);
static
struct
inet6_protocol
icmpv6_protocol
=
{
icmpv6_rcv
,
/* handler */
NULL
,
/* error control */
NULL
,
/* next */
IPPROTO_ICMPV6
,
/* protocol ID */
0
,
/* copy */
NULL
,
/* data */
"ICMPv6"
/* name */
static
struct
inet6_protocol
icmpv6_protocol
=
{
.
handler
=
icmpv6_rcv
,
};
struct
icmpv6_msg
{
...
...
@@ -467,15 +460,9 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
hash
=
nexthdr
&
(
MAX_INET_PROTOS
-
1
);
for
(
ipprot
=
(
struct
inet6_protocol
*
)
inet6_protos
[
hash
];
ipprot
!=
NULL
;
ipprot
=
(
struct
inet6_protocol
*
)
ipprot
->
next
)
{
if
(
ipprot
->
protocol
!=
nexthdr
)
continue
;
if
(
ipprot
->
err_handler
)
ipprot
->
err_handler
(
skb
,
NULL
,
type
,
code
,
inner_offset
,
info
);
}
ipprot
=
inet6_protos
[
hash
];
if
(
ipprot
&&
ipprot
->
err_handler
)
ipprot
->
err_handler
(
skb
,
NULL
,
type
,
code
,
inner_offset
,
info
);
read_lock
(
&
raw_v6_lock
);
if
((
sk
=
raw_v6_htable
[
hash
])
!=
NULL
)
{
...
...
@@ -651,7 +638,12 @@ int __init icmpv6_init(struct net_proto_family *ops)
sk
->
sndbuf
=
SK_WMEM_MAX
*
2
;
sk
->
prot
->
unhash
(
sk
);
inet6_add_protocol
(
&
icmpv6_protocol
);
if
(
inet6_add_protocol
(
&
icmpv6_protocol
,
IPPROTO_ICMPV6
)
<
0
)
{
printk
(
KERN_ERR
"Failed to register ICMP6 protocol
\n
"
);
sock_release
(
icmpv6_socket
);
icmpv6_socket
=
NULL
;
return
-
EAGAIN
;
}
return
0
;
}
...
...
@@ -660,7 +652,7 @@ void icmpv6_cleanup(void)
{
sock_release
(
icmpv6_socket
);
icmpv6_socket
=
NULL
;
/* For safety. */
inet6_del_protocol
(
&
icmpv6_protocol
);
inet6_del_protocol
(
&
icmpv6_protocol
,
IPPROTO_ICMPV6
);
}
static
struct
icmp6_err
{
...
...
net/ipv6/ip6_input.c
View file @
ac3ebbfb
...
...
@@ -126,7 +126,6 @@ static inline int ip6_input_finish(struct sk_buff *skb)
struct
sock
*
raw_sk
;
int
nhoff
;
int
nexthdr
;
int
found
=
0
;
u8
hash
;
skb
->
h
.
raw
=
skb
->
nh
.
raw
+
sizeof
(
struct
ipv6hdr
);
...
...
@@ -164,39 +163,24 @@ static inline int ip6_input_finish(struct sk_buff *skb)
skb
->
csum
=
csum_sub
(
skb
->
csum
,
csum_partial
(
skb
->
nh
.
raw
,
skb
->
h
.
raw
-
skb
->
nh
.
raw
,
0
));
raw_sk
=
raw_v6_htable
[
nexthdr
&
(
MAX_INET_PROTOS
-
1
)];
resubmit:
raw_sk
=
raw_v6_htable
[
nexthdr
&
(
MAX_INET_PROTOS
-
1
)];
if
(
raw_sk
)
raw_sk
=
ipv6_raw_deliver
(
skb
,
nexthdr
);
ipv6_raw_deliver
(
skb
,
nexthdr
);
hash
=
nexthdr
&
(
MAX_INET_PROTOS
-
1
);
for
(
ipprot
=
(
struct
inet6_protocol
*
)
inet6_protos
[
hash
];
ipprot
!=
NULL
;
ipprot
=
(
struct
inet6_protocol
*
)
ipprot
->
next
)
{
struct
sk_buff
*
buff
=
skb
;
if
(
ipprot
->
protocol
!=
nexthdr
)
continue
;
if
(
ipprot
->
copy
||
raw_sk
)
buff
=
skb_clone
(
skb
,
GFP_ATOMIC
);
if
(
buff
)
ipprot
->
handler
(
buff
);
found
=
1
;
}
if
(
raw_sk
)
{
rawv6_rcv
(
raw_sk
,
skb
);
sock_put
(
raw_sk
);
found
=
1
;
}
/*
* not found: send ICMP parameter problem back
*/
if
(
!
found
)
{
IP6_INC_STATS_BH
(
Ip6InUnknownProtos
);
icmpv6_param_prob
(
skb
,
ICMPV6_UNK_NEXTHDR
,
nhoff
);
if
((
ipprot
=
inet6_protos
[
hash
])
!=
NULL
)
{
int
ret
=
ipprot
->
handler
(
skb
);
if
(
ret
<
0
)
{
nexthdr
=
-
ret
;
goto
resubmit
;
}
}
else
{
if
(
!
raw_sk
)
{
IP6_INC_STATS_BH
(
Ip6InUnknownProtos
);
icmpv6_param_prob
(
skb
,
ICMPV6_UNK_NEXTHDR
,
nhoff
);
}
kfree_skb
(
skb
);
}
return
0
;
...
...
net/ipv6/protocol.c
View file @
ac3ebbfb
...
...
@@ -42,77 +42,42 @@
struct
inet6_protocol
*
inet6_protos
[
MAX_INET_PROTOS
];
void
inet6_add_protocol
(
struct
inet6_protocol
*
prot
)
int
inet6_add_protocol
(
struct
inet6_protocol
*
prot
,
unsigned
char
protocol
)
{
unsigned
char
hash
;
struct
inet6_protocol
*
p2
;
int
ret
,
hash
=
protocol
&
(
MAX_INET_PROTOS
-
1
);
hash
=
prot
->
protocol
&
(
MAX_INET_PROTOS
-
1
);
br_write_lock_bh
(
BR_NETPROTO_LOCK
);
prot
->
next
=
inet6_protos
[
hash
];
inet6_protos
[
hash
]
=
prot
;
prot
->
copy
=
0
;
/*
* Set the copy bit if we need to.
*/
p2
=
(
struct
inet6_protocol
*
)
prot
->
next
;
while
(
p2
!=
NULL
)
{
if
(
p2
->
protocol
==
prot
->
protocol
)
{
prot
->
copy
=
1
;
break
;
}
p2
=
(
struct
inet6_protocol
*
)
p2
->
next
;
if
(
inet6_protos
[
hash
])
{
ret
=
-
1
;
}
else
{
inet6_protos
[
hash
]
=
prot
;
ret
=
0
;
}
br_write_unlock_bh
(
BR_NETPROTO_LOCK
);
return
ret
;
}
/*
* Remove a protocol from the hash tables.
*/
int
inet6_del_protocol
(
struct
inet6_protocol
*
prot
)
int
inet6_del_protocol
(
struct
inet6_protocol
*
prot
,
unsigned
char
protocol
)
{
struct
inet6_protocol
*
p
;
struct
inet6_protocol
*
lp
=
NULL
;
unsigned
char
hash
;
int
ret
,
hash
=
protocol
&
(
MAX_INET_PROTOS
-
1
);
hash
=
prot
->
protocol
&
(
MAX_INET_PROTOS
-
1
);
br_write_lock_bh
(
BR_NETPROTO_LOCK
);
if
(
prot
==
inet6_protos
[
hash
])
{
inet6_protos
[
hash
]
=
(
struct
inet6_protocol
*
)
inet6_protos
[
hash
]
->
next
;
br_write_unlock_bh
(
BR_NETPROTO_LOCK
);
return
(
0
);
}
p
=
(
struct
inet6_protocol
*
)
inet6_protos
[
hash
];
if
(
p
!=
NULL
&&
p
->
protocol
==
prot
->
protocol
)
lp
=
p
;
while
(
p
!=
NULL
)
{
/*
* We have to worry if the protocol being deleted is
* the last one on the list, then we may need to reset
* someone's copied bit.
*/
if
(
p
->
next
!=
NULL
&&
p
->
next
==
prot
)
{
/*
* if we are the last one with this protocol and
* there is a previous one, reset its copy bit.
*/
if
(
prot
->
copy
==
0
&&
lp
!=
NULL
)
lp
->
copy
=
0
;
p
->
next
=
prot
->
next
;
br_write_unlock_bh
(
BR_NETPROTO_LOCK
);
return
(
0
);
}
if
(
p
->
next
!=
NULL
&&
p
->
next
->
protocol
==
prot
->
protocol
)
lp
=
p
->
next
;
p
=
(
struct
inet6_protocol
*
)
p
->
next
;
if
(
inet6_protos
[
hash
]
!=
prot
)
{
ret
=
-
1
;
}
else
{
inet6_protos
[
hash
]
=
NULL
;
ret
=
0
;
}
br_write_unlock_bh
(
BR_NETPROTO_LOCK
);
return
(
-
1
);
return
ret
;
}
net/ipv6/raw.c
View file @
ac3ebbfb
...
...
@@ -133,12 +133,14 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
* demultiplex raw sockets.
* (should consider queueing the skb in the sock receive_queue
* without calling rawv6.c)
*
* Caller owns SKB so we must make clones.
*/
struct
sock
*
ipv6_raw_deliver
(
struct
sk_buff
*
skb
,
int
nexthdr
)
void
ipv6_raw_deliver
(
struct
sk_buff
*
skb
,
int
nexthdr
)
{
struct
in6_addr
*
saddr
;
struct
in6_addr
*
daddr
;
struct
sock
*
sk
,
*
sk2
;
struct
sock
*
sk
;
__u8
hash
;
saddr
=
&
skb
->
nh
.
ipv6h
->
saddr
;
...
...
@@ -159,30 +161,18 @@ struct sock * ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
sk
=
__raw_v6_lookup
(
sk
,
nexthdr
,
daddr
,
saddr
);
if
(
sk
)
{
sk2
=
sk
;
while
((
sk2
=
__raw_v6_lookup
(
sk2
->
next
,
nexthdr
,
daddr
,
saddr
)))
{
struct
sk_buff
*
buff
;
if
(
nexthdr
==
IPPROTO_ICMPV6
&&
icmpv6_filter
(
sk2
,
skb
))
continue
;
while
(
sk
)
{
if
(
nexthdr
!=
IPPROTO_ICMPV6
||
!
icmpv6_filter
(
sk
,
skb
))
{
struct
sk_buff
*
clone
=
skb_clone
(
skb
,
GFP_ATOMIC
);
buff
=
skb_clone
(
skb
,
GFP_ATOMIC
);
if
(
buff
)
rawv6_rcv
(
sk
2
,
buff
);
/* Not releasing hash table! */
if
(
clone
)
rawv6_rcv
(
sk
,
clone
);
}
sk
=
__raw_v6_lookup
(
sk
->
next
,
nexthdr
,
daddr
,
saddr
);
}
if
(
sk
&&
nexthdr
==
IPPROTO_ICMPV6
&&
icmpv6_filter
(
sk
,
skb
))
sk
=
NULL
;
out:
if
(
sk
)
sock_hold
(
sk
);
read_unlock
(
&
raw_v6_lock
);
return
sk
;
}
/* This cleans up af_inet6 a bit. -DaveM */
...
...
net/ipv6/sit.c
View file @
ac3ebbfb
...
...
@@ -835,19 +835,14 @@ int __init ipip6_fb_tunnel_init(struct net_device *dev)
}
static
struct
inet_protocol
sit_protocol
=
{
ipip6_rcv
,
ipip6_err
,
0
,
IPPROTO_IPV6
,
0
,
NULL
,
"IPv6"
.
handler
=
ipip6_rcv
,
.
err_handler
=
ipip6_err
,
};
#ifdef MODULE
void
sit_cleanup
(
void
)
{
inet_del_protocol
(
&
sit_protocol
);
inet_del_protocol
(
&
sit_protocol
,
IPPROTO_IPV6
);
unregister_netdev
(
&
ipip6_fb_tunnel_dev
);
}
#endif
...
...
@@ -856,9 +851,13 @@ int __init sit_init(void)
{
printk
(
KERN_INFO
"IPv6 over IPv4 tunneling driver
\n
"
);
if
(
inet_add_protocol
(
&
sit_protocol
,
IPPROTO_IPV6
)
<
0
)
{
printk
(
KERN_INFO
"sit init: Can't add protocol
\n
"
);
return
-
EAGAIN
;
}
ipip6_fb_tunnel_dev
.
priv
=
(
void
*
)
&
ipip6_fb_tunnel
;
strcpy
(
ipip6_fb_tunnel_dev
.
name
,
ipip6_fb_tunnel
.
parms
.
name
);
register_netdev
(
&
ipip6_fb_tunnel_dev
);
inet_add_protocol
(
&
sit_protocol
);
return
0
;
}
net/ipv6/tcp_ipv6.c
View file @
ac3ebbfb
...
...
@@ -2156,12 +2156,9 @@ struct proto tcpv6_prot = {
.
get_port
=
tcp_v6_get_port
,
};
static
struct
inet6_protocol
tcpv6_protocol
=
{
.
handler
=
tcp_v6_rcv
,
.
err_handler
=
tcp_v6_err
,
.
protocol
=
IPPROTO_TCP
,
.
name
=
"TCPv6"
,
static
struct
inet6_protocol
tcpv6_protocol
=
{
.
handler
=
tcp_v6_rcv
,
.
err_handler
=
tcp_v6_err
,
};
extern
struct
proto_ops
inet6_stream_ops
;
...
...
@@ -2179,6 +2176,7 @@ static struct inet_protosw tcpv6_protosw = {
void
__init
tcpv6_init
(
void
)
{
/* register inet6 protocol */
inet6_add_protocol
(
&
tcpv6_protocol
);
if
(
inet6_add_protocol
(
&
tcpv6_protocol
,
IPPROTO_TCP
)
<
0
)
printk
(
KERN_ERR
"tcpv6_init: Could not register protocol
\n
"
);
inet6_register_protosw
(
&
tcpv6_protosw
);
}
net/ipv6/udp.c
View file @
ac3ebbfb
...
...
@@ -907,10 +907,8 @@ static int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, int ulen)
}
static
struct
inet6_protocol
udpv6_protocol
=
{
.
handler
=
udpv6_rcv
,
.
err_handler
=
udpv6_err
,
.
protocol
=
IPPROTO_UDP
,
.
name
=
"UDPv6"
,
.
handler
=
udpv6_rcv
,
.
err_handler
=
udpv6_err
,
};
#define LINE_LEN 190
...
...
@@ -1020,6 +1018,7 @@ static struct inet_protosw udpv6_protosw = {
void
__init
udpv6_init
(
void
)
{
inet6_add_protocol
(
&
udpv6_protocol
);
if
(
inet6_add_protocol
(
&
udpv6_protocol
,
IPPROTO_UDP
)
<
0
)
printk
(
KERN_ERR
"udpv6_init: Could not register protocol
\n
"
);
inet6_register_protosw
(
&
udpv6_protosw
);
}
net/sctp/ipv6.c
View file @
ac3ebbfb
...
...
@@ -295,11 +295,6 @@ static struct inet_protosw sctpv6_protosw = {
static
struct
inet6_protocol
sctpv6_protocol
=
{
.
handler
=
sctp_rcv
,
.
err_handler
=
sctp_v6_err
,
.
next
=
NULL
,
.
protocol
=
IPPROTO_SCTP
,
.
copy
=
0
,
.
data
=
NULL
,
.
name
=
"SCTPv6"
};
static
sctp_func_t
sctp_ipv6_specific
=
{
...
...
@@ -320,10 +315,12 @@ static sctp_pf_t sctp_pf_inet6_specific = {
/* Initialize IPv6 support and register with inet6 stack. */
int
sctp_v6_init
(
void
)
{
/* Register inet6 protocol. */
if
(
inet6_add_protocol
(
&
sctpv6_protocol
,
IPPROTO_SCTP
)
<
0
)
return
-
EAGAIN
;
/* Add SCTPv6 to inetsw6 linked list. */
inet6_register_protosw
(
&
sctpv6_protosw
);
/* Register inet6 protocol. */
inet6_add_protocol
(
&
sctpv6_protocol
);
/* Register the SCTP specfic PF_INET6 functions. */
sctp_set_pf_specific
(
PF_INET6
,
&
sctp_pf_inet6_specific
);
...
...
@@ -339,6 +336,6 @@ int sctp_v6_init(void)
void
sctp_v6_exit
(
void
)
{
list_del
(
&
sctp_ipv6_specific
.
list
);
inet6_del_protocol
(
&
sctpv6_protocol
);
inet6_del_protocol
(
&
sctpv6_protocol
,
IPPROTO_SCTP
);
inet6_unregister_protosw
(
&
sctpv6_protosw
);
}
net/sctp/protocol.c
View file @
ac3ebbfb
...
...
@@ -434,10 +434,8 @@ struct inet_protosw sctp_protosw = {
/* Register with IP layer. */
static
struct
inet_protocol
sctp_protocol
=
{
.
handler
=
sctp_rcv
,
/* SCTP input handler. */
.
err_handler
=
sctp_v4_err
,
/* SCTP error control */
.
protocol
=
IPPROTO_SCTP
,
/* protocol ID */
.
name
=
"SCTP"
/* name */
.
handler
=
sctp_rcv
,
.
err_handler
=
sctp_v4_err
,
};
/* IPv4 address related functions. */
...
...
@@ -485,12 +483,13 @@ int sctp_init(void)
int
i
;
int
status
=
0
;
/* Add SCTP to inet_protos hash table. */
if
(
inet_add_protocol
(
&
sctp_protocol
,
IPPROTO_SCTP
)
<
0
)
return
-
EAGAIN
;
/* Add SCTP to inetsw linked list. */
inet_register_protosw
(
&
sctp_protosw
);
/* Add SCTP to inet_protos hash table. */
inet_add_protocol
(
&
sctp_protocol
);
/* Initialize proc fs directory. */
sctp_proc_init
();
...
...
@@ -626,7 +625,7 @@ int sctp_init(void)
err_ahash_alloc:
sctp_dbg_objcnt_exit
();
sctp_proc_exit
();
inet_del_protocol
(
&
sctp_protocol
);
inet_del_protocol
(
&
sctp_protocol
,
IPPROTO_SCTP
);
inet_unregister_protosw
(
&
sctp_protosw
);
return
status
;
}
...
...
@@ -656,7 +655,7 @@ void sctp_exit(void)
sctp_dbg_objcnt_exit
();
sctp_proc_exit
();
inet_del_protocol
(
&
sctp_protocol
);
inet_del_protocol
(
&
sctp_protocol
,
IPPROTO_SCTP
);
inet_unregister_protosw
(
&
sctp_protosw
);
}
...
...
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