boolean_t rdsv3_isloopback(ipaddr_t addr) { ip_stack_t *ipst; ipst = netstack_find_by_zoneid(GLOBAL_ZONEID)->netstack_ip; ASSERT(ipst != NULL); if (ip_type_v4(addr, ipst) != IRE_LOOPBACK) { netstack_rele(ipst->ips_netstack); return (B_FALSE); } netstack_rele(ipst->ips_netstack); return (B_TRUE); }
boolean_t rds_islocal(ipaddr_t addr) { ip_stack_t *ipst; ipst = netstack_find_by_zoneid(GLOBAL_ZONEID)->netstack_ip; ASSERT(ipst != NULL); if (ip_laddr_verify_v4(addr, ALL_ZONES, ipst, B_FALSE) == IPVL_BAD) { netstack_rele(ipst->ips_netstack); return (B_FALSE); } netstack_rele(ipst->ips_netstack); return (B_TRUE); }
/* ARGSUSED */ static void netstack_zone_destroy(zoneid_t zoneid, void *arg) { netstack_t *ns = (netstack_t *)arg; ASSERT(arg != NULL); mutex_enter(&ns->netstack_lock); ASSERT(ns->netstack_numzones > 0); ns->netstack_numzones--; if (ns->netstack_numzones != 0) { /* Stack instance being used by other zone */ mutex_exit(&ns->netstack_lock); ASSERT(ns->netstack_stackid == GLOBAL_NETSTACKID); /* Record that we a shared stack zone has gone away */ netstack_shared_zone_remove(zoneid); return; } /* * Set CLOSING so that netstack_find_by will not find it. */ ns->netstack_flags |= NSF_CLOSING; mutex_exit(&ns->netstack_lock); DTRACE_PROBE1(netstack__dec__numzones, netstack_t *, ns); /* No other thread can call zone_destroy for this stack */ /* * Decrease refcnt to account for the one in netstack_zone_init() */ netstack_rele(ns); }
/* * taskq function for nic events. */ void ip_ne_queue_func(void *arg) { hook_event_token_t hr; hook_nic_event_int_t *info = (hook_nic_event_int_t *)arg; ip_stack_t *ipst; netstack_t *ns; ns = netstack_find_by_stackid(info->hnei_stackid); if (ns == NULL) goto done; ipst = ns->netstack_ip; if (ipst == NULL) goto done; hr = (info->hnei_event.hne_protocol == ipst->ips_ipv6_net_data) ? ipst->ips_ipv6nicevents : ipst->ips_ipv4nicevents; (void) hook_run(info->hnei_event.hne_protocol->netd_hooks, hr, (hook_data_t)&info->hnei_event); done: if (ns != NULL) netstack_rele(ns); kmem_free(info->hnei_event.hne_data, info->hnei_event.hne_datalen); kmem_free(arg, sizeof (hook_nic_event_int_t)); }
/* ARGSUSED */ void ip_dce_reclaim(void *args) { netstack_handle_t nh; netstack_t *ns; netstack_next_init(&nh); while ((ns = netstack_next(&nh)) != NULL) { ip_dce_reclaim_stack(ns->netstack_ip); netstack_rele(ns); } netstack_next_fini(&nh); }
/* ARGSUSED */ void sctp_conn_reclaim(void *arg) { netstack_handle_t nh; netstack_t *ns; sctp_stack_t *sctps; extern pgcnt_t lotsfree, needfree; if (!sctp_do_reclaim) return; /* * The reclaim function may be called even when the system is not * really under memory pressure. */ if (freemem >= lotsfree + needfree) return; netstack_next_init(&nh); while ((ns = netstack_next(&nh)) != NULL) { int i; int64_t tot_assoc = 0; /* * During boot time, the first netstack_t is created and * initialized before SCTP has registered with the netstack * framework. If this reclaim function is called before SCTP * has finished its initialization, netstack_next() will * return the first netstack_t (since its netstack_flags is * not NSF_UNINIT). And its netstack_sctp will be NULL. We * need to catch it. * * All subsequent netstack_t creation will not have this * problem since the initialization is not finished until SCTP * has finished its own sctp_stack_t initialization. Hence * netstack_next() will not return one with NULL netstack_sctp. */ if ((sctps = ns->netstack_sctp) == NULL) { netstack_rele(ns); continue; } /* * Even if the system is under memory pressure, the reason may * not be because of SCTP activity. Check the number of * associations in each stack. If the number exceeds the * threshold (maxusers), turn on defensive mode. */ for (i = 0; i < sctps->sctps_sc_cnt; i++) tot_assoc += sctps->sctps_sc[i]->sctp_sc_assoc_cnt; if (tot_assoc < maxusers) { netstack_rele(ns); continue; } mutex_enter(&sctps->sctps_reclaim_lock); if (!sctps->sctps_reclaim) { sctps->sctps_reclaim = B_TRUE; sctps->sctps_reclaim_tid = timeout(sctp_reclaim_timer, sctps, MSEC_TO_TICK(sctps->sctps_reclaim_period)); SCTP_KSTAT(sctps, sctp_reclaim_cnt); } mutex_exit(&sctps->sctps_reclaim_lock); netstack_rele(ns); } netstack_next_fini(&nh); }
int ibcm_resolver_pr_lookup(ibcm_arp_streams_t *ib_s, ibt_ip_addr_t *dst_addr, ibt_ip_addr_t *src_addr, zoneid_t myzoneid) { ibcm_arp_prwqn_t *wqnp; ire_t *ire = NULL; ipif_t *ipif = NULL; ill_t *ill = NULL; ill_t *hwaddr_ill = NULL; ip_stack_t *ipst; ipaddr_t setsrcv4; in6_addr_t setsrcv6; IBCM_PRINT_IP("ibcm_arp_pr_lookup: SRC", src_addr); IBCM_PRINT_IP("ibcm_arp_pr_lookup: DST", dst_addr); if ((wqnp = ibcm_arp_create_prwqn(ib_s, dst_addr, src_addr)) == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_arp_create_prwqn failed"); ib_s->status = ENOMEM; return (1); } ipst = netstack_find_by_zoneid(myzoneid)->netstack_ip; if (dst_addr->family == AF_INET) { /* * get an ire for the destination adress. * Note that we can't use MATCH_IRE_ILL since that would * require that the first ill we find have ire_ill set. */ setsrcv4 = INADDR_ANY; ire = ire_route_recursive_v4(dst_addr->un.ip4addr, 0, NULL, myzoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, &setsrcv4, NULL, NULL); ASSERT(ire != NULL); if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_route_recursive_v4 failed"); ib_s->status = EFAULT; goto fail; } ill = ire_nexthop_ill(ire); if (ill == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_nexthop_ill failed"); ib_s->status = EFAULT; goto fail; } /* Pick a source address */ if (ip_select_source_v4(ill, setsrcv4, dst_addr->un.ip4addr, INADDR_ANY, myzoneid, ipst, &wqnp->src_addr.un.ip4addr, NULL, NULL) != 0) { ib_s->status = EADDRNOTAVAIL; goto fail; } wqnp->gateway.un.ip4addr = ire->ire_gateway_addr; wqnp->netmask.un.ip4addr = ire->ire_mask; wqnp->src_addr.family = wqnp->gateway.family = wqnp->netmask.family = AF_INET; } else if (dst_addr->family == AF_INET6) { /* * get an ire for the destination adress. * Note that we can't use MATCH_IRE_ILL since that would * require that the first ill we find have ire_ill set. Thus * we compare ire_ill against ipif_ill after the lookup. */ setsrcv6 = ipv6_all_zeros; ire = ire_route_recursive_v6(&dst_addr->un.ip6addr, 0, NULL, myzoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, &setsrcv6, NULL, NULL); ASSERT(ire != NULL); if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_route_recursive_v6 failed"); ib_s->status = EFAULT; goto fail; } ill = ire_nexthop_ill(ire); if (ill == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_nexthop_ill failed"); ib_s->status = EFAULT; goto fail; } /* Pick a source address */ if (ip_select_source_v6(ill, &setsrcv6, &dst_addr->un.ip6addr, myzoneid, ipst, B_FALSE, IPV6_PREFER_SRC_DEFAULT, &wqnp->src_addr.un.ip6addr, NULL, NULL) != 0) { ib_s->status = EADDRNOTAVAIL; goto fail; } wqnp->gateway.un.ip6addr = ire->ire_gateway_addr_v6; wqnp->netmask.un.ip6addr = ire->ire_mask_v6; wqnp->src_addr.family = wqnp->gateway.family = wqnp->netmask.family = AF_INET6; } (void) strlcpy(wqnp->ifname, ill->ill_name, sizeof (wqnp->ifname)); /* * For IPMP data addresses, we need to use the hardware address of the * interface bound to the given address. */ if (IS_IPMP(ill)) { if (wqnp->src_addr.family == AF_INET) { ipif = ipif_lookup_addr(wqnp->src_addr.un.ip4addr, ill, myzoneid, ipst); } else { ipif = ipif_lookup_addr_v6(&wqnp->src_addr.un.ip6addr, ill, myzoneid, ipst); } if (ipif == NULL) { ib_s->status = ENETUNREACH; goto fail; } if ((hwaddr_ill = ipmp_ipif_hold_bound_ill(ipif)) == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "no bound ill for IPMP interface %s", ill->ill_name); ib_s->status = EFAULT; goto fail; } } else { hwaddr_ill = ill; ill_refhold(hwaddr_ill); /* for symmetry */ } if ((ib_s->status = ibcm_arp_check_interface(hwaddr_ill)) != 0) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_arp_check_interface failed"); goto fail; } bcopy(hwaddr_ill->ill_phys_addr, &wqnp->src_mac, hwaddr_ill->ill_phys_addr_length); IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: outgoing if:%s", wqnp->ifname); /* * at this stage, we have the source address and the IB * interface, now get the destination mac address from * arp or ipv6 drivers */ ib_s->status = ibcm_nce_lookup(wqnp, ill, myzoneid); if (ib_s->status != 0) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_nce_lookup failed: %d", ib_s->status); goto fail; } ill_refrele(hwaddr_ill); ill_refrele(ill); ire_refrele(ire); if (ipif != NULL) ipif_refrele(ipif); netstack_rele(ipst->ips_netstack); IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: Return: 0x%p", wqnp); return (0); fail: if (hwaddr_ill != NULL) ill_refrele(hwaddr_ill); if (ill != NULL) ill_refrele(ill); if (ire != NULL) ire_refrele(ire); if (ipif != NULL) ipif_refrele(ipif); ibcm_arp_delete_prwqn(wqnp); netstack_rele(ipst->ips_netstack); return (1); }
int ibcm_resolver_pr_lookup(ibcm_arp_streams_t *ib_s, ibt_ip_addr_t *dst_addr, ibt_ip_addr_t *src_addr) { ibcm_arp_prwqn_t *wqnp; ire_t *ire = NULL; ipif_t *ipif = NULL; ill_t *ill = NULL; ill_t *hwaddr_ill = NULL; ip_stack_t *ipst; int len; ipaddr_t setsrcv4; in6_addr_t setsrcv6; IBCM_PRINT_IP("ibcm_arp_pr_lookup: SRC", src_addr); IBCM_PRINT_IP("ibcm_arp_pr_lookup: DST", dst_addr); if ((wqnp = ibcm_arp_create_prwqn(ib_s, dst_addr, src_addr)) == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_arp_create_prwqn failed"); ib_s->status = ENOMEM; return (1); } ipst = netstack_find_by_zoneid(GLOBAL_ZONEID)->netstack_ip; if (dst_addr->family == AF_INET) { /* * A local address is always specified, and it is used * to find the zoneid. */ ipif = ipif_lookup_addr(src_addr->un.ip4addr, NULL, ALL_ZONES, ipst); if (ipif == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ipif_lookup_addr failed"); ib_s->status = EFAULT; goto fail; } /* * get an ire for the destination adress. * Note that we can't use MATCH_IRE_ILL since that would * require that the first ill we find have ire_ill set. Thus * we compare ire_ill against ipif_ill after the lookup. */ setsrcv4 = INADDR_ANY; ire = ire_route_recursive_v4(dst_addr->un.ip4addr, 0, NULL, ipif->ipif_zoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, &setsrcv4, NULL, NULL); ASSERT(ire != NULL); if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_route_recursive_v4 failed"); ib_s->status = EFAULT; goto fail; } ill = ire_nexthop_ill(ire); if (ill == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_nexthop_ill failed"); ib_s->status = EFAULT; goto fail; } if (ill != ipif->ipif_ill) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "wrong ill"); ib_s->status = EFAULT; goto fail; } wqnp->gateway.un.ip4addr = ire->ire_gateway_addr; wqnp->netmask.un.ip4addr = ire->ire_mask; wqnp->src_addr.un.ip4addr = src_addr->un.ip4addr; wqnp->src_addr.family = wqnp->gateway.family = wqnp->netmask.family = AF_INET; } else if (dst_addr->family == AF_INET6) { /* * A local address is always specified, and it is used * to find the zoneid. * We should really match on scopeid for link locals here. */ ipif = ipif_lookup_addr_v6(&src_addr->un.ip6addr, NULL, ALL_ZONES, ipst); if (ipif == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ipif_lookup_addr_v6 failed"); ib_s->status = EFAULT; goto fail; } /* * get an ire for the destination adress. * Note that we can't use MATCH_IRE_ILL since that would * require that the first ill we find have ire_ill set. Thus * we compare ire_ill against ipif_ill after the lookup. */ setsrcv6 = ipv6_all_zeros; ire = ire_route_recursive_v6(&dst_addr->un.ip6addr, 0, NULL, ipif->ipif_zoneid, NULL, MATCH_IRE_DSTONLY, B_TRUE, 0, ipst, &setsrcv6, NULL, NULL); ASSERT(ire != NULL); if (ire->ire_flags & (RTF_REJECT|RTF_BLACKHOLE)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_route_recursive_v6 failed"); ib_s->status = EFAULT; goto fail; } ill = ire_nexthop_ill(ire); if (ill == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ire_nexthop_ill failed"); ib_s->status = EFAULT; goto fail; } if (ill != ipif->ipif_ill) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "wrong ill"); ib_s->status = EFAULT; goto fail; } wqnp->gateway.un.ip6addr = ire->ire_gateway_addr_v6; wqnp->netmask.un.ip6addr = ire->ire_mask_v6; wqnp->src_addr.un.ip6addr = src_addr->un.ip6addr; wqnp->src_addr.family = wqnp->gateway.family = wqnp->netmask.family = AF_INET6; } (void) strlcpy(wqnp->ifname, ill->ill_name, sizeof (wqnp->ifname)); /* * For IPMP data addresses, we need to use the hardware address of the * interface bound to the given address. */ if (IS_IPMP(ill)) { if ((hwaddr_ill = ipmp_ipif_hold_bound_ill(ipif)) == NULL) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "no bound ill for IPMP interface %s", ill->ill_name); ib_s->status = EFAULT; goto fail; } } else { hwaddr_ill = ill; ill_refhold(hwaddr_ill); /* for symmetry */ } if ((ib_s->status = ibcm_arp_check_interface(hwaddr_ill)) != 0) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_arp_check_interface failed"); goto fail; } bcopy(hwaddr_ill->ill_phys_addr, &wqnp->src_mac, hwaddr_ill->ill_phys_addr_length); IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: outgoing if:%s", wqnp->ifname); /* * if the user supplied a address, then verify rts returned * the same address */ if (wqnp->usrc_addr.family) { len = (wqnp->usrc_addr.family == AF_INET) ? IP_ADDR_LEN : sizeof (in6_addr_t); if (bcmp(&wqnp->usrc_addr.un, &wqnp->src_addr.un, len)) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "srcaddr mismatch:%d", ENETUNREACH); goto fail; } } /* * at this stage, we have the source address and the IB * interface, now get the destination mac address from * arp or ipv6 drivers */ ib_s->status = ibcm_nce_lookup(wqnp, ill, getzoneid()); if (ib_s->status != 0) { IBTF_DPRINTF_L2(cmlog, "ibcm_resolver_pr_lookup: " "ibcm_nce_lookup failed: %d", ib_s->status); goto fail; } ill_refrele(hwaddr_ill); ill_refrele(ill); ire_refrele(ire); ipif_refrele(ipif); netstack_rele(ipst->ips_netstack); IBTF_DPRINTF_L4(cmlog, "ibcm_resolver_pr_lookup: Return: 0x%p", wqnp); return (0); fail: if (hwaddr_ill != NULL) ill_refrele(hwaddr_ill); if (ill != NULL) ill_refrele(ill); if (ire != NULL) ire_refrele(ire); if (ipif != NULL) ipif_refrele(ipif); ibcm_arp_delete_prwqn(wqnp); netstack_rele(ipst->ips_netstack); return (1); }