2 * $Id: libnet_checksum.c,v 1.1.1.1 2000/05/25 00:28:49 route Exp $
5 * libnet_checksum.c - IP checksum routines
7 * Copyright (c) 1998 - 2001 Mike D. Schiffman <mike@infonexus.com>
8 * Copyright (c) 1999, 2000 Dug Song <dugsong@monkey.org>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include "../include/config.h"
37 #include "../include/libnet.h"
40 libnet_in_cksum(u_short *addr, int len)
59 *(u_char *)(&ans) = *(u_char *)w;
67 libnet_do_checksum(u_char *buf, int protocol, int len)
69 struct libnet_ip_hdr *iph_p;
74 iph_p = (struct libnet_ip_hdr *)buf;
75 ip_hl = iph_p->ip_hl << 2;
78 * Dug Song came up with this very cool checksuming implementation
79 * eliminating the need for explicit psuedoheader use. Check it out.
84 * Style note: normally I don't advocate declaring variables inside
85 * blocks of control, but it makes good sense here. -- MDS
89 struct libnet_tcp_hdr *tcph_p =
90 (struct libnet_tcp_hdr *)(buf + ip_hl);
92 #if (STUPID_SOLARIS_CHECKSUM_BUG)
93 tcph_p->th_sum = tcph_p->th_off << 2;
95 #endif /* STUPID_SOLARIS_CHECKSUM_BUG */
98 sum = libnet_in_cksum((u_short *)&iph_p->ip_src, 8);
99 sum += ntohs(IPPROTO_TCP + len);
100 sum += libnet_in_cksum((u_short *)tcph_p, len);
101 tcph_p->th_sum = LIBNET_CKSUM_CARRY(sum);
106 struct libnet_udp_hdr *udph_p =
107 (struct libnet_udp_hdr *)(buf + ip_hl);
110 sum = libnet_in_cksum((u_short *)&iph_p->ip_src, 8);
111 sum += ntohs(IPPROTO_UDP + len);
112 sum += libnet_in_cksum((u_short *)udph_p, len);
113 udph_p->uh_sum = LIBNET_CKSUM_CARRY(sum);
118 struct libnet_icmp_hdr *icmph_p =
119 (struct libnet_icmp_hdr *)(buf + ip_hl);
121 icmph_p->icmp_sum = 0;
122 sum = libnet_in_cksum((u_short *)icmph_p, len);
123 icmph_p->icmp_sum = LIBNET_CKSUM_CARRY(sum);
128 struct libnet_igmp_hdr *igmph_p =
129 (struct libnet_igmp_hdr *)(buf + ip_hl);
131 igmph_p->igmp_sum = 0;
132 sum = libnet_in_cksum((u_short *)igmph_p, len);
133 igmph_p->igmp_sum = LIBNET_CKSUM_CARRY(sum);
138 struct libnet_ospf_hdr *oh_p =
139 (struct libnet_ospf_hdr *)(buf + ip_hl);
141 u_char *payload = (u_char *)(buf + ip_hl + LIBNET_AUTH_H +
143 u_char *tbuf = (u_char *)malloc(sizeof(oh_p) + sizeof(payload));
148 oh_p->ospf_cksum = 0;
149 sum += libnet_in_cksum((u_short *)tbuf, sizeof(tbuf));
150 oh_p->ospf_cksum = LIBNET_CKSUM_CARRY(sum);
154 case IPPROTO_OSPF_LSA:
157 * Reworked fletcher checksum taken from RFC 1008.
160 struct libnet_lsa_hdr *lsa_p = (struct libnet_lsa_hdr *)buf;
161 u_char *p, *p1, *p2, *p3;
166 lsa_p->lsa_cksum[0] = 0;
167 lsa_p->lsa_cksum[1] = 0; /* zero out checksum */
171 p3 = buf + len; /* beginning and end of buf */
175 p2 = p1 + LIBNET_MODX;
181 for (p = p1; p < p2; p++)
188 c1 %= 255; /* modular 255 */
193 lsa_p->lsa_cksum[0] = (((len - 17) * c0 - c1) % 255);
194 if (lsa_p->lsa_cksum[0] <= 0)
196 lsa_p->lsa_cksum[0] += 255;
199 lsa_p->lsa_cksum[1] = (510 - c0 - lsa_p->lsa_cksum[0]);
200 if (lsa_p->lsa_cksum[1] > 255)
202 lsa_p->lsa_cksum[1] -= 255;
209 sum = libnet_in_cksum((u_short *)iph_p, len);
210 iph_p->ip_sum = LIBNET_CKSUM_CARRY(sum);
215 struct libnet_vrrp_hdr *vrrph_p =
216 (struct libnet_vrrp_hdr *)(buf + ip_hl);
218 vrrph_p->vrrp_sum = 0;
219 sum = libnet_in_cksum((u_short *)vrrph_p, len);
220 vrrph_p->vrrp_sum = LIBNET_CKSUM_CARRY(sum);
226 libnet_error(LN_ERR_CRITICAL, "do_checksum: UNSUPP protocol %d\n",
237 libnet_ip_check(u_short *addr, int len)
241 sum = libnet_in_cksum(addr, len);
242 return (LIBNET_CKSUM_CARRY(sum));