📄 ieee80211softmac_io.c
字号:
/* * Some parts based on code from net80211 * Copyright (c) 2001 Atsushi Onoe * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * Alternatively, this software may be distributed under the terms of the * GNU General Public License ("GPL") version 2 as published by the Free * Software Foundation. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */#include "ieee80211softmac_priv.h"/* Helper functions for inserting data into the frames *//* * Adds an ESSID element to the frame * */static u8 *ieee80211softmac_add_essid(u8 *dst, struct ieee80211softmac_essid *essid){ if (essid) { *dst++ = MFIE_TYPE_SSID; *dst++ = essid->len; memcpy(dst, essid->data, essid->len); return dst+essid->len; } else { *dst++ = MFIE_TYPE_SSID; *dst++ = 0; return dst; }} /* Adds Supported Rates and if required Extended Rates Information Element * to the frame, ASSUMES WE HAVE A SORTED LIST OF RATES */static u8 *ieee80211softmac_frame_add_rates(u8 *dst, const struct ieee80211softmac_ratesinfo *r){ int cck_len, ofdm_len; *dst++ = MFIE_TYPE_RATES; for(cck_len=0; ieee80211_is_cck_rate(r->rates[cck_len]) && (cck_len < r->count);cck_len++); if(cck_len > IEEE80211SOFTMAC_MAX_RATES_LEN) cck_len = IEEE80211SOFTMAC_MAX_RATES_LEN; *dst++ = cck_len; memcpy(dst, r->rates, cck_len); dst += cck_len; if(cck_len < r->count){ for (ofdm_len=0; ieee80211_is_ofdm_rate(r->rates[ofdm_len + cck_len]) && (ofdm_len + cck_len < r->count); ofdm_len++); if (ofdm_len > 0) { if (ofdm_len > IEEE80211SOFTMAC_MAX_EX_RATES_LEN) ofdm_len = IEEE80211SOFTMAC_MAX_EX_RATES_LEN; *dst++ = MFIE_TYPE_RATES_EX; *dst++ = ofdm_len; memcpy(dst, r->rates + cck_len, ofdm_len); dst += ofdm_len; } } return dst;}/* Allocate a management frame */static u8 * ieee80211softmac_alloc_mgt(u32 size){ u8 * data; /* Add the header and FCS to the size */ size = size + IEEE80211_3ADDR_LEN; if(size > IEEE80211_DATA_LEN) return NULL; /* Allocate the frame */ data = kmalloc(size, GFP_ATOMIC); memset(data, 0, size); return data;}/* * Add a 2 Address Header */static void ieee80211softmac_hdr_2addr(struct ieee80211softmac_device *mac, struct ieee80211_hdr_2addr *header, u32 type, u8 *dest){ /* Fill in the frame control flags */ header->frame_ctl = cpu_to_le16(type); /* Control packets always have WEP turned off */ if(type > IEEE80211_STYPE_CFENDACK && type < IEEE80211_STYPE_PSPOLL) header->frame_ctl |= mac->ieee->sec.level ? cpu_to_le16(IEEE80211_FCTL_PROTECTED) : 0; /* Fill in the duration */ header->duration_id = 0; /* FIXME: How do I find this? * calculate. But most drivers just fill in 0 (except if it's a station id of course) */ /* Fill in the Destination Address */ if(dest == NULL) memset(header->addr1, 0xFF, ETH_ALEN); else memcpy(header->addr1, dest, ETH_ALEN); /* Fill in the Source Address */ memcpy(header->addr2, mac->ieee->dev->dev_addr, ETH_ALEN);}/* Add a 3 Address Header */static void ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac, struct ieee80211_hdr_3addr *header, u32 type, u8 *dest, u8 *bssid){ /* This is common with 2addr, so use that instead */ ieee80211softmac_hdr_2addr(mac, (struct ieee80211_hdr_2addr *)header, type, dest); /* Fill in the BSS ID */ if(bssid == NULL) memset(header->addr3, 0xFF, ETH_ALEN); else memcpy(header->addr3, bssid, ETH_ALEN); /* Fill in the sequence # */ /* FIXME: I need to add this to the softmac struct * shouldn't the sequence number be in ieee80211? */}/***************************************************************************** * Create Management packets *****************************************************************************/ /* Creates an association request packet */static u32ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt, struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net){ u8 *data; (*pkt) = (struct ieee80211_assoc_request *)ieee80211softmac_alloc_mgt( 2 + /* Capability Info */ 2 + /* Listen Interval */ /* SSID IE */ 1 + 1 + IW_ESSID_MAX_SIZE + /* Rates IE */ 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN + /* Extended Rates IE */ 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN + /* WPA IE if present */ mac->wpa.IElen /* Other IE's? Optional? * Yeah, probably need an extra IE parameter -- lots of vendors like to * fill in their own IEs */ ); if (unlikely((*pkt) == NULL)) return 0; ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); /* Fill in capability Info */ switch (mac->ieee->iw_mode) { case IW_MODE_INFRA: (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS); break; case IW_MODE_ADHOC: (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS); break; case IW_MODE_AUTO: (*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS); break; default: /* bleh. we don't ever go to these modes */ printk(KERN_ERR PFX "invalid iw_mode!\n"); break; } /* Need to add this (*pkt)->capability |= mac->ieee->short_slot ? cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0; */ (*pkt)->capability |= mac->ieee->sec.level ? cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0; /* Fill in Listen Interval (?) */ (*pkt)->listen_interval = cpu_to_le16(10); data = (u8 *)(*pkt)->info_element; /* Add SSID */ data = ieee80211softmac_add_essid(data, &net->essid); /* Add Rates */ data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo); /* Add WPA IE */ if (mac->wpa.IElen && mac->wpa.IE) { memcpy(data, mac->wpa.IE, mac->wpa.IElen); data += mac->wpa.IElen; } /* Return the number of used bytes */ return (data - (u8*)(*pkt));}/* Create a reassociation request packet */static u32ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt, struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net){ u8 *data; (*pkt) = (struct ieee80211_reassoc_request *)ieee80211softmac_alloc_mgt( 2 + /* Capability Info */ 2 + /* Listen Interval */ ETH_ALEN + /* AP MAC */ /* SSID IE */ 1 + 1 + IW_ESSID_MAX_SIZE + /* Rates IE */ 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN + /* Extended Rates IE */ 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN /* Other IE's? */ ); if (unlikely((*pkt) == NULL)) return 0; ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid); /* Fill in capability Info */ (*pkt)->capability = mac->ieee->iw_mode == IW_MODE_MASTER ? cpu_to_le16(WLAN_CAPABILITY_ESS) :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -