Exemple #1
0
/* Interface between zebra message and rtm message. */
static int
kernel_rtm_ipv4 (int cmd, struct prefix *p, struct rib *rib)

{
  struct sockaddr_in *mask = NULL;
  struct sockaddr_in sin_dest, sin_mask, sin_gate;
  struct nexthop *nexthop, *tnexthop;
  int recursing;
  int nexthop_num = 0;
  ifindex_t ifindex = 0;
  int gate = 0;
  int error;
  char prefix_buf[PREFIX_STRLEN];

  if (IS_ZEBRA_DEBUG_RIB)
    prefix2str (p, prefix_buf, sizeof(prefix_buf));
  memset (&sin_dest, 0, sizeof (struct sockaddr_in));
  sin_dest.sin_family = AF_INET;
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  sin_dest.sin_len = sizeof (struct sockaddr_in);
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
  sin_dest.sin_addr = p->u.prefix4;

  memset (&sin_mask, 0, sizeof (struct sockaddr_in));

  memset (&sin_gate, 0, sizeof (struct sockaddr_in));
  sin_gate.sin_family = AF_INET;
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  sin_gate.sin_len = sizeof (struct sockaddr_in);
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */

  /* Make gateway. */
  for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
    {
      if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
        continue;

      gate = 0;
      char gate_buf[INET_ADDRSTRLEN] = "NULL";

      /*
       * XXX We need to refrain from kernel operations in some cases,
       * but this if statement seems overly cautious - what about
       * other than ADD and DELETE?
       */
      if ((cmd == RTM_ADD
	   && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
	  || (cmd == RTM_DELETE
	      && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)
	      ))
	{
	  if (nexthop->type == NEXTHOP_TYPE_IPV4 ||
	      nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
	    {
	      sin_gate.sin_addr = nexthop->gate.ipv4;
	      gate = 1;
	    }
	  if (nexthop->type == NEXTHOP_TYPE_IFINDEX
	      || nexthop->type == NEXTHOP_TYPE_IFNAME
	      || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
	    ifindex = nexthop->ifindex;
	  if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
	    {
	      struct in_addr loopback;
	      loopback.s_addr = htonl (INADDR_LOOPBACK);
	      sin_gate.sin_addr = loopback;
	      gate = 1;
	    }

	  if (gate && p->prefixlen == 32)
	    mask = NULL;
	  else
	    {
	      masklen2ip (p->prefixlen, &sin_mask.sin_addr);
	      sin_mask.sin_family = AF_INET;
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
	      sin_mask.sin_len = sin_masklen (sin_mask.sin_addr);
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
	      mask = &sin_mask;
	    }

	  error = rtm_write (cmd,
			     (union sockunion *)&sin_dest, 
			     (union sockunion *)mask, 
			     gate ? (union sockunion *)&sin_gate : NULL,
			     ifindex,
			     rib->flags,
			     rib->metric);

           if (IS_ZEBRA_DEBUG_RIB)
           {
             if (!gate)
             {
               zlog_debug ("%s: %s: attention! gate not found for rib %p",
                 __func__, prefix_buf, rib);
               rib_dump (p, rib);
             }
             else
               inet_ntop (AF_INET, &sin_gate.sin_addr, gate_buf, INET_ADDRSTRLEN);
           }
 
           switch (error)
           {
             /* We only flag nexthops as being in FIB if rtm_write() did its work. */
             case ZEBRA_ERR_NOERROR:
               nexthop_num++;
               if (IS_ZEBRA_DEBUG_RIB)
                 zlog_debug ("%s: %s: successfully did NH %s",
                   __func__, prefix_buf, gate_buf);
               if (cmd == RTM_ADD)
                 SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
               break;
 
             /* The only valid case for this error is kernel's failure to install
              * a multipath route, which is common for FreeBSD. This should be
              * ignored silently, but logged as an error otherwise.
              */
             case ZEBRA_ERR_RTEXIST:
               if (cmd != RTM_ADD)
                 zlog_err ("%s: rtm_write() returned %d for command %d",
                   __func__, error, cmd);
               continue;
               break;
 
             /* Given that our NEXTHOP_FLAG_FIB matches real kernel FIB, it isn't
              * normal to get any other messages in ANY case.
              */
             case ZEBRA_ERR_RTNOEXIST:
             case ZEBRA_ERR_RTUNREACH:
             default:
               zlog_err ("%s: %s: rtm_write() unexpectedly returned %d for command %s",
                 __func__, prefix2str(p, prefix_buf, sizeof(prefix_buf)),
                 error, lookup (rtm_type_str, cmd));
               break;
           }
         } /* if (cmd and flags make sense) */
       else
         if (IS_ZEBRA_DEBUG_RIB)
           zlog_debug ("%s: odd command %s for flags %d",
             __func__, lookup (rtm_type_str, cmd), nexthop->flags);
     } /* for (ALL_NEXTHOPS_RO(...))*/
 
   /* If there was no useful nexthop, then complain. */
   if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL)
     zlog_debug ("%s: No useful nexthops were found in RIB entry %p", __func__, rib);

  return 0; /*XXX*/
}
/* RFC 2328 16.2. Calculating the inter-area routes */
void
ospf6_abr_examin_summary (struct ospf6_lsa *lsa, struct ospf6_area *oa)
{
  struct prefix prefix, abr_prefix;
  struct ospf6_route_table *table = NULL;
  struct ospf6_route *range, *route, *old = NULL;
  struct ospf6_route *abr_entry;
  u_char type = 0;
  char options[3] = {0, 0, 0};
  u_int8_t prefix_options = 0;
  u_int32_t cost = 0;
  u_char router_bits = 0;
  int i;
  char buf[64];
  int is_debug = 0;
  struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
  struct ospf6_inter_router_lsa *router_lsa = NULL;

  memset (&prefix, 0, sizeof (prefix));

  if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
    {
      if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX))
        {
          is_debug++;
          zlog_debug ("Examin %s in area %s", lsa->name, oa->name);
        }

      prefix_lsa = (struct ospf6_inter_prefix_lsa *)
        OSPF6_LSA_HEADER_END (lsa->header);
      prefix.family = AF_INET6;
      prefix.prefixlen = prefix_lsa->prefix.prefix_length;
      ospf6_prefix_in6_addr (&prefix.u.prefix6, &prefix_lsa->prefix);
      if (is_debug)
        prefix2str (&prefix, buf, sizeof (buf));
      table = oa->ospf6->route_table;
      type = OSPF6_DEST_TYPE_NETWORK;
      prefix_options = prefix_lsa->prefix.prefix_options;
      cost = OSPF6_ABR_SUMMARY_METRIC (prefix_lsa);
    }
  else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
    {
      if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER))
        {
          is_debug++;
          zlog_debug ("Examin %s in area %s", lsa->name, oa->name);
        }

      router_lsa = (struct ospf6_inter_router_lsa *)
        OSPF6_LSA_HEADER_END (lsa->header);
      ospf6_linkstate_prefix (router_lsa->router_id, htonl (0), &prefix);
      if (is_debug)
        inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
      table = oa->ospf6->brouter_table;
      type = OSPF6_DEST_TYPE_ROUTER;
      options[0] = router_lsa->options[0];
      options[1] = router_lsa->options[1];
      options[2] = router_lsa->options[2];
      cost = OSPF6_ABR_SUMMARY_METRIC (router_lsa);
      SET_FLAG (router_bits, OSPF6_ROUTER_BIT_E);
    }
  else
    assert (0);

  /* Find existing route */
  route = ospf6_route_lookup (&prefix, table);
  if (route)
    ospf6_route_lock (route);
  while (route && ospf6_route_is_prefix (&prefix, route))
    {
      if (route->path.area_id == oa->area_id &&
          route->path.origin.type == lsa->header->type &&
          route->path.origin.id == lsa->header->id &&
          route->path.origin.adv_router == lsa->header->adv_router &&
          ! CHECK_FLAG (route->flag, OSPF6_ROUTE_WAS_REMOVED))
        old = route;
      route = ospf6_route_next (route);
    }

  /* (1) if cost == LSInfinity or if the LSA is MaxAge */
  if (cost == OSPF_LS_INFINITY)
    {
      if (is_debug)
        zlog_debug ("cost is LS_INFINITY, ignore");
      if (old)
        ospf6_route_remove (old, table);
      return;
    }
  if (OSPF6_LSA_IS_MAXAGE (lsa))
    {
      if (is_debug)
        zlog_debug ("LSA is MaxAge, ignore");
      if (old)
        ospf6_route_remove (old, table);
      return;
    }

  /* (2) if the LSA is self-originated, ignore */
  if (lsa->header->adv_router == oa->ospf6->router_id)
    {
      if (is_debug)
        zlog_debug ("LSA is self-originated, ignore");
      if (old)
        ospf6_route_remove (old, table);
      return;
    }

  /* (3) if the prefix is equal to an active configured address range */
  /*     or if the NU bit is set in the prefix */
  if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
    {
      range = ospf6_route_lookup (&prefix, oa->range_table);
      if (range)
        {
          if (is_debug)
            zlog_debug ("Prefix is equal to address range, ignore");
          if (old)
            ospf6_route_remove (old, table);
          return;
        }

      if (CHECK_FLAG (prefix_lsa->prefix.prefix_options,
		      OSPF6_PREFIX_OPTION_NU) ||
	  CHECK_FLAG (prefix_lsa->prefix.prefix_options,
		      OSPF6_PREFIX_OPTION_LA))
	{
          if (is_debug)
            zlog_debug ("Prefix has NU/LA bit set, ignore");
          if (old)
            ospf6_route_remove (old, table);
          return;
	}
    }

  if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
    {
      /* To pass test suites */
      if (! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_R) ||
	  ! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_V6))
	{
          if (is_debug)
            zlog_debug ("Prefix has NU/LA bit set, ignore");
          if (old)
            ospf6_route_remove (old, table);
          return;
	}
    }

  /* (4) if the routing table entry for the ABR does not exist */
  ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &abr_prefix);
  abr_entry = ospf6_route_lookup (&abr_prefix, oa->ospf6->brouter_table);
  if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id ||
      CHECK_FLAG (abr_entry->flag, OSPF6_ROUTE_REMOVE) ||
      ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B))
    {
      if (is_debug)
        zlog_debug ("ABR router entry does not exist, ignore");
      if (old)
        ospf6_route_remove (old, table);
      return;
    }

  /* Check import list */
  if (IMPORT_NAME (oa))
    {
      if (IMPORT_LIST (oa) == NULL)
        IMPORT_LIST (oa) = access_list_lookup (AFI_IP6, IMPORT_NAME (oa));

      if (IMPORT_LIST (oa))
        if (access_list_apply (IMPORT_LIST (oa), &prefix) == FILTER_DENY)
          {
            if (is_debug)
              zlog_debug ("Prefix was denied by import-list");
            if (old)
              ospf6_route_remove (old, table);
            return;
          }
    }

  /* Check input prefix-list */
  if (PREFIX_NAME_IN (oa))
    {
      if (PREFIX_LIST_IN (oa) == NULL)
        PREFIX_LIST_IN (oa) = prefix_list_lookup (AFI_IP6, PREFIX_NAME_IN (oa));

      if (PREFIX_LIST_IN (oa))
        if (prefix_list_apply (PREFIX_LIST_IN (oa), &prefix) != PREFIX_PERMIT)
          {
            if (is_debug)
              zlog_debug ("Prefix was denied by prefix-list");
            if (old)
              ospf6_route_remove (old, table);
            return;
          }
    }

  /* (5),(6),(7) the path preference is handled by the sorting
     in the routing table. Always install the path by substituting
     old route (if any). */
  if (old)
    route = ospf6_route_copy (old);
  else
    route = ospf6_route_create ();

  route->type = type;
  route->prefix = prefix;
  route->path.origin.type = lsa->header->type;
  route->path.origin.id = lsa->header->id;
  route->path.origin.adv_router = lsa->header->adv_router;
  route->path.router_bits = router_bits;
  route->path.options[0] = options[0];
  route->path.options[1] = options[1];
  route->path.options[2] = options[2];
  route->path.prefix_options = prefix_options;
  route->path.area_id = oa->area_id;
  route->path.type = OSPF6_PATH_TYPE_INTER;
  route->path.cost = abr_entry->path.cost + cost;
  for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
    route->nexthop[i] = abr_entry->nexthop[i];

  if (is_debug)
    zlog_debug ("Install route: %s", buf);
  ospf6_route_add (route, table);
}
Exemple #3
0
void
ospf6_asbr_lsa_add (struct ospf6_lsa *lsa)
{
    struct ospf6_as_external_lsa *external;
    struct prefix asbr_id;
    struct ospf6_route *asbr_entry, *route;
    char buf[64];
    int i;

    external = (struct ospf6_as_external_lsa *)
               OSPF6_LSA_HEADER_END (lsa->header);

    if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
        zlog_debug ("Calculate AS-External route for %s", lsa->name);

    if (lsa->header->adv_router == ospf6->router_id)
    {
        if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
            zlog_debug ("Ignore self-originated AS-External-LSA");
        return;
    }

    if (OSPF6_ASBR_METRIC (external) == LS_INFINITY)
    {
        if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
            zlog_debug ("Ignore LSA with LSInfinity Metric");
        return;
    }

    ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
    asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
    if (asbr_entry == NULL ||
            ! CHECK_FLAG (asbr_entry->path.router_bits, OSPF6_ROUTER_BIT_E))
    {
        if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
        {
            prefix2str (&asbr_id, buf, sizeof (buf));
            zlog_debug ("ASBR entry not found: %s", buf);
        }
        return;
    }

    route = ospf6_route_create ();
    route->type = OSPF6_DEST_TYPE_NETWORK;
    route->prefix.family = AF_INET6;
    route->prefix.prefixlen = external->prefix.prefix_length;
    ospf6_prefix_in6_addr (&route->prefix.u.prefix6, &external->prefix);

    route->path.area_id = asbr_entry->path.area_id;
    route->path.origin.type = lsa->header->type;
    route->path.origin.id = lsa->header->id;
    route->path.origin.adv_router = lsa->header->adv_router;

    route->path.prefix_options = external->prefix.prefix_options;
    if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E))
    {
        route->path.type = OSPF6_PATH_TYPE_EXTERNAL2;
        route->path.metric_type = 2;
        route->path.cost = asbr_entry->path.cost;
        route->path.cost_e2 = OSPF6_ASBR_METRIC (external);
    }
    else
    {
        route->path.type = OSPF6_PATH_TYPE_EXTERNAL1;
        route->path.metric_type = 1;
        route->path.cost = asbr_entry->path.cost + OSPF6_ASBR_METRIC (external);
        route->path.cost_e2 = 0;
    }

    for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
        ospf6_nexthop_copy (&route->nexthop[i], &asbr_entry->nexthop[i]);

    if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
    {
        prefix2str (&route->prefix, buf, sizeof (buf));
        zlog_debug ("AS-External route add: %s", buf);
    }

    ospf6_route_add (route, ospf6->route_table);
}
Exemple #4
0
void
ospf6_asbr_redistribute_remove (int type, int ifindex, struct prefix *prefix)
{
    struct ospf6_route *match;
    struct ospf6_external_info *info = NULL;
    struct route_node *node;
    struct ospf6_lsa *lsa;
    struct prefix prefix_id;
    char pbuf[64], ibuf[16];
    struct listnode *lnode, *lnnode;
    struct ospf6_area *oa;

    match = ospf6_route_lookup (prefix, ospf6->external_table);
    if (match == NULL)
    {
        if (IS_OSPF6_DEBUG_ASBR)
        {
            prefix2str (prefix, pbuf, sizeof (pbuf));
            zlog_debug ("No such route %s to withdraw", pbuf);
        }
        return;
    }

    info = match->route_option;
    assert (info);

    if (info->type != type)
    {
        if (IS_OSPF6_DEBUG_ASBR)
        {
            prefix2str (prefix, pbuf, sizeof (pbuf));
            zlog_debug ("Original protocol mismatch: %s", pbuf);
        }
        return;
    }

    if (IS_OSPF6_DEBUG_ASBR)
    {
        prefix2str (prefix, pbuf, sizeof (pbuf));
        inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
        zlog_debug ("Withdraw %s (AS-External Id:%s)", pbuf, ibuf);
    }

    lsa = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
                             htonl (info->id), ospf6->router_id, ospf6->lsdb);
    if (lsa)
        ospf6_lsa_purge (lsa);

    /* remove binding in external_id_table */
    prefix_id.family = AF_INET;
    prefix_id.prefixlen = 32;
    prefix_id.u.prefix4.s_addr = htonl (info->id);
    node = route_node_lookup (ospf6->external_id_table, &prefix_id);
    assert (node);
    node->info = NULL;
    route_unlock_node (node);

    ospf6_route_remove (match, ospf6->external_table);
    XFREE (MTYPE_OSPF6_EXTERNAL_INFO, info);

    /* Router-Bit (ASBR Flag) may have to be updated */
    for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
        OSPF6_ROUTER_LSA_SCHEDULE (oa);
}
Exemple #5
0
struct connected *
zebra_interface_address_read (int type, struct stream *s, vrf_id_t vrf_id)
{
  unsigned int ifindex;
  struct interface *ifp;
  struct connected *ifc;
  struct prefix p, d;
  int family;
  int plen;
  u_char ifc_flags;

  memset (&p, 0, sizeof(p));
  memset (&d, 0, sizeof(d));

  /* Get interface index. */
  ifindex = stream_getl (s);

  /* Lookup index. */
  ifp = if_lookup_by_index_vrf (ifindex, vrf_id);
  if (ifp == NULL)
    {
      zlog_warn ("zebra_interface_address_read(%s): "
                 "Can't find interface by ifindex: %d ",
                 (type == ZEBRA_INTERFACE_ADDRESS_ADD? "ADD" : "DELETE"),
                 ifindex);
      return NULL;
    }

  /* Fetch flag. */
  ifc_flags = stream_getc (s);

  /* Fetch interface address. */
  family = p.family = stream_getc (s);

  plen = prefix_blen (&p);
  stream_get (&p.u.prefix, s, plen);
  p.prefixlen = stream_getc (s);

  /* Fetch destination address. */
  stream_get (&d.u.prefix, s, plen);
  d.family = family;

  if (type == ZEBRA_INTERFACE_ADDRESS_ADD) 
    {
       /* N.B. NULL destination pointers are encoded as all zeroes */
       ifc = connected_add_by_prefix(ifp, &p,(memconstant(&d.u.prefix,0,plen) ?
					      NULL : &d));
       if (ifc != NULL)
	 {
	   ifc->flags = ifc_flags;
	   if (ifc->destination)
	     ifc->destination->prefixlen = ifc->address->prefixlen;
	   else if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
	     {
	       /* carp interfaces on OpenBSD with 0.0.0.0/0 as "peer" */
	       char buf[PREFIX_STRLEN];
	       zlog_warn("warning: interface %s address %s "
		    "with peer flag set, but no peer address!",
		    ifp->name,
		    prefix2str (ifc->address, buf, sizeof buf));
	       UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
	     }
	 }
    }
  else
    {
      assert (type == ZEBRA_INTERFACE_ADDRESS_DELETE);
      ifc = connected_delete_by_prefix(ifp, &p);
    }

  return ifc;
}
Exemple #6
0
char *
rnh_str (struct rnh *rnh, char *buf, int size)
{
  prefix2str(&(rnh->node->p), buf, size);
  return buf;
}
Exemple #7
0
void nhrp_route_announce(int add, enum nhrp_cache_type type,
			 const struct prefix *p, struct interface *ifp,
			 const union sockunion *nexthop, uint32_t mtu)
{
	struct zapi_route api;
	struct zapi_nexthop *api_nh;

	if (zclient->sock < 0)
		return;

	memset(&api, 0, sizeof(api));
	api.type = ZEBRA_ROUTE_NHRP;
	api.safi = SAFI_UNICAST;
	api.vrf_id = VRF_DEFAULT;
	api.prefix = *p;

	switch (type) {
	case NHRP_CACHE_NEGATIVE:
		zapi_route_set_blackhole(&api, BLACKHOLE_REJECT);
		ifp = NULL;
		nexthop = NULL;
		break;
	case NHRP_CACHE_DYNAMIC:
	case NHRP_CACHE_NHS:
	case NHRP_CACHE_STATIC:
		/* Regular route, so these are announced
		 * to other routing daemons */
		break;
	default:
		SET_FLAG(api.flags, ZEBRA_FLAG_FIB_OVERRIDE);
		break;
	}
	SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);

	SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
	api.nexthop_num = 1;
	api_nh = &api.nexthops[0];
	api_nh->vrf_id = VRF_DEFAULT;

	switch (api.prefix.family) {
	case AF_INET:
		if (nexthop) {
			api_nh->gate.ipv4 = nexthop->sin.sin_addr;
			api_nh->type = NEXTHOP_TYPE_IPV4;
		}
		if (ifp) {
			api_nh->ifindex = ifp->ifindex;
			if (api_nh->type == NEXTHOP_TYPE_IPV4)
				api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
			else
				api_nh->type = NEXTHOP_TYPE_IFINDEX;
		}
		break;
	case AF_INET6:
		if (nexthop) {
			api_nh->gate.ipv6 = nexthop->sin6.sin6_addr;
			api_nh->type = NEXTHOP_TYPE_IPV6;
		}
		if (ifp) {
			api_nh->ifindex = ifp->ifindex;
			if (api_nh->type == NEXTHOP_TYPE_IPV6)
				api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
			else
				api_nh->type = NEXTHOP_TYPE_IFINDEX;
		}
		break;
	}
	if (mtu) {
		SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
		api.mtu = mtu;
	}

	if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) {
		char buf[2][PREFIX_STRLEN];

		prefix2str(&api.prefix, buf[0], sizeof(buf[0]));
		zlog_debug(
			"Zebra send: route %s %s nexthop %s metric %u"
			" count %d dev %s",
			add ? "add" : "del", buf[0],
			nexthop ? inet_ntop(api.prefix.family, &api_nh->gate,
					    buf[1], sizeof(buf[1]))
				: "<onlink>",
			api.metric, api.nexthop_num, ifp ? ifp->name : "none");
	}

	zclient_route_send(add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, zclient,
			   &api);
}
Exemple #8
0
int bgp_peer_log_msg(struct bgp_node *route, struct bgp_info *ri, safi_t safi, char *event_type, int output)
{
  char log_rk[SRVBUFLEN];
  struct bgp_peer *peer = ri->peer;
  struct bgp_attr *attr = ri->attr;
  int ret = 0, amqp_ret = 0, etype = BGP_LOGDUMP_ET_NONE;

  if (!strcmp(event_type, "dump")) etype = BGP_LOGDUMP_ET_DUMP;
  else if (!strcmp(event_type, "log")) etype = BGP_LOGDUMP_ET_LOG;
  
#ifdef WITH_RABBITMQ
  if ((config.nfacctd_bgp_msglog_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) ||
      (config.bgp_table_dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP))
    p_amqp_set_routing_key(peer->log->amqp_host, peer->log->filename);
#endif

  if (output == PRINT_OUTPUT_JSON) {
#ifdef WITH_JANSSON
    char ip_address[INET6_ADDRSTRLEN];
    json_t *obj = json_object(), *kv;

    char empty[] = "";
    char prefix_str[INET6_ADDRSTRLEN], nexthop_str[INET6_ADDRSTRLEN];
    char *aspath;

    /* no need for seq and timestamp for "dump" event_type */
    if (etype == BGP_LOGDUMP_ET_LOG) {
      kv = json_pack("{sI}", "seq", log_seq);
      json_object_update_missing(obj, kv);
      json_decref(kv);
      bgp_peer_log_seq_increment(&log_seq);

      kv = json_pack("{ss}", "timestamp", log_tstamp_str);
      json_object_update_missing(obj, kv);
      json_decref(kv);
    }

    addr_to_str(ip_address, &peer->addr);
    kv = json_pack("{ss}", "peer_ip_src", ip_address);
    json_object_update_missing(obj, kv);
    json_decref(kv);

    kv = json_pack("{ss}", "event_type", event_type);
    json_object_update_missing(obj, kv);
    json_decref(kv);

    memset(prefix_str, 0, INET6_ADDRSTRLEN);
    prefix2str(&route->p, prefix_str, INET6_ADDRSTRLEN);
    kv = json_pack("{ss}", "ip_prefix", prefix_str);
    json_object_update_missing(obj, kv);
    json_decref(kv);

    memset(nexthop_str, 0, INET6_ADDRSTRLEN);
    if (attr->mp_nexthop.family) addr_to_str(nexthop_str, &attr->mp_nexthop);
    else inet_ntop(AF_INET, &attr->nexthop, nexthop_str, INET6_ADDRSTRLEN);
    kv = json_pack("{ss}", "bgp_nexthop", nexthop_str);
    json_object_update_missing(obj, kv);
    json_decref(kv);

    if (ri && ri->extra && ri->extra->path_id) {
      kv = json_pack("{sI}", "as_path_id", ri->extra->path_id);
      json_object_update_missing(obj, kv);
      json_decref(kv);
    }

    aspath = attr->aspath ? attr->aspath->str : empty;
    kv = json_pack("{ss}", "as_path", aspath);
    json_object_update_missing(obj, kv);
    json_decref(kv);

    if (attr->community) {
      kv = json_pack("{ss}", "comms", attr->community->str);
      json_object_update_missing(obj, kv);
      json_decref(kv);
    }

    if (attr->ecommunity) {
      kv = json_pack("{ss}", "ecomms", attr->ecommunity->str);
      json_object_update_missing(obj, kv);
      json_decref(kv);
    }

    kv = json_pack("{sI}", "origin", attr->origin);
    json_object_update_missing(obj, kv);
    json_decref(kv);

    kv = json_pack("{sI}", "local_pref", attr->local_pref);
    json_object_update_missing(obj, kv);
    json_decref(kv);

    if (attr->med) {
      kv = json_pack("{sI}", "med", attr->med);
      json_object_update_missing(obj, kv);
      json_decref(kv);
    }

    if (safi == SAFI_MPLS_VPN) {
      u_char rd_str[SRVBUFLEN];

      bgp_rd2str(rd_str, &ri->extra->rd);
      kv = json_pack("{ss}", "rd", rd_str);
      json_object_update_missing(obj, kv);
      json_decref(kv);
    }

    if ((config.nfacctd_bgp_msglog_file && etype == BGP_LOGDUMP_ET_LOG) ||
	(config.bgp_table_dump_file && etype == BGP_LOGDUMP_ET_DUMP))
      write_and_free_json(peer->log->fd, obj);

#ifdef WITH_RABBITMQ
    if ((config.nfacctd_bgp_msglog_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) ||
	(config.bgp_table_dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP)) {
      amqp_ret = write_and_free_json_amqp(peer->log->amqp_host, obj);
      p_amqp_unset_routing_key(peer->log->amqp_host);
    }
#endif
#endif
  }

  return (ret | amqp_ret);
}
Exemple #9
0
/*
 * Handle netlink notification informing a rule add or delete.
 * Handling of an ADD is TBD.
 * DELs are notified up, if other attributes indicate it may be a
 * notification of interest. The expectation is that if this corresponds
 * to a PBR rule added by FRR, it will be readded.
 */
