/* 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; }
/* 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; }