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

  1. ;        ip.asm
  2. ;========================================================================
  3.  
  4. ; Copyright (C) 1991 by Jan.Engvald@ldc.lu.se, see file COPYING.
  5.  
  6.  
  7.                         ; send errors:
  8. SERRUNREACH    equ    0            ; host or net unreachable
  9. SERRNOBUF    equ    2            ; temporary out of buffers
  10. SERRNOARP    equ    4            ; got no ARP reply
  11. SERRTIMOUT    equ    6            ; general timeout
  12. SERRNOTRAF    equ    8            ; received no traffic from dst
  13. SERRNOIP    equ    10            ; no IP # to send to
  14.  
  15. ICMP_PROT    equ    1            ; Internet Control Msg Prot
  16. UDP_PROT    equ    17            ; IP protocol type UDP
  17.  
  18. IpStruc     struc
  19. iIpVerHlen    db    45h            ; ver 4, 5 32-bit hdr words
  20. iIpTos        db    0            ; type of service
  21. iIpLen        dw    0            ; IP packet length
  22. iIpId        dw    0100h            ; id 0001
  23. iIpFlFrag    dw    0            ; no flags or fragments
  24. iIpTtl        db    90            ; time to live
  25. iIpProt     db    0            ; 17 = udp
  26. iIpXsum     dw    0            ; header checksum
  27. iIpSrc        dw    0, 0            ; Don't know my IP nmbr
  28. iIpDst        dw    0ffffh, 0ffffh        ; local net broadcast IP
  29. iIpOptions    equ    $-iIpVerHlen
  30. IpStruc     ends
  31. IPHDRLEN    equ    SIZE IpStruc
  32.  
  33. UdpStruc    struc
  34. uUdpSrc     dw    4400h            ; source port 44h = 68
  35. uUdpDst     dw    4300h            ; dest port 43h = 67
  36. uUdpLen     dw    0            ; length in bytes
  37. uUdpXsum    dw    0            ; udp checksum
  38. uUdpData    equ    $-uUdpSrc
  39. UdpStruc    ends
  40. UDPHDRLEN    equ    SIZE UdpStruc
  41.  
  42. BootpStruc    struc
  43. uUdpStruc    UdpStruc    <>
  44. uBotOp        db    1            ; bootp request
  45. uBotHtype    db    0            ; hardware type
  46. uBotHlen    db    0            ; hardware addr lenght
  47. uBotHops    db    0            ; hops
  48. uBotXid     dw    0, 0            ; transaction id
  49. uBotSecs    dw    0001            ; 0100h seconds since boot
  50. uBotUnused    dw    0            ; not defined
  51. uBotCliIp    dw    0, 0            ; Client IP unknown
  52. uBotYourIp    dw    0, 0            ; my IP yet unknown
  53. uBotServIp    dw    0, 0            ; Server IP
  54. uBotGwyIp    dw    0, 0            ; Gateway IP
  55. uBotCliHwAd    db    16 dup (0)        ; My Hardware address
  56. uBotSname    db    64 dup (0)        ; server name
  57. uBotFilNam    db    128 dup (0)        ; file name
  58. uBotMagNum    dw    8263h, 6353h        ; Magic number
  59. uBotVend    db    64-4 dup (0)        ; Vendor specific area
  60. BootpStruc    ends
  61. BPDATALEN    equ    SIZE BootpStruc
  62.  
  63. IcmpStruc    struc
  64. uIcmpTypecode    dw    0
  65. uIcmpXsum    dw    0
  66. uIcmpData    dw    0, 0
  67. uIcmpIpHdr    equ    $-uIcmpTypecode
  68. IcmpStruc    ends
  69. ICMPHDRLEN    equ    SIZE IcmpStruc
  70.  
  71.         even
  72. IpHandle    dw    0
  73. MyMask        dw    2 dup (0h)
  74. MyNet        dw    2 dup (0h)
  75. MyIpNr        dw    0, 0
  76. IpIdCounter    dw    0
  77. BootpXid    dw    0
  78. AdrBootpReply    dd    0            ; save address of bootp reply
  79.  
  80. if RFCC
  81. AgeNext     dw    0            ; time to check slots
  82. AgeFragsNext    dw    0
  83. endif ; RFCC
  84.  
  85.  
  86. ifndef        MAXDEFGWYS
  87. MAXDEFGWYS    equ    4
  88. endif
  89.  
  90. DefGwyIndex    dw    0
  91. DefGwyNum    dw    0
  92. DefGwys     dw    MAXDEFGWYS*2 dup (0)
  93.  
  94. if TBLBUILD or PINGCLIENT
  95. DefNSnum    dw    0
  96. DefNS        dw    MAXDEFNS*2 dup (0)
  97. endif ; TBLBUILD or PINGCLIENT
  98.  
  99. ifndef        ROUTESLOTS
  100. ROUTESLOTS    equ    8
  101. endif
  102.  
  103. ; The route table contains information on hosts behind gateways.
  104. ;
  105. ; If we don't receive anything from an IP number within one minute after we
  106. ; last sent to it, we return SERRNOTRAF on the next send. This is cleared
  107. ; after another minute.
  108.  
  109. RouteTabIpD2    dw    ROUTESLOTS dup (0)    ; destination IP #
  110. RouteTabIpD1    dw    ROUTESLOTS dup (0)
  111. RouteTabTos    dw    ROUTESLOTS dup (0)    ; type of service
  112. RouteTabIpG2    dw    ROUTESLOTS dup (0)    ; gateway IP #
  113. RouteTabIpG1    dw    ROUTESLOTS dup (0)
  114. RouteTabTrTx    dw    ROUTESLOTS dup (0)    ; transmitt timer
  115. RouteTabTrRx    dw    ROUTESLOTS dup (0)    ; receive timer
  116. RouteTabFlags    dw    ROUTESLOTS dup (0)    ; flags (must follow TrRx)
  117. RouteTabTrSq    dw    ROUTESLOTS dup (0)    ; source quench timer
  118. RouteTabSqDelay dw    ROUTESLOTS dup (0)    ; source quench delay
  119. RouteTabUnreach dw    ROUTESLOTS dup (0)    ; destination unreachable
  120.  
  121. RoutePutSlot    dw    0
  122.  
  123.         assume    ds:nothing
  124.  
  125. ;************************************************************************
  126. ;*        SendUdpFind
  127. ;*
  128. ;*    Input:        DS:BX = IP description buffer ptr (saved)
  129. ;*            DS:[BX].dPktLen = IP data byte length
  130. ;*            CS:DX = addr of length prepended IP list to send to
  131. ;*                 until reply received
  132. ;*    Output:     Zero and CX = 0 if OK
  133. ;*            non-zero and CX = errorcode if error 
  134. ;*    Destroys:    AX, CX, DX, SI, DI, ES and flags
  135. ;************************************************************************
  136.  
  137. SendUdpFind    proc    near
  138.         mov    [bx].dTimoutMsg,0    ; continue even if no reply
  139.         mov    ah,2            ; do 2 turns over all IP #s
  140.   Send2ndTurn:
  141.         mov    si,dx            ; get IP list addr
  142.         lods    byte ptr cs:[TservNum]    ; # of IP numbers to al
  143.         mov    cx,SERRNOIP
  144.         or    al,al
  145.         jz    SendUdpFindRet
  146.  
  147.         inc    si
  148.   SendNextIP:
  149.         push    ds
  150.         pop    es
  151.         mov    di,[bx].dPtrIp
  152.         lea    di,[di].iIpDst         ; put next IP number
  153.         movs    es:[iIpDst],word ptr cs:[TimeServIpNr]
  154.         movs    es:[iIpDst+2],word ptr cs:[TimeServIpNr]
  155.  
  156.         cmp    ax,0101h        ; last IP last turn?
  157.         jne    Send2orMore
  158.         mov    di,[bx].dTimOut2Msg
  159.         mov    [bx].dTimoutMsg,di    ; -yes, terminate if no reply
  160.   Send2orMore:
  161.         push    ax
  162.         push    dx
  163.         push    si
  164.         mov    ax,[bx].dPktLen
  165.         call    SendUdpPkt        ; send udp packet
  166.         pop    si
  167.         pop    dx
  168.         pop    ax
  169.         jz    SendUdpFindRet        ; done if reply
  170.  
  171.         dec    al
  172.         jnz    SendNextIP        ; more IP numbers this turn?
  173.  
  174.         mov    di,[bx].dTick2Timeout    ; -no, use longer timeout
  175.         mov    [bx].dTickTimeout,di    ;   for 2nd turn
  176.         dec    ah
  177.         jnz    Send2ndTurn        ; both turns done?
  178.  
  179.   SendUdpFindRet:
  180.         or    cx,cx
  181.         ret
  182. SendUdpFind    endp
  183.  
  184.  
  185.  
  186. ;************************************************************************
  187. ;*        SendUdpPkt
  188. ;*
  189. ;*    Input:        DS:BX = IP description buffer ptr (saved)
  190. ;*            DS:[BX].dPktLen = IP data byte length
  191. ;*    Output:     Zero and CX = 0 if OK
  192. ;*            non-zero and CX = errorcode if error 
  193. ;*    Destroys:    AX, CX, DX, SI, DI, ES and flags
  194. ;************************************************************************
  195.  
  196. SendUdpPkt    proc    near
  197.         mov    dx,cs:MyIpNr        ; fill in my IP # (used
  198.         mov    di,[bx].dPtrIp        ;   in udp chksum!)
  199.         mov    [di].iIpSrc,dx
  200.         mov    dx,cs:MyIpNr+2
  201.         mov    [di].iIpSrc+2,dx
  202.  
  203.         mov    ax,[bx].dPktLen
  204.         xchg    ah,al
  205.         mov    si,[bx].dPtrUdp
  206.         mov    [si].uUdpLen,ax     ; fill in UDP total length
  207.  
  208.         mov    [si].uUdpXsum,ax    ; ensure chksum is calculated
  209.  
  210.         mov    [di].iIpProt,UDP_PROT    ; set UDP protocol
  211.  
  212.         call    UdpChkSum        ; calculate UDP checksum
  213.  
  214.         jmp    short SendIpPkt        ; send UDP packet
  215. SendUdpPkt    endp
  216.  
  217.  
  218.  
  219. ;************************************************************************
  220. ;*        SendIcmpPkt
  221. ;*
  222. ;*    Input:        DS:BX = IP description buffer ptr (saved)
  223. ;*            DS:[BX].dPktLen = IP data byte length
  224. ;*    Output:     Zero and CX = 0 if OK
  225. ;*            non-zero and CX = errorcode if error 
  226. ;*    Destroys:    AX, CX, DX, SI, DI, ES and flags
  227. ;************************************************************************
  228.  
  229. SendIcmpPkt    proc    near
  230.         call    IcmpChkSum        ; calculate icmp checksum
  231.  
  232.         mov    di,[bx].dPtrIp
  233.         mov    [di].iIpProt,ICMP_PROT
  234. SendIcmpReply:
  235.         mov    [bx].dWaitEvent,0    ; don't wait for answer
  236.  
  237. ;        call    SendIpPkt
  238. ;        ret
  239. SendIcmpPkt    endp
  240.  
  241.  
  242.  
  243. ;************************************************************************
  244. ;*        SendIpPkt
  245. ;*
  246. ;*    Input:        DS:BX = IP description buffer ptr (saved)
  247. ;*            DS:[BX].dPktLen = IP data byte length
  248. ;*    Output:     Zero and CX = 0 if OK
  249. ;*            non-zero and CX = errorcode if error 
  250. ;*    Destroys:    AX, CX, DX, SI, DI, ES and flags
  251. ;************************************************************************
  252.  
  253. SendIpPkt    proc    near
  254.         mov    di,[bx].dPtrIp        ; calculate IP hdr length
  255.         mov    cx,[bx].dPtrUdp
  256.         sub    cx,di
  257.  
  258.         mov    dx,cs:MyIpNr        ; my IP # to IP src
  259.         mov    [di].iIpSrc,dx
  260.         mov    dx,cs:MyIpNr+2
  261.         mov    [di].iIpSrc+2,dx
  262.  
  263.         mov    ax,[bx].dPktLen
  264.         add    ax,cx            ; add hdr length to data length
  265.         mov    [bx].dPktLen,ax     ;   and save it
  266.  
  267.         xchg    ah,al
  268.         mov    [di].iIpLen,ax        ; fill in IP length
  269.  
  270.         mov    dx,cs:IpIdCounter
  271.         mov    [di].iIpId,dx        ; unique id for frag reassembly
  272.         inc    dx
  273.         mov    cs:IpIdCounter,dx
  274.  
  275.         call    IpChkSum        ; calculate checksum
  276.  
  277.         cmp    byte ptr cs:ArpBuf.iArpHtype+1,0 ; slip?
  278.         je    SendIpAndWait
  279.  
  280.         call    PutPhysDst        ; do we have HW dest addr?
  281.         jnz    SendIpRet        ; -no, ARP timed out
  282.  
  283.         call    PutPhysSrc        ; put my HW src addr
  284.  
  285.         add    [bx].dPktLen,cx     ; pkt length (HW addr part)
  286.   SendIpAndWait:
  287.         jmp    SendAndWait        ; -yes, send packet
  288.   SendIpRet:
  289.         ret
  290. SendIpPkt    endp
  291.  
  292.  
  293.  
  294. ;************************************************************************
  295. ;*        PutPhysDst
  296. ;*
  297. ;*    Input:        DS:BX = IP description buffer ptr (saved)
  298. ;*    Output:     Zero and CX = 0 if OK
  299. ;*            non-zero and CX = errorcode if error 
  300. ;*            ES = DS
  301. ;*    Destroys:    AX, CX, DX, SI, DI, ES, flags
  302. ;************************************************************************
  303.  
  304. PutPhysDst    proc    near
  305.         mov    ax,cs:DefGwyNum        ; # of default gwys we have
  306.         mov    [bx].dGwys2Chk,al    ; gwys still left to check
  307.   PutPhysAgain:
  308.         mov    ax,ds
  309.         mov    es,ax
  310.  
  311.         mov    di,[bx].dPtrIp
  312.         mov    al,[di].iIpTos        ; get type of service
  313.         xor    ah,ah
  314.         mov    si,ax
  315.  
  316.         mov    dx,[di].iIpDst        ; set dx,ax = dst IP #
  317.         mov    ax,[di].iIpDst+2
  318.  
  319.         call    ArpPutHwDst        ; do we know dst phys addr?
  320.         jz    FoundArpEntry        ; - yes, copied hw addr
  321.  
  322.         call    MyNetChk        ; - no. Is dst on my net?
  323.         jz    PutMynetArp        ;   - yes, don't use gwy
  324.                         ;       and ARP dst
  325.         call    UseGwy            ;   - no, use a gateway
  326.         jcxz    PutArp            ; destination unreachable?
  327.         jmp    short PutPhysRet
  328.  
  329.   PutMynetArp:
  330.         mov    [bx].dGwys2Chk,1
  331.   PutArp:
  332.         call    ArpPutHwDst        ; have hw addr for this IP # ?
  333.         jz    FoundArpEntry        ; - yes, copied hw addr to pkt
  334.  
  335.         call    SendArpReq        ; - no, arp for it
  336.         jz    PutPhysAgain        ; if reply, put in hw addr
  337.  
  338.         call    SwitchGwy        ;   else try next gwy
  339.  
  340.         mov    cx,SERRNOARP
  341.         dec    [bx].dGwys2Chk        ; any more default gwys?
  342.         jnz    PutPhysAgain
  343.  
  344.   PutPhysRet:
  345.         or    cx,cx
  346.   FoundArpEntry:
  347.         ret
  348. PutPhysDst    endp
  349.  
  350.  
  351.  
  352. ;************************************************************************
  353. ;*        RouteFind
  354. ;*
  355. ;*    Input:        DX = first word of dst IP # (saved if not found)
  356. ;*            AX = second word of dst IP # (saved if not found)
  357. ;*            SI = IP type of service
  358. ;*            A PushfDI must be done before calling
  359. ;*    Output:     if found: zero and DI = route table index
  360. ;*                  DX = first word of gwy IP #
  361. ;*                  AX = second word of gwy IP #
  362. ;*                  CX = net/host unreachable code
  363. ;*    Destroys:    CX, DI, ES, flags
  364. ;************************************************************************
  365.  
  366. RouteFindUtos    proc    near
  367.         assume    ds:nothing
  368.         mov    cl,[si].uIcmpIpHdr.iIpTos
  369. RouteFindCl:
  370.         xor    ch,ch
  371.         mov    si,cx
  372. RouteFind:
  373.         mov    es,cs:MySegm
  374.         mov    di,offset RouteTabIpD2
  375.         mov    cx,ROUTESLOTS
  376.   RouteFindNext:                ; look for matching slot
  377.         repne    scasw
  378.         jnz    RouteFindRet
  379.  
  380.         cmp    dx,cs:2*RouteSLOTS-2[di] ; does dst IP first part match?
  381.         jne    RouteFindNext        ; - no, look further
  382.  
  383.         cmp    si,cs:4*RouteSLOTS-2[di] ; does dst tos    match?
  384.         jne    RouteFindNext        ; - no, look further
  385.  
  386.         sub    di,offset RouteTabIpD2+2 ;- yes, compute slot index
  387.  
  388.         mov    dx,cs:RouteTabIpG1[di]    ; get gwy IP #
  389.         mov    ax,cs:RouteTabIpG2[di]    ;
  390.  
  391.         mov    cx,cs:RouteTabUnreach[di] ; get unreachable code
  392.  
  393.         cmp    di,di            ; set zero flag
  394.   RouteFindRet:
  395.         ret
  396. RouteFindUtos    endp
  397.  
  398.  
  399.  
  400. ;************************************************************************
  401. ;*        MyNetChk
  402. ;*
  403. ;*    Input:        DX = first word of IP # (saved)
  404. ;*            AX = second word of IP # (saved)
  405. ;*    Output:     zero if same net else non-zero 
  406. ;*    Destroys:    CX, flags
  407. ;************************************************************************
  408.  
  409. MyNetChk    proc    near
  410.         mov    cx,dx
  411.         and    cx,cs:MyMask        ; check if my net
  412.         cmp    cx,cs:MyNet
  413.         jne    MyNetRet
  414.         mov    cx,ax
  415.         and    cx,cs:MyMask+2
  416.         cmp    cx,cs:MyNet+2
  417.   MyNetRet:
  418.         ret
  419. MyNetChk    endp
  420.  
  421.  
  422.  
  423. ;************************************************************************
  424. ;*        UseGwy
  425. ;*
  426. ;*    Input:        DX = first word of destination IP #
  427. ;*            AX = second word of destination IP #
  428. ;*            SI = IP type of service
  429. ;*            ES:BX = IP descriptor buffer ptr (saved)
  430. ;*    Output:     DX = first word of gateway IP #
  431. ;*            AX = second part of gateway IP #
  432. ;*            CX = net/host unreachable code
  433. ;*    Destroys:    CX, SI, DI, flags
  434. ;************************************************************************
  435.  
  436. UseGwy        proc    near
  437.         assume    ds:nothing
  438.         push    ds
  439.         mov    ds,cs:MySegm
  440.         assume    ds:code_s
  441.         cli
  442.         call    RouteFind        ; is dst in route tbl?
  443.         jz    UseGwyKnown        ; - yes, have gwy IP #
  444.                         ; - no, use default gwy
  445.         dec    cx
  446.         cmp    dl,127            ; don't send to 127.x.x.x
  447.         je    UseGwyRet
  448.  
  449.         mov    di,RoutePutSlot
  450.         add    di,2            ; advance index two bytes
  451.         cmp    di,ROUTESLOTS*2     ; at end of table?
  452.         jb    UseRouteSlot
  453.  
  454.         xor    di,di            ; - yes, wrap around
  455.   UseRouteSlot:
  456.         mov    RoutePutSlot,di
  457.         mov    RouteTabIpD1[di],dx    ; put destination IP #
  458.         mov    RouteTabIpD2[di],ax
  459.         mov    RouteTabTos[di],si
  460.  
  461.         mov    si,DefGwyIndex
  462.         shl    si,1
  463.         shl    si,1
  464.         mov    dx,DefGwys[si]
  465.         mov    ax,DefGwys+2[si]
  466.         mov    RouteTabIpG1[di],dx    ;   and default gwy IP #
  467.         mov    RouteTabIpG2[di],ax    ;   into route table
  468.  
  469.         mov    cx,SavedTicks
  470.         mov    RouteTabTrRx[di],cx    ; put current time
  471.  
  472.         xor    cx,cx            ; initialize other fields
  473.         mov    RouteTabUnreach[di],cx    ;   clear unreachable
  474.         mov    RouteTabFlags[di],cx
  475.         mov    RouteTabSqDelay[di],cx
  476.  
  477.         or    si,dx
  478.         or    si,ax            ; any non-zero gwy IP #?
  479.         jz    UseGwyNone        ; - yes
  480.   UseGwyKnown:
  481. if RFCC
  482.         push    cx
  483.         push    ax
  484.         mov    cx,SavedTicks
  485.         mov    RouteTabTrTx[di],cx    ; transmit time
  486.  
  487.         mov    ax,RouteTabSqDelay[di]    ; move sq delay to descriptor
  488.         mov    es:[bx].dSqDelay,ax
  489.         dec    ax            ; any delay?
  490.         js    UseNoSqDelay
  491.         mov    ax,RouteTabTrSq[di]    ; - yes
  492.         add    ax,18            ; has one second passed
  493.         cmp    ax,cx            ;   since we last decremented
  494.         jns    UseNoSqDelay        ;   the delay value?
  495.         mov    RouteTabTrSq[di],cx
  496.         dec    RouteTabSqDelay[di]    ; - yes, one millisecond off
  497.   UseNoSqDelay:
  498.         pop    ax
  499.         pop    cx
  500. endif ; RFCC
  501.   UsegwyRet:
  502.         pop    ds
  503.         assume    ds:nothing
  504.         sti
  505.         ret
  506.  
  507.   UseGwyNone:
  508.         assume    ds:code_s
  509.         mov    dx,offset NoGwyMsg    ; - no, print error msg in dx
  510.         mov    al,08            ; error code 8
  511.         call    PrTerminate
  512.         assume    ds:nothing
  513. UseGwy        endp
  514.  
  515.  
  516.  
  517. ;************************************************************************
  518. ;*        SwitchGwy
  519. ;*
  520. ;*    Input:        DX = first word of gateway IP # (saved)
  521. ;*            AX = second word of gateway IP # (saved)
  522. ;*    Destroys:    CX, DI, ES, flags
  523. ;************************************************************************
  524.  
  525. SwitchGwy    proc    near
  526.         push    ds
  527.         mov    ds,cs:MySegm
  528.         assume    ds:code_s
  529.         mov    es,MySegm
  530.         PushfDI
  531.         mov    di,DefGwyIndex        ; if current default gateway
  532.         shl    di,1
  533.         shl    di,1
  534.  
  535.         cmp    dx,DefGwys[di]        ;   is the one
  536.         jne    SwitchNotThis
  537.         cmp    ax,DefGwys+2[di]    ;   that failed
  538.         jne    SwitchNotThis
  539.  
  540.         shr    di,1
  541.         shr    di,1
  542.         inc    di            ;   then switch to
  543.         cmp    di,DefGwyNum
  544.         jb    SwitchNextGwy
  545.         xor    di,di
  546.   SwitchNextGwy:
  547.         mov    DefGwyIndex,di        ;   next default gateway
  548.   SwitchNotThis:
  549.         PopfEI
  550.  
  551.         mov    di,offset RouteTabIpG2    ; remove failing gateway
  552.         mov    cx,ROUTESLOTS        ;   from all route slots
  553.         PushfDI
  554.   SwitchRouteNext:                ; look for matching slot
  555.         repne    scasw
  556.         jnz    SwitchGwyRet        ; all entries searched
  557.  
  558.         cmp    dx,2*ROUTESLOTS-2[di]    ; does gwy IP 2nd part match?
  559.         jne    SwitchRouteNext     ; - no, look further
  560.  
  561.         sub    di,offset RouteTabIpG2+2 ;- yes, clear this route
  562.         mov    RouteTabIpD1[di],0
  563.         mov    RouteTabIpD2[di],0
  564.         mov    RouteTabIpG1[di],0
  565.         mov    RouteTabIpG2[di],0
  566.         add    di,offset RouteTabIpG2+2
  567.         jmp    short SwitchRouteNext    ; more routes using this gwy?
  568.  
  569.   SwitchGwyRet:
  570.         PopfEI
  571.         pop    ds
  572.         assume    ds:nothing
  573.         ret
  574. SwitchGwy    endp
  575.  
  576.  
  577.  
  578. ;************************************************************************
  579. ;*        ChkSum
  580. ;*    Input:        DS:SI = start addr
  581. ;*            CX = # of bytes (at least 6)
  582. ;*    Output:     AX = 1-complement checksum
  583. ;*            DS:SI = addr of next byte
  584. ;*    Destroys:    SI, Flags
  585. ;************************************************************************
  586.  
  587. ChkSum        proc    near
  588. if PINGCLIENT
  589.         test    cs:GenFlags,IS_A_386
  590.         jz    ChkSum8086
  591.  
  592.         .386
  593.         push    edx            ; save 386 registers
  594.         push    eax
  595.         xor    edx,edx            ; clear edx
  596.         .8086
  597.         shr    cx,1            ; divide by two, round down
  598.         pushf                ; keep odd bit in carry
  599.  
  600.         test    si,2            ; double-word aligned?
  601.         jz    ChkAligned
  602.         lodsw
  603.         mov    dx,ax
  604.         dec    cx
  605.   ChkAligned:
  606.         shr    cx,1            ; divide by two, round down
  607.         pushf                ; keep odd bit in carry
  608.  
  609.         shr    cx,1            ; divide by two, round down
  610.         jnc    ChkLoop386
  611.         .386
  612.         lodsd                ; process 4 bytes
  613.         add    edx,eax
  614.         jcxz    ChkLoopEnd
  615.   ChkLoop386:
  616.         lodsd                ; process n*8 bytes
  617.         adc    edx,eax
  618.         lodsd
  619.         adc    edx,eax
  620.         loopw    ChkLoop386
  621.   ChkLoopEnd:
  622.         adc    edx,0            ; add the last carry in again
  623.  
  624.         mov    eax,edx            ; add double word parts
  625.         shr    eax,16
  626.         .8086
  627.         add    dx,ax
  628.         adc    dx,0
  629.  
  630.         popf                ; odd # of words?
  631.         jnc    NotOddWords
  632.  
  633.         lodsw
  634.         add    dx,ax
  635.         adc    dx,0
  636.   NotOddWords:
  637.         popf                ; odd # of bytes?
  638.         jnc    NotOddBytes
  639.  
  640.         lodsb                ; get that last byte
  641.         xor    ah,ah            ; clear carry and the high portion
  642.         add    dx,ax            ; add the last one in
  643.         adc    dx,0            ; add the carry in, too
  644.   NotOddBytes:
  645.         .386
  646.         pop    eax            ; restore saved regs
  647.         mov    ax,dx
  648.         pop    edx
  649.  
  650.         not    ax            ; take one more 1-complement
  651.         ret
  652.  
  653.         .8086
  654. endif ; PINGCLIENT
  655.  
  656.   ChkSum8086:
  657.         push    dx
  658.         shr    cx,1            ; divide by two, round down
  659.         pushf                ; keep odd bit in carry
  660.         xor    dx,dx            ; clear dx and carry
  661.  
  662.         shr    cx,1            ; divide by two, round down
  663.         jnc    ChkLoop
  664.         lodsw                ; process odd word
  665.         add    dx,ax
  666.   ChkLoop:
  667.         lodsw                ; process even # of words
  668.         adc    dx,ax
  669.         lodsw
  670.         adc    dx,ax
  671.         loop    ChkLoop
  672.  
  673.         adc    dx,0            ; add the last carry in again
  674.  
  675.         popf                ; odd # of bytes?
  676.         jnc    NotOdd
  677.  
  678.         lodsb                ; get that last byte
  679.         xor    ah,ah            ; clear carry and the high portion
  680.         add    dx,ax            ; add the last one in
  681.         adc    dx,0            ; add the carry in, too
  682.   NotOdd:
  683.         mov    ax,dx            ; restore saved regs
  684.         pop    dx
  685.  
  686.         not    ax            ; take one more 1-complement
  687.         ret
  688. ChkSum        endp
  689.  
  690.  
  691.  
  692. ;************************************************************************
  693. ;*        UdpChkSum (both for generate and check!)
  694. ;*
  695. ;*    Input:        DS:BX = IP description buffer ptr (saved)
  696. ;*            DS:DI = IP ptr
  697. ;*            DS:SI = UDP ptr
  698. ;*    Output:     Zero if OK; checksum filled in
  699. ;*            DS:SI = addr of next byte
  700. ;*            DS:DI = IP Ptr
  701. ;*    Destroys:    AX, CX, DX, SI, flags
  702. ;************************************************************************
  703.  
  704. UdpChkSum    proc    near
  705.         xchg    di,si
  706.  
  707.         xor    dx,dx
  708.         push    word ptr [si].iIpTtl    ; save ttl for pseudo hdr
  709.         mov    [si].iIpTtl,dl        ;   usage
  710.  
  711.         xchg    dx,[di].uUdpXsum    ; save and clear checksum
  712.  
  713.                 push    [si].iIpXsum            ; save IP chksum for ps-hdr use
  714.         mov    cx,[di].uUdpLen     ; put UDP length into ps-hdr
  715.         mov    [si].iIpXsum,cx
  716.         xchg    ch,cl
  717.  
  718.         mov    ax,di
  719.         add    ax,cx
  720.         or    dx,dx            ; is there a checksum?
  721.         mov    si,ax            ; - no, not available/wanted
  722.         jz    UdpNoSum        ;   but set si to end of data
  723.  
  724.         push    cx            ; - yes
  725.         mov    cx,12            ; checksum pseudo hdr
  726.         mov    si,[bx].dPtrIp
  727.         add    si,iIpTtl
  728.         call    ChkSum
  729.  
  730.         not    ax            ; move partial checksum
  731.         mov    [di].uUdpXsum,ax    ;   into udp hdr
  732.         pop    cx            ; checksum udp hdr+data
  733.         mov    si,di
  734.         call    ChkSum
  735.         jnz    UdpNotZero        ; checksum is zero?
  736.         not    ax            ; - yes, make it FFFFh
  737.   UdpNotZero:
  738.         mov    [di].uUdpXsum,ax
  739.  
  740.         cmp    ax,dx            ; does checksums match?
  741.   UdpNoSum:
  742.         mov    di,[bx].dPtrIp
  743.                 pop     [di].iIpXsum            ; restore IP chksum
  744.         pop    word ptr [di].iIpTtl    ; restore ttl
  745.  
  746.         ret
  747. UdpChkSum    endp
  748.  
  749.  
  750.  
  751. ;************************************************************************
  752. ;*        IpChkSum (both for generate and check!)
  753. ;*
  754. ;*    Input:        DS:BX = IP description buffer ptr (saved)
  755. ;*            DS:DI = IpPtr
  756. ;*            CX = IP hdr length
  757. ;*    Output:     Zero if OK; checksum filled in
  758. ;*    Destroys:    AX, CX, DX, SI, flags
  759. ;************************************************************************
  760.  
  761. IpChkSum    proc    near
  762.         mov    si,di
  763.         xor    dx,dx
  764.         xchg    dx,[di].iIpXsum     ; save and clear checksum
  765.  
  766.         call    ChkSum            ; calculate new checksum
  767.         mov    [di].iIpXsum,ax
  768.  
  769.         cmp    ax,dx            ; does checksums match?
  770.         ret
  771. IpChkSum    endp
  772.  
  773.  
  774.  
  775. ;************************************************************************
  776. ;*        IcmpChkSum (both for generate and check!)
  777. ;*
  778. ;*    Input:        DS:BX = IP description buffer ptr (saved)
  779. ;*    Output:     Zero if OK; checksum filled in
  780. ;*            DI = dPtrUdp
  781. ;*    Destroys:    AX, CX, DX, SI, DI, flags
  782. ;************************************************************************
  783.  
  784. IcmpChkSum    proc    near
  785.         mov    cx,[bx].dPktlen
  786.         mov    si,[bx].dPtrUdp
  787. IcmpChkSum2:
  788.         mov    di,si
  789.         xor    dx,dx
  790.         xchg    dx,[di].uIcmpXsum    ; save and clear checksum
  791.  
  792.         call    ChkSum            ; calculate new checksum
  793.         mov    [di].uIcmpXsum,ax
  794.  
  795.         cmp    ax,dx            ; does checksums match?
  796.         ret
  797. IcmpChkSum    endp
  798.  
  799.  
  800.  
  801. ;************************************************************************
  802. ;*        Ageing of ARP and Route tables
  803. ;*
  804. ;*    Destroys:    AX, BX, CX, DX, SI, DI, ES, flags
  805. ;************************************************************************
  806.  
  807. Ageing        proc    near
  808.         assume    ds:code_s
  809.         call    CurrentTicks        ; get current ticks value
  810. if RFCC
  811.         cmp    cx,AgeNext        ; time to do route/arp ageing?
  812.         jns    AgeNow
  813.  
  814.         cmp    cx,AgeFragsNext        ; time to age frags yet?
  815.         jns    AgeFrags
  816. endif ; RFCC
  817.         ret
  818.  
  819.  
  820. if RFCC
  821.  
  822. AgeFrags:
  823.         mov    dx,cx
  824.         add    cx,5*18+1         ; check next in 5 seconds
  825.         mov    AgeFragsNext,cx
  826.  
  827.         push    ds
  828.         cli
  829.         mov    cx,Fraglist.lBufsAvail
  830.   AgeLook4Buf:
  831.         mov    di,offset FragList
  832.         call    GetFromList
  833.         assume    ds:nothing
  834.         jz    AgeNoMoreFrags        ; any reassembly buffers?
  835.  
  836.         mov    si,offset FragList
  837.         cmp    dx,[bx].dTickTimeout    ; too old?
  838.         js    AgePutBack        ; - no, put it back
  839.                 
  840.         call    BufRelease        ; - yes, release it
  841.         SHOW_EVENT    'Q'
  842.         jmp    short AgeNextBuf
  843.   AgePutBack:
  844.         call    AddToList            
  845.   AgeNextBuf:
  846.         dec    cl
  847.         jnz    AgeLook4Buf        ; any more reassembly bufs?
  848.   AgeNoMoreFrags:
  849.         sti
  850.         pop    ds
  851.         ret
  852.  
  853.  
  854.   AgeNow:
  855.         assume    ds:code_s
  856.         mov    di,cx
  857.         mov    dx,cx
  858.         add    cx,2*18         ; chk next 2 seconds from now
  859.         mov    AgeNext,cx
  860.  
  861.         sub    dx,70*18        ; clear what is older than 1 min
  862.  
  863.         mov    cx,ARPSLOTS-3
  864.         mov    si,offset ArpTabTr+6
  865.         cli
  866.   AgeArpLoop:
  867.         and    word ptr [si+2*ARPSLOTS],not SQ_UPDATED ; clr every 2 s
  868.  
  869.         lodsw
  870.         cmp    ax,dx
  871.         jns    AgeArpYoung        ; not touched in a minute?
  872.  
  873.         push    si
  874.         sub    si,offset ArpTabTr+2
  875.         push    cx
  876.         push    di
  877.         push    dx
  878.         mov    dx,ArpTabIp1[si]
  879.         mov    ax,ArpTabIp2[si]
  880.         call    SwitchGwy        ; in case it's a gwy: switch
  881.         pop    dx
  882.         pop    di
  883.         pop    cx
  884.  
  885.         xor    ax,ax
  886.         mov    ArpTabTr[si],di     ; set current time
  887. if DEBUG ge 2
  888.         cmp    ArpTabIp1[si],ax
  889.         je    AgeUnused
  890.         SHOW_EVENT    'T'
  891.   AgeUnused:
  892. endif ; DEBUG ge 2
  893.         mov    ArpTabIp1[si],ax    ; clear old entries
  894.         mov    ArpTabIp2[si],ax
  895.         shl    si,1
  896.         shl    si,1
  897.         shl    si,1
  898.         mov    word ptr ArpTabHwAdr[si],ax
  899.         mov    word ptr ArpTabHwAdr[si+2],ax
  900.         mov    word ptr ArpTabHwAdr[si+4],ax
  901.         pop    si
  902.   AgeArpYoung:
  903.         loop    AgeArpLoop
  904.         sti
  905.  
  906.         add    dx,10*18        ; need to age RoutTab sooner
  907.         mov    cx,ROUTESLOTS        ;   than ArpTab
  908.         mov    si,offset RouteTabTrRx
  909.         cli
  910.   AgeRouteLoop:
  911.         and    word ptr [si+2*ROUTESLOTS],not SQ_UPDATED ; clr every 2 s
  912.  
  913.         lodsw
  914.         cmp    ax,dx            ; old slot?
  915.         jns    AgeRouteYoung
  916.  
  917.         sub    si,offset RouteTabTrRx+2
  918.         mov    RouteTabTrRx[si],di
  919.         xor    ax,ax
  920.         cmp    RouteTabUnreach[si],ax    ; any error code?
  921.         jne    AgeRouteUnr
  922.  
  923.         cmp    dx,RouteTabTrTx[si]    ; - no. Sent anything lately?
  924.         jns    AgeRouteEnd        ;    - no, that's why
  925.  
  926.         mov    RouteTabUnreach[si],SERRNOTRAF ;- yes, somebody is dead
  927.         jmp    short AgeRouteEnd
  928.   AgeRouteUnr:                    ; - yes, remove slot
  929.         mov    RouteTabIpD1[si],ax
  930.         mov    RouteTabIpD2[si],ax
  931.         mov    RouteTabIpG1[si],ax
  932.         mov    RouteTabIpG2[si],ax
  933.   AgeRouteEnd:
  934.         add    si,offset RouteTabTrRx+2
  935.   AgeRouteYoung:
  936.         loop    AgeRouteLoop
  937.  
  938.         sti
  939.         ret
  940. endif ; RFCC
  941. Ageing        endp
  942.  
  943.  
  944.  
  945. if RFCC
  946. ;************************************************************************
  947. ;*        VerifyIpHdr (RFC1122 requirements)
  948. ;*
  949. ;* verify IP dst = me (or bcast), process IP options, verify IPver=4,
  950. ;* verify IP src not bcast, set timer value in ArpTab and RouteTab.
  951. ;* Process IP fragments.
  952. ;************************************************************************
  953.  
  954. holeStruc    struc
  955. holeNext    dw    0
  956. holeFirst    dw    0
  957. holeLast    dw    0
  958. holeStruc    ends
  959. HOLEDESCRLEN    equ    SIZE holeStruc
  960.  
  961. k18        db    18
  962.  
  963. VerifyIpHdr    proc    near
  964.         assume    ds:nothing
  965.         mov    al,[di].iIpVerHlen
  966.         and    al,0f0h
  967.         cmp    al,040h         ; IP version 4?
  968.         jne    VerifyErr1
  969.  
  970.         mov    ax,[bx].dPtrPhys
  971.         call    ArpFindHw        ; find Hw Dst arp index
  972.         mov    [bx].dIdxHwDst,di    ;   0 = bcast, 4 = me
  973.  
  974.         cmp    di,ARPMYIDX        ; is Hw addr to me or bcast?
  975.         ja    VerifyErr1
  976.  
  977.         mov    ax,[bx].dPtrPhys
  978.         call    ArpFindHwHl        ; is Hw Src in arp table?
  979.         jz    VerifyChkBcast        ; - yes
  980.  
  981.         cmp    [bx].dIdxHwDst,ARPMYIDX    ; - no. Addressed to me?
  982.         jne    VerifyIpDst        ; 
  983.  
  984.         mov    di,[bx].dPtrIp        ; - yes
  985.         mov    dx,[di].iIpSrc
  986.         mov    ax,[di].iIpSrc+2
  987.  
  988.         call    MyNetChk        ; if he is on my net
  989.         jnz    VerifyIpDst
  990.  
  991.         call    ArpPutNewSiHl        ;   add him to arp table
  992.         jmp    short VerifyIpDst
  993.  
  994.   VerifyChkIp:
  995.         cmp    cs:MyIpNr,0        ; do I know who I am?
  996.         je    VerifyIpUnknown
  997.   VerifyErr1:
  998.         jmp    short VerifyErr
  999.  
  1000.   VerifyChkBcast:
  1001.         cmp    di,ARPMYIDX        ; from me or broadcast?
  1002.         jbe    VerifyErr        ; - yes, ignore packet
  1003.  
  1004.         mov    cx,cs:SavedTicks    ; get current ticks value
  1005.         mov    cs:ArpTabTr[di],cx
  1006.   VerifyIpDst:
  1007.         mov    si,[bx].dPtrIp
  1008.         mov    dx,[si].iIpDst        ; check IP dst
  1009.         mov    ax,[si].iIpDst+2
  1010.         call    ArpFindIp
  1011.         mov    [bx].dIdxIpDst,di
  1012.         cmp    di,ARPMYIDX        ; is it to me or broadcast?
  1013.         ja    VerifyChkIp        ; - no, ignore packet
  1014.   VerifyIpUnknown:
  1015.         mov    dx,[si].iIpSrc
  1016.         mov    ax,[si].iIpSrc+2
  1017.         call    ArpFindIp        ; check IP src addr
  1018.         jnz    VerifyNoArp
  1019.  
  1020.         cmp    di,ARPMYIDX        ; from IP broadcast?
  1021.         jb    VerifyErr        ; -yes, ignore packet
  1022.   VerifyOK:
  1023.         mov    di,[bx].dPtrIp
  1024.         test    [di].iIpFlFrag,0ff3fh    ; is this a fragment?
  1025.         jnz    VerifyFrag
  1026.         clc                ; - no, use as is
  1027.   VerifyRet:
  1028.         mov    si,[bx].dPtrUdp
  1029.         ret
  1030.  
  1031.   VerifyNoArp:
  1032.         mov    cl,[si].iIpTos
  1033.         call    RouteFindCl        ; is he in route table?
  1034.         jnz    VerifyNoRoute
  1035.  
  1036.         mov    cx,cs:SavedTicks
  1037.         mov    cs:RouteTabTrRx[di],cx    ; note we've got pkts from him
  1038.   VerifyNoRoute:
  1039.         jmp    short VerifyOK
  1040.  
  1041.   FragAddAndErr:
  1042.         SHOW_EVENT    'Y'
  1043.         mov    si,offset FragList
  1044.         push    es
  1045.         call    AddToList
  1046.         pop    es
  1047.   VerifyFragErr:
  1048.         mov    bx,bp
  1049.         push    es
  1050.         pop    ds
  1051.   VerifyErr:
  1052.         call    BufRelease
  1053.   VerifyKeep:
  1054.         stc
  1055.         mov    di,[bx].dPtrIp
  1056.         jmp    short VerifyRet
  1057.  
  1058.  
  1059.   VerifyFrag:        ; RFC 815 fragment reassembly:
  1060.         SHOW_EVENT    'R'
  1061.         mov    bp,bx            ; addr of fragment buffer
  1062.         push    ds
  1063.         pop    es
  1064.         mov    dx,[di].iIpSrc        ; get IP # / IP id / IP prot
  1065.         mov    ax,[di].iIpSrc+2
  1066.         mov    si,[di].iIpId
  1067.         mov    cx,cs:Fraglist.lBufsAvail
  1068.         mov    ch,[di].iIpProt
  1069.   FragLook4Buf:
  1070.         mov    di,offset FragList
  1071.         push    es
  1072.         push    si
  1073.         call    GetFromList
  1074.         pop    si
  1075.         pop    es
  1076.         jz    FragEarliest        ; any reassembly buffers?
  1077.  
  1078.         SHOW_EVENT    'S'
  1079.         mov    di,[bx].dPtrIp        ; match IP#/Id/Prot
  1080.         cmp    dx,[di].iIpSrc
  1081.         jne    FragNextBuf
  1082.         cmp    ax,[di].iIpSrc+2
  1083.         jne    FragNextBuf
  1084.         cmp    si,[di].iIpId
  1085.         jne    FragNextBuf
  1086.         cmp    ch,[di].iIpProt
  1087.         je    FragBufFound
  1088.   FragNextBuf:
  1089.         push    si            ; irrelevant buf, put it back
  1090.         mov    si,offset FragList
  1091.         push    es
  1092.         call    AddToList
  1093.         pop    es
  1094.         pop    si
  1095.         dec    cl
  1096.         jnz    FragLook4Buf
  1097.   FragEarliest:
  1098.         call    FragFirstLast        ; compute addr of fragment
  1099.         ja    VerifyFragErr        ; too big pkt?
  1100.         or    ax,ax            ; first part earliest?
  1101.         jnz    FragOffset
  1102.  
  1103.         SHOW_EVENT    'U'
  1104.         mov    bx,bp            
  1105.         push    es
  1106.         pop    ds
  1107.         mov    di,[bx].dPtrUdp
  1108.         add    di,dx
  1109.         cmp    [bx].dHomeList,offset FreeBufs ;   and a big buffer?
  1110.         je    FragFirstHole        ; - yes, no extra buffer needed
  1111.   FragOffset:
  1112.         SHOW_EVENT    'V'
  1113.         push    es
  1114.         call    BufAlloc        ; - no, create empty buffer
  1115.         pop    es
  1116.         jz    VerifyFragErr
  1117.  
  1118.         add    di,HWHDRLEN    ;*test
  1119.         mov    [bx].dPtrIp,di
  1120.  
  1121.         mov    si,es:[bp].dPtrIP
  1122.         mov    cx,es:[bp].dPtrUdp     ; copy IP header
  1123.         sub    cx,si
  1124.         call    MovesbEsToDs
  1125.         mov    [bx].dPtrUdp,di
  1126.   FragFirstHole:
  1127.         mov    [di].holeNext,0     ; create first hole descriptor
  1128.         mov    [di].holeFirst,0
  1129.                 mov     ax,cs:MyGiant
  1130.                 mov     [di].holeLast,ax
  1131.         mov    [bx].dPtrFrag,di
  1132.  
  1133.         add    di,HOLEDESCRLEN     ; mark end of info
  1134.         mov    [bx].dPktEnd,di
  1135.   FragBufFound:
  1136.         call    FragFirstLast        ; compute addr of fragment
  1137.         jbe    $+5
  1138.         jmp    FragAddAndErr        ; too big pkt?
  1139.  
  1140.         lea    di,[bx].dPtrFrag
  1141.   FragNextHole:                 ; 1. select next hole descr
  1142.         mov    si,di
  1143.         mov    di,[si].holeNext
  1144.         or    di,di            ;    any more descriptors?
  1145.         jz    FragEndHoles
  1146.  
  1147.         cmp    ax,[di].holeLast    ; 2. frag.first > hole.last?
  1148.         jae    FragNextHole
  1149.  
  1150.         cmp    dx,[di].holeFirst    ; 3. frag.last < hole.first?
  1151.         jbe    FragNextHole
  1152.  
  1153.         mov    cx,[di].holeNext    ; 4. delete current hole descr
  1154.         mov    [si].holeNext,cx
  1155.  
  1156.         mov    cx,[di].holeLast
  1157.         cmp    ax,[di].holeFirst    ; 5. frag.first > hole.first?
  1158.         jbe    FragNoNew1
  1159.         mov    [si].holeNext,di    ;    create new hole descr
  1160.         mov    [di].holeLast,ax
  1161.   FragNoNew1:
  1162.         mov    si,es:[bp].dPtrIp    ; 6. if frag.more
  1163.         test    es:[si].iIpFlFrag,0020h
  1164.         jz    FragLastFrag
  1165.  
  1166.         cmp    dx,cx            ;    and frag.last < hole.last?
  1167.         jae    FragNextHole
  1168.  
  1169.         mov    si,[bx].dPtrUdp
  1170.         add    si,dx
  1171.         mov    [si].holeFirst,dx    ;    create new hole descr
  1172.         mov    [si].holeLast,cx
  1173.         mov    cx,[bx].dPtrFrag
  1174.         mov    [si].holeNext,cx
  1175.         mov    [bx].dPtrFrag,si
  1176.  
  1177.         add    si,HOLEDESCRLEN
  1178.         cmp    si,[bx].dPktEnd
  1179.         jbe    FragNextHole
  1180.   FragPktEnd:
  1181.         mov    [bx].dPktEnd,si
  1182.         jmp    short FragNextHole
  1183.  
  1184.   FragLastFrag:                 ; when last frag
  1185.         mov    si,[bx].dPtrUdp     ;   prepare IP length
  1186.         add    si,dx
  1187.         jmp    short FragPktEnd
  1188.  
  1189.   FragEndHoles:                 ; 8. copy data to assembly buf
  1190.         cmp    bx,bp            ; do we need to copy?
  1191.         jne    FragDoCopy
  1192.         mov    cx,es
  1193.         mov    si,ds
  1194.         cmp    cx,si
  1195.         je    FragTimeUpd
  1196.   FragDoCopy:
  1197.         SHOW_EVENT    'W'
  1198.         or    ax,ax            ; if first frag
  1199.         jnz    FragNotFirst
  1200.  
  1201.         SHOW_EVENT    'X'
  1202.         mov    si,[bx].dPtrUdp     ;   retain this IP header
  1203.         mov    di,es:[bp].dPtrUdp     ;   and copy assembled data
  1204.         mov    cx,[bx].dPktEnd     ;   to frag buffer
  1205.         sub    cx,si
  1206.         add    si,dx            ;   skip over first fragment
  1207.         add    di,dx
  1208.         sub    cx,dx
  1209.         call    Movesb
  1210.         mov    es:[bp].dPktEnd,di
  1211.  
  1212.         mov    cx,[bx].dPtrFrag
  1213.         mov    es:[bp].dPtrFrag,cx
  1214.  
  1215.         xchg    bx,bp            ;   and switch buffers
  1216.         push    ds
  1217.         push    es
  1218.         pop    ds
  1219.         pop    es
  1220.  
  1221.         mov    cx,di
  1222.         sub    cx,si            ;   hole ptr adjustment
  1223.         lea    di,[bx].dPtrFrag
  1224.   FragUpdLoop:
  1225.         mov    si,di
  1226.         mov    di,[si].holeNext
  1227.         or    di,di
  1228.         jz    FragRelBuf        ;   end of hole list 
  1229.  
  1230.         add    di,cx
  1231.         mov    [si].holeNext,di    ;   new pointer address
  1232.         jmp    short FragUpdLoop
  1233.  
  1234.   FragNotFirst:
  1235.         mov    si,es:[bp].dPtrUdp     ; copy this frag to asm buf
  1236.         mov    cx,dx
  1237.         sub    cx,ax
  1238.         mov    di,[bx].dPtrUdp
  1239.         add    di,ax
  1240.         call    MovesbEsToDs
  1241.   FragRelBuf:
  1242.         push    bx            ; release frag buf
  1243.         push    ds
  1244.         mov    bx,bp
  1245.         push    es
  1246.         pop    ds
  1247.         call    BufRelease
  1248.         pop    ds
  1249.         pop    bx
  1250.   FragTimeUpd:
  1251.         push    ds
  1252.         pop    es
  1253.         mov    cx,cs:SavedTicks    ; update timer entry
  1254.         mov    di,[bx].dPtrIp
  1255.         mov    al,[di].iIpTtl
  1256.         mul    cs:k18
  1257.         add    cx,ax
  1258.         mov    [bx].dTickTimeout,cx
  1259.  
  1260.         mov    di,[bx].dPtrIp
  1261.         mov    si,[bx].dPtrUdp
  1262.         cmp    [bx].dPtrFrag,0     ; any holes?
  1263.         jne    FragKeep        ; - yes, wait for more pkts
  1264.  
  1265.         mov    cx,[bx].dPktEnd     ; - no
  1266.         mov    ax,cx            ; compute IP length
  1267.         sub    cx,[bx].dPtrIp
  1268.         xchg    ch,cl
  1269.         mov    [di].iIpLen,cx
  1270.         ret
  1271.  
  1272.   FragKeep:
  1273.         mov    cx,cs:FreeBufs.lBufsAvail
  1274.         cmp    cx,NBUFS/4        ; prevent starving
  1275.         jge    FragKeep2
  1276.         jmp    VerifyErr
  1277.   FragKeep2:
  1278.         mov    si,offset FragList    ; keep buf a while
  1279.         call    AddToList
  1280.         jmp    VerifyKeep
  1281. VerifyIpHdr    endp
  1282.  
  1283.  
  1284.  
  1285. ;************************************************************************
  1286. ;*        FragFirstLast
  1287. ;************************************************************************
  1288.  
  1289. FragFirstLast    proc    near
  1290.         mov    di,es:[bp].dPtrIp        ; compute frag.first
  1291.         mov    ax,es:[di].iIpFlFrag
  1292.         xchg    ah,al
  1293.         and    ax,1fffh
  1294.         shl    ax,1
  1295.         shl    ax,1
  1296.         shl    ax,1
  1297.         mov    dx,es:[di].iIpLen        ; compute frag.last (+1)
  1298.         xchg    dh,dl
  1299.         add    dx,es:[bp].dPtrIp
  1300.         sub    dx,es:[bp].dPtrUdp
  1301.         add    dx,ax
  1302.         cmp    dx,GIANTTR-IPHDRLEN-HWHDRLEN ; fits in buffer?
  1303.         ret    ;*test GIANT
  1304. FragFirstLast    endp
  1305.  
  1306. endif ; RFCC
  1307.  
  1308.  
  1309.  
  1310. ;************************************************************************
  1311. ;*        SwitchIpDst
  1312. ;************************************************************************
  1313.  
  1314. GetIpSrc    proc    near
  1315.         mov    si,[bx].dPtrIp        ; get his IP #
  1316.         mov    dx,[si].iIpSrc
  1317.         mov    ax,[si].iIpSrc+2
  1318.         ret
  1319. GetIpSrc    endp
  1320.  
  1321.  
  1322. SwitchIpDst    proc    near            ; mov his IP # to IP dst
  1323.         call    GetIpSrc
  1324. SetIpDst:
  1325.         mov    di,[bx].dPtrIp
  1326.         mov    [di].iIpDst,dx        ; set IP dst
  1327.         mov    [di].iIpDst+2,ax
  1328.         ret
  1329. SwitchIpDst    endp
  1330.  
  1331.  
  1332.  
  1333. ;************************************************************************
  1334. ;*        MakeMynet
  1335. ;************************************************************************
  1336.  
  1337. MakeMynet    proc    near
  1338.         assume    ds:code_s
  1339.         mov    dx,MyIpNr
  1340.         mov    ax,MyIpNr+2
  1341.  
  1342.         mov    ArpTabIp1+ARPMYIDX,dx    ; third arp slot = me
  1343.         mov    ArpTabIp2+ARPMYIDX,ax
  1344.  
  1345.         mov    si,MyMask
  1346.         mov    di,MyMask+2
  1347.         and    dx,si            ; calculate network #
  1348.         and    ax,di
  1349.         mov    MyNet,dx
  1350.         mov    MyNet+2,ax
  1351.  
  1352.         not    si            ; second arp slot =
  1353.         not    di            ;   subnet broadcast
  1354.         or    dx,si
  1355.         or    ax,di
  1356.         mov    ArpTabIp1+2,dx
  1357.         mov    ArpTabIp2+2,ax
  1358.         ret
  1359. MakeMynet    endp
  1360.  
  1361.  
  1362.  
  1363. ;************************************************************************
  1364. ;*        ValidateIpNr
  1365. ;************************************************************************
  1366.  
  1367. ValidateIpNr    proc    near
  1368.         push    es
  1369.         assume    ds:code_s
  1370.         mov    dx,MyIpNr
  1371.         mov    ax,MyIpNr+2
  1372.         push    ds
  1373.         call    BufAlloc
  1374.         assume    ds:nothing
  1375.         mov    [bx].dTimOutMsg,0    ; we SHOULD get no answer
  1376.         mov    [bx].dTickTimeout,10    ; give them half a second
  1377.         call    SendArpReq        ; send arp to our Ip #
  1378.         call    BufRelease
  1379.         pop    ds
  1380.         assume    ds:code_s
  1381.         pop    es
  1382.         jz    ValConflict        ; someone else has our IP # ?
  1383.  
  1384.         ret                ; - no, return
  1385.  
  1386.   ValConflict:                    ; - yes, error termination
  1387.         call    ArpFindIp
  1388.         mov    cl,3
  1389.         shl    di,cl
  1390.         lea    si,ArpTabHwAdr[di]    ; get HW addr of arp reply
  1391.  
  1392.         mov    di,offset OccupiedHw
  1393.         call    PutHwNum        ; put offending HW addr
  1394.  
  1395.         mov    dx,offset OccupiedMsg    ; display IP occupied msg
  1396.         mov    al,09            ; error code 9
  1397.         call    PrTerminate
  1398. ValidateIpNr    endp
  1399.  
  1400.  
  1401.  
  1402. ;************************************************************************
  1403. ;*        DoBootpPkt
  1404. ;************************************************************************
  1405.  
  1406. DoBootpPkt    proc    near
  1407.         assume    ds:code_s
  1408.         push    ds
  1409.         call    BufAlloc        ; get a buffer
  1410.         call    MakeSendDescr
  1411.  
  1412.         push    di            ; preclear udp hdr and data
  1413.         xor    ax,ax
  1414.         mov    cx,(BPDATALEN+ICMPHDRLEN)/2
  1415.         rep    stosw
  1416.         pop    di
  1417.  
  1418.         mov    [di].uUdpSrc,4400h    ; udp hdr info
  1419.         mov    [di].uUdpDst,4300h
  1420.  
  1421.         mov    [di].uBotOp,1        ; bootp info
  1422.         mov    al,byte ptr ArpBuf.iArpHtype+1
  1423.         mov    [di].uBotHtype,al    ;   put my HW type
  1424.         mov    [di].uBotMagNum,8263h
  1425.         mov    [di].uBotMagNum+2,6353h
  1426.         mov    ax,BootpXid
  1427.         mov    [di].uBotXid,ax
  1428.  
  1429.         mov    cx,Hlen
  1430.         mov    [di].uBotHlen,cl
  1431.         mov    si,offset MyHwAd
  1432.         lea    di,[di].uBotCliHwAd
  1433.         rep    movsb            ;   copy my HW addr
  1434.  
  1435.         xor    ax,ax            ; IP hdr info
  1436.         mov    si,[bx].dPtrIp
  1437.         dec    ax
  1438.         mov    [si].iIpDst,ax
  1439.         mov    [si].iIpDst+2,ax
  1440.  
  1441.         mov    [bx].dWaitEvent,GOT_BOOTP    ; event to wait for
  1442.         mov    [bx].dTimOutMsg,offset NoBotReplyMsg ; error msg
  1443.         mov    ax,BPDATALEN+UDPHDRLEN        ; bootp pkt length
  1444.         mov    [bx].dPktLen,ax
  1445.         call    SendUdpPkt            ; send bootp request
  1446.         call    BufRelease
  1447.         push    cs
  1448.         pop    es
  1449.         pop    ds
  1450.         ret
  1451. DoBootpPkt    endp
  1452.  
  1453.  
  1454.  
  1455. ;************************************************************************
  1456. ;*        InterpBootp according to RFC 1084 and RFC1048
  1457. ;************************************************************************
  1458.  
  1459. InterpBootp    proc    near
  1460.         assume    ds:code_s
  1461.         or    Flagword,HAVE_MYIPNR    ; note what we've got
  1462.  
  1463.         push    es
  1464.         push    ds
  1465.         lds    bx,AdrBootpReply
  1466.         assume    ds:nothing
  1467.  
  1468.         mov    di,[bx].dPtrUdp
  1469.         mov    dx,[di].uBotYourIp    ; save my IP #
  1470.         mov    cs:MyIpNr,dx
  1471.         mov    ax,[di].uBotYourIp+2
  1472.         mov    cs:MyIpNr+2,ax
  1473.  
  1474.         cmp    word ptr [di].uBotMagNum,8263h    ; RFC 1084 type of
  1475.         jne    VendEnd             ;   vendor area?
  1476.         cmp    word ptr [di].uBotMagNum+2,6353h
  1477.         jne    VendEnd
  1478.  
  1479.         lea    si,[di].uBotVend    ; start of "vendor area"
  1480.         lea    bp,[si]+64-4        ; end of "vendor area"
  1481.         push    cs
  1482.         pop    es
  1483.   VendLoop:
  1484.         cmp    si,bp            ; beyond vendor area?
  1485.         jb    VendNext
  1486.  
  1487.   VendEnd:
  1488.         call    BufRelease        ; release bootp reply buf
  1489.         pop    ds
  1490.         pop    es
  1491.         ret
  1492.  
  1493.   VendNext:
  1494.         lodsb                ; get field type:
  1495.  
  1496.         or    al,al            ; filler
  1497.         jz    VendLoop
  1498.  
  1499.         cmp    al,1            ; netmask
  1500.         jne    NotMask
  1501.         mov    di,offset MyMask
  1502.         call    Xtract4Bytes
  1503.         jmp    short VendLoop
  1504.   NotMask:
  1505.         cmp    al,2            ; zone/time (?) offset
  1506.         jne    NotTimeOffs
  1507.         test    cs:Flagword,HAVE_TIMEOFFSET
  1508.         jnz    VendDefault
  1509.         mov    di,offset tzoffset
  1510.         call    Xtract4Bytes
  1511.         or    cs:Flagword,HAVE_TIMEOFFSET
  1512.         jmp    short VendLoop
  1513.   NotTimeOffs:
  1514.         cmp    al,3            ; default gateways
  1515.         jne    NotDefGwys
  1516.         mov    di,offset DefGwys
  1517.         mov    cx,MAXDEFGWYS
  1518.         mov    ax,cs:DefGwyNum
  1519.         call    XtractIpNums
  1520.         add    cs:DefGwyNum,cx
  1521.         jmp    short VendLoop
  1522.   NotDefGwys:
  1523.         cmp    al,4            ; time servers
  1524.         jne    NotTimeserv
  1525.         or    cs:Flagword,HAVE_TIMESERVER
  1526.         mov    di,offset TimeServIpNr
  1527.         mov    cx,MAXTSERVS
  1528.         mov    ax,cs:TservNum
  1529.         call    XtractIpNums
  1530.         add    cs:TservNum,cx
  1531.         jmp    short VendLoop
  1532.   NotTimeserv:
  1533. if TBLBUILD or PINGCLIENT
  1534.         cmp    al,6            ; default nameservers
  1535.         jne    NotDefNS
  1536.         mov    di,offset DefNS
  1537.         mov    cx,MAXDEFNS
  1538.         mov    ax,cs:DefNSnum
  1539.         call    XtractIpNums
  1540.         add    cs:DefNSnum,cx
  1541.         jmp    VendLoop
  1542.   NotDefNS:
  1543. endif ; TBLBUILD or PINGCLIENT
  1544.         cmp    al,0ffh         ; end
  1545.         jne    VendDefault
  1546.         jmp    VendEnd
  1547.   VendDefault:                    ; everything else
  1548.         lodsb
  1549.         xor    ah,ah
  1550.         add    si,ax            ; skip field
  1551.         jmp    Vendloop
  1552.  
  1553. InterpBootp    endp
  1554.  
  1555.  
  1556.  
  1557. ;************************************************************************
  1558. ;*        XtractIpNums
  1559. ;************************************************************************
  1560.  
  1561. XtractIpNums    proc    near
  1562.         assume    ds:nothing
  1563.         sub    cx,ax            ; wanted - already got
  1564.  
  1565.         shl    ax,1
  1566.         shl    ax,1
  1567.         add    di,ax            ; append to what we got
  1568.         shl    cx,1
  1569.         shl    cx,1
  1570.         jmp    short XtractNBytes
  1571. Xtract4Bytes:
  1572.         mov    cl,4
  1573. XtractNBytes:
  1574.         lodsb
  1575.         cmp    cl,al            ; as many as we want?
  1576.         jbe    XtractOkLen
  1577.  
  1578.         mov    cl,al            ; - no, take what there is
  1579.   XtractOkLen:
  1580.         xor    ch,ch
  1581.         xor    ah,ah
  1582.         push    cx
  1583.         push    ax
  1584.         push    si
  1585.         rep    movsb            ; copy field
  1586.         pop    si
  1587.  
  1588.         pop    ax
  1589.         add    si,ax            ; advance field ptr
  1590.  
  1591.         pop    cx
  1592.         shr    cx,1
  1593.         shr    cx,1            ; cx = IP #'s read
  1594.  
  1595.         ret
  1596. XtractIpNums    endp
  1597.  
  1598.  
  1599.  
  1600. if TBLBUILD or PINGCLIENT
  1601.  
  1602. NsStruc     struc
  1603. uNsUdpHdr    UdpStruc    <>
  1604. uNsId        dw    0
  1605. uNsOpwd     dw    0001h            ; do recursion
  1606. uNsQdcount    dw    0100h            ; one question
  1607. uNsAncount    dw    0
  1608. uNsNscount    dw    0
  1609. uNsArcount    dw    0
  1610. uNsQuest    equ    $-uNsUdpHdr
  1611. NsStruc     ends
  1612.  
  1613. ;************************************************************************
  1614. ;*        NameDecode
  1615. ;*
  1616. ;*    Find end of name and change length bytes to dots
  1617. ;************************************************************************
  1618.  
  1619. NameDecode    proc    near
  1620.         assume    ds:nothing
  1621.         lodsb
  1622.         mov     byte ptr [si-1],' '     ; blank 1st length byte
  1623.         jmp    short NameDcTst
  1624.   NameDcLoop:
  1625.         lodsb
  1626.         mov    byte ptr [si-1],'.'    ; change length byte to dot
  1627.   NameDcTst:
  1628.         cmp    al,0c0h         ; compressed?
  1629.         jb    NameDcNorm
  1630.         mov     byte ptr [si],' '
  1631.         inc    si
  1632.         ret
  1633.   NameDcNorm:
  1634.         mov    ah,al
  1635.         or    al,al            ; end of name?
  1636.         jz    NameDcRet        ; -yes, return
  1637.   NameDcSkip:
  1638.         lodsb                ; -no, skip over string
  1639.         or    al,al            ; bad syntax?
  1640.         jz    NameDcRet        ; -yes, better return now
  1641.         dec    ah            ; -no, continue skiping
  1642.         jnz    NameDcSkip      
  1643.         jmp    short NameDcLoop
  1644.   NameDcRet:
  1645.         ret
  1646. NameDecode    endp
  1647.  
  1648.  
  1649.  
  1650. ;************************************************************************
  1651. ;*        NsResolve
  1652. ;*
  1653. ;*    Input:        DX = my udp port
  1654. ;*            AX = Ns Id
  1655. ;*            CS:SI = address of querry string
  1656. ;************************************************************************
  1657.  
  1658. MsgResolve    db    "no response.$"
  1659.  
  1660. NsResolve    proc    near
  1661.         assume    ds:nothing
  1662.         push    es
  1663.         push    bx
  1664.         push    ds
  1665.  
  1666.         push    si
  1667.         call    BufAlloc        ; get a big buf
  1668.         pop    si
  1669.         mov    cx,SERRNOBUF
  1670.         jz    NsResErr
  1671.  
  1672.         call    MakeSendDescr
  1673.         mov    [di].uUdpDst,3500h
  1674.         mov    [di].uUdpSrc,dx
  1675.         mov    [di].uNsId,ax
  1676.         xor    ax,ax
  1677.         mov    [di].uNsOpwd,1        ; recursion desired
  1678.         mov    [di].uNsQdcount,0100h    ; 1 question
  1679.         mov    [di].uNsAncount,ax
  1680.         mov    [di].uNsNscount,ax
  1681.         mov    [di].uNsArcount,ax
  1682.         mov    [bx].dTick2Timeout,14*18 ; give him 14 seconds 2nd turn
  1683.         mov    [bx].dTimOut2Msg,ax
  1684.         mov    [bx].dWaitEvent,GOT_NSREPLY
  1685.         cmp    dx,1234h
  1686.         je    NsTableBuild
  1687.  
  1688.         mov    [bx].dTickResend,4*18    ; resend after 4 seconds
  1689.         mov    [bx].dTickTimeout,2*18    ; give him 2 seconds 1st turn
  1690.         mov    [bx].dTimOut2Msg,offset MsgResolve
  1691.   NsTableBuild:
  1692.         lea    di,[di].uNsQuest    ; copy question
  1693.   NsQloop:
  1694.         lods    byte ptr cs:[EchoNameBuf]
  1695.         stosb
  1696.         or    al,al
  1697.         jnz    NsQloop
  1698.  
  1699.         movs    word ptr es:[uNsQuest],word ptr cs:[EchoNameBuf]    ; copy type
  1700.         movs    word ptr es:[uNsQuest],word ptr cs:[EchoNameBuf]    ; and class
  1701.  
  1702.         mov    ax,di            ; compute ip data length
  1703.         mov    si,[bx].dPtrUdp
  1704.         sub    ax,si
  1705.         mov    [bx].dPktLen,ax
  1706.  
  1707.         SHOW_EVENT    'I'
  1708.         mov    dx,offset DefNsNum
  1709.         call    SendUdpFind        ; send pkt
  1710.         call    BufRelease
  1711.         SHOW_EVENT    'J'
  1712.   NsResErr:
  1713.         or    cx,cx
  1714.         pop    ds
  1715.         pop    bx
  1716.         pop    es
  1717.         ret
  1718. NsResolve    endp
  1719.  
  1720.  
  1721.  
  1722. ;************************************************************************
  1723. ;*        DoNsInterp
  1724. ;************************************************************************
  1725.  
  1726. DoNsInterp     proc     near
  1727.         assume    ds:nothing
  1728.         cld
  1729.         push    cs
  1730.         pop    es
  1731.         mov    di,[bx].dPtrUdp
  1732.         test    [di].uNsOpwd,0080h    ; reply?
  1733.         jnz    NameResReply
  1734.         ret
  1735.  
  1736.   NameResReply:
  1737. if TBLBUILD
  1738.         cmp    [di].uUdpDst,1234h    ; to the tblbuilder?
  1739.         jne    DoNsIntPing
  1740.         jmp    DoName
  1741. endif ; TBLBUILD
  1742.   DoNsIntPing:
  1743.         mov    cx,[di].uNsAncount
  1744.         xchg    ch,cl
  1745.         cmp    cx,1            ; any answers?
  1746.         jb    NameResNoAnswer
  1747.  
  1748.         lea    si,[di].uNsQuest
  1749.         call    NameDecode        ; decode question string
  1750.         add    si,4            ; skip over type and class
  1751.   NsAnsLoop:
  1752.         call    NameDecode        ; decode answer string
  1753.         mov    ax,[si]         ; get type
  1754.         add    si,9            ; skip over junk
  1755.         cmp    ax,0100h        ; address?
  1756.         je    NsAnsAddr
  1757.  
  1758.         lodsb
  1759.         xor    ah,ah
  1760.         add    si,ax            ; skip over data bytes
  1761.         loop    NsAnsLoop
  1762.  
  1763.         jmp    short NameResNoAnswer
  1764.   NsAnsAddr:
  1765.         cmp    byte ptr [si],4     ; 4 IP bytes here?
  1766.         jne    NameResNoAnswer
  1767.  
  1768.         inc    si            ; copy IP number
  1769.         push    cs
  1770.         pop    es
  1771.         mov    di,offset EchoTarget
  1772.         movsw
  1773.         movsw
  1774.   NameResNoAnswer:
  1775.         or    cs:Events,GOT_NSREPLY    ; note we've got ns reply
  1776.         ret
  1777. DoNsInterp    endp
  1778.  
  1779. endif ; TBLBUILD or PINGCLIENT
  1780.  
  1781.  
  1782.  
  1783. ;************************************************************************
  1784. ;*        ARP and IP receiver
  1785. ;************************************************************************
  1786.  
  1787.         assume    ds:nothing
  1788.  
  1789. Receiver:
  1790.         pushf
  1791.         push    ds            ; save segment register
  1792.         cld
  1793.  
  1794. if DEBUG
  1795.         test    cs:GenFlags,DBGSTOP
  1796.         jnz    IpRecTooBig
  1797. endif ; DEBUG
  1798.         or    ax,ax            ; first or second call?
  1799.         jne    IpRecv_1        ; - second, we've got data
  1800.                         ; - first, they want a buf
  1801.         SHOW_EVENT    'A'
  1802.         cmp    cx,cs:MyGiant        ; packet too long?
  1803.         ja    IpRecTooBig
  1804. if PINGCLIENT
  1805. ifdef SMALLBUFS
  1806.         cmp    cx,BUFBODYSML
  1807.         ja    IpRecBig
  1808.  
  1809.         call    BufAlSml
  1810.         jz    IpRecBig
  1811.  
  1812.         pop    ds
  1813.         popf
  1814.         retf
  1815.  
  1816.   IpRecBig:
  1817. endif ; SMALLBUFS
  1818. endif ; PINGCLIENT
  1819.         call    BufAlloc        ; get a receive buffer
  1820.         jz    IpRecNoBuf
  1821.  
  1822.   IpRecRet0:
  1823.         pop    ds
  1824.         popf
  1825.         retf                ; return to pkt drvr
  1826.  
  1827. if DEBUG
  1828.   DbgIpRecv:
  1829.         or    cs:GenFlags,DBGINTERR
  1830. endif ; DEBUG
  1831.  
  1832.   IpRecNoBuf:
  1833.  
  1834. if PINGCLIENT
  1835.         cmp    bx,cs:IpHandle
  1836.         jne    IpRecTooBig
  1837.         inc    cs:EchoDrop
  1838. endif ; PINGCLIENT
  1839.   IpRecTooBig:
  1840.         xor    di,di            ; no buffer available
  1841.         mov    es,di
  1842.         jmp    short IpRecRet0
  1843.  
  1844.  
  1845.   IpRecv_1:
  1846.         mov    word ptr cs:SaveSS,ss    ; switch to our
  1847.         mov    word ptr cs:SaveSP,sp    ;   interrupt stack
  1848.         cli            
  1849.         mov    ss,cs:MySegm
  1850.         mov    sp,offset StackEnd
  1851.         sti                ; allow interrupts
  1852.  
  1853. if DEBUG ge 2
  1854.         mov    dx,ds
  1855.         cmp    dx,cs:MySegm
  1856.         je    IpRecvCs
  1857.         SHOW_EVENT    'B'
  1858.   IprecvCs:
  1859. endif ; DEBUG ge 2
  1860. if DEBUG
  1861.         dec    cs:DbgIntCnt        ; double interrupt?
  1862.         jnz    DbgIpRecv
  1863. endif ; DEBUG
  1864.  
  1865. if PINGCLIENT
  1866.         mov    ax,cx            ; pkt length
  1867.         add    ax,8+4+12        ; preamble, crc, intergap
  1868.         add    cs:EchoLoad+2,ax
  1869.         adc    cs:EchoLoad,0
  1870. endif ; PINGCLIENT
  1871.         mov    ax,si
  1872.         add    ax,cx            ; end of packet limit
  1873.         mov    bx,[si-2]         ; addr of descriptor
  1874.  
  1875.         mov    [bx].dPktLen,cx     ; fill in descriptor info
  1876.         mov    [bx].dPktEnd,ax
  1877.  
  1878.         add    si,cs:H2Len
  1879.         mov    ax,[si]         ; type/length field
  1880.         xchg    ah,al
  1881.  
  1882.         xor    dl,dl
  1883.         cmp    ax,GIANT        ; if 802.3 pkt
  1884.         jbe    BuildSnap        ;   do special handling
  1885.   BuildNotSnap:
  1886.         mov    [bx].dSnap,dl
  1887.         lea    di,[si+2]
  1888.         mov    [bx].dPtrIp,di        ; di must point to IP hdr
  1889.  
  1890.         cmp    ax,0806h        ; ARP protocol?
  1891.         je    ArpRecvCont0
  1892.  
  1893.         mov    cl,[di].iIpVerHlen     ; get version+length byte
  1894.         and    cx,0fh            ; length (32 bit words)
  1895.         shl    cx,1            ; convert to
  1896.         shl    cx,1            ;   byte length
  1897.  
  1898.         call    IpChkSum        ; only accept a correct
  1899.         jne    IpRecRet        ;   IP checksum
  1900.  
  1901.         mov    [bx].dPtrUdp,si
  1902. if RFCC
  1903.         call    VerifyIpHdr        ; verify and process IP hdr
  1904.         jc    IpRecKeepBuf
  1905. endif ; RFCC
  1906.         SHOW_EVENT    'H'
  1907.  
  1908.         mov    cx,[di].iIpLen        ; calculate IP data length
  1909.         xchg    ch,cl
  1910.         add    cx,di
  1911.         sub    cx,si
  1912.         mov    [bx].dPktLen,cx     ; save IP data length
  1913.  
  1914.         mov    al,[di].iIpProt
  1915.         cmp    al,ICMP_PROT        ; ICMP protocol?
  1916.         jne    IpNotIcmp
  1917.         jmp    IpRecIcmp
  1918.  
  1919.  
  1920.   BuildSnap:
  1921.         inc    dl            ; -no, assumed to be snap
  1922.         add    si,SNAPLEN        ; skip over snap bytes
  1923.         jmp    short BuildNotSnap
  1924.  
  1925.  
  1926.   ArpRecvCont0:
  1927.         cmp    [di].iArpProt,0008h    ; arp IP protocol?
  1928.         jne    IpRecRet
  1929.         jmp    ArpRecvCont
  1930.  
  1931.  
  1932.   IpNotIcmp:
  1933.         cmp    al,UDP_PROT        ; UDP protocol?
  1934.         jne    IpProtUnr
  1935.  
  1936.         call    UdpChkSum        ; if available, test 
  1937.         jne    IpRecRet        ;   UDP checksum
  1938.  
  1939.         cmp    si,[bx].dPktEnd     ; still within packet limit?
  1940.         jbe    IpRecUdp
  1941.  
  1942.   IpRecRet:
  1943.         SHOW_EVENT    'Z'
  1944.         call    BufRelease        ; release receive buffer
  1945.   IPRecKeepBuf:
  1946.  
  1947. if DEBUG ge 2
  1948.         cmp    sp,offset StackEnd
  1949.         call    TstEqual
  1950. endif ; DEBUG ge 2
  1951. if DEBUG
  1952.         inc    cs:DbgIntCnt
  1953. endif ; DEBUG
  1954.         cli                ; restore previous stack
  1955.         mov    ss, word ptr cs:SaveSS
  1956.         mov    sp, word ptr cs:SaveSP
  1957.  
  1958.         pop    ds
  1959.         popf
  1960.         retf                ; return to pkt drvr
  1961.  
  1962.  
  1963. if TBLBUILD
  1964.   ArpRecBld0:
  1965.         jmp    ArpRecBld
  1966. endif ; TBLBUILD
  1967.  
  1968.   IpProtUnr:
  1969.         mov    ah,2            ; protocol unreachable
  1970.         jmp    short IpUnr
  1971.   IpPortUnr:
  1972.         mov    ah,3            ; port unreachable
  1973.   IpUnr:
  1974. if RFCC
  1975.         mov    al,3            ; destination unreachable
  1976.  
  1977.         cmp    [bx].dIdxIpDst,ARPMYIDX ; was it specifically to me?
  1978. if TBLBUILD
  1979.                 jne     ArpRecBld0        ; -no, collect his address
  1980. else
  1981.                 jne     IpRecRet
  1982. endif ; TBLBUILD
  1983.  
  1984.         push    bx
  1985.         push    ds
  1986.         push    ax
  1987.         call    GetIpSrc        ; -yes, mov his IP # to IP dst
  1988.         mov    cx,[bx].dPtrUdp        ; copy IP header
  1989.         add    cx,8            ;   + 8 bytes
  1990.         sub    cx,si
  1991.  
  1992.         push    si
  1993.         call    BufAlloc
  1994.         pop    si
  1995.         jz    UnrEnd
  1996.  
  1997.         call    MakeSendDescr
  1998.         push    di
  1999.         call    SetIpDst        ; return to sender
  2000.  
  2001.         pop    di
  2002.         pop    ax
  2003.         mov    [di].uIcmpTypecode,ax ; set type and code
  2004.  
  2005.         pop    es
  2006.         push    es
  2007.         push    ax
  2008.  
  2009.         add    di,8
  2010.         call    MovesbEsToDs
  2011.  
  2012.         mov    si,[bx].dPtrUdp
  2013.         sub    di,si
  2014.         mov    [bx].dPktLen,di     ; set IP data length
  2015.  
  2016.         mov    si,offset IcmpToDo    ; put buf on the ICMP send list
  2017.         call    AddToList
  2018.   UnrEnd:
  2019.         pop    ax
  2020.         pop    ds
  2021.         pop    bx
  2022. endif ; RFCC
  2023.   IpRecRet3:
  2024.         jmp    IpRecRet
  2025.  
  2026.  
  2027.   IpRecUdp:        ; -------------    UDP --------------------
  2028.         mov    [bx].dPktEnd,si     ; end of logical pkt
  2029.  
  2030.         mov    di,[bx].dPtrUdp
  2031.         mov    ax,word ptr [di].uUdpSrc
  2032.         mov    dx,word ptr [di].uUdpDst
  2033. if TBLBUILD or PINGCLIENT
  2034.         cmp    dx,0703h        ; Udp Echo reply?
  2035.         jne    $+5
  2036.         jmp    IpEchoReply
  2037.         cmp    dx,0700h        ; Udp Echo request?
  2038.         jne    $+5
  2039.         jmp    IpEchoRequest
  2040.         cmp    dx,0900h        ; Udp Discard request?
  2041.         jne    $+5
  2042.         jmp    IpDiscard
  2043.         cmp    ax,3500h        ; Name server (53)?
  2044.         jne    $+5
  2045.         jmp    IpRecvName
  2046. endif ; TBLBUILD or PINGCLIENT
  2047.         cmp    ax,2500h        ; Src port 0025 = 37 ?
  2048.         je    IpRecvTime        ; - must be time reply
  2049. if 0
  2050.         cmp    ax,4300h        ; Src port 0043 = 67
  2051.         jne    IpPortUnr
  2052. endif
  2053.         cmp    dx,4400h        ; Dst port 0044 = 68
  2054.         jne    IpPortUnr
  2055.  
  2056.         cmp    byte ptr [di].uBotOp,2    ; bootp reply?
  2057.         jne    IpRecRet3
  2058.  
  2059.   IpRecBootp:        ; -------------    UDP BOOTP REPLY -------------------
  2060.         push    cs
  2061.         pop    es
  2062.         push    di            ; - must be bootp reply
  2063.         lea    si,[di].uBotCliHwAd
  2064.         mov    di,offset MyHwAd
  2065.         mov    cx,cs:Hlen
  2066.         repe    cmpsb            ; our Ethernet addr?
  2067.         pop    di
  2068.         jne    IpRecRet2
  2069.  
  2070.         mov    cx,cs:BootpXid
  2071.         cmp    cx,[di].uBotXid
  2072.         jne    IpRecRet2
  2073.                         ; yes, it's about me!
  2074.         mov    dx,[di].uBotGwyIp    ; saves an ARP request
  2075.         mov    ax,[di].uBotGwyIp+2    ;   in many cases
  2076.         call    ArpPutNewSiHl
  2077.  
  2078.         test    cs:Events,GOT_BOOTP    ; if first answer
  2079.         jnz    IpRecRet2        ;   save bootp answer
  2080.  
  2081.         mov    cs:AdrBootpReply.offs,bx ;  for further study 
  2082.         mov    cs:AdrBootpReply.segm,ds
  2083.         or    cs:Events,GOT_BOOTP
  2084.         jmp    IpRecKeepBuf
  2085.  
  2086.   IpRecvTime:        ; -------------    UDP TIME REPLY --------------------
  2087.         test    cs:Events,GOT_TIMEREPLY    ; already got reply?
  2088.         jnz    IpRecRet2
  2089.  
  2090.         mov    ax,[di].uUdpData    ; save seconds
  2091.         mov    cs:cTime,ax        ;   since year 1900
  2092.         mov    ax,[di].uUdpData+2
  2093.         mov    cs:cTime+2,ax
  2094.  
  2095.         mov    di,[bx].dPtrIp        ; save who was answering
  2096.         mov    dx,[di].iIpSrc
  2097.         mov    ax,[di].iIpSrc+2
  2098.         mov    cs:RespondingIpNr,dx
  2099.         mov    cs:RespondingIpNr+2,ax
  2100.         or    cs:Events,GOT_TIMEREPLY
  2101.   IpRecRet2:
  2102.         jmp    IpRecRet
  2103.  
  2104. if TBLBUILD or PINGCLIENT
  2105.   IpRecvName:        ; -------------    UDP NAME REPLY -----------------
  2106.         SHOW_EVENT    'K'
  2107.         mov    si,offset NameToDo    ; process nameserver reply
  2108.         call    AddToList
  2109.         jmp    IpRecKeepBuf
  2110. endif ; TBLBUILD or PINGCLIENT
  2111.  
  2112.  
  2113. if RFCC
  2114.   IpEchoRequest:    ; -------------    UDP ECHO REQ ----------------
  2115.         call    SwitchIpDst
  2116.  
  2117.         mov    si,[bx].dPtrUdp
  2118.  
  2119.         mov    dx,[si].uUdpDst     ; swap udp src and dst ports
  2120.         mov    ax,[si].uUdpSrc
  2121.         mov    [si].uUdpDst,ax
  2122.         mov    [si].uUdpSrc,dx
  2123.         jmp    IpQueReply
  2124.  
  2125.   IpDiscard:        ; -------------    UDP DISCARD ------------------
  2126.         cmp    cs:EchoTarget,0
  2127.         jne    IpRecRet4
  2128.         add    cs:EchoRxLo,1        ; increment receive counters
  2129.         adc    cs:EchoRxHi,0
  2130.   IpRecRet4:
  2131.         jmp    IpRecRet
  2132. endif ; RFCC
  2133.  
  2134.  
  2135.  
  2136.   IpRecIcmp:        ; -------------    ICMP --------------------------------
  2137.         call    IcmpChkSum2        ; valid ICMP checksum?
  2138.         jne    IpRecRet2
  2139.  
  2140.         mov    cx,[di].uIcmpTypecode    ; get type and code
  2141. if PINGCLIENT
  2142.         cmp    cl,0            ; echo reply?
  2143.         jne    IpNotEchoReply
  2144.   IpEchoReply:        ; -------------    ICMP PING REPLY ------------
  2145.         SHOW_EVENT    'L'
  2146.         call    EchoCalc
  2147.         mov    ds,cx            ; restore ds for buf rel
  2148.         jmp    IpRecRet
  2149.   IpNotEchoReply:
  2150. endif ; PINGCLIENT
  2151.  
  2152.         call    SwitchIpDst        ; in case we want to return it
  2153.         mov    si,[bx].dPtrUdp     ; point to ICMP header
  2154. if RFCC
  2155.         cmp    cl,8            ; echo request?
  2156.         jne    IpNotEchoReq
  2157. ;            ---------------    ICMP PING REQ ---------------
  2158.         SHOW_EVENT    'M'
  2159.         mov    byte ptr [si].uIcmpTypecode,0 ; put echo reply value
  2160.   IpQueReply:
  2161.         cmp    [bx].dIdxIpDst,ARPMYIDX ; broadcast?
  2162.         jb    IpRecRet4        ; - yes, don't echo
  2163.  
  2164.         test    cs:ArgFlags,UPCALL_SEND    ; want to stress the driver?
  2165.         jnz    IpUpcallSend
  2166.  
  2167.         mov    si,offset IcmpToDo    ; put buf on the ICMP send list
  2168.         call    AddToList
  2169.         jmp    IpRecKeepBuf
  2170.  
  2171.   IpUpcallSend:
  2172.         mov    di,[bx].dPtrIp
  2173.         cmp    [di].iIpProt,UDP_PROT    ; UDP protocol?
  2174.         je    IpUdp2Do
  2175.  
  2176.         call    SendIcmpPkt
  2177.         jmp    short IpRecRet5
  2178.   IpUdp2Do:
  2179.         mov    [bx].dWaitEvent,0    ; don't wait for answer
  2180.         call    SendUdpPkt
  2181.   IpRecRet5:
  2182.         jmp    IpRecRet
  2183.  
  2184.   IpNotEchoReq:
  2185. endif ; RFCC
  2186.         mov    dx,[si].uIcmpIpHdr.iIpDst    ; get original IP hdr
  2187.         mov    ax,[si].uIcmpIpHdr.iIpDst+2    ;   dst IP #
  2188.  
  2189.         cmp    cx,11            ; TTL exceeded?
  2190.         je    IpIcmpUnreach
  2191.  
  2192.         cmp    cl,3            ; unreachable
  2193.         jne    IpNotUnreach
  2194. ;            ---------------    ICMP UNREACHABLE ---------
  2195.         cmp    ch,12            ; net or host unreachable?
  2196.         ja    IpIcmpRet2
  2197.         cmp    ch,6
  2198.         ja    IpIcmpUnreach
  2199.         cmp    ch,1
  2200.         ja    IpIcmpRet2
  2201.   IpIcmpUnreach:                ; codes 0 - 1, 6 - 12 go here
  2202.         SHOW_EVENT    'N'
  2203.         push    si
  2204.         call    RouteFindUtos        ; this host in route table?
  2205.         pop    si
  2206.         jnz    IpIcmpUnfound
  2207.  
  2208.         mov    ah,byte ptr [si].uIcmpTypeCode+1 ; icmp code
  2209.         xor    al,al        ;*test
  2210.         inc    ah            ; ensure non zero error code
  2211.         mov    cs:RouteTabUnreach[di],ax ; mark it unreachable
  2212.  
  2213.         mov    cx,cs:SavedTicks    ; get current ticks value
  2214.         mov    cs:RouteTabTrRx[di],cx    ; set timer
  2215.   IpIcmpUnfound:
  2216.   IpIcmpRet2:
  2217.         jmp    IpIcmpRet
  2218.  
  2219.   IpNotUnreach:
  2220. if RFCC
  2221.         cmp    cl,4            ; source quench?
  2222.         jne    IpIcmpNotQuench
  2223. ;            ---------------    ICMP SRC QUENCH ----------
  2224.         SHOW_EVENT    'O'
  2225.         call    RouteFindUtos        ; this host in route table?
  2226.         push    ds
  2227.         push    cs
  2228.         pop    ds
  2229.         jnz    IpIcmpNotRoute
  2230.  
  2231.         mov    dx,RouteTabFlags[di]
  2232.         or    RouteTabFlags[di],SQ_UPDATED
  2233.         lea    si,RouteTabTrSq[di]
  2234.         lea    di,RouteTabSqDelay[di]
  2235.         jmp    short IpIcmpSq
  2236.   IpIcmpNotRoute:
  2237.         call    ArpFindIp
  2238.         jnz    IpIcmpSqEnd
  2239.  
  2240.         mov    dx,ArpTabFlags[di]
  2241.         or    ArpTabFlags[di],SQ_UPDATED
  2242.         lea    si,ArpTabTrSq[di]
  2243.         lea    di,ArpTabSqDelay[di]
  2244.   IpIcmpSq:
  2245.         mov    ax,[di]         ; get current sq delay
  2246.         or    ax,ax
  2247.         jnz    IpIcmpAddDelay
  2248.         mov    cx,SavedTicks
  2249.         mov    [si],cx         ; initialize sq timer
  2250.         mov    ax,100            ; initial sq delay 100 ms
  2251.   IpIcmpAddDelay:
  2252.         add    ax,28            ; increase delay by 28 ms
  2253.         test    dx,SQ_UPDATED        ;   unless already done in
  2254.         jnz    IpIcmpSqEnd        ;   the last two seconds
  2255.         mov    [di],ax
  2256.   IpIcmpSqEnd:
  2257.         pop    ds
  2258.         jmp    short IpIcmpRet
  2259.  
  2260.   IpIcmpNotQuench:
  2261. endif ; RFCC
  2262.         cmp    cl,5            ; redirect?
  2263.         jne    IpNotRedirect
  2264. ;            ---------------    ICMP REDIRECT ------------
  2265.         SHOW_EVENT    'P'
  2266.         push    si
  2267.         call    RouteFindUtos        ; this host in route table?
  2268.         pop    si
  2269.         jnz    IpIcmpDisfound
  2270.  
  2271.         mov    dx,cs:RouteTabIpG1[di]    ; icmp from the gwy used?
  2272.         mov    ax,cs:RouteTabIpG2[di]
  2273.         mov    cx,di
  2274.         mov    di,[bx].dPtrIp
  2275.         cmp    dx,[di].iIpSrc
  2276.         jne    IpIcmpDisfound
  2277.         cmp    ax,[di].iIpSrc+2
  2278.         jne    IpIcmpDisfound
  2279.         mov    di,cx
  2280.  
  2281.         mov    dx,[si].uIcmpData    ; new gateway IP #
  2282.         mov    ax,[si].uIcmpData+2
  2283.  
  2284.         call    MyNetChk        ; is he on my net?
  2285.         jnz    IpIcmpDisfound
  2286.  
  2287.         mov    cs:RouteTabIpG1[di],dx    ; put it into route table
  2288.         mov    cs:RouteTabIpG2[di],ax
  2289.   IpIcmpDisfound:
  2290.         jmp    short IpIcmpRet
  2291.  
  2292.   IpNotRedirect:
  2293.   IpIcmpRet:
  2294.         jmp    IpRecRet
  2295.  
  2296. ;========================================================================
  2297. ;        endinclude
  2298.