<commit_before>/*
 * Copyright (C) 2019 HAW Hamburg
 *
 * This file is subject to the terms and conditions of the GNU Lesser
 * General Public License v2.1. See the file LICENSE in the top level
 * directory for more details.
 */

/**
 * @{
 *
 * @file
 * @author  <NAME> <<EMAIL>>
 */

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "net/lora.h"
#include "net/gnrc/lorawan.h"
#include "net/gnrc/lorawan/region.h"
#include "errno.h"
#include "net/gnrc/pktbuf.h"

#include "net/lorawan/hdr.h"

#include "random.h"

#define ENABLE_DEBUG      0
#include "debug.h"

#define _16_UPPER_BITMASK 0xFFFF0000
#define _16_LOWER_BITMASK 0xFFFF

static void _end_of_tx(gnrc_lorawan_t *mac, int type, int status);

static int gnrc_lorawan_mic_is_valid(uint8_t *buf, size_t len, uint8_t *nwkskey)
{
    le_uint32_t calc_mic;

    lorawan_hdr_t *lw_hdr = (lorawan_hdr_t *)buf;

    uint32_t fcnt = byteorder_ltohs(lw_hdr->fcnt);
    iolist_t iol =
    { .iol_base = buf, .iol_len = len - MIC_SIZE, .iol_next = NULL };

    gnrc_lorawan_calculate_mic(&lw_hdr->addr, fcnt, GNRC_LORAWAN_DIR_DOWNLINK,
                               &iol, nwkskey, &calc_mic);
    return calc_mic.u32 == ((le_uint32_t *)(buf + len - MIC_SIZE))->u32;
}

uint32_t gnrc_lorawan_fcnt_stol(uint32_t fcnt_down, uint16_t s_fcnt)
{
    uint32_t u32_fcnt = (fcnt_down & _16_UPPER_BITMASK) | s_fcnt;

    if (fcnt_down + CONFIG_LORAMAC_DEFAULT_MAX_FCNT_GAP >= _16_LOWER_BITMASK
        && s_fcnt < (fcnt_down & _16_LOWER_BITMASK)) {
        u32_fcnt += _16_LOWER_BITMASK;
    }
    return u32_fcnt;
}

/**
 * @brief holder of parsed packet
 */
struct parsed_packet {
    uint32_t fcnt_down;         /**< frame counter */
    lorawan_hdr_t *hdr;         /**< pointer to the LoRaWAN header */
    bool ack_req;               /**< whether an ACK was requested or not */
    iolist_t fopts;             /**< iolist with Fopts information */
    iolist_t enc_payload;       /**< iolist with encrypted payload */
    uint8_t port;               /**< Fport of the packet */
    bool ack;                   /**< whether the ACK bit was set or not */
    bool frame_pending;         /**< whether there's pending data or not */
};

int gnrc_lorawan_parse_dl(gnrc_lorawan_t *mac, uint8_t *buf, size_t len,
                          struct parsed_packet *pkt)
{
    memset(pkt, 0, sizeof(struct parsed_packet));

    lorawan_hdr_t *_hdr = (lorawan_hdr_t *)buf;
    uint8_t *p_mic = buf + len - MIC_SIZE;

    pkt->hdr = _hdr;
    buf += sizeof(lorawan_hdr_t);

    /* Validate header */
    if (_hdr->addr.u32 != mac->dev_addr.u32) {
        DEBUG("gnrc_lorawan: received packet with wrong dev addr. Drop\n");
        return -1;
    }

    uint32_t _fcnt =
        gnrc_lorawan_fcnt_stol(mac->mcps.fcnt_down, _hdr->fcnt.u16);

    if (mac->mcps.fcnt_down > _fcnt || mac->mcps.fcnt_down +
        CONFIG_LORAMAC_DEFAULT_MAX_FCNT_GAP < _fcnt) {
        DEBUG("gnrc_lorawan: wrong frame counter\n");
        return -1;
    }

    pkt->fcnt_down = _fcnt;

    int fopts_length = lorawan_hdr_get_frame_opts_len(_hdr);

    if (fopts_length) {
        pkt->fopts.iol_base = buf;
        pkt->fopts.iol_len = fopts_length;
        buf += fopts_length;
    }

    if (buf < p_mic) {
        pkt->port = *(buf++);

        if (!pkt->port && fopts_length) {
            DEBUG("gnrc_lorawan: packet with fopts and port == 0. Drop\n");
            return -1;
        }

        if (buf < p_mic) {
            pkt->enc_payload.iol_base = buf;
            pkt->enc_payload.iol_len = p_mic - buf;
        }
    }

    pkt->ack_req = lorawan_hdr_get_mtype(_hdr) == MTYPE_CNF_DOWNLINK;
    pkt->ack = lorawan_hdr_get_ack(_hdr);
    pkt->frame_pending = lorawan_hdr_get_frame_pending(_hdr);

    return 0;
}

void gnrc_lorawan_mcps_process_downlink(gnrc_lorawan_t *mac, uint8_t *psdu,
                                        size_t size)
{
    struct parsed_packet _pkt;

    /* NOTE: MIC is in pkt */
    if (!gnrc_lorawan_mic_is_valid(psdu, size, mac->nwkskey)) {
        DEBUG("gnrc_lorawan: invalid MIC\n");
        gnrc_lorawan_event_no_rx(mac);
        return;
    }

    if (gnrc_lorawan_parse_dl(mac, psdu, size, &_pkt) < 0) {<commit_msg>gnrc_lorawan: drop frame if port exceeds max app port<commit_after>/*
 * Copyright (C) 2019 HAW Hamburg
 *
 * This file is subject to the terms and conditions of the GNU Lesser
 * General Public License v2.1. See the file LICENSE in the top level
 * directory for more details.
 */

/**
 * @{
 *
 * @file
 * @author  <NAME> <<EMAIL>>
 */

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "net/lora.h"
#include "net/gnrc/lorawan.h"
#include "net/gnrc/lorawan/region.h"
#include "errno.h"
#include "net/gnrc/pktbuf.h"

#include "net/lorawan/hdr.h"

#include "random.h"

#define ENABLE_DEBUG      0
#include "debug.h"

#define _16_UPPER_BITMASK 0xFFFF0000
#define _16_LOWER_BITMASK 0xFFFF

static void _end_of_tx(gnrc_lorawan_t *mac, int type, int status);

static int gnrc_lorawan_mic_is_valid(uint8_t *buf, size_t len, uint8_t *nwkskey)
{
    le_uint32_t calc_mic;

    lorawan_hdr_t *lw_hdr = (lorawan_hdr_t *)buf;

    uint32_t fcnt = byteorder_ltohs(lw_hdr->fcnt);
    iolist_t iol =
    { .iol_base = buf, .iol_len = len - MIC_SIZE, .iol_next = NULL };

    gnrc_lorawan_calculate_mic(&lw_hdr->addr, fcnt, GNRC_LORAWAN_DIR_DOWNLINK,
                               &iol, nwkskey, &calc_mic);
    return calc_mic.u32 == ((le_uint32_t *)(buf + len - MIC_SIZE))->u32;
}

uint32_t gnrc_lorawan_fcnt_stol(uint32_t fcnt_down, uint16_t s_fcnt)
{
    uint32_t u32_fcnt = (fcnt_down & _16_UPPER_BITMASK) | s_fcnt;

    if (fcnt_down + CONFIG_LORAMAC_DEFAULT_MAX_FCNT_GAP >= _16_LOWER_BITMASK
        && s_fcnt < (fcnt_down & _16_LOWER_BITMASK)) {
        u32_fcnt += _16_LOWER_BITMASK;
    }
    return u32_fcnt;
}

/**
 * @brief holder of parsed packet
 */
struct parsed_packet {
    uint32_t fcnt_down;         /**< frame counter */
    lorawan_hdr_t *hdr;         /**< pointer to the LoRaWAN header */
    bool ack_req;               /**< whether an ACK was requested or not */
    iolist_t fopts;             /**< iolist with Fopts information */
    iolist_t enc_payload;       /**< iolist with encrypted payload */
    uint8_t port;               /**< Fport of the packet */
    bool ack;                   /**< whether the ACK bit was set or not */
    bool frame_pending;         /**< whether there's pending data or not */
};

int gnrc_lorawan_parse_dl(gnrc_lorawan_t *mac, uint8_t *buf, size_t len,
                          struct parsed_packet *pkt)
{
    memset(pkt, 0, sizeof(struct parsed_packet));

    lorawan_hdr_t *_hdr = (lorawan_hdr_t *)buf;
    uint8_t *p_mic = buf + len - MIC_SIZE;

    pkt->hdr = _hdr;
    buf += sizeof(lorawan_hdr_t);

    /* Validate header */
    if (_hdr->addr.u32 != mac->dev_addr.u32) {
        DEBUG("gnrc_lorawan: received packet with wrong dev addr. Drop\n");
        return -1;
    }

    uint32_t _fcnt =
        gnrc_lorawan_fcnt_stol(mac->mcps.fcnt_down, _hdr->fcnt.u16);

    if (mac->mcps.fcnt_down > _fcnt || mac->mcps.fcnt_down +
        CONFIG_LORAMAC_DEFAULT_MAX_FCNT_GAP < _fcnt) {
        DEBUG("gnrc_lorawan: wrong frame counter\n");
        return -1;
    }

    pkt->fcnt_down = _fcnt;

    int fopts_length = lorawan_hdr_get_frame_opts_len(_hdr);

    if (fopts_length) {
        pkt->fopts.iol_base = buf;
        pkt->fopts.iol_len = fopts_length;
        buf += fopts_length;
    }

    if (buf < p_mic) {
        pkt->port = *(buf++);

        if (!pkt->port && fopts_length) {
            DEBUG("gnrc_lorawan: packet with fopts and port == 0. Drop\n");
            return -1;
        }

        if (pkt->port > LORAMAC_PORT_MAX) {
            DEBUG("gnrc_lorawan: packet with port > 223. Drop\n");
            return -1;
        }

        if (buf < p_mic) {
            pkt->enc_payload.iol_base = buf;
            pkt->enc_payload.iol_len = p_mic - buf;
        }
    }

    pkt->ack_req = lorawan_hdr_get_mtype(_hdr) == MTYPE_CNF_DOWNLINK;
    pkt->ack = lorawan_hdr_get_ack(_hdr);
    pkt->frame_pending = lorawan_hdr_get_frame_pending(_hdr);

    return 0;
}

void gnrc_lorawan_mcps_process_downlink(gnrc_lorawan_t *mac, uint8_t *psdu,
                                        size_t size)
{
    struct parsed_packet _pkt;

    /* NOTE: MIC is in pkt */
    if (!gnrc_lorawan_mic_is_valid(psdu, size, mac->nwkskey)) {
        DEBUG("gnrc_lorawan: invalid MIC\n");
        gnrc_lorawan_event_no_rx(mac);
        return;
    }

    if (gnrc_lorawan_parse_dl(mac, psdu, size, &_pkt) < 0) {
{'fraction_non_alphanumeric': 0.11827203736135435, 'fraction_numerical': 0.01727962638645651, 'mean_word_length': 2.5826014219991635, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 64, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1211366', 'n_tokens_mistral': 3452, 'n_tokens_neox': 3311, 'n_words': 691}