patch-2.4.7 linux/net/irda/af_irda.c

Next file: linux/net/irda/compressors/Config.in
Previous file: linux/net/irda/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.6/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
@@ -218,8 +218,7 @@
 		   self->max_data_size);
 
 	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));
-
-	skb_queue_tail(&sk->receive_queue, skb);
+	kfree_skb(skb);
 
 	/* We are now connected! */
 	sk->state = TCP_ESTABLISHED;
@@ -439,7 +438,7 @@
  * We were waiting for a node to be discovered, but nothing has come up
  * so far. Wake up the user and tell him that we failed...
  */
-static void irda_discovery_timeout(u_long	priv)
+static void irda_discovery_timeout(u_long priv)
 {
 	struct irda_sock *self;
 	
@@ -776,7 +775,6 @@
 	struct sock *sk = sock->sk;
 	struct sockaddr_irda *addr = (struct sockaddr_irda *) uaddr;
 	struct irda_sock *self;
-	__u16 hints = 0;
 	int err;
 
 	IRDA_DEBUG(2, __FUNCTION__ "()\n");
@@ -821,15 +819,6 @@
 				 self->stsap_sel, IAS_KERNEL_ATTR);
 	irias_insert_object(self->ias_obj);
 	
-#if 1 /* Will be removed in near future */
-
-	/* Fill in some default hint bits values */
-	if (strncmp(addr->sir_name, "OBEX", 4) == 0)
-		hints = irlmp_service_to_hint(S_OBEX);
-	
-	if (hints)
-		self->skey = irlmp_register_service(hints);
-#endif
 	return 0;
 }
 
@@ -1079,8 +1068,10 @@
 		return -ENOMEM;
 	
 	self = kmalloc(sizeof(struct irda_sock), GFP_ATOMIC);
-	if (self == NULL)
+	if (self == NULL) {
+		kfree (sk);
 		return -ENOMEM;
+	}
 	memset(self, 0, sizeof(struct irda_sock));
 
 	init_waitqueue_head(&self->query_wait);
@@ -1633,34 +1624,58 @@
 {
 	struct sock *sk = sock->sk;
 	unsigned int mask;
+	struct irda_sock *self;
 
 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
+	self = sk->protinfo.irda;
 	poll_wait(file, sk->sleep, wait);
 	mask = 0;
 
-	/* exceptional events? */
+	/* Exceptional events? */
 	if (sk->err)
 		mask |= POLLERR;
-	if (sk->shutdown & RCV_SHUTDOWN)
+	if (sk->shutdown & RCV_SHUTDOWN) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), POLLHUP\n");
 		mask |= POLLHUP;
+	}
 
-	/* readable? */
+	/* Readable? */
 	if (!skb_queue_empty(&sk->receive_queue)) {
 		IRDA_DEBUG(4, "Socket is readable\n");
 		mask |= POLLIN | POLLRDNORM;
 	}
+
 	/* Connection-based need to check for termination and startup */
-	if (sk->type == SOCK_STREAM && sk->state==TCP_CLOSE)
-		mask |= POLLHUP;
+	switch (sk->type) {
+	case SOCK_STREAM:
+		if (sk->state == TCP_CLOSE) {
+			IRDA_DEBUG(0, __FUNCTION__ "(), POLLHUP\n");
+			mask |= POLLHUP;
+		}
 
-	/*
-	 * we set writable also when the other side has shut down the
-	 * connection. This prevents stuck sockets.
-	 */
-	if (sk->sndbuf - (int)atomic_read(&sk->wmem_alloc) >= SOCK_MIN_WRITE_SPACE)
+		if (sk->state == TCP_ESTABLISHED) {
+			if ((self->tx_flow == FLOW_START) && 
+			    (sk->sndbuf - (int)atomic_read(&sk->wmem_alloc) >= SOCK_MIN_WRITE_SPACE))
+			{
+				mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+			}
+		}
+		break;
+	case SOCK_SEQPACKET:
+		if ((self->tx_flow == FLOW_START) && 
+		    (sk->sndbuf - (int)atomic_read(&sk->wmem_alloc) >= SOCK_MIN_WRITE_SPACE))
+		{	
 			mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
-
+		}
+		break;
+	case SOCK_DGRAM:
+		if (sk->sndbuf - (int)atomic_read(&sk->wmem_alloc) >= SOCK_MIN_WRITE_SPACE)
+			mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+		break;
+	default:
+		break;
+	}		
 	return mask;
 }
 
@@ -1740,7 +1755,7 @@
 {
  	struct sock *sk = sock->sk;
 	struct irda_sock *self;
-	struct irda_ias_set	ias_opt;
+	struct irda_ias_set    *ias_opt;
 	struct ias_object      *ias_obj;
 	struct ias_attrib *	ias_attr;	/* Attribute in IAS object */
 	int opt;
@@ -1763,64 +1778,78 @@
 		if (optlen != sizeof(struct irda_ias_set))
 			return -EINVAL;
 	
+		ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC);
+		if (ias_opt == NULL)
+			return -ENOMEM;
+
 		/* Copy query to the driver. */
-		if (copy_from_user(&ias_opt, (char *)optval, optlen))
+		if (copy_from_user(ias_opt, (char *)optval, optlen)) {
+			kfree(ias_opt);
 		  	return -EFAULT;
+		}
 
 		/* Find the object we target */
-		ias_obj = irias_find_object(ias_opt.irda_class_name);
+		ias_obj = irias_find_object(ias_opt->irda_class_name);
 		if(ias_obj == (struct ias_object *) NULL) {
 			/* Create a new object */
-			ias_obj = irias_new_object(ias_opt.irda_class_name,
+			ias_obj = irias_new_object(ias_opt->irda_class_name,
 						   jiffies);
 		}
 
 		/* Do we have it already ? */
-		if(irias_find_attrib(ias_obj, ias_opt.irda_attrib_name))
+		if(irias_find_attrib(ias_obj, ias_opt->irda_attrib_name)) {
+			kfree(ias_opt);
 			return -EINVAL;
+		}
 
 		/* Look at the type */
-		switch(ias_opt.irda_attrib_type) {
+		switch(ias_opt->irda_attrib_type) {
 		case IAS_INTEGER:
 			/* Add an integer attribute */
 			irias_add_integer_attrib(
 				ias_obj,
-				ias_opt.irda_attrib_name, 
-				ias_opt.attribute.irda_attrib_int,
+				ias_opt->irda_attrib_name, 
+				ias_opt->attribute.irda_attrib_int,
 				IAS_USER_ATTR);
 			break;
 		case IAS_OCT_SEQ:
 			/* Check length */
-			if(ias_opt.attribute.irda_attrib_octet_seq.len >
-			   IAS_MAX_OCTET_STRING)
+			if(ias_opt->attribute.irda_attrib_octet_seq.len >
+			   IAS_MAX_OCTET_STRING) {
+				kfree(ias_opt);
 				return -EINVAL;
+			}
 			/* Add an octet sequence attribute */
 			irias_add_octseq_attrib(
 			      ias_obj,
-			      ias_opt.irda_attrib_name, 
-			      ias_opt.attribute.irda_attrib_octet_seq.octet_seq,
-			      ias_opt.attribute.irda_attrib_octet_seq.len,
+			      ias_opt->irda_attrib_name, 
+			      ias_opt->attribute.irda_attrib_octet_seq.octet_seq,
+			      ias_opt->attribute.irda_attrib_octet_seq.len,
 			      IAS_USER_ATTR);
 			break;
 		case IAS_STRING:
 			/* Should check charset & co */
 			/* Check length */
-			if(ias_opt.attribute.irda_attrib_string.len >
-			   IAS_MAX_STRING)
+			if(ias_opt->attribute.irda_attrib_string.len >
+			   IAS_MAX_STRING) {
+				kfree(ias_opt);
 				return -EINVAL;
+			}
 			/* NULL terminate the string (avoid troubles) */
-			ias_opt.attribute.irda_attrib_string.string[ias_opt.attribute.irda_attrib_string.len] = '\0';
+			ias_opt->attribute.irda_attrib_string.string[ias_opt->attribute.irda_attrib_string.len] = '\0';
 			/* Add a string attribute */
 			irias_add_string_attrib(
 				ias_obj,
-				ias_opt.irda_attrib_name, 
-				ias_opt.attribute.irda_attrib_string.string,
+				ias_opt->irda_attrib_name, 
+				ias_opt->attribute.irda_attrib_string.string,
 				IAS_USER_ATTR);
 			break;
 		default :
+			kfree(ias_opt);
 			return -EINVAL;
 		}
 		irias_insert_object(ias_obj);
+		kfree(ias_opt);
 		break;
 	case IRLMP_IAS_DEL:
 		/* The user want to delete an object from our local IAS
@@ -1831,31 +1860,42 @@
 		if (optlen != sizeof(struct irda_ias_set))
 			return -EINVAL;
 	
+		ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC);
+		if (ias_opt == NULL)
+			return -ENOMEM;
+	
 		/* Copy query to the driver. */
-		if (copy_from_user(&ias_opt, (char *)optval, optlen))
+		if (copy_from_user(ias_opt, (char *)optval, optlen)) {
+			kfree(ias_opt);
 		  	return -EFAULT;
+		}
 
 		/* Find the object we target */
-		ias_obj = irias_find_object(ias_opt.irda_class_name);
-		if(ias_obj == (struct ias_object *) NULL)
+		ias_obj = irias_find_object(ias_opt->irda_class_name);
+		if(ias_obj == (struct ias_object *) NULL) {
+			kfree(ias_opt);
 			return -EINVAL;
+		}
 
 		/* Find the attribute (in the object) we target */
 		ias_attr = irias_find_attrib(ias_obj,
-					     ias_opt.irda_attrib_name); 
-		if(ias_attr == (struct ias_attrib *) NULL)
+					     ias_opt->irda_attrib_name); 
+		if(ias_attr == (struct ias_attrib *) NULL) {
+			kfree(ias_opt);
 			return -EINVAL;
+		}
 
 		/* Check is the user space own the object */
 		if(ias_attr->value->owner != IAS_USER_ATTR) {
 			IRDA_DEBUG(1, __FUNCTION__ 
 				   "(), attempting to delete a kernel attribute\n");
+			kfree(ias_opt);
 			return -EPERM;
 		}
 
 		/* Remove the attribute (and maybe the object) */
 		irias_delete_attrib(ias_obj, ias_attr);
-
+		kfree(ias_opt);
 		break;
 	case IRLMP_MAX_SDU_SIZE:
 		if (optlen < sizeof(int))
@@ -1978,7 +2018,7 @@
 	struct irda_sock *self;
 	struct irda_device_list list;
 	struct irda_device_info *discoveries;
-	struct irda_ias_set	ias_opt;	/* IAS get/query params */
+	struct irda_ias_set *	ias_opt;	/* IAS get/query params */
 	struct ias_object *	ias_obj;	/* Object in IAS */
 	struct ias_attrib *	ias_attr;	/* Attribute in IAS object */
 	int daddr = DEV_ADDR_ANY;	/* Dest address for IAS queries */
@@ -2048,34 +2088,49 @@
 		 * that we found */
 
 		/* Check that the user has allocated the right space for us */
-		if (len != sizeof(ias_opt))
+		if (len != sizeof(struct irda_ias_set))
 			return -EINVAL;
 
+		ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC);
+		if (ias_opt == NULL)
+			return -ENOMEM;
+
 		/* Copy query to the driver. */
-		if (copy_from_user((char *) &ias_opt, (char *)optval, len))
+		if (copy_from_user((char *) ias_opt, (char *)optval, len)) {
+			kfree(ias_opt);
 		  	return -EFAULT;
+		}
 
 		/* Find the object we target */
-		ias_obj = irias_find_object(ias_opt.irda_class_name);
-		if(ias_obj == (struct ias_object *) NULL)
+		ias_obj = irias_find_object(ias_opt->irda_class_name);
+		if(ias_obj == (struct ias_object *) NULL) {
+			kfree(ias_opt);
 			return -EINVAL;
+		}
 
 		/* Find the attribute (in the object) we target */
 		ias_attr = irias_find_attrib(ias_obj,
-					     ias_opt.irda_attrib_name); 
-		if(ias_attr == (struct ias_attrib *) NULL)
+					     ias_opt->irda_attrib_name); 
+		if(ias_attr == (struct ias_attrib *) NULL) {
+			kfree(ias_opt);
 			return -EINVAL;
+		}
 
 		/* Translate from internal to user structure */
-		err = irda_extract_ias_value(&ias_opt, ias_attr->value);
-		if(err)
+		err = irda_extract_ias_value(ias_opt, ias_attr->value);
+		if(err) {
+			kfree(ias_opt);
 			return err;
+		}
 
 		/* Copy reply to the user */
-		if (copy_to_user((char *)optval, (char *) &ias_opt,
-				 sizeof(ias_opt)))
+		if (copy_to_user((char *)optval, (char *) ias_opt,
+				 sizeof(struct irda_ias_set))) {
+			kfree(ias_opt);
 		  	return -EFAULT;
+		}
 		/* Note : don't need to put optlen, we checked it */
+		kfree(ias_opt);
 		break;
 	case IRLMP_IAS_QUERY:
 		/* The user want an object from a remote IAS database.
@@ -2083,12 +2138,18 @@
 		 * then wait for the answer to come back. */
 
 		/* Check that the user has allocated the right space for us */
-		if (len != sizeof(ias_opt))
+		if (len != sizeof(struct irda_ias_set))
 			return -EINVAL;
 
+		ias_opt = kmalloc(sizeof(struct irda_ias_set), GFP_ATOMIC);
+		if (ias_opt == NULL)
+			return -ENOMEM;
+
 		/* Copy query to the driver. */
-		if (copy_from_user((char *) &ias_opt, (char *)optval, len))
+		if (copy_from_user((char *) ias_opt, (char *)optval, len)) {
+			kfree(ias_opt);
 		  	return -EFAULT;
+		}
 
 		/* At this point, there are two cases...
 		 * 1) the socket is connected - that's the easy case, we
@@ -2105,15 +2166,18 @@
 		} else {
 			/* We are not connected, we must specify a valid
 			 * destination address */
-			daddr = ias_opt.daddr;
-			if((!daddr) || (daddr == DEV_ADDR_ANY))
+			daddr = ias_opt->daddr;
+			if((!daddr) || (daddr == DEV_ADDR_ANY)) {
+				kfree(ias_opt);
 				return -EINVAL;
+			}
 		}
 
 		/* Check that we can proceed with IAP */
 		if (self->iriap) {
 			WARNING(__FUNCTION__
 				"(), busy with a previous query\n");
+			kfree(ias_opt);
 			return -EBUSY;
 		}
 
@@ -2126,14 +2190,15 @@
 		/* Query remote LM-IAS */
 		iriap_getvaluebyclass_request(self->iriap,
 					      self->saddr, daddr,
-					      ias_opt.irda_class_name,
-					      ias_opt.irda_attrib_name);
+					      ias_opt->irda_class_name,
+					      ias_opt->irda_attrib_name);
 		/* Wait for answer (if not already failed) */
 		if(self->iriap != NULL)
 			interruptible_sleep_on(&self->query_wait);
 		/* Check what happened */
 		if (self->errno)
 		{
+			kfree(ias_opt);
 			/* Requested object/attribute doesn't exist */
 			if((self->errno == IAS_CLASS_UNKNOWN) ||
 			   (self->errno == IAS_ATTRIB_UNKNOWN))
@@ -2143,17 +2208,22 @@
 		}
 
 		/* Translate from internal to user structure */
-		err = irda_extract_ias_value(&ias_opt, self->ias_result);
+		err = irda_extract_ias_value(ias_opt, self->ias_result);
 		if (self->ias_result)
 			irias_delete_value(self->ias_result);
-		if (err)
+		if (err) {
+			kfree(ias_opt);
 			return err;
+		}
 
 		/* Copy reply to the user */
-		if (copy_to_user((char *)optval, (char *) &ias_opt,
-				 sizeof(ias_opt)))
+		if (copy_to_user((char *)optval, (char *) ias_opt,
+				 sizeof(struct irda_ias_set))) {
+			kfree(ias_opt);
 		  	return -EFAULT;
+		}
 		/* Note : don't need to put optlen, we checked it */
+		kfree(ias_opt);
 		break;
 	case IRLMP_WAITDEVICE:
 		/* This function is just another way of seeing life ;-)
@@ -2328,6 +2398,9 @@
 SOCKOPS_WRAP(irda_stream, PF_IRDA);
 SOCKOPS_WRAP(irda_seqpacket, PF_IRDA);
 SOCKOPS_WRAP(irda_dgram, PF_IRDA);
+#ifdef CONFIG_IRDA_ULTRA
+SOCKOPS_WRAP(irda_ultra, PF_IRDA);
+#endif /* CONFIG_IRDA_ULTRA */
 
 /*
  * Function irda_device_event (this, event, ptr)
@@ -2416,7 +2489,9 @@
 #endif
 	return 0;
 }
-module_init(irda_proto_init);
+#ifdef MODULE
+module_init(irda_proto_init);	/* If non-module, called from init/main.c */
+#endif
 
 /*
  * Function irda_proto_cleanup (void)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)