home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / MSDOS / PKTDRVR / PDTST217.ZIP / PDCLKSRC / ARP.ASM next >
Encoding:
Assembly Source File  |  1994-04-07  |  24.7 KB  |  1,041 lines

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