net: ppp: dialup enablers
Introducing PPP dialup features to enable e.g. usage of nrf9160 based board as a dialup modem for transferring ip data over PPP (e.g. windows dial up), i.e. usage of Zephyr PPP as a server for providing MTU/MRU, IP address and DNS addresses for a PC: - PPP LCP MRU option (configurable) - PPP server: IPCP ip and dns address peer options to enable providing IP and DNS addresses for PPP peer. Signed-off-by: Jani Hirsimäki <jani.hirsimaki@nordicsemi.no>
This commit is contained in:
parent
e3f8757b70
commit
5d76e8aca8
6 changed files with 231 additions and 2 deletions
|
@ -23,6 +23,12 @@ config NET_PPP_DRV_NAME
|
|||
help
|
||||
This option sets the driver name
|
||||
|
||||
config NET_PPP_MTU_MRU
|
||||
int "PPP MTU and MRU"
|
||||
default 1500
|
||||
help
|
||||
This options sets MTU and MRU for PPP link.
|
||||
|
||||
config NET_PPP_UART_BUF_LEN
|
||||
int "Buffer length when reading from UART"
|
||||
default 8
|
||||
|
|
|
@ -576,6 +576,20 @@ static int ppp_send(const struct device *dev, struct net_pkt *pkt)
|
|||
protocol = htons(PPP_IP);
|
||||
} else if (net_pkt_family(pkt) == AF_INET6) {
|
||||
protocol = htons(PPP_IPV6);
|
||||
} else if (IS_ENABLED(CONFIG_NET_SOCKETS_PACKET) &&
|
||||
net_pkt_family(pkt) == AF_PACKET) {
|
||||
char type = (NET_IPV6_HDR(pkt)->vtc & 0xf0);
|
||||
|
||||
switch (type) {
|
||||
case 0x60:
|
||||
protocol = htons(PPP_IPV6);
|
||||
break;
|
||||
case 0x40:
|
||||
protocol = htons(PPP_IP);
|
||||
break;
|
||||
default:
|
||||
return -EPROTONOSUPPORT;
|
||||
}
|
||||
} else {
|
||||
return -EPROTONOSUPPORT;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
|||
*/
|
||||
|
||||
/** PPP maximum receive unit (MRU) */
|
||||
#define PPP_MRU 1500
|
||||
#define PPP_MRU CONFIG_NET_PPP_MTU_MRU
|
||||
|
||||
/** PPP maximum transfer unit (MTU) */
|
||||
#define PPP_MTU PPP_MRU
|
||||
|
@ -350,6 +350,10 @@ struct lcp_options {
|
|||
uint16_t auth_proto;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_L2_PPP_OPTION_MRU)
|
||||
#define LCP_NUM_MY_OPTIONS 1
|
||||
#endif
|
||||
|
||||
struct ipcp_options {
|
||||
/** IPv4 address */
|
||||
struct in_addr address;
|
||||
|
@ -400,6 +404,9 @@ struct ppp_context {
|
|||
|
||||
/** Magic-Number value */
|
||||
uint32_t magic;
|
||||
#if defined(CONFIG_NET_L2_PPP_OPTION_MRU)
|
||||
struct ppp_my_option_data my_options_data[LCP_NUM_MY_OPTIONS];
|
||||
#endif
|
||||
} lcp;
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
|
|
|
@ -63,6 +63,21 @@ config NET_L2_PPP_PAP
|
|||
help
|
||||
Enable support for PAP authentication protocol.
|
||||
|
||||
config NET_L2_PPP_OPTION_MRU
|
||||
bool "LCP MRU option support"
|
||||
help
|
||||
Enable support for LCP MRU option.
|
||||
|
||||
config NET_L2_PPP_OPTION_SERVE_IP
|
||||
bool "Serve IP address to peer"
|
||||
help
|
||||
Enable support for serving IP address to PPP peer.
|
||||
|
||||
config NET_L2_PPP_OPTION_SERVE_DNS
|
||||
bool "Serve DNS addresses to peer"
|
||||
help
|
||||
Enable support for serving DNS addresses to PPP peer.
|
||||
|
||||
module = NET_L2_PPP
|
||||
module-dep = NET_LOG
|
||||
module-str = Log level for ppp L2 layer
|
||||
|
|
|
@ -147,6 +147,32 @@ struct ipcp_peer_option_data {
|
|||
struct in_addr addr;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_L2_PPP_OPTION_SERVE_DNS)
|
||||
static int ipcp_dns_address_parse(struct ppp_fsm *fsm, struct net_pkt *pkt,
|
||||
void *user_data)
|
||||
{
|
||||
struct ipcp_peer_option_data *data = user_data;
|
||||
int ret;
|
||||
|
||||
ret = net_pkt_read(pkt, &data->addr, sizeof(data->addr));
|
||||
if (ret < 0) {
|
||||
/* Should not happen, is the pkt corrupt? */
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
/* Request is zeros? Give our dns address in ConfNak */
|
||||
if (data->addr.s_addr == INADDR_ANY) {
|
||||
NET_DBG("[IPCP] zeroes rcvd as %s addr, sending NAK with our %s addr",
|
||||
"DNS", "DNS");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data->addr_present = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ipcp_ip_address_parse(struct ppp_fsm *fsm, struct net_pkt *pkt,
|
||||
void *user_data)
|
||||
{
|
||||
|
@ -159,6 +185,14 @@ static int ipcp_ip_address_parse(struct ppp_fsm *fsm, struct net_pkt *pkt,
|
|||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_L2_PPP_OPTION_SERVE_IP)
|
||||
/* Request is zeros? Give our IP address in ConfNak */
|
||||
if (data->addr.s_addr == INADDR_ANY) {
|
||||
NET_DBG("[IPCP] zeroes rcvd as %s addr, sending NAK with our %s addr",
|
||||
"IP", "IP");
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
if (CONFIG_NET_L2_PPP_LOG_LEVEL >= LOG_LEVEL_DBG) {
|
||||
char dst[INET_ADDRSTRLEN];
|
||||
char *addr_str;
|
||||
|
@ -175,8 +209,61 @@ static int ipcp_ip_address_parse(struct ppp_fsm *fsm, struct net_pkt *pkt,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_L2_PPP_OPTION_SERVE_IP)
|
||||
static int ipcp_server_nak_ip_address(struct ppp_fsm *fsm,
|
||||
struct net_pkt *ret_pkt, void *user_data)
|
||||
{
|
||||
struct ppp_context *ctx =
|
||||
CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm);
|
||||
|
||||
(void)net_pkt_write_u8(ret_pkt, IPCP_OPTION_IP_ADDRESS);
|
||||
ipcp_add_ip_address(ctx, ret_pkt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_L2_PPP_OPTION_SERVE_DNS)
|
||||
static int ipcp_server_nak_dns1_address(struct ppp_fsm *fsm,
|
||||
struct net_pkt *ret_pkt,
|
||||
void *user_data)
|
||||
{
|
||||
struct ppp_context *ctx =
|
||||
CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm);
|
||||
|
||||
(void)net_pkt_write_u8(ret_pkt, IPCP_OPTION_DNS1);
|
||||
ipcp_add_dns1(ctx, ret_pkt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipcp_server_nak_dns2_address(struct ppp_fsm *fsm,
|
||||
struct net_pkt *ret_pkt,
|
||||
void *user_data)
|
||||
{
|
||||
struct ppp_context *ctx =
|
||||
CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm);
|
||||
|
||||
(void)net_pkt_write_u8(ret_pkt, IPCP_OPTION_DNS2);
|
||||
ipcp_add_dns2(ctx, ret_pkt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct ppp_peer_option_info ipcp_peer_options[] = {
|
||||
#if defined(CONFIG_NET_L2_PPP_OPTION_SERVE_IP)
|
||||
PPP_PEER_OPTION(IPCP_OPTION_IP_ADDRESS, ipcp_ip_address_parse,
|
||||
ipcp_server_nak_ip_address),
|
||||
#else
|
||||
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,
|
||||
ipcp_server_nak_dns1_address),
|
||||
PPP_PEER_OPTION(IPCP_OPTION_DNS2, ipcp_dns_address_parse,
|
||||
ipcp_server_nak_dns2_address),
|
||||
#endif
|
||||
};
|
||||
|
||||
static int ipcp_config_info_req(struct ppp_fsm *fsm,
|
||||
|
@ -354,7 +441,6 @@ static void ipcp_down(struct ppp_fsm *fsm)
|
|||
(void)net_if_ipv4_addr_rm(
|
||||
ctx->iface, &ctx->ipcp.my_options.address);
|
||||
}
|
||||
|
||||
memset(&ctx->ipcp.my_options.address, 0,
|
||||
sizeof(ctx->ipcp.my_options.address));
|
||||
memset(&ctx->ipcp.my_options.dns1_address, 0,
|
||||
|
|
|
@ -203,6 +203,95 @@ static void lcp_finished(struct ppp_fsm *fsm)
|
|||
ppp_link_terminated(ctx);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_L2_PPP_OPTION_MRU)
|
||||
|
||||
#define MRU_OPTION_LEN 4
|
||||
|
||||
static int lcp_add_mru(struct ppp_context *ctx, struct net_pkt *pkt)
|
||||
{
|
||||
net_pkt_write_u8(pkt, MRU_OPTION_LEN);
|
||||
return net_pkt_write_be16(pkt, ctx->lcp.my_options.mru);
|
||||
}
|
||||
|
||||
static int lcp_ack_mru(struct ppp_context *ctx, struct net_pkt *pkt,
|
||||
uint8_t oplen)
|
||||
{
|
||||
int ret;
|
||||
uint16_t mru;
|
||||
|
||||
/* Handle ACK : */
|
||||
if (oplen != sizeof(mru)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = net_pkt_read(pkt, &mru, sizeof(mru));
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
if (mru != ctx->lcp.my_options.mru) {
|
||||
/* Didn't acked our MRU: */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcp_nak_mru(struct ppp_context *ctx, struct net_pkt *pkt,
|
||||
uint8_t oplen)
|
||||
{
|
||||
int ret;
|
||||
uint16_t mru;
|
||||
|
||||
/* Handle NAK: accept only smaller/equal than ours */
|
||||
if (oplen != sizeof(mru)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = net_pkt_read(pkt, &mru, sizeof(mru));
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mru <= ctx->lcp.my_options.mru) {
|
||||
/* OK, reset the MRU also in our side: */
|
||||
ctx->lcp.my_options.mru = mru;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ppp_my_option_info lcp_my_options[] = {
|
||||
PPP_MY_OPTION(LCP_OPTION_MRU, lcp_add_mru, lcp_ack_mru, lcp_nak_mru),
|
||||
};
|
||||
BUILD_ASSERT(ARRAY_SIZE(lcp_my_options) == LCP_NUM_MY_OPTIONS);
|
||||
|
||||
static struct net_pkt *lcp_config_info_add(struct ppp_fsm *fsm)
|
||||
{
|
||||
return ppp_my_options_add(fsm, MRU_OPTION_LEN);
|
||||
}
|
||||
|
||||
static int lcp_config_info_nack(struct ppp_fsm *fsm, struct net_pkt *pkt,
|
||||
uint16_t length, bool rejected)
|
||||
{
|
||||
struct ppp_context *ctx =
|
||||
CONTAINER_OF(fsm, struct ppp_context, lcp.fsm);
|
||||
int ret;
|
||||
|
||||
ret = ppp_my_options_parse_conf_nak(fsm, pkt, length);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!ctx->lcp.my_options.mru) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void lcp_init(struct ppp_context *ctx)
|
||||
{
|
||||
NET_DBG("proto %s (0x%04x) fsm %p", ppp_proto2str(PPP_LCP), PPP_LCP,
|
||||
|
@ -214,6 +303,18 @@ static void lcp_init(struct ppp_context *ctx)
|
|||
|
||||
ppp_fsm_name_set(&ctx->lcp.fsm, ppp_proto2str(PPP_LCP));
|
||||
|
||||
#if defined(CONFIG_NET_L2_PPP_OPTION_MRU)
|
||||
ctx->lcp.my_options.mru = PPP_MRU;
|
||||
ctx->lcp.fsm.my_options.info = lcp_my_options;
|
||||
ctx->lcp.fsm.my_options.data = ctx->lcp.my_options_data;
|
||||
ctx->lcp.fsm.my_options.count = ARRAY_SIZE(lcp_my_options);
|
||||
|
||||
ctx->lcp.fsm.cb.config_info_add = lcp_config_info_add;
|
||||
ctx->lcp.fsm.cb.config_info_req = lcp_config_info_req;
|
||||
ctx->lcp.fsm.cb.config_info_nack = lcp_config_info_nack;
|
||||
ctx->lcp.fsm.cb.config_info_rej = ppp_my_options_parse_conf_rej;
|
||||
#endif
|
||||
|
||||
ctx->lcp.fsm.cb.up = lcp_up;
|
||||
ctx->lcp.fsm.cb.down = lcp_down;
|
||||
ctx->lcp.fsm.cb.starting = lcp_starting;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue