Exemplo n.º 1
0
/* Leave from the all rip routers multicast group. */
static int
ripng_multicast_leave (struct interface *ifp)
{
  int ret;
  struct ipv6_mreq mreq;

  if (if_is_up (ifp) && if_is_multicast (ifp)) {
    memset (&mreq, 0, sizeof (mreq));
    inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
    mreq.ipv6mr_interface = ifp->ifindex;

    ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
		      (char *) &mreq, sizeof (mreq));
    if (ret < 0)
      zlog_warn ("can't setsockopt IPV6_LEAVE_GROUP: %s\n", safe_strerror (errno));

    if (IS_RIPNG_DEBUG_EVENT)
      zlog_debug ("RIPng %s leave from all-rip-routers multicast group",
	         ifp->name);

    if (ret < 0)
      return -1;
  }

  return 0;
}
/* Multicast packet receive socket. */
static int
rip_multicast_join (struct interface *ifp, int sock)
{
  struct listnode *cnode;
  struct connected *ifc;

  if (if_is_operative (ifp) && if_is_multicast (ifp))
    {
      if (IS_RIP_DEBUG_EVENT)
	zlog_debug ("multicast join at %s", ifp->name);

      for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, ifc))
	{
	  struct prefix_ipv4 *p;
	  struct in_addr group;
	      
	  p = (struct prefix_ipv4 *) ifc->address;
      
	  if (p->family != AF_INET)
	    continue;
      
	  group.s_addr = htonl (INADDR_RIP_GROUP);
	  if (ipv4_multicast_join (sock, group, p->prefix, ifp->ifindex) < 0)
	    return -1;
	  else
	    return 0;
	}
    }
  return 0;
}
/* Leave from multicast group. */
static void
rip_multicast_leave (struct interface *ifp, int sock)
{
  struct listnode *cnode;
  struct connected *connected;

  if (if_is_up (ifp) && if_is_multicast (ifp))
    {
      if (IS_RIP_DEBUG_EVENT)
	zlog_debug ("multicast leave from %s", ifp->name);

      for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, connected))
	{
	  struct prefix_ipv4 *p;
	  struct in_addr group;
          
	  p = (struct prefix_ipv4 *) connected->address;
	  
	  if (p->family != AF_INET)
	    continue;
      
	  group.s_addr = htonl (INADDR_RIP_GROUP);
          if (ipv4_multicast_leave (sock, group, p->prefix, ifp->ifindex) == 0)
	    return;
        }
    }
}
/* Send RIP request packet to specified interface. */
static void
rip_request_interface_send (struct interface *ifp, u_char version)
{
  struct sockaddr_in to;

  /* RIPv2 support multicast. */
  if (version == RIPv2 && if_is_multicast (ifp))
    {
      
      if (IS_RIP_DEBUG_EVENT)
	zlog_debug ("multicast request on %s", ifp->name);

      rip_request_send (NULL, ifp, version, NULL);
      return;
    }

  /* RIPv1 and non multicast interface. */
  if (if_is_pointopoint (ifp) || if_is_broadcast (ifp))
    {
      struct listnode *cnode, *cnnode;
      struct connected *connected;

      if (IS_RIP_DEBUG_EVENT)
	zlog_debug ("broadcast request to %s", ifp->name);

      for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, connected))
	{
	  if (connected->address->family == AF_INET)
	    {
	      memset (&to, 0, sizeof (struct sockaddr_in));
	      to.sin_port = htons (RIP_PORT_DEFAULT);
              if (connected->destination)
                /* use specified broadcast or peer destination addr */
                to.sin_addr = connected->destination->u.prefix4;
              else if (connected->address->prefixlen < IPV4_MAX_PREFIXLEN)
	        /* calculate the appropriate broadcast address */
                to.sin_addr.s_addr =
		  ipv4_broadcast_addr(connected->address->u.prefix4.s_addr,
				      connected->address->prefixlen);
	      else
		/* do not know where to send the packet */
	        continue;

	      if (IS_RIP_DEBUG_EVENT)
		zlog_debug ("SEND request to %s", inet_ntoa (to.sin_addr));
	      
	      rip_request_send (&to, ifp, version, connected);
	    }
	}
    }
}
Exemplo n.º 5
0
/* Join to the all rip routers multicast group. */
static int
ripng_multicast_join (struct interface *ifp)
{
  int ret;
  struct ipv6_mreq mreq;
  int save_errno;

  if (if_is_up (ifp) && if_is_multicast (ifp)) {
    memset (&mreq, 0, sizeof (mreq));
    inet_pton(AF_INET6, RIPNG_GROUP, &mreq.ipv6mr_multiaddr);
    mreq.ipv6mr_interface = ifp->ifindex;

    /*
     * NetBSD 1.6.2 requires root to join groups on gif(4).
     * While this is bogus, privs are available and easy to use
     * for this call as a workaround.
     */
    if (ripngd_privs.change (ZPRIVS_RAISE))
      zlog_err ("ripng_multicast_join: could not raise privs");

    ret = setsockopt (ripng->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
		      (char *) &mreq, sizeof (mreq));
    save_errno = errno;

    if (ripngd_privs.change (ZPRIVS_LOWER))
      zlog_err ("ripng_multicast_join: could not lower privs");

    if (ret < 0 && save_errno == EADDRINUSE)
      {
	/*
	 * Group is already joined.  This occurs due to sloppy group
	 * management, in particular declining to leave the group on
	 * an interface that has just gone down.
	 */
	zlog_warn ("ripng join on %s EADDRINUSE (ignoring)\n", ifp->name);
	return 0;		/* not an error */
      }

    if (ret < 0)
      zlog_warn ("can't setsockopt IPV6_JOIN_GROUP: %s",
      		 safe_strerror (save_errno));

    if (IS_RIPNG_DEBUG_EVENT)
      zlog_debug ("RIPng %s join to all-rip-routers multicast group", ifp->name);

    if (ret < 0)
      return -1;
  }
  return 0;
}