patch-2.1.20 linux/net/rose/af_rose.c

Next file: linux/net/rose/rose_dev.c
Previous file: linux/net/protocols.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.19/linux/net/rose/af_rose.c linux/net/rose/af_rose.c
@@ -4,7 +4,7 @@
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
  *
- *	This code REQUIRES 2.1.0 or higher/ NET3.029
+ *	This code REQUIRES 2.1.15 or higher/ NET3.038
  *
  *	This module:
  *		This module is free software; you can redistribute it and/or
@@ -21,6 +21,7 @@
   
 #include <linux/config.h>
 #if defined(CONFIG_ROSE) || defined(CONFIG_ROSE_MODULE)
+#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -62,10 +63,10 @@
 
 static unsigned int lci = 1;
 
-struct proto_ops rose_proto_ops;
-
 static struct sock *volatile rose_list = NULL;
 
+static struct proto_ops rose_proto_ops;
+
 /*
  *	Convert a Rose address into text.
  */
@@ -127,6 +128,38 @@
 	return 0;
 }
 
+static void rose_free_sock(struct sock *sk)
+{
+	kfree_s(sk->protinfo.rose, sizeof(*sk->protinfo.rose));
+
+	sk_free(sk);
+
+	MOD_DEC_USE_COUNT;
+}
+
+static struct sock *rose_alloc_sock(void)
+{
+	struct sock *sk;
+	rose_cb *rose;
+
+	if ((sk = sk_alloc(GFP_ATOMIC)) == NULL)
+		return NULL;
+
+	if ((rose = (rose_cb *)kmalloc(sizeof(*rose), GFP_ATOMIC)) == NULL) {
+		sk_free(sk);
+		return NULL;
+	}
+
+	MOD_INC_USE_COUNT;
+	
+	memset(rose, 0x00, sizeof(*rose));
+
+	sk->protinfo.rose = rose;
+	rose->sk = sk;
+
+	return sk;
+}
+
 /*
  *	Socket removal during an interrupt is now safe.
  */
@@ -328,8 +361,7 @@
 		sk->timer.data     = (unsigned long)sk;
 		add_timer(&sk->timer);
 	} else {
-		kfree_s(sk->protinfo.rose, sizeof(*sk->protinfo.rose));
-		sk_free(sk);
+		rose_free_sock(sk);
 	}
 
 	restore_flags(flags);
@@ -593,7 +625,18 @@
 static void def_callback2(struct sock *sk, int len)
 {
 	if (!sk->dead)
+	{
+		wake_up_interruptible(sk->sleep);
+		sock_wake_async(sk->socket,1);
+	}
+}
+static void def_callback3(struct sock *sk, int len)
+{
+	if (!sk->dead)
+	{
 		wake_up_interruptible(sk->sleep);
+		sock_wake_async(sk->socket,2); 
+	}		
 }
 
 static int rose_create(struct socket *sock, int protocol)
@@ -604,13 +647,10 @@
 	if (sock->type != SOCK_SEQPACKET || protocol != 0)
 		return -ESOCKTNOSUPPORT;
 
-	if ((sk = sk_alloc(GFP_ATOMIC)) == NULL)
+	if ((sk = rose_alloc_sock()) == NULL)
 		return -ENOMEM;
 
-	if ((rose = (rose_cb *)kmalloc(sizeof(*rose), GFP_ATOMIC)) == NULL) {
-		sk_free(sk);
-		return -ENOMEM;
-	}
+	rose = sk->protinfo.rose;
 
 	skb_queue_head_init(&sk->receive_queue);
 	skb_queue_head_init(&sk->write_queue);
@@ -643,39 +683,13 @@
 	skb_queue_head_init(&rose->ack_queue);
 	skb_queue_head_init(&rose->frag_queue);
 
-	rose->lci      = 0;
+	rose->t1    = sysctl_rose_call_request_timeout;
+	rose->t2    = sysctl_rose_reset_request_timeout;
+	rose->t3    = sysctl_rose_clear_request_timeout;
+	rose->hb    = sysctl_rose_ack_hold_back_timeout;
+	rose->idle  = sysctl_rose_no_activity_timeout;
 
