aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2005-06-18 19:28:02 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-06-27 00:23:55 -0400
commit8f2abf4430ef2a131926a537ee6325dc43b0ec28 (patch)
treec476955d07cc82b14c1a5b004b25a3961c05a028 /drivers/net/wireless/orinoco.c
parent95dd91fbd8d3c788ef93bc94b4b600889e04dba1 (diff)
[PATCH] orinoco: always use 802.11 header for rx processing
If the frame has ToDS flag set, mark it by setting skb->pkt_type to PACKET_OTHERHOST, so that applications unaware of promiscous mode won't get uplink (STA->AP) packets for STA->STA transmissions relayed by the AP. Thanks to John Denker and David Gibson for finding the problem and the solution. Patch from Pavel Roskin
Diffstat (limited to 'drivers/net/wireless/orinoco.c')
-rw-r--r--drivers/net/wireless/orinoco.c105
1 files changed, 52 insertions, 53 deletions
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 38fd8623a444..96df2885728f 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -619,7 +619,9 @@ struct hermes_tx_descriptor_802_11 {
619 u16 ethertype; 619 u16 ethertype;
620} __attribute__ ((packed)); 620} __attribute__ ((packed));
621 621
622/* Rx frame header except compatibility 802.3 header */
622struct hermes_rx_descriptor { 623struct hermes_rx_descriptor {
624 /* Control */
623 u16 status; 625 u16 status;
624 u32 time; 626 u32 time;
625 u8 silence; 627 u8 silence;
@@ -627,6 +629,18 @@ struct hermes_rx_descriptor {
627 u8 rate; 629 u8 rate;
628 u8 rxflow; 630 u8 rxflow;
629 u32 reserved; 631 u32 reserved;
632
633 /* 802.11 header */
634 u16 frame_ctl;
635 u16 duration_id;
636 u8 addr1[ETH_ALEN];
637 u8 addr2[ETH_ALEN];
638 u8 addr3[ETH_ALEN];
639 u16 seq_ctl;
640 u8 addr4[ETH_ALEN];
641
642 /* Data length */
643 u16 data_len;
630} __attribute__ ((packed)); 644} __attribute__ ((packed));
631 645
632/********************************************************************/ 646/********************************************************************/
@@ -1110,12 +1124,10 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1110 struct net_device_stats *stats = &priv->stats; 1124 struct net_device_stats *stats = &priv->stats;
1111 struct iw_statistics *wstats = &priv->wstats; 1125 struct iw_statistics *wstats = &priv->wstats;
1112 struct sk_buff *skb = NULL; 1126 struct sk_buff *skb = NULL;
1113 u16 rxfid, status; 1127 u16 rxfid, status, fc;
1114 int length, data_len, data_off; 1128 int length;
1115 char *p;
1116 struct hermes_rx_descriptor desc; 1129 struct hermes_rx_descriptor desc;
1117 struct header_struct hdr; 1130 struct ethhdr *hdr;
1118 struct ethhdr *eh;
1119 int err; 1131 int err;
1120 1132
1121 rxfid = hermes_read_regn(hw, RXFID); 1133 rxfid = hermes_read_regn(hw, RXFID);
@@ -1140,24 +1152,14 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1140 stats->rx_crc_errors++; 1152 stats->rx_crc_errors++;
1141 DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name); 1153 DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);
1142 } 1154 }
1143 stats->rx_errors++;
1144 goto drop;
1145 }
1146 1155
1147 /* For now we ignore the 802.11 header completely, assuming
1148 that the card's firmware has handled anything vital */
1149
1150 err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr),
1151 rxfid, HERMES_802_3_OFFSET);
1152 if (err) {
1153 printk(KERN_ERR "%s: error %d reading frame header. "
1154 "Frame dropped.\n", dev->name, err);
1155 stats->rx_errors++; 1156 stats->rx_errors++;
1156 goto drop; 1157 goto drop;
1157 } 1158 }
1158 1159
1159 length = ntohs(hdr.len); 1160 length = le16_to_cpu(desc.data_len);
1160 1161 fc = le16_to_cpu(desc.frame_ctl);
1162
1161 /* Sanity checks */ 1163 /* Sanity checks */
1162 if (length < 3) { /* No for even an 802.2 LLC header */ 1164 if (length < 3) { /* No for even an 802.2 LLC header */
1163 /* At least on Symbol firmware with PCF we get quite a 1165 /* At least on Symbol firmware with PCF we get quite a
@@ -1186,57 +1188,51 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1186 goto drop; 1188 goto drop;
1187 } 1189 }
1188 1190
1189 skb_reserve(skb, 2); /* This way the IP header is aligned */ 1191 /* We'll prepend the header, so reserve space for it. The worst
1192 case is no decapsulation, when 802.3 header is prepended and
1193 nothing is removed. 2 is for aligning the IP header. */
1194 skb_reserve(skb, ETH_HLEN + 2);
1195
1196 err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length),
1197 ALIGN(length, 2), rxfid,
1198 HERMES_802_2_OFFSET);
1199 if (err) {
1200 printk(KERN_ERR "%s: error %d reading frame. "
1201 "Frame dropped.\n", dev->name, err);
1202 stats->rx_errors++;
1203 goto drop;
1204 }
1190 1205
1191 /* Handle decapsulation 1206 /* Handle decapsulation
1192 * In most cases, the firmware tell us about SNAP frames. 1207 * In most cases, the firmware tell us about SNAP frames.
1193 * For some reason, the SNAP frames sent by LinkSys APs 1208 * For some reason, the SNAP frames sent by LinkSys APs
1194 * are not properly recognised by most firmwares. 1209 * are not properly recognised by most firmwares.
1195 * So, check ourselves */ 1210 * So, check ourselves */
1196 if (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || 1211 if (length >= ENCAPS_OVERHEAD &&
1197 ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || 1212 (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
1198 is_ethersnap(&hdr)) { 1213 ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
1214 is_ethersnap(skb->data))) {
1199 /* These indicate a SNAP within 802.2 LLC within 1215 /* These indicate a SNAP within 802.2 LLC within
1200 802.11 frame which we'll need to de-encapsulate to 1216 802.11 frame which we'll need to de-encapsulate to
1201 the original EthernetII frame. */ 1217 the original EthernetII frame. */
1202 1218 hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD);
1203 if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */
1204 stats->rx_length_errors++;
1205 goto drop;
1206 }
1207
1208 /* Remove SNAP header, reconstruct EthernetII frame */
1209 data_len = length - ENCAPS_OVERHEAD;
1210 data_off = HERMES_802_3_OFFSET + sizeof(hdr);
1211
1212 eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);
1213
1214 memcpy(eh, &hdr, 2 * ETH_ALEN);
1215 eh->h_proto = hdr.ethertype;
1216 } else { 1219 } else {
1217 /* All other cases indicate a genuine 802.3 frame. No 1220 /* 802.3 frame - prepend 802.3 header as is */
1218 decapsulation needed. We just throw the whole 1221 hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN);
1219 thing in, and hope the protocol layer can deal with 1222 hdr->h_proto = htons(length);
1220 it as 802.3 */
1221 data_len = length;
1222 data_off = HERMES_802_3_OFFSET;
1223 /* FIXME: we re-read from the card data we already read here */
1224 }
1225
1226 p = skb_put(skb, data_len);
1227 err = hermes_bap_pread(hw, IRQ_BAP, p, ALIGN(data_len, 2),
1228 rxfid, data_off);
1229 if (err) {
1230 printk(KERN_ERR "%s: error %d reading frame. "
1231 "Frame dropped.\n", dev->name, err);
1232 stats->rx_errors++;
1233 goto drop;
1234 } 1223 }
1224 memcpy(hdr->h_dest, desc.addr1, ETH_ALEN);
1225 if (fc & IEEE80211_FCTL_FROMDS)
1226 memcpy(hdr->h_source, desc.addr3, ETH_ALEN);
1227 else
1228 memcpy(hdr->h_source, desc.addr2, ETH_ALEN);
1235 1229
1236 dev->last_rx = jiffies; 1230 dev->last_rx = jiffies;
1237 skb->dev = dev; 1231 skb->dev = dev;
1238 skb->protocol = eth_type_trans(skb, dev); 1232 skb->protocol = eth_type_trans(skb, dev);
1239 skb->ip_summed = CHECKSUM_NONE; 1233 skb->ip_summed = CHECKSUM_NONE;
1234 if (fc & IEEE80211_FCTL_TODS)
1235 skb->pkt_type = PACKET_OTHERHOST;
1240 1236
1241 /* Process the wireless stats if needed */ 1237 /* Process the wireless stats if needed */
1242 orinoco_stat_gather(dev, skb, &desc); 1238 orinoco_stat_gather(dev, skb, &desc);
@@ -1457,6 +1453,9 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
1457 u16 newstatus; 1453 u16 newstatus;
1458 int connected; 1454 int connected;
1459 1455
1456 if (priv->iw_mode == IW_MODE_MONITOR)
1457 break;
1458
1460 if (len != sizeof(linkstatus)) { 1459 if (len != sizeof(linkstatus)) {
1461 printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n", 1460 printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
1462 dev->name, len); 1461 dev->name, len);