The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/rtwn/if_rtwn_cam.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
    5  * Copyright (c) 2014 Kevin Lo <kevlo@FreeBSD.org>
    6  * Copyright (c) 2015-2016 Andriy Voskoboinyk <avos@FreeBSD.org>
    7  *
    8  * Permission to use, copy, modify, and distribute this software for any
    9  * purpose with or without fee is hereby granted, provided that the above
   10  * copyright notice and this permission notice appear in all copies.
   11  *
   12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   19  */
   20 
   21 #include <sys/cdefs.h>
   22 __FBSDID("$FreeBSD$");
   23 
   24 #include "opt_wlan.h"
   25 
   26 #include <sys/param.h>
   27 #include <sys/lock.h>
   28 #include <sys/mutex.h>
   29 #include <sys/mbuf.h>
   30 #include <sys/kernel.h>
   31 #include <sys/socket.h>
   32 #include <sys/systm.h>
   33 #include <sys/malloc.h>
   34 #include <sys/queue.h>
   35 #include <sys/taskqueue.h>
   36 #include <sys/bus.h>
   37 #include <sys/endian.h>
   38 
   39 #include <net/if.h>
   40 #include <net/ethernet.h>
   41 #include <net/if_media.h>
   42 
   43 #include <net80211/ieee80211_var.h>
   44 #include <net80211/ieee80211_radiotap.h>
   45 
   46 #include <dev/rtwn/if_rtwnreg.h>
   47 #include <dev/rtwn/if_rtwnvar.h>
   48 
   49 #include <dev/rtwn/if_rtwn_cam.h>
   50 #include <dev/rtwn/if_rtwn_debug.h>
   51 #include <dev/rtwn/if_rtwn_task.h>
   52 
   53 #include <dev/rtwn/rtl8192c/r92c_reg.h>
   54 
   55 void
   56 rtwn_init_cam(struct rtwn_softc *sc)
   57 {
   58         /* Invalidate all CAM entries. */
   59         rtwn_write_4(sc, R92C_CAMCMD,
   60             R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR);
   61 }
   62 
   63 static int
   64 rtwn_cam_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data)
   65 {
   66         int error;
   67 
   68         error = rtwn_write_4(sc, R92C_CAMWRITE, data);
   69         if (error != 0)
   70                 return (error);
   71         error = rtwn_write_4(sc, R92C_CAMCMD,
   72             R92C_CAMCMD_POLLING | R92C_CAMCMD_WRITE |
   73             SM(R92C_CAMCMD_ADDR, addr));
   74 
   75         return (error);
   76 }
   77 
   78 void
   79 rtwn_init_seccfg(struct rtwn_softc *sc)
   80 {
   81         uint16_t seccfg;
   82 
   83         /* Select decryption / encryption flags. */
   84         seccfg = 0;
   85         switch (sc->sc_hwcrypto) {
   86         case RTWN_CRYPTO_SW:
   87                 break;  /* nothing to do */
   88         case RTWN_CRYPTO_PAIR:
   89                 /* NB: TXUCKEY_DEF / RXUCKEY_DEF are required for RTL8192C */
   90                 seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF |
   91                     R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA |
   92                     R92C_SECCFG_MC_SRCH_DIS;
   93                 break;
   94         case RTWN_CRYPTO_FULL:
   95                 seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF |
   96                     R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA |
   97                     R92C_SECCFG_TXBCKEY_DEF | R92C_SECCFG_RXBCKEY_DEF;
   98                 break;
   99         default:
  100                 KASSERT(0, ("%s: case %d was not handled\n", __func__,
  101                     sc->sc_hwcrypto));
  102                 break;
  103         }
  104 
  105         RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, "%s: seccfg %04X, hwcrypto %d\n",
  106             __func__, seccfg, sc->sc_hwcrypto);
  107 
  108         rtwn_write_2(sc, R92C_SECCFG, seccfg);
  109 }
  110 
  111 int
  112 rtwn_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
  113     ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
  114 {
  115         struct rtwn_softc *sc = vap->iv_ic->ic_softc;
  116         int i, start;
  117 
  118         if (&vap->iv_nw_keys[0] <= k &&
  119             k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
  120 #if __FreeBSD_version > 1200018
  121                 *keyix = ieee80211_crypto_get_key_wepidx(vap, k);
  122 #else
  123                 *keyix = k - vap->iv_nw_keys;
  124 #endif
  125                 if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL)
  126                         k->wk_flags |= IEEE80211_KEY_SWCRYPT;
  127                 else {
  128                         RTWN_LOCK(sc);
  129                         if (isset(sc->keys_bmap, *keyix)) {
  130                                 device_printf(sc->sc_dev,
  131                                     "%s: group key slot %d is already used!\n",
  132                                     __func__, *keyix);
  133                                 /* XXX recover? */
  134                                 RTWN_UNLOCK(sc);
  135                                 return (0);
  136                         }
  137 
  138                         setbit(sc->keys_bmap, *keyix);
  139                         RTWN_UNLOCK(sc);
  140                 }
  141 
  142                 goto end;
  143         }
  144 
  145         start = sc->cam_entry_limit;
  146         switch (sc->sc_hwcrypto) {
  147         case RTWN_CRYPTO_SW:
  148                 k->wk_flags |= IEEE80211_KEY_SWCRYPT;
  149                 *keyix = 0;
  150                 goto end;
  151         case RTWN_CRYPTO_PAIR:
  152                 /* all slots for pairwise keys. */
  153                 start = 0;
  154                 RTWN_LOCK(sc);
  155                 if (sc->sc_flags & RTWN_FLAG_CAM_FIXED)
  156                         start = 4;
  157                 RTWN_UNLOCK(sc);
  158                 break;
  159         case RTWN_CRYPTO_FULL:
  160                 /* first 4 - for group keys, others for pairwise. */
  161                 start = 4;
  162                 break;
  163         default:
  164                 KASSERT(0, ("%s: case %d was not handled!\n",
  165                     __func__, sc->sc_hwcrypto));
  166                 break;
  167         }
  168 
  169         RTWN_LOCK(sc);
  170         for (i = start; i < sc->cam_entry_limit; i++) {
  171                 if (isclr(sc->keys_bmap, i)) {
  172                         setbit(sc->keys_bmap, i);
  173                         *keyix = i;
  174                         break;
  175                 }
  176         }
  177         RTWN_UNLOCK(sc);
  178         if (i == sc->cam_entry_limit) {
  179 #if __FreeBSD_version > 1200008
  180                 /* XXX check and remove keys with the same MAC address */
  181                 k->wk_flags |= IEEE80211_KEY_SWCRYPT;
  182                 *keyix = 0;
  183 #else
  184                 device_printf(sc->sc_dev,
  185                     "%s: no free space in the key table\n", __func__);
  186                 return (0);
  187 #endif
  188         }
  189 
  190 end:
  191         *rxkeyix = *keyix;
  192         return (1);
  193 }
  194 
  195 static int
  196 rtwn_key_set_cb0(struct rtwn_softc *sc, const struct ieee80211_key *k)
  197 {
  198         uint8_t algo, keyid;
  199         int i, error;
  200 
  201         if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL &&
  202             k->wk_keyix < IEEE80211_WEP_NKID)
  203                 keyid = k->wk_keyix;
  204         else
  205                 keyid = 0;
  206 
  207         /* Map net80211 cipher to HW crypto algorithm. */
  208         switch (k->wk_cipher->ic_cipher) {
  209         case IEEE80211_CIPHER_WEP:
  210                 if (k->wk_keylen < 8)
  211                         algo = R92C_CAM_ALGO_WEP40;
  212                 else
  213                         algo = R92C_CAM_ALGO_WEP104;
  214                 break;
  215         case IEEE80211_CIPHER_TKIP:
  216                 algo = R92C_CAM_ALGO_TKIP;
  217                 break;
  218         case IEEE80211_CIPHER_AES_CCM:
  219                 algo = R92C_CAM_ALGO_AES;
  220                 break;
  221         default:
  222                 device_printf(sc->sc_dev, "%s: unknown cipher %u\n",
  223                     __func__, k->wk_cipher->ic_cipher);
  224                 return (EINVAL);
  225         }
  226 
  227         RTWN_DPRINTF(sc, RTWN_DEBUG_KEY,
  228             "%s: keyix %u, keyid %u, algo %u/%u, flags %04X, len %u, "
  229             "macaddr %s\n", __func__, k->wk_keyix, keyid,
  230             k->wk_cipher->ic_cipher, algo, k->wk_flags, k->wk_keylen,
  231             ether_sprintf(k->wk_macaddr));
  232 
  233         /* Clear high bits. */
  234         rtwn_cam_write(sc, R92C_CAM_CTL6(k->wk_keyix), 0);
  235         rtwn_cam_write(sc, R92C_CAM_CTL7(k->wk_keyix), 0);
  236 
  237         /* Write key. */
  238         for (i = 0; i < 4; i++) {
  239                 error = rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i),
  240                     le32dec(&k->wk_key[i * 4]));
  241                 if (error != 0)
  242                         goto fail;
  243         }
  244 
  245         /* Write CTL0 last since that will validate the CAM entry. */
  246         error = rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix),
  247             le32dec(&k->wk_macaddr[2]));
  248         if (error != 0)
  249                 goto fail;
  250         error = rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix),
  251             SM(R92C_CAM_ALGO, algo) |
  252             SM(R92C_CAM_KEYID, keyid) |
  253             SM(R92C_CAM_MACLO, le16dec(&k->wk_macaddr[0])) |
  254             R92C_CAM_VALID);
  255         if (error != 0)
  256                 goto fail;
  257 
  258         return (0);
  259 
  260 fail:
  261         device_printf(sc->sc_dev, "%s fails, error %d\n", __func__, error);
  262         return (error);
  263 }
  264 
  265 static void
  266 rtwn_key_set_cb(struct rtwn_softc *sc, union sec_param *data)
  267 {
  268         const struct ieee80211_key *k = &data->key;
  269 
  270         (void) rtwn_key_set_cb0(sc, k);
  271 }
  272 
  273 int
  274 rtwn_init_static_keys(struct rtwn_softc *sc, struct rtwn_vap *rvp)
  275 {
  276         int i, error;
  277 
  278         if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL)
  279                 return (0);             /* nothing to do */
  280 
  281         for (i = 0; i < IEEE80211_WEP_NKID; i++) {
  282                 const struct ieee80211_key *k = rvp->keys[i];
  283                 if (k != NULL) {
  284                         error = rtwn_key_set_cb0(sc, k);
  285                         if (error != 0)
  286                                 return (error);
  287                 }
  288         }
  289 
  290         return (0);
  291 }
  292 
  293 static void
  294 rtwn_key_del_cb(struct rtwn_softc *sc, union sec_param *data)
  295 {
  296         struct ieee80211_key *k = &data->key;
  297         int i;
  298 
  299         RTWN_DPRINTF(sc, RTWN_DEBUG_KEY,
  300             "%s: keyix %u, flags %04X, macaddr %s\n", __func__,
  301             k->wk_keyix, k->wk_flags, ether_sprintf(k->wk_macaddr));
  302 
  303         rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), 0);
  304         rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), 0);
  305 
  306         /* Clear key. */
  307         for (i = 0; i < 4; i++)
  308                 rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), 0);
  309         clrbit(sc->keys_bmap, k->wk_keyix);
  310 }
  311 
  312 static int
  313 rtwn_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k,
  314     int set)
  315 {
  316         struct rtwn_softc *sc = vap->iv_ic->ic_softc;
  317 
  318         if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
  319                 /* Not for us. */
  320                 return (1);
  321         }
  322 
  323         if (&vap->iv_nw_keys[0] <= k &&
  324             k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
  325 #if __FreeBSD_version <= 1200008
  326                 struct ieee80211_key *k1 = &vap->iv_nw_keys[k->wk_keyix];
  327 
  328                 if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) {
  329                         k1->wk_flags |= IEEE80211_KEY_SWCRYPT;
  330                         return (k->wk_cipher->ic_setkey(k1));
  331                 } else {
  332 #else
  333                 if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL) {
  334 #endif
  335                         struct rtwn_vap *rvp = RTWN_VAP(vap);
  336 
  337                         RTWN_LOCK(sc);
  338                         rvp->keys[k->wk_keyix] = (set ? k : NULL);
  339                         if ((sc->sc_flags & RTWN_RUNNING) == 0) {
  340                                 if (!set)
  341                                         clrbit(sc->keys_bmap, k->wk_keyix);
  342                                 RTWN_UNLOCK(sc);
  343                                 return (1);
  344                         }
  345                         RTWN_UNLOCK(sc);
  346                 }
  347         }
  348 
  349         return (!rtwn_cmd_sleepable(sc, k, sizeof(*k),
  350             set ? rtwn_key_set_cb : rtwn_key_del_cb));
  351 }
  352 
  353 int
  354 rtwn_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
  355 {
  356         return (rtwn_process_key(vap, k, 1));
  357 }
  358 
  359 int
  360 rtwn_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
  361 {
  362         return (rtwn_process_key(vap, k, 0));
  363 }

Cache object: e387ce2facf0ccac6ac5401c6f79f170


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.