Sophie

Sophie

distrib > Mandriva > 2009.0 > i586 > by-pkgid > 0e3fdb557fa7934b4aa1ea3c70702470 > files > 1

dip-3.3.7o-28mdv2009.0.src.rpm

--- dip-3.3.7o/command.c.amd64	2003-10-02 14:14:45.000000000 +0200
+++ dip-3.3.7o/command.c	2003-10-02 14:32:47.000000000 +0200
@@ -28,6 +28,7 @@
  *		Foundation;  either  version 2 of the License, or  (at
  *		your option) any later version.
  */
+#define _GNU_SOURCE 1 /* stpcpy() is a GNU extension */
 #include "dip.h"
 #include <netinet/ip.h>
 #include <netinet/udp.h>
@@ -2670,6 +2671,107 @@ udp_check(struct udphdr *uh, int len,
 	return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, 0));
 }
 
+#elif defined(__x86_64__)
+
+/*
+ * The following routines come from linux/include/asm-x86_64/checksum.h
+ */
+
+/**
+ * ip_fast_csum - Compute the IPv4 header checksum efficiently.
+ * iph: ipv4 header
+ * ihl: length of header / 4
+ */ 
+static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl) 
+{
+	unsigned int sum;
+
+	asm(	"  movl (%1), %0\n"
+		"  subl $4, %2\n"
+		"  jbe 2f\n"
+		"  addl 4(%1), %0\n"
+		"  adcl 8(%1), %0\n"
+		"  adcl 12(%1), %0\n"
+		"1: adcl 16(%1), %0\n"
+		"  lea 4(%1), %1\n"
+		"  decl %2\n"
+		"  jne	1b\n"
+		"  adcl $0, %0\n"
+		"  movl %0, %2\n"
+		"  shrl $16, %0\n"
+		"  addw %w2, %w0\n"
+		"  adcl $0, %0\n"
+		"  notl %0\n"
+		"2:"
+	/* Since the input registers which are loaded with iph and ipl
+	   are modified, we must also specify them as outputs, or gcc
+	   will assume they contain their original values. */
+	: "=r" (sum), "=r" (iph), "=r" (ihl)
+	: "1" (iph), "2" (ihl));
+	return(sum);
+}
+
+/** 
+ * csum_fold - Fold and invert a 32bit checksum.
+ * sum: 32bit unfolded sum
+ * 
+ * Fold a 32bit running checksum to 16bit and invert it. This is usually
+ * the last step before putting a checksum into a packet.
+ * Make sure not to mix with 64bit checksums.
+ */
+static inline unsigned int csum_fold(unsigned int sum)
+{
+	__asm__(
+		"  addl %1,%0\n"
+		"  adcl $0xffff,%0"
+		: "=r" (sum)
+		: "r" (sum << 16), "0" (sum & 0xffff0000)
+	);
+	return (~sum) >> 16;
+}
+
+/** 
+ * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum.
+ * @saddr: source address
+ * @daddr: destination address
+ * @len: length of packet
+ * @proto: ip protocol of packet
+ * @sum: initial sum to be added in (32bit unfolded) 
+ * 
+ * Returns the pseudo header checksum the input data. Result is 
+ * 32bit unfolded.
+ */
+static inline unsigned long 
+csum_tcpudp_nofold(unsigned saddr, unsigned daddr, unsigned short len,
+		   unsigned short proto, unsigned int sum) 
+{
+  asm("  addl %1, %0\n"
+      "  adcl %2, %0\n"
+      "  adcl %3, %0\n"
+      "  adcl $0, %0\n"
+      : "=r" (sum)
+      : "g" (daddr), "g" (saddr), "g" ((ntohs(len)<<16)+proto*256), "0" (sum));
+  return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned short int
+csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
+		  unsigned short proto, unsigned int sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
+}
+
+static unsigned short
+udp_check(struct udphdr *uh, int len,
+	unsigned long saddr, unsigned long daddr)
+{
+	return(csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, 0));
+}
+
 #else
 
 #error You need to write tcp/ip checksum routines for your architecture