-	rose->t1       = sysctl_rose_call_request_timeout;
-	rose->t2       = sysctl_rose_reset_request_timeout;
-	rose->t3       = sysctl_rose_clear_request_timeout;
-	rose->hb       = sysctl_rose_ack_hold_back_timeout;
-	rose->idle     = sysctl_rose_no_activity_timeout;
-
-	rose->timer    = 0;
-
-	rose->va       = 0;
-	rose->vr       = 0;
-	rose->vs       = 0;
-	rose->vl       = 0;
-
-	rose->fraglen    = 0;
-	rose->hdrincl    = 0;
-	rose->state      = ROSE_STATE_0;
-	rose->neighbour  = NULL;
-	rose->device     = NULL;
-
-	rose->source_ndigis = 0;
-	rose->dest_ndigis   = 0;
-
-	memset(&rose->source_addr, '\0', ROSE_ADDR_LEN);
-	memset(&rose->dest_addr,   '\0', ROSE_ADDR_LEN);
-	memset(&rose->source_call, '\0', AX25_ADDR_LEN);
-	memset(&rose->dest_call,   '\0', AX25_ADDR_LEN);
-	memset(&rose->source_digi, '\0', AX25_ADDR_LEN);
-	memset(&rose->dest_digi,   '\0', AX25_ADDR_LEN);
-
-	rose->sk          = sk;
-	sk->protinfo.rose = rose;
+	rose->state = ROSE_STATE_0;
 
 	return 0;
 }
@@ -688,13 +702,10 @@
 	if (osk->type != SOCK_SEQPACKET)
 		return NULL;
 
-	if ((sk = (struct sock *)sk_alloc(GFP_ATOMIC)) == NULL)
+	if ((sk = rose_alloc_sock()) == NULL)
 		return NULL;
 
-	if ((rose = (rose_cb *)kmalloc(sizeof(*rose), GFP_ATOMIC)) == NULL) {
-		sk_free(sk);
-		return NULL;
-	}
+	rose = sk->protinfo.rose;
 
 	skb_queue_head_init(&sk->receive_queue);
 	skb_queue_head_init(&sk->write_queue);
@@ -722,25 +733,14 @@
 	skb_queue_head_init(&rose->ack_queue);
 	skb_queue_head_init(&rose->frag_queue);
 
-	rose->t1       = osk->protinfo.rose->t1;
-	rose->t2       = osk->protinfo.rose->t2;
-	rose->t3       = osk->protinfo.rose->t3;
-	rose->hb       = osk->protinfo.rose->hb;
-	rose->idle     = osk->protinfo.rose->idle;
-
-	rose->device   = osk->protinfo.rose->device;
-	rose->hdrincl  = osk->protinfo.rose->hdrincl;
-	rose->fraglen  = 0;
-
-	rose->timer    = 0;
-
-	rose->va       = 0;
-	rose->vr       = 0;
-	rose->vs       = 0;
-	rose->vl       = 0;
-	
-	sk->protinfo.rose = rose;
-	rose->sk          = sk;
+	rose->t1      = osk->protinfo.rose->t1;
+	rose->t2      = osk->protinfo.rose->t2;
+	rose->t3      = osk->protinfo.rose->t3;
+	rose->hb      = osk->protinfo.rose->hb;
+	rose->idle    = osk->protinfo.rose->idle;
+
+	rose->device  = osk->protinfo.rose->device;
+	rose->hdrincl = osk->protinfo.rose->hdrincl;
 
 	return sk;
 }
@@ -1241,7 +1241,7 @@
 		return -ENOTCONN;
 
 	/* Now we can treat all alike */
-	if ((skb = skb_recv_datagram(sk, flags, msg->msg_flags & MSG_DONTWAIT, &er)) == NULL)
+	if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &er)) == NULL)
 		return er;
 
 	if (!sk->protinfo.rose->hdrincl) {
@@ -1419,12 +1419,12 @@
 	return(len);
 } 
 
