blob: 45c1e2edc5815ae30a5af1ea890cd23f6a04d4cc [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdint.h>
#include <limits>
#include "src/bringup/bin/netsvc/inet6.h"
static uint16_t checksum(const void* _data, size_t len, uint16_t _sum) {
uint32_t sum = _sum;
const uint16_t* data = static_cast<const uint16_t*>(_data);
while (len > 1) {
sum += *data++;
len -= 2;
}
if (len) {
sum += (*data & 0xFF);
}
while (sum > std::numeric_limits<uint16_t>::max()) {
sum = (sum & 0xFFFF) + (sum >> 16);
}
return static_cast<uint16_t>(sum);
}
uint16_t ip6_header_checksum(const ip6_hdr_t& ip, uint8_t type) {
// Length and protocol field for pseudo-header.
const uint16_t sum = checksum(&ip.length, 2, htons(type));
// src/dst for pseudo-header + payload.
return checksum(&ip.src, 32, sum);
}
uint16_t ip6_finalize_checksum(uint16_t header_checksum, const void* payload, size_t len) {
return ~checksum(payload, len, header_checksum);
}