home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / p / pcrte224.zip / SOURCE.ZIP / RIP.INC < prev    next >
Text File  |  1992-06-09  |  25KB  |  728 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_CX_SI_DI_ES_const_DI_ES name
  26. ;;   ROUTE_FIND_in_AX_BX_CX_out_AX_DL_const_BP_ES name, forme, fail
  27. ;;
  28. ;;*****************************************************************************
  29.  
  30. ;;*****************************************************************************
  31. ;; definition of RIP packet structure
  32.  
  33. RIP_PORT                = 208h
  34. SWAPPED_RIP_PORT        = 802h
  35.  
  36. RIP_REPLY               = 2         ;; sending out RIP packets
  37. IP_FAMILY               = 2
  38. SWAPPED_IP_FAMILY       = 200h
  39.  
  40. rip_head    STRUC
  41.     rip_command         DB RIP_REPLY
  42.     rip_version         DB 1
  43.     rip_zero1           DW 0
  44. rip_head    ENDS
  45.  
  46. rip_route   STRUC
  47.     rip_family          DW SWAPPED_IP_FAMILY
  48.     rip_zero2           DW 0
  49.     rip_address         DD 0
  50.     rip_zero3           DD 0
  51.     rip_zero4           DD 0
  52.     rip_metric          DD 8
  53. rip_route   ENDS
  54.  
  55. ;;*****************************************************************************
  56. ;; internal Routing table definitions
  57.  
  58. rip_entry  STRUC
  59.    re_next      DW ?          ; this MUST be the first field
  60.    re_prev      DW ?
  61.    re_net       DD ?
  62.    re_gateway   DW ?
  63.    re_interface DB ?        ; interface MUST come directly before metric
  64.    re_metric    DB ?
  65.    re_flags     DB ?
  66.    re_timer     DB ?
  67. re_beautify     DW ?
  68. rip_entry  ENDS
  69.  
  70. rip_table_size = 300
  71. rip_data  STRUC
  72.     rip_hash      DW 256 dup (0)
  73.     rip_table     rip_entry rip_table_size dup (<>)
  74.     rip_table_ptr DW ?                    ;; end of the routeing table
  75.     rip_pack_ctr  DW ?
  76.     rip_pack_ptr  DW ?
  77.     rip_pack_out  DW ?
  78.     rip_if_net    DD ?
  79.     rip_if_last   DD ?
  80. rip_data  ENDS
  81. rip_table_end  = (rip_table+(rip_table_size*(size rip_entry)))
  82.  
  83. ;; Routing Flags
  84. ROUTE_SILENT =    (1 shl 0)      ; Do not broadcast via RIP
  85. ROUTE_TRANS  =    (1 shl 1)      ; Transiant, can be changed by RIP
  86.  
  87. ROUTE_VALID  =    (1 shl 7)      ; a valid table entry
  88.  
  89.  
  90. ;;******************************************************************************
  91. ;;  RIP_DECLARE name, ip_net, timer, udp
  92. ;;       RIP_DECLARE delcares a new routing object called 'name'. 
  93. ;;       'ip_net' is the IP_NET that the router is associated with,
  94. ;;       'timer' is a timer object, and 'udp' is the name of
  95. ;;       a UDP object (to get RIP packets from)
  96. ;;
  97. RIP_DECLARE   MACRO  name, ip_net, timer, udp
  98.     .errb <udp>
  99.  
  100.     .DATA
  101.     rip_&name&_ip_net = ip_net
  102.     rip_&name&_timer = timer
  103.     rip_&name&_udp = udp
  104.     rip_&name&_udp_sock = (name*100+1)
  105.     rip_&name&_dls = ip_&ip_net&_dls
  106.     global rip_&name&_data:rip_data 
  107.  
  108.     .CODE
  109.     global rip_&name&_read_code:near 
  110.     global rip_&name&_timer_code:near 
  111.     global rip_&name&_real_define:near
  112.     global rip_&name&_send_dls:near 
  113.  
  114.     UDP_SOCK_DECLARE %rip_&name&_udp_sock, %rip_&name&_udp, RIP_PORT
  115. ENDM
  116.  
  117.  
  118. ;;******************************************************************************
  119. ;;   RIP_DEFINE   name
  120. ;;       RIP_DEFINE sets aside the memory and acutally does the 
  121. ;;       initialization for the routeing objects 'name'
  122. ;;
  123. RIP_DEFINE        MACRO   name
  124.     call rip_&name&_real_define
  125. ENDM
  126.  
  127. RIP_REAL_DEFINE   MACRO   name
  128.     local around, listen_code
  129.     .errb <name>
  130.  
  131.     .DATA
  132. rip_&name&_data   rip_data  <>
  133.  
  134.     .CODE
  135.     jmp around          ;; declare code objects
  136.         rip_&name&_timer_code:
  137.             RIP_TASK name 
  138.             TIMER_RETURN %rip_&name&_timer 
  139.                 ;; this does NOT fall through
  140.  
  141.         rip_&name&_send_dls:
  142.             RIP_SEND_DLS name
  143.             ret
  144.  
  145.         rip_&name&_read_code:
  146.             mov DI, BX
  147.                 ;; this is a violation of layering, but what can I do
  148.             IP_R_HEADER_in_ES_out_SI_const_BX_CX_DX_BP_DI_ES %rip_&name&_ip_net
  149.             add SI, ip_src
  150.             xchg SI, DI
  151.             RIP_PROCESS_PACKET_in_CX_SI_DI_ES name
  152.             RET
  153.                 ;; this does NOT fall through
  154.  
  155.         listen_code:
  156.                 ;; because of circular dependance (RIP, a low level
  157.                 ;; protocol depending on UDP a high level protocol)
  158.                 ;; we have to defer the definition of this socket
  159.             UDP_SOCK_DEFINE %rip_&name&_udp_sock, rip_&name&_read_code
  160.             TIMER_RETURN %rip_&name&_timer 
  161.                 ;; this does NOT fall through
  162.     around:
  163.  
  164. rip_&name&_real_define:
  165.     mov AX, DS              ; NULL all data 
  166.     mov ES, AX
  167.     xor AX, AX
  168.     mov CX, size rip_data
  169.     mov DI, offset rip_&name&_data
  170.     rep
  171.     stosb
  172.  
  173.     mov rip_&name&_data.rip_table_ptr, offset rip_&name&_data.rip_table-(size rip_entry) 
  174.  
  175.         ;; start RIP listening for packets
  176.     mov AX, 18*0
  177.     TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, listen_code
  178.  
  179.         ;; set the expire task to go off 
  180.     mov AX, 18*0
  181.     TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, rip_&name&_timer_code
  182.  
  183.     RET
  184. ENDM
  185.  
  186.  
  187. ;;******************************************************************************
  188. ;;   ROUTE_ADD_in_CX_SI_DI_ES name
  189. ;;      ROUTE_ADD adds the route to described by network pointed to by SI:ES,
  190. ;;      the gateway pointed to by DI:ES and the metric held in CL and flags
  191. ;;      (See flag defs above) held in CH, Note for directly connected networks 
  192. ;;      (CL = 0) the 'gateway' (DI:ES) must point to the IP address of this host
  193. ;;
  194. ROUTE_ADD_in_CX_SI_DI_ES_const_DI_ES MACRO name
  195.    local done, look_for_empty, found_empty, no_wrap, found, new_route
  196.    local add_new_gateway, not_bigger, delete_route, delete_trigger
  197.  
  198.     mov AX, ES:[SI]
  199.     mov BX, ES:[SI+2]
  200.     mov BP, DI                      ; save DI
  201.     IP_COMPUTE_NET_in_AX_BX_out_AX_BX_const_CX_DX_BP_SI_DI_ES rip_&name&_dls 
  202.     RIP_GET_ENTRY_in_AX_BX_out_SI_DI_const_AX_BX_CX_BP name, found
  203.         cmp CL, 16
  204.         jae done
  205.         mov SI, word ptr rip_&name&_data.rip_table_ptr
  206.         look_for_empty:
  207.             add SI, size rip_entry
  208.             cmp SI, offset rip_&name&_data.rip_table_end
  209.             jb no_wrap
  210.                 mov SI, offset rip_&name&_data.rip_table
  211.             no_wrap:
  212.             test byte ptr [SI.re_flags], ROUTE_VALID
  213.             jz found_empty
  214.  
  215.             cmp SI, word ptr rip_&name&_data.rip_table_ptr
  216.             jnz look_for_empty
  217.             LOG_PRINT %mylog, L_ROUTE, L_ERR, <Routing table overflow>
  218.             jmp done
  219.         found_empty:
  220.         cmp SI, word ptr rip_&name&_data.rip_table_ptr
  221.         jbe not_bigger
  222.             mov word ptr rip_&name&_data.rip_table_ptr, SI
  223.         not_bigger:
  224.         mov [SI.re_prev], DI            ;; link this in last in the list
  225.         mov [DI.re_next], SI
  226.  
  227.         mov [SI+re_next], 0             ;; fill in next
  228.         mov word ptr [SI+re_net], AX
  229.         mov word ptr [SI+re_net+2], BX
  230.         or CH, ROUTE_VALID              ;; fill in flags
  231.         mov byte ptr [SI+re_flags], CH
  232.         jmp  add_new_gateway
  233.  
  234.     delete_trigger:
  235.     delete_route:
  236.         LOG_PRINT_INET_in_AX_BX %mylog, L_ROUTE, L_INFO, <Rip from bogus host>
  237.         RIP_DELETE_in_SI_const_BX_CX_DX_SI_BP name
  238.         jmp done
  239.  
  240.     found:
  241.         test [SI+re_flags], ROUTE_TRANS   ;; cant change a permanent route
  242.         jz done 
  243.  
  244.         mov DI, BP                          ;; restore DI
  245.         mov DX, ES:[DI+2]
  246.         cmp DX, [SI+re_gateway]
  247.         jnz new_route
  248.             mov byte ptr [SI+re_metric], CL
  249.             cmp CL, 16
  250.             jae done
  251.                 mov byte ptr [SI+re_timer], 3
  252.                 jmp done
  253.         new_route:
  254.         cmp CL, [SI+re_metric]
  255.         jae done                            ;; old metric less, we are done
  256.  
  257.     add_new_gateway:
  258.     mov DI, BP                              ;; restore DI
  259.     mov byte ptr [SI+re_timer], 3
  260.     mov byte ptr [SI+re_metric], CL
  261.     mov AX, ES:[DI]
  262.     mov BX, ES:[DI+2]
  263.     mov word ptr [SI+re_gateway], BX
  264.     RIP_FIND_IF_in_AX_BX_out_CL_const_AX_BX_SI_DI %rip_&name&_dls, delete_route
  265.     mov byte ptr [SI+re_interface], CL
  266.  
  267.     LOG_PRINT %mylog, L_ROUTE, L_INFO, <Adding the Following Route>
  268.     RIP_LOG_ROUTE_in_SI_const_all name, L_INFO
  269.     done:
  270.     mov DI, BP                          ;; restore DI
  271. ENDM
  272.  
  273.  
  274. ;;*****************************************************************************
  275. ;;   ROUTE_FIND_in_AX_BX_CX_out_AX_DL name, forme, fail
  276. ;;      ROUTE_FIND takes the network number in the AX:BX pair and the
  277. ;;      host part in CX of a packet address and does one of three things
  278. ;;      if it is for this host it jumps to 'forme'.  If it could find no
  279. ;;      route it jumps to 'fail'. otherwise outputs the DL interface 
  280. ;;      in DL and the gatway host part in AX of where to send it to.
  281. ;;
  282. ROUTE_FIND_in_AX_BX_CX_out_AX_DL_const_BP_ES MACRO name, forme, fail
  283.     local found, done, not_direct
  284.  
  285.     RIP_GET_ENTRY_in_AX_BX_out_SI_DI_const_AX_BX_CX_BP name, found
  286.     xor AX, AX                          ; check the default route
  287.     xor BX, BX
  288.     RIP_GET_ENTRY_in_AX_BX_out_SI_DI_const_AX_BX_CX_BP name, found
  289.     jmp fail
  290.  
  291.     found:
  292.     mov DX, word ptr [SI+re_interface]  ; load DL=interface DH=metric
  293.     mov AX, [SI+re_gateway]
  294.     or DH, DH
  295.     jnz not_direct
  296.         cmp AX, CX
  297.         jz forme                ;; the re_gateway holds my IP address 
  298.         mov AX, CX              ;; for direct routes
  299.     not_direct:
  300.     done:
  301. ENDM
  302.  
  303.  
  304. ;;**************************************************************************
  305. ;; RIP_TASK is the code that goes off in 30 seconds.  Basicly all it does
  306. ;; is call RIP_EXPIRE and then resubmit a timer request so it will go off
  307. ;; 30 seconds in the future
  308. ;;
  309. RIP_TASK MACRO name
  310.     local timer_code, rip_loop, packets_sent
  311.  
  312.     timer_code:
  313.         RIP_EXPIRE_const_BX_CX_DX_BP name
  314.  
  315.         call rip_&name&_send_dls
  316.  
  317.         mov AX, 18*30               ;; resubmit the task 30 seconds from now
  318.         TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, timer_code
  319. ENDM
  320.  
  321.  
  322. ;;**************************************************************************
  323. ;; RIP_SEND_DLS sends out a RIP update.
  324. ;;
  325. RIP_SEND_DLS MACRO name
  326.  
  327.     IRP idx, <1,2,3,4,5,6,7,8>
  328.     if idx le rip_&name&_dls
  329.         RIP_SEND_DL name, idx
  330.     endif
  331.     endm
  332. ENDM
  333.  
  334. ;;**************************************************************************
  335. ;; RIP_SEND_DL generates all the RIP packets for the data link interface 'mydl'
  336. ;;
  337. RIP_SEND_DL MACRO name, mydl
  338.     local done, pack_loop
  339.     .errb <mydl>
  340.  
  341.     mov AX, word ptr dl_ip_&mydl&_flags
  342.     test word ptr dl_ip_&mydl&_flags, ROUTE_DL_SILENT   ;; skip silent ifs 
  343.     jnz done
  344.     mov AX, word ptr dl_ip_&mydl&_ip
  345.     mov BX, word ptr dl_ip_&mydl&_ip+2
  346.     IP_COMP_NET_in_AX_BX_out_AX_BX_const_CX_DX_BP_SI_DI_ES rip_&name&_dls
  347.     mov word ptr rip_&name&_data.rip_if_net, AX
  348.     mov word ptr rip_&name&_data.rip_if_net+2, BX
  349.  
  350.     RIP_INIT_ENTRY_out_SI_const_AX_BX_CX_DX_BP_DI name
  351.     mov rip_&name&_data.rip_pack_out, SI
  352.     pack_loop:
  353.         mov CX, 512                 ;; maximum RIP packet size
  354.         mov DX, RIP_PORT
  355.         mov AX, word ptr dl_ip_&mydl&_broad
  356.         mov BX, word ptr dl_ip_&mydl&_broad+2
  357.  
  358.         UDP_SOCK_W_ACCESS_in_AX_BX_CX_DX_out_AX_DI_ES %rip_&name&_udp_sock
  359.         cmp AX, 0
  360.         jnz done
  361.  
  362.         mov DL, mydl
  363.         mov DH, byte ptr dl_ip_&mydl&_metric
  364.         mov SI, rip_&name&_data.rip_pack_out
  365.         RIP_MAKE_PACKET_in_DX_SI_DI_out_CX_SI_const_BP name, rip_&name&_data.rip_if_net, done
  366.         mov rip_&name&_data.rip_pack_out, SI
  367.  
  368.         UDP_SOCK_W_WRITE_in_CX %rip_&name&_udp_sock
  369.     jmp pack_loop
  370.     done:
  371. ENDM
  372.  
  373.  
  374. ;;**************************************************************************
  375. ;; RIP_DELETE_in_SI_const_BX_CX_DX_SI_BP deletes the entry pointed by by SI
  376. ;;
  377. RIP_DELETE_in_SI_const_BX_CX_DX_SI_BP MACRO name
  378.     local end_of_list
  379.  
  380.     mov byte ptr [SI+re_flags], 0       ;; make the route invalid
  381.     mov DI, [SI+re_prev]
  382.     mov AX, [SI+re_next]
  383.     mov [DI.re_next], AX
  384.     or AX, AX
  385.     jz end_of_list
  386.         xchg AX, DI
  387.         mov [DI+re_prev], AX
  388.     end_of_list:
  389. ENDM
  390.  
  391.  
  392. ;;**************************************************************************
  393. ;; RIP_EXPIRE should be called every 30 seconds.  This routine decrements
  394. ;; the timer entries on the routes and expires the routes after 90 seconds.
  395. ;;
  396. RIP_EXPIRE_const_BX_CX_DX_BP MACRO name
  397.     local expire_loop, done, delete_route
  398.     .errb <name>
  399.  
  400.     RIP_INIT_ENTRY_out_SI_const_AX_BX_CX_DX_BP_DI name
  401.     expire_loop:
  402.         RIP_NEXT_ENTRY_in_SI_out_SI_const_AX_BX_CX_DX_BP_DI name, done
  403.         test [SI+re_flags], ROUTE_TRANS      ;; don't expire permenent routes
  404.         jz expire_loop
  405.  
  406.         sub [SI+re_timer], 1                   ;; decrement the timer
  407.         jg expire_loop
  408.         jz delete_route
  409.                 ;; check to see if we should purge it from the table
  410.             cmp [SI+re_timer], -3 
  411.             jg expire_loop
  412.                 RIP_DELETE_in_SI_const_BX_CX_DX_SI_BP name
  413.                 jmp expire_loop
  414.         delete_route:
  415.                 ;; delete the route
  416.             mov [SI+re_metric], 16
  417.             LOG_PRINT %mylog, L_ROUTE, L_INFO, <Route expired.  Deleting route>
  418.             RIP_LOG_ROUTE_in_SI_const_all name, L_INFO
  419.             jmp expire_loop
  420.     done:
  421. ENDM
  422.  
  423.  
  424. ;;**************************************************************************
  425. ;; RIP_PROCESS_PACKET processes the packet in ES:SI.  The IP address of
  426. ;; the gateway that sent the packet is pointed to by ES:DI.  CX holds
  427. ;; the length of the RIP part of the packet
  428.  
  429. RIP_PROCESS_PACKET_in_CX_SI_DI_ES MACRO name
  430.     local process_loop, done, next
  431.  
  432.     mov AX, word ptr ES:[DI]
  433.     mov BX, word ptr ES:[DI+2]
  434.     RIP_SHOULD_LISTEN_in_AX_BX_const_CX_SI_DI_ES name, done
  435.     cmp byte ptr ES:[SI+rip_command], RIP_REPLY
  436.     jnz done
  437.     cmp byte ptr ES:[SI+rip_version], 1
  438.     jnz done
  439.         add SI, 4
  440.         sub CX, 4
  441.         process_loop:
  442.             sub CX, 20
  443.             jb done
  444.  
  445.             cmp word ptr ES:[SI+rip_family], SWAPPED_IP_FAMILY
  446.             jnz next
  447.             cmp word ptr ES:[SI+rip_zero3], 0       ;; not complete checks
  448.             jnz next
  449.             cmp word ptr ES:[SI+rip_zero4], 0
  450.             jnz next
  451.  
  452.             mov word ptr rip_&name&_data.rip_pack_ctr, CX
  453.             mov word ptr rip_&name&_data.rip_pack_ptr, SI
  454.             mov CL, byte ptr ES:[SI+rip_metric+3]
  455.             mov CH, ROUTE_TRANS
  456.             add SI, rip_address
  457.             ROUTE_ADD_in_CX_SI_DI_ES_const_DI_ES name
  458.             mov CX, word ptr rip_&name&_data.rip_pack_ctr
  459.             mov SI, word ptr rip_&name&_data.rip_pack_ptr
  460.     
  461.             next:
  462.                 add SI, 20
  463.         jmp process_loop
  464.     done:
  465. ENDM
  466.  
  467.  
  468. ;;**************************************************************************
  469. ;; RIP_SHOULD_LISTEN determines if we should listen to a RIP packet from 
  470. ;; the gateway AX:BX.  If the packet should be dropped this macro jumps
  471. ;; to 'drop'
  472. ;;
  473. RIP_SHOULD_LISTEN_in_AX_BX_const_CX_SI_DI_ES MACRO name, drop
  474.     .errb <drop>
  475.  
  476.     IRP idx, <1,2,3,4,5,6,7,8>
  477.     local notme 
  478.     if idx le rip_&name&_dls 
  479.             RIP_CHECK_IF_in_AX_BX_const_AX_BX_CX_SI_DI_ES idx, notme
  480.             RIP_CHECK_FLAGS idx, ROUTE_DL_DEAF
  481.             jz done
  482.             jmp drop
  483.         notme:
  484.     endif
  485.     endm
  486.     jmp drop
  487.     done:
  488. ENDM
  489.  
  490. RIP_CHECK_FLAGS MACRO dl, mask
  491.     test word ptr dl_ip_&dl&_flags, mask
  492. ENDM
  493.  
  494.  
  495. ;;**************************************************************************
  496. ;; RIP_MAKE_PACKET generates a RIP packet in DI:ES for the interface in DL
  497. ;; by calling accessing the routing table by means of RIP_NEXT_ENTRY.  
  498. ;; Thus it assumes SI has been initialized with RIP_INIT_ENTRY or is
  499. ;; a continuation of a RIP_NEXT_ENTRY..  CX is set to the length of the 
  500. ;; packet.  It jumps to 'dont_send' when there is not data to send out, so
  501. ;; that the packet should not be sent.  DH contains the interface metric
  502. ;; for the interface.  'if_net' is a pointer to the network part (not assuming
  503. ;; subnets, that is based strictly on the Class of the address).  This is
  504. ;; used to implement the subnet hiding
  505.  
  506. RIP_MAKE_PACKET_in_DX_SI_DI_out_CX_SI_const_BP MACRO name, if_net, dont_send
  507.     local route_loop, packet_full, metric_ok
  508.     local send_full_route, not_same_subnet, not_last, send_metric
  509.     .errb <dont_send>
  510.  
  511.         ;; make up header
  512.     mov AL, RIP_REPLY               ;; this is a reply packet
  513.     stosb
  514.     mov AL, 1                       ;; version 1
  515.     stosb
  516.     xor AX, AX                      ;; must be 0
  517.     stosw
  518.     dec AX                          ;; AX now = -1
  519.     mov word ptr rip_&name&_data.rip_if_last, AX
  520.     mov word ptr rip_&name&_data.rip_if_last+2, AX
  521.     mov CX, 4
  522.     route_loop:
  523.         RIP_NEXT_ENTRY_in_SI_out_SI_const_AX_BX_CX_DX_BP_DI name, packet_full
  524.         test [SI+re_flags], ROUTE_SILENT
  525.         jnz route_loop
  526.  
  527.         cmp DL, [SI+re_interface]           ;; split horizon
  528.         jz route_loop
  529.  
  530.             ;; this code implements the hiding of subnet info outside 
  531.             ;; the subnet
  532.         mov AX, word ptr [SI+re_net]         ;; the destination network
  533.         mov BX, word ptr [SI+re_net+2] 
  534.         IP_COMP_NET_in_AX_BX_out_AX_BX_const_CX_DX_BP_SI_DI_ES rip_&name&_dls
  535.         cmp AX, word ptr if_net
  536.         jnz not_same_subnet
  537.         cmp BX, word ptr if_net+2
  538.         jz send_full_route
  539.             not_same_subnet:
  540.             cmp AX, word ptr rip_&name&_data.rip_if_last
  541.             jnz not_last
  542.             cmp BX, word ptr rip_&name&_data.rip_if_last+2
  543.             jz route_loop
  544.             not_last:
  545.                 mov word ptr rip_&name&_data.rip_if_last, AX
  546.                 mov word ptr rip_&name&_data.rip_if_last+2, BX
  547.  
  548.                 mov AX, SWAPPED_IP_FAMILY            ;; Address family
  549.                 stosw
  550.                 xor AX, AX                           ;; two bytes of zero
  551.                 stosw
  552.                 mov AX, word ptr rip_&name&_data.rip_if_last
  553.                 stosw
  554.                 mov AX, word ptr rip_&name&_data.rip_if_last+2
  555.                 stosw
  556.                 jmp send_metric
  557.  
  558.         send_full_route:
  559.         mov AX, SWAPPED_IP_FAMILY            ;; Address family
  560.         stosw
  561.         xor AX, AX                           ;; two bytes of zero
  562.         stosw
  563.         mov AX, word ptr [SI+re_net]         ;; the destination network
  564.         stosw
  565.         mov AX, word ptr [SI+re_net+2]
  566.         stosw
  567.  
  568.         send_metric:
  569.         xor AX, AX                           ;; 8 zero bytes
  570.         stosw
  571.         stosw
  572.         stosw
  573.         stosw
  574.         stosw                               ;; 4 bytes of metric
  575.         mov AH, [SI+re_metric]   
  576.         add AH, DH                          ;; add in the interface metric
  577.         cmp AH, 16
  578.         jbe metric_ok
  579.             mov AH, 16
  580.         metric_ok:
  581.         stosw
  582.  
  583.         add CX, 20
  584.         cmp CX, 512-20                  ;; is there space for another entry
  585.         ja packet_full
  586.     jmp route_loop
  587.  
  588.     packet_full:
  589.     cmp CX, 4
  590.     jz dont_send
  591. ENDM
  592.  
  593.  
  594.  
  595. ;;**************************************************************************
  596. ;; RIP_INIT_ENTRY initilizes SI so that RIP_NEXT_ENTRY works.  When
  597. ;; RIP_NEXT_ENTRY is called, SI will point to the first entry of the
  598. ;; routing table.  This may seem a bit bizarre that RIP_NEXT_ENTRY MUST
  599. ;; be called immediately after RIP_INIT_ENTRY, but it actually makes
  600. ;; loops easier to construct.
  601.  
  602. RIP_INIT_ENTRY_out_SI_const_AX_BX_CX_DX_BP_DI MACRO name
  603.     .errb <name>
  604.  
  605.     mov SI, offset (rip_&name&_data.rip_table - (size rip_entry))
  606. ENDM
  607.  
  608.  
  609. ;;**************************************************************************
  610. ;; RIP_NEXT_ENTRY gets the next entry in the table and returns it in
  611. ;; SI.  NOTE: SI must be unchanged from the last RIP_INIT_ENTRY or
  612. ;; RIP_NEXT_ENTRY for this function to work.  It jumps to 'done' if 
  613. ;; there are no more entries.
  614. ;;
  615. RIP_NEXT_ENTRY_in_SI_out_SI_const_AX_BX_CX_DX_BP_DI MACRO name, done
  616.     local search_loop
  617.     .errb <done>
  618.  
  619.     search_loop:
  620.         add SI, size rip_entry
  621.         cmp SI, word ptr rip_&name&_data.rip_table_ptr
  622.         ja done
  623.         test [SI+re_flags], ROUTE_VALID
  624.     jz search_loop
  625. ENDM
  626.  
  627.  
  628. ;;**************************************************************************
  629. ;; RIP_GET_ENTRY gets the table entry for the network in the AX:BX 
  630. ;; pair and returns a pointer to it in SI. DI returns the pointer to
  631. ;; the previous entry in the list (useful for insertions and deletions)
  632. ;; It jumps to 'found' if the network entry could is found.  If it is
  633. ;; not found only DI is valid (SI will be 0)
  634. ;;
  635. RIP_GET_ENTRY_in_AX_BX_out_SI_DI_const_AX_BX_CX_BP MACRO name, found
  636.     local start, done, next, search_loop
  637.     .errb <found>
  638.  
  639.     mov DL, AL
  640.     add DL, AH
  641.     add DL, BL
  642.     add DL, BH                  ;; compute the hash function
  643.     xor DH, DH
  644.     mov SI, DX
  645.     shl SI, 1
  646.     add SI, offset rip_&name&_data.rip_hash
  647.  
  648.     jmp start
  649.     search_loop:
  650.         cmp AX, word ptr [SI+re_net]
  651.         jnz next
  652.         cmp BX, word ptr [SI+re_net+2]
  653.         jnz next
  654.         jmp found
  655.     next:
  656.     start:
  657.         mov DI, SI
  658.         mov SI, [SI+re_next]
  659.  
  660.         or SI, SI 
  661.         jnz search_loop
  662.     ;; failure
  663. ENDM
  664.  
  665.  
  666. ;;******************************************************************************
  667. ;; Find interface finds the interface for the network address in AX:BX
  668. ;; from the dl list 1, 2, ... 'dls' and puts it in CL.  It jumps to 'fail'
  669. ;; if the address is not on any of the interfaces in 'dls'.  
  670. ;;
  671. RIP_FIND_IF_in_AX_BX_out_CL_const_AX_BX_SI_DI MACRO dls, fail
  672.     local done
  673.     .errb <fail>
  674.  
  675.     xor CL, CL
  676.     IRP idx, <1,2,3,4,5,6,7,8>
  677.     local notme 
  678.     if idx le dls
  679.             RIP_CHECK_IF_in_AX_BX_const_AX_BX_CX_SI_DI_ES idx, notme
  680.             mov CL, idx
  681.             jmp done
  682.         notme:
  683.     endif
  684.     endm
  685.     jmp fail
  686.     done:
  687. ENDM
  688.  
  689. ;;*****************************************************************************
  690. ;; RIP_CHECK_IF_in_AX_BX checks if the ip address in AX:BX matches the network
  691. ;; associated with 'dl'.   If it does NOT it jumps to 'fail'
  692. ;;
  693. RIP_CHECK_IF_in_AX_BX_const_AX_BX_CX_SI_DI_ES MACRO dl, fail
  694.     cmp AX, word ptr dl_ip_&dl&_net
  695.     jnz fail
  696.     mov DX, BX
  697.     and DX, word ptr dl_ip_&dl&_mask+2
  698.     cmp DX, word ptr dl_ip_&dl&_net+2
  699.     jnz fail
  700. ENDM
  701.  
  702.  
  703. ;;*****************************************************************************
  704. ;; RIP_LOG_ROUTE_in_SI_const_ALL prints out the route entry pointed to by
  705. ;; SI:DS to the loging host
  706. ;;
  707. RIP_LOG_ROUTE_in_SI_const_all MACRO name, severity
  708.     push AX
  709.     push BX
  710.  
  711.     mov AX, word ptr [SI+re_net]
  712.     mov BX, word ptr [SI+re_net+2]
  713.     LOG_PRINT_INET_in_AX_BX %mylog, L_ROUTE, severity, <    Routing to network >
  714.     xor AX, AX
  715.     mov AL, byte ptr [SI+re_interface]
  716.     LOG_PRINT_REG_DEC  %mylog, L_ROUTE, severity, <    Through interface >, AX
  717.     mov AX, word ptr [SI+re_gateway]
  718.     xchg AH, AL
  719.     LOG_PRINT_REG_HEX  %mylog, L_ROUTE, severity, <    To host with IP addr ending with >, AX
  720.     xor AX, AX
  721.     mov AL, byte ptr [SI+re_metric]
  722.     LOG_PRINT_REG_DEC  %mylog, L_ROUTE, severity, <    Routing Metric >, AX
  723.  
  724.     pop BX
  725.     pop AX
  726. ENDM
  727.  
  728.