Example #1
0
/* send all of the routing table or just do a flash update
 */
void
rip_bcast(int flash)
{
#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;
	enum output_type type;
	int vers;
	struct timeval rtime;


	need_flash = 0;
	intvl_random(&rtime, MIN_WAITTIME, MAX_WAITTIME);
	no_flash = rtime;
	timevaladd(&no_flash, &now);

	if (rip_sock < 0)
		return;

	trace_act("send %s and inhibit dynamic updates for %.3f sec",
		  flash ? "dynamic update" : "all routes",
		  rtime.tv_sec + ((float)rtime.tv_usec)/1000000.0);

	for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) {
		/* Skip interfaces not doing RIP.
		 * Do try broken interfaces to see if they have healed.
		 */
		if (IS_RIP_OUT_OFF(ifp->int_state))
			continue;

		/* skip turned off interfaces */
		if (!iff_up(ifp->int_if_flags))
			continue;

		vers = (ifp->int_state & IS_NO_RIPV1_OUT) ? RIPv2 : RIPv1;

		if (ifp->int_if_flags & IFF_BROADCAST) {
			/* ordinary, hardware interface */
			dst.sin_addr.s_addr = ifp->int_brdaddr;

			if (vers == RIPv2
			    && !(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;
		}

		supply(&dst, ifp, type, flash, vers, 1);
	}

	update_seqno++;			/* all routes are up to date */
}
Example #2
0
/* Send the contents of the global buffer via the non-multicast socket
 */
int					/* <0 on failure */
output(enum output_type type,
       struct sockaddr_in *dst,		/* send to here */
       struct interface *ifp,
       struct rip *buf,
       int size)			/* this many bytes */
{
	struct sockaddr_in in;
	int flags;
	const char *msg;
	int res;
	naddr tgt_mcast;
	int soc;
	int serrno;

	in = *dst;
	if (in.sin_port == 0)
		in.sin_port = htons(RIP_PORT);
#ifdef _HAVE_SIN_LEN
	if (in.sin_len == 0)
		in.sin_len = sizeof(in);
#endif

	soc = rip_sock;
	flags = 0;

	switch (type) {
	case OUT_QUERY:
		msg = "Answer Query";
		if (soc < 0)
			soc = ifp->int_rip_sock;
		break;
	case OUT_UNICAST:
		msg = "Send";
		if (soc < 0)
			soc = ifp->int_rip_sock;
		flags = MSG_DONTROUTE;
		break;
	case OUT_BROADCAST:
		if (ifp->int_if_flags & IFF_POINTOPOINT) {
			msg = "Send";
		} else {
			msg = "Send bcast";
		}
		flags = MSG_DONTROUTE;
		break;
	case OUT_MULTICAST:
		if (ifp->int_if_flags & IFF_POINTOPOINT) {
			msg = "Send pt-to-pt";
		} else if (ifp->int_state & IS_DUP) {
			trace_act("abort multicast output via %s"
				  " with duplicate address",
				  ifp->int_name);
			return 0;
		} else {
			msg = "Send mcast";
			if (rip_sock_mcast != ifp) {
#ifdef MCAST_PPP_BUG
				/* Do not specify the primary interface
				 * explicitly if we have the multicast
				 * point-to-point kernel bug, since the
				 * kernel will do the wrong thing if the
				 * local address of a point-to-point link
				 * is the same as the address of an ordinary
				 * interface.
				 */
				if (ifp->int_addr == myaddr) {
					tgt_mcast = 0;
				} else
#endif
				tgt_mcast = ifp->int_addr;
				if (0 > setsockopt(rip_sock,
						   IPPROTO_IP, IP_MULTICAST_IF,
						   &tgt_mcast,
						   sizeof(tgt_mcast))) {
					serrno = errno;
					LOGERR("setsockopt(rip_sock,"
					       "IP_MULTICAST_IF)");
					errno = serrno;
					ifp = NULL;
					return -1;
				}
				rip_sock_mcast = ifp;
			}
			in.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
		}
		break;

	case NO_OUT_MULTICAST:
	case NO_OUT_RIPV2:
	default:
#ifdef DEBUG
		abort();
#endif
		return -1;
	}

	trace_rip(msg, "to", &in, ifp, buf, size);

	res = sendto(soc, buf, size, flags,
		     (struct sockaddr *)&in, sizeof(in));
	if (res < 0
	    && (ifp == NULL || !(ifp->int_state & IS_BROKE))) {
		serrno = errno;
		msglog("%s sendto(%s%s%s.%d): %s", msg,
		       ifp != NULL ? ifp->int_name : "",
		       ifp != NULL ? ", " : "",
		       inet_ntoa(in.sin_addr),
		       ntohs(in.sin_port),
		       strerror(errno));
		errno = serrno;
	}

	return res;
}
Example #3
0
/* Send the contents of the global buffer via the non-multicast socket
 */
int					/* <0 on failure */
output(enum output_type type,
       struct sockaddr_in *dst,		/* send to here */
       struct interface *ifp,
       struct rip *buf,
       int size)			/* this many bytes */
{
	struct sockaddr_in osin;
	int flags;
	const char *msg;
	int res;
	int soc;
	int serrno;

	assert(ifp != NULL);
	osin = *dst;
	if (osin.sin_port == 0)
		osin.sin_port = htons(RIP_PORT);
#ifdef _HAVE_SIN_LEN
	if (osin.sin_len == 0)
		osin.sin_len = sizeof(osin);
#endif

	soc = rip_sock;
	flags = 0;

	switch (type) {
	case OUT_QUERY:
		msg = "Answer Query";
		if (soc < 0)
			soc = ifp->int_rip_sock;
		break;
	case OUT_UNICAST:
		msg = "Send";
		if (soc < 0)
			soc = ifp->int_rip_sock;
		flags = MSG_DONTROUTE;
		break;
	case OUT_BROADCAST:
		if (ifp->int_if_flags & IFF_POINTOPOINT) {
			msg = "Send";
		} else {
			msg = "Send bcast";
		}
		flags = MSG_DONTROUTE;
		break;
	case OUT_MULTICAST:
		if ((ifp->int_if_flags & (IFF_POINTOPOINT|IFF_MULTICAST)) ==
		    IFF_POINTOPOINT) {
			msg = "Send pt-to-pt";
		} else if (ifp->int_state & IS_DUP) {
			trace_act("abort multicast output via %s"
				  " with duplicate address",
				  ifp->int_name);
			return 0;
		} else {
			msg = "Send mcast";
			if (rip_sock_mcast != ifp) {
				struct ip_mreqn mreqn;

				memset(&mreqn, 0, sizeof(struct ip_mreqn));
				mreqn.imr_ifindex = ifp->int_index;
				if (0 > setsockopt(rip_sock,
						   IPPROTO_IP,
						   IP_MULTICAST_IF,
						   &mreqn,
						   sizeof(mreqn))) {
					serrno = errno;
					LOGERR("setsockopt(rip_sock, "
					       "IP_MULTICAST_IF)");
					errno = serrno;
					ifp = 0;
					return -1;
				}
				rip_sock_mcast = ifp;
			}
			osin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
		}
		break;

	case NO_OUT_MULTICAST:
	case NO_OUT_RIPV2:
	default:
#ifdef DEBUG
		abort();
#endif
		return -1;
	}

	trace_rip(msg, "to", &osin, ifp, buf, size);

	res = sendto(soc, buf, size, flags,
		     (struct sockaddr *)&osin, sizeof(osin));
	if (res < 0
	    && (ifp == 0 || !(ifp->int_state & IS_BROKE))) {
		serrno = errno;
		msglog("%s sendto(%s%s%s.%d): %s", msg,
		       ifp != 0 ? ifp->int_name : "",
		       ifp != 0 ? ", " : "",
		       inet_ntoa(osin.sin_addr),
		       ntohs(osin.sin_port),
		       strerror(errno));
		errno = serrno;
	}

	return res;
}