patch-2.3.15 linux/net/decnet/dn_raw.c
Next file: linux/net/decnet/dn_route.c
Previous file: linux/net/decnet/dn_nsp_out.c
Back to the patch index
Back to the overall index
- Lines: 348
- Date:
Mon Aug 23 10:01:02 1999
- Orig file:
v2.3.14/linux/net/decnet/dn_raw.c
- Orig date:
Wed May 26 09:36:36 1999
diff -u --recursive --new-file v2.3.14/linux/net/decnet/dn_raw.c linux/net/decnet/dn_raw.c
@@ -10,6 +10,8 @@
*
* Changes:
* Steve Whitehouse - connect() function.
+ * Steve Whitehouse - SMP changes, removed MOP stubs. MOP will
+ * be userland only.
*/
#include <linux/config.h>
@@ -19,38 +21,62 @@
#include <linux/socket.h>
#include <linux/sockios.h>
#include <net/sock.h>
+#include <net/dst.h>
#include <net/dn.h>
#include <net/dn_raw.h>
+#include <net/dn_route.h>
+static rwlock_t dn_raw_hash_lock = RW_LOCK_UNLOCKED;
static struct sock *dn_raw_nsp_sklist = NULL;
static struct sock *dn_raw_routing_sklist = NULL;
-#ifdef CONFIG_DECNET_MOP
-static struct sock *dn_raw_mop_sklist = NULL;
-#endif /* CONFIG_DECNET_MOP */
-static void dn_raw_autobind(struct sock *sk)
+static void dn_raw_hash(struct sock *sk)
{
+ struct sock **skp;
switch(sk->protocol) {
case DNPROTO_NSP:
- sklist_insert_socket(&dn_raw_nsp_sklist, sk);
+ skp = &dn_raw_nsp_sklist;
break;
case DNPROTO_ROU:
- sklist_insert_socket(&dn_raw_routing_sklist, sk);
+ skp = &dn_raw_routing_sklist;
break;
-#ifdef CONFIG_DECNET_MOP
- case DNPROTO_MOP:
- sklist_insert_socket(&dn_raw_mop_sklist, sk);
-#endif /* CONFIG_DECNET_MOP */
default:
- printk(KERN_DEBUG "dn_raw_autobind: Unknown protocol\n");
+ printk(KERN_DEBUG "dn_raw_hash: Unknown protocol\n");
return;
}
+ write_lock_bh(&dn_raw_hash_lock);
+ sk->next = *skp;
+ sk->pprev = skp;
+ *skp = sk;
+ write_unlock_bh(&dn_raw_hash_lock);
+}
+
+static void dn_raw_unhash(struct sock *sk)
+{
+ struct sock **skp = sk->pprev;
+
+ if (skp == NULL)
+ return;
+
+ write_lock_bh(&dn_raw_hash_lock);
+ while(*skp != sk)
+ skp = &((*skp)->next);
+ *skp = sk->next;
+ write_unlock_bh(&dn_raw_hash_lock);
+
+ sk->next = NULL;
+ sk->pprev = NULL;
+}
+
+static void dn_raw_autobind(struct sock *sk)
+{
+ dn_raw_hash(sk);
sk->zapped = 0;
}
-static int dn_raw_release(struct socket *sock, struct socket *peer)
+static int dn_raw_release(struct socket *sock)
{
struct sock *sk = sock->sk;
@@ -63,32 +89,21 @@
sk->socket = NULL;
sock->sk = NULL;
- switch(sk->protocol) {
- case DNPROTO_NSP:
- sklist_destroy_socket(&dn_raw_nsp_sklist, sk);
- break;
- case DNPROTO_ROU:
- sklist_destroy_socket(&dn_raw_routing_sklist, sk);
- break;
-#ifdef CONFIG_DECNET_MOP
- case DNPROTO_MOP:
- sklist_destroy_socket(&dn_raw_mop_sklist, sk);
- break;
-#endif /* CONFIG_DECNET_MOP */
- }
+ dn_raw_unhash(sk);
+ sock_put(sk);
return 0;
}
/*
* Bind does odd things with raw sockets. Its basically used to filter
- * the incomming packets, but this differs with the different layers
+ * the incoming packets, but this differs with the different layers
* at which you extract packets.
*
* For Routing layer sockets, the object name is a host ordered unsigned
* short which is a mask for the 16 different types of possible routing
* packet. I'd like to also select by destination address of the packets
- * but alas, this is rather too dificult to do at the moment.
+ * but alas, this is rather too difficult to do at the moment.
*/
static int dn_raw_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
@@ -103,24 +118,23 @@
switch(sk->protocol) {
case DNPROTO_ROU:
- if (addr->sdn_objnamel && (addr->sdn_objnamel != 2))
+ if (dn_ntohs(addr->sdn_objnamel) && (dn_ntohs(addr->sdn_objnamel) != 2))
return -EINVAL;
/* Fall through here */
case DNPROTO_NSP:
- if (addr->sdn_add.a_len && (addr->sdn_add.a_len != 2))
+ if (dn_ntohs(addr->sdn_add.a_len) && (dn_ntohs(addr->sdn_add.a_len) != 2))
return -EINVAL;
break;
default:
return -EPROTONOSUPPORT;
}
- if (addr->sdn_objnamel > (DN_MAXOBJL-1))
+ if (dn_ntohs(addr->sdn_objnamel) > (DN_MAXOBJL-1))
return -EINVAL;
- if (addr->sdn_add.a_len > DN_MAXADDL)
+ if (dn_ntohs(addr->sdn_add.a_len) > DN_MAXADDL)
return -EINVAL;
-
memcpy(&sk->protinfo.dn.addr, addr, sizeof(struct sockaddr_dn));
dn_raw_autobind(sk);
@@ -137,25 +151,34 @@
struct sock *sk = sock->sk;
struct dn_scp *scp = &sk->protinfo.dn;
struct sockaddr_dn *saddr = (struct sockaddr_dn *)uaddr;
+ int err;
+ lock_sock(sk);
+
+ err = -EINVAL;
if (addr_len != sizeof(struct sockaddr_dn))
- return -EINVAL;
+ goto out;
if (saddr->sdn_family != AF_DECnet)
- return -EINVAL;
+ goto out;
- if (saddr->sdn_objnamel > (DN_MAXOBJL-1))
- return -EINVAL;
+ if (dn_ntohs(saddr->sdn_objnamel) > (DN_MAXOBJL-1))
+ goto out;
- if (saddr->sdn_add.a_len > DN_MAXADDL)
- return -EINVAL;
+ if (dn_ntohs(saddr->sdn_add.a_len) > DN_MAXADDL)
+ goto out;
if (sk->zapped)
dn_raw_autobind(sk);
+ if ((err = dn_route_output(&sk->dst_cache, dn_saddr2dn(saddr), dn_saddr2dn(&scp->addr), 0)) < 0)
+ goto out;
+
memcpy(&scp->peer, saddr, sizeof(struct sockaddr_dn));
+out:
+ release_sock(sk);
- return 0;
+ return err;
}
/*
@@ -187,6 +210,8 @@
int err = 0;
int copied = 0;
+ lock_sock(sk);
+
if (sk->zapped)
dn_raw_autobind(sk);
@@ -212,13 +237,14 @@
skb_free_datagram(sk, skb);
out:
+ release_sock(sk);
+
return copied ? copied : err;
}
struct proto_ops dn_raw_proto_ops = {
AF_DECnet,
- sock_no_dup,
dn_raw_release,
dn_raw_bind,
dn_raw_connect,
@@ -233,7 +259,8 @@
sock_no_getsockopt,
sock_no_fcntl,
dn_raw_sendmsg,
- dn_raw_recvmsg
+ dn_raw_recvmsg,
+ sock_no_mmap
};
#ifdef CONFIG_PROC_FS
@@ -244,7 +271,7 @@
off_t begin = 0;
struct sock *sk;
- cli();
+ read_lock_bh(&dn_raw_hash_lock);
for(sk = dn_raw_nsp_sklist; sk; sk = sk->next) {
len += sprintf(buffer+len, "NSP\n");
@@ -274,24 +301,8 @@
goto all_done;
}
-#ifdef CONFIG_DECNET_MOP
- for(sk = dn_raw_mop_sklist; sk; sk = sk->next) {
- len += sprintf(buffer+len, "MOP\n");
-
- pos = begin + len;
-
- if (pos < offset) {
- len = 0;
- begin = pos;
- }
-
- if (pos > offset + length)
- goto all_done;
- }
-#endif /* CONFIG_DECNET_MOP */
-
all_done:
- sti();
+ read_unlock_bh(&dn_raw_hash_lock);
*start = buffer + (offset - begin);
len -= (offset - begin);
@@ -306,10 +317,8 @@
{
struct sock *sk;
struct sk_buff *skb2;
- unsigned long cpuflags;
- save_flags(cpuflags);
- cli();
+ read_lock(&dn_raw_hash_lock);
for(sk = dn_raw_nsp_sklist; sk != NULL; sk = sk->next) {
if (skb->len > sock_rspace(sk))
continue;
@@ -317,11 +326,11 @@
continue;
if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
skb_set_owner_r(skb2, sk);
- __skb_queue_tail(&sk->receive_queue, skb2);
+ skb_queue_tail(&sk->receive_queue, skb2);
sk->data_ready(sk, skb->len);
}
}
- restore_flags(cpuflags);
+ read_unlock(&dn_raw_hash_lock);
}
void dn_raw_rx_routing(struct sk_buff *skb)
@@ -329,13 +338,11 @@
struct sock *sk;
struct sk_buff *skb2;
struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
- unsigned long cpuflags;
unsigned short rt_flagmask;
unsigned short objnamel;
struct dn_scp *scp;
- save_flags(cpuflags);
- cli();
+ read_lock(&dn_raw_hash_lock);
for(sk = dn_raw_routing_sklist; sk != NULL; sk = sk->next) {
if (skb->len > sock_rspace(sk))
continue;
@@ -343,7 +350,7 @@
continue;
scp = &sk->protinfo.dn;
- rt_flagmask = *(unsigned short *)scp->addr.sdn_objname;
+ rt_flagmask = dn_ntohs(*(unsigned short *)scp->addr.sdn_objname);
objnamel = dn_ntohs(scp->addr.sdn_objnamel);
if ((objnamel == 2) && (!((1 << (cb->rt_flags & 0x0f)) & rt_flagmask)))
@@ -351,33 +358,10 @@
if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
skb_set_owner_r(skb2, sk);
- __skb_queue_tail(&sk->receive_queue, skb2);
+ skb_queue_tail(&sk->receive_queue, skb2);
sk->data_ready(sk, skb->len);
}
}
- restore_flags(cpuflags);
+ read_unlock(&dn_raw_hash_lock);
}
-#ifdef CONFIG_DECNET_MOP
-void dn_raw_rx_mop(struct sk_buff *skb)
-{
- struct sock *sk;
- struct sk_buff *skb2;
- unsigned long cpuflags;
-
- save_flags(cpuflags);
- cli();
- for(sk = dn_raw_mop_sklist; sk != NULL; sk = sk->next) {
- if (skb->len > sock_rspace(sk))
- continue;
- if (sk->dead)
- continue;
- if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
- skb_set_owner_r(skb2, sk);
- __skb_queue_tail(&sk->receive_queue, skb2);
- sk->data_ready(sk, skb->len);
- }
- }
- restore_flags(cpuflags);
-}
-#endif /* CONFIG_DECNET_MOP */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)