summaryrefslogtreecommitdiff
path: root/frag.c
diff options
context:
space:
mode:
authorThomson Kang <thomson.kang@broadcom.corp-partner.google.com>2020-08-07 13:10:38 +0900
committerAhmed ElArabawy <arabawy@google.com>2020-08-11 08:50:34 -0700
commitb201998fe9fc2dc6890a57b16d0b299f1c0ed4f7 (patch)
treeba4d5097a96ce881fb20d352cb63d15c7aa0a8a6 /frag.c
parentc03ae442aeb9c733879fb0413b600098767f9923 (diff)
downloadbcm4389-b201998fe9fc2dc6890a57b16d0b299f1c0ed4f7.tar.gz
Initial Drop for bcm4389, 2020.08.07
Version : 101.10.355 Bug: 162998780 Test: Make sure it builds, starts at boot, and passes smoke test Signed-off-by: Thomson Kang <thomson.kang@broadcom.corp-partner.google.com> Change-Id: Iba369c92c096a3bcf25ada42ad6a80ac78ecb43d Signed-off-by: Ahmed ElArabawy <arabawy@google.com>
Diffstat (limited to 'frag.c')
-rw-r--r--frag.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/frag.c b/frag.c
new file mode 100644
index 0000000..e49c335
--- /dev/null
+++ b/frag.c
@@ -0,0 +1,108 @@
+/*
+ * IE/TLV fragmentation/defragmentation support for
+ * Broadcom 802.11bang Networking Device Driver
+ *
+ * Copyright (C) 2020, Broadcom.
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Dual:>>
+ */
+
+#include <bcmutils.h>
+#include <frag.h>
+#include <802.11.h>
+
+/* defrag a fragmented dot11 ie/tlv. if space does not permit, return the needed
+ * ie length to contain all the fragments with status BCME_BUFTOOSHORT.
+ * out_len is in/out parameter, max length on input, used/required length on output
+ */
+int
+bcm_tlv_dot11_defrag(const void *buf, uint buf_len, uint8 id, bool id_ext,
+ uint8 *out, uint *out_len)
+{
+ int err = BCME_OK;
+ const bcm_tlv_t *ie;
+ uint tot_len = 0;
+ uint out_left;
+
+ /* find the ie; includes validation */
+ ie = bcm_parse_tlvs_dot11(buf, buf_len, id, id_ext);
+ if (!ie) {
+ err = BCME_IE_NOTFOUND;
+ goto done;
+ }
+
+ out_left = (out && out_len) ? *out_len : 0;
+
+ /* first fragment */
+ tot_len = id_ext ? ie->len - 1 : ie->len;
+
+ /* copy out if output space permits */
+ if (out_left < tot_len) {
+ err = BCME_BUFTOOSHORT;
+ out_left = 0; /* prevent further copy */
+ } else {
+ memcpy(out, &ie->data[id_ext ? 1 : 0], tot_len);
+ out += tot_len;
+ out_left -= tot_len;
+ }
+
+ /* if not fragmened or not fragmentable per 802.11 table 9-77 11md0.1 bail
+ * we can introduce the latter check later
+ */
+ if (ie->len != BCM_TLV_MAX_DATA_SIZE) {
+ goto done;
+ }
+
+ /* adjust buf_len to length after ie including it */
+ buf_len -= (uint)(((const uint8 *)ie - (const uint8 *)buf));
+
+ /* update length from fragments, okay if no next ie */
+ while ((ie = bcm_next_tlv(ie, &buf_len)) &&
+ (ie->id == DOT11_MNG_FRAGMENT_ID)) {
+ /* note: buf_len starts at next ie and last frag may be partial */
+ if (out_left < ie->len) {
+ err = BCME_BUFTOOSHORT;
+ out_left = 0;
+ } else {
+ memcpy(out, &ie->data[0], ie->len);
+ out += ie->len;
+ out_left -= ie->len;
+ }
+
+ tot_len += ie->len + BCM_TLV_HDR_SIZE;
+
+ /* all but last should be of max size */
+ if (ie->len < BCM_TLV_MAX_DATA_SIZE) {
+ break;
+ }
+ }
+
+done:
+ if (out_len) {
+ *out_len = tot_len;
+ }
+
+ return err;
+}
+
+int
+bcm_tlv_dot11_frag_tot_len(const void *buf, uint buf_len,
+ uint8 id, bool id_ext, uint *ie_len)
+{
+ return bcm_tlv_dot11_defrag(buf, buf_len, id, id_ext, NULL, ie_len);
+}