int netlink_rule_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
{
	struct zebra_ns *zns;
	struct fib_rule_hdr *frh;
	struct rtattr *tb[FRA_MAX + 1];
	int len;
	char *ifname;
	struct zebra_pbr_rule rule = {};
	char buf1[PREFIX_STRLEN];
	char buf2[PREFIX_STRLEN];

	/* Basic validation followed by extracting attributes. */
	if (h->nlmsg_type != RTM_NEWRULE && h->nlmsg_type != RTM_DELRULE)
		return 0;

	/* TBD */
	if (h->nlmsg_type == RTM_NEWRULE)
		return 0;

	len = h->nlmsg_len - NLMSG_LENGTH(sizeof(struct fib_rule_hdr));
	if (len < 0) {
		zlog_err("%s: Message received from netlink is of a broken size: %d %zu",
			 __PRETTY_FUNCTION__, h->nlmsg_len,
			 (size_t)NLMSG_LENGTH(sizeof(struct fib_rule_hdr)));
		return -1;
	}

	frh = NLMSG_DATA(h);
	if (frh->family != AF_INET && frh->family != AF_INET6) {
		flog_warn(
			EC_ZEBRA_NETLINK_INVALID_AF,
			"Invalid address family: %u received from kernel rule change: %u",
			frh->family, h->nlmsg_type);
		return 0;
	}
	if (frh->action != FR_ACT_TO_TBL)
		return 0;

	memset(tb, 0, sizeof(tb));
	netlink_parse_rtattr(tb, FRA_MAX, RTM_RTA(frh), len);

	/* TBD: We don't care about rules not specifying an IIF. */
	if (tb[FRA_IFNAME] == NULL)
		return 0;

	/* If we don't know the interface, we don't care. */
	ifname = (char *)RTA_DATA(tb[FRA_IFNAME]);
	zns = zebra_ns_lookup(ns_id);
	rule.ifp = if_lookup_by_name_per_ns(zns, ifname);
	if (!rule.ifp)
		return 0;

	if (tb[FRA_PRIORITY])
		rule.rule.priority = *(uint32_t *)RTA_DATA(tb[FRA_PRIORITY]);

	if (tb[FRA_SRC]) {
		if (frh->family == AF_INET)
			memcpy(&rule.rule.filter.src_ip.u.prefix4,
			       RTA_DATA(tb[FRA_SRC]), 4);
		else
			memcpy(&rule.rule.filter.src_ip.u.prefix6,
			       RTA_DATA(tb[FRA_SRC]), 16);
		rule.rule.filter.src_ip.prefixlen = frh->src_len;
		rule.rule.filter.filter_bm |= PBR_FILTER_SRC_IP;
	}

	if (tb[FRA_DST]) {
		if (frh->family == AF_INET)
			memcpy(&rule.rule.filter.dst_ip.u.prefix4,
			       RTA_DATA(tb[FRA_DST]), 4);
		else
			memcpy(&rule.rule.filter.dst_ip.u.prefix6,
			       RTA_DATA(tb[FRA_DST]), 16);
		rule.rule.filter.dst_ip.prefixlen = frh->dst_len;
		rule.rule.filter.filter_bm |= PBR_FILTER_DST_IP;
	}

	if (tb[FRA_TABLE])
		rule.rule.action.table = *(uint32_t *)RTA_DATA(tb[FRA_TABLE]);
	else
		rule.rule.action.table = frh->table;

	if (IS_ZEBRA_DEBUG_KERNEL)
		zlog_debug(
			"Rx %s family %s IF %s(%u) Pref %u Src %s Dst %s Table %u",
			nl_msg_type_to_str(h->nlmsg_type),
			nl_family_to_str(frh->family), rule.ifp->name,
			rule.ifp->ifindex, rule.rule.priority,
			prefix2str(&rule.rule.filter.src_ip, buf1,
				   sizeof(buf1)),
			prefix2str(&rule.rule.filter.dst_ip, buf2,
				   sizeof(buf2)),
			rule.rule.action.table);

	return kernel_pbr_rule_del(&rule);
}
Exemple #10
0
/* Install or uninstall specified rule for a specific interface.
 * Form netlink message and ship it. Currently, notify status after
 * waiting for netlink status.
 */
static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)
{
	int family;
	int bytelen;
	struct {
		struct nlmsghdr n;
		struct fib_rule_hdr frh;
		char buf[NL_PKT_BUF_SIZE];
	} req;
	struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
	struct sockaddr_nl snl;
	char buf1[PREFIX_STRLEN];
	char buf2[PREFIX_STRLEN];

	memset(&req, 0, sizeof(req) - NL_PKT_BUF_SIZE);
	family = PREFIX_FAMILY(&rule->rule.filter.src_ip);
	bytelen = (family == AF_INET ? 4 : 16);

	req.n.nlmsg_type = cmd;
	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
	req.n.nlmsg_flags = NLM_F_REQUEST;
	req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;

	req.frh.family = family;
	req.frh.action = FR_ACT_TO_TBL;

	/* rule's pref # */
	addattr32(&req.n, sizeof(req), FRA_PRIORITY, rule->rule.priority);

	/* interface on which applied */
	if (rule->ifp)
		addattr_l(&req.n, sizeof(req), FRA_IFNAME, rule->ifp->name,
			  strlen(rule->ifp->name) + 1);

	/* source IP, if specified */
	if (IS_RULE_FILTERING_ON_SRC_IP(rule)) {
		req.frh.src_len = rule->rule.filter.src_ip.prefixlen;
		addattr_l(&req.n, sizeof(req), FRA_SRC,
			  &rule->rule.filter.src_ip.u.prefix, bytelen);
	}
	/* destination IP, if specified */
	if (IS_RULE_FILTERING_ON_DST_IP(rule)) {
		req.frh.dst_len = rule->rule.filter.dst_ip.prefixlen;
		addattr_l(&req.n, sizeof(req), FRA_DST,
			  &rule->rule.filter.dst_ip.u.prefix, bytelen);
	}

	/* fwmark, if specified */
	if (IS_RULE_FILTERING_ON_FWMARK(rule)) {
		addattr32(&req.n, sizeof(req), FRA_FWMARK,
			  rule->rule.filter.fwmark);
	}

	/* Route table to use to forward, if filter criteria matches. */
	if (rule->rule.action.table < 256)
		req.frh.table = rule->rule.action.table;
	else {
		req.frh.table = RT_TABLE_UNSPEC;
		addattr32(&req.n, sizeof(req), FRA_TABLE,
			  rule->rule.action.table);
	}

	if (IS_ZEBRA_DEBUG_KERNEL)
		zlog_debug(
			"Tx %s family %s IF %s(%u) Pref %u Fwmark %u Src %s Dst %s Table %u",
			nl_msg_type_to_str(cmd), nl_family_to_str(family),
			rule->ifp ? rule->ifp->name : "Unknown",
			rule->ifp ? rule->ifp->ifindex : 0, rule->rule.priority,
			rule->rule.filter.fwmark,
			prefix2str(&rule->rule.filter.src_ip, buf1,
				   sizeof(buf1)),
			prefix2str(&rule->rule.filter.dst_ip, buf2,
				   sizeof(buf2)),
			rule->rule.action.table);

	/* Ship off the message.
	 * Note: Currently, netlink_talk() is a blocking call which returns
	 * back the status.
	 */
	memset(&snl, 0, sizeof(snl));
	snl.nl_family = AF_NETLINK;
	return netlink_talk(netlink_talk_filter, &req.n,
			    &zns->netlink_cmd, zns, 0);
}
static void
ospf6_damp_event (damp_event_t event_type,
                  u_short type, struct prefix *name,
                  int (*event) (void *), void *target)
{
    time_t t_now, t_diff;
    struct ospf6_damp_info *di;
    char namebuf[64];
    struct timeval now;

    if (dc->enabled == OFF)
    {
        (*event) (target);
        return;
    }

    di = ospf6_damp_lookup (type, name);
    if (! di)
        di = ospf6_damp_create (type, name);

    t_now = time (NULL);

    di->event = event;
    di->target = target;
    di->event_type = event_type;

    if (! ospf6_reuse_list_lookup (di))
        di->t_start = t_now;
    else
    {
        ospf6_reuse_list_remove (di);

        t_diff = t_now - di->t_updated;
        di->penalty = (int) (di->penalty * ospf6_damp_decay (t_diff));
    }

    /* penalty only on down event */
    if (event_type == event_down)
    {
        di->flap++;
        di->penalty += dc->default_penalty;
    }

    /* limit penalty up to ceiling */
    if (di->penalty > dc->ceiling)
        di->penalty = dc->ceiling;

    if (IS_OSPF6_DEBUG_DAMP)
    {
        prefix2str (&di->name, namebuf, sizeof (namebuf));
        gettimeofday (&now, NULL);
        zlog_info ("DAMP: %lu.%06lu update penalty: type: %d, name: %s, penalty: %d",
                   now.tv_sec, now.tv_usec,
                   di->type, namebuf, di->penalty);
    }

    /* if penalty < reuse, stop damping here */
    if (di->penalty < dc->reuse && di->damping == ON)
    {
        if (IS_OSPF6_DEBUG_DAMP)
        {
            prefix2str (&di->name, namebuf, sizeof (namebuf));
            gettimeofday (&now, NULL);
            zlog_info ("DAMP: %lu.%06lu stop damping: %ld: type: %d, name: %s",
                       now.tv_sec, now.tv_usec,
                       t_now, di->type, namebuf);
        }
        di->damping = OFF;
    }

    /* if event == up and if penalty >= suppress , start damping here */
    if (di->event_type == event_up && di->penalty >= dc->suppress &&
            di->damping == OFF)
    {
        if (IS_OSPF6_DEBUG_DAMP)
        {
            prefix2str (&di->name, namebuf, sizeof (namebuf));
            gettimeofday (&now, NULL);
            zlog_info ("DAMP: %lu.%06lu start damping: %ld: type: %d, name: %s",
                       now.tv_sec, now.tv_usec,
                       t_now, type, namebuf);
        }
        di->damping = ON;
    }

    /* execute event if we're not damping */
    if (di->damping == OFF)
    {
        (*(di->event)) (di->target);
        di->target_status = di->event_type;
    }

    /* if the penalty goes beyond suppress value, start damping */
    if (di->penalty >= dc->suppress && di->damping == OFF)
    {
        if (IS_OSPF6_DEBUG_DAMP)
        {
            prefix2str (name, namebuf, sizeof (namebuf));
            gettimeofday (&now, NULL);
            zlog_info ("DAMP: %lu.%06lu start damping: %ld: type: %d, name: %s",
                       now.tv_sec, now.tv_usec,
                       t_now, type, namebuf);
        }
        di->damping = ON;
    }

    /* update last-updated-time field */
    di->t_updated = t_now;

    /* Insert it into the reuse list */
    ospf6_reuse_list_add (di);
}
/* ospf6_reuse_timer is called every DELTA_REUSE seconds.
   Each route in the current reuse-list is evaluated
   and is used or requeued */
