📄 p80211conv.c
字号:
/* perform de-wep if necessary.. */ if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && WLAN_GET_FC_ISWEP(fc) && (wlandev->hostwep & HOSTWEP_DECRYPT)) { if (payload_length <= 8) { WLAN_LOG_ERROR("WEP frame too short (%u).\n", skb->len); return 1; } if ((foo = wep_decrypt(wlandev, skb->data + payload_offset + 4, payload_length - 8, -1, skb->data + payload_offset, skb->data + payload_offset + payload_length - 4))) { /* de-wep failed, drop skb. */ WLAN_LOG_DEBUG(1, "Host de-WEP failed, dropping frame (%d).\n", foo); wlandev->rx.decrypt_err++; return 2; } /* subtract the IV+ICV length off the payload */ payload_length -= 8; /* chop off the IV */ skb_pull(skb, 4); /* chop off the ICV. */ skb_trim(skb, skb->len - 4); wlandev->rx.decrypt++; } e_hdr = (wlan_ethhdr_t *) (skb->data + payload_offset); e_llc = (wlan_llc_t *) (skb->data + payload_offset); e_snap = (wlan_snap_t *) (skb->data + payload_offset + sizeof(wlan_llc_t)); /* Test for the various encodings */ if ( (payload_length >= sizeof(wlan_ethhdr_t)) && ( e_llc->dsap != 0xaa || e_llc->ssap != 0xaa ) && ((memcmp(daddr, e_hdr->daddr, WLAN_ETHADDR_LEN) == 0) || (memcmp(saddr, e_hdr->saddr, WLAN_ETHADDR_LEN) == 0))) { WLAN_LOG_DEBUG(3, "802.3 ENCAP len: %d\n", payload_length); /* 802.3 Encapsulated */ /* Test for an overlength frame */ if ( payload_length > (netdev->mtu + WLAN_ETHHDR_LEN)) { /* A bogus length ethfrm has been encap'd. */ /* Is someone trying an oflow attack? */ WLAN_LOG_ERROR("ENCAP frame too large (%d > %d)\n", payload_length, netdev->mtu + WLAN_ETHHDR_LEN); return 1; } /* Chop off the 802.11 header. it's already sane. */ skb_pull(skb, payload_offset); /* chop off the 802.11 CRC */ skb_trim(skb, skb->len - WLAN_CRC_LEN); } else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) && (e_llc->dsap == 0xaa) && (e_llc->ssap == 0xaa) && (e_llc->ctl == 0x03) && (((memcmp( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)==0) && (ethconv == WLAN_ETHCONV_8021h) && (p80211_stt_findproto(ieee2host16(e_snap->type)))) || (memcmp( e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN)!=0))) { WLAN_LOG_DEBUG(3, "SNAP+RFC1042 len: %d\n", payload_length); /* it's a SNAP + RFC1042 frame && protocol is in STT */ /* build 802.3 + RFC1042 */ /* Test for an overlength frame */ if ( payload_length > netdev->mtu ) { /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ WLAN_LOG_ERROR("SNAP frame too large (%d > %d)\n", payload_length, netdev->mtu); return 1; } /* chop 802.11 header from skb. */ skb_pull(skb, payload_offset); /* create 802.3 header at beginning of skb. */ e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN); memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN); memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN); e_hdr->type = htons(payload_length); /* chop off the 802.11 CRC */ skb_trim(skb, skb->len - WLAN_CRC_LEN); } else if ((payload_length >= sizeof(wlan_llc_t) + sizeof(wlan_snap_t)) && (e_llc->dsap == 0xaa) && (e_llc->ssap == 0xaa) && (e_llc->ctl == 0x03) ) { WLAN_LOG_DEBUG(3, "802.1h/RFC1042 len: %d\n", payload_length); /* it's an 802.1h frame || (an RFC1042 && protocol is not in STT) */ /* build a DIXII + RFC894 */ /* Test for an overlength frame */ if ((payload_length - sizeof(wlan_llc_t) - sizeof(wlan_snap_t)) > netdev->mtu) { /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ WLAN_LOG_ERROR("DIXII frame too large (%ld > %d)\n", (long int) (payload_length - sizeof(wlan_llc_t) - sizeof(wlan_snap_t)), netdev->mtu); return 1; } /* chop 802.11 header from skb. */ skb_pull(skb, payload_offset); /* chop llc header from skb. */ skb_pull(skb, sizeof(wlan_llc_t)); /* chop snap header from skb. */ skb_pull(skb, sizeof(wlan_snap_t)); /* create 802.3 header at beginning of skb. */ e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN); e_hdr->type = e_snap->type; memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN); memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN); /* chop off the 802.11 CRC */ skb_trim(skb, skb->len - WLAN_CRC_LEN); } else { WLAN_LOG_DEBUG(3, "NON-ENCAP len: %d\n", payload_length); /* 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 ( payload_length > netdev->mtu ) { /* A bogus length ethfrm has been sent. */ /* Is someone trying an oflow attack? */ WLAN_LOG_ERROR("OTHER frame too large (%d > %d)\n", payload_length, netdev->mtu); return 1; } /* Chop off the 802.11 header. */ skb_pull(skb, payload_offset); /* create 802.3 header at beginning of skb. */ e_hdr = (wlan_ethhdr_t *) skb_push(skb, WLAN_ETHHDR_LEN); memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN); memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN); e_hdr->type = htons(payload_length); /* chop off the 802.11 CRC */ skb_trim(skb, skb->len - WLAN_CRC_LEN); } skb->protocol = eth_type_trans(skb, netdev); skb->mac.raw = (unsigned char *) e_hdr; /* new MAC header */ /* jkriegl: process signal and noise as set in hfa384x_int_rx() */ /* jkriegl: only process signal/noise if requested by iwspy */ if (wlandev->spy_number) orinoco_spy_gather(wlandev, eth_hdr(skb)->h_source, P80211SKB_RXMETA(skb)); /* Free the metadata */ p80211skb_rxmeta_detach(skb); DBFEXIT; return 0;}/*----------------------------------------------------------------* 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. */ if (proto == 0x80f3) /* APPLETALK */ return 1; return 0;}/*----------------------------------------------------------------* p80211skb_rxmeta_detach** Disconnects the frmmeta and rxmeta from an skb.** Arguments:* wlandev The wlandev this skb belongs to.* skb The skb we're attaching to.** Returns: * 0 on success, non-zero otherwise* * Call context:* May be called in interrupt or non-interrupt context----------------------------------------------------------------*/voidp80211skb_rxmeta_detach(struct sk_buff *skb){ p80211_rxmeta_t *rxmeta; p80211_frmmeta_t *frmmeta; DBFENTER; /* Sanity checks */ if ( skb==NULL ) { /* bad skb */ WLAN_LOG_DEBUG(1, "Called w/ null skb.\n"); goto exit; } frmmeta = P80211SKB_FRMMETA(skb); if ( frmmeta == NULL ) { /* no magic */ WLAN_LOG_DEBUG(1, "Called w/ bad frmmeta magic.\n"); goto exit; } rxmeta = frmmeta->rx; if ( rxmeta == NULL ) { /* bad meta ptr */ WLAN_LOG_DEBUG(1, "Called w/ bad rxmeta ptr.\n"); goto exit; } /* Free rxmeta */ kfree(rxmeta); /* Clear skb->cb */ memset(skb->cb, 0, sizeof(skb->cb));exit: DBFEXIT; return;}/*----------------------------------------------------------------* p80211skb_rxmeta_attach** Allocates a p80211rxmeta structure, initializes it, and attaches* it to an skb.** Arguments:* wlandev The wlandev this skb belongs to.* skb The skb we're attaching to.** Returns: * 0 on success, non-zero otherwise* * Call context:* May be called in interrupt or non-interrupt context----------------------------------------------------------------*/intp80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb){ int result = 0; p80211_rxmeta_t *rxmeta; p80211_frmmeta_t *frmmeta; DBFENTER; /* If these already have metadata, we error out! */ if (P80211SKB_RXMETA(skb) != NULL) { WLAN_LOG_ERROR("%s: RXmeta already attached!\n", wlandev->name); result = 0; goto exit; } /* Allocate the rxmeta */ rxmeta = kmalloc(sizeof(p80211_rxmeta_t), GFP_ATOMIC); if ( rxmeta == NULL ) { WLAN_LOG_ERROR("%s: Failed to allocate rxmeta.\n", wlandev->name); result = 1; goto exit; } /* Initialize the rxmeta */ memset(rxmeta, 0, sizeof(p80211_rxmeta_t)); rxmeta->wlandev = wlandev; rxmeta->hosttime = jiffies; /* Overlay a frmmeta_t onto skb->cb */ memset(skb->cb, 0, sizeof(p80211_frmmeta_t)); frmmeta = (p80211_frmmeta_t*)(skb->cb); frmmeta->magic = P80211_FRMMETA_MAGIC; frmmeta->rx = rxmeta;exit: DBFEXIT; return result;}/*----------------------------------------------------------------* p80211skb_free** Frees an entire p80211skb by checking and freeing the meta struct* and then freeing the skb.** Arguments:* wlandev The wlandev this skb belongs to.* skb The skb we're attaching to.** Returns: * 0 on success, non-zero otherwise* * Call context:* May be called in interrupt or non-interrupt context----------------------------------------------------------------*/voidp80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb){ p80211_frmmeta_t *meta; DBFENTER; meta = P80211SKB_FRMMETA(skb); if ( meta && meta->rx) { p80211skb_rxmeta_detach(skb); } else { WLAN_LOG_ERROR("Freeing an skb (%p) w/ no frmmeta.\n", skb); } dev_kfree_skb(skb); DBFEXIT; return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -