示例#1
0
文件: nhrp_route.c 项目: ton31337/frr
enum nhrp_route_type nhrp_route_address(struct interface *in_ifp,
					union sockunion *addr, struct prefix *p,
					struct nhrp_peer **peer)
{
	struct interface *ifp = in_ifp;
	struct nhrp_interface *nifp;
	struct nhrp_cache *c;
	union sockunion via[4];
	uint32_t network_id = 0;
	afi_t afi = family2afi(sockunion_family(addr));
	int i;

	if (ifp) {
		nifp = ifp->info;
		network_id = nifp->afi[afi].network_id;

		c = nhrp_cache_get(ifp, addr, 0);
		if (c && c->cur.type == NHRP_CACHE_LOCAL) {
			if (p)
				memset(p, 0, sizeof(*p));
			return NHRP_ROUTE_LOCAL;
		}
	}

	for (i = 0; i < 4; i++) {
		if (!nhrp_route_get_nexthop(addr, p, &via[i], &ifp))
			return NHRP_ROUTE_BLACKHOLE;
		if (ifp) {
			/* Departing from nbma network? */
			nifp = ifp->info;
			if (network_id
			    && network_id != nifp->afi[afi].network_id)
				return NHRP_ROUTE_OFF_NBMA;
		}
		if (sockunion_family(&via[i]) == AF_UNSPEC)
			break;
		/* Resolve via node, but return the prefix of first match */
		addr = &via[i];
		p = NULL;
	}

	if (ifp) {
		c = nhrp_cache_get(ifp, addr, 0);
		if (c && c->cur.type >= NHRP_CACHE_DYNAMIC) {
			if (p)
				memset(p, 0, sizeof(*p));
			if (c->cur.type == NHRP_CACHE_LOCAL)
				return NHRP_ROUTE_LOCAL;
			if (peer)
				*peer = nhrp_peer_ref(c->cur.peer);
			return NHRP_ROUTE_NBMA_NEXTHOP;
		}
	}

	return NHRP_ROUTE_BLACKHOLE;
}
示例#2
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);
}
示例#3
0
/* BGP try to connect to the peer.  */
int
bgp_connect (struct peer *peer)
{
  unsigned int ifindex = 0;

  /* Make socket for the peer. */
  peer->fd = sockunion_socket (&peer->su);
  if (peer->fd < 0)
    return -1;

  /* If we can get socket for the peer, adjest TTL and make connection. */
  if (peer->sort == BGP_PEER_EBGP) {
    sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
    if (peer->gtsm_hops)
      sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - peer->gtsm_hops);
  }

  sockopt_reuseaddr (peer->fd);
  sockopt_reuseport (peer->fd);
  
#ifdef IPTOS_PREC_INTERNETCONTROL
  if (bgpd_privs.change (ZPRIVS_RAISE))
    zlog_err ("%s: could not raise privs", __func__);
  if (sockunion_family (&peer->su) == AF_INET)
    setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL);
# ifdef HAVE_IPV6
  else if (sockunion_family (&peer->su) == AF_INET6)
    setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL);
# endif
  if (bgpd_privs.change (ZPRIVS_LOWER))
    zlog_err ("%s: could not lower privs", __func__);
#endif

  if (peer->password)
    bgp_md5_set_connect (peer->fd, &peer->su, peer->password);

  /* Bind socket. */
  bgp_bind (peer);

  /* Update source bind. */
  bgp_update_source (peer);

#ifdef HAVE_IPV6
  if (peer->ifname)
    ifindex = if_nametoindex (peer->ifname);
