home *** CD-ROM | disk | FTP | other *** search
/ PC Press: Internet / PC_PRESS.ISO / software / dos / misc / inar-100.exe / SRC / PCROUTE / RIP.INC < prev    next >
Encoding:
Text File  |  1995-05-21  |  48.4 KB  |  1,603 lines

  1. ;;************************************************************************* 
  2. ;;                         rip.inc       rip.inc
  3. ;;*************************************************************************
  4. ;;
  5. ;;  Copyright (C) 1989 Northwestern University, Vance Morrison
  6. ;;
  7. ;;
  8. ;; Permission to view, compile, and modify for LOCAL (intra-organization) 
  9. ;; USE ONLY is hereby granted, provided that this copyright and permission 
  10. ;; notice appear on all copies.  Any other use by permission only.
  11. ;;
  12. ;; Northwestern University makes no representations about the suitability 
  13. ;; of this software for any purpose.  It is provided "as is" without expressed 
  14. ;; or implied warranty.  See the copywrite notice file for complete details.
  15. ;;
  16. ;;*****************************************************************************
  17. ;;
  18. ;; rip.inc provides a ROUTE interface for th rip protocol.  In particular
  19. ;; it provides the following functions
  20. ;;
  21. ;; Routines provided by this module
  22. ;;
  23. ;;   RIP_DECLARE name, ip_net, timer, udp, udp_sock
  24. ;;   RIP_DEFINE name
  25. ;;   ROUTE_ADD_in_AX_CX_DX_SI_DI_ES_const_DI_ES name
  26. ;;   ROUTE_FIND_in_AX_BX_SI_DI_out_AX_BX_DX_const_CX_BP_ES name, forme, fail, drop
  27. ;;
  28. ;;*****************************************************************************
  29.  
  30. ;;*****************************************************************************
  31. ;; definition of RIP packet structure
  32.  
  33. RIP_PORT                = 208h
  34. SWAPPED_RIP_PORT        = 802h
  35.  
  36. RIP_REQUEST             = 1         ;; request for RIP packets
  37. RIP_REPLY               = 2         ;; sending out RIP packets
  38. RIP_VER                 = 1
  39. IP_FAMILY               = 2
  40. SWAPPED_IP_FAMILY       = 200h
  41.  
  42. MAX_HOST_SPLIT          = 256
  43.  
  44. rip_head    STRUC
  45.     rip_command         DB RIP_REPLY
  46.     rip_version         DB RIP_VER
  47.     rip_zero1           DW 0
  48. rip_head    ENDS
  49.  
  50. rip_route   STRUC
  51.     rip_family          DW SWAPPED_IP_FAMILY
  52.     rip_zero2           DW 0
  53.     rip_address         DD 0
  54.     rip_zero3           DD 0
  55.     rip_zero4           DD 0
  56.     rip_metric          DD 8
  57. rip_route   ENDS
  58.  
  59. ;;*****************************************************************************
  60. ;; internal Routing table definitions
  61.  
  62. rip_entry  STRUC
  63.    re_next      DW ?          ; this MUST be the first field
  64.    re_prev      DW ?
  65.    re_net       DD ?
  66.    re_mask      DD ?
  67.    re_gateway   DW 2 dup (0)
  68.    re_igateway  DW 2 dup (0)
  69.    re_interface DB ?        ; interface MUST come directly before metric
  70.    re_metric    DB ?
  71.    re_flags     DB ?
  72.    re_timer     DB ?
  73.    re_id        DW ?
  74. rip_entry  ENDS
  75.  
  76. rip_table_size = 1200
  77. rip_data  STRUC
  78.     rip_hash      DW 256 dup (0)
  79.     rip_table     rip_entry rip_table_size dup (<>)
  80.     rip_table_ptr DW ?                    ;; end of the routeing table
  81.     rip_pack_ctr  DW ?
  82.     rip_pack_ptr  DW ?
  83.     rip_pack_out  DW ?
  84.     rip_if_net    DD ?
  85.     rip_if_last   DD ?
  86.     rip_target    DD ?
  87.     rip_udp_port  DW ?
  88.     rip_hr_count  DW 0
  89. rip_data  ENDS
  90. rip_table_end  = (rip_table+(rip_table_size*(size rip_entry)))
  91.  
  92. ;; Routing Flags
  93. ROUTE_SILENT =    (1 shl 0)      ; Do not broadcast via RIP
  94. ROUTE_SPLIT  =    (1 shl 1)      ; For RIP, split network into host routes
  95. ROUTE_TRANS  =    (1 shl 2)      ; Transient, can be changed by RIP
  96. ROUTE_DROP   =    (1 shl 3)      ; Declare as unreachable
  97. ROUTE_DENY   =    (1 shl 4)      ; Do not route (source routing)
  98.  
  99. ROUTE_SOURCE =    (1 shl 6)      ; a source route entry
  100. ROUTE_VALID  =    (1 shl 7)      ; a valid table entry
  101.  
  102.  
  103. ;;******************************************************************************
  104. ;;  RIP_DECLARE name, ip_net, timer, udp
  105. ;;       RIP_DECLARE delcares a new routing object called 'name'. 
  106. ;;       'ip_net' is the IP_NET that the router is associated with,
  107. ;;       'timer' is a timer object, and 'udp' is the name of
  108. ;;       a UDP object (to get RIP packets from)
  109. ;;
  110. RIP_DECLARE   MACRO  name, ip_net, timer, udp
  111.     .errb <udp>
  112.  
  113.     .DATA
  114.     rip_&name&_ip_net = ip_net
  115.     rip_&name&_timer = timer
  116.     rip_&name&_udp = udp
  117.     rip_&name&_udp_sock = (name*100+1)
  118.     rip_&name&_dls = ip_&ip_net&_dls
  119.     global rip_&name&_data:rip_data 
  120.  
  121.     .CODE
  122.     global rip_&name&_read_code:near 
  123.     global rip_&name&_timer_code:near 
  124.     global rip_&name&_expire_code:near
  125.     global rip_&name&_send_code:near 
  126.     global rip_&name&_send_request:near
  127.     global rip_&name&_real_define:near
  128.     global route_&name&_real_add:near 
  129.  
  130.     UDP_SOCK_DECLARE %rip_&name&_udp_sock, %rip_&name&_udp, RIP_PORT
  131. ENDM
  132.  
  133.  
  134. ;;******************************************************************************
  135. ;;   RIP_DEFINE   name
  136. ;;       RIP_DEFINE sets aside the memory and acutally does the 
  137. ;;       initialization for the routeing objects 'name'
  138. ;;
  139. RIP_DEFINE        MACRO   name
  140.     call rip_&name&_real_define
  141. ENDM
  142.  
  143. RIP_REAL_DEFINE   MACRO   name
  144.     local around, listen_code, jmp_table, done
  145.     .errb <name>
  146.  
  147.     .DATA
  148. jmp_table  dw   done
  149.     IRP idx, <1,2,3,4,5,6,7,8>
  150.     if idx le rip_&name&_dls
  151.         RIP_INIT_DL_JMP_TAB name, idx, send_rip
  152.     endif
  153.     endm
  154.  
  155. rip_&name&_data   rip_data  <>
  156.  
  157.     .CODE
  158.     jmp around          ;; declare code objects
  159.         rip_&name&_timer_code:
  160.             RIP_TASK name 
  161.             TIMER_RETURN %rip_&name&_timer 
  162.                 ;; this does NOT fall through
  163.  
  164.         rip_&name&_expire_code:
  165.             RIP_EXPIRE_const_BX_CX_DX_BP name
  166.             TIMER_RETURN %rip_&name&_timer 
  167.                 ;; this does NOT fall through
  168.  
  169.         rip_&name&_send_code:
  170.             mov word ptr rip_&name&_data.rip_target, AX
  171.             mov word ptr rip_&name&_data.rip_target+2, BX
  172.             mov word ptr rip_&name&_data.rip_udp_port, CX
  173.             xor DH, DH                  ;; set up jump to proper DL
  174.             shl DX, 1
  175.             mov DI, offset jmp_table
  176.             add DI, DX
  177.             jmp [DI]                    ;; jump to proper DL
  178.  
  179.                 ;; the above jump goes to one of the code fragments below
  180.             IRP idx, <1,2,3,4,5,6,7,8>
  181.             if idx le rip_&name&_dls
  182.                 RIP_INIT_DL_LABEL name, idx, send_rip
  183.  
  184.                 RIP_SEND_DL name, idx
  185.                 RET
  186.             endif
  187.             endm
  188.                 ;; the above code does NOT fall through
  189.  
  190.             done:
  191.                 RET
  192.  
  193.         rip_&name&_read_code:
  194.             mov DI, BX
  195.                 ;; this is a violation of layering, but what can I do
  196.             IP_R_HEADER_in_ES_out_SI_const_BX_CX_DX_BP_DI_ES %rip_&name&_ip_net
  197.             add SI, ip_src
  198.             xchg SI, DI
  199.             RIP_PROCESS_PACKET_in_CX_SI_DI_ES name
  200.             RET
  201.                 ;; this does NOT fall through
  202.  
  203.         rip_&name&_send_request:
  204.             IRP idx, <1,2,3,4,5,6,7,8>
  205.             if idx le rip_&name&_dls
  206.                 RIP_SEND_REQUEST name, idx
  207.             endif
  208.             endm
  209.             TIMER_RETURN %rip_&name&_timer 
  210.                 ;; this does NOT fall through
  211.  
  212.         listen_code:
  213.                 ;; because of circular dependance (RIP, a low level
  214.                 ;; protocol depending on UDP a high level protocol)
  215.                 ;; we have to defer the definition of this socket
  216.             UDP_SOCK_DEFINE %rip_&name&_udp_sock, rip_&name&_read_code
  217.             TIMER_RETURN %rip_&name&_timer 
  218.                 ;; this does NOT fall through
  219.  
  220.         route_&name&_real_add:
  221.             ROUTE_REAL_ADD_in_AX_CX_DX_SI_DI_ES_const_DI_ES name
  222.             RET
  223.     around:
  224.  
  225. rip_&name&_real_define:
  226.     mov AX, DS              ; NULL all data 
  227.     mov ES, AX
  228.     xor AX, AX
  229.     mov CX, size rip_data
  230.     mov DI, offset rip_&name&_data
  231.     rep
  232.     stosb
  233.  
  234.     mov rip_&name&_data.rip_table_ptr, offset rip_&name&_data.rip_table-(size rip_entry) 
  235.  
  236.         ;; start RIP listening for packets
  237.     mov AX, 18*0
  238.     TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, listen_code
  239.  
  240.         ;; set the RIP request task to go off 
  241.     mov AX, 18*2
  242.     TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, rip_&name&_send_request
  243.  
  244.         ;; set the RIP update task to go off 
  245.     mov AX, 18*4
  246.     TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, rip_&name&_timer_code
  247.  
  248.         ;; set the expire task to go off 
  249.     mov AX, 18*10
  250.     TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, rip_&name&_expire_code
  251.     RET
  252. ENDM
  253.  
  254.  
  255. ;;******************************************************************************
  256. ;;   ROUTE_ADD_in_AX_CX_DX_SI_DI_ES name
  257. ;;      ROUTE_ADD adds the route described by network pointed to by SI:ES,
  258. ;;      the subnet mask pointed to by DX:ES (DX is null if there is no mask),
  259. ;;      the gateway pointed to by DI:ES, the route id in AX and the metric
  260. ;;      held in CL and flags (see flag defs above) held in CH.
  261. ;;      Note: For directly connected networks (CL = 0) the 'gateway' (DI:ES)
  262. ;;      must point to the IP address of this host.
  263. ;;
  264. ROUTE_ADD_in_AX_CX_DX_SI_DI_ES_const_DI_ES MACRO name
  265.     call route_&name&_real_add
  266. ENDM
  267.  
  268. ROUTE_REAL_ADD_in_AX_CX_DX_SI_DI_ES_const_DI_ES MACRO name
  269.    local done, look_for_empty, found_empty, no_wrap, found, new_route
  270.    local add_new_gateway, not_bigger, delete_route, save_mask, save_id
  271.    local check_mask, have_mask, store_mask, check_route, found_mask
  272.    local no_timer, no_delete, log_it, is_source, skip_source
  273.  
  274.     .DATA
  275. save_mask    DD    ?
  276. save_id        DW    ?
  277.     .CODE
  278.  
  279.     mov BP, DI                      ;; save DI
  280.     mov word ptr save_id, AX        ;; save route id
  281.     mov AX, word ptr ES:[SI]        ;; check for default route
  282.     or AX, word ptr ES:[SI+2]
  283.     jnz check_mask
  284.     mov BX, AX
  285.     jmp store_mask
  286. check_mask:
  287.     or DX, DX
  288.     jnz have_mask
  289.     mov AL, byte ptr ES:[SI]        ;; reconstruct the netmask
  290.     mov AH, 0ffh
  291.     mov BX, 0ffffh
  292.     IP_COMP_NET_in_AX_BX_out_AX_BX_const_CX_DX_BP_SI_DI_ES
  293.     mov AL, 0ffh
  294.     mov word ptr save_mask, AX
  295.     mov word ptr save_mask+2, BX
  296.     not AX
  297.     not BX
  298.     and AX, word ptr ES:[SI]
  299.     and BX, word ptr ES:[SI+2]
  300.     or AX, BX                       ;; check for host bits
  301.     jz check_route
  302.     mov AX, word ptr ES:[SI]
  303.     mov BX, word ptr ES:[SI+2]
  304.  
  305.     IRP idx, <1,2,3,4,5,6,7,8>
  306.     if idx le rip_&name&_dls 
  307.             RIP_GET_IF_NETMASK_in_AX_BX_out_AX_BX_const_CX_DX_BP_SI_DI_ES idx, found_mask
  308.     endif
  309.     endm
  310.     mov AX, 0ffffh                  ;; 255.255.255.255
  311.     mov BX, AX
  312.     jmp store_mask
  313.  
  314. found_mask:
  315.     mov word ptr save_mask, AX
  316.     mov word ptr save_mask+2, BX
  317.     not AX
  318.     not BX
  319.     and AX, word ptr ES:[SI]
  320.     and BX, word ptr ES:[SI+2]
  321.     or AX, BX                       ;; check for host bits
  322.     jz check_route
  323.     mov AX, 0ffffh                  ;; 255.255.255.255
  324.     mov BX, AX
  325.     jmp store_mask
  326. have_mask:
  327.     mov DI, DX
  328.     mov AX, word ptr ES:[DI]
  329.     mov BX, word ptr ES:[DI+2]
  330. store_mask:
  331.     mov word ptr save_mask, AX
  332.     mov word ptr save_mask+2, BX
  333. check_route:
  334.     mov AX, ES:[SI]
  335.     mov BX, ES:[SI+2]
  336.     test CH, ROUTE_SOURCE
  337.     jnz is_source
  338.     RIP_GET_ENTRY_in_AX_BX_out_SI_DI_const_AX_BX_CX_BP name, save_mask, found
  339.     jmp skip_source
  340. is_source:
  341.     mov DI, word ptr save_id
  342.     RIP_GET_SRC_ENTRY_in_AX_BX_DI_out_SI_DI_const_AX_BX_CX_BP name, save_mask, found
  343. skip_source:
  344.         cmp CL, 16
  345.         jae done
  346.         mov SI, word ptr rip_&name&_data.rip_table_ptr
  347.         look_for_empty:
  348.             add SI, size rip_entry
  349.             cmp SI, offset rip_&name&_data.rip_table_end
  350.             jb no_wrap
  351.                 mov SI, offset rip_&name&_data.rip_table
  352.             no_wrap:
  353.             test byte ptr [SI.re_flags], ROUTE_VALID
  354.             jz found_empty
  355.  
  356.             cmp SI, word ptr rip_&name&_data.rip_table_ptr
  357.             jnz look_for_empty
  358.             LOG_PRINT %mylog, L_SYS, L_ERR, <Routing table overflow>
  359.             jmp done
  360.         found_empty:
  361.         cmp SI, word ptr rip_&name&_data.rip_table_ptr
  362.         jbe not_bigger
  363.             mov word ptr rip_&name&_data.rip_table_ptr, SI
  364.         not_bigger:
  365.         mov [SI.re_prev], DI            ;; link this in last in the list
  366.         mov [DI.re_next], SI
  367.  
  368.         mov [SI+re_next], 0             ;; fill in next
  369.         mov word ptr [SI+re_net], AX
  370.         mov word ptr [SI+re_net+2], BX
  371.         mov AX, word ptr save_mask
  372.         mov BX, word ptr save_mask+2
  373.         mov word ptr [SI+re_mask], AX
  374.         mov word ptr [SI+re_mask+2], BX
  375.         or CH, ROUTE_VALID              ;; fill in flags
  376.         mov byte ptr [SI+re_flags], CH
  377.         mov AX, word ptr save_id
  378.         mov word ptr [SI+re_id], AX
  379.         test CH, ROUTE_SOURCE
  380.         jz add_new_gateway
  381.         jmp done
  382.  
  383.     delete_route:
  384.         RIP_DELETE_in_SI_const_BX_CX_DX_SI_BP name
  385.         jmp done
  386.  
  387.     found:
  388.         test [SI+re_flags], ROUTE_TRANS   ;; cant change a permanent route
  389.         jz done 
  390.  
  391.         mov DI, BP                          ;; restore DI
  392.         mov DX, ES:[DI]
  393.         cmp DX, [SI+re_gateway]
  394.         jnz new_route
  395.         mov DX, ES:[DI+2]
  396.         cmp DX, [SI+re_gateway+2]
  397.         jnz new_route
  398.             mov DL, 18
  399.             cmp CL, 16
  400.             jb no_delete
  401.                 cmp byte ptr [SI+re_timer], 0
  402.                 jbe no_timer
  403.                 xor DL, DL
  404.             no_delete:
  405.             mov byte ptr [SI+re_timer], DL
  406.             no_timer:
  407.             cmp CL, byte ptr [SI+re_metric]
  408.             je done
  409.             mov byte ptr [SI+re_metric], CL
  410.             jmp log_it
  411.         new_route:
  412.         cmp CL, [SI+re_metric]
  413.         jae done                            ;; old metric less, we are done
  414.  
  415.     add_new_gateway:
  416.     mov DI, BP                              ;; restore DI
  417.     mov byte ptr [SI+re_timer], 18
  418.     mov byte ptr [SI+re_metric], CL
  419.     mov AX, ES:[DI]
  420.     mov BX, ES:[DI+2]
  421.     mov word ptr [SI+re_gateway], AX
  422.     mov word ptr [SI+re_gateway+2], BX
  423.     mov byte ptr [SI+re_interface], 0       ;; Avoid finding this new route
  424.     RIP_FIND_IF_in_AX_BX_out_AX_BX_CL_const_SI_DI %rip_&name&_dls, delete_route
  425.     mov word ptr [SI+re_igateway], AX
  426.     mov word ptr [SI+re_igateway+2], BX
  427.     mov byte ptr [SI+re_interface], CL
  428.  
  429.     log_it:
  430.     LOG_PRINT %mylog, L_ROUTE, L_INFO, <Adding/updating route>
  431.     RIP_LOG_ROUTE_in_SI_const_all name, L_INFO
  432.     done:
  433.     mov DI, BP                          ;; restore DI
  434. ENDM
  435.  
  436.  
  437. ;;*****************************************************************************
  438. ;;   ROUTE_FIND_in_AX_BX_SI_DI_out_AX_BX_DX name, forme, fail, drop
  439. ;;      ROUTE_FIND takes the network number in the AX:BX pair and the
  440. ;;      source address in the SI:DI pair and does one of three things:
  441. ;;      If it is for this host it jumps to 'forme'.  If it could find
  442. ;;      no route it jumps to 'fail'. If it found a route that is declared
  443. ;;      as unreachable it jumps to 'drop'.  Otherwise outputs the
  444. ;;      interface in DL, the metric in DH and the gateway network number
  445. ;;      of where to send it to in AX:BX.
  446. ;;
  447. ROUTE_FIND_in_AX_BX_SI_DI_out_AX_BX_DX_const_CX_BP_ES MACRO name, forme, fail, drop
  448.     local found
  449.  
  450.     call route_&name&_real_find
  451.     or DI, DI
  452.     jz found
  453.     cmp DI, 2
  454.     ja fail
  455.     je forme
  456.     ifnb <drop>
  457.         jmp drop
  458.     endif
  459.     found:
  460. ENDM
  461.  
  462. ;;   ROUTE_REAL_FIND_in_AX_BX_SI_DI_out_AX_BX_DX_DI name
  463. ;;      ROUTE_REAL_FIND returns an error status in DI:
  464. ;;        0 = route was found
  465. ;;        1 = route was found but is declared as unreachable
  466. ;;        2 = the packet is for me
  467. ;;        3 = no route could be found
  468. ;;
  469. ROUTE_REAL_FIND_in_AX_BX_SI_DI_out_AX_BX_DX_DI_const_CX_BP_ES MACRO name
  470.     local found, not_direct, save_address, save_src_address, save_ptr
  471.     local forme, find_route, done, found_src, skip, skip1, not_found
  472.  
  473.     .DATA
  474. save_address    DD    ?
  475. save_src_address DD    ?
  476. save_ptr    DW    ?
  477.     .CODE
  478.  
  479.     irp idx, <1,2,3,4,5,6,7,8>
  480.     if idx le ip_&name&_dls
  481.         CHECK_FORME_in_AX_BX_out_DX_const_AX_BX_CX_BP_SI_DI_ES idx, forme
  482.     endif
  483.     endm
  484.     jmp find_route
  485.  
  486.     forme:
  487.     mov DI, 2
  488.     jmp done
  489.  
  490.     find_route:
  491.     mov word ptr save_address, AX
  492.     mov word ptr save_address+2, BX
  493.     mov word ptr save_src_address, SI
  494.     mov word ptr save_src_address+2, DI
  495.     RIP_GET_NET_ENTRY_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI %ip_&name&_router, found
  496.     RIP_GET_DEFAULT_ENTRY_out_SI_const_AX_BX_CX_BP_DI %ip_&name&_router, found
  497.  
  498.     not_found:
  499.     mov DI, 3
  500.     jmp done
  501.  
  502.     found:
  503.     mov AX, word ptr save_src_address
  504.     or AX, AX
  505.     jz skip1
  506.     mov BX, word ptr save_src_address+2
  507.     mov DI, word ptr [SI+re_id]
  508.     mov word ptr save_ptr, SI
  509.     RIP_GET_SRC_NET_ENTRY_in_AX_BX_DI_out_SI_const_AX_BX_CX_BP_DI %ip_&name&_router, %ip_&name&_dls, found_src
  510.     RIP_GET_SRC_DEFAULT_ENTRY_in_DI_out_SI_const_AX_BX_CX_BP_DI %ip_&name&_router, %ip_&name&_dls, found_src
  511.     jmp skip
  512.  
  513.     found_src:
  514.     test byte ptr [SI+re_flags], ROUTE_DENY
  515.     jnz not_found
  516.  
  517.     skip:
  518.     mov SI, word ptr save_ptr
  519.     skip1:
  520.     mov DX, word ptr [SI+re_interface]  ; load DL=interface DH=metric
  521.     cmp DH, 16
  522.     jae not_found
  523.     mov AX, [SI+re_igateway]
  524.     mov BX, [SI+re_igateway+2]
  525.     or DH, DH
  526.     jnz not_direct            ; For direct routes
  527.     mov AX, word ptr save_address    ;   gateway to destination address
  528.     mov BX, word ptr save_address+2 ;
  529.     not_direct:
  530.     xor DI, DI
  531.     test byte ptr [SI+re_flags], ROUTE_DROP
  532.     jz done
  533.     inc DI
  534.     done:
  535. ENDM
  536.  
  537. CHECK_FORME_in_AX_BX_out_DX_const_AX_BX_CX_BP_SI_DI_ES MACRO name, forme
  538.     local not_for_me
  539.  
  540.     cmp AX, word ptr dl_ip_&name&_ip
  541.     jne not_for_me
  542.     cmp BX, word ptr dl_ip_&name&_ip+2
  543.     jne not_for_me
  544.         mov DL, name
  545.             xor DH, DH
  546.         jmp forme
  547.     not_for_me:
  548. ENDM
  549.  
  550.  
  551. ;;**************************************************************************
  552. ;; RIP_TASK is the code that sends RIP packets to the interfaces every
  553. ;; 30 seconds.  It splits the 30 second interval in equal parts and does
  554. ;; one interface at a time.  This causes a more balanced load on the
  555. ;; router.
  556. ;;
  557. RIP_TASK MACRO name
  558.     local timer_code, rip_loop, set_timer, no_wrap
  559.     local rip_dl_count, rip_dl_init
  560.  
  561.     .DATA
  562. rip_dl_count      DB  rip_&name&_dls
  563. rip_dl_init       DB  1
  564.  
  565.     .CODE
  566.     timer_code:
  567.     rip_loop:
  568.         xor AX, AX
  569.         mov BX, AX
  570.         mov CX, RIP_PORT
  571.         mov DL, byte ptr rip_dl_count
  572.         RIP_SEND_in_AX_BX_CX_DL name
  573.  
  574.         mov DL, byte ptr rip_dl_count
  575.         dec DL
  576.         jnz no_wrap
  577.         mov byte ptr rip_dl_count, rip_&name&_dls
  578.         mov byte ptr rip_dl_init, 0
  579.         jmp set_timer
  580.  
  581.     no_wrap:
  582.         mov byte ptr rip_dl_count, DL
  583.         cmp byte ptr rip_dl_init, 1         ;; do all interfaces the first time
  584.         je rip_loop
  585.  
  586.     set_timer:
  587.         mov AX, 18*30/rip_&name&_dls        ;; resubmit the task
  588.         TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, timer_code
  589. ENDM
  590.  
  591.  
  592. ;;*****************************************************************************
  593. ;;  RIP_SEND_in_AX_BX_CX_DX sends the contents of the routing table as
  594. ;;  RIP packets to the IP address in AX:BX and the UDP port in CX.
  595. ;;  DL contains the number of the interface the packets should be sent to.
  596. ;;  If DL is zero no RIP packets are sent but instead an expire of the
  597. ;;  routing table is performed.
  598. ;;
  599. RIP_SEND_in_AX_BX_CX_DL MACRO name
  600.     call rip_&name&_send_code
  601. ENDM
  602.  
  603.  
  604. ;;*****************************************************************************
  605. ;;  RIP_INIT_DL_LABEL generates a code lable for use in a jump table for
  606. ;;  'name', 'dl'.  'suffix' is a unique suffix
  607. ;;
  608. RIP_INIT_DL_LABEL MACRO name, dl, suffix
  609.     rip_&name&_dl_&dl&_&suffix:
  610. ENDM
  611.  
  612. ;;*****************************************************************************
  613. ;;  RIP_INIT_DL_JMP_TAB generates the table entry for the entry 'name', 'dl'
  614. ;;  'suffix' is a unique suffix.
  615. ;;  This is meant for use in a .DATA section 
  616. ;;
  617. RIP_INIT_DL_JMP_TAB MACRO name, dl, suffix
  618.     dw rip_&name&_dl_&dl&_&suffix
  619. ENDM
  620.  
  621.  
  622. ;;**************************************************************************
  623. ;; RIP_SEND_DL generates all the RIP packets for the data link interface 'mydl'
  624. ;;
  625. RIP_SEND_DL MACRO name, mydl
  626.     local done, pack_loop, no_bcast, skip
  627.     .errb <mydl>
  628.  
  629.     cmp word ptr rip_&name&_data.rip_udp_port, RIP_PORT
  630.     jne skip
  631.     test word ptr dl_ip_&mydl&_flags, (ROUTE_SEND_RIP) or (ROUTE_SEND_DEFROUTE)
  632.     jz done                         ;; skip silent ifs 
  633.  
  634.     skip:
  635.     mov AX, word ptr dl_ip_&mydl&_net
  636.     mov BX, word ptr dl_ip_&mydl&_net+2
  637.     IP_COMP_NET_in_AX_BX_out_AX_BX_const_CX_DX_BP_SI_DI_ES
  638.     mov word ptr rip_&name&_data.rip_if_net, AX
  639.     mov word ptr rip_&name&_data.rip_if_net+2, BX
  640.  
  641.     RIP_INIT_ENTRY_out_SI_const_AX_BX_CX_DX_BP_DI name
  642.     mov rip_&name&_data.rip_pack_out, SI
  643.     pack_loop:
  644.         mov CX, 512                 ;; maximum RIP packet size
  645.         mov DX, word ptr rip_&name&_data.rip_udp_port
  646.         mov AX, word ptr rip_&name&_data.rip_target
  647.         mov BX, word ptr rip_&name&_data.rip_target+2
  648.         or AX, AX
  649.         jnz no_bcast
  650.         or BX, BX
  651.         jnz no_bcast
  652.             mov AX, word ptr dl_ip_&mydl&_broad
  653.             mov BX, word ptr dl_ip_&mydl&_broad+2
  654.         no_bcast:
  655.  
  656.         UDP_SOCK_W_ACCESS_in_AX_BX_CX_DX_out_AX_DI_ES %rip_&name&_udp_sock
  657.         cmp AX, 0
  658.         jnz done
  659.  
  660.         mov DX, word ptr dl_ip_&mydl&_metric
  661.         mov SI, rip_&name&_data.rip_pack_out
  662.         RIP_MAKE_PACKET_in_DX_SI_DI_out_CX_SI name, mydl, rip_&name&_data.rip_if_net, done
  663.         mov rip_&name&_data.rip_pack_out, SI
  664.  
  665.         UDP_SOCK_W_WRITE_in_CX %rip_&name&_udp_sock
  666.     jmp pack_loop
  667.     done:
  668. ENDM
  669.  
  670.  
  671. ;;**************************************************************************
  672. ;; RIP_DELETE_in_SI_const_BX_CX_DX_SI_BP deletes the entry pointed by by SI
  673. ;;
  674. RIP_DELETE_in_SI_const_BX_CX_DX_SI_BP MACRO name
  675.     local end_of_list
  676.  
  677.     mov byte ptr [SI+re_flags], 0       ;; make the route invalid
  678.     mov DI, [SI+re_prev]
  679.     mov AX, [SI+re_next]
  680.     mov [DI.re_next], AX
  681.     or AX, AX
  682.     jz end_of_list
  683.         xchg AX, DI
  684.         mov [DI+re_prev], AX
  685.     end_of_list:
  686. ENDM
  687.  
  688.  
  689. ;;**************************************************************************
  690. ;; RIP_EXPIRE should be called every 10 seconds.  This routine decrements
  691. ;; the timer entries on the routes and expires the routes after 180 seconds.
  692. ;;
  693. RIP_EXPIRE_const_BX_CX_DX_BP MACRO name
  694.     local expire_code, expire_loop, done, invalidate_route
  695.     .errb <name>
  696.  
  697.     expire_code:
  698.     RIP_INIT_ENTRY_out_SI_const_AX_BX_CX_DX_BP_DI name
  699.     expire_loop:
  700.         RIP_NEXT_ENTRY_in_SI_out_SI_const_AX_BX_CX_DX_BP_DI name, done
  701.         test [SI+re_flags], ROUTE_TRANS      ;; don't expire permenent routes
  702.         jz expire_loop
  703.  
  704.         sub [SI+re_timer], 1                 ;; decrement the timer
  705.         jg expire_loop
  706.         jz invalidate_route
  707.                 ;; check to see if we should purge it from the table
  708.             cmp [SI+re_timer], -12
  709.             jg expire_loop
  710.                 LOG_PRINT %mylog, L_ROUTE, L_INFO, <Deleting expired route>
  711.                 RIP_LOG_ROUTE_in_SI_const_all name, L_INFO
  712.                 RIP_DELETE_in_SI_const_BX_CX_DX_SI_BP name
  713.                 jmp expire_loop
  714.         invalidate_route:
  715.                 ;; delete the route
  716.             mov [SI+re_metric], 16
  717.             LOG_PRINT %mylog, L_ROUTE, L_INFO, <Invalidating expired route>
  718.             RIP_LOG_ROUTE_in_SI_const_all name, L_INFO
  719.             jmp expire_loop
  720.     done:
  721.         mov AX, 18*10                       ;; resubmit the task
  722.         TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, expire_code
  723. ENDM
  724.  
  725.  
  726. ;;**************************************************************************
  727. ;; RIP_PROCESS_PACKET processes the packet in ES:SI.  The IP address of
  728. ;; the gateway that sent the packet is pointed to by ES:DI.  CX holds
  729. ;; the length of the RIP part of the packet
  730.  
  731. RIP_PROCESS_PACKET_in_CX_SI_DI_ES MACRO name
  732.     local process_loop, done, next, if_flags, skip, version, is_reply
  733.     local no_check1, no_check2, jmp_table, rip_length, store_flags
  734.     local src_dl, save_ptr, is_def_route
  735.  
  736.     .DATA
  737. jmp_table  dw   done
  738.     IRP idx, <1,2,3,4,5,6,7,8>
  739.     if idx le rip_&name&_dls
  740.         RIP_INIT_DL_JMP_TAB name, idx, load_flags
  741.     endif
  742.     endm
  743.  
  744. if_flags        DW  ?
  745. rip_length      DW  ?
  746. save_ptr        DW  ?
  747. src_dl          DB  ?
  748. version         DB  ?
  749.     .CODE
  750.  
  751.     mov AL, byte ptr ES:[SI+rip_version]
  752.     cmp AL, RIP_VER
  753.     jl done
  754.     jg no_check1                ;; don't check zeros with later RIP versions
  755.     cmp word ptr ES:[SI+rip_zero1], 0
  756.     jnz done
  757.     no_check1:
  758.     mov byte ptr version, AL
  759.  
  760.     mov word ptr rip_length, CX ;; save packet length
  761.     mov AX, word ptr ES:[DI]    ;; find DL for source IP address
  762.     mov BX, word ptr ES:[DI+2]
  763.     RIP_FIND_IF_in_AX_BX_out_AX_BX_CL_const_SI_DI rip_&name&_dls, done
  764.     cmp AX, word ptr ES:[DI]    ;; hack! if address has changed, the sender
  765.     jnz done                    ;; is not on a directly connected network
  766.     cmp BX, word ptr ES:[DI+2]
  767.     jnz done                    ;; is not on a directly connected network
  768.     mov word ptr save_ptr, DI   ;; save IP address pointer
  769.     mov byte ptr src_dl, CL
  770.     xor CH, CH                  ;; set up jump to proper DL
  771.     shl CX, 1
  772.     mov DI, offset jmp_table
  773.     add DI, CX
  774.     jmp [DI]                    ;; jump to proper DL
  775.  
  776.         ;; the above jump goes to one of the code fragments below
  777.     IRP idx, <1,2,3,4,5,6,7,8>
  778.     if idx le rip_&name&_dls
  779.         RIP_INIT_DL_LABEL name, idx, load_flags
  780.  
  781.         RIP_LOAD_FLAGS idx      ;; load DX with the flags for this DL
  782.         jmp store_flags
  783.     endif
  784.     endm
  785.         ;; the above code does NOT fall through
  786.  
  787.     store_flags:
  788.     mov word ptr if_flags, DX
  789.     mov CX, word ptr rip_length ;; restore packet length
  790.     mov DI, word ptr save_ptr   ;; restore IP address pointer
  791.  
  792.     mov AL, byte ptr ES:[SI+rip_command]
  793.     cmp AL, RIP_REPLY
  794.     jz is_reply
  795.     cmp AL, RIP_REQUEST
  796.     jnz done
  797.     cmp CX, 24                       ;; exactly one entry?
  798.     jne done
  799.     cmp word ptr ES:[SI+rip_family+4], 0
  800.     jnz done
  801.     cmp byte ptr ES:[SI+rip_metric+7], 16
  802.     jnz done
  803.     mov AX, word ptr ES:[DI]
  804.     mov BX, word ptr ES:[DI+2]
  805.     sub SI, size udp
  806.     mov CX, word ptr ES:[SI+udp_src]
  807.     xchg CH, CL
  808.     mov DL, byte ptr src_dl
  809.     RIP_SEND_in_AX_BX_CX_DL name
  810.     jmp done
  811.  
  812.     is_reply:
  813.     test word ptr if_flags, (ROUTE_LISTEN_RIP) or (ROUTE_LISTEN_DEFROUTE)
  814.     jz done
  815.         sub SI, size udp
  816.         cmp word ptr ES:[SI+udp_src], SWAPPED_RIP_PORT
  817.         jnz done            ;; don't accept RIP updates from other UDP ports
  818.         add SI, (size udp)+4
  819.         sub CX, 4
  820.         process_loop:
  821.             sub CX, 20
  822.             jb done
  823.  
  824.             cmp word ptr ES:[SI+rip_family], SWAPPED_IP_FAMILY
  825.             jnz next
  826.             cmp byte ptr version, RIP_VER
  827.             jg no_check2          ;; don't check zeros with later RIP versions
  828.             xor DX, DX
  829.             cmp word ptr ES:[SI+rip_zero2], DX
  830.             jnz next
  831.             cmp word ptr ES:[SI+rip_zero3], DX
  832.             jnz next
  833.             cmp word ptr ES:[SI+rip_zero3+2], DX
  834.             jnz next
  835.             cmp word ptr ES:[SI+rip_zero4], DX
  836.             jnz next
  837.             cmp word ptr ES:[SI+rip_zero4+2], DX
  838.             jnz next
  839.  
  840.           no_check2:
  841.             mov DX, word ptr ES:[SI+rip_address]    ;; check for default route
  842.             or DX, word ptr ES:[SI+rip_address+2]
  843.             jz is_def_route
  844.             test word ptr if_flags, ROUTE_LISTEN_RIP
  845.             jz next
  846.             jmp skip
  847.  
  848.           is_def_route:
  849.             test word ptr if_flags, ROUTE_LISTEN_DEFROUTE
  850.             jz next
  851.  
  852.             skip:
  853.                 mov word ptr rip_&name&_data.rip_pack_ctr, CX
  854.                 mov word ptr rip_&name&_data.rip_pack_ptr, SI
  855.                 mov CL, byte ptr ES:[SI+rip_metric+3]
  856.                 mov CH, ROUTE_TRANS
  857.                 add SI, rip_address
  858.                 xor DX, DX
  859.                 mov AL, byte ptr src_dl
  860.                 xor AH, AH
  861.                 inc AX
  862.                 ROUTE_ADD_in_AX_CX_DX_SI_DI_ES_const_DI_ES name
  863.                 mov CX, word ptr rip_&name&_data.rip_pack_ctr
  864.                 mov SI, word ptr rip_&name&_data.rip_pack_ptr
  865.     
  866.             next:
  867.                 add SI, 20
  868.         jmp process_loop
  869.     done:
  870. ENDM
  871.  
  872. RIP_LOAD_FLAGS MACRO dl
  873.     mov DX, word ptr dl_ip_&dl&_flags
  874. ENDM
  875.  
  876.  
  877. ;;**************************************************************************
  878. ;; RIP_SEND_REQUEST sends a RIP request to interface 'mydl'.
  879. ;;
  880. RIP_SEND_REQUEST MACRO name, mydl
  881.     local done
  882.     .errb <mydl>
  883.  
  884.     test word ptr dl_ip_&mydl&_flags, (ROUTE_LISTEN_RIP) or (ROUTE_LISTEN_DEFROUTE)
  885.     jz done                     ;; skip deaf ifs 
  886.     mov AX, word ptr dl_ip_&mydl&_broad
  887.     mov BX, word ptr dl_ip_&mydl&_broad+2
  888.     mov CX, 24                  ;; RIP request packet size
  889.     mov DX, RIP_PORT
  890.  
  891.     UDP_SOCK_W_ACCESS_in_AX_BX_CX_DX_out_AX_DI_ES %rip_&name&_udp_sock
  892.     cmp AX, 0
  893.     jnz done
  894.  
  895.         ;; make up header
  896.     mov AL, RIP_REQUEST             ;; this is a request packet
  897.     stosb
  898.     mov AL, 1                       ;; version 1
  899.     stosb
  900.     xor AX, AX                      ;; must be 0
  901.     stosw
  902.  
  903.     stosw
  904.     stosw
  905.     stosw
  906.     stosw
  907.     stosw
  908.     stosw
  909.     stosw
  910.     stosw
  911.  
  912.     stosw                           ;; 4 bytes of metric
  913.     mov AH, 16
  914.     stosw
  915.  
  916.     mov CX, 24                  ;; RIP request packet size
  917.     UDP_SOCK_W_WRITE_in_CX %rip_&name&_udp_sock
  918.     done:
  919. ENDM
  920.  
  921.  
  922. ;;**************************************************************************
  923. ;; RIP_MAKE_PACKET generates a RIP packet in DI:ES for the interface 'mydl'
  924. ;; by calling accessing the routing table by means of RIP_NEXT_ENTRY.  
  925. ;; Thus it assumes SI has been initialized with RIP_INIT_ENTRY or is
  926. ;; a continuation of a RIP_NEXT_ENTRY.  CX is set to the length of the 
  927. ;; packet.  It jumps to 'dont_send' when there is not data to send out, so
  928. ;; that the packet should not be sent.  DX contains the metric for the
  929. ;; interface.  'if_net' is a pointer to the network part (not assuming
  930. ;; subnets, that is based strictly on the class of the address).  This
  931. ;; is used to implement the subnet hiding.
  932.  
  933. RIP_MAKE_PACKET_in_DX_SI_DI_out_CX_SI MACRO name, mydl, if_net, dont_send
  934.     local route_loop, packet_full, metric_ok, not_default, skip, skip1
  935.     local skip1a, skip2, skip3, check_route
  936.     local send_full_route, not_same_subnet, not_last, send_metric
  937.     .errb <dont_send>
  938.  
  939.         ;; make up header
  940.     mov AL, RIP_REPLY               ;; this is a reply packet
  941.     stosb
  942.     mov AL, RIP_VER                 ;; RIP version
  943.     stosb
  944.     xor AX, AX                      ;; must be 0
  945.     stosw
  946.     dec AX                          ;; AX now = -1
  947.     mov word ptr rip_&name&_data.rip_if_last, AX
  948.     mov word ptr rip_&name&_data.rip_if_last+2, AX
  949.     mov CX, 4
  950.     route_loop:
  951.         cmp word ptr rip_&name&_data.rip_hr_count, 0
  952.         jne check_route
  953.  
  954.         RIP_NEXT_ENTRY_in_SI_out_SI_const_AX_BX_CX_DX_BP_DI name, packet_full
  955.         test byte ptr [SI+re_flags], (ROUTE_SILENT) or (ROUTE_SOURCE)
  956.         jnz route_loop
  957.  
  958.       check_route:
  959.         xor DH, DH                                     ;; clear reverse poison
  960.         cmp byte ptr [SI+re_interface], mydl           ;; split horizon
  961.         jnz skip
  962.         test word ptr dl_ip_&mydl&_flags, ROUTE_POISON_REVERSE
  963.         jz route_loop
  964.         mov DH, 16                                     ;; set reverse poison
  965.  
  966.       skip:
  967.         mov AX, word ptr [SI+re_net]         ;; the destination network
  968.         mov BX, word ptr [SI+re_net+2] 
  969.         or AX, AX
  970.         jnz not_default
  971.         or BX, BX
  972.         jnz not_default
  973.         cmp word ptr rip_&name&_data.rip_udp_port, RIP_PORT
  974.         jne skip3
  975.         test word ptr dl_ip_&mydl&_flags, ROUTE_SEND_DEFROUTE
  976.         jz route_loop
  977.         jmp skip3
  978.  
  979.       not_default:
  980.         cmp word ptr rip_&name&_data.rip_udp_port, RIP_PORT
  981.         jne skip1
  982.         test word ptr dl_ip_&mydl&_flags, ROUTE_SEND_RIP
  983.         jz route_loop
  984.  
  985.       skip1:
  986.         cmp word ptr rip_&name&_data.rip_hr_count, 0
  987.         je skip2
  988.       skip1a:
  989.         mov AX, SWAPPED_IP_FAMILY            ;; Address family
  990.         stosw
  991.         xor AX, AX                           ;; two bytes of zero
  992.         stosw
  993.         mov AX, word ptr [SI+re_net]         ;; the destination network
  994.         stosw
  995.         mov AX, word ptr [SI+re_net+2]
  996.         xchg AH, AL
  997.         add AX, word ptr rip_&name&_data.rip_hr_count
  998.         dec word ptr rip_&name&_data.rip_hr_count
  999.         xchg AH, AL
  1000.         stosw
  1001.         jmp send_metric
  1002.  
  1003.       skip2:
  1004.         test byte ptr [SI+re_flags], ROUTE_SPLIT
  1005.         jz skip3
  1006.         mov AX, word ptr [SI+re_mask+2]
  1007.         xchg AH, AL
  1008.         xor AX, 0ffffh
  1009.         cmp AX, MAX_HOST_SPLIT
  1010.         jge route_loop
  1011.         cmp AX, 3
  1012.         jl route_loop
  1013.         dec AX
  1014.         mov word ptr rip_&name&_data.rip_hr_count, AX
  1015.         jmp skip1a
  1016.  
  1017.             ;; this code implements the hiding of subnet info outside 
  1018.             ;; the subnet
  1019.       skip3:
  1020.         IP_COMP_NET_in_AX_BX_out_AX_BX_const_CX_DX_BP_SI_DI_ES
  1021.         cmp AX, word ptr if_net
  1022.         jnz not_same_subnet
  1023.         cmp BX, word ptr if_net+2
  1024.         jz send_full_route
  1025.             not_same_subnet:
  1026.             cmp AX, word ptr rip_&name&_data.rip_if_last
  1027.             jnz not_last
  1028.             cmp BX, word ptr rip_&name&_data.rip_if_last+2
  1029.             jz route_loop
  1030.             not_last:
  1031.                 mov word ptr rip_&name&_data.rip_if_last, AX
  1032.                 mov word ptr rip_&name&_data.rip_if_last+2, BX
  1033.  
  1034.                 mov AX, SWAPPED_IP_FAMILY            ;; Address family
  1035.                 stosw
  1036.                 xor AX, AX                           ;; two bytes of zero
  1037.                 stosw
  1038.                 mov AX, word ptr rip_&name&_data.rip_if_last
  1039.                 stosw
  1040.                 mov AX, word ptr rip_&name&_data.rip_if_last+2
  1041.                 stosw
  1042.                 jmp send_metric
  1043.  
  1044.         send_full_route:
  1045.         mov AX, SWAPPED_IP_FAMILY            ;; Address family
  1046.         stosw
  1047.         xor AX, AX                           ;; two bytes of zero
  1048.         stosw
  1049.         mov AX, word ptr [SI+re_net]         ;; the destination network
  1050.         stosw
  1051.         mov AX, word ptr [SI+re_net+2]
  1052.         stosw
  1053.  
  1054.         send_metric:
  1055.         xor AX, AX                           ;; 8 zero bytes
  1056.         stosw
  1057.         stosw
  1058.         stosw
  1059.         stosw
  1060.         stosw                               ;; 4 bytes of metric
  1061.         mov AH, [SI+re_metric]   
  1062.         add AH, DL                          ;; add in the interface metric
  1063.         add AH, DH                          ;; add in the reverse poison
  1064.         cmp AH, 16
  1065.         jbe metric_ok
  1066.             mov AH, 16
  1067.         metric_ok:
  1068.         stosw
  1069.  
  1070.         add CX, 20
  1071.         cmp CX, 512-20                  ;; is there space for another entry
  1072.         ja packet_full
  1073.     jmp route_loop
  1074.  
  1075.     packet_full:
  1076.     cmp CX, 4
  1077.     jz dont_send
  1078. ENDM
  1079.  
  1080.  
  1081.  
  1082. ;;**************************************************************************
  1083. ;; RIP_INIT_ENTRY initilizes SI so that RIP_NEXT_ENTRY works.  When
  1084. ;; RIP_NEXT_ENTRY is called, SI will point to the first entry of the
  1085. ;; routing table.  This may seem a bit bizarre that RIP_NEXT_ENTRY MUST
  1086. ;; be called immediately after RIP_INIT_ENTRY, but it actually makes
  1087. ;; loops easier to construct.
  1088.  
  1089. RIP_INIT_ENTRY_out_SI_const_AX_BX_CX_DX_BP_DI MACRO name
  1090.     .errb <name>
  1091.  
  1092.     mov SI, offset (rip_&name&_data.rip_table - (size rip_entry))
  1093. ENDM
  1094.  
  1095.  
  1096. ;;**************************************************************************
  1097. ;; RIP_NEXT_ENTRY gets the next entry in the table and returns it in
  1098. ;; SI.  NOTE: SI must be unchanged from the last RIP_INIT_ENTRY or
  1099. ;; RIP_NEXT_ENTRY for this function to work.  It jumps to 'done' if 
  1100. ;; there are no more entries.
  1101. ;;
  1102. RIP_NEXT_ENTRY_in_SI_out_SI_const_AX_BX_CX_DX_BP_DI MACRO name, done
  1103.     local search_loop
  1104.     .errb <done>
  1105.  
  1106.     search_loop:
  1107.         add SI, size rip_entry
  1108.         cmp SI, word ptr rip_&name&_data.rip_table_ptr
  1109.         ja done
  1110.         test [SI+re_flags], ROUTE_VALID
  1111.     jz search_loop
  1112. ENDM
  1113.  
  1114.  
  1115. ;;**************************************************************************
  1116. ;; RIP_GET_ENTRY gets the table entry for the address in the AX:BX
  1117. ;; pair and returns a pointer to it in SI. DI returns the pointer to
  1118. ;; the previous entry in the list (useful for insertions and deletions)
  1119. ;; 'netmask' is the name of a memory location where the netmask of the
  1120. ;; address in AX:BX is stored. If an entry for AX:BX is found, the netmask
  1121. ;; in 'netmask' is compared with the netmask of the entry in order to
  1122. ;; determine whether the found entry is of the proper type.
  1123. ;; RIP_GET_ENTRY jumps to 'found' if the host entry could be found.
  1124. ;; If it is not found only DI is valid (SI will be 0).
  1125. ;;
  1126. RIP_GET_ENTRY_in_AX_BX_out_SI_DI_const_AX_BX_CX_BP MACRO name, netmask, found
  1127.     local start, next, search_loop, failed
  1128.     .errb <found>
  1129.  
  1130.     RIP_COMP_HASH_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI_ES name
  1131.  
  1132.     jmp start
  1133.     search_loop:
  1134.         cmp AX, word ptr [SI+re_net]
  1135.         jnz next
  1136.         cmp BX, word ptr [SI+re_net+2]
  1137.         jnz next
  1138.         mov DX, word ptr netmask
  1139.         cmp DX, word ptr [SI+re_mask]
  1140.         jnz next
  1141.         mov DX, word ptr netmask+2
  1142.         cmp DX, word ptr [SI+re_mask+2]
  1143.         jnz next
  1144.         cmp byte ptr [SI+re_interface], 0
  1145.         jne found
  1146.     next:
  1147.     start:
  1148.         mov DI, SI
  1149.         mov SI, [SI+re_next]
  1150.         or SI, SI 
  1151.         jz failed
  1152.         test byte ptr [SI+re_flags], ROUTE_SOURCE
  1153.         jnz next
  1154.         jmp search_loop
  1155.     failed:
  1156. ENDM
  1157.  
  1158.  
  1159. ;;**************************************************************************
  1160. ;; RIP_GET_NET_ENTRY gets the table entry with the narrowest netmask for
  1161. ;; the address in the AX:BX pair and returns a pointer to it in SI.
  1162. ;; It jumps to 'found' if a matching entry could be found.  If none is
  1163. ;; found SI will be 0.
  1164. ;;
  1165. RIP_GET_NET_ENTRY_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI MACRO name, found
  1166.     local start, next, search_loop, narrow_mask, narrow_ptr, narrow, done
  1167.     .errb <found>
  1168.  
  1169.     .DATA
  1170. narrow_mask    DD    ?
  1171. narrow_ptr    DW    ?
  1172.     .CODE
  1173.  
  1174.     xor DX, DX
  1175.     mov word ptr narrow_ptr, DX
  1176.     not DX
  1177.     mov word ptr narrow_mask, DX
  1178.     mov word ptr narrow_mask+2, DX
  1179.  
  1180.     RIP_COMP_HASH_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI_ES name
  1181.  
  1182.     jmp start
  1183.     search_loop:
  1184.         mov DX, AX
  1185.         and DX, word ptr [SI+re_mask]
  1186.         cmp DX, word ptr [SI+re_net]
  1187.         jnz next
  1188.         mov DX, BX
  1189.         and DX, word ptr [SI+re_mask+2]
  1190.         cmp DX, word ptr [SI+re_net+2]
  1191.         jnz next
  1192.         mov DX, word ptr narrow_mask
  1193.         and DX, word ptr [SI+re_mask]
  1194.         jnz narrow
  1195.         mov DX, word ptr narrow_mask+2
  1196.         and DX, word ptr [SI+re_mask+2]
  1197.         jz next
  1198.     narrow:
  1199.         cmp byte ptr [SI+re_interface], 0
  1200.         je next
  1201.         mov word ptr narrow_ptr, SI
  1202.         mov DX, word ptr [SI+re_mask]
  1203.         not DX
  1204.         mov word ptr narrow_mask, DX
  1205.         mov DX, word ptr [SI+re_mask+2]
  1206.         not DX
  1207.         mov word ptr narrow_mask+2, DX
  1208.     next:
  1209.     start:
  1210.         mov SI, word ptr [SI+re_next]
  1211.         or SI, SI 
  1212.         jz done
  1213.         test byte ptr [SI+re_flags], ROUTE_SOURCE
  1214.         jnz next
  1215.         jmp search_loop
  1216.     done:
  1217.         or SI, word ptr narrow_ptr
  1218.         jnz found
  1219. ENDM
  1220.  
  1221.  
  1222. ;;**************************************************************************
  1223. ;; RIP_GET_DEFAULT_ENTRY gets the default table entry and returns a pointer
  1224. ;; to it in SI.
  1225. ;; It jumps to 'found' if the default entry could be found.  If it is
  1226. ;; not found SI will be 0.
  1227. ;;
  1228. RIP_GET_DEFAULT_ENTRY_out_SI_const_AX_BX_CX_BP_DI MACRO name, found
  1229.     local start, done, next, search_loop, failed
  1230.     .errb <found>
  1231.  
  1232.     xor DX,DX
  1233.     mov SI, offset rip_&name&_data.rip_hash
  1234.  
  1235.     jmp start
  1236.     search_loop:
  1237.         cmp DX, word ptr [SI+re_net]
  1238.         jnz next
  1239.         cmp DX, word ptr [SI+re_net+2]
  1240.         jnz next
  1241.         cmp DL, byte ptr [SI+re_interface]
  1242.         jne found
  1243.     next:
  1244.     start:
  1245.         mov SI, [SI+re_next]
  1246.         or SI, SI 
  1247.         jz failed
  1248.         test byte ptr [SI+re_flags], ROUTE_SOURCE
  1249.         jnz next
  1250.         jmp search_loop
  1251.     failed:
  1252. ENDM
  1253.  
  1254.  
  1255. ;;**************************************************************************
  1256. ;; RIP_GET_SRC_ENTRY gets the table entry for the source address in the
  1257. ;; AX:BX pair and returns a pointer to it in SI. DI returns the pointer to
  1258. ;; the previous entry in the list (useful for insertions and deletions).
  1259. ;; 'netmask' is the name of a memory location where the netmask of the
  1260. ;; address in AX:BX is stored and DI contains the route id. If an entry
  1261. ;; for DI and AX:BX is found, the netmask in 'netmask' is compared with
  1262. ;; the netmask of the entry in order to determine whether the found entry
  1263. ;; is of the proper type.
  1264. ;; RIP_GET_SRC_ENTRY jumps to 'found' if the source entry could be found.
  1265. ;; If it is not found only DI is valid (SI will be 0).
  1266. ;;
  1267. RIP_GET_SRC_ENTRY_in_AX_BX_DI_out_SI_DI_const_AX_BX_CX_BP MACRO name, netmask, found
  1268.     local start, next, search_loop, failed
  1269.     .errb <found>
  1270.  
  1271.     push CX
  1272.     mov CX, DI
  1273.  
  1274.     RIP_COMP_HASH_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI_ES name
  1275.  
  1276.     jmp start
  1277.     search_loop:
  1278.         cmp CX, word ptr [SI+re_id]
  1279.         jnz next
  1280.         cmp AX, word ptr [SI+re_net]
  1281.         jnz next
  1282.         cmp BX, word ptr [SI+re_net+2]
  1283.         jnz next
  1284.         mov DX, word ptr netmask
  1285.         cmp DX, word ptr [SI+re_mask]
  1286.         jnz next
  1287.         mov DX, word ptr netmask+2
  1288.         cmp DX, word ptr [SI+re_mask+2]
  1289.         jnz next
  1290.         pop CX
  1291.         jmp found
  1292.     next:
  1293.     start:
  1294.         mov DI, SI
  1295.         mov SI, [SI+re_next]
  1296.         or SI, SI 
  1297.         jz failed
  1298.         test byte ptr [SI+re_flags], ROUTE_SOURCE
  1299.         jz next
  1300.         jmp search_loop
  1301.     failed:
  1302.         pop CX
  1303. ENDM
  1304.  
  1305.  
  1306. ;;**************************************************************************
  1307. ;; RIP_GET_SRC_NET_ENTRY gets the table entry with the narrowest netmask for
  1308. ;; the source address in the AX:BX pair and the route id in DI and returns
  1309. ;; a pointer to it in SI.
  1310. ;; It jumps to 'found' if a matching entry could be found.  If none is
  1311. ;; found SI will be 0.
  1312. ;;
  1313. RIP_GET_SRC_NET_ENTRY_in_AX_BX_DI_out_SI_const_AX_BX_CX_BP_DI MACRO name, dls, found
  1314.     local start, next, search_loop, last_mask, last_id
  1315.     local narrow_mask, narrow_ptr, narrow
  1316.     local done, match
  1317.     .errb <found>
  1318.  
  1319.     .DATA
  1320. last_mask    DD    ?
  1321. narrow_mask    DD    ?
  1322. narrow_ptr    DW    ?
  1323. last_id        DW    ?
  1324.     .CODE
  1325.  
  1326.     xor DX, DX
  1327.     mov word ptr narrow_ptr, DX
  1328.     mov word ptr last_mask, DX
  1329.     mov word ptr last_mask+2, DX
  1330.     mov word ptr last_id, DX
  1331.     not DX
  1332.     mov word ptr narrow_mask, DX
  1333.     mov word ptr narrow_mask+2, DX
  1334.  
  1335.     RIP_COMP_HASH_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI_ES name
  1336.  
  1337.     jmp start
  1338.     search_loop:
  1339.         mov DX, word ptr [SI+re_id]
  1340.         cmp DI, DX
  1341.         jz match
  1342.         cmp DX, 1
  1343.         jg next
  1344.         jl match
  1345.         cmp DI, dls+1
  1346.         jg next
  1347.     match:
  1348.         mov DX, AX
  1349.         and DX, word ptr [SI+re_mask]
  1350.         cmp DX, word ptr [SI+re_net]
  1351.         jnz next
  1352.         mov DX, BX
  1353.         and DX, word ptr [SI+re_mask+2]
  1354.         cmp DX, word ptr [SI+re_net+2]
  1355.         jnz next
  1356.         mov DX, word ptr narrow_mask
  1357.         and DX, word ptr [SI+re_mask]
  1358.         jnz narrow
  1359.         mov DX, word ptr narrow_mask+2
  1360.         and DX, word ptr [SI+re_mask+2]
  1361.         jnz narrow
  1362.         mov DX, word ptr last_mask
  1363.         cmp DX, word ptr [SI+re_mask]
  1364.         jnz next
  1365.         mov DX, word ptr last_mask+2
  1366.         cmp DX, word ptr [SI+re_mask+2]
  1367.         jnz next
  1368.         mov DX, word ptr last_id
  1369.         cmp DX, word ptr [SI+re_id]
  1370.         jg next
  1371.     narrow:
  1372.         mov word ptr narrow_ptr, SI
  1373.         mov DX, word ptr [SI+re_mask]
  1374.         mov word ptr last_mask, DX
  1375.         not DX
  1376.         mov word ptr narrow_mask, DX
  1377.         mov DX, word ptr [SI+re_mask+2]
  1378.         mov word ptr last_mask+2, DX
  1379.         not DX
  1380.         mov word ptr narrow_mask+2, DX
  1381.         mov DX, word ptr [SI+re_id]
  1382.         mov word ptr last_id, DX
  1383.     next:
  1384.     start:
  1385.         mov SI, word ptr [SI+re_next]
  1386.         or SI, SI 
  1387.         jz done
  1388.         test byte ptr [SI+re_flags], ROUTE_SOURCE
  1389.         jz next
  1390.         jmp search_loop
  1391.     done:
  1392.         or SI, word ptr narrow_ptr
  1393.         jnz found
  1394. ENDM
  1395.  
  1396.  
  1397. ;;**************************************************************************
  1398. ;; RIP_GET_SRC_DEFAULT_ENTRY gets the default source table entry and
  1399. ;; returns a pointer to it in SI.
  1400. ;; It jumps to 'found' if the default entry could be found.  If it is
  1401. ;; not found SI will be 0.
  1402. ;;
  1403. RIP_GET_SRC_DEFAULT_ENTRY_in_DI_out_SI_const_AX_BX_CX_BP_DI MACRO name, dls, found
  1404.     local start, done, next, search_loop, match, last_id, narrow_ptr
  1405.     .errb <found>
  1406.  
  1407.     .DATA
  1408. last_id        DW    ?
  1409. narrow_ptr    DW    ?
  1410.     .CODE
  1411.  
  1412.     xor DX, DX
  1413.     mov word ptr narrow_ptr, DX
  1414.     mov word ptr last_id, DX
  1415.     mov SI, offset rip_&name&_data.rip_hash
  1416.  
  1417.     jmp start
  1418.     search_loop:
  1419.         mov DX, word ptr [SI+re_id]
  1420.         cmp DI, DX
  1421.         jz match
  1422.         cmp DX, 1
  1423.         jg next
  1424.         jl match
  1425.         cmp DI, dls+1
  1426.         jg next
  1427.     match:
  1428.         cmp word ptr [SI+re_net], 0
  1429.         jnz next
  1430.         cmp word ptr [SI+re_net+2], 0
  1431.         jnz next
  1432.         mov DX, word ptr last_id
  1433.         cmp DX, word ptr [SI+re_id]
  1434.         jg next
  1435.         mov word ptr narrow_ptr, SI
  1436.         mov DX, word ptr [SI+re_id]
  1437.         mov word ptr last_id, DX
  1438.     next:
  1439.     start:
  1440.         mov SI, word ptr [SI+re_next]
  1441.         or SI, SI 
  1442.         jz done
  1443.         test byte ptr [SI+re_flags], ROUTE_SOURCE
  1444.         jz next
  1445.         jmp search_loop
  1446.     done:
  1447.         or SI, word ptr narrow_ptr
  1448.         jnz found
  1449. ENDM
  1450.  
  1451.  
  1452. ;;******************************************************************************
  1453. ;;    RIP_COMP_HASH
  1454. ;;      RIP_COMP_HASH takes an IP address in AX,BX and computes the hash
  1455. ;;      table position based on the class of the IP address. SI returns
  1456. ;;      the pointer into the hash table.
  1457. ;;
  1458. RIP_COMP_HASH_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI_ES MACRO name
  1459.     local class_A, class_B
  1460.  
  1461.     mov DL, AL
  1462.     test AL, 80h        ;; normal IP network interpretation
  1463.     jz class_A
  1464.     test AL, 40h
  1465.     jz class_B
  1466.     add DL, BL
  1467. class_B:
  1468.     add DL, AH
  1469. class_A:
  1470.     xor DH, DH
  1471.     mov SI, DX
  1472.     shl SI, 1
  1473.     add SI, offset rip_&name&_data.rip_hash
  1474. ENDM
  1475.  
  1476.  
  1477. ;;******************************************************************************
  1478. ;; Find interface finds the interface for the network address in AX:BX
  1479. ;; from the dl list 1, 2, ... 'dls'.  If no interface could be found then
  1480. ;; look whether ROUTE_FIND is able to find an interface.  The resulting
  1481. ;; gateway address is returned in AX:BX and the interface number is put
  1482. ;; into CL.  If no interface could be determined, it jumps to 'fail'.
  1483. ;;
  1484. RIP_FIND_IF_in_AX_BX_out_AX_BX_CL_const_SI_DI MACRO dls, fail
  1485.     local done, rf_fail
  1486.     .errb <fail>
  1487.  
  1488.     xor CL, CL
  1489.     IRP idx, <1,2,3,4,5,6,7,8>
  1490.     local notme 
  1491.     if idx le dls
  1492.             RIP_CHECK_IF_in_AX_BX_const_AX_BX_CX_SI_DI_ES idx, notme
  1493.             mov CL, idx
  1494.             jmp done
  1495.         notme:
  1496.     endif
  1497.     endm
  1498.     push AX
  1499.     push BX
  1500.     push SI
  1501.     push DI
  1502.     xor SI, SI
  1503.     mov DI, SI
  1504.     ROUTE_FIND_in_AX_BX_SI_DI_out_AX_BX_DX_const_CX_BP_ES %myip, rf_fail, rf_fail
  1505.     mov CL, DL
  1506.     pop DI
  1507.     pop SI
  1508.     pop DX
  1509.     pop DX
  1510.     jmp done
  1511.   rf_fail:
  1512.     pop DI
  1513.     pop SI
  1514.     pop BX
  1515.     pop AX
  1516.     jmp fail
  1517.   done:
  1518. ENDM
  1519.  
  1520. ;;*****************************************************************************
  1521. ;; RIP_CHECK_IF_in_AX_BX checks if the ip address in AX:BX matches the network
  1522. ;; associated with 'dl'.   If it does NOT it jumps to 'fail'
  1523. ;;
  1524. RIP_CHECK_IF_in_AX_BX_const_AX_BX_CX_SI_DI_ES MACRO dl, fail
  1525.     mov DX, BX
  1526.     and DX, word ptr dl_ip_&dl&_mask+2
  1527.     cmp DX, word ptr dl_ip_&dl&_net+2
  1528.     jne fail
  1529.     mov DX, AX
  1530.     and DX, word ptr dl_ip_&dl&_mask
  1531.     cmp DX, word ptr dl_ip_&dl&_net
  1532.     jne fail
  1533. ENDM
  1534.  
  1535. ;;*****************************************************************************
  1536. ;; RIP_GET_IF_NETMASK_in_AX_BX_out_AX_BX checks if the IP address in AX,BX
  1537. ;; matches the netclass address part of the data link interface 'dl'.
  1538. ;; If it does, it returns the interface netmask in AX,BX and then jumps
  1539. ;; to 'success'.
  1540. ;;
  1541. RIP_GET_IF_NETMASK_in_AX_BX_out_AX_BX_const_CX_DX_BP_SI_DI_ES MACRO dl, success
  1542.     local fail, get_mask
  1543.     .errb <success>
  1544.  
  1545.     cmp AL, byte ptr dl_ip_&dl&_net
  1546.     jnz fail
  1547.     test AL, 80H
  1548.     jz get_mask
  1549.     cmp AH, byte ptr dl_ip_&dl&_net+1
  1550.     jnz fail
  1551.     test AL, 40H
  1552.     jz get_mask
  1553.     cmp BL, byte ptr dl_ip_&dl&_net+2
  1554.     jnz fail
  1555.  
  1556.     get_mask:
  1557.         mov AX, word ptr dl_ip_&dl&_mask
  1558.         mov BX, word ptr dl_ip_&dl&_mask+2
  1559.         jmp success
  1560.     fail:
  1561. ENDM
  1562.  
  1563.  
  1564. ;;*****************************************************************************
  1565. ;; RIP_LOG_ROUTE_in_SI_const_ALL prints out the route entry pointed to by
  1566. ;; SI:DS to the loging host
  1567. ;;
  1568. RIP_LOG_ROUTE_in_SI_const_all MACRO name, severity
  1569.     local no_mask, no_gateway, print_metric
  1570.  
  1571.     push AX
  1572.     push BX
  1573.  
  1574.     mov AX, word ptr [SI+re_net]
  1575.     mov BX, word ptr [SI+re_net+2]
  1576.     LOG_PRINT_INET_in_AX_BX %mylog, L_ROUTE, severity, <    Routing network >
  1577.     or AX, BX
  1578.     jz no_mask
  1579.     mov AX, word ptr [SI+re_mask]
  1580.     mov BX, word ptr [SI+re_mask+2]
  1581.     LOG_PRINT_INET_in_AX_BX %mylog, L_ROUTE, severity, <    With netmask >
  1582. no_mask:
  1583.     xor AX, AX
  1584.     mov AL, byte ptr [SI+re_interface]
  1585.     LOG_PRINT_REG_DEC  %mylog, L_ROUTE, severity, <    Through interface >, AX
  1586.     cmp byte ptr [SI+re_metric], 0     ;; check metric
  1587.     jz no_gateway
  1588.     mov AX, word ptr [SI+re_gateway]
  1589.     mov BX, word ptr [SI+re_gateway+2]
  1590.     LOG_PRINT_INET_in_AX_BX %mylog, L_ROUTE, severity, <    To gateway >
  1591.     jmp print_metric
  1592. no_gateway:
  1593.     LOG_PRINT %mylog, L_ROUTE, severity, <    To direct connection>
  1594. print_metric:
  1595.     xor AX, AX
  1596.     mov AL, byte ptr [SI+re_metric]
  1597.     LOG_PRINT_REG_DEC  %mylog, L_ROUTE, severity, <    Metric >, AX
  1598.  
  1599.     pop BX
  1600.     pop AX
  1601. ENDM
  1602.  
  1603.