Пример #1
0
/* Update source selection.  */
static int bgp_update_source(struct peer *peer)
{
	struct interface *ifp;
	union sockunion addr;
	int ret = 0;

	sockunion_init(&addr);

	/* Source is specified with interface name.  */
	if (peer->update_if) {
		ifp = if_lookup_by_name(peer->update_if, peer->bgp->vrf_id);
		if (!ifp)
			return -1;

		if (bgp_update_address(ifp, &peer->su, &addr))
			return -1;

		ret = sockunion_bind(peer->fd, &addr, 0, &addr);
	}

	/* Source is specified with IP address.  */
	if (peer->update_source)
		ret = sockunion_bind(peer->fd, peer->update_source, 0,
				     peer->update_source);

	return ret;
}
Пример #2
0
/* Match function return 1 if match is success else return zero. */
route_map_result_t
route_match_interface (void *rule, struct prefix *prefix,
		       route_map_object_t type, void *object)
{
  struct rip_info *rinfo;
  struct interface *ifp;
  char *ifname;

  if (type == RMAP_RIP)
    {
      ifname = rule;
      ifp = if_lookup_by_name(ifname);

      if (!ifp)
	return RMAP_NOMATCH;

      rinfo = object;

      if (rinfo->ifindex_out == ifp->ifindex)
	return RMAP_MATCH;
      else
	return RMAP_NOMATCH;
    }
  return RMAP_NOMATCH;
}
Пример #3
0
/* Create new interface structure. */
struct interface *
if_create (const char *name, int namelen)
{
  struct interface *ifp;

  ifp = XCALLOC (MTYPE_IF, sizeof (struct interface));
  ifp->ifindex = IFINDEX_INTERNAL;
  
  assert (name);
  assert (namelen <= INTERFACE_NAMSIZ);	/* Need space for '\0' at end. */
  strncpy (ifp->name, name, namelen);
  ifp->name[namelen] = '\0';
  if (if_lookup_by_name(ifp->name) == NULL)
    listnode_add_sort (iflist, ifp);
  else
    zlog_err("if_create(%s): corruption detected -- interface with this "
	     "name exists already!", ifp->name);
  ifp->connected = list_new ();
  ifp->connected->del = (void (*) (void *)) connected_free;

  if (if_master.if_new_hook)
    (*if_master.if_new_hook) (ifp);

  return ifp;
}
Пример #4
0
unsigned int ifname2ifindex (const char *name)
{
	struct interface *ifp;

	return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp->ifIndex
		: -1;
}
Пример #5
0
static int ldp_labelspace_read(int cmd, struct zclient *client,
    zebra_size_t size) {
    struct zapi_mpls_labelspace api;
    struct interface *ifp;
    struct ldp_interface *li;
    int labelspace;

    mpls_labelspace_stream_read(client->ibuf, &api);
    ifp = if_lookup_by_name(api.ifname);

    if (ifp) {
	labelspace = ifp->mpls_labelspace;
	ifp->mpls_labelspace = api.labelspace;

	if (ifp->info) {
	    li = ifp->info;

	    if (api.labelspace < 0) {
		if (li->configured == MPLS_BOOL_TRUE)
		    ldp_interface_shutdown (li);
	    } else {
		if (labelspace >= 0) {
		    if (li->configured == MPLS_BOOL_TRUE)
			ldp_interface_shutdown (li);
		}
		if (li->configured == MPLS_BOOL_TRUE)
		    ldp_interface_startup (li);
	    }
	}
    }
    return 0;
}
Пример #6
0
Файл: if.c Проект: yubo/quagga
/* Get interface by name if given name interface doesn't exist create
   one. */
struct interface *if_get_by_name(const char *name)
{
	struct interface *ifp;

	return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp :
	    if_create(name, strlen(name));
}
Пример #7
0
/* 
 * Read interface up/down msg (ZEBRA_INTERFACE_UP/ZEBRA_INTERFACE_DOWN)
 * from zebra server.  The format of this message is the same as
 * that sent for ZEBRA_INTERFACE_ADD/ZEBRA_INTERFACE_DELETE (see
 * comments for zebra_interface_add_read), except that no sockaddr_dl
 * is sent at the tail of the message.
 */
struct interface_FOO *
zebra_interface_state_read (struct stream *s)
{
  struct interface_FOO *ifp;
  char ifname_tmp[INTERFACE_NAMSIZ];

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

  /* Lookup this by interface index. */
  ifp = if_lookup_by_name (ifname_tmp);

  /* If such interface does not exist, indicate an error */
  if (! ifp)
     return NULL;

  /* Read interface's index. */
  ifp->ifindex = stream_getl (s);

  /* Read interface's value. */
  ifp->status = stream_getc (s);
  ifp->flags = stream_getl (s);
  ifp->metric = stream_getl (s);
  ifp->mtu = stream_getl (s);
  ifp->mtu6 = stream_getl (s);
  ifp->bandwidth = stream_getl (s);

  return ifp;
}
Пример #8
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);
}
Пример #9
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);
}
Пример #10
0
struct interface * zebra_interface_if_lookup(struct stream *s) {
    struct interface *ifp;
    u_char ifname_tmp[INTERFACE_NAMSIZ];

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

    /* Lookup this by interface index. */
    ifp = if_lookup_by_name(ifname_tmp);

    /* If such interface does not exist, indicate an error */
    if (!ifp) {
	return NULL;
    }

    return ifp;
}
Пример #11
0
/* Match function should return 1 if match is success else return
   zero. */
static route_map_result_t
route_match_interface (void *rule, struct prefix *prefix,
		       route_map_object_t type, void *object)
{
  struct interface *ifp;
  struct external_info *ei;

  if (type == RMAP_OSPF)
    {
      ei = object;
      ifp = if_lookup_by_name ((char *)rule);

      if (ifp == NULL || ifp->ifindex != ei->ifindex)
	return RMAP_NOMATCH;

      return RMAP_MATCH;
    }
  return RMAP_NOMATCH;
}
Пример #12
0
void eigrp_if_rmap_update(struct if_rmap *if_rmap)
{
	struct interface *ifp;
	struct eigrp_interface *ei, *ei2;
	struct listnode *node, *nnode;
	struct route_map *rmap;
	struct eigrp *e;

	ifp = if_lookup_by_name(if_rmap->ifname);
	if (ifp == NULL)
		return;

	ei = NULL;
	e = eigrp_lookup();
	for (ALL_LIST_ELEMENTS(e->eiflist, node, nnode, ei2)) {
		if (strcmp(ei2->ifp->name, ifp->name) == 0) {
			ei = ei2;
			break;
		}
	}

	if (if_rmap->routemap[IF_RMAP_IN]) {
		rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_IN]);
		if (rmap)
			ei->routemap[IF_RMAP_IN] = rmap;
		else
			ei->routemap[IF_RMAP_IN] = NULL;
	} else
		ei->routemap[EIGRP_FILTER_IN] = NULL;

	if (if_rmap->routemap[IF_RMAP_OUT]) {
		rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_OUT]);
		if (rmap)
			ei->routemap[IF_RMAP_OUT] = rmap;
		else
			ei->routemap[IF_RMAP_OUT] = NULL;
	} else
		ei->routemap[EIGRP_FILTER_OUT] = NULL;
}
/* Update source selection.  */
static void
bgp_update_source (struct peer *peer)
{
  struct interface *ifp;
  union sockunion addr;

  /* Source is specified with interface name.  */
  if (peer->update_if)
    {
      ifp = if_lookup_by_name (peer->update_if);
      if (! ifp)
	return;

      if (bgp_update_address (ifp, &peer->su, &addr))
	return;

      sockunion_bind (peer->fd, &addr, 0, &addr);
    }

  /* Source is specified with IP address.  */
  if (peer->update_source)
    sockunion_bind (peer->fd, peer->update_source, 0, peer->update_source);
}
Пример #14
0
struct interface_FOO *
zebra_interface_add_read (struct stream *s)
{
  struct interface_FOO *ifp;
  char ifname_tmp[INTERFACE_NAMSIZ];

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

  /* Lookup this by interface name. */
  ifp = if_lookup_by_name (ifname_tmp);

  /* If such interface does not exist, make new one. */
  if (! ifp)
    ifp = if_create (ifname_tmp, INTERFACE_NAMSIZ);

  /* Read interface's index. */
  ifp->ifindex = stream_getl (s);

  /* Read interface's value. */
  ifp->status = stream_getc (s);
  ifp->flags = stream_getl (s);
  ifp->metric = stream_getl (s);
  ifp->mtu = stream_getl (s);
  ifp->mtu6 = stream_getl (s);
  ifp->bandwidth = stream_getl (s);
#ifdef HAVE_SOCKADDR_DL
  stream_get (&ifp->sdl, s, sizeof (ifp->sdl));
#else
  ifp->hw_addr_len = stream_getl (s);
  if (ifp->hw_addr_len)
    stream_get (ifp->hw_addr, s, ifp->hw_addr_len);
#endif /* HAVE_SOCKADDR_DL */
  
  return ifp;
}
Пример #15
0
/* Update source selection.  */
static void
bgp_update_source (struct peer *peer)
{
  struct interface *ifp;
  struct in_addr *addr;

  /* Source is specified with interface name.  */
  if (peer->update_if)
    {
      ifp = if_lookup_by_name (peer->update_if);
      if (! ifp)
	return;

      addr = bgp_update_address (ifp);
      if (! addr)
	return;

      bgp_bind_address (peer->fd, addr);
    }

  /* Source is specified with IP address.  */
  if (peer->update_source)
    sockunion_bind (peer->fd, peer->update_source, 0, peer->update_source);
}
Пример #16
0
static int
netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
{
  int len;
  struct ifinfomsg *ifi;
  struct rtattr *tb[IFLA_MAX + 1];
  struct interface *ifp;
  char *name;

  ifi = NLMSG_DATA (h);

  if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
    {
      /* If this is not link add/delete message so print warning. */
      zlog_warn ("netlink_link_change: wrong kernel message %d\n",
                 h->nlmsg_type);
      return 0;
    }

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

  /* Looking up interface name. */
  memset (tb, 0, sizeof tb);
  netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);

#ifdef IFLA_WIRELESS
  /* check for wireless messages to ignore */
  if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
    {
      if (IS_DEBUG_HA(kroute, KROUTE))
        zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
      return 0;
    }
#endif /* IFLA_WIRELESS */
  
  if (tb[IFLA_IFNAME] == NULL)
    return -1;
  name = (char *) RTA_DATA (tb[IFLA_IFNAME]);

  /* Add interface. */
  if (h->nlmsg_type == RTM_NEWLINK)
    {
      ifp = if_lookup_by_name (name);

      if (ifp == NULL || !CHECK_FLAG (ifp->status, KROUTE_INTERFACE_ACTIVE))
        {
          if (ifp == NULL)
            ifp = if_get_by_name (name);

          set_ifindex(ifp, ifi->ifi_index);
          ifp->flags = ifi->ifi_flags & 0x0000fffff;
          ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
          ifp->metric = 1;

          netlink_interface_update_hw_addr (tb, ifp);

          /* If new link is added. */
          if_add_update (ifp);
        }
      else
        {
          /* Interface status change. */
          set_ifindex(ifp, ifi->ifi_index);
          ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
          ifp->metric = 1;

          netlink_interface_update_hw_addr (tb, ifp);

          if (if_is_operative (ifp))
            {
              ifp->flags = ifi->ifi_flags & 0x0000fffff;
              if (!if_is_operative (ifp))
                if_down (ifp);
	      else
		/* Must notify client daemons of new interface status. */
	        kroute_interface_up_update (ifp);
            }
          else
            {
              ifp->flags = ifi->ifi_flags & 0x0000fffff;
              if (if_is_operative (ifp))
                if_up (ifp);
            }
        }
    }
  else
    {
      /* RTM_DELLINK. */
      ifp = if_lookup_by_name (name);

      if (ifp == NULL)
        {
          zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
                name);
          return 0;
        }

      if_delete_update (ifp);
    }

  return 0;
}
Пример #17
0
/**gjd : add for Distribute Product , for check interface exist or not
when add interface between master and viace board**/
struct interface *
check_interface_exist_by_name (const char *name)
{
	return if_lookup_by_name(name);
}
Пример #18
0
/* BGP Peer TCP Socket bind to 'update-source' address
 *
 * Specify the TCP client's source IP address.
 * This function must be called before calling connect().
 * The source port is set to "any port"
 * (i.e., picked by the kernel) unless a user specified it.
 */
s_int32_t
bpn_sock_bind_address (struct bgp_peer *peer,
                       pal_sock_handle_t sck_fd)
{
  struct prefix *if_prefix;
  struct interface *ifp;
  union sockunion uaddr;
  s_int32_t uaddr_len;
  s_int32_t ret;

  pal_mem_set (&uaddr, 0, sizeof (union sockunion));
  uaddr_len = 0;
  ret = 0;

  /* Ifname is exist. */
  if (peer->update_if)
    {
      ifp = if_lookup_by_name (&BGP_VR.owning_ivr->ifm,
                               peer->update_if);
      if (! ifp)
        {
          ret = -1;
          goto EXIT;
        }

      if_prefix = if_get_connected_address (ifp, peer->su.sa.sa_family);
      if (! if_prefix)
        {
          ret = -1;
          goto EXIT;
        }

      uaddr.sa.sa_family = if_prefix->family;

      if (uaddr.sa.sa_family == AF_INET)
        {
          uaddr.sin.sin_family = AF_INET;

          uaddr_len = sizeof (struct pal_sockaddr_in4);
#ifdef HAVE_SIN_LEN
          uaddr.sin.sin_len = pal_hton16 (uaddr_len);
#endif /* HAVE_SIN_LEN */
          IPV4_ADDR_COPY (&uaddr.sin.sin_addr, &if_prefix->u.prefix4);

          if (peer->sock_port == BGP_PORT_DEFAULT)
            uaddr.sin.sin_port = 
              bpn_get_port_any (AF_INET, SOCK_STREAM, &uaddr.sa);
          else
            uaddr.sin.sin_port = pal_hton16 (peer->sock_port);

        }
#ifdef HAVE_IPV6
      else if (BGP_CAP_HAVE_IPV6 && uaddr.sa.sa_family == AF_INET6)
        {
          uaddr.sin6.sin6_family = AF_INET6;

          uaddr_len = sizeof (struct pal_sockaddr_in6);
#ifdef HAVE_SIN_LEN
          uaddr.sin6.sin6_len = pal_hton16 (uaddr_len);
#endif /* HAVE_SIN_LEN */
          IPV6_ADDR_COPY (&uaddr.sin6.sin6_addr, &if_prefix->u.prefix6);

          if (peer->sock_port == BGP_PORT_DEFAULT)
            uaddr.sin6.sin6_port = 
              bpn_get_port_any (AF_INET6, SOCK_STREAM, &uaddr.sa);
          else
            uaddr.sin6.sin6_port = pal_hton16 (peer->sock_port);
        }
#endif /* HAVE_IPV6 */
      else
        {
          if (BGP_DEBUG (events, EVENTS))
            zlog_err (&BLG, "%s-%s [NETWORK] bind addr: socket (%d), "
                      "unknown update-interface family (%d)", peer->host,
                      BGP_PEER_DIR_STR (peer), sck_fd, uaddr.sa.sa_family);

          ret = -1;
          goto EXIT;
        }
    }
  else if (peer->update_source)
    {
      uaddr.sa.sa_family = peer->update_source->sa.sa_family;

      if (uaddr.sa.sa_family == AF_INET)
        {
          uaddr.sin.sin_family = AF_INET;

          uaddr_len = sizeof (struct pal_sockaddr_in4);

         if (peer->sock_port == BGP_PORT_DEFAULT)
           uaddr.sin.sin_port =
             bpn_get_port_any (AF_INET, SOCK_STREAM,
                               &peer->update_source->sa);
         else
           uaddr.sin.sin_port = pal_hton16 (peer->sock_port);

#ifdef HAVE_SIN_LEN
          uaddr.sin.sin_len = pal_hton16 (uaddr_len);
#endif /* HAVE_SIN_LEN */

          IPV4_ADDR_COPY (&uaddr.sin.sin_addr,
                          &peer->update_source->sin.sin_addr);
        }
#ifdef HAVE_IPV6
      else if (BGP_CAP_HAVE_IPV6 && uaddr.sa.sa_family == AF_INET6)
        {
          uaddr.sin6.sin6_family = AF_INET6;

          uaddr_len = sizeof (struct pal_sockaddr_in6);

         if (peer->sock_port == BGP_PORT_DEFAULT)
           uaddr.sin6.sin6_port =
             bpn_get_port_any (AF_INET6, SOCK_STREAM,
                               &peer->update_source->sa);
         else
           uaddr.sin.sin_port = pal_hton16 (peer->sock_port);

#ifdef HAVE_SIN_LEN
          uaddr.sin6.sin6_len = pal_hton16 (uaddr_len);
#endif /* HAVE_SIN_LEN */

          IPV6_ADDR_COPY (&uaddr.sin6.sin6_addr,
                          &peer->update_source->sin6.sin6_addr);
        }
#endif /* HAVE_IPV6 */
      else
        {
          if (BGP_DEBUG (events, EVENTS))
            zlog_err (&BLG, "%s-%s [NETWORK] bind addr: socket (%d), "
                      "unknown update-address family (%d)", peer->host,
                      BGP_PEER_DIR_STR (peer), sck_fd, uaddr.sa.sa_family);

          ret = -1;
          goto EXIT;
        }
    }

  if (uaddr_len)
    {
      ret = pal_sock_bind (sck_fd, (struct pal_sockaddr *) &uaddr, uaddr_len);

      if (ret < 0)
        if (BGP_DEBUG (events, EVENTS))
          zlog_err (&BLG, "%s-%s [NETWORK] bind addr: socket (%d), bind"
                    " failed (%d-%s)", peer->host, BGP_PEER_DIR_STR (peer),
                    sck_fd, errno, pal_strerror (errno));
    }

 EXIT:

  return ret;
}
Пример #19
0
/* active peer socket setup */
int pim_msdp_sock_connect(struct pim_msdp_peer *mp)
{
	int rc;

	if (PIM_DEBUG_MSDP_INTERNAL) {
		zlog_debug("MSDP peer %s attempt connect%s", mp->key_str,
			   mp->fd < 0 ? "" : "(dup)");
	}

	/* if we have an existing connection we need to kill that one
	 * with this one */
	if (mp->fd >= 0) {
		if (PIM_DEBUG_MSDP_EVENTS) {
			zlog_notice(
				"msdp duplicate connect to %s nuke old connection",
				mp->key_str);
		}
		pim_msdp_peer_stop_tcp_conn(mp, false /* chg_state */);
	}

	/* Make socket for the peer. */
	mp->fd = sockunion_socket(&mp->su_peer);
	if (mp->fd < 0) {
		flog_err_sys(LIB_ERR_SOCKET,
			     "pim_msdp_socket socket failure: %s",
			     safe_strerror(errno));
		return -1;
	}

	if (mp->pim->vrf_id != VRF_DEFAULT) {
		struct interface *ifp =
			if_lookup_by_name(mp->pim->vrf->name, mp->pim->vrf_id);
		if (!ifp) {
			flog_err(LIB_ERR_INTERFACE,
				  "%s: Unable to lookup vrf interface: %s",
				  __PRETTY_FUNCTION__, mp->pim->vrf->name);
			return -1;
		}
		if (pim_socket_bind(mp->fd, ifp)) {
			flog_err_sys(LIB_ERR_SOCKET,
				     "%s: Unable to bind to socket: %s",
				     __PRETTY_FUNCTION__, safe_strerror(errno));
			close(mp->fd);
			mp->fd = -1;
			return -1;
		}
	}

	set_nonblocking(mp->fd);

	/* Set socket send buffer size */
	pim_msdp_update_sock_send_buffer_size(mp->fd);
	sockopt_reuseaddr(mp->fd);
	sockopt_reuseport(mp->fd);

	/* source bind */
	rc = sockunion_bind(mp->fd, &mp->su_local, 0, &mp->su_local);
	if (rc < 0) {
		flog_err_sys(LIB_ERR_SOCKET,
			     "pim_msdp_socket connect bind failure: %s",
			     safe_strerror(errno));
		close(mp->fd);
		mp->fd = -1;
		return rc;
	}

	/* Connect to the remote mp. */
	return (sockunion_connect(mp->fd, &mp->su_peer,
				  htons(PIM_MSDP_TCP_PORT), 0));
}
Пример #20
0
/* global listener for the MSDP well know TCP port */
int pim_msdp_sock_listen(struct pim_instance *pim)
{
	int sock;
	int socklen;
	struct sockaddr_in sin;
	int rc;
	struct pim_msdp_listener *listener = &pim->msdp.listener;

	if (pim->msdp.flags & PIM_MSDPF_LISTENER) {
		/* listener already setup */
		return 0;
	}

	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock < 0) {
		flog_err_sys(LIB_ERR_SOCKET, "socket: %s",
			     safe_strerror(errno));
		return sock;
	}

	memset(&sin, 0, sizeof(struct sockaddr_in));
	sin.sin_family = AF_INET;
	sin.sin_port = htons(PIM_MSDP_TCP_PORT);
	socklen = sizeof(struct sockaddr_in);
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
	sin.sin_len = socklen;
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */

	sockopt_reuseaddr(sock);
	sockopt_reuseport(sock);

	if (pim->vrf_id != VRF_DEFAULT) {
		struct interface *ifp =
			if_lookup_by_name(pim->vrf->name, pim->vrf_id);
		if (!ifp) {
			flog_err(LIB_ERR_INTERFACE,
				  "%s: Unable to lookup vrf interface: %s",
				  __PRETTY_FUNCTION__, pim->vrf->name);
			close(sock);
			return -1;
		}
		if (pim_socket_bind(sock, ifp)) {
			flog_err_sys(LIB_ERR_SOCKET,
				     "%s: Unable to bind to socket: %s",
				     __PRETTY_FUNCTION__, safe_strerror(errno));
			close(sock);
			return -1;
		}
	}

	frr_elevate_privs(&pimd_privs) {
		/* bind to well known TCP port */
		rc = bind(sock, (struct sockaddr *)&sin, socklen);
	}

	if (rc < 0) {
		flog_err_sys(LIB_ERR_SOCKET,
			     "pim_msdp_socket bind to port %d: %s",
			     ntohs(sin.sin_port), safe_strerror(errno));
		close(sock);
		return rc;
	}

	rc = listen(sock, 3 /* backlog */);
	if (rc < 0) {
		flog_err_sys(LIB_ERR_SOCKET, "pim_msdp_socket listen: %s",
			     safe_strerror(errno));
		close(sock);
		return rc;
	}

	/* add accept thread */
	listener->fd = sock;
	memcpy(&listener->su, &sin, socklen);
	listener->thread = NULL;
	thread_add_read(pim->msdp.master, pim_msdp_sock_accept, pim, sock,
			&listener->thread);

	pim->msdp.flags |= PIM_MSDPF_LISTENER;
	return 0;
}
Пример #21
0
int
if_getaddrs ()
{
  int ret;
  struct ifaddrs *ifap;
  struct ifaddrs *ifapfree;
  struct interface *ifp;
  int prefixlen;

  ret = getifaddrs (&ifap); 
  if (ret != 0)
    {
#ifdef BRCM_RIP_DEBUG
      zlog_err ("getifaddrs(): %s", strerror (errno));
#endif
      return -1;
    }

  for (ifapfree = ifap; ifap; ifap = ifap->ifa_next)
    {
      ifp = if_lookup_by_name (ifap->ifa_name);
      if (ifp == NULL)
	{
#ifdef BRCM_RIP_DEBUG
	  zlog_err ("if_getaddrs(): Can't lookup interface %s\n",
		    ifap->ifa_name);
#endif
	  continue;
	}

      if (ifap->ifa_addr->sa_family == AF_INET)
	{
	  struct sockaddr_in *addr;
	  struct sockaddr_in *mask;
	  struct sockaddr_in *dest;
	  struct in_addr *dest_pnt;

	  addr = (struct sockaddr_in *) ifap->ifa_addr;
	  mask = (struct sockaddr_in *) ifap->ifa_netmask;
	  prefixlen = ip_masklen (mask->sin_addr);

	  dest_pnt = NULL;

	  if (ifap->ifa_flags & IFF_POINTOPOINT) 
	    {
	      dest = (struct sockaddr_in *) ifap->ifa_dstaddr;
	      dest_pnt = &dest->sin_addr;
	    }

	  if (ifap->ifa_flags & IFF_BROADCAST)
	    {
	      dest = (struct sockaddr_in *) ifap->ifa_broadaddr;
	      dest_pnt = &dest->sin_addr;
	    }

	  connected_add_ipv4 (ifp, 0, &addr->sin_addr,
			      prefixlen, dest_pnt, NULL);
	}
#ifdef HAVE_IPV6
      if (ifap->ifa_addr->sa_family == AF_INET6)
	{
	  struct sockaddr_in6 *addr;
	  struct sockaddr_in6 *mask;
	  struct sockaddr_in6 *dest;
	  struct in6_addr *dest_pnt;

	  addr = (struct sockaddr_in6 *) ifap->ifa_addr;
	  mask = (struct sockaddr_in6 *) ifap->ifa_netmask;
	  prefixlen = ip6_masklen (mask->sin6_addr);

	  dest_pnt = NULL;

	  if (ifap->ifa_flags & IFF_POINTOPOINT) 
	    {
	      if (ifap->ifa_dstaddr)
		{
		  dest = (struct sockaddr_in6 *) ifap->ifa_dstaddr;
		  dest_pnt = &dest->sin6_addr;
		}
	    }

	  if (ifap->ifa_flags & IFF_BROADCAST)
	    {
	      if (ifap->ifa_broadaddr)
		{
		  dest = (struct sockaddr_in6 *) ifap->ifa_broadaddr;
		  dest_pnt = &dest->sin6_addr;
		}
	    }

	  connected_add_ipv6 (ifp, &addr->sin6_addr, prefixlen, dest_pnt);
	}
#endif /* HAVE_IPV6 */
    }

  freeifaddrs (ifapfree);

  return 0; 
}
Пример #22
0
int
bgp_nexthop_set (union sockunion *local, union sockunion *remote, 
		 struct bgp_nexthop *nexthop, struct peer *peer)
{
  int ret = 0;
  struct interface *ifp = NULL;

  memset (nexthop, 0, sizeof (struct bgp_nexthop));

  if (!local)
    return -1;
  if (!remote)
    return -1;

  if (local->sa.sa_family == AF_INET)
    {
      nexthop->v4 = local->sin.sin_addr;
      if (peer->update_if)
        ifp = if_lookup_by_name (peer->update_if);
      else
        ifp = if_lookup_by_ipv4_exact (&local->sin.sin_addr);
    }
  if (local->sa.sa_family == AF_INET6)
    {
      if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
	{
	  if (peer->ifname)
	    ifp = if_lookup_by_name (peer->ifname);
	}
      else if (peer->update_if)
        ifp = if_lookup_by_name (peer->update_if);
      else
        ifp = if_lookup_by_ipv6_exact (&local->sin6.sin6_addr);
    }

  if (!ifp)
    return -1;

  nexthop->ifp = ifp;

  /* IPv4 connection. */
  if (local->sa.sa_family == AF_INET)
    {
      /* IPv6 nexthop*/
      ret = if_get_ipv6_global (ifp, &nexthop->v6_global);

      /* There is no global nexthop. */
      if (!ret)
	if_get_ipv6_local (ifp, &nexthop->v6_global);
      else
	if_get_ipv6_local (ifp, &nexthop->v6_local);
    }

  /* IPv6 connection. */
  if (local->sa.sa_family == AF_INET6)
    {
      struct interface *direct = NULL;

      /* IPv4 nexthop. */
      ret = if_get_ipv4_address(ifp, &nexthop->v4);
      if (!ret && peer->local_id.s_addr)
	nexthop->v4 = peer->local_id;

      /* Global address*/
      if (! IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
	{
	  memcpy (&nexthop->v6_global, &local->sin6.sin6_addr, 
		  IPV6_MAX_BYTELEN);

	  /* If directory connected set link-local address. */
	  direct = if_lookup_by_ipv6 (&remote->sin6.sin6_addr);
	  if (direct)
	    if_get_ipv6_local (ifp, &nexthop->v6_local);
	}
      else
	/* Link-local address. */
	{
	  ret = if_get_ipv6_global (ifp, &nexthop->v6_global);

	  /* If there is no global address.  Set link-local address as
             global.  I know this break RFC specification... */
	  if (!ret)
	    memcpy (&nexthop->v6_global, &local->sin6.sin6_addr, 
		    IPV6_MAX_BYTELEN);
	  else
	    memcpy (&nexthop->v6_local, &local->sin6.sin6_addr, 
		    IPV6_MAX_BYTELEN);
	}
    }

  if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) ||
      if_lookup_by_ipv6 (&remote->sin6.sin6_addr))
    peer->shared_network = 1;
  else
    peer->shared_network = 0;

  /* KAME stack specific treatment.  */