#endif /* HAVE_IPV6 */

  if (BGP_DEBUG (events, EVENTS))
    plog_debug (peer->log, "%s [Event] Connect start to %s fd %d",
	       peer->host, peer->host, peer->fd);

  /* Connect to the remote peer. */
  return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex);
}
/* BGP try to connect to the peer.  */
int
bgp_connect (struct peer *peer)
{
  unsigned int ifindex = 0;

  /* Make socket for the peer. */
  peer->fd = sockunion_socket (&peer->su);
  if (peer->fd < 0)
    return -1;

  set_nonblocking (peer->fd);

  /* Set socket send buffer size */
  bgp_update_sock_send_buffer_size(peer->fd);

  bgp_set_socket_ttl (peer, peer->fd);

  sockopt_reuseaddr (peer->fd);
  sockopt_reuseport (peer->fd);
  
#ifdef IPTOS_PREC_INTERNETCONTROL
  if (bgpd_privs.change (ZPRIVS_RAISE))
    zlog_err ("%s: could not raise privs", __func__);
  if (sockunion_family (&peer->su) == AF_INET)
    setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL);
# ifdef HAVE_IPV6
  else if (sockunion_family (&peer->su) == AF_INET6)
    setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL);
# endif
  if (bgpd_privs.change (ZPRIVS_LOWER))
    zlog_err ("%s: could not lower privs", __func__);
#endif

  if (peer->password)
    bgp_md5_set_connect (peer->fd, &peer->su, peer->password);

  /* Bind socket. */
  bgp_bind (peer);

  /* Update source bind. */
  bgp_update_source (peer);

#ifdef HAVE_IPV6
  if (peer->ifname)
    ifindex = if_nametoindex (peer->ifname);
#endif /* HAVE_IPV6 */

  if (BGP_DEBUG (events, EVENTS))
    plog_debug (peer->log, "%s [Event] Connect start to %s fd %d",
	       peer->host, peer->host, peer->fd);

  /* Connect to the remote peer. */
  return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex);
}
示例#5
0
const char *sockunion2str(const union sockunion *su, char *buf, size_t len)
{
	switch (sockunion_family(su)) {
	case AF_UNSPEC:
		snprintf(buf, len, "(unspec)");
		return buf;
	case AF_INET:
		return inet_ntop(AF_INET, &su->sin.sin_addr, buf, len);
	case AF_INET6:
		return inet_ntop(AF_INET6, &su->sin6.sin6_addr, buf, len);
	}
	snprintf(buf, len, "(af %d)", sockunion_family(su));
	return buf;
}
示例#6
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;
}
示例#7
0
const uint8_t *sockunion_get_addr(const union sockunion *su)
{
	switch (sockunion_family(su)) {
	case AF_INET:
		return (const uint8_t *)&su->sin.sin_addr.s_addr;
	case AF_INET6:
		return (const uint8_t *)&su->sin6.sin6_addr;
	}
	return NULL;
}
示例#8
0
unsigned int sockunion_hash(const union sockunion *su)
{
	switch (sockunion_family(su)) {
	case AF_INET:
		return jhash_1word(su->sin.sin_addr.s_addr, 0);
	case AF_INET6:
		return jhash2(su->sin6.sin6_addr.s6_addr32,
			      ZEBRA_NUM_OF(su->sin6.sin6_addr.s6_addr32), 0);
	}
	return 0;
}
示例#9
0
文件: nhrp_route.c 项目: ton31337/frr
static void nhrp_route_update_put(struct route_node *rn)
{
	struct route_info *ri = rn->info;

	if (!ri->ifp && !ri->nhrp_ifp
	    && sockunion_family(&ri->via) == AF_UNSPEC) {
		XFREE(MTYPE_NHRP_ROUTE, rn->info);
		rn->info = NULL;
		route_unlock_node(rn);
	}
	route_unlock_node(rn);
}
示例#10
0
文件: nhrp_route.c 项目: ton31337/frr
int nhrp_route_get_nexthop(const union sockunion *addr, struct prefix *p,
			   union sockunion *via, struct interface **ifp)
{
	struct route_node *rn;
	struct route_info *ri;
	struct prefix lookup;
	afi_t afi = family2afi(sockunion_family(addr));
	char buf[PREFIX_STRLEN];

