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; }
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); }
/* 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); }
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; }
/* 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; }
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; }
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; }
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); }
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; }
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; } }
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); } }
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; }
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); } }
/* 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; }
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); }
/* 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; }
/* 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"); }
/* 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); }
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); }
size_t sockunion_get_addrlen(const union sockunion *su) { return family2addrsize(sockunion_family(su)); }
/* 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); }