mac80211解析五

mac80211驱动会使用到cfg80211模块,分析cfg80211,初始化模块如下:

static int __init cfg80211_init(void)
{
    int err;

    err = register_pernet_device(&cfg80211_pernet_ops);
    if (err)
        goto out_fail_pernet;

    err = wiphy_sysfs_init();
    if (err)
        goto out_fail_sysfs;

    err = register_netdevice_notifier(&cfg80211_netdev_notifier);
    if (err)
        goto out_fail_notifier;

    err = nl80211_init();
    if (err)
        goto out_fail_nl80211;

    ieee80211_debugfs_dir = debugfs_create_dir("ieee80211", NULL);

    err = regulatory_init();
    if (err)
        goto out_fail_reg;

    cfg80211_wq = create_singlethread_workqueue("cfg80211");
    if (!cfg80211_wq) {
        err = -ENOMEM;
        goto out_fail_wq;
    }

    return 0;

out_fail_wq:
    regulatory_exit();
out_fail_reg:
    debugfs_remove(ieee80211_debugfs_dir);
out_fail_nl80211:
    unregister_netdevice_notifier(&cfg80211_netdev_notifier);
out_fail_notifier:
    wiphy_sysfs_exit();
out_fail_sysfs:
    unregister_pernet_device(&cfg80211_pernet_ops);
out_fail_pernet:
    return err;
}

cfg80211中提供了用户端接口nl80211,在模块初始化中也进行了初始化,即函数nl80211_init:


/* initialisation/exit functions */

int nl80211_init(void)
{
    int err;

    err = genl_register_family_with_ops_groups(&nl80211_fam, nl80211_ops,
                           nl80211_mcgrps);
    if (err)
        return err;

    err = netlink_register_notifier(&nl80211_netlink_notifier);
    if (err)
        goto err_out;

    return 0;
 err_out:
    genl_unregister_family(&nl80211_fam);
    return err;
}

其中重要的部分是调用了genl_register_family_with_ops_groups函数和关联的nl80211_ops结构体,前者是generic netlink操作注册函数,后者是操作结构体,nl80211_ops提供了连接和断开的上线连接操作,如下:

static __genl_const struct genl_ops nl80211_ops[] = {
{
    .cmd = NL80211_CMD_CONNECT,
    .doit = nl80211_connect,
    .policy = nl80211_policy,
    .flags = GENL_ADMIN_PERM,
    .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
              NL80211_FLAG_NEED_RTNL,
},
{
    .cmd = NL80211_CMD_DISCONNECT,
    .doit = nl80211_disconnect,
    .policy = nl80211_policy,
    .flags = GENL_ADMIN_PERM,
    .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
              NL80211_FLAG_NEED_RTNL,
}, 
} 

nl80211_connectnl80211_disconnect 函数。


static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
{
    struct cfg80211_registered_device *rdev = info->user_ptr[0];
    struct net_device *dev = info->user_ptr[1];
    struct cfg80211_connect_params connect;
    struct wiphy *wiphy;
    struct cfg80211_cached_keys *connkeys = NULL;
    int err;

    memset(&connect, 0, sizeof(connect));

    if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
        return -EINVAL;

    if (!info->attrs[NL80211_ATTR_SSID] ||
        !nla_len(info->attrs[NL80211_ATTR_SSID]))
        return -EINVAL;

    if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
        connect.auth_type =
            nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
        if (!nl80211_valid_auth_type(rdev, connect.auth_type,
                         NL80211_CMD_CONNECT))
            return -EINVAL;
    } else
        connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;

    connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];

    err = nl80211_crypto_settings(rdev, info, &connect.crypto,
                      NL80211_MAX_NR_CIPHER_SUITES);
    if (err)
        return err;

    if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION &&
        dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)
        return -EOPNOTSUPP;

    wiphy = &rdev->wiphy;

    connect.bg_scan_period = -1;
    if (info->attrs[NL80211_ATTR_BG_SCAN_PERIOD] &&
        (wiphy->flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)) {
        connect.bg_scan_period =
            nla_get_u16(info->attrs[NL80211_ATTR_BG_SCAN_PERIOD]);
    }

    if (info->attrs[NL80211_ATTR_MAC])
        connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
    else if (info->attrs[NL80211_ATTR_MAC_HINT])
        connect.bssid_hint =
            nla_data(info->attrs[NL80211_ATTR_MAC_HINT]);
    connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
    connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);

    if (info->attrs[NL80211_ATTR_IE]) {
        connect.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
        connect.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
    }

    if (info->attrs[NL80211_ATTR_USE_MFP]) {
        connect.mfp = nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
        if (connect.mfp != NL80211_MFP_REQUIRED &&
            connect.mfp != NL80211_MFP_NO)
            return -EINVAL;
    } else {
        connect.mfp = NL80211_MFP_NO;
    }

    if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
        connect.channel = nl80211_get_valid_chan(
            wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ]);
        if (!connect.channel)
            return -EINVAL;
    } else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) {
        connect.channel_hint = nl80211_get_valid_chan(
            wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]);
        if (!connect.channel_hint)
            return -EINVAL;
    }

    if (connect.privacy && info->attrs[NL80211_ATTR_KEYS]) {
        connkeys = nl80211_parse_connkeys(rdev,
                      info->attrs[NL80211_ATTR_KEYS], NULL);
        if (IS_ERR(connkeys))
            return PTR_ERR(connkeys);
    }

    if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
        connect.flags |= ASSOC_REQ_DISABLE_HT;

    if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
        memcpy(&connect.ht_capa_mask,
               nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
               sizeof(connect.ht_capa_mask));

    if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
        if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
            kfree(connkeys);
       
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值