linux-decnet-user Mailing List for DECnet for Linux
Brought to you by:
chrissie_c,
ph3-der-loewe
You can subscribe to this list here.
| 2000 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
(8) |
Jun
(39) |
Jul
(30) |
Aug
(23) |
Sep
(9) |
Oct
(9) |
Nov
(30) |
Dec
(24) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2001 |
Jan
(12) |
Feb
(4) |
Mar
(21) |
Apr
|
May
(3) |
Jun
(3) |
Jul
(13) |
Aug
(13) |
Sep
(18) |
Oct
(10) |
Nov
(25) |
Dec
(2) |
| 2002 |
Jan
(7) |
Feb
(14) |
Mar
(15) |
Apr
(29) |
May
(10) |
Jun
(23) |
Jul
(76) |
Aug
(52) |
Sep
(15) |
Oct
(47) |
Nov
(12) |
Dec
(1) |
| 2003 |
Jan
(5) |
Feb
(12) |
Mar
(21) |
Apr
(26) |
May
(66) |
Jun
(16) |
Jul
(13) |
Aug
(7) |
Sep
(21) |
Oct
(11) |
Nov
(4) |
Dec
(11) |
| 2004 |
Jan
(18) |
Feb
(1) |
Mar
(1) |
Apr
(20) |
May
(10) |
Jun
(4) |
Jul
(9) |
Aug
(9) |
Sep
|
Oct
(5) |
Nov
(13) |
Dec
(8) |
| 2005 |
Jan
(23) |
Feb
(2) |
Mar
(1) |
Apr
|
May
(11) |
Jun
(3) |
Jul
(5) |
Aug
(15) |
Sep
(3) |
Oct
(13) |
Nov
(2) |
Dec
(7) |
| 2006 |
Jan
(5) |
Feb
(8) |
Mar
(6) |
Apr
(6) |
May
|
Jun
|
Jul
(1) |
Aug
(5) |
Sep
(2) |
Oct
(6) |
Nov
|
Dec
(3) |
| 2007 |
Jan
|
Feb
(6) |
Mar
(3) |
Apr
(1) |
May
|
Jun
(5) |
Jul
(7) |
Aug
|
Sep
(7) |
Oct
(7) |
Nov
(4) |
Dec
(2) |
| 2008 |
Jan
(10) |
Feb
(5) |
Mar
(2) |
Apr
(2) |
May
|
Jun
|
Jul
(14) |
Aug
(3) |
Sep
(6) |
Oct
(7) |
Nov
|
Dec
|
| 2009 |
Jan
(4) |
Feb
(1) |
Mar
|
Apr
(2) |
May
(2) |
Jun
(1) |
Jul
(3) |
Aug
(15) |
Sep
(9) |
Oct
(1) |
Nov
(2) |
Dec
|
| 2010 |
Jan
|
Feb
(5) |
Mar
(2) |
Apr
|
May
(3) |
Jun
|
Jul
(5) |
Aug
(2) |
Sep
(6) |
Oct
(1) |
Nov
(15) |
Dec
|
| 2011 |
Jan
(4) |
Feb
(1) |
Mar
(11) |
Apr
|
May
|
Jun
(17) |
Jul
(1) |
Aug
|
Sep
|
Oct
|
Nov
(3) |
Dec
(8) |
| 2012 |
Jan
|
Feb
(5) |
Mar
|
Apr
|
May
(8) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2013 |
Jan
(12) |
Feb
(15) |
Mar
(11) |
Apr
(1) |
May
(3) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2014 |
Jan
|
Feb
|
Mar
|
Apr
(2) |
May
|
Jun
(5) |
Jul
(1) |
Aug
(3) |
Sep
|
Oct
|
Nov
|
Dec
|
| 2015 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(3) |
Dec
|
| 2016 |
Jan
|
Feb
(14) |
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2017 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(1) |
Jun
(1) |
Jul
(1) |
Aug
|
Sep
|
Oct
(1) |
Nov
(3) |
Dec
|
| 2018 |
Jan
|
Feb
(3) |
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
(1) |
Sep
|
Oct
|
Nov
(1) |
Dec
|
| 2019 |
Jan
(2) |
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
|
| 2020 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
(4) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
1
|
2
|
3
(1) |
4
(1) |
5
|
|
6
|
7
|
8
(1) |
9
|
10
|
11
|
12
|
|
13
|
14
|
15
(1) |
16
(1) |
17
(2) |
18
(3) |
19
|
|
20
(1) |
21
|
22
|
23
(1) |
24
|
25
(4) |
26
(3) |
|
27
(1) |
28
(1) |
29
(4) |
30
(1) |
|
|
|
|
From: Patrick C. <pa...@ty...> - 2003-04-30 07:25:38
|
On Tue, Apr 29, 2003 at 09:38:16PM +0200, BASSIR Mohcine wrote:
>
> So,
>
> What is it the patch for the kernel 2.4 because i have do nothing on the
> kernel version that is installed by
> the Mandrake 9.1 version. I have only recompile the Xserver with the
> decnet support.
I posted a partial patch for this when you first reported the problem last
Novemeber. A better one (which was forwarded to me but not to the list for some
reason) is below:
--- net/decnet/af_decnet.c.old 2002-11-04 14:12:26.000000000 -0200
+++ net/decnet/af_decnet.c 2002-11-04 12:45:24.000000000 -0200
@@ -1771,7 +1771,7 @@
goto out;
if (signal_pending(current)) {
- rv = -ERESTARTSYS;
+ rv = -EAGAIN;
goto out;
}
@@ -1964,7 +1964,8 @@
goto out;
if (signal_pending(current)) {
- err = -ERESTARTSYS;
+ /* VMH - testing X crash - printk("DECnet 6\n"); */
+ err = -EAGAIN;
goto out;
}
> If i want to passed the kernel 2.5, what is it the version that i can
> used with my mandrake distrib. And it is
> possible to find an rpm version ?
I have no idea about Mandrake at all I'm afraid. I get all my kernels from
ftp.uk.kernel.org
patrick
|
|
From: BASSIR M. <Moh...@ax...> - 2003-04-29 19:37:38
|
IA0KU28sDQogDQpXaGF0IGlzIGl0IHRoZSBwYXRjaCBmb3IgdGhlIGtlcm5lbCAyLjQgYmVjYXVz ZSBpIGhhdmUgZG8gbm90aGluZyBvbiB0aGUga2VybmVsIHZlcnNpb24gdGhhdCBpcyBpbnN0YWxs ZWQgYnkNCnRoZSBNYW5kcmFrZSA5LjEgdmVyc2lvbi4gSSBoYXZlIG9ubHkgcmVjb21waWxlIHRo ZSBYc2VydmVyIHdpdGggdGhlIA0KZGVjbmV0IHN1cHBvcnQuIA0KIA0KSWYgIGkgd2FudCB0byBw YXNzZWQgdGhlIGtlcm5lbCAyLjUsIHdoYXQgaXMgaXQgdGhlIHZlcnNpb24gdGhhdCBpIGNhbiB1 c2VkIHdpdGggbXkgbWFuZHJha2UgZGlzdHJpYi4gQW5kIGl0IGlzIA0KcG9zc2libGUgdG8gZmlu ZCBhbiBycG0gdmVyc2lvbiA/IA0KIA0KVGhhbmtzDQogDQpNLkJhc3Npcg0KIA0KDQoJLS0tLS0t LS0gTWVzc2FnZSBkJ29yaWdpbmUtLS0tLS0tLSANCglEZTogUGF0cmljayBDYXVsZmllbGQgW21h aWx0bzpwYXRyaWNrQHR5a2VwZW5ndWluLmNvbV0gDQoJRGF0ZTogbWFyLiAyOS8wNC8yMDAzIDE3 OjA0IA0KCcOAOiBCQVNTSVIgTW9oY2luZSANCglDYzogREVDbmV0IGxpc3QgDQoJT2JqZXQ6IFJl OiBSRSA6IFtMaW51eC1kZWNuZXQtdXNlcl0gWCBhbmQgRGVjbmV0DQoJDQoJDQoNCglPbiBUdWUs IEFwciAyOSwgMjAwMyBhdCAwMzowNzozMFBNICswMjAwLCBCQVNTSVIgTW9oY2luZSB3cm90ZToN Cgk+IFNvcnJ5LA0KCT4NCgk+ICAgICAgIEl0J3MgYSBsYW5ndWFnZSBlcnJvciAoaSdtIG5vdCBy ZWFsbHkgZ29vZCBpbiBlbmdsaXNoKS4NCgk+DQoJPiBJIGhhdmUgZG86DQoJPg0KCT4gMSkNCgk+ ICQgbGRkIC91c3IvWDExUjYvYmluL1hGcmVlODYNCgk+DQoJPiByZXN1bHRzOiBsaWJkbmV0LnNv LjIgPT4gL3Vzci9saWIvbGliZG5ldC5zby4yICgweDQwMDIzMDAwKQ0KCT4NCgk+IDIpDQoJPg0K CT4gJCBjYXQgL3Byb2MvbmV0L2RlY25ldA0KCT4NCgk+IHJlc3VsdHM6DQoJPg0KCT4gTG9jYWwg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUmVtb3RlDQoJPiAg ICAzLjIwMC8yMDExIDAwNTA6Mjg4MyAwMTE4OjAwMTYgMiBST09UICAgICAgICAgICAgICAgIDMu MjYyLzAwMEIgMDExODowMDE2IDAwNDk6Mjg4MiAyIDQyIFJVTiBJTU1FRA0KCT4gICAgMC4wLzAw MDAgMDAwMTowMDAxIDAwMDA6MDAwMCAyIFgkWDAgICAgICAgICAgICAgICAgMC4wLzAwMDAgMDAw MDowMDAwIDAwMDA6MDAwMCAyIDAgT1BFTiBJTU1FRA0KCT4NCgk+DQoJPiBJdCdzIGFwcGVhciBp dCBpcyBvayBvciBub3QgPw0KCT4gSWYgeWVzIC4uLg0KCQ0KCVRoYXQgbG9va3MgZmluZS4NCgkN CglpcyB3aGF0IHlvdSBhcmUgc2VlaW5nIHRoZSBYLXNlcnZlciBoYW5ncyB5b3Ugd2VyZSBoYXZp bmcgcHJldmlvdXNseT8gSWYgc28gY2FuDQoJeW91IHNlbmQgdGhlIHBhdGNoIHlvdSBhcmUgdXNp bmcgZm9yIERFQ25ldCBqdXN0IHRvIG1ha2Ugc3VyZSB0aGF0IHlvdSBoYXZlIGFsbA0KCXRoZSBj aGFuZ2VzIHRoYXQgd2VyZSBtYWRlIHRvIHRoYXQgYml0IC0gSSBoYXZlIGEgZmVlbGluZyB0aGF0 IGFub3RoZXIgZml4IHdhcw0KCW1hZGUgYW5kIGFtIG5vdCBzdXJlIHlvdSBnb3QgaXQuDQoJDQoJ QW5vdGhlciB0aGluZyB5b3UgbWlnaHQgbGlrZSB0byB0cnkgaXMgTGludXggMi41LiBUaGVyZSBh cmUgbG90cyBvZiBnb29kIGZpeGVzDQoJYW5kIGNoYW5nZXMgaW4gdGhlIDIuNSBjb2RlLiBJIGFw cHJlY2lhdGUgdGhlIGxpbnV4LTIuNSBpcyBub3Qgc29tZXRoaW5nIHlvdQ0KCXdhbnQgdG8gdHJ5 IG9uIGEgcHJvZHVjdGlvbiBtYWNoaW5lIGJ1dCBpZiBpdCB3b3JrcyBvbiAyLjUgYW5kIG5vdCBv biAyLjQgdGhlbg0KCXRoYXQgbWlnaHQgYmUgYSB1c2VmdWwgcGllY2Ugb2YgaW5mb3JtYXRpb24u DQoJDQoJcmVnYXJkcywNCgkNCglwYXRyaWNrDQoJDQoJDQoNCg== |
|
From: Patrick C. <pa...@ty...> - 2003-04-29 15:05:20
|
On Tue, Apr 29, 2003 at 03:07:30PM +0200, BASSIR Mohcine wrote: > Sorry, > > It's a language error (i'm not really good in english). > > I have do: > > 1) > $ ldd /usr/X11R6/bin/XFree86 > > results: libdnet.so.2 => /usr/lib/libdnet.so.2 (0x40023000) > > 2) > > $ cat /proc/net/decnet > > results: > > Local Remote > 3.200/2011 0050:2883 0118:0016 2 ROOT 3.262/000B 0118:0016 0049:2882 2 42 RUN IMMED > 0.0/0000 0001:0001 0000:0000 2 X$X0 0.0/0000 0000:0000 0000:0000 2 0 OPEN IMMED > > > It's appear it is ok or not ? > If yes ... That looks fine. is what you are seeing the X-server hangs you were having previously? If so can you send the patch you are using for DECnet just to make sure that you have all the changes that were made to that bit - I have a feeling that another fix was made and am not sure you got it. Another thing you might like to try is Linux 2.5. There are lots of good fixes and changes in the 2.5 code. I appreciate the linux-2.5 is not something you want to try on a production machine but if it works on 2.5 and not on 2.4 then that might be a useful piece of information. regards, patrick |
|
From: Steven W. <st...@gw...> - 2003-04-29 10:29:16
|
Hi,
Here is a patch against 2.5.68 which fixes the bugs I introduced last
time and has some more tidying up as well. The features are:
o Introduce kfree_release() in seq_file.c for use of DECnet and eventually
IP as well
o Add proc_net_fops_create() like proc_net_create() but with file_operations
argument to use with seq_file code (cleans up some #ifdefs)
o Remove blksize from decnet device parameters - use the device mtu like we
ought to.
o Remove /proc/net/decnet_route file - I don't think enybody ever used it
and it was lacking a full enough description of the routes to be useful.
ip -D route list is much better :-)
o Add rt_local_src entry to decnet routes so that we get the local source
address right when forwarding.
o Add netfilter subdir for decnet and add the routing grabulator
o Add correct proto argument to struct flowi for routing
o MSG_MORE in sendmsg (ignored, but accepted whereas before we'd error)
o /proc/net/decnet converted to seq_file
o /proc/net/decnet_dev converted to seq_file
o /proc/net/decnet_cache converted to seq_file
o Use pskb_may_pull() and add code to linearize skbs on the input path
except for those containing data.
o Fix returned packet code (mostly - some left to do)
o update_pmtu() method for decnet dst entries
o Fix bug in forwarding to get IE bit set correctly
o Fix compile bugs with CONFIG_DECNET_ROUTE_FWMARK
o Fix zero dest code to grab an address from loopback
o Fix local routes in dn_route_output_slow()
So this should solve all the major problems found in the last patch that I
know about. If you find any more, let me know. I'm hoping to get this
into the kernel shortly once merged with the changes which have recently
gone in to do with module ref counting etc,
Steve.
------------------------------------------------------------------------------
diff -Nru linux-2.5.68/fs/seq_file.c linux/fs/seq_file.c
--- linux-2.5.68/fs/seq_file.c Sun Apr 20 03:27:58 2003
+++ linux/fs/seq_file.c Mon Apr 21 14:40:35 2003
@@ -338,3 +338,13 @@
kfree(op);
return res;
}
+
+int kfree_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = file->private_data;
+
+ kfree(seq->private);
+ seq->private = NULL;
+ return seq_release(inode, file);
+}
+
diff -Nru linux-2.5.68/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- linux-2.5.68/include/linux/proc_fs.h Wed Jan 1 19:20:49 2003
+++ linux/include/linux/proc_fs.h Tue Apr 22 01:32:43 2003
@@ -163,6 +163,15 @@
return create_proc_info_entry(name,mode,proc_net,get_info);
}
+static inline struct proc_dir_entry *proc_net_fops_create(const char *name,
+ mode_t mode, struct file_operations *fops)
+{
+ struct proc_dir_entry *res = create_proc_entry(name, mode, proc_net);
+ if (res)
+ res->proc_fops = fops;
+ return res;
+}
+
static inline void proc_net_remove(const char *name)
{
remove_proc_entry(name,proc_net);
@@ -171,7 +180,7 @@
#else
#define proc_root_driver NULL
-
+#define proc_net_fops_create(name,mode,fops) do {} while(0)
static inline struct proc_dir_entry *proc_net_create(const char *name, mode_t mode,
get_info_t *get_info) {return NULL;}
static inline void proc_net_remove(const char *name) {}
diff -Nru linux-2.5.68/include/linux/seq_file.h linux/include/linux/seq_file.h
--- linux-2.5.68/include/linux/seq_file.h Wed Jan 1 19:23:19 2003
+++ linux/include/linux/seq_file.h Mon Apr 21 14:41:12 2003
@@ -60,5 +60,6 @@
int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
int single_release(struct inode *, struct file *);
+int kfree_release(struct inode *, struct file *);
#endif
#endif
diff -Nru linux-2.5.68/include/net/dn_dev.h linux/include/net/dn_dev.h
--- linux-2.5.68/include/net/dn_dev.h Sun Apr 20 03:28:00 2003
+++ linux/include/net/dn_dev.h Mon Apr 21 04:13:14 2003
@@ -71,7 +71,6 @@
#define DN_DEV_MPOINT 4
int state; /* Initial state */
int forwarding; /* 0=EndNode, 1=L1Router, 2=L2Router */
- unsigned short blksize; /* Block Size */
unsigned long t2; /* Default value of t2 */
unsigned long t3; /* Default value of t3 */
int priority; /* Priority to be a router */
diff -Nru linux-2.5.68/include/net/dn_fib.h linux/include/net/dn_fib.h
--- linux-2.5.68/include/net/dn_fib.h Sun Apr 20 03:28:00 2003
+++ linux/include/net/dn_fib.h Wed Apr 23 09:43:44 2003
@@ -101,10 +101,6 @@
int (*lookup)(struct dn_fib_table *t, const struct flowi *fl,
struct dn_fib_res *res);
int (*flush)(struct dn_fib_table *t);
-#ifdef CONFIG_PROC_FS
- int (*get_info)(struct dn_fib_table *table, char *buf,
- int first, int count);
-#endif /* CONFIG_PROC_FS */
int (*dump)(struct dn_fib_table *t, struct sk_buff *skb, struct netlink_callback *cb);
unsigned char data[0];
@@ -183,6 +179,9 @@
extern struct dn_fib_table *dn_fib_tables[];
#else /* Endnode */
+
+#define dn_fib_init() (0)
+#define dn_fib_cleanup() (0)
#define dn_fib_lookup(fl, res) (-ESRCH)
#define dn_fib_info_put(fi) do { } while(0)
diff -Nru linux-2.5.68/include/net/dn_route.h linux/include/net/dn_route.h
--- linux-2.5.68/include/net/dn_route.h Sun Apr 20 03:28:00 2003
+++ linux/include/net/dn_route.h Wed Apr 23 07:44:23 2003
@@ -74,7 +74,7 @@
__u16 rt_saddr;
__u16 rt_daddr;
__u16 rt_gateway;
- __u16 __padding;
+ __u16 rt_local_src; /* Source used for forwarding packets */
__u16 rt_src_map;
__u16 rt_dst_map;
diff -Nru linux-2.5.68/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.5.68/kernel/ksyms.c Sun Apr 20 03:28:00 2003
+++ linux/kernel/ksyms.c Mon Apr 28 12:06:26 2003
@@ -537,6 +537,7 @@
EXPORT_SYMBOL(seq_lseek);
EXPORT_SYMBOL(single_open);
EXPORT_SYMBOL(single_release);
+EXPORT_SYMBOL(kfree_release);
/* Program loader interfaces */
#ifdef CONFIG_MMU
diff -Nru linux-2.5.68/net/decnet/Kconfig linux/net/decnet/Kconfig
--- linux-2.5.68/net/decnet/Kconfig Wed Jan 1 19:23:15 2003
+++ linux/net/decnet/Kconfig Wed Apr 23 10:29:31 2003
@@ -17,11 +17,11 @@
depends on DECNET && EXPERIMENTAL
---help---
Add support for turning your DECnet Endnode into a level 1 or 2
- router. This is an unfinished option for developers only. If you
+ router. This is an experimental, but functional option. If you
do say Y here, then make sure that you also say Y to "Kernel/User
network link driver", "Routing messages" and "Network packet
filtering". The first two are required to allow configuration via
- rtnetlink (currently you need Alexey Kuznetsov's iproute2 package
+ rtnetlink (you will need Alexey Kuznetsov's iproute2 package
from <ftp://ftp.inr.ac.ru/>). The "Network packet filtering" option
will be required for the forthcoming routing daemon to work.
@@ -34,4 +34,6 @@
If you say Y here, you will be able to specify different routes for
packets with different FWMARK ("firewalling mark") values
(see ipchains(8), "-m" argument).
+
+source "net/decnet/netfilter/Kconfig"
diff -Nru linux-2.5.68/net/decnet/Makefile linux/net/decnet/Makefile
--- linux-2.5.68/net/decnet/Makefile Wed Jan 1 19:21:18 2003
+++ linux/net/decnet/Makefile Wed Apr 23 10:27:53 2003
@@ -1,7 +1,10 @@
obj-$(CONFIG_DECNET) += decnet.o
-decnet-y := af_decnet.o dn_nsp_in.o dn_nsp_out.o dn_route.o dn_dev.o dn_neigh.o dn_timer.o
+decnet-y := af_decnet.o dn_nsp_in.o dn_nsp_out.o \
+ dn_route.o dn_dev.o dn_neigh.o dn_timer.o
decnet-$(CONFIG_DECNET_ROUTER) += dn_fib.o dn_rules.o dn_table.o
-decnet-$(CONFIG_DECNET_FW) += dn_fw.o
decnet-y += sysctl_net_decnet.o
+
+obj-$(CONFIG_NETFILTER) += netfilter/
+
diff -Nru linux-2.5.68/net/decnet/TODO linux/net/decnet/TODO
--- linux-2.5.68/net/decnet/TODO Sun Apr 20 03:28:01 2003
+++ linux/net/decnet/TODO Wed Apr 23 10:31:38 2003
@@ -23,15 +23,9 @@
o check MSG_CTRUNC is set where it should be.
- o Start to hack together user level software and add more DECnet support
- in ifconfig for example.
-
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.7.xx]
- o Add the routing message grabbing netfilter module [written, tested,
- awaiting merge]
-
o Add perfect socket hashing - an idea suggested by Paul Koning. Currently
we have a half-way house scheme which seems to work reasonably well, but
the full scheme is still worth implementing, its not not top of my list
@@ -44,6 +38,4 @@
o DECnet sendpages() function
o AIO for DECnet
-
- o Eliminate dn_db->parms.blksize
diff -Nru linux-2.5.68/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c
--- linux-2.5.68/net/decnet/af_decnet.c Sun Apr 20 03:28:01 2003
+++ linux/net/decnet/af_decnet.c Mon Apr 28 12:19:47 2003
@@ -116,6 +116,7 @@
#include <linux/inet.h>
#include <linux/route.h>
#include <linux/netfilter.h>
+#include <linux/seq_file.h>
#include <net/sock.h>
#include <net/tcp.h>
#include <net/flow.h>
@@ -1008,6 +1009,7 @@
fl.fld_dst = dn_saddr2dn(&scp->peer);
fl.fld_src = dn_saddr2dn(&scp->addr);
dn_sk_ports_copy(&fl, scp);
+ fl.proto = DNPROTO_NSP;
if (dn_route_output_sock(&sk->dst_cache, &fl, sk, flags) < 0)
goto out;
sk->route_caps = sk->dst_cache->dev->features;
@@ -1971,7 +1973,7 @@
unsigned char fctype;
long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
- if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL))
+ if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL|MSG_MORE))
return -EOPNOTSUPP;
if (addr_len && (addr_len != sizeof(struct sockaddr_dn)))
@@ -2150,6 +2152,95 @@
.data = (void*)1,
};
+#ifdef CONFIG_PROC_FS
+struct dn_iter_state {
+ int bucket;
+};
+
+static struct sock *dn_socket_get_first(struct seq_file *seq)
+{
+ struct dn_iter_state *state = seq->private;
+ struct sock *n = NULL;
+
+ for(state->bucket = 0;
+ state->bucket < DN_SK_HASH_SIZE;
+ ++state->bucket) {
+ n = dn_sk_hash[state->bucket];
+ if (n)
+ break;
+ }
+
+ return n;
+}
+
+static struct sock *dn_socket_get_next(struct seq_file *seq,
+ struct sock *n)
+{
+ struct dn_iter_state *state = seq->private;
+
+ n = n->next;
+try_again:
+ if (n)
+ goto out;
+ if (++state->bucket >= DN_SK_HASH_SIZE)
+ goto out;
+ n = dn_sk_hash[state->bucket];
+ goto try_again;
+out:
+ return n;
+}
+
+static struct sock *socket_get_idx(struct seq_file *seq, loff_t *pos)
+{
+ struct sock *sk = dn_socket_get_first(seq);
+
+ if (sk) {
+ while(*pos && (sk = dn_socket_get_next(seq, sk)))
+ --*pos;
+ }
+ return *pos ? NULL : sk;
+}
+
+static void *dn_socket_get_idx(struct seq_file *seq, loff_t pos)
+{
+ void *rc;
+ read_lock_bh(&dn_hash_lock);
+ rc = socket_get_idx(seq, &pos);
+ if (!rc) {
+ read_unlock_bh(&dn_hash_lock);
+ }
+ return rc;
+}
+
+static void *dn_socket_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ return *pos ? dn_socket_get_idx(seq, *pos - 1) : (void*)1;
+}
+
+static void *dn_socket_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ void *rc;
+
+ if (v == (void*)1) {
+ rc = dn_socket_get_idx(seq, 0);
+ goto out;
+ }
+
+ rc = dn_socket_get_next(seq, v);
+ if (rc)
+ goto out;
+ read_unlock_bh(&dn_hash_lock);
+out:
+ ++*pos;
+ return rc;
+}
+
+static void dn_socket_seq_stop(struct seq_file *seq, void *v)
+{
+ if (v && v != (void*)1)
+ read_unlock_bh(&dn_hash_lock);
+}
+
#define IS_NOT_PRINTABLE(x) ((x) < 32 || (x) > 126)
static void dn_printable_object(struct sockaddr_dn *dn, unsigned char *buf)
@@ -2170,70 +2261,87 @@
}
}
-static int dn_get_info(char *buffer, char **start, off_t offset, int length)
+static inline void dn_socket_format_entry(struct seq_file *seq, struct sock *sk)
{
- struct sock *sk;
- struct dn_scp *scp;
- int len = 0;
- off_t pos = 0;
- off_t begin = 0;
+ struct dn_scp *scp = DN_SK(sk);
char buf1[DN_ASCBUF_LEN];
char buf2[DN_ASCBUF_LEN];
char local_object[DN_MAXOBJL+3];
char remote_object[DN_MAXOBJL+3];
- int i;
- len += sprintf(buffer + len, "Local Remote\n");
+ dn_printable_object(&scp->addr, local_object);
+ dn_printable_object(&scp->peer, remote_object);
- read_lock(&dn_hash_lock);
- for(i = 0; i < DN_SK_HASH_SIZE; i++) {
- for(sk = dn_sk_hash[i]; sk != NULL; sk = sk->next) {
- scp = DN_SK(sk);
-
- dn_printable_object(&scp->addr, local_object);
- dn_printable_object(&scp->peer, remote_object);
-
- len += sprintf(buffer + len,
- "%6s/%04X %04d:%04d %04d:%04d %01d %-16s %6s/%04X %04d:%04d %04d:%04d %01d %-16s %4s %s\n",
- dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->addr)), buf1),
- scp->addrloc,
- scp->numdat,
- scp->numoth,
- scp->ackxmt_dat,
- scp->ackxmt_oth,
- scp->flowloc_sw,
- local_object,
- dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->peer)), buf2),
- scp->addrrem,
- scp->numdat_rcv,
- scp->numoth_rcv,
- scp->ackrcv_dat,
- scp->ackrcv_oth,
- scp->flowrem_sw,
- remote_object,
- dn_state2asc(scp->state),
- ((scp->accept_mode == ACC_IMMED) ? "IMMED" : "DEFER"));
-
- pos = begin + len;
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
- if (pos > (offset + length))
- break;
- }
+ seq_printf(seq,
+ "%6s/%04X %04d:%04d %04d:%04d %01d %-16s "
+ "%6s/%04X %04d:%04d %04d:%04d %01d %-16s %4s %s\n",
+ dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->addr)), buf1),
+ scp->addrloc,
+ scp->numdat,
+ scp->numoth,
+ scp->ackxmt_dat,
+ scp->ackxmt_oth,
+ scp->flowloc_sw,
+ local_object,
+ dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->peer)), buf2),
+ scp->addrrem,
+ scp->numdat_rcv,
+ scp->numoth_rcv,
+ scp->ackrcv_dat,
+ scp->ackrcv_oth,
+ scp->flowrem_sw,
+ remote_object,
+ dn_state2asc(scp->state),
+ ((scp->accept_mode == ACC_IMMED) ? "IMMED" : "DEFER"));
+}
+
+static int dn_socket_seq_show(struct seq_file *seq, void *v)
+{
+ if (v == (void*)1) {
+ seq_puts(seq, "Local Remote\n");
+ } else {
+ dn_socket_format_entry(seq, v);
}
- read_unlock(&dn_hash_lock);
+ return 0;
+}
- *start = buffer + (offset - begin);
- len -= (offset - begin);
+static struct seq_operations dn_socket_seq_ops = {
+ .start = dn_socket_seq_start,
+ .next = dn_socket_seq_next,
+ .stop = dn_socket_seq_stop,
+ .show = dn_socket_seq_show,
+};
- if (len > length)
- len = length;
+static int dn_socket_seq_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ int rc = -ENOMEM;
+ struct dn_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
- return len;
+ if (!s)
+ goto out;
+
+ rc = seq_open(file, &dn_socket_seq_ops);
+ if (rc)
+ goto out_kfree;
+
+ seq = file->private_data;
+ seq->private = s;
+ memset(s, 0, sizeof(*s));
+out:
+ return rc;
+out_kfree:
+ kfree(s);
+ goto out;
}
+static struct file_operations dn_socket_seq_fops = {
+ .open = dn_socket_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = kfree_release,
+};
+#endif
static struct net_proto_family dn_family_ops = {
.family = AF_DECnet,
@@ -2264,13 +2372,11 @@
void dn_register_sysctl(void);
void dn_unregister_sysctl(void);
-
MODULE_DESCRIPTION("The Linux DECnet Network Protocol");
MODULE_AUTHOR("Linux DECnet Project Team");
MODULE_LICENSE("GPL");
-
-static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.5.67s (C) 1995-2003 Linux DECnet Project Team\n";
+static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.5.68s (C) 1995-2003 Linux DECnet Project Team\n";
static int __init decnet_init(void)
{
@@ -2287,15 +2393,12 @@
dev_add_pack(&dn_dix_packet_type);
register_netdevice_notifier(&dn_dev_notifier);
- proc_net_create("decnet", 0, dn_get_info);
+ proc_net_fops_create("decnet", S_IRUGO, &dn_socket_seq_fops);
dn_neigh_init();
dn_dev_init();
dn_route_init();
-
-#ifdef CONFIG_DECNET_ROUTER
dn_fib_init();
-#endif /* CONFIG_DECNET_ROUTER */
dn_register_sysctl();
@@ -2322,10 +2425,7 @@
dn_route_cleanup();
dn_dev_cleanup();
dn_neigh_cleanup();
-
-#ifdef CONFIG_DECNET_ROUTER
dn_fib_cleanup();
-#endif /* CONFIG_DECNET_ROUTER */
proc_net_remove("decnet");
diff -Nru linux-2.5.68/net/decnet/dn_dev.c linux/net/decnet/dn_dev.c
--- linux-2.5.68/net/decnet/dn_dev.c Sun Apr 20 03:28:01 2003
+++ linux/net/decnet/dn_dev.c Mon Apr 28 13:15:56 2003
@@ -20,6 +20,8 @@
* Steve Whitehouse : /proc/sys/net/decnet/conf/<sys>/forwarding
* Steve Whitehouse : Removed timer1 - it's a user space issue now
* Patrick Caulfield : Fixed router hello message format
+ * Steve Whitehouse : Got rid of constant sizes for blksize for
+ * devices. All mtu based now.
*/
#include <linux/config.h>
@@ -28,6 +30,7 @@
#include <linux/net.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/if_arp.h>
@@ -72,16 +75,13 @@
static int dn_eth_up(struct net_device *);
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, struct dn_ifaddr *ifa);
-#endif
static struct dn_dev_parms dn_dev_list[] = {
{
.type = ARPHRD_ETHER, /* Ethernet */
.mode = DN_DEV_BCAST,
.state = DN_DEV_S_RU,
- .blksize = 1498,
.t2 = 1,
.t3 = 10,
.name = "ethernet",
@@ -94,7 +94,6 @@
.type = ARPHRD_IPGRE, /* DECnet tunneled over GRE in IP */
.mode = DN_DEV_BCAST,
.state = DN_DEV_S_RU,
- .blksize = 1400,
.t2 = 1,
.t3 = 10,
.name = "ipgre",
@@ -106,7 +105,6 @@
.type = ARPHRD_X25, /* Bog standard X.25 */
.mode = DN_DEV_UCAST,
.state = DN_DEV_S_DS,
- .blksize = 230,
.t2 = 1,
.t3 = 120,
.name = "x25",
@@ -119,7 +117,6 @@
.type = ARPHRD_PPP, /* DECnet over PPP */
.mode = DN_DEV_BCAST,
.state = DN_DEV_S_RU,
- .blksize = 230,
.t2 = 1,
.t3 = 10,
.name = "ppp",
@@ -127,24 +124,20 @@
.timer3 = dn_send_brd_hello,
},
#endif
-#if 0
{
.type = ARPHRD_DDCMP, /* DECnet over DDCMP */
.mode = DN_DEV_UCAST,
.state = DN_DEV_S_DS,
- .blksize = 230,
.t2 = 1,
.t3 = 120,
.name = "ddcmp",
.ctl_name = NET_DECNET_CONF_DDCMP,
.timer3 = dn_send_ptp_hello,
},
-#endif
{
.type = ARPHRD_LOOPBACK, /* Loopback interface - always last */
.mode = DN_DEV_BCAST,
.state = DN_DEV_S_RU,
- .blksize = 1498,
.t2 = 1,
.t3 = 10,
.name = "loopback",
@@ -254,6 +247,23 @@
}, {0}}
};
+static inline __u16 mtu2blksize(struct net_device *dev)
+{
+ u32 blksize = dev->mtu;
+ if (blksize > 0xffff)
+ blksize = 0xffff;
+ /*
+ * We don't bother doing this for loopback - it might be outside the
+ * spec, but nobody will every see the packets outside the box so
+ * they'll never know.
+ */
+ if (dev->type == ARPHRD_ETHER ||
+ dev->type == ARPHRD_PPP ||
+ dev->type == ARPHRD_IPGRE)
+ blksize -= 2;
+ return (__u16)blksize;
+}
+
static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
{
struct dn_dev_sysctl_table *t;
@@ -858,7 +868,7 @@
memcpy(msg->tiver, dn_eco_version, 3);
dn_dn2eth(msg->id, ifa->ifa_local);
msg->iinfo = DN_RT_INFO_ENDN;
- msg->blksize = dn_htons(dn_db->parms.blksize);
+ msg->blksize = dn_htons(mtu2blksize(dev));
msg->area = 0x00;
memset(msg->seed, 0, 8);
memcpy(msg->neighbor, dn_hiord, ETH_ALEN);
@@ -920,10 +930,10 @@
unsigned short *pktlen;
char *src;
- if (dn_db->parms.blksize < (26 + 7))
+ if (mtu2blksize(dev) < (26 + 7))
return;
- n = dn_db->parms.blksize - 26;
+ n = mtu2blksize(dev) - 26;
n /= 7;
if (n > 32)
@@ -946,7 +956,7 @@
ptr += ETH_ALEN;
*ptr++ = dn_db->parms.forwarding == 1 ?
DN_RT_INFO_L1RT : DN_RT_INFO_L2RT;
- *((unsigned short *)ptr) = dn_htons(dn_db->parms.blksize);
+ *((unsigned short *)ptr) = dn_htons(mtu2blksize(dev));
ptr += 2;
*ptr++ = dn_db->parms.priority; /* Priority */
*ptr++ = 0; /* Area: Reserved */
@@ -990,16 +1000,13 @@
dn_send_router_hello(dev, ifa);
}
-#if 0
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;
struct sk_buff *skb = dn_alloc_skb(NULL, size, GFP_ATOMIC);
- struct dn_dev *dn_db = dev->dn_ptr;
int i;
unsigned char *ptr;
- struct dn_neigh *dn = (struct dn_neigh *)dn_db->router;
char src[ETH_ALEN];
if (skb == NULL)
@@ -1020,7 +1027,6 @@
dn_dn2eth(src, ifa->ifa_local);
dn_rt_finish_output(skb, dn_rt_all_rt_mcast, src);
}
-#endif
static int dn_eth_up(struct net_device *dev)
{
@@ -1332,6 +1338,63 @@
#ifdef CONFIG_PROC_FS
+static inline struct net_device *dn_dev_get_next(struct seq_file *seq, struct net_device *dev)
+{
+ do {
+ dev = dev->next;
+ } while(dev && !dev->dn_ptr);
+
+ return dev;
+}
+
+static struct net_device *dn_dev_get_idx(struct seq_file *seq, loff_t pos)
+{
+ struct net_device *dev;
+
+ dev = dev_base;
+ if (dev && !dev->dn_ptr)
+ dev = dn_dev_get_next(seq, dev);
+ if (pos) {
+ while(dev && (dev = dn_dev_get_next(seq, dev)))
+ --pos;
+ }
+ return dev;
+}
+
+static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ if (*pos) {
+ struct net_device *dev;
+ read_lock(&dev_base_lock);
+ dev = dn_dev_get_idx(seq, *pos - 1);
+ if (dev == NULL)
+ read_unlock(&dev_base_lock);
+ return dev;
+ }
+ return (void*)1;
+}
+
+static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct net_device *dev = v;
+ loff_t one = 1;
+
+ if (v == (void*)1) {
+ dev = dn_dev_seq_start(seq, &one);
+ } else {
+ dev = dn_dev_get_next(seq, dev);
+ if (dev == NULL)
+ read_unlock(&dev_base_lock);
+ }
+ ++*pos;
+ return dev;
+}
+
+static void dn_dev_seq_stop(struct seq_file *seq, void *v)
+{
+ if (v && v != (void*)1)
+ read_unlock(&dev_base_lock);
+}
static char *dn_type2asc(char type)
{
@@ -1347,56 +1410,50 @@
return "?";
}
-static int decnet_dev_get_info(char *buffer, char **start, off_t offset, int length)
+static int dn_dev_seq_show(struct seq_file *seq, void *v)
{
- struct dn_dev *dn_db;
- struct net_device *dev;
- int len = 0;
- off_t pos = 0;
- off_t begin = 0;
- char peer_buf[DN_ASCBUF_LEN];
- char router_buf[DN_ASCBUF_LEN];
-
-
- len += sprintf(buffer, "Name Flags T1 Timer1 T3 Timer3 BlkSize Pri State DevType Router Peer\n");
+ if (v == (void*)1)
+ seq_puts(seq, "Name Flags T1 Timer1 T3 Timer3 BlkSize Pri State DevType Router Peer\n");
+ else {
+ struct net_device *dev = v;
+ char peer_buf[DN_ASCBUF_LEN];
+ char router_buf[DN_ASCBUF_LEN];
+ struct dn_dev *dn_db = dev->dn_ptr;
- read_lock(&dev_base_lock);
- for (dev = dev_base; dev; dev = dev->next) {
- if ((dn_db = (struct dn_dev *)dev->dn_ptr) == NULL)
- continue;
-
- len += sprintf(buffer + len, "%-8s %1s %04u %04u %04lu %04lu %04hu %03d %02x %-10s %-7s %-7s\n",
+ seq_printf(seq, "%-8s %1s %04u %04u %04lu %04lu"
+ " %04hu %03d %02x %-10s %-7s %-7s\n",
dev->name ? dev->name : "???",
dn_type2asc(dn_db->parms.mode),
0, 0,
dn_db->t3, dn_db->parms.t3,
- dn_db->parms.blksize,
+ mtu2blksize(dev),
dn_db->parms.priority,
dn_db->parms.state, dn_db->parms.name,
dn_db->router ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->router->primary_key), router_buf) : "",
dn_db->peer ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->peer->primary_key), peer_buf) : "");
+ }
+ return 0;
+}
+static struct seq_operations dn_dev_seq_ops = {
+ .start = dn_dev_seq_start,
+ .next = dn_dev_seq_next,
+ .stop = dn_dev_seq_stop,
+ .show = dn_dev_seq_show,
+};
- pos = begin + len;
-
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
- if (pos > offset + length)
- break;
- }
-
- read_unlock(&dev_base_lock);
-
- *start = buffer + (offset - begin);
- len -= (offset - begin);
-
- if (len > length) len = length;
-
- return(len);
+static int dn_dev_seq_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &dn_dev_seq_ops);
}
+static struct file_operations dn_dev_seq_fops = {
+ .open = dn_dev_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
#endif /* CONFIG_PROC_FS */
static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
@@ -1448,9 +1505,7 @@
rtnetlink_links[PF_DECnet] = dnet_rtnetlink_table;
-#ifdef CONFIG_PROC_FS
- proc_net_create("decnet_dev", 0, decnet_dev_get_info);
-#endif /* CONFIG_PROC_FS */
+ proc_net_fops_create("decnet_dev", S_IRUGO, &dn_dev_seq_fops);
#ifdef CONFIG_SYSCTL
{
diff -Nru linux-2.5.68/net/decnet/dn_fib.c linux/net/decnet/dn_fib.c
--- linux-2.5.68/net/decnet/dn_fib.c Sun Apr 20 03:28:01 2003
+++ linux/net/decnet/dn_fib.c Mon Apr 28 10:21:48 2003
@@ -67,18 +67,18 @@
int error;
u8 scope;
} dn_fib_props[RTA_MAX+1] = {
- { .error = 0, .scope = RT_SCOPE_NOWHERE }, /* RTN_UNSPEC */
- { .error = 0, .scope = RT_SCOPE_UNIVERSE }, /* RTN_UNICAST */
- { .error = 0, .scope = RT_SCOPE_HOST }, /* RTN_LOCAL */
- { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_BROADCAST */
- { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_ANYCAST */
- { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_MULTICAST */
- { .error = -EINVAL, .scope = RT_SCOPE_UNIVERSE }, /* RTN_BLACKHOLE */
- { .error = -EHOSTUNREACH, .scope = RT_SCOPE_UNIVERSE }, /* RTN_UNREACHABLE */
- { .error = -EACCES, .scope = RT_SCOPE_UNIVERSE }, /* RTN_PROHIBIT */
- { .error = -EAGAIN, .scope = RT_SCOPE_UNIVERSE }, /* RTN_THROW */
- { .error = 0, .scope = RT_SCOPE_NOWHERE }, /* RTN_NAT */
- { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE } /* RTN_XRESOLVE */
+ [RTN_UNSPEC] = { .error = 0, .scope = RT_SCOPE_NOWHERE },
+ [RTN_UNICAST] = { .error = 0, .scope = RT_SCOPE_UNIVERSE },
+ [RTN_LOCAL] = { .error = 0, .scope = RT_SCOPE_HOST },
+ [RTN_BROADCAST] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE },
+ [RTN_ANYCAST] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE },
+ [RTN_MULTICAST] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE },
+ [RTN_BLACKHOLE] = { .error = -EINVAL, .scope = RT_SCOPE_UNIVERSE },
+ [RTN_UNREACHABLE] = { .error = -EHOSTUNREACH, .scope = RT_SCOPE_UNIVERSE },
+ [RTN_PROHIBIT] = { .error = -EACCES, .scope = RT_SCOPE_UNIVERSE },
+ [RTN_THROW] = { .error = -EAGAIN, .scope = RT_SCOPE_UNIVERSE },
+ [RTN_NAT] = { .error = 0, .scope = RT_SCOPE_NOWHERE },
+ [RTN_XRESOLVE] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE },
};
void dn_fib_free_info(struct dn_fib_info *fi)
@@ -792,53 +792,12 @@
dn_rt_cache_flush(-1);
}
-#ifdef CONFIG_PROC_FS
-
-static int decnet_rt_get_info(char *buffer, char **start, off_t offset, int length)
-{
- int first = offset / 128;
- char *ptr = buffer;
- int count = (length + 127) / 128;
- int len;
- int i;
- struct dn_fib_table *tb;
-
- *start = buffer + (offset % 128);
-
- if (--first < 0) {
- sprintf(buffer, "%-127s\n", "Iface\tDest\tGW \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\tIRTT");
- --count;
- ptr += 128;
- first = 0;
- }
-
-
- for(i = RT_MIN_TABLE; (i <= RT_TABLE_MAX) && (count > 0); i++) {
- if ((tb = dn_fib_get_table(i, 0)) != NULL) {
- int n = tb->get_info(tb, ptr, first, count);
- count -= n;
- ptr += n * 128;
- }
- }
-
- len = ptr - *start;
- if (len >= length)
- return length;
- if (len >= 0)
- return len;
-
- return 0;
-}
-#endif /* CONFIG_PROC_FS */
-
static struct notifier_block dn_fib_dnaddr_notifier = {
.notifier_call = dn_fib_dnaddr_event,
};
void __exit dn_fib_cleanup(void)
{
- proc_net_remove("decnet_route");
-
dn_fib_table_cleanup();
dn_fib_rules_cleanup();
@@ -848,10 +807,6 @@
void __init dn_fib_init(void)
{
-
-#ifdef CONFIG_PROC_FS
- proc_net_create("decnet_route", 0, decnet_rt_get_info);
-#endif
dn_fib_table_init();
dn_fib_rules_init();
diff -Nru linux-2.5.68/net/decnet/dn_neigh.c linux/net/decnet/dn_neigh.c
--- linux-2.5.68/net/decnet/dn_neigh.c Sun Apr 20 03:28:01 2003
+++ linux/net/decnet/dn_neigh.c Wed Apr 23 13:37:47 2003
@@ -202,7 +202,7 @@
struct net_device *dev = neigh->dev;
char mac_addr[ETH_ALEN];
- dn_dn2eth(mac_addr, rt->rt_saddr);
+ dn_dn2eth(mac_addr, rt->rt_local_src);
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);
@@ -692,48 +692,23 @@
goto out;
}
-static int dn_seq_release(struct inode *inode, struct file *file)
-{
- struct seq_file *seq = (struct seq_file *)file->private_data;
-
- kfree(seq->private);
- seq->private = NULL;
- return seq_release(inode, file);
-}
-
static struct file_operations dn_neigh_seq_fops = {
.open = dn_neigh_seq_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = dn_seq_release,
+ .release = kfree_release,
};
-static int __init dn_neigh_proc_init(void)
-{
- int rc = 0;
- struct proc_dir_entry *p = create_proc_entry("decnet_neigh", S_IRUGO, proc_net);
- if (p)
- p->proc_fops = &dn_neigh_seq_fops;
- else
- rc = -ENOMEM;
- return rc;
-}
-
-#else
-static int __init dn_neigh_proc_init(void)
-{
- return 0;
-}
#endif
void __init dn_neigh_init(void)
{
neigh_table_init(&dn_neigh_table);
-
- dn_neigh_proc_init();
+ proc_net_fops_create("decnet_neigh", S_IRUGO, &dn_neigh_seq_fops);
}
void __exit dn_neigh_cleanup(void)
{
+ proc_net_remove("decnet_neigh");
neigh_table_clear(&dn_neigh_table);
}
diff -Nru linux-2.5.68/net/decnet/dn_nsp_in.c linux/net/decnet/dn_nsp_in.c
--- linux-2.5.68/net/decnet/dn_nsp_in.c Sun Apr 20 03:28:01 2003
+++ linux/net/decnet/dn_nsp_in.c Wed Apr 23 12:38:09 2003
@@ -240,7 +240,7 @@
cb->info = msg->info;
cb->segsize = dn_ntohs(msg->segsize);
- if (skb->len < sizeof(*msg))
+ if (!pskb_may_pull(skb, sizeof(*msg)))
goto err_out;
skb_pull(skb, sizeof(*msg));
@@ -721,34 +721,19 @@
unsigned char *ptr = (unsigned char *)skb->data;
unsigned short reason = NSP_REASON_NL;
+ if (!pskb_may_pull(skb, 2))
+ goto free_out;
+
skb->h.raw = skb->data;
cb->nsp_flags = *ptr++;
if (decnet_debug_level & 2)
printk(KERN_DEBUG "dn_nsp_rx: Message type 0x%02x\n", (int)cb->nsp_flags);
- if (skb->len < 2)
- goto free_out;
-
if (cb->nsp_flags & 0x83)
goto free_out;
/*
- * Returned packets...
- * Swap src & dst and look up in the normal way.
- */
- if (cb->rt_flags & DN_RT_F_RTS) {
- unsigned short tmp = cb->dst_port;
- cb->dst_port = cb->src_port;
- cb->src_port = tmp;
- tmp = cb->dst;
- cb->dst = cb->src;
- cb->src = tmp;
- sk = dn_find_by_skb(skb);
- goto got_it;
- }
-
- /*
* Filter out conninits and useless packet types
*/
if ((cb->nsp_flags & 0x0c) == 0x08) {
@@ -759,12 +744,14 @@
goto free_out;
case 0x10:
case 0x60:
+ if (unlikely(cb->rt_flags & DN_RT_F_RTS))
+ goto free_out;
sk = dn_find_listener(skb, &reason);
goto got_it;
}
}
- if (skb->len < 3)
+ if (!pskb_may_pull(skb, 3))
goto free_out;
/*
@@ -777,13 +764,26 @@
/*
* If not a connack, grab the source address too.
*/
- if (skb->len >= 5) {
+ if (pskb_may_pull(skb, 5)) {
cb->src_port = *(unsigned short *)ptr;
ptr += 2;
skb_pull(skb, 5);
}
/*
+ * Returned packets...
+ * Swap src & dst and look up in the normal way.
+ */
+ if (unlikely(cb->rt_flags & DN_RT_F_RTS)) {
+ unsigned short tmp = cb->dst_port;
+ cb->dst_port = cb->src_port;
+ cb->src_port = tmp;
+ tmp = cb->dst;
+ cb->dst = cb->src;
+ cb->src = tmp;
+ }
+
+ /*
* Find the socket to which this skb is destined.
*/
sk = dn_find_by_skb(skb);
@@ -795,6 +795,15 @@
/* Reset backoff */
scp->nsp_rxtshift = 0;
+ /*
+ * We linearize everything except data segments here.
+ */
+ if ((cb->nsp_flags & 0x60) != cb->nsp_flags) {
+ if (unlikely(skb_is_nonlinear(skb)) &&
+ skb_linearize(skb, GFP_ATOMIC) != 0)
+ goto free_out;
+ }
+
bh_lock_sock(sk);
ret = NET_RX_SUCCESS;
if (decnet_debug_level & 8)
@@ -835,7 +844,10 @@
struct dn_skb_cb *cb = DN_SKB_CB(skb);
if (cb->rt_flags & DN_RT_F_RTS) {
- dn_returned_conn_init(sk, skb);
+ if (cb->nsp_flags == 0x18 || cb->nsp_flags == 0x68)
+ dn_returned_conn_init(sk, skb);
+ else
+ kfree_skb(skb);
return NET_RX_SUCCESS;
}
diff -Nru linux-2.5.68/net/decnet/dn_nsp_out.c linux/net/decnet/dn_nsp_out.c
--- linux-2.5.68/net/decnet/dn_nsp_out.c Sun Apr 20 03:28:01 2003
+++ linux/net/decnet/dn_nsp_out.c Tue Apr 29 02:39:07 2003
@@ -96,6 +96,7 @@
fl.fld_src = dn_saddr2dn(&scp->addr);
fl.fld_dst = dn_saddr2dn(&scp->peer);
dn_sk_ports_copy(&fl, scp);
+ fl.proto = DNPROTO_NSP;
if (dn_route_output_sock(&sk->dst_cache, &fl, sk, 0) == 0) {
dst = sk_dst_get(sk);
sk->route_caps = dst->dev->features;
@@ -349,8 +350,7 @@
{
unsigned char *ptr = skb_push(skb, len);
- if (len < 5)
- BUG();
+ BUG_ON(len < 5);
*ptr++ = msgflag;
*((unsigned short *)ptr) = scp->addrrem;
@@ -367,8 +367,7 @@
unsigned short ackcrs = scp->numoth_rcv & 0x0FFF;
unsigned short *ptr;
- if (hlen < 9)
- BUG();
+ BUG_ON(hlen < 9);
scp->ackxmt_dat = acknum;
scp->ackxmt_oth = ackcrs;
@@ -485,8 +484,8 @@
* We don't expect to see acknowledgements for packets we
* haven't sent yet.
*/
- if (xmit_count == 0)
- BUG();
+ WARN_ON(xmit_count == 0);
+
/*
* If the packet has only been sent once, we can use it
* to calculate the RTT and also open the window a little
diff -Nru linux-2.5.68/net/decnet/dn_route.c linux/net/decnet/dn_route.c
--- linux-2.5.68/net/decnet/dn_route.c Sun Apr 20 03:28:01 2003
+++ linux/net/decnet/dn_route.c Tue Apr 29 02:38:35 2003
@@ -70,6 +70,7 @@
#include <net/sock.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
#include <linux/init.h>
#include <linux/rtnetlink.h>
#include <linux/string.h>
@@ -97,14 +98,17 @@
static unsigned char dn_hiord_addr[6] = {0xAA,0x00,0x04,0x00,0x00,0x00};
-int dn_rt_min_delay = 2*HZ;
-int dn_rt_max_delay = 10*HZ;
-static unsigned long dn_rt_deadline = 0;
+int dn_rt_min_delay = 2 * HZ;
+int dn_rt_max_delay = 10 * HZ;
+int dn_rt_mtu_expires = 10 * 60 * HZ;
+
+static unsigned long dn_rt_deadline;
static int dn_dst_gc(void);
static struct dst_entry *dn_dst_check(struct dst_entry *, __u32);
static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
static void dn_dst_link_failure(struct sk_buff *);
+static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu);
static int dn_route_input(struct sk_buff *);
static void dn_run_flush(unsigned long dummy);
@@ -124,6 +128,7 @@
.check = dn_dst_check,
.negative_advice = dn_dst_negative_advice,
.link_failure = dn_dst_link_failure,
+ .update_pmtu = dn_dst_update_pmtu,
.entry_size = sizeof(struct dn_route),
.entries = ATOMIC_INIT(0),
};
@@ -210,16 +215,49 @@
return 0;
}
+/*
+ * The decnet standards don't impose a particular minimum mtu, what they
+ * do insist on is that the routing layer accepts a datagram of at least
+ * 230 bytes long. Here we have to subtract the routing header length from
+ * 230 to get the minimum acceptable mtu. If there is no neighbour, then we
+ * assume the worst and use a long header size.
+ *
+ * We update both the mtu and the advertised mss (i.e. the segment size we
+ * advertise to the other end).
+ */
+static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu)
+{
+ u32 min_mtu = 230;
+ struct dn_dev *dn = dst->neighbour ?
+ (struct dn_dev *)dst->neighbour->dev->dn_ptr : NULL;
+
+ if (dn && dn->use_long == 0)
+ min_mtu -= 6;
+ else
+ min_mtu -= 21;
+
+ if (dst->metrics[RTAX_MTU-1] > mtu && mtu >= min_mtu) {
+ if (!(dst_metric_locked(dst, RTAX_MTU))) {
+ dst->metrics[RTAX_MTU-1] = mtu;
+ dst_set_expires(dst, dn_rt_mtu_expires);
+ }
+ if (!(dst_metric_locked(dst, RTAX_ADVMSS))) {
+ u32 mss = mtu - DN_MAX_NSP_DATA_HEADER;
+ if (dst->metrics[RTAX_ADVMSS-1] > mss)
+ dst->metrics[RTAX_ADVMSS-1] = mss;
+ }
+ }
+}
+
+/*
+ * When a route has been marked obsolete. (e.g. routing cache flush)
+ */
static struct dst_entry *dn_dst_check(struct dst_entry *dst, __u32 cookie)
{
dst_release(dst);
return NULL;
}
-/*
- * This is called through sendmsg() when you specify MSG_TRYHARD
- * and there is already a route in cache.
- */
static struct dst_entry *dn_dst_negative_advice(struct dst_entry *dst)
{
dst_release(dst);
@@ -467,7 +505,7 @@
struct dn_skb_cb *cb = DN_SKB_CB(skb);
unsigned char *ptr = skb->data;
- if (skb->len < 21) /* 20 for long header, 1 for shortest nsp */
+ if (!pskb_may_pull(skb, 21)) /* 20 for long header, 1 for shortest nsp */
goto drop_it;
skb_pull(skb, 20);
@@ -505,7 +543,7 @@
struct dn_skb_cb *cb = DN_SKB_CB(skb);
unsigned char *ptr = skb->data;
- if (skb->len < 6) /* 5 for short header + 1 for shortest nsp */
+ if (!pskb_may_pull(skb, 6)) /* 5 for short header + 1 for shortest nsp */
goto drop_it;
skb_pull(skb, 5);
@@ -555,6 +593,9 @@
if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
goto out;
+ if (!pskb_may_pull(skb, 3))
+ goto dump_it;
+
skb_pull(skb, 2);
if (len > skb->len)
@@ -573,6 +614,8 @@
*/
if (flags & DN_RT_F_PF) {
padlen = flags & ~DN_RT_F_PF;
+ if (!pskb_may_pull(skb, padlen + 1))
+ goto dump_it;
skb_pull(skb, padlen);
flags = *skb->data;
}
@@ -594,6 +637,10 @@
padlen);
if (flags & DN_RT_PKT_CNTL) {
+ if (unlikely(skb_is_nonlinear(skb)) &&
+ skb_linearize(skb, GFP_ATOMIC) != 0)
+ goto dump_it;
+
switch(flags & DN_RT_CNTL_MSK) {
case DN_RT_PKT_INIT:
dn_dev_init_pkt(skb);
@@ -712,7 +759,7 @@
* packets, so we don't need to test for them here.
*/
cb->rt_flags &= ~DN_RT_F_IE;
- if (rt->rt_flags | RTCF_DOREDIRECT)
+ if (rt->rt_flags & RTCF_DOREDIRECT)
cb->rt_flags |= DN_RT_F_IE;
return NF_HOOK(PF_DECnet, NF_DN_FORWARD, skb, dev, skb->dev, neigh->output);
@@ -788,8 +835,10 @@
{
__u16 tmp = dn_ntohs(addr1) ^ dn_ntohs(addr2);
int match = 16;
- while(tmp)
- tmp >>= 1, match--;
+ while(tmp) {
+ tmp >>= 1;
+ match--;
+ }
return match;
}
@@ -892,23 +941,25 @@
if (dev_out == NULL)
goto out;
dev_hold(dev_out);
-source_ok:
}
+source_ok:
/* No destination? Assume its local */
if (!fl.fld_dst) {
fl.fld_dst = fl.fld_src;
-#if 0
- if (!fl.fld_dst)
- /* grab an address from loopback? */
-#endif
+
err = -EADDRNOTAVAIL;
if (dev_out)
dev_put(dev_out);
- if (!fl.fld_dst)
- goto out;
dev_out = &loopback_dev;
dev_hold(dev_out);
+ if (!fl.fld_dst) {
+ fl.fld_dst =
+ fl.fld_src = dnet_select_source(dev_out, 0,
+ RT_SCOPE_HOST);
+ if (!fl.fld_dst)
+ goto out;
+ }
fl.oif = loopback_dev.ifindex;
res.type = RTN_LOCAL;
goto make_route;
@@ -1054,12 +1105,13 @@
rt->fl.oif = oldflp->oif;
rt->fl.iif = 0;
#ifdef CONFIG_DECNET_ROUTE_FWMARK
- rt->fl.fld_fwmark = flp->fld_fwmark;
+ rt->fl.fld_fwmark = oldflp->fld_fwmark;
#endif
rt->rt_saddr = fl.fld_src;
rt->rt_daddr = fl.fld_dst;
rt->rt_gateway = gateway ? gateway : fl.fld_dst;
+ rt->rt_local_src = fl.fld_src;
rt->rt_dst_map = fl.fld_dst;
rt->rt_src_map = fl.fld_src;
@@ -1074,7 +1126,7 @@
rt->u.dst.input = dn_rt_bug;
rt->rt_flags = flags;
if (flags & RTCF_LOCAL)
- rt->u.dst.output = dn_nsp_rx;
+ rt->u.dst.input = dn_nsp_rx;
if (dn_rt_set_next_hop(rt, &res))
goto e_neighbour;
@@ -1174,12 +1226,13 @@
unsigned hash;
int flags = 0;
__u16 gateway = 0;
+ __u16 local_src = 0;
struct flowi fl = { .nl_u = { .dn_u =
{ .daddr = cb->dst,
.saddr = cb->src,
.scope = RT_SCOPE_UNIVERSE,
#ifdef CONFIG_DECNET_ROUTE_FWMARK
- .fwmark = skb->fwmark
+ .fwmark = skb->nfmark
#endif
} },
.iif = skb->dev->ifindex };
@@ -1274,6 +1327,8 @@
if (out_dev == in_dev && !(flags & RTCF_NAT))
flags |= RTCF_DOREDIRECT;
+ local_src = DN_FIB_RES_PREFSRC(res);
+
case RTN_BLACKHOLE:
case RTN_UNREACHABLE:
break;
@@ -1318,6 +1373,8 @@
rt->rt_gateway = fl.fld_dst;
if (gateway)
rt->rt_gateway = gateway;
+ rt->rt_local_src = local_src ? local_src : rt->rt_saddr;
+
rt->rt_dst_map = fl.fld_dst;
rt->rt_src_map = fl.fld_src;
@@ -1448,7 +1505,7 @@
* they deal only with inputs and not with replies like they do
* currently.
*/
- RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_saddr);
+ RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_local_src);
if (rt->rt_daddr != rt->rt_gateway)
RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway);
if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0)
@@ -1489,6 +1546,7 @@
struct flowi fl;
memset(&fl, 0, sizeof(fl));
+ fl.proto = DNPROTO_NSP;
skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (skb == NULL)
@@ -1608,54 +1666,114 @@
}
#ifdef CONFIG_PROC_FS
+struct dn_rt_cache_iter_state {
+ int bucket;
+};
-static int decnet_cache_get_info(char *buffer, char **start, off_t offset, int length)
+static struct dn_route *dn_rt_cache_get_first(struct seq_file *seq)
{
- int len = 0;
- off_t pos = 0;
- off_t begin = 0;
- struct dn_route *rt;
- int i;
- char buf1[DN_ASCBUF_LEN], buf2[DN_ASCBUF_LEN];
+ struct dn_route *rt = NULL;
+ struct dn_rt_cache_iter_state *s = seq->private;
- for(i = 0; i <= dn_rt_hash_mask; i++) {
+ for(s->bucket = dn_rt_hash_mask; s->bucket >= 0; --s->bucket) {
rcu_read_lock();
- rt = dn_rt_hash_table[i].chain;
- for(; rt != NULL; rt = rt->u.rt_next) {
- read_barrier_depends();
- len += sprintf(buffer + len, "%-8s %-7s %-7s %04d %04d %04d\n",
- rt->u.dst.dev ? rt->u.dst.dev->name : "*",
- dn_addr2asc(dn_ntohs(rt->rt_daddr), buf1),
- dn_addr2asc(dn_ntohs(rt->rt_saddr), buf2),
- atomic_read(&rt->u.dst.__refcnt),
- rt->u.dst.__use,
- (int) dst_metric(&rt->u.dst, RTAX_RTT)
- );
-
+ rt = dn_rt_hash_table[s->bucket].chain;
+ if (rt)
+ break;
+ rcu_read_unlock();
+ }
+ return rt;
+}
+static struct dn_route *dn_rt_cache_get_next(struct seq_file *seq, struct dn_route *rt)
+{
+ struct dn_rt_cache_iter_state *s = seq->private;
- pos = begin + len;
-
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
- if (pos > offset + length)
- break;
- }
+ smp_read_barrier_depends();
+ rt = rt->u.rt_next;
+ while(!rt) {
rcu_read_unlock();
- if (pos > offset + length)
+ if (--s->bucket < 0)
break;
+ rcu_read_lock();
+ rt = dn_rt_hash_table[s->bucket].chain;
}
+ return rt;
+}
+
+static void *dn_rt_cache_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ struct dn_route *rt = dn_rt_cache_get_first(seq);
+
+ if (rt) {
+ while(*pos && (rt = dn_rt_cache_get_next(seq, rt)))
+ --*pos;
+ }
+ return *pos ? NULL : rt;
+}
+
+static void *dn_rt_cache_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct dn_route *rt = dn_rt_cache_get_next(seq, v);
+ ++*pos;
+ return rt;
+}
- *start = buffer + (offset - begin);
- len -= (offset - begin);
+static void dn_rt_cache_seq_stop(struct seq_file *seq, void *v)
+{
+ rcu_read_unlock();
+}
- if (len > length) len = length;
+static int dn_rt_cache_seq_show(struct seq_file *seq, void *v)
+{
+ struct dn_route *rt = v;
+ char buf1[DN_ASCBUF_LEN], buf2[DN_ASCBUF_LEN];
- return(len);
+ seq_printf(seq, "%-8s %-7s %-7s %04d %04d %04d\n",
+ rt->u.dst.dev ? rt->u.dst.dev->name : "*",
+ dn_addr2asc(dn_ntohs(rt->rt_daddr), buf1),
+ dn_addr2asc(dn_ntohs(rt->rt_saddr), buf2),
+ atomic_read(&rt->u.dst.__refcnt),
+ rt->u.dst.__use,
+ (int) dst_metric(&rt->u.dst, RTAX_RTT));
+ return 0;
}
+static struct seq_operations dn_rt_cache_seq_ops = {
+ .start = dn_rt_cache_seq_start,
+ .next = dn_rt_cache_seq_next,
+ .stop = dn_rt_cache_seq_stop,
+ .show = dn_rt_cache_seq_show,
+};
+
+static int dn_rt_cache_seq_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ int rc = -ENOMEM;
+ struct dn_rt_cache_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+ if (!s)
+ goto out;
+ rc = seq_open(file, &dn_rt_cache_seq_ops);
+ if (rc)
+ goto out_kfree;
+ seq = file->private_data;
+ seq->private = s;
+ memset(s, 0, sizeof(*s));
+out:
+ return rc;
+out_kfree:
+ kfree(s);
+ goto out;
+}
+
+static struct file_operations dn_rt_cache_seq_fops = {
+ .open = dn_rt_cache_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = kfree_release,
+};
+
#endif /* CONFIG_PROC_FS */
void __init dn_route_init(void)
@@ -1713,9 +1831,7 @@
dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1);
-#ifdef CONFIG_PROC_FS
- proc_net_create("decnet_cache",0,decnet_cache_get_info);
-#endif /* CONFIG_PROC_FS */
+ proc_net_fops_create("decnet_cache", S_IRUGO, &dn_rt_cache_seq_fops);
}
void __exit dn_route_cleanup(void)
diff -Nru linux-2.5.68/net/decnet/dn_table.c linux/net/decnet/dn_table.c
--- linux-2.5.68/net/decnet/dn_table.c Sun Apr 20 03:28:01 2003
+++ linux/net/decnet/dn_table.c Wed Apr 23 09:43:16 2003
@@ -744,86 +744,6 @@
return err;
}
-#ifdef CONFIG_PROC_FS
-
-static unsigned dn_fib_flag_trans(int type, int dead, u16 mask, struct dn_fib_info *fi)
-{
- static unsigned type2flags[RTN_MAX+1] = {
- 0, 0, 0, 0, 0, 0, 0, RTF_REJECT, RTF_REJECT, 0, 0, 0
- };
- unsigned flags = type2flags[type];
-
- if (fi && fi->fib_nh->nh_gw)
- flags |= RTF_GATEWAY;
- if (mask == 0xFFFF)
- flags |= RTF_HOST;
- if (dead)
- flags |= RTF_UP;
- return flags;
-}
-
-static void dn_fib_node_get_info(int type, int dead, struct dn_fib_info *fi, u16 prefix, u16 mask, char *buffer)
-{
- int len;
- unsigned flags = dn_fib_flag_trans(type, dead, mask, fi);
-
- if (fi) {
- len = sprintf(buffer, "%s\t%04x\t%04x\t%04x\t%d\t%u\t%d\t%04x\t%d\t%u\t%u",
- fi->dn_fib_dev ? fi->dn_fib_dev->name : "*", prefix,
- fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority,
- mask, 0, 0, 0);
- } else {
- len = sprintf(buffer, "*\t%04x\t%04x\t%04x\t%d\t%u\t%d\t%04x\t%d\t%u\t%u",
- prefix, 0,
- flags, 0, 0, 0,
- mask, 0, 0, 0);
- }
- memset(buffer+len, ' ', 127-len);
- buffer[127] = '\n';
-}
-
-static int dn_fib_table_get_info(struct dn_fib_table *tb, char *buffer, int first, int count)
-{
- struct dn_hash *table = (struct dn_hash *)tb->data;
- struct dn_zone *dz;
- int pos = 0;
- int n = 0;
-
- read_lock(&dn_fib_tables_lock);
- for(dz = table->dh_zone_list; dz; dz = dz->dz_next) {
- int i;
- struct dn_fib_node *f;
- int maxslot = dz->dz_divisor;
- struct dn_fib_node **fp = dz->dz_hash;
-
- if (dz->dz_nent == 0)
- continue;
-
- if (pos + dz->dz_nent < first) {
- pos += dz->dz_nent;
- continue;
- }
-
- for(i = 0; i < maxslot; i++, fp++) {
- for(f = *fp; f ; f = f->fn_next) {
- if (++pos <= first)
- continue;
- dn_fib_node_get_info(f->fn_type,
- f->fn_state & DN_S_ZOMBIE,
- DN_FIB_INFO(f),
- dz_prefix(f->fn_key, dz),
- DZ_MASK(dz), buffer);
- buffer += 128;
- if (++n >= count)
- goto out;
- }
- }
- }
-out:
- read_unlock(&dn_fib_tables_lock);
- return n;
-}
-#endif /* CONFIG_PROC_FS */
struct dn_fib_table *dn_fib_get_table(int n, int create)
{
@@ -855,9 +775,6 @@
t->delete = dn_fib_table_delete;
t->lookup = dn_fib_table_lookup;
t->flush = dn_fib_table_flush;
-#ifdef CONFIG_PROC_FS
- t->get_info = dn_fib_table_get_info;
-#endif
t->dump = dn_fib_table_dump;
memset(t->data, 0, sizeof(struct dn_hash));
dn_fib_tables[n] = t;
diff -Nru linux-2.5.68/net/decnet/netfilter/Kconfig linux/net/decnet/netfilter/Kconfig
--- linux-2.5.68/net/decnet/netfilter/Kconfig Wed Dec 31 16:00:00 1969
+++ linux/net/decnet/netfilter/Kconfig Wed Apr 23 13:02:25 2003
@@ -0,0 +1,15 @@
+#
+# DECnet netfilter configuration
+#
+
+menu "DECnet: Netfilter Configuration"
+ depends on DECNET && NETFILTER && EXPERIMENTAL
+
+config DECNET_NF_GRABULATOR
+ tristate "Routing message grabulator (for userland routing daemon)"
+ help
+ Enable this module if you want to use the userland DECnet routing
+ daemon. You will also need to enable routing support for DECnet
+ unless you just want to monitor routing messages from other nodes.
+
+endmenu
diff -Nru linux-2.5.68/net/decnet/netfilter/Makefile linux/net/decnet/netfilter/Makefile
--- linux-2.5.68/net/decnet/netfilter/Makefile Wed Dec 31 16:00:00 1969
+++ linux/net/decnet/netfilter/Makefile Wed Apr 23 10:25:21 2003
@@ -0,0 +1,6 @@
+#
+# Makefile for DECnet netfilter modules
+#
+
+obj-$(CONFIG_DECNET_NF_GRABULATOR) += dn_rtmsg.o
+
diff -Nru linux-2.5.68/net/decnet/netfilter/dn_rtmsg.c linux/net/decnet/netfilter/dn_rtmsg.c
--- linux-2.5.68/net/decnet/netfilter/dn_rtmsg.c Wed Dec 31 16:00:00 1969
+++ linux/net/decnet/netfilter/dn_rtmsg.c Wed Apr 23 14:05:10 2003
@@ -0,0 +1,167 @@
+/*
+ * DECnet An implementation of the DECnet protocol suite for the LINUX
+ * operating system. DECnet is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * DECnet Routing Message Grabulator
+ *
+ * (C) 2000 ChyGwyn Limited - http://www.chygwyn.com/
+ * This code may be copied under the GPL v.2 or at your option
+ * any later version.
+ *
+ * Author: Steven Whitehouse <st...@ch...>
+ *
+ */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/netfilter.h>
+#include <linux/spinlock.h>
+#include <linux/netlink.h>
+
+#include <net/sock.h>
+#include <net/flow.h>
+#include <net/dn.h>
+#include <net/dn_route.h>
+
+#include <linux/netfilter_decnet.h>
+
+static struct sock *dnrmg = NULL;
+
+
+static struct sk_buff *dnrmg_build_message(struct sk_buff *rt_skb, int *errp)
+{
+ struct sk_buff *skb = NULL;
+ size_t size;
+ unsigned char *old_tail;
+ struct nlmsghdr *nlh;
+ unsigned char *ptr;
+ struct nf_dn_rtmsg *rtm;
+
+ size = NLMSG_SPACE(rt_skb->len);
+ size += NLMSG_ALIGN(sizeof(struct nf_dn_rtmsg));
+ skb = alloc_skb(size, GFP_ATOMIC);
+ if (!skb)
+ goto nlmsg_failure;
+ old_tail = skb->tail;
+ nlh = NLMSG_PUT(skb, 0, 0, 0, size - sizeof(*nlh));
+ rtm = (struct nf_dn_rtmsg *)NLMSG_DATA(nlh);
+ rtm->nfdn_ifindex = rt_skb->dev->ifindex;
+ ptr = NFDN_RTMSG(rtm);
+ memcpy(ptr, rt_skb->data, rt_skb->len);
+ nlh->nlmsg_len = skb->tail - old_tail;
+ return skb;
+
+nlmsg_failure:
+ if (skb)
+ kfree(skb);
+ *errp = -ENOMEM;
+ if (net_ratelimit())
+ printk(KERN_ERR "dn_rtmsg: error creating netlink message\n");
+ return NULL;
+}
+
+static void dnrmg_send_peer(struct sk_buff *skb)
+{
+ struct sk_buff *skb2;
+ int status = 0;
+ int group = 0;
+ unsigned char flags = *skb->data;
+
+ switch(flags & DN_RT_CNTL_MSK) {
+ case DN_RT_PKT_L1RT:
+ group = DNRMG_L1_GROUP;
+ break;
+ case DN_RT_PKT_L2RT:
+ group = DNRMG_L2_GROUP;
+ break;
+ default:
+ return;
+ }
+
+ skb2 = dnrmg_build_message(skb, &status);
+ if (skb2 == NULL)
+ return;
+ NETLINK_CB(skb2).dst_groups = group;
+ netlink_broadcast(dnrmg, skb2, 0, group, GFP_ATOMIC);
+}
+
+
+static unsigned int dnrmg_hook(unsigned int hook,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ dnrmg_send_peer(*pskb);
+ return NF_ACCEPT;
+}
+
+
+#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0)
+
+static inline void dnrmg_receive_user_skb(struct sk_buff *skb)
+{
+ struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data;
+
+ if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
+ return;
+
+ if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN))
+ RCV_SKB_FAIL(-EPERM);
+
+ /* Eventually we might send routing messages too */
+
+ RCV_SKB_FAIL(-EINVAL);
+}
+
+static void dnrmg_receive_user_sk(struct sock *sk, int len)
+{
+ struct sk_buff *skb;
+
+ while((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
+ dnrmg_receive_user_skb(skb);
+ kfree_skb(skb);
+ }
+}
+
+static struct nf_hook_ops dnrmg_ops = {
+ .hook = dnrmg_hook,
+ .pf = PF_DECnet,
+ .hooknum = NF_DN_ROUTE,
+ .priority = NF_DN_PRI_DNRTMSG,
+};
+
+static int __init init(void)
+{
+ int rv = 0;
+
+ dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, dnrmg_receive_user_sk);
+ if (dnrmg == NULL) {
+ printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket");
+ return -ENOMEM;
+ }
+
+ rv = nf_register_hook(&dnrmg_ops);
+ if (rv) {
+ sock_release(dnrmg->socket);
+ }
+
+ return rv;
+}
+
+static void __exit fini(void)
+{
+ nf_unregister_hook(&dnrmg_ops);
+ sock_release(dnrmg->socket);
+}
+
+
+MODULE_DESCRIPTION("DECnet Routing Message Grabulator");
+MODULE_AUTHOR("Steven Whitehouse <st...@ch...>");
+MODULE_LICENSE("GPL");
+
+module_init(init);
+module_exit(fini);
+
|
|
From: Patrick C. <pa...@ty...> - 2003-04-29 07:08:26
|
I received this from a SuSE user. If anyone is running SuSE and wants startup scripts/instructions for LAT on that distribution, here they are. I haven't tested these personally but have no reason to beleive they won't work. -- patrick |
|
From: BASSIR M. <Moh...@ax...> - 2003-04-28 07:15:48
|
So, =20 i have provide some diagnostic and it's appear OK. How can i verify that the DECnet module is being=20 loaded before the Xserver starts. =20 Patrick, for information, it is not the first time that i ask you about = a similar problem. This is links with a part of discussion: http://www.geocrawler.com/archives/3/3243/2002/7/0/9148849/ http://www.geocrawler.com/mail/msg.php3?msg_id=3D9149573&list=3D3243 http://www.geocrawler.com/mail/msg.php3?msg_id=3D9151703&list=3D3243 http://www.geocrawler.com/mail/msg.php3?msg_id=3D9151896&list=3D3243 http://www.geocrawler.com/mail/msg.php3?msg_id=3D9152625&list=3D3243 =20 At this time you answer me a solution ( Kernel modification) but with = this Xserver Freeze after a random time. =20 M.Bassir =20 -------- Message d'origine--------=20 De: Patrick Caulfield [mailto:pa...@ty...]=20 Date: sam. 26/04/2003 10:51=20 =C0: BASSIR Mohcine=20 Cc: DECnet list=20 Objet: Re: [Linux-decnet-user] X and Decnet On Sat, Apr 26, 2003 at 09:20:00AM +0200, BASSIR Mohcine wrote: > Hi, > =20 > My Xserver have DECnet support compiled in and i use Decnet. > I think that the problem is not on the Xserver or decnet, but on > the Kernel. > I use the version 2.4.21 that is include on the Mandrake 9.1. Well, please provide some useful diagnostic information then. If your Xserver has DECnet support compiled in then $ ldd /usr/X11R6/bin/XFree86 should show: libdnet.so.2 =3D> /usr/lib/libdnet.so.2 (0x41d2f000) (and others) and $ cat /proc/net/decnet should show: Local Remote 0.0/0000 0001:0001 0000:0000 2 X$X0 0.0/0000 0000:0000 = 0000:0000 2 0 If the first is the case and the latter not then make sure that the = DECnet module is being loaded before the Xserver starts. patrick |
|
From: BASSIR M. <Moh...@ax...> - 2003-04-27 18:46:32
|
U28sDQogDQppIGhhdmUgcHJvdmlkZSBzb21lIGRpYWdub3N0aWMgYW5kIGl0J3MgYXBwZWFyIE9L Lg0KSG93IGNhbiBpIHZlcmlmeSB0aGF0IHRoZSBERUNuZXQgbW9kdWxlIGlzIGJlaW5nIA0KbG9h ZGVkIGJlZm9yZSB0aGUgWHNlcnZlciBzdGFydHMuDQogDQpQYXRyaWNrLCBmb3IgaW5mb3JtYXRp b24sIGl0IGlzIG5vdCB0aGUgZmlyc3QgdGltZSB0aGF0IGkgYXNrIHlvdSBhYm91dCBhDQpzaW1p bGFyIHByb2JsZW0uIFRoaXMgaXMgbGlua3Mgd2l0aCBhIHBhcnQgb2YgZGlzY3Vzc2lvbjoNCmh0 dHA6Ly93d3cuZ2VvY3Jhd2xlci5jb20vYXJjaGl2ZXMvMy8zMjQzLzIwMDIvNy8wLzkxNDg4NDkv DQpodHRwOi8vd3d3Lmdlb2NyYXdsZXIuY29tL21haWwvbXNnLnBocDM/bXNnX2lkPTkxNDk1NzMm bGlzdD0zMjQzDQpodHRwOi8vd3d3Lmdlb2NyYXdsZXIuY29tL21haWwvbXNnLnBocDM/bXNnX2lk PTkxNTE3MDMmbGlzdD0zMjQzDQpodHRwOi8vd3d3Lmdlb2NyYXdsZXIuY29tL21haWwvbXNnLnBo cDM/bXNnX2lkPTkxNTE4OTYmbGlzdD0zMjQzDQpodHRwOi8vd3d3Lmdlb2NyYXdsZXIuY29tL21h aWwvbXNnLnBocDM/bXNnX2lkPTkxNTI2MjUmbGlzdD0zMjQzDQogDQpBdCB0aGlzIHRpbWUgeW91 IGFuc3dlciBtZSBhIHNvbHV0aW9uICggS2VybmVsIG1vZGlmaWNhdGlvbikgYnV0IHdpdGggdGhp cyBYc2VydmVyDQpGcmVlemUgYWZ0ZXIgYSByYW5kb20gdGltZS4NCiANCk0uQmFzc2lyDQogDQoN CgktLS0tLS0tLSBNZXNzYWdlIGQnb3JpZ2luZS0tLS0tLS0tIA0KCURlOiBQYXRyaWNrIENhdWxm aWVsZCBbbWFpbHRvOnBhdHJpY2tAdHlrZXBlbmd1aW4uY29tXSANCglEYXRlOiBzYW0uIDI2LzA0 LzIwMDMgMTA6NTEgDQoJw4A6IEJBU1NJUiBNb2hjaW5lIA0KCUNjOiBERUNuZXQgbGlzdCANCglP YmpldDogUmU6IFtMaW51eC1kZWNuZXQtdXNlcl0gWCBhbmQgRGVjbmV0DQoJDQoJDQoNCglPbiBT YXQsIEFwciAyNiwgMjAwMyBhdCAwOToyMDowMEFNICswMjAwLCBCQVNTSVIgTW9oY2luZSB3cm90 ZToNCgk+ICAgIEhpLA0KCT4gICAgDQoJPiAgICBNeSBYc2VydmVyIGhhdmUgREVDbmV0IHN1cHBv cnQgY29tcGlsZWQgaW4gYW5kIGkgdXNlIERlY25ldC4NCgk+ICAgIEkgdGhpbmsgdGhhdCB0aGUg cHJvYmxlbSBpcyBub3Qgb24gdGhlIFhzZXJ2ZXIgb3IgZGVjbmV0LCBidXQgb24NCgk+ICAgIHRo ZSBLZXJuZWwuDQoJPiAgICBJIHVzZSB0aGUgdmVyc2lvbiAyLjQuMjEgdGhhdCBpcyBpbmNsdWRl IG9uIHRoZSBNYW5kcmFrZSA5LjEuDQoJDQoJV2VsbCwgcGxlYXNlIHByb3ZpZGUgc29tZSB1c2Vm dWwgZGlhZ25vc3RpYyBpbmZvcm1hdGlvbiB0aGVuLg0KCQ0KCUlmIHlvdXIgWHNlcnZlciBoYXMg REVDbmV0IHN1cHBvcnQgY29tcGlsZWQgaW4gdGhlbg0KCQ0KCSQgbGRkIC91c3IvWDExUjYvYmlu L1hGcmVlODYNCgkNCglzaG91bGQgc2hvdzoNCgkNCgkgIGxpYmRuZXQuc28uMiA9PiAvdXNyL2xp Yi9saWJkbmV0LnNvLjIgKDB4NDFkMmYwMDApDQoJICAoYW5kIG90aGVycykNCgkNCglhbmQNCgkN CgkkIGNhdCAvcHJvYy9uZXQvZGVjbmV0DQoJDQoJc2hvdWxkIHNob3c6DQoJDQoJTG9jYWwgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUmVtb3RlDQoJICAgMC4w LzAwMDAgMDAwMTowMDAxIDAwMDA6MDAwMCAyIFgkWDAgICAgICAgICAgICAgICAgMC4wLzAwMDAg MDAwMDowMDAwIDAwMDA6MDAwMCAyIDANCgkNCgkNCglJZiB0aGUgZmlyc3QgaXMgdGhlIGNhc2Ug YW5kIHRoZSBsYXR0ZXIgbm90IHRoZW4gbWFrZSBzdXJlIHRoYXQgdGhlIERFQ25ldA0KCW1vZHVs ZSBpcyBiZWluZyBsb2FkZWQgYmVmb3JlIHRoZSBYc2VydmVyIHN0YXJ0cy4NCgkNCgkNCglwYXRy aWNrDQoJDQoJDQoNCg== |
|
From: Patrick C. <pa...@ty...> - 2003-04-26 09:30:35
|
Oh, and the other thing you might like to check. X authorisation. If you also have DECnet enabled utilities then you can use them (eg "xhost +dnet:vmsbox"), if not then "xhost +" or mucking about with MIT magic cookies may work. patrick |
|
From: Patrick C. <pa...@ty...> - 2003-04-26 08:51:54
|
On Sat, Apr 26, 2003 at 09:20:00AM +0200, BASSIR Mohcine wrote: > Hi, > > My Xserver have DECnet support compiled in and i use Decnet. > I think that the problem is not on the Xserver or decnet, but on > the Kernel. > I use the version 2.4.21 that is include on the Mandrake 9.1. Well, please provide some useful diagnostic information then. If your Xserver has DECnet support compiled in then $ ldd /usr/X11R6/bin/XFree86 should show: libdnet.so.2 => /usr/lib/libdnet.so.2 (0x41d2f000) (and others) and $ cat /proc/net/decnet should show: Local Remote 0.0/0000 0001:0001 0000:0000 2 X$X0 0.0/0000 0000:0000 0000:0000 2 0 If the first is the case and the latter not then make sure that the DECnet module is being loaded before the Xserver starts. patrick |
|
From: BASSIR M. <Moh...@ax...> - 2003-04-26 07:19:33
|
SGksDQogDQpNeSBYc2VydmVyIGhhdmUgREVDbmV0IHN1cHBvcnQgY29tcGlsZWQgaW4gYW5kIGkg dXNlIERlY25ldC4NCkkgdGhpbmsgdGhhdCB0aGUgcHJvYmxlbSBpcyBub3Qgb24gdGhlIFhzZXJ2 ZXIgb3IgZGVjbmV0LCBidXQgb24NCnRoZSBLZXJuZWwuDQpJIHVzZSB0aGUgdmVyc2lvbiAyLjQu MjEgdGhhdCBpcyBpbmNsdWRlIG9uIHRoZSBNYW5kcmFrZSA5LjEuDQogDQpNLkJBU1NJUg0KIA0K DQoJLS0tLS0tLS0gTWVzc2FnZSBkJ29yaWdpbmUtLS0tLS0tLSANCglEZTogbGludXgtZGVjbmV0 LXVzZXItcmVxdWVzdEBsaXN0cy5zb3VyY2Vmb3JnZS5uZXQgW21haWx0bzpsaW51eC1kZWNuZXQt dXNlci1yZXF1ZXN0QGxpc3RzLnNvdXJjZWZvcmdlLm5ldF0gDQoJRGF0ZTogc2FtLiAyNi8wNC8y MDAzIDA1OjA2IA0KCcOAOiBsaW51eC1kZWNuZXQtdXNlckBsaXN0cy5zb3VyY2Vmb3JnZS5uZXQg DQoJQ2M6IA0KCU9iamV0OiBMaW51eC1kZWNuZXQtdXNlciBkaWdlc3QsIFZvbCAxICMyNzkgLSA0 IG1zZ3MNCgkNCgkNCg0KCVNlbmQgTGludXgtZGVjbmV0LXVzZXIgbWFpbGluZyBsaXN0IHN1Ym1p c3Npb25zIHRvDQoJICAgICAgICBsaW51eC1kZWNuZXQtdXNlckBsaXN0cy5zb3VyY2Vmb3JnZS5u ZXQNCgkNCglUbyBzdWJzY3JpYmUgb3IgdW5zdWJzY3JpYmUgdmlhIHRoZSBXb3JsZCBXaWRlIFdl YiwgdmlzaXQNCgkgICAgICAgIGh0dHBzOi8vbGlzdHMuc291cmNlZm9yZ2UubmV0L2xpc3RzL2xp c3RpbmZvL2xpbnV4LWRlY25ldC11c2VyDQoJb3IsIHZpYSBlbWFpbCwgc2VuZCBhIG1lc3NhZ2Ug d2l0aCBzdWJqZWN0IG9yIGJvZHkgJ2hlbHAnIHRvDQoJICAgICAgICBsaW51eC1kZWNuZXQtdXNl ci1yZXF1ZXN0QGxpc3RzLnNvdXJjZWZvcmdlLm5ldA0KCQ0KCVlvdSBjYW4gcmVhY2ggdGhlIHBl cnNvbiBtYW5hZ2luZyB0aGUgbGlzdCBhdA0KCSAgICAgICAgbGludXgtZGVjbmV0LXVzZXItYWRt aW5AbGlzdHMuc291cmNlZm9yZ2UubmV0DQoJDQoJV2hlbiByZXBseWluZywgcGxlYXNlIGVkaXQg eW91ciBTdWJqZWN0IGxpbmUgc28gaXQgaXMgbW9yZSBzcGVjaWZpYw0KCXRoYW4gIlJlOiBDb250 ZW50cyBvZiBMaW51eC1kZWNuZXQtdXNlciBkaWdlc3QuLi4iDQoJDQoJDQoJVG9kYXkncyBUb3Bp Y3M6DQoJDQoJICAgMS4gKG5vIHN1YmplY3QpIChCQVNTSVIgTW9oY2luZSkNCgkgICAyLiBSZTog KG5vIHN1YmplY3QpIChQYXRyaWNrIENhdWxmaWVsZCkNCgkgICAzLiBSZTogWCBmcm9tIFZNUyAo UmVpbmhhcmQgS2FyY2hlcikNCgkgICA0LiBYIGFuZCBEZWNuZXQgKEJBU1NJUiBNb2hjaW5lKQ0K CQ0KCS0tX18tLV9fLS0NCgkNCglNZXNzYWdlOiAxDQoJRGF0ZTogRnJpLCAyNSBBcHIgMjAwMyAx MTo0NTo1MyArMDIwMA0KCUZyb206ICJCQVNTSVIgTW9oY2luZSIgPE1vaGNpbmUuQkFTU0lSQGF4 ZW5zLm5ldD4NCglUbzogPHN0ZXZlQGd3LmNoeWd3eW4uY29tPg0KCUNjOiA8bGludXgtZGVjbmV0 LXVzZXItcmVxdWVzdEBsaXN0cy5zb3VyY2Vmb3JnZS5uZXQ+LA0KCSAgICAgICAgPGxpbnV4LWRl Y25ldC11c2VyQGxpc3RzLnNvdXJjZWZvcmdlLm5ldD4NCglTdWJqZWN0OiBbTGludXgtZGVjbmV0 LXVzZXJdIChubyBzdWJqZWN0KQ0KCQ0KCQ0KCUhpIFN0ZXZlbiBXaGl0ZWhvdXNlLA0KCQ0KCSAg ICAgICAgSSB1c2luZyBkZWNuZXQgZG5wcm9ncy0yLjIyLTEuaTU4NiBvbiBNYW5kcmFrZSA5LjEg d2l0aA0KCVhGcmVlLTQuMy01Lg0KCSAgICAgICAgV2hlbiBpIHRyeSB0byBsdW5jaCBhbiBYIGFw cGxpY2F0aW9uIGZyb20gVk1TIHN5c3RlbSBhbmQNCglkaXNwbGF5ZWQgb24gbGludXgsIHRoZSBh cHBsaWNhdGlvbiByZXR1cm4gYW4gWGxpYiBpbyBlcnJvci4NCgkNCglEbyB5b3UgaGF2ZSBzb21l IGlkZWEgYWJvdXQgaXQgPw0KCQ0KCVRoYW5rcy4NCgkNCglNLiBCQVNTSVINCgkNCgkNCgkNCgkt LV9fLS1fXy0tDQoJDQoJTWVzc2FnZTogMg0KCURhdGU6IEZyaSwgMjUgQXByIDIwMDMgMTA6NTc6 MjcgKzAxMDANCglGcm9tOiBQYXRyaWNrIENhdWxmaWVsZCA8cGF0cmlja0B0eWtlcGVuZ3Vpbi5j b20+DQoJVG86IGxpbnV4LWRlY25ldC11c2VyQGxpc3RzLnNvdXJjZWZvcmdlLm5ldA0KCVN1Ympl Y3Q6IFJlOiBbTGludXgtZGVjbmV0LXVzZXJdIChubyBzdWJqZWN0KQ0KCQ0KCU9uIEZyaSwgQXBy IDI1LCAyMDAzIGF0IDExOjQ1OjUzQU0gKzAyMDAsIEJBU1NJUiBNb2hjaW5lIHdyb3RlOg0KCT4N Cgk+IEhpIFN0ZXZlbiBXaGl0ZWhvdXNlLA0KCT4NCgk+ICAgICAgIEkgdXNpbmcgZGVjbmV0IGRu cHJvZ3MtMi4yMi0xLmk1ODYgb24gTWFuZHJha2UgOS4xIHdpdGgNCgk+IFhGcmVlLTQuMy01Lg0K CT4gICAgICAgV2hlbiBpIHRyeSB0byBsdW5jaCBhbiBYIGFwcGxpY2F0aW9uIGZyb20gVk1TIHN5 c3RlbSBhbmQNCgk+IGRpc3BsYXllZCBvbiBsaW51eCwgdGhlIGFwcGxpY2F0aW9uIHJldHVybiBh biBYbGliIGlvIGVycm9yLg0KCT4NCgk+IERvIHlvdSBoYXZlIHNvbWUgaWRlYSBhYm91dCBpdCA/ DQoJDQoJSXQncyBwcmV0dHkgbGlrZWx5IHRoYXQgeW91ciBYc2VydmVyIGRvZXNuJ3QgaGF2ZSBE RUNuZXQgc3VwcG9ydCBjb21waWxlZCBpbi4NCglUaGF0J3MgbmV2ZXIgYmVlbiB0aGUgZGVmYXVs dCBpbiBhbnkgZGlzdHJpYnV0aW9uIEkndmUgaGVhcmQgb2YuDQoJDQoJWW91J2xsIGVpdGhlciBu ZWVkIHRvIGNvbXBpbGUgeW91ciBvd24gWHNlcnZlciBvciB1c2Ugb25lIG9mIHRoZSBwcmUtYnVp bHQgb25lcw0KCW9uIHRoZSB3ZWIgc2l0ZS4NCgkNCgktLQ0KCQ0KCXBhdHJpY2sNCgkNCgkNCgkN CgktLV9fLS1fXy0tDQoJDQoJTWVzc2FnZTogMw0KCURhdGU6IEZyaSwgMjUgQXByIDIwMDMgMTI6 MDE6MzIgKzAyMDANCglGcm9tOiBSZWluaGFyZCBLYXJjaGVyIDxya2FyY2hlckBmcmV5LmRlPg0K CVRvOiBsaW51eC1kZWNuZXQtdXNlckBsaXN0cy5zb3VyY2Vmb3JnZS5uZXQNCglTdWJqZWN0OiBb TGludXgtZGVjbmV0LXVzZXJdIFJlOiBYIGZyb20gVk1TDQoJDQoJT24gRnJpLCBBcHIgMjUsIDIw MDMgYXQgMTE6NDU6NTNBTSArMDIwMCwgQkFTU0lSIE1vaGNpbmUgd3JvdGUNCgk+DQoJPiAgICAg ICBJIHVzaW5nIGRlY25ldCBkbnByb2dzLTIuMjItMS5pNTg2IG9uIE1hbmRyYWtlIDkuMSB3aXRo DQoJPiBYRnJlZS00LjMtNS4NCgk+ICAgICAgIFdoZW4gaSB0cnkgdG8gbHVuY2ggYW4gWCBhcHBs aWNhdGlvbiBmcm9tIFZNUyBzeXN0ZW0gYW5kDQoJPiBkaXNwbGF5ZWQgb24gbGludXgsIHRoZSBh cHBsaWNhdGlvbiByZXR1cm4gYW4gWGxpYiBpbyBlcnJvci4NCgk+DQoJRG8geW91IHVzZSBERUNO RVQgb3IgVENQSVAgdHJhbnNwb3J0Pw0KCUlmIHlvdSB1c2UgREVDTkVULCB5b3UgbmVlZCBhbiBY U2VydmVyIGNvbXBpbGVkIHdpdGggREVDTkVUIHN1cHBvcnQsDQoJd2hpY2ggaXMgbm90IHRoZSBz dGFuZGFyZC4NCgkNCgkgUmVpbmhhcmQNCgkNCgkNCgkNCgktLV9fLS1fXy0tDQoJDQoJTWVzc2Fn ZTogNA0KCURhdGU6IEZyaSwgMjUgQXByIDIwMDMgMTQ6MDE6MDUgKzAyMDANCglGcm9tOiAiQkFT U0lSIE1vaGNpbmUiIDxNb2hjaW5lLkJBU1NJUkBheGVucy5uZXQ+DQoJVG86IDxzdGV2ZUBndy5j aHlnd3luLmNvbT4sDQoJICAgICAgICA8bGludXgtZGVjbmV0LXVzZXItcmVxdWVzdEBsaXN0cy5z b3VyY2Vmb3JnZS5uZXQ+LA0KCSAgICAgICAgPGxpbnV4LWRlY25ldC11c2VyQGxpc3RzLnNvdXJj ZWZvcmdlLm5ldD4NCglTdWJqZWN0OiBbTGludXgtZGVjbmV0LXVzZXJdIFggYW5kIERlY25ldA0K CQ0KCQ0KCQ0KCUhpIFN0ZXZlbiBXaGl0ZWhvdXNlLA0KCQ0KCSAgICAgICAgSSB1c2luZyBkZWNu ZXQgZG5wcm9ncy0yLjIyLTEuaTU4NiBvbiBNYW5kcmFrZSA5LjEgd2l0aA0KCVhGcmVlLTQuMy01 Lg0KCSAgICAgICAgV2hlbiBpIHRyeSB0byBsdW5jaCBhbiBYIGFwcGxpY2F0aW9uIGZyb20gVk1T IHN5c3RlbSBhbmQNCglkaXNwbGF5ZWQgb24gbGludXgsIHRoZSBhcHBsaWNhdGlvbiByZXR1cm4g YW4gWGxpYiBpbyBlcnJvci4NCgkNCglEbyB5b3UgaGF2ZSBzb21lIGlkZWEgYWJvdXQgaXQgPw0K CQ0KCVRoYW5rcy4NCgkNCglNLiBCQVNTSVINCgkNCgkNCgkNCgkNCgktLV9fLS1fXy0tDQoJDQoJ X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18NCglMaW51eC1k ZWNuZXQtdXNlciBtYWlsaW5nIGxpc3QNCglMaW51eC1kZWNuZXQtdXNlckBsaXN0cy5zb3VyY2Vm b3JnZS5uZXQNCglodHRwczovL2xpc3RzLnNvdXJjZWZvcmdlLm5ldC9saXN0cy9saXN0aW5mby9s aW51eC1kZWNuZXQtdXNlcg0KCQ0KCQ0KCUVuZCBvZiBMaW51eC1kZWNuZXQtdXNlciBEaWdlc3QN CgkNCg0K |
|
From: BASSIR M. <Moh...@ax...> - 2003-04-25 12:00:43
|
Hi Steven Whitehouse, I using decnet dnprogs-2.22-1.i586 on Mandrake 9.1 with XFree-4.3-5. When i try to lunch an X application from VMS system and displayed on linux, the application return an Xlib io error. Do you have some idea about it ? Thanks. M. BASSIR |
|
From: Reinhard K. <rka...@fr...> - 2003-04-25 10:01:49
|
On Fri, Apr 25, 2003 at 11:45:53AM +0200, BASSIR Mohcine wrote > > I using decnet dnprogs-2.22-1.i586 on Mandrake 9.1 with > XFree-4.3-5. > When i try to lunch an X application from VMS system and > displayed on linux, the application return an Xlib io error. > Do you use DECNET or TCPIP transport? If you use DECNET, you need an XServer compiled with DECNET support, which is not the standard. Reinhard |
|
From: Patrick C. <pa...@ty...> - 2003-04-25 09:57:41
|
On Fri, Apr 25, 2003 at 11:45:53AM +0200, BASSIR Mohcine wrote: > > Hi Steven Whitehouse, > > I using decnet dnprogs-2.22-1.i586 on Mandrake 9.1 with > XFree-4.3-5. > When i try to lunch an X application from VMS system and > displayed on linux, the application return an Xlib io error. > > Do you have some idea about it ? It's pretty likely that your Xserver doesn't have DECnet support compiled in. That's never been the default in any distribution I've heard of. You'll either need to compile your own Xserver or use one of the pre-built ones on the web site. -- patrick |
|
From: BASSIR M. <Moh...@ax...> - 2003-04-25 09:45:35
|
Hi Steven Whitehouse, I using decnet dnprogs-2.22-1.i586 on Mandrake 9.1 with XFree-4.3-5. When i try to lunch an X application from VMS system and displayed on linux, the application return an Xlib io error. Do you have some idea about it ? Thanks. M. BASSIR |
|
From: Patrick C. <pa...@ty...> - 2003-04-23 07:25:45
|
I've uploaded a new RPM for latd 1.18 to the sourceforge site. This fixes two problems: - can't find /etc/latd.conf (it was looking in /) - llogin needs liblockdev.so.1 which isn't always available -- patrick |
|
From: Patrick C. <pa...@ty...> - 2003-04-20 10:18:22
|
Here's version 1.18 of LAT with a major new feature and a fix for a
long-standing bug that finally hit me so I decided to try to fix it :-)
The major new feature is support for reverse-LAT services. The most practical
use for this is to use LATSYM on VMS to print to printers on Linux. In brief you
can create a printer service on Linux like this:
latcp -A -a LINUXPRINT -c "lpr" -ulp -glp
and print to it from VMS by associating an LTA device with the node and
service. Thanks to Paul Hanson for the idea.
The important bug fixed is one that I never saw on Linux (but it had been
reported to me) but I have not seen on Darwin - users logging into a LAT service
found that the shell didn't have job-control enabled.
Here's the full changelog
* Fix configure --enable-debug
* Fix configure --sysconfdir
* Don't send issue file if it exists but is empty.
* Add support for reverse-LAT services. you can now use LATSYM
to print to LAT printers on Linux (and probably many other things too!)
* Make sure node names are truncated at 16 characters
* Fix shell job control problems when connecting to some systems
* Send remote credit a little earlier in an attempt to avoid those
annoying pauses.
Get it from the usual places:
https://sourceforge.net/project/showfiles.php?group_id=4993
or your local Debian mirror.
patrick
|
|
From: David S. M. <da...@re...> - 2003-04-18 10:50:05
|
From: Steven Whitehouse <st...@gw...> Date: Fri, 18 Apr 2003 11:09:21 +0100 (BST) Ok. The new patch is attached. It would also be helpful to have the same infrastructure in slab too I think. Perhaps a call along the lines of: kmem_cache_module_associate(kmem_cache_t *cachep, struct module *module); (or an alternative way of initialising a slab cache) so that each allocation then results in an increment of the module usage count if successful. That would solve most of the problems for DECnet. It seems to be something that might be generally useful as it could automatically fail new allocations if a module unload is underway. I can't see any legitimate situation where this cannot be solved by other means. Look, there are two sides to this story: 1) Gaining reference to protocol module must occur at creation point, ie. for sockets this is sock_create() We have patches pending for this. Similarly for netdevice module refcounting, this occurs already. 2) Rest of details are maintained by protocol implementations already. There is zero reason for making module_get() f.e. each time some route is added to routing tables. Similarly for creation of protocol specific netdev information. This means that knowledge of "can unload" is a local matter. The module infrastructure does not provide a way to handle #2, but Rusty recognizes that in order to do proper unloading for complicated modules (such as ipv6, netfilter connection tracking, etc.) there really does need to be such a facility. So let's not put hacks elsewhere. Meanwhile I'll add your updated patch to 2.5.x when I get a chance. Thanks. |
|
From: Steven W. <st...@gw...> - 2003-04-18 10:09:38
|
Hi,
>
>
> Stephen, I would apply this but there is a huge error you must
> correct first.
>
> try_module_get(THIS_MODULE) has zero meaning, it is bug anytime
> it is coded. In fact I may ask Rusty to BUG() check for this.
> Consider the case that the module count is currently zero and
> on another cpu we are currently unloading the decnet module.
> This will explode, in short order.
>
Yes. It wasn't right before either... recently the increment of the
module usage count in the initialisation has been used to prevent the
unloading of the DECnet module. Originally due to the complications
with modules and the use of slab (which have now gone away). I hope
to fix the module unloading problems in a future patch.
> I know you want to get rid of the MOD_{INC,DEC}_USE_COUNT deprecation
> warnings, however don't do so by introducing new bugs.
>
> How to fix this properly? Good question :-) Arnaldo de Melo is
> working on adding a struct module pointer to proto_ops so that this
> can be handled cleanly, ie. sock_create() does a try_module_get()
> on proto_ops->owner before calling into the AF specific code.
>
> So until Arnaldo puts that infrastructure in, please just delete
> the MOD_{INC,DEC}_USE_COUNT bits from your patch and I'll apply
> it to 2.5.x ok?
>
> Thanks.
>
Ok. The new patch is attached. It would also be helpful to have the same
infrastructure in slab too I think. Perhaps a call along the lines of:
kmem_cache_module_associate(kmem_cache_t *cachep, struct module *module);
(or an alternative way of initialising a slab cache) so that each allocation
then results in an increment of the module usage count if successful. That
would solve most of the problems for DECnet. It seems to be something that
might be generally useful as it could automatically fail new allocations if
a module unload is underway.
Steve.
------------------------------------------------------------------------------
diff -Nru linux-2.5.67/include/net/dn.h linux/include/net/dn.h
--- linux-2.5.67/include/net/dn.h Wed Jan 1 19:21:08 2003
+++ linux/include/net/dn.h Tue Apr 1 16:56:58 2003
@@ -171,17 +171,17 @@
int iif;
};
-static __inline__ dn_address dn_eth2dn(unsigned char *ethaddr)
+static inline dn_address dn_eth2dn(unsigned char *ethaddr)
{
return ethaddr[4] | (ethaddr[5] << 8);
}
-static __inline__ dn_address dn_saddr2dn(struct sockaddr_dn *saddr)
+static inline dn_address dn_saddr2dn(struct sockaddr_dn *saddr)
{
return *(dn_address *)saddr->sdn_nodeaddr;
}
-static __inline__ void dn_dn2eth(unsigned char *ethaddr, dn_address addr)
+static inline void dn_dn2eth(unsigned char *ethaddr, dn_address addr)
{
ethaddr[0] = 0xAA;
ethaddr[1] = 0x00;
@@ -190,6 +190,19 @@
ethaddr[4] = (unsigned char)(addr & 0xff);
ethaddr[5] = (unsigned char)(addr >> 8);
}
+
+static inline void dn_sk_ports_copy(struct flowi *fl, struct dn_scp *scp)
+{
+ fl->uli_u.dnports.sport = scp->addrloc;
+ fl->uli_u.dnports.dport = scp->addrrem;
+ fl->uli_u.dnports.objnum = scp->addr.sdn_objnum;
+ if (fl->uli_u.dnports.objnum == 0) {
+ fl->uli_u.dnports.objnamel = scp->addr.sdn_objnamel;
+ memcpy(fl->uli_u.dnports.objname, scp->addr.sdn_objname, 16);
+ }
+}
+
+extern unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu);
#define DN_MENUVER_ACC 0x01
#define DN_MENUVER_USR 0x02
diff -Nru linux-2.5.67/include/net/dn_dev.h linux/include/net/dn_dev.h
--- linux-2.5.67/include/net/dn_dev.h Thu Mar 6 16:38:53 2003
+++ linux/include/net/dn_dev.h Thu Apr 3 20:28:46 2003
@@ -8,6 +8,7 @@
struct dn_ifaddr *ifa_next;
struct dn_dev *ifa_dev;
dn_address ifa_local;
+ dn_address ifa_address;
unsigned char ifa_flags;
unsigned char ifa_scope;
char ifa_label[IFNAMSIZ];
@@ -171,7 +172,10 @@
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)
+extern int register_dnaddr_notifier(struct notifier_block *nb);
+extern int unregister_dnaddr_notifier(struct notifier_block *nb);
+
+static inline int dn_dev_islocal(struct net_device *dev, dn_address addr)
{
struct dn_dev *dn_db = dev->dn_ptr;
struct dn_ifaddr *ifa;
diff -Nru linux-2.5.67/include/net/dn_fib.h linux/include/net/dn_fib.h
--- linux-2.5.67/include/net/dn_fib.h Wed Jan 1 19:22:03 2003
+++ linux/include/net/dn_fib.h Wed Apr 9 14:30:36 2003
@@ -1,12 +1,6 @@
#ifndef _NET_DN_FIB_H
#define _NET_DN_FIB_H
-#include <linux/config.h>
-
-#ifdef CONFIG_DECNET_ROUTER
-
-#include <linux/rtnetlink.h>
-
struct dn_kern_rta
{
void *rta_dst;
@@ -23,15 +17,6 @@
struct rta_cacheinfo *rta_ci;
};
-struct dn_fib_key {
- dn_address src;
- dn_address dst;
- int iif;
- int oif;
- u32 fwmark;
- unsigned char scope;
-};
-
struct dn_fib_res {
struct dn_fib_rule *r;
struct dn_fib_info *fi;
@@ -60,16 +45,23 @@
unsigned fib_flags;
int fib_protocol;
dn_address fib_prefsrc;
- u32 fib_priority;
+ __u32 fib_priority;
+ __u32 fib_metrics[RTAX_MAX];
+#define dn_fib_mtu fib_metrics[RTAX_MTU-1]
+#define dn_fib_window fib_metrics[RTAX_WINDOW-1]
+#define dn_fib_rtt fib_metrics[RTAX_RTT-1]
+#define dn_fib_advmss fib_metrics[RTAX_ADVMSS-1]
int fib_nhs;
int fib_power;
struct dn_fib_nh fib_nh[0];
-#define fib_dev fib_nh[0].nh_dev
+#define dn_fib_dev fib_nh[0].nh_dev
};
-#define DN_FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
#define DN_FIB_RES_RESET(res) ((res).nh_sel = 0)
+#define DN_FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
+
+#define DN_FIB_RES_PREFSRC(res) ((res).fi->fib_prefsrc ? : __dn_fib_res_prefsrc(&res))
#define DN_FIB_RES_GW(res) (DN_FIB_RES_NH(res).nh_gw)
#define DN_FIB_RES_DEV(res) (DN_FIB_RES_NH(res).nh_dev)
#define DN_FIB_RES_OIF(res) (DN_FIB_RES_NH(res).nh_oif)
@@ -106,7 +98,7 @@
int (*delete)(struct dn_fib_table *t, struct rtmsg *r,
struct dn_kern_rta *rta, struct nlmsghdr *n,
struct netlink_skb_parms *req);
- int (*lookup)(struct dn_fib_table *t, const struct dn_fib_key *key,
+ int (*lookup)(struct dn_fib_table *t, const struct flowi *fl,
struct dn_fib_res *res);
int (*flush)(struct dn_fib_table *t);
#ifdef CONFIG_PROC_FS
@@ -118,7 +110,7 @@
unsigned char data[0];
};
-
+#ifdef CONFIG_DECNET_ROUTER
/*
* dn_fib.c
*/
@@ -132,11 +124,12 @@
struct dn_kern_rta *rta,
const struct nlmsghdr *nlh, int *errp);
extern int dn_fib_semantic_match(int type, struct dn_fib_info *fi,
- const struct dn_fib_key *key, struct dn_fib_res *res);
+ const struct flowi *fl,
+ struct dn_fib_res *res);
extern void dn_fib_release_info(struct dn_fib_info *fi);
extern u16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type);
extern void dn_fib_flush(void);
-extern void dn_fib_select_multipath(const struct dn_fib_key *key,
+extern void dn_fib_select_multipath(const struct flowi *fl,
struct dn_fib_res *res);
extern int dn_fib_sync_down(dn_address local, struct net_device *dev,
int force);
@@ -156,7 +149,9 @@
extern void dn_fib_rules_init(void);
extern void dn_fib_rules_cleanup(void);
extern void dn_fib_rule_put(struct dn_fib_rule *);
-extern int dn_fib_lookup(struct dn_fib_key *key, struct dn_fib_res *res);
+extern __u16 dn_fib_rules_policy(__u16 saddr, struct dn_fib_res *res, unsigned *flags);
+extern unsigned dnet_addr_type(__u16 addr);
+extern int dn_fib_lookup(const struct flowi *fl, struct dn_fib_res *res);
/*
* rtnetlink interface
@@ -169,21 +164,15 @@
extern int dn_fib_rtm_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
extern int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb);
-#define DN_NUM_TABLES 255
-#define DN_MIN_TABLE 1
-#define DN_DEFAULT_TABLE 1
-#define DN_L1_TABLE 1
-#define DN_L2_TABLE 2
-
extern void dn_fib_free_info(struct dn_fib_info *fi);
-static __inline__ void dn_fib_info_put(struct dn_fib_info *fi)
+static inline void dn_fib_info_put(struct dn_fib_info *fi)
{
if (atomic_dec_and_test(&fi->fib_clntref))
dn_fib_free_info(fi);
}
-static __inline__ void dn_fib_res_put(struct dn_fib_res *res)
+static inline void dn_fib_res_put(struct dn_fib_res *res)
{
if (res->fi)
dn_fib_info_put(res->fi);
@@ -191,13 +180,23 @@
dn_fib_rule_put(res->r);
}
-static __inline__ u16 dnet_make_mask(int n)
+extern struct dn_fib_table *dn_fib_tables[];
+
+#else /* Endnode */
+
+#define dn_fib_lookup(fl, res) (-ESRCH)
+#define dn_fib_info_put(fi) do { } while(0)
+#define dn_fib_select_multipath(fl, res) do { } while(0)
+#define dn_fib_rules_policy(saddr,res,flags) (0)
+#define dn_fib_res_put(res) do { } while(0)
+
+#endif /* CONFIG_DECNET_ROUTER */
+
+static inline u16 dnet_make_mask(int n)
{
if (n)
return htons(~((1<<(16-n))-1));
return 0;
}
-
-#endif /* CONFIG_DECNET_ROUTER */
#endif /* _NET_DN_FIB_H */
diff -Nru linux-2.5.67/include/net/dn_neigh.h linux/include/net/dn_neigh.h
--- linux-2.5.67/include/net/dn_neigh.h Wed Jan 1 19:22:00 2003
+++ linux/include/net/dn_neigh.h Sun Mar 9 19:27:48 2003
@@ -18,7 +18,7 @@
extern void dn_neigh_init(void);
extern void dn_neigh_cleanup(void);
-extern struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, void *ptr);
+extern struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, const void *ptr);
extern int dn_neigh_router_hello(struct sk_buff *skb);
extern int dn_neigh_endnode_hello(struct sk_buff *skb);
extern void dn_neigh_pointopoint_hello(struct sk_buff *skb);
diff -Nru linux-2.5.67/include/net/dn_nsp.h linux/include/net/dn_nsp.h
--- linux-2.5.67/include/net/dn_nsp.h Wed Jan 1 19:22:43 2003
+++ linux/include/net/dn_nsp.h Tue Apr 1 11:23:50 2003
@@ -204,4 +204,6 @@
return atomic_read(&sk->rmem_alloc) > (sk->rcvbuf >> 1);
}
+#define DN_MAX_NSP_DATA_HEADER (11)
+
#endif /* _NET_DN_NSP_H */
diff -Nru linux-2.5.67/include/net/dn_route.h linux/include/net/dn_route.h
--- linux-2.5.67/include/net/dn_route.h Fri Mar 21 17:43:43 2003
+++ linux/include/net/dn_route.h Tue Apr 1 16:56:18 2003
@@ -16,7 +16,7 @@
*******************************************************************************/
extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, int pri);
-extern int dn_route_output(struct dst_entry **pprt, dn_address dst, dn_address src, int flags);
+extern int dn_route_output_sock(struct dst_entry **pprt, struct flowi *, struct sock *sk, int flags);
extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
extern int dn_cache_getroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
extern void dn_rt_cache_flush(int delay);
@@ -59,10 +59,10 @@
#define DN_RT_INFO_BLKR 0x40 /* Blocking Requested */
/*
- * The key structure is what we used to look up the route.
+ * The fl structure is what we used to look up the route.
* The rt_saddr & rt_daddr entries are the same as key.saddr & key.daddr
- * except for local input routes, where the rt_saddr = key.daddr and
- * rt_daddr = key.saddr to allow the route to be used for returning
+ * except for local input routes, where the rt_saddr = fl.fld_dst and
+ * rt_daddr = fl.fld_src to allow the route to be used for returning
* packets to the originating host.
*/
struct dn_route {
@@ -70,19 +70,18 @@
struct dst_entry dst;
struct dn_route *rt_next;
} u;
- struct {
- unsigned short saddr;
- unsigned short daddr;
- int iif;
- int oif;
- u32 fwmark;
- } key;
- unsigned short rt_saddr;
- unsigned short rt_daddr;
- unsigned char rt_type;
- unsigned char rt_scope;
- unsigned char rt_protocol;
- unsigned char rt_table;
+
+ __u16 rt_saddr;
+ __u16 rt_daddr;
+ __u16 rt_gateway;
+ __u16 __padding;
+ __u16 rt_src_map;
+ __u16 rt_dst_map;
+
+ unsigned rt_flags;
+ unsigned rt_type;
+
+ struct flowi fl;
};
extern void dn_route_init(void);
@@ -108,34 +107,6 @@
dn_rt_send(skb);
else
kfree_skb(skb);
-}
-
-static inline void dn_nsp_send(struct sk_buff *skb)
-{
- struct sock *sk = skb->sk;
- struct dn_scp *scp = DN_SK(sk);
- struct dst_entry *dst;
-
- skb->h.raw = skb->data;
- scp->stamp = jiffies;
-
- if ((dst = sk->dst_cache) && !dst->obsolete) {
-try_again:
- skb->dst = dst_clone(dst);
- dst_output(skb);
- return;
- }
-
- dst_release(xchg(&sk->dst_cache, NULL));
-
- if (dn_route_output(&sk->dst_cache, dn_saddr2dn(&scp->peer), dn_saddr2dn(&scp->addr), 0) == 0) {
- dst = sk->dst_cache;
- goto try_again;
- }
-
- sk->err = EHOSTUNREACH;
- if (!test_bit(SOCK_DEAD, &sk->flags))
- sk->state_change(sk);
}
#endif /* _NET_DN_ROUTE_H */
diff -Nru linux-2.5.67/include/net/flow.h linux/include/net/flow.h
--- linux-2.5.67/include/net/flow.h Wed Jan 1 19:23:03 2003
+++ linux/include/net/flow.h Tue Mar 25 14:48:50 2003
@@ -25,7 +25,18 @@
struct in6_addr * saddr;
__u32 flowlabel;
} ip6_u;
+
+ struct {
+ __u16 daddr;
+ __u16 saddr;
+ __u32 fwmark;
+ __u8 scope;
+ } dn_u;
} nl_u;
+#define fld_dst nl_u.dn_u.daddr
+#define fld_src nl_u.dn_u.saddr
+#define fld_fwmark nl_u.dn_u.fwmark
+#define fld_scope nl_u.dn_u.scope
#define fl6_dst nl_u.ip6_u.daddr
#define fl6_src nl_u.ip6_u.saddr
#define fl6_flowlabel nl_u.ip6_u.flowlabel
@@ -47,6 +58,14 @@
__u8 type;
__u8 code;
} icmpt;
+
+ struct {
+ __u16 sport;
+ __u16 dport;
+ __u8 objnum;
+ __u8 objnamel; /* Not 16 bits since max val is 16 */
+ __u8 objname[16]; /* Not zero terminated */
+ } dnports;
__u32 spi;
} uli_u;
diff -Nru linux-2.5.67/include/net/sock.h linux/include/net/sock.h
--- linux-2.5.67/include/net/sock.h Mon Apr 7 15:36:52 2003
+++ linux/include/net/sock.h Mon Apr 7 15:36:34 2003
@@ -868,6 +868,9 @@
* schedule();
* SOCK_SLEEP_POST(sk)
*
+ * N.B. These are now obsolete and were, afaik, only ever used in DECnet
+ * and when the last use of them in DECnet has gone, I'm intending to
+ * remove them.
*/
#define SOCK_SLEEP_PRE(sk) { struct task_struct *tsk = current; \
diff -Nru linux-2.5.67/net/decnet/TODO linux/net/decnet/TODO
--- linux-2.5.67/net/decnet/TODO Wed Jan 1 19:22:34 2003
+++ linux/net/decnet/TODO Thu Apr 3 21:54:00 2003
@@ -26,25 +26,16 @@
o Start to hack together user level software and add more DECnet support
in ifconfig for example.
- o Test adding/deleting of routes
-
- o Test route lookup
-
- o Test /proc/net/decnet_route route listing works correctly (maybe I'll
- change the format of this file... atm its very similar to the IPv4 route
- 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.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 Add the routing message grabbing netfilter module [written, tested,
awaiting merge]
- o Add perfect socket hashing - an idea suggested by Paul Koning [part written,
- awaiting debugging and merge]
+ o Add perfect socket hashing - an idea suggested by Paul Koning. Currently
+ we have a half-way house scheme which seems to work reasonably well, but
+ the full scheme is still worth implementing, its not not top of my list
+ right now.
o Add session control message flow control
@@ -53,4 +44,6 @@
o DECnet sendpages() function
o AIO for DECnet
+
+ o Eliminate dn_db->parms.blksize
diff -Nru linux-2.5.67/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c
--- linux-2.5.67/net/decnet/af_decnet.c Fri Mar 21 17:43:44 2003
+++ linux/net/decnet/af_decnet.c Fri Apr 18 02:39:42 2003
@@ -118,6 +118,7 @@
#include <linux/netfilter.h>
#include <net/sock.h>
#include <net/tcp.h>
+#include <net/flow.h>
#include <asm/system.h>
#include <asm/ioctls.h>
#include <linux/mm.h>
@@ -146,6 +147,7 @@
#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;
static rwlock_t dn_hash_lock = RW_LOCK_UNLOCKED;
@@ -273,7 +275,7 @@
if (hash == 0) {
hash = addr->sdn_objnamel;
- for(i = 0; i < addr->sdn_objnamel; i++) {
+ for(i = 0; i < dn_ntohs(addr->sdn_objnamel); i++) {
hash ^= addr->sdn_objname[i];
hash ^= (hash << 3);
}
@@ -512,8 +514,7 @@
scp->services_loc = 1 | NSP_FC_NONE;
scp->info_rem = 0;
scp->info_loc = 0x03; /* NSP version 4.1 */
- scp->segsize_rem = 230; /* Default: Updated by remote segsize */
- scp->segsize_loc = 1450; /* Best guess for ethernet */
+ scp->segsize_rem = 230 - DN_MAX_NSP_DATA_HEADER; /* Default: Updated by remote segsize */
scp->nonagle = 0;
scp->multi_ireq = 1;
scp->accept_mode = ACC_IMMED;
@@ -788,8 +789,8 @@
return -EINVAL;
#if 1
- if ((!capable(CAP_NET_BIND_SERVICE) && saddr->sdn_objnum) ||
- (saddr->sdn_flags & SDF_WILD))
+ if (!capable(CAP_NET_BIND_SERVICE) && (saddr->sdn_objnum ||
+ (saddr->sdn_flags & SDF_WILD)))
return -EACCES;
#else
/*
@@ -877,18 +878,18 @@
static int dn_confirm_accept(struct sock *sk, long *timeo, int allocation)
{
struct dn_scp *scp = DN_SK(sk);
- DECLARE_WAITQUEUE(wait, current);
+ DEFINE_WAIT(wait);
int err;
if (scp->state != DN_CR)
return -EINVAL;
scp->state = DN_CC;
+ scp->segsize_loc = dst_path_metric(__sk_dst_get(sk), RTAX_ADVMSS);
dn_send_conn_conf(sk, allocation);
- add_wait_queue(sk->sleep, &wait);
+ prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE);
for(;;) {
- set_current_state(TASK_INTERRUPTIBLE);
release_sock(sk);
if (scp->state == DN_CC)
*timeo = schedule_timeout(*timeo);
@@ -905,16 +906,21 @@
err = -EAGAIN;
if (!*timeo)
break;
+ prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE);
+ }
+ finish_wait(sk->sleep, &wait);
+ if (err == 0) {
+ sk->socket->state = SS_CONNECTED;
+ } else if (scp->state != DN_CC) {
+ sk->socket->state = SS_UNCONNECTED;
}
- remove_wait_queue(sk->sleep, &wait);
- current->state = TASK_RUNNING;
return err;
}
static int dn_wait_run(struct sock *sk, long *timeo)
{
struct dn_scp *scp = DN_SK(sk);
- DECLARE_WAITQUEUE(wait, current);
+ DEFINE_WAIT(wait);
int err = 0;
if (scp->state == DN_RUN)
@@ -923,9 +929,8 @@
if (!*timeo)
return -EALREADY;
- add_wait_queue(sk->sleep, &wait);
+ prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE);
for(;;) {
- set_current_state(TASK_INTERRUPTIBLE);
release_sock(sk);
if (scp->state == DN_CI || scp->state == DN_CC)
*timeo = schedule_timeout(*timeo);
@@ -942,12 +947,14 @@
err = -ETIMEDOUT;
if (!*timeo)
break;
+ prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE);
}
- remove_wait_queue(sk->sleep, &wait);
- current->state = TASK_RUNNING;
+ finish_wait(sk->sleep, &wait);
out:
if (err == 0) {
sk->socket->state = SS_CONNECTED;
+ } else if (scp->state != DN_CI && scp->state != DN_CC) {
+ sk->socket->state = SS_UNCONNECTED;
}
return err;
}
@@ -957,6 +964,7 @@
struct socket *sock = sk->socket;
struct dn_scp *scp = DN_SK(sk);
int err = -EISCONN;
+ struct flowi fl;
if (sock->state == SS_CONNECTED)
goto out;
@@ -995,12 +1003,17 @@
memcpy(&scp->peer, addr, sizeof(struct sockaddr_dn));
err = -EHOSTUNREACH;
- if (dn_route_output(&sk->dst_cache, dn_saddr2dn(&scp->peer),
- dn_saddr2dn(&scp->addr), flags & MSG_TRYHARD) < 0)
+ memset(&fl, 0, sizeof(fl));
+ fl.oif = sk->bound_dev_if;
+ fl.fld_dst = dn_saddr2dn(&scp->peer);
+ fl.fld_src = dn_saddr2dn(&scp->addr);
+ dn_sk_ports_copy(&fl, scp);
+ if (dn_route_output_sock(&sk->dst_cache, &fl, sk, flags) < 0)
goto out;
-
+ sk->route_caps = sk->dst_cache->dev->features;
sock->state = SS_CONNECTING;
scp->state = DN_CI;
+ scp->segsize_loc = dst_path_metric(sk->dst_cache, RTAX_ADVMSS);
dn_nsp_send_conninit(sk, NSP_CI);
err = -EINPROGRESS;
@@ -1077,13 +1090,12 @@
static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo)
{
- DECLARE_WAITQUEUE(wait, current);
+ DEFINE_WAIT(wait);
struct sk_buff *skb = NULL;
int err = 0;
- add_wait_queue_exclusive(sk->sleep, &wait);
+ prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE);
for(;;) {
- set_current_state(TASK_INTERRUPTIBLE);
release_sock(sk);
skb = skb_dequeue(&sk->receive_queue);
if (skb == NULL) {
@@ -1102,9 +1114,10 @@
err = -EAGAIN;
if (!*timeo)
break;
+ prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE);
}
- remove_wait_queue(sk->sleep, &wait);
- current->state = TASK_RUNNING;
+ finish_wait(sk->sleep, &wait);
+
return skb == NULL ? ERR_PTR(err) : skb;
}
@@ -1276,12 +1289,6 @@
release_sock(sk);
return val;
-#ifdef CONFIG_DECNET_ROUTER
- case SIOCADDRT:
- case SIOCDELRT:
- return dn_fib_ioctl(sock, cmd, arg);
-#endif /* CONFIG_DECNET_ROUTER */
-
case TIOCOUTQ:
amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
if (amount < 0)
@@ -1888,6 +1895,64 @@
return 0;
}
+/*
+ * The DECnet spec requires the the "routing layer" accepts packets which
+ * are at least 230 bytes in size. This excludes any headers which the NSP
+ * layer might add, so we always assume that we'll be using the maximal
+ * length header on data packets. The variation in length is due to the
+ * inclusion (or not) of the two 16 bit acknowledgement fields so it doesn't
+ * make much practical difference.
+ */
+unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu)
+{
+ unsigned mss = 230 - DN_MAX_NSP_DATA_HEADER;
+ if (dev) {
+ struct dn_dev *dn_db = dev->dn_ptr;
+ mtu -= LL_RESERVED_SPACE(dev);
+ if (dn_db->use_long)
+ mtu -= 21;
+ else
+ mtu -= 6;
+ mtu -= DN_MAX_NSP_DATA_HEADER;
+ } else {
+ /*
+ * 21 = long header, 16 = guess at MAC header length
+ */
+ mtu -= (21 + DN_MAX_NSP_DATA_HEADER + 16);
+ }
+ if (mtu > mss)
+ mss = mtu;
+ return mss;
+}
+
+static inline unsigned int dn_current_mss(struct sock *sk, int flags)
+{
+ struct dst_entry *dst = __sk_dst_get(sk);
+ struct dn_scp *scp = DN_SK(sk);
+ int mss_now = min_t(int, scp->segsize_loc, scp->segsize_rem);
+
+ /* Other data messages are limited to 16 bytes per packet */
+ if (flags & MSG_OOB)
+ return 16;
+
+ /* This works out the maximum size of segment we can send out */
+ if (dst) {
+ u32 mtu = dst_pmtu(dst);
+ mss_now = min_t(int, dn_mss_from_pmtu(dst->dev, mtu), mss_now);
+ }
+
+ return mss_now;
+}
+
+static int dn_error(struct sock *sk, int flags, int err)
+{
+ if (err == -EPIPE)
+ err = sock_error(sk) ? : -EPIPE;
+ if (err == -EPIPE && !(flags & MSG_NOSIGNAL))
+ send_sig(SIGPIPE, current, 0);
+ return err;
+}
+
static int dn_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, int size)
{
@@ -1902,9 +1967,6 @@
struct sockaddr_dn *addr = (struct sockaddr_dn *)msg->msg_name;
struct sk_buff *skb = NULL;
struct dn_skb_cb *cb;
- unsigned char msgflg;
- unsigned char *ptr;
- unsigned short ack;
int len;
unsigned char fctype;
long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
@@ -1915,17 +1977,26 @@
if (addr_len && (addr_len != sizeof(struct sockaddr_dn)))
return -EINVAL;
+ /*
+ * The only difference between stream sockets and sequenced packet
+ * sockets is that the stream sockets always behave as if MSG_EOR
+ * has been set.
+ */
+ if (sock->type == SOCK_STREAM) {
+ if (flags & MSG_EOR)
+ return -EINVAL;
+ flags |= MSG_EOR;
+ }
+
lock_sock(sk);
err = dn_check_state(sk, addr, addr_len, &timeo, flags);
if (err)
- goto out;
+ goto out_err;
if (sk->shutdown & SEND_SHUTDOWN) {
- if (!(flags & MSG_NOSIGNAL))
- send_sig(SIGPIPE, current, 0);
err = -EPIPE;
- goto out;
+ goto out_err;
}
if ((flags & MSG_TRYHARD) && sk->dst_cache)
@@ -1934,20 +2005,9 @@
mss = scp->segsize_rem;
fctype = scp->services_rem & NSP_FC_MASK;
- if (sk->dst_cache && sk->dst_cache->neighbour) {
- struct dn_neigh *dn = (struct dn_neigh *)sk->dst_cache->neighbour;
- if (dn->blksize < (mss + 11))
- mss = dn->blksize - 11;
- }
-
- /*
- * The only difference between SEQPACKET & STREAM sockets under DECnet
- * is that SEQPACKET sockets set the MSG_EOR flag for the last
- * session control message segment.
- */
+ mss = dn_current_mss(sk, flags);
if (flags & MSG_OOB) {
- mss = 16;
queue = &scp->other_xmit_queue;
if (size > mss) {
err = -EMSGSIZE;
@@ -2008,7 +2068,7 @@
cb = DN_SKB_CB(skb);
- ptr = skb_put(skb, 9);
+ skb_reserve(skb, DN_MAX_NSP_DATA_HEADER);
if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
err = -EFAULT;
@@ -2016,45 +2076,26 @@
}
if (flags & MSG_OOB) {
- cb->segnum = scp->numoth;
- seq_add(&scp->numoth, 1);
- msgflg = 0x30;
- ack = (scp->numoth_rcv & 0x0FFF) | 0x8000;
- scp->ackxmt_oth = scp->numoth_rcv;
+ cb->nsp_flags = 0x30;
if (fctype != NSP_FC_NONE)
scp->flowrem_oth--;
} else {
- cb->segnum = scp->numdat;
- seq_add(&scp->numdat, 1);
- msgflg = 0x00;
- if (sock->type == SOCK_STREAM)
- msgflg = 0x60;
+ cb->nsp_flags = 0x00;
if (scp->seg_total == 0)
- msgflg |= 0x20;
+ cb->nsp_flags |= 0x20;
scp->seg_total += len;
if (((sent + len) == size) && (flags & MSG_EOR)) {
- msgflg |= 0x40;
+ cb->nsp_flags |= 0x40;
scp->seg_total = 0;
if (fctype == NSP_FC_SCMC)
scp->flowrem_dat--;
}
- ack = (scp->numdat_rcv & 0x0FFF) | 0x8000;
- scp->ackxmt_dat = scp->numdat_rcv;
if (fctype == NSP_FC_SRC)
scp->flowrem_dat--;
}
- *ptr++ = msgflg;
- *(__u16 *)ptr = scp->addrrem;
- ptr += 2;
- *(__u16 *)ptr = scp->addrloc;
- ptr += 2;
- *(__u16 *)ptr = dn_htons(ack);
- ptr += 2;
- *(__u16 *)ptr = dn_htons(cb->segnum);
-
sent += len;
dn_nsp_queue_xmit(sk, skb, sk->allocation, flags & MSG_OOB);
skb = NULL;
@@ -2070,6 +2111,11 @@
release_sock(sk);
return sent ? sent : err;
+
+out_err:
+ err = dn_error(sk, flags, err);
+ release_sock(sk);
+ return err;
}
static int dn_device_event(struct notifier_block *this, unsigned long event,
@@ -2215,10 +2261,8 @@
.sendpage = sock_no_sendpage,
};
-#ifdef CONFIG_SYSCTL
void dn_register_sysctl(void);
void dn_unregister_sysctl(void);
-#endif
MODULE_DESCRIPTION("The Linux DECnet Network Protocol");
@@ -2226,7 +2270,7 @@
MODULE_LICENSE("GPL");
-static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.5.40s (C) 1995-2002 Linux DECnet Project Team\n";
+static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.5.67s (C) 1995-2003 Linux DECnet Project Team\n";
static int __init decnet_init(void)
{
@@ -2253,9 +2297,7 @@
dn_fib_init();
#endif /* CONFIG_DECNET_ROUTER */
-#ifdef CONFIG_SYSCTL
dn_register_sysctl();
-#endif /* CONFIG_SYSCTL */
/*
* Prevent DECnet module unloading until its fixed properly.
@@ -2273,9 +2315,7 @@
sock_unregister(AF_DECnet);
dev_remove_pack(&dn_dix_packet_type);
-#ifdef CONFIG_SYSCTL
dn_unregister_sysctl();
-#endif /* CONFIG_SYSCTL */
unregister_netdevice_notifier(&dn_dev_notifier);
diff -Nru linux-2.5.67/net/decnet/dn_dev.c linux/net/decnet/dn_dev.c
--- linux-2.5.67/net/decnet/dn_dev.c Thu Mar 6 16:38:53 2003
+++ linux/net/decnet/dn_dev.c Thu Apr 3 23:26:31 2003
@@ -36,9 +36,11 @@
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/sysctl.h>
+#include <linux/notifier.h>
#include <asm/uaccess.h>
#include <net/neighbour.h>
#include <net/dst.h>
+#include <net/flow.h>
#include <net/dn.h>
#include <net/dn_dev.h>
#include <net/dn_route.h>
@@ -61,6 +63,7 @@
static rwlock_t dndev_lock = RW_LOCK_UNLOCKED;
static struct net_device *decnet_default_device;
+static struct notifier_block *dnaddr_chain;
static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
static void dn_dev_delete(struct net_device *dev);
@@ -478,7 +481,7 @@
}
rtmsg_ifa(RTM_DELADDR, ifa1);
-
+ notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
if (destroy) {
dn_dev_free_ifa(ifa1);
@@ -513,6 +516,7 @@
dn_db->ifa_list = ifa;
rtmsg_ifa(RTM_NEWADDR, ifa);
+ notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
return 0;
}
@@ -609,7 +613,7 @@
dn_dev_del_ifa(dn_db, ifap, 0);
}
- ifa->ifa_local = dn_saddr2dn(sdn);
+ ifa->ifa_local = ifa->ifa_address = dn_saddr2dn(sdn);
ret = dn_dev_set_ifa(dev, ifa);
}
@@ -686,7 +690,10 @@
if ((ifa = dn_dev_alloc_ifa()) == NULL)
return -ENOBUFS;
+ if (!rta[IFA_ADDRESS - 1])
+ rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1];
memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL-1]), 2);
+ memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS-1]), 2);
ifa->ifa_flags = ifm->ifa_flags;
ifa->ifa_scope = ifm->ifa_scope;
ifa->ifa_dev = dn_db;
@@ -716,7 +723,10 @@
ifm->ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT;
ifm->ifa_scope = ifa->ifa_scope;
ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
- RTA_PUT(skb, IFA_LOCAL, 2, &ifa->ifa_local);
+ if (ifa->ifa_address)
+ RTA_PUT(skb, IFA_ADDRESS, 2, &ifa->ifa_address);
+ if (ifa->ifa_local)
+ RTA_PUT(skb, IFA_LOCAL, 2, &ifa->ifa_local);
if (ifa->ifa_label[0])
RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label);
nlh->nlmsg_len = skb->tail - b;
@@ -758,10 +768,7 @@
s_idx = cb->args[0];
s_dn_idx = dn_idx = cb->args[1];
read_lock(&dev_base_lock);
- for(dev = dev_base, idx = 0; dev; dev = dev->next) {
- if ((dn_db = dev->dn_ptr) == NULL)
- continue;
- idx++;
+ for(dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
if (idx < s_idx)
continue;
if (idx > s_idx)
@@ -773,7 +780,10 @@
if (dn_idx < s_dn_idx)
continue;
- if (dn_dev_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWADDR) <= 0)
+ if (dn_dev_fill_ifaddr(skb, ifa,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq,
+ RTM_NEWADDR) <= 0)
goto done;
}
}
@@ -872,8 +882,6 @@
}
-#ifdef CONFIG_DECNET_ROUTER
-
#define DRDELAY (5 * HZ)
static int dn_am_i_a_router(struct dn_neigh *dn, struct dn_dev *dn_db, struct dn_ifaddr *ifa)
@@ -981,12 +989,6 @@
else
dn_send_router_hello(dev, ifa);
}
-#else
-static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa)
-{
- dn_send_endnode_hello(dev, ifa);
-}
-#endif
#if 0
static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa)
@@ -1175,7 +1177,7 @@
if ((ifa = dn_dev_alloc_ifa()) == NULL)
return;
- ifa->ifa_local = addr;
+ ifa->ifa_local = ifa->ifa_address = addr;
ifa->ifa_flags = 0;
ifa->ifa_scope = RT_SCOPE_UNIVERSE;
strcpy(ifa->ifa_label, dev->name);
@@ -1274,6 +1276,15 @@
rtnl_unlock();
}
+int register_dnaddr_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_register(&dnaddr_chain, nb);
+}
+
+int unregister_dnaddr_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_unregister(&dnaddr_chain, nb);
+}
#ifdef CONFIG_DECNET_SIOCGIFCONF
/*
@@ -1390,43 +1401,21 @@
static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
{
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, },
-
- { dn_dev_rtm_newaddr, NULL, },
- { dn_dev_rtm_deladdr, NULL, },
- { NULL, dn_dev_dump_ifaddr, },
- { NULL, NULL, },
+ [4] = { .doit = dn_dev_rtm_newaddr, },
+ [5] = { .doit = dn_dev_rtm_deladdr, },
+ [6] = { .dumpit = dn_dev_dump_ifaddr, },
#ifdef CONFIG_DECNET_ROUTER
- { dn_fib_rtm_newroute, NULL, },
- { dn_fib_rtm_delroute, NULL, },
- { dn_cache_getroute, dn_fib_dump, },
- { NULL, NULL, },
+ [8] = { .doit = dn_fib_rtm_newroute, },
+ [9] = { .doit = dn_fib_rtm_delroute, },
+ [10] = { .doit = dn_cache_getroute, .dumpit = dn_fib_dump, },
+ [16] = { .doit = dn_fib_rtm_newrule, },
+ [17] = { .doit = dn_fib_rtm_delrule, },
+ [18] = { .dumpit = dn_fib_dump_rules, },
#else
- { NULL, NULL, },
- { NULL, NULL, },
- { dn_cache_getroute, dn_cache_dump, },
- { NULL, NULL, },
+ [10] = { .doit = dn_cache_getroute, .dumpit = dn_cache_dump, },
#endif
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, },
-#ifdef CONFIG_DECNET_ROUTER
- { dn_fib_rtm_newrule, NULL, },
- { dn_fib_rtm_delrule, NULL, },
- { NULL, dn_fib_dump_rules, },
- { NULL, NULL, }
-#else
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, }
-#endif
};
#ifdef MODULE
diff -Nru linux-2.5.67/net/decnet/dn_fib.c linux/net/decnet/dn_fib.c
--- linux-2.5.67/net/decnet/dn_fib.c Wed Jan 1 19:23:31 2003
+++ linux/net/decnet/dn_fib.c Mon Apr 7 11:37:06 2003
@@ -12,6 +12,9 @@
* Alexey Kuznetsov : SMP locking changes
* Steve Whitehouse : Rewrote it... Well to be more correct, I
* copied most of it from the ipv4 fib code.
+ * Steve Whitehouse : Updated it in style and fixed a few bugs
+ * which were fixed in the ipv4 code since
+ * this code was copied from it.
*
*/
#include <linux/config.h>
@@ -31,12 +34,14 @@
#include <asm/uaccess.h>
#include <net/neighbour.h>
#include <net/dst.h>
+#include <net/flow.h>
#include <net/dn.h>
#include <net/dn_route.h>
#include <net/dn_fib.h>
#include <net/dn_neigh.h>
#include <net/dn_dev.h>
+#define RT_MIN_TABLE 1
#define for_fib_info() { struct dn_fib_info *fi;\
for(fi = dn_fib_info_list; fi; fi = fi->fib_next)
@@ -52,7 +57,7 @@
extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
-
+static spinlock_t dn_fib_multipath_lock = SPIN_LOCK_UNLOCKED;
static struct dn_fib_info *dn_fib_info_list;
static rwlock_t dn_fib_info_lock = RW_LOCK_UNLOCKED;
int dn_fib_info_cnt;
@@ -62,18 +67,18 @@
int error;
u8 scope;
} dn_fib_props[RTA_MAX+1] = {
- { 0, RT_SCOPE_NOWHERE }, /* RTN_UNSPEC */
- { 0, RT_SCOPE_UNIVERSE }, /* RTN_UNICAST */
- { 0, RT_SCOPE_HOST }, /* RTN_LOCAL */
- { -EINVAL, RT_SCOPE_NOWHERE }, /* RTN_BROADCAST */
- { -EINVAL, RT_SCOPE_NOWHERE }, /* RTN_ANYCAST */
- { -EINVAL, RT_SCOPE_NOWHERE }, /* RTN_MULTICAST */
- { -EINVAL, RT_SCOPE_UNIVERSE }, /* RTN_BLACKHOLE */
- { -EHOSTUNREACH, RT_SCOPE_UNIVERSE }, /* RTN_UNREACHABLE */
- { -EACCES, RT_SCOPE_UNIVERSE }, /* RTN_PROHIBIT */
- { -EAGAIN, RT_SCOPE_UNIVERSE }, /* RTN_THROW */
- { -EINVAL, RT_SCOPE_NOWHERE }, /* RTN_NAT */
- { -EINVAL, RT_SCOPE_NOWHERE } /* RTN_XRESOLVE */
+ { .error = 0, .scope = RT_SCOPE_NOWHERE }, /* RTN_UNSPEC */
+ { .error = 0, .scope = RT_SCOPE_UNIVERSE }, /* RTN_UNICAST */
+ { .error = 0, .scope = RT_SCOPE_HOST }, /* RTN_LOCAL */
+ { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_BROADCAST */
+ { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_ANYCAST */
+ { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_MULTICAST */
+ { .error = -EINVAL, .scope = RT_SCOPE_UNIVERSE }, /* RTN_BLACKHOLE */
+ { .error = -EHOSTUNREACH, .scope = RT_SCOPE_UNIVERSE }, /* RTN_UNREACHABLE */
+ { .error = -EACCES, .scope = RT_SCOPE_UNIVERSE }, /* RTN_PROHIBIT */
+ { .error = -EAGAIN, .scope = RT_SCOPE_UNIVERSE }, /* RTN_THROW */
+ { .error = 0, .scope = RT_SCOPE_NOWHERE }, /* RTN_NAT */
+ { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE } /* RTN_XRESOLVE */
};
void dn_fib_free_info(struct dn_fib_info *fi)
@@ -108,7 +113,7 @@
write_unlock(&dn_fib_info_lock);
}
-static __inline__ int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi)
+static inline int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi)
{
const struct dn_fib_nh *onh = ofi->fib_nh;
@@ -124,7 +129,7 @@
return 0;
}
-static __inline__ struct dn_fib_info *dn_fib_find_info(const struct dn_fib_info *nfi)
+static inline struct dn_fib_info *dn_fib_find_info(const struct dn_fib_info *nfi)
{
for_fib_info() {
if (fi->fib_nhs != nfi->fib_nhs)
@@ -132,6 +137,7 @@
if (nfi->fib_protocol == fi->fib_protocol &&
nfi->fib_prefsrc == fi->fib_prefsrc &&
nfi->fib_priority == fi->fib_priority &&
+ memcmp(nfi->fib_metrics, fi->fib_metrics, sizeof(fi->fib_metrics)) == 0 &&
((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 &&
(nfi->fib_nhs == 0 || dn_fib_nh_comp(fi, nfi) == 0))
return fi;
@@ -195,14 +201,18 @@
int err;
if (nh->nh_gw) {
- struct dn_fib_key key;
+ struct flowi fl;
struct dn_fib_res res;
+ memset(&fl, 0, sizeof(fl));
+
if (nh->nh_flags&RTNH_F_ONLINK) {
struct net_device *dev;
if (r->rtm_scope >= RT_SCOPE_LINK)
return -EINVAL;
+ if (dnet_addr_type(nh->nh_gw) != RTN_UNICAST)
+ return -EINVAL;
if ((dev = __dev_get_by_index(nh->nh_oif)) == NULL)
return -ENODEV;
if (!(dev->flags&IFF_UP))
@@ -213,23 +223,33 @@
return 0;
}
- memset(&key, 0, sizeof(key));
- key.dst = nh->nh_gw;
- key.oif = nh->nh_oif;
- key.scope = r->rtm_scope + 1;
+ memset(&fl, 0, sizeof(fl));
+ fl.fld_dst = nh->nh_gw;
+ fl.oif = nh->nh_oif;
+ fl.fld_scope = r->rtm_scope + 1;
- if (key.scope < RT_SCOPE_LINK)
- key.scope = RT_SCOPE_LINK;
+ if (fl.fld_scope < RT_SCOPE_LINK)
+ fl.fld_scope = RT_SCOPE_LINK;
- if ((err = dn_fib_lookup(&key, &res)) != 0)
+ if ((err = dn_fib_lookup(&fl, &res)) != 0)
return err;
+ err = -EINVAL;
+ if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
+ goto out;
nh->nh_scope = res.scope;
nh->nh_oif = DN_FIB_RES_OIF(res);
nh->nh_dev = DN_FIB_RES_DEV(res);
- if (nh->nh_dev)
- atomic_inc(&nh->nh_dev->refcnt);
+ if (nh->nh_dev == NULL)
+ goto out;
+ atomic_inc(&nh->nh_dev->refcnt);
+ err = -ENETDOWN;
+ if (!(nh->nh_dev->flags & IFF_UP))
+ goto out;
+ err = 0;
+out:
dn_fib_res_put(&res);
+ return err;
} else {
struct net_device *dev;
@@ -277,6 +297,20 @@
fi->fib_flags = r->rtm_flags;
if (rta->rta_priority)
fi->fib_priority = *rta->rta_priority;
+ if (rta->rta_mx) {
+ int attrlen = RTA_PAYLOAD(rta->rta_mx);
+ struct rtattr *attr = RTA_DATA(rta->rta_mx);
+
+ while(RTA_OK(attr, attrlen)) {
+ unsigned flavour = attr->rta_type;
+ if (flavour) {
+ if (flavour > RTAX_MAX)
+ goto err_inval;
+ fi->fib_metrics[flavour-1] = *(unsigned*)RTA_DATA(attr);
+ }
+ attr = RTA_NEXT(attr, attrlen);
+ }
+ }
if (rta->rta_prefsrc)
memcpy(&fi->fib_prefsrc, rta->rta_prefsrc, 2);
@@ -297,6 +331,13 @@
nh->nh_weight = 1;
}
+ if (r->rtm_type == RTN_NAT) {
+ if (rta->rta_gw == NULL || nhs != 1 || rta->rta_oif)
+ goto err_inval;
+ memcpy(&fi->fib_nh->nh_gw, rta->rta_gw, 2);
+ goto link_it;
+ }
+
if (dn_fib_props[r->rtm_type].error) {
if (rta->rta_gw || rta->rta_oif || rta->rta_mp)
goto err_inval;
@@ -324,14 +365,12 @@
} endfor_nexthops(fi)
}
-#if I_GET_AROUND_TO_FIXING_PREFSRC
if (fi->fib_prefsrc) {
if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL ||
memcmp(&fi->fib_prefsrc, rta->rta_dst, 2))
- if (dn_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
+ if (dnet_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
goto err_inval;
}
-#endif
link_it:
if ((ofi = dn_fib_find_info(fi)) != NULL) {
@@ -366,12 +405,53 @@
return NULL;
}
+int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowi *fl, struct dn_fib_res *res)
+{
+ int err = dn_fib_props[type].error;
+
+ if (err == 0) {
+ if (fi->fib_flags & RTNH_F_DEAD)
+ return 1;
+
+ res->fi = fi;
+
+ switch(type) {
+ case RTN_NAT:
+ DN_FIB_RES_RESET(*res);
+ atomic_inc(&fi->fib_clntref);
+ return 0;
+ case RTN_UNICAST:
+ case RTN_LOCAL:
+ for_nexthops(fi) {
+ if (nh->nh_flags & RTNH_F_DEAD)
+ continue;
+ if (!fl->oif || fl->oif == nh->nh_oif)
+ break;
+ }
+ if (nhsel < fi->fib_nhs) {
+ res->nh_sel = nhsel;
+ atomic_inc(&fi->fib_clntref);
+ return 0;
+ }
+ endfor_nexthops(fi);
+ res->fi = NULL;
+ return 1;
+ default:
+ if (net_ratelimit())
+ printk("DECnet: impossible routing event : dn_fib_semantic_match type=%d\n", type);
+ res->fi = NULL;
+ return -EINVAL;
+ }
+ }
+ return err;
+}
-void dn_fib_select_multipath(const struct dn_fib_key *key, struct dn_fib_res *res)
+void dn_fib_select_multipath(const struct flowi *fl, struct dn_fib_res *res)
{
struct dn_fib_info *fi = res->fi;
int w;
+ spin_lock_bh(&dn_fib_multipath_lock);
if (fi->fib_power <= 0) {
int power = 0;
change_nexthops(fi) {
@@ -381,6 +461,11 @@
}
} endfor_nexthops(fi);
fi->fib_power = power;
+ if (power < 0) {
+ spin_unlock_bh(&dn_fib_multipath_lock);
+ res->nh_sel = 0;
+ return;
+ }
}
w = jiffies % fi->fib_power;
@@ -391,16 +476,16 @@
nh->nh_power--;
fi->fib_power--;
res->nh_sel = nhsel;
+ spin_unlock_bh(&dn_fib_multipath_lock);
return;
}
}
} endfor_nexthops(fi);
-
- printk(KERN_DEBUG "DECnet: BUG! dn_fib_select_multipath\n");
+ res->nh_sel = 0;
+ spin_unlock_bh(&dn_fib_multipath_lock);
}
-
/*
* Punt to user via netlink for example, but for now
* we just drop it.
@@ -475,9 +560,9 @@
s_t = cb->args[0];
if (s_t == 0)
- s_t = cb->args[0] = DN_MIN_TABLE;
+ s_t = cb->args[0] = RT_MIN_TABLE;
- for(t = s_t; t < DN_NUM_TABLES; t++) {
+ for(t = s_t; t <= RT_TABLE_MAX; t++) {
if (t < s_t)
continue;
if (t > s_t)
@@ -494,6 +579,125 @@
return skb->len;
}
+static void fib_magic(int cmd, int type, __u16 dst, int dst_len, struct dn_ifaddr *ifa)
+{
+ struct dn_fib_table *tb;
+ struct {
+ struct nlmsghdr nlh;
+ struct rtmsg rtm;
+ } req;
+ struct dn_kern_rta rta;
+
+ memset(&req.rtm, 0, sizeof(req.rtm));
+ memset(&rta, 0, sizeof(rta));
+
+ if (type == RTN_UNICAST)
+ tb = dn_fib_get_table(RT_MIN_TABLE, 1);
+ else
+ tb = dn_fib_get_table(RT_TABLE_LOCAL, 1);
+
+ if (tb == NULL)
+ return;
+
+ req.nlh.nlmsg_len = sizeof(req);
+ req.nlh.nlmsg_type = cmd;
+ req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND;
+ req.nlh.nlmsg_pid = 0;
+ req.nlh.nlmsg_seq = 0;
+
+ req.rtm.rtm_dst_len = dst_len;
+ req.rtm.rtm_table = tb->n;
+ req.rtm.rtm_protocol = RTPROT_KERNEL;
+ req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST);
+ req.rtm.rtm_type = type;
+
+ rta.rta_dst = &dst;
+ rta.rta_prefsrc = &ifa->ifa_local;
+ rta.rta_oif = &ifa->ifa_dev->dev->ifindex;
+
+ if (cmd == RTM_NEWROUTE)
+ tb->insert(tb, &req.rtm, &rta, &req.nlh, NULL);
+ else
+ tb->delete(tb, &req.rtm, &rta, &req.nlh, NULL);
+}
+
+static void dn_fib_add_ifaddr(struct dn_ifaddr *ifa)
+{
+
+ fib_magic(RTM_NEWROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa);
+
+#if 0
+ if (!(dev->flags&IFF_UP))
+ return;
+ /* In the future, we will want to add default routes here */
+
+#endif
+}
+
+static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa)
+{
+ int found_it = 0;
+ struct net_device *dev;
+ struct dn_dev *dn_db;
+ struct dn_ifaddr *ifa2;
+
+ ASSERT_RTNL();
+
+ /* Scan device list */
+ read_lock(&dev_base_lock);
+ for(dev = dev_base; dev; dev = dev->next) {
+ dn_db = dev->dn_ptr;
+ if (dn_db == NULL)
+ continue;
+ for(ifa2 = dn_db->ifa_list; ifa2; ifa2 = ifa2->ifa_next) {
+ if (ifa2->ifa_local == ifa->ifa_local) {
+ found_it = 1;
+ break;
+ }
+ }
+ }
+ read_unlock(&dev_base_lock);
+
+ if (found_it == 0) {
+ fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa);
+
+ if (dnet_addr_type(ifa->ifa_local) != RTN_LOCAL) {
+ if (dn_fib_sync_down(ifa->ifa_local, NULL, 0))
+ dn_fib_flush();
+ }
+ }
+}
+
+static void dn_fib_disable_addr(struct net_device *dev, int force)
+{
+ if (dn_fib_sync_down(0, dev, force))
+ dn_fib_flush();
+ dn_rt_cache_flush(0);
+ neigh_ifdown(&dn_neigh_table, dev);
+}
+
+static int dn_fib_dnaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct dn_ifaddr *ifa = (struct dn_ifaddr *)ptr;
+
+ switch(event) {
+ case NETDEV_UP:
+ dn_fib_add_ifaddr(ifa);
+ dn_fib_sync_up(ifa->ifa_dev->dev);
+ dn_rt_cache_flush(-1);
+ break;
+ case NETDEV_DOWN:
+ dn_fib_del_ifaddr(ifa);
+ if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {
+ dn_fib_disable_addr(ifa->ifa_dev->dev, 1);
+ } else {
+ dn_rt_cache_flush(-1);
+ }
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
int dn_fib_sync_down(dn_address local, struct net_device *dev, int force)
{
int ret = 0;
@@ -520,9 +724,11 @@
dead++;
else if (nh->nh_dev == dev &&
nh->nh_scope != scope) {
+ spin_lock_bh(&dn_fib_multipath_lock);
nh->nh_flags |= RTNH_F_DEAD;
fi->fib_power -= nh->nh_power;
nh->nh_power = 0;
+ spin_unlock_bh(&dn_fib_multipath_lock);
dead++;
}
} endfor_nexthops(fi)
@@ -556,11 +762,13 @@
if (nh->nh_dev != dev || dev->dn_ptr == NULL)
continue;
alive++;
+ spin_lock_bh(&dn_fib_multipath_lock);
nh->nh_power = 0;
nh->nh_flags &= ~RTNH_F_DEAD;
+ spin_unlock_bh(&dn_fib_multipath_lock);
} endfor_nexthops(fi);
- if (alive == fi->fib_nhs) {
+ if (alive > 0) {
fi->fib_flags &= ~RTNH_F_DEAD;
ret++;
}
@@ -574,7 +782,7 @@
struct dn_fib_table *tb;
int id;
- for(id = DN_NUM_TABLES; id > 0; id--) {
+ for(id = RT_TABLE_MAX; id > 0; id--) {
if ((tb = dn_fib_get_table(id, 0)) == NULL)
continue;
flushed += tb->flush(tb);
@@ -584,21 +792,6 @@
dn_rt_cache_flush(-1);
}
-int dn_fib_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
-
- switch(cmd) {
- case SIOCADDRT:
- case SIOCDELRT:
- return 0;
- }
-
- return -EINVAL;
-}
-
#ifdef CONFIG_PROC_FS
static int decnet_rt_get_info(char *buffer, char **start, off_t offset, int length)
@@ -620,7 +813,7 @@
}
- for(i = DN_MIN_TABLE; (i <= DN_NUM_TABLES) && (count > 0); i++) {
+ for(i = RT_MIN_TABLE; (i <= RT_TABLE_MAX) && (count > 0); i++) {
if ((tb = dn_fib_get_table(i, 0)) != NULL) {
int n = tb->get_info(tb, ptr, first, count);
count -= n;
@@ -638,12 +831,18 @@
}
#endif /* CONFIG_PROC_FS */
+static struct notifier_block dn_fib_dnaddr_notifier = {
+ .notifier_call = dn_fib_dnaddr_event,
+};
+
void __exit dn_fib_cleanup(void)
{
proc_net_remove("decnet_route");
dn_fib_table_cleanup();
dn_fib_rules_cleanup();
+
+ unregister_dnaddr_notifier(&dn_fib_dnaddr_notifier);
}
@@ -656,6 +855,8 @@
dn_fib_table_init();
dn_fib_rules_init();
+
+ register_dnaddr_notifier(&dn_fib_dnaddr_notifier);
}
diff -Nru linux-2.5.67/net/decnet/dn_neigh.c linux/net/decnet/dn_neigh.c
--- linux-2.5.67/net/decnet/dn_neigh.c Wed Jan 1 19:22:30 2003
+++ linux/net/decnet/dn_neigh.c Tue Apr 8 08:44:19 2003
@@ -20,6 +20,7 @@
* Steve Whitehouse : Fixed neighbour states (for now anyway).
* Steve Whitehouse : Made error_report functions dummies. This
* is not the right place to return skbs.
+ * Steve Whitehouse : Convert to seq_file
*
*/
@@ -33,9 +34,11 @@
#include <linux/string.h>
#include <linux/netfilter_decnet.h>
#include <linux/spinlock.h>
+#include <linux/seq_file.h>
#include <asm/atomic.h>
#include <net/neighbour.h>
#include <net/dst.h>
+#include <net/flow.h>
#include <net/dn.h>
#include <net/dn_dev.h>
#include <net/dn_neigh.h>
@@ -160,7 +163,20 @@
return -EINVAL;
}
- dn->blksize = 230;
+ /*
+ * Make an estimate of the remote block size by assuming that its
+ * two less then the device mtu, which it true for ethernet (and
+ * other things which support long format headers) since there is
+ * an extra length field (of 16 bits) which isn't part of the
+ * ethernet headers and which the DECnet specs won't admit is part
+ * of the DECnet routing headers either.
+ *
+ * If we over estimate here its no big deal, the NSP negotiations
+ * will prevent us from sending packets which are too large for the
+ * remote node to handle. In any case this figure is normally updated
+ * by a hello message in most cases.
+ */
+ dn->blksize = dev->mtu - 2;
return 0;
}
@@ -330,7 +346,7 @@
* basically does a neigh_lookup(), but without comparing the device
* field. This is required for the On-Ethernet cache
*/
-struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, void *ptr)
+struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, const void *ptr)
{
struct neighbour *neigh;
u32 hash_val;
@@ -466,8 +482,6 @@
return 0;
}
-
-#ifdef CONFIG_DECNET_ROUTER
static char *dn_find_slot(char *base, int max, int priority)
{
int i;
@@ -526,78 +540,200 @@
return t;
}
-#endif /* CONFIG_DECNET_ROUTER */
-
#ifdef CONFIG_PROC_FS
-static int dn_neigh_get_info(char *buffer, char **start, off_t offset, int length)
+
+struct dn_neigh_iter_state {
+ int bucket;
+};
+
+static struct neighbour *neigh_get_first(struct seq_file *seq)
{
- int len = 0;
- off_t pos = 0;
- off_t begin = 0;
- struct neighbour *n;
- int i;
- char buf[DN_ASCBUF_LEN];
+ struct dn_neigh_iter_state *state = seq->private;
+ struct neighbour *n = NULL;
+
+ for(state->bucket = 0;
+ state->bucket <= NEIGH_HASHMASK;
+ ++state->bucket) {
+ n = dn_neigh_table.hash_buckets[state->bucket];
+ if (n)
+ break;
+ }
- len += sprintf(buffer + len, "Addr Flags State Use Blksize Dev\n");
+ return n;
+}
- for(i=0;i <= NEIGH_HASHMASK; i++) {
- read_lock_bh(&dn_neigh_table.lock);
- n = dn_neigh_table.hash_buckets[i];
- for(; n != NULL; n = n->next) {
- struct dn_neigh *dn = (struct dn_neigh *)n;
-
- read_lock(&n->lock);
- len += sprintf(buffer+len, "%-7s %s%s%s %02x %02d %07ld %-8s\n",
- dn_addr2asc(dn_ntohs(dn->addr), buf),
- (dn->flags&DN_NDFLAG_R1) ? "1" : "-",
- (dn->flags&DN_NDFLAG_R2) ? "2" : "-",
- (dn->flags&DN_NDFLAG_P3) ? "3" : "-",
- dn->n.nud_state,
- atomic_read(&dn->n.refcnt),
- dn->blksize,
- (dn->n.dev) ? dn->n.dev->name : "?");
- read_unlock(&n->lock);
-
- pos = begin + len;
-
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
-
- if (pos > offset + length) {
- read_unlock_bh(&dn_neigh_table.lock);
- goto done;
- }
- }
+static struct neighbour *neigh_get_next(struct seq_file *seq,
+ struct neighbour *n)
+{
+ struct dn_neigh_iter_state *state = seq->private;
+
+ n = n->next;
+try_again:
+ if (n)
+ goto out;
+ if (++state->bucket > NEIGH_HASHMASK)
+ goto out;
+ n = dn_neigh_table.hash_buckets[state->bucket];
+ goto try_again;
+out:
+ return n;
+}
+
+static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
+{
+ struct neighbour *n = neigh_get_first(seq);
+
+ if (n)
+ while(*pos && (n = neigh_get_next(seq, n)))
+ --*pos;
+ return *pos ? NULL : n;
+}
+
+static void *dn_neigh_get_idx(struct seq_file *seq, loff_t pos)
+{
+ void *rc;
+ read_lock_bh(&dn_neigh_table.lock);
+ rc = neigh_get_idx(seq, &pos);
+ if (!rc) {
read_unlock_bh(&dn_neigh_table.lock);
}
+ return rc;
+}
-done:
+static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ return *pos ? dn_neigh_get_idx(seq, *pos - 1) : (void*)1;
+}
+
+static void *dn_neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ void *rc;
- *start = buffer + (offset - begin);
- len -= offset - begin;
- if (len > length) len = length;
+ if (v == (void*)1) {
+ rc = dn_neigh_get_idx(seq, 0);
+ goto out;
+ }
- return len;
+ rc = neigh_get_next(seq, v);
+ if (rc)
+ goto out;
+ read_unlock_bh(&dn_neigh_table.lock);
+out:
+ ++*pos;
+ return rc;
+}
+
+static void dn_neigh_seq_stop(struct seq_file *seq, void *v)
+{
+ if (v && v != (void*)1)
+ read_unlock_bh(&dn_neigh_table.lock);
}
+static inline void dn_neigh_format_entry(struct seq_file *seq,
+ struct neighbour *n)
+{
+ struct dn_neigh *dn = (struct dn_neigh *)n;
+ char buf[DN_ASCBUF_LEN];
+
+ read_lock(&n->lock);
+ seq_printf(seq, "%-7s %s%s%s %02x %02d %07ld %-8s\n",
+ dn_addr2asc(dn_ntohs(dn->addr), buf),
+ (dn->flags&DN_NDFLAG_R1) ? "1" : "-",
+ (dn->flags&DN_NDFLAG_R2) ? "2" : "-",
+ (dn->flags&DN_NDFLAG_P3) ? "3" : "-",
+ dn->n.nud_state,
+ atomic_read(&dn->n.refcnt),
+ dn->blksize,
+ (dn->n.dev) ? dn->n.dev->name : "?");
+ read_unlock(&n->lock);
+}
+
+static int dn_neigh_seq_show(struct seq_file *seq, void *v)
+{
+ if (v == (void*)1) {
+ seq_puts(seq, "Addr Flags State Use Blksize Dev\n");
+ } else {
+ dn_neigh_format_entry(seq, v);
+ }
+
+ return 0;
+}
+
+static struct seq_operations dn_neigh_seq_ops = {
+ .start = dn_neigh_seq_start,
+ .next = dn_neigh_seq_next,
+ .stop = dn_neigh_seq_stop,
+ .show = dn_neigh_seq_show,
+};
+
+static int dn_neigh_seq_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ int rc = -ENOMEM;
+ struct dn_neigh_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+ if (!s)
+ goto out;
+
+ rc = seq_open(file, &dn_neigh_seq_ops);
+ if (rc)
+ goto out_kfree;
+
+ seq = file->private_data;
+ seq->private = s;
+ memset(s, 0, sizeof(*s));
+out:
+ return rc;
+out_kfree:
+ kfree(s);
+ goto out;
+}
+
+static int dn_seq_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = (struct seq_file *)file->private_data;
+
+ kfree(seq->private);
+ seq->private = NULL;
+ return seq_release(inode, file);
+}
+
+static struct file_operations dn_neigh_seq_fops = {
+ .open = dn_neigh_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = dn_seq_release,
+};
+
+static int __init dn_neigh_proc_init(void)
+{
+ int rc = 0;
+ struct proc_dir_entry *p = create_proc_entry("decnet_neigh", S_IRUGO, proc_net);
+ if (p)
+ p->proc_fops = &dn_neigh_seq_fops;
+ else
+ rc = -ENOMEM;
+ return rc;
+}
+
+#else
+static int __init dn_neigh_proc_init(void)
+{
+ return 0;
+}
#endif
void __init dn_neigh_init(void)
{
neigh_table_init(&dn_neigh_table);
-#ifdef CONFIG_PROC_FS
- proc_net_create("decnet_neigh",0,dn_neigh_get_info);
-#endif /* CONFIG_PROC_FS */
+ dn_neigh_proc_init();
}
void __exit dn_neigh_cleanup(void)
{
- proc_net_remove("decnet_neigh");
neigh_table_clear(&dn_neigh_table);
}
diff -Nru linux-2.5.67/net/decnet/dn_nsp_in.c linux/net/decnet/dn_nsp_in.c
--- linux-2.5.67/net/decnet/dn_nsp_in.c Fri Mar 21 17:43:44 2003
+++ linux/net/decnet/dn_nsp_in.c Fri Mar 21 17:43:27 2003
@@ -434,7 +434,15 @@
sk->state_change(sk);
}
- dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
+ /*
+ * It appears that its possible for remote machines to send disc
+ * init messages with no port identifier if we are in the CI and
+ * possibly also the CD state. Obviously we shouldn't reply with
+ * a message if we don't know what the end point is.
+ */
+ if (scp->addrrem) {
+ dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
+ }
scp->persist_fxn = dn_destroy_timer;
scp->persist = dn_nsp_persist(sk);
diff -Nru linux-2.5.67/net/decnet/dn_nsp_out.c linux/net/decnet/dn_nsp_out.c
--- linux-2.5.67/net/decnet/dn_nsp_out.c Tue Feb 25 05:12:25 2003
+++ linux/net/decnet/dn_nsp_out.c Tue Apr 1 14:09:26 2003
@@ -21,6 +21,7 @@
* Paul Koning: Connect Confirm message fix.
* Eduardo Serrat: Fix to stop dn_nsp_do_disc() sending malformed packets.
* Steve Whitehouse: dn_nsp_output() and friends needed a spring clean
+ * Steve Whitehouse: Moved dn_nsp_send() in here from route.h
*/
/******************************************************************************
@@ -63,6 +64,7 @@
#include <linux/if_packet.h>
#include <net/neighbour.h>
#include <net/dst.h>
+#include <net/flow.h>
#include <net/dn.h>
#include <net/dn_nsp.h>
#include <net/dn_dev.h>
@@ -71,6 +73,41 @@
static int nsp_backoff[NSP_MAXRXTSHIFT + 1] = { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
+static void dn_nsp_send(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+ struct dn_scp *scp = DN_SK(sk);
+ struct dst_entry *dst;
+ struct flowi fl;
+
+ skb->h.raw = skb->data;
+ scp->stamp = jiffies;
+
+ dst = sk_dst_check(sk, 0);
+ if (dst) {
+try_again:
+ skb->dst = dst;
+ dst_output(skb);
+ return;
+ }
+
+ memset(&fl, 0, sizeof(fl));
+ fl.oif = sk->bound_dev_if;
+ fl.fld_src = dn_saddr2dn(&scp->addr);
+ fl.fld_dst = dn_saddr2dn(&scp->peer);
+ dn_sk_ports_copy(&fl, scp);
+ if (dn_route_output_sock(&sk->dst_cache, &fl, sk, 0) == 0) {
+ dst = sk_dst_get(sk);
+ sk->route_caps = dst->dev->features;
+ goto try_again;
+ }
+
+ sk->err = EHOSTUNREACH;
+ if (!test_bit(SOCK_DEAD, &sk->flags))
+ sk->state_change(sk);
+}
+
+
/*
* If sk == NULL, then we assume that we are supposed to be making
* a routing layer skb. If sk != NULL, then we are supposed to be
@@ -356,12 +393,33 @@
return ptr;
}
+static unsigned short *dn_nsp_mk_data_header(struct sock *sk, struct sk_buff *skb, int oth)
+{
+ struct dn_scp *scp = DN_SK(sk);
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
+ unsigned short *ptr = dn_mk_ack_header(sk, skb, cb->nsp_flags, 11, oth);
+
+ if (unlikely(oth)) {
+ cb->segnum = scp->numoth;
+ seq_add(&scp->numoth, 1);
+ } else {
+ cb->segnum = scp->numdat;
+ seq_add(&scp->numdat, 1);
+ }
+ *(ptr++) = dn_htons(cb->segnum);
+
+ return ptr;
+}
+
void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, int gfp, int oth)
{
struct dn_scp *scp = DN_SK(sk);
struct dn_skb_cb *cb = DN_SKB_CB(skb);
unsigned long t = ((scp->nsp_srtt >> 2) + scp->nsp_rttvar) >> 1;
+ cb->xmit_count = 0;
+ dn_nsp_mk_data_header(sk, skb, oth);
+
/*
* Slow start: If we have been idle for more than
* one RTT, then reset window to min size.
@@ -369,10 +427,6 @@
if ((jiffies - scp->stamp) > t)
scp->snd_window = NSP_MIN_WINDOW;
- /* printk(KERN_DEBUG "Window: %lu\n", scp->snd_window); */
-
- cb->xmit_count = 0;
-
if (oth)
skb_queue_tail(&scp->other_xmit_queue, skb);
else
@@ -630,19 +684,15 @@
{
struct dn_scp *scp = DN_SK(sk);
struct sk_buff *skb;
- unsigned short *segnum;
unsigned char *ptr;
int gfp = GFP_ATOMIC;
- if ((skb = dn_alloc_skb(sk, 13, gfp)) == NULL)
+ if ((skb = dn_alloc_skb(sk, DN_MAX_NSP_DATA_HEADER + 2, gfp)) == NULL)
return;
- skb_reserve(skb, 13);
- segnum = dn_mk_ack_header(sk, skb, 0x10, 13, 1);
- *segnum = dn_htons(scp->numoth);
- DN_SKB_CB(skb)->segnum = scp->numoth;
- seq_add(&scp->numoth, 1);
- ptr = (unsigned char *)(segnum + 1);
+ skb_reserve(skb, DN_MAX_NSP_DATA_HEADER);
+ ptr = skb_put(skb, 2);
+ DN_SKB_CB(skb)->nsp_flags = 0x10;
*ptr++ = lsflags;
*ptr = fcval;
diff -Nru linux-2.5.67/net/decnet/dn_route.c linux/net/decnet/dn_route.c
--- linux-2.5.67/net/decnet/dn_route.c Tue Feb 25 05:12:25 2003
+++ linux/net/decnet/dn_route.c Thu Apr 17 09:12:07 2003
@@ -37,7 +37,8 @@
* backlog congestion level return codes.
* Steve Whitehouse : Fixed bug where routes were set up with
* no ref count on net devices.
- *
+ * Steve Whitehouse : RCU for the route cache
+ * Steve Whitehouse : Preparations for the flow cache
*/
/******************************************************************************
@@ -65,17 +66,19 @@
#include <linux/netdevice.h>
#include <linux/inet.h>
#include <linux/route.h>
+#include <linux/in_route.h>
#include <net/sock.h>
-#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/rtnetlink.h>
#include <linux/string.h>
#include <linux/netfilter_decnet.h>
+#include <linux/rcupdate.h>
#include <asm/errno.h>
#include <net/neighbour.h>
#include <net/dst.h>
+#include <net/flow.h>
#include <net/dn.h>
#include <net/dn_dev.h>
#include <net/dn_nsp.h>
@@ -86,7 +89,7 @@
struct dn_rt_hash_bucket
{
struct dn_route *chain;
- rwlock_t lock;
+ spinlock_t lock;
} __attribute__((__aligned__(8)));
extern struct neigh_table dn_neigh_table;
@@ -134,6 +137,18 @@
return dn_rt_hash_mask & (unsigned)tmp;
}
+static inline void dnrt_free(struct dn_route *rt)
+{
+ call_rcu(&rt->u.dst.rcu_head, (void (*)(void *))dst_free, &rt->u.dst);
+}
+
+static inline void dnrt_drop(struct dn_route *rt)
+{
+ if (rt)
+ dst_release(&rt->u.dst);
+ call_rcu(&rt->u.dst.rcu_head, (void (*)(void *))dst_free, &rt->u.dst);
+}
+
static void SMP_TIMER_NAME(dn_dst_check_expire)(unsigned long dummy)
{
int i;
@@ -144,7 +159,7 @@
for(i = 0; i <= dn_rt_hash_mask; i++) {
rtp = &dn_rt_hash_table[i].chain;
- write_lock(&dn_rt_hash_table[i].lock);
+ spin_lock(&dn_rt_h...
[truncated message content] |
|
From: David S. M. <da...@re...> - 2003-04-18 08:37:44
|
Stephen, I would apply this but there is a huge error you must
correct first.
try_module_get(THIS_MODULE) has zero meaning, it is bug anytime
it is coded. In fact I may ask Rusty to BUG() check for this.
Consider the case that the module count is currently zero and
on another cpu we are currently unloading the decnet module.
This will explode, in short order.
I know you want to get rid of the MOD_{INC,DEC}_USE_COUNT deprecation
warnings, however don't do so by introducing new bugs.
How to fix this properly? Good question :-) Arnaldo de Melo is
working on adding a struct module pointer to proto_ops so that this
can be handled cleanly, ie. sock_create() does a try_module_get()
on proto_ops->owner before calling into the AF specific code.
So until Arnaldo puts that infrastructure in, please just delete
the MOD_{INC,DEC}_USE_COUNT bits from your patch and I'll apply
it to 2.5.x ok?
Thanks.
|
|
From: Steven W. <st...@gw...> - 2003-04-17 22:30:10
|
Hi,
Here is a patch with some of the fixes from the 2.5 DECnet stack, but none
of the new features. There are other things which need fixing too, but this
will deal with several issues and is relatively straight forward so I'm
hoping to submit this sooner rather than later and follow up with further
patches as time permits,
Steve.
------------------------------------------------------------------------------
diff -Nru linux-2.4.21-pre7/include/net/dn_fib.h linux/include/net/dn_fib.h
--- linux-2.4.21-pre7/include/net/dn_fib.h Fri Dec 21 09:42:04 2001
+++ linux/include/net/dn_fib.h Thu Apr 17 15:16:03 2003
@@ -126,8 +126,6 @@
extern void dn_fib_cleanup(void);
extern int dn_fib_rt_message(struct sk_buff *skb);
-extern int dn_fib_ioctl(struct socket *sock, unsigned int cmd,
- unsigned long arg);
extern struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r,
struct dn_kern_rta *rta,
const struct nlmsghdr *nlh, int *errp);
diff -Nru linux-2.4.21-pre7/include/net/dn_nsp.h linux/include/net/dn_nsp.h
--- linux-2.4.21-pre7/include/net/dn_nsp.h Mon Jan 22 13:32:10 2001
+++ linux/include/net/dn_nsp.h Thu Apr 17 14:11:11 2003
@@ -204,4 +204,6 @@
return atomic_read(&sk->rmem_alloc) > (sk->rcvbuf >> 1);
}
+#define DN_MAX_NSP_DATA_HEADER (11)
+
#endif /* _NET_DN_NSP_H */
diff -Nru linux-2.4.21-pre7/net/decnet/TODO linux/net/decnet/TODO
--- linux-2.4.21-pre7/net/decnet/TODO Mon Jan 22 13:32:10 2001
+++ linux/net/decnet/TODO Thu Apr 17 14:15:23 2003
@@ -1,17 +1,10 @@
Steve's quick list of things that need finishing off:
-[they are in no particular order and range from the trivial to the long winded]
+[they are in no particular order and range from the trivial to the long winded.
+I've also removed things which are 2.5 projects]
o Proper timeouts on each neighbour (in routing mode) rather than
just the 60 second On-Ethernet cache value.
- o Support for X.25 linklayer
-
- o Support for DDCMP link layer
-
- o The DDCMP device itself
-
- o PPP support (rfc1762)
-
o Lots of testing with real applications
o Verify errors etc. against POSIX 1003.1g (draft)
@@ -21,8 +14,6 @@
send/recvmsg() calls should simply be a vector of set/getsockopt()
calls]
- o check MSG_CTRUNC is set where it should be.
-
o Start to hack together user level software and add more DECnet support
in ifconfig for example.
@@ -30,28 +21,13 @@
o Test route lookup
- o Test /proc/net/decnet_route route listing works correctly (maybe I'll
- change the format of this file... atm its very similar to the IPv4 route
- 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]
-
- 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]
-
- o Add perfect socket hashing - an idea suggested by Paul Koning [part written,
- awaiting debugging and merge]
-
o Add session control message flow control
o Add NSP message flow control
- o DECnet sendpages() function
+ o Back port some of the fixes & features from DECnet in 2.5 as they become
+ stable and well tested
diff -Nru linux-2.4.21-pre7/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c
--- linux-2.4.21-pre7/net/decnet/af_decnet.c Thu Nov 28 15:53:15 2002
+++ linux/net/decnet/af_decnet.c Thu Apr 17 14:16:58 2003
@@ -479,7 +479,7 @@
if (sock) {
sock->ops = &dn_proto_ops;
}
- sock_init_data(sock,sk);
+ sock_init_data(sock, sk);
scp = DN_SK(sk);
sk->backlog_rcv = dn_nsp_backlog_rcv;
@@ -1198,12 +1198,6 @@
release_sock(sk);
return val;
-#ifdef CONFIG_DECNET_ROUTER
- case SIOCADDRT:
- case SIOCDELRT:
- return dn_fib_ioctl(sock, cmd, arg);
-#endif /* CONFIG_DECNET_ROUTER */
-
case OSIOCSNETADDR:
if (!capable(CAP_NET_ADMIN)) {
err = -EPERM;
@@ -1222,10 +1216,6 @@
case OSIOCGNETADDR:
err = put_user(decnet_address, (unsigned short *)arg);
break;
- case SIOCGIFCONF:
- case SIOCGIFFLAGS:
- case SIOCGIFBRDADDR:
- return dev_ioctl(cmd,(void *)arg);
case TIOCOUTQ:
amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
@@ -1250,6 +1240,10 @@
release_sock(sk);
err = put_user(amount, (int *)arg);
break;
+
+ default:
+ err = dev_ioctl(cmd, (void *)arg);
+ break;
}
return err;
@@ -1897,7 +1891,7 @@
int len;
unsigned char fctype;
- if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR))
+ if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR|MSG_MORE))
return -EOPNOTSUPP;
if (addr_len && (addr_len != sizeof(struct sockaddr_dn)))
@@ -2216,10 +2210,8 @@
sendpage: sock_no_sendpage,
};
-#ifdef CONFIG_SYSCTL
void dn_register_sysctl(void);
void dn_unregister_sysctl(void);
-#endif
#ifdef MODULE
@@ -2269,9 +2261,7 @@
dn_fib_init();
#endif /* CONFIG_DECNET_ROUTER */
-#ifdef CONFIG_SYSCTL
dn_register_sysctl();
-#endif /* CONFIG_SYSCTL */
/*
* Prevent DECnet module unloading until its fixed properly.
@@ -2304,9 +2294,7 @@
sock_unregister(AF_DECnet);
dev_remove_pack(&dn_dix_packet_type);
-#ifdef CONFIG_SYSCTL
dn_unregister_sysctl();
-#endif /* CONFIG_SYSCTL */
unregister_netdevice_notifier(&dn_dev_notifier);
diff -Nru linux-2.4.21-pre7/net/decnet/dn_dev.c linux/net/decnet/dn_dev.c
--- linux-2.4.21-pre7/net/decnet/dn_dev.c Fri Dec 21 09:42:05 2001
+++ linux/net/decnet/dn_dev.c Thu Apr 17 14:19:30 2003
@@ -693,8 +693,6 @@
}
-#ifdef CONFIG_DECNET_ROUTER
-
#define DRDELAY (5 * HZ)
static int dn_am_i_a_router(struct dn_neigh *dn, struct dn_dev *dn_db)
@@ -800,12 +798,6 @@
else
dn_send_router_hello(dev);
}
-#else
-static void dn_send_brd_hello(struct net_device *dev)
-{
- dn_send_endnode_hello(dev);
-}
-#endif
#if 0
static void dn_send_ptp_hello(struct net_device *dev)
@@ -1034,19 +1026,22 @@
{
struct net_device *dev;
+ rtnl_lock();
for(dev = dev_base; dev; dev = dev->next)
dn_dev_down(dev);
-
+ rtnl_unlock();
}
void dn_dev_devices_on(void)
{
struct net_device *dev;
+ rtnl_lock();
for(dev = dev_base; dev; dev = dev->next) {
if (dev->flags & IFF_UP)
dn_dev_up(dev);
}
+ rtnl_unlock();
}
diff -Nru linux-2.4.21-pre7/net/decnet/dn_fib.c linux/net/decnet/dn_fib.c
--- linux-2.4.21-pre7/net/decnet/dn_fib.c Fri Dec 21 09:42:05 2001
+++ linux/net/decnet/dn_fib.c Thu Apr 17 15:21:37 2003
@@ -52,7 +52,7 @@
extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
-
+static spinlock_t dn_fib_multipath_lock = SPIN_LOCK_UNLOCKED;
static struct dn_fib_info *dn_fib_info_list;
static rwlock_t dn_fib_info_lock = RW_LOCK_UNLOCKED;
int dn_fib_info_cnt;
@@ -297,6 +297,13 @@
nh->nh_weight = 1;
}
+ if (r->rtm_type == RTN_NAT) {
+ if (rta->rta_gw == NULL || nhs != 1 || rta->rta_oif)
+ goto err_inval;
+ memcpy(&fi->fib_nh->nh_gw, rta->rta_gw, 2);
+ goto link_it;
+ }
+
if (dn_fib_props[r->rtm_type].error) {
if (rta->rta_gw || rta->rta_oif || rta->rta_mp)
goto err_inval;
@@ -328,7 +335,7 @@
if (fi->fib_prefsrc) {
if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL ||
memcmp(&fi->fib_prefsrc, rta->rta_dst, 2))
- if (dn_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
+ if (dnet_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
goto err_inval;
}
#endif
@@ -366,12 +373,53 @@
return NULL;
}
+int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct dn_fib_key *key, struct dn_fib_res *res)
+{
+ int err = dn_fib_props[type].error;
+
+ if (err == 0) {
+ if (fi->fib_flags & RTNH_F_DEAD)
+ return 1;
+
+ res->fi = fi;
+
+ switch(type) {
+ case RTN_NAT:
+ DN_FIB_RES_RESET(*res);
+ atomic_inc(&fi->fib_clntref);
+ return 0;
+ case RTN_UNICAST:
+ case RTN_LOCAL:
+ for_nexthops(fi) {
+ if (nh->nh_flags & RTNH_F_DEAD)
+ continue;
+ if (!key->oif || key->oif == nh->nh_oif)
+ break;
+ }
+ if (nhsel < fi->fib_nhs) {
+ res->nh_sel = nhsel;
+ atomic_inc(&fi->fib_clntref);
+ return 0;
+ }
+ endfor_nexthops(fi);
+ res->fi = NULL;
+ return 1;
+ default:
+ if (net_ratelimit())
+ printk("DECnet: impossible routing event : dn_fib_semantic_match type=%d\n", type);
+ res->fi = NULL;
+ return -EINVAL;
+ }
+ }
+ return err;
+}
void dn_fib_select_multipath(const struct dn_fib_key *key, struct dn_fib_res *res)
{
struct dn_fib_info *fi = res->fi;
int w;
+ spin_lock_bh(&dn_fib_multipath_lock);
if (fi->fib_power <= 0) {
int power = 0;
change_nexthops(fi) {
@@ -381,6 +429,11 @@
}
} endfor_nexthops(fi);
fi->fib_power = power;
+ if (power < 0) {
+ spin_unlock_bh(&dn_fib_multipath_lock);
+ res->nh_sel = 0;
+ return;
+ }
}
w = jiffies % fi->fib_power;
@@ -391,12 +444,13 @@
nh->nh_power--;
fi->fib_power--;
res->nh_sel = nhsel;
+ spin_unlock_bh(&dn_fib_multipath_lock);
return;
}
}
} endfor_nexthops(fi);
-
- printk(KERN_DEBUG "DECnet: BUG! dn_fib_select_multipath\n");
+ res->nh_sel = 0;
+ spin_unlock_bh(&dn_fib_multipath_lock);
}
@@ -477,7 +531,7 @@
if (s_t == 0)
s_t = cb->args[0] = DN_MIN_TABLE;
- for(t = s_t; t < DN_NUM_TABLES; t++) {
+ for(t = s_t; t <= RT_TABLE_MAX; t++) {
if (t < s_t)
continue;
if (t > s_t)
@@ -520,9 +574,11 @@
dead++;
else if (nh->nh_dev == dev &&
nh->nh_scope != scope) {
+ spin_lock_bh(&dn_fib_multipath_lock);
nh->nh_flags |= RTNH_F_DEAD;
fi->fib_power -= nh->nh_power;
nh->nh_power = 0;
+ spin_unlock_bh(&dn_fib_multipath_lock);
dead++;
}
} endfor_nexthops(fi)
@@ -556,11 +612,13 @@
if (nh->nh_dev != dev || dev->dn_ptr == NULL)
continue;
alive++;
+ spin_lock_bh(&dn_fib_multipath_lock);
nh->nh_power = 0;
nh->nh_flags &= ~RTNH_F_DEAD;
+ spin_unlock_bh(&dn_fib_multipath_lock);
} endfor_nexthops(fi);
- if (alive == fi->fib_nhs) {
+ if (alive > 0) {
fi->fib_flags &= ~RTNH_F_DEAD;
ret++;
}
@@ -584,20 +642,6 @@
dn_rt_cache_flush(-1);
}
-int dn_fib_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
-
- switch(cmd) {
- case SIOCADDRT:
- case SIOCDELRT:
- return 0;
- }
-
- return -EINVAL;
-}
#ifdef CONFIG_PROC_FS
@@ -620,7 +664,7 @@
}
- for(i = DN_MIN_TABLE; (i <= DN_NUM_TABLES) && (count > 0); i++) {
+ for(i = DN_MIN_TABLE; (i <= RT_TABLE_MAX) && (count > 0); i++) {
if ((tb = dn_fib_get_table(i, 0)) != NULL) {
int n = tb->get_info(tb, ptr, first, count);
count -= n;
diff -Nru linux-2.4.21-pre7/net/decnet/dn_neigh.c linux/net/decnet/dn_neigh.c
--- linux-2.4.21-pre7/net/decnet/dn_neigh.c Mon Jan 22 13:32:10 2001
+++ linux/net/decnet/dn_neigh.c Thu Apr 17 14:26:09 2003
@@ -464,7 +464,6 @@
}
-#ifdef CONFIG_DECNET_ROUTER
static char *dn_find_slot(char *base, int max, int priority)
{
int i;
@@ -523,8 +522,6 @@
return t;
}
-#endif /* CONFIG_DECNET_ROUTER */
-
#ifdef CONFIG_PROC_FS
diff -Nru linux-2.4.21-pre7/net/decnet/dn_nsp_in.c linux/net/decnet/dn_nsp_in.c
--- linux-2.4.21-pre7/net/decnet/dn_nsp_in.c Thu Apr 17 15:25:39 2003
+++ linux/net/decnet/dn_nsp_in.c Thu Apr 17 15:25:25 2003
@@ -433,7 +433,15 @@
sk->state_change(sk);
}
- dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
+ /*
+ * It appears that its possible for remote machines to send disc
+ * init messages with no port identifier if we are in the CI and
+ * possibly also the CD state. Obviously we shouldn't reply with
+ * a message if we don't know what the end point is.
+ */
+ if (scp->addrrem) {
+ dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
+ }
scp->persist_fxn = dn_destroy_timer;
scp->persist = dn_nsp_persist(sk);
diff -Nru linux-2.4.21-pre7/net/decnet/dn_nsp_out.c linux/net/decnet/dn_nsp_out.c
--- linux-2.4.21-pre7/net/decnet/dn_nsp_out.c Mon Jan 22 13:32:10 2001
+++ linux/net/decnet/dn_nsp_out.c Thu Apr 17 14:30:01 2003
@@ -369,8 +369,6 @@
if ((jiffies - scp->stamp) > t)
scp->snd_window = NSP_MIN_WINDOW;
- /* printk(KERN_DEBUG "Window: %lu\n", scp->snd_window); */
-
cb->xmit_count = 0;
if (oth)
diff -Nru linux-2.4.21-pre7/net/decnet/dn_route.c linux/net/decnet/dn_route.c
--- linux-2.4.21-pre7/net/decnet/dn_route.c Thu Nov 28 15:53:15 2002
+++ linux/net/decnet/dn_route.c Thu Apr 17 15:18:41 2003
@@ -65,8 +65,8 @@
#include <linux/netdevice.h>
#include <linux/inet.h>
#include <linux/route.h>
+#include <linux/in_route.h>
#include <net/sock.h>
-#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
@@ -641,7 +641,9 @@
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)
@@ -1035,20 +1037,24 @@
nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
r = NLMSG_DATA(nlh);
- nlh->nlmsg_flags = nowait ? NLM_F_MULTI : 0;
+ nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
r->rtm_family = AF_DECnet;
r->rtm_dst_len = 16;
- r->rtm_src_len = 16;
+ r->rtm_src_len = 0;
r->rtm_tos = 0;
- r->rtm_table = 0;
+ r->rtm_table = DN_MIN_TABLE;
r->rtm_type = 0;
r->rtm_flags = 0;
r->rtm_scope = RT_SCOPE_UNIVERSE;
r->rtm_protocol = RTPROT_UNSPEC;
RTA_PUT(skb, RTA_DST, 2, &rt->rt_daddr);
- RTA_PUT(skb, RTA_SRC, 2, &rt->rt_saddr);
+ if (rt->rt_saddr) {
+ r->rtm_src_len = 16;
+ RTA_PUT(skb, RTA_SRC, 2, &rt->rt_saddr);
+ }
if (rt->u.dst.dev)
RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->u.dst.dev->ifindex);
+ RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_saddr);
if (rt->u.dst.window)
RTA_PUT(skb, RTAX_WINDOW, sizeof(unsigned), &rt->u.dst.window);
if (rt->u.dst.rtt)
@@ -1110,12 +1116,12 @@
local_bh_enable();
memset(cb, 0, sizeof(struct dn_skb_cb));
rt = (struct dn_route *)skb->dst;
+ if (!err && rt->u.dst.error)
+ err = rt->u.dst.error;
} else {
err = dn_route_output((struct dst_entry **)&rt, dst, src, 0);
}
- if (!err && rt->u.dst.error)
- err = rt->u.dst.error;
if (skb->dev)
dev_put(skb->dev);
skb->dev = NULL;
diff -Nru linux-2.4.21-pre7/net/decnet/dn_rules.c linux/net/decnet/dn_rules.c
--- linux-2.4.21-pre7/net/decnet/dn_rules.c Fri Dec 21 09:42:05 2001
+++ linux/net/decnet/dn_rules.c Thu Apr 17 15:22:08 2003
@@ -26,6 +26,7 @@
#include <linux/netdevice.h>
#include <linux/timer.h>
#include <linux/spinlock.h>
+#include <linux/in_route.h>
#include <asm/atomic.h>
#include <asm/uaccess.h>
#include <net/neighbour.h>
@@ -48,6 +49,7 @@
dn_address r_srcmask;
dn_address r_dst;
dn_address r_dstmask;
+ dn_address r_srcmap;
u8 r_flags;
#ifdef CONFIG_DECNET_ROUTE_FWMARK
u32 r_fwmark;
@@ -60,7 +62,7 @@
static struct dn_fib_rule default_rule = {
r_clntref: ATOMIC_INIT(2),
r_preference: 0x7fff,
- r_table: DN_DEFAULT_TABLE,
+ r_table: RT_TABLE_MAIN,
r_action: RTN_UNICAST
};
@@ -150,6 +152,8 @@
memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 2);
if (rta[RTA_DST-1])
memcpy(&new_r->r_dst, RTA_DATA(rta[RTA_DST-1]), 2);
+ if (rta[RTA_GATEWAY-1])
+ memcpy(&new_r->r_srcmap, RTA_DATA(rta[RTA_GATEWAY-1]), 2);
new_r->r_src_len = rtm->rtm_src_len;
new_r->r_dst_len = rtm->rtm_dst_len;
new_r->r_srcmask = dnet_make_mask(rtm->rtm_src_len);
@@ -218,6 +222,7 @@
switch(r->r_action) {
case RTN_UNICAST:
+ case RTN_NAT:
policy = r;
break;
case RTN_UNREACHABLE:
@@ -330,6 +335,8 @@
RTA_PUT(skb, RTA_IIF, IFNAMSIZ, &r->r_ifname);
if (r->r_preference)
RTA_PUT(skb, RTA_PRIORITY, 4, &r->r_preference);
+ if (r->r_srcmap)
+ RTA_PUT(skb, RTA_GATEWAY, 2, &r->r_srcmap);
nlh->nlmsg_len = skb->tail - b;
return skb->len;
diff -Nru linux-2.4.21-pre7/net/decnet/dn_table.c linux/net/decnet/dn_table.c
--- linux-2.4.21-pre7/net/decnet/dn_table.c Fri Dec 21 09:42:05 2001
+++ linux/net/decnet/dn_table.c Thu Apr 17 14:42:07 2003
@@ -45,7 +45,7 @@
u32 dz_hashmask;
#define DZ_HASHMASK(dz) ((dz)->dz_hashmask)
int dz_order;
- u32 dz_mask;
+ u16 dz_mask;
#define DZ_MASK(dz) ((dz)->dz_mask)
};
@@ -75,17 +75,16 @@
static rwlock_t dn_fib_tables_lock = RW_LOCK_UNLOCKED;
-static struct dn_fib_table *dn_fib_tables[DN_NUM_TABLES + 1];
+static struct dn_fib_table *dn_fib_tables[RT_TABLE_MAX + 1];
static kmem_cache_t *dn_hash_kmem;
static int dn_fib_hash_zombies;
static __inline__ dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz)
{
- u32 h = ntohs(key.datum)>>(16 - dz->dz_order);
+ u16 h = ntohs(key.datum)>>(16 - dz->dz_order);
h ^= (h >> 10);
h ^= (h >> 6);
- h ^= (h >> 3);
h &= DZ_HASHMASK(dz);
return *(dn_fib_idx_t *)&h;
}
@@ -118,8 +117,8 @@
}
static __inline__ void dn_rebuild_zone(struct dn_zone *dz,
- struct dn_fib_node **old_ht,
- int old_divisor)
+ struct dn_fib_node **old_ht,
+ int old_divisor)
{
int i;
struct dn_fib_node *f, **fp, *next;
@@ -709,10 +708,12 @@
dn_fib_key_t k = dz_key(key->dst, dz);
for(f = dz_chain(k, dz); f; f = f->fn_next) {
- if (!dn_key_leq(k, f->fn_key))
- break;
- else
- continue;
+ if (!dn_key_eq(k, f->fn_key)) {
+ if (!dn_key_leq(k, f->fn_key))
+ break;
+ else
+ continue;
+ }
f->fn_state |= DN_S_ACCESSED;
@@ -826,7 +827,7 @@
if (n < DN_MIN_TABLE)
return NULL;
- if (n > DN_NUM_TABLES)
+ if (n > RT_TABLE_MAX)
return NULL;
if (dn_fib_tables[n])
@@ -840,7 +841,7 @@
from interrupt\n");
return NULL;
}
- if ((t = kmalloc(sizeof(struct dn_fib_table), GFP_KERNEL)) == NULL)
+ if ((t = kmalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash), GFP_KERNEL)) == NULL)
return NULL;
memset(t, 0, sizeof(struct dn_fib_table));
@@ -854,6 +855,7 @@
t->get_info = dn_fib_table_get_info;
#endif
t->dump = dn_fib_table_dump;
+ memset(t->data, 0, sizeof(struct dn_hash));
dn_fib_tables[n] = t;
return t;
|
|
From: Steven W. <st...@gw...> - 2003-04-17 18:08:36
|
Hi,
Here is the much promised patch for DECnet routing in 2.5. My initial tests
have all been positive although I do know there are a few more things left
to do. This makes a big improvement (I think :-) and I'd therefore like to
submit this to the 2.5 kernel now. Its pretty much as it was when you last saw
it except for a few minor changes (including the name changes in dn_fib.h).
Feature list:
o As requested, macros in dn_fib.h changed to decnet specific names
o Two bugs fixed (only in 2.5 decnet stack) relating to bind and connection
states.
o Numerous style changes: using C99 initialisers and inline rather
than __inline__
o Use struct flowi as routing key (for forthcoming flow cache)
o Add metrics to routing table
o Many routing table bug fixes
o New wait code to improve efficiency
o New module interface functions
o We use real device MTUs now rather than saying "hmm... looks like ethernet
must be 1500" as we used to (still one or two places to fix, but its
mostly correct in this patch)
o Tidy up in af_decnet.c:dn_sendmsg() in preparation for zerocopy
o Updates to rtnetlink code to return more information
o Removed ioctl() for decnet fib. It never did anything and rtnetlink is
a far better interface anyway.
o Converted /proc/decnet_neigh to seq_file (other /proc files to follow)
o DECnet route cache now uses RCU like the ipv4 route cache
o Misc bug fixes wherever I found them
o SO_BINDTODEVICE works for outgoing connections
Some notes to people using iproute2 and DECnet:
- If you list the addresses, don't be surprised to see that you get a
"peer" address appearing seemingly randomly. Just ignore it. Its down
to the iproute2 code comparing two addresses with a length of 4 bytes
where it should be using 2 bytes and I'll try and get it patched shortly,
its otherwise harmless.
- The kernel code supplies "cache info" for routing cache entries which
is never displayed. Again a patch to iproute2 will enable this
information but it makes no other difference to the operation.
Steve.
------------------------------------------------------------------------------
diff -Nru linux-2.5.67/include/net/dn.h linux/include/net/dn.h
--- linux-2.5.67/include/net/dn.h Wed Jan 1 19:21:08 2003
+++ linux/include/net/dn.h Tue Apr 1 16:56:58 2003
@@ -171,17 +171,17 @@
int iif;
};
-static __inline__ dn_address dn_eth2dn(unsigned char *ethaddr)
+static inline dn_address dn_eth2dn(unsigned char *ethaddr)
{
return ethaddr[4] | (ethaddr[5] << 8);
}
-static __inline__ dn_address dn_saddr2dn(struct sockaddr_dn *saddr)
+static inline dn_address dn_saddr2dn(struct sockaddr_dn *saddr)
{
return *(dn_address *)saddr->sdn_nodeaddr;
}
-static __inline__ void dn_dn2eth(unsigned char *ethaddr, dn_address addr)
+static inline void dn_dn2eth(unsigned char *ethaddr, dn_address addr)
{
ethaddr[0] = 0xAA;
ethaddr[1] = 0x00;
@@ -190,6 +190,19 @@
ethaddr[4] = (unsigned char)(addr & 0xff);
ethaddr[5] = (unsigned char)(addr >> 8);
}
+
+static inline void dn_sk_ports_copy(struct flowi *fl, struct dn_scp *scp)
+{
+ fl->uli_u.dnports.sport = scp->addrloc;
+ fl->uli_u.dnports.dport = scp->addrrem;
+ fl->uli_u.dnports.objnum = scp->addr.sdn_objnum;
+ if (fl->uli_u.dnports.objnum == 0) {
+ fl->uli_u.dnports.objnamel = scp->addr.sdn_objnamel;
+ memcpy(fl->uli_u.dnports.objname, scp->addr.sdn_objname, 16);
+ }
+}
+
+extern unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu);
#define DN_MENUVER_ACC 0x01
#define DN_MENUVER_USR 0x02
diff -Nru linux-2.5.67/include/net/dn_dev.h linux/include/net/dn_dev.h
--- linux-2.5.67/include/net/dn_dev.h Thu Mar 6 16:38:53 2003
+++ linux/include/net/dn_dev.h Thu Apr 3 20:28:46 2003
@@ -8,6 +8,7 @@
struct dn_ifaddr *ifa_next;
struct dn_dev *ifa_dev;
dn_address ifa_local;
+ dn_address ifa_address;
unsigned char ifa_flags;
unsigned char ifa_scope;
char ifa_label[IFNAMSIZ];
@@ -171,7 +172,10 @@
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)
+extern int register_dnaddr_notifier(struct notifier_block *nb);
+extern int unregister_dnaddr_notifier(struct notifier_block *nb);
+
+static inline int dn_dev_islocal(struct net_device *dev, dn_address addr)
{
struct dn_dev *dn_db = dev->dn_ptr;
struct dn_ifaddr *ifa;
diff -Nru linux-2.5.67/include/net/dn_fib.h linux/include/net/dn_fib.h
--- linux-2.5.67/include/net/dn_fib.h Wed Jan 1 19:22:03 2003
+++ linux/include/net/dn_fib.h Wed Apr 9 14:30:36 2003
@@ -1,12 +1,6 @@
#ifndef _NET_DN_FIB_H
#define _NET_DN_FIB_H
-#include <linux/config.h>
-
-#ifdef CONFIG_DECNET_ROUTER
-
-#include <linux/rtnetlink.h>
-
struct dn_kern_rta
{
void *rta_dst;
@@ -23,15 +17,6 @@
struct rta_cacheinfo *rta_ci;
};
-struct dn_fib_key {
- dn_address src;
- dn_address dst;
- int iif;
- int oif;
- u32 fwmark;
- unsigned char scope;
-};
-
struct dn_fib_res {
struct dn_fib_rule *r;
struct dn_fib_info *fi;
@@ -60,16 +45,23 @@
unsigned fib_flags;
int fib_protocol;
dn_address fib_prefsrc;
- u32 fib_priority;
+ __u32 fib_priority;
+ __u32 fib_metrics[RTAX_MAX];
+#define dn_fib_mtu fib_metrics[RTAX_MTU-1]
+#define dn_fib_window fib_metrics[RTAX_WINDOW-1]
+#define dn_fib_rtt fib_metrics[RTAX_RTT-1]
+#define dn_fib_advmss fib_metrics[RTAX_ADVMSS-1]
int fib_nhs;
int fib_power;
struct dn_fib_nh fib_nh[0];
-#define fib_dev fib_nh[0].nh_dev
+#define dn_fib_dev fib_nh[0].nh_dev
};
-#define DN_FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
#define DN_FIB_RES_RESET(res) ((res).nh_sel = 0)
+#define DN_FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
+
+#define DN_FIB_RES_PREFSRC(res) ((res).fi->fib_prefsrc ? : __dn_fib_res_prefsrc(&res))
#define DN_FIB_RES_GW(res) (DN_FIB_RES_NH(res).nh_gw)
#define DN_FIB_RES_DEV(res) (DN_FIB_RES_NH(res).nh_dev)
#define DN_FIB_RES_OIF(res) (DN_FIB_RES_NH(res).nh_oif)
@@ -106,7 +98,7 @@
int (*delete)(struct dn_fib_table *t, struct rtmsg *r,
struct dn_kern_rta *rta, struct nlmsghdr *n,
struct netlink_skb_parms *req);
- int (*lookup)(struct dn_fib_table *t, const struct dn_fib_key *key,
+ int (*lookup)(struct dn_fib_table *t, const struct flowi *fl,
struct dn_fib_res *res);
int (*flush)(struct dn_fib_table *t);
#ifdef CONFIG_PROC_FS
@@ -118,7 +110,7 @@
unsigned char data[0];
};
-
+#ifdef CONFIG_DECNET_ROUTER
/*
* dn_fib.c
*/
@@ -132,11 +124,12 @@
struct dn_kern_rta *rta,
const struct nlmsghdr *nlh, int *errp);
extern int dn_fib_semantic_match(int type, struct dn_fib_info *fi,
- const struct dn_fib_key *key, struct dn_fib_res *res);
+ const struct flowi *fl,
+ struct dn_fib_res *res);
extern void dn_fib_release_info(struct dn_fib_info *fi);
extern u16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type);
extern void dn_fib_flush(void);
-extern void dn_fib_select_multipath(const struct dn_fib_key *key,
+extern void dn_fib_select_multipath(const struct flowi *fl,
struct dn_fib_res *res);
extern int dn_fib_sync_down(dn_address local, struct net_device *dev,
int force);
@@ -156,7 +149,9 @@
extern void dn_fib_rules_init(void);
extern void dn_fib_rules_cleanup(void);
extern void dn_fib_rule_put(struct dn_fib_rule *);
-extern int dn_fib_lookup(struct dn_fib_key *key, struct dn_fib_res *res);
+extern __u16 dn_fib_rules_policy(__u16 saddr, struct dn_fib_res *res, unsigned *flags);
+extern unsigned dnet_addr_type(__u16 addr);
+extern int dn_fib_lookup(const struct flowi *fl, struct dn_fib_res *res);
/*
* rtnetlink interface
@@ -169,21 +164,15 @@
extern int dn_fib_rtm_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
extern int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb);
-#define DN_NUM_TABLES 255
-#define DN_MIN_TABLE 1
-#define DN_DEFAULT_TABLE 1
-#define DN_L1_TABLE 1
-#define DN_L2_TABLE 2
-
extern void dn_fib_free_info(struct dn_fib_info *fi);
-static __inline__ void dn_fib_info_put(struct dn_fib_info *fi)
+static inline void dn_fib_info_put(struct dn_fib_info *fi)
{
if (atomic_dec_and_test(&fi->fib_clntref))
dn_fib_free_info(fi);
}
-static __inline__ void dn_fib_res_put(struct dn_fib_res *res)
+static inline void dn_fib_res_put(struct dn_fib_res *res)
{
if (res->fi)
dn_fib_info_put(res->fi);
@@ -191,13 +180,23 @@
dn_fib_rule_put(res->r);
}
-static __inline__ u16 dnet_make_mask(int n)
+extern struct dn_fib_table *dn_fib_tables[];
+
+#else /* Endnode */
+
+#define dn_fib_lookup(fl, res) (-ESRCH)
+#define dn_fib_info_put(fi) do { } while(0)
+#define dn_fib_select_multipath(fl, res) do { } while(0)
+#define dn_fib_rules_policy(saddr,res,flags) (0)
+#define dn_fib_res_put(res) do { } while(0)
+
+#endif /* CONFIG_DECNET_ROUTER */
+
+static inline u16 dnet_make_mask(int n)
{
if (n)
return htons(~((1<<(16-n))-1));
return 0;
}
-
-#endif /* CONFIG_DECNET_ROUTER */
#endif /* _NET_DN_FIB_H */
diff -Nru linux-2.5.67/include/net/dn_neigh.h linux/include/net/dn_neigh.h
--- linux-2.5.67/include/net/dn_neigh.h Wed Jan 1 19:22:00 2003
+++ linux/include/net/dn_neigh.h Sun Mar 9 19:27:48 2003
@@ -18,7 +18,7 @@
extern void dn_neigh_init(void);
extern void dn_neigh_cleanup(void);
-extern struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, void *ptr);
+extern struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, const void *ptr);
extern int dn_neigh_router_hello(struct sk_buff *skb);
extern int dn_neigh_endnode_hello(struct sk_buff *skb);
extern void dn_neigh_pointopoint_hello(struct sk_buff *skb);
diff -Nru linux-2.5.67/include/net/dn_nsp.h linux/include/net/dn_nsp.h
--- linux-2.5.67/include/net/dn_nsp.h Wed Jan 1 19:22:43 2003
+++ linux/include/net/dn_nsp.h Tue Apr 1 11:23:50 2003
@@ -204,4 +204,6 @@
return atomic_read(&sk->rmem_alloc) > (sk->rcvbuf >> 1);
}
+#define DN_MAX_NSP_DATA_HEADER (11)
+
#endif /* _NET_DN_NSP_H */
diff -Nru linux-2.5.67/include/net/dn_route.h linux/include/net/dn_route.h
--- linux-2.5.67/include/net/dn_route.h Fri Mar 21 17:43:43 2003
+++ linux/include/net/dn_route.h Tue Apr 1 16:56:18 2003
@@ -16,7 +16,7 @@
*******************************************************************************/
extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, int pri);
-extern int dn_route_output(struct dst_entry **pprt, dn_address dst, dn_address src, int flags);
+extern int dn_route_output_sock(struct dst_entry **pprt, struct flowi *, struct sock *sk, int flags);
extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
extern int dn_cache_getroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
extern void dn_rt_cache_flush(int delay);
@@ -59,10 +59,10 @@
#define DN_RT_INFO_BLKR 0x40 /* Blocking Requested */
/*
- * The key structure is what we used to look up the route.
+ * The fl structure is what we used to look up the route.
* The rt_saddr & rt_daddr entries are the same as key.saddr & key.daddr
- * except for local input routes, where the rt_saddr = key.daddr and
- * rt_daddr = key.saddr to allow the route to be used for returning
+ * except for local input routes, where the rt_saddr = fl.fld_dst and
+ * rt_daddr = fl.fld_src to allow the route to be used for returning
* packets to the originating host.
*/
struct dn_route {
@@ -70,19 +70,18 @@
struct dst_entry dst;
struct dn_route *rt_next;
} u;
- struct {
- unsigned short saddr;
- unsigned short daddr;
- int iif;
- int oif;
- u32 fwmark;
- } key;
- unsigned short rt_saddr;
- unsigned short rt_daddr;
- unsigned char rt_type;
- unsigned char rt_scope;
- unsigned char rt_protocol;
- unsigned char rt_table;
+
+ __u16 rt_saddr;
+ __u16 rt_daddr;
+ __u16 rt_gateway;
+ __u16 __padding;
+ __u16 rt_src_map;
+ __u16 rt_dst_map;
+
+ unsigned rt_flags;
+ unsigned rt_type;
+
+ struct flowi fl;
};
extern void dn_route_init(void);
@@ -108,34 +107,6 @@
dn_rt_send(skb);
else
kfree_skb(skb);
-}
-
-static inline void dn_nsp_send(struct sk_buff *skb)
-{
- struct sock *sk = skb->sk;
- struct dn_scp *scp = DN_SK(sk);
- struct dst_entry *dst;
-
- skb->h.raw = skb->data;
- scp->stamp = jiffies;
-
- if ((dst = sk->dst_cache) && !dst->obsolete) {
-try_again:
- skb->dst = dst_clone(dst);
- dst_output(skb);
- return;
- }
-
- dst_release(xchg(&sk->dst_cache, NULL));
-
- if (dn_route_output(&sk->dst_cache, dn_saddr2dn(&scp->peer), dn_saddr2dn(&scp->addr), 0) == 0) {
- dst = sk->dst_cache;
- goto try_again;
- }
-
- sk->err = EHOSTUNREACH;
- if (!test_bit(SOCK_DEAD, &sk->flags))
- sk->state_change(sk);
}
#endif /* _NET_DN_ROUTE_H */
diff -Nru linux-2.5.67/include/net/flow.h linux/include/net/flow.h
--- linux-2.5.67/include/net/flow.h Wed Jan 1 19:23:03 2003
+++ linux/include/net/flow.h Tue Mar 25 14:48:50 2003
@@ -25,7 +25,18 @@
struct in6_addr * saddr;
__u32 flowlabel;
} ip6_u;
+
+ struct {
+ __u16 daddr;
+ __u16 saddr;
+ __u32 fwmark;
+ __u8 scope;
+ } dn_u;
} nl_u;
+#define fld_dst nl_u.dn_u.daddr
+#define fld_src nl_u.dn_u.saddr
+#define fld_fwmark nl_u.dn_u.fwmark
+#define fld_scope nl_u.dn_u.scope
#define fl6_dst nl_u.ip6_u.daddr
#define fl6_src nl_u.ip6_u.saddr
#define fl6_flowlabel nl_u.ip6_u.flowlabel
@@ -47,6 +58,14 @@
__u8 type;
__u8 code;
} icmpt;
+
+ struct {
+ __u16 sport;
+ __u16 dport;
+ __u8 objnum;
+ __u8 objnamel; /* Not 16 bits since max val is 16 */
+ __u8 objname[16]; /* Not zero terminated */
+ } dnports;
__u32 spi;
} uli_u;
diff -Nru linux-2.5.67/include/net/sock.h linux/include/net/sock.h
--- linux-2.5.67/include/net/sock.h Mon Apr 7 15:36:52 2003
+++ linux/include/net/sock.h Mon Apr 7 15:36:34 2003
@@ -868,6 +868,9 @@
* schedule();
* SOCK_SLEEP_POST(sk)
*
+ * N.B. These are now obsolete and were, afaik, only ever used in DECnet
+ * and when the last use of them in DECnet has gone, I'm intending to
+ * remove them.
*/
#define SOCK_SLEEP_PRE(sk) { struct task_struct *tsk = current; \
diff -Nru linux-2.5.67/net/decnet/TODO linux/net/decnet/TODO
--- linux-2.5.67/net/decnet/TODO Wed Jan 1 19:22:34 2003
+++ linux/net/decnet/TODO Thu Apr 3 21:54:00 2003
@@ -26,25 +26,16 @@
o Start to hack together user level software and add more DECnet support
in ifconfig for example.
- o Test adding/deleting of routes
-
- o Test route lookup
-
- o Test /proc/net/decnet_route route listing works correctly (maybe I'll
- change the format of this file... atm its very similar to the IPv4 route
- 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.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 Add the routing message grabbing netfilter module [written, tested,
awaiting merge]
- o Add perfect socket hashing - an idea suggested by Paul Koning [part written,
- awaiting debugging and merge]
+ o Add perfect socket hashing - an idea suggested by Paul Koning. Currently
+ we have a half-way house scheme which seems to work reasonably well, but
+ the full scheme is still worth implementing, its not not top of my list
+ right now.
o Add session control message flow control
@@ -53,4 +44,6 @@
o DECnet sendpages() function
o AIO for DECnet
+
+ o Eliminate dn_db->parms.blksize
diff -Nru linux-2.5.67/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c
--- linux-2.5.67/net/decnet/af_decnet.c Fri Mar 21 17:43:44 2003
+++ linux/net/decnet/af_decnet.c Wed Apr 9 06:15:21 2003
@@ -118,6 +118,7 @@
#include <linux/netfilter.h>
#include <net/sock.h>
#include <net/tcp.h>
+#include <net/flow.h>
#include <asm/system.h>
#include <asm/ioctls.h>
#include <linux/mm.h>
@@ -146,6 +147,7 @@
#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;
static rwlock_t dn_hash_lock = RW_LOCK_UNLOCKED;
@@ -273,7 +275,7 @@
if (hash == 0) {
hash = addr->sdn_objnamel;
- for(i = 0; i < addr->sdn_objnamel; i++) {
+ for(i = 0; i < dn_ntohs(addr->sdn_objnamel); i++) {
hash ^= addr->sdn_objname[i];
hash ^= (hash << 3);
}
@@ -468,7 +470,7 @@
dst_release(xchg(&sk->dst_cache, NULL));
- MOD_DEC_USE_COUNT;
+ module_put(THIS_MODULE);
}
struct sock *dn_alloc_sock(struct socket *sock, int gfp)
@@ -512,8 +514,7 @@
scp->services_loc = 1 | NSP_FC_NONE;
scp->info_rem = 0;
scp->info_loc = 0x03; /* NSP version 4.1 */
- scp->segsize_rem = 230; /* Default: Updated by remote segsize */
- scp->segsize_loc = 1450; /* Best guess for ethernet */
+ scp->segsize_rem = 230 - DN_MAX_NSP_DATA_HEADER; /* Default: Updated by remote segsize */
scp->nonagle = 0;
scp->multi_ireq = 1;
scp->accept_mode = ACC_IMMED;
@@ -543,7 +544,7 @@
dn_start_slow_timer(sk);
- MOD_INC_USE_COUNT;
+ try_module_get(THIS_MODULE);
return sk;
@@ -788,8 +789,8 @@
return -EINVAL;
#if 1
- if ((!capable(CAP_NET_BIND_SERVICE) && saddr->sdn_objnum) ||
- (saddr->sdn_flags & SDF_WILD))
+ if (!capable(CAP_NET_BIND_SERVICE) && (saddr->sdn_objnum ||
+ (saddr->sdn_flags & SDF_WILD)))
return -EACCES;
#else
/*
@@ -877,18 +878,18 @@
static int dn_confirm_accept(struct sock *sk, long *timeo, int allocation)
{
struct dn_scp *scp = DN_SK(sk);
- DECLARE_WAITQUEUE(wait, current);
+ DEFINE_WAIT(wait);
int err;
if (scp->state != DN_CR)
return -EINVAL;
scp->state = DN_CC;
+ scp->segsize_loc = dst_path_metric(__sk_dst_get(sk), RTAX_ADVMSS);
dn_send_conn_conf(sk, allocation);
- add_wait_queue(sk->sleep, &wait);
+ prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE);
for(;;) {
- set_current_state(TASK_INTERRUPTIBLE);
release_sock(sk);
if (scp->state == DN_CC)
*timeo = schedule_timeout(*timeo);
@@ -905,16 +906,21 @@
err = -EAGAIN;
if (!*timeo)
break;
+ prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE);
+ }
+ finish_wait(sk->sleep, &wait);
+ if (err == 0) {
+ sk->socket->state = SS_CONNECTED;
+ } else if (scp->state != DN_CC) {
+ sk->socket->state = SS_UNCONNECTED;
}
- remove_wait_queue(sk->sleep, &wait);
- current->state = TASK_RUNNING;
return err;
}
static int dn_wait_run(struct sock *sk, long *timeo)
{
struct dn_scp *scp = DN_SK(sk);
- DECLARE_WAITQUEUE(wait, current);
+ DEFINE_WAIT(wait);
int err = 0;
if (scp->state == DN_RUN)
@@ -923,9 +929,8 @@
if (!*timeo)
return -EALREADY;
- add_wait_queue(sk->sleep, &wait);
+ prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE);
for(;;) {
- set_current_state(TASK_INTERRUPTIBLE);
release_sock(sk);
if (scp->state == DN_CI || scp->state == DN_CC)
*timeo = schedule_timeout(*timeo);
@@ -942,12 +947,14 @@
err = -ETIMEDOUT;
if (!*timeo)
break;
+ prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE);
}
- remove_wait_queue(sk->sleep, &wait);
- current->state = TASK_RUNNING;
+ finish_wait(sk->sleep, &wait);
out:
if (err == 0) {
sk->socket->state = SS_CONNECTED;
+ } else if (scp->state != DN_CI && scp->state != DN_CC) {
+ sk->socket->state = SS_UNCONNECTED;
}
return err;
}
@@ -957,6 +964,7 @@
struct socket *sock = sk->socket;
struct dn_scp *scp = DN_SK(sk);
int err = -EISCONN;
+ struct flowi fl;
if (sock->state == SS_CONNECTED)
goto out;
@@ -995,12 +1003,17 @@
memcpy(&scp->peer, addr, sizeof(struct sockaddr_dn));
err = -EHOSTUNREACH;
- if (dn_route_output(&sk->dst_cache, dn_saddr2dn(&scp->peer),
- dn_saddr2dn(&scp->addr), flags & MSG_TRYHARD) < 0)
+ memset(&fl, 0, sizeof(fl));
+ fl.oif = sk->bound_dev_if;
+ fl.fld_dst = dn_saddr2dn(&scp->peer);
+ fl.fld_src = dn_saddr2dn(&scp->addr);
+ dn_sk_ports_copy(&fl, scp);
+ if (dn_route_output_sock(&sk->dst_cache, &fl, sk, flags) < 0)
goto out;
-
+ sk->route_caps = sk->dst_cache->dev->features;
sock->state = SS_CONNECTING;
scp->state = DN_CI;
+ scp->segsize_loc = dst_path_metric(sk->dst_cache, RTAX_ADVMSS);
dn_nsp_send_conninit(sk, NSP_CI);
err = -EINPROGRESS;
@@ -1077,13 +1090,12 @@
static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo)
{
- DECLARE_WAITQUEUE(wait, current);
+ DEFINE_WAIT(wait);
struct sk_buff *skb = NULL;
int err = 0;
- add_wait_queue_exclusive(sk->sleep, &wait);
+ prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE);
for(;;) {
- set_current_state(TASK_INTERRUPTIBLE);
release_sock(sk);
skb = skb_dequeue(&sk->receive_queue);
if (skb == NULL) {
@@ -1102,9 +1114,10 @@
err = -EAGAIN;
if (!*timeo)
break;
+ prepare_to_wait(sk->sleep, &wait, TASK_INTERRUPTIBLE);
}
- remove_wait_queue(sk->sleep, &wait);
- current->state = TASK_RUNNING;
+ finish_wait(sk->sleep, &wait);
+
return skb == NULL ? ERR_PTR(err) : skb;
}
@@ -1276,12 +1289,6 @@
release_sock(sk);
return val;
-#ifdef CONFIG_DECNET_ROUTER
- case SIOCADDRT:
- case SIOCDELRT:
- return dn_fib_ioctl(sock, cmd, arg);
-#endif /* CONFIG_DECNET_ROUTER */
-
case TIOCOUTQ:
amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
if (amount < 0)
@@ -1888,6 +1895,64 @@
return 0;
}
+/*
+ * The DECnet spec requires the the "routing layer" accepts packets which
+ * are at least 230 bytes in size. This excludes any headers which the NSP
+ * layer might add, so we always assume that we'll be using the maximal
+ * length header on data packets. The variation in length is due to the
+ * inclusion (or not) of the two 16 bit acknowledgement fields so it doesn't
+ * make much practical difference.
+ */
+unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu)
+{
+ unsigned mss = 230 - DN_MAX_NSP_DATA_HEADER;
+ if (dev) {
+ struct dn_dev *dn_db = dev->dn_ptr;
+ mtu -= LL_RESERVED_SPACE(dev);
+ if (dn_db->use_long)
+ mtu -= 21;
+ else
+ mtu -= 6;
+ mtu -= DN_MAX_NSP_DATA_HEADER;
+ } else {
+ /*
+ * 21 = long header, 16 = guess at MAC header length
+ */
+ mtu -= (21 + DN_MAX_NSP_DATA_HEADER + 16);
+ }
+ if (mtu > mss)
+ mss = mtu;
+ return mss;
+}
+
+static inline unsigned int dn_current_mss(struct sock *sk, int flags)
+{
+ struct dst_entry *dst = __sk_dst_get(sk);
+ struct dn_scp *scp = DN_SK(sk);
+ int mss_now = min_t(int, scp->segsize_loc, scp->segsize_rem);
+
+ /* Other data messages are limited to 16 bytes per packet */
+ if (flags & MSG_OOB)
+ return 16;
+
+ /* This works out the maximum size of segment we can send out */
+ if (dst) {
+ u32 mtu = dst_pmtu(dst);
+ mss_now = min_t(int, dn_mss_from_pmtu(dst->dev, mtu), mss_now);
+ }
+
+ return mss_now;
+}
+
+static int dn_error(struct sock *sk, int flags, int err)
+{
+ if (err == -EPIPE)
+ err = sock_error(sk) ? : -EPIPE;
+ if (err == -EPIPE && !(flags & MSG_NOSIGNAL))
+ send_sig(SIGPIPE, current, 0);
+ return err;
+}
+
static int dn_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, int size)
{
@@ -1902,9 +1967,6 @@
struct sockaddr_dn *addr = (struct sockaddr_dn *)msg->msg_name;
struct sk_buff *skb = NULL;
struct dn_skb_cb *cb;
- unsigned char msgflg;
- unsigned char *ptr;
- unsigned short ack;
int len;
unsigned char fctype;
long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
@@ -1915,17 +1977,26 @@
if (addr_len && (addr_len != sizeof(struct sockaddr_dn)))
return -EINVAL;
+ /*
+ * The only difference between stream sockets and sequenced packet
+ * sockets is that the stream sockets always behave as if MSG_EOR
+ * has been set.
+ */
+ if (sock->type == SOCK_STREAM) {
+ if (flags & MSG_EOR)
+ return -EINVAL;
+ flags |= MSG_EOR;
+ }
+
lock_sock(sk);
err = dn_check_state(sk, addr, addr_len, &timeo, flags);
if (err)
- goto out;
+ goto out_err;
if (sk->shutdown & SEND_SHUTDOWN) {
- if (!(flags & MSG_NOSIGNAL))
- send_sig(SIGPIPE, current, 0);
err = -EPIPE;
- goto out;
+ goto out_err;
}
if ((flags & MSG_TRYHARD) && sk->dst_cache)
@@ -1934,20 +2005,9 @@
mss = scp->segsize_rem;
fctype = scp->services_rem & NSP_FC_MASK;
- if (sk->dst_cache && sk->dst_cache->neighbour) {
- struct dn_neigh *dn = (struct dn_neigh *)sk->dst_cache->neighbour;
- if (dn->blksize < (mss + 11))
- mss = dn->blksize - 11;
- }
-
- /*
- * The only difference between SEQPACKET & STREAM sockets under DECnet
- * is that SEQPACKET sockets set the MSG_EOR flag for the last
- * session control message segment.
- */
+ mss = dn_current_mss(sk, flags);
if (flags & MSG_OOB) {
- mss = 16;
queue = &scp->other_xmit_queue;
if (size > mss) {
err = -EMSGSIZE;
@@ -2008,7 +2068,7 @@
cb = DN_SKB_CB(skb);
- ptr = skb_put(skb, 9);
+ skb_reserve(skb, DN_MAX_NSP_DATA_HEADER);
if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
err = -EFAULT;
@@ -2016,45 +2076,26 @@
}
if (flags & MSG_OOB) {
- cb->segnum = scp->numoth;
- seq_add(&scp->numoth, 1);
- msgflg = 0x30;
- ack = (scp->numoth_rcv & 0x0FFF) | 0x8000;
- scp->ackxmt_oth = scp->numoth_rcv;
+ cb->nsp_flags = 0x30;
if (fctype != NSP_FC_NONE)
scp->flowrem_oth--;
} else {
- cb->segnum = scp->numdat;
- seq_add(&scp->numdat, 1);
- msgflg = 0x00;
- if (sock->type == SOCK_STREAM)
- msgflg = 0x60;
+ cb->nsp_flags = 0x00;
if (scp->seg_total == 0)
- msgflg |= 0x20;
+ cb->nsp_flags |= 0x20;
scp->seg_total += len;
if (((sent + len) == size) && (flags & MSG_EOR)) {
- msgflg |= 0x40;
+ cb->nsp_flags |= 0x40;
scp->seg_total = 0;
if (fctype == NSP_FC_SCMC)
scp->flowrem_dat--;
}
- ack = (scp->numdat_rcv & 0x0FFF) | 0x8000;
- scp->ackxmt_dat = scp->numdat_rcv;
if (fctype == NSP_FC_SRC)
scp->flowrem_dat--;
}
- *ptr++ = msgflg;
- *(__u16 *)ptr = scp->addrrem;
- ptr += 2;
- *(__u16 *)ptr = scp->addrloc;
- ptr += 2;
- *(__u16 *)ptr = dn_htons(ack);
- ptr += 2;
- *(__u16 *)ptr = dn_htons(cb->segnum);
-
sent += len;
dn_nsp_queue_xmit(sk, skb, sk->allocation, flags & MSG_OOB);
skb = NULL;
@@ -2070,6 +2111,11 @@
release_sock(sk);
return sent ? sent : err;
+
+out_err:
+ err = dn_error(sk, flags, err);
+ release_sock(sk);
+ return err;
}
static int dn_device_event(struct notifier_block *this, unsigned long event,
@@ -2215,10 +2261,8 @@
.sendpage = sock_no_sendpage,
};
-#ifdef CONFIG_SYSCTL
void dn_register_sysctl(void);
void dn_unregister_sysctl(void);
-#endif
MODULE_DESCRIPTION("The Linux DECnet Network Protocol");
@@ -2226,7 +2270,7 @@
MODULE_LICENSE("GPL");
-static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.5.40s (C) 1995-2002 Linux DECnet Project Team\n";
+static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.5.67s (C) 1995-2003 Linux DECnet Project Team\n";
static int __init decnet_init(void)
{
@@ -2253,16 +2297,14 @@
dn_fib_init();
#endif /* CONFIG_DECNET_ROUTER */
-#ifdef CONFIG_SYSCTL
dn_register_sysctl();
-#endif /* CONFIG_SYSCTL */
/*
* Prevent DECnet module unloading until its fixed properly.
* Requires an audit of the code to check for memory leaks and
* initialisation problems etc.
*/
- MOD_INC_USE_COUNT;
+ try_module_get(THIS_MODULE);
return 0;
@@ -2273,9 +2315,7 @@
sock_unregister(AF_DECnet);
dev_remove_pack(&dn_dix_packet_type);
-#ifdef CONFIG_SYSCTL
dn_unregister_sysctl();
-#endif /* CONFIG_SYSCTL */
unregister_netdevice_notifier(&dn_dev_notifier);
diff -Nru linux-2.5.67/net/decnet/dn_dev.c linux/net/decnet/dn_dev.c
--- linux-2.5.67/net/decnet/dn_dev.c Thu Mar 6 16:38:53 2003
+++ linux/net/decnet/dn_dev.c Thu Apr 3 23:26:31 2003
@@ -36,9 +36,11 @@
#include <linux/skbuff.h>
#include <linux/rtnetlink.h>
#include <linux/sysctl.h>
+#include <linux/notifier.h>
#include <asm/uaccess.h>
#include <net/neighbour.h>
#include <net/dst.h>
+#include <net/flow.h>
#include <net/dn.h>
#include <net/dn_dev.h>
#include <net/dn_route.h>
@@ -61,6 +63,7 @@
static rwlock_t dndev_lock = RW_LOCK_UNLOCKED;
static struct net_device *decnet_default_device;
+static struct notifier_block *dnaddr_chain;
static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
static void dn_dev_delete(struct net_device *dev);
@@ -478,7 +481,7 @@
}
rtmsg_ifa(RTM_DELADDR, ifa1);
-
+ notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
if (destroy) {
dn_dev_free_ifa(ifa1);
@@ -513,6 +516,7 @@
dn_db->ifa_list = ifa;
rtmsg_ifa(RTM_NEWADDR, ifa);
+ notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
return 0;
}
@@ -609,7 +613,7 @@
dn_dev_del_ifa(dn_db, ifap, 0);
}
- ifa->ifa_local = dn_saddr2dn(sdn);
+ ifa->ifa_local = ifa->ifa_address = dn_saddr2dn(sdn);
ret = dn_dev_set_ifa(dev, ifa);
}
@@ -686,7 +690,10 @@
if ((ifa = dn_dev_alloc_ifa()) == NULL)
return -ENOBUFS;
+ if (!rta[IFA_ADDRESS - 1])
+ rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1];
memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL-1]), 2);
+ memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS-1]), 2);
ifa->ifa_flags = ifm->ifa_flags;
ifa->ifa_scope = ifm->ifa_scope;
ifa->ifa_dev = dn_db;
@@ -716,7 +723,10 @@
ifm->ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT;
ifm->ifa_scope = ifa->ifa_scope;
ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
- RTA_PUT(skb, IFA_LOCAL, 2, &ifa->ifa_local);
+ if (ifa->ifa_address)
+ RTA_PUT(skb, IFA_ADDRESS, 2, &ifa->ifa_address);
+ if (ifa->ifa_local)
+ RTA_PUT(skb, IFA_LOCAL, 2, &ifa->ifa_local);
if (ifa->ifa_label[0])
RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label);
nlh->nlmsg_len = skb->tail - b;
@@ -758,10 +768,7 @@
s_idx = cb->args[0];
s_dn_idx = dn_idx = cb->args[1];
read_lock(&dev_base_lock);
- for(dev = dev_base, idx = 0; dev; dev = dev->next) {
- if ((dn_db = dev->dn_ptr) == NULL)
- continue;
- idx++;
+ for(dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
if (idx < s_idx)
continue;
if (idx > s_idx)
@@ -773,7 +780,10 @@
if (dn_idx < s_dn_idx)
continue;
- if (dn_dev_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, RTM_NEWADDR) <= 0)
+ if (dn_dev_fill_ifaddr(skb, ifa,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq,
+ RTM_NEWADDR) <= 0)
goto done;
}
}
@@ -872,8 +882,6 @@
}
-#ifdef CONFIG_DECNET_ROUTER
-
#define DRDELAY (5 * HZ)
static int dn_am_i_a_router(struct dn_neigh *dn, struct dn_dev *dn_db, struct dn_ifaddr *ifa)
@@ -981,12 +989,6 @@
else
dn_send_router_hello(dev, ifa);
}
-#else
-static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa)
-{
- dn_send_endnode_hello(dev, ifa);
-}
-#endif
#if 0
static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa)
@@ -1175,7 +1177,7 @@
if ((ifa = dn_dev_alloc_ifa()) == NULL)
return;
- ifa->ifa_local = addr;
+ ifa->ifa_local = ifa->ifa_address = addr;
ifa->ifa_flags = 0;
ifa->ifa_scope = RT_SCOPE_UNIVERSE;
strcpy(ifa->ifa_label, dev->name);
@@ -1274,6 +1276,15 @@
rtnl_unlock();
}
+int register_dnaddr_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_register(&dnaddr_chain, nb);
+}
+
+int unregister_dnaddr_notifier(struct notifier_block *nb)
+{
+ return notifier_chain_unregister(&dnaddr_chain, nb);
+}
#ifdef CONFIG_DECNET_SIOCGIFCONF
/*
@@ -1390,43 +1401,21 @@
static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
{
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, },
-
- { dn_dev_rtm_newaddr, NULL, },
- { dn_dev_rtm_deladdr, NULL, },
- { NULL, dn_dev_dump_ifaddr, },
- { NULL, NULL, },
+ [4] = { .doit = dn_dev_rtm_newaddr, },
+ [5] = { .doit = dn_dev_rtm_deladdr, },
+ [6] = { .dumpit = dn_dev_dump_ifaddr, },
#ifdef CONFIG_DECNET_ROUTER
- { dn_fib_rtm_newroute, NULL, },
- { dn_fib_rtm_delroute, NULL, },
- { dn_cache_getroute, dn_fib_dump, },
- { NULL, NULL, },
+ [8] = { .doit = dn_fib_rtm_newroute, },
+ [9] = { .doit = dn_fib_rtm_delroute, },
+ [10] = { .doit = dn_cache_getroute, .dumpit = dn_fib_dump, },
+ [16] = { .doit = dn_fib_rtm_newrule, },
+ [17] = { .doit = dn_fib_rtm_delrule, },
+ [18] = { .dumpit = dn_fib_dump_rules, },
#else
- { NULL, NULL, },
- { NULL, NULL, },
- { dn_cache_getroute, dn_cache_dump, },
- { NULL, NULL, },
+ [10] = { .doit = dn_cache_getroute, .dumpit = dn_cache_dump, },
#endif
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, },
-#ifdef CONFIG_DECNET_ROUTER
- { dn_fib_rtm_newrule, NULL, },
- { dn_fib_rtm_delrule, NULL, },
- { NULL, dn_fib_dump_rules, },
- { NULL, NULL, }
-#else
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, },
- { NULL, NULL, }
-#endif
};
#ifdef MODULE
diff -Nru linux-2.5.67/net/decnet/dn_fib.c linux/net/decnet/dn_fib.c
--- linux-2.5.67/net/decnet/dn_fib.c Wed Jan 1 19:23:31 2003
+++ linux/net/decnet/dn_fib.c Mon Apr 7 11:37:06 2003
@@ -12,6 +12,9 @@
* Alexey Kuznetsov : SMP locking changes
* Steve Whitehouse : Rewrote it... Well to be more correct, I
* copied most of it from the ipv4 fib code.
+ * Steve Whitehouse : Updated it in style and fixed a few bugs
+ * which were fixed in the ipv4 code since
+ * this code was copied from it.
*
*/
#include <linux/config.h>
@@ -31,12 +34,14 @@
#include <asm/uaccess.h>
#include <net/neighbour.h>
#include <net/dst.h>
+#include <net/flow.h>
#include <net/dn.h>
#include <net/dn_route.h>
#include <net/dn_fib.h>
#include <net/dn_neigh.h>
#include <net/dn_dev.h>
+#define RT_MIN_TABLE 1
#define for_fib_info() { struct dn_fib_info *fi;\
for(fi = dn_fib_info_list; fi; fi = fi->fib_next)
@@ -52,7 +57,7 @@
extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
-
+static spinlock_t dn_fib_multipath_lock = SPIN_LOCK_UNLOCKED;
static struct dn_fib_info *dn_fib_info_list;
static rwlock_t dn_fib_info_lock = RW_LOCK_UNLOCKED;
int dn_fib_info_cnt;
@@ -62,18 +67,18 @@
int error;
u8 scope;
} dn_fib_props[RTA_MAX+1] = {
- { 0, RT_SCOPE_NOWHERE }, /* RTN_UNSPEC */
- { 0, RT_SCOPE_UNIVERSE }, /* RTN_UNICAST */
- { 0, RT_SCOPE_HOST }, /* RTN_LOCAL */
- { -EINVAL, RT_SCOPE_NOWHERE }, /* RTN_BROADCAST */
- { -EINVAL, RT_SCOPE_NOWHERE }, /* RTN_ANYCAST */
- { -EINVAL, RT_SCOPE_NOWHERE }, /* RTN_MULTICAST */
- { -EINVAL, RT_SCOPE_UNIVERSE }, /* RTN_BLACKHOLE */
- { -EHOSTUNREACH, RT_SCOPE_UNIVERSE }, /* RTN_UNREACHABLE */
- { -EACCES, RT_SCOPE_UNIVERSE }, /* RTN_PROHIBIT */
- { -EAGAIN, RT_SCOPE_UNIVERSE }, /* RTN_THROW */
- { -EINVAL, RT_SCOPE_NOWHERE }, /* RTN_NAT */
- { -EINVAL, RT_SCOPE_NOWHERE } /* RTN_XRESOLVE */
+ { .error = 0, .scope = RT_SCOPE_NOWHERE }, /* RTN_UNSPEC */
+ { .error = 0, .scope = RT_SCOPE_UNIVERSE }, /* RTN_UNICAST */
+ { .error = 0, .scope = RT_SCOPE_HOST }, /* RTN_LOCAL */
+ { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_BROADCAST */
+ { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_ANYCAST */
+ { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_MULTICAST */
+ { .error = -EINVAL, .scope = RT_SCOPE_UNIVERSE }, /* RTN_BLACKHOLE */
+ { .error = -EHOSTUNREACH, .scope = RT_SCOPE_UNIVERSE }, /* RTN_UNREACHABLE */
+ { .error = -EACCES, .scope = RT_SCOPE_UNIVERSE }, /* RTN_PROHIBIT */
+ { .error = -EAGAIN, .scope = RT_SCOPE_UNIVERSE }, /* RTN_THROW */
+ { .error = 0, .scope = RT_SCOPE_NOWHERE }, /* RTN_NAT */
+ { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE } /* RTN_XRESOLVE */
};
void dn_fib_free_info(struct dn_fib_info *fi)
@@ -108,7 +113,7 @@
write_unlock(&dn_fib_info_lock);
}
-static __inline__ int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi)
+static inline int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi)
{
const struct dn_fib_nh *onh = ofi->fib_nh;
@@ -124,7 +129,7 @@
return 0;
}
-static __inline__ struct dn_fib_info *dn_fib_find_info(const struct dn_fib_info *nfi)
+static inline struct dn_fib_info *dn_fib_find_info(const struct dn_fib_info *nfi)
{
for_fib_info() {
if (fi->fib_nhs != nfi->fib_nhs)
@@ -132,6 +137,7 @@
if (nfi->fib_protocol == fi->fib_protocol &&
nfi->fib_prefsrc == fi->fib_prefsrc &&
nfi->fib_priority == fi->fib_priority &&
+ memcmp(nfi->fib_metrics, fi->fib_metrics, sizeof(fi->fib_metrics)) == 0 &&
((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 &&
(nfi->fib_nhs == 0 || dn_fib_nh_comp(fi, nfi) == 0))
return fi;
@@ -195,14 +201,18 @@
int err;
if (nh->nh_gw) {
- struct dn_fib_key key;
+ struct flowi fl;
struct dn_fib_res res;
+ memset(&fl, 0, sizeof(fl));
+
if (nh->nh_flags&RTNH_F_ONLINK) {
struct net_device *dev;
if (r->rtm_scope >= RT_SCOPE_LINK)
return -EINVAL;
+ if (dnet_addr_type(nh->nh_gw) != RTN_UNICAST)
+ return -EINVAL;
if ((dev = __dev_get_by_index(nh->nh_oif)) == NULL)
return -ENODEV;
if (!(dev->flags&IFF_UP))
@@ -213,23 +223,33 @@
return 0;
}
- memset(&key, 0, sizeof(key));
- key.dst = nh->nh_gw;
- key.oif = nh->nh_oif;
- key.scope = r->rtm_scope + 1;
+ memset(&fl, 0, sizeof(fl));
+ fl.fld_dst = nh->nh_gw;
+ fl.oif = nh->nh_oif;
+ fl.fld_scope = r->rtm_scope + 1;
- if (key.scope < RT_SCOPE_LINK)
- key.scope = RT_SCOPE_LINK;
+ if (fl.fld_scope < RT_SCOPE_LINK)
+ fl.fld_scope = RT_SCOPE_LINK;
- if ((err = dn_fib_lookup(&key, &res)) != 0)
+ if ((err = dn_fib_lookup(&fl, &res)) != 0)
return err;
+ err = -EINVAL;
+ if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
+ goto out;
nh->nh_scope = res.scope;
nh->nh_oif = DN_FIB_RES_OIF(res);
nh->nh_dev = DN_FIB_RES_DEV(res);
- if (nh->nh_dev)
- atomic_inc(&nh->nh_dev->refcnt);
+ if (nh->nh_dev == NULL)
+ goto out;
+ atomic_inc(&nh->nh_dev->refcnt);
+ err = -ENETDOWN;
+ if (!(nh->nh_dev->flags & IFF_UP))
+ goto out;
+ err = 0;
+out:
dn_fib_res_put(&res);
+ return err;
} else {
struct net_device *dev;
@@ -277,6 +297,20 @@
fi->fib_flags = r->rtm_flags;
if (rta->rta_priority)
fi->fib_priority = *rta->rta_priority;
+ if (rta->rta_mx) {
+ int attrlen = RTA_PAYLOAD(rta->rta_mx);
+ struct rtattr *attr = RTA_DATA(rta->rta_mx);
+
+ while(RTA_OK(attr, attrlen)) {
+ unsigned flavour = attr->rta_type;
+ if (flavour) {
+ if (flavour > RTAX_MAX)
+ goto err_inval;
+ fi->fib_metrics[flavour-1] = *(unsigned*)RTA_DATA(attr);
+ }
+ attr = RTA_NEXT(attr, attrlen);
+ }
+ }
if (rta->rta_prefsrc)
memcpy(&fi->fib_prefsrc, rta->rta_prefsrc, 2);
@@ -297,6 +331,13 @@
nh->nh_weight = 1;
}
+ if (r->rtm_type == RTN_NAT) {
+ if (rta->rta_gw == NULL || nhs != 1 || rta->rta_oif)
+ goto err_inval;
+ memcpy(&fi->fib_nh->nh_gw, rta->rta_gw, 2);
+ goto link_it;
+ }
+
if (dn_fib_props[r->rtm_type].error) {
if (rta->rta_gw || rta->rta_oif || rta->rta_mp)
goto err_inval;
@@ -324,14 +365,12 @@
} endfor_nexthops(fi)
}
-#if I_GET_AROUND_TO_FIXING_PREFSRC
if (fi->fib_prefsrc) {
if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL ||
memcmp(&fi->fib_prefsrc, rta->rta_dst, 2))
- if (dn_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
+ if (dnet_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
goto err_inval;
}
-#endif
link_it:
if ((ofi = dn_fib_find_info(fi)) != NULL) {
@@ -366,12 +405,53 @@
return NULL;
}
+int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowi *fl, struct dn_fib_res *res)
+{
+ int err = dn_fib_props[type].error;
+
+ if (err == 0) {
+ if (fi->fib_flags & RTNH_F_DEAD)
+ return 1;
+
+ res->fi = fi;
+
+ switch(type) {
+ case RTN_NAT:
+ DN_FIB_RES_RESET(*res);
+ atomic_inc(&fi->fib_clntref);
+ return 0;
+ case RTN_UNICAST:
+ case RTN_LOCAL:
+ for_nexthops(fi) {
+ if (nh->nh_flags & RTNH_F_DEAD)
+ continue;
+ if (!fl->oif || fl->oif == nh->nh_oif)
+ break;
+ }
+ if (nhsel < fi->fib_nhs) {
+ res->nh_sel = nhsel;
+ atomic_inc(&fi->fib_clntref);
+ return 0;
+ }
+ endfor_nexthops(fi);
+ res->fi = NULL;
+ return 1;
+ default:
+ if (net_ratelimit())
+ printk("DECnet: impossible routing event : dn_fib_semantic_match type=%d\n", type);
+ res->fi = NULL;
+ return -EINVAL;
+ }
+ }
+ return err;
+}
-void dn_fib_select_multipath(const struct dn_fib_key *key, struct dn_fib_res *res)
+void dn_fib_select_multipath(const struct flowi *fl, struct dn_fib_res *res)
{
struct dn_fib_info *fi = res->fi;
int w;
+ spin_lock_bh(&dn_fib_multipath_lock);
if (fi->fib_power <= 0) {
int power = 0;
change_nexthops(fi) {
@@ -381,6 +461,11 @@
}
} endfor_nexthops(fi);
fi->fib_power = power;
+ if (power < 0) {
+ spin_unlock_bh(&dn_fib_multipath_lock);
+ res->nh_sel = 0;
+ return;
+ }
}
w = jiffies % fi->fib_power;
@@ -391,16 +476,16 @@
nh->nh_power--;
fi->fib_power--;
res->nh_sel = nhsel;
+ spin_unlock_bh(&dn_fib_multipath_lock);
return;
}
}
} endfor_nexthops(fi);
-
- printk(KERN_DEBUG "DECnet: BUG! dn_fib_select_multipath\n");
+ res->nh_sel = 0;
+ spin_unlock_bh(&dn_fib_multipath_lock);
}
-
/*
* Punt to user via netlink for example, but for now
* we just drop it.
@@ -475,9 +560,9 @@
s_t = cb->args[0];
if (s_t == 0)
- s_t = cb->args[0] = DN_MIN_TABLE;
+ s_t = cb->args[0] = RT_MIN_TABLE;
- for(t = s_t; t < DN_NUM_TABLES; t++) {
+ for(t = s_t; t <= RT_TABLE_MAX; t++) {
if (t < s_t)
continue;
if (t > s_t)
@@ -494,6 +579,125 @@
return skb->len;
}
+static void fib_magic(int cmd, int type, __u16 dst, int dst_len, struct dn_ifaddr *ifa)
+{
+ struct dn_fib_table *tb;
+ struct {
+ struct nlmsghdr nlh;
+ struct rtmsg rtm;
+ } req;
+ struct dn_kern_rta rta;
+
+ memset(&req.rtm, 0, sizeof(req.rtm));
+ memset(&rta, 0, sizeof(rta));
+
+ if (type == RTN_UNICAST)
+ tb = dn_fib_get_table(RT_MIN_TABLE, 1);
+ else
+ tb = dn_fib_get_table(RT_TABLE_LOCAL, 1);
+
+ if (tb == NULL)
+ return;
+
+ req.nlh.nlmsg_len = sizeof(req);
+ req.nlh.nlmsg_type = cmd;
+ req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND;
+ req.nlh.nlmsg_pid = 0;
+ req.nlh.nlmsg_seq = 0;
+
+ req.rtm.rtm_dst_len = dst_len;
+ req.rtm.rtm_table = tb->n;
+ req.rtm.rtm_protocol = RTPROT_KERNEL;
+ req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST);
+ req.rtm.rtm_type = type;
+
+ rta.rta_dst = &dst;
+ rta.rta_prefsrc = &ifa->ifa_local;
+ rta.rta_oif = &ifa->ifa_dev->dev->ifindex;
+
+ if (cmd == RTM_NEWROUTE)
+ tb->insert(tb, &req.rtm, &rta, &req.nlh, NULL);
+ else
+ tb->delete(tb, &req.rtm, &rta, &req.nlh, NULL);
+}
+
+static void dn_fib_add_ifaddr(struct dn_ifaddr *ifa)
+{
+
+ fib_magic(RTM_NEWROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa);
+
+#if 0
+ if (!(dev->flags&IFF_UP))
+ return;
+ /* In the future, we will want to add default routes here */
+
+#endif
+}
+
+static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa)
+{
+ int found_it = 0;
+ struct net_device *dev;
+ struct dn_dev *dn_db;
+ struct dn_ifaddr *ifa2;
+
+ ASSERT_RTNL();
+
+ /* Scan device list */
+ read_lock(&dev_base_lock);
+ for(dev = dev_base; dev; dev = dev->next) {
+ dn_db = dev->dn_ptr;
+ if (dn_db == NULL)
+ continue;
+ for(ifa2 = dn_db->ifa_list; ifa2; ifa2 = ifa2->ifa_next) {
+ if (ifa2->ifa_local == ifa->ifa_local) {
+ found_it = 1;
+ break;
+ }
+ }
+ }
+ read_unlock(&dev_base_lock);
+
+ if (found_it == 0) {
+ fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa);
+
+ if (dnet_addr_type(ifa->ifa_local) != RTN_LOCAL) {
+ if (dn_fib_sync_down(ifa->ifa_local, NULL, 0))
+ dn_fib_flush();
+ }
+ }
+}
+
+static void dn_fib_disable_addr(struct net_device *dev, int force)
+{
+ if (dn_fib_sync_down(0, dev, force))
+ dn_fib_flush();
+ dn_rt_cache_flush(0);
+ neigh_ifdown(&dn_neigh_table, dev);
+}
+
+static int dn_fib_dnaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct dn_ifaddr *ifa = (struct dn_ifaddr *)ptr;
+
+ switch(event) {
+ case NETDEV_UP:
+ dn_fib_add_ifaddr(ifa);
+ dn_fib_sync_up(ifa->ifa_dev->dev);
+ dn_rt_cache_flush(-1);
+ break;
+ case NETDEV_DOWN:
+ dn_fib_del_ifaddr(ifa);
+ if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {
+ dn_fib_disable_addr(ifa->ifa_dev->dev, 1);
+ } else {
+ dn_rt_cache_flush(-1);
+ }
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
int dn_fib_sync_down(dn_address local, struct net_device *dev, int force)
{
int ret = 0;
@@ -520,9 +724,11 @@
dead++;
else if (nh->nh_dev == dev &&
nh->nh_scope != scope) {
+ spin_lock_bh(&dn_fib_multipath_lock);
nh->nh_flags |= RTNH_F_DEAD;
fi->fib_power -= nh->nh_power;
nh->nh_power = 0;
+ spin_unlock_bh(&dn_fib_multipath_lock);
dead++;
}
} endfor_nexthops(fi)
@@ -556,11 +762,13 @@
if (nh->nh_dev != dev || dev->dn_ptr == NULL)
continue;
alive++;
+ spin_lock_bh(&dn_fib_multipath_lock);
nh->nh_power = 0;
nh->nh_flags &= ~RTNH_F_DEAD;
+ spin_unlock_bh(&dn_fib_multipath_lock);
} endfor_nexthops(fi);
- if (alive == fi->fib_nhs) {
+ if (alive > 0) {
fi->fib_flags &= ~RTNH_F_DEAD;
ret++;
}
@@ -574,7 +782,7 @@
struct dn_fib_table *tb;
int id;
- for(id = DN_NUM_TABLES; id > 0; id--) {
+ for(id = RT_TABLE_MAX; id > 0; id--) {
if ((tb = dn_fib_get_table(id, 0)) == NULL)
continue;
flushed += tb->flush(tb);
@@ -584,21 +792,6 @@
dn_rt_cache_flush(-1);
}
-int dn_fib_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
-
- switch(cmd) {
- case SIOCADDRT:
- case SIOCDELRT:
- return 0;
- }
-
- return -EINVAL;
-}
-
#ifdef CONFIG_PROC_FS
static int decnet_rt_get_info(char *buffer, char **start, off_t offset, int length)
@@ -620,7 +813,7 @@
}
- for(i = DN_MIN_TABLE; (i <= DN_NUM_TABLES) && (count > 0); i++) {
+ for(i = RT_MIN_TABLE; (i <= RT_TABLE_MAX) && (count > 0); i++) {
if ((tb = dn_fib_get_table(i, 0)) != NULL) {
int n = tb->get_info(tb, ptr, first, count);
count -= n;
@@ -638,12 +831,18 @@
}
#endif /* CONFIG_PROC_FS */
+static struct notifier_block dn_fib_dnaddr_notifier = {
+ .notifier_call = dn_fib_dnaddr_event,
+};
+
void __exit dn_fib_cleanup(void)
{
proc_net_remove("decnet_route");
dn_fib_table_cleanup();
dn_fib_rules_cleanup();
+
+ unregister_dnaddr_notifier(&dn_fib_dnaddr_notifier);
}
@@ -656,6 +855,8 @@
dn_fib_table_init();
dn_fib_rules_init();
+
+ register_dnaddr_notifier(&dn_fib_dnaddr_notifier);
}
diff -Nru linux-2.5.67/net/decnet/dn_neigh.c linux/net/decnet/dn_neigh.c
--- linux-2.5.67/net/decnet/dn_neigh.c Wed Jan 1 19:22:30 2003
+++ linux/net/decnet/dn_neigh.c Tue Apr 8 08:44:19 2003
@@ -20,6 +20,7 @@
* Steve Whitehouse : Fixed neighbour states (for now anyway).
* Steve Whitehouse : Made error_report functions dummies. This
* is not the right place to return skbs.
+ * Steve Whitehouse : Convert to seq_file
*
*/
@@ -33,9 +34,11 @@
#include <linux/string.h>
#include <linux/netfilter_decnet.h>
#include <linux/spinlock.h>
+#include <linux/seq_file.h>
#include <asm/atomic.h>
#include <net/neighbour.h>
#include <net/dst.h>
+#include <net/flow.h>
#include <net/dn.h>
#include <net/dn_dev.h>
#include <net/dn_neigh.h>
@@ -160,7 +163,20 @@
return -EINVAL;
}
- dn->blksize = 230;
+ /*
+ * Make an estimate of the remote block size by assuming that its
+ * two less then the device mtu, which it true for ethernet (and
+ * other things which support long format headers) since there is
+ * an extra length field (of 16 bits) which isn't part of the
+ * ethernet headers and which the DECnet specs won't admit is part
+ * of the DECnet routing headers either.
+ *
+ * If we over estimate here its no big deal, the NSP negotiations
+ * will prevent us from sending packets which are too large for the
+ * remote node to handle. In any case this figure is normally updated
+ * by a hello message in most cases.
+ */
+ dn->blksize = dev->mtu - 2;
return 0;
}
@@ -330,7 +346,7 @@
* basically does a neigh_lookup(), but without comparing the device
* field. This is required for the On-Ethernet cache
*/
-struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, void *ptr)
+struct neighbour *dn_neigh_lookup(struct neigh_table *tbl, const void *ptr)
{
struct neighbour *neigh;
u32 hash_val;
@@ -466,8 +482,6 @@
return 0;
}
-
-#ifdef CONFIG_DECNET_ROUTER
static char *dn_find_slot(char *base, int max, int priority)
{
int i;
@@ -526,78 +540,200 @@
return t;
}
-#endif /* CONFIG_DECNET_ROUTER */
-
#ifdef CONFIG_PROC_FS
-static int dn_neigh_get_info(char *buffer, char **start, off_t offset, int length)
+
+struct dn_neigh_iter_state {
+ int bucket;
+};
+
+static struct neighbour *neigh_get_first(struct seq_file *seq)
{
- int len = 0;
- off_t pos = 0;
- off_t begin = 0;
- struct neighbour *n;
- int i;
- char buf[DN_ASCBUF_LEN];
+ struct dn_neigh_iter_state *state = seq->private;
+ struct neighbour *n = NULL;
+
+ for(state->bucket = 0;
+ state->bucket <= NEIGH_HASHMASK;
+ ++state->bucket) {
+ n = dn_neigh_table.hash_buckets[state->bucket];
+ if (n)
+ break;
+ }
- len += sprintf(buffer + len, "Addr Flags State Use Blksize Dev\n");
+ return n;
+}
- for(i=0;i <= NEIGH_HASHMASK; i++) {
- read_lock_bh(&dn_neigh_table.lock);
- n = dn_neigh_table.hash_buckets[i];
- for(; n != NULL; n = n->next) {
- struct dn_neigh *dn = (struct dn_neigh *)n;
-
- read_lock(&n->lock);
- len += sprintf(buffer+len, "%-7s %s%s%s %02x %02d %07ld %-8s\n",
- dn_addr2asc(dn_ntohs(dn->addr), buf),
- (dn->flags&DN_NDFLAG_R1) ? "1" : "-",
- (dn->flags&DN_NDFLAG_R2) ? "2" : "-",
- (dn->flags&DN_NDFLAG_P3) ? "3" : "-",
- dn->n.nud_state,
- atomic_read(&dn->n.refcnt),
- dn->blksize,
- (dn->n.dev) ? dn->n.dev->name : "?");
- read_unlock(&n->lock);
-
- pos = begin + len;
-
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
-
- if (pos > offset + length) {
- read_unlock_bh(&dn_neigh_table.lock);
- goto done;
- }
- }
+static struct neighbour *neigh_get_next(struct seq_file *seq,
+ struct neighbour *n)
+{
+ struct dn_neigh_iter_state *state = seq->private;
+
+ n = n->next;
+try_again:
+ if (n)
+ goto out;
+ if (++state->bucket > NEIGH_HASHMASK)
+ goto out;
+ n = dn_neigh_table.hash_buckets[state->bucket];
+ goto try_again;
+out:
+ return n;
+}
+
+static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
+{
+ struct neighbour *n = neigh_get_first(seq);
+
+ if (n)
+ while(*pos && (n = neigh_get_next(seq, n)))
+ --*pos;
+ return *pos ? NULL : n;
+}
+
+static void *dn_neigh_get_idx(struct seq_file *seq, loff_t pos)
+{
+ void *rc;
+ read_lock_bh(&dn_neigh_table.lock);
+ rc = neigh_get_idx(seq, &pos);
+ if (!rc) {
read_unlock_bh(&dn_neigh_table.lock);
}
+ return rc;
+}
-done:
+static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ return *pos ? dn_neigh_get_idx(seq, *pos - 1) : (void*)1;
+}
+
+static void *dn_neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ void *rc;
- *start = buffer + (offset - begin);
- len -= offset - begin;
- if (len > length) len = length;
+ if (v == (void*)1) {
+ rc = dn_neigh_get_idx(seq, 0);
+ goto out;
+ }
- return len;
+ rc = neigh_get_next(seq, v);
+ if (rc)
+ goto out;
+ read_unlock_bh(&dn_neigh_table.lock);
+out:
+ ++*pos;
+ return rc;
+}
+
+static void dn_neigh_seq_stop(struct seq_file *seq, void *v)
+{
+ if (v && v != (void*)1)
+ read_unlock_bh(&dn_neigh_table.lock);
}
+static inline void dn_neigh_format_entry(struct seq_file *seq,
+ struct neighbour *n)
+{
+ struct dn_neigh *dn = (struct dn_neigh *)n;
+ char buf[DN_ASCBUF_LEN];
+
+ read_lock(&n->lock);
+ seq_printf(seq, "%-7s %s%s%s %02x %02d %07ld %-8s\n",
+ dn_addr2asc(dn_ntohs(dn->addr), buf),
+ (dn->flags&DN_NDFLAG_R1) ? "1" : "-",
+ (dn->flags&DN_NDFLAG_R2) ? "2" : "-",
+ (dn->flags&DN_NDFLAG_P3) ? "3" : "-",
+ dn->n.nud_state,
+ atomic_read(&dn->n.refcnt),
+ dn->blksize,
+ (dn->n.dev) ? dn->n.dev->name : "?");
+ read_unlock(&n->lock);
+}
+
+static int dn_neigh_seq_show(struct seq_file *seq, void *v)
+{
+ if (v == (void*)1) {
+ seq_puts(seq, "Addr Flags State Use Blksize Dev\n");
+ } else {
+ dn_neigh_format_entry(seq, v);
+ }
+
+ return 0;
+}
+
+static struct seq_operations dn_neigh_seq_ops = {
+ .start = dn_neigh_seq_start,
+ .next = dn_neigh_seq_next,
+ .stop = dn_neigh_seq_stop,
+ .show = dn_neigh_seq_show,
+};
+
+static int dn_neigh_seq_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ int rc = -ENOMEM;
+ struct dn_neigh_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+ if (!s)
+ goto out;
+
+ rc = seq_open(file, &dn_neigh_seq_ops);
+ if (rc)
+ goto out_kfree;
+
+ seq = file->private_data;
+ seq->private = s;
+ memset(s, 0, sizeof(*s));
+out:
+ return rc;
+out_kfree:
+ kfree(s);
+ goto out;
+}
+
+static int dn_seq_release(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq = (struct seq_file *)file->private_data;
+
+ kfree(seq->private);
+ seq->private = NULL;
+ return seq_release(inode, file);
+}
+
+static struct file_operations dn_neigh_seq_fops = {
+ .open = dn_neigh_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = dn_seq_release,
+};
+
+static int __init dn_neigh_proc_init(void)
+{
+ int rc = 0;
+ struct proc_dir_entry *p = create_proc_entry("decnet_neigh", S_IRUGO, proc_net);
+ if (p)
+ p->proc_fops = &dn_neigh_seq_fops;
+ else
+ rc = -ENOMEM;
+ return rc;
+}
+
+#else
+static int __init dn_neigh_proc_init(void)
+{
+ return 0;
+}
#endif
void __init dn_neigh_init(void)
{
neigh_table_init(&dn_neigh_table);
-#ifdef CONFIG_PROC_FS
- proc_net_create("decnet_neigh",0,dn_neigh_get_info);
-#endif /* CONFIG_PROC_FS */
+ dn_neigh_proc_init();
}
void __exit dn_neigh_cleanup(void)
{
- proc_net_remove("decnet_neigh");
neigh_table_clear(&dn_neigh_table);
}
diff -Nru linux-2.5.67/net/decnet/dn_nsp_in.c linux/net/decnet/dn_nsp_in.c
--- linux-2.5.67/net/decnet/dn_nsp_in.c Fri Mar 21 17:43:44 2003
+++ linux/net/decnet/dn_nsp_in.c Fri Mar 21 17:43:27 2003
@@ -434,7 +434,15 @@
sk->state_change(sk);
}
- dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
+ /*
+ * It appears that its possible for remote machines to send disc
+ * init messages with no port identifier if we are in the CI and
+ * possibly also the CD state. Obviously we shouldn't reply with
+ * a message if we don't know what the end point is.
+ */
+ if (scp->addrrem) {
+ dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
+ }
scp->persist_fxn = dn_destroy_timer;
scp->persist = dn_nsp_persist(sk);
diff -Nru linux-2.5.67/net/decnet/dn_nsp_out.c linux/net/decnet/dn_nsp_out.c
--- linux-2.5.67/net/decnet/dn_nsp_out.c Tue Feb 25 05:12:25 2003
+++ linux/net/decnet/dn_nsp_out.c Tue Apr 1 14:09:26 2003
@@ -21,6 +21,7 @@
* Paul Koning: Connect Confirm message fix.
* Eduardo Serrat: Fix to stop dn_nsp_do_disc() sending malformed packets.
* Steve Whitehouse: dn_nsp_output() and friends needed a spring clean
+ * Steve Whitehouse: Moved dn_nsp_send() in here from route.h
*/
/******************************************************************************
@@ -63,6 +64,7 @@
#include <linux/if_packet.h>
#include <net/neighbour.h>
#include <net/dst.h>
+#include <net/flow.h>
#include <net/dn.h>
#include <net/dn_nsp.h>
#include <net/dn_dev.h>
@@ -71,6 +73,41 @@
static int nsp_backoff[NSP_MAXRXTSHIFT + 1] = { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
+static void dn_nsp_send(struct sk_buff *skb)
+{
+ struct sock *sk = skb->sk;
+ struct dn_scp *scp = DN_SK(sk);
+ struct dst_entry *dst;
+ struct flowi fl;
+
+ skb->h.raw = skb->data;
+ scp->stamp = jiffies;
+
+ dst = sk_dst_check(sk, 0);
+ if (dst) {
+try_again:
+ skb->dst = dst;
+ dst_output(skb);
+ return;
+ }
+
+ memset(&fl, 0, sizeof(fl));
+ fl.oif = sk->bound_dev_if;
+ fl.fld_src = dn_saddr2dn(&scp->addr);
+ fl.fld_dst = dn_saddr2dn(&scp->peer);
+ dn_sk_ports_copy(&fl, scp);
+ if (dn_route_output_sock(&sk->dst_cache, &fl, sk, 0) == 0) {
+ dst = sk_dst_get(sk);
+ sk->route_caps = dst->dev->features;
+ goto try_again;
+ }
+
+ sk->err = EHOSTUNREACH;
+ if (!test_bit(SOCK_DEAD, &sk->flags))
+ sk->state_change(sk);
+}
+
+
/*
* If sk == NULL, then we assume that we are supposed to be making
* a routing layer skb. If sk != NULL, then we are supposed to be
@@ -356,12 +393,33 @@
return ptr;
}
+static unsigned short *dn_nsp_mk_data_header(struct sock *sk, struct sk_buff *skb, int oth)
+{
+ struct dn_scp *scp = DN_SK(sk);
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
+ unsigned short *ptr = dn_mk_ack_header(sk, skb, cb->nsp_flags, 11, oth);
+
+ if (unlikely(oth)) {
+ cb->segnum = scp->numoth;
+ seq_add(&scp->numoth, 1);
+ } else {
+ cb->segnum = scp->numdat;
+ seq_add(&scp->numdat, 1);
+ }
+ *(ptr++) = dn_htons(cb->segnum);
+
+ return ptr;
+}
+
void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, int gfp, int oth)
{
struct dn_scp *scp = DN_SK(sk);
struct dn_skb_cb *cb = DN_SKB_CB(skb);
unsigned long t = ((scp->nsp_srtt >> 2) + scp->nsp_rttvar) >> 1;
+ cb->xmit_count = 0;
+ dn_nsp_mk_data_header(sk, skb, oth);
+
/*
* Slow start: If we have been idle for more than
* one RTT, then reset window to min size.
@@ -369,10 +427,6 @@
if ((jiffies - scp->stamp) > t)
scp->snd_window = NSP_MIN_WINDOW;
- /* printk(KERN_DEBUG "Window: %lu\n", scp->snd_window); */
-
- cb->xmit_count = 0;
-
if (oth)
skb_queue_tail(&scp->other_xmit_queue, skb);
else
@@ -630,19 +684,15 @@
{
struct dn_scp *scp = DN_SK(sk);
struct sk_buff *skb;
- unsigned short *segnum;
unsigned char *ptr;
int gfp = GFP_ATOMIC;
- if ((skb = dn_alloc_skb(sk, 13, gfp)) == NULL)
+ if ((skb = dn_alloc_skb(sk, DN_MAX_NSP_DATA_HEADER + 2, gfp)) == NULL)
return;
- skb_reserve(skb, 13);
- segnum = dn_mk_ack_header(sk, skb, 0x10, 13, 1);
- *segnum = dn_htons(scp->numoth);
- DN_SKB_CB(skb)->segnum = scp->numoth;
- seq_add(&scp->numoth, 1);
- ptr = (unsigned char *)(segnum + 1);
+ skb_reserve(skb, DN_MAX_NSP_DATA_HEADER);
+ ptr = skb_put(skb, 2);
+ DN_SKB_CB(skb)->nsp_flags = 0x10;
*ptr++ = lsflags;
*ptr = fcval;
diff -Nru linux-2.5.67/net/decnet/dn_route.c linux/net/decnet/dn_route.c
--- linux-2.5.67/net/decnet/dn_route.c Tue Feb 25 05:12:25 2003
+++ linux/net/decnet/dn_route.c Thu Apr 17 09:12:07 2003
@@ -37,7 +37,8 @@
* backlog congestion level return codes.
* Steve Whitehouse : Fixed bug where routes were set up with
* no ref count on net devices.
- *
+ * Steve Whitehouse : RCU for the route cache
+ * Steve Whitehouse : Preparations for the flow cache
*/
/******************************************************************************
@@ -65,17 +66,19 @@
#include <linux/netdevice.h>
#include <linux/inet.h>
#include <linux/route.h>
+#include <linux/in_route.h>
#include <net/sock.h>
-#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/rtnetlink.h>
#include <linux/string.h>
#include <linux/netfilter_decnet.h>
+#include <linux/rcupdate.h>
#include <asm/errno.h>
#include <net/neighbour.h>
#include <net/dst.h>
+#include <net/flow.h>
#include <net/dn.h>
#include <net/dn_dev.h>
#include <net/dn_nsp.h>
@@ -86,7 +89,7 @@
struct dn_rt_hash_bucket
{
struct dn_route *chain;
- rwlock_t lock;
+ spinlock_t lock;
} __attrib...
[truncated message content] |
|
From: Patrick C. <pa...@ty...> - 2003-04-16 07:00:30
|
On Tue, Apr 15, 2003 at 06:13:44PM -0400, McVeagh, John wrote: > > Using Debian release 3 (woody/i386/stable). > > Made an assumption that I could just do "apt-get install dnet-common", and > everything would install fine. When I did this, the install process failed > with the message "modprobe: Can't locate module decnet". > > I read the FAQ over and figured that since woody stable does not use the 2.4 > kernel, I figured I would have to patch the kernel. I tried to do that but > the "patch -p1 <decnet2216.diff" command failed with "can't fine file to > patch at input line 4". You'll need to run a 2.4 kernel. While there are patches for 2.2 kernels on the SF site nobody has tested them for ages and I've no idea whether they work with newer 2.2 kernels. Incidentally dnet-common isn't enough to get a running system, "apt-get dnet-progs" will get you something that is actually useful - provided you have the kernel support that is... -- patrick |
|
From: McVeagh, J. <Joh...@CS...> - 2003-04-15 22:18:37
|
Using Debian release 3 (woody/i386/stable).
Made an assumption that I could just do "apt-get install dnet-common", and
everything would install fine. When I did this, the install process failed
with the message "modprobe: Can't locate module decnet".
I read the FAQ over and figured that since woody stable does not use the 2.4
kernel, I figured I would have to patch the kernel. I tried to do that but
the "patch -p1 <decnet2216.diff" command failed with "can't fine file to
patch at input line 4".
Any help would be appreciated.
|
|
From: Steven W. <st...@gw...> - 2003-04-08 16:13:12
|
Hi, I've had a little time recently to work on the routing for DECnet. I've got a patch against 2.5.67 which is rather large which fixes a number of issues which have been outstanding for some time. It also brings into the DECnet code some bug fixes which were introduced into the ipv4 routing code after the DECnet routing code was split from it. Some of the fixes need back porting into 2.4 and I may get time to do that over the next few weeks, but its not an easy thing to do since so much has changed. I suspect that very few people are using the routing code in the 2.4 kernel version of DECnet anyway. Since the patch is large I've not attached it, but it can be found here: http://www.chygwyn.com/~steve/kpatch/ I'm also intending to submit it to the 2.5 kernel very shortly. Some of the features are: o Two bugs fixed (only in 2.5 decnet stack) relating to bind and connection states. o Numerous style changes: using C99 initialisers and inline rather than __inline__ o Use struct flowi as routing key (for forthcoming flow cache) o Add metrics to routing table o Many routing table bug fixes o New wait code to improve efficiency o New module interface functions o We use real device MTUs now rather than saying "hmm... looks like ethernet must be 1500" as we used to (still one or two places to fix, but its mostly correct in this patch) o Tidy up in af_decnet.c:dn_sendmsg() in preparation for zerocopy o Updates to rtnetlink code to return more information o Removed ioctl() for decnet fib. It never did anything and rtnetlink is a far better interface anyway. o Converted /proc/decnet_neigh to seq_file (other /proc files to follow) o DECnet route cache now uses RCU like the ipv4 route cache o Misc bug fixes wherever I found them I would recommend all users of DECnet in 2.5 to upgrade to this patch as soon as it makes it into the standard kernel. As always - let me know if you have any comments or questions or spot any more bugs! Steve. |
|
From: Steven W. <st...@gw...> - 2003-04-04 10:05:33
|
Hi, I've not looked at dapfs for quite a while now. You will be safe to change the malloc.h for slab.h as the comment suggests, thats the easy part. As for the rest of the code, it may need some work to get it going properly. The other problem you are seeing is probably due to missing prototypes in a header file or something similar, Steve. > > > > Hello DecNet Users, I am hoping someone can help with this problem. > > During the kernel make process , two undefined symbols are reported during the kallsyms phase: "dap_file_operations" and "dap_dir_operations" (see below for details). I am a complete novice at kernel rebuilds, and as a result have not been able to find the cause of (what I think is ) the linking problem. > As far as I can tell, these data structures are defined in /usr/src/linux/fs/dapfs/file.c and /usr/src/linux/fs/dapfs/dir.c. > There are no errors reported from gcc apart from a warning regarding the deprecated status of "malloc.h". > There was however, a problem in applying the dapfs patch to the 2.4.18-3 kernel source, but I believe it was because of a change related to the inclusion of jfss2 in the vfs somewhere between 2.4.1 and 2.4.18. The patch problem (also below) was inserted manually and seems to be ok. I have decnet connectivity to the target VMS 5.42 system after successfully compiling the source for dnprogs 2.20. The commands dncopy, dndir and dntype have all been successful but of course dnmount fails. > > My configuration is as follows: > RH 7.3 kernel 2.4.18-3 on an Armada E700 laptop > glibc 2.2.5 > gcc 2.96 > > My objective is to use the KDE gui to perform file housekeeping functions for an extremely user unfriendly application running on a VAX 4000 > > Can anyone shed a light on the kallsyms errors - all suggestions appreciated. > > TIA > > Mark G. > > > Error data extracted from nohup.out: > > make[1]: Entering directory `/usr/src/linux-2.4.18-3' > kallsyms pass 1 > ld -m elf_i386 -T /usr/src/linux-2.4.18-3/arch/i386/vmlinux.lds -e stext > arch/i386/kernel/head.o arch/i386/kernel/init_task.o init/main.o init/version.o > init/do_mounts.o --start-group arch/i386/kernel/kernel.o arch/i386/mm/mm.o > kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o drivers/char/char.o > drivers/block/block.o drivers/misc/misc.o drivers/net/net.o > drivers/media/media.o drivers/char/drm/drm.o drivers/net/fc/fc.o > drivers/net/appletalk/appletalk.o drivers/net/tokenring/tr.o > drivers/net/wan/wan.o drivers/atm/atm.o drivers/ide/idedriver.o > drivers/cdrom/driver.o drivers/pci/driver.o drivers/net/pcmcia/pcmcia_net.o > drivers/net/wireless/wireless_net.o drivers/pnp/pnp.o drivers/video/video.o > drivers/md/mddev.o drivers/sensors/sensor.o net/network.o abi/abi.o > /usr/src/linux-2.4.18-3/arch/i386/lib/lib.a /usr/src/linux-2.4.18-3/lib/lib.a > /usr/src/linux-2.4.18-3/arch/i386/lib/lib.a --end-group -o .tmp_vmlinux1 > fs/fs.o: In function `dap_read_inode': > fs/fs.o(.text+0x2f2f1): undefined reference to `dap_dir_operations' > fs/fs.o(.text+0x2f30f): undefined reference to `dap_file_operations' > make[1]: *** [kallsyms] Error 1 > make[1]: Leaving directory `/usr/src/linux-2.4.18-3' > make: *** [vmlinux] Error 2 > -------------------------------------------------------------------------------------------------------- > Patch problem - only the second hunk for `/include/linux/fs.h was rejected > --------------------------------------------------------------------------------------------------------- > > Compiler warning re malloc.h ------ > > make[1]: Entering directory `/usr/src/linux-2.4.18-3/fs' > make -C dapfs > make[2]: Entering directory `/usr/src/linux-2.4.18-3/fs/dapfs' > make all_targets > make[3]: Entering directory `/usr/src/linux-2.4.18-3/fs/dapfs' > cc -D__KERNEL__ -I/usr/src/linux-2.4.18-3/include -Wall -Wstrict-prototypes > -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common > -Wno-unused -pipe -mpreferred-stack-boundary=2 -march=i686 -Wno-unused > -DKBUILD_BASENAME=inode -c -o inode.o inode.c > In file included from inode.c:15: > /usr/src/linux-2.4.18-3/include/linux/malloc.h:4:2: warning: #warning > linux/malloc.h is deprecated, use linux/slab.h instead. > cc -D__KERNEL__ -I/usr/src/linux-2.4.18-3/include -Wall -Wstrict-prototypes > -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common > -Wno-unused -pipe -mpreferred-stack-boundary=2 -march=i686 -Wno-unused > -DKBUILD_BASENAME=dir -c -o dir.o dir.c > cc -D__KERNEL__ -I/usr/src/linux-2.4.18-3/include -Wall -Wstrict-prototypes > -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common > -Wno-unused -pipe -mpreferred-stack-boundary=2 -march=i686 -Wno-unused > -DKBUILD_BASENAME=file -c -o file.o file.c > cc -D__KERNEL__ -I/usr/src/linux-2.4.18-3/include -Wall -Wstrict-prototypes > -Wno-trigraphs -O2 -fomit-frame-pointer -fno-strict-aliasing -fno-common > -Wno-unused -pipe -mpreferred-stack-boundary=2 -march=i686 -Wno-unused > -DKBUILD_BASENAME=dap_functions -c -o dap_functions.o dap_functions.c > rm -f dapfs.o > ld -m elf_i386 -r -o dapfs.o inode.o dir.o file.o dap_functions.o > make[3]: Leaving directory `/usr/src/linux-2.4.18-3/fs/dapfs' > make[2]: Leaving directory `/usr/src/linux-2.4.18-3/fs/dapfs' > > > > ------------------------------------------------------- > This SF.net email is sponsored by: ValueWeb: > Dedicated Hosting for just $79/mo with 500 GB of bandwidth! > No other company gives more support or power for your dedicated server > http://click.atdmt.com/AFF/go/sdnxxaff00300020aff/direct/01/ > _______________________________________________ > Linux-decnet-user mailing list > Lin...@li... > https://lists.sourceforge.net/lists/listinfo/linux-decnet-user > |