From 091f630014aac2ebfd11a4f9d4110124c5cfe1dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Weinholt?= Date: Mon, 17 Feb 2020 14:40:32 +0100 Subject: [PATCH] net: ppp: ipcp: negotiate DNS servers and optionally use them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now negotiate DNS servers in the IPCP configuration. This has been observed to speed up the connection setup. The received DNS servers are used by the DNS resolver library, but we leave it optional since the static server list might be preferable. Increase MAX_IPCP_OPTIONS to 4 so that we can nack all RFC 1877 options. Signed-off-by: Göran Weinholt --- include/net/ppp.h | 16 ++++ subsys/net/l2/ppp/Kconfig | 6 ++ subsys/net/l2/ppp/ipcp.c | 134 +++++++++++++++++++++++++------ subsys/net/l2/ppp/misc.c | 8 ++ subsys/net/l2/ppp/ppp_internal.h | 2 +- 5 files changed, 139 insertions(+), 27 deletions(-) diff --git a/include/net/ppp.h b/include/net/ppp.h index aebb8dd7561..c5f307a4b66 100644 --- a/include/net/ppp.h +++ b/include/net/ppp.h @@ -175,6 +175,20 @@ enum ipcp_option_type { /** IP Address */ IPCP_OPTION_IP_ADDRESS = 3, + + /* RFC 1877 */ + + /** Primary DNS Server Address */ + IPCP_OPTION_DNS1 = 129, + + /** Primary NBNS Server Address */ + IPCP_OPTION_NBNS1 = 130, + + /** Secondary DNS Server Address */ + IPCP_OPTION_DNS2 = 131, + + /** Secondary NBNS Server Address */ + IPCP_OPTION_NBNS2 = 132, } __packed; /** @@ -358,6 +372,8 @@ struct lcp_options { struct ipcp_options { /** IPv4 address */ struct in_addr address; + struct in_addr dns1_address; + struct in_addr dns2_address; }; struct ipv6cp_options { diff --git a/subsys/net/l2/ppp/Kconfig b/subsys/net/l2/ppp/Kconfig index 31c8870b25d..663115ffd42 100644 --- a/subsys/net/l2/ppp/Kconfig +++ b/subsys/net/l2/ppp/Kconfig @@ -61,6 +61,12 @@ config NET_L2_PPP_OPTION_MRU_NEG help Try to negotiate with peer for MRU (MTU) for the link. +config NET_L2_PPP_OPTION_DNS_USE + bool "Use negotiated DNS servers" + depends on DNS_RESOLVER + help + Use the DNS servers negotiated in the IPCP configuration. + module = NET_L2_PPP module-dep = NET_LOG module-str = Log level for ppp L2 layer diff --git a/subsys/net/l2/ppp/ipcp.c b/subsys/net/l2/ppp/ipcp.c index 152732a2cbe..2998efcb0a6 100644 --- a/subsys/net/l2/ppp/ipcp.c +++ b/subsys/net/l2/ppp/ipcp.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 Intel Corporation. + * Copyright (c) 2020 Endian Technologies AB * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,6 +12,7 @@ LOG_MODULE_DECLARE(net_l2_ppp, CONFIG_NET_L2_PPP_LOG_LEVEL); #include #include +#include #include "net_private.h" @@ -37,7 +39,9 @@ static bool append_to_buf(struct net_buf *buf, u8_t *data, u8_t data_len) return true; } -/* Length is (6): code + id + IPv4 address length */ +/* Length is (6): code + id + IPv4 address length. RFC 1332 and also + * DNS in RFC 1877. + */ #define IP_ADDRESS_OPTION_LEN (1 + 1 + 4) static struct net_buf *ipcp_config_info_add(struct ppp_fsm *fsm) @@ -45,24 +49,37 @@ static struct net_buf *ipcp_config_info_add(struct ppp_fsm *fsm) struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm); - /* Currently we support only one option (IP address) */ - u8_t option[IP_ADDRESS_OPTION_LEN]; + /* Currently we support IP address and DNS servers */ + u8_t options[3 * IP_ADDRESS_OPTION_LEN]; const struct in_addr *my_addr; struct net_buf *buf; bool added; my_addr = &ctx->ipcp.my_options.address; + u8_t *option = options; option[0] = IPCP_OPTION_IP_ADDRESS; option[1] = IP_ADDRESS_OPTION_LEN; memcpy(&option[2], &my_addr->s_addr, sizeof(my_addr->s_addr)); + option += IP_ADDRESS_OPTION_LEN; + + my_addr = &ctx->ipcp.my_options.dns1_address; + option[0] = IPCP_OPTION_DNS1; + option[1] = IP_ADDRESS_OPTION_LEN; + memcpy(&option[2], &my_addr->s_addr, sizeof(my_addr->s_addr)); + + option += IP_ADDRESS_OPTION_LEN; + my_addr = &ctx->ipcp.my_options.dns2_address; + option[0] = IPCP_OPTION_DNS2; + option[1] = IP_ADDRESS_OPTION_LEN; + memcpy(&option[2], &my_addr->s_addr, sizeof(my_addr->s_addr)); buf = ppp_get_net_buf(NULL, 0); if (!buf) { goto out_of_mem; } - added = append_to_buf(buf, option, sizeof(option)); + added = append_to_buf(buf, options, sizeof(options)); if (!added) { goto out_of_mem; } @@ -184,7 +201,8 @@ static int ipcp_config_info_req(struct ppp_fsm *fsm, if (address_option_idx < 0) { /* The address option was not present, but we - * can continue without it. */ + * can continue without it. + */ NET_DBG("[%s/%p] No %saddress provided", fsm->name, fsm, "peer "); return PPP_CONFIGURE_ACK; @@ -264,6 +282,56 @@ bail_out: return -ENOMEM; } +static void ipcp_set_dns_servers(struct ppp_fsm *fsm) +{ +#if defined(CONFIG_NET_L2_PPP_OPTION_DNS_USE) + struct ppp_context *ctx = CONTAINER_OF(fsm, struct ppp_context, + ipcp.fsm); + + struct dns_resolve_context *dnsctx; + struct sockaddr_in dns1 = { + .sin_family = AF_INET, + .sin_port = htons(53), + .sin_addr = ctx->ipcp.my_options.dns1_address + }; + struct sockaddr_in dns2 = { + .sin_family = AF_INET, + .sin_port = htons(53), + .sin_addr = ctx->ipcp.my_options.dns2_address + }; + const struct sockaddr *dns_servers[] = { + (struct sockaddr *) &dns1, + (struct sockaddr *) &dns2, + NULL + }; + int i, ret; + + if (!dns1.sin_addr.s_addr) { + return; + } + + if (!dns2.sin_addr.s_addr) { + dns_servers[1] = NULL; + } + + dnsctx = dns_resolve_get_default(); + for (i = 0; i < CONFIG_DNS_NUM_CONCUR_QUERIES; i++) { + if (!dnsctx->queries[i].cb) { + continue; + } + + dns_resolve_cancel(dnsctx, dnsctx->queries[i].id); + } + dns_resolve_close(dnsctx); + + ret = dns_resolve_init(dnsctx, NULL, dns_servers); + if (ret < 0) { + NET_ERR("Could not set DNS servers"); + return; + } +#endif +} + static int ipcp_config_info_nack(struct ppp_fsm *fsm, struct net_pkt *pkt, u16_t length, @@ -274,7 +342,7 @@ static int ipcp_config_info_nack(struct ppp_fsm *fsm, struct ppp_option_pkt nack_options[MAX_IPCP_OPTIONS]; enum net_verdict verdict; int i, ret, address_option_idx = -1; - struct in_addr addr; + struct in_addr addr, *dst_addr; memset(nack_options, 0, sizeof(nack_options)); @@ -304,39 +372,53 @@ static int ipcp_config_info_nack(struct ppp_fsm *fsm, case IPCP_OPTION_IP_COMP_PROTO: continue; + case IPCP_OPTION_DNS1: + dst_addr = &ctx->ipcp.my_options.dns1_address; + break; + + case IPCP_OPTION_DNS2: + dst_addr = &ctx->ipcp.my_options.dns2_address; + break; + case IPCP_OPTION_IP_ADDRESS: + dst_addr = &ctx->ipcp.my_options.address; address_option_idx = i; break; default: continue; } + + net_pkt_cursor_restore(pkt, &nack_options[i].value); + + ret = net_pkt_read(pkt, (u32_t *)&addr, sizeof(addr)); + if (ret < 0) { + /* Should not happen, is the pkt corrupt? */ + return -EMSGSIZE; + } + + memcpy(dst_addr, &addr, sizeof(addr)); + + if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) { + char dst[INET_ADDRSTRLEN]; + char *addr_str; + + addr_str = net_addr_ntop(AF_INET, &addr, dst, + sizeof(dst)); + + NET_DBG("[%s/%p] Received %s address %s", + fsm->name, fsm, + ppp_option2str(PPP_IPCP, + nack_options[i].type.ipcp), + log_strdup(addr_str)); + } } if (address_option_idx < 0) { return -EINVAL; } - net_pkt_cursor_restore(pkt, &nack_options[address_option_idx].value); - - ret = net_pkt_read(pkt, (u32_t *)&addr, sizeof(addr)); - if (ret < 0) { - /* Should not happen, is the pkt corrupt? */ - return -EMSGSIZE; - } - - memcpy(&ctx->ipcp.my_options.address, &addr, sizeof(addr)); - - if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) { - char dst[INET_ADDRSTRLEN]; - char *addr_str; - - addr_str = net_addr_ntop(AF_INET, &addr, dst, - sizeof(dst)); - - NET_DBG("[%s/%p] Received %saddress %s", - fsm->name, fsm, "", log_strdup(addr_str)); - } + ipcp_set_dns_servers(fsm); return 0; } diff --git a/subsys/net/l2/ppp/misc.c b/subsys/net/l2/ppp/misc.c index 7a27610f4a0..abcf36d1b90 100644 --- a/subsys/net/l2/ppp/misc.c +++ b/subsys/net/l2/ppp/misc.c @@ -317,6 +317,14 @@ const char *ppp_option2str(enum ppp_protocol_type protocol, return "IP_COMPRESSION_PROTOCOL"; case IPCP_OPTION_IP_ADDRESS: return "IP_ADDRESS"; + case IPCP_OPTION_DNS1: + return "DNS1"; + case IPCP_OPTION_NBNS1: + return "NBNS1"; + case IPCP_OPTION_DNS2: + return "DNS2"; + case IPCP_OPTION_NBNS2: + return "NBNS2"; } break; diff --git a/subsys/net/l2/ppp/ppp_internal.h b/subsys/net/l2/ppp/ppp_internal.h index 882624369f4..6a3780ed656 100644 --- a/subsys/net/l2/ppp/ppp_internal.h +++ b/subsys/net/l2/ppp/ppp_internal.h @@ -39,7 +39,7 @@ struct ppp_packet { #define MAX_LCP_OPTIONS CONFIG_NET_L2_PPP_MAX_OPTIONS /** Max number of IPCP options */ -#define MAX_IPCP_OPTIONS 3 +#define MAX_IPCP_OPTIONS 4 /** Max number of IPV6CP options */ #define MAX_IPV6CP_OPTIONS 1