/* Add connected IPv6 route to the interface. */ void connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr, u_char prefixlen, struct in6_addr *broad, const char *label) { struct prefix_ipv6 *p; struct connected *ifc; /* Make connected structure. */ ifc = connected_new (); ifc->ifp = ifp; ifc->flags = flags; /* If we get a notification from the kernel, * we can safely assume the address is known to the kernel */ SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); /* Allocate new connected address. */ p = prefix_ipv6_new (); p->family = AF_INET6; IPV6_ADDR_COPY (&p->prefix, addr); p->prefixlen = prefixlen; ifc->address = (struct prefix *) p; /* If there is broadcast or peer address. */ if (broad) { if (IN6_IS_ADDR_UNSPECIFIED(broad)) zlog_warn("warning: %s called for interface %s with unspecified " "destination address; ignoring!", __func__, ifp->name); else { p = prefix_ipv6_new (); p->family = AF_INET6; IPV6_ADDR_COPY (&p->prefix, broad); p->prefixlen = prefixlen; ifc->destination = (struct prefix *) p; } } if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination) { zlog_warn("warning: %s called for interface %s " "with peer flag set, but no peer address supplied", __func__, ifp->name); UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); } /* Label of this address. */ if (label) ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); /* On Linux, we only get here when DAD is complete, therefore we can set * ZEBRA_IFC_REAL. * * On BSD, there currently doesn't seem to be a way to check for completion of * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, although DAD * might still be running. */ SET_FLAG(ifc->conf, ZEBRA_IFC_REAL); connected_update(ifp, ifc); }
/* Add connected IPv6 route to the interface. */ void connected_add_ipv6 (struct interface *ifp, int flags, struct in6_addr *addr, u_char prefixlen, struct in6_addr *broad, const char *label) { struct prefix_ipv6 *p; struct connected *ifc; /* Make connected structure. */ ifc = connected_new (); ifc->ifp = ifp; ifc->flags = flags; /* Allocate new connected address. */ p = prefix_ipv6_new (); p->family = AF_INET6; IPV6_ADDR_COPY (&p->prefix, addr); p->prefixlen = prefixlen; ifc->address = (struct prefix *) p; /* If there is broadcast or peer address. */ if (broad) { if (IN6_IS_ADDR_UNSPECIFIED(broad)) zlog_warn("warning: %s called for interface %s with unspecified " "destination address; ignoring!", __func__, ifp->name); else { p = prefix_ipv6_new (); p->family = AF_INET6; IPV6_ADDR_COPY (&p->prefix, broad); p->prefixlen = prefixlen; ifc->destination = (struct prefix *) p; } } if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER) && !ifc->destination) { zlog_warn("warning: %s called for interface %s " "with peer flag set, but no peer address supplied", __func__, ifp->name); UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER); } /* Label of this address. */ if (label) ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL) return; connected_announce (ifp, ifc); }
pcp_errno psd_add_pcp_server(pcp_ctx_t *ctx, struct sockaddr *sa, uint8_t version) { struct in6_addr pcp_ip=IN6ADDR_ANY_INIT; uint16_t pcp_port; uint32_t scope_id=0; pcp_server_t *pcps=NULL; PCP_LOG_BEGIN(PCP_LOGLVL_DEBUG); if (sa->sa_family == AF_INET) { S6_ADDR32(&pcp_ip)[0]=0; S6_ADDR32(&pcp_ip)[1]=0; S6_ADDR32(&pcp_ip)[2]=htonl(0xFFFF); S6_ADDR32(&pcp_ip)[3]=((struct sockaddr_in *)sa)->sin_addr.s_addr; pcp_port=((struct sockaddr_in *)sa)->sin_port; } else { IPV6_ADDR_COPY(&pcp_ip, &((struct sockaddr_in6*)sa)->sin6_addr); pcp_port=((struct sockaddr_in6 *)sa)->sin6_port; scope_id=((struct sockaddr_in6 *)sa)->sin6_scope_id; } if (!pcp_port) { pcp_port=ntohs(PCP_SERVER_PORT); } pcps=get_pcp_server_by_ip(ctx, (struct in6_addr *)&pcp_ip); if (!pcps) { int pcps_indx=pcp_new_server(ctx, &pcp_ip, pcp_port, scope_id); if (pcps_indx >= 0) { pcps=get_pcp_server(ctx, pcps_indx); } if (pcps == NULL) { PCP_LOG(PCP_LOGLVL_ERR, "%s", "Can't add PCP server.\n"); PCP_LOG_END(PCP_LOGLVL_DEBUG); return PCP_ERR_UNKNOWN; } } else { pcps->pcp_port=pcp_port; } pcps->pcp_version=version; pcps->server_state=pss_allocated; if (psd_fill_pcp_server_src(pcps)) { pcps->server_state=pss_unitialized; PCP_LOG(PCP_LOGLVL_INFO, "Failed to add PCP server %s", pcps->pcp_server_paddr); PCP_LOG_END(PCP_LOGLVL_DEBUG); return PCP_ERR_UNKNOWN; } PCP_LOG(PCP_LOGLVL_INFO, "Added PCP server %s", pcps->pcp_server_paddr); PCP_LOG_END(PCP_LOGLVL_DEBUG); return (pcp_errno)pcps->index; }
/* Add connected IPv6 route to the interface. */ void connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr, u_char prefixlen, struct in6_addr *broad, const char *label) { struct prefix_ipv6 *p; struct connected *ifc; /* Make connected structure. */ ifc = connected_new (); ifc->ifp = ifp; /* Allocate new connected address. */ p = prefix_ipv6_new (); p->family = AF_INET6; IPV6_ADDR_COPY (&p->prefix, addr); p->prefixlen = prefixlen; ifc->address = (struct prefix *) p; /* If there is broadcast or pointopoint address. */ if (broad) { p = prefix_ipv6_new (); p->family = AF_INET6; IPV6_ADDR_COPY (&p->prefix, broad); ifc->destination = (struct prefix *) p; } /* Label of this address. */ if (label) ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label); if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL) return; connected_announce (ifp, ifc); }
/* 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; }