Exemplo n.º 1
0
void add_ptopt_localrt(struct interface *ifp)
{
    struct rt_entry *rt;
    struct sockaddr *dst;
    struct sockaddr_in net;
    int state;

    state = RTS_INTERFACE | RTS_PASSIVE;

    /* look for route to logical network */
    memset(&net, 0, sizeof (net));
    net.sin_family = AF_INET;
    net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
    dst = (struct sockaddr *)&net;
    rt = rtfind(dst);
    if (rt && rt->rt_state & RTS_INTERNAL)
        state |= RTS_SUBNET;

    dst = &ifp->int_addr;
    if ((rt = rtfind(dst))!=NULL) {
        if (rt && rt->rt_state & RTS_INTERFACE)
            return;
        rtdelete(rt);
    }
    rtadd(dst, &loopaddr, 1, state);
}
Exemplo n.º 2
0
void addrouteforif(struct interface *ifp)
{
    struct sockaddr_in net;
    struct sockaddr *dst;
    int state;
    struct rt_entry *rt;

    if (ifp->int_flags & IFF_POINTOPOINT)
        dst = &ifp->int_dstaddr;
    else {
        memset(&net, 0, sizeof (net));
        net.sin_family = AF_INET;
        net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY);
        dst = (struct sockaddr *)&net;
    }
    rt = rtfind(dst);
    if (rt &&
            (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE)
        return;
    if (rt)
        rtdelete(rt);
    /*
     * If interface on subnetted network,
     * install route to network as well.
     * This is meant for external viewers.
     */
    if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) {
        struct in_addr subnet;

        subnet = net.sin_addr;
        net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY);
        rt = rtfind(dst);
        if (rt == 0)
            rtadd(dst, &ifp->int_addr, ifp->int_metric,
                  ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) |
                   RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET));
        else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) ==
                 (RTS_INTERNAL|RTS_SUBNET) &&
                 ifp->int_metric < rt->rt_metric)
            rtchange(rt, &rt->rt_router, ifp->int_metric);
        net.sin_addr = subnet;
    }
    if (ifp->int_transitions++ > 0)
        syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
    state = ifp->int_flags &
            (IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET);
    if (ifp->int_flags & IFF_POINTOPOINT &&
            (ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) &
             ifp->int_netmask) != ifp->int_net)
        state &= ~RTS_SUBNET;
    if (ifp->int_flags & IFF_LOOPBACK)
        state |= RTS_EXTERNAL;
    rtadd(dst, &ifp->int_addr, ifp->int_metric, state);
    if (ifp->int_flags & IFF_POINTOPOINT && foundloopback)
        add_ptopt_localrt(ifp);
}
Exemplo n.º 3
0
/* Supply dst with the contents of the routing tables.
 * If this won't fit in one packet, chop it up into several.
 */
