linux-bk/include/net/checksum.h History
<<
>>
Prefs
   1/*
   2 * INET         An implementation of the TCP/IP protocol suite for the LINUX
   3 *              operating system.  INET is implemented using the  BSD Socket
   4 *              interface as the means of communication with the user level.
   5 *
   6 *              Checksumming functions for IP, TCP, UDP and so on
   7 *
   8 * Authors:     Jorge Cwik, <jorge@laser.satlink.net>
   9 *              Arnt Gulbrandsen, <agulbra@nvg.unit.no>
  10 *              Borrows very liberally from tcp.c and ip.c, see those
  11 *              files for more names.
  12 *
  13 *              This program is free software; you can redistribute it and/or
  14 *              modify it under the terms of the GNU General Public License
  15 *              as published by the Free Software Foundation; either version
  16 *              2 of the License, or (at your option) any later version.
  17 */
  18
  19/*
  20 *      Fixes:
  21 *
  22 *      Ralf Baechle                    :       generic ipv6 checksum
  23 *      <ralf@waldorf-gmbh.de>
  24 */
  25
  26#ifndef _CHECKSUM_H
  27#define _CHECKSUM_H
  28
  29#include <asm/types.h>
  30#include <asm/byteorder.h>
  31#include <net/ip.h>
  32#include <linux/in6.h>
  33#include <asm/uaccess.h>
  34#include <asm/checksum.h>
  35
  36#ifndef _HAVE_ARCH_IPV6_CSUM
  37
  38static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
  39                                                     struct in6_addr *daddr,
  40                                                     __u16 len,
  41                                                     unsigned short proto,
  42                                                     unsigned int csum) 
  43{
  44
  45        int carry;
  46        __u32 ulen;
  47        __u32 uproto;
  48
  49        csum += saddr->s6_addr32[0];
  50        carry = (csum < saddr->s6_addr32[0]);
  51        csum += carry;
  52
  53        csum += saddr->s6_addr32[1];
  54        carry = (csum < saddr->s6_addr32[1]);
  55        csum += carry;
  56
  57        csum += saddr->s6_addr32[2];
  58        carry = (csum < saddr->s6_addr32[2]);
  59        csum += carry;
  60
  61        csum += saddr->s6_addr32[3];
  62        carry = (csum < saddr->s6_addr32[3]);
  63        csum += carry;
  64
  65        csum += daddr->s6_addr32[0];
  66        carry = (csum < daddr->s6_addr32[0]);
  67        csum += carry;
  68
  69        csum += daddr->s6_addr32[1];
  70        carry = (csum < daddr->s6_addr32[1]);
  71        csum += carry;
  72
  73        csum += daddr->s6_addr32[2];
  74        carry = (csum < daddr->s6_addr32[2]);
  75        csum += carry;
  76
  77        csum += daddr->s6_addr32[3];
  78        carry = (csum < daddr->s6_addr32[3]);
  79        csum += carry;
  80
  81        ulen = htonl((__u32) len);
  82        csum += ulen;
  83        carry = (csum < ulen);
  84        csum += carry;
  85
  86        uproto = htonl(proto);
  87        csum += uproto;
  88        carry = (csum < uproto);
  89        csum += carry;
  90
  91        return csum_fold(csum);
  92}
  93
  94#endif
  95
  96#ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
  97static inline
  98unsigned int csum_and_copy_from_user (const char *src, char *dst,
  99                                      int len, int sum, int *err_ptr)
 100{
 101        if (verify_area(VERIFY_READ, src, len) == 0)
 102                return csum_partial_copy_from_user(src, dst, len, sum, err_ptr);
 103
 104        if (len)
 105                *err_ptr = -EFAULT;
 106
 107        return sum;
 108}
 109#endif
 110
 111#ifndef HAVE_CSUM_COPY_USER
 112static __inline__ unsigned int csum_and_copy_to_user
 113(const char *src, char *dst, int len, unsigned int sum, int *err_ptr)
 114{
 115        sum = csum_partial(src, len, sum);
 116
 117        if (access_ok(VERIFY_WRITE, dst, len)) {
 118                if (copy_to_user(dst, src, len) == 0)
 119                        return sum;
 120        }
 121        if (len)
 122                *err_ptr = -EFAULT;
 123
 124        return -1; /* invalid checksum */
 125}
 126#endif
 127
 128static inline unsigned int csum_add(unsigned int csum, unsigned int addend)
 129{
 130        csum += addend;
 131        return csum + (csum < addend);
 132}
 133
 134static inline unsigned int csum_sub(unsigned int csum, unsigned int addend)
 135{
 136        return csum_add(csum, ~addend);
 137}
 138
 139static inline unsigned int
 140csum_block_add(unsigned int csum, unsigned int csum2, int offset)
 141{
 142        if (offset&1)
 143                csum2 = ((csum2&0xFF00FF)<<8)+((csum2>>8)&0xFF00FF);
 144        return csum_add(csum, csum2);
 145}
 146
 147static inline unsigned int
 148csum_block_sub(unsigned int csum, unsigned int csum2, int offset)
 149{
 150        if (offset&1)
 151                csum2 = ((csum2&0xFF00FF)<<8)+((csum2>>8)&0xFF00FF);
 152        return csum_sub(csum, csum2);
 153}
 154
 155#endif
 156
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.