FreeBSD/sbin/routed/rdisc.c
/* handle a single address in an advertisement
 */
handle a single address in an advertisement
handle a single address in an advertisement
static void
parse_ad(naddr from,
	 naddr gate,
	 n_long pref,			
	 u_short life,			
	 struct interface *ifp)
{
	static struct msg_limit bad_gate;
	struct dr *drp, *new_drp;
	if (gate == RIP_DEFAULT
	    || !check_dst(gate)) {
		msglim(&bad_gate, from,"router %s advertising bad gateway %s",
		       naddr_ntoa(from),
		       naddr_ntoa(gate));
		return;
	}
	if (ifwithaddr(gate, 1, 0) != NULL) {
		trace_pkt("    discard Router Discovery Ad pointing at us");
		return;
	}
	if (!on_net(gate, ifp->int_net, ifp->int_mask)) {
		trace_pkt("    discard Router Discovery Ad"
			  " toward unreachable net");
		return;
	}
	pref = UNSIGN_PREF(ntohl(pref));
	if (pref == 0 || life < MinMaxAdvertiseInterval) {
		pref = 0;
		life = 0;
	}
	for (new_drp = NULL, drp = drs; drp < &drs[MAX_ADS]; drp++) {
		if (drp->dr_gate == gate) {
			new_drp = drp;
			break;
		}
		if (life == 0)
			continue;	
		if (drp->dr_ts == 0) {
			new_drp = drp;	
		} else if (new_drp == NULL) {
			if ((!(ifp->int_state & IS_SICK)
			     && (drp->dr_ifp->int_state & IS_SICK))
			    || (pref > drp->dr_pref
				&& !((ifp->int_state ^ drp->dr_ifp->int_state)
				     & IS_SICK)))
				new_drp = drp;
		} else if (new_drp->dr_ts != 0) {
			if ((!(new_drp->dr_ifp->int_state & IS_SICK)
			     && (drp->dr_ifp->int_state & IS_SICK))
			    || (new_drp->dr_pref > drp->dr_pref
				&& !((new_drp->dr_ifp->int_state
				      ^ drp->dr_ifp->int_state)
				     & IS_SICK)))
				new_drp = drp;
		}
	}
	if (new_drp == NULL)
		return;
	new_drp->dr_ifp = ifp;
	new_drp->dr_gate = gate;
	new_drp->dr_ts = now.tv_sec;
	new_drp->dr_life = life;
	new_drp->dr_recv_pref = pref;
	new_drp->dr_pref = PREF(pref,ifp);
	if (!(ifp->int_state & IS_SICK))
		ifp->int_rdisc_cnt = MAX_SOLICITATIONS;
}
static void parse_ad ( naddr from , naddr gate , n_long pref , u_short life , struct interface * ifp ) { static struct msg_limit bad_gate ; struct dr * drp , * new_drp ; if ( gate == RIP_DEFAULT || ! check_dst ( gate ) ) { msglim ( & bad_gate , from , " " , naddr_ntoa ( from ) , naddr_ntoa ( gate ) ) ; return ; } if ( ifwithaddr ( gate , 1 , 0 ) != NULL ) { trace_pkt ( " " ) ; return ; } if ( ! on_net ( gate , ifp -> int_net , ifp -> int_mask ) ) { trace_pkt ( " " " " ) ; return ; } pref = UNSIGN_PREF ( ntohl ( pref ) ) ; if ( pref == 0 || life < MinMaxAdvertiseInterval ) { pref = 0 ; life = 0 ; } for ( new_drp = NULL , drp = drs ; drp < & drs [ MAX_ADS ] ; drp ++ ) { if ( drp -> dr_gate == gate ) { new_drp = drp ; break ; } if ( life == 0 ) continue ; if ( drp -> dr_ts == 0 ) { new_drp = drp ; } else if ( new_drp == NULL ) { if ( ( ! ( ifp -> int_state & IS_SICK ) && ( drp -> dr_ifp -> int_state & IS_SICK ) ) || ( pref > drp -> dr_pref && ! ( ( ifp -> int_state ^ drp -> dr_ifp -> int_state ) & IS_SICK ) ) ) new_drp = drp ; } else if ( new_drp -> dr_ts != 0 ) { if ( ( ! ( new_drp -> dr_ifp -> int_state & IS_SICK ) && ( drp -> dr_ifp -> int_state & IS_SICK ) ) || ( new_drp -> dr_pref > drp -> dr_pref && ! ( ( new_drp -> dr_ifp -> int_state ^ drp -> dr_ifp -> int_state ) & IS_SICK ) ) ) new_drp = drp ; } } if ( new_drp == NULL ) return ; new_drp -> dr_ifp = ifp ; new_drp -> dr_gate = gate ; new_drp -> dr_ts = now . tv_sec ; new_drp -> dr_life = life ; new_drp -> dr_recv_pref = pref ; new_drp -> dr_pref = PREF ( pref , ifp ) ; if ( ! ( ifp -> int_state & IS_SICK ) ) ifp -> int_rdisc_cnt = MAX_SOLICITATIONS ; }
handle a single address in an advertisement
handle a single address in an advertisement
/* signed and in network order */ /* in host byte order */ /* ignore pointers to ourself and routes via unreachable networks
	 */ /* Convert preference to an unsigned value
	 * and later bias it by the metric of the interface.
	 */ /* accept new info for a familiar entry
		 */ /* do not worry about dead ads */ /* use unused entry */ /* look for an entry worse than the new one to
			 * reuse.
			 */ /* look for the least valuable entry to reuse
			 */ /* forget it if all of the current entries are better */ /* bias functional preference by metric of the interface */ /* after hearing a good advertisement, stop asking
	 */