-struct net_proto_family rose_family_ops = {
+static struct net_proto_family rose_family_ops = {
 	AF_ROSE,
 	rose_create
 };
 
-struct proto_ops rose_proto_ops = {
+static struct proto_ops rose_proto_ops = {
 	AF_ROSE,
 	
 	rose_dup,
@@ -1445,51 +1445,113 @@
 	rose_recvmsg
 };
 
-struct notifier_block rose_dev_notifier = {
+static struct notifier_block rose_dev_notifier = {
 	rose_device_event,
 	0
 };
 
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry proc_net_rose = {
+	PROC_NET_RS, 4, "rose",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations, 
+	rose_get_info
+};
+static struct proc_dir_entry proc_net_rose_neigh = {
+	PROC_NET_RS_NEIGH, 10, "rose_neigh",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations, 
+	rose_neigh_get_info
+};
+static struct proc_dir_entry proc_net_rose_nodes = {
+	PROC_NET_RS_NODES, 10, "rose_nodes",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations, 
+	rose_nodes_get_info
+};
+static struct proc_dir_entry proc_net_rose_routes = {
+	PROC_NET_RS_ROUTES, 11, "rose_routes",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations, 
+	rose_routes_get_info
+};
+#endif	
+
+static struct device dev_rose[] = {
+	{"rose0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init},
+	{"rose1", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init},
+	{"rose2", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init},
+	{"rose3", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init},
+	{"rose4", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init},
+	{"rose5", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, rose_init}
+};
+
 void rose_proto_init(struct net_proto *pro)
 {
+	int i;
+
 	sock_register(&rose_family_ops);
 	register_netdevice_notifier(&rose_dev_notifier);
-	printk(KERN_INFO "G4KLX Rose for Linux. Version 0.1 for AX25.034 Linux 2.1\n");
+	printk(KERN_INFO "G4KLX Rose for Linux. Version 0.1 for AX25.035 Linux 2.1\n");
 
 	if (!ax25_protocol_register(AX25_P_ROSE, rose_route_frame))
 		printk(KERN_ERR "Rose unable to register protocol with AX.25\n");
 	if (!ax25_linkfail_register(rose_link_failed))
 		printk(KERN_ERR "Rose unable to register linkfail handler with AX.25\n");
 
+	for (i = 0; i < 6; i++)
+		register_netdev(&dev_rose[i]);
+
 	rose_register_sysctl();
 
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_RS, 4, "rose",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations, 
-		rose_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_RS_NEIGH, 10, "rose_neigh",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations, 
-		rose_neigh_get_info
-	});
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_RS_NODES, 10, "rose_nodes",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations, 
-		rose_nodes_get_info
-	});
-
-	proc_net_register(&(struct proc_dir_entry) {
-		PROC_NET_RS_ROUTES, 11, "rose_routes",
-		S_IFREG | S_IRUGO, 1, 0, 0,
-		0, &proc_net_inode_operations, 
-		rose_routes_get_info
-	});
+	proc_net_register(&proc_net_rose);
+	proc_net_register(&proc_net_rose_neigh);
+	proc_net_register(&proc_net_rose_nodes);
+	proc_net_register(&proc_net_rose_routes);
 #endif	
 }
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+
+int init_module(void)
+{
+	rose_proto_init(NULL);
+
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	int i;
+
+#ifdef CONFIG_PROC_FS
+	proc_net_unregister(PROC_NET_RS);
+	proc_net_unregister(PROC_NET_RS_NEIGH);
+	proc_net_unregister(PROC_NET_RS_NODES);
+	proc_net_unregister(PROC_NET_RS_ROUTES);
+#endif
+	rose_rt_free();
+
+	ax25_protocol_release(AX25_P_ROSE);
+	ax25_linkfail_release(rose_link_failed);
+
+	rose_unregister_sysctl();
+
+	unregister_netdevice_notifier(&rose_dev_notifier);
+
+	sock_unregister(AF_ROSE);
+
+	for (i = 0; i < 6; i++) {
+		if (dev_rose[i].priv != NULL) {
+			kfree(dev_rose[i].priv);
+			dev_rose[i].priv = NULL;
+			unregister_netdev(&dev_rose[i]);
+		}
+	}
+}
+
+#endif
 
 #endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov