⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_an.c

📁 linux 下通过802.1认证的安装包
💻 C
📖 第 1 页 / 共 4 页
字号:
	case AN_RID_SSIDLIST:
		ssid = (struct an_ltv_ssidlist *)areq;
		bcopy((char *)ssid, (char *)&sc->an_ssidlist,
			sizeof(struct an_ltv_ssidlist));
		break;
	case AN_RID_APLIST:
		ap = (struct an_ltv_aplist *)areq;
		bcopy((char *)ap, (char *)&sc->an_aplist,
			sizeof(struct an_ltv_aplist));
		break;
	case AN_RID_TX_SPEED:
		sp = (struct an_ltv_gen *)areq;
		sc->an_tx_rate = sp->an_val;
		break;
	case AN_RID_WEP_TEMP:
	case AN_RID_WEP_PERM:
		/* Disable the MAC. */
      	        /* an_cmd(sc, AN_CMD_DISABLE, 0); */

		/* Write the key */
		an_write_record(sc, (struct an_ltv_gen *)areq);

		/* Turn the MAC back on. */
		/* an_cmd(sc, AN_CMD_ENABLE, 0); */
		return;
		break;
	case AN_RID_MONITOR_MODE:
		cfg = (struct an_ltv_genconfig *)areq;
		bpfdetach(ifp);
		if (ng_ether_detach_p != NULL)
			(*ng_ether_detach_p) (ifp);
		sc->an_monitor = cfg->an_len;

		if (sc->an_monitor & AN_MONITOR) {
			if (sc->an_monitor & AN_MONITOR_AIRONET_HEADER) {
				bpfattach(ifp, DLT_AIRONET_HEADER,
					sizeof(struct ether_header));
			} else {
				bpfattach(ifp, DLT_IEEE802_11,
					sizeof(struct ether_header));
			}
		} else {
			bpfattach(ifp, DLT_EN10MB,
				  sizeof(struct ether_header));
			if (ng_ether_attach_p != NULL)
				(*ng_ether_attach_p) (ifp);
		}
		break;
	default:
		printf("an%d: unknown RID: %x\n", sc->an_unit, areq->an_type);
		return;
		break;
	}


	/* Reinitialize the card. */
	if (ifp->if_flags)
		an_init(sc);

	return;
}

/*
 * Derived from Linux driver to enable promiscious mode.
 */

static void
an_promisc(sc, promisc)
	struct an_softc		*sc;
	int			promisc;
{
	if (sc->an_was_monitor)
		an_reset(sc);
	if (sc->an_monitor || sc->an_was_monitor)
		an_init(sc);

	sc->an_was_monitor = sc->an_monitor;
	an_cmd(sc, AN_CMD_SET_MODE, promisc ? 0xffff : 0);

	return;
}

static int
an_ioctl(ifp, command, data)
	struct ifnet		*ifp;
	u_long			command;
	caddr_t			data;
{
	int			s, error = 0;
	int			len;
	int			i;
	struct an_softc		*sc;
	struct an_req		areq;
	struct ifreq		*ifr;
	struct proc		*p = curproc;
	struct ieee80211req	*ireq;
	u_int8_t		tmpstr[IEEE80211_NWID_LEN*2];
	u_int8_t		*tmpptr;
	struct an_ltv_genconfig	*config;
	struct an_ltv_key	*key;
	struct an_ltv_status	*status;
	struct an_ltv_ssidlist	*ssids;

	s = splimp();

	sc = ifp->if_softc;
	ifr = (struct ifreq *)data;
	ireq = (struct ieee80211req *)data;

	config = (struct an_ltv_genconfig *)&areq;
	key = (struct an_ltv_key *)&areq;
	status = (struct an_ltv_status *)&areq;
	ssids = (struct an_ltv_ssidlist *)&areq;

	if (sc->an_gone) {
		error = ENODEV;
		goto out;
	}

	switch (command) {
	case SIOCSIFADDR:
	case SIOCGIFADDR:
	case SIOCSIFMTU:
		error = ether_ioctl(ifp, command, data);
		break;
	case SIOCSIFFLAGS:
		if (ifp->if_flags & IFF_UP) {
			if (ifp->if_flags & IFF_RUNNING &&
			    ifp->if_flags & IFF_PROMISC &&
			    !(sc->an_if_flags & IFF_PROMISC)) {
				an_promisc(sc, 1);
			} else if (ifp->if_flags & IFF_RUNNING &&
			    !(ifp->if_flags & IFF_PROMISC) &&
			    sc->an_if_flags & IFF_PROMISC) {
				an_promisc(sc, 0);
			} else
				an_init(sc);
		} else {
			if (ifp->if_flags & IFF_RUNNING)
				an_stop(sc);
		}
		sc->an_if_flags = ifp->if_flags;
		error = 0;
		break;
	case SIOCSIFMEDIA:
	case SIOCGIFMEDIA:
		error = ifmedia_ioctl(ifp, ifr, &sc->an_ifmedia, command);
		break;
	case SIOCADDMULTI:
	case SIOCDELMULTI:
		/* The Aironet has no multicast filter. */
		error = 0;
		break;
	case SIOCGAIRONET:
		error = copyin(ifr->ifr_data, &areq, sizeof(areq));
		if (error != 0)
			break;
#ifdef ANCACHE
		if (areq.an_type == AN_RID_ZERO_CACHE) {
			sc->an_sigitems = sc->an_nextitem = 0;
			break;
		} else if (areq.an_type == AN_RID_READ_CACHE) {
			char *pt = (char *)&areq.an_val;
			bcopy((char *)&sc->an_sigitems, (char *)pt,
			    sizeof(int));
			pt += sizeof(int);
			areq.an_len = sizeof(int) / 2;
			bcopy((char *)&sc->an_sigcache, (char *)pt,
			    sizeof(struct an_sigcache) * sc->an_sigitems);
			areq.an_len += ((sizeof(struct an_sigcache) *
			    sc->an_sigitems) / 2) + 1;
		} else
#endif
		if (an_read_record(sc, (struct an_ltv_gen *)&areq)) {
			error = EINVAL;
			break;
		}
		error = copyout(&areq, ifr->ifr_data, sizeof(areq));
		break;
	case SIOCSAIRONET:
		if ((error = suser(p)))
			goto out;
		error = copyin(ifr->ifr_data, &areq, sizeof(areq));
		if (error != 0)
			break;
		an_setdef(sc, &areq);
		break;
	case SIOCG80211:
		areq.an_len = sizeof(areq);
		switch (ireq->i_type) {
		case IEEE80211_IOC_SSID:
			if (ireq->i_val == -1) {
				areq.an_type = AN_RID_STATUS;
				if (an_read_record(sc,
				    (struct an_ltv_gen *)&areq)) {
					error = EINVAL;
					break;
				}
				len = status->an_ssidlen;
				tmpptr = status->an_ssid;
			} else if (ireq->i_val >= 0) {
				areq.an_type = AN_RID_SSIDLIST;
				if (an_read_record(sc,
				    (struct an_ltv_gen *)&areq)) {
					error = EINVAL;
					break;
				}
				if (ireq->i_val == 0) {
					len = ssids->an_ssid1_len;
					tmpptr = ssids->an_ssid1;
				} else if (ireq->i_val == 1) {
					len = ssids->an_ssid2_len;
					tmpptr = ssids->an_ssid3;
				} else if (ireq->i_val == 1) {
					len = ssids->an_ssid3_len;
					tmpptr = ssids->an_ssid3;
				} else {
					error = EINVAL;
					break;
				}
			} else {
				error = EINVAL;
				break;
			}
			if (len > IEEE80211_NWID_LEN) {
				error = EINVAL;
				break;
			}
			ireq->i_len = len;
			bzero(tmpstr, IEEE80211_NWID_LEN);
			bcopy(tmpptr, tmpstr, len);
			error = copyout(tmpstr, ireq->i_data,
			    IEEE80211_NWID_LEN);
			break;
		case IEEE80211_IOC_NUMSSIDS:
			ireq->i_val = 3;
			break;
		case IEEE80211_IOC_WEP:
			areq.an_type = AN_RID_ACTUALCFG;
			if (an_read_record(sc,
			    (struct an_ltv_gen *)&areq)) {
				error = EINVAL;
				break;
			}
			if (config->an_authtype & AN_AUTHTYPE_PRIVACY_IN_USE) {
				if (config->an_authtype &
				    AN_AUTHTYPE_ALLOW_UNENCRYPTED)
					ireq->i_val = IEEE80211_WEP_MIXED;
				else
					ireq->i_val = IEEE80211_WEP_ON;
			} else {
				ireq->i_val = IEEE80211_WEP_OFF;
			}
			break;
		case IEEE80211_IOC_WEPKEY:
			/*
			 * XXX: I'm not entierly convinced this is
			 * correct, but it's what is implemented in
			 * ancontrol so it will have to do until we get
			 * access to actual Cisco code.
			 */
			if (ireq->i_val < 0 || ireq->i_val > 7) {
				error = EINVAL;
				break;
			}
			len = 0;
			if (ireq->i_val < 4) {
				areq.an_type = AN_RID_WEP_TEMP;
				for (i = 0; i < 5; i++) {
					if (an_read_record(sc,
					    (struct an_ltv_gen *)&areq)) {
						error = EINVAL;
						break;
					}
					if (key->kindex == 0xffff)
						break;
					if (key->kindex == ireq->i_val)
						len = key->klen;
					/* Required to get next entry */
					areq.an_type = AN_RID_WEP_PERM;
				}
				if (error != 0)
					break;
			}
			/* We aren't allowed to read the value of the
			 * key from the card so we just output zeros
			 * like we would if we could read the card, but
			 * denied the user access.
			 */
			bzero(tmpstr, len);
			ireq->i_len = len;
			error = copyout(tmpstr, ireq->i_data, len);
			break;
		case IEEE80211_IOC_NUMWEPKEYS:
			ireq->i_val = 8;
			break;
		case IEEE80211_IOC_WEPTXKEY:
			/*
			 * For some strange reason, you have to read all
			 * keys before you can read the txkey.
			 */
			areq.an_type = AN_RID_WEP_TEMP;
			for (i = 0; i < 5; i++) {
				if (an_read_record(sc,
				    (struct an_ltv_gen *)&areq)) {
					error = EINVAL;
					break;
				}
				if (key->kindex == 0xffff)
					break;
				/* Required to get next entry */
				areq.an_type = AN_RID_WEP_PERM;
			}
			if (error != 0)
				break;

			areq.an_type = AN_RID_WEP_PERM;
			key->kindex = 0xffff;
			if (an_read_record(sc,
			    (struct an_ltv_gen *)&areq)) {
				error = EINVAL;
				break;
			}
			ireq->i_val = key->mac[0];
			break;
		case IEEE80211_IOC_AUTHMODE:
			areq.an_type = AN_RID_ACTUALCFG;
			if (an_read_record(sc,
			    (struct an_ltv_gen *)&areq)) {
				error = EINVAL;
				break;
			}
			if ((config->an_authtype & AN_AUTHTYPE_MASK) ==
			    AN_AUTHTYPE_NONE) {
			    ireq->i_val = IEEE80211_AUTH_NONE;
			} else if ((config->an_authtype & AN_AUTHTYPE_MASK) ==
			    AN_AUTHTYPE_OPEN) {
			    ireq->i_val = IEEE80211_AUTH_OPEN;
			} else if ((config->an_authtype & AN_AUTHTYPE_MASK) ==
			    AN_AUTHTYPE_SHAREDKEY) {
			    ireq->i_val = IEEE80211_AUTH_SHARED;
			} else
				error = EINVAL;
			break;
		case IEEE80211_IOC_STATIONNAME:
			areq.an_type = AN_RID_ACTUALCFG;
			if (an_read_record(sc,
			    (struct an_ltv_gen *)&areq)) {
				error = EINVAL;
				break;
			}
			ireq->i_len = sizeof(config->an_nodename);
			tmpptr = config->an_nodename;
			bzero(tmpstr, IEEE80211_NWID_LEN);
			bcopy(tmpptr, tmpstr, ireq->i_len);
			error = copyout(tmpstr, ireq->i_data,
			    IEEE80211_NWID_LEN);
			break;
		case IEEE80211_IOC_CHANNEL:
			areq.an_type = AN_RID_STATUS;
			if (an_read_record(sc,
			    (struct an_ltv_gen *)&areq)) {
				error = EINVAL;
				break;
			}
			ireq->i_val = status->an_cur_channel;
			break;
		case IEEE80211_IOC_POWERSAVE:
			areq.an_type = AN_RID_ACTUALCFG;
			if (an_read_record(sc,
			    (struct an_ltv_gen *)&areq)) {
				error = EINVAL;
				break;
			}
			if (config->an_psave_mode == AN_PSAVE_NONE) {
				ireq->i_val = IEEE80211_POWERSAVE_OFF;
			} else if (config->an_psave_mode == AN_PSAVE_CAM) {
				ireq->i_val = IEEE80211_POWERSAVE_CAM;
			} else if (config->an_psave_mode == AN_PSAVE_PSP) {
				ireq->i_val = IEEE80211_POWERSAVE_PSP;
			} else if (config->an_psave_mode == AN_PSAVE_PSP_CAM) {
				ireq->i_val = IEEE80211_POWERSAVE_PSP_CAM;
			} else
				error = EINVAL;
			break;
		case IEEE80211_IOC_POWERSAVESLEEP:
			areq.an_type = AN_RID_ACTUALCFG;
			if (an_read_record(sc,
			    (struct an_ltv_gen *)&areq)) {
				error = EINVAL;
				break;
			}
			ireq->i_val = config->an_listen_interval;
			break;
		}
		break;
	case SIOCS80211:
		if ((error = suser(p)))
			goto out;
		areq.an_len = sizeof(areq);
		/*
		 * We need a config structure for everything but the WEP
		 * key management and SSIDs so we get it now so avoid
		 * duplicating this code every time.
		 */
		if (ireq->i_type != IEEE80211_IOC_SSID &&
		    ireq->i_type != IEEE80211_IOC_WEPKEY &&
		    ireq->i_type != IEEE80211_IOC_WEPTXKEY) {
			areq.an_type = AN_RID_GENCONFIG;
			if (an_read_record(sc,
			    (struct an_ltv_gen *)&areq)) {
				error = EINVAL;
				break;
			}
		}
		switch (ireq->i_type) {
		case IEEE80211_IOC_SSID:
			areq.an_type = AN_RID_SSIDLIST;
			if (an_read_record(sc,
			    (struct an_ltv_gen *)&areq)) {
				error = EINVAL;
				break;
			}
			if (ireq->i_len > IEEE80211_NWID_LEN) {
				error = EINVAL;
				break;
			}
			switch (ireq->i_val) {
			case 0:
				error = copyin(ireq->i_data,
				    ssids->an_ssid1, ireq->i_len);
				ssids->an_ssid1_len = ireq->i_len;
				break;
			case 1:
				error = copyin(ireq->i_data,
				    ssids->an_ssid2, ireq->i_len);
				ssids->an_ssid2_len = ireq->i_len;
				break;
			case 2:
				error = copyin(ireq->i_data,
				    ssids->an_ssid3, ireq->i_len);
				ssids->an_ssid3_len = ireq->i_len;
				break;
			default:
				error = EINVAL;
				break;
			}
			break;
		case IEEE80211_IOC_WEP:
			switch (ireq->i_val) {
			case IEEE80211_WEP_OFF:
				config->an_authtype &=
				    ~(AN_AUTHTYPE_PRIVACY_IN_USE |
				    AN_AUTHTYPE_ALLOW_UNENCRYPTED);
				break;
			case IEEE80211_WEP_ON:
				config->an_authtype |=
				    AN_AUTHTYPE_PRIVACY_IN_USE;
				config->an_authtype &=
				    ~AN_AUTHTYPE_ALLOW_UNENCRYPTED;
				break;
			case IEEE80211_WEP_MIXED:
				config->an_authtype |=
				    AN_AUTHTYPE_PRIVACY_IN_USE |
				    AN_AUTHTYPE_ALLOW_UNENCRYPTED;
				break;
			default:
				error = EINVAL;
				break;
			}
			break;
		case IEEE80211_IOC_WEPKEY:
			if (ireq->i_val < 0 || ireq->i_val > 7 ||
			    ireq->i_len > 13) {
				error = EINVAL;
				break;
			}
			error = copyin(ireq->i_data, tmpstr, 13);
			if (error != 0)
				break;
			bzero(&areq, sizeof(struct an_ltv_key));
			areq.an_len = sizeof(struct an_ltv_key);
			key->mac[0] = 1;	/* The others are 0. */
			key->kindex = ireq->i_val % 4;
			if (ireq->i_val < 4)
				areq.an_type = AN_RID_WEP_TEMP;
			else
				areq.an_type = AN_RID_WEP_PERM;
			key->klen = ireq->i_len;
			bcopy(tmpstr, key->key, key->klen);
			break;
		case IEEE80211_IOC_WEPTXKEY:
			if (ireq->i_val < 0 || ireq->i_val > 3) {
				error = EINVAL;
				break;
			}
			bzero(&areq, sizeof(struct an_ltv_key));
			areq.an_len = sizeof(struct an_ltv_key);
			areq.an_type = AN_RID_WEP_PERM;
			key->kindex = 0xffff;
			key->mac[0] = ireq->i_val;
			break;
		case IEEE80211_IOC_AUTHMODE:
			switch (ireq->i_val) {
			case IEEE80211_AUTH_NONE:
				config->an_authtype = AN_AUTHTYPE_NONE |
				    (config->an_authtype & ~AN_AUTHTYPE_MASK);
				break;
			case IEEE80211_AUTH_OPEN:
				config->an_authtype = AN_AUTHTYPE_OPEN |
				    (config->an_authtype & ~AN_AUTHTYPE_MASK);
				break;
			case IEEE80211_AUTH_SHARED:
				config->an_authtype = AN_AUTHTYPE_SHAREDKEY |
				    (config->an_authtype & ~AN_AUTHTYPE_MASK);
				break;
			default:
				error = EINVAL;
			}
			break;
		case IEEE80211_IOC_STATIONNAME:
			if (ireq->i_len > 16) {
				error = EINVAL;
				break;
			}
			bzero(config->an_nodename, 16);
			error = copyin(ireq->i_data,
			    config->an_nodename, ireq->i_len);
			break;
		case IEEE80211_IOC_CHANNEL:
			/*
			 * The actual range is 1-14, but if you set it
			 * to 0 you get the default so we let that work
			 * too.
			 */
			if (ireq->i_val < 0 || ireq->i_val >14) {
				error = EINVAL;
				break;
			}
			config->an_ds_channel = ireq->i_val;
			break;
		case IEEE80211_IOC_POWERSAVE:
			switch (ireq->i_val) {
			case IEEE80211_POWERSAVE_OFF:
				config->an_psave_mode = AN_PSAVE_NONE;
				break;
			case IEEE80211_POWERSAVE_CAM:
				config->an_psave_mode = AN_PSAVE_CAM;
				break;
			case IEEE80211_POWERSAVE_PSP:
				config->an_psave_mode = AN_PSAVE_PSP;
				break;
			case IEEE80211_POWERSAVE_PSP_CAM:
				config->an_psave_mode = AN_PSAVE_PSP_CAM;
				break;
			default:
				error = EINVAL;
				break;
			}
			break;
		case IEEE80211_IOC_POWERSAVESLEEP:
			config->an_listen_interval = ireq->i_val;
			break;
		}

		if (!error)
			an_setdef(sc, &areq);
		break;
	default:
		error = EINVAL;
		break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -