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

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