Example #1
0
int mpls_socket_udp_recvfrom(mpls_socket_mgr_handle handle,
  mpls_socket_handle socket, uint8_t * buffer, int size, mpls_dest * from)
{
  int ret;
  unsigned int ifindex = 0;
  struct iovec iov;
  struct cmsghdr *cmsg;
  struct in_pktinfo *pktinfo;
  struct sockaddr addr;
  char buff [sizeof (*cmsg) + sizeof (*pktinfo)];
  struct msghdr msgh = {&addr, sizeof(struct sockaddr), &iov, 1, buff,
                        sizeof (*cmsg) + sizeof (*pktinfo), 0};

  iov.iov_base = buffer;
  iov.iov_len = size;
  ret = recvmsg(socket->fd,&msgh,0);

  if (ret < 0 && errno != EAGAIN) {
    return 0;
  }

  cmsg = CMSG_FIRSTHDR(&msgh);

  if (cmsg != NULL &&
      cmsg->cmsg_level == IPPROTO_IP &&
      cmsg->cmsg_type == IP_PKTINFO) {
      pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
      ifindex = pktinfo->ipi_ifindex;
      from->if_handle = if_lookup_by_index(ifindex);
      _sockaddr2mpls_dest((const struct sockaddr*)&addr, from);
  }

  return ret;
}
Example #2
0
/* Interface adding function */
int
ifan_read (struct if_announcemsghdr *ifan)
{
  struct interface *ifp;

  ifp = if_lookup_by_index (ifan->ifan_index);
  if (ifp == NULL && ifan->ifan_what == IFAN_ARRIVAL)
    {
      /* Create Interface */
      ifp = if_get_by_name (ifan->ifan_name);
      ifp->ifindex = ifan->ifan_index;

      if_add_update (ifp);
    }
  else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE)
    {
      if_delete_update (ifp);
      if_delete (ifp);
    }

  if_get_flags (ifp);
  if_get_mtu (ifp);
  if_get_metric (ifp);

  if (IS_ZEBRA_DEBUG_KERNEL)
    zlog_info ("interface %s index %d", ifp->name, ifp->ifindex);

  return 0;
}
Example #3
0
const char * ifindex2ifname (unsigned int idx)
{
	struct interface *ifp;

	return ((ifp = if_lookup_by_index(idx)) != NULL) ?
		ifp->ifDescr : "unknown";
}
Example #4
0
const char *
ifindex2ifname (unsigned int index)
{
  struct interface_FOO *ifp;

  return ((ifp = if_lookup_by_index(index)) != NULL) ?
  	 ifp->name : "unknown";
}
Example #5
0
/* Interface's address information get. */
int
ifam_read (struct ifa_msghdr *ifam)
{
  struct interface *ifp;
  union sockunion addr, mask, gate;

  /* Check does this interface exist or not. */
  ifp = if_lookup_by_index (ifam->ifam_index);
  if (ifp == NULL) 
    {
      zlog_warn ("no interface for index %d", ifam->ifam_index); 
      return -1;
    }

  /* Allocate and read address information. */
  ifam_read_mesg (ifam, &addr, &mask, &gate);

  /* Check interface flag for implicit up of the interface. */
  if_refresh (ifp);

  /* Add connected address. */
  switch (sockunion_family (&addr))
    {
    case AF_INET:
      if (ifam->ifam_type == RTM_NEWADDR)
	connected_add_ipv4 (ifp, 0, &addr.sin.sin_addr, 
			    ip_masklen (mask.sin.sin_addr),
			    &gate.sin.sin_addr, NULL);
      else
	connected_delete_ipv4 (ifp, 0, &addr.sin.sin_addr, 
			       ip_masklen (mask.sin.sin_addr),
			       &gate.sin.sin_addr, NULL);
      break;
#ifdef HAVE_IPV6
    case AF_INET6:
      /* Unset interface index from link-local address when IPv6 stack
	 is KAME. */
      if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr))
	SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);

      if (ifam->ifam_type == RTM_NEWADDR)
	connected_add_ipv6 (ifp,
			    &addr.sin6.sin6_addr, 
			    ip6_masklen (mask.sin6.sin6_addr),
			    &gate.sin6.sin6_addr);
      else
	connected_delete_ipv6 (ifp,
			       &addr.sin6.sin6_addr, 
			       ip6_masklen (mask.sin6.sin6_addr),
			       &gate.sin6.sin6_addr);
      break;
#endif /* HAVE_IPV6 */
    default:
      /* Unsupported family silently ignore... */
      break;
    }
  return 0;
}
struct connected *
zebra_interface_address_read (int type, struct stream *s)
{
  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 (ifindex);
  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;
    }
  else
    {
      assert (type == ZEBRA_INTERFACE_ADDRESS_DELETE);
      ifc = connected_delete_by_prefix(ifp, &p);
    }

  return ifc;
}
Example #7
0
char *
if_indextoname (unsigned int ifindex, char *name)
{
  struct interface *ifp;

  if (!(ifp = if_lookup_by_index(ifindex)))
    return NULL;
  strncpy (name, ifp->ifDescr, IFNAMSIZ);
  return ifp->ifDescr;
}
Example #8
0
static void nhrp_interface_update_nbma(struct interface *ifp)
{
	struct nhrp_interface *nifp = ifp->info, *nbmanifp = NULL;
	struct interface *nbmaifp = NULL;
	union sockunion nbma;

	sockunion_family(&nbma) = AF_UNSPEC;

	if (nifp->source)
		nbmaifp = if_lookup_by_name(nifp->source);

	switch (ifp->ll_type) {
	case ZEBRA_LLT_IPGRE: {
			struct in_addr saddr = {0};
			netlink_gre_get_info(ifp->ifindex, &nifp->grekey, &nifp->linkidx, &saddr);
			debugf(NHRP_DEBUG_IF, "%s: GRE: %x %x %x", ifp->name, nifp->grekey, nifp->linkidx, saddr.s_addr);
			if (saddr.s_addr)
				sockunion_set(&nbma, AF_INET, (u_char *) &saddr.s_addr, sizeof(saddr.s_addr));
			else if (!nbmaifp && nifp->linkidx != IFINDEX_INTERNAL)
				nbmaifp = if_lookup_by_index(nifp->linkidx);
		}
		break;
	default:
		break;
	}

	if (nbmaifp)
		nbmanifp = nbmaifp->info;

	if (nbmaifp != nifp->nbmaifp) {
		if (nifp->nbmaifp)
			notifier_del(&nifp->nbmanifp_notifier);
		nifp->nbmaifp = nbmaifp;
		if (nbmaifp) {
			notifier_add(&nifp->nbmanifp_notifier, &nbmanifp->notifier_list, nhrp_interface_interface_notifier);
			debugf(NHRP_DEBUG_IF, "%s: bound to %s", ifp->name, nbmaifp->name);
		}
	}

	if (nbmaifp) {
		if (sockunion_family(&nbma) == AF_UNSPEC)
			nbma = nbmanifp->afi[AFI_IP].addr;
		nhrp_interface_update_mtu(ifp, AFI_IP);
		nhrp_interface_update_source(ifp);
	}

	if (!sockunion_same(&nbma, &nifp->nbma)) {
		nifp->nbma = nbma;
		nhrp_interface_update(nifp->ifp);
		debugf(NHRP_DEBUG_IF, "%s: NBMA address changed", ifp->name);
		notifier_call(&nifp->notifier_list, NOTIFY_INTERFACE_NBMA_CHANGED);
	}

	nhrp_interface_update(ifp);
}
Example #9
0
int
ifstat_update_sysctl ()
{
  caddr_t ref, buf, end;
  size_t bufsiz;
  struct if_msghdr *ifm;
  struct interface *ifp;

#define MIBSIZ 6
  int mib[MIBSIZ] =
  { 
    CTL_NET,
    PF_ROUTE,
    0,
    0, /*  AF_INET & AF_INET6 */
    NET_RT_IFLIST,
    0 
  };

  /* Query buffer size. */
  if (sysctl (mib, MIBSIZ, NULL, &bufsiz, NULL, 0) < 0) 
    {
      zlog_warn ("sysctl() error by %s", strerror (errno));
      return -1;
    }

  /* We free this memory at the end of this function. */
  ref = buf = XMALLOC (MTYPE_TMP, bufsiz);

  /* Fetch interface informations into allocated buffer. */
  if (sysctl (mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) 
    {
      zlog (NULL, LOG_WARNING, "sysctl error by %s", strerror (errno));
      return -1;
    }

  /* Parse both interfaces and addresses. */
  for (end = buf + bufsiz; buf < end; buf += ifm->ifm_msglen) 
    {
      ifm = (struct if_msghdr *) buf;
      if (ifm->ifm_type == RTM_IFINFO)
	{
	  ifp = if_lookup_by_index (ifm->ifm_index);
	  if (ifp)
	    ifp->stats = ifm->ifm_data;
	}
    }

  /* Free sysctl buffer. */
  XFREE (MTYPE_TMP, ref);

  return 0;
}
Example #10
0
struct ospf6_interface *
ospf6_interface_lookup_by_ifindex (int ifindex)
{
  struct ospf6_interface *oi;
  struct interface *ifp;

  ifp = if_lookup_by_index (ifindex);
  if (ifp == NULL)
    return (struct ospf6_interface *) NULL;

  oi = (struct ospf6_interface *) ifp->info;
  return oi;
}
Example #11
0
int irdp_read_raw(struct thread *r)
{
	struct interface *ifp;
	struct zebra_if *zi;
	struct irdp_interface *irdp;
	char buf[IRDP_RX_BUF];
	int ret, ifindex = 0;

	int irdp_sock = THREAD_FD(r);
	t_irdp_raw =
	    thread_add_read(zebrad.master, irdp_read_raw, NULL, irdp_sock);

	ret = irdp_recvmsg(irdp_sock, (u_char *) buf, IRDP_RX_BUF, &ifindex);

	if (ret < 0)
		zlog_warn("IRDP: RX Error length = %d", ret);

	ifp = if_lookup_by_index(ifindex);
	if (!ifp)
		return ret;

	zi = ifp->info;
	if (!zi)
		return ret;

	irdp = &zi->irdp;
	if (!irdp)
		return ret;

	if (!(irdp->flags & IF_ACTIVE)) {

		if (irdp->flags & IF_DEBUG_MISC)
			zlog_debug("IRDP: RX ICMP for disabled interface %s\n",
				   ifp->name);
		return 0;
	}

	if (irdp->flags & IF_DEBUG_PACKET) {
		int i;
		zlog_debug("IRDP: RX (idx %d) ", ifindex);
		for (i = 0; i < ret; i++)
			zlog_debug("IRDP: RX %x ", buf[i] & 0xFF);
	}

	parse_irdp_packet(buf, ret, ifp);

	return ret;
}
Example #12
0
/* Allocate a new internal interface index 
 * This works done from the top so that %d macros
 * print a - sign! 
 */
static unsigned int
if_new_intern_ifindex (void)
{
  /* Start here so that first one assigned is 0xFFFFFFFF */
  static unsigned int ifindex = IFINDEX_INTERNBASE + 1;

  for (;;) 
    {
      ifindex--;
      if ( ifindex <= IFINDEX_INTERNBASE )
       ifindex = 0xFFFFFFFF;

      if (if_lookup_by_index(ifindex) == NULL)
       return ifindex;
    }
}
Example #13
0
int if_address_add_v6(struct ctrl_client * ctrl_client, struct rfpbuf * buffer)
{
  const struct rfp_ipv6_address * address = buffer->data;
  struct interface * ifp = if_lookup_by_index(ctrl_client->if_list, address->ifindex);
  struct connected * ifc;

  struct prefix p;

  memcpy(&p.u.prefix, &address->p, 16);
  p.prefixlen = address->prefixlen;
  p.family = AF_INET6;

  ifc = connected_add_by_prefix(ifp, &p, NULL);
  if(ifc == NULL)
    return 1;

  if(IS_OSPF6_SIBLING_DEBUG_MSG)
  {
    char prefix_str[INET6_ADDRSTRLEN+3]; // three extra chars for slash + two digits
    if(prefix2str(ifc->address, prefix_str, INET6_ADDRSTRLEN) != 1)
    {   
      zlog_debug("v6 addr: %s", prefix_str, ifc->address->prefixlen);
    }   
  }

//  check here for:
//    1. prefix matches
//    2. extract hostnum from host portion of address
//    3. if hostnum matches, this is the internal interface that should be recorded

  char inter_target_str[INET6_ADDRSTRLEN+3]; // three extra chars for slash + two digits
  struct prefix inter_target_p;

  sprintf(inter_target_str, "2001:db8:beef:10::%x/64", ctrl_client->hostnum);
  str2prefix(inter_target_str, &inter_target_p);
  
  // link up the internal connected address with a pointer at ctrl_client
  if(prefix_same(ifc->address, &inter_target_p))
  {
    ctrl_client->inter_con = ifc;
  }
  
  // since connected address is AF_INET6, needs to be updated
  ospf6_interface_connected_route_update(ifc->ifp);

  return 0;
}
Example #14
0
int nhrp_route_read(ZAPI_CALLBACK_ARGS)
{
	struct zapi_route api;
	struct zapi_nexthop *api_nh;
	struct interface *ifp = NULL;
	union sockunion nexthop_addr;
	char buf[2][PREFIX_STRLEN];
	int added;

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

	/* we completely ignore srcdest routes for now. */
	if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
		return 0;

	sockunion_family(&nexthop_addr) = AF_UNSPEC;
	if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
		api_nh = &api.nexthops[0];

		nexthop_addr.sa.sa_family = api.prefix.family;
		switch (nexthop_addr.sa.sa_family) {
		case AF_INET:
			nexthop_addr.sin.sin_addr = api_nh->gate.ipv4;
			break;
		case AF_INET6:
			nexthop_addr.sin6.sin6_addr = api_nh->gate.ipv6;
			break;
		}

		if (api_nh->ifindex != IFINDEX_INTERNAL)
			ifp = if_lookup_by_index(api_nh->ifindex, VRF_DEFAULT);
	}

	added = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
	debugf(NHRP_DEBUG_ROUTE, "if-route-%s: %s via %s dev %s",
	       added ? "add" : "del",
	       prefix2str(&api.prefix, buf[0], sizeof buf[0]),
	       sockunion2str(&nexthop_addr, buf[1], sizeof buf[1]),
	       ifp ? ifp->name : "(none)");

	nhrp_route_update_zebra(&api.prefix, &nexthop_addr, ifp);
	nhrp_shortcut_prefix_change(&api.prefix, !added);

	return 0;
}
Example #15
0
/* Interface adding function */
static int
ifan_read (struct if_announcemsghdr *ifan)
{
  struct interface *ifp;
  
  ifp = if_lookup_by_index (ifan->ifan_index);
  
  if (ifp)
    assert ( (ifp->ifindex == ifan->ifan_index) 
             || (ifp->ifindex == IFINDEX_INTERNAL) );

  if ( (ifp == NULL) 
      || ((ifp->ifindex == IFINDEX_INTERNAL)
          && (ifan->ifan_what == IFAN_ARRIVAL)) )
    {
      if (IS_ZEBRA_DEBUG_KERNEL)
        zlog_debug ("%s: creating interface for ifindex %d, name %s",
                    __func__, ifan->ifan_index, ifan->ifan_name);
      
      /* Create Interface */
      ifp = if_get_by_name_len(ifan->ifan_name,
			       strnlen(ifan->ifan_name,
				       sizeof(ifan->ifan_name)));
      ifp->ifindex = ifan->ifan_index;

      if_add_update (ifp);
    }
  else if (ifp != NULL && ifan->ifan_what == IFAN_DEPARTURE)
    if_delete_update (ifp);

  if_get_flags (ifp);
  if_get_mtu (ifp);
  if_get_metric (ifp);

  if (IS_ZEBRA_DEBUG_KERNEL)
    zlog_debug ("%s: interface %s index %d", 
                __func__, ifan->ifan_name, ifan->ifan_index);

  return 0;
}
Example #16
0
int if_address_add_v4(struct ctrl_client * ctrl_client, struct rfpbuf * buffer)
{
  const struct rfp_ipv4_address * address = buffer->data;
  struct interface * ifp = if_lookup_by_index(ctrl_client->if_list, address->ifindex);
  struct connected * ifc;

  struct prefix p;

  memcpy(&p.u.prefix, &address->p, 4);
  p.prefixlen = address->prefixlen;
  p.family = AF_INET;

  ifc = connected_add_by_prefix(ifp, &p, NULL);
  if(ifc == NULL)
    return 1;

//  struct connected * ifc = calloc(1, sizeof(struct connected));
//  ifc->address = calloc(1, sizeof(struct prefix));
//  memcpy(&ifc->address->u.prefix, &address->p, 4); 
//  ifc->address->prefixlen = address->prefixlen;
//  ifc->address->family = AF_INET;

//  list_init(&ifc->node);

  if(IS_OSPF6_SIBLING_DEBUG_MSG)
  {
    char prefix_str[INET_ADDRSTRLEN];
    if(inet_ntop(AF_INET, &(p.u.prefix4.s_addr), prefix_str, INET_ADDRSTRLEN) != 1)
    {   
      zlog_debug("v4 addr: %s/%d", prefix_str, ifc->address->prefixlen);
    }   
  }

  // add addresss to list of connected 
//  list_push_back(&ifp->connected, &ifc->node);
//  ifc->ifp = ifp;

  return 0;
}
Example #17
0
struct interface *
zebra_interface_link_params_read (struct stream *s)
{
  struct if_link_params *iflp;
  uint32_t ifindex = stream_getl (s);

  struct interface *ifp = if_lookup_by_index (ifindex);

  if (ifp == NULL || s == NULL)
    {
      zlog_err ("%s: unknown ifindex %u, shouldn't happen",
                __func__, ifindex);
      return NULL;
    }

  if ((iflp = if_link_params_get (ifp)) == NULL)
    return NULL;

  link_params_set_value(s, iflp);
  
  return ifp;
}
Example #18
0
/* Lookup interface by interface's IP address or interface index. */
static struct interface *
ifaddr_ipv4_lookup (struct in_addr *addr, unsigned int ifindex)
{
  struct prefix_ipv4 p;
  struct route_node *rn;
  struct interface *ifp;

  if (addr)
    {
      p.family = AF_INET;
      p.prefixlen = IPV4_MAX_PREFIXLEN;
      p.prefix = *addr;

      rn = route_node_lookup (ifaddr_ipv4_table, (struct prefix *) &p);
      if (! rn)
	return NULL;
      
      ifp = rn->info;
      route_unlock_node (rn);
      return ifp;
    }
  else
    return if_lookup_by_index(ifindex);
}
Example #19
0
/*
 * Search the network interface and gateway address to forward the packet.
 * Return also the IP adress of the interface,
 */
if_t *route_lookup (uint32_t ip)
{
	struct rib * rib_new;
	struct in_addr addr;
	if_t   *outif = NULL;
	
	addr.s_addr = ip;

	rib_new = rib_match_ipv4 (addr);

	if (!rib_new) {
		/*Temp Fix*/
		if ((ip & 0x000007f) == 0x7f)
			return get_loopback_if ();
		return NULL;
	}

	outif = if_lookup_by_index (rib_new->nexthop->ifindex);

	if ((outif->ip_addr.addr == ip) || ((ip & 0x000007f) == 0x7f)) {
		outif = get_loopback_if ();
	}
	return outif;
}
Example #20
0
/* Note: on netlink systems, there should be a 1-to-1 mapping between interface
   names and ifindex values. */
static void
set_ifindex(struct interface *ifp, unsigned int ifi_index)
{
  struct interface *oifp;

  if (((oifp = if_lookup_by_index(ifi_index)) != NULL) && (oifp != ifp))
    {
      if (ifi_index == IFINDEX_INTERNAL)
        zlog_err("Netlink is setting interface %s ifindex to reserved "
		 "internal value %u", ifp->name, ifi_index);
      else
        {
	  if (IS_DEBUG_HA(kroute, KROUTE))
	    zlog_debug("interface index %d was renamed from %s to %s",
	    	       ifi_index, oifp->name, ifp->name);
	  if (if_is_up(oifp))
	    zlog_err("interface rename detected on up interface: index %d "
		     "was renamed from %s to %s, results are uncertain!", 
	    	     ifi_index, oifp->name, ifp->name);
	  if_delete_update(oifp);
        }
    }
  ifp->ifindex = ifi_index;
}
Example #21
0
/* Interface adding function called from interface_list. */
int
ifm_read (struct if_msghdr *ifm)
{
  struct interface *ifp;
  struct sockaddr_dl *sdl = NULL;

  sdl = (struct sockaddr_dl *)(ifm + 1);

  /* Use sdl index. */
  ifp = if_lookup_by_index (ifm->ifm_index);

  if (ifp == NULL)
    {
      /* Check interface's address.*/
      if (! (ifm->ifm_addrs & RTA_IFP))
	{
	  zlog_warn ("There must be RTA_IFP address for ifindex %d\n",
		     ifm->ifm_index);
	  return -1;
	}

      ifp = if_create ();

      strncpy (ifp->name, sdl->sdl_data, sdl->sdl_nlen);
      ifp->ifindex = ifm->ifm_index;
      ifp->flags = ifm->ifm_flags;
#if defined(__bsdi__)
      if_kvm_get_mtu (ifp);
#else
      if_get_mtu (ifp);
#endif /* __bsdi__ */
      if_get_metric (ifp);

      /* Fetch hardware address. */
      if (sdl->sdl_family != AF_LINK)
	{
	  zlog_warn ("sockaddr_dl->sdl_family is not AF_LINK");
	  return -1;
	}
      memcpy (&ifp->sdl, sdl, sizeof (struct sockaddr_dl));

      if_add_update (ifp);
    }
  else
    {
      /* There is a case of promisc, allmulti flag modification. */
      if (if_is_up (ifp))
	{
	  ifp->flags = ifm->ifm_flags;
	  if (! if_is_up (ifp))
	    if_down (ifp);
	}
      else
	{
	  ifp->flags = ifm->ifm_flags;
	  if (if_is_up (ifp))
	    if_up (ifp);
	}
    }
  
#ifdef HAVE_NET_RT_IFLIST
  ifp->stats = ifm->ifm_data;
#endif /* HAVE_NET_RT_IFLIST */

  if (IS_ZEBRA_DEBUG_KERNEL)
    zlog_info ("interface %s index %d", ifp->name, ifp->ifindex);

  return 0;
}
Example #22
0
static int ldp_zebra_read_ipv4(int cmd, struct zclient *client,
  zebra_size_t length) {
  struct prefix_ipv4 prefix;
  struct zapi_ipv4 api;
  int i = 0;
  int j;

  struct mpls_nexthop nexthop[8];
  struct ldp *ldp = ldp_get();
  struct mpls_fec fec;
  struct stream *s;
  struct in_addr tmp;

  memset(&api,0,sizeof(api));
  memset(nexthop,0,sizeof(nexthop));

  s = client->ibuf;
  zapi_ipv4_read (s, length, &api, &prefix);

  zlog_info("route %s/%d", inet_ntoa(prefix.prefix), prefix.prefixlen);

  if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
    {
      for (i = 0; i < api.nexthop_num; i++)
        {
          if (api.type == ZEBRA_ROUTE_CONNECT)
            {
	      nexthop[i].attached = MPLS_BOOL_TRUE;
	      zlog_info("\tattached");
            }
          nexthop[i].ip.type = MPLS_FAMILY_IPV4;
          if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
            nexthop[i].distance = api.message;
          if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC))
            nexthop[i].metric = api.metric;
          if (CHECK_FLAG (api.nexthop[i].type, ZEBRA_NEXTHOP_IPV4))
            {
              nexthop[i].ip.u.ipv4 = ntohl(api.nexthop[i].gw.ipv4.s_addr);
              nexthop[i].type |= MPLS_NH_IP;
              tmp.s_addr = htonl(nexthop[i].ip.u.ipv4);
              zlog_info("\tnexthop %s", inet_ntoa(tmp));
            }
          if (CHECK_FLAG (api.nexthop[i].type, ZEBRA_NEXTHOP_IFINDEX))
            {
              nexthop[i].if_handle =
                  if_lookup_by_index(api.nexthop[i].intf.index);
              if (nexthop[i].if_handle)
                {
	          nexthop[i].type |= MPLS_NH_IF;
	          zlog_info("\tifindex %d", nexthop[i].if_handle->ifindex);
                }
            }
        }
    }

  zebra_prefix2mpls_fec((struct prefix*)&prefix, &fec);
  for (j = 0; j < i; j++) {
    if (cmd == ZEBRA_IPV4_ROUTE_ADD) {
      zlog_info("\tadd");
      if ((ldp_cfg_fec_get(ldp->h, &fec, 0) != MPLS_SUCCESS) ||
	  (fec.is_route == MPLS_BOOL_FALSE)) {
        if (ldp_cfg_fec_set(ldp->h, &fec, LDP_CFG_ADD) != MPLS_SUCCESS) {
          MPLS_ASSERT(0);
        }
      }
      if (ldp_cfg_fec_nexthop_get(ldp->h, &fec, &nexthop[j],
        LDP_FEC_CFG_BY_INDEX) != MPLS_SUCCESS) {
        if (ldp_cfg_fec_nexthop_set(ldp->h, &fec, &nexthop[j],
          LDP_CFG_ADD|LDP_FEC_CFG_BY_INDEX) != MPLS_SUCCESS) {
          MPLS_ASSERT(0);
        }
      } else {
	/*
	 * already exists ... looks like we can get the same route sent
	 * to us twice ... multiple protocols?
        MPLS_ASSERT(0);
	 */
      }
    } else {
      zlog_info("\tdelete");
      if ((ldp_cfg_fec_get(ldp->h, &fec, 0) == MPLS_SUCCESS) &&
	  (fec.is_route == MPLS_BOOL_TRUE)) {
        if (ldp_cfg_fec_nexthop_get(ldp->h, &fec, &nexthop[j],
          LDP_FEC_CFG_BY_INDEX) == MPLS_SUCCESS) {
          if (ldp_cfg_fec_nexthop_set(ldp->h, &fec, &nexthop[j],
            LDP_FEC_CFG_BY_INDEX|LDP_CFG_DEL|
            LDP_FEC_NEXTHOP_CFG_BY_INDEX) != MPLS_SUCCESS) {
            MPLS_ASSERT(0);
          }
        } else {
          MPLS_ASSERT(0);
        }
        if (ldp_cfg_fec_set(ldp->h, &fec, LDP_CFG_DEL|LDP_FEC_CFG_BY_INDEX) !=
          MPLS_SUCCESS) {
          MPLS_ASSERT(0);
        }
      } else {
        MPLS_ASSERT(0);
      }
    }
  }
  return 0;
}
Example #23
0
/* Interface function for the kernel routing table updates.  Support
 * for RTM_CHANGE will be needed.
 * Exported only for rt_socket.c
 */
int
rtm_write (int message,
	   union sockunion *dest,
	   union sockunion *mask,
	   union sockunion *gate,
	   unsigned int index,
	   int zebra_flags,
	   int metric)
{
  int ret;
  caddr_t pnt;
  struct interface *ifp;

  /* Sequencial number of routing message. */
  static int msg_seq = 0;

  /* Struct of rt_msghdr and buffer for storing socket's data. */
  struct 
  {
    struct rt_msghdr rtm;
    char buf[512];
  } msg;
  
  if (routing_sock < 0)
    return ZEBRA_ERR_EPERM;

  /* Clear and set rt_msghdr values */
  memset (&msg, 0, sizeof (struct rt_msghdr));
  msg.rtm.rtm_version = RTM_VERSION;
  msg.rtm.rtm_type = message;
  msg.rtm.rtm_seq = msg_seq++;
  msg.rtm.rtm_addrs = RTA_DST;
  msg.rtm.rtm_addrs |= RTA_GATEWAY;
  msg.rtm.rtm_flags = RTF_UP;
  msg.rtm.rtm_index = index;

  if (metric != 0)
    {
      msg.rtm.rtm_rmx.rmx_hopcount = metric;
      msg.rtm.rtm_inits |= RTV_HOPCOUNT;
    }

  ifp = if_lookup_by_index (index);

  if (gate && message == RTM_ADD)
    msg.rtm.rtm_flags |= RTF_GATEWAY;

  /* When RTF_CLONING is unavailable on BSD, should we set some
   * other flag instead?
   */
#ifdef RTF_CLONING
  if (! gate && message == RTM_ADD && ifp &&
      (ifp->flags & IFF_POINTOPOINT) == 0)
    msg.rtm.rtm_flags |= RTF_CLONING;
#endif /* RTF_CLONING */

  /* If no protocol specific gateway is specified, use link
     address for gateway. */
  if (! gate)
    {
      if (!ifp)
        {
          char dest_buf[INET_ADDRSTRLEN] = "NULL", mask_buf[INET_ADDRSTRLEN] = "255.255.255.255";
          if (dest)
            inet_ntop (AF_INET, &dest->sin.sin_addr, dest_buf, INET_ADDRSTRLEN);
          if (mask)
            inet_ntop (AF_INET, &mask->sin.sin_addr, mask_buf, INET_ADDRSTRLEN);
          zlog_warn ("%s: %s/%s: gate == NULL and no gateway found for ifindex %d",
            __func__, dest_buf, mask_buf, index);
          return -1;
        }
      gate = (union sockunion *) & ifp->sdl;
    }

  if (mask)
    msg.rtm.rtm_addrs |= RTA_NETMASK;
  else if (message == RTM_ADD) 
    msg.rtm.rtm_flags |= RTF_HOST;

  /* Tagging route with flags */
  msg.rtm.rtm_flags |= (RTF_PROTO1);

  /* Additional flags. */
  if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
    msg.rtm.rtm_flags |= RTF_BLACKHOLE;
  if (zebra_flags & ZEBRA_FLAG_REJECT)
    msg.rtm.rtm_flags |= RTF_REJECT;


#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
#define SOCKADDRSET(X,R) \
  if (msg.rtm.rtm_addrs & (R)) \
    { \
      int len = ROUNDUP ((X)->sa.sa_len); \
      memcpy (pnt, (caddr_t)(X), len); \
      pnt += len; \
    }
#else 
#define SOCKADDRSET(X,R) \
  if (msg.rtm.rtm_addrs & (R)) \
    { \
      int len = SAROUNDUP (X); \
      memcpy (pnt, (caddr_t)(X), len); \
      pnt += len; \
    }
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */

  pnt = (caddr_t) msg.buf;

  /* Write each socket data into rtm message buffer */
  SOCKADDRSET (dest, RTA_DST);
  SOCKADDRSET (gate, RTA_GATEWAY);
  SOCKADDRSET (mask, RTA_NETMASK);

  msg.rtm.rtm_msglen = pnt - (caddr_t) &msg;

  ret = write (routing_sock, &msg, msg.rtm.rtm_msglen);

  if (ret != msg.rtm.rtm_msglen) 
    {
      if (errno == EEXIST) 
	return ZEBRA_ERR_RTEXIST;
      if (errno == ENETUNREACH)
	return ZEBRA_ERR_RTUNREACH;
      if (errno == ESRCH)
	return ZEBRA_ERR_RTNOEXIST;
      
      zlog_warn ("%s: write : %s (%d)", __func__, safe_strerror (errno), errno);
      return ZEBRA_ERR_KERNEL;
    }
  return ZEBRA_ERR_NOERROR;
}
Example #24
0
/* Interface's address information get. */
int
ifam_read (struct ifa_msghdr *ifam)
{
  struct interface *ifp = NULL;
  union sockunion addr, mask, brd;
  char ifname[INTERFACE_NAMSIZ];
  short ifnlen = 0;
  char isalias = 0;
  int flags = 0;
  
  ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0';
  
  /* Allocate and read address information. */
  ifam_read_mesg (ifam, &addr, &mask, &brd, ifname, &ifnlen);
  
  if ((ifp = if_lookup_by_index(ifam->ifam_index)) == NULL)
    {
      zlog_warn ("%s: no interface for ifname %s, index %d", 
                 __func__, ifname, ifam->ifam_index);
      return -1;
    }
  
  if (ifnlen && strncmp (ifp->name, ifname, INTERFACE_NAMSIZ))
    isalias = 1;
  
  /* N.B. The info in ifa_msghdr does not tell us whether the RTA_BRD
     field contains a broadcast address or a peer address, so we are forced to
     rely upon the interface type. */
  if (if_is_pointopoint(ifp))
    SET_FLAG(flags, ZEBRA_IFA_PEER);

#if 0
  /* it might seem cute to grab the interface metric here, however
   * we're processing an address update message, and so some systems
   * (e.g. FBSD) dont bother to fill in ifam_metric. Disabled, but left
   * in deliberately, as comment.
   */
  ifp->metric = ifam->ifam_metric;
#endif

  /* Add connected address. */
  switch (sockunion_family (&addr))
    {
    case AF_INET:
      if (ifam->ifam_type == RTM_NEWADDR)
	connected_add_ipv4 (ifp, flags, &addr.sin.sin_addr, 
			    ip_masklen (mask.sin.sin_addr),
			    &brd.sin.sin_addr,
			    (isalias ? ifname : NULL));
      else
	connected_delete_ipv4 (ifp, flags, &addr.sin.sin_addr, 
			       ip_masklen (mask.sin.sin_addr),
			       &brd.sin.sin_addr);
      break;
#ifdef HAVE_IPV6
    case AF_INET6:
      /* Unset interface index from link-local address when IPv6 stack
	 is KAME. */
      if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr))
	SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);

      if (ifam->ifam_type == RTM_NEWADDR)
	connected_add_ipv6 (ifp, flags, &addr.sin6.sin6_addr, 
			    ip6_masklen (mask.sin6.sin6_addr),
			    &brd.sin6.sin6_addr,
			    (isalias ? ifname : NULL));
      else
	connected_delete_ipv6 (ifp,
			       &addr.sin6.sin6_addr, 
			       ip6_masklen (mask.sin6.sin6_addr),
			       &brd.sin6.sin6_addr);
      break;
#endif /* HAVE_IPV6 */
    default:
      /* Unsupported family silently ignore... */
      break;
    }
  
  /* Check interface flag for implicit up of the interface. */
  if_refresh (ifp);

#ifdef SUNOS_5
  /* In addition to lacking IFANNOUNCE, on SUNOS IFF_UP is strange. 
   * See comments for SUNOS_5 in interface.c::if_flags_mangle.
   * 
   * Here we take care of case where the real IFF_UP was previously
   * unset (as kept in struct zebra_if.primary_state) and the mangled
   * IFF_UP (ie IFF_UP set || listcount(connected) has now transitioned
   * to unset due to the lost non-primary address having DELADDR'd.
   *
   * we must delete the interface, because in between here and next
   * event for this interface-name the administrator could unplumb
   * and replumb the interface.
   */
  if (!if_is_up (ifp))
    if_delete_update (ifp);
#endif /* SUNOS_5 */
  
  return 0;
}
Example #25
0
/*
 * Handle struct if_msghdr obtained from reading routing socket or
 * sysctl (from interface_list).  There may or may not be sockaddrs
 * present after the header.
 */
int
ifm_read (struct if_msghdr *ifm)
{
  struct interface *ifp = NULL;
  char ifname[IFNAMSIZ];
  short ifnlen = 0;
  caddr_t *cp;
  
  /* terminate ifname at head (for strnlen) and tail (for safety) */
  ifname[IFNAMSIZ - 1] = '\0';
  
  /* paranoia: sanity check structure */
  if (ifm->ifm_msglen < sizeof(struct if_msghdr))
    {
      zlog_err ("ifm_read: ifm->ifm_msglen %d too short\n",
		ifm->ifm_msglen);
      return -1;
    }

  /*
   * Check for a sockaddr_dl following the message.  First, point to
   * where a socakddr might be if one follows the message.
   */
  cp = (void *)(ifm + 1);

#ifdef SUNOS_5
  /* 
   * XXX This behavior should be narrowed to only the kernel versions
   * for which the structures returned do not match the headers.
   *
   * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions
   * is 12 bytes larger than the 32 bit version.
   */
  if (((struct sockaddr *) cp)->sa_family == AF_UNSPEC)
  	cp = cp + 12;
#endif

  RTA_ADDR_GET (NULL, RTA_DST, ifm->ifm_addrs, cp);
  RTA_ADDR_GET (NULL, RTA_GATEWAY, ifm->ifm_addrs, cp);
  RTA_ATTR_GET (NULL, RTA_NETMASK, ifm->ifm_addrs, cp);
  RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifm_addrs, cp);
  RTA_NAME_GET (ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen);
  RTA_ADDR_GET (NULL, RTA_IFA, ifm->ifm_addrs, cp);
  RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifm_addrs, cp);
  RTA_ADDR_GET (NULL, RTA_BRD, ifm->ifm_addrs, cp);
  
  if (IS_ZEBRA_DEBUG_KERNEL)
    zlog_debug ("%s: sdl ifname %s", __func__, (ifnlen ? ifname : "(nil)"));
  
  /* 
   * Look up on ifindex first, because ifindices are the primary handle for
   * interfaces across the user/kernel boundary, for most systems.  (Some
   * messages, such as up/down status changes on NetBSD, do not include a
   * sockaddr_dl).
   */
  if ( (ifp = if_lookup_by_index (ifm->ifm_index)) != NULL )
    {
      /* we have an ifp, verify that the name matches as some systems,
       * eg Solaris, have a 1:many association of ifindex:ifname
       * if they dont match, we dont have the correct ifp and should
       * set it back to NULL to let next check do lookup by name
       */
      if (ifnlen && (strncmp (ifp->name, ifname, IFNAMSIZ) != 0) )
        {
          if (IS_ZEBRA_DEBUG_KERNEL)
            zlog_debug ("%s: ifp name %s doesnt match sdl name %s",
                        __func__, ifp->name, ifname);
          ifp = NULL;
        }
    }
  
  /* 
   * If we dont have an ifp, try looking up by name.  Particularly as some
   * systems (Solaris) have a 1:many mapping of ifindex:ifname - the ifname
   * is therefore our unique handle to that interface.
   *
   * Interfaces specified in the configuration file for which the ifindex
   * has not been determined will have ifindex == IFINDEX_INTERNAL, and such
   * interfaces are found by this search, and then their ifindex values can
   * be filled in.
   */
  if ( (ifp == NULL) && ifnlen)
    ifp = if_lookup_by_name (ifname);

  /*
   * If ifp still does not exist or has an invalid index (IFINDEX_INTERNAL),
   * create or fill in an interface.
   */
  if ((ifp == NULL) || (ifp->ifindex == IFINDEX_INTERNAL))
    {
      /*
       * To create or fill in an interface, a sockaddr_dl (via
       * RTA_IFP) is required.
       */
      if (!ifnlen)
	{
	  zlog_warn ("Interface index %d (new) missing ifname\n",
		     ifm->ifm_index);
	  return -1;
	}

#ifndef RTM_IFANNOUNCE
      /* Down->Down interface should be ignored here.
       * See further comment below.
       */
      if (!CHECK_FLAG (ifm->ifm_flags, IFF_UP))
        return 0;
#endif /* !RTM_IFANNOUNCE */
      
      if (ifp == NULL)
        {
	  /* Interface that zebra was not previously aware of, so create. */ 
	  ifp = if_create (ifname, ifnlen);
	  if (IS_ZEBRA_DEBUG_KERNEL)
	    zlog_debug ("%s: creating ifp for ifindex %d", 
	                __func__, ifm->ifm_index);
        }

      if (IS_ZEBRA_DEBUG_KERNEL)
        zlog_debug ("%s: updated/created ifp, ifname %s, ifindex %d",
                    __func__, ifp->name, ifp->ifindex);
      /* 
       * Fill in newly created interface structure, or larval
       * structure with ifindex IFINDEX_INTERNAL.
       */
      ifp->ifindex = ifm->ifm_index;
      
#ifdef HAVE_BSD_LINK_DETECT /* translate BSD kernel msg for link-state */
      bsd_linkdetect_translate(ifm);
#endif /* HAVE_BSD_LINK_DETECT */

      if_flags_update (ifp, ifm->ifm_flags);
#if defined(__bsdi__)
      if_kvm_get_mtu (ifp);
#else
      if_get_mtu (ifp);
#endif /* __bsdi__ */
      if_get_metric (ifp);

      if_add_update (ifp);
    }
  else
    /*
     * Interface structure exists.  Adjust stored flags from
     * notification.  If interface has up->down or down->up
     * transition, call state change routines (to adjust routes,
     * notify routing daemons, etc.).  (Other flag changes are stored
     * but apparently do not trigger action.)
     */
    {
      if (ifp->ifindex != ifm->ifm_index)
        {
          zlog_warn ("%s: index mismatch, ifname %s, ifp index %d, "
                     "ifm index %d", 
                     __func__, ifp->name, ifp->ifindex, ifm->ifm_index);
          return -1;
        }
      
#ifdef HAVE_BSD_LINK_DETECT /* translate BSD kernel msg for link-state */
      bsd_linkdetect_translate(ifm);
#endif /* HAVE_BSD_LINK_DETECT */

      /* update flags and handle operative->inoperative transition, if any */
      if_flags_update (ifp, ifm->ifm_flags);
      
#ifndef RTM_IFANNOUNCE
      if (!if_is_up (ifp))
          {
            /* No RTM_IFANNOUNCE on this platform, so we can never
             * distinguish between ~IFF_UP and delete. We must presume
             * it has been deleted.
             * Eg, Solaris will not notify us of unplumb.
             *
             * XXX: Fixme - this should be runtime detected
             * So that a binary compiled on a system with IFANNOUNCE
             * will still behave correctly if run on a platform without
             */
            if_delete_update (ifp);
          }
#endif /* RTM_IFANNOUNCE */
      if (if_is_up (ifp))
      {
#if defined(__bsdi__)
        if_kvm_get_mtu (ifp);
#else
        if_get_mtu (ifp);
#endif /* __bsdi__ */
        if_get_metric (ifp);
      }
    }

#ifdef HAVE_NET_RT_IFLIST
  ifp->stats = ifm->ifm_data;
#endif /* HAVE_NET_RT_IFLIST */

  if (IS_ZEBRA_DEBUG_KERNEL)
    zlog_debug ("%s: interface %s index %d", 
                __func__, ifp->name, ifp->ifindex);

  return 0;
}
Example #26
0
int
babel_filter(int output, const unsigned char *prefix, unsigned short plen,
             unsigned int ifindex)
{
    struct interface *ifp = if_lookup_by_index(ifindex);
    babel_interface_nfo *babel_ifp = ifp ? babel_get_if_nfo(ifp) : NULL;
    struct prefix p;
    struct distribute *dist;
    struct access_list *alist;
    struct prefix_list *plist;
    int filter = output ? BABEL_FILTER_OUT : BABEL_FILTER_IN;
    int distribute = output ? DISTRIBUTE_OUT : DISTRIBUTE_IN;

    p.family = v4mapped(prefix) ? AF_INET : AF_INET6;
    p.prefixlen = v4mapped(prefix) ? plen - 96 : plen;
    if (p.family == AF_INET)
        uchar_to_inaddr(&p.u.prefix4, prefix);
#ifdef HAVE_IPV6
    else
        uchar_to_in6addr(&p.u.prefix6, prefix);
#endif
    if (babel_ifp != NULL && babel_ifp->list[filter]) {
        if (access_list_apply (babel_ifp->list[filter], &p)
            == FILTER_DENY) {
            debugf(BABEL_DEBUG_FILTER,
                   "%s/%d filtered by distribute in",
#ifdef HAVE_IPV6
                   p.family == AF_INET ?
                   inet_ntoa(p.u.prefix4) :
                   inet6_ntoa (p.u.prefix6),
#else
		   inet_ntoa(p.u.prefix4),
#endif
                   p.prefixlen);
            return INFINITY;
	}
    }
    if (babel_ifp != NULL && babel_ifp->prefix[filter]) {
        if (prefix_list_apply (babel_ifp->prefix[filter], &p)
            == PREFIX_DENY) {
            debugf(BABEL_DEBUG_FILTER, "%s/%d filtered by distribute in",
#ifdef HAVE_IPV6
                        p.family == AF_INET ?
                        inet_ntoa(p.u.prefix4) :
                        inet6_ntoa (p.u.prefix6),
#else
                        inet_ntoa(p.u.prefix4),
#endif
                        p.prefixlen);
            return INFINITY;
	}
    }

    /* All interface filter check. */
    dist = distribute_lookup (NULL);
    if (dist) {
        if (dist->list[distribute]) {
            alist = access_list_lookup (AFI_IP6, dist->list[distribute]);

            if (alist) {
                if (access_list_apply (alist, &p) == FILTER_DENY) {
                    debugf(BABEL_DEBUG_FILTER, "%s/%d filtered by distribute in",
#ifdef HAVE_IPV6
                                p.family == AF_INET ?
                                inet_ntoa(p.u.prefix4) :
                                inet6_ntoa (p.u.prefix6),
#else
                                inet_ntoa(p.u.prefix4),
#endif
                                p.prefixlen);
                    return INFINITY;
		}
	    }
	}
        if (dist->prefix[distribute]) {
            plist = prefix_list_lookup (AFI_IP6, dist->prefix[distribute]);
            if (plist) {
                if (prefix_list_apply (plist, &p) == PREFIX_DENY) {
                    debugf(BABEL_DEBUG_FILTER, "%s/%d filtered by distribute in",
#ifdef HAVE_IPV6
                                p.family == AF_INET ?
                                inet_ntoa(p.u.prefix4) :
                                inet6_ntoa (p.u.prefix6),
#else
                                inet_ntoa(p.u.prefix4),
#endif
                                p.prefixlen);
                    return INFINITY;
		}
	    }
	}
    }
    return 0;
}
Example #27
0
/* Lookup interface IPv4/IPv6 address. */
static int
netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
{
  int len;
  struct ifaddrmsg *ifa;
  struct rtattr *tb[IFA_MAX + 1];
  struct interface *ifp;
  void *addr;
  void *broad;
  u_char flags = 0;
  char *label = NULL;

  ifa = NLMSG_DATA (h);

  if (ifa->ifa_family != AF_INET
#ifdef HAVE_IPV6
      && ifa->ifa_family != AF_INET6
#endif /* HAVE_IPV6 */
    )
    return 0;

  if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
    return 0;

  len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifaddrmsg));
  if (len < 0)
    return -1;

  memset (tb, 0, sizeof tb);
  netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);

  ifp = if_lookup_by_index (ifa->ifa_index);
  if (ifp == NULL)
    {
      zlog_err ("netlink_interface_addr can't find interface by index %d",
                ifa->ifa_index);
      return -1;
    }

  if (IS_DEBUG_HA(kroute, KROUTE))    /* remove this line to see initial ifcfg */
    {
      char buf[BUFSIZ];
      zlog_debug ("netlink_interface_addr %s %s:",
                 lookup (nlmsg_str, h->nlmsg_type), ifp->name);
      if (tb[IFA_LOCAL])
        zlog_debug ("  IFA_LOCAL     %s/%d",
		    inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_LOCAL]),
			       buf, BUFSIZ), ifa->ifa_prefixlen);
      if (tb[IFA_ADDRESS])
        zlog_debug ("  IFA_ADDRESS   %s/%d",
		    inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_ADDRESS]),
                               buf, BUFSIZ), ifa->ifa_prefixlen);
      if (tb[IFA_BROADCAST])
        zlog_debug ("  IFA_BROADCAST %s/%d",
		    inet_ntop (ifa->ifa_family, RTA_DATA (tb[IFA_BROADCAST]),
			       buf, BUFSIZ), ifa->ifa_prefixlen);
      if (tb[IFA_LABEL] && strcmp (ifp->name, RTA_DATA (tb[IFA_LABEL])))
        zlog_debug ("  IFA_LABEL     %s", (char *)RTA_DATA (tb[IFA_LABEL]));
      
      if (tb[IFA_CACHEINFO])
        {
          struct ifa_cacheinfo *ci = RTA_DATA (tb[IFA_CACHEINFO]);
          zlog_debug ("  IFA_CACHEINFO pref %d, valid %d",
                      ci->ifa_prefered, ci->ifa_valid);
        }
    }
  
  /* logic copied from iproute2/ip/ipaddress.c:print_addrinfo() */
  if (tb[IFA_LOCAL] == NULL)
    tb[IFA_LOCAL] = tb[IFA_ADDRESS];
  if (tb[IFA_ADDRESS] == NULL)
    tb[IFA_ADDRESS] = tb[IFA_LOCAL];
  
  /* local interface address */
  addr = (tb[IFA_LOCAL] ? RTA_DATA(tb[IFA_LOCAL]) : NULL);

  /* is there a peer address? */
  if (tb[IFA_ADDRESS] &&
      memcmp(RTA_DATA(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_LOCAL]), RTA_PAYLOAD(tb[IFA_ADDRESS])))
    {
      broad = RTA_DATA(tb[IFA_ADDRESS]);
      SET_FLAG (flags, KROUTE_IFA_PEER);
    }
  else
    /* seeking a broadcast address */
    broad = (tb[IFA_BROADCAST] ? RTA_DATA(tb[IFA_BROADCAST]) : NULL);

  /* addr is primary key, SOL if we don't have one */
  if (addr == NULL)
    {
      zlog_debug ("%s: NULL address", __func__);
      return -1;
    }

  /* Flags. */
  if (ifa->ifa_flags & IFA_F_SECONDARY)
    SET_FLAG (flags, KROUTE_IFA_SECONDARY);

  /* Label */
  if (tb[IFA_LABEL])
    label = (char *) RTA_DATA (tb[IFA_LABEL]);

  if (ifp && label && strcmp (ifp->name, label) == 0)
    label = NULL;

  /* Register interface address to the interface. */
  if (ifa->ifa_family == AF_INET)
    {
      if (h->nlmsg_type == RTM_NEWADDR)
        connected_add_ipv4 (ifp, flags,
                            (struct in_addr *) addr, ifa->ifa_prefixlen,
                            (struct in_addr *) broad, label);
      else
        connected_delete_ipv4 (ifp, flags,
                               (struct in_addr *) addr, ifa->ifa_prefixlen,
                               (struct in_addr *) broad);
    }
#ifdef HAVE_IPV6
  if (ifa->ifa_family == AF_INET6)
    {
      if (h->nlmsg_type == RTM_NEWADDR)
        connected_add_ipv6 (ifp, flags,
                            (struct in6_addr *) addr, ifa->ifa_prefixlen,
                            (struct in6_addr *) broad, label);
      else
        connected_delete_ipv6 (ifp,
                               (struct in6_addr *) addr, ifa->ifa_prefixlen,
                               (struct in6_addr *) broad);
    }
#endif /* HAVE_IPV6 */

  return 0;
}
Example #28
0
struct connected *
zebra_interface_address_read (int type, struct stream *s)
{
  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 (ifindex);
  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[BUFSIZ];
	       prefix2str (ifc->address, buf, sizeof(buf));
	       zlog_warn("warning: interface %s address %s "
		    "with peer flag set, but no peer address!",
		    ifp->name, buf);
	       UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
	     }
	 }
    }
  else
    {
      assert (type == ZEBRA_INTERFACE_ADDRESS_DELETE);
      ifc = connected_delete_by_prefix(ifp, &p);
    }

  return ifc;
}
Example #29
0
/* Interface function for the kernel routing table updates.  Support
   for RTM_CHANGE will be needed. */
int
rtm_write (int message,
	   union sockunion *dest,
	   union sockunion *mask,
	   union sockunion *gate,
	   unsigned int index,
	   int zebra_flags,
	   int metric)
{
  int ret;
  caddr_t pnt;
  struct interface *ifp;
  struct sockaddr_in tmp_gate;
#ifdef HAVE_IPV6
  struct sockaddr_in6 tmp_gate6;
#endif /* HAVE_IPV6 */

  /* Sequencial number of routing message. */
  static int msg_seq = 0;

  /* Struct of rt_msghdr and buffer for storing socket's data. */
  struct 
  {
    struct rt_msghdr rtm;
    char buf[512];
  } msg;
  
  memset (&tmp_gate, 0, sizeof (struct sockaddr_in));
  tmp_gate.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
  tmp_gate.sin_len = sizeof (struct sockaddr_in);
#endif /* HAVE_SIN_LEN */

#ifdef HAVE_IPV6
  memset (&tmp_gate6, 0, sizeof (struct sockaddr_in6));
  tmp_gate6.sin6_family = AF_INET6;
#ifdef SIN6_LEN
  tmp_gate6.sin6_len = sizeof (struct sockaddr_in6);
#endif /* SIN6_LEN */
#endif /* HAVE_IPV6 */

  if (routing_sock < 0)
    return ZEBRA_ERR_EPERM;

  /* Clear and set rt_msghdr values */
  memset (&msg, 0, sizeof (struct rt_msghdr));
  msg.rtm.rtm_version = RTM_VERSION;
  msg.rtm.rtm_type = message;
  msg.rtm.rtm_seq = msg_seq++;
  msg.rtm.rtm_addrs = RTA_DST;
  msg.rtm.rtm_addrs |= RTA_GATEWAY;
  msg.rtm.rtm_flags = RTF_UP;
  msg.rtm.rtm_index = index;

  if (metric != 0)
    {
      msg.rtm.rtm_rmx.rmx_hopcount = metric;
      msg.rtm.rtm_inits |= RTV_HOPCOUNT;
    }

  ifp = if_lookup_by_index (index);

  if (gate && message == RTM_ADD)
    msg.rtm.rtm_flags |= RTF_GATEWAY;

  if (! gate && message == RTM_ADD && ifp &&
      (ifp->flags & IFF_POINTOPOINT) == 0)
    msg.rtm.rtm_flags |= RTF_CLONING;

  /* If no protocol specific gateway is specified, use link
     address for gateway. */
  if (! gate)
    {
      if (!ifp)
        {
          zlog_warn ("no gateway found for interface index %d", index);
          return -1;
        }
      gate = (union sockunion *) & ifp->sdl;
    }

  if (mask)
    msg.rtm.rtm_addrs |= RTA_NETMASK;
  else if (message == RTM_ADD) 
    msg.rtm.rtm_flags |= RTF_HOST;

  /* Tagging route with flags */
  msg.rtm.rtm_flags |= (RTF_PROTO1);

  /* Additional flags. */
  if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
    msg.rtm.rtm_flags |= RTF_BLACKHOLE;

#ifdef HAVE_SIN_LEN
#define SOCKADDRSET(X,R) \
  if (msg.rtm.rtm_addrs & (R)) \
    { \
      int len = ROUNDUP ((X)->sa.sa_len); \
      memcpy (pnt, (caddr_t)(X), len); \
      pnt += len; \
    }
#else 
#define SOCKADDRSET(X,R) \
  if (msg.rtm.rtm_addrs & (R)) \
    { \
      int len = ROUNDUP (sizeof((X)->sa)); \
      memcpy (pnt, (caddr_t)(X), len); \
      pnt += len; \
    }
#endif /* HAVE_SIN_LEN */

  pnt = (caddr_t) msg.buf;

  /* Write each socket data into rtm message buffer */
  SOCKADDRSET (dest, RTA_DST);
  SOCKADDRSET (gate, RTA_GATEWAY);
  SOCKADDRSET (mask, RTA_NETMASK);

  msg.rtm.rtm_msglen = pnt - (caddr_t) &msg;

  ret = write (routing_sock, &msg, msg.rtm.rtm_msglen);

  if (ret != msg.rtm.rtm_msglen) 
    {
      if (errno == EEXIST) 
	return ZEBRA_ERR_RTEXIST;
      if (errno == ENETUNREACH)
	return ZEBRA_ERR_RTUNREACH;
      
      zlog_warn ("write : %s (%d)", strerror (errno), errno);
      return -1;
    }
  return 0;
}
Example #30
0
/* Lookup interface IPv4/IPv6 address. */
int
netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
{
    int len;
    struct ifaddrmsg *ifa;
    struct rtattr *tb [IFA_MAX + 1];
    struct interface *ifp;
    void *addr = NULL;
    void *broad = NULL;
    u_char flags = 0;
    char *label = NULL;

    ifa = NLMSG_DATA (h);

    if (ifa->ifa_family != AF_INET
#ifdef HAVE_IPV6
            && ifa->ifa_family != AF_INET6
#endif /* HAVE_IPV6 */
       )
        return 0;

    if (h->nlmsg_type != RTM_NEWADDR && h->nlmsg_type != RTM_DELADDR)
        return 0;

    len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct ifaddrmsg));
    if (len < 0)
        return -1;

    memset (tb, 0, sizeof tb);
    netlink_parse_rtattr (tb, IFA_MAX, IFA_RTA (ifa), len);

    ifp = if_lookup_by_index (ifa->ifa_index);
    if (ifp == NULL)
    {
        zlog_err ("netlink_interface_addr can't find interface by index %d",
                  ifa->ifa_index);
        return -1;
    }

    if (tb[IFA_ADDRESS] == NULL)
        tb[IFA_ADDRESS] = tb[IFA_LOCAL];

    if (ifp->flags & IFF_POINTOPOINT)
    {
        if (tb[IFA_LOCAL])
        {
            addr = RTA_DATA (tb[IFA_LOCAL]);
            if (tb[IFA_ADDRESS])
                broad = RTA_DATA (tb[IFA_ADDRESS]);
            else
                broad = NULL;
        }
        else
        {
            if (tb[IFA_ADDRESS])
                addr = RTA_DATA (tb[IFA_ADDRESS]);
            else
                addr = NULL;
        }
    }
    else
    {
        if (tb[IFA_ADDRESS])
            addr = RTA_DATA (tb[IFA_ADDRESS]);
        else
            addr = NULL;

        if (tb[IFA_BROADCAST])
            broad = RTA_DATA(tb[IFA_BROADCAST]);
        else
            broad = NULL;
    }

    /* Flags. */
    if (ifa->ifa_flags & IFA_F_SECONDARY)
        SET_FLAG (flags, ZEBRA_IFA_SECONDARY);

    /* Label */
    if (tb[IFA_LABEL])
        label = (char *) RTA_DATA (tb[IFA_LABEL]);

    if (ifp && label && strcmp (ifp->name, label) == 0)
        label = NULL;

    /* Register interface address to the interface. */
    if (ifa->ifa_family == AF_INET)
    {
        if (h->nlmsg_type == RTM_NEWADDR)
            connected_add_ipv4 (ifp, flags,
                                (struct in_addr *) addr, ifa->ifa_prefixlen,
                                (struct in_addr *) broad, label);
        else
            connected_delete_ipv4 (ifp, flags,
                                   (struct in_addr *) addr, ifa->ifa_prefixlen,
                                   (struct in_addr *) broad, label);
    }
#ifdef HAVE_IPV6
    if (ifa->ifa_family == AF_INET6)
    {
        if (h->nlmsg_type == RTM_NEWADDR)
            connected_add_ipv6 (ifp,
                                (struct in6_addr *) addr, ifa->ifa_prefixlen,
                                (struct in6_addr *) broad);
        else
            connected_delete_ipv6 (ifp,
                                   (struct in6_addr *) addr, ifa->ifa_prefixlen,
                                   (struct in6_addr *) broad);
    }
#endif /* HAVE_IPV6*/

    return 0;
}