IP.Mod 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758
  1. (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
  2. MODULE IP; (** AUTHOR "pjm, mvt, eb"; PURPOSE "IP (v4 and v6)"; *)
  3. IMPORT SYSTEM, KernelLog, Commands, Strings, Network;
  4. CONST
  5. (* DEBUG *)
  6. DEBUG = TRUE;
  7. (** Error codes *)
  8. Ok* = 0;
  9. DeviceAlreadyUsed* = 3901;
  10. DuplicateInterfaceName* = 3902;
  11. NoInterfaceName* = 3903;
  12. GatewayNotInSubnet* = 3904;
  13. IPv6AdrUsedOnIPv4Interface* = 4001;
  14. IPv4AdrUsedOnIPv6Interface* = 4002;
  15. DublicatedAddresses* = 4003;
  16. MixedIpProtocols* = 4003;
  17. LocalAdrSetIntv6* = 4004; (* local address must be NIL when calling SetAdrs on a IPv6 interface *)
  18. PrefixNotSet* = 4005; (* prefix on ipv6 interface must be set with local address *)
  19. MaxNofDNS* = 10; (** maximum number of DNS servers per interface *)
  20. MaxTTL* = 255; (** maximum time-to-live on outgoing datagrams *)
  21. NbrOfReceivers = 255; (* Number of possible receivers, i.e. possible layer 3 protocols *)
  22. (** IP address constants *)
  23. NilAdrIPv4 = 0;
  24. (* Comparators for Adr.usedProtocols *)
  25. IPv4* = 4;
  26. IPv6* = 6;
  27. NilAdrIdent = -1; (* usedProtocol of NilAdrs *)
  28. (* ICMP *)
  29. ICMPHdrLen* = 4;
  30. ICMPSrcLLAdrOptionType* = 1;
  31. ICMPTargetLLAdrOptionType* = 2;
  32. ICMPPrefixInfoOptionType* = 3;
  33. ICMPRedirectHdrOptionType* = 4;
  34. ICMPMTUOptionType* = 5;
  35. ICMPAdvIntOptionType* = 7;
  36. ICMPHomeAgOptionType* = 8;
  37. ICMPRouteOption* = 9;
  38. TYPE
  39. Adr* = RECORD
  40. ipv4Adr*: LONGINT;
  41. ipv6Adr*: ARRAY 16 OF CHAR;
  42. usedProtocol*: LONGINT;
  43. data*: LONGINT;
  44. END; (** An IP Address. usedProtocol = 0: No protocol yet used
  45. usedProtocol = IPv4: IPv4 address stored in field ipv4Adr
  46. usedProtocol = IPv6: IPv6 address stored in field ipv6Adr
  47. data can be used to store additional informations. I.e. in IPv6 the
  48. prefix length is stored in the data field *)
  49. TYPE
  50. Packet* = POINTER TO ARRAY OF CHAR;
  51. Name* = ARRAY 128 OF CHAR; (** Name type for interface name *)
  52. Interface* = OBJECT
  53. VAR
  54. (** IP addresses of this interface. *)
  55. localAdr*, maskAdr*, gatewayAdr*, subnetAdr*, broadAdr*: Adr;
  56. (** name of the interface *)
  57. name*: Name;
  58. (** Device that the interface belongs to *)
  59. dev*: Network.LinkDevice;
  60. (** DNS server list - can be used by DNS, not used in IP itself *)
  61. DNS-: ARRAY MaxNofDNS OF Adr; (* DNS server list *)
  62. DNScount*: LONGINT; (* number of DNS servers in list *)
  63. (* interface *)
  64. next*: Interface; (* next pointer for interface list *)
  65. closed*: BOOLEAN; (* is interface already closed? *)
  66. protocol*: LONGINT; (* Interface for IPv4 or IPv6?. Only used by IP otherwise use dynamic type checking! *)
  67. (** Set addresses. Is normally called just after instanciation, but can also be called later, e.g. by DHCP.
  68. If "gatewayAdr" is "NilAdr", the subnet is considered to have no gateway, else it must be in the same
  69. subnet as the "localAdr".
  70. "domain" can be an empty string. It is normally used by a DNS implementation. It is not used in IP directly.
  71. In IPv6 maskAdr is the prefix of the currently IP address *)
  72. PROCEDURE SetAdrs*(localAdr, maskOrPrefixAdr, gatewayAdr: Adr; VAR res: WORD);
  73. BEGIN
  74. (* Extensions have to override this method.*)
  75. HALT(99);
  76. END SetAdrs;
  77. (** Remove all domain name servers from the interface. *)
  78. PROCEDURE DNSRemoveAll*;
  79. BEGIN {EXCLUSIVE}
  80. DNScount := 0;
  81. END DNSRemoveAll;
  82. (** Add a domain name server to the interface. *)
  83. PROCEDURE DNSAdd*(adr: Adr);
  84. VAR
  85. i: LONGINT;
  86. BEGIN {EXCLUSIVE}
  87. (* concurrent lookup is consistent *)
  88. ASSERT(DNScount < MaxNofDNS);
  89. i := 0;
  90. WHILE i < DNScount DO
  91. IF AdrsEqual (DNS[i],adr) THEN RETURN END;
  92. INC(i)
  93. END;
  94. DNS[DNScount] := adr;
  95. INC(DNScount);
  96. END DNSAdd;
  97. (** Remove a domain name server from the interface. *)
  98. PROCEDURE DNSRemove*(adr: Adr);
  99. VAR i: LONGINT;
  100. BEGIN {EXCLUSIVE}
  101. (* concurrent lookup could result in a duplicate address in worst-case *)
  102. (* this happends hardly ever and is harmless for DNS anyway *)
  103. i := 0;
  104. WHILE (i < DNScount) & (~ AdrsEqual(DNS[i],adr)) DO
  105. INC(i)
  106. END;
  107. IF i < DNScount THEN
  108. INC(i);
  109. WHILE i < DNScount DO
  110. DNS[i-1] := DNS[i];
  111. INC(i);
  112. END;
  113. DEC(DNScount);
  114. END;
  115. END DNSRemove;
  116. (** Send an IP packet on this interface. *)
  117. PROCEDURE Send*(type: LONGINT; destAdr: Adr; CONST l4hdr, data: ARRAY OF CHAR; h4len, dofs, dlen, TTL: LONGINT);
  118. BEGIN
  119. (* Extensions have to override this method.*)
  120. HALT(99);
  121. END Send;
  122. (* Internal procedure to perform the rest of the send operation. Used by "Send" and for IP forwarding. *)
  123. PROCEDURE DoSend*(destAdr: Adr; CONST l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT) ;
  124. BEGIN
  125. (* Extensions have to override this method.*)
  126. HALT(99);
  127. END DoSend;
  128. (** Enumerate all ARP table entries. *)
  129. PROCEDURE ARPEnumerate*(handle: ARPHandler);
  130. BEGIN
  131. (* Extensions have to override this method.*)
  132. HALT(99);
  133. END ARPEnumerate;
  134. (** Close and deactivate the interface, i.e. remove it from the configuration. *)
  135. PROCEDURE Close*;
  136. BEGIN
  137. (* Extensions have to override this method.*)
  138. HALT(99);
  139. END Close;
  140. (** Check if adr is a broadcast address *)
  141. PROCEDURE IsBroadcast*(adr: Adr) : BOOLEAN;
  142. BEGIN
  143. (* Extensions have to override this method.*)
  144. HALT(99);
  145. END IsBroadcast;
  146. (** Check if adr is a multicast address *)
  147. PROCEDURE IsMulticast*(adr: Adr) : BOOLEAN;
  148. BEGIN
  149. (* Extensions have to override this method.*)
  150. HALT(99);
  151. END IsMulticast;
  152. (** Receive an IP packet *)
  153. PROCEDURE IPInput*(dev: Network.LinkDevice; type: LONGINT; buffer: Network.Buffer);
  154. BEGIN
  155. (* Extensions have to override this method.*)
  156. HALT(99);
  157. END IPInput;
  158. (** Reads the source address of a IP packet buffer *)
  159. PROCEDURE ReadSrcAdr* (buffer: Network.Buffer): Adr;
  160. BEGIN
  161. (* Extensions have to override this method.*)
  162. HALT(99);
  163. END ReadSrcAdr;
  164. (** Reads the destination address of a IP packet buffer *)
  165. PROCEDURE ReadDestAdr* (buffer: Network.Buffer): Adr;
  166. BEGIN
  167. (* Extensions have to override this method.*)
  168. HALT(99);
  169. END ReadDestAdr;
  170. (** Creates a pseudo-header for checksum calculation (TCP/UDP) and returns the length of this header *)
  171. PROCEDURE WritePseudoHeader*(VAR pseudoHdr: ARRAY OF CHAR; src, dst: Adr; protocol, pktLengthUpperLayer: LONGINT): LONGINT;
  172. BEGIN
  173. (* Extensions have to override this method.*)
  174. HALT(99);
  175. END WritePseudoHeader;
  176. (** Writes the configuration of this interface *)
  177. PROCEDURE OutInterface*;
  178. BEGIN
  179. (* Extensions have to override this method.*)
  180. HALT(99);
  181. END OutInterface;
  182. END Interface;
  183. TYPE
  184. (* List of interfaces *)
  185. InterfaceList* = POINTER TO RECORD
  186. interface*: Interface;
  187. next*: InterfaceList;
  188. END;
  189. Receiver* = PROCEDURE {DELEGATE} (int: Interface; type: LONGINT; fip, lip: Adr; buffer: Network.Buffer);
  190. V6InterfaceByDstIP* = PROCEDURE {DELEGATE} (dstAdr: Adr): Interface;
  191. (** Handler for ARPPool.Enumerate. *)
  192. ARPHandler* = PROCEDURE {DELEGATE} (ip: Adr; complete: BOOLEAN; link: Network.LinkAdr; size, sendTime, updateTime, updateDate, hash: LONGINT);
  193. InterfaceHandler* = PROCEDURE {DELEGATE} (int: Interface);
  194. VAR
  195. (* receiver *)
  196. receivers*: ARRAY 256 OF Receiver; (* registered receivers - array position is IPv4 protocol field or IPv6 next header field *)
  197. (* Interface by dst for IPv6 *)
  198. v6InterfaceByDstIP*: V6InterfaceByDstIP;
  199. (* IP *)
  200. NilAdr*: Adr; (* To check if an IP address is NIL use IsNilAdr instead *)
  201. preferredProtocol*: LONGINT; (* Preferred IP protocol *)
  202. (* IP counters *)
  203. NIPSentToSubnet*, NIPSentToGateway*, NIPSentBroadcast*, NIPCantFragment*,
  204. NIPRcvTotal*, NIPTooSmall*, NIPBadVersion*, NIPOptions*, NIPBadChecksum*,
  205. NIPBadLength*, NIPTrim*, NIPBadHdrLen*, NIPNotForUs*, NIPCantReassemble*, NIPSrcIsBroadcast*,
  206. NIPDelivered*, NIPNoReceiver*, NIPForwarded*, NIPSentLocalLoopback*, NIPSentPointToPoint*: LONGINT;
  207. (* turn on/off IP forwarding, echo replay *)
  208. IPForwarding*: BOOLEAN;
  209. EchoReply*: BOOLEAN;
  210. (* Interface *)
  211. interfaces*: Interface; (* list of all installed interfaces *)
  212. counter: LONGINT; (* Use it only in the module body! *)
  213. (** Is address not yet specified *)
  214. PROCEDURE IsNilAdr* (adr: Adr): BOOLEAN;
  215. VAR
  216. isNil: BOOLEAN;
  217. i: LONGINT;
  218. BEGIN
  219. CASE adr.usedProtocol OF
  220. IPv4:
  221. RETURN (adr.ipv4Adr = NilAdrIPv4)
  222. |IPv6:
  223. isNil := TRUE;
  224. i := 0;
  225. WHILE ((i<16) & isNil) DO
  226. IF adr.ipv6Adr[i] # 0X THEN
  227. isNil := FALSE;
  228. END;
  229. INC(i);
  230. END;
  231. RETURN isNil;
  232. |NilAdrIdent:
  233. RETURN TRUE;
  234. ELSE
  235. IF DEBUG THEN
  236. ASSERT(TRUE);
  237. END;
  238. RETURN TRUE;
  239. END;
  240. END IsNilAdr;
  241. (* Checks if two addresses are equal *)
  242. PROCEDURE AdrsEqual* (adr1, adr2: Adr): BOOLEAN;
  243. VAR
  244. equal: BOOLEAN;
  245. i: LONGINT;
  246. BEGIN
  247. IF adr1.usedProtocol # adr2.usedProtocol THEN
  248. RETURN FALSE;
  249. END;
  250. CASE adr1.usedProtocol OF
  251. IPv4:
  252. IF adr1.ipv4Adr = adr2.ipv4Adr THEN
  253. RETURN TRUE;
  254. END;
  255. |IPv6:
  256. equal := TRUE;
  257. i := 0;
  258. WHILE ((i < 16) & equal) DO
  259. IF adr1.ipv6Adr[i] # adr2.ipv6Adr[i] THEN
  260. equal := FALSE;
  261. END;
  262. INC(i);
  263. END;
  264. IF adr1.data # adr2.data THEN
  265. equal := FALSE;
  266. END;
  267. RETURN equal;
  268. |NilAdrIdent:
  269. (* both addresses NIL therefore equal *)
  270. IF adr2.usedProtocol = NilAdrIdent THEN
  271. RETURN TRUE;
  272. ELSE
  273. RETURN FALSE;
  274. END;
  275. ELSE
  276. IF DEBUG THEN
  277. ASSERT(TRUE);
  278. END;
  279. RETURN FALSE;
  280. END;
  281. RETURN FALSE;
  282. END AdrsEqual;
  283. (** Convert a dotted-decimal string to an ip address. Return NilAdr on failure. *)
  284. PROCEDURE StrToAdr*(ipString: ARRAY OF CHAR): Adr;
  285. VAR
  286. retAdr: Adr;
  287. i, j, x: LONGINT;
  288. adr: ARRAY 4 OF CHAR;
  289. ok: BOOLEAN;
  290. charCount: LONGINT; (* ipv6: number of character between two : *)
  291. ipv6AdrPart: ARRAY 6 OF CHAR; (* two bytes of an IPv6 address *)
  292. ipv6AdrRight: ARRAY 16 OF CHAR; (* right part of an IPv6 address; after :: *)
  293. hexToChar: ARRAY 3 OF CHAR;
  294. leftParts: LONGINT; (* number of bytes before :: *)
  295. rightParts: LONGINT; (* number of bytes after :: *)
  296. val: LONGINT;
  297. res: WORD;
  298. state: LONGINT; (* state of the FSM look at the eof for more info *)
  299. dPointOcc: BOOLEAN; (* double point occured *)
  300. prefixVal: LONGINT;
  301. (* compute a subpart (two bytes) of a IPv6 address; subpart:=between two : *)
  302. PROCEDURE ComputeIPv6Part():BOOLEAN;
  303. BEGIN
  304. CASE charCount OF
  305. 0:
  306. RETURN TRUE;
  307. |1,2:
  308. IF dPointOcc THEN
  309. ipv6AdrRight[rightParts] := 0X;
  310. INC(rightParts);
  311. ELSE
  312. retAdr.ipv6Adr[leftParts] := 0X;
  313. INC(leftParts);
  314. END;
  315. Strings.HexStrToInt(ipv6AdrPart, val, res);
  316. IF res = Strings.Ok THEN
  317. IF dPointOcc THEN
  318. ipv6AdrRight[rightParts] := CHR(val);
  319. INC(rightParts);
  320. ELSE
  321. retAdr.ipv6Adr[leftParts] := CHR(val);
  322. INC(leftParts);
  323. END;
  324. ELSE
  325. RETURN FALSE;
  326. END;
  327. |3:
  328. hexToChar[0] := ipv6AdrPart[0];
  329. hexToChar[1] := 0X;
  330. Strings.HexStrToInt(hexToChar, val, res);
  331. IF res = Strings.Ok THEN
  332. IF dPointOcc THEN
  333. ipv6AdrRight[rightParts] := CHR(val);
  334. INC(rightParts);
  335. ELSE
  336. retAdr.ipv6Adr[leftParts] := CHR(val);
  337. INC(leftParts);
  338. END;
  339. ELSE
  340. RETURN FALSE;
  341. END;
  342. ipv6AdrPart[0] := "0";
  343. Strings.HexStrToInt(ipv6AdrPart, val, res);
  344. IF res = Strings.Ok THEN
  345. IF dPointOcc THEN
  346. ipv6AdrRight[rightParts] := CHR(val);
  347. INC(rightParts);
  348. ELSE
  349. retAdr.ipv6Adr[leftParts] := CHR(val);
  350. INC(leftParts);
  351. END;
  352. ELSE
  353. RETURN FALSE;
  354. END;
  355. |4:
  356. hexToChar[0] := ipv6AdrPart[0];
  357. hexToChar[1] := ipv6AdrPart[1];
  358. hexToChar[2] := 0X;
  359. Strings.HexStrToInt(hexToChar, val, res);
  360. IF res = Strings.Ok THEN
  361. IF dPointOcc THEN
  362. ipv6AdrRight[rightParts] := CHR(val);
  363. INC(rightParts);
  364. ELSE
  365. retAdr.ipv6Adr[leftParts] := CHR(val);
  366. INC(leftParts);
  367. END;
  368. ELSE
  369. RETURN FALSE;
  370. END;
  371. ipv6AdrPart[0] := "0";
  372. ipv6AdrPart[1] := "0";
  373. Strings.HexStrToInt(ipv6AdrPart, val, res);
  374. IF res = Strings.Ok THEN
  375. IF dPointOcc THEN
  376. ipv6AdrRight[rightParts] := CHR(val);
  377. INC(rightParts);
  378. ELSE
  379. retAdr.ipv6Adr[leftParts] := CHR(val);
  380. INC(leftParts);
  381. END;
  382. ELSE
  383. RETURN FALSE;
  384. END;
  385. ELSE
  386. IF DEBUG THEN
  387. ASSERT(TRUE);
  388. END;
  389. RETURN FALSE;
  390. END;
  391. charCount := 0;
  392. RETURN TRUE;
  393. END ComputeIPv6Part;
  394. BEGIN
  395. retAdr := NilAdr;
  396. IF IsValidIPv4Str(ipString) THEN
  397. (* Return an ipv4 address *)
  398. i := 0;
  399. j := 0;
  400. x := -1;
  401. ok := FALSE;
  402. LOOP
  403. IF (ipString[i] = ".") OR (ipString[i] = 0X) THEN
  404. IF (x < 0) OR (x > 255) OR (j = 4) THEN EXIT END;
  405. adr[j] := CHR(x);
  406. IF ipString[i] = 0X THEN ok := (j = 3); EXIT END;
  407. x := -1; INC(i); INC(j)
  408. ELSIF (ipString[i] >= "0") & (ipString[i] <= "9") THEN
  409. IF x = -1 THEN x := 0 END;
  410. x := x*10 + (ORD(ipString[i])-ORD("0"));
  411. INC(i)
  412. ELSE
  413. EXIT
  414. END
  415. END;
  416. IF ok THEN
  417. retAdr.ipv4Adr := SYSTEM.VAL (LONGINT, adr);
  418. retAdr.usedProtocol := IPv4;
  419. RETURN retAdr;
  420. ELSE
  421. RETURN NilAdr;
  422. END
  423. (* IPv6 *)
  424. ELSIF IsValidIPv6Str(ipString) THEN
  425. i := 0;
  426. state := 1;
  427. charCount := 0;
  428. dPointOcc := FALSE;
  429. retAdr.usedProtocol := 6;
  430. retAdr.ipv4Adr := NilAdrIPv4;
  431. i := 0;
  432. j := 0;
  433. charCount := 0;
  434. leftParts := 0;
  435. rightParts := 0;
  436. prefixVal := 0;
  437. Strings.UpperCase(ipString);
  438. WHILE (i < (LEN(ipString) - 1)) & (ipString[i] # 0X) DO
  439. CASE state OF (* Using the same FSM as IsValidIPv6Str *)
  440. -1: (* Error state
  441. Should never happen, is checked by IsValidIPv6Str() *)
  442. RETURN NilAdr;
  443. |1: (* reading two blocks of two bytes of 0-9\A-F *)
  444. IF ipString[i] = ":" THEN
  445. ipv6AdrPart[charCount] := 0X;
  446. IF ~ComputeIPv6Part() THEN
  447. RETURN NilAdr;
  448. END;
  449. state := 2;
  450. ELSIF ipString[i] = "/" THEN
  451. ipv6AdrPart[charCount] := 0X;
  452. IF ~ComputeIPv6Part() THEN
  453. RETURN NilAdr;
  454. END;
  455. state := 3;
  456. ELSE
  457. (* 0-9, A-F *)
  458. ipv6AdrPart[charCount] := ipString[i];
  459. INC(charCount);
  460. END;
  461. |2: (* a : occured *)
  462. IF ipString[i] = ":" THEN
  463. dPointOcc := TRUE;
  464. state := 4;
  465. ELSE
  466. (* 0-9, A-F *)
  467. state := 1;
  468. charCount := 0;
  469. ipv6AdrPart[charCount] := ipString[i];
  470. INC(charCount);
  471. END;
  472. |3: (* prefix will follow *)
  473. prefixVal := (prefixVal * 10) + (ORD(ipString[i]) - ORD("0"));
  474. |4: (* A :: occured *)
  475. IF ipString[i] = "/" THEN
  476. state := 3;
  477. ELSE
  478. IF ~ComputeIPv6Part() THEN
  479. RETURN NilAdr;
  480. END;
  481. (* 0-9, A-F *)
  482. state := 1;
  483. charCount := 0;
  484. ipv6AdrPart[charCount] := ipString[i];
  485. INC(charCount);
  486. END;
  487. ELSE
  488. IF DEBUG THEN
  489. ASSERT(TRUE);
  490. END;
  491. END;
  492. INC(i);
  493. END;
  494. ipv6AdrPart[charCount] := 0X;
  495. IF charCount # 0 THEN
  496. IF ~ComputeIPv6Part() THEN
  497. RETURN NilAdr;
  498. END;
  499. END;
  500. IF dPointOcc THEN
  501. (* fill 0X for :: *)
  502. FOR i:= leftParts TO ((LEN(retAdr.ipv6Adr) -1) - rightParts) DO
  503. retAdr.ipv6Adr[i] := 0X;
  504. END;
  505. (* fill part behind :: *)
  506. FOR i := 0 TO (rightParts - 1) DO
  507. retAdr.ipv6Adr[(LEN(retAdr.ipv6Adr) - rightParts) + i] := ipv6AdrRight[i];
  508. END;
  509. END;
  510. IF prefixVal > 64 THEN
  511. RETURN NilAdr;
  512. END;
  513. retAdr.data := prefixVal;
  514. RETURN retAdr;
  515. END;
  516. RETURN NilAdr;
  517. END StrToAdr;
  518. (** Convert an IP address to a dotted-decimal string. *)
  519. PROCEDURE AdrToStr*(adr: Adr; VAR string: ARRAY OF CHAR);
  520. VAR
  521. i, j, x: LONGINT;
  522. a: ARRAY 4 OF CHAR;
  523. val: LONGINT;
  524. hexToStr: ARRAY 5 OF CHAR;
  525. prefixLenStr: ARRAY 64 OF CHAR;
  526. maxZeroRow: LONGINT;
  527. currentZeroRow: LONGINT;
  528. maxZeroStart: LONGINT;
  529. currentZeroStart: LONGINT;
  530. lastZero: BOOLEAN;
  531. lastDPoint: BOOLEAN;
  532. countEnded: BOOLEAN;
  533. BEGIN
  534. CASE adr.usedProtocol OF
  535. IPv4:
  536. ASSERT(LEN(string) >= 16); (* enough space for largest result *)
  537. Network.Put4(a, 0, adr.ipv4Adr);
  538. i := 0;
  539. FOR j := 0 TO 3 DO
  540. x := ORD(a[j]);
  541. IF x >= 100 THEN string[i] := CHR(ORD("0")+x DIV 100); INC(i) END;
  542. IF x >= 10 THEN string[i] := CHR(ORD("0")+x DIV 10 MOD 10); INC(i) END;
  543. string[i] := CHR(ORD("0")+x MOD 10); INC(i);
  544. IF j = 3 THEN string[i] := 0X ELSE string[i] := "." END;
  545. INC(i)
  546. END
  547. |IPv6:
  548. FOR i := 0 TO (LEN(adr.ipv6Adr) -1) BY 2 DO
  549. (* simple version *)
  550. val := ORD(adr.ipv6Adr[i]) * 256;
  551. val := val + ORD(adr.ipv6Adr[i+1]);
  552. Strings.IntToHexStr (val, 3, hexToStr);
  553. (* Delete leading zeros *)
  554. WHILE (hexToStr[0] = "0") & (hexToStr[1] # 0X) DO
  555. Strings.Delete(hexToStr, 0, 1);
  556. END;
  557. Strings.Append (string, hexToStr);
  558. IF i # (LEN(adr.ipv6Adr) - 2) THEN
  559. Strings.Append (string, ":");
  560. END;
  561. END;
  562. (* replace longest row of zeros with :: *)
  563. maxZeroRow := 0;
  564. currentZeroRow := 0;
  565. maxZeroStart := 0;
  566. currentZeroStart := 0;
  567. i := 0;
  568. lastZero := FALSE;
  569. lastDPoint := TRUE;
  570. countEnded :=TRUE;
  571. WHILE string[i] # 0X DO
  572. IF string[i] = "0" THEN
  573. IF lastDPoint THEN
  574. INC(currentZeroRow);
  575. lastZero := TRUE;
  576. lastDPoint := FALSE;
  577. IF countEnded THEN
  578. currentZeroStart := i;
  579. countEnded := FALSE;
  580. END;
  581. END;
  582. ELSIF string[i] = ":" THEN
  583. lastDPoint := TRUE;
  584. IF lastZero THEN
  585. lastZero := FALSE;
  586. END;
  587. ELSE
  588. IF lastDPoint THEN
  589. lastDPoint := FALSE;
  590. countEnded := TRUE;
  591. IF currentZeroRow > maxZeroRow THEN
  592. maxZeroRow := currentZeroRow;
  593. maxZeroStart := currentZeroStart;
  594. END;
  595. END;
  596. END;
  597. INC(i);
  598. END;
  599. IF ~countEnded THEN
  600. IF currentZeroRow > maxZeroRow THEN
  601. maxZeroRow := currentZeroRow;
  602. maxZeroStart := currentZeroStart;
  603. END;
  604. END;
  605. IF maxZeroRow # 0 THEN
  606. (* write a :: *)
  607. IF maxZeroStart = 0 THEN
  608. string[0] := ":";
  609. i := 1;
  610. WHILE ((string[i] # 0X) & ~((string[i] # "0") & (string[i] # ":"))) DO INC(i); END;
  611. IF string[i] = 0X THEN
  612. string := "::";
  613. ELSE
  614. Strings.Delete(string, 1, i-2);
  615. END;
  616. ELSE
  617. i := maxZeroStart;
  618. WHILE ((string[i] = "0") OR (string[i] = ":")) DO INC(i); END;
  619. IF string[i] = 0X THEN
  620. string[maxZeroStart] := ":";
  621. string[maxZeroStart+1] := 0X;
  622. ELSE
  623. Strings.Delete(string, maxZeroStart, i - maxZeroStart - 1);
  624. END;
  625. END;
  626. END;
  627. IF adr.data # 0 THEN
  628. (* write prefix *)
  629. Strings.IntToStr(adr.data, prefixLenStr);
  630. Strings.Append (string, "/");
  631. Strings.Append (string, prefixLenStr);
  632. END;
  633. ELSE
  634. IF IsNilAdr (adr) THEN
  635. string := "";
  636. END;
  637. END;
  638. END AdrToStr;
  639. (** Convert a IP address from an array [ofs..ofs+x] to an
  640. Adr-type variable.
  641. Example for IPv4:
  642. If the LSB (least significant byte) is stored the the beginning [ofs],
  643. LSBfirst must be set to TRUE.
  644. (address "a.b.c.d" is stored as [d,c,b,a])
  645. If the LSB is stored at the end [ofs+3], LSBfirst must be set to FALSE.
  646. (address "a.b.c.d" is stored as [a,b,c,d])
  647. *)
  648. PROCEDURE ArrayToAdr*(CONST array: ARRAY OF CHAR; ofs, protocol: LONGINT; LSBfirst: BOOLEAN): Adr;
  649. VAR
  650. adr: Adr;
  651. i, swapTemp: LONGINT;
  652. BEGIN
  653. ASSERT((protocol = 4) OR (protocol = 6));
  654. IF protocol = IPv4 THEN (* index check *)
  655. IF ~(ofs + 4 <= LEN(array)) THEN
  656. RETURN NilAdr;
  657. END;
  658. SYSTEM.MOVE(ADDRESSOF(array[ofs]), ADDRESSOF(adr.ipv4Adr), 4);
  659. IF LSBfirst THEN
  660. SwapEndian(adr.ipv4Adr);
  661. END;
  662. adr.usedProtocol := IPv4;
  663. ELSIF protocol = IPv6 THEN
  664. IF ~(ofs + 16 <= LEN(array)) THEN
  665. RETURN NilAdr;
  666. END;
  667. SYSTEM.MOVE(ADDRESSOF(array[ofs]), ADDRESSOF(adr.ipv6Adr), 16);
  668. IF LSBfirst THEN
  669. FOR i := 0 TO 3 DO
  670. SYSTEM.MOVE(ADDRESSOF(adr.ipv6Adr[i*4]), ADDRESSOF(swapTemp), 4);
  671. SwapEndian(swapTemp);
  672. SYSTEM.MOVE(ADDRESSOF(swapTemp), ADDRESSOF(adr.ipv6Adr[i*4]), 4);
  673. END;
  674. END;
  675. adr.usedProtocol := IPv6;
  676. ELSE
  677. IF DEBUG THEN
  678. ASSERT(TRUE);
  679. END;
  680. RETURN NilAdr;
  681. END;
  682. RETURN adr;
  683. END ArrayToAdr;
  684. (** Convert an Adr-type variable into an array [ofs..ofs+x]
  685. Example in IPv4:
  686. If the LSB (least significant byte) should be stored the the
  687. beginning [ofs], LSBfirst must be set to TRUE.
  688. (address "a.b.c.d" is stored as [d,c,b,a])
  689. If the LSB should be stored at the end [ofs+3], LSBfirst must be set to FALSE.
  690. (address "a.b.c.d" is stored as [a,b,c,d])
  691. *)
  692. PROCEDURE AdrToArray*(adr: Adr; VAR array: ARRAY OF CHAR; ofs: LONGINT; LSBfirst: BOOLEAN);
  693. VAR
  694. tempAdr: Adr;
  695. i, swapTemp: LONGINT;
  696. BEGIN
  697. tempAdr := adr;
  698. CASE adr.usedProtocol OF
  699. IPv4:
  700. IF ~(ofs+4 <= LEN(array)) THEN
  701. tempAdr := NilAdr;
  702. END;
  703. IF LSBfirst THEN
  704. SwapEndian(tempAdr.ipv4Adr);
  705. END;
  706. SYSTEM.MOVE(ADDRESSOF(tempAdr.ipv4Adr), ADDRESSOF(array[ofs]), 4);
  707. | IPv6:
  708. IF ~(ofs + 16 <= LEN(array)) THEN
  709. tempAdr := NilAdr;
  710. END;
  711. IF LSBfirst THEN
  712. FOR i := 0 TO 3 DO
  713. SYSTEM.MOVE(ADDRESSOF(tempAdr.ipv6Adr[i*4]), ADDRESSOF(swapTemp), 4);
  714. SwapEndian(swapTemp);
  715. SYSTEM.MOVE(ADDRESSOF(swapTemp), ADDRESSOF(tempAdr.ipv6Adr[i*4]), 4);
  716. END;
  717. END;
  718. SYSTEM.MOVE(ADDRESSOF(adr.ipv6Adr), ADDRESSOF(array[ofs]), 16);
  719. ELSE
  720. IF DEBUG THEN
  721. ASSERT(TRUE);
  722. END;
  723. END;
  724. END AdrToArray;
  725. (** Reads the IP source address from a buffer *)
  726. PROCEDURE SrcAdrFromBuffer* (buffer: Network.Buffer): Adr;
  727. VAR
  728. i: LONGINT;
  729. adr: Adr;
  730. BEGIN
  731. CASE ORD(buffer.data[buffer.l3ofs]) DIV 16 OF
  732. IPv4:
  733. adr.usedProtocol := IPv4;
  734. SYSTEM.MOVE(ADDRESSOF(buffer.data[buffer.l3ofs+12]),ADDRESSOF(adr.ipv4Adr),4); (* data might be unaligned *)
  735. SetIPv6AdrNil(adr);
  736. RETURN adr;
  737. |IPv6:
  738. adr.usedProtocol := IPv6;
  739. FOR i := 0 TO 15 DO
  740. adr.ipv6Adr[i] := buffer.data[buffer.l3ofs+8 + i];
  741. END;
  742. adr.ipv4Adr := NilAdrIPv4;
  743. ELSE
  744. IF DEBUG THEN
  745. ASSERT(TRUE);
  746. END;
  747. RETURN NilAdr;
  748. END;
  749. RETURN NilAdr;
  750. END SrcAdrFromBuffer;
  751. (** Reads the IP destination address from a buffer *)
  752. PROCEDURE DestAdrFromBuffer* (buffer: Network.Buffer): Adr;
  753. VAR
  754. adr: Adr;
  755. i: LONGINT;
  756. BEGIN
  757. CASE ORD(buffer.data[buffer.l3ofs]) DIV 16 OF
  758. IPv4:
  759. adr.usedProtocol := IPv4;
  760. SYSTEM.MOVE(ADDRESSOF(buffer.data[buffer.l3ofs+16]),ADDRESSOF(adr.ipv4Adr),4); (* data might be unaligned *)
  761. SetIPv6AdrNil(adr);
  762. RETURN adr;
  763. |IPv6:
  764. adr.usedProtocol := IPv6;
  765. FOR i := 0 TO 15 DO
  766. adr.ipv6Adr[i] := buffer.data[buffer.l3ofs+24 + i];
  767. END;
  768. adr.ipv4Adr := NilAdrIPv4;
  769. ELSE
  770. IF DEBUG THEN
  771. ASSERT(TRUE);
  772. END;
  773. RETURN NilAdr;
  774. END;
  775. RETURN NilAdr;
  776. END DestAdrFromBuffer;
  777. (* Swap internal representation of an IP address from big to little endian or vice versa. *)
  778. PROCEDURE -SwapEndian(VAR adr: LONGINT);
  779. CODE
  780. #IF I386 THEN
  781. POP EAX
  782. MOV ECX, [EAX]
  783. XCHG CL, CH
  784. ROL ECX, 16
  785. XCHG CL, CH
  786. MOV [EAX], ECX
  787. #ELSIF AMD64 THEN
  788. POP RAX
  789. MOV ECX, [RAX]
  790. BSWAP ECX
  791. MOV [RAX], ECX
  792. #ELSIF ARM THEN
  793. LDMIA SP!, {R0}
  794. LDR R1, [R0, #0]
  795. REV R1, R1
  796. STR R1, [R0, #0]
  797. #ELSE
  798. unimplemented
  799. #END
  800. END SwapEndian;
  801. (** Write an IP address. *)
  802. PROCEDURE OutAdr*(adr: Adr);
  803. VAR
  804. s: ARRAY 64 OF CHAR;
  805. BEGIN
  806. AdrToStr(adr, s); KernelLog.String(s);
  807. END OutAdr;
  808. (** Enumerate all installed interfaces *)
  809. PROCEDURE Enumerate*(handler: InterfaceHandler);
  810. VAR item: Interface;
  811. BEGIN
  812. item := interfaces;
  813. WHILE item # NIL DO
  814. handler(item);
  815. item := item.next;
  816. END;
  817. END Enumerate;
  818. (** Output the configuration of the specified interface. Can be used as Handler in Enumerate(). *)
  819. PROCEDURE OutInterface*(interface: Interface);
  820. BEGIN
  821. interface.OutInterface;
  822. END OutInterface;
  823. (** Aos command: Output statistics and configuration of all installed interfaces. *)
  824. PROCEDURE IPConfig*(context : Commands.Context);
  825. BEGIN
  826. context.out.String("Interfaces:"); context.out.Ln;
  827. context.out.String("----------------------"); context.out.Ln;
  828. Enumerate(OutInterface);
  829. context.out.Ln;
  830. context.out.String("IP statistics:"); context.out.Ln;
  831. context.out.String("----------------------"); context.out.Ln;
  832. context.out.String("NIPSentToSubnet"); context.out.Int(NIPSentToSubnet,10);context.out.Ln;
  833. context.out.String("NIPSentToGateway"); context.out.Int(NIPSentToGateway,10);context.out.Ln;
  834. context.out.String("NIPSentBroadcast"); context.out.Int(NIPSentBroadcast,10);context.out.Ln;
  835. context.out.String("NIPCantFragment"); context.out.Int(NIPCantFragment,10);context.out.Ln;
  836. context.out.String("NIPRcvTotal"); context.out.Int(NIPRcvTotal,10);context.out.Ln;
  837. context.out.String("NIPTooSmall"); context.out.Int(NIPTooSmall,10);context.out.Ln;
  838. context.out.String("NIPBadVersion"); context.out.Int(NIPBadVersion,10);context.out.Ln;
  839. context.out.String("NIPOptions"); context.out.Int(NIPOptions,10);context.out.Ln;
  840. context.out.String("NIPBadChecksum"); context.out.Int(NIPBadChecksum,10);context.out.Ln;
  841. context.out.String("NIPBadLength"); context.out.Int(NIPBadLength,10);context.out.Ln;
  842. context.out.String("NIPTrim"); context.out.Int(NIPTrim, 10);context.out.Ln;
  843. context.out.String("NIPBadHdrLen"); context.out.Int(NIPBadHdrLen,10);context.out.Ln;
  844. context.out.String("NIPNotForUs"); context.out.Int(NIPNotForUs,10);context.out.Ln;
  845. context.out.String("NIPCantReassemble"); context.out.Int(NIPCantReassemble,10);context.out.Ln;
  846. context.out.String("NIPSrcIsBroadcast"); context.out.Int(NIPSrcIsBroadcast,10);context.out.Ln;
  847. context.out.String("NIPDelivered"); context.out.Int(NIPDelivered,10);context.out.Ln;
  848. context.out.String("NIPNoReceiver"); context.out.Int(NIPNoReceiver,10);context.out.Ln;
  849. context.out.String("NIPForwarded"); context.out.Int(NIPForwarded,10);context.out.Ln;
  850. context.out.String("NIPSentLocalLoopback"); context.out.Int(NIPSentLocalLoopback,10);context.out.Ln;
  851. context.out.String("NIPSentPointToPoint"); context.out.Int(NIPSentPointToPoint,10);context.out.Ln; context.out.Ln;
  852. END IPConfig;
  853. (** First part of a split checksum operation. len must be non-zero and even. chk1 must be 0 at the
  854. beginning. The result can be passed to a following call to Checksum1(). The last chk1 result must
  855. be passed to Checksum2, which sums the data following sequentially on the data summed by this
  856. operation. Carries from bit 15 are accumulated in the top 16 bits, so at most 65535 words can be
  857. summed by Checksum1 and Checksum2 together. *)
  858. PROCEDURE Checksum1*(CONST data: ARRAY OF CHAR; ofs, len, chk1: LONGINT): LONGINT;
  859. CODE
  860. #IF I386 THEN
  861. MOV EAX, [EBP+chk1]
  862. MOV EBX, [EBP+data]
  863. ADD EBX, [EBP+ofs]
  864. MOV ECX, [EBP+len]
  865. SHR ECX, 1
  866. JNC sloop
  867. PUSH 8 ; ASSERT(~ODD(len))
  868. INT 3
  869. sloop:
  870. MOVZX EDX, WORD [EBX]
  871. ADD EAX, EDX
  872. ADD EBX, 2
  873. DEC ECX
  874. JNZ sloop
  875. #ELSIF AMD64 THEN
  876. MOV EAX, [RBP+chk1]
  877. MOV RBX, [RBP+data]
  878. ADD EBX, [RBP+ofs]
  879. MOV ECX, [RBP+len]
  880. SHR ECX, 1
  881. JNC sloop
  882. PUSH 8 ; ASSERT(~ODD(len))
  883. INT 3
  884. sloop:
  885. MOVZX EDX, WORD [RBX]
  886. ADD EAX, EDX
  887. ADD RBX, 2
  888. DEC ECX
  889. JNZ sloop
  890. #ELSIF ARM THEN
  891. LDR R0, [FP, #chk1]
  892. LDR R1, [FP, #ofs]
  893. LDR R2, [FP, #len]
  894. LDR R3, [FP, #data] ; LDR R3, [FP, #20]
  895. ADD R3, R3, R1
  896. AND R4, R2, #1
  897. LSR R2, R2, #1 ; number of 16-bit words to process
  898. CMP R4, #0
  899. BEQ WordLoop
  900. SWI #8 ; ASSERT(~ODD(length))
  901. WordLoop: ; sum up the words
  902. LDRH R4, [R3, #0]
  903. ADD R0, R0, R4
  904. ADD R3, R3, #2
  905. SUB R2, R2, #1
  906. CMP R2, #0
  907. BNE WordLoop
  908. #ELSE
  909. unimplemented
  910. #END
  911. END Checksum1;
  912. (** Continue a checksum operation. len can be zero or odd. chk1 can be the result of Checksum1 for
  913. the immediately preceding data, or 0 for contiguous data. *)
  914. PROCEDURE Checksum2*(CONST data: ARRAY OF CHAR; ofs, len, chk1: LONGINT): INTEGER;
  915. CODE
  916. #IF I386 THEN
  917. MOV EAX, [EBP+chk1]
  918. MOV EBX, [EBP+data]
  919. ADD EBX, [EBP+ofs]
  920. MOV ECX, [EBP+len]
  921. SHR ECX, 1
  922. JZ eloop
  923. sloop:
  924. MOVZX EDX, WORD [EBX]
  925. ADD EAX, EDX
  926. ADD EBX, 2
  927. DEC ECX
  928. JNZ sloop
  929. eloop:
  930. TEST [EBP+len], 1 ; check for odd length
  931. JZ even
  932. MOVZX EDX, BYTE [EBX] ; add last byte
  933. ADD EAX, EDX
  934. even:
  935. MOV ECX, EAX ; now add in all the carries
  936. SHR ECX, 16
  937. AND EAX, 0FFFFH
  938. ADD EAX, ECX
  939. MOV ECX, EAX ; add in additional carry
  940. SHR ECX, 16
  941. ADD EAX, ECX ; result is in low 16 bits of EAX
  942. NOT EAX
  943. #ELSIF AMD64 THEN
  944. MOV EAX, [RBP + chk1]
  945. MOV RBX, [RBP + data]
  946. ADD EBX, [RBP + ofs]
  947. MOV ECX, [RBP + len]
  948. SHR ECX, 1
  949. JZ eloop
  950. sloop:
  951. MOVZX EDX, WORD [RBX]
  952. ADD EAX, EDX
  953. ADD RBX, 2
  954. DEC ECX
  955. JNZ sloop
  956. eloop:
  957. TEST [RBP + len], 1 ; check for odd length
  958. JZ even
  959. MOVZX EDX, BYTE [RBX] ; add last byte
  960. ADD EAX, EDX
  961. even:
  962. MOV ECX, EAX ; now add in all the carries
  963. SHR ECX, 16
  964. AND EAX, 0FFFFH
  965. ADD EAX, ECX
  966. MOV ECX, EAX ; add in additional carry
  967. SHR ECX, 16
  968. ADD EAX, ECX ; result is in low 16 bits of EAX
  969. NOT EAX
  970. #ELSIF ARM THEN
  971. LDR R0, [FP, #chk1]
  972. LDR R1, [FP, #20] ; LDR R1, [FP, #data]
  973. LDR R2, [FP, #ofs]
  974. LDR R3, [FP, #len]
  975. ADD R1, R1, R2
  976. LSR R4, R3, #1 ; number of 16-bit words to process
  977. CMP R4, #0
  978. BEQ Remainder
  979. WordLoop: ; sum up the words
  980. LDRH R5, [R1, #0]
  981. ADD R0, R0, R5
  982. ADD R1, R1, #2
  983. SUB R4, R4, #1
  984. CMP R4, #0
  985. BNE WordLoop
  986. ANDS R5, R3, #1 ; if len is even
  987. BEQ WrapUp
  988. Remainder: ; addition of the remaining byte
  989. LDRB R5, [R1, #0]
  990. ADD R0, R0, R5
  991. WrapUp: ; 32-bit sum is in R0
  992. LDR R7, [PC, #WordMask - $ - 8] ; load the 16-bit word mask
  993. LSR R6, R0, 16 ; upper 16 bits of R0 is the carry
  994. AND R0, R0, R7
  995. ADD R0, R0, R6
  996. LSR R6, R0, 16 ; upper 16 bits of R0 is the carry
  997. AND R0, R0, R7
  998. ADD R0, R0, R6
  999. EOR R0, R0, R7 ; negate the bits of the resulted 16-bit word
  1000. B end
  1001. data:
  1002. WordMask: d32 0FFFFH
  1003. end:
  1004. #ELSE
  1005. unimplemented
  1006. #END
  1007. END Checksum2;
  1008. (* Return TRUE if "adr1" and "adr2" are in the same subnet defined by "mask". Only for IPv4 *)
  1009. PROCEDURE SameSubnetv4(adr1, adr2, mask: LONGINT): BOOLEAN;
  1010. CODE
  1011. #IF I386 THEN
  1012. MOV EAX, [EBP + adr1]
  1013. MOV EBX, [EBP + adr2]
  1014. MOV ECX, [EBP + mask]
  1015. AND EAX, ECX
  1016. AND EBX, ECX
  1017. CMP EAX, EBX
  1018. SETE AL
  1019. #ELSIF AMD64 THEN
  1020. MOV EAX, [RBP + adr1]
  1021. MOV EBX, [RBP + adr2]
  1022. MOV ECX, [RBP + mask]
  1023. AND EAX, ECX
  1024. AND EBX, ECX
  1025. CMP EAX, EBX
  1026. SETE AL
  1027. #ELSIF ARM THEN
  1028. LDR R0, [FP, #adr1]
  1029. LDR R1, [FP, #adr2]
  1030. LDR R2, [FP, #mask]
  1031. AND R0, R0, R2
  1032. AND R1, R1, R2
  1033. CMP R0, R1
  1034. MOVEQ R0, #1
  1035. MOVNE R0, #0
  1036. #ELSE
  1037. unimplemented
  1038. #END
  1039. END SameSubnetv4;
  1040. (* Return TRUE if adr matches the prefix *)
  1041. PROCEDURE MatchPrefix*(adr: Adr; prefix: Adr): BOOLEAN;
  1042. VAR
  1043. bytesToCheck: LONGINT;
  1044. bitsToCheck: LONGINT;
  1045. i: LONGINT;
  1046. matches: BOOLEAN;
  1047. diffSet: SET;
  1048. BEGIN
  1049. IF DEBUG THEN
  1050. ASSERT ((IsNilAdr(adr)) OR (adr.usedProtocol = IPv6));
  1051. END;
  1052. matches := TRUE;
  1053. bytesToCheck := prefix.data DIV 8;
  1054. bitsToCheck := prefix.data MOD 8;
  1055. FOR i := 0 TO bytesToCheck - 1 DO
  1056. IF adr.ipv6Adr[i] # prefix.ipv6Adr[i] THEN
  1057. matches := FALSE;
  1058. END;
  1059. END;
  1060. IF bitsToCheck # 0 THEN
  1061. diffSet := {};
  1062. FOR i := 0 TO 8 - bitsToCheck - 1 DO
  1063. diffSet := diffSet + {i};
  1064. END;
  1065. FOR i := 0 TO bitsToCheck - 1 DO
  1066. IF (SYSTEM.VAL(SET, adr.ipv6Adr[bytesToCheck]) - diffSet) # (SYSTEM.VAL(SET, prefix.ipv6Adr[bytesToCheck]) - diffSet) THEN
  1067. matches := FALSE;
  1068. END;
  1069. END;
  1070. END;
  1071. RETURN matches;
  1072. END MatchPrefix;
  1073. (** Return the interface on which packets with "dst" address should be sent. Return NIL if no interface matches. *)
  1074. PROCEDURE InterfaceByDstIP*(dest: Adr): Interface;
  1075. VAR
  1076. item, gw: Interface;
  1077. BEGIN
  1078. CASE dest.usedProtocol OF
  1079. IPv4:
  1080. gw := NIL;
  1081. item := interfaces;
  1082. LOOP
  1083. IF item = NIL THEN EXIT END;
  1084. IF (item.protocol = IPv4) & (~IsNilAdr(item.localAdr)) & (item.dev.Linked() # Network.LinkNotLinked) THEN
  1085. IF SameSubnetv4(dest.ipv4Adr, item.subnetAdr.ipv4Adr, item.maskAdr.ipv4Adr) THEN
  1086. EXIT;
  1087. ELSIF (gw = NIL) & (~IsNilAdr(item.subnetAdr)) THEN
  1088. IF item.protocol # IPv4 THEN
  1089. gw := item;
  1090. ELSIF ~IsNilAdr(item.gatewayAdr) THEN
  1091. gw := item;
  1092. END;
  1093. END;
  1094. END;
  1095. item := item.next;
  1096. END;
  1097. IF item # NIL THEN
  1098. RETURN item;
  1099. ELSE
  1100. RETURN gw;
  1101. END;
  1102. |IPv6:
  1103. (* Requires special handling when multiple devices are present *)
  1104. RETURN v6InterfaceByDstIP(dest);
  1105. ELSE
  1106. IF DEBUG THEN
  1107. ASSERT(TRUE);
  1108. END;
  1109. RETURN NIL;
  1110. END;
  1111. END InterfaceByDstIP;
  1112. (** Return the reference to an installed interface by its name. NIL is returned if no interface with this name
  1113. was found. *)
  1114. PROCEDURE InterfaceByName*(CONST name: ARRAY OF CHAR): Interface;
  1115. VAR item: Interface;
  1116. BEGIN
  1117. item := interfaces;
  1118. WHILE (item # NIL) & (item.name # name) DO
  1119. item := item.next;
  1120. END;
  1121. RETURN item;
  1122. END InterfaceByName;
  1123. (** Delivers first preferred (if possible) interface of an device.
  1124. Return the reference to an installed interface by its device. NIL is returned if no interface with this
  1125. device was found. *)
  1126. PROCEDURE InterfaceByDevice*(dev: Network.LinkDevice): Interface;
  1127. VAR
  1128. item: Interface;
  1129. unprefInt: Interface;
  1130. BEGIN
  1131. unprefInt := NIL;
  1132. item := interfaces;
  1133. WHILE (item # NIL) DO
  1134. IF item.dev = dev THEN
  1135. IF item.protocol # preferredProtocol THEN
  1136. unprefInt := item;
  1137. ELSE
  1138. RETURN item;
  1139. END;
  1140. END;
  1141. item := item.next;
  1142. END;
  1143. (* return interface with unpreferred protocol or NIL *)
  1144. RETURN unprefInt;
  1145. END InterfaceByDevice;
  1146. (** Return a list of installed interfaces of a certain device. *)
  1147. PROCEDURE InterfaceListByDevice* (dev: Network.LinkDevice):InterfaceList;
  1148. VAR
  1149. item: Interface;
  1150. interfaceList: InterfaceList;
  1151. interfaceListItem: InterfaceList;
  1152. BEGIN
  1153. item := interfaces;
  1154. interfaceList := NIL;
  1155. (* search for interfaces with matching device and put them in a list *)
  1156. WHILE item # NIL DO
  1157. IF item.dev = dev THEN
  1158. NEW(interfaceListItem);
  1159. interfaceListItem.interface := item;
  1160. interfaceListItem.next := interfaceList;
  1161. interfaceList := interfaceListItem;
  1162. END;
  1163. item := item.next;
  1164. END;
  1165. RETURN interfaceList;
  1166. END InterfaceListByDevice;
  1167. (** Install a receiver for a type. The type is stored in
  1168. IPv4: Protocol field
  1169. IPv6: Next header field *)
  1170. PROCEDURE InstallReceiver*( type: LONGINT; r: Receiver);
  1171. BEGIN {EXCLUSIVE}
  1172. IF DEBUG THEN
  1173. ASSERT(r # NIL);
  1174. ASSERT((type >=0) & (type <= 255));
  1175. ASSERT(receivers[type] = NIL);
  1176. END;
  1177. receivers[type] := r;
  1178. END InstallReceiver;
  1179. (** Remove the currently installed receiver for a type. The type is stored in
  1180. IPv4: Protocol field
  1181. IPv6: Next header field *)
  1182. PROCEDURE RemoveReceiver*(type: LONGINT);
  1183. BEGIN {EXCLUSIVE}
  1184. ASSERT((type >=0) & (type <= 255));
  1185. ASSERT(receivers[type] # NIL);
  1186. receivers[type] := NIL;
  1187. END RemoveReceiver;
  1188. (** Checks if a string is a valid IPv4 address *)
  1189. PROCEDURE IsValidIPv4Str (CONST ipString: ARRAY OF CHAR): BOOLEAN;
  1190. VAR
  1191. i,j: LONGINT;
  1192. ipNr: LONGINT;
  1193. digits: ARRAY 4 OF CHAR;
  1194. startClass: LONGINT;
  1195. BEGIN
  1196. i := 0;
  1197. (* Class A *)
  1198. WHILE (i < Strings.Length(ipString)) & (ipString[i] #'.') & (i < 3) DO
  1199. digits[i] := ipString[i];
  1200. INC (i);
  1201. END;
  1202. digits[i] := 0X;
  1203. IF ipString[i] # '.' THEN RETURN FALSE END;
  1204. (* Check if in digits are only numbers *)
  1205. j := 0;
  1206. WHILE digits[j] # 0X DO
  1207. IF (ORD(digits[j]) - ORD("0")) > 9 THEN RETURN FALSE END;
  1208. INC (j);
  1209. END;
  1210. Strings.StrToInt (digits, ipNr);
  1211. IF ipNr > 255 THEN RETURN FALSE END;
  1212. (* Class B *)
  1213. INC(i);
  1214. startClass := i;
  1215. WHILE (i < Strings.Length(ipString)) & (ipString[i] # '.') & (i - startClass <= 3) DO
  1216. digits[i-startClass] := ipString[i];
  1217. INC (i);
  1218. END;
  1219. digits[i-startClass] := 0X;
  1220. IF ipString[i] # '.' THEN RETURN FALSE END;
  1221. (* Check if in digits are only number *)
  1222. j := 0;
  1223. WHILE digits[j] # 0X DO
  1224. IF (ORD(digits[j]) - ORD("0")) > 9 THEN RETURN FALSE END;
  1225. INC (j);
  1226. END;
  1227. Strings.StrToInt (digits, ipNr);
  1228. IF ipNr > 255 THEN RETURN FALSE END;
  1229. (* Class C *)
  1230. INC(i);
  1231. startClass := i;
  1232. WHILE (i < Strings.Length (ipString)) & (ipString[i] # '.') & (i - startClass <= 3) DO
  1233. digits[i-startClass] := ipString[i];
  1234. INC (i);
  1235. END;
  1236. digits[i-startClass] := 0X;
  1237. IF ipString[i] # '.' THEN RETURN FALSE END;
  1238. (* Check if in digits are only number *)
  1239. j := 0;
  1240. WHILE digits[j] # 0X DO
  1241. IF (ORD(digits[j]) - ORD("0")) > 9 THEN RETURN FALSE END;
  1242. INC (j);
  1243. END;
  1244. Strings.StrToInt (digits, ipNr);
  1245. IF ipNr > 255 THEN RETURN FALSE END;
  1246. (* Class D *)
  1247. INC(i);
  1248. startClass := i;
  1249. WHILE (i < Strings.Length (ipString)) & (i - startClass <= 3) DO
  1250. digits[i-startClass] := ipString[i];
  1251. INC (i);
  1252. END;
  1253. digits[i-startClass] := 0X;
  1254. (* Check if in digits are only number *)
  1255. j := 0;
  1256. WHILE digits[j] # 0X DO
  1257. IF (ORD(digits[j]) - ORD("0")) > 9 THEN RETURN FALSE END;
  1258. INC (j);
  1259. END;
  1260. Strings.StrToInt (digits, ipNr);
  1261. IF ipNr > 255 THEN RETURN FALSE END;
  1262. RETURN TRUE;
  1263. END IsValidIPv4Str;
  1264. (** Checks if a string is a valid IPv6 address *)
  1265. PROCEDURE IsValidIPv6Str (ipString: ARRAY OF CHAR): BOOLEAN;
  1266. VAR
  1267. i: LONGINT;
  1268. state: LONGINT; (* -1: error *)
  1269. charCount: LONGINT;
  1270. ascD: LONGINT;
  1271. ascH: LONGINT;
  1272. dPointOcc: BOOLEAN;
  1273. prefixLenArr: ARRAY 3 OF LONGINT;
  1274. prefixLen: LONGINT;
  1275. BEGIN
  1276. i := 0;
  1277. state := 1;
  1278. dPointOcc := FALSE;
  1279. Strings.UpperCase(ipString);
  1280. WHILE (i < (LEN(ipString) - 1)) & (ipString[i] # 0X) DO
  1281. CASE state OF
  1282. -1:
  1283. RETURN FALSE;
  1284. |1:
  1285. (* 0-9 & A-F *)
  1286. ascD := ORD(ipString[i]) - ORD("0");
  1287. ascH := ORD(ipString[i]) - ORD("A");
  1288. IF ((ascD >= 0) & (ascD <= 9)) OR ((ascH >= 0) & (ascH <= 5)) THEN
  1289. INC(charCount);
  1290. (* more than 4 digits between two : *)
  1291. IF charCount > 4 THEN
  1292. state := -1;
  1293. END;
  1294. (* : *)
  1295. ELSIF ipString[i] = ":" THEN
  1296. charCount := 0;
  1297. state := 2;
  1298. ELSIF ipString[i] = "/" THEN
  1299. charCount := 0;
  1300. state := 3;
  1301. ELSE
  1302. state := -1;
  1303. END;
  1304. |2:
  1305. ascD := ORD(ipString[i]) - ORD("0");
  1306. ascH := ORD(ipString[i]) - ORD("A");
  1307. IF ipString[i] = ":" THEN
  1308. IF dPointOcc THEN
  1309. state := -1;
  1310. ELSE
  1311. dPointOcc := TRUE;
  1312. state := 4;
  1313. END
  1314. ELSIF ((ascD >= 0) & (ascD <= 9)) OR ((ascH >= 0) & (ascH <= 5)) THEN
  1315. INC(charCount);
  1316. state := 1;
  1317. ELSE
  1318. state := -1;
  1319. END;
  1320. |3:
  1321. ascD := ORD(ipString[i]) - ORD("0");
  1322. IF ~((ascD >= 0) & (ascD <= 9)) THEN
  1323. state := -1;
  1324. ELSE
  1325. IF charCount > 3 THEN
  1326. state := -1;
  1327. ELSE
  1328. prefixLenArr[charCount] := ascD;
  1329. INC(charCount);
  1330. END;
  1331. END;
  1332. |4:
  1333. ascD := ORD(ipString[i]) - ORD("0");
  1334. ascH := ORD(ipString[i]) - ORD("A");
  1335. IF ipString[i] = "/" THEN
  1336. state := 3;
  1337. ELSIF ((ascD >= 0) & (ascD <= 9)) OR ((ascH >= 0) & (ascH <= 5)) THEN
  1338. INC(charCount);
  1339. state := 1;
  1340. ELSE
  1341. state := -1;
  1342. END;
  1343. ELSE
  1344. IF DEBUG THEN
  1345. ASSERT(TRUE);
  1346. END;
  1347. END;
  1348. INC(i);
  1349. END;
  1350. CASE state OF
  1351. 1:
  1352. RETURN TRUE;
  1353. |3:
  1354. IF charCount > 0 THEN
  1355. prefixLen := 0;
  1356. FOR i:= 0 TO charCount - 1 DO
  1357. prefixLen := prefixLen * 10;
  1358. INC(prefixLen, prefixLenArr[i]);
  1359. END;
  1360. IF prefixLen <= 64 THEN
  1361. RETURN TRUE;
  1362. ELSE
  1363. RETURN FALSE;
  1364. END;
  1365. ELSE
  1366. RETURN FALSE;
  1367. END;
  1368. |4:
  1369. RETURN TRUE;
  1370. ELSE
  1371. IF DEBUG THEN
  1372. ASSERT(TRUE);
  1373. END;
  1374. RETURN FALSE;
  1375. END;
  1376. RETURN FALSE;
  1377. END IsValidIPv6Str;
  1378. (** Set IPv6 address to zero *)
  1379. PROCEDURE SetIPv6AdrNil (adr: Adr);
  1380. VAR
  1381. i: LONGINT;
  1382. BEGIN
  1383. FOR i := 0 TO 15 DO
  1384. adr.ipv6Adr[i] := 0X;
  1385. END;
  1386. END SetIPv6AdrNil;
  1387. (* Add the interface to the IP configuration. *)
  1388. PROCEDURE AddInterface*(int: Interface; VAR res: WORD);
  1389. VAR
  1390. item: Interface;
  1391. BEGIN {EXCLUSIVE}
  1392. item := interfaces;
  1393. WHILE item # NIL DO
  1394. (* Check if interface name already exists *)
  1395. IF item.name = int.name THEN
  1396. res := DuplicateInterfaceName;
  1397. RETURN;
  1398. END;
  1399. item := item.next;
  1400. END;
  1401. (* Add interface *)
  1402. int.next := interfaces;
  1403. interfaces := int;
  1404. res := Ok;
  1405. END AddInterface;
  1406. (* Remove the interface from the IP configuration. *)
  1407. PROCEDURE RemoveInterface*(int: Interface);
  1408. VAR
  1409. item: Interface;
  1410. BEGIN {EXCLUSIVE}
  1411. item := interfaces;
  1412. IF item = NIL THEN
  1413. (* empty list *)
  1414. ELSIF item = int THEN
  1415. (* remove first item *)
  1416. interfaces := interfaces.next;
  1417. ELSE
  1418. WHILE item.next # int DO
  1419. item := item.next;
  1420. END;
  1421. IF item.next # NIL THEN
  1422. item.next := item.next.next;
  1423. ELSE
  1424. (* not found *)
  1425. END;
  1426. END;
  1427. END RemoveInterface;
  1428. (* Prints out a packet *)
  1429. PROCEDURE PacketOut*(CONST title, buffer: ARRAY OF CHAR; all: BOOLEAN);
  1430. VAR
  1431. i: LONGINT;
  1432. length: LONGINT;
  1433. BEGIN
  1434. KernelLog.Ln;KernelLog.String("********************");KernelLog.Ln;
  1435. KernelLog.String(title); KernelLog.Ln;
  1436. IF all THEN
  1437. length := LEN(buffer) -1;
  1438. ELSE
  1439. length := MIN(LEN(buffer) - 1, 256);
  1440. END;
  1441. FOR i := 0 TO length DO
  1442. IF (i MOD 4) = 0 THEN
  1443. KernelLog.Ln;
  1444. KernelLog.Int(i, 2);KernelLog.String(": ");
  1445. END;
  1446. KernelLog.Hex(ORD(buffer[i]), -1);
  1447. KernelLog.String(" ");
  1448. END;
  1449. KernelLog.Ln;KernelLog.String("********************");KernelLog.Ln;
  1450. END PacketOut;
  1451. BEGIN
  1452. (* IPFowarding default value is FALSE *)
  1453. IPForwarding := FALSE;
  1454. (* EchoReply default value is TRUE *)
  1455. EchoReply := TRUE;
  1456. (* Initializations *)
  1457. (* NilAdr *)
  1458. NilAdr.ipv4Adr := NilAdrIPv4;
  1459. SetIPv6AdrNil (NilAdr);
  1460. NilAdr.usedProtocol := NilAdrIdent;
  1461. (* Initialize receiver list *)
  1462. FOR counter:=0 TO NbrOfReceivers-1 DO
  1463. receivers[counter] := NIL;
  1464. END;
  1465. (* Initialize inteface list *)
  1466. interfaces := NIL;
  1467. END IP.
  1468. Free:
  1469. System.Free TraceRoute VNC Ping WMFTPClient FTPClient WebFTPServer TCPServices TLS InitNetwork Ping DHCP TCP DNS UDP ICMP IPv4 IPv6 IP~
  1470. Start:
  1471. InitNetwork.Init
  1472. Compile:
  1473. 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~
  1474. History:
  1475. 02.05.2005 eb Supports IPv6 and fragmented IPv6 packets.
  1476. IsValidIPv6Str:
  1477. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
  1478. FSM used in IsValidIPv6Str:
  1479. -----------------------
  1480. EOS: end of string
  1481. State 1: Initial state
  1482. 0-9/A-F goto state 1
  1483. : goto state 2
  1484. / goto state 3
  1485. EOS valid
  1486. State 2: 0-9/A-F goto state 1
  1487. : goto state 4
  1488. EOS invalid
  1489. State 3: 0-9 goto state 3
  1490. EOS valid
  1491. State 4: / goto state 3
  1492. 0-9/A-F goto state 1
  1493. EOS valid