diff --git a/include/zephyr/net/ppp.h b/include/zephyr/net/ppp.h index a2f58825c358..82e026483806 100644 --- a/include/zephyr/net/ppp.h +++ b/include/zephyr/net/ppp.h @@ -353,7 +353,11 @@ struct ppp_my_option_data { uint32_t flags; }; +#if defined(CONFIG_NET_L2_PPP_OPTION_DNS_USE) #define IPCP_NUM_MY_OPTIONS 3 +#else +#define IPCP_NUM_MY_OPTIONS 1 +#endif #define IPV6CP_NUM_MY_OPTIONS 1 enum ppp_flags { diff --git a/subsys/net/l2/ppp/ipcp.c b/subsys/net/l2/ppp/ipcp.c index 35b7bac018bc..320b78a0c0c3 100644 --- a/subsys/net/l2/ppp/ipcp.c +++ b/subsys/net/l2/ppp/ipcp.c @@ -42,16 +42,6 @@ static int ipcp_add_ip_address(struct ppp_context *ctx, struct net_pkt *pkt) return ipcp_add_address(ctx, pkt, &ctx->ipcp.my_options.address); } -static int ipcp_add_dns1(struct ppp_context *ctx, struct net_pkt *pkt) -{ - return ipcp_add_address(ctx, pkt, &ctx->ipcp.my_options.dns1_address); -} - -static int ipcp_add_dns2(struct ppp_context *ctx, struct net_pkt *pkt) -{ - return ipcp_add_address(ctx, pkt, &ctx->ipcp.my_options.dns2_address); -} - static int ipcp_ack_check_address(struct net_pkt *pkt, size_t oplen, struct in_addr *addr) { @@ -81,20 +71,6 @@ static int ipcp_ack_ip_address(struct ppp_context *ctx, struct net_pkt *pkt, &ctx->ipcp.my_options.address); } -static int ipcp_ack_dns1(struct ppp_context *ctx, struct net_pkt *pkt, - uint8_t oplen) -{ - return ipcp_ack_check_address(pkt, oplen, - &ctx->ipcp.my_options.dns1_address); -} - -static int ipcp_ack_dns2(struct ppp_context *ctx, struct net_pkt *pkt, - uint8_t oplen) -{ - return ipcp_ack_check_address(pkt, oplen, - &ctx->ipcp.my_options.dns2_address); -} - static int ipcp_nak_override_address(struct net_pkt *pkt, size_t oplen, struct in_addr *addr) { @@ -112,6 +88,31 @@ static int ipcp_nak_ip_address(struct ppp_context *ctx, struct net_pkt *pkt, &ctx->ipcp.my_options.address); } +#if defined(CONFIG_NET_L2_PPP_OPTION_DNS_USE) +static int ipcp_add_dns1(struct ppp_context *ctx, struct net_pkt *pkt) +{ + return ipcp_add_address(ctx, pkt, &ctx->ipcp.my_options.dns1_address); +} + +static int ipcp_add_dns2(struct ppp_context *ctx, struct net_pkt *pkt) +{ + return ipcp_add_address(ctx, pkt, &ctx->ipcp.my_options.dns2_address); +} + +static int ipcp_ack_dns1(struct ppp_context *ctx, struct net_pkt *pkt, + uint8_t oplen) +{ + return ipcp_ack_check_address(pkt, oplen, + &ctx->ipcp.my_options.dns1_address); +} + +static int ipcp_ack_dns2(struct ppp_context *ctx, struct net_pkt *pkt, + uint8_t oplen) +{ + return ipcp_ack_check_address(pkt, oplen, + &ctx->ipcp.my_options.dns2_address); +} + static int ipcp_nak_dns1(struct ppp_context *ctx, struct net_pkt *pkt, uint8_t oplen) { @@ -125,21 +126,24 @@ static int ipcp_nak_dns2(struct ppp_context *ctx, struct net_pkt *pkt, return ipcp_nak_override_address(pkt, oplen, &ctx->ipcp.my_options.dns2_address); } +#endif /* CONFIG_NET_L2_PPP_OPTION_DNS_USE */ static const struct ppp_my_option_info ipcp_my_options[] = { PPP_MY_OPTION(IPCP_OPTION_IP_ADDRESS, ipcp_add_ip_address, ipcp_ack_ip_address, ipcp_nak_ip_address), +#if defined(CONFIG_NET_L2_PPP_OPTION_DNS_USE) PPP_MY_OPTION(IPCP_OPTION_DNS1, ipcp_add_dns1, ipcp_ack_dns1, ipcp_nak_dns1), PPP_MY_OPTION(IPCP_OPTION_DNS2, ipcp_add_dns2, ipcp_ack_dns2, ipcp_nak_dns2), +#endif }; BUILD_ASSERT(ARRAY_SIZE(ipcp_my_options) == IPCP_NUM_MY_OPTIONS); static struct net_pkt *ipcp_config_info_add(struct ppp_fsm *fsm) { - return ppp_my_options_add(fsm, 3 * IP_ADDRESS_OPTION_LEN); + return ppp_my_options_add(fsm, IPCP_NUM_MY_OPTIONS * IP_ADDRESS_OPTION_LEN); } struct ipcp_peer_option_data { @@ -224,6 +228,37 @@ static int ipcp_server_nak_ip_address(struct ppp_fsm *fsm, #endif #if defined(CONFIG_NET_L2_PPP_OPTION_SERVE_DNS) + +static int ipcp_dns1_address_parse(struct ppp_fsm *fsm, struct net_pkt *pkt, + void *user_data) +{ + struct ppp_context *ctx = + CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm); + int ret; + + ret = ipcp_dns_address_parse(fsm, pkt, user_data); + + if (ret == -EINVAL && ctx->ipcp.peer_options.dns1_address.s_addr == INADDR_ANY) { + return -ENOTSUP; + } + return ret; +} + +static int ipcp_dns2_address_parse(struct ppp_fsm *fsm, struct net_pkt *pkt, + void *user_data) +{ + struct ppp_context *ctx = + CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm); + int ret; + + ret = ipcp_dns_address_parse(fsm, pkt, user_data); + + if (ret == -EINVAL && ctx->ipcp.peer_options.dns2_address.s_addr == INADDR_ANY) { + return -ENOTSUP; + } + return ret; +} + static int ipcp_server_nak_dns1_address(struct ppp_fsm *fsm, struct net_pkt *ret_pkt, void *user_data) @@ -232,7 +267,7 @@ static int ipcp_server_nak_dns1_address(struct ppp_fsm *fsm, CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm); (void)net_pkt_write_u8(ret_pkt, IPCP_OPTION_DNS1); - ipcp_add_dns1(ctx, ret_pkt); + (void)ipcp_add_address(ctx, ret_pkt, &ctx->ipcp.peer_options.dns1_address); return 0; } @@ -245,7 +280,7 @@ static int ipcp_server_nak_dns2_address(struct ppp_fsm *fsm, CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm); (void)net_pkt_write_u8(ret_pkt, IPCP_OPTION_DNS2); - ipcp_add_dns2(ctx, ret_pkt); + (void)ipcp_add_address(ctx, ret_pkt, &ctx->ipcp.peer_options.dns2_address); return 0; } @@ -259,9 +294,9 @@ static const struct ppp_peer_option_info ipcp_peer_options[] = { PPP_PEER_OPTION(IPCP_OPTION_IP_ADDRESS, ipcp_ip_address_parse, NULL), #endif #if defined(CONFIG_NET_L2_PPP_OPTION_SERVE_DNS) - PPP_PEER_OPTION(IPCP_OPTION_DNS1, ipcp_dns_address_parse, + PPP_PEER_OPTION(IPCP_OPTION_DNS1, ipcp_dns1_address_parse, ipcp_server_nak_dns1_address), - PPP_PEER_OPTION(IPCP_OPTION_DNS2, ipcp_dns_address_parse, + PPP_PEER_OPTION(IPCP_OPTION_DNS2, ipcp_dns2_address_parse, ipcp_server_nak_dns2_address), #endif }; diff --git a/subsys/net/l2/ppp/options.c b/subsys/net/l2/ppp/options.c index 6fd8c15de6e0..694d338c9b76 100644 --- a/subsys/net/l2/ppp/options.c +++ b/subsys/net/l2/ppp/options.c @@ -144,14 +144,38 @@ static int ppp_parse_option_conf_req_supported(struct net_pkt *pkt, { struct ppp_parse_option_conf_req_data *parse_data = user_data; struct ppp_fsm *fsm = parse_data->fsm; + struct net_pkt *ret_pkt = parse_data->ret_pkt; + struct net_pkt_cursor cursor; const struct ppp_peer_option_info *option_info = ppp_peer_option_info_get(parse_data->options_info, parse_data->num_options_info, code); int ret; + net_pkt_cursor_backup(pkt, &cursor); ret = option_info->parse(fsm, pkt, parse_data->user_data); - if (ret == -EINVAL) { + if (ret == -ENOTSUP) { + net_pkt_cursor_restore(pkt, &cursor); + parse_data->rej_count++; + if (parse_data->nack_count != 0) { + /* Remove any NACKed data, if we need to reject something first */ + net_pkt_update_length(ret_pkt, 0); + net_pkt_cursor_init(ret_pkt); + parse_data->nack_count = 0; + } + net_pkt_write_u8(ret_pkt, code); + net_pkt_write_u8(ret_pkt, len + sizeof(code) + sizeof(len)); + if (len > 0) { + net_pkt_copy(ret_pkt, pkt, len); + } + return 0; + } else if (ret == -EINVAL) { + if (parse_data->rej_count != 0) { + /* If we have already rejected some options, we + * cannot NACK anything in the same packet. + */ + return 0; + } parse_data->nack_count++; ret = option_info->nack(fsm, parse_data->ret_pkt, parse_data->user_data); @@ -202,6 +226,10 @@ int ppp_config_info_req(struct ppp_fsm *fsm, return -EINVAL; } + if (parse_data.rej_count) { + return PPP_CONFIGURE_REJ; + } + if (parse_data.nack_count) { return PPP_CONFIGURE_NACK; }