00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "config.h"
00010
00011 #include "dnet.h"
00012
00013 #define IP6_IS_EXT(n) \
00014 ((n) == IP_PROTO_HOPOPTS || (n) == IP_PROTO_DSTOPTS || \
00015 (n) == IP_PROTO_ROUTING || (n) == IP_PROTO_FRAGMENT)
00016
00017 void
00018 ip6_checksum(void *buf, size_t len)
00019 {
00020 struct ip6_hdr *ip6 = (struct ip6_hdr *)buf;
00021 struct ip6_ext_hdr *ext;
00022 u_char *p, nxt;
00023 int i, sum;
00024
00025 nxt = ip6->ip6_nxt;
00026
00027 for (i = IP6_HDR_LEN; IP6_IS_EXT(nxt); i += (ext->ext_len + 1) << 3) {
00028 if (i >= (int)len) return;
00029 ext = (struct ip6_ext_hdr *)((u_char *)buf + i);
00030 nxt = ext->ext_nxt;
00031 }
00032 p = (u_char *)buf + i;
00033 len -= i;
00034
00035 if (nxt == IP_PROTO_TCP) {
00036 struct tcp_hdr *tcp = (struct tcp_hdr *)p;
00037
00038 if (len >= TCP_HDR_LEN) {
00039 tcp->th_sum = 0;
00040 sum = ip_cksum_add(tcp, len, 0) + htons(nxt + len);
00041 sum = ip_cksum_add(&ip6->ip6_src, 32, sum);
00042 tcp->th_sum = ip_cksum_carry(sum);
00043 }
00044 } else if (nxt == IP_PROTO_UDP) {
00045 struct udp_hdr *udp = (struct udp_hdr *)p;
00046
00047 if (len >= UDP_HDR_LEN) {
00048 udp->uh_sum = 0;
00049 sum = ip_cksum_add(udp, len, 0) + htons(nxt + len);
00050 sum = ip_cksum_add(&ip6->ip6_src, 32, sum);
00051 if ((udp->uh_sum = ip_cksum_carry(sum)) == 0)
00052 udp->uh_sum = 0xffff;
00053 }
00054 } else if (nxt == IP_PROTO_ICMPV6) {
00055 struct icmp_hdr *icmp = (struct icmp_hdr *)p;
00056
00057 if (len >= ICMP_HDR_LEN) {
00058 icmp->icmp_cksum = 0;
00059 sum = ip_cksum_add(icmp, len, 0) + htons(nxt + len);
00060 sum = ip_cksum_add(&ip6->ip6_src, 32, sum);
00061 icmp->icmp_cksum = ip_cksum_carry(sum);
00062 }
00063 } else if (nxt == IP_PROTO_ICMP || nxt == IP_PROTO_IGMP) {
00064 struct icmp_hdr *icmp = (struct icmp_hdr *)p;
00065
00066 if (len >= ICMP_HDR_LEN) {
00067 icmp->icmp_cksum = 0;
00068 sum = ip_cksum_add(icmp, len, 0);
00069 icmp->icmp_cksum = ip_cksum_carry(sum);
00070 }
00071 }
00072 }