Release 4.11 net/decnet/af_decnet.c
/*
* DECnet An implementation of the DECnet protocol suite for the LINUX
* operating system. DECnet is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* DECnet Socket Layer Interface
*
* Authors: Eduardo Marcelo Serrat <emserrat@geocities.com>
* Patrick Caulfield <patrick@pandh.demon.co.uk>
*
* Changes:
* Steve Whitehouse: Copied from Eduardo Serrat and Patrick Caulfield's
* version of the code. Original copyright preserved
* below.
* Steve Whitehouse: Some bug fixes, cleaning up some code to make it
* compatible with my routing layer.
* Steve Whitehouse: Merging changes from Eduardo Serrat and Patrick
* Caulfield.
* Steve Whitehouse: Further bug fixes, checking module code still works
* with new routing layer.
* Steve Whitehouse: Additional set/get_sockopt() calls.
* Steve Whitehouse: Fixed TIOCINQ ioctl to be same as Eduardo's new
* code.
* Steve Whitehouse: recvmsg() changed to try and behave in a POSIX like
* way. Didn't manage it entirely, but its better.
* Steve Whitehouse: ditto for sendmsg().
* Steve Whitehouse: A selection of bug fixes to various things.
* Steve Whitehouse: Added TIOCOUTQ ioctl.
* Steve Whitehouse: Fixes to username2sockaddr & sockaddr2username.
* Steve Whitehouse: Fixes to connect() error returns.
* Patrick Caulfield: Fixes to delayed acceptance logic.
* David S. Miller: New socket locking
* Steve Whitehouse: Socket list hashing/locking
* 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
* Steve Whitehouse: Fixed local port allocation, hashed sk list
* Matthew Wilcox: Fixes for dn_ioctl()
* Steve Whitehouse: New connect/accept logic to allow timeouts and
* prepare for sendpage etc.
*/
/******************************************************************************
(c) 1995-1998 E.M. Serrat emserrat@geocities.com
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
HISTORY:
Version Kernel Date Author/Comments
------- ------ ---- ---------------
Version 0.0.1 2.0.30 01-dic-97 Eduardo Marcelo Serrat
(emserrat@geocities.com)
First Development of DECnet Socket La-
yer for Linux. Only supports outgoing
connections.
Version 0.0.2 2.1.105 20-jun-98 Patrick J. Caulfield
(patrick@pandh.demon.co.uk)
Port to new kernel development version.
Version 0.0.3 2.1.106 25-jun-98 Eduardo Marcelo Serrat
(emserrat@geocities.com)
_
Added support for incoming connections
so we can start developing server apps
on Linux.
-
Module Support
Version 0.0.4 2.1.109 21-jul-98 Eduardo Marcelo Serrat
(emserrat@geocities.com)
_
Added support for X11R6.4. Now we can
use DECnet transport for X on Linux!!!
-
Version 0.0.5 2.1.110 01-aug-98 Eduardo Marcelo Serrat
(emserrat@geocities.com)
Removed bugs on flow control
Removed bugs on incoming accessdata
order
-
Version 0.0.6 2.1.110 07-aug-98 Eduardo Marcelo Serrat
dn_recvmsg fixes
Patrick J. Caulfield
dn_bind fixes
*******************************************************************************/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/sched/signal.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/netdevice.h>
#include <linux/inet.h>
#include <linux/route.h>
#include <linux/netfilter.h>
#include <linux/seq_file.h>
#include <net/sock.h>
#include <net/tcp_states.h>
#include <net/flow.h>
#include <asm/ioctls.h>
#include <linux/capability.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/jiffies.h>
#include <net/net_namespace.h>
#include <net/neighbour.h>
#include <net/dst.h>
#include <net/fib_rules.h>
#include <net/dn.h>
#include <net/dn_nsp.h>
#include <net/dn_dev.h>
#include <net/dn_route.h>
#include <net/dn_fib.h>
#include <net/dn_neigh.h>
struct dn_sock {
struct sock sk;
struct dn_scp scp;
};
static void dn_keepalive(struct sock *sk);
#define DN_SK_HASH_SHIFT 8
#define DN_SK_HASH_SIZE (1 << DN_SK_HASH_SHIFT)
#define DN_SK_HASH_MASK (DN_SK_HASH_SIZE - 1)
static const struct proto_ops dn_proto_ops;
static DEFINE_RWLOCK(dn_hash_lock);
static struct hlist_head dn_sk_hash[DN_SK_HASH_SIZE];
static struct hlist_head dn_wild_sk;
static atomic_long_t decnet_memory_allocated;
static int __dn_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen, int flags);
static int __dn_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen, int flags);
static struct hlist_head *dn_find_list(struct sock *sk)
{
struct dn_scp *scp = DN_SK(sk);
if (scp->addr.sdn_flags & SDF_WILD)
return hlist_empty(&dn_wild_sk) ? &dn_wild_sk : NULL;
return &dn_sk_hash[le16_to_cpu(scp->addrloc) & DN_SK_HASH_MASK];
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 36 | 61.02% | 2 | 25.00% |
Linus Torvalds | 13 | 22.03% | 2 | 25.00% |
Arnaldo Carvalho de Melo | 5 | 8.47% | 1 | 12.50% |
Steven Whitehouse | 2 | 3.39% | 1 | 12.50% |
Patrick Caulfield | 2 | 3.39% | 1 | 12.50% |
Harvey Harrison | 1 | 1.69% | 1 | 12.50% |
Total | 59 | 100.00% | 8 | 100.00% |
/*
* Valid ports are those greater than zero and not already in use.
*/
static int check_port(__le16 port)
{
struct sock *sk;
if (port == 0)
return -1;
sk_for_each(sk, &dn_sk_hash[le16_to_cpu(port) & DN_SK_HASH_MASK]) {
struct dn_scp *scp = DN_SK(sk);
if (scp->addrloc == port)
return -1;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 47 | 82.46% | 1 | 20.00% |
Arnaldo Carvalho de Melo | 6 | 10.53% | 1 | 20.00% |
Linus Torvalds (pre-git) | 2 | 3.51% | 1 | 20.00% |
Steven Whitehouse | 1 | 1.75% | 1 | 20.00% |
Harvey Harrison | 1 | 1.75% | 1 | 20.00% |
Total | 57 | 100.00% | 5 | 100.00% |
static unsigned short port_alloc(struct sock *sk)
{
struct dn_scp *scp = DN_SK(sk);
static unsigned short port = 0x2000;
unsigned short i_port = port;
while(check_port(cpu_to_le16(++port)) != 0) {
if (port == i_port)
return 0;
}
scp->addrloc = cpu_to_le16(port);
return 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 40 | 56.34% | 2 | 33.33% |
Linus Torvalds | 25 | 35.21% | 2 | 33.33% |
Steven Whitehouse | 4 | 5.63% | 1 | 16.67% |
Harvey Harrison | 2 | 2.82% | 1 | 16.67% |
Total | 71 | 100.00% | 6 | 100.00% |
/*
* Since this is only ever called from user
* level, we don't need a write_lock() version
* of this.
*/
static int dn_hash_sock(struct sock *sk)
{
struct dn_scp *scp = DN_SK(sk);
struct hlist_head *list;
int rv = -EUSERS;
BUG_ON(sk_hashed(sk));
write_lock_bh(&dn_hash_lock);
if (!scp->addrloc && !port_alloc(sk))
goto out;
rv = -EADDRINUSE;
if ((list = dn_find_list(sk)) == NULL)
goto out;
sk_add_node(sk, list);
rv = 0;
out:
write_unlock_bh(&dn_hash_lock);
return rv;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 86 | 81.90% | 2 | 50.00% |
Arnaldo Carvalho de Melo | 14 | 13.33% | 1 | 25.00% |
Linus Torvalds | 5 | 4.76% | 1 | 25.00% |
Total | 105 | 100.00% | 4 | 100.00% |
static void dn_unhash_sock(struct sock *sk)
{
write_lock(&dn_hash_lock);
sk_del_node_init(sk);
write_unlock(&dn_hash_lock);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 25 | 89.29% | 2 | 66.67% |
Arnaldo Carvalho de Melo | 3 | 10.71% | 1 | 33.33% |
Total | 28 | 100.00% | 3 | 100.00% |
static void dn_unhash_sock_bh(struct sock *sk)
{
write_lock_bh(&dn_hash_lock);
sk_del_node_init(sk);
write_unlock_bh(&dn_hash_lock);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 25 | 89.29% | 2 | 66.67% |
Arnaldo Carvalho de Melo | 3 | 10.71% | 1 | 33.33% |
Total | 28 | 100.00% | 3 | 100.00% |
static struct hlist_head *listen_hash(struct sockaddr_dn *addr)
{
int i;
unsigned int hash = addr->sdn_objnum;
if (hash == 0) {
hash = addr->sdn_objnamel;
for(i = 0; i < le16_to_cpu(addr->sdn_objnamel); i++) {
hash ^= addr->sdn_objname[i];
hash ^= (hash << 3);
}
}
return &dn_sk_hash[hash & DN_SK_HASH_MASK];
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 78 | 92.86% | 1 | 16.67% |
Steven Whitehouse | 2 | 2.38% | 1 | 16.67% |
Adrian Bunk | 1 | 1.19% | 1 | 16.67% |
Harvey Harrison | 1 | 1.19% | 1 | 16.67% |
Eric Dumazet | 1 | 1.19% | 1 | 16.67% |
Arnaldo Carvalho de Melo | 1 | 1.19% | 1 | 16.67% |
Total | 84 | 100.00% | 6 | 100.00% |
/*
* Called to transform a socket from bound (i.e. with a local address)
* into a listening socket (doesn't need a local port number) and rehashes
* based upon the object name/number.
*/
static void dn_rehash_sock(struct sock *sk)
{
struct hlist_head *list;
struct dn_scp *scp = DN_SK(sk);
if (scp->addr.sdn_flags & SDF_WILD)
return;
write_lock_bh(&dn_hash_lock);
sk_del_node_init(sk);
DN_SK(sk)->addrloc = 0;
list = listen_hash(&DN_SK(sk)->addr);
sk_add_node(sk, list);
write_unlock_bh(&dn_hash_lock);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds | 72 | 86.75% | 1 | 33.33% |
Arnaldo Carvalho de Melo | 11 | 13.25% | 2 | 66.67% |
Total | 83 | 100.00% | 3 | 100.00% |
int dn_sockaddr2username(struct sockaddr_dn *sdn, unsigned char *buf, unsigned char type)
{
int len = 2;
*buf++ = type;
switch (type) {
case 0:
*buf++ = sdn->sdn_objnum;
break;
case 1:
*buf++ = 0;
*buf++ = le16_to_cpu(sdn->sdn_objnamel);
memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
len = 3 + le16_to_cpu(sdn->sdn_objnamel);
break;
case 2:
memset(buf, 0, 5);
buf += 5;
*buf++ = le16_to_cpu(sdn->sdn_objnamel);
memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
len = 7 + le16_to_cpu(sdn->sdn_objnamel);
break;
}
return len;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 148 | 96.10% | 2 | 66.67% |
Harvey Harrison | 6 | 3.90% | 1 | 33.33% |
Total | 154 | 100.00% | 3 | 100.00% |
/*
* On reception of usernames, we handle types 1 and 0 for destination
* addresses only. Types 2 and 4 are used for source addresses, but the
* UIC, GIC are ignored and they are both treated the same way. Type 3
* is never used as I've no idea what its purpose might be or what its
* format is.
*/
int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *sdn, unsigned char *fmt)
{
unsigned char type;
int size = len;
int namel = 12;
sdn->sdn_objnum = 0;
sdn->sdn_objnamel = cpu_to_le16(0);
memset(sdn->sdn_objname, 0, DN_MAXOBJL);
if (len < 2)
return -1;
len -= 2;
*fmt = *data++;
type = *data++;
switch (*fmt) {
case 0:
sdn->sdn_objnum = type;
return 2;
case 1:
namel = 16;
break;
case 2:
len -= 4;
data += 4;
break;
case 4:
len -= 8;
data += 8;
break;
default:
return -1;
}
len -= 1;
if (len < 0)
return -1;
sdn->sdn_objnamel = cpu_to_le16(*data++);
len -= le16_to_cpu(sdn->sdn_objnamel);
if ((len < 0) || (le16_to_cpu(sdn->sdn_objnamel) > namel))
return -1;
memcpy(sdn->sdn_objname, data, le16_to_cpu(sdn->sdn_objnamel));
return size - len;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 219 | 97.77% | 2 | 66.67% |
Harvey Harrison | 5 | 2.23% | 1 | 33.33% |
Total | 224 | 100.00% | 3 | 100.00% |
struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr)
{
struct hlist_head *list = listen_hash(addr);
struct sock *sk;
read_lock(&dn_hash_lock);
sk_for_each(sk, list) {
struct dn_scp *scp = DN_SK(sk);
if (sk->sk_state != TCP_LISTEN)
continue;
if (scp->addr.sdn_objnum) {
if (scp->addr.sdn_objnum != addr->sdn_objnum)
continue;
} else {
if (addr->sdn_objnum)
continue;
if (scp->addr.sdn_objnamel != addr->sdn_objnamel)
continue;
if (memcmp(scp->addr.sdn_objname, addr->sdn_objname, le16_to_cpu(addr->sdn_objnamel)) != 0)
continue;
}
sock_hold(sk);
read_unlock(&dn_hash_lock);
return sk;
}
sk = sk_head(&dn_wild_sk);
if (sk) {
if (sk->sk_state == TCP_LISTEN)
sock_hold(sk);
else
sk = NULL;
}
read_unlock(&dn_hash_lock);
return sk;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 142 | 76.34% | 2 | 28.57% |
Arnaldo Carvalho de Melo | 30 | 16.13% | 2 | 28.57% |
Linus Torvalds | 13 | 6.99% | 2 | 28.57% |
Harvey Harrison | 1 | 0.54% | 1 | 14.29% |
Total | 186 | 100.00% | 7 | 100.00% |
struct sock *dn_find_by_skb(struct sk_buff *skb)
{
struct dn_skb_cb *cb = DN_SKB_CB(skb);
struct sock *sk;
struct dn_scp *scp;
read_lock(&dn_hash_lock);
sk_for_each(sk, &dn_sk_hash[le16_to_cpu(cb->dst_port) & DN_SK_HASH_MASK]) {
scp = DN_SK(sk);
if (cb->src != dn_saddr2dn(&scp->peer))
continue;
if (cb->dst_port != scp->addrloc)
continue;
if (scp->addrrem && (cb->src_port != scp->addrrem))
continue;
sock_hold(sk);
goto found;
}
sk = NULL;
found:
read_unlock(&dn_hash_lock);
return sk;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 97 | 81.51% | 2 | 40.00% |
Arnaldo Carvalho de Melo | 15 | 12.61% | 1 | 20.00% |
Linus Torvalds | 6 | 5.04% | 1 | 20.00% |
Harvey Harrison | 1 | 0.84% | 1 | 20.00% |
Total | 119 | 100.00% | 5 | 100.00% |
static void dn_destruct(struct sock *sk)
{
struct dn_scp *scp = DN_SK(sk);
skb_queue_purge(&scp->data_xmit_queue);
skb_queue_purge(&scp->other_xmit_queue);
skb_queue_purge(&scp->other_receive_queue);
dst_release(rcu_dereference_check(sk->sk_dst_cache, 1));
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 51 | 89.47% | 1 | 25.00% |
Linus Torvalds | 3 | 5.26% | 1 | 25.00% |
Eric Dumazet | 2 | 3.51% | 1 | 25.00% |
Arnaldo Carvalho de Melo | 1 | 1.75% | 1 | 25.00% |
Total | 57 | 100.00% | 4 | 100.00% |
static int dn_memory_pressure;
static void dn_enter_memory_pressure(struct sock *sk)
{
if (!dn_memory_pressure) {
dn_memory_pressure = 1;
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Steven Whitehouse | 18 | 81.82% | 1 | 50.00% |
Pavel Emelyanov | 4 | 18.18% | 1 | 50.00% |
Total | 22 | 100.00% | 2 | 100.00% |
static struct proto dn_proto = {
.name = "NSP",
.owner = THIS_MODULE,
.enter_memory_pressure = dn_enter_memory_pressure,
.memory_pressure = &dn_memory_pressure,
.memory_allocated = &decnet_memory_allocated,
.sysctl_mem = sysctl_decnet_mem,
.sysctl_wmem = sysctl_decnet_wmem,
.sysctl_rmem = sysctl_decnet_rmem,
.max_header = DN_MAX_NSP_DATA_HEADER + 64,
.obj_size = sizeof(struct dn_sock),
};
static struct sock *dn_alloc_sock(struct net *net, struct socket *sock, gfp_t gfp, int kern)
{
struct dn_scp *scp;
struct sock *sk = sk_alloc(net, PF_DECnet, gfp, &dn_proto, kern);
if (!sk)
goto out;
if (sock)
sock->ops = &dn_proto_ops;
sock_init_data(sock, sk);
sk->sk_backlog_rcv = dn_nsp_backlog_rcv;
sk->sk_destruct = dn_destruct;
sk->sk_no_check_tx = 1;
sk->sk_family = PF_DECnet;
sk->sk_protocol = 0;
sk->sk_allocation = gfp;
sk->sk_sndbuf = sysctl_decnet_wmem[1];
sk->sk_rcvbuf = sysctl_decnet_rmem[1];
/* Initialization of DECnet Session Control Port */
scp = DN_SK(sk);
scp->state = DN_O; /* Open */
scp->numdat = 1; /* Next data seg to tx */
scp->numoth = 1; /* Next oth data to tx */
scp->ackxmt_dat = 0; /* Last data seg ack'ed */
scp->ackxmt_oth = 0; /* Last oth data ack'ed */
scp->ackrcv_dat = 0; /* Highest data ack recv*/
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 - DN_MAX_NSP_DATA_HEADER; /* Default: Updated by remote segsize */
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->max_window = NSP_MAX_WINDOW;
scp->snd_window = NSP_MIN_WINDOW;
scp->nsp_srtt = NSP_INITIAL_SRTT;
scp->nsp_rttvar = NSP_INITIAL_RTTVAR;
scp->nsp_rxtshift = 0;
skb_queue_head_init(&scp->data_xmit_queue);
skb_queue_head_init(&scp->other_xmit_queue);
skb_queue_head_init(&scp->other_receive_queue);
scp->persist = 0;
scp->persist_fxn = NULL;
scp->keepalive = 10 * HZ;
scp->keepalive_fxn = dn_keepalive;
init_timer(&scp->delack_timer);
scp->delack_pending = 0;
scp->delack_fxn = dn_nsp_delayed_ack;
dn_start_slow_timer(sk);
out:
return sk;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 282 | 66.82% | 1 | 7.69% |
Linus Torvalds | 79 | 18.72% | 1 | 7.69% |
Arnaldo Carvalho de Melo | 26 | 6.16% | 4 | 30.77% |
Steven Whitehouse | 20 | 4.74% | 2 | 15.38% |
Eric W. Biedermann | 12 | 2.84% | 2 | 15.38% |
Adrian Bunk | 1 | 0.24% | 1 | 7.69% |
Al Viro | 1 | 0.24% | 1 | 7.69% |
Tom Herbert | 1 | 0.24% | 1 | 7.69% |
Total | 422 | 100.00% | 13 | 100.00% |
/*
* Keepalive timer.
* FIXME: Should respond to SO_KEEPALIVE etc.
*/
static void dn_keepalive(struct sock *sk)
{
struct dn_scp *scp = DN_SK(sk);
/*
* By checking the other_data transmit queue is empty
* we are double checking that we are not sending too
* many of these keepalive frames.
*/
if (skb_queue_empty(&scp->other_xmit_queue))
dn_nsp_send_link(sk, DN_NOCHANGE, 0);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 34 | 82.93% | 1 | 33.33% |
Linus Torvalds | 6 | 14.63% | 1 | 33.33% |
David S. Miller | 1 | 2.44% | 1 | 33.33% |
Total | 41 | 100.00% | 3 | 100.00% |
/*
* Timer for shutdown/destroyed sockets.
* When socket is dead & no packets have been sent for a
* certain amount of time, they are removed by this
* routine. Also takes care of sending out DI & DC
* frames at correct times.
*/
int dn_destroy_timer(struct sock *sk)
{
struct dn_scp *scp = DN_SK(sk);
scp->persist = dn_nsp_persist(sk);
switch (scp->state) {
case DN_DI:
dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
if (scp->nsp_rxtshift >= decnet_di_count)
scp->state = DN_CN;
return 0;
case DN_DR:
dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
if (scp->nsp_rxtshift >= decnet_dr_count)
scp->state = DN_DRC;
return 0;
case DN_DN:
if (scp->nsp_rxtshift < decnet_dn_count) {
/* printk(KERN_DEBUG "dn_destroy_timer: DN\n"); */
dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC,
GFP_ATOMIC);
return 0;
}
}
scp->persist = (HZ * decnet_time_wait);
if (sk->sk_socket)
return 0;
if (time_after_eq(jiffies, scp->stamp + HZ * decnet_time_wait)) {
dn_unhash_sock(sk);
sock_put(sk);
return 1;
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 170 | 94.97% | 3 | 50.00% |
Himangi Saraogi | 5 | 2.79% | 1 | 16.67% |
Linus Torvalds | 3 | 1.68% | 1 | 16.67% |
Arnaldo Carvalho de Melo | 1 | 0.56% | 1 | 16.67% |
Total | 179 | 100.00% | 6 | 100.00% |
static void dn_destroy_sock(struct sock *sk)
{
struct dn_scp *scp = DN_SK(sk);
scp->nsp_rxtshift = 0; /* reset back off */
if (sk->sk_socket) {
if (sk->sk_socket->state != SS_UNCONNECTED)
sk->sk_socket->state = SS_DISCONNECTING;
}
sk->sk_state = TCP_CLOSE;
switch (scp->state) {
case DN_DN:
dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC,
sk->sk_allocation);
scp->persist_fxn = dn_destroy_timer;
scp->persist = dn_nsp_persist(sk);
break;
case DN_CR:
scp->state = DN_DR;
goto disc_reject;
case DN_RUN:
scp->state = DN_DI;
case DN_DI:
case DN_DR:
disc_reject:
dn_nsp_send_disc(sk, NSP_DISCINIT, 0, sk->sk_allocation);
case DN_NC:
case DN_NR:
case DN_RJ:
case DN_DIC:
case DN_CN:
case DN_DRC:
case DN_CI:
case DN_CD:
scp->persist_fxn = dn_destroy_timer;
scp->persist = dn_nsp_persist(sk);
break;
default:
printk(KERN_DEBUG "DECnet: dn_destroy_sock passed socket in invalid state\n");
case DN_O:
dn_stop_slow_timer(sk);
dn_unhash_sock_bh(sk);
sock_put(sk);
break;
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 199 | 95.67% | 4 | 66.67% |
Arnaldo Carvalho de Melo | 6 | 2.88% | 1 | 16.67% |
Linus Torvalds | 3 | 1.44% | 1 | 16.67% |
Total | 208 | 100.00% | 6 | 100.00% |
char *dn_addr2asc(__u16 addr, char *buf)
{
unsigned short node, area;
node = addr & 0x03ff;
area = addr >> 10;
sprintf(buf, "%hd.%hd", area, node);
return buf;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 44 | 97.78% | 1 | 50.00% |
Steven Whitehouse | 1 | 2.22% | 1 | 50.00% |
Total | 45 | 100.00% | 2 | 100.00% |
static int dn_create(struct net *net, struct socket *sock, int protocol,
int kern)
{
struct sock *sk;
if (protocol < 0 || protocol > SK_PROTOCOL_MAX)
return -EINVAL;
if (!net_eq(net, &init_net))
return -EAFNOSUPPORT;
switch (sock->type) {
case SOCK_SEQPACKET:
if (protocol != DNPROTO_NSP)
return -EPROTONOSUPPORT;
break;
case SOCK_STREAM:
break;
default:
return -ESOCKTNOSUPPORT;
}
if ((sk = dn_alloc_sock(net, sock, GFP_KERNEL, kern)) == NULL)
return -ENOBUFS;
sk->sk_protocol = protocol;
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 77 | 64.71% | 2 | 25.00% |
Eric W. Biedermann | 19 | 15.97% | 2 | 25.00% |
Hannes Frederic Sowa | 14 | 11.76% | 1 | 12.50% |
Octavian Purdila | 5 | 4.20% | 1 | 12.50% |
Eric Paris | 3 | 2.52% | 1 | 12.50% |
Arnaldo Carvalho de Melo | 1 | 0.84% | 1 | 12.50% |
Total | 119 | 100.00% | 8 | 100.00% |
static int
dn_release(struct socket *sock)
{
struct sock *sk = sock->sk;
if (sk) {
sock_orphan(sk);
sock_hold(sk);
lock_sock(sk);
dn_destroy_sock(sk);
release_sock(sk);
sock_put(sk);
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 59 | 100.00% | 3 | 100.00% |
Total | 59 | 100.00% | 3 | 100.00% |
static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct sock *sk = sock->sk;
struct dn_scp *scp = DN_SK(sk);
struct sockaddr_dn *saddr = (struct sockaddr_dn *)uaddr;
struct net_device *dev, *ldev;
int rv;
if (addr_len != sizeof(struct sockaddr_dn))
return -EINVAL;
if (saddr->sdn_family != AF_DECnet)
return -EINVAL;
if (le16_to_cpu(saddr->sdn_nodeaddrl) && (le16_to_cpu(saddr->sdn_nodeaddrl) != 2))
return -EINVAL;
if (le16_to_cpu(saddr->sdn_objnamel) > DN_MAXOBJL)
return -EINVAL;
if (saddr->sdn_flags & ~SDF_WILD)
return -EINVAL;
if (!capable(CAP_NET_BIND_SERVICE) && (saddr->sdn_objnum ||
(saddr->sdn_flags & SDF_WILD)))
return -EACCES;
if (!(saddr->sdn_flags & SDF_WILD)) {
if (le16_to_cpu(saddr->sdn_nodeaddrl)) {
rcu_read_lock();
ldev = NULL;
for_each_netdev_rcu(&init_net, dev) {
if (!dev->dn_ptr)
continue;
if (dn_dev_islocal(dev, dn_saddr2dn(saddr))) {
ldev = dev;
break;
}
}
rcu_read_unlock();
if (ldev == NULL)
return -EADDRNOTAVAIL;
}
}
rv = -EINVAL;
lock_sock(sk);
if (sock_flag(sk, SOCK_ZAPPED)) {
memcpy(&scp->addr, saddr, addr_len);
sock_reset_flag(sk, SOCK_ZAPPED);
rv = dn_hash_sock(sk);
if (rv)
sock_set_flag(sk, SOCK_ZAPPED);
}
release_sock(sk);
return rv;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 211 | 68.06% | 2 | 20.00% |
Steven Whitehouse | 54 | 17.42% | 2 | 20.00% |
Pavel Emelyanov | 16 | 5.16% | 1 | 10.00% |
Thomas Graf | 15 | 4.84% | 1 | 10.00% |
Eric Dumazet | 5 | 1.61% | 1 | 10.00% |
Harvey Harrison | 4 | 1.29% | 1 | 10.00% |
Linus Torvalds | 3 | 0.97% | 1 | 10.00% |
Eric W. Biedermann | 2 | 0.65% | 1 | 10.00% |
Total | 310 | 100.00% | 10 | 100.00% |
static int dn_auto_bind(struct socket *sock)
{
struct sock *sk = sock->sk;
struct dn_scp *scp = DN_SK(sk);
int rv;
sock_reset_flag(sk, SOCK_ZAPPED);
scp->addr.sdn_flags = 0;
scp->addr.sdn_objnum = 0;
/*
* This stuff is to keep compatibility with Eduardo's
* patch. I hope I can dispense with it shortly...
*/
if ((scp->accessdata.acc_accl != 0) &&
(scp<