Windows.Network.Mod 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
  2. MODULE Network; (** AUTHOR "pjm, mvt"; PURPOSE "Abstract network device driver"; *)
  3. IMPORT SYSTEM, WSock32, Machine, KernelLog, Plugins, Kernel, Objects, Modules;
  4. VAR
  5. CONST
  6. MaxLinkAdrSize* = 8; (** largest link address size in bytes *)
  7. MaxPacketSize* = 1600; (** maximum amount of data bytes in a link layer frame *)
  8. MaxNofBuffers = 10000; (* maximum number of buffers allowed within the whole net system *)
  9. (** Constants for LinkDevice.type *)
  10. TypePointToPoint* = 0;
  11. TypeEthernet* = 1;
  12. (** Constants for LinkDevice.Linked *)
  13. LinkNotLinked* = 0;
  14. LinkLinked* = 1;
  15. LinkUnknown* = 2;
  16. (** Constants for LinkDevice.calcChecksum and Buffer.calcChecksum *)
  17. ChecksumIP* = 0;
  18. ChecksumUDP* = 1;
  19. ChecksumTCP* = 2;
  20. (* Number of loopback packets that can be sent per 1-2 ms.
  21. This protects the upcall buffers from running out. *)
  22. MaxLoopbackPacketsPerMS = 500;
  23. TYPE
  24. LinkAdr* = ARRAY MaxLinkAdrSize OF CHAR; (** link layer address *)
  25. (** Buffer for passing network packets to upper layer protocols *)
  26. Buffer* = POINTER TO RECORD
  27. data*: ARRAY MaxPacketSize OF CHAR;
  28. ofs*: LONGINT; (** valid data starts at this offset *)
  29. len*: LONGINT; (** length of valid data *)
  30. l3ofs*: LONGINT; (** the layer 3 header starts at this offset *)
  31. l4ofs*: LONGINT; (** the layer 4 header starts at this offset *)
  32. src*: LinkAdr; (** link layer source address *)
  33. calcChecksum*: SET; (** these checksums are already verified by the device *)
  34. int*: LONGINT; (** used in TCP, UDP and ICMP, but can be used by any upper layer protocol *)
  35. set*: SET; (** used in TCP, but can be used by any upper layer protocol *)
  36. next*, prev*: Buffer; (** for queueing the buffer *)
  37. END;
  38. ReceiverList = POINTER TO RECORD
  39. next: ReceiverList;
  40. type: LONGINT;
  41. receiver: Receiver;
  42. END;
  43. SendSnifferList = POINTER TO RECORD
  44. next: SendSnifferList;
  45. sniffer: SendSniffer;
  46. END;
  47. RecvSnifferList = POINTER TO RECORD
  48. next: RecvSnifferList;
  49. sniffer: ReceiveSniffer;
  50. END;
  51. (** Abstract implementation of a generic network driver object *)
  52. LinkDevice* = OBJECT (Plugins.Plugin)
  53. VAR
  54. (** pubic device properties *)
  55. type-: LONGINT; (** LinkType: TypePointToPoint, TypeEthernet *)
  56. local-: LinkAdr; (** local link address *)
  57. broadcast-: LinkAdr; (** link address for sending a broadcast *)
  58. mtu-: LONGINT; (** largest packet size in bytes *)
  59. adrSize-: LONGINT; (** link address size in bytes *)
  60. sendCount-, recvCount-: HUGEINT; (** number of bytes sent and received *)
  61. calcChecksum-: SET; (** these checksums are calculated by the device hardware when sending. *)
  62. recList: ReceiverList; (* receiver list *)
  63. sendSnifferList: SendSnifferList; (* list for send sniffers *)
  64. recvSnifferList: RecvSnifferList; (* list for receive sniffers *)
  65. item: ReceiverList; (* temporary item in receiver list *)
  66. sniffer: RecvSnifferList; (* temporary item in receive sniffer list *)
  67. discard: BOOLEAN; (* shall the current packet be discarded? (used in active body) *)
  68. finalized: BOOLEAN; (* is object already finalized or currently finalizing? *)
  69. (* queue for buffers waiting for upcall *)
  70. upBufFirst, upBufLast: Buffer;
  71. buf: Buffer; (* temporary buffer for active body *)
  72. (* timer and packet count for loopback bandwidth control *)
  73. timer: Kernel.MilliTimer;
  74. packetCount: LONGINT;
  75. (** Constructor - Initialize the driver and the device.
  76. NOTE:
  77. Is normally overridden by device driver. If so, this constructor has to be called at the beginning
  78. of the overriding constructor!
  79. *)
  80. PROCEDURE &Constr*(type, mtu, adrSize: LONGINT);
  81. VAR res: WORD;
  82. BEGIN
  83. ASSERT((mtu >= 0) & (mtu <= MaxPacketSize));
  84. ASSERT((adrSize >= 0) & (adrSize <= MaxLinkAdrSize));
  85. IF type = TypeEthernet THEN
  86. ASSERT(adrSize = 6);
  87. END;
  88. SELF.type := type;
  89. SELF.mtu := mtu;
  90. SELF.adrSize := adrSize;
  91. SELF.sendCount := 0;
  92. SELF.recvCount := 0;
  93. SELF.calcChecksum := {};
  94. recList := NIL;
  95. upBufFirst := NIL;
  96. Kernel.SetTimer(timer, 2);
  97. packetCount := 0;
  98. finalized := FALSE;
  99. sendSnifferList := NIL;
  100. recvSnifferList := NIL;
  101. END Constr;
  102. (** Destructor - Finalize driver object. If connected = TRUE, device is still connected and has to be deinitialized.
  103. NOTE:
  104. Is normally overridden by device driver. If so, this method has to be called at the end
  105. of the overriding method!
  106. *)
  107. PROCEDURE Finalize*(connected: BOOLEAN);
  108. BEGIN {EXCLUSIVE}
  109. ASSERT(~finalized);
  110. finalized := TRUE;
  111. END Finalize;
  112. (** Return the link status of the device.
  113. This function has to be overridden by the device driver in order to provide this information.
  114. *)
  115. PROCEDURE Linked*(): LONGINT;
  116. BEGIN
  117. RETURN LinkUnknown;
  118. END Linked;
  119. (** Send a packet. Called by its user. Can be called concurrently. *)
  120. PROCEDURE Send*(dst: LinkAdr; type: LONGINT; VAR l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT; loopback: BOOLEAN);
  121. VAR
  122. sniffer: SendSnifferList;
  123. discard: BOOLEAN; (* shall the packet be discarded? *)
  124. BEGIN (* can run concurrently with InstallSendSniffer and RemoveSendSniffer *)
  125. ASSERT(~finalized);
  126. discard := FALSE;
  127. sniffer := sendSnifferList;
  128. WHILE sniffer # NIL DO
  129. (* call sniffer *)
  130. discard := discard OR sniffer^.sniffer(SELF, dst, type, l3hdr, l4hdr, data, h3len, h4len, dofs, dlen);
  131. sniffer := sniffer^.next;
  132. END;
  133. IF ~discard THEN
  134. (* send the packet *)
  135. IF loopback THEN
  136. Loopback(dst, type, l3hdr, l4hdr, data, h3len, h4len, dofs, dlen);
  137. ELSE
  138. DoSend(dst, type, l3hdr, l4hdr, data, h3len, h4len, dofs, dlen);
  139. END;
  140. INC(sendCount, dlen + h3len + h4len);
  141. END;
  142. END Send;
  143. (** Do frame send operation. Must be overridden and implemented by device driver! *)
  144. (** Must be able to handle concurrent calls. e.g. by declaring itself as EXCLUSIVE! *)
  145. PROCEDURE DoSend*(dst: LinkAdr; type: LONGINT; VAR l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT);
  146. BEGIN
  147. HALT(301); (* Abstract! *)
  148. END DoSend;
  149. (* Do internal loopback. Send packet directly to the receive queue. *)
  150. PROCEDURE Loopback(dst: LinkAdr; type: LONGINT; VAR l3hdr, l4hdr, data: ARRAY OF CHAR; h3len, h4len, dofs, dlen: LONGINT);
  151. VAR buf: Buffer;
  152. BEGIN
  153. IF packetCount >= MaxLoopbackPacketsPerMS THEN
  154. WHILE ~Kernel.Expired(timer) DO
  155. (* no more packets can be sent until timer is expired *)
  156. Objects.Yield();
  157. END;
  158. Kernel.SetTimer(timer, 2);
  159. packetCount := 0;
  160. END;
  161. buf := GetNewBuffer();
  162. IF buf # NIL THEN
  163. buf.l3ofs := 0;
  164. buf.l4ofs := 0;
  165. buf.ofs := 0;
  166. buf.len := 0;
  167. buf.src := dst;
  168. buf.calcChecksum := {ChecksumIP, ChecksumUDP, ChecksumTCP};
  169. (* Copy data to receive buffer *)
  170. Copy(l3hdr, buf.data, 0, buf.len, h3len);
  171. INC(buf.len, h3len);
  172. Copy(l4hdr, buf.data, 0, buf.len, h4len);
  173. INC(buf.len, h4len);
  174. Copy(data, buf.data, dofs, buf.len, dlen);
  175. INC(buf.len, dlen);
  176. (* Queue the receive buffer *)
  177. QueueBuffer(buf, type);
  178. Machine.AtomicInc(packetCount)
  179. ELSE (* packet loss in loopback :o *)
  180. END
  181. END Loopback;
  182. (** Install a receiver for the given type. Only one receiver can be installed per type! *)
  183. PROCEDURE InstallReceiver*(type: LONGINT; r: Receiver);
  184. VAR item: ReceiverList;
  185. BEGIN {EXCLUSIVE}
  186. (* can run concurrently with active body *)
  187. ASSERT(~finalized);
  188. ASSERT(r # NIL);
  189. (* test if there is already a receiver installed for this type *)
  190. item := recList;
  191. WHILE item # NIL DO
  192. ASSERT(item^.type # type);
  193. item := item^.next;
  194. END;
  195. (* create new entry *)
  196. NEW(item);
  197. item^.type := type;
  198. item^.receiver := r;
  199. item^.next := recList;
  200. recList := item;
  201. END InstallReceiver;
  202. (** Remove the currently installed receiver for the given type. *)
  203. PROCEDURE RemoveReceiver*(type: LONGINT);
  204. VAR item: ReceiverList;
  205. BEGIN {EXCLUSIVE}
  206. (* can run concurrently with active body *)
  207. ASSERT(~finalized);
  208. (* remove receiver *)
  209. IF recList = NIL THEN
  210. (* empty list - nothing to remove *)
  211. ELSIF recList^.type = type THEN
  212. (* remove first item *)
  213. recList := recList^.next;
  214. ELSE
  215. (* search list *)
  216. item := recList;
  217. WHILE (item^.next # NIL) & (item^.next^.type # type) DO
  218. item := item^.next;
  219. END;
  220. IF item^.next # NIL THEN
  221. item^.next := item^.next^.next;
  222. ELSE
  223. (* no receiver found for this type *)
  224. END;
  225. END;
  226. END RemoveReceiver;
  227. (** Install a sniffer for sent packets *)
  228. PROCEDURE InstallSendSniffer*(s: SendSniffer);
  229. VAR item: SendSnifferList;
  230. BEGIN {EXCLUSIVE}
  231. ASSERT(~finalized);
  232. item := sendSnifferList;
  233. WHILE (item # NIL) & (item^.sniffer # s) DO
  234. item := item^.next;
  235. END;
  236. IF item # NIL THEN
  237. (* sniffer already registered *)
  238. ELSE
  239. NEW(item);
  240. item^.sniffer := s;
  241. item^.next := sendSnifferList;
  242. sendSnifferList := item;
  243. END;
  244. END InstallSendSniffer;
  245. (** Remove a sniffer for sent packets *)
  246. PROCEDURE RemoveSendSniffer*(s: SendSniffer);
  247. VAR item: SendSnifferList;
  248. BEGIN {EXCLUSIVE}
  249. ASSERT(~finalized);
  250. IF sendSnifferList = NIL THEN
  251. (* empty list *)
  252. ELSIF sendSnifferList^.sniffer = s THEN
  253. (* remove first item *)
  254. sendSnifferList := sendSnifferList^.next;
  255. ELSE
  256. (* search list *)
  257. item := sendSnifferList;
  258. WHILE (item^.next # NIL) & (item^.next^.sniffer # s) DO
  259. item := item^.next;
  260. END;
  261. IF item^.next # NIL THEN
  262. item^.next := item^.next^.next;
  263. ELSE
  264. (* sniffer not found *)
  265. END;
  266. END;
  267. END RemoveSendSniffer;
  268. (** Install a sniffer for received packets *)
  269. PROCEDURE InstallReceiveSniffer*(s: ReceiveSniffer);
  270. VAR item: RecvSnifferList;
  271. BEGIN {EXCLUSIVE}
  272. ASSERT(~finalized);
  273. item := recvSnifferList;
  274. WHILE (item # NIL) & (item^.sniffer # s) DO
  275. item := item^.next;
  276. END;
  277. IF item # NIL THEN
  278. (* sniffer already registered *)
  279. ELSE
  280. NEW(item);
  281. item^.sniffer := s;
  282. item^.next := recvSnifferList;
  283. recvSnifferList := item;
  284. END;
  285. END InstallReceiveSniffer;
  286. (** Remove a sniffer for received packets *)
  287. PROCEDURE RemoveReceiveSniffer*(s: ReceiveSniffer);
  288. VAR item: RecvSnifferList;
  289. BEGIN {EXCLUSIVE}
  290. ASSERT(~finalized);
  291. IF recvSnifferList = NIL THEN
  292. (* empty list *)
  293. ELSIF recvSnifferList^.sniffer = s THEN
  294. (* remove first item *)
  295. recvSnifferList := recvSnifferList^.next;
  296. ELSE
  297. (* search list *)
  298. item := recvSnifferList;
  299. WHILE (item^.next # NIL) & (item^.next^.sniffer # s) DO
  300. item := item^.next;
  301. END;
  302. IF item^.next # NIL THEN
  303. item^.next := item^.next^.next;
  304. ELSE
  305. (* sniffer not found *)
  306. END;
  307. END;
  308. END RemoveReceiveSniffer;
  309. (** Queue buffer for upcall. Called from inside the LinkDevice object, normally from the interrupt handler. *)
  310. PROCEDURE QueueBuffer*(buf: Buffer; type: LONGINT);
  311. BEGIN {EXCLUSIVE}
  312. ASSERT(buf # NIL);
  313. buf.int := type; (* use "int" field for type information *)
  314. buf.next := NIL;
  315. IF upBufFirst = NIL THEN
  316. upBufFirst := buf;
  317. ELSE
  318. upBufLast.next := buf;
  319. END;
  320. upBufLast := buf;
  321. END QueueBuffer;
  322. BEGIN {ACTIVE, PRIORITY(Objects.High)}
  323. (* can run concurrently with SetReceiver, QueueBuffer, InstallReceiverSniffer and RemoveReceiverSniffer *)
  324. LOOP
  325. BEGIN {EXCLUSIVE}
  326. AWAIT((upBufFirst # NIL) OR finalized);
  327. IF (upBufFirst = NIL) & finalized THEN
  328. (* terminate process after all buffer upcalls are done *)
  329. EXIT;
  330. END;
  331. buf := upBufFirst;
  332. upBufFirst := upBufFirst.next;
  333. END;
  334. INC(recvCount, buf.len);
  335. discard := FALSE;
  336. sniffer := recvSnifferList;
  337. WHILE sniffer # NIL DO
  338. (* call sniffer *)
  339. discard := discard OR sniffer^.sniffer(SELF, buf.int, buf);
  340. sniffer := sniffer^.next;
  341. END;
  342. IF ~discard THEN
  343. (* search for receiver *)
  344. item := recList;
  345. WHILE (item # NIL) & (item^.type # buf.int) DO
  346. item := item^.next;
  347. END;
  348. discard := (item = NIL);
  349. END;
  350. IF discard THEN
  351. (* discard packet and return buffer *)
  352. ReturnBuffer(buf);
  353. ELSE
  354. (* do upcall *)
  355. item^.receiver(SELF, item^.type, buf);
  356. END;
  357. END;
  358. END LinkDevice;
  359. TYPE
  360. (** Upcall procedures *)
  361. (** Packet receiver upcall
  362. CAUTION:
  363. After the buffer has been used, it has to be returned by calling Network.ReturnBuffer(buffer)!
  364. The Receiver can do this by itself or delegate this job to other procedures or processes, wherever the
  365. buffer is passed to. It has not necessarily to be returned within the receiver upcall.
  366. *)
  367. Receiver* = PROCEDURE {DELEGATE} (dev: LinkDevice; type: LONGINT; buffer: Buffer);
  368. (* Sniffer for sent packets. May modify type, headers and data. Return TRUE if packet shall be discarded. *)
  369. (* Must be able to handle concurrent calls. e.g. by declaring itself as EXCLUSIVE. *)
  370. SendSniffer* = PROCEDURE {DELEGATE} (dev: LinkDevice; VAR dst: LinkAdr; VAR type: LONGINT; VAR l3hdr, l4hdr, data: ARRAY OF CHAR; VAR h3len, h4len, dofs, dlen: LONGINT): BOOLEAN;
  371. (* Sniffer for received packets. May modify type and buffer. Return TRUE if packet shall be discarded. *)
  372. (* Will never be called concurrenty from the same LinkDevice. *)
  373. ReceiveSniffer* = PROCEDURE {DELEGATE} (dev: LinkDevice; VAR type: LONGINT; buffer: Buffer): BOOLEAN;
  374. (** Module variables *)
  375. VAR
  376. registry*: Plugins.Registry;
  377. nofBuf: LONGINT; (* number of buffers existing *)
  378. nofFreeBuf: LONGINT; (* number of free buffers *)
  379. freeBufList: Buffer; (* free buffer list *)
  380. (** Get a new buffer - return NIL if MaxNofBuffers is exceeded *)
  381. PROCEDURE GetNewBuffer*(): Buffer;
  382. VAR item: Buffer;
  383. BEGIN {EXCLUSIVE}
  384. IF freeBufList # NIL THEN
  385. (* free buffer is available *)
  386. item := freeBufList;
  387. freeBufList := freeBufList.next;
  388. Machine.AtomicAdd(nofFreeBuf, -1);
  389. ELSIF nofBuf < MaxNofBuffers THEN
  390. (* no free buffer available - create new one *)
  391. NEW(item);
  392. Machine.AtomicInc(nofBuf);
  393. ELSE
  394. (* not allowed to create more buffers *)
  395. item := NIL;
  396. END;
  397. RETURN item;
  398. END GetNewBuffer;
  399. (** Return a buffer to be reused *)
  400. PROCEDURE ReturnBuffer*(buf: Buffer);
  401. BEGIN {EXCLUSIVE}
  402. ASSERT(buf # NIL);
  403. buf.next := freeBufList;
  404. freeBufList := buf;
  405. Machine.AtomicInc(nofFreeBuf);
  406. END ReturnBuffer;
  407. (* Passed to registry.Enumerate() to Finalize each registered LinkDevice *)
  408. PROCEDURE Finalize(p: Plugins.Plugin);
  409. BEGIN
  410. p(LinkDevice).Finalize(TRUE);
  411. END Finalize;
  412. (** Test whether the n bytes of buf1 and buf2 starting at ofs1 and ofs2 respectively are equal *)
  413. PROCEDURE Equal*(VAR buf1, buf2: ARRAY OF CHAR; ofs1, ofs2, n: LONGINT): BOOLEAN;
  414. BEGIN
  415. WHILE (n > 0) & (buf1[ofs1] = buf2[ofs2]) DO INC(ofs1); INC(ofs2); DEC(n) END;
  416. RETURN n <= 0
  417. END Equal;
  418. (** Procedures to put and get data from and to arrays. No index checks are done due to performance! *)
  419. (** Put a 32-bit host value into buf[ofs..ofs+3] *)
  420. PROCEDURE Put4*(VAR buf: ARRAY OF CHAR; ofs, val: LONGINT);
  421. #IF I386 THEN
  422. CODE
  423. MOV EAX, [EBP+val]
  424. MOV EBX, [EBP+ofs]
  425. MOV ECX, [EBP+buf]
  426. MOV [ECX+EBX], EAX
  427. #ELSIF AMD64 THEN
  428. CODE
  429. MOV EAX, [RBP+val]
  430. MOV EBX, [RBP+ofs]
  431. MOV RCX, [RBP+buf]
  432. MOV [RCX+RBX], EAX
  433. #ELSE
  434. BEGIN
  435. ASSERT (FALSE);
  436. #END
  437. END Put4;
  438. (** Put a 16-bit host value into buf[ofs..ofs+1] *)
  439. PROCEDURE Put2*(VAR buf: ARRAY OF CHAR; ofs, val: LONGINT);
  440. #IF I386 THEN
  441. CODE
  442. MOV EAX, [EBP+val]
  443. MOV EBX, [EBP+ofs]
  444. MOV ECX, [EBP+buf]
  445. MOV [ECX+EBX], AX
  446. #ELSIF AMD64 THEN
  447. CODE
  448. MOV EAX, [RBP+val]
  449. MOV EBX, [RBP+ofs]
  450. MOV RCX, [RBP+buf]
  451. MOV [RCX+RBX], AX
  452. #ELSE
  453. BEGIN
  454. ASSERT (FALSE);
  455. #END
  456. END Put2;
  457. (** Get a 32-bit host value from buf[ofs..ofs+3] *)
  458. PROCEDURE Get4*(CONST buf: ARRAY OF CHAR; ofs: LONGINT): LONGINT;
  459. #IF I386 THEN
  460. CODE
  461. MOV EBX, [EBP+ofs]
  462. MOV ECX, [EBP+buf]
  463. MOV EAX, [ECX+EBX]
  464. #ELSIF AMD64 THEN
  465. CODE
  466. MOV EBX, [RBP+ofs]
  467. MOV RCX, [RBP+buf]
  468. MOV EAX, [RCX+RBX]
  469. #ELSE
  470. BEGIN
  471. ASSERT (FALSE);
  472. #END
  473. END Get4;
  474. (** Get a 16-bit host value from buf[ofs..ofs+1] *)
  475. PROCEDURE Get2*(CONST buf: ARRAY OF CHAR; ofs: LONGINT): LONGINT;
  476. #IF I386 THEN
  477. CODE
  478. MOV EBX, [EBP+ofs]
  479. MOV ECX, [EBP+buf]
  480. XOR EAX, EAX
  481. MOV AX, [ECX+EBX]
  482. #ELSIF AMD64 THEN
  483. CODE
  484. MOV EBX, [RBP+ofs]
  485. MOV RCX, [RBP+buf]
  486. XOR EAX, EAX
  487. MOV AX, [RCX+RBX]
  488. #ELSE
  489. BEGIN
  490. ASSERT (FALSE);
  491. #END
  492. END Get2;
  493. (** Put a 32-bit host value into buf[ofs..ofs+3] in network byte order *)
  494. PROCEDURE PutNet4*(VAR buf: ARRAY OF CHAR; ofs, val: LONGINT);
  495. #IF I386 THEN
  496. CODE
  497. MOV EAX, [EBP+val]
  498. XCHG AL, AH
  499. ROL EAX, 16
  500. XCHG AL, AH
  501. MOV EBX, [EBP+ofs]
  502. MOV ECX, [EBP+buf]
  503. MOV [ECX+EBX], EAX
  504. #ELSIF AMD64 THEN
  505. CODE
  506. MOV EAX, [RBP+val]
  507. XCHG AL, AH
  508. ROL EAX, 16
  509. XCHG AL, AH
  510. MOV EBX, [RBP+ofs]
  511. MOV RCX, [RBP+buf]
  512. MOV [RCX+RBX], EAX
  513. #ELSE
  514. BEGIN
  515. ASSERT (FALSE);
  516. #END
  517. END PutNet4;
  518. (** Put a 16-bit host value into buf[ofs..ofs+1] in network byte order *)
  519. PROCEDURE PutNet2*(VAR buf: ARRAY OF CHAR; ofs, val: LONGINT);
  520. #IF I386 THEN
  521. CODE
  522. MOV EAX, [EBP+val]
  523. XCHG AL, AH
  524. MOV EBX, [EBP+ofs]
  525. MOV ECX, [EBP+buf]
  526. MOV [ECX+EBX], AX
  527. #ELSIF AMD64 THEN
  528. CODE
  529. MOV EAX, [RBP+val]
  530. XCHG AL, AH
  531. MOV EBX, [RBP+ofs]
  532. MOV RCX, [RBP+buf]
  533. MOV [RCX+RBX], AX
  534. #ELSE
  535. BEGIN
  536. ASSERT (FALSE);
  537. #END
  538. END PutNet2;
  539. (** Get a 32-bit network value from buf[ofs..ofs+3] in host byte order *)
  540. PROCEDURE GetNet4*(CONST buf: ARRAY OF CHAR; ofs: LONGINT): LONGINT;
  541. #IF I386 THEN
  542. CODE
  543. MOV EBX, [EBP+ofs]
  544. MOV ECX, [EBP+buf]
  545. MOV EAX, [ECX+EBX]
  546. XCHG AL, AH
  547. ROL EAX, 16
  548. XCHG AL, AH
  549. #ELSIF AMD64 THEN
  550. CODE
  551. MOV EBX, [RBP+ofs]
  552. MOV RCX, [RBP+buf]
  553. MOV EAX, [RCX+EBX]
  554. XCHG AL, AH
  555. ROL EAX, 16
  556. XCHG AL, AH
  557. #ELSE
  558. BEGIN
  559. ASSERT (FALSE);
  560. #END
  561. END GetNet4;
  562. (** Get a 16-bit network value from buf[ofs..ofs+1] in host byte order *)
  563. PROCEDURE GetNet2*(CONST buf: ARRAY OF CHAR; ofs: LONGINT): LONGINT;
  564. #IF I386 THEN
  565. CODE
  566. MOV EBX, [EBP+ofs]
  567. MOV ECX, [EBP+buf]
  568. XOR EAX, EAX
  569. MOV AX, [ECX+EBX]
  570. XCHG AL, AH
  571. #ELSIF AMD64 THEN
  572. CODE
  573. MOV EBX, [RBP+ofs]
  574. MOV RCX, [RBP+buf]
  575. XOR EAX, EAX
  576. MOV AX, [RCX+RBX]
  577. XCHG AL, AH
  578. #ELSE
  579. BEGIN
  580. ASSERT (FALSE);
  581. #END
  582. END GetNet2;
  583. (** Convert a LinkAdr to a printable string (up to size*3 characters) *)
  584. PROCEDURE LinkAdrToStr*(VAR adr: LinkAdr; size: LONGINT; VAR s: ARRAY OF CHAR);
  585. VAR
  586. i, j: LONGINT;
  587. hex: ARRAY 17 OF CHAR;
  588. BEGIN
  589. ASSERT(LEN(s) >= size*3); (* enough space for largest result *)
  590. hex := "0123456789ABCDEF";
  591. i := 0;
  592. FOR j := 0 TO size-1 DO
  593. s[i] := hex[ORD(adr[j]) DIV 10H MOD 10H]; INC(i);
  594. s[i] := hex[ORD(adr[j]) MOD 10H]; INC(i);
  595. IF j = size-1 THEN s[i] := 0X ELSE s[i] := ":" END;
  596. INC(i);
  597. END;
  598. END LinkAdrToStr;
  599. (** Write a link address *)
  600. PROCEDURE OutLinkAdr*(VAR adr: LinkAdr; size: LONGINT);
  601. VAR s: ARRAY MaxLinkAdrSize*3 OF CHAR;
  602. BEGIN
  603. LinkAdrToStr(adr, size, s);
  604. KernelLog.String(s);
  605. END OutLinkAdr;
  606. (** Copy data from array to array *)
  607. PROCEDURE Copy*(VAR from, to: ARRAY OF CHAR; fofs, tofs, len: LONGINT);
  608. VAR res: WORD;
  609. BEGIN
  610. IF len > 0 THEN
  611. ASSERT((fofs+len <= LEN(from)) & (tofs+len <= LEN(to)));
  612. SYSTEM.MOVE(ADDRESSOF(from[fofs]), ADDRESSOF(to[tofs]), len);
  613. END;
  614. END Copy;
  615. PROCEDURE Cleanup;
  616. BEGIN
  617. registry.Enumerate(Finalize);
  618. Plugins.main.Remove(registry);
  619. WSock32.CleanUp;
  620. END Cleanup;
  621. BEGIN
  622. nofBuf := 0;
  623. nofFreeBuf := 0;
  624. NEW(registry, "Network", "Network interface drivers");
  625. WSock32.Startup;
  626. Modules.InstallTermHandler(Cleanup);
  627. END Network.
  628. (*
  629. History:
  630. 10.10.2003 mvt Complete redesign and additional implementation of buffer handling and upcall mechanism
  631. 17.10.2003 mvt Changed the way of initialization and finalization (now only Constr/Finalize)
  632. 21.10.2003 mvt Changed SetReceiver to InstallReceiver and RemoveReceiver
  633. 15.11.2003 mvt Changed buffering to work with EXCLUSIVE sections instead of using locking and a semaphore.
  634. 16.11.2003 mvt Added support for checksum calclulation by the device.
  635. 25.11.2003 mvt Added l3ofs and l4ofs to Buffer type.
  636. 17.12.2003 mvt Changed variable "linked" to method "Linked".
  637. *)
  638. (**
  639. How to use the module:
  640. The module is loaded as soon as it is used first. It needn't to be loaded explicitly at startup. It can also be unloaded an reloaded without reboot.
  641. How to use a driver:
  642. Network driver objects in Bluebottle are extensions of the Network.LinkDevice object. All loaded instances of network driver objects are registered in the registry Network.registry. To obtain access to a network driver, use the Get, Await or GetAll methods of this registry.
  643. Example:
  644. VAR dev: Network.LinkDevice;
  645. dev := Network.registry.Get(""); (* if no name is specified, first device (or NIL) is returned *)
  646. The Send method of LinkDevice is used to send a packet. The dst parameter specifies the link destination address (e.g., a 6-byte ethernet MAC address for an ethernet device). The type parameter specifies the link-layer protocol type (e.g. 800H when sending IP over ethernet). The source address of the packet is automatically generated by the device, if necessary.
  647. For reasons of reducing buffer copying between network layers, the method allows 3 buffers to be passed:
  648. The l3hdr, l4hdr, data, h3len, h4len, dofs and dlen fields specify 3 buffers:
  649. One buffer for a layer 3 header, one for a layer 4 header and one for the payload of the packet. The buffers don't have to be filled like this. They are simply concatenated to one frame by the device driver. Therefore, each of them is allowed to be empty.
  650. The layer 3 header is stored in: l3hdr[0..h3len-1]
  651. The layer 4 header is stored in: l4hdr[0..h4len-1]
  652. The payload is stored in data[dofs..dofs+dlen-1]
  653. Example:
  654. CONST
  655. Type = 05555H; (* link-layer protocol type *)
  656. VAR
  657. dlen: LONGINT;
  658. l3hdr: ARRAY HdrLen OF CHAR;
  659. data: ARRAY MaxDataLen OF CHAR;
  660. (* - l3hdr[0..HdrLen-1] contains the layer 3 packet header.
  661. - data[0..dlen-1] contains the packet data.
  662. - there is no layer 4 header in this example, i.e. an empty buffer is passed (len=0)
  663. *)
  664. dev.Send(dev.broadcast, Type, l3hdr, l3hdr, data, HdrLen, 0, 0, dlen); (* send a broadcast packet *)
  665. Packet receiving is driven by the driver object. A receiver interested in a specific type of packet registers itself using the InstallReceiver method. The type parameter specifies the link-layer protocol type, which must be unique. There can only be one receiver installed per type. When a packet arrives, the driver object looks at the protocol type and calls the specific receiver (if any is installed for this type).
  666. Example:
  667. PROCEDURE Receiver(dev: Network.LinkDevice; type: LONGINT; buffer: Network.Buffer);
  668. BEGIN
  669. ASSERT(type = Type);
  670. CheckAdr(buffer.src); (* some link layer source address checks *)
  671. IF ~(ChecksumForThisProtocol IN buffer.calcChecksum) THEN
  672. VerifyChecksum(buffer);
  673. END;
  674. ExamineLayer3Header(buffer.data, buffer.ofs, Layer3HeaderSize);
  675. ProcessPayload(buffer.data, buffer.ofs+Layer3HeaderSize, buffer.len-Header3LayerSize);
  676. (* MANDATORY!!
  677. Buffer must be returned here! - or at higher layers, if the buffer is passed there! *)
  678. Network.ReturnBuffer(buffer);
  679. END Receiver;
  680. dev.InstallReceiver(Type, Receiver); (* install the receiver *)
  681. When passing the buffer to a higher layer (e.g. layer 4), the field "l3ofs" should be set in order to enable the higher layer protocol to access this layer's header (required by ICMP).
  682. The same is valid for the field "l4ofs" when passing the buffer to a higher layer than 4.
  683. The "type" field of a LinkDevice specifies what kind of device it is. Currently, two options (constants) are available:
  684. - TypePointToPoint: dev is a point-to-point link (device), e.g. PPP
  685. - TypeEthernet: dev is an ethernet device
  686. For point-to-point links, the following rules are met:
  687. In constructor, the "local" and "broadcast" parameters are ignored.
  688. If it is not possible to transmit the layer 3 type of packet, the type is set to 0 for the received packet.
  689. If the field "adrSize" is 0, the dst address parameter in Send() is ignored and the src address parameter in the Receiver is not defined.
  690. If "adrSize" is > 0, the dst address passed in Send() is transmitted and presented as src address for the received packet.
  691. The "local" and "broadcast" fields of the object specify the link-level address of the device, and the broadcast address, respectively. If needed, they have to be set during device initialization.
  692. The mtu field specifies the largest allowed packet size in bytes, excluding layer 2 headers and trailers (e.g. 1500 for ethernet).
  693. The "sendCount" and "recvCount" fields show the number of data bytes sent and received by the device since the driver object was loaded.
  694. How to implement a driver:
  695. IMPORTANT:
  696. - Read first "How to use a driver"!
  697. - Read comments of methods you override!
  698. A network driver object is implemented by extending the LinkDevice object. At least the "DoSend" method has to be overridden with a concrete implementation. Normally, you will also override the constructor, the destructor (method "Finalize") and the method "Linked".
  699. CAUTION:
  700. If you override the constructor or destructor:
  701. - At the beginning of the overriding constructor, the overridden constructor has to be called!
  702. - At the end of the overriding destructor, the overridden destructor has to be called!
  703. NOTE:
  704. The device has to be registered and deregistered as a Plugin in Network.registry by the device driver as follows:
  705. Add the device to the registry after it is ready to send/receive data!
  706. Remove the device from the registry before you begin to deinitialize the device!
  707. Normally, the device driver will have to install an interrupt handler for receiving packets. This handler must be installed in Objects. Interrupts registered in Machine are not allowed! (because they are not allowed to call QueueBuffer due to its EXCLUSIVE section)
  708. If you use interrupts:
  709. - do the minimum operations required for receiving and queueing a packet!
  710. - return immediately after having done the operations!
  711. Receiving and queueing packets is done like this:
  712. When you are notified of an incomming network packet (normally by an interrupt), get a new buffer by calling:
  713. buf := Network.GetNewBuffer();
  714. If buf = NIL, the packet has to be discarded because all buffers are currently in use and the maximum amount of buffers (MaxNofBuffers) is exceeded.
  715. If buf # NIL (the normal case), read the packet data into buf.data and set buf.ofs and buf.len accordingly.
  716. The buffer is not initialized in any way.
  717. If the device supports DMA, you could try to get the buffers earlier and pass their physical addesses to the device. With this you can save one packet copying operation!
  718. In addition to the fields "data", "ofs", "len" of "buffer", it is mandatory to set the fields "src" and "calcChecksum" correctly. "src" is the link layer source address and "calcChecksum" is the set of checksums already verified by the device (normally {}).
  719. As soon as the buffer contains the whole packet data, it is passed to the upper layers by calling:
  720. QueueBuffer(buf, type);
  721. Where "type" is the layer 3 type of the packet.
  722. See TestNet.Mod (SendBroadcast, SendTest and Receiver) and IP.Mod (ARPRequest and ARPInput) for an example of packet sending and receiving. See Ethernet3Com90x.Mod for an example of an ethernet driver object and Loopback.Mod for a simple point-to-point link implementation.
  723. *)