/* 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; }
/* 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; }
/* 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; }
unsigned int ifname2ifindex (const char *name) { struct interface *ifp; return ((ifp = if_lookup_by_name(name)) != NULL) ? ifp->ifIndex : -1; }
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; }
/* 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)); }
/* * 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; }
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); }
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); }
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; }
/* 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; }
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); }
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; }
/* 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); }
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; }
/**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); }
/* 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; }
/* 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)); }
/* 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; }
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; }
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; }
/* 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; }
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); }
/* * 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; }
/* * 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 }
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; }
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; }