cregit-Linux how code gets into the kernel

Release 4.11 net/decnet/af_decnet.c

Directory: net/decnet
/*
 * 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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3661.02%225.00%
Linus Torvalds1322.03%225.00%
Arnaldo Carvalho de Melo58.47%112.50%
Steven Whitehouse23.39%112.50%
Patrick Caulfield23.39%112.50%
Harvey Harrison11.69%112.50%
Total59100.00%8100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds4782.46%120.00%
Arnaldo Carvalho de Melo610.53%120.00%
Linus Torvalds (pre-git)23.51%120.00%
Steven Whitehouse11.75%120.00%
Harvey Harrison11.75%120.00%
Total57100.00%5100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)4056.34%233.33%
Linus Torvalds2535.21%233.33%
Steven Whitehouse45.63%116.67%
Harvey Harrison22.82%116.67%
Total71100.00%6100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)8681.90%250.00%
Arnaldo Carvalho de Melo1413.33%125.00%
Linus Torvalds54.76%125.00%
Total105100.00%4100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2589.29%266.67%
Arnaldo Carvalho de Melo310.71%133.33%
Total28100.00%3100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2589.29%266.67%
Arnaldo Carvalho de Melo310.71%133.33%
Total28100.00%3100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds7892.86%116.67%
Steven Whitehouse22.38%116.67%
Adrian Bunk11.19%116.67%
Harvey Harrison11.19%116.67%
Eric Dumazet11.19%116.67%
Arnaldo Carvalho de Melo11.19%116.67%
Total84100.00%6100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds7286.75%133.33%
Arnaldo Carvalho de Melo1113.25%266.67%
Total83100.00%3100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)14896.10%266.67%
Harvey Harrison63.90%133.33%
Total154100.00%3100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)21997.77%266.67%
Harvey Harrison52.23%133.33%
Total224100.00%3100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)14276.34%228.57%
Arnaldo Carvalho de Melo3016.13%228.57%
Linus Torvalds136.99%228.57%
Harvey Harrison10.54%114.29%
Total186100.00%7100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)9781.51%240.00%
Arnaldo Carvalho de Melo1512.61%120.00%
Linus Torvalds65.04%120.00%
Harvey Harrison10.84%120.00%
Total119100.00%5100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)5189.47%125.00%
Linus Torvalds35.26%125.00%
Eric Dumazet23.51%125.00%
Arnaldo Carvalho de Melo11.75%125.00%
Total57100.00%4100.00%

static int dn_memory_pressure;
static void dn_enter_memory_pressure(struct sock *sk) { if (!dn_memory_pressure) { dn_memory_pressure = 1; } }

Contributors

PersonTokensPropCommitsCommitProp
Steven Whitehouse1881.82%150.00%
Pavel Emelyanov418.18%150.00%
Total22100.00%2100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)28266.82%17.69%
Linus Torvalds7918.72%17.69%
Arnaldo Carvalho de Melo266.16%430.77%
Steven Whitehouse204.74%215.38%
Eric W. Biedermann122.84%215.38%
Adrian Bunk10.24%17.69%
Al Viro10.24%17.69%
Tom Herbert10.24%17.69%
Total422100.00%13100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)3482.93%133.33%
Linus Torvalds614.63%133.33%
David S. Miller12.44%133.33%
Total41100.00%3100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)17094.97%350.00%
Himangi Saraogi52.79%116.67%
Linus Torvalds31.68%116.67%
Arnaldo Carvalho de Melo10.56%116.67%
Total179100.00%6100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)19995.67%466.67%
Arnaldo Carvalho de Melo62.88%116.67%
Linus Torvalds31.44%116.67%
Total208100.00%6100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)4497.78%150.00%
Steven Whitehouse12.22%150.00%
Total45100.00%2100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)7764.71%225.00%
Eric W. Biedermann1915.97%225.00%
Hannes Frederic Sowa1411.76%112.50%
Octavian Purdila54.20%112.50%
Eric Paris32.52%112.50%
Arnaldo Carvalho de Melo10.84%112.50%
Total119100.00%8100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)59100.00%3100.00%
Total59100.00%3100.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

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)21168.06%220.00%
Steven Whitehouse5417.42%220.00%
Pavel Emelyanov165.16%110.00%
Thomas Graf154.84%110.00%
Eric Dumazet51.61%110.00%
Harvey Harrison41.29%110.00%
Linus Torvalds30.97%110.00%
Eric W. Biedermann20.65%110.00%
Total310100.00%10100.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<