aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@gmail.com>2008-08-21 18:28:05 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-22 19:28:07 -0400
commit23edcc4147ad36f8d55f0eb79c21e245ffb9f211 (patch)
tree20aaa2208d7ba51769639bcedd6be3bc3cd8673c /drivers/net
parent31afcef385bb8bf528c6fbe05b359af9f456f02a (diff)
orinoco: Add MIC on TX and check on RX
Use the MIC algorithm from the crypto subsystem. Signed-off-by: David Kilroy <kilroyd@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/Kconfig2
-rw-r--r--drivers/net/wireless/hermes.h7
-rw-r--r--drivers/net/wireless/orinoco.c234
-rw-r--r--drivers/net/wireless/orinoco.h2
4 files changed, 229 insertions, 16 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index ea7da7117f4d..45bdf0b339bb 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -336,6 +336,8 @@ config HERMES
336 depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211 336 depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211
337 select WIRELESS_EXT 337 select WIRELESS_EXT
338 select FW_LOADER 338 select FW_LOADER
339 select CRYPTO
340 select CRYPTO_MICHAEL_MIC
339 ---help--- 341 ---help---
340 A driver for 802.11b wireless cards based on the "Hermes" or 342 A driver for 802.11b wireless cards based on the "Hermes" or
341 Intersil HFA384x (Prism 2) MAC controller. This includes the vast 343 Intersil HFA384x (Prism 2) MAC controller. This includes the vast
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
index 113f3f6cb2d1..8b13c8fef3dc 100644
--- a/drivers/net/wireless/hermes.h
+++ b/drivers/net/wireless/hermes.h
@@ -184,13 +184,18 @@
184#define HERMES_RXSTAT_ERR (0x0003) 184#define HERMES_RXSTAT_ERR (0x0003)
185#define HERMES_RXSTAT_BADCRC (0x0001) 185#define HERMES_RXSTAT_BADCRC (0x0001)
186#define HERMES_RXSTAT_UNDECRYPTABLE (0x0002) 186#define HERMES_RXSTAT_UNDECRYPTABLE (0x0002)
187#define HERMES_RXSTAT_MIC (0x0010) /* Frame contains MIC */
187#define HERMES_RXSTAT_MACPORT (0x0700) 188#define HERMES_RXSTAT_MACPORT (0x0700)
188#define HERMES_RXSTAT_PCF (0x1000) /* Frame was received in CF period */ 189#define HERMES_RXSTAT_PCF (0x1000) /* Frame was received in CF period */
190#define HERMES_RXSTAT_MIC_KEY_ID (0x1800) /* MIC key used */
189#define HERMES_RXSTAT_MSGTYPE (0xE000) 191#define HERMES_RXSTAT_MSGTYPE (0xE000)
190#define HERMES_RXSTAT_1042 (0x2000) /* RFC-1042 frame */ 192#define HERMES_RXSTAT_1042 (0x2000) /* RFC-1042 frame */
191#define HERMES_RXSTAT_TUNNEL (0x4000) /* bridge-tunnel encoded frame */ 193#define HERMES_RXSTAT_TUNNEL (0x4000) /* bridge-tunnel encoded frame */
192#define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */ 194#define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */
193 195
196/* Shift amount for key ID in RXSTAT and TXCTRL */
197#define HERMES_MIC_KEY_ID_SHIFT 11
198
194struct hermes_tx_descriptor { 199struct hermes_tx_descriptor {
195 __le16 status; 200 __le16 status;
196 __le16 reserved1; 201 __le16 reserved1;
@@ -209,6 +214,8 @@ struct hermes_tx_descriptor {
209#define HERMES_TXCTRL_TX_OK (0x0002) /* ?? interrupt on Tx complete */ 214#define HERMES_TXCTRL_TX_OK (0x0002) /* ?? interrupt on Tx complete */
210#define HERMES_TXCTRL_TX_EX (0x0004) /* ?? interrupt on Tx exception */ 215#define HERMES_TXCTRL_TX_EX (0x0004) /* ?? interrupt on Tx exception */
211#define HERMES_TXCTRL_802_11 (0x0008) /* We supply 802.11 header */ 216#define HERMES_TXCTRL_802_11 (0x0008) /* We supply 802.11 header */
217#define HERMES_TXCTRL_MIC (0x0010) /* 802.3 + TKIP */
218#define HERMES_TXCTRL_MIC_KEY_ID (0x1800) /* MIC Key ID mask */
212#define HERMES_TXCTRL_ALT_RTRY (0x0020) 219#define HERMES_TXCTRL_ALT_RTRY (0x0020)
213 220
214/* Inquiry constants and data types */ 221/* Inquiry constants and data types */
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 768b39452674..6a196c31de43 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -89,6 +89,9 @@
89#include <net/iw_handler.h> 89#include <net/iw_handler.h>
90#include <net/ieee80211.h> 90#include <net/ieee80211.h>
91 91
92#include <linux/scatterlist.h>
93#include <linux/crypto.h>
94
92#include "hermes_rid.h" 95#include "hermes_rid.h"
93#include "hermes_dld.h" 96#include "hermes_dld.h"
94#include "orinoco.h" 97#include "orinoco.h"
@@ -244,6 +247,74 @@ static int __orinoco_program_rids(struct net_device *dev);
244static void __orinoco_set_multicast_list(struct net_device *dev); 247static void __orinoco_set_multicast_list(struct net_device *dev);
245 248
246/********************************************************************/ 249/********************************************************************/
250/* Michael MIC crypto setup */
251/********************************************************************/
252#define MICHAEL_MIC_LEN 8
253static int orinoco_mic_init(struct orinoco_private *priv)
254{
255 priv->tx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0);
256 if (IS_ERR(priv->tx_tfm_mic)) {
257 printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
258 "crypto API michael_mic\n");
259 priv->tx_tfm_mic = NULL;
260 return -ENOMEM;
261 }
262
263 priv->rx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0);
264 if (IS_ERR(priv->rx_tfm_mic)) {
265 printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
266 "crypto API michael_mic\n");
267 priv->rx_tfm_mic = NULL;
268 return -ENOMEM;
269 }
270
271 return 0;
272}
273
274static void orinoco_mic_free(struct orinoco_private *priv)
275{
276 if (priv->tx_tfm_mic)
277 crypto_free_hash(priv->tx_tfm_mic);
278 if (priv->rx_tfm_mic)
279 crypto_free_hash(priv->rx_tfm_mic);
280}
281
282static int michael_mic(struct crypto_hash *tfm_michael, u8 *key,
283 u8 *da, u8 *sa, u8 priority,
284 u8 *data, size_t data_len, u8 *mic)
285{
286 struct hash_desc desc;
287 struct scatterlist sg[2];
288 u8 hdr[ETH_HLEN + 2]; /* size of header + padding */
289
290 if (tfm_michael == NULL) {
291 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
292 return -1;
293 }
294
295 /* Copy header into buffer. We need the padding on the end zeroed */
296 memcpy(&hdr[0], da, ETH_ALEN);
297 memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN);
298 hdr[ETH_ALEN*2] = priority;
299 hdr[ETH_ALEN*2+1] = 0;
300 hdr[ETH_ALEN*2+2] = 0;
301 hdr[ETH_ALEN*2+3] = 0;
302
303 /* Use scatter gather to MIC header and data in one go */
304 sg_init_table(sg, 2);
305 sg_set_buf(&sg[0], hdr, sizeof(hdr));
306 sg_set_buf(&sg[1], data, data_len);
307
308 if (crypto_hash_setkey(tfm_michael, key, MIC_KEYLEN))
309 return -1;
310
311 desc.tfm = tfm_michael;
312 desc.flags = 0;
313 return crypto_hash_digest(&desc, sg, data_len + sizeof(hdr),
314 mic);
315}
316
317/********************************************************************/
247/* Internal helper functions */ 318/* Internal helper functions */
248/********************************************************************/ 319/********************************************************************/
249 320
@@ -764,7 +835,6 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
764 int err = 0; 835 int err = 0;
765 u16 txfid = priv->txfid; 836 u16 txfid = priv->txfid;
766 struct ethhdr *eh; 837 struct ethhdr *eh;
767 int data_off;
768 int tx_control; 838 int tx_control;
769 unsigned long flags; 839 unsigned long flags;
770 840
@@ -797,10 +867,12 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
797 if (skb->len < ETH_HLEN) 867 if (skb->len < ETH_HLEN)
798 goto drop; 868 goto drop;
799 869
800 eh = (struct ethhdr *)skb->data;
801
802 tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX; 870 tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
803 871
872 if (priv->encode_alg == IW_ENCODE_ALG_TKIP)
873 tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
874 HERMES_TXCTRL_MIC;
875
804 if (priv->has_alt_txcntl) { 876 if (priv->has_alt_txcntl) {
805 /* WPA enabled firmwares have tx_cntl at the end of 877 /* WPA enabled firmwares have tx_cntl at the end of
806 * the 802.11 header. So write zeroed descriptor and 878 * the 802.11 header. So write zeroed descriptor and
@@ -842,6 +914,8 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
842 HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); 914 HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
843 } 915 }
844 916
917 eh = (struct ethhdr *)skb->data;
918
845 /* Encapsulate Ethernet-II frames */ 919 /* Encapsulate Ethernet-II frames */
846 if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ 920 if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
847 struct header_struct { 921 struct header_struct {
@@ -851,33 +925,65 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
851 925
852 /* Strip destination and source from the data */ 926 /* Strip destination and source from the data */
853 skb_pull(skb, 2 * ETH_ALEN); 927 skb_pull(skb, 2 * ETH_ALEN);
854 data_off = HERMES_802_2_OFFSET + sizeof(encaps_hdr);
855 928
856 /* And move them to a separate header */ 929 /* And move them to a separate header */
857 memcpy(&hdr.eth, eh, 2 * ETH_ALEN); 930 memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
858 hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len); 931 hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len);
859 memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr)); 932 memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
860 933
861 err = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr), 934 /* Insert the SNAP header */
862 txfid, HERMES_802_3_OFFSET); 935 if (skb_headroom(skb) < sizeof(hdr)) {
863 if (err) { 936 printk(KERN_ERR
864 if (net_ratelimit()) 937 "%s: Not enough headroom for 802.2 headers %d\n",
865 printk(KERN_ERR "%s: Error %d writing packet " 938 dev->name, skb_headroom(skb));
866 "header to BAP\n", dev->name, err); 939 goto drop;
867 goto busy;
868 } 940 }
869 } else { /* IEEE 802.3 frame */ 941 eh = (struct ethhdr *) skb_push(skb, sizeof(hdr));
870 data_off = HERMES_802_3_OFFSET; 942 memcpy(eh, &hdr, sizeof(hdr));
871 } 943 }
872 944
873 err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len, 945 err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,
874 txfid, data_off); 946 txfid, HERMES_802_3_OFFSET);
875 if (err) { 947 if (err) {
876 printk(KERN_ERR "%s: Error %d writing packet to BAP\n", 948 printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
877 dev->name, err); 949 dev->name, err);
878 goto busy; 950 goto busy;
879 } 951 }
880 952
953 /* Calculate Michael MIC */
954 if (priv->encode_alg == IW_ENCODE_ALG_TKIP) {
955 u8 mic_buf[MICHAEL_MIC_LEN + 1];
956 u8 *mic;
957 size_t offset;
958 size_t len;
959
960 if (skb->len % 2) {
961 /* MIC start is on an odd boundary */
962 mic_buf[0] = skb->data[skb->len - 1];
963 mic = &mic_buf[1];
964 offset = skb->len - 1;
965 len = MICHAEL_MIC_LEN + 1;
966 } else {
967 mic = &mic_buf[0];
968 offset = skb->len;
969 len = MICHAEL_MIC_LEN;
970 }
971
972 michael_mic(priv->tx_tfm_mic,
973 priv->tkip_key[priv->tx_key].tx_mic,
974 eh->h_dest, eh->h_source, 0 /* priority */,
975 skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);
976
977 /* Write the MIC */
978 err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
979 txfid, HERMES_802_3_OFFSET + offset);
980 if (err) {
981 printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",
982 dev->name, err);
983 goto busy;
984 }
985 }
986
881 /* Finally, we actually initiate the send */ 987 /* Finally, we actually initiate the send */
882 netif_stop_queue(dev); 988 netif_stop_queue(dev);
883 989
@@ -892,7 +998,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
892 } 998 }
893 999
894 dev->trans_start = jiffies; 1000 dev->trans_start = jiffies;
895 stats->tx_bytes += data_off + skb->len; 1001 stats->tx_bytes += HERMES_802_3_OFFSET + skb->len;
896 goto ok; 1002 goto ok;
897 1003
898 drop: 1004 drop:
@@ -1172,6 +1278,25 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
1172 stats->rx_dropped++; 1278 stats->rx_dropped++;
1173} 1279}
1174 1280
1281/* Get tsc from the firmware */
1282static int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key,
1283 u8 *tsc)
1284{
1285 hermes_t *hw = &priv->hw;
1286 int err = 0;
1287 u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];
1288
1289 if ((key < 0) || (key > 4))
1290 return -EINVAL;
1291
1292 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
1293 sizeof(tsc_arr), NULL, &tsc_arr);
1294 if (!err)
1295 memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
1296
1297 return err;
1298}
1299
1175static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) 1300static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1176{ 1301{
1177 struct orinoco_private *priv = netdev_priv(dev); 1302 struct orinoco_private *priv = netdev_priv(dev);
@@ -1240,6 +1365,11 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1240 goto update_stats; 1365 goto update_stats;
1241 } 1366 }
1242 1367
1368 /* Payload size does not include Michael MIC. Increase payload
1369 * size to read it together with the data. */
1370 if (status & HERMES_RXSTAT_MIC)
1371 length += MICHAEL_MIC_LEN;
1372
1243 /* We need space for the packet data itself, plus an ethernet 1373 /* We need space for the packet data itself, plus an ethernet
1244 header, plus 2 bytes so we can align the IP header on a 1374 header, plus 2 bytes so we can align the IP header on a
1245 32bit boundary, plus 1 byte so we can read in odd length 1375 32bit boundary, plus 1 byte so we can read in odd length
@@ -1303,6 +1433,63 @@ static void orinoco_rx(struct net_device *dev,
1303 length = le16_to_cpu(desc->data_len); 1433 length = le16_to_cpu(desc->data_len);
1304 fc = le16_to_cpu(desc->frame_ctl); 1434 fc = le16_to_cpu(desc->frame_ctl);
1305 1435
1436 /* Calculate and check MIC */
1437 if (status & HERMES_RXSTAT_MIC) {
1438 int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >>
1439 HERMES_MIC_KEY_ID_SHIFT);
1440 u8 mic[MICHAEL_MIC_LEN];
1441 u8 *rxmic;
1442 u8 *src = (fc & IEEE80211_FCTL_FROMDS) ?
1443 desc->addr3 : desc->addr2;
1444
1445 /* Extract Michael MIC from payload */
1446 rxmic = skb->data + skb->len - MICHAEL_MIC_LEN;
1447
1448 skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
1449 length -= MICHAEL_MIC_LEN;
1450
1451 michael_mic(priv->rx_tfm_mic,
1452 priv->tkip_key[key_id].rx_mic,
1453 desc->addr1,
1454 src,
1455 0, /* priority or QoS? */
1456 skb->data,
1457 skb->len,
1458 &mic[0]);
1459
1460 if (memcmp(mic, rxmic,
1461 MICHAEL_MIC_LEN)) {
1462 union iwreq_data wrqu;
1463 struct iw_michaelmicfailure wxmic;
1464 DECLARE_MAC_BUF(mac);
1465
1466 printk(KERN_WARNING "%s: "
1467 "Invalid Michael MIC in data frame from %s, "
1468 "using key %i\n",
1469 dev->name, print_mac(mac, src), key_id);
1470
1471 /* TODO: update stats */
1472
1473 /* Notify userspace */
1474 memset(&wxmic, 0, sizeof(wxmic));
1475 wxmic.flags = key_id & IW_MICFAILURE_KEY_ID;
1476 wxmic.flags |= (desc->addr1[0] & 1) ?
1477 IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
1478 wxmic.src_addr.sa_family = ARPHRD_ETHER;
1479 memcpy(wxmic.src_addr.sa_data, src, ETH_ALEN);
1480
1481 (void) orinoco_hw_get_tkip_iv(priv, key_id,
1482 &wxmic.tsc[0]);
1483
1484 memset(&wrqu, 0, sizeof(wrqu));
1485 wrqu.data.length = sizeof(wxmic);
1486 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu,
1487 (char *) &wxmic);
1488
1489 goto drop;
1490 }
1491 }
1492
1306 /* Handle decapsulation 1493 /* Handle decapsulation
1307 * In most cases, the firmware tell us about SNAP frames. 1494 * In most cases, the firmware tell us about SNAP frames.
1308 * For some reason, the SNAP frames sent by LinkSys APs 1495 * For some reason, the SNAP frames sent by LinkSys APs
@@ -1342,6 +1529,11 @@ static void orinoco_rx(struct net_device *dev,
1342 stats->rx_bytes += length; 1529 stats->rx_bytes += length;
1343 1530
1344 return; 1531 return;
1532
1533 drop:
1534 dev_kfree_skb(skb);
1535 stats->rx_errors++;
1536 stats->rx_dropped++;
1345} 1537}
1346 1538
1347static void orinoco_rx_isr_tasklet(unsigned long data) 1539static void orinoco_rx_isr_tasklet(unsigned long data)
@@ -3112,8 +3304,14 @@ static int orinoco_init(struct net_device *dev)
3112 else 3304 else
3113 printk("40-bit key\n"); 3305 printk("40-bit key\n");
3114 } 3306 }
3115 if (priv->has_wpa) 3307 if (priv->has_wpa) {
3116 printk(KERN_DEBUG "%s: WPA-PSK supported\n", dev->name); 3308 printk(KERN_DEBUG "%s: WPA-PSK supported\n", dev->name);
3309 if (orinoco_mic_init(priv)) {
3310 printk(KERN_ERR "%s: Failed to setup MIC crypto "
3311 "algorithm. Disabling WPA support\n", dev->name);
3312 priv->has_wpa = 0;
3313 }
3314 }
3117 3315
3118 /* Now we have the firmware capabilities, allocate appropiate 3316 /* Now we have the firmware capabilities, allocate appropiate
3119 * sized scan buffers */ 3317 * sized scan buffers */
@@ -3292,6 +3490,9 @@ struct net_device
3292 dev->set_multicast_list = orinoco_set_multicast_list; 3490 dev->set_multicast_list = orinoco_set_multicast_list;
3293 /* we use the default eth_mac_addr for setting the MAC addr */ 3491 /* we use the default eth_mac_addr for setting the MAC addr */
3294 3492
3493 /* Reserve space in skb for the SNAP header */
3494 dev->hard_header_len += ENCAPS_OVERHEAD;
3495
3295 /* Set up default callbacks */ 3496 /* Set up default callbacks */
3296 dev->open = orinoco_open; 3497 dev->open = orinoco_open;
3297 dev->stop = orinoco_stop; 3498 dev->stop = orinoco_stop;
@@ -3327,6 +3528,7 @@ void free_orinocodev(struct net_device *dev)
3327 tasklet_kill(&priv->rx_tasklet); 3528 tasklet_kill(&priv->rx_tasklet);
3328 priv->wpa_ie_len = 0; 3529 priv->wpa_ie_len = 0;
3329 kfree(priv->wpa_ie); 3530 kfree(priv->wpa_ie);
3531 orinoco_mic_free(priv);
3330 orinoco_bss_data_free(priv); 3532 orinoco_bss_data_free(priv);
3331 free_netdev(dev); 3533 free_netdev(dev);
3332} 3534}
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index e0c9be3daa30..981570bd3b9d 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -158,6 +158,8 @@ struct orinoco_private {
158 int wpa_ie_len; 158 int wpa_ie_len;
159 159
160 struct orinoco_tkip_key tkip_key[ORINOCO_MAX_KEYS]; 160 struct orinoco_tkip_key tkip_key[ORINOCO_MAX_KEYS];
161 struct crypto_hash *rx_tfm_mic;
162 struct crypto_hash *tx_tfm_mic;
161 163
162 unsigned int wpa_enabled:1; 164 unsigned int wpa_enabled:1;
163 unsigned int tkip_cm_active:1; 165 unsigned int tkip_cm_active:1;