Ejemplo n.º 1
0
int pim_assert_build_msg(uint8_t *pim_msg, int buf_size,
			 struct interface *ifp,
			 struct in_addr group_addr,
			 struct in_addr source_addr,
			 uint32_t metric_preference,
			 uint32_t route_metric,
			 uint32_t rpt_bit_flag)
{
  uint8_t *buf_pastend = pim_msg + buf_size;
  uint8_t *pim_msg_curr;
  int pim_msg_size;
  int remain;

  pim_msg_curr = pim_msg + PIM_MSG_HEADER_LEN; /* skip room for pim header */

  /* Encode group */
  remain = buf_pastend - pim_msg_curr;
  pim_msg_curr = pim_msg_addr_encode_ipv4_group(pim_msg_curr,
						remain,
						group_addr);
  if (!pim_msg_curr) {
    char group_str[100];
    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str));
    zlog_warn("%s: failure encoding group address %s: space left=%d",
	      __PRETTY_FUNCTION__, group_str, remain);
    return -1;
  }

  /* Encode source */
  remain = buf_pastend - pim_msg_curr;
  pim_msg_curr = pim_msg_addr_encode_ipv4_ucast(pim_msg_curr,
						remain,
						source_addr);
  if (!pim_msg_curr) {
    char source_str[100];
    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str));
    zlog_warn("%s: failure encoding source address %s: space left=%d",
	      __PRETTY_FUNCTION__, source_str, remain);
    return -2;
  }

  /* Metric preference */
  pim_write_uint32(pim_msg_curr, rpt_bit_flag ?
		   metric_preference | 0x80000000 :
		   metric_preference);
  pim_msg_curr += 4;

  /* Route metric */
  pim_write_uint32(pim_msg_curr, route_metric);
  pim_msg_curr += 4;

  /*
    Add PIM header
  */
  pim_msg_size = pim_msg_curr - pim_msg;
  pim_msg_build_header(pim_msg, pim_msg_size,
		       PIM_MSG_TYPE_ASSERT);

  return pim_msg_size;
}
Ejemplo n.º 2
0
/*********************** MSDP feature APIs *********************************/
int pim_msdp_config_write(struct pim_instance *pim, struct vty *vty,
			  const char *spaces)
{
	struct listnode *mbrnode;
	struct pim_msdp_mg_mbr *mbr;
	struct pim_msdp_mg *mg = pim->msdp.mg;
	char mbr_str[INET_ADDRSTRLEN];
	char src_str[INET_ADDRSTRLEN];
	int count = 0;

	if (!mg) {
		return count;
	}

	if (mg->src_ip.s_addr != INADDR_ANY) {
		pim_inet4_dump("<src?>", mg->src_ip, src_str, sizeof(src_str));
		vty_out(vty, "%sip msdp mesh-group %s source %s\n", spaces,
			mg->mesh_group_name, src_str);
		++count;
	}

	for (ALL_LIST_ELEMENTS_RO(mg->mbr_list, mbrnode, mbr)) {
		pim_inet4_dump("<mbr?>", mbr->mbr_ip, mbr_str, sizeof(mbr_str));
		vty_out(vty, "%sip msdp mesh-group %s member %s\n", spaces,
			mg->mesh_group_name, mbr_str);
		++count;
	}
	return count;
}
Ejemplo n.º 3
0
void pim_forward_stop(struct pim_ifchannel *ch)
{
  struct pim_upstream *up = ch->upstream;

  if (PIM_DEBUG_PIM_TRACE) {
    char source_str[100];
    char group_str[100]; 
    pim_inet4_dump("<source?>", ch->source_addr, source_str, sizeof(source_str));
    pim_inet4_dump("<group?>", ch->group_addr, group_str, sizeof(group_str));
    zlog_debug("%s: (S,G)=(%s,%s) oif=%s",
	       __PRETTY_FUNCTION__,
	       source_str, group_str, ch->interface->name);
  }

  if (!up->channel_oil) {
    char source_str[100];
    char group_str[100]; 
    pim_inet4_dump("<source?>", ch->source_addr, source_str, sizeof(source_str));
    pim_inet4_dump("<group?>", ch->group_addr, group_str, sizeof(group_str));
    zlog_warn("%s: (S,G)=(%s,%s) oif=%s missing channel OIL",
	       __PRETTY_FUNCTION__,
	       source_str, group_str, ch->interface->name);

    return;
  }

  del_oif(up->channel_oil,
	  ch->interface,
	  PIM_OIF_FLAG_PROTO_PIM);
}
static void send_join(struct pim_upstream *up)
{
  zassert(up->join_state == PIM_UPSTREAM_JOINED);

  
  if (PIM_DEBUG_PIM_TRACE) {
    if (PIM_INADDR_IS_ANY(up->rpf.rpf_addr)) {
      char src_str[100];
      char grp_str[100];
      char rpf_str[100];
      pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
      pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
      pim_inet4_dump("<rpf?>", up->rpf.rpf_addr, rpf_str, sizeof(rpf_str));
      zlog_warn("%s: can't send join upstream: RPF'(%s,%s)=%s",
		__PRETTY_FUNCTION__,
		src_str, grp_str, rpf_str);
      /* warning only */
    }
  }
  
  /* send Join(S,G) to the current upstream neighbor */
  pim_joinprune_send(up->rpf.source_nexthop.interface,
  		     up->rpf.rpf_addr,
		     up->source_addr,
		     up->group_addr,
		     1 /* join */);
}
Ejemplo n.º 5
0
int pim_ssmpingd_start(struct pim_instance *pim, struct in_addr source_addr)
{
	struct ssmpingd_sock *ss;

	ss = ssmpingd_find(pim, source_addr);
	if (ss) {
		/* silently ignore request to recreate entry */
		return 0;
	}

	{
		char source_str[INET_ADDRSTRLEN];
		pim_inet4_dump("<src?>", source_addr, source_str,
			       sizeof(source_str));
		zlog_info("%s: starting ssmpingd for source %s",
			  __PRETTY_FUNCTION__, source_str);
	}

	ss = ssmpingd_new(pim, source_addr);
	if (!ss) {
		char source_str[INET_ADDRSTRLEN];
		pim_inet4_dump("<src?>", source_addr, source_str,
			       sizeof(source_str));
		zlog_warn("%s: ssmpingd_new() failure for source %s",
			  __PRETTY_FUNCTION__, source_str);
		return -1;
	}

	return 0;
}
Ejemplo n.º 6
0
int pim_ssmpingd_stop(struct pim_instance *pim, struct in_addr source_addr)
{
	struct ssmpingd_sock *ss;

	ss = ssmpingd_find(pim, source_addr);
	if (!ss) {
		char source_str[INET_ADDRSTRLEN];
		pim_inet4_dump("<src?>", source_addr, source_str,
			       sizeof(source_str));
		zlog_warn("%s: could not find ssmpingd for source %s",
			  __PRETTY_FUNCTION__, source_str);
		return -1;
	}

	{
		char source_str[INET_ADDRSTRLEN];
		pim_inet4_dump("<src?>", source_addr, source_str,
			       sizeof(source_str));
		zlog_info("%s: stopping ssmpingd for source %s",
			  __PRETTY_FUNCTION__, source_str);
	}

	ssmpingd_delete(ss);

	return 0;
}
static void on_primary_address_change(struct interface *ifp,
				      const char *caller,
				      struct in_addr old_addr,
				      struct in_addr new_addr)
{
  struct pim_interface *pim_ifp;

  {
    char old_str[100];
    char new_str[100];
    pim_inet4_dump("<old?>", old_addr, old_str, sizeof(old_str));
    pim_inet4_dump("<new?>", new_addr, new_str, sizeof(new_str));
    zlog_info("%s: %s: primary address changed from %s to %s on interface %s",
	      __PRETTY_FUNCTION__, caller,
	      old_str, new_str, ifp->name);
  }

  pim_ifp = ifp->info;
  if (!pim_ifp) {
    return;
  }

  if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
    return;
  }

  pim_addr_change(ifp);
}
Ejemplo n.º 8
0
static void pim_assert_timer_set(struct pim_ifchannel *ch,
				 int interval)
{
  struct interface *ifp;

  zassert(ch);
  ifp = ch->interface;
  zassert(ifp);

  assert_timer_off(ch);

  if (PIM_DEBUG_PIM_TRACE) {
    char src_str[100];
    char grp_str[100];
    pim_inet4_dump("<src?>", ch->source_addr, src_str, sizeof(src_str));
    pim_inet4_dump("<grp?>", ch->group_addr, grp_str, sizeof(grp_str));
    zlog_debug("%s: (S,G)=(%s,%s) starting %u sec timer on interface %s",
	       __PRETTY_FUNCTION__,
	       src_str, grp_str, interval, ifp->name);
  }

  THREAD_TIMER_ON(master, ch->t_ifassert_timer,
		  on_assert_timer,
		  ch, interval);
}
Ejemplo n.º 9
0
static struct channel_oil *channel_oil_new(struct in_addr group_addr,
					   struct in_addr source_addr,
					   int input_vif_index)
{
  struct channel_oil *c_oil;
  struct interface *ifp_in;

  ifp_in = pim_if_find_by_vif_index(input_vif_index);
  if (!ifp_in) {
    /* warning only */
    char group_str[100]; 
    char source_str[100];
    pim_inet4_dump("<group?>", group_addr, group_str, sizeof(group_str));
    pim_inet4_dump("<source?>", source_addr, source_str, sizeof(source_str));
    zlog_warn("%s: (S,G)=(%s,%s) could not find input interface for input_vif_index=%d",
	      __PRETTY_FUNCTION__,
	      source_str, group_str, input_vif_index);
  }

  c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil));
  if (!c_oil) {
    zlog_err("PIM XCALLOC(%zu) failure", sizeof(*c_oil));
    return 0;
  }

  c_oil->oil.mfcc_mcastgrp = group_addr;
  c_oil->oil.mfcc_origin   = source_addr;
  c_oil->oil.mfcc_parent   = input_vif_index;
  c_oil->oil_ref_count     = 1;

  zassert(c_oil->oil_size == 0);

  return c_oil;
}
Ejemplo n.º 10
0
/* Issue IGMP general query */
static int pim_igmp_general_query(struct thread *t)
{
  char   query_buf[PIM_IGMP_BUFSIZE_WRITE];
  struct igmp_sock *igmp;
  struct in_addr dst_addr;
  struct in_addr group_addr;
  struct pim_interface *pim_ifp;

  zassert(t);

  igmp = THREAD_ARG(t);

  zassert(igmp);
  zassert(igmp->interface);
  zassert(igmp->interface->info);

  pim_ifp = igmp->interface->info;

  /*
    RFC3376: 4.1.12. IP Destination Addresses for Queries

    In IGMPv3, General Queries are sent with an IP destination address
    of 224.0.0.1, the all-systems multicast address.  Group-Specific
    and Group-and-Source-Specific Queries are sent with an IP
    destination address equal to the multicast address of interest.
  */

  dst_addr.s_addr   = htonl(INADDR_ALLHOSTS_GROUP);
  group_addr.s_addr = PIM_NET_INADDR_ANY;

  if (PIM_DEBUG_IGMP_TRACE) {
    char querier_str[100];
    char dst_str[100];
    pim_inet4_dump("<querier?>", igmp->ifaddr, querier_str,
		   sizeof(querier_str));
    pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str));
    zlog_debug("Querier %s issuing IGMP general query to %s on %s",
	       querier_str, dst_str, igmp->interface->name);
  }

  pim_igmp_send_membership_query(0 /* igmp_group */,
				 igmp->fd,
				 igmp->interface->name,
				 query_buf,
				 sizeof(query_buf),
				 0 /* num_sources */,
				 dst_addr,
				 group_addr,
				 pim_ifp->igmp_query_max_response_time_dsec,
				 1 /* s_flag: always set for general queries */,
				 igmp->querier_robustness_variable,
				 igmp->querier_query_interval);

  pim_igmp_general_query_on(igmp);

  return 0;
}
Ejemplo n.º 11
0
int pim_msg_send(int fd,
		 struct in_addr dst,
		 uint8_t *pim_msg,
		 int pim_msg_size,
		 const char *ifname)
{
  ssize_t            sent;
  struct sockaddr_in to;
  socklen_t          tolen;

  if (PIM_DEBUG_PIM_PACKETS) {
    char dst_str[100];
    pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str));
    zlog_debug("%s: to %s on %s: msg_size=%d checksum=%x",
	       __PRETTY_FUNCTION__,
	       dst_str, ifname, pim_msg_size,
	       *(uint16_t *) PIM_MSG_HDR_OFFSET_CHECKSUM(pim_msg));
  }

#if 0
  memset(&to, 0, sizeof(to));
#endif
  to.sin_family = AF_INET;
  to.sin_addr = dst;
#if 0
  to.sin_port = htons(0);
#endif
  tolen = sizeof(to);

  if (PIM_DEBUG_PIM_PACKETDUMP_SEND) {
    pim_pkt_dump(__PRETTY_FUNCTION__, pim_msg, pim_msg_size);
  }

  sent = sendto(fd, pim_msg, pim_msg_size, MSG_DONTWAIT,
                (struct sockaddr *)&to, tolen);
  if (sent != (ssize_t) pim_msg_size) {
    int e = errno;
    char dst_str[100];
    pim_inet4_dump("<dst?>", dst, dst_str, sizeof(dst_str));
    if (sent < 0) {
      zlog_warn("%s: sendto() failure to %s on %s: fd=%d msg_size=%d: errno=%d: %s",
		__PRETTY_FUNCTION__,
		dst_str, ifname, fd, pim_msg_size,
		e, safe_strerror(e));
    }
    else {
      zlog_warn("%s: sendto() partial to %s on %s: fd=%d msg_size=%d: sent=%zd",
		__PRETTY_FUNCTION__,
		dst_str, ifname, fd,
		pim_msg_size, sent);
    }
    return -1;
  }

  return 0;
}
Ejemplo n.º 12
0
/*
  igmp_source_forward_stop: stop fowarding, but keep the source
  igmp_source_delete:       stop fowarding, and delete the source
 */
void igmp_source_forward_stop(struct igmp_source *source)
{
  struct igmp_group *group;
  int result;

  if (PIM_DEBUG_IGMP_TRACE) {
    char source_str[100];
    char group_str[100]; 
    pim_inet4_dump("<source?>", source->source_addr, source_str, sizeof(source_str));
    pim_inet4_dump("<group?>", source->source_group->group_addr, group_str, sizeof(group_str));
    zlog_debug("%s: (S,G)=(%s,%s) igmp_sock=%d oif=%s fwd=%d",
	       __PRETTY_FUNCTION__,
	       source_str, group_str,
	       source->source_group->group_igmp_sock->fd,
	       source->source_group->group_igmp_sock->interface->name,
	       IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
  }

  /* Prevent IGMP interface from removing multicast route multiple
     times */
  if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) {
    return;
  }

  group = source->source_group;

  /*
   It appears that in certain circumstances that 
   igmp_source_forward_stop is called when IGMP forwarding
   was not enabled in oif_flags for this outgoing interface.
   Possibly because of multiple calls. When that happens, we
   enter the below if statement and this function returns early
   which in turn triggers the calling function to assert.
   Making the call to del_oif and ignoring the return code 
   fixes the issue without ill effect, similar to 
   pim_forward_stop below.   
  */
  result = del_oif(source->source_channel_oil,
		   group->group_igmp_sock->interface,
		   PIM_OIF_FLAG_PROTO_IGMP);
  if (result) {
    zlog_warn("%s: del_oif() failed with return=%d",
	      __func__, result);
    return;
  }

  /*
    Feed IGMPv3-gathered local membership information into PIM
    per-interface (S,G) state.
   */
  pim_ifchannel_local_membership_del(group->group_igmp_sock->interface,
				     source->source_addr, group->group_addr);

  IGMP_SOURCE_DONT_FORWARDING(source->source_flags);
}
int pim_if_igmp_join_del(struct interface *ifp,
			 struct in_addr group_addr,
			 struct in_addr source_addr)
{
  struct pim_interface *pim_ifp;
  struct igmp_join *ij;

  pim_ifp = ifp->info;
  if (!pim_ifp) {
    zlog_warn("%s: multicast not enabled on interface %s",
	      __PRETTY_FUNCTION__, 
	      ifp->name);
    return -1;
  }

  if (!pim_ifp->igmp_join_list) {
    zlog_warn("%s: no IGMP join on interface %s",
	      __PRETTY_FUNCTION__, 
	      ifp->name);
    return -2;
  }

  ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
  if (!ij) {
    char group_str[100];
    char source_str[100];
    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str));
    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str));
    zlog_warn("%s: could not find IGMP group %s source %s on interface %s",
	      __PRETTY_FUNCTION__,
	      group_str, source_str, ifp->name);
    return -3;
  }

  if (close(ij->sock_fd)) {
    int e = errno;
    char group_str[100];
    char source_str[100];
    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str));
    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str));
    zlog_warn("%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
	      __PRETTY_FUNCTION__,
	      ij->sock_fd, group_str, source_str, ifp->name, e, safe_strerror(e));
    /* warning only */
  }
  listnode_delete(pim_ifp->igmp_join_list, ij);
  igmp_join_free(ij);
  if (listcount(pim_ifp->igmp_join_list) < 1) {
    list_delete(pim_ifp->igmp_join_list);
    pim_ifp->igmp_join_list = 0;
  }

  return 0;
}
Ejemplo n.º 14
0
/*
  RFC 4601: 4.3.4.  Maintaining Secondary Address Lists
  
  All the advertised secondary addresses in received Hello messages
  must be checked against those previously advertised by all other
  PIM neighbors on that interface.  If there is a conflict and the
  same secondary address was previously advertised by another
  neighbor, then only the most recently received mapping MUST be
  maintained, and an error message SHOULD be logged to the
  administrator in a rate-limited manner.
*/
static void delete_from_neigh_addr(struct interface *ifp,
				   struct list *addr_list,
				   struct in_addr neigh_addr)
{
  struct listnode      *addr_node;
  struct prefix        *addr;
  struct pim_interface *pim_ifp;

  pim_ifp = ifp->info;
  zassert(pim_ifp);

  zassert(addr_list);

  /*
    Scan secondary address list
  */
  for (ALL_LIST_ELEMENTS_RO(addr_list, addr_node,
			    addr)) {
    struct listnode      *neigh_node;
    struct pim_neighbor  *neigh;

    if (addr->family != AF_INET)
      continue;

    /*
      Scan neighbors
    */
    for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node,
			      neigh)) {
      {
	struct prefix *p = pim_neighbor_find_secondary(neigh, addr->u.prefix4);
	if (p) {
	  char addr_str[100];
	  char this_neigh_str[100];
	  char other_neigh_str[100];
	  
	  pim_inet4_dump("<addr?>", addr->u.prefix4, addr_str, sizeof(addr_str));
	  pim_inet4_dump("<neigh1?>", neigh_addr, this_neigh_str, sizeof(this_neigh_str));
	  pim_inet4_dump("<neigh2?>", neigh->source_addr, other_neigh_str, sizeof(other_neigh_str));
	  
	  zlog_info("secondary addr %s recvd from neigh %s deleted from neigh %s on %s",
		    addr_str, this_neigh_str, other_neigh_str, ifp->name);
	  
	  listnode_delete(neigh->prefix_list, p);
	  prefix_free(p);
	}
      }

    } /* scan neighbors */
    
  } /* scan addr list */

}
Ejemplo n.º 15
0
/* add peer configuration if it doesn't already exist */
enum pim_msdp_err pim_msdp_peer_add(struct pim_instance *pim,
				    struct in_addr peer_addr,
				    struct in_addr local_addr,
				    const char *mesh_group_name,
				    struct pim_msdp_peer **mp_p)
{
	struct pim_msdp_peer *mp;

	if (mp_p) {
		*mp_p = NULL;
	}

	if (peer_addr.s_addr == local_addr.s_addr) {
		/* skip session setup if config is invalid */
		if (PIM_DEBUG_MSDP_EVENTS) {
			char peer_str[INET_ADDRSTRLEN];

			pim_inet4_dump("<peer?>", peer_addr, peer_str,
				       sizeof(peer_str));
			zlog_debug("%s add skipped as DIP=SIP", peer_str);
		}
		return PIM_MSDP_ERR_SIP_EQ_DIP;
	}

	mp = pim_msdp_peer_find(pim, peer_addr);
	if (mp) {
		if (mp_p) {
			*mp_p = mp;
		}
		return PIM_MSDP_ERR_PEER_EXISTS;
	}

	return pim_msdp_peer_new(pim, peer_addr, local_addr, mesh_group_name,
				 mp_p);
}
Ejemplo n.º 16
0
static int on_neighbor_timer(struct thread *t)
{
  struct pim_neighbor *neigh;
  struct interface *ifp;
  char msg[100];

  zassert(t);
  neigh = THREAD_ARG(t);
  zassert(neigh);

  ifp = neigh->interface;

  if (PIM_DEBUG_PIM_TRACE) {
    char src_str[100];
    pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
    zlog_debug("Expired %d sec holdtime for neighbor %s on interface %s",
	       neigh->holdtime, src_str, ifp->name);
  }

  neigh->t_expire_timer = 0;

  snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime);
  pim_neighbor_delete(ifp, neigh, msg);

  /*
    RFC 4601: 4.3.2.  DR Election
    
    A router's idea of the current DR on an interface can change when a
    PIM Hello message is received, when a neighbor times out, or when a
    router's own DR Priority changes.
  */
  pim_if_dr_election(ifp); // neighbor times out

  return 0;
}
Ejemplo n.º 17
0
void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime)
{
  neigh->holdtime = holdtime;

  neighbor_timer_off(neigh);

  /*
    0xFFFF is request for no holdtime
   */
  if (neigh->holdtime == 0xFFFF) {
    return;
  }

  if (PIM_DEBUG_PIM_TRACE) {
    char src_str[100];
    pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
    zlog_debug("%s: starting %u sec timer for neighbor %s on %s",
	       __PRETTY_FUNCTION__,
	       neigh->holdtime, src_str, neigh->interface->name);
  }

  THREAD_TIMER_ON(master, neigh->t_expire_timer,
		  on_neighbor_timer,
		  neigh, neigh->holdtime);
}
Ejemplo n.º 18
0
void igmp_group_timer_on(struct igmp_group *group,
			 long interval_msec, const char *ifname)
{
  group_timer_off(group);

  if (PIM_DEBUG_IGMP_EVENTS) {
    char group_str[100];
    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
    zlog_debug("Scheduling %ld.%03ld sec TIMER event for group %s on %s",
	       interval_msec / 1000,
	       interval_msec % 1000,
	       group_str, ifname);
  }

  /*
    RFC 3376: 6.2.2. Definition of Group Timers

    The group timer is only used when a group is in EXCLUDE mode and
    it represents the time for the *filter-mode* of the group to
    expire and switch to INCLUDE mode.
  */
  zassert(group->group_filtermode_isexcl);

  THREAD_TIMER_MSEC_ON(master, group->t_group_timer,
		       igmp_group_timer,
		       group, interval_msec);
}
Ejemplo n.º 19
0
static void igmp_group_delete(struct igmp_group *group)
{
  struct listnode *src_node;
  struct listnode *src_nextnode;
  struct igmp_source *src;

  if (PIM_DEBUG_IGMP_TRACE) {
    char group_str[100];
    pim_inet4_dump("<group?>", group->group_addr, group_str, sizeof(group_str));
    zlog_debug("Deleting IGMP group %s from socket %d interface %s",
	       group_str,
	       group->group_igmp_sock->fd,
	       group->group_igmp_sock->interface->name);
  }

  for (ALL_LIST_ELEMENTS(group->group_source_list, src_node, src_nextnode, src)) {
    igmp_source_delete(src);
  }

  if (group->t_group_query_retransmit_timer) {
    THREAD_OFF(group->t_group_query_retransmit_timer);
    zassert(!group->t_group_query_retransmit_timer);
  }

  group_timer_off(group);
  listnode_delete(group->group_igmp_sock->igmp_group_list, group);
  igmp_group_free(group);
}
Ejemplo n.º 20
0
static void ssmpingd_sendto(struct ssmpingd_sock *ss,
			    const uint8_t *buf,
			    int len,
			    struct sockaddr_in to)
{
  socklen_t tolen = sizeof(to);
  int sent;

  sent = sendto(ss->sock_fd, buf, len, MSG_DONTWAIT,
                (struct sockaddr *)&to, tolen);
  if (sent != len) {
    int e = errno;
    char to_str[100];
    pim_inet4_dump("<to?>", to.sin_addr, to_str, sizeof(to_str));
    if (sent < 0) {
      zlog_warn("%s: sendto() failure to %s,%d: fd=%d len=%d: errno=%d: %s",
		__PRETTY_FUNCTION__,
		to_str, ntohs(to.sin_port), ss->sock_fd, len,
		e, safe_strerror(e));
    }
    else {
      zlog_warn("%s: sendto() partial to %s,%d: fd=%d len=%d: sent=%d",
		__PRETTY_FUNCTION__,
		to_str, ntohs(to.sin_port), ss->sock_fd,
		len, sent);
    }
  }
}
Ejemplo n.º 21
0
static int pim_igmp_other_querier_expire(struct thread *t)
{
  struct igmp_sock *igmp;

  zassert(t);
  igmp = THREAD_ARG(t);
  zassert(igmp);

  zassert(igmp->t_other_querier_timer);
  zassert(!igmp->t_igmp_query_timer);

  if (PIM_DEBUG_IGMP_TRACE) {
    char ifaddr_str[100];
    pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str, sizeof(ifaddr_str));
    zlog_debug("%s: Querier %s resuming",
	       __PRETTY_FUNCTION__,
	       ifaddr_str);
  }

  igmp->t_other_querier_timer = 0;

  /*
    We are the current querier, then
    re-start sending general queries.
  */
  pim_igmp_general_query_on(igmp);

  return 0;
}
Ejemplo n.º 22
0
static void if_could_assert_do_a1(const char *caller,
				  struct pim_ifchannel *ch)
{
  if (PIM_IF_FLAG_TEST_COULD_ASSERT(ch->flags)) {
    if (assert_action_a1(ch)) {
      char src_str[100];
      char grp_str[100];
      pim_inet4_dump("<src?>", ch->source_addr, src_str, sizeof(src_str));
      pim_inet4_dump("<grp?>", ch->group_addr, grp_str, sizeof(grp_str));
      zlog_warn("%s: %s: (S,G)=(%s,%s) assert_action_a1 failure on interface %s",
		__PRETTY_FUNCTION__, caller,
		src_str, grp_str, ch->interface->name);
      /* log warning only */
    }
  }
}
Ejemplo n.º 23
0
static struct ssmpingd_sock *ssmpingd_new(struct in_addr source_addr)
{
  struct ssmpingd_sock *ss;
  int sock_fd;

  if (!qpim_ssmpingd_list) {
    qpim_ssmpingd_list = list_new();
    if (!qpim_ssmpingd_list) {
      zlog_err("%s %s: failure: qpim_ssmpingd_list=list_new()",
	       __FILE__, __PRETTY_FUNCTION__);
      return 0;
    }
    qpim_ssmpingd_list->del = (void (*)(void *)) ssmpingd_free;
  }

  sock_fd = ssmpingd_socket(source_addr, /* port: */ 4321, /* mTTL: */ 64);
  if (sock_fd < 0) {
    char source_str[100];
    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str));
    zlog_warn("%s: ssmpingd_socket() failure for source %s",
	      __PRETTY_FUNCTION__, source_str);
    return 0;
  }

  ss = XMALLOC(MTYPE_PIM_SSMPINGD, sizeof(*ss));
  if (!ss) {
    char source_str[100];
    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str));
    zlog_err("%s: XMALLOC(%zu) failure for ssmpingd source %s",
	     __PRETTY_FUNCTION__,
	     sizeof(*ss), source_str);
    close(sock_fd);
    return 0;
  }

  ss->sock_fd     = sock_fd;
  ss->t_sock_read = 0;
  ss->source_addr = source_addr;
  ss->creation    = pim_time_monotonic_sec();
  ss->requests    = 0;

  listnode_add(qpim_ssmpingd_list, ss);

  ssmpingd_read_on(ss);

  return ss;
}
Ejemplo n.º 24
0
static int hello_send(struct interface *ifp,
		      uint16_t holdtime)
{
  uint8_t pim_msg[PIM_PIM_BUFSIZE_WRITE];
  struct pim_interface *pim_ifp;
  int pim_tlv_size;
  int pim_msg_size;

  pim_ifp = ifp->info;

  if (PIM_DEBUG_PIM_HELLO) {
    char dst_str[100];
    pim_inet4_dump("<dst?>", qpim_all_pim_routers_addr, dst_str, sizeof(dst_str));
    zlog_debug("%s: to %s on %s: holdt=%u prop_d=%u overr_i=%u dis_join_supp=%d dr_prio=%u gen_id=%08x addrs=%d",
	       __PRETTY_FUNCTION__,
	       dst_str, ifp->name,
	       holdtime,
	       pim_ifp->pim_propagation_delay_msec, pim_ifp->pim_override_interval_msec,
	       PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options),
	       pim_ifp->pim_dr_priority, pim_ifp->pim_generation_id,
	       listcount(ifp->connected));
  }

  pim_tlv_size = pim_hello_build_tlv(ifp->name,
				     pim_msg + PIM_PIM_MIN_LEN,
				     sizeof(pim_msg) - PIM_PIM_MIN_LEN,
				     holdtime,
				     pim_ifp->pim_dr_priority,
				     pim_ifp->pim_generation_id,
				     pim_ifp->pim_propagation_delay_msec,
				     pim_ifp->pim_override_interval_msec,
				     PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options),
				     ifp->connected);
  if (pim_tlv_size < 0) {
    return -1;
  }

  pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN;

  zassert(pim_msg_size >= PIM_PIM_MIN_LEN);
  zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE);

  pim_msg_build_header(pim_msg, pim_msg_size,
		       PIM_MSG_TYPE_HELLO);

  if (pim_msg_send(pim_ifp->pim_sock_fd,
		   qpim_all_pim_routers_addr,
		   pim_msg,
		   pim_msg_size,
		   ifp->name)) {
    if (PIM_DEBUG_PIM_HELLO) {
      zlog_debug("%s: could not send PIM message on interface %s",
		 __PRETTY_FUNCTION__, ifp->name);
    }
    return -2;
  }

  return 0;
}
Ejemplo n.º 25
0
static int on_assert_timer(struct thread *t)
{
  struct pim_ifchannel *ch;
  struct interface *ifp;

  zassert(t);
  ch = THREAD_ARG(t);
  zassert(ch);

  ifp = ch->interface;
  zassert(ifp);

  if (PIM_DEBUG_PIM_TRACE) {
    char src_str[100];
    char grp_str[100];
    pim_inet4_dump("<src?>", ch->source_addr, src_str, sizeof(src_str));
    pim_inet4_dump("<grp?>", ch->group_addr, grp_str, sizeof(grp_str));
    zlog_debug("%s: (S,G)=(%s,%s) timer expired on interface %s",
	       __PRETTY_FUNCTION__,
	       src_str, grp_str, ifp->name);
  }

  ch->t_ifassert_timer = 0;

  switch (ch->ifassert_state) {
  case PIM_IFASSERT_I_AM_WINNER:
    zassert(ch->ifassert_state == PIM_IFASSERT_I_AM_WINNER); /* a3 requirement */
    assert_action_a3(ch);
    break;
  case PIM_IFASSERT_I_AM_LOSER:
    assert_action_a5(ch);
    break;
  default:
    {
      char source_str[100];
      char group_str[100];
      pim_inet4_dump("<src?>", ch->source_addr, source_str, sizeof(source_str));
      pim_inet4_dump("<grp?>", ch->group_addr, group_str, sizeof(group_str));
      zlog_warn("%s: (S,G)=(%s,%s) invalid assert state %d on interface %s",
		__PRETTY_FUNCTION__,
		source_str, group_str, ch->ifassert_state, ifp->name);
    }
  }

  return 0;
}
Ejemplo n.º 26
0
/*
  RFC 4601: 4.6.1.  (S,G) Assert Message State Machine

  (S,G) Assert State machine Actions

     A4:  Send AssertCancel(S,G).
          Delete assert info (AssertWinner(S,G,I) and
          AssertWinnerMetric(S,G,I) will then return their default
          values).
*/
void assert_action_a4(struct pim_ifchannel *ch)
{
  if (pim_assert_cancel(ch)) {
    char src_str[100];
    char grp_str[100];
    pim_inet4_dump("<src?>", ch->source_addr, src_str, sizeof(src_str));
    pim_inet4_dump("<grp?>", ch->group_addr, grp_str, sizeof(grp_str));
    zlog_warn("%s: failure sending AssertCancel(%s,%s) on interface %s",
	      __PRETTY_FUNCTION__,
	      src_str, grp_str, ch->interface->name);
    /* log warning only */
  }

  assert_action_a5(ch);

  zassert(ch->ifassert_state == PIM_IFASSERT_NOINFO);
}
static struct igmp_join *igmp_join_new(struct interface *ifp,
				       struct in_addr group_addr,
				       struct in_addr source_addr)
{
  struct pim_interface *pim_ifp;
  struct igmp_join *ij;
  int join_fd;

