diff --git a/Ubiquitous/XiZi_AIoT/services/Makefile b/Ubiquitous/XiZi_AIoT/services/Makefile index 2de214d06..dd1f9f0c9 100644 --- a/Ubiquitous/XiZi_AIoT/services/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/Makefile @@ -1,5 +1,5 @@ -SRC_DIR := fs shell lib boards drivers tools app +SRC_DIR := fs shell lib boards drivers tools net app include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/net/libnet/Makefile b/Ubiquitous/XiZi_AIoT/services/net/libnet/Makefile new file mode 100644 index 000000000..31c9a0ea8 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/net/libnet/Makefile @@ -0,0 +1,31 @@ +ifeq ($(BOARD), imx6q-sabrelite) +toolchain ?= arm-none-eabi- +user_ldflags = -N -Ttext 0 +cflags = -std=c11 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie +endif +ifeq ($(BOARD), zynq7000-zc702) +toolchain ?= arm-xilinx-eabi- +user_ldflags = --start-group,-lgcc,-lc,--end-group +cflags = -std=c11 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie +#cflags = -Wall -g -std=c11 +endif +cc = ${toolchain}gcc +ld = ${toolchain}g++ +objdump = ${toolchain}objdump + +c_useropts = -O2 + +INC_DIR = -I$(KERNEL_ROOT)/services/net/libnet \ + -I$(KERNEL_ROOT)/services/lib/ipc \ + -I$(KERNEL_ROOT)/services/lib/memory \ + -I$(KERNEL_ROOT)/services/lib/serial \ + -I$(KERNEL_ROOT)/services/lib/usyscall \ + -I$(KERNEL_ROOT)/services/boards/$(BOARD) \ + -I$(KERNEL_ROOT)/services/app + +net_server: lwip_service.o + @mv $^ ../../app + +%.o: %.c + @echo "cc $^" + @${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^ \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/Makefile b/Ubiquitous/XiZi_AIoT/services/net/net_server/Makefile index 6da598939..f2d5f1e39 100644 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/net/net_server/Makefile @@ -1,14 +1,16 @@ +include $(KERNEL_ROOT)/services/net/net_server/lwip.mk + +net_server: lwip_server.o + @echo "generate $^" + +%.o: %.c + @echo "cc $^" + @${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^ + + + SRC_DIR += api -SRC_DIR += arch SRC_DIR += core SRC_DIR += netif -SRC_DIR += apps -LWIP_DIR += api -LWIP_DIR += arch -LWIP_DIR += core -LWIP_DIR += netif -LWIP_DIR += apps - -SRC_FILES += lwip_server.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/api/Makefile b/Ubiquitous/XiZi_AIoT/services/net/net_server/api/Makefile index c2879b28c..3b9672c08 100644 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/api/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/net/net_server/api/Makefile @@ -1,12 +1,22 @@ -SRC_FILES += api_lib.c \ - api_msg.c \ - err.c \ - if_api.c \ - netbuf.c \ - netdb.c \ - netifapi.c \ - sockets.c \ - tcpip.c + +include $(KERNEL_ROOT)/services/net/net_server/lwip.mk +objs += api_lib.o \ + api_msg.o \ + err.o \ + if_api.o \ + netbuf.o \ + netdb.o \ + netifapi.o \ + sockets.o \ + tcpip.o + + +api: ${objs} + @echo "generate $^" + +%.o: %.c + @echo "cc $^" + @${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^ include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/Makefile b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/Makefile deleted file mode 100644 index 6f5f2913e..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -SRC_FILES += lwiperf/lwiperf.c http/http_client.c - -include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/altcp_tls/altcp_tls_mbedtls.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/altcp_tls/altcp_tls_mbedtls.c deleted file mode 100644 index d642decb5..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/altcp_tls/altcp_tls_mbedtls.c +++ /dev/null @@ -1,1178 +0,0 @@ -/** - * @file - * Application layered TCP/TLS connection API (to be used from TCPIP thread) - * - * This file provides a TLS layer using mbedTLS - */ - -/* - * Copyright (c) 2017 Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - * Watch out: - * - 'sent' is always called with len==0 to the upper layer. This is because keeping - * track of the ratio of application data and TLS overhead would be too much. - * - * Mandatory security-related configuration: - * - define ALTCP_MBEDTLS_RNG_FN to mbedtls_entropy_func to use the standard mbedTLS - * entropy and ensure to add at least one strong entropy source to your mbedtls port - * (implement mbedtls_platform_entropy_poll or mbedtls_hardware_poll providing strong - * entropy) - * - define ALTCP_MBEDTLS_ENTROPY_PTR and ALTCP_MBEDTLS_ENTROPY_LEN to something providing - * GOOD custom entropy - * - * Missing things / @todo: - * - some unhandled/untested things migh be caught by LWIP_ASSERTs... - */ - -#include "lwip/opt.h" - -#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/altcp_tls_mbedtls_opts.h" - -#if LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS - -#include "lwip/altcp.h" -#include "lwip/altcp_tls.h" -#include "lwip/priv/altcp_priv.h" - -#include "altcp_tls_mbedtls_structs.h" -#include "altcp_tls_mbedtls_mem.h" - -/* @todo: which includes are really needed? */ -#include "mbedtls/entropy.h" -#include "mbedtls/ctr_drbg.h" -#include "mbedtls/certs.h" -#include "mbedtls/x509.h" -#include "mbedtls/ssl.h" -#include "mbedtls/net.h" -#include "mbedtls/error.h" -#include "mbedtls/debug.h" -#include "mbedtls/platform.h" -#include "mbedtls/memory_buffer_alloc.h" -#include "mbedtls/ssl_cache.h" - -#include "mbedtls/ssl_internal.h" /* to call mbedtls_flush_output after ERR_MEM */ - -#include - -#ifndef ALTCP_MBEDTLS_ENTROPY_PTR -#define ALTCP_MBEDTLS_ENTROPY_PTR NULL -#endif -#ifndef ALTCP_MBEDTLS_ENTROPY_LEN -#define ALTCP_MBEDTLS_ENTROPY_LEN 0 -#endif - -/* Variable prototype, the actual declaration is at the end of this file - since it contains pointers to static functions declared here */ -extern const struct altcp_functions altcp_mbedtls_functions; - -/** Our global mbedTLS configuration (server-specific, not connection-specific) */ -struct altcp_tls_config { - mbedtls_ssl_config conf; - mbedtls_entropy_context entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_x509_crt *cert; - mbedtls_pk_context *pkey; - mbedtls_x509_crt *ca; -#if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS - /** Inter-connection cache for fast connection startup */ - struct mbedtls_ssl_cache_context cache; -#endif -}; - -static err_t altcp_mbedtls_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err); -static err_t altcp_mbedtls_setup(void *conf, struct altcp_pcb *conn, struct altcp_pcb *inner_conn); -static err_t altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t *state); -static err_t altcp_mbedtls_handle_rx_appldata(struct altcp_pcb *conn, altcp_mbedtls_state_t *state); -static int altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size); - - -/* callback functions from inner/lower connection: */ - -/** Accept callback from lower connection (i.e. TCP) - * Allocate one of our structures, assign it to the new connection's 'state' and - * call the new connection's 'accepted' callback. If that succeeds, we wait - * to receive connection setup handshake bytes from the client. - */ -static err_t -altcp_mbedtls_lower_accept(void *arg, struct altcp_pcb *accepted_conn, err_t err) -{ - struct altcp_pcb *listen_conn = (struct altcp_pcb *)arg; - if (listen_conn && listen_conn->state && listen_conn->accept) { - err_t setup_err; - altcp_mbedtls_state_t *listen_state = (altcp_mbedtls_state_t *)listen_conn->state; - /* create a new altcp_conn to pass to the next 'accept' callback */ - struct altcp_pcb *new_conn = altcp_alloc(); - if (new_conn == NULL) { - return ERR_MEM; - } - setup_err = altcp_mbedtls_setup(listen_state->conf, new_conn, accepted_conn); - if (setup_err != ERR_OK) { - altcp_free(new_conn); - return setup_err; - } - return listen_conn->accept(listen_conn->arg, new_conn, err); - } - return ERR_ARG; -} - -/** Connected callback from lower connection (i.e. TCP). - * Not really implemented/tested yet... - */ -static err_t -altcp_mbedtls_lower_connected(void *arg, struct altcp_pcb *inner_conn, err_t err) -{ - struct altcp_pcb *conn = (struct altcp_pcb *)arg; - LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */ - if (conn && conn->state) { - LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn); - /* upper connected is called when handshake is done */ - if (err != ERR_OK) { - if (conn->connected) { - return conn->connected(conn->arg, conn, err); - } - } - return altcp_mbedtls_lower_recv_process(conn, (altcp_mbedtls_state_t *)conn->state); - } - return ERR_VAL; -} - -/* Call recved for possibly more than an u16_t */ -static void -altcp_mbedtls_lower_recved(struct altcp_pcb *inner_conn, int recvd_cnt) -{ - while (recvd_cnt > 0) { - u16_t recvd_part = (u16_t)LWIP_MIN(recvd_cnt, 0xFFFF); - altcp_recved(inner_conn, recvd_part); - recvd_cnt -= recvd_part; - } -} - -/** Recv callback from lower connection (i.e. TCP) - * This one mainly differs between connection setup/handshake (data is fed into mbedTLS only) - * and application phase (data is decoded by mbedTLS and passed on to the application). - */ -static err_t -altcp_mbedtls_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err) -{ - altcp_mbedtls_state_t *state; - struct altcp_pcb *conn = (struct altcp_pcb *)arg; - - LWIP_ASSERT("no err expected", err == ERR_OK); - LWIP_UNUSED_ARG(err); - - if (!conn) { - /* no connection given as arg? should not happen, but prevent pbuf/conn leaks */ - if (p != NULL) { - pbuf_free(p); - } - altcp_close(inner_conn); - return ERR_CLSD; - } - state = (altcp_mbedtls_state_t *)conn->state; - LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn); - if (!state) { - /* already closed */ - if (p != NULL) { - pbuf_free(p); - } - altcp_close(inner_conn); - return ERR_CLSD; - } - - /* handle NULL pbuf (inner connection closed) */ - if (p == NULL) { - /* remote host sent FIN, remember this (SSL state is destroyed - when both sides are closed only!) */ - if ((state->flags & (ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE | ALTCP_MBEDTLS_FLAGS_UPPER_CALLED)) == - (ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE | ALTCP_MBEDTLS_FLAGS_UPPER_CALLED)) { - /* need to notify upper layer (e.g. 'accept' called or 'connect' succeeded) */ - if ((state->rx != NULL) || (state->rx_app != NULL)) { - state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED; - /* this is a normal close (FIN) but we have unprocessed data, so delay the FIN */ - altcp_mbedtls_handle_rx_appldata(conn, state); - return ERR_OK; - } - state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSED; - if (conn->recv) { - return conn->recv(conn->arg, conn, NULL, ERR_OK); - } - } else { - /* before connection setup is done: call 'err' */ - if (conn->err) { - conn->err(conn->arg, ERR_CLSD); - } - altcp_close(conn); - } - return ERR_OK; - } - - /* If we come here, the connection is in good state (handshake phase or application data phase). - Queue up the pbuf for processing as handshake data or application data. */ - if (state->rx == NULL) { - state->rx = p; - } else { - LWIP_ASSERT("rx pbuf overflow", (int)p->tot_len + (int)p->len <= 0xFFFF); - pbuf_cat(state->rx, p); - } - return altcp_mbedtls_lower_recv_process(conn, state); -} - -static err_t -altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t *state) -{ - if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) { - /* handle connection setup (handshake not done) */ - int ret = mbedtls_ssl_handshake(&state->ssl_context); - /* try to send data... */ - altcp_output(conn->inner_conn); - if (state->bio_bytes_read) { - /* acknowledge all bytes read */ - altcp_mbedtls_lower_recved(conn->inner_conn, state->bio_bytes_read); - state->bio_bytes_read = 0; - } - - if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { - /* handshake not done, wait for more recv calls */ - LWIP_ASSERT("in this state, the rx chain should be empty", state->rx == NULL); - return ERR_OK; - } - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_handshake failed: %d\n", ret)); - /* handshake failed, connection has to be closed */ - if (conn->err) { - conn->err(conn->arg, ERR_CLSD); - } - - if (altcp_close(conn) != ERR_OK) { - altcp_abort(conn); - } - return ERR_OK; - } - /* If we come here, handshake succeeded. */ - LWIP_ASSERT("state", state->bio_bytes_read == 0); - LWIP_ASSERT("state", state->bio_bytes_appl == 0); - state->flags |= ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE; - /* issue "connect" callback" to upper connection (this can only happen for active open) */ - if (conn->connected) { - err_t err; - err = conn->connected(conn->arg, conn, ERR_OK); - if (err != ERR_OK) { - return err; - } - } - if (state->rx == NULL) { - return ERR_OK; - } - } - /* handle application data */ - return altcp_mbedtls_handle_rx_appldata(conn, state); -} - -/* Pass queued decoded rx data to application */ -static err_t -altcp_mbedtls_pass_rx_data(struct altcp_pcb *conn, altcp_mbedtls_state_t *state) -{ - err_t err; - struct pbuf *buf; - LWIP_ASSERT("conn != NULL", conn != NULL); - LWIP_ASSERT("state != NULL", state != NULL); - buf = state->rx_app; - if (buf) { - state->rx_app = NULL; - if (conn->recv) { - u16_t tot_len = buf->tot_len; - /* this needs to be increased first because the 'recved' call may come nested */ - state->rx_passed_unrecved += tot_len; - state->flags |= ALTCP_MBEDTLS_FLAGS_UPPER_CALLED; - err = conn->recv(conn->arg, conn, buf, ERR_OK); - if (err != ERR_OK) { - if (err == ERR_ABRT) { - return ERR_ABRT; - } - /* not received, leave the pbuf(s) queued (and decrease 'unrecved' again) */ - LWIP_ASSERT("state == conn->state", state == conn->state); - state->rx_app = buf; - state->rx_passed_unrecved -= tot_len; - LWIP_ASSERT("state->rx_passed_unrecved >= 0", state->rx_passed_unrecved >= 0); - if (state->rx_passed_unrecved < 0) { - state->rx_passed_unrecved = 0; - } - return err; - } - } else { - pbuf_free(buf); - } - } else if ((state->flags & (ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED | ALTCP_MBEDTLS_FLAGS_RX_CLOSED)) == - ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED) { - state->flags |= ALTCP_MBEDTLS_FLAGS_RX_CLOSED; - if (conn->recv) { - return conn->recv(conn->arg, conn, NULL, ERR_OK); - } - } - - /* application may have close the connection */ - if (conn->state != state) { - /* return error code to ensure altcp_mbedtls_handle_rx_appldata() exits the loop */ - return ERR_CLSD; - } - return ERR_OK; -} - -/* Helper function that processes rx application data stored in rx pbuf chain */ -static err_t -altcp_mbedtls_handle_rx_appldata(struct altcp_pcb *conn, altcp_mbedtls_state_t *state) -{ - int ret; - LWIP_ASSERT("state != NULL", state != NULL); - if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) { - /* handshake not done yet */ - return ERR_VAL; - } - do { - /* allocate a full-sized unchained PBUF_POOL: this is for RX! */ - struct pbuf *buf = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL); - if (buf == NULL) { - /* We're short on pbufs, try again later from 'poll' or 'recv' callbacks. - @todo: close on excessive allocation failures or leave this up to upper conn? */ - return ERR_OK; - } - - /* decrypt application data, this pulls encrypted RX data off state->rx pbuf chain */ - ret = mbedtls_ssl_read(&state->ssl_context, (unsigned char *)buf->payload, PBUF_POOL_BUFSIZE); - if (ret < 0) { - if (ret == MBEDTLS_ERR_SSL_CLIENT_RECONNECT) { - /* client is initiating a new connection using the same source port -> close connection or make handshake */ - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("new connection on same source port\n")); - LWIP_ASSERT("TODO: new connection on same source port, close this connection", 0); - } else if ((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE)) { - if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("connection was closed gracefully\n")); - } else if (ret == MBEDTLS_ERR_NET_CONN_RESET) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("connection was reset by peer\n")); - } - pbuf_free(buf); - return ERR_OK; - } else { - pbuf_free(buf); - return ERR_OK; - } - pbuf_free(buf); - altcp_abort(conn); - return ERR_ABRT; - } else { - err_t err; - if (ret) { - LWIP_ASSERT("bogus receive length", ret <= PBUF_POOL_BUFSIZE); - /* trim pool pbuf to actually decoded length */ - pbuf_realloc(buf, (u16_t)ret); - - state->bio_bytes_appl += ret; - if (mbedtls_ssl_get_bytes_avail(&state->ssl_context) == 0) { - /* Record is done, now we know the share between application and protocol bytes - and can adjust the RX window by the protocol bytes. - The rest is 'recved' by the application calling our 'recved' fn. */ - int overhead_bytes; - LWIP_ASSERT("bogus byte counts", state->bio_bytes_read > state->bio_bytes_appl); - overhead_bytes = state->bio_bytes_read - state->bio_bytes_appl; - altcp_mbedtls_lower_recved(conn->inner_conn, overhead_bytes); - state->bio_bytes_read = 0; - state->bio_bytes_appl = 0; - } - - if (state->rx_app == NULL) { - state->rx_app = buf; - } else { - pbuf_cat(state->rx_app, buf); - } - } else { - pbuf_free(buf); - buf = NULL; - } - err = altcp_mbedtls_pass_rx_data(conn, state); - if (err != ERR_OK) { - if (err == ERR_ABRT) { - /* recv callback needs to return this as the pcb is deallocated */ - return ERR_ABRT; - } - /* we hide all other errors as we retry feeding the pbuf to the app later */ - return ERR_OK; - } - } - } while (ret > 0); - return ERR_OK; -} - -/** Receive callback function called from mbedtls (set via mbedtls_ssl_set_bio) - * This function mainly copies data from pbufs and frees the pbufs after copying. - */ -static int -altcp_mbedtls_bio_recv(void *ctx, unsigned char *buf, size_t len) -{ - struct altcp_pcb *conn = (struct altcp_pcb *)ctx; - altcp_mbedtls_state_t *state; - struct pbuf *p; - u16_t ret; - u16_t copy_len; - err_t err; - - LWIP_UNUSED_ARG(err); /* for LWIP_NOASSERT */ - if ((conn == NULL) || (conn->state == NULL)) { - return MBEDTLS_ERR_NET_INVALID_CONTEXT; - } - state = (altcp_mbedtls_state_t *)conn->state; - p = state->rx; - - /* @todo: return MBEDTLS_ERR_NET_CONN_RESET/MBEDTLS_ERR_NET_RECV_FAILED? */ - - if ((p == NULL) || ((p->len == 0) && (p->next == NULL))) { - if (p) { - pbuf_free(p); - } - state->rx = NULL; - if ((state->flags & (ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED | ALTCP_MBEDTLS_FLAGS_RX_CLOSED)) == - ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED) { - /* close queued but not passed up yet */ - return 0; - } - return MBEDTLS_ERR_SSL_WANT_READ; - } - /* limit number of bytes again to copy from first pbuf in a chain only */ - copy_len = (u16_t)LWIP_MIN(len, p->len); - /* copy the data */ - ret = pbuf_copy_partial(p, buf, copy_len, 0); - LWIP_ASSERT("ret == copy_len", ret == copy_len); - /* hide the copied bytes from the pbuf */ - err = pbuf_remove_header(p, ret); - LWIP_ASSERT("error", err == ERR_OK); - if (p->len == 0) { - /* the first pbuf has been fully read, free it */ - state->rx = p->next; - p->next = NULL; - pbuf_free(p); - } - - state->bio_bytes_read += (int)ret; - return ret; -} - -/** Sent callback from lower connection (i.e. TCP) - * This only informs the upper layer to try to send more, not about - * the number of ACKed bytes. - */ -static err_t -altcp_mbedtls_lower_sent(void *arg, struct altcp_pcb *inner_conn, u16_t len) -{ - struct altcp_pcb *conn = (struct altcp_pcb *)arg; - LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */ - LWIP_UNUSED_ARG(len); - if (conn) { - altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state; - LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn); - if (!state || !(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) { - /* @todo: do something here? */ - return ERR_OK; - } - /* try to send more if we failed before */ - mbedtls_ssl_flush_output(&state->ssl_context); - /* call upper sent with len==0 if the application already sent data */ - if ((state->flags & ALTCP_MBEDTLS_FLAGS_APPLDATA_SENT) && conn->sent) { - return conn->sent(conn->arg, conn, 0); - } - } - return ERR_OK; -} - -/** Poll callback from lower connection (i.e. TCP) - * Just pass this on to the application. - * @todo: retry sending? - */ -static err_t -altcp_mbedtls_lower_poll(void *arg, struct altcp_pcb *inner_conn) -{ - struct altcp_pcb *conn = (struct altcp_pcb *)arg; - LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */ - if (conn) { - LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn); - /* check if there's unreceived rx data */ - if (conn->state) { - altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state; - /* try to send more if we failed before */ - mbedtls_ssl_flush_output(&state->ssl_context); - if (altcp_mbedtls_handle_rx_appldata(conn, state) == ERR_ABRT) { - return ERR_ABRT; - } - } - if (conn->poll) { - return conn->poll(conn->arg, conn); - } - } - return ERR_OK; -} - -static void -altcp_mbedtls_lower_err(void *arg, err_t err) -{ - struct altcp_pcb *conn = (struct altcp_pcb *)arg; - if (conn) { - conn->inner_conn = NULL; /* already freed */ - if (conn->err) { - conn->err(conn->arg, err); - } - altcp_free(conn); - } -} - -/* setup functions */ - -static void -altcp_mbedtls_remove_callbacks(struct altcp_pcb *inner_conn) -{ - altcp_arg(inner_conn, NULL); - altcp_recv(inner_conn, NULL); - altcp_sent(inner_conn, NULL); - altcp_err(inner_conn, NULL); - altcp_poll(inner_conn, NULL, inner_conn->pollinterval); -} - -static void -altcp_mbedtls_setup_callbacks(struct altcp_pcb *conn, struct altcp_pcb *inner_conn) -{ - altcp_arg(inner_conn, conn); - altcp_recv(inner_conn, altcp_mbedtls_lower_recv); - altcp_sent(inner_conn, altcp_mbedtls_lower_sent); - altcp_err(inner_conn, altcp_mbedtls_lower_err); - /* tcp_poll is set when interval is set by application */ - /* listen is set totally different :-) */ -} - -static err_t -altcp_mbedtls_setup(void *conf, struct altcp_pcb *conn, struct altcp_pcb *inner_conn) -{ - int ret; - struct altcp_tls_config *config = (struct altcp_tls_config *)conf; - altcp_mbedtls_state_t *state; - if (!conf) { - return ERR_ARG; - } - LWIP_ASSERT("invalid inner_conn", conn != inner_conn); - - /* allocate mbedtls context */ - state = altcp_mbedtls_alloc(conf); - if (state == NULL) { - return ERR_MEM; - } - /* initialize mbedtls context: */ - mbedtls_ssl_init(&state->ssl_context); - ret = mbedtls_ssl_setup(&state->ssl_context, &config->conf); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_setup failed\n")); - /* @todo: convert 'ret' to err_t */ - altcp_mbedtls_free(conf, state); - return ERR_MEM; - } - /* tell mbedtls about our I/O functions */ - mbedtls_ssl_set_bio(&state->ssl_context, conn, altcp_mbedtls_bio_send, altcp_mbedtls_bio_recv, NULL); - - altcp_mbedtls_setup_callbacks(conn, inner_conn); - conn->inner_conn = inner_conn; - conn->fns = &altcp_mbedtls_functions; - conn->state = state; - return ERR_OK; -} - -struct altcp_pcb * -altcp_tls_wrap(struct altcp_tls_config *config, struct altcp_pcb *inner_pcb) -{ - struct altcp_pcb *ret; - if (inner_pcb == NULL) { - return NULL; - } - ret = altcp_alloc(); - if (ret != NULL) { - if (altcp_mbedtls_setup(config, ret, inner_pcb) != ERR_OK) { - altcp_free(ret); - return NULL; - } - } - return ret; -} - -void * -altcp_tls_context(struct altcp_pcb *conn) -{ - if (conn && conn->state) { - altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state; - return &state->ssl_context; - } - return NULL; -} - -#if ALTCP_MBEDTLS_DEBUG != LWIP_DBG_OFF -static void -altcp_mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) -{ - LWIP_UNUSED_ARG(ctx); - LWIP_UNUSED_ARG(level); - LWIP_UNUSED_ARG(file); - LWIP_UNUSED_ARG(line); - LWIP_UNUSED_ARG(str); - - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("%s:%04d: %s", file, line, str)); -} -#endif - -#ifndef ALTCP_MBEDTLS_RNG_FN -/** ATTENTION: It is *really* important to *NOT* use this dummy RNG in production code!!!! */ -static int -dummy_rng(void *ctx, unsigned char *buffer, size_t len) -{ - static size_t ctr; - size_t i; - LWIP_UNUSED_ARG(ctx); - for (i = 0; i < len; i++) { - buffer[i] = (unsigned char)++ctr; - } - return 0; -} -#define ALTCP_MBEDTLS_RNG_FN dummy_rng -#endif /* ALTCP_MBEDTLS_RNG_FN */ - -/** Create new TLS configuration - * ATTENTION: Server certificate and private key have to be added outside this function! - */ -static struct altcp_tls_config * -altcp_tls_create_config(int is_server, int have_cert, int have_pkey, int have_ca) -{ - size_t sz; - int ret; - struct altcp_tls_config *conf; - mbedtls_x509_crt *mem; - - if (TCP_WND < MBEDTLS_SSL_MAX_CONTENT_LEN) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG|LWIP_DBG_LEVEL_SERIOUS, - ("altcp_tls: TCP_WND is smaller than the RX decryption buffer, connection RX might stall!\n")); - } - - altcp_mbedtls_mem_init(); - - sz = sizeof(struct altcp_tls_config); - if (have_cert) { - sz += sizeof(mbedtls_x509_crt); - } - if (have_ca) { - sz += sizeof(mbedtls_x509_crt); - } - if (have_pkey) { - sz += sizeof(mbedtls_pk_context); - } - - conf = (struct altcp_tls_config *)altcp_mbedtls_alloc_config(sz); - if (conf == NULL) { - return NULL; - } - mem = (mbedtls_x509_crt *)(conf + 1); - if (have_cert) { - conf->cert = mem; - mem++; - } - if (have_ca) { - conf->ca = mem; - mem++; - } - if (have_pkey) { - conf->pkey = (mbedtls_pk_context *)mem; - } - - mbedtls_ssl_config_init(&conf->conf); - mbedtls_entropy_init(&conf->entropy); - mbedtls_ctr_drbg_init(&conf->ctr_drbg); - - /* Seed the RNG */ - ret = mbedtls_ctr_drbg_seed(&conf->ctr_drbg, ALTCP_MBEDTLS_RNG_FN, &conf->entropy, ALTCP_MBEDTLS_ENTROPY_PTR, ALTCP_MBEDTLS_ENTROPY_LEN); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ctr_drbg_seed failed: %d\n", ret)); - altcp_mbedtls_free_config(conf); - return NULL; - } - - /* Setup ssl context (@todo: what's different for a client here? -> might better be done on listen/connect) */ - ret = mbedtls_ssl_config_defaults(&conf->conf, is_server ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, - MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_config_defaults failed: %d\n", ret)); - altcp_mbedtls_free_config(conf); - return NULL; - } - mbedtls_ssl_conf_authmode(&conf->conf, MBEDTLS_SSL_VERIFY_OPTIONAL); - - mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &conf->ctr_drbg); -#if ALTCP_MBEDTLS_DEBUG != LWIP_DBG_OFF - mbedtls_ssl_conf_dbg(&conf->conf, altcp_mbedtls_debug, stdout); -#endif -#if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS - mbedtls_ssl_conf_session_cache(&conf->conf, &conf->cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set); - mbedtls_ssl_cache_set_timeout(&conf->cache, 30); - mbedtls_ssl_cache_set_max_entries(&conf->cache, 30); -#endif - - return conf; -} - -/** Create new TLS configuration - * This is a suboptimal version that gets the encrypted private key and its password, - * as well as the server certificate. - */ -struct altcp_tls_config * -altcp_tls_create_config_server_privkey_cert(const u8_t *privkey, size_t privkey_len, - const u8_t *privkey_pass, size_t privkey_pass_len, - const u8_t *cert, size_t cert_len) -{ - int ret; - mbedtls_x509_crt *srvcert; - mbedtls_pk_context *pkey; - struct altcp_tls_config *conf = altcp_tls_create_config(1, 1, 1, 0); - if (conf == NULL) { - return NULL; - } - - srvcert = conf->cert; - mbedtls_x509_crt_init(srvcert); - - pkey = conf->pkey; - mbedtls_pk_init(pkey); - - /* Load the certificates and private key */ - ret = mbedtls_x509_crt_parse(srvcert, cert, cert_len); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse failed: %d\n", ret)); - altcp_mbedtls_free_config(conf); - return NULL; - } - - ret = mbedtls_pk_parse_key(pkey, (const unsigned char *) privkey, privkey_len, privkey_pass, privkey_pass_len); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_public_key failed: %d\n", ret)); - mbedtls_x509_crt_free(srvcert); - altcp_mbedtls_free_config(conf); - return NULL; - } - - mbedtls_ssl_conf_ca_chain(&conf->conf, srvcert->next, NULL); - ret = mbedtls_ssl_conf_own_cert(&conf->conf, srvcert, pkey); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_conf_own_cert failed: %d\n", ret)); - mbedtls_x509_crt_free(srvcert); - mbedtls_pk_free(pkey); - altcp_mbedtls_free_config(conf); - return NULL; - } - return conf; -} - -static struct altcp_tls_config * -altcp_tls_create_config_client_common(const u8_t *ca, size_t ca_len, int is_2wayauth) -{ - int ret; - struct altcp_tls_config *conf = altcp_tls_create_config(0, is_2wayauth, is_2wayauth, ca != NULL); - if (conf == NULL) { - return NULL; - } - - /* Initialize the CA certificate if provided - * CA certificate is optional (to save memory) but recommended for production environment - * Without CA certificate, connection will be prone to man-in-the-middle attacks */ - if (ca) { - mbedtls_x509_crt_init(conf->ca); - ret = mbedtls_x509_crt_parse(conf->ca, ca, ca_len); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse ca failed: %d 0x%x", ret, -1*ret)); - altcp_mbedtls_free_config(conf); - return NULL; - } - - mbedtls_ssl_conf_ca_chain(&conf->conf, conf->ca, NULL); - } - return conf; -} - -struct altcp_tls_config * -altcp_tls_create_config_client(const u8_t *ca, size_t ca_len) -{ - return altcp_tls_create_config_client_common(ca, ca_len, 0); -} - -struct altcp_tls_config * -altcp_tls_create_config_client_2wayauth(const u8_t *ca, size_t ca_len, const u8_t *privkey, size_t privkey_len, - const u8_t *privkey_pass, size_t privkey_pass_len, - const u8_t *cert, size_t cert_len) -{ - int ret; - struct altcp_tls_config *conf; - - if (!cert || !privkey) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("altcp_tls_create_config_client_2wayauth: certificate and priv key required")); - return NULL; - } - - conf = altcp_tls_create_config_client_common(ca, ca_len, 1); - if (conf == NULL) { - return NULL; - } - - /* Initialize the client certificate and corresponding private key */ - mbedtls_x509_crt_init(conf->cert); - ret = mbedtls_x509_crt_parse(conf->cert, cert, cert_len); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_x509_crt_parse cert failed: %d 0x%x", ret, -1*ret)); - altcp_mbedtls_free_config(conf->cert); - return NULL; - } - - mbedtls_pk_init(conf->pkey); - ret = mbedtls_pk_parse_key(conf->pkey, privkey, privkey_len, privkey_pass, privkey_pass_len); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_pk_parse_key failed: %d 0x%x", ret, -1*ret)); - altcp_mbedtls_free_config(conf); - return NULL; - } - - ret = mbedtls_ssl_conf_own_cert(&conf->conf, conf->cert, conf->pkey); - if (ret != 0) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_conf_own_cert failed: %d 0x%x", ret, -1*ret)); - altcp_mbedtls_free_config(conf); - return NULL; - } - - return conf; -} - -void -altcp_tls_free_config(struct altcp_tls_config *conf) -{ - if (conf->pkey) { - mbedtls_pk_free(conf->pkey); - } - if (conf->cert) { - mbedtls_x509_crt_free(conf->cert); - } - if (conf->ca) { - mbedtls_x509_crt_free(conf->ca); - } - altcp_mbedtls_free_config(conf); -} - -/* "virtual" functions */ -static void -altcp_mbedtls_set_poll(struct altcp_pcb *conn, u8_t interval) -{ - if (conn != NULL) { - altcp_poll(conn->inner_conn, altcp_mbedtls_lower_poll, interval); - } -} - -static void -altcp_mbedtls_recved(struct altcp_pcb *conn, u16_t len) -{ - u16_t lower_recved; - altcp_mbedtls_state_t *state; - if (conn == NULL) { - return; - } - state = (altcp_mbedtls_state_t *)conn->state; - if (state == NULL) { - return; - } - if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) { - return; - } - lower_recved = len; - if (lower_recved > state->rx_passed_unrecved) { - LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("bogus recved count (len > state->rx_passed_unrecved / %d / %d)", - len, state->rx_passed_unrecved)); - lower_recved = (u16_t)state->rx_passed_unrecved; - } - state->rx_passed_unrecved -= lower_recved; - - altcp_recved(conn->inner_conn, lower_recved); -} - -static err_t -altcp_mbedtls_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected) -{ - if (conn == NULL) { - return ERR_VAL; - } - conn->connected = connected; - return altcp_connect(conn->inner_conn, ipaddr, port, altcp_mbedtls_lower_connected); -} - -static struct altcp_pcb * -altcp_mbedtls_listen(struct altcp_pcb *conn, u8_t backlog, err_t *err) -{ - struct altcp_pcb *lpcb; - if (conn == NULL) { - return NULL; - } - lpcb = altcp_listen_with_backlog_and_err(conn->inner_conn, backlog, err); - if (lpcb != NULL) { - conn->inner_conn = lpcb; - altcp_accept(lpcb, altcp_mbedtls_lower_accept); - return conn; - } - return NULL; -} - -static void -altcp_mbedtls_abort(struct altcp_pcb *conn) -{ - if (conn != NULL) { - altcp_abort(conn->inner_conn); - } -} - -static err_t -altcp_mbedtls_close(struct altcp_pcb *conn) -{ - struct altcp_pcb *inner_conn; - if (conn == NULL) { - return ERR_VAL; - } - inner_conn = conn->inner_conn; - if (inner_conn) { - err_t err; - altcp_poll_fn oldpoll = inner_conn->poll; - altcp_mbedtls_remove_callbacks(conn->inner_conn); - err = altcp_close(conn->inner_conn); - if (err != ERR_OK) { - /* not closed, set up all callbacks again */ - altcp_mbedtls_setup_callbacks(conn, inner_conn); - /* poll callback is not included in the above */ - altcp_poll(inner_conn, oldpoll, inner_conn->pollinterval); - return err; - } - conn->inner_conn = NULL; - } - altcp_free(conn); - return ERR_OK; -} - -/** Allow caller of altcp_write() to limit to negotiated chunk size - * or remaining sndbuf space of inner_conn. - */ -static u16_t -altcp_mbedtls_sndbuf(struct altcp_pcb *conn) -{ - if (conn) { - altcp_mbedtls_state_t *state; - state = (altcp_mbedtls_state_t*)conn->state; - if (!state || !(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) { - return 0; - } - if (conn->inner_conn) { - u16_t sndbuf = altcp_sndbuf(conn->inner_conn); - /* Take care of record header, IV, AuthTag */ - int ssl_expan = mbedtls_ssl_get_record_expansion(&state->ssl_context); - if (ssl_expan > 0) { - size_t ssl_added = (u16_t)LWIP_MIN(ssl_expan, 0xFFFF); - /* internal sndbuf smaller than our offset */ - if (ssl_added < sndbuf) { - size_t max_len = 0xFFFF; - size_t ret; -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - /* @todo: adjust ssl_added to real value related to negociated cipher */ - size_t max_frag_len = mbedtls_ssl_get_max_frag_len(&state->ssl_context); - max_len = LWIP_MIN(max_frag_len, max_len); -#endif - /* Adjust sndbuf of inner_conn with what added by SSL */ - ret = LWIP_MIN(sndbuf - ssl_added, max_len); - LWIP_ASSERT("sndbuf overflow", ret <= 0xFFFF); - return (u16_t)ret; - } - } - } - } - /* fallback: use sendbuf of the inner connection */ - return altcp_default_sndbuf(conn); -} - -/** Write data to a TLS connection. Calls into mbedTLS, which in turn calls into - * @ref altcp_mbedtls_bio_send() to send the encrypted data - */ -static err_t -altcp_mbedtls_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags) -{ - int ret; - altcp_mbedtls_state_t *state; - - LWIP_UNUSED_ARG(apiflags); - - if (conn == NULL) { - return ERR_VAL; - } - - state = (altcp_mbedtls_state_t *)conn->state; - if (state == NULL) { - /* @todo: which error? */ - return ERR_CLSD; - } - if (!(state->flags & ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE)) { - /* @todo: which error? */ - return ERR_VAL; - } - - /* HACK: if thre is something left to send, try to flush it and only - allow sending more if this succeeded (this is a hack because neither - returning 0 nor MBEDTLS_ERR_SSL_WANT_WRITE worked for me) */ - if (state->ssl_context.out_left) { - mbedtls_ssl_flush_output(&state->ssl_context); - if (state->ssl_context.out_left) { - return ERR_MEM; - } - } - ret = mbedtls_ssl_write(&state->ssl_context, (const unsigned char *)dataptr, len); - /* try to send data... */ - altcp_output(conn->inner_conn); - if (ret >= 0) { - if (ret == len) { - state->flags |= ALTCP_MBEDTLS_FLAGS_APPLDATA_SENT; - return ERR_OK; - } else { - /* @todo/@fixme: assumption: either everything sent or error */ - LWIP_ASSERT("ret <= 0", 0); - return ERR_MEM; - } - } else { - if (ret == MBEDTLS_ERR_SSL_WANT_WRITE) { - /* @todo: convert error to err_t */ - return ERR_MEM; - } - LWIP_ASSERT("unhandled error", 0); - return ERR_VAL; - } -} - -/** Send callback function called from mbedtls (set via mbedtls_ssl_set_bio) - * This function is either called during handshake or when sending application - * data via @ref altcp_mbedtls_write (or altcp_write) - */ -static int -altcp_mbedtls_bio_send(void *ctx, const unsigned char *dataptr, size_t size) -{ - struct altcp_pcb *conn = (struct altcp_pcb *) ctx; - int written = 0; - size_t size_left = size; - u8_t apiflags = TCP_WRITE_FLAG_COPY; - - LWIP_ASSERT("conn != NULL", conn != NULL); - if ((conn == NULL) || (conn->inner_conn == NULL)) { - return MBEDTLS_ERR_NET_INVALID_CONTEXT; - } - - while (size_left) { - u16_t write_len = (u16_t)LWIP_MIN(size_left, 0xFFFF); - err_t err = altcp_write(conn->inner_conn, (const void *)dataptr, write_len, apiflags); - if (err == ERR_OK) { - written += write_len; - size_left -= write_len; - } else if (err == ERR_MEM) { - if (written) { - return written; - } - return 0; /* MBEDTLS_ERR_SSL_WANT_WRITE; */ - } else { - LWIP_ASSERT("tls_write, tcp_write: err != ERR MEM", 0); - /* @todo: return MBEDTLS_ERR_NET_CONN_RESET or MBEDTLS_ERR_NET_SEND_FAILED */ - return MBEDTLS_ERR_NET_SEND_FAILED; - } - } - return written; -} - -static u16_t -altcp_mbedtls_mss(struct altcp_pcb *conn) -{ - if (conn == NULL) { - return 0; - } - /* @todo: LWIP_MIN(mss, mbedtls_ssl_get_max_frag_len()) ? */ - return altcp_mss(conn->inner_conn); -} - -static void -altcp_mbedtls_dealloc(struct altcp_pcb *conn) -{ - /* clean up and free tls state */ - if (conn) { - altcp_mbedtls_state_t *state = (altcp_mbedtls_state_t *)conn->state; - if (state) { - mbedtls_ssl_free(&state->ssl_context); - state->flags = 0; - if (state->rx) { - /* free leftover (unhandled) rx pbufs */ - pbuf_free(state->rx); - state->rx = NULL; - } - altcp_mbedtls_free(state->conf, state); - conn->state = NULL; - } - } -} - -const struct altcp_functions altcp_mbedtls_functions = { - altcp_mbedtls_set_poll, - altcp_mbedtls_recved, - altcp_default_bind, - altcp_mbedtls_connect, - altcp_mbedtls_listen, - altcp_mbedtls_abort, - altcp_mbedtls_close, - altcp_default_shutdown, - altcp_mbedtls_write, - altcp_default_output, - altcp_mbedtls_mss, - altcp_mbedtls_sndbuf, - altcp_default_sndqueuelen, - altcp_default_nagle_disable, - altcp_default_nagle_enable, - altcp_default_nagle_disabled, - altcp_default_setprio, - altcp_mbedtls_dealloc, - altcp_default_get_tcp_addrinfo, - altcp_default_get_ip, - altcp_default_get_port -#ifdef LWIP_DEBUG - , altcp_default_dbg_get_tcp_state -#endif -}; - -#endif /* LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS */ -#endif /* LWIP_ALTCP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/altcp_tls/altcp_tls_mbedtls_mem.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/altcp_tls/altcp_tls_mbedtls_mem.c deleted file mode 100644 index 04d47ae51..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/altcp_tls/altcp_tls_mbedtls_mem.c +++ /dev/null @@ -1,210 +0,0 @@ -/** - * @file - * Application layered TCP connection API (to be used from TCPIP thread) - * - * This file contains memory management functions for a TLS layer using mbedTLS. - * - * ATTENTION: For production usage, you might want to override this file with - * your own implementation since this implementation simply uses the - * lwIP heap without caring for fragmentation or leaving heap for - * other parts of lwIP! - */ - -/* - * Copyright (c) 2017 Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - * Missing things / @todo: - * - RX data is acknowledged after receiving (tcp_recved is called when enqueueing - * the pbuf for mbedTLS receive, not when processed by mbedTLS or the inner - * connection; altcp_recved() from inner connection does nothing) - * - TX data is marked as 'sent' (i.e. acknowledged; sent callback is called) right - * after enqueueing for transmission, not when actually ACKed be the remote host. - */ - -#include "lwip/opt.h" - -#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/altcp_tls_mbedtls_opts.h" - -#if LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS - -#include "altcp_tls_mbedtls_mem.h" -#include "altcp_tls_mbedtls_structs.h" -#include "lwip/mem.h" - -#include "mbedtls/platform.h" - -#include - -#ifndef ALTCP_MBEDTLS_MEM_DEBUG -#define ALTCP_MBEDTLS_MEM_DEBUG LWIP_DBG_OFF -#endif - -#if defined(MBEDTLS_PLATFORM_MEMORY) && \ - (!defined(MBEDTLS_PLATFORM_FREE_MACRO) || \ - defined(MBEDTLS_PLATFORM_CALLOC_MACRO)) -#define ALTCP_MBEDTLS_PLATFORM_ALLOC 1 -#else -#define ALTCP_MBEDTLS_PLATFORM_ALLOC 0 -#endif - -#if ALTCP_MBEDTLS_PLATFORM_ALLOC - -#ifndef ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS -#define ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS 0 -#endif - -/* This is an example/debug implementation of alloc/free functions only */ -typedef struct altcp_mbedtls_malloc_helper_s { - size_t c; - size_t len; -} altcp_mbedtls_malloc_helper_t; - -#if ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS -typedef struct altcp_mbedtls_malloc_stats_s { - size_t allocedBytes; - size_t allocCnt; - size_t maxBytes; - size_t totalBytes; -} altcp_mbedtls_malloc_stats_t; -altcp_mbedtls_malloc_stats_t altcp_mbedtls_malloc_stats; -volatile int altcp_mbedtls_malloc_clear_stats; -#endif - -static void * -tls_malloc(size_t c, size_t len) -{ - altcp_mbedtls_malloc_helper_t *hlpr; - void *ret; - size_t alloc_size; -#if ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS - if (altcp_mbedtls_malloc_clear_stats) { - altcp_mbedtls_malloc_clear_stats = 0; - memset(&altcp_mbedtls_malloc_stats, 0, sizeof(altcp_mbedtls_malloc_stats)); - } -#endif - alloc_size = sizeof(altcp_mbedtls_malloc_helper_t) + (c * len); - /* check for maximum allocation size, mainly to prevent mem_size_t overflow */ - if (alloc_size > MEM_SIZE) { - LWIP_DEBUGF(ALTCP_MBEDTLS_MEM_DEBUG, ("mbedtls allocation too big: %c * %d bytes vs MEM_SIZE=%d", - (int)c, (int)len, (int)MEM_SIZE)); - return NULL; - } - hlpr = (altcp_mbedtls_malloc_helper_t *)mem_malloc((mem_size_t)alloc_size); - if (hlpr == NULL) { - LWIP_DEBUGF(ALTCP_MBEDTLS_MEM_DEBUG, ("mbedtls alloc callback failed for %c * %d bytes", (int)c, (int)len)); - return NULL; - } -#if ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS - altcp_mbedtls_malloc_stats.allocCnt++; - altcp_mbedtls_malloc_stats.allocedBytes += c * len; - if (altcp_mbedtls_malloc_stats.allocedBytes > altcp_mbedtls_malloc_stats.maxBytes) { - altcp_mbedtls_malloc_stats.maxBytes = altcp_mbedtls_malloc_stats.allocedBytes; - } - altcp_mbedtls_malloc_stats.totalBytes += c * len; -#endif - hlpr->c = c; - hlpr->len = len; - ret = hlpr + 1; - /* zeroing the allocated chunk is required by mbedTLS! */ - memset(ret, 0, c * len); - return ret; -} - -static void -tls_free(void *ptr) -{ - altcp_mbedtls_malloc_helper_t *hlpr; - if (ptr == NULL) { - /* this obviously happened in mbedtls... */ - return; - } - hlpr = ((altcp_mbedtls_malloc_helper_t *)ptr) - 1; -#if ALTCP_MBEDTLS_PLATFORM_ALLOC_STATS - if (!altcp_mbedtls_malloc_clear_stats) { - altcp_mbedtls_malloc_stats.allocedBytes -= hlpr->c * hlpr->len; - } -#endif - mem_free(hlpr); -} -#endif /* ALTCP_MBEDTLS_PLATFORM_ALLOC*/ - -void -altcp_mbedtls_mem_init(void) -{ - /* not much to do here when using the heap */ - -#if ALTCP_MBEDTLS_PLATFORM_ALLOC - /* set mbedtls allocation methods */ - mbedtls_platform_set_calloc_free(&tls_malloc, &tls_free); -#endif -} - -altcp_mbedtls_state_t * -altcp_mbedtls_alloc(void *conf) -{ - altcp_mbedtls_state_t *ret = (altcp_mbedtls_state_t *)mem_calloc(1, sizeof(altcp_mbedtls_state_t)); - if (ret != NULL) { - ret->conf = conf; - } - return ret; -} - -void -altcp_mbedtls_free(void *conf, altcp_mbedtls_state_t *state) -{ - LWIP_UNUSED_ARG(conf); - LWIP_ASSERT("state != NULL", state != NULL); - mem_free(state); -} - -void * -altcp_mbedtls_alloc_config(size_t size) -{ - void *ret; - size_t checked_size = (mem_size_t)size; - if (size != checked_size) { - /* allocation too big (mem_size_t overflow) */ - return NULL; - } - ret = (altcp_mbedtls_state_t *)mem_calloc(1, (mem_size_t)size); - return ret; -} - -void -altcp_mbedtls_free_config(void *item) -{ - LWIP_ASSERT("item != NULL", item != NULL); - mem_free(item); -} - -#endif /* LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS */ -#endif /* LWIP_ALTCP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/altcp_tls/altcp_tls_mbedtls_mem.h b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/altcp_tls/altcp_tls_mbedtls_mem.h deleted file mode 100644 index b391bf874..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/altcp_tls/altcp_tls_mbedtls_mem.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @file - * Application layered TCP/TLS connection API (to be used from TCPIP thread) - * - * This file contains memory management function prototypes for a TLS layer using mbedTLS. - * - * Memory management contains: - * - allocating/freeing altcp_mbedtls_state_t - * - allocating/freeing memory used in the mbedTLS library - */ - -/* - * Copyright (c) 2017 Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_ALTCP_MBEDTLS_MEM_H -#define LWIP_HDR_ALTCP_MBEDTLS_MEM_H - -#include "lwip/opt.h" - -#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/altcp_tls_mbedtls_opts.h" - -#if LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS - -#include "altcp_tls_mbedtls_structs.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void altcp_mbedtls_mem_init(void); -altcp_mbedtls_state_t *altcp_mbedtls_alloc(void *conf); -void altcp_mbedtls_free(void *conf, altcp_mbedtls_state_t *state); -void *altcp_mbedtls_alloc_config(size_t size); -void altcp_mbedtls_free_config(void *item); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS */ -#endif /* LWIP_ALTCP */ -#endif /* LWIP_HDR_ALTCP_MBEDTLS_MEM_H */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/altcp_tls/altcp_tls_mbedtls_structs.h b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/altcp_tls/altcp_tls_mbedtls_structs.h deleted file mode 100644 index 17efaaf63..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/altcp_tls/altcp_tls_mbedtls_structs.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file - * Application layered TCP/TLS connection API (to be used from TCPIP thread) - * - * This file contains structure definitions for a TLS layer using mbedTLS. - */ - -/* - * Copyright (c) 2017 Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ -#ifndef LWIP_HDR_ALTCP_MBEDTLS_STRUCTS_H -#define LWIP_HDR_ALTCP_MBEDTLS_STRUCTS_H - -#include "lwip/opt.h" - -#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/altcp_tls_mbedtls_opts.h" - -#if LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS - -#include "lwip/altcp.h" -#include "lwip/pbuf.h" - -#include "mbedtls/ssl.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ALTCP_MBEDTLS_FLAGS_HANDSHAKE_DONE 0x01 -#define ALTCP_MBEDTLS_FLAGS_UPPER_CALLED 0x02 -#define ALTCP_MBEDTLS_FLAGS_RX_CLOSE_QUEUED 0x04 -#define ALTCP_MBEDTLS_FLAGS_RX_CLOSED 0x08 -#define ALTCP_MBEDTLS_FLAGS_APPLDATA_SENT 0x10 - -typedef struct altcp_mbedtls_state_s { - void *conf; - mbedtls_ssl_context ssl_context; - /* chain of rx pbufs (before decryption) */ - struct pbuf *rx; - struct pbuf *rx_app; - u8_t flags; - int rx_passed_unrecved; - int bio_bytes_read; - int bio_bytes_appl; -} altcp_mbedtls_state_t; - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_ALTCP_TLS && LWIP_ALTCP_TLS_MBEDTLS */ -#endif /* LWIP_ALTCP */ -#endif /* LWIP_HDR_ALTCP_MBEDTLS_STRUCTS_H */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/altcp_proxyconnect.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/altcp_proxyconnect.c deleted file mode 100644 index 9a0b2ba19..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/altcp_proxyconnect.c +++ /dev/null @@ -1,584 +0,0 @@ -/** - * @file - * Application layered TCP connection API that executes a proxy-connect. - * - * This file provides a starting layer that executes a proxy-connect e.g. to - * set up TLS connections through a http proxy. - */ - -/* - * Copyright (c) 2018 Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - * - */ - -#include "lwip/apps/altcp_proxyconnect.h" - -#if LWIP_ALTCP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/altcp.h" -#include "lwip/priv/altcp_priv.h" - -#include "lwip/altcp_tcp.h" -#include "lwip/altcp_tls.h" - -#include "lwip/mem.h" -#include "lwip/init.h" - -#include - -/** This string is passed in the HTTP header as "User-Agent: " */ -#ifndef ALTCP_PROXYCONNECT_CLIENT_AGENT -#define ALTCP_PROXYCONNECT_CLIENT_AGENT "lwIP/" LWIP_VERSION_STRING " (http://savannah.nongnu.org/projects/lwip)" -#endif - -#define ALTCP_PROXYCONNECT_FLAGS_CONNECT_STARTED 0x01 -#define ALTCP_PROXYCONNECT_FLAGS_HANDSHAKE_DONE 0x02 - -typedef struct altcp_proxyconnect_state_s -{ - ip_addr_t outer_addr; - u16_t outer_port; - struct altcp_proxyconnect_config *conf; - u8_t flags; -} altcp_proxyconnect_state_t; - -/* Variable prototype, the actual declaration is at the end of this file - since it contains pointers to static functions declared here */ -extern const struct altcp_functions altcp_proxyconnect_functions; - -/* memory management functions: */ - -static altcp_proxyconnect_state_t * -altcp_proxyconnect_state_alloc(void) -{ - altcp_proxyconnect_state_t *ret = (altcp_proxyconnect_state_t *)mem_calloc(1, sizeof(altcp_proxyconnect_state_t)); - return ret; -} - -static void -altcp_proxyconnect_state_free(altcp_proxyconnect_state_t *state) -{ - LWIP_ASSERT("state != NULL", state != NULL); - mem_free(state); -} - -/* helper functions */ - -#define PROXY_CONNECT "CONNECT %s:%d HTTP/1.1\r\n" /* HOST, PORT */ \ - "User-Agent: %s\r\n" /* User-Agent */\ - "Proxy-Connection: keep-alive\r\n" \ - "Connection: keep-alive\r\n" \ - "\r\n" -#define PROXY_CONNECT_FORMAT(host, port) PROXY_CONNECT, host, port, ALTCP_PROXYCONNECT_CLIENT_AGENT - -/* Format the http proxy connect request via snprintf */ -static int -altcp_proxyconnect_format_request(char *buffer, size_t bufsize, const char *host, int port) -{ - return snprintf(buffer, bufsize, PROXY_CONNECT_FORMAT(host, port)); -} - -/* Create and send the http proxy connect request */ -static err_t -altcp_proxyconnect_send_request(struct altcp_pcb *conn) -{ - int len, len2; - mem_size_t alloc_len; - char *buffer, *host; - altcp_proxyconnect_state_t *state = (altcp_proxyconnect_state_t *)conn->state; - - if (!state) { - return ERR_VAL; - } - /* Use printf with zero length to get the required allocation size */ - len = altcp_proxyconnect_format_request(NULL, 0, "", state->outer_port); - if (len < 0) { - return ERR_VAL; - } - /* add allocation size for IP address strings */ -#if LWIP_IPV6 - len += 40; /* worst-case IPv6 address length */ -#else - len += 16; /* worst-case IPv4 address length */ -#endif - alloc_len = (mem_size_t)len; - if ((len < 0) || (int)alloc_len != len) { - /* overflow */ - return ERR_MEM; - } - /* Allocate a bufer for the request string */ - buffer = (char *)mem_malloc(alloc_len); - if (buffer == NULL) { - return ERR_MEM; - } - host = ipaddr_ntoa(&state->outer_addr); - len2 = altcp_proxyconnect_format_request(buffer, alloc_len, host, state->outer_port); - if ((len2 > 0) && (len2 <= len) && (len2 <= 0xFFFF)) { - err_t err = altcp_write(conn->inner_conn, buffer, (u16_t)len2, TCP_WRITE_FLAG_COPY); - if (err != ERR_OK) { - /* @todo: abort? */ - mem_free(buffer); - return err; - } - } - mem_free(buffer); - return ERR_OK; -} - -/* callback functions from inner/lower connection: */ - -/** Connected callback from lower connection (i.e. TCP). - * Not really implemented/tested yet... - */ -static err_t -altcp_proxyconnect_lower_connected(void *arg, struct altcp_pcb *inner_conn, err_t err) -{ - struct altcp_pcb *conn = (struct altcp_pcb *)arg; - if (conn && conn->state) { - LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn); - LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */ - /* upper connected is called when handshake is done */ - if (err != ERR_OK) { - if (conn->connected) { - if (conn->connected(conn->arg, conn, err) == ERR_ABRT) { - return ERR_ABRT; - } - return ERR_OK; - } - } - /* send proxy connect request here */ - return altcp_proxyconnect_send_request(conn); - } - return ERR_VAL; -} - -/** Recv callback from lower connection (i.e. TCP) - * This one mainly differs between connection setup (wait for proxy OK string) - * and application phase (data is passed on to the application). - */ -static err_t -altcp_proxyconnect_lower_recv(void *arg, struct altcp_pcb *inner_conn, struct pbuf *p, err_t err) -{ - altcp_proxyconnect_state_t *state; - struct altcp_pcb *conn = (struct altcp_pcb *)arg; - - LWIP_ASSERT("no err expected", err == ERR_OK); - LWIP_UNUSED_ARG(err); - - if (!conn) { - /* no connection given as arg? should not happen, but prevent pbuf/conn leaks */ - if (p != NULL) { - pbuf_free(p); - } - altcp_close(inner_conn); - return ERR_CLSD; - } - state = (altcp_proxyconnect_state_t *)conn->state; - LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn); - if (!state) { - /* already closed */ - if (p != NULL) { - pbuf_free(p); - } - altcp_close(inner_conn); - return ERR_CLSD; - } - if (state->flags & ALTCP_PROXYCONNECT_FLAGS_HANDSHAKE_DONE) { - /* application phase, just pass this through */ - if (conn->recv) { - return conn->recv(conn->arg, conn, p, err); - } - pbuf_free(p); - return ERR_OK; - } else { - /* setup phase */ - /* handle NULL pbuf (inner connection closed) */ - if (p == NULL) { - if (altcp_close(conn) != ERR_OK) { - altcp_abort(conn); - return ERR_ABRT; - } - return ERR_OK; - } else { - /* @todo: parse setup phase rx data - for now, we just wait for the end of the header... */ - u16_t idx = pbuf_memfind(p, "\r\n\r\n", 4, 0); - altcp_recved(inner_conn, p->tot_len); - pbuf_free(p); - if (idx != 0xFFFF) { - state->flags |= ALTCP_PROXYCONNECT_FLAGS_HANDSHAKE_DONE; - if (conn->connected) { - return conn->connected(conn->arg, conn, ERR_OK); - } - } - return ERR_OK; - } - } -} - -/** Sent callback from lower connection (i.e. TCP) - * This only informs the upper layer to try to send more, not about - * the number of ACKed bytes. - */ -static err_t -altcp_proxyconnect_lower_sent(void *arg, struct altcp_pcb *inner_conn, u16_t len) -{ - struct altcp_pcb *conn = (struct altcp_pcb *)arg; - LWIP_UNUSED_ARG(len); - if (conn) { - altcp_proxyconnect_state_t *state = (altcp_proxyconnect_state_t *)conn->state; - LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn); - LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */ - if (!state || !(state->flags & ALTCP_PROXYCONNECT_FLAGS_HANDSHAKE_DONE)) { - /* @todo: do something here? */ - return ERR_OK; - } - /* pass this on to upper sent */ - if (conn->sent) { - return conn->sent(conn->arg, conn, len); - } - } - return ERR_OK; -} - -/** Poll callback from lower connection (i.e. TCP) - * Just pass this on to the application. - * @todo: retry sending? - */ -static err_t -altcp_proxyconnect_lower_poll(void *arg, struct altcp_pcb *inner_conn) -{ - struct altcp_pcb *conn = (struct altcp_pcb *)arg; - if (conn) { - LWIP_ASSERT("pcb mismatch", conn->inner_conn == inner_conn); - LWIP_UNUSED_ARG(inner_conn); /* for LWIP_NOASSERT */ - if (conn->poll) { - return conn->poll(conn->arg, conn); - } - } - return ERR_OK; -} - -static void -altcp_proxyconnect_lower_err(void *arg, err_t err) -{ - struct altcp_pcb *conn = (struct altcp_pcb *)arg; - if (conn) { - conn->inner_conn = NULL; /* already freed */ - if (conn->err) { - conn->err(conn->arg, err); - } - altcp_free(conn); - } -} - - -/* setup functions */ - -static void -altcp_proxyconnect_setup_callbacks(struct altcp_pcb *conn, struct altcp_pcb *inner_conn) -{ - altcp_arg(inner_conn, conn); - altcp_recv(inner_conn, altcp_proxyconnect_lower_recv); - altcp_sent(inner_conn, altcp_proxyconnect_lower_sent); - altcp_err(inner_conn, altcp_proxyconnect_lower_err); - /* tcp_poll is set when interval is set by application */ - /* listen is set totally different :-) */ -} - -static err_t -altcp_proxyconnect_setup(struct altcp_proxyconnect_config *config, struct altcp_pcb *conn, struct altcp_pcb *inner_conn) -{ - altcp_proxyconnect_state_t *state; - if (!config) { - return ERR_ARG; - } - LWIP_ASSERT("invalid inner_conn", conn != inner_conn); - - /* allocate proxyconnect context */ - state = altcp_proxyconnect_state_alloc(); - if (state == NULL) { - return ERR_MEM; - } - state->flags = 0; - state->conf = config; - altcp_proxyconnect_setup_callbacks(conn, inner_conn); - conn->inner_conn = inner_conn; - conn->fns = &altcp_proxyconnect_functions; - conn->state = state; - return ERR_OK; -} - -/** Allocate a new altcp layer connecting through a proxy. - * This function gets the inner pcb passed. - * - * @param config struct altcp_proxyconnect_config that contains the proxy settings - * @param inner_pcb pcb that makes the connection to the proxy (i.e. tcp pcb) - */ -struct altcp_pcb * -altcp_proxyconnect_new(struct altcp_proxyconnect_config *config, struct altcp_pcb *inner_pcb) -{ - struct altcp_pcb *ret; - if (inner_pcb == NULL) { - return NULL; - } - ret = altcp_alloc(); - if (ret != NULL) { - if (altcp_proxyconnect_setup(config, ret, inner_pcb) != ERR_OK) { - altcp_free(ret); - return NULL; - } - } - return ret; -} - -/** Allocate a new altcp layer connecting through a proxy. - * This function allocates the inner pcb as tcp pcb, resulting in a direct tcp - * connection to the proxy. - * - * @param config struct altcp_proxyconnect_config that contains the proxy settings - * @param ip_type IP type of the connection (@ref lwip_ip_addr_type) - */ -struct altcp_pcb * -altcp_proxyconnect_new_tcp(struct altcp_proxyconnect_config *config, u8_t ip_type) -{ - struct altcp_pcb *inner_pcb, *ret; - - /* inner pcb is tcp */ - inner_pcb = altcp_tcp_new_ip_type(ip_type); - if (inner_pcb == NULL) { - return NULL; - } - ret = altcp_proxyconnect_new(config, inner_pcb); - if (ret == NULL) { - altcp_close(inner_pcb); - } - return ret; -} - -/** Allocator function to allocate a proxy connect altcp pcb connecting directly - * via tcp to the proxy. - * - * The returned pcb is a chain: altcp_proxyconnect - altcp_tcp - tcp pcb - * - * This function is meant for use with @ref altcp_new. - * - * @param arg struct altcp_proxyconnect_config that contains the proxy settings - * @param ip_type IP type of the connection (@ref lwip_ip_addr_type) - */ -struct altcp_pcb * -altcp_proxyconnect_alloc(void *arg, u8_t ip_type) -{ - return altcp_proxyconnect_new_tcp((struct altcp_proxyconnect_config *)arg, ip_type); -} - - -#if LWIP_ALTCP_TLS - -/** Allocator function to allocate a TLS connection through a proxy. - * - * The returned pcb is a chain: altcp_tls - altcp_proxyconnect - altcp_tcp - tcp pcb - * - * This function is meant for use with @ref altcp_new. - * - * @param arg struct altcp_proxyconnect_tls_config that contains the proxy settings - * and tls settings - * @param ip_type IP type of the connection (@ref lwip_ip_addr_type) - */ -struct altcp_pcb * -altcp_proxyconnect_tls_alloc(void *arg, u8_t ip_type) -{ - struct altcp_proxyconnect_tls_config *cfg = (struct altcp_proxyconnect_tls_config *)arg; - struct altcp_pcb *proxy_pcb; - struct altcp_pcb *tls_pcb; - - proxy_pcb = altcp_proxyconnect_new_tcp(&cfg->proxy, ip_type); - tls_pcb = altcp_tls_wrap(cfg->tls_config, proxy_pcb); - - if (tls_pcb == NULL) { - altcp_close(proxy_pcb); - } - return tls_pcb; -} -#endif /* LWIP_ALTCP_TLS */ - -/* "virtual" functions */ -static void -altcp_proxyconnect_set_poll(struct altcp_pcb *conn, u8_t interval) -{ - if (conn != NULL) { - altcp_poll(conn->inner_conn, altcp_proxyconnect_lower_poll, interval); - } -} - -static void -altcp_proxyconnect_recved(struct altcp_pcb *conn, u16_t len) -{ - altcp_proxyconnect_state_t *state; - if (conn == NULL) { - return; - } - state = (altcp_proxyconnect_state_t *)conn->state; - if (state == NULL) { - return; - } - if (!(state->flags & ALTCP_PROXYCONNECT_FLAGS_HANDSHAKE_DONE)) { - return; - } - altcp_recved(conn->inner_conn, len); -} - -static err_t -altcp_proxyconnect_connect(struct altcp_pcb *conn, const ip_addr_t *ipaddr, u16_t port, altcp_connected_fn connected) -{ - altcp_proxyconnect_state_t *state; - - if ((conn == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } - state = (altcp_proxyconnect_state_t *)conn->state; - if (state == NULL) { - return ERR_VAL; - } - if (state->flags & ALTCP_PROXYCONNECT_FLAGS_CONNECT_STARTED) { - return ERR_VAL; - } - state->flags |= ALTCP_PROXYCONNECT_FLAGS_CONNECT_STARTED; - - conn->connected = connected; - /* connect to our proxy instead, but store the requested address and port */ - ip_addr_copy(state->outer_addr, *ipaddr); - state->outer_port = port; - - return altcp_connect(conn->inner_conn, &state->conf->proxy_addr, state->conf->proxy_port, altcp_proxyconnect_lower_connected); -} - -static struct altcp_pcb * -altcp_proxyconnect_listen(struct altcp_pcb *conn, u8_t backlog, err_t *err) -{ - LWIP_UNUSED_ARG(conn); - LWIP_UNUSED_ARG(backlog); - LWIP_UNUSED_ARG(err); - /* listen not supported! */ - return NULL; -} - -static void -altcp_proxyconnect_abort(struct altcp_pcb *conn) -{ - if (conn != NULL) { - if (conn->inner_conn != NULL) { - altcp_abort(conn->inner_conn); - } - altcp_free(conn); - } -} - -static err_t -altcp_proxyconnect_close(struct altcp_pcb *conn) -{ - if (conn == NULL) { - return ERR_VAL; - } - if (conn->inner_conn != NULL) { - err_t err = altcp_close(conn->inner_conn); - if (err != ERR_OK) { - /* closing inner conn failed, return the error */ - return err; - } - } - /* no inner conn or closing it succeeded, deallocate myself */ - altcp_free(conn); - return ERR_OK; -} - -static err_t -altcp_proxyconnect_write(struct altcp_pcb *conn, const void *dataptr, u16_t len, u8_t apiflags) -{ - altcp_proxyconnect_state_t *state; - - LWIP_UNUSED_ARG(apiflags); - - if (conn == NULL) { - return ERR_VAL; - } - - state = (altcp_proxyconnect_state_t *)conn->state; - if (state == NULL) { - /* @todo: which error? */ - return ERR_CLSD; - } - if (!(state->flags & ALTCP_PROXYCONNECT_FLAGS_HANDSHAKE_DONE)) { - /* @todo: which error? */ - return ERR_VAL; - } - return altcp_write(conn->inner_conn, dataptr, len, apiflags); -} - -static void -altcp_proxyconnect_dealloc(struct altcp_pcb *conn) -{ - /* clean up and free tls state */ - if (conn) { - altcp_proxyconnect_state_t *state = (altcp_proxyconnect_state_t *)conn->state; - if (state) { - altcp_proxyconnect_state_free(state); - conn->state = NULL; - } - } -} -const struct altcp_functions altcp_proxyconnect_functions = { - altcp_proxyconnect_set_poll, - altcp_proxyconnect_recved, - altcp_default_bind, - altcp_proxyconnect_connect, - altcp_proxyconnect_listen, - altcp_proxyconnect_abort, - altcp_proxyconnect_close, - altcp_default_shutdown, - altcp_proxyconnect_write, - altcp_default_output, - altcp_default_mss, - altcp_default_sndbuf, - altcp_default_sndqueuelen, - altcp_default_nagle_disable, - altcp_default_nagle_enable, - altcp_default_nagle_disabled, - altcp_default_setprio, - altcp_proxyconnect_dealloc, - altcp_default_get_tcp_addrinfo, - altcp_default_get_ip, - altcp_default_get_port -#ifdef LWIP_DEBUG - , altcp_default_dbg_get_tcp_state -#endif -}; - -#endif /* LWIP_ALTCP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/fs.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/fs.c deleted file mode 100644 index f15a48016..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/fs.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ - -#include "lwip/apps/httpd_opts.h" -#include "lwip/def.h" -#include "lwip/apps/fs.h" -#include - - -#include HTTPD_FSDATA_FILE - -/*-----------------------------------------------------------------------------------*/ - -#if LWIP_HTTPD_CUSTOM_FILES -int fs_open_custom(struct fs_file *file, const char *name); -void fs_close_custom(struct fs_file *file); -#if LWIP_HTTPD_FS_ASYNC_READ -u8_t fs_canread_custom(struct fs_file *file); -u8_t fs_wait_read_custom(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg); -int fs_read_async_custom(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg); -#else /* LWIP_HTTPD_FS_ASYNC_READ */ -int fs_read_custom(struct fs_file *file, char *buffer, int count); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -#endif /* LWIP_HTTPD_CUSTOM_FILES */ - -/*-----------------------------------------------------------------------------------*/ -err_t -fs_open(struct fs_file *file, const char *name) -{ - const struct fsdata_file *f; - - if ((file == NULL) || (name == NULL)) { - return ERR_ARG; - } - -#if LWIP_HTTPD_CUSTOM_FILES - if (fs_open_custom(file, name)) { - file->is_custom_file = 1; - return ERR_OK; - } - file->is_custom_file = 0; -#endif /* LWIP_HTTPD_CUSTOM_FILES */ - - for (f = FS_ROOT; f != NULL; f = f->next) { - if (!strcmp(name, (const char *)f->name)) { - file->data = (const char *)f->data; - file->len = f->len; - file->index = f->len; - file->pextension = NULL; - file->flags = f->flags; -#if HTTPD_PRECALCULATED_CHECKSUM - file->chksum_count = f->chksum_count; - file->chksum = f->chksum; -#endif /* HTTPD_PRECALCULATED_CHECKSUM */ -#if LWIP_HTTPD_FILE_STATE - file->state = fs_state_init(file, name); -#endif /* #if LWIP_HTTPD_FILE_STATE */ - return ERR_OK; - } - } - /* file not found */ - return ERR_VAL; -} - -/*-----------------------------------------------------------------------------------*/ -void -fs_close(struct fs_file *file) -{ -#if LWIP_HTTPD_CUSTOM_FILES - if (file->is_custom_file) { - fs_close_custom(file); - } -#endif /* LWIP_HTTPD_CUSTOM_FILES */ -#if LWIP_HTTPD_FILE_STATE - fs_state_free(file, file->state); -#endif /* #if LWIP_HTTPD_FILE_STATE */ - LWIP_UNUSED_ARG(file); -} -/*-----------------------------------------------------------------------------------*/ -#if LWIP_HTTPD_DYNAMIC_FILE_READ -#if LWIP_HTTPD_FS_ASYNC_READ -int -fs_read_async(struct fs_file *file, char *buffer, int count, fs_wait_cb callback_fn, void *callback_arg) -#else /* LWIP_HTTPD_FS_ASYNC_READ */ -int -fs_read(struct fs_file *file, char *buffer, int count) -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -{ - int read; - if (file->index == file->len) { - return FS_READ_EOF; - } -#if LWIP_HTTPD_FS_ASYNC_READ - LWIP_UNUSED_ARG(callback_fn); - LWIP_UNUSED_ARG(callback_arg); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -#if LWIP_HTTPD_CUSTOM_FILES - if (file->is_custom_file) { -#if LWIP_HTTPD_FS_ASYNC_READ - return fs_read_async_custom(file, buffer, count, callback_fn, callback_arg); -#else /* LWIP_HTTPD_FS_ASYNC_READ */ - return fs_read_custom(file, buffer, count); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - } -#endif /* LWIP_HTTPD_CUSTOM_FILES */ - - read = file->len - file->index; - if (read > count) { - read = count; - } - - MEMCPY(buffer, (file->data + file->index), read); - file->index += read; - - return (read); -} -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ -/*-----------------------------------------------------------------------------------*/ -#if LWIP_HTTPD_FS_ASYNC_READ -int -fs_is_file_ready(struct fs_file *file, fs_wait_cb callback_fn, void *callback_arg) -{ - if (file != NULL) { -#if LWIP_HTTPD_FS_ASYNC_READ -#if LWIP_HTTPD_CUSTOM_FILES - if (!fs_canread_custom(file)) { - if (fs_wait_read_custom(file, callback_fn, callback_arg)) { - return 0; - } - } -#else /* LWIP_HTTPD_CUSTOM_FILES */ - LWIP_UNUSED_ARG(callback_fn); - LWIP_UNUSED_ARG(callback_arg); -#endif /* LWIP_HTTPD_CUSTOM_FILES */ -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - } - return 1; -} -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ -/*-----------------------------------------------------------------------------------*/ -int -fs_bytes_left(struct fs_file *file) -{ - return file->len - file->index; -} diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/fs/img/sics.gif b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/fs/img/sics.gif deleted file mode 100644 index 0a4fc7bb0..000000000 Binary files a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/fs/img/sics.gif and /dev/null differ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/fsdata.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/fsdata.c deleted file mode 100644 index ab9da7e13..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/fsdata.c +++ /dev/null @@ -1,337 +0,0 @@ -#include "lwip/apps/fs.h" -#include "lwip/def.h" - - -#define file_NULL (struct fsdata_file *) NULL - - -#ifndef FS_FILE_FLAGS_HEADER_INCLUDED -#define FS_FILE_FLAGS_HEADER_INCLUDED 1 -#endif -#ifndef FS_FILE_FLAGS_HEADER_PERSISTENT -#define FS_FILE_FLAGS_HEADER_PERSISTENT 0 -#endif -/* FSDATA_FILE_ALIGNMENT: 0=off, 1=by variable, 2=by include */ -#ifndef FSDATA_FILE_ALIGNMENT -#define FSDATA_FILE_ALIGNMENT 0 -#endif -#ifndef FSDATA_ALIGN_PRE -#define FSDATA_ALIGN_PRE -#endif -#ifndef FSDATA_ALIGN_POST -#define FSDATA_ALIGN_POST -#endif -#if FSDATA_FILE_ALIGNMENT==2 -#include "fsdata_alignment.h" -#endif -#if FSDATA_FILE_ALIGNMENT==1 -static const unsigned int dummy_align__img_sics_gif = 0; -#endif -static const unsigned char FSDATA_ALIGN_PRE data__img_sics_gif[] FSDATA_ALIGN_POST = { -/* /img/sics.gif (14 chars) */ -0x2f,0x69,0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x00,0x00,0x00, - -/* HTTP header */ -/* "HTTP/1.0 200 OK -" (17 bytes) */ -0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d, -0x0a, -/* "Server: lwIP/2.0.3d (http://savannah.nongnu.org/projects/lwip) -" (64 bytes) */ -0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x32,0x2e,0x30, -0x2e,0x33,0x64,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61, -0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f, -0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, - -/* "Content-Length: 724 -" (18+ bytes) */ -0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20, -0x37,0x32,0x34,0x0d,0x0a, -/* "Content-Type: image/gif - -" (27 bytes) */ -0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x69,0x6d, -0x61,0x67,0x65,0x2f,0x67,0x69,0x66,0x0d,0x0a,0x0d,0x0a, -/* raw file data (724 bytes) */ -0x47,0x49,0x46,0x38,0x39,0x61,0x46,0x00,0x22,0x00,0xa5,0x00,0x00,0xd9,0x2b,0x39, -0x6a,0x6a,0x6a,0xbf,0xbf,0xbf,0x93,0x93,0x93,0x0f,0x0f,0x0f,0xb0,0xb0,0xb0,0xa6, -0xa6,0xa6,0x80,0x80,0x80,0x76,0x76,0x76,0x1e,0x1e,0x1e,0x9d,0x9d,0x9d,0x2e,0x2e, -0x2e,0x49,0x49,0x49,0x54,0x54,0x54,0x8a,0x8a,0x8a,0x60,0x60,0x60,0xc6,0xa6,0x99, -0xbd,0xb5,0xb2,0xc2,0xab,0xa1,0xd9,0x41,0x40,0xd5,0x67,0x55,0xc0,0xb0,0xaa,0xd5, -0x5e,0x4e,0xd6,0x50,0x45,0xcc,0x93,0x7d,0xc8,0xa1,0x90,0xce,0x8b,0x76,0xd2,0x7b, -0x65,0xd1,0x84,0x6d,0xc9,0x99,0x86,0x3a,0x3a,0x3a,0x00,0x00,0x00,0xb8,0xb8,0xb8, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x2c,0x00,0x00, -0x00,0x00,0x46,0x00,0x22,0x00,0x00,0x06,0xfe,0x40,0x90,0x70,0x48,0x2c,0x1a,0x8f, -0xc8,0xa4,0x72,0xc9,0x6c,0x3a,0x9f,0xd0,0xa8,0x74,0x4a,0xad,0x5a,0xaf,0xd8,0xac, -0x76,0xa9,0x40,0x04,0xbe,0x83,0xe2,0x60,0x3c,0x50,0x20,0x0d,0x8e,0x6f,0x00,0x31, -0x28,0x1c,0x0d,0x07,0xb5,0xc3,0x60,0x75,0x24,0x3e,0xf8,0xfc,0x87,0x11,0x06,0xe9, -0x3d,0x46,0x07,0x0b,0x7a,0x7a,0x7c,0x43,0x06,0x1e,0x84,0x78,0x0b,0x07,0x6e,0x51, -0x01,0x8a,0x84,0x08,0x7e,0x79,0x80,0x87,0x89,0x91,0x7a,0x93,0x0a,0x04,0x99,0x78, -0x96,0x4f,0x03,0x9e,0x79,0x01,0x94,0x9f,0x43,0x9c,0xa3,0xa4,0x05,0x77,0xa3,0xa0, -0x4e,0x98,0x79,0x0b,0x1e,0x83,0xa4,0xa6,0x1f,0x96,0x05,0x9d,0xaa,0x78,0x01,0x07, -0x84,0x04,0x1e,0x1e,0xbb,0xb8,0x51,0x84,0x0e,0x43,0x05,0x07,0x77,0xa5,0x7f,0x42, -0xb1,0xb2,0x01,0x63,0x08,0x0d,0xbb,0x01,0x0c,0x7a,0x0d,0x44,0x0e,0xd8,0xaf,0x4c, -0x05,0x7a,0x04,0x47,0x07,0x07,0xb7,0x80,0xa2,0xe1,0x7d,0x44,0x05,0x01,0x04,0x01, -0xd0,0xea,0x87,0x93,0x4f,0xe0,0x9a,0x49,0xce,0xd8,0x79,0x04,0x66,0x20,0x15,0x10, -0x10,0x11,0x92,0x29,0x80,0xb6,0xc0,0x91,0x15,0x45,0x1e,0x90,0x19,0x71,0x46,0xa8, -0x5c,0x04,0x0e,0x00,0x22,0x4e,0xe8,0x40,0x24,0x9f,0x3e,0x04,0x06,0xa7,0x58,0xd4, -0x93,0xa0,0x1c,0x91,0x3f,0xe8,0xf0,0x88,0x03,0xb1,0x21,0xa2,0x49,0x00,0x19,0x86, -0xfc,0x52,0x44,0xe0,0x01,0x9d,0x29,0x21,0x15,0x25,0x50,0xf7,0x67,0x25,0x1e,0x06, -0xfd,0x4e,0x9a,0xb4,0x90,0xac,0x15,0xfa,0xcb,0x52,0x53,0x1e,0x8c,0xf2,0xf8,0x07, -0x92,0x2d,0x08,0x3a,0x4d,0x12,0x49,0x95,0x49,0xdb,0x14,0x04,0xc4,0x14,0x85,0x29, -0xaa,0xe7,0x01,0x08,0xa4,0x49,0x01,0x14,0x51,0xe0,0x53,0x91,0xd5,0x29,0x06,0x1a, -0x64,0x02,0xf4,0xc7,0x81,0x9e,0x05,0x20,0x22,0x64,0xa5,0x30,0xae,0xab,0x9e,0x97, -0x53,0xd8,0xb9,0xfd,0x50,0xef,0x93,0x02,0x42,0x74,0x34,0xe8,0x9c,0x20,0x21,0xc9, -0x01,0x68,0x78,0xe6,0x55,0x29,0x20,0x56,0x4f,0x4c,0x40,0x51,0x71,0x82,0xc0,0x70, -0x21,0x22,0x85,0xbe,0x4b,0x1c,0x44,0x05,0xea,0xa4,0x01,0xbf,0x22,0xb5,0xf0,0x1c, -0x06,0x51,0x38,0x8f,0xe0,0x22,0xec,0x18,0xac,0x39,0x22,0xd4,0xd6,0x93,0x44,0x01, -0x32,0x82,0xc8,0xfc,0x61,0xb3,0x01,0x45,0x0c,0x2e,0x83,0x30,0xd0,0x0e,0x17,0x24, -0x0f,0x70,0x85,0x94,0xee,0x05,0x05,0x53,0x4b,0x32,0x1b,0x3f,0x98,0xd3,0x1d,0x29, -0x81,0xb0,0xae,0x1e,0x8c,0x7e,0x68,0xe0,0x60,0x5a,0x54,0x8f,0xb0,0x78,0x69,0x73, -0x06,0xa2,0x00,0x6b,0x57,0xca,0x3d,0x11,0x50,0xbd,0x04,0x30,0x4b,0x3a,0xd4,0xab, -0x5f,0x1f,0x9b,0x3d,0x13,0x74,0x27,0x88,0x3c,0x25,0xe0,0x17,0xbe,0x7a,0x79,0x45, -0x0d,0x0c,0xb0,0x8b,0xda,0x90,0xca,0x80,0x06,0x5d,0x17,0x60,0x1c,0x22,0x4c,0xd8, -0x57,0x22,0x06,0x20,0x00,0x98,0x07,0x08,0xe4,0x56,0x80,0x80,0x1c,0xc5,0xb7,0xc5, -0x82,0x0c,0x36,0xe8,0xe0,0x83,0x10,0x46,0x28,0xe1,0x84,0x14,0x56,0x68,0xa1,0x10, -0x41,0x00,0x00,0x3b,}; - -#if FSDATA_FILE_ALIGNMENT==1 -static const unsigned int dummy_align__404_html = 1; -#endif -static const unsigned char FSDATA_ALIGN_PRE data__404_html[] FSDATA_ALIGN_POST = { -/* /404.html (10 chars) */ -0x2f,0x34,0x30,0x34,0x2e,0x68,0x74,0x6d,0x6c,0x00,0x00,0x00, - -/* HTTP header */ -/* "HTTP/1.0 404 File not found -" (29 bytes) */ -0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x34,0x30,0x34,0x20,0x46,0x69,0x6c, -0x65,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x0d,0x0a, -/* "Server: lwIP/2.0.3d (http://savannah.nongnu.org/projects/lwip) -" (64 bytes) */ -0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x32,0x2e,0x30, -0x2e,0x33,0x64,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61, -0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f, -0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, - -/* "Content-Length: 565 -" (18+ bytes) */ -0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20, -0x35,0x36,0x35,0x0d,0x0a, -/* "Content-Type: text/html - -" (27 bytes) */ -0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65, -0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a, -/* raw file data (565 bytes) */ -0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74, -0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69, -0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50, -0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f, -0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63, -0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78, -0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20, -0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22, -0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74, -0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c, -0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20, -0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, -0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, -0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69, -0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20, -0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d, -0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c, -0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f, -0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69, -0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09, -0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c, -0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49, -0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20, -0x20,0x3c,0x68,0x32,0x3e,0x34,0x30,0x34,0x20,0x2d,0x20,0x50,0x61,0x67,0x65,0x20, -0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x3c,0x2f,0x68,0x32,0x3e,0x0d,0x0a, -0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x53,0x6f,0x72, -0x72,0x79,0x2c,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75, -0x20,0x61,0x72,0x65,0x20,0x72,0x65,0x71,0x75,0x65,0x73,0x74,0x69,0x6e,0x67,0x20, -0x77,0x61,0x73,0x20,0x6e,0x6f,0x74,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x6f,0x6e, -0x20,0x74,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76, -0x65,0x72,0x2e,0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09, -0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e, -0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72, -0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65, -0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74, -0x6d,0x6c,0x3e,0x0d,0x0a,}; - -#if FSDATA_FILE_ALIGNMENT==1 -static const unsigned int dummy_align__index_html = 2; -#endif -static const unsigned char FSDATA_ALIGN_PRE data__index_html[] FSDATA_ALIGN_POST = { -/* /index.html (12 chars) */ -0x2f,0x69,0x6e,0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,0x00, - -/* HTTP header */ -/* "HTTP/1.0 200 OK -" (17 bytes) */ -0x48,0x54,0x54,0x50,0x2f,0x31,0x2e,0x30,0x20,0x32,0x30,0x30,0x20,0x4f,0x4b,0x0d, -0x0a, -/* "Server: lwIP/2.0.3d (http://savannah.nongnu.org/projects/lwip) -" (64 bytes) */ -0x53,0x65,0x72,0x76,0x65,0x72,0x3a,0x20,0x6c,0x77,0x49,0x50,0x2f,0x32,0x2e,0x30, -0x2e,0x33,0x64,0x20,0x28,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61, -0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f, -0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x29,0x0d,0x0a, - -/* "Content-Length: 1751 -" (18+ bytes) */ -0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x4c,0x65,0x6e,0x67,0x74,0x68,0x3a,0x20, -0x31,0x37,0x35,0x31,0x0d,0x0a, -/* "Content-Type: text/html - -" (27 bytes) */ -0x43,0x6f,0x6e,0x74,0x65,0x6e,0x74,0x2d,0x54,0x79,0x70,0x65,0x3a,0x20,0x74,0x65, -0x78,0x74,0x2f,0x68,0x74,0x6d,0x6c,0x0d,0x0a,0x0d,0x0a, -/* raw file data (1751 bytes) */ -0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0d,0x0a,0x3c,0x68,0x65,0x61,0x64,0x3e,0x3c,0x74, -0x69,0x74,0x6c,0x65,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c,0x69, -0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50, -0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x74,0x69,0x74,0x6c,0x65,0x3e,0x3c,0x2f, -0x68,0x65,0x61,0x64,0x3e,0x0d,0x0a,0x3c,0x62,0x6f,0x64,0x79,0x20,0x62,0x67,0x63, -0x6f,0x6c,0x6f,0x72,0x3d,0x22,0x77,0x68,0x69,0x74,0x65,0x22,0x20,0x74,0x65,0x78, -0x74,0x3d,0x22,0x62,0x6c,0x61,0x63,0x6b,0x22,0x3e,0x0d,0x0a,0x0d,0x0a,0x20,0x20, -0x20,0x20,0x3c,0x74,0x61,0x62,0x6c,0x65,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22, -0x31,0x30,0x30,0x25,0x22,0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x74, -0x72,0x20,0x76,0x61,0x6c,0x69,0x67,0x6e,0x3d,0x22,0x74,0x6f,0x70,0x22,0x3e,0x3c, -0x74,0x64,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x38,0x30,0x22,0x3e,0x09,0x20, -0x20,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x61,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, -0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, -0x65,0x2f,0x22,0x3e,0x3c,0x69,0x6d,0x67,0x20,0x73,0x72,0x63,0x3d,0x22,0x2f,0x69, -0x6d,0x67,0x2f,0x73,0x69,0x63,0x73,0x2e,0x67,0x69,0x66,0x22,0x0d,0x0a,0x09,0x20, -0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3d,0x22,0x30,0x22,0x20,0x61,0x6c,0x74,0x3d, -0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x20,0x74,0x69,0x74,0x6c, -0x65,0x3d,0x22,0x53,0x49,0x43,0x53,0x20,0x6c,0x6f,0x67,0x6f,0x22,0x3e,0x3c,0x2f, -0x61,0x3e,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x20,0x77,0x69, -0x64,0x74,0x68,0x3d,0x22,0x35,0x30,0x30,0x22,0x3e,0x09,0x20,0x20,0x0d,0x0a,0x09, -0x20,0x20,0x3c,0x68,0x31,0x3e,0x6c,0x77,0x49,0x50,0x20,0x2d,0x20,0x41,0x20,0x4c, -0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67,0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49, -0x50,0x20,0x53,0x74,0x61,0x63,0x6b,0x3c,0x2f,0x68,0x31,0x3e,0x0d,0x0a,0x09,0x20, -0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x77, -0x65,0x62,0x20,0x70,0x61,0x67,0x65,0x20,0x79,0x6f,0x75,0x20,0x61,0x72,0x65,0x20, -0x77,0x61,0x74,0x63,0x68,0x69,0x6e,0x67,0x20,0x77,0x61,0x73,0x20,0x73,0x65,0x72, -0x76,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x73,0x69,0x6d,0x70,0x6c,0x65,0x20, -0x77,0x65,0x62,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x65,0x72,0x76,0x65,0x72, -0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,0x20,0x6f,0x6e,0x20,0x74,0x6f,0x70,0x20, -0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x69,0x67,0x68,0x74,0x77,0x65,0x69,0x67, -0x68,0x74,0x20,0x54,0x43,0x50,0x2f,0x49,0x50,0x20,0x73,0x74,0x61,0x63,0x6b,0x20, -0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68, -0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73, -0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f,0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x6c, -0x77,0x49,0x50,0x3c,0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70, -0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20, -0x6c,0x77,0x49,0x50,0x20,0x69,0x73,0x20,0x61,0x6e,0x20,0x6f,0x70,0x65,0x6e,0x20, -0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, -0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x54,0x43,0x50, -0x2f,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x74,0x6f,0x63, -0x6f,0x6c,0x20,0x73,0x75,0x69,0x74,0x65,0x20,0x74,0x68,0x61,0x74,0x20,0x77,0x61, -0x73,0x20,0x6f,0x72,0x69,0x67,0x69,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x77,0x72,0x69, -0x74,0x74,0x65,0x6e,0x20,0x62,0x79,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20, -0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x77, -0x77,0x2e,0x73,0x69,0x63,0x73,0x2e,0x73,0x65,0x2f,0x7e,0x61,0x64,0x61,0x6d,0x2f, -0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x41,0x64,0x61,0x6d,0x20,0x44,0x75,0x6e,0x6b, -0x65,0x6c,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x66,0x20,0x74,0x68,0x65, -0x20,0x53,0x77,0x65,0x64,0x69,0x73,0x68,0x20,0x49,0x6e,0x73,0x74,0x69,0x74,0x75, -0x74,0x65,0x20,0x6f,0x66,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x20,0x53, -0x63,0x69,0x65,0x6e,0x63,0x65,0x3c,0x2f,0x61,0x3e,0x20,0x62,0x75,0x74,0x20,0x6e, -0x6f,0x77,0x20,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x62,0x65,0x69,0x6e, -0x67,0x20,0x61,0x63,0x74,0x69,0x76,0x65,0x6c,0x79,0x20,0x64,0x65,0x76,0x65,0x6c, -0x6f,0x70,0x65,0x64,0x20,0x62,0x79,0x20,0x61,0x20,0x74,0x65,0x61,0x6d,0x20,0x6f, -0x66,0x20,0x64,0x65,0x76,0x65,0x6c,0x6f,0x70,0x65,0x72,0x73,0x0d,0x0a,0x09,0x20, -0x20,0x20,0x20,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x64,0x20,0x77, -0x6f,0x72,0x6c,0x64,0x2d,0x77,0x69,0x64,0x65,0x2e,0x20,0x53,0x69,0x6e,0x63,0x65, -0x20,0x69,0x74,0x27,0x73,0x20,0x72,0x65,0x6c,0x65,0x61,0x73,0x65,0x2c,0x20,0x6c, -0x77,0x49,0x50,0x20,0x68,0x61,0x73,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x73,0x70, -0x75,0x72,0x72,0x65,0x64,0x20,0x61,0x20,0x6c,0x6f,0x74,0x20,0x6f,0x66,0x20,0x69, -0x6e,0x74,0x65,0x72,0x65,0x73,0x74,0x20,0x61,0x6e,0x64,0x20,0x68,0x61,0x73,0x20, -0x62,0x65,0x65,0x6e,0x20,0x70,0x6f,0x72,0x74,0x65,0x64,0x20,0x74,0x6f,0x20,0x73, -0x65,0x76,0x65,0x72,0x61,0x6c,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x70,0x6c,0x61, -0x74,0x66,0x6f,0x72,0x6d,0x73,0x20,0x61,0x6e,0x64,0x20,0x6f,0x70,0x65,0x72,0x61, -0x74,0x69,0x6e,0x67,0x20,0x73,0x79,0x73,0x74,0x65,0x6d,0x73,0x2e,0x20,0x6c,0x77, -0x49,0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x20,0x65, -0x69,0x74,0x68,0x65,0x72,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x77,0x69,0x74,0x68, -0x20,0x6f,0x72,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x61,0x6e,0x20,0x75, -0x6e,0x64,0x65,0x72,0x6c,0x79,0x69,0x6e,0x67,0x20,0x4f,0x53,0x2e,0x0d,0x0a,0x09, -0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d,0x0a, -0x09,0x20,0x20,0x20,0x20,0x54,0x68,0x65,0x20,0x66,0x6f,0x63,0x75,0x73,0x20,0x6f, -0x66,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x54,0x43,0x50,0x2f,0x49, -0x50,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e, -0x20,0x69,0x73,0x20,0x74,0x6f,0x20,0x72,0x65,0x64,0x75,0x63,0x65,0x0d,0x0a,0x09, -0x20,0x20,0x20,0x20,0x74,0x68,0x65,0x20,0x52,0x41,0x4d,0x20,0x75,0x73,0x61,0x67, -0x65,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x73,0x74,0x69,0x6c,0x6c,0x20,0x68,0x61, -0x76,0x69,0x6e,0x67,0x20,0x61,0x20,0x66,0x75,0x6c,0x6c,0x20,0x73,0x63,0x61,0x6c, -0x65,0x20,0x54,0x43,0x50,0x2e,0x20,0x54,0x68,0x69,0x73,0x0d,0x0a,0x09,0x20,0x20, -0x20,0x20,0x6d,0x61,0x6b,0x65,0x73,0x20,0x6c,0x77,0x49,0x50,0x20,0x73,0x75,0x69, -0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f,0x72,0x20,0x75,0x73,0x65,0x20,0x69,0x6e, -0x20,0x65,0x6d,0x62,0x65,0x64,0x64,0x65,0x64,0x20,0x73,0x79,0x73,0x74,0x65,0x6d, -0x73,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x65,0x6e,0x73,0x0d,0x0a,0x09,0x20,0x20, -0x20,0x20,0x6f,0x66,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x20,0x6f, -0x66,0x20,0x66,0x72,0x65,0x65,0x20,0x52,0x41,0x4d,0x20,0x61,0x6e,0x64,0x20,0x72, -0x6f,0x6f,0x6d,0x20,0x66,0x6f,0x72,0x20,0x61,0x72,0x6f,0x75,0x6e,0x64,0x20,0x34, -0x30,0x20,0x6b,0x69,0x6c,0x6f,0x62,0x79,0x74,0x65,0x73,0x0d,0x0a,0x09,0x20,0x20, -0x20,0x20,0x6f,0x66,0x20,0x63,0x6f,0x64,0x65,0x20,0x52,0x4f,0x4d,0x2e,0x0d,0x0a, -0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x70,0x3e,0x0d, -0x0a,0x09,0x20,0x20,0x20,0x20,0x4d,0x6f,0x72,0x65,0x20,0x69,0x6e,0x66,0x6f,0x72, -0x6d,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x62,0x6f,0x75,0x74,0x20,0x6c,0x77,0x49, -0x50,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x66,0x6f,0x75,0x6e,0x64,0x20,0x61, -0x74,0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x0d,0x0a,0x09,0x20,0x20,0x20, -0x20,0x68,0x6f,0x6d,0x65,0x70,0x61,0x67,0x65,0x20,0x61,0x74,0x20,0x3c,0x61,0x0d, -0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x68,0x74,0x74,0x70, -0x3a,0x2f,0x2f,0x73,0x61,0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67, -0x6e,0x75,0x2e,0x6f,0x72,0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f, -0x6c,0x77,0x69,0x70,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x73,0x61, -0x76,0x61,0x6e,0x6e,0x61,0x68,0x2e,0x6e,0x6f,0x6e,0x67,0x6e,0x75,0x2e,0x6f,0x72, -0x67,0x2f,0x70,0x72,0x6f,0x6a,0x65,0x63,0x74,0x73,0x2f,0x6c,0x77,0x69,0x70,0x2f, -0x3c,0x2f,0x61,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x6f,0x72,0x20,0x61,0x74, -0x20,0x74,0x68,0x65,0x20,0x6c,0x77,0x49,0x50,0x20,0x77,0x69,0x6b,0x69,0x20,0x61, -0x74,0x20,0x3c,0x61,0x0d,0x0a,0x09,0x20,0x20,0x20,0x20,0x68,0x72,0x65,0x66,0x3d, -0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b, -0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x22,0x3e,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, -0x6c,0x77,0x69,0x70,0x2e,0x77,0x69,0x6b,0x69,0x61,0x2e,0x63,0x6f,0x6d,0x2f,0x3c, -0x2f,0x61,0x3e,0x2e,0x0d,0x0a,0x09,0x20,0x20,0x3c,0x2f,0x70,0x3e,0x0d,0x0a,0x09, -0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x74,0x64,0x3e,0x0d,0x0a,0x09,0x20,0x20,0x26,0x6e, -0x62,0x73,0x70,0x3b,0x0d,0x0a,0x09,0x3c,0x2f,0x74,0x64,0x3e,0x3c,0x2f,0x74,0x72, -0x3e,0x0d,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x2f,0x74,0x61,0x62,0x6c,0x65, -0x3e,0x0d,0x0a,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0d,0x0a,0x3c,0x2f,0x68,0x74, -0x6d,0x6c,0x3e,0x0d,0x0a,0x0d,0x0a,}; - - - -const struct fsdata_file file__img_sics_gif[] = { { -file_NULL, -data__img_sics_gif, -data__img_sics_gif + 16, -sizeof(data__img_sics_gif) - 16, -FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT, -}}; - -const struct fsdata_file file__404_html[] = { { -file__img_sics_gif, -data__404_html, -data__404_html + 12, -sizeof(data__404_html) - 12, -FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT, -}}; - -const struct fsdata_file file__index_html[] = { { -file__404_html, -data__index_html, -data__index_html + 12, -sizeof(data__index_html) - 12, -FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT, -}}; - -#define FS_ROOT file__index_html -#define FS_NUMFILES 3 - diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/fsdata.h b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/fsdata.h deleted file mode 100644 index d31550d71..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/fsdata.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * - */ -#ifndef LWIP_FSDATA_H -#define LWIP_FSDATA_H - -#include "lwip/apps/httpd_opts.h" -#include "lwip/apps/fs.h" - -/* THIS FILE IS DEPRECATED AND WILL BE REMOVED IN THE FUTURE */ -/* content was moved to fs.h to simplify #include structure */ - -#endif /* LWIP_FSDATA_H */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/http_client.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/http_client.c deleted file mode 100644 index 9d6ca9cf3..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/http_client.c +++ /dev/null @@ -1,910 +0,0 @@ -/** - * @file - * HTTP client - */ - -/* - * Copyright (c) 2018 Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - */ - -/** - * @defgroup httpc HTTP client - * @ingroup apps - * @todo: - * - persistent connections - * - select outgoing http version - * - optionally follow redirect - * - check request uri for invalid characters? (e.g. encode spaces) - * - IPv6 support - */ - -#include "lwip/apps/http_client.h" - -#include "lwip/altcp_tcp.h" -#include "lwip/dns.h" -#include "lwip/debug.h" -#include "lwip/mem.h" -#include "lwip/altcp_tls.h" -#include "lwip/init.h" - -#include -#include -#include - -#if LWIP_TCP && LWIP_CALLBACK_API - -/** - * HTTPC_DEBUG: Enable debugging for HTTP client. - */ -#ifndef HTTPC_DEBUG -#define HTTPC_DEBUG LWIP_DBG_ON -// #define HTTPC_DEBUG LWIP_DBG_OFF -#endif - -/** Set this to 1 to keep server name and uri in request state */ -#ifndef HTTPC_DEBUG_REQUEST -#define HTTPC_DEBUG_REQUEST 0 -#endif - -/** This string is passed in the HTTP header as "User-Agent: " */ -#ifndef HTTPC_CLIENT_AGENT -#define HTTPC_CLIENT_AGENT "lwIP/" LWIP_VERSION_STRING " (http://savannah.nongnu.org/projects/lwip)" -#endif - -/* the various debug levels for this file */ -#define HTTPC_DEBUG_TRACE (HTTPC_DEBUG | LWIP_DBG_TRACE) -#define HTTPC_DEBUG_STATE (HTTPC_DEBUG | LWIP_DBG_STATE) -#define HTTPC_DEBUG_WARN (HTTPC_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define HTTPC_DEBUG_WARN_STATE (HTTPC_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) -#define HTTPC_DEBUG_SERIOUS (HTTPC_DEBUG | LWIP_DBG_LEVEL_SERIOUS) - -#define HTTPC_POLL_INTERVAL 1 -#define HTTPC_POLL_TIMEOUT 30 /* 15 seconds */ - -#define HTTPC_CONTENT_LEN_INVALID 0xFFFFFFFF - -/* GET request basic */ -#define HTTPC_REQ_11 "GET %s HTTP/1.1\r\n" /* URI */\ - "User-Agent: %s\r\n" /* User-Agent */ \ - "Accept: */*\r\n" \ - "Connection: Close\r\n" /* we don't support persistent connections, yet */ \ - "\r\n" -#define HTTPC_REQ_11_FORMAT(uri) HTTPC_REQ_11, uri, HTTPC_CLIENT_AGENT - -/* GET request with host */ -#define HTTPC_REQ_11_HOST "GET %s HTTP/1.1\r\n" /* URI */\ - "User-Agent: %s\r\n" /* User-Agent */ \ - "Accept: */*\r\n" \ - "Host: %s\r\n" /* server name */ \ - "Connection: Close\r\n" /* we don't support persistent connections, yet */ \ - "\r\n" -#define HTTPC_REQ_11_HOST_FORMAT(uri, srv_name) HTTPC_REQ_11_HOST, uri, HTTPC_CLIENT_AGENT, srv_name - -/* GET request with proxy */ -#define HTTPC_REQ_11_PROXY "GET http://%s%s HTTP/1.1\r\n" /* HOST, URI */\ - "User-Agent: %s\r\n" /* User-Agent */ \ - "Accept: */*\r\n" \ - "Host: %s\r\n" /* server name */ \ - "Connection: Close\r\n" /* we don't support persistent connections, yet */ \ - "\r\n" -#define HTTPC_REQ_11_PROXY_FORMAT(host, uri, srv_name) HTTPC_REQ_11_PROXY, host, uri, HTTPC_CLIENT_AGENT, srv_name - -/* GET request with proxy (non-default server port) */ -#define HTTPC_REQ_11_PROXY_PORT "GET http://%s:%d%s HTTP/1.1\r\n" /* HOST, host-port, URI */\ - "User-Agent: %s\r\n" /* User-Agent */ \ - "Accept: */*\r\n" \ - "Host: %s\r\n" /* server name */ \ - "Connection: Close\r\n" /* we don't support persistent connections, yet */ \ - "\r\n" -#define HTTPC_REQ_11_PROXY_PORT_FORMAT(host, host_port, uri, srv_name) HTTPC_REQ_11_PROXY_PORT, host, host_port, uri, HTTPC_CLIENT_AGENT, srv_name - -typedef enum ehttpc_parse_state { - HTTPC_PARSE_WAIT_FIRST_LINE = 0, - HTTPC_PARSE_WAIT_HEADERS, - HTTPC_PARSE_RX_DATA -} httpc_parse_state_t; - -typedef struct _httpc_state -{ - struct altcp_pcb* pcb; - ip_addr_t remote_addr; - u16_t remote_port; - int timeout_ticks; - struct pbuf *request; - struct pbuf *rx_hdrs; - u16_t rx_http_version; - u16_t rx_status; - altcp_recv_fn recv_fn; - const httpc_connection_t *conn_settings; - void* callback_arg; - u32_t rx_content_len; - u32_t hdr_content_len; - httpc_parse_state_t parse_state; -#if HTTPC_DEBUG_REQUEST - char* server_name; - char* uri; -#endif -} httpc_state_t; - -/** Free http client state and deallocate all resources within */ -static err_t -httpc_free_state(httpc_state_t* req) -{ - struct altcp_pcb* tpcb; - - if (req->request != NULL) { - pbuf_free(req->request); - req->request = NULL; - } - if (req->rx_hdrs != NULL) { - pbuf_free(req->rx_hdrs); - req->rx_hdrs = NULL; - } - - tpcb = req->pcb; - mem_free(req); - req = NULL; - - if (tpcb != NULL) { - err_t r; - altcp_arg(tpcb, NULL); - altcp_recv(tpcb, NULL); - altcp_err(tpcb, NULL); - altcp_poll(tpcb, NULL, 0); - altcp_sent(tpcb, NULL); - r = altcp_close(tpcb); - if (r != ERR_OK) { - altcp_abort(tpcb); - return ERR_ABRT; - } - } - return ERR_OK; -} - -/** Close the connection: call finished callback and free the state */ -static err_t -httpc_close(httpc_state_t* req, httpc_result_t result, u32_t server_response, err_t err) -{ - if (req != NULL) { - if (req->conn_settings != NULL) { - if (req->conn_settings->result_fn != NULL) { - req->conn_settings->result_fn(req->callback_arg, result, req->rx_content_len, server_response, err); - } - } - return httpc_free_state(req); - } - return ERR_OK; -} - -/** Parse http header response line 1 */ -static err_t -http_parse_response_status(struct pbuf *p, u16_t *http_version, u16_t *http_status, u16_t *http_status_str_offset) -{ - u16_t end1 = pbuf_memfind(p, "\r\n", 2, 0); - if (end1 != 0xFFFF) { - /* get parts of first line */ - u16_t space1, space2; - space1 = pbuf_memfind(p, " ", 1, 0); - if (space1 != 0xFFFF) { - if ((pbuf_memcmp(p, 0, "HTTP/", 5) == 0) && (pbuf_get_at(p, 6) == '.')) { - char status_num[10]; - size_t status_num_len; - /* parse http version */ - u16_t version = pbuf_get_at(p, 5) - '0'; - version <<= 8; - version |= pbuf_get_at(p, 7) - '0'; - *http_version = version; - - /* parse http status number */ - space2 = pbuf_memfind(p, " ", 1, space1 + 1); - if (space2 != 0xFFFF) { - *http_status_str_offset = space2 + 1; - status_num_len = space2 - space1 - 1; - } else { - status_num_len = end1 - space1 - 1; - } - memset(status_num, 0, sizeof(status_num)); - if (pbuf_copy_partial(p, status_num, (u16_t)status_num_len, space1 + 1) == status_num_len) { - int status = atoi(status_num); - if ((status > 0) && (status <= 0xFFFF)) { - *http_status = (u16_t)status; - return ERR_OK; - } - } - } - } - } - return ERR_VAL; -} - -/** Wait for all headers to be received, return its length and content-length (if available) */ -static err_t -http_wait_headers(struct pbuf *p, u32_t *content_length, u16_t *total_header_len) -{ - u16_t end1 = pbuf_memfind(p, "\r\n\r\n", 4, 0); - if (end1 < (0xFFFF - 2)) { - /* all headers received */ - /* check if we have a content length (@todo: case insensitive?) */ - u16_t content_len_hdr; - *content_length = HTTPC_CONTENT_LEN_INVALID; - *total_header_len = end1 + 4; - - content_len_hdr = pbuf_memfind(p, "Content-Length: ", 16, 0); - if (content_len_hdr != 0xFFFF) { - u16_t content_len_line_end = pbuf_memfind(p, "\r\n", 2, content_len_hdr); - if (content_len_line_end != 0xFFFF) { - char content_len_num[16]; - u16_t content_len_num_len = (u16_t)(content_len_line_end - content_len_hdr - 16); - memset(content_len_num, 0, sizeof(content_len_num)); - if (pbuf_copy_partial(p, content_len_num, content_len_num_len, content_len_hdr + 16) == content_len_num_len) { - int len = atoi(content_len_num); - if ((len >= 0) && ((u32_t)len < HTTPC_CONTENT_LEN_INVALID)) { - *content_length = (u32_t)len; - } - } - } - } - return ERR_OK; - } - return ERR_VAL; -} - -/** http client tcp recv callback */ -static err_t -httpc_tcp_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t r) -{ - httpc_state_t* req = (httpc_state_t*)arg; - LWIP_UNUSED_ARG(r); - - if (p == NULL) { - httpc_result_t result; - if (req->parse_state != HTTPC_PARSE_RX_DATA) { - /* did not get RX data yet */ - result = HTTPC_RESULT_ERR_CLOSED; - } else if ((req->hdr_content_len != HTTPC_CONTENT_LEN_INVALID) && - (req->hdr_content_len != req->rx_content_len)) { - /* header has been received with content length but not all data received */ - result = HTTPC_RESULT_ERR_CONTENT_LEN; - } else { - /* receiving data and either all data received or no content length header */ - result = HTTPC_RESULT_OK; - } - return httpc_close(req, result, req->rx_status, ERR_OK); - } - if (req->parse_state != HTTPC_PARSE_RX_DATA) { - if (req->rx_hdrs == NULL) { - req->rx_hdrs = p; - } else { - pbuf_cat(req->rx_hdrs, p); - } - if (req->parse_state == HTTPC_PARSE_WAIT_FIRST_LINE) { - u16_t status_str_off; - err_t err = http_parse_response_status(req->rx_hdrs, &req->rx_http_version, &req->rx_status, &status_str_off); - if (err == ERR_OK) { - /* don't care status string */ - req->parse_state = HTTPC_PARSE_WAIT_HEADERS; - } - } - if (req->parse_state == HTTPC_PARSE_WAIT_HEADERS) { - u16_t total_header_len; - err_t err = http_wait_headers(req->rx_hdrs, &req->hdr_content_len, &total_header_len); - if (err == ERR_OK) { - struct pbuf *q; - /* full header received, send window update for header bytes and call into client callback */ - altcp_recved(pcb, total_header_len); - if (req->conn_settings) { - if (req->conn_settings->headers_done_fn) { - err = req->conn_settings->headers_done_fn(req, req->callback_arg, req->rx_hdrs, total_header_len, req->hdr_content_len); - if (err != ERR_OK) { - return httpc_close(req, HTTPC_RESULT_LOCAL_ABORT, req->rx_status, err); - } - } - } - /* hide header bytes in pbuf */ - q = pbuf_free_header(req->rx_hdrs, total_header_len); - p = q; - req->rx_hdrs = NULL; - /* go on with data */ - req->parse_state = HTTPC_PARSE_RX_DATA; - } - } - } - if ((p != NULL) && (req->parse_state == HTTPC_PARSE_RX_DATA)) { - req->rx_content_len += p->tot_len; - if (req->recv_fn != NULL) { - /* directly return here: the connection migth already be aborted from the callback! */ - return req->recv_fn(req->callback_arg, pcb, p, r); - } else { - altcp_recved(pcb, p->tot_len); - pbuf_free(p); - } - } - return ERR_OK; -} - -/** http client tcp err callback */ -static void -httpc_tcp_err(void *arg, err_t err) -{ - httpc_state_t* req = (httpc_state_t*)arg; - if (req != NULL) { - /* pcb has already been deallocated */ - req->pcb = NULL; - httpc_close(req, HTTPC_RESULT_ERR_CLOSED, 0, err); - } -} - -/** http client tcp poll callback */ -static err_t -httpc_tcp_poll(void *arg, struct altcp_pcb *pcb) -{ - /* implement timeout */ - httpc_state_t* req = (httpc_state_t*)arg; - LWIP_UNUSED_ARG(pcb); - if (req != NULL) { - if (req->timeout_ticks) { - req->timeout_ticks--; - } - if (!req->timeout_ticks) { - return httpc_close(req, HTTPC_RESULT_ERR_TIMEOUT, 0, ERR_OK); - } - } - return ERR_OK; -} - -/** http client tcp sent callback */ -static err_t -httpc_tcp_sent(void *arg, struct altcp_pcb *pcb, u16_t len) -{ - /* nothing to do here for now */ - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(len); - return ERR_OK; -} - -/** http client tcp connected callback */ -static err_t -httpc_tcp_connected(void *arg, struct altcp_pcb *pcb, err_t err) -{ - err_t r; - httpc_state_t* req = (httpc_state_t*)arg; - LWIP_UNUSED_ARG(pcb); - LWIP_UNUSED_ARG(err); - - /* send request; last char is zero termination */ - r = altcp_write(req->pcb, req->request->payload, req->request->len - 1, TCP_WRITE_FLAG_COPY); - if (r != ERR_OK) { - /* could not write the single small request -> fail, don't retry */ - return httpc_close(req, HTTPC_RESULT_ERR_MEM, 0, r); - } - /* everything written, we can free the request */ - pbuf_free(req->request); - req->request = NULL; - - altcp_output(req->pcb); - return ERR_OK; -} - -/** Start the http request when the server IP addr is known */ -static err_t -httpc_get_internal_addr(httpc_state_t* req, const ip_addr_t *ipaddr) -{ - err_t err; - LWIP_ASSERT("req != NULL", req != NULL); - - if (&req->remote_addr != ipaddr) { - /* fill in remote addr if called externally */ - req->remote_addr = *ipaddr; - } - - err = altcp_connect(req->pcb, &req->remote_addr, req->remote_port, httpc_tcp_connected); - if (err == ERR_OK) { - return ERR_OK; - } - LWIP_DEBUGF(HTTPC_DEBUG_WARN_STATE, ("tcp_connect failed: %d\n", (int)err)); - return err; -} - -#if LWIP_DNS -/** DNS callback - * If ipaddr is non-NULL, resolving succeeded and the request can be sent, otherwise it failed. - */ -static void -httpc_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg) -{ - httpc_state_t* req = (httpc_state_t*)arg; - err_t err; - httpc_result_t result; - - LWIP_UNUSED_ARG(hostname); - - if (ipaddr != NULL) { - err = httpc_get_internal_addr(req, ipaddr); - if (err == ERR_OK) { - return; - } - result = HTTPC_RESULT_ERR_CONNECT; - } else { - LWIP_DEBUGF(HTTPC_DEBUG_WARN_STATE, ("httpc_dns_found: failed to resolve hostname: %s\n", - hostname)); - result = HTTPC_RESULT_ERR_HOSTNAME; - err = ERR_ARG; - } - httpc_close(req, result, 0, err); -} -#endif /* LWIP_DNS */ - -/** Start the http request after converting 'server_name' to ip address (DNS or address string) */ -static err_t -httpc_get_internal_dns(httpc_state_t* req, const char* server_name) -{ - err_t err; - LWIP_ASSERT("req != NULL", req != NULL); - -#if LWIP_DNS - err = dns_gethostbyname(server_name, &req->remote_addr, httpc_dns_found, req); -#else - err = ipaddr_aton(server_name, &req->remote_addr) ? ERR_OK : ERR_ARG; -#endif - - if (err == ERR_OK) { - /* cached or IP-string */ - err = httpc_get_internal_addr(req, &req->remote_addr); - } else if (err == ERR_INPROGRESS) { - return ERR_OK; - } - return err; -} - -static int -httpc_create_request_string(const httpc_connection_t *settings, const char* server_name, int server_port, const char* uri, - int use_host, char *buffer, size_t buffer_size) -{ - if (settings->use_proxy) { - LWIP_ASSERT("server_name != NULL", server_name != NULL); - if (server_port != HTTP_DEFAULT_PORT) { - return snprintf(buffer, buffer_size, HTTPC_REQ_11_PROXY_PORT_FORMAT(server_name, server_port, uri, server_name)); - } else { - return snprintf(buffer, buffer_size, HTTPC_REQ_11_PROXY_FORMAT(server_name, uri, server_name)); - } - } else if (use_host) { - LWIP_ASSERT("server_name != NULL", server_name != NULL); - return snprintf(buffer, buffer_size, HTTPC_REQ_11_HOST_FORMAT(uri, server_name)); - } else { - return snprintf(buffer, buffer_size, HTTPC_REQ_11_FORMAT(uri)); - } -} - -/** Initialize the connection struct */ -static err_t -httpc_init_connection_common(httpc_state_t **connection, const httpc_connection_t *settings, const char* server_name, - u16_t server_port, const char* uri, altcp_recv_fn recv_fn, void* callback_arg, int use_host) -{ - size_t alloc_len; - mem_size_t mem_alloc_len; - int req_len, req_len2; - httpc_state_t *req; -#if HTTPC_DEBUG_REQUEST - size_t server_name_len, uri_len; -#endif - - LWIP_ASSERT("uri != NULL", uri != NULL); - - /* get request len */ - req_len = httpc_create_request_string(settings, server_name, server_port, uri, use_host, NULL, 0); - if ((req_len < 0) || (req_len > 0xFFFF)) { - return ERR_VAL; - } - /* alloc state and request in one block */ - alloc_len = sizeof(httpc_state_t); -#if HTTPC_DEBUG_REQUEST - server_name_len = server_name ? strlen(server_name) : 0; - uri_len = strlen(uri); - alloc_len += server_name_len + 1 + uri_len + 1; -#endif - mem_alloc_len = (mem_size_t)alloc_len; - if ((mem_alloc_len < alloc_len) || (req_len + 1 > 0xFFFF)) { - return ERR_VAL; - } - - req = (httpc_state_t*)mem_malloc((mem_size_t)alloc_len); - if(req == NULL) { - return ERR_MEM; - } - memset(req, 0, sizeof(httpc_state_t)); - req->timeout_ticks = HTTPC_POLL_TIMEOUT; - req->request = pbuf_alloc(PBUF_RAW, (u16_t)(req_len + 1), PBUF_RAM); - if (req->request == NULL) { - httpc_free_state(req); - return ERR_MEM; - } - if (req->request->next != NULL) { - /* need a pbuf in one piece */ - httpc_free_state(req); - return ERR_MEM; - } - req->hdr_content_len = HTTPC_CONTENT_LEN_INVALID; -#if HTTPC_DEBUG_REQUEST - req->server_name = (char*)(req + 1); - if (server_name) { - memcpy(req->server_name, server_name, server_name_len + 1); - } - req->uri = req->server_name + server_name_len + 1; - memcpy(req->uri, uri, uri_len + 1); -#endif - req->pcb = altcp_new(settings->altcp_allocator); - if(req->pcb == NULL) { - httpc_free_state(req); - return ERR_MEM; - } - req->remote_port = settings->use_proxy ? settings->proxy_port : server_port; - altcp_arg(req->pcb, req); - altcp_recv(req->pcb, httpc_tcp_recv); - altcp_err(req->pcb, httpc_tcp_err); - altcp_poll(req->pcb, httpc_tcp_poll, HTTPC_POLL_INTERVAL); - altcp_sent(req->pcb, httpc_tcp_sent); - - /* set up request buffer */ - req_len2 = httpc_create_request_string(settings, server_name, server_port, uri, use_host, - (char *)req->request->payload, req_len + 1); - if (req_len2 != req_len) { - httpc_free_state(req); - return ERR_VAL; - } - - req->recv_fn = recv_fn; - req->conn_settings = settings; - req->callback_arg = callback_arg; - - *connection = req; - return ERR_OK; -} - -/** - * Initialize the connection struct - */ -static err_t -httpc_init_connection(httpc_state_t **connection, const httpc_connection_t *settings, const char* server_name, - u16_t server_port, const char* uri, altcp_recv_fn recv_fn, void* callback_arg) -{ - return httpc_init_connection_common(connection, settings, server_name, server_port, uri, recv_fn, callback_arg, 1); -} - - -/** - * Initialize the connection struct (from IP address) - */ -static err_t -httpc_init_connection_addr(httpc_state_t **connection, const httpc_connection_t *settings, - const ip_addr_t* server_addr, u16_t server_port, const char* uri, - altcp_recv_fn recv_fn, void* callback_arg) -{ - char *server_addr_str = ipaddr_ntoa(server_addr); - if (server_addr_str == NULL) { - return ERR_VAL; - } - return httpc_init_connection_common(connection, settings, server_addr_str, server_port, uri, - recv_fn, callback_arg, 1); -} - -/** - * @ingroup httpc - * HTTP client API: get a file by passing server IP address - * - * @param server_addr IP address of the server to connect - * @param port tcp port of the server - * @param uri uri to get from the server, remember leading "/"! - * @param settings connection settings (callbacks, proxy, etc.) - * @param recv_fn the http body (not the headers) are passed to this callback - * @param callback_arg argument passed to all the callbacks - * @param connection retreives the connection handle (to match in callbacks) - * @return ERR_OK if starting the request succeeds (callback_fn will be called later) - * or an error code - */ -err_t -httpc_get_file(const ip_addr_t* server_addr, u16_t port, const char* uri, const httpc_connection_t *settings, - altcp_recv_fn recv_fn, void* callback_arg, httpc_state_t **connection) -{ - err_t err; - httpc_state_t* req; - - LWIP_ERROR("invalid parameters", (server_addr != NULL) && (uri != NULL) && (recv_fn != NULL), return ERR_ARG;); - - err = httpc_init_connection_addr(&req, settings, server_addr, port, - uri, recv_fn, callback_arg); - if (err != ERR_OK) { - return err; - } - - if (settings->use_proxy) { - err = httpc_get_internal_addr(req, &settings->proxy_addr); - } else { - err = httpc_get_internal_addr(req, server_addr); - } - if(err != ERR_OK) { - httpc_free_state(req); - return err; - } - - if (connection != NULL) { - *connection = req; - } - return ERR_OK; -} - -/** - * @ingroup httpc - * HTTP client API: get a file by passing server name as string (DNS name or IP address string) - * - * @param server_name server name as string (DNS name or IP address string) - * @param port tcp port of the server - * @param uri uri to get from the server, remember leading "/"! - * @param settings connection settings (callbacks, proxy, etc.) - * @param recv_fn the http body (not the headers) are passed to this callback - * @param callback_arg argument passed to all the callbacks - * @param connection retreives the connection handle (to match in callbacks) - * @return ERR_OK if starting the request succeeds (callback_fn will be called later) - * or an error code - */ -err_t -httpc_get_file_dns(const char* server_name, u16_t port, const char* uri, const httpc_connection_t *settings, - altcp_recv_fn recv_fn, void* callback_arg, httpc_state_t **connection) -{ - err_t err; - httpc_state_t* req; - - LWIP_ERROR("invalid parameters", (server_name != NULL) && (uri != NULL) && (recv_fn != NULL), return ERR_ARG;); - - err = httpc_init_connection(&req, settings, server_name, port, uri, recv_fn, callback_arg); - if (err != ERR_OK) { - return err; - } - - if (settings->use_proxy) { - err = httpc_get_internal_addr(req, &settings->proxy_addr); - } else { - err = httpc_get_internal_dns(req, server_name); - } - if(err != ERR_OK) { - httpc_free_state(req); - return err; - } - - if (connection != NULL) { - *connection = req; - } - return ERR_OK; -} - -#if LWIP_HTTPC_HAVE_FILE_IO -/* Implementation to disk via fopen/fwrite/fclose follows */ - -typedef struct _httpc_filestate -{ - const char* local_file_name; - FILE *file; - httpc_connection_t settings; - const httpc_connection_t *client_settings; - void *callback_arg; -} httpc_filestate_t; - -static void httpc_fs_result(void *arg, httpc_result_t httpc_result, u32_t rx_content_len, - u32_t srv_res, err_t err); - -/** Initalize http client state for download to file system */ -static err_t -httpc_fs_init(httpc_filestate_t **filestate_out, const char* local_file_name, - const httpc_connection_t *settings, void* callback_arg) -{ - httpc_filestate_t *filestate; - size_t file_len, alloc_len; - FILE *f; - - file_len = strlen(local_file_name); - alloc_len = sizeof(httpc_filestate_t) + file_len + 1; - - filestate = (httpc_filestate_t *)mem_malloc((mem_size_t)alloc_len); - if (filestate == NULL) { - return ERR_MEM; - } - memset(filestate, 0, sizeof(httpc_filestate_t)); - filestate->local_file_name = (const char *)(filestate + 1); - memcpy((char *)(filestate + 1), local_file_name, file_len + 1); - filestate->file = NULL; - filestate->client_settings = settings; - filestate->callback_arg = callback_arg; - /* copy client settings but override result callback */ - memcpy(&filestate->settings, settings, sizeof(httpc_connection_t)); - filestate->settings.result_fn = httpc_fs_result; - - f = fopen(local_file_name, "wb"); - if(f == NULL) { - /* could not open file */ - mem_free(filestate); - return ERR_VAL; - } - filestate->file = f; - *filestate_out = filestate; - return ERR_OK; -} - -/** Free http client state for download to file system */ -static void -httpc_fs_free(httpc_filestate_t *filestate) -{ - if (filestate != NULL) { - if (filestate->file != NULL) { - fclose(filestate->file); - filestate->file = NULL; - } - mem_free(filestate); - } -} - -/** Connection closed (success or error) */ -static void -httpc_fs_result(void *arg, httpc_result_t httpc_result, u32_t rx_content_len, - u32_t srv_res, err_t err) -{ - httpc_filestate_t *filestate = (httpc_filestate_t *)arg; - if (filestate != NULL) { - if (filestate->client_settings->result_fn != NULL) { - filestate->client_settings->result_fn(filestate->callback_arg, httpc_result, rx_content_len, - srv_res, err); - } - httpc_fs_free(filestate); - } -} - -/** tcp recv callback */ -static err_t -httpc_fs_tcp_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err) -{ - httpc_filestate_t *filestate = (httpc_filestate_t*)arg; - struct pbuf* q; - LWIP_UNUSED_ARG(err); - - LWIP_ASSERT("p != NULL", p != NULL); - - for (q = p; q != NULL; q = q->next) { - fwrite(q->payload, 1, q->len, filestate->file); - } - altcp_recved(pcb, p->tot_len); - pbuf_free(p); - return ERR_OK; -} - -/** - * @ingroup httpc - * HTTP client API: get a file to disk by passing server IP address - * - * @param server_addr IP address of the server to connect - * @param port tcp port of the server - * @param uri uri to get from the server, remember leading "/"! - * @param settings connection settings (callbacks, proxy, etc.) - * @param callback_arg argument passed to all the callbacks - * @param connection retreives the connection handle (to match in callbacks) - * @return ERR_OK if starting the request succeeds (callback_fn will be called later) - * or an error code - */ -err_t -httpc_get_file_to_disk(const ip_addr_t* server_addr, u16_t port, const char* uri, const httpc_connection_t *settings, - void* callback_arg, const char* local_file_name, httpc_state_t **connection) -{ - err_t err; - httpc_state_t* req; - httpc_filestate_t *filestate; - - LWIP_ERROR("invalid parameters", (server_addr != NULL) && (uri != NULL) && (local_file_name != NULL), return ERR_ARG;); - - err = httpc_fs_init(&filestate, local_file_name, settings, callback_arg); - if (err != ERR_OK) { - return err; - } - - err = httpc_init_connection_addr(&req, &filestate->settings, server_addr, port, - uri, httpc_fs_tcp_recv, filestate); - if (err != ERR_OK) { - httpc_fs_free(filestate); - return err; - } - - if (settings->use_proxy) { - err = httpc_get_internal_addr(req, &settings->proxy_addr); - } else { - err = httpc_get_internal_addr(req, server_addr); - } - if(err != ERR_OK) { - httpc_fs_free(filestate); - httpc_free_state(req); - return err; - } - - if (connection != NULL) { - *connection = req; - } - return ERR_OK; -} - -/** - * @ingroup httpc - * HTTP client API: get a file to disk by passing server name as string (DNS name or IP address string) - * - * @param server_name server name as string (DNS name or IP address string) - * @param port tcp port of the server - * @param uri uri to get from the server, remember leading "/"! - * @param settings connection settings (callbacks, proxy, etc.) - * @param callback_arg argument passed to all the callbacks - * @param connection retreives the connection handle (to match in callbacks) - * @return ERR_OK if starting the request succeeds (callback_fn will be called later) - * or an error code - */ -err_t -httpc_get_file_dns_to_disk(const char* server_name, u16_t port, const char* uri, const httpc_connection_t *settings, - void* callback_arg, const char* local_file_name, httpc_state_t **connection) -{ - err_t err; - httpc_state_t* req; - httpc_filestate_t *filestate; - - LWIP_ERROR("invalid parameters", (server_name != NULL) && (uri != NULL) && (local_file_name != NULL), return ERR_ARG;); - - err = httpc_fs_init(&filestate, local_file_name, settings, callback_arg); - if (err != ERR_OK) { - return err; - } - - err = httpc_init_connection(&req, &filestate->settings, server_name, port, - uri, httpc_fs_tcp_recv, filestate); - if (err != ERR_OK) { - httpc_fs_free(filestate); - return err; - } - - if (settings->use_proxy) { - err = httpc_get_internal_addr(req, &settings->proxy_addr); - } else { - err = httpc_get_internal_dns(req, server_name); - } - if(err != ERR_OK) { - httpc_fs_free(filestate); - httpc_free_state(req); - return err; - } - - if (connection != NULL) { - *connection = req; - } - return ERR_OK; -} -#endif /* LWIP_HTTPC_HAVE_FILE_IO */ - -#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/httpd.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/httpd.c deleted file mode 100644 index ccc9ba728..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/httpd.c +++ /dev/null @@ -1,2746 +0,0 @@ -/** - * @file - * LWIP HTTP server implementation - */ - -/* - * Copyright (c) 2001-2003 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Adam Dunkels - * Simon Goldschmidt - * - */ - -/** - * @defgroup httpd HTTP server - * @ingroup apps - * - * This httpd supports for a - * rudimentary server-side-include facility which will replace tags of the form - * in any file whose extension is .shtml, .shtm or .ssi with - * strings provided by an include handler whose pointer is provided to the - * module via function http_set_ssi_handler(). - * Additionally, a simple common - * gateway interface (CGI) handling mechanism has been added to allow clients - * to hook functions to particular request URIs. - * - * To enable SSI support, define label LWIP_HTTPD_SSI in lwipopts.h. - * To enable CGI support, define label LWIP_HTTPD_CGI in lwipopts.h. - * - * By default, the server assumes that HTTP headers are already present in - * each file stored in the file system. By defining LWIP_HTTPD_DYNAMIC_HEADERS in - * lwipopts.h, this behavior can be changed such that the server inserts the - * headers automatically based on the extension of the file being served. If - * this mode is used, be careful to ensure that the file system image used - * does not already contain the header information. - * - * File system images without headers can be created using the makefsfile - * tool with the -h command line option. - * - * - * Notes about valid SSI tags - * -------------------------- - * - * The following assumptions are made about tags used in SSI markers: - * - * 1. No tag may contain '-' or whitespace characters within the tag name. - * 2. Whitespace is allowed between the tag leadin "". - * 3. The maximum tag name length is LWIP_HTTPD_MAX_TAG_NAME_LEN, currently 8 characters. - * - * Notes on CGI usage - * ------------------ - * - * The simple CGI support offered here works with GET method requests only - * and can handle up to 16 parameters encoded into the URI. The handler - * function may not write directly to the HTTP output but must return a - * filename that the HTTP server will send to the browser as a response to - * the incoming CGI request. - * - * - * - * The list of supported file types is quite short, so if makefsdata complains - * about an unknown extension, make sure to add it (and its doctype) to - * the 'g_psHTTPHeaders' list. - */ -#include "lwip/init.h" -#include "lwip/apps/httpd.h" -#include "lwip/debug.h" -#include "lwip/stats.h" -#include "lwip/apps/fs.h" -#include "httpd_structs.h" -#include "lwip/def.h" - -#include "lwip/altcp.h" -#include "lwip/altcp_tcp.h" -#if HTTPD_ENABLE_HTTPS -#include "lwip/altcp_tls.h" -#endif -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif -#if LWIP_HTTPD_TIMING -#include "lwip/sys.h" -#endif /* LWIP_HTTPD_TIMING */ - -#include /* memset */ -#include /* atoi */ -#include - -#if LWIP_TCP && LWIP_CALLBACK_API - -/** Minimum length for a valid HTTP/0.9 request: "GET /\r\n" -> 7 bytes */ -#define MIN_REQ_LEN 7 - -#define CRLF "\r\n" -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE -#define HTTP11_CONNECTIONKEEPALIVE "Connection: keep-alive" -#define HTTP11_CONNECTIONKEEPALIVE2 "Connection: Keep-Alive" -#endif - -#if LWIP_HTTPD_DYNAMIC_FILE_READ -#define HTTP_IS_DYNAMIC_FILE(hs) ((hs)->buf != NULL) -#else -#define HTTP_IS_DYNAMIC_FILE(hs) 0 -#endif - -/* This defines checks whether tcp_write has to copy data or not */ - -#ifndef HTTP_IS_DATA_VOLATILE -/** tcp_write does not have to copy data when sent from rom-file-system directly */ -#define HTTP_IS_DATA_VOLATILE(hs) (HTTP_IS_DYNAMIC_FILE(hs) ? TCP_WRITE_FLAG_COPY : 0) -#endif -/** Default: dynamic headers are sent from ROM (non-dynamic headers are handled like file data) */ -#ifndef HTTP_IS_HDR_VOLATILE -#define HTTP_IS_HDR_VOLATILE(hs, ptr) 0 -#endif - -/* Return values for http_send_*() */ -#define HTTP_DATA_TO_SEND_FREED 3 -#define HTTP_DATA_TO_SEND_BREAK 2 -#define HTTP_DATA_TO_SEND_CONTINUE 1 -#define HTTP_NO_DATA_TO_SEND 0 - -typedef struct { - const char *name; - u8_t shtml; -} default_filename; - -static const default_filename httpd_default_filenames[] = { - {"/index.shtml", 1 }, - {"/index.ssi", 1 }, - {"/index.shtm", 1 }, - {"/index.html", 0 }, - {"/index.htm", 0 } -}; - -#define NUM_DEFAULT_FILENAMES LWIP_ARRAYSIZE(httpd_default_filenames) - -#if LWIP_HTTPD_SUPPORT_REQUESTLIST -/** HTTP request is copied here from pbufs for simple parsing */ -static char httpd_req_buf[LWIP_HTTPD_MAX_REQ_LENGTH + 1]; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - -#if LWIP_HTTPD_SUPPORT_POST -#if LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN > LWIP_HTTPD_MAX_REQUEST_URI_LEN -#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_POST_MAX_RESPONSE_URI_LEN -#endif -#endif -#ifndef LWIP_HTTPD_URI_BUF_LEN -#define LWIP_HTTPD_URI_BUF_LEN LWIP_HTTPD_MAX_REQUEST_URI_LEN -#endif -#if LWIP_HTTPD_URI_BUF_LEN -/* Filename for response file to send when POST is finished or - * search for default files when a directory is requested. */ -static char http_uri_buf[LWIP_HTTPD_URI_BUF_LEN + 1]; -#endif - -#if LWIP_HTTPD_DYNAMIC_HEADERS -/* The number of individual strings that comprise the headers sent before each - * requested file. - */ -#define NUM_FILE_HDR_STRINGS 5 -#define HDR_STRINGS_IDX_HTTP_STATUS 0 /* e.g. "HTTP/1.0 200 OK\r\n" */ -#define HDR_STRINGS_IDX_SERVER_NAME 1 /* e.g. "Server: "HTTPD_SERVER_AGENT"\r\n" */ -#define HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE 2 /* e.g. "Content-Length: xy\r\n" and/or "Connection: keep-alive\r\n" */ -#define HDR_STRINGS_IDX_CONTENT_LEN_NR 3 /* the byte count, when content-length is used */ -#define HDR_STRINGS_IDX_CONTENT_TYPE 4 /* the content type (or default answer content type including default document) */ - -/* The dynamically generated Content-Length buffer needs space for CRLF + NULL */ -#define LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET 3 -#ifndef LWIP_HTTPD_MAX_CONTENT_LEN_SIZE -/* The dynamically generated Content-Length buffer shall be able to work with - ~953 MB (9 digits) */ -#define LWIP_HTTPD_MAX_CONTENT_LEN_SIZE (9 + LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) -#endif -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ - -#if LWIP_HTTPD_SSI - -#define HTTPD_LAST_TAG_PART 0xFFFF - -enum tag_check_state { - TAG_NONE, /* Not processing an SSI tag */ - TAG_LEADIN, /* Tag lead in "" being processed */ - TAG_SENDING /* Sending tag replacement string */ -}; - -struct http_ssi_state { - const char *parsed; /* Pointer to the first unparsed byte in buf. */ -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - const char *tag_started;/* Pointer to the first opening '<' of the tag. */ -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */ - const char *tag_end; /* Pointer to char after the closing '>' of the tag. */ - u32_t parse_left; /* Number of unparsed bytes in buf. */ - u16_t tag_index; /* Counter used by tag parsing state machine */ - u16_t tag_insert_len; /* Length of insert in string tag_insert */ -#if LWIP_HTTPD_SSI_MULTIPART - u16_t tag_part; /* Counter passed to and changed by tag insertion function to insert multiple times */ -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - u8_t tag_type; /* index into http_ssi_tag_desc array */ - u8_t tag_name_len; /* Length of the tag name in string tag_name */ - char tag_name[LWIP_HTTPD_MAX_TAG_NAME_LEN + 1]; /* Last tag name extracted */ - char tag_insert[LWIP_HTTPD_MAX_TAG_INSERT_LEN + 1]; /* Insert string for tag_name */ - enum tag_check_state tag_state; /* State of the tag processor */ -}; - -struct http_ssi_tag_description { - const char *lead_in; - const char *lead_out; -}; - -#endif /* LWIP_HTTPD_SSI */ - -struct http_state { -#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED - struct http_state *next; -#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - struct fs_file file_handle; - struct fs_file *handle; - const char *file; /* Pointer to first unsent byte in buf. */ - - struct altcp_pcb *pcb; -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - struct pbuf *req; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - -#if LWIP_HTTPD_DYNAMIC_FILE_READ - char *buf; /* File read buffer. */ - int buf_len; /* Size of file read buffer, buf. */ -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ - u32_t left; /* Number of unsent bytes in buf. */ - u8_t retries; -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - u8_t keepalive; -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ -#if LWIP_HTTPD_SSI - struct http_ssi_state *ssi; -#endif /* LWIP_HTTPD_SSI */ -#if LWIP_HTTPD_CGI - char *params[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Params extracted from the request URI */ - char *param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each extracted param */ -#endif /* LWIP_HTTPD_CGI */ -#if LWIP_HTTPD_DYNAMIC_HEADERS - const char *hdrs[NUM_FILE_HDR_STRINGS]; /* HTTP headers to be sent. */ - char hdr_content_len[LWIP_HTTPD_MAX_CONTENT_LEN_SIZE]; - u16_t hdr_pos; /* The position of the first unsent header byte in the - current string */ - u16_t hdr_index; /* The index of the hdr string currently being sent. */ -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ -#if LWIP_HTTPD_TIMING - u32_t time_started; -#endif /* LWIP_HTTPD_TIMING */ -#if LWIP_HTTPD_SUPPORT_POST - u32_t post_content_len_left; -#if LWIP_HTTPD_POST_MANUAL_WND - u32_t unrecved_bytes; - u8_t no_auto_wnd; - u8_t post_finished; -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ -#endif /* LWIP_HTTPD_SUPPORT_POST*/ -}; - -#if HTTPD_USE_MEM_POOL -LWIP_MEMPOOL_DECLARE(HTTPD_STATE, MEMP_NUM_PARALLEL_HTTPD_CONNS, sizeof(struct http_state), "HTTPD_STATE") -#if LWIP_HTTPD_SSI -LWIP_MEMPOOL_DECLARE(HTTPD_SSI_STATE, MEMP_NUM_PARALLEL_HTTPD_SSI_CONNS, sizeof(struct http_ssi_state), "HTTPD_SSI_STATE") -#define HTTP_FREE_SSI_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_SSI_STATE, (x)) -#define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)LWIP_MEMPOOL_ALLOC(HTTPD_SSI_STATE) -#endif /* LWIP_HTTPD_SSI */ -#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)LWIP_MEMPOOL_ALLOC(HTTPD_STATE) -#define HTTP_FREE_HTTP_STATE(x) LWIP_MEMPOOL_FREE(HTTPD_STATE, (x)) -#else /* HTTPD_USE_MEM_POOL */ -#define HTTP_ALLOC_HTTP_STATE() (struct http_state *)mem_malloc(sizeof(struct http_state)) -#define HTTP_FREE_HTTP_STATE(x) mem_free(x) -#if LWIP_HTTPD_SSI -#define HTTP_ALLOC_SSI_STATE() (struct http_ssi_state *)mem_malloc(sizeof(struct http_ssi_state)) -#define HTTP_FREE_SSI_STATE(x) mem_free(x) -#endif /* LWIP_HTTPD_SSI */ -#endif /* HTTPD_USE_MEM_POOL */ - -static err_t http_close_conn(struct altcp_pcb *pcb, struct http_state *hs); -static err_t http_close_or_abort_conn(struct altcp_pcb *pcb, struct http_state *hs, u8_t abort_conn); -static err_t http_find_file(struct http_state *hs, const char *uri, int is_09); -static err_t http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, u8_t tag_check, char *params); -static err_t http_poll(void *arg, struct altcp_pcb *pcb); -static u8_t http_check_eof(struct altcp_pcb *pcb, struct http_state *hs); -#if LWIP_HTTPD_FS_ASYNC_READ -static void http_continue(void *connection); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - -#if LWIP_HTTPD_SSI -/* SSI insert handler function pointer. */ -static tSSIHandler httpd_ssi_handler; -#if !LWIP_HTTPD_SSI_RAW -static int httpd_num_tags; -static const char **httpd_tags; -#endif /* !LWIP_HTTPD_SSI_RAW */ - -/* Define the available tag lead-ins and corresponding lead-outs. - * ATTENTION: for the algorithm below using this array, it is essential - * that the lead in differs in the first character! */ -const struct http_ssi_tag_description http_ssi_tag_desc[] = { - {""}, - {"/*#", "*/"} -}; - -#endif /* LWIP_HTTPD_SSI */ - -#if LWIP_HTTPD_CGI -/* CGI handler information */ -static const tCGI *httpd_cgis; -static int httpd_num_cgis; -static int http_cgi_paramcount; -#define http_cgi_params hs->params -#define http_cgi_param_vals hs->param_vals -#elif LWIP_HTTPD_CGI_SSI -static char *http_cgi_params[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Params extracted from the request URI */ -static char *http_cgi_param_vals[LWIP_HTTPD_MAX_CGI_PARAMETERS]; /* Values for each extracted param */ -#endif /* LWIP_HTTPD_CGI */ - -#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED -/** global list of active HTTP connections, use to kill the oldest when - running out of memory */ -static struct http_state *http_connections; - -static void -http_add_connection(struct http_state *hs) -{ - /* add the connection to the list */ - hs->next = http_connections; - http_connections = hs; -} - -static void -http_remove_connection(struct http_state *hs) -{ - /* take the connection off the list */ - if (http_connections) { - if (http_connections == hs) { - http_connections = hs->next; - } else { - struct http_state *last; - for (last = http_connections; last->next != NULL; last = last->next) { - if (last->next == hs) { - last->next = hs->next; - break; - } - } - } - } -} - -static void -http_kill_oldest_connection(u8_t ssi_required) -{ - struct http_state *hs = http_connections; - struct http_state *hs_free_next = NULL; - while (hs && hs->next) { -#if LWIP_HTTPD_SSI - if (ssi_required) { - if (hs->next->ssi != NULL) { - hs_free_next = hs; - } - } else -#else /* LWIP_HTTPD_SSI */ - LWIP_UNUSED_ARG(ssi_required); -#endif /* LWIP_HTTPD_SSI */ - { - hs_free_next = hs; - } - LWIP_ASSERT("broken list", hs != hs->next); - hs = hs->next; - } - if (hs_free_next != NULL) { - LWIP_ASSERT("hs_free_next->next != NULL", hs_free_next->next != NULL); - LWIP_ASSERT("hs_free_next->next->pcb != NULL", hs_free_next->next->pcb != NULL); - /* send RST when killing a connection because of memory shortage */ - http_close_or_abort_conn(hs_free_next->next->pcb, hs_free_next->next, 1); /* this also unlinks the http_state from the list */ - } -} -#else /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - -#define http_add_connection(hs) -#define http_remove_connection(hs) - -#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - -#if LWIP_HTTPD_SSI -/** Allocate as struct http_ssi_state. */ -static struct http_ssi_state * -http_ssi_state_alloc(void) -{ - struct http_ssi_state *ret = HTTP_ALLOC_SSI_STATE(); -#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED - if (ret == NULL) { - http_kill_oldest_connection(1); - ret = HTTP_ALLOC_SSI_STATE(); - } -#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - if (ret != NULL) { - memset(ret, 0, sizeof(struct http_ssi_state)); - } - return ret; -} - -/** Free a struct http_ssi_state. */ -static void -http_ssi_state_free(struct http_ssi_state *ssi) -{ - if (ssi != NULL) { - HTTP_FREE_SSI_STATE(ssi); - } -} -#endif /* LWIP_HTTPD_SSI */ - -/** Initialize a struct http_state. - */ -static void -http_state_init(struct http_state *hs) -{ - /* Initialize the structure. */ - memset(hs, 0, sizeof(struct http_state)); -#if LWIP_HTTPD_DYNAMIC_HEADERS - /* Indicate that the headers are not yet valid */ - hs->hdr_index = NUM_FILE_HDR_STRINGS; -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ -} - -/** Allocate a struct http_state. */ -static struct http_state * -http_state_alloc(void) -{ - struct http_state *ret = HTTP_ALLOC_HTTP_STATE(); -#if LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED - if (ret == NULL) { - http_kill_oldest_connection(0); - ret = HTTP_ALLOC_HTTP_STATE(); - } -#endif /* LWIP_HTTPD_KILL_OLD_ON_CONNECTIONS_EXCEEDED */ - if (ret != NULL) { - http_state_init(ret); - http_add_connection(ret); - } - return ret; -} - -/** Free a struct http_state. - * Also frees the file data if dynamic. - */ -static void -http_state_eof(struct http_state *hs) -{ - if (hs->handle) { -#if LWIP_HTTPD_TIMING - u32_t ms_needed = sys_now() - hs->time_started; - u32_t needed = LWIP_MAX(1, (ms_needed / 100)); - LWIP_DEBUGF(HTTPD_DEBUG_TIMING, ("httpd: needed %"U32_F" ms to send file of %d bytes -> %"U32_F" bytes/sec\n", - ms_needed, hs->handle->len, ((((u32_t)hs->handle->len) * 10) / needed))); -#endif /* LWIP_HTTPD_TIMING */ - fs_close(hs->handle); - hs->handle = NULL; - } -#if LWIP_HTTPD_DYNAMIC_FILE_READ - if (hs->buf != NULL) { - mem_free(hs->buf); - hs->buf = NULL; - } -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ -#if LWIP_HTTPD_SSI - if (hs->ssi) { - http_ssi_state_free(hs->ssi); - hs->ssi = NULL; - } -#endif /* LWIP_HTTPD_SSI */ -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - if (hs->req) { - pbuf_free(hs->req); - hs->req = NULL; - } -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ -} - -/** Free a struct http_state. - * Also frees the file data if dynamic. - */ -static void -http_state_free(struct http_state *hs) -{ - if (hs != NULL) { - http_state_eof(hs); - http_remove_connection(hs); - HTTP_FREE_HTTP_STATE(hs); - } -} - -/** Call tcp_write() in a loop trying smaller and smaller length - * - * @param pcb altcp_pcb to send - * @param ptr Data to send - * @param length Length of data to send (in/out: on return, contains the - * amount of data sent) - * @param apiflags directly passed to tcp_write - * @return the return value of tcp_write - */ -static err_t -http_write(struct altcp_pcb *pcb, const void *ptr, u16_t *length, u8_t apiflags) -{ - u16_t len, max_len; - err_t err; - LWIP_ASSERT("length != NULL", length != NULL); - len = *length; - if (len == 0) { - return ERR_OK; - } - /* We cannot send more data than space available in the send buffer. */ - max_len = altcp_sndbuf(pcb); - if (max_len < len) { - len = max_len; - } -#ifdef HTTPD_MAX_WRITE_LEN - /* Additional limitation: e.g. don't enqueue more than 2*mss at once */ - max_len = HTTPD_MAX_WRITE_LEN(pcb); - if (len > max_len) { - len = max_len; - } -#endif /* HTTPD_MAX_WRITE_LEN */ - do { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Trying to send %d bytes\n", len)); - err = altcp_write(pcb, ptr, len, apiflags); - if (err == ERR_MEM) { - if ((altcp_sndbuf(pcb) == 0) || - (altcp_sndqueuelen(pcb) >= TCP_SND_QUEUELEN)) { - /* no need to try smaller sizes */ - len = 1; - } else { - len /= 2; - } - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, - ("Send failed, trying less (%d bytes)\n", len)); - } - } while ((err == ERR_MEM) && (len > 1)); - - if (err == ERR_OK) { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Sent %d bytes\n", len)); - *length = len; - } else { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Send failed with err %d (\"%s\")\n", err, lwip_strerr(err))); - *length = 0; - } - -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - /* ensure nagle is normally enabled (only disabled for persistent connections - when all data has been enqueued but the connection stays open for the next - request */ - altcp_nagle_enable(pcb); -#endif - - return err; -} - -/** - * The connection shall be actively closed (using RST to close from fault states). - * Reset the sent- and recv-callbacks. - * - * @param pcb the tcp pcb to reset callbacks - * @param hs connection state to free - */ -static err_t -http_close_or_abort_conn(struct altcp_pcb *pcb, struct http_state *hs, u8_t abort_conn) -{ - err_t err; - LWIP_DEBUGF(HTTPD_DEBUG, ("Closing connection %p\n", (void *)pcb)); - -#if LWIP_HTTPD_SUPPORT_POST - if (hs != NULL) { - if ((hs->post_content_len_left != 0) -#if LWIP_HTTPD_POST_MANUAL_WND - || ((hs->no_auto_wnd != 0) && (hs->unrecved_bytes != 0)) -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - ) { - /* make sure the post code knows that the connection is closed */ - http_uri_buf[0] = 0; - httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN); - } - } -#endif /* LWIP_HTTPD_SUPPORT_POST*/ - - - altcp_arg(pcb, NULL); - altcp_recv(pcb, NULL); - altcp_err(pcb, NULL); - altcp_poll(pcb, NULL, 0); - altcp_sent(pcb, NULL); - if (hs != NULL) { - http_state_free(hs); - } - - if (abort_conn) { - altcp_abort(pcb); - return ERR_OK; - } - err = altcp_close(pcb); - if (err != ERR_OK) { - LWIP_DEBUGF(HTTPD_DEBUG, ("Error %d closing %p\n", err, (void *)pcb)); - /* error closing, try again later in poll */ - altcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL); - } - return err; -} - -/** - * The connection shall be actively closed. - * Reset the sent- and recv-callbacks. - * - * @param pcb the tcp pcb to reset callbacks - * @param hs connection state to free - */ -static err_t -http_close_conn(struct altcp_pcb *pcb, struct http_state *hs) -{ - return http_close_or_abort_conn(pcb, hs, 0); -} - -/** End of file: either close the connection (Connection: close) or - * close the file (Connection: keep-alive) - */ -static void -http_eof(struct altcp_pcb *pcb, struct http_state *hs) -{ - /* HTTP/1.1 persistent connection? (Not supported for SSI) */ -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - if (hs->keepalive) { - http_remove_connection(hs); - - http_state_eof(hs); - http_state_init(hs); - /* restore state: */ - hs->pcb = pcb; - hs->keepalive = 1; - http_add_connection(hs); - /* ensure nagle doesn't interfere with sending all data as fast as possible: */ - altcp_nagle_disable(pcb); - } else -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - { - http_close_conn(pcb, hs); - } -} - -#if LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI -/** - * Extract URI parameters from the parameter-part of an URI in the form - * "test.cgi?x=y" @todo: better explanation! - * Pointers to the parameters are stored in hs->param_vals. - * - * @param hs http connection state - * @param params pointer to the NULL-terminated parameter string from the URI - * @return number of parameters extracted - */ -static int -extract_uri_parameters(struct http_state *hs, char *params) -{ - char *pair; - char *equals; - int loop; - - LWIP_UNUSED_ARG(hs); - - /* If we have no parameters at all, return immediately. */ - if (!params || (params[0] == '\0')) { - return (0); - } - - /* Get a pointer to our first parameter */ - pair = params; - - /* Parse up to LWIP_HTTPD_MAX_CGI_PARAMETERS from the passed string and ignore the - * remainder (if any) */ - for (loop = 0; (loop < LWIP_HTTPD_MAX_CGI_PARAMETERS) && pair; loop++) { - - /* Save the name of the parameter */ - http_cgi_params[loop] = pair; - - /* Remember the start of this name=value pair */ - equals = pair; - - /* Find the start of the next name=value pair and replace the delimiter - * with a 0 to terminate the previous pair string. */ - pair = strchr(pair, '&'); - if (pair) { - *pair = '\0'; - pair++; - } else { - /* We didn't find a new parameter so find the end of the URI and - * replace the space with a '\0' */ - pair = strchr(equals, ' '); - if (pair) { - *pair = '\0'; - } - - /* Revert to NULL so that we exit the loop as expected. */ - pair = NULL; - } - - /* Now find the '=' in the previous pair, replace it with '\0' and save - * the parameter value string. */ - equals = strchr(equals, '='); - if (equals) { - *equals = '\0'; - http_cgi_param_vals[loop] = equals + 1; - } else { - http_cgi_param_vals[loop] = NULL; - } - } - - return loop; -} -#endif /* LWIP_HTTPD_CGI || LWIP_HTTPD_CGI_SSI */ - -#if LWIP_HTTPD_SSI -/** - * Insert a tag (found in an shtml in the form of "" into the file. - * The tag's name is stored in ssi->tag_name (NULL-terminated), the replacement - * should be written to hs->tag_insert (up to a length of LWIP_HTTPD_MAX_TAG_INSERT_LEN). - * The amount of data written is stored to ssi->tag_insert_len. - * - * @todo: return tag_insert_len - maybe it can be removed from struct http_state? - * - * @param hs http connection state - */ -static void -get_tag_insert(struct http_state *hs) -{ -#if LWIP_HTTPD_SSI_RAW - const char *tag; -#else /* LWIP_HTTPD_SSI_RAW */ - int tag; -#endif /* LWIP_HTTPD_SSI_RAW */ - size_t len; - struct http_ssi_state *ssi; -#if LWIP_HTTPD_SSI_MULTIPART - u16_t current_tag_part; -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - - LWIP_ASSERT("hs != NULL", hs != NULL); - ssi = hs->ssi; - LWIP_ASSERT("ssi != NULL", ssi != NULL); -#if LWIP_HTTPD_SSI_MULTIPART - current_tag_part = ssi->tag_part; - ssi->tag_part = HTTPD_LAST_TAG_PART; -#endif /* LWIP_HTTPD_SSI_MULTIPART */ -#if LWIP_HTTPD_SSI_RAW - tag = ssi->tag_name; -#endif - - if (httpd_ssi_handler -#if !LWIP_HTTPD_SSI_RAW - && httpd_tags && httpd_num_tags -#endif /* !LWIP_HTTPD_SSI_RAW */ - ) { - - /* Find this tag in the list we have been provided. */ -#if LWIP_HTTPD_SSI_RAW - { -#else /* LWIP_HTTPD_SSI_RAW */ - for (tag = 0; tag < httpd_num_tags; tag++) { - if (strcmp(ssi->tag_name, httpd_tags[tag]) == 0) -#endif /* LWIP_HTTPD_SSI_RAW */ - { - ssi->tag_insert_len = httpd_ssi_handler(tag, ssi->tag_insert, - LWIP_HTTPD_MAX_TAG_INSERT_LEN -#if LWIP_HTTPD_SSI_MULTIPART - , current_tag_part, &ssi->tag_part -#endif /* LWIP_HTTPD_SSI_MULTIPART */ -#if LWIP_HTTPD_FILE_STATE - , (hs->handle ? hs->handle->state : NULL) -#endif /* LWIP_HTTPD_FILE_STATE */ - ); -#if LWIP_HTTPD_SSI_RAW - if (ssi->tag_insert_len != HTTPD_SSI_TAG_UNKNOWN) -#endif /* LWIP_HTTPD_SSI_RAW */ - { - return; - } - } - } - } - - /* If we drop out, we were asked to serve a page which contains tags that - * we don't have a handler for. Merely echo back the tags with an error - * marker. */ -#define UNKNOWN_TAG1_TEXT "***UNKNOWN TAG " -#define UNKNOWN_TAG1_LEN 18 -#define UNKNOWN_TAG2_TEXT "***" -#define UNKNOWN_TAG2_LEN 7 - len = LWIP_MIN(sizeof(ssi->tag_name), LWIP_MIN(strlen(ssi->tag_name), - LWIP_HTTPD_MAX_TAG_INSERT_LEN - (UNKNOWN_TAG1_LEN + UNKNOWN_TAG2_LEN))); - MEMCPY(ssi->tag_insert, UNKNOWN_TAG1_TEXT, UNKNOWN_TAG1_LEN); - MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN], ssi->tag_name, len); - MEMCPY(&ssi->tag_insert[UNKNOWN_TAG1_LEN + len], UNKNOWN_TAG2_TEXT, UNKNOWN_TAG2_LEN); - ssi->tag_insert[UNKNOWN_TAG1_LEN + len + UNKNOWN_TAG2_LEN] = 0; - - len = strlen(ssi->tag_insert); - LWIP_ASSERT("len <= 0xffff", len <= 0xffff); - ssi->tag_insert_len = (u16_t)len; -} -#endif /* LWIP_HTTPD_SSI */ - -#if LWIP_HTTPD_DYNAMIC_HEADERS -/** - * Generate the relevant HTTP headers for the given filename and write - * them into the supplied buffer. - */ -static void -get_http_headers(struct http_state *hs, const char *uri) -{ - size_t content_type; - char *tmp; - char *ext; - char *vars; - - /* In all cases, the second header we send is the server identification - so set it here. */ - hs->hdrs[HDR_STRINGS_IDX_SERVER_NAME] = g_psHTTPHeaderStrings[HTTP_HDR_SERVER]; - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE] = NULL; - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] = NULL; - - /* Is this a normal file or the special case we use to send back the - default "404: Page not found" response? */ - if (uri == NULL) { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND]; -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - if (hs->keepalive) { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML_PERSISTENT]; - } else -#endif - { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaderStrings[DEFAULT_404_HTML]; - } - - /* Set up to send the first header string. */ - hs->hdr_index = 0; - hs->hdr_pos = 0; - return; - } - /* We are dealing with a particular filename. Look for one other - special case. We assume that any filename with "404" in it must be - indicative of a 404 server error whereas all other files require - the 200 OK header. */ - if (strstr(uri, "404")) { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND]; - } else if (strstr(uri, "400")) { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_BAD_REQUEST]; - } else if (strstr(uri, "501")) { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_IMPL]; - } else { - hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_OK]; - } - - /* Determine if the URI has any variables and, if so, temporarily remove - them. */ - vars = strchr(uri, '?'); - if (vars) { - *vars = '\0'; - } - - /* Get a pointer to the file extension. We find this by looking for the - last occurrence of "." in the filename passed. */ - ext = NULL; - tmp = strchr(uri, '.'); - while (tmp) { - ext = tmp + 1; - tmp = strchr(ext, '.'); - } - if (ext != NULL) { - /* Now determine the content type and add the relevant header for that. */ - for (content_type = 0; content_type < NUM_HTTP_HEADERS; content_type++) { - /* Have we found a matching extension? */ - if (!lwip_stricmp(g_psHTTPHeaders[content_type].extension, ext)) { - break; - } - } - } else { - content_type = NUM_HTTP_HEADERS; - } - - /* Reinstate the parameter marker if there was one in the original URI. */ - if (vars) { - *vars = '?'; - } - -#if LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI - /* Does the URL passed have any file extension? If not, we assume it - is a special-case URL used for control state notification and we do - not send any HTTP headers with the response. */ - if (!ext) { - /* Force the header index to a value indicating that all headers - have already been sent. */ - hs->hdr_index = NUM_FILE_HDR_STRINGS; - return; - } -#endif /* LWIP_HTTPD_OMIT_HEADER_FOR_EXTENSIONLESS_URI */ - /* Did we find a matching extension? */ - if (content_type < NUM_HTTP_HEADERS) { - /* yes, store it */ - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = g_psHTTPHeaders[content_type].content_type; - } else if (!ext) { - /* no, no extension found -> use binary transfer to prevent the browser adding '.txt' on save */ - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_APP; - } else { - /* No - use the default, plain text file type. */ - hs->hdrs[HDR_STRINGS_IDX_CONTENT_TYPE] = HTTP_HDR_DEFAULT_TYPE; - } - /* Set up to send the first header string. */ - hs->hdr_index = 0; - hs->hdr_pos = 0; -} - -/* Add content-length header? */ -static void -get_http_content_length(struct http_state *hs) -{ - u8_t add_content_len = 0; - - LWIP_ASSERT("already been here?", hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE] == NULL); - - add_content_len = 0; -#if LWIP_HTTPD_SSI - if (hs->ssi == NULL) /* @todo: get maximum file length from SSI */ -#endif /* LWIP_HTTPD_SSI */ - { - if ((hs->handle != NULL) && (hs->handle->flags & FS_FILE_FLAGS_HEADER_PERSISTENT)) { - add_content_len = 1; - } - } - if (add_content_len) { - size_t len; - lwip_itoa(hs->hdr_content_len, (size_t)LWIP_HTTPD_MAX_CONTENT_LEN_SIZE, - hs->handle->len); - len = strlen(hs->hdr_content_len); - if (len <= LWIP_HTTPD_MAX_CONTENT_LEN_SIZE - LWIP_HTTPD_MAX_CONTENT_LEN_OFFSET) { - SMEMCPY(&hs->hdr_content_len[len], CRLF, 3); - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_NR] = hs->hdr_content_len; - } else { - add_content_len = 0; - } - } -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - if (add_content_len) { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_KEEPALIVE_LEN]; - } else { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE]; - hs->keepalive = 0; - } -#else /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - if (add_content_len) { - hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE] = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH]; - } -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ -} - -/** Sub-function of http_send(): send dynamic headers - * - * @returns: - HTTP_NO_DATA_TO_SEND: no new data has been enqueued - * - HTTP_DATA_TO_SEND_CONTINUE: continue with sending HTTP body - * - HTTP_DATA_TO_SEND_BREAK: data has been enqueued, headers pending, - * so don't send HTTP body yet - * - HTTP_DATA_TO_SEND_FREED: http_state and pcb are already freed - */ -static u8_t -http_send_headers(struct altcp_pcb *pcb, struct http_state *hs) -{ - err_t err; - u16_t len; - u8_t data_to_send = HTTP_NO_DATA_TO_SEND; - u16_t hdrlen, sendlen; - - if (hs->hdrs[HDR_STRINGS_IDX_CONTENT_LEN_KEEPALIVE] == NULL) { - /* set up "content-length" and "connection:" headers */ - get_http_content_length(hs); - } - - /* How much data can we send? */ - len = altcp_sndbuf(pcb); - sendlen = len; - - while (len && (hs->hdr_index < NUM_FILE_HDR_STRINGS) && sendlen) { - const void *ptr; - u16_t old_sendlen; - u8_t apiflags; - /* How much do we have to send from the current header? */ - hdrlen = (u16_t)strlen(hs->hdrs[hs->hdr_index]); - - /* How much of this can we send? */ - sendlen = (len < (hdrlen - hs->hdr_pos)) ? len : (hdrlen - hs->hdr_pos); - - /* Send this amount of data or as much as we can given memory - * constraints. */ - ptr = (const void *)(hs->hdrs[hs->hdr_index] + hs->hdr_pos); - old_sendlen = sendlen; - apiflags = HTTP_IS_HDR_VOLATILE(hs, ptr); - if (hs->hdr_index == HDR_STRINGS_IDX_CONTENT_LEN_NR) { - /* content-length is always volatile */ - apiflags |= TCP_WRITE_FLAG_COPY; - } - if (hs->hdr_index < NUM_FILE_HDR_STRINGS - 1) { - apiflags |= TCP_WRITE_FLAG_MORE; - } - err = http_write(pcb, ptr, &sendlen, apiflags); - if ((err == ERR_OK) && (old_sendlen != sendlen)) { - /* Remember that we added some more data to be transmitted. */ - data_to_send = HTTP_DATA_TO_SEND_CONTINUE; - } else if (err != ERR_OK) { - /* special case: http_write does not try to send 1 byte */ - sendlen = 0; - } - - /* Fix up the header position for the next time round. */ - hs->hdr_pos += sendlen; - len -= sendlen; - - /* Have we finished sending this string? */ - if (hs->hdr_pos == hdrlen) { - /* Yes - move on to the next one */ - hs->hdr_index++; - /* skip headers that are NULL (not all headers are required) */ - while ((hs->hdr_index < NUM_FILE_HDR_STRINGS) && - (hs->hdrs[hs->hdr_index] == NULL)) { - hs->hdr_index++; - } - hs->hdr_pos = 0; - } - } - - if ((hs->hdr_index >= NUM_FILE_HDR_STRINGS) && (hs->file == NULL)) { - /* When we are at the end of the headers, check for data to send - * instead of waiting for ACK from remote side to continue - * (which would happen when sending files from async read). */ - if (http_check_eof(pcb, hs)) { - data_to_send = HTTP_DATA_TO_SEND_BREAK; - } else { - /* At this point, for non-keepalive connections, hs is deallocated an - pcb is closed. */ - return HTTP_DATA_TO_SEND_FREED; - } - } - /* If we get here and there are still header bytes to send, we send - * the header information we just wrote immediately. If there are no - * more headers to send, but we do have file data to send, drop through - * to try to send some file data too. */ - if ((hs->hdr_index < NUM_FILE_HDR_STRINGS) || !hs->file) { - LWIP_DEBUGF(HTTPD_DEBUG, ("tcp_output\n")); - return HTTP_DATA_TO_SEND_BREAK; - } - return data_to_send; -} -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ - -/** Sub-function of http_send(): end-of-file (or block) is reached, - * either close the file or read the next block (if supported). - * - * @returns: 0 if the file is finished or no data has been read - * 1 if the file is not finished and data has been read - */ -static u8_t -http_check_eof(struct altcp_pcb *pcb, struct http_state *hs) -{ - int bytes_left; -#if LWIP_HTTPD_DYNAMIC_FILE_READ - int count; -#ifdef HTTPD_MAX_WRITE_LEN - int max_write_len; -#endif /* HTTPD_MAX_WRITE_LEN */ -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ */ - - /* Do we have a valid file handle? */ - if (hs->handle == NULL) { - /* No - close the connection. */ - http_eof(pcb, hs); - return 0; - } - bytes_left = fs_bytes_left(hs->handle); - if (bytes_left <= 0) { - /* We reached the end of the file so this request is done. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); - http_eof(pcb, hs); - return 0; - } -#if LWIP_HTTPD_DYNAMIC_FILE_READ - /* Do we already have a send buffer allocated? */ - if (hs->buf) { - /* Yes - get the length of the buffer */ - count = LWIP_MIN(hs->buf_len, bytes_left); - } else { - /* We don't have a send buffer so allocate one now */ - count = altcp_sndbuf(pcb); - if (bytes_left < count) { - count = bytes_left; - } -#ifdef HTTPD_MAX_WRITE_LEN - /* Additional limitation: e.g. don't enqueue more than 2*mss at once */ - max_write_len = HTTPD_MAX_WRITE_LEN(pcb); - if (count > max_write_len) { - count = max_write_len; - } -#endif /* HTTPD_MAX_WRITE_LEN */ - do { - hs->buf = (char *)mem_malloc((mem_size_t)count); - if (hs->buf != NULL) { - hs->buf_len = count; - break; - } - count = count / 2; - } while (count > 100); - - /* Did we get a send buffer? If not, return immediately. */ - if (hs->buf == NULL) { - LWIP_DEBUGF(HTTPD_DEBUG, ("No buff\n")); - return 0; - } - } - - /* Read a block of data from the file. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Trying to read %d bytes.\n", count)); - -#if LWIP_HTTPD_FS_ASYNC_READ - count = fs_read_async(hs->handle, hs->buf, count, http_continue, hs); -#else /* LWIP_HTTPD_FS_ASYNC_READ */ - count = fs_read(hs->handle, hs->buf, count); -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - if (count < 0) { - if (count == FS_READ_DELAYED) { - /* Delayed read, wait for FS to unblock us */ - return 0; - } - /* We reached the end of the file so this request is done. - * @todo: close here for HTTP/1.1 when reading file fails */ - LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); - http_eof(pcb, hs); - return 0; - } - - /* Set up to send the block of data we just read */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Read %d bytes.\n", count)); - hs->left = count; - hs->file = hs->buf; -#if LWIP_HTTPD_SSI - if (hs->ssi) { - hs->ssi->parse_left = count; - hs->ssi->parsed = hs->buf; - } -#endif /* LWIP_HTTPD_SSI */ -#else /* LWIP_HTTPD_DYNAMIC_FILE_READ */ - LWIP_ASSERT("SSI and DYNAMIC_HEADERS turned off but eof not reached", 0); -#endif /* LWIP_HTTPD_SSI || LWIP_HTTPD_DYNAMIC_HEADERS */ - return 1; -} - -/** Sub-function of http_send(): This is the normal send-routine for non-ssi files - * - * @returns: - 1: data has been written (so call tcp_ouput) - * - 0: no data has been written (no need to call tcp_output) - */ -static u8_t -http_send_data_nonssi(struct altcp_pcb *pcb, struct http_state *hs) -{ - err_t err; - u16_t len; - u8_t data_to_send = 0; - - /* We are not processing an SHTML file so no tag checking is necessary. - * Just send the data as we received it from the file. */ - len = (u16_t)LWIP_MIN(hs->left, 0xffff); - - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; - hs->file += len; - hs->left -= len; - } - - return data_to_send; -} - -#if LWIP_HTTPD_SSI -/** Sub-function of http_send(): This is the send-routine for ssi files - * - * @returns: - 1: data has been written (so call tcp_ouput) - * - 0: no data has been written (no need to call tcp_output) - */ -static u8_t -http_send_data_ssi(struct altcp_pcb *pcb, struct http_state *hs) -{ - err_t err = ERR_OK; - u16_t len; - u8_t data_to_send = 0; - u8_t tag_type; - - struct http_ssi_state *ssi = hs->ssi; - LWIP_ASSERT("ssi != NULL", ssi != NULL); - /* We are processing an SHTML file so need to scan for tags and replace - * them with insert strings. We need to be careful here since a tag may - * straddle the boundary of two blocks read from the file and we may also - * have to split the insert string between two tcp_write operations. */ - - /* How much data could we send? */ - len = altcp_sndbuf(pcb); - - /* Do we have remaining data to send before parsing more? */ - if (ssi->parsed > hs->file) { - len = (u16_t)LWIP_MIN(ssi->parsed - hs->file, 0xffff); - - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; - hs->file += len; - hs->left -= len; - } - - /* If the send buffer is full, return now. */ - if (altcp_sndbuf(pcb) == 0) { - return data_to_send; - } - } - - LWIP_DEBUGF(HTTPD_DEBUG, ("State %d, %d left\n", ssi->tag_state, (int)ssi->parse_left)); - - /* We have sent all the data that was already parsed so continue parsing - * the buffer contents looking for SSI tags. */ - while (((ssi->tag_state == TAG_SENDING) || ssi->parse_left) && (err == ERR_OK)) { - if (len == 0) { - return data_to_send; - } - switch (ssi->tag_state) { - case TAG_NONE: - /* We are not currently processing an SSI tag so scan for the - * start of the lead-in marker. */ - for (tag_type = 0; tag_type < LWIP_ARRAYSIZE(http_ssi_tag_desc); tag_type++) { - if (*ssi->parsed == http_ssi_tag_desc[tag_type].lead_in[0]) { - /* We found what could be the lead-in for a new tag so change - * state appropriately. */ - ssi->tag_type = tag_type; - ssi->tag_state = TAG_LEADIN; - ssi->tag_index = 1; - #if !LWIP_HTTPD_SSI_INCLUDE_TAG - ssi->tag_started = ssi->parsed; - #endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG */ - break; - } - } - - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - break; - - case TAG_LEADIN: - /* We are processing the lead-in marker, looking for the start of - * the tag name. */ - - /* Have we reached the end of the leadin? */ - if (http_ssi_tag_desc[ssi->tag_type].lead_in[ssi->tag_index] == 0) { - ssi->tag_index = 0; - ssi->tag_state = TAG_FOUND; - } else { - /* Have we found the next character we expect for the tag leadin? */ - if (*ssi->parsed == http_ssi_tag_desc[ssi->tag_type].lead_in[ssi->tag_index]) { - /* Yes - move to the next one unless we have found the complete - * leadin, in which case we start looking for the tag itself */ - ssi->tag_index++; - } else { - /* We found an unexpected character so this is not a tag. Move - * back to idle state. */ - ssi->tag_state = TAG_NONE; - } - - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - } - break; - - case TAG_FOUND: - /* We are reading the tag name, looking for the start of the - * lead-out marker and removing any whitespace found. */ - - /* Remove leading whitespace between the tag leading and the first - * tag name character. */ - if ((ssi->tag_index == 0) && ((*ssi->parsed == ' ') || - (*ssi->parsed == '\t') || (*ssi->parsed == '\n') || - (*ssi->parsed == '\r'))) { - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - break; - } - - /* Have we found the end of the tag name? This is signalled by - * us finding the first leadout character or whitespace */ - if ((*ssi->parsed == http_ssi_tag_desc[ssi->tag_type].lead_out[0]) || - (*ssi->parsed == ' ') || (*ssi->parsed == '\t') || - (*ssi->parsed == '\n') || (*ssi->parsed == '\r')) { - - if (ssi->tag_index == 0) { - /* We read a zero length tag so ignore it. */ - ssi->tag_state = TAG_NONE; - } else { - /* We read a non-empty tag so go ahead and look for the - * leadout string. */ - ssi->tag_state = TAG_LEADOUT; - LWIP_ASSERT("ssi->tag_index <= 0xff", ssi->tag_index <= 0xff); - ssi->tag_name_len = (u8_t)ssi->tag_index; - ssi->tag_name[ssi->tag_index] = '\0'; - if (*ssi->parsed == http_ssi_tag_desc[ssi->tag_type].lead_out[0]) { - ssi->tag_index = 1; - } else { - ssi->tag_index = 0; - } - } - } else { - /* This character is part of the tag name so save it */ - if (ssi->tag_index < LWIP_HTTPD_MAX_TAG_NAME_LEN) { - ssi->tag_name[ssi->tag_index++] = *ssi->parsed; - } else { - /* The tag was too long so ignore it. */ - ssi->tag_state = TAG_NONE; - } - } - - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - - break; - - /* We are looking for the end of the lead-out marker. */ - case TAG_LEADOUT: - /* Remove leading whitespace between the tag leading and the first - * tag leadout character. */ - if ((ssi->tag_index == 0) && ((*ssi->parsed == ' ') || - (*ssi->parsed == '\t') || (*ssi->parsed == '\n') || - (*ssi->parsed == '\r'))) { - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - break; - } - - /* Have we found the next character we expect for the tag leadout? */ - if (*ssi->parsed == http_ssi_tag_desc[ssi->tag_type].lead_out[ssi->tag_index]) { - /* Yes - move to the next one unless we have found the complete - * leadout, in which case we need to call the client to process - * the tag. */ - - /* Move on to the next character in the buffer */ - ssi->parse_left--; - ssi->parsed++; - ssi->tag_index++; - - if (http_ssi_tag_desc[ssi->tag_type].lead_out[ssi->tag_index] == 0) { - /* Call the client to ask for the insert string for the - * tag we just found. */ -#if LWIP_HTTPD_SSI_MULTIPART - ssi->tag_part = 0; /* start with tag part 0 */ -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - get_tag_insert(hs); - - /* Next time through, we are going to be sending data - * immediately, either the end of the block we start - * sending here or the insert string. */ - ssi->tag_index = 0; - ssi->tag_state = TAG_SENDING; - ssi->tag_end = ssi->parsed; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - ssi->parsed = ssi->tag_started; -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ - - /* If there is any unsent data in the buffer prior to the - * tag, we need to send it now. */ - if (ssi->tag_end > hs->file) { - /* How much of the data can we send? */ -#if LWIP_HTTPD_SSI_INCLUDE_TAG - len = (u16_t)LWIP_MIN(ssi->tag_end - hs->file, 0xffff); -#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ - /* we would include the tag in sending */ - len = (u16_t)LWIP_MIN(ssi->tag_started - hs->file, 0xffff); -#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ - - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - if (ssi->tag_started <= hs->file) { - /* pretend to have sent the tag, too */ - len += (u16_t)(ssi->tag_end - ssi->tag_started); - } -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ - hs->file += len; - hs->left -= len; - } - } - } - } else { - /* We found an unexpected character so this is not a tag. Move - * back to idle state. */ - ssi->parse_left--; - ssi->parsed++; - ssi->tag_state = TAG_NONE; - } - break; - - /* - * We have found a valid tag and are in the process of sending - * data as a result of that discovery. We send either remaining data - * from the file prior to the insert point or the insert string itself. - */ - case TAG_SENDING: - /* Do we have any remaining file data to send from the buffer prior - * to the tag? */ - if (ssi->tag_end > hs->file) { - /* How much of the data can we send? */ -#if LWIP_HTTPD_SSI_INCLUDE_TAG - len = (u16_t)LWIP_MIN(ssi->tag_end - hs->file, 0xffff); -#else /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ - LWIP_ASSERT("hs->started >= hs->file", ssi->tag_started >= hs->file); - /* we would include the tag in sending */ - len = (u16_t)LWIP_MIN(ssi->tag_started - hs->file, 0xffff); -#endif /* LWIP_HTTPD_SSI_INCLUDE_TAG*/ - if (len != 0) { - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - } else { - err = ERR_OK; - } - if (err == ERR_OK) { - data_to_send = 1; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - if (ssi->tag_started <= hs->file) { - /* pretend to have sent the tag, too */ - len += (u16_t)(ssi->tag_end - ssi->tag_started); - } -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ - hs->file += len; - hs->left -= len; - } - } else { -#if LWIP_HTTPD_SSI_MULTIPART - if (ssi->tag_index >= ssi->tag_insert_len) { - /* Did the last SSIHandler have more to send? */ - if (ssi->tag_part != HTTPD_LAST_TAG_PART) { - /* If so, call it again */ - ssi->tag_index = 0; - get_tag_insert(hs); - } - } -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - - /* Do we still have insert data left to send? */ - if (ssi->tag_index < ssi->tag_insert_len) { - /* We are sending the insert string itself. How much of the - * insert can we send? */ - len = (ssi->tag_insert_len - ssi->tag_index); - - /* Note that we set the copy flag here since we only have a - * single tag insert buffer per connection. If we don't do - * this, insert corruption can occur if more than one insert - * is processed before we call tcp_output. */ - err = http_write(pcb, &(ssi->tag_insert[ssi->tag_index]), &len, - HTTP_IS_TAG_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; - ssi->tag_index += len; - /* Don't return here: keep on sending data */ - } - } else { -#if LWIP_HTTPD_SSI_MULTIPART - if (ssi->tag_part == HTTPD_LAST_TAG_PART) -#endif /* LWIP_HTTPD_SSI_MULTIPART */ - { - /* We have sent all the insert data so go back to looking for - * a new tag. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Everything sent.\n")); - ssi->tag_index = 0; - ssi->tag_state = TAG_NONE; -#if !LWIP_HTTPD_SSI_INCLUDE_TAG - ssi->parsed = ssi->tag_end; -#endif /* !LWIP_HTTPD_SSI_INCLUDE_TAG*/ - } - } - break; - default: - break; - } - } - } - - /* If we drop out of the end of the for loop, this implies we must have - * file data to send so send it now. In TAG_SENDING state, we've already - * handled this so skip the send if that's the case. */ - if ((ssi->tag_state != TAG_SENDING) && (ssi->parsed > hs->file)) { -#if LWIP_HTTPD_DYNAMIC_FILE_READ && !LWIP_HTTPD_SSI_INCLUDE_TAG - if ((ssi->tag_state != TAG_NONE) && (ssi->tag_started > ssi->tag_end)) { - /* If we found tag on the edge of the read buffer: just throw away the first part - (we have copied/saved everything required for parsing on later). */ - len = (u16_t)(ssi->tag_started - hs->file); - hs->left -= (ssi->parsed - ssi->tag_started); - ssi->parsed = ssi->tag_started; - ssi->tag_started = hs->buf; - } else -#endif /* LWIP_HTTPD_DYNAMIC_FILE_READ && !LWIP_HTTPD_SSI_INCLUDE_TAG */ - { - len = (u16_t)LWIP_MIN(ssi->parsed - hs->file, 0xffff); - } - - err = http_write(pcb, hs->file, &len, HTTP_IS_DATA_VOLATILE(hs)); - if (err == ERR_OK) { - data_to_send = 1; - hs->file += len; - hs->left -= len; - } - } - return data_to_send; -} -#endif /* LWIP_HTTPD_SSI */ - -/** - * Try to send more data on this pcb. - * - * @param pcb the pcb to send data - * @param hs connection state - */ -static u8_t -http_send(struct altcp_pcb *pcb, struct http_state *hs) -{ - u8_t data_to_send = HTTP_NO_DATA_TO_SEND; - - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_send: pcb=%p hs=%p left=%d\n", (void *)pcb, - (void *)hs, hs != NULL ? (int)hs->left : 0)); - -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - if (hs->unrecved_bytes != 0) { - return 0; - } -#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ - - /* If we were passed a NULL state structure pointer, ignore the call. */ - if (hs == NULL) { - return 0; - } - -#if LWIP_HTTPD_FS_ASYNC_READ - /* Check if we are allowed to read from this file. - (e.g. SSI might want to delay sending until data is available) */ - if (!fs_is_file_ready(hs->handle, http_continue, hs)) { - return 0; - } -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - -#if LWIP_HTTPD_DYNAMIC_HEADERS - /* Do we have any more header data to send for this file? */ - if (hs->hdr_index < NUM_FILE_HDR_STRINGS) { - data_to_send = http_send_headers(pcb, hs); - if ((data_to_send == HTTP_DATA_TO_SEND_FREED) || - ((data_to_send != HTTP_DATA_TO_SEND_CONTINUE) && - (hs->hdr_index < NUM_FILE_HDR_STRINGS))) { - return data_to_send; - } - } -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ - - /* Have we run out of file data to send? If so, we need to read the next - * block from the file. */ - if (hs->left == 0) { - if (!http_check_eof(pcb, hs)) { - return 0; - } - } - -#if LWIP_HTTPD_SSI - if (hs->ssi) { - data_to_send = http_send_data_ssi(pcb, hs); - } else -#endif /* LWIP_HTTPD_SSI */ - { - data_to_send = http_send_data_nonssi(pcb, hs); - } - - if ((hs->left == 0) && (fs_bytes_left(hs->handle) <= 0)) { - /* We reached the end of the file so this request is done. - * This adds the FIN flag right into the last data segment. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("End of file.\n")); - http_eof(pcb, hs); - return 0; - } - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("send_data end.\n")); - return data_to_send; -} - -#if LWIP_HTTPD_SUPPORT_EXTSTATUS -/** Initialize a http connection with a file to send for an error message - * - * @param hs http connection state - * @param error_nr HTTP error number - * @return ERR_OK if file was found and hs has been initialized correctly - * another err_t otherwise - */ -static err_t -http_find_error_file(struct http_state *hs, u16_t error_nr) -{ - const char *uri, *uri1, *uri2, *uri3; - - if (error_nr == 501) { - uri1 = "/501.html"; - uri2 = "/501.htm"; - uri3 = "/501.shtml"; - } else { - /* 400 (bad request is the default) */ - uri1 = "/400.html"; - uri2 = "/400.htm"; - uri3 = "/400.shtml"; - } - if (fs_open(&hs->file_handle, uri1) == ERR_OK) { - uri = uri1; - } else if (fs_open(&hs->file_handle, uri2) == ERR_OK) { - uri = uri2; - } else if (fs_open(&hs->file_handle, uri3) == ERR_OK) { - uri = uri3; - } else { - LWIP_DEBUGF(HTTPD_DEBUG, ("Error page for error %"U16_F" not found\n", - error_nr)); - return ERR_ARG; - } - return http_init_file(hs, &hs->file_handle, 0, uri, 0, NULL); -} -#else /* LWIP_HTTPD_SUPPORT_EXTSTATUS */ -#define http_find_error_file(hs, error_nr) ERR_ARG -#endif /* LWIP_HTTPD_SUPPORT_EXTSTATUS */ - -/** - * Get the file struct for a 404 error page. - * Tries some file names and returns NULL if none found. - * - * @param uri pointer that receives the actual file name URI - * @return file struct for the error page or NULL no matching file was found - */ -static struct fs_file * -http_get_404_file(struct http_state *hs, const char **uri) -{ - err_t err; - - *uri = "/404.html"; - err = fs_open(&hs->file_handle, *uri); - if (err != ERR_OK) { - /* 404.html doesn't exist. Try 404.htm instead. */ - *uri = "/404.htm"; - err = fs_open(&hs->file_handle, *uri); - if (err != ERR_OK) { - /* 404.htm doesn't exist either. Try 404.shtml instead. */ - *uri = "/404.shtml"; - err = fs_open(&hs->file_handle, *uri); - if (err != ERR_OK) { - /* 404.htm doesn't exist either. Indicate to the caller that it should - * send back a default 404 page. - */ - *uri = NULL; - return NULL; - } - } - } - - return &hs->file_handle; -} - -#if LWIP_HTTPD_SUPPORT_POST -static err_t -http_handle_post_finished(struct http_state *hs) -{ -#if LWIP_HTTPD_POST_MANUAL_WND - /* Prevent multiple calls to httpd_post_finished, since it might have already - been called before from httpd_post_data_recved(). */ - if (hs->post_finished) { - return ERR_OK; - } - hs->post_finished = 1; -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - /* application error or POST finished */ - /* NULL-terminate the buffer */ - http_uri_buf[0] = 0; - httpd_post_finished(hs, http_uri_buf, LWIP_HTTPD_URI_BUF_LEN); - return http_find_file(hs, http_uri_buf, 0); -} - -/** Pass received POST body data to the application and correctly handle - * returning a response document or closing the connection. - * ATTENTION: The application is responsible for the pbuf now, so don't free it! - * - * @param hs http connection state - * @param p pbuf to pass to the application - * @return ERR_OK if passed successfully, another err_t if the response file - * hasn't been found (after POST finished) - */ -static err_t -http_post_rxpbuf(struct http_state *hs, struct pbuf *p) -{ - err_t err; - - if (p != NULL) { - /* adjust remaining Content-Length */ - if (hs->post_content_len_left < p->tot_len) { - hs->post_content_len_left = 0; - } else { - hs->post_content_len_left -= p->tot_len; - } - } -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - /* prevent connection being closed if httpd_post_data_recved() is called nested */ - hs->unrecved_bytes++; -#endif - if (p != NULL) { - err = httpd_post_receive_data(hs, p); - } else { - err = ERR_OK; - } -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - hs->unrecved_bytes--; -#endif - if (err != ERR_OK) { - /* Ignore remaining content in case of application error */ - hs->post_content_len_left = 0; - } - if (hs->post_content_len_left == 0) { -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - if (hs->unrecved_bytes != 0) { - return ERR_OK; - } -#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ - /* application error or POST finished */ - return http_handle_post_finished(hs); - } - - return ERR_OK; -} - -/** Handle a post request. Called from http_parse_request when method 'POST' - * is found. - * - * @param p The input pbuf (containing the POST header and body). - * @param hs The http connection state. - * @param data HTTP request (header and part of body) from input pbuf(s). - * @param data_len Size of 'data'. - * @param uri The HTTP URI parsed from input pbuf(s). - * @param uri_end Pointer to the end of 'uri' (here, the rest of the HTTP - * header starts). - * @return ERR_OK: POST correctly parsed and accepted by the application. - * ERR_INPROGRESS: POST not completely parsed (no error yet) - * another err_t: Error parsing POST or denied by the application - */ -static err_t -http_post_request(struct pbuf *inp, struct http_state *hs, - char *data, u16_t data_len, char *uri, char *uri_end) -{ - err_t err; - /* search for end-of-header (first double-CRLF) */ - char *crlfcrlf = lwip_strnstr(uri_end + 1, CRLF CRLF, data_len - (uri_end + 1 - data)); - - if (crlfcrlf != NULL) { - /* search for "Content-Length: " */ -#define HTTP_HDR_CONTENT_LEN "Content-Length: " -#define HTTP_HDR_CONTENT_LEN_LEN 16 -#define HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN 10 - char *scontent_len = lwip_strnstr(uri_end + 1, HTTP_HDR_CONTENT_LEN, crlfcrlf - (uri_end + 1)); - if (scontent_len != NULL) { - char *scontent_len_end = lwip_strnstr(scontent_len + HTTP_HDR_CONTENT_LEN_LEN, CRLF, HTTP_HDR_CONTENT_LEN_DIGIT_MAX_LEN); - if (scontent_len_end != NULL) { - int content_len; - char *content_len_num = scontent_len + HTTP_HDR_CONTENT_LEN_LEN; - content_len = atoi(content_len_num); - if (content_len == 0) { - /* if atoi returns 0 on error, fix this */ - if ((content_len_num[0] != '0') || (content_len_num[1] != '\r')) { - content_len = -1; - } - } - if (content_len >= 0) { - /* adjust length of HTTP header passed to application */ - const char *hdr_start_after_uri = uri_end + 1; - u16_t hdr_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - data); - u16_t hdr_data_len = (u16_t)LWIP_MIN(data_len, crlfcrlf + 4 - hdr_start_after_uri); - u8_t post_auto_wnd = 1; - http_uri_buf[0] = 0; - /* trim http header */ - *crlfcrlf = 0; - err = httpd_post_begin(hs, uri, hdr_start_after_uri, hdr_data_len, content_len, - http_uri_buf, LWIP_HTTPD_URI_BUF_LEN, &post_auto_wnd); - if (err == ERR_OK) { - /* try to pass in data of the first pbuf(s) */ - struct pbuf *q = inp; - u16_t start_offset = hdr_len; -#if LWIP_HTTPD_POST_MANUAL_WND - hs->no_auto_wnd = !post_auto_wnd; -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - /* set the Content-Length to be received for this POST */ - hs->post_content_len_left = (u32_t)content_len; - - /* get to the pbuf where the body starts */ - while ((q != NULL) && (q->len <= start_offset)) { - start_offset -= q->len; - q = q->next; - } - if (q != NULL) { - /* hide the remaining HTTP header */ - pbuf_remove_header(q, start_offset); -#if LWIP_HTTPD_POST_MANUAL_WND - if (!post_auto_wnd) { - /* already tcp_recved() this data... */ - hs->unrecved_bytes = q->tot_len; - } -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - pbuf_ref(q); - return http_post_rxpbuf(hs, q); - } else if (hs->post_content_len_left == 0) { - q = pbuf_alloc(PBUF_RAW, 0, PBUF_REF); - return http_post_rxpbuf(hs, q); - } else { - return ERR_OK; - } - } else { - /* return file passed from application */ - return http_find_file(hs, http_uri_buf, 0); - } - } else { - LWIP_DEBUGF(HTTPD_DEBUG, ("POST received invalid Content-Length: %s\n", - content_len_num)); - return ERR_ARG; - } - } - } - /* If we come here, headers are fully received (double-crlf), but Content-Length - was not included. Since this is currently the only supported method, we have - to fail in this case! */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Error when parsing Content-Length\n")); - return ERR_ARG; - } - /* if we come here, the POST is incomplete */ -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - return ERR_INPROGRESS; -#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - return ERR_ARG; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ -} - -#if LWIP_HTTPD_POST_MANUAL_WND -/** - * @ingroup httpd - * A POST implementation can call this function to update the TCP window. - * This can be used to throttle data reception (e.g. when received data is - * programmed to flash and data is received faster than programmed). - * - * @param connection A connection handle passed to httpd_post_begin for which - * httpd_post_finished has *NOT* been called yet! - * @param recved_len Length of data received (for window update) - */ -void httpd_post_data_recved(void *connection, u16_t recved_len) -{ - struct http_state *hs = (struct http_state *)connection; - if (hs != NULL) { - if (hs->no_auto_wnd) { - u16_t len = recved_len; - if (hs->unrecved_bytes >= recved_len) { - hs->unrecved_bytes -= recved_len; - } else { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_LEVEL_WARNING, ("httpd_post_data_recved: recved_len too big\n")); - len = (u16_t)hs->unrecved_bytes; - hs->unrecved_bytes = 0; - } - if (hs->pcb != NULL) { - if (len != 0) { - altcp_recved(hs->pcb, len); - } - if ((hs->post_content_len_left == 0) && (hs->unrecved_bytes == 0)) { - /* finished handling POST */ - http_handle_post_finished(hs); - http_send(hs->pcb, hs); - } - } - } - } -} -#endif /* LWIP_HTTPD_POST_MANUAL_WND */ - -#endif /* LWIP_HTTPD_SUPPORT_POST */ - -#if LWIP_HTTPD_FS_ASYNC_READ -/** Try to send more data if file has been blocked before - * This is a callback function passed to fs_read_async(). - */ -static void -http_continue(void *connection) -{ - struct http_state *hs = (struct http_state *)connection; - LWIP_ASSERT_CORE_LOCKED(); - if (hs && (hs->pcb) && (hs->handle)) { - LWIP_ASSERT("hs->pcb != NULL", hs->pcb != NULL); - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("httpd_continue: try to send more data\n")); - if (http_send(hs->pcb, hs)) { - /* If we wrote anything to be sent, go ahead and send it now. */ - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n")); - altcp_output(hs->pcb); - } - } -} -#endif /* LWIP_HTTPD_FS_ASYNC_READ */ - -/** - * When data has been received in the correct state, try to parse it - * as a HTTP request. - * - * @param inp the received pbuf - * @param hs the connection state - * @param pcb the altcp_pcb which received this packet - * @return ERR_OK if request was OK and hs has been initialized correctly - * ERR_INPROGRESS if request was OK so far but not fully received - * another err_t otherwise - */ -static err_t -http_parse_request(struct pbuf *inp, struct http_state *hs, struct altcp_pcb *pcb) -{ - char *data; - char *crlf; - u16_t data_len; - struct pbuf *p = inp; -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - u16_t clen; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ -#if LWIP_HTTPD_SUPPORT_POST - err_t err; -#endif /* LWIP_HTTPD_SUPPORT_POST */ - - LWIP_UNUSED_ARG(pcb); /* only used for post */ - LWIP_ASSERT("p != NULL", p != NULL); - LWIP_ASSERT("hs != NULL", hs != NULL); - - if ((hs->handle != NULL) || (hs->file != NULL)) { - LWIP_DEBUGF(HTTPD_DEBUG, ("Received data while sending a file\n")); - /* already sending a file */ - /* @todo: abort? */ - return ERR_USE; - } - -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - - LWIP_DEBUGF(HTTPD_DEBUG, ("Received %"U16_F" bytes\n", p->tot_len)); - - /* first check allowed characters in this pbuf? */ - - /* enqueue the pbuf */ - if (hs->req == NULL) { - LWIP_DEBUGF(HTTPD_DEBUG, ("First pbuf\n")); - hs->req = p; - } else { - LWIP_DEBUGF(HTTPD_DEBUG, ("pbuf enqueued\n")); - pbuf_cat(hs->req, p); - } - /* increase pbuf ref counter as it is freed when we return but we want to - keep it on the req list */ - pbuf_ref(p); - - if (hs->req->next != NULL) { - data_len = LWIP_MIN(hs->req->tot_len, LWIP_HTTPD_MAX_REQ_LENGTH); - pbuf_copy_partial(hs->req, httpd_req_buf, data_len, 0); - data = httpd_req_buf; - } else -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - { - data = (char *)p->payload; - data_len = p->len; - if (p->len != p->tot_len) { - LWIP_DEBUGF(HTTPD_DEBUG, ("Warning: incomplete header due to chained pbufs\n")); - } - } - - /* received enough data for minimal request? */ - if (data_len >= MIN_REQ_LEN) { - /* wait for CRLF before parsing anything */ - crlf = lwip_strnstr(data, CRLF, data_len); - if (crlf != NULL) { -#if LWIP_HTTPD_SUPPORT_POST - int is_post = 0; -#endif /* LWIP_HTTPD_SUPPORT_POST */ - int is_09 = 0; - char *sp1, *sp2; - u16_t left_len, uri_len; - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("CRLF received, parsing request\n")); - /* parse method */ - if (!strncmp(data, "GET ", 4)) { - sp1 = data + 3; - /* received GET request */ - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received GET request\"\n")); -#if LWIP_HTTPD_SUPPORT_POST - } else if (!strncmp(data, "POST ", 5)) { - /* store request type */ - is_post = 1; - sp1 = data + 4; - /* received GET request */ - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Received POST request\n")); -#endif /* LWIP_HTTPD_SUPPORT_POST */ - } else { - /* null-terminate the METHOD (pbuf is freed anyway wen returning) */ - data[4] = 0; - /* unsupported method! */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Unsupported request method (not implemented): \"%s\"\n", - data)); - return http_find_error_file(hs, 501); - } - /* if we come here, method is OK, parse URI */ - left_len = (u16_t)(data_len - ((sp1 + 1) - data)); - sp2 = lwip_strnstr(sp1 + 1, " ", left_len); -#if LWIP_HTTPD_SUPPORT_V09 - if (sp2 == NULL) { - /* HTTP 0.9: respond with correct protocol version */ - sp2 = lwip_strnstr(sp1 + 1, CRLF, left_len); - is_09 = 1; -#if LWIP_HTTPD_SUPPORT_POST - if (is_post) { - /* HTTP/0.9 does not support POST */ - goto badrequest; - } -#endif /* LWIP_HTTPD_SUPPORT_POST */ - } -#endif /* LWIP_HTTPD_SUPPORT_V09 */ - uri_len = (u16_t)(sp2 - (sp1 + 1)); - if ((sp2 != 0) && (sp2 > sp1)) { - /* wait for CRLFCRLF (indicating end of HTTP headers) before parsing anything */ - if (lwip_strnstr(data, CRLF CRLF, data_len) != NULL) { - char *uri = sp1 + 1; -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - /* This is HTTP/1.0 compatible: for strict 1.1, a connection - would always be persistent unless "close" was specified. */ - if (!is_09 && (lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE, data_len) || - lwip_strnstr(data, HTTP11_CONNECTIONKEEPALIVE2, data_len))) { - hs->keepalive = 1; - } else { - hs->keepalive = 0; - } -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - /* null-terminate the METHOD (pbuf is freed anyway wen returning) */ - *sp1 = 0; - uri[uri_len] = 0; - LWIP_DEBUGF(HTTPD_DEBUG, ("Received \"%s\" request for URI: \"%s\"\n", - data, uri)); -#if LWIP_HTTPD_SUPPORT_POST - if (is_post) { -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - struct pbuf *q = hs->req; -#else /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - struct pbuf *q = inp; -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - err = http_post_request(q, hs, data, data_len, uri, sp2); - if (err != ERR_OK) { - /* restore header for next try */ - *sp1 = ' '; - *sp2 = ' '; - uri[uri_len] = ' '; - } - if (err == ERR_ARG) { - goto badrequest; - } - return err; - } else -#endif /* LWIP_HTTPD_SUPPORT_POST */ - { - return http_find_file(hs, uri, is_09); - } - } - } else { - LWIP_DEBUGF(HTTPD_DEBUG, ("invalid URI\n")); - } - } - } - -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - clen = pbuf_clen(hs->req); - if ((hs->req->tot_len <= LWIP_HTTPD_REQ_BUFSIZE) && - (clen <= LWIP_HTTPD_REQ_QUEUELEN)) { - /* request not fully received (too short or CRLF is missing) */ - return ERR_INPROGRESS; - } else -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - { -#if LWIP_HTTPD_SUPPORT_POST -badrequest: -#endif /* LWIP_HTTPD_SUPPORT_POST */ - LWIP_DEBUGF(HTTPD_DEBUG, ("bad request\n")); - /* could not parse request */ - return http_find_error_file(hs, 400); - } -} - -#if LWIP_HTTPD_SSI && (LWIP_HTTPD_SSI_BY_FILE_EXTENSION == 1) -/* Check if SSI should be parsed for this file/URL - * (With LWIP_HTTPD_SSI_BY_FILE_EXTENSION == 2, this function can be - * overridden by an external implementation.) - * - * @return 1 for SSI, 0 for standard files - */ -static u8_t -http_uri_is_ssi(struct fs_file *file, const char *uri) -{ - size_t loop; - u8_t tag_check = 0; - if (file != NULL) { - /* See if we have been asked for an shtml file and, if so, - enable tag checking. */ - const char *ext = NULL, *sub; - char *param = (char *)strstr(uri, "?"); - if (param != NULL) { - /* separate uri from parameters for now, set back later */ - *param = 0; - } - sub = uri; - ext = uri; - for (sub = strstr(sub, "."); sub != NULL; sub = strstr(sub, ".")) { - ext = sub; - sub++; - } - for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) { - if (!lwip_stricmp(ext, g_pcSSIExtensions[loop])) { - tag_check = 1; - break; - } - } - if (param != NULL) { - *param = '?'; - } - } - return tag_check; -} -#endif /* LWIP_HTTPD_SSI */ - -/** Try to find the file specified by uri and, if found, initialize hs - * accordingly. - * - * @param hs the connection state - * @param uri the HTTP header URI - * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response) - * @return ERR_OK if file was found and hs has been initialized correctly - * another err_t otherwise - */ -static err_t -http_find_file(struct http_state *hs, const char *uri, int is_09) -{ - size_t loop; - struct fs_file *file = NULL; - char *params = NULL; - err_t err; -#if LWIP_HTTPD_CGI - int i; -#endif /* LWIP_HTTPD_CGI */ -#if !LWIP_HTTPD_SSI - const -#endif /* !LWIP_HTTPD_SSI */ - /* By default, assume we will not be processing server-side-includes tags */ - u8_t tag_check = 0; - - /* Have we been asked for the default file (in root or a directory) ? */ -#if LWIP_HTTPD_MAX_REQUEST_URI_LEN - size_t uri_len = strlen(uri); - if ((uri_len > 0) && (uri[uri_len - 1] == '/') && - ((uri != http_uri_buf) || (uri_len == 1))) { - size_t copy_len = LWIP_MIN(sizeof(http_uri_buf) - 1, uri_len - 1); - if (copy_len > 0) { - MEMCPY(http_uri_buf, uri, copy_len); - http_uri_buf[copy_len] = 0; - } -#else /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ - if ((uri[0] == '/') && (uri[1] == 0)) { -#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ - /* Try each of the configured default filenames until we find one - that exists. */ - for (loop = 0; loop < NUM_DEFAULT_FILENAMES; loop++) { - const char *file_name; -#if LWIP_HTTPD_MAX_REQUEST_URI_LEN - if (copy_len > 0) { - size_t len_left = sizeof(http_uri_buf) - copy_len - 1; - if (len_left > 0) { - size_t name_len = strlen(httpd_default_filenames[loop].name); - size_t name_copy_len = LWIP_MIN(len_left, name_len); - MEMCPY(&http_uri_buf[copy_len], httpd_default_filenames[loop].name, name_copy_len); - http_uri_buf[copy_len + name_copy_len] = 0; - } - file_name = http_uri_buf; - } else -#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */ - { - file_name = httpd_default_filenames[loop].name; - } - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Looking for %s...\n", file_name)); - err = fs_open(&hs->file_handle, file_name); - if (err == ERR_OK) { - uri = file_name; - file = &hs->file_handle; - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opened.\n")); -#if LWIP_HTTPD_SSI - tag_check = httpd_default_filenames[loop].shtml; -#endif /* LWIP_HTTPD_SSI */ - break; - } - } - } - if (file == NULL) { - /* No - we've been asked for a specific file. */ - /* First, isolate the base URI (without any parameters) */ - params = (char *)strchr(uri, '?'); - if (params != NULL) { - /* URI contains parameters. NULL-terminate the base URI */ - *params = '\0'; - params++; - } - -#if LWIP_HTTPD_CGI - http_cgi_paramcount = -1; - /* Does the base URI we have isolated correspond to a CGI handler? */ - if (httpd_num_cgis && httpd_cgis) { - for (i = 0; i < httpd_num_cgis; i++) { - if (strcmp(uri, httpd_cgis[i].pcCGIName) == 0) { - /* - * We found a CGI that handles this URI so extract the - * parameters and call the handler. - */ - http_cgi_paramcount = extract_uri_parameters(hs, params); - uri = httpd_cgis[i].pfnCGIHandler(i, http_cgi_paramcount, hs->params, - hs->param_vals); - break; - } - } - } -#endif /* LWIP_HTTPD_CGI */ - - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opening %s\n", uri)); - - err = fs_open(&hs->file_handle, uri); - if (err == ERR_OK) { - file = &hs->file_handle; - } else { - file = http_get_404_file(hs, &uri); - } -#if LWIP_HTTPD_SSI - if (file != NULL) { - if (file->flags & FS_FILE_FLAGS_SSI) { - tag_check = 1; - } else { -#if LWIP_HTTPD_SSI_BY_FILE_EXTENSION - tag_check = http_uri_is_ssi(file, uri); -#endif /* LWIP_HTTPD_SSI_BY_FILE_EXTENSION */ - } - } -#endif /* LWIP_HTTPD_SSI */ - } - if (file == NULL) { - /* None of the default filenames exist so send back a 404 page */ - file = http_get_404_file(hs, &uri); - } - return http_init_file(hs, file, is_09, uri, tag_check, params); -} - -/** Initialize a http connection with a file to send (if found). - * Called by http_find_file and http_find_error_file. - * - * @param hs http connection state - * @param file file structure to send (or NULL if not found) - * @param is_09 1 if the request is HTTP/0.9 (no HTTP headers in response) - * @param uri the HTTP header URI - * @param tag_check enable SSI tag checking - * @param params != NULL if URI has parameters (separated by '?') - * @return ERR_OK if file was found and hs has been initialized correctly - * another err_t otherwise - */ -static err_t -http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, - u8_t tag_check, char *params) -{ -#if !LWIP_HTTPD_SUPPORT_V09 - LWIP_UNUSED_ARG(is_09); -#endif - if (file != NULL) { - /* file opened, initialise struct http_state */ -#if !LWIP_HTTPD_DYNAMIC_FILE_READ - /* If dynamic read is disabled, file data must be in one piece and available now */ - LWIP_ASSERT("file->data != NULL", file->data != NULL); -#endif - -#if LWIP_HTTPD_SSI - if (tag_check) { - struct http_ssi_state *ssi = http_ssi_state_alloc(); - if (ssi != NULL) { - ssi->tag_index = 0; - ssi->tag_state = TAG_NONE; - ssi->parsed = file->data; - ssi->parse_left = file->len; - ssi->tag_end = file->data; - hs->ssi = ssi; - } - } -#else /* LWIP_HTTPD_SSI */ - LWIP_UNUSED_ARG(tag_check); -#endif /* LWIP_HTTPD_SSI */ - hs->handle = file; -#if LWIP_HTTPD_CGI_SSI - if (params != NULL) { - /* URI contains parameters, call generic CGI handler */ - int count; -#if LWIP_HTTPD_CGI - if (http_cgi_paramcount >= 0) { - count = http_cgi_paramcount; - } else -#endif - { - count = extract_uri_parameters(hs, params); - } - httpd_cgi_handler(file, uri, count, http_cgi_params, http_cgi_param_vals -#if defined(LWIP_HTTPD_FILE_STATE) && LWIP_HTTPD_FILE_STATE - , file->state -#endif /* LWIP_HTTPD_FILE_STATE */ - ); - } -#else /* LWIP_HTTPD_CGI_SSI */ - LWIP_UNUSED_ARG(params); -#endif /* LWIP_HTTPD_CGI_SSI */ - hs->file = file->data; - LWIP_ASSERT("File length must be positive!", (file->len >= 0)); -#if LWIP_HTTPD_CUSTOM_FILES - if (file->is_custom_file && (file->data == NULL)) { - /* custom file, need to read data first (via fs_read_custom) */ - hs->left = 0; - } else -#endif /* LWIP_HTTPD_CUSTOM_FILES */ - { - hs->left = (u32_t)file->len; - } - hs->retries = 0; -#if LWIP_HTTPD_TIMING - hs->time_started = sys_now(); -#endif /* LWIP_HTTPD_TIMING */ -#if !LWIP_HTTPD_DYNAMIC_HEADERS - LWIP_ASSERT("HTTP headers not included in file system", - (hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0); -#endif /* !LWIP_HTTPD_DYNAMIC_HEADERS */ -#if LWIP_HTTPD_SUPPORT_V09 - if (is_09 && ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) != 0)) { - /* HTTP/0.9 responses are sent without HTTP header, - search for the end of the header. */ - char *file_start = lwip_strnstr(hs->file, CRLF CRLF, hs->left); - if (file_start != NULL) { - int diff = file_start + 4 - hs->file; - hs->file += diff; - hs->left -= (u32_t)diff; - } - } -#endif /* LWIP_HTTPD_SUPPORT_V09*/ - } else { - hs->handle = NULL; - hs->file = NULL; - hs->left = 0; - hs->retries = 0; - } -#if LWIP_HTTPD_DYNAMIC_HEADERS - /* Determine the HTTP headers to send based on the file extension of - * the requested URI. */ - if ((hs->handle == NULL) || ((hs->handle->flags & FS_FILE_FLAGS_HEADER_INCLUDED) == 0)) { - get_http_headers(hs, uri); - } -#else /* LWIP_HTTPD_DYNAMIC_HEADERS */ - LWIP_UNUSED_ARG(uri); -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - if (hs->keepalive) { -#if LWIP_HTTPD_SSI - if (hs->ssi != NULL) { - hs->keepalive = 0; - } else -#endif /* LWIP_HTTPD_SSI */ - { - if ((hs->handle != NULL) && - ((hs->handle->flags & (FS_FILE_FLAGS_HEADER_INCLUDED | FS_FILE_FLAGS_HEADER_PERSISTENT)) == FS_FILE_FLAGS_HEADER_INCLUDED)) { - hs->keepalive = 0; - } - } - } -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ - return ERR_OK; -} - -/** - * The pcb had an error and is already deallocated. - * The argument might still be valid (if != NULL). - */ -static void -http_err(void *arg, err_t err) -{ - struct http_state *hs = (struct http_state *)arg; - LWIP_UNUSED_ARG(err); - - LWIP_DEBUGF(HTTPD_DEBUG, ("http_err: %s", lwip_strerr(err))); - - if (hs != NULL) { - http_state_free(hs); - } -} - -/** - * Data has been sent and acknowledged by the remote host. - * This means that more data can be sent. - */ -static err_t -http_sent(void *arg, struct altcp_pcb *pcb, u16_t len) -{ - struct http_state *hs = (struct http_state *)arg; - - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_sent %p\n", (void *)pcb)); - - LWIP_UNUSED_ARG(len); - - if (hs == NULL) { - return ERR_OK; - } - - hs->retries = 0; - - http_send(pcb, hs); - - return ERR_OK; -} - -/** - * The poll function is called every 2nd second. - * If there has been no data sent (which resets the retries) in 8 seconds, close. - * If the last portion of a file has not been sent in 2 seconds, close. - * - * This could be increased, but we don't want to waste resources for bad connections. - */ -static err_t -http_poll(void *arg, struct altcp_pcb *pcb) -{ - struct http_state *hs = (struct http_state *)arg; - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: pcb=%p hs=%p pcb_state=%s\n", - (void *)pcb, (void *)hs, tcp_debug_state_str(altcp_dbg_get_tcp_state(pcb)))); - - if (hs == NULL) { - err_t closed; - /* arg is null, close. */ - LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: arg is NULL, close\n")); - closed = http_close_conn(pcb, NULL); - LWIP_UNUSED_ARG(closed); -#if LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR - if (closed == ERR_MEM) { - altcp_abort(pcb); - return ERR_ABRT; - } -#endif /* LWIP_HTTPD_ABORT_ON_CLOSE_MEM_ERROR */ - return ERR_OK; - } else { - hs->retries++; - if (hs->retries == HTTPD_MAX_RETRIES) { - LWIP_DEBUGF(HTTPD_DEBUG, ("http_poll: too many retries, close\n")); - http_close_conn(pcb, hs); - return ERR_OK; - } - - /* If this connection has a file open, try to send some more data. If - * it has not yet received a GET request, don't do this since it will - * cause the connection to close immediately. */ - if (hs->handle) { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_poll: try to send more data\n")); - if (http_send(pcb, hs)) { - /* If we wrote anything to be sent, go ahead and send it now. */ - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("tcp_output\n")); - altcp_output(pcb); - } - } - } - - return ERR_OK; -} - -/** - * Data has been received on this pcb. - * For HTTP 1.0, this should normally only happen once (if the request fits in one packet). - */ -static err_t -http_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err) -{ - struct http_state *hs = (struct http_state *)arg; - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: pcb=%p pbuf=%p err=%s\n", (void *)pcb, - (void *)p, lwip_strerr(err))); - - if ((err != ERR_OK) || (p == NULL) || (hs == NULL)) { - /* error or closed by other side? */ - if (p != NULL) { - /* Inform TCP that we have taken the data. */ - altcp_recved(pcb, p->tot_len); - pbuf_free(p); - } - if (hs == NULL) { - /* this should not happen, only to be robust */ - LWIP_DEBUGF(HTTPD_DEBUG, ("Error, http_recv: hs is NULL, close\n")); - } - http_close_conn(pcb, hs); - return ERR_OK; - } - -#if LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND - if (hs->no_auto_wnd) { - hs->unrecved_bytes += p->tot_len; - } else -#endif /* LWIP_HTTPD_SUPPORT_POST && LWIP_HTTPD_POST_MANUAL_WND */ - { - /* Inform TCP that we have taken the data. */ - altcp_recved(pcb, p->tot_len); - } - -#if LWIP_HTTPD_SUPPORT_POST - if (hs->post_content_len_left > 0) { - /* reset idle counter when POST data is received */ - hs->retries = 0; - /* this is data for a POST, pass the complete pbuf to the application */ - http_post_rxpbuf(hs, p); - /* pbuf is passed to the application, don't free it! */ - if (hs->post_content_len_left == 0) { - /* all data received, send response or close connection */ - http_send(pcb, hs); - } - return ERR_OK; - } else -#endif /* LWIP_HTTPD_SUPPORT_POST */ - { - if (hs->handle == NULL) { - err_t parsed = http_parse_request(p, hs, pcb); - LWIP_ASSERT("http_parse_request: unexpected return value", parsed == ERR_OK - || parsed == ERR_INPROGRESS || parsed == ERR_ARG || parsed == ERR_USE); -#if LWIP_HTTPD_SUPPORT_REQUESTLIST - if (parsed != ERR_INPROGRESS) { - /* request fully parsed or error */ - if (hs->req != NULL) { - pbuf_free(hs->req); - hs->req = NULL; - } - } -#endif /* LWIP_HTTPD_SUPPORT_REQUESTLIST */ - pbuf_free(p); - if (parsed == ERR_OK) { -#if LWIP_HTTPD_SUPPORT_POST - if (hs->post_content_len_left == 0) -#endif /* LWIP_HTTPD_SUPPORT_POST */ - { - LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("http_recv: data %p len %"S32_F"\n", (const void *)hs->file, hs->left)); - http_send(pcb, hs); - } - } else if (parsed == ERR_ARG) { - /* @todo: close on ERR_USE? */ - http_close_conn(pcb, hs); - } - } else { - LWIP_DEBUGF(HTTPD_DEBUG, ("http_recv: already sending data\n")); - /* already sending but still receiving data, we might want to RST here? */ - pbuf_free(p); - } - } - return ERR_OK; -} - -/** - * A new incoming connection has been accepted. - */ -static err_t -http_accept(void *arg, struct altcp_pcb *pcb, err_t err) -{ - struct http_state *hs; - LWIP_UNUSED_ARG(err); - LWIP_UNUSED_ARG(arg); - LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept %p / %p\n", (void *)pcb, arg)); - - if ((err != ERR_OK) || (pcb == NULL)) { - return ERR_VAL; - } - - /* Set priority */ - altcp_setprio(pcb, HTTPD_TCP_PRIO); - - /* Allocate memory for the structure that holds the state of the - connection - initialized by that function. */ - hs = http_state_alloc(); - if (hs == NULL) { - LWIP_DEBUGF(HTTPD_DEBUG, ("http_accept: Out of memory, RST\n")); - return ERR_MEM; - } - hs->pcb = pcb; - - /* Tell TCP that this is the structure we wish to be passed for our - callbacks. */ - altcp_arg(pcb, hs); - - /* Set up the various callback functions */ - altcp_recv(pcb, http_recv); - altcp_err(pcb, http_err); - altcp_poll(pcb, http_poll, HTTPD_POLL_INTERVAL); - altcp_sent(pcb, http_sent); - - return ERR_OK; -} - -static void -httpd_init_pcb(struct altcp_pcb *pcb, u16_t port) -{ - err_t err; - - if (pcb) { - altcp_setprio(pcb, HTTPD_TCP_PRIO); - /* set SOF_REUSEADDR here to explicitly bind httpd to multiple interfaces */ - err = altcp_bind(pcb, IP_ANY_TYPE, port); - LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("httpd_init: tcp_bind failed", err == ERR_OK); - pcb = altcp_listen(pcb); - LWIP_ASSERT("httpd_init: tcp_listen failed", pcb != NULL); - altcp_accept(pcb, http_accept); - } -} - -/** - * @ingroup httpd - * Initialize the httpd: set up a listening PCB and bind it to the defined port - */ -void -httpd_init(void) -{ - struct altcp_pcb *pcb; - -#if HTTPD_USE_MEM_POOL - LWIP_MEMPOOL_INIT(HTTPD_STATE); -#if LWIP_HTTPD_SSI - LWIP_MEMPOOL_INIT(HTTPD_SSI_STATE); -#endif -#endif - LWIP_DEBUGF(HTTPD_DEBUG, ("httpd_init\n")); - - /* LWIP_ASSERT_CORE_LOCKED(); is checked by tcp_new() */ - - pcb = altcp_tcp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ASSERT("httpd_init: tcp_new failed", pcb != NULL); - httpd_init_pcb(pcb, HTTPD_SERVER_PORT); -} - -#if HTTPD_ENABLE_HTTPS -/** - * @ingroup httpd - * Initialize the httpd: set up a listening PCB and bind it to the defined port. - * Also set up TLS connection handling (HTTPS). - */ -void -httpd_inits(struct altcp_tls_config *conf) -{ -#if LWIP_ALTCP_TLS - struct altcp_pcb *pcb_tls = altcp_tls_new(conf, IPADDR_TYPE_ANY); - LWIP_ASSERT("httpd_init: altcp_tls_new failed", pcb_tls != NULL); - httpd_init_pcb(pcb_tls, HTTPD_SERVER_PORT_HTTPS); -#else /* LWIP_ALTCP_TLS */ - LWIP_UNUSED_ARG(conf); -#endif /* LWIP_ALTCP_TLS */ -} -#endif /* HTTPD_ENABLE_HTTPS */ - -#if LWIP_HTTPD_SSI -/** - * @ingroup httpd - * Set the SSI handler function. - * - * @param ssi_handler the SSI handler function - * @param tags an array of SSI tag strings to search for in SSI-enabled files - * @param num_tags number of tags in the 'tags' array - */ -void -http_set_ssi_handler(tSSIHandler ssi_handler, const char **tags, int num_tags) -{ - LWIP_DEBUGF(HTTPD_DEBUG, ("http_set_ssi_handler\n")); - - LWIP_ASSERT("no ssi_handler given", ssi_handler != NULL); - httpd_ssi_handler = ssi_handler; - -#if LWIP_HTTPD_SSI_RAW - LWIP_UNUSED_ARG(tags); - LWIP_UNUSED_ARG(num_tags); -#else /* LWIP_HTTPD_SSI_RAW */ - LWIP_ASSERT("no tags given", tags != NULL); - LWIP_ASSERT("invalid number of tags", num_tags > 0); - - httpd_tags = tags; - httpd_num_tags = num_tags; -#endif /* !LWIP_HTTPD_SSI_RAW */ -} -#endif /* LWIP_HTTPD_SSI */ - -#if LWIP_HTTPD_CGI -/** - * @ingroup httpd - * Set an array of CGI filenames/handler functions - * - * @param cgis an array of CGI filenames/handler functions - * @param num_handlers number of elements in the 'cgis' array - */ -void -http_set_cgi_handlers(const tCGI *cgis, int num_handlers) -{ - LWIP_ASSERT("no cgis given", cgis != NULL); - LWIP_ASSERT("invalid number of handlers", num_handlers > 0); - - httpd_cgis = cgis; - httpd_num_cgis = num_handlers; -} -#endif /* LWIP_HTTPD_CGI */ - -#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/httpd_structs.h b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/httpd_structs.h deleted file mode 100644 index 56b97a32b..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/httpd_structs.h +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef LWIP_HTTPD_STRUCTS_H -#define LWIP_HTTPD_STRUCTS_H - -#include "lwip/apps/httpd.h" - -#if LWIP_HTTPD_DYNAMIC_HEADERS -/** This struct is used for a list of HTTP header strings for various - * filename extensions. */ -typedef struct { - const char *extension; - const char *content_type; -} tHTTPHeader; - -/** A list of strings used in HTTP headers (see RFC 1945 HTTP/1.0 and - * RFC 2616 HTTP/1.1 for header field definitions) */ -static const char *const g_psHTTPHeaderStrings[] = { - "HTTP/1.0 200 OK\r\n", - "HTTP/1.0 404 File not found\r\n", - "HTTP/1.0 400 Bad Request\r\n", - "HTTP/1.0 501 Not Implemented\r\n", - "HTTP/1.1 200 OK\r\n", - "HTTP/1.1 404 File not found\r\n", - "HTTP/1.1 400 Bad Request\r\n", - "HTTP/1.1 501 Not Implemented\r\n", - "Content-Length: ", - "Connection: Close\r\n", - "Connection: keep-alive\r\n", - "Connection: keep-alive\r\nContent-Length: ", - "Server: "HTTPD_SERVER_AGENT"\r\n", - "\r\n

404: The requested file cannot be found.

\r\n" -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE - , "Connection: keep-alive\r\nContent-Length: 77\r\n\r\n

404: The requested file cannot be found.

\r\n" -#endif -}; - -/* Indexes into the g_psHTTPHeaderStrings array */ -#define HTTP_HDR_OK 0 /* 200 OK */ -#define HTTP_HDR_NOT_FOUND 1 /* 404 File not found */ -#define HTTP_HDR_BAD_REQUEST 2 /* 400 Bad request */ -#define HTTP_HDR_NOT_IMPL 3 /* 501 Not Implemented */ -#define HTTP_HDR_OK_11 4 /* 200 OK */ -#define HTTP_HDR_NOT_FOUND_11 5 /* 404 File not found */ -#define HTTP_HDR_BAD_REQUEST_11 6 /* 400 Bad request */ -#define HTTP_HDR_NOT_IMPL_11 7 /* 501 Not Implemented */ -#define HTTP_HDR_CONTENT_LENGTH 8 /* Content-Length: (HTTP 1.0)*/ -#define HTTP_HDR_CONN_CLOSE 9 /* Connection: Close (HTTP 1.1) */ -#define HTTP_HDR_CONN_KEEPALIVE 10 /* Connection: keep-alive (HTTP 1.1) */ -#define HTTP_HDR_KEEPALIVE_LEN 11 /* Connection: keep-alive + Content-Length: (HTTP 1.1)*/ -#define HTTP_HDR_SERVER 12 /* Server: HTTPD_SERVER_AGENT */ -#define DEFAULT_404_HTML 13 /* default 404 body */ -#if LWIP_HTTPD_SUPPORT_11_KEEPALIVE -#define DEFAULT_404_HTML_PERSISTENT 14 /* default 404 body, but including Connection: keep-alive */ -#endif - -#define HTTP_CONTENT_TYPE(contenttype) "Content-Type: "contenttype"\r\n\r\n" -#define HTTP_CONTENT_TYPE_ENCODING(contenttype, encoding) "Content-Type: "contenttype"\r\nContent-Encoding: "encoding"\r\n\r\n" - -#define HTTP_HDR_HTML HTTP_CONTENT_TYPE("text/html") -#define HTTP_HDR_SSI HTTP_CONTENT_TYPE("text/html\r\nExpires: Fri, 10 Apr 2008 14:00:00 GMT\r\nPragma: no-cache") -#define HTTP_HDR_GIF HTTP_CONTENT_TYPE("image/gif") -#define HTTP_HDR_PNG HTTP_CONTENT_TYPE("image/png") -#define HTTP_HDR_JPG HTTP_CONTENT_TYPE("image/jpeg") -#define HTTP_HDR_BMP HTTP_CONTENT_TYPE("image/bmp") -#define HTTP_HDR_ICO HTTP_CONTENT_TYPE("image/x-icon") -#define HTTP_HDR_APP HTTP_CONTENT_TYPE("application/octet-stream") -#define HTTP_HDR_JS HTTP_CONTENT_TYPE("application/javascript") -#define HTTP_HDR_RA HTTP_CONTENT_TYPE("application/javascript") -#define HTTP_HDR_CSS HTTP_CONTENT_TYPE("text/css") -#define HTTP_HDR_SWF HTTP_CONTENT_TYPE("application/x-shockwave-flash") -#define HTTP_HDR_XML HTTP_CONTENT_TYPE("text/xml") -#define HTTP_HDR_PDF HTTP_CONTENT_TYPE("application/pdf") -#define HTTP_HDR_JSON HTTP_CONTENT_TYPE("application/json") -#define HTTP_HDR_CSV HTTP_CONTENT_TYPE("text/csv") -#define HTTP_HDR_TSV HTTP_CONTENT_TYPE("text/tsv") -#define HTTP_HDR_SVG HTTP_CONTENT_TYPE("image/svg+xml") -#define HTTP_HDR_SVGZ HTTP_CONTENT_TYPE_ENCODING("image/svg+xml", "gzip") - -#define HTTP_HDR_DEFAULT_TYPE HTTP_CONTENT_TYPE("text/plain") - -/** A list of extension-to-HTTP header strings (see outdated RFC 1700 MEDIA TYPES - * and http://www.iana.org/assignments/media-types for registered content types - * and subtypes) */ -static const tHTTPHeader g_psHTTPHeaders[] = { - { "html", HTTP_HDR_HTML}, - { "htm", HTTP_HDR_HTML}, - { "shtml", HTTP_HDR_SSI}, - { "shtm", HTTP_HDR_SSI}, - { "ssi", HTTP_HDR_SSI}, - { "gif", HTTP_HDR_GIF}, - { "png", HTTP_HDR_PNG}, - { "jpg", HTTP_HDR_JPG}, - { "bmp", HTTP_HDR_BMP}, - { "ico", HTTP_HDR_ICO}, - { "class", HTTP_HDR_APP}, - { "cls", HTTP_HDR_APP}, - { "js", HTTP_HDR_JS}, - { "ram", HTTP_HDR_RA}, - { "css", HTTP_HDR_CSS}, - { "swf", HTTP_HDR_SWF}, - { "xml", HTTP_HDR_XML}, - { "xsl", HTTP_HDR_XML}, - { "pdf", HTTP_HDR_PDF}, - { "json", HTTP_HDR_JSON} -#ifdef HTTPD_ADDITIONAL_CONTENT_TYPES - /* If you need to add content types not listed here: - * #define HTTPD_ADDITIONAL_CONTENT_TYPES {"ct1", HTTP_CONTENT_TYPE("text/ct1")}, {"exe", HTTP_CONTENT_TYPE("application/exe")} - */ - , HTTPD_ADDITIONAL_CONTENT_TYPES -#endif -}; - -#define NUM_HTTP_HEADERS LWIP_ARRAYSIZE(g_psHTTPHeaders) - -#endif /* LWIP_HTTPD_DYNAMIC_HEADERS */ - -#if LWIP_HTTPD_SSI -static const char *const g_pcSSIExtensions[] = { - ".shtml", ".shtm", ".ssi", ".xml", ".json" -}; -#define NUM_SHTML_EXTENSIONS LWIP_ARRAYSIZE(g_pcSSIExtensions) -#endif /* LWIP_HTTPD_SSI */ - -#endif /* LWIP_HTTPD_STRUCTS_H */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/makefsdata/makefsdata b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/makefsdata/makefsdata deleted file mode 100644 index 37b4203e6..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/makefsdata/makefsdata +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/perl - -open(OUTPUT, "> fsdata.c"); - -chdir("fs"); -open(FILES, "find . -type f |"); - -while($file = ) { - - # Do not include files in CVS directories nor backup files. - if($file =~ /(CVS|~)/) { - next; - } - - chop($file); - - open(HEADER, "> /tmp/header") || die $!; - if($file =~ /404/) { - print(HEADER "HTTP/1.0 404 File not found\r\n"); - } else { - print(HEADER "HTTP/1.0 200 OK\r\n"); - } - print(HEADER "Server: lwIP/pre-0.6 (http://www.sics.se/~adam/lwip/)\r\n"); - if($file =~ /\.html$/) { - print(HEADER "Content-type: text/html\r\n"); - } elsif($file =~ /\.gif$/) { - print(HEADER "Content-type: image/gif\r\n"); - } elsif($file =~ /\.png$/) { - print(HEADER "Content-type: image/png\r\n"); - } elsif($file =~ /\.jpg$/) { - print(HEADER "Content-type: image/jpeg\r\n"); - } elsif($file =~ /\.class$/) { - print(HEADER "Content-type: application/octet-stream\r\n"); - } elsif($file =~ /\.ram$/) { - print(HEADER "Content-type: audio/x-pn-realaudio\r\n"); - } else { - print(HEADER "Content-type: text/plain\r\n"); - } - print(HEADER "\r\n"); - close(HEADER); - - unless($file =~ /\.plain$/ || $file =~ /cgi/) { - system("cat /tmp/header $file > /tmp/file"); - } else { - system("cp $file /tmp/file"); - } - - open(FILE, "/tmp/file"); - unlink("/tmp/file"); - unlink("/tmp/header"); - - $file =~ s/\.//; - $fvar = $file; - $fvar =~ s-/-_-g; - $fvar =~ s-\.-_-g; - print(OUTPUT "static const unsigned char data".$fvar."[] = {\n"); - print(OUTPUT "\t/* $file */\n\t"); - for($j = 0; $j < length($file); $j++) { - printf(OUTPUT "%#02x, ", unpack("C", substr($file, $j, 1))); - } - printf(OUTPUT "0,\n"); - - - $i = 0; - while(read(FILE, $data, 1)) { - if($i == 0) { - print(OUTPUT "\t"); - } - printf(OUTPUT "%#02x, ", unpack("C", $data)); - $i++; - if($i == 10) { - print(OUTPUT "\n"); - $i = 0; - } - } - print(OUTPUT "};\n\n"); - close(FILE); - push(@fvars, $fvar); - push(@files, $file); -} - -for($i = 0; $i < @fvars; $i++) { - $file = $files[$i]; - $fvar = $fvars[$i]; - - if($i == 0) { - $prevfile = "NULL"; - } else { - $prevfile = "file" . $fvars[$i - 1]; - } - print(OUTPUT "const struct fsdata_file file".$fvar."[] = {{$prevfile, data$fvar, "); - print(OUTPUT "data$fvar + ". (length($file) + 1) .", "); - print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n"); -} - -print(OUTPUT "#define FS_ROOT file$fvars[$i - 1]\n\n"); -print(OUTPUT "#define FS_NUMFILES $i\n"); diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/makefsdata/makefsdata.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/makefsdata/makefsdata.c deleted file mode 100644 index 695e94f5f..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/makefsdata/makefsdata.c +++ /dev/null @@ -1,1251 +0,0 @@ -/** - * makefsdata: Converts a directory structure for use with the lwIP httpd. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Jim Pettinato - * Simon Goldschmidt - * - * @todo: - * - take TCP_MSS, LWIP_TCP_TIMESTAMPS and - * PAYLOAD_ALIGN_TYPE/PAYLOAD_ALIGNMENT as arguments - */ - -#include -#include -#include -#include -#include - -#include "tinydir.h" - -/** Makefsdata can generate *all* files deflate-compressed (where file size shrinks). - * Since nearly all browsers support this, this is a good way to reduce ROM size. - * To compress the files, "miniz.c" must be downloaded seperately. - */ -#ifndef MAKEFS_SUPPORT_DEFLATE -#define MAKEFS_SUPPORT_DEFLATE 0 -#endif - -#define COPY_BUFSIZE (1024*1024) /* 1 MByte */ - -#if MAKEFS_SUPPORT_DEFLATE -#include "../miniz.c" - -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint; - -#define my_max(a,b) (((a) > (b)) ? (a) : (b)) -#define my_min(a,b) (((a) < (b)) ? (a) : (b)) - -/* COMP_OUT_BUF_SIZE is the size of the output buffer used during compression. - COMP_OUT_BUF_SIZE must be >= 1 and <= OUT_BUF_SIZE */ -#define COMP_OUT_BUF_SIZE COPY_BUFSIZE - -/* OUT_BUF_SIZE is the size of the output buffer used during decompression. - OUT_BUF_SIZE must be a power of 2 >= TINFL_LZ_DICT_SIZE (because the low-level decompressor not only writes, but reads from the output buffer as it decompresses) */ -#define OUT_BUF_SIZE COPY_BUFSIZE -static uint8 s_outbuf[OUT_BUF_SIZE]; -static uint8 s_checkbuf[OUT_BUF_SIZE]; - -/* tdefl_compressor contains all the state needed by the low-level compressor so it's a pretty big struct (~300k). - This example makes it a global vs. putting it on the stack, of course in real-world usage you'll probably malloc() or new it. */ -tdefl_compressor g_deflator; -tinfl_decompressor g_inflator; - -int deflate_level = 10; /* default compression level, can be changed via command line */ -#define USAGE_ARG_DEFLATE " [-defl<:compr_level>]" -#else /* MAKEFS_SUPPORT_DEFLATE */ -#define USAGE_ARG_DEFLATE "" -#endif /* MAKEFS_SUPPORT_DEFLATE */ - -#ifdef WIN32 - -#define GETCWD(path, len) GetCurrentDirectoryA(len, path) -#define CHDIR(path) SetCurrentDirectoryA(path) -#define CHDIR_SUCCEEDED(ret) (ret == TRUE) - -#elif __linux__ - -#define GETCWD(path, len) getcwd(path, len) -#define CHDIR(path) chdir(path) -#define CHDIR_SUCCEEDED(ret) (ret == 0) - -#else - -#error makefsdata not supported on this platform - -#endif - -#define NEWLINE "\r\n" -#define NEWLINE_LEN 2 - -/* define this to get the header variables we use to build HTTP headers */ -#define LWIP_HTTPD_DYNAMIC_HEADERS 1 -#define LWIP_HTTPD_SSI 1 -#include "lwip/init.h" -#include "../httpd_structs.h" -#include "lwip/apps/fs.h" - -#include "../core/inet_chksum.c" -#include "../core/def.c" - -/** (Your server name here) */ -const char *serverID = "Server: "HTTPD_SERVER_AGENT"\r\n"; -char serverIDBuffer[1024]; - -/* change this to suit your MEM_ALIGNMENT */ -#define PAYLOAD_ALIGNMENT 4 -/* set this to 0 to prevent aligning payload */ -#define ALIGN_PAYLOAD 1 -/* define this to a type that has the required alignment */ -#define PAYLOAD_ALIGN_TYPE "unsigned int" -static int payload_alingment_dummy_counter = 0; - -#define HEX_BYTES_PER_LINE 16 - -#define MAX_PATH_LEN 256 - -struct file_entry { - struct file_entry *next; - const char *filename_c; -}; - -int process_sub(FILE *data_file, FILE *struct_file); -int process_file(FILE *data_file, FILE *struct_file, const char *filename); -int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len, - u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed); -int file_put_ascii(FILE *file, const char *ascii_string, int len, int *i); -int s_put_ascii(char *buf, const char *ascii_string, int len, int *i); -void concat_files(const char *file1, const char *file2, const char *targetfile); -int check_path(char *path, size_t size); -static int checkSsiByFilelist(const char* filename_listfile); -static int ext_in_list(const char* filename, const char *ext_list); -static int file_to_exclude(const char* filename); -static int file_can_be_compressed(const char* filename); - -/* 5 bytes per char + 3 bytes per line */ -static char file_buffer_c[COPY_BUFSIZE * 5 + ((COPY_BUFSIZE / HEX_BYTES_PER_LINE) * 3)]; - -char curSubdir[MAX_PATH_LEN]; -char lastFileVar[MAX_PATH_LEN]; -char hdr_buf[4096]; - -unsigned char processSubs = 1; -unsigned char includeHttpHeader = 1; -unsigned char useHttp11 = 0; -unsigned char supportSsi = 1; -unsigned char precalcChksum = 0; -unsigned char includeLastModified = 0; -#if MAKEFS_SUPPORT_DEFLATE -unsigned char deflateNonSsiFiles = 0; -size_t deflatedBytesReduced = 0; -size_t overallDataBytes = 0; -#endif -const char *exclude_list = NULL; -const char *ncompress_list = NULL; - -struct file_entry *first_file = NULL; -struct file_entry *last_file = NULL; - -static char *ssi_file_buffer; -static char **ssi_file_lines; -static size_t ssi_file_num_lines; - -static void print_usage(void) -{ - printf(" Usage: htmlgen [targetdir] [-s] [-e] [-11] [-nossi] [-ssi:] [-c] [-f:] [-m] [-svr:] [-x:] [-xc:" USAGE_ARG_DEFLATE NEWLINE NEWLINE); - printf(" targetdir: relative or absolute path to files to convert" NEWLINE); - printf(" switch -s: toggle processing of subdirectories (default is on)" NEWLINE); - printf(" switch -e: exclude HTTP header from file (header is created at runtime, default is off)" NEWLINE); - printf(" switch -11: include HTTP 1.1 header (1.0 is default)" NEWLINE); - printf(" switch -nossi: no support for SSI (cannot calculate Content-Length for SSI)" NEWLINE); - printf(" switch -ssi: ssi filename (ssi support controlled by file list, not by extension)" NEWLINE); - printf(" switch -c: precalculate checksums for all pages (default is off)" NEWLINE); - printf(" switch -f: target filename (default is \"fsdata.c\")" NEWLINE); - printf(" switch -m: include \"Last-Modified\" header based on file time" NEWLINE); - printf(" switch -svr: server identifier sent in HTTP response header ('Server' field)" NEWLINE); - printf(" switch -x: comma separated list of extensions of files to exclude (e.g., -x:json,txt)" NEWLINE); - printf(" switch -xc: comma separated list of extensions of files to not compress (e.g., -xc:mp3,jpg)" NEWLINE); -#if MAKEFS_SUPPORT_DEFLATE - printf(" switch -defl: deflate-compress all non-SSI files (with opt. compr.-level, default=10)" NEWLINE); - printf(" ATTENTION: browser has to support \"Content-Encoding: deflate\"!" NEWLINE); -#endif - printf(" if targetdir not specified, htmlgen will attempt to" NEWLINE); - printf(" process files in subdirectory 'fs'" NEWLINE); -} - -int main(int argc, char *argv[]) -{ - char path[MAX_PATH_LEN]; - char appPath[MAX_PATH_LEN]; - FILE *data_file; - FILE *struct_file; - int filesProcessed; - int i; - char targetfile[MAX_PATH_LEN]; - strcpy(targetfile, "fsdata.c"); - - memset(path, 0, sizeof(path)); - memset(appPath, 0, sizeof(appPath)); - - printf(NEWLINE " makefsdata - HTML to C source converter" NEWLINE); - printf(" by Jim Pettinato - circa 2003 " NEWLINE); - printf(" extended by Simon Goldschmidt - 2009 " NEWLINE NEWLINE); - - LWIP_ASSERT("sizeof(hdr_buf) must fit into an u16_t", sizeof(hdr_buf) <= 0xffff); - - strcpy(path, "fs"); - for (i = 1; i < argc; i++) { - if (argv[i] == NULL) { - continue; - } - if (argv[i][0] == '-') { - if (strstr(argv[i], "-svr:") == argv[i]) { - snprintf(serverIDBuffer, sizeof(serverIDBuffer), "Server: %s\r\n", &argv[i][5]); - serverID = serverIDBuffer; - printf("Using Server-ID: \"%s\"\n", serverID); - } else if (!strcmp(argv[i], "-s")) { - processSubs = 0; - } else if (!strcmp(argv[i], "-e")) { - includeHttpHeader = 0; - } else if (!strcmp(argv[i], "-11")) { - useHttp11 = 1; - } else if (!strcmp(argv[i], "-nossi")) { - supportSsi = 0; - } else if (strstr(argv[i], "-ssi:") == argv[i]) { - const char* ssi_list_filename = &argv[i][5]; - if (checkSsiByFilelist(ssi_list_filename)) { - printf("Reading list of SSI files from \"%s\"\n", ssi_list_filename); - } else { - printf("Failed to load list of SSI files from \"%s\"\n", ssi_list_filename); - } - } else if (!strcmp(argv[i], "-c")) { - precalcChksum = 1; - } else if (strstr(argv[i], "-f:") == argv[i]) { - strncpy(targetfile, &argv[i][3], sizeof(targetfile) - 1); - targetfile[sizeof(targetfile) - 1] = 0; - printf("Writing to file \"%s\"\n", targetfile); - } else if (!strcmp(argv[i], "-m")) { - includeLastModified = 1; - } else if (!strcmp(argv[i], "-defl")) { -#if MAKEFS_SUPPORT_DEFLATE - char *colon = strstr(argv[i], ":"); - if (colon) { - if (colon[1] != 0) { - int defl_level = atoi(&colon[1]); - if ((defl_level >= 0) && (defl_level <= 10)) { - deflate_level = defl_level; - } else { - printf("ERROR: deflate level must be [0..10]" NEWLINE); - exit(0); - } - } - } - deflateNonSsiFiles = 1; - printf("Deflating all non-SSI files with level %d (but only if size is reduced)" NEWLINE, deflate_level); -#else - printf("WARNING: Deflate support is disabled\n"); -#endif - } else if (strstr(argv[i], "-x:") == argv[i]) { - exclude_list = &argv[i][3]; - printf("Excluding files with extensions %s" NEWLINE, exclude_list); - } else if (strstr(argv[i], "-xc:") == argv[i]) { - ncompress_list = &argv[i][4]; - printf("Skipping compresion for files with extensions %s" NEWLINE, ncompress_list); - } else if ((strstr(argv[i], "-?")) || (strstr(argv[i], "-h"))) { - print_usage(); - exit(0); - } - } else if ((argv[i][0] == '/') && (argv[i][1] == '?') && (argv[i][2] == 0)) { - print_usage(); - exit(0); - } else { - strncpy(path, argv[i], sizeof(path) - 1); - path[sizeof(path) - 1] = 0; - } - } - - if (!check_path(path, sizeof(path))) { - printf("Invalid path: \"%s\"." NEWLINE, path); - exit(-1); - } - - GETCWD(appPath, MAX_PATH_LEN); - /* if command line param or subdir named 'fs' not found spout usage verbiage */ - if (!CHDIR_SUCCEEDED(CHDIR(path))) { - /* if no subdir named 'fs' (or the one which was given) exists, spout usage verbiage */ - printf(" Failed to open directory \"%s\"." NEWLINE NEWLINE, path); - print_usage(); - exit(-1); - } - CHDIR(appPath); - - printf("HTTP %sheader will %s statically included." NEWLINE, - (includeHttpHeader ? (useHttp11 ? "1.1 " : "1.0 ") : ""), - (includeHttpHeader ? "be" : "not be")); - - curSubdir[0] = '\0'; /* start off in web page's root directory - relative paths */ - printf(" Processing all files in directory %s", path); - if (processSubs) { - printf(" and subdirectories..." NEWLINE NEWLINE); - } else { - printf("..." NEWLINE NEWLINE); - } - - data_file = fopen("fsdata.tmp", "wb"); - if (data_file == NULL) { - printf("Failed to create file \"fsdata.tmp\"\n"); - exit(-1); - } - struct_file = fopen("fshdr.tmp", "wb"); - if (struct_file == NULL) { - printf("Failed to create file \"fshdr.tmp\"\n"); - fclose(data_file); - exit(-1); - } - - CHDIR(path); - - fprintf(data_file, "#include \"lwip/apps/fs.h\"" NEWLINE); - fprintf(data_file, "#include \"lwip/def.h\"" NEWLINE NEWLINE NEWLINE); - - fprintf(data_file, "#define file_NULL (struct fsdata_file *) NULL" NEWLINE NEWLINE NEWLINE); - /* define FS_FILE_FLAGS_HEADER_INCLUDED to 1 if not defined (compatibility with older httpd/fs) */ - fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_INCLUDED" NEWLINE "#define FS_FILE_FLAGS_HEADER_INCLUDED 1" NEWLINE "#endif" NEWLINE); - /* define FS_FILE_FLAGS_HEADER_PERSISTENT to 0 if not defined (compatibility with older httpd/fs: wasn't supported back then) */ - fprintf(data_file, "#ifndef FS_FILE_FLAGS_HEADER_PERSISTENT" NEWLINE "#define FS_FILE_FLAGS_HEADER_PERSISTENT 0" NEWLINE "#endif" NEWLINE); - - /* define alignment defines */ -#if ALIGN_PAYLOAD - fprintf(data_file, "/* FSDATA_FILE_ALIGNMENT: 0=off, 1=by variable, 2=by include */" NEWLINE "#ifndef FSDATA_FILE_ALIGNMENT" NEWLINE "#define FSDATA_FILE_ALIGNMENT 0" NEWLINE "#endif" NEWLINE); -#endif - fprintf(data_file, "#ifndef FSDATA_ALIGN_PRE" NEWLINE "#define FSDATA_ALIGN_PRE" NEWLINE "#endif" NEWLINE); - fprintf(data_file, "#ifndef FSDATA_ALIGN_POST" NEWLINE "#define FSDATA_ALIGN_POST" NEWLINE "#endif" NEWLINE); -#if ALIGN_PAYLOAD - fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==2" NEWLINE "#include \"fsdata_alignment.h\"" NEWLINE "#endif" NEWLINE); -#endif - - sprintf(lastFileVar, "NULL"); - - filesProcessed = process_sub(data_file, struct_file); - - /* data_file now contains all of the raw data.. now append linked list of - * file header structs to allow embedded app to search for a file name */ - fprintf(data_file, NEWLINE NEWLINE); - fprintf(struct_file, "#define FS_ROOT file_%s" NEWLINE, lastFileVar); - fprintf(struct_file, "#define FS_NUMFILES %d" NEWLINE NEWLINE, filesProcessed); - - fclose(data_file); - fclose(struct_file); - - CHDIR(appPath); - /* append struct_file to data_file */ - printf(NEWLINE "Creating target file..." NEWLINE NEWLINE); - concat_files("fsdata.tmp", "fshdr.tmp", targetfile); - - /* if succeeded, delete the temporary files */ - if (remove("fsdata.tmp") != 0) { - printf("Warning: failed to delete fsdata.tmp\n"); - } - if (remove("fshdr.tmp") != 0) { - printf("Warning: failed to delete fshdr.tmp\n"); - } - - printf(NEWLINE "Processed %d files - done." NEWLINE, filesProcessed); -#if MAKEFS_SUPPORT_DEFLATE - if (deflateNonSsiFiles) { - printf("(Deflated total byte reduction: %d bytes -> %d bytes (%.02f%%)" NEWLINE, - (int)overallDataBytes, (int)deflatedBytesReduced, (float)((deflatedBytesReduced * 100.0) / overallDataBytes)); - } -#endif - printf(NEWLINE); - - while (first_file != NULL) { - struct file_entry *fe = first_file; - first_file = fe->next; - free(fe); - } - - if (ssi_file_buffer) { - free(ssi_file_buffer); - } - if (ssi_file_lines) { - free(ssi_file_lines); - } - - return 0; -} - -int check_path(char *path, size_t size) -{ - size_t slen; - if (path[0] == 0) { - /* empty */ - return 0; - } - slen = strlen(path); - if (slen >= size) { - /* not NULL-terminated */ - return 0; - } - while ((slen > 0) && ((path[slen] == '\\') || (path[slen] == '/'))) { - /* path should not end with trailing backslash */ - path[slen] = 0; - slen--; - } - if (slen == 0) { - return 0; - } - return 1; -} - -static void copy_file(const char *filename_in, FILE *fout) -{ - FILE *fin; - size_t len; - void *buf; - fin = fopen(filename_in, "rb"); - if (fin == NULL) { - printf("Failed to open file \"%s\"\n", filename_in); - exit(-1); - } - buf = malloc(COPY_BUFSIZE); - while ((len = fread(buf, 1, COPY_BUFSIZE, fin)) > 0) { - fwrite(buf, 1, len, fout); - } - free(buf); - fclose(fin); -} - -void concat_files(const char *file1, const char *file2, const char *targetfile) -{ - FILE *fout; - fout = fopen(targetfile, "wb"); - if (fout == NULL) { - printf("Failed to open file \"%s\"\n", targetfile); - exit(-1); - } - copy_file(file1, fout); - copy_file(file2, fout); - fclose(fout); -} - -int process_sub(FILE *data_file, FILE *struct_file) -{ - tinydir_dir dir; - int filesProcessed = 0; - - if (processSubs) { - /* process subs recursively */ - size_t sublen = strlen(curSubdir); - size_t freelen = sizeof(curSubdir) - sublen - 1; - int ret; - LWIP_ASSERT("sublen < sizeof(curSubdir)", sublen < sizeof(curSubdir)); - - ret = tinydir_open_sorted(&dir, TINYDIR_STRING(".")); - - if (ret == 0) { - unsigned int i; - for (i = 0; i < dir.n_files; i++) { - tinydir_file file; - - ret = tinydir_readfile_n(&dir, &file, i); - - if (ret == 0) { -#if (defined _MSC_VER || defined __MINGW32__) && (defined _UNICODE) - size_t num_char_converted; - char currName[256]; - wcstombs_s(&num_char_converted, currName, sizeof(currName), file.name, sizeof(currName)); -#else - const char *currName = file.name; -#endif - - if (currName[0] == '.') { - continue; - } - if (!file.is_dir) { - continue; - } - if (freelen > 0) { - CHDIR(currName); - strncat(curSubdir, "/", freelen); - strncat(curSubdir, currName, freelen - 1); - curSubdir[sizeof(curSubdir) - 1] = 0; - printf("processing subdirectory %s/..." NEWLINE, curSubdir); - filesProcessed += process_sub(data_file, struct_file); - CHDIR(".."); - curSubdir[sublen] = 0; - } else { - printf("WARNING: cannot process sub due to path length restrictions: \"%s/%s\"\n", curSubdir, currName); - } - } - } - } - - ret = tinydir_open_sorted(&dir, TINYDIR_STRING(".")); - if (ret == 0) { - unsigned int i; - for (i = 0; i < dir.n_files; i++) { - tinydir_file file; - - ret = tinydir_readfile_n(&dir, &file, i); - - if (ret == 0) { - if (!file.is_dir) { -#if (defined _MSC_VER || defined __MINGW32__) && (defined _UNICODE) - size_t num_char_converted; - char curName[256]; - wcstombs_s(&num_char_converted, curName, sizeof(curName), file.name, sizeof(curName)); -#else - const char *curName = file.name; -#endif - - if (strcmp(curName, "fsdata.tmp") == 0) { - continue; - } - if (strcmp(curName, "fshdr.tmp") == 0) { - continue; - } - if (file_to_exclude(curName)) { - printf("skipping %s/%s by exclude list (-x option)..." NEWLINE, curSubdir, curName); - continue; - } - - printf("processing %s/%s..." NEWLINE, curSubdir, curName); - - if (process_file(data_file, struct_file, curName) < 0) { - printf(NEWLINE "Error... aborting" NEWLINE); - return -1; - } - filesProcessed++; - } - } - } - } - } - - return filesProcessed; -} - -static u8_t *get_file_data(const char *filename, int *file_size, int can_be_compressed, int *is_compressed) -{ - FILE *inFile; - size_t fsize = 0; - u8_t *buf; - size_t r; - int rs; - LWIP_UNUSED_ARG(r); /* for LWIP_NOASSERT */ - inFile = fopen(filename, "rb"); - if (inFile == NULL) { - printf("Failed to open file \"%s\"\n", filename); - exit(-1); - } - fseek(inFile, 0, SEEK_END); - rs = ftell(inFile); - if (rs < 0) { - printf("ftell failed with %d\n", errno); - exit(-1); - } - fsize = (size_t)rs; - fseek(inFile, 0, SEEK_SET); - buf = (u8_t *)malloc(fsize); - LWIP_ASSERT("buf != NULL", buf != NULL); - r = fread(buf, 1, fsize, inFile); - LWIP_ASSERT("r == fsize", r == fsize); - *file_size = fsize; - *is_compressed = 0; -#if MAKEFS_SUPPORT_DEFLATE - overallDataBytes += fsize; - if (deflateNonSsiFiles) { - if (can_be_compressed) { - if (fsize < OUT_BUF_SIZE) { - u8_t *ret_buf; - tdefl_status status; - size_t in_bytes = fsize; - size_t out_bytes = OUT_BUF_SIZE; - const void *next_in = buf; - void *next_out = s_outbuf; - /* create tdefl() compatible flags (we have to compose the low-level flags ourselves, or use tdefl_create_comp_flags_from_zip_params() but that means MINIZ_NO_ZLIB_APIS can't be defined). */ - mz_uint comp_flags = s_tdefl_num_probes[MZ_MIN(10, deflate_level)] | ((deflate_level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); - if (!deflate_level) { - comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; - } - status = tdefl_init(&g_deflator, NULL, NULL, comp_flags); - if (status != TDEFL_STATUS_OKAY) { - printf("tdefl_init() failed!\n"); - exit(-1); - } - memset(s_outbuf, 0, sizeof(s_outbuf)); - status = tdefl_compress(&g_deflator, next_in, &in_bytes, next_out, &out_bytes, TDEFL_FINISH); - if (status != TDEFL_STATUS_DONE) { - printf("deflate failed: %d\n", status); - exit(-1); - } - LWIP_ASSERT("out_bytes <= COPY_BUFSIZE", out_bytes <= OUT_BUF_SIZE); - if (out_bytes < fsize) { - ret_buf = (u8_t *)malloc(out_bytes); - LWIP_ASSERT("ret_buf != NULL", ret_buf != NULL); - memcpy(ret_buf, s_outbuf, out_bytes); - { - /* sanity-check compression be inflating and comparing to the original */ - tinfl_status dec_status; - tinfl_decompressor inflator; - size_t dec_in_bytes = out_bytes; - size_t dec_out_bytes = OUT_BUF_SIZE; - next_out = s_checkbuf; - - tinfl_init(&inflator); - memset(s_checkbuf, 0, sizeof(s_checkbuf)); - dec_status = tinfl_decompress(&inflator, (const mz_uint8 *)ret_buf, &dec_in_bytes, s_checkbuf, (mz_uint8 *)next_out, &dec_out_bytes, 0); - LWIP_ASSERT("tinfl_decompress failed", dec_status == TINFL_STATUS_DONE); - LWIP_ASSERT("tinfl_decompress size mismatch", fsize == dec_out_bytes); - LWIP_ASSERT("decompressed memcmp failed", !memcmp(s_checkbuf, buf, fsize)); - } - /* free original buffer, use compressed data + size */ - free(buf); - buf = ret_buf; - *file_size = out_bytes; - printf(" - deflate: %d bytes -> %d bytes (%.02f%%)" NEWLINE, (int)fsize, (int)out_bytes, (float)((out_bytes * 100.0) / fsize)); - deflatedBytesReduced += (size_t)(fsize - out_bytes); - *is_compressed = 1; - } else { - printf(" - uncompressed: (would be %d bytes larger using deflate)" NEWLINE, (int)(out_bytes - fsize)); - } - } else { - printf(" - uncompressed: (file is larger than deflate bufer)" NEWLINE); - } - } else { - printf(" - cannot be compressed" NEWLINE); - } - } -#else - LWIP_UNUSED_ARG(can_be_compressed); -#endif - fclose(inFile); - return buf; -} - -static void process_file_data(FILE *data_file, u8_t *file_data, size_t file_size) -{ - size_t written, i, src_off = 0; - size_t off = 0; - LWIP_UNUSED_ARG(written); /* for LWIP_NOASSERT */ - for (i = 0; i < file_size; i++) { - LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - 5); - sprintf(&file_buffer_c[off], "0x%02x,", file_data[i]); - off += 5; - if ((++src_off % HEX_BYTES_PER_LINE) == 0) { - LWIP_ASSERT("file_buffer_c overflow", off < sizeof(file_buffer_c) - NEWLINE_LEN); - memcpy(&file_buffer_c[off], NEWLINE, NEWLINE_LEN); - off += NEWLINE_LEN; - } - if (off + 20 >= sizeof(file_buffer_c)) { - written = fwrite(file_buffer_c, 1, off, data_file); - LWIP_ASSERT("written == off", written == off); - off = 0; - } - } - written = fwrite(file_buffer_c, 1, off, data_file); - LWIP_ASSERT("written == off", written == off); -} - -static int write_checksums(FILE *struct_file, const char *varname, - u16_t hdr_len, u16_t hdr_chksum, const u8_t *file_data, size_t file_size) -{ - int chunk_size = TCP_MSS; - int offset, src_offset; - size_t len; - int i = 0; -#if LWIP_TCP_TIMESTAMPS - /* when timestamps are used, usable space is 12 bytes less per segment */ - chunk_size -= 12; -#endif - - fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); - fprintf(struct_file, "const struct fsdata_chksum chksums_%s[] = {" NEWLINE, varname); - - if (hdr_len > 0) { - /* add checksum for HTTP header */ - fprintf(struct_file, "{%d, 0x%04x, %d}," NEWLINE, 0, hdr_chksum, hdr_len); - i++; - } - src_offset = 0; - for (offset = hdr_len; ; offset += len) { - unsigned short chksum; - const void *data = (const void *)&file_data[src_offset]; - len = LWIP_MIN(chunk_size, (int)file_size - src_offset); - if (len == 0) { - break; - } - chksum = ~inet_chksum(data, (u16_t)len); - /* add checksum for data */ - fprintf(struct_file, "{%d, 0x%04x, %"SZT_F"}," NEWLINE, offset, chksum, len); - i++; - } - fprintf(struct_file, "};" NEWLINE); - fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); - return i; -} - -static int is_valid_char_for_c_var(char x) -{ - if (((x >= 'A') && (x <= 'Z')) || - ((x >= 'a') && (x <= 'z')) || - ((x >= '0') && (x <= '9')) || - (x == '_')) { - return 1; - } - return 0; -} - -static void fix_filename_for_c(char *qualifiedName, size_t max_len) -{ - struct file_entry *f; - size_t len = strlen(qualifiedName); - char *new_name = (char *)malloc(len + 2); - int filename_ok; - int cnt = 0; - size_t i; - if (len + 3 == max_len) { - printf("File name too long: \"%s\"\n", qualifiedName); - exit(-1); - } - strcpy(new_name, qualifiedName); - for (i = 0; i < len; i++) { - if (!is_valid_char_for_c_var(new_name[i])) { - new_name[i] = '_'; - } - } - do { - filename_ok = 1; - for (f = first_file; f != NULL; f = f->next) { - if (!strcmp(f->filename_c, new_name)) { - filename_ok = 0; - cnt++; - /* try next unique file name */ - sprintf(&new_name[len], "%d", cnt); - break; - } - } - } while (!filename_ok && (cnt < 999)); - if (!filename_ok) { - printf("Failed to get unique file name: \"%s\"\n", qualifiedName); - exit(-1); - } - strcpy(qualifiedName, new_name); - free(new_name); -} - -static void register_filename(const char *qualifiedName) -{ - struct file_entry *fe = (struct file_entry *)malloc(sizeof(struct file_entry)); - fe->filename_c = strdup(qualifiedName); - fe->next = NULL; - if (first_file == NULL) { - first_file = last_file = fe; - } else { - last_file->next = fe; - last_file = fe; - } -} - -static int checkSsiByFilelist(const char* filename_listfile) -{ - FILE *f = fopen(filename_listfile, "r"); - if (f != NULL) { - char *buf; - long rs; - size_t fsize, readcount; - size_t i, l, num_lines; - char **lines; - int state; - - fseek(f, 0, SEEK_END); - rs = ftell(f); - if (rs < 0) { - printf("ftell failed with %d\n", errno); - fclose(f); - return 0; - } - fsize = (size_t)rs; - fseek(f, 0, SEEK_SET); - buf = (char*)malloc(fsize); - if (!buf) { - printf("failed to allocate ssi file buffer\n"); - fclose(f); - return 0; - } - memset(buf, 0, fsize); - readcount = fread(buf, 1, fsize, f); - fclose(f); - if ((readcount > fsize) || !readcount) { - printf("failed to read data from ssi file\n"); - free(buf); - return 0; - } - - /* first pass: get the number of lines (and convert newlines to '0') */ - num_lines = 1; - for (i = 0; i < readcount; i++) { - if (buf[i] == '\n') { - num_lines++; - buf[i] = 0; - } else if (buf[i] == '\r') { - buf[i] = 0; - } - } - /* allocate the line pointer array */ - lines = (char**)malloc(sizeof(char*) * num_lines); - if (!lines) { - printf("failed to allocate ssi line buffer\n"); - free(buf); - return 0; - } - memset(lines, 0, sizeof(char*) * num_lines); - l = 0; - state = 0; - for (i = 0; i < readcount; i++) { - if (state) { - /* waiting for null */ - if (buf[i] == 0) { - state = 0; - } - } else { - /* waiting for beginning of new string */ - if (buf[i] != 0) { - LWIP_ASSERT("lines array overflow", l < num_lines); - lines[l] = &buf[i]; - state = 1; - l++; - } - } - } - LWIP_ASSERT("lines array overflow", l < num_lines); - - ssi_file_buffer = buf; - ssi_file_lines = lines; - ssi_file_num_lines = l; - } - return 0; -} - -static int is_ssi_file(const char *filename) -{ - if (supportSsi) { - if (ssi_file_buffer) { - /* compare by list */ - size_t i; - int ret = 0; - /* build up the relative path to this file */ - size_t sublen = strlen(curSubdir); - size_t freelen = sizeof(curSubdir) - sublen - 1; - strncat(curSubdir, "/", freelen); - strncat(curSubdir, filename, freelen - 1); - curSubdir[sizeof(curSubdir) - 1] = 0; - for (i = 0; i < ssi_file_num_lines; i++) { - const char *listed_file = ssi_file_lines[i]; - /* compare without the leading '/' */ - if (!strcmp(&curSubdir[1], listed_file)) { - ret = 1; - } - } - curSubdir[sublen] = 0; - return ret; - } else { - /* check file extension */ - size_t loop; - for (loop = 0; loop < NUM_SHTML_EXTENSIONS; loop++) { - if (strstr(filename, g_pcSSIExtensions[loop])) { - return 1; - } - } - } - } - return 0; -} - -static int ext_in_list(const char* filename, const char *ext_list) -{ - int found = 0; - const char *ext = ext_list; - if (ext_list == NULL) { - return 0; - } - while(*ext != '\0') { - const char *comma = strchr(ext, ','); - size_t ext_size; - size_t filename_size = strlen(filename); - if (comma == NULL) { - comma = strchr(ext, '\0'); - } - ext_size = comma - ext; - if ((filename[filename_size - ext_size - 1] == '.') && - !strncmp(&filename[filename_size - ext_size], ext, ext_size)) { - found = 1; - break; - } - ext = comma + 1; - } - - return found; -} - -static int file_to_exclude(const char *filename) -{ - return (exclude_list != NULL) && ext_in_list(filename, exclude_list); -} - -static int file_can_be_compressed(const char *filename) -{ - return (ncompress_list == NULL) || !ext_in_list(filename, ncompress_list); -} - -int process_file(FILE *data_file, FILE *struct_file, const char *filename) -{ - char varname[MAX_PATH_LEN]; - int i = 0; - char qualifiedName[MAX_PATH_LEN]; - int file_size; - u16_t http_hdr_chksum = 0; - u16_t http_hdr_len = 0; - int chksum_count = 0; - u8_t flags = 0; - u8_t has_content_len; - u8_t *file_data; - int is_ssi; - int can_be_compressed; - int is_compressed = 0; - int flags_printed; - - /* create qualified name (@todo: prepend slash or not?) */ - sprintf(qualifiedName, "%s/%s", curSubdir, filename); - /* create C variable name */ - strcpy(varname, qualifiedName); - /* convert slashes & dots to underscores */ - fix_filename_for_c(varname, MAX_PATH_LEN); - register_filename(varname); -#if ALIGN_PAYLOAD - /* to force even alignment of array, type 1 */ - fprintf(data_file, "#if FSDATA_FILE_ALIGNMENT==1" NEWLINE); - fprintf(data_file, "static const " PAYLOAD_ALIGN_TYPE " dummy_align_%s = %d;" NEWLINE, varname, payload_alingment_dummy_counter++); - fprintf(data_file, "#endif" NEWLINE); -#endif /* ALIGN_PAYLOAD */ - fprintf(data_file, "static const unsigned char FSDATA_ALIGN_PRE data_%s[] FSDATA_ALIGN_POST = {" NEWLINE, varname); - /* encode source file name (used by file system, not returned to browser) */ - fprintf(data_file, "/* %s (%"SZT_F" chars) */" NEWLINE, qualifiedName, strlen(qualifiedName) + 1); - file_put_ascii(data_file, qualifiedName, strlen(qualifiedName) + 1, &i); -#if ALIGN_PAYLOAD - /* pad to even number of bytes to assure payload is on aligned boundary */ - while (i % PAYLOAD_ALIGNMENT != 0) { - fprintf(data_file, "0x%02x,", 0); - i++; - } -#endif /* ALIGN_PAYLOAD */ - fprintf(data_file, NEWLINE); - - is_ssi = is_ssi_file(filename); - if (is_ssi) { - flags |= FS_FILE_FLAGS_SSI; - } - has_content_len = !is_ssi; - can_be_compressed = includeHttpHeader && !is_ssi && file_can_be_compressed(filename); - file_data = get_file_data(filename, &file_size, can_be_compressed, &is_compressed); - if (includeHttpHeader) { - file_write_http_header(data_file, filename, file_size, &http_hdr_len, &http_hdr_chksum, has_content_len, is_compressed); - flags |= FS_FILE_FLAGS_HEADER_INCLUDED; - if (has_content_len) { - flags |= FS_FILE_FLAGS_HEADER_PERSISTENT; - if (useHttp11) { - flags |= FS_FILE_FLAGS_HEADER_HTTPVER_1_1; - } - } - } - if (precalcChksum) { - chksum_count = write_checksums(struct_file, varname, http_hdr_len, http_hdr_chksum, file_data, file_size); - } - - /* build declaration of struct fsdata_file in temp file */ - fprintf(struct_file, "const struct fsdata_file file_%s[] = { {" NEWLINE, varname); - fprintf(struct_file, "file_%s," NEWLINE, lastFileVar); - fprintf(struct_file, "data_%s," NEWLINE, varname); - fprintf(struct_file, "data_%s + %d," NEWLINE, varname, i); - fprintf(struct_file, "sizeof(data_%s) - %d," NEWLINE, varname, i); - - flags_printed = 0; - if (flags & FS_FILE_FLAGS_HEADER_INCLUDED) { - fputs("FS_FILE_FLAGS_HEADER_INCLUDED", struct_file); - flags_printed = 1; - } - if (flags & FS_FILE_FLAGS_HEADER_PERSISTENT) { - if (flags_printed) { - fputs(" | ", struct_file); - } - fputs("FS_FILE_FLAGS_HEADER_PERSISTENT", struct_file); - flags_printed = 1; - } - if (flags & FS_FILE_FLAGS_HEADER_HTTPVER_1_1) { - if (flags_printed) { - fputs(" | ", struct_file); - } - fputs("FS_FILE_FLAGS_HEADER_HTTPVER_1_1", struct_file); - flags_printed = 1; - } - if (flags & FS_FILE_FLAGS_SSI) { - if (flags_printed) { - fputs(" | ", struct_file); - } - fputs("FS_FILE_FLAGS_SSI", struct_file); - flags_printed = 1; - } - if (!flags_printed) { - fputs("0", struct_file); - } - fputs("," NEWLINE, struct_file); - if (precalcChksum) { - fprintf(struct_file, "#if HTTPD_PRECALCULATED_CHECKSUM" NEWLINE); - fprintf(struct_file, "%d, chksums_%s," NEWLINE, chksum_count, varname); - fprintf(struct_file, "#endif /* HTTPD_PRECALCULATED_CHECKSUM */" NEWLINE); - } - fprintf(struct_file, "}};" NEWLINE NEWLINE); - strcpy(lastFileVar, varname); - - /* write actual file contents */ - i = 0; - fprintf(data_file, NEWLINE "/* raw file data (%d bytes) */" NEWLINE, file_size); - process_file_data(data_file, file_data, file_size); - fprintf(data_file, "};" NEWLINE NEWLINE); - free(file_data); - return 0; -} - -int file_write_http_header(FILE *data_file, const char *filename, int file_size, u16_t *http_hdr_len, - u16_t *http_hdr_chksum, u8_t provide_content_len, int is_compressed) -{ - int i = 0; - int response_type = HTTP_HDR_OK; - const char *file_type; - const char *cur_string; - size_t cur_len; - int written = 0; - size_t hdr_len = 0; - u16_t acc; - const char *file_ext; - size_t j; - u8_t provide_last_modified = includeLastModified; - - memset(hdr_buf, 0, sizeof(hdr_buf)); - - if (useHttp11) { - response_type = HTTP_HDR_OK_11; - } - - fprintf(data_file, NEWLINE "/* HTTP header */"); - if (strstr(filename, "404") == filename) { - response_type = HTTP_HDR_NOT_FOUND; - if (useHttp11) { - response_type = HTTP_HDR_NOT_FOUND_11; - } - } else if (strstr(filename, "400") == filename) { - response_type = HTTP_HDR_BAD_REQUEST; - if (useHttp11) { - response_type = HTTP_HDR_BAD_REQUEST_11; - } - } else if (strstr(filename, "501") == filename) { - response_type = HTTP_HDR_NOT_IMPL; - if (useHttp11) { - response_type = HTTP_HDR_NOT_IMPL_11; - } - } - cur_string = g_psHTTPHeaderStrings[response_type]; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%"SZT_F" bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - - cur_string = serverID; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%"SZT_F" bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - - file_ext = filename; - if (file_ext != NULL) { - while (strstr(file_ext, ".") != NULL) { - file_ext = strstr(file_ext, "."); - file_ext++; - } - } - if ((file_ext == NULL) || (*file_ext == 0)) { - printf("failed to get extension for file \"%s\", using default.\n", filename); - file_type = HTTP_HDR_DEFAULT_TYPE; - } else { - file_type = NULL; - for (j = 0; j < NUM_HTTP_HEADERS; j++) { - if (!strcmp(file_ext, g_psHTTPHeaders[j].extension)) { - file_type = g_psHTTPHeaders[j].content_type; - break; - } - } - if (file_type == NULL) { - printf("failed to get file type for extension \"%s\", using default.\n", file_ext); - file_type = HTTP_HDR_DEFAULT_TYPE; - } - } - - /* Content-Length is used for persistent connections in HTTP/1.1 but also for - download progress in older versions - @todo: just use a big-enough buffer and let the HTTPD send spaces? */ - if (provide_content_len) { - char intbuf[MAX_PATH_LEN]; - int content_len = file_size; - memset(intbuf, 0, sizeof(intbuf)); - cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONTENT_LENGTH]; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s%d\r\n\" (%"SZT_F"+ bytes) */" NEWLINE, cur_string, content_len, cur_len + 2); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - - lwip_itoa(intbuf, sizeof(intbuf), content_len); - strcat(intbuf, "\r\n"); - cur_len = strlen(intbuf); - written += file_put_ascii(data_file, intbuf, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], intbuf, cur_len); - hdr_len += cur_len; - } - } - if (provide_last_modified) { - char modbuf[256]; - struct stat stat_data; - struct tm *t; - memset(modbuf, 0, sizeof(modbuf)); - memset(&stat_data, 0, sizeof(stat_data)); - cur_string = modbuf; - strcpy(modbuf, "Last-Modified: "); - if (stat(filename, &stat_data) != 0) { - printf("stat(%s) failed with error %d\n", filename, errno); - exit(-1); - } - t = gmtime(&stat_data.st_mtime); - if (t == NULL) { - printf("gmtime() failed with error %d\n", errno); - exit(-1); - } - strftime(&modbuf[15], sizeof(modbuf) - 15, "%a, %d %b %Y %H:%M:%S GMT", t); - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\"\r\n\" (%"SZT_F"+ bytes) */" NEWLINE, cur_string, cur_len + 2); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - - modbuf[0] = 0; - strcat(modbuf, "\r\n"); - cur_len = strlen(modbuf); - written += file_put_ascii(data_file, modbuf, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], modbuf, cur_len); - hdr_len += cur_len; - } - } - - /* HTTP/1.1 implements persistent connections */ - if (useHttp11) { - if (provide_content_len) { - cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_KEEPALIVE]; - } else { - /* no Content-Length available, so a persistent connection is no possible - because the client does not know the data length */ - cur_string = g_psHTTPHeaderStrings[HTTP_HDR_CONN_CLOSE]; - } - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%"SZT_F" bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - if (precalcChksum) { - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - } - } - -#if MAKEFS_SUPPORT_DEFLATE - if (is_compressed) { - /* tell the client about the deflate encoding */ - LWIP_ASSERT("error", deflateNonSsiFiles); - cur_string = "Content-Encoding: deflate\r\n"; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%d bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - } -#else - LWIP_UNUSED_ARG(is_compressed); -#endif - - /* write content-type, ATTENTION: this includes the double-CRLF! */ - cur_string = file_type; - cur_len = strlen(cur_string); - fprintf(data_file, NEWLINE "/* \"%s\" (%"SZT_F" bytes) */" NEWLINE, cur_string, cur_len); - written += file_put_ascii(data_file, cur_string, cur_len, &i); - i = 0; - - /* ATTENTION: headers are done now (double-CRLF has been written!) */ - - if (precalcChksum) { - LWIP_ASSERT("hdr_len + cur_len <= sizeof(hdr_buf)", hdr_len + cur_len <= sizeof(hdr_buf)); - memcpy(&hdr_buf[hdr_len], cur_string, cur_len); - hdr_len += cur_len; - - LWIP_ASSERT("strlen(hdr_buf) == hdr_len", strlen(hdr_buf) == hdr_len); - acc = ~inet_chksum(hdr_buf, (u16_t)hdr_len); - *http_hdr_len = (u16_t)hdr_len; - *http_hdr_chksum = acc; - } - - return written; -} - -int file_put_ascii(FILE *file, const char *ascii_string, int len, int *i) -{ - int x; - for (x = 0; x < len; x++) { - unsigned char cur = ascii_string[x]; - fprintf(file, "0x%02x,", cur); - if ((++(*i) % HEX_BYTES_PER_LINE) == 0) { - fprintf(file, NEWLINE); - } - } - return len; -} - -int s_put_ascii(char *buf, const char *ascii_string, int len, int *i) -{ - int x; - int idx = 0; - for (x = 0; x < len; x++) { - unsigned char cur = ascii_string[x]; - sprintf(&buf[idx], "0x%02x,", cur); - idx += 5; - if ((++(*i) % HEX_BYTES_PER_LINE) == 0) { - sprintf(&buf[idx], NEWLINE); - idx += NEWLINE_LEN; - } - } - return len; -} diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/makefsdata/readme.txt b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/makefsdata/readme.txt deleted file mode 100644 index 3768585ef..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/makefsdata/readme.txt +++ /dev/null @@ -1,13 +0,0 @@ -This directory contains a script ('makefsdata') to create C code suitable for -httpd for given html pages (or other files) in a directory. - -There is also a plain C console application doing the same and extended a bit. - -Usage: htmlgen [targetdir] [-s] [-i]s - targetdir: relative or absolute path to files to convert - switch -s: toggle processing of subdirectories (default is on) - switch -e: exclude HTTP header from file (header is created at runtime, default is on) - switch -11: include HTTP 1.1 header (1.0 is default) - - if targetdir not specified, makefsdata will attempt to - process files in subdirectory 'fs'. diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/makefsdata/tinydir.h b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/makefsdata/tinydir.h deleted file mode 100644 index 32ae5e84a..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/http/makefsdata/tinydir.h +++ /dev/null @@ -1,808 +0,0 @@ -/* -Copyright (c) 2013-2017, tinydir authors: -- Cong Xu -- Lautis Sun -- Baudouin Feildel -- Andargor -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef TINYDIR_H -#define TINYDIR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if ((defined _UNICODE) && !(defined UNICODE)) -#define UNICODE -#endif - -#if ((defined UNICODE) && !(defined _UNICODE)) -#define _UNICODE -#endif - -#include -#include -#include -#ifdef _MSC_VER -# define WIN32_LEAN_AND_MEAN -# include -# include -# pragma warning(push) -# pragma warning (disable : 4996) -#else -# include -# include -# include -# include -#endif -#ifdef __MINGW32__ -# include -#endif - - -/* types */ - -/* Windows UNICODE wide character support */ -#if defined _MSC_VER || defined __MINGW32__ -#define _tinydir_char_t TCHAR -#define TINYDIR_STRING(s) _TEXT(s) -#define _tinydir_strlen _tcslen -#define _tinydir_strcpy _tcscpy -#define _tinydir_strcat _tcscat -#define _tinydir_strcmp _tcscmp -#define _tinydir_strrchr _tcsrchr -#define _tinydir_strncmp _tcsncmp -#else -#define _tinydir_char_t char -#define TINYDIR_STRING(s) s -#define _tinydir_strlen strlen -#define _tinydir_strcpy strcpy -#define _tinydir_strcat strcat -#define _tinydir_strcmp strcmp -#define _tinydir_strrchr strrchr -#define _tinydir_strncmp strncmp -#endif - -#if (defined _MSC_VER || defined __MINGW32__) -#include -#define _TINYDIR_PATH_MAX MAX_PATH -#elif defined __linux__ -#include -#define _TINYDIR_PATH_MAX PATH_MAX -#else -#define _TINYDIR_PATH_MAX 4096 -#endif - -#ifdef _MSC_VER -/* extra chars for the "\\*" mask */ -# define _TINYDIR_PATH_EXTRA 2 -#else -# define _TINYDIR_PATH_EXTRA 0 -#endif - -#define _TINYDIR_FILENAME_MAX 256 - -#if (defined _MSC_VER || defined __MINGW32__) -#define _TINYDIR_DRIVE_MAX 3 -#endif - -#ifdef _MSC_VER -# define _TINYDIR_FUNC static __inline -#elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L -# define _TINYDIR_FUNC static __inline__ -#else -# define _TINYDIR_FUNC static inline -#endif - -/* readdir_r usage; define TINYDIR_USE_READDIR_R to use it (if supported) */ -#ifdef TINYDIR_USE_READDIR_R - -/* readdir_r is a POSIX-only function, and may not be available under various - * environments/settings, e.g. MinGW. Use readdir fallback */ -#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE ||\ - _POSIX_SOURCE -# define _TINYDIR_HAS_READDIR_R -#endif -#if _POSIX_C_SOURCE >= 200112L -# define _TINYDIR_HAS_FPATHCONF -# include -#endif -#if _BSD_SOURCE || _SVID_SOURCE || \ - (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) -# define _TINYDIR_HAS_DIRFD -# include -#endif -#if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD &&\ - defined _PC_NAME_MAX -# define _TINYDIR_USE_FPATHCONF -#endif -#if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R ||\ - !(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX) -# define _TINYDIR_USE_READDIR -#endif - -/* Use readdir by default */ -#else -# define _TINYDIR_USE_READDIR -#endif - -/* MINGW32 has two versions of dirent, ASCII and UNICODE*/ -#ifndef _MSC_VER -#if (defined __MINGW32__) && (defined _UNICODE) -#define _TINYDIR_DIR _WDIR -#define _tinydir_dirent _wdirent -#define _tinydir_opendir _wopendir -#define _tinydir_readdir _wreaddir -#define _tinydir_closedir _wclosedir -#else -#define _TINYDIR_DIR DIR -#define _tinydir_dirent dirent -#define _tinydir_opendir opendir -#define _tinydir_readdir readdir -#define _tinydir_closedir closedir -#endif -#endif - -/* Allow user to use a custom allocator by defining _TINYDIR_MALLOC and _TINYDIR_FREE. */ -#if defined(_TINYDIR_MALLOC) && defined(_TINYDIR_FREE) -#elif !defined(_TINYDIR_MALLOC) && !defined(_TINYDIR_FREE) -#else -#error "Either define both alloc and free or none of them!" -#endif - -#if !defined(_TINYDIR_MALLOC) - #define _TINYDIR_MALLOC(_size) malloc(_size) - #define _TINYDIR_FREE(_ptr) free(_ptr) -#endif /* !defined(_TINYDIR_MALLOC) */ - -typedef struct tinydir_file -{ - _tinydir_char_t path[_TINYDIR_PATH_MAX]; - _tinydir_char_t name[_TINYDIR_FILENAME_MAX]; - _tinydir_char_t *extension; - int is_dir; - int is_reg; - -#ifndef _MSC_VER -#ifdef __MINGW32__ - struct _stat _s; -#else - struct stat _s; -#endif -#endif -} tinydir_file; - -typedef struct tinydir_dir -{ - _tinydir_char_t path[_TINYDIR_PATH_MAX]; - int has_next; - size_t n_files; - - tinydir_file *_files; -#ifdef _MSC_VER - HANDLE _h; - WIN32_FIND_DATA _f; -#else - _TINYDIR_DIR *_d; - struct _tinydir_dirent *_e; -#ifndef _TINYDIR_USE_READDIR - struct _tinydir_dirent *_ep; -#endif -#endif -} tinydir_dir; - - -/* declarations */ - -_TINYDIR_FUNC -int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path); -_TINYDIR_FUNC -int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path); -_TINYDIR_FUNC -void tinydir_close(tinydir_dir *dir); - -_TINYDIR_FUNC -int tinydir_next(tinydir_dir *dir); -_TINYDIR_FUNC -int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file); -_TINYDIR_FUNC -int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i); -_TINYDIR_FUNC -int tinydir_open_subdir_n(tinydir_dir *dir, size_t i); - -_TINYDIR_FUNC -int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path); -_TINYDIR_FUNC -void _tinydir_get_ext(tinydir_file *file); -_TINYDIR_FUNC -int _tinydir_file_cmp(const void *a, const void *b); -#ifndef _MSC_VER -#ifndef _TINYDIR_USE_READDIR -_TINYDIR_FUNC -size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp); -#endif -#endif - - -/* definitions*/ - -_TINYDIR_FUNC -int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path) -{ -#ifndef _MSC_VER -#ifndef _TINYDIR_USE_READDIR - int error; - int size; /* using int size */ -#endif -#else - _tinydir_char_t path_buf[_TINYDIR_PATH_MAX]; -#endif - _tinydir_char_t *pathp; - - if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0) - { - errno = EINVAL; - return -1; - } - if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) - { - errno = ENAMETOOLONG; - return -1; - } - - /* initialise dir */ - dir->_files = NULL; -#ifdef _MSC_VER - dir->_h = INVALID_HANDLE_VALUE; -#else - dir->_d = NULL; -#ifndef _TINYDIR_USE_READDIR - dir->_ep = NULL; -#endif -#endif - tinydir_close(dir); - - _tinydir_strcpy(dir->path, path); - /* Remove trailing slashes */ - pathp = &dir->path[_tinydir_strlen(dir->path) - 1]; - while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/'))) - { - *pathp = TINYDIR_STRING('\0'); - pathp++; - } -#ifdef _MSC_VER - _tinydir_strcpy(path_buf, dir->path); - _tinydir_strcat(path_buf, TINYDIR_STRING("\\*")); -#if (defined WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP) - dir->_h = FindFirstFileEx(path_buf, FindExInfoStandard, &dir->_f, FindExSearchNameMatch, NULL, 0); -#else - dir->_h = FindFirstFile(path_buf, &dir->_f); -#endif - if (dir->_h == INVALID_HANDLE_VALUE) - { - errno = ENOENT; -#else - dir->_d = _tinydir_opendir(path); - if (dir->_d == NULL) - { -#endif - goto bail; - } - - /* read first file */ - dir->has_next = 1; -#ifndef _MSC_VER -#ifdef _TINYDIR_USE_READDIR - dir->_e = _tinydir_readdir(dir->_d); -#else - /* allocate dirent buffer for readdir_r */ - size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */ - if (size == -1) return -1; - dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size); - if (dir->_ep == NULL) return -1; - - error = readdir_r(dir->_d, dir->_ep, &dir->_e); - if (error != 0) return -1; -#endif - if (dir->_e == NULL) - { - dir->has_next = 0; - } -#endif - - return 0; - -bail: - tinydir_close(dir); - return -1; -} - -_TINYDIR_FUNC -int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path) -{ - /* Count the number of files first, to pre-allocate the files array */ - size_t n_files = 0; - if (tinydir_open(dir, path) == -1) - { - return -1; - } - while (dir->has_next) - { - n_files++; - if (tinydir_next(dir) == -1) - { - goto bail; - } - } - tinydir_close(dir); - - if (tinydir_open(dir, path) == -1) - { - return -1; - } - - dir->n_files = 0; - dir->_files = (tinydir_file *)_TINYDIR_MALLOC(sizeof *dir->_files * n_files); - if (dir->_files == NULL) - { - goto bail; - } - while (dir->has_next) - { - tinydir_file *p_file; - dir->n_files++; - - p_file = &dir->_files[dir->n_files - 1]; - if (tinydir_readfile(dir, p_file) == -1) - { - goto bail; - } - - if (tinydir_next(dir) == -1) - { - goto bail; - } - - /* Just in case the number of files has changed between the first and - second reads, terminate without writing into unallocated memory */ - if (dir->n_files == n_files) - { - break; - } - } - - qsort(dir->_files, dir->n_files, sizeof(tinydir_file), _tinydir_file_cmp); - - return 0; - -bail: - tinydir_close(dir); - return -1; -} - -_TINYDIR_FUNC -void tinydir_close(tinydir_dir *dir) -{ - if (dir == NULL) - { - return; - } - - memset(dir->path, 0, sizeof(dir->path)); - dir->has_next = 0; - dir->n_files = 0; - _TINYDIR_FREE(dir->_files); - dir->_files = NULL; -#ifdef _MSC_VER - if (dir->_h != INVALID_HANDLE_VALUE) - { - FindClose(dir->_h); - } - dir->_h = INVALID_HANDLE_VALUE; -#else - if (dir->_d) - { - _tinydir_closedir(dir->_d); - } - dir->_d = NULL; - dir->_e = NULL; -#ifndef _TINYDIR_USE_READDIR - _TINYDIR_FREE(dir->_ep); - dir->_ep = NULL; -#endif -#endif -} - -_TINYDIR_FUNC -int tinydir_next(tinydir_dir *dir) -{ - if (dir == NULL) - { - errno = EINVAL; - return -1; - } - if (!dir->has_next) - { - errno = ENOENT; - return -1; - } - -#ifdef _MSC_VER - if (FindNextFile(dir->_h, &dir->_f) == 0) -#else -#ifdef _TINYDIR_USE_READDIR - dir->_e = _tinydir_readdir(dir->_d); -#else - if (dir->_ep == NULL) - { - return -1; - } - if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0) - { - return -1; - } -#endif - if (dir->_e == NULL) -#endif - { - dir->has_next = 0; -#ifdef _MSC_VER - if (GetLastError() != ERROR_SUCCESS && - GetLastError() != ERROR_NO_MORE_FILES) - { - tinydir_close(dir); - errno = EIO; - return -1; - } -#endif - } - - return 0; -} - -_TINYDIR_FUNC -int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file) -{ - if (dir == NULL || file == NULL) - { - errno = EINVAL; - return -1; - } -#ifdef _MSC_VER - if (dir->_h == INVALID_HANDLE_VALUE) -#else - if (dir->_e == NULL) -#endif - { - errno = ENOENT; - return -1; - } - if (_tinydir_strlen(dir->path) + - _tinydir_strlen( -#ifdef _MSC_VER - dir->_f.cFileName -#else - dir->_e->d_name -#endif - ) + 1 + _TINYDIR_PATH_EXTRA >= - _TINYDIR_PATH_MAX) - { - /* the path for the file will be too long */ - errno = ENAMETOOLONG; - return -1; - } - if (_tinydir_strlen( -#ifdef _MSC_VER - dir->_f.cFileName -#else - dir->_e->d_name -#endif - ) >= _TINYDIR_FILENAME_MAX) - { - errno = ENAMETOOLONG; - return -1; - } - - _tinydir_strcpy(file->path, dir->path); - _tinydir_strcat(file->path, TINYDIR_STRING("/")); - _tinydir_strcpy(file->name, -#ifdef _MSC_VER - dir->_f.cFileName -#else - dir->_e->d_name -#endif - ); - _tinydir_strcat(file->path, file->name); -#ifndef _MSC_VER -#ifdef __MINGW32__ - if (_tstat( -#else - if (stat( -#endif - file->path, &file->_s) == -1) - { - return -1; - } -#endif - _tinydir_get_ext(file); - - file->is_dir = -#ifdef _MSC_VER - !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); -#else - S_ISDIR(file->_s.st_mode); -#endif - file->is_reg = -#ifdef _MSC_VER - !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || - ( - !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) && - !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && - !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) && -#ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM - !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) && -#endif -#ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA - !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) && -#endif - !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) && - !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY)); -#else - S_ISREG(file->_s.st_mode); -#endif - - return 0; -} - -_TINYDIR_FUNC -int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i) -{ - if (dir == NULL || file == NULL) - { - errno = EINVAL; - return -1; - } - if (i >= dir->n_files) - { - errno = ENOENT; - return -1; - } - - memcpy(file, &dir->_files[i], sizeof(tinydir_file)); - _tinydir_get_ext(file); - - return 0; -} - -_TINYDIR_FUNC -int tinydir_open_subdir_n(tinydir_dir *dir, size_t i) -{ - _tinydir_char_t path[_TINYDIR_PATH_MAX]; - if (dir == NULL) - { - errno = EINVAL; - return -1; - } - if (i >= dir->n_files || !dir->_files[i].is_dir) - { - errno = ENOENT; - return -1; - } - - _tinydir_strcpy(path, dir->_files[i].path); - tinydir_close(dir); - if (tinydir_open_sorted(dir, path) == -1) - { - return -1; - } - - return 0; -} - -/* Open a single file given its path */ -_TINYDIR_FUNC -int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path) -{ - tinydir_dir dir; - int result = 0; - int found = 0; - _tinydir_char_t dir_name_buf[_TINYDIR_PATH_MAX]; - _tinydir_char_t file_name_buf[_TINYDIR_FILENAME_MAX]; - _tinydir_char_t *dir_name; - _tinydir_char_t *base_name; -#if (defined _MSC_VER || defined __MINGW32__) - _tinydir_char_t drive_buf[_TINYDIR_PATH_MAX]; - _tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX]; -#endif - - if (file == NULL || path == NULL || _tinydir_strlen(path) == 0) - { - errno = EINVAL; - return -1; - } - if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) - { - errno = ENAMETOOLONG; - return -1; - } - - /* Get the parent path */ -#if (defined _MSC_VER || defined __MINGW32__) -#if ((defined _MSC_VER) && (_MSC_VER >= 1400)) - _tsplitpath_s( - path, - drive_buf, _TINYDIR_DRIVE_MAX, - dir_name_buf, _TINYDIR_FILENAME_MAX, - file_name_buf, _TINYDIR_FILENAME_MAX, - ext_buf, _TINYDIR_FILENAME_MAX); -#else - _tsplitpath( - path, - drive_buf, - dir_name_buf, - file_name_buf, - ext_buf); -#endif - -/* _splitpath_s not work fine with only filename and widechar support */ -#ifdef _UNICODE - if (drive_buf[0] == L'\xFEFE') - drive_buf[0] = '\0'; - if (dir_name_buf[0] == L'\xFEFE') - dir_name_buf[0] = '\0'; -#endif - - if (errno) - { - errno = EINVAL; - return -1; - } - /* Emulate the behavior of dirname by returning "." for dir name if it's - empty */ - if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0') - { - _tinydir_strcpy(dir_name_buf, TINYDIR_STRING(".")); - } - /* Concatenate the drive letter and dir name to form full dir name */ - _tinydir_strcat(drive_buf, dir_name_buf); - dir_name = drive_buf; - /* Concatenate the file name and extension to form base name */ - _tinydir_strcat(file_name_buf, ext_buf); - base_name = file_name_buf; -#else - _tinydir_strcpy(dir_name_buf, path); - dir_name = dirname(dir_name_buf); - _tinydir_strcpy(file_name_buf, path); - base_name =basename(file_name_buf); -#endif - - /* Open the parent directory */ - if (tinydir_open(&dir, dir_name) == -1) - { - return -1; - } - - /* Read through the parent directory and look for the file */ - while (dir.has_next) - { - if (tinydir_readfile(&dir, file) == -1) - { - result = -1; - goto bail; - } - if (_tinydir_strcmp(file->name, base_name) == 0) - { - /* File found */ - found = 1; - break; - } - tinydir_next(&dir); - } - if (!found) - { - result = -1; - errno = ENOENT; - } - -bail: - tinydir_close(&dir); - return result; -} - -_TINYDIR_FUNC -void _tinydir_get_ext(tinydir_file *file) -{ - _tinydir_char_t *period = _tinydir_strrchr(file->name, TINYDIR_STRING('.')); - if (period == NULL) - { - file->extension = &(file->name[_tinydir_strlen(file->name)]); - } - else - { - file->extension = period + 1; - } -} - -_TINYDIR_FUNC -int _tinydir_file_cmp(const void *a, const void *b) -{ - const tinydir_file *fa = (const tinydir_file *)a; - const tinydir_file *fb = (const tinydir_file *)b; - if (fa->is_dir != fb->is_dir) - { - return -(fa->is_dir - fb->is_dir); - } - return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX); -} - -#ifndef _MSC_VER -#ifndef _TINYDIR_USE_READDIR -/* -The following authored by Ben Hutchings -from https://womble.decadent.org.uk/readdir_r-advisory.html -*/ -/* Calculate the required buffer size (in bytes) for directory * -* entries read from the given directory handle. Return -1 if this * -* this cannot be done. * -* * -* This code does not trust values of NAME_MAX that are less than * -* 255, since some systems (including at least HP-UX) incorrectly * -* define it to be a smaller value. */ -_TINYDIR_FUNC -size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp) -{ - long name_max; - size_t name_end; - /* parameter may be unused */ - (void)dirp; - -#if defined _TINYDIR_USE_FPATHCONF - name_max = fpathconf(dirfd(dirp), _PC_NAME_MAX); - if (name_max == -1) -#if defined(NAME_MAX) - name_max = (NAME_MAX > 255) ? NAME_MAX : 255; -#else - return (size_t)(-1); -#endif -#elif defined(NAME_MAX) - name_max = (NAME_MAX > 255) ? NAME_MAX : 255; -#else -#error "buffer size for readdir_r cannot be determined" -#endif - name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1; - return (name_end > sizeof(struct _tinydir_dirent) ? - name_end : sizeof(struct _tinydir_dirent)); -} -#endif -#endif - -#ifdef __cplusplus -} -#endif - -# if defined (_MSC_VER) -# pragma warning(pop) -# endif - -#endif diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/lwiperf/lwiperf.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/lwiperf/lwiperf.c deleted file mode 100644 index dbec4dae9..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/lwiperf/lwiperf.c +++ /dev/null @@ -1,841 +0,0 @@ -/** - * @file - * lwIP iPerf server implementation - */ - -/** - * @defgroup iperf Iperf server - * @ingroup apps - * - * This is a simple performance measuring client/server to check your bandwith using - * iPerf2 on a PC as server/client. - * It is currently a minimal implementation providing a TCP client/server only. - * - * @todo: - * - implement UDP mode - * - protect combined sessions handling (via 'related_master_state') against reallocation - * (this is a pointer address, currently, so if the same memory is allocated again, - * session pairs (tx/rx) can be confused on reallocation) - */ - -/* - * Copyright (c) 2014 Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Simon Goldschmidt - */ - -#include "lwip/apps/lwiperf.h" - -#include "lwip/tcp.h" -#include "lwip/sys.h" - -#include - -/* Currently, only TCP is implemented */ -#if LWIP_TCP && LWIP_CALLBACK_API - -/** Specify the idle timeout (in seconds) after that the test fails */ -#ifndef LWIPERF_TCP_MAX_IDLE_SEC -#define LWIPERF_TCP_MAX_IDLE_SEC 10U -#endif -#if LWIPERF_TCP_MAX_IDLE_SEC > 255 -#error LWIPERF_TCP_MAX_IDLE_SEC must fit into an u8_t -#endif - -/** Change this if you don't want to lwiperf to listen to any IP version */ -#ifndef LWIPERF_SERVER_IP_TYPE -#define LWIPERF_SERVER_IP_TYPE IPADDR_TYPE_ANY -#endif - -/* File internal memory allocation (struct lwiperf_*): this defaults to - the heap */ -#ifndef LWIPERF_ALLOC -#define LWIPERF_ALLOC(type) mem_malloc(sizeof(type)) -#define LWIPERF_FREE(type, item) mem_free(item) -#endif - -/** If this is 1, check that received data has the correct format */ -#ifndef LWIPERF_CHECK_RX_DATA -#define LWIPERF_CHECK_RX_DATA 0 -#endif - -/** This is the Iperf settings struct sent from the client */ -typedef struct _lwiperf_settings { -#define LWIPERF_FLAGS_ANSWER_TEST 0x80000000 -#define LWIPERF_FLAGS_ANSWER_NOW 0x00000001 - u32_t flags; - u32_t num_threads; /* unused for now */ - u32_t remote_port; - u32_t buffer_len; /* unused for now */ - u32_t win_band; /* TCP window / UDP rate: unused for now */ - u32_t amount; /* pos. value: bytes?; neg. values: time (unit is 10ms: 1/100 second) */ -} lwiperf_settings_t; - -/** Basic connection handle */ -struct _lwiperf_state_base; -typedef struct _lwiperf_state_base lwiperf_state_base_t; -struct _lwiperf_state_base { - /* linked list */ - lwiperf_state_base_t *next; - /* 1=tcp, 0=udp */ - u8_t tcp; - /* 1=server, 0=client */ - u8_t server; - /* master state used to abort sessions (e.g. listener, main client) */ - lwiperf_state_base_t *related_master_state; -}; - -/** Connection handle for a TCP iperf session */ -typedef struct _lwiperf_state_tcp { - lwiperf_state_base_t base; - struct tcp_pcb *server_pcb; - struct tcp_pcb *conn_pcb; - u32_t time_started; - lwiperf_report_fn report_fn; - void *report_arg; - u8_t poll_count; - u8_t next_num; - /* 1=start server when client is closed */ - u8_t client_tradeoff_mode; - u32_t bytes_transferred; - lwiperf_settings_t settings; - u8_t have_settings_buf; - u8_t specific_remote; - ip_addr_t remote_addr; -} lwiperf_state_tcp_t; - -/** List of active iperf sessions */ -static lwiperf_state_base_t *lwiperf_all_connections; -/** A const buffer to send from: we want to measure sending, not copying! */ -static const u8_t lwiperf_txbuf_const[1600] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', -}; - -static err_t lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb); -static void lwiperf_tcp_err(void *arg, err_t err); -static err_t lwiperf_start_tcp_server_impl(const ip_addr_t *local_addr, u16_t local_port, - lwiperf_report_fn report_fn, void *report_arg, - lwiperf_state_base_t *related_master_state, lwiperf_state_tcp_t **state); - - -/** Add an iperf session to the 'active' list */ -static void -lwiperf_list_add(lwiperf_state_base_t *item) -{ - item->next = lwiperf_all_connections; - lwiperf_all_connections = item; -} - -/** Remove an iperf session from the 'active' list */ -static void -lwiperf_list_remove(lwiperf_state_base_t *item) -{ - lwiperf_state_base_t *prev = NULL; - lwiperf_state_base_t *iter; - for (iter = lwiperf_all_connections; iter != NULL; prev = iter, iter = iter->next) { - if (iter == item) { - if (prev == NULL) { - lwiperf_all_connections = iter->next; - } else { - prev->next = iter->next; - } - /* @debug: ensure this item is listed only once */ - for (iter = iter->next; iter != NULL; iter = iter->next) { - LWIP_ASSERT("duplicate entry", iter != item); - } - break; - } - } -} - -static lwiperf_state_base_t * -lwiperf_list_find(lwiperf_state_base_t *item) -{ - lwiperf_state_base_t *iter; - for (iter = lwiperf_all_connections; iter != NULL; iter = iter->next) { - if (iter == item) { - return item; - } - } - return NULL; -} - -/** Call the report function of an iperf tcp session */ -static void -lwip_tcp_conn_report(lwiperf_state_tcp_t *conn, enum lwiperf_report_type report_type) -{ - if ((conn != NULL) && (conn->report_fn != NULL)) { - u32_t now, duration_ms, bandwidth_kbitpsec; - now = sys_now(); - duration_ms = now - conn->time_started; - if (duration_ms == 0) { - bandwidth_kbitpsec = 0; - } else { - bandwidth_kbitpsec = (conn->bytes_transferred / duration_ms) * 8U; - } - conn->report_fn(conn->report_arg, report_type, - &conn->conn_pcb->local_ip, conn->conn_pcb->local_port, - &conn->conn_pcb->remote_ip, conn->conn_pcb->remote_port, - conn->bytes_transferred, duration_ms, bandwidth_kbitpsec); - } -} - -/** Close an iperf tcp session */ -static void -lwiperf_tcp_close(lwiperf_state_tcp_t *conn, enum lwiperf_report_type report_type) -{ - err_t err; - - lwiperf_list_remove(&conn->base); - lwip_tcp_conn_report(conn, report_type); - if (conn->conn_pcb != NULL) { - tcp_arg(conn->conn_pcb, NULL); - tcp_poll(conn->conn_pcb, NULL, 0); - tcp_sent(conn->conn_pcb, NULL); - tcp_recv(conn->conn_pcb, NULL); - tcp_err(conn->conn_pcb, NULL); - err = tcp_close(conn->conn_pcb); - if (err != ERR_OK) { - /* don't want to wait for free memory here... */ - tcp_abort(conn->conn_pcb); - } - } else { - /* no conn pcb, this is the listener pcb */ - err = tcp_close(conn->server_pcb); - LWIP_ASSERT("error", err == ERR_OK); - } - LWIPERF_FREE(lwiperf_state_tcp_t, conn); -} - -/** Try to send more data on an iperf tcp session */ -static err_t -lwiperf_tcp_client_send_more(lwiperf_state_tcp_t *conn) -{ - int send_more; - err_t err; - u16_t txlen; - u16_t txlen_max; - void *txptr; - u8_t apiflags; - - LWIP_ASSERT("conn invalid", (conn != NULL) && conn->base.tcp && (conn->base.server == 0)); - - do { - send_more = 0; - if (conn->settings.amount & PP_HTONL(0x80000000)) { - /* this session is time-limited */ - u32_t now = sys_now(); - u32_t diff_ms = now - conn->time_started; - u32_t time = (u32_t) - (s32_t)lwip_htonl(conn->settings.amount); - u32_t time_ms = time * 10; - if (diff_ms >= time_ms) { - /* time specified by the client is over -> close the connection */ - lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); - return ERR_OK; - } - } else { - /* this session is byte-limited */ - u32_t amount_bytes = lwip_htonl(conn->settings.amount); - /* @todo: this can send up to 1*MSS more than requested... */ - if (amount_bytes >= conn->bytes_transferred) { - /* all requested bytes transferred -> close the connection */ - lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_CLIENT); - return ERR_OK; - } - } - - if (conn->bytes_transferred < 24) { - /* transmit the settings a first time */ - txptr = &((u8_t *)&conn->settings)[conn->bytes_transferred]; - txlen_max = (u16_t)(24 - conn->bytes_transferred); - apiflags = TCP_WRITE_FLAG_COPY; - } else if (conn->bytes_transferred < 48) { - /* transmit the settings a second time */ - txptr = &((u8_t *)&conn->settings)[conn->bytes_transferred - 24]; - txlen_max = (u16_t)(48 - conn->bytes_transferred); - apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE; - send_more = 1; - } else { - /* transmit data */ - /* @todo: every x bytes, transmit the settings again */ - txptr = LWIP_CONST_CAST(void *, &lwiperf_txbuf_const[conn->bytes_transferred % 10]); - txlen_max = TCP_MSS; - if (conn->bytes_transferred == 48) { /* @todo: fix this for intermediate settings, too */ - txlen_max = TCP_MSS - 24; - } - apiflags = 0; /* no copying needed */ - send_more = 1; - } - txlen = txlen_max; - do { - err = tcp_write(conn->conn_pcb, txptr, txlen, apiflags); - if (err == ERR_MEM) { - txlen /= 2; - } - } while ((err == ERR_MEM) && (txlen >= (TCP_MSS / 2))); - - if (err == ERR_OK) { - conn->bytes_transferred += txlen; - } else { - send_more = 0; - } - } while (send_more); - - tcp_output(conn->conn_pcb); - return ERR_OK; -} - -/** TCP sent callback, try to send more data */ -static err_t -lwiperf_tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len) -{ - lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg; - /* @todo: check 'len' (e.g. to time ACK of all data)? for now, we just send more... */ - LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb); - LWIP_UNUSED_ARG(tpcb); - LWIP_UNUSED_ARG(len); - - conn->poll_count = 0; - - return lwiperf_tcp_client_send_more(conn); -} - -/** TCP connected callback (active connection), send data now */ -static err_t -lwiperf_tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err) -{ - lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg; - LWIP_ASSERT("invalid conn", conn->conn_pcb == tpcb); - LWIP_UNUSED_ARG(tpcb); - if (err != ERR_OK) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); - return ERR_OK; - } - conn->poll_count = 0; - conn->time_started = sys_now(); - return lwiperf_tcp_client_send_more(conn); -} - -/** Start TCP connection back to the client (either parallel or after the - * receive test has finished. - */ -static err_t -lwiperf_tx_start_impl(const ip_addr_t *remote_ip, u16_t remote_port, lwiperf_settings_t *settings, lwiperf_report_fn report_fn, - void *report_arg, lwiperf_state_base_t *related_master_state, lwiperf_state_tcp_t **new_conn) -{ - err_t err; - lwiperf_state_tcp_t *client_conn; - struct tcp_pcb *newpcb; - ip_addr_t remote_addr; - - LWIP_ASSERT("remote_ip != NULL", remote_ip != NULL); - LWIP_ASSERT("remote_ip != NULL", settings != NULL); - LWIP_ASSERT("new_conn != NULL", new_conn != NULL); - *new_conn = NULL; - - client_conn = (lwiperf_state_tcp_t *)LWIPERF_ALLOC(lwiperf_state_tcp_t); - if (client_conn == NULL) { - return ERR_MEM; - } - newpcb = tcp_new_ip_type(IP_GET_TYPE(remote_ip)); - if (newpcb == NULL) { - LWIPERF_FREE(lwiperf_state_tcp_t, client_conn); - return ERR_MEM; - } - memset(client_conn, 0, sizeof(lwiperf_state_tcp_t)); - client_conn->base.tcp = 1; - client_conn->base.related_master_state = related_master_state; - client_conn->conn_pcb = newpcb; - client_conn->time_started = sys_now(); /* @todo: set this again on 'connected' */ - client_conn->report_fn = report_fn; - client_conn->report_arg = report_arg; - client_conn->next_num = 4; /* initial nr is '4' since the header has 24 byte */ - client_conn->bytes_transferred = 0; - memcpy(&client_conn->settings, settings, sizeof(*settings)); - client_conn->have_settings_buf = 1; - - tcp_arg(newpcb, client_conn); - tcp_sent(newpcb, lwiperf_tcp_client_sent); - tcp_poll(newpcb, lwiperf_tcp_poll, 2U); - tcp_err(newpcb, lwiperf_tcp_err); - - ip_addr_copy(remote_addr, *remote_ip); - - err = tcp_connect(newpcb, &remote_addr, remote_port, lwiperf_tcp_client_connected); - if (err != ERR_OK) { - lwiperf_tcp_close(client_conn, LWIPERF_TCP_ABORTED_LOCAL); - return err; - } - lwiperf_list_add(&client_conn->base); - *new_conn = client_conn; - return ERR_OK; -} - -static err_t -lwiperf_tx_start_passive(lwiperf_state_tcp_t *conn) -{ - err_t ret; - lwiperf_state_tcp_t *new_conn = NULL; - u16_t remote_port = (u16_t)lwip_htonl(conn->settings.remote_port); - - ret = lwiperf_tx_start_impl(&conn->conn_pcb->remote_ip, remote_port, &conn->settings, conn->report_fn, conn->report_arg, - conn->base.related_master_state, &new_conn); - if (ret == ERR_OK) { - LWIP_ASSERT("new_conn != NULL", new_conn != NULL); - new_conn->settings.flags = 0; /* prevent the remote side starting back as client again */ - } - return ret; -} - -/** Receive data on an iperf tcp session */ -static err_t -lwiperf_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) -{ - u8_t tmp; - u16_t tot_len; - u32_t packet_idx; - struct pbuf *q; - lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg; - - LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); - LWIP_UNUSED_ARG(tpcb); - - if (err != ERR_OK) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); - return ERR_OK; - } - if (p == NULL) { - /* connection closed -> test done */ - if (conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) { - if ((conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_NOW)) == 0) { - /* client requested transmission after end of test */ - lwiperf_tx_start_passive(conn); - } - } - lwiperf_tcp_close(conn, LWIPERF_TCP_DONE_SERVER); - return ERR_OK; - } - tot_len = p->tot_len; - - conn->poll_count = 0; - - if ((!conn->have_settings_buf) || ((conn->bytes_transferred - 24) % (1024 * 128) == 0)) { - /* wait for 24-byte header */ - if (p->tot_len < sizeof(lwiperf_settings_t)) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); - pbuf_free(p); - return ERR_OK; - } - if (!conn->have_settings_buf) { - if (pbuf_copy_partial(p, &conn->settings, sizeof(lwiperf_settings_t), 0) != sizeof(lwiperf_settings_t)) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); - pbuf_free(p); - return ERR_OK; - } - conn->have_settings_buf = 1; - if (conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) { - if (conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_NOW)) { - /* client requested parallel transmission test */ - err_t err2 = lwiperf_tx_start_passive(conn); - if (err2 != ERR_OK) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_TXERROR); - pbuf_free(p); - return ERR_OK; - } - } - } - } else { - if (conn->settings.flags & PP_HTONL(LWIPERF_FLAGS_ANSWER_TEST)) { - if (pbuf_memcmp(p, 0, &conn->settings, sizeof(lwiperf_settings_t)) != 0) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); - pbuf_free(p); - return ERR_OK; - } - } - } - conn->bytes_transferred += sizeof(lwiperf_settings_t); - if (conn->bytes_transferred <= 24) { - conn->time_started = sys_now(); - tcp_recved(tpcb, p->tot_len); - pbuf_free(p); - return ERR_OK; - } - conn->next_num = 4; /* 24 bytes received... */ - tmp = pbuf_remove_header(p, 24); - LWIP_ASSERT("pbuf_remove_header failed", tmp == 0); - LWIP_UNUSED_ARG(tmp); /* for LWIP_NOASSERT */ - } - - packet_idx = 0; - for (q = p; q != NULL; q = q->next) { -#if LWIPERF_CHECK_RX_DATA - const u8_t *payload = (const u8_t *)q->payload; - u16_t i; - for (i = 0; i < q->len; i++) { - u8_t val = payload[i]; - u8_t num = val - '0'; - if (num == conn->next_num) { - conn->next_num++; - if (conn->next_num == 10) { - conn->next_num = 0; - } - } else { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL_DATAERROR); - pbuf_free(p); - return ERR_OK; - } - } -#endif - packet_idx += q->len; - } - LWIP_ASSERT("count mismatch", packet_idx == p->tot_len); - conn->bytes_transferred += packet_idx; - tcp_recved(tpcb, tot_len); - pbuf_free(p); - return ERR_OK; -} - -/** Error callback, iperf tcp session aborted */ -static void -lwiperf_tcp_err(void *arg, err_t err) -{ - lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg; - LWIP_UNUSED_ARG(err); - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_REMOTE); -} - -/** TCP poll callback, try to send more data */ -static err_t -lwiperf_tcp_poll(void *arg, struct tcp_pcb *tpcb) -{ - lwiperf_state_tcp_t *conn = (lwiperf_state_tcp_t *)arg; - LWIP_ASSERT("pcb mismatch", conn->conn_pcb == tpcb); - LWIP_UNUSED_ARG(tpcb); - if (++conn->poll_count >= LWIPERF_TCP_MAX_IDLE_SEC) { - lwiperf_tcp_close(conn, LWIPERF_TCP_ABORTED_LOCAL); - return ERR_OK; /* lwiperf_tcp_close frees conn */ - } - - if (!conn->base.server) { - lwiperf_tcp_client_send_more(conn); - } - - return ERR_OK; -} - -/** This is called when a new client connects for an iperf tcp session */ -static err_t -lwiperf_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) -{ - lwiperf_state_tcp_t *s, *conn; - if ((err != ERR_OK) || (newpcb == NULL) || (arg == NULL)) { - return ERR_VAL; - } - - s = (lwiperf_state_tcp_t *)arg; - LWIP_ASSERT("invalid session", s->base.server); - LWIP_ASSERT("invalid listen pcb", s->server_pcb != NULL); - LWIP_ASSERT("invalid conn pcb", s->conn_pcb == NULL); - if (s->specific_remote) { - LWIP_ASSERT("s->base.related_master_state != NULL", s->base.related_master_state != NULL); - if (!ip_addr_cmp(&newpcb->remote_ip, &s->remote_addr)) { - /* this listener belongs to a client session, and this is not the correct remote */ - return ERR_VAL; - } - } else { - LWIP_ASSERT("s->base.related_master_state == NULL", s->base.related_master_state == NULL); - } - - conn = (lwiperf_state_tcp_t *)LWIPERF_ALLOC(lwiperf_state_tcp_t); - if (conn == NULL) { - return ERR_MEM; - } - memset(conn, 0, sizeof(lwiperf_state_tcp_t)); - conn->base.tcp = 1; - conn->base.server = 1; - conn->base.related_master_state = &s->base; - conn->conn_pcb = newpcb; - conn->time_started = sys_now(); - conn->report_fn = s->report_fn; - conn->report_arg = s->report_arg; - - /* setup the tcp rx connection */ - tcp_arg(newpcb, conn); - tcp_recv(newpcb, lwiperf_tcp_recv); - tcp_poll(newpcb, lwiperf_tcp_poll, 2U); - tcp_err(conn->conn_pcb, lwiperf_tcp_err); - - if (s->specific_remote) { - /* this listener belongs to a client, so make the client the master of the newly created connection */ - conn->base.related_master_state = s->base.related_master_state; - /* if dual mode or (tradeoff mode AND client is done): close the listener */ - if (!s->client_tradeoff_mode || !lwiperf_list_find(s->base.related_master_state)) { - /* prevent report when closing: this is expected */ - s->report_fn = NULL; - lwiperf_tcp_close(s, LWIPERF_TCP_ABORTED_LOCAL); - } - } - lwiperf_list_add(&conn->base); - return ERR_OK; -} - -/** - * @ingroup iperf - * Start a TCP iperf server on the default TCP port (5001) and listen for - * incoming connections from iperf clients. - * - * @returns a connection handle that can be used to abort the server - * by calling @ref lwiperf_abort() - */ -void * -lwiperf_start_tcp_server_default(lwiperf_report_fn report_fn, void *report_arg) -{ - return lwiperf_start_tcp_server(IP_ADDR_ANY, LWIPERF_TCP_PORT_DEFAULT, - report_fn, report_arg); -} - -/** - * @ingroup iperf - * Start a TCP iperf server on a specific IP address and port and listen for - * incoming connections from iperf clients. - * - * @returns a connection handle that can be used to abort the server - * by calling @ref lwiperf_abort() - */ -void * -lwiperf_start_tcp_server(const ip_addr_t *local_addr, u16_t local_port, - lwiperf_report_fn report_fn, void *report_arg) -{ - err_t err; - lwiperf_state_tcp_t *state = NULL; - - err = lwiperf_start_tcp_server_impl(local_addr, local_port, report_fn, report_arg, - NULL, &state); - if (err == ERR_OK) { - return state; - } - return NULL; -} - -static err_t lwiperf_start_tcp_server_impl(const ip_addr_t *local_addr, u16_t local_port, - lwiperf_report_fn report_fn, void *report_arg, - lwiperf_state_base_t *related_master_state, lwiperf_state_tcp_t **state) -{ - err_t err; - struct tcp_pcb *pcb; - lwiperf_state_tcp_t *s; - - LWIP_ASSERT_CORE_LOCKED(); - - LWIP_ASSERT("state != NULL", state != NULL); - - if (local_addr == NULL) { - return ERR_ARG; - } - - s = (lwiperf_state_tcp_t *)LWIPERF_ALLOC(lwiperf_state_tcp_t); - if (s == NULL) { - return ERR_MEM; - } - memset(s, 0, sizeof(lwiperf_state_tcp_t)); - s->base.tcp = 1; - s->base.server = 1; - s->base.related_master_state = related_master_state; - s->report_fn = report_fn; - s->report_arg = report_arg; - - pcb = tcp_new_ip_type(LWIPERF_SERVER_IP_TYPE); - if (pcb == NULL) { - return ERR_MEM; - } - err = tcp_bind(pcb, local_addr, local_port); - if (err != ERR_OK) { - return err; - } - s->server_pcb = tcp_listen_with_backlog(pcb, 1); - if (s->server_pcb == NULL) { - if (pcb != NULL) { - tcp_close(pcb); - } - LWIPERF_FREE(lwiperf_state_tcp_t, s); - return ERR_MEM; - } - pcb = NULL; - - tcp_arg(s->server_pcb, s); - tcp_accept(s->server_pcb, lwiperf_tcp_accept); - - lwiperf_list_add(&s->base); - *state = s; - return ERR_OK; -} - -/** - * @ingroup iperf - * Start a TCP iperf client to the default TCP port (5001). - * - * @returns a connection handle that can be used to abort the client - * by calling @ref lwiperf_abort() - */ -void* lwiperf_start_tcp_client_default(const ip_addr_t* remote_addr, - lwiperf_report_fn report_fn, void* report_arg) -{ - return lwiperf_start_tcp_client(remote_addr, LWIPERF_TCP_PORT_DEFAULT, LWIPERF_CLIENT, - report_fn, report_arg); -} - -/** - * @ingroup iperf - * Start a TCP iperf client to a specific IP address and port. - * - * @returns a connection handle that can be used to abort the client - * by calling @ref lwiperf_abort() - */ -void* lwiperf_start_tcp_client(const ip_addr_t* remote_addr, u16_t remote_port, - enum lwiperf_client_type type, lwiperf_report_fn report_fn, void* report_arg) -{ - err_t ret; - lwiperf_settings_t settings; - lwiperf_state_tcp_t *state = NULL; - - memset(&settings, 0, sizeof(settings)); - switch (type) { - case LWIPERF_CLIENT: - /* Unidirectional tx only test */ - settings.flags = 0; - break; - case LWIPERF_DUAL: - /* Do a bidirectional test simultaneously */ - settings.flags = htonl(LWIPERF_FLAGS_ANSWER_TEST | LWIPERF_FLAGS_ANSWER_NOW); - break; - case LWIPERF_TRADEOFF: - /* Do a bidirectional test individually */ - settings.flags = htonl(LWIPERF_FLAGS_ANSWER_TEST); - break; - default: - /* invalid argument */ - return NULL; - } - settings.num_threads = htonl(1); - settings.remote_port = htonl(LWIPERF_TCP_PORT_DEFAULT); - /* TODO: implement passing duration/amount of bytes to transfer */ - settings.amount = htonl((u32_t)-1000); - - ret = lwiperf_tx_start_impl(remote_addr, remote_port, &settings, report_fn, report_arg, NULL, &state); - if (ret == ERR_OK) { - LWIP_ASSERT("state != NULL", state != NULL); - if (type != LWIPERF_CLIENT) { - /* start corresponding server now */ - lwiperf_state_tcp_t *server = NULL; - ret = lwiperf_start_tcp_server_impl(&state->conn_pcb->local_ip, LWIPERF_TCP_PORT_DEFAULT, - report_fn, report_arg, (lwiperf_state_base_t *)state, &server); - if (ret != ERR_OK) { - /* starting server failed, abort client */ - lwiperf_abort(state); - return NULL; - } - /* make this server accept one connection only */ - server->specific_remote = 1; - server->remote_addr = state->conn_pcb->remote_ip; - if (type == LWIPERF_TRADEOFF) { - /* tradeoff means that the remote host connects only after the client is done, - so keep the listen pcb open until the client is done */ - server->client_tradeoff_mode = 1; - } - } - return state; - } - return NULL; -} - -/** - * @ingroup iperf - * Abort an iperf session (handle returned by lwiperf_start_tcp_server*()) - */ -void -lwiperf_abort(void *lwiperf_session) -{ - lwiperf_state_base_t *i, *dealloc, *last = NULL; - - LWIP_ASSERT_CORE_LOCKED(); - - for (i = lwiperf_all_connections; i != NULL; ) { - if ((i == lwiperf_session) || (i->related_master_state == lwiperf_session)) { - dealloc = i; - i = i->next; - if (last != NULL) { - last->next = i; - } - LWIPERF_FREE(lwiperf_state_tcp_t, dealloc); /* @todo: type? */ - } else { - last = i; - i = i->next; - } - } -} - -#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/mdns/mdns.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/mdns/mdns.c deleted file mode 100644 index aad272889..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/mdns/mdns.c +++ /dev/null @@ -1,2407 +0,0 @@ -/** - * @file - * MDNS responder implementation - * - * @defgroup mdns MDNS - * @ingroup apps - * - * RFC 6762 - Multicast DNS\n - * RFC 6763 - DNS-Based Service Discovery\n - * - * @verbinclude mdns.txt - * - * Things left to implement: - * ------------------------- - * - * - Tiebreaking for simultaneous probing - * - Sending goodbye messages (zero ttl) - shutdown, DHCP lease about to expire, DHCP turned off... - * - Checking that source address of unicast requests are on the same network - * - Limiting multicast responses to 1 per second per resource record - * - Fragmenting replies if required - * - Handling multi-packet known answers - * - Individual known answer detection for all local IPv6 addresses - * - Dynamic size of outgoing packet - */ - -/* - * Copyright (c) 2015 Verisure Innovation AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Erik Ekman - * - */ - -#include "lwip/apps/mdns.h" -#include "lwip/apps/mdns_priv.h" -#include "lwip/netif.h" -#include "lwip/udp.h" -#include "lwip/ip_addr.h" -#include "lwip/mem.h" -#include "lwip/prot/dns.h" -#include "lwip/prot/iana.h" -#include "lwip/timeouts.h" - -#include - -#if LWIP_MDNS_RESPONDER - -#if (LWIP_IPV4 && !LWIP_IGMP) -#error "If you want to use MDNS with IPv4, you have to define LWIP_IGMP=1 in your lwipopts.h" -#endif -#if (LWIP_IPV6 && !LWIP_IPV6_MLD) -#error "If you want to use MDNS with IPv6, you have to define LWIP_IPV6_MLD=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP) -#error "If you want to use MDNS, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif - -#if LWIP_IPV4 -#include "lwip/igmp.h" -/* IPv4 multicast group 224.0.0.251 */ -static const ip_addr_t v4group = DNS_MQUERY_IPV4_GROUP_INIT; -#endif - -#if LWIP_IPV6 -#include "lwip/mld6.h" -/* IPv6 multicast group FF02::FB */ -static const ip_addr_t v6group = DNS_MQUERY_IPV6_GROUP_INIT; -#endif - -#define MDNS_TTL 255 - -/* Stored offsets to beginning of domain names - * Used for compression. - */ -#define NUM_DOMAIN_OFFSETS 10 -#define DOMAIN_JUMP_SIZE 2 -#define DOMAIN_JUMP 0xc000 - -static u8_t mdns_netif_client_id; -static struct udp_pcb *mdns_pcb; -#if MDNS_RESP_USENETIF_EXTCALLBACK -NETIF_DECLARE_EXT_CALLBACK(netif_callback) -#endif -static mdns_name_result_cb_t mdns_name_result_cb; - -#define NETIF_TO_HOST(netif) (struct mdns_host*)(netif_get_client_data(netif, mdns_netif_client_id)) - -#define TOPDOMAIN_LOCAL "local" - -#define REVERSE_PTR_TOPDOMAIN "arpa" -#define REVERSE_PTR_V4_DOMAIN "in-addr" -#define REVERSE_PTR_V6_DOMAIN "ip6" - -#define SRV_PRIORITY 0 -#define SRV_WEIGHT 0 - -/* Payload size allocated for each outgoing UDP packet */ -#define OUTPACKET_SIZE 500 - -/* Lookup from hostname -> IPv4 */ -#define REPLY_HOST_A 0x01 -/* Lookup from IPv4/v6 -> hostname */ -#define REPLY_HOST_PTR_V4 0x02 -/* Lookup from hostname -> IPv6 */ -#define REPLY_HOST_AAAA 0x04 -/* Lookup from hostname -> IPv6 */ -#define REPLY_HOST_PTR_V6 0x08 - -/* Lookup for service types */ -#define REPLY_SERVICE_TYPE_PTR 0x10 -/* Lookup for instances of service */ -#define REPLY_SERVICE_NAME_PTR 0x20 -/* Lookup for location of service instance */ -#define REPLY_SERVICE_SRV 0x40 -/* Lookup for text info on service instance */ -#define REPLY_SERVICE_TXT 0x80 - -#define MDNS_PROBE_DELAY_MS 250 -#define MDNS_PROBE_COUNT 3 -#ifdef LWIP_RAND -/* first probe timeout SHOULD be random 0-250 ms*/ -#define MDNS_INITIAL_PROBE_DELAY_MS (LWIP_RAND() % MDNS_PROBE_DELAY_MS) -#else -#define MDNS_INITIAL_PROBE_DELAY_MS MDNS_PROBE_DELAY_MS -#endif - -#define MDNS_PROBING_NOT_STARTED 0 -#define MDNS_PROBING_ONGOING 1 -#define MDNS_PROBING_COMPLETE 2 - -static const char *dnssd_protos[] = { - "_udp", /* DNSSD_PROTO_UDP */ - "_tcp", /* DNSSD_PROTO_TCP */ -}; - -/** Description of a service */ -struct mdns_service { - /** TXT record to answer with */ - struct mdns_domain txtdata; - /** Name of service, like 'myweb' */ - char name[MDNS_LABEL_MAXLEN + 1]; - /** Type of service, like '_http' */ - char service[MDNS_LABEL_MAXLEN + 1]; - /** Callback function and userdata - * to update txtdata buffer */ - service_get_txt_fn_t txt_fn; - void *txt_userdata; - /** TTL in seconds of SRV/TXT replies */ - u32_t dns_ttl; - /** Protocol, TCP or UDP */ - u16_t proto; - /** Port of the service */ - u16_t port; -}; - -/** Description of a host/netif */ -struct mdns_host { - /** Hostname */ - char name[MDNS_LABEL_MAXLEN + 1]; - /** Pointer to services */ - struct mdns_service *services[MDNS_MAX_SERVICES]; - /** TTL in seconds of A/AAAA/PTR replies */ - u32_t dns_ttl; - /** Number of probes sent for the current name */ - u8_t probes_sent; - /** State in probing sequence */ - u8_t probing_state; -}; - -/** Information about received packet */ -struct mdns_packet { - /** Sender IP/port */ - ip_addr_t source_addr; - u16_t source_port; - /** If packet was received unicast */ - u16_t recv_unicast; - /** Netif that received the packet */ - struct netif *netif; - /** Packet data */ - struct pbuf *pbuf; - /** Current parsing offset in packet */ - u16_t parse_offset; - /** Identifier. Used in legacy queries */ - u16_t tx_id; - /** Number of questions in packet, - * read from packet header */ - u16_t questions; - /** Number of unparsed questions */ - u16_t questions_left; - /** Number of answers in packet, - * (sum of normal, authoritative and additional answers) - * read from packet header */ - u16_t answers; - /** Number of unparsed answers */ - u16_t answers_left; -}; - -/** Information about outgoing packet */ -struct mdns_outpacket { - /** Netif to send the packet on */ - struct netif *netif; - /** Packet data */ - struct pbuf *pbuf; - /** Current write offset in packet */ - u16_t write_offset; - /** Identifier. Used in legacy queries */ - u16_t tx_id; - /** Destination IP/port if sent unicast */ - ip_addr_t dest_addr; - u16_t dest_port; - /** Number of questions written */ - u16_t questions; - /** Number of normal answers written */ - u16_t answers; - /** Number of authoritative answers written */ - u16_t authoritative; - /** Number of additional answers written */ - u16_t additional; - /** Offsets for written domain names in packet. - * Used for compression */ - u16_t domain_offsets[NUM_DOMAIN_OFFSETS]; - /** If all answers in packet should set cache_flush bit */ - u8_t cache_flush; - /** If reply should be sent unicast */ - u8_t unicast_reply; - /** If legacy query. (tx_id needed, and write - * question again in reply before answer) */ - u8_t legacy_query; - /* Reply bitmask for host information */ - u8_t host_replies; - /* Bitmask for which reverse IPv6 hosts to answer */ - u8_t host_reverse_v6_replies; - /* Reply bitmask per service */ - u8_t serv_replies[MDNS_MAX_SERVICES]; -}; - -/** Domain, type and class. - * Shared between questions and answers */ -struct mdns_rr_info { - struct mdns_domain domain; - u16_t type; - u16_t klass; -}; - -struct mdns_question { - struct mdns_rr_info info; - /** unicast reply requested */ - u16_t unicast; -}; - -struct mdns_answer { - struct mdns_rr_info info; - /** cache flush command bit */ - u16_t cache_flush; - /* Validity time in seconds */ - u32_t ttl; - /** Length of variable answer */ - u16_t rd_length; - /** Offset of start of variable answer in packet */ - u16_t rd_offset; -}; - -static err_t mdns_send_outpacket(struct mdns_outpacket *outpkt, u8_t flags); -static void mdns_probe(void* arg); - -static err_t -mdns_domain_add_label_base(struct mdns_domain *domain, u8_t len) -{ - if (len > MDNS_LABEL_MAXLEN) { - return ERR_VAL; - } - if (len > 0 && (1 + len + domain->length >= MDNS_DOMAIN_MAXLEN)) { - return ERR_VAL; - } - /* Allow only zero marker on last byte */ - if (len == 0 && (1 + domain->length > MDNS_DOMAIN_MAXLEN)) { - return ERR_VAL; - } - domain->name[domain->length] = len; - domain->length++; - return ERR_OK; -} - -/** - * Add a label part to a domain - * @param domain The domain to add a label to - * @param label The label to add, like <hostname>, 'local', 'com' or '' - * @param len The length of the label - * @return ERR_OK on success, an err_t otherwise if label too long - */ -err_t -mdns_domain_add_label(struct mdns_domain *domain, const char *label, u8_t len) -{ - err_t err = mdns_domain_add_label_base(domain, len); - if (err != ERR_OK) { - return err; - } - if (len) { - MEMCPY(&domain->name[domain->length], label, len); - domain->length += len; - } - return ERR_OK; -} - -/** - * Add a label part to a domain (@see mdns_domain_add_label but copy directly from pbuf) - */ -static err_t -mdns_domain_add_label_pbuf(struct mdns_domain *domain, const struct pbuf *p, u16_t offset, u8_t len) -{ - err_t err = mdns_domain_add_label_base(domain, len); - if (err != ERR_OK) { - return err; - } - if (len) { - if (pbuf_copy_partial(p, &domain->name[domain->length], len, offset) != len) { - /* take back the ++ done before */ - domain->length--; - return ERR_ARG; - } - domain->length += len; - } - return ERR_OK; -} - -/** - * Internal readname function with max 6 levels of recursion following jumps - * while decompressing name - */ -static u16_t -mdns_readname_loop(struct pbuf *p, u16_t offset, struct mdns_domain *domain, unsigned depth) -{ - u8_t c; - - do { - if (depth > 5) { - /* Too many jumps */ - return MDNS_READNAME_ERROR; - } - - c = pbuf_get_at(p, offset); - offset++; - - /* is this a compressed label? */ - if ((c & 0xc0) == 0xc0) { - u16_t jumpaddr; - if (offset >= p->tot_len) { - /* Make sure both jump bytes fit in the packet */ - return MDNS_READNAME_ERROR; - } - jumpaddr = (((c & 0x3f) << 8) | (pbuf_get_at(p, offset) & 0xff)); - offset++; - if (jumpaddr >= SIZEOF_DNS_HDR && jumpaddr < p->tot_len) { - u16_t res; - /* Recursive call, maximum depth will be checked */ - res = mdns_readname_loop(p, jumpaddr, domain, depth + 1); - /* Dont return offset since new bytes were not read (jumped to somewhere in packet) */ - if (res == MDNS_READNAME_ERROR) { - return res; - } - } else { - return MDNS_READNAME_ERROR; - } - break; - } - - /* normal label */ - if (c <= MDNS_LABEL_MAXLEN) { - err_t res; - - if (c + domain->length >= MDNS_DOMAIN_MAXLEN) { - return MDNS_READNAME_ERROR; - } - res = mdns_domain_add_label_pbuf(domain, p, offset, c); - if (res != ERR_OK) { - return MDNS_READNAME_ERROR; - } - offset += c; - } else { - /* bad length byte */ - return MDNS_READNAME_ERROR; - } - } while (c != 0); - - return offset; -} - -/** - * Read possibly compressed domain name from packet buffer - * @param p The packet - * @param offset start position of domain name in packet - * @param domain The domain name destination - * @return The new offset after the domain, or MDNS_READNAME_ERROR - * if reading failed - */ -u16_t -mdns_readname(struct pbuf *p, u16_t offset, struct mdns_domain *domain) -{ - memset(domain, 0, sizeof(struct mdns_domain)); - return mdns_readname_loop(p, offset, domain, 0); -} - -/** - * Print domain name to debug output - * @param domain The domain name - */ -static void -mdns_domain_debug_print(struct mdns_domain *domain) -{ - u8_t *src = domain->name; - u8_t i; - - while (*src) { - u8_t label_len = *src; - src++; - for (i = 0; i < label_len; i++) { - LWIP_DEBUGF(MDNS_DEBUG, ("%c", src[i])); - } - src += label_len; - LWIP_DEBUGF(MDNS_DEBUG, (".")); - } -} - -/** - * Return 1 if contents of domains match (case-insensitive) - * @param a Domain name to compare 1 - * @param b Domain name to compare 2 - * @return 1 if domains are equal ignoring case, 0 otherwise - */ -int -mdns_domain_eq(struct mdns_domain *a, struct mdns_domain *b) -{ - u8_t *ptra, *ptrb; - u8_t len; - int res; - - if (a->length != b->length) { - return 0; - } - - ptra = a->name; - ptrb = b->name; - while (*ptra && *ptrb && ptra < &a->name[a->length]) { - if (*ptra != *ptrb) { - return 0; - } - len = *ptra; - ptra++; - ptrb++; - res = lwip_strnicmp((char *) ptra, (char *) ptrb, len); - if (res != 0) { - return 0; - } - ptra += len; - ptrb += len; - } - if (*ptra != *ptrb && ptra < &a->name[a->length]) { - return 0; - } - return 1; -} - -/** - * Call user supplied function to setup TXT data - * @param service The service to build TXT record for - */ -static void -mdns_prepare_txtdata(struct mdns_service *service) -{ - memset(&service->txtdata, 0, sizeof(struct mdns_domain)); - if (service->txt_fn) { - service->txt_fn(service, service->txt_userdata); - } -} - -#if LWIP_IPV4 -/** - * Build domain for reverse lookup of IPv4 address - * like 12.0.168.192.in-addr.arpa. for 192.168.0.12 - * @param domain Where to write the domain name - * @param addr Pointer to an IPv4 address to encode - * @return ERR_OK if domain was written, an err_t otherwise - */ -static err_t -mdns_build_reverse_v4_domain(struct mdns_domain *domain, const ip4_addr_t *addr) -{ - int i; - err_t res; - const u8_t *ptr; - - LWIP_UNUSED_ARG(res); - if (!domain || !addr) { - return ERR_ARG; - } - memset(domain, 0, sizeof(struct mdns_domain)); - ptr = (const u8_t *) addr; - for (i = sizeof(ip4_addr_t) - 1; i >= 0; i--) { - char buf[4]; - u8_t val = ptr[i]; - - lwip_itoa(buf, sizeof(buf), val); - res = mdns_domain_add_label(domain, buf, (u8_t)strlen(buf)); - LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); - } - res = mdns_domain_add_label(domain, REVERSE_PTR_V4_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V4_DOMAIN) - 1)); - LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN) - 1)); - LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, NULL, 0); - LWIP_ERROR("mdns_build_reverse_v4_domain: Failed to add label", (res == ERR_OK), return res); - - return ERR_OK; -} -#endif - -#if LWIP_IPV6 -/** - * Build domain for reverse lookup of IP address - * like b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. for 2001:db8::567:89ab - * @param domain Where to write the domain name - * @param addr Pointer to an IPv6 address to encode - * @return ERR_OK if domain was written, an err_t otherwise - */ -static err_t -mdns_build_reverse_v6_domain(struct mdns_domain *domain, const ip6_addr_t *addr) -{ - int i; - err_t res; - const u8_t *ptr; - LWIP_UNUSED_ARG(res); - if (!domain || !addr) { - return ERR_ARG; - } - memset(domain, 0, sizeof(struct mdns_domain)); - ptr = (const u8_t *) addr; - for (i = sizeof(ip6_addr_p_t) - 1; i >= 0; i--) { - char buf; - u8_t byte = ptr[i]; - int j; - for (j = 0; j < 2; j++) { - if ((byte & 0x0F) < 0xA) { - buf = '0' + (byte & 0x0F); - } else { - buf = 'a' + (byte & 0x0F) - 0xA; - } - res = mdns_domain_add_label(domain, &buf, sizeof(buf)); - LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); - byte >>= 4; - } - } - res = mdns_domain_add_label(domain, REVERSE_PTR_V6_DOMAIN, (u8_t)(sizeof(REVERSE_PTR_V6_DOMAIN) - 1)); - LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, REVERSE_PTR_TOPDOMAIN, (u8_t)(sizeof(REVERSE_PTR_TOPDOMAIN) - 1)); - LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, NULL, 0); - LWIP_ERROR("mdns_build_reverse_v6_domain: Failed to add label", (res == ERR_OK), return res); - - return ERR_OK; -} -#endif - -/* Add .local. to domain */ -static err_t -mdns_add_dotlocal(struct mdns_domain *domain) -{ - err_t res = mdns_domain_add_label(domain, TOPDOMAIN_LOCAL, (u8_t)(sizeof(TOPDOMAIN_LOCAL) - 1)); - LWIP_UNUSED_ARG(res); - LWIP_ERROR("mdns_add_dotlocal: Failed to add label", (res == ERR_OK), return res); - return mdns_domain_add_label(domain, NULL, 0); -} - -/** - * Build the .local. domain name - * @param domain Where to write the domain name - * @param mdns TMDNS netif descriptor. - * @return ERR_OK if domain .local. was written, an err_t otherwise - */ -static err_t -mdns_build_host_domain(struct mdns_domain *domain, struct mdns_host *mdns) -{ - err_t res; - LWIP_UNUSED_ARG(res); - memset(domain, 0, sizeof(struct mdns_domain)); - LWIP_ERROR("mdns_build_host_domain: mdns != NULL", (mdns != NULL), return ERR_VAL); - res = mdns_domain_add_label(domain, mdns->name, (u8_t)strlen(mdns->name)); - LWIP_ERROR("mdns_build_host_domain: Failed to add label", (res == ERR_OK), return res); - return mdns_add_dotlocal(domain); -} - -/** - * Build the lookup-all-services special DNS-SD domain name - * @param domain Where to write the domain name - * @return ERR_OK if domain _services._dns-sd._udp.local. was written, an err_t otherwise - */ -static err_t -mdns_build_dnssd_domain(struct mdns_domain *domain) -{ - err_t res; - LWIP_UNUSED_ARG(res); - memset(domain, 0, sizeof(struct mdns_domain)); - res = mdns_domain_add_label(domain, "_services", (u8_t)(sizeof("_services") - 1)); - LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, "_dns-sd", (u8_t)(sizeof("_dns-sd") - 1)); - LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, dnssd_protos[DNSSD_PROTO_UDP], (u8_t)strlen(dnssd_protos[DNSSD_PROTO_UDP])); - LWIP_ERROR("mdns_build_dnssd_domain: Failed to add label", (res == ERR_OK), return res); - return mdns_add_dotlocal(domain); -} - -/** - * Build domain name for a service - * @param domain Where to write the domain name - * @param service The service struct, containing service name, type and protocol - * @param include_name Whether to include the service name in the domain - * @return ERR_OK if domain was written. If service name is included, - * ...local. will be written, otherwise ..local. - * An err_t is returned on error. - */ -static err_t -mdns_build_service_domain(struct mdns_domain *domain, struct mdns_service *service, int include_name) -{ - err_t res; - LWIP_UNUSED_ARG(res); - memset(domain, 0, sizeof(struct mdns_domain)); - if (include_name) { - res = mdns_domain_add_label(domain, service->name, (u8_t)strlen(service->name)); - LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); - } - res = mdns_domain_add_label(domain, service->service, (u8_t)strlen(service->service)); - LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); - res = mdns_domain_add_label(domain, dnssd_protos[service->proto], (u8_t)strlen(dnssd_protos[service->proto])); - LWIP_ERROR("mdns_build_service_domain: Failed to add label", (res == ERR_OK), return res); - return mdns_add_dotlocal(domain); -} - -/** - * Check which replies we should send for a host/netif based on question - * @param netif The network interface that received the question - * @param rr Domain/type/class from a question - * @param reverse_v6_reply Bitmask of which IPv6 addresses to send reverse PTRs for - * if reply bit has REPLY_HOST_PTR_V6 set - * @return Bitmask of which replies to send - */ -static int -check_host(struct netif *netif, struct mdns_rr_info *rr, u8_t *reverse_v6_reply) -{ - err_t res; - int replies = 0; - struct mdns_domain mydomain; - - LWIP_UNUSED_ARG(reverse_v6_reply); /* if ipv6 is disabled */ - - if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) { - /* Invalid class */ - return replies; - } - - /* Handle PTR for our addresses */ - if (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY) { -#if LWIP_IPV6 - int i; - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { - res = mdns_build_reverse_v6_domain(&mydomain, netif_ip6_addr(netif, i)); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { - replies |= REPLY_HOST_PTR_V6; - /* Mark which addresses where requested */ - if (reverse_v6_reply) { - *reverse_v6_reply |= (1 << i); - } - } - } - } -#endif -#if LWIP_IPV4 - if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { - res = mdns_build_reverse_v4_domain(&mydomain, netif_ip4_addr(netif)); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { - replies |= REPLY_HOST_PTR_V4; - } - } -#endif - } - - res = mdns_build_host_domain(&mydomain, NETIF_TO_HOST(netif)); - /* Handle requests for our hostname */ - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { - /* TODO return NSEC if unsupported protocol requested */ -#if LWIP_IPV4 - if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) - && (rr->type == DNS_RRTYPE_A || rr->type == DNS_RRTYPE_ANY)) { - replies |= REPLY_HOST_A; - } -#endif -#if LWIP_IPV6 - if (rr->type == DNS_RRTYPE_AAAA || rr->type == DNS_RRTYPE_ANY) { - replies |= REPLY_HOST_AAAA; - } -#endif - } - - return replies; -} - -/** - * Check which replies we should send for a service based on question - * @param service A registered MDNS service - * @param rr Domain/type/class from a question - * @return Bitmask of which replies to send - */ -static int -check_service(struct mdns_service *service, struct mdns_rr_info *rr) -{ - err_t res; - int replies = 0; - struct mdns_domain mydomain; - - if (rr->klass != DNS_RRCLASS_IN && rr->klass != DNS_RRCLASS_ANY) { - /* Invalid class */ - return 0; - } - - res = mdns_build_dnssd_domain(&mydomain); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) && - (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) { - /* Request for all service types */ - replies |= REPLY_SERVICE_TYPE_PTR; - } - - res = mdns_build_service_domain(&mydomain, service, 0); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain) && - (rr->type == DNS_RRTYPE_PTR || rr->type == DNS_RRTYPE_ANY)) { - /* Request for the instance of my service */ - replies |= REPLY_SERVICE_NAME_PTR; - } - - res = mdns_build_service_domain(&mydomain, service, 1); - if (res == ERR_OK && mdns_domain_eq(&rr->domain, &mydomain)) { - /* Request for info about my service */ - if (rr->type == DNS_RRTYPE_SRV || rr->type == DNS_RRTYPE_ANY) { - replies |= REPLY_SERVICE_SRV; - } - if (rr->type == DNS_RRTYPE_TXT || rr->type == DNS_RRTYPE_ANY) { - replies |= REPLY_SERVICE_TXT; - } - } - - return replies; -} - -/** - * Return bytes needed to write before jump for best result of compressing supplied domain - * against domain in outpacket starting at specified offset. - * If a match is found, offset is updated to where to jump to - * @param pbuf Pointer to pbuf with the partially constructed DNS packet - * @param offset Start position of a domain written earlier. If this location is suitable - * for compression, the pointer is updated to where in the domain to jump to. - * @param domain The domain to write - * @return Number of bytes to write of the new domain before writing a jump to the offset. - * If compression can not be done against this previous domain name, the full new - * domain length is returned. - */ -u16_t -mdns_compress_domain(struct pbuf *pbuf, u16_t *offset, struct mdns_domain *domain) -{ - struct mdns_domain target; - u16_t target_end; - u8_t target_len; - u8_t writelen = 0; - u8_t *ptr; - if (pbuf == NULL) { - return domain->length; - } - target_end = mdns_readname(pbuf, *offset, &target); - if (target_end == MDNS_READNAME_ERROR) { - return domain->length; - } - target_len = (u8_t)(target_end - *offset); - ptr = domain->name; - while (writelen < domain->length) { - u8_t domainlen = (u8_t)(domain->length - writelen); - u8_t labellen; - if (domainlen <= target.length && domainlen > DOMAIN_JUMP_SIZE) { - /* Compare domains if target is long enough, and we have enough left of the domain */ - u8_t targetpos = (u8_t)(target.length - domainlen); - if ((targetpos + DOMAIN_JUMP_SIZE) >= target_len) { - /* We are checking at or beyond a jump in the original, stop looking */ - break; - } - if (target.length >= domainlen && - memcmp(&domain->name[writelen], &target.name[targetpos], domainlen) == 0) { - *offset += targetpos; - return writelen; - } - } - /* Skip to next label in domain */ - labellen = *ptr; - writelen += 1 + labellen; - ptr += 1 + labellen; - } - /* Nothing found */ - return domain->length; -} - -/** - * Write domain to outpacket. Compression will be attempted, - * unless domain->skip_compression is set. - * @param outpkt The outpacket to write to - * @param domain The domain name to write - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_write_domain(struct mdns_outpacket *outpkt, struct mdns_domain *domain) -{ - int i; - err_t res; - u16_t writelen = domain->length; - u16_t jump_offset = 0; - u16_t jump; - - if (!domain->skip_compression) { - for (i = 0; i < NUM_DOMAIN_OFFSETS; i++) { - u16_t offset = outpkt->domain_offsets[i]; - if (offset) { - u16_t len = mdns_compress_domain(outpkt->pbuf, &offset, domain); - if (len < writelen) { - writelen = len; - jump_offset = offset; - } - } - } - } - - if (writelen) { - /* Write uncompressed part of name */ - res = pbuf_take_at(outpkt->pbuf, domain->name, writelen, outpkt->write_offset); - if (res != ERR_OK) { - return res; - } - - /* Store offset of this new domain */ - for (i = 0; i < NUM_DOMAIN_OFFSETS; i++) { - if (outpkt->domain_offsets[i] == 0) { - outpkt->domain_offsets[i] = outpkt->write_offset; - break; - } - } - - outpkt->write_offset += writelen; - } - if (jump_offset) { - /* Write jump */ - jump = lwip_htons(DOMAIN_JUMP | jump_offset); - res = pbuf_take_at(outpkt->pbuf, &jump, DOMAIN_JUMP_SIZE, outpkt->write_offset); - if (res != ERR_OK) { - return res; - } - outpkt->write_offset += DOMAIN_JUMP_SIZE; - } - return ERR_OK; -} - -/** - * Write a question to an outpacket - * A question contains domain, type and class. Since an answer also starts with these fields this function is also - * called from mdns_add_answer(). - * @param outpkt The outpacket to write to - * @param domain The domain name the answer is for - * @param type The DNS type of the answer (like 'AAAA', 'SRV') - * @param klass The DNS type of the answer (like 'IN') - * @param unicast If highest bit in class should be set, to instruct the responder to - * reply with a unicast packet - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_add_question(struct mdns_outpacket *outpkt, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t unicast) -{ - u16_t question_len; - u16_t field16; - err_t res; - - if (!outpkt->pbuf) { - /* If no pbuf is active, allocate one */ - outpkt->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM); - if (!outpkt->pbuf) { - return ERR_MEM; - } - outpkt->write_offset = SIZEOF_DNS_HDR; - } - - /* Worst case calculation. Domain string might be compressed */ - question_len = domain->length + sizeof(type) + sizeof(klass); - if (outpkt->write_offset + question_len > outpkt->pbuf->tot_len) { - /* No space */ - return ERR_MEM; - } - - /* Write name */ - res = mdns_write_domain(outpkt, domain); - if (res != ERR_OK) { - return res; - } - - /* Write type */ - field16 = lwip_htons(type); - res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset); - if (res != ERR_OK) { - return res; - } - outpkt->write_offset += sizeof(field16); - - /* Write class */ - if (unicast) { - klass |= 0x8000; - } - field16 = lwip_htons(klass); - res = pbuf_take_at(outpkt->pbuf, &field16, sizeof(field16), outpkt->write_offset); - if (res != ERR_OK) { - return res; - } - outpkt->write_offset += sizeof(field16); - - return ERR_OK; -} - -/** - * Write answer to reply packet. - * buf or answer_domain can be null. The rd_length written will be buf_length + - * size of (compressed) domain. Most uses will need either buf or answer_domain, - * special case is SRV that starts with 3 u16 and then a domain name. - * @param reply The outpacket to write to - * @param domain The domain name the answer is for - * @param type The DNS type of the answer (like 'AAAA', 'SRV') - * @param klass The DNS type of the answer (like 'IN') - * @param cache_flush If highest bit in class should be set, to instruct receiver that - * this reply replaces any earlier answer for this domain/type/class - * @param ttl Validity time in seconds to send out for IP address data in DNS replies - * @param buf Pointer to buffer of answer data - * @param buf_length Length of variable data - * @param answer_domain A domain to write after any buffer data as answer - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_add_answer(struct mdns_outpacket *reply, struct mdns_domain *domain, u16_t type, u16_t klass, u16_t cache_flush, - u32_t ttl, const u8_t *buf, size_t buf_length, struct mdns_domain *answer_domain) -{ - u16_t answer_len; - u16_t field16; - u16_t rdlen_offset; - u16_t answer_offset; - u32_t field32; - err_t res; - - if (!reply->pbuf) { - /* If no pbuf is active, allocate one */ - reply->pbuf = pbuf_alloc(PBUF_TRANSPORT, OUTPACKET_SIZE, PBUF_RAM); - if (!reply->pbuf) { - return ERR_MEM; - } - reply->write_offset = SIZEOF_DNS_HDR; - } - - /* Worst case calculation. Domain strings might be compressed */ - answer_len = domain->length + sizeof(type) + sizeof(klass) + sizeof(ttl) + sizeof(field16)/*rd_length*/; - if (buf) { - answer_len += (u16_t)buf_length; - } - if (answer_domain) { - answer_len += answer_domain->length; - } - if (reply->write_offset + answer_len > reply->pbuf->tot_len) { - /* No space */ - return ERR_MEM; - } - - /* Answer starts with same data as question, then more fields */ - mdns_add_question(reply, domain, type, klass, cache_flush); - - /* Write TTL */ - field32 = lwip_htonl(ttl); - res = pbuf_take_at(reply->pbuf, &field32, sizeof(field32), reply->write_offset); - if (res != ERR_OK) { - return res; - } - reply->write_offset += sizeof(field32); - - /* Store offsets and skip forward to the data */ - rdlen_offset = reply->write_offset; - reply->write_offset += sizeof(field16); - answer_offset = reply->write_offset; - - if (buf) { - /* Write static data */ - res = pbuf_take_at(reply->pbuf, buf, (u16_t)buf_length, reply->write_offset); - if (res != ERR_OK) { - return res; - } - reply->write_offset += (u16_t)buf_length; - } - - if (answer_domain) { - /* Write name answer (compressed if possible) */ - res = mdns_write_domain(reply, answer_domain); - if (res != ERR_OK) { - return res; - } - } - - /* Write rd_length after when we know the answer size */ - field16 = lwip_htons(reply->write_offset - answer_offset); - res = pbuf_take_at(reply->pbuf, &field16, sizeof(field16), rdlen_offset); - - return res; -} - -/** - * Helper function for mdns_read_question/mdns_read_answer - * Reads a domain, type and class from the packet - * @param pkt The MDNS packet to read from. The parse_offset field will be - * incremented to point to the next unparsed byte. - * @param info The struct to fill with domain, type and class - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_read_rr_info(struct mdns_packet *pkt, struct mdns_rr_info *info) -{ - u16_t field16, copied; - pkt->parse_offset = mdns_readname(pkt->pbuf, pkt->parse_offset, &info->domain); - if (pkt->parse_offset == MDNS_READNAME_ERROR) { - return ERR_VAL; - } - - copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); - if (copied != sizeof(field16)) { - return ERR_VAL; - } - pkt->parse_offset += copied; - info->type = lwip_ntohs(field16); - - copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); - if (copied != sizeof(field16)) { - return ERR_VAL; - } - pkt->parse_offset += copied; - info->klass = lwip_ntohs(field16); - - return ERR_OK; -} - -/** - * Read a question from the packet. - * All questions have to be read before the answers. - * @param pkt The MDNS packet to read from. The questions_left field will be decremented - * and the parse_offset will be updated. - * @param question The struct to fill with question data - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_read_question(struct mdns_packet *pkt, struct mdns_question *question) -{ - /* Safety check */ - if (pkt->pbuf->tot_len < pkt->parse_offset) { - return ERR_VAL; - } - - if (pkt->questions_left) { - err_t res; - pkt->questions_left--; - - memset(question, 0, sizeof(struct mdns_question)); - res = mdns_read_rr_info(pkt, &question->info); - if (res != ERR_OK) { - return res; - } - - /* Extract unicast flag from class field */ - question->unicast = question->info.klass & 0x8000; - question->info.klass &= 0x7FFF; - - return ERR_OK; - } - return ERR_VAL; -} - -/** - * Read an answer from the packet - * The variable length reply is not copied, its pbuf offset and length is stored instead. - * @param pkt The MDNS packet to read. The answers_left field will be decremented and - * the parse_offset will be updated. - * @param answer The struct to fill with answer data - * @return ERR_OK on success, an err_t otherwise - */ -static err_t -mdns_read_answer(struct mdns_packet *pkt, struct mdns_answer *answer) -{ - /* Read questions first */ - if (pkt->questions_left) { - return ERR_VAL; - } - - /* Safety check */ - if (pkt->pbuf->tot_len < pkt->parse_offset) { - return ERR_VAL; - } - - if (pkt->answers_left) { - u16_t copied, field16; - u32_t ttl; - err_t res; - pkt->answers_left--; - - memset(answer, 0, sizeof(struct mdns_answer)); - res = mdns_read_rr_info(pkt, &answer->info); - if (res != ERR_OK) { - return res; - } - - /* Extract cache_flush flag from class field */ - answer->cache_flush = answer->info.klass & 0x8000; - answer->info.klass &= 0x7FFF; - - copied = pbuf_copy_partial(pkt->pbuf, &ttl, sizeof(ttl), pkt->parse_offset); - if (copied != sizeof(ttl)) { - return ERR_VAL; - } - pkt->parse_offset += copied; - answer->ttl = lwip_ntohl(ttl); - - copied = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), pkt->parse_offset); - if (copied != sizeof(field16)) { - return ERR_VAL; - } - pkt->parse_offset += copied; - answer->rd_length = lwip_ntohs(field16); - - answer->rd_offset = pkt->parse_offset; - pkt->parse_offset += answer->rd_length; - - return ERR_OK; - } - return ERR_VAL; -} - -#if LWIP_IPV4 -/** Write an IPv4 address (A) RR to outpacket */ -static err_t -mdns_add_a_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif) -{ - struct mdns_domain host; - mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with A record\n")); - return mdns_add_answer(reply, &host, DNS_RRTYPE_A, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip4_addr(netif), sizeof(ip4_addr_t), NULL); -} - -/** Write a 4.3.2.1.in-addr.arpa -> hostname.local PTR RR to outpacket */ -static err_t -mdns_add_hostv4_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif) -{ - struct mdns_domain host, revhost; - mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); - mdns_build_reverse_v4_domain(&revhost, netif_ip4_addr(netif)); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v4 PTR record\n")); - return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host); -} -#endif - -#if LWIP_IPV6 -/** Write an IPv6 address (AAAA) RR to outpacket */ -static err_t -mdns_add_aaaa_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex) -{ - struct mdns_domain host; - mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with AAAA record\n")); - return mdns_add_answer(reply, &host, DNS_RRTYPE_AAAA, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, (const u8_t *) netif_ip6_addr(netif, addrindex), sizeof(ip6_addr_p_t), NULL); -} - -/** Write a x.y.z.ip6.arpa -> hostname.local PTR RR to outpacket */ -static err_t -mdns_add_hostv6_ptr_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct netif *netif, int addrindex) -{ - struct mdns_domain host, revhost; - mdns_build_host_domain(&host, NETIF_TO_HOST(netif)); - mdns_build_reverse_v6_domain(&revhost, netif_ip6_addr(netif, addrindex)); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with v6 PTR record\n")); - return mdns_add_answer(reply, &revhost, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, cache_flush, (NETIF_TO_HOST(netif))->dns_ttl, NULL, 0, &host); -} -#endif - -/** Write an all-services -> servicetype PTR RR to outpacket */ -static err_t -mdns_add_servicetype_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service) -{ - struct mdns_domain service_type, service_dnssd; - mdns_build_service_domain(&service_type, service, 0); - mdns_build_dnssd_domain(&service_dnssd); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service type PTR record\n")); - return mdns_add_answer(reply, &service_dnssd, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_type); -} - -/** Write a servicetype -> servicename PTR RR to outpacket */ -static err_t -mdns_add_servicename_ptr_answer(struct mdns_outpacket *reply, struct mdns_service *service) -{ - struct mdns_domain service_type, service_instance; - mdns_build_service_domain(&service_type, service, 0); - mdns_build_service_domain(&service_instance, service, 1); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with service name PTR record\n")); - return mdns_add_answer(reply, &service_type, DNS_RRTYPE_PTR, DNS_RRCLASS_IN, 0, service->dns_ttl, NULL, 0, &service_instance); -} - -/** Write a SRV RR to outpacket */ -static err_t -mdns_add_srv_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_host *mdns, struct mdns_service *service) -{ - struct mdns_domain service_instance, srvhost; - u16_t srvdata[3]; - mdns_build_service_domain(&service_instance, service, 1); - mdns_build_host_domain(&srvhost, mdns); - if (reply->legacy_query) { - /* RFC 6762 section 18.14: - * In legacy unicast responses generated to answer legacy queries, - * name compression MUST NOT be performed on SRV records. - */ - srvhost.skip_compression = 1; - } - srvdata[0] = lwip_htons(SRV_PRIORITY); - srvdata[1] = lwip_htons(SRV_WEIGHT); - srvdata[2] = lwip_htons(service->port); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with SRV record\n")); - return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_SRV, DNS_RRCLASS_IN, cache_flush, service->dns_ttl, - (const u8_t *) &srvdata, sizeof(srvdata), &srvhost); -} - -/** Write a TXT RR to outpacket */ -static err_t -mdns_add_txt_answer(struct mdns_outpacket *reply, u16_t cache_flush, struct mdns_service *service) -{ - struct mdns_domain service_instance; - mdns_build_service_domain(&service_instance, service, 1); - mdns_prepare_txtdata(service); - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Responding with TXT record\n")); - return mdns_add_answer(reply, &service_instance, DNS_RRTYPE_TXT, DNS_RRCLASS_IN, cache_flush, service->dns_ttl, - (u8_t *) &service->txtdata.name, service->txtdata.length, NULL); -} - -/** - * Setup outpacket as a reply to the incoming packet - */ -static void -mdns_init_outpacket(struct mdns_outpacket *out, struct mdns_packet *in) -{ - memset(out, 0, sizeof(struct mdns_outpacket)); - out->cache_flush = 1; - out->netif = in->netif; - - /* Copy source IP/port to use when responding unicast, or to choose - * which pcb to use for multicast (IPv4/IPv6) - */ - SMEMCPY(&out->dest_addr, &in->source_addr, sizeof(ip_addr_t)); - out->dest_port = in->source_port; - - if (in->source_port != LWIP_IANA_PORT_MDNS) { - out->unicast_reply = 1; - out->cache_flush = 0; - if (in->questions == 1) { - out->legacy_query = 1; - out->tx_id = in->tx_id; - } - } - - if (in->recv_unicast) { - out->unicast_reply = 1; - } -} - -/** - * Send chosen answers as a reply - * - * Add all selected answers (first write will allocate pbuf) - * Add additional answers based on the selected answers - * Send the packet - */ -static err_t -mdns_send_outpacket(struct mdns_outpacket *outpkt, u8_t flags) -{ - struct mdns_service *service; - err_t res = ERR_ARG; - int i; - struct mdns_host *mdns = NETIF_TO_HOST(outpkt->netif); - u16_t answers = 0; - - /* Write answers to host questions */ -#if LWIP_IPV4 - if (outpkt->host_replies & REPLY_HOST_A) { - res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif); - if (res != ERR_OK) { - goto cleanup; - } - answers++; - } - if (outpkt->host_replies & REPLY_HOST_PTR_V4) { - res = mdns_add_hostv4_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif); - if (res != ERR_OK) { - goto cleanup; - } - answers++; - } -#endif -#if LWIP_IPV6 - if (outpkt->host_replies & REPLY_HOST_AAAA) { - int addrindex; - for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; addrindex++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) { - res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); - if (res != ERR_OK) { - goto cleanup; - } - answers++; - } - } - } - if (outpkt->host_replies & REPLY_HOST_PTR_V6) { - u8_t rev_addrs = outpkt->host_reverse_v6_replies; - int addrindex = 0; - while (rev_addrs) { - if (rev_addrs & 1) { - res = mdns_add_hostv6_ptr_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); - if (res != ERR_OK) { - goto cleanup; - } - answers++; - } - addrindex++; - rev_addrs >>= 1; - } - } -#endif - - /* Write answers to service questions */ - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - service = mdns->services[i]; - if (!service) { - continue; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_TYPE_PTR) { - res = mdns_add_servicetype_ptr_answer(outpkt, service); - if (res != ERR_OK) { - goto cleanup; - } - answers++; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) { - res = mdns_add_servicename_ptr_answer(outpkt, service); - if (res != ERR_OK) { - goto cleanup; - } - answers++; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_SRV) { - res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service); - if (res != ERR_OK) { - goto cleanup; - } - answers++; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_TXT) { - res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service); - if (res != ERR_OK) { - goto cleanup; - } - answers++; - } - } - - /* if this is a response, the data above is anwers, else this is a probe and the answers above goes into auth section */ - if (flags & DNS_FLAG1_RESPONSE) { - outpkt->answers += answers; - } else { - outpkt->authoritative += answers; - } - - /* All answers written, add additional RRs */ - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - service = mdns->services[i]; - if (!service) { - continue; - } - - if (outpkt->serv_replies[i] & REPLY_SERVICE_NAME_PTR) { - /* Our service instance requested, include SRV & TXT - * if they are already not requested. */ - if (!(outpkt->serv_replies[i] & REPLY_SERVICE_SRV)) { - res = mdns_add_srv_answer(outpkt, outpkt->cache_flush, mdns, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->additional++; - } - - if (!(outpkt->serv_replies[i] & REPLY_SERVICE_TXT)) { - res = mdns_add_txt_answer(outpkt, outpkt->cache_flush, service); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->additional++; - } - } - - /* If service instance, SRV, record or an IP address is requested, - * supply all addresses for the host - */ - if ((outpkt->serv_replies[i] & (REPLY_SERVICE_NAME_PTR | REPLY_SERVICE_SRV)) || - (outpkt->host_replies & (REPLY_HOST_A | REPLY_HOST_AAAA))) { -#if LWIP_IPV6 - if (!(outpkt->host_replies & REPLY_HOST_AAAA)) { - int addrindex; - for (addrindex = 0; addrindex < LWIP_IPV6_NUM_ADDRESSES; addrindex++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(outpkt->netif, addrindex))) { - res = mdns_add_aaaa_answer(outpkt, outpkt->cache_flush, outpkt->netif, addrindex); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->additional++; - } - } - } -#endif -#if LWIP_IPV4 - if (!(outpkt->host_replies & REPLY_HOST_A) && - !ip4_addr_isany_val(*netif_ip4_addr(outpkt->netif))) { - res = mdns_add_a_answer(outpkt, outpkt->cache_flush, outpkt->netif); - if (res != ERR_OK) { - goto cleanup; - } - outpkt->additional++; - } -#endif - } - } - - if (outpkt->pbuf) { - const ip_addr_t *mcast_destaddr; - struct dns_hdr hdr; - - /* Write header */ - memset(&hdr, 0, sizeof(hdr)); - hdr.flags1 = flags; - hdr.numquestions = lwip_htons(outpkt->questions); - hdr.numanswers = lwip_htons(outpkt->answers); - hdr.numauthrr = lwip_htons(outpkt->authoritative); - hdr.numextrarr = lwip_htons(outpkt->additional); - hdr.id = lwip_htons(outpkt->tx_id); - pbuf_take(outpkt->pbuf, &hdr, sizeof(hdr)); - - /* Shrink packet */ - pbuf_realloc(outpkt->pbuf, outpkt->write_offset); - - if (IP_IS_V6_VAL(outpkt->dest_addr)) { -#if LWIP_IPV6 - mcast_destaddr = &v6group; -#endif - } else { -#if LWIP_IPV4 - mcast_destaddr = &v4group; -#endif - } - /* Send created packet */ - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Sending packet, len=%d, unicast=%d\n", outpkt->write_offset, outpkt->unicast_reply)); - if (outpkt->unicast_reply) { - res = udp_sendto_if(mdns_pcb, outpkt->pbuf, &outpkt->dest_addr, outpkt->dest_port, outpkt->netif); - } else { - res = udp_sendto_if(mdns_pcb, outpkt->pbuf, mcast_destaddr, LWIP_IANA_PORT_MDNS, outpkt->netif); - } - } - -cleanup: - if (outpkt->pbuf) { - pbuf_free(outpkt->pbuf); - outpkt->pbuf = NULL; - } - return res; -} - -/** - * Send unsolicited answer containing all our known data - * @param netif The network interface to send on - * @param destination The target address to send to (usually multicast address) - */ -static void -mdns_announce(struct netif *netif, const ip_addr_t *destination) -{ - struct mdns_outpacket announce; - int i; - struct mdns_host *mdns = NETIF_TO_HOST(netif); - - memset(&announce, 0, sizeof(announce)); - announce.netif = netif; - announce.cache_flush = 1; -#if LWIP_IPV4 - if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { - announce.host_replies = REPLY_HOST_A | REPLY_HOST_PTR_V4; - } -#endif -#if LWIP_IPV6 - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { - announce.host_replies |= REPLY_HOST_AAAA | REPLY_HOST_PTR_V6; - announce.host_reverse_v6_replies |= (1 << i); - } - } -#endif - - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - struct mdns_service *serv = mdns->services[i]; - if (serv) { - announce.serv_replies[i] = REPLY_SERVICE_TYPE_PTR | REPLY_SERVICE_NAME_PTR | - REPLY_SERVICE_SRV | REPLY_SERVICE_TXT; - } - } - - announce.dest_port = LWIP_IANA_PORT_MDNS; - SMEMCPY(&announce.dest_addr, destination, sizeof(announce.dest_addr)); - mdns_send_outpacket(&announce, DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE); -} - -/** - * Handle question MDNS packet - * 1. Parse all questions and set bits what answers to send - * 2. Clear pending answers if known answers are supplied - * 3. Put chosen answers in new packet and send as reply - */ -static void -mdns_handle_question(struct mdns_packet *pkt) -{ - struct mdns_service *service; - struct mdns_outpacket reply; - int replies = 0; - int i; - err_t res; - struct mdns_host *mdns = NETIF_TO_HOST(pkt->netif); - - if (mdns->probing_state != MDNS_PROBING_COMPLETE) { - /* Don't answer questions until we've verified our domains via probing */ - /* @todo we should check incoming questions during probing for tiebreaking */ - return; - } - - mdns_init_outpacket(&reply, pkt); - - while (pkt->questions_left) { - struct mdns_question q; - - res = mdns_read_question(pkt, &q); - if (res != ERR_OK) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping query packet\n")); - return; - } - - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Query for domain ")); - mdns_domain_debug_print(&q.info.domain); - LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", q.info.type, q.info.klass)); - - if (q.unicast) { - /* Reply unicast if any question is unicast */ - reply.unicast_reply = 1; - } - - reply.host_replies |= check_host(pkt->netif, &q.info, &reply.host_reverse_v6_replies); - replies |= reply.host_replies; - - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - service = mdns->services[i]; - if (!service) { - continue; - } - reply.serv_replies[i] |= check_service(service, &q.info); - replies |= reply.serv_replies[i]; - } - - if (replies && reply.legacy_query) { - /* Add question to reply packet (legacy packet only has 1 question) */ - res = mdns_add_question(&reply, &q.info.domain, q.info.type, q.info.klass, 0); - reply.questions = 1; - if (res != ERR_OK) { - goto cleanup; - } - } - } - - /* Handle known answers */ - while (pkt->answers_left) { - struct mdns_answer ans; - u8_t rev_v6; - int match; - - res = mdns_read_answer(pkt, &ans); - if (res != ERR_OK) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping query packet\n")); - goto cleanup; - } - - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Known answer for domain ")); - mdns_domain_debug_print(&ans.info.domain); - LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass)); - - - if (ans.info.type == DNS_RRTYPE_ANY || ans.info.klass == DNS_RRCLASS_ANY) { - /* Skip known answers for ANY type & class */ - continue; - } - - rev_v6 = 0; - match = reply.host_replies & check_host(pkt->netif, &ans.info, &rev_v6); - if (match && (ans.ttl > (mdns->dns_ttl / 2))) { - /* The RR in the known answer matches an RR we are planning to send, - * and the TTL is less than half gone. - * If the payload matches we should not send that answer. - */ - if (ans.info.type == DNS_RRTYPE_PTR) { - /* Read domain and compare */ - struct mdns_domain known_ans, my_ans; - u16_t len; - len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans); - res = mdns_build_host_domain(&my_ans, mdns); - if (len != MDNS_READNAME_ERROR && res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { -#if LWIP_IPV4 - if (match & REPLY_HOST_PTR_V4) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v4 PTR\n")); - reply.host_replies &= ~REPLY_HOST_PTR_V4; - } -#endif -#if LWIP_IPV6 - if (match & REPLY_HOST_PTR_V6) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: v6 PTR\n")); - reply.host_reverse_v6_replies &= ~rev_v6; - if (reply.host_reverse_v6_replies == 0) { - reply.host_replies &= ~REPLY_HOST_PTR_V6; - } - } -#endif - } - } else if (match & REPLY_HOST_A) { -#if LWIP_IPV4 - if (ans.rd_length == sizeof(ip4_addr_t) && - pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip4_addr(pkt->netif), ans.rd_length) == 0) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: A\n")); - reply.host_replies &= ~REPLY_HOST_A; - } -#endif - } else if (match & REPLY_HOST_AAAA) { -#if LWIP_IPV6 - if (ans.rd_length == sizeof(ip6_addr_p_t) && - /* TODO this clears all AAAA responses if first addr is set as known */ - pbuf_memcmp(pkt->pbuf, ans.rd_offset, netif_ip6_addr(pkt->netif, 0), ans.rd_length) == 0) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: AAAA\n")); - reply.host_replies &= ~REPLY_HOST_AAAA; - } -#endif - } - } - - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - service = mdns->services[i]; - if (!service) { - continue; - } - match = reply.serv_replies[i] & check_service(service, &ans.info); - if (match && (ans.ttl > (service->dns_ttl / 2))) { - /* The RR in the known answer matches an RR we are planning to send, - * and the TTL is less than half gone. - * If the payload matches we should not send that answer. - */ - if (ans.info.type == DNS_RRTYPE_PTR) { - /* Read domain and compare */ - struct mdns_domain known_ans, my_ans; - u16_t len; - len = mdns_readname(pkt->pbuf, ans.rd_offset, &known_ans); - if (len != MDNS_READNAME_ERROR) { - if (match & REPLY_SERVICE_TYPE_PTR) { - res = mdns_build_service_domain(&my_ans, service, 0); - if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service type PTR\n")); - reply.serv_replies[i] &= ~REPLY_SERVICE_TYPE_PTR; - } - } - if (match & REPLY_SERVICE_NAME_PTR) { - res = mdns_build_service_domain(&my_ans, service, 1); - if (res == ERR_OK && mdns_domain_eq(&known_ans, &my_ans)) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: service name PTR\n")); - reply.serv_replies[i] &= ~REPLY_SERVICE_NAME_PTR; - } - } - } - } else if (match & REPLY_SERVICE_SRV) { - /* Read and compare to my SRV record */ - u16_t field16, len, read_pos; - struct mdns_domain known_ans, my_ans; - read_pos = ans.rd_offset; - do { - /* Check priority field */ - len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); - if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_PRIORITY) { - break; - } - read_pos += len; - /* Check weight field */ - len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); - if (len != sizeof(field16) || lwip_ntohs(field16) != SRV_WEIGHT) { - break; - } - read_pos += len; - /* Check port field */ - len = pbuf_copy_partial(pkt->pbuf, &field16, sizeof(field16), read_pos); - if (len != sizeof(field16) || lwip_ntohs(field16) != service->port) { - break; - } - read_pos += len; - /* Check host field */ - len = mdns_readname(pkt->pbuf, read_pos, &known_ans); - mdns_build_host_domain(&my_ans, mdns); - if (len == MDNS_READNAME_ERROR || !mdns_domain_eq(&known_ans, &my_ans)) { - break; - } - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: SRV\n")); - reply.serv_replies[i] &= ~REPLY_SERVICE_SRV; - } while (0); - } else if (match & REPLY_SERVICE_TXT) { - mdns_prepare_txtdata(service); - if (service->txtdata.length == ans.rd_length && - pbuf_memcmp(pkt->pbuf, ans.rd_offset, service->txtdata.name, ans.rd_length) == 0) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Skipping known answer: TXT\n")); - reply.serv_replies[i] &= ~REPLY_SERVICE_TXT; - } - } - } - } - } - - mdns_send_outpacket(&reply, DNS_FLAG1_RESPONSE | DNS_FLAG1_AUTHORATIVE); - -cleanup: - if (reply.pbuf) { - /* This should only happen if we fail to alloc/write question for legacy query */ - pbuf_free(reply.pbuf); - reply.pbuf = NULL; - } -} - -/** - * Handle response MDNS packet - * Only prints debug for now. Will need more code to do conflict resolution. - */ -static void -mdns_handle_response(struct mdns_packet *pkt) -{ - struct mdns_host* mdns = NETIF_TO_HOST(pkt->netif); - - /* Ignore all questions */ - while (pkt->questions_left) { - struct mdns_question q; - err_t res; - - res = mdns_read_question(pkt, &q); - if (res != ERR_OK) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse question, skipping response packet\n")); - return; - } - } - - while (pkt->answers_left) { - struct mdns_answer ans; - err_t res; - - res = mdns_read_answer(pkt, &ans); - if (res != ERR_OK) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Failed to parse answer, skipping response packet\n")); - return; - } - - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Answer for domain ")); - mdns_domain_debug_print(&ans.info.domain); - LWIP_DEBUGF(MDNS_DEBUG, (" type %d class %d\n", ans.info.type, ans.info.klass)); - - /*"Apparently conflicting Multicast DNS responses received *before* the first probe packet is sent MUST - be silently ignored" so drop answer if we haven't started probing yet*/ - if ((mdns->probing_state == MDNS_PROBING_ONGOING) && (mdns->probes_sent > 0)) { - struct mdns_domain domain; - u8_t i; - u8_t conflict = 0; - - res = mdns_build_host_domain(&domain, mdns); - if (res == ERR_OK && mdns_domain_eq(&ans.info.domain, &domain)) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Probe response matches host domain!")); - conflict = 1; - } - - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - struct mdns_service* service = mdns->services[i]; - if (!service) { - continue; - } - res = mdns_build_service_domain(&domain, service, 1); - if ((res == ERR_OK) && mdns_domain_eq(&ans.info.domain, &domain)) { - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Probe response matches service domain!")); - conflict = 1; - } - } - - if (conflict != 0) { - sys_untimeout(mdns_probe, pkt->netif); - if (mdns_name_result_cb != NULL) { - mdns_name_result_cb(pkt->netif, MDNS_PROBING_CONFLICT); - } - } - } - } -} - -/** - * Receive input function for MDNS packets. - * Handles both IPv4 and IPv6 UDP pcbs. - */ -static void -mdns_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - struct dns_hdr hdr; - struct mdns_packet packet; - struct netif *recv_netif = ip_current_input_netif(); - u16_t offset = 0; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(pcb); - - LWIP_DEBUGF(MDNS_DEBUG, ("MDNS: Received IPv%d MDNS packet, len %d\n", IP_IS_V6(addr) ? 6 : 4, p->tot_len)); - - if (NETIF_TO_HOST(recv_netif) == NULL) { - /* From netif not configured for MDNS */ - goto dealloc; - } - - if (pbuf_copy_partial(p, &hdr, SIZEOF_DNS_HDR, offset) < SIZEOF_DNS_HDR) { - /* Too small */ - goto dealloc; - } - offset += SIZEOF_DNS_HDR; - - if (DNS_HDR_GET_OPCODE(&hdr)) { - /* Ignore non-standard queries in multicast packets (RFC 6762, section 18.3) */ - goto dealloc; - } - - memset(&packet, 0, sizeof(packet)); - SMEMCPY(&packet.source_addr, addr, sizeof(packet.source_addr)); - packet.source_port = port; - packet.netif = recv_netif; - packet.pbuf = p; - packet.parse_offset = offset; - packet.tx_id = lwip_ntohs(hdr.id); - packet.questions = packet.questions_left = lwip_ntohs(hdr.numquestions); - packet.answers = packet.answers_left = lwip_ntohs(hdr.numanswers) + lwip_ntohs(hdr.numauthrr) + lwip_ntohs(hdr.numextrarr); - -#if LWIP_IPV6 - if (IP_IS_V6(ip_current_dest_addr())) { - /* instead of having one 'v6group' per netif, just compare zoneless here */ - if (!ip_addr_cmp_zoneless(ip_current_dest_addr(), &v6group)) { - packet.recv_unicast = 1; - } - } -#endif -#if LWIP_IPV4 - if (!IP_IS_V6(ip_current_dest_addr())) { - if (!ip_addr_cmp(ip_current_dest_addr(), &v4group)) { - packet.recv_unicast = 1; - } - } -#endif - - if (hdr.flags1 & DNS_FLAG1_RESPONSE) { - mdns_handle_response(&packet); - } else { - mdns_handle_question(&packet); - } - -dealloc: - pbuf_free(p); -} - -#if LWIP_NETIF_EXT_STATUS_CALLBACK && MDNS_RESP_USENETIF_EXTCALLBACK -static void -mdns_netif_ext_status_callback(struct netif *netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t *args) -{ - LWIP_UNUSED_ARG(args); - - /* MDNS enabled on netif? */ - if (NETIF_TO_HOST(netif) == NULL) { - return; - } - - if (reason & LWIP_NSC_STATUS_CHANGED) { - if (args->status_changed.state != 0) { - mdns_resp_restart(netif); - } - /* TODO: send goodbye message */ - } - if (reason & LWIP_NSC_LINK_CHANGED) { - if (args->link_changed.state != 0) { - mdns_resp_restart(netif); - } - } - if (reason & (LWIP_NSC_IPV4_ADDRESS_CHANGED | LWIP_NSC_IPV4_GATEWAY_CHANGED | - LWIP_NSC_IPV4_NETMASK_CHANGED | LWIP_NSC_IPV4_SETTINGS_CHANGED | - LWIP_NSC_IPV6_SET | LWIP_NSC_IPV6_ADDR_STATE_CHANGED)) { - mdns_resp_announce(netif); - } -} -#endif /* LWIP_NETIF_EXT_STATUS_CALLBACK && MDNS_RESP_USENETIF_EXTCALLBACK */ - -static err_t -mdns_send_probe(struct netif* netif, const ip_addr_t *destination) -{ - struct mdns_host* mdns; - struct mdns_outpacket pkt; - struct mdns_domain domain; - u8_t i; - err_t res; - - mdns = NETIF_TO_HOST(netif); - - memset(&pkt, 0, sizeof(pkt)); - pkt.netif = netif; - - /* Add unicast questions with rtype ANY for all our desired records */ - mdns_build_host_domain(&domain, mdns); - res = mdns_add_question(&pkt, &domain, DNS_RRTYPE_ANY, DNS_RRCLASS_IN, 1); - if (res != ERR_OK) { - goto cleanup; - } - pkt.questions++; - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - struct mdns_service* service = mdns->services[i]; - if (!service) { - continue; - } - mdns_build_service_domain(&domain, service, 1); - res = mdns_add_question(&pkt, &domain, DNS_RRTYPE_ANY, DNS_RRCLASS_IN, 1); - if (res != ERR_OK) { - goto cleanup; - } - pkt.questions++; - } - - /* Add answers to the questions above into the authority section for tiebreaking */ -#if LWIP_IPV4 - if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { - pkt.host_replies = REPLY_HOST_A; - } -#endif -#if LWIP_IPV6 - for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { - if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { - pkt.host_replies |= REPLY_HOST_AAAA; - } - } -#endif - - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - struct mdns_service *serv = mdns->services[i]; - if (serv) { - pkt.serv_replies[i] = REPLY_SERVICE_SRV | REPLY_SERVICE_TXT; - } - } - - pkt.tx_id = 0; - pkt.dest_port = LWIP_IANA_PORT_MDNS; - SMEMCPY(&pkt.dest_addr, destination, sizeof(pkt.dest_addr)); - res = mdns_send_outpacket(&pkt, 0); - -cleanup: - if (pkt.pbuf) { - pbuf_free(pkt.pbuf); - pkt.pbuf = NULL; - } - return res; -} - -/** - * Timer callback for probing network. - */ -static void -mdns_probe(void* arg) -{ - struct netif *netif = (struct netif *)arg; - struct mdns_host* mdns = NETIF_TO_HOST(netif); - - if(mdns->probes_sent >= MDNS_PROBE_COUNT) { - /* probing successful, announce the new name */ - mdns->probing_state = MDNS_PROBING_COMPLETE; - mdns_resp_announce(netif); - if (mdns_name_result_cb != NULL) { - mdns_name_result_cb(netif, MDNS_PROBING_SUCCESSFUL); - } - } else { -#if LWIP_IPV4 - /*if ipv4 wait with probing until address is set*/ - if (!ip4_addr_isany_val(*netif_ip4_addr(netif)) && - mdns_send_probe(netif, IP4_ADDR_ANY) == ERR_OK) -#endif - { -#if LWIP_IPV6 - if (mdns_send_probe(netif, IP6_ADDR_ANY) == ERR_OK) -#endif - { - mdns->probes_sent++; - } - } - sys_timeout(MDNS_PROBE_DELAY_MS, mdns_probe, netif); - } -} - -/** - * @ingroup mdns - * Activate MDNS responder for a network interface. - * @param netif The network interface to activate. - * @param hostname Name to use. Queries for <hostname>.local will be answered - * with the IP addresses of the netif. The hostname will be copied, the - * given pointer can be on the stack. - * @param dns_ttl Validity time in seconds to send out for IP address data in DNS replies - * @return ERR_OK if netif was added, an err_t otherwise - */ -err_t -mdns_resp_add_netif(struct netif *netif, const char *hostname, u32_t dns_ttl) -{ - err_t res; - struct mdns_host *mdns; - - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ERROR("mdns_resp_add_netif: netif != NULL", (netif != NULL), return ERR_VAL); - LWIP_ERROR("mdns_resp_add_netif: Hostname too long", (strlen(hostname) <= MDNS_LABEL_MAXLEN), return ERR_VAL); - - LWIP_ASSERT("mdns_resp_add_netif: Double add", NETIF_TO_HOST(netif) == NULL); - mdns = (struct mdns_host *) mem_calloc(1, sizeof(struct mdns_host)); - LWIP_ERROR("mdns_resp_add_netif: Alloc failed", (mdns != NULL), return ERR_MEM); - - netif_set_client_data(netif, mdns_netif_client_id, mdns); - - MEMCPY(&mdns->name, hostname, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(hostname))); - mdns->dns_ttl = dns_ttl; - mdns->probes_sent = 0; - mdns->probing_state = MDNS_PROBING_NOT_STARTED; - - /* Join multicast groups */ -#if LWIP_IPV4 - res = igmp_joingroup_netif(netif, ip_2_ip4(&v4group)); - if (res != ERR_OK) { - goto cleanup; - } -#endif -#if LWIP_IPV6 - res = mld6_joingroup_netif(netif, ip_2_ip6(&v6group)); - if (res != ERR_OK) { - goto cleanup; - } -#endif - - mdns_resp_restart(netif); - - return ERR_OK; - -cleanup: - mem_free(mdns); - netif_set_client_data(netif, mdns_netif_client_id, NULL); - return res; -} - -/** - * @ingroup mdns - * Stop responding to MDNS queries on this interface, leave multicast groups, - * and free the helper structure and any of its services. - * @param netif The network interface to remove. - * @return ERR_OK if netif was removed, an err_t otherwise - */ -err_t -mdns_resp_remove_netif(struct netif *netif) -{ - int i; - struct mdns_host *mdns; - - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("mdns_resp_remove_netif: Null pointer", netif); - mdns = NETIF_TO_HOST(netif); - LWIP_ERROR("mdns_resp_remove_netif: Not an active netif", (mdns != NULL), return ERR_VAL); - - if (mdns->probing_state == MDNS_PROBING_ONGOING) { - sys_untimeout(mdns_probe, netif); - } - - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - struct mdns_service *service = mdns->services[i]; - if (service) { - mem_free(service); - } - } - - /* Leave multicast groups */ -#if LWIP_IPV4 - igmp_leavegroup_netif(netif, ip_2_ip4(&v4group)); -#endif -#if LWIP_IPV6 - mld6_leavegroup_netif(netif, ip_2_ip6(&v6group)); -#endif - - mem_free(mdns); - netif_set_client_data(netif, mdns_netif_client_id, NULL); - return ERR_OK; -} - -/** - * @ingroup mdns - * Update MDNS hostname for a network interface. - * @param netif The network interface to activate. - * @param hostname Name to use. Queries for <hostname>.local will be answered - * with the IP addresses of the netif. The hostname will be copied, the - * given pointer can be on the stack. - * @return ERR_OK if name could be set on netif, an err_t otherwise - */ -err_t -mdns_resp_rename_netif(struct netif *netif, const char *hostname) -{ - struct mdns_host *mdns; - size_t len; - - LWIP_ASSERT_CORE_LOCKED(); - len = strlen(hostname); - LWIP_ERROR("mdns_resp_rename_netif: netif != NULL", (netif != NULL), return ERR_VAL); - LWIP_ERROR("mdns_resp_rename_netif: Hostname too long", (len <= MDNS_LABEL_MAXLEN), return ERR_VAL); - mdns = NETIF_TO_HOST(netif); - LWIP_ERROR("mdns_resp_rename_netif: Not an mdns netif", (mdns != NULL), return ERR_VAL); - - MEMCPY(&mdns->name, hostname, LWIP_MIN(MDNS_LABEL_MAXLEN, len)); - mdns->name[len] = '\0'; /* null termination in case new name is shorter than previous */ - - mdns_resp_restart(netif); - - return ERR_OK; -} - -/** - * @ingroup mdns - * Add a service to the selected network interface. - * @param netif The network interface to publish this service on - * @param name The name of the service - * @param service The service type, like "_http" - * @param proto The service protocol, DNSSD_PROTO_TCP for TCP ("_tcp") and DNSSD_PROTO_UDP - * for others ("_udp") - * @param port The port the service listens to - * @param dns_ttl Validity time in seconds to send out for service data in DNS replies - * @param txt_fn Callback to get TXT data. Will be called each time a TXT reply is created to - * allow dynamic replies. - * @param txt_data Userdata pointer for txt_fn - * @return service_id if the service was added to the netif, an err_t otherwise - */ -s8_t -mdns_resp_add_service(struct netif *netif, const char *name, const char *service, enum mdns_sd_proto proto, u16_t port, u32_t dns_ttl, service_get_txt_fn_t txt_fn, void *txt_data) -{ - s8_t i; - s8_t slot = -1; - struct mdns_service *srv; - struct mdns_host *mdns; - - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("mdns_resp_add_service: netif != NULL", netif); - mdns = NETIF_TO_HOST(netif); - LWIP_ERROR("mdns_resp_add_service: Not an mdns netif", (mdns != NULL), return ERR_VAL); - - LWIP_ERROR("mdns_resp_add_service: Name too long", (strlen(name) <= MDNS_LABEL_MAXLEN), return ERR_VAL); - LWIP_ERROR("mdns_resp_add_service: Service too long", (strlen(service) <= MDNS_LABEL_MAXLEN), return ERR_VAL); - LWIP_ERROR("mdns_resp_add_service: Bad proto (need TCP or UDP)", (proto == DNSSD_PROTO_TCP || proto == DNSSD_PROTO_UDP), return ERR_VAL); - - for (i = 0; i < MDNS_MAX_SERVICES; i++) { - if (mdns->services[i] == NULL) { - slot = i; - break; - } - } - LWIP_ERROR("mdns_resp_add_service: Service list full (increase MDNS_MAX_SERVICES)", (slot >= 0), return ERR_MEM); - - srv = (struct mdns_service *)mem_calloc(1, sizeof(struct mdns_service)); - LWIP_ERROR("mdns_resp_add_service: Alloc failed", (srv != NULL), return ERR_MEM); - - MEMCPY(&srv->name, name, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(name))); - MEMCPY(&srv->service, service, LWIP_MIN(MDNS_LABEL_MAXLEN, strlen(service))); - srv->txt_fn = txt_fn; - srv->txt_userdata = txt_data; - srv->proto = (u16_t)proto; - srv->port = port; - srv->dns_ttl = dns_ttl; - - mdns->services[slot] = srv; - - mdns_resp_restart(netif); - - return slot; -} - -/** - * @ingroup mdns - * Delete a service on the selected network interface. - * @param netif The network interface on which service should be removed - * @param slot The service slot number returned by mdns_resp_add_service - * @return ERR_OK if the service was removed from the netif, an err_t otherwise - */ -err_t -mdns_resp_del_service(struct netif *netif, s8_t slot) -{ - struct mdns_host *mdns; - struct mdns_service *srv; - LWIP_ASSERT("mdns_resp_del_service: netif != NULL", netif); - mdns = NETIF_TO_HOST(netif); - LWIP_ERROR("mdns_resp_del_service: Not an mdns netif", (mdns != NULL), return ERR_VAL); - LWIP_ERROR("mdns_resp_del_service: Invalid Service ID", (slot >= 0) && (slot < MDNS_MAX_SERVICES), return ERR_VAL); - LWIP_ERROR("mdns_resp_del_service: Invalid Service ID", (mdns->services[slot] != NULL), return ERR_VAL); - - srv = mdns->services[slot]; - mdns->services[slot] = NULL; - mem_free(srv); - return ERR_OK; -} - -/** - * @ingroup mdns - * Update name for an MDNS service. - * @param netif The network interface to activate. - * @param slot The service slot number returned by mdns_resp_add_service - * @param name The new name for the service - * @return ERR_OK if name could be set on service, an err_t otherwise - */ -err_t -mdns_resp_rename_service(struct netif *netif, s8_t slot, const char *name) -{ - struct mdns_service *srv; - struct mdns_host *mdns; - size_t len; - - LWIP_ASSERT_CORE_LOCKED(); - len = strlen(name); - LWIP_ASSERT("mdns_resp_rename_service: netif != NULL", netif); - mdns = NETIF_TO_HOST(netif); - LWIP_ERROR("mdns_resp_rename_service: Not an mdns netif", (mdns != NULL), return ERR_VAL); - LWIP_ERROR("mdns_resp_rename_service: Name too long", (len <= MDNS_LABEL_MAXLEN), return ERR_VAL); - LWIP_ERROR("mdns_resp_rename_service: Invalid Service ID", (slot >= 0) && (slot < MDNS_MAX_SERVICES), return ERR_VAL); - LWIP_ERROR("mdns_resp_rename_service: Invalid Service ID", (mdns->services[slot] != NULL), return ERR_VAL); - - srv = mdns->services[slot]; - - MEMCPY(&srv->name, name, LWIP_MIN(MDNS_LABEL_MAXLEN, len)); - srv->name[len] = '\0'; /* null termination in case new name is shorter than previous */ - - mdns_resp_restart(netif); - - return ERR_OK; -} - -/** - * @ingroup mdns - * Call this function from inside the service_get_txt_fn_t callback to add text data. - * Buffer for TXT data is 256 bytes, and each field is prefixed with a length byte. - * @param service The service provided to the get_txt callback - * @param txt String to add to the TXT field. - * @param txt_len Length of string - * @return ERR_OK if the string was added to the reply, an err_t otherwise - */ -err_t -mdns_resp_add_service_txtitem(struct mdns_service *service, const char *txt, u8_t txt_len) -{ - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("mdns_resp_add_service_txtitem: service != NULL", service); - - /* Use a mdns_domain struct to store txt chunks since it is the same encoding */ - return mdns_domain_add_label(&service->txtdata, txt, txt_len); -} - -/** - * @ingroup mdns - * Send unsolicited answer containing all our known data - * @param netif The network interface to send on - */ -void -mdns_resp_announce(struct netif *netif) -{ - struct mdns_host* mdns; - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ERROR("mdns_resp_announce: netif != NULL", (netif != NULL), return); - - mdns = NETIF_TO_HOST(netif); - if (mdns == NULL) { - return; - } - - if (mdns->probing_state == MDNS_PROBING_COMPLETE) { - /* Announce on IPv6 and IPv4 */ -#if LWIP_IPV6 - mdns_announce(netif, IP6_ADDR_ANY); -#endif -#if LWIP_IPV4 - if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { - mdns_announce(netif, IP4_ADDR_ANY); - } -#endif - } /* else: ip address changed while probing was ongoing? @todo reset counter to restart? */ -} - -/** Register a callback function that is called if probing is completed successfully - * or with a conflict. */ -void -mdns_resp_register_name_result_cb(mdns_name_result_cb_t cb) -{ - mdns_name_result_cb = cb; -} - -/** - * @ingroup mdns - * Restart mdns responder. Call this when cable is connected after being disconnected or - * administrative interface is set up after being down - * @param netif The network interface to send on - */ -void -mdns_resp_restart(struct netif *netif) -{ - struct mdns_host* mdns; - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ERROR("mdns_resp_restart: netif != NULL", (netif != NULL), return); - - mdns = NETIF_TO_HOST(netif); - if (mdns == NULL) { - return; - } - - if (mdns->probing_state == MDNS_PROBING_ONGOING) { - sys_untimeout(mdns_probe, netif); - } - /* @todo if we've failed 15 times within a 10 second period we MUST wait 5 seconds (or wait 5 seconds every time except first)*/ - mdns->probes_sent = 0; - mdns->probing_state = MDNS_PROBING_ONGOING; - sys_timeout(MDNS_INITIAL_PROBE_DELAY_MS, mdns_probe, netif); -} - -/** - * @ingroup mdns - * Initiate MDNS responder. Will open UDP sockets on port 5353 - */ -void -mdns_resp_init(void) -{ - err_t res; - - /* LWIP_ASSERT_CORE_LOCKED(); is checked by udp_new() */ - - mdns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ASSERT("Failed to allocate pcb", mdns_pcb != NULL); -#if LWIP_MULTICAST_TX_OPTIONS - udp_set_multicast_ttl(mdns_pcb, MDNS_TTL); -#else - mdns_pcb->ttl = MDNS_TTL; -#endif - res = udp_bind(mdns_pcb, IP_ANY_TYPE, LWIP_IANA_PORT_MDNS); - LWIP_UNUSED_ARG(res); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("Failed to bind pcb", res == ERR_OK); - udp_recv(mdns_pcb, mdns_recv, NULL); - - mdns_netif_client_id = netif_alloc_client_data_id(); - -#if MDNS_RESP_USENETIF_EXTCALLBACK - /* register for netif events when started on first netif */ - netif_add_ext_callback(&netif_callback, mdns_netif_ext_status_callback); -#endif -} - -#endif /* LWIP_MDNS_RESPONDER */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/mqtt/mqtt.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/mqtt/mqtt.c deleted file mode 100644 index 269f4a490..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/mqtt/mqtt.c +++ /dev/null @@ -1,1463 +0,0 @@ -/** - * @file - * MQTT client - * - * @defgroup mqtt MQTT client - * @ingroup apps - * @verbinclude mqtt_client.txt - */ - -/* - * Copyright (c) 2016 Erik Andersson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack - * - * Author: Erik Andersson - * - * - * @todo: - * - Handle large outgoing payloads for PUBLISH messages - * - Fix restriction of a single topic in each (UN)SUBSCRIBE message (protocol has support for multiple topics) - * - Add support for legacy MQTT protocol version - * - * Please coordinate changes and requests with Erik Andersson - * Erik Andersson - * - */ -#include "lwip/apps/mqtt.h" -#include "lwip/apps/mqtt_priv.h" -#include "lwip/timeouts.h" -#include "lwip/ip_addr.h" -#include "lwip/mem.h" -#include "lwip/err.h" -#include "lwip/pbuf.h" -#include "lwip/altcp.h" -#include "lwip/altcp_tcp.h" -#include "lwip/altcp_tls.h" -#include - -#if LWIP_TCP && LWIP_CALLBACK_API - -/** - * MQTT_DEBUG: Default is off. - */ -#if !defined MQTT_DEBUG || defined __DOXYGEN__ -#define MQTT_DEBUG LWIP_DBG_OFF -#endif - -#define MQTT_DEBUG_TRACE (MQTT_DEBUG | LWIP_DBG_TRACE) -#define MQTT_DEBUG_STATE (MQTT_DEBUG | LWIP_DBG_STATE) -#define MQTT_DEBUG_WARN (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define MQTT_DEBUG_WARN_STATE (MQTT_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) -#define MQTT_DEBUG_SERIOUS (MQTT_DEBUG | LWIP_DBG_LEVEL_SERIOUS) - - - -/** - * MQTT client connection states - */ -enum { - TCP_DISCONNECTED, - TCP_CONNECTING, - MQTT_CONNECTING, - MQTT_CONNECTED -}; - -/** - * MQTT control message types - */ -enum mqtt_message_type { - MQTT_MSG_TYPE_CONNECT = 1, - MQTT_MSG_TYPE_CONNACK = 2, - MQTT_MSG_TYPE_PUBLISH = 3, - MQTT_MSG_TYPE_PUBACK = 4, - MQTT_MSG_TYPE_PUBREC = 5, - MQTT_MSG_TYPE_PUBREL = 6, - MQTT_MSG_TYPE_PUBCOMP = 7, - MQTT_MSG_TYPE_SUBSCRIBE = 8, - MQTT_MSG_TYPE_SUBACK = 9, - MQTT_MSG_TYPE_UNSUBSCRIBE = 10, - MQTT_MSG_TYPE_UNSUBACK = 11, - MQTT_MSG_TYPE_PINGREQ = 12, - MQTT_MSG_TYPE_PINGRESP = 13, - MQTT_MSG_TYPE_DISCONNECT = 14 -}; - -/** Helpers to extract control packet type and qos from first byte in fixed header */ -#define MQTT_CTL_PACKET_TYPE(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0xf0) >> 4) -#define MQTT_CTL_PACKET_QOS(fixed_hdr_byte0) ((fixed_hdr_byte0 & 0x6) >> 1) - -/** - * MQTT connect flags, only used in CONNECT message - */ -enum mqtt_connect_flag { - MQTT_CONNECT_FLAG_USERNAME = 1 << 7, - MQTT_CONNECT_FLAG_PASSWORD = 1 << 6, - MQTT_CONNECT_FLAG_WILL_RETAIN = 1 << 5, - MQTT_CONNECT_FLAG_WILL = 1 << 2, - MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1 -}; - - -static void mqtt_cyclic_timer(void *arg); - -#if defined(LWIP_DEBUG) -static const char *const mqtt_message_type_str[15] = { - "UNDEFINED", - "CONNECT", - "CONNACK", - "PUBLISH", - "PUBACK", - "PUBREC", - "PUBREL", - "PUBCOMP", - "SUBSCRIBE", - "SUBACK", - "UNSUBSCRIBE", - "UNSUBACK", - "PINGREQ", - "PINGRESP", - "DISCONNECT" -}; - -/** - * Message type value to string - * @param msg_type see enum mqtt_message_type - * - * @return Control message type text string - */ -static const char * -mqtt_msg_type_to_str(u8_t msg_type) -{ - if (msg_type >= LWIP_ARRAYSIZE(mqtt_message_type_str)) { - msg_type = 0; - } - return mqtt_message_type_str[msg_type]; -} - -#endif - - -/** - * Generate MQTT packet identifier - * @param client MQTT client - * @return New packet identifier, range 1 to 65535 - */ -static u16_t -msg_generate_packet_id(mqtt_client_t *client) -{ - client->pkt_id_seq++; - if (client->pkt_id_seq == 0) { - client->pkt_id_seq++; - } - return client->pkt_id_seq; -} - -/*--------------------------------------------------------------------------------------------------------------------- */ -/* Output ring buffer */ - -/** Add single item to ring buffer */ -static void -mqtt_ringbuf_put(struct mqtt_ringbuf_t *rb, u8_t item) -{ - rb->buf[rb->put] = item; - rb->put++; - if (rb->put >= MQTT_OUTPUT_RINGBUF_SIZE) { - rb->put = 0; - } -} - -/** Return pointer to ring buffer get position */ -static u8_t * -mqtt_ringbuf_get_ptr(struct mqtt_ringbuf_t *rb) -{ - return &rb->buf[rb->get]; -} - -static void -mqtt_ringbuf_advance_get_idx(struct mqtt_ringbuf_t *rb, u16_t len) -{ - LWIP_ASSERT("mqtt_ringbuf_advance_get_idx: len < MQTT_OUTPUT_RINGBUF_SIZE", len < MQTT_OUTPUT_RINGBUF_SIZE); - - rb->get += len; - if (rb->get >= MQTT_OUTPUT_RINGBUF_SIZE) { - rb->get = rb->get - MQTT_OUTPUT_RINGBUF_SIZE; - } -} - -/** Return number of bytes in ring buffer */ -static u16_t -mqtt_ringbuf_len(struct mqtt_ringbuf_t *rb) -{ - u32_t len = rb->put - rb->get; - if (len > 0xFFFF) { - len += MQTT_OUTPUT_RINGBUF_SIZE; - } - return (u16_t)len; -} - -/** Return number of bytes free in ring buffer */ -#define mqtt_ringbuf_free(rb) (MQTT_OUTPUT_RINGBUF_SIZE - mqtt_ringbuf_len(rb)) - -/** Return number of bytes possible to read without wrapping around */ -#define mqtt_ringbuf_linear_read_length(rb) LWIP_MIN(mqtt_ringbuf_len(rb), (MQTT_OUTPUT_RINGBUF_SIZE - (rb)->get)) - -/** - * Try send as many bytes as possible from output ring buffer - * @param rb Output ring buffer - * @param tpcb TCP connection handle - */ -static void -mqtt_output_send(struct mqtt_ringbuf_t *rb, struct altcp_pcb *tpcb) -{ - err_t err; - u8_t wrap = 0; - u16_t ringbuf_lin_len = mqtt_ringbuf_linear_read_length(rb); - u16_t send_len = altcp_sndbuf(tpcb); - LWIP_ASSERT("mqtt_output_send: tpcb != NULL", tpcb != NULL); - - if (send_len == 0 || ringbuf_lin_len == 0) { - return; - } - - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_output_send: tcp_sndbuf: %d bytes, ringbuf_linear_available: %d, get %d, put %d\n", - send_len, ringbuf_lin_len, rb->get, rb->put)); - - if (send_len > ringbuf_lin_len) { - /* Space in TCP output buffer is larger than available in ring buffer linear portion */ - send_len = ringbuf_lin_len; - /* Wrap around if more data in ring buffer after linear portion */ - wrap = (mqtt_ringbuf_len(rb) > ringbuf_lin_len); - } - err = altcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY | (wrap ? TCP_WRITE_FLAG_MORE : 0)); - if ((err == ERR_OK) && wrap) { - mqtt_ringbuf_advance_get_idx(rb, send_len); - /* Use the lesser one of ring buffer linear length and TCP send buffer size */ - send_len = LWIP_MIN(altcp_sndbuf(tpcb), mqtt_ringbuf_linear_read_length(rb)); - err = altcp_write(tpcb, mqtt_ringbuf_get_ptr(rb), send_len, TCP_WRITE_FLAG_COPY); - } - - if (err == ERR_OK) { - mqtt_ringbuf_advance_get_idx(rb, send_len); - /* Flush */ - altcp_output(tpcb); - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_output_send: Send failed with err %d (\"%s\")\n", err, lwip_strerr(err))); - } -} - - - -/*--------------------------------------------------------------------------------------------------------------------- */ -/* Request queue */ - -/** - * Create request item - * @param r_objs Pointer to request objects - * @param r_objs_len Number of array entries - * @param pkt_id Packet identifier of request - * @param cb Packet callback to call when requests lifetime ends - * @param arg Parameter following callback - * @return Request or NULL if failed to create - */ -static struct mqtt_request_t * -mqtt_create_request(struct mqtt_request_t *r_objs, size_t r_objs_len, u16_t pkt_id, mqtt_request_cb_t cb, void *arg) -{ - struct mqtt_request_t *r = NULL; - u8_t n; - LWIP_ASSERT("mqtt_create_request: r_objs != NULL", r_objs != NULL); - for (n = 0; n < r_objs_len; n++) { - /* Item point to itself if not in use */ - if (r_objs[n].next == &r_objs[n]) { - r = &r_objs[n]; - r->next = NULL; - r->cb = cb; - r->arg = arg; - r->pkt_id = pkt_id; - break; - } - } - return r; -} - - -/** - * Append request to pending request queue - * @param tail Pointer to request queue tail pointer - * @param r Request to append - */ -static void -mqtt_append_request(struct mqtt_request_t **tail, struct mqtt_request_t *r) -{ - struct mqtt_request_t *head = NULL; - s16_t time_before = 0; - struct mqtt_request_t *iter; - - LWIP_ASSERT("mqtt_append_request: tail != NULL", tail != NULL); - - /* Iterate trough queue to find head, and count total timeout time */ - for (iter = *tail; iter != NULL; iter = iter->next) { - time_before += iter->timeout_diff; - head = iter; - } - - LWIP_ASSERT("mqtt_append_request: time_before <= MQTT_REQ_TIMEOUT", time_before <= MQTT_REQ_TIMEOUT); - r->timeout_diff = MQTT_REQ_TIMEOUT - time_before; - if (head == NULL) { - *tail = r; - } else { - head->next = r; - } -} - - -/** - * Delete request item - * @param r Request item to delete - */ -static void -mqtt_delete_request(struct mqtt_request_t *r) -{ - if (r != NULL) { - r->next = r; - } -} - -/** - * Remove a request item with a specific packet identifier from request queue - * @param tail Pointer to request queue tail pointer - * @param pkt_id Packet identifier of request to take - * @return Request item if found, NULL if not - */ -static struct mqtt_request_t * -mqtt_take_request(struct mqtt_request_t **tail, u16_t pkt_id) -{ - struct mqtt_request_t *iter = NULL, *prev = NULL; - LWIP_ASSERT("mqtt_take_request: tail != NULL", tail != NULL); - /* Search all request for pkt_id */ - for (iter = *tail; iter != NULL; iter = iter->next) { - if (iter->pkt_id == pkt_id) { - break; - } - prev = iter; - } - - /* If request was found */ - if (iter != NULL) { - /* unchain */ - if (prev == NULL) { - *tail = iter->next; - } else { - prev->next = iter->next; - } - /* If exists, add remaining timeout time for the request to next */ - if (iter->next != NULL) { - iter->next->timeout_diff += iter->timeout_diff; - } - iter->next = NULL; - } - return iter; -} - -/** - * Handle requests timeout - * @param tail Pointer to request queue tail pointer - * @param t Time since last call in seconds - */ -static void -mqtt_request_time_elapsed(struct mqtt_request_t **tail, u8_t t) -{ - struct mqtt_request_t *r; - LWIP_ASSERT("mqtt_request_time_elapsed: tail != NULL", tail != NULL); - r = *tail; - while (t > 0 && r != NULL) { - if (t >= r->timeout_diff) { - t -= (u8_t)r->timeout_diff; - /* Unchain */ - *tail = r->next; - /* Notify upper layer about timeout */ - if (r->cb != NULL) { - r->cb(r->arg, ERR_TIMEOUT); - } - mqtt_delete_request(r); - /* Tail might be be modified in callback, so re-read it in every iteration */ - r = *(struct mqtt_request_t *const volatile *)tail; - } else { - r->timeout_diff -= t; - t = 0; - } - } -} - -/** - * Free all request items - * @param tail Pointer to request queue tail pointer - */ -static void -mqtt_clear_requests(struct mqtt_request_t **tail) -{ - struct mqtt_request_t *iter, *next; - LWIP_ASSERT("mqtt_clear_requests: tail != NULL", tail != NULL); - for (iter = *tail; iter != NULL; iter = next) { - next = iter->next; - mqtt_delete_request(iter); - } - *tail = NULL; -} -/** - * Initialize all request items - * @param r_objs Pointer to request objects - * @param r_objs_len Number of array entries - */ -static void -mqtt_init_requests(struct mqtt_request_t *r_objs, size_t r_objs_len) -{ - u8_t n; - LWIP_ASSERT("mqtt_init_requests: r_objs != NULL", r_objs != NULL); - for (n = 0; n < r_objs_len; n++) { - /* Item pointing to itself indicates unused */ - r_objs[n].next = &r_objs[n]; - } -} - -/*--------------------------------------------------------------------------------------------------------------------- */ -/* Output message build helpers */ - - -static void -mqtt_output_append_u8(struct mqtt_ringbuf_t *rb, u8_t value) -{ - mqtt_ringbuf_put(rb, value); -} - -static -void mqtt_output_append_u16(struct mqtt_ringbuf_t *rb, u16_t value) -{ - mqtt_ringbuf_put(rb, value >> 8); - mqtt_ringbuf_put(rb, value & 0xff); -} - -static void -mqtt_output_append_buf(struct mqtt_ringbuf_t *rb, const void *data, u16_t length) -{ - u16_t n; - for (n = 0; n < length; n++) { - mqtt_ringbuf_put(rb, ((const u8_t *)data)[n]); - } -} - -static void -mqtt_output_append_string(struct mqtt_ringbuf_t *rb, const char *str, u16_t length) -{ - u16_t n; - mqtt_ringbuf_put(rb, length >> 8); - mqtt_ringbuf_put(rb, length & 0xff); - for (n = 0; n < length; n++) { - mqtt_ringbuf_put(rb, str[n]); - } -} - -/** - * Append fixed header - * @param rb Output ring buffer - * @param msg_type see enum mqtt_message_type - * @param fdup MQTT DUP flag - * @param fqos MQTT QoS field - * @param fretain MQTT retain flag - * @param r_length Remaining length after fixed header - */ - -static void -mqtt_output_append_fixed_header(struct mqtt_ringbuf_t *rb, u8_t msg_type, u8_t fdup, - u8_t fqos, u8_t fretain, u16_t r_length) -{ - /* Start with control byte */ - mqtt_output_append_u8(rb, (((msg_type & 0x0f) << 4) | ((fdup & 1) << 3) | ((fqos & 3) << 1) | (fretain & 1))); - /* Encode remaining length field */ - do { - mqtt_output_append_u8(rb, (r_length & 0x7f) | (r_length >= 128 ? 0x80 : 0)); - r_length >>= 7; - } while (r_length > 0); -} - - -/** - * Check output buffer space - * @param rb Output ring buffer - * @param r_length Remaining length after fixed header - * @return 1 if message will fit, 0 if not enough buffer space - */ -static u8_t -mqtt_output_check_space(struct mqtt_ringbuf_t *rb, u16_t r_length) -{ - /* Start with length of type byte + remaining length */ - u16_t total_len = 1 + r_length; - - LWIP_ASSERT("mqtt_output_check_space: rb != NULL", rb != NULL); - - /* Calculate number of required bytes to contain the remaining bytes field and add to total*/ - do { - total_len++; - r_length >>= 7; - } while (r_length > 0); - - return (total_len <= mqtt_ringbuf_free(rb)); -} - - -/** - * Close connection to server - * @param client MQTT client - * @param reason Reason for disconnection - */ -static void -mqtt_close(mqtt_client_t *client, mqtt_connection_status_t reason) -{ - LWIP_ASSERT("mqtt_close: client != NULL", client != NULL); - - /* Bring down TCP connection if not already done */ - if (client->conn != NULL) { - err_t res; - altcp_recv(client->conn, NULL); - altcp_err(client->conn, NULL); - altcp_sent(client->conn, NULL); - res = altcp_close(client->conn); - if (res != ERR_OK) { - altcp_abort(client->conn); - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_close: Close err=%s\n", lwip_strerr(res))); - } - client->conn = NULL; - } - - /* Remove all pending requests */ - mqtt_clear_requests(&client->pend_req_queue); - /* Stop cyclic timer */ - sys_untimeout(mqtt_cyclic_timer, client); - - /* Notify upper layer of disconnection if changed state */ - if (client->conn_state != TCP_DISCONNECTED) { - - client->conn_state = TCP_DISCONNECTED; - if (client->connect_cb != NULL) { - client->connect_cb(client, client->connect_arg, reason); - } - } -} - - -/** - * Interval timer, called every MQTT_CYCLIC_TIMER_INTERVAL seconds in MQTT_CONNECTING and MQTT_CONNECTED states - * @param arg MQTT client - */ -static void -mqtt_cyclic_timer(void *arg) -{ - u8_t restart_timer = 1; - mqtt_client_t *client = (mqtt_client_t *)arg; - LWIP_ASSERT("mqtt_cyclic_timer: client != NULL", client != NULL); - - if (client->conn_state == MQTT_CONNECTING) { - client->cyclic_tick++; - if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= MQTT_CONNECT_TIMOUT) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_cyclic_timer: CONNECT attempt to server timed out\n")); - /* Disconnect TCP */ - mqtt_close(client, MQTT_CONNECT_TIMEOUT); - restart_timer = 0; - } - } else if (client->conn_state == MQTT_CONNECTED) { - /* Handle timeout for pending requests */ - mqtt_request_time_elapsed(&client->pend_req_queue, MQTT_CYCLIC_TIMER_INTERVAL); - - /* keep_alive > 0 means keep alive functionality shall be used */ - if (client->keep_alive > 0) { - - client->server_watchdog++; - /* If reception from server has been idle for 1.5*keep_alive time, server is considered unresponsive */ - if ((client->server_watchdog * MQTT_CYCLIC_TIMER_INTERVAL) > (client->keep_alive + client->keep_alive / 2)) { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_cyclic_timer: Server incoming keep-alive timeout\n")); - mqtt_close(client, MQTT_CONNECT_TIMEOUT); - restart_timer = 0; - } - - /* If time for a keep alive message to be sent, transmission has been idle for keep_alive time */ - if ((client->cyclic_tick * MQTT_CYCLIC_TIMER_INTERVAL) >= client->keep_alive) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_cyclic_timer: Sending keep-alive message to server\n")); - if (mqtt_output_check_space(&client->output, 0) != 0) { - mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0, 0); - client->cyclic_tick = 0; - } - } else { - client->cyclic_tick++; - } - } - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_cyclic_timer: Timer should not be running in state %d\n", client->conn_state)); - restart_timer = 0; - } - if (restart_timer) { - sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL * 1000, mqtt_cyclic_timer, arg); - } -} - - -/** - * Send PUBACK, PUBREC or PUBREL response message - * @param client MQTT client - * @param msg PUBACK, PUBREC or PUBREL - * @param pkt_id Packet identifier - * @param qos QoS value - * @return ERR_OK if successful, ERR_MEM if out of memory - */ -static err_t -pub_ack_rec_rel_response(mqtt_client_t *client, u8_t msg, u16_t pkt_id, u8_t qos) -{ - err_t err = ERR_OK; - if (mqtt_output_check_space(&client->output, 2)) { - mqtt_output_append_fixed_header(&client->output, msg, 0, qos, 0, 2); - mqtt_output_append_u16(&client->output, pkt_id); - mqtt_output_send(&client->output, client->conn); - } else { - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("pub_ack_rec_rel_response: OOM creating response: %s with pkt_id: %d\n", - mqtt_msg_type_to_str(msg), pkt_id)); - err = ERR_MEM; - } - return err; -} - -/** - * Subscribe response from server - * @param r Matching request - * @param result Result code from server - */ -static void -mqtt_incomming_suback(struct mqtt_request_t *r, u8_t result) -{ - if (r->cb != NULL) { - r->cb(r->arg, result < 3 ? ERR_OK : ERR_ABRT); - } -} - - -/** - * Complete MQTT message received or buffer full - * @param client MQTT client - * @param fixed_hdr_idx header index - * @param length length received part - * @param remaining_length Remaining length of complete message - */ -static mqtt_connection_status_t -mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_idx, u16_t length, u32_t remaining_length) -{ - mqtt_connection_status_t res = MQTT_CONNECT_ACCEPTED; - - u8_t *var_hdr_payload = client->rx_buffer + fixed_hdr_idx; - size_t var_hdr_payload_bufsize = sizeof(client->rx_buffer) - fixed_hdr_idx; - - /* Control packet type */ - u8_t pkt_type = MQTT_CTL_PACKET_TYPE(client->rx_buffer[0]); - u16_t pkt_id = 0; - - LWIP_ASSERT("client->msg_idx < MQTT_VAR_HEADER_BUFFER_LEN", client->msg_idx < MQTT_VAR_HEADER_BUFFER_LEN); - LWIP_ASSERT("fixed_hdr_idx <= client->msg_idx", fixed_hdr_idx <= client->msg_idx); - LWIP_ERROR("buffer length mismatch", fixed_hdr_idx + length <= MQTT_VAR_HEADER_BUFFER_LEN, - return MQTT_CONNECT_DISCONNECTED); - - if (pkt_type == MQTT_MSG_TYPE_CONNACK) { - if (client->conn_state == MQTT_CONNECTING) { - if (length < 2) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received short CONNACK message\n")); - goto out_disconnect; - } - /* Get result code from CONNACK */ - res = (mqtt_connection_status_t)var_hdr_payload[1]; - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_message_received: Connect response code %d\n", res)); - if (res == MQTT_CONNECT_ACCEPTED) { - /* Reset cyclic_tick when changing to connected state */ - client->cyclic_tick = 0; - client->conn_state = MQTT_CONNECTED; - /* Notify upper layer */ - if (client->connect_cb != 0) { - client->connect_cb(client, client->connect_arg, res); - } - } - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_message_received: Received CONNACK in connected state\n")); - } - } else if (pkt_type == MQTT_MSG_TYPE_PINGRESP) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ( "mqtt_message_received: Received PINGRESP from server\n")); - - } else if (pkt_type == MQTT_MSG_TYPE_PUBLISH) { - u16_t payload_offset = 0; - u16_t payload_length = length; - u8_t qos = MQTT_CTL_PACKET_QOS(client->rx_buffer[0]); - - if (client->msg_idx <= MQTT_VAR_HEADER_BUFFER_LEN) { - /* Should have topic and pkt id*/ - u8_t *topic; - u16_t after_topic; - u8_t bkp; - u16_t topic_len; - u16_t qos_len = (qos ? 2U : 0U); - if (length < 2 + qos_len) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received short PUBLISH packet\n")); - goto out_disconnect; - } - topic_len = var_hdr_payload[0]; - topic_len = (topic_len << 8) + (u16_t)(var_hdr_payload[1]); - if ((topic_len > length - (2 + qos_len)) || - (topic_len > var_hdr_payload_bufsize - (2 + qos_len))) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received short PUBLISH packet (topic)\n")); - goto out_disconnect; - } - - topic = var_hdr_payload + 2; - after_topic = 2 + topic_len; - /* Check buffer length, add one byte even for QoS 0 so that zero termination will fit */ - if ((after_topic + (qos ? 2U : 1U)) > var_hdr_payload_bufsize) { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_message_received: Receive buffer can not fit topic + pkt_id\n")); - goto out_disconnect; - } - - /* id for QoS 1 and 2 */ - if (qos > 0) { - if (length < after_topic + 2U) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received short PUBLISH packet (after_topic)\n")); - goto out_disconnect; - } - client->inpub_pkt_id = ((u16_t)var_hdr_payload[after_topic] << 8) + (u16_t)var_hdr_payload[after_topic + 1]; - after_topic += 2; - } else { - client->inpub_pkt_id = 0; - } - /* Take backup of byte after topic */ - bkp = topic[topic_len]; - /* Zero terminate string */ - topic[topic_len] = 0; - /* Payload data remaining in receive buffer */ - payload_length = length - after_topic; - payload_offset = after_topic; - - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_incomming_publish: Received message with QoS %d at topic: %s, payload length %"U32_F"\n", - qos, topic, remaining_length + payload_length)); - if (client->pub_cb != NULL) { - client->pub_cb(client->inpub_arg, (const char *)topic, remaining_length + payload_length); - } - /* Restore byte after topic */ - topic[topic_len] = bkp; - } - if (payload_length > 0 || remaining_length == 0) { - if (length < (size_t)(payload_offset + payload_length)) { - LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received short packet (payload)\n")); - goto out_disconnect; - } - client->data_cb(client->inpub_arg, var_hdr_payload + payload_offset, payload_length, remaining_length == 0 ? MQTT_DATA_FLAG_LAST : 0); - /* Reply if QoS > 0 */ - if (remaining_length == 0 && qos > 0) { - /* Send PUBACK for QoS 1 or PUBREC for QoS 2 */ - u8_t resp_msg = (qos == 1) ? MQTT_MSG_TYPE_PUBACK : MQTT_MSG_TYPE_PUBREC; - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_incomming_publish: Sending publish response: %s with pkt_id: %d\n", - mqtt_msg_type_to_str(resp_msg), client->inpub_pkt_id)); - pub_ack_rec_rel_response(client, resp_msg, client->inpub_pkt_id, 0); - } - } - } else { - /* Get packet identifier */ - pkt_id = (u16_t)var_hdr_payload[0] << 8; - pkt_id |= (u16_t)var_hdr_payload[1]; - if (pkt_id == 0) { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_message_received: Got message with illegal packet identifier: 0\n")); - goto out_disconnect; - } - if (pkt_type == MQTT_MSG_TYPE_PUBREC) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_message_received: PUBREC, sending PUBREL with pkt_id: %d\n", pkt_id)); - pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBREL, pkt_id, 1); - - } else if (pkt_type == MQTT_MSG_TYPE_PUBREL) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_message_received: PUBREL, sending PUBCOMP response with pkt_id: %d\n", pkt_id)); - pub_ack_rec_rel_response(client, MQTT_MSG_TYPE_PUBCOMP, pkt_id, 0); - - } else if (pkt_type == MQTT_MSG_TYPE_SUBACK || pkt_type == MQTT_MSG_TYPE_UNSUBACK || - pkt_type == MQTT_MSG_TYPE_PUBCOMP || pkt_type == MQTT_MSG_TYPE_PUBACK) { - struct mqtt_request_t *r = mqtt_take_request(&client->pend_req_queue, pkt_id); - if (r != NULL) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_message_received: %s response with id %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id)); - if (pkt_type == MQTT_MSG_TYPE_SUBACK) { - if (length < 3) { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_message_received: To small SUBACK packet\n")); - goto out_disconnect; - } else { - mqtt_incomming_suback(r, var_hdr_payload[2]); - } - } else if (r->cb != NULL) { - r->cb(r->arg, ERR_OK); - } - mqtt_delete_request(r); - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ( "mqtt_message_received: Received %s reply, with wrong pkt_id: %d\n", mqtt_msg_type_to_str(pkt_type), pkt_id)); - } - } else { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ( "mqtt_message_received: Received unknown message type: %d\n", pkt_type)); - goto out_disconnect; - } - } - return res; -out_disconnect: - return MQTT_CONNECT_DISCONNECTED; -} - - -/** - * MQTT incoming message parser - * @param client MQTT client - * @param p PBUF chain of received data - * @return Connection status - */ -static mqtt_connection_status_t -mqtt_parse_incoming(mqtt_client_t *client, struct pbuf *p) -{ - u16_t in_offset = 0; - u32_t msg_rem_len = 0; - u8_t fixed_hdr_idx = 0; - u8_t b = 0; - - while (p->tot_len > in_offset) { - /* We ALWAYS parse the header here first. Even if the header was not - included in this segment, we re-parse it here by buffering it in - client->rx_buffer. client->msg_idx keeps track of this. */ - if ((fixed_hdr_idx < 2) || ((b & 0x80) != 0)) { - - if (fixed_hdr_idx < client->msg_idx) { - /* parse header from old pbuf (buffered in client->rx_buffer) */ - b = client->rx_buffer[fixed_hdr_idx]; - } else { - /* parse header from this pbuf and save it in client->rx_buffer in case - it comes in segmented */ - b = pbuf_get_at(p, in_offset++); - client->rx_buffer[client->msg_idx++] = b; - } - fixed_hdr_idx++; - - if (fixed_hdr_idx >= 2) { - /* fixed header contains at least 2 bytes but can contain more, depending on - 'remaining length'. All bytes but the last of this have 0x80 set to - indicate more bytes are coming. */ - msg_rem_len |= (u32_t)(b & 0x7f) << ((fixed_hdr_idx - 2) * 7); - if ((b & 0x80) == 0) { - /* fixed header is done */ - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_parse_incoming: Remaining length after fixed header: %"U32_F"\n", msg_rem_len)); - if (msg_rem_len == 0) { - /* Complete message with no extra headers of payload received */ - mqtt_message_received(client, fixed_hdr_idx, 0, 0); - client->msg_idx = 0; - fixed_hdr_idx = 0; - } else { - /* Bytes remaining in message (changes remaining length if this is - not the first segment of this message) */ - msg_rem_len = (msg_rem_len + fixed_hdr_idx) - client->msg_idx; - } - } - } - } else { - /* Fixed header has been parsed, parse variable header */ - u16_t cpy_len, cpy_start, buffer_space; - - cpy_start = (client->msg_idx - fixed_hdr_idx) % (MQTT_VAR_HEADER_BUFFER_LEN - fixed_hdr_idx) + fixed_hdr_idx; - - /* Allow to copy the lesser one of available length in input data or bytes remaining in message */ - cpy_len = (u16_t)LWIP_MIN((u16_t)(p->tot_len - in_offset), msg_rem_len); - - /* Limit to available space in buffer */ - buffer_space = MQTT_VAR_HEADER_BUFFER_LEN - cpy_start; - if (cpy_len > buffer_space) { - cpy_len = buffer_space; - } - pbuf_copy_partial(p, client->rx_buffer + cpy_start, cpy_len, in_offset); - - /* Advance get and put indexes */ - client->msg_idx += cpy_len; - in_offset += cpy_len; - msg_rem_len -= cpy_len; - - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_parse_incoming: msg_idx: %"U32_F", cpy_len: %"U16_F", remaining %"U32_F"\n", client->msg_idx, cpy_len, msg_rem_len)); - if ((msg_rem_len == 0) || (cpy_len == buffer_space)) { - /* Whole message received or buffer is full */ - mqtt_connection_status_t res = mqtt_message_received(client, fixed_hdr_idx, (cpy_start + cpy_len) - fixed_hdr_idx, msg_rem_len); - if (res != MQTT_CONNECT_ACCEPTED) { - return res; - } - if (msg_rem_len == 0) { - /* Reset parser state */ - client->msg_idx = 0; - /* msg_tot_len = 0; */ - fixed_hdr_idx = 0; - } - } - } - } - return MQTT_CONNECT_ACCEPTED; -} - - -/** - * TCP received callback function. @see tcp_recv_fn - * @param arg MQTT client - * @param p PBUF chain of received data - * @param err Passed as return value if not ERR_OK - * @return ERR_OK or err passed into callback - */ -static err_t -mqtt_tcp_recv_cb(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err) -{ - mqtt_client_t *client = (mqtt_client_t *)arg; - LWIP_ASSERT("mqtt_tcp_recv_cb: client != NULL", client != NULL); - LWIP_ASSERT("mqtt_tcp_recv_cb: client->conn == pcb", client->conn == pcb); - - if (p == NULL) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_tcp_recv_cb: Recv pbuf=NULL, remote has closed connection\n")); - mqtt_close(client, MQTT_CONNECT_DISCONNECTED); - } else { - mqtt_connection_status_t res; - if (err != ERR_OK) { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_tcp_recv_cb: Recv err=%d\n", err)); - pbuf_free(p); - return err; - } - - /* Tell remote that data has been received */ - altcp_recved(pcb, p->tot_len); - res = mqtt_parse_incoming(client, p); - pbuf_free(p); - - if (res != MQTT_CONNECT_ACCEPTED) { - mqtt_close(client, res); - } - /* If keep alive functionality is used */ - if (client->keep_alive != 0) { - /* Reset server alive watchdog */ - client->server_watchdog = 0; - } - - } - return ERR_OK; -} - - -/** - * TCP data sent callback function. @see tcp_sent_fn - * @param arg MQTT client - * @param tpcb TCP connection handle - * @param len Number of bytes sent - * @return ERR_OK - */ -static err_t -mqtt_tcp_sent_cb(void *arg, struct altcp_pcb *tpcb, u16_t len) -{ - mqtt_client_t *client = (mqtt_client_t *)arg; - - LWIP_UNUSED_ARG(tpcb); - LWIP_UNUSED_ARG(len); - - if (client->conn_state == MQTT_CONNECTED) { - struct mqtt_request_t *r; - - /* Reset keep-alive send timer and server watchdog */ - client->cyclic_tick = 0; - client->server_watchdog = 0; - /* QoS 0 publish has no response from server, so call its callbacks here */ - while ((r = mqtt_take_request(&client->pend_req_queue, 0)) != NULL) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_tcp_sent_cb: Calling QoS 0 publish complete callback\n")); - if (r->cb != NULL) { - r->cb(r->arg, ERR_OK); - } - mqtt_delete_request(r); - } - /* Try send any remaining buffers from output queue */ - mqtt_output_send(&client->output, client->conn); - } - return ERR_OK; -} - -/** - * TCP error callback function. @see tcp_err_fn - * @param arg MQTT client - * @param err Error encountered - */ -static void -mqtt_tcp_err_cb(void *arg, err_t err) -{ - mqtt_client_t *client = (mqtt_client_t *)arg; - LWIP_UNUSED_ARG(err); /* only used for debug output */ - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_tcp_err_cb: TCP error callback: error %d, arg: %p\n", err, arg)); - LWIP_ASSERT("mqtt_tcp_err_cb: client != NULL", client != NULL); - /* Set conn to null before calling close as pcb is already deallocated*/ - client->conn = 0; - mqtt_close(client, MQTT_CONNECT_DISCONNECTED); -} - -/** - * TCP poll callback function. @see tcp_poll_fn - * @param arg MQTT client - * @param tpcb TCP connection handle - * @return err ERR_OK - */ -static err_t -mqtt_tcp_poll_cb(void *arg, struct altcp_pcb *tpcb) -{ - mqtt_client_t *client = (mqtt_client_t *)arg; - if (client->conn_state == MQTT_CONNECTED) { - /* Try send any remaining buffers from output queue */ - mqtt_output_send(&client->output, tpcb); - } - return ERR_OK; -} - -/** - * TCP connect callback function. @see tcp_connected_fn - * @param arg MQTT client - * @param err Always ERR_OK, mqtt_tcp_err_cb is called in case of error - * @return ERR_OK - */ -static err_t -mqtt_tcp_connect_cb(void *arg, struct altcp_pcb *tpcb, err_t err) -{ - mqtt_client_t *client = (mqtt_client_t *)arg; - - if (err != ERR_OK) { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_tcp_connect_cb: TCP connect error %d\n", err)); - return err; - } - - /* Initiate receiver state */ - client->msg_idx = 0; - - /* Setup TCP callbacks */ - altcp_recv(tpcb, mqtt_tcp_recv_cb); - altcp_sent(tpcb, mqtt_tcp_sent_cb); - altcp_poll(tpcb, mqtt_tcp_poll_cb, 2); - - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_tcp_connect_cb: TCP connection established to server\n")); - /* Enter MQTT connect state */ - client->conn_state = MQTT_CONNECTING; - - /* Start cyclic timer */ - sys_timeout(MQTT_CYCLIC_TIMER_INTERVAL * 1000, mqtt_cyclic_timer, client); - client->cyclic_tick = 0; - - /* Start transmission from output queue, connect message is the first one out*/ - mqtt_output_send(&client->output, client->conn); - - return ERR_OK; -} - - - -/*---------------------------------------------------------------------------------------------------- */ -/* Public API */ - - -/** - * @ingroup mqtt - * MQTT publish function. - * @param client MQTT client - * @param topic Publish topic string - * @param payload Data to publish (NULL is allowed) - * @param payload_length Length of payload (0 is allowed) - * @param qos Quality of service, 0 1 or 2 - * @param retain MQTT retain flag - * @param cb Callback to call when publish is complete or has timed out - * @param arg User supplied argument to publish callback - * @return ERR_OK if successful - * ERR_CONN if client is disconnected - * ERR_MEM if short on memory - */ -err_t -mqtt_publish(mqtt_client_t *client, const char *topic, const void *payload, u16_t payload_length, u8_t qos, u8_t retain, - mqtt_request_cb_t cb, void *arg) -{ - struct mqtt_request_t *r; - u16_t pkt_id; - size_t topic_strlen; - size_t total_len; - u16_t topic_len; - u16_t remaining_length; - - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("mqtt_publish: client != NULL", client); - LWIP_ASSERT("mqtt_publish: topic != NULL", topic); - LWIP_ERROR("mqtt_publish: TCP disconnected", (client->conn_state != TCP_DISCONNECTED), return ERR_CONN); - - topic_strlen = strlen(topic); - LWIP_ERROR("mqtt_publish: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG); - topic_len = (u16_t)topic_strlen; - total_len = 2 + topic_len + payload_length; - - if (qos > 0) { - total_len += 2; - /* Generate pkt_id id for QoS1 and 2 */ - pkt_id = msg_generate_packet_id(client); - } else { - /* Use reserved value pkt_id 0 for QoS 0 in request handle */ - pkt_id = 0; - } - LWIP_ERROR("mqtt_publish: total length overflow", (total_len <= 0xFFFF), return ERR_ARG); - remaining_length = (u16_t)total_len; - - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_publish: Publish with payload length %d to topic \"%s\"\n", payload_length, topic)); - - r = mqtt_create_request(client->req_list, LWIP_ARRAYSIZE(client->req_list), pkt_id, cb, arg); - if (r == NULL) { - return ERR_MEM; - } - - if (mqtt_output_check_space(&client->output, remaining_length) == 0) { - mqtt_delete_request(r); - return ERR_MEM; - } - /* Append fixed header */ - mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain, remaining_length); - - /* Append Topic */ - mqtt_output_append_string(&client->output, topic, topic_len); - - /* Append packet if for QoS 1 and 2*/ - if (qos > 0) { - mqtt_output_append_u16(&client->output, pkt_id); - } - - /* Append optional publish payload */ - if ((payload != NULL) && (payload_length > 0)) { - mqtt_output_append_buf(&client->output, payload, payload_length); - } - - mqtt_append_request(&client->pend_req_queue, r); - mqtt_output_send(&client->output, client->conn); - return ERR_OK; -} - - -/** - * @ingroup mqtt - * MQTT subscribe/unsubscribe function. - * @param client MQTT client - * @param topic topic to subscribe to - * @param qos Quality of service, 0 1 or 2 (only used for subscribe) - * @param cb Callback to call when subscribe/unsubscribe reponse is received - * @param arg User supplied argument to publish callback - * @param sub 1 for subscribe, 0 for unsubscribe - * @return ERR_OK if successful, @see err_t enum for other results - */ -err_t -mqtt_sub_unsub(mqtt_client_t *client, const char *topic, u8_t qos, mqtt_request_cb_t cb, void *arg, u8_t sub) -{ - size_t topic_strlen; - size_t total_len; - u16_t topic_len; - u16_t remaining_length; - u16_t pkt_id; - struct mqtt_request_t *r; - - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("mqtt_sub_unsub: client != NULL", client); - LWIP_ASSERT("mqtt_sub_unsub: topic != NULL", topic); - - topic_strlen = strlen(topic); - LWIP_ERROR("mqtt_sub_unsub: topic length overflow", (topic_strlen <= (0xFFFF - 2)), return ERR_ARG); - topic_len = (u16_t)topic_strlen; - /* Topic string, pkt_id, qos for subscribe */ - total_len = topic_len + 2 + 2 + (sub != 0); - LWIP_ERROR("mqtt_sub_unsub: total length overflow", (total_len <= 0xFFFF), return ERR_ARG); - remaining_length = (u16_t)total_len; - - LWIP_ASSERT("mqtt_sub_unsub: qos < 3", qos < 3); - if (client->conn_state == TCP_DISCONNECTED) { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_sub_unsub: Can not (un)subscribe in disconnected state\n")); - return ERR_CONN; - } - - pkt_id = msg_generate_packet_id(client); - r = mqtt_create_request(client->req_list, LWIP_ARRAYSIZE(client->req_list), pkt_id, cb, arg); - if (r == NULL) { - return ERR_MEM; - } - - if (mqtt_output_check_space(&client->output, remaining_length) == 0) { - mqtt_delete_request(r); - return ERR_MEM; - } - - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_sub_unsub: Client (un)subscribe to topic \"%s\", id: %d\n", topic, pkt_id)); - - mqtt_output_append_fixed_header(&client->output, sub ? MQTT_MSG_TYPE_SUBSCRIBE : MQTT_MSG_TYPE_UNSUBSCRIBE, 0, 1, 0, remaining_length); - /* Packet id */ - mqtt_output_append_u16(&client->output, pkt_id); - /* Topic */ - mqtt_output_append_string(&client->output, topic, topic_len); - /* QoS */ - if (sub != 0) { - mqtt_output_append_u8(&client->output, LWIP_MIN(qos, 2)); - } - - mqtt_append_request(&client->pend_req_queue, r); - mqtt_output_send(&client->output, client->conn); - return ERR_OK; -} - - -/** - * @ingroup mqtt - * Set callback to handle incoming publish requests from server - * @param client MQTT client - * @param pub_cb Callback invoked when publish starts, contain topic and total length of payload - * @param data_cb Callback for each fragment of payload that arrives - * @param arg User supplied argument to both callbacks - */ -void -mqtt_set_inpub_callback(mqtt_client_t *client, mqtt_incoming_publish_cb_t pub_cb, - mqtt_incoming_data_cb_t data_cb, void *arg) -{ - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("mqtt_set_inpub_callback: client != NULL", client != NULL); - client->data_cb = data_cb; - client->pub_cb = pub_cb; - client->inpub_arg = arg; -} - -/** - * @ingroup mqtt - * Create a new MQTT client instance - * @return Pointer to instance on success, NULL otherwise - */ -mqtt_client_t * -mqtt_client_new(void) -{ - LWIP_ASSERT_CORE_LOCKED(); - return (mqtt_client_t *)mem_calloc(1, sizeof(mqtt_client_t)); -} - -/** - * @ingroup mqtt - * Free MQTT client instance - * @param client Pointer to instance to be freed - */ -void -mqtt_client_free(mqtt_client_t *client) -{ - mem_free(client); -} - -/** - * @ingroup mqtt - * Connect to MQTT server - * @param client MQTT client - * @param ip_addr Server IP - * @param port Server port - * @param cb Connection state change callback - * @param arg User supplied argument to connection callback - * @param client_info Client identification and connection options - * @return ERR_OK if successful, @see err_t enum for other results - */ -err_t -mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port, mqtt_connection_cb_t cb, void *arg, - const struct mqtt_connect_client_info_t *client_info) -{ - err_t err; - size_t len; - u16_t client_id_length; - /* Length is the sum of 2+"MQTT", protocol level, flags and keep alive */ - u16_t remaining_length = 2 + 4 + 1 + 1 + 2; - u8_t flags = 0, will_topic_len = 0, will_msg_len = 0; - u16_t client_user_len = 0, client_pass_len = 0; - - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("mqtt_client_connect: client != NULL", client != NULL); - LWIP_ASSERT("mqtt_client_connect: ip_addr != NULL", ip_addr != NULL); - LWIP_ASSERT("mqtt_client_connect: client_info != NULL", client_info != NULL); - LWIP_ASSERT("mqtt_client_connect: client_info->client_id != NULL", client_info->client_id != NULL); - - if (client->conn_state != TCP_DISCONNECTED) { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_client_connect: Already connected\n")); - return ERR_ISCONN; - } - - /* Wipe clean */ - memset(client, 0, sizeof(mqtt_client_t)); - client->connect_arg = arg; - client->connect_cb = cb; - client->keep_alive = client_info->keep_alive; - mqtt_init_requests(client->req_list, LWIP_ARRAYSIZE(client->req_list)); - - /* Build connect message */ - if (client_info->will_topic != NULL && client_info->will_msg != NULL) { - flags |= MQTT_CONNECT_FLAG_WILL; - flags |= (client_info->will_qos & 3) << 3; - if (client_info->will_retain) { - flags |= MQTT_CONNECT_FLAG_WILL_RETAIN; - } - len = strlen(client_info->will_topic); - LWIP_ERROR("mqtt_client_connect: client_info->will_topic length overflow", len <= 0xFF, return ERR_VAL); - LWIP_ERROR("mqtt_client_connect: client_info->will_topic length must be > 0", len > 0, return ERR_VAL); - will_topic_len = (u8_t)len; - len = strlen(client_info->will_msg); - LWIP_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return ERR_VAL); - will_msg_len = (u8_t)len; - len = remaining_length + 2 + will_topic_len + 2 + will_msg_len; - LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); - remaining_length = (u16_t)len; - } - if (client_info->client_user != NULL) { - flags |= MQTT_CONNECT_FLAG_USERNAME; - len = strlen(client_info->client_user); - LWIP_ERROR("mqtt_client_connect: client_info->client_user length overflow", len <= 0xFFFF, return ERR_VAL); - LWIP_ERROR("mqtt_client_connect: client_info->client_user length must be > 0", len > 0, return ERR_VAL); - client_user_len = (u16_t)len; - len = remaining_length + 2 + client_user_len; - LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); - remaining_length = (u16_t)len; - } - if (client_info->client_pass != NULL) { - flags |= MQTT_CONNECT_FLAG_PASSWORD; - len = strlen(client_info->client_pass); - LWIP_ERROR("mqtt_client_connect: client_info->client_pass length overflow", len <= 0xFFFF, return ERR_VAL); - LWIP_ERROR("mqtt_client_connect: client_info->client_pass length must be > 0", len > 0, return ERR_VAL); - client_pass_len = (u16_t)len; - len = remaining_length + 2 + client_pass_len; - LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); - remaining_length = (u16_t)len; - } - - /* Don't complicate things, always connect using clean session */ - flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION; - - len = strlen(client_info->client_id); - LWIP_ERROR("mqtt_client_connect: client_info->client_id length overflow", len <= 0xFFFF, return ERR_VAL); - client_id_length = (u16_t)len; - len = remaining_length + 2 + client_id_length; - LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL); - remaining_length = (u16_t)len; - - if (mqtt_output_check_space(&client->output, remaining_length) == 0) { - return ERR_MEM; - } - -#if LWIP_ALTCP && LWIP_ALTCP_TLS - if (client_info->tls_config) { - client->conn = altcp_tls_new(client_info->tls_config, IP_GET_TYPE(ip_addr)); - } else -#endif - { - client->conn = altcp_tcp_new_ip_type(IP_GET_TYPE(ip_addr)); - } - if (client->conn == NULL) { - return ERR_MEM; - } - - /* Set arg pointer for callbacks */ - altcp_arg(client->conn, client); - /* Any local address, pick random local port number */ - err = altcp_bind(client->conn, IP_ADDR_ANY, 0); - if (err != ERR_OK) { - LWIP_DEBUGF(MQTT_DEBUG_WARN, ("mqtt_client_connect: Error binding to local ip/port, %d\n", err)); - goto tcp_fail; - } - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_client_connect: Connecting to host: %s at port:%"U16_F"\n", ipaddr_ntoa(ip_addr), port)); - - /* Connect to server */ - err = altcp_connect(client->conn, ip_addr, port, mqtt_tcp_connect_cb); - if (err != ERR_OK) { - LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_client_connect: Error connecting to remote ip/port, %d\n", err)); - goto tcp_fail; - } - /* Set error callback */ - altcp_err(client->conn, mqtt_tcp_err_cb); - client->conn_state = TCP_CONNECTING; - - /* Append fixed header */ - mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_CONNECT, 0, 0, 0, remaining_length); - /* Append Protocol string */ - mqtt_output_append_string(&client->output, "MQTT", 4); - /* Append Protocol level */ - mqtt_output_append_u8(&client->output, 4); - /* Append connect flags */ - mqtt_output_append_u8(&client->output, flags); - /* Append keep-alive */ - mqtt_output_append_u16(&client->output, client_info->keep_alive); - /* Append client id */ - mqtt_output_append_string(&client->output, client_info->client_id, client_id_length); - /* Append will message if used */ - if ((flags & MQTT_CONNECT_FLAG_WILL) != 0) { - mqtt_output_append_string(&client->output, client_info->will_topic, will_topic_len); - mqtt_output_append_string(&client->output, client_info->will_msg, will_msg_len); - } - /* Append user name if given */ - if ((flags & MQTT_CONNECT_FLAG_USERNAME) != 0) { - mqtt_output_append_string(&client->output, client_info->client_user, client_user_len); - } - /* Append password if given */ - if ((flags & MQTT_CONNECT_FLAG_PASSWORD) != 0) { - mqtt_output_append_string(&client->output, client_info->client_pass, client_pass_len); - } - return ERR_OK; - -tcp_fail: - altcp_abort(client->conn); - client->conn = NULL; - return err; -} - - -/** - * @ingroup mqtt - * Disconnect from MQTT server - * @param client MQTT client - */ -void -mqtt_disconnect(mqtt_client_t *client) -{ - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("mqtt_disconnect: client != NULL", client); - /* If connection in not already closed */ - if (client->conn_state != TCP_DISCONNECTED) { - /* Set conn_state before calling mqtt_close to prevent callback from being called */ - client->conn_state = TCP_DISCONNECTED; - mqtt_close(client, (mqtt_connection_status_t)0); - } -} - -/** - * @ingroup mqtt - * Check connection with server - * @param client MQTT client - * @return 1 if connected to server, 0 otherwise - */ -u8_t -mqtt_client_is_connected(mqtt_client_t *client) -{ - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("mqtt_client_is_connected: client != NULL", client); - return client->conn_state == MQTT_CONNECTED; -} - -#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/netbiosns/netbiosns.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/netbiosns/netbiosns.c deleted file mode 100644 index c94a77910..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/netbiosns/netbiosns.c +++ /dev/null @@ -1,533 +0,0 @@ - /** - * @file - * NetBIOS name service responder - */ - -/** - * @defgroup netbiosns NETBIOS responder - * @ingroup apps - * - * This is an example implementation of a NetBIOS name server. - * It responds to name queries for a configurable name. - * Name resolving is not supported. - * - * Note that the device doesn't broadcast it's own name so can't - * detect duplicate names! - */ - -/* - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Modifications by Ray Abram to respond to NetBIOS name requests when Incoming name = * - * - based on code from "https://github.com/esp8266/Arduino/commit/1f7989b31d26d7df9776a08f36d685eae7ac8f99" - * - with permission to relicense to BSD from original author: - * http://www.xpablo.cz/?p=751#more-751 - */ - -#include "lwip/apps/netbiosns.h" - -#if LWIP_IPV4 && LWIP_UDP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/def.h" -#include "lwip/udp.h" -#include "lwip/ip.h" -#include "lwip/netif.h" -#include "lwip/prot/iana.h" - -#include - -/** size of a NetBIOS name */ -#define NETBIOS_NAME_LEN 16 - -/** The Time-To-Live for NetBIOS name responds (in seconds) - * Default is 300000 seconds (3 days, 11 hours, 20 minutes) */ -#define NETBIOS_NAME_TTL 300000u - -/** NetBIOS header flags */ -#define NETB_HFLAG_RESPONSE 0x8000U -#define NETB_HFLAG_OPCODE 0x7800U -#define NETB_HFLAG_OPCODE_NAME_QUERY 0x0000U -#define NETB_HFLAG_AUTHORATIVE 0x0400U -#define NETB_HFLAG_TRUNCATED 0x0200U -#define NETB_HFLAG_RECURS_DESIRED 0x0100U -#define NETB_HFLAG_RECURS_AVAILABLE 0x0080U -#define NETB_HFLAG_BROADCAST 0x0010U -#define NETB_HFLAG_REPLYCODE 0x0008U -#define NETB_HFLAG_REPLYCODE_NOERROR 0x0000U - -/* NetBIOS question types */ -#define NETB_QTYPE_NB 0x0020U -#define NETB_QTYPE_NBSTAT 0x0021U - -/** NetBIOS name flags */ -#define NETB_NFLAG_UNIQUE 0x8000U -#define NETB_NFLAG_NODETYPE 0x6000U -#define NETB_NFLAG_NODETYPE_HNODE 0x6000U -#define NETB_NFLAG_NODETYPE_MNODE 0x4000U -#define NETB_NFLAG_NODETYPE_PNODE 0x2000U -#define NETB_NFLAG_NODETYPE_BNODE 0x0000U - -#define NETB_NFLAG_NAME_IN_CONFLICT 0x0800U /* 1=Yes, 0=No */ -#define NETB_NFLAG_NAME_IS_ACTIVE 0x0400U /* 1=Yes, 0=No */ -#define NETB_NFLAG_NAME_IS_PERMANENT 0x0200U /* 1=Yes (Name is Permanent Node Name), 0=No */ - -/** NetBIOS message header */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct netbios_hdr { - PACK_STRUCT_FIELD(u16_t trans_id); - PACK_STRUCT_FIELD(u16_t flags); - PACK_STRUCT_FIELD(u16_t questions); - PACK_STRUCT_FIELD(u16_t answerRRs); - PACK_STRUCT_FIELD(u16_t authorityRRs); - PACK_STRUCT_FIELD(u16_t additionalRRs); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** NetBIOS message question part */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct netbios_question_hdr { - PACK_STRUCT_FLD_8(u8_t nametype); - PACK_STRUCT_FLD_8(u8_t encname[(NETBIOS_NAME_LEN * 2) + 1]); - PACK_STRUCT_FIELD(u16_t type); - PACK_STRUCT_FIELD(u16_t cls); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** NetBIOS message name part */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct netbios_name_hdr { - PACK_STRUCT_FLD_8(u8_t nametype); - PACK_STRUCT_FLD_8(u8_t encname[(NETBIOS_NAME_LEN * 2) + 1]); - PACK_STRUCT_FIELD(u16_t type); - PACK_STRUCT_FIELD(u16_t cls); - PACK_STRUCT_FIELD(u32_t ttl); - PACK_STRUCT_FIELD(u16_t datalen); - PACK_STRUCT_FIELD(u16_t flags); - PACK_STRUCT_FLD_S(ip4_addr_p_t addr); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** NetBIOS message */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct netbios_resp { - struct netbios_hdr resp_hdr; - struct netbios_name_hdr resp_name; -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/** The NBNS Structure Responds to a Name Query */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct netbios_answer { - struct netbios_hdr answer_hdr; - /** the length of the next string */ - PACK_STRUCT_FIELD(u8_t name_size); - /** WARNING!!! this item may be of a different length (we use this struct for transmission) */ - PACK_STRUCT_FLD_8(u8_t query_name[(NETBIOS_NAME_LEN * 2) + 1]); - PACK_STRUCT_FIELD(u16_t packet_type); - PACK_STRUCT_FIELD(u16_t cls); - PACK_STRUCT_FIELD(u32_t ttl); - PACK_STRUCT_FIELD(u16_t data_length); -#define OFFSETOF_STRUCT_NETBIOS_ANSWER_NUMBER_OF_NAMES 56 - /** number of names */ - PACK_STRUCT_FLD_8(u8_t number_of_names); - /** node name */ - PACK_STRUCT_FLD_8(u8_t answer_name[NETBIOS_NAME_LEN]); - /** node flags */ - PACK_STRUCT_FIELD(u16_t answer_name_flags); - /** Unit ID */ - PACK_STRUCT_FLD_8(u8_t unit_id[6]); - /** Jumpers */ - PACK_STRUCT_FLD_8(u8_t jumpers); - /** Test result */ - PACK_STRUCT_FLD_8(u8_t test_result); - /** Version number */ - PACK_STRUCT_FIELD(u16_t version_number); - /** Period of statistics */ - PACK_STRUCT_FIELD(u16_t period_of_statistics); - /** Statistics */ - PACK_STRUCT_FIELD(u16_t number_of_crcs); - /** Statistics */ - PACK_STRUCT_FIELD(u16_t number_of_alignment_errors); - /** Statistics */ - PACK_STRUCT_FIELD(u16_t number_of_collisions); - /** Statistics */ - PACK_STRUCT_FIELD(u16_t number_of_send_aborts); - /** Statistics */ - PACK_STRUCT_FIELD(u32_t number_of_good_sends); - /** Statistics */ - PACK_STRUCT_FIELD(u32_t number_of_good_receives); - /** Statistics */ - PACK_STRUCT_FIELD(u16_t number_of_retransmits); - /** Statistics */ - PACK_STRUCT_FIELD(u16_t number_of_no_resource_condition); - /** Statistics */ - PACK_STRUCT_FIELD(u16_t number_of_free_command_blocks); - /** Statistics */ - PACK_STRUCT_FIELD(u16_t total_number_of_command_blocks); - /** Statistics */ - PACK_STRUCT_FIELD(u16_t max_total_number_of_command_blocks); - /** Statistics */ - PACK_STRUCT_FIELD(u16_t number_of_pending_sessions); - /** Statistics */ - PACK_STRUCT_FIELD(u16_t max_number_of_pending_sessions); - /** Statistics */ - PACK_STRUCT_FIELD(u16_t max_total_sessions_possible); - /** Statistics */ - PACK_STRUCT_FIELD(u16_t session_data_packet_size); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -#ifdef NETBIOS_LWIP_NAME -#define NETBIOS_LOCAL_NAME NETBIOS_LWIP_NAME -#else -static char netbiosns_local_name[NETBIOS_NAME_LEN]; -#define NETBIOS_LOCAL_NAME netbiosns_local_name -#endif - -static struct udp_pcb *netbiosns_pcb; - -/** Decode a NetBIOS name (from packet to string) */ -static int -netbiosns_name_decode(char *name_enc, char *name_dec, int name_dec_len) -{ - char *pname; - char cname; - char cnbname; - int idx = 0; - - LWIP_UNUSED_ARG(name_dec_len); - - /* Start decoding netbios name. */ - pname = name_enc; - for (;;) { - /* Every two characters of the first level-encoded name - * turn into one character in the decoded name. */ - cname = *pname; - if (cname == '\0') { - break; /* no more characters */ - } - if (cname == '.') { - break; /* scope ID follows */ - } - if (!lwip_isupper(cname)) { - /* Not legal. */ - return -1; - } - cname -= 'A'; - cnbname = cname << 4; - pname++; - - cname = *pname; - if (!lwip_isupper(cname)) { - /* Not legal. */ - return -1; - } - cname -= 'A'; - cnbname |= cname; - pname++; - - /* Do we have room to store the character? */ - if (idx < NETBIOS_NAME_LEN) { - /* Yes - store the character. */ - name_dec[idx++] = (cnbname != ' ' ? cnbname : '\0'); - } - } - - return 0; -} - -#if 0 /* function currently unused */ -/** Encode a NetBIOS name (from string to packet) - currently unused because - we don't ask for names. */ -static int -netbiosns_name_encode(char *name_enc, char *name_dec, int name_dec_len) -{ - char *pname; - char cname; - unsigned char ucname; - int idx = 0; - - /* Start encoding netbios name. */ - pname = name_enc; - - for (;;) { - /* Every two characters of the first level-encoded name - * turn into one character in the decoded name. */ - cname = *pname; - if (cname == '\0') { - break; /* no more characters */ - } - if (cname == '.') { - break; /* scope ID follows */ - } - if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) { - /* Not legal. */ - return -1; - } - - /* Do we have room to store the character? */ - if (idx >= name_dec_len) { - return -1; - } - - /* Yes - store the character. */ - ucname = cname; - name_dec[idx++] = ('A' + ((ucname >> 4) & 0x0F)); - name_dec[idx++] = ('A' + ( ucname & 0x0F)); - pname++; - } - - /* Fill with "space" coding */ - for (; idx < name_dec_len - 1;) { - name_dec[idx++] = 'C'; - name_dec[idx++] = 'A'; - } - - /* Terminate string */ - name_dec[idx] = '\0'; - - return 0; -} -#endif /* 0 */ - -/** NetBIOS Name service recv callback */ -static void -netbiosns_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - LWIP_UNUSED_ARG(arg); - - /* if packet is valid */ - if (p != NULL) { - char netbios_name[NETBIOS_NAME_LEN + 1]; - struct netbios_hdr *netbios_hdr = (struct netbios_hdr *)p->payload; - struct netbios_question_hdr *netbios_question_hdr = (struct netbios_question_hdr *)(netbios_hdr + 1); - - /* is the packet long enough (we need the header in one piece) */ - if (p->len < (sizeof(struct netbios_hdr) + sizeof(struct netbios_question_hdr))) { - /* packet too short */ - pbuf_free(p); - return; - } - /* we only answer if we got a default interface */ - if (netif_default != NULL) { - /* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */ - /* if the packet is a NetBIOS name query question */ - if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) && - ((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) && - (netbios_hdr->questions == PP_NTOHS(1))) { - /* decode the NetBIOS name */ - netbiosns_name_decode((char *)(netbios_question_hdr->encname), netbios_name, sizeof(netbios_name)); - /* check the request type */ - if (netbios_question_hdr->type == PP_HTONS(NETB_QTYPE_NB)) { - /* if the packet is for us */ - if (lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) == 0) { - struct pbuf *q; - struct netbios_resp *resp; - - q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM); - if (q != NULL) { - resp = (struct netbios_resp *)q->payload; - - /* prepare NetBIOS header response */ - resp->resp_hdr.trans_id = netbios_hdr->trans_id; - resp->resp_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE | - NETB_HFLAG_OPCODE_NAME_QUERY | - NETB_HFLAG_AUTHORATIVE | - NETB_HFLAG_RECURS_DESIRED); - resp->resp_hdr.questions = 0; - resp->resp_hdr.answerRRs = PP_HTONS(1); - resp->resp_hdr.authorityRRs = 0; - resp->resp_hdr.additionalRRs = 0; - - /* prepare NetBIOS header datas */ - MEMCPY( resp->resp_name.encname, netbios_question_hdr->encname, sizeof(netbios_question_hdr->encname)); - resp->resp_name.nametype = netbios_question_hdr->nametype; - resp->resp_name.type = netbios_question_hdr->type; - resp->resp_name.cls = netbios_question_hdr->cls; - resp->resp_name.ttl = PP_HTONL(NETBIOS_NAME_TTL); - resp->resp_name.datalen = PP_HTONS(sizeof(resp->resp_name.flags) + sizeof(resp->resp_name.addr)); - resp->resp_name.flags = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE); - ip4_addr_copy(resp->resp_name.addr, *netif_ip4_addr(netif_default)); - - /* send the NetBIOS response */ - udp_sendto(upcb, q, addr, port); - - /* free the "reference" pbuf */ - pbuf_free(q); - } - } -#if LWIP_NETBIOS_RESPOND_NAME_QUERY - } else if (netbios_question_hdr->type == PP_HTONS(NETB_QTYPE_NBSTAT)) { - /* if the packet is for us or general query */ - if (!lwip_strnicmp(netbios_name, NETBIOS_LOCAL_NAME, sizeof(NETBIOS_LOCAL_NAME)) || - !lwip_strnicmp(netbios_name, "*", sizeof(NETBIOS_LOCAL_NAME))) { - /* general query - ask for our IP address */ - struct pbuf *q; - struct netbios_answer *resp; - - q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_answer), PBUF_RAM); - if (q != NULL) { - /* buffer to which a response is compiled */ - resp = (struct netbios_answer *) q->payload; - - /* Init response to zero, especially the statistics fields */ - memset(resp, 0, sizeof(*resp)); - - /* copy the query to the response ID */ - resp->answer_hdr.trans_id = netbios_hdr->trans_id; - /* acknowledgment of termination */ - resp->answer_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE | NETB_HFLAG_OPCODE_NAME_QUERY | NETB_HFLAG_AUTHORATIVE); - /* resp->answer_hdr.questions = PP_HTONS(0); done by memset() */ - /* serial number of the answer */ - resp->answer_hdr.answerRRs = PP_HTONS(1); - /* resp->answer_hdr.authorityRRs = PP_HTONS(0); done by memset() */ - /* resp->answer_hdr.additionalRRs = PP_HTONS(0); done by memset() */ - /* we will copy the length of the station name */ - resp->name_size = netbios_question_hdr->nametype; - /* we will copy the queried name */ - MEMCPY(resp->query_name, netbios_question_hdr->encname, (NETBIOS_NAME_LEN * 2) + 1); - /* NBSTAT */ - resp->packet_type = PP_HTONS(0x21); - /* Internet name */ - resp->cls = PP_HTONS(1); - /* resp->ttl = PP_HTONL(0); done by memset() */ - resp->data_length = PP_HTONS(sizeof(struct netbios_answer) - offsetof(struct netbios_answer, number_of_names)); - resp->number_of_names = 1; - - /* make windows see us as workstation, not as a server */ - memset(resp->answer_name, 0x20, NETBIOS_NAME_LEN - 1); - /* strlen is checked to be < NETBIOS_NAME_LEN during initialization */ - MEMCPY(resp->answer_name, NETBIOS_LOCAL_NAME, strlen(NETBIOS_LOCAL_NAME)); - - /* b-node, unique, active */ - resp->answer_name_flags = PP_HTONS(NETB_NFLAG_NAME_IS_ACTIVE); - - /* Set responder netif MAC address */ - SMEMCPY(resp->unit_id, ip_current_input_netif()->hwaddr, sizeof(resp->unit_id)); - - udp_sendto(upcb, q, addr, port); - pbuf_free(q); - } - } -#endif /* LWIP_NETBIOS_RESPOND_NAME_QUERY */ - } - } - } - /* free the pbuf */ - pbuf_free(p); - } -} - -/** - * @ingroup netbiosns - * Init netbios responder - */ -void -netbiosns_init(void) -{ - /* LWIP_ASSERT_CORE_LOCKED(); is checked by udp_new() */ -#ifdef NETBIOS_LWIP_NAME - LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN); -#endif - - netbiosns_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - if (netbiosns_pcb != NULL) { - /* we have to be allowed to send broadcast packets! */ - ip_set_option(netbiosns_pcb, SOF_BROADCAST); - udp_bind(netbiosns_pcb, IP_ANY_TYPE, LWIP_IANA_PORT_NETBIOS); - udp_recv(netbiosns_pcb, netbiosns_recv, netbiosns_pcb); - } -} - -#ifndef NETBIOS_LWIP_NAME -/** - * @ingroup netbiosns - * Set netbios name. ATTENTION: the hostname must be less than 15 characters! - * the NetBIOS name spec says the name MUST be upper case, so incoming name is forced into uppercase :-) - */ -void -netbiosns_set_name(const char *hostname) -{ - size_t i; - size_t copy_len = strlen(hostname); - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("NetBIOS name is too long!", copy_len < NETBIOS_NAME_LEN); - if (copy_len >= NETBIOS_NAME_LEN) { - copy_len = NETBIOS_NAME_LEN - 1; - } - - /* make name into upper case */ - for (i = 0; i < copy_len; i++ ) { - netbiosns_local_name[i] = (char)lwip_toupper(hostname[i]); - } - netbiosns_local_name[copy_len] = '\0'; -} -#endif /* NETBIOS_LWIP_NAME */ - -/** - * @ingroup netbiosns - * Stop netbios responder - */ -void -netbiosns_stop(void) -{ - LWIP_ASSERT_CORE_LOCKED(); - if (netbiosns_pcb != NULL) { - udp_remove(netbiosns_pcb); - netbiosns_pcb = NULL; - } -} - -#endif /* LWIP_IPV4 && LWIP_UDP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/smtp/smtp.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/smtp/smtp.c deleted file mode 100644 index 55303c35d..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/smtp/smtp.c +++ /dev/null @@ -1,1555 +0,0 @@ -/** - * @file - * SMTP client module - * - * Author: Simon Goldschmidt - * - * @defgroup smtp SMTP client - * @ingroup apps - * - * This is simple SMTP client for raw API. - * It is a minimal implementation of SMTP as specified in RFC 5321. - * - * Example usage: -@code{.c} - void my_smtp_result_fn(void *arg, u8_t smtp_result, u16_t srv_err, err_t err) - { - printf("mail (%p) sent with results: 0x%02x, 0x%04x, 0x%08x\n", arg, - smtp_result, srv_err, err); - } - static void my_smtp_test(void) - { - smtp_set_server_addr("mymailserver.org"); - -> set both username and password as NULL if no auth needed - smtp_set_auth("username", "password"); - smtp_send_mail("sender", "recipient", "subject", "body", my_smtp_result_fn, - some_argument); - } -@endcode - - * When using from any other thread than the tcpip_thread (for NO_SYS==0), use - * smtp_send_mail_int()! - * - * SMTP_BODYDH usage: -@code{.c} - int my_smtp_bodydh_fn(void *arg, struct smtp_bodydh *bdh) - { - if(bdh->state >= 10) { - return BDH_DONE; - } - sprintf(bdh->buffer,"Line #%2d\r\n",bdh->state); - bdh->length = strlen(bdh->buffer); - ++bdh->state; - return BDH_WORKING; - } - - smtp_send_mail_bodycback("sender", "recipient", "subject", - my_smtp_bodydh_fn, my_smtp_result_fn, some_argument); -@endcode - * - * @todo: - * - attachments (the main difficulty here is streaming base64-encoding to - * prevent having to allocate a buffer for the whole encoded file at once) - * - test with more mail servers... - * - */ - -#include "lwip/apps/smtp.h" - -#if LWIP_TCP && LWIP_CALLBACK_API -#include "lwip/sys.h" -#include "lwip/sockets.h" -#include "lwip/altcp.h" -#include "lwip/dns.h" -#include "lwip/mem.h" -#include "lwip/altcp_tcp.h" -#include "lwip/altcp_tls.h" - -#include /* strlen, memcpy */ -#include - -/** TCP poll interval. Unit is 0.5 sec. */ -#define SMTP_POLL_INTERVAL 4 -/** TCP poll timeout while sending message body, reset after every - * successful write. 3 minutes */ -#define SMTP_TIMEOUT_DATABLOCK ( 3 * 60 * SMTP_POLL_INTERVAL / 2) -/** TCP poll timeout while waiting for confirmation after sending the body. - * 10 minutes */ -#define SMTP_TIMEOUT_DATATERM (10 * 60 * SMTP_POLL_INTERVAL / 2) -/** TCP poll timeout while not sending the body. - * This is somewhat lower than the RFC states (5 minutes for initial, MAIL - * and RCPT) but still OK for us here. - * 2 minutes */ -#define SMTP_TIMEOUT ( 2 * 60 * SMTP_POLL_INTERVAL / 2) - -/* the various debug levels for this file */ -#define SMTP_DEBUG_TRACE (SMTP_DEBUG | LWIP_DBG_TRACE) -#define SMTP_DEBUG_STATE (SMTP_DEBUG | LWIP_DBG_STATE) -#define SMTP_DEBUG_WARN (SMTP_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define SMTP_DEBUG_WARN_STATE (SMTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) -#define SMTP_DEBUG_SERIOUS (SMTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS) - - -#define SMTP_RX_BUF_LEN 255 -#define SMTP_TX_BUF_LEN 255 -#define SMTP_CRLF "\r\n" -#define SMTP_CRLF_LEN 2 - -#define SMTP_RESP_220 "220" -#define SMTP_RESP_235 "235" -#define SMTP_RESP_250 "250" -#define SMTP_RESP_334 "334" -#define SMTP_RESP_354 "354" -#define SMTP_RESP_LOGIN_UNAME "VXNlcm5hbWU6" -#define SMTP_RESP_LOGIN_PASS "UGFzc3dvcmQ6" - -#define SMTP_KEYWORD_AUTH_SP "AUTH " -#define SMTP_KEYWORD_AUTH_EQ "AUTH=" -#define SMTP_KEYWORD_AUTH_LEN 5 -#define SMTP_AUTH_PARAM_PLAIN "PLAIN" -#define SMTP_AUTH_PARAM_LOGIN "LOGIN" - -#define SMTP_CMD_EHLO_1 "EHLO [" -#define SMTP_CMD_EHLO_1_LEN 6 -#define SMTP_CMD_EHLO_2 "]\r\n" -#define SMTP_CMD_EHLO_2_LEN 3 -#define SMTP_CMD_AUTHPLAIN_1 "AUTH PLAIN " -#define SMTP_CMD_AUTHPLAIN_1_LEN 11 -#define SMTP_CMD_AUTHPLAIN_2 "\r\n" -#define SMTP_CMD_AUTHPLAIN_2_LEN 2 -#define SMTP_CMD_AUTHLOGIN "AUTH LOGIN\r\n" -#define SMTP_CMD_AUTHLOGIN_LEN 12 -#define SMTP_CMD_MAIL_1 "MAIL FROM: <" -#define SMTP_CMD_MAIL_1_LEN 12 -#define SMTP_CMD_MAIL_2 ">\r\n" -#define SMTP_CMD_MAIL_2_LEN 3 -#define SMTP_CMD_RCPT_1 "RCPT TO: <" -#define SMTP_CMD_RCPT_1_LEN 10 -#define SMTP_CMD_RCPT_2 ">\r\n" -#define SMTP_CMD_RCPT_2_LEN 3 -#define SMTP_CMD_DATA "DATA\r\n" -#define SMTP_CMD_DATA_LEN 6 -#define SMTP_CMD_HEADER_1 "From: <" -#define SMTP_CMD_HEADER_1_LEN 7 -#define SMTP_CMD_HEADER_2 ">\r\nTo: <" -#define SMTP_CMD_HEADER_2_LEN 8 -#define SMTP_CMD_HEADER_3 ">\r\nSubject: " -#define SMTP_CMD_HEADER_3_LEN 12 -#define SMTP_CMD_HEADER_4 "\r\n\r\n" -#define SMTP_CMD_HEADER_4_LEN 4 -#define SMTP_CMD_BODY_FINISHED "\r\n.\r\n" -#define SMTP_CMD_BODY_FINISHED_LEN 5 -#define SMTP_CMD_QUIT "QUIT\r\n" -#define SMTP_CMD_QUIT_LEN 6 - -#if defined(SMTP_STAT_TX_BUF_MAX) && SMTP_STAT_TX_BUF_MAX -#define SMTP_TX_BUF_MAX(len) LWIP_MACRO(if((len) > smtp_tx_buf_len_max) smtp_tx_buf_len_max = (len);) -#else /* SMTP_STAT_TX_BUF_MAX */ -#define SMTP_TX_BUF_MAX(len) -#endif /* SMTP_STAT_TX_BUF_MAX */ - -#if SMTP_COPY_AUTHDATA -#define SMTP_USERNAME(session) (session)->username -#define SMTP_PASS(session) (session)->pass -#define SMTP_AUTH_PLAIN_DATA(session) (session)->auth_plain -#define SMTP_AUTH_PLAIN_LEN(session) (session)->auth_plain_len -#else /* SMTP_COPY_AUTHDATA */ -#define SMTP_USERNAME(session) smtp_username -#define SMTP_PASS(session) smtp_pass -#define SMTP_AUTH_PLAIN_DATA(session) smtp_auth_plain -#define SMTP_AUTH_PLAIN_LEN(session) smtp_auth_plain_len -#endif /* SMTP_COPY_AUTHDATA */ - -#if SMTP_BODYDH -#ifndef SMTP_BODYDH_MALLOC -#define SMTP_BODYDH_MALLOC(size) mem_malloc(size) -#define SMTP_BODYDH_FREE(ptr) mem_free(ptr) -#endif - -/* Some internal state return values */ -#define BDHALLDATASENT 2 -#define BDHSOMEDATASENT 1 - -enum bdh_handler_state { - BDH_SENDING, /* Serving the user function generating body content */ - BDH_STOP /* User function stopped, closing */ -}; -#endif - -/** State for SMTP client state machine */ -enum smtp_session_state { - SMTP_NULL, - SMTP_HELO, - SMTP_AUTH_PLAIN, - SMTP_AUTH_LOGIN_UNAME, - SMTP_AUTH_LOGIN_PASS, - SMTP_AUTH_LOGIN, - SMTP_MAIL, - SMTP_RCPT, - SMTP_DATA, - SMTP_BODY, - SMTP_QUIT, - SMTP_CLOSED -}; - -#ifdef LWIP_DEBUG -/** State-to-string table for debugging */ -static const char *smtp_state_str[] = { - "SMTP_NULL", - "SMTP_HELO", - "SMTP_AUTH_PLAIN", - "SMTP_AUTH_LOGIN_UNAME", - "SMTP_AUTH_LOGIN_PASS", - "SMTP_AUTH_LOGIN", - "SMTP_MAIL", - "SMTP_RCPT", - "SMTP_DATA", - "SMTP_BODY", - "SMTP_QUIT", - "SMTP_CLOSED", -}; - -static const char *smtp_result_strs[] = { - "SMTP_RESULT_OK", - "SMTP_RESULT_ERR_UNKNOWN", - "SMTP_RESULT_ERR_CONNECT", - "SMTP_RESULT_ERR_HOSTNAME", - "SMTP_RESULT_ERR_CLOSED", - "SMTP_RESULT_ERR_TIMEOUT", - "SMTP_RESULT_ERR_SVR_RESP", - "SMTP_RESULT_ERR_MEM" -}; -#endif /* LWIP_DEBUG */ - -#if SMTP_BODYDH -struct smtp_bodydh_state { - smtp_bodycback_fn callback_fn; /* The function to call (again) */ - u16_t state; - struct smtp_bodydh exposed; /* the user function structure */ -}; -#endif /* SMTP_BODYDH */ - -/** struct keeping the body and state of an smtp session */ -struct smtp_session { - /** keeping the state of the smtp session */ - enum smtp_session_state state; - /** timeout handling, if this reaches 0, the connection is closed */ - u16_t timer; - /** helper buffer for transmit, not used for sending body */ - char tx_buf[SMTP_TX_BUF_LEN + 1]; - struct pbuf* p; - /** source email address */ - const char* from; - /** size of the sourceemail address */ - u16_t from_len; - /** target email address */ - const char* to; - /** size of the target email address */ - u16_t to_len; - /** subject of the email */ - const char *subject; - /** length of the subject string */ - u16_t subject_len; - /** this is the body of the mail to be sent */ - const char* body; - /** this is the length of the body to be sent */ - u16_t body_len; - /** amount of data from body already sent */ - u16_t body_sent; - /** callback function to call when closed */ - smtp_result_fn callback_fn; - /** argument for callback function */ - void *callback_arg; -#if SMTP_COPY_AUTHDATA - /** Username to use for this request */ - char *username; - /** Password to use for this request */ - char *pass; - /** Username and password combined as necessary for PLAIN authentication */ - char auth_plain[SMTP_MAX_USERNAME_LEN + SMTP_MAX_PASS_LEN + 3]; - /** Length of smtp_auth_plain string (cannot use strlen since it includes \0) */ - size_t auth_plain_len; -#endif /* SMTP_COPY_AUTHDATA */ -#if SMTP_BODYDH - struct smtp_bodydh_state *bodydh; -#endif /* SMTP_BODYDH */ -}; - -/** IP address or DNS name of the server to use for next SMTP request */ -static char smtp_server[SMTP_MAX_SERVERNAME_LEN + 1]; -/** TCP port of the server to use for next SMTP request */ -static u16_t smtp_server_port = SMTP_DEFAULT_PORT; -#if LWIP_ALTCP && LWIP_ALTCP_TLS -/** If this is set, mail is sent using SMTPS */ -static struct altcp_tls_config *smtp_server_tls_config; -#endif -/** Username to use for the next SMTP request */ -static char *smtp_username; -/** Password to use for the next SMTP request */ -static char *smtp_pass; -/** Username and password combined as necessary for PLAIN authentication */ -static char smtp_auth_plain[SMTP_MAX_USERNAME_LEN + SMTP_MAX_PASS_LEN + 3]; -/** Length of smtp_auth_plain string (cannot use strlen since it includes \0) */ -static size_t smtp_auth_plain_len; - -#if SMTP_CHECK_DATA -static err_t smtp_verify(const char *data, size_t data_len, u8_t linebreaks_allowed); -#endif /* SMTP_CHECK_DATA */ -static err_t smtp_tcp_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err); -static void smtp_tcp_err(void *arg, err_t err); -static err_t smtp_tcp_poll(void *arg, struct altcp_pcb *pcb); -static err_t smtp_tcp_sent(void *arg, struct altcp_pcb *pcb, u16_t len); -static err_t smtp_tcp_connected(void *arg, struct altcp_pcb *pcb, err_t err); -#if LWIP_DNS -static void smtp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg); -#endif /* LWIP_DNS */ -#if SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN -static size_t smtp_base64_encode(char* target, size_t target_len, const char* source, size_t source_len); -#endif /* SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN */ -static enum smtp_session_state smtp_prepare_mail(struct smtp_session *s, u16_t *tx_buf_len); -static void smtp_send_body(struct smtp_session *s, struct altcp_pcb *pcb); -static void smtp_process(void *arg, struct altcp_pcb *pcb, struct pbuf *p); -#if SMTP_BODYDH -static void smtp_send_body_data_handler(struct smtp_session *s, struct altcp_pcb *pcb); -#endif /* SMTP_BODYDH */ - - -#ifdef LWIP_DEBUG -/** Convert an smtp result to a string */ -const char* -smtp_result_str(u8_t smtp_result) -{ - if (smtp_result >= LWIP_ARRAYSIZE(smtp_result_strs)) { - return "UNKNOWN"; - } - return smtp_result_strs[smtp_result]; -} - -/** Null-terminates the payload of p for printing out messages. - * WARNING: use this only if p is not needed any more as the last byte of - * payload is deleted! - */ -static const char* -smtp_pbuf_str(struct pbuf* p) -{ - if ((p == NULL) || (p->len == 0)) { - return ""; - } - ((char*)p->payload)[p->len] = 0; - return (const char*)p->payload; -} -#endif /* LWIP_DEBUG */ - -/** @ingroup smtp - * Set IP address or DNS name for next SMTP connection - * - * @param server IP address (in ASCII representation) or DNS name of the server - */ -err_t -smtp_set_server_addr(const char* server) -{ - size_t len = 0; - - LWIP_ASSERT_CORE_LOCKED(); - - if (server != NULL) { - /* strlen: returns length WITHOUT terminating 0 byte */ - len = strlen(server); - } - if (len > SMTP_MAX_SERVERNAME_LEN) { - return ERR_MEM; - } - if (len != 0) { - MEMCPY(smtp_server, server, len); - } - smtp_server[len] = 0; /* always OK because of smtp_server[SMTP_MAX_SERVERNAME_LEN + 1] */ - return ERR_OK; -} - -/** @ingroup smtp - * Set TCP port for next SMTP connection - * - * @param port TCP port - */ -void -smtp_set_server_port(u16_t port) -{ - LWIP_ASSERT_CORE_LOCKED(); - smtp_server_port = port; -} - -#if LWIP_ALTCP && LWIP_ALTCP_TLS -/** @ingroup smtp - * Set TLS configuration for next SMTP connection - * - * @param tls_config TLS configuration - */ -void -smtp_set_tls_config(struct altcp_tls_config *tls_config) -{ - LWIP_ASSERT_CORE_LOCKED(); - smtp_server_tls_config = tls_config; -} -#endif - -/** @ingroup smtp - * Set authentication parameters for next SMTP connection - * - * @param username login name as passed to the server - * @param pass password passed to the server together with username - */ -err_t -smtp_set_auth(const char* username, const char* pass) -{ - size_t uname_len = 0; - size_t pass_len = 0; - - LWIP_ASSERT_CORE_LOCKED(); - - memset(smtp_auth_plain, 0xfa, 64); - if (username != NULL) { - uname_len = strlen(username); - if (uname_len > SMTP_MAX_USERNAME_LEN) { - LWIP_DEBUGF(SMTP_DEBUG_SERIOUS, ("Username is too long, %d instead of %d\n", - (int)uname_len, SMTP_MAX_USERNAME_LEN)); - return ERR_ARG; - } - } - if (pass != NULL) { -#if SMTP_SUPPORT_AUTH_LOGIN || SMTP_SUPPORT_AUTH_PLAIN - pass_len = strlen(pass); - if (pass_len > SMTP_MAX_PASS_LEN) { - LWIP_DEBUGF(SMTP_DEBUG_SERIOUS, ("Password is too long, %d instead of %d\n", - (int)uname_len, SMTP_MAX_USERNAME_LEN)); - return ERR_ARG; - } -#else /* SMTP_SUPPORT_AUTH_LOGIN || SMTP_SUPPORT_AUTH_PLAIN */ - LWIP_DEBUGF(SMTP_DEBUG_WARN, ("Password not supported as no authentication methods are activated\n")); -#endif /* SMTP_SUPPORT_AUTH_LOGIN || SMTP_SUPPORT_AUTH_PLAIN */ - } - *smtp_auth_plain = 0; - if (username != NULL) { - smtp_username = smtp_auth_plain + 1; - strcpy(smtp_username, username); - } - if (pass != NULL) { - smtp_pass = smtp_auth_plain + uname_len + 2; - strcpy(smtp_pass, pass); - } - smtp_auth_plain_len = uname_len + pass_len + 2; - - return ERR_OK; -} - -#if SMTP_BODYDH -static void smtp_free_struct(struct smtp_session *s) -{ - if (s->bodydh != NULL) { - SMTP_BODYDH_FREE(s->bodydh); - } - SMTP_STATE_FREE(s); -} -#else /* SMTP_BODYDH */ -#define smtp_free_struct(x) SMTP_STATE_FREE(x) -#endif /* SMTP_BODYDH */ - -static struct altcp_pcb* -smtp_setup_pcb(struct smtp_session *s, const ip_addr_t* remote_ip) -{ - struct altcp_pcb* pcb; - LWIP_UNUSED_ARG(remote_ip); - -#if LWIP_ALTCP && LWIP_ALTCP_TLS - if (smtp_server_tls_config) { - pcb = altcp_tls_new(smtp_server_tls_config, IP_GET_TYPE(remote_ip)); - } else -#endif - { - pcb = altcp_tcp_new_ip_type(IP_GET_TYPE(remote_ip)); - } - if (pcb != NULL) { - altcp_arg(pcb, s); - altcp_recv(pcb, smtp_tcp_recv); - altcp_err(pcb, smtp_tcp_err); - altcp_poll(pcb, smtp_tcp_poll, SMTP_POLL_INTERVAL); - altcp_sent(pcb, smtp_tcp_sent); - } - return pcb; -} - -/** The actual mail-sending function, called by smtp_send_mail and - * smtp_send_mail_static after setting up the struct smtp_session. - */ -static err_t -smtp_send_mail_alloced(struct smtp_session *s) -{ - err_t err; - struct altcp_pcb* pcb = NULL; - ip_addr_t addr; - - LWIP_ASSERT("no smtp_session supplied", s != NULL); - -#if SMTP_CHECK_DATA - /* check that body conforms to RFC: - * - convert all single-CR or -LF in body to CRLF - * - only 7-bit ASCII is allowed - */ - if (smtp_verify(s->to, s->to_len, 0) != ERR_OK) { - err = ERR_ARG; - goto leave; - } - if (smtp_verify(s->from, s->from_len, 0) != ERR_OK) { - err = ERR_ARG; - goto leave; - } - if (smtp_verify(s->subject, s->subject_len, 0) != ERR_OK) { - err = ERR_ARG; - goto leave; - } -#if SMTP_BODYDH - if (s->bodydh == NULL) -#endif /* SMTP_BODYDH */ - { - if (smtp_verify(s->body, s->body_len, 0) != ERR_OK) { - err = ERR_ARG; - goto leave; - } - } -#endif /* SMTP_CHECK_DATA */ - -#if SMTP_COPY_AUTHDATA - /* copy auth data, ensuring the first byte is always zero */ - MEMCPY(s->auth_plain + 1, smtp_auth_plain + 1, smtp_auth_plain_len - 1); - s->auth_plain_len = smtp_auth_plain_len; - /* default username and pass is empty string */ - s->username = s->auth_plain; - s->pass = s->auth_plain; - if (smtp_username != NULL) { - s->username += smtp_username - smtp_auth_plain; - } - if (smtp_pass != NULL) { - s->pass += smtp_pass - smtp_auth_plain; - } -#endif /* SMTP_COPY_AUTHDATA */ - - s->state = SMTP_NULL; - s->timer = SMTP_TIMEOUT; - -#if LWIP_DNS - err = dns_gethostbyname(smtp_server, &addr, smtp_dns_found, s); -#else /* LWIP_DNS */ - err = ipaddr_aton(smtp_server, &addr) ? ERR_OK : ERR_ARG; -#endif /* LWIP_DNS */ - if (err == ERR_OK) { - pcb = smtp_setup_pcb(s, &addr); - if (pcb == NULL) { - err = ERR_MEM; - goto leave; - } - err = altcp_connect(pcb, &addr, smtp_server_port, smtp_tcp_connected); - if (err != ERR_OK) { - LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, ("tcp_connect failed: %d\n", (int)err)); - goto deallocate_and_leave; - } - } else if (err != ERR_INPROGRESS) { - LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, ("dns_gethostbyname failed: %d\n", (int)err)); - goto deallocate_and_leave; - } - return ERR_OK; - -deallocate_and_leave: - if (pcb != NULL) { - altcp_arg(pcb, NULL); - altcp_close(pcb); - } -leave: - smtp_free_struct(s); - /* no need to call the callback here since we return != ERR_OK */ - return err; -} - -/** @ingroup smtp - * Send an email via the currently selected server, username and password. - * - * @param from source email address (must be NULL-terminated) - * @param to target email address (must be NULL-terminated) - * @param subject email subject (must be NULL-terminated) - * @param body email body (must be NULL-terminated) - * @param callback_fn callback function - * @param callback_arg user argument to callback_fn - * @returns - ERR_OK if structures were allocated and no error occured starting the connection - * (this does not mean the email has been successfully sent!) - * - another err_t on error. - */ -err_t -smtp_send_mail(const char* from, const char* to, const char* subject, const char* body, - smtp_result_fn callback_fn, void* callback_arg) -{ - struct smtp_session* s; - size_t from_len = strlen(from); - size_t to_len = strlen(to); - size_t subject_len = strlen(subject); - size_t body_len = strlen(body); - size_t mem_len = sizeof(struct smtp_session); - char *sfrom, *sto, *ssubject, *sbody; - - LWIP_ASSERT_CORE_LOCKED(); - - mem_len += from_len + to_len + subject_len + body_len + 4; - if (mem_len > 0xffff) { - /* too long! */ - return ERR_MEM; - } - - /* Allocate memory to keep this email's session state */ - s = (struct smtp_session *)SMTP_STATE_MALLOC((mem_size_t)mem_len); - if (s == NULL) { - return ERR_MEM; - } - /* initialize the structure */ - memset(s, 0, mem_len); - s->from = sfrom = (char*)s + sizeof(struct smtp_session); - s->from_len = (u16_t)from_len; - s->to = sto = sfrom + from_len + 1; - s->to_len = (u16_t)to_len; - s->subject = ssubject = sto + to_len + 1; - s->subject_len = (u16_t)subject_len; - s->body = sbody = ssubject + subject_len + 1; - s->body_len = (u16_t)body_len; - /* copy source and target email address */ - /* cast to size_t is a hack to cast away constness */ - MEMCPY(sfrom, from, from_len + 1); - MEMCPY(sto, to, to_len + 1); - MEMCPY(ssubject, subject, subject_len + 1); - MEMCPY(sbody, body, body_len + 1); - - s->callback_fn = callback_fn; - s->callback_arg = callback_arg; - - /* call the actual implementation of this function */ - return smtp_send_mail_alloced(s); -} - -/** @ingroup smtp - * Same as smtp_send_mail, but doesn't copy from, to, subject and body into - * an internal buffer to save memory. - * WARNING: the above data must stay untouched until the callback function is - * called (unless the function returns != ERR_OK) - */ -err_t -smtp_send_mail_static(const char *from, const char* to, const char* subject, - const char* body, smtp_result_fn callback_fn, void* callback_arg) -{ - struct smtp_session* s; - size_t len; - - LWIP_ASSERT_CORE_LOCKED(); - - s = (struct smtp_session*)SMTP_STATE_MALLOC(sizeof(struct smtp_session)); - if (s == NULL) { - return ERR_MEM; - } - memset(s, 0, sizeof(struct smtp_session)); - /* initialize the structure */ - s->from = from; - len = strlen(from); - LWIP_ASSERT("string is too long", len <= 0xffff); - s->from_len = (u16_t)len; - s->to = to; - len = strlen(to); - LWIP_ASSERT("string is too long", len <= 0xffff); - s->to_len = (u16_t)len; - s->subject = subject; - len = strlen(subject); - LWIP_ASSERT("string is too long", len <= 0xffff); - s->subject_len = (u16_t)len; - s->body = body; - len = strlen(body); - LWIP_ASSERT("string is too long", len <= 0xffff); - s->body_len = (u16_t)len; - s->callback_fn = callback_fn; - s->callback_arg = callback_arg; - /* call the actual implementation of this function */ - return smtp_send_mail_alloced(s); -} - - -/** @ingroup smtp - * Same as smtp_send_mail but takes a struct smtp_send_request as single - * parameter which contains all the other parameters. - * To be used with tcpip_callback to send mail from interrupt context or from - * another thread. - * - * WARNING: server and authentication must stay untouched until this function has run! - * - * Usage example: - * - allocate a struct smtp_send_request (in a way that is allowed in interrupt context) - * - fill the members of the struct as if calling smtp_send_mail - * - specify a callback_function - * - set callback_arg to the structure itself - * - call this function - * - wait for the callback function to be called - * - in the callback function, deallocate the structure (passed as arg) - */ -void -smtp_send_mail_int(void *arg) -{ - struct smtp_send_request *req = (struct smtp_send_request*)arg; - err_t err; - - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("smtp_send_mail_int: no argument given", arg != NULL); - - if (req->static_data) { - err = smtp_send_mail_static(req->from, req->to, req->subject, req->body, - req->callback_fn, req->callback_arg); - } else { - err = smtp_send_mail(req->from, req->to, req->subject, req->body, - req->callback_fn, req->callback_arg); - } - if ((err != ERR_OK) && (req->callback_fn != NULL)) { - req->callback_fn(req->callback_arg, SMTP_RESULT_ERR_UNKNOWN, 0, err); - } -} - -#if SMTP_CHECK_DATA -/** Verify that a given string conforms to the SMTP rules - * (7-bit only, no single CR or LF, - * @todo: no line consisting of a single dot only) - */ -static err_t -smtp_verify(const char *data, size_t data_len, u8_t linebreaks_allowed) -{ - size_t i; - u8_t last_was_cr = 0; - for (i = 0; i < data_len; i++) { - char current = data[i]; - if ((current & 0x80) != 0) { - LWIP_DEBUGF(SMTP_DEBUG_WARN, ("smtp_verify: no 8-bit data supported: %s\n", data)); - return ERR_ARG; - } - if (current == '\r') { - if (!linebreaks_allowed) { - LWIP_DEBUGF(SMTP_DEBUG_WARN, ("smtp_verify: found CR where no linebreaks allowed: %s\n", data)); - return ERR_ARG; - } - if (last_was_cr) { - LWIP_DEBUGF(SMTP_DEBUG_WARN, ("smtp_verify: found double CR: %s\n", data)); - return ERR_ARG; - } - last_was_cr = 1; - } else { - if (current == '\n') { - if (!last_was_cr) { - LWIP_DEBUGF(SMTP_DEBUG_WARN, ("smtp_verify: found LF without CR before: %s\n", data)); - return ERR_ARG; - } - } - last_was_cr = 0; - } - } - return ERR_OK; -} -#endif /* SMTP_CHECK_DATA */ - -/** Frees the smtp_session and calls the callback function */ -static void -smtp_free(struct smtp_session *s, u8_t result, u16_t srv_err, err_t err) -{ - smtp_result_fn fn = s->callback_fn; - void *arg = s->callback_arg; - if (s->p != NULL) { - pbuf_free(s->p); - } - smtp_free_struct(s); - if (fn != NULL) { - fn(arg, result, srv_err, err); - } -} - -/** Try to close a pcb and free the arg if successful */ -static void -smtp_close(struct smtp_session *s, struct altcp_pcb *pcb, u8_t result, - u16_t srv_err, err_t err) -{ - if (pcb != NULL) { - altcp_arg(pcb, NULL); - if (altcp_close(pcb) == ERR_OK) { - if (s != NULL) { - smtp_free(s, result, srv_err, err); - } - } else { - /* close failed, set back arg */ - altcp_arg(pcb, s); - } - } else { - if (s != NULL) { - smtp_free(s, result, srv_err, err); - } - } -} - -/** Raw API TCP err callback: pcb is already deallocated */ -static void -smtp_tcp_err(void *arg, err_t err) -{ - LWIP_UNUSED_ARG(err); - if (arg != NULL) { - LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, ("smtp_tcp_err: connection reset by remote host\n")); - smtp_free((struct smtp_session*)arg, SMTP_RESULT_ERR_CLOSED, 0, err); - } -} - -/** Raw API TCP poll callback */ -static err_t -smtp_tcp_poll(void *arg, struct altcp_pcb *pcb) -{ - if (arg != NULL) { - struct smtp_session *s = (struct smtp_session*)arg; - if (s->timer != 0) { - s->timer--; - } - } - smtp_process(arg, pcb, NULL); - return ERR_OK; -} - -/** Raw API TCP sent callback */ -static err_t -smtp_tcp_sent(void *arg, struct altcp_pcb *pcb, u16_t len) -{ - LWIP_UNUSED_ARG(len); - - smtp_process(arg, pcb, NULL); - - return ERR_OK; -} - -/** Raw API TCP recv callback */ -static err_t -smtp_tcp_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t err) -{ - LWIP_UNUSED_ARG(err); - if (p != NULL) { - altcp_recved(pcb, p->tot_len); - smtp_process(arg, pcb, p); - } else { - LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, ("smtp_tcp_recv: connection closed by remote host\n")); - smtp_close((struct smtp_session*)arg, pcb, SMTP_RESULT_ERR_CLOSED, 0, err); - } - return ERR_OK; -} - -static err_t -smtp_tcp_connected(void *arg, struct altcp_pcb *pcb, err_t err) -{ - LWIP_UNUSED_ARG(arg); - - if (err == ERR_OK) { - LWIP_DEBUGF(SMTP_DEBUG_STATE, ("smtp_connected: Waiting for 220\n")); - } else { - /* shouldn't happen, but we still check 'err', only to be sure */ - LWIP_DEBUGF(SMTP_DEBUG_WARN, ("smtp_connected: %d\n", (int)err)); - smtp_close((struct smtp_session*)arg, pcb, SMTP_RESULT_ERR_CONNECT, 0, err); - } - return ERR_OK; -} - -#if LWIP_DNS -/** DNS callback - * If ipaddr is non-NULL, resolving succeeded, otherwise it failed. - */ -static void -smtp_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg) -{ - struct smtp_session *s = (struct smtp_session*)arg; - struct altcp_pcb *pcb; - err_t err; - u8_t result; - - LWIP_UNUSED_ARG(hostname); - - if (ipaddr != NULL) { - pcb = smtp_setup_pcb(s, ipaddr); - if (pcb != NULL) { - LWIP_DEBUGF(SMTP_DEBUG_STATE, ("smtp_dns_found: hostname resolved, connecting\n")); - err = altcp_connect(pcb, ipaddr, smtp_server_port, smtp_tcp_connected); - if (err == ERR_OK) { - return; - } - LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, ("tcp_connect failed: %d\n", (int)err)); - result = SMTP_RESULT_ERR_CONNECT; - } else { - LWIP_DEBUGF(SMTP_DEBUG_STATE, ("smtp_dns_found: failed to allocate tcp pcb\n")); - result = SMTP_RESULT_ERR_MEM; - err = ERR_MEM; - } - } else { - LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, ("smtp_dns_found: failed to resolve hostname: %s\n", - hostname)); - pcb = NULL; - result = SMTP_RESULT_ERR_HOSTNAME; - err = ERR_ARG; - } - smtp_close(s, pcb, result, 0, err); -} -#endif /* LWIP_DNS */ - -#if SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN - -/** Table 6-bit-index-to-ASCII used for base64-encoding */ -static const char base64_table[] = { - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', - 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - '+', '/' -}; - -/** Base64 encoding */ -static size_t -smtp_base64_encode(char* target, size_t target_len, const char* source, size_t source_len) -{ - size_t i; - s8_t j; - size_t target_idx = 0; - size_t longer = (source_len % 3) ? (3 - (source_len % 3)) : 0; - size_t source_len_b64 = source_len + longer; - size_t len = (((source_len_b64) * 4) / 3); - u8_t x = 5; - u8_t current = 0; - LWIP_UNUSED_ARG(target_len); - - LWIP_ASSERT("target_len is too short", target_len >= len); - - for (i = 0; i < source_len_b64; i++) { - u8_t b = (i < source_len ? (u8_t)source[i] : 0); - for (j = 7; j >= 0; j--, x--) { - if ((b & (1 << j)) != 0) { - current = (u8_t)(current | (1U << x)); - } - if (x == 0) { - target[target_idx++] = base64_table[current]; - x = 6; - current = 0; - } - } - } - for (i = len - longer; i < len; i++) { - target[i] = '='; - } - return len; -} -#endif /* SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN */ - -/** Parse pbuf to see if it contains the beginning of an answer. - * If so, it returns the contained response code as number between 1 and 999. - * If not, zero is returned. - * - * @param s smtp session struct - */ -static u16_t -smtp_is_response(struct smtp_session *s) -{ - char digits[4]; - long num; - - if (s->p == NULL) { - return 0; - } - /* copy three digits and convert them to int */ - if (pbuf_copy_partial(s->p, digits, 3, 0) != 3) { - /* pbuf was too short */ - return 0; - } - digits[3] = 0; - num = strtol(digits, NULL, 10); - if ((num <= 0) || (num >= 1000)) { - /* failed to find response code at start of line */ - return 0; - } - return (u16_t)num; -} - -/** Parse pbuf to see if it contains a fully received answer. - * If one is found, ERR_OK is returned. - * If none is found, ERR_VAL is returned. - * - * A fully received answer is a 3-digit number followed by a space, - * some string and a CRLF as line ending. - * - * @param s smtp session struct - */ -static err_t -smtp_is_response_finished(struct smtp_session *s) -{ - u8_t sp; - u16_t crlf; - u16_t offset; - - if (s->p == NULL) { - return ERR_VAL; - } - offset = 0; -again: - /* We could check the response number here, but we trust the - * protocol definition which says the client can rely on it being - * the same on every line. */ - - /* find CRLF */ - if (offset > 0xFFFF - 4) { - /* would overflow */ - return ERR_VAL; - } - crlf = pbuf_memfind(s->p, SMTP_CRLF, SMTP_CRLF_LEN, (u16_t)(offset + 4)); - if (crlf == 0xFFFF) { - /* no CRLF found */ - return ERR_VAL; - } - sp = pbuf_get_at(s->p, (u16_t)(offset + 3)); - if (sp == '-') { - /* no space after response code -> try next line */ - offset = (u16_t)(crlf + 2); - if (offset < crlf) { - /* overflow */ - return ERR_VAL; - } - goto again; - } else if (sp == ' ') { - /* CRLF found after response code + space -> valid response */ - return ERR_OK; - } - /* sp contains invalid character */ - return ERR_VAL; -} - -/** Prepare HELO/EHLO message */ -static enum smtp_session_state -smtp_prepare_helo(struct smtp_session *s, u16_t *tx_buf_len, struct altcp_pcb *pcb) -{ - size_t ipa_len; - const char *ipa = ipaddr_ntoa(altcp_get_ip(pcb, 1)); - LWIP_ASSERT("ipaddr_ntoa returned NULL", ipa != NULL); - ipa_len = strlen(ipa); - LWIP_ASSERT("string too long", ipa_len <= (SMTP_TX_BUF_LEN-SMTP_CMD_EHLO_1_LEN-SMTP_CMD_EHLO_2_LEN)); - - *tx_buf_len = (u16_t)(SMTP_CMD_EHLO_1_LEN + (u16_t)ipa_len + SMTP_CMD_EHLO_2_LEN); - LWIP_ASSERT("tx_buf overflow detected", *tx_buf_len <= SMTP_TX_BUF_LEN); - - SMEMCPY(s->tx_buf, SMTP_CMD_EHLO_1, SMTP_CMD_EHLO_1_LEN); - MEMCPY(&s->tx_buf[SMTP_CMD_EHLO_1_LEN], ipa, ipa_len); - SMEMCPY(&s->tx_buf[SMTP_CMD_EHLO_1_LEN + ipa_len], SMTP_CMD_EHLO_2, SMTP_CMD_EHLO_2_LEN); - return SMTP_HELO; -} - -#if SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN -/** Parse last server response (in rx_buf) for supported authentication method, - * create data to send out (to tx_buf), set tx_data_len correctly - * and return the next state. - */ -static enum smtp_session_state -smtp_prepare_auth_or_mail(struct smtp_session *s, u16_t *tx_buf_len) -{ - /* check response for supported authentication method */ - u16_t auth = pbuf_strstr(s->p, SMTP_KEYWORD_AUTH_SP); - if (auth == 0xFFFF) { - auth = pbuf_strstr(s->p, SMTP_KEYWORD_AUTH_EQ); - } - if (auth != 0xFFFF) { - u16_t crlf = pbuf_memfind(s->p, SMTP_CRLF, SMTP_CRLF_LEN, auth); - if ((crlf != 0xFFFF) && (crlf > auth)) { - /* use tx_buf temporarily */ - u16_t copied = pbuf_copy_partial(s->p, s->tx_buf, (u16_t)(crlf - auth), auth); - if (copied != 0) { - char *sep = s->tx_buf + SMTP_KEYWORD_AUTH_LEN; - s->tx_buf[copied] = 0; -#if SMTP_SUPPORT_AUTH_PLAIN - /* favour PLAIN over LOGIN since it involves less requests */ - if (strstr(sep, SMTP_AUTH_PARAM_PLAIN) != NULL) { - size_t auth_len; - /* server supports AUTH PLAIN */ - SMEMCPY(s->tx_buf, SMTP_CMD_AUTHPLAIN_1, SMTP_CMD_AUTHPLAIN_1_LEN); - - /* add base64-encoded string "\0username\0password" */ - auth_len = smtp_base64_encode(&s->tx_buf[SMTP_CMD_AUTHPLAIN_1_LEN], - SMTP_TX_BUF_LEN - SMTP_CMD_AUTHPLAIN_1_LEN, SMTP_AUTH_PLAIN_DATA(s), - SMTP_AUTH_PLAIN_LEN(s)); - LWIP_ASSERT("string too long", auth_len <= (SMTP_TX_BUF_LEN-SMTP_CMD_AUTHPLAIN_1_LEN-SMTP_CMD_AUTHPLAIN_2_LEN)); - *tx_buf_len = (u16_t)(SMTP_CMD_AUTHPLAIN_1_LEN + SMTP_CMD_AUTHPLAIN_2_LEN + (u16_t)auth_len); - SMEMCPY(&s->tx_buf[SMTP_CMD_AUTHPLAIN_1_LEN + auth_len], SMTP_CMD_AUTHPLAIN_2, - SMTP_CMD_AUTHPLAIN_2_LEN); - return SMTP_AUTH_PLAIN; - } else -#endif /* SMTP_SUPPORT_AUTH_PLAIN */ - { -#if SMTP_SUPPORT_AUTH_LOGIN - if (strstr(sep, SMTP_AUTH_PARAM_LOGIN) != NULL) { - /* server supports AUTH LOGIN */ - *tx_buf_len = SMTP_CMD_AUTHLOGIN_LEN; - SMEMCPY(s->tx_buf, SMTP_CMD_AUTHLOGIN, SMTP_CMD_AUTHLOGIN_LEN); - return SMTP_AUTH_LOGIN_UNAME; - } -#endif /* SMTP_SUPPORT_AUTH_LOGIN */ - } - } - } - } - /* server didnt's send correct keywords for AUTH, try sending directly */ - return smtp_prepare_mail(s, tx_buf_len); -} -#endif /* SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN */ - -#if SMTP_SUPPORT_AUTH_LOGIN -/** Send base64-encoded username */ -static enum smtp_session_state -smtp_prepare_auth_login_uname(struct smtp_session *s, u16_t *tx_buf_len) -{ - size_t base64_len = smtp_base64_encode(s->tx_buf, SMTP_TX_BUF_LEN, - SMTP_USERNAME(s), strlen(SMTP_USERNAME(s))); - /* @todo: support base64-encoded longer than 64k */ - LWIP_ASSERT("string too long", base64_len <= 0xffff); - LWIP_ASSERT("tx_buf overflow detected", base64_len <= SMTP_TX_BUF_LEN - SMTP_CRLF_LEN); - *tx_buf_len = (u16_t)(base64_len + SMTP_CRLF_LEN); - - SMEMCPY(&s->tx_buf[base64_len], SMTP_CRLF, SMTP_CRLF_LEN); - s->tx_buf[*tx_buf_len] = 0; - return SMTP_AUTH_LOGIN_PASS; -} - -/** Send base64-encoded password */ -static enum smtp_session_state -smtp_prepare_auth_login_pass(struct smtp_session *s, u16_t *tx_buf_len) -{ - size_t base64_len = smtp_base64_encode(s->tx_buf, SMTP_TX_BUF_LEN, - SMTP_PASS(s), strlen(SMTP_PASS(s))); - /* @todo: support base64-encoded longer than 64k */ - LWIP_ASSERT("string too long", base64_len <= 0xffff); - LWIP_ASSERT("tx_buf overflow detected", base64_len <= SMTP_TX_BUF_LEN - SMTP_CRLF_LEN); - *tx_buf_len = (u16_t)(base64_len + SMTP_CRLF_LEN); - - SMEMCPY(&s->tx_buf[base64_len], SMTP_CRLF, SMTP_CRLF_LEN); - s->tx_buf[*tx_buf_len] = 0; - return SMTP_AUTH_LOGIN; -} -#endif /* SMTP_SUPPORT_AUTH_LOGIN */ - -/** Prepare MAIL message */ -static enum smtp_session_state -smtp_prepare_mail(struct smtp_session *s, u16_t *tx_buf_len) -{ - char *target = s->tx_buf; - LWIP_ASSERT("tx_buf overflow detected", s->from_len <= (SMTP_TX_BUF_LEN - SMTP_CMD_MAIL_1_LEN - SMTP_CMD_MAIL_2_LEN)); - *tx_buf_len = (u16_t)(SMTP_CMD_MAIL_1_LEN + SMTP_CMD_MAIL_2_LEN + s->from_len); - target[*tx_buf_len] = 0; - - SMEMCPY(target, SMTP_CMD_MAIL_1, SMTP_CMD_MAIL_1_LEN); - target += SMTP_CMD_MAIL_1_LEN; - MEMCPY(target, s->from, s->from_len); - target += s->from_len; - SMEMCPY(target, SMTP_CMD_MAIL_2, SMTP_CMD_MAIL_2_LEN); - return SMTP_MAIL; -} - -/** Prepare RCPT message */ -static enum smtp_session_state -smtp_prepare_rcpt(struct smtp_session *s, u16_t *tx_buf_len) -{ - char *target = s->tx_buf; - LWIP_ASSERT("tx_buf overflow detected", s->to_len <= (SMTP_TX_BUF_LEN - SMTP_CMD_RCPT_1_LEN - SMTP_CMD_RCPT_2_LEN)); - *tx_buf_len = (u16_t)(SMTP_CMD_RCPT_1_LEN + SMTP_CMD_RCPT_2_LEN + s->to_len); - target[*tx_buf_len] = 0; - - SMEMCPY(target, SMTP_CMD_RCPT_1, SMTP_CMD_RCPT_1_LEN); - target += SMTP_CMD_RCPT_1_LEN; - MEMCPY(target, s->to, s->to_len); - target += s->to_len; - SMEMCPY(target, SMTP_CMD_RCPT_2, SMTP_CMD_RCPT_2_LEN); - return SMTP_RCPT; -} - -/** Prepare header of body */ -static enum smtp_session_state -smtp_prepare_header(struct smtp_session *s, u16_t *tx_buf_len) -{ - char *target = s->tx_buf; - int len = SMTP_CMD_HEADER_1_LEN + SMTP_CMD_HEADER_2_LEN + - SMTP_CMD_HEADER_3_LEN + SMTP_CMD_HEADER_4_LEN + s->from_len + s->to_len + - s->subject_len; - LWIP_ASSERT("tx_buf overflow detected", len > 0 && len <= SMTP_TX_BUF_LEN); - *tx_buf_len = (u16_t)len; - target[*tx_buf_len] = 0; - - SMEMCPY(target, SMTP_CMD_HEADER_1, SMTP_CMD_HEADER_1_LEN); - target += SMTP_CMD_HEADER_1_LEN; - MEMCPY(target, s->from, s->from_len); - target += s->from_len; - SMEMCPY(target, SMTP_CMD_HEADER_2, SMTP_CMD_HEADER_2_LEN); - target += SMTP_CMD_HEADER_2_LEN; - MEMCPY(target, s->to, s->to_len); - target += s->to_len; - SMEMCPY(target, SMTP_CMD_HEADER_3, SMTP_CMD_HEADER_3_LEN); - target += SMTP_CMD_HEADER_3_LEN; - MEMCPY(target, s->subject, s->subject_len); - target += s->subject_len; - SMEMCPY(target, SMTP_CMD_HEADER_4, SMTP_CMD_HEADER_4_LEN); - - return SMTP_BODY; -} - -/** Prepare QUIT message */ -static enum smtp_session_state -smtp_prepare_quit(struct smtp_session *s, u16_t *tx_buf_len) -{ - *tx_buf_len = SMTP_CMD_QUIT_LEN; - s->tx_buf[*tx_buf_len] = 0; - SMEMCPY(s->tx_buf, SMTP_CMD_QUIT, SMTP_CMD_QUIT_LEN); - LWIP_ASSERT("tx_buf overflow detected", *tx_buf_len <= SMTP_TX_BUF_LEN); - return SMTP_CLOSED; -} - -/** If in state SMTP_BODY, try to send more body data */ -static void -smtp_send_body(struct smtp_session *s, struct altcp_pcb *pcb) -{ - err_t err; - - if (s->state == SMTP_BODY) { -#if SMTP_BODYDH - if (s->bodydh) { - smtp_send_body_data_handler(s, pcb); - } else -#endif /* SMTP_BODYDH */ - { - u16_t send_len = (u16_t)(s->body_len - s->body_sent); - if (send_len > 0) { - u16_t snd_buf = altcp_sndbuf(pcb); - if (send_len > snd_buf) { - send_len = snd_buf; - } - if (send_len > 0) { - /* try to send something out */ - err = altcp_write(pcb, &s->body[s->body_sent], (u16_t)send_len, TCP_WRITE_FLAG_COPY); - if (err == ERR_OK) { - s->timer = SMTP_TIMEOUT_DATABLOCK; - s->body_sent = (u16_t)(s->body_sent + send_len); - if (s->body_sent < s->body_len) { - LWIP_DEBUGF(SMTP_DEBUG_STATE, ("smtp_send_body: %d of %d bytes written\n", - s->body_sent, s->body_len)); - } - } - } - } - } - if (s->body_sent == s->body_len) { - /* the whole body has been written, write last line */ - LWIP_DEBUGF(SMTP_DEBUG_STATE, ("smtp_send_body: body completely written (%d bytes), appending end-of-body\n", - s->body_len)); - err = altcp_write(pcb, SMTP_CMD_BODY_FINISHED, SMTP_CMD_BODY_FINISHED_LEN, 0); - if (err == ERR_OK) { - s->timer = SMTP_TIMEOUT_DATATERM; - LWIP_DEBUGF(SMTP_DEBUG_STATE, ("smtp_send_body: end-of-body written, changing state to %s\n", - smtp_state_str[SMTP_QUIT])); - /* last line written, change state, wait for confirmation */ - s->state = SMTP_QUIT; - } - } - } -} - -/** State machine-like implementation of an SMTP client. - */ -static void -smtp_process(void *arg, struct altcp_pcb *pcb, struct pbuf *p) -{ - struct smtp_session* s = (struct smtp_session*)arg; - u16_t response_code = 0; - u16_t tx_buf_len = 0; - enum smtp_session_state next_state; - - if (arg == NULL) { - /* already closed SMTP connection */ - if (p != NULL) { - LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("Received %d bytes after closing: %s\n", - p->tot_len, smtp_pbuf_str(p))); - pbuf_free(p); - } - return; - } - - next_state = s->state; - - if (p != NULL) { - /* received data */ - if (s->p == NULL) { - s->p = p; - } else { - pbuf_cat(s->p, p); - } - } else { - /* idle timer, close connection if timed out */ - if (s->timer == 0) { - LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, ("smtp_process: connection timed out, closing\n")); - smtp_close(s, pcb, SMTP_RESULT_ERR_TIMEOUT, 0, ERR_TIMEOUT); - return; - } - if (s->state == SMTP_BODY) { - smtp_send_body(s, pcb); - return; - } - } - response_code = smtp_is_response(s); - if (response_code) { - LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("smtp_process: received response code: %d\n", response_code)); - if (smtp_is_response_finished(s) != ERR_OK) { - LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("smtp_process: partly received response code: %d\n", response_code)); - /* wait for next packet to complete the respone */ - return; - } - } else { - if (s->p != NULL) { - LWIP_DEBUGF(SMTP_DEBUG_WARN, ("smtp_process: unknown data received (%s)\n", - smtp_pbuf_str(s->p))); - pbuf_free(s->p); - s->p = NULL; - } - return; - } - - switch(s->state) - { - case(SMTP_NULL): - /* wait for 220 */ - if (response_code == 220) { - /* then send EHLO */ - next_state = smtp_prepare_helo(s, &tx_buf_len, pcb); - } - break; - case(SMTP_HELO): - /* wait for 250 */ - if (response_code == 250) { -#if SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN - /* then send AUTH or MAIL */ - next_state = smtp_prepare_auth_or_mail(s, &tx_buf_len); - } - break; - case(SMTP_AUTH_LOGIN): - case(SMTP_AUTH_PLAIN): - /* wait for 235 */ - if (response_code == 235) { -#endif /* SMTP_SUPPORT_AUTH_PLAIN || SMTP_SUPPORT_AUTH_LOGIN */ - /* send MAIL */ - next_state = smtp_prepare_mail(s, &tx_buf_len); - } - break; -#if SMTP_SUPPORT_AUTH_LOGIN - case(SMTP_AUTH_LOGIN_UNAME): - /* wait for 334 Username */ - if (response_code == 334) { - if (pbuf_strstr(s->p, SMTP_RESP_LOGIN_UNAME) != 0xFFFF) { - /* send username */ - next_state = smtp_prepare_auth_login_uname(s, &tx_buf_len); - } - } - break; - case(SMTP_AUTH_LOGIN_PASS): - /* wait for 334 Password */ - if (response_code == 334) { - if (pbuf_strstr(s->p, SMTP_RESP_LOGIN_PASS) != 0xFFFF) { - /* send username */ - next_state = smtp_prepare_auth_login_pass(s, &tx_buf_len); - } - } - break; -#endif /* SMTP_SUPPORT_AUTH_LOGIN */ - case(SMTP_MAIL): - /* wait for 250 */ - if (response_code == 250) { - /* send RCPT */ - next_state = smtp_prepare_rcpt(s, &tx_buf_len); - } - break; - case(SMTP_RCPT): - /* wait for 250 */ - if (response_code == 250) { - /* send DATA */ - SMEMCPY(s->tx_buf, SMTP_CMD_DATA, SMTP_CMD_DATA_LEN); - tx_buf_len = SMTP_CMD_DATA_LEN; - next_state = SMTP_DATA; - } - break; - case(SMTP_DATA): - /* wait for 354 */ - if (response_code == 354) { - /* send email header */ - next_state = smtp_prepare_header(s, &tx_buf_len); - } - break; - case(SMTP_BODY): - /* nothing to be done here, handled somewhere else */ - break; - case(SMTP_QUIT): - /* wait for 250 */ - if (response_code == 250) { - /* send QUIT */ - next_state = smtp_prepare_quit(s, &tx_buf_len); - } - break; - case(SMTP_CLOSED): - /* nothing to do, wait for connection closed from server */ - return; - default: - LWIP_DEBUGF(SMTP_DEBUG_SERIOUS, ("Invalid state: %d/%s\n", (int)s->state, - smtp_state_str[s->state])); - break; - } - if (s->state == next_state) { - LWIP_DEBUGF(SMTP_DEBUG_WARN_STATE, ("smtp_process[%s]: unexpected response_code, closing: %d (%s)\n", - smtp_state_str[s->state], response_code, smtp_pbuf_str(s->p))); - /* close connection */ - smtp_close(s, pcb, SMTP_RESULT_ERR_SVR_RESP, response_code, ERR_OK); - return; - } - if (tx_buf_len > 0) { - SMTP_TX_BUF_MAX(tx_buf_len); - if (altcp_write(pcb, s->tx_buf, tx_buf_len, TCP_WRITE_FLAG_COPY) == ERR_OK) { - LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("smtp_process[%s]: received command %d (%s)\n", - smtp_state_str[s->state], response_code, smtp_pbuf_str(s->p))); - LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("smtp_process[%s]: sent %"U16_F" bytes: \"%s\"\n", - smtp_state_str[s->state], tx_buf_len, s->tx_buf)); - s->timer = SMTP_TIMEOUT; - pbuf_free(s->p); - s->p = NULL; - LWIP_DEBUGF(SMTP_DEBUG_STATE, ("smtp_process: changing state from %s to %s\n", - smtp_state_str[s->state], smtp_state_str[next_state])); - s->state = next_state; - if (next_state == SMTP_BODY) { - /* try to stream-send body data right now */ - smtp_send_body(s, pcb); - } else if (next_state == SMTP_CLOSED) { - /* sent out all data, delete structure */ - altcp_arg(pcb, NULL); - smtp_free(s, SMTP_RESULT_OK, 0, ERR_OK); - } - } - } -} - -#if SMTP_BODYDH -/** Elementary sub-function to send data - * - * @returns: BDHALLDATASENT all data has been written - * BDHSOMEDATASENT some data has been written - * 0 no data has been written - */ -static int -smtp_send_bodyh_data(struct altcp_pcb *pcb, const char **from, u16_t *howmany) -{ - err_t err; - u16_t len = *howmany; - - len = (u16_t)LWIP_MIN(len, altcp_sndbuf(pcb)); - err = altcp_write(pcb, *from, len, TCP_WRITE_FLAG_COPY); - if (err == ERR_OK) { - *from += len; - if ((*howmany -= len) > 0) { - return BDHSOMEDATASENT; - } - return BDHALLDATASENT; - } - return 0; -} - -/** Same as smtp_send_mail_static, but uses a callback function to send body data - */ -err_t -smtp_send_mail_bodycback(const char *from, const char* to, const char* subject, - smtp_bodycback_fn bodycback_fn, smtp_result_fn callback_fn, void* callback_arg) -{ - struct smtp_session* s; - size_t len; - - LWIP_ASSERT_CORE_LOCKED(); - - s = (struct smtp_session*)SMTP_STATE_MALLOC(sizeof(struct smtp_session)); - if (s == NULL) { - return ERR_MEM; - } - memset(s, 0, sizeof(struct smtp_session)); - s->bodydh = (struct smtp_bodydh_state*)SMTP_BODYDH_MALLOC(sizeof(struct smtp_bodydh_state)); - if (s->bodydh == NULL) { - SMTP_STATE_FREE(s); - return ERR_MEM; - } - memset(s->bodydh, 0, sizeof(struct smtp_bodydh_state)); - /* initialize the structure */ - s->from = from; - len = strlen(from); - LWIP_ASSERT("string is too long", len <= 0xffff); - s->from_len = (u16_t)len; - s->to = to; - len = strlen(to); - LWIP_ASSERT("string is too long", len <= 0xffff); - s->to_len = (u16_t)len; - s->subject = subject; - len = strlen(subject); - LWIP_ASSERT("string is too long", len <= 0xffff); - s->subject_len = (u16_t)len; - s->body = NULL; - LWIP_ASSERT("string is too long", len <= 0xffff); - s->callback_fn = callback_fn; - s->callback_arg = callback_arg; - s->bodydh->callback_fn = bodycback_fn; - s->bodydh->state = BDH_SENDING; - /* call the actual implementation of this function */ - return smtp_send_mail_alloced(s); -} - -static void -smtp_send_body_data_handler(struct smtp_session *s, struct altcp_pcb *pcb) -{ - struct smtp_bodydh_state *bdh; - int res = 0, ret; - LWIP_ASSERT("s != NULL", s != NULL); - bdh = s->bodydh; - LWIP_ASSERT("bodydh != NULL", bdh != NULL); - - /* resume any leftovers from prior memory constraints */ - if (s->body_len) { - LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("smtp_send_body_data_handler: resume\n")); - if((res = smtp_send_bodyh_data(pcb, (const char **)&s->body, &s->body_len)) - != BDHALLDATASENT) { - s->body_sent = s->body_len - 1; - return; - } - } - ret = res; - /* all data on buffer has been queued, resume execution */ - if (bdh->state == BDH_SENDING) { - LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("smtp_send_body_data_handler: run\n")); - do { - ret |= res; /* remember if we once queued something to send */ - bdh->exposed.length = 0; - if (bdh->callback_fn(s->callback_arg, &bdh->exposed) == BDH_DONE) { - bdh->state = BDH_STOP; - } - s->body = bdh->exposed.buffer; - s->body_len = bdh->exposed.length; - LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("smtp_send_body_data_handler: trying to send %u bytes\n", (unsigned int)s->body_len)); - } while (s->body_len && - ((res = smtp_send_bodyh_data(pcb, (const char **)&s->body, &s->body_len)) == BDHALLDATASENT) - && (bdh->state != BDH_STOP)); - } - if ((bdh->state != BDH_SENDING) && (ret != BDHSOMEDATASENT)) { - LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("smtp_send_body_data_handler: stop\n")); - s->body_sent = s->body_len; - } else { - LWIP_DEBUGF(SMTP_DEBUG_TRACE, ("smtp_send_body_data_handler: pause\n")); - s->body_sent = s->body_len - 1; - } -} -#endif /* SMTP_BODYDH */ - -#endif /* LWIP_TCP && LWIP_CALLBACK_API */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_asn1.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_asn1.c deleted file mode 100644 index 6df34dbd6..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_asn1.c +++ /dev/null @@ -1,704 +0,0 @@ -/** - * @file - * Abstract Syntax Notation One (ISO 8824, 8825) encoding - * - * @todo not optimised (yet), favor correctness over speed, favor speed over size - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "snmp_asn1.h" - -#define PBUF_OP_EXEC(code) \ - if ((code) != ERR_OK) { \ - return ERR_BUF; \ - } - -/** - * Encodes a TLV into a pbuf stream. - * - * @param pbuf_stream points to a pbuf stream - * @param tlv TLV to encode - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - */ -err_t -snmp_ans1_enc_tlv(struct snmp_pbuf_stream *pbuf_stream, struct snmp_asn1_tlv *tlv) -{ - u8_t data; - u8_t length_bytes_required; - - /* write type */ - if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) { - /* extended format is not used by SNMP so we do not accept those values */ - return ERR_ARG; - } - if (tlv->type_len != 0) { - /* any other value as auto is not accepted for type (we always use one byte because extended syntax is prohibited) */ - return ERR_ARG; - } - - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, tlv->type)); - tlv->type_len = 1; - - /* write length */ - if (tlv->value_len <= 127) { - length_bytes_required = 1; - } else if (tlv->value_len <= 255) { - length_bytes_required = 2; - } else { - length_bytes_required = 3; - } - - /* check for forced min length */ - if (tlv->length_len > 0) { - if (tlv->length_len < length_bytes_required) { - /* unable to code requested length in requested number of bytes */ - return ERR_ARG; - } - - length_bytes_required = tlv->length_len; - } else { - tlv->length_len = length_bytes_required; - } - - if (length_bytes_required > 1) { - /* multi byte representation required */ - length_bytes_required--; - data = 0x80 | length_bytes_required; /* extended length definition, 1 length byte follows */ - - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); - - while (length_bytes_required > 1) { - if (length_bytes_required == 2) { - /* append high byte */ - data = (u8_t)(tlv->value_len >> 8); - } else { - /* append leading 0x00 */ - data = 0x00; - } - - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); - length_bytes_required--; - } - } - - /* append low byte */ - data = (u8_t)(tlv->value_len & 0xFF); - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, data)); - - return ERR_OK; -} - -/** - * Encodes raw data (octet string, opaque) into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param raw_len raw data length - * @param raw points raw data - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - */ -err_t -snmp_asn1_enc_raw(struct snmp_pbuf_stream *pbuf_stream, const u8_t *raw, u16_t raw_len) -{ - PBUF_OP_EXEC(snmp_pbuf_stream_writebuf(pbuf_stream, raw, raw_len)); - - return ERR_OK; -} - -/** - * Encodes u32_t (counter, gauge, timeticks) into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) - * @param value is the host order u32_t value to be encoded - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - * - * @see snmp_asn1_enc_u32t_cnt() - */ -err_t -snmp_asn1_enc_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t octets_needed, u32_t value) -{ - if (octets_needed > 5) { - return ERR_ARG; - } - if (octets_needed == 5) { - /* not enough bits in 'value' add leading 0x00 */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); - octets_needed--; - } - - while (octets_needed > 1) { - octets_needed--; - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3)))); - } - - /* (only) one least significant octet */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value)); - - return ERR_OK; -} -/** - * Encodes s32_t integer into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param octets_needed encoding length (from snmp_asn1_enc_s32t_cnt()) - * @param value is the host order s32_t value to be encoded - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - * - * @see snmp_asn1_enc_s32t_cnt() - */ -err_t -snmp_asn1_enc_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t octets_needed, s32_t value) -{ - while (octets_needed > 1) { - octets_needed--; - - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3)))); - } - - /* (only) one least significant octet */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)value)); - - return ERR_OK; -} - -/** - * Encodes object identifier into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param oid points to object identifier array - * @param oid_len object identifier array length - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - */ -err_t -snmp_asn1_enc_oid(struct snmp_pbuf_stream *pbuf_stream, const u32_t *oid, u16_t oid_len) -{ - if (oid_len > 1) { - /* write compressed first two sub id's */ - u32_t compressed_byte = ((oid[0] * 40) + oid[1]); - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)compressed_byte)); - oid_len -= 2; - oid += 2; - } else { - /* @bug: allow empty varbinds for symmetry (we must decode them for getnext), allow partial compression?? */ - /* ident_len <= 1, at least we need zeroDotZero (0.0) (ident_len == 2) */ - return ERR_ARG; - } - - while (oid_len > 0) { - u32_t sub_id; - u8_t shift, tail; - - oid_len--; - sub_id = *oid; - tail = 0; - shift = 28; - while (shift > 0) { - u8_t code; - - code = (u8_t)(sub_id >> shift); - if ((code != 0) || (tail != 0)) { - tail = 1; - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, code | 0x80)); - } - shift -= 7; - } - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)sub_id & 0x7F)); - - /* proceed to next sub-identifier */ - oid++; - } - return ERR_OK; -} - -/** - * Returns octet count for length. - * - * @param length parameter length - * @param octets_needed points to the return value - */ -void -snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed) -{ - if (length < 0x80U) { - *octets_needed = 1; - } else if (length < 0x100U) { - *octets_needed = 2; - } else { - *octets_needed = 3; - } -} - -/** - * Returns octet count for an u32_t. - * - * @param value value to be encoded - * @param octets_needed points to the return value - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -void -snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed) -{ - if (value < 0x80UL) { - *octets_needed = 1; - } else if (value < 0x8000UL) { - *octets_needed = 2; - } else if (value < 0x800000UL) { - *octets_needed = 3; - } else if (value < 0x80000000UL) { - *octets_needed = 4; - } else { - *octets_needed = 5; - } -} - -/** - * Returns octet count for an s32_t. - * - * @param value value to be encoded - * @param octets_needed points to the return value - * - * @note ASN coded integers are _always_ signed. - */ -void -snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed) -{ - if (value < 0) { - value = ~value; - } - if (value < 0x80L) { - *octets_needed = 1; - } else if (value < 0x8000L) { - *octets_needed = 2; - } else if (value < 0x800000L) { - *octets_needed = 3; - } else { - *octets_needed = 4; - } -} - -/** - * Returns octet count for an object identifier. - * - * @param oid points to object identifier array - * @param oid_len object identifier array length - * @param octets_needed points to the return value - */ -void -snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed) -{ - u32_t sub_id; - - *octets_needed = 0; - if (oid_len > 1) { - /* compressed prefix in one octet */ - (*octets_needed)++; - oid_len -= 2; - oid += 2; - } - while (oid_len > 0) { - oid_len--; - sub_id = *oid; - - sub_id >>= 7; - (*octets_needed)++; - while (sub_id > 0) { - sub_id >>= 7; - (*octets_needed)++; - } - oid++; - } -} - -/** - * Decodes a TLV from a pbuf stream. - * - * @param pbuf_stream points to a pbuf stream - * @param tlv returns decoded TLV - * @return ERR_OK if successful, ERR_VAL if we can't decode - */ -err_t -snmp_asn1_dec_tlv(struct snmp_pbuf_stream *pbuf_stream, struct snmp_asn1_tlv *tlv) -{ - u8_t data; - - /* decode type first */ - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - tlv->type = data; - - if ((tlv->type & SNMP_ASN1_DATATYPE_MASK) == SNMP_ASN1_DATATYPE_EXTENDED) { - /* extended format is not used by SNMP so we do not accept those values */ - return ERR_VAL; - } - tlv->type_len = 1; - - /* now, decode length */ - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - if (data < 0x80) { /* short form */ - tlv->length_len = 1; - tlv->value_len = data; - } else if (data > 0x80) { /* long form */ - u8_t length_bytes = data - 0x80; - if (length_bytes > pbuf_stream->length) { - return ERR_VAL; - } - tlv->length_len = length_bytes + 1; /* this byte + defined number of length bytes following */ - tlv->value_len = 0; - - while (length_bytes > 0) { - /* we only support up to u16.maxvalue-1 (2 bytes) but have to accept leading zero bytes */ - if (tlv->value_len > 0xFF) { - return ERR_VAL; - } - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - tlv->value_len <<= 8; - tlv->value_len |= data; - - /* take care for special value used for indefinite length */ - if (tlv->value_len == 0xFFFF) { - return ERR_VAL; - } - - length_bytes--; - } - } else { /* data == 0x80 indefinite length form */ - /* (not allowed for SNMP; RFC 1157, 3.2.2) */ - return ERR_VAL; - } - - return ERR_OK; -} - -/** - * Decodes positive integer (counter, gauge, timeticks) into u32_t. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded integer field - * @param value return host order integer - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFF is preceded with 0x00 and the length is 5 octets!! - */ -err_t -snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value) -{ - u8_t data; - - if ((len > 0) && (len <= 5)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - /* expecting sign bit to be zero, only unsigned please! */ - if (((len == 5) && (data == 0x00)) || ((len < 5) && ((data & 0x80) == 0))) { - *value = data; - len--; - - while (len > 0) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - *value <<= 8; - *value |= data; - } - - return ERR_OK; - } - } - - return ERR_VAL; -} - -/** - * Decodes integer into s32_t. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded integer field - * @param value return host order integer - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - * - * @note ASN coded integers are _always_ signed! - */ -err_t -snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value) -{ - u8_t data; - - if ((len > 0) && (len < 5)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - if (data & 0x80) { - /* negative, start from -1 */ - *value = -1; - *value = (*value << 8) | data; - } else { - /* positive, start from 0 */ - *value = data; - } - len--; - /* shift in the remaining value */ - while (len > 0) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - *value = (*value << 8) | data; - len--; - } - return ERR_OK; - } - - return ERR_VAL; -} - -/** - * Decodes object identifier from incoming message into array of u32_t. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded object identifier - * @param oid return decoded object identifier - * @param oid_len return decoded object identifier length - * @param oid_max_len size of oid buffer - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - */ -err_t -snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *oid, u8_t *oid_len, u8_t oid_max_len) -{ - u32_t *oid_ptr; - u8_t data; - - *oid_len = 0; - oid_ptr = oid; - if (len > 0) { - if (oid_max_len < 2) { - return ERR_MEM; - } - - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - /* first compressed octet */ - if (data == 0x2B) { - /* (most) common case 1.3 (iso.org) */ - *oid_ptr = 1; - oid_ptr++; - *oid_ptr = 3; - oid_ptr++; - } else if (data < 40) { - *oid_ptr = 0; - oid_ptr++; - *oid_ptr = data; - oid_ptr++; - } else if (data < 80) { - *oid_ptr = 1; - oid_ptr++; - *oid_ptr = data - 40; - oid_ptr++; - } else { - *oid_ptr = 2; - oid_ptr++; - *oid_ptr = data - 80; - oid_ptr++; - } - *oid_len = 2; - } else { - /* accepting zero length identifiers e.g. for getnext operation. uncommon but valid */ - return ERR_OK; - } - - while ((len > 0) && (*oid_len < oid_max_len)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - if ((data & 0x80) == 0x00) { - /* sub-identifier uses single octet */ - *oid_ptr = data; - } else { - /* sub-identifier uses multiple octets */ - u32_t sub_id = (data & ~0x80); - while ((len > 0) && ((data & 0x80) != 0)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - len--; - - sub_id = (sub_id << 7) + (data & ~0x80); - } - - if ((data & 0x80) != 0) { - /* "more bytes following" bit still set at end of len */ - return ERR_VAL; - } - *oid_ptr = sub_id; - } - oid_ptr++; - (*oid_len)++; - } - - if (len > 0) { - /* OID to long to fit in our buffer */ - return ERR_MEM; - } - - return ERR_OK; -} - -/** - * Decodes (copies) raw data (ip-addresses, octet strings, opaque encoding) - * from incoming message into array. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded raw data (zero is valid, e.g. empty string!) - * @param buf return raw bytes - * @param buf_len returns length of the raw return value - * @param buf_max_len buffer size - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - */ -err_t -snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t *buf_len, u16_t buf_max_len) -{ - if (len > buf_max_len) { - /* not enough dst space */ - return ERR_MEM; - } - *buf_len = len; - - while (len > 0) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, buf)); - buf++; - len--; - } - - return ERR_OK; -} - -#if LWIP_HAVE_INT64 -/** - * Returns octet count for an u64_t. - * - * @param value value to be encoded - * @param octets_needed points to the return value - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFFFFFFFFFF is preceded with 0x00 and the length is 9 octets!! - */ -void -snmp_asn1_enc_u64t_cnt(u64_t value, u16_t *octets_needed) -{ - /* check if high u32 is 0 */ - if ((value >> 32) == 0) { - /* only low u32 is important */ - snmp_asn1_enc_u32t_cnt((u32_t)value, octets_needed); - } else { - /* low u32 does not matter for length determination */ - snmp_asn1_enc_u32t_cnt((u32_t)(value >> 32), octets_needed); - *octets_needed = *octets_needed + 4; /* add the 4 bytes of low u32 */ - } -} - -/** - * Decodes large positive integer (counter64) into 2x u32_t. - * - * @param pbuf_stream points to a pbuf stream - * @param len length of the coded integer field - * @param value return 64 bit integer - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) decode - * - * @note ASN coded integers are _always_ signed. E.g. +0xFFFF is coded - * as 0x00,0xFF,0xFF. Note the leading sign octet. A positive value - * of 0xFFFFFFFFFFFFFFFF is preceded with 0x00 and the length is 9 octets!! - */ -err_t -snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u64_t *value) -{ - u8_t data; - - if ((len > 0) && (len <= 9)) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - - /* expecting sign bit to be zero, only unsigned please! */ - if (((len == 9) && (data == 0x00)) || ((len < 9) && ((data & 0x80) == 0))) { - *value = data; - len--; - - while (len > 0) { - PBUF_OP_EXEC(snmp_pbuf_stream_read(pbuf_stream, &data)); - *value <<= 8; - *value |= data; - len--; - } - - return ERR_OK; - } - } - - return ERR_VAL; -} - -/** - * Encodes u64_t (counter64) into a pbuf chained ASN1 msg. - * - * @param pbuf_stream points to a pbuf stream - * @param octets_needed encoding length (from snmp_asn1_enc_u32t_cnt()) - * @param value is the value to be encoded - * @return ERR_OK if successful, ERR_ARG if we can't (or won't) encode - * - * @see snmp_asn1_enc_u64t_cnt() - */ -err_t -snmp_asn1_enc_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t octets_needed, u64_t value) -{ - if (octets_needed > 9) { - return ERR_ARG; - } - if (octets_needed == 9) { - /* not enough bits in 'value' add leading 0x00 */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, 0x00)); - octets_needed--; - } - - while (octets_needed > 1) { - octets_needed--; - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value >> (octets_needed << 3)))); - } - - /* always write at least one octet (also in case of value == 0) */ - PBUF_OP_EXEC(snmp_pbuf_stream_write(pbuf_stream, (u8_t)(value))); - - return ERR_OK; -} -#endif - -#endif /* LWIP_SNMP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_asn1.h b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_asn1.h deleted file mode 100644 index 87c0973fd..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_asn1.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @file - * Abstract Syntax Notation One (ISO 8824, 8825) codec. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - * Elias Oenal - */ - -#ifndef LWIP_HDR_APPS_SNMP_ASN1_H -#define LWIP_HDR_APPS_SNMP_ASN1_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP - -#include "lwip/err.h" -#include "lwip/apps/snmp_core.h" -#include "snmp_pbuf_stream.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define SNMP_ASN1_TLV_INDEFINITE_LENGTH 0x80 - -#define SNMP_ASN1_CLASS_MASK 0xC0 -#define SNMP_ASN1_CONTENTTYPE_MASK 0x20 -#define SNMP_ASN1_DATATYPE_MASK 0x1F -#define SNMP_ASN1_DATATYPE_EXTENDED 0x1F /* DataType indicating that datatype is encoded in following bytes */ - -/* context specific (SNMP) tags (from SNMP spec. RFC1157 and RFC1905) */ -#define SNMP_ASN1_CONTEXT_PDU_GET_REQ 0 -#define SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ 1 -#define SNMP_ASN1_CONTEXT_PDU_GET_RESP 2 -#define SNMP_ASN1_CONTEXT_PDU_SET_REQ 3 -#define SNMP_ASN1_CONTEXT_PDU_TRAP 4 -#define SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ 5 -#define SNMP_ASN1_CONTEXT_PDU_INFORM_REQ 6 -#define SNMP_ASN1_CONTEXT_PDU_V2_TRAP 7 -#define SNMP_ASN1_CONTEXT_PDU_REPORT 8 - -#define SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT 0 -#define SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW 2 - -struct snmp_asn1_tlv { - u8_t type; /* only U8 because extended types are not specified by SNMP */ - u8_t type_len; /* encoded length of 'type' field (normally 1) */ - u8_t length_len; /* indicates how many bytes are required to encode the 'value_len' field */ - u16_t value_len; /* encoded length of the value */ -}; -#define SNMP_ASN1_TLV_HDR_LENGTH(tlv) ((tlv).type_len + (tlv).length_len) -#define SNMP_ASN1_TLV_LENGTH(tlv) ((tlv).type_len + (tlv).length_len + (tlv).value_len) -#define SNMP_ASN1_SET_TLV_PARAMS(tlv, type_, length_len_, value_len_) do { (tlv).type = (type_); (tlv).type_len = 0; (tlv).length_len = (length_len_); (tlv).value_len = (value_len_); } while (0); - -err_t snmp_asn1_dec_tlv(struct snmp_pbuf_stream *pbuf_stream, struct snmp_asn1_tlv *tlv); -err_t snmp_asn1_dec_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *value); -err_t snmp_asn1_dec_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, s32_t *value); -err_t snmp_asn1_dec_oid(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u32_t *oid, u8_t *oid_len, u8_t oid_max_len); -err_t snmp_asn1_dec_raw(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u8_t *buf, u16_t *buf_len, u16_t buf_max_len); - -err_t snmp_ans1_enc_tlv(struct snmp_pbuf_stream *pbuf_stream, struct snmp_asn1_tlv *tlv); - -void snmp_asn1_enc_length_cnt(u16_t length, u8_t *octets_needed); -void snmp_asn1_enc_u32t_cnt(u32_t value, u16_t *octets_needed); -void snmp_asn1_enc_s32t_cnt(s32_t value, u16_t *octets_needed); -void snmp_asn1_enc_oid_cnt(const u32_t *oid, u16_t oid_len, u16_t *octets_needed); -err_t snmp_asn1_enc_oid(struct snmp_pbuf_stream *pbuf_stream, const u32_t *oid, u16_t oid_len); -err_t snmp_asn1_enc_s32t(struct snmp_pbuf_stream *pbuf_stream, u16_t octets_needed, s32_t value); -err_t snmp_asn1_enc_u32t(struct snmp_pbuf_stream *pbuf_stream, u16_t octets_needed, u32_t value); -err_t snmp_asn1_enc_raw(struct snmp_pbuf_stream *pbuf_stream, const u8_t *raw, u16_t raw_len); - -#if LWIP_HAVE_INT64 -err_t snmp_asn1_dec_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t len, u64_t *value); -void snmp_asn1_enc_u64t_cnt(u64_t value, u16_t *octets_needed); -err_t snmp_asn1_enc_u64t(struct snmp_pbuf_stream *pbuf_stream, u16_t octets_needed, u64_t value); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_ASN1_H */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_core.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_core.c deleted file mode 100644 index 987f1066f..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_core.c +++ /dev/null @@ -1,1353 +0,0 @@ -/** - * @file - * MIB tree access/construction functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel -*/ - -/** - * @defgroup snmp SNMPv2c/v3 agent - * @ingroup apps - * SNMPv2c and SNMPv3 compatible agent\n - * There is also a MIB compiler and a MIB viewer in lwIP contrib repository - * (lwip-contrib/apps/LwipMibCompiler).\n - * The agent implements the most important MIB2 MIBs including IPv6 support - * (interfaces, UDP, TCP, SNMP, ICMP, SYSTEM). IP MIB is an older version - * without IPv6 statistics (TODO).\n - * Rewritten by Martin Hentschel and - * Dirk Ziegelmeier \n - * - * 0 Agent Capabilities - * ==================== - * - * Features: - * --------- - * - SNMPv2c support. - * - SNMPv3 support (a port to ARM mbedtls is provided, LWIP_SNMP_V3_MBEDTLS option). - * - Low RAM usage - no memory pools, stack only. - * - MIB2 implementation is separated from SNMP stack. - * - Support for multiple MIBs (snmp_set_mibs() call) - e.g. for private MIB. - * - Simple and generic API for MIB implementation. - * - Comfortable node types and helper functions for scalar arrays and tables. - * - Counter64, bit and truthvalue datatype support. - * - Callbacks for SNMP writes e.g. to implement persistency. - * - Runs on two APIs: RAW and netconn. - * - Async API is gone - the stack now supports netconn API instead, - * so blocking operations can be done in MIB calls. - * SNMP runs in a worker thread when netconn API is used. - * - Simplified thread sync support for MIBs - useful when MIBs - * need to access variables shared with other threads where no locking is - * possible. Used in MIB2 to access lwIP stats from lwIP thread. - * - * MIB compiler (code generator): - * ------------------------------ - * - Provided in lwIP contrib repository. - * - Written in C#. MIB viewer used Windows Forms. - * - Developed on Windows with Visual Studio 2010. - * - Can be compiled and used on all platforms with http://www.monodevelop.com/. - * - Based on a heavily modified version of of SharpSnmpLib (a4bd05c6afb4) - * (https://sharpsnmplib.codeplex.com/SourceControl/network/forks/Nemo157/MIBParserUpdate). - * - MIB parser, C file generation framework and LWIP code generation are cleanly - * separated, which means the code may be useful as a base for code generation - * of other SNMP agents. - * - * Notes: - * ------ - * - Stack and MIB compiler were used to implement a Profinet device. - * Compiled/implemented MIBs: LLDP-MIB, LLDP-EXT-DOT3-MIB, LLDP-EXT-PNO-MIB. - * - * SNMPv1 per RFC1157 and SNMPv2c per RFC 3416 - * ------------------------------------------- - * Note the S in SNMP stands for "Simple". Note that "Simple" is - * relative. SNMP is simple compared to the complex ISO network - * management protocols CMIP (Common Management Information Protocol) - * and CMOT (CMip Over Tcp). - * - * SNMPv3 - * ------ - * When SNMPv3 is used, several functions from snmpv3.h must be implemented - * by the user. This is mainly user management and persistence handling. - * The sample provided in lwip-contrib is insecure, don't use it in production - * systems, especially the missing persistence for engine boots variable - * simplifies replay attacks. - * - * MIB II - * ------ - * The standard lwIP stack management information base. - * This is a required MIB, so this is always enabled. - * The groups EGP, CMOT and transmission are disabled by default. - * - * Most mib-2 objects are not writable except: - * sysName, sysLocation, sysContact, snmpEnableAuthenTraps. - * Writing to or changing the ARP and IP address and route - * tables is not possible. - * - * Note lwIP has a very limited notion of IP routing. It currently - * doen't have a route table and doesn't have a notion of the U,G,H flags. - * Instead lwIP uses the interface list with only one default interface - * acting as a single gateway interface (G) for the default route. - * - * The agent returns a "virtual table" with the default route 0.0.0.0 - * for the default interface and network routes (no H) for each - * network interface in the netif_list. - * All routes are considered to be up (U). - * - * Loading additional MIBs - * ----------------------- - * MIBs can only be added in compile-time, not in run-time. - * - * - * 1 Building the Agent - * ==================== - * First of all you'll need to add the following define - * to your local lwipopts.h: - * \#define LWIP_SNMP 1 - * - * and add the source files your makefile. - * - * Note you'll might need to adapt you network driver to update - * the mib2 variables for your interface. - * - * 2 Running the Agent - * =================== - * The following function calls must be made in your program to - * actually get the SNMP agent running. - * - * Before starting the agent you should supply pointers - * for sysContact, sysLocation, and snmpEnableAuthenTraps. - * You can do this by calling - * - * - snmp_mib2_set_syscontact() - * - snmp_mib2_set_syslocation() - * - snmp_set_auth_traps_enabled() - * - * You can register a callback which is called on successful write access: - * snmp_set_write_callback(). - * - * Additionally you may want to set - * - * - snmp_mib2_set_sysdescr() - * - snmp_set_device_enterprise_oid() - * - snmp_mib2_set_sysname() - * - * Also before starting the agent you need to setup - * one or more trap destinations using these calls: - * - * - snmp_trap_dst_enable() - * - snmp_trap_dst_ip_set() - * - * If you need more than MIB2, set the MIBs you want to use - * by snmp_set_mibs(). - * - * Finally, enable the agent by calling snmp_init() - * - * @defgroup snmp_core Core - * @ingroup snmp - * - * @defgroup snmp_traps Traps - * @ingroup snmp - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "snmp_core_priv.h" -#include "lwip/netif.h" -#include - - -#if (LWIP_SNMP && (SNMP_TRAP_DESTINATIONS<=0)) -#error "If you want to use SNMP, you have to define SNMP_TRAP_DESTINATIONS>=1 in your lwipopts.h" -#endif -#if (!LWIP_UDP && LWIP_SNMP) -#error "If you want to use SNMP, you have to define LWIP_UDP=1 in your lwipopts.h" -#endif -#if SNMP_MAX_OBJ_ID_LEN > 255 -#error "SNMP_MAX_OBJ_ID_LEN must fit into an u8_t" -#endif - -struct snmp_statistics snmp_stats; -static const struct snmp_obj_id snmp_device_enterprise_oid_default = {SNMP_DEVICE_ENTERPRISE_OID_LEN, SNMP_DEVICE_ENTERPRISE_OID}; -static const struct snmp_obj_id *snmp_device_enterprise_oid = &snmp_device_enterprise_oid_default; - -const u32_t snmp_zero_dot_zero_values[] = { 0, 0 }; -const struct snmp_obj_id_const_ref snmp_zero_dot_zero = { LWIP_ARRAYSIZE(snmp_zero_dot_zero_values), snmp_zero_dot_zero_values }; - -#if SNMP_LWIP_MIB2 && LWIP_SNMP_V3 -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_snmpv2_framework.h" -#include "lwip/apps/snmp_snmpv2_usm.h" -static const struct snmp_mib *const default_mibs[] = { &mib2, &snmpframeworkmib, &snmpusmmib }; -static u8_t snmp_num_mibs = LWIP_ARRAYSIZE(default_mibs); -#elif SNMP_LWIP_MIB2 -#include "lwip/apps/snmp_mib2.h" -static const struct snmp_mib *const default_mibs[] = { &mib2 }; -static u8_t snmp_num_mibs = LWIP_ARRAYSIZE(default_mibs); -#else -static const struct snmp_mib *const default_mibs[] = { NULL }; -static u8_t snmp_num_mibs = 0; -#endif - -/* List of known mibs */ -static struct snmp_mib const *const *snmp_mibs = default_mibs; - -/** - * @ingroup snmp_core - * Sets the MIBs to use. - * Example: call snmp_set_mibs() as follows: - * static const struct snmp_mib *my_snmp_mibs[] = { - * &mib2, - * &private_mib - * }; - * snmp_set_mibs(my_snmp_mibs, LWIP_ARRAYSIZE(my_snmp_mibs)); - */ -void -snmp_set_mibs(const struct snmp_mib **mibs, u8_t num_mibs) -{ - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("mibs pointer must be != NULL", (mibs != NULL)); - LWIP_ASSERT("num_mibs pointer must be != 0", (num_mibs != 0)); - snmp_mibs = mibs; - snmp_num_mibs = num_mibs; -} - -/** - * @ingroup snmp_core - * 'device enterprise oid' is used for 'device OID' field in trap PDU's (for identification of generating device) - * as well as for value returned by MIB-2 'sysObjectID' field (if internal MIB2 implementation is used). - * The 'device enterprise oid' shall point to an OID located under 'private-enterprises' branch (1.3.6.1.4.1.XXX). If a vendor - * wants to provide a custom object there, he has to get its own enterprise oid from IANA (http://www.iana.org). It - * is not allowed to use LWIP enterprise ID! - * In order to identify a specific device it is recommended to create a dedicated OID for each device type under its own - * enterprise oid. - * e.g. - * device a > 1.3.6.1.4.1.XXX(ent-oid).1(devices).1(device a) - * device b > 1.3.6.1.4.1.XXX(ent-oid).1(devices).2(device b) - * for more details see description of 'sysObjectID' field in RFC1213-MIB - */ -void snmp_set_device_enterprise_oid(const struct snmp_obj_id *device_enterprise_oid) -{ - LWIP_ASSERT_CORE_LOCKED(); - if (device_enterprise_oid == NULL) { - snmp_device_enterprise_oid = &snmp_device_enterprise_oid_default; - } else { - snmp_device_enterprise_oid = device_enterprise_oid; - } -} - -/** - * @ingroup snmp_core - * Get 'device enterprise oid' - */ -const struct snmp_obj_id *snmp_get_device_enterprise_oid(void) -{ - LWIP_ASSERT_CORE_LOCKED(); - return snmp_device_enterprise_oid; -} - -#if LWIP_IPV4 -/** - * Conversion from InetAddressIPv4 oid to lwIP ip4_addr - * @param oid points to u32_t ident[4] input - * @param ip points to output struct - */ -u8_t -snmp_oid_to_ip4(const u32_t *oid, ip4_addr_t *ip) -{ - if ((oid[0] > 0xFF) || - (oid[1] > 0xFF) || - (oid[2] > 0xFF) || - (oid[3] > 0xFF)) { - ip4_addr_copy(*ip, *IP4_ADDR_ANY4); - return 0; - } - - IP4_ADDR(ip, oid[0], oid[1], oid[2], oid[3]); - return 1; -} - -/** - * Convert ip4_addr to InetAddressIPv4 (no InetAddressType) - * @param ip points to input struct - * @param oid points to u32_t ident[4] output - */ -void -snmp_ip4_to_oid(const ip4_addr_t *ip, u32_t *oid) -{ - oid[0] = ip4_addr1(ip); - oid[1] = ip4_addr2(ip); - oid[2] = ip4_addr3(ip); - oid[3] = ip4_addr4(ip); -} -#endif /* LWIP_IPV4 */ - -#if LWIP_IPV6 -/** - * Conversion from InetAddressIPv6 oid to lwIP ip6_addr - * @param oid points to u32_t oid[16] input - * @param ip points to output struct - */ -u8_t -snmp_oid_to_ip6(const u32_t *oid, ip6_addr_t *ip) -{ - if ((oid[0] > 0xFF) || - (oid[1] > 0xFF) || - (oid[2] > 0xFF) || - (oid[3] > 0xFF) || - (oid[4] > 0xFF) || - (oid[5] > 0xFF) || - (oid[6] > 0xFF) || - (oid[7] > 0xFF) || - (oid[8] > 0xFF) || - (oid[9] > 0xFF) || - (oid[10] > 0xFF) || - (oid[11] > 0xFF) || - (oid[12] > 0xFF) || - (oid[13] > 0xFF) || - (oid[14] > 0xFF) || - (oid[15] > 0xFF)) { - ip6_addr_set_any(ip); - return 0; - } - - ip->addr[0] = (oid[0] << 24) | (oid[1] << 16) | (oid[2] << 8) | (oid[3] << 0); - ip->addr[1] = (oid[4] << 24) | (oid[5] << 16) | (oid[6] << 8) | (oid[7] << 0); - ip->addr[2] = (oid[8] << 24) | (oid[9] << 16) | (oid[10] << 8) | (oid[11] << 0); - ip->addr[3] = (oid[12] << 24) | (oid[13] << 16) | (oid[14] << 8) | (oid[15] << 0); - return 1; -} - -/** - * Convert ip6_addr to InetAddressIPv6 (no InetAddressType) - * @param ip points to input struct - * @param oid points to u32_t ident[16] output - */ -void -snmp_ip6_to_oid(const ip6_addr_t *ip, u32_t *oid) -{ - oid[0] = (ip->addr[0] & 0xFF000000) >> 24; - oid[1] = (ip->addr[0] & 0x00FF0000) >> 16; - oid[2] = (ip->addr[0] & 0x0000FF00) >> 8; - oid[3] = (ip->addr[0] & 0x000000FF) >> 0; - oid[4] = (ip->addr[1] & 0xFF000000) >> 24; - oid[5] = (ip->addr[1] & 0x00FF0000) >> 16; - oid[6] = (ip->addr[1] & 0x0000FF00) >> 8; - oid[7] = (ip->addr[1] & 0x000000FF) >> 0; - oid[8] = (ip->addr[2] & 0xFF000000) >> 24; - oid[9] = (ip->addr[2] & 0x00FF0000) >> 16; - oid[10] = (ip->addr[2] & 0x0000FF00) >> 8; - oid[11] = (ip->addr[2] & 0x000000FF) >> 0; - oid[12] = (ip->addr[3] & 0xFF000000) >> 24; - oid[13] = (ip->addr[3] & 0x00FF0000) >> 16; - oid[14] = (ip->addr[3] & 0x0000FF00) >> 8; - oid[15] = (ip->addr[3] & 0x000000FF) >> 0; -} -#endif /* LWIP_IPV6 */ - -#if LWIP_IPV4 || LWIP_IPV6 -/** - * Convert to InetAddressType+InetAddress+InetPortNumber - * @param ip IP address - * @param port Port - * @param oid OID - * @return OID length - */ -u8_t -snmp_ip_port_to_oid(const ip_addr_t *ip, u16_t port, u32_t *oid) -{ - u8_t idx; - - idx = snmp_ip_to_oid(ip, oid); - oid[idx] = port; - idx++; - - return idx; -} - -/** - * Convert to InetAddressType+InetAddress - * @param ip IP address - * @param oid OID - * @return OID length - */ -u8_t -snmp_ip_to_oid(const ip_addr_t *ip, u32_t *oid) -{ - if (IP_IS_ANY_TYPE_VAL(*ip)) { - oid[0] = 0; /* any */ - oid[1] = 0; /* no IP OIDs follow */ - return 2; - } else if (IP_IS_V6(ip)) { -#if LWIP_IPV6 - oid[0] = 2; /* ipv6 */ - oid[1] = 16; /* 16 InetAddressIPv6 OIDs follow */ - snmp_ip6_to_oid(ip_2_ip6(ip), &oid[2]); - return 18; -#else /* LWIP_IPV6 */ - return 0; -#endif /* LWIP_IPV6 */ - } else { -#if LWIP_IPV4 - oid[0] = 1; /* ipv4 */ - oid[1] = 4; /* 4 InetAddressIPv4 OIDs follow */ - snmp_ip4_to_oid(ip_2_ip4(ip), &oid[2]); - return 6; -#else /* LWIP_IPV4 */ - return 0; -#endif /* LWIP_IPV4 */ - } -} - -/** - * Convert from InetAddressType+InetAddress to ip_addr_t - * @param oid OID - * @param oid_len OID length - * @param ip IP address - * @return Parsed OID length - */ -u8_t -snmp_oid_to_ip(const u32_t *oid, u8_t oid_len, ip_addr_t *ip) -{ - /* InetAddressType */ - if (oid_len < 1) { - return 0; - } - - if (oid[0] == 0) { /* any */ - /* 1x InetAddressType, 1x OID len */ - if (oid_len < 2) { - return 0; - } - if (oid[1] != 0) { - return 0; - } - - memset(ip, 0, sizeof(*ip)); - IP_SET_TYPE(ip, IPADDR_TYPE_ANY); - - return 2; - } else if (oid[0] == 1) { /* ipv4 */ -#if LWIP_IPV4 - /* 1x InetAddressType, 1x OID len, 4x InetAddressIPv4 */ - if (oid_len < 6) { - return 0; - } - - /* 4x ipv4 OID */ - if (oid[1] != 4) { - return 0; - } - - IP_SET_TYPE(ip, IPADDR_TYPE_V4); - if (!snmp_oid_to_ip4(&oid[2], ip_2_ip4(ip))) { - return 0; - } - - return 6; -#else /* LWIP_IPV4 */ - return 0; -#endif /* LWIP_IPV4 */ - } else if (oid[0] == 2) { /* ipv6 */ -#if LWIP_IPV6 - /* 1x InetAddressType, 1x OID len, 16x InetAddressIPv6 */ - if (oid_len < 18) { - return 0; - } - - /* 16x ipv6 OID */ - if (oid[1] != 16) { - return 0; - } - - IP_SET_TYPE(ip, IPADDR_TYPE_V6); - if (!snmp_oid_to_ip6(&oid[2], ip_2_ip6(ip))) { - return 0; - } - - return 18; -#else /* LWIP_IPV6 */ - return 0; -#endif /* LWIP_IPV6 */ - } else { /* unsupported InetAddressType */ - return 0; - } -} - -/** - * Convert from InetAddressType+InetAddress+InetPortNumber to ip_addr_t and u16_t - * @param oid OID - * @param oid_len OID length - * @param ip IP address - * @param port Port - * @return Parsed OID length - */ -u8_t -snmp_oid_to_ip_port(const u32_t *oid, u8_t oid_len, ip_addr_t *ip, u16_t *port) -{ - u8_t idx; - - /* InetAddressType + InetAddress */ - idx = snmp_oid_to_ip(&oid[0], oid_len, ip); - if (idx == 0) { - return 0; - } - - /* InetPortNumber */ - if (oid_len < (idx + 1)) { - return 0; - } - if (oid[idx] > 0xffff) { - return 0; - } - *port = (u16_t)oid[idx]; - idx++; - - return idx; -} - -#endif /* LWIP_IPV4 || LWIP_IPV6 */ - -/** - * Assign an OID to struct snmp_obj_id - * @param target Assignment target - * @param oid OID - * @param oid_len OID length - */ -void -snmp_oid_assign(struct snmp_obj_id *target, const u32_t *oid, u8_t oid_len) -{ - LWIP_ASSERT("oid_len <= SNMP_MAX_OBJ_ID_LEN", oid_len <= SNMP_MAX_OBJ_ID_LEN); - - target->len = oid_len; - - if (oid_len > 0) { - MEMCPY(target->id, oid, oid_len * sizeof(u32_t)); - } -} - -/** - * Prefix an OID to OID in struct snmp_obj_id - * @param target Assignment target to prefix - * @param oid OID - * @param oid_len OID length - */ -void -snmp_oid_prefix(struct snmp_obj_id *target, const u32_t *oid, u8_t oid_len) -{ - LWIP_ASSERT("target->len + oid_len <= SNMP_MAX_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN); - - if (oid_len > 0) { - /* move existing OID to make room at the beginning for OID to insert */ - int i; - for (i = target->len - 1; i >= 0; i--) { - target->id[i + oid_len] = target->id[i]; - } - - /* paste oid at the beginning */ - MEMCPY(target->id, oid, oid_len * sizeof(u32_t)); - } -} - -/** - * Combine two OIDs into struct snmp_obj_id - * @param target Assignmet target - * @param oid1 OID 1 - * @param oid1_len OID 1 length - * @param oid2 OID 2 - * @param oid2_len OID 2 length - */ -void -snmp_oid_combine(struct snmp_obj_id *target, const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) -{ - snmp_oid_assign(target, oid1, oid1_len); - snmp_oid_append(target, oid2, oid2_len); -} - -/** - * Append OIDs to struct snmp_obj_id - * @param target Assignment target to append to - * @param oid OID - * @param oid_len OID length - */ -void -snmp_oid_append(struct snmp_obj_id *target, const u32_t *oid, u8_t oid_len) -{ - LWIP_ASSERT("offset + oid_len <= SNMP_MAX_OBJ_ID_LEN", (target->len + oid_len) <= SNMP_MAX_OBJ_ID_LEN); - - if (oid_len > 0) { - MEMCPY(&target->id[target->len], oid, oid_len * sizeof(u32_t)); - target->len = (u8_t)(target->len + oid_len); - } -} - -/** - * Compare two OIDs - * @param oid1 OID 1 - * @param oid1_len OID 1 length - * @param oid2 OID 2 - * @param oid2_len OID 2 length - * @return -1: OID1<OID2 1: OID1 >OID2 0: equal - */ -s8_t -snmp_oid_compare(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) -{ - u8_t level = 0; - LWIP_ASSERT("'oid1' param must not be NULL or 'oid1_len' param be 0!", (oid1 != NULL) || (oid1_len == 0)); - LWIP_ASSERT("'oid2' param must not be NULL or 'oid2_len' param be 0!", (oid2 != NULL) || (oid2_len == 0)); - - while ((level < oid1_len) && (level < oid2_len)) { - if (*oid1 < *oid2) { - return -1; - } - if (*oid1 > *oid2) { - return 1; - } - - level++; - oid1++; - oid2++; - } - - /* common part of both OID's is equal, compare length */ - if (oid1_len < oid2_len) { - return -1; - } - if (oid1_len > oid2_len) { - return 1; - } - - /* they are equal */ - return 0; -} - - -/** - * Check of two OIDs are equal - * @param oid1 OID 1 - * @param oid1_len OID 1 length - * @param oid2 OID 2 - * @param oid2_len OID 2 length - * @return 1: equal 0: non-equal - */ -u8_t -snmp_oid_equal(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) -{ - return (snmp_oid_compare(oid1, oid1_len, oid2, oid2_len) == 0) ? 1 : 0; -} - -/** - * Convert netif to interface index - * @param netif netif - * @return index - */ -u8_t -netif_to_num(const struct netif *netif) -{ - return netif_get_index(netif); -} - -static const struct snmp_mib * -snmp_get_mib_from_oid(const u32_t *oid, u8_t oid_len) -{ - const u32_t *list_oid; - const u32_t *searched_oid; - u8_t i, l; - - u8_t max_match_len = 0; - const struct snmp_mib *matched_mib = NULL; - - LWIP_ASSERT("'oid' param must not be NULL!", (oid != NULL)); - - if (oid_len == 0) { - return NULL; - } - - for (i = 0; i < snmp_num_mibs; i++) { - LWIP_ASSERT("MIB array not initialized correctly", (snmp_mibs[i] != NULL)); - LWIP_ASSERT("MIB array not initialized correctly - base OID is NULL", (snmp_mibs[i]->base_oid != NULL)); - - if (oid_len >= snmp_mibs[i]->base_oid_len) { - l = snmp_mibs[i]->base_oid_len; - list_oid = snmp_mibs[i]->base_oid; - searched_oid = oid; - - while (l > 0) { - if (*list_oid != *searched_oid) { - break; - } - - l--; - list_oid++; - searched_oid++; - } - - if ((l == 0) && (snmp_mibs[i]->base_oid_len > max_match_len)) { - max_match_len = snmp_mibs[i]->base_oid_len; - matched_mib = snmp_mibs[i]; - } - } - } - - return matched_mib; -} - -static const struct snmp_mib * -snmp_get_next_mib(const u32_t *oid, u8_t oid_len) -{ - u8_t i; - const struct snmp_mib *next_mib = NULL; - - LWIP_ASSERT("'oid' param must not be NULL!", (oid != NULL)); - - if (oid_len == 0) { - return NULL; - } - - for (i = 0; i < snmp_num_mibs; i++) { - if (snmp_mibs[i]->base_oid != NULL) { - /* check if mib is located behind starting point */ - if (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len, oid, oid_len) > 0) { - if ((next_mib == NULL) || - (snmp_oid_compare(snmp_mibs[i]->base_oid, snmp_mibs[i]->base_oid_len, - next_mib->base_oid, next_mib->base_oid_len) < 0)) { - next_mib = snmp_mibs[i]; - } - } - } - } - - return next_mib; -} - -static const struct snmp_mib * -snmp_get_mib_between(const u32_t *oid1, u8_t oid1_len, const u32_t *oid2, u8_t oid2_len) -{ - const struct snmp_mib *next_mib = snmp_get_next_mib(oid1, oid1_len); - - LWIP_ASSERT("'oid2' param must not be NULL!", (oid2 != NULL)); - LWIP_ASSERT("'oid2_len' param must be greater than 0!", (oid2_len > 0)); - - if (next_mib != NULL) { - if (snmp_oid_compare(next_mib->base_oid, next_mib->base_oid_len, oid2, oid2_len) < 0) { - return next_mib; - } - } - - return NULL; -} - -u8_t -snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance *node_instance) -{ - u8_t result = SNMP_ERR_NOSUCHOBJECT; - const struct snmp_mib *mib; - const struct snmp_node *mn = NULL; - - mib = snmp_get_mib_from_oid(oid, oid_len); - if (mib != NULL) { - u8_t oid_instance_len; - - mn = snmp_mib_tree_resolve_exact(mib, oid, oid_len, &oid_instance_len); - if ((mn != NULL) && (mn->node_type != SNMP_NODE_TREE)) { - /* get instance */ - const struct snmp_leaf_node *leaf_node = (const struct snmp_leaf_node *)(const void *)mn; - - node_instance->node = mn; - snmp_oid_assign(&node_instance->instance_oid, oid + (oid_len - oid_instance_len), oid_instance_len); - - result = leaf_node->get_instance( - oid, - oid_len - oid_instance_len, - node_instance); - -#ifdef LWIP_DEBUG - if (result == SNMP_ERR_NOERROR) { - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value == NULL)) { - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is readable but no get_value function is specified\n")); - } - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value == NULL)) { - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is writable but no set_value and/or set_test function is specified\n")); - } - } -#endif - } - } - - return result; -} - -u8_t -snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void *validate_node_instance_arg, struct snmp_obj_id *node_oid, struct snmp_node_instance *node_instance) -{ - const struct snmp_mib *mib; - const struct snmp_node *mn = NULL; - const u32_t *start_oid = NULL; - u8_t start_oid_len = 0; - - /* resolve target MIB from passed OID */ - mib = snmp_get_mib_from_oid(oid, oid_len); - if (mib == NULL) { - /* passed OID does not reference any known MIB, start at the next closest MIB */ - mib = snmp_get_next_mib(oid, oid_len); - - if (mib != NULL) { - start_oid = mib->base_oid; - start_oid_len = mib->base_oid_len; - } - } else { - start_oid = oid; - start_oid_len = oid_len; - } - - /* resolve target node from MIB, skip to next MIB if no suitable node is found in current MIB */ - while ((mib != NULL) && (mn == NULL)) { - u8_t oid_instance_len; - - /* check if OID directly references a node inside current MIB, in this case we have to ask this node for the next instance */ - mn = snmp_mib_tree_resolve_exact(mib, start_oid, start_oid_len, &oid_instance_len); - if (mn != NULL) { - snmp_oid_assign(node_oid, start_oid, start_oid_len - oid_instance_len); /* set oid to node */ - snmp_oid_assign(&node_instance->instance_oid, start_oid + (start_oid_len - oid_instance_len), oid_instance_len); /* set (relative) instance oid */ - } else { - /* OID does not reference a node, search for the next closest node inside MIB; set instance_oid.len to zero because we want the first instance of this node */ - mn = snmp_mib_tree_resolve_next(mib, start_oid, start_oid_len, node_oid); - node_instance->instance_oid.len = 0; - } - - /* validate the node; if the node has no further instance or the returned instance is invalid, search for the next in MIB and validate again */ - node_instance->node = mn; - while (mn != NULL) { - u8_t result; - - /* clear fields which may have values from previous loops */ - node_instance->asn1_type = 0; - node_instance->access = SNMP_NODE_INSTANCE_NOT_ACCESSIBLE; - node_instance->get_value = NULL; - node_instance->set_test = NULL; - node_instance->set_value = NULL; - node_instance->release_instance = NULL; - node_instance->reference.ptr = NULL; - node_instance->reference_len = 0; - - result = ((const struct snmp_leaf_node *)(const void *)mn)->get_next_instance( - node_oid->id, - node_oid->len, - node_instance); - - if (result == SNMP_ERR_NOERROR) { -#ifdef LWIP_DEBUG - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != 0) && (node_instance->get_value == NULL)) { - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is readable but no get_value function is specified\n")); - } - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != 0) && (node_instance->set_value == NULL)) { - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP inconsistent access: node is writable but no set_value function is specified\n")); - } -#endif - - /* validate node because the node may be not accessible for example (but let the caller decide what is valid */ - if ((validate_node_instance_method == NULL) || - (validate_node_instance_method(node_instance, validate_node_instance_arg) == SNMP_ERR_NOERROR)) { - /* node_oid "returns" the full result OID (including the instance part) */ - snmp_oid_append(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len); - break; - } - - if (node_instance->release_instance != NULL) { - node_instance->release_instance(node_instance); - } - /* - the instance itself is not valid, ask for next instance from same node. - we don't have to change any variables because node_instance->instance_oid is used as input (starting point) - as well as output (resulting next OID), so we have to simply call get_next_instance method again - */ - } else { - if (node_instance->release_instance != NULL) { - node_instance->release_instance(node_instance); - } - - /* the node has no further instance, skip to next node */ - mn = snmp_mib_tree_resolve_next(mib, node_oid->id, node_oid->len, &node_instance->instance_oid); /* misuse node_instance->instance_oid as tmp buffer */ - if (mn != NULL) { - /* prepare for next loop */ - snmp_oid_assign(node_oid, node_instance->instance_oid.id, node_instance->instance_oid.len); - node_instance->instance_oid.len = 0; - node_instance->node = mn; - } - } - } - - if (mn != NULL) { - /* - we found a suitable next node, - now we have to check if a inner MIB is located between the searched OID and the resulting OID. - this is possible because MIB's may be located anywhere in the global tree, that means also in - the subtree of another MIB (e.g. if searched OID is .2 and resulting OID is .4, then another - MIB having .3 as root node may exist) - */ - const struct snmp_mib *intermediate_mib; - intermediate_mib = snmp_get_mib_between(start_oid, start_oid_len, node_oid->id, node_oid->len); - - if (intermediate_mib != NULL) { - /* search for first node inside intermediate mib in next loop */ - if (node_instance->release_instance != NULL) { - node_instance->release_instance(node_instance); - } - - mn = NULL; - mib = intermediate_mib; - start_oid = mib->base_oid; - start_oid_len = mib->base_oid_len; - } - /* else { we found out target node } */ - } else { - /* - there is no further (suitable) node inside this MIB, search for the next MIB with following priority - 1. search for inner MIB's (whose root is located inside tree of current MIB) - 2. search for surrouding MIB's (where the current MIB is the inner MIB) and continue there if any - 3. take the next closest MIB (not being related to the current MIB) - */ - const struct snmp_mib *next_mib; - next_mib = snmp_get_next_mib(start_oid, start_oid_len); /* returns MIB's related to point 1 and 3 */ - - /* is the found MIB an inner MIB? (point 1) */ - if ((next_mib != NULL) && (next_mib->base_oid_len > mib->base_oid_len) && - (snmp_oid_compare(next_mib->base_oid, mib->base_oid_len, mib->base_oid, mib->base_oid_len) == 0)) { - /* yes it is -> continue at inner MIB */ - mib = next_mib; - start_oid = mib->base_oid; - start_oid_len = mib->base_oid_len; - } else { - /* check if there is a surrounding mib where to continue (point 2) (only possible if OID length > 1) */ - if (mib->base_oid_len > 1) { - mib = snmp_get_mib_from_oid(mib->base_oid, mib->base_oid_len - 1); - - if (mib == NULL) { - /* no surrounding mib, use next mib encountered above (point 3) */ - mib = next_mib; - - if (mib != NULL) { - start_oid = mib->base_oid; - start_oid_len = mib->base_oid_len; - } - } - /* else { start_oid stays the same because we want to continue from current offset in surrounding mib (point 2) } */ - } - } - } - } - - if (mib == NULL) { - /* loop is only left when mib == null (error) or mib_node != NULL (success) */ - return SNMP_ERR_ENDOFMIBVIEW; - } - - return SNMP_ERR_NOERROR; -} - -/** - * Searches tree for the supplied object identifier. - * - */ -const struct snmp_node * -snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, u8_t *oid_instance_len) -{ - const struct snmp_node *const *node = &mib->root_node; - u8_t oid_offset = mib->base_oid_len; - - while ((oid_offset < oid_len) && ((*node)->node_type == SNMP_NODE_TREE)) { - /* search for matching sub node */ - u32_t subnode_oid = *(oid + oid_offset); - - u32_t i = (*(const struct snmp_tree_node * const *)node)->subnode_count; - node = (*(const struct snmp_tree_node * const *)node)->subnodes; - while ((i > 0) && ((*node)->oid != subnode_oid)) { - node++; - i--; - } - - if (i == 0) { - /* no matching subnode found */ - return NULL; - } - - oid_offset++; - } - - if ((*node)->node_type != SNMP_NODE_TREE) { - /* we found a leaf node */ - *oid_instance_len = oid_len - oid_offset; - return (*node); - } - - return NULL; -} - -const struct snmp_node * -snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id *oidret) -{ - u8_t oid_offset = mib->base_oid_len; - const struct snmp_node *const *node; - const struct snmp_tree_node *node_stack[SNMP_MAX_OBJ_ID_LEN]; - s32_t nsi = 0; /* NodeStackIndex */ - u32_t subnode_oid; - - if (mib->root_node->node_type != SNMP_NODE_TREE) { - /* a next operation on a mib with only a leaf node will always return NULL because there is no other node */ - return NULL; - } - - /* first build node stack related to passed oid (as far as possible), then go backwards to determine the next node */ - node_stack[nsi] = (const struct snmp_tree_node *)(const void *)mib->root_node; - while (oid_offset < oid_len) { - /* search for matching sub node */ - u32_t i = node_stack[nsi]->subnode_count; - node = node_stack[nsi]->subnodes; - - subnode_oid = *(oid + oid_offset); - - while ((i > 0) && ((*node)->oid != subnode_oid)) { - node++; - i--; - } - - if ((i == 0) || ((*node)->node_type != SNMP_NODE_TREE)) { - /* no (matching) tree-subnode found */ - break; - } - nsi++; - node_stack[nsi] = (const struct snmp_tree_node *)(const void *)(*node); - - oid_offset++; - } - - - if (oid_offset >= oid_len) { - /* passed oid references a tree node -> return first useable sub node of it */ - subnode_oid = 0; - } else { - subnode_oid = *(oid + oid_offset) + 1; - } - - while (nsi >= 0) { - const struct snmp_node *subnode = NULL; - - /* find next node on current level */ - s32_t i = node_stack[nsi]->subnode_count; - node = node_stack[nsi]->subnodes; - while (i > 0) { - if ((*node)->oid == subnode_oid) { - subnode = *node; - break; - } else if (((*node)->oid > subnode_oid) && ((subnode == NULL) || ((*node)->oid < subnode->oid))) { - subnode = *node; - } - - node++; - i--; - } - - if (subnode == NULL) { - /* no further node found on this level, go one level up and start searching with index of current node*/ - subnode_oid = node_stack[nsi]->node.oid + 1; - nsi--; - } else { - if (subnode->node_type == SNMP_NODE_TREE) { - /* next is a tree node, go into it and start searching */ - nsi++; - node_stack[nsi] = (const struct snmp_tree_node *)(const void *)subnode; - subnode_oid = 0; - } else { - /* we found a leaf node -> fill oidret and return it */ - snmp_oid_assign(oidret, mib->base_oid, mib->base_oid_len); - i = 1; - while (i <= nsi) { - oidret->id[oidret->len] = node_stack[i]->node.oid; - oidret->len++; - i++; - } - - oidret->id[oidret->len] = subnode->oid; - oidret->len++; - - return subnode; - } - } - } - - return NULL; -} - -/** initialize struct next_oid_state using this function before passing it to next_oid_check */ -void -snmp_next_oid_init(struct snmp_next_oid_state *state, - const u32_t *start_oid, u8_t start_oid_len, - u32_t *next_oid_buf, u8_t next_oid_max_len) -{ - state->start_oid = start_oid; - state->start_oid_len = start_oid_len; - state->next_oid = next_oid_buf; - state->next_oid_len = 0; - state->next_oid_max_len = next_oid_max_len; - state->status = SNMP_NEXT_OID_STATUS_NO_MATCH; -} - -/** checks if the passed incomplete OID may be a possible candidate for snmp_next_oid_check(); -this methid is intended if the complete OID is not yet known but it is very expensive to build it up, -so it is possible to test the starting part before building up the complete oid and pass it to snmp_next_oid_check()*/ -u8_t -snmp_next_oid_precheck(struct snmp_next_oid_state *state, const u32_t *oid, u8_t oid_len) -{ - if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL) { - u8_t start_oid_len = (oid_len < state->start_oid_len) ? oid_len : state->start_oid_len; - - /* check passed OID is located behind start offset */ - if (snmp_oid_compare(oid, oid_len, state->start_oid, start_oid_len) >= 0) { - /* check if new oid is located closer to start oid than current closest oid */ - if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) || - (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0)) { - return 1; - } - } - } - - return 0; -} - -/** checks the passed OID if it is a candidate to be the next one (get_next); returns !=0 if passed oid is currently closest, otherwise 0 */ -u8_t -snmp_next_oid_check(struct snmp_next_oid_state *state, const u32_t *oid, u8_t oid_len, void *reference) -{ - /* do not overwrite a fail result */ - if (state->status != SNMP_NEXT_OID_STATUS_BUF_TO_SMALL) { - /* check passed OID is located behind start offset */ - if (snmp_oid_compare(oid, oid_len, state->start_oid, state->start_oid_len) > 0) { - /* check if new oid is located closer to start oid than current closest oid */ - if ((state->status == SNMP_NEXT_OID_STATUS_NO_MATCH) || - (snmp_oid_compare(oid, oid_len, state->next_oid, state->next_oid_len) < 0)) { - if (oid_len <= state->next_oid_max_len) { - MEMCPY(state->next_oid, oid, oid_len * sizeof(u32_t)); - state->next_oid_len = oid_len; - state->status = SNMP_NEXT_OID_STATUS_SUCCESS; - state->reference = reference; - return 1; - } else { - state->status = SNMP_NEXT_OID_STATUS_BUF_TO_SMALL; - } - } - } - } - - return 0; -} - -u8_t -snmp_oid_in_range(const u32_t *oid_in, u8_t oid_len, const struct snmp_oid_range *oid_ranges, u8_t oid_ranges_len) -{ - u8_t i; - - if (oid_len != oid_ranges_len) { - return 0; - } - - for (i = 0; i < oid_ranges_len; i++) { - if ((oid_in[i] < oid_ranges[i].min) || (oid_in[i] > oid_ranges[i].max)) { - return 0; - } - } - - return 1; -} - -snmp_err_t -snmp_set_test_ok(struct snmp_node_instance *instance, u16_t value_len, void *value) -{ - LWIP_UNUSED_ARG(instance); - LWIP_UNUSED_ARG(value_len); - LWIP_UNUSED_ARG(value); - - return SNMP_ERR_NOERROR; -} - -/** - * Decodes BITS pseudotype value from ASN.1 OctetString. - * - * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly - * be encoded/decoded by the agent. Instead call this function as required from - * get/test/set methods. - * - * @param buf points to a buffer holding the ASN1 octet string - * @param buf_len length of octet string - * @param bit_value decoded Bit value with Bit0 == LSB - * @return ERR_OK if successful, ERR_ARG if bit value contains more than 32 bit - */ -err_t -snmp_decode_bits(const u8_t *buf, u32_t buf_len, u32_t *bit_value) -{ - u8_t b; - u8_t bits_processed = 0; - *bit_value = 0; - - while (buf_len > 0) { - /* any bit set in this byte? */ - if (*buf != 0x00) { - if (bits_processed >= 32) { - /* accept more than 4 bytes, but only when no bits are set */ - return ERR_VAL; - } - - b = *buf; - do { - if (b & 0x80) { - *bit_value |= (1 << bits_processed); - } - bits_processed++; - b <<= 1; - } while ((bits_processed & 0x07) != 0); /* &0x07 -> % 8 */ - } else { - bits_processed += 8; - } - - buf_len--; - buf++; - } - - return ERR_OK; -} - -err_t -snmp_decode_truthvalue(const s32_t *asn1_value, u8_t *bool_value) -{ - /* defined by RFC1443: - TruthValue ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Represents a boolean value." - SYNTAX INTEGER { true(1), false(2) } - */ - - if ((asn1_value == NULL) || (bool_value == NULL)) { - return ERR_ARG; - } - - if (*asn1_value == 1) { - *bool_value = 1; - } else if (*asn1_value == 2) { - *bool_value = 0; - } else { - return ERR_VAL; - } - - return ERR_OK; -} - -/** - * Encodes BITS pseudotype value into ASN.1 OctetString. - * - * @note Because BITS pseudo type is encoded as OCTET STRING, it cannot directly - * be encoded/decoded by the agent. Instead call this function as required from - * get/test/set methods. - * - * @param buf points to a buffer where the resulting ASN1 octet string is stored to - * @param buf_len max length of the bufffer - * @param bit_value Bit value to encode with Bit0 == LSB - * @param bit_count Number of possible bits for the bit value (according to rfc we have to send all bits independant from their truth value) - * @return number of bytes used from buffer to store the resulting OctetString - */ -u8_t -snmp_encode_bits(u8_t *buf, u32_t buf_len, u32_t bit_value, u8_t bit_count) -{ - u8_t len = 0; - u8_t min_bytes = (bit_count + 7) >> 3; /* >>3 -> / 8 */ - - while ((buf_len > 0) && (bit_value != 0x00)) { - s8_t i = 7; - *buf = 0x00; - while (i >= 0) { - if (bit_value & 0x01) { - *buf |= 0x01; - } - - if (i > 0) { - *buf <<= 1; - } - - bit_value >>= 1; - i--; - } - - buf++; - buf_len--; - len++; - } - - if (len < min_bytes) { - buf += len; - buf_len -= len; - - while ((len < min_bytes) && (buf_len > 0)) { - *buf = 0x00; - buf++; - buf_len--; - len++; - } - } - - return len; -} - -u8_t -snmp_encode_truthvalue(s32_t *asn1_value, u32_t bool_value) -{ - /* defined by RFC1443: - TruthValue ::= TEXTUAL-CONVENTION - STATUS current - DESCRIPTION - "Represents a boolean value." - SYNTAX INTEGER { true(1), false(2) } - */ - - if (asn1_value == NULL) { - return 0; - } - - if (bool_value) { - *asn1_value = 1; /* defined by RFC1443 */ - } else { - *asn1_value = 2; /* defined by RFC1443 */ - } - - return sizeof(s32_t); -} - -#endif /* LWIP_SNMP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_core_priv.h b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_core_priv.h deleted file mode 100644 index 9532c05e4..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_core_priv.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#ifndef LWIP_HDR_APPS_SNMP_CORE_PRIV_H -#define LWIP_HDR_APPS_SNMP_CORE_PRIV_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_core.h" -#include "snmp_asn1.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* (outdated) SNMPv1 error codes - * shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request - */ -#define SNMP_ERR_NOSUCHNAME 2 -#define SNMP_ERR_BADVALUE 3 -#define SNMP_ERR_READONLY 4 -/* error codes which are internal and shall not be used by MIBS - * shall not be used by MIBS anymore, nevertheless required from core for properly answering a v1 request - */ -#define SNMP_ERR_TOOBIG 1 -#define SNMP_ERR_AUTHORIZATIONERROR 16 - -#define SNMP_ERR_UNKNOWN_ENGINEID 30 -#define SNMP_ERR_UNKNOWN_SECURITYNAME 31 -#define SNMP_ERR_UNSUPPORTED_SECLEVEL 32 -#define SNMP_ERR_NOTINTIMEWINDOW 33 -#define SNMP_ERR_DECRYIPTION_ERROR 34 - -#define SNMP_ERR_NOSUCHOBJECT SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_NO_SUCH_OBJECT -#define SNMP_ERR_ENDOFMIBVIEW SNMP_VARBIND_EXCEPTION_OFFSET + SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW - - -const struct snmp_node *snmp_mib_tree_resolve_exact(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, u8_t *oid_instance_len); -const struct snmp_node *snmp_mib_tree_resolve_next(const struct snmp_mib *mib, const u32_t *oid, u8_t oid_len, struct snmp_obj_id *oidret); - -typedef u8_t (*snmp_validate_node_instance_method)(struct snmp_node_instance *, void *); - -u8_t snmp_get_node_instance_from_oid(const u32_t *oid, u8_t oid_len, struct snmp_node_instance *node_instance); -u8_t snmp_get_next_node_instance_from_oid(const u32_t *oid, u8_t oid_len, snmp_validate_node_instance_method validate_node_instance_method, void *validate_node_instance_arg, struct snmp_obj_id *node_oid, struct snmp_node_instance *node_instance); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_CORE_PRIV_H */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2.c deleted file mode 100644 index 3383e44e9..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2.c +++ /dev/null @@ -1,116 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -/** - * @defgroup snmp_mib2 MIB2 - * @ingroup snmp - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP && SNMP_LWIP_MIB2 /* don't build if not configured for use in lwipopts.h */ - -#if !LWIP_STATS -#error LWIP_SNMP MIB2 needs LWIP_STATS (for MIB2) -#endif -#if !MIB2_STATS -#error LWIP_SNMP MIB2 needs MIB2_STATS (for MIB2) -#endif - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_scalar.h" - -#if SNMP_USE_NETCONN -#include "lwip/tcpip.h" -#include "lwip/priv/tcpip_priv.h" -void -snmp_mib2_lwip_synchronizer(snmp_threadsync_called_fn fn, void *arg) -{ -#if LWIP_TCPIP_CORE_LOCKING - LOCK_TCPIP_CORE(); - fn(arg); - UNLOCK_TCPIP_CORE(); -#else - tcpip_callback(fn, arg); -#endif -} - -struct snmp_threadsync_instance snmp_mib2_lwip_locks; -#endif - -/* dot3 and EtherLike MIB not planned. (transmission .1.3.6.1.2.1.10) */ -/* historical (some say hysterical). (cmot .1.3.6.1.2.1.9) */ -/* lwIP has no EGP, thus may not implement it. (egp .1.3.6.1.2.1.8) */ - -/* --- mib-2 .1.3.6.1.2.1 ----------------------------------------------------- */ -extern const struct snmp_scalar_array_node snmp_mib2_snmp_root; -extern const struct snmp_tree_node snmp_mib2_udp_root; -extern const struct snmp_tree_node snmp_mib2_tcp_root; -extern const struct snmp_scalar_array_node snmp_mib2_icmp_root; -extern const struct snmp_tree_node snmp_mib2_interface_root; -extern const struct snmp_scalar_array_node snmp_mib2_system_node; -extern const struct snmp_tree_node snmp_mib2_at_root; -extern const struct snmp_tree_node snmp_mib2_ip_root; - -static const struct snmp_node *const mib2_nodes[] = { - &snmp_mib2_system_node.node.node, - &snmp_mib2_interface_root.node, -#if LWIP_ARP && LWIP_IPV4 - &snmp_mib2_at_root.node, -#endif /* LWIP_ARP && LWIP_IPV4 */ -#if LWIP_IPV4 - &snmp_mib2_ip_root.node, -#endif /* LWIP_IPV4 */ -#if LWIP_ICMP - &snmp_mib2_icmp_root.node.node, -#endif /* LWIP_ICMP */ -#if LWIP_TCP - &snmp_mib2_tcp_root.node, -#endif /* LWIP_TCP */ -#if LWIP_UDP - &snmp_mib2_udp_root.node, -#endif /* LWIP_UDP */ - &snmp_mib2_snmp_root.node.node -}; - -static const struct snmp_tree_node mib2_root = SNMP_CREATE_TREE_NODE(1, mib2_nodes); - -static const u32_t mib2_base_oid_arr[] = { 1, 3, 6, 1, 2, 1 }; -const struct snmp_mib mib2 = SNMP_MIB_CREATE(mib2_base_oid_arr, &mib2_root.node); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_icmp.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_icmp.c deleted file mode 100644 index 033d229ee..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_icmp.c +++ /dev/null @@ -1,182 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) ICMP objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/icmp.h" -#include "lwip/stats.h" - -#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -/* --- icmp .1.3.6.1.2.1.5 ----------------------------------------------------- */ - -static s16_t -icmp_get_value(const struct snmp_scalar_array_node_def *node, void *value) -{ - u32_t *uint_ptr = (u32_t *)value; - - switch (node->oid) { - case 1: /* icmpInMsgs */ - *uint_ptr = STATS_GET(mib2.icmpinmsgs); - return sizeof(*uint_ptr); - case 2: /* icmpInErrors */ - *uint_ptr = STATS_GET(mib2.icmpinerrors); - return sizeof(*uint_ptr); - case 3: /* icmpInDestUnreachs */ - *uint_ptr = STATS_GET(mib2.icmpindestunreachs); - return sizeof(*uint_ptr); - case 4: /* icmpInTimeExcds */ - *uint_ptr = STATS_GET(mib2.icmpintimeexcds); - return sizeof(*uint_ptr); - case 5: /* icmpInParmProbs */ - *uint_ptr = STATS_GET(mib2.icmpinparmprobs); - return sizeof(*uint_ptr); - case 6: /* icmpInSrcQuenchs */ - *uint_ptr = STATS_GET(mib2.icmpinsrcquenchs); - return sizeof(*uint_ptr); - case 7: /* icmpInRedirects */ - *uint_ptr = STATS_GET(mib2.icmpinredirects); - return sizeof(*uint_ptr); - case 8: /* icmpInEchos */ - *uint_ptr = STATS_GET(mib2.icmpinechos); - return sizeof(*uint_ptr); - case 9: /* icmpInEchoReps */ - *uint_ptr = STATS_GET(mib2.icmpinechoreps); - return sizeof(*uint_ptr); - case 10: /* icmpInTimestamps */ - *uint_ptr = STATS_GET(mib2.icmpintimestamps); - return sizeof(*uint_ptr); - case 11: /* icmpInTimestampReps */ - *uint_ptr = STATS_GET(mib2.icmpintimestampreps); - return sizeof(*uint_ptr); - case 12: /* icmpInAddrMasks */ - *uint_ptr = STATS_GET(mib2.icmpinaddrmasks); - return sizeof(*uint_ptr); - case 13: /* icmpInAddrMaskReps */ - *uint_ptr = STATS_GET(mib2.icmpinaddrmaskreps); - return sizeof(*uint_ptr); - case 14: /* icmpOutMsgs */ - *uint_ptr = STATS_GET(mib2.icmpoutmsgs); - return sizeof(*uint_ptr); - case 15: /* icmpOutErrors */ - *uint_ptr = STATS_GET(mib2.icmpouterrors); - return sizeof(*uint_ptr); - case 16: /* icmpOutDestUnreachs */ - *uint_ptr = STATS_GET(mib2.icmpoutdestunreachs); - return sizeof(*uint_ptr); - case 17: /* icmpOutTimeExcds */ - *uint_ptr = STATS_GET(mib2.icmpouttimeexcds); - return sizeof(*uint_ptr); - case 18: /* icmpOutParmProbs: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 19: /* icmpOutSrcQuenchs: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 20: /* icmpOutRedirects: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 21: /* icmpOutEchos */ - *uint_ptr = STATS_GET(mib2.icmpoutechos); - return sizeof(*uint_ptr); - case 22: /* icmpOutEchoReps */ - *uint_ptr = STATS_GET(mib2.icmpoutechoreps); - return sizeof(*uint_ptr); - case 23: /* icmpOutTimestamps: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 24: /* icmpOutTimestampReps: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 25: /* icmpOutAddrMasks: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - case 26: /* icmpOutAddrMaskReps: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG, ("icmp_get_value(): unknown id: %"S32_F"\n", node->oid)); - break; - } - - return 0; -} - - -static const struct snmp_scalar_array_node_def icmp_nodes[] = { - { 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 7, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - { 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {23, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, - {26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} -}; - -const struct snmp_scalar_array_node snmp_mib2_icmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(5, icmp_nodes, icmp_get_value, NULL, NULL); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_ICMP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_interfaces.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_interfaces.c deleted file mode 100644 index 5f12dd552..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_interfaces.c +++ /dev/null @@ -1,368 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) INTERFACES objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/netif.h" -#include "lwip/stats.h" - -#include - -#if LWIP_SNMP && SNMP_LWIP_MIB2 - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - - -/* --- interfaces .1.3.6.1.2.1.2 ----------------------------------------------------- */ - -static s16_t -interfaces_get_value(struct snmp_node_instance *instance, void *value) -{ - if (instance->node->oid == 1) { - s32_t *sint_ptr = (s32_t *)value; - s32_t num_netifs = 0; - - struct netif *netif; - NETIF_FOREACH(netif) { - num_netifs++; - } - - *sint_ptr = num_netifs; - return sizeof(*sint_ptr); - } - - return 0; -} - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range interfaces_Table_oid_ranges[] = { - { 1, 0xff } /* netif->num is u8_t */ -}; - -static const u8_t iftable_ifOutQLen = 0; - -static const u8_t iftable_ifOperStatus_up = 1; -static const u8_t iftable_ifOperStatus_down = 2; - -static const u8_t iftable_ifAdminStatus_up = 1; -static const u8_t iftable_ifAdminStatus_lowerLayerDown = 7; -static const u8_t iftable_ifAdminStatus_down = 2; - -static snmp_err_t -interfaces_Table_get_cell_instance(const u32_t *column, const u32_t *row_oid, u8_t row_oid_len, struct snmp_node_instance *cell_instance) -{ - u32_t ifIndex; - struct netif *netif; - - LWIP_UNUSED_ARG(column); - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, interfaces_Table_oid_ranges, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get netif index from incoming OID */ - ifIndex = row_oid[0]; - - /* find netif with index */ - NETIF_FOREACH(netif) { - if (netif_to_num(netif) == ifIndex) { - /* store netif pointer for subsequent operations (get/test/set) */ - cell_instance->reference.ptr = netif; - return SNMP_ERR_NOERROR; - } - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -interfaces_Table_get_next_cell_instance(const u32_t *column, struct snmp_obj_id *row_oid, struct snmp_node_instance *cell_instance) -{ - struct netif *netif; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; - - LWIP_UNUSED_ARG(column); - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - NETIF_FOREACH(netif) { - u32_t test_oid[LWIP_ARRAYSIZE(interfaces_Table_oid_ranges)]; - test_oid[0] = netif_to_num(netif); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(interfaces_Table_oid_ranges), netif); - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* store netif pointer for subsequent operations (get/test/set) */ - cell_instance->reference.ptr = /* (struct netif*) */state.reference; - return SNMP_ERR_NOERROR; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static s16_t -interfaces_Table_get_value(struct snmp_node_instance *instance, void *value) -{ - struct netif *netif = (struct netif *)instance->reference.ptr; - u32_t *value_u32 = (u32_t *)value; - s32_t *value_s32 = (s32_t *)value; - u16_t value_len; - - switch (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id)) { - case 1: /* ifIndex */ - *value_s32 = netif_to_num(netif); - value_len = sizeof(*value_s32); - break; - case 2: /* ifDescr */ - value_len = sizeof(netif->name); - MEMCPY(value, netif->name, value_len); - break; - case 3: /* ifType */ - *value_s32 = netif->link_type; - value_len = sizeof(*value_s32); - break; - case 4: /* ifMtu */ - *value_s32 = netif->mtu; - value_len = sizeof(*value_s32); - break; - case 5: /* ifSpeed */ - *value_u32 = netif->link_speed; - value_len = sizeof(*value_u32); - break; - case 6: /* ifPhysAddress */ - value_len = sizeof(netif->hwaddr); - MEMCPY(value, &netif->hwaddr, value_len); - break; - case 7: /* ifAdminStatus */ - if (netif_is_up(netif)) { - *value_s32 = iftable_ifOperStatus_up; - } else { - *value_s32 = iftable_ifOperStatus_down; - } - value_len = sizeof(*value_s32); - break; - case 8: /* ifOperStatus */ - if (netif_is_up(netif)) { - if (netif_is_link_up(netif)) { - *value_s32 = iftable_ifAdminStatus_up; - } else { - *value_s32 = iftable_ifAdminStatus_lowerLayerDown; - } - } else { - *value_s32 = iftable_ifAdminStatus_down; - } - value_len = sizeof(*value_s32); - break; - case 9: /* ifLastChange */ - *value_u32 = netif->ts; - value_len = sizeof(*value_u32); - break; - case 10: /* ifInOctets */ - *value_u32 = netif->mib2_counters.ifinoctets; - value_len = sizeof(*value_u32); - break; - case 11: /* ifInUcastPkts */ - *value_u32 = netif->mib2_counters.ifinucastpkts; - value_len = sizeof(*value_u32); - break; - case 12: /* ifInNUcastPkts */ - *value_u32 = netif->mib2_counters.ifinnucastpkts; - value_len = sizeof(*value_u32); - break; - case 13: /* ifInDiscards */ - *value_u32 = netif->mib2_counters.ifindiscards; - value_len = sizeof(*value_u32); - break; - case 14: /* ifInErrors */ - *value_u32 = netif->mib2_counters.ifinerrors; - value_len = sizeof(*value_u32); - break; - case 15: /* ifInUnkownProtos */ - *value_u32 = netif->mib2_counters.ifinunknownprotos; - value_len = sizeof(*value_u32); - break; - case 16: /* ifOutOctets */ - *value_u32 = netif->mib2_counters.ifoutoctets; - value_len = sizeof(*value_u32); - break; - case 17: /* ifOutUcastPkts */ - *value_u32 = netif->mib2_counters.ifoutucastpkts; - value_len = sizeof(*value_u32); - break; - case 18: /* ifOutNUcastPkts */ - *value_u32 = netif->mib2_counters.ifoutnucastpkts; - value_len = sizeof(*value_u32); - break; - case 19: /* ifOutDiscarts */ - *value_u32 = netif->mib2_counters.ifoutdiscards; - value_len = sizeof(*value_u32); - break; - case 20: /* ifOutErrors */ - *value_u32 = netif->mib2_counters.ifouterrors; - value_len = sizeof(*value_u32); - break; - case 21: /* ifOutQLen */ - *value_u32 = iftable_ifOutQLen; - value_len = sizeof(*value_u32); - break; - /** @note returning zeroDotZero (0.0) no media specific MIB support */ - case 22: /* ifSpecific */ - value_len = snmp_zero_dot_zero.len * sizeof(u32_t); - MEMCPY(value, snmp_zero_dot_zero.id, value_len); - break; - default: - return 0; - } - - return value_len; -} - -#if !SNMP_SAFE_REQUESTS - -static snmp_err_t -interfaces_Table_set_test(struct snmp_node_instance *instance, u16_t len, void *value) -{ - s32_t *sint_ptr = (s32_t *)value; - - /* stack should never call this method for another column, - because all other columns are set to readonly */ - LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7)); - LWIP_UNUSED_ARG(len); - - if (*sint_ptr == 1 || *sint_ptr == 2) { - return SNMP_ERR_NOERROR; - } - - return SNMP_ERR_WRONGVALUE; -} - -static snmp_err_t -interfaces_Table_set_value(struct snmp_node_instance *instance, u16_t len, void *value) -{ - struct netif *netif = (struct netif *)instance->reference.ptr; - s32_t *sint_ptr = (s32_t *)value; - - /* stack should never call this method for another column, - because all other columns are set to readonly */ - LWIP_ASSERT("Invalid column", (SNMP_TABLE_GET_COLUMN_FROM_OID(instance->instance_oid.id) == 7)); - LWIP_UNUSED_ARG(len); - - if (*sint_ptr == 1) { - netif_set_up(netif); - } else if (*sint_ptr == 2) { - netif_set_down(netif); - } - - return SNMP_ERR_NOERROR; -} - -#endif /* SNMP_SAFE_REQUESTS */ - -static const struct snmp_scalar_node interfaces_Number = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, interfaces_get_value); - -static const struct snmp_table_col_def interfaces_Table_columns[] = { - { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifIndex */ - { 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifDescr */ - { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifType */ - { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifMtu */ - { 5, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifSpeed */ - { 6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifPhysAddress */ -#if !SNMP_SAFE_REQUESTS - { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE }, /* ifAdminStatus */ -#else - { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifAdminStatus */ -#endif - { 8, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOperStatus */ - { 9, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifLastChange */ - { 10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInOctets */ - { 11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUcastPkts */ - { 12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInNUcastPkts */ - { 13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInDiscarts */ - { 14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInErrors */ - { 15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifInUnkownProtos */ - { 16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutOctets */ - { 17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutUcastPkts */ - { 18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutNUcastPkts */ - { 19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutDiscarts */ - { 20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutErrors */ - { 21, SNMP_ASN1_TYPE_GAUGE, SNMP_NODE_INSTANCE_READ_ONLY }, /* ifOutQLen */ - { 22, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY } /* ifSpecific */ -}; - -#if !SNMP_SAFE_REQUESTS -static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( - 2, interfaces_Table_columns, - interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, - interfaces_Table_get_value, interfaces_Table_set_test, interfaces_Table_set_value); -#else -static const struct snmp_table_node interfaces_Table = SNMP_TABLE_CREATE( - 2, interfaces_Table_columns, - interfaces_Table_get_cell_instance, interfaces_Table_get_next_cell_instance, - interfaces_Table_get_value, NULL, NULL); -#endif - -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ -CREATE_LWIP_SYNC_NODE(1, interfaces_Number) -CREATE_LWIP_SYNC_NODE(2, interfaces_Table) - -static const struct snmp_node *const interface_nodes[] = { - &SYNC_NODE_NAME(interfaces_Number).node.node, - &SYNC_NODE_NAME(interfaces_Table).node.node -}; - -const struct snmp_tree_node snmp_mib2_interface_root = SNMP_CREATE_TREE_NODE(2, interface_nodes); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_ip.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_ip.c deleted file mode 100644 index 6931049e7..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_ip.c +++ /dev/null @@ -1,731 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) IP objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/stats.h" -#include "lwip/netif.h" -#include "lwip/ip.h" -#include "lwip/etharp.h" - -#if LWIP_SNMP && SNMP_LWIP_MIB2 - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -#if LWIP_IPV4 -/* --- ip .1.3.6.1.2.1.4 ----------------------------------------------------- */ - -static s16_t -ip_get_value(struct snmp_node_instance *instance, void *value) -{ - s32_t *sint_ptr = (s32_t *)value; - u32_t *uint_ptr = (u32_t *)value; - - switch (instance->node->oid) { - case 1: /* ipForwarding */ -#if IP_FORWARD - /* forwarding */ - *sint_ptr = 1; -#else - /* not-forwarding */ - *sint_ptr = 2; -#endif - return sizeof(*sint_ptr); - case 2: /* ipDefaultTTL */ - *sint_ptr = IP_DEFAULT_TTL; - return sizeof(*sint_ptr); - case 3: /* ipInReceives */ - *uint_ptr = STATS_GET(mib2.ipinreceives); - return sizeof(*uint_ptr); - case 4: /* ipInHdrErrors */ - *uint_ptr = STATS_GET(mib2.ipinhdrerrors); - return sizeof(*uint_ptr); - case 5: /* ipInAddrErrors */ - *uint_ptr = STATS_GET(mib2.ipinaddrerrors); - return sizeof(*uint_ptr); - case 6: /* ipForwDatagrams */ - *uint_ptr = STATS_GET(mib2.ipforwdatagrams); - return sizeof(*uint_ptr); - case 7: /* ipInUnknownProtos */ - *uint_ptr = STATS_GET(mib2.ipinunknownprotos); - return sizeof(*uint_ptr); - case 8: /* ipInDiscards */ - *uint_ptr = STATS_GET(mib2.ipindiscards); - return sizeof(*uint_ptr); - case 9: /* ipInDelivers */ - *uint_ptr = STATS_GET(mib2.ipindelivers); - return sizeof(*uint_ptr); - case 10: /* ipOutRequests */ - *uint_ptr = STATS_GET(mib2.ipoutrequests); - return sizeof(*uint_ptr); - case 11: /* ipOutDiscards */ - *uint_ptr = STATS_GET(mib2.ipoutdiscards); - return sizeof(*uint_ptr); - case 12: /* ipOutNoRoutes */ - *uint_ptr = STATS_GET(mib2.ipoutnoroutes); - return sizeof(*uint_ptr); - case 13: /* ipReasmTimeout */ -#if IP_REASSEMBLY - *sint_ptr = IP_REASS_MAXAGE; -#else - *sint_ptr = 0; -#endif - return sizeof(*sint_ptr); - case 14: /* ipReasmReqds */ - *uint_ptr = STATS_GET(mib2.ipreasmreqds); - return sizeof(*uint_ptr); - case 15: /* ipReasmOKs */ - *uint_ptr = STATS_GET(mib2.ipreasmoks); - return sizeof(*uint_ptr); - case 16: /* ipReasmFails */ - *uint_ptr = STATS_GET(mib2.ipreasmfails); - return sizeof(*uint_ptr); - case 17: /* ipFragOKs */ - *uint_ptr = STATS_GET(mib2.ipfragoks); - return sizeof(*uint_ptr); - case 18: /* ipFragFails */ - *uint_ptr = STATS_GET(mib2.ipfragfails); - return sizeof(*uint_ptr); - case 19: /* ipFragCreates */ - *uint_ptr = STATS_GET(mib2.ipfragcreates); - return sizeof(*uint_ptr); - case 23: /* ipRoutingDiscards: not supported -> always 0 */ - *uint_ptr = 0; - return sizeof(*uint_ptr); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG, ("ip_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); - break; - } - - return 0; -} - -/** - * Test ip object value before setting. - * - * @param instance node instance - * @param len return value space (in bytes) - * @param value points to (varbind) space to copy value from. - * - * @note we allow set if the value matches the hardwired value, - * otherwise return badvalue. - */ -static snmp_err_t -ip_set_test(struct snmp_node_instance *instance, u16_t len, void *value) -{ - snmp_err_t ret = SNMP_ERR_WRONGVALUE; - s32_t *sint_ptr = (s32_t *)value; - - LWIP_UNUSED_ARG(len); - switch (instance->node->oid) { - case 1: /* ipForwarding */ -#if IP_FORWARD - /* forwarding */ - if (*sint_ptr == 1) -#else - /* not-forwarding */ - if (*sint_ptr == 2) -#endif - { - ret = SNMP_ERR_NOERROR; - } - break; - case 2: /* ipDefaultTTL */ - if (*sint_ptr == IP_DEFAULT_TTL) { - ret = SNMP_ERR_NOERROR; - } - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG, ("ip_set_test(): unknown id: %"S32_F"\n", instance->node->oid)); - break; - } - - return ret; -} - -static snmp_err_t -ip_set_value(struct snmp_node_instance *instance, u16_t len, void *value) -{ - LWIP_UNUSED_ARG(instance); - LWIP_UNUSED_ARG(len); - LWIP_UNUSED_ARG(value); - /* nothing to do here because in set_test we only accept values being the same as our own stored value -> no need to store anything */ - return SNMP_ERR_NOERROR; -} - -/* --- ipAddrTable --- */ - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range ip_AddrTable_oid_ranges[] = { - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff } /* IP D */ -}; - -static snmp_err_t -ip_AddrTable_get_cell_value_core(struct netif *netif, const u32_t *column, union snmp_variant_value *value, u32_t *value_len) -{ - LWIP_UNUSED_ARG(value_len); - - switch (*column) { - case 1: /* ipAdEntAddr */ - value->u32 = netif_ip4_addr(netif)->addr; - break; - case 2: /* ipAdEntIfIndex */ - value->u32 = netif_to_num(netif); - break; - case 3: /* ipAdEntNetMask */ - value->u32 = netif_ip4_netmask(netif)->addr; - break; - case 4: /* ipAdEntBcastAddr */ - /* lwIP oddity, there's no broadcast - address in the netif we can rely on */ - value->u32 = IPADDR_BROADCAST & 1; - break; - case 5: /* ipAdEntReasmMaxSize */ -#if IP_REASSEMBLY - /* @todo The theoretical maximum is IP_REASS_MAX_PBUFS * size of the pbufs, - * but only if receiving one fragmented packet at a time. - * The current solution is to calculate for 2 simultaneous packets... - */ - value->u32 = (IP_HLEN + ((IP_REASS_MAX_PBUFS / 2) * - (PBUF_POOL_BUFSIZE - PBUF_LINK_ENCAPSULATION_HLEN - PBUF_LINK_HLEN - IP_HLEN))); -#else - /** @todo returning MTU would be a bad thing and - returning a wild guess like '576' isn't good either */ - value->u32 = 0; -#endif - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -ip_AddrTable_get_cell_value(const u32_t *column, const u32_t *row_oid, u8_t row_oid_len, union snmp_variant_value *value, u32_t *value_len) -{ - ip4_addr_t ip; - struct netif *netif; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, ip_AddrTable_oid_ranges, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IP from incoming OID */ - snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */ - - /* find netif with requested ip */ - NETIF_FOREACH(netif) { - if (ip4_addr_cmp(&ip, netif_ip4_addr(netif))) { - /* fill in object properties */ - return ip_AddrTable_get_cell_value_core(netif, column, value, value_len); - } - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -ip_AddrTable_get_next_cell_instance_and_value(const u32_t *column, struct snmp_obj_id *row_oid, union snmp_variant_value *value, u32_t *value_len) -{ - struct netif *netif; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - NETIF_FOREACH(netif) { - u32_t test_oid[LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges)]; - snmp_ip4_to_oid(netif_ip4_addr(netif), &test_oid[0]); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_AddrTable_oid_ranges), netif); - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return ip_AddrTable_get_cell_value_core((struct netif *)state.reference, column, value, value_len); - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -/* --- ipRouteTable --- */ - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range ip_RouteTable_oid_ranges[] = { - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff }, /* IP D */ -}; - -static snmp_err_t -ip_RouteTable_get_cell_value_core(struct netif *netif, u8_t default_route, const u32_t *column, union snmp_variant_value *value, u32_t *value_len) -{ - switch (*column) { - case 1: /* ipRouteDest */ - if (default_route) { - /* default rte has 0.0.0.0 dest */ - value->u32 = IP4_ADDR_ANY4->addr; - } else { - /* netifs have netaddress dest */ - ip4_addr_t tmp; - ip4_addr_get_network(&tmp, netif_ip4_addr(netif), netif_ip4_netmask(netif)); - value->u32 = tmp.addr; - } - break; - case 2: /* ipRouteIfIndex */ - value->u32 = netif_to_num(netif); - break; - case 3: /* ipRouteMetric1 */ - if (default_route) { - value->s32 = 1; /* default */ - } else { - value->s32 = 0; /* normal */ - } - break; - case 4: /* ipRouteMetric2 */ - case 5: /* ipRouteMetric3 */ - case 6: /* ipRouteMetric4 */ - value->s32 = -1; /* none */ - break; - case 7: /* ipRouteNextHop */ - if (default_route) { - /* default rte: gateway */ - value->u32 = netif_ip4_gw(netif)->addr; - } else { - /* other rtes: netif ip_addr */ - value->u32 = netif_ip4_addr(netif)->addr; - } - break; - case 8: /* ipRouteType */ - if (default_route) { - /* default rte is indirect */ - value->u32 = 4; /* indirect */ - } else { - /* other rtes are direct */ - value->u32 = 3; /* direct */ - } - break; - case 9: /* ipRouteProto */ - /* locally defined routes */ - value->u32 = 2; /* local */ - break; - case 10: /* ipRouteAge */ - /* @todo (sysuptime - timestamp last change) / 100 */ - value->u32 = 0; - break; - case 11: /* ipRouteMask */ - if (default_route) { - /* default rte use 0.0.0.0 mask */ - value->u32 = IP4_ADDR_ANY4->addr; - } else { - /* other rtes use netmask */ - value->u32 = netif_ip4_netmask(netif)->addr; - } - break; - case 12: /* ipRouteMetric5 */ - value->s32 = -1; /* none */ - break; - case 13: /* ipRouteInfo */ - value->const_ptr = snmp_zero_dot_zero.id; - *value_len = snmp_zero_dot_zero.len * sizeof(u32_t); - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -ip_RouteTable_get_cell_value(const u32_t *column, const u32_t *row_oid, u8_t row_oid_len, union snmp_variant_value *value, u32_t *value_len) -{ - ip4_addr_t test_ip; - struct netif *netif; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, ip_RouteTable_oid_ranges, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IP and port from incoming OID */ - snmp_oid_to_ip4(&row_oid[0], &test_ip); /* we know it succeeds because of oid_in_range check above */ - - /* default route is on default netif */ - if (ip4_addr_isany_val(test_ip) && (netif_default != NULL)) { - /* fill in object properties */ - return ip_RouteTable_get_cell_value_core(netif_default, 1, column, value, value_len); - } - - /* find netif with requested route */ - NETIF_FOREACH(netif) { - ip4_addr_t dst; - ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif)); - - if (ip4_addr_cmp(&dst, &test_ip)) { - /* fill in object properties */ - return ip_RouteTable_get_cell_value_core(netif, 0, column, value, value_len); - } - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -ip_RouteTable_get_next_cell_instance_and_value(const u32_t *column, struct snmp_obj_id *row_oid, union snmp_variant_value *value, u32_t *value_len) -{ - struct netif *netif; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)]; - u32_t test_oid[LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)]; - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges)); - - /* check default route */ - if (netif_default != NULL) { - snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[0]); - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif_default); - } - - /* iterate over all possible OIDs to find the next one */ - NETIF_FOREACH(netif) { - ip4_addr_t dst; - ip4_addr_get_network(&dst, netif_ip4_addr(netif), netif_ip4_netmask(netif)); - - /* check generated OID: is it a candidate for the next one? */ - if (!ip4_addr_isany_val(dst)) { - snmp_ip4_to_oid(&dst, &test_oid[0]); - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_RouteTable_oid_ranges), netif); - } - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - ip4_addr_t dst; - snmp_oid_to_ip4(&result_temp[0], &dst); - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return ip_RouteTable_get_cell_value_core((struct netif *)state.reference, ip4_addr_isany_val(dst), column, value, value_len); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -#if LWIP_ARP && LWIP_IPV4 -/* --- ipNetToMediaTable --- */ - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range ip_NetToMediaTable_oid_ranges[] = { - { 1, 0xff }, /* IfIndex */ - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff } /* IP D */ -}; - -static snmp_err_t -ip_NetToMediaTable_get_cell_value_core(size_t arp_table_index, const u32_t *column, union snmp_variant_value *value, u32_t *value_len) -{ - ip4_addr_t *ip; - struct netif *netif; - struct eth_addr *ethaddr; - - etharp_get_entry(arp_table_index, &ip, &netif, ðaddr); - - /* value */ - switch (*column) { - case 1: /* atIfIndex / ipNetToMediaIfIndex */ - value->u32 = netif_to_num(netif); - break; - case 2: /* atPhysAddress / ipNetToMediaPhysAddress */ - value->ptr = ethaddr; - *value_len = sizeof(*ethaddr); - break; - case 3: /* atNetAddress / ipNetToMediaNetAddress */ - value->u32 = ip->addr; - break; - case 4: /* ipNetToMediaType */ - value->u32 = 3; /* dynamic*/ - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -ip_NetToMediaTable_get_cell_value(const u32_t *column, const u32_t *row_oid, u8_t row_oid_len, union snmp_variant_value *value, u32_t *value_len) -{ - ip4_addr_t ip_in; - u8_t netif_index; - size_t i; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, ip_NetToMediaTable_oid_ranges, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IP from incoming OID */ - netif_index = (u8_t)row_oid[0]; - snmp_oid_to_ip4(&row_oid[1], &ip_in); /* we know it succeeds because of oid_in_range check above */ - - /* find requested entry */ - for (i = 0; i < ARP_TABLE_SIZE; i++) { - ip4_addr_t *ip; - struct netif *netif; - struct eth_addr *ethaddr; - - if (etharp_get_entry(i, &ip, &netif, ðaddr)) { - if ((netif_index == netif_to_num(netif)) && ip4_addr_cmp(&ip_in, ip)) { - /* fill in object properties */ - return ip_NetToMediaTable_get_cell_value_core(i, column, value, value_len); - } - } - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -ip_NetToMediaTable_get_next_cell_instance_and_value(const u32_t *column, struct snmp_obj_id *row_oid, union snmp_variant_value *value, u32_t *value_len) -{ - size_t i; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)]; - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - for (i = 0; i < ARP_TABLE_SIZE; i++) { - ip4_addr_t *ip; - struct netif *netif; - struct eth_addr *ethaddr; - - if (etharp_get_entry(i, &ip, &netif, ðaddr)) { - u32_t test_oid[LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges)]; - - test_oid[0] = netif_to_num(netif); - snmp_ip4_to_oid(ip, &test_oid[1]); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(ip_NetToMediaTable_oid_ranges), LWIP_PTR_NUMERIC_CAST(void *, i)); - } - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return ip_NetToMediaTable_get_cell_value_core(LWIP_PTR_NUMERIC_CAST(size_t, state.reference), column, value, value_len); - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -#endif /* LWIP_ARP && LWIP_IPV4 */ - -static const struct snmp_scalar_node ip_Forwarding = SNMP_SCALAR_CREATE_NODE(1, SNMP_NODE_INSTANCE_READ_WRITE, SNMP_ASN1_TYPE_INTEGER, ip_get_value, ip_set_test, ip_set_value); -static const struct snmp_scalar_node ip_DefaultTTL = SNMP_SCALAR_CREATE_NODE(2, SNMP_NODE_INSTANCE_READ_WRITE, SNMP_ASN1_TYPE_INTEGER, ip_get_value, ip_set_test, ip_set_value); -static const struct snmp_scalar_node ip_InReceives = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_InHdrErrors = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_InAddrErrors = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_ForwDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_InUnknownProtos = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_InDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_InDelivers = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_OutRequests = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_OutDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_OutNoRoutes = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_ReasmTimeout = SNMP_SCALAR_CREATE_NODE_READONLY(13, SNMP_ASN1_TYPE_INTEGER, ip_get_value); -static const struct snmp_scalar_node ip_ReasmReqds = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_ReasmOKs = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_ReasmFails = SNMP_SCALAR_CREATE_NODE_READONLY(16, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_FragOKs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_FragFails = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_FragCreates = SNMP_SCALAR_CREATE_NODE_READONLY(19, SNMP_ASN1_TYPE_COUNTER, ip_get_value); -static const struct snmp_scalar_node ip_RoutingDiscards = SNMP_SCALAR_CREATE_NODE_READONLY(23, SNMP_ASN1_TYPE_COUNTER, ip_get_value); - -static const struct snmp_table_simple_col_def ip_AddrTable_columns[] = { - { 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntAddr */ - { 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntIfIndex */ - { 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntNetMask */ - { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipAdEntBcastAddr */ - { 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* ipAdEntReasmMaxSize */ -}; - -static const struct snmp_table_simple_node ip_AddrTable = SNMP_TABLE_CREATE_SIMPLE(20, ip_AddrTable_columns, ip_AddrTable_get_cell_value, ip_AddrTable_get_next_cell_instance_and_value); - -static const struct snmp_table_simple_col_def ip_RouteTable_columns[] = { - { 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteDest */ - { 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteIfIndex */ - { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric1 */ - { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric2 */ - { 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric3 */ - { 6, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric4 */ - { 7, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteNextHop */ - { 8, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteType */ - { 9, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteProto */ - { 10, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteAge */ - { 11, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipRouteMask */ - { 12, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_S32 }, /* ipRouteMetric5 */ - { 13, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_VARIANT_VALUE_TYPE_PTR } /* ipRouteInfo */ -}; - -static const struct snmp_table_simple_node ip_RouteTable = SNMP_TABLE_CREATE_SIMPLE(21, ip_RouteTable_columns, ip_RouteTable_get_cell_value, ip_RouteTable_get_next_cell_instance_and_value); -#endif /* LWIP_IPV4 */ - -#if LWIP_ARP && LWIP_IPV4 -static const struct snmp_table_simple_col_def ip_NetToMediaTable_columns[] = { - { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipNetToMediaIfIndex */ - { 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_VARIANT_VALUE_TYPE_PTR }, /* ipNetToMediaPhysAddress */ - { 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* ipNetToMediaNetAddress */ - { 4, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* ipNetToMediaType */ -}; - -static const struct snmp_table_simple_node ip_NetToMediaTable = SNMP_TABLE_CREATE_SIMPLE(22, ip_NetToMediaTable_columns, ip_NetToMediaTable_get_cell_value, ip_NetToMediaTable_get_next_cell_instance_and_value); -#endif /* LWIP_ARP && LWIP_IPV4 */ - -#if LWIP_IPV4 -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ -CREATE_LWIP_SYNC_NODE( 1, ip_Forwarding) -CREATE_LWIP_SYNC_NODE( 2, ip_DefaultTTL) -CREATE_LWIP_SYNC_NODE( 3, ip_InReceives) -CREATE_LWIP_SYNC_NODE( 4, ip_InHdrErrors) -CREATE_LWIP_SYNC_NODE( 5, ip_InAddrErrors) -CREATE_LWIP_SYNC_NODE( 6, ip_ForwDatagrams) -CREATE_LWIP_SYNC_NODE( 7, ip_InUnknownProtos) -CREATE_LWIP_SYNC_NODE( 8, ip_InDiscards) -CREATE_LWIP_SYNC_NODE( 9, ip_InDelivers) -CREATE_LWIP_SYNC_NODE(10, ip_OutRequests) -CREATE_LWIP_SYNC_NODE(11, ip_OutDiscards) -CREATE_LWIP_SYNC_NODE(12, ip_OutNoRoutes) -CREATE_LWIP_SYNC_NODE(13, ip_ReasmTimeout) -CREATE_LWIP_SYNC_NODE(14, ip_ReasmReqds) -CREATE_LWIP_SYNC_NODE(15, ip_ReasmOKs) -CREATE_LWIP_SYNC_NODE(15, ip_ReasmFails) -CREATE_LWIP_SYNC_NODE(17, ip_FragOKs) -CREATE_LWIP_SYNC_NODE(18, ip_FragFails) -CREATE_LWIP_SYNC_NODE(19, ip_FragCreates) -CREATE_LWIP_SYNC_NODE(20, ip_AddrTable) -CREATE_LWIP_SYNC_NODE(21, ip_RouteTable) -#if LWIP_ARP -CREATE_LWIP_SYNC_NODE(22, ip_NetToMediaTable) -#endif /* LWIP_ARP */ -CREATE_LWIP_SYNC_NODE(23, ip_RoutingDiscards) - -static const struct snmp_node *const ip_nodes[] = { - &SYNC_NODE_NAME(ip_Forwarding).node.node, - &SYNC_NODE_NAME(ip_DefaultTTL).node.node, - &SYNC_NODE_NAME(ip_InReceives).node.node, - &SYNC_NODE_NAME(ip_InHdrErrors).node.node, - &SYNC_NODE_NAME(ip_InAddrErrors).node.node, - &SYNC_NODE_NAME(ip_ForwDatagrams).node.node, - &SYNC_NODE_NAME(ip_InUnknownProtos).node.node, - &SYNC_NODE_NAME(ip_InDiscards).node.node, - &SYNC_NODE_NAME(ip_InDelivers).node.node, - &SYNC_NODE_NAME(ip_OutRequests).node.node, - &SYNC_NODE_NAME(ip_OutDiscards).node.node, - &SYNC_NODE_NAME(ip_OutNoRoutes).node.node, - &SYNC_NODE_NAME(ip_ReasmTimeout).node.node, - &SYNC_NODE_NAME(ip_ReasmReqds).node.node, - &SYNC_NODE_NAME(ip_ReasmOKs).node.node, - &SYNC_NODE_NAME(ip_ReasmFails).node.node, - &SYNC_NODE_NAME(ip_FragOKs).node.node, - &SYNC_NODE_NAME(ip_FragFails).node.node, - &SYNC_NODE_NAME(ip_FragCreates).node.node, - &SYNC_NODE_NAME(ip_AddrTable).node.node, - &SYNC_NODE_NAME(ip_RouteTable).node.node, -#if LWIP_ARP - &SYNC_NODE_NAME(ip_NetToMediaTable).node.node, -#endif /* LWIP_ARP */ - &SYNC_NODE_NAME(ip_RoutingDiscards).node.node -}; - -const struct snmp_tree_node snmp_mib2_ip_root = SNMP_CREATE_TREE_NODE(4, ip_nodes); -#endif /* LWIP_IPV4 */ - -/* --- at .1.3.6.1.2.1.3 ----------------------------------------------------- */ - -#if LWIP_ARP && LWIP_IPV4 -/* at node table is a subset of ip_nettomedia table (same rows but less columns) */ -static const struct snmp_table_simple_col_def at_Table_columns[] = { - { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* atIfIndex */ - { 2, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_VARIANT_VALUE_TYPE_PTR }, /* atPhysAddress */ - { 3, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 } /* atNetAddress */ -}; - -static const struct snmp_table_simple_node at_Table = SNMP_TABLE_CREATE_SIMPLE(1, at_Table_columns, ip_NetToMediaTable_get_cell_value, ip_NetToMediaTable_get_next_cell_instance_and_value); - -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ -CREATE_LWIP_SYNC_NODE(1, at_Table) - -static const struct snmp_node *const at_nodes[] = { - &SYNC_NODE_NAME(at_Table).node.node -}; - -const struct snmp_tree_node snmp_mib2_at_root = SNMP_CREATE_TREE_NODE(3, at_nodes); -#endif /* LWIP_ARP && LWIP_IPV4 */ - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_snmp.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_snmp.c deleted file mode 100644 index ca22e4163..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_snmp.c +++ /dev/null @@ -1,227 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) SNMP objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_scalar.h" - -#if LWIP_SNMP && SNMP_LWIP_MIB2 - -#define MIB2_AUTH_TRAPS_ENABLED 1 -#define MIB2_AUTH_TRAPS_DISABLED 2 - -/* --- snmp .1.3.6.1.2.1.11 ----------------------------------------------------- */ -static s16_t -snmp_get_value(const struct snmp_scalar_array_node_def *node, void *value) -{ - u32_t *uint_ptr = (u32_t *)value; - switch (node->oid) { - case 1: /* snmpInPkts */ - *uint_ptr = snmp_stats.inpkts; - break; - case 2: /* snmpOutPkts */ - *uint_ptr = snmp_stats.outpkts; - break; - case 3: /* snmpInBadVersions */ - *uint_ptr = snmp_stats.inbadversions; - break; - case 4: /* snmpInBadCommunityNames */ - *uint_ptr = snmp_stats.inbadcommunitynames; - break; - case 5: /* snmpInBadCommunityUses */ - *uint_ptr = snmp_stats.inbadcommunityuses; - break; - case 6: /* snmpInASNParseErrs */ - *uint_ptr = snmp_stats.inasnparseerrs; - break; - case 8: /* snmpInTooBigs */ - *uint_ptr = snmp_stats.intoobigs; - break; - case 9: /* snmpInNoSuchNames */ - *uint_ptr = snmp_stats.innosuchnames; - break; - case 10: /* snmpInBadValues */ - *uint_ptr = snmp_stats.inbadvalues; - break; - case 11: /* snmpInReadOnlys */ - *uint_ptr = snmp_stats.inreadonlys; - break; - case 12: /* snmpInGenErrs */ - *uint_ptr = snmp_stats.ingenerrs; - break; - case 13: /* snmpInTotalReqVars */ - *uint_ptr = snmp_stats.intotalreqvars; - break; - case 14: /* snmpInTotalSetVars */ - *uint_ptr = snmp_stats.intotalsetvars; - break; - case 15: /* snmpInGetRequests */ - *uint_ptr = snmp_stats.ingetrequests; - break; - case 16: /* snmpInGetNexts */ - *uint_ptr = snmp_stats.ingetnexts; - break; - case 17: /* snmpInSetRequests */ - *uint_ptr = snmp_stats.insetrequests; - break; - case 18: /* snmpInGetResponses */ - *uint_ptr = snmp_stats.ingetresponses; - break; - case 19: /* snmpInTraps */ - *uint_ptr = snmp_stats.intraps; - break; - case 20: /* snmpOutTooBigs */ - *uint_ptr = snmp_stats.outtoobigs; - break; - case 21: /* snmpOutNoSuchNames */ - *uint_ptr = snmp_stats.outnosuchnames; - break; - case 22: /* snmpOutBadValues */ - *uint_ptr = snmp_stats.outbadvalues; - break; - case 24: /* snmpOutGenErrs */ - *uint_ptr = snmp_stats.outgenerrs; - break; - case 25: /* snmpOutGetRequests */ - *uint_ptr = snmp_stats.outgetrequests; - break; - case 26: /* snmpOutGetNexts */ - *uint_ptr = snmp_stats.outgetnexts; - break; - case 27: /* snmpOutSetRequests */ - *uint_ptr = snmp_stats.outsetrequests; - break; - case 28: /* snmpOutGetResponses */ - *uint_ptr = snmp_stats.outgetresponses; - break; - case 29: /* snmpOutTraps */ - *uint_ptr = snmp_stats.outtraps; - break; - case 30: /* snmpEnableAuthenTraps */ - if (snmp_get_auth_traps_enabled() == SNMP_AUTH_TRAPS_DISABLED) { - *uint_ptr = MIB2_AUTH_TRAPS_DISABLED; - } else { - *uint_ptr = MIB2_AUTH_TRAPS_ENABLED; - } - break; - case 31: /* snmpSilentDrops */ - *uint_ptr = 0; /* not supported */ - break; - case 32: /* snmpProxyDrops */ - *uint_ptr = 0; /* not supported */ - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG, ("snmp_get_value(): unknown id: %"S32_F"\n", node->oid)); - return 0; - } - - return sizeof(*uint_ptr); -} - -static snmp_err_t -snmp_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) -{ - snmp_err_t ret = SNMP_ERR_WRONGVALUE; - LWIP_UNUSED_ARG(len); - - if (node->oid == 30) { - /* snmpEnableAuthenTraps */ - s32_t *sint_ptr = (s32_t *)value; - - /* we should have writable non-volatile mem here */ - if ((*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) || (*sint_ptr == MIB2_AUTH_TRAPS_ENABLED)) { - ret = SNMP_ERR_NOERROR; - } - } - return ret; -} - -static snmp_err_t -snmp_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) -{ - LWIP_UNUSED_ARG(len); - - if (node->oid == 30) { - /* snmpEnableAuthenTraps */ - s32_t *sint_ptr = (s32_t *)value; - if (*sint_ptr == MIB2_AUTH_TRAPS_DISABLED) { - snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_DISABLED); - } else { - snmp_set_auth_traps_enabled(SNMP_AUTH_TRAPS_ENABLED); - } - } - - return SNMP_ERR_NOERROR; -} - -/* the following nodes access variables in SNMP stack (snmp_stats) from SNMP worker thread -> OK, no sync needed */ -static const struct snmp_scalar_array_node_def snmp_nodes[] = { - { 1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInPkts */ - { 2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutPkts */ - { 3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadVersions */ - { 4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityNames */ - { 5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadCommunityUses */ - { 6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInASNParseErrs */ - { 8, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTooBigs */ - { 9, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInNoSuchNames */ - {10, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInBadValues */ - {11, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInReadOnlys */ - {12, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGenErrs */ - {13, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalReqVars */ - {14, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTotalSetVars */ - {15, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetRequests */ - {16, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetNexts */ - {17, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInSetRequests */ - {18, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInGetResponses */ - {19, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpInTraps */ - {20, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTooBigs */ - {21, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutNoSuchNames */ - {22, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutBadValues */ - {24, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGenErrs */ - {25, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetRequests */ - {26, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetNexts */ - {27, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutSetRequests */ - {28, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutGetResponses */ - {29, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpOutTraps */ - {30, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_WRITE}, /* snmpEnableAuthenTraps */ - {31, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpSilentDrops */ - {32, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY} /* snmpProxyDrops */ -}; - -const struct snmp_scalar_array_node snmp_mib2_snmp_root = SNMP_SCALAR_CREATE_ARRAY_NODE(11, snmp_nodes, snmp_get_value, snmp_set_test, snmp_set_value); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_system.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_system.c deleted file mode 100644 index 71c1c29c0..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_system.c +++ /dev/null @@ -1,376 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) SYSTEM objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/sys.h" - -#include - -#if LWIP_SNMP && SNMP_LWIP_MIB2 - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -/* --- system .1.3.6.1.2.1.1 ----------------------------------------------------- */ - -/** mib-2.system.sysDescr */ -static const u8_t sysdescr_default[] = SNMP_LWIP_MIB2_SYSDESC; -static const u8_t *sysdescr = sysdescr_default; -static const u16_t *sysdescr_len = NULL; /* use strlen for determining len */ - -/** mib-2.system.sysContact */ -static const u8_t syscontact_default[] = SNMP_LWIP_MIB2_SYSCONTACT; -static const u8_t *syscontact = syscontact_default; -static const u16_t *syscontact_len = NULL; /* use strlen for determining len */ -static u8_t *syscontact_wr = NULL; /* if writable, points to the same buffer as syscontact (required for correct constness) */ -static u16_t *syscontact_wr_len = NULL; /* if writable, points to the same buffer as syscontact_len (required for correct constness) */ -static u16_t syscontact_bufsize = 0; /* 0=not writable */ - -/** mib-2.system.sysName */ -static const u8_t sysname_default[] = SNMP_LWIP_MIB2_SYSNAME; -static const u8_t *sysname = sysname_default; -static const u16_t *sysname_len = NULL; /* use strlen for determining len */ -static u8_t *sysname_wr = NULL; /* if writable, points to the same buffer as sysname (required for correct constness) */ -static u16_t *sysname_wr_len = NULL; /* if writable, points to the same buffer as sysname_len (required for correct constness) */ -static u16_t sysname_bufsize = 0; /* 0=not writable */ - -/** mib-2.system.sysLocation */ -static const u8_t syslocation_default[] = SNMP_LWIP_MIB2_SYSLOCATION; -static const u8_t *syslocation = syslocation_default; -static const u16_t *syslocation_len = NULL; /* use strlen for determining len */ -static u8_t *syslocation_wr = NULL; /* if writable, points to the same buffer as syslocation (required for correct constness) */ -static u16_t *syslocation_wr_len = NULL; /* if writable, points to the same buffer as syslocation_len (required for correct constness) */ -static u16_t syslocation_bufsize = 0; /* 0=not writable */ - -/** - * @ingroup snmp_mib2 - * Initializes sysDescr pointers. - * - * @param str if non-NULL then copy str pointer - * @param len points to string length, excluding zero terminator - */ -void -snmp_mib2_set_sysdescr(const u8_t *str, const u16_t *len) -{ - if (str != NULL) { - sysdescr = str; - sysdescr_len = len; - } -} - -/** - * @ingroup snmp_mib2 - * Initializes sysContact pointers - * - * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator. - * if set to NULL it is assumed that ocstr is NULL-terminated. - * @param bufsize size of the buffer in bytes. - * (this is required because the buffer can be overwritten by snmp-set) - * if ocstrlen is NULL buffer needs space for terminating 0 byte. - * otherwise complete buffer is used for string. - * if bufsize is set to 0, the value is regarded as read-only. - */ -void -snmp_mib2_set_syscontact(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) -{ - if (ocstr != NULL) { - syscontact = ocstr; - syscontact_wr = ocstr; - syscontact_len = ocstrlen; - syscontact_wr_len = ocstrlen; - syscontact_bufsize = bufsize; - } -} - -/** - * @ingroup snmp_mib2 - * see \ref snmp_mib2_set_syscontact but set pointer to readonly memory - */ -void -snmp_mib2_set_syscontact_readonly(const u8_t *ocstr, const u16_t *ocstrlen) -{ - if (ocstr != NULL) { - syscontact = ocstr; - syscontact_len = ocstrlen; - syscontact_wr = NULL; - syscontact_wr_len = NULL; - syscontact_bufsize = 0; - } -} - - -/** - * @ingroup snmp_mib2 - * Initializes sysName pointers - * - * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator. - * if set to NULL it is assumed that ocstr is NULL-terminated. - * @param bufsize size of the buffer in bytes. - * (this is required because the buffer can be overwritten by snmp-set) - * if ocstrlen is NULL buffer needs space for terminating 0 byte. - * otherwise complete buffer is used for string. - * if bufsize is set to 0, the value is regarded as read-only. - */ -void -snmp_mib2_set_sysname(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) -{ - if (ocstr != NULL) { - sysname = ocstr; - sysname_wr = ocstr; - sysname_len = ocstrlen; - sysname_wr_len = ocstrlen; - sysname_bufsize = bufsize; - } -} - -/** - * @ingroup snmp_mib2 - * see \ref snmp_mib2_set_sysname but set pointer to readonly memory - */ -void -snmp_mib2_set_sysname_readonly(const u8_t *ocstr, const u16_t *ocstrlen) -{ - if (ocstr != NULL) { - sysname = ocstr; - sysname_len = ocstrlen; - sysname_wr = NULL; - sysname_wr_len = NULL; - sysname_bufsize = 0; - } -} - -/** - * @ingroup snmp_mib2 - * Initializes sysLocation pointers - * - * @param ocstr if non-NULL then copy str pointer - * @param ocstrlen points to string length, excluding zero terminator. - * if set to NULL it is assumed that ocstr is NULL-terminated. - * @param bufsize size of the buffer in bytes. - * (this is required because the buffer can be overwritten by snmp-set) - * if ocstrlen is NULL buffer needs space for terminating 0 byte. - * otherwise complete buffer is used for string. - * if bufsize is set to 0, the value is regarded as read-only. - */ -void -snmp_mib2_set_syslocation(u8_t *ocstr, u16_t *ocstrlen, u16_t bufsize) -{ - if (ocstr != NULL) { - syslocation = ocstr; - syslocation_wr = ocstr; - syslocation_len = ocstrlen; - syslocation_wr_len = ocstrlen; - syslocation_bufsize = bufsize; - } -} - -/** - * @ingroup snmp_mib2 - * see \ref snmp_mib2_set_syslocation but set pointer to readonly memory - */ -void -snmp_mib2_set_syslocation_readonly(const u8_t *ocstr, const u16_t *ocstrlen) -{ - if (ocstr != NULL) { - syslocation = ocstr; - syslocation_len = ocstrlen; - syslocation_wr = NULL; - syslocation_wr_len = NULL; - syslocation_bufsize = 0; - } -} - - -static s16_t -system_get_value(const struct snmp_scalar_array_node_def *node, void *value) -{ - const u8_t *var = NULL; - const s16_t *var_len; - u16_t result; - - switch (node->oid) { - case 1: /* sysDescr */ - var = sysdescr; - var_len = (const s16_t *)sysdescr_len; - break; - case 2: { /* sysObjectID */ - const struct snmp_obj_id *dev_enterprise_oid = snmp_get_device_enterprise_oid(); - MEMCPY(value, dev_enterprise_oid->id, dev_enterprise_oid->len * sizeof(u32_t)); - return dev_enterprise_oid->len * sizeof(u32_t); - } - case 3: /* sysUpTime */ - MIB2_COPY_SYSUPTIME_TO((u32_t *)value); - return sizeof(u32_t); - case 4: /* sysContact */ - var = syscontact; - var_len = (const s16_t *)syscontact_len; - break; - case 5: /* sysName */ - var = sysname; - var_len = (const s16_t *)sysname_len; - break; - case 6: /* sysLocation */ - var = syslocation; - var_len = (const s16_t *)syslocation_len; - break; - case 7: /* sysServices */ - *(s32_t *)value = SNMP_SYSSERVICES; - return sizeof(s32_t); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG, ("system_get_value(): unknown id: %"S32_F"\n", node->oid)); - return 0; - } - - /* handle string values (OID 1,4,5 and 6) */ - LWIP_ASSERT("", (value != NULL)); - if (var_len == NULL) { - result = (s16_t)strlen((const char *)var); - } else { - result = *var_len; - } - MEMCPY(value, var, result); - return result; -} - -static snmp_err_t -system_set_test(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) -{ - snmp_err_t ret = SNMP_ERR_WRONGVALUE; - const u16_t *var_bufsize = NULL; - const u16_t *var_wr_len; - - LWIP_UNUSED_ARG(value); - - switch (node->oid) { - case 4: /* sysContact */ - var_bufsize = &syscontact_bufsize; - var_wr_len = syscontact_wr_len; - break; - case 5: /* sysName */ - var_bufsize = &sysname_bufsize; - var_wr_len = sysname_wr_len; - break; - case 6: /* sysLocation */ - var_bufsize = &syslocation_bufsize; - var_wr_len = syslocation_wr_len; - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG, ("system_set_test(): unknown id: %"S32_F"\n", node->oid)); - return ret; - } - - /* check if value is writable at all */ - if (*var_bufsize > 0) { - if (var_wr_len == NULL) { - /* we have to take the terminating 0 into account */ - if (len < *var_bufsize) { - ret = SNMP_ERR_NOERROR; - } - } else { - if (len <= *var_bufsize) { - ret = SNMP_ERR_NOERROR; - } - } - } else { - ret = SNMP_ERR_NOTWRITABLE; - } - - return ret; -} - -static snmp_err_t -system_set_value(const struct snmp_scalar_array_node_def *node, u16_t len, void *value) -{ - u8_t *var_wr = NULL; - u16_t *var_wr_len; - - switch (node->oid) { - case 4: /* sysContact */ - var_wr = syscontact_wr; - var_wr_len = syscontact_wr_len; - break; - case 5: /* sysName */ - var_wr = sysname_wr; - var_wr_len = sysname_wr_len; - break; - case 6: /* sysLocation */ - var_wr = syslocation_wr; - var_wr_len = syslocation_wr_len; - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG, ("system_set_value(): unknown id: %"S32_F"\n", node->oid)); - return SNMP_ERR_GENERROR; - } - - /* no need to check size of target buffer, this was already done in set_test method */ - LWIP_ASSERT("", var_wr != NULL); - MEMCPY(var_wr, value, len); - - if (var_wr_len == NULL) { - /* add terminating 0 */ - var_wr[len] = 0; - } else { - *var_wr_len = len; - } - - return SNMP_ERR_NOERROR; -} - -static const struct snmp_scalar_array_node_def system_nodes[] = { - {1, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysDescr */ - {2, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysObjectID */ - {3, SNMP_ASN1_TYPE_TIMETICKS, SNMP_NODE_INSTANCE_READ_ONLY}, /* sysUpTime */ - {4, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysContact */ - {5, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysName */ - {6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_WRITE}, /* sysLocation */ - {7, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY} /* sysServices */ -}; - -const struct snmp_scalar_array_node snmp_mib2_system_node = SNMP_SCALAR_CREATE_ARRAY_NODE(1, system_nodes, system_get_value, system_set_test, system_set_value); - -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_tcp.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_tcp.c deleted file mode 100644 index 8a321f3f1..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_tcp.c +++ /dev/null @@ -1,607 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) TCP objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/tcp.h" -#include "lwip/priv/tcp_priv.h" -#include "lwip/stats.h" - -#include - -#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -/* --- tcp .1.3.6.1.2.1.6 ----------------------------------------------------- */ - -static s16_t -tcp_get_value(struct snmp_node_instance *instance, void *value) -{ - u32_t *uint_ptr = (u32_t *)value; - s32_t *sint_ptr = (s32_t *)value; - - switch (instance->node->oid) { - case 1: /* tcpRtoAlgorithm, vanj(4) */ - *sint_ptr = 4; - return sizeof(*sint_ptr); - case 2: /* tcpRtoMin */ - /* @todo not the actual value, a guess, - needs to be calculated */ - *sint_ptr = 1000; - return sizeof(*sint_ptr); - case 3: /* tcpRtoMax */ - /* @todo not the actual value, a guess, - needs to be calculated */ - *sint_ptr = 60000; - return sizeof(*sint_ptr); - case 4: /* tcpMaxConn */ - *sint_ptr = MEMP_NUM_TCP_PCB; - return sizeof(*sint_ptr); - case 5: /* tcpActiveOpens */ - *uint_ptr = STATS_GET(mib2.tcpactiveopens); - return sizeof(*uint_ptr); - case 6: /* tcpPassiveOpens */ - *uint_ptr = STATS_GET(mib2.tcppassiveopens); - return sizeof(*uint_ptr); - case 7: /* tcpAttemptFails */ - *uint_ptr = STATS_GET(mib2.tcpattemptfails); - return sizeof(*uint_ptr); - case 8: /* tcpEstabResets */ - *uint_ptr = STATS_GET(mib2.tcpestabresets); - return sizeof(*uint_ptr); - case 9: { /* tcpCurrEstab */ - u16_t tcpcurrestab = 0; - struct tcp_pcb *pcb = tcp_active_pcbs; - while (pcb != NULL) { - if ((pcb->state == ESTABLISHED) || - (pcb->state == CLOSE_WAIT)) { - tcpcurrestab++; - } - pcb = pcb->next; - } - *uint_ptr = tcpcurrestab; - } - return sizeof(*uint_ptr); - case 10: /* tcpInSegs */ - *uint_ptr = STATS_GET(mib2.tcpinsegs); - return sizeof(*uint_ptr); - case 11: /* tcpOutSegs */ - *uint_ptr = STATS_GET(mib2.tcpoutsegs); - return sizeof(*uint_ptr); - case 12: /* tcpRetransSegs */ - *uint_ptr = STATS_GET(mib2.tcpretranssegs); - return sizeof(*uint_ptr); - case 14: /* tcpInErrs */ - *uint_ptr = STATS_GET(mib2.tcpinerrs); - return sizeof(*uint_ptr); - case 15: /* tcpOutRsts */ - *uint_ptr = STATS_GET(mib2.tcpoutrsts); - return sizeof(*uint_ptr); -#if LWIP_HAVE_INT64 - case 17: { /* tcpHCInSegs */ - /* use the 32 bit counter for now... */ - u64_t val64 = STATS_GET(mib2.tcpinsegs); - *((u64_t *)value) = val64; - } - return sizeof(u64_t); - case 18: { /* tcpHCOutSegs */ - /* use the 32 bit counter for now... */ - u64_t val64 = STATS_GET(mib2.tcpoutsegs); - *((u64_t *)value) = val64; - } - return sizeof(u64_t); -#endif - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG, ("tcp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); - break; - } - - return 0; -} - -/* --- tcpConnTable --- */ - -#if LWIP_IPV4 - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range tcp_ConnTable_oid_ranges[] = { - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff }, /* IP D */ - { 0, 0xffff }, /* Port */ - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff }, /* IP D */ - { 0, 0xffff } /* Port */ -}; - -static snmp_err_t -tcp_ConnTable_get_cell_value_core(struct tcp_pcb *pcb, const u32_t *column, union snmp_variant_value *value, u32_t *value_len) -{ - LWIP_UNUSED_ARG(value_len); - - /* value */ - switch (*column) { - case 1: /* tcpConnState */ - value->u32 = pcb->state + 1; - break; - case 2: /* tcpConnLocalAddress */ - value->u32 = ip_2_ip4(&pcb->local_ip)->addr; - break; - case 3: /* tcpConnLocalPort */ - value->u32 = pcb->local_port; - break; - case 4: /* tcpConnRemAddress */ - if (pcb->state == LISTEN) { - value->u32 = IP4_ADDR_ANY4->addr; - } else { - value->u32 = ip_2_ip4(&pcb->remote_ip)->addr; - } - break; - case 5: /* tcpConnRemPort */ - if (pcb->state == LISTEN) { - value->u32 = 0; - } else { - value->u32 = pcb->remote_port; - } - break; - default: - LWIP_ASSERT("invalid id", 0); - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -tcp_ConnTable_get_cell_value(const u32_t *column, const u32_t *row_oid, u8_t row_oid_len, union snmp_variant_value *value, u32_t *value_len) -{ - u8_t i; - ip4_addr_t local_ip; - ip4_addr_t remote_ip; - u16_t local_port; - u16_t remote_port; - struct tcp_pcb *pcb; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, tcp_ConnTable_oid_ranges, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IPs and ports from incoming OID */ - snmp_oid_to_ip4(&row_oid[0], &local_ip); /* we know it succeeds because of oid_in_range check above */ - local_port = (u16_t)row_oid[4]; - snmp_oid_to_ip4(&row_oid[5], &remote_ip); /* we know it succeeds because of oid_in_range check above */ - remote_port = (u16_t)row_oid[9]; - - /* find tcp_pcb with requested ips and ports */ - for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { - pcb = *tcp_pcb_lists[i]; - - while (pcb != NULL) { - /* do local IP and local port match? */ - if (IP_IS_V4_VAL(pcb->local_ip) && - ip4_addr_cmp(&local_ip, ip_2_ip4(&pcb->local_ip)) && (local_port == pcb->local_port)) { - - /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ - if (pcb->state == LISTEN) { - if (ip4_addr_cmp(&remote_ip, IP4_ADDR_ANY4) && (remote_port == 0)) { - /* fill in object properties */ - return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); - } - } else { - if (IP_IS_V4_VAL(pcb->remote_ip) && - ip4_addr_cmp(&remote_ip, ip_2_ip4(&pcb->remote_ip)) && (remote_port == pcb->remote_port)) { - /* fill in object properties */ - return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); - } - } - } - - pcb = pcb->next; - } - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -tcp_ConnTable_get_next_cell_instance_and_value(const u32_t *column, struct snmp_obj_id *row_oid, union snmp_variant_value *value, u32_t *value_len) -{ - u8_t i; - struct tcp_pcb *pcb; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { - pcb = *tcp_pcb_lists[i]; - while (pcb != NULL) { - u32_t test_oid[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; - - if (IP_IS_V4_VAL(pcb->local_ip)) { - snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); - test_oid[4] = pcb->local_port; - - /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ - if (pcb->state == LISTEN) { - snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[5]); - test_oid[9] = 0; - } else { - if (IP_IS_V6_VAL(pcb->remote_ip)) { /* should never happen */ - continue; - } - snmp_ip4_to_oid(ip_2_ip4(&pcb->remote_ip), &test_oid[5]); - test_oid[9] = pcb->remote_port; - } - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges), pcb); - } - - pcb = pcb->next; - } - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return tcp_ConnTable_get_cell_value_core((struct tcp_pcb *)state.reference, column, value, value_len); - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -#endif /* LWIP_IPV4 */ - -/* --- tcpConnectionTable --- */ - -static snmp_err_t -tcp_ConnectionTable_get_cell_value_core(const u32_t *column, struct tcp_pcb *pcb, union snmp_variant_value *value) -{ - /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ - switch (*column) { - case 7: /* tcpConnectionState */ - value->u32 = pcb->state + 1; - break; - case 8: /* tcpConnectionProcess */ - value->u32 = 0; /* not supported */ - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -tcp_ConnectionTable_get_cell_value(const u32_t *column, const u32_t *row_oid, u8_t row_oid_len, union snmp_variant_value *value, u32_t *value_len) -{ - ip_addr_t local_ip, remote_ip; - u16_t local_port, remote_port; - struct tcp_pcb *pcb; - u8_t idx = 0; - u8_t i; - struct tcp_pcb **const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; - - LWIP_UNUSED_ARG(value_len); - - /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len - idx, &local_ip, &local_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len - idx, &remote_ip, &remote_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* find tcp_pcb with requested ip and port*/ - for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { - pcb = *tcp_pcb_nonlisten_lists[i]; - - while (pcb != NULL) { - if (ip_addr_cmp(&local_ip, &pcb->local_ip) && - (local_port == pcb->local_port) && - ip_addr_cmp(&remote_ip, &pcb->remote_ip) && - (remote_port == pcb->remote_port)) { - /* fill in object properties */ - return tcp_ConnectionTable_get_cell_value_core(column, pcb, value); - } - pcb = pcb->next; - } - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t *column, struct snmp_obj_id *row_oid, union snmp_variant_value *value, u32_t *value_len) -{ - struct tcp_pcb *pcb; - struct snmp_next_oid_state state; - /* 1x tcpConnectionLocalAddressType + 1x OID len + 16x tcpConnectionLocalAddress + 1x tcpConnectionLocalPort - * 1x tcpConnectionRemAddressType + 1x OID len + 16x tcpConnectionRemAddress + 1x tcpConnectionRemPort */ - u32_t result_temp[38]; - u8_t i; - struct tcp_pcb **const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; - - LWIP_UNUSED_ARG(value_len); - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); - - /* iterate over all possible OIDs to find the next one */ - for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { - pcb = *tcp_pcb_nonlisten_lists[i]; - - while (pcb != NULL) { - u8_t idx = 0; - u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; - - /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ - idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); - - /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ - idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, idx, pcb); - - pcb = pcb->next; - } - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return tcp_ConnectionTable_get_cell_value_core(column, (struct tcp_pcb *)state.reference, value); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -/* --- tcpListenerTable --- */ - -static snmp_err_t -tcp_ListenerTable_get_cell_value_core(const u32_t *column, union snmp_variant_value *value) -{ - /* all items except tcpListenerProcess are declared as not-accessible */ - switch (*column) { - case 4: /* tcpListenerProcess */ - value->u32 = 0; /* not supported */ - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -tcp_ListenerTable_get_cell_value(const u32_t *column, const u32_t *row_oid, u8_t row_oid_len, union snmp_variant_value *value, u32_t *value_len) -{ - ip_addr_t local_ip; - u16_t local_port; - struct tcp_pcb_listen *pcb; - u8_t idx = 0; - - LWIP_UNUSED_ARG(value_len); - - /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len - idx, &local_ip, &local_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* find tcp_pcb with requested ip and port*/ - pcb = tcp_listen_pcbs.listen_pcbs; - while (pcb != NULL) { - if (ip_addr_cmp(&local_ip, &pcb->local_ip) && - (local_port == pcb->local_port)) { - /* fill in object properties */ - return tcp_ListenerTable_get_cell_value_core(column, value); - } - pcb = pcb->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -tcp_ListenerTable_get_next_cell_instance_and_value(const u32_t *column, struct snmp_obj_id *row_oid, union snmp_variant_value *value, u32_t *value_len) -{ - struct tcp_pcb_listen *pcb; - struct snmp_next_oid_state state; - /* 1x tcpListenerLocalAddressType + 1x OID len + 16x tcpListenerLocalAddress + 1x tcpListenerLocalPort */ - u32_t result_temp[19]; - - LWIP_UNUSED_ARG(value_len); - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); - - /* iterate over all possible OIDs to find the next one */ - pcb = tcp_listen_pcbs.listen_pcbs; - while (pcb != NULL) { - u8_t idx = 0; - u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; - - /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ - idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, idx, NULL); - - pcb = pcb->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return tcp_ListenerTable_get_cell_value_core(column, value); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -static const struct snmp_scalar_node tcp_RtoAlgorithm = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); -static const struct snmp_scalar_node tcp_RtoMin = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); -static const struct snmp_scalar_node tcp_RtoMax = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); -static const struct snmp_scalar_node tcp_MaxConn = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); -static const struct snmp_scalar_node tcp_ActiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_PassiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_AttemptFails = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_EstabResets = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_CurrEstab = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_GAUGE, tcp_get_value); -static const struct snmp_scalar_node tcp_InSegs = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_OutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_RetransSegs = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_InErrs = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -static const struct snmp_scalar_node tcp_OutRsts = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); -#if LWIP_HAVE_INT64 -static const struct snmp_scalar_node tcp_HCInSegs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); -static const struct snmp_scalar_node tcp_HCOutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); -#endif - -#if LWIP_IPV4 -static const struct snmp_table_simple_col_def tcp_ConnTable_columns[] = { - { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnState */ - { 2, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalAddress */ - { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalPort */ - { 4, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnRemAddress */ - { 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnRemPort */ -}; - -static const struct snmp_table_simple_node tcp_ConnTable = SNMP_TABLE_CREATE_SIMPLE(13, tcp_ConnTable_columns, tcp_ConnTable_get_cell_value, tcp_ConnTable_get_next_cell_instance_and_value); -#endif /* LWIP_IPV4 */ - -static const struct snmp_table_simple_col_def tcp_ConnectionTable_columns[] = { - /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ - { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnectionState */ - { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnectionProcess */ -}; - -static const struct snmp_table_simple_node tcp_ConnectionTable = SNMP_TABLE_CREATE_SIMPLE(19, tcp_ConnectionTable_columns, tcp_ConnectionTable_get_cell_value, tcp_ConnectionTable_get_next_cell_instance_and_value); - - -static const struct snmp_table_simple_col_def tcp_ListenerTable_columns[] = { - /* all items except tcpListenerProcess are declared as not-accessible */ - { 4, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpListenerProcess */ -}; - -static const struct snmp_table_simple_node tcp_ListenerTable = SNMP_TABLE_CREATE_SIMPLE(20, tcp_ListenerTable_columns, tcp_ListenerTable_get_cell_value, tcp_ListenerTable_get_next_cell_instance_and_value); - -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ -CREATE_LWIP_SYNC_NODE( 1, tcp_RtoAlgorithm) -CREATE_LWIP_SYNC_NODE( 2, tcp_RtoMin) -CREATE_LWIP_SYNC_NODE( 3, tcp_RtoMax) -CREATE_LWIP_SYNC_NODE( 4, tcp_MaxConn) -CREATE_LWIP_SYNC_NODE( 5, tcp_ActiveOpens) -CREATE_LWIP_SYNC_NODE( 6, tcp_PassiveOpens) -CREATE_LWIP_SYNC_NODE( 7, tcp_AttemptFails) -CREATE_LWIP_SYNC_NODE( 8, tcp_EstabResets) -CREATE_LWIP_SYNC_NODE( 9, tcp_CurrEstab) -CREATE_LWIP_SYNC_NODE(10, tcp_InSegs) -CREATE_LWIP_SYNC_NODE(11, tcp_OutSegs) -CREATE_LWIP_SYNC_NODE(12, tcp_RetransSegs) -#if LWIP_IPV4 -CREATE_LWIP_SYNC_NODE(13, tcp_ConnTable) -#endif /* LWIP_IPV4 */ -CREATE_LWIP_SYNC_NODE(14, tcp_InErrs) -CREATE_LWIP_SYNC_NODE(15, tcp_OutRsts) -#if LWIP_HAVE_INT64 -CREATE_LWIP_SYNC_NODE(17, tcp_HCInSegs) -CREATE_LWIP_SYNC_NODE(18, tcp_HCOutSegs) -#endif -CREATE_LWIP_SYNC_NODE(19, tcp_ConnectionTable) -CREATE_LWIP_SYNC_NODE(20, tcp_ListenerTable) - -static const struct snmp_node *const tcp_nodes[] = { - &SYNC_NODE_NAME(tcp_RtoAlgorithm).node.node, - &SYNC_NODE_NAME(tcp_RtoMin).node.node, - &SYNC_NODE_NAME(tcp_RtoMax).node.node, - &SYNC_NODE_NAME(tcp_MaxConn).node.node, - &SYNC_NODE_NAME(tcp_ActiveOpens).node.node, - &SYNC_NODE_NAME(tcp_PassiveOpens).node.node, - &SYNC_NODE_NAME(tcp_AttemptFails).node.node, - &SYNC_NODE_NAME(tcp_EstabResets).node.node, - &SYNC_NODE_NAME(tcp_CurrEstab).node.node, - &SYNC_NODE_NAME(tcp_InSegs).node.node, - &SYNC_NODE_NAME(tcp_OutSegs).node.node, - &SYNC_NODE_NAME(tcp_RetransSegs).node.node, -#if LWIP_IPV4 - &SYNC_NODE_NAME(tcp_ConnTable).node.node, -#endif /* LWIP_IPV4 */ - &SYNC_NODE_NAME(tcp_InErrs).node.node, - &SYNC_NODE_NAME(tcp_OutRsts).node.node, - &SYNC_NODE_NAME(tcp_HCInSegs).node.node, -#if LWIP_HAVE_INT64 - &SYNC_NODE_NAME(tcp_HCOutSegs).node.node, - &SYNC_NODE_NAME(tcp_ConnectionTable).node.node, -#endif - &SYNC_NODE_NAME(tcp_ListenerTable).node.node -}; - -const struct snmp_tree_node snmp_mib2_tcp_root = SNMP_CREATE_TREE_NODE(6, tcp_nodes); -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_udp.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_udp.c deleted file mode 100644 index d0bd5dec2..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_mib2_udp.c +++ /dev/null @@ -1,372 +0,0 @@ -/** - * @file - * Management Information Base II (RFC1213) UDP objects and functions. - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - * Christiaan Simons - */ - -#include "lwip/snmp.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_mib2.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/udp.h" -#include "lwip/stats.h" - -#include - -#if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP - -#if SNMP_USE_NETCONN -#define SYNC_NODE_NAME(node_name) node_name ## _synced -#define CREATE_LWIP_SYNC_NODE(oid, node_name) \ - static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); -#else -#define SYNC_NODE_NAME(node_name) node_name -#define CREATE_LWIP_SYNC_NODE(oid, node_name) -#endif - -/* --- udp .1.3.6.1.2.1.7 ----------------------------------------------------- */ - -static s16_t -udp_get_value(struct snmp_node_instance *instance, void *value) -{ - u32_t *uint_ptr = (u32_t *)value; - - switch (instance->node->oid) { - case 1: /* udpInDatagrams */ - *uint_ptr = STATS_GET(mib2.udpindatagrams); - return sizeof(*uint_ptr); - case 2: /* udpNoPorts */ - *uint_ptr = STATS_GET(mib2.udpnoports); - return sizeof(*uint_ptr); - case 3: /* udpInErrors */ - *uint_ptr = STATS_GET(mib2.udpinerrors); - return sizeof(*uint_ptr); - case 4: /* udpOutDatagrams */ - *uint_ptr = STATS_GET(mib2.udpoutdatagrams); - return sizeof(*uint_ptr); -#if LWIP_HAVE_INT64 - case 8: { /* udpHCInDatagrams */ - /* use the 32 bit counter for now... */ - u64_t val64 = STATS_GET(mib2.udpindatagrams); - *((u64_t *)value) = val64; - } - return sizeof(u64_t); - case 9: { /* udpHCOutDatagrams */ - /* use the 32 bit counter for now... */ - u64_t val64 = STATS_GET(mib2.udpoutdatagrams); - *((u64_t *)value) = val64; - } - return sizeof(u64_t); -#endif - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG, ("udp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); - break; - } - - return 0; -} - -/* --- udpEndpointTable --- */ - -static snmp_err_t -udp_endpointTable_get_cell_value_core(const u32_t *column, union snmp_variant_value *value) -{ - /* all items except udpEndpointProcess are declared as not-accessible */ - switch (*column) { - case 8: /* udpEndpointProcess */ - value->u32 = 0; /* not supported */ - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -udp_endpointTable_get_cell_value(const u32_t *column, const u32_t *row_oid, u8_t row_oid_len, union snmp_variant_value *value, u32_t *value_len) -{ - ip_addr_t local_ip, remote_ip; - u16_t local_port, remote_port; - struct udp_pcb *pcb; - u8_t idx = 0; - - LWIP_UNUSED_ARG(value_len); - - /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len - idx, &local_ip, &local_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ - idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len - idx, &remote_ip, &remote_port); - if (idx == 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* udpEndpointInstance */ - if (row_oid_len < (idx + 1)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - if (row_oid[idx] != 0) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* find udp_pcb with requested ip and port*/ - pcb = udp_pcbs; - while (pcb != NULL) { - if (ip_addr_cmp(&local_ip, &pcb->local_ip) && - (local_port == pcb->local_port) && - ip_addr_cmp(&remote_ip, &pcb->remote_ip) && - (remote_port == pcb->remote_port)) { - /* fill in object properties */ - return udp_endpointTable_get_cell_value_core(column, value); - } - pcb = pcb->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -udp_endpointTable_get_next_cell_instance_and_value(const u32_t *column, struct snmp_obj_id *row_oid, union snmp_variant_value *value, u32_t *value_len) -{ - struct udp_pcb *pcb; - struct snmp_next_oid_state state; - /* 1x udpEndpointLocalAddressType + 1x OID len + 16x udpEndpointLocalAddress + 1x udpEndpointLocalPort + - * 1x udpEndpointRemoteAddressType + 1x OID len + 16x udpEndpointRemoteAddress + 1x udpEndpointRemotePort + - * 1x udpEndpointInstance = 39 - */ - u32_t result_temp[39]; - - LWIP_UNUSED_ARG(value_len); - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); - - /* iterate over all possible OIDs to find the next one */ - pcb = udp_pcbs; - while (pcb != NULL) { - u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; - u8_t idx = 0; - - /* udpEndpointLocalAddressType + udpEndpointLocalAddress + udpEndpointLocalPort */ - idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); - - /* udpEndpointRemoteAddressType + udpEndpointRemoteAddress + udpEndpointRemotePort */ - idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); - - test_oid[idx] = 0; /* udpEndpointInstance */ - idx++; - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, idx, NULL); - - pcb = pcb->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return udp_endpointTable_get_cell_value_core(column, value); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -/* --- udpTable --- */ - -#if LWIP_IPV4 - -/* list of allowed value ranges for incoming OID */ -static const struct snmp_oid_range udp_Table_oid_ranges[] = { - { 0, 0xff }, /* IP A */ - { 0, 0xff }, /* IP B */ - { 0, 0xff }, /* IP C */ - { 0, 0xff }, /* IP D */ - { 1, 0xffff } /* Port */ -}; - -static snmp_err_t -udp_Table_get_cell_value_core(struct udp_pcb *pcb, const u32_t *column, union snmp_variant_value *value, u32_t *value_len) -{ - LWIP_UNUSED_ARG(value_len); - - switch (*column) { - case 1: /* udpLocalAddress */ - /* set reference to PCB local IP and return a generic node that copies IP4 addresses */ - value->u32 = ip_2_ip4(&pcb->local_ip)->addr; - break; - case 2: /* udpLocalPort */ - /* set reference to PCB local port and return a generic node that copies u16_t values */ - value->u32 = pcb->local_port; - break; - default: - return SNMP_ERR_NOSUCHINSTANCE; - } - - return SNMP_ERR_NOERROR; -} - -static snmp_err_t -udp_Table_get_cell_value(const u32_t *column, const u32_t *row_oid, u8_t row_oid_len, union snmp_variant_value *value, u32_t *value_len) -{ - ip4_addr_t ip; - u16_t port; - struct udp_pcb *pcb; - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(row_oid, row_oid_len, udp_Table_oid_ranges, LWIP_ARRAYSIZE(udp_Table_oid_ranges))) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* get IP and port from incoming OID */ - snmp_oid_to_ip4(&row_oid[0], &ip); /* we know it succeeds because of oid_in_range check above */ - port = (u16_t)row_oid[4]; - - /* find udp_pcb with requested ip and port*/ - pcb = udp_pcbs; - while (pcb != NULL) { - if (IP_IS_V4_VAL(pcb->local_ip)) { - if (ip4_addr_cmp(&ip, ip_2_ip4(&pcb->local_ip)) && (port == pcb->local_port)) { - /* fill in object properties */ - return udp_Table_get_cell_value_core(pcb, column, value, value_len); - } - } - pcb = pcb->next; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static snmp_err_t -udp_Table_get_next_cell_instance_and_value(const u32_t *column, struct snmp_obj_id *row_oid, union snmp_variant_value *value, u32_t *value_len) -{ - struct udp_pcb *pcb; - struct snmp_next_oid_state state; - u32_t result_temp[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(udp_Table_oid_ranges)); - - /* iterate over all possible OIDs to find the next one */ - pcb = udp_pcbs; - while (pcb != NULL) { - u32_t test_oid[LWIP_ARRAYSIZE(udp_Table_oid_ranges)]; - - if (IP_IS_V4_VAL(pcb->local_ip)) { - snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); - test_oid[4] = pcb->local_port; - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(udp_Table_oid_ranges), pcb); - } - - pcb = pcb->next; - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* fill in object properties */ - return udp_Table_get_cell_value_core((struct udp_pcb *)state.reference, column, value, value_len); - } else { - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; - } -} - -#endif /* LWIP_IPV4 */ - -static const struct snmp_scalar_node udp_inDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_COUNTER, udp_get_value); -static const struct snmp_scalar_node udp_noPorts = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_COUNTER, udp_get_value); -static const struct snmp_scalar_node udp_inErrors = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_COUNTER, udp_get_value); -static const struct snmp_scalar_node udp_outDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_COUNTER, udp_get_value); -#if LWIP_HAVE_INT64 -static const struct snmp_scalar_node udp_HCInDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); -static const struct snmp_scalar_node udp_HCOutDatagrams = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_COUNTER64, udp_get_value); -#endif - -#if LWIP_IPV4 -static const struct snmp_table_simple_col_def udp_Table_columns[] = { - { 1, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* udpLocalAddress */ - { 2, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpLocalPort */ -}; -static const struct snmp_table_simple_node udp_Table = SNMP_TABLE_CREATE_SIMPLE(5, udp_Table_columns, udp_Table_get_cell_value, udp_Table_get_next_cell_instance_and_value); -#endif /* LWIP_IPV4 */ - -static const struct snmp_table_simple_col_def udp_endpointTable_columns[] = { - /* all items except udpEndpointProcess are declared as not-accessible */ - { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* udpEndpointProcess */ -}; - -static const struct snmp_table_simple_node udp_endpointTable = SNMP_TABLE_CREATE_SIMPLE(7, udp_endpointTable_columns, udp_endpointTable_get_cell_value, udp_endpointTable_get_next_cell_instance_and_value); - -/* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ -CREATE_LWIP_SYNC_NODE(1, udp_inDatagrams) -CREATE_LWIP_SYNC_NODE(2, udp_noPorts) -CREATE_LWIP_SYNC_NODE(3, udp_inErrors) -CREATE_LWIP_SYNC_NODE(4, udp_outDatagrams) -#if LWIP_IPV4 -CREATE_LWIP_SYNC_NODE(5, udp_Table) -#endif /* LWIP_IPV4 */ -CREATE_LWIP_SYNC_NODE(7, udp_endpointTable) -#if LWIP_HAVE_INT64 -CREATE_LWIP_SYNC_NODE(8, udp_HCInDatagrams) -CREATE_LWIP_SYNC_NODE(9, udp_HCOutDatagrams) -#endif - -static const struct snmp_node *const udp_nodes[] = { - &SYNC_NODE_NAME(udp_inDatagrams).node.node, - &SYNC_NODE_NAME(udp_noPorts).node.node, - &SYNC_NODE_NAME(udp_inErrors).node.node, - &SYNC_NODE_NAME(udp_outDatagrams).node.node, -#if LWIP_IPV4 - &SYNC_NODE_NAME(udp_Table).node.node, -#endif /* LWIP_IPV4 */ - &SYNC_NODE_NAME(udp_endpointTable).node.node -#if LWIP_HAVE_INT64 - , - &SYNC_NODE_NAME(udp_HCInDatagrams).node.node, - &SYNC_NODE_NAME(udp_HCOutDatagrams).node.node -#endif -}; - -const struct snmp_tree_node snmp_mib2_udp_root = SNMP_CREATE_TREE_NODE(7, udp_nodes); -#endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_UDP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_msg.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_msg.c deleted file mode 100644 index 0b6693a79..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_msg.c +++ /dev/null @@ -1,1951 +0,0 @@ -/** - * @file - * SNMP message processing (RFC1157). - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - * Elias Oenal - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "snmp_msg.h" -#include "snmp_asn1.h" -#include "snmp_core_priv.h" -#include "lwip/ip_addr.h" -#include "lwip/stats.h" - -#if LWIP_SNMP_V3 -#include "lwip/apps/snmpv3.h" -#include "snmpv3_priv.h" -#ifdef LWIP_HOOK_FILENAME -#include LWIP_HOOK_FILENAME -#endif -#endif - -#include - -#define SNMP_V3_AUTH_FLAG 0x01 -#define SNMP_V3_PRIV_FLAG 0x02 - -/* Security levels */ -#define SNMP_V3_NOAUTHNOPRIV 0x00 -#define SNMP_V3_AUTHNOPRIV SNMP_V3_AUTH_FLAG -#define SNMP_V3_AUTHPRIV (SNMP_V3_AUTH_FLAG | SNMP_V3_PRIV_FLAG) - -/* public (non-static) constants */ -/** SNMP community string */ -const char *snmp_community = SNMP_COMMUNITY; -/** SNMP community string for write access */ -const char *snmp_community_write = SNMP_COMMUNITY_WRITE; -/** SNMP community string for sending traps */ -const char *snmp_community_trap = SNMP_COMMUNITY_TRAP; - -snmp_write_callback_fct snmp_write_callback = NULL; -void *snmp_write_callback_arg = NULL; - -#if LWIP_SNMP_CONFIGURE_VERSIONS - -static u8_t v1_enabled = 1; -static u8_t v2c_enabled = 1; -static u8_t v3_enabled = 1; - -static u8_t -snmp_version_enabled(u8_t version) -{ - if (version == SNMP_VERSION_1) { - return v1_enabled; - } else if (version == SNMP_VERSION_2c) { - return v2c_enabled; - } -#if LWIP_SNMP_V3 - else if (version == SNMP_VERSION_3) { - return v3_enabled; - } -#endif - else { - LWIP_ASSERT("Invalid SNMP version", 0); - return 0; - } -} - -u8_t -snmp_v1_enabled(void) -{ - return snmp_version_enabled(SNMP_VERSION_1); -} - -u8_t -snmp_v2c_enabled(void) -{ - return snmp_version_enabled(SNMP_VERSION_2c); -} - -u8_t -snmp_v3_enabled(void) -{ - return snmp_version_enabled(SNMP_VERSION_3); -} - -static void -snmp_version_enable(u8_t version, u8_t enable) -{ - if (version == SNMP_VERSION_1) { - v1_enabled = enable; - } else if (version == SNMP_VERSION_2c) { - v2c_enabled = enable; - } -#if LWIP_SNMP_V3 - else if (version == SNMP_VERSION_3) { - v3_enabled = enable; - } -#endif - else { - LWIP_ASSERT("Invalid SNMP version", 0); - } -} - -void -snmp_v1_enable(u8_t enable) -{ - snmp_version_enable(SNMP_VERSION_1, enable); -} - -void -snmp_v2c_enable(u8_t enable) -{ - snmp_version_enable(SNMP_VERSION_2c, enable); -} - -void -snmp_v3_enable(u8_t enable) -{ - snmp_version_enable(SNMP_VERSION_3, enable); -} - -#endif - -/** - * @ingroup snmp_core - * Returns current SNMP community string. - * @return current SNMP community string - */ -const char * -snmp_get_community(void) -{ - return snmp_community; -} - -/** - * @ingroup snmp_core - * Sets SNMP community string. - * The string itself (its storage) must be valid throughout the whole life of - * program (or until it is changed to sth else). - * - * @param community is a pointer to new community string - */ -void -snmp_set_community(const char *const community) -{ - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); - snmp_community = community; -} - -/** - * @ingroup snmp_core - * Returns current SNMP write-access community string. - * @return current SNMP write-access community string - */ -const char * -snmp_get_community_write(void) -{ - return snmp_community_write; -} - -/** - * @ingroup snmp_traps - * Returns current SNMP community string used for sending traps. - * @return current SNMP community string used for sending traps - */ -const char * -snmp_get_community_trap(void) -{ - return snmp_community_trap; -} - -/** - * @ingroup snmp_core - * Sets SNMP community string for write-access. - * The string itself (its storage) must be valid throughout the whole life of - * program (or until it is changed to sth else). - * - * @param community is a pointer to new write-access community string - */ -void -snmp_set_community_write(const char *const community) -{ - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("community string must not be NULL", community != NULL); - LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); - snmp_community_write = community; -} - -/** - * @ingroup snmp_traps - * Sets SNMP community string used for sending traps. - * The string itself (its storage) must be valid throughout the whole life of - * program (or until it is changed to sth else). - * - * @param community is a pointer to new trap community string - */ -void -snmp_set_community_trap(const char *const community) -{ - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_MAX_COMMUNITY_STR_LEN); - snmp_community_trap = community; -} - -/** - * @ingroup snmp_core - * Callback fired on every successful write access - */ -void -snmp_set_write_callback(snmp_write_callback_fct write_callback, void *callback_arg) -{ - LWIP_ASSERT_CORE_LOCKED(); - snmp_write_callback = write_callback; - snmp_write_callback_arg = callback_arg; -} - -/* ----------------------------------------------------------------------- */ -/* forward declarations */ -/* ----------------------------------------------------------------------- */ - -static err_t snmp_process_get_request(struct snmp_request *request); -static err_t snmp_process_getnext_request(struct snmp_request *request); -static err_t snmp_process_getbulk_request(struct snmp_request *request); -static err_t snmp_process_set_request(struct snmp_request *request); - -static err_t snmp_parse_inbound_frame(struct snmp_request *request); -static err_t snmp_prepare_outbound_frame(struct snmp_request *request); -static err_t snmp_complete_outbound_frame(struct snmp_request *request); -static void snmp_execute_write_callbacks(struct snmp_request *request); - - -/* ----------------------------------------------------------------------- */ -/* implementation */ -/* ----------------------------------------------------------------------- */ - -void -snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port) -{ - err_t err; - struct snmp_request request; - - memset(&request, 0, sizeof(request)); - request.handle = handle; - request.source_ip = source_ip; - request.source_port = port; - request.inbound_pbuf = p; - - snmp_stats.inpkts++; - - err = snmp_parse_inbound_frame(&request); - if (err == ERR_OK) { - err = snmp_prepare_outbound_frame(&request); - if (err == ERR_OK) { - - if (request.error_status == SNMP_ERR_NOERROR) { - /* only process frame if we do not already have an error to return (e.g. all readonly) */ - if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_REQ) { - err = snmp_process_get_request(&request); - } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ) { - err = snmp_process_getnext_request(&request); - } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { - err = snmp_process_getbulk_request(&request); - } else if (request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { - err = snmp_process_set_request(&request); - } - } -#if LWIP_SNMP_V3 - else { - struct snmp_varbind vb; - - vb.next = NULL; - vb.prev = NULL; - vb.type = SNMP_ASN1_TYPE_COUNTER32; - vb.value_len = sizeof(u32_t); - - switch (request.error_status) { - case SNMP_ERR_AUTHORIZATIONERROR: { - static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 5, 0 }; - snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid)); - vb.value = &snmp_stats.wrongdigests; - } - break; - case SNMP_ERR_UNKNOWN_ENGINEID: { - static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 4, 0 }; - snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid)); - vb.value = &snmp_stats.unknownengineids; - } - break; - case SNMP_ERR_UNKNOWN_SECURITYNAME: { - static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 3, 0 }; - snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid)); - vb.value = &snmp_stats.unknownusernames; - } - break; - case SNMP_ERR_UNSUPPORTED_SECLEVEL: { - static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 1, 0 }; - snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid)); - vb.value = &snmp_stats.unsupportedseclevels; - } - break; - case SNMP_ERR_NOTINTIMEWINDOW: { - static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 2, 0 }; - snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid)); - vb.value = &snmp_stats.notintimewindows; - } - break; - case SNMP_ERR_DECRYIPTION_ERROR: { - static const u32_t oid[] = { 1, 3, 6, 1, 6, 3, 15, 1, 1, 6, 0 }; - snmp_oid_assign(&vb.oid, oid, LWIP_ARRAYSIZE(oid)); - vb.value = &snmp_stats.decryptionerrors; - } - break; - default: - /* Unknown or unhandled error_status */ - err = ERR_ARG; - } - - if (err == ERR_OK) { - snmp_append_outbound_varbind(&(request.outbound_pbuf_stream), &vb); - request.error_status = SNMP_ERR_NOERROR; - } - - request.request_out_type = (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_REPORT); - request.request_id = request.msg_id; - } -#endif - - if (err == ERR_OK) { - err = snmp_complete_outbound_frame(&request); - - if (err == ERR_OK) { - err = snmp_sendto(request.handle, request.outbound_pbuf, request.source_ip, request.source_port); - - if ((request.request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) - && (request.error_status == SNMP_ERR_NOERROR) - && (snmp_write_callback != NULL)) { - /* raise write notification for all written objects */ - snmp_execute_write_callbacks(&request); - } - } - } - } - - if (request.outbound_pbuf != NULL) { - pbuf_free(request.outbound_pbuf); - } - } -} - -static u8_t -snmp_msg_getnext_validate_node_inst(struct snmp_node_instance *node_instance, void *validate_arg) -{ - if (((node_instance->access & SNMP_NODE_INSTANCE_ACCESS_READ) != SNMP_NODE_INSTANCE_ACCESS_READ) || (node_instance->get_value == NULL)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - -#if LWIP_HAVE_INT64 - if ((node_instance->asn1_type == SNMP_ASN1_TYPE_COUNTER64) && (((struct snmp_request *)validate_arg)->version == SNMP_VERSION_1)) { - /* according to RFC 2089 skip Counter64 objects in GetNext requests from v1 clients */ - return SNMP_ERR_NOSUCHINSTANCE; - } -#endif - - return SNMP_ERR_NOERROR; -} - -static void -snmp_process_varbind(struct snmp_request *request, struct snmp_varbind *vb, u8_t get_next) -{ - err_t err; - struct snmp_node_instance node_instance; - memset(&node_instance, 0, sizeof(node_instance)); - - if (get_next) { - struct snmp_obj_id result_oid; - request->error_status = snmp_get_next_node_instance_from_oid(vb->oid.id, vb->oid.len, snmp_msg_getnext_validate_node_inst, request, &result_oid, &node_instance); - - if (request->error_status == SNMP_ERR_NOERROR) { - snmp_oid_assign(&vb->oid, result_oid.id, result_oid.len); - } - } else { - request->error_status = snmp_get_node_instance_from_oid(vb->oid.id, vb->oid.len, &node_instance); - - if (request->error_status == SNMP_ERR_NOERROR) { - /* use 'getnext_validate' method for validation to avoid code duplication (some checks have to be executed here) */ - request->error_status = snmp_msg_getnext_validate_node_inst(&node_instance, request); - - if (request->error_status != SNMP_ERR_NOERROR) { - if (node_instance.release_instance != NULL) { - node_instance.release_instance(&node_instance); - } - } - } - } - - if (request->error_status != SNMP_ERR_NOERROR) { - if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { - if ((request->version == SNMP_VERSION_2c) || request->version == SNMP_VERSION_3) { - /* in SNMP v2c a varbind related exception is stored in varbind and not in frame header */ - vb->type = (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | (request->error_status & SNMP_VARBIND_EXCEPTION_MASK)); - vb->value_len = 0; - - err = snmp_append_outbound_varbind(&(request->outbound_pbuf_stream), vb); - if (err == ERR_OK) { - /* we stored the exception in varbind -> go on */ - request->error_status = SNMP_ERR_NOERROR; - } else if (err == ERR_BUF) { - request->error_status = SNMP_ERR_TOOBIG; - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } - } else { - /* according to RFC 1157/1905, all other errors only return genError */ - request->error_status = SNMP_ERR_GENERROR; - } - } else { - s16_t len = node_instance.get_value(&node_instance, vb->value); - - if (len >= 0) { - vb->value_len = (u16_t)len; /* cast is OK because we checked >= 0 above */ - vb->type = node_instance.asn1_type; - - LWIP_ASSERT("SNMP_MAX_VALUE_SIZE is configured too low", (vb->value_len & ~SNMP_GET_VALUE_RAW_DATA) <= SNMP_MAX_VALUE_SIZE); - err = snmp_append_outbound_varbind(&request->outbound_pbuf_stream, vb); - - if (err == ERR_BUF) { - request->error_status = SNMP_ERR_TOOBIG; - } else if (err != ERR_OK) { - request->error_status = SNMP_ERR_GENERROR; - } - } else { - request->error_status = SNMP_ERR_GENERROR; - } - - if (node_instance.release_instance != NULL) { - node_instance.release_instance(&node_instance); - } - } -} - - -/** - * Service an internal or external event for SNMP GET. - * - * @param request points to the associated message process state - */ -static err_t -snmp_process_get_request(struct snmp_request *request) -{ - snmp_vb_enumerator_err_t err; - struct snmp_varbind vb; - vb.value = request->value_buffer; - - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get request\n")); - - while (request->error_status == SNMP_ERR_NOERROR) { - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) { - snmp_process_varbind(request, &vb, 0); - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { - /* malformed ASN.1, don't answer */ - return ERR_ARG; - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } - - return ERR_OK; -} - -/** - * Service an internal or external event for SNMP GET. - * - * @param request points to the associated message process state - */ -static err_t -snmp_process_getnext_request(struct snmp_request *request) -{ - snmp_vb_enumerator_err_t err; - struct snmp_varbind vb; - vb.value = request->value_buffer; - - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-next request\n")); - - while (request->error_status == SNMP_ERR_NOERROR) { - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - if ((vb.type == SNMP_ASN1_TYPE_NULL) && (vb.value_len == 0)) { - snmp_process_varbind(request, &vb, 1); - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { - /* malformed ASN.1, don't answer */ - return ERR_ARG; - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } - - return ERR_OK; -} - -/** - * Service an internal or external event for SNMP GETBULKT. - * - * @param request points to the associated message process state - */ -static err_t -snmp_process_getbulk_request(struct snmp_request *request) -{ - snmp_vb_enumerator_err_t err; - s32_t non_repeaters = request->non_repeaters; - s32_t repetitions; - u16_t repetition_offset = 0; - struct snmp_varbind_enumerator repetition_varbind_enumerator; - struct snmp_varbind vb; - vb.value = request->value_buffer; - - if (SNMP_LWIP_GETBULK_MAX_REPETITIONS > 0) { - repetitions = LWIP_MIN(request->max_repetitions, SNMP_LWIP_GETBULK_MAX_REPETITIONS); - } else { - repetitions = request->max_repetitions; - } - - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP get-bulk request\n")); - - /* process non repeaters and first repetition */ - while (request->error_status == SNMP_ERR_NOERROR) { - if (non_repeaters == 0) { - repetition_offset = request->outbound_pbuf_stream.offset; - - if (repetitions == 0) { - /* do not resolve repeaters when repetitions is set to 0 */ - break; - } - repetitions--; - } - - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { - /* malformed ASN.1, don't answer */ - return ERR_ARG; - } else if ((err != SNMP_VB_ENUMERATOR_ERR_OK) || (vb.type != SNMP_ASN1_TYPE_NULL) || (vb.value_len != 0)) { - request->error_status = SNMP_ERR_GENERROR; - } else { - snmp_process_varbind(request, &vb, 1); - non_repeaters--; - } - } - - /* process repetitions > 1 */ - while ((request->error_status == SNMP_ERR_NOERROR) && (repetitions > 0) && (request->outbound_pbuf_stream.offset != repetition_offset)) { - - u8_t all_endofmibview = 1; - - snmp_vb_enumerator_init(&repetition_varbind_enumerator, request->outbound_pbuf, repetition_offset, request->outbound_pbuf_stream.offset - repetition_offset); - repetition_offset = request->outbound_pbuf_stream.offset; /* for next loop */ - - while (request->error_status == SNMP_ERR_NOERROR) { - vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned) */ - err = snmp_vb_enumerator_get_next(&repetition_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - vb.value = request->value_buffer; - snmp_process_varbind(request, &vb, 1); - - if (request->error_status != SNMP_ERR_NOERROR) { - /* already set correct error-index (here it cannot be taken from inbound varbind enumerator) */ - request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count; - } else if (vb.type != (SNMP_ASN1_CONTENTTYPE_PRIMITIVE | SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTEXT_VARBIND_END_OF_MIB_VIEW)) { - all_endofmibview = 0; - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else { - LWIP_DEBUGF(SNMP_DEBUG, ("Very strange, we cannot parse the varbind output that we created just before!")); - request->error_status = SNMP_ERR_GENERROR; - request->error_index = request->non_repeaters + repetition_varbind_enumerator.varbind_count; - } - } - - if ((request->error_status == SNMP_ERR_NOERROR) && all_endofmibview) { - /* stop when all varbinds in a loop return EndOfMibView */ - break; - } - - repetitions--; - } - - if (request->error_status == SNMP_ERR_TOOBIG) { - /* for GetBulk it is ok, if not all requested variables fit into the response -> just return the varbinds added so far */ - request->error_status = SNMP_ERR_NOERROR; - } - - return ERR_OK; -} - -/** - * Service an internal or external event for SNMP SET. - * - * @param request points to the associated message process state - */ -static err_t -snmp_process_set_request(struct snmp_request *request) -{ - snmp_vb_enumerator_err_t err; - struct snmp_varbind vb; - vb.value = request->value_buffer; - - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP set request\n")); - - /* perform set test on all objects */ - while (request->error_status == SNMP_ERR_NOERROR) { - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - struct snmp_node_instance node_instance; - memset(&node_instance, 0, sizeof(node_instance)); - - request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); - if (request->error_status == SNMP_ERR_NOERROR) { - if (node_instance.asn1_type != vb.type) { - request->error_status = SNMP_ERR_WRONGTYPE; - } else if (((node_instance.access & SNMP_NODE_INSTANCE_ACCESS_WRITE) != SNMP_NODE_INSTANCE_ACCESS_WRITE) || (node_instance.set_value == NULL)) { - request->error_status = SNMP_ERR_NOTWRITABLE; - } else { - if (node_instance.set_test != NULL) { - request->error_status = node_instance.set_test(&node_instance, vb.value_len, vb.value); - } - } - - if (node_instance.release_instance != NULL) { - node_instance.release_instance(&node_instance); - } - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else if (err == SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH) { - request->error_status = SNMP_ERR_WRONGLENGTH; - } else if (err == SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) { - /* malformed ASN.1, don't answer */ - return ERR_ARG; - } else { - request->error_status = SNMP_ERR_GENERROR; - } - } - - /* perform real set operation on all objects */ - if (request->error_status == SNMP_ERR_NOERROR) { - snmp_vb_enumerator_init(&request->inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); - while (request->error_status == SNMP_ERR_NOERROR) { - err = snmp_vb_enumerator_get_next(&request->inbound_varbind_enumerator, &vb); - if (err == SNMP_VB_ENUMERATOR_ERR_OK) { - struct snmp_node_instance node_instance; - memset(&node_instance, 0, sizeof(node_instance)); - request->error_status = snmp_get_node_instance_from_oid(vb.oid.id, vb.oid.len, &node_instance); - if (request->error_status == SNMP_ERR_NOERROR) { - if (node_instance.set_value(&node_instance, vb.value_len, vb.value) != SNMP_ERR_NOERROR) { - if (request->inbound_varbind_enumerator.varbind_count == 1) { - request->error_status = SNMP_ERR_COMMITFAILED; - } else { - /* we cannot undo the set operations done so far */ - request->error_status = SNMP_ERR_UNDOFAILED; - } - } - - if (node_instance.release_instance != NULL) { - node_instance.release_instance(&node_instance); - } - } - } else if (err == SNMP_VB_ENUMERATOR_ERR_EOVB) { - /* no more varbinds in request */ - break; - } else { - /* first time enumerating varbinds work but second time not, although nothing should have changed in between ??? */ - request->error_status = SNMP_ERR_GENERROR; - } - } - } - - return ERR_OK; -} - -#define PARSE_EXEC(code, retValue) \ - if ((code) != ERR_OK) { \ - LWIP_DEBUGF(SNMP_DEBUG, ("Malformed ASN.1 detected.\n")); \ - snmp_stats.inasnparseerrs++; \ - return retValue; \ - } - -#define PARSE_ASSERT(cond, retValue) \ - if (!(cond)) { \ - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP parse assertion failed!: " # cond)); \ - snmp_stats.inasnparseerrs++; \ - return retValue; \ - } - -#define BUILD_EXEC(code, retValue) \ - if ((code) != ERR_OK) { \ - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP error during creation of outbound frame!: " # code)); \ - return retValue; \ - } - -#define IF_PARSE_EXEC(code) PARSE_EXEC(code, ERR_ARG) -#define IF_PARSE_ASSERT(code) PARSE_ASSERT(code, ERR_ARG) - -/** - * Checks and decodes incoming SNMP message header, logs header errors. - * - * @param request points to the current message request state return - * @return - * - ERR_OK SNMP header is sane and accepted - * - ERR_VAL SNMP header is either malformed or rejected - */ -static err_t -snmp_parse_inbound_frame(struct snmp_request *request) -{ - struct snmp_pbuf_stream pbuf_stream; - struct snmp_asn1_tlv tlv; - s32_t parent_tlv_value_len; - s32_t s32_value; - err_t err; -#if LWIP_SNMP_V3 - snmpv3_auth_algo_t auth; - snmpv3_priv_algo_t priv; -#endif - - IF_PARSE_EXEC(snmp_pbuf_stream_init(&pbuf_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); - - /* decode main container consisting of version, community and PDU */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len == pbuf_stream.length)); - parent_tlv_value_len = tlv.value_len; - - /* decode version */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - - if (((s32_value != SNMP_VERSION_1) && - (s32_value != SNMP_VERSION_2c) -#if LWIP_SNMP_V3 - && (s32_value != SNMP_VERSION_3) -#endif - ) -#if LWIP_SNMP_CONFIGURE_VERSIONS - || (!snmp_version_enabled(s32_value)) -#endif - ) { - /* unsupported SNMP version */ - snmp_stats.inbadversions++; - return ERR_ARG; - } - request->version = (u8_t)s32_value; - -#if LWIP_SNMP_V3 - if (request->version == SNMP_VERSION_3) { - u16_t u16_value; - u16_t inbound_msgAuthenticationParameters_offset; - - /* SNMPv3 doesn't use communities */ - /* @todo: Differentiate read/write access */ - strncpy((char *)request->community, snmp_community, SNMP_MAX_COMMUNITY_STR_LEN); - request->community[SNMP_MAX_COMMUNITY_STR_LEN] = 0; /* ensure NULL termination (strncpy does NOT guarantee it!) */ - request->community_strlen = (u16_t)strnlen((char *)request->community, SNMP_MAX_COMMUNITY_STR_LEN); - - /* RFC3414 globalData */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - /* decode msgID */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - request->msg_id = s32_value; - - /* decode msgMaxSize */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - request->msg_max_size = s32_value; - - /* decode msgFlags */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - request->msg_flags = (u8_t)s32_value; - - /* decode msgSecurityModel */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - request->msg_security_model = s32_value; - - /* RFC3414 msgSecurityParameters - * The User-based Security Model defines the contents of the OCTET - * STRING as a SEQUENCE. - * - * We skip the protective dummy OCTET STRING header - * to access the SEQUENCE header. - */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - /* msgSecurityParameters SEQUENCE header */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - /* decode msgAuthoritativeEngineID */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authoritative_engine_id, - &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); - request->msg_authoritative_engine_id_len = (u8_t)u16_value; - - /* msgAuthoritativeEngineBoots */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_boots)); - - /* msgAuthoritativeEngineTime */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->msg_authoritative_engine_time)); - - /* msgUserName */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_user_name, - &u16_value, SNMP_V3_MAX_USER_LENGTH)); - request->msg_user_name_len = (u8_t)u16_value; - - /* msgAuthenticationParameters */ - memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - /* Remember position */ - inbound_msgAuthenticationParameters_offset = pbuf_stream.offset; - LWIP_UNUSED_ARG(inbound_msgAuthenticationParameters_offset); - /* Read auth parameters */ - /* IF_PARSE_ASSERT(tlv.value_len <= SNMP_V3_MAX_AUTH_PARAM_LENGTH); */ - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_authentication_parameters, - &u16_value, tlv.value_len)); - request->msg_authentication_parameters_len = (u8_t)u16_value; - - /* msgPrivacyParameters */ - memset(request->msg_privacy_parameters, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->msg_privacy_parameters, - &u16_value, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); - request->msg_privacy_parameters_len = (u8_t)u16_value; - - /* validate securityParameters here (do this after decoding because we don't want to increase other counters for wrong frames) - * 1) securityParameters was correctly serialized if we reach here. - * 2) securityParameters are already cached. - * 3) if msgAuthoritativeEngineID is unknown, zero-length or too long: - b) https://tools.ietf.org/html/rfc3414#section-7 - */ - { - const char *eid; - u8_t eid_len; - - snmpv3_get_engine_id(&eid, &eid_len); - - if ((request->msg_authoritative_engine_id_len == 0) || - (request->msg_authoritative_engine_id_len != eid_len) || - (memcmp(eid, request->msg_authoritative_engine_id, eid_len) != 0)) { - snmp_stats.unknownengineids++; - request->msg_flags = 0; /* noauthnopriv */ - request->error_status = SNMP_ERR_UNKNOWN_ENGINEID; - return ERR_OK; - } - } - - /* 4) verify username */ - if (snmpv3_get_user((char *)request->msg_user_name, &auth, NULL, &priv, NULL)) { - snmp_stats.unknownusernames++; - request->msg_flags = 0; /* noauthnopriv */ - request->error_status = SNMP_ERR_UNKNOWN_SECURITYNAME; - return ERR_OK; - } - - /* 5) verify security level */ - switch (request->msg_flags & (SNMP_V3_AUTH_FLAG | SNMP_V3_PRIV_FLAG)) { - case SNMP_V3_NOAUTHNOPRIV: - if ((auth != SNMP_V3_AUTH_ALGO_INVAL) || (priv != SNMP_V3_PRIV_ALGO_INVAL)) { - /* Invalid security level for user */ - snmp_stats.unsupportedseclevels++; - request->msg_flags = SNMP_V3_NOAUTHNOPRIV; - request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL; - return ERR_OK; - } - break; -#if LWIP_SNMP_V3_CRYPTO - case SNMP_V3_AUTHNOPRIV: - if ((auth == SNMP_V3_AUTH_ALGO_INVAL) || (priv != SNMP_V3_PRIV_ALGO_INVAL)) { - /* Invalid security level for user */ - snmp_stats.unsupportedseclevels++; - request->msg_flags = SNMP_V3_NOAUTHNOPRIV; - request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL; - return ERR_OK; - } - break; - case SNMP_V3_AUTHPRIV: - if ((auth == SNMP_V3_AUTH_ALGO_INVAL) || (priv == SNMP_V3_PRIV_ALGO_INVAL)) { - /* Invalid security level for user */ - snmp_stats.unsupportedseclevels++; - request->msg_flags = SNMP_V3_NOAUTHNOPRIV; - request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL; - return ERR_OK; - } - break; -#endif - default: - snmp_stats.unsupportedseclevels++; - request->msg_flags = SNMP_V3_NOAUTHNOPRIV; - request->error_status = SNMP_ERR_UNSUPPORTED_SECLEVEL; - return ERR_OK; - } - - /* 6) if securitylevel specifies authentication, authenticate message. */ -#if LWIP_SNMP_V3_CRYPTO - if (request->msg_flags & SNMP_V3_AUTH_FLAG) { - const u8_t zero_arr[SNMP_V3_MAX_AUTH_PARAM_LENGTH] = { 0 }; - u8_t key[20]; - u8_t hmac[LWIP_MAX(SNMP_V3_SHA_LEN, SNMP_V3_MD5_LEN)]; - struct snmp_pbuf_stream auth_stream; - - if (request->msg_authentication_parameters_len > SNMP_V3_MAX_AUTH_PARAM_LENGTH) { - snmp_stats.wrongdigests++; - request->msg_flags = SNMP_V3_NOAUTHNOPRIV; - request->error_status = SNMP_ERR_AUTHORIZATIONERROR; - return ERR_OK; - } - - /* Rewind stream */ - IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); - IF_PARSE_EXEC(snmp_pbuf_stream_seek_abs(&auth_stream, inbound_msgAuthenticationParameters_offset)); - /* Set auth parameters to zero for verification */ - IF_PARSE_EXEC(snmp_asn1_enc_raw(&auth_stream, zero_arr, request->msg_authentication_parameters_len)); - - /* Verify authentication */ - IF_PARSE_EXEC(snmp_pbuf_stream_init(&auth_stream, request->inbound_pbuf, 0, request->inbound_pbuf->tot_len)); - - IF_PARSE_EXEC(snmpv3_get_user((char *)request->msg_user_name, &auth, key, NULL, NULL)); - IF_PARSE_EXEC(snmpv3_auth(&auth_stream, request->inbound_pbuf->tot_len, key, auth, hmac)); - - if (memcmp(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH)) { - snmp_stats.wrongdigests++; - request->msg_flags = SNMP_V3_NOAUTHNOPRIV; - request->error_status = SNMP_ERR_AUTHORIZATIONERROR; - return ERR_OK; - } - - /* 7) if securitylevel specifies authentication, verify engineboots, enginetime and lastenginetime */ - { - s32_t boots = snmpv3_get_engine_boots_internal(); - if ((request->msg_authoritative_engine_boots != boots) || (boots == 2147483647UL)) { - snmp_stats.notintimewindows++; - request->msg_flags = SNMP_V3_AUTHNOPRIV; - request->error_status = SNMP_ERR_NOTINTIMEWINDOW; - return ERR_OK; - } - } - { - s32_t time = snmpv3_get_engine_time_internal(); - if (request->msg_authoritative_engine_time > (time + 150)) { - snmp_stats.notintimewindows++; - request->msg_flags = SNMP_V3_AUTHNOPRIV; - request->error_status = SNMP_ERR_NOTINTIMEWINDOW; - return ERR_OK; - } else if (time > 150) { - if (request->msg_authoritative_engine_time < (time - 150)) { - snmp_stats.notintimewindows++; - request->msg_flags = SNMP_V3_AUTHNOPRIV; - request->error_status = SNMP_ERR_NOTINTIMEWINDOW; - return ERR_OK; - } - } - } - } -#endif - - /* 8) if securitylevel specifies privacy, decrypt message. */ -#if LWIP_SNMP_V3_CRYPTO - if (request->msg_flags & SNMP_V3_PRIV_FLAG) { - /* Decrypt message */ - - u8_t key[20]; - - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmpv3_get_user((char *)request->msg_user_name, NULL, NULL, &priv, key)); - if (snmpv3_crypt(&pbuf_stream, tlv.value_len, key, - request->msg_privacy_parameters, request->msg_authoritative_engine_boots, - request->msg_authoritative_engine_time, priv, SNMP_V3_PRIV_MODE_DECRYPT) != ERR_OK) { - snmp_stats.decryptionerrors++; - request->msg_flags = SNMP_V3_AUTHNOPRIV; - request->error_status = SNMP_ERR_DECRYIPTION_ERROR; - return ERR_OK; - } - } -#endif - /* 9) calculate max size of scoped pdu? - * 10) securityname for user is retrieved from usertable? - * 11) security data is cached? - * 12) - */ - - /* Scoped PDU - * Encryption context - */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_SEQUENCE); - parent_tlv_value_len -= SNMP_ASN1_TLV_HDR_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - /* contextEngineID */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_engine_id, - &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); - request->context_engine_id_len = (u8_t)u16_value; - /* TODO: do we need to verify this contextengineid too? */ - - /* contextName */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->context_name, - &u16_value, SNMP_V3_MAX_ENGINE_ID_LENGTH)); - request->context_name_len = (u8_t)u16_value; - /* TODO: do we need to verify this contextname too? */ - } else -#endif - { - /* decode community */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_OCTET_STRING); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - err = snmp_asn1_dec_raw(&pbuf_stream, tlv.value_len, request->community, &request->community_strlen, SNMP_MAX_COMMUNITY_STR_LEN); - if (err == ERR_MEM) { - /* community string does not fit in our buffer -> its too long -> its invalid */ - request->community_strlen = 0; - snmp_pbuf_stream_seek(&pbuf_stream, tlv.value_len); - } else { - IF_PARSE_ASSERT(err == ERR_OK); - } - /* add zero terminator */ - request->community[request->community_strlen] = 0; - } - - /* decode PDU type (next container level) */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.value_len <= pbuf_stream.length); - request->inbound_padding_len = pbuf_stream.length - tlv.value_len; - parent_tlv_value_len = tlv.value_len; - - /* validate PDU type */ - switch (tlv.type) { - case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_REQ): - /* GetRequest PDU */ - snmp_stats.ingetrequests++; - break; - case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_NEXT_REQ): - /* GetNextRequest PDU */ - snmp_stats.ingetnexts++; - break; - case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ): - /* GetBulkRequest PDU */ - if (request->version < SNMP_VERSION_2c) { - /* RFC2089: invalid, drop packet */ - return ERR_ARG; - } - break; - case (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_SET_REQ): - /* SetRequest PDU */ - snmp_stats.insetrequests++; - break; - default: - /* unsupported input PDU for this agent (no parse error) */ - LWIP_DEBUGF(SNMP_DEBUG, ("Unknown/Invalid SNMP PDU type received: %d", tlv.type)); \ - return ERR_ARG; - } - request->request_type = tlv.type & SNMP_ASN1_DATATYPE_MASK; - request->request_out_type = (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_GET_RESP); - - /* validate community (do this after decoding PDU type because we don't want to increase 'inbadcommunitynames' for wrong frame types */ - if (request->community_strlen == 0) { - /* community string was too long or really empty*/ - snmp_stats.inbadcommunitynames++; - snmp_authfail_trap(); - return ERR_ARG; - } else if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { - if (snmp_community_write[0] == 0) { - /* our write community is empty, that means all our objects are readonly */ - request->error_status = SNMP_ERR_NOTWRITABLE; - request->error_index = 1; - } else if (strncmp(snmp_community_write, (const char *)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) { - /* community name does not match */ - snmp_stats.inbadcommunitynames++; - snmp_authfail_trap(); - return ERR_ARG; - } - } else { - if (strncmp(snmp_community, (const char *)request->community, SNMP_MAX_COMMUNITY_STR_LEN) != 0) { - /* community name does not match */ - snmp_stats.inbadcommunitynames++; - snmp_authfail_trap(); - return ERR_ARG; - } - } - - /* decode request ID */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->request_id)); - - /* decode error status / non-repeaters */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->non_repeaters)); - if (request->non_repeaters < 0) { - /* RFC 1905, 4.2.3 */ - request->non_repeaters = 0; - } - } else { - /* only check valid value, don't touch 'request->error_status', maybe a response error status was already set to above; */ - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &s32_value)); - IF_PARSE_ASSERT(s32_value == SNMP_ERR_NOERROR); - } - - /* decode error index / max-repetitions */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT(tlv.type == SNMP_ASN1_TYPE_INTEGER); - parent_tlv_value_len -= SNMP_ASN1_TLV_LENGTH(tlv); - IF_PARSE_ASSERT(parent_tlv_value_len > 0); - - if (request->request_type == SNMP_ASN1_CONTEXT_PDU_GET_BULK_REQ) { - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->max_repetitions)); - if (request->max_repetitions < 0) { - /* RFC 1905, 4.2.3 */ - request->max_repetitions = 0; - } - } else { - IF_PARSE_EXEC(snmp_asn1_dec_s32t(&pbuf_stream, tlv.value_len, &request->error_index)); - IF_PARSE_ASSERT(s32_value == 0); - } - - /* decode varbind-list type (next container level) */ - IF_PARSE_EXEC(snmp_asn1_dec_tlv(&pbuf_stream, &tlv)); - IF_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= pbuf_stream.length)); - - request->inbound_varbind_offset = pbuf_stream.offset; - request->inbound_varbind_len = pbuf_stream.length - request->inbound_padding_len; - snmp_vb_enumerator_init(&(request->inbound_varbind_enumerator), request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); - - return ERR_OK; -} - -#define OF_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG) - -static err_t -snmp_prepare_outbound_frame(struct snmp_request *request) -{ - struct snmp_asn1_tlv tlv; - struct snmp_pbuf_stream *pbuf_stream = &(request->outbound_pbuf_stream); - - /* try allocating pbuf(s) for maximum response size */ - request->outbound_pbuf = pbuf_alloc(PBUF_TRANSPORT, 1472, PBUF_RAM); - if (request->outbound_pbuf == NULL) { - return ERR_MEM; - } - - snmp_pbuf_stream_init(pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len); - - /* 'Message' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - - /* version */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(request->version, &tlv.value_len); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->version) ); - -#if LWIP_SNMP_V3 - if (request->version < SNMP_VERSION_3) { -#endif - /* community */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->community_strlen); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - OF_BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, request->community, request->community_strlen) ); -#if LWIP_SNMP_V3 - } else { - const char *id; - - /* globalData */ - request->outbound_msg_global_data_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - /* msgID */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - snmp_asn1_enc_s32t_cnt(request->msg_id, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_id)); - - /* msgMaxSize */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - snmp_asn1_enc_s32t_cnt(request->msg_max_size, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_max_size)); - - /* msgFlags */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 1); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, &request->msg_flags, 1)); - - /* msgSecurityModel */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - snmp_asn1_enc_s32t_cnt(request->msg_security_model, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_security_model)); - - /* end of msgGlobalData */ - request->outbound_msg_global_data_end = pbuf_stream->offset; - - /* msgSecurityParameters */ - request->outbound_msg_security_parameters_str_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - request->outbound_msg_security_parameters_seq_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - /* msgAuthoritativeEngineID */ - snmpv3_get_engine_id(&id, &request->msg_authoritative_engine_id_len); - MEMCPY(request->msg_authoritative_engine_id, id, request->msg_authoritative_engine_id_len); - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_authoritative_engine_id_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authoritative_engine_id, request->msg_authoritative_engine_id_len)); - - request->msg_authoritative_engine_time = snmpv3_get_engine_time(); - request->msg_authoritative_engine_boots = snmpv3_get_engine_boots(); - - /* msgAuthoritativeEngineBoots */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_boots, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_boots)); - - /* msgAuthoritativeEngineTime */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(request->msg_authoritative_engine_time, &tlv.value_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->msg_authoritative_engine_time)); - - /* msgUserName */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->msg_user_name_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_user_name, request->msg_user_name_len)); - -#if LWIP_SNMP_V3_CRYPTO - /* msgAuthenticationParameters */ - if (request->msg_flags & SNMP_V3_AUTH_FLAG) { - memset(request->msg_authentication_parameters, 0, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - request->outbound_msg_authentication_parameters_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); - } else -#endif - { - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - } - -#if LWIP_SNMP_V3_CRYPTO - /* msgPrivacyParameters */ - if (request->msg_flags & SNMP_V3_PRIV_FLAG) { - snmpv3_build_priv_param(request->msg_privacy_parameters); - - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, SNMP_V3_MAX_PRIV_PARAM_LENGTH); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->msg_privacy_parameters, SNMP_V3_MAX_PRIV_PARAM_LENGTH)); - } else -#endif - { - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - } - - /* End of msgSecurityParameters, so we can calculate the length of this sequence later */ - request->outbound_msg_security_parameters_end = pbuf_stream->offset; - -#if LWIP_SNMP_V3_CRYPTO - /* For encryption we have to encapsulate the payload in an octet string */ - if (request->msg_flags & SNMP_V3_PRIV_FLAG) { - request->outbound_scoped_pdu_string_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - } -#endif - /* Scoped PDU - * Encryption context - */ - request->outbound_scoped_pdu_seq_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - /* contextEngineID */ - snmpv3_get_engine_id(&id, &request->context_engine_id_len); - MEMCPY(request->context_engine_id, id, request->context_engine_id_len); - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_engine_id_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_engine_id, request->context_engine_id_len)); - - /* contextName */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, request->context_name_len); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, request->context_name, request->context_name_len)); - } -#endif - - /* 'PDU' sequence */ - request->outbound_pdu_offset = pbuf_stream->offset; - SNMP_ASN1_SET_TLV_PARAMS(tlv, request->request_out_type, 3, 0); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - - /* request ID */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(request->request_id, &tlv.value_len); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - OF_BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, request->request_id) ); - - /* error status */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - request->outbound_error_status_offset = pbuf_stream->offset; - OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) ); - - /* error index */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 1); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - request->outbound_error_index_offset = pbuf_stream->offset; - OF_BUILD_EXEC( snmp_pbuf_stream_write(pbuf_stream, 0) ); - - /* 'VarBindList' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, 0); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - - request->outbound_varbind_offset = pbuf_stream->offset; - - return ERR_OK; -} - -/** Calculate the length of a varbind list */ -err_t -snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len) -{ - /* calculate required lengths */ - snmp_asn1_enc_oid_cnt(varbind->oid.id, varbind->oid.len, &len->oid_value_len); - snmp_asn1_enc_length_cnt(len->oid_value_len, &len->oid_len_len); - - if (varbind->value_len == 0) { - len->value_value_len = 0; - } else if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) { - len->value_value_len = varbind->value_len & (~SNMP_GET_VALUE_RAW_DATA); - } else { - switch (varbind->type) { - case SNMP_ASN1_TYPE_INTEGER: - if (varbind->value_len != sizeof (s32_t)) { - return ERR_VAL; - } - snmp_asn1_enc_s32t_cnt(*((s32_t *) varbind->value), &len->value_value_len); - break; - case SNMP_ASN1_TYPE_COUNTER: - case SNMP_ASN1_TYPE_GAUGE: - case SNMP_ASN1_TYPE_TIMETICKS: - if (varbind->value_len != sizeof (u32_t)) { - return ERR_VAL; - } - snmp_asn1_enc_u32t_cnt(*((u32_t *) varbind->value), &len->value_value_len); - break; - case SNMP_ASN1_TYPE_OCTET_STRING: - case SNMP_ASN1_TYPE_IPADDR: - case SNMP_ASN1_TYPE_OPAQUE: - len->value_value_len = varbind->value_len; - break; - case SNMP_ASN1_TYPE_NULL: - if (varbind->value_len != 0) { - return ERR_VAL; - } - len->value_value_len = 0; - break; - case SNMP_ASN1_TYPE_OBJECT_ID: - if ((varbind->value_len & 0x03) != 0) { - return ERR_VAL; - } - snmp_asn1_enc_oid_cnt((u32_t *) varbind->value, varbind->value_len >> 2, &len->value_value_len); - break; -#if LWIP_HAVE_INT64 - case SNMP_ASN1_TYPE_COUNTER64: - if (varbind->value_len != sizeof(u64_t)) { - return ERR_VAL; - } - snmp_asn1_enc_u64t_cnt(*(u64_t *)varbind->value, &len->value_value_len); - break; -#endif - default: - /* unsupported type */ - return ERR_VAL; - } - } - snmp_asn1_enc_length_cnt(len->value_value_len, &len->value_len_len); - - len->vb_value_len = 1 + len->oid_len_len + len->oid_value_len + 1 + len->value_len_len + len->value_value_len; - snmp_asn1_enc_length_cnt(len->vb_value_len, &len->vb_len_len); - - return ERR_OK; -} - -#define OVB_BUILD_EXEC(code) BUILD_EXEC(code, ERR_ARG) - -err_t -snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbind) -{ - struct snmp_asn1_tlv tlv; - struct snmp_varbind_len len; - err_t err; - - err = snmp_varbind_length(varbind, &len); - - if (err != ERR_OK) { - return err; - } - - /* check length already before adding first data because in case of GetBulk, - * data added so far is returned and therefore no partial data shall be added - */ - if ((1 + len.vb_len_len + len.vb_value_len) > pbuf_stream->length) { - return ERR_BUF; - } - - /* 'VarBind' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, len.vb_len_len, len.vb_value_len); - OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - /* VarBind OID */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, len.oid_len_len, len.oid_value_len); - OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, varbind->oid.id, varbind->oid.len)); - - /* VarBind value */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, varbind->type, len.value_len_len, len.value_value_len); - OVB_BUILD_EXEC(snmp_ans1_enc_tlv(pbuf_stream, &tlv)); - - if (len.value_value_len > 0) { - if (varbind->value_len & SNMP_GET_VALUE_RAW_DATA) { - OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t *) varbind->value, len.value_value_len)); - } else { - switch (varbind->type) { - case SNMP_ASN1_TYPE_INTEGER: - OVB_BUILD_EXEC(snmp_asn1_enc_s32t(pbuf_stream, len.value_value_len, *((s32_t *) varbind->value))); - break; - case SNMP_ASN1_TYPE_COUNTER: - case SNMP_ASN1_TYPE_GAUGE: - case SNMP_ASN1_TYPE_TIMETICKS: - OVB_BUILD_EXEC(snmp_asn1_enc_u32t(pbuf_stream, len.value_value_len, *((u32_t *) varbind->value))); - break; - case SNMP_ASN1_TYPE_OCTET_STRING: - case SNMP_ASN1_TYPE_IPADDR: - case SNMP_ASN1_TYPE_OPAQUE: - OVB_BUILD_EXEC(snmp_asn1_enc_raw(pbuf_stream, (u8_t *) varbind->value, len.value_value_len)); - len.value_value_len = varbind->value_len; - break; - case SNMP_ASN1_TYPE_OBJECT_ID: - OVB_BUILD_EXEC(snmp_asn1_enc_oid(pbuf_stream, (u32_t *) varbind->value, varbind->value_len / sizeof (u32_t))); - break; -#if LWIP_HAVE_INT64 - case SNMP_ASN1_TYPE_COUNTER64: - OVB_BUILD_EXEC(snmp_asn1_enc_u64t(pbuf_stream, len.value_value_len, *(u64_t *) varbind->value)); - break; -#endif - default: - LWIP_ASSERT("Unknown variable type", 0); - break; - } - } - } - - return ERR_OK; -} - -static err_t -snmp_complete_outbound_frame(struct snmp_request *request) -{ - struct snmp_asn1_tlv tlv; - u16_t frame_size; - u8_t outbound_padding = 0; - - if (request->version == SNMP_VERSION_1) { - if (request->error_status != SNMP_ERR_NOERROR) { - /* map v2c error codes to v1 compliant error code (according to RFC 2089) */ - switch (request->error_status) { - /* mapping of implementation specific "virtual" error codes - * (during processing of frame we already stored them in error_status field, - * so no need to check all varbinds here for those exceptions as suggested by RFC) */ - case SNMP_ERR_NOSUCHINSTANCE: - case SNMP_ERR_NOSUCHOBJECT: - case SNMP_ERR_ENDOFMIBVIEW: - request->error_status = SNMP_ERR_NOSUCHNAME; - break; - /* mapping according to RFC */ - case SNMP_ERR_WRONGVALUE: - case SNMP_ERR_WRONGENCODING: - case SNMP_ERR_WRONGTYPE: - case SNMP_ERR_WRONGLENGTH: - case SNMP_ERR_INCONSISTENTVALUE: - request->error_status = SNMP_ERR_BADVALUE; - break; - case SNMP_ERR_NOACCESS: - case SNMP_ERR_NOTWRITABLE: - case SNMP_ERR_NOCREATION: - case SNMP_ERR_INCONSISTENTNAME: - case SNMP_ERR_AUTHORIZATIONERROR: - request->error_status = SNMP_ERR_NOSUCHNAME; - break; - case SNMP_ERR_RESOURCEUNAVAILABLE: - case SNMP_ERR_COMMITFAILED: - case SNMP_ERR_UNDOFAILED: - default: - request->error_status = SNMP_ERR_GENERROR; - break; - } - } - } else { - if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { - /* map error codes to according to RFC 1905 (4.2.5. The SetRequest-PDU) return 'NotWritable' for unknown OIDs) */ - switch (request->error_status) { - case SNMP_ERR_NOSUCHINSTANCE: - case SNMP_ERR_NOSUCHOBJECT: - case SNMP_ERR_ENDOFMIBVIEW: - request->error_status = SNMP_ERR_NOTWRITABLE; - break; - default: - break; - } - } - - if (request->error_status >= SNMP_VARBIND_EXCEPTION_OFFSET) { - /* should never occur because v2 frames store exceptions directly inside varbinds and not as frame error_status */ - LWIP_DEBUGF(SNMP_DEBUG, ("snmp_complete_outbound_frame() > Found v2 request with varbind exception code stored as error status!\n")); - return ERR_ARG; - } - } - - if ((request->error_status != SNMP_ERR_NOERROR) || (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ)) { - /* all inbound vars are returned in response without any modification for error responses and successful set requests*/ - struct snmp_pbuf_stream inbound_stream; - OF_BUILD_EXEC( snmp_pbuf_stream_init(&inbound_stream, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len) ); - OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, request->outbound_varbind_offset, request->outbound_pbuf->tot_len - request->outbound_varbind_offset) ); - OF_BUILD_EXEC( snmp_pbuf_stream_writeto(&inbound_stream, &(request->outbound_pbuf_stream), 0) ); - } - - frame_size = request->outbound_pbuf_stream.offset; - -#if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO - /* Calculate padding for encryption */ - if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) { - u8_t i; - outbound_padding = (8 - (u8_t)((frame_size - request->outbound_scoped_pdu_seq_offset) & 0x07)) & 0x07; - for (i = 0; i < outbound_padding; i++) { - OF_BUILD_EXEC( snmp_pbuf_stream_write(&request->outbound_pbuf_stream, 0) ); - } - } -#endif - - /* complete missing length in 'Message' sequence ; 'Message' tlv is located at the beginning (offset 0) */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size + outbound_padding - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ - OF_BUILD_EXEC( snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), request->outbound_pbuf, 0, request->outbound_pbuf->tot_len) ); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); - -#if LWIP_SNMP_V3 - if (request->version == SNMP_VERSION_3) { - /* complete missing length in 'globalData' sequence */ - /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_global_data_end - - request->outbound_msg_global_data_offset - 1 - 1); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_global_data_offset)); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - - /* complete missing length in 'msgSecurityParameters' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, request->outbound_msg_security_parameters_end - - request->outbound_msg_security_parameters_str_offset - 1 - 1); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_str_offset)); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 1, request->outbound_msg_security_parameters_end - - request->outbound_msg_security_parameters_seq_offset - 1 - 1); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_msg_security_parameters_seq_offset)); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - - /* complete missing length in scoped PDU sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_scoped_pdu_seq_offset - 1 - 3); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_seq_offset)); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - } -#endif - - /* complete missing length in 'PDU' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, request->request_out_type, 3, - frame_size - request->outbound_pdu_offset - 1 - 3); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ - OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_pdu_offset) ); - OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); - - /* process and encode final error status */ - if (request->error_status != 0) { - u16_t len; - snmp_asn1_enc_s32t_cnt(request->error_status, &len); - if (len != 1) { - /* error, we only reserved one byte for it */ - return ERR_ARG; - } - OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_status_offset) ); - OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_status) ); - - /* for compatibility to v1, log statistics; in v2 (RFC 1907) these statistics are obsoleted */ - switch (request->error_status) { - case SNMP_ERR_TOOBIG: - snmp_stats.outtoobigs++; - break; - case SNMP_ERR_NOSUCHNAME: - snmp_stats.outnosuchnames++; - break; - case SNMP_ERR_BADVALUE: - snmp_stats.outbadvalues++; - break; - case SNMP_ERR_GENERROR: - default: - snmp_stats.outgenerrs++; - break; - } - - if (request->error_status == SNMP_ERR_TOOBIG) { - request->error_index = 0; /* defined by RFC 1157 */ - } else if (request->error_index == 0) { - /* set index to varbind where error occured (if not already set before, e.g. during GetBulk processing) */ - request->error_index = request->inbound_varbind_enumerator.varbind_count; - } - } else { - if (request->request_type == SNMP_ASN1_CONTEXT_PDU_SET_REQ) { - snmp_stats.intotalsetvars += request->inbound_varbind_enumerator.varbind_count; - } else { - snmp_stats.intotalreqvars += request->inbound_varbind_enumerator.varbind_count; - } - } - - /* encode final error index*/ - if (request->error_index != 0) { - u16_t len; - snmp_asn1_enc_s32t_cnt(request->error_index, &len); - if (len != 1) { - /* error, we only reserved one byte for it */ - return ERR_VAL; - } - OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_error_index_offset) ); - OF_BUILD_EXEC( snmp_asn1_enc_s32t(&(request->outbound_pbuf_stream), len, request->error_index) ); - } - - /* complete missing length in 'VarBindList' sequence ; 'VarBindList' tlv is located directly before varbind offset */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 3, frame_size - request->outbound_varbind_offset); - OF_BUILD_EXEC( snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_varbind_offset - 1 - 3) ); /* - type - length_len(fixed, see snmp_prepare_outbound_frame()) */ - OF_BUILD_EXEC( snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv) ); - - /* Authenticate response */ -#if LWIP_SNMP_V3 && LWIP_SNMP_V3_CRYPTO - /* Encrypt response */ - if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_PRIV_FLAG)) { - u8_t key[20]; - snmpv3_priv_algo_t algo; - - /* complete missing length in PDU sequence */ - OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&(request->outbound_pbuf_stream), request->outbound_scoped_pdu_string_offset)); - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 3, frame_size + outbound_padding - - request->outbound_scoped_pdu_string_offset - 1 - 3); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&(request->outbound_pbuf_stream), &tlv)); - - OF_BUILD_EXEC(snmpv3_get_user((char *)request->msg_user_name, NULL, NULL, &algo, key)); - - OF_BUILD_EXEC(snmpv3_crypt(&request->outbound_pbuf_stream, tlv.value_len, key, - request->msg_privacy_parameters, request->msg_authoritative_engine_boots, - request->msg_authoritative_engine_time, algo, SNMP_V3_PRIV_MODE_ENCRYPT)); - } - - if (request->version == SNMP_VERSION_3 && (request->msg_flags & SNMP_V3_AUTH_FLAG)) { - u8_t key[20]; - snmpv3_auth_algo_t algo; - u8_t hmac[20]; - - OF_BUILD_EXEC(snmpv3_get_user((char *)request->msg_user_name, &algo, key, NULL, NULL)); - OF_BUILD_EXEC(snmp_pbuf_stream_init(&(request->outbound_pbuf_stream), - request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); - OF_BUILD_EXEC(snmpv3_auth(&request->outbound_pbuf_stream, frame_size + outbound_padding, key, algo, hmac)); - - MEMCPY(request->msg_authentication_parameters, hmac, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - OF_BUILD_EXEC(snmp_pbuf_stream_init(&request->outbound_pbuf_stream, - request->outbound_pbuf, 0, request->outbound_pbuf->tot_len)); - OF_BUILD_EXEC(snmp_pbuf_stream_seek_abs(&request->outbound_pbuf_stream, - request->outbound_msg_authentication_parameters_offset)); - - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 1, SNMP_V3_MAX_AUTH_PARAM_LENGTH); - OF_BUILD_EXEC(snmp_ans1_enc_tlv(&request->outbound_pbuf_stream, &tlv)); - OF_BUILD_EXEC(snmp_asn1_enc_raw(&request->outbound_pbuf_stream, - request->msg_authentication_parameters, SNMP_V3_MAX_AUTH_PARAM_LENGTH)); - } -#endif - - pbuf_realloc(request->outbound_pbuf, frame_size + outbound_padding); - - snmp_stats.outgetresponses++; - snmp_stats.outpkts++; - - return ERR_OK; -} - -static void -snmp_execute_write_callbacks(struct snmp_request *request) -{ - struct snmp_varbind_enumerator inbound_varbind_enumerator; - struct snmp_varbind vb; - - snmp_vb_enumerator_init(&inbound_varbind_enumerator, request->inbound_pbuf, request->inbound_varbind_offset, request->inbound_varbind_len); - vb.value = NULL; /* do NOT decode value (we enumerate outbound buffer here, so all varbinds have values assigned, which we don't need here) */ - - while (snmp_vb_enumerator_get_next(&inbound_varbind_enumerator, &vb) == SNMP_VB_ENUMERATOR_ERR_OK) { - snmp_write_callback(vb.oid.id, vb.oid.len, snmp_write_callback_arg); - } -} - - -/* ----------------------------------------------------------------------- */ -/* VarBind enumerator methods */ -/* ----------------------------------------------------------------------- */ - -void -snmp_vb_enumerator_init(struct snmp_varbind_enumerator *enumerator, struct pbuf *p, u16_t offset, u16_t length) -{ - snmp_pbuf_stream_init(&(enumerator->pbuf_stream), p, offset, length); - enumerator->varbind_count = 0; -} - -#define VB_PARSE_EXEC(code) PARSE_EXEC(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) -#define VB_PARSE_ASSERT(code) PARSE_ASSERT(code, SNMP_VB_ENUMERATOR_ERR_ASN1ERROR) - -snmp_vb_enumerator_err_t -snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator *enumerator, struct snmp_varbind *varbind) -{ - struct snmp_asn1_tlv tlv; - u16_t varbind_len; - err_t err; - - if (enumerator->pbuf_stream.length == 0) { - return SNMP_VB_ENUMERATOR_ERR_EOVB; - } - enumerator->varbind_count++; - - /* decode varbind itself (parent container of a varbind) */ - VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); - VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_SEQUENCE) && (tlv.value_len <= enumerator->pbuf_stream.length)); - varbind_len = tlv.value_len; - - /* decode varbind name (object id) */ - VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); - VB_PARSE_ASSERT((tlv.type == SNMP_ASN1_TYPE_OBJECT_ID) && (SNMP_ASN1_TLV_LENGTH(tlv) < varbind_len) && (tlv.value_len < enumerator->pbuf_stream.length)); - - VB_PARSE_EXEC(snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, varbind->oid.id, &(varbind->oid.len), SNMP_MAX_OBJ_ID_LEN)); - varbind_len -= SNMP_ASN1_TLV_LENGTH(tlv); - - /* decode varbind value (object id) */ - VB_PARSE_EXEC(snmp_asn1_dec_tlv(&(enumerator->pbuf_stream), &tlv)); - VB_PARSE_ASSERT((SNMP_ASN1_TLV_LENGTH(tlv) == varbind_len) && (tlv.value_len <= enumerator->pbuf_stream.length)); - varbind->type = tlv.type; - - /* shall the value be decoded ? */ - if (varbind->value != NULL) { - switch (varbind->type) { - case SNMP_ASN1_TYPE_INTEGER: - VB_PARSE_EXEC(snmp_asn1_dec_s32t(&(enumerator->pbuf_stream), tlv.value_len, (s32_t *)varbind->value)); - varbind->value_len = sizeof(s32_t); - break; - case SNMP_ASN1_TYPE_COUNTER: - case SNMP_ASN1_TYPE_GAUGE: - case SNMP_ASN1_TYPE_TIMETICKS: - VB_PARSE_EXEC(snmp_asn1_dec_u32t(&(enumerator->pbuf_stream), tlv.value_len, (u32_t *)varbind->value)); - varbind->value_len = sizeof(u32_t); - break; - case SNMP_ASN1_TYPE_OCTET_STRING: - case SNMP_ASN1_TYPE_OPAQUE: - err = snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t *)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE); - if (err == ERR_MEM) { - return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH; - } - VB_PARSE_ASSERT(err == ERR_OK); - break; - case SNMP_ASN1_TYPE_NULL: - varbind->value_len = 0; - break; - case SNMP_ASN1_TYPE_OBJECT_ID: - /* misuse tlv.length_len as OID_length transporter */ - err = snmp_asn1_dec_oid(&(enumerator->pbuf_stream), tlv.value_len, (u32_t *)varbind->value, &tlv.length_len, SNMP_MAX_OBJ_ID_LEN); - if (err == ERR_MEM) { - return SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH; - } - VB_PARSE_ASSERT(err == ERR_OK); - varbind->value_len = tlv.length_len * sizeof(u32_t); - break; - case SNMP_ASN1_TYPE_IPADDR: - if (tlv.value_len == 4) { - /* must be exactly 4 octets! */ - VB_PARSE_EXEC(snmp_asn1_dec_raw(&(enumerator->pbuf_stream), tlv.value_len, (u8_t *)varbind->value, &varbind->value_len, SNMP_MAX_VALUE_SIZE)); - } else { - VB_PARSE_ASSERT(0); - } - break; -#if LWIP_HAVE_INT64 - case SNMP_ASN1_TYPE_COUNTER64: - VB_PARSE_EXEC(snmp_asn1_dec_u64t(&(enumerator->pbuf_stream), tlv.value_len, (u64_t *)varbind->value)); - varbind->value_len = sizeof(u64_t); - break; -#endif - default: - VB_PARSE_ASSERT(0); - break; - } - } else { - snmp_pbuf_stream_seek(&(enumerator->pbuf_stream), tlv.value_len); - varbind->value_len = tlv.value_len; - } - - return SNMP_VB_ENUMERATOR_ERR_OK; -} - -#endif /* LWIP_SNMP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_msg.h b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_msg.h deleted file mode 100644 index 903f08a2d..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_msg.h +++ /dev/null @@ -1,185 +0,0 @@ -/** - * @file - * SNMP Agent message handling structures (internal API, do not use in client code). - */ - -/* - * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Christiaan Simons - * Martin Hentschel - * Elias Oenal - */ - -#ifndef LWIP_HDR_APPS_SNMP_MSG_H -#define LWIP_HDR_APPS_SNMP_MSG_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP - -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "snmp_pbuf_stream.h" -#include "lwip/ip_addr.h" -#include "lwip/err.h" - -#if LWIP_SNMP_V3 -#include "snmpv3_priv.h" -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -/* version defines used in PDU */ -#define SNMP_VERSION_1 0 -#define SNMP_VERSION_2c 1 -#define SNMP_VERSION_3 3 - -struct snmp_varbind_enumerator { - struct snmp_pbuf_stream pbuf_stream; - u16_t varbind_count; -}; - -typedef enum { - SNMP_VB_ENUMERATOR_ERR_OK = 0, - SNMP_VB_ENUMERATOR_ERR_EOVB = 1, - SNMP_VB_ENUMERATOR_ERR_ASN1ERROR = 2, - SNMP_VB_ENUMERATOR_ERR_INVALIDLENGTH = 3 -} snmp_vb_enumerator_err_t; - -void snmp_vb_enumerator_init(struct snmp_varbind_enumerator *enumerator, struct pbuf *p, u16_t offset, u16_t length); -snmp_vb_enumerator_err_t snmp_vb_enumerator_get_next(struct snmp_varbind_enumerator *enumerator, struct snmp_varbind *varbind); - -struct snmp_request { - /* Communication handle */ - void *handle; - /* source IP address */ - const ip_addr_t *source_ip; - /* source UDP port */ - u16_t source_port; - /* incoming snmp version */ - u8_t version; - /* community name (zero terminated) */ - u8_t community[SNMP_MAX_COMMUNITY_STR_LEN + 1]; - /* community string length (exclusive zero term) */ - u16_t community_strlen; - /* request type */ - u8_t request_type; - /* request ID */ - s32_t request_id; - /* error status */ - s32_t error_status; - /* error index */ - s32_t error_index; - /* non-repeaters (getBulkRequest (SNMPv2c)) */ - s32_t non_repeaters; - /* max-repetitions (getBulkRequest (SNMPv2c)) */ - s32_t max_repetitions; - - /* Usually response-pdu (2). When snmpv3 errors are detected report-pdu(8) */ - u8_t request_out_type; - -#if LWIP_SNMP_V3 - s32_t msg_id; - s32_t msg_max_size; - u8_t msg_flags; - s32_t msg_security_model; - u8_t msg_authoritative_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH]; - u8_t msg_authoritative_engine_id_len; - s32_t msg_authoritative_engine_boots; - s32_t msg_authoritative_engine_time; - u8_t msg_user_name[SNMP_V3_MAX_USER_LENGTH]; - u8_t msg_user_name_len; - u8_t msg_authentication_parameters[SNMP_V3_MAX_AUTH_PARAM_LENGTH]; - u8_t msg_authentication_parameters_len; - u8_t msg_privacy_parameters[SNMP_V3_MAX_PRIV_PARAM_LENGTH]; - u8_t msg_privacy_parameters_len; - u8_t context_engine_id[SNMP_V3_MAX_ENGINE_ID_LENGTH]; - u8_t context_engine_id_len; - u8_t context_name[SNMP_V3_MAX_ENGINE_ID_LENGTH]; - u8_t context_name_len; -#endif - - struct pbuf *inbound_pbuf; - struct snmp_varbind_enumerator inbound_varbind_enumerator; - u16_t inbound_varbind_offset; - u16_t inbound_varbind_len; - u16_t inbound_padding_len; - - struct pbuf *outbound_pbuf; - struct snmp_pbuf_stream outbound_pbuf_stream; - u16_t outbound_pdu_offset; - u16_t outbound_error_status_offset; - u16_t outbound_error_index_offset; - u16_t outbound_varbind_offset; -#if LWIP_SNMP_V3 - u16_t outbound_msg_global_data_offset; - u16_t outbound_msg_global_data_end; - u16_t outbound_msg_security_parameters_str_offset; - u16_t outbound_msg_security_parameters_seq_offset; - u16_t outbound_msg_security_parameters_end; - u16_t outbound_msg_authentication_parameters_offset; - u16_t outbound_scoped_pdu_seq_offset; - u16_t outbound_scoped_pdu_string_offset; -#endif - - u8_t value_buffer[SNMP_MAX_VALUE_SIZE]; -}; - -/** A helper struct keeping length information about varbinds */ -struct snmp_varbind_len { - u8_t vb_len_len; - u16_t vb_value_len; - u8_t oid_len_len; - u16_t oid_value_len; - u8_t value_len_len; - u16_t value_value_len; -}; - -/** Agent community string */ -extern const char *snmp_community; -/** Agent community string for write access */ -extern const char *snmp_community_write; -/** handle for sending traps */ -extern void *snmp_traps_handle; - -void snmp_receive(void *handle, struct pbuf *p, const ip_addr_t *source_ip, u16_t port); -err_t snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port); -u8_t snmp_get_local_ip_for_dst(void *handle, const ip_addr_t *dst, ip_addr_t *result); -err_t snmp_varbind_length(struct snmp_varbind *varbind, struct snmp_varbind_len *len); -err_t snmp_append_outbound_varbind(struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbind); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_MSG_H */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_netconn.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_netconn.c deleted file mode 100644 index 8850acb50..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_netconn.c +++ /dev/null @@ -1,123 +0,0 @@ -/** - * @file - * SNMP netconn frontend. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP && SNMP_USE_NETCONN - -#include -#include "lwip/api.h" -#include "lwip/ip.h" -#include "lwip/udp.h" -#include "snmp_msg.h" -#include "lwip/sys.h" -#include "lwip/prot/iana.h" - -/** SNMP netconn API worker thread */ -static void -snmp_netconn_thread(void *arg) -{ - struct netconn *conn; - struct netbuf *buf; - err_t err; - LWIP_UNUSED_ARG(arg); - - /* Bind to SNMP port with default IP address */ -#if LWIP_IPV6 - conn = netconn_new(NETCONN_UDP_IPV6); - netconn_bind(conn, IP6_ADDR_ANY, LWIP_IANA_PORT_SNMP); -#else /* LWIP_IPV6 */ - conn = netconn_new(NETCONN_UDP); - netconn_bind(conn, IP4_ADDR_ANY, LWIP_IANA_PORT_SNMP); -#endif /* LWIP_IPV6 */ - LWIP_ERROR("snmp_netconn: invalid conn", (conn != NULL), return;); - - snmp_traps_handle = conn; - - do { - err = netconn_recv(conn, &buf); - - if (err == ERR_OK) { - snmp_receive(conn, buf->p, &buf->addr, buf->port); - } - - if (buf != NULL) { - netbuf_delete(buf); - } - } while (1); -} - -err_t -snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port) -{ - err_t result; - struct netbuf buf; - - memset(&buf, 0, sizeof(buf)); - buf.p = p; - result = netconn_sendto((struct netconn *)handle, &buf, dst, port); - - return result; -} - -u8_t -snmp_get_local_ip_for_dst(void *handle, const ip_addr_t *dst, ip_addr_t *result) -{ - struct netconn *conn = (struct netconn *)handle; - struct netif *dst_if; - const ip_addr_t *dst_ip; - - LWIP_UNUSED_ARG(conn); /* unused in case of IPV4 only configuration */ - - ip_route_get_local_ip(&conn->pcb.udp->local_ip, dst, dst_if, dst_ip); - - if ((dst_if != NULL) && (dst_ip != NULL)) { - ip_addr_copy(*result, *dst_ip); - return 1; - } else { - return 0; - } -} - -/** - * Starts SNMP Agent. - */ -void -snmp_init(void) -{ - LWIP_ASSERT_CORE_LOCKED(); - sys_thread_new("snmp_netconn", snmp_netconn_thread, NULL, SNMP_STACK_SIZE, SNMP_THREAD_PRIO); -} - -#endif /* LWIP_SNMP && SNMP_USE_NETCONN */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_pbuf_stream.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_pbuf_stream.c deleted file mode 100644 index 42867fbbc..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_pbuf_stream.c +++ /dev/null @@ -1,156 +0,0 @@ -/** - * @file - * SNMP pbuf stream wrapper implementation (internal API, do not use in client code). - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "snmp_pbuf_stream.h" -#include "lwip/def.h" -#include - -err_t -snmp_pbuf_stream_init(struct snmp_pbuf_stream *pbuf_stream, struct pbuf *p, u16_t offset, u16_t length) -{ - pbuf_stream->offset = offset; - pbuf_stream->length = length; - pbuf_stream->pbuf = p; - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_read(struct snmp_pbuf_stream *pbuf_stream, u8_t *data) -{ - if (pbuf_stream->length == 0) { - return ERR_BUF; - } - - if (pbuf_copy_partial(pbuf_stream->pbuf, data, 1, pbuf_stream->offset) == 0) { - return ERR_BUF; - } - - pbuf_stream->offset++; - pbuf_stream->length--; - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_write(struct snmp_pbuf_stream *pbuf_stream, u8_t data) -{ - return snmp_pbuf_stream_writebuf(pbuf_stream, &data, 1); -} - -err_t -snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream *pbuf_stream, const void *buf, u16_t buf_len) -{ - if (pbuf_stream->length < buf_len) { - return ERR_BUF; - } - - if (pbuf_take_at(pbuf_stream->pbuf, buf, buf_len, pbuf_stream->offset) != ERR_OK) { - return ERR_BUF; - } - - pbuf_stream->offset += buf_len; - pbuf_stream->length -= buf_len; - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_writeto(struct snmp_pbuf_stream *pbuf_stream, struct snmp_pbuf_stream *target_pbuf_stream, u16_t len) -{ - - if ((pbuf_stream == NULL) || (target_pbuf_stream == NULL)) { - return ERR_ARG; - } - if ((len > pbuf_stream->length) || (len > target_pbuf_stream->length)) { - return ERR_ARG; - } - - if (len == 0) { - len = LWIP_MIN(pbuf_stream->length, target_pbuf_stream->length); - } - - while (len > 0) { - u16_t chunk_len; - err_t err; - u16_t target_offset; - struct pbuf *pbuf = pbuf_skip(pbuf_stream->pbuf, pbuf_stream->offset, &target_offset); - - if ((pbuf == NULL) || (pbuf->len == 0)) { - return ERR_BUF; - } - - chunk_len = LWIP_MIN(len, pbuf->len); - err = snmp_pbuf_stream_writebuf(target_pbuf_stream, &((u8_t *)pbuf->payload)[target_offset], chunk_len); - if (err != ERR_OK) { - return err; - } - - pbuf_stream->offset += chunk_len; - pbuf_stream->length -= chunk_len; - len -= chunk_len; - } - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_seek(struct snmp_pbuf_stream *pbuf_stream, s32_t offset) -{ - if ((offset < 0) || (offset > pbuf_stream->length)) { - /* we cannot seek backwards or forward behind stream end */ - return ERR_ARG; - } - - pbuf_stream->offset += (u16_t)offset; - pbuf_stream->length -= (u16_t)offset; - - return ERR_OK; -} - -err_t -snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream *pbuf_stream, u32_t offset) -{ - s32_t rel_offset = offset - pbuf_stream->offset; - return snmp_pbuf_stream_seek(pbuf_stream, rel_offset); -} - -#endif /* LWIP_SNMP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_pbuf_stream.h b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_pbuf_stream.h deleted file mode 100644 index 682713f95..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_pbuf_stream.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @file - * SNMP pbuf stream wrapper (internal API, do not use in client code). - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#ifndef LWIP_HDR_APPS_SNMP_PBUF_STREAM_H -#define LWIP_HDR_APPS_SNMP_PBUF_STREAM_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP - -#include "lwip/err.h" -#include "lwip/pbuf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct snmp_pbuf_stream { - struct pbuf *pbuf; - u16_t offset; - u16_t length; -}; - -err_t snmp_pbuf_stream_init(struct snmp_pbuf_stream *pbuf_stream, struct pbuf *p, u16_t offset, u16_t length); -err_t snmp_pbuf_stream_read(struct snmp_pbuf_stream *pbuf_stream, u8_t *data); -err_t snmp_pbuf_stream_write(struct snmp_pbuf_stream *pbuf_stream, u8_t data); -err_t snmp_pbuf_stream_writebuf(struct snmp_pbuf_stream *pbuf_stream, const void *buf, u16_t buf_len); -err_t snmp_pbuf_stream_writeto(struct snmp_pbuf_stream *pbuf_stream, struct snmp_pbuf_stream *target_pbuf_stream, u16_t len); -err_t snmp_pbuf_stream_seek(struct snmp_pbuf_stream *pbuf_stream, s32_t offset); -err_t snmp_pbuf_stream_seek_abs(struct snmp_pbuf_stream *pbuf_stream, u32_t offset); - -#ifdef __cplusplus -} -#endif - -#endif /* LWIP_SNMP */ - -#endif /* LWIP_HDR_APPS_SNMP_PBUF_STREAM_H */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_raw.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_raw.c deleted file mode 100644 index e203cb694..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_raw.c +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @file - * SNMP RAW API frontend. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - */ - -#include "lwip/apps/snmp_opts.h" -#include "lwip/ip_addr.h" - -#if LWIP_SNMP && SNMP_USE_RAW - -#include "lwip/udp.h" -#include "lwip/ip.h" -#include "lwip/prot/iana.h" -#include "snmp_msg.h" - -/* lwIP UDP receive callback function */ -static void -snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - LWIP_UNUSED_ARG(arg); - - snmp_receive(pcb, p, addr, port); - - pbuf_free(p); -} - -err_t -snmp_sendto(void *handle, struct pbuf *p, const ip_addr_t *dst, u16_t port) -{ - return udp_sendto((struct udp_pcb *)handle, p, dst, port); -} - -u8_t -snmp_get_local_ip_for_dst(void *handle, const ip_addr_t *dst, ip_addr_t *result) -{ - struct udp_pcb *udp_pcb = (struct udp_pcb *)handle; - struct netif *dst_if; - const ip_addr_t *dst_ip; - - LWIP_UNUSED_ARG(udp_pcb); /* unused in case of IPV4 only configuration */ - - ip_route_get_local_ip(&udp_pcb->local_ip, dst, dst_if, dst_ip); - - if ((dst_if != NULL) && (dst_ip != NULL)) { - ip_addr_copy(*result, *dst_ip); - return 1; - } else { - return 0; - } -} - -/** - * @ingroup snmp_core - * Starts SNMP Agent. - * Allocates UDP pcb and binds it to IP_ANY_TYPE port 161. - */ -void -snmp_init(void) -{ - err_t err; - - struct udp_pcb *snmp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ERROR("snmp_raw: no PCB", (snmp_pcb != NULL), return;); - - LWIP_ASSERT_CORE_LOCKED(); - - snmp_traps_handle = snmp_pcb; - - udp_recv(snmp_pcb, snmp_recv, NULL); - err = udp_bind(snmp_pcb, IP_ANY_TYPE, LWIP_IANA_PORT_SNMP); - LWIP_ERROR("snmp_raw: Unable to bind PCB", (err == ERR_OK), return;); -} - -#endif /* LWIP_SNMP && SNMP_USE_RAW */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_scalar.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_scalar.c deleted file mode 100644 index 094f52fe9..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_scalar.c +++ /dev/null @@ -1,232 +0,0 @@ -/** - * @file - * SNMP scalar node support implementation. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_scalar.h" -#include "lwip/apps/snmp_core.h" - -static s16_t snmp_scalar_array_get_value(struct snmp_node_instance *instance, void *value); -static snmp_err_t snmp_scalar_array_set_test(struct snmp_node_instance *instance, u16_t value_len, void *value); -static snmp_err_t snmp_scalar_array_set_value(struct snmp_node_instance *instance, u16_t value_len, void *value); - -snmp_err_t -snmp_scalar_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance) -{ - const struct snmp_scalar_node *scalar_node = (const struct snmp_scalar_node *)(const void *)instance->node; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* scalar only has one dedicated instance: .0 */ - if ((instance->instance_oid.len != 1) || (instance->instance_oid.id[0] != 0)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - instance->access = scalar_node->access; - instance->asn1_type = scalar_node->asn1_type; - instance->get_value = scalar_node->get_value; - instance->set_test = scalar_node->set_test; - instance->set_value = scalar_node->set_value; - return SNMP_ERR_NOERROR; -} - -snmp_err_t -snmp_scalar_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance) -{ - /* because our only instance is .0 we can only return a next instance if no instance oid is passed */ - if (instance->instance_oid.len == 0) { - instance->instance_oid.len = 1; - instance->instance_oid.id[0] = 0; - - return snmp_scalar_get_instance(root_oid, root_oid_len, instance); - } - - return SNMP_ERR_NOSUCHINSTANCE; -} - - -snmp_err_t -snmp_scalar_array_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance) -{ - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - if ((instance->instance_oid.len == 2) && (instance->instance_oid.id[1] == 0)) { - const struct snmp_scalar_array_node *array_node = (const struct snmp_scalar_array_node *)(const void *)instance->node; - const struct snmp_scalar_array_node_def *array_node_def = array_node->array_nodes; - u32_t i = 0; - - while (i < array_node->array_node_count) { - if (array_node_def->oid == instance->instance_oid.id[0]) { - break; - } - - array_node_def++; - i++; - } - - if (i < array_node->array_node_count) { - instance->access = array_node_def->access; - instance->asn1_type = array_node_def->asn1_type; - instance->get_value = snmp_scalar_array_get_value; - instance->set_test = snmp_scalar_array_set_test; - instance->set_value = snmp_scalar_array_set_value; - instance->reference.const_ptr = array_node_def; - - return SNMP_ERR_NOERROR; - } - } - - return SNMP_ERR_NOSUCHINSTANCE; -} - -snmp_err_t -snmp_scalar_array_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance) -{ - const struct snmp_scalar_array_node *array_node = (const struct snmp_scalar_array_node *)(const void *)instance->node; - const struct snmp_scalar_array_node_def *array_node_def = array_node->array_nodes; - const struct snmp_scalar_array_node_def *result = NULL; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - if ((instance->instance_oid.len == 0) && (array_node->array_node_count > 0)) { - /* return node with lowest OID */ - u16_t i = 0; - - result = array_node_def; - array_node_def++; - - for (i = 1; i < array_node->array_node_count; i++) { - if (array_node_def->oid < result->oid) { - result = array_node_def; - } - array_node_def++; - } - } else if (instance->instance_oid.len >= 1) { - if (instance->instance_oid.len == 1) { - /* if we have the requested OID we return its instance, otherwise we search for the next available */ - u16_t i = 0; - while (i < array_node->array_node_count) { - if (array_node_def->oid == instance->instance_oid.id[0]) { - result = array_node_def; - break; - } - - array_node_def++; - i++; - } - } - if (result == NULL) { - u32_t oid_dist = 0xFFFFFFFFUL; - u16_t i = 0; - array_node_def = array_node->array_nodes; /* may be already at the end when if case before was executed without result -> reinitialize to start */ - while (i < array_node->array_node_count) { - if ((array_node_def->oid > instance->instance_oid.id[0]) && - ((u32_t)(array_node_def->oid - instance->instance_oid.id[0]) < oid_dist)) { - result = array_node_def; - oid_dist = array_node_def->oid - instance->instance_oid.id[0]; - } - - array_node_def++; - i++; - } - } - } - - if (result == NULL) { - /* nothing to return */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - instance->instance_oid.len = 2; - instance->instance_oid.id[0] = result->oid; - instance->instance_oid.id[1] = 0; - - instance->access = result->access; - instance->asn1_type = result->asn1_type; - instance->get_value = snmp_scalar_array_get_value; - instance->set_test = snmp_scalar_array_set_test; - instance->set_value = snmp_scalar_array_set_value; - instance->reference.const_ptr = result; - - return SNMP_ERR_NOERROR; -} - -static s16_t -snmp_scalar_array_get_value(struct snmp_node_instance *instance, void *value) -{ - s16_t result = -1; - const struct snmp_scalar_array_node *array_node = (const struct snmp_scalar_array_node *)(const void *)instance->node; - const struct snmp_scalar_array_node_def *array_node_def = (const struct snmp_scalar_array_node_def *)instance->reference.const_ptr; - - if (array_node->get_value != NULL) { - result = array_node->get_value(array_node_def, value); - } - return result; -} - -static snmp_err_t -snmp_scalar_array_set_test(struct snmp_node_instance *instance, u16_t value_len, void *value) -{ - snmp_err_t result = SNMP_ERR_NOTWRITABLE; - const struct snmp_scalar_array_node *array_node = (const struct snmp_scalar_array_node *)(const void *)instance->node; - const struct snmp_scalar_array_node_def *array_node_def = (const struct snmp_scalar_array_node_def *)instance->reference.const_ptr; - - if (array_node->set_test != NULL) { - result = array_node->set_test(array_node_def, value_len, value); - } - return result; -} - -static snmp_err_t -snmp_scalar_array_set_value(struct snmp_node_instance *instance, u16_t value_len, void *value) -{ - snmp_err_t result = SNMP_ERR_NOTWRITABLE; - const struct snmp_scalar_array_node *array_node = (const struct snmp_scalar_array_node *)(const void *)instance->node; - const struct snmp_scalar_array_node_def *array_node_def = (const struct snmp_scalar_array_node_def *)instance->reference.const_ptr; - - if (array_node->set_value != NULL) { - result = array_node->set_value(array_node_def, value_len, value); - } - return result; -} - -#endif /* LWIP_SNMP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_snmpv2_framework.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_snmpv2_framework.c deleted file mode 100644 index a5611dbf7..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_snmpv2_framework.c +++ /dev/null @@ -1,90 +0,0 @@ -/* -Generated by LwipMibCompiler -*/ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP && LWIP_SNMP_V3 /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_snmpv2_framework.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmpv3.h" -#include "snmpv3_priv.h" - -#include "lwip/sys.h" - -#include - -const struct snmp_obj_id usmNoAuthProtocol = { 10, { 1, 3, 6, 1, 6, 3, 10, 1, 1, 1 } }; -const struct snmp_obj_id usmHMACMD5AuthProtocol = { 10, { 1, 3, 6, 1, 6, 3, 10, 1, 1, 2 } }; -const struct snmp_obj_id usmHMACSHAAuthProtocol = { 10, { 1, 3, 6, 1, 6, 3, 10, 1, 1, 3 } }; -/* .4 sha-224 - * .5 sha-256 - * .6 sha-384 - * .7 sha-512 - */ - -const struct snmp_obj_id usmNoPrivProtocol = { 10, { 1, 3, 6, 1, 6, 3, 10, 1, 2, 1 } }; -const struct snmp_obj_id usmDESPrivProtocol = { 10, { 1, 3, 6, 1, 6, 3, 10, 1, 2, 2 } }; -/* .3 3des-ede */ -const struct snmp_obj_id usmAESPrivProtocol = { 10, { 1, 3, 6, 1, 6, 3, 10, 1, 2, 4 } }; -/* .5 unknown - * .6 unknown - * .7 unknown - */ - -/* TODO: where should this value come from? */ -#define SNMP_FRAMEWORKMIB_SNMPENGINEMAXMESSAGESIZE 1500 - -/* --- snmpFrameworkMIBObjects 1.3.6.1.6.3.10.2 ----------------------------------------------------- */ -static s16_t snmpengine_scalars_get_value(const struct snmp_scalar_array_node_def *node, void *value) -{ - const char *engineid; - u8_t engineid_len; - - switch (node->oid) { - case 1: /* snmpEngineID */ - snmpv3_get_engine_id(&engineid, &engineid_len); - MEMCPY(value, engineid, engineid_len); - return engineid_len; - case 2: /* snmpEngineBoots */ - *(s32_t *)value = snmpv3_get_engine_boots_internal(); - return sizeof(s32_t); - case 3: /* snmpEngineTime */ - *(s32_t *)value = snmpv3_get_engine_time_internal(); - return sizeof(s32_t); - case 4: /* snmpEngineMaxMessageSize */ - *(s32_t *)value = SNMP_FRAMEWORKMIB_SNMPENGINEMAXMESSAGESIZE; - return sizeof(s32_t); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG, ("snmpengine_scalars_get_value(): unknown id: %"S32_F"\n", node->oid)); - return 0; - } -} - -static const struct snmp_scalar_array_node_def snmpengine_scalars_nodes[] = { - {1, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpEngineID */ - {2, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpEngineBoots */ - {3, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpEngineTime */ - {4, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY}, /* snmpEngineMaxMessageSize */ -}; -static const struct snmp_scalar_array_node snmpengine_scalars = SNMP_SCALAR_CREATE_ARRAY_NODE(1, snmpengine_scalars_nodes, snmpengine_scalars_get_value, NULL, NULL); - -static const struct snmp_node *const snmpframeworkmibobjects_subnodes[] = { - &snmpengine_scalars.node.node -}; -static const struct snmp_tree_node snmpframeworkmibobjects_treenode = SNMP_CREATE_TREE_NODE(2, snmpframeworkmibobjects_subnodes); - -/* --- snmpFrameworkMIB ----------------------------------------------------- */ -static const struct snmp_node *const snmpframeworkmib_subnodes[] = { - &snmpframeworkmibobjects_treenode.node -}; -static const struct snmp_tree_node snmpframeworkmib_root = SNMP_CREATE_TREE_NODE(10, snmpframeworkmib_subnodes); -static const u32_t snmpframeworkmib_base_oid[] = {1, 3, 6, 1, 6, 3, 10}; -const struct snmp_mib snmpframeworkmib = {snmpframeworkmib_base_oid, LWIP_ARRAYSIZE(snmpframeworkmib_base_oid), &snmpframeworkmib_root.node}; - -/* --- snmpFrameworkMIB ----------------------------------------------------- */ -#endif /* LWIP_SNMP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_snmpv2_usm.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_snmpv2_usm.c deleted file mode 100644 index 7490c9c83..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_snmpv2_usm.c +++ /dev/null @@ -1,410 +0,0 @@ -/* -Generated by LwipMibCompiler -*/ - -#include "lwip/apps/snmp_opts.h" -#if LWIP_SNMP && LWIP_SNMP_V3 - -#include "lwip/apps/snmp_snmpv2_usm.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_scalar.h" -#include "lwip/apps/snmp_table.h" -#include "lwip/apps/snmpv3.h" -#include "snmpv3_priv.h" - -#include "lwip/apps/snmp_snmpv2_framework.h" - -#include - -/* --- usmUser 1.3.6.1.6.3.15.1.2 ----------------------------------------------------- */ - -static const struct snmp_oid_range usmUserTable_oid_ranges[] = { - { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, - { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, - { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, - { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, - { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, - { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, - { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, - { 0, 0xff }, { 0, 0xff }, { 0, 0xff }, { 0, 0xff } -}; - -static void snmp_engineid_to_oid(const char *engineid, u32_t *oid, u32_t len) -{ - u8_t i; - - for (i = 0; i < len; i++) { - oid[i] = engineid[i]; - } -} - -static void snmp_oid_to_name(char *name, const u32_t *oid, size_t len) -{ - u8_t i; - - for (i = 0; i < len; i++) { - name[i] = (char)oid[i]; - } -} - -static void snmp_name_to_oid(const char *name, u32_t *oid, size_t len) -{ - u8_t i; - - for (i = 0; i < len; i++) { - oid[i] = name[i]; - } -} - -static const struct snmp_obj_id *snmp_auth_algo_to_oid(snmpv3_auth_algo_t algo) -{ - if (algo == SNMP_V3_AUTH_ALGO_MD5) { - return &usmHMACMD5AuthProtocol; - } else if (algo == SNMP_V3_AUTH_ALGO_SHA) { - return &usmHMACMD5AuthProtocol; - } - - return &usmNoAuthProtocol; -} - -static const struct snmp_obj_id *snmp_priv_algo_to_oid(snmpv3_priv_algo_t algo) -{ - if (algo == SNMP_V3_PRIV_ALGO_DES) { - return &usmDESPrivProtocol; - } else if (algo == SNMP_V3_PRIV_ALGO_AES) { - return &usmAESPrivProtocol; - } - - return &usmNoPrivProtocol; -} - -char username[32]; - -static snmp_err_t usmusertable_get_instance(const u32_t *column, const u32_t *row_oid, u8_t row_oid_len, struct snmp_node_instance *cell_instance) -{ - const char *engineid; - u8_t eid_len; - - u32_t engineid_oid[SNMP_V3_MAX_ENGINE_ID_LENGTH]; - - u8_t name_len; - u8_t engineid_len; - - u8_t name_start; - u8_t engineid_start; - - LWIP_UNUSED_ARG(column); - - snmpv3_get_engine_id(&engineid, &eid_len); - - engineid_len = (u8_t)row_oid[0]; - engineid_start = 1; - - if (engineid_len != eid_len) { - /* EngineID length does not match! */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - if (engineid_len > row_oid_len) { - /* row OID doesn't contain enough data according to engineid_len.*/ - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(&row_oid[engineid_start], engineid_len, usmUserTable_oid_ranges, engineid_len)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - snmp_engineid_to_oid(engineid, engineid_oid, engineid_len); - - /* Verify EngineID */ - if (snmp_oid_equal(&row_oid[engineid_start], engineid_len, engineid_oid, engineid_len)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - name_len = (u8_t)row_oid[engineid_start + engineid_len]; - name_start = engineid_start + engineid_len + 1; - - if (name_len > SNMP_V3_MAX_USER_LENGTH) { - /* specified name is too long */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - if (1 + engineid_len + 1 + name_len != row_oid_len) { - /* Length of EngineID and name does not match row oid length. (+2 for length fields)*/ - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* check if incoming OID length and if values are in plausible range */ - if (!snmp_oid_in_range(&row_oid[name_start], name_len, usmUserTable_oid_ranges, name_len)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* Verify if user exists */ - memset(username, 0, sizeof(username)); - snmp_oid_to_name(username, &row_oid[name_start], name_len); - if (snmpv3_get_user(username, NULL, NULL, NULL, NULL) != ERR_OK) { - return SNMP_ERR_NOSUCHINSTANCE; - } - - /* Save name in reference pointer to make it easier to handle later on */ - cell_instance->reference.ptr = username; - cell_instance->reference_len = name_len; - - /* user was found */ - return SNMP_ERR_NOERROR; -} - -/* - * valid oid options - * - * . - * .. - * .. - * ... - * .... - * .... - * - */ -static snmp_err_t usmusertable_get_next_instance(const u32_t *column, struct snmp_obj_id *row_oid, struct snmp_node_instance *cell_instance) -{ - const char *engineid; - u8_t eid_len; - - u32_t engineid_oid[SNMP_V3_MAX_ENGINE_ID_LENGTH]; - - u8_t name_len; - u8_t engineid_len; - - u8_t name_start; - u8_t engineid_start = 1; - u8_t i; - - struct snmp_next_oid_state state; - - u32_t result_temp[LWIP_ARRAYSIZE(usmUserTable_oid_ranges)]; - - LWIP_UNUSED_ARG(column); - - snmpv3_get_engine_id(&engineid, &eid_len); - - /* If EngineID might be given */ - if (row_oid->len > 0) { - engineid_len = (u8_t)row_oid->id[0]; - engineid_start = 1; - - if (engineid_len != eid_len) { - /* EngineID length does not match! */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - if (engineid_len > row_oid->len) { - /* Verify partial EngineID */ - snmp_engineid_to_oid(engineid, engineid_oid, row_oid->len - 1); - if (!snmp_oid_equal(&row_oid->id[engineid_start], row_oid->len - 1, engineid_oid, row_oid->len - 1)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - } else { - /* Verify complete EngineID */ - snmp_engineid_to_oid(engineid, engineid_oid, engineid_len); - if (!snmp_oid_equal(&row_oid->id[engineid_start], engineid_len, engineid_oid, engineid_len)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - } - - /* At this point, the given EngineID (partially) matches the local EngineID.*/ - - /* If name might also be given */ - if (row_oid->len > engineid_start + engineid_len) { - name_len = (u8_t)row_oid->id[engineid_start + engineid_len]; - name_start = engineid_start + engineid_len + 1; - - if (name_len > SNMP_V3_MAX_USER_LENGTH) { - /* specified name is too long, max length is 32 according to mib file.*/ - return SNMP_ERR_NOSUCHINSTANCE; - } - - if (row_oid->len < engineid_len + name_len + 2) { - /* Partial name given according to oid.*/ - u8_t tmplen = row_oid->len - engineid_len - 2; - if (!snmp_oid_in_range(&row_oid->id[name_start], tmplen, usmUserTable_oid_ranges, tmplen)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - } else { - /* Full name given according to oid. Also test for too much data.*/ - u8_t tmplen = row_oid->len - engineid_len - 2; - if (!snmp_oid_in_range(&row_oid->id[name_start], name_len, usmUserTable_oid_ranges, tmplen)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - } - - /* At this point the EngineID and (partial) UserName match the local EngineID and UserName.*/ - } - } - - /* init struct to search next oid */ - snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(usmUserTable_oid_ranges)); - - for (i = 0; i < snmpv3_get_amount_of_users(); i++) { - u32_t test_oid[LWIP_ARRAYSIZE(usmUserTable_oid_ranges)]; - - test_oid[0] = eid_len; - snmp_engineid_to_oid(engineid, &test_oid[1], eid_len); - - snmpv3_get_username(username, i); - - test_oid[1 + eid_len] = strlen(username); - snmp_name_to_oid(username, &test_oid[2 + eid_len], strlen(username)); - - /* check generated OID: is it a candidate for the next one? */ - snmp_next_oid_check(&state, test_oid, (u8_t)(1 + eid_len + 1 + strlen(username)), LWIP_PTR_NUMERIC_CAST(void *, i)); - } - - /* did we find a next one? */ - if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { - snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); - /* store username for subsequent operations (get/test/set) */ - memset(username, 0, sizeof(username)); - snmpv3_get_username(username, LWIP_PTR_NUMERIC_CAST(u8_t, state.reference)); - cell_instance->reference.ptr = username; - cell_instance->reference_len = strlen(username); - return SNMP_ERR_NOERROR; - } - - /* not found */ - return SNMP_ERR_NOSUCHINSTANCE; -} - -static s16_t usmusertable_get_value(struct snmp_node_instance *cell_instance, void *value) -{ - snmpv3_user_storagetype_t storage_type; - - switch (SNMP_TABLE_GET_COLUMN_FROM_OID(cell_instance->instance_oid.id)) { - case 3: /* usmUserSecurityName */ - MEMCPY(value, cell_instance->reference.ptr, cell_instance->reference_len); - return (s16_t)cell_instance->reference_len; - case 4: /* usmUserCloneFrom */ - MEMCPY(value, snmp_zero_dot_zero.id, snmp_zero_dot_zero.len * sizeof(u32_t)); - return snmp_zero_dot_zero.len * sizeof(u32_t); - case 5: { /* usmUserAuthProtocol */ - const struct snmp_obj_id *auth_algo; - snmpv3_auth_algo_t auth_algo_val; - snmpv3_get_user((const char *)cell_instance->reference.ptr, &auth_algo_val, NULL, NULL, NULL); - auth_algo = snmp_auth_algo_to_oid(auth_algo_val); - MEMCPY(value, auth_algo->id, auth_algo->len * sizeof(u32_t)); - return auth_algo->len * sizeof(u32_t); - } - case 6: /* usmUserAuthKeyChange */ - return 0; - case 7: /* usmUserOwnAuthKeyChange */ - return 0; - case 8: { /* usmUserPrivProtocol */ - const struct snmp_obj_id *priv_algo; - snmpv3_priv_algo_t priv_algo_val; - snmpv3_get_user((const char *)cell_instance->reference.ptr, NULL, NULL, &priv_algo_val, NULL); - priv_algo = snmp_priv_algo_to_oid(priv_algo_val); - MEMCPY(value, priv_algo->id, priv_algo->len * sizeof(u32_t)); - return priv_algo->len * sizeof(u32_t); - } - case 9: /* usmUserPrivKeyChange */ - return 0; - case 10: /* usmUserOwnPrivKeyChange */ - return 0; - case 11: /* usmUserPublic */ - /* TODO: Implement usmUserPublic */ - return 0; - case 12: /* usmUserStorageType */ - snmpv3_get_user_storagetype((const char *)cell_instance->reference.ptr, &storage_type); - *(s32_t *)value = storage_type; - return sizeof(s32_t); - case 13: /* usmUserStatus */ - *(s32_t *)value = 1; /* active */ - return sizeof(s32_t); - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG, ("usmusertable_get_value(): unknown id: %"S32_F"\n", SNMP_TABLE_GET_COLUMN_FROM_OID(cell_instance->instance_oid.id))); - return 0; - } -} - -/* --- usmMIBObjects 1.3.6.1.6.3.15.1 ----------------------------------------------------- */ -static s16_t usmstats_scalars_get_value(const struct snmp_scalar_array_node_def *node, void *value) -{ - u32_t *uint_ptr = (u32_t *)value; - switch (node->oid) { - case 1: /* usmStatsUnsupportedSecLevels */ - *uint_ptr = snmp_stats.unsupportedseclevels; - break; - case 2: /* usmStatsNotInTimeWindows */ - *uint_ptr = snmp_stats.notintimewindows; - break; - case 3: /* usmStatsUnknownUserNames */ - *uint_ptr = snmp_stats.unknownusernames; - break; - case 4: /* usmStatsUnknownEngineIDs */ - *uint_ptr = snmp_stats.unknownengineids; - break; - case 5: /* usmStatsWrongDigests */ - *uint_ptr = snmp_stats.wrongdigests; - break; - case 6: /* usmStatsDecryptionErrors */ - *uint_ptr = snmp_stats.decryptionerrors; - break; - default: - LWIP_DEBUGF(SNMP_MIB_DEBUG, ("usmstats_scalars_get_value(): unknown id: %"S32_F"\n", node->oid)); - return 0; - } - - return sizeof(*uint_ptr); -} - -/* --- snmpUsmMIB ----------------------------------------------------- */ - -/* --- usmUser 1.3.6.1.6.3.15.1.2 ----------------------------------------------------- */ - -static const struct snmp_table_col_def usmusertable_columns[] = { - {3, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmUserSecurityName */ - {4, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmUserCloneFrom */ - {5, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmUserAuthProtocol */ - {6, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmUserAuthKeyChange */ - {7, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmUserOwnAuthKeyChange */ - {8, SNMP_ASN1_TYPE_OBJECT_ID, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmUserPrivProtocol */ - {9, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmUserPrivKeyChange */ - {10, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmUserOwnPrivKeyChange */ - {11, SNMP_ASN1_TYPE_OCTET_STRING, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmUserPublic */ - {12, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmUserStorageType */ - {13, SNMP_ASN1_TYPE_INTEGER, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmUserStatus */ -}; -static const struct snmp_table_node usmusertable = SNMP_TABLE_CREATE(2, usmusertable_columns, usmusertable_get_instance, usmusertable_get_next_instance, usmusertable_get_value, NULL, NULL); - -static const struct snmp_node *const usmuser_subnodes[] = { - &usmusertable.node.node -}; -static const struct snmp_tree_node usmuser_treenode = SNMP_CREATE_TREE_NODE(2, usmuser_subnodes); - -/* --- usmMIBObjects 1.3.6.1.6.3.15.1 ----------------------------------------------------- */ -static const struct snmp_scalar_array_node_def usmstats_scalars_nodes[] = { - {1, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmStatsUnsupportedSecLevels */ - {2, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmStatsNotInTimeWindows */ - {3, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmStatsUnknownUserNames */ - {4, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmStatsUnknownEngineIDs */ - {5, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmStatsWrongDigests */ - {6, SNMP_ASN1_TYPE_COUNTER, SNMP_NODE_INSTANCE_READ_ONLY}, /* usmStatsDecryptionErrors */ -}; -static const struct snmp_scalar_array_node usmstats_scalars = SNMP_SCALAR_CREATE_ARRAY_NODE(1, usmstats_scalars_nodes, usmstats_scalars_get_value, NULL, NULL); - -static const struct snmp_node *const usmmibobjects_subnodes[] = { - &usmstats_scalars.node.node, - &usmuser_treenode.node -}; -static const struct snmp_tree_node usmmibobjects_treenode = SNMP_CREATE_TREE_NODE(1, usmmibobjects_subnodes); - -/* --- snmpUsmMIB ----------------------------------------------------- */ -static const struct snmp_node *const snmpusmmib_subnodes[] = { - &usmmibobjects_treenode.node -}; -static const struct snmp_tree_node snmpusmmib_root = SNMP_CREATE_TREE_NODE(15, snmpusmmib_subnodes); -static const u32_t snmpusmmib_base_oid[] = {1, 3, 6, 1, 6, 3, 15}; -const struct snmp_mib snmpusmmib = {snmpusmmib_base_oid, LWIP_ARRAYSIZE(snmpusmmib_base_oid), &snmpusmmib_root.node}; - -#endif /* LWIP_SNMP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_table.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_table.c deleted file mode 100644 index 4b77a4746..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_table.c +++ /dev/null @@ -1,342 +0,0 @@ -/** - * @file - * SNMP table support implementation. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_core.h" -#include "lwip/apps/snmp_table.h" -#include - -snmp_err_t snmp_table_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance) -{ - snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE; - const struct snmp_table_node *table_node = (const struct snmp_table_node *)(const void *)instance->node; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* check min. length (fixed row entry definition, column, row instance oid with at least one entry */ - /* fixed row entry always has oid 1 */ - if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) { - /* search column */ - const struct snmp_table_col_def *col_def = table_node->columns; - u16_t i = table_node->column_count; - while (i > 0) { - if (col_def->index == instance->instance_oid.id[1]) { - break; - } - - col_def++; - i--; - } - - if (i > 0) { - /* everything may be overwritten by get_cell_instance_method() in order to implement special handling for single columns/cells */ - instance->asn1_type = col_def->asn1_type; - instance->access = col_def->access; - instance->get_value = table_node->get_value; - instance->set_test = table_node->set_test; - instance->set_value = table_node->set_value; - - ret = table_node->get_cell_instance( - &(instance->instance_oid.id[1]), - &(instance->instance_oid.id[2]), - instance->instance_oid.len - 2, - instance); - } - } - - return ret; -} - -snmp_err_t snmp_table_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance) -{ - const struct snmp_table_node *table_node = (const struct snmp_table_node *)(const void *)instance->node; - const struct snmp_table_col_def *col_def; - struct snmp_obj_id row_oid; - u32_t column = 0; - snmp_err_t result; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* check that first part of id is 0 or 1, referencing fixed row entry */ - if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - if (instance->instance_oid.len > 1) { - column = instance->instance_oid.id[1]; - } - if (instance->instance_oid.len > 2) { - snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); - } else { - row_oid.len = 0; - } - - instance->get_value = table_node->get_value; - instance->set_test = table_node->set_test; - instance->set_value = table_node->set_value; - - /* resolve column and value */ - do { - u16_t i; - const struct snmp_table_col_def *next_col_def = NULL; - col_def = table_node->columns; - - for (i = 0; i < table_node->column_count; i++) { - if (col_def->index == column) { - next_col_def = col_def; - break; - } else if ((col_def->index > column) && ((next_col_def == NULL) || (col_def->index < next_col_def->index))) { - next_col_def = col_def; - } - col_def++; - } - - if (next_col_def == NULL) { - /* no further column found */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - instance->asn1_type = next_col_def->asn1_type; - instance->access = next_col_def->access; - - result = table_node->get_next_cell_instance( - &next_col_def->index, - &row_oid, - instance); - - if (result == SNMP_ERR_NOERROR) { - col_def = next_col_def; - break; - } - - row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ - column = next_col_def->index + 1; - } while (1); - - /* build resulting oid */ - instance->instance_oid.len = 2; - instance->instance_oid.id[0] = 1; - instance->instance_oid.id[1] = col_def->index; - snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); - - return SNMP_ERR_NOERROR; -} - - -snmp_err_t snmp_table_simple_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance) -{ - snmp_err_t ret = SNMP_ERR_NOSUCHINSTANCE; - const struct snmp_table_simple_node *table_node = (const struct snmp_table_simple_node *)(const void *)instance->node; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* check min. length (fixed row entry definition, column, row instance oid with at least one entry */ - /* fixed row entry always has oid 1 */ - if ((instance->instance_oid.len >= 3) && (instance->instance_oid.id[0] == 1)) { - ret = table_node->get_cell_value( - &(instance->instance_oid.id[1]), - &(instance->instance_oid.id[2]), - instance->instance_oid.len - 2, - &instance->reference, - &instance->reference_len); - - if (ret == SNMP_ERR_NOERROR) { - /* search column */ - const struct snmp_table_simple_col_def *col_def = table_node->columns; - u32_t i = table_node->column_count; - while (i > 0) { - if (col_def->index == instance->instance_oid.id[1]) { - break; - } - - col_def++; - i--; - } - - if (i > 0) { - instance->asn1_type = col_def->asn1_type; - instance->access = SNMP_NODE_INSTANCE_READ_ONLY; - instance->set_test = NULL; - instance->set_value = NULL; - - switch (col_def->data_type) { - case SNMP_VARIANT_VALUE_TYPE_U32: - instance->get_value = snmp_table_extract_value_from_u32ref; - break; - case SNMP_VARIANT_VALUE_TYPE_S32: - instance->get_value = snmp_table_extract_value_from_s32ref; - break; - case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */ - case SNMP_VARIANT_VALUE_TYPE_CONST_PTR: - instance->get_value = snmp_table_extract_value_from_refconstptr; - break; - default: - LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type)); - return SNMP_ERR_GENERROR; - } - - ret = SNMP_ERR_NOERROR; - } else { - ret = SNMP_ERR_NOSUCHINSTANCE; - } - } - } - - return ret; -} - -snmp_err_t snmp_table_simple_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance) -{ - const struct snmp_table_simple_node *table_node = (const struct snmp_table_simple_node *)(const void *)instance->node; - const struct snmp_table_simple_col_def *col_def; - struct snmp_obj_id row_oid; - u32_t column = 0; - snmp_err_t result; - - LWIP_UNUSED_ARG(root_oid); - LWIP_UNUSED_ARG(root_oid_len); - - /* check that first part of id is 0 or 1, referencing fixed row entry */ - if ((instance->instance_oid.len > 0) && (instance->instance_oid.id[0] > 1)) { - return SNMP_ERR_NOSUCHINSTANCE; - } - if (instance->instance_oid.len > 1) { - column = instance->instance_oid.id[1]; - } - if (instance->instance_oid.len > 2) { - snmp_oid_assign(&row_oid, &(instance->instance_oid.id[2]), instance->instance_oid.len - 2); - } else { - row_oid.len = 0; - } - - /* resolve column and value */ - do { - u32_t i; - const struct snmp_table_simple_col_def *next_col_def = NULL; - col_def = table_node->columns; - - for (i = 0; i < table_node->column_count; i++) { - if (col_def->index == column) { - next_col_def = col_def; - break; - } else if ((col_def->index > column) && ((next_col_def == NULL) || - (col_def->index < next_col_def->index))) { - next_col_def = col_def; - } - col_def++; - } - - if (next_col_def == NULL) { - /* no further column found */ - return SNMP_ERR_NOSUCHINSTANCE; - } - - result = table_node->get_next_cell_instance_and_value( - &next_col_def->index, - &row_oid, - &instance->reference, - &instance->reference_len); - - if (result == SNMP_ERR_NOERROR) { - col_def = next_col_def; - break; - } - - row_oid.len = 0; /* reset row_oid because we switch to next column and start with the first entry there */ - column = next_col_def->index + 1; - } while (1); - - instance->asn1_type = col_def->asn1_type; - instance->access = SNMP_NODE_INSTANCE_READ_ONLY; - instance->set_test = NULL; - instance->set_value = NULL; - - switch (col_def->data_type) { - case SNMP_VARIANT_VALUE_TYPE_U32: - instance->get_value = snmp_table_extract_value_from_u32ref; - break; - case SNMP_VARIANT_VALUE_TYPE_S32: - instance->get_value = snmp_table_extract_value_from_s32ref; - break; - case SNMP_VARIANT_VALUE_TYPE_PTR: /* fall through */ - case SNMP_VARIANT_VALUE_TYPE_CONST_PTR: - instance->get_value = snmp_table_extract_value_from_refconstptr; - break; - default: - LWIP_DEBUGF(SNMP_DEBUG, ("snmp_table_simple_get_instance(): unknown column data_type: %d\n", col_def->data_type)); - return SNMP_ERR_GENERROR; - } - - /* build resulting oid */ - instance->instance_oid.len = 2; - instance->instance_oid.id[0] = 1; - instance->instance_oid.id[1] = col_def->index; - snmp_oid_append(&instance->instance_oid, row_oid.id, row_oid.len); - - return SNMP_ERR_NOERROR; -} - - -s16_t -snmp_table_extract_value_from_s32ref(struct snmp_node_instance *instance, void *value) -{ - s32_t *dst = (s32_t *)value; - *dst = instance->reference.s32; - return sizeof(*dst); -} - -s16_t -snmp_table_extract_value_from_u32ref(struct snmp_node_instance *instance, void *value) -{ - u32_t *dst = (u32_t *)value; - *dst = instance->reference.u32; - return sizeof(*dst); -} - -s16_t -snmp_table_extract_value_from_refconstptr(struct snmp_node_instance *instance, void *value) -{ - MEMCPY(value, instance->reference.const_ptr, instance->reference_len); - return (u16_t)instance->reference_len; -} - -#endif /* LWIP_SNMP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_threadsync.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_threadsync.c deleted file mode 100644 index 56d98862c..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_threadsync.c +++ /dev/null @@ -1,231 +0,0 @@ -/** - * @file - * SNMP thread synchronization implementation. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Dirk Ziegelmeier - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP && (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */ - -#include "lwip/apps/snmp_threadsync.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/sys.h" -#include - -static void -call_synced_function(struct threadsync_data *call_data, snmp_threadsync_called_fn fn) -{ - sys_mutex_lock(&call_data->threadsync_node->instance->sem_usage_mutex); - call_data->threadsync_node->instance->sync_fn(fn, call_data); - sys_sem_wait(&call_data->threadsync_node->instance->sem); - sys_mutex_unlock(&call_data->threadsync_node->instance->sem_usage_mutex); -} - -static void -threadsync_get_value_synced(void *ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data *)ctx; - - if (call_data->proxy_instance.get_value != NULL) { - call_data->retval.s16 = call_data->proxy_instance.get_value(&call_data->proxy_instance, call_data->arg1.value); - } else { - call_data->retval.s16 = -1; - } - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static s16_t -threadsync_get_value(struct snmp_node_instance *instance, void *value) -{ - struct threadsync_data *call_data = (struct threadsync_data *)instance->reference.ptr; - - call_data->arg1.value = value; - call_synced_function(call_data, threadsync_get_value_synced); - - return call_data->retval.s16; -} - -static void -threadsync_set_test_synced(void *ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data *)ctx; - - if (call_data->proxy_instance.set_test != NULL) { - call_data->retval.err = call_data->proxy_instance.set_test(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); - } else { - call_data->retval.err = SNMP_ERR_NOTWRITABLE; - } - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static snmp_err_t -threadsync_set_test(struct snmp_node_instance *instance, u16_t len, void *value) -{ - struct threadsync_data *call_data = (struct threadsync_data *)instance->reference.ptr; - - call_data->arg1.value = value; - call_data->arg2.len = len; - call_synced_function(call_data, threadsync_set_test_synced); - - return call_data->retval.err; -} - -static void -threadsync_set_value_synced(void *ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data *)ctx; - - if (call_data->proxy_instance.set_value != NULL) { - call_data->retval.err = call_data->proxy_instance.set_value(&call_data->proxy_instance, call_data->arg2.len, call_data->arg1.value); - } else { - call_data->retval.err = SNMP_ERR_NOTWRITABLE; - } - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static snmp_err_t -threadsync_set_value(struct snmp_node_instance *instance, u16_t len, void *value) -{ - struct threadsync_data *call_data = (struct threadsync_data *)instance->reference.ptr; - - call_data->arg1.value = value; - call_data->arg2.len = len; - call_synced_function(call_data, threadsync_set_value_synced); - - return call_data->retval.err; -} - -static void -threadsync_release_instance_synced(void *ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data *)ctx; - - call_data->proxy_instance.release_instance(&call_data->proxy_instance); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static void -threadsync_release_instance(struct snmp_node_instance *instance) -{ - struct threadsync_data *call_data = (struct threadsync_data *)instance->reference.ptr; - - if (call_data->proxy_instance.release_instance != NULL) { - call_synced_function(call_data, threadsync_release_instance_synced); - } -} - -static void -get_instance_synced(void *ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data *)ctx; - const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node *)(const void *)call_data->proxy_instance.node; - - call_data->retval.err = leaf->get_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static void -get_next_instance_synced(void *ctx) -{ - struct threadsync_data *call_data = (struct threadsync_data *)ctx; - const struct snmp_leaf_node *leaf = (const struct snmp_leaf_node *)(const void *)call_data->proxy_instance.node; - - call_data->retval.err = leaf->get_next_instance(call_data->arg1.root_oid, call_data->arg2.root_oid_len, &call_data->proxy_instance); - - sys_sem_signal(&call_data->threadsync_node->instance->sem); -} - -static snmp_err_t -do_sync(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance, snmp_threadsync_called_fn fn) -{ - const struct snmp_threadsync_node *threadsync_node = (const struct snmp_threadsync_node *)(const void *)instance->node; - struct threadsync_data *call_data = &threadsync_node->instance->data; - - if (threadsync_node->node.node.oid != threadsync_node->target->node.oid) { - LWIP_DEBUGF(SNMP_DEBUG, ("Sync node OID does not match target node OID")); - return SNMP_ERR_NOSUCHINSTANCE; - } - - memset(&call_data->proxy_instance, 0, sizeof(call_data->proxy_instance)); - - instance->reference.ptr = call_data; - snmp_oid_assign(&call_data->proxy_instance.instance_oid, instance->instance_oid.id, instance->instance_oid.len); - - call_data->proxy_instance.node = &threadsync_node->target->node; - call_data->threadsync_node = threadsync_node; - - call_data->arg1.root_oid = root_oid; - call_data->arg2.root_oid_len = root_oid_len; - call_synced_function(call_data, fn); - - if (call_data->retval.err == SNMP_ERR_NOERROR) { - instance->access = call_data->proxy_instance.access; - instance->asn1_type = call_data->proxy_instance.asn1_type; - instance->release_instance = threadsync_release_instance; - instance->get_value = (call_data->proxy_instance.get_value != NULL) ? threadsync_get_value : NULL; - instance->set_value = (call_data->proxy_instance.set_value != NULL) ? threadsync_set_value : NULL; - instance->set_test = (call_data->proxy_instance.set_test != NULL) ? threadsync_set_test : NULL; - snmp_oid_assign(&instance->instance_oid, call_data->proxy_instance.instance_oid.id, call_data->proxy_instance.instance_oid.len); - } - - return call_data->retval.err; -} - -snmp_err_t -snmp_threadsync_get_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance) -{ - return do_sync(root_oid, root_oid_len, instance, get_instance_synced); -} - -snmp_err_t -snmp_threadsync_get_next_instance(const u32_t *root_oid, u8_t root_oid_len, struct snmp_node_instance *instance) -{ - return do_sync(root_oid, root_oid_len, instance, get_next_instance_synced); -} - -/** Initializes thread synchronization instance */ -void snmp_threadsync_init(struct snmp_threadsync_instance *instance, snmp_threadsync_synchronizer_fn sync_fn) -{ - err_t err = sys_mutex_new(&instance->sem_usage_mutex); - LWIP_ASSERT("Failed to set up mutex", err == ERR_OK); - err = sys_sem_new(&instance->sem, 0); - LWIP_UNUSED_ARG(err); /* in case of LWIP_NOASSERT */ - LWIP_ASSERT("Failed to set up semaphore", err == ERR_OK); - instance->sync_fn = sync_fn; -} - -#endif /* LWIP_SNMP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_traps.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_traps.c deleted file mode 100644 index 3c9c81767..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmp_traps.c +++ /dev/null @@ -1,458 +0,0 @@ -/** - * @file - * SNMPv1 traps implementation. - */ - -/* - * Copyright (c) 2001-2004 Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Martin Hentschel - * Christiaan Simons - * - */ - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ - -#include - -#include "lwip/snmp.h" -#include "lwip/sys.h" -#include "lwip/apps/snmp.h" -#include "lwip/apps/snmp_core.h" -#include "lwip/prot/iana.h" -#include "snmp_msg.h" -#include "snmp_asn1.h" -#include "snmp_core_priv.h" - -struct snmp_msg_trap { - /* source enterprise ID (sysObjectID) */ - const struct snmp_obj_id *enterprise; - /* source IP address, raw network order format */ - ip_addr_t sip; - /* generic trap code */ - u32_t gen_trap; - /* specific trap code */ - u32_t spc_trap; - /* timestamp */ - u32_t ts; - /* snmp_version */ - u32_t snmp_version; - - /* output trap lengths used in ASN encoding */ - /* encoding pdu length */ - u16_t pdulen; - /* encoding community length */ - u16_t comlen; - /* encoding sequence length */ - u16_t seqlen; - /* encoding varbinds sequence length */ - u16_t vbseqlen; -}; - -static u16_t snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds); -static u16_t snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len); -static err_t snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream); -static err_t snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds); - -#define BUILD_EXEC(code) \ - if ((code) != ERR_OK) { \ - LWIP_DEBUGF(SNMP_DEBUG, ("SNMP error during creation of outbound trap frame!")); \ - return ERR_ARG; \ - } - -/** Agent community string for sending traps */ -extern const char *snmp_community_trap; - -void *snmp_traps_handle; - -struct snmp_trap_dst { - /* destination IP address in network order */ - ip_addr_t dip; - /* set to 0 when disabled, >0 when enabled */ - u8_t enable; -}; -static struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; - -static u8_t snmp_auth_traps_enabled = 0; - -/** - * @ingroup snmp_traps - * Sets enable switch for this trap destination. - * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 - * @param enable switch if 0 destination is disabled >0 enabled. - */ -void -snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) -{ - LWIP_ASSERT_CORE_LOCKED(); - if (dst_idx < SNMP_TRAP_DESTINATIONS) { - trap_dst[dst_idx].enable = enable; - } -} - -/** - * @ingroup snmp_traps - * Sets IPv4 address for this trap destination. - * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 - * @param dst IPv4 address in host order. - */ -void -snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst) -{ - LWIP_ASSERT_CORE_LOCKED(); - if (dst_idx < SNMP_TRAP_DESTINATIONS) { - ip_addr_set(&trap_dst[dst_idx].dip, dst); - } -} - -/** - * @ingroup snmp_traps - * Enable/disable authentication traps - */ -void -snmp_set_auth_traps_enabled(u8_t enable) -{ - snmp_auth_traps_enabled = enable; -} - -/** - * @ingroup snmp_traps - * Get authentication traps enabled state - */ -u8_t -snmp_get_auth_traps_enabled(void) -{ - return snmp_auth_traps_enabled; -} - - -/** - * @ingroup snmp_traps - * Sends a generic or enterprise specific trap message. - * - * @param eoid points to enterprise object identifier - * @param generic_trap is the trap code - * @param specific_trap used for enterprise traps when generic_trap == 6 - * @param varbinds linked list of varbinds to be sent - * @return ERR_OK when success, ERR_MEM if we're out of memory - * - * @note the use of the enterprise identifier field - * is per RFC1215. - * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps - * and .iso.org.dod.internet.private.enterprises.yourenterprise - * (sysObjectID) for specific traps. - */ -err_t -snmp_send_trap(const struct snmp_obj_id *eoid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds) -{ - struct snmp_msg_trap trap_msg; - struct snmp_trap_dst *td; - struct pbuf *p; - u16_t i, tot_len; - err_t err = ERR_OK; - - LWIP_ASSERT_CORE_LOCKED(); - - trap_msg.snmp_version = 0; - - for (i = 0, td = &trap_dst[0]; i < SNMP_TRAP_DESTINATIONS; i++, td++) { - if ((td->enable != 0) && !ip_addr_isany(&td->dip)) { - /* lookup current source address for this dst */ - if (snmp_get_local_ip_for_dst(snmp_traps_handle, &td->dip, &trap_msg.sip)) { - if (eoid == NULL) { - trap_msg.enterprise = snmp_get_device_enterprise_oid(); - } else { - trap_msg.enterprise = eoid; - } - - trap_msg.gen_trap = generic_trap; - if (generic_trap == SNMP_GENTRAP_ENTERPRISE_SPECIFIC) { - trap_msg.spc_trap = specific_trap; - } else { - trap_msg.spc_trap = 0; - } - - MIB2_COPY_SYSUPTIME_TO(&trap_msg.ts); - - /* pass 0, calculate length fields */ - tot_len = snmp_trap_varbind_sum(&trap_msg, varbinds); - tot_len = snmp_trap_header_sum(&trap_msg, tot_len); - - /* allocate pbuf(s) */ - p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_RAM); - if (p != NULL) { - struct snmp_pbuf_stream pbuf_stream; - snmp_pbuf_stream_init(&pbuf_stream, p, 0, tot_len); - - /* pass 1, encode packet into the pbuf(s) */ - snmp_trap_header_enc(&trap_msg, &pbuf_stream); - snmp_trap_varbind_enc(&trap_msg, &pbuf_stream, varbinds); - - snmp_stats.outtraps++; - snmp_stats.outpkts++; - - /** send to the TRAP destination */ - snmp_sendto(snmp_traps_handle, p, &td->dip, LWIP_IANA_PORT_SNMP_TRAP); - pbuf_free(p); - } else { - err = ERR_MEM; - } - } else { - /* routing error */ - err = ERR_RTE; - } - } - } - return err; -} - -/** - * @ingroup snmp_traps - * Send generic SNMP trap - */ -err_t -snmp_send_trap_generic(s32_t generic_trap) -{ - static const struct snmp_obj_id oid = { 7, { 1, 3, 6, 1, 2, 1, 11 } }; - return snmp_send_trap(&oid, generic_trap, 0, NULL); -} - -/** - * @ingroup snmp_traps - * Send specific SNMP trap with variable bindings - */ -err_t -snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds) -{ - return snmp_send_trap(NULL, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, specific_trap, varbinds); -} - -/** - * @ingroup snmp_traps - * Send coldstart trap - */ -void -snmp_coldstart_trap(void) -{ - snmp_send_trap_generic(SNMP_GENTRAP_COLDSTART); -} - -/** - * @ingroup snmp_traps - * Send authentication failure trap (used internally by agent) - */ -void -snmp_authfail_trap(void) -{ - if (snmp_auth_traps_enabled != 0) { - snmp_send_trap_generic(SNMP_GENTRAP_AUTH_FAILURE); - } -} - -static u16_t -snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds) -{ - struct snmp_varbind *varbind; - u16_t tot_len; - u8_t tot_len_len; - - tot_len = 0; - varbind = varbinds; - while (varbind != NULL) { - struct snmp_varbind_len len; - - if (snmp_varbind_length(varbind, &len) == ERR_OK) { - tot_len += 1 + len.vb_len_len + len.vb_value_len; - } - - varbind = varbind->next; - } - - trap->vbseqlen = tot_len; - snmp_asn1_enc_length_cnt(trap->vbseqlen, &tot_len_len); - tot_len += 1 + tot_len_len; - - return tot_len; -} - -/** - * Sums trap header field lengths from tail to head and - * returns trap_header_lengths for second encoding pass. - * - * @param trap Trap message - * @param vb_len varbind-list length - * @return the required length for encoding the trap header - */ -static u16_t -snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len) -{ - u16_t tot_len; - u16_t len; - u8_t lenlen; - - tot_len = vb_len; - - snmp_asn1_enc_u32t_cnt(trap->ts, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - snmp_asn1_enc_s32t_cnt(trap->spc_trap, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - snmp_asn1_enc_s32t_cnt(trap->gen_trap, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - if (IP_IS_V6_VAL(trap->sip)) { -#if LWIP_IPV6 - len = sizeof(ip_2_ip6(&trap->sip)->addr); -#endif - } else { -#if LWIP_IPV4 - len = sizeof(ip_2_ip4(&trap->sip)->addr); -#endif - } - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - trap->pdulen = tot_len; - snmp_asn1_enc_length_cnt(trap->pdulen, &lenlen); - tot_len += 1 + lenlen; - - trap->comlen = (u16_t)LWIP_MIN(strlen(snmp_community_trap), 0xFFFF); - snmp_asn1_enc_length_cnt(trap->comlen, &lenlen); - tot_len += 1 + lenlen + trap->comlen; - - snmp_asn1_enc_s32t_cnt(trap->snmp_version, &len); - snmp_asn1_enc_length_cnt(len, &lenlen); - tot_len += 1 + len + lenlen; - - trap->seqlen = tot_len; - snmp_asn1_enc_length_cnt(trap->seqlen, &lenlen); - tot_len += 1 + lenlen; - - return tot_len; -} - -static err_t -snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds) -{ - struct snmp_asn1_tlv tlv; - struct snmp_varbind *varbind; - - varbind = varbinds; - - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->vbseqlen); - BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - - while (varbind != NULL) { - BUILD_EXEC( snmp_append_outbound_varbind(pbuf_stream, varbind) ); - - varbind = varbind->next; - } - - return ERR_OK; -} - -/** - * Encodes trap header from head to tail. - */ -static err_t -snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream) -{ - struct snmp_asn1_tlv tlv; - - /* 'Message' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->seqlen); - BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - - /* version */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(trap->snmp_version, &tlv.value_len); - BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->snmp_version) ); - - /* community */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, trap->comlen); - BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)snmp_community_trap, trap->comlen) ); - - /* 'PDU' sequence */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP), 0, trap->pdulen); - BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - - /* object ID */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, 0, 0); - snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &tlv.value_len); - BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - BUILD_EXEC( snmp_asn1_enc_oid(pbuf_stream, trap->enterprise->id, trap->enterprise->len) ); - - /* IP addr */ - if (IP_IS_V6_VAL(trap->sip)) { -#if LWIP_IPV6 - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip6(&trap->sip)->addr)); - BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip6(&trap->sip)->addr, sizeof(ip_2_ip6(&trap->sip)->addr)) ); -#endif - } else { -#if LWIP_IPV4 - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip4(&trap->sip)->addr)); - BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip4(&trap->sip)->addr, sizeof(ip_2_ip4(&trap->sip)->addr)) ); -#endif - } - - /* trap length */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(trap->gen_trap, &tlv.value_len); - BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->gen_trap) ); - - /* specific trap */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); - snmp_asn1_enc_s32t_cnt(trap->spc_trap, &tlv.value_len); - BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->spc_trap) ); - - /* timestamp */ - SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_TIMETICKS, 0, 0); - snmp_asn1_enc_s32t_cnt(trap->ts, &tlv.value_len); - BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); - BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->ts) ); - - return ERR_OK; -} - -#endif /* LWIP_SNMP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmpv3.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmpv3.c deleted file mode 100644 index ed5a076c2..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmpv3.c +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @file - * Additional SNMPv3 functionality RFC3414 and RFC3826. - */ - -/* - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Elias Oenal - */ - -#include "snmpv3_priv.h" -#include "lwip/apps/snmpv3.h" -#include "lwip/sys.h" -#include - -#if LWIP_SNMP && LWIP_SNMP_V3 - -#ifdef LWIP_SNMPV3_INCLUDE_ENGINE -#include LWIP_SNMPV3_INCLUDE_ENGINE -#endif - -#define SNMP_MAX_TIME_BOOT 2147483647UL - -/** Call this if engine has been changed. Has to reset boots, see below */ -void -snmpv3_engine_id_changed(void) -{ - snmpv3_set_engine_boots(0); -} - -/** According to RFC3414 2.2.2. - * - * The number of times that the SNMP engine has - * (re-)initialized itself since snmpEngineID - * was last configured. - */ -s32_t -snmpv3_get_engine_boots_internal(void) -{ - if (snmpv3_get_engine_boots() == 0 || - snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT) { - return snmpv3_get_engine_boots(); - } - - snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT); - return snmpv3_get_engine_boots(); -} - -/** RFC3414 2.2.2. - * - * Once the timer reaches 2147483647 it gets reset to zero and the - * engine boot ups get incremented. - */ -s32_t -snmpv3_get_engine_time_internal(void) -{ - if (snmpv3_get_engine_time() >= SNMP_MAX_TIME_BOOT) { - snmpv3_reset_engine_time(); - - if (snmpv3_get_engine_boots() < SNMP_MAX_TIME_BOOT - 1) { - snmpv3_set_engine_boots(snmpv3_get_engine_boots() + 1); - } else { - snmpv3_set_engine_boots(SNMP_MAX_TIME_BOOT); - } - } - - return snmpv3_get_engine_time(); -} - -#if LWIP_SNMP_V3_CRYPTO - -/* This function ignores the byte order suggestion in RFC3414 - * since it simply doesn't influence the effectiveness of an IV. - * - * Implementing RFC3826 priv param algorithm if LWIP_RAND is available. - * - * @todo: This is a potential thread safety issue. - */ -err_t -snmpv3_build_priv_param(u8_t *priv_param) -{ -#ifdef LWIP_RAND /* Based on RFC3826 */ - static u8_t init; - static u32_t priv1, priv2; - - /* Lazy initialisation */ - if (init == 0) { - init = 1; - priv1 = LWIP_RAND(); - priv2 = LWIP_RAND(); - } - - SMEMCPY(&priv_param[0], &priv1, sizeof(priv1)); - SMEMCPY(&priv_param[4], &priv2, sizeof(priv2)); - - /* Emulate 64bit increment */ - priv1++; - if (!priv1) { /* Overflow */ - priv2++; - } -#else /* Based on RFC3414 */ - static u32_t ctr; - u32_t boots = snmpv3_get_engine_boots_internal(); - SMEMCPY(&priv_param[0], &boots, 4); - SMEMCPY(&priv_param[4], &ctr, 4); - ctr++; -#endif - return ERR_OK; -} -#endif /* LWIP_SNMP_V3_CRYPTO */ - -#endif diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmpv3_mbedtls.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmpv3_mbedtls.c deleted file mode 100644 index 48c1a81fe..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmpv3_mbedtls.c +++ /dev/null @@ -1,342 +0,0 @@ -/** - * @file - * SNMPv3 crypto/auth functions implemented for ARM mbedtls. - */ - -/* - * Copyright (c) 2016 Elias Oenal and Dirk Ziegelmeier. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Elias Oenal - * Dirk Ziegelmeier - */ - -#include "lwip/apps/snmpv3.h" -#include "snmpv3_priv.h" -#include "lwip/arch.h" -#include "snmp_msg.h" -#include "lwip/sys.h" -#include - -#if LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS - -#include "mbedtls/md.h" -#include "mbedtls/cipher.h" - -#include "mbedtls/md5.h" -#include "mbedtls/sha1.h" - -err_t -snmpv3_auth(struct snmp_pbuf_stream *stream, u16_t length, - const u8_t *key, snmpv3_auth_algo_t algo, u8_t *hmac_out) -{ - u32_t i; - u8_t key_len; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t ctx; - struct snmp_pbuf_stream read_stream; - snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length); - - if (algo == SNMP_V3_AUTH_ALGO_MD5) { - md_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5); - key_len = SNMP_V3_MD5_LEN; - } else if (algo == SNMP_V3_AUTH_ALGO_SHA) { - md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); - key_len = SNMP_V3_SHA_LEN; - } else { - return ERR_ARG; - } - - mbedtls_md_init(&ctx); - if (mbedtls_md_setup(&ctx, md_info, 1) != 0) { - return ERR_ARG; - } - - if (mbedtls_md_hmac_starts(&ctx, key, key_len) != 0) { - goto free_md; - } - - for (i = 0; i < length; i++) { - u8_t byte; - - if (snmp_pbuf_stream_read(&read_stream, &byte)) { - goto free_md; - } - - if (mbedtls_md_hmac_update(&ctx, &byte, 1) != 0) { - goto free_md; - } - } - - if (mbedtls_md_hmac_finish(&ctx, hmac_out) != 0) { - goto free_md; - } - - mbedtls_md_free(&ctx); - return ERR_OK; - -free_md: - mbedtls_md_free(&ctx); - return ERR_ARG; -} - -#if LWIP_SNMP_V3_CRYPTO - -err_t -snmpv3_crypt(struct snmp_pbuf_stream *stream, u16_t length, - const u8_t *key, const u8_t *priv_param, const u32_t engine_boots, - const u32_t engine_time, snmpv3_priv_algo_t algo, snmpv3_priv_mode_t mode) -{ - size_t i; - mbedtls_cipher_context_t ctx; - const mbedtls_cipher_info_t *cipher_info; - - struct snmp_pbuf_stream read_stream; - struct snmp_pbuf_stream write_stream; - snmp_pbuf_stream_init(&read_stream, stream->pbuf, stream->offset, stream->length); - snmp_pbuf_stream_init(&write_stream, stream->pbuf, stream->offset, stream->length); - mbedtls_cipher_init(&ctx); - - if (algo == SNMP_V3_PRIV_ALGO_DES) { - u8_t iv_local[8]; - u8_t out_bytes[8]; - size_t out_len; - - /* RFC 3414 mandates padding for DES */ - if ((length & 0x07) != 0) { - return ERR_ARG; - } - - cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_DES_CBC); - if (mbedtls_cipher_setup(&ctx, cipher_info) != 0) { - return ERR_ARG; - } - if (mbedtls_cipher_set_padding_mode(&ctx, MBEDTLS_PADDING_NONE) != 0) { - return ERR_ARG; - } - if (mbedtls_cipher_setkey(&ctx, key, 8 * 8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) { - goto error; - } - - /* Prepare IV */ - for (i = 0; i < LWIP_ARRAYSIZE(iv_local); i++) { - iv_local[i] = priv_param[i] ^ key[i + 8]; - } - if (mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) { - goto error; - } - - for (i = 0; i < length; i += 8) { - size_t j; - u8_t in_bytes[8]; - out_len = LWIP_ARRAYSIZE(out_bytes) ; - - for (j = 0; j < LWIP_ARRAYSIZE(in_bytes); j++) { - if (snmp_pbuf_stream_read(&read_stream, &in_bytes[j]) != ERR_OK) { - goto error; - } - } - - if (mbedtls_cipher_update(&ctx, in_bytes, LWIP_ARRAYSIZE(in_bytes), out_bytes, &out_len) != 0) { - goto error; - } - - if (snmp_pbuf_stream_writebuf(&write_stream, out_bytes, (u16_t)out_len) != ERR_OK) { - goto error; - } - } - - out_len = LWIP_ARRAYSIZE(out_bytes); - if (mbedtls_cipher_finish(&ctx, out_bytes, &out_len) != 0) { - goto error; - } - - if (snmp_pbuf_stream_writebuf(&write_stream, out_bytes, (u16_t)out_len) != ERR_OK) { - goto error; - } - } else if (algo == SNMP_V3_PRIV_ALGO_AES) { - u8_t iv_local[16]; - - cipher_info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_CFB128); - if (mbedtls_cipher_setup(&ctx, cipher_info) != 0) { - return ERR_ARG; - } - if (mbedtls_cipher_setkey(&ctx, key, 16 * 8, (mode == SNMP_V3_PRIV_MODE_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT) != 0) { - goto error; - } - - /* - * IV is the big endian concatenation of boots, - * uptime and priv param - see RFC3826. - */ - iv_local[0 + 0] = (engine_boots >> 24) & 0xFF; - iv_local[0 + 1] = (engine_boots >> 16) & 0xFF; - iv_local[0 + 2] = (engine_boots >> 8) & 0xFF; - iv_local[0 + 3] = (engine_boots >> 0) & 0xFF; - iv_local[4 + 0] = (engine_time >> 24) & 0xFF; - iv_local[4 + 1] = (engine_time >> 16) & 0xFF; - iv_local[4 + 2] = (engine_time >> 8) & 0xFF; - iv_local[4 + 3] = (engine_time >> 0) & 0xFF; - SMEMCPY(iv_local + 8, priv_param, 8); - if (mbedtls_cipher_set_iv(&ctx, iv_local, LWIP_ARRAYSIZE(iv_local)) != 0) { - goto error; - } - - for (i = 0; i < length; i++) { - u8_t in_byte; - u8_t out_byte; - size_t out_len = sizeof(out_byte); - - if (snmp_pbuf_stream_read(&read_stream, &in_byte) != ERR_OK) { - goto error; - } - if (mbedtls_cipher_update(&ctx, &in_byte, sizeof(in_byte), &out_byte, &out_len) != 0) { - goto error; - } - if (snmp_pbuf_stream_write(&write_stream, out_byte) != ERR_OK) { - goto error; - } - } - } else { - return ERR_ARG; - } - - mbedtls_cipher_free(&ctx); - return ERR_OK; - -error: - mbedtls_cipher_free(&ctx); - return ERR_OK; -} - -#endif /* LWIP_SNMP_V3_CRYPTO */ - -/* A.2.1. Password to Key Sample Code for MD5 */ -void -snmpv3_password_to_key_md5( - const u8_t *password, /* IN */ - size_t passwordlen, /* IN */ - const u8_t *engineID, /* IN - pointer to snmpEngineID */ - u8_t engineLength,/* IN - length of snmpEngineID */ - u8_t *key) /* OUT - pointer to caller 16-octet buffer */ -{ - mbedtls_md5_context MD; - u8_t *cp, password_buf[64]; - u32_t password_index = 0; - u8_t i; - u32_t count = 0; - - mbedtls_md5_init(&MD); /* initialize MD5 */ - mbedtls_md5_starts(&MD); - - /**********************************************/ - /* Use while loop until we've done 1 Megabyte */ - /**********************************************/ - while (count < 1048576) { - cp = password_buf; - for (i = 0; i < 64; i++) { - /*************************************************/ - /* Take the next octet of the password, wrapping */ - /* to the beginning of the password as necessary.*/ - /*************************************************/ - *cp++ = password[password_index++ % passwordlen]; - } - mbedtls_md5_update(&MD, password_buf, 64); - count += 64; - } - mbedtls_md5_finish(&MD, key); /* tell MD5 we're done */ - - /*****************************************************/ - /* Now localize the key with the engineID and pass */ - /* through MD5 to produce final key */ - /* May want to ensure that engineLength <= 32, */ - /* otherwise need to use a buffer larger than 64 */ - /*****************************************************/ - SMEMCPY(password_buf, key, 16); - MEMCPY(password_buf + 16, engineID, engineLength); - SMEMCPY(password_buf + 16 + engineLength, key, 16); - - mbedtls_md5_starts(&MD); - mbedtls_md5_update(&MD, password_buf, 32 + engineLength); - mbedtls_md5_finish(&MD, key); - - mbedtls_md5_free(&MD); - return; -} - -/* A.2.2. Password to Key Sample Code for SHA */ -void -snmpv3_password_to_key_sha( - const u8_t *password, /* IN */ - size_t passwordlen, /* IN */ - const u8_t *engineID, /* IN - pointer to snmpEngineID */ - u8_t engineLength,/* IN - length of snmpEngineID */ - u8_t *key) /* OUT - pointer to caller 20-octet buffer */ -{ - mbedtls_sha1_context SH; - u8_t *cp, password_buf[72]; - u32_t password_index = 0; - u8_t i; - u32_t count = 0; - - mbedtls_sha1_init(&SH); /* initialize SHA */ - mbedtls_sha1_starts(&SH); - - /**********************************************/ - /* Use while loop until we've done 1 Megabyte */ - /**********************************************/ - while (count < 1048576) { - cp = password_buf; - for (i = 0; i < 64; i++) { - /*************************************************/ - /* Take the next octet of the password, wrapping */ - /* to the beginning of the password as necessary.*/ - /*************************************************/ - *cp++ = password[password_index++ % passwordlen]; - } - mbedtls_sha1_update(&SH, password_buf, 64); - count += 64; - } - mbedtls_sha1_finish(&SH, key); /* tell SHA we're done */ - - /*****************************************************/ - /* Now localize the key with the engineID and pass */ - /* through SHA to produce final key */ - /* May want to ensure that engineLength <= 32, */ - /* otherwise need to use a buffer larger than 72 */ - /*****************************************************/ - SMEMCPY(password_buf, key, 20); - MEMCPY(password_buf + 20, engineID, engineLength); - SMEMCPY(password_buf + 20 + engineLength, key, 20); - - mbedtls_sha1_starts(&SH); - mbedtls_sha1_update(&SH, password_buf, 40 + engineLength); - mbedtls_sha1_finish(&SH, key); - - mbedtls_sha1_free(&SH); - return; -} - -#endif /* LWIP_SNMP && LWIP_SNMP_V3 && LWIP_SNMP_V3_MBEDTLS */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmpv3_priv.h b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmpv3_priv.h deleted file mode 100644 index 323364c30..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/snmp/snmpv3_priv.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @file - * Additional SNMPv3 functionality RFC3414 and RFC3826 (internal API, do not use in client code). - */ - -/* - * Copyright (c) 2016 Elias Oenal. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * Author: Elias Oenal - */ - -#ifndef LWIP_HDR_APPS_SNMP_V3_PRIV_H -#define LWIP_HDR_APPS_SNMP_V3_PRIV_H - -#include "lwip/apps/snmp_opts.h" - -#if LWIP_SNMP && LWIP_SNMP_V3 - -#include "lwip/apps/snmpv3.h" -#include "snmp_pbuf_stream.h" - -/* According to RFC 3411 */ -#define SNMP_V3_MAX_ENGINE_ID_LENGTH 32 -#define SNMP_V3_MAX_USER_LENGTH 32 - -#define SNMP_V3_MAX_AUTH_PARAM_LENGTH 12 -#define SNMP_V3_MAX_PRIV_PARAM_LENGTH 8 - -#define SNMP_V3_MD5_LEN 16 -#define SNMP_V3_SHA_LEN 20 - -typedef enum { - SNMP_V3_PRIV_MODE_DECRYPT = 0, - SNMP_V3_PRIV_MODE_ENCRYPT = 1 -} snmpv3_priv_mode_t; - -s32_t snmpv3_get_engine_boots_internal(void); -err_t snmpv3_auth(struct snmp_pbuf_stream *stream, u16_t length, const u8_t *key, snmpv3_auth_algo_t algo, u8_t *hmac_out); -err_t snmpv3_crypt(struct snmp_pbuf_stream *stream, u16_t length, const u8_t *key, - const u8_t *priv_param, const u32_t engine_boots, const u32_t engine_time, snmpv3_priv_algo_t algo, snmpv3_priv_mode_t mode); -err_t snmpv3_build_priv_param(u8_t *priv_param); -void snmpv3_enginetime_timer(void *arg); - -#endif - -#endif /* LWIP_HDR_APPS_SNMP_V3_PRIV_H */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/sntp/sntp.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/sntp/sntp.c deleted file mode 100644 index b7ff56adc..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/sntp/sntp.c +++ /dev/null @@ -1,869 +0,0 @@ -/** - * @file - * SNTP client module - */ - -/* - * Copyright (c) 2007-2009 Frédéric Bernon, Simon Goldschmidt - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT - * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * This file is part of the lwIP TCP/IP stack. - * - * Author: Frédéric Bernon, Simon Goldschmidt - */ - - -/** - * @defgroup sntp SNTP - * @ingroup apps - * - * This is simple "SNTP" client for the lwIP raw API. - * It is a minimal implementation of SNTPv4 as specified in RFC 4330. - * - * For a list of some public NTP servers, see this link: - * http://support.ntp.org/bin/view/Servers/NTPPoolServers - * - * @todo: - * - complete SNTP_CHECK_RESPONSE checks 3 and 4 - */ - -#include "lwip/apps/sntp.h" - -#include "lwip/opt.h" -#include "lwip/timeouts.h" -#include "lwip/udp.h" -#include "lwip/dns.h" -#include "lwip/ip_addr.h" -#include "lwip/pbuf.h" -#include "lwip/dhcp.h" - -#include -#include - -#if LWIP_UDP - -/* Handle support for more than one server via SNTP_MAX_SERVERS */ -#if SNTP_MAX_SERVERS > 1 -#define SNTP_SUPPORT_MULTIPLE_SERVERS 1 -#else /* NTP_MAX_SERVERS > 1 */ -#define SNTP_SUPPORT_MULTIPLE_SERVERS 0 -#endif /* NTP_MAX_SERVERS > 1 */ - -#ifndef SNTP_SUPPRESS_DELAY_CHECK -#if SNTP_UPDATE_DELAY < 15000 -#error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds (define SNTP_SUPPRESS_DELAY_CHECK to disable this error)!" -#endif -#endif - -/* the various debug levels for this file */ -#define SNTP_DEBUG_TRACE (SNTP_DEBUG | LWIP_DBG_TRACE) -#define SNTP_DEBUG_STATE (SNTP_DEBUG | LWIP_DBG_STATE) -#define SNTP_DEBUG_WARN (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING) -#define SNTP_DEBUG_WARN_STATE (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE) -#define SNTP_DEBUG_SERIOUS (SNTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS) - -#define SNTP_ERR_KOD 1 - -/* SNTP protocol defines */ -#define SNTP_MSG_LEN 48 - -#define SNTP_OFFSET_LI_VN_MODE 0 -#define SNTP_LI_MASK 0xC0 -#define SNTP_LI_NO_WARNING (0x00 << 6) -#define SNTP_LI_LAST_MINUTE_61_SEC (0x01 << 6) -#define SNTP_LI_LAST_MINUTE_59_SEC (0x02 << 6) -#define SNTP_LI_ALARM_CONDITION (0x03 << 6) /* (clock not synchronized) */ - -#define SNTP_VERSION_MASK 0x38 -#define SNTP_VERSION (4/* NTP Version 4*/<<3) - -#define SNTP_MODE_MASK 0x07 -#define SNTP_MODE_CLIENT 0x03 -#define SNTP_MODE_SERVER 0x04 -#define SNTP_MODE_BROADCAST 0x05 - -#define SNTP_OFFSET_STRATUM 1 -#define SNTP_STRATUM_KOD 0x00 - -#define SNTP_OFFSET_ORIGINATE_TIME 24 -#define SNTP_OFFSET_RECEIVE_TIME 32 -#define SNTP_OFFSET_TRANSMIT_TIME 40 - -/* Number of seconds between 1970 and Feb 7, 2036 06:28:16 UTC (epoch 1) */ -#define DIFF_SEC_1970_2036 ((u32_t)2085978496L) - -/** Convert NTP timestamp fraction to microseconds. - */ -#ifndef SNTP_FRAC_TO_US -# if LWIP_HAVE_INT64 -# define SNTP_FRAC_TO_US(f) ((u32_t)(((u64_t)(f) * 1000000UL) >> 32)) -# else -# define SNTP_FRAC_TO_US(f) ((u32_t)(f) / 4295) -# endif -#endif /* !SNTP_FRAC_TO_US */ - -/* Configure behaviour depending on native, microsecond or second precision. - * Treat NTP timestamps as signed two's-complement integers. This way, - * timestamps that have the MSB set simply become negative offsets from - * the epoch (Feb 7, 2036 06:28:16 UTC). Representable dates range from - * 1968 to 2104. - */ -#ifndef SNTP_SET_SYSTEM_TIME_NTP -# ifdef SNTP_SET_SYSTEM_TIME_US -# define SNTP_SET_SYSTEM_TIME_NTP(s, f) \ - SNTP_SET_SYSTEM_TIME_US((u32_t)((s) + DIFF_SEC_1970_2036), SNTP_FRAC_TO_US(f)) -# else -# define SNTP_SET_SYSTEM_TIME_NTP(s, f) \ - SNTP_SET_SYSTEM_TIME((u32_t)((s) + DIFF_SEC_1970_2036)) -# endif -#endif /* !SNTP_SET_SYSTEM_TIME_NTP */ - -/* Get the system time either natively as NTP timestamp or convert from - * Unix time in seconds and microseconds. Take care to avoid overflow if the - * microsecond value is at the maximum of 999999. Also add 0.5 us fudge to - * avoid special values like 0, and to mask round-off errors that would - * otherwise break round-trip conversion identity. - */ -#ifndef SNTP_GET_SYSTEM_TIME_NTP -# define SNTP_GET_SYSTEM_TIME_NTP(s, f) do { \ - u32_t sec_, usec_; \ - SNTP_GET_SYSTEM_TIME(sec_, usec_); \ - (s) = (s32_t)(sec_ - DIFF_SEC_1970_2036); \ - (f) = usec_ * 4295 - ((usec_ * 2143) >> 16) + 2147; \ - } while (0) -#endif /* !SNTP_GET_SYSTEM_TIME_NTP */ - -/* Start offset of the timestamps to extract from the SNTP packet */ -#define SNTP_OFFSET_TIMESTAMPS \ - (SNTP_OFFSET_TRANSMIT_TIME + 8 - sizeof(struct sntp_timestamps)) - -/* Round-trip delay arithmetic helpers */ -#if SNTP_COMP_ROUNDTRIP -# if !LWIP_HAVE_INT64 -# error "SNTP round-trip delay compensation requires 64-bit arithmetic" -# endif -# define SNTP_SEC_FRAC_TO_S64(s, f) \ - ((s64_t)(((u64_t)(s) << 32) | (u32_t)(f))) -# define SNTP_TIMESTAMP_TO_S64(t) \ - SNTP_SEC_FRAC_TO_S64(lwip_ntohl((t).sec), lwip_ntohl((t).frac)) -#endif /* SNTP_COMP_ROUNDTRIP */ - -/** - * 64-bit NTP timestamp, in network byte order. - */ -struct sntp_time { - u32_t sec; - u32_t frac; -}; - -/** - * Timestamps to be extracted from the NTP header. - */ -struct sntp_timestamps { -#if SNTP_COMP_ROUNDTRIP || SNTP_CHECK_RESPONSE >= 2 - struct sntp_time orig; - struct sntp_time recv; -#endif - struct sntp_time xmit; -}; - -/** - * SNTP packet format (without optional fields) - * Timestamps are coded as 64 bits: - * - signed 32 bits seconds since Feb 07, 2036, 06:28:16 UTC (epoch 1) - * - unsigned 32 bits seconds fraction (2^32 = 1 second) - */ -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/bpstruct.h" -#endif -PACK_STRUCT_BEGIN -struct sntp_msg { - PACK_STRUCT_FLD_8(u8_t li_vn_mode); - PACK_STRUCT_FLD_8(u8_t stratum); - PACK_STRUCT_FLD_8(u8_t poll); - PACK_STRUCT_FLD_8(u8_t precision); - PACK_STRUCT_FIELD(u32_t root_delay); - PACK_STRUCT_FIELD(u32_t root_dispersion); - PACK_STRUCT_FIELD(u32_t reference_identifier); - PACK_STRUCT_FIELD(u32_t reference_timestamp[2]); - PACK_STRUCT_FIELD(u32_t originate_timestamp[2]); - PACK_STRUCT_FIELD(u32_t receive_timestamp[2]); - PACK_STRUCT_FIELD(u32_t transmit_timestamp[2]); -} PACK_STRUCT_STRUCT; -PACK_STRUCT_END -#ifdef PACK_STRUCT_USE_INCLUDES -# include "arch/epstruct.h" -#endif - -/* function prototypes */ -static void sntp_request(void *arg); - -/** The operating mode */ -static u8_t sntp_opmode; - -/** The UDP pcb used by the SNTP client */ -static struct udp_pcb *sntp_pcb; -/** Names/Addresses of servers */ -struct sntp_server { -#if SNTP_SERVER_DNS - const char *name; -#endif /* SNTP_SERVER_DNS */ - ip_addr_t addr; -#if SNTP_MONITOR_SERVER_REACHABILITY - /** Reachability shift register as described in RFC 5905 */ - u8_t reachability; -#endif /* SNTP_MONITOR_SERVER_REACHABILITY */ -}; -static struct sntp_server sntp_servers[SNTP_MAX_SERVERS]; - -#if SNTP_GET_SERVERS_FROM_DHCP -static u8_t sntp_set_servers_from_dhcp; -#endif /* SNTP_GET_SERVERS_FROM_DHCP */ -#if SNTP_SUPPORT_MULTIPLE_SERVERS -/** The currently used server (initialized to 0) */ -static u8_t sntp_current_server; -#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ -#define sntp_current_server 0 -#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ - -#if SNTP_RETRY_TIMEOUT_EXP -#define SNTP_RESET_RETRY_TIMEOUT() sntp_retry_timeout = SNTP_RETRY_TIMEOUT -/** Retry time, initialized with SNTP_RETRY_TIMEOUT and doubled with each retry. */ -static u32_t sntp_retry_timeout; -#else /* SNTP_RETRY_TIMEOUT_EXP */ -#define SNTP_RESET_RETRY_TIMEOUT() -#define sntp_retry_timeout SNTP_RETRY_TIMEOUT -#endif /* SNTP_RETRY_TIMEOUT_EXP */ - -#if SNTP_CHECK_RESPONSE >= 1 -/** Saves the last server address to compare with response */ -static ip_addr_t sntp_last_server_address; -#endif /* SNTP_CHECK_RESPONSE >= 1 */ - -#if SNTP_CHECK_RESPONSE >= 2 -/** Saves the last timestamp sent (which is sent back by the server) - * to compare against in response. Stored in network byte order. */ -static struct sntp_time sntp_last_timestamp_sent; -#endif /* SNTP_CHECK_RESPONSE >= 2 */ - -#if defined(LWIP_DEBUG) && !defined(sntp_format_time) -/* Debug print helper. */ -static const char * -sntp_format_time(s32_t sec) -{ - time_t ut; - ut = (u32_t)((u32_t)sec + DIFF_SEC_1970_2036); - return ctime(&ut); -} -#endif /* LWIP_DEBUG && !sntp_format_time */ - -/** - * SNTP processing of received timestamp - */ -static void -sntp_process(const struct sntp_timestamps *timestamps) -{ - s32_t sec; - u32_t frac; - - sec = (s32_t)lwip_ntohl(timestamps->xmit.sec); - frac = lwip_ntohl(timestamps->xmit.frac); - -#if SNTP_COMP_ROUNDTRIP -# if SNTP_CHECK_RESPONSE >= 2 - if (timestamps->recv.sec != 0 || timestamps->recv.frac != 0) -# endif - { - s32_t dest_sec; - u32_t dest_frac; - u32_t step_sec; - - /* Get the destination time stamp, i.e. the current system time */ - SNTP_GET_SYSTEM_TIME_NTP(dest_sec, dest_frac); - - step_sec = (dest_sec < sec) ? ((u32_t)sec - (u32_t)dest_sec) - : ((u32_t)dest_sec - (u32_t)sec); - /* In order to avoid overflows, skip the compensation if the clock step - * is larger than about 34 years. */ - if ((step_sec >> 30) == 0) { - s64_t t1, t2, t3, t4; - - t4 = SNTP_SEC_FRAC_TO_S64(dest_sec, dest_frac); - t3 = SNTP_SEC_FRAC_TO_S64(sec, frac); - t1 = SNTP_TIMESTAMP_TO_S64(timestamps->orig); - t2 = SNTP_TIMESTAMP_TO_S64(timestamps->recv); - /* Clock offset calculation according to RFC 4330 */ - t4 += ((t2 - t1) + (t3 - t4)) / 2; - - sec = (s32_t)((u64_t)t4 >> 32); - frac = (u32_t)((u64_t)t4); - } - } -#endif /* SNTP_COMP_ROUNDTRIP */ - - SNTP_SET_SYSTEM_TIME_NTP(sec, frac); - LWIP_UNUSED_ARG(frac); /* might be unused if only seconds are set */ - LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %" U32_F " us\n", - sntp_format_time(sec), SNTP_FRAC_TO_US(frac))); -} - -/** - * Initialize request struct to be sent to server. - */ -static void -sntp_initialize_request(struct sntp_msg *req) -{ - memset(req, 0, SNTP_MSG_LEN); - req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT; - -#if SNTP_CHECK_RESPONSE >= 2 || SNTP_COMP_ROUNDTRIP - { - s32_t secs; - u32_t sec, frac; - /* Get the transmit timestamp */ - SNTP_GET_SYSTEM_TIME_NTP(secs, frac); - sec = lwip_htonl((u32_t)secs); - frac = lwip_htonl(frac); - -# if SNTP_CHECK_RESPONSE >= 2 - sntp_last_timestamp_sent.sec = sec; - sntp_last_timestamp_sent.frac = frac; -# endif - req->transmit_timestamp[0] = sec; - req->transmit_timestamp[1] = frac; - } -#endif /* SNTP_CHECK_RESPONSE >= 2 || SNTP_COMP_ROUNDTRIP */ -} - -/** - * Retry: send a new request (and increase retry timeout). - * - * @param arg is unused (only necessary to conform to sys_timeout) - */ -static void -sntp_retry(void *arg) -{ - LWIP_UNUSED_ARG(arg); - - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_retry: Next request will be sent in %"U32_F" ms\n", - sntp_retry_timeout)); - - /* set up a timer to send a retry and increase the retry delay */ - sys_timeout(sntp_retry_timeout, sntp_request, NULL); - -#if SNTP_RETRY_TIMEOUT_EXP - { - u32_t new_retry_timeout; - /* increase the timeout for next retry */ - new_retry_timeout = sntp_retry_timeout << 1; - /* limit to maximum timeout and prevent overflow */ - if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) && - (new_retry_timeout > sntp_retry_timeout)) { - sntp_retry_timeout = new_retry_timeout; - } - } -#endif /* SNTP_RETRY_TIMEOUT_EXP */ -} - -#if SNTP_SUPPORT_MULTIPLE_SERVERS -/** - * If Kiss-of-Death is received (or another packet parsing error), - * try the next server or retry the current server and increase the retry - * timeout if only one server is available. - * (implicitly, SNTP_MAX_SERVERS > 1) - * - * @param arg is unused (only necessary to conform to sys_timeout) - */ -static void -sntp_try_next_server(void *arg) -{ - u8_t old_server, i; - LWIP_UNUSED_ARG(arg); - - old_server = sntp_current_server; - for (i = 0; i < SNTP_MAX_SERVERS - 1; i++) { - sntp_current_server++; - if (sntp_current_server >= SNTP_MAX_SERVERS) { - sntp_current_server = 0; - } - if (!ip_addr_isany(&sntp_servers[sntp_current_server].addr) -#if SNTP_SERVER_DNS - || (sntp_servers[sntp_current_server].name != NULL) -#endif - ) { - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_try_next_server: Sending request to server %"U16_F"\n", - (u16_t)sntp_current_server)); - /* new server: reset retry timeout */ - SNTP_RESET_RETRY_TIMEOUT(); - /* instantly send a request to the next server */ - sntp_request(NULL); - return; - } - } - /* no other valid server found */ - sntp_current_server = old_server; - sntp_retry(NULL); -} -#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */ -/* Always retry on error if only one server is supported */ -#define sntp_try_next_server sntp_retry -#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */ - -/** UDP recv callback for the sntp pcb */ -static void -sntp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - struct sntp_timestamps timestamps; - u8_t mode; - u8_t stratum; - err_t err; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(pcb); - - err = ERR_ARG; -#if SNTP_CHECK_RESPONSE >= 1 - /* check server address and port */ - if (((sntp_opmode != SNTP_OPMODE_POLL) || ip_addr_cmp(addr, &sntp_last_server_address)) && - (port == SNTP_PORT)) -#else /* SNTP_CHECK_RESPONSE >= 1 */ - LWIP_UNUSED_ARG(addr); - LWIP_UNUSED_ARG(port); -#endif /* SNTP_CHECK_RESPONSE >= 1 */ - { - /* process the response */ - if (p->tot_len == SNTP_MSG_LEN) { - mode = pbuf_get_at(p, SNTP_OFFSET_LI_VN_MODE) & SNTP_MODE_MASK; - /* if this is a SNTP response... */ - if (((sntp_opmode == SNTP_OPMODE_POLL) && (mode == SNTP_MODE_SERVER)) || - ((sntp_opmode == SNTP_OPMODE_LISTENONLY) && (mode == SNTP_MODE_BROADCAST))) { - stratum = pbuf_get_at(p, SNTP_OFFSET_STRATUM); - - if (stratum == SNTP_STRATUM_KOD) { - /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ - err = SNTP_ERR_KOD; - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n")); - } else { - pbuf_copy_partial(p, ×tamps, sizeof(timestamps), SNTP_OFFSET_TIMESTAMPS); -#if SNTP_CHECK_RESPONSE >= 2 - /* check originate_timetamp against sntp_last_timestamp_sent */ - if (timestamps.orig.sec != sntp_last_timestamp_sent.sec || - timestamps.orig.frac != sntp_last_timestamp_sent.frac) { - LWIP_DEBUGF(SNTP_DEBUG_WARN, - ("sntp_recv: Invalid originate timestamp in response\n")); - } else -#endif /* SNTP_CHECK_RESPONSE >= 2 */ - /* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */ - { - /* correct answer */ - err = ERR_OK; - } - } - } else { - LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode)); - /* wait for correct response */ - err = ERR_TIMEOUT; - } - } else { - LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len)); - } - } -#if SNTP_CHECK_RESPONSE >= 1 - else { - /* packet from wrong remote address or port, wait for correct response */ - err = ERR_TIMEOUT; - } -#endif /* SNTP_CHECK_RESPONSE >= 1 */ - - pbuf_free(p); - - if (err == ERR_OK) { - /* correct packet received: process it it */ - sntp_process(×tamps); - -#if SNTP_MONITOR_SERVER_REACHABILITY - /* indicate that server responded */ - sntp_servers[sntp_current_server].reachability |= 1; -#endif /* SNTP_MONITOR_SERVER_REACHABILITY */ - /* Set up timeout for next request (only if poll response was received)*/ - if (sntp_opmode == SNTP_OPMODE_POLL) { - u32_t sntp_update_delay; - sys_untimeout(sntp_try_next_server, NULL); - sys_untimeout(sntp_request, NULL); - - /* Correct response, reset retry timeout */ - SNTP_RESET_RETRY_TIMEOUT(); - - sntp_update_delay = (u32_t)SNTP_UPDATE_DELAY; - sys_timeout(sntp_update_delay, sntp_request, NULL); - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n", - sntp_update_delay)); - } - } else if (err == SNTP_ERR_KOD) { - /* KOD errors are only processed in case of an explicit poll response */ - if (sntp_opmode == SNTP_OPMODE_POLL) { - /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */ - sntp_try_next_server(NULL); - } - } else { - /* ignore any broken packet, poll mode: retry after timeout to avoid flooding */ - } -} - -/** Actually send an sntp request to a server. - * - * @param server_addr resolved IP address of the SNTP server - */ -static void -sntp_send_request(const ip_addr_t *server_addr) -{ - struct pbuf *p; - - LWIP_ASSERT("server_addr != NULL", server_addr != NULL); - - p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM); - if (p != NULL) { - struct sntp_msg *sntpmsg = (struct sntp_msg *)p->payload; - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_send_request: Sending request to server\n")); - /* initialize request message */ - sntp_initialize_request(sntpmsg); - /* send request */ - udp_sendto(sntp_pcb, p, server_addr, SNTP_PORT); - /* free the pbuf after sending it */ - pbuf_free(p); -#if SNTP_MONITOR_SERVER_REACHABILITY - /* indicate new packet has been sent */ - sntp_servers[sntp_current_server].reachability <<= 1; -#endif /* SNTP_MONITOR_SERVER_REACHABILITY */ - /* set up receive timeout: try next server or retry on timeout */ - sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL); -#if SNTP_CHECK_RESPONSE >= 1 - /* save server address to verify it in sntp_recv */ - ip_addr_copy(sntp_last_server_address, *server_addr); -#endif /* SNTP_CHECK_RESPONSE >= 1 */ - } else { - LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n", - (u32_t)SNTP_RETRY_TIMEOUT)); - /* out of memory: set up a timer to send a retry */ - sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL); - } -} - -#if SNTP_SERVER_DNS -/** - * DNS found callback when using DNS names as server address. - */ -static void -sntp_dns_found(const char *hostname, const ip_addr_t *ipaddr, void *arg) -{ - LWIP_UNUSED_ARG(hostname); - LWIP_UNUSED_ARG(arg); - - if (ipaddr != NULL) { - /* Address resolved, send request */ - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_dns_found: Server address resolved, sending request\n")); - sntp_servers[sntp_current_server].addr = *ipaddr; - sntp_send_request(ipaddr); - } else { - /* DNS resolving failed -> try another server */ - LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_dns_found: Failed to resolve server address resolved, trying next server\n")); - sntp_try_next_server(NULL); - } -} -#endif /* SNTP_SERVER_DNS */ - -/** - * Send out an sntp request. - * - * @param arg is unused (only necessary to conform to sys_timeout) - */ -static void -sntp_request(void *arg) -{ - ip_addr_t sntp_server_address; - err_t err; - - LWIP_UNUSED_ARG(arg); - - /* initialize SNTP server address */ -#if SNTP_SERVER_DNS - if (sntp_servers[sntp_current_server].name) { - /* always resolve the name and rely on dns-internal caching & timeout */ - ip_addr_set_zero(&sntp_servers[sntp_current_server].addr); - err = dns_gethostbyname(sntp_servers[sntp_current_server].name, &sntp_server_address, - sntp_dns_found, NULL); - if (err == ERR_INPROGRESS) { - /* DNS request sent, wait for sntp_dns_found being called */ - LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_request: Waiting for server address to be resolved.\n")); - return; - } else if (err == ERR_OK) { - sntp_servers[sntp_current_server].addr = sntp_server_address; - } - } else -#endif /* SNTP_SERVER_DNS */ - { - sntp_server_address = sntp_servers[sntp_current_server].addr; - err = (ip_addr_isany_val(sntp_server_address)) ? ERR_ARG : ERR_OK; - } - - if (err == ERR_OK) { - LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_request: current server address is %s\n", - ipaddr_ntoa(&sntp_server_address))); - sntp_send_request(&sntp_server_address); - } else { - /* address conversion failed, try another server */ - LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n")); - sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL); - } -} - -/** - * @ingroup sntp - * Initialize this module. - * Send out request instantly or after SNTP_STARTUP_DELAY(_FUNC). - */ -void -sntp_init(void) -{ - /* LWIP_ASSERT_CORE_LOCKED(); is checked by udp_new() */ - -#ifdef SNTP_SERVER_ADDRESS -#if SNTP_SERVER_DNS - sntp_setservername(0, SNTP_SERVER_ADDRESS); -#else -#error SNTP_SERVER_ADDRESS string not supported SNTP_SERVER_DNS==0 -#endif -#endif /* SNTP_SERVER_ADDRESS */ - - if (sntp_pcb == NULL) { - sntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL); - if (sntp_pcb != NULL) { - udp_recv(sntp_pcb, sntp_recv, NULL); - - if (sntp_opmode == SNTP_OPMODE_POLL) { - SNTP_RESET_RETRY_TIMEOUT(); -#if SNTP_STARTUP_DELAY - sys_timeout((u32_t)SNTP_STARTUP_DELAY_FUNC, sntp_request, NULL); -#else - sntp_request(NULL); -#endif - } else if (sntp_opmode == SNTP_OPMODE_LISTENONLY) { - ip_set_option(sntp_pcb, SOF_BROADCAST); - udp_bind(sntp_pcb, IP_ANY_TYPE, SNTP_PORT); - } - } - } -} - -/** - * @ingroup sntp - * Stop this module. - */ -void -sntp_stop(void) -{ - LWIP_ASSERT_CORE_LOCKED(); - if (sntp_pcb != NULL) { -#if SNTP_MONITOR_SERVER_REACHABILITY - u8_t i; - for (i = 0; i < SNTP_MAX_SERVERS; i++) { - sntp_servers[i].reachability = 0; - } -#endif /* SNTP_MONITOR_SERVER_REACHABILITY */ - sys_untimeout(sntp_request, NULL); - sys_untimeout(sntp_try_next_server, NULL); - udp_remove(sntp_pcb); - sntp_pcb = NULL; - } -} - -/** - * @ingroup sntp - * Get enabled state. - */ -u8_t sntp_enabled(void) -{ - return (sntp_pcb != NULL) ? 1 : 0; -} - -/** - * @ingroup sntp - * Sets the operating mode. - * @param operating_mode one of the available operating modes - */ -void -sntp_setoperatingmode(u8_t operating_mode) -{ - LWIP_ASSERT_CORE_LOCKED(); - LWIP_ASSERT("Invalid operating mode", operating_mode <= SNTP_OPMODE_LISTENONLY); - LWIP_ASSERT("Operating mode must not be set while SNTP client is running", sntp_pcb == NULL); - sntp_opmode = operating_mode; -} - -/** - * @ingroup sntp - * Gets the operating mode. - */ -u8_t -sntp_getoperatingmode(void) -{ - return sntp_opmode; -} - -#if SNTP_MONITOR_SERVER_REACHABILITY -/** - * @ingroup sntp - * Gets the server reachability shift register as described in RFC 5905. - * - * @param idx the index of the NTP server - */ -u8_t -sntp_getreachability(u8_t idx) -{ - if (idx < SNTP_MAX_SERVERS) { - return sntp_servers[idx].reachability; - } - return 0; -} -#endif /* SNTP_MONITOR_SERVER_REACHABILITY */ - -#if SNTP_GET_SERVERS_FROM_DHCP -/** - * Config SNTP server handling by IP address, name, or DHCP; clear table - * @param set_servers_from_dhcp enable or disable getting server addresses from dhcp - */ -void -sntp_servermode_dhcp(int set_servers_from_dhcp) -{ - u8_t new_mode = set_servers_from_dhcp ? 1 : 0; - LWIP_ASSERT_CORE_LOCKED(); - if (sntp_set_servers_from_dhcp != new_mode) { - sntp_set_servers_from_dhcp = new_mode; - } -} -#endif /* SNTP_GET_SERVERS_FROM_DHCP */ - -/** - * @ingroup sntp - * Initialize one of the NTP servers by IP address - * - * @param idx the index of the NTP server to set must be < SNTP_MAX_SERVERS - * @param server IP address of the NTP server to set - */ -void -sntp_setserver(u8_t idx, const ip_addr_t *server) -{ - LWIP_ASSERT_CORE_LOCKED(); - if (idx < SNTP_MAX_SERVERS) { - if (server != NULL) { - sntp_servers[idx].addr = (*server); - } else { - ip_addr_set_zero(&sntp_servers[idx].addr); - } -#if SNTP_SERVER_DNS - sntp_servers[idx].name = NULL; -#endif - } -} - -#if LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP -/** - * Initialize one of the NTP servers by IP address, required by DHCP - * - * @param num the index of the NTP server to set must be < SNTP_MAX_SERVERS - * @param server IP address of the NTP server to set - */ -void -dhcp_set_ntp_servers(u8_t num, const ip4_addr_t *server) -{ - LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp: %s %u.%u.%u.%u as NTP server #%u via DHCP\n", - (sntp_set_servers_from_dhcp ? "Got" : "Rejected"), - ip4_addr1(server), ip4_addr2(server), ip4_addr3(server), ip4_addr4(server), num)); - if (sntp_set_servers_from_dhcp && num) { - u8_t i; - for (i = 0; (i < num) && (i < SNTP_MAX_SERVERS); i++) { - ip_addr_t addr; - ip_addr_copy_from_ip4(addr, server[i]); - sntp_setserver(i, &addr); - } - for (i = num; i < SNTP_MAX_SERVERS; i++) { - sntp_setserver(i, NULL); - } - } -} -#endif /* LWIP_DHCP && SNTP_GET_SERVERS_FROM_DHCP */ - -/** - * @ingroup sntp - * Obtain one of the currently configured by IP address (or DHCP) NTP servers - * - * @param idx the index of the NTP server - * @return IP address of the indexed NTP server or "ip_addr_any" if the NTP - * server has not been configured by address (or at all). - */ -const ip_addr_t * -sntp_getserver(u8_t idx) -{ - if (idx < SNTP_MAX_SERVERS) { - return &sntp_servers[idx].addr; - } - return IP_ADDR_ANY; -} - -#if SNTP_SERVER_DNS -/** - * Initialize one of the NTP servers by name - * - * @param idx the index of the NTP server to set must be < SNTP_MAX_SERVERS - * @param server DNS name of the NTP server to set, to be resolved at contact time - */ -void -sntp_setservername(u8_t idx, const char *server) -{ - LWIP_ASSERT_CORE_LOCKED(); - if (idx < SNTP_MAX_SERVERS) { - sntp_servers[idx].name = server; - } -} - -/** - * Obtain one of the currently configured by name NTP servers. - * - * @param idx the index of the NTP server - * @return IP address of the indexed NTP server or NULL if the NTP - * server has not been configured by name (or at all) - */ -const char * -sntp_getservername(u8_t idx) -{ - if (idx < SNTP_MAX_SERVERS) { - return sntp_servers[idx].name; - } - return NULL; -} -#endif /* SNTP_SERVER_DNS */ - -#endif /* LWIP_UDP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/tftp/tftp_server.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/tftp/tftp_server.c deleted file mode 100644 index e3f15124a..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/apps/tftp/tftp_server.c +++ /dev/null @@ -1,435 +0,0 @@ -/** - * - * @file tftp_server.c - * - * @author Logan Gunthorpe - * Dirk Ziegelmeier - * - * @brief Trivial File Transfer Protocol (RFC 1350) - * - * Copyright (c) Deltatee Enterprises Ltd. 2013 - * All rights reserved. - * - */ - -/* - * Redistribution and use in source and binary forms, with or without - * modification,are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Author: Logan Gunthorpe - * Dirk Ziegelmeier - * - */ - -/** - * @defgroup tftp TFTP server - * @ingroup apps - * - * This is simple TFTP server for the lwIP raw API. - */ - -#include "lwip/apps/tftp_server.h" - -#if LWIP_UDP - -#include "lwip/udp.h" -#include "lwip/timeouts.h" -#include "lwip/debug.h" - -#define TFTP_MAX_PAYLOAD_SIZE 512 -#define TFTP_HEADER_LENGTH 4 - -#define TFTP_RRQ 1 -#define TFTP_WRQ 2 -#define TFTP_DATA 3 -#define TFTP_ACK 4 -#define TFTP_ERROR 5 - -enum tftp_error { - TFTP_ERROR_FILE_NOT_FOUND = 1, - TFTP_ERROR_ACCESS_VIOLATION = 2, - TFTP_ERROR_DISK_FULL = 3, - TFTP_ERROR_ILLEGAL_OPERATION = 4, - TFTP_ERROR_UNKNOWN_TRFR_ID = 5, - TFTP_ERROR_FILE_EXISTS = 6, - TFTP_ERROR_NO_SUCH_USER = 7 -}; - -#include - -struct tftp_state { - const struct tftp_context *ctx; - void *handle; - struct pbuf *last_data; - struct udp_pcb *upcb; - ip_addr_t addr; - u16_t port; - int timer; - int last_pkt; - u16_t blknum; - u8_t retries; - u8_t mode_write; -}; - -static struct tftp_state tftp_state; - -static void tftp_tmr(void *arg); - -static void -close_handle(void) -{ - tftp_state.port = 0; - ip_addr_set_any(0, &tftp_state.addr); - - if (tftp_state.last_data != NULL) { - pbuf_free(tftp_state.last_data); - tftp_state.last_data = NULL; - } - - sys_untimeout(tftp_tmr, NULL); - - if (tftp_state.handle) { - tftp_state.ctx->close(tftp_state.handle); - tftp_state.handle = NULL; - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: closing\n")); - } -} - -static void -send_error(const ip_addr_t *addr, u16_t port, enum tftp_error code, const char *str) -{ - int str_length = strlen(str); - struct pbuf *p; - u16_t *payload; - - p = pbuf_alloc(PBUF_TRANSPORT, (u16_t)(TFTP_HEADER_LENGTH + str_length + 1), PBUF_RAM); - if (p == NULL) { - return; - } - - payload = (u16_t *) p->payload; - payload[0] = PP_HTONS(TFTP_ERROR); - payload[1] = lwip_htons(code); - MEMCPY(&payload[2], str, str_length + 1); - - udp_sendto(tftp_state.upcb, p, addr, port); - pbuf_free(p); -} - -static void -send_ack(u16_t blknum) -{ - struct pbuf *p; - u16_t *payload; - - p = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH, PBUF_RAM); - if (p == NULL) { - return; - } - payload = (u16_t *) p->payload; - - payload[0] = PP_HTONS(TFTP_ACK); - payload[1] = lwip_htons(blknum); - udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); - pbuf_free(p); -} - -static void -resend_data(void) -{ - struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, tftp_state.last_data->len, PBUF_RAM); - if (p == NULL) { - return; - } - - if (pbuf_copy(p, tftp_state.last_data) != ERR_OK) { - pbuf_free(p); - return; - } - - udp_sendto(tftp_state.upcb, p, &tftp_state.addr, tftp_state.port); - pbuf_free(p); -} - -static void -send_data(void) -{ - u16_t *payload; - int ret; - - if (tftp_state.last_data != NULL) { - pbuf_free(tftp_state.last_data); - } - - tftp_state.last_data = pbuf_alloc(PBUF_TRANSPORT, TFTP_HEADER_LENGTH + TFTP_MAX_PAYLOAD_SIZE, PBUF_RAM); - if (tftp_state.last_data == NULL) { - return; - } - - payload = (u16_t *) tftp_state.last_data->payload; - payload[0] = PP_HTONS(TFTP_DATA); - payload[1] = lwip_htons(tftp_state.blknum); - - ret = tftp_state.ctx->read(tftp_state.handle, &payload[2], TFTP_MAX_PAYLOAD_SIZE); - if (ret < 0) { - send_error(&tftp_state.addr, tftp_state.port, TFTP_ERROR_ACCESS_VIOLATION, "Error occured while reading the file."); - close_handle(); - return; - } - - pbuf_realloc(tftp_state.last_data, (u16_t)(TFTP_HEADER_LENGTH + ret)); - resend_data(); -} - -static void -recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -{ - u16_t *sbuf = (u16_t *) p->payload; - int opcode; - - LWIP_UNUSED_ARG(arg); - LWIP_UNUSED_ARG(upcb); - - if (((tftp_state.port != 0) && (port != tftp_state.port)) || - (!ip_addr_isany_val(tftp_state.addr) && !ip_addr_cmp(&tftp_state.addr, addr))) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); - pbuf_free(p); - return; - } - - opcode = sbuf[0]; - - tftp_state.last_pkt = tftp_state.timer; - tftp_state.retries = 0; - - switch (opcode) { - case PP_HTONS(TFTP_RRQ): /* fall through */ - case PP_HTONS(TFTP_WRQ): { - const char tftp_null = 0; - char filename[TFTP_MAX_FILENAME_LEN + 1]; - char mode[TFTP_MAX_MODE_LEN + 1]; - u16_t filename_end_offset; - u16_t mode_end_offset; - - if (tftp_state.handle != NULL) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Only one connection at a time is supported"); - break; - } - - sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); - - /* find \0 in pbuf -> end of filename string */ - filename_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), 2); - if ((u16_t)(filename_end_offset - 1) > sizeof(filename)) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Filename too long/not NULL terminated"); - break; - } - pbuf_copy_partial(p, filename, filename_end_offset - 1, 2); - - /* find \0 in pbuf -> end of mode string */ - mode_end_offset = pbuf_memfind(p, &tftp_null, sizeof(tftp_null), filename_end_offset + 1); - if ((u16_t)(mode_end_offset - filename_end_offset) > sizeof(mode)) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Mode too long/not NULL terminated"); - break; - } - pbuf_copy_partial(p, mode, mode_end_offset - filename_end_offset, filename_end_offset + 1); - - tftp_state.handle = tftp_state.ctx->open(filename, mode, opcode == PP_HTONS(TFTP_WRQ)); - tftp_state.blknum = 1; - - if (!tftp_state.handle) { - send_error(addr, port, TFTP_ERROR_FILE_NOT_FOUND, "Unable to open requested file."); - break; - } - - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: %s request from ", (opcode == PP_HTONS(TFTP_WRQ)) ? "write" : "read")); - ip_addr_debug_print(TFTP_DEBUG | LWIP_DBG_STATE, addr); - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, (" for '%s' mode '%s'\n", filename, mode)); - - ip_addr_copy(tftp_state.addr, *addr); - tftp_state.port = port; - - if (opcode == PP_HTONS(TFTP_WRQ)) { - tftp_state.mode_write = 1; - send_ack(0); - } else { - tftp_state.mode_write = 0; - send_data(); - } - - break; - } - - case PP_HTONS(TFTP_DATA): { - int ret; - u16_t blknum; - - if (tftp_state.handle == NULL) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); - break; - } - - if (tftp_state.mode_write != 1) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a write connection"); - break; - } - - blknum = lwip_ntohs(sbuf[1]); - if (blknum == tftp_state.blknum) { - pbuf_remove_header(p, TFTP_HEADER_LENGTH); - - ret = tftp_state.ctx->write(tftp_state.handle, p); - if (ret < 0) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "error writing file"); - close_handle(); - } else { - send_ack(blknum); - } - - if (p->tot_len < TFTP_MAX_PAYLOAD_SIZE) { - close_handle(); - } else { - tftp_state.blknum++; - } - } else if ((u16_t)(blknum + 1) == tftp_state.blknum) { - /* retransmit of previous block, ack again (casting to u16_t to care for overflow) */ - send_ack(blknum); - } else { - send_error(addr, port, TFTP_ERROR_UNKNOWN_TRFR_ID, "Wrong block number"); - } - break; - } - - case PP_HTONS(TFTP_ACK): { - u16_t blknum; - int lastpkt; - - if (tftp_state.handle == NULL) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "No connection"); - break; - } - - if (tftp_state.mode_write != 0) { - send_error(addr, port, TFTP_ERROR_ACCESS_VIOLATION, "Not a read connection"); - break; - } - - blknum = lwip_ntohs(sbuf[1]); - if (blknum != tftp_state.blknum) { - send_error(addr, port, TFTP_ERROR_UNKNOWN_TRFR_ID, "Wrong block number"); - break; - } - - lastpkt = 0; - - if (tftp_state.last_data != NULL) { - lastpkt = tftp_state.last_data->tot_len != (TFTP_MAX_PAYLOAD_SIZE + TFTP_HEADER_LENGTH); - } - - if (!lastpkt) { - tftp_state.blknum++; - send_data(); - } else { - close_handle(); - } - - break; - } - - default: - send_error(addr, port, TFTP_ERROR_ILLEGAL_OPERATION, "Unknown operation"); - break; - } - - pbuf_free(p); -} - -static void -tftp_tmr(void *arg) -{ - LWIP_UNUSED_ARG(arg); - - tftp_state.timer++; - - if (tftp_state.handle == NULL) { - return; - } - - sys_timeout(TFTP_TIMER_MSECS, tftp_tmr, NULL); - - if ((tftp_state.timer - tftp_state.last_pkt) > (TFTP_TIMEOUT_MSECS / TFTP_TIMER_MSECS)) { - if ((tftp_state.last_data != NULL) && (tftp_state.retries < TFTP_MAX_RETRIES)) { - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout, retrying\n")); - resend_data(); - tftp_state.retries++; - } else { - LWIP_DEBUGF(TFTP_DEBUG | LWIP_DBG_STATE, ("tftp: timeout\n")); - close_handle(); - } - } -} - -/** @ingroup tftp - * Initialize TFTP server. - * @param ctx TFTP callback struct - */ -err_t -tftp_init(const struct tftp_context *ctx) -{ - err_t ret; - - /* LWIP_ASSERT_CORE_LOCKED(); is checked by udp_new() */ - struct udp_pcb *pcb = udp_new_ip_type(IPADDR_TYPE_ANY); - if (pcb == NULL) { - return ERR_MEM; - } - - ret = udp_bind(pcb, IP_ANY_TYPE, TFTP_PORT); - if (ret != ERR_OK) { - udp_remove(pcb); - return ret; - } - - tftp_state.handle = NULL; - tftp_state.port = 0; - tftp_state.ctx = ctx; - tftp_state.timer = 0; - tftp_state.last_data = NULL; - tftp_state.upcb = pcb; - - udp_recv(pcb, recv, NULL); - - return ERR_OK; -} - -/** @ingroup tftp - * Deinitialize ("turn off") TFTP server. - */ -void tftp_cleanup(void) -{ - LWIP_ASSERT("Cleanup called on non-initialized TFTP", tftp_state.upcb != NULL); - udp_remove(tftp_state.upcb); - close_handle(); - memset(&tftp_state, 0, sizeof(tftp_state)); -} - -#endif /* LWIP_UDP */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/arch/Makefile b/Ubiquitous/XiZi_AIoT/services/net/net_server/arch/Makefile deleted file mode 100644 index 49aca72f6..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/arch/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -SRC_FILES += clock_base.c - -include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/arch/cc.h b/Ubiquitous/XiZi_AIoT/services/net/net_server/arch/cc.h index 389673e9c..76d9c3a0b 100644 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/arch/cc.h +++ b/Ubiquitous/XiZi_AIoT/services/net/net_server/arch/cc.h @@ -87,4 +87,16 @@ #define LWIP_PLATFORM_ASSERT(x) do {printf(x);}while(0) #define LWIP_RAND() ((u32_t)rand()) + +static inline u32_t sys_jiffies(void) +{ + // lwip_sys_now = CurrentTicksGain(); + // return lwip_sys_now; +} + +static inline u32_t sys_now(void) +{ + // lwip_sys_now = CurrentTicksGain(); + // return CalculateTimeMsFromTick(lwip_sys_now); +} #endif /* LWIP_ARCH_CC_H */ diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/arch/clock_base.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/arch/clock_base.c deleted file mode 100644 index 46f7d8827..000000000 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/arch/clock_base.c +++ /dev/null @@ -1,26 +0,0 @@ - -/* - * Copyright (c) 2020 AIIT XUOS Lab - * XiUOS is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -#include "sys.h" - -u32_t sys_jiffies(void) -{ - // lwip_sys_now = CurrentTicksGain(); - // return lwip_sys_now; -} - -u32_t sys_now(void) -{ - // lwip_sys_now = CurrentTicksGain(); - // return CalculateTimeMsFromTick(lwip_sys_now); -} \ No newline at end of file diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/core/Makefile b/Ubiquitous/XiZi_AIoT/services/net/net_server/core/Makefile index dda9ed9f7..b70956811 100644 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/core/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/net/net_server/core/Makefile @@ -1,25 +1,32 @@ -SRC_FILES += altcp_alloc.c \ - altcp_tcp.c \ - altcp.c \ - def.c \ - dns.c \ - inet_chksum.c \ - init.c \ - ip.c \ - mem.c \ - memp.c \ - netif.c \ - pbuf.c \ - raw.c \ - stats.c \ - sys.c \ - tcp_in.c \ - tcp_out.c \ - tcp.c \ - timeouts.c \ - udp.c +include $(KERNEL_ROOT)/services/net/net_server/lwip.mk +objs += altcp_alloc.o \ + altcp_tcp.o \ + altcp.o \ + def.o \ + dns.o \ + inet_chksum.o \ + init.o \ + ip.o \ + mem.o \ + memp.o \ + netif.o \ + pbuf.o \ + raw.o \ + stats.o \ + sys.o \ + tcp_in.o \ + tcp_out.c \ + tcp.o \ + timeouts.o \ + udp.o + +core: ${objs} + @echo "generate $^" + +%.o: %.c + @echo "cc $^" + @${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^ + SRC_DIR += ipv4 -LWIP_DIR += ipv4 - include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/core/ipv4/Makefile b/Ubiquitous/XiZi_AIoT/services/net/net_server/core/ipv4/Makefile index 66f2781dd..db96f1d30 100644 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/core/ipv4/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/net/net_server/core/ipv4/Makefile @@ -1,10 +1,19 @@ -SRC_FILES += autoip.c \ - dhcp.c \ - etharp.c \ - icmp.c \ - igmp.c \ - ip4_addr.c \ - ip4_frag.c \ - ip4.c +include $(KERNEL_ROOT)/services/net/net_server/lwip.mk + +objs += autoip.o \ + dhcp.o \ + etharp.o \ + icmp.o \ + igmp.o \ + ip4_addr.o \ + ip4_frag.o \ + ip4.o + +ip4: ${objs} + @echo "generate $^" + +%.o: %.c + @echo "cc $^" + @${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^ include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/include/lwip/arch.h b/Ubiquitous/XiZi_AIoT/services/net/net_server/include/lwip/arch.h index 3bdc2a5e0..5d4211130 100644 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/include/lwip/arch.h +++ b/Ubiquitous/XiZi_AIoT/services/net/net_server/include/lwip/arch.h @@ -78,7 +78,6 @@ * systems, this should be defined to something less resource-consuming. */ #ifndef LWIP_PLATFORM_DIAG -#include "xs_base.h" #define LWIP_PLATFORM_DIAG(x) do {KPrintf x;} while(0) #include #include diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/lwip.mk b/Ubiquitous/XiZi_AIoT/services/net/net_server/lwip.mk new file mode 100644 index 000000000..41123bf16 --- /dev/null +++ b/Ubiquitous/XiZi_AIoT/services/net/net_server/lwip.mk @@ -0,0 +1,27 @@ +ifeq ($(BOARD), imx6q-sabrelite) +toolchain ?= arm-none-eabi- +user_ldflags = -N -Ttext 0 +cflags = -std=c11 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie +endif +ifeq ($(BOARD), zynq7000-zc702) +toolchain ?= arm-xilinx-eabi- +user_ldflags = --start-group,-lgcc,-lc,--end-group +cflags = -std=c11 -march=armv7-a -mtune=cortex-a9 -nostdlib -nodefaultlibs -mfloat-abi=soft -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -ggdb -Wno-unused -Werror -fno-omit-frame-pointer -fno-stack-protector -fno-pie +#cflags = -Wall -g -std=c11 +endif +cc = ${toolchain}gcc +ld = ${toolchain}g++ +objdump = ${toolchain}objdump + +c_useropts = -O2 + +INC_DIR = -I$(KERNEL_ROOT)/services/net/libnet \ + -I$(KERNEL_ROOT)/services/net/net_server/include/lwip \ + -I$(KERNEL_ROOT)/services/net/net_server/include/netif \ + -I$(KERNEL_ROOT)/services/net/net_server/include/compat \ + -I$(KERNEL_ROOT)/services/lib/ipc \ + -I$(KERNEL_ROOT)/services/lib/memory \ + -I$(KERNEL_ROOT)/services/lib/serial \ + -I$(KERNEL_ROOT)/services/lib/usyscall \ + -I$(KERNEL_ROOT)/services/boards/$(BOARD) \ + -I$(KERNEL_ROOT)/services/app diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/lwip_server.c b/Ubiquitous/XiZi_AIoT/services/net/net_server/lwip_server.c index 47c2af48b..4062eb8c0 100644 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/lwip_server.c +++ b/Ubiquitous/XiZi_AIoT/services/net/net_server/lwip_server.c @@ -14,7 +14,8 @@ #include "libserial.h" #include "usyscall.h" #include "lwip_service.h" -#include "ip4_addr.h" + + #include "ethernet.h" diff --git a/Ubiquitous/XiZi_AIoT/services/net/net_server/netif/Makefile b/Ubiquitous/XiZi_AIoT/services/net/net_server/netif/Makefile index 99de0a625..465179cb4 100644 --- a/Ubiquitous/XiZi_AIoT/services/net/net_server/netif/Makefile +++ b/Ubiquitous/XiZi_AIoT/services/net/net_server/netif/Makefile @@ -1,5 +1,14 @@ -SRC_FILES += bridgeif.c \ - ethernet.c \ - zepif.c +include $(KERNEL_ROOT)/services/net/net_server/lwip.mk +objs += bridgeif.o \ + ethernet.o \ + zepif.o + +netif:${objs} + @echo "generate $^" + +%.o: %.c + @echo "cc $^" + @${cc} ${cflags} ${c_useropts} ${INC_DIR} -o $@ -c $^ + include $(KERNEL_ROOT)/compiler.mk