📄 if_wlp_wavelan_roam.c
字号:
else { if (sc->sc_rs.rs_apreg) {#ifdef WLP_DEBUG printf("Aborting Registration!\n");#endif SendRECReq(a->ap_softc); /* XXX */ } sc->sc_rs.rs_apreg = a; /* NWID Promisc Mode */ SetNWID(sc, a->ap_beacon.snwid, 1); SendSOReq(sc, a); /* Send a Sign-on Request */ sc->sc_rs.rs_roam_mode = MODE_REG_CELL; } break; /* switch() */ case MODE_STOP_CELL: if (sc->sc_rs.rs_ap == 0) panic("Stop Cell Search Mode && ap == 0"); if (sc->sc_rs.rs_apreg) panic("Stop Cell Search Mode && apreq != 0"); if (SNR(sc->sc_rs.rs_ap) > REG_CELL(sc->sc_rs.rs_ap)) { goto done; } else if (SNR(sc->sc_rs.rs_ap) < FAST_CELL(sc->sc_rs.rs_ap)) { sc->sc_rs.rs_roam_mode = MODE_FAST_CELL; goto start; } else { sc->sc_rs.rs_roam_mode = MODE_REG_CELL; goto start; } break; default: panic("roam_timer(): RoamMode is invalid"); }done: timeout(roam_timer, (void *) sc, 2 * hz); /* 2 seconds */quit: splx(s);}static voidPurgeAccessPointList(sc) struct wlp_softc *sc;{ struct accesspoint *a, *an; for (a = sc->sc_rs.rs_aplist.lh_first; a;) { an = a->ap_link.le_next; if (AP_EXPIRED(a)) {#ifdef WLP_DEBUG printf("NWID: %x expired at %ld.%ld\n", a->ap_beacon.snwid, a->ap_expire.tv_sec, a->ap_expire.tv_usec);#endif if (a == sc->sc_rs.rs_ap) { sc->sc_rs.rs_ap = 0; sc->sc_rs.rs_roam_mode = MODE_FAST_CELL; } if (a == sc->sc_rs.rs_apreg) { SendRECReq(sc); /* XXX */ sc->sc_rs.rs_apreg = 0; sc->sc_rs.rs_roam_mode = MODE_FAST_CELL; sc->sc_rs.rs_SOReqRetrans = 0; } LIST_REMOVE(a, ap_link); free(a, M_TEMP); } a = an; }}struct accesspoint *BestAccessPoint1(sc) struct wlp_softc *sc;{ struct accesspoint *a; struct accesspoint *maxa = 0; int maxsnr = -1; for (a = sc->sc_rs.rs_aplist.lh_first; a; a = a->ap_link.le_next) { if (maxsnr < 0) { maxsnr = SNR(a); maxa = a; } else if (SNR(a) > maxsnr) { maxsnr = SNR(a); maxa = a; } }#ifdef WLP_DEBUG if(maxa == 0) printf("%s: no Access Point found...\n", __FUNCTION__);#endif return maxa;}static struct accesspoint *BestAccessPoint2(X, Y) struct accesspoint *X; struct accesspoint *Y;{ int x = 0; int y = 0; if (Y == 0) return X; /* X has prescedence */ if (X == 0) return Y; if (SNR(X) < FAST_CELL(X)) x = 1; else if (SNR(X) < REG_CELL(X)) x = 2; else if (SNR(X) < STOP_CELL(X)) x = 3; else x = 4; if (SNR(Y) < FAST_CELL(Y)) y = 1; else if (SNR(Y) < REG_CELL(Y)) y = 2; else if (SNR(Y) < STOP_CELL(Y)) y = 3; else y = 4; return (x >= y ? X : Y);}/* * ====================================================================== * Packet Processing Functions * ====================================================================== */static voidProcessBeacon(eh, m, sigstat) struct ether_header *eh; struct mbuf *m; int sigstat;{ struct arpcom *ac = (struct arpcom *) m->m_pkthdr.rcvif; struct wlp_softc *sc; struct pkt_beacon *p; struct accesspoint *a; if (ac == 0) panic("ProcessBeacon(): ac = 0"); sc = (struct wlp_softc *) ac->ac_if.if_softc; p = mtod(m, struct pkt_beacon *); sc->sc_rs.rs_BeaconCount++; if (sc->sc_rs.rs_domid && sc->sc_rs.rs_domid != ntohs(p->domid)) { return; } p->snwid ^= htons(sc->sc_rs.rs_beaconkey); for (a = sc->sc_rs.rs_aplist.lh_first; a; a = a->ap_link.le_next) { if (a->ap_beacon.snwid == ntohs(p->snwid)) break; } /* * If this is a beacon from a new access point... */ if (a == 0) { /* * Discard the Beacon if the SNR is < Fast Cell Search * Threshold */ if ((min((sigstat >> 16) & 0xFF, 36) - min((sigstat >> 8) & 0xFF, 36)) < p->fcell) { return; } a = (struct accesspoint *) malloc(sizeof(*a), M_TEMP, M_DONTWAIT); if (!a) return; bzero(a, sizeof(*a)); a->ap_beacon.pdutype = p->pdutype; /* a->ap_beacon.sequence = p->sequence; */ a->ap_beacon.domid = ntohs(p->domid); a->ap_beacon.snwid = ntohs(p->snwid); /* a->ap_beacon.rfnoise = p->rfnoise; */ a->ap_beacon.threshold = p->threshold; a->ap_beacon.scell = p->scell; a->ap_beacon.rcell = p->rcell; a->ap_beacon.fcell = p->fcell; *((u_int16_t *) & a->ap_beacon.interval) = ntohs(*((u_int16_t *) & p->interval)); *((u_int16_t *) & a->ap_beacon.timeout) = ntohs(*((u_int16_t *) & p->timeout)); strncpy(a->ap_beacon.apname, p->apname, sizeof(p->apname)); /* * Save MAC Address and ifp */ bcopy(eh->ether_shost, a->ap_macaddr, ETHER_ADDR_LEN); a->ap_softc = (struct wlp_softc *) ((struct ifnet *) m->m_pkthdr.rcvif)->if_softc; LIST_INSERT_HEAD(&sc->sc_rs.rs_aplist, a, ap_link);#ifdef WLP_DEBUG printf("%s: added %p to the AP list\n", __FUNCTION__, a);#endif } a->ap_beacon.sequence = p->sequence; a->ap_beacon.rfnoise = p->rfnoise;#define sigavg(x, y) ( (x) ? (((x) + (y)) >> 1) : (y) ) a->ap_siglevel = sigavg(a->ap_siglevel, min((sigstat >> 16) & 0xFF, 36)); a->ap_sillevel = sigavg(a->ap_sillevel, min((sigstat >> 8) & 0xFF, 36)); a->ap_sigqual = sigstat & 0x0F; AP_SET_EXPIRE(a); sc->sc_rs.rs_BeaconKept++;}static voidProcessSORsp(eh, m) struct ether_header *eh; struct mbuf *m;{ struct ifnet *ifp = (struct ifnet *) m->m_pkthdr.rcvif; struct wlp_softc *sc; struct pkt_sorsp *p; if (ifp == 0) panic("ProcessSORsp(): ifp = 0"); sc = (struct wlp_softc *) ifp->if_softc; p = mtod(m, struct pkt_sorsp *); if (sc->sc_rs.rs_apreg == 0) {#ifdef WLP_DEBUG printf("wlp%d: Received a SIGN-ON Response, but not registering\n", ifp->if_unit);#endif return; } if (p->seq != (sc->sc_rs.rs_SOReqCnt - 1)) {#ifdef WLP_DEBUG printf("\tERROR: Invalid Sequence Number %d (expected %d)\n", p->seq, sc->sc_rs.rs_SOReqCnt);#endif return; } if (p->status != 0) {#ifdef WLP_DEBUG printf("\tERROR: Sign-on Request Rejected (status = %d)\n", p->status);#endif return; } /* * Save the Access Point Information... */ if (p->infoblock[0] > SORSP_INFOBLOCK_MAX_LEN - 1) {#ifdef WLP_DEBUG printf("\tERROR: Sign-on Request has invalid infoblock length (%d)\n", p->infoblock[0]);#endif return; } bcopy(p->infoblock, sc->sc_rs.rs_apreg->ap_infoblock, p->infoblock[0] + 1); /* NWID Promisc Mode */ SetNWID(sc, sc->sc_rs.rs_apreg->ap_beacon.snwid, 1); EnableTX(ifp); sc->sc_rs.rs_SOReqRetrans = 0; if (sc->sc_rs.rs_ap == 0 && sc->sc_rs.rs_SOReqFailed) { /* Initial Sign-ON */ SendRECReq(sc); /* XXX */ } sc->sc_rs.rs_ap = sc->sc_rs.rs_apreg; sc->sc_rs.rs_apreg = 0;#ifdef WLP_DEBUG printf("-------------------- New Access Point --------------------\n"); dump_ap(sc->sc_rs.rs_ap);#endif}/* * ====================================================================== * Packet Building Functions... * ====================================================================== */static voidSendSOReq(sc, a) struct wlp_softc *sc; struct accesspoint *a;{ struct mbuf *m; struct ether_header *eh; struct pkt_soreq *p; MGETHDR(m, M_DONTWAIT, MT_HEADER); if (!m) return; eh = mtod(m, struct ether_header *); bzero((caddr_t) eh, MHLEN); /* * Insert the SNAP goop... */ bcopy(ether_wavelan_snaphdr, (caddr_t) (eh + 1), sizeof(ether_wavelan_snaphdr)); /* * Insert the Sign On Request stuff... */ p = (struct pkt_soreq *) (((caddr_t) (eh + 1)) + sizeof(ether_wavelan_snaphdr)); p->pdutype = PDUTYPE_SOREQ; /* Sign-On Request */ p->seq = sc->sc_rs.rs_SOReqCnt++; /* Not used by base station */ p->numaps = 0x00; /* Not Presently Used */ p->roamstate = 0x00; /* Not Presently Used */ p->reserved = 0x00; /* SHOULD be 0x00 */ m->m_len = sizeof(*eh) + sizeof(ether_wavelan_snaphdr) + sizeof(struct pkt_soreq); if (sc->sc_rs.rs_ap && sc->sc_rs.rs_ap->ap_infoblock[0]) { bcopy(sc->sc_rs.rs_ap->ap_infoblock, p->infoblock, sc->sc_rs.rs_ap->ap_infoblock[0]); m->m_len += sc->sc_rs.rs_ap->ap_infoblock[0]; } /* * Fill in the Ethernet header... */ bcopy(a->ap_softc->sc_ac.ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN); bcopy(a->ap_macaddr, eh->ether_dhost, ETHER_ADDR_LEN); eh->ether_type = htons(m->m_len - sizeof(*eh)); m->m_pkthdr.len = m->m_len = BEACON_MIN_LEN + sizeof(ether_wavelan_snaphdr); sc->sc_rs.rs_SOReqRetrans++; /* Increment Sign-ON Counter */ wlptransmit(sc, m); m_freem(m);#ifdef WLP_DEBUG printf("-------------------- Registering --------------------\n"); dump_ap(a);#endif}static voidSendRECReq(sc) struct wlp_softc *sc;{ struct mbuf *m; struct ether_header *eh; struct pkt_recreq *p; MGETHDR(m, M_DONTWAIT, MT_HEADER); if (m == 0) return; eh = mtod(m, struct ether_header *); p = (struct pkt_recreq *) (((caddr_t) (eh + 1)) + sizeof(ether_wavelan_snaphdr)); bzero((caddr_t) eh, MHLEN); /* Ethernet Header */ bcopy(sc->sc_ac.ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN); bcopy(ether_bridge_multiaddr, eh->ether_dhost, ETHER_ADDR_LEN); eh->ether_type = htons(sizeof(ether_wavelan_snaphdr) + sizeof(struct pkt_recreq)); /* SNAP Header */ bcopy(ether_wavelan_snaphdr, (caddr_t) (eh + 1), sizeof(ether_wavelan_snaphdr)); /* WaveLAN Stuff */ p->pdutype = PDUTYPE_RECREQ; m->m_pkthdr.len = m->m_len = sizeof(*eh) + sizeof(ether_wavelan_snaphdr) + sizeof(struct pkt_recreq) + RECREQ_PADDING_LEN; wlptransmit(sc, m); m_freem(m); sc->sc_rs.rs_SOReqFailed = 0;}/* ====================================================================== */#ifdef WLP_DEBUGstatic voiddump_ap(a) struct accesspoint *a;{ if (!a) return; printf("NAME: %s, MAC ADDR: %02x:%02x:%02x:%02x:%02x:%02x, NWID: %x\n", a->ap_beacon.apname, ETHER_ADDR_FORMAT(a->ap_macaddr), a->ap_beacon.snwid); printf("\tEXPIRE: %ld.%ld, INTERVAL: %d, TIMEOUT: %d\n", a->ap_expire.tv_sec, a->ap_expire.tv_usec, *((u_int16_t*) a->ap_beacon.interval), *((u_int16_t*) a->ap_beacon.timeout)); printf("\tSIGNAL: %2d %2d %2d %2d, THRESHOLD: %2d %2d %2d\n", a->ap_siglevel, a->ap_sillevel, a->ap_sigqual, a->ap_beacon.rfnoise, a->ap_beacon.scell, a->ap_beacon.rcell, a->ap_beacon.fcell);}static voiddump_aplist(sc) struct wlp_softc *sc;{ struct accesspoint *a; printf("----------------------------------------\n"); for (a = sc->sc_rs.rs_aplist.lh_first; a; a = a->ap_link.le_next) dump_ap(a); printf("********* Current Base Station (mode: %s, time: %ld.%ld)\n", RoamModeString[sc->sc_rs.rs_roam_mode], time.tv_sec, time.tv_usec); dump_ap(sc->sc_rs.rs_ap); printf("----------------------------------------\n");}#endif /* WLP_DEBUG */#endif /* NCARD > 0 */#endif /* WAVELAN_ROAMING */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -