patch-2.3.39 linux/net/core/iovec.c
Next file: linux/net/decnet/Config.in
Previous file: linux/mm/memory.c
Back to the patch index
Back to the overall index
-  Lines: 43
-  Date:
Sat Jan  8 21:36:20 2000
-  Orig file: 
v2.3.38/linux/net/core/iovec.c
-  Orig date: 
Tue Sep  7 12:14:07 1999
diff -u --recursive --new-file v2.3.38/linux/net/core/iovec.c linux/net/core/iovec.c
@@ -99,7 +99,41 @@
 	}
 	err = 0;
 out:
-	return err; 
+	return err;
+}
+
+/* Copy and checkum skb to user iovec. Caller _must_ check that
+   skb will fit to this iovec.
+ */
+
+int copy_and_csum_toiovec(struct iovec *iov, struct sk_buff *skb, int hlen)
+{
+	unsigned int csum;
+	int chunk = skb->len - hlen;
+
+	/* Skip filled elements. Pretty silly, look at mecpy_toiove, though 8) */
+	while (iov->iov_len == 0)
+		iov++;
+
+	if (iov->iov_len < chunk) {
+		if ((unsigned short)csum_fold(csum_partial(skb->h.raw, chunk+hlen, skb->csum)))
+			goto csum_error;
+		if (memcpy_toiovec(iov, skb->h.raw + hlen, chunk))
+			goto csum_error;
+	} else {
+		int err = 0;
+		csum = csum_partial(skb->h.raw, hlen, skb->csum);
+		csum = csum_and_copy_to_user(skb->h.raw+hlen, iov->iov_base,
+					     chunk, csum, &err);
+		if (err || ((unsigned short)csum_fold(csum)))
+			goto csum_error;
+		iov->iov_len -= chunk;
+		iov->iov_base += chunk;
+	}
+	return 0;
+
+csum_error:
+	return -EFAULT;
 }
 
 /*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)