|
@@ -1,1618 +0,0 @@
|
|
-(* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
|
|
|
|
-
|
|
|
|
-MODULE IP; (** AUTHOR "pjm, mvt, eb"; PURPOSE "IP (v4 and v6)"; *)
|
|
|
|
-
|
|
|
|
-IMPORT SYSTEM, KernelLog, Commands, Strings, Network;
|
|
|
|
-
|
|
|
|
-CONST
|
|
|
|
- (* DEBUG *)
|
|
|
|
- DEBUG = TRUE;
|
|
|
|
-
|
|
|
|
- (** Error codes *)
|
|
|
|
- Ok* = 0;
|
|
|
|
- DeviceAlreadyUsed* = 3901;
|
|
|
|
- DuplicateInterfaceName* = 3902;
|
|
|
|
- NoInterfaceName* = 3903;
|
|
|
|
- GatewayNotInSubnet* = 3904;
|
|
|
|
- IPv6AdrUsedOnIPv4Interface* = 4001;
|
|
|
|
- IPv4AdrUsedOnIPv6Interface* = 4002;
|
|
|
|
- DublicatedAddresses* = 4003;
|
|
|
|
- MixedIpProtocols* = 4003;
|
|
|
|
- LocalAdrSetIntv6* = 4004; (* local address must be NIL when calling SetAdrs on a IPv6 interface *)
|
|
|
|
- PrefixNotSet* = 4005; (* prefix on ipv6 interface must be set with local address *)
|
|
|
|
-
|
|
|
|
- MaxNofDNS* = 10; (** maximum number of DNS servers per interface *)
|
|
|
|
- MaxTTL* = 255; (** maximum time-to-live on outgoing datagrams *)
|
|
|
|
-
|
|
|
|
- NbrOfReceivers = 255; (* Number of possible receivers, i.e. possible layer 3 protocols *)
|
|
|
|
-
|
|
|
|
- (** IP address constants *)
|
|
|
|
- NilAdrIPv4 = 0;
|
|
|
|
-
|
|
|
|
- (* Comparators for Adr.usedProtocols *)
|
|
|
|
- IPv4* = 4;
|
|
|
|
- IPv6* = 6;
|
|
|
|
- NilAdrIdent = -1; (* usedProtocol of NilAdrs *)
|
|
|
|
-
|
|
|
|
- (* ICMP *)
|
|
|
|
- ICMPHdrLen* = 4;
|
|
|
|
- ICMPSrcLLAdrOptionType* = 1;
|
|
|
|
- ICMPTargetLLAdrOptionType* = 2;
|
|
|
|
- ICMPPrefixInfoOptionType* = 3;
|
|
|
|
- ICMPRedirectHdrOptionType* = 4;
|
|
|
|
- ICMPMTUOptionType* = 5;
|
|
|
|
- ICMPAdvIntOptionType* = 7;
|
|
|
|
- ICMPHomeAgOptionType* = 8;
|
|
|
|
- ICMPRouteOption* = 9;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-TYPE
|
|
|
|
- Adr* = RECORD
|
|
|
|
- ipv4Adr*: LONGINT;
|
|
|
|
- ipv6Adr*: ARRAY 16 OF CHAR;
|
|
|
|
- usedProtocol*: LONGINT;
|
|
|
|
- data*: LONGINT;
|
|
|
|
- END; (** An IP Address. usedProtocol = 0: No protocol yet used
|
|
|
|
- usedProtocol = IPv4: IPv4 address stored in field ipv4Adr
|
|
|
|
- usedProtocol = IPv6: IPv6 address stored in field ipv6Adr
|
|
|
|
- data can be used to store additional informations. I.e. in IPv6 the
|
|
|
|
- prefix length is stored in the data field *)
|
|
|
|
-
|
|
|
|
-TYPE
|
|
|
|
- Packet* = POINTER TO ARRAY OF CHAR;
|
|
|
|
-
|
|
|
|
- Name* = ARRAY 128 OF CHAR; (** Name type for interface name *)
|
|
|
|
-
|
|
|
|
- Interface* = OBJECT
|
|
|
|
- VAR
|
|
|
|
- (** IP addresses of this interface. *)
|
|
|
|
- localAdr*, maskAdr*, gatewayAdr*, subnetAdr*, broadAdr*: Adr;
|
|
|
|
-
|
|
|
|
- (** name of the interface *)
|
|
|
|
- name*: Name;
|
|
|
|
-
|
|
|
|
- (** Device that the interface belongs to *)
|
|
|
|
- dev*: Network.LinkDevice;
|
|
|
|
-
|
|
|
|
- (** DNS server list - can be used by DNS, not used in IP itself *)
|
|
|
|
- DNS-: ARRAY MaxNofDNS OF Adr; (* DNS server list *)
|
|
|
|
- DNScount*: LONGINT; (* number of DNS servers in list *)
|
|
|
|
-
|
|
|
|
- (* interface *)
|
|
|
|
- next*: Interface; (* next pointer for interface list *)
|
|
|
|
- closed*: BOOLEAN; (* is interface already closed? *)
|
|
|
|
- protocol*: LONGINT; (* Interface for IPv4 or IPv6?. Only used by IP otherwise use dynamic type checking! *)
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Set addresses. Is normally called just after instanciation, but can also be called later, e.g. by DHCP.
|
|
|
|
- If "gatewayAdr" is "NilAdr", the subnet is considered to have no gateway, else it must be in the same
|
|
|
|
- subnet as the "localAdr".
|
|
|
|
- "domain" can be an empty string. It is normally used by a DNS implementation. It is not used in IP directly.
|
|
|
|
- In IPv6 maskAdr is the prefix of the currently IP address *)
|
|
|
|
- PROCEDURE SetAdrs*(localAdr, maskOrPrefixAdr, gatewayAdr: Adr; VAR res: WORD);
|
|
|
|
- BEGIN
|
|
|
|
- (* Extensions have to override this method.*)
|
|
|
|
- HALT(99);
|
|
|
|
- END SetAdrs;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Remove all domain name servers from the interface. *)
|
|
|
|
- PROCEDURE DNSRemoveAll*;
|
|
|
|
- BEGIN {EXCLUSIVE}
|
|
|
|
- DNScount := 0;
|
|
|
|
- END DNSRemoveAll;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Add a domain name server to the interface. *)
|
|
|
|
- PROCEDURE DNSAdd*(adr: Adr);
|
|
|
|
- VAR
|
|
|
|
- i: LONGINT;
|
|
|
|
-
|
|
|
|
- BEGIN {EXCLUSIVE}
|
|
|
|
- (* concurrent lookup is consistent *)
|
|
|
|
- ASSERT(DNScount < MaxNofDNS);
|
|
|
|
-
|
|
|
|
- i := 0;
|
|
|
|
- WHILE i < DNScount DO
|
|
|
|
- IF AdrsEqual (DNS[i],adr) THEN RETURN END;
|
|
|
|
- INC(i)
|
|
|
|
- END;
|
|
|
|
- DNS[DNScount] := adr;
|
|
|
|
- INC(DNScount);
|
|
|
|
- END DNSAdd;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Remove a domain name server from the interface. *)
|
|
|
|
- PROCEDURE DNSRemove*(adr: Adr);
|
|
|
|
- VAR i: LONGINT;
|
|
|
|
- BEGIN {EXCLUSIVE}
|
|
|
|
- (* concurrent lookup could result in a duplicate address in worst-case *)
|
|
|
|
- (* this happends hardly ever and is harmless for DNS anyway *)
|
|
|
|
- i := 0;
|
|
|
|
- WHILE (i < DNScount) & (~ AdrsEqual(DNS[i],adr)) DO
|
|
|
|
- INC(i)
|
|
|
|
- END;
|
|
|
|
- IF i < DNScount THEN
|
|
|
|
- INC(i);
|
|
|
|
- WHILE i < DNScount DO
|
|
|
|
- DNS[i-1] := DNS[i];
|
|
|
|
- INC(i);
|
|
|
|
- END;
|
|
|
|
- DEC(DNScount);
|
|
|
|
- END;
|
|
|
|
- END DNSRemove;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Send an IP packet on this interface. *)
|
|
|
|
- PROCEDURE Send*(type: LONGINT; destAdr: Adr; CONST l4hdr, data: ARRAY OF CHAR; h4len, dofs, dlen, TTL: LONGINT);
|
|
|
|
- BEGIN
|
|
|
|
- (* Extensions have to override this method.*)
|
|
|
|
- HALT(99);
|
|
|
|
- END Send;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (* Internal procedure to perform the rest of the send operation. Used by "Send" and for IP forwarding. *)
|
|
|
|
- PROCEDURE DoSend*(destAdr: Adr; CONST l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT) ;
|
|
|
|
- BEGIN
|
|
|
|
- (* Extensions have to override this method.*)
|
|
|
|
- HALT(99);
|
|
|
|
- END DoSend;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Enumerate all ARP table entries. *)
|
|
|
|
- PROCEDURE ARPEnumerate*(handle: ARPHandler);
|
|
|
|
- BEGIN
|
|
|
|
- (* Extensions have to override this method.*)
|
|
|
|
- HALT(99);
|
|
|
|
- END ARPEnumerate;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Close and deactivate the interface, i.e. remove it from the configuration. *)
|
|
|
|
- PROCEDURE Close*;
|
|
|
|
- BEGIN
|
|
|
|
- (* Extensions have to override this method.*)
|
|
|
|
- HALT(99);
|
|
|
|
- END Close;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Check if adr is a broadcast address *)
|
|
|
|
- PROCEDURE IsBroadcast*(adr: Adr) : BOOLEAN;
|
|
|
|
- BEGIN
|
|
|
|
- (* Extensions have to override this method.*)
|
|
|
|
- HALT(99);
|
|
|
|
- END IsBroadcast;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Check if adr is a multicast address *)
|
|
|
|
- PROCEDURE IsMulticast*(adr: Adr) : BOOLEAN;
|
|
|
|
- BEGIN
|
|
|
|
- (* Extensions have to override this method.*)
|
|
|
|
- HALT(99);
|
|
|
|
- END IsMulticast;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Receive an IP packet *)
|
|
|
|
- PROCEDURE IPInput*(dev: Network.LinkDevice; type: LONGINT; buffer: Network.Buffer);
|
|
|
|
- BEGIN
|
|
|
|
- (* Extensions have to override this method.*)
|
|
|
|
- HALT(99);
|
|
|
|
- END IPInput;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Reads the source address of a IP packet buffer *)
|
|
|
|
- PROCEDURE ReadSrcAdr* (buffer: Network.Buffer): Adr;
|
|
|
|
- BEGIN
|
|
|
|
- (* Extensions have to override this method.*)
|
|
|
|
- HALT(99);
|
|
|
|
- END ReadSrcAdr;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Reads the destination address of a IP packet buffer *)
|
|
|
|
- PROCEDURE ReadDestAdr* (buffer: Network.Buffer): Adr;
|
|
|
|
- BEGIN
|
|
|
|
- (* Extensions have to override this method.*)
|
|
|
|
- HALT(99);
|
|
|
|
- END ReadDestAdr;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Creates a pseudo-header for checksum calculation (TCP/UDP) and returns the length of this header *)
|
|
|
|
- PROCEDURE WritePseudoHeader*(VAR pseudoHdr: ARRAY OF CHAR; src, dst: Adr; protocol, pktLengthUpperLayer: LONGINT): LONGINT;
|
|
|
|
- BEGIN
|
|
|
|
- (* Extensions have to override this method.*)
|
|
|
|
- HALT(99);
|
|
|
|
- END WritePseudoHeader;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (** Writes the configuration of this interface *)
|
|
|
|
- PROCEDURE OutInterface*;
|
|
|
|
- BEGIN
|
|
|
|
- (* Extensions have to override this method.*)
|
|
|
|
- HALT(99);
|
|
|
|
- END OutInterface;
|
|
|
|
-
|
|
|
|
- END Interface;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-TYPE
|
|
|
|
- (* List of interfaces *)
|
|
|
|
- InterfaceList* = POINTER TO RECORD
|
|
|
|
- interface*: Interface;
|
|
|
|
- next*: InterfaceList;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- Receiver* = PROCEDURE {DELEGATE} (int: Interface; type: LONGINT; fip, lip: Adr; buffer: Network.Buffer);
|
|
|
|
- V6InterfaceByDstIP* = PROCEDURE {DELEGATE} (dstAdr: Adr): Interface;
|
|
|
|
-
|
|
|
|
- (** Handler for ARPPool.Enumerate. *)
|
|
|
|
- ARPHandler* = PROCEDURE {DELEGATE} (ip: Adr; complete: BOOLEAN; link: Network.LinkAdr; size, sendTime, updateTime, updateDate, hash: LONGINT);
|
|
|
|
-
|
|
|
|
- InterfaceHandler* = PROCEDURE {DELEGATE} (int: Interface);
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-VAR
|
|
|
|
- (* receiver *)
|
|
|
|
- receivers*: ARRAY 256 OF Receiver; (* registered receivers - array position is IPv4 protocol field or IPv6 next header field *)
|
|
|
|
-
|
|
|
|
- (* Interface by dst for IPv6 *)
|
|
|
|
- v6InterfaceByDstIP*: V6InterfaceByDstIP;
|
|
|
|
-
|
|
|
|
- (* IP *)
|
|
|
|
- NilAdr*: Adr; (* To check if an IP address is NIL use IsNilAdr instead *)
|
|
|
|
- preferredProtocol*: LONGINT; (* Preferred IP protocol *)
|
|
|
|
-
|
|
|
|
- (* IP counters *)
|
|
|
|
- NIPSentToSubnet*, NIPSentToGateway*, NIPSentBroadcast*, NIPCantFragment*,
|
|
|
|
- NIPRcvTotal*, NIPTooSmall*, NIPBadVersion*, NIPOptions*, NIPBadChecksum*,
|
|
|
|
- NIPBadLength*, NIPTrim*, NIPBadHdrLen*, NIPNotForUs*, NIPCantReassemble*, NIPSrcIsBroadcast*,
|
|
|
|
- NIPDelivered*, NIPNoReceiver*, NIPForwarded*, NIPSentLocalLoopback*, NIPSentPointToPoint*: LONGINT;
|
|
|
|
-
|
|
|
|
- (* turn on/off IP forwarding, echo replay *)
|
|
|
|
- IPForwarding*: BOOLEAN;
|
|
|
|
- EchoReply*: BOOLEAN;
|
|
|
|
-
|
|
|
|
- (* Interface *)
|
|
|
|
- interfaces*: Interface; (* list of all installed interfaces *)
|
|
|
|
-
|
|
|
|
- counter: LONGINT; (* Use it only in the module body! *)
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Is address not yet specified *)
|
|
|
|
-PROCEDURE IsNilAdr* (adr: Adr): BOOLEAN;
|
|
|
|
-VAR
|
|
|
|
- isNil: BOOLEAN;
|
|
|
|
- i: LONGINT;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- CASE adr.usedProtocol OF
|
|
|
|
- IPv4:
|
|
|
|
- RETURN (adr.ipv4Adr = NilAdrIPv4)
|
|
|
|
-
|
|
|
|
- |IPv6:
|
|
|
|
- isNil := TRUE;
|
|
|
|
- i := 0;
|
|
|
|
- WHILE ((i<16) & isNil) DO
|
|
|
|
- IF adr.ipv6Adr[i] # 0X THEN
|
|
|
|
- isNil := FALSE;
|
|
|
|
- END;
|
|
|
|
- INC(i);
|
|
|
|
- END;
|
|
|
|
- RETURN isNil;
|
|
|
|
-
|
|
|
|
- |NilAdrIdent:
|
|
|
|
- RETURN TRUE;
|
|
|
|
-
|
|
|
|
- ELSE
|
|
|
|
- IF DEBUG THEN
|
|
|
|
- ASSERT(TRUE);
|
|
|
|
- END;
|
|
|
|
- RETURN TRUE;
|
|
|
|
- END;
|
|
|
|
-END IsNilAdr;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(* Checks if two addresses are equal *)
|
|
|
|
-PROCEDURE AdrsEqual* (adr1, adr2: Adr): BOOLEAN;
|
|
|
|
-VAR
|
|
|
|
- equal: BOOLEAN;
|
|
|
|
- i: LONGINT;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- IF adr1.usedProtocol # adr2.usedProtocol THEN
|
|
|
|
- RETURN FALSE;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- CASE adr1.usedProtocol OF
|
|
|
|
- IPv4:
|
|
|
|
- IF adr1.ipv4Adr = adr2.ipv4Adr THEN
|
|
|
|
- RETURN TRUE;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- |IPv6:
|
|
|
|
- equal := TRUE;
|
|
|
|
- i := 0;
|
|
|
|
- WHILE ((i < 16) & equal) DO
|
|
|
|
- IF adr1.ipv6Adr[i] # adr2.ipv6Adr[i] THEN
|
|
|
|
- equal := FALSE;
|
|
|
|
- END;
|
|
|
|
- INC(i);
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF adr1.data # adr2.data THEN
|
|
|
|
- equal := FALSE;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- RETURN equal;
|
|
|
|
-
|
|
|
|
- |NilAdrIdent:
|
|
|
|
- (* both addresses NIL therefore equal *)
|
|
|
|
- IF adr2.usedProtocol = NilAdrIdent THEN
|
|
|
|
- RETURN TRUE;
|
|
|
|
- ELSE
|
|
|
|
- RETURN FALSE;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- ELSE
|
|
|
|
- IF DEBUG THEN
|
|
|
|
- ASSERT(TRUE);
|
|
|
|
- END;
|
|
|
|
- RETURN FALSE;
|
|
|
|
- END;
|
|
|
|
- RETURN FALSE;
|
|
|
|
-END AdrsEqual;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Convert a dotted-decimal string to an ip address. Return NilAdr on failure. *)
|
|
|
|
-PROCEDURE StrToAdr*(ipString: ARRAY OF CHAR): Adr;
|
|
|
|
-VAR
|
|
|
|
- retAdr: Adr;
|
|
|
|
- i, j, x: LONGINT;
|
|
|
|
- adr: ARRAY 4 OF CHAR;
|
|
|
|
- ok: BOOLEAN;
|
|
|
|
- charCount: LONGINT; (* ipv6: number of character between two : *)
|
|
|
|
- ipv6AdrPart: ARRAY 6 OF CHAR; (* two bytes of an IPv6 address *)
|
|
|
|
- ipv6AdrRight: ARRAY 16 OF CHAR; (* right part of an IPv6 address; after :: *)
|
|
|
|
- hexToChar: ARRAY 3 OF CHAR;
|
|
|
|
- leftParts: LONGINT; (* number of bytes before :: *)
|
|
|
|
- rightParts: LONGINT; (* number of bytes after :: *)
|
|
|
|
- val, res: LONGINT;
|
|
|
|
- state: LONGINT; (* state of the FSM look at the eof for more info *)
|
|
|
|
- dPointOcc: BOOLEAN; (* double point occured *)
|
|
|
|
- prefixVal: LONGINT;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (* compute a subpart (two bytes) of a IPv6 address; subpart:=between two : *)
|
|
|
|
- PROCEDURE ComputeIPv6Part():BOOLEAN;
|
|
|
|
- BEGIN
|
|
|
|
- CASE charCount OF
|
|
|
|
- 0:
|
|
|
|
- RETURN TRUE;
|
|
|
|
-
|
|
|
|
- |1,2:
|
|
|
|
- IF dPointOcc THEN
|
|
|
|
- ipv6AdrRight[rightParts] := 0X;
|
|
|
|
- INC(rightParts);
|
|
|
|
- ELSE
|
|
|
|
- retAdr.ipv6Adr[leftParts] := 0X;
|
|
|
|
- INC(leftParts);
|
|
|
|
- END;
|
|
|
|
- Strings.HexStrToInt(ipv6AdrPart, val, res);
|
|
|
|
-
|
|
|
|
- IF res = Strings.Ok THEN
|
|
|
|
- IF dPointOcc THEN
|
|
|
|
- ipv6AdrRight[rightParts] := CHR(val);
|
|
|
|
- INC(rightParts);
|
|
|
|
- ELSE
|
|
|
|
- retAdr.ipv6Adr[leftParts] := CHR(val);
|
|
|
|
- INC(leftParts);
|
|
|
|
- END;
|
|
|
|
- ELSE
|
|
|
|
- RETURN FALSE;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- |3:
|
|
|
|
- hexToChar[0] := ipv6AdrPart[0];
|
|
|
|
- hexToChar[1] := 0X;
|
|
|
|
- Strings.HexStrToInt(hexToChar, val, res);
|
|
|
|
-
|
|
|
|
- IF res = Strings.Ok THEN
|
|
|
|
- IF dPointOcc THEN
|
|
|
|
- ipv6AdrRight[rightParts] := CHR(val);
|
|
|
|
- INC(rightParts);
|
|
|
|
- ELSE
|
|
|
|
- retAdr.ipv6Adr[leftParts] := CHR(val);
|
|
|
|
- INC(leftParts);
|
|
|
|
- END;
|
|
|
|
- ELSE
|
|
|
|
- RETURN FALSE;
|
|
|
|
- END;
|
|
|
|
- ipv6AdrPart[0] := "0";
|
|
|
|
- Strings.HexStrToInt(ipv6AdrPart, val, res);
|
|
|
|
-
|
|
|
|
- IF res = Strings.Ok THEN
|
|
|
|
- IF dPointOcc THEN
|
|
|
|
- ipv6AdrRight[rightParts] := CHR(val);
|
|
|
|
- INC(rightParts);
|
|
|
|
- ELSE
|
|
|
|
- retAdr.ipv6Adr[leftParts] := CHR(val);
|
|
|
|
- INC(leftParts);
|
|
|
|
- END;
|
|
|
|
- ELSE
|
|
|
|
- RETURN FALSE;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- |4:
|
|
|
|
- hexToChar[0] := ipv6AdrPart[0];
|
|
|
|
- hexToChar[1] := ipv6AdrPart[1];
|
|
|
|
- hexToChar[2] := 0X;
|
|
|
|
- Strings.HexStrToInt(hexToChar, val, res);
|
|
|
|
-
|
|
|
|
- IF res = Strings.Ok THEN
|
|
|
|
- IF dPointOcc THEN
|
|
|
|
- ipv6AdrRight[rightParts] := CHR(val);
|
|
|
|
- INC(rightParts);
|
|
|
|
- ELSE
|
|
|
|
- retAdr.ipv6Adr[leftParts] := CHR(val);
|
|
|
|
- INC(leftParts);
|
|
|
|
- END;
|
|
|
|
- ELSE
|
|
|
|
- RETURN FALSE;
|
|
|
|
- END;
|
|
|
|
- ipv6AdrPart[0] := "0";
|
|
|
|
- ipv6AdrPart[1] := "0";
|
|
|
|
- Strings.HexStrToInt(ipv6AdrPart, val, res);
|
|
|
|
-
|
|
|
|
- IF res = Strings.Ok THEN
|
|
|
|
- IF dPointOcc THEN
|
|
|
|
- ipv6AdrRight[rightParts] := CHR(val);
|
|
|
|
- INC(rightParts);
|
|
|
|
- ELSE
|
|
|
|
- retAdr.ipv6Adr[leftParts] := CHR(val);
|
|
|
|
- INC(leftParts);
|
|
|
|
- END;
|
|
|
|
- ELSE
|
|
|
|
- RETURN FALSE;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- ELSE
|
|
|
|
- IF DEBUG THEN
|
|
|
|
- ASSERT(TRUE);
|
|
|
|
- END;
|
|
|
|
- RETURN FALSE;
|
|
|
|
- END;
|
|
|
|
- charCount := 0;
|
|
|
|
- RETURN TRUE;
|
|
|
|
- END ComputeIPv6Part;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- retAdr := NilAdr;
|
|
|
|
-
|
|
|
|
- IF IsValidIPv4Str(ipString) THEN
|
|
|
|
- (* Return an ipv4 address *)
|
|
|
|
- i := 0;
|
|
|
|
- j := 0;
|
|
|
|
- x := -1;
|
|
|
|
- ok := FALSE;
|
|
|
|
-
|
|
|
|
- LOOP
|
|
|
|
- IF (ipString[i] = ".") OR (ipString[i] = 0X) THEN
|
|
|
|
- IF (x < 0) OR (x > 255) OR (j = 4) THEN EXIT END;
|
|
|
|
- adr[j] := CHR(x);
|
|
|
|
- IF ipString[i] = 0X THEN ok := (j = 3); EXIT END;
|
|
|
|
- x := -1; INC(i); INC(j)
|
|
|
|
- ELSIF (ipString[i] >= "0") & (ipString[i] <= "9") THEN
|
|
|
|
- IF x = -1 THEN x := 0 END;
|
|
|
|
- x := x*10 + (ORD(ipString[i])-ORD("0"));
|
|
|
|
- INC(i)
|
|
|
|
- ELSE
|
|
|
|
- EXIT
|
|
|
|
- END
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF ok THEN
|
|
|
|
- retAdr.ipv4Adr := SYSTEM.VAL (LONGINT, adr);
|
|
|
|
- retAdr.usedProtocol := IPv4;
|
|
|
|
- RETURN retAdr;
|
|
|
|
- ELSE
|
|
|
|
- RETURN NilAdr;
|
|
|
|
- END
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- (* IPv6 *)
|
|
|
|
- ELSIF IsValidIPv6Str(ipString) THEN
|
|
|
|
- i := 0;
|
|
|
|
- state := 1;
|
|
|
|
- charCount := 0;
|
|
|
|
- dPointOcc := FALSE;
|
|
|
|
- retAdr.usedProtocol := 6;
|
|
|
|
- retAdr.ipv4Adr := NilAdrIPv4;
|
|
|
|
- i := 0;
|
|
|
|
- j := 0;
|
|
|
|
- charCount := 0;
|
|
|
|
- leftParts := 0;
|
|
|
|
- rightParts := 0;
|
|
|
|
- prefixVal := 0;
|
|
|
|
-
|
|
|
|
- Strings.UpperCase(ipString);
|
|
|
|
-
|
|
|
|
- WHILE (i < (LEN(ipString) - 1)) & (ipString[i] # 0X) DO
|
|
|
|
-
|
|
|
|
- CASE state OF (* Using the same FSM as IsValidIPv6Str *)
|
|
|
|
- -1: (* Error state
|
|
|
|
- Should never happen, is checked by IsValidIPv6Str() *)
|
|
|
|
- RETURN NilAdr;
|
|
|
|
-
|
|
|
|
- |1: (* reading two blocks of two bytes of 0-9\A-F *)
|
|
|
|
- IF ipString[i] = ":" THEN
|
|
|
|
- ipv6AdrPart[charCount] := 0X;
|
|
|
|
- IF ~ComputeIPv6Part() THEN
|
|
|
|
- RETURN NilAdr;
|
|
|
|
- END;
|
|
|
|
- state := 2;
|
|
|
|
-
|
|
|
|
- ELSIF ipString[i] = "/" THEN
|
|
|
|
- ipv6AdrPart[charCount] := 0X;
|
|
|
|
-
|
|
|
|
- IF ~ComputeIPv6Part() THEN
|
|
|
|
- RETURN NilAdr;
|
|
|
|
- END;
|
|
|
|
- state := 3;
|
|
|
|
-
|
|
|
|
- ELSE
|
|
|
|
- (* 0-9, A-F *)
|
|
|
|
- ipv6AdrPart[charCount] := ipString[i];
|
|
|
|
- INC(charCount);
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- |2: (* a : occured *)
|
|
|
|
- IF ipString[i] = ":" THEN
|
|
|
|
- dPointOcc := TRUE;
|
|
|
|
- state := 4;
|
|
|
|
- ELSE
|
|
|
|
- (* 0-9, A-F *)
|
|
|
|
- state := 1;
|
|
|
|
- charCount := 0;
|
|
|
|
- ipv6AdrPart[charCount] := ipString[i];
|
|
|
|
- INC(charCount);
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- |3: (* prefix will follow *)
|
|
|
|
- prefixVal := (prefixVal * 10) + (ORD(ipString[i]) - ORD("0"));
|
|
|
|
-
|
|
|
|
- |4: (* A :: occured *)
|
|
|
|
- IF ipString[i] = "/" THEN
|
|
|
|
- state := 3;
|
|
|
|
- ELSE
|
|
|
|
- IF ~ComputeIPv6Part() THEN
|
|
|
|
- RETURN NilAdr;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- (* 0-9, A-F *)
|
|
|
|
- state := 1;
|
|
|
|
- charCount := 0;
|
|
|
|
- ipv6AdrPart[charCount] := ipString[i];
|
|
|
|
- INC(charCount);
|
|
|
|
- END;
|
|
|
|
- ELSE
|
|
|
|
- IF DEBUG THEN
|
|
|
|
- ASSERT(TRUE);
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
- INC(i);
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- ipv6AdrPart[charCount] := 0X;
|
|
|
|
- IF charCount # 0 THEN
|
|
|
|
- IF ~ComputeIPv6Part() THEN
|
|
|
|
- RETURN NilAdr;
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF dPointOcc THEN
|
|
|
|
- (* fill 0X for :: *)
|
|
|
|
- FOR i:= leftParts TO ((LEN(retAdr.ipv6Adr) -1) - rightParts) DO
|
|
|
|
- retAdr.ipv6Adr[i] := 0X;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- (* fill part behind :: *)
|
|
|
|
- FOR i := 0 TO (rightParts - 1) DO
|
|
|
|
- retAdr.ipv6Adr[(LEN(retAdr.ipv6Adr) - rightParts) + i] := ipv6AdrRight[i];
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF prefixVal > 64 THEN
|
|
|
|
- RETURN NilAdr;
|
|
|
|
- END;
|
|
|
|
- retAdr.data := prefixVal;
|
|
|
|
- RETURN retAdr;
|
|
|
|
- END;
|
|
|
|
- RETURN NilAdr;
|
|
|
|
-END StrToAdr;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Convert an IP address to a dotted-decimal string. *)
|
|
|
|
-PROCEDURE AdrToStr*(adr: Adr; VAR string: ARRAY OF CHAR);
|
|
|
|
-VAR
|
|
|
|
- i, j, x: LONGINT;
|
|
|
|
- a: ARRAY 4 OF CHAR;
|
|
|
|
- val: LONGINT;
|
|
|
|
- hexToStr: ARRAY 5 OF CHAR;
|
|
|
|
- prefixLenStr: ARRAY 64 OF CHAR;
|
|
|
|
- maxZeroRow: LONGINT;
|
|
|
|
- currentZeroRow: LONGINT;
|
|
|
|
- maxZeroStart: LONGINT;
|
|
|
|
- currentZeroStart: LONGINT;
|
|
|
|
- lastZero: BOOLEAN;
|
|
|
|
- lastDPoint: BOOLEAN;
|
|
|
|
- countEnded: BOOLEAN;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- CASE adr.usedProtocol OF
|
|
|
|
- IPv4:
|
|
|
|
- ASSERT(LEN(string) >= 16); (* enough space for largest result *)
|
|
|
|
- Network.Put4(a, 0, adr.ipv4Adr);
|
|
|
|
- i := 0;
|
|
|
|
- FOR j := 0 TO 3 DO
|
|
|
|
- x := ORD(a[j]);
|
|
|
|
- IF x >= 100 THEN string[i] := CHR(ORD("0")+x DIV 100); INC(i) END;
|
|
|
|
- IF x >= 10 THEN string[i] := CHR(ORD("0")+x DIV 10 MOD 10); INC(i) END;
|
|
|
|
- string[i] := CHR(ORD("0")+x MOD 10); INC(i);
|
|
|
|
- IF j = 3 THEN string[i] := 0X ELSE string[i] := "." END;
|
|
|
|
- INC(i)
|
|
|
|
- END
|
|
|
|
-
|
|
|
|
- |IPv6:
|
|
|
|
- FOR i := 0 TO (LEN(adr.ipv6Adr) -1) BY 2 DO
|
|
|
|
- (* simple version *)
|
|
|
|
- val := ORD(adr.ipv6Adr[i]) * 256;
|
|
|
|
- val := val + ORD(adr.ipv6Adr[i+1]);
|
|
|
|
- Strings.IntToHexStr (val, 3, hexToStr);
|
|
|
|
-
|
|
|
|
- (* Delete leading zeros *)
|
|
|
|
- WHILE (hexToStr[0] = "0") & (hexToStr[1] # 0X) DO
|
|
|
|
- Strings.Delete(hexToStr, 0, 1);
|
|
|
|
- END;
|
|
|
|
- Strings.Append (string, hexToStr);
|
|
|
|
-
|
|
|
|
- IF i # (LEN(adr.ipv6Adr) - 2) THEN
|
|
|
|
- Strings.Append (string, ":");
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- (* replace longest row of zeros with :: *)
|
|
|
|
- maxZeroRow := 0;
|
|
|
|
- currentZeroRow := 0;
|
|
|
|
- maxZeroStart := 0;
|
|
|
|
- currentZeroStart := 0;
|
|
|
|
- i := 0;
|
|
|
|
- lastZero := FALSE;
|
|
|
|
- lastDPoint := TRUE;
|
|
|
|
- countEnded :=TRUE;
|
|
|
|
-
|
|
|
|
- WHILE string[i] # 0X DO
|
|
|
|
- IF string[i] = "0" THEN
|
|
|
|
- IF lastDPoint THEN
|
|
|
|
- INC(currentZeroRow);
|
|
|
|
- lastZero := TRUE;
|
|
|
|
- lastDPoint := FALSE;
|
|
|
|
- IF countEnded THEN
|
|
|
|
- currentZeroStart := i;
|
|
|
|
- countEnded := FALSE;
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
- ELSIF string[i] = ":" THEN
|
|
|
|
- lastDPoint := TRUE;
|
|
|
|
- IF lastZero THEN
|
|
|
|
- lastZero := FALSE;
|
|
|
|
- END;
|
|
|
|
- ELSE
|
|
|
|
- IF lastDPoint THEN
|
|
|
|
- lastDPoint := FALSE;
|
|
|
|
- countEnded := TRUE;
|
|
|
|
- IF currentZeroRow > maxZeroRow THEN
|
|
|
|
- maxZeroRow := currentZeroRow;
|
|
|
|
- maxZeroStart := currentZeroStart;
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- INC(i);
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF ~countEnded THEN
|
|
|
|
- IF currentZeroRow > maxZeroRow THEN
|
|
|
|
- maxZeroRow := currentZeroRow;
|
|
|
|
- maxZeroStart := currentZeroStart;
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
- IF maxZeroRow # 0 THEN
|
|
|
|
- (* write a :: *)
|
|
|
|
- IF maxZeroStart = 0 THEN
|
|
|
|
- string[0] := ":";
|
|
|
|
- i := 1;
|
|
|
|
- WHILE ((string[i] # 0X) & ~((string[i] # "0") & (string[i] # ":"))) DO INC(i); END;
|
|
|
|
- IF string[i] = 0X THEN
|
|
|
|
- string := "::";
|
|
|
|
- ELSE
|
|
|
|
- Strings.Delete(string, 1, i-2);
|
|
|
|
- END;
|
|
|
|
- ELSE
|
|
|
|
- i := maxZeroStart;
|
|
|
|
- WHILE ((string[i] = "0") OR (string[i] = ":")) DO INC(i); END;
|
|
|
|
- IF string[i] = 0X THEN
|
|
|
|
- string[maxZeroStart] := ":";
|
|
|
|
- string[maxZeroStart+1] := 0X;
|
|
|
|
- ELSE
|
|
|
|
- Strings.Delete(string, maxZeroStart, i - maxZeroStart - 1);
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF adr.data # 0 THEN
|
|
|
|
- (* write prefix *)
|
|
|
|
- Strings.IntToStr(adr.data, prefixLenStr);
|
|
|
|
- Strings.Append (string, "/");
|
|
|
|
- Strings.Append (string, prefixLenStr);
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- ELSE
|
|
|
|
- IF IsNilAdr (adr) THEN
|
|
|
|
- string := "";
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-END AdrToStr;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Convert a IP address from an array [ofs..ofs+x] to an
|
|
|
|
- Adr-type variable.
|
|
|
|
- Example for IPv4:
|
|
|
|
- If the LSB (least significant byte) is stored the the beginning [ofs],
|
|
|
|
- LSBfirst must be set to TRUE.
|
|
|
|
- (address "a.b.c.d" is stored as [d,c,b,a])
|
|
|
|
- If the LSB is stored at the end [ofs+3], LSBfirst must be set to FALSE.
|
|
|
|
- (address "a.b.c.d" is stored as [a,b,c,d])
|
|
|
|
-*)
|
|
|
|
-PROCEDURE ArrayToAdr*(CONST array: ARRAY OF CHAR; ofs, protocol: LONGINT; LSBfirst: BOOLEAN): Adr;
|
|
|
|
-VAR
|
|
|
|
- adr: Adr;
|
|
|
|
- i, swapTemp: LONGINT;
|
|
|
|
-BEGIN
|
|
|
|
- ASSERT((protocol = 4) OR (protocol = 6));
|
|
|
|
-
|
|
|
|
- IF protocol = IPv4 THEN (* index check *)
|
|
|
|
- IF ~(ofs + 4 <= LEN(array)) THEN
|
|
|
|
- RETURN NilAdr;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- SYSTEM.MOVE(ADDRESSOF(array[ofs]), ADDRESSOF(adr.ipv4Adr), 4);
|
|
|
|
- IF LSBfirst THEN
|
|
|
|
- SwapEndian(adr.ipv4Adr);
|
|
|
|
- END;
|
|
|
|
- adr.usedProtocol := IPv4;
|
|
|
|
-
|
|
|
|
- ELSIF protocol = IPv6 THEN
|
|
|
|
- IF ~(ofs + 16 <= LEN(array)) THEN
|
|
|
|
- RETURN NilAdr;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- SYSTEM.MOVE(ADDRESSOF(array[ofs]), ADDRESSOF(adr.ipv6Adr), 16);
|
|
|
|
- IF LSBfirst THEN
|
|
|
|
- FOR i := 0 TO 3 DO
|
|
|
|
- SYSTEM.MOVE(ADDRESSOF(adr.ipv6Adr[i*4]), ADDRESSOF(swapTemp), 4);
|
|
|
|
- SwapEndian(swapTemp);
|
|
|
|
- SYSTEM.MOVE(ADDRESSOF(swapTemp), ADDRESSOF(adr.ipv6Adr[i*4]), 4);
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
- adr.usedProtocol := IPv6;
|
|
|
|
-
|
|
|
|
- ELSE
|
|
|
|
- IF DEBUG THEN
|
|
|
|
- ASSERT(TRUE);
|
|
|
|
- END;
|
|
|
|
- RETURN NilAdr;
|
|
|
|
- END;
|
|
|
|
- RETURN adr;
|
|
|
|
-END ArrayToAdr;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Convert an Adr-type variable into an array [ofs..ofs+x]
|
|
|
|
- Example in IPv4:
|
|
|
|
- If the LSB (least significant byte) should be stored the the
|
|
|
|
- beginning [ofs], LSBfirst must be set to TRUE.
|
|
|
|
- (address "a.b.c.d" is stored as [d,c,b,a])
|
|
|
|
- If the LSB should be stored at the end [ofs+3], LSBfirst must be set to FALSE.
|
|
|
|
- (address "a.b.c.d" is stored as [a,b,c,d])
|
|
|
|
-*)
|
|
|
|
-PROCEDURE AdrToArray*(adr: Adr; VAR array: ARRAY OF CHAR; ofs: LONGINT; LSBfirst: BOOLEAN);
|
|
|
|
-VAR
|
|
|
|
- tempAdr: Adr;
|
|
|
|
- i, swapTemp: LONGINT;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- tempAdr := adr;
|
|
|
|
-
|
|
|
|
- CASE adr.usedProtocol OF
|
|
|
|
- IPv4:
|
|
|
|
- IF ~(ofs+4 <= LEN(array)) THEN
|
|
|
|
- tempAdr := NilAdr;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF LSBfirst THEN
|
|
|
|
- SwapEndian(tempAdr.ipv4Adr);
|
|
|
|
- END;
|
|
|
|
- SYSTEM.MOVE(ADDRESSOF(tempAdr.ipv4Adr), ADDRESSOF(array[ofs]), 4);
|
|
|
|
-
|
|
|
|
- | IPv6:
|
|
|
|
- IF ~(ofs + 16 <= LEN(array)) THEN
|
|
|
|
- tempAdr := NilAdr;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF LSBfirst THEN
|
|
|
|
- FOR i := 0 TO 3 DO
|
|
|
|
- SYSTEM.MOVE(ADDRESSOF(tempAdr.ipv6Adr[i*4]), ADDRESSOF(swapTemp), 4);
|
|
|
|
- SwapEndian(swapTemp);
|
|
|
|
- SYSTEM.MOVE(ADDRESSOF(swapTemp), ADDRESSOF(tempAdr.ipv6Adr[i*4]), 4);
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
- SYSTEM.MOVE(ADDRESSOF(adr.ipv6Adr), ADDRESSOF(array[ofs]), 16);
|
|
|
|
- ELSE
|
|
|
|
- IF DEBUG THEN
|
|
|
|
- ASSERT(TRUE);
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-END AdrToArray;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Reads the IP source address from a buffer *)
|
|
|
|
-PROCEDURE SrcAdrFromBuffer* (buffer: Network.Buffer): Adr;
|
|
|
|
-VAR
|
|
|
|
- i: LONGINT;
|
|
|
|
- adr: Adr;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- CASE ORD(buffer.data[buffer.l3ofs]) DIV 16 OF
|
|
|
|
- IPv4:
|
|
|
|
- adr.usedProtocol := IPv4;
|
|
|
|
- adr.ipv4Adr := SYSTEM.VAL(LONGINT, buffer.data[buffer.l3ofs+12]);
|
|
|
|
- SetIPv6AdrNil(adr);
|
|
|
|
- RETURN adr;
|
|
|
|
-
|
|
|
|
- |IPv6:
|
|
|
|
- adr.usedProtocol := IPv6;
|
|
|
|
- FOR i := 0 TO 15 DO
|
|
|
|
- adr.ipv6Adr[i] := buffer.data[buffer.l3ofs+8 + i];
|
|
|
|
- END;
|
|
|
|
- adr.ipv4Adr := NilAdrIPv4;
|
|
|
|
-
|
|
|
|
- ELSE
|
|
|
|
- IF DEBUG THEN
|
|
|
|
- ASSERT(TRUE);
|
|
|
|
- END;
|
|
|
|
- RETURN NilAdr;
|
|
|
|
- END;
|
|
|
|
- RETURN NilAdr;
|
|
|
|
-END SrcAdrFromBuffer;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Reads the IP destination address from a buffer *)
|
|
|
|
-PROCEDURE DestAdrFromBuffer* (buffer: Network.Buffer): Adr;
|
|
|
|
-VAR
|
|
|
|
- adr: Adr;
|
|
|
|
- i: LONGINT;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- CASE ORD(buffer.data[buffer.l3ofs]) DIV 16 OF
|
|
|
|
- IPv4:
|
|
|
|
- adr.usedProtocol := IPv4;
|
|
|
|
- adr.ipv4Adr := SYSTEM.VAL(LONGINT, buffer.data[buffer.l3ofs+16]);
|
|
|
|
- SetIPv6AdrNil(adr);
|
|
|
|
- RETURN adr;
|
|
|
|
-
|
|
|
|
- |IPv6:
|
|
|
|
- adr.usedProtocol := IPv6;
|
|
|
|
- FOR i := 0 TO 15 DO
|
|
|
|
- adr.ipv6Adr[i] := buffer.data[buffer.l3ofs+24 + i];
|
|
|
|
- END;
|
|
|
|
- adr.ipv4Adr := NilAdrIPv4;
|
|
|
|
-
|
|
|
|
- ELSE
|
|
|
|
- IF DEBUG THEN
|
|
|
|
- ASSERT(TRUE);
|
|
|
|
- END;
|
|
|
|
- RETURN NilAdr;
|
|
|
|
- END;
|
|
|
|
- RETURN NilAdr;
|
|
|
|
-END DestAdrFromBuffer;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(* Swap internal representation of an IP address from big to little endian or vice versa. *)
|
|
|
|
-PROCEDURE -SwapEndian(VAR adr: LONGINT);
|
|
|
|
-CODE {SYSTEM.AMD64}
|
|
|
|
- POP RAX
|
|
|
|
- MOV ECX, [RAX]
|
|
|
|
- BSWAP ECX
|
|
|
|
- MOV [RAX], ECX
|
|
|
|
-END SwapEndian;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Write an IP address. *)
|
|
|
|
-PROCEDURE OutAdr*(adr: Adr);
|
|
|
|
-VAR
|
|
|
|
- s: ARRAY 64 OF CHAR;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- AdrToStr(adr, s); KernelLog.String(s);
|
|
|
|
-END OutAdr;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Enumerate all installed interfaces *)
|
|
|
|
-PROCEDURE Enumerate*(handler: InterfaceHandler);
|
|
|
|
-VAR item: Interface;
|
|
|
|
-BEGIN
|
|
|
|
- item := interfaces;
|
|
|
|
- WHILE item # NIL DO
|
|
|
|
- handler(item);
|
|
|
|
- item := item.next;
|
|
|
|
- END;
|
|
|
|
-END Enumerate;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Output the configuration of the specified interface. Can be used as Handler in Enumerate(). *)
|
|
|
|
-PROCEDURE OutInterface*(interface: Interface);
|
|
|
|
-BEGIN
|
|
|
|
- interface.OutInterface;
|
|
|
|
-END OutInterface;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Aos command: Output statistics and configuration of all installed interfaces. *)
|
|
|
|
-PROCEDURE IPConfig*(context : Commands.Context);
|
|
|
|
-BEGIN
|
|
|
|
- context.out.String("Interfaces:"); context.out.Ln;
|
|
|
|
- context.out.String("----------------------"); context.out.Ln;
|
|
|
|
- Enumerate(OutInterface);
|
|
|
|
- context.out.Ln;
|
|
|
|
- context.out.String("IP statistics:"); context.out.Ln;
|
|
|
|
- context.out.String("----------------------"); context.out.Ln;
|
|
|
|
- context.out.String("NIPSentToSubnet"); context.out.Int(NIPSentToSubnet,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPSentToGateway"); context.out.Int(NIPSentToGateway,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPSentBroadcast"); context.out.Int(NIPSentBroadcast,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPCantFragment"); context.out.Int(NIPCantFragment,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPRcvTotal"); context.out.Int(NIPRcvTotal,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPTooSmall"); context.out.Int(NIPTooSmall,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPBadVersion"); context.out.Int(NIPBadVersion,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPOptions"); context.out.Int(NIPOptions,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPBadChecksum"); context.out.Int(NIPBadChecksum,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPBadLength"); context.out.Int(NIPBadLength,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPTrim"); context.out.Int(NIPTrim, 10);context.out.Ln;
|
|
|
|
- context.out.String("NIPBadHdrLen"); context.out.Int(NIPBadHdrLen,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPNotForUs"); context.out.Int(NIPNotForUs,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPCantReassemble"); context.out.Int(NIPCantReassemble,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPSrcIsBroadcast"); context.out.Int(NIPSrcIsBroadcast,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPDelivered"); context.out.Int(NIPDelivered,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPNoReceiver"); context.out.Int(NIPNoReceiver,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPForwarded"); context.out.Int(NIPForwarded,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPSentLocalLoopback"); context.out.Int(NIPSentLocalLoopback,10);context.out.Ln;
|
|
|
|
- context.out.String("NIPSentPointToPoint"); context.out.Int(NIPSentPointToPoint,10);context.out.Ln; context.out.Ln;
|
|
|
|
-END IPConfig;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** First part of a split checksum operation. len must be non-zero and even. chk1 must be 0 at the
|
|
|
|
- beginning. The result can be passed to a following call to Checksum1(). The last chk1 result must
|
|
|
|
- be passed to Checksum2, which sums the data following sequentially on the data summed by this
|
|
|
|
- operation. Carries from bit 15 are accumulated in the top 16 bits, so at most 65535 words can be
|
|
|
|
- summed by Checksum1 and Checksum2 together. *)
|
|
|
|
-PROCEDURE Checksum1*(CONST data: ARRAY OF CHAR; ofs, len, chk1: LONGINT): LONGINT;
|
|
|
|
-CODE {SYSTEM.AMD64}
|
|
|
|
- MOV EAX, [RBP + chk1]
|
|
|
|
- MOV RBX, [RBP + data]
|
|
|
|
- ADD EBX, [RBP + ofs]
|
|
|
|
- MOV ECX, [RBP + len]
|
|
|
|
- SHR ECX, 1
|
|
|
|
- JNC sloop
|
|
|
|
- PUSH 8 ; ASSERT(~ODD(len))
|
|
|
|
- INT 3
|
|
|
|
-sloop:
|
|
|
|
- MOVZX EDX, WORD [RBX]
|
|
|
|
- ADD EAX, EDX
|
|
|
|
- ADD RBX, 2
|
|
|
|
- DEC ECX
|
|
|
|
- JNZ sloop
|
|
|
|
-END Checksum1;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Continue a checksum operation. len can be zero or odd. chk1 can be the result of Checksum1 for
|
|
|
|
- the immediately preceding data, or 0 for contiguous data. *)
|
|
|
|
-PROCEDURE Checksum2*(CONST data: ARRAY OF CHAR; ofs, len, chk1: LONGINT): INTEGER;
|
|
|
|
- CODE {SYSTEM.AMD64}
|
|
|
|
- MOV EAX, [RBP + chk1]
|
|
|
|
- MOV RBX, [RBP + data]
|
|
|
|
- ADD EBX, [RBP + ofs]
|
|
|
|
- MOV ECX, [RBP + len]
|
|
|
|
- SHR ECX, 1
|
|
|
|
- JZ eloop
|
|
|
|
-sloop:
|
|
|
|
- MOVZX EDX, WORD [RBX]
|
|
|
|
- ADD EAX, EDX
|
|
|
|
- ADD RBX, 2
|
|
|
|
- DEC ECX
|
|
|
|
- JNZ sloop
|
|
|
|
-eloop:
|
|
|
|
- TEST [RBP + len], 1 ; check for odd length
|
|
|
|
- JZ even
|
|
|
|
- MOVZX EDX, BYTE [RBX] ; add last byte
|
|
|
|
- ADD EAX, EDX
|
|
|
|
-even:
|
|
|
|
- MOV ECX, EAX ; now add in all the carries
|
|
|
|
- SHR ECX, 16
|
|
|
|
- AND EAX, 0FFFFH
|
|
|
|
- ADD EAX, ECX
|
|
|
|
- MOV ECX, EAX ; add in additional carry
|
|
|
|
- SHR ECX, 16
|
|
|
|
- ADD EAX, ECX ; result is in low 16 bits of EAX
|
|
|
|
- NOT EAX
|
|
|
|
-END Checksum2;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(* Return TRUE if "adr1" and "adr2" are in the same subnet defined by "mask". Only for IPv4 *)
|
|
|
|
-PROCEDURE SameSubnetv4(adr1, adr2, mask: LONGINT): BOOLEAN;
|
|
|
|
-CODE {SYSTEM.AMD64}
|
|
|
|
- MOV EAX, [RBP + adr1]
|
|
|
|
- MOV EBX, [RBP + adr2]
|
|
|
|
- MOV ECX, [RBP + mask]
|
|
|
|
- AND EAX, ECX
|
|
|
|
- AND EBX, ECX
|
|
|
|
- CMP EAX, EBX
|
|
|
|
- SETZ AL
|
|
|
|
-END SameSubnetv4;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(* Return TRUE if adr matches the prefix *)
|
|
|
|
-PROCEDURE MatchPrefix*(adr: Adr; prefix: Adr): BOOLEAN;
|
|
|
|
-VAR
|
|
|
|
- bytesToCheck: LONGINT;
|
|
|
|
- bitsToCheck: LONGINT;
|
|
|
|
- i: LONGINT;
|
|
|
|
- matches: BOOLEAN;
|
|
|
|
- diffSet: SET;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- IF DEBUG THEN
|
|
|
|
- ASSERT ((IsNilAdr(adr)) OR (adr.usedProtocol = IPv6));
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- matches := TRUE;
|
|
|
|
-
|
|
|
|
- bytesToCheck := prefix.data DIV 8;
|
|
|
|
- bitsToCheck := prefix.data MOD 8;
|
|
|
|
-
|
|
|
|
- FOR i := 0 TO bytesToCheck - 1 DO
|
|
|
|
- IF adr.ipv6Adr[i] # prefix.ipv6Adr[i] THEN
|
|
|
|
- matches := FALSE;
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF bitsToCheck # 0 THEN
|
|
|
|
- diffSet := {};
|
|
|
|
- FOR i := 0 TO 8 - bitsToCheck - 1 DO
|
|
|
|
- diffSet := diffSet + {i};
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- FOR i := 0 TO bitsToCheck - 1 DO
|
|
|
|
- IF (SYSTEM.VAL(SET, adr.ipv6Adr[bytesToCheck]) - diffSet) # (SYSTEM.VAL(SET, prefix.ipv6Adr[bytesToCheck]) - diffSet) THEN
|
|
|
|
- matches := FALSE;
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
- RETURN matches;
|
|
|
|
-END MatchPrefix;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Return the interface on which packets with "dst" address should be sent. Return NIL if no interface matches. *)
|
|
|
|
-PROCEDURE InterfaceByDstIP*(dest: Adr): Interface;
|
|
|
|
-VAR
|
|
|
|
- item, gw: Interface;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- CASE dest.usedProtocol OF
|
|
|
|
- IPv4:
|
|
|
|
- gw := NIL;
|
|
|
|
- item := interfaces;
|
|
|
|
- LOOP
|
|
|
|
- IF item = NIL THEN EXIT END;
|
|
|
|
- IF (item.protocol = IPv4) & (~IsNilAdr(item.localAdr)) & (item.dev.Linked() # Network.LinkNotLinked) THEN
|
|
|
|
- IF SameSubnetv4(dest.ipv4Adr, item.subnetAdr.ipv4Adr, item.maskAdr.ipv4Adr) THEN
|
|
|
|
- EXIT;
|
|
|
|
- ELSIF (gw = NIL) & (~IsNilAdr(item.subnetAdr)) THEN
|
|
|
|
- IF item.protocol # IPv4 THEN
|
|
|
|
- gw := item;
|
|
|
|
- ELSIF ~IsNilAdr(item.gatewayAdr) THEN
|
|
|
|
- gw := item;
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
- item := item.next;
|
|
|
|
- END;
|
|
|
|
- IF item # NIL THEN
|
|
|
|
- RETURN item;
|
|
|
|
- ELSE
|
|
|
|
- RETURN gw;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- |IPv6:
|
|
|
|
- (* Requires special handling when multiple devices are present *)
|
|
|
|
- RETURN v6InterfaceByDstIP(dest);
|
|
|
|
-
|
|
|
|
- ELSE
|
|
|
|
- IF DEBUG THEN
|
|
|
|
- ASSERT(TRUE);
|
|
|
|
- END;
|
|
|
|
- RETURN NIL;
|
|
|
|
- END;
|
|
|
|
-END InterfaceByDstIP;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Return the reference to an installed interface by its name. NIL is returned if no interface with this name
|
|
|
|
- was found. *)
|
|
|
|
-PROCEDURE InterfaceByName*(CONST name: ARRAY OF CHAR): Interface;
|
|
|
|
-VAR item: Interface;
|
|
|
|
-BEGIN
|
|
|
|
- item := interfaces;
|
|
|
|
- WHILE (item # NIL) & (item.name # name) DO
|
|
|
|
- item := item.next;
|
|
|
|
- END;
|
|
|
|
- RETURN item;
|
|
|
|
-END InterfaceByName;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Delivers first preferred (if possible) interface of an device.
|
|
|
|
- Return the reference to an installed interface by its device. NIL is returned if no interface with this
|
|
|
|
- device was found. *)
|
|
|
|
-PROCEDURE InterfaceByDevice*(dev: Network.LinkDevice): Interface;
|
|
|
|
-VAR
|
|
|
|
- item: Interface;
|
|
|
|
- unprefInt: Interface;
|
|
|
|
-BEGIN
|
|
|
|
- unprefInt := NIL;
|
|
|
|
- item := interfaces;
|
|
|
|
- WHILE (item # NIL) DO
|
|
|
|
- IF item.dev = dev THEN
|
|
|
|
- IF item.protocol # preferredProtocol THEN
|
|
|
|
- unprefInt := item;
|
|
|
|
- ELSE
|
|
|
|
- RETURN item;
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
- item := item.next;
|
|
|
|
- END;
|
|
|
|
- (* return interface with unpreferred protocol or NIL *)
|
|
|
|
- RETURN unprefInt;
|
|
|
|
-END InterfaceByDevice;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Return a list of installed interfaces of a certain device. *)
|
|
|
|
-PROCEDURE InterfaceListByDevice* (dev: Network.LinkDevice):InterfaceList;
|
|
|
|
-VAR
|
|
|
|
- item: Interface;
|
|
|
|
- interfaceList: InterfaceList;
|
|
|
|
- interfaceListItem: InterfaceList;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- item := interfaces;
|
|
|
|
- interfaceList := NIL;
|
|
|
|
-
|
|
|
|
- (* search for interfaces with matching device and put them in a list *)
|
|
|
|
- WHILE item # NIL DO
|
|
|
|
- IF item.dev = dev THEN
|
|
|
|
- NEW(interfaceListItem);
|
|
|
|
- interfaceListItem.interface := item;
|
|
|
|
- interfaceListItem.next := interfaceList;
|
|
|
|
- interfaceList := interfaceListItem;
|
|
|
|
- END;
|
|
|
|
- item := item.next;
|
|
|
|
- END;
|
|
|
|
- RETURN interfaceList;
|
|
|
|
-END InterfaceListByDevice;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Install a receiver for a type. The type is stored in
|
|
|
|
- IPv4: Protocol field
|
|
|
|
- IPv6: Next header field *)
|
|
|
|
-PROCEDURE InstallReceiver*( type: LONGINT; r: Receiver);
|
|
|
|
-BEGIN {EXCLUSIVE}
|
|
|
|
- IF DEBUG THEN
|
|
|
|
- ASSERT(r # NIL);
|
|
|
|
- ASSERT((type >=0) & (type <= 255));
|
|
|
|
- ASSERT(receivers[type] = NIL);
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- receivers[type] := r;
|
|
|
|
-END InstallReceiver;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Remove the currently installed receiver for a type. The type is stored in
|
|
|
|
- IPv4: Protocol field
|
|
|
|
- IPv6: Next header field *)
|
|
|
|
-PROCEDURE RemoveReceiver*(type: LONGINT);
|
|
|
|
-BEGIN {EXCLUSIVE}
|
|
|
|
- ASSERT((type >=0) & (type <= 255));
|
|
|
|
- ASSERT(receivers[type] # NIL);
|
|
|
|
-
|
|
|
|
- receivers[type] := NIL;
|
|
|
|
-END RemoveReceiver;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Checks if a string is a valid IPv4 address *)
|
|
|
|
-PROCEDURE IsValidIPv4Str (CONST ipString: ARRAY OF CHAR): BOOLEAN;
|
|
|
|
-VAR
|
|
|
|
- i,j: LONGINT;
|
|
|
|
- ipNr: LONGINT;
|
|
|
|
- digits: ARRAY 4 OF CHAR;
|
|
|
|
- startClass: LONGINT;
|
|
|
|
-BEGIN
|
|
|
|
- i := 0;
|
|
|
|
-
|
|
|
|
- (* Class A *)
|
|
|
|
- WHILE (i < Strings.Length(ipString)) & (ipString[i] #'.') & (i < 3) DO
|
|
|
|
- digits[i] := ipString[i];
|
|
|
|
- INC (i);
|
|
|
|
- END;
|
|
|
|
- digits[i] := 0X;
|
|
|
|
-
|
|
|
|
- IF ipString[i] # '.' THEN RETURN FALSE END;
|
|
|
|
-
|
|
|
|
- (* Check if in digits are only numbers *)
|
|
|
|
- j := 0;
|
|
|
|
- WHILE digits[j] # 0X DO
|
|
|
|
- IF (ORD(digits[j]) - ORD("0")) > 9 THEN RETURN FALSE END;
|
|
|
|
- INC (j);
|
|
|
|
- END;
|
|
|
|
- Strings.StrToInt (digits, ipNr);
|
|
|
|
- IF ipNr > 255 THEN RETURN FALSE END;
|
|
|
|
-
|
|
|
|
- (* Class B *)
|
|
|
|
- INC(i);
|
|
|
|
- startClass := i;
|
|
|
|
- WHILE (i < Strings.Length(ipString)) & (ipString[i] # '.') & (i - startClass <= 3) DO
|
|
|
|
- digits[i-startClass] := ipString[i];
|
|
|
|
- INC (i);
|
|
|
|
- END;
|
|
|
|
- digits[i-startClass] := 0X;
|
|
|
|
-
|
|
|
|
- IF ipString[i] # '.' THEN RETURN FALSE END;
|
|
|
|
-
|
|
|
|
- (* Check if in digits are only number *)
|
|
|
|
- j := 0;
|
|
|
|
- WHILE digits[j] # 0X DO
|
|
|
|
- IF (ORD(digits[j]) - ORD("0")) > 9 THEN RETURN FALSE END;
|
|
|
|
- INC (j);
|
|
|
|
- END;
|
|
|
|
- Strings.StrToInt (digits, ipNr);
|
|
|
|
- IF ipNr > 255 THEN RETURN FALSE END;
|
|
|
|
-
|
|
|
|
- (* Class C *)
|
|
|
|
- INC(i);
|
|
|
|
- startClass := i;
|
|
|
|
- WHILE (i < Strings.Length (ipString)) & (ipString[i] # '.') & (i - startClass <= 3) DO
|
|
|
|
- digits[i-startClass] := ipString[i];
|
|
|
|
- INC (i);
|
|
|
|
- END;
|
|
|
|
- digits[i-startClass] := 0X;
|
|
|
|
-
|
|
|
|
- IF ipString[i] # '.' THEN RETURN FALSE END;
|
|
|
|
-
|
|
|
|
- (* Check if in digits are only number *)
|
|
|
|
- j := 0;
|
|
|
|
- WHILE digits[j] # 0X DO
|
|
|
|
- IF (ORD(digits[j]) - ORD("0")) > 9 THEN RETURN FALSE END;
|
|
|
|
- INC (j);
|
|
|
|
- END;
|
|
|
|
- Strings.StrToInt (digits, ipNr);
|
|
|
|
- IF ipNr > 255 THEN RETURN FALSE END;
|
|
|
|
-
|
|
|
|
- (* Class D *)
|
|
|
|
- INC(i);
|
|
|
|
- startClass := i;
|
|
|
|
- WHILE (i < Strings.Length (ipString)) & (i - startClass <= 3) DO
|
|
|
|
- digits[i-startClass] := ipString[i];
|
|
|
|
- INC (i);
|
|
|
|
- END;
|
|
|
|
- digits[i-startClass] := 0X;
|
|
|
|
-
|
|
|
|
- (* Check if in digits are only number *)
|
|
|
|
- j := 0;
|
|
|
|
- WHILE digits[j] # 0X DO
|
|
|
|
- IF (ORD(digits[j]) - ORD("0")) > 9 THEN RETURN FALSE END;
|
|
|
|
- INC (j);
|
|
|
|
- END;
|
|
|
|
- Strings.StrToInt (digits, ipNr);
|
|
|
|
- IF ipNr > 255 THEN RETURN FALSE END;
|
|
|
|
-
|
|
|
|
- RETURN TRUE;
|
|
|
|
-END IsValidIPv4Str;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Checks if a string is a valid IPv6 address *)
|
|
|
|
-PROCEDURE IsValidIPv6Str (ipString: ARRAY OF CHAR): BOOLEAN;
|
|
|
|
-VAR
|
|
|
|
- i: LONGINT;
|
|
|
|
- state: LONGINT; (* -1: error *)
|
|
|
|
- charCount: LONGINT;
|
|
|
|
- ascD: LONGINT;
|
|
|
|
- ascH: LONGINT;
|
|
|
|
- dPointOcc: BOOLEAN;
|
|
|
|
- prefixLenArr: ARRAY 3 OF LONGINT;
|
|
|
|
- prefixLen: LONGINT;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- i := 0;
|
|
|
|
- state := 1;
|
|
|
|
- dPointOcc := FALSE;
|
|
|
|
-
|
|
|
|
- Strings.UpperCase(ipString);
|
|
|
|
-
|
|
|
|
- WHILE (i < (LEN(ipString) - 1)) & (ipString[i] # 0X) DO
|
|
|
|
-
|
|
|
|
- CASE state OF
|
|
|
|
- -1:
|
|
|
|
- RETURN FALSE;
|
|
|
|
-
|
|
|
|
- |1:
|
|
|
|
- (* 0-9 & A-F *)
|
|
|
|
- ascD := ORD(ipString[i]) - ORD("0");
|
|
|
|
- ascH := ORD(ipString[i]) - ORD("A");
|
|
|
|
-
|
|
|
|
- IF ((ascD >= 0) & (ascD <= 9)) OR ((ascH >= 0) & (ascH <= 5)) THEN
|
|
|
|
- INC(charCount);
|
|
|
|
-
|
|
|
|
- (* more than 4 digits between two : *)
|
|
|
|
- IF charCount > 4 THEN
|
|
|
|
- state := -1;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- (* : *)
|
|
|
|
- ELSIF ipString[i] = ":" THEN
|
|
|
|
- charCount := 0;
|
|
|
|
- state := 2;
|
|
|
|
- ELSIF ipString[i] = "/" THEN
|
|
|
|
- charCount := 0;
|
|
|
|
- state := 3;
|
|
|
|
- ELSE
|
|
|
|
- state := -1;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- |2:
|
|
|
|
- ascD := ORD(ipString[i]) - ORD("0");
|
|
|
|
- ascH := ORD(ipString[i]) - ORD("A");
|
|
|
|
-
|
|
|
|
- IF ipString[i] = ":" THEN
|
|
|
|
- IF dPointOcc THEN
|
|
|
|
- state := -1;
|
|
|
|
- ELSE
|
|
|
|
- dPointOcc := TRUE;
|
|
|
|
- state := 4;
|
|
|
|
- END
|
|
|
|
-
|
|
|
|
- ELSIF ((ascD >= 0) & (ascD <= 9)) OR ((ascH >= 0) & (ascH <= 5)) THEN
|
|
|
|
- INC(charCount);
|
|
|
|
- state := 1;
|
|
|
|
- ELSE
|
|
|
|
- state := -1;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- |3:
|
|
|
|
- ascD := ORD(ipString[i]) - ORD("0");
|
|
|
|
-
|
|
|
|
- IF ~((ascD >= 0) & (ascD <= 9)) THEN
|
|
|
|
- state := -1;
|
|
|
|
- ELSE
|
|
|
|
- IF charCount > 3 THEN
|
|
|
|
- state := -1;
|
|
|
|
- ELSE
|
|
|
|
- prefixLenArr[charCount] := ascD;
|
|
|
|
- INC(charCount);
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- |4:
|
|
|
|
- ascD := ORD(ipString[i]) - ORD("0");
|
|
|
|
- ascH := ORD(ipString[i]) - ORD("A");
|
|
|
|
-
|
|
|
|
- IF ipString[i] = "/" THEN
|
|
|
|
- state := 3;
|
|
|
|
- ELSIF ((ascD >= 0) & (ascD <= 9)) OR ((ascH >= 0) & (ascH <= 5)) THEN
|
|
|
|
- INC(charCount);
|
|
|
|
- state := 1;
|
|
|
|
- ELSE
|
|
|
|
- state := -1;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- ELSE
|
|
|
|
- IF DEBUG THEN
|
|
|
|
- ASSERT(TRUE);
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
- INC(i);
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- CASE state OF
|
|
|
|
- 1:
|
|
|
|
- RETURN TRUE;
|
|
|
|
-
|
|
|
|
- |3:
|
|
|
|
- IF charCount > 0 THEN
|
|
|
|
- prefixLen := 0;
|
|
|
|
- FOR i:= 0 TO charCount - 1 DO
|
|
|
|
- prefixLen := prefixLen * 10;
|
|
|
|
- INC(prefixLen, prefixLenArr[i]);
|
|
|
|
- END;
|
|
|
|
- IF prefixLen <= 64 THEN
|
|
|
|
- RETURN TRUE;
|
|
|
|
- ELSE
|
|
|
|
- RETURN FALSE;
|
|
|
|
- END;
|
|
|
|
- ELSE
|
|
|
|
- RETURN FALSE;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- |4:
|
|
|
|
- RETURN TRUE;
|
|
|
|
-
|
|
|
|
- ELSE
|
|
|
|
- IF DEBUG THEN
|
|
|
|
- ASSERT(TRUE);
|
|
|
|
- END;
|
|
|
|
- RETURN FALSE;
|
|
|
|
- END;
|
|
|
|
- RETURN FALSE;
|
|
|
|
-END IsValidIPv6Str;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(** Set IPv6 address to zero *)
|
|
|
|
-PROCEDURE SetIPv6AdrNil (adr: Adr);
|
|
|
|
-VAR
|
|
|
|
- i: LONGINT;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- FOR i := 0 TO 15 DO
|
|
|
|
- adr.ipv6Adr[i] := 0X;
|
|
|
|
- END;
|
|
|
|
-END SetIPv6AdrNil;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(* Add the interface to the IP configuration. *)
|
|
|
|
-PROCEDURE AddInterface*(int: Interface; VAR res: WORD);
|
|
|
|
-VAR
|
|
|
|
- item: Interface;
|
|
|
|
-BEGIN {EXCLUSIVE}
|
|
|
|
- item := interfaces;
|
|
|
|
- WHILE item # NIL DO
|
|
|
|
- (* Check if interface name already exists *)
|
|
|
|
- IF item.name = int.name THEN
|
|
|
|
- res := DuplicateInterfaceName;
|
|
|
|
- RETURN;
|
|
|
|
- END;
|
|
|
|
- item := item.next;
|
|
|
|
- END;
|
|
|
|
- (* Add interface *)
|
|
|
|
- int.next := interfaces;
|
|
|
|
- interfaces := int;
|
|
|
|
- res := Ok;
|
|
|
|
-END AddInterface;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(* Remove the interface from the IP configuration. *)
|
|
|
|
-PROCEDURE RemoveInterface*(int: Interface);
|
|
|
|
-VAR
|
|
|
|
- item: Interface;
|
|
|
|
-
|
|
|
|
-BEGIN {EXCLUSIVE}
|
|
|
|
- item := interfaces;
|
|
|
|
- IF item = NIL THEN
|
|
|
|
- (* empty list *)
|
|
|
|
- ELSIF item = int THEN
|
|
|
|
- (* remove first item *)
|
|
|
|
- interfaces := interfaces.next;
|
|
|
|
- ELSE
|
|
|
|
- WHILE item.next # int DO
|
|
|
|
- item := item.next;
|
|
|
|
- END;
|
|
|
|
- IF item.next # NIL THEN
|
|
|
|
- item.next := item.next.next;
|
|
|
|
- ELSE
|
|
|
|
- (* not found *)
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-END RemoveInterface;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-(* Prints out a packet *)
|
|
|
|
-PROCEDURE PacketOut*(CONST title, buffer: ARRAY OF CHAR; all: BOOLEAN);
|
|
|
|
-VAR
|
|
|
|
- i: LONGINT;
|
|
|
|
- length: LONGINT;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- KernelLog.Ln;KernelLog.String("********************");KernelLog.Ln;
|
|
|
|
- KernelLog.String(title); KernelLog.Ln;
|
|
|
|
-
|
|
|
|
- IF all THEN
|
|
|
|
- length := LEN(buffer) -1;
|
|
|
|
- ELSE
|
|
|
|
- length := Strings.Min(LEN(buffer) - 1, 256);
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- FOR i := 0 TO length DO
|
|
|
|
- IF (i MOD 4) = 0 THEN
|
|
|
|
- KernelLog.Ln;
|
|
|
|
- KernelLog.Int(i, 2);KernelLog.String(": ");
|
|
|
|
- END;
|
|
|
|
- KernelLog.Hex(ORD(buffer[i]), -1);
|
|
|
|
- KernelLog.String(" ");
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- KernelLog.Ln;KernelLog.String("********************");KernelLog.Ln;
|
|
|
|
-END PacketOut;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- (* IPFowarding default value is FALSE *)
|
|
|
|
- IPForwarding := FALSE;
|
|
|
|
-
|
|
|
|
- (* EchoReply default value is TRUE *)
|
|
|
|
- EchoReply := TRUE;
|
|
|
|
-
|
|
|
|
- (* Initializations *)
|
|
|
|
- (* NilAdr *)
|
|
|
|
- NilAdr.ipv4Adr := NilAdrIPv4;
|
|
|
|
- SetIPv6AdrNil (NilAdr);
|
|
|
|
- NilAdr.usedProtocol := NilAdrIdent;
|
|
|
|
-
|
|
|
|
- (* Initialize receiver list *)
|
|
|
|
- FOR counter:=0 TO NbrOfReceivers-1 DO
|
|
|
|
- receivers[counter] := NIL;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- (* Initialize inteface list *)
|
|
|
|
- interfaces := NIL;
|
|
|
|
-END IP.
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-Free:
|
|
|
|
-System.Free TraceRoute VNC Ping WMFTPClient FTPClient WebFTPServer TCPServices TLS InitNetwork Ping DHCP TCP DNS UDP ICMP IPv4 IPv6 IP~
|
|
|
|
-
|
|
|
|
-Start:
|
|
|
|
-InitNetwork.Init
|
|
|
|
-
|
|
|
|
-Compile:
|
|
|
|
-PC.Compile \s IP.Mod IPv4.Mod IPv6.Mod ICMP.Mod UDP.Mod DNS.Mod TCP.Mod DHCP.Mod InitNetwork.Mod WebFTPServer.Mod FTPClient.Mod WMFTPClient.Mod Ping.Mod VNC.Mod TraceRoute.Mod~
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-History:
|
|
|
|
-02.05.2005 eb Supports IPv6 and fragmented IPv6 packets.
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-IsValidIPv6Str:
|
|
|
|
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
|
|
|
|
-
|
|
|
|
-FSM used in IsValidIPv6Str:
|
|
|
|
------------------------
|
|
|
|
-EOS: end of string
|
|
|
|
- State 1: Initial state
|
|
|
|
- 0-9/A-F goto state 1
|
|
|
|
- : goto state 2
|
|
|
|
- / goto state 3
|
|
|
|
- EOS valid
|
|
|
|
- State 2: 0-9/A-F goto state 1
|
|
|
|
- : goto state 4
|
|
|
|
- EOS invalid
|
|
|
|
- State 3: 0-9 goto state 3
|
|
|
|
- EOS valid
|
|
|
|
- State 4: / goto state 3
|
|
|
|
- 0-9/A-F goto state 1
|
|
|
|
- EOS valid
|
|
|
|
-
|
|
|
|
-
|
|
|