#ifdef KAME
  if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_global)
      && IN6_LINKLOCAL_IFINDEX (nexthop->v6_global))
    {
      SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_global, 0);
    }
  if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_local)
      && IN6_LINKLOCAL_IFINDEX (nexthop->v6_local))
    {
      SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0);
    }
#endif /* KAME */
  return ret;
}
Пример #23
0
/* Get interface by name if given name interface doesn't exist create
   one. */
struct interface * if_get_by_name (const char *name)
{
	struct interface *ifp;

	return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp : NULL;
}
Пример #24
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);
}
Пример #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;
}
Пример #26
0
/*
 * Obtain the BGP instance that the incoming connection should be processed
 * against. This is important because more than one VRF could be using the
 * same IP address space. The instance is got by obtaining the device to
 * which the incoming connection is bound to. This could either be a VRF
 * or it could be an interface, which in turn determines the VRF.
 */
static int bgp_get_instance_for_inc_conn(int sock, struct bgp **bgp_inst)
{
#ifndef SO_BINDTODEVICE
	/* only Linux has SO_BINDTODEVICE, but we're in Linux-specific code here
	 * anyway since the assumption is that the interface name returned by
	 * getsockopt() is useful in identifying the VRF, particularly with
	 * Linux's
	 * VRF l3master device.  The whole mechanism is specific to Linux, so...
	 * when other platforms add VRF support, this will need handling here as
	 * well.  (or, some restructuring) */
	*bgp_inst = bgp_get_default();
	return !*bgp_inst;

#else
	char name[VRF_NAMSIZ + 1];
	socklen_t name_len = VRF_NAMSIZ;
	struct bgp *bgp;
	int rc;
	struct listnode *node, *nnode;

	*bgp_inst = NULL;
	name[0] = '\0';
	rc = getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, name, &name_len);
	if (rc != 0) {
#if defined(HAVE_CUMULUS)
		flog_err(EC_LIB_SOCKET,
			 "[Error] BGP SO_BINDTODEVICE get failed (%s), sock %d",
			 safe_strerror(errno), sock);
		return -1;
#endif
	}

	if (!strlen(name)) {
		*bgp_inst = bgp_get_default();
		return 0; /* default instance. */
	}

	/* First try match to instance; if that fails, check for interfaces. */
	bgp = bgp_lookup_by_name(name);
	if (bgp) {
		if (!bgp->vrf_id) // unexpected
			return -1;
		*bgp_inst = bgp;
		return 0;
	}

	/* TODO - This will be optimized once interfaces move into the NS */
	for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
		struct interface *ifp;

		if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
			continue;

		ifp = if_lookup_by_name(name, bgp->vrf_id);
		if (ifp) {
			*bgp_inst = bgp;
			return 0;
		}
	}

	/* We didn't match to either an instance or an interface. */
	return -1;
#endif
}
Пример #27
0
int
netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
{
    int len;
    struct ifinfomsg *ifi;
    struct rtattr *tb [IFLA_MAX + 1];
    struct interface *ifp;
    char *name;

    ifi = NLMSG_DATA (h);

    if (! (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
    {
        /* If this is not link add/delete message so print warning. */
        zlog_warn ("netlink_link_change: wrong kernel message %d\n",
                   h->nlmsg_type);
        return 0;
    }

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

    /* Looking up interface name. */
    memset (tb, 0, sizeof tb);
    netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
    if (tb[IFLA_IFNAME] == NULL)
        return -1;
    name = (char *)RTA_DATA(tb[IFLA_IFNAME]);

    /* Add interface. */
    if (h->nlmsg_type == RTM_NEWLINK)
    {
        ifp = if_lookup_by_name (name);

        if (ifp == NULL || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
        {
            if (ifp == NULL)
                ifp = if_get_by_name (name);

            ifp->ifindex = ifi->ifi_index;
            ifp->flags = ifi->ifi_flags & 0x0000fffff;
            ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
            ifp->metric = 1;

            /* If new link is added. */
            if_add_update(ifp);
        }
        else
        {
            /* Interface status change. */
            ifp->ifindex = ifi->ifi_index;
            ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
            ifp->metric = 1;

            if (if_is_up (ifp))
            {
                ifp->flags = ifi->ifi_flags & 0x0000fffff;
                if (! if_is_up (ifp))
                    if_down (ifp);
            }
            else
            {
                ifp->flags = ifi->ifi_flags & 0x0000fffff;
                if (if_is_up (ifp))
                    if_up (ifp);
            }
        }
    }
    else
    {
        /* RTM_DELLINK. */
        ifp = if_lookup_by_name (name);

        if (ifp == NULL)
        {
            zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
                  ifp->name);
            return 0;
        }

        if_delete_update (ifp);
    }

    return 0;
}
Пример #28
0
static int
if_getaddrs (void)
{
  int ret;
  struct ifaddrs *ifap;
  struct ifaddrs *ifapfree;
  struct interface *ifp;
  int prefixlen;

  ret = getifaddrs (&ifap); 
  if (ret != 0)
    {
      zlog_err ("getifaddrs(): %s", safe_strerror (errno));
      return -1;
    }

  for (ifapfree = ifap; ifap; ifap = ifap->ifa_next)
    {
      if (ifap->ifa_addr == NULL)
        {
          zlog_err ("%s: nonsensical ifaddr with NULL ifa_addr, ifname %s",
                    __func__, (ifap->ifa_name ? ifap->ifa_name : "(null)"));
          continue;
        }
       
      ifp = if_lookup_by_name (ifap->ifa_name);
      if (ifp == NULL)
	{
	  zlog_err ("if_getaddrs(): Can't lookup interface %s\n",
		    ifap->ifa_name);
	  continue;
	}

      if (ifap->ifa_addr->sa_family == AF_INET)
	{
	  struct sockaddr_in *addr;
	  struct sockaddr_in *mask;
	  struct sockaddr_in *dest;
	  struct in_addr *dest_pnt;

	  addr = (struct sockaddr_in *) ifap->ifa_addr;
	  mask = (struct sockaddr_in *) ifap->ifa_netmask;
	  prefixlen = ip_masklen (mask->sin_addr);

	  dest_pnt = NULL;

	  if (ifap->ifa_flags & IFF_POINTOPOINT) 
	    {
	      dest = (struct sockaddr_in *) ifap->ifa_dstaddr;
	      dest_pnt = &dest->sin_addr;
	    }

	  if (ifap->ifa_flags & IFF_BROADCAST)
	    {
	      dest = (struct sockaddr_in *) ifap->ifa_broadaddr;
	      dest_pnt = &dest->sin_addr;
	    }

	  connected_add_ipv4 (ifp, 0, &addr->sin_addr,
			      prefixlen, dest_pnt, NULL);
	}
#ifdef HAVE_IPV6
      if (ifap->ifa_addr->sa_family == AF_INET6)
	{
	  struct sockaddr_in6 *addr;
	  struct sockaddr_in6 *mask;
	  struct sockaddr_in6 *dest;
	  struct in6_addr *dest_pnt;

	  addr = (struct sockaddr_in6 *) ifap->ifa_addr;
	  mask = (struct sockaddr_in6 *) ifap->ifa_netmask;
	  prefixlen = ip6_masklen (mask->sin6_addr);

	  dest_pnt = NULL;

	  if (ifap->ifa_flags & IFF_POINTOPOINT) 
	    {
	      if (ifap->ifa_dstaddr)
		{
		  dest = (struct sockaddr_in6 *) ifap->ifa_dstaddr;
		  dest_pnt = &dest->sin6_addr;
		}
	    }

	  if (ifap->ifa_flags & IFF_BROADCAST)
	    {
	      if (ifap->ifa_broadaddr)
		{
		  dest = (struct sockaddr_in6 *) ifap->ifa_broadaddr;
		  dest_pnt = &dest->sin6_addr;
		}
	    }

#if defined(KAME)
	  if (IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) 
	    {
	      addr->sin6_scope_id =
			ntohs(*(u_int16_t *)&addr->sin6_addr.s6_addr[2]);
	      addr->sin6_addr.s6_addr[2] = addr->sin6_addr.s6_addr[3] = 0;
	    }	
#endif          

	  connected_add_ipv6 (ifp, &addr->sin6_addr, prefixlen, 
	                      dest_pnt, NULL);
	}
#endif /* HAVE_IPV6 */
    }

  freeifaddrs (ifapfree);

  return 0; 
}