1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1996-2001 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #include <sys/types.h> 28 #include <strings.h> 29 #include <netinet/in.h> 30 #include "v4_sum_impl.h" 31 32 /* 33 * RFC 768 pseudo header. Used in calculating UDP checksums. 34 */ 35 struct pseudo_udp { 36 struct in_addr src; 37 struct in_addr dst; 38 uint8_t notused; /* always zero */ 39 uint8_t proto; /* protocol used */ 40 uint16_t len; /* UDP len */ 41 }; 42 43 /* 44 * One's complement checksum of pseudo header, udp header, and data. 45 * Must be MT SAFE. 46 */ 47 uint16_t 48 udp_chksum(struct udphdr *udph, const struct in_addr *src, 49 const struct in_addr *dst, uint8_t proto) 50 { 51 struct pseudo_udp ck; 52 uint16_t *end_pseudo_hdr = (uint16_t *)(&ck + 1); 53 uint16_t *sp = (uint16_t *)&ck; 54 uint_t sum = 0; 55 uint16_t cnt; 56 57 /* 58 * Start on the pseudo header. Note that pseudo_udp already takes 59 * acount for the udphdr... 60 */ 61 62 bzero(&ck, sizeof (ck)); 63 64 /* struct copies */ 65 ck.src = *src; 66 ck.dst = *dst; 67 ck.len = udph->uh_ulen; 68 ck.proto = proto; 69 70 /* 71 * If the packet is an odd length, zero the pad byte for checksum 72 * purposes [doesn't hurt data] 73 */ 74 75 cnt = ntohs(ck.len) + sizeof (ck); 76 if (cnt & 1) { 77 ((caddr_t)udph)[ntohs(udph->uh_ulen)] = '\0'; 78 cnt++; /* make even */ 79 } 80 81 for (cnt >>= 1; cnt != 0; cnt--) { 82 83 sum += *sp++; 84 if (sum >= BIT_WRAP) { 85 /* Wrap carries into low bit */ 86 sum -= BIT_WRAP; 87 sum++; 88 } 89 90 /* 91 * If we've finished checking the pseudo-header, move 92 * onto the udp header and data. 93 */ 94 95 if (sp == end_pseudo_hdr) 96 sp = (uint16_t *)udph; 97 } 98 99 return (~sum == 0 ? ~0 : ~sum); 100 } 101