📄 msripv6.c
字号:
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
//
// (c) Microsoft Corporation. All rights reserved.
//
// This file is part of the Microsoft Virtual Ring Routing distribution.
// You should have received a copy of the Microsoft Research Shared Source
// license agreement (MSR-SSLA) for this software; see the file "license.txt".
// If not, please see http://research.microsoft.com/vrr/license.htm,
// or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
//
//
// This file contains snips of msripv6 code being substituted for missing
// items from Windows DDK build environment.
//
#include "headers.h"
uint RandomValue;
//* Random - Generate a psuedo random value between 1 and 2^32.
//
// This routine is a quick and dirty psuedo random number generator.
// It has the advantages of being fast and consuming very little
// memory (for either code or data). The random numbers it produces are
// not of the best quality, however. A much better generator could be
// had if we were willing to use an extra 256 bytes of memory for data.
//
// This routine uses the linear congruential method (see Knuth, Vol II),
// with specific values for the multiplier and constant taken from
// Numerical Recipes in C Second Edition by Press, et. al.
//
uint // Returns: A random value between 1 and 2^32.
Random(void)
{
//
// The algorithm is R = (aR + c) mod m, where R is the random number,
// a is a magic multiplier, c is a constant, and the modulus m is the
// maximum number of elements in the period. We chose our m to be 2^32
// in order to get the mod operation for free.
// BUGBUG: What about concurrent calls?
//
RandomValue = (1664525 * RandomValue) + 1013904223;
return RandomValue;
}
//* SeedRandom - Provide a seed value.
//
// Called to provide a seed value for the random number generator.
//
void
SeedRandom(uint Seed)
{
int i;
//
// Incorporate the seed into our random value.
//
RandomValue ^= Seed;
//
// Stir the bits.
//
for (i = 0; i < 100; i++)
(void) Random();
}
//* RandomNumber
//
// Returns a number randomly selected from a range.
//
uint
RandomNumber(uint Min, uint Max)
{
uint Number;
//
// Note that the high bits of Random() are much more random
// than the low bits.
//
Number = Max - Min; // Spread.
Number = (uint)(((ULONGLONG)Random() * Number) >> 32); // Randomize spread.
Number += Min;
return Number;
}
//* ChecksumPacket - Calculate the Internet checksum of a packet.
//
// Taken from msripv6\tcpip6\ip6\subr.c
//
// Calculates the checksum of packet data. The data may be supplied
// either with the Packet/Offset arguments, or (if Packet is NULL)
// the Data argument. In either case, Length specifies how much
// data to checksum.
//
// The Packet is assumed to contain (at least) Offset + Length bytes.
//
// Also calculates and adds-in the pseudo-header checksum,
// using IP->Source, IP->Dest, Length, and NextHeader.
// (With options, we may have IP->NextHeader != NextHeader.)
//
ushort
ChecksumPacket(
PNDIS_PACKET Packet, // Packet with data to checksum.
uint Offset, // Offset into packet where data starts.
uchar *Data, // If Packet is NULL, data to checksum.
uint Length, // Length of packet data.
IPv6Addr *Source, // Source address.
IPv6Addr *Dest, // Destination address.
uchar NextHeader) // Protocol type for pseudo-header.
{
PNDIS_BUFFER Buffer = NULL;
uint Checksum;
uint PayloadLength;
uint Size;
uint TotalSummed;
//
// Start with the pseudo-header.
//
Checksum = Cksum((unsigned char *)Source, sizeof *Source) + Cksum((unsigned char *)Dest, sizeof *Dest);
PayloadLength = RtlUlongByteSwap(Length);
Checksum += (PayloadLength >> 16) + (PayloadLength & 0xffff);
Checksum += (NextHeader << 8);
if (Packet == NULL) {
//
// We do not have to initialize Buffer.
// The checksum loop below will exit before trying to use it.
//
Size = Length;
Data += Offset;
} else {
//
// Skip over Offset bytes in the packet.
//
Buffer = NdisFirstBuffer(Packet);
for (;;) {
Size = NdisBufferLength(Buffer);
//
// There is a boundary case here: the Packet contains
// exactly Offset bytes total, and Length is zero.
// Checking Offset <= Size instead of Offset < Size
// makes this work.
//
if (Offset <= Size) {
//Data = NdisBufferVirtualAddressSafe(Buffer, LowPagePriority);
Data = NdisBufferVirtualAddress(Buffer);
if (Data == NULL)
return 0;
Data += Offset;
Size -= Offset;
break;
}
Offset -= Size;
NdisGetNextBuffer(Buffer, &Buffer);
ASSERT(Buffer != NULL); // Caller ensures this.
}
}
for (TotalSummed = 0;;) {
ushort Temp;
//
// Size might be bigger than we need,
// if there is "extra" data in the packet.
//
if (Size > Length)
Size = Length;
Temp = Cksum(Data, Size);
if (TotalSummed & 1) {
// We're at an odd offset into the logical buffer,
// so we need to swap the bytes that Cksum returns.
Checksum += (Temp >> 8) + ((Temp & 0xff) << 8);
} else {
Checksum += Temp;
}
TotalSummed += Size;
Length -= Size;
if (Length == 0)
break;
// Buffer is always initialized if we reach here.
// So the next clause is redundant, but keeps PreFast happy.
if (Buffer == NULL)
break;
NdisGetNextBuffer(Buffer, &Buffer);
NdisQueryBufferSafe(Buffer, &Data, &Size, LowPagePriority);
if (Data == NULL)
return 0;
}
//
// Wrap in the carries to reduce Checksum to 16 bits.
// (Twice is sufficient because it can only overflow once.)
//
Checksum = (Checksum >> 16) + (Checksum & 0xffff);
Checksum += (Checksum >> 16);
//
// Take ones-complement and replace 0 with 0xffff.
//
Checksum = (ushort) ~Checksum;
if (Checksum == 0)
Checksum = 0xffff;
return (ushort) Checksum;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -