From patchwork Thu Nov 9 09:40:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sergey Matyukevich X-Patchwork-Id: 10050653 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 56AB360381 for ; Thu, 9 Nov 2017 09:40:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 46C742AB2B for ; Thu, 9 Nov 2017 09:40:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3B8C92AB5C; Thu, 9 Nov 2017 09:40:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6D13B2AB2B for ; Thu, 9 Nov 2017 09:40:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753983AbdKIJks (ORCPT ); Thu, 9 Nov 2017 04:40:48 -0500 Received: from mail-bn3nam01on0041.outbound.protection.outlook.com ([104.47.33.41]:53568 "EHLO NAM01-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753292AbdKIJkl (ORCPT ); Thu, 9 Nov 2017 04:40:41 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quantenna.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=Q0V5FUjPPW2WPdyZ3C3jdAWTwSNxYKdT21UOu2s6SiQ=; b=TlM1v35mOx66W6Ht6zl7Tg7PHzvJI/D89Gwe/3cYj6OlRDlL2cUR0FXsZsIate5rRWPtBjuN2LZIAXpEn07m4CRAgowGbpQxw2745zwixO7VT5dPr6GBePcNQ2acz5K0Hm2Zi9ny25bAWK2R/kDKW8ioAyUyX8mWMYQ2ysj9ej4= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=sergey.matyukevich.os@quantenna.com; Received: from bars.quantenna.com (195.182.157.78) by BY2PR05MB1927.namprd05.prod.outlook.com (10.163.32.141) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.218.6; Thu, 9 Nov 2017 09:40:36 +0000 From: Sergey Matyukevich To: linux-wireless@vger.kernel.org, Johannes Berg Cc: Igor Mitsyanko , Avinash Patil , Vasily Ulyanov , Sergey Matyukevich Subject: [RFC PATCH 1/2] nl80211: implement NL80211_CMD_GET_BEACON command Date: Thu, 9 Nov 2017 12:40:23 +0300 Message-Id: <20171109094024.9085-1-sergey.matyukevich.os@quantenna.com> X-Mailer: git-send-email 2.11.0 MIME-Version: 1.0 X-Originating-IP: [195.182.157.78] X-ClientProxiedBy: DB6PR0301CA0065.eurprd03.prod.outlook.com (10.168.69.33) To BY2PR05MB1927.namprd05.prod.outlook.com (10.163.32.141) X-MS-Office365-Filtering-Correlation-Id: 8fcfacb6-17e8-465c-a2b0-08d52755ef9e X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(2017052603199); SRVR:BY2PR05MB1927; X-Microsoft-Exchange-Diagnostics: 1; BY2PR05MB1927; 3:TCknY1Og/uC/gwKki820rON6/vj2DY9PLH477v0Qm+TOGVTyRoNodX2olduvflRJfun0WU8shoeRGCMDsiJ+FlryIm0wK/KQDLRkGRQykV4mhkjxhoyECC3XZ3kb9sXBi7f2IDlt0JW/oKrTLvYphkAjBkkKJn3r7TifF0XLcKsa6FMfrmsAOFMqGuWyyUUeWd0diz3xU9pfjdwtVtsndqSO7ID9yAIXL+EhNStwaQt7aQx5hW+cieZUbGU1MU5b; 25:2oswKqPRoNgeh8tOSvgg3HMOeL1fiR4PPGvFu+lmf4zhuIebL2hAc61nKmPFa19N90DGm07cLy8vpUA3/AeZVMkhKM4UVI4nHgxK/DO77Jjo3JKrM4AV4v9RLsfEOuiQfp9hzTrX78hNCBKBkMIZYnjr2VNxI60uJFrXAIidvt2QsDjszmygArDpJ+MyYeSa2BMTC9+ciS8SsxADliGsTXWBrwQWXMBWZ5nMc58v4ChVkbybtmsb0wBnM7pNSYfMbjlwLnycEVYVjb8NPzTekwnRJn2v4bI8xJvI33l3dmQxPcrPRZYS/tESSCgNd+VCT8r3Ffmu7Q8cJYDgG0fcAw==; 31:MTzIiw8WkkLxJy8zvrJNpnf2feOYEzEMJPQe60Kz5IUDootXj+nzhK3C11MuwTZ5XsvXaYu6Ge/RoXFPaHRSS/QxUes0DHtPnkfLbUOMZj1xzfHuV9MWQRG7vdW8UTRIH5P5i/re0aM8j8Btg2RZleZVe4asMc2rGKE6KDi4LcL1j7GLmo5xHDI74bMHvw7W1K0eo+9LqqKDXkKBw+thpAFb2JepkAdVYZulGBHDD+o= X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BY2PR05MB1927: X-Microsoft-Exchange-Diagnostics: 1; BY2PR05MB1927; 20:kxUgi05oHbIGfJml91+Kgb8aPcnRxIISJ7/dY3uWDK0/tHjVv58nTxX2qg3Ishcfo3JyHcqxdl07Swb2l6bXTXh/yANZtCszyx649xX8Qp/eHUcPLy49dAry5uB7UducVfZvAmEO8PD2k26l3qfq87OcehKzSHYhSZqOEw8MT7ytcRUBes3XH/RB0WfCihdBgo8zCA/00Ccvg7XiJtOSwAggloC3bkhOEBOmo9agPCARHnOc7rK0D4iFUlEJ619d9q+bvIKMhdZ4BGxX+lSwDKIagBfu9YB5cFXbOcpnAhvQxwPkOro2DmBEA3BclEnVS5P2E+u5smd4IYPYkO3GYxq7E4KWq+M6FBipW1HcADztfNSLXpowG7e8vlDiiUtzGHxmxq3KWdIL5km3LKw1oshSVfcqbzYNH5jZ9McPNP0J7UQ0m9bF7CkHJxqddVJIDyXmqFValrifzJeYJcx4pwCyBwF+OU9Y7djShdNPrqCnYKdYdRwl2uFOo2zr2DJi; 4:+9fCWErZpnTO2j23Qltcy4Um+ezDR058hCgZnAGMPpe7SGU8oo14p1hHw3OJliXK+pbLxNYHeAhuUeLa3BkOg/buQyujDZVtIOuqTZNmIoOg0sjbceBNQ2W6ri7EFpUlHKK2nhJtjhEFHpQQF81+4gACrJQC8xGWPjGAbnTbGAX1VXAF/tm1F3iwTHrC5i/Q8JgF5dDfiSM3QlLUs8B9YHbrHE5aInK8gVbwUthqYXZIqQOpOmqx4yZS21vKJiEkwLzcWZq7OmN3MGRnDAl96g== X-Exchange-Antispam-Report-Test: UriScan:; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(5005006)(8121501046)(3231021)(100000703101)(100105400095)(93006095)(93001095)(10201501046)(3002001)(6041248)(20161123560025)(20161123562025)(20161123558100)(20161123564025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123555025)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:BY2PR05MB1927; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:BY2PR05MB1927; X-Forefront-PRVS: 0486A0CB86 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6009001)(39830400002)(376002)(346002)(189002)(199003)(316002)(105586002)(101416001)(4326008)(103116003)(7736002)(1076002)(68736007)(189998001)(106356001)(53936002)(69596002)(6486002)(50986999)(53416004)(478600001)(33646002)(16526018)(107886003)(6116002)(305945005)(6666003)(25786009)(66066001)(5660300001)(36756003)(2906002)(81156014)(6916009)(8676002)(47776003)(86362001)(15760500003)(48376002)(50226002)(97736004)(50466002)(5003940100001)(54906003)(3846002)(16586007)(8936002)(81166006)(217873001); DIR:OUT; SFP:1101; SCL:1; SRVR:BY2PR05MB1927; H:bars.quantenna.com; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; Received-SPF: None (protection.outlook.com: quantenna.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BY2PR05MB1927; 23:hls8Y3R9nENZfQ+/1CnJOc74buTFvAtFR+rTFzQUk?= =?us-ascii?Q?oyKO5O5P5IJ0DnX6Vk+5JapTC22IEYRW2o9be416cpaoKizXpRwn/6kdAAMZ?= =?us-ascii?Q?HV6pPrt4e4fJggOVtXW06lilYtLrneGoImxbtrogxRFnc9EAofC7S5OWU+Sq?= =?us-ascii?Q?l/T+P3eWUAsodJ6SBotmb8bqYe2a9QnbrwW6iaG48+KEHgqVOcjbwT/II7XU?= =?us-ascii?Q?LIPlLOp6zwmu8UBHmLmvRn/Xbg7+YKIYm7dTRKag/TPEiEisUy9Wq029TFBY?= =?us-ascii?Q?qjkTTioybbwdd2ILRKL2MvrJUnmvLBZ7iS8u9bbHkiVFnwEhK6VVtsi06idn?= =?us-ascii?Q?cdbVt0XLJVUxciSIoh54F1qqLoKqgGicvVOHr/eyk1yiAhQ70n2DWbasfKEz?= =?us-ascii?Q?HXNfWYAITGck4fl86YvOm3TJDcmqmCQb2mBR6+0YmOx4vNOJiURnnKV4MJtl?= =?us-ascii?Q?n0Z+gOkjNwS9yvVoqbrQ6enIcjDqLGUtleG4bjvuMJGpuknHf1LKgppYtbrw?= =?us-ascii?Q?R2K/jDddVaOTedvvACY64N0CSDK62/HH2I0HYrWjyqr+Kz2+eTDHWO19MGAo?= =?us-ascii?Q?CMzNIIYHDuCLiFhmQ+73aW33nRH0+Hbk3M3sUVZQcg2xm4BNJv2yxOjpAnvS?= =?us-ascii?Q?P0CtHfi2rZOu8ESDWNa78k/mAeHkpmxjIwyce2FwDhOH4+VBkl8OxG/V7Iri?= =?us-ascii?Q?yXCBlLSa70r2YDridCzbmoMPxNfDdtne4wlSbtgNOUEquvyoPU4DYWwlQLV/?= =?us-ascii?Q?rvt8pLyyk8rbIUYdD82hjvHvY0OVwKLfCXcF6F62PPHqnNqaMu/8+wV77ajX?= =?us-ascii?Q?V63RL10mnVvc6Ck/KRVa5df0VuRJ9k1t92Qvnignw6sQtK68vP9wFjB2DjSi?= =?us-ascii?Q?0Ts/w+PmZbGskY1YWVYPEeG6GaPLFOoxnqPPcyhvMdmKuIoTMUJdSW1aVGM6?= =?us-ascii?Q?BF6ZLZMqSSi/+FzesBre+u9Tf9nnSoKmBKzjTMLPUZji0bA+OP45nxrMn0dS?= =?us-ascii?Q?FvUmIV/JEmc3i1BPqYXMhWg6Od/H4LHNTz63R/6+O155BXkzPhppuuEWy+F1?= =?us-ascii?Q?PCFNw9hd82/d1yTX/kXFal7xVoRl0ilsV7YOZWpKRg7sjpZuwFtfrrOYxjl8?= =?us-ascii?Q?fnpQVeZ+b+Sj258qtu9m8qlZaUiJ4WDCWA9jISyJd5Yt+QSrGQRzN/E1VZrp?= =?us-ascii?Q?KpkdGc9yDJXj9I=3D?= X-Microsoft-Exchange-Diagnostics: 1; BY2PR05MB1927; 6:toCTS5EdX05KzixboiHINvBIL5HwgY/9V91TBQJk7pDJuRiPCZ2UBdNBbswuOoWKBgerWjTJJRyZJkV97lVc6oHSKwdzyuIuOCX3UZIokzPG1Fqda8VI8BGCkf9PikdrQpRUtwMb6SHVMLFpmzCXElzcdP864htf9zjFCyDdEJgJ3rkUVDtAf10zDvB71yqpDLQc5wyvdMF8/rZEDZzRtF7AvECcHiOVyM20aKo0JBOuOir6STfmDhvrORoVjv6J8nkp7q+0X54+S9NHqZ3ckfoAjDVBjS999eIynp+DjRhEfHnOPRxFLnN08EDjjuA7oTdk16rgIbHylWDIB4cwgXtCUF3m8+vcIViI48GVDYg=; 5:LcmDaRiXJ+RLr7KzkfudnIEvnBfMCleCTsH4LqeDSpSn8RKP4EiwyPTACSuefUZ1QqQVaz3pMfxhwpTZ3ol0dACBxWJ+XfZHi1JV5Le4XD1XRWDqbgkVsUuutMoVzvHVdYYE6A6zzpzJ6OWPHzkcB4wfwavETh+fMKi8CoahudA=; 24:1mPJfmMAcnnSS3JO+rWdpx7lGAstOlpUVKt2Jto1eNbDkD3Mks0RGlkOFiqMpTmhiBSAOM0IUY6OOB7OST+1c8DKlAjr88yUsFHKMxH8Tjc=; 7:uF+1vXgHnfYtOtXyXy3gG58ZkdV9DCjznvS5IB5iIN3CKA3LrqoThe5v8iuCP2KpY0acST/lDlnlmyAthZLU9WJUWSEZOoGeFHniK+wyW02/XQe0TVamT2t9cC9LHaUtQ69YQkKC9AgcHb8V6oGKXzcjemPWBCvOfwqSP/kN5Eng+xgGn6leZyGsTq/YvrSrtNC4Y5Us2/p2zFhW8KyTewMGXj+kIeSmWyJ+P+hTJOMBIs9qHakS69jM4keiJRE1 SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: quantenna.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Nov 2017 09:40:36.8899 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 8fcfacb6-17e8-465c-a2b0-08d52755ef9e X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: a355dbce-62b4-4789-9446-c1d5582180ff X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2PR05MB1927 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Vasily Ulyanov Implement nl80211_get_beacon callback which returns current beacon configuration. The actual data is saved on .start_ap and .set_beacon calls. Signed-off-by: Vasily Ulyanov --- include/net/cfg80211.h | 3 + include/uapi/linux/nl80211.h | 5 +- net/wireless/nl80211.c | 220 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 227 insertions(+), 1 deletion(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 8b8118a7fadb..31d39e066274 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4002,6 +4002,8 @@ struct cfg80211_cqm_config; * the user-set channel definition. * @preset_chandef: (private) Used by the internal configuration code to * track the channel to be used for AP later + * @beacon: (private) Used by the internal configuration code to track + * the user-set effective beacon data. * @bssid: (private) Used by the internal configuration code * @ssid: (private) Used by the internal configuration code * @ssid_len: (private) Used by the internal configuration code @@ -4078,6 +4080,7 @@ struct wireless_dev { struct cfg80211_internal_bss *current_bss; /* associated / joined */ struct cfg80211_chan_def preset_chandef; struct cfg80211_chan_def chandef; + struct cfg80211_beacon_data beacon; bool ibss_fixed; bool ibss_dfs_possible; diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index f882fe1f9709..e9e163bbe11a 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -279,7 +279,10 @@ * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX * or %NL80211_ATTR_MAC. * - * @NL80211_CMD_GET_BEACON: (not used) + * @NL80211_CMD_GET_BEACON: Get beacon attributes on an access point interface. + * %NL80211_ATTR_BEACON_HEAD, %NL80211_ATTR_BEACON_TAIL, %NL80211_ATTR_IE, + * %NL80211_ATTR_IE_PROBE_RESP, NL80211_ATTR_IE_ASSOC_RESP, + * %NL80211_ATTR_PROBE_RESP will be returned if present. * @NL80211_CMD_SET_BEACON: change the beacon on an access point interface * using the %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL * attributes. For drivers that generate the beacon and probe responses diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index fce2cbe6a193..f03f9989efbc 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3784,6 +3784,172 @@ static int nl80211_parse_beacon(struct nlattr *attrs[], return 0; } +static size_t nl80211_beacon_size(struct cfg80211_beacon_data *bcn) +{ + size_t size = bcn->head_len + bcn->tail_len + + bcn->beacon_ies_len + + bcn->proberesp_ies_len + + bcn->assocresp_ies_len + + bcn->probe_resp_len; + + return size; +} + +static void nl80211_free_beacon(struct cfg80211_beacon_data *bcn) +{ +#define free_and_null(member) \ + do { \ + kfree(bcn->member); \ + bcn->member = NULL; \ + bcn->member ## _len = 0; \ + } while (0) + + free_and_null(head); + free_and_null(tail); + free_and_null(beacon_ies); + free_and_null(proberesp_ies); + free_and_null(assocresp_ies); + free_and_null(probe_resp); + +#undef free_and_null +} + +static int nl80211_dup_beacon(struct cfg80211_beacon_data *dst, + struct cfg80211_beacon_data *src) +{ + memset(dst, 0, sizeof(*dst)); + +#define check_and_dup(member) \ + do { \ + if (src->member && (src->member ## _len > 0)) { \ + dst->member = kmemdup(src->member, \ + src->member ## _len, \ + GFP_KERNEL); \ + if (!dst->member) \ + goto dup_failure; \ + dst->member ## _len = src->member ## _len; \ + } \ + } while (0) + + check_and_dup(head); + check_and_dup(tail); + check_and_dup(beacon_ies); + check_and_dup(proberesp_ies); + check_and_dup(assocresp_ies); + check_and_dup(probe_resp); + +#undef dup_and_check + + return 0; + +dup_failure: + nl80211_free_beacon(dst); + return -ENOMEM; +} + +static int nl80211_merge_beacons(struct cfg80211_beacon_data *dst, + struct cfg80211_beacon_data *old, + struct cfg80211_beacon_data *new) +{ + memset(dst, 0, sizeof(*dst)); + +#define check_and_merge(member) \ + do { \ + if (new->member && (new->member ## _len > 0)) { \ + dst->member = kmemdup(new->member, \ + new->member ## _len, \ + GFP_KERNEL); \ + if (!dst->member) \ + goto dup_failure; \ + dst->member ## _len = new->member ## _len; \ + } else if (old->member && (old->member ## _len > 0)) { \ + dst->member = kmemdup(old->member, \ + old->member ## _len, \ + GFP_KERNEL); \ + if (!dst->member) \ + goto dup_failure; \ + dst->member ## _len = old->member ## _len; \ + } \ + } while (0) + + check_and_merge(head); + check_and_merge(tail); + check_and_merge(beacon_ies); + check_and_merge(proberesp_ies); + check_and_merge(assocresp_ies); + check_and_merge(probe_resp); + +#undef check_and_merge + + return 0; + +dup_failure: + nl80211_free_beacon(dst); + return -ENOMEM; +} + +static void nl80211_assign_beacon(struct cfg80211_beacon_data *dst, + struct cfg80211_beacon_data *src) +{ + nl80211_free_beacon(dst); + *dst = *src; +} + +static int nl80211_send_beacon(struct sk_buff *msg, u32 portid, + enum nl80211_commands cmd, + u32 seq, int flags, + struct cfg80211_beacon_data *bcn) +{ + void *hdr; + + hdr = nl80211hdr_put(msg, portid, seq, flags, cmd); + if (!hdr) + return -EMSGSIZE; + + if (bcn->head && (bcn->head_len > 0)) { + if (nla_put(msg, NL80211_ATTR_BEACON_HEAD, + bcn->head_len, bcn->head)) + goto nla_put_failure; + } + + if (bcn->tail && (bcn->tail_len > 0)) { + if (nla_put(msg, NL80211_ATTR_BEACON_TAIL, + bcn->tail_len, bcn->tail)) + goto nla_put_failure; + } + + if (bcn->beacon_ies && (bcn->beacon_ies_len > 0)) { + if (nla_put(msg, NL80211_ATTR_IE, + bcn->beacon_ies_len, bcn->beacon_ies)) + goto nla_put_failure; + } + + if (bcn->proberesp_ies && (bcn->proberesp_ies_len > 0)) { + if (nla_put(msg, NL80211_ATTR_IE_PROBE_RESP, + bcn->proberesp_ies_len, bcn->proberesp_ies)) + goto nla_put_failure; + } + + if (bcn->assocresp_ies && (bcn->assocresp_ies_len > 0)) { + if (nla_put(msg, NL80211_ATTR_IE_ASSOC_RESP, + bcn->assocresp_ies_len, bcn->assocresp_ies)) + goto nla_put_failure; + } + + if (bcn->probe_resp && (bcn->probe_resp_len > 0)) { + if (nla_put(msg, NL80211_ATTR_PROBE_RESP, + bcn->probe_resp_len, bcn->probe_resp)) + goto nla_put_failure; + } + + genlmsg_end(msg, hdr); + return 0; + +nla_put_failure: + genlmsg_cancel(msg, hdr); + return -EMSGSIZE; +} + static void nl80211_check_ap_rate_selectors(struct cfg80211_ap_settings *params, const u8 *rates) { @@ -3903,6 +4069,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) struct net_device *dev = info->user_ptr[1]; struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_ap_settings params; + struct cfg80211_beacon_data new_bcn; int err; if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && @@ -4070,6 +4237,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) nl80211_calculate_ap_params(¶ms); + err = nl80211_dup_beacon(&new_bcn, ¶ms.beacon); + if (err) + goto dup_failure; + wdev_lock(wdev); err = rdev_start_ap(rdev, dev, ¶ms); if (!err) { @@ -4078,20 +4249,52 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) wdev->chandef = params.chandef; wdev->ssid_len = params.ssid_len; memcpy(wdev->ssid, params.ssid, wdev->ssid_len); + nl80211_assign_beacon(&wdev->beacon, &new_bcn); } wdev_unlock(wdev); + if (err) + nl80211_free_beacon(&new_bcn); + +dup_failure: kfree(params.acl); return err; } +static int nl80211_get_beacon(struct sk_buff *skb, struct genl_info *info) +{ + struct net_device *dev = info->user_ptr[1]; + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct sk_buff *msg; + + if (wdev->iftype != NL80211_IFTYPE_AP && + wdev->iftype != NL80211_IFTYPE_P2P_GO) + return -EOPNOTSUPP; + + if (!wdev->beacon_interval) + return -EINVAL; + + msg = nlmsg_new(nl80211_beacon_size(&wdev->beacon), GFP_KERNEL); + if (!msg) + return -ENOMEM; + + if (nl80211_send_beacon(msg, NL80211_CMD_GET_BEACON, info->snd_portid, + info->snd_seq, 0, &wdev->beacon) < 0) { + nlmsg_free(msg); + return -ENOBUFS; + } + + return genlmsg_reply(msg, info); +} + static int nl80211_set_beacon(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 wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_beacon_data params; + struct cfg80211_beacon_data merged_bcn; int err; if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && @@ -4108,10 +4311,19 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info) if (err) return err; + err = nl80211_merge_beacons(&merged_bcn, &wdev->beacon, ¶ms); + if (err) + return err; + wdev_lock(wdev); err = rdev_change_beacon(rdev, dev, ¶ms); + if (!err) + nl80211_assign_beacon(&wdev->beacon, &merged_bcn); wdev_unlock(wdev); + if (err) + nl80211_free_beacon(&merged_bcn); + return err; } @@ -12595,6 +12807,14 @@ static const struct genl_ops nl80211_ops[] = { NL80211_FLAG_NEED_RTNL, }, { + .cmd = NL80211_CMD_GET_BEACON, + .policy = nl80211_policy, + .flags = GENL_UNS_ADMIN_PERM, + .doit = nl80211_get_beacon, + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, + { .cmd = NL80211_CMD_SET_BEACON, .policy = nl80211_policy, .flags = GENL_UNS_ADMIN_PERM,