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

📄 airo.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (!ai->micstats.enabled) {		//No Mic set or Mic OFF but we received a MIC'd packet.		if (memcmp ((u8*)eth + 14, micsnap, sizeof(micsnap)) == 0) {			ai->micstats.rxMICPlummed++;			return ERROR;		}		return SUCCESS;	}	if (ntohs(mic->typelen) == 0x888E)		return SUCCESS;	if (memcmp (mic->u.snap, micsnap, sizeof(micsnap)) != 0) {	    // Mic enabled but packet isn't Mic'd		ai->micstats.rxMICPlummed++;	    	return ERROR;	}	micSEQ = ntohl(mic->seq);            //store SEQ as CPU order	//At this point we a have a mic'd packet and mic is enabled	//Now do the mic error checking.	//Receive seq must be odd	if ( (micSEQ & 1) == 0 ) {		ai->micstats.rxWrongSequence++;		return ERROR;	}	for (i = 0; i < NUM_MODULES; i++) {		int mcast = eth->da[0] & 1;		//Determine proper context 		context = mcast ? &ai->mod[i].mCtx : &ai->mod[i].uCtx;			//Make sure context is valid		if (!context->valid) {			if (i == 0)				micError = NOMICPLUMMED;			continue;                		}	       	//DeMic it 		if (!mic->typelen)			mic->typelen = htons(payLen + sizeof(MICBuffer) - 2);			emmh32_init(&context->seed);		emmh32_update(&context->seed, eth->da, ETH_ALEN*2); 		emmh32_update(&context->seed, (u8 *)&mic->typelen, sizeof(mic->typelen)+sizeof(mic->u.snap)); 		emmh32_update(&context->seed, (u8 *)&mic->seq,sizeof(mic->seq));			emmh32_update(&context->seed, eth->da + ETH_ALEN*2,payLen);			//Calculate MIC		emmh32_final(&context->seed, digest);			if (memcmp(digest, &mic->mic, 4)) { //Make sure the mics match		  //Invalid Mic			if (i == 0)				micError = INCORRECTMIC;			continue;		}		//Check Sequence number if mics pass		if (RxSeqValid(ai, context, mcast, micSEQ) == SUCCESS) {			ai->micstats.rxSuccess++;			return SUCCESS;		}		if (i == 0)			micError = SEQUENCE;	}	// Update statistics	switch (micError) {		case NOMICPLUMMED: ai->micstats.rxMICPlummed++;   break;		case SEQUENCE:    ai->micstats.rxWrongSequence++; break;		case INCORRECTMIC: ai->micstats.rxIncorrectMIC++; break;		case NONE:  break;		case NOMIC: break;	}	return ERROR;}/*=========================================================================== * Description:  Checks the Rx Seq number to make sure it is valid *               and hasn't already been received *    *     Inputs: miccntx - mic context to check seq against *             micSeq  - the Mic seq number *    *    Returns: TRUE if valid otherwise FALSE.  * *    Author: sbraneky (10/15/01) *    Merciless hacks by rwilcher (1/14/02) *--------------------------------------------------------------------------- */static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq){	u32 seq,index;	//Allow for the ap being rebooted - if it is then use the next 	//sequence number of the current sequence number - might go backwards	if (mcast) {		if (test_bit(FLAG_UPDATE_MULTI, &ai->flags)) {			clear_bit (FLAG_UPDATE_MULTI, &ai->flags);			context->window = (micSeq > 33) ? micSeq : 33;			context->rx     = 0;        // Reset rx		}	} else if (test_bit(FLAG_UPDATE_UNI, &ai->flags)) {		clear_bit (FLAG_UPDATE_UNI, &ai->flags);		context->window = (micSeq > 33) ? micSeq : 33; // Move window		context->rx     = 0;        // Reset rx	}	//Make sequence number relative to START of window	seq = micSeq - (context->window - 33);	//Too old of a SEQ number to check.	if ((s32)seq < 0)		return ERROR;    	if ( seq > 64 ) {		//Window is infinite forward		MoveWindow(context,micSeq);		return SUCCESS;	}	// We are in the window. Now check the context rx bit to see if it was already sent	seq >>= 1;         //divide by 2 because we only have odd numbers	index = 1 << seq;  //Get an index number	if (!(context->rx & index)) {		//micSEQ falls inside the window.		//Add seqence number to the list of received numbers.		context->rx |= index;		MoveWindow(context,micSeq);		return SUCCESS;	}	return ERROR;}static void MoveWindow(miccntx *context, u32 micSeq){	u32 shift;	//Move window if seq greater than the middle of the window	if (micSeq > context->window) {		shift = (micSeq - context->window) >> 1;    		    //Shift out old		if (shift < 32)			context->rx >>= shift;		else			context->rx = 0;		context->window = micSeq;      //Move window	}}/*==============================================*//*========== EMMH ROUTINES  ====================*//*==============================================*//* mic accumulate */#define MIC_ACCUM(val)	\	context->accum += (u64)(val) * context->coeff[coeff_position++];static unsigned char aes_counter[16];/* expand the key to fill the MMH coefficient array */static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *tfm){  /* take the keying material, expand if necessary, truncate at 16-bytes */  /* run through AES counter mode to generate context->coeff[] */  	int i,j;	u32 counter;	u8 *cipher, plain[16];	struct scatterlist sg[1];	crypto_cipher_setkey(tfm, pkey, 16);	counter = 0;	for (i = 0; i < (sizeof(context->coeff)/sizeof(context->coeff[0])); ) {		aes_counter[15] = (u8)(counter >> 0);		aes_counter[14] = (u8)(counter >> 8);		aes_counter[13] = (u8)(counter >> 16);		aes_counter[12] = (u8)(counter >> 24);		counter++;		memcpy (plain, aes_counter, 16);		sg_set_buf(sg, plain, 16);		crypto_cipher_encrypt(tfm, sg, sg, 16);		cipher = kmap(sg->page) + sg->offset;		for (j=0; (j<16) && (i< (sizeof(context->coeff)/sizeof(context->coeff[0]))); ) {			context->coeff[i++] = ntohl(*(u32 *)&cipher[j]);			j += 4;		}	}}/* prepare for calculation of a new mic */static void emmh32_init(emmh32_context *context){	/* prepare for new mic calculation */	context->accum = 0;	context->position = 0;}/* add some bytes to the mic calculation */static void emmh32_update(emmh32_context *context, u8 *pOctets, int len){	int	coeff_position, byte_position;  	if (len == 0) return;  	coeff_position = context->position >> 2;  	/* deal with partial 32-bit word left over from last update */	byte_position = context->position & 3;	if (byte_position) {		/* have a partial word in part to deal with */		do {			if (len == 0) return;			context->part.d8[byte_position++] = *pOctets++;			context->position++;			len--;		} while (byte_position < 4);		MIC_ACCUM(htonl(context->part.d32));	}	/* deal with full 32-bit words */	while (len >= 4) {		MIC_ACCUM(htonl(*(u32 *)pOctets));		context->position += 4;		pOctets += 4;		len -= 4;	}	/* deal with partial 32-bit word that will be left over from this update */	byte_position = 0;	while (len > 0) {		context->part.d8[byte_position++] = *pOctets++;		context->position++;		len--;	}}/* mask used to zero empty bytes for final partial word */static u32 mask32[4] = { 0x00000000L, 0xFF000000L, 0xFFFF0000L, 0xFFFFFF00L };/* calculate the mic */static void emmh32_final(emmh32_context *context, u8 digest[4]){	int	coeff_position, byte_position;	u32	val;  	u64 sum, utmp;	s64 stmp;	coeff_position = context->position >> 2;  	/* deal with partial 32-bit word left over from last update */	byte_position = context->position & 3;	if (byte_position) {		/* have a partial word in part to deal with */		val = htonl(context->part.d32);		MIC_ACCUM(val & mask32[byte_position]);	/* zero empty bytes */	}	/* reduce the accumulated u64 to a 32-bit MIC */	sum = context->accum;	stmp = (sum  & 0xffffffffLL) - ((sum >> 32)  * 15);	utmp = (stmp & 0xffffffffLL) - ((stmp >> 32) * 15);	sum = utmp & 0xffffffffLL;	if (utmp > 0x10000000fLL)		sum -= 15;	val = (u32)sum;	digest[0] = (val>>24) & 0xFF;	digest[1] = (val>>16) & 0xFF;	digest[2] = (val>>8) & 0xFF;	digest[3] = val & 0xFF;}#endifstatic int readBSSListRid(struct airo_info *ai, int first,		      BSSListRid *list) {	int rc;			Cmd cmd;			Resp rsp;	if (first == 1) {			if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;			memset(&cmd, 0, sizeof(cmd));			cmd.cmd=CMD_LISTBSS;			if (down_interruptible(&ai->sem))				return -ERESTARTSYS;			issuecommand(ai, &cmd, &rsp);			up(&ai->sem);			/* Let the command take effect */			ai->task = current;			ssleep(3);			ai->task = NULL;		}	rc = PC4500_readrid(ai, first ? RID_BSSLISTFIRST : RID_BSSLISTNEXT,			    list, sizeof(*list), 1);	list->len = le16_to_cpu(list->len);	list->index = le16_to_cpu(list->index);	list->radioType = le16_to_cpu(list->radioType);	list->cap = le16_to_cpu(list->cap);	list->beaconInterval = le16_to_cpu(list->beaconInterval);	list->fh.dwell = le16_to_cpu(list->fh.dwell);	list->dsChannel = le16_to_cpu(list->dsChannel);	list->atimWindow = le16_to_cpu(list->atimWindow);	list->dBm = le16_to_cpu(list->dBm);	return rc;}static int readWepKeyRid(struct airo_info*ai, WepKeyRid *wkr, int temp, int lock) {	int rc = PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM,				wkr, sizeof(*wkr), lock);	wkr->len = le16_to_cpu(wkr->len);	wkr->kindex = le16_to_cpu(wkr->kindex);	wkr->klen = le16_to_cpu(wkr->klen);	return rc;}/* In the writeXXXRid routines we copy the rids so that we don't screwup * the originals when we endian them... */static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lock) {	int rc;	WepKeyRid wkr = *pwkr;	wkr.len = cpu_to_le16(wkr.len);	wkr.kindex = cpu_to_le16(wkr.kindex);	wkr.klen = cpu_to_le16(wkr.klen);	rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr), lock);	if (rc!=SUCCESS) printk(KERN_ERR "airo:  WEP_TEMP set %x\n", rc);	if (perm) {		rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr), lock);		if (rc!=SUCCESS) {			printk(KERN_ERR "airo:  WEP_PERM set %x\n", rc);		}	}	return rc;}static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) {	int i;	int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1);	ssidr->len = le16_to_cpu(ssidr->len);	for(i = 0; i < 3; i++) {		ssidr->ssids[i].len = le16_to_cpu(ssidr->ssids[i].len);	}	return rc;}static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr, int lock) {	int rc;	int i;	SsidRid ssidr = *pssidr;	ssidr.len = cpu_to_le16(ssidr.len);	for(i = 0; i < 3; i++) {		ssidr.ssids[i].len = cpu_to_le16(ssidr.ssids[i].len);	}	rc = PC4500_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr), lock);	return rc;}static int readConfigRid(struct airo_info*ai, int lock) {	int rc;	u16 *s;	ConfigRid cfg;	if (ai->config.len)		return SUCCESS;	rc = PC4500_readrid(ai, RID_ACTUALCONFIG, &cfg, sizeof(cfg), lock);	if (rc != SUCCESS)		return rc;	for(s = &cfg.len; s <= &cfg.rtsThres; s++) *s = le16_to_cpu(*s);	for(s = &cfg.shortRetryLimit; s <= &cfg.radioType; s++)		*s = le16_to_cpu(*s);	for(s = &cfg.txPower; s <= &cfg.radioSpecific; s++)		*s = le16_to_cpu(*s);	for(s = &cfg.arlThreshold; s <= &cfg._reserved4[0]; s++)		*s = cpu_to_le16(*s);	for(s = &cfg.autoWake; s <= &cfg.autoWake; s++)		*s = cpu_to_le16(*s);	ai->config = cfg;	return SUCCESS;}static inline void checkThrottle(struct airo_info *ai) {	int i;/* Old hardware had a limit on encryption speed */	if (ai->config.authType != AUTH_OPEN && maxencrypt) {		for(i=0; i<8; i++) {			if (ai->config.rates[i] > maxencrypt) {				ai->config.rates[i] = 0;			}		}	}}static int writeConfigRid(struct airo_info*ai, int lock) {	u16 *s;	ConfigRid cfgr;	if (!test_bit (FLAG_COMMIT, &ai->flags))		return SUCCESS;	clear_bit (FLAG_COMMIT, &ai->flags);	clear_bit (FLAG_RESET, &ai->flags);	checkThrottle(ai);	cfgr = ai->config;	if ((cfgr.opmode & 0xFF) == MODE_STA_IBSS)		set_bit(FLAG_ADHOC, &ai->flags);	else		clear_bit(FLAG_ADHOC, &ai->flags);	for(s = &cfgr.len; s <= &cfgr.rtsThres; s++) *s = cpu_to_le16(*s);	for(s = &cfgr.shortRetryLimit; s <= &cfgr.radioType; s++)		*s = cpu_to_le16(*s);	for(s = &cfgr.txPower; s <= &cfgr.radioSpecific; s++)		*s = cpu_to_le16(*s);	for(s = &cfgr.arlThreshold; s <= &cfgr._reserved4[0]; s++)		*s = cpu_to_le16(*s);	for(s = &cfgr.autoWake; s <= &cfgr.autoWake; s++)		*s = cpu_to_le16(*s);	return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr), lock);}static int readStatusRid(struct airo_info*ai, StatusRid *statr, int lock) {	int rc = PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock);	u16 *s;	statr->len = le16_to_cpu(statr->len);	for(s = &statr->mode; s <= &statr->SSIDlen; s++) *s = le16_to_cpu(*s);	for(s = &statr->beaconPeriod; s <= &statr->shortPreamble; s++)		*s = le16_to_cpu(*s);	statr->load = le16_to_cpu(statr->load);	statr->assocStatus = le16_to_cpu(statr->assocStatus);	return rc;}static int readAPListRid(struct airo_info*ai, APListRid *aplr) {	int rc =  PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1);	aplr->len = le16_to_cpu(aplr->len);	return rc;}static int writeAPListRid(struct airo_info*ai, APListRid *aplr, int lock) {	int rc;	aplr->len = cpu_to_le16(aplr->len);	rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock);	return rc;}

⌨️ 快捷键说明

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