From 11a025ade973d7d8b3353608a74dc0c16c156f89 Mon Sep 17 00:00:00 2001 From: Claudiu Mihail Date: Tue, 12 Jul 2011 14:06:50 +0000 Subject: [PATCH] [lwIP] - Upgrade to the latest version of lwIP (1.40) svn path=/branches/GSoC_2011/TcpIpDriver/; revision=52655 --- lib/drivers/lwip/src/api/api_lib.c | 19 +- lib/drivers/lwip/src/api/api_msg.c | 23 +- lib/drivers/lwip/src/api/err.c | 16 +- lib/drivers/lwip/src/api/sockets.c | 131 +- lib/drivers/lwip/src/api/tcpip.c | 1 - lib/drivers/lwip/src/core/dhcp.c | 30 +- lib/drivers/lwip/src/core/dns.c | 3 +- lib/drivers/lwip/src/core/init.c | 3 + lib/drivers/lwip/src/core/ipv4/autoip.c | 7 +- lib/drivers/lwip/src/core/ipv4/icmp.c | 2 +- lib/drivers/lwip/src/core/ipv4/igmp.c | 2 +- lib/drivers/lwip/src/core/ipv4/ip.c | 9 +- lib/drivers/lwip/src/core/ipv4/ip_addr.c | 2 +- lib/drivers/lwip/src/core/raw.c | 6 +- lib/drivers/lwip/src/core/snmp/mib2.c | 2 + lib/drivers/lwip/src/core/tcp.c | 97 +- lib/drivers/lwip/src/core/tcp_in.c | 136 +-- lib/drivers/lwip/src/core/tcp_out.c | 23 +- lib/drivers/lwip/src/core/timers.c | 2 +- lib/drivers/lwip/src/core/udp.c | 12 +- lib/drivers/lwip/src/include/ipv4/lwip/icmp.h | 28 +- lib/drivers/lwip/src/include/ipv4/lwip/ip.h | 8 +- lib/drivers/lwip/src/include/lwip/api.h | 5 +- lib/drivers/lwip/src/include/lwip/api_msg.h | 3 +- lib/drivers/lwip/src/include/lwip/debug.h | 2 - lib/drivers/lwip/src/include/lwip/dhcp.h | 3 + lib/drivers/lwip/src/include/lwip/dns.h | 8 + lib/drivers/lwip/src/include/lwip/err.h | 19 +- lib/drivers/lwip/src/include/lwip/init.h | 2 +- lib/drivers/lwip/src/include/lwip/mem.h | 2 +- lib/drivers/lwip/src/include/lwip/netdb.h | 8 + lib/drivers/lwip/src/include/lwip/opt.h | 11 +- lib/drivers/lwip/src/include/lwip/sockets.h | 8 +- lib/drivers/lwip/src/include/lwip/tcp.h | 2 +- lib/drivers/lwip/src/include/lwip/tcp_impl.h | 1 - lib/drivers/lwip/src/include/lwipopts.h | 2 + lib/drivers/lwip/src/include/netif/etharp.h | 12 +- lib/drivers/lwip/src/netif/etharp.c | 908 +++++++------- lib/drivers/lwip/src/netif/ppp/auth.c | 1050 +++++++++++------ lib/drivers/lwip/src/netif/ppp/auth.h | 2 +- lib/drivers/lwip/src/netif/ppp/chap.c | 255 ++-- lib/drivers/lwip/src/netif/ppp/chap.h | 66 +- lib/drivers/lwip/src/netif/ppp/chpms.c | 95 +- lib/drivers/lwip/src/netif/ppp/fsm.c | 380 +++--- lib/drivers/lwip/src/netif/ppp/fsm.h | 60 +- lib/drivers/lwip/src/netif/ppp/ipcp.c | 226 ++-- lib/drivers/lwip/src/netif/ppp/ipcp.h | 24 +- lib/drivers/lwip/src/netif/ppp/lcp.c | 325 ++--- lib/drivers/lwip/src/netif/ppp/lcp.h | 20 +- lib/drivers/lwip/src/netif/ppp/magic.c | 4 +- lib/drivers/lwip/src/netif/ppp/magic.h | 6 +- lib/drivers/lwip/src/netif/ppp/md5.c | 4 +- lib/drivers/lwip/src/netif/ppp/pap.c | 210 ++-- lib/drivers/lwip/src/netif/ppp/pap.h | 49 +- lib/drivers/lwip/src/netif/ppp/ppp.c | 801 +++++++------ lib/drivers/lwip/src/netif/ppp/ppp.h | 48 +- lib/drivers/lwip/src/netif/ppp/ppp_oe.c | 323 ++--- lib/drivers/lwip/src/netif/ppp/pppdebug.h | 55 +- lib/drivers/lwip/src/netif/ppp/randm.c | 4 +- lib/drivers/lwip/src/netif/ppp/vj.c | 182 ++- lib/drivers/lwip/src/netif/ppp/vj.h | 7 +- lib/drivers/lwip/src/netif/slipif.c | 2 +- 62 files changed, 3028 insertions(+), 2728 deletions(-) diff --git a/lib/drivers/lwip/src/api/api_lib.c b/lib/drivers/lwip/src/api/api_lib.c index 04f6d306d5b..b1a9e5253d8 100644 --- a/lib/drivers/lwip/src/api/api_lib.c +++ b/lib/drivers/lwip/src/api/api_lib.c @@ -240,6 +240,7 @@ netconn_disconnect(struct netconn *conn) err_t netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) { +#if LWIP_TCP struct api_msg msg; err_t err; @@ -257,6 +258,11 @@ netconn_listen_with_backlog(struct netconn *conn, u8_t backlog) NETCONN_SET_SAFE_ERR(conn, err); return err; +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(backlog); + return ERR_ARG; +#endif /* LWIP_TCP */ } /** @@ -301,9 +307,9 @@ netconn_accept(struct netconn *conn, struct netconn **new_conn) API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0); if (newconn == NULL) { - /* connection has been closed */ - NETCONN_SET_SAFE_ERR(conn, ERR_CLSD); - return ERR_CLSD; + /* connection has been aborted */ + NETCONN_SET_SAFE_ERR(conn, ERR_ABRT); + return ERR_ABRT; } #if TCP_LISTEN_BACKLOG /* Let the stack know that we have accepted the connection. */ @@ -402,7 +408,9 @@ netconn_recv_data(struct netconn *conn, void **new_buf) } #endif /* (LWIP_UDP || LWIP_RAW) */ +#if LWIP_SO_RCVBUF SYS_ARCH_DEC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVMINUS, len); @@ -499,6 +507,7 @@ netconn_recv(struct netconn *conn, struct netbuf **new_buf) void netconn_recved(struct netconn *conn, u32_t length) { +#if LWIP_TCP if ((conn != NULL) && (conn->type == NETCONN_TCP) && (netconn_get_noautorecved(conn))) { struct api_msg msg; @@ -511,6 +520,10 @@ netconn_recved(struct netconn *conn, u32_t length) /* don't care for the return value of do_recv */ TCPIP_APIMSG(&msg); } +#else /* LWIP_TCP */ + LWIP_UNUSED_ARG(conn); + LWIP_UNUSED_ARG(length); +#endif /* LWIP_TCP */ } /** diff --git a/lib/drivers/lwip/src/api/api_msg.c b/lib/drivers/lwip/src/api/api_msg.c index 366f5d9a2af..448f96dda0a 100644 --- a/lib/drivers/lwip/src/api/api_msg.c +++ b/lib/drivers/lwip/src/api/api_msg.c @@ -120,7 +120,9 @@ recv_raw(void *arg, struct raw_pcb *pcb, struct pbuf *p, netbuf_delete(buf); return 0; } else { +#if LWIP_SO_RCVBUF SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); } @@ -194,7 +196,9 @@ recv_udp(void *arg, struct udp_pcb *pcb, struct pbuf *p, netbuf_delete(buf); return; } else { +#if LWIP_SO_RCVBUF SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); } @@ -248,7 +252,9 @@ recv_tcp(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) /* don't deallocate p: it is presented to us later again from tcp_fasttmr! */ return ERR_MEM; } else { +#if LWIP_SO_RCVBUF SYS_ARCH_INC(conn->recv_avail, len); +#endif /* LWIP_SO_RCVBUF */ /* Register event with callback */ API_EVENT(conn, NETCONN_EVT_RCVPLUS, len); } @@ -614,7 +620,6 @@ netconn_alloc(enum netconn_type t, netconn_callback callback) conn->socket = -1; #endif /* LWIP_SOCKET */ conn->callback = callback; - conn->recv_avail = 0; #if LWIP_TCP conn->current_msg = NULL; conn->write_offset = 0; @@ -624,6 +629,7 @@ netconn_alloc(enum netconn_type t, netconn_callback callback) #endif /* LWIP_SO_RCVTIMEO */ #if LWIP_SO_RCVBUF conn->recv_bufsize = RECV_BUFSIZE_DEFAULT; + conn->recv_avail = 0; #endif /* LWIP_SO_RCVBUF */ conn->flags = 0; return conn; @@ -944,12 +950,7 @@ do_connected(void *arg, struct tcp_pcb *pcb, err_t err) conn->current_msg = NULL; conn->state = NETCONN_NONE; if (!was_blocking) { - SYS_ARCH_DECL_PROTECT(lev); - SYS_ARCH_PROTECT(lev); - if (conn->last_err == ERR_INPROGRESS) { - conn->last_err = ERR_OK; - } - SYS_ARCH_UNPROTECT(lev); + NETCONN_SET_SAFE_ERR(conn, ERR_OK); } API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); @@ -1040,6 +1041,7 @@ do_disconnect(struct api_msg_msg *msg) TCPIP_APIMSG_ACK(msg); } +#if LWIP_TCP /** * Set a TCP pcb contained in a netconn into listen mode * Called from netconn_listen. @@ -1049,7 +1051,6 @@ do_disconnect(struct api_msg_msg *msg) void do_listen(struct api_msg_msg *msg) { -#if LWIP_TCP if (ERR_IS_FATAL(msg->conn->last_err)) { msg->err = msg->conn->last_err; } else { @@ -1091,9 +1092,9 @@ do_listen(struct api_msg_msg *msg) } } } -#endif /* LWIP_TCP */ TCPIP_APIMSG_ACK(msg); } +#endif /* LWIP_TCP */ /** * Send some data on a RAW or UDP pcb contained in a netconn @@ -1147,6 +1148,7 @@ do_send(struct api_msg_msg *msg) TCPIP_APIMSG_ACK(msg); } +#if LWIP_TCP /** * Indicate data has been received from a TCP pcb contained in a netconn * Called from netconn_recv @@ -1156,7 +1158,6 @@ do_send(struct api_msg_msg *msg) void do_recv(struct api_msg_msg *msg) { -#if LWIP_TCP msg->err = ERR_OK; if (msg->conn->pcb.tcp != NULL) { if (msg->conn->type == NETCONN_TCP) { @@ -1175,11 +1176,9 @@ do_recv(struct api_msg_msg *msg) } } } -#endif /* LWIP_TCP */ TCPIP_APIMSG_ACK(msg); } -#if LWIP_TCP /** * See if more data needs to be written from a previous call to netconn_write. * Called initially from do_write. If the first call can't send all data diff --git a/lib/drivers/lwip/src/api/err.c b/lib/drivers/lwip/src/api/err.c index b0a4eb3e156..92fa8b7dba1 100644 --- a/lib/drivers/lwip/src/api/err.c +++ b/lib/drivers/lwip/src/api/err.c @@ -49,14 +49,14 @@ static const char *err_strerr[] = { "Operation in progress.", /* ERR_INPROGRESS -5 */ "Illegal value.", /* ERR_VAL -6 */ "Operation would block.", /* ERR_WOULDBLOCK -7 */ - "Connection aborted.", /* ERR_ABRT -8 */ - "Connection reset.", /* ERR_RST -9 */ - "Connection closed.", /* ERR_CLSD -10 */ - "Not connected.", /* ERR_CONN -11 */ - "Illegal argument.", /* ERR_ARG -12 */ - "Address in use.", /* ERR_USE -13 */ - "Low-level netif error.", /* ERR_IF -14 */ - "Already connected.", /* ERR_ISCONN -15 */ + "Address in use.", /* ERR_USE -8 */ + "Already connected.", /* ERR_ISCONN -9 */ + "Connection aborted.", /* ERR_ABRT -10 */ + "Connection reset.", /* ERR_RST -11 */ + "Connection closed.", /* ERR_CLSD -12 */ + "Not connected.", /* ERR_CONN -13 */ + "Illegal argument.", /* ERR_ARG -14 */ + "Low-level netif error.", /* ERR_IF -15 */ }; /** diff --git a/lib/drivers/lwip/src/api/sockets.c b/lib/drivers/lwip/src/api/sockets.c index 9919b6112e0..e36012ce43b 100644 --- a/lib/drivers/lwip/src/api/sockets.c +++ b/lib/drivers/lwip/src/api/sockets.c @@ -105,8 +105,10 @@ struct lwip_select_cb { struct lwip_setgetsockopt_data { /** socket struct for which to change options */ struct lwip_sock *sock; +#ifdef LWIP_DEBUG /** socket index for which to change options */ int s; +#endif /* LWIP_DEBUG */ /** level of the option to process */ int level; /** name of the option to process */ @@ -139,14 +141,14 @@ static const int err_to_errno_table[] = { EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */ EINVAL, /* ERR_VAL -6 Illegal value. */ EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */ - ECONNABORTED, /* ERR_ABRT -8 Connection aborted. */ - ECONNRESET, /* ERR_RST -9 Connection reset. */ - ESHUTDOWN, /* ERR_CLSD -10 Connection closed. */ - ENOTCONN, /* ERR_CONN -11 Not connected. */ - EIO, /* ERR_ARG -12 Illegal argument. */ - EADDRINUSE, /* ERR_USE -13 Address in use. */ - -1, /* ERR_IF -14 Low-level netif error */ - -1, /* ERR_ISCONN -15 Already connected. */ + EADDRINUSE, /* ERR_USE -8 Address in use. */ + EALREADY, /* ERR_ISCONN -9 Already connected. */ + ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */ + ECONNRESET, /* ERR_RST -11 Connection reset. */ + ENOTCONN, /* ERR_CLSD -12 Connection closed. */ + ENOTCONN, /* ERR_CONN -13 Not connected. */ + EIO, /* ERR_ARG -14 Illegal argument. */ + -1, /* ERR_IF -15 Low-level netif error */ }; #define ERR_TO_ERRNO_TABLE_SIZE \ @@ -804,6 +806,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags, #if LWIP_TCP return lwip_send(s, data, size, flags); #else /* LWIP_TCP */ + LWIP_UNUSED_ARG(flags); sock_set_errno(sock, err_to_errno(ERR_ARG)); return -1; #endif /* LWIP_TCP */ @@ -844,14 +847,19 @@ lwip_sendto(int s, const void *data, size_t size, int flags, inet_addr_to_ipaddr_p(remote_addr, &to_in->sin_addr); remote_port = ntohs(to_in->sin_port); } else { - remote_addr = IP_ADDR_ANY; - remote_port = 0; + remote_addr = &sock->conn->pcb.raw->remote_ip; + if (sock->conn->type == NETCONN_RAW) { + remote_port = 0; + } else { + remote_port = sock->conn->pcb.udp->remote_port; + } } LOCK_TCPIP_CORE(); if (sock->conn->type == NETCONN_RAW) { err = sock->conn->last_err = raw_sendto(sock->conn->pcb.raw, p, remote_addr); } else { +#if LWIP_UDP #if LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF err = sock->conn->last_err = udp_sendto_chksum(sock->conn->pcb.udp, p, remote_addr, remote_port, 1, chksum); @@ -859,6 +867,9 @@ lwip_sendto(int s, const void *data, size_t size, int flags, err = sock->conn->last_err = udp_sendto(sock->conn->pcb.udp, p, remote_addr, remote_port); #endif /* LWIP_CHECKSUM_ON_COPY && LWIP_NETIF_TX_SINGLE_PBUF */ +#else /* LWIP_UDP */ + err = ERR_ARG; +#endif /* LWIP_UDP */ } UNLOCK_TCPIP_CORE(); @@ -883,7 +894,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags, netbuf_fromport(&buf) = 0; } - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%d"U16_F", flags=0x%x to=", + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", s, data, short_size, flags)); ip_addr_debug_print(SOCKETS_DEBUG, &buf.addr); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); @@ -1181,6 +1192,8 @@ lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, LWIP_ASSERT("select_cb.prev != NULL", select_cb.prev != NULL); select_cb.prev->next = select_cb.next; } + /* Increasing this counter tells even_callback that the list has changed. */ + select_cb_ctr++; SYS_ARCH_UNPROTECT(lev); sys_sem_free(&select_cb.sem); @@ -1223,6 +1236,7 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) int s; struct lwip_sock *sock; struct lwip_select_cb *scb; + int last_select_cb_ctr; SYS_ARCH_DECL_PROTECT(lev); LWIP_UNUSED_ARG(len); @@ -1285,56 +1299,51 @@ event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) return; } - SYS_ARCH_UNPROTECT(lev); - /* Now decide if anyone is waiting for this socket */ - /* NOTE: This code is written this way to protect the select link list - but to avoid a deadlock situation by releasing select_lock before - signalling for the select. This means we need to go through the list - multiple times ONLY IF a select was actually waiting. We go through - the list the number of waiting select calls + 1. This list is - expected to be small. */ - while (1) { - int last_select_cb_ctr; - SYS_ARCH_PROTECT(lev); - for (scb = select_cb_list; scb; scb = scb->next) { - /* @todo: unprotect with each loop and check for changes? */ - if (scb->sem_signalled == 0) { - /* Test this select call for our socket */ + /* NOTE: This code goes through the select_cb_list list multiple times + ONLY IF a select was actually waiting. We go through the list the number + of waiting select calls + 1. This list is expected to be small. */ + + /* At this point, SYS_ARCH is still protected! */ +again: + for (scb = select_cb_list; scb != NULL; scb = scb->next) { + if (scb->sem_signalled == 0) { + /* semaphore not signalled yet */ + int do_signal = 0; + /* Test this select call for our socket */ + if (sock->rcvevent > 0) { if (scb->readset && FD_ISSET(s, scb->readset)) { - if (sock->rcvevent > 0) { - break; - } - } - if (scb->writeset && FD_ISSET(s, scb->writeset)) { - if (sock->sendevent != 0) { - break; - } - } - if (scb->exceptset && FD_ISSET(s, scb->exceptset)) { - if (sock->errevent != 0) { - break; - } + do_signal = 1; } } - /* unlock interrupts with each step */ - last_select_cb_ctr = select_cb_ctr; - SYS_ARCH_UNPROTECT(lev); - SYS_ARCH_PROTECT(lev); - if (last_select_cb_ctr != select_cb_ctr) { - /* someone has changed select_cb_list, restart at the beginning */ - scb = select_cb_list; + if (sock->sendevent != 0) { + if (!do_signal && scb->writeset && FD_ISSET(s, scb->writeset)) { + do_signal = 1; + } + } + if (sock->errevent != 0) { + if (!do_signal && scb->exceptset && FD_ISSET(s, scb->exceptset)) { + do_signal = 1; + } + } + if (do_signal) { + scb->sem_signalled = 1; + /* Don't call SYS_ARCH_UNPROTECT() before signaling the semaphore, as this might + lead to the select thread taking itself off the list, invalidagin the semaphore. */ + sys_sem_signal(&scb->sem); } } - if (scb) { - scb->sem_signalled = 1; - sys_sem_signal(&scb->sem); - SYS_ARCH_UNPROTECT(lev); - } else { - SYS_ARCH_UNPROTECT(lev); - break; + /* unlock interrupts with each step */ + last_select_cb_ctr = select_cb_ctr; + SYS_ARCH_UNPROTECT(lev); + /* this makes sure interrupt protection time is short */ + SYS_ARCH_PROTECT(lev); + if (last_select_cb_ctr != select_cb_ctr) { + /* someone has changed select_cb_list, restart at the beginning */ + goto again; } } + SYS_ARCH_UNPROTECT(lev); } /** @@ -1610,6 +1619,9 @@ lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) /* Now do the actual option processing */ data.sock = sock; +#ifdef LWIP_DEBUG + data.s = s; +#endif /* LWIP_DEBUG */ data.level = level; data.optname = optname; data.optval = optval; @@ -1691,8 +1703,8 @@ lwip_getsockopt_internal(void *arg) break; case SO_ERROR: - /* only overwrite if ERR_OK before */ - if (sock->err == 0) { + /* only overwrite ERR_OK or tempoary errors */ + if ((sock->err == 0) || (sock->err == EINPROGRESS)) { sock_set_errno(sock, err_to_errno(sock->conn->last_err)); } *(int *)optval = sock->err; @@ -2017,6 +2029,9 @@ lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t opt /* Now do the actual option processing */ data.sock = sock; +#ifdef LWIP_DEBUG + data.s = s; +#endif /* LWIP_DEBUG */ data.level = level; data.optname = optname; data.optval = (void*)optval; @@ -2239,15 +2254,18 @@ int lwip_ioctl(int s, long cmd, void *argp) { struct lwip_sock *sock = get_socket(s); + u8_t val; +#if LWIP_SO_RCVBUF u16_t buflen = 0; s16_t recv_avail; - u8_t val; +#endif /* LWIP_SO_RCVBUF */ if (!sock) { return -1; } switch (cmd) { +#if LWIP_SO_RCVBUF case FIONREAD: if (!argp) { sock_set_errno(sock, EINVAL); @@ -2275,6 +2293,7 @@ lwip_ioctl(int s, long cmd, void *argp) LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t*)argp))); sock_set_errno(sock, 0); return 0; +#endif /* LWIP_SO_RCVBUF */ case FIONBIO: val = 0; diff --git a/lib/drivers/lwip/src/api/tcpip.c b/lib/drivers/lwip/src/api/tcpip.c index 846d2fde0f8..857e7d9bd64 100644 --- a/lib/drivers/lwip/src/api/tcpip.c +++ b/lib/drivers/lwip/src/api/tcpip.c @@ -46,7 +46,6 @@ #include "lwip/pbuf.h" #include "lwip/tcpip.h" #include "lwip/init.h" -#include "lwip/ip.h" #include "netif/etharp.h" #include "netif/ppp_oe.h" diff --git a/lib/drivers/lwip/src/core/dhcp.c b/lib/drivers/lwip/src/core/dhcp.c index 37943ca6403..81b4be271e9 100644 --- a/lib/drivers/lwip/src/core/dhcp.c +++ b/lib/drivers/lwip/src/core/dhcp.c @@ -592,6 +592,23 @@ dhcp_set_struct(struct netif *netif, struct dhcp *dhcp) netif->dhcp = dhcp; } +/** Removes a struct dhcp from a netif. + * + * ATTENTION: Only use this when not using dhcp_set_struct() to allocate the + * struct dhcp since the memory is passed back to the heap. + * + * @param netif the netif from which to remove the struct dhcp + */ +void dhcp_cleanup(struct netif *netif) +{ + LWIP_ASSERT("netif != NULL", netif != NULL); + + if (netif->dhcp != NULL) { + mem_free(netif->dhcp); + netif->dhcp = NULL; + } +} + /** * Start DHCP negotiation for a network interface. * @@ -762,7 +779,10 @@ dhcp_network_changed(struct netif *netif) default: dhcp->tries = 0; #if LWIP_DHCP_AUTOIP_COOP - dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + if(dhcp->autoip_coop_state == DHCP_AUTOIP_COOP_STATE_ON) { + autoip_stop(netif); + dhcp->autoip_coop_state = DHCP_AUTOIP_COOP_STATE_OFF; + } #endif /* LWIP_DHCP_AUTOIP_COOP */ dhcp_discover(netif); break; @@ -945,11 +965,11 @@ dhcp_bind(struct netif *netif) /* subnet mask not given, choose a safe subnet mask given the network class */ u8_t first_octet = ip4_addr1(&dhcp->offered_ip_addr); if (first_octet <= 127) { - ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000)); + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xff000000UL)); } else if (first_octet >= 192) { - ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00)); + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffffff00UL)); } else { - ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000)); + ip4_addr_set_u32(&sn_mask, PP_HTONL(0xffff0000UL)); } } @@ -959,7 +979,7 @@ dhcp_bind(struct netif *netif) /* copy network address */ ip_addr_get_network(&gw_addr, &dhcp->offered_ip_addr, &sn_mask); /* use first host address on network as gateway */ - ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001)); + ip4_addr_set_u32(&gw_addr, ip4_addr_get_u32(&gw_addr) | PP_HTONL(0x00000001UL)); } #if LWIP_DHCP_AUTOIP_COOP diff --git a/lib/drivers/lwip/src/core/dns.c b/lib/drivers/lwip/src/core/dns.c index 2efc4517643..d63361226f2 100644 --- a/lib/drivers/lwip/src/core/dns.c +++ b/lib/drivers/lwip/src/core/dns.c @@ -922,6 +922,7 @@ dns_enqueue(const char *name, dns_found_callback found, void *callback_arg) * name is already in the local names table. * - ERR_INPROGRESS enqueue a request to be sent to the DNS server * for resolution if no errors are present. + * - ERR_ARG: dns client not initialized or invalid hostname * * @param hostname the hostname that is to be queried * @param addr pointer to a ip_addr_t where to store the address if it is already @@ -941,7 +942,7 @@ dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback foun if ((dns_pcb == NULL) || (addr == NULL) || (!hostname) || (!hostname[0]) || (strlen(hostname) >= DNS_MAX_NAME_LENGTH)) { - return ERR_VAL; + return ERR_ARG; } #if LWIP_HAVE_LOOPIF diff --git a/lib/drivers/lwip/src/core/init.c b/lib/drivers/lwip/src/core/init.c index 949934ae5c5..bf5c79da0d6 100644 --- a/lib/drivers/lwip/src/core/init.c +++ b/lib/drivers/lwip/src/core/init.c @@ -105,6 +105,9 @@ #if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff)) #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h" #endif +#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2)) + #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work" +#endif #if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12))) #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h" #endif diff --git a/lib/drivers/lwip/src/core/ipv4/autoip.c b/lib/drivers/lwip/src/core/ipv4/autoip.c index f5fbe34ef80..92bb4591f1a 100644 --- a/lib/drivers/lwip/src/core/ipv4/autoip.c +++ b/lib/drivers/lwip/src/core/ipv4/autoip.c @@ -494,12 +494,7 @@ autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr) */ ip_addr_t sipaddr, dipaddr; struct eth_addr netifaddr; - netifaddr.addr[0] = netif->hwaddr[0]; - netifaddr.addr[1] = netif->hwaddr[1]; - netifaddr.addr[2] = netif->hwaddr[2]; - netifaddr.addr[3] = netif->hwaddr[3]; - netifaddr.addr[4] = netif->hwaddr[4]; - netifaddr.addr[5] = netif->hwaddr[5]; + ETHADDR16_COPY(netifaddr.addr, netif->hwaddr); /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without * structure packing (not using structure copy which breaks strict-aliasing rules). diff --git a/lib/drivers/lwip/src/core/ipv4/icmp.c b/lib/drivers/lwip/src/core/ipv4/icmp.c index 02e498d759f..32902a522ca 100644 --- a/lib/drivers/lwip/src/core/ipv4/icmp.c +++ b/lib/drivers/lwip/src/core/ipv4/icmp.c @@ -191,7 +191,7 @@ icmp_input(struct pbuf *p, struct netif *inp) ip_addr_copy(iphdr->dest, *ip_current_src_addr()); ICMPH_TYPE_SET(iecho, ICMP_ER); /* adjust the checksum */ - if (iecho->chksum >= PP_HTONS(0xffff - (ICMP_ECHO << 8))) { + if (iecho->chksum >= PP_HTONS(0xffffU - (ICMP_ECHO << 8))) { iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1; } else { iecho->chksum += PP_HTONS(ICMP_ECHO << 8); diff --git a/lib/drivers/lwip/src/core/ipv4/igmp.c b/lib/drivers/lwip/src/core/ipv4/igmp.c index 390a5a741c4..4e4405e16f9 100644 --- a/lib/drivers/lwip/src/core/ipv4/igmp.c +++ b/lib/drivers/lwip/src/core/ipv4/igmp.c @@ -100,7 +100,7 @@ Steve Reynolds */ #define IGMP_TTL 1 #define IGMP_MINLEN 8 -#define ROUTER_ALERT 0x9404 +#define ROUTER_ALERT 0x9404U #define ROUTER_ALERTLEN 4 /* diff --git a/lib/drivers/lwip/src/core/ipv4/ip.c b/lib/drivers/lwip/src/core/ipv4/ip.c index 0c3beca10fb..6f248716b63 100644 --- a/lib/drivers/lwip/src/core/ipv4/ip.c +++ b/lib/drivers/lwip/src/core/ipv4/ip.c @@ -201,7 +201,7 @@ ip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) } /* Incrementally update the IP checksum. */ - if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffff - 0x100)) { + if (IPH_CHKSUM(iphdr) >= PP_HTONS(0xffffU - 0x100)) { IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100) + 1); } else { IPH_CHKSUM_SET(iphdr, IPH_CHKSUM(iphdr) + PP_HTONS(0x100)); @@ -252,8 +252,6 @@ ip_input(struct pbuf *p, struct netif *inp) IP_STATS_INC(ip.recv); snmp_inc_ipinreceives(); - DbgPrint("ip_input: called\n"); - /* identify the IP header */ iphdr = (struct ip_hdr *)p->payload; if (IPH_V(iphdr) != 4) { @@ -490,7 +488,7 @@ ip_input(struct pbuf *p, struct netif *inp) if (raw_input(p, inp) == 0) #endif /* LWIP_RAW */ { - DbgPrint("ip_input: choosing protocol\n"); + switch (IPH_PROTO(iphdr)) { #if LWIP_UDP case IP_PROTO_UDP: @@ -504,7 +502,6 @@ ip_input(struct pbuf *p, struct netif *inp) #if LWIP_TCP case IP_PROTO_TCP: snmp_inc_ipindelivers(); - DbgPrint("ip_input: sending data to tcp_input\n"); tcp_input(p, inp); break; #endif /* LWIP_TCP */ @@ -628,7 +625,7 @@ err_t ip_output_if_opt(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, memset(((char*)p->payload) + optlen, 0, optlen_aligned - optlen); } #if CHECKSUM_GEN_IP_INLINE - for (i = 0; i < optlen_aligned; i += sizeof(u16_t)) { + for (i = 0; i < optlen_aligned/2; i++) { chk_sum += ((u16_t*)p->payload)[i]; } #endif /* CHECKSUM_GEN_IP_INLINE */ diff --git a/lib/drivers/lwip/src/core/ipv4/ip_addr.c b/lib/drivers/lwip/src/core/ipv4/ip_addr.c index 7e953d375ea..8f633ff2310 100644 --- a/lib/drivers/lwip/src/core/ipv4/ip_addr.c +++ b/lib/drivers/lwip/src/core/ipv4/ip_addr.c @@ -93,7 +93,7 @@ ip4_addr_netmask_valid(u32_t netmask) u32_t nm_hostorder = lwip_htonl(netmask); /* first, check for the first zero */ - for (mask = 1U << 31 ; mask != 0; mask >>= 1) { + for (mask = 1UL << 31 ; mask != 0; mask >>= 1) { if ((nm_hostorder & mask) == 0) { break; } diff --git a/lib/drivers/lwip/src/core/raw.c b/lib/drivers/lwip/src/core/raw.c index 3c1ee8209bc..9fcb100316d 100644 --- a/lib/drivers/lwip/src/core/raw.c +++ b/lib/drivers/lwip/src/core/raw.c @@ -218,8 +218,10 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr) LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("raw_sendto: could not allocate header\n")); return ERR_MEM; } - /* chain header q in front of given pbuf p */ - pbuf_chain(q, p); + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p */ + pbuf_chain(q, p); + } /* { first pbuf q points to header pbuf } */ LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); } else { diff --git a/lib/drivers/lwip/src/core/snmp/mib2.c b/lib/drivers/lwip/src/core/snmp/mib2.c index 5ed9fcd66a2..29decd306f3 100644 --- a/lib/drivers/lwip/src/core/snmp/mib2.c +++ b/lib/drivers/lwip/src/core/snmp/mib2.c @@ -43,10 +43,12 @@ #include "lwip/netif.h" #include "lwip/ip.h" #include "lwip/ip_frag.h" +#include "lwip/mem.h" #include "lwip/tcp_impl.h" #include "lwip/udp.h" #include "lwip/snmp_asn1.h" #include "lwip/snmp_structs.h" +#include "lwip/sys.h" #include "netif/etharp.h" /** diff --git a/lib/drivers/lwip/src/core/tcp.c b/lib/drivers/lwip/src/core/tcp.c index ca182a20e1e..c629bc4e8ac 100644 --- a/lib/drivers/lwip/src/core/tcp.c +++ b/lib/drivers/lwip/src/core/tcp.c @@ -91,7 +91,7 @@ struct tcp_pcb *tcp_tw_pcbs; #define NUM_TCP_PCB_LISTS 4 #define NUM_TCP_PCB_LISTS_NO_TIME_WAIT 3 /** An array with all (non-temporary) PCB lists, mainly used for smaller code size */ -struct tcp_pcb **tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, +struct tcp_pcb ** const tcp_pcb_lists[] = {&tcp_listen_pcbs.pcbs, &tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; /** Only used for temporary storage. */ @@ -139,8 +139,6 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) { err_t err; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_close_shutdown: called on pcb 0x%x\n", pcb)); - if (rst_on_unacked_data && (pcb->state != LISTEN)) { if ((pcb->refused_data != NULL) || (pcb->rcv_wnd != TCP_WND)) { /* Not all data received by application, send RST to tell the remote @@ -175,13 +173,14 @@ tcp_close_shutdown(struct tcp_pcb *pcb, u8_t rst_on_unacked_data) * is erroneous, but this should never happen as the pcb has in those cases * been freed, and so any remaining handles are bogus. */ err = ERR_OK; - TCP_RMV(&tcp_bound_pcbs, pcb); + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } memp_free(MEMP_TCP_PCB, pcb); pcb = NULL; break; case LISTEN: err = ERR_OK; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_close_shutdown: Remove pcb from listen list and free\n")); tcp_pcb_remove(&tcp_listen_pcbs.pcbs, pcb); memp_free(MEMP_TCP_PCB_LISTEN, pcb); pcb = NULL; @@ -394,6 +393,7 @@ tcp_abort(struct tcp_pcb *pcb) * to any local address * @param port the local port to bind to * @return ERR_USE if the port is already in use + * ERR_VAL if bind failed because the PCB is not in a valid state * ERR_OK if bound */ err_t @@ -403,7 +403,7 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) int max_pcb_list = NUM_TCP_PCB_LISTS; struct tcp_pcb *cpcb; - LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); + LWIP_ERROR("tcp_bind: can only bind in state CLOSED", pcb->state == CLOSED, return ERR_VAL); #if SO_REUSE /* Unless the REUSEADDR flag is set, @@ -411,11 +411,9 @@ tcp_bind(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) We do not dump TIME_WAIT pcb's; they can still be matched by incoming packets using both local and remote IP addresses and ports to distinguish. */ -#if SO_REUSE if ((pcb->so_options & SOF_REUSEADDR) != 0) { max_pcb_list = NUM_TCP_PCB_LISTS_NO_TIME_WAIT; } -#endif /* SO_REUSE */ #endif /* SO_REUSE */ if (port == 0) { @@ -488,8 +486,6 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) LWIP_UNUSED_ARG(backlog); LWIP_ERROR("tcp_listen: pcb already connected", pcb->state == CLOSED, return NULL); - DbgPrint("tcp_listen_with_backlog: sizeof(tcp_pcb_listen) = %d, %d\n", - sizeof(struct tcp_pcb_listen), (((sizeof(struct tcp_pcb_listen)) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1))); /* already listening? */ if (pcb->state == LISTEN) { @@ -523,7 +519,9 @@ tcp_listen_with_backlog(struct tcp_pcb *pcb, u8_t backlog) lpcb->ttl = pcb->ttl; lpcb->tos = pcb->tos; ip_addr_copy(lpcb->local_ip, pcb->local_ip); - TCP_RMV(&tcp_bound_pcbs, pcb); + if (pcb->local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } memp_free(MEMP_TCP_PCB, pcb); #if LWIP_CALLBACK_API lpcb->accept = tcp_accept_null; @@ -613,17 +611,19 @@ tcp_new_port(void) int i; struct tcp_pcb *pcb; #ifndef TCP_LOCAL_PORT_RANGE_START -#define TCP_LOCAL_PORT_RANGE_START 4096 -#define TCP_LOCAL_PORT_RANGE_END 0x7fff +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define TCP_LOCAL_PORT_RANGE_START 0xc000 +#define TCP_LOCAL_PORT_RANGE_END 0xffff #endif static u16_t port = TCP_LOCAL_PORT_RANGE_START; again: - if (++port > TCP_LOCAL_PORT_RANGE_END) { + if (port++ >= TCP_LOCAL_PORT_RANGE_END) { port = TCP_LOCAL_PORT_RANGE_START; } /* Check all PCB lists. */ - for (i = 1; i < NUM_TCP_PCB_LISTS; i++) { + for (i = 0; i < NUM_TCP_PCB_LISTS; i++) { for(pcb = *tcp_pcb_lists[i]; pcb != NULL; pcb = pcb->next) { if (pcb->local_port == port) { goto again; @@ -651,8 +651,9 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, { err_t ret; u32_t iss; + u16_t old_local_port; - LWIP_ERROR("tcp_connect: can only connected from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); + LWIP_ERROR("tcp_connect: can only connect from state CLOSED", pcb->state == CLOSED, return ERR_ISCONN); LWIP_DEBUGF(TCP_DEBUG, ("tcp_connect to port %"U16_F"\n", port)); if (ipaddr != NULL) { @@ -675,6 +676,7 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, ip_addr_copy(pcb->local_ip, netif->ip_addr); } + old_local_port = pcb->local_port; if (pcb->local_port == 0) { pcb->local_port = tcp_new_port(); } @@ -684,8 +686,8 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, now that the 5-tuple is unique. */ struct tcp_pcb *cpcb; int i; - /* Don't check listen PCBs, check bound-, active- and TIME-WAIT PCBs. */ - for (i = 1; i < NUM_TCP_PCB_LISTS; i++) { + /* Don't check listen- and bound-PCBs, check active- and TIME-WAIT PCBs. */ + for (i = 2; i < NUM_TCP_PCB_LISTS; i++) { for(cpcb = *tcp_pcb_lists[i]; cpcb != NULL; cpcb = cpcb->next) { if ((cpcb->local_port == pcb->local_port) && (cpcb->remote_port == port) && @@ -726,7 +728,9 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, if (ret == ERR_OK) { /* SYN segment was enqueued, changed the pcbs state now */ pcb->state = SYN_SENT; - TCP_RMV(&tcp_bound_pcbs, pcb); + if (old_local_port != 0) { + TCP_RMV(&tcp_bound_pcbs, pcb); + } TCP_REG(&tcp_active_pcbs, pcb); snmp_inc_tcpactiveopens(); @@ -745,7 +749,7 @@ tcp_connect(struct tcp_pcb *pcb, ip_addr_t *ipaddr, u16_t port, void tcp_slowtmr(void) { - struct tcp_pcb *pcb, *pcb2, *prev; + struct tcp_pcb *pcb, *prev; u16_t eff_wnd; u8_t pcb_remove; /* flag if a PCB should be removed */ u8_t pcb_reset; /* flag if a RST should be sent when removing */ @@ -758,33 +762,26 @@ tcp_slowtmr(void) /* Steps through all of the active PCBs. */ prev = NULL; pcb = tcp_active_pcbs; - if (pcb == NULL) - { + if (pcb == NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n")); } - while (pcb != NULL) - { + while (pcb != NULL) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n")); LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED); LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN); LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); - LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: active pcb = 0x%x ports (%d -> %d)\n", pcb, pcb->local_port, pcb->remote_port)); - pcb_remove = 0; pcb_reset = 0; - if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) - { + if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) { ++pcb_remove; LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n")); } - else if (pcb->nrtx == TCP_MAXRTX) - { + else if (pcb->nrtx == TCP_MAXRTX) { ++pcb_remove; LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n")); - } - else { + } else { if (pcb->persist_backoff > 0) { /* If snd_wnd is zero, use persist timer to send 1 byte probes * instead of using the standard retransmission mechanism. */ @@ -907,16 +904,14 @@ tcp_slowtmr(void) } /* If the PCB should be removed, do it. */ - if (pcb_remove) - { + if (pcb_remove) { + struct tcp_pcb *pcb2; tcp_pcb_purge(pcb); /* Remove PCB from tcp_active_pcbs list. */ if (prev != NULL) { LWIP_ASSERT("tcp_slowtmr: middle tcp != tcp_active_pcbs", pcb != tcp_active_pcbs); prev->next = pcb->next; - } - else - { + } else { /* This PCB was the first. */ LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_active_pcbs", tcp_active_pcbs == pcb); tcp_active_pcbs = pcb->next; @@ -928,27 +923,22 @@ tcp_slowtmr(void) pcb->local_port, pcb->remote_port); } - pcb2 = pcb->next; - memp_free(MEMP_TCP_PCB, pcb); - pcb = pcb2; - } - else - { + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); + } else { /* get the 'next' element now and work with 'prev' below (in case of abort) */ prev = pcb; pcb = pcb->next; /* We check if we should poll the connection. */ ++prev->polltmr; - if (prev->polltmr >= prev->pollinterval) - { + if (prev->polltmr >= prev->pollinterval) { prev->polltmr = 0; LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: polling application\n")); - //LWIP_ASSERT("tcp_slowtmr: active pcb->poll != 0\n", pcb->poll != 0); TCP_EVENT_POLL(prev, err); /* if err == ERR_ABRT, 'prev' is already deallocated */ - if (err == ERR_OK) - { + if (err == ERR_OK) { tcp_output(prev); } } @@ -957,7 +947,7 @@ tcp_slowtmr(void) /* Steps through all of the TIME-WAIT PCBs. */ - prev = NULL; + prev = NULL; pcb = tcp_tw_pcbs; while (pcb != NULL) { LWIP_ASSERT("tcp_slowtmr: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); @@ -972,6 +962,7 @@ tcp_slowtmr(void) /* If the PCB should be removed, do it. */ if (pcb_remove) { + struct tcp_pcb *pcb2; tcp_pcb_purge(pcb); /* Remove PCB from tcp_tw_pcbs list. */ if (prev != NULL) { @@ -982,9 +973,9 @@ tcp_slowtmr(void) LWIP_ASSERT("tcp_slowtmr: first pcb == tcp_tw_pcbs", tcp_tw_pcbs == pcb); tcp_tw_pcbs = pcb->next; } - pcb2 = pcb->next; - memp_free(MEMP_TCP_PCB, pcb); - pcb = pcb2; + pcb2 = pcb; + pcb = pcb->next; + memp_free(MEMP_TCP_PCB, pcb2); } else { prev = pcb; pcb = pcb->next; @@ -1019,7 +1010,7 @@ tcp_fasttmr(void) } } - /* send delayed ACKs */ + /* send delayed ACKs */ if (pcb && (pcb->flags & TF_ACK_DELAY)) { LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n")); tcp_ack_now(pcb); diff --git a/lib/drivers/lwip/src/core/tcp_in.c b/lib/drivers/lwip/src/core/tcp_in.c index 955894ae6ec..90952648d7f 100644 --- a/lib/drivers/lwip/src/core/tcp_in.c +++ b/lib/drivers/lwip/src/core/tcp_in.c @@ -113,8 +113,7 @@ tcp_input(struct pbuf *p, struct netif *inp) #endif /* remove header from payload */ - if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) - { + if (pbuf_header(p, -((s16_t)(IPH_HL(iphdr) * 4))) || (p->tot_len < sizeof(struct tcp_hdr))) { /* drop short packets */ LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: short packet (%"U16_F" bytes) discarded\n", p->tot_len)); TCP_STATS_INC(tcp.lenerr); @@ -175,31 +174,25 @@ tcp_input(struct pbuf *p, struct netif *inp) flags = TCPH_FLAGS(tcphdr); tcplen = p->tot_len + ((flags & (TCP_FIN | TCP_SYN)) ? 1 : 0); - LWIP_DEBUGF(TCP_DEBUG, ("tcp_input: called %"U16_F" -> %"U16_F"\n", tcphdr->src, tcphdr->dest)); - /* Demultiplex an incoming segment. First, we check if it is destined for an active connection. */ prev = NULL; + - for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) - { + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) { LWIP_ASSERT("tcp_input: active pcb->state != CLOSED", pcb->state != CLOSED); LWIP_ASSERT("tcp_input: active pcb->state != TIME-WAIT", pcb->state != TIME_WAIT); LWIP_ASSERT("tcp_input: active pcb->state != LISTEN", pcb->state != LISTEN); - if (pcb->remote_port == tcphdr->src && pcb->local_port == tcphdr->dest && ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src) && - ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) - { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_input: active pcb -> (localport, remoteport) = %"U16_F" -> %"U16_F"\n", pcb->local_port, pcb->remote_port)); - DbgPrint("tcp_input: pcb = 0x%x\n", pcb); + ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) { + /* Move this PCB to the front of the list so that subsequent lookups will be faster (we exploit locality in TCP segment arrivals). */ LWIP_ASSERT("tcp_input: pcb->next != pcb (before cache)", pcb->next != pcb); - if (prev != NULL) - { + if (prev != NULL) { prev->next = pcb->next; pcb->next = tcp_active_pcbs; tcp_active_pcbs = pcb; @@ -210,18 +203,15 @@ tcp_input(struct pbuf *p, struct netif *inp) prev = pcb; } - if (pcb == NULL) - { + if (pcb == NULL) { /* If it did not go to an active connection, we check the connections in the TIME-WAIT state. */ - for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) - { + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) { LWIP_ASSERT("tcp_input: TIME-WAIT pcb->state == TIME-WAIT", pcb->state == TIME_WAIT); if (pcb->remote_port == tcphdr->src && pcb->local_port == tcphdr->dest && ip_addr_cmp(&(pcb->remote_ip), ¤t_iphdr_src) && - ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) - { + ip_addr_cmp(&(pcb->local_ip), ¤t_iphdr_dest)) { /* We don't really care enough to move this PCB to the front of the list since we are not very likely to receive that many segments for connections in TIME-WAIT. */ @@ -235,10 +225,8 @@ tcp_input(struct pbuf *p, struct netif *inp) /* Finally, if we still did not get a match, we check all PCBs that are LISTENing for incoming connections. */ prev = NULL; - for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) - { - if (lpcb->local_port == tcphdr->dest) - { + for(lpcb = tcp_listen_pcbs.listen_pcbs; lpcb != NULL; lpcb = lpcb->next) { + if (lpcb->local_port == tcphdr->dest) { #if SO_REUSE if (ip_addr_cmp(&(lpcb->local_ip), ¤t_iphdr_dest)) { /* found an exact match */ @@ -250,8 +238,7 @@ tcp_input(struct pbuf *p, struct netif *inp) } #else /* SO_REUSE */ if (ip_addr_cmp(&(lpcb->local_ip), ¤t_iphdr_dest) || - ip_addr_isany(&(lpcb->local_ip))) - { + ip_addr_isany(&(lpcb->local_ip))) { /* found a match */ break; } @@ -267,13 +254,11 @@ tcp_input(struct pbuf *p, struct netif *inp) prev = lpcb_prev; } #endif /* SO_REUSE */ - if (lpcb != NULL) - { + if (lpcb != NULL) { /* Move this PCB to the front of the list so that subsequent lookups will be faster (we exploit locality in TCP segment arrivals). */ - if (prev != NULL) - { + if (prev != NULL) { ((struct tcp_pcb_listen *)prev)->next = lpcb->next; /* our successor is the remainder of the listening list */ lpcb->next = tcp_listen_pcbs.listen_pcbs; @@ -281,8 +266,7 @@ tcp_input(struct pbuf *p, struct netif *inp) tcp_listen_pcbs.listen_pcbs = lpcb; } - LWIP_DEBUGF(TCP_DEBUG, ("tcp_input: packed for LISTENing connection\n")); - + LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packed for LISTENing connection.\n")); tcp_listen_input(lpcb); pbuf_free(p); return; @@ -296,9 +280,7 @@ tcp_input(struct pbuf *p, struct netif *inp) #endif /* TCP_INPUT_DEBUG */ - if (pcb != NULL) - { - LWIP_DEBUGF(TCP_DEBUG, ("tcp_input: pcb = 0x%x is for active connection\n", pcb)); + if (pcb != NULL) { /* The incoming segment belongs to a connection. */ #if TCP_INPUT_DEBUG #if TCP_DEBUG @@ -309,7 +291,6 @@ tcp_input(struct pbuf *p, struct netif *inp) /* Set up a tcp_seg structure. */ inseg.next = NULL; inseg.len = p->tot_len; - inseg.dataptr = p->payload; inseg.p = p; inseg.tcphdr = tcphdr; @@ -317,18 +298,16 @@ tcp_input(struct pbuf *p, struct netif *inp) recv_flags = 0; /* If there is data which was previously "refused" by upper layer */ - if (pcb->refused_data != NULL) - { + if (pcb->refused_data != NULL) { /* Notify again application with data previously received. */ LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: notify kept packet\n")); TCP_EVENT_RECV(pcb, pcb->refused_data, ERR_OK, err); if (err == ERR_OK) { pcb->refused_data = NULL; - } - else - { + } else if ((err == ERR_ABRT) || (tcplen > 0)) { /* if err == ERR_ABRT, 'pcb' is already deallocated */ - /* drop incoming packets, because pcb is "full" */ + /* Drop incoming packets because pcb is "full" (only if the incoming + segment contains data). */ LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: drop incoming packets, because pcb is \"full\"\n")); TCP_STATS_INC(tcp.drop); snmp_inc_tcpinerrs(); @@ -340,10 +319,8 @@ tcp_input(struct pbuf *p, struct netif *inp) err = tcp_process(pcb); /* A return value of ERR_ABRT means that tcp_abort() was called and that the pcb has been freed. If so, we don't do anything. */ - if (err != ERR_ABRT) - { - if (recv_flags & TF_RESET) - { + if (err != ERR_ABRT) { + if (recv_flags & TF_RESET) { /* TF_RESET means that the connection was reset by the other end. We then call the error callback to inform the application that the connection is dead before we @@ -351,54 +328,44 @@ tcp_input(struct pbuf *p, struct netif *inp) TCP_EVENT_ERR(pcb->errf, pcb->callback_arg, ERR_RST); tcp_pcb_remove(&tcp_active_pcbs, pcb); memp_free(MEMP_TCP_PCB, pcb); - } - else if (recv_flags & TF_CLOSED) - { + } else if (recv_flags & TF_CLOSED) { /* The connection has been closed and we will deallocate the PCB. */ tcp_pcb_remove(&tcp_active_pcbs, pcb); memp_free(MEMP_TCP_PCB, pcb); - } - else - { + } else { err = ERR_OK; /* If the application has registered a "sent" function to be called when new send buffer space is available, we call it now. */ - if (pcb->acked > 0) - { + if (pcb->acked > 0) { TCP_EVENT_SENT(pcb, pcb->acked, err); - if (err == ERR_ABRT) - { + if (err == ERR_ABRT) { goto aborted; } } - if (recv_data != NULL) - { - if (pcb->flags & TF_RXCLOSED) - { + if (recv_data != NULL) { + LWIP_ASSERT("pcb->refused_data == NULL", pcb->refused_data == NULL); + if (pcb->flags & TF_RXCLOSED) { /* received data although already closed -> abort (send RST) to notify the remote host that not all data has been processed */ pbuf_free(recv_data); tcp_abort(pcb); goto aborted; } - if (flags & TCP_PSH) - { + if (flags & TCP_PSH) { recv_data->flags |= PBUF_FLAG_PUSH; } /* Notify application that data has been received. */ TCP_EVENT_RECV(pcb, recv_data, ERR_OK, err); - if (err == ERR_ABRT) - { + if (err == ERR_ABRT) { goto aborted; } /* If the upper layer can't receive this data, store it */ - if (err != ERR_OK) - { + if (err != ERR_OK) { pcb->refused_data = recv_data; LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: keep incoming packet, because pcb is \"full\"\n")); } @@ -406,19 +373,14 @@ tcp_input(struct pbuf *p, struct netif *inp) /* If a FIN segment was received, we call the callback function with a NULL buffer to indicate EOF. */ - if (recv_flags & TF_GOT_FIN) - { + if (recv_flags & TF_GOT_FIN) { /* correct rcv_wnd as the application won't call tcp_recved() for the FIN's seqno */ - if (pcb->rcv_wnd != TCP_WND) - { + if (pcb->rcv_wnd != TCP_WND) { pcb->rcv_wnd++; } - TCP_EVENT_CLOSED(pcb, err); - - if (err == ERR_ABRT) - { + if (err == ERR_ABRT) { goto aborted; } } @@ -445,9 +407,7 @@ aborted: pbuf_free(inseg.p); inseg.p = NULL; } - } - else - { + } else { /* If no matching PCB was found, send a TCP RST (reset) to the sender. */ @@ -530,13 +490,10 @@ tcp_listen_input(struct tcp_pcb_listen *pcb) #endif /* LWIP_CALLBACK_API */ /* inherit socket options */ npcb->so_options = pcb->so_options & SOF_INHERITED; - /* Register the new PCB so that we can begin receiving segments for it. */ TCP_REG(&tcp_active_pcbs, npcb); - LWIP_DEBUGF(TCP_DEBUG, ("TCP new pcb created with %"U16_F" -> %"U16_F".\n", npcb->local_port, npcb->remote_port)); - /* Parse any options in the SYN. */ tcp_parseopt(npcb); #if TCP_CALCULATE_EFF_SEND_MSS @@ -620,8 +577,6 @@ tcp_process(struct tcp_pcb *pcb) err = ERR_OK; - LWIP_DEBUGF(TCP_DEBUG, ("[tcp_process] called\n")); - /* Process incoming RST segments. */ if (flags & TCP_RST) { /* First, determine if the reset is acceptable. */ @@ -681,10 +636,6 @@ tcp_process(struct tcp_pcb *pcb) pcb->snd_wl1 = seqno - 1; /* initialise to seqno - 1 to force window update */ pcb->state = ESTABLISHED; - LWIP_DEBUGF(TCP_DEBUG, - ("[tcp_process] (SYN_SENT) TCP connection established %"U16_F" -> %"U16_F"\n", - pcb->local_port , pcb->remote_port)); - #if TCP_CALCULATE_EFF_SEND_MSS pcb->mss = tcp_eff_send_mss(pcb->mss, &(pcb->remote_ip)); #endif /* TCP_CALCULATE_EFF_SEND_MSS */ @@ -732,13 +683,7 @@ tcp_process(struct tcp_pcb *pcb) if (TCP_SEQ_BETWEEN(ackno, pcb->lastack+1, pcb->snd_nxt)) { u16_t old_cwnd; pcb->state = ESTABLISHED; - LWIP_DEBUGF(TCP_DEBUG, - ("[tcp_process] (SYN_RCVD) TCP connection established %"U16_F" -> %"U16_F"\n", - inseg.tcphdr->src, inseg.tcphdr->dest)); - LWIP_DEBUGF(TCP_DEBUG, - ("[tcp_process] (SYN_RCVD) TCP local port = %"U16_F"\n", - pcb->local_port)); - + LWIP_DEBUGF(TCP_DEBUG, ("TCP connection established %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); #if LWIP_CALLBACK_API LWIP_ASSERT("pcb->accept != NULL", pcb->accept != NULL); #endif @@ -909,8 +854,6 @@ tcp_receive(struct tcp_pcb *pcb) u16_t new_tot_len; int found_dupack = 0; - LWIP_DEBUGF(TCP_DEBUG, ("tcp_receive: called\n")); - if (flags & TCP_ACK) { right_wnd_edge = pcb->snd_wnd + pcb->snd_wl2; @@ -1223,9 +1166,6 @@ tcp_receive(struct tcp_pcb *pcb) LWIP_ASSERT("pbuf_header failed", 0); } } - /* KJM following line changed to use p->payload rather than inseg->p->payload - to fix bug #9076 */ - inseg.dataptr = p->payload; inseg.len -= (u16_t)(pcb->rcv_nxt - seqno); inseg.tcphdr->seqno = seqno = pcb->rcv_nxt; } @@ -1536,8 +1476,6 @@ tcp_receive(struct tcp_pcb *pcb) tcp_ack_now(pcb); } } - - LWIP_DEBUGF(TCP_DEBUG, ("tcp_receive: done\n")); } /** diff --git a/lib/drivers/lwip/src/core/tcp_out.c b/lib/drivers/lwip/src/core/tcp_out.c index bbe1d3c9a9a..86e0919531f 100644 --- a/lib/drivers/lwip/src/core/tcp_out.c +++ b/lib/drivers/lwip/src/core/tcp_out.c @@ -166,7 +166,6 @@ tcp_create_segment(struct tcp_pcb *pcb, struct pbuf *p, u8_t flags, u32_t seqno, seg->flags = optflags; seg->next = NULL; seg->p = p; - seg->dataptr = p->payload; seg->len = p->tot_len - optlen; #if TCP_OVERSIZE_DBGCHECK seg->oversize_left = 0; @@ -590,10 +589,6 @@ tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags) seg->chksum_swapped = chksum_swapped; seg->flags |= TF_SEG_DATA_CHECKSUMMED; #endif /* TCP_CHECKSUM_ON_COPY */ - /* Fix dataptr for the nocopy case */ - if ((apiflags & TCP_WRITE_FLAG_COPY) == 0) { - seg->dataptr = (u8_t*)arg + pos; - } /* first segment of to-be-queued data? */ if (queue == NULL) { @@ -773,6 +768,7 @@ tcp_enqueue_flags(struct tcp_pcb *pcb, u8_t flags) TCP_STATS_INC(tcp.memerr); return ERR_MEM; } + LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0); LWIP_ASSERT("tcp_enqueue_flags: invalid segment length", seg->len == 0); LWIP_DEBUGF(TCP_OUTPUT_DEBUG | LWIP_DBG_TRACE, @@ -1067,7 +1063,7 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) /* Add any requested options. NB MSS option is only set on SYN packets, so ignore it here */ - LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)(seg->tcphdr + 1) % 4) == 0); + LWIP_ASSERT("seg->tcphdr not aligned", ((mem_ptr_t)seg->tcphdr % MEM_ALIGNMENT) == 0); opts = (u32_t *)(void *)(seg->tcphdr + 1); if (seg->flags & TF_SEG_OPTS_MSS) { TCP_BUILD_MSS_OPTION(*opts); @@ -1082,6 +1078,12 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) } #endif + /* Set retransmission timer running if it is not currently enabled + This must be set before checking the route. */ + if (pcb->rtime == -1) { + pcb->rtime = 0; + } + /* If we don't have a local IP address, we get one by calling ip_route(). */ if (ip_addr_isany(&(pcb->local_ip))) { @@ -1092,11 +1094,6 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb) ip_addr_copy(pcb->local_ip, netif->ip_addr); } - /* Set retransmission timer running if it is not currently enabled */ - if(pcb->rtime == -1) { - pcb->rtime = 0; - } - if (pcb->rttest == 0) { pcb->rttest = tcp_ticks; pcb->rtseq = ntohl(seg->tcphdr->seqno); @@ -1443,7 +1440,9 @@ tcp_zero_window_probe(struct tcp_pcb *pcb) TCPH_FLAGS_SET(tcphdr, TCP_ACK | TCP_FIN); } else { /* Data segment, copy in one byte from the head of the unacked queue */ - *((char *)p->payload + TCP_HLEN) = *(char *)seg->dataptr; + struct tcp_hdr *thdr = (struct tcp_hdr *)seg->p->payload; + char *d = ((char *)p->payload + TCP_HLEN); + pbuf_copy_partial(seg->p, d, 1, TCPH_HDRLEN(thdr) * 4); } #if CHECKSUM_GEN_TCP diff --git a/lib/drivers/lwip/src/core/timers.c b/lib/drivers/lwip/src/core/timers.c index d28cb0843b1..f0e92ccebe7 100644 --- a/lib/drivers/lwip/src/core/timers.c +++ b/lib/drivers/lwip/src/core/timers.c @@ -42,6 +42,7 @@ #include "lwip/opt.h" #include "lwip/timers.h" +#include "lwip/tcp_impl.h" #if LWIP_TIMERS @@ -49,7 +50,6 @@ #include "lwip/memp.h" #include "lwip/tcpip.h" -#include "lwip/tcp_impl.h" #include "lwip/ip_frag.h" #include "netif/etharp.h" #include "lwip/dhcp.h" diff --git a/lib/drivers/lwip/src/core/udp.c b/lib/drivers/lwip/src/core/udp.c index 97e3f70fae0..4596ba2b79e 100644 --- a/lib/drivers/lwip/src/core/udp.c +++ b/lib/drivers/lwip/src/core/udp.c @@ -520,8 +520,10 @@ udp_sendto_if_chksum(struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *dst_ip, LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_SERIOUS, ("udp_send: could not allocate header\n")); return ERR_MEM; } - /* chain header q in front of given pbuf p */ - pbuf_chain(q, p); + if (p->tot_len != 0) { + /* chain header q in front of given pbuf p (only if p contains data) */ + pbuf_chain(q, p); + } /* first pbuf q points to header pbuf */ LWIP_DEBUGF(UDP_DEBUG, ("udp_send: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p)); @@ -744,8 +746,10 @@ udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port) /* no port specified? */ if (port == 0) { #ifndef UDP_LOCAL_PORT_RANGE_START -#define UDP_LOCAL_PORT_RANGE_START 4096 -#define UDP_LOCAL_PORT_RANGE_END 0x7fff +/* From http://www.iana.org/assignments/port-numbers: + "The Dynamic and/or Private Ports are those from 49152 through 65535" */ +#define UDP_LOCAL_PORT_RANGE_START 0xc000 +#define UDP_LOCAL_PORT_RANGE_END 0xffff #endif port = UDP_LOCAL_PORT_RANGE_START; ipcb = udp_pcbs; diff --git a/lib/drivers/lwip/src/include/ipv4/lwip/icmp.h b/lib/drivers/lwip/src/include/ipv4/lwip/icmp.h index c73961c917d..d47a7d8a2e2 100644 --- a/lib/drivers/lwip/src/include/ipv4/lwip/icmp.h +++ b/lib/drivers/lwip/src/include/ipv4/lwip/icmp.h @@ -41,29 +41,29 @@ extern "C" { #endif -#define ICMP_ER 0 /* echo reply */ -#define ICMP_DUR 3 /* destination unreachable */ -#define ICMP_SQ 4 /* source quench */ -#define ICMP_RD 5 /* redirect */ +#define ICMP_ER 0 /* echo reply */ +#define ICMP_DUR 3 /* destination unreachable */ +#define ICMP_SQ 4 /* source quench */ +#define ICMP_RD 5 /* redirect */ #define ICMP_ECHO 8 /* echo */ -#define ICMP_TE 11 /* time exceeded */ -#define ICMP_PP 12 /* parameter problem */ -#define ICMP_TS 13 /* timestamp */ +#define ICMP_TE 11 /* time exceeded */ +#define ICMP_PP 12 /* parameter problem */ +#define ICMP_TS 13 /* timestamp */ #define ICMP_TSR 14 /* timestamp reply */ #define ICMP_IRQ 15 /* information request */ -#define ICMP_IR 16 /* information reply */ +#define ICMP_IR 16 /* information reply */ enum icmp_dur_type { - ICMP_DUR_NET = 0, /* net unreachable */ - ICMP_DUR_HOST = 1, /* host unreachable */ + ICMP_DUR_NET = 0, /* net unreachable */ + ICMP_DUR_HOST = 1, /* host unreachable */ ICMP_DUR_PROTO = 2, /* protocol unreachable */ - ICMP_DUR_PORT = 3, /* port unreachable */ - ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */ - ICMP_DUR_SR = 5 /* source route failed */ + ICMP_DUR_PORT = 3, /* port unreachable */ + ICMP_DUR_FRAG = 4, /* fragmentation needed and DF set */ + ICMP_DUR_SR = 5 /* source route failed */ }; enum icmp_te_type { - ICMP_TE_TTL = 0, /* time to live exceeded in transit */ + ICMP_TE_TTL = 0, /* time to live exceeded in transit */ ICMP_TE_FRAG = 1 /* fragment reassembly time exceeded */ }; diff --git a/lib/drivers/lwip/src/include/ipv4/lwip/ip.h b/lib/drivers/lwip/src/include/ipv4/lwip/ip.h index 296e344bad1..74f501d1ab4 100644 --- a/lib/drivers/lwip/src/include/ipv4/lwip/ip.h +++ b/lib/drivers/lwip/src/include/ipv4/lwip/ip.h @@ -122,10 +122,10 @@ struct ip_hdr { PACK_STRUCT_FIELD(u16_t _id); /* fragment offset field */ PACK_STRUCT_FIELD(u16_t _offset); -#define IP_RF 0x8000 /* reserved fragment flag */ -#define IP_DF 0x4000 /* dont fragment flag */ -#define IP_MF 0x2000 /* more fragments flag */ -#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ +#define IP_RF 0x8000U /* reserved fragment flag */ +#define IP_DF 0x4000U /* dont fragment flag */ +#define IP_MF 0x2000U /* more fragments flag */ +#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ /* time to live */ PACK_STRUCT_FIELD(u8_t _ttl); /* protocol*/ diff --git a/lib/drivers/lwip/src/include/lwip/api.h b/lib/drivers/lwip/src/include/lwip/api.h index 9add7e89eaa..91b9e5d2435 100644 --- a/lib/drivers/lwip/src/include/lwip/api.h +++ b/lib/drivers/lwip/src/include/lwip/api.h @@ -168,12 +168,11 @@ struct netconn { /** maximum amount of bytes queued in recvmbox not used for TCP: adjust TCP_WND instead! */ int recv_bufsize; -#endif /* LWIP_SO_RCVBUF */ /** number of bytes currently in recvmbox to be received, tested against recv_bufsize to limit bytes on recvmbox - for UDP and RAW - @todo: should only be necessary with LWIP_SO_RCVBUF==1 */ + for UDP and RAW, used for FIONREAD */ s16_t recv_avail; +#endif /* LWIP_SO_RCVBUF */ /** flags holding more netconn-internal state, see NETCONN_FLAG_* defines */ u8_t flags; #if LWIP_TCP diff --git a/lib/drivers/lwip/src/include/lwip/api_msg.h b/lib/drivers/lwip/src/include/lwip/api_msg.h index ccb1015f286..f99d8c3b719 100644 --- a/lib/drivers/lwip/src/include/lwip/api_msg.h +++ b/lib/drivers/lwip/src/include/lwip/api_msg.h @@ -48,9 +48,10 @@ extern "C" { #endif +/* For the netconn API, these values are use as a bitmask! */ #define NETCONN_SHUT_RD 1 #define NETCONN_SHUT_WR 2 -#define NETCONN_SHUT_RDWR 3 +#define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) /* IP addresses and port numbers are expected to be in * the same byte order as in the corresponding pcb. diff --git a/lib/drivers/lwip/src/include/lwip/debug.h b/lib/drivers/lwip/src/include/lwip/debug.h index 973f5af4b9a..d8359ea3a53 100644 --- a/lib/drivers/lwip/src/include/lwip/debug.h +++ b/lib/drivers/lwip/src/include/lwip/debug.h @@ -74,8 +74,6 @@ LWIP_PLATFORM_ASSERT(message); handler;}} while(0) #endif /* LWIP_ERROR */ -#define LWIP_DEBUG - #ifdef LWIP_DEBUG /** print debug message only if debug message type is enabled... * AND is of correct type AND is at least LWIP_DBG_LEVEL diff --git a/lib/drivers/lwip/src/include/lwip/dhcp.h b/lib/drivers/lwip/src/include/lwip/dhcp.h index 8767605c988..32d93381d12 100644 --- a/lib/drivers/lwip/src/include/lwip/dhcp.h +++ b/lib/drivers/lwip/src/include/lwip/dhcp.h @@ -106,6 +106,9 @@ PACK_STRUCT_END #endif void dhcp_set_struct(struct netif *netif, struct dhcp *dhcp); +/** Remove a struct dhcp previously set to the netif using dhcp_set_struct() */ +#define dhcp_remove_struct(netif) do { (netif)->dhcp = NULL; } while(0) +void dhcp_cleanup(struct netif *netif); /** start DHCP configuration */ err_t dhcp_start(struct netif *netif); /** enforce early lease renewal (not needed normally)*/ diff --git a/lib/drivers/lwip/src/include/lwip/dns.h b/lib/drivers/lwip/src/include/lwip/dns.h index 6042bf75b0e..6c7d9b07399 100644 --- a/lib/drivers/lwip/src/include/lwip/dns.h +++ b/lib/drivers/lwip/src/include/lwip/dns.h @@ -38,6 +38,10 @@ #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ +#ifdef __cplusplus +extern "C" { +#endif + /** DNS timer period */ #define DNS_TMR_INTERVAL 1000 @@ -111,6 +115,10 @@ int dns_local_removehost(const char *hostname, const ip_addr_t *addr) err_t dns_local_addhost(const char *hostname, const ip_addr_t *addr); #endif /* DNS_LOCAL_HOSTLIST && DNS_LOCAL_HOSTLIST_IS_DYNAMIC */ +#ifdef __cplusplus +} +#endif + #endif /* LWIP_DNS */ #endif /* __LWIP_DNS_H__ */ diff --git a/lib/drivers/lwip/src/include/lwip/err.h b/lib/drivers/lwip/src/include/lwip/err.h index b35ae75f844..ac907729fcd 100644 --- a/lib/drivers/lwip/src/include/lwip/err.h +++ b/lib/drivers/lwip/src/include/lwip/err.h @@ -57,20 +57,19 @@ typedef s8_t err_t; #define ERR_INPROGRESS -5 /* Operation in progress */ #define ERR_VAL -6 /* Illegal value. */ #define ERR_WOULDBLOCK -7 /* Operation would block. */ +#define ERR_USE -8 /* Address in use. */ +#define ERR_ISCONN -9 /* Already connected. */ -#define ERR_IS_FATAL(e) ((e) < ERR_VAL) +#define ERR_IS_FATAL(e) ((e) < ERR_ISCONN) -#define ERR_ABRT -8 /* Connection aborted. */ -#define ERR_RST -9 /* Connection reset. */ -#define ERR_CLSD -10 /* Connection closed. */ -#define ERR_CONN -11 /* Not connected. */ +#define ERR_ABRT -10 /* Connection aborted. */ +#define ERR_RST -11 /* Connection reset. */ +#define ERR_CLSD -12 /* Connection closed. */ +#define ERR_CONN -13 /* Not connected. */ -#define ERR_ARG -12 /* Illegal argument. */ +#define ERR_ARG -14 /* Illegal argument. */ -#define ERR_USE -13 /* Address in use. */ - -#define ERR_IF -14 /* Low-level netif error */ -#define ERR_ISCONN -15 /* Already connected. */ +#define ERR_IF -15 /* Low-level netif error */ #ifdef LWIP_DEBUG diff --git a/lib/drivers/lwip/src/include/lwip/init.h b/lib/drivers/lwip/src/include/lwip/init.h index 1c54d3e5140..77dcdfc7757 100644 --- a/lib/drivers/lwip/src/include/lwip/init.h +++ b/lib/drivers/lwip/src/include/lwip/init.h @@ -47,7 +47,7 @@ extern "C" { /** For release candidates, this is set to 1..254 * For official releases, this is set to 255 (LWIP_RC_RELEASE) * For development versions (CVS), this is set to 0 (LWIP_RC_DEVELOPMENT) */ -#define LWIP_VERSION_RC 1U +#define LWIP_VERSION_RC 255U /** LWIP_VERSION_RC is set to LWIP_RC_RELEASE for official releases */ #define LWIP_RC_RELEASE 255U diff --git a/lib/drivers/lwip/src/include/lwip/mem.h b/lib/drivers/lwip/src/include/lwip/mem.h index e7d8b8baf09..9507c0aec41 100644 --- a/lib/drivers/lwip/src/include/lwip/mem.h +++ b/lib/drivers/lwip/src/include/lwip/mem.h @@ -68,7 +68,7 @@ typedef size_t mem_size_t; /* MEM_SIZE would have to be aligned, but using 64000 here instead of * 65535 leaves some room for alignment... */ -#if MEM_SIZE > 64000l +#if MEM_SIZE > 64000L typedef u32_t mem_size_t; #define MEM_SIZE_F U32_F #else diff --git a/lib/drivers/lwip/src/include/lwip/netdb.h b/lib/drivers/lwip/src/include/lwip/netdb.h index 54a1eb87852..7587e2f2d16 100644 --- a/lib/drivers/lwip/src/include/lwip/netdb.h +++ b/lib/drivers/lwip/src/include/lwip/netdb.h @@ -38,6 +38,10 @@ #include "lwip/inet.h" #include "lwip/sockets.h" +#ifdef __cplusplus +extern "C" { +#endif + /* some rarely used options */ #ifndef LWIP_DNS_API_DECLARE_H_ERRNO #define LWIP_DNS_API_DECLARE_H_ERRNO 1 @@ -111,6 +115,10 @@ int lwip_getaddrinfo(const char *nodename, lwip_getaddrinfo(nodname, servname, hints, res) #endif /* LWIP_COMPAT_SOCKETS */ +#ifdef __cplusplus +} +#endif + #endif /* LWIP_DNS && LWIP_SOCKET */ #endif /* __LWIP_NETDB_H__ */ diff --git a/lib/drivers/lwip/src/include/lwip/opt.h b/lib/drivers/lwip/src/include/lwip/opt.h index c5e3967e81c..a1b876583f1 100644 --- a/lib/drivers/lwip/src/include/lwip/opt.h +++ b/lib/drivers/lwip/src/include/lwip/opt.h @@ -432,11 +432,14 @@ #endif /** - * ARP_QUEUEING==1: Outgoing packets are queued during hardware address - * resolution. + * ARP_QUEUEING==1: Multiple outgoing packets are queued during hardware address + * resolution. By default, only the most recent packet is queued per IP address. + * This is sufficient for most protocols and mainly reduces TCP connection + * startup time. Set this to 1 if you know your application sends more than one + * packet in a row to an IP address that is not in the ARP cache. */ #ifndef ARP_QUEUEING -#define ARP_QUEUEING 1 +#define ARP_QUEUEING 0 #endif /** @@ -954,7 +957,7 @@ * as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */ #ifndef TCP_SND_QUEUELEN -#define TCP_SND_QUEUELEN (4 * (TCP_SND_BUF)/(TCP_MSS)) +#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS)) #endif /** diff --git a/lib/drivers/lwip/src/include/lwip/sockets.h b/lib/drivers/lwip/src/include/lwip/sockets.h index ccc012dbd98..3c8fed24e6e 100644 --- a/lib/drivers/lwip/src/include/lwip/sockets.h +++ b/lib/drivers/lwip/src/include/lwip/sockets.h @@ -59,7 +59,7 @@ struct sockaddr_in { struct sockaddr { u8_t sa_len; u8_t sa_family; - u16_t sa_data[14]; + char sa_data[14]; }; #ifndef socklen_t @@ -280,9 +280,9 @@ typedef struct ip_mreq { #endif #ifndef SHUT_RD - #define SHUT_RD 1 - #define SHUT_WR 2 - #define SHUT_RDWR 3 + #define SHUT_RD 0 + #define SHUT_WR 1 + #define SHUT_RDWR 2 #endif /* FD_SET used for lwip_select */ diff --git a/lib/drivers/lwip/src/include/lwip/tcp.h b/lib/drivers/lwip/src/include/lwip/tcp.h index a09c5ef7dcb..07dcd10e786 100644 --- a/lib/drivers/lwip/src/include/lwip/tcp.h +++ b/lib/drivers/lwip/src/include/lwip/tcp.h @@ -228,7 +228,7 @@ struct tcp_pcb { u16_t acked; u16_t snd_buf; /* Available buffer space for sending (in bytes). */ -#define TCP_SNDQUEUELEN_OVERFLOW (0xffff-3) +#define TCP_SNDQUEUELEN_OVERFLOW (0xffffU-3) u16_t snd_queuelen; /* Available buffer space for sending (in tcp_segs). */ #if TCP_OVERSIZE diff --git a/lib/drivers/lwip/src/include/lwip/tcp_impl.h b/lib/drivers/lwip/src/include/lwip/tcp_impl.h index 320b88ef2a7..b4feec0da19 100644 --- a/lib/drivers/lwip/src/include/lwip/tcp_impl.h +++ b/lib/drivers/lwip/src/include/lwip/tcp_impl.h @@ -278,7 +278,6 @@ PACK_STRUCT_END struct tcp_seg { struct tcp_seg *next; /* used when putting segements on a queue */ struct pbuf *p; /* buffer containing data + TCP header */ - void *dataptr; /* pointer to the TCP data in the pbuf */ u16_t len; /* the TCP length of this segment */ #if TCP_OVERSIZE_DBGCHECK u16_t oversize_left; /* Extra bytes available at the end of the last diff --git a/lib/drivers/lwip/src/include/lwipopts.h b/lib/drivers/lwip/src/include/lwipopts.h index 1fbd4fe7e62..6baab6a4f85 100755 --- a/lib/drivers/lwip/src/include/lwipopts.h +++ b/lib/drivers/lwip/src/include/lwipopts.h @@ -18,6 +18,8 @@ #define ARP_QUEUEING 0 +#define ETH_PAD_SIZE 2 + #define IP_FORWARD 0 #define IP_REASS_MAX_PBUFS 0xFFFFFFFF diff --git a/lib/drivers/lwip/src/include/netif/etharp.h b/lib/drivers/lwip/src/include/netif/etharp.h index a4803ec4dbb..691575fa130 100644 --- a/lib/drivers/lwip/src/include/netif/etharp.h +++ b/lib/drivers/lwip/src/include/netif/etharp.h @@ -94,8 +94,8 @@ PACK_STRUCT_BEGIN * if 'type' in ethernet header is ETHTYPE_VLAN. * See IEEE802.Q */ struct eth_vlan_hdr { - PACK_STRUCT_FIELD(u16_t tpid); PACK_STRUCT_FIELD(u16_t prio_vid); + PACK_STRUCT_FIELD(u16_t tpid); } PACK_STRUCT_STRUCT; PACK_STRUCT_END #ifdef PACK_STRUCT_USE_INCLUDES @@ -134,11 +134,11 @@ PACK_STRUCT_END /** 5 seconds period */ #define ARP_TMR_INTERVAL 5000 -#define ETHTYPE_ARP 0x0806 -#define ETHTYPE_IP 0x0800 -#define ETHTYPE_VLAN 0x8100 -#define ETHTYPE_PPPOEDISC 0x8863 /* PPP Over Ethernet Discovery Stage */ -#define ETHTYPE_PPPOE 0x8864 /* PPP Over Ethernet Session Stage */ +#define ETHTYPE_ARP 0x0806U +#define ETHTYPE_IP 0x0800U +#define ETHTYPE_VLAN 0x8100U +#define ETHTYPE_PPPOEDISC 0x8863U /* PPP Over Ethernet Discovery Stage */ +#define ETHTYPE_PPPOE 0x8864U /* PPP Over Ethernet Session Stage */ /** MEMCPY-like macro to copy to/from struct eth_addr's that are local variables * or known to be 32-bit aligned within the protocol header. */ diff --git a/lib/drivers/lwip/src/netif/etharp.c b/lib/drivers/lwip/src/netif/etharp.c index 8f6872fa2c4..b60dadd0244 100644 --- a/lib/drivers/lwip/src/netif/etharp.c +++ b/lib/drivers/lwip/src/netif/etharp.c @@ -45,9 +45,10 @@ #include "lwip/opt.h" -#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ +#if LWIP_ARP || LWIP_ETHERNET -#include "lwip/inet.h" +#include "lwip/ip_addr.h" +#include "lwip/def.h" #include "lwip/ip.h" #include "lwip/stats.h" #include "lwip/snmp.h" @@ -61,6 +62,11 @@ #include +const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; +const struct eth_addr ethzero = {{0,0,0,0,0,0}}; + +#if LWIP_ARP /* don't build if not configured for use in lwipopts.h */ + /** the time an ARP entry stays valid after its last update, * for ARP_TMR_INTERVAL = 5000, this is * (240 * 5) seconds = 20 minutes. @@ -77,12 +83,6 @@ #define HWTYPE_ETHERNET 1 -#define ARPH_HWLEN(hdr) (ntohs((hdr)->_hwlen_protolen) >> 8) -#define ARPH_PROTOLEN(hdr) (ntohs((hdr)->_hwlen_protolen) & 0xff) - -#define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons(ARPH_PROTOLEN(hdr) | ((len) << 8)) -#define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = htons((len) | (ARPH_HWLEN(hdr) << 8)) - enum etharp_state { ETHARP_STATE_EMPTY = 0, ETHARP_STATE_PENDING, @@ -91,45 +91,49 @@ enum etharp_state { struct etharp_entry { #if ARP_QUEUEING - /** - * Pointer to queue of pending outgoing packets on this ARP entry. - */ + /** Pointer to queue of pending outgoing packets on this ARP entry. */ struct etharp_q_entry *q; -#endif - struct ip_addr ipaddr; +#else /* ARP_QUEUEING */ + /** Pointer to a single pending outgoing packet on this ARP entry. */ + struct pbuf *q; +#endif /* ARP_QUEUEING */ + ip_addr_t ipaddr; struct eth_addr ethaddr; - enum etharp_state state; - u8_t ctime; +#if LWIP_SNMP struct netif *netif; +#endif /* LWIP_SNMP */ + u8_t state; + u8_t ctime; +#if ETHARP_SUPPORT_STATIC_ENTRIES + u8_t static_entry; +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ }; -const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; -const struct eth_addr ethzero = {{0,0,0,0,0,0}}; static struct etharp_entry arp_table[ARP_TABLE_SIZE]; + #if !LWIP_NETIF_HWADDRHINT static u8_t etharp_cached_entry; -#endif +#endif /* !LWIP_NETIF_HWADDRHINT */ -/** - * Try hard to create a new entry - we want the IP address to appear in - * the cache (even if this means removing an active entry or so). */ -#define ETHARP_TRY_HARD 1 -#define ETHARP_FIND_ONLY 2 +/** Try hard to create a new entry - we want the IP address to appear in + the cache (even if this means removing an active entry or so). */ +#define ETHARP_FLAG_TRY_HARD 1 +#define ETHARP_FLAG_FIND_ONLY 2 +#define ETHARP_FLAG_STATIC_ENTRY 4 #if LWIP_NETIF_HWADDRHINT -#define NETIF_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ +#define ETHARP_SET_HINT(netif, hint) if (((netif) != NULL) && ((netif)->addr_hint != NULL)) \ *((netif)->addr_hint) = (hint); -static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif); #else /* LWIP_NETIF_HWADDRHINT */ -static s8_t find_entry(struct ip_addr *ipaddr, u8_t flags); +#define ETHARP_SET_HINT(netif, hint) (etharp_cached_entry = (hint)) #endif /* LWIP_NETIF_HWADDRHINT */ -static err_t update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags); +static err_t update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags); /* Some checks, instead of etharp_init(): */ #if (LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) - #error "If you want to use ARP, ARP_TABLE_SIZE must fit in an s8_t, so, you have to reduce it in your lwipopts.h" + #error "ARP_TABLE_SIZE must fit in an s8_t, you have to reduce it in your lwipopts.h" #endif @@ -153,12 +157,46 @@ free_etharp_q(struct etharp_q_entry *q) memp_free(MEMP_ARP_QUEUE, r); } } -#endif +#else /* ARP_QUEUEING */ + +/** Compatibility define: free the queued pbuf */ +#define free_etharp_q(q) pbuf_free(q) + +#endif /* ARP_QUEUEING */ + +/** Clean up ARP table entries */ +static void +free_entry(int i) +{ + /* remove from SNMP ARP index tree */ + snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); + /* and empty packet queue */ + if (arp_table[i].q != NULL) { + /* remove all queued packets */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); + free_etharp_q(arp_table[i].q); + arp_table[i].q = NULL; + } + /* recycle entry for re-use */ + arp_table[i].state = ETHARP_STATE_EMPTY; +#if ETHARP_SUPPORT_STATIC_ENTRIES + arp_table[i].static_entry = 0; +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ +#ifdef LWIP_DEBUG + /* for debugging, clean out the complete entry */ + arp_table[i].ctime = 0; +#if LWIP_SNMP + arp_table[i].netif = NULL; +#endif /* LWIP_SNMP */ + ip_addr_set_zero(&arp_table[i].ipaddr); + arp_table[i].ethaddr = ethzero; +#endif /* LWIP_DEBUG */ +} /** * Clears expired entries in the ARP table. * - * This function should be called every ETHARP_TMR_INTERVAL microseconds (5 seconds), + * This function should be called every ETHARP_TMR_INTERVAL milliseconds (5 seconds), * in order to expire entries in the ARP table. */ void @@ -169,35 +207,29 @@ etharp_tmr(void) LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer\n")); /* remove expired entries from the ARP table */ for (i = 0; i < ARP_TABLE_SIZE; ++i) { - arp_table[i].ctime++; - if (((arp_table[i].state == ETHARP_STATE_STABLE) && - (arp_table[i].ctime >= ARP_MAXAGE)) || - ((arp_table[i].state == ETHARP_STATE_PENDING) && - (arp_table[i].ctime >= ARP_MAXPENDING))) { - /* pending or stable entry has become old! */ - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", - arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); - /* clean up entries that have just been expired */ - /* remove from SNMP ARP index tree */ - snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); -#if ARP_QUEUEING - /* and empty packet queue */ - if (arp_table[i].q != NULL) { - /* remove all queued packets */ - LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: freeing entry %"U16_F", packet queue %p.\n", (u16_t)i, (void *)(arp_table[i].q))); - free_etharp_q(arp_table[i].q); - arp_table[i].q = NULL; + u8_t state = arp_table[i].state; + if (state != ETHARP_STATE_EMPTY +#if ETHARP_SUPPORT_STATIC_ENTRIES + && (arp_table[i].static_entry == 0) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + ) { + arp_table[i].ctime++; + if ((arp_table[i].ctime >= ARP_MAXAGE) || + ((arp_table[i].state == ETHARP_STATE_PENDING) && + (arp_table[i].ctime >= ARP_MAXPENDING))) { + /* pending or stable entry has become old! */ + LWIP_DEBUGF(ETHARP_DEBUG, ("etharp_timer: expired %s entry %"U16_F".\n", + arp_table[i].state == ETHARP_STATE_STABLE ? "stable" : "pending", (u16_t)i)); + /* clean up entries that have just been expired */ + free_entry(i); } -#endif - /* recycle entry for re-use */ - arp_table[i].state = ETHARP_STATE_EMPTY; - } #if ARP_QUEUEING - /* still pending entry? (not expired) */ - if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* still pending entry? (not expired) */ + if (arp_table[i].state == ETHARP_STATE_PENDING) { /* resend an ARP query here? */ + } +#endif /* ARP_QUEUEING */ } -#endif } } @@ -212,62 +244,26 @@ etharp_tmr(void) * If ipaddr is NULL, return a initialized new entry in state ETHARP_EMPTY. * * In all cases, attempt to create new entries from an empty entry. If no - * empty entries are available and ETHARP_TRY_HARD flag is set, recycle + * empty entries are available and ETHARP_FLAG_TRY_HARD flag is set, recycle * old entries. Heuristic choose the least important entry for recycling. * * @param ipaddr IP address to find in ARP cache, or to add if not found. - * @param flags - * - ETHARP_TRY_HARD: Try hard to create a entry by allowing recycling of - * active (stable or pending) entries. + * @param flags @see definition of ETHARP_FLAG_* + * @param netif netif related to this address (used for NETIF_HWADDRHINT) * * @return The ARP entry index that matched or is created, ERR_MEM if no * entry is found or could be recycled. */ static s8_t -#if LWIP_NETIF_HWADDRHINT -find_entry(struct ip_addr *ipaddr, u8_t flags, struct netif *netif) -#else /* LWIP_NETIF_HWADDRHINT */ -find_entry(struct ip_addr *ipaddr, u8_t flags) -#endif /* LWIP_NETIF_HWADDRHINT */ +find_entry(ip_addr_t *ipaddr, u8_t flags) { s8_t old_pending = ARP_TABLE_SIZE, old_stable = ARP_TABLE_SIZE; s8_t empty = ARP_TABLE_SIZE; u8_t i = 0, age_pending = 0, age_stable = 0; -#if ARP_QUEUEING /* oldest entry with packets on queue */ s8_t old_queue = ARP_TABLE_SIZE; /* its age */ u8_t age_queue = 0; -#endif - - /* First, test if the last call to this function asked for the - * same address. If so, we're really fast! */ - if (ipaddr) { - /* ipaddr to search for was given */ -#if LWIP_NETIF_HWADDRHINT - if ((netif != NULL) && (netif->addr_hint != NULL)) { - /* per-pcb cached entry was given */ - u8_t per_pcb_cache = *(netif->addr_hint); - if ((per_pcb_cache < ARP_TABLE_SIZE) && arp_table[per_pcb_cache].state == ETHARP_STATE_STABLE) { - /* the per-pcb-cached entry is stable */ - if (ip_addr_cmp(ipaddr, &arp_table[per_pcb_cache].ipaddr)) { - /* per-pcb cached entry was the right one! */ - ETHARP_STATS_INC(etharp.cachehit); - return per_pcb_cache; - } - } - } -#else /* #if LWIP_NETIF_HWADDRHINT */ - if (arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) { - /* the cached entry is stable */ - if (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr)) { - /* cached entry was the right one! */ - ETHARP_STATS_INC(etharp.cachehit); - return etharp_cached_entry; - } - } -#endif /* #if LWIP_NETIF_HWADDRHINT */ - } /** * a) do a search through the cache, remember candidates @@ -285,65 +281,59 @@ find_entry(struct ip_addr *ipaddr, u8_t flags) */ for (i = 0; i < ARP_TABLE_SIZE; ++i) { + u8_t state = arp_table[i].state; /* no empty entry found yet and now we do find one? */ - if ((empty == ARP_TABLE_SIZE) && (arp_table[i].state == ETHARP_STATE_EMPTY)) { + if ((empty == ARP_TABLE_SIZE) && (state == ETHARP_STATE_EMPTY)) { LWIP_DEBUGF(ETHARP_DEBUG, ("find_entry: found empty entry %"U16_F"\n", (u16_t)i)); /* remember first empty entry */ empty = i; - } - /* pending entry? */ - else if (arp_table[i].state == ETHARP_STATE_PENDING) { + } else if (state != ETHARP_STATE_EMPTY) { + LWIP_ASSERT("state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE", + state == ETHARP_STATE_PENDING || state == ETHARP_STATE_STABLE); /* if given, does IP address match IP address in ARP entry? */ if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching pending entry %"U16_F"\n", (u16_t)i)); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching entry %"U16_F"\n", (u16_t)i)); /* found exact IP address match, simply bail out */ -#if LWIP_NETIF_HWADDRHINT - NETIF_SET_HINT(netif, i); -#else /* #if LWIP_NETIF_HWADDRHINT */ - etharp_cached_entry = i; -#endif /* #if LWIP_NETIF_HWADDRHINT */ return i; -#if ARP_QUEUEING - /* pending with queued packets? */ - } else if (arp_table[i].q != NULL) { - if (arp_table[i].ctime >= age_queue) { - old_queue = i; - age_queue = arp_table[i].ctime; + } + /* pending entry? */ + if (state == ETHARP_STATE_PENDING) { + /* pending with queued packets? */ + if (arp_table[i].q != NULL) { + if (arp_table[i].ctime >= age_queue) { + old_queue = i; + age_queue = arp_table[i].ctime; + } + } else + /* pending without queued packets? */ + { + if (arp_table[i].ctime >= age_pending) { + old_pending = i; + age_pending = arp_table[i].ctime; + } } -#endif - /* pending without queued packets? */ - } else { - if (arp_table[i].ctime >= age_pending) { - old_pending = i; - age_pending = arp_table[i].ctime; + /* stable entry? */ + } else if (state == ETHARP_STATE_STABLE) { +#if ETHARP_SUPPORT_STATIC_ENTRIES + /* don't record old_stable for static entries since they never expire */ + if (arp_table[i].static_entry == 0) +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + { + /* remember entry with oldest stable entry in oldest, its age in maxtime */ + if (arp_table[i].ctime >= age_stable) { + old_stable = i; + age_stable = arp_table[i].ctime; + } } - } - } - /* stable entry? */ - else if (arp_table[i].state == ETHARP_STATE_STABLE) { - /* if given, does IP address match IP address in ARP entry? */ - if (ipaddr && ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) { - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: found matching stable entry %"U16_F"\n", (u16_t)i)); - /* found exact IP address match, simply bail out */ -#if LWIP_NETIF_HWADDRHINT - NETIF_SET_HINT(netif, i); -#else /* #if LWIP_NETIF_HWADDRHINT */ - etharp_cached_entry = i; -#endif /* #if LWIP_NETIF_HWADDRHINT */ - return i; - /* remember entry with oldest stable entry in oldest, its age in maxtime */ - } else if (arp_table[i].ctime >= age_stable) { - old_stable = i; - age_stable = arp_table[i].ctime; } } } /* { we have no match } => try to create a new entry */ - /* no empty entry found and not allowed to recycle? */ - if (((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_TRY_HARD) == 0)) - /* or don't create new entry, only search? */ - || ((flags & ETHARP_FIND_ONLY) != 0)) { + /* don't create new entry, only search? */ + if (((flags & ETHARP_FLAG_FIND_ONLY) != 0) || + /* or no empty entry found and not allowed to recycle? */ + ((empty == ARP_TABLE_SIZE) && ((flags & ETHARP_FLAG_TRY_HARD) == 0))) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty entry found and not allowed to recycle\n")); return (s8_t)ERR_MEM; } @@ -354,63 +344,55 @@ find_entry(struct ip_addr *ipaddr, u8_t flags) * 3) oldest pending entry without queued packets * 4) oldest pending entry with queued packets * - * { ETHARP_TRY_HARD is set at this point } + * { ETHARP_FLAG_TRY_HARD is set at this point } */ /* 1) empty entry available? */ if (empty < ARP_TABLE_SIZE) { i = empty; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting empty entry %"U16_F"\n", (u16_t)i)); - } - /* 2) found recyclable stable entry? */ - else if (old_stable < ARP_TABLE_SIZE) { - /* recycle oldest stable*/ - i = old_stable; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); -#if ARP_QUEUEING - /* no queued packets should exist on stable entries */ - LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); -#endif - /* 3) found recyclable pending entry without queued packets? */ - } else if (old_pending < ARP_TABLE_SIZE) { - /* recycle oldest pending */ - i = old_pending; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); -#if ARP_QUEUEING - /* 4) found recyclable pending entry with queued packets? */ - } else if (old_queue < ARP_TABLE_SIZE) { - /* recycle oldest pending */ - i = old_queue; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); - free_etharp_q(arp_table[i].q); - arp_table[i].q = NULL; -#endif - /* no empty or recyclable entries found */ } else { - return (s8_t)ERR_MEM; + /* 2) found recyclable stable entry? */ + if (old_stable < ARP_TABLE_SIZE) { + /* recycle oldest stable*/ + i = old_stable; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest stable entry %"U16_F"\n", (u16_t)i)); + /* no queued packets should exist on stable entries */ + LWIP_ASSERT("arp_table[i].q == NULL", arp_table[i].q == NULL); + /* 3) found recyclable pending entry without queued packets? */ + } else if (old_pending < ARP_TABLE_SIZE) { + /* recycle oldest pending */ + i = old_pending; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F" (without queue)\n", (u16_t)i)); + /* 4) found recyclable pending entry with queued packets? */ + } else if (old_queue < ARP_TABLE_SIZE) { + /* recycle oldest pending (queued packets are free in free_entry) */ + i = old_queue; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: selecting oldest pending entry %"U16_F", freeing packet queue %p\n", (u16_t)i, (void *)(arp_table[i].q))); + /* no empty or recyclable entries found */ + } else { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("find_entry: no empty or recyclable entries found\n")); + return (s8_t)ERR_MEM; + } + + /* { empty or recyclable entry found } */ + LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); + free_entry(i); } - /* { empty or recyclable entry found } */ LWIP_ASSERT("i < ARP_TABLE_SIZE", i < ARP_TABLE_SIZE); - - if (arp_table[i].state != ETHARP_STATE_EMPTY) - { - snmp_delete_arpidx_tree(arp_table[i].netif, &arp_table[i].ipaddr); - } - /* recycle entry (no-op for an already empty entry) */ - arp_table[i].state = ETHARP_STATE_EMPTY; + LWIP_ASSERT("arp_table[i].state == ETHARP_STATE_EMPTY", + arp_table[i].state == ETHARP_STATE_EMPTY); /* IP address given? */ if (ipaddr != NULL) { /* set IP address */ - ip_addr_set(&arp_table[i].ipaddr, ipaddr); + ip_addr_copy(arp_table[i].ipaddr, *ipaddr); } arp_table[i].ctime = 0; -#if LWIP_NETIF_HWADDRHINT - NETIF_SET_HINT(netif, i); -#else /* #if LWIP_NETIF_HWADDRHINT */ - etharp_cached_entry = i; -#endif /* #if LWIP_NETIF_HWADDRHINT */ +#if ETHARP_SUPPORT_STATIC_ENTRIES + arp_table[i].static_entry = 0; +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ return (err_t)i; } @@ -427,18 +409,13 @@ find_entry(struct ip_addr *ipaddr, u8_t flags) static err_t etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct eth_addr *dst) { - struct eth_hdr *ethhdr = p->payload; - u8_t k; + struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload; LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", (netif->hwaddr_len == ETHARP_HWADDR_LEN)); - k = ETHARP_HWADDR_LEN; - while(k > 0) { - k--; - ethhdr->dest.addr[k] = dst->addr[k]; - ethhdr->src.addr[k] = src->addr[k]; - } - ethhdr->type = htons(ETHTYPE_IP); + ETHADDR32_COPY(ðhdr->dest, dst); + ETHADDR16_COPY(ðhdr->src, src); + ethhdr->type = PP_HTONS(ETHTYPE_IP); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_send_ip: sending packet %p\n", (void *)p)); /* send the packet */ return netif->linkoutput(netif, p); @@ -450,30 +427,27 @@ etharp_send_ip(struct netif *netif, struct pbuf *p, struct eth_addr *src, struct * If a pending entry is resolved, any queued packets will be sent * at this point. * + * @param netif netif related to this entry (used for NETIF_ADDRHINT) * @param ipaddr IP address of the inserted ARP entry. * @param ethaddr Ethernet address of the inserted ARP entry. - * @param flags Defines behaviour: - * - ETHARP_TRY_HARD Allows ARP to insert this as a new item. If not specified, - * only existing ARP entries will be updated. + * @param flags @see definition of ETHARP_FLAG_* * * @return * - ERR_OK Succesfully updated ARP cache. - * - ERR_MEM If we could not add a new ARP entry when ETHARP_TRY_HARD was set. + * - ERR_MEM If we could not add a new ARP entry when ETHARP_FLAG_TRY_HARD was set. * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. * * @see pbuf_free() */ static err_t -update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *ethaddr, u8_t flags) +update_arp_entry(struct netif *netif, ip_addr_t *ipaddr, struct eth_addr *ethaddr, u8_t flags) { s8_t i; - u8_t k; - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry()\n")); LWIP_ASSERT("netif->hwaddr_len == ETHARP_HWADDR_LEN", netif->hwaddr_len == ETHARP_HWADDR_LEN); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", - ip4_addr1(ipaddr), ip4_addr2(ipaddr), ip4_addr3(ipaddr), ip4_addr4(ipaddr), - ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], - ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], + ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); /* non-unicast address? */ if (ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, netif) || @@ -482,34 +456,36 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e return ERR_ARG; } /* find or create ARP entry */ -#if LWIP_NETIF_HWADDRHINT - i = find_entry(ipaddr, flags, netif); -#else /* LWIP_NETIF_HWADDRHINT */ i = find_entry(ipaddr, flags); -#endif /* LWIP_NETIF_HWADDRHINT */ /* bail out if no entry could be found */ - if (i < 0) + if (i < 0) { return (err_t)i; - + } + +#if ETHARP_SUPPORT_STATIC_ENTRIES + if (flags & ETHARP_FLAG_STATIC_ENTRY) { + /* record static type */ + arp_table[i].static_entry = 1; + } +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + /* mark it stable */ arp_table[i].state = ETHARP_STATE_STABLE; + +#if LWIP_SNMP /* record network interface */ arp_table[i].netif = netif; - +#endif /* LWIP_SNMP */ /* insert in SNMP ARP index tree */ snmp_insert_arpidx_tree(netif, &arp_table[i].ipaddr); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("update_arp_entry: updating stable entry %"S16_F"\n", (s16_t)i)); /* update address */ - k = ETHARP_HWADDR_LEN; - while (k > 0) { - k--; - arp_table[i].ethaddr.addr[k] = ethaddr->addr[k]; - } + ETHADDR32_COPY(&arp_table[i].ethaddr, ethaddr); /* reset time stamp */ arp_table[i].ctime = 0; -#if ARP_QUEUEING /* this is where we will send out queued packets! */ +#if ARP_QUEUEING while (arp_table[i].q != NULL) { struct pbuf *p; /* remember remainder of queue */ @@ -520,15 +496,78 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e p = q->p; /* now queue entry can be freed */ memp_free(MEMP_ARP_QUEUE, q); +#else /* ARP_QUEUEING */ + if (arp_table[i].q != NULL) { + struct pbuf *p = arp_table[i].q; + arp_table[i].q = NULL; +#endif /* ARP_QUEUEING */ /* send the queued IP packet */ etharp_send_ip(netif, p, (struct eth_addr*)(netif->hwaddr), ethaddr); /* free the queued IP packet */ pbuf_free(p); } -#endif return ERR_OK; } +#if ETHARP_SUPPORT_STATIC_ENTRIES +/** Add a new static entry to the ARP table. If an entry exists for the + * specified IP address, this entry is overwritten. + * If packets are queued for the specified IP address, they are sent out. + * + * @param ipaddr IP address for the new static entry + * @param ethaddr ethernet address for the new static entry + * @return @see return values of etharp_add_static_entry + */ +err_t +etharp_add_static_entry(ip_addr_t *ipaddr, struct eth_addr *ethaddr) +{ + struct netif *netif; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_add_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F" - %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr), + ethaddr->addr[0], ethaddr->addr[1], ethaddr->addr[2], + ethaddr->addr[3], ethaddr->addr[4], ethaddr->addr[5])); + + netif = ip_route(ipaddr); + if (netif == NULL) { + return ERR_RTE; + } + + return update_arp_entry(netif, ipaddr, ethaddr, ETHARP_FLAG_TRY_HARD | ETHARP_FLAG_STATIC_ENTRY); +} + +/** Remove a static entry from the ARP table previously added with a call to + * etharp_add_static_entry. + * + * @param ipaddr IP address of the static entry to remove + * @return ERR_OK: entry removed + * ERR_MEM: entry wasn't found + * ERR_ARG: entry wasn't a static entry but a dynamic one + */ +err_t +etharp_remove_static_entry(ip_addr_t *ipaddr) +{ + s8_t i; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_remove_static_entry: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", + ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr), ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr))); + + /* find or create ARP entry */ + i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); + /* bail out if no entry could be found */ + if (i < 0) { + return (err_t)i; + } + + if ((arp_table[i].state != ETHARP_STATE_STABLE) || + (arp_table[i].static_entry == 0)) { + /* entry wasn't a static entry, cannot remove it */ + return ERR_ARG; + } + /* entry found, free it */ + free_entry(i); + return ERR_OK; +} +#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ + /** * Finds (stable) ethernet/IP address pair from ARP table * using interface and IP address index. @@ -541,18 +580,17 @@ update_arp_entry(struct netif *netif, struct ip_addr *ipaddr, struct eth_addr *e * @return table index if found, -1 otherwise */ s8_t -etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr, - struct eth_addr **eth_ret, struct ip_addr **ip_ret) +etharp_find_addr(struct netif *netif, ip_addr_t *ipaddr, + struct eth_addr **eth_ret, ip_addr_t **ip_ret) { s8_t i; + LWIP_ASSERT("eth_ret != NULL && ip_ret != NULL", + eth_ret != NULL && ip_ret != NULL); + LWIP_UNUSED_ARG(netif); -#if LWIP_NETIF_HWADDRHINT - i = find_entry(ipaddr, ETHARP_FIND_ONLY, NULL); -#else /* LWIP_NETIF_HWADDRHINT */ - i = find_entry(ipaddr, ETHARP_FIND_ONLY); -#endif /* LWIP_NETIF_HWADDRHINT */ + i = find_entry(ipaddr, ETHARP_FLAG_FIND_ONLY); if((i >= 0) && arp_table[i].state == ETHARP_STATE_STABLE) { *eth_ret = &arp_table[i].ethaddr; *ip_ret = &arp_table[i].ipaddr; @@ -561,6 +599,7 @@ etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr, return -1; } +#if ETHARP_TRUST_IP_MAC /** * Updates the ARP table using the given IP packet. * @@ -576,35 +615,39 @@ etharp_find_addr(struct netif *netif, struct ip_addr *ipaddr, * * @see pbuf_free() */ -void +static void etharp_ip_input(struct netif *netif, struct pbuf *p) { struct eth_hdr *ethhdr; struct ip_hdr *iphdr; + ip_addr_t iphdr_src; LWIP_ERROR("netif != NULL", (netif != NULL), return;); + /* Only insert an entry if the source IP address of the incoming IP packet comes from a host on the local network. */ - ethhdr = p->payload; + ethhdr = (struct eth_hdr *)p->payload; iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); #if ETHARP_SUPPORT_VLAN - if (ethhdr->type == ETHTYPE_VLAN) { + if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { iphdr = (struct ip_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); } #endif /* ETHARP_SUPPORT_VLAN */ + ip_addr_copy(iphdr_src, iphdr->src); + /* source is not on the local network? */ - if (!ip_addr_netcmp(&(iphdr->src), &(netif->ip_addr), &(netif->netmask))) { + if (!ip_addr_netcmp(&iphdr_src, &(netif->ip_addr), &(netif->netmask))) { /* do nothing */ return; } LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_ip_input: updating ETHARP table.\n")); - /* update ARP table */ - /* @todo We could use ETHARP_TRY_HARD if we think we are going to talk + /* update the source IP address in the cache, if present */ + /* @todo We could use ETHARP_FLAG_TRY_HARD if we think we are going to talk * back soon (for example, if the destination IP address is ours. */ - update_arp_entry(netif, &(iphdr->src), &(ethhdr->src), 0); + update_arp_entry(netif, &iphdr_src, &(ethhdr->src), ETHARP_FLAG_FIND_ONLY); } - +#endif /* ETHARP_TRUST_IP_MAC */ /** * Responds to ARP requests to us. Upon ARP replies to us, add entry to cache @@ -621,21 +664,20 @@ etharp_ip_input(struct netif *netif, struct pbuf *p) * * @see pbuf_free() */ -void +static void etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) { struct etharp_hdr *hdr; struct eth_hdr *ethhdr; /* these are aligned properly, whereas the ARP header fields might not be */ - struct ip_addr sipaddr, dipaddr; - u8_t i; + ip_addr_t sipaddr, dipaddr; u8_t for_us; #if LWIP_AUTOIP const u8_t * ethdst_hwaddr; #endif /* LWIP_AUTOIP */ LWIP_ERROR("netif != NULL", (netif != NULL), return;); - + /* drop short ARP packets: we have to check for p->len instead of p->tot_len here since a struct etharp_hdr is pointed to p->payload, so it musn't be chained! */ if (p->len < SIZEOF_ETHARP_PACKET) { @@ -648,22 +690,22 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) return; } - ethhdr = p->payload; + ethhdr = (struct eth_hdr *)p->payload; hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); #if ETHARP_SUPPORT_VLAN - if (ethhdr->type == ETHTYPE_VLAN) { + if (ethhdr->type == PP_HTONS(ETHTYPE_VLAN)) { hdr = (struct etharp_hdr *)(((u8_t*)ethhdr) + SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR); } #endif /* ETHARP_SUPPORT_VLAN */ /* RFC 826 "Packet Reception": */ - if ((hdr->hwtype != htons(HWTYPE_ETHERNET)) || - (hdr->_hwlen_protolen != htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr))) || - (hdr->proto != htons(ETHTYPE_IP)) || - (ethhdr->type != htons(ETHTYPE_ARP))) { + if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) || + (hdr->hwlen != ETHARP_HWADDR_LEN) || + (hdr->protolen != sizeof(ip_addr_t)) || + (hdr->proto != PP_HTONS(ETHTYPE_IP))) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, - ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", - hdr->hwtype, ARPH_HWLEN(hdr), hdr->proto, ARPH_PROTOLEN(hdr), ethhdr->type)); + ("etharp_arp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n", + hdr->hwtype, hdr->hwlen, hdr->proto, hdr->protolen)); ETHARP_STATS_INC(etharp.proterr); ETHARP_STATS_INC(etharp.drop); pbuf_free(p); @@ -680,32 +722,29 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without * structure packing (not using structure copy which breaks strict-aliasing rules). */ - SMEMCPY(&sipaddr, &hdr->sipaddr, sizeof(sipaddr)); - SMEMCPY(&dipaddr, &hdr->dipaddr, sizeof(dipaddr)); + IPADDR2_COPY(&sipaddr, &hdr->sipaddr); + IPADDR2_COPY(&dipaddr, &hdr->dipaddr); /* this interface is not configured? */ - if (netif->ip_addr.addr == 0) { + if (ip_addr_isany(&netif->ip_addr)) { for_us = 0; } else { /* ARP packet directed to us? */ - for_us = ip_addr_cmp(&dipaddr, &(netif->ip_addr)); + for_us = (u8_t)ip_addr_cmp(&dipaddr, &(netif->ip_addr)); } - /* ARP message directed to us? */ - if (for_us) { - /* add IP address in ARP cache; assume requester wants to talk to us. - * can result in directly sending the queued packets for this host. */ - update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), ETHARP_TRY_HARD); - /* ARP message not directed to us? */ - } else { - /* update the source IP address in the cache, if present */ - update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), 0); - } + /* ARP message directed to us? + -> add IP address in ARP cache; assume requester wants to talk to us, + can result in directly sending the queued packets for this host. + ARP message not directed to us? + -> update the source IP address in the cache, if present */ + update_arp_entry(netif, &sipaddr, &(hdr->shwaddr), + for_us ? ETHARP_FLAG_TRY_HARD : ETHARP_FLAG_FIND_ONLY); /* now act on the message itself */ - switch (htons(hdr->opcode)) { + switch (hdr->opcode) { /* ARP request? */ - case ARP_REQUEST: + case PP_HTONS(ARP_REQUEST): /* ARP request. If it asked for our address, we send out a * reply. In any case, we time-stamp any existing ARP entry, * and possiby send out an IP packet that was queued on it. */ @@ -720,29 +759,26 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) that would allocate a new pbuf. */ hdr->opcode = htons(ARP_REPLY); - hdr->dipaddr = hdr->sipaddr; - SMEMCPY(&hdr->sipaddr, &netif->ip_addr, sizeof(hdr->sipaddr)); + IPADDR2_COPY(&hdr->dipaddr, &hdr->sipaddr); + IPADDR2_COPY(&hdr->sipaddr, &netif->ip_addr); LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", (netif->hwaddr_len == ETHARP_HWADDR_LEN)); - i = ETHARP_HWADDR_LEN; #if LWIP_AUTOIP - /* If we are using Link-Local, ARP packets must be broadcast on the - * link layer. (See RFC3927 Section 2.5) */ - ethdst_hwaddr = ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr; + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + ethdst_hwaddr = ip_addr_islinklocal(&netif->ip_addr) ? (u8_t*)(ethbroadcast.addr) : hdr->shwaddr.addr; #endif /* LWIP_AUTOIP */ - while(i > 0) { - i--; - hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i]; + ETHADDR16_COPY(&hdr->dhwaddr, &hdr->shwaddr); #if LWIP_AUTOIP - ethhdr->dest.addr[i] = ethdst_hwaddr[i]; + ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); #else /* LWIP_AUTOIP */ - ethhdr->dest.addr[i] = hdr->shwaddr.addr[i]; + ETHADDR16_COPY(ðhdr->dest, &hdr->shwaddr); #endif /* LWIP_AUTOIP */ - hdr->shwaddr.addr[i] = ethaddr->addr[i]; - ethhdr->src.addr[i] = ethaddr->addr[i]; - } + ETHADDR16_COPY(&hdr->shwaddr, ethaddr); + ETHADDR16_COPY(ðhdr->src, ethaddr); /* hwtype, hwaddr_len, proto, protolen and the type in the ethernet header are already correct, we tested that before */ @@ -750,7 +786,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) /* return ARP reply */ netif->linkoutput(netif, p); /* we are not configured? */ - } else if (netif->ip_addr.addr == 0) { + } else if (ip_addr_isany(&netif->ip_addr)) { /* { for_us == 0 and netif->ip_addr.addr == 0 } */ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: we are unconfigured, ARP request ignored.\n")); /* request was not directed to us */ @@ -759,7 +795,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP request was not for us.\n")); } break; - case ARP_REPLY: + case PP_HTONS(ARP_REPLY): /* ARP reply. We already updated the ARP cache earlier. */ LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: incoming ARP reply\n")); #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK) @@ -768,7 +804,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) * want to take a duplicate IP address on a single network. * @todo How should we handle redundant (fail-over) interfaces? */ dhcp_arp_reply(netif, &sipaddr); -#endif +#endif /* (LWIP_DHCP && DHCP_DOES_ARP_CHECK) */ break; default: LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_arp_input: ARP unknown opcode type %"S16_F"\n", htons(hdr->opcode))); @@ -798,7 +834,7 @@ etharp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p) * or the return type of either etharp_query() or etharp_send_ip(). */ err_t -etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr) +etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr) { struct eth_addr *dest, mcastaddr; @@ -834,17 +870,46 @@ etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr) /* unicast destination IP address? */ } else { /* outside local network? */ - if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) { - /* interface has default gateway? */ - if (netif->gw.addr != 0) { - /* send to hardware address of default gateway IP address */ - ipaddr = &(netif->gw); - /* no default gateway available */ - } else { - /* no route to destination error (default gateway missing) */ - return ERR_RTE; + if (!ip_addr_netcmp(ipaddr, &(netif->ip_addr), &(netif->netmask)) && + !ip_addr_islinklocal(ipaddr)) { +#if LWIP_AUTOIP + struct ip_hdr *iphdr = (struct ip_hdr*)((u8_t*)q->payload + + sizeof(struct eth_hdr)); + /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with + a link-local source address must always be "directly to its destination + on the same physical link. The host MUST NOT send the packet to any + router for forwarding". */ + if (!ip_addr_islinklocal(&iphdr->src)) +#endif /* LWIP_AUTOIP */ + { + /* interface has default gateway? */ + if (!ip_addr_isany(&netif->gw)) { + /* send to hardware address of default gateway IP address */ + ipaddr = &(netif->gw); + /* no default gateway available */ + } else { + /* no route to destination error (default gateway missing) */ + return ERR_RTE; + } } } +#if LWIP_NETIF_HWADDRHINT + if (netif->addr_hint != NULL) { + /* per-pcb cached entry was given */ + u8_t etharp_cached_entry = *(netif->addr_hint); + if (etharp_cached_entry < ARP_TABLE_SIZE) { +#endif /* LWIP_NETIF_HWADDRHINT */ + if ((arp_table[etharp_cached_entry].state == ETHARP_STATE_STABLE) && + (ip_addr_cmp(ipaddr, &arp_table[etharp_cached_entry].ipaddr))) { + /* the per-pcb-cached entry is stable and the right one! */ + ETHARP_STATS_INC(etharp.cachehit); + return etharp_send_ip(netif, q, (struct eth_addr*)(netif->hwaddr), + &arp_table[etharp_cached_entry].ethaddr); + } +#if LWIP_NETIF_HWADDRHINT + } + } +#endif /* LWIP_NETIF_HWADDRHINT */ /* queue on destination Ethernet address belonging to ipaddr */ return etharp_query(netif, ipaddr, q); } @@ -889,7 +954,7 @@ etharp_output(struct netif *netif, struct pbuf *q, struct ip_addr *ipaddr) * */ err_t -etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) +etharp_query(struct netif *netif, ip_addr_t *ipaddr, struct pbuf *q) { struct eth_addr * srcaddr = (struct eth_addr *)netif->hwaddr; err_t result = ERR_MEM; @@ -904,11 +969,7 @@ etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) } /* find entry in ARP cache, ask to create entry if queueing packet */ -#if LWIP_NETIF_HWADDRHINT - i = find_entry(ipaddr, ETHARP_TRY_HARD, netif); -#else /* LWIP_NETIF_HWADDRHINT */ - i = find_entry(ipaddr, ETHARP_TRY_HARD); -#endif /* LWIP_NETIF_HWADDRHINT */ + i = find_entry(ipaddr, ETHARP_FLAG_TRY_HARD); /* could not find or create entry? */ if (i < 0) { @@ -940,85 +1001,94 @@ etharp_query(struct netif *netif, struct ip_addr *ipaddr, struct pbuf *q) since this failure could be temporary, and the next packet calling etharp_query again could lead to sending the queued packets. */ } + if (q == NULL) { + return result; + } } - + /* packet given? */ - if (q != NULL) { - /* stable entry? */ - if (arp_table[i].state == ETHARP_STATE_STABLE) { - /* we have a valid IP->Ethernet address mapping */ - /* send the packet */ - result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr)); - /* pending entry? (either just created or already pending */ - } else if (arp_table[i].state == ETHARP_STATE_PENDING) { -#if ARP_QUEUEING /* queue the given q packet */ - struct pbuf *p; - int copy_needed = 0; - /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but - * to copy the whole queue into a new PBUF_RAM (see bug #11400) - * PBUF_ROMs can be left as they are, since ROM must not get changed. */ - p = q; - while (p) { - LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); - if(p->type != PBUF_ROM) { - copy_needed = 1; - break; - } - p = p->next; + LWIP_ASSERT("q != NULL", q != NULL); + /* stable entry? */ + if (arp_table[i].state == ETHARP_STATE_STABLE) { + /* we have a valid IP->Ethernet address mapping */ + ETHARP_SET_HINT(netif, i); + /* send the packet */ + result = etharp_send_ip(netif, q, srcaddr, &(arp_table[i].ethaddr)); + /* pending entry? (either just created or already pending */ + } else if (arp_table[i].state == ETHARP_STATE_PENDING) { + /* entry is still pending, queue the given packet 'q' */ + struct pbuf *p; + int copy_needed = 0; + /* IF q includes a PBUF_REF, PBUF_POOL or PBUF_RAM, we have no choice but + * to copy the whole queue into a new PBUF_RAM (see bug #11400) + * PBUF_ROMs can be left as they are, since ROM must not get changed. */ + p = q; + while (p) { + LWIP_ASSERT("no packet queues allowed!", (p->len != p->tot_len) || (p->next == 0)); + if(p->type != PBUF_ROM) { + copy_needed = 1; + break; } - if(copy_needed) { - /* copy the whole packet into new pbufs */ - p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); - if(p != NULL) { - if (pbuf_copy(p, q) != ERR_OK) { - pbuf_free(p); - p = NULL; - } - } - } else { - /* referencing the old pbuf is enough */ - p = q; - pbuf_ref(p); - } - /* packet could be taken over? */ - if (p != NULL) { - /* queue packet ... */ - struct etharp_q_entry *new_entry; - /* allocate a new arp queue entry */ - new_entry = memp_malloc(MEMP_ARP_QUEUE); - if (new_entry != NULL) { - new_entry->next = 0; - new_entry->p = p; - if(arp_table[i].q != NULL) { - /* queue was already existent, append the new entry to the end */ - struct etharp_q_entry *r; - r = arp_table[i].q; - while (r->next != NULL) { - r = r->next; - } - r->next = new_entry; - } else { - /* queue did not exist, first item in queue */ - arp_table[i].q = new_entry; - } - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); - result = ERR_OK; - } else { - /* the pool MEMP_ARP_QUEUE is empty */ + p = p->next; + } + if(copy_needed) { + /* copy the whole packet into new pbufs */ + p = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); + if(p != NULL) { + if (pbuf_copy(p, q) != ERR_OK) { pbuf_free(p); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); - /* { result == ERR_MEM } through initialization */ + p = NULL; } - } else { - ETHARP_STATS_INC(etharp.memerr); - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); - /* { result == ERR_MEM } through initialization */ } -#else /* ARP_QUEUEING == 0 */ - /* q && state == PENDING && ARP_QUEUEING == 0 => result = ERR_MEM */ - /* { result == ERR_MEM } through initialization */ - LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: Ethernet destination address unknown, queueing disabled, packet %p dropped\n", (void *)q)); -#endif + } else { + /* referencing the old pbuf is enough */ + p = q; + pbuf_ref(p); + } + /* packet could be taken over? */ + if (p != NULL) { + /* queue packet ... */ +#if ARP_QUEUEING + struct etharp_q_entry *new_entry; + /* allocate a new arp queue entry */ + new_entry = (struct etharp_q_entry *)memp_malloc(MEMP_ARP_QUEUE); + if (new_entry != NULL) { + new_entry->next = 0; + new_entry->p = p; + if(arp_table[i].q != NULL) { + /* queue was already existent, append the new entry to the end */ + struct etharp_q_entry *r; + r = arp_table[i].q; + while (r->next != NULL) { + r = r->next; + } + r->next = new_entry; + } else { + /* queue did not exist, first item in queue */ + arp_table[i].q = new_entry; + } + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + result = ERR_OK; + } else { + /* the pool MEMP_ARP_QUEUE is empty */ + pbuf_free(p); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; + } +#else /* ARP_QUEUEING */ + /* always queue one packet per ARP request only, freeing a previously queued packet */ + if (arp_table[i].q != NULL) { + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: dropped previously queued packet %p for ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); + pbuf_free(arp_table[i].q); + } + arp_table[i].q = p; + result = ERR_OK; + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: queued packet %p on ARP entry %"S16_F"\n", (void *)q, (s16_t)i)); +#endif /* ARP_QUEUEING */ + } else { + ETHARP_STATS_INC(etharp.memerr); + LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_query: could not queue a copy of PBUF_REF packet %p (out of memory)\n", (void *)q)); + result = ERR_MEM; } } return result; @@ -1045,13 +1115,12 @@ static err_t etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, const struct eth_addr *ethdst_addr, - const struct eth_addr *hwsrc_addr, const struct ip_addr *ipsrc_addr, - const struct eth_addr *hwdst_addr, const struct ip_addr *ipdst_addr, + const struct eth_addr *hwsrc_addr, const ip_addr_t *ipsrc_addr, + const struct eth_addr *hwdst_addr, const ip_addr_t *ipdst_addr, const u16_t opcode) { struct pbuf *p; err_t result = ERR_OK; - u8_t k; /* ARP entry index */ struct eth_hdr *ethhdr; struct etharp_hdr *hdr; #if LWIP_AUTOIP @@ -1070,42 +1139,41 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, LWIP_ASSERT("check that first pbuf can hold struct etharp_hdr", (p->len >= SIZEOF_ETHARP_PACKET)); - ethhdr = p->payload; + ethhdr = (struct eth_hdr *)p->payload; hdr = (struct etharp_hdr *)((u8_t*)ethhdr + SIZEOF_ETH_HDR); LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_raw: sending raw ARP packet.\n")); hdr->opcode = htons(opcode); LWIP_ASSERT("netif->hwaddr_len must be the same as ETHARP_HWADDR_LEN for etharp!", (netif->hwaddr_len == ETHARP_HWADDR_LEN)); - k = ETHARP_HWADDR_LEN; #if LWIP_AUTOIP - /* If we are using Link-Local, ARP packets must be broadcast on the - * link layer. (See RFC3927 Section 2.5) */ - ethdst_hwaddr = ((netif->autoip != NULL) && (netif->autoip->state != AUTOIP_STATE_OFF)) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr; + /* If we are using Link-Local, all ARP packets that contain a Link-Local + * 'sender IP address' MUST be sent using link-layer broadcast instead of + * link-layer unicast. (See RFC3927 Section 2.5, last paragraph) */ + ethdst_hwaddr = ip_addr_islinklocal(ipsrc_addr) ? (u8_t*)(ethbroadcast.addr) : ethdst_addr->addr; #endif /* LWIP_AUTOIP */ - /* Write MAC-Addresses (combined loop for both headers) */ - while(k > 0) { - k--; - /* Write the ARP MAC-Addresses */ - hdr->shwaddr.addr[k] = hwsrc_addr->addr[k]; - hdr->dhwaddr.addr[k] = hwdst_addr->addr[k]; - /* Write the Ethernet MAC-Addresses */ + /* Write the ARP MAC-Addresses */ + ETHADDR16_COPY(&hdr->shwaddr, hwsrc_addr); + ETHADDR16_COPY(&hdr->dhwaddr, hwdst_addr); + /* Write the Ethernet MAC-Addresses */ #if LWIP_AUTOIP - ethhdr->dest.addr[k] = ethdst_hwaddr[k]; + ETHADDR16_COPY(ðhdr->dest, ethdst_hwaddr); #else /* LWIP_AUTOIP */ - ethhdr->dest.addr[k] = ethdst_addr->addr[k]; + ETHADDR16_COPY(ðhdr->dest, ethdst_addr); #endif /* LWIP_AUTOIP */ - ethhdr->src.addr[k] = ethsrc_addr->addr[k]; - } - hdr->sipaddr = *(struct ip_addr2 *)ipsrc_addr; - hdr->dipaddr = *(struct ip_addr2 *)ipdst_addr; + ETHADDR16_COPY(ðhdr->src, ethsrc_addr); + /* Copy struct ip_addr2 to aligned ip_addr, to support compilers without + * structure packing. */ + IPADDR2_COPY(&hdr->sipaddr, ipsrc_addr); + IPADDR2_COPY(&hdr->dipaddr, ipdst_addr); - hdr->hwtype = htons(HWTYPE_ETHERNET); - hdr->proto = htons(ETHTYPE_IP); - /* set hwlen and protolen together */ - hdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(struct ip_addr)); + hdr->hwtype = PP_HTONS(HWTYPE_ETHERNET); + hdr->proto = PP_HTONS(ETHTYPE_IP); + /* set hwlen and protolen */ + hdr->hwlen = ETHARP_HWADDR_LEN; + hdr->protolen = sizeof(ip_addr_t); - ethhdr->type = htons(ETHTYPE_ARP); + ethhdr->type = PP_HTONS(ETHTYPE_ARP); /* send ARP query */ result = netif->linkoutput(netif, p); ETHARP_STATS_INC(etharp.xmit); @@ -1127,13 +1195,14 @@ etharp_raw(struct netif *netif, const struct eth_addr *ethsrc_addr, * any other err_t on failure */ err_t -etharp_request(struct netif *netif, struct ip_addr *ipaddr) +etharp_request(struct netif *netif, ip_addr_t *ipaddr) { LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, ("etharp_request: sending ARP request.\n")); return etharp_raw(netif, (struct eth_addr *)netif->hwaddr, ðbroadcast, (struct eth_addr *)netif->hwaddr, &netif->ip_addr, ðzero, ipaddr, ARP_REQUEST); } +#endif /* LWIP_ARP */ /** * Process received ethernet frames. Using this function instead of directly @@ -1148,21 +1217,35 @@ ethernet_input(struct pbuf *p, struct netif *netif) { struct eth_hdr* ethhdr; u16_t type; + s16_t ip_hdr_offset = SIZEOF_ETH_HDR; + + if (p->len <= SIZEOF_ETH_HDR) { + /* a packet with only an ethernet header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } /* points to packet payload, which starts with an Ethernet header */ - ethhdr = p->payload; + ethhdr = (struct eth_hdr *)p->payload; LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE, - ("ethernet_input: dest:%02x:%02x:%02x:%02x:%02x:%02x, src:%02x:%02x:%02x:%02x:%02x:%02x, type:%2hx\n", + ("ethernet_input: dest:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", src:%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F":%"X8_F", type:%"X16_F"\n", (unsigned)ethhdr->dest.addr[0], (unsigned)ethhdr->dest.addr[1], (unsigned)ethhdr->dest.addr[2], (unsigned)ethhdr->dest.addr[3], (unsigned)ethhdr->dest.addr[4], (unsigned)ethhdr->dest.addr[5], (unsigned)ethhdr->src.addr[0], (unsigned)ethhdr->src.addr[1], (unsigned)ethhdr->src.addr[2], (unsigned)ethhdr->src.addr[3], (unsigned)ethhdr->src.addr[4], (unsigned)ethhdr->src.addr[5], (unsigned)htons(ethhdr->type))); - type = htons(ethhdr->type); + type = ethhdr->type; #if ETHARP_SUPPORT_VLAN - if (type == ETHTYPE_VLAN) { + if (type == PP_HTONS(ETHTYPE_VLAN)) { struct eth_vlan_hdr *vlan = (struct eth_vlan_hdr*)(((char*)ethhdr) + SIZEOF_ETH_HDR); + if (p->len <= SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR) { + /* a packet with only an ethernet/vlan header (or less) is not valid for us */ + ETHARP_STATS_INC(etharp.proterr); + ETHARP_STATS_INC(etharp.drop); + goto free_and_return; + } #ifdef ETHARP_VLAN_CHECK /* if not, allow all VLANs */ if (VLAN_ID(vlan) != ETHARP_VLAN_CHECK) { /* silently ignore this packet: not for our VLAN */ @@ -1170,39 +1253,50 @@ ethernet_input(struct pbuf *p, struct netif *netif) return ERR_OK; } #endif /* ETHARP_VLAN_CHECK */ - type = htons(vlan->tpid); + type = vlan->tpid; + ip_hdr_offset = SIZEOF_ETH_HDR + SIZEOF_VLAN_HDR; } #endif /* ETHARP_SUPPORT_VLAN */ +#if LWIP_ARP_FILTER_NETIF + netif = LWIP_ARP_FILTER_NETIF_FN(p, netif, htons(type)); +#endif /* LWIP_ARP_FILTER_NETIF*/ + switch (type) { +#if LWIP_ARP /* IP packet? */ - case ETHTYPE_IP: + case PP_HTONS(ETHTYPE_IP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } #if ETHARP_TRUST_IP_MAC /* update ARP table */ etharp_ip_input(netif, p); #endif /* ETHARP_TRUST_IP_MAC */ /* skip Ethernet header */ - if(pbuf_header(p, -(s16_t)SIZEOF_ETH_HDR)) { + if(pbuf_header(p, -ip_hdr_offset)) { LWIP_ASSERT("Can't move over header in packet", 0); - pbuf_free(p); - p = NULL; + goto free_and_return; } else { /* pass to IP layer */ ip_input(p, netif); } break; - case ETHTYPE_ARP: + case PP_HTONS(ETHTYPE_ARP): + if (!(netif->flags & NETIF_FLAG_ETHARP)) { + goto free_and_return; + } /* pass p to ARP module */ etharp_arp_input(netif, (struct eth_addr*)(netif->hwaddr), p); break; - +#endif /* LWIP_ARP */ #if PPPOE_SUPPORT - case ETHTYPE_PPPOEDISC: /* PPP Over Ethernet Discovery Stage */ + case PP_HTONS(ETHTYPE_PPPOEDISC): /* PPP Over Ethernet Discovery Stage */ pppoe_disc_input(netif, p); break; - case ETHTYPE_PPPOE: /* PPP Over Ethernet Session Stage */ + case PP_HTONS(ETHTYPE_PPPOE): /* PPP Over Ethernet Session Stage */ pppoe_data_input(netif, p); break; #endif /* PPPOE_SUPPORT */ @@ -1210,13 +1304,15 @@ ethernet_input(struct pbuf *p, struct netif *netif) default: ETHARP_STATS_INC(etharp.proterr); ETHARP_STATS_INC(etharp.drop); - pbuf_free(p); - p = NULL; - break; + goto free_and_return; } /* This means the pbuf is freed or consumed, so the caller doesn't have to free it again */ return ERR_OK; + +free_and_return: + pbuf_free(p); + return ERR_OK; } -#endif /* LWIP_ARP */ +#endif /* LWIP_ARP || LWIP_ETHERNET */ diff --git a/lib/drivers/lwip/src/netif/ppp/auth.c b/lib/drivers/lwip/src/netif/ppp/auth.c index cbd3eb21b0b..c3c49d22a25 100644 --- a/lib/drivers/lwip/src/netif/ppp/auth.c +++ b/lib/drivers/lwip/src/netif/ppp/auth.c @@ -82,65 +82,18 @@ #include "cbcp.h" #endif /* CBCP_SUPPORT */ +#include "lwip/inet.h" + #include -/*************************/ -/*** LOCAL DEFINITIONS ***/ -/*************************/ +#if 0 /* UNUSED */ +/* Bits in scan_authfile return value */ +#define NONWILD_SERVER 1 +#define NONWILD_CLIENT 2 -/* Bits in auth_pending[] */ -#define PAP_WITHPEER 1 -#define PAP_PEER 2 -#define CHAP_WITHPEER 4 -#define CHAP_PEER 8 +#define ISWILD(word) (word[0] == '*' && word[1] == 0) +#endif /* UNUSED */ - -/************************/ -/*** LOCAL DATA TYPES ***/ -/************************/ -/* Used for storing a sequence of words. Usually malloced. */ -struct wordlist { - struct wordlist *next; - char word[1]; -}; - - -/***********************************/ -/*** LOCAL FUNCTION DECLARATIONS ***/ -/***********************************/ -extern char *crypt (const char *, const char *); - -/* Prototypes for procedures local to this file. */ - -static void network_phase (int); -static void check_idle (void *); -static void connect_time_expired (void *); -#if 0 -static int login (char *, char *, char **, int *); -#endif -static void logout (void); -static int null_login (int); -static int get_pap_passwd (int, char *, char *); -static int have_pap_secret (void); -static int have_chap_secret (char *, char *, u32_t); -static int ip_addr_check (u32_t, struct wordlist *); -#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ -static void set_allowed_addrs(int unit, struct wordlist *addrs); -static void free_wordlist (struct wordlist *); -#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ -#if CBCP_SUPPORT -static void callback_phase (int); -#endif /* CBCP_SUPPORT */ - - -/******************************/ -/*** PUBLIC DATA STRUCTURES ***/ -/******************************/ - - -/*****************************/ -/*** LOCAL DATA STRUCTURES ***/ -/*****************************/ #if PAP_SUPPORT || CHAP_SUPPORT /* The name by which the peer authenticated itself to us. */ static char peer_authname[MAXNAMELEN]; @@ -149,15 +102,24 @@ static char peer_authname[MAXNAMELEN]; /* Records which authentication operations haven't completed yet. */ static int auth_pending[NUM_PPP]; -/* Set if we have successfully called login() */ +/* Set if we have successfully called plogin() */ static int logged_in; /* Set if we have run the /etc/ppp/auth-up script. */ -static int did_authup; +static int did_authup; /* @todo, we don't need this in lwip*/ /* List of addresses which the peer may use. */ static struct wordlist *addresses[NUM_PPP]; +#if 0 /* UNUSED */ +/* Wordlist giving addresses which the peer may use + without authenticating itself. */ +static struct wordlist *noauth_addrs; + +/* Extra options to apply, from the secrets file entry for the peer. */ +static struct wordlist *extra_options; +#endif /* UNUSED */ + /* Number of network protocols which we have opened. */ static int num_np_open; @@ -169,10 +131,244 @@ static int num_np_up; static int passwd_from_file; #endif /* PAP_SUPPORT || CHAP_SUPPORT */ +#if 0 /* UNUSED */ +/* Set if we require authentication only because we have a default route. */ +static bool default_auth; + +/* Hook to enable a plugin to control the idle time limit */ +int (*idle_time_hook) __P((struct ppp_idle *)) = NULL; + +/* Hook for a plugin to say whether we can possibly authenticate any peer */ +int (*pap_check_hook) __P((void)) = NULL; + +/* Hook for a plugin to check the PAP user and password */ +int (*pap_auth_hook) __P((char *user, char *passwd, char **msgp, + struct wordlist **paddrs, + struct wordlist **popts)) = NULL; + +/* Hook for a plugin to know about the PAP user logout */ +void (*pap_logout_hook) __P((void)) = NULL; + +/* Hook for a plugin to get the PAP password for authenticating us */ +int (*pap_passwd_hook) __P((char *user, char *passwd)) = NULL; + +/* + * This is used to ensure that we don't start an auth-up/down + * script while one is already running. + */ +enum script_state { + s_down, + s_up +}; + +static enum script_state auth_state = s_down; +static enum script_state auth_script_state = s_down; +static pid_t auth_script_pid = 0; + +/* + * Option variables. + * lwip: some of these are present in the ppp_settings structure + */ +bool uselogin = 0; /* Use /etc/passwd for checking PAP */ +bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */ +bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */ +bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */ +bool usehostname = 0; /* Use hostname for our_name */ +bool auth_required = 0; /* Always require authentication from peer */ +bool allow_any_ip = 0; /* Allow peer to use any IP address */ +bool explicit_remote = 0; /* User specified explicit remote name */ +char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ + +#endif /* UNUSED */ + +/* Bits in auth_pending[] */ +#define PAP_WITHPEER 1 +#define PAP_PEER 2 +#define CHAP_WITHPEER 4 +#define CHAP_PEER 8 + +/* @todo, move this somewhere */ +/* Used for storing a sequence of words. Usually malloced. */ +struct wordlist { + struct wordlist *next; + char word[1]; +}; + + +extern char *crypt (const char *, const char *); + +/* Prototypes for procedures local to this file. */ + +static void network_phase (int); +static void check_idle (void *); +static void connect_time_expired (void *); +#if 0 +static int plogin (char *, char *, char **, int *); +#endif +static void plogout (void); +static int null_login (int); +static int get_pap_passwd (int, char *, char *); +static int have_pap_secret (void); +static int have_chap_secret (char *, char *, u32_t); +static int ip_addr_check (u32_t, struct wordlist *); + +#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ +static int scan_authfile (FILE *, char *, char *, char *, + struct wordlist **, struct wordlist **, + char *); +static void free_wordlist (struct wordlist *); +static void auth_script (char *); +static void auth_script_done (void *); +static void set_allowed_addrs (int unit, struct wordlist *addrs); +static int some_ip_ok (struct wordlist *); +static int setupapfile (char **); +static int privgroup (char **); +static int set_noauth_addr (char **); +static void check_access (FILE *, char *); +#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ + +#if 0 /* UNUSED */ +/* + * Authentication-related options. + */ +option_t auth_options[] = { + { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", 1, &auth_required }, + { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, + "Require PAP authentication from peer", 1, &auth_required }, + { "refuse-pap", o_bool, &refuse_pap, + "Don't agree to auth to peer with PAP", 1 }, + { "-pap", o_bool, &refuse_pap, + "Don't allow PAP authentication with peer", 1 }, + { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap, + "Require CHAP authentication from peer", 1, &auth_required }, + { "+chap", o_bool, &lcp_wantoptions[0].neg_chap, + "Require CHAP authentication from peer", 1, &auth_required }, + { "refuse-chap", o_bool, &refuse_chap, + "Don't agree to auth to peer with CHAP", 1 }, + { "-chap", o_bool, &refuse_chap, + "Don't allow CHAP authentication with peer", 1 }, + { "name", o_string, our_name, + "Set local name for authentication", + OPT_PRIV|OPT_STATIC, NULL, MAXNAMELEN }, + { "user", o_string, user, + "Set name for auth with peer", OPT_STATIC, NULL, MAXNAMELEN }, + { "usehostname", o_bool, &usehostname, + "Must use hostname for authentication", 1 }, + { "remotename", o_string, remote_name, + "Set remote name for authentication", OPT_STATIC, + &explicit_remote, MAXNAMELEN }, + { "auth", o_bool, &auth_required, + "Require authentication from peer", 1 }, + { "noauth", o_bool, &auth_required, + "Don't require peer to authenticate", OPT_PRIV, &allow_any_ip }, + { "login", o_bool, &uselogin, + "Use system password database for PAP", 1 }, + { "papcrypt", o_bool, &cryptpap, + "PAP passwords are encrypted", 1 }, + { "+ua", o_special, (void *)setupapfile, + "Get PAP user and password from file" }, + { "password", o_string, passwd, + "Password for authenticating us to the peer", OPT_STATIC, + NULL, MAXSECRETLEN }, + { "privgroup", o_special, (void *)privgroup, + "Allow group members to use privileged options", OPT_PRIV }, + { "allow-ip", o_special, (void *)set_noauth_addr, + "Set IP address(es) which can be used without authentication", + OPT_PRIV }, + { NULL } +}; +#endif /* UNUSED */ +#if 0 /* UNUSED */ +/* + * setupapfile - specifies UPAP info for authenticating with peer. + */ +static int +setupapfile(char **argv) +{ + FILE * ufile; + int l; + + lcp_allowoptions[0].neg_upap = 1; + + /* open user info file */ + seteuid(getuid()); + ufile = fopen(*argv, "r"); + seteuid(0); + if (ufile == NULL) { + option_error("unable to open user login data file %s", *argv); + return 0; + } + check_access(ufile, *argv); + + /* get username */ + if (fgets(user, MAXNAMELEN - 1, ufile) == NULL + || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){ + option_error("unable to read user login data file %s", *argv); + return 0; + } + fclose(ufile); + + /* get rid of newlines */ + l = strlen(user); + if (l > 0 && user[l-1] == '\n') + user[l-1] = 0; + l = strlen(passwd); + if (l > 0 && passwd[l-1] == '\n') + passwd[l-1] = 0; + + return (1); +} +#endif /* UNUSED */ + +#if 0 /* UNUSED */ +/* + * privgroup - allow members of the group to have privileged access. + */ +static int +privgroup(char **argv) +{ + struct group *g; + int i; + + g = getgrnam(*argv); + if (g == 0) { + option_error("group %s is unknown", *argv); + return 0; + } + for (i = 0; i < ngroups; ++i) { + if (groups[i] == g->gr_gid) { + privileged = 1; + break; + } + } + return 1; +} +#endif + +#if 0 /* UNUSED */ +/* + * set_noauth_addr - set address(es) that can be used without authentication. + * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets. + */ +static int +set_noauth_addr(char **argv) +{ + char *addr = *argv; + int l = strlen(addr); + struct wordlist *wp; + + wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l + 1); + if (wp == NULL) + novm("allow-ip argument"); + wp->word = (char *) (wp + 1); + wp->next = noauth_addrs; + BCOPY(addr, wp->word, l); + noauth_addrs = wp; + return 1; +} +#endif /* UNUSED */ -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ /* * An Open on LCP has requested a change from Dead to Establish phase. * Do what's necessary to bring the physical layer up. @@ -182,7 +378,7 @@ link_required(int unit) { LWIP_UNUSED_ARG(unit); - AUTHDEBUG((LOG_INFO, "link_required: %d\n", unit)); + AUTHDEBUG(LOG_INFO, ("link_required: %d\n", unit)); } /* @@ -192,15 +388,15 @@ link_required(int unit) void link_terminated(int unit) { - AUTHDEBUG((LOG_INFO, "link_terminated: %d\n", unit)); + AUTHDEBUG(LOG_INFO, ("link_terminated: %d\n", unit)); if (lcp_phase[unit] == PHASE_DEAD) { return; } if (logged_in) { - logout(); + plogout(); } lcp_phase[unit] = PHASE_DEAD; - AUTHDEBUG((LOG_NOTICE, "Connection terminated.\n")); + AUTHDEBUG(LOG_NOTICE, ("Connection terminated.\n")); pppLinkTerminated(unit); } @@ -212,8 +408,9 @@ link_down(int unit) { int i; struct protent *protp; - - AUTHDEBUG((LOG_INFO, "link_down: %d\n", unit)); + + AUTHDEBUG(LOG_INFO, ("link_down: %d\n", unit)); + if (did_authup) { /* XXX Do link down processing. */ did_authup = 0; @@ -229,8 +426,9 @@ link_down(int unit) (*protp->close)(unit, "LCP down"); } } - num_np_open = 0; - num_np_up = 0; + num_np_open = 0; /* number of network protocols we have opened */ + num_np_up = 0; /* Number of network protocols which have come up */ + if (lcp_phase[unit] != PHASE_DEAD) { lcp_phase[unit] = PHASE_TERMINATE; } @@ -253,7 +451,7 @@ link_established(int unit) lcp_options *ho = &lcp_hisoptions[unit]; #endif /* PAP_SUPPORT || CHAP_SUPPORT */ - AUTHDEBUG((LOG_INFO, "link_established: %d\n", unit)); + AUTHDEBUG(LOG_INFO, ("link_established: unit %d; Lowering up all protocols...\n", unit)); /* * Tell higher-level protocols that LCP is up. */ @@ -269,12 +467,12 @@ link_established(int unit) * of "" and a password of "". If that's not OK, boot it out. */ if (!wo->neg_upap || !null_login(unit)) { - AUTHDEBUG((LOG_WARNING, "peer refused to authenticate\n")); + AUTHDEBUG(LOG_WARNING, ("peer refused to authenticate\n")); lcp_close(unit, "peer refused to authenticate"); return; } } - + lcp_phase[unit] = PHASE_AUTHENTICATE; auth = 0; #if CHAP_SUPPORT @@ -306,7 +504,7 @@ link_established(int unit) if (ppp_settings.passwd[0] == 0) { passwd_from_file = 1; if (!get_pap_passwd(unit, ppp_settings.user, ppp_settings.passwd)) { - AUTHDEBUG((LOG_ERR, "No secret found for PAP login\n")); + AUTHDEBUG(LOG_ERR, ("No secret found for PAP login\n")); } } upap_authwithpeer(unit, ppp_settings.user, ppp_settings.passwd); @@ -320,6 +518,52 @@ link_established(int unit) } } +/* + * Proceed to the network phase. + */ +static void +network_phase(int unit) +{ + int i; + struct protent *protp; + lcp_options *go = &lcp_gotoptions[unit]; + + /* + * If the peer had to authenticate, run the auth-up script now. + */ + if ((go->neg_chap || go->neg_upap) && !did_authup) { + /* XXX Do setup for peer authentication. */ + did_authup = 1; + } + +#if CBCP_SUPPORT + /* + * If we negotiated callback, do it now. + */ + if (go->neg_cbcp) { + lcp_phase[unit] = PHASE_CALLBACK; + (*cbcp_protent.open)(unit); + return; + } +#endif /* CBCP_SUPPORT */ + + lcp_phase[unit] = PHASE_NETWORK; + for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { + if (protp->protocol < 0xC000 && protp->enabled_flag && protp->open != NULL) { + (*protp->open)(unit); + if (protp->protocol != PPP_CCP) { + ++num_np_open; + } + } + } + + if (num_np_open == 0) { + /* nothing to do */ + lcp_close(0, "No network protocols running"); + } +} +/* @todo: add void start_networks(void) here (pppd 2.3.11) */ + /* * The peer has failed to authenticate himself using `protocol'. */ @@ -328,7 +572,7 @@ auth_peer_fail(int unit, u16_t protocol) { LWIP_UNUSED_ARG(protocol); - AUTHDEBUG((LOG_INFO, "auth_peer_fail: %d proto=%X\n", unit, protocol)); + AUTHDEBUG(LOG_INFO, ("auth_peer_fail: %d proto=%X\n", unit, protocol)); /* * Authentication failure: take the link down */ @@ -344,8 +588,8 @@ void auth_peer_success(int unit, u16_t protocol, char *name, int namelen) { int pbit; - - AUTHDEBUG((LOG_INFO, "auth_peer_success: %d proto=%X\n", unit, protocol)); + + AUTHDEBUG(LOG_INFO, ("auth_peer_success: %d proto=%X\n", unit, protocol)); switch (protocol) { case PPP_CHAP: pbit = CHAP_PEER; @@ -354,14 +598,14 @@ auth_peer_success(int unit, u16_t protocol, char *name, int namelen) pbit = PAP_PEER; break; default: - AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n", protocol)); + AUTHDEBUG(LOG_WARNING, ("auth_peer_success: unknown protocol %x\n", protocol)); return; } - + /* * Save the authenticated name of the peer for later. */ - if (namelen > sizeof(peer_authname) - 1) { + if (namelen > (int)sizeof(peer_authname) - 1) { namelen = sizeof(peer_authname) - 1; } BCOPY(name, peer_authname, namelen); @@ -383,25 +627,21 @@ void auth_withpeer_fail(int unit, u16_t protocol) { int errCode = PPPERR_AUTHFAIL; - + LWIP_UNUSED_ARG(protocol); - AUTHDEBUG((LOG_INFO, "auth_withpeer_fail: %d proto=%X\n", unit, protocol)); + AUTHDEBUG(LOG_INFO, ("auth_withpeer_fail: %d proto=%X\n", unit, protocol)); if (passwd_from_file) { BZERO(ppp_settings.passwd, MAXSECRETLEN); } - /* - * XXX Warning: the unit number indicates the interface which is - * not necessarily the PPP connection. It works here as long - * as we are only supporting PPP interfaces. - */ - pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode); /* * We've failed to authenticate ourselves to our peer. * He'll probably take the link down, and there's not much * we can do except wait for that. */ + pppIOCtl(unit, PPPCTLS_ERRCODE, &errCode); + lcp_close(unit, "Failed to authenticate ourselves to peer"); } /* @@ -411,8 +651,8 @@ void auth_withpeer_success(int unit, u16_t protocol) { int pbit; - - AUTHDEBUG((LOG_INFO, "auth_withpeer_success: %d proto=%X\n", unit, protocol)); + + AUTHDEBUG(LOG_INFO, ("auth_withpeer_success: %d proto=%X\n", unit, protocol)); switch (protocol) { case PPP_CHAP: pbit = CHAP_WITHPEER; @@ -424,10 +664,10 @@ auth_withpeer_success(int unit, u16_t protocol) pbit = PAP_WITHPEER; break; default: - AUTHDEBUG((LOG_WARNING, "auth_peer_success: unknown protocol %x\n", protocol)); + AUTHDEBUG(LOG_WARNING, ("auth_peer_success: unknown protocol %x\n", protocol)); pbit = 0; } - + /* * If there is no more authentication still being done, * proceed to the network (or callback) phase. @@ -448,16 +688,16 @@ np_up(int unit, u16_t proto) LWIP_UNUSED_ARG(unit); LWIP_UNUSED_ARG(proto); - AUTHDEBUG((LOG_INFO, "np_up: %d proto=%X\n", unit, proto)); + AUTHDEBUG(LOG_INFO, ("np_up: %d proto=%X\n", unit, proto)); if (num_np_up == 0) { - AUTHDEBUG((LOG_INFO, "np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit)); + AUTHDEBUG(LOG_INFO, ("np_up: maxconnect=%d idle_time_limit=%d\n",ppp_settings.maxconnect,ppp_settings.idle_time_limit)); /* * At this point we consider that the link has come up successfully. */ if (ppp_settings.idle_time_limit > 0) { TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit); } - + /* * Set a timeout to close the connection once the maximum * connect time has expired. @@ -478,7 +718,7 @@ np_down(int unit, u16_t proto) LWIP_UNUSED_ARG(unit); LWIP_UNUSED_ARG(proto); - AUTHDEBUG((LOG_INFO, "np_down: %d proto=%X\n", unit, proto)); + AUTHDEBUG(LOG_INFO, ("np_down: %d proto=%X\n", unit, proto)); if (--num_np_up == 0 && ppp_settings.idle_time_limit > 0) { UNTIMEOUT(check_idle, NULL); } @@ -493,7 +733,7 @@ np_finished(int unit, u16_t proto) LWIP_UNUSED_ARG(unit); LWIP_UNUSED_ARG(proto); - AUTHDEBUG((LOG_INFO, "np_finished: %d proto=%X\n", unit, proto)); + AUTHDEBUG(LOG_INFO, ("np_finished: %d proto=%X\n", unit, proto)); if (--num_np_open <= 0) { /* no further use for the link: shut up shop. */ lcp_close(0, "No network protocols running"); @@ -501,202 +741,41 @@ np_finished(int unit, u16_t proto) } /* - * auth_reset - called when LCP is starting negotiations to recheck - * authentication options, i.e. whether we have appropriate secrets - * to use for authenticating ourselves and/or the peer. + * check_idle - check whether the link has been idle for long + * enough that we can shut it down. */ -void -auth_reset(int unit) +static void +check_idle(void *arg) { - lcp_options *go = &lcp_gotoptions[unit]; - lcp_options *ao = &lcp_allowoptions[0]; - ipcp_options *ipwo = &ipcp_wantoptions[0]; - u32_t remote; - - AUTHDEBUG((LOG_INFO, "auth_reset: %d\n", unit)); - ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL)); - ao->neg_chap = !ppp_settings.refuse_chap && ppp_settings.passwd[0] != 0 /*have_chap_secret(ppp_settings.user, ppp_settings.remote_name, (u32_t)0)*/; - - if (go->neg_upap && !have_pap_secret()) { - go->neg_upap = 0; - } - if (go->neg_chap) { - remote = ipwo->accept_remote? 0: ipwo->hisaddr; - if (!have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote)) { - go->neg_chap = 0; - } - } -} - -#if PAP_SUPPORT -/* - * check_passwd - Check the user name and passwd against the PAP secrets - * file. If requested, also check against the system password database, - * and login the user if OK. - * - * returns: - * UPAP_AUTHNAK: Authentication failed. - * UPAP_AUTHACK: Authentication succeeded. - * In either case, msg points to an appropriate message. - */ -int -check_passwd( int unit, char *auser, int userlen, char *apasswd, int passwdlen, char **msg, int *msglen) -{ -#if 1 - LWIP_UNUSED_ARG(unit); - LWIP_UNUSED_ARG(auser); - LWIP_UNUSED_ARG(userlen); - LWIP_UNUSED_ARG(apasswd); - LWIP_UNUSED_ARG(passwdlen); - LWIP_UNUSED_ARG(msglen); - *msg = (char *) 0; - return UPAP_AUTHACK; /* XXX Assume all entries OK. */ -#else - int ret = 0; - struct wordlist *addrs = NULL; - char passwd[256], user[256]; - char secret[MAXWORDLEN]; - static u_short attempts = 0; + struct ppp_idle idle; + u_short itime; - /* - * Make copies of apasswd and auser, then null-terminate them. - */ - BCOPY(apasswd, passwd, passwdlen); - passwd[passwdlen] = '\0'; - BCOPY(auser, user, userlen); - user[userlen] = '\0'; - *msg = (char *) 0; - - /* XXX Validate user name and password. */ - ret = UPAP_AUTHACK; /* XXX Assume all entries OK. */ - - if (ret == UPAP_AUTHNAK) { - if (*msg == (char *) 0) { - *msg = "Login incorrect"; - } - *msglen = strlen(*msg); - /* - * Frustrate passwd stealer programs. - * Allow 10 tries, but start backing off after 3 (stolen from login). - * On 10'th, drop the connection. - */ - if (attempts++ >= 10) { - AUTHDEBUG((LOG_WARNING, "%d LOGIN FAILURES BY %s\n", attempts, user)); - /*ppp_panic("Excess Bad Logins");*/ - } - if (attempts > 3) { - sys_msleep((attempts - 3) * 5); - } - if (addrs != NULL) { - free_wordlist(addrs); - } + LWIP_UNUSED_ARG(arg); + if (!get_idle_time(0, &idle)) { + return; + } + itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); + if (itime >= ppp_settings.idle_time_limit) { + /* link is idle: shut it down. */ + AUTHDEBUG(LOG_INFO, ("Terminating connection due to lack of activity.\n")); + lcp_close(0, "Link inactive"); } else { - attempts = 0; /* Reset count */ - if (*msg == (char *) 0) { - *msg = "Login ok"; - } - *msglen = strlen(*msg); - set_allowed_addrs(unit, addrs); + TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime); } - - BZERO(passwd, sizeof(passwd)); - BZERO(secret, sizeof(secret)); - - return ret; -#endif -} -#endif /* PAP_SUPPORT */ - - -/* - * auth_ip_addr - check whether the peer is authorized to use - * a given IP address. Returns 1 if authorized, 0 otherwise. - */ -int -auth_ip_addr(int unit, u32_t addr) -{ - return ip_addr_check(addr, addresses[unit]); } /* - * bad_ip_adrs - return 1 if the IP address is one we don't want - * to use, such as an address in the loopback net or a multicast address. - * addr is in network byte order. + * connect_time_expired - log a message and close the connection. */ -int -bad_ip_adrs(u32_t addr) +static void +connect_time_expired(void *arg) { - addr = ntohl(addr); - return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET - || IN_MULTICAST(addr) || IN_BADCLASS(addr); + LWIP_UNUSED_ARG(arg); + + AUTHDEBUG(LOG_INFO, ("Connect time expired\n")); + lcp_close(0, "Connect time expired"); /* Close connection */ } - -#if CHAP_SUPPORT -/* - * get_secret - open the CHAP secret file and return the secret - * for authenticating the given client on the given server. - * (We could be either client or server). - */ -int get_secret( int unit, char *client, char *server, char *secret, int *secret_len, int save_addrs) -{ -#if 1 - int len; - struct wordlist *addrs; - - LWIP_UNUSED_ARG(unit); - LWIP_UNUSED_ARG(server); - LWIP_UNUSED_ARG(save_addrs); - - addrs = NULL; - - if(!client || !client[0] || strcmp(client, ppp_settings.user)) { - return 0; - } - - len = strlen(ppp_settings.passwd); - if (len > MAXSECRETLEN) { - AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server)); - len = MAXSECRETLEN; - } - - BCOPY(ppp_settings.passwd, secret, len); - *secret_len = len; - - return 1; -#else - int ret = 0, len; - struct wordlist *addrs; - char secbuf[MAXWORDLEN]; - - addrs = NULL; - secbuf[0] = 0; - - /* XXX Find secret. */ - if (ret < 0) { - return 0; - } - - if (save_addrs) { - set_allowed_addrs(unit, addrs); - } - - len = strlen(secbuf); - if (len > MAXSECRETLEN) { - AUTHDEBUG((LOG_ERR, "Secret for %s on %s is too long\n", client, server)); - len = MAXSECRETLEN; - } - - BCOPY(secbuf, secret, len); - BZERO(secbuf, sizeof(secbuf)); - *secret_len = len; - - return 1; -#endif -} -#endif /* CHAP_SUPPORT */ - - #if 0 /* UNUSED */ /* * auth_check_options - called to check authentication options. @@ -738,96 +817,135 @@ auth_check_options(void) ppp_panic("No auth secret"); } } -#endif +#endif /* UNUSED */ - -/**********************************/ -/*** LOCAL FUNCTION DEFINITIONS ***/ -/**********************************/ /* - * Proceed to the network phase. + * auth_reset - called when LCP is starting negotiations to recheck + * authentication options, i.e. whether we have appropriate secrets + * to use for authenticating ourselves and/or the peer. */ -static void -network_phase(int unit) +void +auth_reset(int unit) { - int i; - struct protent *protp; lcp_options *go = &lcp_gotoptions[unit]; - - /* - * If the peer had to authenticate, run the auth-up script now. - */ - if ((go->neg_chap || go->neg_upap) && !did_authup) { - /* XXX Do setup for peer authentication. */ - did_authup = 1; - } + lcp_options *ao = &lcp_allowoptions[0]; + ipcp_options *ipwo = &ipcp_wantoptions[0]; + u32_t remote; -#if CBCP_SUPPORT - /* - * If we negotiated callback, do it now. - */ - if (go->neg_cbcp) { - lcp_phase[unit] = PHASE_CALLBACK; - (*cbcp_protent.open)(unit); - return; - } -#endif /* CBCP_SUPPORT */ + AUTHDEBUG(LOG_INFO, ("auth_reset: %d\n", unit)); + ao->neg_upap = !ppp_settings.refuse_pap && (ppp_settings.passwd[0] != 0 || get_pap_passwd(unit, NULL, NULL)); + ao->neg_chap = !ppp_settings.refuse_chap && ppp_settings.passwd[0] != 0 /*have_chap_secret(ppp_settings.user, ppp_settings.remote_name, (u32_t)0)*/; - lcp_phase[unit] = PHASE_NETWORK; - for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { - if (protp->protocol < 0xC000 && protp->enabled_flag && protp->open != NULL) { - (*protp->open)(unit); - if (protp->protocol != PPP_CCP) { - ++num_np_open; - } + if (go->neg_upap && !have_pap_secret()) { + go->neg_upap = 0; + } + if (go->neg_chap) { + remote = ipwo->accept_remote? 0: ipwo->hisaddr; + if (!have_chap_secret(ppp_settings.remote_name, ppp_settings.our_name, remote)) { + go->neg_chap = 0; } } - - if (num_np_open == 0) { - /* nothing to do */ - lcp_close(0, "No network protocols running"); - } } +#if PAP_SUPPORT /* - * check_idle - check whether the link has been idle for long - * enough that we can shut it down. + * check_passwd - Check the user name and passwd against the PAP secrets + * file. If requested, also check against the system password database, + * and login the user if OK. + * + * returns: + * UPAP_AUTHNAK: Authentication failed. + * UPAP_AUTHACK: Authentication succeeded. + * In either case, msg points to an appropriate message. */ -static void -check_idle(void *arg) +u_char +check_passwd( int unit, char *auser, int userlen, char *apasswd, int passwdlen, char **msg, int *msglen) { - struct ppp_idle idle; - u_short itime; +#if 1 /* XXX Assume all entries OK. */ + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(auser); + LWIP_UNUSED_ARG(userlen); + LWIP_UNUSED_ARG(apasswd); + LWIP_UNUSED_ARG(passwdlen); + LWIP_UNUSED_ARG(msglen); + *msg = (char *) 0; + return UPAP_AUTHACK; /* XXX Assume all entries OK. */ +#else + u_char ret = 0; + struct wordlist *addrs = NULL; + char passwd[256], user[256]; + char secret[MAXWORDLEN]; + static u_short attempts = 0; - LWIP_UNUSED_ARG(arg); - if (!get_idle_time(0, &idle)) { - return; - } - itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle); - if (itime >= ppp_settings.idle_time_limit) { - /* link is idle: shut it down. */ - AUTHDEBUG((LOG_INFO, "Terminating connection due to lack of activity.\n")); - lcp_close(0, "Link inactive"); + /* + * Make copies of apasswd and auser, then null-terminate them. + */ + BCOPY(apasswd, passwd, passwdlen); + passwd[passwdlen] = '\0'; + BCOPY(auser, user, userlen); + user[userlen] = '\0'; + *msg = (char *) 0; + + /* XXX Validate user name and password. */ + ret = UPAP_AUTHACK; /* XXX Assume all entries OK. */ + + if (ret == UPAP_AUTHNAK) { + if (*msg == (char *) 0) { + *msg = "Login incorrect"; + } + *msglen = strlen(*msg); + /* + * Frustrate passwd stealer programs. + * Allow 10 tries, but start backing off after 3 (stolen from login). + * On 10'th, drop the connection. + */ + if (attempts++ >= 10) { + AUTHDEBUG(LOG_WARNING, ("%d LOGIN FAILURES BY %s\n", attempts, user)); + /*ppp_panic("Excess Bad Logins");*/ + } + if (attempts > 3) { + /* @todo: this was sleep(), i.e. seconds, not milliseconds + * I don't think we really need this in lwIP - we would block tcpip_thread! + */ + /*sys_msleep((attempts - 3) * 5);*/ + } + if (addrs != NULL) { + free_wordlist(addrs); + } } else { - TIMEOUT(check_idle, NULL, ppp_settings.idle_time_limit - itime); + attempts = 0; /* Reset count */ + if (*msg == (char *) 0) { + *msg = "Login ok"; + } + *msglen = strlen(*msg); + set_allowed_addrs(unit, addrs); } -} + BZERO(passwd, sizeof(passwd)); + BZERO(secret, sizeof(secret)); + + return ret; +#endif +} +#endif /* PAP_SUPPORT */ + +#if 0 /* UNUSED */ /* - * connect_time_expired - log a message and close the connection. + * This function is needed for PAM. */ -static void -connect_time_expired(void *arg) -{ - LWIP_UNUSED_ARG(arg); - AUTHDEBUG((LOG_INFO, "Connect time expired\n")); - lcp_close(0, "Connect time expired"); /* Close connection */ -} +#ifdef USE_PAM -#if 0 +/* lwip does not support PAM*/ + +#endif /* USE_PAM */ + +#endif /* UNUSED */ + + +#if 0 /* UNUSED */ /* - * login - Check the user name and password against the system + * plogin - Check the user name and password against the system * password database, and login the user if OK. * * returns: @@ -836,18 +954,45 @@ connect_time_expired(void *arg) * In either case, msg points to an appropriate message. */ static int -login(char *user, char *passwd, char **msg, int *msglen) +plogin(char *user, char *passwd, char **msg, int *msglen) { + + LWIP_UNUSED_ARG(user); + LWIP_UNUSED_ARG(passwd); + LWIP_UNUSED_ARG(msg); + LWIP_UNUSED_ARG(msglen); + + + /* The new lines are here align the file when + * compared against the pppd 2.3.11 code */ + + + + + + + + + + + + + + + + /* XXX Fail until we decide that we want to support logins. */ return (UPAP_AUTHNAK); } #endif + + /* - * logout - Logout the user. + * plogout - Logout the user. */ static void -logout(void) +plogout(void) { logged_in = 0; } @@ -865,6 +1010,7 @@ null_login(int unit) return 0; } + /* * get_pap_passwd - get a password for authenticating ourselves with * our peer using PAP. Returns 1 on success, 0 if no suitable password @@ -878,6 +1024,8 @@ get_pap_passwd(int unit, char *user, char *passwd) but this causes problems with some providers (like CHT in Taiwan) who incorrectly request PAP and expect a bogus/empty password, so always provide a default user/passwd of "none"/"none" + + @todo: This should be configured by the user, instead of being hardcoded here! */ if(user) { strcpy(user, "none"); @@ -911,9 +1059,76 @@ have_chap_secret(char *client, char *server, u32_t remote) LWIP_UNUSED_ARG(client); LWIP_UNUSED_ARG(server); LWIP_UNUSED_ARG(remote); + /* XXX Fail until we set up our passwords. */ return 0; } +#if CHAP_SUPPORT + +/* + * get_secret - open the CHAP secret file and return the secret + * for authenticating the given client on the given server. + * (We could be either client or server). + */ +int +get_secret(int unit, char *client, char *server, char *secret, int *secret_len, int save_addrs) +{ +#if 1 + int len; + struct wordlist *addrs; + + LWIP_UNUSED_ARG(unit); + LWIP_UNUSED_ARG(server); + LWIP_UNUSED_ARG(save_addrs); + + addrs = NULL; + + if(!client || !client[0] || strcmp(client, ppp_settings.user)) { + return 0; + } + + len = (int)strlen(ppp_settings.passwd); + if (len > MAXSECRETLEN) { + AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server)); + len = MAXSECRETLEN; + } + + BCOPY(ppp_settings.passwd, secret, len); + *secret_len = len; + + return 1; +#else + int ret = 0, len; + struct wordlist *addrs; + char secbuf[MAXWORDLEN]; + + addrs = NULL; + secbuf[0] = 0; + + /* XXX Find secret. */ + if (ret < 0) { + return 0; + } + + if (save_addrs) { + set_allowed_addrs(unit, addrs); + } + + len = strlen(secbuf); + if (len > MAXSECRETLEN) { + AUTHDEBUG(LOG_ERR, ("Secret for %s on %s is too long\n", client, server)); + len = MAXSECRETLEN; + } + + BCOPY(secbuf, secret, len); + BZERO(secbuf, sizeof(secbuf)); + *secret_len = len; + + return 1; +#endif +} +#endif /* CHAP_SUPPORT */ + #if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ /* @@ -954,7 +1169,17 @@ set_allowed_addrs(int unit, struct wordlist *addrs) } #endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ -static int +/* + * auth_ip_addr - check whether the peer is authorized to use + * a given IP address. Returns 1 if authorized, 0 otherwise. + */ +int +auth_ip_addr(int unit, u32_t addr) +{ + return ip_addr_check(addr, addresses[unit]); +} + +static int /* @todo: integrate this funtion into auth_ip_addr()*/ ip_addr_check(u32_t addr, struct wordlist *addrs) { /* don't allow loopback or multicast address */ @@ -970,7 +1195,71 @@ ip_addr_check(u32_t addr, struct wordlist *addrs) return 1; } -#if 0 /* PAP_SUPPORT || CHAP_SUPPORT */ +/* + * bad_ip_adrs - return 1 if the IP address is one we don't want + * to use, such as an address in the loopback net or a multicast address. + * addr is in network byte order. + */ +int +bad_ip_adrs(u32_t addr) +{ + addr = ntohl(addr); + return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET + || IN_MULTICAST(addr) || IN_BADCLASS(addr); +} + +#if 0 /* UNUSED */ /* PAP_SUPPORT || CHAP_SUPPORT */ +/* + * some_ip_ok - check a wordlist to see if it authorizes any + * IP address(es). + */ +static int +some_ip_ok(struct wordlist *addrs) +{ + for (; addrs != 0; addrs = addrs->next) { + if (addrs->word[0] == '-') + break; + if (addrs->word[0] != '!') + return 1; /* some IP address is allowed */ + } + return 0; +} + +/* + * check_access - complain if a secret file has too-liberal permissions. + */ +static void +check_access(FILE *f, char *filename) +{ + struct stat sbuf; + + if (fstat(fileno(f), &sbuf) < 0) { + warn("cannot stat secret file %s: %m", filename); + } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) { + warn("Warning - secret file %s has world and/or group access", + filename); + } +} + + +/* + * scan_authfile - Scan an authorization file for a secret suitable + * for authenticating `client' on `server'. The return value is -1 + * if no secret is found, otherwise >= 0. The return value has + * NONWILD_CLIENT set if the secret didn't have "*" for the client, and + * NONWILD_SERVER set if the secret didn't have "*" for the server. + * Any following words on the line up to a "--" (i.e. address authorization + * info) are placed in a wordlist and returned in *addrs. Any + * following words (extra options) are placed in a wordlist and + * returned in *opts. + * We assume secret is NULL or points to MAXWORDLEN bytes of space. + */ +static int +scan_authfile(FILE *f, char *client, char *server, char *secret, struct wordlist **addrs, struct wordlist **opts, char *filename) +{ + /* We do not (currently) need this in lwip */ + return 0; /* dummy */ +} /* * free_wordlist - release memory allocated for a wordlist. */ @@ -978,13 +1267,68 @@ static void free_wordlist(struct wordlist *wp) { struct wordlist *next; - + while (wp != NULL) { next = wp->next; free(wp); wp = next; } } -#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ +/* + * auth_script_done - called when the auth-up or auth-down script + * has finished. + */ +static void +auth_script_done(void *arg) +{ + auth_script_pid = 0; + switch (auth_script_state) { + case s_up: + if (auth_state == s_down) { + auth_script_state = s_down; + auth_script(_PATH_AUTHDOWN); + } + break; + case s_down: + if (auth_state == s_up) { + auth_script_state = s_up; + auth_script(_PATH_AUTHUP); + } + break; + } +} + +/* + * auth_script - execute a script with arguments + * interface-name peer-name real-user tty speed + */ +static void +auth_script(char *script) +{ + char strspeed[32]; + struct passwd *pw; + char struid[32]; + char *user_name; + char *argv[8]; + + if ((pw = getpwuid(getuid())) != NULL && pw->pw_name != NULL) + user_name = pw->pw_name; + else { + slprintf(struid, sizeof(struid), "%d", getuid()); + user_name = struid; + } + slprintf(strspeed, sizeof(strspeed), "%d", baud_rate); + + argv[0] = script; + argv[1] = ifname; + argv[2] = peer_authname; + argv[3] = user_name; + argv[4] = devnam; + argv[5] = strspeed; + argv[6] = NULL; + + auth_script_pid = run_program(script, argv, 0, auth_script_done, NULL); +} +#endif /* 0 */ /* PAP_SUPPORT || CHAP_SUPPORT */ #endif /* PPP_SUPPORT */ diff --git a/lib/drivers/lwip/src/netif/ppp/auth.h b/lib/drivers/lwip/src/netif/ppp/auth.h index 86ff04945a9..a8069ec4640 100644 --- a/lib/drivers/lwip/src/netif/ppp/auth.h +++ b/lib/drivers/lwip/src/netif/ppp/auth.h @@ -97,7 +97,7 @@ void auth_check_options (void); void auth_reset (int); /* Check peer-supplied username/password */ -int check_passwd (int, char *, int, char *, int, char **, int *); +u_char check_passwd (int, char *, int, char *, int, char **, int *); /* get "secret" for chap */ int get_secret (int, char *, char *, char *, int *, int); diff --git a/lib/drivers/lwip/src/netif/ppp/chap.c b/lib/drivers/lwip/src/netif/ppp/chap.c index b3ea6b2220b..3a49ff8a5e4 100644 --- a/lib/drivers/lwip/src/netif/ppp/chap.c +++ b/lib/drivers/lwip/src/netif/ppp/chap.c @@ -84,19 +84,25 @@ #include -/*************************/ -/*** LOCAL DEFINITIONS ***/ -/*************************/ +#if 0 /* UNUSED */ +/* + * Command-line options. + */ +static option_t chap_option_list[] = { + { "chap-restart", o_int, &chap[0].timeouttime, + "Set timeout for CHAP" }, + { "chap-max-challenge", o_int, &chap[0].max_transmits, + "Set max #xmits for challenge" }, + { "chap-interval", o_int, &chap[0].chal_interval, + "Set interval for rechallenge" }, +#ifdef MSLANMAN + { "ms-lanman", o_bool, &ms_lanman, + "Use LanMan passwd when using MS-CHAP", 1 }, +#endif + { NULL } +}; +#endif /* UNUSED */ - -/************************/ -/*** LOCAL DATA TYPES ***/ -/************************/ - - -/***********************************/ -/*** LOCAL FUNCTION DECLARATIONS ***/ -/***********************************/ /* * Protocol entry points. */ @@ -105,28 +111,10 @@ static void ChapLowerUp (int); static void ChapLowerDown (int); static void ChapInput (int, u_char *, int); static void ChapProtocolReject (int); -#if 0 +#if PPP_ADDITIONAL_CALLBACKS static int ChapPrintPkt (u_char *, int, void (*) (void *, char *, ...), void *); #endif -static void ChapChallengeTimeout (void *); -static void ChapResponseTimeout (void *); -static void ChapReceiveChallenge (chap_state *, u_char *, int, int); -static void ChapRechallenge (void *); -static void ChapReceiveResponse (chap_state *, u_char *, int, int); -static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len); -static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len); -static void ChapSendStatus (chap_state *, int); -static void ChapSendChallenge (chap_state *); -static void ChapSendResponse (chap_state *); -static void ChapGenChallenge (chap_state *); - - -/******************************/ -/*** PUBLIC DATA STRUCTURES ***/ -/******************************/ -chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */ - struct protent chap_protent = { PPP_CHAP, ChapInit, @@ -136,29 +124,57 @@ struct protent chap_protent = { ChapLowerDown, NULL, NULL, -#if 0 +#if PPP_ADDITIONAL_CALLBACKS ChapPrintPkt, NULL, -#endif +#endif /* PPP_ADDITIONAL_CALLBACKS */ 1, "CHAP", -#if 0 +#if PPP_ADDITIONAL_CALLBACKS NULL, NULL, NULL -#endif +#endif /* PPP_ADDITIONAL_CALLBACKS */ }; +chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */ + +static void ChapChallengeTimeout (void *); +static void ChapResponseTimeout (void *); +static void ChapReceiveChallenge (chap_state *, u_char *, u_char, int); +static void ChapRechallenge (void *); +static void ChapReceiveResponse (chap_state *, u_char *, int, int); +static void ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len); +static void ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len); +static void ChapSendStatus (chap_state *, int); +static void ChapSendChallenge (chap_state *); +static void ChapSendResponse (chap_state *); +static void ChapGenChallenge (chap_state *); + +/* + * ChapInit - Initialize a CHAP unit. + */ +static void +ChapInit(int unit) +{ + chap_state *cstate = &chap[unit]; + + BZERO(cstate, sizeof(*cstate)); + cstate->unit = unit; + cstate->clientstate = CHAPCS_INITIAL; + cstate->serverstate = CHAPSS_INITIAL; + cstate->timeouttime = CHAP_DEFTIMEOUT; + cstate->max_transmits = CHAP_DEFTRANSMITS; + /* random number generator is initialized in magic_init */ +} + -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ /* * ChapAuthWithPeer - Authenticate us with our peer (start client). * */ void -ChapAuthWithPeer(int unit, char *our_name, int digest) +ChapAuthWithPeer(int unit, char *our_name, u_char digest) { chap_state *cstate = &chap[unit]; @@ -185,7 +201,7 @@ ChapAuthWithPeer(int unit, char *our_name, int digest) * ChapAuthPeer - Authenticate our peer (start server). */ void -ChapAuthPeer(int unit, char *our_name, int digest) +ChapAuthPeer(int unit, char *our_name, u_char digest) { chap_state *cstate = &chap[unit]; @@ -205,27 +221,6 @@ ChapAuthPeer(int unit, char *our_name, int digest) } -/**********************************/ -/*** LOCAL FUNCTION DEFINITIONS ***/ -/**********************************/ -/* - * ChapInit - Initialize a CHAP unit. - */ -static void -ChapInit(int unit) -{ - chap_state *cstate = &chap[unit]; - - BZERO(cstate, sizeof(*cstate)); - cstate->unit = unit; - cstate->clientstate = CHAPCS_INITIAL; - cstate->serverstate = CHAPSS_INITIAL; - cstate->timeouttime = CHAP_DEFTIMEOUT; - cstate->max_transmits = CHAP_DEFTRANSMITS; - /* random number generator is initialized in magic_init */ -} - - /* * ChapChallengeTimeout - Timeout expired on sending challenge. */ @@ -243,7 +238,7 @@ ChapChallengeTimeout(void *arg) if (cstate->chal_transmits >= cstate->max_transmits) { /* give up on peer */ - CHAPDEBUG((LOG_ERR, "Peer failed to respond to CHAP challenge\n")); + CHAPDEBUG(LOG_ERR, ("Peer failed to respond to CHAP challenge\n")); cstate->serverstate = CHAPSS_BADAUTH; auth_peer_fail(cstate->unit, PPP_CHAP); return; @@ -355,7 +350,7 @@ ChapProtocolReject(int unit) } if (cstate->clientstate != CHAPCS_INITIAL && cstate->clientstate != CHAPCS_CLOSED) { - auth_withpeer_fail(unit, PPP_CHAP); + auth_withpeer_fail(unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */ } ChapLowerDown(unit); /* shutdown chap */ } @@ -378,18 +373,18 @@ ChapInput(int unit, u_char *inpacket, int packet_len) */ inp = inpacket; if (packet_len < CHAP_HEADERLEN) { - CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short header.\n")); + CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short header.\n")); return; } GETCHAR(code, inp); GETCHAR(id, inp); GETSHORT(len, inp); if (len < CHAP_HEADERLEN) { - CHAPDEBUG((LOG_INFO, "ChapInput: rcvd illegal length.\n")); + CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd illegal length.\n")); return; } if (len > packet_len) { - CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short packet.\n")); + CHAPDEBUG(LOG_INFO, ("ChapInput: rcvd short packet.\n")); return; } len -= CHAP_HEADERLEN; @@ -415,7 +410,7 @@ ChapInput(int unit, u_char *inpacket, int packet_len) break; default: /* Need code reject? */ - CHAPDEBUG((LOG_WARNING, "Unknown CHAP code (%d) received.\n", code)); + CHAPDEBUG(LOG_WARNING, ("Unknown CHAP code (%d) received.\n", code)); break; } } @@ -425,7 +420,7 @@ ChapInput(int unit, u_char *inpacket, int packet_len) * ChapReceiveChallenge - Receive Challenge and send Response. */ static void -ChapReceiveChallenge(chap_state *cstate, u_char *inp, int id, int len) +ChapReceiveChallenge(chap_state *cstate, u_char *inp, u_char id, int len) { int rchallenge_len; u_char *rchallenge; @@ -434,48 +429,52 @@ ChapReceiveChallenge(chap_state *cstate, u_char *inp, int id, int len) char rhostname[256]; MD5_CTX mdContext; u_char hash[MD5_SIGNATURE_SIZE]; - - CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: Rcvd id %d.\n", id)); + + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: Rcvd id %d.\n", id)); if (cstate->clientstate == CHAPCS_CLOSED || cstate->clientstate == CHAPCS_PENDING) { - CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: in state %d\n", + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: in state %d\n", cstate->clientstate)); return; } if (len < 2) { - CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n")); + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n")); return; } GETCHAR(rchallenge_len, inp); len -= sizeof (u_char) + rchallenge_len; /* now name field length */ if (len < 0) { - CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet.\n")); + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: rcvd short packet.\n")); return; } rchallenge = inp; INCPTR(rchallenge_len, inp); - if (len >= sizeof(rhostname)) { + if (len >= (int)sizeof(rhostname)) { len = sizeof(rhostname) - 1; } BCOPY(inp, rhostname, len); rhostname[len] = '\000'; - CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field '%s'\n", rhostname)); + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: received name field '%s'\n", + rhostname)); /* Microsoft doesn't send their name back in the PPP packet */ if (ppp_settings.remote_name[0] != 0 && (ppp_settings.explicit_remote || rhostname[0] == 0)) { strncpy(rhostname, ppp_settings.remote_name, sizeof(rhostname)); rhostname[sizeof(rhostname) - 1] = 0; - CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: using '%s' as remote name\n", rhostname)); + CHAPDEBUG(LOG_INFO, ("ChapReceiveChallenge: using '%s' as remote name\n", + rhostname)); } /* get secret for authenticating ourselves with the specified host */ - if (!get_secret(cstate->unit, cstate->resp_name, rhostname, secret, &secret_len, 0)) { + if (!get_secret(cstate->unit, cstate->resp_name, rhostname, + secret, &secret_len, 0)) { secret_len = 0; /* assume null secret if can't find one */ - CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating us to %s\n", rhostname)); + CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating us to %s\n", + rhostname)); } /* cancel response send timeout if necessary */ @@ -499,14 +498,14 @@ ChapReceiveChallenge(chap_state *cstate, u_char *inp, int id, int len) cstate->resp_length = MD5_SIGNATURE_SIZE; break; -#ifdef CHAPMS +#if MSCHAP_SUPPORT case CHAP_MICROSOFT: ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len); break; #endif default: - CHAPDEBUG((LOG_INFO, "unknown digest type %d\n", cstate->resp_type)); + CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->resp_type)); return; } @@ -528,12 +527,12 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len) MD5_CTX mdContext; char secret[MAXSECRETLEN]; u_char hash[MD5_SIGNATURE_SIZE]; - - CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: Rcvd id %d.\n", id)); + + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: Rcvd id %d.\n", id)); if (cstate->serverstate == CHAPSS_CLOSED || cstate->serverstate == CHAPSS_PENDING) { - CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: in state %d\n", + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: in state %d\n", cstate->serverstate)); return; } @@ -557,7 +556,7 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len) } if (len < 2) { - CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n")); + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n")); return; } GETCHAR(remmd_len, inp); /* get length of MD */ @@ -566,29 +565,30 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len) len -= sizeof (u_char) + remmd_len; if (len < 0) { - CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet.\n")); + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: rcvd short packet.\n")); return; } UNTIMEOUT(ChapChallengeTimeout, cstate); - if (len >= sizeof(rhostname)) { + if (len >= (int)sizeof(rhostname)) { len = sizeof(rhostname) - 1; } BCOPY(inp, rhostname, len); rhostname[len] = '\000'; - CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: received name field: %s\n", rhostname)); + CHAPDEBUG(LOG_INFO, ("ChapReceiveResponse: received name field: %s\n", + rhostname)); /* * Get secret for authenticating them with us, * do the hash ourselves, and compare the result. */ code = CHAP_FAILURE; - if (!get_secret(cstate->unit, rhostname, cstate->chal_name, secret, &secret_len, 1)) { - /* CHAPDEBUG((LOG_WARNING, TL_CHAP, "No CHAP secret found for authenticating %s\n", rhostname)); */ - CHAPDEBUG((LOG_WARNING, "No CHAP secret found for authenticating %s\n", - rhostname)); + if (!get_secret(cstate->unit, rhostname, cstate->chal_name, + secret, &secret_len, 1)) { + CHAPDEBUG(LOG_WARNING, ("No CHAP secret found for authenticating %s\n", + rhostname)); } else { /* generate MD based on negotiated type */ switch (cstate->chal_type) { @@ -610,7 +610,7 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len) break; default: - CHAPDEBUG((LOG_INFO, "unknown digest type %d\n", cstate->chal_type)); + CHAPDEBUG(LOG_INFO, ("unknown digest type %d\n", cstate->chal_type)); } } @@ -627,7 +627,7 @@ ChapReceiveResponse(chap_state *cstate, u_char *inp, int id, int len) TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval); } } else { - CHAPDEBUG((LOG_ERR, "CHAP peer authentication failed\n")); + CHAPDEBUG(LOG_ERR, ("CHAP peer authentication failed\n")); cstate->serverstate = CHAPSS_BADAUTH; auth_peer_fail(cstate->unit, PPP_CHAP); } @@ -642,7 +642,7 @@ ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len) LWIP_UNUSED_ARG(id); LWIP_UNUSED_ARG(inp); - CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: Rcvd id %d.\n", id)); + CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: Rcvd id %d.\n", id)); if (cstate->clientstate == CHAPCS_OPEN) { /* presumably an answer to a duplicate response */ @@ -651,7 +651,8 @@ ChapReceiveSuccess(chap_state *cstate, u_char *inp, u_char id, int len) if (cstate->clientstate != CHAPCS_RESPONSE) { /* don't know what this is */ - CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: in state %d\n", cstate->clientstate)); + CHAPDEBUG(LOG_INFO, ("ChapReceiveSuccess: in state %d\n", + cstate->clientstate)); return; } @@ -679,11 +680,12 @@ ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len) LWIP_UNUSED_ARG(id); LWIP_UNUSED_ARG(inp); - CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: Rcvd id %d.\n", id)); + CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: Rcvd id %d.\n", id)); if (cstate->clientstate != CHAPCS_RESPONSE) { /* don't know what this is */ - CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: in state %d\n", cstate->clientstate)); + CHAPDEBUG(LOG_INFO, ("ChapReceiveFailure: in state %d\n", + cstate->clientstate)); return; } @@ -696,8 +698,8 @@ ChapReceiveFailure(chap_state *cstate, u_char *inp, u_char id, int len) PRINTMSG(inp, len); } - CHAPDEBUG((LOG_ERR, "CHAP authentication failed\n")); - auth_withpeer_fail(cstate->unit, PPP_CHAP); + CHAPDEBUG(LOG_ERR, ("CHAP authentication failed\n")); + auth_withpeer_fail(cstate->unit, PPP_CHAP); /* lwip: just sets the PPP error code on this unit to PPPERR_AUTHFAIL */ } @@ -712,25 +714,25 @@ ChapSendChallenge(chap_state *cstate) int outlen; chal_len = cstate->chal_len; - name_len = strlen(cstate->chal_name); + name_len = (int)strlen(cstate->chal_name); outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len; outp = outpacket_buf[cstate->unit]; - + MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */ - + PUTCHAR(CHAP_CHALLENGE, outp); PUTCHAR(cstate->chal_id, outp); PUTSHORT(outlen, outp); - + PUTCHAR(chal_len, outp); /* put length of challenge */ BCOPY(cstate->challenge, outp, chal_len); INCPTR(chal_len, outp); - + BCOPY(cstate->chal_name, outp, name_len); /* append hostname */ pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); - - CHAPDEBUG((LOG_INFO, "ChapSendChallenge: Sent id %d.\n", cstate->chal_id)); + + CHAPDEBUG(LOG_INFO, ("ChapSendChallenge: Sent id %d.\n", cstate->chal_id)); TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime); ++cstate->chal_transmits; @@ -745,18 +747,18 @@ ChapSendStatus(chap_state *cstate, int code) { u_char *outp; int outlen, msglen; - char msg[256]; - + char msg[256]; /* @todo: this can be a char*, no strcpy needed */ + if (code == CHAP_SUCCESS) { strcpy(msg, "Welcome!"); } else { strcpy(msg, "I don't like you. Go 'way."); } - msglen = strlen(msg); - + msglen = (int)strlen(msg); + outlen = CHAP_HEADERLEN + msglen; outp = outpacket_buf[cstate->unit]; - + MAKEHEADER(outp, PPP_CHAP); /* paste in a header */ PUTCHAR(code, outp); @@ -764,8 +766,9 @@ ChapSendStatus(chap_state *cstate, int code) PUTSHORT(outlen, outp); BCOPY(msg, outp, msglen); pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); - - CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.\n", code, cstate->chal_id)); + + CHAPDEBUG(LOG_INFO, ("ChapSendStatus: Sent code %d, id %d.\n", code, + cstate->chal_id)); } /* @@ -781,17 +784,18 @@ ChapGenChallenge(chap_state *cstate) int chal_len; u_char *ptr = cstate->challenge; int i; - + /* pick a random challenge length between MIN_CHALLENGE_LENGTH and MAX_CHALLENGE_LENGTH */ chal_len = (unsigned) ((((magic() >> 16) * (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) >> 16) + MIN_CHALLENGE_LENGTH); - cstate->chal_len = chal_len; + LWIP_ASSERT("chal_len <= 0xff", chal_len <= 0xffff); + cstate->chal_len = (u_char)chal_len; cstate->chal_id = ++cstate->id; cstate->chal_transmits = 0; - + /* generate a random string */ for (i = 0; i < chal_len; i++ ) { *ptr++ = (char) (magic() & 0xff); @@ -808,12 +812,12 @@ ChapSendResponse(chap_state *cstate) { u_char *outp; int outlen, md_len, name_len; - + md_len = cstate->resp_length; - name_len = strlen(cstate->resp_name); + name_len = (int)strlen(cstate->resp_name); outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len; outp = outpacket_buf[cstate->unit]; - + MAKEHEADER(outp, PPP_CHAP); PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */ @@ -823,18 +827,18 @@ ChapSendResponse(chap_state *cstate) PUTCHAR(md_len, outp); /* length of MD */ BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */ INCPTR(md_len, outp); - + BCOPY(cstate->resp_name, outp, name_len); /* append our name */ - + /* send the packet */ pppWrite(cstate->unit, outpacket_buf[cstate->unit], outlen + PPP_HDRLEN); - + cstate->clientstate = CHAPCS_RESPONSE; TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime); ++cstate->resp_transmits; } -#if 0 +#if PPP_ADDITIONAL_CALLBACKS static char *ChapCodenames[] = { "Challenge", "Response", "Success", "Failure" }; @@ -847,7 +851,7 @@ ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void * int code, id, len; int clen, nlen; u_char x; - + if (plen < CHAP_HEADERLEN) { return 0; } @@ -857,6 +861,7 @@ ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void * if (len < CHAP_HEADERLEN || len > plen) { return 0; } + if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) { printer(arg, " %s", ChapCodenames[code-1]); } else { @@ -896,7 +901,7 @@ ChapPrintPkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void * return len + CHAP_HEADERLEN; } -#endif +#endif /* PPP_ADDITIONAL_CALLBACKS */ #endif /* CHAP_SUPPORT */ diff --git a/lib/drivers/lwip/src/netif/ppp/chap.h b/lib/drivers/lwip/src/netif/ppp/chap.h index 83dafd734fc..fedcab8da1a 100644 --- a/lib/drivers/lwip/src/netif/ppp/chap.h +++ b/lib/drivers/lwip/src/netif/ppp/chap.h @@ -62,16 +62,12 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: chap.h,v 1.4 2007/12/19 20:47:22 fbernon Exp $ + * $Id: chap.h,v 1.6 2010/01/24 13:19:34 goldsimon Exp $ */ #ifndef CHAP_H #define CHAP_H -/************************* -*** PUBLIC DEFINITIONS *** -*************************/ - /* Code + ID + length */ #define CHAP_HEADERLEN 4 @@ -96,31 +92,6 @@ #define MAX_CHALLENGE_LENGTH 64 #define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */ -/* - * Client (peer) states. - */ -#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */ -#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */ -#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */ -#define CHAPCS_LISTEN 3 /* Listening for a challenge */ -#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */ -#define CHAPCS_OPEN 5 /* We've received Success */ - -/* - * Server (authenticator) states. - */ -#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */ -#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */ -#define CHAPSS_PENDING 2 /* Auth peer when lower up */ -#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */ -#define CHAPSS_OPEN 4 /* We've sent a Success msg */ -#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */ -#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */ - -/************************ -*** PUBLIC DATA TYPES *** -************************/ - /* * Each interface is described by a chap structure. */ @@ -148,19 +119,32 @@ typedef struct chap_state { } chap_state; -/****************** -*** PUBLIC DATA *** -******************/ +/* + * Client (peer) states. + */ +#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */ +#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */ +#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */ +#define CHAPCS_LISTEN 3 /* Listening for a challenge */ +#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */ +#define CHAPCS_OPEN 5 /* We've received Success */ + +/* + * Server (authenticator) states. + */ +#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */ +#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */ +#define CHAPSS_PENDING 2 /* Auth peer when lower up */ +#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */ +#define CHAPSS_OPEN 4 /* We've sent a Success msg */ +#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */ +#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */ + extern chap_state chap[]; +void ChapAuthWithPeer (int, char *, u_char); +void ChapAuthPeer (int, char *, u_char); + extern struct protent chap_protent; - -/*********************** -*** PUBLIC FUNCTIONS *** -***********************/ - -void ChapAuthWithPeer (int, char *, int); -void ChapAuthPeer (int, char *, int); - #endif /* CHAP_H */ diff --git a/lib/drivers/lwip/src/netif/ppp/chpms.c b/lib/drivers/lwip/src/netif/ppp/chpms.c index 582cfd2dd7d..83acefcec6d 100644 --- a/lib/drivers/lwip/src/netif/ppp/chpms.c +++ b/lib/drivers/lwip/src/netif/ppp/chpms.c @@ -85,6 +85,8 @@ #include "chap.h" #include "chpms.h" +#include + /*************************/ /*** LOCAL DEFINITIONS ***/ @@ -137,49 +139,12 @@ static u_char Get7Bits( int startBit ); - -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ -void -ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len) -{ - MS_ChapResponse response; -#ifdef MSLANMAN - extern int ms_lanman; -#endif - -#if 0 - CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'\n", secret_len, secret)); -#endif - BZERO(&response, sizeof(response)); - - /* Calculate both always */ - ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response); - -#ifdef MSLANMAN - ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response); - - /* prefered method is set by option */ - response.UseNT = !ms_lanman; -#else - response.UseNT = 1; -#endif - - BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN); - cstate->resp_length = MS_CHAP_RESPONSE_LEN; -} - - -/**********************************/ -/*** LOCAL FUNCTION DEFINITIONS ***/ -/**********************************/ static void ChallengeResponse( u_char *challenge, /* IN 8 octets */ u_char *pwHash, /* IN 16 octets */ u_char *response /* OUT 24 octets */) { - char ZPasswordHash[21]; + u_char ZPasswordHash[21]; BZERO(ZPasswordHash, sizeof(ZPasswordHash)); BCOPY(pwHash, ZPasswordHash, 16); @@ -211,19 +176,19 @@ DesEncrypt( u_char *clear, /* IN 8 octets */ MakeKey(key, des_key); Expand(des_key, crypt_key); - setkey(crypt_key); + setkey((char*)crypt_key); #if 0 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n", + CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n", clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7])); #endif Expand(clear, des_input); - encrypt(des_input, 0); + encrypt((char*)des_input, 0); Collapse(des_input, cipher); #if 0 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n", + CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n", cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7])); #endif } @@ -243,14 +208,14 @@ DesEncrypt( u_char *clear, /* IN 8 octets */ des_set_key(&des_key, key_schedule); #if 0 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n", + CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X\n", clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7])); #endif des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1); #if 0 - CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n", + CHAPDEBUG(LOG_INFO, ("DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X\n", cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7])); #endif } @@ -329,9 +294,9 @@ MakeKey( u_char *key, /* IN 56 bit DES key missing parity bits */ #endif #if 0 - CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n", + CHAPDEBUG(LOG_INFO, ("MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X\n", key[0], key[1], key[2], key[3], key[4], key[5], key[6])); - CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n", + CHAPDEBUG(LOG_INFO, ("MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X\n", des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7])); #endif } @@ -348,6 +313,8 @@ ChapMS_NT( char *rchallenge, u_char unicodePassword[MAX_NT_PASSWORD * 2]; static int low_byte_first = -1; + LWIP_UNUSED_ARG(rchallenge_len); + /* Initialize the Unicode version of the secret (== password). */ /* This implicitly supports 8-bit ISO8859/1 characters. */ BZERO(unicodePassword, sizeof(unicodePassword)); @@ -358,15 +325,16 @@ ChapMS_NT( char *rchallenge, MDupdate(&md4Context, unicodePassword, secret_len * 2 * 8); /* Unicode is 2 bytes/char, *8 for bit count */ if (low_byte_first == -1) { - low_byte_first = (htons((unsigned short int)1) != 1); + low_byte_first = (PP_HTONS((unsigned short int)1) != 1); } if (low_byte_first == 0) { - MDreverse((u_long *)&md4Context); /* sfb 961105 */ + /* @todo: arg type - u_long* or u_int* ? */ + MDreverse((unsigned int*)&md4Context); /* sfb 961105 */ } MDupdate(&md4Context, NULL, 0); /* Tell MD4 we're done */ - ChallengeResponse(rchallenge, (char *)md4Context.buffer, response->NTResp); + ChallengeResponse((u_char*)rchallenge, (u_char*)md4Context.buffer, response->NTResp); } #ifdef MSLANMAN @@ -394,6 +362,35 @@ ChapMS_LANMan( char *rchallenge, } #endif +void +ChapMS( chap_state *cstate, char *rchallenge, int rchallenge_len, char *secret, int secret_len) +{ + MS_ChapResponse response; +#ifdef MSLANMAN + extern int ms_lanman; +#endif + +#if 0 + CHAPDEBUG(LOG_INFO, ("ChapMS: secret is '%.*s'\n", secret_len, secret)); +#endif + BZERO(&response, sizeof(response)); + + /* Calculate both always */ + ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response); + +#ifdef MSLANMAN + ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response); + + /* prefered method is set by option */ + response.UseNT = !ms_lanman; +#else + response.UseNT = 1; +#endif + + BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN); + cstate->resp_length = MS_CHAP_RESPONSE_LEN; +} + #endif /* MSCHAP_SUPPORT */ #endif /* PPP_SUPPORT */ diff --git a/lib/drivers/lwip/src/netif/ppp/fsm.c b/lib/drivers/lwip/src/netif/ppp/fsm.c index ee549f230d8..2e73c5af8ff 100644 --- a/lib/drivers/lwip/src/netif/ppp/fsm.c +++ b/lib/drivers/lwip/src/netif/ppp/fsm.c @@ -66,13 +66,7 @@ #include - -/*************************/ -/*** LOCAL DEFINITIONS ***/ -/*************************/ - #if PPP_DEBUG - static const char *ppperr_strerr[] = { "LS_INITIAL", /* LS_INITIAL 0 */ "LS_STARTING", /* LS_STARTING 1 */ @@ -85,17 +79,8 @@ static const char *ppperr_strerr[] = { "LS_ACKSENT", /* LS_ACKSENT 8 */ "LS_OPENED" /* LS_OPENED 9 */ }; - #endif /* PPP_DEBUG */ -/************************/ -/*** LOCAL DATA TYPES ***/ -/************************/ - - -/***********************************/ -/*** LOCAL FUNCTION DECLARATIONS ***/ -/***********************************/ static void fsm_timeout (void *); static void fsm_rconfreq (fsm *, u_char, u_char *, int); static void fsm_rconfack (fsm *, int, u_char *, int); @@ -107,22 +92,9 @@ static void fsm_sconfreq (fsm *, int); #define PROTO_NAME(f) ((f)->callbacks->proto_name) - -/******************************/ -/*** PUBLIC DATA STRUCTURES ***/ -/******************************/ - - -/*****************************/ -/*** LOCAL DATA STRUCTURES ***/ -/*****************************/ int peer_mru[NUM_PPP]; -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ - /* * fsm_init - Initialize fsm. * @@ -168,11 +140,11 @@ fsm_lowerup(fsm *f) break; default: - FSMDEBUG((LOG_INFO, "%s: Up event in state %d (%s)!\n", + FSMDEBUG(LOG_INFO, ("%s: Up event in state %d (%s)!\n", PROTO_NAME(f), f->state, ppperr_strerr[f->state])); } - - FSMDEBUG((LOG_INFO, "%s: lowerup state %d (%s) -> %d (%s)\n", + + FSMDEBUG(LOG_INFO, ("%s: lowerup state %d (%s) -> %d (%s)\n", PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); } @@ -222,11 +194,11 @@ fsm_lowerdown(fsm *f) break; default: - FSMDEBUG((LOG_INFO, "%s: Down event in state %d (%s)!\n", + FSMDEBUG(LOG_INFO, ("%s: Down event in state %d (%s)!\n", PROTO_NAME(f), f->state, ppperr_strerr[f->state])); } - FSMDEBUG((LOG_INFO, "%s: lowerdown state %d (%s) -> %d (%s)\n", + FSMDEBUG(LOG_INFO, ("%s: lowerdown state %d (%s) -> %d (%s)\n", PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); } @@ -271,10 +243,23 @@ fsm_open(fsm *f) break; } - FSMDEBUG((LOG_INFO, "%s: open state %d (%s) -> %d (%s)\n", + FSMDEBUG(LOG_INFO, ("%s: open state %d (%s) -> %d (%s)\n", PROTO_NAME(f), oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); } +#if 0 /* backport pppd 2.4.4b1; */ +/* + * terminate_layer - Start process of shutting down the FSM + * + * Cancel any timeout running, notify upper layers we're done, and + * send a terminate-request message as configured. + */ +static void +terminate_layer(fsm *f, int nextstate) +{ + /* @todo */ +} +#endif /* * fsm_close - Start closing connection. @@ -290,7 +275,7 @@ fsm_close(fsm *f, char *reason) LWIP_UNUSED_ARG(oldState); f->term_reason = reason; - f->term_reason_len = (reason == NULL? 0: strlen(reason)); + f->term_reason_len = (reason == NULL ? 0 : (int)strlen(reason)); switch( f->state ) { case LS_STARTING: f->state = LS_INITIAL; @@ -322,38 +307,71 @@ fsm_close(fsm *f, char *reason) break; } - FSMDEBUG((LOG_INFO, "%s: close reason=%s state %d (%s) -> %d (%s)\n", + FSMDEBUG(LOG_INFO, ("%s: close reason=%s state %d (%s) -> %d (%s)\n", PROTO_NAME(f), reason, oldState, ppperr_strerr[oldState], f->state, ppperr_strerr[f->state])); } /* - * fsm_sdata - Send some data. - * - * Used for all packets sent to our peer by this module. + * fsm_timeout - Timeout expired. */ -void -fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen) +static void +fsm_timeout(void *arg) { - u_char *outp; - int outlen; + fsm *f = (fsm *) arg; - /* Adjust length to be smaller than MTU */ - outp = outpacket_buf[f->unit]; - if (datalen > peer_mru[f->unit] - (int)HEADERLEN) { - datalen = peer_mru[f->unit] - HEADERLEN; + switch (f->state) { + case LS_CLOSING: + case LS_STOPPING: + if( f->retransmits <= 0 ) { + FSMDEBUG(LOG_WARNING, ("%s: timeout sending Terminate-Request state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + /* + * We've waited for an ack long enough. Peer probably heard us. + */ + f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + } else { + FSMDEBUG(LOG_WARNING, ("%s: timeout resending Terminate-Requests state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + /* Send Terminate-Request */ + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, f->timeouttime); + --f->retransmits; + } + break; + + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + if (f->retransmits <= 0) { + FSMDEBUG(LOG_WARNING, ("%s: timeout sending Config-Requests state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + f->state = LS_STOPPED; + if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + } else { + FSMDEBUG(LOG_WARNING, ("%s: timeout resending Config-Request state=%d (%s)\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + /* Retransmit the configure-request */ + if (f->callbacks->retransmit) { + (*f->callbacks->retransmit)(f); + } + fsm_sconfreq(f, 1); /* Re-send Configure-Request */ + if( f->state == LS_ACKRCVD ) { + f->state = LS_REQSENT; + } + } + break; + + default: + FSMDEBUG(LOG_INFO, ("%s: UNHANDLED timeout event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); } - if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) { - BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen); - } - outlen = datalen + HEADERLEN; - MAKEHEADER(outp, f->protocol); - PUTCHAR(code, outp); - PUTCHAR(id, outp); - PUTSHORT(outlen, outp); - pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN); - FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d,%d,%d.\n", - PROTO_NAME(f), code, id, outlen)); } @@ -372,7 +390,7 @@ fsm_input(fsm *f, u_char *inpacket, int l) * If packet too short, drop it. */ if (l < HEADERLEN) { - FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.\n", + FSMDEBUG(LOG_WARNING, ("fsm_input(%x): Rcvd short header.\n", f->protocol)); return; } @@ -380,23 +398,23 @@ fsm_input(fsm *f, u_char *inpacket, int l) GETCHAR(id, inp); GETSHORT(len, inp); if (len < HEADERLEN) { - FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd illegal length.\n", + FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd illegal length.\n", f->protocol)); return; } if (len > l) { - FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.\n", + FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd short packet.\n", f->protocol)); return; } len -= HEADERLEN; /* subtract header length */ if( f->state == LS_INITIAL || f->state == LS_STARTING ) { - FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d (%s).\n", + FSMDEBUG(LOG_INFO, ("fsm_input(%x): Rcvd packet in state %d (%s).\n", f->protocol, f->state, ppperr_strerr[f->state])); return; } - FSMDEBUG((LOG_INFO, "fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l)); + FSMDEBUG(LOG_INFO, ("fsm_input(%s):%d,%d,%d\n", PROTO_NAME(f), code, id, l)); /* * Action depends on code. */ @@ -427,6 +445,7 @@ fsm_input(fsm *f, u_char *inpacket, int l) break; default: + FSMDEBUG(LOG_INFO, ("fsm_input(%s): default: \n", PROTO_NAME(f))); if( !f->callbacks->extcode || !(*f->callbacks->extcode)(f, code, id, inp, len) ) { fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN); @@ -436,129 +455,6 @@ fsm_input(fsm *f, u_char *inpacket, int l) } -/* - * fsm_protreject - Peer doesn't speak this protocol. - * - * Treat this as a catastrophic error (RXJ-). - */ -void -fsm_protreject(fsm *f) -{ - switch( f->state ) { - case LS_CLOSING: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - /* fall through */ - case LS_CLOSED: - f->state = LS_CLOSED; - if( f->callbacks->finished ) { - (*f->callbacks->finished)(f); - } - break; - - case LS_STOPPING: - case LS_REQSENT: - case LS_ACKRCVD: - case LS_ACKSENT: - UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ - /* fall through */ - case LS_STOPPED: - f->state = LS_STOPPED; - if( f->callbacks->finished ) { - (*f->callbacks->finished)(f); - } - break; - - case LS_OPENED: - if( f->callbacks->down ) { - (*f->callbacks->down)(f); - } - /* Init restart counter, send Terminate-Request */ - f->retransmits = f->maxtermtransmits; - fsm_sdata(f, TERMREQ, f->reqid = ++f->id, - (u_char *) f->term_reason, f->term_reason_len); - TIMEOUT(fsm_timeout, f, f->timeouttime); - --f->retransmits; - - f->state = LS_STOPPING; - break; - - default: - FSMDEBUG((LOG_INFO, "%s: Protocol-reject event in state %d (%s)!\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - } -} - - - - - -/**********************************/ -/*** LOCAL FUNCTION DEFINITIONS ***/ -/**********************************/ - -/* - * fsm_timeout - Timeout expired. - */ -static void -fsm_timeout(void *arg) -{ - fsm *f = (fsm *) arg; - - switch (f->state) { - case LS_CLOSING: - case LS_STOPPING: - if( f->retransmits <= 0 ) { - FSMDEBUG((LOG_WARNING, "%s: timeout sending Terminate-Request state=%d (%s)\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - /* - * We've waited for an ack long enough. Peer probably heard us. - */ - f->state = (f->state == LS_CLOSING)? LS_CLOSED: LS_STOPPED; - if( f->callbacks->finished ) { - (*f->callbacks->finished)(f); - } - } else { - FSMDEBUG((LOG_WARNING, "%s: timeout resending Terminate-Requests state=%d (%s)\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - /* Send Terminate-Request */ - fsm_sdata(f, TERMREQ, f->reqid = ++f->id, - (u_char *) f->term_reason, f->term_reason_len); - TIMEOUT(fsm_timeout, f, f->timeouttime); - --f->retransmits; - } - break; - - case LS_REQSENT: - case LS_ACKRCVD: - case LS_ACKSENT: - if (f->retransmits <= 0) { - FSMDEBUG((LOG_WARNING, "%s: timeout sending Config-Requests state=%d (%s)\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - f->state = LS_STOPPED; - if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished ) { - (*f->callbacks->finished)(f); - } - } else { - FSMDEBUG((LOG_WARNING, "%s: timeout resending Config-Request state=%d (%s)\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - /* Retransmit the configure-request */ - if (f->callbacks->retransmit) { - (*f->callbacks->retransmit)(f); - } - fsm_sconfreq(f, 1); /* Re-send Configure-Request */ - if( f->state == LS_ACKRCVD ) { - f->state = LS_REQSENT; - } - } - break; - - default: - FSMDEBUG((LOG_INFO, "%s: UNHANDLED timeout event in state %d (%s)!\n", - PROTO_NAME(f), f->state, ppperr_strerr[f->state])); - } -} - - /* * fsm_rconfreq - Receive Configure-Request. */ @@ -567,7 +463,7 @@ fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) { int code, reject_if_disagree; - FSMDEBUG((LOG_INFO, "fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n", + FSMDEBUG(LOG_INFO, ("fsm_rconfreq(%s): Rcvd id %d state=%d (%s)\n", PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); switch( f->state ) { case LS_CLOSED: @@ -638,7 +534,7 @@ fsm_rconfreq(fsm *f, u_char id, u_char *inp, int len) static void fsm_rconfack(fsm *f, int id, u_char *inp, int len) { - FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n", + FSMDEBUG(LOG_INFO, ("fsm_rconfack(%s): Rcvd id %d state=%d (%s)\n", PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); if (id != f->reqid || f->seen_ack) { /* Expected id? */ @@ -646,7 +542,7 @@ fsm_rconfack(fsm *f, int id, u_char *inp, int len) } if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ) { /* Ack is bad - ignore it */ - FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)\n", + FSMDEBUG(LOG_INFO, ("%s: received bad Ack (length %d)\n", PROTO_NAME(f), len)); return; } @@ -700,7 +596,7 @@ fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) int (*proc) (fsm *, u_char *, int); int ret; - FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n", + FSMDEBUG(LOG_INFO, ("fsm_rconfnakrej(%s): Rcvd id %d state=%d (%s)\n", PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); if (id != f->reqid || f->seen_ack) { /* Expected id? */ @@ -709,7 +605,7 @@ fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci; if (!proc || !((ret = proc(f, inp, len)))) { /* Nak/reject is bad - ignore it */ - FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)\n", + FSMDEBUG(LOG_INFO, ("%s: received bad %s (length %d)\n", PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len)); return; } @@ -759,7 +655,7 @@ fsm_rtermreq(fsm *f, int id, u_char *p, int len) { LWIP_UNUSED_ARG(p); - FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n", + FSMDEBUG(LOG_INFO, ("fsm_rtermreq(%s): Rcvd id %d state=%d (%s)\n", PROTO_NAME(f), id, f->state, ppperr_strerr[f->state])); switch (f->state) { @@ -770,9 +666,9 @@ fsm_rtermreq(fsm *f, int id, u_char *p, int len) case LS_OPENED: if (len > 0) { - FSMDEBUG((LOG_INFO, "%s terminated by peer (%x)\n", PROTO_NAME(f), p)); + FSMDEBUG(LOG_INFO, ("%s terminated by peer (%p)\n", PROTO_NAME(f), p)); } else { - FSMDEBUG((LOG_INFO, "%s terminated by peer\n", PROTO_NAME(f))); + FSMDEBUG(LOG_INFO, ("%s terminated by peer\n", PROTO_NAME(f))); } if (f->callbacks->down) { (*f->callbacks->down)(f); /* Inform upper layers */ @@ -793,7 +689,7 @@ fsm_rtermreq(fsm *f, int id, u_char *p, int len) static void fsm_rtermack(fsm *f) { - FSMDEBUG((LOG_INFO, "fsm_rtermack(%s): state=%d (%s)\n", + FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): state=%d (%s)\n", PROTO_NAME(f), f->state, ppperr_strerr[f->state])); switch (f->state) { @@ -823,6 +719,9 @@ fsm_rtermack(fsm *f) } fsm_sconfreq(f, 0); break; + default: + FSMDEBUG(LOG_INFO, ("fsm_rtermack(%s): UNHANDLED state=%d (%s)!!!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); } } @@ -835,16 +734,16 @@ fsm_rcoderej(fsm *f, u_char *inp, int len) { u_char code, id; - FSMDEBUG((LOG_INFO, "fsm_rcoderej(%s): state=%d (%s)\n", + FSMDEBUG(LOG_INFO, ("fsm_rcoderej(%s): state=%d (%s)\n", PROTO_NAME(f), f->state, ppperr_strerr[f->state])); if (len < HEADERLEN) { - FSMDEBUG((LOG_INFO, "fsm_rcoderej: Rcvd short Code-Reject packet!\n")); + FSMDEBUG(LOG_INFO, ("fsm_rcoderej: Rcvd short Code-Reject packet!\n")); return; } GETCHAR(code, inp); GETCHAR(id, inp); - FSMDEBUG((LOG_WARNING, "%s: Rcvd Code-Reject for code %d, id %d\n", + FSMDEBUG(LOG_WARNING, ("%s: Rcvd Code-Reject for code %d, id %d\n", PROTO_NAME(f), code, id)); if( f->state == LS_ACKRCVD ) { @@ -853,6 +752,59 @@ fsm_rcoderej(fsm *f, u_char *inp, int len) } +/* + * fsm_protreject - Peer doesn't speak this protocol. + * + * Treat this as a catastrophic error (RXJ-). + */ +void +fsm_protreject(fsm *f) +{ + switch( f->state ) { + case LS_CLOSING: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + case LS_CLOSED: + f->state = LS_CLOSED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_STOPPING: + case LS_REQSENT: + case LS_ACKRCVD: + case LS_ACKSENT: + UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ + /* fall through */ + case LS_STOPPED: + f->state = LS_STOPPED; + if( f->callbacks->finished ) { + (*f->callbacks->finished)(f); + } + break; + + case LS_OPENED: + if( f->callbacks->down ) { + (*f->callbacks->down)(f); + } + /* Init restart counter, send Terminate-Request */ + f->retransmits = f->maxtermtransmits; + fsm_sdata(f, TERMREQ, f->reqid = ++f->id, + (u_char *) f->term_reason, f->term_reason_len); + TIMEOUT(fsm_timeout, f, f->timeouttime); + --f->retransmits; + + f->state = LS_STOPPING; + break; + + default: + FSMDEBUG(LOG_INFO, ("%s: Protocol-reject event in state %d (%s)!\n", + PROTO_NAME(f), f->state, ppperr_strerr[f->state])); + } +} + + /* * fsm_sconfreq - Send a Configure-Request. */ @@ -901,8 +853,38 @@ fsm_sconfreq(fsm *f, int retransmit) --f->retransmits; TIMEOUT(fsm_timeout, f, f->timeouttime); - FSMDEBUG((LOG_INFO, "%s: sending Configure-Request, id %d\n", + FSMDEBUG(LOG_INFO, ("%s: sending Configure-Request, id %d\n", PROTO_NAME(f), f->reqid)); } + +/* + * fsm_sdata - Send some data. + * + * Used for all packets sent to our peer by this module. + */ +void +fsm_sdata( fsm *f, u_char code, u_char id, u_char *data, int datalen) +{ + u_char *outp; + int outlen; + + /* Adjust length to be smaller than MTU */ + outp = outpacket_buf[f->unit]; + if (datalen > peer_mru[f->unit] - (int)HEADERLEN) { + datalen = peer_mru[f->unit] - HEADERLEN; + } + if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) { + BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen); + } + outlen = datalen + HEADERLEN; + MAKEHEADER(outp, f->protocol); + PUTCHAR(code, outp); + PUTCHAR(id, outp); + PUTSHORT(outlen, outp); + pppWrite(f->unit, outpacket_buf[f->unit], outlen + PPP_HDRLEN); + FSMDEBUG(LOG_INFO, ("fsm_sdata(%s): Sent code %d,%d,%d.\n", + PROTO_NAME(f), code, id, outlen)); +} + #endif /* PPP_SUPPORT */ diff --git a/lib/drivers/lwip/src/netif/ppp/fsm.h b/lib/drivers/lwip/src/netif/ppp/fsm.h index 14034ec7fdf..8d41b5f511c 100644 --- a/lib/drivers/lwip/src/netif/ppp/fsm.h +++ b/lib/drivers/lwip/src/netif/ppp/fsm.h @@ -48,15 +48,12 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: fsm.h,v 1.4 2007/12/19 20:47:23 fbernon Exp $ + * $Id: fsm.h,v 1.5 2009/12/31 17:08:08 goldsimon Exp $ */ #ifndef FSM_H #define FSM_H -/***************************************************************************** -************************* PUBLIC DEFINITIONS ********************************* -*****************************************************************************/ /* * LCP Packet header = Code, id, length. */ @@ -74,31 +71,7 @@ #define TERMACK 6 /* Termination Ack */ #define CODEREJ 7 /* Code Reject */ -/* - * Link states. - */ -#define LS_INITIAL 0 /* Down, hasn't been opened */ -#define LS_STARTING 1 /* Down, been opened */ -#define LS_CLOSED 2 /* Up, hasn't been opened */ -#define LS_STOPPED 3 /* Open, waiting for down event */ -#define LS_CLOSING 4 /* Terminating the connection, not open */ -#define LS_STOPPING 5 /* Terminating, but open */ -#define LS_REQSENT 6 /* We've sent a Config Request */ -#define LS_ACKRCVD 7 /* We've received a Config Ack */ -#define LS_ACKSENT 8 /* We've sent a Config Ack */ -#define LS_OPENED 9 /* Connection available */ -/* - * Flags - indicate options controlling FSM operation - */ -#define OPT_PASSIVE 1 /* Don't die if we don't get a response */ -#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */ -#define OPT_SILENT 4 /* Wait for peer to speak first */ - - -/***************************************************************************** -************************* PUBLIC DATA TYPES ********************************** -*****************************************************************************/ /* * Each FSM is described by an fsm structure and fsm callbacks. */ @@ -141,18 +114,27 @@ typedef struct fsm_callbacks { } fsm_callbacks; -/***************************************************************************** -*********************** PUBLIC DATA STRUCTURES ******************************* -*****************************************************************************/ /* - * Variables + * Link states. */ -extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */ +#define LS_INITIAL 0 /* Down, hasn't been opened */ +#define LS_STARTING 1 /* Down, been opened */ +#define LS_CLOSED 2 /* Up, hasn't been opened */ +#define LS_STOPPED 3 /* Open, waiting for down event */ +#define LS_CLOSING 4 /* Terminating the connection, not open */ +#define LS_STOPPING 5 /* Terminating, but open */ +#define LS_REQSENT 6 /* We've sent a Config Request */ +#define LS_ACKRCVD 7 /* We've received a Config Ack */ +#define LS_ACKSENT 8 /* We've sent a Config Ack */ +#define LS_OPENED 9 /* Connection available */ +/* + * Flags - indicate options controlling FSM operation + */ +#define OPT_PASSIVE 1 /* Don't die if we don't get a response */ +#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */ +#define OPT_SILENT 4 /* Wait for peer to speak first */ -/***************************************************************************** -************************** PUBLIC FUNCTIONS ********************************** -*****************************************************************************/ /* * Prototypes @@ -166,4 +148,10 @@ void fsm_input (fsm*, u_char*, int); void fsm_protreject (fsm*); void fsm_sdata (fsm*, u_char, u_char, u_char*, int); + +/* + * Variables + */ +extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */ + #endif /* FSM_H */ diff --git a/lib/drivers/lwip/src/netif/ppp/ipcp.c b/lib/drivers/lwip/src/netif/ppp/ipcp.c index 0ff4ce3fff4..461a600f85c 100644 --- a/lib/drivers/lwip/src/netif/ppp/ipcp.c +++ b/lib/drivers/lwip/src/netif/ppp/ipcp.c @@ -1,3 +1,5 @@ +/** In contrast to pppd 2.3.1, DNS support has been added, proxy-ARP and + dial-on-demand has been stripped. */ /***************************************************************************** * ipcp.c - Network PPP IP Control Protocol program file. * @@ -61,27 +63,23 @@ #include "vj.h" #include "ipcp.h" +#include "lwip/inet.h" + #include -/*************************/ -/*** LOCAL DEFINITIONS ***/ -/*************************/ /* #define OLD_CI_ADDRS 1 */ /* Support deprecated address negotiation. */ -/* - * Lengths of configuration options. - */ -#define CILEN_VOID 2 -#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ -#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ -#define CILEN_ADDR 6 /* new-style single address option */ -#define CILEN_ADDRS 10 /* old-style dual address option */ +/* global vars */ +ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ +ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ +ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ +ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ + +/* local vars */ +static int default_route_set[NUM_PPP]; /* Have set up a default route */ +static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ - -/***********************************/ -/*** LOCAL FUNCTION DECLARATIONS ***/ -/***********************************/ /* * Callbacks for fsm code. (CI = Configuration Information) */ @@ -94,70 +92,14 @@ static int ipcp_rejci (fsm *, u_char *, int); /* Peer rej'd our CI */ static int ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */ static void ipcp_up (fsm *); /* We're UP */ static void ipcp_down (fsm *); /* We're DOWN */ -#if 0 +#if PPP_ADDITIONAL_CALLBACKS static void ipcp_script (fsm *, char *); /* Run an up/down script */ #endif static void ipcp_finished (fsm *); /* Don't need lower layer */ -/* - * Protocol entry points from main code. - */ -static void ipcp_init (int); -static void ipcp_open (int); -static void ipcp_close (int, char *); -static void ipcp_lowerup (int); -static void ipcp_lowerdown (int); -static void ipcp_input (int, u_char *, int); -static void ipcp_protrej (int); - -static void ipcp_clear_addrs (int); - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ - (x) == CONFNAK ? "NAK" : "REJ") - - - -/******************************/ -/*** PUBLIC DATA STRUCTURES ***/ -/******************************/ -/* global vars */ -ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ -ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ -ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ -ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ -struct protent ipcp_protent = { - PPP_IPCP, - ipcp_init, - ipcp_input, - ipcp_protrej, - ipcp_lowerup, - ipcp_lowerdown, - ipcp_open, - ipcp_close, -#if 0 - ipcp_printpkt, - NULL, -#endif - 1, - "IPCP", -#if 0 - ip_check_options, - NULL, - ip_active_pkt -#endif -}; - - - -/*****************************/ -/*** LOCAL DATA STRUCTURES ***/ -/*****************************/ -/* local vars */ -static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ -static int default_route_set[NUM_PPP]; /* Have set up a default route */ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ ipcp_resetci, /* Reset our Configuration Information */ @@ -177,13 +119,55 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ "IPCP" /* String name of protocol */ }; +/* + * Protocol entry points from main code. + */ +static void ipcp_init (int); +static void ipcp_open (int); +static void ipcp_close (int, char *); +static void ipcp_lowerup (int); +static void ipcp_lowerdown (int); +static void ipcp_input (int, u_char *, int); +static void ipcp_protrej (int); -/**********************************/ -/*** LOCAL FUNCTION DEFINITIONS ***/ -/**********************************/ +struct protent ipcp_protent = { + PPP_IPCP, + ipcp_init, + ipcp_input, + ipcp_protrej, + ipcp_lowerup, + ipcp_lowerdown, + ipcp_open, + ipcp_close, +#if PPP_ADDITIONAL_CALLBACKS + ipcp_printpkt, + NULL, +#endif /* PPP_ADDITIONAL_CALLBACKS */ + 1, + "IPCP", +#if PPP_ADDITIONAL_CALLBACKS + ip_check_options, + NULL, + ip_active_pkt +#endif /* PPP_ADDITIONAL_CALLBACKS */ +}; + +static void ipcp_clear_addrs (int); + +/* + * Lengths of configuration options. + */ +#define CILEN_VOID 2 +#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */ +#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */ +#define CILEN_ADDR 6 /* new-style single address option */ +#define CILEN_ADDRS 10 /* old-style dual address option */ + + +#define CODENAME(x) ((x) == CONFACK ? "ACK" : \ + (x) == CONFNAK ? "NAK" : "REJ") -#define inet_ntoa(addr) ip_ntoa(((struct ip_addr*)&(addr))) /* * ipcp_init - Initialize IPCP. @@ -542,9 +526,9 @@ ipcp_ackci(fsm *f, u_char *p, int len) goto bad; } return (1); - + bad: - IPCPDEBUG((LOG_INFO, "ipcp_ackci: received bad Ack!\n")); + IPCPDEBUG(LOG_INFO, ("ipcp_ackci: received bad Ack!\n")); return (0); } @@ -628,12 +612,12 @@ ipcp_nakci(fsm *f, u_char *p, int len) NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs, if (go->accept_local && ciaddr1) { /* Do we know our address? */ try.ouraddr = ciaddr1; - IPCPDEBUG((LOG_INFO, "local IP address %s\n", + IPCPDEBUG(LOG_INFO, ("local IP address %s\n", inet_ntoa(ciaddr1))); } if (go->accept_remote && ciaddr2) { /* Does he know his? */ try.hisaddr = ciaddr2; - IPCPDEBUG((LOG_INFO, "remote IP address %s\n", + IPCPDEBUG(LOG_INFO, ("remote IP address %s\n", inet_ntoa(ciaddr2))); } ); @@ -671,12 +655,12 @@ ipcp_nakci(fsm *f, u_char *p, int len) NAKCIDNS(CI_MS_DNS1, req_dns1, try.dnsaddr[0] = cidnsaddr; - IPCPDEBUG((LOG_INFO, "primary DNS address %s\n", inet_ntoa(cidnsaddr))); + IPCPDEBUG(LOG_INFO, ("primary DNS address %s\n", inet_ntoa(cidnsaddr))); ); NAKCIDNS(CI_MS_DNS2, req_dns2, try.dnsaddr[1] = cidnsaddr; - IPCPDEBUG((LOG_INFO, "secondary DNS address %s\n", inet_ntoa(cidnsaddr))); + IPCPDEBUG(LOG_INFO, ("secondary DNS address %s\n", inet_ntoa(cidnsaddr))); ); /* @@ -754,7 +738,7 @@ ipcp_nakci(fsm *f, u_char *p, int len) return 1; bad: - IPCPDEBUG((LOG_INFO, "ipcp_nakci: received bad Nak!\n")); + IPCPDEBUG(LOG_INFO, ("ipcp_nakci: received bad Nak!\n")); return 0; } @@ -869,7 +853,7 @@ ipcp_rejci(fsm *f, u_char *p, int len) return 1; bad: - IPCPDEBUG((LOG_INFO, "ipcp_rejci: received bad Reject!\n")); + IPCPDEBUG(LOG_INFO, ("ipcp_rejci: received bad Reject!\n")); return 0; } @@ -922,9 +906,9 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested if (l < 2 || /* Not enough data for CI header or */ p[1] < 2 || /* CI length too small or */ p[1] > l) { /* CI length too big? */ - IPCPDEBUG((LOG_INFO, "ipcp_reqci: bad CI length!\n")); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: bad CI length!\n")); orc = CONFREJ; /* Reject bad CI */ - cilen = l; /* Reject till end of packet */ + cilen = (u_short)l;/* Reject till end of packet */ l = 0; /* Don't loop again */ goto endswitch; } @@ -936,7 +920,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested switch (citype) { /* Check CI type */ #ifdef OLD_CI_ADDRS /* Need to save space... */ case CI_ADDRS: - IPCPDEBUG((LOG_INFO, "ipcp_reqci: received ADDRS\n")); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received ADDRS\n")); if (!ao->neg_addr || cilen != CILEN_ADDRS) { /* Check CI length */ orc = CONFREJ; /* Reject CI */ @@ -951,7 +935,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested */ GETLONG(tl, p); /* Parse source address (his) */ ciaddr1 = htonl(tl); - IPCPDEBUG((LOG_INFO, "his addr %s\n", inet_ntoa(ciaddr1))); + IPCPDEBUG(LOG_INFO, ("his addr %s\n", inet_ntoa(ciaddr1))); if (ciaddr1 != wo->hisaddr && (ciaddr1 == 0 || !wo->accept_remote)) { orc = CONFNAK; @@ -975,7 +959,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested */ GETLONG(tl, p); /* Parse desination address (ours) */ ciaddr2 = htonl(tl); - IPCPDEBUG((LOG_INFO, "our addr %s\n", inet_ntoa(ciaddr2))); + IPCPDEBUG(LOG_INFO, ("our addr %s\n", inet_ntoa(ciaddr2))); if (ciaddr2 != wo->ouraddr) { if (ciaddr2 == 0 || !wo->accept_local) { orc = CONFNAK; @@ -998,11 +982,11 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested case CI_ADDR: if (!ao->neg_addr) { - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR not allowed\n")); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR not allowed\n")); orc = CONFREJ; /* Reject CI */ break; } else if (cilen != CILEN_ADDR) { /* Check CI length */ - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR bad len\n")); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR bad len\n")); orc = CONFREJ; /* Reject CI */ break; } @@ -1023,12 +1007,12 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested tl = ntohl(wo->hisaddr); PUTLONG(tl, p); } - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1))); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1))); } else if (ciaddr1 == 0 && wo->hisaddr == 0) { /* * Don't ACK an address of 0.0.0.0 - reject it instead. */ - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1))); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1))); orc = CONFREJ; wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ break; @@ -1036,7 +1020,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested ho->neg_addr = 1; ho->hisaddr = ciaddr1; - IPCPDEBUG((LOG_INFO, "ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1))); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1))); break; case CI_MS_DNS1: @@ -1047,27 +1031,27 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested /* If we do not have a DNS address then we cannot send it */ if (ao->dnsaddr[d] == 0 || cilen != CILEN_ADDR) { /* Check CI length */ - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting DNS%d Request\n", d+1)); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting DNS%d Request\n", d+1)); orc = CONFREJ; /* Reject CI */ break; } GETLONG(tl, p); if (htonl(tl) != ao->dnsaddr[d]) { - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking DNS%d Request %d\n", + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking DNS%d Request %s\n", d+1, inet_ntoa(tl))); DECPTR(sizeof(u32_t), p); tl = ntohl(ao->dnsaddr[d]); PUTLONG(tl, p); orc = CONFNAK; } - IPCPDEBUG((LOG_INFO, "ipcp_reqci: received DNS%d Request\n", d+1)); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received DNS%d Request\n", d+1)); break; case CI_MS_WINS1: case CI_MS_WINS2: /* Microsoft primary or secondary WINS request */ d = citype == CI_MS_WINS2; - IPCPDEBUG((LOG_INFO, "ipcp_reqci: received WINS%d Request\n", d+1)); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: received WINS%d Request\n", d+1)); /* If we do not have a DNS address then we cannot send it */ if (ao->winsaddr[d] == 0 || @@ -1086,11 +1070,11 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested case CI_COMPRESSTYPE: if (!ao->neg_vj) { - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n")); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n")); orc = CONFREJ; break; } else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) { - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen)); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen)); orc = CONFREJ; break; } @@ -1098,7 +1082,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested if (!(cishort == IPCP_VJ_COMP || (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) { - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort)); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort)); orc = CONFREJ; break; } @@ -1108,7 +1092,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested if (cilen == CILEN_VJ) { GETCHAR(maxslotindex, p); if (maxslotindex > ao->maxslotindex) { - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ max slot %d\n", maxslotindex)); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ max slot %d\n", maxslotindex)); orc = CONFNAK; if (!reject_if_disagree) { DECPTR(1, p); @@ -1117,7 +1101,7 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested } GETCHAR(cflag, p); if (cflag && !ao->cflag) { - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ cflag %d\n", cflag)); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Naking VJ cflag %d\n", cflag)); orc = CONFNAK; if (!reject_if_disagree) { DECPTR(1, p); @@ -1131,13 +1115,13 @@ ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested ho->maxslotindex = MAX_SLOTS - 1; ho->cflag = 1; } - IPCPDEBUG((LOG_INFO, + IPCPDEBUG(LOG_INFO, ( "ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n", ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag)); break; default: - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting unknown CI type %d\n", citype)); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting unknown CI type %d\n", citype)); orc = CONFREJ; break; } @@ -1150,7 +1134,7 @@ endswitch: if (orc == CONFNAK) { /* Nak this CI? */ if (reject_if_disagree) { /* Getting fed up with sending NAKs? */ - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting too many naks\n")); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Rejecting too many naks\n")); orc = CONFREJ; /* Get tough if so */ } else { if (rc == CONFREJ) { /* Rejecting prior CI? */ @@ -1187,7 +1171,7 @@ endswitch: */ if (rc != CONFREJ && !ho->neg_addr && wo->req_addr && !reject_if_disagree) { - IPCPDEBUG((LOG_INFO, "ipcp_reqci: Requesting peer address\n")); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: Requesting peer address\n")); if (rc == CONFACK) { rc = CONFNAK; ucp = inp; /* reset pointer */ @@ -1200,7 +1184,7 @@ endswitch: } *len = (int)(ucp - inp); /* Compute output length */ - IPCPDEBUG((LOG_INFO, "ipcp_reqci: returning Configure-%s\n", CODENAME(rc))); + IPCPDEBUG(LOG_INFO, ("ipcp_reqci: returning Configure-%s\n", CODENAME(rc))); return (rc); /* Return final code */ } @@ -1241,7 +1225,7 @@ ipcp_up(fsm *f) ipcp_options *wo = &ipcp_wantoptions[f->unit]; np_up(f->unit, PPP_IP); - IPCPDEBUG((LOG_INFO, "ipcp: up\n")); + IPCPDEBUG(LOG_INFO, ("ipcp: up\n")); /* * We must have a non-zero IP address for both ends of the link. @@ -1251,12 +1235,12 @@ ipcp_up(fsm *f) } if (ho->hisaddr == 0) { - IPCPDEBUG((LOG_ERR, "Could not determine remote IP address\n")); + IPCPDEBUG(LOG_ERR, ("Could not determine remote IP address\n")); ipcp_close(f->unit, "Could not determine remote IP address"); return; } if (go->ouraddr == 0) { - IPCPDEBUG((LOG_ERR, "Could not determine local IP address\n")); + IPCPDEBUG(LOG_ERR, ("Could not determine local IP address\n")); ipcp_close(f->unit, "Could not determine local IP address"); return; } @@ -1269,7 +1253,7 @@ ipcp_up(fsm *f) * Check that the peer is allowed to use the IP address it wants. */ if (!auth_ip_addr(f->unit, ho->hisaddr)) { - IPCPDEBUG((LOG_ERR, "Peer is not authorized to use remote address %s\n", + IPCPDEBUG(LOG_ERR, ("Peer is not authorized to use remote address %s\n", inet_ntoa(ho->hisaddr))); ipcp_close(f->unit, "Unauthorized remote IP address"); return; @@ -1284,14 +1268,14 @@ ipcp_up(fsm *f) mask = GetMask(go->ouraddr); if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) { - IPCPDEBUG((LOG_WARNING, "sifaddr failed\n")); + IPCPDEBUG(LOG_WARNING, ("sifaddr failed\n")); ipcp_close(f->unit, "Interface configuration failed"); return; } /* bring the interface up for IP */ if (!sifup(f->unit)) { - IPCPDEBUG((LOG_WARNING, "sifup failed\n")); + IPCPDEBUG(LOG_WARNING, ("sifup failed\n")); ipcp_close(f->unit, "Interface configuration failed"); return; } @@ -1305,13 +1289,13 @@ ipcp_up(fsm *f) } } - IPCPDEBUG((LOG_NOTICE, "local IP address %s\n", inet_ntoa(go->ouraddr))); - IPCPDEBUG((LOG_NOTICE, "remote IP address %s\n", inet_ntoa(ho->hisaddr))); + IPCPDEBUG(LOG_NOTICE, ("local IP address %s\n", inet_ntoa(go->ouraddr))); + IPCPDEBUG(LOG_NOTICE, ("remote IP address %s\n", inet_ntoa(ho->hisaddr))); if (go->dnsaddr[0]) { - IPCPDEBUG((LOG_NOTICE, "primary DNS address %s\n", inet_ntoa(go->dnsaddr[0]))); + IPCPDEBUG(LOG_NOTICE, ("primary DNS address %s\n", inet_ntoa(go->dnsaddr[0]))); } if (go->dnsaddr[1]) { - IPCPDEBUG((LOG_NOTICE, "secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1]))); + IPCPDEBUG(LOG_NOTICE, ("secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1]))); } } @@ -1325,7 +1309,7 @@ ipcp_up(fsm *f) static void ipcp_down(fsm *f) { - IPCPDEBUG((LOG_INFO, "ipcp: down\n")); + IPCPDEBUG(LOG_INFO, ("ipcp: down\n")); np_down(f->unit, PPP_IP); sifvjcomp(f->unit, 0, 0, 0); @@ -1361,7 +1345,7 @@ ipcp_finished(fsm *f) np_finished(f->unit, PPP_IP); } -#if 0 +#if PPP_ADDITIONAL_CALLBACKS static int ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg) { @@ -1422,6 +1406,6 @@ ip_active_pkt(u_char *pkt, int len) } return 1; } -#endif +#endif /* PPP_ADDITIONAL_CALLBACKS */ #endif /* PPP_SUPPORT */ diff --git a/lib/drivers/lwip/src/netif/ppp/ipcp.h b/lib/drivers/lwip/src/netif/ppp/ipcp.h index dfcf4fba61f..de03f460ecb 100644 --- a/lib/drivers/lwip/src/netif/ppp/ipcp.h +++ b/lib/drivers/lwip/src/netif/ppp/ipcp.h @@ -48,15 +48,12 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: ipcp.h,v 1.3 2007/12/19 20:47:23 fbernon Exp $ + * $Id: ipcp.h,v 1.4 2010/01/18 20:49:43 goldsimon Exp $ */ #ifndef IPCP_H #define IPCP_H -/************************* -*** PUBLIC DEFINITIONS *** -*************************/ /* * Options. */ @@ -64,10 +61,10 @@ #define CI_COMPRESSTYPE 2 /* Compression Type */ #define CI_ADDR 3 -#define CI_MS_WINS1 128 /* Primary WINS value */ #define CI_MS_DNS1 129 /* Primary DNS value */ -#define CI_MS_WINS2 130 /* Secondary WINS value */ +#define CI_MS_WINS1 128 /* Primary WINS value */ #define CI_MS_DNS2 131 /* Secondary DNS value */ +#define CI_MS_WINS2 130 /* Secondary WINS value */ #define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */ #define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */ @@ -78,11 +75,6 @@ #define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */ /* compression option */ - -/************************ -*** PUBLIC DATA TYPES *** -************************/ - typedef struct ipcp_options { u_int neg_addr : 1; /* Negotiate IP Address? */ u_int old_addrs : 1; /* Use old (IP-Addresses) option? */ @@ -103,11 +95,6 @@ typedef struct ipcp_options { u32_t winsaddr[2]; /* Primary and secondary MS WINS entries */ } ipcp_options; - -/***************************** -*** PUBLIC DATA STRUCTURES *** -*****************************/ - extern fsm ipcp_fsm[]; extern ipcp_options ipcp_wantoptions[]; extern ipcp_options ipcp_gotoptions[]; @@ -116,9 +103,4 @@ extern ipcp_options ipcp_hisoptions[]; extern struct protent ipcp_protent; - -/*********************** -*** PUBLIC FUNCTIONS *** -***********************/ - #endif /* IPCP_H */ diff --git a/lib/drivers/lwip/src/netif/ppp/lcp.c b/lib/drivers/lwip/src/netif/ppp/lcp.c index 85a0add95b7..21c83ac4449 100644 --- a/lib/drivers/lwip/src/netif/ppp/lcp.c +++ b/lib/drivers/lwip/src/netif/ppp/lcp.c @@ -72,25 +72,43 @@ #define PPPOE_MAXMTU PPP_MAXMRU #endif - -/*************************/ -/*** LOCAL DEFINITIONS ***/ -/*************************/ +#if 0 /* UNUSED */ /* - * Length of each type of configuration option (in octets) + * LCP-related command-line options. */ -#define CILEN_VOID 2 -#define CILEN_CHAR 3 -#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */ -#define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */ -#define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */ -#define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */ -#define CILEN_CBCP 3 +int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ +int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ +bool lax_recv = 0; /* accept control chars in asyncmap */ +static int setescape (char **); + +static option_t lcp_option_list[] = { + /* LCP options */ + /* list stripped for simplicity */ + {NULL} +}; +#endif /* UNUSED */ + +/* options */ +LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */ +static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */ +static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */ + +/* global vars */ +static fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/ +lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */ +lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ +lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ +lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ +ext_accm xmit_accm[NUM_PPP]; /* extended transmit ACCM */ + +static u32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */ +static u32_t lcp_echo_number = 0; /* ID number of next echo frame */ +static u32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */ + +/* @todo: do we really need such a large buffer? The typical 1500 bytes seem too much. */ +static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */ -/***********************************/ -/*** LOCAL FUNCTION DECLARATIONS ***/ -/***********************************/ /* * Callbacks for fsm code. (CI = Configuration Information) */ @@ -106,12 +124,12 @@ static void lcp_down (fsm*); /* We're DOWN */ static void lcp_starting (fsm*); /* We need lower layer up */ static void lcp_finished (fsm*); /* We need lower layer down */ static int lcp_extcode (fsm*, int, u_char, u_char*, int); - static void lcp_rprotrej (fsm*, u_char*, int); /* * routines to send LCP echos to peer */ + static void lcp_echo_lowerup (int); static void lcp_echo_lowerdown (int); static void LcpEchoTimeout (void*); @@ -120,41 +138,6 @@ static void LcpSendEchoRequest (fsm*); static void LcpLinkFailure (fsm*); static void LcpEchoCheck (fsm*); -/* - * Protocol entry points. - * Some of these are called directly. - */ -static void lcp_input (int, u_char *, int); -static void lcp_protrej (int); - -#define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ") - - -/******************************/ -/*** PUBLIC DATA STRUCTURES ***/ -/******************************/ -/* global vars */ -LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */ -lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */ -lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ -lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ -lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ -ext_accm xmit_accm[NUM_PPP]; /* extended transmit ACCM */ - - - -/*****************************/ -/*** LOCAL DATA STRUCTURES ***/ -/*****************************/ -static fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/ -static u_int lcp_echo_interval = LCP_ECHOINTERVAL; /* Interval between LCP echo-requests */ -static u_int lcp_echo_fails = LCP_MAXECHOFAILS; /* Tolerance to unanswered echo-requests */ -static u32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */ -static u32_t lcp_echo_number = 0; /* ID number of next echo frame */ -static u32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */ - -static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */ - static fsm_callbacks lcp_callbacks = { /* LCP callback routines */ lcp_resetci, /* Reset our Configuration Information */ lcp_cilen, /* Length of our Configuration Information */ @@ -173,6 +156,14 @@ static fsm_callbacks lcp_callbacks = { /* LCP callback routines */ "LCP" /* String name of protocol */ }; +/* + * Protocol entry points. + * Some of these are called directly. + */ + +static void lcp_input (int, u_char *, int); +static void lcp_protrej (int); + struct protent lcp_protent = { PPP_LCP, lcp_init, @@ -182,26 +173,66 @@ struct protent lcp_protent = { lcp_lowerdown, lcp_open, lcp_close, -#if 0 +#if PPP_ADDITIONAL_CALLBACKS lcp_printpkt, NULL, -#endif +#endif /* PPP_ADDITIONAL_CALLBACKS */ 1, "LCP", -#if 0 +#if PPP_ADDITIONAL_CALLBACKS NULL, NULL, NULL -#endif +#endif /* PPP_ADDITIONAL_CALLBACKS */ }; int lcp_loopbackfail = DEFLOOPBACKFAIL; +/* + * Length of each type of configuration option (in octets) + */ +#define CILEN_VOID 2 +#define CILEN_CHAR 3 +#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */ +#define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */ +#define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */ +#define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */ +#define CILEN_CBCP 3 +#define CODENAME(x) ((x) == CONFACK ? "ACK" : (x) == CONFNAK ? "NAK" : "REJ") + +#if 0 /* UNUSED */ +/* + * setescape - add chars to the set we escape on transmission. + */ +static int +setescape(argv) + char **argv; +{ + int n, ret; + char *p, *endp; + + p = *argv; + ret = 1; + while (*p) { + n = strtol(p, &endp, 16); + if (p == endp) { + option_error("escape parameter contains invalid hex number '%s'", p); + return 0; + } + p = endp; + if (n < 0 || n == 0x5E || n > 0xFF) { + option_error("can't escape character 0x%x", n); + ret = 0; + } else + xmit_accm[0][n >> 5] |= 1 << (n & 0x1F); + while (*p == ',' || *p == ' ') + ++p; + } + return ret; +} +#endif /* UNUSED */ -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ /* * lcp_init - Initialize LCP. */ @@ -211,13 +242,13 @@ lcp_init(int unit) fsm *f = &lcp_fsm[unit]; lcp_options *wo = &lcp_wantoptions[unit]; lcp_options *ao = &lcp_allowoptions[unit]; - + f->unit = unit; f->protocol = PPP_LCP; f->callbacks = &lcp_callbacks; - + fsm_init(f); - + wo->passive = 0; wo->silent = 0; wo->restart = 0; /* Set to 1 in kernels or multi-line implementations */ @@ -233,7 +264,7 @@ lcp_init(int unit) wo->neg_accompression = 1; wo->neg_lqr = 0; /* no LQR implementation yet */ wo->neg_cbcp = 0; - + ao->neg_mru = 1; ao->mru = PPP_MAXMRU; ao->neg_asyncmap = 1; @@ -257,7 +288,7 @@ lcp_init(int unit) xmit_accm[unit][1] = (u_char)((ao->asyncmap >> 8) & 0xFF); xmit_accm[unit][2] = (u_char)((ao->asyncmap >> 16) & 0xFF); xmit_accm[unit][3] = (u_char)((ao->asyncmap >> 24) & 0xFF); - LCPDEBUG((LOG_INFO, "lcp_init: xmit_accm=%X %X %X %X\n", + LCPDEBUG(LOG_INFO, ("lcp_init: xmit_accm=%X %X %X %X\n", xmit_accm[unit][0], xmit_accm[unit][1], xmit_accm[unit][2], @@ -310,7 +341,7 @@ lcp_close(int unit, char *reason) f->state = LS_CLOSED; lcp_finished(f); } else { - fsm_close(&lcp_fsm[unit], reason); + fsm_close(f, reason); } } @@ -337,7 +368,7 @@ lcp_lowerup(int unit) | ((u_long)xmit_accm[unit][1] << 8) | ((u_long)xmit_accm[unit][2] << 16) | ((u_long)xmit_accm[unit][3] << 24); - LCPDEBUG((LOG_INFO, "lcp_lowerup: asyncmap=%X %X %X %X\n", + LCPDEBUG(LOG_INFO, ("lcp_lowerup: asyncmap=%X %X %X %X\n", xmit_accm[unit][3], xmit_accm[unit][2], xmit_accm[unit][1], @@ -356,25 +387,7 @@ lcp_lowerdown(int unit) fsm_lowerdown(&lcp_fsm[unit]); } -/* - * lcp_sprotrej - Send a Protocol-Reject for some protocol. - */ -void -lcp_sprotrej(int unit, u_char *p, int len) -{ - /* - * Send back the protocol and the information field of the - * rejected packet. We only get here if LCP is in the LS_OPENED state. - */ - fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len); -} - - - -/**********************************/ -/*** LOCAL FUNCTION DEFINITIONS ***/ -/**********************************/ /* * lcp_input - Input LCP packet. */ @@ -404,7 +417,7 @@ lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len) if (f->state != LS_OPENED) { break; } - LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d\n", id)); + LCPDEBUG(LOG_INFO, ("lcp: Echo-Request, Rcvd id %d\n", id)); magp = inp; PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp); fsm_sdata(f, ECHOREP, id, inp, len); @@ -413,10 +426,10 @@ lcp_extcode(fsm *f, int code, u_char id, u_char *inp, int len) case ECHOREP: lcp_received_echo_reply(f, id, inp, len); break; - + case DISCREQ: break; - + default: return 0; } @@ -436,21 +449,21 @@ lcp_rprotrej(fsm *f, u_char *inp, int len) struct protent *protp; u_short prot; - if (len < sizeof (u_short)) { - LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd short Protocol-Reject packet!\n")); + if (len < (int)sizeof (u_short)) { + LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd short Protocol-Reject packet!\n")); return; } GETSHORT(prot, inp); - LCPDEBUG((LOG_INFO, "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot)); + LCPDEBUG(LOG_INFO, ("lcp_rprotrej: Rcvd Protocol-Reject packet for %x!\n", prot)); /* * Protocol-Reject packets received in any state other than the LCP * LS_OPENED state SHOULD be silently discarded. */ if( f->state != LS_OPENED ) { - LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d\n", f->state)); + LCPDEBUG(LOG_INFO, ("Protocol-Reject discarded: LCP in state %d\n", f->state)); return; } @@ -464,7 +477,7 @@ lcp_rprotrej(fsm *f, u_char *inp, int len) } } - LCPDEBUG((LOG_WARNING, "Protocol-Reject for unsupported protocol 0x%x\n", prot)); + LCPDEBUG(LOG_WARNING, ("Protocol-Reject for unsupported protocol 0x%x\n", prot)); } @@ -478,11 +491,26 @@ lcp_protrej(int unit) /* * Can't reject LCP! */ - LCPDEBUG((LOG_WARNING, "lcp_protrej: Received Protocol-Reject for LCP!\n")); + LCPDEBUG(LOG_WARNING, ("lcp_protrej: Received Protocol-Reject for LCP!\n")); fsm_protreject(&lcp_fsm[unit]); } +/* + * lcp_sprotrej - Send a Protocol-Reject for some protocol. + */ +void +lcp_sprotrej(int unit, u_char *p, int len) +{ + /* + * Send back the protocol and the information field of the + * rejected packet. We only get here if LCP is in the LS_OPENED state. + */ + + fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id, p, len); +} + + /* * lcp_resetci - Reset our CI. */ @@ -500,7 +528,8 @@ lcp_resetci(fsm *f) /* * lcp_cilen - Return length of our CI. */ -static int lcp_cilen(fsm *f) +static int +lcp_cilen(fsm *f) { lcp_options *go = &lcp_gotoptions[f->unit]; @@ -537,20 +566,20 @@ lcp_addci(fsm *f, u_char *ucp, int *lenp) #define ADDCIVOID(opt, neg) \ if (neg) { \ - LCPDEBUG((LOG_INFO, "lcp_addci: opt=%d\n", opt)); \ + LCPDEBUG(LOG_INFO, ("lcp_addci: opt=%d\n", opt)); \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_VOID, ucp); \ } #define ADDCISHORT(opt, neg, val) \ if (neg) { \ - LCPDEBUG((LOG_INFO, "lcp_addci: INT opt=%d %X\n", opt, val)); \ + LCPDEBUG(LOG_INFO, ("lcp_addci: INT opt=%d %X\n", opt, val)); \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_SHORT, ucp); \ PUTSHORT(val, ucp); \ } #define ADDCICHAP(opt, neg, val, digest) \ if (neg) { \ - LCPDEBUG((LOG_INFO, "lcp_addci: CHAP opt=%d %X\n", opt, val)); \ + LCPDEBUG(LOG_INFO, ("lcp_addci: CHAP opt=%d %X\n", opt, val)); \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_CHAP, ucp); \ PUTSHORT(val, ucp); \ @@ -558,14 +587,14 @@ lcp_addci(fsm *f, u_char *ucp, int *lenp) } #define ADDCILONG(opt, neg, val) \ if (neg) { \ - LCPDEBUG((LOG_INFO, "lcp_addci: L opt=%d %lX\n", opt, val)); \ + LCPDEBUG(LOG_INFO, ("lcp_addci: L opt=%d %lX\n", opt, val)); \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_LONG, ucp); \ PUTLONG(val, ucp); \ } #define ADDCILQR(opt, neg, val) \ if (neg) { \ - LCPDEBUG((LOG_INFO, "lcp_addci: LQR opt=%d %lX\n", opt, val)); \ + LCPDEBUG(LOG_INFO, ("lcp_addci: LQR opt=%d %lX\n", opt, val)); \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_LQR, ucp); \ PUTSHORT(PPP_LQR, ucp); \ @@ -573,7 +602,7 @@ lcp_addci(fsm *f, u_char *ucp, int *lenp) } #define ADDCICHAR(opt, neg, val) \ if (neg) { \ - LCPDEBUG((LOG_INFO, "lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \ + LCPDEBUG(LOG_INFO, ("lcp_addci: CHAR opt=%d %X '%z'\n", opt, val, val)); \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_CHAR, ucp); \ PUTCHAR(val, ucp); \ @@ -591,7 +620,7 @@ lcp_addci(fsm *f, u_char *ucp, int *lenp) if (ucp - start_ucp != *lenp) { /* this should never happen, because peer_mtu should be 1500 */ - LCPDEBUG((LOG_ERR, "Bug in lcp_addci: wrong length\n")); + LCPDEBUG(LOG_ERR, ("Bug in lcp_addci: wrong length\n")); } } @@ -709,10 +738,10 @@ lcp_ackci(fsm *f, u_char *p, int len) if (len != 0) { goto bad; } - LCPDEBUG((LOG_INFO, "lcp_acki: Ack\n")); + LCPDEBUG(LOG_INFO, ("lcp_acki: Ack\n")); return (1); bad: - LCPDEBUG((LOG_WARNING, "lcp_acki: received bad Ack!\n")); + LCPDEBUG(LOG_WARNING, ("lcp_acki: received bad Ack!\n")); return (0); } @@ -1020,7 +1049,7 @@ lcp_nakci(fsm *f, u_char *p, int len) if (f->state != LS_OPENED) { if (looped_back) { if (++try.numloops >= lcp_loopbackfail) { - LCPDEBUG((LOG_NOTICE, "Serial line is looped back.\n")); + LCPDEBUG(LOG_NOTICE, ("Serial line is looped back.\n")); lcp_close(f->unit, "Loopback detected"); } } else { @@ -1032,7 +1061,7 @@ lcp_nakci(fsm *f, u_char *p, int len) return 1; bad: - LCPDEBUG((LOG_WARNING, "lcp_nakci: received bad Nak!\n")); + LCPDEBUG(LOG_WARNING, ("lcp_nakci: received bad Nak!\n")); return 0; } @@ -1070,7 +1099,7 @@ lcp_rejci(fsm *f, u_char *p, int len) len -= CILEN_VOID; \ INCPTR(CILEN_VOID, p); \ try.neg = 0; \ - LCPDEBUG((LOG_INFO, "lcp_rejci: void opt %d rejected\n", opt)); \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: void opt %d rejected\n", opt)); \ } #define REJCISHORT(opt, neg, val) \ if (go->neg && \ @@ -1085,7 +1114,7 @@ lcp_rejci(fsm *f, u_char *p, int len) goto bad; \ } \ try.neg = 0; \ - LCPDEBUG((LOG_INFO,"lcp_rejci: short opt %d rejected\n", opt)); \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: short opt %d rejected\n", opt)); \ } #define REJCICHAP(opt, neg, val, digest) \ if (go->neg && \ @@ -1102,7 +1131,7 @@ lcp_rejci(fsm *f, u_char *p, int len) } \ try.neg = 0; \ try.neg_upap = 0; \ - LCPDEBUG((LOG_INFO,"lcp_rejci: chap opt %d rejected\n", opt)); \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: chap opt %d rejected\n", opt)); \ } #define REJCILONG(opt, neg, val) \ if (go->neg && \ @@ -1117,7 +1146,7 @@ lcp_rejci(fsm *f, u_char *p, int len) goto bad; \ } \ try.neg = 0; \ - LCPDEBUG((LOG_INFO,"lcp_rejci: long opt %d rejected\n", opt)); \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: long opt %d rejected\n", opt)); \ } #define REJCILQR(opt, neg, val) \ if (go->neg && \ @@ -1133,7 +1162,7 @@ lcp_rejci(fsm *f, u_char *p, int len) goto bad; \ } \ try.neg = 0; \ - LCPDEBUG((LOG_INFO,"lcp_rejci: LQR opt %d rejected\n", opt)); \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: LQR opt %d rejected\n", opt)); \ } #define REJCICBCP(opt, neg, val) \ if (go->neg && \ @@ -1148,7 +1177,7 @@ lcp_rejci(fsm *f, u_char *p, int len) goto bad; \ } \ try.neg = 0; \ - LCPDEBUG((LOG_INFO,"lcp_rejci: Callback opt %d rejected\n", opt)); \ + LCPDEBUG(LOG_INFO, ("lcp_rejci: Callback opt %d rejected\n", opt)); \ } REJCISHORT(CI_MRU, neg_mru, go->mru); @@ -1178,7 +1207,7 @@ lcp_rejci(fsm *f, u_char *p, int len) return 1; bad: - LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!\n")); + LCPDEBUG(LOG_WARNING, ("lcp_rejci: received bad Reject!\n")); return 0; } @@ -1200,7 +1229,8 @@ lcp_reqci(fsm *f, lcp_options *ho = &lcp_hisoptions[f->unit]; lcp_options *ao = &lcp_allowoptions[f->unit]; u_char *cip, *next; /* Pointer to current and next CIs */ - int cilen, citype, cichar; /* Parsed len, type, char value */ + int cilen, citype; /* Parsed len, type */ + u_char cichar; /* Parsed char value */ u_short cishort; /* Parsed short value */ u32_t cilong; /* Parse long value */ int rc = CONFACK; /* Final packet return code */ @@ -1211,7 +1241,7 @@ lcp_reqci(fsm *f, int l = *lenp; /* Length left */ #if TRACELCP > 0 char traceBuf[80]; - int traceNdx = 0; + size_t traceNdx = 0; #endif /* @@ -1231,7 +1261,7 @@ lcp_reqci(fsm *f, if (l < 2 || /* Not enough data for CI header or */ p[1] < 2 || /* CI length too small or */ p[1] > l) { /* CI length too big? */ - LCPDEBUG((LOG_WARNING, "lcp_reqci: bad CI length!\n")); + LCPDEBUG(LOG_WARNING, ("lcp_reqci: bad CI length!\n")); orc = CONFREJ; /* Reject bad CI */ cilen = l; /* Reject till end of packet */ l = 0; /* Don't loop again */ @@ -1246,11 +1276,11 @@ lcp_reqci(fsm *f, switch (citype) { /* Check CI type */ case CI_MRU: if (!ao->neg_mru) { /* Allow option? */ - LCPDEBUG((LOG_INFO, "lcp_reqci: Reject MRU - not allowed\n")); + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - not allowed\n")); orc = CONFREJ; /* Reject CI */ break; } else if (cilen != CILEN_SHORT) { /* Check CI length */ - LCPDEBUG((LOG_INFO, "lcp_reqci: Reject MRU - bad length\n")); + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject MRU - bad length\n")); orc = CONFREJ; /* Reject CI */ break; } @@ -1262,7 +1292,7 @@ lcp_reqci(fsm *f, * we'll just ignore it. */ if (cishort < PPP_MINMRU) { - LCPDEBUG((LOG_INFO, "lcp_reqci: Nak - MRU too small\n")); + LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak - MRU too small\n")); orc = CONFNAK; /* Nak CI */ PUTCHAR(CI_MRU, nakp); PUTCHAR(CILEN_SHORT, nakp); @@ -1279,11 +1309,11 @@ lcp_reqci(fsm *f, case CI_ASYNCMAP: if (!ao->neg_asyncmap) { - LCPDEBUG((LOG_INFO, "lcp_reqci: Reject ASYNCMAP not allowed\n")); + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP not allowed\n")); orc = CONFREJ; break; } else if (cilen != CILEN_LONG) { - LCPDEBUG((LOG_INFO, "lcp_reqci: Reject ASYNCMAP bad length\n")); + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject ASYNCMAP bad length\n")); orc = CONFREJ; break; } @@ -1294,7 +1324,7 @@ lcp_reqci(fsm *f, * which are set in lcp_allowoptions[unit].asyncmap. */ if ((ao->asyncmap & ~cilong) != 0) { - LCPDEBUG((LOG_INFO, "lcp_reqci: Nak ASYNCMAP %lX missing %lX\n", + LCPDEBUG(LOG_INFO, ("lcp_reqci: Nak ASYNCMAP %lX missing %lX\n", cilong, ao->asyncmap)); orc = CONFNAK; PUTCHAR(CI_ASYNCMAP, nakp); @@ -1312,14 +1342,14 @@ lcp_reqci(fsm *f, case CI_AUTHTYPE: if (cilen < CILEN_SHORT) { - LCPDEBUG((LOG_INFO, "lcp_reqci: Reject AUTHTYPE missing arg\n")); + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE missing arg\n")); orc = CONFREJ; break; } else if (!(ao->neg_upap || ao->neg_chap)) { /* * Reject the option if we're not willing to authenticate. */ - LCPDEBUG((LOG_INFO, "lcp_reqci: Reject AUTHTYPE not allowed\n")); + LCPDEBUG(LOG_INFO, ("lcp_reqci: Reject AUTHTYPE not allowed\n")); orc = CONFREJ; break; } @@ -1338,16 +1368,16 @@ lcp_reqci(fsm *f, if (cishort == PPP_PAP) { if (ho->neg_chap) { /* we've already accepted CHAP */ - LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE PAP already accepted\n")); + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP already accepted\n")); orc = CONFREJ; break; } else if (cilen != CILEN_SHORT) { - LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE PAP bad len\n")); + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE PAP bad len\n")); orc = CONFREJ; break; } if (!ao->neg_upap) { /* we don't want to do PAP */ - LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE PAP not allowed\n")); + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE PAP not allowed\n")); orc = CONFNAK; /* NAK it and suggest CHAP */ PUTCHAR(CI_AUTHTYPE, nakp); PUTCHAR(CILEN_CHAP, nakp); @@ -1364,16 +1394,16 @@ lcp_reqci(fsm *f, } if (cishort == PPP_CHAP) { if (ho->neg_upap) { /* we've already accepted PAP */ - LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE CHAP accepted PAP\n")); + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP accepted PAP\n")); orc = CONFREJ; break; } else if (cilen != CILEN_CHAP) { - LCPDEBUG((LOG_WARNING, "lcp_reqci: Reject AUTHTYPE CHAP bad len\n")); + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Reject AUTHTYPE CHAP bad len\n")); orc = CONFREJ; break; } if (!ao->neg_chap) { /* we don't want to do CHAP */ - LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE CHAP not allowed\n")); + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP not allowed\n")); orc = CONFNAK; /* NAK it and suggest PAP */ PUTCHAR(CI_AUTHTYPE, nakp); PUTCHAR(CILEN_SHORT, nakp); @@ -1382,11 +1412,11 @@ lcp_reqci(fsm *f, } GETCHAR(cichar, p); /* get digest type*/ if (cichar != CHAP_DIGEST_MD5 -#ifdef CHAPMS +#if MSCHAP_SUPPORT && cichar != CHAP_MICROSOFT #endif ) { - LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE CHAP digest=%d\n", cichar)); + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE CHAP digest=%d\n", (int)cichar)); orc = CONFNAK; PUTCHAR(CI_AUTHTYPE, nakp); PUTCHAR(CILEN_CHAP, nakp); @@ -1395,7 +1425,7 @@ lcp_reqci(fsm *f, break; } #if TRACELCP > 0 - snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, cichar); + snprintf(&traceBuf[traceNdx], sizeof(traceBuf), " CHAP %X,%d", cishort, (int)cichar); traceNdx = strlen(traceBuf); #endif ho->chap_mdtype = cichar; /* save md type */ @@ -1411,12 +1441,12 @@ lcp_reqci(fsm *f, orc = CONFNAK; PUTCHAR(CI_AUTHTYPE, nakp); if (ao->neg_chap) { - LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE %d req CHAP\n", cishort)); + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req CHAP\n", cishort)); PUTCHAR(CILEN_CHAP, nakp); PUTSHORT(PPP_CHAP, nakp); PUTCHAR(ao->chap_mdtype, nakp); } else { - LCPDEBUG((LOG_WARNING, "lcp_reqci: Nak AUTHTYPE %d req PAP\n", cishort)); + LCPDEBUG(LOG_WARNING, ("lcp_reqci: Nak AUTHTYPE %d req PAP\n", cishort)); PUTCHAR(CILEN_SHORT, nakp); PUTSHORT(PPP_PAP, nakp); } @@ -1541,7 +1571,7 @@ lcp_reqci(fsm *f, endswitch: #if TRACELCP if (traceNdx >= 80 - 32) { - LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd%s\n", traceBuf)); + LCPDEBUG(LOG_INFO, ("lcp_reqci: rcvd%s\n", traceBuf)); traceNdx = 0; } #endif @@ -1595,10 +1625,10 @@ lcp_reqci(fsm *f, #if TRACELCP > 0 if (traceNdx > 0) { - LCPDEBUG((LOG_INFO, "lcp_reqci: %s\n", traceBuf)); + LCPDEBUG(LOG_INFO, ("lcp_reqci: %s\n", traceBuf)); } #endif - LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.\n", CODENAME(rc))); + LCPDEBUG(LOG_INFO, ("lcp_reqci: returning CONF%s.\n", CODENAME(rc))); return (rc); /* Return final code */ } @@ -1645,7 +1675,7 @@ lcp_up(fsm *f) lcp_echo_lowerup(f->unit); /* Enable echo messages */ - link_established(f->unit); + link_established(f->unit); /* The link is up; authenticate now */ } @@ -1677,7 +1707,7 @@ lcp_down(fsm *f) static void lcp_starting(fsm *f) { - link_required(f->unit); + link_required(f->unit); /* lwip: currently does nothing */ } @@ -1687,11 +1717,11 @@ lcp_starting(fsm *f) static void lcp_finished(fsm *f) { - link_terminated(f->unit); + link_terminated(f->unit); /* we are finished with the link */ } -#if 0 +#if PPP_ADDITIONAL_CALLBACKS /* * print_string - print a readable representation of a string using * printer. @@ -1898,7 +1928,7 @@ lcp_printpkt( u_char *p, int plen, void (*printer) (void *, char *, ...), void * return (int)(p - pstart); } -#endif +#endif /* PPP_ADDITIONAL_CALLBACKS */ /* * Time to shut down the link because there is nothing out there. @@ -1907,8 +1937,8 @@ static void LcpLinkFailure (fsm *f) { if (f->state == LS_OPENED) { - LCPDEBUG((LOG_INFO, "No response to %d echo-requests\n", lcp_echos_pending)); - LCPDEBUG((LOG_NOTICE, "Serial link appears to be disconnected.\n")); + LCPDEBUG(LOG_INFO, ("No response to %d echo-requests\n", lcp_echos_pending)); + LCPDEBUG(LOG_NOTICE, ("Serial link appears to be disconnected.\n")); lcp_close(f->unit, "Peer not responding"); } } @@ -1954,15 +1984,15 @@ lcp_received_echo_reply (fsm *f, int id, u_char *inp, int len) /* Check the magic number - don't count replies from ourselves. */ if (len < 4) { - LCPDEBUG((LOG_WARNING, "lcp: received short Echo-Reply, length %d\n", len)); + LCPDEBUG(LOG_WARNING, ("lcp: received short Echo-Reply, length %d\n", len)); return; } GETLONG(magic, inp); if (lcp_gotoptions[f->unit].neg_magicnumber && magic == lcp_gotoptions[f->unit].magicnumber) { - LCPDEBUG((LOG_WARNING, "appear to have received our own echo-reply!\n")); + LCPDEBUG(LOG_WARNING, ("appear to have received our own echo-reply!\n")); return; } - + /* Reset the number of outstanding echo frames */ lcp_echos_pending = 0; } @@ -1980,7 +2010,7 @@ LcpSendEchoRequest (fsm *f) * Detect the failure of the peer at this point. */ if (lcp_echo_fails != 0) { - if (lcp_echos_pending++ >= lcp_echo_fails) { + if (lcp_echos_pending >= lcp_echo_fails) { LcpLinkFailure(f); lcp_echos_pending = 0; } @@ -1994,6 +2024,7 @@ LcpSendEchoRequest (fsm *f) pktp = pkt; PUTLONG(lcp_magic, pktp); fsm_sdata(f, ECHOREQ, (u_char)(lcp_echo_number++ & 0xFF), pkt, (int)(pktp - pkt)); + ++lcp_echos_pending; } } diff --git a/lib/drivers/lwip/src/netif/ppp/lcp.h b/lib/drivers/lwip/src/netif/ppp/lcp.h index 1a5e5a4c081..b9201eeb50b 100644 --- a/lib/drivers/lwip/src/netif/ppp/lcp.h +++ b/lib/drivers/lwip/src/netif/ppp/lcp.h @@ -48,15 +48,11 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: lcp.h,v 1.3 2007/12/19 20:47:23 fbernon Exp $ + * $Id: lcp.h,v 1.4 2010/01/18 20:49:43 goldsimon Exp $ */ #ifndef LCP_H #define LCP_H - -/************************* -*** PUBLIC DEFINITIONS *** -*************************/ /* * Options. */ @@ -73,7 +69,7 @@ #define CI_EPDISC 19 /* endpoint discriminator */ /* - * LCP-specific packet types. + * LCP-specific packet types (code numbers). */ #define PROTREJ 8 /* Protocol Reject */ #define ECHOREQ 9 /* Echo Request */ @@ -81,11 +77,6 @@ #define DISCREQ 11 /* Discard Request */ #define CBCP_OPT 6 /* Use callback control protocol */ - -/************************ -*** PUBLIC DATA TYPES *** -************************/ - /* * The state of options is described by an lcp_options structure. */ @@ -135,9 +126,6 @@ typedef enum { } LinkPhase; -/***************************** -*** PUBLIC DATA STRUCTURES *** -*****************************/ extern LinkPhase lcp_phase[NUM_PPP]; /* Phase of link session (RFC 1661) */ extern lcp_options lcp_wantoptions[]; @@ -147,10 +135,6 @@ extern lcp_options lcp_hisoptions[]; extern ext_accm xmit_accm[]; -/*********************** -*** PUBLIC FUNCTIONS *** -***********************/ - void lcp_init (int); void lcp_open (int); void lcp_close (int, char *); diff --git a/lib/drivers/lwip/src/netif/ppp/magic.c b/lib/drivers/lwip/src/netif/ppp/magic.c index d3922bb5693..3901330895a 100644 --- a/lib/drivers/lwip/src/netif/ppp/magic.c +++ b/lib/drivers/lwip/src/netif/ppp/magic.c @@ -57,9 +57,7 @@ #include "randm.h" #include "magic.h" -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ + /* * magicInit - Initialize the magic number generator. * diff --git a/lib/drivers/lwip/src/netif/ppp/magic.h b/lib/drivers/lwip/src/netif/ppp/magic.h index bc517499333..eba70d20b00 100644 --- a/lib/drivers/lwip/src/netif/ppp/magic.h +++ b/lib/drivers/lwip/src/netif/ppp/magic.h @@ -48,16 +48,12 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: magic.h,v 1.2 2007/12/02 22:35:55 fbernon Exp $ + * $Id: magic.h,v 1.3 2010/01/18 20:49:43 goldsimon Exp $ */ #ifndef MAGIC_H #define MAGIC_H -/***************************************************************************** -************************** PUBLIC FUNCTIONS ********************************** -*****************************************************************************/ - /* Initialize the magic number generator */ void magicInit(void); diff --git a/lib/drivers/lwip/src/netif/ppp/md5.c b/lib/drivers/lwip/src/netif/ppp/md5.c index 7a60d783258..3cb69e2b065 100644 --- a/lib/drivers/lwip/src/netif/ppp/md5.c +++ b/lib/drivers/lwip/src/netif/ppp/md5.c @@ -138,8 +138,8 @@ MD5Update(MD5_CTX *mdContext, unsigned char *inBuf, unsigned int inLen) unsigned int i, ii; #if 0 - ppp_trace(LOG_INFO, "MD5Update: %u:%.*H\n", inLen, MIN(inLen, 20) * 2, inBuf); - ppp_trace(LOG_INFO, "MD5Update: %u:%s\n", inLen, inBuf); + PPPDEBUG(LOG_INFO, ("MD5Update: %u:%.*H\n", inLen, LWIP_MIN(inLen, 20) * 2, inBuf)); + PPPDEBUG(LOG_INFO, ("MD5Update: %u:%s\n", inLen, inBuf)); #endif /* compute number of bytes mod 64 */ diff --git a/lib/drivers/lwip/src/netif/ppp/pap.c b/lib/drivers/lwip/src/netif/ppp/pap.c index e8c45dff9c9..ac44e6464ce 100644 --- a/lib/drivers/lwip/src/netif/ppp/pap.c +++ b/lib/drivers/lwip/src/netif/ppp/pap.c @@ -63,9 +63,27 @@ #include -/***********************************/ -/*** LOCAL FUNCTION DECLARATIONS ***/ -/***********************************/ +#if 0 /* UNUSED */ +static bool hide_password = 1; + +/* + * Command-line options. + */ +static option_t pap_option_list[] = { + { "hide-password", o_bool, &hide_password, + "Don't output passwords to log", 1 }, + { "show-password", o_bool, &hide_password, + "Show password string in debug log messages", 0 }, + { "pap-restart", o_int, &upap[0].us_timeouttime, + "Set retransmit timeout for PAP" }, + { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, + "Set max number of transmissions for auth-reqs" }, + { "pap-timeout", o_int, &upap[0].us_reqtimeout, + "Set time limit for peer PAP authentication" }, + { NULL } +}; +#endif + /* * Protocol entry points. */ @@ -74,19 +92,10 @@ static void upap_lowerup (int); static void upap_lowerdown (int); static void upap_input (int, u_char *, int); static void upap_protrej (int); +#if PPP_ADDITIONAL_CALLBACKS +static int upap_printpkt (u_char *, int, void (*)(void *, char *, ...), void *); +#endif /* PPP_ADDITIONAL_CALLBACKS */ -static void upap_timeout (void *); -static void upap_reqtimeout(void *); -static void upap_rauthreq (upap_state *, u_char *, int, int); -static void upap_rauthack (upap_state *, u_char *, int, int); -static void upap_rauthnak (upap_state *, u_char *, int, int); -static void upap_sauthreq (upap_state *); -static void upap_sresp (upap_state *, u_char, u_char, char *, int); - - -/******************************/ -/*** PUBLIC DATA STRUCTURES ***/ -/******************************/ struct protent pap_protent = { PPP_PAP, upap_init, @@ -96,41 +105,51 @@ struct protent pap_protent = { upap_lowerdown, NULL, NULL, -#if 0 +#if PPP_ADDITIONAL_CALLBACKS upap_printpkt, NULL, -#endif +#endif /* PPP_ADDITIONAL_CALLBACKS */ 1, "PAP", -#if 0 +#if PPP_ADDITIONAL_CALLBACKS NULL, NULL, NULL -#endif +#endif /* PPP_ADDITIONAL_CALLBACKS */ }; upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */ +static void upap_timeout (void *); +static void upap_reqtimeout(void *); +static void upap_rauthreq (upap_state *, u_char *, u_char, int); +static void upap_rauthack (upap_state *, u_char *, int, int); +static void upap_rauthnak (upap_state *, u_char *, int, int); +static void upap_sauthreq (upap_state *); +static void upap_sresp (upap_state *, u_char, u_char, char *, int); -/***********************************/ -/*** PUBLIC FUNCTION DEFINITIONS ***/ -/***********************************/ /* - * Set the default login name and password for the pap sessions + * upap_init - Initialize a UPAP unit. */ -void -upap_setloginpasswd(int unit, const char *luser, const char *lpassword) +static void +upap_init(int unit) { upap_state *u = &upap[unit]; - - /* Save the username and password we're given */ - u->us_user = luser; - u->us_userlen = strlen(luser); - u->us_passwd = lpassword; - u->us_passwdlen = strlen(lpassword); -} + UPAPDEBUG(LOG_INFO, ("upap_init: %d\n", unit)); + u->us_unit = unit; + u->us_user = NULL; + u->us_userlen = 0; + u->us_passwd = NULL; + u->us_passwdlen = 0; + u->us_clientstate = UPAPCS_INITIAL; + u->us_serverstate = UPAPSS_INITIAL; + u->us_id = 0; + u->us_timeouttime = UPAP_DEFTIMEOUT; + u->us_maxtransmits = 10; + u->us_reqtimeout = UPAP_DEFREQTIME; +} /* * upap_authwithpeer - Authenticate us with our peer (start client). @@ -142,10 +161,14 @@ upap_authwithpeer(int unit, char *user, char *password) { upap_state *u = &upap[unit]; - UPAPDEBUG((LOG_INFO, "upap_authwithpeer: %d user=%s password=%s s=%d\n", + UPAPDEBUG(LOG_INFO, ("upap_authwithpeer: %d user=%s password=%s s=%d\n", unit, user, password, u->us_clientstate)); - upap_setloginpasswd(unit, user, password); + /* Save the username and password we're given */ + u->us_user = user; + u->us_userlen = (int)strlen(user); + u->us_passwd = password; + u->us_passwdlen = (int)strlen(password); u->us_transmits = 0; @@ -183,33 +206,6 @@ upap_authpeer(int unit) } } - - -/**********************************/ -/*** LOCAL FUNCTION DEFINITIONS ***/ -/**********************************/ -/* - * upap_init - Initialize a UPAP unit. - */ -static void -upap_init(int unit) -{ - upap_state *u = &upap[unit]; - - UPAPDEBUG((LOG_INFO, "upap_init: %d\n", unit)); - u->us_unit = unit; - u->us_user = NULL; - u->us_userlen = 0; - u->us_passwd = NULL; - u->us_passwdlen = 0; - u->us_clientstate = UPAPCS_INITIAL; - u->us_serverstate = UPAPSS_INITIAL; - u->us_id = 0; - u->us_timeouttime = UPAP_DEFTIMEOUT; - u->us_maxtransmits = 10; - u->us_reqtimeout = UPAP_DEFREQTIME; -} - /* * upap_timeout - Retransmission timer for sending auth-reqs expired. */ @@ -218,22 +214,23 @@ upap_timeout(void *arg) { upap_state *u = (upap_state *) arg; - UPAPDEBUG((LOG_INFO, "upap_timeout: %d timeout %d expired s=%d\n", + UPAPDEBUG(LOG_INFO, ("upap_timeout: %d timeout %d expired s=%d\n", u->us_unit, u->us_timeouttime, u->us_clientstate)); if (u->us_clientstate != UPAPCS_AUTHREQ) { + UPAPDEBUG(LOG_INFO, ("upap_timeout: not in AUTHREQ state!\n")); return; } if (u->us_transmits >= u->us_maxtransmits) { /* give up in disgust */ - UPAPDEBUG((LOG_ERR, "No response to PAP authenticate-requests\n")); + UPAPDEBUG(LOG_ERR, ("No response to PAP authenticate-requests\n")); u->us_clientstate = UPAPCS_BADAUTH; auth_withpeer_fail(u->us_unit, PPP_PAP); return; } - upap_sauthreq(u); /* Send Authenticate-Request */ + upap_sauthreq(u); /* Send Authenticate-Request and set upap timeout*/ } @@ -264,12 +261,13 @@ upap_lowerup(int unit) { upap_state *u = &upap[unit]; - UPAPDEBUG((LOG_INFO, "upap_lowerup: %d s=%d\n", unit, u->us_clientstate)); + UPAPDEBUG(LOG_INFO, ("upap_lowerup: init %d clientstate s=%d\n", unit, u->us_clientstate)); if (u->us_clientstate == UPAPCS_INITIAL) { u->us_clientstate = UPAPCS_CLOSED; } else if (u->us_clientstate == UPAPCS_PENDING) { upap_sauthreq(u); /* send an auth-request */ + /* now client state is UPAPCS__AUTHREQ */ } if (u->us_serverstate == UPAPSS_INITIAL) { @@ -293,7 +291,7 @@ upap_lowerdown(int unit) { upap_state *u = &upap[unit]; - UPAPDEBUG((LOG_INFO, "upap_lowerdown: %d s=%d\n", unit, u->us_clientstate)); + UPAPDEBUG(LOG_INFO, ("upap_lowerdown: %d s=%d\n", unit, u->us_clientstate)); if (u->us_clientstate == UPAPCS_AUTHREQ) { /* Timeout pending? */ UNTIMEOUT(upap_timeout, u); /* Cancel timeout */ @@ -318,11 +316,11 @@ upap_protrej(int unit) upap_state *u = &upap[unit]; if (u->us_clientstate == UPAPCS_AUTHREQ) { - UPAPDEBUG((LOG_ERR, "PAP authentication failed due to protocol-reject\n")); + UPAPDEBUG(LOG_ERR, ("PAP authentication failed due to protocol-reject\n")); auth_withpeer_fail(unit, PPP_PAP); } if (u->us_serverstate == UPAPSS_LISTEN) { - UPAPDEBUG((LOG_ERR, "PAP authentication of peer failed (protocol-reject)\n")); + UPAPDEBUG(LOG_ERR, ("PAP authentication of peer failed (protocol-reject)\n")); auth_peer_fail(unit, PPP_PAP); } upap_lowerdown(unit); @@ -345,19 +343,19 @@ upap_input(int unit, u_char *inpacket, int l) * If packet too short, drop it. */ inp = inpacket; - if (l < UPAP_HEADERLEN) { - UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header.\n")); + if (l < (int)UPAP_HEADERLEN) { + UPAPDEBUG(LOG_INFO, ("pap_input: rcvd short header.\n")); return; } GETCHAR(code, inp); GETCHAR(id, inp); GETSHORT(len, inp); - if (len < UPAP_HEADERLEN) { - UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length.\n")); + if (len < (int)UPAP_HEADERLEN) { + UPAPDEBUG(LOG_INFO, ("pap_input: rcvd illegal length.\n")); return; } if (len > l) { - UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet.\n")); + UPAPDEBUG(LOG_INFO, ("pap_input: rcvd short packet.\n")); return; } len -= UPAP_HEADERLEN; @@ -379,6 +377,7 @@ upap_input(int unit, u_char *inpacket, int l) break; default: /* XXX Need code reject */ + UPAPDEBUG(LOG_INFO, ("pap_input: UNHANDLED default: code: %d, id: %d, len: %d.\n", code, id, len)); break; } } @@ -388,15 +387,15 @@ upap_input(int unit, u_char *inpacket, int l) * upap_rauth - Receive Authenticate. */ static void -upap_rauthreq(upap_state *u, u_char *inp, int id, int len) +upap_rauthreq(upap_state *u, u_char *inp, u_char id, int len) { u_char ruserlen, rpasswdlen; char *ruser, *rpasswd; - int retcode; + u_char retcode; char *msg; int msglen; - UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.\n", id)); + UPAPDEBUG(LOG_INFO, ("pap_rauth: Rcvd id %d.\n", id)); if (u->us_serverstate < UPAPSS_LISTEN) { return; @@ -418,21 +417,21 @@ upap_rauthreq(upap_state *u, u_char *inp, int id, int len) /* * Parse user/passwd. */ - if (len < sizeof (u_char)) { - UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n")); + if (len < (int)sizeof (u_char)) { + UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n")); return; } GETCHAR(ruserlen, inp); len -= sizeof (u_char) + ruserlen + sizeof (u_char); if (len < 0) { - UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n")); + UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n")); return; } ruser = (char *) inp; INCPTR(ruserlen, inp); GETCHAR(rpasswdlen, inp); if (len < rpasswdlen) { - UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet.\n")); + UPAPDEBUG(LOG_INFO, ("pap_rauth: rcvd short packet.\n")); return; } rpasswd = (char *) inp; @@ -441,6 +440,7 @@ upap_rauthreq(upap_state *u, u_char *inp, int id, int len) * Check the username and password given. */ retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd, rpasswdlen, &msg, &msglen); + /* lwip: currently retcode is always UPAP_AUTHACK */ BZERO(rpasswd, rpasswdlen); upap_sresp(u, retcode, id, msg, msglen); @@ -470,28 +470,30 @@ upap_rauthack(upap_state *u, u_char *inp, int id, int len) LWIP_UNUSED_ARG(id); - UPAPDEBUG((LOG_INFO, "pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate)); + UPAPDEBUG(LOG_INFO, ("pap_rauthack: Rcvd id %d s=%d\n", id, u->us_clientstate)); if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */ + UPAPDEBUG(LOG_INFO, ("pap_rauthack: us_clientstate != UPAPCS_AUTHREQ\n")); return; } /* * Parse message. */ - if (len < sizeof (u_char)) { - UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n")); - return; + if (len < (int)sizeof (u_char)) { + UPAPDEBUG(LOG_INFO, ("pap_rauthack: ignoring missing msg-length.\n")); + } else { + GETCHAR(msglen, inp); + if (msglen > 0) { + len -= sizeof (u_char); + if (len < msglen) { + UPAPDEBUG(LOG_INFO, ("pap_rauthack: rcvd short packet.\n")); + return; + } + msg = (char *) inp; + PRINTMSG(msg, msglen); + } } - GETCHAR(msglen, inp); - len -= sizeof (u_char); - if (len < msglen) { - UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet.\n")); - return; - } - msg = (char *) inp; - PRINTMSG(msg, msglen); - UNTIMEOUT(upap_timeout, u); /* Cancel timeout */ u->us_clientstate = UPAPCS_OPEN; @@ -500,7 +502,7 @@ upap_rauthack(upap_state *u, u_char *inp, int id, int len) /* - * upap_rauthnak - Receive Authenticate-Nakk. + * upap_rauthnak - Receive Authenticate-Nak. */ static void upap_rauthnak(upap_state *u, u_char *inp, int id, int len) @@ -510,7 +512,7 @@ upap_rauthnak(upap_state *u, u_char *inp, int id, int len) LWIP_UNUSED_ARG(id); - UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate)); + UPAPDEBUG(LOG_INFO, ("pap_rauthnak: Rcvd id %d s=%d\n", id, u->us_clientstate)); if (u->us_clientstate != UPAPCS_AUTHREQ) { /* XXX */ return; @@ -520,13 +522,13 @@ upap_rauthnak(upap_state *u, u_char *inp, int id, int len) * Parse message. */ if (len < sizeof (u_char)) { - UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n")); + UPAPDEBUG(LOG_INFO, ("pap_rauthnak: ignoring missing msg-length.\n")); } else { GETCHAR(msglen, inp); if(msglen > 0) { len -= sizeof (u_char); if (len < msglen) { - UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet.\n")); + UPAPDEBUG(LOG_INFO, ("pap_rauthnak: rcvd short packet.\n")); return; } msg = (char *) inp; @@ -536,7 +538,7 @@ upap_rauthnak(upap_state *u, u_char *inp, int id, int len) u->us_clientstate = UPAPCS_BADAUTH; - UPAPDEBUG((LOG_ERR, "PAP authentication failed\n")); + UPAPDEBUG(LOG_ERR, ("PAP authentication failed\n")); auth_withpeer_fail(u->us_unit, PPP_PAP); } @@ -567,7 +569,7 @@ upap_sauthreq(upap_state *u) pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN); - UPAPDEBUG((LOG_INFO, "pap_sauth: Sent id %d\n", u->us_id)); + UPAPDEBUG(LOG_INFO, ("pap_sauth: Sent id %d\n", u->us_id)); TIMEOUT(upap_timeout, u, u->us_timeouttime); ++u->us_transmits; @@ -595,10 +597,14 @@ upap_sresp(upap_state *u, u_char code, u_char id, char *msg, int msglen) BCOPY(msg, outp, msglen); pppWrite(u->us_unit, outpacket_buf[u->us_unit], outlen + PPP_HDRLEN); - UPAPDEBUG((LOG_INFO, "pap_sresp: Sent code %d, id %d s=%d\n", code, id, u->us_clientstate)); + UPAPDEBUG(LOG_INFO, ("pap_sresp: Sent code %d, id %d s=%d\n", code, id, u->us_clientstate)); } -#if 0 +#if PPP_ADDITIONAL_CALLBACKS +static char *upap_codenames[] = { + "AuthReq", "AuthAck", "AuthNak" +}; + /* * upap_printpkt - print the contents of a PAP packet. */ @@ -615,7 +621,7 @@ static int upap_printpkt( LWIP_UNUSED_ARG(arg); return 0; } -#endif /* 0 */ +#endif /* PPP_ADDITIONAL_CALLBACKS */ #endif /* PAP_SUPPORT */ diff --git a/lib/drivers/lwip/src/netif/ppp/pap.h b/lib/drivers/lwip/src/netif/ppp/pap.h index 0a09fc841b6..c99a2040196 100644 --- a/lib/drivers/lwip/src/netif/ppp/pap.h +++ b/lib/drivers/lwip/src/netif/ppp/pap.h @@ -54,9 +54,6 @@ #if PAP_SUPPORT /* don't build if not configured for use in lwipopts.h */ -/************************* -*** PUBLIC DEFINITIONS *** -*************************/ /* * Packet header = Code, id, length. */ @@ -70,6 +67,24 @@ #define UPAP_AUTHACK 2 /* Authenticate-Ack */ #define UPAP_AUTHNAK 3 /* Authenticate-Nak */ +/* + * Each interface is described by upap structure. + */ +typedef struct upap_state { + int us_unit; /* Interface unit number */ + const char *us_user; /* User */ + int us_userlen; /* User length */ + const char *us_passwd; /* Password */ + int us_passwdlen; /* Password length */ + int us_clientstate; /* Client state */ + int us_serverstate; /* Server state */ + u_char us_id; /* Current id */ + int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */ + int us_transmits; /* Number of auth-reqs sent */ + int us_maxtransmits; /* Maximum number of auth-reqs to send */ + int us_reqtimeout; /* Time to wait for auth-req from peer */ +} upap_state; + /* * Client states. */ @@ -91,36 +106,8 @@ #define UPAPSS_BADAUTH 5 /* We've sent a Nak */ -/************************ -*** PUBLIC DATA TYPES *** -************************/ - -/* - * Each interface is described by upap structure. - */ -typedef struct upap_state { - int us_unit; /* Interface unit number */ - const char *us_user; /* User */ - int us_userlen; /* User length */ - const char *us_passwd; /* Password */ - int us_passwdlen; /* Password length */ - int us_clientstate; /* Client state */ - int us_serverstate; /* Server state */ - u_char us_id; /* Current id */ - int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */ - int us_transmits; /* Number of auth-reqs sent */ - int us_maxtransmits; /* Maximum number of auth-reqs to send */ - int us_reqtimeout; /* Time to wait for auth-req from peer */ -} upap_state; - - -/*********************** -*** PUBLIC FUNCTIONS *** -***********************/ - extern upap_state upap[]; -void upap_setloginpasswd(int unit, const char *luser, const char *lpassword); void upap_authwithpeer (int, char *, char *); void upap_authpeer (int); diff --git a/lib/drivers/lwip/src/netif/ppp/ppp.c b/lib/drivers/lwip/src/netif/ppp/ppp.c index 13fa5ed0902..e9b433b0534 100644 --- a/lib/drivers/lwip/src/netif/ppp/ppp.c +++ b/lib/drivers/lwip/src/netif/ppp/ppp.c @@ -107,12 +107,35 @@ #include "netif/ppp_oe.h" #endif /* PPPOE_SUPPORT */ +#include "lwip/tcpip.h" +#include "lwip/api.h" +#include "lwip/snmp.h" + #include /*************************/ /*** LOCAL DEFINITIONS ***/ /*************************/ +/** PPP_INPROC_MULTITHREADED==1 call pppInput using tcpip_callback(). + * Set this to 0 if pppInProc is called inside tcpip_thread or with NO_SYS==1. + * Default is 1 for NO_SYS==0 (multithreaded) and 0 for NO_SYS==1 (single-threaded). + */ +#ifndef PPP_INPROC_MULTITHREADED +#define PPP_INPROC_MULTITHREADED (NO_SYS==0) +#endif + +/** PPP_INPROC_OWNTHREAD==1: start a dedicated RX thread per PPP session. + * Default is 0: call pppos_input() for received raw characters, charcater + * reception is up to the port */ +#ifndef PPP_INPROC_OWNTHREAD +#define PPP_INPROC_OWNTHREAD PPP_INPROC_MULTITHREADED +#endif + +#if PPP_INPROC_OWNTHREAD && !PPP_INPROC_MULTITHREADED + #error "PPP_INPROC_OWNTHREAD needs PPP_INPROC_MULTITHREADED==1" +#endif + /* * The basic PPP frame. */ @@ -137,10 +160,37 @@ typedef enum { /************************/ /*** LOCAL DATA TYPES ***/ /************************/ + +/** RX buffer size: this may be configured smaller! */ +#ifndef PPPOS_RX_BUFSIZE +#define PPPOS_RX_BUFSIZE (PPP_MRU + PPP_HDRLEN) +#endif + +typedef struct PPPControlRx_s { + /** unit number / ppp descriptor */ + int pd; + /** the rx file descriptor */ + sio_fd_t fd; + /** receive buffer - encoded data is stored here */ + u_char rxbuf[PPPOS_RX_BUFSIZE]; + + /* The input packet. */ + struct pbuf *inHead, *inTail; + +#if PPPOS_SUPPORT + u16_t inProtocol; /* The input protocol code. */ + u16_t inFCS; /* Input Frame Check Sequence value. */ +#endif /* PPPOS_SUPPORT */ + PPPDevStates inState; /* The input process state. */ + char inEscaped; /* Escape next character. */ + ext_accm inACCM; /* Async-Ctl-Char-Map for input. */ +} PPPControlRx; + /* * PPP interface control block. */ typedef struct PPPControl_s { + PPPControlRx rx; char openFlag; /* True when in use. */ #if PPPOE_SUPPORT struct netif *ethif; @@ -150,19 +200,11 @@ typedef struct PPPControl_s { int errCode; /* Code indicating why interface is down. */ #if PPPOS_SUPPORT sio_fd_t fd; /* File device ID of port. */ - int kill_link; /* Shut the link down. */ - int sig_hup; /* Carrier lost. */ - struct pbuf *inHead, *inTail; /* The input packet. */ - PPPDevStates inState; /* The input process state. */ - char inEscaped; /* Escape next character. */ - u16_t inProtocol; /* The input protocol code. */ - u16_t inFCS; /* Input Frame Check Sequence value. */ #endif /* PPPOS_SUPPORT */ - int mtu; /* Peer's mru */ + u16_t mtu; /* Peer's mru */ int pcomp; /* Does peer accept protocol compression? */ int accomp; /* Does peer accept addr/ctl compression? */ u_long lastXMit; /* Time of last transmission. */ - ext_accm inACCM; /* Async-Ctl-Char-Map for input. */ ext_accm outACCM; /* Async-Ctl-Char-Map for output. */ #if PPPOS_SUPPORT && VJ_SUPPORT int vjEnabled; /* Flag indicating VJ compression enabled. */ @@ -194,9 +236,11 @@ struct npioctl { /*** LOCAL FUNCTION DECLARATIONS ***/ /***********************************/ #if PPPOS_SUPPORT -static void pppMain(void *pd); -static void pppDrop(PPPControl *pc); -static void pppInProc(int pd, u_char *s, int l); +#if PPP_INPROC_OWNTHREAD +static void pppInputThread(void *arg); +#endif /* PPP_INPROC_OWNTHREAD */ +static void pppDrop(PPPControlRx *pcrx); +static void pppInProc(PPPControlRx *pcrx, u_char *s, int l); #endif /* PPPOS_SUPPORT */ @@ -245,6 +289,7 @@ u_char outpacket_buf[NUM_PPP][PPP_MRU+PPP_HDRLEN]; #if PPPOS_SUPPORT /* * FCS lookup table as calculated by genfcstab. + * @todo: smaller, slower implementation for lower memory footprint? */ static const u_short fcstab[256] = { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, @@ -294,80 +339,84 @@ static u_char pppACCMMask[] = { 0x80 }; - -void -pppMainWakeup(int pd) +/** Wake up the task blocked in reading from serial line (if any) */ +static void +pppRecvWakeup(int pd) { - PPPDEBUG((LOG_DEBUG, "pppMainWakeup: unit %d\n", pd)); - sio_read_abort(pppControl[pd].fd); + PPPDEBUG(LOG_DEBUG, ("pppRecvWakeup: unit %d\n", pd)); + if (pppControl[pd].openFlag != 0) { + sio_read_abort(pppControl[pd].fd); + } } #endif /* PPPOS_SUPPORT */ void pppLinkTerminated(int pd) { - PPPDEBUG((LOG_DEBUG, "pppLinkTerminated: unit %d\n", pd)); + PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d\n", pd)); #if PPPOE_SUPPORT - if(pppControl[pd].ethif) { + if (pppControl[pd].ethif) { pppoe_disconnect(pppControl[pd].pppoe_sc); } else #endif /* PPPOE_SUPPORT */ { #if PPPOS_SUPPORT - pppMainWakeup(pd); + PPPControl* pc; + pppRecvWakeup(pd); + pc = &pppControl[pd]; + + PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); + if (pc->linkStatusCB) { + pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); + } + + pc->openFlag = 0;/**/ #endif /* PPPOS_SUPPORT */ } + PPPDEBUG(LOG_DEBUG, ("pppLinkTerminated: finished.\n")); } void pppLinkDown(int pd) { - PPPDEBUG((LOG_DEBUG, "pppLinkDown: unit %d\n", pd)); + PPPDEBUG(LOG_DEBUG, ("pppLinkDown: unit %d\n", pd)); #if PPPOE_SUPPORT - if(pppControl[pd].ethif) { + if (pppControl[pd].ethif) { pppoe_disconnect(pppControl[pd].pppoe_sc); } else #endif /* PPPOE_SUPPORT */ { #if PPPOS_SUPPORT - pppMainWakeup(pd); + pppRecvWakeup(pd); #endif /* PPPOS_SUPPORT */ } } -/* these callbacks are necessary because lcp_* functions - must be called in the same context as pppInput(), - namely the tcpip_thread(), essentially because - they manipulate timeouts which are thread-private -*/ - +/** Initiate LCP open request */ static void -pppStartCB(void *arg) +pppStart(int pd) { - int pd = (int)arg; - - PPPDEBUG((LOG_DEBUG, "pppStartCB: unit %d\n", pd)); + PPPDEBUG(LOG_DEBUG, ("pppStart: unit %d\n", pd)); lcp_lowerup(pd); lcp_open(pd); /* Start protocol */ + PPPDEBUG(LOG_DEBUG, ("pppStart: finished\n")); } +/** LCP close request */ static void -pppStopCB(void *arg) +pppStop(int pd) { - int pd = (int)arg; - - PPPDEBUG((LOG_DEBUG, "pppStopCB: unit %d\n", pd)); + PPPDEBUG(LOG_DEBUG, ("pppStop: unit %d\n", pd)); lcp_close(pd, "User request"); } +/** Called when carrier/link is lost */ static void -pppHupCB(void *arg) +pppHup(int pd) { - int pd = (int)arg; - - PPPDEBUG((LOG_DEBUG, "pppHupCB: unit %d\n", pd)); + PPPDEBUG(LOG_DEBUG, ("pppHupCB: unit %d\n", pd)); lcp_lowerdown(pd); link_terminated(pd); } @@ -391,22 +440,14 @@ pppInit(void) magicInit(); - subnetMask = htonl(0xffffff00); + subnetMask = PP_HTONL(0xffffff00UL); for (i = 0; i < NUM_PPP; i++) { - pppControl[i].openFlag = 0; - - /* - * Initialize to the standard option set. - */ + /* Initialize each protocol to the standard option set. */ for (j = 0; (protp = ppp_protocols[j]) != NULL; ++j) { (*protp->init)(i); } } - -#if PPPOE_SUPPORT - pppoe_init(); -#endif /* PPPOE_SUPPORT */ } void @@ -475,50 +516,44 @@ pppSetAuth(enum pppAuthType authType, const char *user, const char *passwd) } #if PPPOS_SUPPORT -/* Open a new PPP connection using the given I/O device. +/** Open a new PPP connection using the given I/O device. * This initializes the PPP control block but does not * attempt to negotiate the LCP session. If this port * connects to a modem, the modem connection must be * established before calling this. * Return a new PPP connection descriptor on success or - * an error code (negative) on failure. */ + * an error code (negative) on failure. + * + * pppOpen() is directly defined to this function. + */ int pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void *arg), void *linkStatusCtx) { PPPControl *pc; int pd; - /* Find a free PPP session descriptor. Critical region? */ + if (linkStatusCB == NULL) { + /* PPP is single-threaded: without a callback, + * there is no way to know when the link is up. */ + return PPPERR_PARAM; + } + + /* Find a free PPP session descriptor. */ for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); if (pd >= NUM_PPP) { pd = PPPERR_OPEN; } else { - pppControl[pd].openFlag = !0; - } - - /* Launch a deamon thread. */ - if (pd >= 0) { - pppControl[pd].openFlag = 1; - - lcp_init(pd); pc = &pppControl[pd]; + /* @todo: is this correct or do I overwrite something? */ + memset(pc, 0, sizeof(PPPControl)); + pc->rx.pd = pd; + pc->rx.fd = fd; + + pc->openFlag = 1; pc->fd = fd; -#if PPPOE_SUPPORT - pc->ethif= NULL; -#endif /* PPPOE_SUPPORT */ - pc->kill_link = 0; - pc->sig_hup = 0; - pc->if_up = 0; - pc->errCode = 0; - pc->inState = PDIDLE; - pc->inHead = NULL; - pc->inTail = NULL; - pc->inEscaped = 0; - pc->lastXMit = 0; #if VJ_SUPPORT - pc->vjEnabled = 0; vj_compress_init(&pc->vjComp); #endif /* VJ_SUPPORT */ @@ -526,28 +561,20 @@ pppOverSerialOpen(sio_fd_t fd, void (*linkStatusCB)(void *ctx, int errCode, void * Default the in and out accm so that escape and flag characters * are always escaped. */ - memset(pc->inACCM, 0, sizeof(ext_accm)); - pc->inACCM[15] = 0x60; - memset(pc->outACCM, 0, sizeof(ext_accm)); + pc->rx.inACCM[15] = 0x60; /* no need to protect since RX is not running */ pc->outACCM[15] = 0x60; pc->linkStatusCB = linkStatusCB; pc->linkStatusCtx = linkStatusCtx; - sys_thread_new(PPP_THREAD_NAME, pppMain, (void*)pd, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO); - if(!linkStatusCB) { - while(pd >= 0 && !pc->if_up) { - sys_msleep(500); - if (lcp_phase[pd] == PHASE_DEAD) { - pppClose(pd); - if (pc->errCode) { - pd = pc->errCode; - } else { - pd = PPPERR_CONNECT; - } - } - } - } + /* + * Start the connection and handle incoming events (packet or timeout). + */ + PPPDEBUG(LOG_INFO, ("pppOverSerialOpen: unit %d: Connecting\n", pd)); + pppStart(pd); +#if PPP_INPROC_OWNTHREAD + sys_thread_new(PPP_THREAD_NAME, pppInputThread, (void*)&pc->rx, PPP_THREAD_STACKSIZE, PPP_THREAD_PRIO); +#endif } return pd; @@ -576,20 +603,24 @@ int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const cha LWIP_UNUSED_ARG(service_name); LWIP_UNUSED_ARG(concentrator_name); + if (linkStatusCB == NULL) { + /* PPP is single-threaded: without a callback, + * there is no way to know when the link is up. */ + return PPPERR_PARAM; + } + /* Find a free PPP session descriptor. Critical region? */ for (pd = 0; pd < NUM_PPP && pppControl[pd].openFlag != 0; pd++); if (pd >= NUM_PPP) { pd = PPPERR_OPEN; } else { - pppControl[pd].openFlag = !0; - } + pc = &pppControl[pd]; + memset(pc, 0, sizeof(PPPControl)); + pc->openFlag = 1; + pc->ethif = ethif; - /* PPP session descriptor found, start PPPoE */ - if (pd >= 0) { - - pppControl[pd].openFlag = 1; - - lcp_init(pd); + pc->linkStatusCB = linkStatusCB; + pc->linkStatusCtx = linkStatusCtx; lcp_wantoptions[pd].mru = PPPOE_MAXMTU; lcp_wantoptions[pd].neg_asyncmap = 0; @@ -601,49 +632,12 @@ int pppOverEthernetOpen(struct netif *ethif, const char *service_name, const cha lcp_allowoptions[pd].neg_pcompression = 0; lcp_allowoptions[pd].neg_accompression = 0; - pc = &pppControl[pd]; - pc->if_up = 0; - pc->errCode = 0; - pc->lastXMit = 0; -#if PPPOS_SUPPORT - pc->kill_link = 0; - pc->sig_hup = 0; - pc->inState = PDIDLE; - pc->inHead = NULL; - pc->inTail = NULL; - pc->inEscaped = 0; -#if VJ_SUPPORT - pc->vjEnabled = 0; -#endif /* VJ_SUPPORT */ -#endif /* PPPOS_SUPPORT */ - pc->ethif= ethif; - - memset(pc->inACCM, 0, sizeof(ext_accm)); - memset(pc->outACCM, 0, sizeof(ext_accm)); - - pc->linkStatusCB = linkStatusCB; - pc->linkStatusCtx = linkStatusCtx; - if(pppoe_create(ethif, pd, pppOverEthernetLinkStatusCB, &pc->pppoe_sc) != ERR_OK) { pc->openFlag = 0; return PPPERR_OPEN; } pppoe_connect(pc->pppoe_sc); - - if(!linkStatusCB) { - while(pd >= 0 && !pc->if_up) { - sys_msleep(500); - if (lcp_phase[pd] == PHASE_DEAD) { - pppClose(pd); - if (pc->errCode) { - pd = pc->errCode; - } else { - pd = PPPERR_CONNECT; - } - } - } - } } return pd; @@ -660,29 +654,27 @@ pppClose(int pd) PPPControl *pc = &pppControl[pd]; int st = 0; + PPPDEBUG(LOG_DEBUG, ("pppClose() called\n")); + /* Disconnect */ #if PPPOE_SUPPORT if(pc->ethif) { - PPPDEBUG((LOG_DEBUG, "pppClose: unit %d kill_link -> pppStopCB\n", pd)); + PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); pc->errCode = PPPERR_USER; /* This will leave us at PHASE_DEAD. */ - tcpip_callback(pppStopCB, (void*)pd); + pppStop(pd); } else #endif /* PPPOE_SUPPORT */ { #if PPPOS_SUPPORT - pc->kill_link = !0; - pppMainWakeup(pd); + PPPDEBUG(LOG_DEBUG, ("pppClose: unit %d kill_link -> pppStop\n", pd)); + pc->errCode = PPPERR_USER; + /* This will leave us at PHASE_DEAD. */ + pppStop(pd); + pppRecvWakeup(pd); #endif /* PPPOS_SUPPORT */ } - if(!pc->linkStatusCB) { - while(st >= 0 && lcp_phase[pd] != PHASE_DEAD) { - sys_msleep(500); - break; - } - } - return st; } @@ -690,20 +682,8 @@ pppClose(int pd) void pppSigHUP(int pd) { - PPPControl *pc = &pppControl[pd]; - -#if PPPOE_SUPPORT - if(pc->ethif) { - PPPDEBUG((LOG_DEBUG, "pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd)); - tcpip_callback(pppHupCB, (void*)pd); - } else -#endif /* PPPOE_SUPPORT */ - { -#if PPPOS_SUPPORT - pc->sig_hup = 1; - pppMainWakeup(pd); -#endif /* PPPOS_SUPPORT */ - } + PPPDEBUG(LOG_DEBUG, ("pppSigHUP: unit %d sig_hup -> pppHupCB\n", pd)); + pppHup(pd); } #if PPPOS_SUPPORT @@ -715,14 +695,18 @@ nPut(PPPControl *pc, struct pbuf *nb) for(b = nb; b != NULL; b = b->next) { if((c = sio_write(pc->fd, b->payload, b->len)) != b->len) { - PPPDEBUG((LOG_WARNING, - "PPP nPut: incomplete sio_write(%d,, %u) = %d\n", pc->fd, b->len, c)); + PPPDEBUG(LOG_WARNING, + ("PPP nPut: incomplete sio_write(fd:%"SZT_F", len:%d, c: 0x%"X8_F") c = %d\n", (size_t)pc->fd, b->len, c, c)); LINK_STATS_INC(link.err); pc->lastXMit = 0; /* prepend PPP_FLAG to next packet */ - break; + snmp_inc_ifoutdiscards(&pc->netif); + pbuf_free(nb); + return; } } + snmp_add_ifoutoctets(&pc->netif, nb->tot_len); + snmp_inc_ifoutucastpkts(&pc->netif); pbuf_free(nb); LINK_STATS_INC(link.xmit); } @@ -773,15 +757,18 @@ pppifOutputOverEthernet(int pd, struct pbuf *p) struct pbuf *pb; u_short protocol = PPP_IP; int i=0; + u16_t tot_len; - pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + sizeof(protocol), PBUF_RAM); + /* @todo: try to use pbuf_header() here! */ + pb = pbuf_alloc(PBUF_LINK, PPPOE_HDRLEN + sizeof(protocol), PBUF_RAM); if(!pb) { LINK_STATS_INC(link.memerr); LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pc->netif); return ERR_MEM; } - pbuf_header(pb, -pppoe_hdrlen); + pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); pc->lastXMit = sys_jiffies(); @@ -791,12 +778,16 @@ pppifOutputOverEthernet(int pd, struct pbuf *p) *((u_char*)pb->payload + i) = protocol & 0xFF; pbuf_chain(pb, p); + tot_len = pb->tot_len; if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { LINK_STATS_INC(link.err); + snmp_inc_ifoutdiscards(&pc->netif); return PPPERR_DEVICE; } + snmp_add_ifoutoctets(&pc->netif, tot_len); + snmp_inc_ifoutucastpkts(&pc->netif); LINK_STATS_INC(link.xmit); return ERR_OK; } @@ -804,9 +795,9 @@ pppifOutputOverEthernet(int pd, struct pbuf *p) /* Send a packet on the given connection. */ static err_t -pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr) +pppifOutput(struct netif *netif, struct pbuf *pb, ip_addr_t *ipaddr) { - int pd = (int)netif->state; + int pd = (int)(size_t)netif->state; PPPControl *pc = &pppControl[pd]; #if PPPOS_SUPPORT u_short protocol = PPP_IP; @@ -821,18 +812,20 @@ pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr) /* We let any protocol value go through - it can't hurt us * and the peer will just drop it if it's not accepting it. */ if (pd < 0 || pd >= NUM_PPP || !pc->openFlag || !pb) { - PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad parms prot=%d pb=%p\n", + PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad parms prot=%d pb=%p\n", pd, PPP_IP, pb)); LINK_STATS_INC(link.opterr); LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); return ERR_ARG; } /* Check that the link is up. */ if (lcp_phase[pd] == PHASE_DEAD) { - PPPDEBUG((LOG_ERR, "pppifOutput[%d]: link not up\n", pd)); + PPPDEBUG(LOG_ERR, ("pppifOutput[%d]: link not up\n", pd)); LINK_STATS_INC(link.rterr); LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); return ERR_RTE; } @@ -846,9 +839,10 @@ pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr) /* Grab an output buffer. */ headMB = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL); if (headMB == NULL) { - PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: first alloc fail\n", pd)); + PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: first alloc fail\n", pd)); LINK_STATS_INC(link.memerr); LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); return ERR_MEM; } @@ -870,9 +864,10 @@ pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr) protocol = PPP_VJC_UNCOMP; break; default: - PPPDEBUG((LOG_WARNING, "pppifOutput[%d]: bad IP packet\n", pd)); + PPPDEBUG(LOG_WARNING, ("pppifOutput[%d]: bad IP packet\n", pd)); LINK_STATS_INC(link.proterr); LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); pbuf_free(headMB); return ERR_VAL; } @@ -929,17 +924,18 @@ pppifOutput(struct netif *netif, struct pbuf *pb, struct ip_addr *ipaddr) /* If we failed to complete the packet, throw it away. */ if (!tailMB) { - PPPDEBUG((LOG_WARNING, - "pppifOutput[%d]: Alloc err - dropping proto=%d\n", + PPPDEBUG(LOG_WARNING, + ("pppifOutput[%d]: Alloc err - dropping proto=%d\n", pd, protocol)); pbuf_free(headMB); LINK_STATS_INC(link.memerr); LINK_STATS_INC(link.drop); + snmp_inc_ifoutdiscards(netif); return ERR_MEM; } /* Send it. */ - PPPDEBUG((LOG_INFO, "pppifOutput[%d]: proto=0x%04X\n", pd, protocol)); + PPPDEBUG(LOG_INFO, ("pppifOutput[%d]: proto=0x%"X16_F"\n", pd, protocol)); nPut(pc, headMB); #endif /* PPPOS_SUPPORT */ @@ -981,7 +977,7 @@ pppIOCtl(int pd, int cmd, void *arg) } break; #if PPPOS_SUPPORT - case PPPCTLG_FD: + case PPPCTLG_FD: /* Get the fd associated with the ppp */ if (arg) { *(sio_fd_t *)arg = pc->fd; } else { @@ -1001,11 +997,11 @@ pppIOCtl(int pd, int cmd, void *arg) /* * Return the Maximum Transmission Unit for the given PPP connection. */ -u_int +u_short pppMTU(int pd) { PPPControl *pc = &pppControl[pd]; - u_int st; + u_short st; /* Validate parameters. */ if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { @@ -1028,14 +1024,16 @@ pppWriteOverEthernet(int pd, const u_char *s, int n) s += 2; n -= 2; - pb = pbuf_alloc(PBUF_LINK, pppoe_hdrlen + n, PBUF_RAM); + LWIP_ASSERT("PPPOE_HDRLEN + n <= 0xffff", PPPOE_HDRLEN + n <= 0xffff); + pb = pbuf_alloc(PBUF_LINK, (u16_t)(PPPOE_HDRLEN + n), PBUF_RAM); if(!pb) { LINK_STATS_INC(link.memerr); LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pc->netif); return PPPERR_ALLOC; } - pbuf_header(pb, -pppoe_hdrlen); + pbuf_header(pb, -(s16_t)PPPOE_HDRLEN); pc->lastXMit = sys_jiffies(); @@ -1043,9 +1041,12 @@ pppWriteOverEthernet(int pd, const u_char *s, int n) if(pppoe_xmit(pc->pppoe_sc, pb) != ERR_OK) { LINK_STATS_INC(link.err); + snmp_inc_ifoutdiscards(&pc->netif); return PPPERR_DEVICE; } + snmp_add_ifoutoctets(&pc->netif, (u16_t)n); + snmp_inc_ifoutucastpkts(&pc->netif); LINK_STATS_INC(link.xmit); return PPPERR_NONE; } @@ -1077,6 +1078,7 @@ pppWrite(int pd, const u_char *s, int n) if (headMB == NULL) { LINK_STATS_INC(link.memerr); LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pc->netif); return PPPERR_ALLOC; } @@ -1111,16 +1113,17 @@ pppWrite(int pd, const u_char *s, int n) /* If we failed to complete the packet, throw it away. * Otherwise send it. */ if (!tailMB) { - PPPDEBUG((LOG_WARNING, - "pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len)); + PPPDEBUG(LOG_WARNING, + ("pppWrite[%d]: Alloc err - dropping pbuf len=%d\n", pd, headMB->len)); /*"pppWrite[%d]: Alloc err - dropping %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ pbuf_free(headMB); LINK_STATS_INC(link.memerr); LINK_STATS_INC(link.proterr); + snmp_inc_ifoutdiscards(&pc->netif); return PPPERR_ALLOC; } - PPPDEBUG((LOG_INFO, "pppWrite[%d]: len=%d\n", pd, headMB->len)); + PPPDEBUG(LOG_INFO, ("pppWrite[%d]: len=%d\n", pd, headMB->len)); /* "pppWrite[%d]: %d:%.*H", pd, headMB->len, LWIP_MIN(headMB->len * 2, 40), headMB->payload)); */ nPut(pc, headMB); #endif /* PPPOS_SUPPORT */ @@ -1133,7 +1136,7 @@ pppWrite(int pd, const u_char *s, int n) * the ppp interface. */ void -ppp_send_config( int unit, int mtu, u32_t asyncmap, int pcomp, int accomp) +ppp_send_config( int unit, u16_t mtu, u32_t asyncmap, int pcomp, int accomp) { PPPControl *pc = &pppControl[unit]; int i; @@ -1146,7 +1149,7 @@ ppp_send_config( int unit, int mtu, u32_t asyncmap, int pcomp, int accomp) for (i = 0; i < 32/8; i++) { pc->outACCM[i] = (u_char)((asyncmap >> (8 * i)) & 0xFF); } - PPPDEBUG((LOG_INFO, "ppp_send_config[%d]: outACCM=%X %X %X %X\n", + PPPDEBUG(LOG_INFO, ("ppp_send_config[%d]: outACCM=%X %X %X %X\n", unit, pc->outACCM[0], pc->outACCM[1], pc->outACCM[2], pc->outACCM[3])); } @@ -1159,7 +1162,7 @@ void ppp_set_xaccm(int unit, ext_accm *accm) { SMEMCPY(pppControl[unit].outACCM, accm, sizeof(ext_accm)); - PPPDEBUG((LOG_INFO, "ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n", + PPPDEBUG(LOG_INFO, ("ppp_set_xaccm[%d]: outACCM=%X %X %X %X\n", unit, pppControl[unit].outACCM[0], pppControl[unit].outACCM[1], @@ -1177,18 +1180,22 @@ ppp_recv_config( int unit, int mru, u32_t asyncmap, int pcomp, int accomp) { PPPControl *pc = &pppControl[unit]; int i; + SYS_ARCH_DECL_PROTECT(lev); LWIP_UNUSED_ARG(accomp); LWIP_UNUSED_ARG(pcomp); LWIP_UNUSED_ARG(mru); /* Load the ACCM bits for the 32 control codes. */ + SYS_ARCH_PROTECT(lev); for (i = 0; i < 32 / 8; i++) { - pc->inACCM[i] = (u_char)(asyncmap >> (i * 8)); + /* @todo: does this work? ext_accm has been modified from pppd! */ + pc->rx.inACCM[i] = (u_char)(asyncmap >> (i * 8)); } - PPPDEBUG((LOG_INFO, "ppp_recv_config[%d]: inACCM=%X %X %X %X\n", + SYS_ARCH_UNPROTECT(lev); + PPPDEBUG(LOG_INFO, ("ppp_recv_config[%d]: inACCM=%X %X %X %X\n", unit, - pc->inACCM[0], pc->inACCM[1], pc->inACCM[2], pc->inACCM[3])); + pc->rx.inACCM[0], pc->rx.inACCM[1], pc->rx.inACCM[2], pc->rx.inACCM[3])); } #if 0 @@ -1254,12 +1261,12 @@ GetMask(u32_t addr) u32_t mask, nmask; htonl(addr); - if (IN_CLASSA(addr)) { /* determine network mask for address class */ - nmask = IN_CLASSA_NET; - } else if (IN_CLASSB(addr)) { - nmask = IN_CLASSB_NET; + if (IP_CLASSA(addr)) { /* determine network mask for address class */ + nmask = IP_CLASSA_NET; + } else if (IP_CLASSB(addr)) { + nmask = IP_CLASSB_NET; } else { - nmask = IN_CLASSC_NET; + nmask = IP_CLASSC_NET; } /* class D nets are disallowed by bad_ip_adrs */ @@ -1277,7 +1284,7 @@ GetMask(u32_t addr) * sifvjcomp - config tcp header compression */ int -sifvjcomp(int pd, int vjcomp, int cidcomp, int maxcid) +sifvjcomp(int pd, int vjcomp, u8_t cidcomp, u8_t maxcid) { #if PPPOS_SUPPORT && VJ_SUPPORT PPPControl *pc = &pppControl[pd]; @@ -1285,7 +1292,7 @@ sifvjcomp(int pd, int vjcomp, int cidcomp, int maxcid) pc->vjEnabled = vjcomp; pc->vjComp.compressSlot = cidcomp; pc->vjComp.maxSlotIndex = maxcid; - PPPDEBUG((LOG_INFO, "sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n", + PPPDEBUG(LOG_INFO, ("sifvjcomp: VJ compress enable=%d slot=%d max slot=%d\n", vjcomp, cidcomp, maxcid)); #else /* PPPOS_SUPPORT && VJ_SUPPORT */ LWIP_UNUSED_ARG(pd); @@ -1306,7 +1313,12 @@ pppifNetifInit(struct netif *netif) netif->name[0] = 'p'; netif->name[1] = 'p'; netif->output = pppifOutput; - netif->mtu = pppMTU((int)netif->state); + netif->mtu = pppMTU((int)(size_t)netif->state); + netif->flags = NETIF_FLAG_POINTTOPOINT | NETIF_FLAG_LINK_UP; +#if LWIP_NETIF_HOSTNAME + /* @todo: Initialize interface hostname */ + /* netif_set_hostname(netif, "lwip"); */ +#endif /* LWIP_NETIF_HOSTNAME */ return ERR_OK; } @@ -1322,21 +1334,22 @@ sifup(int pd) if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { st = 0; - PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); } else { netif_remove(&pc->netif); - if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, &pc->addrs.his_ipaddr, (void *)pd, pppifNetifInit, ip_input)) { + if (netif_add(&pc->netif, &pc->addrs.our_ipaddr, &pc->addrs.netmask, + &pc->addrs.his_ipaddr, (void *)(size_t)pd, pppifNetifInit, ip_input)) { netif_set_up(&pc->netif); pc->if_up = 1; pc->errCode = PPPERR_NONE; - PPPDEBUG((LOG_DEBUG, "sifup: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); - if(pc->linkStatusCB) { + PPPDEBUG(LOG_DEBUG, ("sifup: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); + if (pc->linkStatusCB) { pc->linkStatusCB(pc->linkStatusCtx, pc->errCode, &pc->addrs); } } else { st = 0; - PPPDEBUG((LOG_ERR, "sifup[%d]: netif_add failed\n", pd)); + PPPDEBUG(LOG_ERR, ("sifup[%d]: netif_add failed\n", pd)); } } @@ -1366,14 +1379,14 @@ sifdown(int pd) if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { st = 0; - PPPDEBUG((LOG_WARNING, "sifdown[%d]: bad parms\n", pd)); + PPPDEBUG(LOG_WARNING, ("sifdown[%d]: bad parms\n", pd)); } else { pc->if_up = 0; /* make sure the netif status callback is called */ netif_set_down(&pc->netif); netif_remove(&pc->netif); - PPPDEBUG((LOG_DEBUG, "sifdown: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); - if(pc->linkStatusCB) { + PPPDEBUG(LOG_DEBUG, ("sifdown: unit %d: linkStatusCB=%p errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); + if (pc->linkStatusCB) { pc->linkStatusCB(pc->linkStatusCtx, PPPERR_CONNECT, NULL); } } @@ -1397,7 +1410,7 @@ sifaddr( int pd, u32_t o, u32_t h, u32_t m, u32_t ns1, u32_t ns2) if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { st = 0; - PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); } else { SMEMCPY(&pc->addrs.our_ipaddr, &o, sizeof(o)); SMEMCPY(&pc->addrs.his_ipaddr, &h, sizeof(h)); @@ -1425,7 +1438,7 @@ cifaddr( int pd, u32_t o, u32_t h) LWIP_UNUSED_ARG(h); if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { st = 0; - PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); } else { IP4_ADDR(&pc->addrs.our_ipaddr, 0,0,0,0); IP4_ADDR(&pc->addrs.his_ipaddr, 0,0,0,0); @@ -1450,7 +1463,7 @@ sifdefaultroute(int pd, u32_t l, u32_t g) if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { st = 0; - PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); } else { netif_set_default(&pc->netif); } @@ -1474,7 +1487,7 @@ cifdefaultroute(int pd, u32_t l, u32_t g) if (pd < 0 || pd >= NUM_PPP || !pc->openFlag) { st = 0; - PPPDEBUG((LOG_WARNING, "sifup[%d]: bad parms\n", pd)); + PPPDEBUG(LOG_WARNING, ("sifup[%d]: bad parms\n", pd)); } else { netif_set_default(NULL); } @@ -1486,76 +1499,36 @@ cifdefaultroute(int pd, u32_t l, u32_t g) /*** LOCAL FUNCTION DEFINITIONS ***/ /**********************************/ -#if PPPOS_SUPPORT +#if PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD /* The main PPP process function. This implements the state machine according * to section 4 of RFC 1661: The Point-To-Point Protocol. */ static void -pppMain(void *arg) +pppInputThread(void *arg) { - int pd = (int)arg; - struct pbuf *p; - PPPControl* pc; - int c; + int count; + PPPControlRx *pcrx = arg; - pc = &pppControl[pd]; - - p = pbuf_alloc(PBUF_RAW, PPP_MRU+PPP_HDRLEN, PBUF_RAM); - if (!p) { - LWIP_ASSERT("p != NULL", p); - pc->errCode = PPPERR_ALLOC; - goto out; - } - - /* - * Start the connection and handle incoming events (packet or timeout). - */ - PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd)); - tcpip_callback(pppStartCB, arg); - while (lcp_phase[pd] != PHASE_DEAD) { - if (pc->kill_link) { - PPPDEBUG((LOG_DEBUG, "pppMain: unit %d kill_link -> pppStopCB\n", pd)); - pc->errCode = PPPERR_USER; - /* This will leave us at PHASE_DEAD. */ - tcpip_callback(pppStopCB, arg); - pc->kill_link = 0; - } else if (pc->sig_hup) { - PPPDEBUG((LOG_DEBUG, "pppMain: unit %d sig_hup -> pppHupCB\n", pd)); - pc->sig_hup = 0; - tcpip_callback(pppHupCB, arg); + while (lcp_phase[pcrx->pd] != PHASE_DEAD) { + count = sio_read(pcrx->fd, pcrx->rxbuf, PPPOS_RX_BUFSIZE); + if(count > 0) { + pppInProc(pcrx, pcrx->rxbuf, count); } else { - c = sio_read(pc->fd, p->payload, p->len); - if(c > 0) { - pppInProc(pd, p->payload, c); - } else { - /* nothing received, give other tasks a chance to run */ - sys_msleep(1); - } + /* nothing received, give other tasks a chance to run */ + sys_msleep(1); } } - PPPDEBUG((LOG_INFO, "pppMain: unit %d: PHASE_DEAD\n", pd)); - pppDrop(pc); /* bug fix #17726 */ - pbuf_free(p); - -out: - PPPDEBUG((LOG_DEBUG, "pppMain: unit %d: linkStatusCB=%lx errCode=%d\n", pd, pc->linkStatusCB, pc->errCode)); - if(pc->linkStatusCB) { - pc->linkStatusCB(pc->linkStatusCtx, pc->errCode ? pc->errCode : PPPERR_PROTOCOL, NULL); - } - - pc->openFlag = 0; } -#endif /* PPPOS_SUPPORT */ +#endif /* PPPOS_SUPPORT && PPP_INPROC_OWNTHREAD */ #if PPPOE_SUPPORT void -pppOverEthernetInitFailed(void* arg) +pppOverEthernetInitFailed(int pd) { PPPControl* pc; - int pd = (int)arg; - pppHupCB(arg); - pppStopCB(arg); + pppHup(pd); + pppStop(pd); pc = &pppControl[pd]; pppoe_destroy(&pc->netif); @@ -1570,12 +1543,10 @@ static void pppOverEthernetLinkStatusCB(int pd, int up) { if(up) { - PPPDEBUG((LOG_INFO, "pppMain: unit %d: Connecting\n", pd)); - tcpip_callback(pppStartCB, (void*)pd); + PPPDEBUG(LOG_INFO, ("pppOverEthernetLinkStatusCB: unit %d: Connecting\n", pd)); + pppStart(pd); } else { - PPPControl* pc; - pc = &pppControl[pd]; - tcpip_callback(pppOverEthernetInitFailed, (void*)pd); + pppOverEthernetInitFailed(pd); } } #endif /* PPPOE_SUPPORT */ @@ -1592,8 +1563,8 @@ pppSingleBuf(struct pbuf *p) q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM); if(!q) { - PPPDEBUG((LOG_ERR, - "pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len)); + PPPDEBUG(LOG_ERR, + ("pppSingleBuf: unable to alloc new buf (%d)\n", p->tot_len)); return p; /* live dangerously */ } @@ -1632,6 +1603,8 @@ pppInput(void *arg) } LINK_STATS_INC(link.recv); + snmp_inc_ifinucastpkts(&pppControl[pd].netif); + snmp_add_ifinoctets(&pppControl[pd].netif, nb->tot_len); /* * Toss all non-LCP packets unless LCP is OPEN. @@ -1641,7 +1614,7 @@ pppInput(void *arg) if((lcp_phase[pd] <= PHASE_AUTHENTICATE) && (protocol != PPP_LCP)) { if(!((protocol == PPP_LQR) || (protocol == PPP_PAP) || (protocol == PPP_CHAP)) || (lcp_phase[pd] != PHASE_AUTHENTICATE)) { - PPPDEBUG((LOG_INFO, "pppInput: discarding proto 0x%04X in phase %d\n", protocol, lcp_phase[pd])); + PPPDEBUG(LOG_INFO, ("pppInput: discarding proto 0x%"X16_F" in phase %d\n", protocol, lcp_phase[pd])); goto drop; } } @@ -1649,7 +1622,7 @@ pppInput(void *arg) switch(protocol) { case PPP_VJC_COMP: /* VJ compressed TCP */ #if PPPOS_SUPPORT && VJ_SUPPORT - PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len)); + PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_comp in pbuf len=%d\n", pd, nb->len)); /* * Clip off the VJ header and prepend the rebuilt TCP/IP header and * pass the result to IP. @@ -1659,16 +1632,16 @@ pppInput(void *arg) return; } /* Something's wrong so drop it. */ - PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ compressed\n", pd)); + PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ compressed\n", pd)); #else /* PPPOS_SUPPORT && VJ_SUPPORT */ /* No handler for this protocol so drop the packet. */ - PPPDEBUG((LOG_INFO, "pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload)); + PPPDEBUG(LOG_INFO, ("pppInput[%d]: drop VJ Comp in %d:%s\n", pd, nb->len, nb->payload)); #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ break; case PPP_VJC_UNCOMP: /* VJ uncompressed TCP */ #if PPPOS_SUPPORT && VJ_SUPPORT - PPPDEBUG((LOG_INFO, "pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len)); + PPPDEBUG(LOG_INFO, ("pppInput[%d]: vj_un in pbuf len=%d\n", pd, nb->len)); /* * Process the TCP/IP header for VJ header compression and then pass * the packet to IP. @@ -1678,17 +1651,17 @@ pppInput(void *arg) return; } /* Something's wrong so drop it. */ - PPPDEBUG((LOG_WARNING, "pppInput[%d]: Dropping VJ uncompressed\n", pd)); + PPPDEBUG(LOG_WARNING, ("pppInput[%d]: Dropping VJ uncompressed\n", pd)); #else /* PPPOS_SUPPORT && VJ_SUPPORT */ /* No handler for this protocol so drop the packet. */ - PPPDEBUG((LOG_INFO, - "pppInput[%d]: drop VJ UnComp in %d:.*H\n", + PPPDEBUG(LOG_INFO, + ("pppInput[%d]: drop VJ UnComp in %d:.*H\n", pd, nb->len, LWIP_MIN(nb->len * 2, 40), nb->payload)); #endif /* PPPOS_SUPPORT && VJ_SUPPORT */ break; case PPP_IP: /* Internet Protocol */ - PPPDEBUG((LOG_INFO, "pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len)); + PPPDEBUG(LOG_INFO, ("pppInput[%d]: ip in pbuf len=%d\n", pd, nb->len)); if (pppControl[pd].netif.input) { pppControl[pd].netif.input(nb, &pppControl[pd].netif); return; @@ -1704,23 +1677,24 @@ pppInput(void *arg) */ for (i = 0; (protp = ppp_protocols[i]) != NULL; ++i) { if (protp->protocol == protocol && protp->enabled_flag) { - PPPDEBUG((LOG_INFO, "pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len)); + PPPDEBUG(LOG_INFO, ("pppInput[%d]: %s len=%d\n", pd, protp->name, nb->len)); nb = pppSingleBuf(nb); (*protp->input)(pd, nb->payload, nb->len); + PPPDEBUG(LOG_DETAIL, ("pppInput[%d]: packet processed\n", pd)); goto out; } } /* No handler for this protocol so reject the packet. */ - PPPDEBUG((LOG_INFO, "pppInput[%d]: rejecting unsupported proto 0x%04X len=%d\n", pd, protocol, nb->len)); + PPPDEBUG(LOG_INFO, ("pppInput[%d]: rejecting unsupported proto 0x%"X16_F" len=%d\n", pd, protocol, nb->len)); if (pbuf_header(nb, sizeof(protocol))) { LWIP_ASSERT("pbuf_header failed\n", 0); goto drop; } #if BYTE_ORDER == LITTLE_ENDIAN protocol = htons(protocol); - SMEMCPY(nb->payload, &protocol, sizeof(protocol)); #endif /* BYTE_ORDER == LITTLE_ENDIAN */ + SMEMCPY(nb->payload, &protocol, sizeof(protocol)); lcp_sprotrej(pd, nb->payload, nb->len); } break; @@ -1728,6 +1702,7 @@ pppInput(void *arg) drop: LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pppControl[pd].netif); out: pbuf_free(nb); @@ -1739,118 +1714,145 @@ out: * Drop the input packet. */ static void -pppDrop(PPPControl *pc) +pppDrop(PPPControlRx *pcrx) { - if (pc->inHead != NULL) { + if (pcrx->inHead != NULL) { #if 0 - PPPDEBUG((LOG_INFO, "pppDrop: %d:%.*H\n", pc->inHead->len, min(60, pc->inHead->len * 2), pc->inHead->payload)); + PPPDEBUG(LOG_INFO, ("pppDrop: %d:%.*H\n", pcrx->inHead->len, min(60, pcrx->inHead->len * 2), pcrx->inHead->payload)); #endif - PPPDEBUG((LOG_INFO, "pppDrop: pbuf len=%d\n", pc->inHead->len)); - if (pc->inTail && (pc->inTail != pc->inHead)) { - pbuf_free(pc->inTail); + PPPDEBUG(LOG_INFO, ("pppDrop: pbuf len=%d, addr %p\n", pcrx->inHead->len, (void*)pcrx->inHead)); + if (pcrx->inTail && (pcrx->inTail != pcrx->inHead)) { + pbuf_free(pcrx->inTail); } - pbuf_free(pc->inHead); - pc->inHead = NULL; - pc->inTail = NULL; + pbuf_free(pcrx->inHead); + pcrx->inHead = NULL; + pcrx->inTail = NULL; } #if VJ_SUPPORT - vj_uncompress_err(&pc->vjComp); + vj_uncompress_err(&pppControl[pcrx->pd].vjComp); #endif /* VJ_SUPPORT */ LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); +} + +/** Pass received raw characters to PPPoS to be decoded. This function is + * thread-safe and can be called from a dedicated RX-thread or from a main-loop. + * + * @param pd PPP descriptor index, returned by pppOpen() + * @param data received data + * @param len length of received data + */ +void +pppos_input(int pd, u_char* data, int len) +{ + pppInProc(&pppControl[pd].rx, data, len); } /** * Process a received octet string. */ static void -pppInProc(int pd, u_char *s, int l) +pppInProc(PPPControlRx *pcrx, u_char *s, int l) { - PPPControl *pc = &pppControl[pd]; struct pbuf *nextNBuf; u_char curChar; + u_char escaped; + SYS_ARCH_DECL_PROTECT(lev); - PPPDEBUG((LOG_DEBUG, "pppInProc[%d]: got %d bytes\n", pd, l)); + PPPDEBUG(LOG_DEBUG, ("pppInProc[%d]: got %d bytes\n", pcrx->pd, l)); while (l-- > 0) { curChar = *s++; - + + SYS_ARCH_PROTECT(lev); + escaped = ESCAPE_P(pcrx->inACCM, curChar); + SYS_ARCH_UNPROTECT(lev); /* Handle special characters. */ - if (ESCAPE_P(pc->inACCM, curChar)) { + if (escaped) { /* Check for escape sequences. */ /* XXX Note that this does not handle an escaped 0x5d character which * would appear as an escape character. Since this is an ASCII ']' * and there is no reason that I know of to escape it, I won't complicate * the code to handle this case. GLL */ if (curChar == PPP_ESCAPE) { - pc->inEscaped = 1; + pcrx->inEscaped = 1; /* Check for the flag character. */ } else if (curChar == PPP_FLAG) { - /* If this is just an extra flag character, ignore it. */ - if (pc->inState <= PDADDRESS) { - /* ignore it */; - /* If we haven't received the packet header, drop what has come in. */ - } else if (pc->inState < PDDATA) { - PPPDEBUG((LOG_WARNING, - "pppInProc[%d]: Dropping incomplete packet %d\n", - pd, pc->inState)); - LINK_STATS_INC(link.lenerr); - pppDrop(pc); - /* If the fcs is invalid, drop the packet. */ - } else if (pc->inFCS != PPP_GOODFCS) { - PPPDEBUG((LOG_INFO, - "pppInProc[%d]: Dropping bad fcs 0x%04X proto=0x%04X\n", - pd, pc->inFCS, pc->inProtocol)); - LINK_STATS_INC(link.chkerr); - pppDrop(pc); - /* Otherwise it's a good packet so pass it on. */ - } else { - /* Trim off the checksum. */ - if(pc->inTail->len >= 2) { - pc->inTail->len -= 2; + /* If this is just an extra flag character, ignore it. */ + if (pcrx->inState <= PDADDRESS) { + /* ignore it */; + /* If we haven't received the packet header, drop what has come in. */ + } else if (pcrx->inState < PDDATA) { + PPPDEBUG(LOG_WARNING, + ("pppInProc[%d]: Dropping incomplete packet %d\n", + pcrx->pd, pcrx->inState)); + LINK_STATS_INC(link.lenerr); + pppDrop(pcrx); + /* If the fcs is invalid, drop the packet. */ + } else if (pcrx->inFCS != PPP_GOODFCS) { + PPPDEBUG(LOG_INFO, + ("pppInProc[%d]: Dropping bad fcs 0x%"X16_F" proto=0x%"X16_F"\n", + pcrx->pd, pcrx->inFCS, pcrx->inProtocol)); + /* Note: If you get lots of these, check for UART frame errors or try different baud rate */ + LINK_STATS_INC(link.chkerr); + pppDrop(pcrx); + /* Otherwise it's a good packet so pass it on. */ + } else { + struct pbuf *inp; + /* Trim off the checksum. */ + if(pcrx->inTail->len >= 2) { + pcrx->inTail->len -= 2; - pc->inTail->tot_len = pc->inTail->len; - if (pc->inTail != pc->inHead) { - pbuf_cat(pc->inHead, pc->inTail); - } - } else { - pc->inTail->tot_len = pc->inTail->len; - if (pc->inTail != pc->inHead) { - pbuf_cat(pc->inHead, pc->inTail); - } + pcrx->inTail->tot_len = pcrx->inTail->len; + if (pcrx->inTail != pcrx->inHead) { + pbuf_cat(pcrx->inHead, pcrx->inTail); + } + } else { + pcrx->inTail->tot_len = pcrx->inTail->len; + if (pcrx->inTail != pcrx->inHead) { + pbuf_cat(pcrx->inHead, pcrx->inTail); + } - pbuf_realloc(pc->inHead, pc->inHead->tot_len - 2); - } + pbuf_realloc(pcrx->inHead, pcrx->inHead->tot_len - 2); + } - /* Dispatch the packet thereby consuming it. */ - if(tcpip_callback(pppInput, pc->inHead) != ERR_OK) { - PPPDEBUG((LOG_ERR, "pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pd)); - pbuf_free(pc->inHead); - LINK_STATS_INC(link.drop); - } - pc->inHead = NULL; - pc->inTail = NULL; - } + /* Dispatch the packet thereby consuming it. */ + inp = pcrx->inHead; + /* Packet consumed, release our references. */ + pcrx->inHead = NULL; + pcrx->inTail = NULL; +#if PPP_INPROC_MULTITHREADED + if(tcpip_callback_with_block(pppInput, inp, 0) != ERR_OK) { + PPPDEBUG(LOG_ERR, ("pppInProc[%d]: tcpip_callback() failed, dropping packet\n", pcrx->pd)); + pbuf_free(inp); + LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pppControl[pcrx->pd].netif); + } +#else /* PPP_INPROC_MULTITHREADED */ + pppInput(inp); +#endif /* PPP_INPROC_MULTITHREADED */ + } - /* Prepare for a new packet. */ - pc->inFCS = PPP_INITFCS; - pc->inState = PDADDRESS; - pc->inEscaped = 0; + /* Prepare for a new packet. */ + pcrx->inFCS = PPP_INITFCS; + pcrx->inState = PDADDRESS; + pcrx->inEscaped = 0; /* Other characters are usually control characters that may have * been inserted by the physical layer so here we just drop them. */ } else { - PPPDEBUG((LOG_WARNING, - "pppInProc[%d]: Dropping ACCM char <%d>\n", pd, curChar)); + PPPDEBUG(LOG_WARNING, + ("pppInProc[%d]: Dropping ACCM char <%d>\n", pcrx->pd, curChar)); } /* Process other characters. */ } else { /* Unencode escaped characters. */ - if (pc->inEscaped) { - pc->inEscaped = 0; + if (pcrx->inEscaped) { + pcrx->inEscaped = 0; curChar ^= PPP_TRANS; } /* Process character relative to current state. */ - switch(pc->inState) { + switch(pcrx->inState) { case PDIDLE: /* Idle state - waiting. */ /* Drop the character if it's not 0xff * we would have processed a flag character above. */ @@ -1861,12 +1863,12 @@ pppInProc(int pd, u_char *s, int l) /* Fall through */ case PDSTART: /* Process start flag. */ /* Prepare for a new packet. */ - pc->inFCS = PPP_INITFCS; + pcrx->inFCS = PPP_INITFCS; /* Fall through */ case PDADDRESS: /* Process address field. */ if (curChar == PPP_ALLSTATIONS) { - pc->inState = PDCONTROL; + pcrx->inState = PDCONTROL; break; } /* Else assume compressed address and control fields so @@ -1874,38 +1876,40 @@ pppInProc(int pd, u_char *s, int l) case PDCONTROL: /* Process control field. */ /* If we don't get a valid control code, restart. */ if (curChar == PPP_UI) { - pc->inState = PDPROTOCOL1; + pcrx->inState = PDPROTOCOL1; break; } #if 0 else { - PPPDEBUG((LOG_WARNING, - "pppInProc[%d]: Invalid control <%d>\n", pd, curChar)); - pc->inState = PDSTART; + PPPDEBUG(LOG_WARNING, + ("pppInProc[%d]: Invalid control <%d>\n", pcrx->pd, curChar)); + pcrx->inState = PDSTART; } #endif case PDPROTOCOL1: /* Process protocol field 1. */ /* If the lower bit is set, this is the end of the protocol * field. */ if (curChar & 1) { - pc->inProtocol = curChar; - pc->inState = PDDATA; + pcrx->inProtocol = curChar; + pcrx->inState = PDDATA; } else { - pc->inProtocol = (u_int)curChar << 8; - pc->inState = PDPROTOCOL2; + pcrx->inProtocol = (u_int)curChar << 8; + pcrx->inState = PDPROTOCOL2; } break; case PDPROTOCOL2: /* Process protocol field 2. */ - pc->inProtocol |= curChar; - pc->inState = PDDATA; + pcrx->inProtocol |= curChar; + pcrx->inState = PDDATA; break; case PDDATA: /* Process data byte. */ /* Make space to receive processed data. */ - if (pc->inTail == NULL || pc->inTail->len == PBUF_POOL_BUFSIZE) { - if(pc->inTail) { - pc->inTail->tot_len = pc->inTail->len; - if (pc->inTail != pc->inHead) { - pbuf_cat(pc->inHead, pc->inTail); + if (pcrx->inTail == NULL || pcrx->inTail->len == PBUF_POOL_BUFSIZE) { + if (pcrx->inTail != NULL) { + pcrx->inTail->tot_len = pcrx->inTail->len; + if (pcrx->inTail != pcrx->inHead) { + pbuf_cat(pcrx->inHead, pcrx->inTail); + /* give up the inTail reference now */ + pcrx->inTail = NULL; } } /* If we haven't started a packet, we need a packet header. */ @@ -1914,33 +1918,33 @@ pppInProc(int pd, u_char *s, int l) /* No free buffers. Drop the input packet and let the * higher layers deal with it. Continue processing * the received pbuf chain in case a new packet starts. */ - PPPDEBUG((LOG_ERR, "pppInProc[%d]: NO FREE MBUFS!\n", pd)); + PPPDEBUG(LOG_ERR, ("pppInProc[%d]: NO FREE MBUFS!\n", pcrx->pd)); LINK_STATS_INC(link.memerr); - pppDrop(pc); - pc->inState = PDSTART; /* Wait for flag sequence. */ + pppDrop(pcrx); + pcrx->inState = PDSTART; /* Wait for flag sequence. */ break; } - if (pc->inHead == NULL) { + if (pcrx->inHead == NULL) { struct pppInputHeader *pih = nextNBuf->payload; - pih->unit = pd; - pih->proto = pc->inProtocol; + pih->unit = pcrx->pd; + pih->proto = pcrx->inProtocol; nextNBuf->len += sizeof(*pih); - pc->inHead = nextNBuf; + pcrx->inHead = nextNBuf; } - pc->inTail = nextNBuf; + pcrx->inTail = nextNBuf; } /* Load character into buffer. */ - ((u_char*)pc->inTail->payload)[pc->inTail->len++] = curChar; + ((u_char*)pcrx->inTail->payload)[pcrx->inTail->len++] = curChar; break; } /* update the frame check sequence number. */ - pc->inFCS = PPP_FCS(pc->inFCS, curChar); + pcrx->inFCS = PPP_FCS(pcrx->inFCS, curChar); } - } + } /* while (l-- > 0), all bytes processed */ avRandomize(); } @@ -1954,7 +1958,7 @@ pppInProcOverEthernet(int pd, struct pbuf *pb) u16_t inProtocol; if(pb->len < sizeof(inProtocol)) { - PPPDEBUG((LOG_ERR, "pppInProcOverEthernet: too small for protocol field\n")); + PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: too small for protocol field\n")); goto drop; } @@ -1962,7 +1966,7 @@ pppInProcOverEthernet(int pd, struct pbuf *pb) /* make room for pppInputHeader - should not fail */ if (pbuf_header(pb, sizeof(*pih) - sizeof(inProtocol)) != 0) { - PPPDEBUG((LOG_ERR, "pppInProcOverEthernet: could not allocate room for header\n")); + PPPDEBUG(LOG_ERR, ("pppInProcOverEthernet: could not allocate room for header\n")); goto drop; } @@ -1972,18 +1976,45 @@ pppInProcOverEthernet(int pd, struct pbuf *pb) pih->proto = inProtocol; /* Dispatch the packet thereby consuming it. */ - if(tcpip_callback(pppInput, pb) != ERR_OK) { - PPPDEBUG((LOG_ERR, "pppInProcOverEthernet[%d]: tcpip_callback() failed, dropping packet\n", pd)); - goto drop; - } - + pppInput(pb); return; drop: LINK_STATS_INC(link.drop); + snmp_inc_ifindiscards(&pppControl[pd].netif); pbuf_free(pb); return; } #endif /* PPPOE_SUPPORT */ +#if LWIP_NETIF_STATUS_CALLBACK +/** Set the status callback of a PPP's netif + * + * @param pd The PPP descriptor returned by pppOpen() + * @param status_callback pointer to the status callback function + * + * @see netif_set_status_callback + */ +void +ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback) +{ + netif_set_status_callback(&pppControl[pd].netif, status_callback); +} +#endif /* LWIP_NETIF_STATUS_CALLBACK */ + +#if LWIP_NETIF_LINK_CALLBACK +/** Set the link callback of a PPP's netif + * + * @param pd The PPP descriptor returned by pppOpen() + * @param link_callback pointer to the link callback function + * + * @see netif_set_link_callback + */ +void +ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback) +{ + netif_set_link_callback(&pppControl[pd].netif, link_callback); +} +#endif /* LWIP_NETIF_LINK_CALLBACK */ + #endif /* PPP_SUPPORT */ diff --git a/lib/drivers/lwip/src/netif/ppp/ppp.h b/lib/drivers/lwip/src/netif/ppp/ppp.h index ebc733be650..a72ac9576ba 100644 --- a/lib/drivers/lwip/src/netif/ppp/ppp.h +++ b/lib/drivers/lwip/src/netif/ppp/ppp.h @@ -40,12 +40,23 @@ #include "lwip/def.h" #include "lwip/sio.h" -#include "lwip/api.h" -#include "lwip/sockets.h" #include "lwip/stats.h" #include "lwip/mem.h" -#include "lwip/tcpip.h" #include "lwip/netif.h" +#include "lwip/sys.h" +#include "lwip/timers.h" + +/** Some defines for code we skip compared to the original pppd. + * These are just here to minimise the use of the ugly "#if 0". */ +#define PPP_ADDITIONAL_CALLBACKS 0 + +/** Some error checks to test for unsupported code */ +#if CBCP_SUPPORT +#error "CBCP is not supported in lwIP PPP" +#endif +#if CCP_SUPPORT +#error "CCP is not supported in lwIP PPP" +#endif /* * pppd.h - PPP daemon global declarations. @@ -93,7 +104,7 @@ * OR MODIFICATIONS. */ -#define TIMEOUT(f, a, t) sys_untimeout((f), (a)), sys_timeout((t)*1000, (f), (a)) +#define TIMEOUT(f, a, t) do { sys_untimeout((f), (a)); sys_timeout((t)*1000, (f), (a)); } while(0) #define UNTIMEOUT(f, a) sys_untimeout((f), (a)) @@ -212,7 +223,7 @@ enum NPmode { #define BZERO(s, n) memset(s, 0, n) #if PPP_DEBUG -#define PRINTMSG(m, l) { m[l] = '\0'; ppp_trace(LOG_INFO, "Remote message: %s\n", m); } +#define PRINTMSG(m, l) { m[l] = '\0'; LWIP_DEBUGF(LOG_INFO, ("Remote message: %s\n", m)); } #else /* PPP_DEBUG */ #define PRINTMSG(m, l) #endif /* PPP_DEBUG */ @@ -276,24 +287,24 @@ struct protent { void (*open) (int unit); /* Close the protocol */ void (*close) (int unit, char *reason); -#if 0 +#if PPP_ADDITIONAL_CALLBACKS /* Print a packet in readable form */ int (*printpkt) (u_char *pkt, int len, void (*printer) (void *, char *, ...), void *arg); /* Process a received data packet */ void (*datainput) (int unit, u_char *pkt, int len); -#endif - int enabled_flag; /* 0 iff protocol is disabled */ +#endif /* PPP_ADDITIONAL_CALLBACKS */ + int enabled_flag; /* 0 if protocol is disabled */ char *name; /* Text name of protocol */ -#if 0 +#if PPP_ADDITIONAL_CALLBACKS /* Check requested options, assign defaults */ void (*check_options) (u_long); /* Configure interface for demand-dial */ int (*demand_conf) (int unit); /* Say whether to bring up link for this pkt */ int (*active_pkt) (u_char *pkt, int len); -#endif +#endif /* PPP_ADDITIONAL_CALLBACKS */ }; /* @@ -325,7 +336,7 @@ struct ppp_settings { }; struct ppp_addrs { - struct ip_addr our_ipaddr, his_ipaddr, netmask, dns1, dns2; + ip_addr_t our_ipaddr, his_ipaddr, netmask, dns1, dns2; }; /***************************** @@ -413,7 +424,7 @@ int pppIOCtl(int pd, int cmd, void *arg); /* * Return the Maximum Transmission Unit for the given PPP connection. */ -u_int pppMTU(int pd); +u_short pppMTU(int pd); /* * Write n characters to a ppp link. @@ -429,10 +440,10 @@ void pppLinkTerminated(int pd); void pppLinkDown(int pd); -void pppMainWakeup(int pd); +void pppos_input(int pd, u_char* data, int len); /* Configure i/f transmit parameters */ -void ppp_send_config (int, int, u32_t, int, int); +void ppp_send_config (int, u16_t, u32_t, int, int); /* Set extended transmit ACCM */ void ppp_set_xaccm (int, ext_accm *); /* Configure i/f receive parameters */ @@ -441,7 +452,7 @@ void ppp_recv_config (int, int, u32_t, int, int); int get_idle_time (int, struct ppp_idle *); /* Configure VJ TCP header compression */ -int sifvjcomp (int, int, int, int); +int sifvjcomp (int, int, u8_t, u8_t); /* Configure i/f down (for IP) */ int sifup (int); /* Set mode for handling packets for proto */ @@ -460,6 +471,13 @@ int cifdefaultroute (int, u32_t, u32_t); /* Get appropriate netmask for address */ u32_t GetMask (u32_t); +#if LWIP_NETIF_STATUS_CALLBACK +void ppp_set_netif_statuscallback(int pd, netif_status_callback_fn status_callback); +#endif /* LWIP_NETIF_STATUS_CALLBACK */ +#if LWIP_NETIF_LINK_CALLBACK +void ppp_set_netif_linkcallback(int pd, netif_status_callback_fn link_callback); +#endif /* LWIP_NETIF_LINK_CALLBACK */ + #endif /* PPP_SUPPORT */ #endif /* PPP_H */ diff --git a/lib/drivers/lwip/src/netif/ppp/ppp_oe.c b/lib/drivers/lwip/src/netif/ppp/ppp_oe.c index 5a8a45cf6b7..040a0bc93c9 100644 --- a/lib/drivers/lwip/src/netif/ppp/ppp_oe.c +++ b/lib/drivers/lwip/src/netif/ppp/ppp_oe.c @@ -72,104 +72,22 @@ #if PPPOE_SUPPORT /* don't build if not configured for use in lwipopts.h */ +#include "netif/ppp_oe.h" + #include "ppp.h" #include "pppdebug.h" -#include "lwip/sys.h" - -#include "netif/ppp_oe.h" -#include "netif/etharp.h" +#include "lwip/timers.h" +#include "lwip/memp.h" #include #include -/** @todo Replace this part with a simple list like other lwIP lists */ -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -/* - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * For details on the use of these macros, see the queue(3) manual page. - */ - -/* - * List declarations. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ - -#define LIST_EMPTY(head) ((head)->lh_first == NULL) - -#define LIST_FIRST(head) ((head)->lh_first) - -#define LIST_FOREACH(var, head, field) \ - for ((var) = LIST_FIRST((head)); \ - (var); \ - (var) = LIST_NEXT((var), field)) - -#define LIST_INIT(head) do { \ - LIST_FIRST((head)) = NULL; \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL) \ - LIST_NEXT((listelm), field)->field.le_prev = \ - &LIST_NEXT((elm), field); \ - LIST_NEXT((listelm), field) = (elm); \ - (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - LIST_NEXT((elm), field) = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ - LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field); \ - LIST_FIRST((head)) = (elm); \ - (elm)->field.le_prev = &LIST_FIRST((head)); \ -} while (0) - -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_REMOVE(elm, field) do { \ - if (LIST_NEXT((elm), field) != NULL) \ - LIST_NEXT((elm), field)->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = LIST_NEXT((elm), field); \ -} while (0) - -#endif /* !_SYS_QUEUE_H_ */ - /* Add a 16 bit unsigned value to a buffer pointed to by PTR */ #define PPPOE_ADD_16(PTR, VAL) \ - *(PTR)++ = (VAL) / 256; \ - *(PTR)++ = (VAL) % 256 + *(PTR)++ = (u8_t)((VAL) / 256); \ + *(PTR)++ = (u8_t)((VAL) % 256) /* Add a complete PPPoE header to the buffer pointed to by PTR */ #define PPPOE_ADD_HEADER(PTR, CODE, SESS, LEN) \ @@ -184,31 +102,16 @@ struct { \ #define PPPOE_DISC_MAXPADR 2 /* retry PADR twice */ #ifdef PPPOE_SERVER +#error "PPPOE_SERVER is not yet supported under lwIP!" /* from if_spppsubr.c */ #define IFF_PASSIVE IFF_LINK0 /* wait passively for connection */ #endif -struct pppoe_softc { - LIST_ENTRY(pppoe_softc) sc_list; - struct netif *sc_ethif; /* ethernet interface we are using */ - int sc_pd; /* ppp unit number */ - void (*sc_linkStatusCB)(int pd, int up); - - int sc_state; /* discovery phase or session connected */ - struct eth_addr sc_dest; /* hardware address of concentrator */ - u16_t sc_session; /* PPPoE session id */ - - char *sc_service_name; /* if != NULL: requested name of service */ - char *sc_concentrator_name; /* if != NULL: requested concentrator id */ - u8_t *sc_ac_cookie; /* content of AC cookie we must echo back */ - size_t sc_ac_cookie_len; /* length of cookie data */ -#ifdef PPPOE_SERVER - u8_t *sc_hunique; /* content of host unique we must echo back */ - size_t sc_hunique_len; /* length of host unique */ +#ifndef PPPOE_ERRORSTRING_LEN +#define PPPOE_ERRORSTRING_LEN 64 #endif - int sc_padi_retried; /* number of PADI retries already done */ - int sc_padr_retried; /* number of PADR retries already done */ -}; +static char pppoe_error_tmp[PPPOE_ERRORSTRING_LEN]; + /* input routines */ static void pppoe_dispatch_disc_pkt(struct netif *, struct pbuf *); @@ -234,24 +137,16 @@ static err_t pppoe_send_padt(struct netif *, u_int, const u8_t *); static struct pppoe_softc * pppoe_find_softc_by_session(u_int, struct netif *); static struct pppoe_softc * pppoe_find_softc_by_hunique(u8_t *, size_t, struct netif *); -static LIST_HEAD(pppoe_softc_head, pppoe_softc) pppoe_softc_list; - -int pppoe_hdrlen; - -void -pppoe_init(void) -{ - pppoe_hdrlen = sizeof(struct eth_hdr) + PPPOE_HEADERLEN; - LIST_INIT(&pppoe_softc_list); -} +/** linked list of created pppoe interfaces */ +static struct pppoe_softc *pppoe_softc_list; err_t pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), struct pppoe_softc **scptr) { struct pppoe_softc *sc; - sc = mem_malloc(sizeof(struct pppoe_softc)); - if(!sc) { + sc = (struct pppoe_softc *)memp_malloc(MEMP_PPPOE_IF); + if (sc == NULL) { *scptr = NULL; return ERR_MEM; } @@ -264,7 +159,9 @@ pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), sc->sc_linkStatusCB = linkStatusCB; sc->sc_ethif = ethif; - LIST_INSERT_HEAD(&pppoe_softc_list, sc, sc_list); + /* put the new interface at the head of the list */ + sc->next = pppoe_softc_list; + pppoe_softc_list = sc; *scptr = sc; @@ -274,9 +171,9 @@ pppoe_create(struct netif *ethif, int pd, void (*linkStatusCB)(int pd, int up), err_t pppoe_destroy(struct netif *ifp) { - struct pppoe_softc * sc; + struct pppoe_softc *sc, *prev = NULL; - LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + for (sc = pppoe_softc_list; sc != NULL; prev = sc, sc = sc->next) { if (sc->sc_ethif == ifp) { break; } @@ -286,19 +183,24 @@ pppoe_destroy(struct netif *ifp) return ERR_IF; } - tcpip_untimeout(pppoe_timeout, sc); - LIST_REMOVE(sc, sc_list); + sys_untimeout(pppoe_timeout, sc); + if (prev == NULL) { + /* remove sc from the head of the list */ + pppoe_softc_list = sc->next; + } else { + /* remove sc from the list */ + prev->next = sc->next; + } +#ifdef PPPOE_TODO if (sc->sc_concentrator_name) { mem_free(sc->sc_concentrator_name); } if (sc->sc_service_name) { mem_free(sc->sc_service_name); } - if (sc->sc_ac_cookie) { - mem_free(sc->sc_ac_cookie); - } - mem_free(sc); +#endif /* PPPOE_TODO */ + memp_free(MEMP_PPPOE_IF, sc); return ERR_OK; } @@ -318,7 +220,7 @@ pppoe_find_softc_by_session(u_int session, struct netif *rcvif) return NULL; } - LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { if (sc->sc_state == PPPOE_STATE_SESSION && sc->sc_session == session) { if (sc->sc_ethif == rcvif) { @@ -338,7 +240,7 @@ pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) { struct pppoe_softc *sc, *t; - if (LIST_EMPTY(&pppoe_softc_list)) { + if (pppoe_softc_list == NULL) { return NULL; } @@ -347,14 +249,14 @@ pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) } MEMCPY(&t, token, len); - LIST_FOREACH(sc, &pppoe_softc_list, sc_list) { + for (sc = pppoe_softc_list; sc != NULL; sc = sc->next) { if (sc == t) { break; } } if (sc == NULL) { - PPPDEBUG((LOG_DEBUG, "pppoe: alien host unique tag, no session found\n")); + PPPDEBUG(LOG_DEBUG, ("pppoe: alien host unique tag, no session found\n")); return NULL; } @@ -373,10 +275,8 @@ pppoe_find_softc_by_hunique(u8_t *token, size_t len, struct netif *rcvif) } static void -pppoe_linkstatus_up(void *arg) +pppoe_linkstatus_up(struct pppoe_softc *sc) { - struct pppoe_softc *sc = (struct pppoe_softc*)arg; - sc->sc_linkStatusCB(sc->sc_pd, 1); } @@ -389,9 +289,8 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb) struct pppoe_softc *sc; const char *err_msg; char devname[6]; - char *error; u8_t *ac_cookie; - size_t ac_cookie_len; + u16_t ac_cookie_len; #ifdef PPPOE_SERVER u8_t *hunique; size_t hunique_len; @@ -439,7 +338,7 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb) goto done; } if(pb->tot_len == pb->len) { - pb->tot_len = pb->len = off + plen; /* ignore trailing garbage */ + pb->tot_len = pb->len = (u16_t)off + plen; /* ignore trailing garbage */ } tag = 0; len = 0; @@ -492,17 +391,11 @@ pppoe_dispatch_disc_pkt(struct netif *netif, struct pbuf *pb) break; } if (err_msg) { - error = NULL; if (errortag && len) { - error = mem_malloc(len+1); - if (error) { - strncpy(error, (char*)pb->payload + off + sizeof(pt), len); - error[len-1] = '\0'; - } - } - if (error) { - printf("%s: %s: %s\n", devname, err_msg, error); - mem_free(error); + u16_t error_len = LWIP_MIN(len, sizeof(pppoe_error_tmp)-1); + strncpy(pppoe_error_tmp, (char*)pb->payload + off + sizeof(pt), error_len); + pppoe_error_tmp[error_len-1] = '\0'; + printf("%s: %s: %s\n", devname, err_msg, pppoe_error_tmp); } else { printf("%s: %s\n", devname, err_msg); } @@ -554,9 +447,9 @@ breakbreak:; sc->sc_state = PPPOE_STATE_PADO_SENT; pppoe_send_pado(sc); break; - #endif /* PPPOE_SERVER */ +#endif /* PPPOE_SERVER */ case PPPOE_CODE_PADR: - #ifdef PPPOE_SERVER +#ifdef PPPOE_SERVER /* * get sc from ac_cookie if IFF_PASSIVE */ @@ -590,16 +483,16 @@ breakbreak:; } pppoe_send_pads(sc); sc->sc_state = PPPOE_STATE_SESSION; - tcpip_timeout (100, pppoe_linkstatus_up, sc); /* notify upper layers */ + pppoe_linkstatus_up(sc); /* notify upper layers */ break; - #else +#else /* ignore, we are no access concentrator */ goto done; - #endif /* PPPOE_SERVER */ +#endif /* PPPOE_SERVER */ case PPPOE_CODE_PADO: if (sc == NULL) { /* be quiet if there is not a single pppoe instance */ - if (!LIST_EMPTY(&pppoe_softc_list)) { + if (pppoe_softc_list != NULL) { printf("pppoe: received PADO but could not find request for it\n"); } goto done; @@ -609,34 +502,27 @@ breakbreak:; goto done; } if (ac_cookie) { - if (sc->sc_ac_cookie) { - mem_free(sc->sc_ac_cookie); - } - sc->sc_ac_cookie = mem_malloc(ac_cookie_len); - if (sc->sc_ac_cookie == NULL) { - goto done; - } sc->sc_ac_cookie_len = ac_cookie_len; MEMCPY(sc->sc_ac_cookie, ac_cookie, ac_cookie_len); } MEMCPY(&sc->sc_dest, ethhdr->src.addr, sizeof(sc->sc_dest.addr)); - tcpip_untimeout(pppoe_timeout, sc); + sys_untimeout(pppoe_timeout, sc); sc->sc_padr_retried = 0; sc->sc_state = PPPOE_STATE_PADR_SENT; if ((err = pppoe_send_padr(sc)) != 0) { - PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); } - tcpip_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); break; case PPPOE_CODE_PADS: if (sc == NULL) { goto done; } sc->sc_session = session; - tcpip_untimeout(pppoe_timeout, sc); - PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session)); + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x connected\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, session)); sc->sc_state = PPPOE_STATE_SESSION; - tcpip_timeout (100, pppoe_linkstatus_up, sc); /* notify upper layers */ + pppoe_linkstatus_up(sc); /* notify upper layers */ break; case PPPOE_CODE_PADT: if (sc == NULL) { @@ -646,11 +532,11 @@ breakbreak:; break; default: if(sc) { - printf("%c%c%"U16_F": unknown code (0x%04x) session = 0x%04x\n", + printf("%c%c%"U16_F": unknown code (0x%"X16_F") session = 0x%"X16_F"\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, - ph->code, session); + (u16_t)ph->code, session); } else { - printf("pppoe: unknown code (0x%04x) session = 0x%04x\n", ph->code, session); + printf("pppoe: unknown code (0x%"X16_F") session = 0x%"X16_F"\n", (u16_t)ph->code, session); } break; } @@ -664,7 +550,7 @@ void pppoe_disc_input(struct netif *netif, struct pbuf *p) { /* avoid error messages if there is not a single pppoe instance */ - if (!LIST_EMPTY(&pppoe_softc_list)) { + if (pppoe_softc_list != NULL) { pppoe_dispatch_disc_pkt(netif, p); } else { pbuf_free(p); @@ -686,7 +572,7 @@ pppoe_data_input(struct netif *netif, struct pbuf *pb) #endif if (pbuf_header(pb, -(int)sizeof(struct eth_hdr)) != 0) { /* bail out */ - PPPDEBUG((LOG_ERR, "pppoe_data_input: pbuf_header failed\n")); + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header failed\n")); LINK_STATS_INC(link.lenerr); goto drop; } @@ -726,12 +612,12 @@ pppoe_data_input(struct netif *netif, struct pbuf *pb) if (pbuf_header(pb, -(int)(PPPOE_HEADERLEN)) != 0) { /* bail out */ - PPPDEBUG((LOG_ERR, "pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n")); + PPPDEBUG(LOG_ERR, ("pppoe_data_input: pbuf_header PPPOE_HEADERLEN failed\n")); LINK_STATS_INC(link.lenerr); goto drop; } - PPPDEBUG((LOG_DEBUG, "pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n", + PPPDEBUG(LOG_DEBUG, ("pppoe_data_input: %c%c%"U16_F": pkthdr.len=%d, pppoe.len=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, pb->len, plen)); @@ -765,7 +651,7 @@ pppoe_output(struct pppoe_softc *sc, struct pbuf *pb) MEMCPY(ethhdr->dest.addr, sc->sc_dest.addr, sizeof(ethhdr->dest.addr)); MEMCPY(ethhdr->src.addr, ((struct eth_addr *)sc->sc_ethif->hwaddr)->addr, sizeof(ethhdr->src.addr)); - PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n", + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F" (%x) state=%d, session=0x%x output -> %02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F":%02"X16_F", len=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, etype, sc->sc_state, sc->sc_session, sc->sc_dest.addr[0], sc->sc_dest.addr[1], sc->sc_dest.addr[2], sc->sc_dest.addr[3], sc->sc_dest.addr[4], sc->sc_dest.addr[5], @@ -783,46 +669,59 @@ pppoe_send_padi(struct pppoe_softc *sc) { struct pbuf *pb; u8_t *p; - int len, l1 = 0, l2 = 0; /* XXX: gcc */ + int len; +#ifdef PPPOE_TODO + int l1 = 0, l2 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ if (sc->sc_state >PPPOE_STATE_PADI_SENT) { - PPPDEBUG((LOG_ERR, "ERROR: pppoe_send_padi in state %d", sc->sc_state)); + PPPDEBUG(LOG_ERR, ("ERROR: pppoe_send_padi in state %d", sc->sc_state)); } /* calculate length of frame (excluding ethernet header + pppoe header) */ len = 2 + 2 + 2 + 2 + sizeof sc; /* service name tag is required, host unique is send too */ +#ifdef PPPOE_TODO if (sc->sc_service_name != NULL) { - l1 = strlen(sc->sc_service_name); + l1 = (int)strlen(sc->sc_service_name); len += l1; } if (sc->sc_concentrator_name != NULL) { - l2 = strlen(sc->sc_concentrator_name); + l2 = (int)strlen(sc->sc_concentrator_name); len += 2 + 2 + l2; } +#endif /* PPPOE_TODO */ + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); /* allocate a buffer */ - pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); + pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM); if (!pb) { return ERR_MEM; } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); p = (u8_t*)pb->payload + sizeof (struct eth_hdr); /* fill in pkt */ - PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, len); + PPPOE_ADD_HEADER(p, PPPOE_CODE_PADI, 0, (u16_t)len); PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO if (sc->sc_service_name != NULL) { PPPOE_ADD_16(p, l1); MEMCPY(p, sc->sc_service_name, l1); p += l1; - } else { + } else +#endif /* PPPOE_TODO */ + { PPPOE_ADD_16(p, 0); } +#ifdef PPPOE_TODO if (sc->sc_concentrator_name != NULL) { PPPOE_ADD_16(p, PPPOE_TAG_ACNAME); PPPOE_ADD_16(p, l2); MEMCPY(p, sc->sc_concentrator_name, l2); p += l2; } +#endif /* PPPOE_TODO */ PPPOE_ADD_16(p, PPPOE_TAG_HUNIQUE); PPPOE_ADD_16(p, sizeof(sc)); MEMCPY(p, &sc, sizeof sc); @@ -837,7 +736,7 @@ pppoe_timeout(void *arg) int retry_wait, err; struct pppoe_softc *sc = (struct pppoe_softc*)arg; - PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": timeout\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); switch (sc->sc_state) { case PPPOE_STATE_PADI_SENT: @@ -869,9 +768,9 @@ pppoe_timeout(void *arg) } if ((err = pppoe_send_padi(sc)) != 0) { sc->sc_padi_retried--; - PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to transmit PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); } - tcpip_timeout(retry_wait, pppoe_timeout, sc); + sys_timeout(retry_wait, pppoe_timeout, sc); break; case PPPOE_STATE_PADR_SENT: @@ -881,16 +780,16 @@ pppoe_timeout(void *arg) sc->sc_state = PPPOE_STATE_PADI_SENT; sc->sc_padr_retried = 0; if ((err = pppoe_send_padi(sc)) != 0) { - PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); } - tcpip_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padi_retried), pppoe_timeout, sc); return; } if ((err = pppoe_send_padr(sc)) != 0) { sc->sc_padr_retried--; - PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADR, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); } - tcpip_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); + sys_timeout(PPPOE_DISC_TIMEOUT * (1 + sc->sc_padr_retried), pppoe_timeout, sc); break; case PPPOE_STATE_CLOSING: pppoe_do_disconnect(sc); @@ -920,8 +819,8 @@ pppoe_connect(struct pppoe_softc *sc) sc->sc_state = PPPOE_STATE_PADI_SENT; sc->sc_padr_retried = 0; err = pppoe_send_padi(sc); - PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); - tcpip_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": failed to send PADI, error=%d\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, err)); + sys_timeout(PPPOE_DISC_TIMEOUT, pppoe_timeout, sc); return err; } @@ -938,7 +837,7 @@ pppoe_disconnect(struct pppoe_softc *sc) * function and defer disconnecting to the timeout handler. */ sc->sc_state = PPPOE_STATE_CLOSING; - tcpip_timeout(20, pppoe_timeout, sc); + sys_timeout(20, pppoe_timeout, sc); } static int @@ -949,17 +848,13 @@ pppoe_do_disconnect(struct pppoe_softc *sc) if (sc->sc_state < PPPOE_STATE_SESSION) { err = EBUSY; } else { - PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": disconnecting\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); err = pppoe_send_padt(sc->sc_ethif, sc->sc_session, (const u8_t *)&sc->sc_dest); } /* cleanup softc */ sc->sc_state = PPPOE_STATE_INITIAL; MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); - if (sc->sc_ac_cookie) { - mem_free(sc->sc_ac_cookie); - sc->sc_ac_cookie = NULL; - } sc->sc_ac_cookie_len = 0; #ifdef PPPOE_SERVER if (sc->sc_hunique) { @@ -995,32 +890,43 @@ pppoe_send_padr(struct pppoe_softc *sc) { struct pbuf *pb; u8_t *p; - size_t len, l1 = 0; /* XXX: gcc */ + size_t len; +#ifdef PPPOE_TODO + size_t l1 = 0; /* XXX: gcc */ +#endif /* PPPOE_TODO */ if (sc->sc_state != PPPOE_STATE_PADR_SENT) { return ERR_CONN; } len = 2 + 2 + 2 + 2 + sizeof(sc); /* service name, host unique */ +#ifdef PPPOE_TODO if (sc->sc_service_name != NULL) { /* service name tag maybe empty */ l1 = strlen(sc->sc_service_name); len += l1; } +#endif /* PPPOE_TODO */ if (sc->sc_ac_cookie_len > 0) { len += 2 + 2 + sc->sc_ac_cookie_len; /* AC cookie */ } - pb = pbuf_alloc(PBUF_LINK, sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len, PBUF_RAM); + LWIP_ASSERT("sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff", + sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len <= 0xffff); + pb = pbuf_alloc(PBUF_LINK, (u16_t)(sizeof(struct eth_hdr) + PPPOE_HEADERLEN + len), PBUF_RAM); if (!pb) { return ERR_MEM; } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); p = (u8_t*)pb->payload + sizeof (struct eth_hdr); PPPOE_ADD_HEADER(p, PPPOE_CODE_PADR, 0, len); PPPOE_ADD_16(p, PPPOE_TAG_SNAME); +#ifdef PPPOE_TODO if (sc->sc_service_name != NULL) { PPPOE_ADD_16(p, l1); MEMCPY(p, sc->sc_service_name, l1); p += l1; - } else { + } else +#endif /* PPPOE_TODO */ + { PPPOE_ADD_16(p, 0); } if (sc->sc_ac_cookie_len > 0) { @@ -1049,9 +955,10 @@ pppoe_send_padt(struct netif *outgoing_if, u_int session, const u8_t *dest) if (!pb) { return ERR_MEM; } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); ethhdr = (struct eth_hdr *)pb->payload; - ethhdr->type = htons(ETHTYPE_PPPOEDISC); + ethhdr->type = PP_HTONS(ETHTYPE_PPPOEDISC); MEMCPY(ethhdr->dest.addr, dest, sizeof(ethhdr->dest.addr)); MEMCPY(ethhdr->src.addr, ((struct eth_addr *)outgoing_if->hwaddr)->addr, sizeof(ethhdr->src.addr)); @@ -1087,6 +994,7 @@ pppoe_send_pado(struct pppoe_softc *sc) if (!pb) { return ERR_MEM; } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); p = (u8_t*)pb->payload + sizeof (struct eth_hdr); PPPOE_ADD_HEADER(p, PPPOE_CODE_PADO, 0, len); PPPOE_ADD_16(p, PPPOE_TAG_ACCOOKIE); @@ -1123,6 +1031,7 @@ pppoe_send_pads(struct pppoe_softc *sc) if (!pb) { return ERR_MEM; } + LWIP_ASSERT("pb->tot_len == pb->len", pb->tot_len == pb->len); p = (u8_t*)pb->payload + sizeof (struct eth_hdr); PPPOE_ADD_HEADER(p, PPPOE_CODE_PADS, sc->sc_session, len); PPPOE_ADD_16(p, PPPOE_TAG_SNAME); @@ -1158,7 +1067,7 @@ pppoe_xmit(struct pppoe_softc *sc, struct pbuf *pb) /* make room for Ethernet header - should not fail */ if (pbuf_header(pb, sizeof(struct eth_hdr) + PPPOE_HEADERLEN) != 0) { /* bail out */ - PPPDEBUG((LOG_ERR, "pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); + PPPDEBUG(LOG_ERR, ("pppoe: %c%c%"U16_F": pppoe_xmit: could not allocate room for header\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num)); LINK_STATS_INC(link.lenerr); pbuf_free(pb); return ERR_BUF; @@ -1204,8 +1113,8 @@ pppoe_clear_softc(struct pppoe_softc *sc, const char *message) LWIP_UNUSED_ARG(message); /* stop timer */ - tcpip_untimeout(pppoe_timeout, sc); - PPPDEBUG((LOG_DEBUG, "pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); + sys_untimeout(pppoe_timeout, sc); + PPPDEBUG(LOG_DEBUG, ("pppoe: %c%c%"U16_F": session 0x%x terminated, %s\n", sc->sc_ethif->name[0], sc->sc_ethif->name[1], sc->sc_ethif->num, sc->sc_session, message)); /* fix our state */ sc->sc_state = PPPOE_STATE_INITIAL; @@ -1215,10 +1124,6 @@ pppoe_clear_softc(struct pppoe_softc *sc, const char *message) /* clean up softc */ MEMCPY(&sc->sc_dest, ethbroadcast.addr, sizeof(sc->sc_dest)); - if (sc->sc_ac_cookie) { - mem_free(sc->sc_ac_cookie); - sc->sc_ac_cookie = NULL; - } sc->sc_ac_cookie_len = 0; sc->sc_session = 0; } diff --git a/lib/drivers/lwip/src/netif/ppp/pppdebug.h b/lib/drivers/lwip/src/netif/ppp/pppdebug.h index 6253863c9b9..81349971db6 100644 --- a/lib/drivers/lwip/src/netif/ppp/pppdebug.h +++ b/lib/drivers/lwip/src/netif/ppp/pppdebug.h @@ -36,50 +36,37 @@ #ifndef PPPDEBUG_H #define PPPDEBUG_H -/************************ -*** PUBLIC DATA TYPES *** -************************/ /* Trace levels. */ -typedef enum { -LOG_CRITICAL = 0, -LOG_ERR = 1, -LOG_NOTICE = 2, -LOG_WARNING = 3, -LOG_INFO = 5, -LOG_DETAIL = 6, -LOG_DEBUG = 7 -} LogCodes; +#define LOG_CRITICAL (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_ERR (PPP_DEBUG | LWIP_DBG_LEVEL_SEVERE) +#define LOG_NOTICE (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_WARNING (PPP_DEBUG | LWIP_DBG_LEVEL_WARNING) +#define LOG_INFO (PPP_DEBUG) +#define LOG_DETAIL (PPP_DEBUG) +#define LOG_DEBUG (PPP_DEBUG) -/*********************** -*** PUBLIC FUNCTIONS *** -***********************/ -/* - * ppp_trace - a form of printf to send tracing information to stderr - */ -void ppp_trace(int level, const char *format,...); - #define TRACELCP PPP_DEBUG #if PPP_DEBUG -#define AUTHDEBUG(a) ppp_trace a -#define IPCPDEBUG(a) ppp_trace a -#define UPAPDEBUG(a) ppp_trace a -#define LCPDEBUG(a) ppp_trace a -#define FSMDEBUG(a) ppp_trace a -#define CHAPDEBUG(a) ppp_trace a -#define PPPDEBUG(a) ppp_trace a +#define AUTHDEBUG(a, b) LWIP_DEBUGF(a, b) +#define IPCPDEBUG(a, b) LWIP_DEBUGF(a, b) +#define UPAPDEBUG(a, b) LWIP_DEBUGF(a, b) +#define LCPDEBUG(a, b) LWIP_DEBUGF(a, b) +#define FSMDEBUG(a, b) LWIP_DEBUGF(a, b) +#define CHAPDEBUG(a, b) LWIP_DEBUGF(a, b) +#define PPPDEBUG(a, b) LWIP_DEBUGF(a, b) #else /* PPP_DEBUG */ -#define AUTHDEBUG(a) -#define IPCPDEBUG(a) -#define UPAPDEBUG(a) -#define LCPDEBUG(a) -#define FSMDEBUG(a) -#define CHAPDEBUG(a) -#define PPPDEBUG(a) +#define AUTHDEBUG(a, b) +#define IPCPDEBUG(a, b) +#define UPAPDEBUG(a, b) +#define LCPDEBUG(a, b) +#define FSMDEBUG(a, b) +#define CHAPDEBUG(a, b) +#define PPPDEBUG(a, b) #endif /* PPP_DEBUG */ diff --git a/lib/drivers/lwip/src/netif/ppp/randm.c b/lib/drivers/lwip/src/netif/ppp/randm.c index 83c4174171f..2f35caf6a00 100644 --- a/lib/drivers/lwip/src/netif/ppp/randm.c +++ b/lib/drivers/lwip/src/netif/ppp/randm.c @@ -85,7 +85,7 @@ avChurnRand(char *randData, u32_t randLen) { MD5_CTX md5; - /* ppp_trace(LOG_INFO, "churnRand: %u@%P\n", randLen, randData); */ + /* LWIP_DEBUGF(LOG_INFO, ("churnRand: %u@%P\n", randLen, randData)); */ MD5Init(&md5); MD5Update(&md5, (u_char *)randPool, sizeof(randPool)); if (randData) { @@ -100,7 +100,7 @@ avChurnRand(char *randData, u32_t randLen) MD5Update(&md5, (u_char *)&sysData, sizeof(sysData)); } MD5Final((u_char *)randPool, &md5); -/* ppp_trace(LOG_INFO, "churnRand: -> 0\n"); */ +/* LWIP_DEBUGF(LOG_INFO, ("churnRand: -> 0\n")); */ } /* diff --git a/lib/drivers/lwip/src/netif/ppp/vj.c b/lib/drivers/lwip/src/netif/ppp/vj.c index 694b7027d0a..b7f2d54c627 100644 --- a/lib/drivers/lwip/src/netif/ppp/vj.c +++ b/lib/drivers/lwip/src/netif/ppp/vj.c @@ -47,18 +47,10 @@ #define INCR(counter) #endif -#if defined(NO_CHAR_BITFIELDS) -#define getip_hl(base) ((base).ip_hl_v&0xf) -#define getth_off(base) (((base).th_x2_off&0xf0)>>4) -#else -#define getip_hl(base) ((base).ip_hl) -#define getth_off(base) ((base).th_off) -#endif - void vj_compress_init(struct vjcompress *comp) { - register u_int i; + register u_char i; register struct cstate *tstate = comp->tstate; #if MAX_SLOTS == 0 @@ -86,21 +78,21 @@ vj_compress_init(struct vjcompress *comp) #define ENCODE(n) { \ if ((u_short)(n) >= 256) { \ *cp++ = 0; \ - cp[1] = (n); \ - cp[0] = (n) >> 8; \ + cp[1] = (u_char)(n); \ + cp[0] = (u_char)((n) >> 8); \ cp += 2; \ } else { \ - *cp++ = (n); \ + *cp++ = (u_char)(n); \ } \ } #define ENCODEZ(n) { \ if ((u_short)(n) >= 256 || (u_short)(n) == 0) { \ *cp++ = 0; \ - cp[1] = (n); \ - cp[0] = (n) >> 8; \ + cp[1] = (u_char)(n); \ + cp[0] = (u_char)((n) >> 8); \ cp += 2; \ } else { \ - *cp++ = (n); \ + *cp++ = (u_char)(n); \ } \ } @@ -145,11 +137,11 @@ vj_compress_init(struct vjcompress *comp) u_int vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) { - register struct ip *ip = (struct ip *)pb->payload; + register struct ip_hdr *ip = (struct ip_hdr *)pb->payload; register struct cstate *cs = comp->last_cs->cs_next; - register u_short hlen = getip_hl(*ip); - register struct tcphdr *oth; - register struct tcphdr *th; + register u_short hlen = IPH_HL(ip); + register struct tcp_hdr *oth; + register struct tcp_hdr *th; register u_short deltaS, deltaA; register u_long deltaL; register u_int changes = 0; @@ -159,7 +151,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) /* * Check that the packet is IP proto TCP. */ - if (ip->ip_p != IPPROTO_TCP) { + if (IPH_PROTO(ip) != IP_PROTO_TCP) { return (TYPE_IP); } @@ -168,11 +160,11 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) * `compressible' (i.e., ACK isn't set or some other control bit is * set). */ - if ((ip->ip_off & htons(0x3fff)) || pb->tot_len < 40) { + if ((IPH_OFFSET(ip) & PP_HTONS(0x3fff)) || pb->tot_len < 40) { return (TYPE_IP); } - th = (struct tcphdr *)&((long *)ip)[hlen]; - if ((th->th_flags & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) { + th = (struct tcp_hdr *)&((long *)ip)[hlen]; + if ((TCPH_FLAGS(th) & (TCP_SYN|TCP_FIN|TCP_RST|TCP_ACK)) != TCP_ACK) { return (TYPE_IP); } /* @@ -183,9 +175,9 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) * again & we don't have to do any reordering if it's used. */ INCR(vjs_packets); - if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr - || ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr - || *(long *)th != ((long *)&cs->cs_ip)[getip_hl(cs->cs_ip)]) { + if (!ip_addr_cmp(&ip->src, &cs->cs_ip.src) + || !ip_addr_cmp(&ip->dest, &cs->cs_ip.dest) + || *(long *)th != ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) { /* * Wasn't the first -- search for it. * @@ -204,9 +196,9 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) do { lcs = cs; cs = cs->cs_next; INCR(vjs_searches); - if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr - && ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr - && *(long *)th == ((long *)&cs->cs_ip)[getip_hl(cs->cs_ip)]) { + if (ip_addr_cmp(&ip->src, &cs->cs_ip.src) + && ip_addr_cmp(&ip->dest, &cs->cs_ip.dest) + && *(long *)th == ((long *)&cs->cs_ip)[IPH_HL(&cs->cs_ip)]) { goto found; } } while (cs != lastcs); @@ -221,7 +213,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) */ INCR(vjs_misses); comp->last_cs = lcs; - hlen += getth_off(*th); + hlen += TCPH_OFFSET(th); hlen <<= 2; /* Check that the IP/TCP headers are contained in the first buffer. */ if (hlen > pb->len) { @@ -242,13 +234,13 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) } } - oth = (struct tcphdr *)&((long *)&cs->cs_ip)[hlen]; + oth = (struct tcp_hdr *)&((long *)&cs->cs_ip)[hlen]; deltaS = hlen; - hlen += getth_off(*th); + hlen += TCPH_OFFSET(th); hlen <<= 2; /* Check that the IP/TCP headers are contained in the first buffer. */ if (hlen > pb->len) { - PPPDEBUG((LOG_INFO, "vj_compress_tcp: header len %d spans buffers\n", hlen)); + PPPDEBUG(LOG_INFO, ("vj_compress_tcp: header len %d spans buffers\n", hlen)); return (TYPE_IP); } @@ -266,9 +258,9 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) if (((u_short *)ip)[0] != ((u_short *)&cs->cs_ip)[0] || ((u_short *)ip)[3] != ((u_short *)&cs->cs_ip)[3] || ((u_short *)ip)[4] != ((u_short *)&cs->cs_ip)[4] - || getth_off(*th) != getth_off(*oth) + || TCPH_OFFSET(th) != TCPH_OFFSET(oth) || (deltaS > 5 && BCMP(ip + 1, &cs->cs_ip + 1, (deltaS - 5) << 2)) - || (getth_off(*th) > 5 && BCMP(th + 1, oth + 1, (getth_off(*th) - 5) << 2))) { + || (TCPH_OFFSET(th) > 5 && BCMP(th + 1, oth + 1, (TCPH_OFFSET(th) - 5) << 2))) { goto uncompressed; } @@ -278,11 +270,11 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) * ack, seq (the order minimizes the number of temporaries * needed in this section of code). */ - if (th->th_flags & TCP_URG) { - deltaS = ntohs(th->th_urp); + if (TCPH_FLAGS(th) & TCP_URG) { + deltaS = ntohs(th->urgp); ENCODEZ(deltaS); changes |= NEW_U; - } else if (th->th_urp != oth->th_urp) { + } else if (th->urgp != oth->urgp) { /* argh! URG not set but urp changed -- a sensible * implementation should never do this but RFC793 * doesn't prohibit the change so we have to deal @@ -290,12 +282,12 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) goto uncompressed; } - if ((deltaS = (u_short)(ntohs(th->th_win) - ntohs(oth->th_win))) != 0) { + if ((deltaS = (u_short)(ntohs(th->wnd) - ntohs(oth->wnd))) != 0) { ENCODE(deltaS); changes |= NEW_W; } - if ((deltaL = ntohl(th->th_ack) - ntohl(oth->th_ack)) != 0) { + if ((deltaL = ntohl(th->ackno) - ntohl(oth->ackno)) != 0) { if (deltaL > 0xffff) { goto uncompressed; } @@ -304,7 +296,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) changes |= NEW_A; } - if ((deltaL = ntohl(th->th_seq) - ntohl(oth->th_seq)) != 0) { + if ((deltaL = ntohl(th->seqno) - ntohl(oth->seqno)) != 0) { if (deltaL > 0xffff) { goto uncompressed; } @@ -323,8 +315,8 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) * retransmitted ack or window probe. Send it uncompressed * in case the other side missed the compressed version. */ - if (ip->ip_len != cs->cs_ip.ip_len && - ntohs(cs->cs_ip.ip_len) == hlen) { + if (IPH_LEN(ip) != IPH_LEN(&cs->cs_ip) && + ntohs(IPH_LEN(&cs->cs_ip)) == hlen) { break; } @@ -339,7 +331,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) goto uncompressed; case NEW_S|NEW_A: - if (deltaS == deltaA && deltaS == ntohs(cs->cs_ip.ip_len) - hlen) { + if (deltaS == deltaA && deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { /* special case for echoed terminal traffic */ changes = SPECIAL_I; cp = new_seq; @@ -347,7 +339,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) break; case NEW_S: - if (deltaS == ntohs(cs->cs_ip.ip_len) - hlen) { + if (deltaS == ntohs(IPH_LEN(&cs->cs_ip)) - hlen) { /* special case for data xfer */ changes = SPECIAL_D; cp = new_seq; @@ -355,19 +347,19 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) break; } - deltaS = (u_short)(ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id)); + deltaS = (u_short)(ntohs(IPH_ID(ip)) - ntohs(IPH_ID(&cs->cs_ip))); if (deltaS != 1) { ENCODEZ(deltaS); changes |= NEW_I; } - if (th->th_flags & TCP_PSH) { + if (TCPH_FLAGS(th) & TCP_PSH) { changes |= TCP_PUSH_BIT; } /* * Grab the cksum before we overwrite it below. Then update our * state with this packet's header. */ - deltaA = ntohs(th->th_sum); + deltaA = ntohs(th->chksum); BCOPY(ip, &cs->cs_ip, hlen); /* @@ -388,7 +380,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) LWIP_ASSERT("pbuf_header failed\n", 0); } cp = (u_char *)pb->payload; - *cp++ = changes | NEW_C; + *cp++ = (u_char)(changes | NEW_C); *cp++ = cs->cs_id; } else { hlen -= deltaS + 3; @@ -397,10 +389,10 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) LWIP_ASSERT("pbuf_header failed\n", 0); } cp = (u_char *)pb->payload; - *cp++ = changes; + *cp++ = (u_char)changes; } - *cp++ = deltaA >> 8; - *cp++ = deltaA; + *cp++ = (u_char)(deltaA >> 8); + *cp++ = (u_char)deltaA; BCOPY(new_seq, cp, deltaS); INCR(vjs_compressed); return (TYPE_COMPRESSED_TCP); @@ -412,7 +404,7 @@ vj_compress_tcp(struct vjcompress *comp, struct pbuf *pb) */ uncompressed: BCOPY(ip, &cs->cs_ip, hlen); - ip->ip_p = cs->cs_id; + IPH_PROTO_SET(ip, cs->cs_id); comp->last_xmit = cs->cs_id; return (TYPE_UNCOMPRESSED_TCP); } @@ -436,26 +428,26 @@ vj_uncompress_uncomp(struct pbuf *nb, struct vjcompress *comp) { register u_int hlen; register struct cstate *cs; - register struct ip *ip; + register struct ip_hdr *ip; - ip = (struct ip *)nb->payload; - hlen = getip_hl(*ip) << 2; - if (ip->ip_p >= MAX_SLOTS - || hlen + sizeof(struct tcphdr) > nb->len - || (hlen += getth_off(*((struct tcphdr *)&((char *)ip)[hlen])) << 2) + ip = (struct ip_hdr *)nb->payload; + hlen = IPH_HL(ip) << 2; + if (IPH_PROTO(ip) >= MAX_SLOTS + || hlen + sizeof(struct tcp_hdr) > nb->len + || (hlen += TCPH_OFFSET(((struct tcp_hdr *)&((char *)ip)[hlen])) << 2) > nb->len || hlen > MAX_HDR) { - PPPDEBUG((LOG_INFO, "vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", - ip->ip_p, hlen, nb->len)); + PPPDEBUG(LOG_INFO, ("vj_uncompress_uncomp: bad cid=%d, hlen=%d buflen=%d\n", + IPH_PROTO(ip), hlen, nb->len)); comp->flags |= VJF_TOSS; INCR(vjs_errorin); return -1; } - cs = &comp->rstate[comp->last_recv = ip->ip_p]; + cs = &comp->rstate[comp->last_recv = IPH_PROTO(ip)]; comp->flags &=~ VJF_TOSS; - ip->ip_p = IPPROTO_TCP; + IPH_PROTO_SET(ip, IP_PROTO_TCP); BCOPY(ip, &cs->cs_ip, hlen); - cs->cs_hlen = hlen; + cs->cs_hlen = (u_short)hlen; INCR(vjs_uncompressedin); return 0; } @@ -472,7 +464,7 @@ int vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) { u_char *cp; - struct tcphdr *th; + struct tcp_hdr *th; struct cstate *cs; u_short *bp; struct pbuf *n0 = *nb; @@ -488,7 +480,7 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) * If we have a good state index, clear the 'discard' flag. */ if (*cp >= MAX_SLOTS) { - PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: bad cid=%d\n", *cp)); + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: bad cid=%d\n", *cp)); goto bad; } @@ -501,63 +493,63 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) * explicit state index, we have to toss the packet. */ if (comp->flags & VJF_TOSS) { - PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: tossing\n")); + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: tossing\n")); INCR(vjs_tossed); return (-1); } } cs = &comp->rstate[comp->last_recv]; - hlen = getip_hl(cs->cs_ip) << 2; - th = (struct tcphdr *)&((u_char *)&cs->cs_ip)[hlen]; - th->th_sum = htons((*cp << 8) | cp[1]); + hlen = IPH_HL(&cs->cs_ip) << 2; + th = (struct tcp_hdr *)&((u_char *)&cs->cs_ip)[hlen]; + th->chksum = htons((*cp << 8) | cp[1]); cp += 2; if (changes & TCP_PUSH_BIT) { - th->th_flags |= TCP_PSH; + TCPH_SET_FLAG(th, TCP_PSH); } else { - th->th_flags &=~ TCP_PSH; + TCPH_UNSET_FLAG(th, TCP_PSH); } switch (changes & SPECIALS_MASK) { case SPECIAL_I: { - register u32_t i = ntohs(cs->cs_ip.ip_len) - cs->cs_hlen; + register u32_t i = ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; /* some compilers can't nest inline assembler.. */ - tmp = ntohl(th->th_ack) + i; - th->th_ack = htonl(tmp); - tmp = ntohl(th->th_seq) + i; - th->th_seq = htonl(tmp); + tmp = ntohl(th->ackno) + i; + th->ackno = htonl(tmp); + tmp = ntohl(th->seqno) + i; + th->seqno = htonl(tmp); } break; case SPECIAL_D: /* some compilers can't nest inline assembler.. */ - tmp = ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len) - cs->cs_hlen; - th->th_seq = htonl(tmp); + tmp = ntohl(th->seqno) + ntohs(IPH_LEN(&cs->cs_ip)) - cs->cs_hlen; + th->seqno = htonl(tmp); break; default: if (changes & NEW_U) { - th->th_flags |= TCP_URG; - DECODEU(th->th_urp); + TCPH_SET_FLAG(th, TCP_URG); + DECODEU(th->urgp); } else { - th->th_flags &=~ TCP_URG; + TCPH_UNSET_FLAG(th, TCP_URG); } if (changes & NEW_W) { - DECODES(th->th_win); + DECODES(th->wnd); } if (changes & NEW_A) { - DECODEL(th->th_ack); + DECODEL(th->ackno); } if (changes & NEW_S) { - DECODEL(th->th_seq); + DECODEL(th->seqno); } break; } if (changes & NEW_I) { - DECODES(cs->cs_ip.ip_id); + DECODES(cs->cs_ip._id); } else { - cs->cs_ip.ip_id = ntohs(cs->cs_ip.ip_id) + 1; - cs->cs_ip.ip_id = htons(cs->cs_ip.ip_id); + IPH_ID_SET(&cs->cs_ip, ntohs(IPH_ID(&cs->cs_ip)) + 1); + IPH_ID_SET(&cs->cs_ip, htons(IPH_ID(&cs->cs_ip))); } /* @@ -571,27 +563,27 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) * We must have dropped some characters (crc should detect * this but the old slip framing won't) */ - PPPDEBUG((LOG_INFO, "vj_uncompress_tcp: head buffer %d too short %d\n", + PPPDEBUG(LOG_INFO, ("vj_uncompress_tcp: head buffer %d too short %d\n", n0->len, vjlen)); goto bad; } #if BYTE_ORDER == LITTLE_ENDIAN tmp = n0->tot_len - vjlen + cs->cs_hlen; - cs->cs_ip.ip_len = htons(tmp); + IPH_LEN_SET(&cs->cs_ip, htons((u_short)tmp)); #else - cs->cs_ip.ip_len = htons(n0->tot_len - vjlen + cs->cs_hlen); + IPH_LEN_SET(&cs->cs_ip, htons(n0->tot_len - vjlen + cs->cs_hlen)); #endif /* recompute the ip header checksum */ bp = (u_short *) &cs->cs_ip; - cs->cs_ip.ip_sum = 0; + IPH_CHKSUM_SET(&cs->cs_ip, 0); for (tmp = 0; hlen > 0; hlen -= 2) { tmp += *bp++; } tmp = (tmp & 0xffff) + (tmp >> 16); tmp = (tmp & 0xffff) + (tmp >> 16); - cs->cs_ip.ip_sum = (u_short)(~tmp); + IPH_CHKSUM_SET(&cs->cs_ip, (u_short)(~tmp)); /* Remove the compressed header and prepend the uncompressed header. */ if(pbuf_header(n0, -((s16_t)(vjlen)))) { @@ -606,7 +598,7 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) np = pbuf_alloc(PBUF_RAW, n0->len + cs->cs_hlen, PBUF_POOL); if(!np) { - PPPDEBUG((LOG_WARNING, "vj_uncompress_tcp: realign failed\n")); + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: realign failed\n")); goto bad; } @@ -636,7 +628,7 @@ vj_uncompress_tcp(struct pbuf **nb, struct vjcompress *comp) LWIP_ASSERT("vj_uncompress_tcp: cs->cs_hlen <= PBUF_POOL_BUFSIZE", cs->cs_hlen <= PBUF_POOL_BUFSIZE); np = pbuf_alloc(PBUF_RAW, cs->cs_hlen, PBUF_POOL); if(!np) { - PPPDEBUG((LOG_WARNING, "vj_uncompress_tcp: prepend failed\n")); + PPPDEBUG(LOG_WARNING, ("vj_uncompress_tcp: prepend failed\n")); goto bad; } pbuf_cat(np, n0); diff --git a/lib/drivers/lwip/src/netif/ppp/vj.h b/lib/drivers/lwip/src/netif/ppp/vj.h index b9617da4dc8..fad1213646a 100644 --- a/lib/drivers/lwip/src/netif/ppp/vj.h +++ b/lib/drivers/lwip/src/netif/ppp/vj.h @@ -1,7 +1,7 @@ /* * Definitions for tcp compression routines. * - * $Id: vj.h,v 1.5 2007/12/19 20:47:23 fbernon Exp $ + * $Id: vj.h,v 1.7 2010/02/22 17:52:09 goldsimon Exp $ * * Copyright (c) 1989 Regents of the University of California. * All rights reserved. @@ -25,7 +25,8 @@ #ifndef VJ_H #define VJ_H -#include "vjbsdhdr.h" +#include "lwip/ip.h" +#include "lwip/tcp_impl.h" #define MAX_SLOTS 16 /* must be > 2 and < 256 */ #define MAX_HDR 128 @@ -108,7 +109,7 @@ struct cstate { u_char cs_filler; union { char csu_hdr[MAX_HDR]; - struct ip csu_ip; /* ip/tcp hdr from most recent packet */ + struct ip_hdr csu_ip; /* ip/tcp hdr from most recent packet */ } vjcs_u; }; #define cs_ip vjcs_u.csu_ip diff --git a/lib/drivers/lwip/src/netif/slipif.c b/lib/drivers/lwip/src/netif/slipif.c index 089d2d3eb8f..c19333dd704 100644 --- a/lib/drivers/lwip/src/netif/slipif.c +++ b/lib/drivers/lwip/src/netif/slipif.c @@ -88,7 +88,7 @@ struct slipif_priv { * @return always returns ERR_OK since the serial layer does not provide return values */ err_t -slipif_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr) +slipif_output(struct netif *netif, struct pbuf *p, ip_addr_t *ipaddr) { struct slipif_priv *priv; struct pbuf *q;