arp.fs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. ( ARP: Address Resolution Protocol JCB 13:12 08/24/10)
  2. module[ arp"
  3. \ ARP uses a small cache of entries. Each entry has an age counter; new
  4. \ entries have an age of 0, any entry with an age >N is old.
  5. \
  6. d# 12 constant arp-cache-entry-size
  7. d# 5 constant arp-cache-entries
  8. TARGET? [IF]
  9. meta
  10. arp-cache-entry-size arp-cache-entries * d# 64 max
  11. target
  12. constant arp-size
  13. create arp-cache arp-size allot
  14. meta
  15. arp-cache-entries 1- arp-cache-entry-size * arp-cache +
  16. target
  17. constant arp-cache-last
  18. [ELSE]
  19. arp-cache-entry-size arp-cache-entries * d# 64 max constant arp-size
  20. create arp-cache arp-size allot
  21. arp-cache-entries 1- arp-cache-entry-size * arp-cache + constant arp-cache-last
  22. [THEN]
  23. : arp-foreach \ (func -- )
  24. arp-cache-last 2>r
  25. begin
  26. 2r@ swap \ ptr func
  27. execute
  28. r> dup arp-cache-entry-size - >r
  29. arp-cache =
  30. until
  31. 2r> 2drop
  32. ;
  33. build-debug? [IF]
  34. : arp-.
  35. dup @ hex4 space \ age
  36. dup 2+ dup @ swap d# 2 + dup @ swap d# 2 + @ ethaddr-pretty space
  37. d# 8 + 2@ ip-pretty
  38. cr
  39. ;
  40. : arp-dump
  41. ['] arp-. arp-foreach
  42. ;
  43. [THEN]
  44. : arp-del h# ff swap ! ;
  45. : arp-reset ['] arp-del arp-foreach ;
  46. : used? @ h# ff <> ;
  47. : arp-age-1 dup used? d# 1 and swap +! ;
  48. : arp-age ['] arp-age-1 arp-foreach ;
  49. : arp-cmp ( ptr0 ptr1 -- ptr) over @ over @ > ?: ;
  50. : arp-oldest \ return the address of the oldest ARP entry
  51. arp-cache ['] arp-cmp arp-foreach ;
  52. \ ARP offsets
  53. \ d# 28 sender ethaddr
  54. \ d# 34 sender ip
  55. \ d# 38 target ethaddr
  56. \ d# 44 target ip
  57. d# 20 constant OFFSET_ARP_OPCODE
  58. d# 22 constant OFFSET_ARP_SRC_ETH
  59. d# 28 constant OFFSET_ARP_SRC_IP
  60. d# 32 constant OFFSET_ARP_DST_ETH
  61. d# 38 constant OFFSET_ARP_DST_IP
  62. : arp-is-response
  63. OFFSET_ETH_TYPE packet@ h# 806 =
  64. OFFSET_ARP_OPCODE packet@ d# 2 =
  65. and
  66. ;
  67. \ write the current arp response into the cache, replacing the oldest entry
  68. : !-- \ ( val ptr -- ptr-2 )
  69. tuck \ ptr val ptr
  70. !
  71. 2-
  72. ;
  73. \ Current packet is an ARP response; write it to the given slot in the ARP cache, ageing all others
  74. : arp-cache-write \ ( ptr -- )
  75. arp-age \ because this new entry will have age d# 0
  76. d# 0 over ! \ age d# 0
  77. >r
  78. d# 3 OFFSET_ARP_SRC_ETH mac-inoffset mac@n
  79. r@ d# 6 + !-- !-- !-- drop
  80. d# 2 OFFSET_ARP_SRC_IP mac-inoffset mac@n
  81. r> d# 8 + 2!
  82. ;
  83. \ Comparison of IP
  84. : arp-cmpip \ (ip01 ip23 ptr/0 ptr -- ip01 ip23 ptr)
  85. dup used? if
  86. dup d# 8 + 2@ d# 2 2pick d<> ?:
  87. else
  88. drop
  89. then
  90. ;
  91. : arp-cache-find ( ip01 ip23 -- ip01 ip23 ptr )
  92. \ Find an IP. Zero if the IP was not found in the cache, ptr to entry otherwise
  93. d# 0 ['] arp-cmpip arp-foreach ;
  94. : arp-issue-whohas \ (ip01 ip23 -- ptr)
  95. mac-pkt-begin
  96. ethaddr-broadcast mac-pkt-3,
  97. net-my-mac mac-pkt-3,
  98. h# 806 \ frame type
  99. d# 1 \ hard type
  100. h# 800 \ prot type
  101. mac-pkt-3,
  102. h# 0604 \ hard size, prot size
  103. d# 1 \ op (1=request)
  104. mac-pkt-2,
  105. net-my-mac mac-pkt-3,
  106. net-my-ip mac-pkt-2,
  107. ethaddr-broadcast mac-pkt-3,
  108. mac-pkt-2,
  109. mac-pkt-complete drop
  110. mac-send
  111. ;
  112. \ Look up ethaddr for given IP.
  113. \ If found, return pointer to the 6-byte ethaddr
  114. \ If not found, issue an ARP request and return d# 0.
  115. : arp-lookup \ ( ip01 ip23 -- ptr)
  116. 2dup
  117. ip-router 2@ dxor ip-subnetmask 2@ dand
  118. d0<>
  119. if
  120. 2drop
  121. ip-router 2@
  122. then
  123. arp-cache-find \ ip01 ip23 ptr
  124. dup 0= if
  125. -rot \ d# 0 ip01 ip23
  126. arp-issue-whohas \ d# 0
  127. else
  128. nip nip 2+ \ ptr
  129. then
  130. ;
  131. \ If the current packet is an ARP request for our IP, answer it
  132. : arp-responder
  133. \ is destination ff:ff:ff:ff:ff:ff or my mac
  134. d# 3 OFFSET_ETH_DST mac-inoffset mac@n
  135. and and invert 0=
  136. net-my-mac \ a b c
  137. d# 2 OFFSET_ETH_DST 2+ mac-inoffset mac@n
  138. d= swap \ F a
  139. OFFSET_ETH_DST packet@ = and
  140. or
  141. OFFSET_ETH_TYPE packet@ h# 806 = and
  142. \ is target IP mine?
  143. d# 2 OFFSET_ARP_DST_IP mac-inoffset mac@n net-my-ip d= and
  144. if
  145. mac-pkt-begin
  146. d# 3 OFFSET_ARP_SRC_ETH mac-pkt-src
  147. net-my-mac mac-pkt-3,
  148. h# 806 \ frame type
  149. d# 1 \ hard type
  150. h# 800 \ prot type
  151. mac-pkt-3,
  152. h# 0604 \ hard size, prot size
  153. d# 2 \ op (2=reply)
  154. mac-pkt-2,
  155. net-my-mac mac-pkt-3,
  156. net-my-ip mac-pkt-2,
  157. d# 3 OFFSET_ARP_SRC_ETH mac-pkt-src
  158. d# 2 OFFSET_ARP_SRC_IP mac-pkt-src
  159. mac-pkt-complete drop
  160. mac-send
  161. then
  162. ;
  163. : arp-announce
  164. mac-pkt-begin
  165. ethaddr-broadcast mac-pkt-3,
  166. net-my-mac mac-pkt-3,
  167. h# 806 \ frame type
  168. d# 1 \ hard type
  169. h# 800 \ prot type
  170. mac-pkt-3,
  171. h# 0604 \ hard size, prot size
  172. d# 2 \ op (2=reply)
  173. mac-pkt-2,
  174. net-my-mac mac-pkt-3,
  175. net-my-ip mac-pkt-2,
  176. ethaddr-broadcast mac-pkt-3,
  177. net-my-ip mac-pkt-2,
  178. mac-pkt-complete drop
  179. mac-send
  180. ;
  181. : arp-handler
  182. arp-responder
  183. arp-is-response
  184. if
  185. d# 2 OFFSET_ARP_SRC_IP mac-inoffset mac@n
  186. arp-cache-find nip nip
  187. dup 0= if
  188. drop arp-oldest
  189. then
  190. arp-cache-write
  191. then
  192. ;
  193. ]module