summaryrefslogtreecommitdiffstats
path: root/net/decnet
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2001-01-31 22:22:27 +0000
committerRalf Baechle <ralf@linux-mips.org>2001-01-31 22:22:27 +0000
commit825423e4c4f18289df2393951cfd2a7a31fc0464 (patch)
tree4ad80e981c3d9effa910d2247d118d254f9a5d09 /net/decnet
parentc4693dc4856ab907a5c02187a8d398861bebfc7e (diff)
Merge with Linux 2.4.1.
Diffstat (limited to 'net/decnet')
-rw-r--r--net/decnet/Makefile2
-rw-r--r--net/decnet/TODO12
-rw-r--r--net/decnet/af_decnet.c567
-rw-r--r--net/decnet/dn_dev.c4
-rw-r--r--net/decnet/dn_fib.c6
-rw-r--r--net/decnet/dn_neigh.c168
-rw-r--r--net/decnet/dn_nsp_in.c174
-rw-r--r--net/decnet/dn_nsp_out.c304
-rw-r--r--net/decnet/dn_route.c190
-rw-r--r--net/decnet/dn_rules.c11
-rw-r--r--net/decnet/dn_table.c2
-rw-r--r--net/decnet/dn_timer.c8
12 files changed, 822 insertions, 626 deletions
diff --git a/net/decnet/Makefile b/net/decnet/Makefile
index ac7a1a462..11f7c8b08 100644
--- a/net/decnet/Makefile
+++ b/net/decnet/Makefile
@@ -11,5 +11,3 @@ obj-y += sysctl_net_decnet.o
include $(TOPDIR)/Rules.make
-tar:
- tar -cvf /dev/f1 .
diff --git a/net/decnet/TODO b/net/decnet/TODO
index 1607d6d1b..c8ea8178d 100644
--- a/net/decnet/TODO
+++ b/net/decnet/TODO
@@ -43,15 +43,15 @@ Steve's quick list of things that need finishing off:
o Hello messages should be generated for each primary address on each
interface.
- o Add more information into /proc/net/decnet and finalise the format to
- allow DECnet support in netstat.
-
- o Make sure that returned connect messages are generated when they should
- be, and that the correct error messages are sent too.
-
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
+
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index bc51b636d..b930878c2 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -35,6 +35,7 @@
* Arnaldo C. Melo: use capable, not suser
* Steve Whitehouse: Removed unused code. Fix to use sk->allocation
* when required.
+ * Patrick Caulfield: /proc/net/decnet now has object name/number
*/
@@ -128,8 +129,6 @@ Version 0.0.6 2.1.110 07-aug-98 Eduardo Marcelo Serrat
#include <net/dn_fib.h>
#include <net/dn_neigh.h>
-#define MAX(a,b) ((a)>(b)?(a):(b))
-
static void dn_keepalive(struct sock *sk);
/*
@@ -141,15 +140,15 @@ unsigned char decnet_ether_address[ETH_ALEN] = { 0xAA, 0x00, 0x04, 0x00, 0x00, 0
static struct proto_ops dn_proto_ops;
rwlock_t dn_hash_lock = RW_LOCK_UNLOCKED;
-static struct sock *dn_sklist = NULL;
-static struct sock *dn_wild_sk = NULL;
+static struct sock *dn_sklist;
+static struct sock *dn_wild_sk;
static int __dn_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen, int flags);
static int __dn_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen, int flags);
static struct sock **dn_find_list(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
if (scp->addr.sdn_flags & SDF_WILD)
return dn_wild_sk ? NULL : &dn_wild_sk;
@@ -159,7 +158,7 @@ static struct sock **dn_find_list(struct sock *sk)
static unsigned short port_alloc(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
static unsigned short port = 0x2000;
if (port == 0)
@@ -177,12 +176,17 @@ static unsigned short port = 0x2000;
*/
static int dn_hash_sock(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
struct sock **skp;
int rv = -EUSERS;
- write_lock_bh(&dn_hash_lock);
+ if (sk->next)
+ BUG();
+ if (sk->pprev)
+ BUG();
+ write_lock_bh(&dn_hash_lock);
+
if (!scp->addrloc && !port_alloc(sk))
goto out;
@@ -327,7 +331,7 @@ struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr)
read_lock(&dn_hash_lock);
for(sk = dn_sklist; sk != NULL; sk = sk->next) {
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
if (sk->state != TCP_LISTEN)
continue;
if (scp->addr.sdn_objnum) {
@@ -355,13 +359,13 @@ struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr)
struct sock *dn_find_by_skb(struct sk_buff *skb)
{
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
struct sock *sk;
struct dn_scp *scp;
read_lock(&dn_hash_lock);
for(sk = dn_sklist; sk != NULL; sk = sk->next) {
- scp = &sk->protinfo.dn;
+ scp = DN_SK(sk);
if (cb->src != dn_saddr2dn(&scp->peer))
continue;
if (cb->dst_port != scp->addrloc)
@@ -383,7 +387,7 @@ struct sock *dn_find_by_skb(struct sk_buff *skb)
static void dn_destruct(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
skb_queue_purge(&scp->data_xmit_queue);
skb_queue_purge(&scp->other_xmit_queue);
@@ -394,25 +398,26 @@ static void dn_destruct(struct sock *sk)
MOD_DEC_USE_COUNT;
}
-struct sock *dn_alloc_sock(struct socket *sock, int flags)
+struct sock *dn_alloc_sock(struct socket *sock, int gfp)
{
struct sock *sk;
struct dn_scp *scp;
- if ((sk = sk_alloc(PF_DECnet, flags, 1)) == NULL)
+ if ((sk = sk_alloc(PF_DECnet, gfp, 1)) == NULL)
goto no_sock;
if (sock) {
sock->ops = &dn_proto_ops;
}
sock_init_data(sock,sk);
- scp = &sk->protinfo.dn;
+ scp = DN_SK(sk);
sk->backlog_rcv = dn_nsp_backlog_rcv;
sk->destruct = dn_destruct;
sk->no_check = 1;
sk->family = PF_DECnet;
sk->protocol = 0;
+ sk->allocation = gfp;
/* Initialization of DECnet Session Control Port */
scp->state = DN_O; /* Open */
@@ -424,13 +429,25 @@ struct sock *dn_alloc_sock(struct socket *sock, int flags)
scp->ackrcv_oth = 0; /* Last oth data ack rec*/
scp->flowrem_sw = DN_SEND;
scp->flowloc_sw = DN_SEND;
+ scp->flowrem_dat = 0;
+ scp->flowrem_oth = 1;
+ scp->flowloc_dat = 0;
+ scp->flowloc_oth = 1;
+ scp->services_rem = 0;
+ 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->nonagle = 0;
+ scp->multi_ireq = 1;
scp->accept_mode = ACC_IMMED;
scp->addr.sdn_family = AF_DECnet;
scp->peer.sdn_family = AF_DECnet;
scp->accessdata.acc_accl = 5;
memcpy(scp->accessdata.acc_acc, "LINUX", 5);
- scp->mss = 1460;
+ scp->max_window = NSP_MAX_WINDOW;
scp->snd_window = NSP_MIN_WINDOW;
scp->nsp_srtt = NSP_INITIAL_SRTT;
scp->nsp_rttvar = NSP_INITIAL_RTTVAR;
@@ -464,7 +481,7 @@ no_sock:
*/
static void dn_keepalive(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
/*
* By checking the other_data transmit queue is empty
@@ -472,7 +489,7 @@ static void dn_keepalive(struct sock *sk)
* many of these keepalive frames.
*/
if (skb_queue_len(&scp->other_xmit_queue) == 0)
- dn_nsp_send_lnk(sk, DN_NOCHANGE);
+ dn_nsp_send_link(sk, DN_NOCHANGE, 0);
}
@@ -485,7 +502,7 @@ static void dn_keepalive(struct sock *sk)
*/
int dn_destroy_timer(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
scp->persist = dn_nsp_persist(sk);
@@ -527,7 +544,7 @@ int dn_destroy_timer(struct sock *sk)
static void dn_destroy_sock(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
scp->nsp_rxtshift = 0; /* reset back off */
@@ -674,7 +691,7 @@ dn_release(struct socket *sock)
static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct sock *sk = sock->sk;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
struct sockaddr_dn *saddr = (struct sockaddr_dn *)uaddr;
struct net_device *dev;
int rv;
@@ -722,11 +739,8 @@ static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
memcpy(&scp->addr, saddr, addr_len);
sk->zapped = 0;
- if ((rv = dn_hash_sock(sk)) == 0)
- goto out;
-
- sk->zapped = 1;
-out:
+ if ((rv = dn_hash_sock(sk)) != 0)
+ sk->zapped = 1;
return rv;
}
@@ -735,7 +749,7 @@ out:
static int dn_auto_bind(struct socket *sock)
{
struct sock *sk = sock->sk;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
sk->zapped = 0;
@@ -769,7 +783,7 @@ static int dn_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len,
{
struct sockaddr_dn *addr = (struct sockaddr_dn *)uaddr;
struct sock *sk = sock->sk;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
int err = -EISCONN;
lock_sock(sk);
@@ -788,7 +802,7 @@ static int dn_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len,
}
err = -EINVAL;
- if (sk->protinfo.dn.state != DN_O)
+ if (DN_SK(sk)->state != DN_O)
goto out;
if (addr_len != sizeof(struct sockaddr_dn))
@@ -812,7 +826,7 @@ static int dn_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len,
sk->state = TCP_SYN_SENT;
sock->state = SS_CONNECTING;
- sk->protinfo.dn.state = DN_CI;
+ DN_SK(sk)->state = DN_CI;
dn_nsp_send_conninit(sk, NSP_CI);
@@ -853,7 +867,7 @@ out:
return err;
}
-static int dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc)
+static void dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc)
{
unsigned char *ptr = skb->data;
@@ -870,10 +884,9 @@ static int dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc)
skb_pull(skb, acc->acc_accl + acc->acc_passl + acc->acc_userl + 3);
- return 0;
}
-static int dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt)
+static void dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt)
{
unsigned char *ptr = skb->data;
@@ -882,7 +895,6 @@ static int dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt)
memcpy(opt->opt_data, ptr, opt->opt_optl);
skb_pull(skb, opt->opt_optl + 1);
- return 0;
}
@@ -910,7 +922,7 @@ static int dn_wait_accept(struct socket *sock, int flags)
return -ERESTARTSYS; /* But of course you don't! */
}
- if ((sk->protinfo.dn.state != DN_RUN) && (sk->protinfo.dn.state != DN_DRC)) {
+ if ((DN_SK(sk)->state != DN_RUN) && (DN_SK(sk)->state != DN_DRC)) {
sock->state = SS_UNCONNECTED;
return sock_error(sk);
}
@@ -937,7 +949,7 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
return -EINVAL;
}
- if (sk->protinfo.dn.state != DN_O) {
+ if (DN_SK(sk)->state != DN_O) {
release_sock(sk);
return -EINVAL;
}
@@ -967,7 +979,7 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
}
} while (skb == NULL);
- cb = (struct dn_skb_cb *)skb->cb;
+ cb = DN_SKB_CB(skb);
if ((newsk = dn_alloc_sock(newsock, sk->allocation)) == NULL) {
release_sock(sk);
@@ -980,50 +992,52 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
dst_release(xchg(&newsk->dst_cache, skb->dst));
skb->dst = NULL;
- newsk->protinfo.dn.state = DN_CR;
- newsk->protinfo.dn.addrrem = cb->src_port;
- newsk->protinfo.dn.mss = cb->segsize;
- newsk->protinfo.dn.accept_mode = sk->protinfo.dn.accept_mode;
+ DN_SK(newsk)->state = DN_CR;
+ DN_SK(newsk)->addrrem = cb->src_port;
+ DN_SK(newsk)->services_rem = cb->services;
+ DN_SK(newsk)->info_rem = cb->info;
+ DN_SK(newsk)->segsize_rem = cb->segsize;
+ DN_SK(newsk)->accept_mode = DN_SK(sk)->accept_mode;
- if (newsk->protinfo.dn.mss < 230)
- newsk->protinfo.dn.mss = 230;
+ if (DN_SK(newsk)->segsize_rem < 230)
+ DN_SK(newsk)->segsize_rem = 230;
newsk->state = TCP_LISTEN;
newsk->zapped = 0;
- memcpy(&newsk->protinfo.dn.addr, &sk->protinfo.dn.addr, sizeof(struct sockaddr_dn));
+ memcpy(&(DN_SK(newsk)->addr), &(DN_SK(sk)->addr), sizeof(struct sockaddr_dn));
/*
* If we are listening on a wild socket, we don't want
* the newly created socket on the wrong hash queue.
*/
- newsk->protinfo.dn.addr.sdn_flags &= ~SDF_WILD;
+ DN_SK(newsk)->addr.sdn_flags &= ~SDF_WILD;
- skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &newsk->protinfo.dn.addr, &type));
- skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &newsk->protinfo.dn.peer, &type));
- *(dn_address *)newsk->protinfo.dn.peer.sdn_add.a_addr = cb->src;
- *(dn_address *)newsk->protinfo.dn.addr.sdn_add.a_addr = cb->dst;
+ skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->addr), &type));
+ skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->peer), &type));
+ *(dn_address *)(DN_SK(newsk)->peer.sdn_add.a_addr) = cb->src;
+ *(dn_address *)(DN_SK(newsk)->addr.sdn_add.a_addr) = cb->dst;
menuver = *skb->data;
skb_pull(skb, 1);
if (menuver & DN_MENUVER_ACC)
- dn_access_copy(skb, &newsk->protinfo.dn.accessdata);
+ dn_access_copy(skb, &(DN_SK(newsk)->accessdata));
if (menuver & DN_MENUVER_USR)
- dn_user_copy(skb, &newsk->protinfo.dn.conndata_in);
+ dn_user_copy(skb, &(DN_SK(newsk)->conndata_in));
if (menuver & DN_MENUVER_PRX)
- newsk->protinfo.dn.peer.sdn_flags |= SDF_PROXY;
+ DN_SK(newsk)->peer.sdn_flags |= SDF_PROXY;
if (menuver & DN_MENUVER_UIC)
- newsk->protinfo.dn.peer.sdn_flags |= SDF_UICPROXY;
+ DN_SK(newsk)->peer.sdn_flags |= SDF_UICPROXY;
kfree_skb(skb);
- memcpy(&newsk->protinfo.dn.conndata_out, &sk->protinfo.dn.conndata_out,
+ memcpy(&(DN_SK(newsk)->conndata_out), &(DN_SK(sk)->conndata_out),
sizeof(struct optdata_dn));
- memcpy(&newsk->protinfo.dn.discdata_out, &sk->protinfo.dn.discdata_out,
+ memcpy(&(DN_SK(newsk)->discdata_out), &(DN_SK(sk)->discdata_out),
sizeof(struct optdata_dn));
lock_sock(newsk);
@@ -1031,9 +1045,13 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
dn_send_conn_ack(newsk);
- if (newsk->protinfo.dn.accept_mode == ACC_IMMED) {
- newsk->protinfo.dn.state = DN_CC;
- dn_send_conn_conf(newsk, newsk->allocation);
+ /*
+ * Here we use sk->allocation since although the conn conf is
+ * for the newsk, the context is the old socket.
+ */
+ if (DN_SK(newsk)->accept_mode == ACC_IMMED) {
+ DN_SK(newsk)->state = DN_CC;
+ dn_send_conn_conf(newsk, sk->allocation);
err = dn_wait_accept(newsock, flags);
}
@@ -1046,7 +1064,7 @@ static int dn_getname(struct socket *sock, struct sockaddr *uaddr,int *uaddr_len
{
struct sockaddr_dn *sa = (struct sockaddr_dn *)uaddr;
struct sock *sk = sock->sk;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
*uaddr_len = sizeof(struct sockaddr_dn);
@@ -1070,7 +1088,7 @@ static int dn_getname(struct socket *sock, struct sockaddr *uaddr,int *uaddr_len
static unsigned int dn_poll(struct file *file, struct socket *sock, poll_table *wait)
{
struct sock *sk = sock->sk;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
int mask = datagram_poll(file, sock, wait);
if (skb_queue_len(&scp->other_receive_queue))
@@ -1082,100 +1100,32 @@ static unsigned int dn_poll(struct file *file, struct socket *sock, poll_table
static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
int err = -EOPNOTSUPP;
unsigned long amount = 0;
struct sk_buff *skb;
+ int val;
-#if 0
- struct dn_naddr dnaddr;
-#endif
switch(cmd)
{
case SIOCGIFADDR:
case SIOCSIFADDR:
return dn_dev_ioctl(cmd, (void *)arg);
+ case SIOCATMARK:
+ lock_sock(sk);
+ val = (skb_queue_len(&scp->other_receive_queue) != 0);
+ if (scp->state != DN_RUN)
+ val = -ENOTCONN;
+ release_sock(sk);
+ return val;
+
#ifdef CONFIG_DECNET_ROUTER
case SIOCADDRT:
case SIOCDELRT:
return dn_fib_ioctl(sock, cmd, arg);
#endif /* CONFIG_DECNET_ROUTER */
-#if 0
- case SIOCSIFADDR:
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
-
- if ((err = copy_from_user(devname, ioarg->devname, 5)) != 0)
- break;
- if ((err = copy_from_user(addr, ioarg->exec_addr, 6)) != 0)
- break;
- if ((dev = dev_get(devname)) == NULL) {
- err = -ENODEV;
- break;
- }
- if (dev->dn_ptr == NULL) {
- err = -ENODEV;
- break;
- }
-
- dn_dev_devices_off();
-
- decnet_default_device = dev;
- memcpy(decnet_ether_address, addr, ETH_ALEN);
- decnet_address = dn_htons(dn_eth2dn(decnet_ether_address));
-
- dn_dev_devices_on();
-
- break;
-
- case SIOCGIFADDR:
- if (decnet_default_device)
- strcpy(devname, decnet_default_device->name);
- else
- memset(devname, 0, 6);
-
- if ((err = copy_to_user(ioarg->devname, devname, 5)) != 0)
- break;
-
- if ((err = copy_to_user(ioarg->exec_addr, decnet_ether_address, 6)) != 0)
- break;
-
- break;
-#endif
-
-#if 0
- case SIOCSNETADDR:
- if (!capable(CAP_NET_ADMIN)) {
- err = -EPERM;
- break;
- }
-
- if ((err = copy_from_user(&dnaddr, (void *)arg, sizeof(struct dn_naddr))) != 0)
- break;
-
- if (dnaddr.a_len != ETH_ALEN) {
- err = -EINVAL;
- break;
- }
-
- dn_dev_devices_off();
-
- memcpy(decnet_ether_address, dnaddr.a_addr, ETH_ALEN);
- decnet_address = dn_htons(dn_eth2dn(decnet_ether_address));
-
- dn_dev_devices_on();
- break;
-
- case SIOCGNETADDR:
- dnaddr.a_len = ETH_ALEN;
- memcpy(dnaddr.a_addr, decnet_ether_address, ETH_ALEN);
-
- if ((err = copy_to_user((void *)arg, &dnaddr, sizeof(struct dn_naddr))) != 0)
- break;
-
- break;
-#endif
case OSIOCSNETADDR:
if (!capable(CAP_NET_ADMIN)) {
err = -EPERM;
@@ -1237,7 +1187,7 @@ static int dn_listen(struct socket *sock, int backlog)
if (sk->zapped)
goto out;
- if ((sk->protinfo.dn.state != DN_O) || (sk->state == TCP_LISTEN))
+ if ((DN_SK(sk)->state != DN_O) || (sk->state == TCP_LISTEN))
goto out;
sk->max_ack_backlog = backlog;
@@ -1255,7 +1205,7 @@ out:
static int dn_shutdown(struct socket *sock, int how)
{
struct sock *sk = sock->sk;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
int err = -ENOTCONN;
lock_sock(sk);
@@ -1300,14 +1250,27 @@ static int dn_setsockopt(struct socket *sock, int level, int optname, char *optv
static int __dn_setsockopt(struct socket *sock, int level,int optname, char *optval, int optlen, int flags)
{
struct sock *sk = sock->sk;
- struct dn_scp *scp = &sk->protinfo.dn;
- struct optdata_dn opt;
- struct accessdata_dn acc;
+ struct dn_scp *scp = DN_SK(sk);
+ union {
+ struct optdata_dn opt;
+ struct accessdata_dn acc;
+ int mode;
+ unsigned long win;
+ int val;
+ unsigned char services;
+ unsigned char info;
+ } u;
int err;
if (optlen && !optval)
return -EINVAL;
+ if (optlen > sizeof(u))
+ return -EINVAL;
+
+ if (copy_from_user(&u, optval, optlen))
+ return -EFAULT;
+
switch(optname) {
case DSO_CONDATA:
if (sock->state == SS_CONNECTED)
@@ -1318,29 +1281,23 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt
if (optlen != sizeof(struct optdata_dn))
return -EINVAL;
- if (copy_from_user(&opt, optval, optlen))
- return -EFAULT;
-
- if (opt.opt_optl > 16)
+ if (u.opt.opt_optl > 16)
return -EINVAL;
- memcpy(&scp->conndata_out, &opt, sizeof(struct optdata_dn));
+ memcpy(&scp->conndata_out, &u.opt, optlen);
break;
case DSO_DISDATA:
- if (sock->state != SS_CONNECTED && sk->protinfo.dn.accept_mode == ACC_IMMED)
+ if (sock->state != SS_CONNECTED && scp->accept_mode == ACC_IMMED)
return -ENOTCONN;
if (optlen != sizeof(struct optdata_dn))
return -EINVAL;
- if (copy_from_user(&opt, optval, sizeof(struct optdata_dn)))
- return -EFAULT;
-
- if (opt.opt_optl > 16)
+ if (u.opt.opt_optl > 16)
return -EINVAL;
- memcpy(&scp->discdata_out, &opt, sizeof(struct optdata_dn));
+ memcpy(&scp->discdata_out, &u.opt, optlen);
break;
case DSO_CONACCESS:
@@ -1352,15 +1309,12 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt
if (optlen != sizeof(struct accessdata_dn))
return -EINVAL;
- if (copy_from_user(&acc, optval, sizeof(struct accessdata_dn)))
- return -EFAULT;
-
- if ((acc.acc_accl > DN_MAXACCL) ||
- (acc.acc_passl > DN_MAXACCL) ||
- (acc.acc_userl > DN_MAXACCL))
+ if ((u.acc.acc_accl > DN_MAXACCL) ||
+ (u.acc.acc_passl > DN_MAXACCL) ||
+ (u.acc.acc_userl > DN_MAXACCL))
return -EINVAL;
- memcpy(&scp->accessdata, &acc, sizeof(struct accessdata_dn));
+ memcpy(&scp->accessdata, &u.acc, optlen);
break;
case DSO_ACCEPTMODE:
@@ -1372,16 +1326,10 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt
if (optlen != sizeof(int))
return -EINVAL;
- {
- int mode;
-
- if (get_user(mode, optval))
- return -EFAULT;
- if ((mode != ACC_IMMED) && (mode != ACC_DEFER))
- return -EINVAL;
+ if ((u.mode != ACC_IMMED) && (u.mode != ACC_DEFER))
+ return -EINVAL;
- scp->accept_mode = (unsigned char)mode;
- }
+ scp->accept_mode = (unsigned char)u.mode;
break;
case DSO_CONACCEPT:
@@ -1411,8 +1359,55 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt
case DSO_LINKINFO:
case DSO_STREAM:
case DSO_SEQPACKET:
-
return -ENOPROTOOPT;
+
+ case DSO_MAXWINDOW:
+ if (optlen != sizeof(unsigned long))
+ return -EINVAL;
+ if (u.win > NSP_MAX_WINDOW)
+ u.win = NSP_MAX_WINDOW;
+ if (u.win == 0)
+ return -EINVAL;
+ scp->max_window = u.win;
+ if (scp->snd_window > u.win)
+ scp->snd_window = u.win;
+ break;
+
+ case DSO_NODELAY:
+ if (optlen != sizeof(int))
+ return -EINVAL;
+ if (scp->nonagle == 2)
+ return -EINVAL;
+ scp->nonagle = (u.val == 0) ? 0 : 1;
+ /* if (scp->nonagle == 1) { Push pending frames } */
+ break;
+
+ case DSO_CORK:
+ if (optlen != sizeof(int))
+ return -EINVAL;
+ if (scp->nonagle == 1)
+ return -EINVAL;
+ scp->nonagle = (u.val == 0) ? 0 : 2;
+ /* if (scp->nonagle == 0) { Push pending frames } */
+ break;
+
+ case DSO_SERVICES:
+ if (optlen != sizeof(unsigned char))
+ return -EINVAL;
+ if ((u.services & ~NSP_FC_MASK) != 0x01)
+ return -EINVAL;
+ if ((u.services & NSP_FC_MASK) == NSP_FC_MASK)
+ return -EINVAL;
+ scp->services_loc = u.services;
+ break;
+
+ case DSO_INFO:
+ if (optlen != sizeof(unsigned char))
+ return -EINVAL;
+ if (u.info & 0xfc)
+ return -EINVAL;
+ scp->info_loc = u.info;
+ break;
}
return 0;
@@ -1433,44 +1428,40 @@ static int dn_getsockopt(struct socket *sock, int level, int optname, char *optv
static int __dn_getsockopt(struct socket *sock, int level,int optname, char *optval,int *optlen, int flags)
{
struct sock *sk = sock->sk;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
struct linkinfo_dn link;
- int mode = scp->accept_mode;
+ int r_len = *optlen;
+ void *r_data = NULL;
+ int val;
switch(optname) {
case DSO_CONDATA:
- if (*optlen != sizeof(struct optdata_dn))
- return -EINVAL;
-
- if (copy_to_user(optval, &scp->conndata_in, sizeof(struct optdata_dn)))
- return -EFAULT;
+ if (r_len > sizeof(struct optdata_dn))
+ r_len = sizeof(struct optdata_dn);
+ r_data = &scp->conndata_in;
break;
case DSO_DISDATA:
- if (*optlen != sizeof(struct optdata_dn))
- return -EINVAL;
-
- if (copy_to_user(optval, &scp->discdata_in, sizeof(struct optdata_dn)))
- return -EFAULT;
-
+ if (r_len > sizeof(struct optdata_dn))
+ r_len = sizeof(struct optdata_dn);
+ r_data = &scp->discdata_in;
break;
case DSO_CONACCESS:
- if (*optlen != sizeof(struct accessdata_dn))
- return -EINVAL;
-
- if (copy_to_user(optval, &scp->accessdata, sizeof(struct accessdata_dn)))
- return -EFAULT;
+ if (r_len > sizeof(struct accessdata_dn))
+ r_len = sizeof(struct accessdata_dn);
+ r_data = &scp->accessdata;
break;
case DSO_ACCEPTMODE:
- if (put_user(mode, optval))
- return -EFAULT;
+ if (r_len > sizeof(unsigned char))
+ r_len = sizeof(unsigned char);
+ r_data = &scp->accept_mode;
break;
case DSO_LINKINFO:
- if (*optlen != sizeof(struct linkinfo_dn))
- return -EINVAL;
+ if (r_len > sizeof(struct linkinfo_dn))
+ r_len = sizeof(struct linkinfo_dn);
switch(sock->state) {
case SS_CONNECTING:
@@ -1486,10 +1477,8 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char *opt
link.idn_linkstate = LL_INACTIVE;
}
- link.idn_segsize = scp->mss;
-
- if (copy_to_user(optval, &link, sizeof(struct linkinfo_dn)))
- return -EFAULT;
+ link.idn_segsize = scp->segsize_rem;
+ r_data = &link;
break;
default:
@@ -1508,6 +1497,45 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char *opt
case DSO_CONACCEPT:
case DSO_CONREJECT:
return -ENOPROTOOPT;
+
+ case DSO_MAXWINDOW:
+ if (r_len > sizeof(unsigned long))
+ r_len = sizeof(unsigned long);
+ r_data = &scp->max_window;
+ break;
+
+ case DSO_NODELAY:
+ if (r_len > sizeof(int))
+ r_len = sizeof(int);
+ val = (scp->nonagle == 1);
+ r_data = &val;
+ break;
+
+ case DSO_CORK:
+ if (r_len > sizeof(int))
+ r_len = sizeof(int);
+ val = (scp->nonagle == 2);
+ r_data = &val;
+ break;
+
+ case DSO_SERVICES:
+ if (r_len > sizeof(unsigned char))
+ r_len = sizeof(unsigned char);
+ r_data = &scp->services_rem;
+ break;
+
+ case DSO_INFO:
+ if (r_len > sizeof(unsigned char))
+ r_len = sizeof(unsigned char);
+ r_data = &scp->info_rem;
+ break;
+ }
+
+ if (r_data) {
+ if (copy_to_user(optval, r_data, r_len))
+ return -EFAULT;
+ if (put_user(r_len, optlen))
+ return -EFAULT;
}
return 0;
@@ -1520,7 +1548,7 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char *opt
*/
static int dn_wait_run(struct sock *sk, int flags)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
int err = 0;
switch(scp->state) {
@@ -1572,7 +1600,7 @@ static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, int
return skb_queue_len(q) ? 1 : 0;
while(skb != (struct sk_buff *)q) {
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
len += skb->len;
if (cb->nsp_flags & 0x40) {
@@ -1599,7 +1627,7 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, int size,
int flags, struct scm_cookie *scm)
{
struct sock *sk = sock->sk;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
struct sk_buff_head *queue = &sk->receive_queue;
int target = size > 1 ? 1 : 0;
int copied = 0;
@@ -1681,7 +1709,7 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, int size,
for(skb = queue->next; skb != (struct sk_buff *)queue; skb = nskb) {
int chunk = skb->len;
- cb = (struct dn_skb_cb *)skb->cb;
+ cb = DN_SKB_CB(skb);
if ((chunk + copied) > size)
chunk = size - copied;
@@ -1693,7 +1721,7 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, int size,
copied += chunk;
if (!(flags & MSG_PEEK))
- skb->len -= chunk;
+ skb_pull(skb, chunk);
eor = cb->nsp_flags & 0x40;
nskb = skb->next;
@@ -1707,7 +1735,7 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, int size,
*/
if ((scp->flowloc_sw == DN_DONTSEND) && !dn_congested(sk)) {
scp->flowloc_sw = DN_SEND;
- dn_nsp_send_lnk(sk, DN_SEND);
+ dn_nsp_send_link(sk, DN_SEND, 0);
}
}
@@ -1727,6 +1755,7 @@ static int dn_recvmsg(struct socket *sock, struct msghdr *msg, int size,
rv = copied;
+
if (eor && (sk->type == SOCK_SEQPACKET))
msg->msg_flags |= MSG_EOR;
@@ -1745,16 +1774,31 @@ out:
}
+static inline int dn_queue_too_long(struct dn_scp *scp, struct sk_buff_head *queue, int flags)
+{
+ unsigned char fctype = scp->services_rem & NSP_FC_MASK;
+ if (skb_queue_len(queue) >= scp->snd_window)
+ return 1;
+ if (fctype != NSP_FC_NONE) {
+ if (flags & MSG_OOB) {
+ if (scp->flowrem_oth == 0)
+ return 1;
+ } else {
+ if (scp->flowrem_dat == 0)
+ return 1;
+ }
+ }
+ return 0;
+}
+
static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size,
struct scm_cookie *scm)
{
struct sock *sk = sock->sk;
- struct dn_scp *scp = &sk->protinfo.dn;
- int mss = scp->mss;
- int mtu = 230 - 11; /* maximum value thats always safe */
+ struct dn_scp *scp = DN_SK(sk);
+ int mss;
struct sk_buff_head *queue = &scp->data_xmit_queue;
int flags = msg->msg_flags;
- unsigned short numseg = 0;
int err = 0;
int sent = 0;
int addr_len = msg->msg_namelen;
@@ -1765,6 +1809,7 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size,
unsigned char *ptr;
unsigned short ack;
int len;
+ unsigned char fctype;
if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR))
return -EOPNOTSUPP;
@@ -1801,16 +1846,19 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size,
if ((flags & MSG_TRYHARD) && sk->dst_cache)
dst_negative_advice(&sk->dst_cache);
+ 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 > 230)
- mtu = dn->blksize - 11;
+ if (dn->blksize < (mss + 11))
+ mss = dn->blksize - 11;
}
/*
* The only difference between SEQPACKET & STREAM sockets under DECnet
- * AFAIK is that SEQPACKET sockets set the MSG_EOR flag for the last
- * session control message segment.
+ * is that SEQPACKET sockets set the MSG_EOR flag for the last
+ * session control message segment.
*/
if (flags & MSG_OOB) {
@@ -1822,9 +1870,6 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size,
}
}
- if (mss < mtu)
- mtu = mss;
-
scp->persist_fxn = dn_nsp_xmit_timeout;
while(sent < size) {
@@ -1842,14 +1887,14 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size,
*/
len = size - sent;
- if (len > mtu)
- len = mtu;
+ if (len > mss)
+ len = mss;
/*
* Wait for queue size to go down below the window
* size.
*/
- if (skb_queue_len(queue) >= scp->snd_window) {
+ if (dn_queue_too_long(scp, queue, flags)) {
if (flags & MSG_DONTWAIT) {
err = -EWOULDBLOCK;
goto out;
@@ -1857,7 +1902,7 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size,
SOCK_SLEEP_PRE(sk)
- if (skb_queue_len(queue) >= scp->snd_window)
+ if (dn_queue_too_long(scp, queue, flags))
schedule();
SOCK_SLEEP_POST(sk)
@@ -1876,7 +1921,7 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size,
if (!skb)
continue;
- cb = (struct dn_skb_cb *)skb->cb;
+ cb = DN_SKB_CB(skb);
ptr = skb_put(skb, 9);
@@ -1886,26 +1931,34 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size,
}
if (flags & MSG_OOB) {
- cb->segnum = scp->numoth++;
- scp->numoth &= 0x0fff;
+ cb->segnum = scp->numoth;
+ seq_add(&scp->numoth, 1);
msgflg = 0x30;
- ack = scp->ackxmt_oth | 0x8000;
+ ack = (scp->numoth_rcv & 0x0FFF) | 0x8000;
+ scp->ackxmt_oth = scp->numoth_rcv;
+ if (fctype != NSP_FC_NONE)
+ scp->flowrem_oth--;
} else {
- cb->segnum = scp->numdat++;
- scp->numdat &= 0x0fff;
+ cb->segnum = scp->numdat;
+ seq_add(&scp->numdat, 1);
msgflg = 0x00;
if (sock->type == SOCK_STREAM)
msgflg = 0x60;
- if (scp->seg_size == 0)
+ if (scp->seg_total == 0)
msgflg |= 0x20;
- scp->seg_size += len;
+ scp->seg_total += len;
if (((sent + len) == size) && (flags & MSG_EOR)) {
msgflg |= 0x40;
- scp->seg_size = 0;
+ scp->seg_total = 0;
+ if (fctype == NSP_FC_SCMC)
+ scp->flowrem_dat--;
}
- ack = scp->ackxmt_dat | 0x8000;
+ ack = (scp->numdat_rcv & 0x0FFF) | 0x8000;
+ scp->ackxmt_dat = scp->numdat_rcv;
+ if (fctype == NSP_FC_SRC)
+ scp->flowrem_dat--;
}
*ptr++ = msgflg;
@@ -1918,8 +1971,7 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size,
*(__u16 *)ptr = dn_htons(cb->segnum);
sent += len;
- dn_nsp_queue_xmit(sk, skb, flags & MSG_OOB);
- numseg++;
+ dn_nsp_queue_xmit(sk, skb, sk->allocation, flags & MSG_OOB);
skb = NULL;
scp->persist = dn_nsp_persist(sk);
@@ -1955,21 +2007,38 @@ static int dn_device_event(struct notifier_block *this, unsigned long event,
}
static struct notifier_block dn_dev_notifier = {
- dn_device_event,
- 0
+ notifier_call: dn_device_event,
};
extern int dn_route_rcv(struct sk_buff *, struct net_device *, struct packet_type *);
-static struct packet_type dn_dix_packet_type =
-{
- __constant_htons(ETH_P_DNA_RT),
- NULL, /* All devices */
- dn_route_rcv,
- (void*)1,
- NULL,
+static struct packet_type dn_dix_packet_type = {
+ type: __constant_htons(ETH_P_DNA_RT),
+ dev: NULL, /* All devices */
+ func: dn_route_rcv,
+ data: (void*)1,
};
+#define IS_NOT_PRINTABLE(x) ((x) < 32 || (x) > 126)
+
+static void dn_printable_object(struct sockaddr_dn *dn, unsigned char *buf)
+{
+ int i;
+
+ switch (dn_ntohs(dn->sdn_objnamel)) {
+ case 0:
+ sprintf(buf, "%d", dn->sdn_objnum);
+ break;
+ default:
+ for (i = 0; i < dn_ntohs(dn->sdn_objnamel); i++) {
+ buf[i] = dn->sdn_objname[i];
+ if (IS_NOT_PRINTABLE(buf[i]))
+ buf[i] = '.';
+ }
+ buf[i] = 0;
+ }
+}
+
static int dn_get_info(char *buffer, char **start, off_t offset, int length)
{
struct sock *sk;
@@ -1979,15 +2048,20 @@ static int dn_get_info(char *buffer, char **start, off_t offset, int length)
off_t begin = 0;
char buf1[DN_ASCBUF_LEN];
char buf2[DN_ASCBUF_LEN];
+ char local_object[DN_MAXOBJL+3];
+ char remote_object[DN_MAXOBJL+3];
- len += sprintf(buffer + len, "Local Remote\n");
+ len += sprintf(buffer + len, "Local Remote\n");
read_lock(&dn_hash_lock);
for(sk = dn_sklist; sk != NULL; sk = sk->next) {
- scp = &sk->protinfo.dn;
+ 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 %6s/%04X %04d:%04d %04d:%04d %01d %4s %s\n",
+ "%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,
@@ -1995,6 +2069,7 @@ static int dn_get_info(char *buffer, char **start, off_t offset, int length)
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,
@@ -2002,6 +2077,7 @@ static int dn_get_info(char *buffer, char **start, off_t offset, int length)
scp->ackrcv_dat,
scp->ackrcv_oth,
scp->flowrem_sw,
+ remote_object,
dn_state2asc(scp->state),
((scp->accept_mode == ACC_IMMED) ? "IMMED" : "DEFER"));
@@ -2026,8 +2102,8 @@ static int dn_get_info(char *buffer, char **start, off_t offset, int length)
static struct net_proto_family dn_family_ops = {
- AF_DECnet,
- dn_create
+ family: AF_DECnet,
+ create: dn_create,
};
static struct proto_ops dn_proto_ops = {
@@ -2067,6 +2143,7 @@ MODULE_PARM(addr, "2i");
MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node");
#endif
+static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.4.0-test12s (C) 1995-2000 Linux DECnet Project Team\n";
static int __init decnet_init(void)
{
@@ -2085,7 +2162,7 @@ static int __init decnet_init(void)
dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address));
#endif
- printk(KERN_INFO "NET4: DECnet for Linux: V.2.4.0-test10s (C) 1995-2000 Linux DECnet Project Team\n");
+ printk(banner);
sock_register(&dn_family_ops);
dev_add_pack(&dn_dix_packet_type);
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index d8f91ac38..056eaa043 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -52,7 +52,7 @@ static unsigned char dn_eco_version[3] = {0x02,0x00,0x00};
extern struct neigh_table dn_neigh_table;
-struct net_device *decnet_default_device = NULL;
+struct net_device *decnet_default_device;
static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
static void dn_dev_delete(struct net_device *dev);
@@ -1286,9 +1286,7 @@ void __exit dn_dev_cleanup(void)
}
#endif /* CONFIG_SYSCTL */
-#ifdef CONFIG_PROC_FS
proc_net_remove("decnet_dev");
-#endif /* CONFIG_PROC_FS */
dn_dev_devices_off();
}
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
index aff2dc05d..f82e26406 100644
--- a/net/decnet/dn_fib.c
+++ b/net/decnet/dn_fib.c
@@ -55,7 +55,7 @@ extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
#endif /* CONFIG_RTNETLINK */
-static struct dn_fib_info *dn_fib_info_list = NULL;
+static struct dn_fib_info *dn_fib_info_list;
static rwlock_t dn_fib_info_lock = RW_LOCK_UNLOCKED;
int dn_fib_info_cnt;
@@ -641,15 +641,11 @@ static int decnet_rt_get_info(char *buffer, char **start, off_t offset, int leng
return 0;
}
-
#endif /* CONFIG_PROC_FS */
-
void __exit dn_fib_cleanup(void)
{
-#ifdef CONFIG_PROC_FS
proc_net_remove("decnet_route");
-#endif
dn_fib_table_cleanup();
dn_fib_rules_cleanup();
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 00c27cdec..f25f37275 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -18,6 +18,8 @@
* forwarding now stands a good chance of
* working.
* Steve Whitehouse : Fixed neighbour states (for now anyway).
+ * Steve Whitehouse : Made error_report functions dummies. This
+ * is not the right place to return skbs.
*
*/
@@ -52,81 +54,66 @@ static int dn_phase3_output(struct sk_buff *);
* For talking to broadcast devices: Ethernet & PPP
*/
static struct neigh_ops dn_long_ops = {
- AF_DECnet,
- NULL,
- NULL,
- dn_long_error_report,
- dn_long_output,
- dn_long_output,
- dev_queue_xmit,
- dev_queue_xmit
+ family: AF_DECnet,
+ error_report: dn_long_error_report,
+ output: dn_long_output,
+ connected_output: dn_long_output,
+ hh_output: dev_queue_xmit,
+ queue_xmit: dev_queue_xmit,
};
/*
* For talking to pointopoint and multidrop devices: DDCMP and X.25
*/
static struct neigh_ops dn_short_ops = {
- AF_DECnet,
- NULL,
- NULL,
- dn_short_error_report,
- dn_short_output,
- dn_short_output,
- dev_queue_xmit,
- dev_queue_xmit
+ family: AF_DECnet,
+ error_report: dn_short_error_report,
+ output: dn_short_output,
+ connected_output: dn_short_output,
+ hh_output: dev_queue_xmit,
+ queue_xmit: dev_queue_xmit,
};
/*
* For talking to DECnet phase III nodes
*/
static struct neigh_ops dn_phase3_ops = {
- AF_DECnet,
- NULL,
- NULL,
- dn_short_error_report, /* Can use short version here */
- dn_phase3_output,
- dn_phase3_output,
- dev_queue_xmit,
- dev_queue_xmit
+ family: AF_DECnet,
+ error_report: dn_short_error_report, /* Can use short version here */
+ output: dn_phase3_output,
+ connected_output: dn_phase3_output,
+ hh_output: dev_queue_xmit,
+ queue_xmit: dev_queue_xmit
};
struct neigh_table dn_neigh_table = {
- NULL,
- PF_DECnet,
- sizeof(struct dn_neigh),
- sizeof(dn_address),
- dn_neigh_hash,
- dn_neigh_construct,
- NULL, /* pconstructor */
- NULL, /* pdestructor */
- NULL, /* proxyredo */
- "dn_neigh_cache",
- {
- NULL,
- NULL,
- &dn_neigh_table,
- 0,
- NULL,
- NULL,
- 30 * HZ, /* base_reachable_time */
- 1 * HZ, /* retrans_time */
- 60 * HZ, /* gc_staletime */
- 30 * HZ, /* reachable_time */
- 5 * HZ, /* delay_probe_time */
- 3, /* queue_len */
- 0, /* ucast_probes */
- 0, /* app_probes */
- 0, /* mcast_probes */
- 0, /* anycast_delay */
- 0, /* proxy_delay */
- 0, /* proxy_qlen */
- 1 * HZ, /* locktime */
+ family: PF_DECnet,
+ entry_size: sizeof(struct dn_neigh),
+ key_len: sizeof(dn_address),
+ hash: dn_neigh_hash,
+ constructor: dn_neigh_construct,
+ id: "dn_neigh_cache",
+ parms: {
+ tbl: &dn_neigh_table,
+ entries: 0,
+ base_reachable_time: 30 * HZ,
+ retrans_time: 1 * HZ,
+ gc_staletime: 60 * HZ,
+ reachable_time: 30 * HZ,
+ delay_probe_time: 5 * HZ,
+ queue_len: 3,
+ ucast_probes: 0,
+ app_probes: 0,
+ mcast_probes: 0,
+ anycast_delay: 0,
+ proxy_delay: 0,
+ proxy_qlen: 0,
+ locktime: 1 * HZ,
},
- 30 * HZ, /* gc_interval */
- 128, /* gc_thresh1 */
- 512, /* gc_thresh2 */
- 1024, /* gc_thresh3 */
-
+ gc_interval: 30 * HZ,
+ gc_thresh1: 128,
+ gc_thresh2: 512,
+ gc_thresh3: 1024,
};
static u32 dn_neigh_hash(const void *pkey, const struct net_device *dev)
@@ -180,66 +167,15 @@ static int dn_neigh_construct(struct neighbour *neigh)
static void dn_long_error_report(struct neighbour *neigh, struct sk_buff *skb)
{
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
- unsigned char *ptr;
-
printk(KERN_DEBUG "dn_long_error_report: called\n");
-
- if (!(cb->rt_flags & DN_RT_F_RQR)) {
- kfree_skb(skb);
- return;
- }
-
- skb_push(skb, skb->data - skb->nh.raw);
- ptr = skb->data;
-
- *(unsigned short *)ptr = dn_htons(skb->len - 2);
- ptr += 2;
-
- if (*ptr & DN_RT_F_PF) {
- char padlen = (*ptr & ~DN_RT_F_PF);
- ptr += padlen;
- }
-
- *ptr++ |= (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS;
-
- ptr += 2;
- dn_dn2eth(ptr, dn_ntohs(cb->src));
- ptr += 8;
- dn_dn2eth(ptr, dn_ntohs(cb->dst));
- ptr += 6;
- *ptr = 0;
-
- skb->dst->neighbour->ops->queue_xmit(skb);
+ kfree_skb(skb);
}
static void dn_short_error_report(struct neighbour *neigh, struct sk_buff *skb)
{
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
- unsigned char *ptr;
-
printk(KERN_DEBUG "dn_short_error_report: called\n");
-
- if (!(cb->rt_flags & DN_RT_F_RQR)) {
- kfree_skb(skb);
- return;
- }
-
- skb_push(skb, skb->data - skb->nh.raw);
- ptr = skb->data;
-
- *(unsigned short *)ptr = dn_htons(skb->len - 2);
- ptr += 2;
- *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS;
-
- *(dn_address *)ptr = cb->src;
- ptr += 2;
- *(dn_address *)ptr = cb->dst;
- ptr += 2;
- *ptr = 0;
-
- skb->dst->neighbour->ops->queue_xmit(skb);
+ kfree_skb(skb);
}
static int dn_neigh_output_packet(struct sk_buff *skb)
@@ -266,7 +202,7 @@ static int dn_long_output(struct sk_buff *skb)
int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3;
unsigned char *data;
struct dn_long_packet *lp;
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
if (skb_headroom(skb) < headroom) {
@@ -312,7 +248,7 @@ static int dn_short_output(struct sk_buff *skb)
int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
struct dn_short_packet *sp;
unsigned char *data;
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
if (skb_headroom(skb) < headroom) {
@@ -355,7 +291,7 @@ static int dn_phase3_output(struct sk_buff *skb)
int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
struct dn_short_packet *sp;
unsigned char *data;
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
if (skb_headroom(skb) < headroom) {
struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
@@ -659,8 +595,6 @@ void __init dn_neigh_init(void)
void __exit dn_neigh_cleanup(void)
{
-#ifdef CONFIG_PROC_FS
proc_net_remove("decnet_neigh");
-#endif /* CONFIG_PROC_FS */
neigh_table_clear(&dn_neigh_table);
}
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 361729458..11a4e8237 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -25,6 +25,9 @@
* Steve Whitehouse:
* Patrick Caulfield: Checking conninits for correctness & sending of error
* responses.
+ * Steve Whitehouse: Added backlog congestion level return codes.
+ * Patrick Caulfield:
+ * Steve Whitehouse: Added flow control support (outbound)
*/
/******************************************************************************
@@ -79,7 +82,7 @@ static void dn_log_martian(struct sk_buff *skb, const char *msg)
{
if (decnet_log_martians && net_ratelimit()) {
char *devname = skb->dev ? skb->dev->name : "???";
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
printk(KERN_INFO "DECnet: Martian packet (%s) dev=%s src=0x%04hx dst=0x%04hx srcport=0x%04hx dstport=0x%04hx\n", msg, devname, cb->src, cb->dst, cb->src_port, cb->dst_port);
}
}
@@ -91,7 +94,7 @@ static void dn_log_martian(struct sk_buff *skb, const char *msg)
*/
static void dn_ack(struct sock *sk, struct sk_buff *skb, unsigned short ack)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
unsigned short type = ((ack >> 12) & 0x0003);
int wakeup = 0;
@@ -212,7 +215,7 @@ static struct {
*/
static struct sock *dn_find_listener(struct sk_buff *skb, unsigned short *reason)
{
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
struct nsp_conn_init_msg *msg = (struct nsp_conn_init_msg *)skb->data;
struct sockaddr_dn dstaddr;
struct sockaddr_dn srcaddr;
@@ -331,33 +334,26 @@ static void dn_nsp_conn_init(struct sock *sk, struct sk_buff *skb)
static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb)
{
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
+ struct dn_scp *scp = DN_SK(sk);
+ unsigned char *ptr;
- if (skb->len < 3)
+ if (skb->len < 4)
goto out;
- cb->services = *skb->data;
- cb->info = *(skb->data+1);
- skb_pull(skb, 2);
- cb->segsize = dn_ntohs(*(__u16 *)skb->data);
- skb_pull(skb, 2);
-
- /*
- * FIXME: Check out services and info fields to check that
- * we can talk to this kind of node.
- */
+ ptr = skb->data;
+ cb->services = *ptr++;
+ cb->info = *ptr++;
+ cb->segsize = dn_ntohs(*(__u16 *)ptr);
if ((scp->state == DN_CI) || (scp->state == DN_CD)) {
scp->persist = 0;
scp->addrrem = cb->src_port;
sk->state = TCP_ESTABLISHED;
scp->state = DN_RUN;
-
- if (scp->mss > cb->segsize)
- scp->mss = cb->segsize;
- if (scp->mss < 230)
- scp->mss = 230;
+ scp->services_rem = cb->services;
+ scp->info_rem = cb->info;
+ scp->segsize_rem = cb->segsize;
if (skb->len > 0) {
unsigned char dlen = *skb->data;
@@ -366,7 +362,7 @@ static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb)
memcpy(scp->conndata_in.opt_data, skb->data + 1, dlen);
}
}
- dn_nsp_send_lnk(sk, DN_NOCHANGE);
+ dn_nsp_send_link(sk, DN_NOCHANGE, 0);
if (!sk->dead)
sk->state_change(sk);
}
@@ -377,7 +373,7 @@ out:
static void dn_nsp_conn_ack(struct sock *sk, struct sk_buff *skb)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
if (scp->state == DN_CI) {
scp->state = DN_CD;
@@ -389,8 +385,8 @@ static void dn_nsp_conn_ack(struct sock *sk, struct sk_buff *skb)
static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb)
{
- struct dn_scp *scp = &sk->protinfo.dn;
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_scp *scp = DN_SK(sk);
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
unsigned short reason;
if (skb->len < 2)
@@ -448,7 +444,7 @@ out:
*/
static void dn_nsp_disc_conf(struct sock *sk, struct sk_buff *skb)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
unsigned short reason;
if (skb->len != 2)
@@ -492,38 +488,65 @@ out:
static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb)
{
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_scp *scp = DN_SK(sk);
unsigned short segnum;
unsigned char lsflags;
char fcval;
+ int wake_up = 0;
+ char *ptr = skb->data;
+ unsigned char fctype = scp->services_rem & NSP_FC_MASK;
if (skb->len != 4)
goto out;
- cb->segnum = segnum = dn_ntohs(*(__u16 *)skb->data);
- skb_pull(skb, 2);
- lsflags = *(unsigned char *)skb->data;
- skb_pull(skb, 1);
- fcval = *(char *)skb->data;
+ segnum = dn_ntohs(*(__u16 *)ptr);
+ ptr += 2;
+ lsflags = *(unsigned char *)ptr++;
+ fcval = *ptr;
- if (lsflags & 0xf0)
+ /*
+ * Here we ignore erronous packets which should really
+ * should cause a connection abort. It is not critical
+ * for now though.
+ */
+ if (lsflags & 0xf8)
goto out;
- if (((sk->protinfo.dn.numoth_rcv + 1) & 0x0FFF) == (segnum & 0x0FFF)) {
- sk->protinfo.dn.numoth_rcv += 1;
- switch(lsflags & 0x03) {
- case 0x00:
- break;
- case 0x01:
- sk->protinfo.dn.flowrem_sw = DN_DONTSEND;
- break;
- case 0x02:
- sk->protinfo.dn.flowrem_sw = DN_SEND;
+ if (seq_next(scp->numoth_rcv, segnum)) {
+ seq_add(&scp->numoth_rcv, 1);
+ switch(lsflags & 0x04) { /* FCVAL INT */
+ case 0x00: /* Normal Request */
+ switch(lsflags & 0x03) { /* FCVAL MOD */
+ case 0x00: /* Request count */
+ if (fcval < 0) {
+ unsigned char p_fcval = -fcval;
+ if ((scp->flowrem_dat > p_fcval) &&
+ (fctype == NSP_FC_SCMC)) {
+ scp->flowrem_dat -= p_fcval;
+ }
+ } else if (fcval > 0) {
+ scp->flowrem_dat += fcval;
+ wake_up = 1;
+ }
+ break;
+ case 0x01: /* Stop outgoing data */
+ scp->flowrem_sw = DN_DONTSEND;
+ break;
+ case 0x02: /* Ok to start again */
+ scp->flowrem_sw = DN_SEND;
dn_nsp_output(sk);
- if (!sk->dead)
- sk->state_change(sk);
+ wake_up = 1;
+ }
+ break;
+ case 0x04: /* Interrupt Request */
+ if (fcval > 0) {
+ scp->flowrem_oth += fcval;
+ wake_up = 1;
+ }
+ break;
}
-
+ if (wake_up && !sk->dead)
+ sk->state_change(sk);
}
dn_nsp_send_oth_ack(sk);
@@ -582,9 +605,9 @@ static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig
static void dn_nsp_otherdata(struct sock *sk, struct sk_buff *skb)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
unsigned short segnum;
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
int queued = 0;
if (skb->len < 2)
@@ -593,10 +616,10 @@ static void dn_nsp_otherdata(struct sock *sk, struct sk_buff *skb)
cb->segnum = segnum = dn_ntohs(*(__u16 *)skb->data);
skb_pull(skb, 2);
- if (((sk->protinfo.dn.numoth_rcv + 1) & 0x0fff) == (segnum & 0x0fff)) {
+ if (seq_next(scp->numoth_rcv, segnum)) {
if (dn_queue_skb(sk, skb, SIGURG, &scp->other_receive_queue) == 0) {
- sk->protinfo.dn.numoth_rcv++;
+ seq_add(&scp->numoth_rcv, 1);
scp->other_report = 0;
queued = 1;
}
@@ -612,8 +635,8 @@ static void dn_nsp_data(struct sock *sk, struct sk_buff *skb)
{
int queued = 0;
unsigned short segnum;
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
+ struct dn_scp *scp = DN_SK(sk);
if (skb->len < 2)
goto out;
@@ -621,17 +644,15 @@ static void dn_nsp_data(struct sock *sk, struct sk_buff *skb)
cb->segnum = segnum = dn_ntohs(*(__u16 *)skb->data);
skb_pull(skb, 2);
- if (((sk->protinfo.dn.numdat_rcv + 1) & 0x0FFF) ==
- (segnum & 0x0FFF)) {
-
+ if (seq_next(scp->numdat_rcv, segnum)) {
if (dn_queue_skb(sk, skb, SIGIO, &sk->receive_queue) == 0) {
- sk->protinfo.dn.numdat_rcv++;
+ seq_add(&scp->numdat_rcv, 1);
queued = 1;
}
if ((scp->flowloc_sw == DN_SEND) && dn_congested(sk)) {
scp->flowloc_sw = DN_DONTSEND;
- dn_nsp_send_lnk(sk, DN_DONTSEND);
+ dn_nsp_send_link(sk, DN_DONTSEND, 0);
}
}
@@ -648,7 +669,7 @@ out:
*/
static void dn_returned_conn_init(struct sock *sk, struct sk_buff *skb)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
if (scp->state == DN_CI) {
scp->state = DN_NC;
@@ -660,28 +681,37 @@ static void dn_returned_conn_init(struct sock *sk, struct sk_buff *skb)
kfree_skb(skb);
}
-static void dn_nsp_no_socket(struct sk_buff *skb, unsigned short reason)
+static int dn_nsp_no_socket(struct sk_buff *skb, unsigned short reason)
{
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
+ int ret = NET_RX_DROP;
+
+ /* Must not reply to returned packets */
+ if (cb->rt_flags & DN_RT_F_RTS)
+ goto out;
if ((reason != NSP_REASON_OK) && ((cb->nsp_flags & 0x0c) == 0x08)) {
switch(cb->nsp_flags & 0x70) {
case 0x10:
case 0x60: /* (Retransmitted) Connect Init */
dn_nsp_return_disc(skb, NSP_DISCINIT, reason);
+ ret = NET_RX_SUCCESS;
break;
case 0x20: /* Connect Confirm */
dn_nsp_return_disc(skb, NSP_DISCCONF, reason);
+ ret = NET_RX_SUCCESS;
break;
}
}
+out:
kfree_skb(skb);
+ return ret;
}
static int dn_nsp_rx_packet(struct sk_buff *skb)
{
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
struct sock *sk = NULL;
unsigned char *ptr = (unsigned char *)skb->data;
unsigned short reason = NSP_REASON_NL;
@@ -754,14 +784,19 @@ static int dn_nsp_rx_packet(struct sk_buff *skb)
sk = dn_find_by_skb(skb);
got_it:
if (sk != NULL) {
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
int ret;
/* Reset backoff */
scp->nsp_rxtshift = 0;
bh_lock_sock(sk);
- ret = 0;
+ ret = NET_RX_SUCCESS;
+ if (decnet_debug_level & 8)
+ printk(KERN_DEBUG "NSP: 0x%02x 0x%02x 0x%04x 0x%04x %d\n",
+ (int)cb->rt_flags, (int)cb->nsp_flags,
+ (int)cb->src_port, (int)cb->dst_port,
+ (int)sk->lock.users);
if (sk->lock.users == 0)
ret = dn_nsp_backlog_rcv(sk, skb);
else
@@ -772,12 +807,11 @@ got_it:
return ret;
}
- dn_nsp_no_socket(skb, reason);
- return 1;
+ return dn_nsp_no_socket(skb, reason);
free_out:
kfree_skb(skb);
- return 0;
+ return NET_RX_DROP;
}
int dn_nsp_rx(struct sk_buff *skb)
@@ -792,12 +826,12 @@ int dn_nsp_rx(struct sk_buff *skb)
*/
int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
{
- struct dn_scp *scp = &sk->protinfo.dn;
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_scp *scp = DN_SK(sk);
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
if (cb->rt_flags & DN_RT_F_RTS) {
dn_returned_conn_init(sk, skb);
- return 0;
+ return NET_RX_SUCCESS;
}
/*
@@ -875,6 +909,6 @@ free_out:
}
}
- return 0;
+ return NET_RX_SUCCESS;
}
diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c
index 6965cbf42..5e8482ce0 100644
--- a/net/decnet/dn_nsp_out.c
+++ b/net/decnet/dn_nsp_out.c
@@ -20,6 +20,7 @@
* Steve Whitehouse: New output state machine
* 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
*/
/******************************************************************************
@@ -165,7 +166,7 @@ struct sk_buff *dn_alloc_send_skb(struct sock *sk, int *size, int noblock, int *
*/
unsigned long dn_nsp_persist(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
unsigned long t = ((scp->nsp_srtt >> 2) + scp->nsp_rttvar) >> 1;
@@ -188,7 +189,7 @@ unsigned long dn_nsp_persist(struct sock *sk)
*/
static void dn_nsp_rtt(struct sock *sk, long rtt)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
long srtt = (long)scp->nsp_srtt;
long rttvar = (long)scp->nsp_rttvar;
long delta;
@@ -223,65 +224,64 @@ static void dn_nsp_rtt(struct sock *sk, long rtt)
/* printk(KERN_DEBUG "srtt=%lu rttvar=%lu\n", scp->nsp_srtt, scp->nsp_rttvar); */
}
-/*
- * Walk the queues, otherdata/linkservice first. Send as many
- * frames as the window allows, increment send counts on all
- * skbs which are sent. Reduce the window if we are retransmitting
- * frames.
+/**
+ * dn_nsp_clone_and_send - Send a data packet by cloning it
+ * @skb: The packet to clone and transmit
+ * @gfp: memory allocation flag
+ *
+ * Clone a queued data or other data packet and transmit it.
+ *
+ * Returns: The number of times the packet has been sent previously
*/
-void dn_nsp_output(struct sock *sk)
+static inline unsigned dn_nsp_clone_and_send(struct sk_buff *skb, int gfp)
{
- struct dn_scp *scp = &sk->protinfo.dn;
- unsigned long win = scp->snd_window;
- struct sk_buff *skb, *skb2, *list;
- struct dn_skb_cb *cb;
- int reduce_win = 0;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
+ struct sk_buff *skb2;
+ int ret = 0;
- /* printk(KERN_DEBUG "dn_nsp_output: ping\n"); */
+ if ((skb2 = skb_clone(skb, gfp)) != NULL) {
+ ret = cb->xmit_count;
+ cb->xmit_count++;
+ cb->stamp = jiffies;
+ skb2->sk = skb->sk;
+ dn_nsp_send(skb2);
+ }
+
+ return ret;
+}
+
+/**
+ * dn_nsp_output - Try and send something from socket queues
+ * @sk: The socket whose queues are to be investigated
+ * @gfp: The memory allocation flags
+ *
+ * Try and send the packet on the end of the data and other data queues.
+ * Other data gets priority over data, and if we retransmit a packet we
+ * reduce the window by dividing it in two.
+ *
+ */
+void dn_nsp_output(struct sock *sk)
+{
+ struct dn_scp *scp = DN_SK(sk);
+ struct sk_buff *skb;
+ unsigned reduce_win = 0;
/*
* First we check for otherdata/linkservice messages
*/
- skb = scp->other_xmit_queue.next;
- list = (struct sk_buff *)&scp->other_xmit_queue;
- while(win && (skb != list)) {
- if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
- cb = (struct dn_skb_cb *)skb;
- if (cb->xmit_count > 0)
- reduce_win = 1;
- else
- cb->stamp = jiffies;
- cb->xmit_count++;
- skb2->sk = sk;
- dn_nsp_send(skb2);
- }
- skb = skb->next;
- win--;
- }
+ if ((skb = skb_peek(&scp->other_xmit_queue)) != NULL)
+ reduce_win = dn_nsp_clone_and_send(skb, GFP_ATOMIC);
/*
* If we may not send any data, we don't.
- * Should this apply to otherdata as well ? - SJW
+ * If we are still trying to get some other data down the
+ * channel, we don't try and send any data.
*/
- if (scp->flowrem_sw != DN_SEND)
+ if (reduce_win || (scp->flowrem_sw != DN_SEND))
goto recalc_window;
- skb = scp->data_xmit_queue.next;
- list = (struct sk_buff *)&scp->data_xmit_queue;
- while(win && (skb != list)) {
- if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
- cb = (struct dn_skb_cb *)skb;
- if (cb->xmit_count > 0)
- reduce_win = 1;
- else
- cb->stamp = jiffies;
- cb->xmit_count++;
- skb2->sk = sk;
- dn_nsp_send(skb2);
- }
- skb = skb->next;
- win--;
- }
+ if ((skb = skb_peek(&scp->data_xmit_queue)) != NULL)
+ reduce_win = dn_nsp_clone_and_send(skb, GFP_ATOMIC);
/*
* If we've sent any frame more than once, we cut the
@@ -290,7 +290,6 @@ void dn_nsp_output(struct sock *sk)
*/
recalc_window:
if (reduce_win) {
- /* printk(KERN_DEBUG "Window reduction %ld\n", scp->snd_window); */
scp->snd_window >>= 1;
if (scp->snd_window < NSP_MIN_WINDOW)
scp->snd_window = NSP_MIN_WINDOW;
@@ -299,7 +298,7 @@ recalc_window:
int dn_nsp_xmit_timeout(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
dn_nsp_output(sk);
@@ -309,14 +308,60 @@ int dn_nsp_xmit_timeout(struct sock *sk)
return 0;
}
-void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, int oth)
+static inline unsigned char *dn_mk_common_header(struct dn_scp *scp, struct sk_buff *skb, unsigned char msgflag, int len)
+{
+ unsigned char *ptr = skb_push(skb, len);
+
+ if (len < 5)
+ BUG();
+
+ *ptr++ = msgflag;
+ *((unsigned short *)ptr) = scp->addrrem;
+ ptr += 2;
+ *((unsigned short *)ptr) = scp->addrloc;
+ ptr += 2;
+ return ptr;
+}
+
+static unsigned short *dn_mk_ack_header(struct sock *sk, struct sk_buff *skb, unsigned char msgflag, int hlen, int other)
+{
+ struct dn_scp *scp = DN_SK(sk);
+ unsigned short acknum = scp->numdat_rcv & 0x0FFF;
+ unsigned short ackcrs = scp->numoth_rcv & 0x0FFF;
+ unsigned short *ptr;
+
+ if (hlen < 9)
+ BUG();
+
+ scp->ackxmt_dat = acknum;
+ scp->ackxmt_oth = ackcrs;
+ acknum |= 0x8000;
+ ackcrs |= 0x8000;
+
+ /* If this is an "other data/ack" message, swap acknum and ackcrs */
+ if (other) {
+ unsigned short tmp = acknum;
+ acknum = ackcrs;
+ ackcrs = tmp;
+ }
+
+ /* Set "cross subchannel" bit in ackcrs */
+ ackcrs |= 0x2000;
+
+ ptr = (unsigned short *)dn_mk_common_header(scp, skb, msgflag, hlen);
+
+ *ptr++ = dn_htons(acknum);
+ *ptr++ = dn_htons(ackcrs);
+
+ return ptr;
+}
+
+void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, int gfp, int oth)
{
- struct dn_scp *scp = &sk->protinfo.dn;
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ 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;
- struct sk_buff *skb2;
- if (t < HZ) t = HZ;
/*
* Slow start: If we have been idle for more than
* one RTT, then reset window to min size.
@@ -336,20 +381,17 @@ void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, int oth)
if (scp->flowrem_sw != DN_SEND)
return;
- if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
- cb->stamp = jiffies;
- cb->xmit_count++;
- skb2->sk = sk;
- dn_nsp_send(skb2);
- }
+ dn_nsp_clone_and_send(skb, gfp);
}
+
int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff_head *q, unsigned short acknum)
{
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
+ struct dn_scp *scp = DN_SK(sk);
struct sk_buff *skb2, *list, *ack = NULL;
int wakeup = 0;
+ int try_retrans = 0;
unsigned long reftime = cb->stamp;
unsigned long pkttime;
unsigned short xmit_count;
@@ -358,7 +400,7 @@ int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff
skb2 = q->next;
list = (struct sk_buff *)q;
while(list != skb2) {
- struct dn_skb_cb *cb2 = (struct dn_skb_cb *)skb2->cb;
+ struct dn_skb_cb *cb2 = DN_SKB_CB(skb2);
if (before_or_equal(cb2->segnum, acknum))
ack = skb2;
@@ -372,27 +414,50 @@ int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff
/* printk(KERN_DEBUG "check_xmit_queue: %04x, %d\n", acknum, cb2->xmit_count); */
+ /* Does _last_ packet acked have xmit_count > 1 */
+ try_retrans = 0;
+ /* Remember to wake up the sending process */
wakeup = 1;
+ /* Keep various statistics */
pkttime = cb2->stamp;
xmit_count = cb2->xmit_count;
segnum = cb2->segnum;
+ /* Remove and drop ack'ed packet */
skb_unlink(ack);
kfree_skb(ack);
ack = NULL;
+
+ /*
+ * We don't expect to see acknowledgements for packets we
+ * haven't sent yet.
+ */
+ if (xmit_count == 0)
+ BUG();
+ /*
+ * If the packet has only been sent once, we can use it
+ * to calculate the RTT and also open the window a little
+ * further.
+ */
if (xmit_count == 1) {
if (equal(segnum, acknum))
dn_nsp_rtt(sk, (long)(pkttime - reftime));
- if (scp->snd_window < NSP_MAX_WINDOW)
+ if (scp->snd_window < scp->max_window)
scp->snd_window++;
}
+
+ /*
+ * Packet has been sent more than once. If this is the last
+ * packet to be acknowledged then we want to send the next
+ * packet in the send queue again (assumes the remote host does
+ * go-back-N error control).
+ */
+ if (xmit_count > 1)
+ try_retrans = 1;
}
-#if 0 /* Turned off due to possible interference in socket shutdown */
- if ((skb_queue_len(&scp->data_xmit_queue) == 0) &&
- (skb_queue_len(&scp->other_xmit_queue) == 0))
- scp->persist = 0;
-#endif
+ if (try_retrans)
+ dn_nsp_output(sk);
return wakeup;
}
@@ -400,47 +465,31 @@ int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff
void dn_nsp_send_data_ack(struct sock *sk)
{
struct sk_buff *skb = NULL;
- struct nsp_data_ack_msg *msg;
- if ((skb = dn_alloc_skb(sk, 200, GFP_ATOMIC)) == NULL)
+ if ((skb = dn_alloc_skb(sk, 9, GFP_ATOMIC)) == NULL)
return;
-
- msg = (struct nsp_data_ack_msg *)skb_put(skb,sizeof(*msg));
-
- msg->msgflg = 0x04; /* data ack message */
- msg->dstaddr = sk->protinfo.dn.addrrem;
- msg->srcaddr = sk->protinfo.dn.addrloc;
- msg->acknum = dn_htons((sk->protinfo.dn.numdat_rcv & 0x0FFF) | 0x8000);
-
- sk->protinfo.dn.ackxmt_dat = sk->protinfo.dn.numdat_rcv;
+ skb_reserve(skb, 9);
+ dn_mk_ack_header(sk, skb, 0x04, 9, 0);
dn_nsp_send(skb);
}
void dn_nsp_send_oth_ack(struct sock *sk)
{
struct sk_buff *skb = NULL;
- struct nsp_data_ack_msg *msg;
- if ((skb = dn_alloc_skb(sk, 200, GFP_ATOMIC)) == NULL)
+ if ((skb = dn_alloc_skb(sk, 9, GFP_ATOMIC)) == NULL)
return;
-
- msg = (struct nsp_data_ack_msg *)skb_put(skb,sizeof(*msg));
-
- msg->msgflg = 0x14; /* oth ack message */
- msg->dstaddr = sk->protinfo.dn.addrrem;
- msg->srcaddr = sk->protinfo.dn.addrloc;
- msg->acknum = dn_htons((sk->protinfo.dn.numoth_rcv & 0x0FFF) | 0x8000);
-
- sk->protinfo.dn.ackxmt_oth = sk->protinfo.dn.numoth_rcv;
+ skb_reserve(skb, 9);
+ dn_mk_ack_header(sk, skb, 0x14, 9, 1);
dn_nsp_send(skb);
}
void dn_send_conn_ack (struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
struct sk_buff *skb = NULL;
struct nsp_conn_ack_msg *msg;
@@ -456,7 +505,7 @@ void dn_send_conn_ack (struct sock *sk)
void dn_nsp_delayed_ack(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
if (scp->ackxmt_oth != scp->numoth_rcv)
dn_nsp_send_oth_ack(sk);
@@ -467,7 +516,7 @@ void dn_nsp_delayed_ack(struct sock *sk)
static int dn_nsp_retrans_conn_conf(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
if (scp->state == DN_CC)
dn_send_conn_conf(sk, GFP_ATOMIC);
@@ -477,7 +526,7 @@ static int dn_nsp_retrans_conn_conf(struct sock *sk)
void dn_send_conn_conf(struct sock *sk, int gfp)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
struct sk_buff *skb = NULL;
struct nsp_conn_init_msg *msg;
unsigned char len = scp->conndata_out.opt_optl;
@@ -489,9 +538,9 @@ void dn_send_conn_conf(struct sock *sk, int gfp)
msg->msgflg = 0x28;
msg->dstaddr = scp->addrrem;
msg->srcaddr = scp->addrloc;
- msg->services = 0x01;
- msg->info = 0x03;
- msg->segsize = dn_htons(0x05B3);
+ msg->services = scp->services_loc;
+ msg->info = scp->info_loc;
+ msg->segsize = dn_htons(scp->segsize_loc);
*skb_put(skb,1) = len;
@@ -551,7 +600,7 @@ static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg,
void dn_nsp_send_disc(struct sock *sk, unsigned char msgflg,
unsigned short reason, int gfp)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
int ddl = 0;
if (msgflg == NSP_DISCINIT)
@@ -568,7 +617,7 @@ void dn_nsp_send_disc(struct sock *sk, unsigned char msgflg,
void dn_nsp_return_disc(struct sk_buff *skb, unsigned char msgflg,
unsigned short reason)
{
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
int ddl = 0;
int gfp = GFP_ATOMIC;
@@ -577,38 +626,35 @@ void dn_nsp_return_disc(struct sk_buff *skb, unsigned char msgflg,
}
-void dn_nsp_send_lnk(struct sock *sk, unsigned short flgs)
+void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval)
{
- struct dn_scp *scp = &sk->protinfo.dn;
- struct sk_buff *skb = NULL;
- struct nsp_data_seg_msg *msg;
- struct nsp_data_opt_msg *msg1;
- struct dn_skb_cb *cb;
+ 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, 80, GFP_ATOMIC)) == NULL)
+ if ((skb = dn_alloc_skb(sk, 13, gfp)) == NULL)
return;
- cb = (struct dn_skb_cb *)skb->cb;
- msg = (struct nsp_data_seg_msg *)skb_put(skb, sizeof(*msg));
- msg->msgflg = 0x10; /* Link svc message */
- msg->dstaddr = scp->addrrem;
- msg->srcaddr = scp->addrloc;
+ 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);
+ *ptr++ = lsflags;
+ *ptr = fcval;
- msg1 = (struct nsp_data_opt_msg *)skb_put(skb, sizeof(*msg1));
- msg1->acknum = dn_htons((scp->ackxmt_oth & 0x0FFF) | 0x8000);
- msg1->segnum = dn_htons(cb->segnum = (scp->numoth++ & 0x0FFF));
- msg1->lsflgs = flgs;
-
- dn_nsp_queue_xmit(sk, skb, 1);
+ dn_nsp_queue_xmit(sk, skb, gfp, 1);
scp->persist = dn_nsp_persist(sk);
scp->persist_fxn = dn_nsp_xmit_timeout;
-
}
static int dn_nsp_retrans_conninit(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
if (scp->state == DN_CI)
dn_nsp_send_conninit(sk, NSP_RCI);
@@ -618,7 +664,7 @@ static int dn_nsp_retrans_conninit(struct sock *sk)
void dn_nsp_send_conninit(struct sock *sk, unsigned char msgflg)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
struct sk_buff *skb = NULL;
struct nsp_conn_init_msg *msg;
unsigned char aux;
@@ -629,16 +675,16 @@ void dn_nsp_send_conninit(struct sock *sk, unsigned char msgflg)
if ((skb = dn_alloc_skb(sk, 200, (msgflg == NSP_CI) ? sk->allocation : GFP_ATOMIC)) == NULL)
return;
- cb = (struct dn_skb_cb *)skb->cb;
+ cb = DN_SKB_CB(skb);
msg = (struct nsp_conn_init_msg *)skb_put(skb,sizeof(*msg));
msg->msgflg = msgflg;
msg->dstaddr = 0x0000; /* Remote Node will assign it*/
- msg->srcaddr = sk->protinfo.dn.addrloc;
- msg->services = 1 | NSP_FC_NONE; /* Requested flow control */
- msg->info = 0x03; /* Version Number */
- msg->segsize = dn_htons(1459); /* Max segment size */
+ msg->srcaddr = scp->addrloc;
+ msg->services = scp->services_loc; /* Requested flow control */
+ msg->info = scp->info_loc; /* Version Number */
+ msg->segsize = dn_htons(scp->segsize_loc); /* Max segment size */
if (scp->peer.sdn_objnum)
type = 0;
@@ -674,8 +720,8 @@ void dn_nsp_send_conninit(struct sock *sk, unsigned char msgflg)
if (aux > 0)
memcpy(skb_put(skb,aux), scp->conndata_out.opt_data, aux);
- sk->protinfo.dn.persist = dn_nsp_persist(sk);
- sk->protinfo.dn.persist_fxn = dn_nsp_retrans_conninit;
+ scp->persist = dn_nsp_persist(sk);
+ scp->persist_fxn = dn_nsp_retrans_conninit;
cb->rt_flags = DN_RT_F_RQR;
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 70646fc11..b40c601b6 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -33,6 +33,9 @@
* Steve Whitehouse : Real SMP at last :-) Also new netfilter
* stuff. Look out raw sockets your days
* are numbered!
+ * Steve Whitehouse : Added return-to-sender functions. Added
+ * backlog congestion level return codes.
+ *
*/
/******************************************************************************
@@ -109,17 +112,16 @@ static struct timer_list dn_rt_flush_timer = { function: dn_run_flush };
int decnet_dst_gc_interval = 2;
static struct dst_ops dn_dst_ops = {
- PF_DECnet,
- __constant_htons(ETH_P_DNA_RT),
- 128,
- dn_dst_gc,
- dn_dst_check,
- dn_dst_reroute,
- NULL,
- dn_dst_negative_advice,
- dn_dst_link_failure,
- sizeof(struct dn_route),
- ATOMIC_INIT(0)
+ family: PF_DECnet,
+ protocol: __constant_htons(ETH_P_DNA_RT),
+ gc_thresh: 128,
+ gc: dn_dst_gc,
+ check: dn_dst_check,
+ reroute: dn_dst_reroute,
+ negative_advice: dn_dst_negative_advice,
+ link_failure: dn_dst_link_failure,
+ entry_size: sizeof(struct dn_route),
+ entries: ATOMIC_INIT(0),
};
static __inline__ unsigned dn_hash(unsigned short src, unsigned short dst)
@@ -294,21 +296,131 @@ void dn_rt_cache_flush(int delay)
spin_unlock_bh(&dn_rt_flush_lock);
}
+/**
+ * dn_return_short - Return a short packet to its sender
+ * @skb: The packet to return
+ *
+ */
+static int dn_return_short(struct sk_buff *skb)
+{
+ struct dn_skb_cb *cb;
+ unsigned char *ptr;
+ dn_address *src;
+ dn_address *dst;
+ dn_address tmp;
+
+ /* Add back headers */
+ skb_push(skb, skb->data - skb->nh.raw);
+
+ if ((skb = skb_unshare(skb, GFP_ATOMIC)) == NULL)
+ return NET_RX_DROP;
+
+ cb = DN_SKB_CB(skb);
+ /* Skip packet length and point to flags */
+ ptr = skb->data + 2;
+ *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS;
+
+ dst = (dn_address *)ptr;
+ ptr += 2;
+ src = (dn_address *)ptr;
+ ptr += 2;
+ *ptr = 0; /* Zero hop count */
+
+ /* Swap source and destination */
+ tmp = *src;
+ *src = *dst;
+ *dst = tmp;
+
+ skb->pkt_type = PACKET_OUTGOING;
+ dn_rt_finish_output(skb, NULL);
+ return NET_RX_SUCCESS;
+}
+
+/**
+ * dn_return_long - Return a long packet to its sender
+ * @skb: The long format packet to return
+ *
+ */
+static int dn_return_long(struct sk_buff *skb)
+{
+ struct dn_skb_cb *cb;
+ unsigned char *ptr;
+ unsigned char *src_addr, *dst_addr;
+ unsigned char tmp[ETH_ALEN];
+
+ /* Add back all headers */
+ skb_push(skb, skb->data - skb->nh.raw);
+
+ if ((skb = skb_unshare(skb, GFP_ATOMIC)) == NULL)
+ return NET_RX_DROP;
+ cb = DN_SKB_CB(skb);
+ /* Ignore packet length and point to flags */
+ ptr = skb->data + 2;
+
+ /* Skip padding */
+ if (*ptr & DN_RT_F_PF) {
+ char padlen = (*ptr & ~DN_RT_F_PF);
+ ptr += padlen;
+ }
+
+ *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS;
+ ptr += 2;
+ dst_addr = ptr;
+ ptr += 8;
+ src_addr = ptr;
+ ptr += 6;
+ *ptr = 0; /* Zero hop count */
+
+ /* Swap source and destination */
+ memcpy(tmp, src_addr, ETH_ALEN);
+ memcpy(src_addr, dst_addr, ETH_ALEN);
+ memcpy(dst_addr, tmp, ETH_ALEN);
+
+ skb->pkt_type = PACKET_OUTGOING;
+ dn_rt_finish_output(skb, tmp);
+ return NET_RX_SUCCESS;
+}
+
+/**
+ * dn_route_rx_packet - Try and find a route for an incoming packet
+ * @skb: The packet to find a route for
+ *
+ * Returns: result of input function if route is found, error code otherwise
+ */
static int dn_route_rx_packet(struct sk_buff *skb)
{
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
int err;
if ((err = dn_route_input(skb)) == 0)
return skb->dst->input(skb);
+ if (decnet_debug_level & 4) {
+ char *devname = skb->dev ? skb->dev->name : "???";
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
+ printk(KERN_DEBUG
+ "DECnet: dn_route_rx_packet: rt_flags=0x%02x dev=%s len=%d src=0x%04hx dst=0x%04hx err=%d type=%d\n",
+ (int)cb->rt_flags, devname, skb->len, cb->src, cb->dst,
+ err, skb->pkt_type);
+ }
+
+ if ((skb->pkt_type == PACKET_HOST) && (cb->rt_flags & DN_RT_F_RQR)) {
+ switch(cb->rt_flags & DN_RT_PKT_MSK) {
+ case DN_RT_PKT_SHORT:
+ return dn_return_short(skb);
+ case DN_RT_PKT_LONG:
+ return dn_return_long(skb);
+ }
+ }
+
kfree_skb(skb);
- return err;
+ return NET_RX_DROP;
}
static int dn_route_rx_long(struct sk_buff *skb)
{
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ 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 */
@@ -339,14 +451,14 @@ static int dn_route_rx_long(struct sk_buff *skb)
drop_it:
kfree_skb(skb);
- return 0;
+ return NET_RX_DROP;
}
static int dn_route_rx_short(struct sk_buff *skb)
{
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ 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 */
@@ -365,29 +477,33 @@ static int dn_route_rx_short(struct sk_buff *skb)
drop_it:
kfree_skb(skb);
- return 0;
+ return NET_RX_DROP;
}
static int dn_route_discard(struct sk_buff *skb)
{
+ /*
+ * I know we drop the packet here, but thats considered success in
+ * this case
+ */
kfree_skb(skb);
- return 0;
+ return NET_RX_SUCCESS;
}
static int dn_route_ptp_hello(struct sk_buff *skb)
{
dn_dev_hello(skb);
dn_neigh_pointopoint_hello(skb);
- return 0;
+ return NET_RX_SUCCESS;
}
int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
{
struct dn_skb_cb *cb;
unsigned char flags = 0;
- int padlen = 0;
__u16 len = dn_ntohs(*(__u16 *)skb->data);
struct dn_dev *dn = (struct dn_dev *)dev->dn_ptr;
+ unsigned char padlen = 0;
if (dn == NULL)
goto dump_it;
@@ -404,7 +520,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
flags = *skb->data;
- cb = (struct dn_skb_cb *)skb->cb;
+ cb = DN_SKB_CB(skb);
cb->stamp = jiffies;
cb->iif = dev->ifindex;
@@ -448,20 +564,16 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
switch(flags & DN_RT_CNTL_MSK) {
case DN_RT_PKT_HELO:
- NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_route_ptp_hello);
- goto out;
+ return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_route_ptp_hello);
case DN_RT_PKT_L1RT:
case DN_RT_PKT_L2RT:
- NF_HOOK(PF_DECnet, NF_DN_ROUTE, skb, skb->dev, NULL, dn_route_discard);
- goto out;
+ return NF_HOOK(PF_DECnet, NF_DN_ROUTE, skb, skb->dev, NULL, dn_route_discard);
case DN_RT_PKT_ERTH:
- NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_router_hello);
- goto out;
+ return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_router_hello);
case DN_RT_PKT_EEDH:
- NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_endnode_hello);
- goto out;
+ return NF_HOOK(PF_DECnet, NF_DN_HELLO, skb, skb->dev, NULL, dn_neigh_endnode_hello);
}
} else {
if (dn->parms.state != DN_DEV_S_RU)
@@ -480,7 +592,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
dump_it:
kfree_skb(skb);
out:
- return 0;
+ return NET_RX_DROP;
}
static int dn_output(struct sk_buff *skb)
@@ -488,7 +600,7 @@ static int dn_output(struct sk_buff *skb)
struct dst_entry *dst = skb->dst;
struct dn_route *rt = (struct dn_route *)dst;
struct net_device *dev = dst->dev;
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
struct neighbour *neigh;
int err = -EINVAL;
@@ -524,7 +636,7 @@ error:
#ifdef CONFIG_DECNET_ROUTER
static int dn_forward(struct sk_buff *skb)
{
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
struct dst_entry *dst = skb->dst;
struct net_device *dev = skb->dev;
struct neighbour *neigh;
@@ -536,7 +648,7 @@ static int dn_forward(struct sk_buff *skb)
/*
* Hop count exceeded.
*/
- err = 0;
+ err = NET_RX_DROP;
if (++cb->hops > 30)
goto drop;
@@ -573,7 +685,7 @@ drop:
static int dn_blackhole(struct sk_buff *skb)
{
kfree_skb(skb);
- return 0;
+ return NET_RX_DROP;
}
/*
@@ -583,7 +695,7 @@ static int dn_blackhole(struct sk_buff *skb)
static int dn_rt_bug(struct sk_buff *skb)
{
if (net_ratelimit()) {
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
printk(KERN_DEBUG "dn_rt_bug: skb from:%04x to:%04x\n",
cb->src, cb->dst);
@@ -591,7 +703,7 @@ static int dn_rt_bug(struct sk_buff *skb)
kfree_skb(skb);
- return -EINVAL;
+ return NET_RX_BAD;
}
static int dn_route_output_slow(struct dst_entry **pprt, dn_address dst, dn_address src, int flags)
@@ -732,7 +844,7 @@ int dn_route_output(struct dst_entry **pprt, dn_address dst, dn_address src, int
static int dn_route_input_slow(struct sk_buff *skb)
{
struct dn_route *rt = NULL;
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
struct net_device *dev = skb->dev;
struct dn_dev *dn_db;
struct neighbour *neigh = NULL;
@@ -880,7 +992,7 @@ add_entry:
int dn_route_input(struct sk_buff *skb)
{
struct dn_route *rt;
- struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+ struct dn_skb_cb *cb = DN_SKB_CB(skb);
unsigned hash = dn_hash(cb->src, cb->dst);
if (skb->dst)
@@ -964,7 +1076,7 @@ int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
if (skb == NULL)
return -ENOBUFS;
skb->mac.raw = skb->data;
- cb = (struct dn_skb_cb *)skb->cb;
+ cb = DN_SKB_CB(skb);
if (rta[RTA_SRC-1])
memcpy(&src, RTA_DATA(rta[RTA_SRC-1]), 2);
@@ -1185,8 +1297,6 @@ void __exit dn_route_cleanup(void)
del_timer(&dn_route_timer);
dn_run_flush(0);
-#ifdef CONFIG_PROC_FS
proc_net_remove("decnet_cache");
-#endif /* CONFIG_PROC_FS */
}
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 133591f0b..32adfecba 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -57,7 +57,12 @@ struct dn_fib_rule
int r_dead;
};
-static struct dn_fib_rule default_rule = { NULL, ATOMIC_INIT(2), 0x7fff, DN_DEFAULT_TABLE, RTN_UNICAST };
+static struct dn_fib_rule default_rule = {
+ r_clntref: ATOMIC_INIT(2),
+ r_preference: 0x7fff,
+ r_table: DN_DEFAULT_TABLE,
+ r_action: RTN_UNICAST
+};
static struct dn_fib_rule *dn_fib_rules = &default_rule;
static rwlock_t dn_fib_rules_lock = RW_LOCK_UNLOCKED;
@@ -291,9 +296,7 @@ static int dn_fib_rules_event(struct notifier_block *this, unsigned long event,
static struct notifier_block dn_fib_rules_notifier = {
- dn_fib_rules_event,
- NULL,
- 0
+ notifier_call: dn_fib_rules_event,
};
#ifdef CONFIG_RTNETLINK
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index ce7a3ac06..bc21acb4b 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -78,7 +78,7 @@ static rwlock_t dn_fib_tables_lock = RW_LOCK_UNLOCKED;
static struct dn_fib_table *dn_fib_tables[DN_NUM_TABLES + 1];
static kmem_cache_t *dn_hash_kmem;
-static int dn_fib_hash_zombies = 0;
+static int dn_fib_hash_zombies;
static __inline__ dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz)
{
diff --git a/net/decnet/dn_timer.c b/net/decnet/dn_timer.c
index bbba58b02..41a4aa602 100644
--- a/net/decnet/dn_timer.c
+++ b/net/decnet/dn_timer.c
@@ -52,7 +52,7 @@ void dn_stop_slow_timer(struct sock *sk)
static void dn_slow_timer(unsigned long arg)
{
struct sock *sk = (struct sock *)arg;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
sock_hold(sk);
bh_lock_sock(sk);
@@ -112,7 +112,7 @@ out:
static void dn_fast_timer(unsigned long arg)
{
struct sock *sk = (struct sock *)arg;
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
bh_lock_sock(sk);
if (sk->lock.users != 0) {
@@ -131,7 +131,7 @@ out:
void dn_start_fast_timer(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
if (!scp->delack_pending) {
scp->delack_pending = 1;
@@ -145,7 +145,7 @@ void dn_start_fast_timer(struct sock *sk)
void dn_stop_fast_timer(struct sock *sk)
{
- struct dn_scp *scp = &sk->protinfo.dn;
+ struct dn_scp *scp = DN_SK(sk);
if (scp->delack_pending) {
scp->delack_pending = 0;