diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2001-01-31 22:22:27 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2001-01-31 22:22:27 +0000 |
commit | 825423e4c4f18289df2393951cfd2a7a31fc0464 (patch) | |
tree | 4ad80e981c3d9effa910d2247d118d254f9a5d09 /net/decnet | |
parent | c4693dc4856ab907a5c02187a8d398861bebfc7e (diff) |
Merge with Linux 2.4.1.
Diffstat (limited to 'net/decnet')
-rw-r--r-- | net/decnet/Makefile | 2 | ||||
-rw-r--r-- | net/decnet/TODO | 12 | ||||
-rw-r--r-- | net/decnet/af_decnet.c | 567 | ||||
-rw-r--r-- | net/decnet/dn_dev.c | 4 | ||||
-rw-r--r-- | net/decnet/dn_fib.c | 6 | ||||
-rw-r--r-- | net/decnet/dn_neigh.c | 168 | ||||
-rw-r--r-- | net/decnet/dn_nsp_in.c | 174 | ||||
-rw-r--r-- | net/decnet/dn_nsp_out.c | 304 | ||||
-rw-r--r-- | net/decnet/dn_route.c | 190 | ||||
-rw-r--r-- | net/decnet/dn_rules.c | 11 | ||||
-rw-r--r-- | net/decnet/dn_table.c | 2 | ||||
-rw-r--r-- | net/decnet/dn_timer.c | 8 |
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; |