blob: a2baa67c3d3907be2650453b84b85dc5e7417ae0 [file] [log] [blame]
/*
* Copyright (c) 2019 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <logging/log.h>
LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL);
#include <net/net_core.h>
#include <net/net_pkt.h>
#include <net/ppp.h>
#include "net_private.h"
#include "ppp_internal.h"
#define ALLOC_TIMEOUT K_MSEC(100)
enum net_verdict ppp_parse_options(struct ppp_fsm *fsm,
struct net_pkt *pkt,
u16_t length,
struct ppp_option_pkt options[],
int options_len)
{
int remaining = length, pkt_remaining;
enum net_verdict verdict;
u8_t opt_type, opt_len;
int ret, idx = 0;
pkt_remaining = net_pkt_remaining_data(pkt);
if (remaining != pkt_remaining) {
NET_DBG("Expecting %d but pkt data length is %d bytes",
remaining, pkt_remaining);
verdict = NET_DROP;
goto out;
}
while (remaining > 0) {
ret = net_pkt_read_u8(pkt, &opt_type);
if (ret < 0) {
NET_DBG("Cannot read %s (%d) (remaining len %d)",
"opt_type", ret, pkt_remaining);
verdict = NET_DROP;
goto out;
}
ret = net_pkt_read_u8(pkt, &opt_len);
if (ret < 0) {
NET_DBG("Cannot read %s (%d) (remaining len %d)",
"opt_len", ret, remaining);
verdict = NET_DROP;
goto out;
}
if (idx >= options_len) {
NET_DBG("Cannot insert options (max %d)", options_len);
verdict = NET_DROP;
goto out;
}
options[idx].type.lcp = opt_type;
options[idx].len = opt_len;
NET_DBG("[%s/%p] %s option %s (%d) len %d", fsm->name, fsm,
"Recv", ppp_option2str(fsm->protocol, opt_type),
opt_type, opt_len);
if (opt_len > 2) {
/* There is an option value here */
net_pkt_cursor_backup(pkt, &options[idx].value);
}
net_pkt_skip(pkt,
opt_len - sizeof(opt_type) - sizeof(opt_len));
remaining -= opt_len;
idx++;
};
if (remaining < 0) {
verdict = NET_DROP;
goto out;
}
verdict = NET_OK;
out:
return verdict;
}
struct net_buf *ppp_get_net_buf(struct net_buf *root_buf, u8_t len)
{
struct net_buf *tmp;
if (root_buf) {
tmp = net_buf_frag_last(root_buf);
if (len > net_buf_tailroom(tmp)) {
tmp = net_pkt_get_reserve_tx_data(ALLOC_TIMEOUT);
if (tmp) {
net_buf_frag_add(root_buf, tmp);
}
}
return tmp;
}
tmp = net_pkt_get_reserve_tx_data(ALLOC_TIMEOUT);
if (tmp) {
return tmp;
}
return NULL;
}