  pim_ifp = ifp->info;
  zassert(pim_ifp);

  join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr, source_addr);
  if (join_fd < 0) {
    char group_str[100];
    char source_str[100];
    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str));
    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str));
    zlog_warn("%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
	      __PRETTY_FUNCTION__,
	      group_str, source_str, ifp->name);
    return 0;
  }

  ij = XMALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij));
  if (!ij) {
    char group_str[100];
    char source_str[100];
    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str));
    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str));
    zlog_err("%s: XMALLOC(%zu) failure for IGMP group %s source %s on interface %s",
	     __PRETTY_FUNCTION__,
	     sizeof(*ij), group_str, source_str, ifp->name);
    close(join_fd);
    return 0;
  }

  ij->sock_fd       = join_fd;
  ij->group_addr    = group_addr;
  ij->source_addr   = source_addr;
  ij->sock_creation = pim_time_monotonic_sec();

  listnode_add(pim_ifp->igmp_join_list, ij);

  return ij;
}
Ejemplo n.º 28
0
char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size,
			     bool long_format)
{
	char peer_str[INET_ADDRSTRLEN];
	char local_str[INET_ADDRSTRLEN];

	pim_inet4_dump("<peer?>", mp->peer, peer_str, sizeof(peer_str));
	if (long_format) {
		pim_inet4_dump("<local?>", mp->local, local_str,
			       sizeof(local_str));
		snprintf(buf, buf_size, "MSDP peer %s local %s mg %s", peer_str,
			 local_str, mp->mesh_group_name);
	} else {
		snprintf(buf, buf_size, "MSDP peer %s", peer_str);
	}

	return buf;
}
Ejemplo n.º 29
0
static void on_trace(const char *label, struct interface *ifp,
		     struct in_addr src)
{
	if (PIM_DEBUG_PIM_TRACE) {
		char src_str[INET_ADDRSTRLEN];
		pim_inet4_dump("<src?>", src, src_str, sizeof(src_str));
		zlog_debug("%s: from %s on %s", label, src_str, ifp->name);
	}
}
static void pim_upstream_join_timer_restart_msec(struct pim_upstream *up,
						 int interval_msec)
{
  if (PIM_DEBUG_PIM_EVENTS) {
    char src_str[100];
    char grp_str[100];
    pim_inet4_dump("<src?>", up->source_addr, src_str, sizeof(src_str));
    pim_inet4_dump("<grp?>", up->group_addr, grp_str, sizeof(grp_str));
    zlog_debug("%s: restarting %d msec timer for upstream (S,G)=(%s,%s)",
	       __PRETTY_FUNCTION__,
	       interval_msec,
	       src_str, grp_str);
  }

  THREAD_OFF(up->t_join_timer);
  THREAD_TIMER_MSEC_ON(master, up->t_join_timer,
		       on_join_timer,
		       up, interval_msec);
}