	sockunion2hostprefix(addr, &lookup);

	rn = route_node_match(zebra_rib[afi], &lookup);
	if (!rn)
		return 0;

	ri = rn->info;
	if (ri->nhrp_ifp) {
		debugf(NHRP_DEBUG_ROUTE, "lookup %s: nhrp_if=%s",
		       prefix2str(&lookup, buf, sizeof buf),
		       ri->nhrp_ifp->name);

		if (via)
			sockunion_family(via) = AF_UNSPEC;
		if (ifp)
			*ifp = ri->nhrp_ifp;
	} else {
		debugf(NHRP_DEBUG_ROUTE, "lookup %s: zebra route dev %s",
		       prefix2str(&lookup, buf, sizeof buf),
		       ri->ifp ? ri->ifp->name : "(none)");

		if (via)
			*via = ri->via;
		if (ifp)
			*ifp = ri->ifp;
	}
	if (p)
		*p = rn->p;
	route_unlock_node(rn);
	return 1;
}
示例#11
0
void sockunion_set(union sockunion *su, int family, const uint8_t *addr,
		   size_t bytes)
{
	if (family2addrsize(family) != bytes)
		return;

	sockunion_family(su) = family;
	switch (family) {
	case AF_INET:
		memcpy(&su->sin.sin_addr.s_addr, addr, bytes);
		break;
	case AF_INET6:
		memcpy(&su->sin6.sin6_addr, addr, bytes);
		break;
	}
}
示例#12
0
文件: nhrp_route.c 项目: ton31337/frr
static void nhrp_route_update_zebra(const struct prefix *p,
				    union sockunion *nexthop,
				    struct interface *ifp)
{
	struct route_node *rn;
	struct route_info *ri;

