Win32.I386.IP.Mod 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. (* Aos Runtime: IP, Copyright 2005, Emil J. Zeller *)
  2. (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
  3. MODULE IP; (** AUTHOR "pjm, mvt"; PURPOSE "IP and ARP protocols"; *)
  4. IMPORT SYSTEM, WSock32, Network, Strings, Kernel, KernelLog;
  5. CONST
  6. (** Error codes *)
  7. Ok* = 0;
  8. (** TCP connection states *)
  9. NumStates* = 12; Closed* = 0; Listen* = 1; SynSent* = 2;
  10. SynReceived* = 3; Established* = 4; CloseWait* = 5; FinWait1* = 6;
  11. Closing* = 7; LastAck* = 8; FinWait2* = 9; TimeWait* = 10;
  12. Unused* = 11; (* no real state, only used in this implementation *)
  13. Trace=TRUE;
  14. (** IP address constants *)
  15. NilAdrIPv4 = 0;
  16. NilPort* = 0;
  17. (* Comparators for Adr.usedProtocols *)
  18. IPv4* = 4;
  19. IPv6* = 6;
  20. NilAdrIdent = -1; (* usedProtocol of NilAdrs *)
  21. TYPE
  22. Adr* = RECORD
  23. ipv4Adr*: LONGINT;
  24. ipv6Adr*: ARRAY 16 OF CHAR;
  25. usedProtocol*: LONGINT;
  26. data*: LONGINT;
  27. END; (** An IP Address. usedProtocol = 0: No protocol yet used
  28. usedProtocol = IPv4: IPv4 address stored in field ipv4Adr
  29. usedProtocol = IPv6: IPv6 address stored in field ipv6Adr
  30. data can be used to store additional informations. I.e. in IPv6 the
  31. prefix length is stored in the data field *)
  32. Name* = ARRAY 128 OF CHAR; (** Name type for interface name *)
  33. (** IP interface. See note at the end of the module. *)
  34. Interface* = OBJECT
  35. VAR
  36. (** IP addresses of this interface *)
  37. localAdr-: Adr;
  38. next*:Interface;
  39. END Interface;
  40. VAR
  41. pool*: Kernel.FinalizedCollection; (* pool of all IP.Socket *)
  42. (* Interfaces *)
  43. default-: Interface;
  44. interfaces*: Interface; (* list of all installed interfaces *)
  45. (* IP *)
  46. NilAdr*: Adr; (* To check if an IP address is NIL use IsNilAdr instead *)
  47. (** Is address not yet specified *)
  48. PROCEDURE IsNilAdr* (adr: Adr): BOOLEAN;
  49. VAR
  50. isNil: BOOLEAN;
  51. i: LONGINT;
  52. BEGIN
  53. CASE adr.usedProtocol OF
  54. IPv4:
  55. RETURN (adr.ipv4Adr = NilAdrIPv4)
  56. |IPv6:
  57. isNil := TRUE;
  58. i := 0;
  59. WHILE ((i<16) & isNil) DO
  60. IF adr.ipv6Adr[i] # 0X THEN
  61. isNil := FALSE;
  62. END;
  63. INC(i);
  64. END;
  65. RETURN isNil;
  66. |NilAdrIdent:
  67. RETURN TRUE;
  68. ELSE
  69. RETURN TRUE;
  70. END;
  71. END IsNilAdr;
  72. (* Checks if two addresses are equal *)
  73. PROCEDURE AdrsEqual* (adr1, adr2: Adr): BOOLEAN;
  74. VAR
  75. equal: BOOLEAN;
  76. i: LONGINT;
  77. BEGIN
  78. IF adr1.usedProtocol # adr2.usedProtocol THEN
  79. RETURN FALSE;
  80. END;
  81. CASE adr1.usedProtocol OF
  82. IPv4:
  83. IF adr1.ipv4Adr = adr2.ipv4Adr THEN
  84. RETURN TRUE;
  85. END;
  86. |IPv6:
  87. equal := TRUE;
  88. i := 0;
  89. WHILE ((i < 16) & equal) DO
  90. IF adr1.ipv6Adr[i] # adr2.ipv6Adr[i] THEN
  91. equal := FALSE;
  92. END;
  93. INC(i);
  94. END;
  95. IF adr1.data # adr2.data THEN
  96. equal := FALSE;
  97. END;
  98. RETURN equal;
  99. |NilAdrIdent:
  100. (* both addresses NIL therefore equal *)
  101. IF adr2.usedProtocol = NilAdrIdent THEN
  102. RETURN TRUE;
  103. ELSE
  104. RETURN FALSE;
  105. END;
  106. ELSE
  107. RETURN FALSE;
  108. END;
  109. RETURN FALSE;
  110. END AdrsEqual;
  111. (** Convert a dotted-decimal string to an ip address. Return NilAdr on failure. *)
  112. PROCEDURE StrToAdr*(CONST s: ARRAY OF CHAR): Adr;
  113. VAR
  114. i, j, x: LONGINT;
  115. adr: ARRAY 4 OF CHAR;
  116. ok: BOOLEAN;
  117. ip: Adr;
  118. BEGIN
  119. i := 0; j := 0; x := -1; ok := FALSE;
  120. LOOP
  121. IF (s[i] = ".") OR (s[i] = 0X) THEN
  122. IF (x < 0) OR (x > 255) OR (j = 4) THEN EXIT END;
  123. adr[j] := CHR(x);
  124. IF s[i] = 0X THEN ok := (j = 3); EXIT END;
  125. x := -1; INC(i); INC(j)
  126. ELSIF (s[i] >= "0") & (s[i] <= "9") THEN
  127. IF x = -1 THEN x := 0 END;
  128. x := x*10 + (ORD(s[i])-ORD("0"));
  129. INC(i)
  130. ELSE
  131. EXIT
  132. END
  133. END;
  134. IF ok THEN
  135. ip.ipv4Adr := SYSTEM.VAL(LONGINT,adr);
  136. ip.usedProtocol := IPv4;
  137. RETURN ip;
  138. ELSE
  139. RETURN NilAdr;
  140. END
  141. END StrToAdr;
  142. (** Convert an IP address to a dotted-decimal string. *)
  143. PROCEDURE AdrToStr*(adr: Adr; VAR string: ARRAY OF CHAR);
  144. VAR
  145. i, j, x: LONGINT;
  146. a: ARRAY 4 OF CHAR;
  147. val : LONGINT;
  148. hexToStr: ARRAY 5 OF CHAR;
  149. prefixLenStr: ARRAY 64 OF CHAR;
  150. maxZeroRow: LONGINT;
  151. currentZeroRow: LONGINT;
  152. maxZeroStart: LONGINT;
  153. currentZeroStart: LONGINT;
  154. lastZero: BOOLEAN;
  155. lastDPoint: BOOLEAN;
  156. countEnded: BOOLEAN;
  157. BEGIN
  158. CASE adr.usedProtocol OF
  159. IPv4:
  160. ASSERT(LEN(string) >= 16); (* enough space for largest result *)
  161. Network.Put4(a, 0, adr.ipv4Adr);
  162. i := 0;
  163. FOR j := 0 TO 3 DO
  164. x := ORD(a[j]);
  165. IF x >= 100 THEN string[i] := CHR(ORD("0")+x DIV 100); INC(i) END;
  166. IF x >= 10 THEN string[i] := CHR(ORD("0")+x DIV 10 MOD 10); INC(i) END;
  167. string[i] := CHR(ORD("0")+x MOD 10); INC(i);
  168. IF j = 3 THEN string[i] := 0X ELSE string[i] := "." END;
  169. INC(i)
  170. END
  171. |IPv6:
  172. FOR i := 0 TO (LEN(adr.ipv6Adr) -1) BY 2 DO
  173. (* simple version *)
  174. val := ORD(adr.ipv6Adr[i]) * 256;
  175. val := val + ORD(adr.ipv6Adr[i+1]);
  176. Strings.IntToHexStr (val, 3, hexToStr);
  177. (* Delete leading zeros *)
  178. WHILE (hexToStr[0] = "0") & (hexToStr[1] # 0X) DO
  179. Strings.Delete(hexToStr, 0, 1);
  180. END;
  181. Strings.Append (string, hexToStr);
  182. IF i # (LEN(adr.ipv6Adr) - 2) THEN
  183. Strings.Append (string, ":");
  184. END;
  185. END;
  186. (* replace longest row of zeros with :: *)
  187. maxZeroRow := 0;
  188. currentZeroRow := 0;
  189. maxZeroStart := 0;
  190. currentZeroStart := 0;
  191. i := 0;
  192. lastZero := FALSE;
  193. lastDPoint := TRUE;
  194. countEnded :=TRUE;
  195. WHILE string[i] # 0X DO
  196. IF string[i] = "0" THEN
  197. IF lastDPoint THEN
  198. INC(currentZeroRow);
  199. lastZero := TRUE;
  200. lastDPoint := FALSE;
  201. IF countEnded THEN
  202. currentZeroStart := i;
  203. countEnded := FALSE;
  204. END;
  205. END;
  206. ELSIF string[i] = ":" THEN
  207. lastDPoint := TRUE;
  208. IF lastZero THEN
  209. lastZero := FALSE;
  210. END;
  211. ELSE
  212. IF lastDPoint THEN
  213. lastDPoint := FALSE;
  214. countEnded := TRUE;
  215. IF currentZeroRow > maxZeroRow THEN
  216. maxZeroRow := currentZeroRow;
  217. maxZeroStart := currentZeroStart;
  218. END;
  219. END;
  220. END;
  221. INC(i);
  222. END;
  223. IF ~countEnded THEN
  224. IF currentZeroRow > maxZeroRow THEN
  225. maxZeroRow := currentZeroRow;
  226. maxZeroStart := currentZeroStart;
  227. END;
  228. END;
  229. IF maxZeroRow # 0 THEN
  230. (* write a :: *)
  231. IF maxZeroStart = 0 THEN
  232. string[0] := ":";
  233. i := 1;
  234. WHILE ((string[i] # 0X) & ~((string[i] # "0") & (string[i] # ":"))) DO INC(i); END;
  235. IF string[i] = 0X THEN
  236. string := "::";
  237. ELSE
  238. Strings.Delete(string, 1, i-2);
  239. END;
  240. ELSE
  241. i := maxZeroStart;
  242. WHILE ((string[i] = "0") OR (string[i] = ":")) DO INC(i); END;
  243. IF string[i] = 0X THEN
  244. string[maxZeroStart] := ":";
  245. string[maxZeroStart+1] := 0X;
  246. ELSE
  247. Strings.Delete(string, maxZeroStart, i - maxZeroStart - 1);
  248. END;
  249. END;
  250. END;
  251. IF adr.data # 0 THEN
  252. (* write prefix *)
  253. Strings.IntToStr(adr.data, prefixLenStr);
  254. Strings.Append (string, "/");
  255. Strings.Append (string, prefixLenStr);
  256. END;
  257. ELSE
  258. IF IsNilAdr (adr) THEN
  259. string := "";
  260. END;
  261. END;
  262. END AdrToStr;
  263. (** Convert a IP address from an array [ofs..ofs+x] to an
  264. Adr-type variable.
  265. Example for IPv4:
  266. If the LSB (least significant byte) is stored the the beginning [ofs],
  267. LSBfirst must be set to TRUE.
  268. (address "a.b.c.d" is stored as [d,c,b,a])
  269. If the LSB is stored at the end [ofs+3], LSBfirst must be set to FALSE.
  270. (address "a.b.c.d" is stored as [a,b,c,d])
  271. *)
  272. PROCEDURE ArrayToAdr*(CONST array: ARRAY OF CHAR; ofs, protocol: LONGINT; LSBfirst: BOOLEAN): Adr;
  273. VAR
  274. adr: Adr;
  275. i, swapTemp: LONGINT;
  276. BEGIN
  277. ASSERT((protocol = 4) OR (protocol = 6));
  278. IF protocol = IPv4 THEN (* index check *)
  279. IF ~(ofs + 4 <= LEN(array)) THEN
  280. RETURN NilAdr;
  281. END;
  282. SYSTEM.MOVE(ADDRESSOF(array[ofs]), ADDRESSOF(adr.ipv4Adr), 4);
  283. IF LSBfirst THEN
  284. SwapEndian(adr.ipv4Adr);
  285. END;
  286. adr.usedProtocol := IPv4;
  287. ELSIF protocol = IPv6 THEN
  288. IF ~(ofs + 16 <= LEN(array)) THEN
  289. RETURN NilAdr;
  290. END;
  291. SYSTEM.MOVE(ADDRESSOF(array[ofs]), ADDRESSOF(adr.ipv6Adr), 16);
  292. IF LSBfirst THEN
  293. FOR i := 0 TO 3 DO
  294. SYSTEM.MOVE(ADDRESSOF(adr.ipv6Adr[i*4]), ADDRESSOF(swapTemp), 4);
  295. SwapEndian(swapTemp);
  296. SYSTEM.MOVE(ADDRESSOF(swapTemp), ADDRESSOF(adr.ipv6Adr[i*4]), 4);
  297. END;
  298. END;
  299. adr.usedProtocol := IPv6;
  300. ELSE
  301. RETURN NilAdr;
  302. END;
  303. RETURN adr;
  304. END ArrayToAdr;
  305. (** Convert an Adr-type variable into an array [ofs..ofs+x]
  306. Example in IPv4:
  307. If the LSB (least significant byte) should be stored the the
  308. beginning [ofs], LSBfirst must be set to TRUE.
  309. (address "a.b.c.d" is stored as [d,c,b,a])
  310. If the LSB should be stored at the end [ofs+3], LSBfirst must be set to FALSE.
  311. (address "a.b.c.d" is stored as [a,b,c,d])
  312. *)
  313. PROCEDURE AdrToArray*(adr: Adr; CONST array: ARRAY OF CHAR; ofs: LONGINT; LSBfirst: BOOLEAN);
  314. VAR
  315. tempAdr: Adr;
  316. i, swapTemp: LONGINT;
  317. BEGIN
  318. tempAdr := adr;
  319. CASE adr.usedProtocol OF
  320. IPv4:
  321. IF ~(ofs+4 <= LEN(array)) THEN
  322. tempAdr := NilAdr;
  323. END;
  324. IF LSBfirst THEN
  325. SwapEndian(tempAdr.ipv4Adr);
  326. END;
  327. SYSTEM.MOVE(ADDRESSOF(tempAdr.ipv4Adr), ADDRESSOF(array[ofs]), 4);
  328. | IPv6:
  329. IF ~(ofs + 16 <= LEN(array)) THEN
  330. tempAdr := NilAdr;
  331. END;
  332. IF LSBfirst THEN
  333. FOR i := 0 TO 3 DO
  334. SYSTEM.MOVE(ADDRESSOF(tempAdr.ipv6Adr[i*4]), ADDRESSOF(swapTemp), 4);
  335. SwapEndian(swapTemp);
  336. SYSTEM.MOVE(ADDRESSOF(swapTemp), ADDRESSOF(tempAdr.ipv6Adr[i*4]), 4);
  337. END;
  338. END;
  339. SYSTEM.MOVE(ADDRESSOF(adr.ipv6Adr), ADDRESSOF(array[ofs]), 16);
  340. ELSE
  341. END;
  342. END AdrToArray;
  343. (** Return the interface on which packets with "dst" address should be sent. Return NIL if no interface matches. *)
  344. PROCEDURE InterfaceByDstIP*(dst: Adr): Interface;(*! NYI*)
  345. BEGIN
  346. RETURN default
  347. END InterfaceByDstIP;
  348. (* Find MULTIPLE IP address of the specified host. *)
  349. PROCEDURE InitInterfaces( hostname: ARRAY OF CHAR; VAR res: LONGINT );
  350. VAR hostent: WSock32.PHostent; str: ARRAY 64 OF CHAR;
  351. adr, adr2: Adr;
  352. int0, int:Interface; i:LONGINT;
  353. addr: ADDRESS;
  354. BEGIN
  355. hostent := WSock32.gethostbyname(hostname);
  356. IF hostent = NIL THEN
  357. WSock32.DispError()
  358. ELSE
  359. WHILE hostent.hLength>0 DO
  360. adr.usedProtocol := IPv4;
  361. (*adr := hostent.hName;
  362. adr.ipv4Adr := hostent.hName;*)
  363. SYSTEM.GET(hostent.hAddrList+i*SIZEOF(ADDRESS), addr (*adr.ipv4Adr*));
  364. IF addr # NIL (*adr.ipv4Adr # 0*) THEN
  365. SYSTEM.GET(addr (*adr.ipv4Adr*), adr.ipv4Adr);
  366. NEW(int); int.localAdr:=adr;
  367. IF int0=NIL THEN
  368. int0:=int; interfaces:=int0; default:=int0;
  369. ELSE
  370. int0.next:=int; int0:=int;
  371. END;
  372. INC(i);
  373. KernelLog.String("added IP interface "); AdrToStr(adr, str); KernelLog.String(str); KernelLog.Ln;
  374. END;
  375. DEC(hostent.hLength);
  376. END;
  377. END;
  378. IF adr.ipv4Adr # 0 THEN res := Ok ELSE res := -1 END;
  379. END InitInterfaces;
  380. PROCEDURE Init;
  381. VAR name: ARRAY 256 OF CHAR; res: LONGINT;
  382. BEGIN
  383. KernelLog.String("IP.Init: Hostname ");
  384. res := WSock32.gethostname(name, 256);
  385. IF res = 0 THEN
  386. KernelLog.String(name);KernelLog.Ln;
  387. ELSE
  388. KernelLog.String("failed "); KernelLog.Int(res, 0);KernelLog.Ln;
  389. RETURN
  390. END;
  391. NilAdr.usedProtocol := IPv4;
  392. InitInterfaces(name, res);
  393. END Init;
  394. (* Swap internal representation of an IP address from big to little endian or vice versa. *)
  395. PROCEDURE -SwapEndian(VAR adr: LONGINT);
  396. CODE {SYSTEM.i386}
  397. POP EAX
  398. MOV ECX, [EAX]
  399. XCHG CL, CH
  400. ROL ECX, 16
  401. XCHG CL, CH
  402. MOV [EAX], ECX
  403. END SwapEndian;
  404. BEGIN
  405. default := NIL;
  406. Init;
  407. END IP.
  408. SystemTools.FreeDownTo IP ~