/* Ask for routes * Do it only once to an interface, and not even after the interface * was broken and recovered. */ void rip_query(void) { #ifdef _HAVE_SIN_LEN static struct sockaddr_in dst = {sizeof(dst), AF_INET, 0, {0}, {0}}; #else static struct sockaddr_in dst = {AF_INET}; #endif struct interface *ifp; struct rip buf; enum output_type type; if (rip_sock < 0) return; memset(&buf, 0, sizeof(buf)); for (ifp = ifnet; ifp; ifp = ifp->int_next) { /* Skip interfaces those already queried. * Do not ask via interfaces through which we don't * accept input. Do not ask via interfaces that cannot * send RIP packets. * Do try broken interfaces to see if they have healed. */ if (IS_RIP_IN_OFF(ifp->int_state) || ifp->int_query_time != NEVER) continue; /* skip turned off interfaces */ if (!iff_up(ifp->int_if_flags)) continue; buf.rip_vers = (ifp->int_state&IS_NO_RIPV1_OUT) ? RIPv2:RIPv1; buf.rip_cmd = RIPCMD_REQUEST; buf.rip_nets[0].n_family = RIP_AF_UNSPEC; buf.rip_nets[0].n_metric = htonl(HOPCNT_INFINITY); /* Send a RIPv1 query only if allowed and if we will * listen to RIPv1 routers. */ if ((ifp->int_state & IS_NO_RIPV1_OUT) || (ifp->int_state & IS_NO_RIPV1_IN)) { buf.rip_vers = RIPv2; } else { buf.rip_vers = RIPv1; } if (ifp->int_if_flags & IFF_BROADCAST) { /* ordinary, hardware interface */ dst.sin_addr.s_addr = ifp->int_brdaddr; /* Broadcast RIPv1 queries and RIPv2 queries * when the hardware cannot multicast. */ if (buf.rip_vers == RIPv2 && (ifp->int_if_flags & IFF_MULTICAST) && !(ifp->int_state & IS_NO_RIP_MCAST)) { type = OUT_MULTICAST; } else { type = OUT_BROADCAST; } } else if (ifp->int_if_flags & IFF_POINTOPOINT) { /* point-to-point hardware interface */ dst.sin_addr.s_addr = ifp->int_dstaddr; type = OUT_UNICAST; } else if (ifp->int_state & IS_REMOTE) { /* remote interface */ dst.sin_addr.s_addr = ifp->int_addr; type = OUT_UNICAST; } else { /* ATM, HIPPI, etc. */ continue; } ifp->int_query_time = now.tv_sec+SUPPLY_INTERVAL; if (output(type, &dst, ifp, &buf, sizeof(buf)) < 0) if_sick(ifp); } }
/* use configured parameters */ void get_parms(struct interface *ifp) { static boolean_t warned_auth_in, warned_auth_out; struct parm *parmp; int i, num_passwds = 0; if (ifp == NULL) return; /* get all relevant parameters */ for (parmp = parms; parmp != NULL; parmp = parmp->parm_next) { if (parmp->parm_name[0] == '\0' || strcmp(ifp->int_name, parmp->parm_name) == 0 || (parmp->parm_name[0] == '\n' && on_net(ifp->int_addr, parmp->parm_net, parmp->parm_mask))) { /* * This group of parameters is relevant, * so get its settings */ ifp->int_state |= parmp->parm_int_state; for (i = 0; i < MAX_AUTH_KEYS; i++) { if (parmp->parm_auth[i].type == RIP_AUTH_NONE || num_passwds >= MAX_AUTH_KEYS) break; ifp->int_auth[num_passwds++] = parmp->parm_auth[i]; } if (parmp->parm_rdisc_pref != 0) ifp->int_rdisc_pref = parmp->parm_rdisc_pref; if (parmp->parm_rdisc_int != 0) ifp->int_rdisc_int = parmp->parm_rdisc_int; if (parmp->parm_d_metric != 0) ifp->int_d_metric = parmp->parm_d_metric; if (parmp->parm_ripout_addr != 0) ifp->int_ripout_addr = parmp->parm_ripout_addr; } } /* * Set general defaults. * * Default poor-man's router discovery to a metric that will * be heard by old versions of `routed`. They ignored received * routes with metric 15. */ if ((ifp->int_state & IS_PM_RDISC) && ifp->int_d_metric == 0) ifp->int_d_metric = FAKE_METRIC; if (ifp->int_rdisc_int == 0) ifp->int_rdisc_int = DEF_MAXADVERTISEINTERVAL; if (!(ifp->int_if_flags & IFF_MULTICAST) && !(ifp->int_state & IS_REMOTE)) ifp->int_state |= IS_BCAST_RDISC; if (ifp->int_if_flags & IFF_POINTOPOINT) { ifp->int_state |= IS_BCAST_RDISC; /* * By default, point-to-point links should be passive * about router-discovery for the sake of demand-dialing. */ if (!(ifp->int_state & GROUP_IS_SOL_OUT)) ifp->int_state |= IS_NO_SOL_OUT; if (!(ifp->int_state & GROUP_IS_ADV_OUT)) ifp->int_state |= IS_NO_ADV_OUT; } if (0 != (ifp->int_state & (IS_PASSIVE | IS_REMOTE))) ifp->int_state |= IS_NO_RDISC; if (ifp->int_state & IS_PASSIVE) ifp->int_state |= IS_NO_RIP; if (!IS_RIP_IN_OFF(ifp->int_state) && ifp->int_auth[0].type != RIP_AUTH_NONE && !(ifp->int_state & IS_NO_RIPV1_IN) && !warned_auth_in) { writelog(LOG_WARNING, "RIPv1 input via %s" " will be accepted without authentication", ifp->int_name); warned_auth_in = _B_TRUE; } if (!IS_RIP_OUT_OFF(ifp->int_state) && ifp->int_auth[0].type != RIP_AUTH_NONE && !(ifp->int_state & IS_NO_RIPV1_OUT)) { if (!warned_auth_out) { writelog(LOG_WARNING, "RIPv1 output via %s" " will be sent without authentication", ifp->int_name); warned_auth_out = _B_TRUE; } } /* * If not overriden by the rip_neighbor option, set the * default address to which RIP packets will be sent on * this interface. */ if (ifp->int_ripout_addr == 0) { if (ifp->int_state & IS_REMOTE) { /* * By definition we always send RIP packets to * the address assigned to a remote interface. */ ifp->int_ripout_addr = ifp->int_addr; } else if ((ifp->int_state & IS_NO_RIPV1_OUT) && (ifp->int_if_flags & IFF_MULTICAST) && !(ifp->int_state & IS_NO_RIP_MCAST)) { /* * If the interface is being used for RIPv2 * and it supports multicast, and if the user * has not explicitely turned off multicast * RIP output, send to the all RIP routers * multicast address. */ ifp->int_ripout_addr = htonl(INADDR_RIP_GROUP); } else if (ifp->int_if_flags & IFF_POINTOPOINT) { /* * For point-to-point interfaces which don't * fall into the two categories above, just * send to the destination address of the * interface. */ ifp->int_ripout_addr = ifp->int_dstaddr; } else { /* Otherwise, use the broadcast address. */ ifp->int_ripout_addr = ifp->int_brdaddr; } } }