Coverage Report

Created: 2026-07-10 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/SockFuzzer/third_party/xnu/bsd/net/frame802154.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2017-2021 Apple Inc. All rights reserved.
3
 *
4
 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5
 *
6
 * This file contains Original Code and/or Modifications of Original Code
7
 * as defined in and that are subject to the Apple Public Source License
8
 * Version 2.0 (the 'License'). You may not use this file except in
9
 * compliance with the License. The rights granted to you under the License
10
 * may not be used to create, or enable the creation or redistribution of,
11
 * unlawful or unlicensed copies of an Apple operating system, or to
12
 * circumvent, violate, or enable the circumvention or violation of, any
13
 * terms of an Apple operating system software license agreement.
14
 *
15
 * Please obtain a copy of the License at
16
 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17
 *
18
 * The Original Code and all software distributed under the License are
19
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23
 * Please see the License for the specific language governing rights and
24
 * limitations under the License.
25
 *
26
 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27
 */
28
/*
29
 *
30
 *  Copyright (c) 2008, Swedish Institute of Computer Science
31
 *  All rights reserved.
32
 *
33
 *  Additional fixes for AVR contributed by:
34
 *
35
 *      Colin O'Flynn coflynn@newae.com
36
 *      Eric Gnoske egnoske@gmail.com
37
 *      Blake Leverett bleverett@gmail.com
38
 *      Mike Vidales mavida404@gmail.com
39
 *      Kevin Brown kbrown3@uccs.edu
40
 *      Nate Bohlmann nate@elfwerks.com
41
 *
42
 *  Additional fixes for MSP430 contributed by:
43
 *        Joakim Eriksson
44
 *        Niclas Finne
45
 *        Nicolas Tsiftes
46
 *
47
 *   All rights reserved.
48
 *
49
 *   Redistribution and use in source and binary forms, with or without
50
 *   modification, are permitted provided that the following conditions are met:
51
 *
52
 *   * Redistributions of source code must retain the above copyright
53
 *     notice, this list of conditions and the following disclaimer.
54
 *   * Redistributions in binary form must reproduce the above copyright
55
 *     notice, this list of conditions and the following disclaimer in
56
 *     the documentation and/or other materials provided with the
57
 *     distribution.
58
 *   * Neither the name of the copyright holders nor the names of
59
 *     contributors may be used to endorse or promote products derived
60
 *     from this software without specific prior written permission.
61
 *
62
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
63
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
66
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
67
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
68
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
69
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
70
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
71
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
72
 *  POSSIBILITY OF SUCH DAMAGE.
73
 *
74
 */
75
/*
76
 *  \brief This file is where the main functions that relate to frame
77
 *  manipulation will reside.
78
 */
79
80
/**
81
 *  \file
82
 *  \brief 802.15.4 frame creation and parsing functions
83
 *
84
 *  This file converts to and from a structure to a packed 802.15.4
85
 *  frame.
86
 */
87
88
/**
89
 *   \addtogroup frame802154
90
 *   @{
91
 */
92
93
#include "cc.h"
94
#include "frame802154.h"
95
//#include "net/llsec/llsec802154.h"
96
#include "linkaddr.h"
97
#include <string.h>
98
99
/**
100
 *  \brief Structure that contains the lengths of the various addressing and security fields
101
 *  in the 802.15.4 header.  This structure is used in \ref frame802154_create()
102
 */
