diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/ieee80211/ieee80211_rx.c | 58 | ||||
| -rw-r--r-- | net/ieee80211/ieee80211_tx.c | 64 |
2 files changed, 107 insertions, 15 deletions
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 71d14c7d915c..d1ae28280d7e 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c | |||
| @@ -1029,12 +1029,18 @@ static inline void update_network(struct ieee80211_network *dst, | |||
| 1029 | /* dst->last_associate is not overwritten */ | 1029 | /* dst->last_associate is not overwritten */ |
| 1030 | } | 1030 | } |
| 1031 | 1031 | ||
| 1032 | static inline int is_beacon(int fc) | ||
| 1033 | { | ||
| 1034 | return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON); | ||
| 1035 | } | ||
| 1036 | |||
| 1032 | static inline void ieee80211_process_probe_response(struct ieee80211_device | 1037 | static inline void ieee80211_process_probe_response(struct ieee80211_device |
| 1033 | *ieee, struct | 1038 | *ieee, struct |
| 1034 | ieee80211_probe_response | 1039 | ieee80211_probe_response |
| 1035 | *beacon, struct ieee80211_rx_stats | 1040 | *beacon, struct ieee80211_rx_stats |
| 1036 | *stats) | 1041 | *stats) |
| 1037 | { | 1042 | { |
| 1043 | struct net_device *dev = ieee->dev; | ||
| 1038 | struct ieee80211_network network; | 1044 | struct ieee80211_network network; |
| 1039 | struct ieee80211_network *target; | 1045 | struct ieee80211_network *target; |
| 1040 | struct ieee80211_network *oldest = NULL; | 1046 | struct ieee80211_network *oldest = NULL; |
| @@ -1070,11 +1076,10 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device | |||
| 1070 | escape_essid(info_element->data, | 1076 | escape_essid(info_element->data, |
| 1071 | info_element->len), | 1077 | info_element->len), |
| 1072 | MAC_ARG(beacon->header.addr3), | 1078 | MAC_ARG(beacon->header.addr3), |
| 1073 | WLAN_FC_GET_STYPE(le16_to_cpu | 1079 | is_beacon(le16_to_cpu |
| 1074 | (beacon->header. | 1080 | (beacon->header. |
| 1075 | frame_ctl)) == | 1081 | frame_ctl)) ? |
| 1076 | IEEE80211_STYPE_PROBE_RESP ? | 1082 | "BEACON" : "PROBE RESPONSE"); |
| 1077 | "PROBE RESPONSE" : "BEACON"); | ||
| 1078 | return; | 1083 | return; |
| 1079 | } | 1084 | } |
| 1080 | 1085 | ||
| @@ -1123,11 +1128,10 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device | |||
| 1123 | escape_essid(network.ssid, | 1128 | escape_essid(network.ssid, |
| 1124 | network.ssid_len), | 1129 | network.ssid_len), |
| 1125 | MAC_ARG(network.bssid), | 1130 | MAC_ARG(network.bssid), |
| 1126 | WLAN_FC_GET_STYPE(le16_to_cpu | 1131 | is_beacon(le16_to_cpu |
| 1127 | (beacon->header. | 1132 | (beacon->header. |
| 1128 | frame_ctl)) == | 1133 | frame_ctl)) ? |
| 1129 | IEEE80211_STYPE_PROBE_RESP ? | 1134 | "BEACON" : "PROBE RESPONSE"); |
| 1130 | "PROBE RESPONSE" : "BEACON"); | ||
| 1131 | #endif | 1135 | #endif |
| 1132 | memcpy(target, &network, sizeof(*target)); | 1136 | memcpy(target, &network, sizeof(*target)); |
| 1133 | list_add_tail(&target->list, &ieee->network_list); | 1137 | list_add_tail(&target->list, &ieee->network_list); |
| @@ -1136,15 +1140,22 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device | |||
| 1136 | escape_essid(target->ssid, | 1140 | escape_essid(target->ssid, |
| 1137 | target->ssid_len), | 1141 | target->ssid_len), |
| 1138 | MAC_ARG(target->bssid), | 1142 | MAC_ARG(target->bssid), |
| 1139 | WLAN_FC_GET_STYPE(le16_to_cpu | 1143 | is_beacon(le16_to_cpu |
| 1140 | (beacon->header. | 1144 | (beacon->header. |
| 1141 | frame_ctl)) == | 1145 | frame_ctl)) ? |
| 1142 | IEEE80211_STYPE_PROBE_RESP ? | 1146 | "BEACON" : "PROBE RESPONSE"); |
| 1143 | "PROBE RESPONSE" : "BEACON"); | ||
| 1144 | update_network(target, &network); | 1147 | update_network(target, &network); |
| 1145 | } | 1148 | } |
| 1146 | 1149 | ||
| 1147 | spin_unlock_irqrestore(&ieee->lock, flags); | 1150 | spin_unlock_irqrestore(&ieee->lock, flags); |
| 1151 | |||
| 1152 | if (is_beacon(le16_to_cpu(beacon->header.frame_ctl))) { | ||
| 1153 | if (ieee->handle_beacon != NULL) | ||
| 1154 | ieee->handle_beacon(dev, beacon, &network); | ||
| 1155 | } else { | ||
| 1156 | if (ieee->handle_probe_response != NULL) | ||
| 1157 | ieee->handle_probe_response(dev, beacon, &network); | ||
| 1158 | } | ||
| 1148 | } | 1159 | } |
| 1149 | 1160 | ||
| 1150 | void ieee80211_rx_mgt(struct ieee80211_device *ieee, | 1161 | void ieee80211_rx_mgt(struct ieee80211_device *ieee, |
| @@ -1185,6 +1196,23 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee, | |||
| 1185 | ieee80211_probe_response *) | 1196 | ieee80211_probe_response *) |
| 1186 | header, stats); | 1197 | header, stats); |
| 1187 | break; | 1198 | break; |
| 1199 | case IEEE80211_STYPE_AUTH: | ||
| 1200 | |||
| 1201 | IEEE80211_DEBUG_MGMT("recieved auth (%d)\n", | ||
| 1202 | WLAN_FC_GET_STYPE(le16_to_cpu | ||
| 1203 | (header->frame_ctl))); | ||
| 1204 | |||
| 1205 | if (ieee->handle_auth != NULL) | ||
| 1206 | ieee->handle_auth(ieee->dev, | ||
| 1207 | (struct ieee80211_auth *)header); | ||
| 1208 | break; | ||
| 1209 | |||
| 1210 | case IEEE80211_STYPE_DISASSOC: | ||
| 1211 | if (ieee->handle_disassoc != NULL) | ||
| 1212 | ieee->handle_disassoc(ieee->dev, | ||
| 1213 | (struct ieee80211_disassoc *) | ||
| 1214 | header); | ||
| 1215 | break; | ||
| 1188 | 1216 | ||
| 1189 | default: | 1217 | default: |
| 1190 | IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n", | 1218 | IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n", |
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index cdee41cefb26..f505aa127e21 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c | |||
| @@ -459,7 +459,71 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 459 | netif_stop_queue(dev); | 459 | netif_stop_queue(dev); |
| 460 | stats->tx_errors++; | 460 | stats->tx_errors++; |
| 461 | return 1; | 461 | return 1; |
| 462 | } | ||
| 463 | |||
| 464 | /* Incoming 802.11 strucure is converted to a TXB | ||
| 465 | * a block of 802.11 fragment packets (stored as skbs) */ | ||
| 466 | int ieee80211_tx_frame(struct ieee80211_device *ieee, | ||
| 467 | struct ieee80211_hdr *frame, int len) | ||
| 468 | { | ||
| 469 | struct ieee80211_txb *txb = NULL; | ||
| 470 | unsigned long flags; | ||
| 471 | struct net_device_stats *stats = &ieee->stats; | ||
| 472 | struct sk_buff *skb_frag; | ||
| 473 | |||
| 474 | spin_lock_irqsave(&ieee->lock, flags); | ||
| 475 | |||
| 476 | /* If there is no driver handler to take the TXB, dont' bother | ||
| 477 | * creating it... */ | ||
| 478 | if (!ieee->hard_start_xmit) { | ||
| 479 | printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); | ||
| 480 | goto success; | ||
| 481 | } | ||
| 462 | 482 | ||
| 483 | if (unlikely(len < 24)) { | ||
| 484 | printk(KERN_WARNING "%s: skb too small (%d).\n", | ||
| 485 | ieee->dev->name, len); | ||
| 486 | goto success; | ||
| 487 | } | ||
| 488 | |||
| 489 | /* When we allocate the TXB we allocate enough space for the reserve | ||
| 490 | * and full fragment bytes (bytes_per_frag doesn't include prefix, | ||
| 491 | * postfix, header, FCS, etc.) */ | ||
| 492 | txb = ieee80211_alloc_txb(1, len, GFP_ATOMIC); | ||
| 493 | if (unlikely(!txb)) { | ||
| 494 | printk(KERN_WARNING "%s: Could not allocate TXB\n", | ||
| 495 | ieee->dev->name); | ||
| 496 | goto failed; | ||
| 497 | } | ||
| 498 | txb->encrypted = 0; | ||
| 499 | txb->payload_size = len; | ||
| 500 | |||
| 501 | skb_frag = txb->fragments[0]; | ||
| 502 | |||
| 503 | memcpy(skb_put(skb_frag, len), frame, len); | ||
| 504 | |||
| 505 | if (ieee->config & | ||
| 506 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) | ||
| 507 | skb_put(skb_frag, 4); | ||
| 508 | |||
| 509 | success: | ||
| 510 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
| 511 | |||
| 512 | if (txb) { | ||
| 513 | if ((*ieee->hard_start_xmit) (txb, ieee->dev) == 0) { | ||
| 514 | stats->tx_packets++; | ||
| 515 | stats->tx_bytes += txb->payload_size; | ||
| 516 | return 0; | ||
| 517 | } | ||
| 518 | ieee80211_txb_free(txb); | ||
| 519 | } | ||
| 520 | return 0; | ||
| 521 | |||
| 522 | failed: | ||
| 523 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
| 524 | stats->tx_errors++; | ||
| 525 | return 1; | ||
| 463 | } | 526 | } |
| 464 | 527 | ||
| 528 | EXPORT_SYMBOL(ieee80211_tx_frame); | ||
| 465 | EXPORT_SYMBOL(ieee80211_txb_free); | 529 | EXPORT_SYMBOL(ieee80211_txb_free); |
