1  /* $Id: cksum.c 98103 20230117 14:15:46Z vboxsync $ */


2  /** @file


3  * NAT  IP checksum generation.


4  */


5 


6  /*


7  * Copyright (C) 20062023 Oracle and/or its affiliates.


8  *


9  * This file is part of VirtualBox base platform packages, as


10  * available from https://www.virtualbox.org.


11  *


12  * This program is free software; you can redistribute it and/or


13  * modify it under the terms of the GNU General Public License


14  * as published by the Free Software Foundation, in version 3 of the


15  * License.


16  *


17  * This program is distributed in the hope that it will be useful, but


18  * WITHOUT ANY WARRANTY; without even the implied warranty of


19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU


20  * General Public License for more details.


21  *


22  * You should have received a copy of the GNU General Public License


23  * along with this program; if not, see <https://www.gnu.org/licenses>.


24  *


25  * SPDXLicenseIdentifier: GPL3.0only


26  */


27 


28  /*


29  * This code is based on:


30  *


31  * Copyright (c) 1988, 1992, 1993


32  * The Regents of the University of California. All rights reserved.


33  *


34  * Redistribution and use in source and binary forms, with or without


35  * modification, are permitted provided that the following conditions


36  * are met:


37  * 1. Redistributions of source code must retain the above copyright


38  * notice, this list of conditions and the following disclaimer.


39  * 2. Redistributions in binary form must reproduce the above copyright


40  * notice, this list of conditions and the following disclaimer in the


41  * documentation and/or other materials provided with the distribution.


42  * 3. Neither the name of the University nor the names of its contributors


43  * may be used to endorse or promote products derived from this software


44  * without specific prior written permission.


45  *


46  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND


47  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE


48  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE


49  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE


50  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL


51  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS


52  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)


53  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT


54  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY


55  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF


56  * SUCH DAMAGE.


57  *


58  * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93


59  * in_cksum.c,v 1.2 1994/08/02 07:48:16 davidg Exp


60  */


61 


62  #include <slirp.h>


63 


64  /*


65  * Checksum routine for Internet Protocol family headers (Portable Version).


66  *


67  * This routine is very heavily used in the network


68  * code and should be modified for each CPU to be as fast as possible.


69  *


70  * XXX Since we will never span more than 1 mbuf, we can optimise this


71  */


72 


73  #define ADDCARRY(x) (x > 65535 ? x = 65535 : x)


74  #define REDUCE { l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum); }


75 


76  int cksum(struct mbuf *m, int len)


77  {


78  register u_int16_t *w;


79  register int sum = 0;


80  register int mlen = 0;


81  int byte_swapped = 0;


82 


83  union


84  {


85  u_int8_t c[2];


86  u_int16_t s;


87  } s_util;


88  union


89  {


90  u_int16_t s[2];


91  u_int32_t l;


92  } l_util;


93 


94  if (m>m_len == 0)


95  goto cont;


96  w = mtod(m, u_int16_t *);


97 


98  mlen = m>m_len;


99 


100  if (len < mlen)


101  mlen = len;


102  len = mlen;


103  /*


104  * Force to even boundary.


105  */


106  if ((1 & (long) w) && (mlen > 0))


107  {


108  REDUCE;


109  sum <<= 8;


110  s_util.c[0] = *(u_int8_t *)w;


111  w = (u_int16_t *)((int8_t *)w + 1);


112  mlen;


113  byte_swapped = 1;


114  }


115  /*


116  * Unroll the loop to make overhead from


117  * branches &c small.


118  */


119  while ((mlen = 32) >= 0)


120  {


121  sum += w[ 0]; sum += w[ 1]; sum += w[ 2]; sum += w[ 3];


122  sum += w[ 4]; sum += w[ 5]; sum += w[ 6]; sum += w[ 7];


123  sum += w[ 8]; sum += w[ 9]; sum += w[10]; sum += w[11];


124  sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];


125  w += 16;


126  }


127  mlen += 32;


128  while ((mlen = 8) >= 0)


129  {


130  sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];


131  w += 4;


132  }


133  mlen += 8;


134  if (mlen == 0 && byte_swapped == 0)


135  goto cont;


136  REDUCE;


137  while ((mlen = 2) >= 0)


138  {


139  sum += *w++;


140  }


141 


142  if (byte_swapped)


143  {


144  REDUCE;


145  sum <<= 8;


146  byte_swapped = 0;


147  if (mlen == 1)


148  {


149  s_util.c[1] = *(u_int8_t *)w;


150  sum += s_util.s;


151  mlen = 0;


152  }


153  else


154  mlen = 1;


155  }


156  else if (mlen == 1)


157  s_util.c[0] = *(u_int8_t *)w;


158 


159  cont:


160  #ifdef DEBUG


161  if (len)


162  Log(("cksum: out of data: len = %d\n", len));


163  #endif


164  if (mlen == 1)


165  {


166  /* The last mbuf has odd # of bytes. Follow the


167  standard (the odd byte may be shifted left by 8 bits


168  or not as determined by endianness of the machine) */


169  s_util.c[1] = 0;


170  sum += s_util.s;


171  }


172  REDUCE;


173  return (~sum & 0xffff);


174  }