void
supply(struct sockaddr_in *dst,
       struct interface *ifp,		/* output interface */
       enum output_type type,
       int flash,			/* 1=flash update */
       int vers,			/* RIP version */
       int passwd_ok)			/* OK to include cleartext password */
{
	struct rt_entry *rt;
	int def_metric;


	ws.state = 0;
	ws.gen_limit = 1024;

	ws.to = *dst;
	ws.to_std_mask = std_mask(ws.to.sin_addr.s_addr);
	ws.to_std_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_std_mask;

	if (ifp != NULL) {
		ws.to_mask = ifp->int_mask;
		ws.to_net = ifp->int_net;
		if (on_net(ws.to.sin_addr.s_addr, ws.to_net, ws.to_mask))
			ws.state |= WS_ST_TO_ON_NET;

	} else {
		ws.to_mask = ripv1_mask_net(ws.to.sin_addr.s_addr, 0);
		ws.to_net = ntohl(ws.to.sin_addr.s_addr) & ws.to_mask;
		rt = rtfind(dst->sin_addr.s_addr);
		if (rt)
			ifp = rt->rt_ifp;
	}

	ws.npackets = 0;
	if (flash)
		ws.state |= WS_ST_FLASH;

	if ((ws.ifp = ifp) == NULL) {
		ws.metric = 1;
	} else {
		/* Adjust the advertised metric by the outgoing interface
		 * metric.
		 */
		ws.metric = ifp->int_metric+1;
	}

	ripv12_buf.rip.rip_vers = vers;

	switch (type) {
	case OUT_MULTICAST:
		if (ifp->int_if_flags & IFF_MULTICAST)
			v2buf.type = OUT_MULTICAST;
		else
			v2buf.type = NO_OUT_MULTICAST;
		v12buf.type = OUT_BROADCAST;
		break;

	case OUT_QUERY:
		ws.state |= WS_ST_QUERY;
		/* fall through */
	case OUT_BROADCAST:
	case OUT_UNICAST:
		v2buf.type = (vers == RIPv2) ? type : NO_OUT_RIPV2;
		v12buf.type = type;
		break;

	case NO_OUT_MULTICAST:
	case NO_OUT_RIPV2:
		break;			/* no output */
	}

	if (vers == RIPv2) {
		/* full RIPv2 only if cannot be heard by RIPv1 listeners */
		if (type != OUT_BROADCAST)
			ws.state |= WS_ST_RIP2_ALL;
		if ((ws.state & WS_ST_QUERY)
		    || !(ws.state & WS_ST_TO_ON_NET)) {
			ws.state |= (WS_ST_AG | WS_ST_SUPER_AG);
		} else if (ifp == NULL || !(ifp->int_state & IS_NO_AG)) {
			ws.state |= WS_ST_AG;
			if (type != OUT_BROADCAST
			    && (ifp == NULL
				|| !(ifp->int_state & IS_NO_SUPER_AG)))
				ws.state |= WS_ST_SUPER_AG;
		}
	}

	ws.a = (vers == RIPv2) ? find_auth(ifp) : 0;
	if (!passwd_ok && ws.a != NULL && ws.a->type == RIP_AUTH_PW)
		ws.a = NULL;
	clr_ws_buf(&v12buf,ws.a);
	clr_ws_buf(&v2buf,ws.a);

	/*  Fake a default route if asked and if there is not already
	 * a better, real default route.
	 */
	if (supplier && (def_metric = ifp->int_d_metric) != 0) {
		if (NULL == (rt = rtget(RIP_DEFAULT, 0))
		    || rt->rt_metric+ws.metric >= def_metric) {
			ws.state |= WS_ST_DEFAULT;
			ag_check(0, 0, 0, 0, def_metric, def_metric,
				 0, 0, 0, supply_out);
		} else {
			def_metric = rt->rt_metric+ws.metric;
		}

		/* If both RIPv2 and the poor-man's router discovery
		 * kludge are on, arrange to advertise an extra
		 * default route via RIPv1.
		 */
		if ((ws.state & WS_ST_RIP2_ALL)
		    && (ifp->int_state & IS_PM_RDISC)) {
			ripv12_buf.rip.rip_vers = RIPv1;
			v12buf.n->n_family = RIP_AF_INET;
			v12buf.n->n_dst = htonl(RIP_DEFAULT);
			v12buf.n->n_metric = htonl(def_metric);
			v12buf.n++;
		}
	}

	rn_walktree(rhead, walk_supply, 0);
	ag_flush(0,0,supply_out);

	/* Flush the packet buffers, provided they are not empty and
	 * do not contain only the password.
	 */
	if (v12buf.n != v12buf.base
	    && (v12buf.n > v12buf.base+1
		|| v12buf.base->n_family != RIP_AF_AUTH))
		supply_write(&v12buf);
	if (v2buf.n != v2buf.base
	    && (v2buf.n > v2buf.base+1
		|| v2buf.base->n_family != RIP_AF_AUTH))
		supply_write(&v2buf);

	/* If we sent nothing and this is an answer to a query, send
	 * an empty buffer.
	 */
	if (ws.npackets == 0
	    && (ws.state & WS_ST_QUERY))
		supply_write(&v12buf);
}