	rn = nhrp_route_update_get(
		p, (sockunion_family(nexthop) != AF_UNSPEC) || ifp);
	if (rn) {
		ri = rn->info;
		ri->via = *nexthop;
		ri->ifp = ifp;
		nhrp_route_update_put(rn);
	}
}
示例#13
0
文件: nhrp_route.c 项目: ton31337/frr
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;
}
示例#14
0
void nhrp_interface_update(struct interface *ifp)
{
	struct nhrp_interface *nifp = ifp->info;
	struct nhrp_afi_data *if_ad;
	afi_t afi;
	int enabled = 0;

	notifier_call(&nifp->notifier_list, NOTIFY_INTERFACE_CHANGED);

	for (afi = 0; afi < AFI_MAX; afi++) {
		if_ad = &nifp->afi[afi];

		if (sockunion_family(&nifp->nbma) == AF_UNSPEC ||
		    ifp->ifindex == IFINDEX_INTERNAL || !if_is_up(ifp) ||
		    !if_ad->network_id) {
			if (if_ad->configured) {
				if_ad->configured = 0;
				nhrp_interface_update_address(ifp, afi, 1);
			}
			continue;
		}

		if (!if_ad->configured) {
			os_configure_dmvpn(ifp->ifindex, ifp->name, afi2family(afi));
			if_ad->configured = 1;
			nhrp_interface_update_address(ifp, afi, 1);
		}

		enabled = 1;
	}

	if (enabled != nifp->enabled) {
		nifp->enabled = enabled;
		notifier_call(&nifp->notifier_list, enabled ? NOTIFY_INTERFACE_UP : NOTIFY_INTERFACE_DOWN);
	}
}
示例#15
0
/* BGP Peer General TCP Socket Option Settings */
s_int32_t
bpn_sock_set_opt (struct bgp_peer *peer,
                  pal_sock_handle_t sck_fd,
                  bool_t do_bind)
{
  fib_id_t fib_id;
  s_int32_t ret;
  int flags = 1;


  fib_id = LIB_VRF_GET_FIB_ID (peer->bgp->owning_ivrf);
  ret = 0;

  /* set socket as ipv6 only */
  if (peer->su.sa.sa_family == AF_INET6)
    {
      ret = setsockopt(sck_fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &flags, sizeof(flags));
      if (ret < 0)
        {
          zlog_err (&BLG, "%s-%s [NETWORK] Set Sock Opt: "
                    "failed to set option: Sock = %d",
                    peer->host, BGP_PEER_DIR_STR (peer), sck_fd);
        }
    }

  /* Set Socket as Non-blocking */
  pal_sock_set_nonblocking (sck_fd, PAL_TRUE);

  /* Set Socket to reuse Addr and Port */
  ret = pal_sock_set_reuseaddr (sck_fd, PAL_TRUE);
  if (ret < 0)
    {
      zlog_err (&BLG, "%s-%s [NETWORK] Set Sock Opt: "
                "failed to reuse addr: Sock %d",
                peer->host, BGP_PEER_DIR_STR (peer), sck_fd);

      return ret;
    }
  pal_sock_set_reuseport (sck_fd, PAL_TRUE);

  /* Set TTL for EBGP peers */
  if (peer_sort (peer) == BGP_PEER_EBGP)
    {
      if (peer->su.sa.sa_family == AF_INET)
        ret = (s_int32_t)pal_sock_set_ipv4_unicast_hops (sck_fd, peer->ttl);
#ifdef HAVE_IPV6
      else if (BGP_CAP_HAVE_IPV6
               && peer->su.sa.sa_family == AF_INET6)
        ret = (s_int32_t)pal_sock_set_ipv6_hoplimit (sck_fd, peer->ttl);
#endif /* HAVE_IPV6 */
      
      if (ret < 0)
        zlog_warn (&BLG, "Can't set Hop Limit: %s(%d)",    
	           pal_strerror (errno), errno);
    }

  if (PAL_TRUE == do_bind)
    {
      /* Bind socket to FIB */
      ret = pal_sock_set_bindtofib (sck_fd, fib_id);
      if (ret < 0)
        {
          zlog_err (&BLG, "%s-%s [NETWORK] Set Sock Opt: Failed to bind "
              "Sock %d to FIB with VRF-ID %d",
              peer->host, BGP_PEER_DIR_STR (peer), sck_fd, fib_id);

          return ret;
        }
    }

  /* Bind Socket to Interface */
#ifdef SO_BINDTODEVICE
  if (peer->ifname)
    {
      ret = pal_sock_set_bindtodevice (sck_fd, peer->ifname);
      if (ret < 0)
        {
          zlog_err (&BLG, "%s-%s [NETWORK] Set Sock Opt: Failed to "
                    "bind Sock %d to IF %s", peer->host,
                    BGP_PEER_DIR_STR (peer), sck_fd, peer->ifname);

          return ret;
        }
    }
#endif /* SO_BINDTODEVICE */

  /* Update-source address bind */
  if (do_bind == PAL_TRUE)
    {
      ret = bpn_sock_bind_address (peer, sck_fd);
      if (ret < 0)
        {
          zlog_err (&BLG, "%s-%s [NETWORK] Set Sock Opt: Update-source "
                    "failed on Sock %d", peer->host,
                    BGP_PEER_DIR_STR (peer), sck_fd);

          return ret;
        }
    }

  /* Set TCP MD5 authentication */
#ifdef HAVE_TCP_MD5SIG
  if (CHECK_FLAG (peer->config, PEER_CONFIG_PASSWORD))
    if (sockunion_family (&peer->su) == AF_INET)
      bgp_md5_set (sck_fd, &peer->su.sin.sin_addr, peer->password);
#endif /* TCP_MD5SIG */

  return ret;
}
示例#16
0
static void
bgp_dump_routes_index_table(struct bgp *bgp)
{
  struct peer *peer;
  struct listnode *node;
  uint16_t peerno = 0;
  struct stream *obuf;

  obuf = bgp_dump_obuf;
  stream_reset (obuf);

  /* MRT header */
  bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE,
		   BGP_DUMP_ROUTES);

  /* Collector BGP ID */
  stream_put_in_addr (obuf, &bgp->router_id);

  /* View name */
  if(bgp->name)
    {
      stream_putw (obuf, strlen(bgp->name));
      stream_put(obuf, bgp->name, strlen(bgp->name));
    }
  else
    {
      stream_putw(obuf, 0);
    }

  /* Peer count */
  stream_putw (obuf, listcount(bgp->peer));

  /* Walk down all peers */
  for(ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
    {

      /* Peer's type */
      if (sockunion_family(&peer->su) == AF_INET)
        {
          stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP);
        }
      else if (sockunion_family(&peer->su) == AF_INET6)
        {
          stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6);
        }

      /* Peer's BGP ID */
      stream_put_in_addr (obuf, &peer->remote_id);

      /* Peer's IP address */
      if (sockunion_family(&peer->su) == AF_INET)
        {
          stream_put_in_addr (obuf, &peer->su.sin.sin_addr);
        }
      else if (sockunion_family(&peer->su) == AF_INET6)
        {
          stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr,
                        IPV6_MAX_BYTELEN);
        }

      /* Peer's AS number. */
      /* Note that, as this is an AS4 compliant quagga, the RIB is always AS4 */
      stream_putl (obuf, peer->as);

      /* Store the peer number for this peer */
      peer->table_dump_index = peerno;
      peerno++;
    }

  bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2);

  fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp);
  fflush (bgp_dump_routes.fp);
}
示例#17
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;
}
示例#18
0
/* Address read from struct ifa_msghdr. */
static void
ifam_read_mesg (struct ifa_msghdr *ifm,
		union sockunion *addr,
		union sockunion *mask,
		union sockunion *brd,
		char *ifname,
		short *ifnlen)
{
  caddr_t pnt, end;
  union sockunion dst;
  union sockunion gateway;

  pnt = (caddr_t)(ifm + 1);
  end = ((caddr_t)ifm) + ifm->ifam_msglen;

  /* Be sure structure is cleared */
  memset (mask, 0, sizeof (union sockunion));
  memset (addr, 0, sizeof (union sockunion));
  memset (brd, 0, sizeof (union sockunion));
  memset (&dst, 0, sizeof (union sockunion));
  memset (&gateway, 0, sizeof (union sockunion));

  /* We fetch each socket variable into sockunion. */
  RTA_ADDR_GET (&dst, RTA_DST, ifm->ifam_addrs, pnt);
  RTA_ADDR_GET (&gateway, RTA_GATEWAY, ifm->ifam_addrs, pnt);
  RTA_ATTR_GET (mask, RTA_NETMASK, ifm->ifam_addrs, pnt);
  RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifam_addrs, pnt);
  RTA_NAME_GET (ifname, RTA_IFP, ifm->ifam_addrs, pnt, *ifnlen);
  RTA_ADDR_GET (addr, RTA_IFA, ifm->ifam_addrs, pnt);
  RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt);
  RTA_ADDR_GET (brd, RTA_BRD, ifm->ifam_addrs, pnt);

  if (IS_ZEBRA_DEBUG_KERNEL)
    {
      switch (sockunion_family(addr))
        {
	case AF_INET:
	  {
	    char buf[4][INET_ADDRSTRLEN];
	    zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x, "
			"ifam_flags 0x%x, addr %s/%d broad %s dst %s "
			"gateway %s",
			__func__, ifm->ifam_index,
			(ifnlen ? ifname : "(nil)"), ifm->ifam_addrs,
			ifm->ifam_flags,
			inet_ntop(AF_INET,&addr->sin.sin_addr,
			          buf[0],sizeof(buf[0])),
			ip_masklen(mask->sin.sin_addr),
			inet_ntop(AF_INET,&brd->sin.sin_addr,
			          buf[1],sizeof(buf[1])),
			inet_ntop(AF_INET,&dst.sin.sin_addr,
			          buf[2],sizeof(buf[2])),
			inet_ntop(AF_INET,&gateway.sin.sin_addr,
			          buf[3],sizeof(buf[3])));
	  }
	  break;
#ifdef HAVE_IPV6
	case AF_INET6:
	  {
	    char buf[4][INET6_ADDRSTRLEN];
	    zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x, "
			"ifam_flags 0x%x, addr %s/%d broad %s dst %s "
			"gateway %s",
			__func__, ifm->ifam_index, 
			(ifnlen ? ifname : "(nil)"), ifm->ifam_addrs,
			ifm->ifam_flags,
			inet_ntop(AF_INET6,&addr->sin6.sin6_addr,
			          buf[0],sizeof(buf[0])),
			ip6_masklen(mask->sin6.sin6_addr),
			inet_ntop(AF_INET6,&brd->sin6.sin6_addr,
			          buf[1],sizeof(buf[1])),
			inet_ntop(AF_INET6,&dst.sin6.sin6_addr,
			          buf[2],sizeof(buf[2])),
			inet_ntop(AF_INET6,&gateway.sin6.sin6_addr,
			          buf[3],sizeof(buf[3])));
	  }
	  break;
#endif /* HAVE_IPV6 */
        default:
	  zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x",
		      __func__, ifm->ifam_index, 
		      (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs);
	  break;
        }
    }

  /* Assert read up end point matches to end point */
  if (pnt != end)
    zlog_warn ("ifam_read() does't read all socket data");
}
示例#19
0
/* BGP try to connect to the peer.  */
int bgp_connect(struct peer *peer)
{
	assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
	assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
	ifindex_t ifindex = 0;

	if (peer->conf_if && BGP_PEER_SU_UNSPEC(peer)) {
		zlog_debug("Peer address not learnt: Returning from connect");
		return 0;
	}
	frr_elevate_privs(&bgpd_privs) {
	/* Make socket for the peer. */
		peer->fd = vrf_sockunion_socket(&peer->su, peer->bgp->vrf_id,
						bgp_get_bound_name(peer));
	}
	if (peer->fd < 0)
		return -1;

	set_nonblocking(peer->fd);

	/* Set socket send buffer size */
	setsockopt_so_sendbuf(peer->fd, BGP_SOCKET_SNDBUF_SIZE);

	if (bgp_set_socket_ttl(peer, peer->fd) < 0)
		return -1;

	sockopt_reuseaddr(peer->fd);
	sockopt_reuseport(peer->fd);

#ifdef IPTOS_PREC_INTERNETCONTROL
	frr_elevate_privs(&bgpd_privs) {
		if (sockunion_family(&peer->su) == AF_INET)
			setsockopt_ipv4_tos(peer->fd,
					    IPTOS_PREC_INTERNETCONTROL);
		else if (sockunion_family(&peer->su) == AF_INET6)
			setsockopt_ipv6_tclass(peer->fd,
					       IPTOS_PREC_INTERNETCONTROL);
	}
#endif

	if (peer->password) {
		uint16_t prefixlen = peer->su.sa.sa_family == AF_INET
					     ? IPV4_MAX_PREFIXLEN
					     : IPV6_MAX_PREFIXLEN;

		bgp_md5_set_connect(peer->fd, &peer->su, prefixlen,
				    peer->password);
	}

	/* Update source bind. */
	if (bgp_update_source(peer) < 0) {
		return connect_error;
	}

	if (peer->conf_if || peer->ifname)
		ifindex = ifname2ifindex(peer->conf_if ? peer->conf_if
						       : peer->ifname,
					 peer->bgp->vrf_id);

	if (bgp_debug_neighbor_events(peer))
		zlog_debug("%s [Event] Connect start to %s fd %d", peer->host,
			   peer->host, peer->fd);

	/* Connect to the remote peer. */
	return sockunion_connect(peer->fd, &peer->su, htons(peer->port),
				 ifindex);
}
示例#20
0
static void nhrp_interface_update_address(struct interface *ifp, afi_t afi, int force)
{
	const int family = afi2family(afi);
	struct nhrp_interface *nifp = ifp->info;
	struct nhrp_afi_data *if_ad = &nifp->afi[afi];
	struct nhrp_cache *nc;
	struct connected *c, *best;
	struct listnode *cnode;
	union sockunion addr;
	char buf[PREFIX_STRLEN];

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

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

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

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

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

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

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

	notifier_call(&nifp->notifier_list, NOTIFY_INTERFACE_ADDRESS_CHANGED);
}
示例#21
0
size_t sockunion_get_addrlen(const union sockunion *su)
{
	return family2addrsize(sockunion_family(su));
}
示例#22
0
/* BGP try to connect to the peer. */
int bgp_connect (struct peer *peer)
{
printf("\n BGP CONNECT: I am in BGP Connect\n");
unsigned int ifindex = 0;
/*setting up TLS for a second*/


printf("\n BGP CONNECT: I am just about to initialise SSL\n");

ssl_init();		//initialise the library, method, contact of ssl session, returns nothing

if(BGPTLS.psCTX==NULL)
	{
		printf("\n BGP CONNECT: There is no entry in the .psCTX pointer \n");
	}
else 
	{
		printf("\n BGP CONNECT: There is an entry in the .psCTX pointer, it is %i \n", BGPTLS_sess_server.psCTX);
	}

printf("\n BGP CONNECT: There is an entry in the .psCTX pointer: ");
printf("%i \n", BGPTLS.psCTX);

/*if (SSL_CTX_use_certificate_chain_file(BGPTLS_sess_server.psCTX,"/usr/home/dugald/subcert.pem")!=1)
{
	printf("Error loading certificate from file");
}
else
{
	printf("Certificate has loaded correctly");
} */

/* Make socket for the peer. */
printf("BGP CONNECT: Here's sockets");
peer->fd = sockunion_socket (&peer->su);

SSL_connect(BGPTLS->ssl);


if (peer->fd < 0)
	return -1;


	/* If we can get socket for the peer, adjest TTL and make connection. */
if (peer->sort == BGP_PEER_EBGP) 
{
	sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
	if (peer->gtsm_hops)
		sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - peer->gtsm_hops);
}

sockopt_reuseaddr (peer->fd);
sockopt_reuseport (peer->fd);

#ifdef IPTOS_PREC_INTERNETCONTROL

if (bgpd_privs.change (ZPRIVS_RAISE))
	zlog_err ("%s: could not raise privs", __func__);
if (sockunion_family (&peer->su) == AF_INET)
	setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL);

# ifdef HAVE_IPV6
else if (sockunion_family (&peer->su) == AF_INET6)
	setsockopt_ipv6_tclass (peer->fd, IPTOS_PREC_INTERNETCONTROL);
# endif

if (bgpd_privs.change (ZPRIVS_LOWER))
	zlog_err ("%s: could not lower privs", __func__);
#endif

if (peer->password)
	bgp_md5_set_connect (peer->fd, &peer->su, peer->password);

/* Bind socket. */
//bgp_bind (peer);

/* Update source bind. */
//bgp_update_source (peer);

#ifdef HAVE_IPV6
if (peer->ifname)
	ifindex = if_nametoindex (peer->ifname);
#endif /* HAVE_IPV6 */


if (BGP_DEBUG (events, EVENTS))
	plog_debug (peer->log, "%s [Event] Connect start to %s fd %d", peer->host, peer->host, peer->fd);


/* Connect to the remote peer. */
return sockunion_connect (peer->fd, &peer->su, htons (peer->port), ifindex);
}