home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / PKTDRVR / PDCLK207.ZIP / PDCLKSRC / ARP.ASM next >
Encoding:
Assembly Source File  |  1993-10-09  |  28.3 KB  |  1,181 lines

  1. ;        arp.asm
  2. ;========================================================================
  3.  
  4. ; Copyright (C) 1991 by Jan.Engvald@ldc.lu.se, see file COPYING.
  5.  
  6. ;************************************************************************
  7. ;************************************************************************
  8. ;*
  9. ;*        UDP/IP library
  10. ;*
  11. ;* This library is in a transition phase from a PDCLKSET specific library
  12. ;* into a multiprocess, reentrant, any hardware type, general UDP/IP
  13. ;* library. The buffers used have a descriptor part and a packet part.
  14. ;* The descriptor part is used to allow reentrancy, different physical 
  15. ;* address lengths and varying number of IP options.
  16. ;*
  17. ;* In this library DS:BX always points to the descriptor buffer, DS:DI and
  18. ;* DS:SI usually points to the physical header/IP header/UDP header part of
  19. ;* the IP packet buffer and DX,AX often contains an IP number in network
  20. ;* byte order (DL,DH,AL,AH). For efficiency reasons, IP numbers are
  21. ;* searched last half first (first halves are often equal).
  22. ;*
  23. ;* As this library is still evolving, you can not assume that it looks
  24. ;* the same in the next release. In particular, if you are using any of
  25. ;* of the subroutines, check if their calls or results have been changed.
  26. ;* For the 2.0 version subroutine register usage has changed from save
  27. ;* almost everything to save almost nothing. This because it speeds up
  28. ;* execution speed significantly and there were only a few places where
  29. ;* it affected the caller so he had to save additional registers.
  30. ;*
  31. ;* The current implementation is RFC791 (IP) and RFC1122 (host requirements)
  32. ;* compliant, except for a few cases: I havn't found a reasonable solution
  33. ;* on how to report back to the application ICMP errors like parameter
  34. ;* problem, protocol and port unreachables, and fragment reassembly time
  35. ;* exceeded. Also, IP options are allowed, but the interpretation and handling
  36. ;* must be done by the application. Apart from the above, it is a de luxe
  37. ;* implementation that includes things like multiple default gateways,
  38. ;* sending protocol and port unreachables, IP type of service handling (not
  39. ;* tested), fragment reassembly and source quench introduced delay.
  40. ;*
  41. ;************************************************************************
  42. ;************************************************************************
  43.  
  44. Descriptor    struc
  45. dLink        LinkStruc    <>        ; next & prev links
  46. ; dIOCB     iocb    <>            ; pkt drvr hi perf struc
  47. dPtrPhys    dw    0            ; ptr to physical hdr
  48. dPtrIp        dw    0            ; ptr to IP hdr
  49. dPtrUdp     dw    0            ; ptr to UDP hdr
  50. dPktLen     dw    0            ; packet length (bytes)
  51. dPktEnd     dw    0            ; end of packet
  52. dTimOut2Msg    equ    dPktEnd         ; Timeout msg for findsends
  53. dSqDelay    dw    0            ; source quench delay (ms)
  54. dWaitEvent    dw    0            ; event to wait for
  55. dPtrFrag    equ    dWaitEvent        ; ptr to defargment listhead
  56. dTimOutMsg    dw    0            ; to be displayed at timeout
  57. dTickResend    dw    1*18            ; resend start interval (ticks)
  58. dTickTimeout    dw    4*18            ; timeout ticks (in 1/18 s)
  59. dTick2Timeout    dw    14*18            ; second timeout
  60. dIdxHwDst    equ    dSqDelay        ; arp table index for hw dst
  61. dIdxIpDst    equ    dTick2Timeout        ; arp table index for IP dst
  62. dAdjust     equ    (4-(($-dLink) and 3)) and 3
  63. if    dAdjust
  64.         db    dAdjust dup (0)
  65. endif
  66. dGwys2Chk    db    0            ; # of untried gateways
  67. dSnap        db    0            ; 802.3 snaps used
  68. dPtrDes     dw    0            ; ptr to start of descriptor
  69. dHwDst        equ    $-dLink         ; (part of pd packet)
  70. Descriptor    ends
  71. DESCRLEN    equ    SIZE Descriptor
  72.  
  73. HwStruc     struc
  74. hEthDst     db    6 dup (0)        ; Ethernet destination address
  75. hEthSrc     db    6 dup (0)        ; my Ether addr
  76. hProtType    dw    0008            ; 0800 = IP
  77. HwStruc     ends
  78. HWHDRLEN    equ    SIZE HwStruc
  79.  
  80. SnapStruc    struc
  81. sDSAP        db    170
  82. sSSAP        db    170
  83. sContr        db    3
  84. sOrgCode    db    0,0,0
  85. sProt        db    08, 00
  86. SnapStruc    ends
  87. SNAPLEN     equ    SIZE SnapStruc
  88.  
  89. ArpStruc    struc
  90. iArpHtype    dw    0            ; 0001 = Ether
  91. iArpProt    dw    0008h            ; 0800 = IP
  92. iArpHlen    db    0            ; Hw addr length
  93. iArpPlen    db    4            ; IP addr length
  94. iArpOp        dw    0100h            ; 0001 = request
  95. iArpMyHwAd    db    2*MAX_ADDR_LEN+2*4 dup (0)
  96. ArpBodyLen    =    $-iArpHtype
  97. ArpStruc    ends
  98.  
  99. DriverClass    label    byte
  100. Class2Htype    db    0
  101.         db    1            ; 1 Ethernet
  102.         db    4            ; 2 Pronet-10
  103.         db    6            ; 3 802.5 TR
  104.         db    0            ; 4 Omninet
  105.         db    11            ; 5 LocalTalk
  106.         db    0            ; 6 Slip
  107. if 0
  108.         db    1            ; 7 StarLan
  109.         db    7            ; 8 Arcnet
  110.         db    3            ; 9 AX.25
  111. endif
  112.  
  113. ifndef        ARPSLOTS
  114. ARPSLOTS    equ    12
  115. endif
  116.  
  117. ; The arp table contains information on hosts on this net.
  118. ; Slot 0, 1 and 2 (index 0, 2 and 4) are static and contain:
  119. ; this net broadcast, this subnet broadcast and my address, respectively.
  120. ;
  121. ; If we don't RECEIVE packets for more than a minute from a host or gateway,
  122. ; its slot is cleared. If we then DO receive a packet, the slot is restored
  123. ; by VerifyIpHdr without sending an ARP. On the other hand, if WE want to
  124. ; send the next packet, we will do an ARP and can thus detect dead hosts
  125. ; or gateways.
  126.         even
  127. ArpTabIp2    dw    2 dup (0ffffh)        ; IP # (last part)
  128.         dw    ARPSLOTS-2 dup (0)
  129. ArpTabIp1    dw    2 dup (0ffffh)        ; IP # (first part)
  130.         dw    ARPSLOTS-2 dup (0)
  131. ArpTabTr    dw    ARPSLOTS dup (0)    ; timer
  132. ArpTabFlags    dw    ARPSLOTS dup (0)    ; flags
  133. ArpTabTrSq    dw    ARPSLOTS dup (0)    ; source quench timer
  134. ArpTabSqDelay    dw    ARPSLOTS dup (0)    ; source quench delay
  135. ArpTabHwAdr    db    ARPSLOTS*MAX_ADDR_LEN dup (0ffh) ; hardware addr (max 16 bytes)
  136. ArpTabHwEnd    equ    $
  137. USE_SNAP    equ    1            ; bit in ArpTabFlags
  138. SQ_UPDATED    equ    2            ; bit in ArptabFlags/RouteTabFl
  139.  
  140. ARPMYIDX    equ    4
  141. ArpPutSlot    dw    ARPMYIDX
  142.  
  143. ArpType     dw    0608h
  144. ArpBuf        ArpStruc    <>
  145.  
  146. ArpFixedLen    equ    $-ArpType
  147. aArpOffsSrcIp    equ    iArpMyHwAd+2-iArpHtype
  148. MyHwAd        equ    ArpBuf.iArpMyHwAd
  149. IpType        equ    ArpBuf.iArpProt
  150. ArpFixedPart    equ    ArpType
  151.  
  152.         even
  153. DONT_WAIT    equ    1
  154. GOT_BOOTP    equ    2
  155. GOT_ARPREPLY    equ    4
  156. GOT_TIMEREPLY    equ    8
  157. GOT_ARPREQ    equ    16
  158. GOT_ICMPMSG    equ    32
  159. GOT_NSREPLY    equ    64
  160. Events        dw    1            ; =1 so DONT_WAIT always true
  161.  
  162. ARGZONE     equ    2
  163. ARGZONESPEC    equ    4
  164. DSTNOW        equ    8
  165. IS_A_386    equ    16
  166. TBL_READY    equ    32
  167. UDP_ECHO    equ    64
  168. DBGSTOP        equ    0080h
  169. ECHO_DISPL      equ     0100h
  170. GOT_DSP_ROW    equ    0200h
  171. CONT_ON_ERR    equ    0400h            ; = xor STOP_ON_ERR
  172. NO_ERR_YET    equ    0800h
  173. NO_DROP_YET    equ    1000h
  174. PING_DELAY    equ    2000h
  175. PROBE_REPLY    equ    4000h
  176. DBGINTERR    equ    8000h
  177. GenFlags    dw    NO_DROP_YET
  178.  
  179. SnapHdr     SnapStruc    <>
  180.  
  181. ArpHandle    dw    0
  182. MySegm        dw    0
  183. Hlen        dw    0
  184. H2Len        dw    0
  185. LongerTimOut    dw    0
  186. SavedTicks    dw    0
  187. InSendAndW    db    0
  188.  
  189. if DEBUG
  190. DbgIntCnt    db    1
  191. endif ; DEBUG
  192.  
  193.  
  194.  
  195. ;************************************************************************
  196. ;*        CurrentTicks
  197. ;*    Output:     CX = low word of ticks (1/18 second) counter
  198. ;*    Destroys:    CX, ES
  199. ;************************************************************************
  200.  
  201. CurrentTicks    proc    near
  202.         assume    ds:nothing
  203.         mov    cx,040h         ; DOS data segment
  204.         mov    es,cx
  205.         mov    cx,es:[6ch]        ; get low word of ticks cntr
  206.         mov    cs:SavedTicks,cx
  207.         ret
  208. CurrentTicks    endp
  209.  
  210.  
  211.  
  212. if RFCC
  213. ;************************************************************************
  214. ;*        HardwareTicks (48 bit time to si:dx:ax in 838 ns units)
  215. ;************************************************************************
  216.  
  217. TimerResolution equ    1193            ; hw ticks per millisecond
  218.  
  219. InitTimer    proc    near
  220.         assume    ds:code_s
  221.         test    ArgFlags,AVOID_HDWR
  222.         jnz    InitTimRet
  223.         mov    dx,043h         ; select timer control port
  224.         mov    al,034h
  225.         out    dx,al            ; mode 2: Rate generator
  226.         call    IoDelay         ;   (counts down by 1 to zero)
  227.         xor    ax,ax
  228.         mov    dx,040h         ; select timer 0
  229.         out    dx,al            ; set divide by 2**16
  230.         call    IoDelay
  231.         out    dx,al            ; the generator is now started
  232.   InitTimRet:
  233.         ret
  234. InitTimer    endp
  235.  
  236. RestoreTimer    proc    near
  237.         assume    ds:code_s
  238.         test    ArgFlags,AVOID_HDWR
  239.         jnz    ResTimRet
  240.         mov    dx,043h         ; select timer control port
  241.         mov    al,036h
  242.         out    dx,al            ; mode 3: Square wave generator
  243.         call    IoDelay         ;   (counts down by 2 to zero,
  244.         xor    ax,ax            ;    twice)
  245.         mov    dx,040h         ; select timer 0
  246.         out    dx,al            ; set divide by 2**16
  247.         call    IoDelay
  248.         out    dx,al
  249.   ResTimRet:
  250.         ret
  251. RestoreTimer    endp
  252.  
  253. IoDelay     proc    near
  254.         assume    ds:nothing
  255.         push    ax
  256.         in    al,061h            ; ISA/EISA: 1us, MCA: 0.5 us
  257.         pop    ax
  258.         ret
  259. IoDelay     endp
  260.  
  261. HardwareTicks    proc    near
  262.         assume    ds:nothing
  263.         test    cs:ArgFlags,AVOID_HDWR 
  264.         jnz    HwTicksNoHi
  265.  
  266.         push    es
  267.         mov    dx,020h         ;/* Address PIC ocw3   */
  268.         mov    al,00Ah         ;/* Ask to read irr    */
  269.         cli
  270.         out    dx,al
  271.  
  272.         xor    al,al            ;/* Latch timer 0 */
  273.         out    043h,al
  274.         in    al,040h         ;/* Counter --> ax*/
  275.         mov    ah,al            ;/* LSB in AH      */
  276.         in    al,040h         ;/* MSB in AL      */
  277.         xchg    al,ah   
  278.         not    ax            ;/* Need ascending counter */
  279.         push    ax            ; Save hardware counter value
  280.  
  281.         in    al,dx            ;/* Read irr      */
  282.         push    ax            ; Save irr
  283.  
  284.         in    al,021h         ;/* Read PIC imr  */
  285.         push    ax            ; Save imr
  286.  
  287.         mov    al,00FFh        ;/* Mask all interrupts */
  288.         out    021h,al
  289.  
  290.         mov    ax,040h         ;/* read low word of time */
  291.         mov    es,ax            ;/* from BIOS data area   */
  292.         mov    dx,es:[06Ch]
  293.         mov    si,es:[06Ch+2]        ; get high word too
  294.  
  295.         pop    ax            ; Restore imr
  296.         out    021h,al
  297.         pop    ax            ; Restore irr
  298.         test    al,001h         ;/* Counter hit 0?    */
  299.         pop    ax            ; Restore counter value
  300.         jnz    HwTicksMore        ;/* Jump if yes       */
  301.         sti
  302.         pop    es
  303.         ret
  304.  
  305.   HwTicksMore:
  306.         cmp    ax,0FFh         ;/* Counter > 0x0FF?    */
  307.         ja    HwTicksDone        ;/* Done if so          */
  308.  
  309.         add    dx,1            ;/* Else count int req. */
  310.         adc    si,0
  311.   HwTicksDone:
  312.         sti
  313.         pop    es
  314.         ret
  315.  
  316. HwTicksNoHi:
  317.         push    es
  318.         mov    ax,040h
  319.         mov    es,ax
  320.         cli
  321.         mov    dx,es:[06Ch]
  322.         mov    si,es:[06Ch+2]
  323.         xor    ax,ax
  324.         sti
  325.         pop    es
  326.         ret
  327. HardwareTicks    endp
  328. endif ; RFCC
  329.  
  330.  
  331.  
  332. ;************************************************************************
  333. ;*        OpenProt
  334. ;************************************************************************
  335.  
  336. OpenProt    proc    near
  337.         assume    ds:code_s
  338.         push    si            ; save protocol ptr
  339.         push    ds
  340.         mov    ax,1ffh         ; driver_info
  341.         int_pkt
  342.         pop    ds
  343.  
  344.         call    fatal_error
  345.  
  346.         mov    ah,2            ; access all packets.
  347.         mov    al,ch            ; their class from driver_info().
  348.         mov    DriverClass,ch
  349.         mov    bx,offset Class2Htype    ; class dependent code
  350.         xlat
  351.         mov    byte ptr ArpBuf.iArpHtype+1,al
  352.         cmp    al,6            ; 802.2 ?
  353.         jne    InitNotSnap
  354.         or    GenFlags,USE_SNAP
  355.   InitNotSNap:
  356.         mov    al,ch
  357.         mov    bx,dx            ; their type from driver_info().
  358.         mov    dl,cl            ;their number from driver_info().
  359.         mov    cx,2            ;type length of two.
  360.         pop    si            ;ds:si -> protocol type
  361.         push    cs
  362.         pop    es
  363.         mov    di,offset Receiver    ;es:di -> our receiver.
  364.  
  365.         push    ds
  366.         int_pkt
  367.         pop    ds
  368.  
  369.         call    fatal_error
  370.         ret
  371. OpenProt    endp
  372.  
  373.  
  374.  
  375. ;************************************************************************
  376. ;*        InitProtocols
  377. ;************************************************************************
  378.  
  379. InitProtocols     proc    near
  380.         assume    ds:code_s
  381.  
  382.         push    sp            ; find CPU features
  383.         pop    ax
  384.         cmp    ax,sp            ; 286 or better?
  385.         jne    IsNot386
  386.  
  387.         pushf
  388.         pop    ax
  389.         or    ax,7000h        ;the 386 lets us set these bits
  390.         push    ax
  391.         popf
  392.         pushf
  393.         pop    ax
  394.         test    ax,7000h        ;did the bits get set?
  395.         jz    IsNot386        ;no.
  396.         or    GenFlags,IS_A_386     ;yes, use a 386-optimized code
  397.   IsNot386:
  398.         call    CurrentTicks        ; get current ticks value
  399.         mov    BootpXid,cx
  400. if RFCC
  401.         mov    AgeNext,cx         ; initialize ageing
  402.         mov    AgeFragsNext,cx
  403. endif ; RFCC
  404.  
  405.         mov    si,offset IpType    ; start IP
  406.         call    OpenProt
  407.         mov    IpHandle,ax
  408.  
  409.         cmp    byte ptr ArpBuf.iArpHtype+1,0 ; need ARP?
  410.         je    InitArpNotUsed
  411.  
  412.         mov    si,offset ArpType    ; start ARP
  413.         call    OpenProt
  414.         mov    ArpHandle,ax
  415.  
  416.         mov    bx,ax
  417.         push    cs
  418.         pop    es
  419.         mov    di,offset MyHwAd
  420.         push    di
  421.         mov    cx,15
  422.         mov    ah,6            ; get my Hw addr
  423.  
  424.         push    ds
  425.         int_pkt
  426.         pop    ds
  427.  
  428.         call    fatal_error
  429.  
  430.         mov    ArpBuf.iArpHlen,cl    ; save Hw address length
  431.         mov    Hlen,cx
  432.         shl    cx,1
  433.         mov    H2Len,cx
  434.  
  435.         pop    si            ; my HW addr to ARP tab
  436.         xor    ax,ax
  437.         mov    dx,ax
  438.         call    ArpPutNew
  439.   InitArpNotUsed:
  440.         push    cs
  441.         pop    es
  442.         ret
  443. InitProtocols     endp
  444.  
  445.  
  446.  
  447. ;************************************************************************
  448. ;*        EndProtocol
  449. ;************************************************************************
  450.  
  451. EndProtocol    proc    near
  452.         assume    ds:code_s
  453.         mov    ah,3            ; release handle in bx
  454.  
  455.         push    ds
  456.         int_pkt
  457.         pop    ds
  458.  
  459.         call    print_error
  460.  
  461.         ret
  462. EndProtocol    endp
  463.  
  464.  
  465.  
  466. ;************************************************************************
  467. ;*        MakeSendDescr
  468. ;*
  469. ;*    Input:        DS:BX = IP description buffer ptr (saved)
  470. ;*    Output:     Descriptor defaults filled in
  471. ;*            DI = Udp ptr
  472. ;*    Destroys:    DI, flags
  473. ;************************************************************************
  474.  
  475. MakeSendDescr    proc    near
  476.         assume    ds:nothing
  477.         push    si
  478.         push    cx
  479.         mov    [bx].dSqDelay,0
  480.         mov    [bx].dWaitEvent,0
  481.         mov    [bx].dTimOutMsg,offset MsgNoConect
  482.         mov    [bx].dTickTimeout,4*18
  483.         mov    [bx].dTickResend,1*18
  484.         lea    di,[bx+DESCRLEN+2*MAX_ADDR_LEN+2+SNAPLEN]
  485.         mov    si,di
  486.         sub    si,2
  487.         xor    cx,cx
  488.         test    cs:GenFlags,USE_SNAP    ; 802.5 network?
  489.         jz    MakeNotSnap
  490.         sub    si,SNAPLEN
  491.         inc    cx
  492.   MakeNotSnap:
  493.         mov    [bx].dSnap,cl
  494.         sub    si,cs:H2Len
  495.         mov    [bx].dPtrPhys,si
  496.                 add     si,cs:MyGiant
  497.         mov    [bx].dPktEnd,si
  498.  
  499.         mov    [bx].dPtrIp,di
  500.         mov    word ptr [di].iIpVerHlen,0045h ; IP ver 4; Tos = 0
  501.         mov    [di].iIpFlFrag,0
  502.         mov    [di].iIpTtl,90
  503.  
  504.         add    di,IPHDRLEN
  505.         mov    [bx].dPtrUdp,di
  506.         pop    cx
  507.         pop    si
  508.         ret
  509. MakeSendDescr    endp
  510.  
  511.  
  512.  
  513. ;************************************************************************
  514. ;*        PutPhysSrc
  515. ;*
  516. ;*    Input:        DS:BX = IP description buffer ptr (saved)
  517. ;*            ES = DS
  518. ;*    Output:     HW src addr and IP prot type put into pkt
  519. ;*            CX = phys header length
  520. ;*    Destroys:    CX, SI, DI, ES, flags, enables interrupt
  521. ;************************************************************************
  522.  
  523. PutPhysSrc    proc    near
  524.         assume    ds:nothing
  525.         CHK_ES_EQ_DS
  526.         mov    si,offset MyHwAd    ; get my HW addr from ARP buf
  527.         mov    di,[bx].dPtrPhys
  528.         mov    cx,cs:Hlen
  529.         add    di,cx
  530.   PutPhysLoop1:
  531.         cli
  532.         rep    movs    byte ptr es:[hEthSrc],cs:[MyHwAd]
  533.         sti
  534.  
  535.         test    [bx].dSnap,1        ; use snap?
  536.         jz    PutPhysNotSnap
  537.  
  538.         mov    cx,[bx].dPktLen
  539.         add    cx,SNAPLEN
  540.         xchg    ch,cl
  541.         mov    [di],cx
  542.         add    di,2
  543.  
  544.         mov    si,offset SnapHdr
  545.         rept    (sProt-sDSAP)/2
  546.         movs    word ptr es:[sDSAP], word ptr cs:[SnapHdr]
  547.         endm
  548.   PutPhysNotSnap:
  549.         mov    cx,di
  550.         sub    cx,[bx].dPtrPhys
  551.         add    cx,2            ; physical header length
  552.  
  553.         mov    word ptr [di],0008h    ; protocol type IP (0800)
  554.  
  555.         ret
  556. PutPhysSrc    endp
  557.  
  558.  
  559.  
  560. ;************************************************************************
  561. ;*        ArpFindIp
  562. ;*
  563. ;*    Input:        DX = first word of IP # (saved)
  564. ;*            AX = second word of IP # (saved)
  565. ;*            A PushfDI must be done before calling
  566. ;*    Output:     if found: zero and DI = arp table index
  567. ;*            ES = CS
  568. ;*    Destroys:    CX, DI, ES, flags
  569. ;************************************************************************
  570.  
  571. ArpFindIp    proc    near
  572.         assume    ds:nothing
  573.         mov    es,cs:MySegm
  574.         mov    di,offset ArpTabIp2
  575.         mov    cx,ARPSLOTS
  576.   ArpFindIpNext:                ; look for matching slot
  577.         repne    scasw
  578.         jnz    ArpFindIpRet
  579.  
  580.         cmp    dx,cs:2*ARPSLOTS-2[di]    ; does IP # first part match?
  581.         jne    ArpFindIpNext        ; - no, look further
  582.  
  583.         sub    di,offset ArpTabIp2+2    ; - yes, compute slot index
  584.         cmp    di,di            ; set zero flag
  585.   ArpFindIpRet:
  586.         ret
  587. ArpFindIp    endp
  588.  
  589.  
  590.  
  591. ;************************************************************************
  592. ;*        ArpFindHw
  593. ;*
  594. ;*    Input:        DS:AX = address of HW addr
  595. ;*            A PushfDI must be done before calling
  596. ;*    Output:     if found: zero and DI = arp table index
  597. ;*            ES = CS
  598. ;*    Destroys:    (AX,) DX, CX, SI, DI, ES, flags
  599. ;************************************************************************
  600.  
  601. ArpFindHwHl    proc    near
  602.         assume    ds:nothing
  603.         add    ax,cs:Hlen         ; get physical src addr
  604. ArpFindHw:
  605.         mov    es,cs:MySegm
  606.         mov    dx,offset ArpTabHwAdr+MAX_ADDR_LEN ; first two entries are similar
  607.   ArpFindHwNext:
  608.         mov    cx,cs:Hlen
  609.         mov    di,dx
  610.         mov    si,ax
  611.         repe    cmpsb            ; is this hw addr in arp tab?
  612.         jz    ArpFindHwFound
  613.  
  614.         add    dx,MAX_ADDR_LEN        ; check next entry
  615.         cmp    dx,offset ArpTabHwEnd-MAX_ADDR_LEN ; more entries?
  616.         jbe    ArpFindHwNext
  617.  
  618.         ret                ; not found (non-zero) return
  619.  
  620.   ArpFindHwFound:
  621.         sub    dx,offset ArpTabHwAdr
  622.         shr    dx,1
  623.         shr    dx,1
  624.         shr    dx,1
  625.         mov    di,dx
  626.         cmp    di,di
  627.         ret                ; found (zero) return
  628. ArpFindHwHl    endp
  629.  
  630.  
  631.  
  632. ;************************************************************************
  633. ;*        ArpPutHwAd
  634. ;*
  635. ;*    Input:        DS:SI = pointer to physical address (saved)
  636. ;*            DS:BX = descriptor buffer ptr (saved)
  637. ;*            DI = arp table index
  638. ;*            A PushfDI must be done before calling
  639. ;*    Destroys:    CX, DI, ES, flags
  640. ;************************************************************************
  641.  
  642. ArpPutHwAd    proc    near
  643.         assume    ds:nothing
  644.         mov    es,cs:MySegm
  645.         push    si
  646.  
  647.         mov    cx,cs:SavedTicks    ; get current ticks value
  648.         mov    cs:ArpTabTr[di],cx
  649.  
  650.         mov    cx,cs:ArpTabFlags[di]
  651.         and    cl,not USE_SNAP
  652.         or    cl,[bx].dSnap        ; remember if snaps used
  653.         mov    cs:ArpTabFlags[di],cx    ;   by that host
  654.  
  655.         mov    cl,3            ; put hw addr into slot
  656.         shl    di,cl
  657.         lea    di,ArpTabHwAdr[di]
  658.         mov    cx,cs:Hlen
  659.         rep    movsb
  660.         pop    si
  661.         ret
  662. ArpPutHwAd    endp
  663.  
  664.  
  665.  
  666. ;************************************************************************
  667. ;*        ArpPutHwDst
  668. ;*
  669. ;*    Input:        DX = first word of IP # (saved)
  670. ;*            AX = second word of IP # (saved)
  671. ;*            DS:BX = description buffer ptr (saved)
  672. ;*    Output:     if found: zero, HW dst addr copied to pkt and CX = 0
  673. ;*            ES = DS
  674. ;*    Destroys:    CX, SI, DI, ES, flags
  675. ;************************************************************************
  676.  
  677. ArpPutHwDst    proc    near
  678.         assume    ds:nothing
  679.         cli
  680.  
  681.         call    ArpFindIp        ; IP # in arp table?
  682.         mov    cx,ds
  683.         mov    es,cx
  684.         jnz    ArpPutHwRet        ; - no, non-zero (not found)
  685.  
  686.         mov    cx,cs:ArpTabFlags[di]     ; use snap if neeeded
  687.         and    cl,USE_SNAP
  688.         mov    [bx].dSnap,cl        ;   by dst host
  689. if RFCC
  690.         push    ax
  691.         mov    cx,cs:SavedTicks
  692.         mov    ax,cs:ArpTabSqDelay[di]    ; move sq delay to descriptor
  693.         mov    [bx].dSqDelay,ax
  694.         dec    ax            ; any delay?
  695.         js    ArpNoSqDelay
  696.         mov    ax,cs:ArpTabTrSq[di]    ; - yes
  697.         add    ax,18            ; has one second has passed
  698.         cmp    ax,cx            ;   since we last decremented
  699.         jns    ArpNoSqDelay        ;   the delay value?
  700.         mov    cs:ArpTabTrSq[di],cx
  701.         dec    cs:ArpTabSqDelay[di]    ; - yes, one millisecond off
  702.   ArpNoSqDelay:
  703.         pop    ax
  704. endif ; RFCC
  705.         mov    cl,3            ; - yes, copy HW addr
  706.         shl    di,cl
  707.         lea    si,ArpTabHwAdr[di]
  708.         mov    di,[bx].dPtrPhys
  709.         mov    cx,cs:Hlen
  710.         rep    movs    byte ptr es:[hEthDst],cs:[ArpTabHwAdr]
  711.         cmp    di,di            ; zero (found) return
  712.   ArpPutHwRet:
  713.         sti
  714.         ret
  715. ArpPutHwDst    endp
  716.  
  717.  
  718.  
  719. ;************************************************************************
  720. ;*        ArpPutNew
  721. ;*
  722. ;*    Input:        DX = first word of IP # (saved)
  723. ;*            AX = second word of IP # (saved)
  724. ;*            SI = pointer to physical address (saved)
  725. ;*    Destroys:    CX, DI, ES, flags
  726. ;************************************************************************
  727.  
  728. ArpPutNewSiHl    proc    near
  729.         assume    ds:nothing
  730.         mov    si,[bx].dPtrPhys
  731.         add    si,cs:Hlen
  732.   ArpPutNew:
  733.         PushfDI
  734.  
  735.         call    ArpFindIp        ; already have IP # ?
  736.         jz    ArpPutHere        ; - yes, update hw addr
  737.   ArpPutWrap:                    ; - no, find next slot
  738.         mov    di,cs:ArpPutSlot
  739.         add    di,2            ; advance index two bytes
  740.  
  741.         cmp    di,2*ARPSLOTS        ; end of arp table?
  742.         jb    ArpPut
  743.  
  744.         mov    di,ARPMYIDX+2        ; preserve bcast mappings
  745.   ArpPut:                    ;   (first slots)
  746. if TBLBUILD
  747.         push    si
  748.         mov    si,di
  749.         add    si,2
  750.         cmp    si,2*ARPSLOTS
  751.         jb    ArpPut2
  752.         mov    si,ARPMYIDX+2
  753.   ArpPut2:
  754.         mov    cx,cs:ArpTabTr[di]
  755.         sub    cx,cs:ArpTabTr[si]
  756.         js    ArpPut3
  757.         mov    di,si            ; use elder of next 2 slots
  758.   ArpPut3:
  759.         pop    si
  760. endif ; TBLBUILD
  761.         mov    cs:ArpPutSlot,di
  762.         mov    cs:ArpTabIp1[di],dx    ; put IP # into slot
  763.         mov    cs:ArpTabIp2[di],ax
  764.         xor    cx,cx            ; clear other fileds
  765.         mov    cs:ArpTabFlags[di],cx
  766.         mov    cs:ArpTabSqDelay[di],cx
  767.   ArpPutHere:
  768.         call    ArpPutHwAd        ; put HW addr into slot
  769.  
  770.         PopfEI
  771.         ret
  772. ArpPutNewSiHl    endp
  773.  
  774.  
  775.  
  776. ;************************************************************************
  777. ;*        SendAndWait
  778. ;*    Input:        DS:BX = description buffer ptr (saved)
  779. ;*    Output:     Zero and CX = 0 if OK
  780. ;*            non-zero and CX = errorcode if error 
  781. ;*    Destroys:    AX, CX, DX, SI, DI, ES, flags
  782. ;************************************************************************
  783.  
  784. SendAndWait    proc    near
  785.         assume    ds:nothing
  786.         inc    cs:InSendAndW
  787.  
  788.         mov    si,[bx].dWaitEvent    ; event to wait for
  789.         or    si,si            ; no event to wait for?
  790.         jz    SendDontWait
  791.  
  792.         not    si
  793.         and    cs:Events,si        ; clear this event bit
  794.   SendDontWait:
  795.         not    si
  796.         push    si
  797. if RFCC
  798. ; Do RFC1016 Source Quench Introduced Delay
  799.  
  800.         mov    di,[bx].dSqDelay
  801.         or    di,di            ; any SQ delay?
  802.         jz    SendNoSqDelay
  803.  
  804.         call    HardwareTicks
  805.         call    DblShr10
  806.         add    di,ax
  807.  
  808.         test    cs:ArgFlags,AVOID_HDWR
  809.         jz    SendSqLoop
  810.         add    di,55/2            ; round up
  811.   SendSqLoop:
  812.         call    Something2Do        ; wait a while
  813.         call    HardwareTicks
  814.         call    DblShr10
  815.         cmp    ax,di            ; can we send it now?
  816.         js    SendSqLoop
  817.   SendNoSqDelay:
  818. endif ; RFCC
  819.         call    SendRawPkt        ; send packet part of buffer
  820.  
  821.         pop    si
  822.         test    cs:Events,si        ; got what we want?
  823.         jz    SendWait4Rep
  824.   SendWaitOK:
  825.         xor    cx,cx
  826.   SendWaitRet:
  827.         dec    cs:InSendAndW
  828.         or    cx,cx
  829.         ret
  830.  
  831.  
  832.   SendWait4Rep:
  833.         mov    cx,cs:SavedTicks
  834.         mov    di,[bx].dTickResend    ; first resend time
  835.         mov    ax,cx
  836.         add    ax,di
  837.         add    ax,cs:LongerTimOut
  838.  
  839.         mov    dx,cx
  840.         add    dx,cs:LongerTimOut
  841.         add    dx,[bx].dTickTimeout    ; time out time
  842.   WaitLoop:
  843.         test    cs:Events,si        ; got what we want?
  844.         jnz    SendWaitOK
  845.   SendChk:
  846.         call    Something2Do        ; anything else to do?
  847.   ChkTimeout:
  848.         call    CurrentTicks
  849.         cmp    cx,dx            ; time out?
  850.         jns    SendTimedout
  851.  
  852.         cmp    cx,ax            ; time to resend?
  853.         js    WaitLoop
  854.  
  855.         shl    di,1            ; double resend time    
  856.  
  857.         cmp    di,30*18
  858.         jbe    SendDouble
  859.         mov    di,30*18        ; max 30 seconds
  860.   SendDouble:
  861.         add    ax,di            ; next resend time
  862.  
  863.         push    ax
  864.         push    dx
  865.         push    si
  866.         push    di
  867.         call    SendRawPkt        ; send same packet again
  868.         pop    di
  869.         pop    si
  870.         pop    dx
  871.         pop    ax
  872.         jmp    short WaitLoop
  873.  
  874.   SendTimedout:
  875.         mov    dx,[bx].dTimOutMsg
  876.         mov    cx,SERRTIMOUT
  877.         or    dx,dx            ; if no timeout msg
  878.         jz    SendWaitRet        ;   just return
  879.  
  880.         mov    al,04            ; error code 4
  881.         call    PrTerminate        ; print error msg in dx
  882. SendAndWait    endp
  883.  
  884.  
  885.  
  886. ;************************************************************************
  887. ;*        SendRawPkt
  888. ;*    Input:        DS:BX = description buffer ptr (saved)
  889. ;*    Destroys:    AX, CX, DX, SI, DI, ES, flags
  890. ;************************************************************************
  891.  
  892. SendRawPkt    proc    near
  893.         assume    ds:nothing
  894. if PINGCLIENT
  895.         mov    ax,[bx].dPktLen
  896.         add    ax,8+4+12        ; preamble, crc, intergap
  897.         cli
  898.         add    cs:EchoLoad+2,ax
  899.         adc    cs:EchoLoad,0
  900.         sti
  901. endif ; PINGCLIENT
  902.         mov    ax,3000            ; # of retries if temporary err
  903.   SendRawAgain:
  904.         push    ax
  905.         push    bx
  906.         push    bp
  907.         mov    si,[bx].dPtrPhys    ; get start of packet
  908.         mov    cx,[bx].dPktLen     ; and its length
  909.  
  910.         mov    ah,4            ; send packet to
  911.         push    ds            ;   packet driver
  912.         int_pkt
  913.         pop    ds
  914.  
  915.         pop    bp
  916.         pop    bx
  917.         pop    ax
  918.  
  919.         jc    SendBadPkt        ; any errors?
  920. if DEBUG
  921.         mov    ax,0aaaah        ; trash regs
  922.         mov    cx,ax
  923.         mov    dx,ax
  924.         mov    si,ax
  925.         mov    es,ax
  926. endif ; DEBUG
  927.         ret
  928.  
  929.   SendBadPkt:
  930.         cmp    dh,CANT_SEND        ; can't send?
  931.         jne    SendPermBad
  932.   SendTempBad:                    
  933.         dec    ax            ; have we tried enough times?
  934.         jnz    SendRawAgain
  935.   SendPermBad:
  936.         stc
  937.         call    print_error        ; display explanation
  938.  
  939.         mov    al,03            ; error code 3
  940.         call    Terminate
  941. SendRawPkt    endp
  942.  
  943.  
  944.  
  945. ;************************************************************************
  946. ;*        SendArpReq
  947. ;*
  948. ;*    Input:        DX = first word of IP # (saved)
  949. ;*            AX = second word of IP # (saved)
  950. ;*            DS:BX = IP description buffer ptr (saved)
  951. ;*    Output:     Zero and CX = 0 if OK
  952. ;*            non-zero and CX = errorcode if error 
  953. ;*    Destroys:    CX, SI, DI, ES, flags
  954. ;************************************************************************
  955.  
  956. SendArpReq    proc    near
  957.         assume    ds:nothing
  958.         push    dx            ; dx,ax has IP # to arp for
  959.         push    ax
  960.         push    bx            ; save IP descr addr
  961.         push    ds
  962.  
  963.         call    BufAlloc        ; get a buffer
  964.         mov    cx,SERRNOBUF
  965.         jz    SendArpRet
  966.  
  967.         call    MakeSendDescr        ; set up descriptor
  968.  
  969.         mov    di,[bx].dPtrPhys
  970.         mov    si,offset ArpTabHwAdr    ; put Ether broadcast dst
  971.         mov    cx,cs:Hlen
  972.   SendArpL1:
  973.         movs    byte ptr es:[hEthDst],cs:[ArpTabHwAdr]
  974.         loop    SendArpL1
  975.  
  976.         call    PutPhysSrc        ; put Ether src addr
  977.  
  978.         push    di
  979.         mov    si,offset ArpFixedPart    ; copy in static arp part
  980.         mov    cx,ArpFixedLen-2*MAX_ADDR_LEN
  981.         add    cx,cs:H2len
  982.   SendArpL2:
  983.         movs    byte ptr es:[hEthSrc],byte ptr cs:[ArpFixedPart]
  984.         loop    SendArpL2
  985.  
  986.         sub    di,[bx].dPtrPhys    ; calculate packet length
  987.         mov    [bx].dPktLen,di
  988.  
  989.         pop    di            ; compute addr to dst IP #
  990.         add    di,aArpOffsSrcIp
  991.         add    di,cs:H2Len
  992.  
  993.         mov    [di+4],dx        ; IP # to arp for
  994.         mov    [di+4+2],ax
  995.  
  996.         sub    di,cs:Hlen         ; fill in My IP #
  997.         mov    dx,cs:MyIpNr
  998.         mov    ax,cs:MyIpNr+2
  999.         mov    [di],dx
  1000.         mov    [di+2],ax
  1001.  
  1002.         pop    es
  1003.         pop    si            ; IP descr addr
  1004.         push    si
  1005.         push    es
  1006.  
  1007.         mov    cx,es:[si].dTimOutMsg    ; use application timeout msg
  1008.         mov    [bx].dTimOutMsg,cx
  1009.  
  1010.         mov    cx,es:[si].dTickTimeout    
  1011.         cmp    cx,3*18         ; limit arp timeout
  1012.         jbe    SendArpOkTim
  1013.         mov    cx,3*18         ;   to 3 seconds or less
  1014.   SendArpOkTim:
  1015.         mov    [bx].dTickTimeout,cx
  1016.  
  1017.         mov    [bx].dWaitEvent,GOT_ARPREPLY
  1018.  
  1019.         call    SendAndWait        ; send arp request packet
  1020.  
  1021.         call    BufRelease        ; release buffer
  1022.   SendArpRet:
  1023.         or    cx,cx
  1024.         pop    ds            ; restore IP descr addr
  1025.         pop    bx
  1026.  
  1027.         pop    ax            ; restore IP # we ARPed for
  1028.         pop    dx
  1029.         ret
  1030. SendArpReq    endp
  1031.  
  1032.  
  1033.  
  1034. ;************************************************************************
  1035. ;*        ARP receiver (branched off from general receiver)    *
  1036. ;************************************************************************
  1037.  
  1038.         assume    ds:nothing
  1039.  
  1040. ArpRecvCont:
  1041.         SHOW_EVENT    'C'
  1042.         push    di
  1043.         mov    ax,[bx].dPtrPhys
  1044.         call    ArpFindHwHl        ; Hw Src addr in ARP table?
  1045.         pop    si
  1046.         jnz    ArpRecNew
  1047.  
  1048.         cmp    di,ARPMYIDX        ; ignore pkts from bcast or me
  1049.         jbe    ArpRecRet        ;   (also helps NDIS)
  1050.   ArpRecNew:
  1051.         lea    di,[si].iArpMyHwAd
  1052.         mov    cx,[si].iArpOp        ; ARP reply?
  1053.  
  1054.         mov    si,di
  1055.         add    di,cs:Hlen
  1056.         mov    dx,word ptr [di]    ; get HIS (!) IP # and keep
  1057.         mov    ax,word ptr [di+2]    ;   it for a long while
  1058.  
  1059.         add    di,4
  1060.         cmp    di,[bx].dPktEnd     ; big enough to be arp pkt?
  1061.         ja    ArpRecRet
  1062.  
  1063. ; The following test is not according to the ARP RFC. The reason for this
  1064. ; divergence is that if we follow the RFC algorithm, anybody that momentarily
  1065. ; uses a wrong IP number would disrupt our communication with the original
  1066. ; owner of that IP number. This would be true even if the program he uses
  1067. ; is nice (NCSA Telnet for example) and starts by sending an ARP packet for 
  1068. ; itself to see if anybody will answer (a very good thing to do and this
  1069. ; package does so too).
  1070. ;
  1071. ; We do obey an unsolicited arp reply immediately, other cases of changed
  1072. ; hardware address will be taken care of in a minute automagically by the 
  1073. ; arp table ageing mechanism, so this package should do well even when moving
  1074. ; hosts in a proxy arp environment.
  1075.  
  1076.         cmp    cx,0200h        ; ARP reply?
  1077.         jne    ArpNotReply
  1078.  
  1079.         call    ArpFindIp        ; if he is in our ARP table we
  1080.         jnz    ArpNotThere
  1081.  
  1082.         SHOW_EVENT    'D'
  1083.         call    ArpPutHwAd        ;   should update his HW addr
  1084.   ArpNotThere:
  1085.   ArpNotReply:
  1086.         mov    di,si
  1087.         add    di,cs:H2Len
  1088.         mov    cx,[di+4]
  1089.         cmp    cx,cs:MyIpNr        ; is this arp for me?
  1090.         jne    ArpRecTbl
  1091.         mov    cx,[di+6]
  1092.         cmp    cx,cs:MyIpNr+2
  1093.         jne    ArpRecTbl
  1094.  
  1095.         add    di,8
  1096.         cmp    di,[bx].dPktEnd
  1097.         ja    ArpRecRet
  1098.  
  1099.         SHOW_EVENT    'E'
  1100.         call    ArpPutNew        ; - yes, put his IP # and HW
  1101.                         ;     addr into the ARP table
  1102.         mov    di,[bx].dPtrIp
  1103.         cmp    [di].iArpOp,0100h    ; arp request?
  1104.         je    ArpRecReq
  1105.  
  1106.         or    cs:Events,GOT_ARPREPLY    ; - no, probably a wanted reply
  1107.   ArpRecTbl:
  1108.  
  1109. if TBLBUILD
  1110.         test    cs:ArgFlags,MAKE_TABLE
  1111.         jnz    ArpRecBld
  1112. endif ; TBLBUILD
  1113.  
  1114.   ArpRecRet:
  1115.         jmp    IpRecRet
  1116.  
  1117.   ArpRecKeepBuf:
  1118.         jmp    IpRecKeepBuf
  1119.  
  1120. if TBLBUILD
  1121.   ArpRecBld:
  1122.         cmp    cs:FreeBufs.lBufsAvail,NBUFS/4 ; prevent starving
  1123.         jbe    ArpRecRet
  1124.  
  1125.         test    cs:GenFlags,TBL_READY
  1126.         jz    ArpRecRet
  1127.  
  1128.         SHOW_EVENT    'F'
  1129.         mov    si,offset TblToDo
  1130.         call    AddToList        ; collect adress info
  1131.         jmp    short ArpRecKeepBuf
  1132. endif ; TBLBUILD
  1133.  
  1134.   ArpRecReq:
  1135.         SHOW_EVENT    'G'
  1136.         mov    [di].iArpOp,0200h    ; put arp reply code
  1137.  
  1138.         mov    di,si
  1139.         push    di
  1140.         push    ds
  1141.         pop    es
  1142.         mov    cx,cs:Hlen
  1143.         add    cx,4
  1144.         add    di,cx
  1145.         rep    movsb            ; mov arp dst to arp src
  1146.         pop    di
  1147.  
  1148.         mov    si,offset MyHwAd
  1149.         mov    cx,cs:Hlen
  1150.   ArpRecReqL1:
  1151.         movs    byte ptr es:[hEthSrc],cs:[MyHwAd] ; put in my HW addr as arp src
  1152.         loop    ArpRecReqL1
  1153.  
  1154.         mov    cx,cs:MyIpNr
  1155.         mov    [di],cx         ; put my IP # to arp src
  1156.         mov    si,cs:MyIpNr+2
  1157.         mov    [di+2],si
  1158.  
  1159.         cmp    dx,cx            ; is he stealing my IP # ?
  1160.         jne    ArpRecNoSteal
  1161.         cmp    ax,si
  1162.         jne    ArpRecNoSteal
  1163.  
  1164.         mov    dx,0ffffh        ; - yes, tell everybody by
  1165.         mov    ax,dx            ;   broadcasting my reply
  1166.   ArpRecNoSteal:
  1167.         mov    [bx].dWaitEvent,0
  1168.  
  1169.         call    ArpPutHwDst        ; put dst Ether addr fr DX,AX
  1170.  
  1171.         call    PutPhysSrc        ; put src Ether addr
  1172.  
  1173.         mov    word ptr [di],0608h    ; arp prot
  1174.  
  1175.         mov    si,offset SendToDo    ; put buffer on the send list
  1176.         call    AddToList        ;   for non-interrupt handling
  1177.         jmp    short ArpRecKeepBuf
  1178.  
  1179. ;========================================================================
  1180. ;        endinclude
  1181.