home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-05-21 | 48.4 KB | 1,603 lines |
- ;;*************************************************************************
- ;; rip.inc rip.inc
- ;;*************************************************************************
- ;;
- ;; Copyright (C) 1989 Northwestern University, Vance Morrison
- ;;
- ;;
- ;; Permission to view, compile, and modify for LOCAL (intra-organization)
- ;; USE ONLY is hereby granted, provided that this copyright and permission
- ;; notice appear on all copies. Any other use by permission only.
- ;;
- ;; Northwestern University makes no representations about the suitability
- ;; of this software for any purpose. It is provided "as is" without expressed
- ;; or implied warranty. See the copywrite notice file for complete details.
- ;;
- ;;*****************************************************************************
- ;;
- ;; rip.inc provides a ROUTE interface for th rip protocol. In particular
- ;; it provides the following functions
- ;;
- ;; Routines provided by this module
- ;;
- ;; RIP_DECLARE name, ip_net, timer, udp, udp_sock
- ;; RIP_DEFINE name
- ;; ROUTE_ADD_in_AX_CX_DX_SI_DI_ES_const_DI_ES name
- ;; ROUTE_FIND_in_AX_BX_SI_DI_out_AX_BX_DX_const_CX_BP_ES name, forme, fail, drop
- ;;
- ;;*****************************************************************************
-
- ;;*****************************************************************************
- ;; definition of RIP packet structure
-
- RIP_PORT = 208h
- SWAPPED_RIP_PORT = 802h
-
- RIP_REQUEST = 1 ;; request for RIP packets
- RIP_REPLY = 2 ;; sending out RIP packets
- RIP_VER = 1
- IP_FAMILY = 2
- SWAPPED_IP_FAMILY = 200h
-
- MAX_HOST_SPLIT = 256
-
- rip_head STRUC
- rip_command DB RIP_REPLY
- rip_version DB RIP_VER
- rip_zero1 DW 0
- rip_head ENDS
-
- rip_route STRUC
- rip_family DW SWAPPED_IP_FAMILY
- rip_zero2 DW 0
- rip_address DD 0
- rip_zero3 DD 0
- rip_zero4 DD 0
- rip_metric DD 8
- rip_route ENDS
-
- ;;*****************************************************************************
- ;; internal Routing table definitions
-
- rip_entry STRUC
- re_next DW ? ; this MUST be the first field
- re_prev DW ?
- re_net DD ?
- re_mask DD ?
- re_gateway DW 2 dup (0)
- re_igateway DW 2 dup (0)
- re_interface DB ? ; interface MUST come directly before metric
- re_metric DB ?
- re_flags DB ?
- re_timer DB ?
- re_id DW ?
- rip_entry ENDS
-
- rip_table_size = 1200
- rip_data STRUC
- rip_hash DW 256 dup (0)
- rip_table rip_entry rip_table_size dup (<>)
- rip_table_ptr DW ? ;; end of the routeing table
- rip_pack_ctr DW ?
- rip_pack_ptr DW ?
- rip_pack_out DW ?
- rip_if_net DD ?
- rip_if_last DD ?
- rip_target DD ?
- rip_udp_port DW ?
- rip_hr_count DW 0
- rip_data ENDS
- rip_table_end = (rip_table+(rip_table_size*(size rip_entry)))
-
- ;; Routing Flags
- ROUTE_SILENT = (1 shl 0) ; Do not broadcast via RIP
- ROUTE_SPLIT = (1 shl 1) ; For RIP, split network into host routes
- ROUTE_TRANS = (1 shl 2) ; Transient, can be changed by RIP
- ROUTE_DROP = (1 shl 3) ; Declare as unreachable
- ROUTE_DENY = (1 shl 4) ; Do not route (source routing)
-
- ROUTE_SOURCE = (1 shl 6) ; a source route entry
- ROUTE_VALID = (1 shl 7) ; a valid table entry
-
-
- ;;******************************************************************************
- ;; RIP_DECLARE name, ip_net, timer, udp
- ;; RIP_DECLARE delcares a new routing object called 'name'.
- ;; 'ip_net' is the IP_NET that the router is associated with,
- ;; 'timer' is a timer object, and 'udp' is the name of
- ;; a UDP object (to get RIP packets from)
- ;;
- RIP_DECLARE MACRO name, ip_net, timer, udp
- .errb <udp>
-
- .DATA
- rip_&name&_ip_net = ip_net
- rip_&name&_timer = timer
- rip_&name&_udp = udp
- rip_&name&_udp_sock = (name*100+1)
- rip_&name&_dls = ip_&ip_net&_dls
- global rip_&name&_data:rip_data
-
- .CODE
- global rip_&name&_read_code:near
- global rip_&name&_timer_code:near
- global rip_&name&_expire_code:near
- global rip_&name&_send_code:near
- global rip_&name&_send_request:near
- global rip_&name&_real_define:near
- global route_&name&_real_add:near
-
- UDP_SOCK_DECLARE %rip_&name&_udp_sock, %rip_&name&_udp, RIP_PORT
- ENDM
-
-
- ;;******************************************************************************
- ;; RIP_DEFINE name
- ;; RIP_DEFINE sets aside the memory and acutally does the
- ;; initialization for the routeing objects 'name'
- ;;
- RIP_DEFINE MACRO name
- call rip_&name&_real_define
- ENDM
-
- RIP_REAL_DEFINE MACRO name
- local around, listen_code, jmp_table, done
- .errb <name>
-
- .DATA
- jmp_table dw done
- IRP idx, <1,2,3,4,5,6,7,8>
- if idx le rip_&name&_dls
- RIP_INIT_DL_JMP_TAB name, idx, send_rip
- endif
- endm
-
- rip_&name&_data rip_data <>
-
- .CODE
- jmp around ;; declare code objects
- rip_&name&_timer_code:
- RIP_TASK name
- TIMER_RETURN %rip_&name&_timer
- ;; this does NOT fall through
-
- rip_&name&_expire_code:
- RIP_EXPIRE_const_BX_CX_DX_BP name
- TIMER_RETURN %rip_&name&_timer
- ;; this does NOT fall through
-
- rip_&name&_send_code:
- mov word ptr rip_&name&_data.rip_target, AX
- mov word ptr rip_&name&_data.rip_target+2, BX
- mov word ptr rip_&name&_data.rip_udp_port, CX
- xor DH, DH ;; set up jump to proper DL
- shl DX, 1
- mov DI, offset jmp_table
- add DI, DX
- jmp [DI] ;; jump to proper DL
-
- ;; the above jump goes to one of the code fragments below
- IRP idx, <1,2,3,4,5,6,7,8>
- if idx le rip_&name&_dls
- RIP_INIT_DL_LABEL name, idx, send_rip
-
- RIP_SEND_DL name, idx
- RET
- endif
- endm
- ;; the above code does NOT fall through
-
- done:
- RET
-
- rip_&name&_read_code:
- mov DI, BX
- ;; this is a violation of layering, but what can I do
- IP_R_HEADER_in_ES_out_SI_const_BX_CX_DX_BP_DI_ES %rip_&name&_ip_net
- add SI, ip_src
- xchg SI, DI
- RIP_PROCESS_PACKET_in_CX_SI_DI_ES name
- RET
- ;; this does NOT fall through
-
- rip_&name&_send_request:
- IRP idx, <1,2,3,4,5,6,7,8>
- if idx le rip_&name&_dls
- RIP_SEND_REQUEST name, idx
- endif
- endm
- TIMER_RETURN %rip_&name&_timer
- ;; this does NOT fall through
-
- listen_code:
- ;; because of circular dependance (RIP, a low level
- ;; protocol depending on UDP a high level protocol)
- ;; we have to defer the definition of this socket
- UDP_SOCK_DEFINE %rip_&name&_udp_sock, rip_&name&_read_code
- TIMER_RETURN %rip_&name&_timer
- ;; this does NOT fall through
-
- route_&name&_real_add:
- ROUTE_REAL_ADD_in_AX_CX_DX_SI_DI_ES_const_DI_ES name
- RET
- around:
-
- rip_&name&_real_define:
- mov AX, DS ; NULL all data
- mov ES, AX
- xor AX, AX
- mov CX, size rip_data
- mov DI, offset rip_&name&_data
- rep
- stosb
-
- mov rip_&name&_data.rip_table_ptr, offset rip_&name&_data.rip_table-(size rip_entry)
-
- ;; start RIP listening for packets
- mov AX, 18*0
- TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, listen_code
-
- ;; set the RIP request task to go off
- mov AX, 18*2
- TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, rip_&name&_send_request
-
- ;; set the RIP update task to go off
- mov AX, 18*4
- TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, rip_&name&_timer_code
-
- ;; set the expire task to go off
- mov AX, 18*10
- TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, rip_&name&_expire_code
- RET
- ENDM
-
-
- ;;******************************************************************************
- ;; ROUTE_ADD_in_AX_CX_DX_SI_DI_ES name
- ;; ROUTE_ADD adds the route described by network pointed to by SI:ES,
- ;; the subnet mask pointed to by DX:ES (DX is null if there is no mask),
- ;; the gateway pointed to by DI:ES, the route id in AX and the metric
- ;; held in CL and flags (see flag defs above) held in CH.
- ;; Note: For directly connected networks (CL = 0) the 'gateway' (DI:ES)
- ;; must point to the IP address of this host.
- ;;
- ROUTE_ADD_in_AX_CX_DX_SI_DI_ES_const_DI_ES MACRO name
- call route_&name&_real_add
- ENDM
-
- ROUTE_REAL_ADD_in_AX_CX_DX_SI_DI_ES_const_DI_ES MACRO name
- local done, look_for_empty, found_empty, no_wrap, found, new_route
- local add_new_gateway, not_bigger, delete_route, save_mask, save_id
- local check_mask, have_mask, store_mask, check_route, found_mask
- local no_timer, no_delete, log_it, is_source, skip_source
-
- .DATA
- save_mask DD ?
- save_id DW ?
- .CODE
-
- mov BP, DI ;; save DI
- mov word ptr save_id, AX ;; save route id
- mov AX, word ptr ES:[SI] ;; check for default route
- or AX, word ptr ES:[SI+2]
- jnz check_mask
- mov BX, AX
- jmp store_mask
- check_mask:
- or DX, DX
- jnz have_mask
- mov AL, byte ptr ES:[SI] ;; reconstruct the netmask
- mov AH, 0ffh
- mov BX, 0ffffh
- IP_COMP_NET_in_AX_BX_out_AX_BX_const_CX_DX_BP_SI_DI_ES
- mov AL, 0ffh
- mov word ptr save_mask, AX
- mov word ptr save_mask+2, BX
- not AX
- not BX
- and AX, word ptr ES:[SI]
- and BX, word ptr ES:[SI+2]
- or AX, BX ;; check for host bits
- jz check_route
- mov AX, word ptr ES:[SI]
- mov BX, word ptr ES:[SI+2]
-
- IRP idx, <1,2,3,4,5,6,7,8>
- if idx le rip_&name&_dls
- RIP_GET_IF_NETMASK_in_AX_BX_out_AX_BX_const_CX_DX_BP_SI_DI_ES idx, found_mask
- endif
- endm
- mov AX, 0ffffh ;; 255.255.255.255
- mov BX, AX
- jmp store_mask
-
- found_mask:
- mov word ptr save_mask, AX
- mov word ptr save_mask+2, BX
- not AX
- not BX
- and AX, word ptr ES:[SI]
- and BX, word ptr ES:[SI+2]
- or AX, BX ;; check for host bits
- jz check_route
- mov AX, 0ffffh ;; 255.255.255.255
- mov BX, AX
- jmp store_mask
- have_mask:
- mov DI, DX
- mov AX, word ptr ES:[DI]
- mov BX, word ptr ES:[DI+2]
- store_mask:
- mov word ptr save_mask, AX
- mov word ptr save_mask+2, BX
- check_route:
- mov AX, ES:[SI]
- mov BX, ES:[SI+2]
- test CH, ROUTE_SOURCE
- jnz is_source
- RIP_GET_ENTRY_in_AX_BX_out_SI_DI_const_AX_BX_CX_BP name, save_mask, found
- jmp skip_source
- is_source:
- mov DI, word ptr save_id
- RIP_GET_SRC_ENTRY_in_AX_BX_DI_out_SI_DI_const_AX_BX_CX_BP name, save_mask, found
- skip_source:
- cmp CL, 16
- jae done
- mov SI, word ptr rip_&name&_data.rip_table_ptr
- look_for_empty:
- add SI, size rip_entry
- cmp SI, offset rip_&name&_data.rip_table_end
- jb no_wrap
- mov SI, offset rip_&name&_data.rip_table
- no_wrap:
- test byte ptr [SI.re_flags], ROUTE_VALID
- jz found_empty
-
- cmp SI, word ptr rip_&name&_data.rip_table_ptr
- jnz look_for_empty
- LOG_PRINT %mylog, L_SYS, L_ERR, <Routing table overflow>
- jmp done
- found_empty:
- cmp SI, word ptr rip_&name&_data.rip_table_ptr
- jbe not_bigger
- mov word ptr rip_&name&_data.rip_table_ptr, SI
- not_bigger:
- mov [SI.re_prev], DI ;; link this in last in the list
- mov [DI.re_next], SI
-
- mov [SI+re_next], 0 ;; fill in next
- mov word ptr [SI+re_net], AX
- mov word ptr [SI+re_net+2], BX
- mov AX, word ptr save_mask
- mov BX, word ptr save_mask+2
- mov word ptr [SI+re_mask], AX
- mov word ptr [SI+re_mask+2], BX
- or CH, ROUTE_VALID ;; fill in flags
- mov byte ptr [SI+re_flags], CH
- mov AX, word ptr save_id
- mov word ptr [SI+re_id], AX
- test CH, ROUTE_SOURCE
- jz add_new_gateway
- jmp done
-
- delete_route:
- RIP_DELETE_in_SI_const_BX_CX_DX_SI_BP name
- jmp done
-
- found:
- test [SI+re_flags], ROUTE_TRANS ;; cant change a permanent route
- jz done
-
- mov DI, BP ;; restore DI
- mov DX, ES:[DI]
- cmp DX, [SI+re_gateway]
- jnz new_route
- mov DX, ES:[DI+2]
- cmp DX, [SI+re_gateway+2]
- jnz new_route
- mov DL, 18
- cmp CL, 16
- jb no_delete
- cmp byte ptr [SI+re_timer], 0
- jbe no_timer
- xor DL, DL
- no_delete:
- mov byte ptr [SI+re_timer], DL
- no_timer:
- cmp CL, byte ptr [SI+re_metric]
- je done
- mov byte ptr [SI+re_metric], CL
- jmp log_it
- new_route:
- cmp CL, [SI+re_metric]
- jae done ;; old metric less, we are done
-
- add_new_gateway:
- mov DI, BP ;; restore DI
- mov byte ptr [SI+re_timer], 18
- mov byte ptr [SI+re_metric], CL
- mov AX, ES:[DI]
- mov BX, ES:[DI+2]
- mov word ptr [SI+re_gateway], AX
- mov word ptr [SI+re_gateway+2], BX
- mov byte ptr [SI+re_interface], 0 ;; Avoid finding this new route
- RIP_FIND_IF_in_AX_BX_out_AX_BX_CL_const_SI_DI %rip_&name&_dls, delete_route
- mov word ptr [SI+re_igateway], AX
- mov word ptr [SI+re_igateway+2], BX
- mov byte ptr [SI+re_interface], CL
-
- log_it:
- LOG_PRINT %mylog, L_ROUTE, L_INFO, <Adding/updating route>
- RIP_LOG_ROUTE_in_SI_const_all name, L_INFO
- done:
- mov DI, BP ;; restore DI
- ENDM
-
-
- ;;*****************************************************************************
- ;; ROUTE_FIND_in_AX_BX_SI_DI_out_AX_BX_DX name, forme, fail, drop
- ;; ROUTE_FIND takes the network number in the AX:BX pair and the
- ;; source address in the SI:DI pair and does one of three things:
- ;; If it is for this host it jumps to 'forme'. If it could find
- ;; no route it jumps to 'fail'. If it found a route that is declared
- ;; as unreachable it jumps to 'drop'. Otherwise outputs the
- ;; interface in DL, the metric in DH and the gateway network number
- ;; of where to send it to in AX:BX.
- ;;
- ROUTE_FIND_in_AX_BX_SI_DI_out_AX_BX_DX_const_CX_BP_ES MACRO name, forme, fail, drop
- local found
-
- call route_&name&_real_find
- or DI, DI
- jz found
- cmp DI, 2
- ja fail
- je forme
- ifnb <drop>
- jmp drop
- endif
- found:
- ENDM
-
- ;; ROUTE_REAL_FIND_in_AX_BX_SI_DI_out_AX_BX_DX_DI name
- ;; ROUTE_REAL_FIND returns an error status in DI:
- ;; 0 = route was found
- ;; 1 = route was found but is declared as unreachable
- ;; 2 = the packet is for me
- ;; 3 = no route could be found
- ;;
- ROUTE_REAL_FIND_in_AX_BX_SI_DI_out_AX_BX_DX_DI_const_CX_BP_ES MACRO name
- local found, not_direct, save_address, save_src_address, save_ptr
- local forme, find_route, done, found_src, skip, skip1, not_found
-
- .DATA
- save_address DD ?
- save_src_address DD ?
- save_ptr DW ?
- .CODE
-
- irp idx, <1,2,3,4,5,6,7,8>
- if idx le ip_&name&_dls
- CHECK_FORME_in_AX_BX_out_DX_const_AX_BX_CX_BP_SI_DI_ES idx, forme
- endif
- endm
- jmp find_route
-
- forme:
- mov DI, 2
- jmp done
-
- find_route:
- mov word ptr save_address, AX
- mov word ptr save_address+2, BX
- mov word ptr save_src_address, SI
- mov word ptr save_src_address+2, DI
- RIP_GET_NET_ENTRY_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI %ip_&name&_router, found
- RIP_GET_DEFAULT_ENTRY_out_SI_const_AX_BX_CX_BP_DI %ip_&name&_router, found
-
- not_found:
- mov DI, 3
- jmp done
-
- found:
- mov AX, word ptr save_src_address
- or AX, AX
- jz skip1
- mov BX, word ptr save_src_address+2
- mov DI, word ptr [SI+re_id]
- mov word ptr save_ptr, SI
- 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
- RIP_GET_SRC_DEFAULT_ENTRY_in_DI_out_SI_const_AX_BX_CX_BP_DI %ip_&name&_router, %ip_&name&_dls, found_src
- jmp skip
-
- found_src:
- test byte ptr [SI+re_flags], ROUTE_DENY
- jnz not_found
-
- skip:
- mov SI, word ptr save_ptr
- skip1:
- mov DX, word ptr [SI+re_interface] ; load DL=interface DH=metric
- cmp DH, 16
- jae not_found
- mov AX, [SI+re_igateway]
- mov BX, [SI+re_igateway+2]
- or DH, DH
- jnz not_direct ; For direct routes
- mov AX, word ptr save_address ; gateway to destination address
- mov BX, word ptr save_address+2 ;
- not_direct:
- xor DI, DI
- test byte ptr [SI+re_flags], ROUTE_DROP
- jz done
- inc DI
- done:
- ENDM
-
- CHECK_FORME_in_AX_BX_out_DX_const_AX_BX_CX_BP_SI_DI_ES MACRO name, forme
- local not_for_me
-
- cmp AX, word ptr dl_ip_&name&_ip
- jne not_for_me
- cmp BX, word ptr dl_ip_&name&_ip+2
- jne not_for_me
- mov DL, name
- xor DH, DH
- jmp forme
- not_for_me:
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_TASK is the code that sends RIP packets to the interfaces every
- ;; 30 seconds. It splits the 30 second interval in equal parts and does
- ;; one interface at a time. This causes a more balanced load on the
- ;; router.
- ;;
- RIP_TASK MACRO name
- local timer_code, rip_loop, set_timer, no_wrap
- local rip_dl_count, rip_dl_init
-
- .DATA
- rip_dl_count DB rip_&name&_dls
- rip_dl_init DB 1
-
- .CODE
- timer_code:
- rip_loop:
- xor AX, AX
- mov BX, AX
- mov CX, RIP_PORT
- mov DL, byte ptr rip_dl_count
- RIP_SEND_in_AX_BX_CX_DL name
-
- mov DL, byte ptr rip_dl_count
- dec DL
- jnz no_wrap
- mov byte ptr rip_dl_count, rip_&name&_dls
- mov byte ptr rip_dl_init, 0
- jmp set_timer
-
- no_wrap:
- mov byte ptr rip_dl_count, DL
- cmp byte ptr rip_dl_init, 1 ;; do all interfaces the first time
- je rip_loop
-
- set_timer:
- mov AX, 18*30/rip_&name&_dls ;; resubmit the task
- TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, timer_code
- ENDM
-
-
- ;;*****************************************************************************
- ;; RIP_SEND_in_AX_BX_CX_DX sends the contents of the routing table as
- ;; RIP packets to the IP address in AX:BX and the UDP port in CX.
- ;; DL contains the number of the interface the packets should be sent to.
- ;; If DL is zero no RIP packets are sent but instead an expire of the
- ;; routing table is performed.
- ;;
- RIP_SEND_in_AX_BX_CX_DL MACRO name
- call rip_&name&_send_code
- ENDM
-
-
- ;;*****************************************************************************
- ;; RIP_INIT_DL_LABEL generates a code lable for use in a jump table for
- ;; 'name', 'dl'. 'suffix' is a unique suffix
- ;;
- RIP_INIT_DL_LABEL MACRO name, dl, suffix
- rip_&name&_dl_&dl&_&suffix:
- ENDM
-
- ;;*****************************************************************************
- ;; RIP_INIT_DL_JMP_TAB generates the table entry for the entry 'name', 'dl'
- ;; 'suffix' is a unique suffix.
- ;; This is meant for use in a .DATA section
- ;;
- RIP_INIT_DL_JMP_TAB MACRO name, dl, suffix
- dw rip_&name&_dl_&dl&_&suffix
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_SEND_DL generates all the RIP packets for the data link interface 'mydl'
- ;;
- RIP_SEND_DL MACRO name, mydl
- local done, pack_loop, no_bcast, skip
- .errb <mydl>
-
- cmp word ptr rip_&name&_data.rip_udp_port, RIP_PORT
- jne skip
- test word ptr dl_ip_&mydl&_flags, (ROUTE_SEND_RIP) or (ROUTE_SEND_DEFROUTE)
- jz done ;; skip silent ifs
-
- skip:
- mov AX, word ptr dl_ip_&mydl&_net
- mov BX, word ptr dl_ip_&mydl&_net+2
- IP_COMP_NET_in_AX_BX_out_AX_BX_const_CX_DX_BP_SI_DI_ES
- mov word ptr rip_&name&_data.rip_if_net, AX
- mov word ptr rip_&name&_data.rip_if_net+2, BX
-
- RIP_INIT_ENTRY_out_SI_const_AX_BX_CX_DX_BP_DI name
- mov rip_&name&_data.rip_pack_out, SI
- pack_loop:
- mov CX, 512 ;; maximum RIP packet size
- mov DX, word ptr rip_&name&_data.rip_udp_port
- mov AX, word ptr rip_&name&_data.rip_target
- mov BX, word ptr rip_&name&_data.rip_target+2
- or AX, AX
- jnz no_bcast
- or BX, BX
- jnz no_bcast
- mov AX, word ptr dl_ip_&mydl&_broad
- mov BX, word ptr dl_ip_&mydl&_broad+2
- no_bcast:
-
- UDP_SOCK_W_ACCESS_in_AX_BX_CX_DX_out_AX_DI_ES %rip_&name&_udp_sock
- cmp AX, 0
- jnz done
-
- mov DX, word ptr dl_ip_&mydl&_metric
- mov SI, rip_&name&_data.rip_pack_out
- RIP_MAKE_PACKET_in_DX_SI_DI_out_CX_SI name, mydl, rip_&name&_data.rip_if_net, done
- mov rip_&name&_data.rip_pack_out, SI
-
- UDP_SOCK_W_WRITE_in_CX %rip_&name&_udp_sock
- jmp pack_loop
- done:
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_DELETE_in_SI_const_BX_CX_DX_SI_BP deletes the entry pointed by by SI
- ;;
- RIP_DELETE_in_SI_const_BX_CX_DX_SI_BP MACRO name
- local end_of_list
-
- mov byte ptr [SI+re_flags], 0 ;; make the route invalid
- mov DI, [SI+re_prev]
- mov AX, [SI+re_next]
- mov [DI.re_next], AX
- or AX, AX
- jz end_of_list
- xchg AX, DI
- mov [DI+re_prev], AX
- end_of_list:
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_EXPIRE should be called every 10 seconds. This routine decrements
- ;; the timer entries on the routes and expires the routes after 180 seconds.
- ;;
- RIP_EXPIRE_const_BX_CX_DX_BP MACRO name
- local expire_code, expire_loop, done, invalidate_route
- .errb <name>
-
- expire_code:
- RIP_INIT_ENTRY_out_SI_const_AX_BX_CX_DX_BP_DI name
- expire_loop:
- RIP_NEXT_ENTRY_in_SI_out_SI_const_AX_BX_CX_DX_BP_DI name, done
- test [SI+re_flags], ROUTE_TRANS ;; don't expire permenent routes
- jz expire_loop
-
- sub [SI+re_timer], 1 ;; decrement the timer
- jg expire_loop
- jz invalidate_route
- ;; check to see if we should purge it from the table
- cmp [SI+re_timer], -12
- jg expire_loop
- LOG_PRINT %mylog, L_ROUTE, L_INFO, <Deleting expired route>
- RIP_LOG_ROUTE_in_SI_const_all name, L_INFO
- RIP_DELETE_in_SI_const_BX_CX_DX_SI_BP name
- jmp expire_loop
- invalidate_route:
- ;; delete the route
- mov [SI+re_metric], 16
- LOG_PRINT %mylog, L_ROUTE, L_INFO, <Invalidating expired route>
- RIP_LOG_ROUTE_in_SI_const_all name, L_INFO
- jmp expire_loop
- done:
- mov AX, 18*10 ;; resubmit the task
- TIMER_MARK_in_AX_const_CX_BP_ES %rip_&name&_timer, expire_code
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_PROCESS_PACKET processes the packet in ES:SI. The IP address of
- ;; the gateway that sent the packet is pointed to by ES:DI. CX holds
- ;; the length of the RIP part of the packet
-
- RIP_PROCESS_PACKET_in_CX_SI_DI_ES MACRO name
- local process_loop, done, next, if_flags, skip, version, is_reply
- local no_check1, no_check2, jmp_table, rip_length, store_flags
- local src_dl, save_ptr, is_def_route
-
- .DATA
- jmp_table dw done
- IRP idx, <1,2,3,4,5,6,7,8>
- if idx le rip_&name&_dls
- RIP_INIT_DL_JMP_TAB name, idx, load_flags
- endif
- endm
-
- if_flags DW ?
- rip_length DW ?
- save_ptr DW ?
- src_dl DB ?
- version DB ?
- .CODE
-
- mov AL, byte ptr ES:[SI+rip_version]
- cmp AL, RIP_VER
- jl done
- jg no_check1 ;; don't check zeros with later RIP versions
- cmp word ptr ES:[SI+rip_zero1], 0
- jnz done
- no_check1:
- mov byte ptr version, AL
-
- mov word ptr rip_length, CX ;; save packet length
- mov AX, word ptr ES:[DI] ;; find DL for source IP address
- mov BX, word ptr ES:[DI+2]
- RIP_FIND_IF_in_AX_BX_out_AX_BX_CL_const_SI_DI rip_&name&_dls, done
- cmp AX, word ptr ES:[DI] ;; hack! if address has changed, the sender
- jnz done ;; is not on a directly connected network
- cmp BX, word ptr ES:[DI+2]
- jnz done ;; is not on a directly connected network
- mov word ptr save_ptr, DI ;; save IP address pointer
- mov byte ptr src_dl, CL
- xor CH, CH ;; set up jump to proper DL
- shl CX, 1
- mov DI, offset jmp_table
- add DI, CX
- jmp [DI] ;; jump to proper DL
-
- ;; the above jump goes to one of the code fragments below
- IRP idx, <1,2,3,4,5,6,7,8>
- if idx le rip_&name&_dls
- RIP_INIT_DL_LABEL name, idx, load_flags
-
- RIP_LOAD_FLAGS idx ;; load DX with the flags for this DL
- jmp store_flags
- endif
- endm
- ;; the above code does NOT fall through
-
- store_flags:
- mov word ptr if_flags, DX
- mov CX, word ptr rip_length ;; restore packet length
- mov DI, word ptr save_ptr ;; restore IP address pointer
-
- mov AL, byte ptr ES:[SI+rip_command]
- cmp AL, RIP_REPLY
- jz is_reply
- cmp AL, RIP_REQUEST
- jnz done
- cmp CX, 24 ;; exactly one entry?
- jne done
- cmp word ptr ES:[SI+rip_family+4], 0
- jnz done
- cmp byte ptr ES:[SI+rip_metric+7], 16
- jnz done
- mov AX, word ptr ES:[DI]
- mov BX, word ptr ES:[DI+2]
- sub SI, size udp
- mov CX, word ptr ES:[SI+udp_src]
- xchg CH, CL
- mov DL, byte ptr src_dl
- RIP_SEND_in_AX_BX_CX_DL name
- jmp done
-
- is_reply:
- test word ptr if_flags, (ROUTE_LISTEN_RIP) or (ROUTE_LISTEN_DEFROUTE)
- jz done
- sub SI, size udp
- cmp word ptr ES:[SI+udp_src], SWAPPED_RIP_PORT
- jnz done ;; don't accept RIP updates from other UDP ports
- add SI, (size udp)+4
- sub CX, 4
- process_loop:
- sub CX, 20
- jb done
-
- cmp word ptr ES:[SI+rip_family], SWAPPED_IP_FAMILY
- jnz next
- cmp byte ptr version, RIP_VER
- jg no_check2 ;; don't check zeros with later RIP versions
- xor DX, DX
- cmp word ptr ES:[SI+rip_zero2], DX
- jnz next
- cmp word ptr ES:[SI+rip_zero3], DX
- jnz next
- cmp word ptr ES:[SI+rip_zero3+2], DX
- jnz next
- cmp word ptr ES:[SI+rip_zero4], DX
- jnz next
- cmp word ptr ES:[SI+rip_zero4+2], DX
- jnz next
-
- no_check2:
- mov DX, word ptr ES:[SI+rip_address] ;; check for default route
- or DX, word ptr ES:[SI+rip_address+2]
- jz is_def_route
- test word ptr if_flags, ROUTE_LISTEN_RIP
- jz next
- jmp skip
-
- is_def_route:
- test word ptr if_flags, ROUTE_LISTEN_DEFROUTE
- jz next
-
- skip:
- mov word ptr rip_&name&_data.rip_pack_ctr, CX
- mov word ptr rip_&name&_data.rip_pack_ptr, SI
- mov CL, byte ptr ES:[SI+rip_metric+3]
- mov CH, ROUTE_TRANS
- add SI, rip_address
- xor DX, DX
- mov AL, byte ptr src_dl
- xor AH, AH
- inc AX
- ROUTE_ADD_in_AX_CX_DX_SI_DI_ES_const_DI_ES name
- mov CX, word ptr rip_&name&_data.rip_pack_ctr
- mov SI, word ptr rip_&name&_data.rip_pack_ptr
-
- next:
- add SI, 20
- jmp process_loop
- done:
- ENDM
-
- RIP_LOAD_FLAGS MACRO dl
- mov DX, word ptr dl_ip_&dl&_flags
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_SEND_REQUEST sends a RIP request to interface 'mydl'.
- ;;
- RIP_SEND_REQUEST MACRO name, mydl
- local done
- .errb <mydl>
-
- test word ptr dl_ip_&mydl&_flags, (ROUTE_LISTEN_RIP) or (ROUTE_LISTEN_DEFROUTE)
- jz done ;; skip deaf ifs
- mov AX, word ptr dl_ip_&mydl&_broad
- mov BX, word ptr dl_ip_&mydl&_broad+2
- mov CX, 24 ;; RIP request packet size
- mov DX, RIP_PORT
-
- UDP_SOCK_W_ACCESS_in_AX_BX_CX_DX_out_AX_DI_ES %rip_&name&_udp_sock
- cmp AX, 0
- jnz done
-
- ;; make up header
- mov AL, RIP_REQUEST ;; this is a request packet
- stosb
- mov AL, 1 ;; version 1
- stosb
- xor AX, AX ;; must be 0
- stosw
-
- stosw
- stosw
- stosw
- stosw
- stosw
- stosw
- stosw
- stosw
-
- stosw ;; 4 bytes of metric
- mov AH, 16
- stosw
-
- mov CX, 24 ;; RIP request packet size
- UDP_SOCK_W_WRITE_in_CX %rip_&name&_udp_sock
- done:
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_MAKE_PACKET generates a RIP packet in DI:ES for the interface 'mydl'
- ;; by calling accessing the routing table by means of RIP_NEXT_ENTRY.
- ;; Thus it assumes SI has been initialized with RIP_INIT_ENTRY or is
- ;; a continuation of a RIP_NEXT_ENTRY. CX is set to the length of the
- ;; packet. It jumps to 'dont_send' when there is not data to send out, so
- ;; that the packet should not be sent. DX contains the metric for the
- ;; interface. 'if_net' is a pointer to the network part (not assuming
- ;; subnets, that is based strictly on the class of the address). This
- ;; is used to implement the subnet hiding.
-
- RIP_MAKE_PACKET_in_DX_SI_DI_out_CX_SI MACRO name, mydl, if_net, dont_send
- local route_loop, packet_full, metric_ok, not_default, skip, skip1
- local skip1a, skip2, skip3, check_route
- local send_full_route, not_same_subnet, not_last, send_metric
- .errb <dont_send>
-
- ;; make up header
- mov AL, RIP_REPLY ;; this is a reply packet
- stosb
- mov AL, RIP_VER ;; RIP version
- stosb
- xor AX, AX ;; must be 0
- stosw
- dec AX ;; AX now = -1
- mov word ptr rip_&name&_data.rip_if_last, AX
- mov word ptr rip_&name&_data.rip_if_last+2, AX
- mov CX, 4
- route_loop:
- cmp word ptr rip_&name&_data.rip_hr_count, 0
- jne check_route
-
- RIP_NEXT_ENTRY_in_SI_out_SI_const_AX_BX_CX_DX_BP_DI name, packet_full
- test byte ptr [SI+re_flags], (ROUTE_SILENT) or (ROUTE_SOURCE)
- jnz route_loop
-
- check_route:
- xor DH, DH ;; clear reverse poison
- cmp byte ptr [SI+re_interface], mydl ;; split horizon
- jnz skip
- test word ptr dl_ip_&mydl&_flags, ROUTE_POISON_REVERSE
- jz route_loop
- mov DH, 16 ;; set reverse poison
-
- skip:
- mov AX, word ptr [SI+re_net] ;; the destination network
- mov BX, word ptr [SI+re_net+2]
- or AX, AX
- jnz not_default
- or BX, BX
- jnz not_default
- cmp word ptr rip_&name&_data.rip_udp_port, RIP_PORT
- jne skip3
- test word ptr dl_ip_&mydl&_flags, ROUTE_SEND_DEFROUTE
- jz route_loop
- jmp skip3
-
- not_default:
- cmp word ptr rip_&name&_data.rip_udp_port, RIP_PORT
- jne skip1
- test word ptr dl_ip_&mydl&_flags, ROUTE_SEND_RIP
- jz route_loop
-
- skip1:
- cmp word ptr rip_&name&_data.rip_hr_count, 0
- je skip2
- skip1a:
- mov AX, SWAPPED_IP_FAMILY ;; Address family
- stosw
- xor AX, AX ;; two bytes of zero
- stosw
- mov AX, word ptr [SI+re_net] ;; the destination network
- stosw
- mov AX, word ptr [SI+re_net+2]
- xchg AH, AL
- add AX, word ptr rip_&name&_data.rip_hr_count
- dec word ptr rip_&name&_data.rip_hr_count
- xchg AH, AL
- stosw
- jmp send_metric
-
- skip2:
- test byte ptr [SI+re_flags], ROUTE_SPLIT
- jz skip3
- mov AX, word ptr [SI+re_mask+2]
- xchg AH, AL
- xor AX, 0ffffh
- cmp AX, MAX_HOST_SPLIT
- jge route_loop
- cmp AX, 3
- jl route_loop
- dec AX
- mov word ptr rip_&name&_data.rip_hr_count, AX
- jmp skip1a
-
- ;; this code implements the hiding of subnet info outside
- ;; the subnet
- skip3:
- IP_COMP_NET_in_AX_BX_out_AX_BX_const_CX_DX_BP_SI_DI_ES
- cmp AX, word ptr if_net
- jnz not_same_subnet
- cmp BX, word ptr if_net+2
- jz send_full_route
- not_same_subnet:
- cmp AX, word ptr rip_&name&_data.rip_if_last
- jnz not_last
- cmp BX, word ptr rip_&name&_data.rip_if_last+2
- jz route_loop
- not_last:
- mov word ptr rip_&name&_data.rip_if_last, AX
- mov word ptr rip_&name&_data.rip_if_last+2, BX
-
- mov AX, SWAPPED_IP_FAMILY ;; Address family
- stosw
- xor AX, AX ;; two bytes of zero
- stosw
- mov AX, word ptr rip_&name&_data.rip_if_last
- stosw
- mov AX, word ptr rip_&name&_data.rip_if_last+2
- stosw
- jmp send_metric
-
- send_full_route:
- mov AX, SWAPPED_IP_FAMILY ;; Address family
- stosw
- xor AX, AX ;; two bytes of zero
- stosw
- mov AX, word ptr [SI+re_net] ;; the destination network
- stosw
- mov AX, word ptr [SI+re_net+2]
- stosw
-
- send_metric:
- xor AX, AX ;; 8 zero bytes
- stosw
- stosw
- stosw
- stosw
- stosw ;; 4 bytes of metric
- mov AH, [SI+re_metric]
- add AH, DL ;; add in the interface metric
- add AH, DH ;; add in the reverse poison
- cmp AH, 16
- jbe metric_ok
- mov AH, 16
- metric_ok:
- stosw
-
- add CX, 20
- cmp CX, 512-20 ;; is there space for another entry
- ja packet_full
- jmp route_loop
-
- packet_full:
- cmp CX, 4
- jz dont_send
- ENDM
-
-
-
- ;;**************************************************************************
- ;; RIP_INIT_ENTRY initilizes SI so that RIP_NEXT_ENTRY works. When
- ;; RIP_NEXT_ENTRY is called, SI will point to the first entry of the
- ;; routing table. This may seem a bit bizarre that RIP_NEXT_ENTRY MUST
- ;; be called immediately after RIP_INIT_ENTRY, but it actually makes
- ;; loops easier to construct.
-
- RIP_INIT_ENTRY_out_SI_const_AX_BX_CX_DX_BP_DI MACRO name
- .errb <name>
-
- mov SI, offset (rip_&name&_data.rip_table - (size rip_entry))
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_NEXT_ENTRY gets the next entry in the table and returns it in
- ;; SI. NOTE: SI must be unchanged from the last RIP_INIT_ENTRY or
- ;; RIP_NEXT_ENTRY for this function to work. It jumps to 'done' if
- ;; there are no more entries.
- ;;
- RIP_NEXT_ENTRY_in_SI_out_SI_const_AX_BX_CX_DX_BP_DI MACRO name, done
- local search_loop
- .errb <done>
-
- search_loop:
- add SI, size rip_entry
- cmp SI, word ptr rip_&name&_data.rip_table_ptr
- ja done
- test [SI+re_flags], ROUTE_VALID
- jz search_loop
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_GET_ENTRY gets the table entry for the address in the AX:BX
- ;; pair and returns a pointer to it in SI. DI returns the pointer to
- ;; the previous entry in the list (useful for insertions and deletions)
- ;; 'netmask' is the name of a memory location where the netmask of the
- ;; address in AX:BX is stored. If an entry for AX:BX is found, the netmask
- ;; in 'netmask' is compared with the netmask of the entry in order to
- ;; determine whether the found entry is of the proper type.
- ;; RIP_GET_ENTRY jumps to 'found' if the host entry could be found.
- ;; If it is not found only DI is valid (SI will be 0).
- ;;
- RIP_GET_ENTRY_in_AX_BX_out_SI_DI_const_AX_BX_CX_BP MACRO name, netmask, found
- local start, next, search_loop, failed
- .errb <found>
-
- RIP_COMP_HASH_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI_ES name
-
- jmp start
- search_loop:
- cmp AX, word ptr [SI+re_net]
- jnz next
- cmp BX, word ptr [SI+re_net+2]
- jnz next
- mov DX, word ptr netmask
- cmp DX, word ptr [SI+re_mask]
- jnz next
- mov DX, word ptr netmask+2
- cmp DX, word ptr [SI+re_mask+2]
- jnz next
- cmp byte ptr [SI+re_interface], 0
- jne found
- next:
- start:
- mov DI, SI
- mov SI, [SI+re_next]
- or SI, SI
- jz failed
- test byte ptr [SI+re_flags], ROUTE_SOURCE
- jnz next
- jmp search_loop
- failed:
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_GET_NET_ENTRY gets the table entry with the narrowest netmask for
- ;; the address in the AX:BX pair and returns a pointer to it in SI.
- ;; It jumps to 'found' if a matching entry could be found. If none is
- ;; found SI will be 0.
- ;;
- RIP_GET_NET_ENTRY_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI MACRO name, found
- local start, next, search_loop, narrow_mask, narrow_ptr, narrow, done
- .errb <found>
-
- .DATA
- narrow_mask DD ?
- narrow_ptr DW ?
- .CODE
-
- xor DX, DX
- mov word ptr narrow_ptr, DX
- not DX
- mov word ptr narrow_mask, DX
- mov word ptr narrow_mask+2, DX
-
- RIP_COMP_HASH_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI_ES name
-
- jmp start
- search_loop:
- mov DX, AX
- and DX, word ptr [SI+re_mask]
- cmp DX, word ptr [SI+re_net]
- jnz next
- mov DX, BX
- and DX, word ptr [SI+re_mask+2]
- cmp DX, word ptr [SI+re_net+2]
- jnz next
- mov DX, word ptr narrow_mask
- and DX, word ptr [SI+re_mask]
- jnz narrow
- mov DX, word ptr narrow_mask+2
- and DX, word ptr [SI+re_mask+2]
- jz next
- narrow:
- cmp byte ptr [SI+re_interface], 0
- je next
- mov word ptr narrow_ptr, SI
- mov DX, word ptr [SI+re_mask]
- not DX
- mov word ptr narrow_mask, DX
- mov DX, word ptr [SI+re_mask+2]
- not DX
- mov word ptr narrow_mask+2, DX
- next:
- start:
- mov SI, word ptr [SI+re_next]
- or SI, SI
- jz done
- test byte ptr [SI+re_flags], ROUTE_SOURCE
- jnz next
- jmp search_loop
- done:
- or SI, word ptr narrow_ptr
- jnz found
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_GET_DEFAULT_ENTRY gets the default table entry and returns a pointer
- ;; to it in SI.
- ;; It jumps to 'found' if the default entry could be found. If it is
- ;; not found SI will be 0.
- ;;
- RIP_GET_DEFAULT_ENTRY_out_SI_const_AX_BX_CX_BP_DI MACRO name, found
- local start, done, next, search_loop, failed
- .errb <found>
-
- xor DX,DX
- mov SI, offset rip_&name&_data.rip_hash
-
- jmp start
- search_loop:
- cmp DX, word ptr [SI+re_net]
- jnz next
- cmp DX, word ptr [SI+re_net+2]
- jnz next
- cmp DL, byte ptr [SI+re_interface]
- jne found
- next:
- start:
- mov SI, [SI+re_next]
- or SI, SI
- jz failed
- test byte ptr [SI+re_flags], ROUTE_SOURCE
- jnz next
- jmp search_loop
- failed:
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_GET_SRC_ENTRY gets the table entry for the source address in the
- ;; AX:BX pair and returns a pointer to it in SI. DI returns the pointer to
- ;; the previous entry in the list (useful for insertions and deletions).
- ;; 'netmask' is the name of a memory location where the netmask of the
- ;; address in AX:BX is stored and DI contains the route id. If an entry
- ;; for DI and AX:BX is found, the netmask in 'netmask' is compared with
- ;; the netmask of the entry in order to determine whether the found entry
- ;; is of the proper type.
- ;; RIP_GET_SRC_ENTRY jumps to 'found' if the source entry could be found.
- ;; If it is not found only DI is valid (SI will be 0).
- ;;
- RIP_GET_SRC_ENTRY_in_AX_BX_DI_out_SI_DI_const_AX_BX_CX_BP MACRO name, netmask, found
- local start, next, search_loop, failed
- .errb <found>
-
- push CX
- mov CX, DI
-
- RIP_COMP_HASH_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI_ES name
-
- jmp start
- search_loop:
- cmp CX, word ptr [SI+re_id]
- jnz next
- cmp AX, word ptr [SI+re_net]
- jnz next
- cmp BX, word ptr [SI+re_net+2]
- jnz next
- mov DX, word ptr netmask
- cmp DX, word ptr [SI+re_mask]
- jnz next
- mov DX, word ptr netmask+2
- cmp DX, word ptr [SI+re_mask+2]
- jnz next
- pop CX
- jmp found
- next:
- start:
- mov DI, SI
- mov SI, [SI+re_next]
- or SI, SI
- jz failed
- test byte ptr [SI+re_flags], ROUTE_SOURCE
- jz next
- jmp search_loop
- failed:
- pop CX
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_GET_SRC_NET_ENTRY gets the table entry with the narrowest netmask for
- ;; the source address in the AX:BX pair and the route id in DI and returns
- ;; a pointer to it in SI.
- ;; It jumps to 'found' if a matching entry could be found. If none is
- ;; found SI will be 0.
- ;;
- RIP_GET_SRC_NET_ENTRY_in_AX_BX_DI_out_SI_const_AX_BX_CX_BP_DI MACRO name, dls, found
- local start, next, search_loop, last_mask, last_id
- local narrow_mask, narrow_ptr, narrow
- local done, match
- .errb <found>
-
- .DATA
- last_mask DD ?
- narrow_mask DD ?
- narrow_ptr DW ?
- last_id DW ?
- .CODE
-
- xor DX, DX
- mov word ptr narrow_ptr, DX
- mov word ptr last_mask, DX
- mov word ptr last_mask+2, DX
- mov word ptr last_id, DX
- not DX
- mov word ptr narrow_mask, DX
- mov word ptr narrow_mask+2, DX
-
- RIP_COMP_HASH_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI_ES name
-
- jmp start
- search_loop:
- mov DX, word ptr [SI+re_id]
- cmp DI, DX
- jz match
- cmp DX, 1
- jg next
- jl match
- cmp DI, dls+1
- jg next
- match:
- mov DX, AX
- and DX, word ptr [SI+re_mask]
- cmp DX, word ptr [SI+re_net]
- jnz next
- mov DX, BX
- and DX, word ptr [SI+re_mask+2]
- cmp DX, word ptr [SI+re_net+2]
- jnz next
- mov DX, word ptr narrow_mask
- and DX, word ptr [SI+re_mask]
- jnz narrow
- mov DX, word ptr narrow_mask+2
- and DX, word ptr [SI+re_mask+2]
- jnz narrow
- mov DX, word ptr last_mask
- cmp DX, word ptr [SI+re_mask]
- jnz next
- mov DX, word ptr last_mask+2
- cmp DX, word ptr [SI+re_mask+2]
- jnz next
- mov DX, word ptr last_id
- cmp DX, word ptr [SI+re_id]
- jg next
- narrow:
- mov word ptr narrow_ptr, SI
- mov DX, word ptr [SI+re_mask]
- mov word ptr last_mask, DX
- not DX
- mov word ptr narrow_mask, DX
- mov DX, word ptr [SI+re_mask+2]
- mov word ptr last_mask+2, DX
- not DX
- mov word ptr narrow_mask+2, DX
- mov DX, word ptr [SI+re_id]
- mov word ptr last_id, DX
- next:
- start:
- mov SI, word ptr [SI+re_next]
- or SI, SI
- jz done
- test byte ptr [SI+re_flags], ROUTE_SOURCE
- jz next
- jmp search_loop
- done:
- or SI, word ptr narrow_ptr
- jnz found
- ENDM
-
-
- ;;**************************************************************************
- ;; RIP_GET_SRC_DEFAULT_ENTRY gets the default source table entry and
- ;; returns a pointer to it in SI.
- ;; It jumps to 'found' if the default entry could be found. If it is
- ;; not found SI will be 0.
- ;;
- RIP_GET_SRC_DEFAULT_ENTRY_in_DI_out_SI_const_AX_BX_CX_BP_DI MACRO name, dls, found
- local start, done, next, search_loop, match, last_id, narrow_ptr
- .errb <found>
-
- .DATA
- last_id DW ?
- narrow_ptr DW ?
- .CODE
-
- xor DX, DX
- mov word ptr narrow_ptr, DX
- mov word ptr last_id, DX
- mov SI, offset rip_&name&_data.rip_hash
-
- jmp start
- search_loop:
- mov DX, word ptr [SI+re_id]
- cmp DI, DX
- jz match
- cmp DX, 1
- jg next
- jl match
- cmp DI, dls+1
- jg next
- match:
- cmp word ptr [SI+re_net], 0
- jnz next
- cmp word ptr [SI+re_net+2], 0
- jnz next
- mov DX, word ptr last_id
- cmp DX, word ptr [SI+re_id]
- jg next
- mov word ptr narrow_ptr, SI
- mov DX, word ptr [SI+re_id]
- mov word ptr last_id, DX
- next:
- start:
- mov SI, word ptr [SI+re_next]
- or SI, SI
- jz done
- test byte ptr [SI+re_flags], ROUTE_SOURCE
- jz next
- jmp search_loop
- done:
- or SI, word ptr narrow_ptr
- jnz found
- ENDM
-
-
- ;;******************************************************************************
- ;; RIP_COMP_HASH
- ;; RIP_COMP_HASH takes an IP address in AX,BX and computes the hash
- ;; table position based on the class of the IP address. SI returns
- ;; the pointer into the hash table.
- ;;
- RIP_COMP_HASH_in_AX_BX_out_SI_const_AX_BX_CX_BP_DI_ES MACRO name
- local class_A, class_B
-
- mov DL, AL
- test AL, 80h ;; normal IP network interpretation
- jz class_A
- test AL, 40h
- jz class_B
- add DL, BL
- class_B:
- add DL, AH
- class_A:
- xor DH, DH
- mov SI, DX
- shl SI, 1
- add SI, offset rip_&name&_data.rip_hash
- ENDM
-
-
- ;;******************************************************************************
- ;; Find interface finds the interface for the network address in AX:BX
- ;; from the dl list 1, 2, ... 'dls'. If no interface could be found then
- ;; look whether ROUTE_FIND is able to find an interface. The resulting
- ;; gateway address is returned in AX:BX and the interface number is put
- ;; into CL. If no interface could be determined, it jumps to 'fail'.
- ;;
- RIP_FIND_IF_in_AX_BX_out_AX_BX_CL_const_SI_DI MACRO dls, fail
- local done, rf_fail
- .errb <fail>
-
- xor CL, CL
- IRP idx, <1,2,3,4,5,6,7,8>
- local notme
- if idx le dls
- RIP_CHECK_IF_in_AX_BX_const_AX_BX_CX_SI_DI_ES idx, notme
- mov CL, idx
- jmp done
- notme:
- endif
- endm
- push AX
- push BX
- push SI
- push DI
- xor SI, SI
- mov DI, SI
- ROUTE_FIND_in_AX_BX_SI_DI_out_AX_BX_DX_const_CX_BP_ES %myip, rf_fail, rf_fail
- mov CL, DL
- pop DI
- pop SI
- pop DX
- pop DX
- jmp done
- rf_fail:
- pop DI
- pop SI
- pop BX
- pop AX
- jmp fail
- done:
- ENDM
-
- ;;*****************************************************************************
- ;; RIP_CHECK_IF_in_AX_BX checks if the ip address in AX:BX matches the network
- ;; associated with 'dl'. If it does NOT it jumps to 'fail'
- ;;
- RIP_CHECK_IF_in_AX_BX_const_AX_BX_CX_SI_DI_ES MACRO dl, fail
- mov DX, BX
- and DX, word ptr dl_ip_&dl&_mask+2
- cmp DX, word ptr dl_ip_&dl&_net+2
- jne fail
- mov DX, AX
- and DX, word ptr dl_ip_&dl&_mask
- cmp DX, word ptr dl_ip_&dl&_net
- jne fail
- ENDM
-
- ;;*****************************************************************************
- ;; RIP_GET_IF_NETMASK_in_AX_BX_out_AX_BX checks if the IP address in AX,BX
- ;; matches the netclass address part of the data link interface 'dl'.
- ;; If it does, it returns the interface netmask in AX,BX and then jumps
- ;; to 'success'.
- ;;
- RIP_GET_IF_NETMASK_in_AX_BX_out_AX_BX_const_CX_DX_BP_SI_DI_ES MACRO dl, success
- local fail, get_mask
- .errb <success>
-
- cmp AL, byte ptr dl_ip_&dl&_net
- jnz fail
- test AL, 80H
- jz get_mask
- cmp AH, byte ptr dl_ip_&dl&_net+1
- jnz fail
- test AL, 40H
- jz get_mask
- cmp BL, byte ptr dl_ip_&dl&_net+2
- jnz fail
-
- get_mask:
- mov AX, word ptr dl_ip_&dl&_mask
- mov BX, word ptr dl_ip_&dl&_mask+2
- jmp success
- fail:
- ENDM
-
-
- ;;*****************************************************************************
- ;; RIP_LOG_ROUTE_in_SI_const_ALL prints out the route entry pointed to by
- ;; SI:DS to the loging host
- ;;
- RIP_LOG_ROUTE_in_SI_const_all MACRO name, severity
- local no_mask, no_gateway, print_metric
-
- push AX
- push BX
-
- mov AX, word ptr [SI+re_net]
- mov BX, word ptr [SI+re_net+2]
- LOG_PRINT_INET_in_AX_BX %mylog, L_ROUTE, severity, < Routing network >
- or AX, BX
- jz no_mask
- mov AX, word ptr [SI+re_mask]
- mov BX, word ptr [SI+re_mask+2]
- LOG_PRINT_INET_in_AX_BX %mylog, L_ROUTE, severity, < With netmask >
- no_mask:
- xor AX, AX
- mov AL, byte ptr [SI+re_interface]
- LOG_PRINT_REG_DEC %mylog, L_ROUTE, severity, < Through interface >, AX
- cmp byte ptr [SI+re_metric], 0 ;; check metric
- jz no_gateway
- mov AX, word ptr [SI+re_gateway]
- mov BX, word ptr [SI+re_gateway+2]
- LOG_PRINT_INET_in_AX_BX %mylog, L_ROUTE, severity, < To gateway >
- jmp print_metric
- no_gateway:
- LOG_PRINT %mylog, L_ROUTE, severity, < To direct connection>
- print_metric:
- xor AX, AX
- mov AL, byte ptr [SI+re_metric]
- LOG_PRINT_REG_DEC %mylog, L_ROUTE, severity, < Metric >, AX
-
- pop BX
- pop AX
- ENDM
-
-