|
|
1.1 ! root 1: #ifndef _I386_CHECKSUM_H ! 2: #define _I386_CHECKSUM_H ! 3: ! 4: /* ! 5: * computes the checksum of a memory block at buff, length len, ! 6: * and adds in "sum" (32-bit) ! 7: * ! 8: * returns a 32-bit number suitable for feeding into itself ! 9: * or csum_tcpudp_magic ! 10: * ! 11: * this function must be called with even lengths, except ! 12: * for the last fragment, which may be odd ! 13: * ! 14: * it's best to have buff aligned on a 32-bit boundary ! 15: */ ! 16: unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum); ! 17: ! 18: /* ! 19: * the same as csum_partial, but copies from src while it ! 20: * checksums ! 21: * ! 22: * here even more important to align src and dst on a 32-bit (or even ! 23: * better 64-bit) boundary ! 24: */ ! 25: ! 26: unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum); ! 27: ! 28: ! 29: /* ! 30: * the same as csum_partial_copy, but copies from user space. ! 31: * ! 32: * here even more important to align src and dst on a 32-bit (or even ! 33: * better 64-bit) boundary ! 34: */ ! 35: ! 36: unsigned int csum_partial_copy_fromuser(const char *src, char *dst, int len, int sum); ! 37: ! 38: /* ! 39: * This is a version of ip_compute_csum() optimized for IP headers, ! 40: * which always checksum on 4 octet boundaries. ! 41: * ! 42: * By Jorge Cwik <[email protected]>, adapted for linux by ! 43: * Arnt Gulbrandsen. ! 44: */ ! 45: static inline unsigned short ip_fast_csum(unsigned char * iph, ! 46: unsigned int ihl) { ! 47: unsigned int sum; ! 48: ! 49: __asm__ __volatile__(" ! 50: movl (%1), %0 ! 51: subl $4, %2 ! 52: jbe 2f ! 53: addl 4(%1), %0 ! 54: adcl 8(%1), %0 ! 55: adcl 12(%1), %0 ! 56: 1: adcl 16(%1), %0 ! 57: lea 4(%1), %1 ! 58: decl %2 ! 59: jne 1b ! 60: adcl $0, %0 ! 61: movl %0, %2 ! 62: shrl $16, %0 ! 63: addw %w2, %w0 ! 64: adcl $0, %0 ! 65: notl %0 ! 66: 2: ! 67: " ! 68: /* Since the input registers which are loaded with iph and ipl ! 69: are modified, we must also specify them as outputs, or gcc ! 70: will assume they contain their original values. */ ! 71: : "=r" (sum), "=r" (iph), "=r" (ihl) ! 72: : "1" (iph), "2" (ihl)); ! 73: return(sum); ! 74: } ! 75: ! 76: /* ! 77: * Fold a partial checksum ! 78: */ ! 79: ! 80: static inline unsigned int csum_fold(unsigned int sum) ! 81: { ! 82: __asm__(" ! 83: addl %1, %0 ! 84: adcl $0xffff, %0 ! 85: " ! 86: : "=r" (sum) ! 87: : "r" (sum << 16), "0" (sum & 0xffff0000) ! 88: ); ! 89: return (~sum) >> 16; ! 90: } ! 91: ! 92: /* ! 93: * computes the checksum of the TCP/UDP pseudo-header ! 94: * returns a 16-bit checksum, already complemented ! 95: */ ! 96: ! 97: static inline unsigned short int csum_tcpudp_magic(unsigned long saddr, ! 98: unsigned long daddr, ! 99: unsigned short len, ! 100: unsigned short proto, ! 101: unsigned int sum) { ! 102: __asm__(" ! 103: addl %1, %0 ! 104: adcl %2, %0 ! 105: adcl %3, %0 ! 106: adcl $0, %0 ! 107: " ! 108: : "=r" (sum) ! 109: : "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum)); ! 110: return csum_fold(sum); ! 111: } ! 112: /* ! 113: * this routine is used for miscellaneous IP-like checksums, mainly ! 114: * in icmp.c ! 115: */ ! 116: ! 117: static inline unsigned short ip_compute_csum(unsigned char * buff, int len) { ! 118: return csum_fold (csum_partial(buff, len, 0)); ! 119: } ! 120: ! 121: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.