📄 p80211conv.c
字号:
skb_put( ((struct sk_buff*)pb->ethhostbuf), buflen); /* make room */ pb->ethbuf = ((struct sk_buff*)pb->ethhostbuf)->data; pb->ethbuflen = buflen; /* setup the pointers */ pb->eth_hdr = (wlan_ethhdr_t*)pb->ethbuf; pb->eth_llc = (wlan_llc_t*)(pb->ethbuf + sizeof(wlan_ethhdr_t)); pb->eth_snap = (wlan_snap_t*) (pb->ethbuf + sizeof(wlan_ethhdr_t) + sizeof(wlan_llc_t)); pb->eth_payload = pb->ethbuf + sizeof(wlan_ethhdr_t); pb->eth_payloadlen = buflen - sizeof(wlan_ethhdr_t); /* now copy the data from the 80211 frame */ memcpy( pb->ethbuf, pb->p80211_payload, buflen); /* copy the data */ } else if ( pb->p80211_llc->dsap == 0xaa && pb->p80211_llc->ssap == 0xaa && pb->p80211_llc->ctl == 0x03 && memcmp( pb->p80211_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) == 0 && ethconv == WLAN_ETHCONV_8021h && p80211_stt_findproto(ieee2host16(pb->p80211_snap->type)) ) { /* it's a SNAP + RFC1042 frame && protocol is in STT */ /* build 802.3 + RFC1042 */ /* Test for an overlength frame */ if ( pb->p80211_payloadlen > WLAN_MAX_ETHFRM_LEN - WLAN_ETHHDR_LEN ) { /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ return 1; } llclen = pb->p80211_payloadlen; buflen = wlan_max( llclen + sizeof(wlan_ethhdr_t), WLAN_MIN_ETHFRM_LEN); pb->ethhostbuf = dev_alloc_skb(buflen + 2); /* +2 is attempt to align IP header */ if ( pb->ethhostbuf == NULL ) return 1; skb_reserve( (struct sk_buff*)pb->ethhostbuf, 2); skb_put( (struct sk_buff*)pb->ethhostbuf, buflen); /* make room */ pb->ethbuf = ((struct sk_buff*)pb->ethhostbuf)->data; pb->ethbuflen = buflen;/* memset( pb->ethbuf, 0, buflen); */ /* zero for possible PAD */ /* set up the pointers */ pb->eth_hdr = (wlan_ethhdr_t*)pb->ethbuf; pb->eth_llc = (wlan_llc_t*)(pb->ethbuf + sizeof(wlan_ethhdr_t)); pb->eth_snap = (wlan_snap_t*) (pb->ethbuf + sizeof(wlan_ethhdr_t) + sizeof(wlan_llc_t)); pb->eth_payload = pb->ethbuf + sizeof(wlan_ethhdr_t); pb->eth_payloadlen = llclen; /* set up the 802.3 header */ pb->eth_hdr->type = htons(pb->eth_payloadlen); memcpy( pb->eth_hdr->daddr, daddr, WLAN_ETHADDR_LEN); memcpy( pb->eth_hdr->saddr, saddr, WLAN_ETHADDR_LEN); /* now copy the data from the 80211 frame */ memcpy( pb->eth_payload, pb->p80211_payload, pb->p80211_payloadlen); } else if ( pb->p80211_llc->dsap == 0xaa && pb->p80211_llc->ssap == 0xaa && pb->p80211_llc->ctl == 0x03 ) { /* it's an 802.1h frame || (an RFC1042 && protocol is not in STT) */ /* build a DIXII + RFC894 */ dixlen = pb->p80211_payloadlen - sizeof(wlan_llc_t) - sizeof(wlan_snap_t); /* Test for an overlength frame */ if ( dixlen + WLAN_ETHHDR_LEN > WLAN_MAX_ETHFRM_LEN) { /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ return 1; } dixlen = pb->p80211_payloadlen - sizeof(wlan_llc_t) - sizeof(wlan_snap_t); buflen = wlan_max( dixlen + sizeof(wlan_ethhdr_t), WLAN_MIN_ETHFRM_LEN); pb->ethhostbuf = dev_alloc_skb(buflen + 2); /* +2 is attempt to align IP header */ if ( pb->ethhostbuf == NULL ) return 1; skb_reserve( (struct sk_buff*)pb->ethhostbuf, 2); skb_put( (struct sk_buff*)pb->ethhostbuf, buflen); /* make room */ pb->ethbuf = ((struct sk_buff*)pb->ethhostbuf)->data; pb->ethbuflen = buflen;/* memset( pb->ethbuf, 0, buflen); */ /* zero for possible PAD */ /* set up the pointers */ pb->eth_hdr = (wlan_ethhdr_t*)pb->ethbuf; pb->eth_llc = NULL; pb->eth_snap = NULL; pb->eth_payload = pb->ethbuf + sizeof(wlan_ethhdr_t); pb->eth_payloadlen = dixlen; /* make sure the llc and snap ptrs are set */ pb->p80211_llc = (wlan_llc_t*)pb->p80211_payload; pb->p80211_snap = (wlan_snap_t*) (pb->p80211_payload + sizeof(wlan_llc_t)); /* set up the DIXII header */ pb->eth_hdr->type = pb->p80211_snap->type; memcpy( pb->eth_hdr->daddr, daddr, WLAN_ETHADDR_LEN); memcpy( pb->eth_hdr->saddr, saddr, WLAN_ETHADDR_LEN); /* now copy the data from the 80211 frame */ memcpy( pb->eth_payload, pb->p80211_payload + sizeof(wlan_llc_t) + sizeof(wlan_snap_t), dixlen); } else { /* any NON-ENCAP */ /* it's a generic 80211+LLC or IPX 'Raw 802.3' */ /* build an 802.3 frame */ /* allocate space and setup hostbuf */ /* Test for an overlength frame */ if ( pb->p80211_payloadlen + WLAN_ETHHDR_LEN > WLAN_MAX_ETHFRM_LEN) { /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ return 1; } llclen = pb->p80211_payloadlen; buflen = wlan_max( llclen + sizeof(wlan_ethhdr_t), WLAN_MIN_ETHFRM_LEN); pb->ethhostbuf = dev_alloc_skb(buflen + 2); /* +2 is attempt to align IP header */ if ( pb->ethhostbuf == NULL ) return 1; skb_reserve( (struct sk_buff*)pb->ethhostbuf, 2); skb_put( (struct sk_buff*)pb->ethhostbuf, buflen); /* make room */ pb->ethbuf = ((struct sk_buff*)pb->ethhostbuf)->data; pb->ethbuflen = buflen;/* memset( pb->ethbuf, 0, buflen); */ /* zero for possible PAD */ /* set up the pointers */ pb->eth_hdr = (wlan_ethhdr_t*)pb->ethbuf; pb->eth_llc = (wlan_llc_t*)(pb->ethbuf + sizeof(wlan_ethhdr_t)); pb->eth_snap = (wlan_snap_t*) (pb->ethbuf + sizeof(wlan_ethhdr_t) + sizeof(wlan_llc_t)); pb->eth_payload = pb->ethbuf + sizeof(wlan_ethhdr_t); pb->eth_payloadlen = llclen; /* set up the 802.3 header */ pb->eth_hdr->type = htons(pb->eth_payloadlen); memcpy( pb->eth_hdr->daddr, daddr, WLAN_ETHADDR_LEN); memcpy( pb->eth_hdr->saddr, saddr, WLAN_ETHADDR_LEN); /* now copy the data from the 80211 frame */ memcpy( pb->eth_payload, pb->p80211_payload, pb->p80211_payloadlen); } return 0;}/*----------------------------------------------------------------* p80211pb_freeskb** Free method for wlan_pb's that have skbs in them. Called* via ptr from p80211pb_free. ** Arguments:* buf Ptr to an skb* size Passed in to match the ptr declaration.* Unused in this function.** Returns: * nothing* * Call context:* May be called in interrupt or non-interrupt context----------------------------------------------------------------*/void p80211pb_freeskb( void *buf, int size ){ dev_kfree_skb( (struct sk_buff*)buf );}/*----------------------------------------------------------------* p80211pb_pbfreeskb** Free method for wlan_pb's that linux kmalloc'd buffers in them. * Called via ptr from p80211pb_free. ** Arguments:* buf Ptr to buffer* size Size of buffer** Returns: * nothing* * Call context:* May be called in interrupt or non-interrupt context----------------------------------------------------------------*/void p80211pb_kfree_s( void *buf, int size){ kfree_s( buf, size);}/*----------------------------------------------------------------* p80211pb_alloc** Allocs and zeros a wlan_pb structure. Largely here for symmetry* with the pbfree routine. Also handy w/ ports to platforms where* we have fixed alloc pools.** Arguments:* none** Returns: * The address of a zeroed wlan_pb on success, NULL otherwise.* * Call context:* May be called in interrupt or non-interrupt context----------------------------------------------------------------*/wlan_pb_t* p80211pb_alloc(void){ wlan_pb_t *pb; pb = kmalloc( sizeof(wlan_pb_t), GFP_ATOMIC); if ( pb != NULL ) { memset(pb, 0, sizeof(wlan_pb_t)); } return pb;}/*----------------------------------------------------------------* p80211pb_alloc_p80211** Allocates a buffer for an 80211 frame and sets the ptrs in a * given pb. Primarily used by the receive path. Handled* here so that the allocation used and the free method are set* in one place (helps with portability?).** Arguments:* pb ptr to a wlan_pb_t previously allocated w/ p80211pb_alloc* if NULL, calls p80211pb_alloc.* size length of the 802.11 buffer to allocate. Note that* on some platforms w/ fixed size buffer pools, the size* will be ignored for allocation but _will_ be set in* the pb structure.** Returns: * The address of the given or allocated wlan_pb on success, * NULL otherwise.* * Call context:* May be called in interrupt or non-interrupt context----------------------------------------------------------------*/wlan_pb_t* p80211pb_alloc_p80211(wlan_pb_t *pb, UINT len){ if ( pb == NULL ) { pb = p80211pb_alloc(); } if ( pb != NULL ) { pb->p80211hostbuf = kmalloc( len, GFP_ATOMIC); if ( pb->p80211hostbuf != NULL ) { pb->p80211free = p80211pb_kfree_s; pb->p80211buf = (UINT8*)pb->p80211hostbuf; pb->p80211buflen = len; pb->p80211frmlen = len; /* initially assume frm is same as buf */ pb->p80211_hdr = (p80211_hdr_t*)pb->p80211buf; pb->p80211_payload = pb->p80211buf + WLAN_HDR_A3_LEN; pb->p80211_payloadlen = pb->p80211buflen - WLAN_HDR_A3_LEN - WLAN_CRC_LEN; } } return pb;}/*----------------------------------------------------------------* p80211pb_free** Frees the ethhostbuf and the p80211hostbuf elements of a wlan_pb* if there is a free method for each. Then frees the wlan_pb itself.** Arguments:* pb ptr to a wlan_pb_t previously allocated w/ p80211pb_alloc* or p80211pb_alloc_p80211.** Returns: * nothing* * Call context:* May be called in interrupt or non-interrupt context----------------------------------------------------------------*/void p80211pb_free(wlan_pb_t* pb){ if ( pb != NULL ) { if ( pb->ethhostbuf != NULL && pb->ethfree != NULL) { (*(pb->ethfree))(pb->ethhostbuf, pb->ethbuflen); } if ( pb->p80211hostbuf != NULL && pb->p80211free != NULL) { (*(pb->p80211free))(pb->p80211hostbuf, pb->p80211buflen); } kfree_s(pb, sizeof(wlan_pb_t)); }}/*----------------------------------------------------------------* p80211_stt_findproto** Searches the 802.1h Selective Translation Table for a given * protocol.** Arguments:* proto protocl number (in host order) to search for.** Returns: * 1 - if the table is empty or a match is found.* 0 - if the table is non-empty and a match is not found.* * Call context:* May be called in interrupt or non-interrupt context----------------------------------------------------------------*/int p80211_stt_findproto(UINT16 proto){ /* Always return found for now. This is the behavior used by the */ /* Zoom Win95 driver when 802.1h mode is selected */ /* TODO: If necessary, add an actual search we'll probably need this to match the CMAC's way of doing things. Need to do some testing to confirm. */ return 1;}#if 0/* MSM: This function is currently unused. Not sure if we'll ever need it. *//*----------------------------------------------------------------* p80211_stt_addproto** Add a protocol to the 802.1h Selective Translation Table.** Arguments:* proto protocl number (in host order) to search for.** Returns: * nothing* * Call context:* May be called in interrupt or non-interrupt context----------------------------------------------------------------*/int p80211_stt_addproto(UINT16 proto){ return;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -