📄 airo.c
字号:
miccntx mCtx; // Multicast context miccntx uCtx; // Unicast context} mic_module;typedef struct { unsigned int rid: 16; unsigned int len: 15; unsigned int valid: 1; dma_addr_t host_addr;} Rid;typedef struct { unsigned int offset: 15; unsigned int eoc: 1; unsigned int len: 15; unsigned int valid: 1; dma_addr_t host_addr;} TxFid;typedef struct { unsigned int ctl: 15; unsigned int rdy: 1; unsigned int len: 15; unsigned int valid: 1; dma_addr_t host_addr;} RxFid;/* * Host receive descriptor */typedef struct { unsigned char __iomem *card_ram_off; /* offset into card memory of the desc */ RxFid rx_desc; /* card receive descriptor */ char *virtual_host_addr; /* virtual address of host receive buffer */ int pending;} HostRxDesc;/* * Host transmit descriptor */typedef struct { unsigned char __iomem *card_ram_off; /* offset into card memory of the desc */ TxFid tx_desc; /* card transmit descriptor */ char *virtual_host_addr; /* virtual address of host receive buffer */ int pending;} HostTxDesc;/* * Host RID descriptor */typedef struct { unsigned char __iomem *card_ram_off; /* offset into card memory of the descriptor */ Rid rid_desc; /* card RID descriptor */ char *virtual_host_addr; /* virtual address of host receive buffer */} HostRidDesc;typedef struct { u16 sw0; u16 sw1; u16 status; u16 len;#define HOST_SET (1 << 0)#define HOST_INT_TX (1 << 1) /* Interrupt on successful TX */#define HOST_INT_TXERR (1 << 2) /* Interrupt on unseccessful TX */#define HOST_LCC_PAYLOAD (1 << 4) /* LLC payload, 0 = Ethertype */#define HOST_DONT_RLSE (1 << 5) /* Don't release buffer when done */#define HOST_DONT_RETRY (1 << 6) /* Don't retry trasmit */#define HOST_CLR_AID (1 << 7) /* clear AID failure */#define HOST_RTS (1 << 9) /* Force RTS use */#define HOST_SHORT (1 << 10) /* Do short preamble */ u16 ctl; u16 aid; u16 retries; u16 fill;} TxCtlHdr;typedef struct { u16 ctl; u16 duration; char addr1[6]; char addr2[6]; char addr3[6]; u16 seq; char addr4[6];} WifiHdr;typedef struct { TxCtlHdr ctlhdr; u16 fill1; u16 fill2; WifiHdr wifihdr; u16 gaplen; u16 status;} WifiCtlHdr;WifiCtlHdr wifictlhdr8023 = { .ctlhdr = { .ctl = HOST_DONT_RLSE, }};#ifdef WIRELESS_EXT// Frequency list (map channels to frequencies)static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484 };// A few details needed for WEP (Wireless Equivalent Privacy)#define MAX_KEY_SIZE 13 // 128 (?) bits#define MIN_KEY_SIZE 5 // 40 bits RC4 - WEPtypedef struct wep_key_t { u16 len; u8 key[16]; /* 40-bit and 104-bit keys */} wep_key_t;/* Backward compatibility */#ifndef IW_ENCODE_NOKEY#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */#define IW_ENCODE_MODE (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN)#endif /* IW_ENCODE_NOKEY *//* List of Wireless Handlers (new API) */static const struct iw_handler_def airo_handler_def;#endif /* WIRELESS_EXT */static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";struct airo_info;static int get_dec_u16( char *buffer, int *start, int limit );static void OUT4500( struct airo_info *, u16 register, u16 value );static unsigned short IN4500( struct airo_info *, u16 register );static u16 setup_card(struct airo_info*, u8 *mac, int lock);static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock );static void disable_MAC(struct airo_info *ai, int lock);static void enable_interrupts(struct airo_info*);static void disable_interrupts(struct airo_info*);static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp);static int bap_setup(struct airo_info*, u16 rid, u16 offset, int whichbap);static int aux_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen, int whichbap);static int fast_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen, int whichbap);static int bap_write(struct airo_info*, const u16 *pu16Src, int bytelen, int whichbap);static int PC4500_accessrid(struct airo_info*, u16 rid, u16 accmd);static int PC4500_readrid(struct airo_info*, u16 rid, void *pBuf, int len, int lock);static int PC4500_writerid(struct airo_info*, u16 rid, const void *pBuf, int len, int lock);static int do_writerid( struct airo_info*, u16 rid, const void *rid_data, int len, int dummy );static u16 transmit_allocate(struct airo_info*, int lenPayload, int raw);static int transmit_802_3_packet(struct airo_info*, int len, char *pPacket);static int transmit_802_11_packet(struct airo_info*, int len, char *pPacket);static int mpi_send_packet (struct net_device *dev);static void mpi_unmap_card(struct pci_dev *pci);static void mpi_receive_802_3(struct airo_info *ai);static void mpi_receive_802_11(struct airo_info *ai);static int waitbusy (struct airo_info *ai);static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs *regs);static int airo_thread(void *data);static void timer_func( struct net_device *dev );static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);#ifdef WIRELESS_EXTstruct iw_statistics *airo_get_wireless_stats (struct net_device *dev);static void airo_read_wireless_stats (struct airo_info *local);#endif /* WIRELESS_EXT */#ifdef CISCO_EXTstatic int readrids(struct net_device *dev, aironet_ioctl *comp);static int writerids(struct net_device *dev, aironet_ioctl *comp);int flashcard(struct net_device *dev, aironet_ioctl *comp);#endif /* CISCO_EXT */#ifdef MICSUPPORTstatic void micinit(struct airo_info *ai);static int micsetup(struct airo_info *ai);static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len);static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen);#include <linux/crypto.h>#endifstruct airo_info { struct net_device_stats stats; struct net_device *dev; /* Note, we can have MAX_FIDS outstanding. FIDs are 16-bits, so we use the high bit to mark whether it is in use. */#define MAX_FIDS 6#define MPI_MAX_FIDS 1 int fids[MAX_FIDS]; ConfigRid config; char keyindex; // Used with auto wep char defindex; // Used with auto wep struct proc_dir_entry *proc_entry; spinlock_t aux_lock; unsigned long flags;#define FLAG_PROMISC 8 /* IFF_PROMISC 0x100 - include/linux/if.h */#define FLAG_RADIO_OFF 0 /* User disabling of MAC */#define FLAG_RADIO_DOWN 1 /* ifup/ifdown disabling of MAC */#define FLAG_RADIO_MASK 0x03#define FLAG_ENABLED 2#define FLAG_ADHOC 3 /* Needed by MIC */#define FLAG_MIC_CAPABLE 4#define FLAG_UPDATE_MULTI 5#define FLAG_UPDATE_UNI 6#define FLAG_802_11 7#define FLAG_PENDING_XMIT 9#define FLAG_PENDING_XMIT11 10#define FLAG_MPI 11#define FLAG_REGISTERED 12#define FLAG_COMMIT 13#define FLAG_RESET 14#define FLAG_FLASHING 15#define JOB_MASK 0x1ff0000#define JOB_DIE 16#define JOB_XMIT 17#define JOB_XMIT11 18#define JOB_STATS 19#define JOB_PROMISC 20#define JOB_MIC 21#define JOB_EVENT 22#define JOB_AUTOWEP 23#define JOB_WSTATS 24 int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen, int whichbap); unsigned short *flash; tdsRssiEntry *rssi; struct task_struct *task; struct semaphore sem; pid_t thr_pid; wait_queue_head_t thr_wait; struct completion thr_exited; unsigned long expires; struct { struct sk_buff *skb; int fid; } xmit, xmit11; struct net_device *wifidev;#ifdef WIRELESS_EXT struct iw_statistics wstats; // wireless stats unsigned long scan_timestamp; /* Time started to scan */ struct iw_spy_data spy_data; struct iw_public_data wireless_data;#endif /* WIRELESS_EXT */#ifdef MICSUPPORT /* MIC stuff */ struct crypto_tfm *tfm; mic_module mod[2]; mic_statistics micstats;#endif HostRxDesc rxfids[MPI_MAX_FIDS]; // rx/tx/config MPI350 descriptors HostTxDesc txfids[MPI_MAX_FIDS]; HostRidDesc config_desc; unsigned long ridbus; // phys addr of config_desc struct sk_buff_head txq;// tx queue used by mpi350 code struct pci_dev *pci; unsigned char __iomem *pcimem; unsigned char __iomem *pciaux; unsigned char *shared; dma_addr_t shared_dma; int power; SsidRid *SSID; APListRid *APList;#define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE char proc_name[IFNAMSIZ];};static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen, int whichbap) { return ai->bap_read(ai, pu16Dst, bytelen, whichbap);}static int setup_proc_entry( struct net_device *dev, struct airo_info *apriv );static int takedown_proc_entry( struct net_device *dev, struct airo_info *apriv );#ifdef MICSUPPORT/*********************************************************************** * MIC ROUTINES * *********************************************************************** */static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq);static void MoveWindow(miccntx *context, u32 micSeq);void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *);void emmh32_init(emmh32_context *context);void emmh32_update(emmh32_context *context, u8 *pOctets, int len);void emmh32_final(emmh32_context *context, u8 digest[4]);/* micinit - Initialize mic seed */static void micinit(struct airo_info *ai){ MICRid mic_rid; clear_bit(JOB_MIC, &ai->flags); PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0); up(&ai->sem); ai->micstats.enabled = (mic_rid.state & 0x00FF) ? 1 : 0; if (ai->micstats.enabled) { /* Key must be valid and different */ if (mic_rid.multicastValid && (!ai->mod[0].mCtx.valid || (memcmp (ai->mod[0].mCtx.key, mic_rid.multicast, sizeof(ai->mod[0].mCtx.key)) != 0))) { /* Age current mic Context */ memcpy(&ai->mod[1].mCtx,&ai->mod[0].mCtx,sizeof(miccntx)); /* Initialize new context */ memcpy(&ai->mod[0].mCtx.key,mic_rid.multicast,sizeof(mic_rid.multicast)); ai->mod[0].mCtx.window = 33; //Window always points to the middle ai->mod[0].mCtx.rx = 0; //Rx Sequence numbers ai->mod[0].mCtx.tx = 0; //Tx sequence numbers ai->mod[0].mCtx.valid = 1; //Key is now valid /* Give key to mic seed */ emmh32_setseed(&ai->mod[0].mCtx.seed,mic_rid.multicast,sizeof(mic_rid.multicast), ai->tfm); } /* Key must be valid and different */ if (mic_rid.unicastValid && (!ai->mod[0].uCtx.valid || (memcmp(ai->mod[0].uCtx.key, mic_rid.unicast, sizeof(ai->mod[0].uCtx.key)) != 0))) { /* Age current mic Context */ memcpy(&ai->mod[1].uCtx,&ai->mod[0].uCtx,sizeof(miccntx)); /* Initialize new context */ memcpy(&ai->mod[0].uCtx.key,mic_rid.unicast,sizeof(mic_rid.unicast)); ai->mod[0].uCtx.window = 33; //Window always points to the middle ai->mod[0].uCtx.rx = 0; //Rx Sequence numbers ai->mod[0].uCtx.tx = 0; //Tx sequence numbers ai->mod[0].uCtx.valid = 1; //Key is now valid //Give key to mic seed emmh32_setseed(&ai->mod[0].uCtx.seed, mic_rid.unicast, sizeof(mic_rid.unicast), ai->tfm); } } else { /* So next time we have a valid key and mic is enabled, we will update * the sequence number if the key is the same as before. */ ai->mod[0].uCtx.valid = 0; ai->mod[0].mCtx.valid = 0; }}/* micsetup - Get ready for business */static int micsetup(struct airo_info *ai) { int i; if (ai->tfm == NULL) ai->tfm = crypto_alloc_tfm("aes", 0); if (ai->tfm == NULL) { printk(KERN_ERR "airo: failed to load transform for AES\n"); return ERROR; } for (i=0; i < NUM_MODULES; i++) { memset(&ai->mod[i].mCtx,0,sizeof(miccntx)); memset(&ai->mod[i].uCtx,0,sizeof(miccntx)); } return SUCCESS;}char micsnap[]= {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};/*=========================================================================== * Description: Mic a packet * * Inputs: etherHead * pointer to an 802.3 frame * * Returns: BOOLEAN if successful, otherwise false. * PacketTxLen will be updated with the mic'd packets size. * * Caveats: It is assumed that the frame buffer will already * be big enough to hold the largets mic message possible. * (No memory allocation is done here). * * Author: sbraneky (10/15/01) * Merciless hacks by rwilcher (1/14/02) */static int encapsulate(struct airo_info *ai ,etherHead *frame, MICBuffer *mic, int payLen){ miccntx *context; // Determine correct context // If not adhoc, always use unicast key if (test_bit(FLAG_ADHOC, &ai->flags) && (frame->da[0] & 0x1)) context = &ai->mod[0].mCtx; else context = &ai->mod[0].uCtx; if (!context->valid) return ERROR; mic->typelen = htons(payLen + 16); //Length of Mic'd packet memcpy(&mic->u.snap, micsnap, sizeof(micsnap)); // Add Snap // Add Tx sequence mic->seq = htonl(context->tx); context->tx += 2; emmh32_init(&context->seed); // Mic the packet emmh32_update(&context->seed,frame->da,ETH_ALEN * 2); // DA,SA emmh32_update(&context->seed,(u8*)&mic->typelen,10); // Type/Length and Snap emmh32_update(&context->seed,(u8*)&mic->seq,sizeof(mic->seq)); //SEQ emmh32_update(&context->seed,frame->da + ETH_ALEN * 2,payLen); //payload emmh32_final(&context->seed, (u8*)&mic->mic); /* New Type/length ?????????? */ mic->typelen = 0; //Let NIC know it could be an oversized packet return SUCCESS;}typedef enum { NONE, NOMIC, NOMICPLUMMED, SEQUENCE, INCORRECTMIC,} mic_error;/*=========================================================================== * Description: Decapsulates a MIC'd packet and returns the 802.3 packet * (removes the MIC stuff) if packet is a valid packet. * * Inputs: etherHead pointer to the 802.3 packet * * Returns: BOOLEAN - TRUE if packet should be dropped otherwise FALSE * * Author: sbraneky (10/15/01) * Merciless hacks by rwilcher (1/14/02) *--------------------------------------------------------------------------- */static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *eth, u16 payLen){ int i; u32 micSEQ; miccntx *context; u8 digest[4]; mic_error micError = NONE; // Check if the packet is a Mic'd packet 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -