net: l2: ppp: use net_pkt API for replying to Configure-Req
Use net_pkt instead of net_buf API for replying to Configure-Req. We use the fact that for now we reply with either Configure-Ack or Configure-Rej only. In both cases we can allocate net_pkt ahead, because we know its maximum length (which is equal to length of received Configure-Req packet). Make also an improvement in generic FSM code and reply with Configure-Rej to all Configure-Req for which there is no config_info_req callback set. Use that to drop LCP specific Conf-Req handling code, because there is no option properly supported there yet. Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
This commit is contained in:
parent
b091181fa5
commit
50b2cafc42
@ -241,7 +241,7 @@ struct ppp_fsm {
|
||||
int (*config_info_req)(struct ppp_fsm *fsm,
|
||||
struct net_pkt *pkt,
|
||||
uint16_t length,
|
||||
struct net_buf **buf);
|
||||
struct net_pkt *ret_pkt);
|
||||
|
||||
/** Reject Configuration Information */
|
||||
int (*config_info_rej)(struct ppp_fsm *fsm,
|
||||
|
||||
@ -351,7 +351,7 @@ int ppp_send_pkt(struct ppp_fsm *fsm, struct net_if *iface,
|
||||
uint16_t protocol = 0;
|
||||
size_t len = 0;
|
||||
struct ppp_packet ppp;
|
||||
struct net_pkt *pkt;
|
||||
struct net_pkt *pkt = NULL;
|
||||
int ret;
|
||||
|
||||
if (!iface) {
|
||||
@ -390,6 +390,8 @@ int ppp_send_pkt(struct ppp_fsm *fsm, struct net_if *iface,
|
||||
case PPP_CONFIGURE_ACK:
|
||||
case PPP_CONFIGURE_NACK:
|
||||
case PPP_CONFIGURE_REJ:
|
||||
pkt = data;
|
||||
/* FALLTHROUGH */
|
||||
case PPP_CONFIGURE_REQ:
|
||||
/* 2 + 1 + 1 (configure-[req|ack|nack|rej]) +
|
||||
* data_len (options)
|
||||
@ -431,11 +433,25 @@ int ppp_send_pkt(struct ppp_fsm *fsm, struct net_if *iface,
|
||||
ppp.id = id;
|
||||
ppp.length = htons(len);
|
||||
|
||||
pkt = net_pkt_alloc_with_buffer(iface,
|
||||
sizeof(uint16_t) + len,
|
||||
AF_UNSPEC, 0, BUF_ALLOC_TIMEOUT);
|
||||
if (!pkt) {
|
||||
goto out_of_mem;
|
||||
pkt = net_pkt_alloc_with_buffer(iface,
|
||||
sizeof(uint16_t) + len,
|
||||
AF_UNSPEC, 0,
|
||||
BUF_ALLOC_TIMEOUT);
|
||||
if (!pkt) {
|
||||
goto out_of_mem;
|
||||
}
|
||||
} else {
|
||||
struct net_buf *buf;
|
||||
|
||||
buf = net_pkt_get_reserve_tx_data(BUF_ALLOC_TIMEOUT);
|
||||
if (!buf) {
|
||||
LOG_ERR("failed to allocate buffer");
|
||||
goto out_of_mem;
|
||||
}
|
||||
|
||||
net_pkt_frag_insert(pkt, buf);
|
||||
net_pkt_cursor_init(pkt);
|
||||
}
|
||||
|
||||
ret = net_pkt_write_be16(pkt, protocol);
|
||||
@ -483,8 +499,7 @@ int ppp_send_pkt(struct ppp_fsm *fsm, struct net_if *iface,
|
||||
}
|
||||
} else if (type == PPP_ECHO_REPLY) {
|
||||
net_pkt_copy(pkt, req_pkt, len);
|
||||
} else if (type == PPP_CONFIGURE_ACK || type == PPP_CONFIGURE_REQ ||
|
||||
type == PPP_CONFIGURE_REJ || type == PPP_CONFIGURE_NACK) {
|
||||
} else if (type == PPP_CONFIGURE_REQ) {
|
||||
/* add options */
|
||||
if (data) {
|
||||
net_buf_frag_add(pkt->buffer, data);
|
||||
@ -533,7 +548,7 @@ static enum net_verdict fsm_recv_configure_req(struct ppp_fsm *fsm,
|
||||
struct net_pkt *pkt,
|
||||
uint16_t remaining_len)
|
||||
{
|
||||
struct net_buf *buf = NULL;
|
||||
struct net_pkt *out = NULL;
|
||||
int len = 0;
|
||||
enum ppp_packet_type code;
|
||||
|
||||
@ -578,12 +593,23 @@ static enum net_verdict fsm_recv_configure_req(struct ppp_fsm *fsm,
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
out = net_pkt_alloc_with_buffer(net_pkt_iface(pkt),
|
||||
sizeof(uint16_t) + sizeof(uint16_t) +
|
||||
sizeof(uint8_t) + sizeof(uint8_t) +
|
||||
remaining_len,
|
||||
AF_UNSPEC, 0, BUF_ALLOC_TIMEOUT);
|
||||
if (!out) {
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
net_pkt_cursor_init(out);
|
||||
|
||||
if (fsm->cb.config_info_req) {
|
||||
int ret;
|
||||
|
||||
ret = fsm->cb.config_info_req(fsm, pkt, remaining_len, &buf);
|
||||
ret = fsm->cb.config_info_req(fsm, pkt, remaining_len, out);
|
||||
if (ret < 0) {
|
||||
return NET_DROP;
|
||||
goto unref_out_pkt;
|
||||
}
|
||||
|
||||
if (fsm->nack_loops >= MAX_NACK_LOOPS &&
|
||||
@ -592,13 +618,12 @@ static enum net_verdict fsm_recv_configure_req(struct ppp_fsm *fsm,
|
||||
}
|
||||
|
||||
code = ret;
|
||||
len = net_buf_frags_len(buf);
|
||||
|
||||
len = net_pkt_get_len(out);
|
||||
} else if (remaining_len) {
|
||||
/* If there are any options at this point, then reject.
|
||||
* TODO: construct the NACKed options buf
|
||||
*/
|
||||
code = PPP_CONFIGURE_REJ;
|
||||
|
||||
net_pkt_copy(out, pkt, remaining_len);
|
||||
len = remaining_len;
|
||||
} else {
|
||||
code = PPP_CONFIGURE_ACK;
|
||||
}
|
||||
@ -607,7 +632,7 @@ static enum net_verdict fsm_recv_configure_req(struct ppp_fsm *fsm,
|
||||
fsm->name, fsm, ppp_pkt_type2str(code), code, id,
|
||||
ppp_state_str(fsm->state), fsm->state);
|
||||
|
||||
(void)ppp_send_pkt(fsm, NULL, code, id, buf, len);
|
||||
(void)ppp_send_pkt(fsm, NULL, code, id, out, len);
|
||||
|
||||
if (code == PPP_CONFIGURE_ACK) {
|
||||
if (fsm->state == PPP_ACK_RECEIVED) {
|
||||
@ -634,6 +659,11 @@ static enum net_verdict fsm_recv_configure_req(struct ppp_fsm *fsm,
|
||||
}
|
||||
|
||||
return NET_OK;
|
||||
|
||||
unref_out_pkt:
|
||||
net_pkt_unref(out);
|
||||
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
static enum net_verdict fsm_recv_configure_ack(struct ppp_fsm *fsm, uint8_t id,
|
||||
|
||||
@ -100,10 +100,9 @@ out_of_mem:
|
||||
static int ipcp_config_info_req(struct ppp_fsm *fsm,
|
||||
struct net_pkt *pkt,
|
||||
uint16_t length,
|
||||
struct net_buf **ret_buf)
|
||||
struct net_pkt *ret_pkt)
|
||||
{
|
||||
int nack_idx = 0, address_option_idx = -1;
|
||||
struct net_buf *buf = NULL;
|
||||
struct ppp_option_pkt options[MAX_IPCP_OPTIONS];
|
||||
struct ppp_option_pkt nack_options[MAX_IPCP_OPTIONS];
|
||||
enum ppp_packet_type code;
|
||||
@ -152,43 +151,19 @@ static int ipcp_config_info_req(struct ppp_fsm *fsm,
|
||||
}
|
||||
|
||||
if (nack_idx > 0) {
|
||||
struct net_buf *nack_buf;
|
||||
|
||||
code = PPP_CONFIGURE_REJ;
|
||||
|
||||
/* Create net_buf containing options that are not accepted */
|
||||
/* Fill ret_pkt with options that are not accepted */
|
||||
for (i = 0; i < MIN(nack_idx, ARRAY_SIZE(nack_options)); i++) {
|
||||
bool added;
|
||||
|
||||
nack_buf = ppp_get_net_buf(buf, nack_options[i].len);
|
||||
if (!nack_buf) {
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
if (!buf) {
|
||||
buf = nack_buf;
|
||||
}
|
||||
|
||||
added = append_to_buf(nack_buf,
|
||||
&nack_options[i].type.ipcp, 1);
|
||||
if (!added) {
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
added = append_to_buf(nack_buf, &nack_options[i].len,
|
||||
1);
|
||||
if (!added) {
|
||||
goto bail_out;
|
||||
}
|
||||
net_pkt_write_u8(ret_pkt, nack_options[i].type.ipcp);
|
||||
net_pkt_write_u8(ret_pkt, nack_options[i].len);
|
||||
|
||||
/* If there is some data, copy it to result buf */
|
||||
if (nack_options[i].value.pos) {
|
||||
added = append_to_buf(nack_buf,
|
||||
nack_options[i].value.pos,
|
||||
nack_options[i].len - 1 - 1);
|
||||
if (!added) {
|
||||
goto bail_out;
|
||||
}
|
||||
net_pkt_cursor_restore(pkt,
|
||||
&nack_options[i].value);
|
||||
net_pkt_copy(ret_pkt, pkt,
|
||||
nack_options[i].len - 1 - 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -232,9 +207,6 @@ static int ipcp_config_info_req(struct ppp_fsm *fsm,
|
||||
}
|
||||
|
||||
if (addr.s_addr) {
|
||||
bool added;
|
||||
uint8_t val;
|
||||
|
||||
/* The address is the remote address, we then need
|
||||
* to figure out what our address should be.
|
||||
*
|
||||
@ -242,43 +214,15 @@ static int ipcp_config_info_req(struct ppp_fsm *fsm,
|
||||
* - check that the IP address can be accepted
|
||||
*/
|
||||
|
||||
buf = ppp_get_net_buf(NULL, IP_ADDRESS_OPTION_LEN);
|
||||
if (!buf) {
|
||||
goto bail_out;
|
||||
}
|
||||
net_pkt_write_u8(ret_pkt, IPCP_OPTION_IP_ADDRESS);
|
||||
net_pkt_write_u8(ret_pkt, IP_ADDRESS_OPTION_LEN);
|
||||
|
||||
val = IPCP_OPTION_IP_ADDRESS;
|
||||
added = append_to_buf(buf, &val, sizeof(val));
|
||||
if (!added) {
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
val = IP_ADDRESS_OPTION_LEN;
|
||||
added = append_to_buf(buf, &val, sizeof(val));
|
||||
if (!added) {
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
added = append_to_buf(buf, (uint8_t *)&addr.s_addr,
|
||||
sizeof(addr.s_addr));
|
||||
if (!added) {
|
||||
goto bail_out;
|
||||
}
|
||||
net_pkt_write(ret_pkt, &addr.s_addr,
|
||||
sizeof(addr.s_addr));
|
||||
}
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
*ret_buf = buf;
|
||||
}
|
||||
|
||||
return code;
|
||||
|
||||
bail_out:
|
||||
if (buf) {
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void ipcp_set_dns_servers(struct ppp_fsm *fsm)
|
||||
|
||||
@ -90,10 +90,9 @@ out_of_mem:
|
||||
static int ipv6cp_config_info_req(struct ppp_fsm *fsm,
|
||||
struct net_pkt *pkt,
|
||||
uint16_t length,
|
||||
struct net_buf **ret_buf)
|
||||
struct net_pkt *ret_pkt)
|
||||
{
|
||||
int nack_idx = 0, iface_id_option_idx = -1;
|
||||
struct net_buf *buf = NULL;
|
||||
struct ppp_option_pkt options[MAX_IPV6CP_OPTIONS];
|
||||
struct ppp_option_pkt nack_options[MAX_IPV6CP_OPTIONS];
|
||||
enum ppp_packet_type code;
|
||||
@ -143,52 +142,24 @@ static int ipv6cp_config_info_req(struct ppp_fsm *fsm,
|
||||
}
|
||||
|
||||
if (nack_idx > 0) {
|
||||
struct net_buf *nack_buf;
|
||||
code = PPP_CONFIGURE_REJ;
|
||||
|
||||
/* Once rejected count logic is in, it will be possible
|
||||
* to set this code to PPP_CONFIGURE_REJ. */
|
||||
code = PPP_CONFIGURE_NACK;
|
||||
|
||||
/* Create net_buf containing options that are not accepted */
|
||||
/* Fill ret_pkt with options that are not accepted */
|
||||
for (i = 0; i < MIN(nack_idx, ARRAY_SIZE(nack_options)); i++) {
|
||||
bool added;
|
||||
|
||||
nack_buf = ppp_get_net_buf(buf, nack_options[i].len);
|
||||
if (!nack_buf) {
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
if (!buf) {
|
||||
buf = nack_buf;
|
||||
}
|
||||
|
||||
added = append_to_buf(nack_buf,
|
||||
&nack_options[i].type.ipv6cp, 1);
|
||||
if (!added) {
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
added = append_to_buf(nack_buf, &nack_options[i].len,
|
||||
1);
|
||||
if (!added) {
|
||||
goto bail_out;
|
||||
}
|
||||
net_pkt_write_u8(ret_pkt, nack_options[i].type.ipv6cp);
|
||||
net_pkt_write_u8(ret_pkt, nack_options[i].len);
|
||||
|
||||
/* If there is some data, copy it to result buf */
|
||||
if (nack_options[i].value.pos) {
|
||||
added = append_to_buf(nack_buf,
|
||||
nack_options[i].value.pos,
|
||||
nack_options[i].len - 1 - 1);
|
||||
if (!added) {
|
||||
goto bail_out;
|
||||
}
|
||||
net_pkt_cursor_restore(pkt,
|
||||
&nack_options[i].value);
|
||||
net_pkt_copy(ret_pkt, pkt,
|
||||
nack_options[i].len - 1 - 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint8_t iface_id[PPP_INTERFACE_IDENTIFIER_LEN];
|
||||
struct ppp_context *ctx;
|
||||
bool added;
|
||||
uint8_t val;
|
||||
int ret;
|
||||
|
||||
ctx = CONTAINER_OF(fsm, struct ppp_context, ipv6cp.fsm);
|
||||
@ -224,41 +195,13 @@ static int ipv6cp_config_info_req(struct ppp_fsm *fsm,
|
||||
|
||||
/* TODO: check whether iid is empty and create one if so */
|
||||
|
||||
buf = ppp_get_net_buf(NULL, INTERFACE_IDENTIFIER_OPTION_LEN);
|
||||
if (!buf) {
|
||||
goto bail_out;
|
||||
}
|
||||
net_pkt_write_u8(ret_pkt, IPV6CP_OPTION_INTERFACE_IDENTIFIER);
|
||||
net_pkt_write_u8(ret_pkt, INTERFACE_IDENTIFIER_OPTION_LEN);
|
||||
|
||||
val = IPV6CP_OPTION_INTERFACE_IDENTIFIER;
|
||||
added = append_to_buf(buf, &val, sizeof(val));
|
||||
if (!added) {
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
val = INTERFACE_IDENTIFIER_OPTION_LEN;
|
||||
added = append_to_buf(buf, &val, sizeof(val));
|
||||
if (!added) {
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
added = append_to_buf(buf, iface_id, sizeof(iface_id));
|
||||
if (!added) {
|
||||
goto bail_out;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
*ret_buf = buf;
|
||||
net_pkt_write(ret_pkt, iface_id, sizeof(iface_id));
|
||||
}
|
||||
|
||||
return code;
|
||||
|
||||
bail_out:
|
||||
if (buf) {
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int ipv6cp_config_info_ack(struct ppp_fsm *fsm,
|
||||
|
||||
@ -57,127 +57,6 @@ static enum net_verdict lcp_handle(struct ppp_context *ctx,
|
||||
return ppp_fsm_input(&ctx->lcp.fsm, PPP_LCP, pkt);
|
||||
}
|
||||
|
||||
static bool append_to_buf(struct net_buf *buf, uint8_t *data, uint8_t data_len)
|
||||
{
|
||||
if (data_len > net_buf_tailroom(buf)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* FIXME: use net_pkt api so that we can handle a case where data
|
||||
* might split to two net_buf's
|
||||
*/
|
||||
net_buf_add_mem(buf, data, data_len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int lcp_config_info_req(struct ppp_fsm *fsm,
|
||||
struct net_pkt *pkt,
|
||||
uint16_t length,
|
||||
struct net_buf **buf)
|
||||
{
|
||||
struct ppp_option_pkt options[MAX_LCP_OPTIONS];
|
||||
struct ppp_option_pkt nack_options[MAX_LCP_OPTIONS];
|
||||
struct net_buf *nack = NULL;
|
||||
enum ppp_packet_type code;
|
||||
int i, nack_idx = 0;
|
||||
int ret;
|
||||
|
||||
memset(options, 0, sizeof(options));
|
||||
memset(nack_options, 0, sizeof(nack_options));
|
||||
|
||||
ret = ppp_parse_options(fsm, pkt, length, options, ARRAY_SIZE(options));
|
||||
if (ret < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(options); i++) {
|
||||
if (options[i].type.lcp != LCP_OPTION_RESERVED) {
|
||||
NET_DBG("[%s/%p] %s option %s (%d) len %d",
|
||||
fsm->name, fsm, "Check",
|
||||
ppp_option2str(PPP_LCP, options[i].type.lcp),
|
||||
options[i].type.lcp, options[i].len);
|
||||
}
|
||||
|
||||
switch (options[i].type.lcp) {
|
||||
case LCP_OPTION_RESERVED:
|
||||
continue;
|
||||
|
||||
default:
|
||||
nack_options[nack_idx].type.lcp = options[i].type.lcp;
|
||||
nack_options[nack_idx].len = options[i].len;
|
||||
|
||||
if (options[i].len > 2) {
|
||||
memcpy(&nack_options[nack_idx].value,
|
||||
&options[i].value,
|
||||
sizeof(nack_options[nack_idx].value));
|
||||
}
|
||||
|
||||
nack_idx++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nack_idx > 0) {
|
||||
struct net_buf *nack_buf;
|
||||
|
||||
code = PPP_CONFIGURE_REJ;
|
||||
|
||||
/* Create net_buf containing options that are not accepted */
|
||||
for (i = 0; i < MIN(nack_idx, ARRAY_SIZE(nack_options)); i++) {
|
||||
bool added;
|
||||
|
||||
nack_buf = ppp_get_net_buf(nack, nack_options[i].len);
|
||||
if (!nack_buf) {
|
||||
goto out_of_mem;
|
||||
}
|
||||
|
||||
if (!nack) {
|
||||
nack = nack_buf;
|
||||
}
|
||||
|
||||
added = append_to_buf(nack_buf,
|
||||
&nack_options[i].type.lcp, 1);
|
||||
if (!added) {
|
||||
goto out_of_mem;
|
||||
}
|
||||
|
||||
added = append_to_buf(nack_buf, &nack_options[i].len,
|
||||
1);
|
||||
if (!added) {
|
||||
goto out_of_mem;
|
||||
}
|
||||
|
||||
/* If there is some data, copy it to result buf */
|
||||
if (nack_options[i].value.pos) {
|
||||
added = append_to_buf(nack_buf,
|
||||
nack_options[i].value.pos,
|
||||
nack_options[i].len - 1 - 1);
|
||||
if (!added) {
|
||||
goto out_of_mem;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
out_of_mem:
|
||||
if (nack) {
|
||||
net_buf_unref(nack);
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
} else {
|
||||
code = PPP_CONFIGURE_ACK;
|
||||
}
|
||||
|
||||
if (nack) {
|
||||
*buf = nack;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static void lcp_lower_down(struct ppp_context *ctx)
|
||||
{
|
||||
ppp_fsm_lower_down(&ctx->lcp.fsm);
|
||||
@ -256,7 +135,6 @@ static void lcp_init(struct ppp_context *ctx)
|
||||
ctx->lcp.fsm.cb.starting = lcp_starting;
|
||||
ctx->lcp.fsm.cb.finished = lcp_finished;
|
||||
ctx->lcp.fsm.cb.proto_extension = lcp_handle_ext;
|
||||
ctx->lcp.fsm.cb.config_info_req = lcp_config_info_req;
|
||||
}
|
||||
|
||||
PPP_PROTOCOL_REGISTER(LCP, PPP_LCP,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user