103
typedef struct {
104
  uint8_t dest_pid_len;    /**<  Length (in bytes) of destination PAN ID field */
105
  uint8_t dest_addr_len;   /**<  Length (in bytes) of destination address field */
106
  uint8_t src_pid_len;     /**<  Length (in bytes) of source PAN ID field */
107
  uint8_t src_addr_len;    /**<  Length (in bytes) of source address field */
108
  uint8_t aux_sec_len;     /**<  Length (in bytes) of aux security header field */
109
} field_length_t;
110
111
/*----------------------------------------------------------------------------*/
112
CC_INLINE static uint8_t
113
addr_len(uint8_t mode)
114
0
{
115
0
  switch (mode) {
116
0
  case FRAME802154_SHORTADDRMODE:          /* 16-bit address */
117
0
    return 2;
118
0
  case FRAME802154_LONGADDRMODE:           /* 64-bit address */
119
0
    return 8;
120
0
  default:
121
0
    return 0;
122
0
  }
123
0
}
124
/*----------------------------------------------------------------------------*/
125
#if LLSEC802154_USES_EXPLICIT_KEYS
126
static uint8_t
127
get_key_id_len(uint8_t key_id_mode)
128
{
129
  switch (key_id_mode) {
130
  case FRAME802154_1_BYTE_KEY_ID_MODE:
131
    return 1;
132
  case FRAME802154_5_BYTE_KEY_ID_MODE:
133
    return 5;
134
  case FRAME802154_9_BYTE_KEY_ID_MODE:
135
    return 9;
136
  default:
137
    return 0;
138
  }
139
}
140
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
141
/*----------------------------------------------------------------------------*/
142
static void
143
field_len(frame802154_t *p, field_length_t *flen)
144
0
{
145
  /* init flen to zeros */
146
0
  memset(flen, 0, sizeof(field_length_t));
147
148
  /* Determine lengths of each field based on fcf and other args */
149
0
  if (p->fcf.dest_addr_mode & 3) {
150
0
    flen->dest_pid_len = 2;
151
0
  }
152
0
  if (p->fcf.src_addr_mode & 3) {
153
0
    flen->src_pid_len = 2;
154
0
  }
155
156
  /* Set PAN ID compression bit if src pan id matches dest pan id. */
157
0
  if (p->fcf.dest_addr_mode & 3 && p->fcf.src_addr_mode & 3 &&
158
0
      p->src_pid == p->dest_pid) {
159
0
    p->fcf.panid_compression = 1;
160
161
    /* compressed header, only do dest pid */
162
0
    flen->src_pid_len = 0;
163
0
  } else {
164
0
    p->fcf.panid_compression = 0;
165
0
  }
166
167
  /* determine address lengths */
168
0
  flen->dest_addr_len = addr_len(p->fcf.dest_addr_mode & 3);
169
0
  flen->src_addr_len = addr_len(p->fcf.src_addr_mode & 3);
170
171
#if LLSEC802154_SECURITY_LEVEL
172
  /* Aux security header */
173
  if (p->fcf.security_enabled & 1) {
174
    flen->aux_sec_len = 5
175
#if LLSEC802154_USES_EXPLICIT_KEYS
176
        + get_key_id_len(p->aux_hdr.security_control.key_id_mode);
177
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
178
    ;
179
  }
180
#endif /* LLSEC802154_SECURITY_LEVEL */
181
0
}
182
/*----------------------------------------------------------------------------*/
183
/**
184
 *   \brief Calculates the length of the frame header.  This function is
185
 *   meant to be called by a higher level function, that interfaces to a MAC.
186
 *
187
 *   \param p Pointer to frame802154_t_t struct, which specifies the
188
 *   frame to send.
189
 *
190
 *   \return The length of the frame header.
191
 */
192
int
193
frame802154_hdrlen(frame802154_t *p)
194
0
{
195
0
  field_length_t flen;
196
0
  field_len(p, &flen);
197
0
  return 3 + flen.dest_pid_len + flen.dest_addr_len +
198
0
         flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len;
199
0
}
200
/*----------------------------------------------------------------------------*/
201
/**
202
 *   \brief Creates a frame for transmission over the air.  This function is
203
 *   meant to be called by a higher level function, that interfaces to a MAC.
204
 *
205
 *   \param p Pointer to frame802154_t struct, which specifies the
206
 *   frame to send.
207
 *
208
 *   \param buf Pointer to the buffer to use for the frame.
209
 *
210
 *   \return The length of the frame header
211
 */
212
int
213
frame802154_create(frame802154_t *p, uint8_t *buf)
214
0
{
215
0
  int c;
216
0
  field_length_t flen;
217
0
  uint8_t pos;
218
#if LLSEC802154_USES_EXPLICIT_KEYS
219
  uint8_t key_id_mode;
220
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
221
222
0
  field_len(p, &flen);
223
224
  /* OK, now we have field lengths.  Time to actually construct */
225
  /* the outgoing frame, and store it in buf */
226
0
  buf[0] = (uint8_t)((p->fcf.frame_type & 7) |
227
0
      ((p->fcf.security_enabled & 1) << 3) |
228
0
      ((p->fcf.frame_pending & 1) << 4) |
229
0
      ((p->fcf.ack_required & 1) << 5) |
230
0
      ((p->fcf.panid_compression & 1) << 6));
231
0
  buf[1] = (uint8_t)(((p->fcf.dest_addr_mode & 3) << 2) |
232
0
      ((p->fcf.frame_version & 3) << 4) |
233
0
      ((p->fcf.src_addr_mode & 3) << 6));
234
235
  /* sequence number */
236
0
  buf[2] = p->seq;
237
0
  pos = 3;
238
239
  /* Destination PAN ID */
240
0
  if (flen.dest_pid_len == 2) {
241
0
    buf[pos++] = p->dest_pid & 0xff;
242
0
    buf[pos++] = (p->dest_pid >> 8) & 0xff;
243
0
  }
244
245
  /* Destination address */
246
0
  for (c = flen.dest_addr_len; c > 0; c--) {
247
0
    buf[pos++] = p->dest_addr[c - 1];
248
0
  }
249
250
  /* Source PAN ID */
251
0
  if (flen.src_pid_len == 2) {
252
0
    buf[pos++] = p->src_pid & 0xff;
253
0
    buf[pos++] = (p->src_pid >> 8) & 0xff;
254
0
  }
255
256
  /* Source address */
257
0
  for (c = flen.src_addr_len; c > 0; c--) {
258
0
    buf[pos++] = p->src_addr[c - 1];
259
0
  }
260
261
#if LLSEC802154_SECURITY_LEVEL
262
  /* Aux header */
263
  if (flen.aux_sec_len) {
264
    buf[pos++] = p->aux_hdr.security_control.security_level
265
#if LLSEC802154_USES_EXPLICIT_KEYS
266
        | (p->aux_hdr.security_control.key_id_mode << 3)
267
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
268
    ;
269
    memcpy(buf + pos, p->aux_hdr.frame_counter.u8, 4);
270
    pos += 4;
271
272
#if LLSEC802154_USES_EXPLICIT_KEYS
273
    key_id_mode = p->aux_hdr.security_control.key_id_mode;
274
    if (key_id_mode) {
275
      c = (key_id_mode - 1) * 4;
276
      memcpy(buf + pos, p->aux_hdr.key_source.u8, c);
277
      pos += c;
278
      buf[pos++] = p->aux_hdr.key_index;
279
    }
280
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
281
  }
282
#endif /* LLSEC802154_SECURITY_LEVEL */
283
284
0
  return (int)pos;
285
0
}
286
/*----------------------------------------------------------------------------*/
287
/**
288
 *   \brief Parses an input frame.  Scans the input frame to find each
289
 *   section, and stores the information of each section in a
290
 *   frame802154_t structure.
291
 *
292
 *   \param data The input data from the radio chip.
293
 *   \param len The size of the input data
294
 *   \param pf The frame802154_t struct to store the parsed frame information.
295
 */
296
size_t
297
frame802154_parse(uint8_t *data, size_t len, frame802154_t *pf, uint8_t **payload)
298
0
{
299
0
  uint8_t *p;
300
0
  frame802154_fcf_t fcf;
301
0
  size_t c;
302
#if LLSEC802154_USES_EXPLICIT_KEYS
303
  uint8_t key_id_mode;
304
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
305
306
0
  if (len < 3) {
307
0
    *payload = NULL;
308
0
    return 0;
309
0
  }
310
311
0
  p = data;
312
313
  /* decode the FCF */
314
0
  fcf.frame_type = p[0] & 7;
315
0
  fcf.security_enabled = (p[0] >> 3) & 1;
316
0
  fcf.frame_pending = (p[0] >> 4) & 1;
317
0
  fcf.ack_required = (p[0] >> 5) & 1;
318
0
  fcf.panid_compression = (p[0] >> 6) & 1;
319
320
0
  fcf.dest_addr_mode = (p[1] >> 2) & 3;
321
0
  fcf.frame_version = (p[1] >> 4) & 3;
322
0
  fcf.src_addr_mode = (p[1] >> 6) & 3;
323
324
  /* copy fcf and seqNum */
325
0
  memcpy(&pf->fcf, &fcf, sizeof(frame802154_fcf_t));
326
0
  pf->seq = p[2];
327
0
  p += 3;                             /* Skip first three bytes */
328
329
  /* Destination address, if any */
330
0
  if (fcf.dest_addr_mode) {
331
    /* Destination PAN */
332
0
    pf->dest_pid = (uint16_t)(p[0] + (p[1] << 8));
333
0
    p += 2;
334
335
    /* Destination address */
336
    /*     l = addr_len(fcf.dest_addr_mode); */
337
    /*     for(c = 0; c < l; c++) { */
338
    /*       pf->dest_addr.u8[c] = p[l - c - 1]; */
339
    /*     } */
340
    /*     p += l; */
341
0
    if (fcf.dest_addr_mode == FRAME802154_SHORTADDRMODE) {
342
0
      linkaddr_copy((linkaddr_t *)(uintptr_t)&(pf->dest_addr), &linkaddr_null);
343
0
      pf->dest_addr[0] = p[1];
344
0
      pf->dest_addr[1] = p[0];
345
0
      p += 2;
346
0
    } else if (fcf.dest_addr_mode == FRAME802154_LONGADDRMODE) {
347
0
      for (c = 0; c < 8; c++) {
348
0
        pf->dest_addr[c] = p[7 - c];
349
0
      }
350
0
      p += 8;
351
0
    }
352
0
  } else {
353
0
    linkaddr_copy((linkaddr_t *)(uintptr_t)&(pf->dest_addr), &linkaddr_null);
354
0
    pf->dest_pid = 0;
355
0
  }
356
357
  /* Source address, if any */
358
0
  if (fcf.src_addr_mode) {
359
    /* Source PAN */
360
0
    if (!fcf.panid_compression) {
361
0
      pf->src_pid = (uint16_t)(p[0] + (p[1] << 8));
362
0
      p += 2;
363
0
    } else {
364
0
      pf->src_pid = pf->dest_pid;
365
0
    }
366
367
    /* Source address */
368
    /*     l = addr_len(fcf.src_addr_mode); */
369
    /*     for(c = 0; c < l; c++) { */
370
    /*       pf->src_addr.u8[c] = p[l - c - 1]; */
371
    /*     } */
372
    /*     p += l; */
373
0
    if (fcf.src_addr_mode == FRAME802154_SHORTADDRMODE) {
374
0
      linkaddr_copy((linkaddr_t *)(uintptr_t)&(pf->src_addr), &linkaddr_null);
375
0
      pf->src_addr[0] = p[1];
376
0
      pf->src_addr[1] = p[0];
377
0
      p += 2;
378
0
    } else if (fcf.src_addr_mode == FRAME802154_LONGADDRMODE) {
379
0
      for (c = 0; c < 8; c++) {
380
0
        pf->src_addr[c] = p[7 - c];
381
0
      }
382
0
      p += 8;
383
0
    }
384
0
  } else {
385
0
    linkaddr_copy((linkaddr_t *)(uintptr_t)&(pf->src_addr), &linkaddr_null);
386
0
    pf->src_pid = 0;
387
0
  }
388
389
#if LLSEC802154_SECURITY_LEVEL
390
  if (fcf.security_enabled) {
391
    pf->aux_hdr.security_control.security_level = p[0] & 7;
392
#if LLSEC802154_USES_EXPLICIT_KEYS
393
    pf->aux_hdr.security_control.key_id_mode = (p[0] >> 3) & 3;
394
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
395
    p += 1;
396
397
    memcpy(pf->aux_hdr.frame_counter.u8, p, 4);
398
    p += 4;
399
400
#if LLSEC802154_USES_EXPLICIT_KEYS
401
    key_id_mode = pf->aux_hdr.security_control.key_id_mode;
402
    if (key_id_mode) {
403
      c = (key_id_mode - 1) * 4;
404
      memcpy(pf->aux_hdr.key_source.u8, p, c);
405
      p += c;
406
      pf->aux_hdr.key_index = p[0];
407
      p += 1;
408
    }
409
#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
410
  }
411
#endif /* LLSEC802154_SECURITY_LEVEL */
412
413
  /* header length */
414
0
  c = p - data;
415
416
417
0
  if (c <= len) {
418
    /* payload length */
419
0
    pf->payload_len = (int)(len - c);
420
    /* payload */
421
0
    *payload = p;
422
0
  } else {
423
0
    *payload = NULL;
424
0
  }
425
426
  /* return header length if successful */
427
0
  return c > len ? 0 : c;
428
0
}
429
/** \}   */