Skip to content

Commit d5f4ca3

Browse files
SeppoTakalonashif
authored andcommitted
net: ppp: Allow peer-options to be rejected
There are cases, for example when peer is requesting two DNS addresses, but we can only give one, we should reject the secondary DNS request first, before sending NAK to acceptable options. Option parser can reject a parameter by returning -ENOTSUP and when it wants to NAK the parameter, it returns -EINVAL. On RFC 1661: Configure-Reject If some Configuration Options received in a Configure-Request are not recognizable or are not acceptable for negotiation (as configured by a network administrator), then the implementation MUST transmit a Configure-Reject. Configure-Nak If every instance of the received Configuration Options is recognizable, but some values are not acceptable, then the implementation MUST transmit a Configure-Nak. So as stated by RFC, we should start the negotiation by rejecting all parameters that we cannot configure. I added an example of rejecting DNS requests, if we don't have those. Signed-off-by: Seppo Takalo <seppo.takalo@nordicsemi.no>
1 parent 5a31f3d commit d5f4ca3

File tree

2 files changed

+62
-3
lines changed

2 files changed

+62
-3
lines changed

subsys/net/l2/ppp/ipcp.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,37 @@ static int ipcp_server_nak_ip_address(struct ppp_fsm *fsm,
228228
#endif
229229

230230
#if defined(CONFIG_NET_L2_PPP_OPTION_SERVE_DNS)
231+
232+
static int ipcp_dns1_address_parse(struct ppp_fsm *fsm, struct net_pkt *pkt,
233+
void *user_data)
234+
{
235+
struct ppp_context *ctx =
236+
CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm);
237+
int ret;
238+
239+
ret = ipcp_dns_address_parse(fsm, pkt, user_data);
240+
241+
if (ret == -EINVAL && ctx->ipcp.peer_options.dns1_address.s_addr == INADDR_ANY) {
242+
return -ENOTSUP;
243+
}
244+
return ret;
245+
}
246+
247+
static int ipcp_dns2_address_parse(struct ppp_fsm *fsm, struct net_pkt *pkt,
248+
void *user_data)
249+
{
250+
struct ppp_context *ctx =
251+
CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm);
252+
int ret;
253+
254+
ret = ipcp_dns_address_parse(fsm, pkt, user_data);
255+
256+
if (ret == -EINVAL && ctx->ipcp.peer_options.dns2_address.s_addr == INADDR_ANY) {
257+
return -ENOTSUP;
258+
}
259+
return ret;
260+
}
261+
231262
static int ipcp_server_nak_dns1_address(struct ppp_fsm *fsm,
232263
struct net_pkt *ret_pkt,
233264
void *user_data)
@@ -263,9 +294,9 @@ static const struct ppp_peer_option_info ipcp_peer_options[] = {
263294
PPP_PEER_OPTION(IPCP_OPTION_IP_ADDRESS, ipcp_ip_address_parse, NULL),
264295
#endif
265296
#if defined(CONFIG_NET_L2_PPP_OPTION_SERVE_DNS)
266-
PPP_PEER_OPTION(IPCP_OPTION_DNS1, ipcp_dns_address_parse,
297+
PPP_PEER_OPTION(IPCP_OPTION_DNS1, ipcp_dns1_address_parse,
267298
ipcp_server_nak_dns1_address),
268-
PPP_PEER_OPTION(IPCP_OPTION_DNS2, ipcp_dns_address_parse,
299+
PPP_PEER_OPTION(IPCP_OPTION_DNS2, ipcp_dns2_address_parse,
269300
ipcp_server_nak_dns2_address),
270301
#endif
271302
};

subsys/net/l2/ppp/options.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,38 @@ static int ppp_parse_option_conf_req_supported(struct net_pkt *pkt,
144144
{
145145
struct ppp_parse_option_conf_req_data *parse_data = user_data;
146146
struct ppp_fsm *fsm = parse_data->fsm;
147+
struct net_pkt *ret_pkt = parse_data->ret_pkt;
148+
struct net_pkt_cursor cursor;
147149
const struct ppp_peer_option_info *option_info =
148150
ppp_peer_option_info_get(parse_data->options_info,
149151
parse_data->num_options_info,
150152
code);
151153
int ret;
152154

155+
net_pkt_cursor_backup(pkt, &cursor);
153156
ret = option_info->parse(fsm, pkt, parse_data->user_data);
154-
if (ret == -EINVAL) {
157+
if (ret == -ENOTSUP) {
158+
net_pkt_cursor_restore(pkt, &cursor);
159+
parse_data->rej_count++;
160+
if (parse_data->nack_count != 0) {
161+
/* Remove any NACKed data, if we need to reject something first */
162+
net_pkt_update_length(ret_pkt, 0);
163+
net_pkt_cursor_init(ret_pkt);
164+
parse_data->nack_count = 0;
165+
}
166+
net_pkt_write_u8(ret_pkt, code);
167+
net_pkt_write_u8(ret_pkt, len + sizeof(code) + sizeof(len));
168+
if (len > 0) {
169+
net_pkt_copy(ret_pkt, pkt, len);
170+
}
171+
return 0;
172+
} else if (ret == -EINVAL) {
173+
if (parse_data->rej_count != 0) {
174+
/* If we have already rejected some options, we
175+
* cannot NACK anything in the same packet.
176+
*/
177+
return 0;
178+
}
155179
parse_data->nack_count++;
156180
ret = option_info->nack(fsm, parse_data->ret_pkt,
157181
parse_data->user_data);
@@ -202,6 +226,10 @@ int ppp_config_info_req(struct ppp_fsm *fsm,
202226
return -EINVAL;
203227
}
204228

229+
if (parse_data.rej_count) {
230+
return PPP_CONFIGURE_REJ;
231+
}
232+
205233
if (parse_data.nack_count) {
206234
return PPP_CONFIGURE_NACK;
207235
}

0 commit comments

Comments
 (0)