/* * Attach/setup the common net80211 state. Called by * the driver on attach to prior to creating any vap's. */ void ieee80211_ifattach(struct ieee80211com *ic, const uint8_t macaddr[IEEE80211_ADDR_LEN]) { struct ifnet *ifp = ic->ic_ifp; struct sockaddr_dl *sdl; struct ifaddr *ifa; KASSERT(ifp->if_type == IFT_IEEE80211, ("if_type %d", ifp->if_type)); TAILQ_INIT(&ic->ic_vaps); /* Create a taskqueue for all state changes */ ic->ic_tq = taskqueue_create("ic_taskq", M_WAITOK | M_ZERO, taskqueue_thread_enqueue, &ic->ic_tq); taskqueue_start_threads(&ic->ic_tq, 1, TDPRI_KERN_DAEMON, -1, "%s taskq", ifp->if_xname); /* * Fill in 802.11 available channel set, mark all * available channels as active, and pick a default * channel if not already specified. */ ieee80211_media_init(ic); ic->ic_update_mcast = null_update_mcast; ic->ic_update_promisc = null_update_promisc; ic->ic_hash_key = karc4random(); ic->ic_bintval = IEEE80211_BINTVAL_DEFAULT; ic->ic_lintval = ic->ic_bintval; ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX; ieee80211_crypto_attach(ic); ieee80211_node_attach(ic); ieee80211_power_attach(ic); ieee80211_proto_attach(ic); #ifdef IEEE80211_SUPPORT_SUPERG ieee80211_superg_attach(ic); #endif ieee80211_ht_attach(ic); ieee80211_scan_attach(ic); ieee80211_regdomain_attach(ic); ieee80211_dfs_attach(ic); ieee80211_sysctl_attach(ic); ifp->if_addrlen = IEEE80211_ADDR_LEN; ifp->if_hdrlen = 0; if_attach(ifp, NULL); ifp->if_mtu = IEEE80211_MTU_MAX; ifp->if_broadcastaddr = ieee80211broadcastaddr; ifp->if_output = null_output; ifp->if_input = null_input; /* just in case */ ifp->if_resolvemulti = NULL; /* NB: callers check */ ifa = ifaddr_byindex(ifp->if_index); KASSERT(ifa != NULL, ("%s: no lladdr!", __func__)); sdl = (struct sockaddr_dl *)ifa->ifa_addr; sdl->sdl_type = IFT_ETHER; /* XXX IFT_IEEE80211? */ sdl->sdl_alen = IEEE80211_ADDR_LEN; IEEE80211_ADDR_COPY(LLADDR(sdl), macaddr); // IFAFREE(ifa); }
void ieee80211_ifattach(struct ieee80211com *ic) { struct ifnet *ifp = ic->ic_ifp; struct ieee80211_channel *c; int i; #ifdef __NetBSD__ ieee80211_init(); #endif /* __NetBSD__ */ ether_ifattach(ifp, ic->ic_myaddr); bpf_attach2(ifp, DLT_IEEE802_11, sizeof(struct ieee80211_frame_addr4), &ic->ic_rawbpf); ieee80211_crypto_attach(ic); /* * Fill in 802.11 available channel set, mark * all available channels as active, and pick * a default channel if not already specified. */ memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail)); ic->ic_modecaps |= 1<<IEEE80211_MODE_AUTO; for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { c = &ic->ic_channels[i]; if (c->ic_flags) { /* * Verify driver passed us valid data. */ if (i != ieee80211_chan2ieee(ic, c)) { if_printf(ifp, "bad channel ignored; " "freq %u flags %x number %u\n", c->ic_freq, c->ic_flags, i); c->ic_flags = 0; /* NB: remove */ continue; } setbit(ic->ic_chan_avail, i); /* * Identify mode capabilities. */ if (IEEE80211_IS_CHAN_A(c)) ic->ic_modecaps |= 1<<IEEE80211_MODE_11A; if (IEEE80211_IS_CHAN_B(c)) ic->ic_modecaps |= 1<<IEEE80211_MODE_11B; if (IEEE80211_IS_CHAN_PUREG(c)) ic->ic_modecaps |= 1<<IEEE80211_MODE_11G; if (IEEE80211_IS_CHAN_FHSS(c)) ic->ic_modecaps |= 1<<IEEE80211_MODE_FH; if (IEEE80211_IS_CHAN_T(c)) ic->ic_modecaps |= 1<<IEEE80211_MODE_TURBO_A; if (IEEE80211_IS_CHAN_108G(c)) ic->ic_modecaps |= 1<<IEEE80211_MODE_TURBO_G; if (ic->ic_curchan == NULL) { /* arbitrarily pick the first channel */ ic->ic_curchan = &ic->ic_channels[i]; } } } /* validate ic->ic_curmode */ if ((ic->ic_modecaps & (1<<ic->ic_curmode)) == 0) ic->ic_curmode = IEEE80211_MODE_AUTO; ic->ic_des_chan = IEEE80211_CHAN_ANYC; /* any channel is ok */ #if 0 /* * Enable WME by default if we're capable. */ if (ic->ic_caps & IEEE80211_C_WME) ic->ic_flags |= IEEE80211_F_WME; #endif (void) ieee80211_setmode(ic, ic->ic_curmode); if (ic->ic_bintval == 0) ic->ic_bintval = IEEE80211_BINTVAL_DEFAULT; ic->ic_bmisstimeout = 7*ic->ic_bintval; /* default 7 beacons */ ic->ic_dtim_period = IEEE80211_DTIM_DEFAULT; IEEE80211_BEACON_LOCK_INIT(ic, "beacon"); if (ic->ic_lintval == 0) ic->ic_lintval = ic->ic_bintval; ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX; LIST_INSERT_HEAD(&ieee80211com_head, ic, ic_list); ieee80211_node_attach(ic); ieee80211_proto_attach(ic); ieee80211_add_vap(ic); ieee80211_sysctl_attach(ic); /* NB: requires ic_vap */ /* * Install a default reset method for the ioctl support. * The driver is expected to fill this in before calling us. */ if (ic->ic_reset == NULL) ic->ic_reset = ieee80211_default_reset; }