int
ospf6_damp_reuse_timer (struct thread *t)
{
    struct ospf6_damp_info *di, *next;
    time_t t_now, t_diff;
    char namebuf[64];
    struct timeval now;

    /* Restart the reuse timer */
    ospf6_reuse_thread =
        thread_add_timer (master, ospf6_damp_reuse_timer, NULL, dc->delta_reuse);

    t_now = time (NULL);

    /* get the damp info list head */
    di = dc->reuse_list_array[reuse_array_offset];
    dc->reuse_list_array[reuse_array_offset] = NULL;

    /* rotate the circular reuse list head array */
    reuse_array_offset = (reuse_array_offset + 1) % dc->reuse_list_size;

    /* for each damp info */
    while (di)
    {
        next = di->next;
        di->next = NULL;

        /* Update penalty */
        t_diff = t_now - di->t_updated;
        di->t_updated = t_now;
        di->penalty = (int)
                      ((double) di->penalty * ospf6_damp_decay (t_diff));
        /* configration of ceiling may be just changed */
        if (di->penalty > dc->ceiling)
            di->penalty = dc->ceiling;

        if (IS_OSPF6_DEBUG_DAMP)
        {
            prefix2str (&di->name, namebuf, sizeof (namebuf));
            gettimeofday (&now, NULL);
            zlog_info ("DAMP: %lu.%06lu update penalty: type: %d, name: %s, penalty: %d",
                       now.tv_sec, now.tv_usec,
                       di->type, namebuf, di->penalty);
        }

        /* If the penalty becomes under reuse,
           call real event that we have been postponed. */
        if (di->penalty < dc->reuse && di->damping == ON)
            ospf6_damp_stop (di);

        /* If the penalty becomes less than the half of the
           reuse value, this damp info will be freed from reuse-list,
           by assuming that it is considered to be stable enough already,
           and there's no need to maintain flapping history for this. */
        if (di->penalty <= dc->reuse / 2)
        {
            ospf6_damp_delete (di->type, &di->name);
            di = next;
            continue;
        }

        /* re-insert to the reuse-list */
        ospf6_reuse_list_add (di);

        di = next;
    }

    return 0;
}
Exemple #13
0
static int
ospf6_zebra_read_ipv6 (int command, struct zclient *zclient,
                       zebra_size_t length)
{
  struct stream *s;
  struct zapi_ipv6 api;
  unsigned long ifindex;
  struct prefix_ipv6 p;
  struct in6_addr *nexthop;

  s = zclient->ibuf;
  ifindex = 0;
  nexthop = NULL;
  memset (&api, 0, sizeof (api));

  /* Type, flags, message. */
  api.type = stream_getc (s);
  api.flags = stream_getc (s);
  api.message = stream_getc (s);

  /* IPv6 prefix. */
  memset (&p, 0, sizeof (struct prefix_ipv6));
  p.family = AF_INET6;
  p.prefixlen = stream_getc (s);
  stream_get (&p.prefix, s, PSIZE (p.prefixlen));

  /* Nexthop, ifindex, distance, metric. */
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    {
      api.nexthop_num = stream_getc (s);
      nexthop = (struct in6_addr *)
        malloc (api.nexthop_num * sizeof (struct in6_addr));
      stream_get (nexthop, s, api.nexthop_num * sizeof (struct in6_addr));
    }
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
    {
      api.ifindex_num = stream_getc (s);
      ifindex = stream_getl (s);
    }
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
    api.distance = stream_getc (s);
  else
    api.distance = 0;
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    api.metric = stream_getl (s);
  else
    api.metric = 0;

  if (IS_OSPF6_DEBUG_ZEBRA (RECV))
    {
      char prefixstr[128], nexthopstr[128];
      prefix2str ((struct prefix *)&p, prefixstr, sizeof (prefixstr));
      if (nexthop)
        inet_ntop (AF_INET6, nexthop, nexthopstr, sizeof (nexthopstr));
      else
        snprintf (nexthopstr, sizeof (nexthopstr), "::");

      zlog_debug ("Zebra Receive route %s: %s %s nexthop %s ifindex %ld",
		  (command == ZEBRA_IPV6_ROUTE_ADD ? "add" : "delete"),
		  zebra_route_string(api.type), prefixstr, nexthopstr, ifindex);
    }
 
  if (command == ZEBRA_IPV6_ROUTE_ADD)
    ospf6_asbr_redistribute_add (api.type, ifindex, (struct prefix *) &p,
                                 api.nexthop_num, nexthop);
  else
    ospf6_asbr_redistribute_remove (api.type, ifindex, (struct prefix *) &p);

  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    free (nexthop);

  return 0;
}
Exemple #14
0
int
operand2str(operand_t const *op, char *buf, size_t size)
{
    char *ptr = buf, *end = buf + size;

    switch (op->type) {
    case invalid:
        DBE(INSN, dprintk("(inval)"));
        break;
    case op_reg:
        ptr += reg2str(op->val.reg, op->tag.reg, op->size, op->rex_used,
                       ptr, end - ptr);
        DBE(INSN, dprintk("(reg) %s", buf));
        break;
    case op_seg:
        ptr += seg2str(op->val.seg, op->tag.seg, ptr, end - ptr);
        DBE(INSN, dprintk("(seg) %s", buf));
        break;
    case op_mem:
        ptr += mem2str(&op->val.mem, &op->tag.mem, op->size, op->rex_used, ptr,
                       end - ptr);
        DBE(INSN, dprintk("(mem) %s", buf));
        break;
    case op_imm:
        ptr += imm2str(op->val.imm, op->tag.imm, ptr, end - ptr);
        DBE(INSN, dprintk("(imm) %s", buf));
        break;
    case op_pcrel:
        ptr += pcrel2str(op->val.pcrel, op->tag.pcrel, ptr, end - ptr);
        DBE(INSN, dprintk("(pcrel) %s", buf));
        break;
    case op_cr:
        ptr += cr2str(op->val.cr, op->tag.cr, ptr, end - ptr);
        DBE(INSN, dprintk("(cr) %s", buf));
        break;
    case op_db:
        ptr += db2str(op->val.db, op->tag.db, ptr, end - ptr);
        DBE(INSN, dprintk("(db) %s", buf));
        break;
    case op_tr:
        ptr += tr2str(op->val.tr, op->tag.tr, ptr, end - ptr);
        DBE(INSN, dprintk("(tr) %s", buf));
        break;
    case op_mmx:
        ptr += mmx2str(op->val.mmx, op->tag.mmx, ptr, end - ptr);
        DBE(INSN, dprintk("(mm) %s", buf));
        break;
    case op_xmm:
        ptr += xmm2str(op->val.xmm, op->tag.xmm, ptr, end - ptr);
        DBE(INSN, dprintk("(xmm) %s", buf));
        break;
    case op_3dnow:
        ptr += op3dnow2str(op->val.d3now, op->tag.d3now, ptr, end - ptr);
        DBE(INSN, dprintk("(3dnow) %s", buf));
        break;
    case op_prefix:
        ptr += prefix2str(op->val.prefix, op->tag.prefix, ptr, end - ptr);
        break;
    case op_st:
        ptr += st2str(op->val.st, op->tag.st, ptr, end - ptr);
        break;
    default:
        dprintk("Invalid op->type[%d]\n", op->type);
        ASSERT(0);
    }

    return ptr - buf;
}
Exemple #15
0
static void nhrp_interface_update_address(struct interface *ifp, afi_t afi, int force)
{
	const int family = afi2family(afi);
	struct nhrp_interface *nifp = ifp->info;
	struct nhrp_afi_data *if_ad = &nifp->afi[afi];
	struct nhrp_cache *nc;
	struct connected *c, *best;
	struct listnode *cnode;
	union sockunion addr;
	char buf[PREFIX_STRLEN];

	/* Select new best match preferring primary address */
	best = NULL;
	for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
		if (PREFIX_FAMILY(c->address) != family)
			continue;
		if (best == NULL) {
			best = c;
			continue;
		}
		if ((best->flags & ZEBRA_IFA_SECONDARY) && !(c->flags & ZEBRA_IFA_SECONDARY)) {
			best = c;
			continue;
		}
		if (!(best->flags & ZEBRA_IFA_SECONDARY) && (c->flags & ZEBRA_IFA_SECONDARY))
			continue;
		if (best->address->prefixlen > c->address->prefixlen) {
			best = c;
			continue;
		}
		if (best->address->prefixlen < c->address->prefixlen)
			continue;
	}

	/* On NHRP interfaces a host prefix is required */
	if (best && if_ad->configured && best->address->prefixlen != 8 * prefix_blen(best->address)) {
		zlog_notice("%s: %s is not a host prefix", ifp->name,
			prefix2str(best->address, buf, sizeof buf));
		best = NULL;
	}

	/* Update address if it changed */
	if (best)
		prefix2sockunion(best->address, &addr);
	else
		memset(&addr, 0, sizeof(addr));

	if (!force && sockunion_same(&if_ad->addr, &addr))
		return;

	if (sockunion_family(&if_ad->addr) != AF_UNSPEC) {
		nc = nhrp_cache_get(ifp, &if_ad->addr, 0);
		if (nc) nhrp_cache_update_binding(nc, NHRP_CACHE_LOCAL, -1, NULL, 0, NULL);
	}

	debugf(NHRP_DEBUG_KERNEL, "%s: IPv%d address changed to %s",
		ifp->name, afi == AFI_IP ? 4 : 6,
		best ? prefix2str(best->address, buf, sizeof buf) : "(none)");
	if_ad->addr = addr;

	if (if_ad->configured && sockunion_family(&if_ad->addr) != AF_UNSPEC) {
		nc = nhrp_cache_get(ifp, &addr, 1);
		if (nc) nhrp_cache_update_binding(nc, NHRP_CACHE_LOCAL, 0, NULL, 0, NULL);
	}

	notifier_call(&nifp->notifier_list, NOTIFY_INTERFACE_ADDRESS_CHANGED);
}
int
ospf6_zebra_read_ipv6 (int command, struct zclient *zclient,
                       zebra_size_t length)
{
  struct stream *s;
  struct zapi_ipv6 api;
  unsigned long ifindex;
  struct prefix_ipv6 p;
  struct in6_addr *nexthop;
  char prefixstr[128], nexthopstr[128];

  s = zclient->ibuf;
  ifindex = 0;
  nexthop = NULL;
  memset (&api, 0, sizeof (api));

  /* Type, flags, message. */
  api.type = stream_getc (s);
  api.flags = stream_getc (s);
  api.message = stream_getc (s);

  /* IPv6 prefix. */
  memset (&p, 0, sizeof (struct prefix_ipv6));
  p.family = AF_INET6;
  p.prefixlen = stream_getc (s);
  stream_get (&p.prefix, s, PSIZE (p.prefixlen));

  /* Nexthop, ifindex, distance, metric. */
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    {
      api.nexthop_num = stream_getc (s);
      nexthop = (struct in6_addr *)
        malloc (api.nexthop_num * sizeof (struct in6_addr));
      stream_get (nexthop, s, api.nexthop_num * sizeof (struct in6_addr));
    }
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
    {
      api.ifindex_num = stream_getc (s);
      ifindex = stream_getl (s);
    }
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
    api.distance = stream_getc (s);
  else
    api.distance = 0;
  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
    api.metric = stream_getl (s);
  else
    api.metric = 0;

  /* log */
  if (IS_OSPF6_DUMP_ZEBRA)
    {
      prefix2str ((struct prefix *)&p, prefixstr, sizeof (prefixstr));
      inet_ntop (AF_INET6, &nexthop, nexthopstr, sizeof (nexthopstr));

      if (command == ZEBRA_IPV6_ROUTE_ADD)
	zlog_info ("ZEBRA: Receive add %s route: %s nexthop:%s ifindex:%ld",
		   zebra_route_name [api.type], prefixstr,
		   nexthopstr, ifindex);
      else
	zlog_info ("ZEBRA: Receive remove %s route: %s nexthop:%s ifindex:%ld",
		   zebra_route_name [api.type], prefixstr,
		   nexthopstr, ifindex);
    }
 
  if (command == ZEBRA_IPV6_ROUTE_ADD)
    ospf6_asbr_route_add (api.type, ifindex, (struct prefix *) &p,
                          api.nexthop_num, nexthop);
  else
    ospf6_asbr_route_remove (api.type, ifindex, (struct prefix *) &p);

  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    free (nexthop);

  return 0;
}
void
ospf6_interface_connected_route_update (struct interface *ifp)
{
    struct ospf6_interface *oi;
    struct ospf6_route *route;
    struct connected *c;
    struct listnode *node, *nnode;

    oi = (struct ospf6_interface *) ifp->info;
    if (oi == NULL)
        return;

    /* reset linklocal pointer */
    oi->linklocal_addr = ospf6_interface_get_linklocal_address (ifp);

    /* if area is null, do not make connected-route list */
    if (oi->area == NULL)
        return;

    /* update "route to advertise" interface route table */
    ospf6_route_remove_all (oi->route_connected);

    for (ALL_LIST_ELEMENTS (oi->interface->connected, node, nnode, c))
    {
        if (c->address->family != AF_INET6)
            continue;

        CONTINUE_IF_ADDRESS_LINKLOCAL (IS_OSPF6_DEBUG_INTERFACE, c->address);
        CONTINUE_IF_ADDRESS_UNSPECIFIED (IS_OSPF6_DEBUG_INTERFACE, c->address);
        CONTINUE_IF_ADDRESS_LOOPBACK (IS_OSPF6_DEBUG_INTERFACE, c->address);
        CONTINUE_IF_ADDRESS_V4COMPAT (IS_OSPF6_DEBUG_INTERFACE, c->address);
        CONTINUE_IF_ADDRESS_V4MAPPED (IS_OSPF6_DEBUG_INTERFACE, c->address);

        /* apply filter */
        if (oi->plist_name)
        {
            struct prefix_list *plist;
            enum prefix_list_type ret;
            char buf[128];

            prefix2str (c->address, buf, sizeof (buf));
            plist = prefix_list_lookup (AFI_IP6, oi->plist_name);
            ret = prefix_list_apply (plist, (void *) c->address);
            if (ret == PREFIX_DENY)
            {
                if (IS_OSPF6_DEBUG_INTERFACE)
                    zlog_debug ("%s on %s filtered by prefix-list %s ",
                                buf, oi->interface->name, oi->plist_name);
                continue;
            }
        }

        route = ospf6_route_create ();
        memcpy (&route->prefix, c->address, sizeof (struct prefix));
        apply_mask (&route->prefix);
        route->type = OSPF6_DEST_TYPE_NETWORK;
        route->path.area_id = oi->area->area_id;
        route->path.type = OSPF6_PATH_TYPE_INTRA;
        route->path.cost = oi->cost;
        route->nexthop[0].ifindex = oi->interface->ifindex;
        inet_pton (AF_INET6, "::1", &route->nexthop[0].address);
        ospf6_route_add (route, oi->route_connected);
    }

    /* create new Link-LSA */
    OSPF6_LINK_LSA_SCHEDULE (oi);
    OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
    OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB (oi->area);
}
Exemple #18
0
static int pim_zebra_if_address_add(int command, struct zclient *zclient,
				    zebra_size_t length, vrf_id_t vrf_id)
{
  struct connected *c;
  struct prefix *p;

  /*
    zebra api notifies address adds/dels events by using the same call
    interface_add_read below, see comments in lib/zclient.c

    zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
    will add address to interface list by calling
    connected_add_by_prefix()
  */
  c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);
  if (!c)
    return 0;

  p = c->address;
  if (p->family != AF_INET)
    return 0;
  
  if (PIM_DEBUG_ZEBRA) {
    char buf[BUFSIZ];
    prefix2str(p, buf, BUFSIZ);
    zlog_debug("%s: %s connected IP address %s flags %u %s",
	       __PRETTY_FUNCTION__,
	       c->ifp->name, buf, c->flags,
	       CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY) ? "secondary" : "primary");
    
#ifdef PIM_DEBUG_IFADDR_DUMP
    dump_if_address(c->ifp);
#endif
  }

  if (!CHECK_FLAG(c->flags, ZEBRA_IFA_SECONDARY)) {
    /* trying to add primary address */

    struct in_addr primary_addr = pim_find_primary_addr(c->ifp);
    if (primary_addr.s_addr != p->u.prefix4.s_addr) {
      if (PIM_DEBUG_ZEBRA) {
	/* but we had a primary address already */

	char buf[BUFSIZ];
	char old[100];

	prefix2str(p, buf, BUFSIZ);
	pim_inet4_dump("<old?>", primary_addr, old, sizeof(old));

	zlog_warn("%s: %s primary addr old=%s: forcing secondary flag on new=%s",
		  __PRETTY_FUNCTION__,
		  c->ifp->name, old, buf);
      }
      SET_FLAG(c->flags, ZEBRA_IFA_SECONDARY);
    }
  }

  pim_if_addr_add(c);

  return 0;
}
/* show specified interface structure */
static int
ospf6_interface_show (struct vty *vty, struct interface *ifp)
{
    struct ospf6_interface *oi;
    struct connected *c;
    struct prefix *p;
    struct listnode *i;
    char strbuf[64], drouter[32], bdrouter[32];
    const char *updown[3] = {"down", "up", NULL};
    const char *type;
    struct timeval res, now;
    char duration[32];
    struct ospf6_lsa *lsa;

    /* check physical interface type */
    if (if_is_loopback (ifp))
        type = "LOOPBACK";
    else if (if_is_broadcast (ifp))
        type = "BROADCAST";
    else if (if_is_pointopoint (ifp))
        type = "POINTOPOINT";
    else
        type = "UNKNOWN";

    vty_out (vty, "%s is %s, type %s%s",
             ifp->name, updown[if_is_up (ifp)], type,
             VNL);
    vty_out (vty, "  Interface ID: %d%s", ifp->ifindex, VNL);

    if (ifp->info == NULL)
    {
        vty_out (vty, "   OSPF not enabled on this interface%s", VNL);
        return 0;
    }
    else
        oi = (struct ospf6_interface *) ifp->info;

    vty_out (vty, "  Internet Address:%s", VNL);

    for (ALL_LIST_ELEMENTS_RO (ifp->connected, i, c))
    {
        p = c->address;
        prefix2str (p, strbuf, sizeof (strbuf));
        switch (p->family)
        {
        case AF_INET:
            vty_out (vty, "    inet : %s%s", strbuf,
                     VNL);
            break;
        case AF_INET6:
            vty_out (vty, "    inet6: %s%s", strbuf,
                     VNL);
            break;
        default:
            vty_out (vty, "    ???  : %s%s", strbuf,
                     VNL);
            break;
        }
    }

    if (oi->area)
    {
        vty_out (vty, "  Instance ID %d, Interface MTU %d (autodetect: %d)%s",
                 oi->instance_id, oi->ifmtu, ifp->mtu6, VNL);
        vty_out (vty, "  MTU mismatch detection: %s%s", oi->mtu_ignore ?
                 "disabled" : "enabled", VNL);
        inet_ntop (AF_INET, &oi->area->area_id,
                   strbuf, sizeof (strbuf));
        vty_out (vty, "  Area ID %s, Cost %hu%s", strbuf, oi->cost,
                 VNL);
    }
    else
        vty_out (vty, "  Not Attached to Area%s", VNL);

    vty_out (vty, "  State %s, Transmit Delay %d sec, Priority %d%s",
             ospf6_interface_state_str[oi->state],
             oi->transdelay, oi->priority,
             VNL);
    vty_out (vty, "  Timer intervals configured:%s", VNL);
    vty_out (vty, "   Hello %d, Dead %d, Retransmit %d%s",
             oi->hello_interval, oi->dead_interval, oi->rxmt_interval,
             VNL);

    inet_ntop (AF_INET, &oi->drouter, drouter, sizeof (drouter));
    inet_ntop (AF_INET, &oi->bdrouter, bdrouter, sizeof (bdrouter));
    vty_out (vty, "  DR: %s BDR: %s%s", drouter, bdrouter, VNL);

    vty_out (vty, "  Number of I/F scoped LSAs is %u%s",
             oi->lsdb->count, VNL);

    quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);

    timerclear (&res);
    if (oi->thread_send_lsupdate)
        timersub (&oi->thread_send_lsupdate->u.sands, &now, &res);
    timerstring (&res, duration, sizeof (duration));
    vty_out (vty, "    %d Pending LSAs for LSUpdate in Time %s [thread %s]%s",
             oi->lsupdate_list->count, duration,
             (oi->thread_send_lsupdate ? "on" : "off"),
             VNL);
    for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
            lsa = ospf6_lsdb_next (lsa))
        vty_out (vty, "      %s%s", lsa->name, VNL);

    timerclear (&res);
    if (oi->thread_send_lsack)
        timersub (&oi->thread_send_lsack->u.sands, &now, &res);
    timerstring (&res, duration, sizeof (duration));
    vty_out (vty, "    %d Pending LSAs for LSAck in Time %s [thread %s]%s",
             oi->lsack_list->count, duration,
             (oi->thread_send_lsack ? "on" : "off"),
             VNL);
    for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
            lsa = ospf6_lsdb_next (lsa))
        vty_out (vty, "      %s%s", lsa->name, VNL);

    return 0;
}
Exemple #20
0
int
zebra_evaluate_rnh_table (vrf_id_t vrfid, int family)
{
  struct route_table *ptable;
  struct route_table *ntable;
  struct route_node *prn;
  struct route_node *nrn;
  struct rnh *rnh;
  struct zserv *client;
  struct listnode *node;
  struct rib *rib;

  ntable = lookup_rnh_table(vrfid, family);
  if (!ntable)
    {
      zlog_debug("evaluate_rnh_table: rnh table not found\n");
      return -1;
    }

  ptable = zebra_vrf_table(family2afi(family), SAFI_UNICAST, vrfid);
  if (!ptable)
    {
      zlog_debug("evaluate_rnh_table: prefix table not found\n");
      return -1;
    }

  for (nrn = route_top (ntable); nrn; nrn = route_next (nrn))
    {
      if (!nrn->info)
	  continue;
      
      rnh = nrn->info;
      prn = route_node_match(ptable, &nrn->p);
      if (!prn)
	rib = NULL;
      else
	{
	  RNODE_FOREACH_RIB(prn, rib)
	    {
	      if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
		continue;
	      if (! CHECK_FLAG (rib->status, RIB_ENTRY_SELECTED_FIB))
		continue;

	      if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED))
		{
		  if (rib->type == ZEBRA_ROUTE_CONNECT)
		    break;

		  if (rib->type == ZEBRA_ROUTE_NHRP)
		    {
		      struct nexthop *nexthop;
		      for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
			if (nexthop->type == NEXTHOP_TYPE_IFINDEX ||
			    nexthop->type == NEXTHOP_TYPE_IFNAME)
			  break;
		      if (nexthop)
			break;
		    }
		}
	      else
		break;
	    }
	}

      if (compare_state(rib, rnh->state))
	{
	  if (IS_ZEBRA_DEBUG_NHT)
	    {
	      char bufn[INET6_ADDRSTRLEN];
	      char bufp[INET6_ADDRSTRLEN];
	      prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN);
	      if (prn)
		prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN);
	      else
		strcpy(bufp, "null");
	      zlog_debug("rnh %s resolved through route %s - sending "
			 "nexthop %s event to clients", bufn, bufp,
			 rib ? "reachable" : "unreachable");
	    }
	  copy_state(rnh, rib);
	  for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client))
	    send_client(rnh, client, vrfid);
	}
    }
  return 1;
}
void
ospf6_asbr_external_lsa_update (struct ospf6_route_req *request)
{
  char buffer [MAXLSASIZE];
  u_int16_t size;
  struct ospf6_lsa_as_external *external;
  char *p;
  struct ospf6_route_req route;
  char pbuf[BUFSIZ];

  /* assert this is best path; if not, return */
  ospf6_route_lookup (&route, &request->route.prefix, request->table);
  if (memcmp (&route.path, &request->path, sizeof (route.path)))
    return;

  if (IS_OSPF6_DUMP_LSA)
    zlog_info ("Update AS-External: ID: %lu",
               (u_long) ntohl (request->path.origin.id));

  /* prepare buffer */
  memset (buffer, 0, sizeof (buffer));
  size = sizeof (struct ospf6_lsa_as_external);
  external = (struct ospf6_lsa_as_external *) buffer;
  p = (char *) (external + 1);

  if (route.path.metric_type == 2)
    SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E);   /* type2 */
  else
    UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_E); /* type1 */

  /* forwarding address */
  if (! IN6_IS_ADDR_UNSPECIFIED (&route.nexthop.address))
    SET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F);
  else
    UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F);

  /* external route tag */
  UNSET_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T);

  /* set metric. note: related to E bit */
  OSPF6_ASBR_METRIC_SET (external, route.path.cost);

  /* prefixlen */
  external->prefix.prefix_length = route.route.prefix.prefixlen;

  /* PrefixOptions */
  external->prefix.prefix_options = route.path.prefix_options;

  /* don't use refer LS-type */
  external->prefix.prefix_refer_lstype = htons (0);

  if (IS_OSPF6_DUMP_LSA)
    {
      prefix2str (&route.route.prefix, pbuf, sizeof (pbuf));
      zlog_info ("  Prefix: %s", pbuf);
    }

  /* set Prefix */
  memcpy (p, &route.route.prefix.u.prefix6,
          OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen));
  ospf6_prefix_apply_mask (&external->prefix);
  size += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen);
  p += OSPF6_PREFIX_SPACE (route.route.prefix.prefixlen);

  /* Forwarding address */
  if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
    {
      memcpy (p, &route.nexthop.address, sizeof (struct in6_addr));
      size += sizeof (struct in6_addr);
      p += sizeof (struct in6_addr);
    }

  /* External Route Tag */
  if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_T))
    {
      /* xxx */
    }

  ospf6_lsa_originate (htons (OSPF6_LSA_TYPE_AS_EXTERNAL),
                       route.path.origin.id, ospf6->router_id,
                       (char *) external, size, ospf6);
  return;
}
Exemple #22
0
void eigrp_zebra_init(void)
{
	struct zclient_options opt = {.receive_notify = false};

	zclient = zclient_new_notify(master, &opt);

	zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs);
	zclient->zebra_connected = eigrp_zebra_connected;
	zclient->router_id_update = eigrp_router_id_update_zebra;
	zclient->interface_add = eigrp_interface_add;
	zclient->interface_delete = eigrp_interface_delete;
	zclient->interface_up = eigrp_interface_state_up;
	zclient->interface_down = eigrp_interface_state_down;
	zclient->interface_address_add = eigrp_interface_address_add;
	zclient->interface_address_delete = eigrp_interface_address_delete;
	zclient->redistribute_route_add = eigrp_zebra_read_route;
	zclient->redistribute_route_del = eigrp_zebra_read_route;
	zclient->route_notify_owner = eigrp_zebra_route_notify_owner;
}


/* Zebra route add and delete treatment. */
static int eigrp_zebra_read_route(int command, struct zclient *zclient,
				  zebra_size_t length, vrf_id_t vrf_id)
{
	struct zapi_route api;
	struct eigrp *eigrp;

	if (zapi_route_decode(zclient->ibuf, &api) < 0)
		return -1;

	if (IPV4_NET127(ntohl(api.prefix.u.prefix4.s_addr)))
		return 0;

	eigrp = eigrp_lookup();
	if (eigrp == NULL)
		return 0;

	if (command == ZEBRA_REDISTRIBUTE_ROUTE_ADD) {

	} else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
	{
	}

	return 0;
}

/* Inteface addition message from zebra. */
static int eigrp_interface_add(int command, struct zclient *zclient,
			       zebra_size_t length, vrf_id_t vrf_id)
{
	struct interface *ifp;
	struct eigrp_interface *ei;

	ifp = zebra_interface_add_read(zclient->ibuf, vrf_id);

	if (!ifp->info)
		return 0;

	ei = ifp->info;

	ei->params.type = eigrp_default_iftype(ifp);

	eigrp_if_update(ifp);

	return 0;
}

static int eigrp_interface_delete(int command, struct zclient *zclient,
				  zebra_size_t length, vrf_id_t vrf_id)
{
	struct interface *ifp;
	struct stream *s;

	s = zclient->ibuf;
	/* zebra_interface_state_read () updates interface structure in iflist
	 */
	ifp = zebra_interface_state_read(s, vrf_id);

	if (ifp == NULL)
		return 0;

	if (if_is_up(ifp))
		zlog_warn("Zebra: got delete of %s, but interface is still up",
			  ifp->name);

	if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
		zlog_debug(
			"Zebra: interface delete %s index %d flags %llx metric %d mtu %d",
			ifp->name, ifp->ifindex, (unsigned long long)ifp->flags,
			ifp->metric, ifp->mtu);

	if (ifp->info)
		eigrp_if_free(ifp->info, INTERFACE_DOWN_BY_ZEBRA);

	if_set_index(ifp, IFINDEX_INTERNAL);
	return 0;
}

static int eigrp_interface_address_add(int command, struct zclient *zclient,
				       zebra_size_t length, vrf_id_t vrf_id)
{
	struct connected *c;

	c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);

	if (c == NULL)
		return 0;

	if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) {
		char buf[128];
		prefix2str(c->address, buf, sizeof(buf));
		zlog_debug("Zebra: interface %s address add %s", c->ifp->name,
			   buf);
	}

	eigrp_if_update(c->ifp);

	return 0;
}

static int eigrp_interface_address_delete(int command, struct zclient *zclient,
					  zebra_size_t length, vrf_id_t vrf_id)
{
	struct connected *c;
	struct interface *ifp;
	struct eigrp_interface *ei;

	c = zebra_interface_address_read(command, zclient->ibuf, vrf_id);

	if (c == NULL)
		return 0;

	if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE)) {
		char buf[128];
		prefix2str(c->address, buf, sizeof(buf));
		zlog_debug("Zebra: interface %s address delete %s",
			   c->ifp->name, buf);
	}

	ifp = c->ifp;
	ei = ifp->info;
	if (!ei)
		return 0;

	/* Call interface hook functions to clean up */
	eigrp_if_free(ei, INTERFACE_DOWN_BY_ZEBRA);

	connected_free(c);

	return 0;
}

static int eigrp_interface_state_up(int command, struct zclient *zclient,
				    zebra_size_t length, vrf_id_t vrf_id)
{
	struct interface *ifp;

	ifp = zebra_interface_if_lookup(zclient->ibuf);

	if (ifp == NULL)
		return 0;

	/* Interface is already up. */
	if (if_is_operative(ifp)) {
		/* Temporarily keep ifp values. */
		struct interface if_tmp;
		memcpy(&if_tmp, ifp, sizeof(struct interface));

		zebra_interface_if_set_value(zclient->ibuf, ifp);

		if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
			zlog_debug("Zebra: Interface[%s] state update.",
				   ifp->name);

		if (if_tmp.bandwidth != ifp->bandwidth) {
			if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
				zlog_debug(
					"Zebra: Interface[%s] bandwidth change %d -> %d.",
					ifp->name, if_tmp.bandwidth,
					ifp->bandwidth);

			//          eigrp_if_recalculate_output_cost (ifp);
		}

		if (if_tmp.mtu != ifp->mtu) {
			if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
				zlog_debug(
					"Zebra: Interface[%s] MTU change %u -> %u.",
					ifp->name, if_tmp.mtu, ifp->mtu);

			/* Must reset the interface (simulate down/up) when MTU
			 * changes. */
			eigrp_if_reset(ifp);
		}
		return 0;
	}

	zebra_interface_if_set_value(zclient->ibuf, ifp);

	if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
		zlog_debug("Zebra: Interface[%s] state change to up.",
			   ifp->name);

	if (ifp->info)
		eigrp_if_up(ifp->info);

	return 0;
}

static int eigrp_interface_state_down(int command, struct zclient *zclient,
				      zebra_size_t length, vrf_id_t vrf_id)
{
	struct interface *ifp;

	ifp = zebra_interface_state_read(zclient->ibuf, vrf_id);

	if (ifp == NULL)
		return 0;

	if (IS_DEBUG_EIGRP(zebra, ZEBRA_INTERFACE))
		zlog_debug("Zebra: Interface[%s] state change to down.",
			   ifp->name);

	if (ifp->info)
		eigrp_if_down(ifp->info);

	return 0;
}

static struct interface *zebra_interface_if_lookup(struct stream *s)
{
	char ifname_tmp[INTERFACE_NAMSIZ];

	/* Read interface name. */
	stream_get(ifname_tmp, s, INTERFACE_NAMSIZ);

	/* And look it up. */
	return if_lookup_by_name(ifname_tmp, VRF_DEFAULT);
}
Exemple #23
0
struct ospf6_lsa *
ospf6_lsdb_lookup_next (u_int16_t type, u_int32_t id, u_int32_t adv_router,
                        struct ospf6_lsdb *lsdb)
{
  struct route_node *node;
  struct route_node *matched = NULL;
  struct prefix_ipv6 key;
  struct prefix *p;

  if (lsdb == NULL)
    return NULL;

  memset (&key, 0, sizeof (key));
  ospf6_lsdb_set_key (&key, &type, sizeof (type));
  ospf6_lsdb_set_key (&key, &adv_router, sizeof (adv_router));
  ospf6_lsdb_set_key (&key, &id, sizeof (id));
  p = (struct prefix *) &key;

  {
    char buf[64];
    prefix2str (p, buf, sizeof (buf));
    zlog_debug ("lsdb_lookup_next: key: %s", buf);
  }

  node = lsdb->table->top;
  /* walk down tree. */
  while (node && node->p.prefixlen <= p->prefixlen &&
         prefix_match (&node->p, p))
    {
      matched = node;
      node = node->link[prefix_bit(&p->u.prefix, node->p.prefixlen)];
    }

  if (matched)
    node = matched;
  else
    node = lsdb->table->top;
  route_lock_node (node);

  /* skip to real existing entry */
  while (node && node->info == NULL)
    node = route_next (node);

  if (! node)
    return NULL;

  if (prefix_same (&node->p, p))
    {
      struct route_node *prev = node;
      struct ospf6_lsa *lsa_prev;
      struct ospf6_lsa *lsa_next;

      node = route_next (node);
      while (node && node->info == NULL)
        node = route_next (node);

      lsa_prev = prev->info;
      lsa_next = (node ? node->info : NULL);
      assert (lsa_prev);
      assert (lsa_prev->next == lsa_next);
      if (lsa_next)
        assert (lsa_next->prev == lsa_prev);
      zlog_debug ("lsdb_lookup_next: assert OK with previous LSA");
    }

  if (! node)
    return NULL;

  route_unlock_node (node);
  return (struct ospf6_lsa *) node->info;
}
Exemple #24
0
void
ospf6_asbr_redistribute_add (int type, int ifindex, struct prefix *prefix,
                             u_int nexthop_num, struct in6_addr *nexthop)
{
    int ret;
    struct ospf6_route troute;
    struct ospf6_external_info tinfo;
    struct ospf6_route *route, *match;
    struct ospf6_external_info *info;
    struct prefix prefix_id;
    struct route_node *node;
    char pbuf[64], ibuf[16];
    struct listnode *lnode, *lnnode;
    struct ospf6_area *oa;

    if (! ospf6_zebra_is_redistribute (type))
        return;

    if (IS_OSPF6_DEBUG_ASBR)
    {
        prefix2str (prefix, pbuf, sizeof (pbuf));
        zlog_debug ("Redistribute %s (%s)", pbuf, ZROUTE_NAME (type));
    }

    /* if route-map was specified but not found, do not advertise */
    if (ospf6->rmap[type].name)
    {
        if (ospf6->rmap[type].map == NULL)
            ospf6_asbr_routemap_update (NULL);
        if (ospf6->rmap[type].map == NULL)
        {
            zlog_warn ("route-map \"%s\" not found, suppress redistributing",
                       ospf6->rmap[type].name);
            return;
        }
    }

    /* apply route-map */
    if (ospf6->rmap[type].map)
    {
        memset (&troute, 0, sizeof (troute));
        memset (&tinfo, 0, sizeof (tinfo));
        troute.route_option = &tinfo;
        tinfo.ifindex = ifindex;

        ret = route_map_apply (ospf6->rmap[type].map, prefix,
                               RMAP_OSPF6, &troute);
        if (ret == RMAP_DENYMATCH)
        {
            if (IS_OSPF6_DEBUG_ASBR)
                zlog_debug ("Denied by route-map \"%s\"", ospf6->rmap[type].name);
            return;
        }
    }

    match = ospf6_route_lookup (prefix, ospf6->external_table);
    if (match)
    {
        info = match->route_option;

        /* copy result of route-map */
        if (ospf6->rmap[type].map)
        {
            if (troute.path.metric_type)
                match->path.metric_type = troute.path.metric_type;
            if (troute.path.cost)
                match->path.cost = troute.path.cost;
            if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
                memcpy (&info->forwarding, &tinfo.forwarding,
                        sizeof (struct in6_addr));
        }

        info->type = type;
        match->nexthop[0].ifindex = ifindex;
        if (nexthop_num && nexthop)
            memcpy (&match->nexthop[0].address, nexthop, sizeof (struct in6_addr));

        /* create/update binding in external_id_table */
        prefix_id.family = AF_INET;
        prefix_id.prefixlen = 32;
        prefix_id.u.prefix4.s_addr = htonl (info->id);
        node = route_node_get (ospf6->external_id_table, &prefix_id);
        node->info = match;

        if (IS_OSPF6_DEBUG_ASBR)
        {
            inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
            zlog_debug ("Advertise as AS-External Id:%s", ibuf);
        }

        match->path.origin.id = htonl (info->id);
        ospf6_as_external_lsa_originate (match);
        return;
    }

    /* create new entry */
    route = ospf6_route_create ();
    route->type = OSPF6_DEST_TYPE_NETWORK;
    memcpy (&route->prefix, prefix, sizeof (struct prefix));

    info = (struct ospf6_external_info *)
           XCALLOC (MTYPE_OSPF6_EXTERNAL_INFO, sizeof (struct ospf6_external_info));
    route->route_option = info;
    info->id = ospf6->external_id++;

    /* copy result of route-map */
    if (ospf6->rmap[type].map)
    {
        if (troute.path.metric_type)
            route->path.metric_type = troute.path.metric_type;
        if (troute.path.cost)
            route->path.cost = troute.path.cost;
        if (! IN6_IS_ADDR_UNSPECIFIED (&tinfo.forwarding))
            memcpy (&info->forwarding, &tinfo.forwarding,
                    sizeof (struct in6_addr));
    }

    info->type = type;
    route->nexthop[0].ifindex = ifindex;
    if (nexthop_num && nexthop)
        memcpy (&route->nexthop[0].address, nexthop, sizeof (struct in6_addr));

    /* create/update binding in external_id_table */
    prefix_id.family = AF_INET;
    prefix_id.prefixlen = 32;
    prefix_id.u.prefix4.s_addr = htonl (info->id);
    node = route_node_get (ospf6->external_id_table, &prefix_id);
    node->info = route;

    route = ospf6_route_add (route, ospf6->external_table);
    route->route_option = info;

    if (IS_OSPF6_DEBUG_ASBR)
    {
        inet_ntop (AF_INET, &prefix_id.u.prefix4, ibuf, sizeof (ibuf));
        zlog_debug ("Advertise as AS-External Id:%s", ibuf);
    }

    route->path.origin.id = htonl (info->id);
    ospf6_as_external_lsa_originate (route);

    /* Router-Bit (ASBR Flag) may have to be updated */
    for (ALL_LIST_ELEMENTS (ospf6->area_list, lnode, lnnode, oa))
        OSPF6_ROUTER_LSA_SCHEDULE (oa);
}
/* RFC 2328 12.4.3. Summary-LSAs */
void
ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
                                     struct ospf6_area *area)
{
  struct ospf6_lsa *lsa, *old = NULL;
  struct ospf6_interface *oi;
  struct ospf6_route *summary, *range = NULL;
  struct ospf6_area *route_area;
  char buffer[OSPF6_MAX_LSASIZE];
  struct ospf6_lsa_header *lsa_header;
  caddr_t p;
  struct ospf6_inter_prefix_lsa *prefix_lsa;
  struct ospf6_inter_router_lsa *router_lsa;
  struct ospf6_route_table *summary_table = NULL;
  u_int16_t type;
  char buf[64];
  int is_debug = 0;

  if (route->type == OSPF6_DEST_TYPE_ROUTER)
    {
      if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_ROUTER))
        {
          is_debug++;
          inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
                     buf, sizeof (buf));
          zlog_debug ("Originating summary in area %s for ASBR %s",
		      area->name, buf);
        }
      summary_table = area->summary_router;
    }
  else
    {
      if (IS_OSPF6_DEBUG_ABR || IS_OSPF6_DEBUG_ORIGINATE (INTER_PREFIX))
        {
          is_debug++;
          prefix2str (&route->prefix, buf, sizeof (buf));
          zlog_debug ("Originating summary in area %s for %s",
		      area->name, buf);
        }
      summary_table = area->summary_prefix;
    }

  summary = ospf6_route_lookup (&route->prefix, summary_table);
  if (summary)
    old = ospf6_lsdb_lookup (summary->path.origin.type,
                             summary->path.origin.id,
                             area->ospf6->router_id, area->lsdb);

  /* if this route has just removed, remove corresponding LSA */
  if (CHECK_FLAG (route->flag, OSPF6_ROUTE_REMOVE))
    {
      if (is_debug)
        zlog_debug ("The route has just removed, purge previous LSA");
      if (summary)
        ospf6_route_remove (summary, summary_table);
      if (old)
        ospf6_lsa_purge (old);
      return;
    }

  /* Only destination type network, range or ASBR are considered */
  if (route->type != OSPF6_DEST_TYPE_NETWORK &&
      route->type != OSPF6_DEST_TYPE_RANGE &&
      (route->type != OSPF6_DEST_TYPE_ROUTER ||
       ! CHECK_FLAG (route->path.router_bits, OSPF6_ROUTER_BIT_E)))
    {
      if (is_debug)
        zlog_debug ("Route type is none of network, range nor ASBR, withdraw");
      if (summary)
        ospf6_route_remove (summary, summary_table);
      if (old)
        ospf6_lsa_purge (old);
      return;
    }

  /* AS External routes are never considered */
  if (route->path.type == OSPF6_PATH_TYPE_EXTERNAL1 ||
      route->path.type == OSPF6_PATH_TYPE_EXTERNAL2)
    {
      if (is_debug)
        zlog_debug ("Path type is external, withdraw");
      if (summary)
        ospf6_route_remove (summary, summary_table);
      if (old)
        ospf6_lsa_purge (old);
      return;
    }

  /* do not generate if the path's area is the same as target area */
  if (route->path.area_id == area->area_id)
    {
      if (is_debug)
        zlog_debug ("The route is in the area itself, ignore");
      if (summary)
        ospf6_route_remove (summary, summary_table);
      if (old)
        ospf6_lsa_purge (old);
      return;
    }

  /* do not generate if the nexthops belongs to the target area */
  oi = ospf6_interface_lookup_by_ifindex (route->nexthop[0].ifindex);
  if (oi && oi->area && oi->area == area)
    {
      if (is_debug)
        zlog_debug ("The route's nexthop is in the same area, ignore");
      if (summary)
        ospf6_route_remove (summary, summary_table);
      if (old)
        ospf6_lsa_purge (old);
      return;
    }

  /* do not generate if the route cost is greater or equal to LSInfinity */
  if (route->path.cost >= OSPF_LS_INFINITY)
    {
      if (is_debug)
        zlog_debug ("The cost exceeds LSInfinity, withdraw");
      if (summary)
        ospf6_route_remove (summary, summary_table);
      if (old)
        ospf6_lsa_purge (old);
      return;
    }

  /* if this is a route to ASBR */
  if (route->type == OSPF6_DEST_TYPE_ROUTER)
    {
      /* Only the prefered best path is considered */
      if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_BEST))
        {
          if (is_debug)
            zlog_debug ("This is the secondary path to the ASBR, ignore");
          if (summary)
            ospf6_route_remove (summary, summary_table);
          if (old)
            ospf6_lsa_purge (old);
          return;
        }

      /* Do not generate if the area is stub */
      /* XXX */
    }

  /* if this is an intra-area route, this may be suppressed by aggregation */
  if (route->type == OSPF6_DEST_TYPE_NETWORK &&
      route->path.type == OSPF6_PATH_TYPE_INTRA)
    {
      /* search for configured address range for the route's area */
      route_area = ospf6_area_lookup (route->path.area_id, area->ospf6);
      assert (route_area);
      range = ospf6_route_lookup_bestmatch (&route->prefix,
                                            route_area->range_table);

      /* ranges are ignored when originate backbone routes to transit area.
         Otherwise, if ranges are configured, the route is suppressed. */
      if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) &&
          (route->path.area_id != OSPF_AREA_BACKBONE ||
           ! IS_AREA_TRANSIT (area)))
        {
          if (is_debug)
            {
              prefix2str (&range->prefix, buf, sizeof (buf));
              zlog_debug ("Suppressed by range %s of area %s",
                         buf, route_area->name);
            }

          if (summary)
            ospf6_route_remove (summary, summary_table);
          if (old)
            ospf6_lsa_purge (old);
          return;
        }
    }

  /* If this is a configured address range */
  if (route->type == OSPF6_DEST_TYPE_RANGE)
    {
      /* If DoNotAdvertise is set */
      if (CHECK_FLAG (route->flag, OSPF6_ROUTE_DO_NOT_ADVERTISE))
        {
          if (is_debug)
            zlog_debug ("This is the range with DoNotAdvertise set. ignore");
          if (summary)
            ospf6_route_remove (summary, summary_table);
          if (old)
            ospf6_lsa_purge (old);
          return;
        }

      /* Whether the route have active longer prefix */
      if (! CHECK_FLAG (route->flag, OSPF6_ROUTE_ACTIVE_SUMMARY))
        {
          if (is_debug)
            zlog_debug ("The range is not active. withdraw");
          if (summary)
            ospf6_route_remove (summary, summary_table);
          if (old)
            ospf6_lsa_purge (old);
          return;
        }
    }

  /* Check export list */
  if (EXPORT_NAME (area))
    {
      if (EXPORT_LIST (area) == NULL)
        EXPORT_LIST (area) =
          access_list_lookup (AFI_IP6, EXPORT_NAME (area));

      if (EXPORT_LIST (area))
        if (access_list_apply (EXPORT_LIST (area),
                               &route->prefix) == FILTER_DENY)
          {
            if (is_debug)
              {
                inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
                           buf, sizeof(buf));
                zlog_debug ("prefix %s was denied by export list", buf);
              }
            return;
          }
    }

  /* Check filter-list */
  if (PREFIX_NAME_OUT (area))
    {
      if (PREFIX_LIST_OUT (area) == NULL)
        PREFIX_LIST_OUT (area) =
          prefix_list_lookup(AFI_IP6, PREFIX_NAME_OUT (area));

      if (PREFIX_LIST_OUT (area))
         if (prefix_list_apply (PREFIX_LIST_OUT (area), 
                                &route->prefix) != PREFIX_PERMIT) 
           {
             if (is_debug)
               {
                 inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
                            buf, sizeof (buf));
                 zlog_debug ("prefix %s was denied by filter-list out", buf);
               }
             return;
           }
    }

  /* the route is going to be originated. store it in area's summary_table */
  if (summary == NULL)
    {
      summary = ospf6_route_copy (route);
      if (route->type == OSPF6_DEST_TYPE_NETWORK ||
          route->type == OSPF6_DEST_TYPE_RANGE)
        summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX);
      else
        summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_ROUTER);
      summary->path.origin.adv_router = area->ospf6->router_id;
      summary->path.origin.id =
        ospf6_new_ls_id (summary->path.origin.type,
                         summary->path.origin.adv_router, area->lsdb);
      summary = ospf6_route_add (summary, summary_table);
    }
  else
    {
      summary->type = route->type;
      quagga_gettime (QUAGGA_CLK_MONOTONIC, &summary->changed);
    }

  summary->path.router_bits = route->path.router_bits;
  summary->path.options[0] = route->path.options[0];
  summary->path.options[1] = route->path.options[1];
  summary->path.options[2] = route->path.options[2];
  summary->path.prefix_options = route->path.prefix_options;
  summary->path.area_id = area->area_id;
  summary->path.type = OSPF6_PATH_TYPE_INTER;
  summary->path.cost = route->path.cost;
  summary->nexthop[0] = route->nexthop[0];

  /* prepare buffer */
  memset (buffer, 0, sizeof (buffer));
  lsa_header = (struct ospf6_lsa_header *) buffer;

  if (route->type == OSPF6_DEST_TYPE_ROUTER)
    {
      router_lsa = (struct ospf6_inter_router_lsa *)
        ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
      p = (caddr_t) router_lsa + sizeof (struct ospf6_inter_router_lsa);

      /* Fill Inter-Area-Router-LSA */
      router_lsa->options[0] = route->path.options[0];
      router_lsa->options[1] = route->path.options[1];
      router_lsa->options[2] = route->path.options[2];
      OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost);
      router_lsa->router_id = ADV_ROUTER_IN_PREFIX (&route->prefix);
      type = htons (OSPF6_LSTYPE_INTER_ROUTER);
    }
  else
    {
      prefix_lsa = (struct ospf6_inter_prefix_lsa *)
        ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
      p = (caddr_t) prefix_lsa + sizeof (struct ospf6_inter_prefix_lsa);

      /* Fill Inter-Area-Prefix-LSA */
      OSPF6_ABR_SUMMARY_METRIC_SET (prefix_lsa, route->path.cost);
      prefix_lsa->prefix.prefix_length = route->prefix.prefixlen;
      prefix_lsa->prefix.prefix_options = route->path.prefix_options;

      /* set Prefix */
      memcpy (p, &route->prefix.u.prefix6,
              OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
      ospf6_prefix_apply_mask (&prefix_lsa->prefix);
      p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);
      type = htons (OSPF6_LSTYPE_INTER_PREFIX);
    }

  /* Fill LSA Header */
  lsa_header->age = 0;
  lsa_header->type = type;
  lsa_header->id = summary->path.origin.id;
  lsa_header->adv_router = area->ospf6->router_id;
  lsa_header->seqnum =
    ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
                         lsa_header->adv_router, area->lsdb);
  lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);

  /* LSA checksum */
  ospf6_lsa_checksum (lsa_header);

  /* create LSA */
  lsa = ospf6_lsa_create (lsa_header);

  /* Originate */
  ospf6_lsa_originate_area (lsa, area);
}
Exemple #26
0
/* AS External LSA origination */
static void
ospf6_as_external_lsa_originate (struct ospf6_route *route)
{
    char buffer[OSPF6_MAX_LSASIZE];
    struct ospf6_lsa_header *lsa_header;
    struct ospf6_lsa *old, *lsa;
    struct ospf6_external_info *info = route->route_option;

    struct ospf6_as_external_lsa *as_external_lsa;
    char buf[64];
    caddr_t p;

    /* find previous LSA */
    old = ospf6_lsdb_lookup (htons (OSPF6_LSTYPE_AS_EXTERNAL),
                             route->path.origin.id, ospf6->router_id,
                             ospf6->lsdb);

    if (IS_OSPF6_DEBUG_ASBR || IS_OSPF6_DEBUG_ORIGINATE (AS_EXTERNAL))
    {
        prefix2str (&route->prefix, buf, sizeof (buf));
        zlog_debug ("Originate AS-External-LSA for %s", buf);
    }

    /* prepare buffer */
    memset (buffer, 0, sizeof (buffer));
    lsa_header = (struct ospf6_lsa_header *) buffer;
    as_external_lsa = (struct ospf6_as_external_lsa *)
                      ((caddr_t) lsa_header + sizeof (struct ospf6_lsa_header));
    p = (caddr_t)
        ((caddr_t) as_external_lsa + sizeof (struct ospf6_as_external_lsa));

    /* Fill AS-External-LSA */
    /* Metric type */
    if (route->path.metric_type == 2)
        SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);
    else
        UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_E);

    /* forwarding address */
    if (! IN6_IS_ADDR_UNSPECIFIED (&info->forwarding))
        SET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);
    else
        UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F);

    /* external route tag */
    UNSET_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T);

    /* Set metric */
    OSPF6_ASBR_METRIC_SET (as_external_lsa, route->path.cost);

    /* prefixlen */
    as_external_lsa->prefix.prefix_length = route->prefix.prefixlen;

    /* PrefixOptions */
    as_external_lsa->prefix.prefix_options = route->path.prefix_options;

    /* don't use refer LS-type */
    as_external_lsa->prefix.prefix_refer_lstype = htons (0);

    /* set Prefix */
    memcpy (p, &route->prefix.u.prefix6,
            OSPF6_PREFIX_SPACE (route->prefix.prefixlen));
    ospf6_prefix_apply_mask (&as_external_lsa->prefix);
    p += OSPF6_PREFIX_SPACE (route->prefix.prefixlen);

    /* Forwarding address */
    if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_F))
    {
        memcpy (p, &info->forwarding, sizeof (struct in6_addr));
        p += sizeof (struct in6_addr);
    }

    /* External Route Tag */
    if (CHECK_FLAG (as_external_lsa->bits_metric, OSPF6_ASBR_BIT_T))
    {
        /* xxx */
    }

    /* Fill LSA Header */
    lsa_header->age = 0;
    lsa_header->type = htons (OSPF6_LSTYPE_AS_EXTERNAL);
    lsa_header->id = route->path.origin.id;
    lsa_header->adv_router = ospf6->router_id;
    lsa_header->seqnum =
        ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
                             lsa_header->adv_router, ospf6->lsdb);
    lsa_header->length = htons ((caddr_t) p - (caddr_t) lsa_header);

    /* LSA checksum */
    ospf6_lsa_checksum (lsa_header);

    /* create LSA */
    lsa = ospf6_lsa_create (lsa_header);

    /* Originate */
    ospf6_lsa_originate_process (lsa, ospf6);
}
Exemple #27
0
int bgp_peer_log_msg(struct bgp_node *route, struct bgp_info *ri, afi_t afi, safi_t safi, char *event_type, int output, int log_type)
{
  struct bgp_misc_structs *bms;
  char log_rk[SRVBUFLEN];
  struct bgp_peer *peer;
  struct bgp_attr *attr;
  int ret = 0, amqp_ret = 0, kafka_ret = 0, etype = BGP_LOGDUMP_ET_NONE;
  pid_t writer_pid = getpid();

  if (!ri || !ri->peer || !ri->peer->log || !event_type) return ERR;

  peer = ri->peer;
  attr = ri->attr;

  bms = bgp_select_misc_db(peer->type);
  if (!bms) return ERR;

  if (!strcmp(event_type, "dump")) etype = BGP_LOGDUMP_ET_DUMP;
  else if (!strcmp(event_type, "log")) etype = BGP_LOGDUMP_ET_LOG;

#ifdef WITH_RABBITMQ
  if ((bms->msglog_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) ||
      (bms->dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP))
    p_amqp_set_routing_key(peer->log->amqp_host, peer->log->filename);
#endif

#ifdef WITH_KAFKA
  if ((bms->msglog_kafka_topic && etype == BGP_LOGDUMP_ET_LOG) ||
      (bms->dump_kafka_topic && etype == BGP_LOGDUMP_ET_DUMP))
    p_kafka_set_topic(peer->log->kafka_host, peer->log->filename);
#endif

  if (output == PRINT_OUTPUT_JSON) {
#ifdef WITH_JANSSON
    char ip_address[INET6_ADDRSTRLEN];
    json_t *obj = json_object();

    char empty[] = "";
    char prefix_str[INET6_ADDRSTRLEN], nexthop_str[INET6_ADDRSTRLEN];
    char *aspath;

    /* no need for seq for "dump" event_type */
    if (etype == BGP_LOGDUMP_ET_LOG) {
      json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t)bms->log_seq));
      bgp_peer_log_seq_increment(&bms->log_seq);

      switch (log_type) {
      case BGP_LOG_TYPE_UPDATE:
	json_object_set_new_nocheck(obj, "log_type", json_string("update"));
	break;
      case BGP_LOG_TYPE_WITHDRAW:
	json_object_set_new_nocheck(obj, "log_type", json_string("withdraw"));
	break;
      case BGP_LOG_TYPE_DELETE:
	json_object_set_new_nocheck(obj, "log_type", json_string("delete"));
	break;
      default:
        json_object_set_new_nocheck(obj, "log_type", json_integer((json_int_t)log_type));
	break;
      }
    }

    if (etype == BGP_LOGDUMP_ET_LOG)
      json_object_set_new_nocheck(obj, "timestamp", json_string(bms->log_tstamp_str));
    else if (etype == BGP_LOGDUMP_ET_DUMP)
      json_object_set_new_nocheck(obj, "timestamp", json_string(bms->dump.tstamp_str));

    if (bms->bgp_peer_log_msg_extras) bms->bgp_peer_log_msg_extras(peer, output, obj);

    if (ri && ri->extra && ri->extra->bmed.id && bms->bgp_peer_logdump_extra_data)
      bms->bgp_peer_logdump_extra_data(&ri->extra->bmed, output, obj);

    addr_to_str(ip_address, &peer->addr);
    json_object_set_new_nocheck(obj, bms->peer_str, json_string(ip_address));

    json_object_set_new_nocheck(obj, "event_type", json_string(event_type));

    json_object_set_new_nocheck(obj, "afi", json_integer((json_int_t)afi));

    json_object_set_new_nocheck(obj, "safi", json_integer((json_int_t)safi));

    if (route) {
      memset(prefix_str, 0, INET6_ADDRSTRLEN);
      prefix2str(&route->p, prefix_str, INET6_ADDRSTRLEN);
      json_object_set_new_nocheck(obj, "ip_prefix", json_string(prefix_str));
    }

    if (ri && ri->extra && ri->extra->path_id)
      json_object_set_new_nocheck(obj, "as_path_id", json_integer((json_int_t)ri->extra->path_id));

    if (attr) {
      memset(nexthop_str, 0, INET6_ADDRSTRLEN);
      if (attr->mp_nexthop.family) addr_to_str(nexthop_str, &attr->mp_nexthop);
      else inet_ntop(AF_INET, &attr->nexthop, nexthop_str, INET6_ADDRSTRLEN);
      json_object_set_new_nocheck(obj, "bgp_nexthop", json_string(nexthop_str));

      aspath = attr->aspath ? attr->aspath->str : empty;
      json_object_set_new_nocheck(obj, "as_path", json_string(aspath));

      if (attr->community)
	json_object_set_new_nocheck(obj, "comms", json_string(attr->community->str));

      if (attr->ecommunity)
	json_object_set_new_nocheck(obj, "ecomms", json_string(attr->ecommunity->str));

      if (attr->lcommunity)
	json_object_set_new_nocheck(obj, "lcomms", json_string(attr->lcommunity->str));

      json_object_set_new_nocheck(obj, "origin", json_integer((json_int_t)attr->origin));

      json_object_set_new_nocheck(obj, "local_pref", json_integer((json_int_t)attr->local_pref));

      if (attr->med)
	json_object_set_new_nocheck(obj, "med", json_integer((json_int_t)attr->med));
    }

    if (safi == SAFI_MPLS_LABEL || safi == SAFI_MPLS_VPN) {
      u_char label_str[SHORTSHORTBUFLEN];

      if (safi == SAFI_MPLS_VPN) {
        u_char rd_str[SHORTSHORTBUFLEN];

        bgp_rd2str(rd_str, &ri->extra->rd);
	json_object_set_new_nocheck(obj, "rd", json_string(rd_str));
      }

      bgp_label2str(label_str, ri->extra->label);
      json_object_set_new_nocheck(obj, "label", json_string(label_str));
    }

    if ((bms->msglog_file && etype == BGP_LOGDUMP_ET_LOG) ||
	(bms->dump_file && etype == BGP_LOGDUMP_ET_DUMP))
      write_and_free_json(peer->log->fd, obj);

#ifdef WITH_RABBITMQ
    if ((bms->msglog_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) ||
	(bms->dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP)) {
      add_writer_name_and_pid_json(obj, config.proc_name, writer_pid);
      amqp_ret = write_and_free_json_amqp(peer->log->amqp_host, obj);
      p_amqp_unset_routing_key(peer->log->amqp_host);
    }
#endif

#ifdef WITH_KAFKA
    if ((bms->msglog_kafka_topic && etype == BGP_LOGDUMP_ET_LOG) ||
        (bms->dump_kafka_topic && etype == BGP_LOGDUMP_ET_DUMP)) {
      add_writer_name_and_pid_json(obj, config.proc_name, writer_pid);
      kafka_ret = write_and_free_json_kafka(peer->log->kafka_host, obj);
      p_kafka_unset_topic(peer->log->kafka_host);
    }
#endif
#endif
  }

  return (ret | amqp_ret | kafka_ret);
}