/* ------------------------------------------------------------------------ */ void * ipf_lookup_res_name(ipf_main_softc_t *softc, int unit, u_int type, char *name, lookupfunc_t *funcptr) { ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; ipf_lookup_t **l; void *ptr = NULL; int i; READ_ENTER(&softc->ipf_poolrw); for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { if (type == (*l)->ipfl_type) { ptr = (*(*l)->ipfl_select_add_ref)(softl->ipf_back[i], unit, name); if (ptr != NULL && funcptr != NULL) { *funcptr = (*l)->ipfl_addr_find; } break; } } if (i == MAX_BACKENDS) { ptr = NULL; if (funcptr != NULL) *funcptr = NULL; } RWLOCK_EXIT(&softc->ipf_poolrw); return ptr; }
/* * clean up after ourselves. */ void ipf_p_pptp_del(ipf_main_softc_t *softc, ap_session_t *aps) { pptp_pxy_t *pptp; pptp = aps->aps_data; if (pptp != NULL) { /* * Don't bother changing any of the NAT structure details, * *_del() is on a callback from aps_free(), from nat_delete() */ READ_ENTER(&softc->ipf_state); if (pptp->pptp_state != NULL) { ipf_state_setpending(softc, pptp->pptp_state); } RWLOCK_EXIT(&softc->ipf_state); if (pptp->pptp_nat != NULL) ipf_nat_setpending(softc, pptp->pptp_nat); pptp->pptp_rule->in_flags |= IPN_DELETE; ipf_nat_rule_deref(softc, &pptp->pptp_rule); } }
/* ARGSUSED */ static void vsw_if_rx_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp, boolean_t loopback) { _NOTE(ARGUNUSED(mrh)) vsw_t *vswp = (vsw_t *)arg; mblk_t *mpt; int count; ASSERT(vswp != NULL); D1(vswp, "%s: enter", __func__); READ_ENTER(&vswp->if_lockrw); if (vswp->if_state & VSW_IF_UP) { RW_EXIT(&vswp->if_lockrw); count = vsw_vlan_frame_untag(vswp, VSW_LOCALDEV, &mp, &mpt); if (count != 0) { mac_rx(vswp->if_mh, NULL, mp); } } else { RW_EXIT(&vswp->if_lockrw); freemsgchain(mp); } D1(vswp, "%s: exit", __func__); }
/* * clean up after ourselves. */ void ippr_pptp_del(ap_session_t *aps) { pptp_pxy_t *pptp; pptp = aps->aps_data; if (pptp != NULL) { /* * Don't bother changing any of the NAT structure details, * *_del() is on a callback from aps_free(), from nat_delete() */ READ_ENTER(&ipf_state); if (pptp->pptp_state != NULL) { pptp->pptp_state->is_die = fr_ticks + 1; pptp->pptp_state->is_me = NULL; fr_queuefront(&pptp->pptp_state->is_sti); } RWLOCK_EXIT(&ipf_state); pptp->pptp_state = NULL; pptp->pptp_nat = NULL; } }
int ipsc_attachis(struct ipstate *is) { frentry_t *fr; ipscan_t *i; READ_ENTER(&ipsc_rwlock); fr = is->is_rule; if (fr) { i = fr->fr_isc; if ((i != NULL) && (i != (ipscan_t *)-1)) { is->is_isc = i; ATOMIC_INC32(i->ipsc_sref); if (i->ipsc_clen) is->is_flags |= IS_SC_CLIENT; else is->is_flags |= IS_SC_MATCHC; if (i->ipsc_slen) is->is_flags |= IS_SC_SERVER; else is->is_flags |= IS_SC_MATCHS; } } RWLOCK_EXIT(&ipsc_rwlock); return 0; }
/* * Program unicast and multicast addresses of vsw interface and the ports * into the network device. */ void vsw_set_addrs(vsw_t *vswp) { vsw_port_list_t *plist = &vswp->plist; vsw_port_t *port; int rv; READ_ENTER(&vswp->if_lockrw); if (vswp->if_state & VSW_IF_UP) { /* Open a mac client and program addresses */ rv = vsw_mac_client_init(vswp, NULL, VSW_LOCALDEV); if (rv != 0) { cmn_err(CE_NOTE, "!vsw%d: failed to program interface " "unicast address\n", vswp->instance); } /* * Notify the MAC layer of the changed address. */ if (rv == 0) { mac_unicst_update(vswp->if_mh, (uint8_t *)&vswp->if_addr); } } RW_EXIT(&vswp->if_lockrw); WRITE_ENTER(&plist->lockrw); /* program unicast address of ports in the network device */ for (port = plist->head; port != NULL; port = port->p_next) { if (port->addr_set) /* addr already set */ continue; /* Open a mac client and program addresses */ rv = vsw_mac_client_init(vswp, port, VSW_VNETPORT); if (rv != 0) { cmn_err(CE_NOTE, "!vsw%d: failed to program port(%d) " "unicast address\n", vswp->instance, port->p_instance); } } /* announce macaddr of vnets to the physical switch */ if (vsw_publish_macaddr_count != 0) { /* enabled */ for (port = plist->head; port != NULL; port = port->p_next) { vsw_publish_macaddr(vswp, port); } } RW_EXIT(&plist->lockrw); }
/* * Cleanup MAC client related stuff for all ports. */ void vsw_mac_cleanup_ports(vsw_t *vswp) { vsw_port_list_t *plist = &vswp->plist; vsw_port_t *port; READ_ENTER(&plist->lockrw); for (port = plist->head; port != NULL; port = port->p_next) { vsw_mac_client_cleanup(vswp, port, VSW_VNETPORT); } RW_EXIT(&plist->lockrw); }
/* * Remove unicast, multicast addresses and close mac clients * for the vsw interface and all ports. */ void vsw_unset_addrs(vsw_t *vswp) { READ_ENTER(&vswp->if_lockrw); if (vswp->if_state & VSW_IF_UP) { /* Cleanup and close the mac client for the interface */ vsw_mac_client_cleanup(vswp, NULL, VSW_LOCALDEV); } RW_EXIT(&vswp->if_lockrw); /* Cleanup and close the mac clients for all ports */ vsw_mac_cleanup_ports(vswp); }
int ipsc_detachis(struct ipstate *is) { ipscan_t *i; READ_ENTER(&ipsc_rwlock); if ((i = is->is_isc) && (i != (ipscan_t *)-1)) { ATOMIC_DEC32(i->ipsc_sref); is->is_isc = NULL; is->is_flags &= ~(IS_SC_CLIENT|IS_SC_SERVER); } RWLOCK_EXIT(&ipsc_rwlock); return 0; }
/*ARGSUSED*/ void ipf_lookup_sync(ipf_main_softc_t *softc, void *ifp) { ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; ipf_lookup_t **l; int i; READ_ENTER(&softc->ipf_poolrw); for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) if ((*l)->ipfl_sync != NULL) (*(*l)->ipfl_sync)(softc, softl->ipf_back[i]); RWLOCK_EXIT(&softc->ipf_poolrw); }
int ipsc_attachfr(struct frentry *fr) { ipscan_t *i; if (fr->fr_isctag[0]) { READ_ENTER(&ipsc_rwlock); i = ipsc_lookup(fr->fr_isctag); if (i != NULL) { ATOMIC_INC32(i->ipsc_fref); } RWLOCK_EXIT(&ipsc_rwlock); if (i == NULL) return ENOENT; fr->fr_isc = i; } return 0; }
/* ------------------------------------------------------------------------ */ void * ipf_lookup_find_htable(ipf_main_softc_t *softc, int unit, char *name) { ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; ipf_lookup_t **l; void *tab = NULL; int i; READ_ENTER(&softc->ipf_poolrw); for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) if (IPLT_HASH == (*l)->ipfl_type) { tab = ipf_htable_find(softl->ipf_back[i], unit, name); break; } RWLOCK_EXIT(&softc->ipf_poolrw); return tab; }
void ippr_pptp_donatstate(fr_info_t *fin, nat_t *nat, pptp_pxy_t *pptp) { fr_info_t fi; grehdr_t gre; nat_t *nat2; u_char p; ip_t *ip; ip = fin->fin_ip; p = ip->ip_p; nat2 = pptp->pptp_nat; if ((nat2 == NULL) || (pptp->pptp_state == NULL)) { bcopy((char *)fin, (char *)&fi, sizeof(fi)); bzero((char *)&gre, sizeof(gre)); fi.fin_fi.fi_p = IPPROTO_GRE; fi.fin_fr = &pptpfr; if ((nat->nat_dir == NAT_OUTBOUND && fin->fin_out) || (nat->nat_dir == NAT_INBOUND && !fin->fin_out)) { fi.fin_data[0] = pptp->pptp_call[0]; fi.fin_data[1] = pptp->pptp_call[1]; } else { fi.fin_data[0] = pptp->pptp_call[1]; fi.fin_data[1] = pptp->pptp_call[0]; } ip = fin->fin_ip; ip->ip_p = IPPROTO_GRE; fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG); fi.fin_flx |= FI_IGNORE; fi.fin_dp = &gre; gre.gr_flags = htons(1 << 13); if (fin->fin_out && nat->nat_dir == NAT_INBOUND) { fi.fin_fi.fi_saddr = fin->fin_fi.fi_daddr; fi.fin_fi.fi_daddr = nat->nat_outip.s_addr; } else if (!fin->fin_out && nat->nat_dir == NAT_OUTBOUND) { fi.fin_fi.fi_saddr = nat->nat_inip.s_addr; fi.fin_fi.fi_daddr = fin->fin_fi.fi_saddr; } } /* * Update NAT timeout/create NAT if missing. */ if (nat2 != NULL) fr_queueback(&nat2->nat_tqe); else { MUTEX_ENTER(&ipf_nat_new); nat2 = nat_new(&fi, &pptp->pptp_rule, &pptp->pptp_nat, NAT_SLAVE, nat->nat_dir); MUTEX_EXIT(&ipf_nat_new); pptp->pptp_nat = nat2; if (nat2 != NULL) { (void) nat_proto(&fi, nat2, 0); MUTEX_ENTER(&nat2->nat_lock); nat_update(&fi, nat2); MUTEX_EXIT(&nat2->nat_lock); } } READ_ENTER(&ipf_state); if (pptp->pptp_state != NULL) { fr_queueback(&pptp->pptp_state->is_sti); RWLOCK_EXIT(&ipf_state); } else { RWLOCK_EXIT(&ipf_state); if (nat2 != NULL) { if (nat->nat_dir == NAT_INBOUND) fi.fin_fi.fi_daddr = nat2->nat_inip.s_addr; else fi.fin_fi.fi_saddr = nat2->nat_inip.s_addr; } fi.fin_ifp = NULL; pptp->pptp_state = fr_addstate(&fi, &pptp->pptp_state, 0); } ip->ip_p = p; return; }
/* * Forward pkts to any devices or interfaces which have registered * an interest in them (i.e. multicast groups). */ static int vsw_forward_grp(vsw_t *vswp, mblk_t *mp, int caller, vsw_port_t *arg) { struct ether_header *ehp = (struct ether_header *)mp->b_rptr; mfdb_ent_t *entp = NULL; mfdb_ent_t *tpp = NULL; vsw_port_t *port; uint64_t key = 0; mblk_t *nmp = NULL; mblk_t *ret_m = NULL; boolean_t check_if = B_TRUE; /* * Convert address to hash table key */ KEY_HASH(key, &ehp->ether_dhost); D1(vswp, "%s: key 0x%llx", __func__, key); /* * If pkt came from either a vnet or down the stack (if we are * plumbed) and we are in layer 2 mode, then we send the pkt out * over the physical adapter, and then check to see if any other * vnets are interested in it. */ if ((vswp->smode & VSW_LAYER2) && ((caller == VSW_VNETPORT) || (caller == VSW_LOCALDEV))) { nmp = vsw_dupmsgchain(mp); if (nmp) { if ((ret_m = vsw_tx_msg(vswp, nmp, caller, arg)) != NULL) { DERR(vswp, "%s: dropping pkt(s) consisting of " "%ld bytes of data for physical device", __func__, MBLKL(ret_m)); freemsgchain(ret_m); } } } READ_ENTER(&vswp->mfdbrw); if (mod_hash_find(vswp->mfdb, (mod_hash_key_t)key, (mod_hash_val_t *)&entp) != 0) { D3(vswp, "%s: no table entry found for addr 0x%llx", __func__, key); } else { /* * Send to list of devices associated with this address... */ for (tpp = entp; tpp != NULL; tpp = tpp->nextp) { /* dont send to ourselves */ if ((caller == VSW_VNETPORT) && (tpp->d_addr == (void *)arg)) { port = (vsw_port_t *)tpp->d_addr; D3(vswp, "%s: not sending to ourselves" " : port %d", __func__, port->p_instance); continue; } else if ((caller == VSW_LOCALDEV) && (tpp->d_type == VSW_LOCALDEV)) { D2(vswp, "%s: not sending back up stack", __func__); continue; } if (tpp->d_type == VSW_VNETPORT) { port = (vsw_port_t *)tpp->d_addr; D3(vswp, "%s: sending to port %ld for addr " "0x%llx", __func__, port->p_instance, key); nmp = vsw_dupmsgchain(mp); if (nmp) { /* * The vswp->mfdbrw is protecting the * portp from getting destroyed here. * So, no ref_cnt is incremented here. */ (void) vsw_portsend(port, nmp); } } else { vsw_mac_rx(vswp, NULL, mp, VSW_MACRX_COPYMSG); D2(vswp, "%s: sending up stack" " for addr 0x%llx", __func__, key); check_if = B_FALSE; } } } RW_EXIT(&vswp->mfdbrw); /* * If the pkt came from either a vnet or from physical device, * and if we havent already sent the pkt up the stack then we * check now if we can/should (i.e. the interface is plumbed * and in promisc mode). */ if ((check_if) && ((caller == VSW_VNETPORT) || (caller == VSW_PHYSDEV))) { vsw_mac_rx(vswp, NULL, mp, VSW_MACRX_PROMISC | VSW_MACRX_COPYMSG); } freemsgchain(mp); D1(vswp, "%s: exit", __func__); return (0); }
/* * Forward the ethernet frame to all ports (VNETPORTs, PHYSDEV, LOCALDEV), * except the caller (port on which frame arrived). */ static int vsw_forward_all(vsw_t *vswp, mblk_t *mp, int caller, vsw_port_t *arg) { vsw_port_list_t *plist = &vswp->plist; vsw_port_t *portp; mblk_t *nmp = NULL; mblk_t *ret_m = NULL; int skip_port = 0; D1(vswp, "vsw_forward_all: enter\n"); /* * Broadcast message from inside ldoms so send to outside * world if in either of layer 2 modes. */ if ((vswp->smode & VSW_LAYER2) && ((caller == VSW_LOCALDEV) || (caller == VSW_VNETPORT))) { nmp = vsw_dupmsgchain(mp); if (nmp) { if ((ret_m = vsw_tx_msg(vswp, nmp, caller, arg)) != NULL) { DERR(vswp, "%s: dropping pkt(s) " "consisting of %ld bytes of data for" " physical device", __func__, MBLKL(ret_m)); freemsgchain(ret_m); } } } if (caller == VSW_VNETPORT) skip_port = 1; /* * Broadcast message from other vnet (layer 2 or 3) or outside * world (layer 2 only), send up stack if plumbed. */ if ((caller == VSW_PHYSDEV) || (caller == VSW_VNETPORT)) { vsw_mac_rx(vswp, NULL, mp, VSW_MACRX_COPYMSG); } /* send it to all VNETPORTs */ READ_ENTER(&plist->lockrw); for (portp = plist->head; portp != NULL; portp = portp->p_next) { D2(vswp, "vsw_forward_all: port %d", portp->p_instance); /* * Caution ! - don't reorder these two checks as arg * will be NULL if the caller is PHYSDEV. skip_port is * only set if caller is VNETPORT. */ if ((skip_port) && (portp == arg)) { continue; } else { nmp = vsw_dupmsgchain(mp); if (nmp) { /* * The plist->lockrw is protecting the * portp from getting destroyed here. * So, no ref_cnt is incremented here. */ (void) vsw_portsend(portp, nmp); } else { DERR(vswp, "vsw_forward_all: nmp NULL"); } } } RW_EXIT(&plist->lockrw); freemsgchain(mp); D1(vswp, "vsw_forward_all: exit\n"); return (0); }
void ipf_p_pptp_donatstate(fr_info_t *fin, nat_t *nat, pptp_pxy_t *pptp) { ipf_main_softc_t *softc = fin->fin_main_soft; fr_info_t fi; grehdr_t gre; nat_t *nat2; u_char p; ip_t *ip; ip = fin->fin_ip; p = ip->ip_p; nat2 = pptp->pptp_nat; if ((nat2 == NULL) || (pptp->pptp_state == NULL)) { bcopy((char *)fin, (char *)&fi, sizeof(fi)); bzero((char *)&gre, sizeof(gre)); fi.fin_fi.fi_p = IPPROTO_GRE; fi.fin_fr = &pptpfr; if ((nat->nat_dir == NAT_OUTBOUND && fin->fin_out) || (nat->nat_dir == NAT_INBOUND && !fin->fin_out)) { fi.fin_data[0] = pptp->pptp_call[0]; fi.fin_data[1] = pptp->pptp_call[1]; } else { fi.fin_data[0] = pptp->pptp_call[1]; fi.fin_data[1] = pptp->pptp_call[0]; } ip = fin->fin_ip; ip->ip_p = IPPROTO_GRE; fi.fin_flx &= ~(FI_TCPUDP|FI_STATE|FI_FRAG); fi.fin_flx |= FI_IGNORE; fi.fin_dp = &gre; gre.gr_flags = htons(1 << 13); fi.fin_fi.fi_saddr = nat->nat_osrcaddr; fi.fin_fi.fi_daddr = nat->nat_odstaddr; } /* * Update NAT timeout/create NAT if missing. */ if (nat2 != NULL) ipf_queueback(softc->ipf_ticks, &nat2->nat_tqe); else { #ifdef USE_MUTEXES ipf_nat_softc_t *softn = softc->ipf_nat_soft; #endif MUTEX_ENTER(&softn->ipf_nat_new); nat2 = ipf_nat_add(&fi, pptp->pptp_rule, &pptp->pptp_nat, NAT_SLAVE, nat->nat_dir); MUTEX_EXIT(&softn->ipf_nat_new); if (nat2 != NULL) { (void) ipf_nat_proto(&fi, nat2, 0); MUTEX_ENTER(&nat2->nat_lock); ipf_nat_update(&fi, nat2); MUTEX_EXIT(&nat2->nat_lock); } } READ_ENTER(&softc->ipf_state); if (pptp->pptp_state != NULL) { ipf_queueback(softc->ipf_ticks, &pptp->pptp_state->is_sti); RWLOCK_EXIT(&softc->ipf_state); } else { RWLOCK_EXIT(&softc->ipf_state); if (nat2 != NULL) { if (nat->nat_dir == NAT_INBOUND) fi.fin_fi.fi_daddr = nat2->nat_ndstaddr; else fi.fin_fi.fi_saddr = nat2->nat_osrcaddr; } fi.fin_ifp = NULL; (void) ipf_state_add(softc, &fi, &pptp->pptp_state, 0); } ip->ip_p = p; return; }