diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-08-26 23:12:17 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2007-08-26 23:12:17 +0000 |
commit | 93f9271b27b33e322ffa45ec71c43884674458af (patch) | |
tree | 36f9bb5f22dc98aee189714b2733c7cbcb6c08d1 | |
parent | c010014195f732bf60d018d9432354fba0950a11 (diff) | |
download | nuttx-93f9271b27b33e322ffa45ec71c43884674458af.tar.gz nuttx-93f9271b27b33e322ffa45ec71c43884674458af.tar.bz2 nuttx-93f9271b27b33e322ffa45ec71c43884674458af.zip |
Import of uIP 1.0
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@308 42af7a65-404d-4744-a932-0658087f49c3
63 files changed, 11944 insertions, 0 deletions
diff --git a/nuttx/examples/uip/Makefile b/nuttx/examples/uip/Makefile new file mode 100644 index 000000000..6d10d8e9b --- /dev/null +++ b/nuttx/examples/uip/Makefile @@ -0,0 +1,77 @@ +############################################################ +# Makefile +# +# Copyright (C) 2007 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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. Neither the name Gregory Nutt nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################ + +-include $(TOPDIR)/.config +-include $(TOPDIR)/Make.defs + +MKDEP = $(TOPDIR)/tools/mkdeps.sh + +ASRCS = +AOBJS = $(ASRCS:.S=$(OBJEXT)) +CSRCS = main.c +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = lib$(CONFIG_EXAMPLE)$(LIBEXT) + +all: $(BIN) + +$(AOBJS): %$(OBJEXT): %.S + $(CC) -c $(CFLAGS) $< -o $@ + +$(COBJS): %$(OBJEXT): %.c + $(CC) -c $(CFLAGS) $< -o $@ + +$(BIN): $(OBJS) + ( for obj in $(OBJS) ; do \ + $(AR) $@ $${obj} || \ + { echo "$(AR) $@ $obj FAILED!" ; exit 1 ; } ; \ + done ; ) + +.depend: Makefile $(SRCS) + $(MKDEP) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep + touch $@ + +depend: .depend + +clean: + rm -f $(BIN) *.o *.rel *.asm *.lst *.sym *.adb *~ + +distclean: clean + rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/examples/uip/main.c b/nuttx/examples/uip/main.c new file mode 100644 index 000000000..1c3fff340 --- /dev/null +++ b/nuttx/examples/uip/main.c @@ -0,0 +1,165 @@ +/* main.c + * Copyright (c) 2001, Adam Dunkels. + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Adam Dunkels. + * 4. 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 uIP TCP/IP stack. + * + * $Id: main.c,v 1.1.1.1 2007-08-26 23:10:37 patacongo Exp $ + * + */ + +#include <stdio.h> +#include <time.h> + +#include <net/uip/uip.h> +#include <net/uip/uip-arp.h> + +/* Here we include the header file for the application(s) we use in + * our project as defined in the config/<board-name>/defconfig file + */ + +#define CONFIG_EXAMPLE_UIP_WEBSERVER 1 /* For now */ + +#if defined(CONFIG_EXAMPLE_UIP_SMTP) +# include <net/uip/smtp.h> +#elif defined(CONFIG_EXAMPLE_UIP_TELNETD) +# include <net/uip/telnetd.h> +#elif defined(CONFIG_EXAMPLE_UIP_WEBSERVER) +# include <net/uip/httpd.h> +#elif defined(CONFIG_EXAMPLE_UIP_DHCPC) +# include <net/uip/dhcpc.h> +#elif defined(CONFIG_EXAMPLE_UIP_RESOLV) +# include <net/uip/resolv.h> +#elif defined(CONFIG_EXAMPLE_UIP_WEBCLIENT) +# include <net/uip/webclient.h> +#endif + +int user_start(int argc, char *argv[]) +{ + int i; + uip_ipaddr_t ipaddr; +#if defined(CONFIG_EXAMPLE_UIP_DHCPC) + uint16 mac[6] = {1,2,3,4,5,6}; +#endif + + uip_ipaddr(ipaddr, 192,168,0,2); + uip_sethostaddr(ipaddr); + uip_ipaddr(ipaddr, 192,168,0,1); + uip_setdraddr(ipaddr); + uip_ipaddr(ipaddr, 255,255,255,0); + uip_setnetmask(ipaddr); + +#if defined(CONFIG_EXAMPLE_UIP_WEBSERVER) + httpd_init(); +#elif defined(CONFIG_EXAMPLE_UIP_TELNETD) + telnetd_init(); +#elif defined(CONFIG_EXAMPLE_UIP_DHCPC) + dhcpc_init(&mac, 6); +#elif defined(CONFIG_EXAMPLE_UIP_SMTP) + uip_ipaddr(ipaddr, 127,0,0,1); + smtp_configure("localhost", ipaddr); + SMTP_SEND("adam@sics.se", NULL, "uip-testing@example.com", + "Testing SMTP from uIP", + "Test message sent by uIP\r\n"); +#elif defined(CONFIG_EXAMPLE_UIP_WEBCLIENT) + webclient_init(); + resolv_init(); + uip_ipaddr(ipaddr, 195,54,122,204); + resolv_conf(ipaddr); + resolv_query("www.sics.se"); +#endif + + while(1) + { + sleep(3); + printf("main: Still running\n"); + } + return 0; +} + +void uip_log(char *m) +{ + printf("uIP log message: %s\n", m); +} + +void resolv_found(char *name, uint16 *ipaddr) +{ + if (ipaddr == NULL) + { + printf("Host '%s' not found.\n", name); + } + else + { + printf("Found name '%s' = %d.%d.%d.%d\n", name, + htons(ipaddr[0]) >> 8, htons(ipaddr[0]) & 0xff, + htons(ipaddr[1]) >> 8, htons(ipaddr[1]) & 0xff); + /* webclient_get("www.sics.se", 80, "/~adam/uip");*/ + } +} + +#ifdef __DHCPC_H__ +void dhcpc_configured(const struct dhcpc_state *s) +{ + uip_sethostaddr(s->ipaddr); + uip_setnetmask(s->netmask); + uip_setdraddr(s->default_router); + resolv_conf(s->dnsaddr); +} +#endif /* __DHCPC_H__ */ + +void smtp_done(unsigned char code) +{ + printf("SMTP done with code %d\n", code); +} + +void webclient_closed(void) +{ + printf("Webclient: connection closed\n"); +} + +void webclient_aborted(void) +{ + printf("Webclient: connection aborted\n"); +} + +void webclient_timedout(void) +{ + printf("Webclient: connection timed out\n"); +} + +void webclient_connected(void) +{ + printf("Webclient: connected, waiting for data...\n"); +} + +void webclient_datahandler(char *data, uint16 len) +{ + printf("Webclient: got %d bytes of data.\n", len); +} diff --git a/nuttx/include/net/uip/httpd.h b/nuttx/include/net/uip/httpd.h new file mode 100644 index 000000000..1c9420448 --- /dev/null +++ b/nuttx/include/net/uip/httpd.h @@ -0,0 +1,78 @@ +/* httpd.h + * + * Copyright (c) 2001-2005, Adam Dunkels. + * 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. + */ + +#ifndef __HTTPD_H__ +#define __HTTPD_H__ + +#include <sys/types.h> +#include <net/uip/psock.h> + +#define HTTPD_FS_STATISTICS 1 + +struct httpd_fs_file +{ + char *data; + int len; +}; + +struct httpd_state +{ + unsigned char timer; + struct psock sin, sout; + char inputbuf[50]; + char filename[20]; + char state; + struct httpd_fs_file file; + int len; + char *scriptptr; + int scriptlen; + + unsigned short count; +}; + +#ifdef HTTPD_FS_STATISTICS +#if HTTPD_FS_STATISTICS == 1 +extern uint16 httpd_fs_count(char *name); +#endif /* HTTPD_FS_STATISTICS */ +#endif /* HTTPD_FS_STATISTICS */ + +void httpd_init(void); +void httpd_log(char *msg); +void httpd_log_file(uint16 *requester, char *file); + +/* file must be allocated by caller and will be filled in + * by the function. + */ + +int httpd_fs_open(const char *name, struct httpd_fs_file *file); +void httpd_fs_init(void); + + +#endif /* __HTTPD_H__ */ diff --git a/nuttx/include/net/uip/psock.h b/nuttx/include/net/uip/psock.h new file mode 100644 index 000000000..9e505c970 --- /dev/null +++ b/nuttx/include/net/uip/psock.h @@ -0,0 +1,237 @@ +/* psock.h + * Protosocket library header file + * Author: Adam Dunkels <adam@sics.se> + * + * Copyright (c) 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + */ + +/* psock Protosockets library + * + * The protosocket library provides an interface to the uIP stack that is + * similar to the traditional BSD socket interface. Unlike programs + * written for the ordinary uIP event-driven interface, programs + * written with the protosocket library are executed in a sequential + * fashion and does not have to be implemented as explicit state + * machines. + * + * Protosockets only work with TCP connections. + * + * The protosocket library uses \ref pt protothreads to provide + * sequential control flow. This makes the protosockets lightweight in + * terms of memory, but also means that protosockets inherits the + * functional limitations of protothreads. Each protosocket lives only + * within a single function. Automatic variables (stack variables) are + * not retained across a protosocket library function call. + * + * \note Because the protosocket library uses protothreads, local + * variables will not always be saved across a call to a protosocket + * library function. It is therefore advised that local variables are + * used with extreme care. + * + * The protosocket library provides functions for sending data without + * having to deal with retransmissions and acknowledgements, as well + * as functions for reading data without having to deal with data + * being split across more than one TCP segment. + * + * Because each protosocket runs as a protothread, the protosocket has to be + * started with a call to PSOCK_BEGIN() at the start of the function + * in which the protosocket is used. Similarly, the protosocket protothread can + * be terminated by a call to PSOCK_EXIT(). + * + */ + +#ifndef __PSOCK_H__ +#define __PSOCK_H__ + +#include <sys/types.h> +#include <net/uip/uipopt.h> + +/* The structure that holds the state of a buffer. + * + * This structure holds the state of a uIP buffer. The structure has + * no user-visible elements, but is used through the functions + * provided by the library. + * + */ + +struct psock_buf +{ + uint8 *ptr; + unsigned short left; +}; + +/* The representation of a protosocket. + * + * The protosocket structrure is an opaque structure with no user-visible + * elements. + */ + +struct psock +{ + const uint8 *sendptr; /* Pointer to the next data to be sent. */ + uint8 *readptr; /* Pointer to the next data to be read. */ + uint8 *bufptr; /* Pointer to the buffer used for buffering incoming data. */ + uint16 sendlen; /* The number of bytes left to be sent. */ + uint16 readlen; /* The number of bytes left to be read. */ + struct psock_buf buf; /* The structure holding the state of the input buffer. */ + unsigned int bufsize; /* The size of the input buffer. */ + unsigned char state; /* The state of the protosocket. */ +}; + +/* Initialize a protosocket. + * + * Initializes a protosocket and must be called before the + * protosocket is used. The initialization also specifies the input buffer + * for the protosocket. + * + * psock (struct psock *) A pointer to the protosocket to be + * initialized + * + * buffer (char *) A pointer to the input buffer for the + * protosocket. + * + * buffersize (unsigned int) The size of the input buffer. + */ + +extern void psock_init(struct psock *psock, char *buffer, unsigned int buffersize); + +/* Send data. + * + * This macro sends data over a protosocket. The protosocket protothread blocks + * until all data has been sent and is known to have been received by + * the remote end of the TCP connection. + * + * psock (struct psock *) A pointer to the protosocket over which + * data is to be sent. + * + * data (char *) A pointer to the data that is to be sent. + * + * datalen (unsigned int) The length of the data that is to be + * sent. + */ + +extern void psock_send(struct psock *psock, const char *buf, unsigned int len); + +/*Send a null-terminated string. + * + * psock Pointer to the protosocket. + * str The string to be sent. + * + * This function sends a null-terminated string over the + * protosocket. + */ + +#define PSOCK_SEND_STR(psock, str) psock_send(psock, str, strlen(str)) + +/* Generate data with a function and send it + * + * psock Pointer to the protosocket. + * generator Pointer to the generator function + * arg Argument to the generator function + * + * This function generates data and sends it over the + * protosocket. This can be used to dynamically generate + * data for a transmission, instead of generating the data + * in a buffer beforehand. This function reduces the need for + * buffer memory. The generator function is implemented by + * the application, and a pointer to the function is given + * as an argument with the call to PSOCK_GENERATOR_SEND(). + * + * The generator function should place the generated data + * directly in the uip_appdata buffer, and return the + * length of the generated data. The generator function is + * called by the protosocket layer when the data first is + * sent, and once for every retransmission that is needed. + */ + +extern void psock_generator_send(struct psock *psock, unsigned short (*f)(void *), void *arg); + +/* Close a protosocket. + * + * This macro closes a protosocket and can only be called from within the + * protothread in which the protosocket lives. + * + * psock (struct psock *) A pointer to the protosocket that is to + * be closed. + */ + +#define PSOCK_CLOSE(psock) uip_close() + +/* Read data until the buffer is full. + * + * This macro will block waiting for data and read the data into the + * input buffer specified with the call to PSOCK_INIT(). Data is read + * until the buffer is full.. + * + * psock (struct psock *) A pointer to the protosocket from which + * data should be read. + */ + +extern void psock_readbuf(struct psock *psock); + +/* Read data up to a specified character. + * + * This macro will block waiting for data and read the data into the + * input buffer specified with the call to PSOCK_INIT(). Data is only + * read until the specifieed character appears in the data stream. + * + * psock (struct psock *) A pointer to the protosocket from which + * data should be read. + * + * c (char) The character at which to stop reading. + */ + +extern void psock_readto(struct psock *psock, unsigned char c); + +/* The length of the data that was previously read. + * + * Returns the length of the data that was previously read + * using PSOCK_READTO() or PSOCK_READ(). + * + * psock (struct psock *) A pointer to the protosocket holding the data. + */ + +extern uint16 psock_datalen(struct psock *psock); + +/* Check if there is new data has arrived on a protosocket without blocking + * + * psock (struct psock *) A pointer to the protosocket. + */ + +extern boolean psock_checknewdata(struct psock *s); + +/* Block until new data has arrived on a protosocket. + * + * psock (struct psock *) A pointer to the protosocket. + */ + +extern void psock_waitnewdata(struct psock *s); + +#endif /* __PSOCK_H__ */ + +/** @} */ diff --git a/nuttx/include/net/uip/resolv.h b/nuttx/include/net/uip/resolv.h new file mode 100644 index 000000000..3411966ea --- /dev/null +++ b/nuttx/include/net/uip/resolv.h @@ -0,0 +1,60 @@ +/* resolv.h + * DNS resolver code header file. + * Authtor Adam Dunkels <adam@dunkels.com> + * + * Copyright (c) 2002-2003, Adam Dunkels. + * 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. + */ + +#ifndef __UIP_RESOLV_H__ +#define __UIP_RESOLV_H__ + +#include <sys/types.h> +#include <net/uip/uipopt.h> + +/* Callback function which is called when a hostname is found. + * + * This function must be implemented by the module that uses the DNS + * resolver. It is called when a hostname is found, or when a hostname + * was not found. + * + * name A pointer to the name that was looked up. \param + * ipaddr A pointer to a 4-byte array containing the IP address of the + * hostname, or NULL if the hostname could not be found. + */ + +extern void resolv_found(char *name, uint16 *ipaddr); + +/* Functions. */ + +extern void resolv_conf(uint16 *dnsserver); +extern uint16 *resolv_getserver(void); +extern void resolv_init(void); +extern uint16 *resolv_lookup(char *name); +extern void resolv_query(char *name); + +#endif /* __UIP_RESOLV_H__ */ diff --git a/nuttx/include/net/uip/smtp.h b/nuttx/include/net/uip/smtp.h new file mode 100644 index 000000000..da2683f65 --- /dev/null +++ b/nuttx/include/net/uip/smtp.h @@ -0,0 +1,75 @@ +/* smtp.h + * SMTP header file + * Author: Adam Dunkels <adam@dunkels.com> + * + * Copyright (c) 2002, Adam Dunkels. + * 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. + */ + +#ifndef __SMTP_H__ +#define __SMTP_H__ + +#include <sys/types.h> + +#include <net/uip/uipopt.h> + +/* Error number that signifies a non-error condition. */ + +#define SMTP_ERR_OK 0 + +/* Callback function that is called when an e-mail transmission is + * done. + * + * This function must be implemented by the module that uses the SMTP + * module. + * + * error The number of the error if an error occured, or + * SMTP_ERR_OK. + */ + +void smtp_done(unsigned char error); + +void smtp_init(void); +void smtp_configure(char *localhostname, uint16 *smtpserver); +unsigned char smtp_send(char *to, char *from, + char *subject, char *msg, + uint16 msglen); + +struct smtp_state +{ + uint8 state; + char *to; + char *from; + char *subject; + char *msg; + uint16 msglen; + + uint16 sentlen, textlen; + uint16 sendptr; +}; + +#endif /* __SMTP_H__ */ diff --git a/nuttx/include/net/uip/uip-arch.h b/nuttx/include/net/uip/uip-arch.h new file mode 100644 index 000000000..f49448da2 --- /dev/null +++ b/nuttx/include/net/uip/uip-arch.h @@ -0,0 +1,343 @@ +/**************************************************************************** + * uip-arch.h + * Defines architecture-specific device driver interfaces to uIP + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Derived largely from portions of uIP with has a similar BSD-styple license: + * + * Copyright (c) 2001-2003, Adam Dunkels. + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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 __UIP_ARCH_H +#define __UIP_ARCH_H + +#include <sys/types.h> +#include <net/uip/uip.h> + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <net/uip/uipopt.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* The following flags are passed as an argument to the uip_interrupt() + * function. They are used to distinguish between the two cases where + * uip_interrupt() is called. It can be called either because we have + * incoming data that should be processed, or because the periodic + * timer has fired. These values are never used directly, but only in + * the macrose defined in this file. + */ + +#define UIP_DATA 1 /* Tells uIP that there is incoming data in the uip_buf buffer. The + * length of the data is stored in the global variable uip_len. */ +#define UIP_TIMER 2 /* Tells uIP that the periodic timer has fired. */ +#define UIP_POLL_REQUEST 3 /* Tells uIP that a connection should be polled. */ +#define UIP_UDP_SEND_CONN 4 /* Tells uIP that a UDP datagram should be constructed in the + * uip_buf buffer. */ +#if UIP_UDP +# define UIP_UDP_TIMER 5 +#endif /* UIP_UDP */ + +/* uIP device driver functions + * + * These functions are used by a network device driver for interacting + * with uIP. + * + * Process an incoming packet. + * + * This function should be called when the device driver has received + * a packet from the network. The packet from the device driver must + * be present in the uip_buf buffer, and the length of the packet + * should be placed in the uip_len variable. + * + * When the function returns, there may be an outbound packet placed + * in the uip_buf packet buffer. If so, the uip_len variable is set to + * the length of the packet. If no packet is to be sent out, the + * uip_len variable is set to 0. + * + * The usual way of calling the function is presented by the source + * code below. + * + * uip_len = devicedriver_poll(); + * if(uip_len > 0) { + * uip_input(); + * if(uip_len > 0) { + * devicedriver_send(); + * } + * } + * + * Note: If you are writing a uIP device driver that needs ARP + * (Address Resolution Protocol), e.g., when running uIP over + * Ethernet, you will need to call the uIP ARP code before calling + * this function: + * + * #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) + * uip_len = ethernet_devicedrver_poll(); + * if(uip_len > 0) { + * if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { + * uip_arp_ipin(); + * uip_input(); + * if(uip_len > 0) { + * uip_arp_out(); + * ethernet_devicedriver_send(); + * } + * } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { + * uip_arp_arpin(); + * if(uip_len > 0) { + * ethernet_devicedriver_send(); + * } + * } + */ + +#define uip_input() uip_interrupt(UIP_DATA) + +/* Periodic processing for a connection identified by its number. + * + * This function does the necessary periodic processing (timers, + * polling) for a uIP TCP conneciton, and should be called when the + * periodic uIP timer goes off. It should be called for every + * connection, regardless of whether they are open of closed. + * + * When the function returns, it may have an outbound packet waiting + * for service in the uIP packet buffer, and if so the uip_len + * variable is set to a value larger than zero. The device driver + * should be called to send out the packet. + * + * The ususal way of calling the function is through a for() loop like + * this: + * + * for(i = 0; i < UIP_CONNS; ++i) { + * uip_periodic(i); + * if(uip_len > 0) { + * devicedriver_send(); + * } + * } + * + * Note: If you are writing a uIP device driver that needs ARP + * (Address Resolution Protocol), e.g., when running uIP over + * Ethernet, you will need to call the uip_arp_out() function before + * calling the device driver: + * + * for(i = 0; i < UIP_CONNS; ++i) { + * uip_periodic(i); + * if(uip_len > 0) { + * uip_arp_out(); + * ethernet_devicedriver_send(); + * } + * } + * + * conn The number of the connection which is to be periodically polled. + */ + +#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ + uip_interrupt(UIP_TIMER); } while (0) + +#define uip_conn_active(conn) (uip_conns[conn].tcpstateflags != UIP_CLOSED) + +/* Perform periodic processing for a connection identified by a pointer + * to its structure. + * + * Same as uip_periodic() but takes a pointer to the actual uip_conn + * struct instead of an integer as its argument. This function can be + * used to force periodic processing of a specific connection. + * + * conn A pointer to the uip_conn struct for the connection to + * be processed. + */ + +#define uip_periodic_conn(conn) do { uip_conn = conn; uip_interrupt(UIP_TIMER); } while (0) + +/* Request that a particular connection should be polled. + * + * Similar to uip_periodic_conn() but does not perform any timer + * processing. The application is polled for new data. + * + * conn A pointer to the uip_conn struct for the connection to + * be processed. + */ + +#define uip_poll_conn(conn) do { uip_conn = conn; uip_interrupt(UIP_POLL_REQUEST); } while (0) + + +#if UIP_UDP +/* Periodic processing for a UDP connection identified by its number. + * + * This function is essentially the same as uip_periodic(), but for + * UDP connections. It is called in a similar fashion as the + * uip_periodic() function: + * + * for(i = 0; i < UIP_UDP_CONNS; i++) { + * uip_udp_periodic(i); + * if(uip_len > 0) { + * devicedriver_send(); + * } + * } + * + * Note: As for the uip_periodic() function, special care has to be + * taken when using uIP together with ARP and Ethernet: + * + * for(i = 0; i < UIP_UDP_CONNS; i++) { + * uip_udp_periodic(i); + * if(uip_len > 0) { + * uip_arp_out(); + * ethernet_devicedriver_send(); + * } + * } + * + * conn The number of the UDP connection to be processed. + */ + +#define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ + uip_interrupt(UIP_UDP_TIMER); } while (0) + +/* Periodic processing for a UDP connection identified by a pointer to + * its structure. + * + * Same as uip_udp_periodic() but takes a pointer to the actual + * uip_conn struct instead of an integer as its argument. This + * function can be used to force periodic processing of a specific + * connection. + * + * conn A pointer to the uip_udp_conn struct for the connection + * to be processed. + */ + +#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ + uip_interrupt(UIP_UDP_TIMER); } while (0) + + +#endif /* UIP_UDP */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/**************************************************************************** + * Pulblic Function Prototypes + ****************************************************************************/ + +/* Architecure support + * + * uip_interrupt(flag): + * + * The actual uIP function which does all the work. Called from the + * interrupt level by a device driver. + */ + +extern void uip_interrupt(uint8 flag); + +/* By defining UIP_ARCH_CHKSUM, the architecture can replace the following + * functions with hardware assisted solutions. + */ + +/* Carry out a 32-bit addition. + * + * Because not all architectures for which uIP is intended has native + * 32-bit arithmetic, uIP uses an external C function for doing the + * required 32-bit additions in the TCP protocol processing. This + * function should add the two arguments and place the result in the + * global variable uip_acc32. + * + * Note: The 32-bit integer pointed to by the op32 parameter and the + * result in the uip_acc32 variable are in network byte order (big + * endian). + * + * op32 A pointer to a 4-byte array representing a 32-bit + * integer in network byte order (big endian). + * + * op16 A 16-bit integer in host byte order. + */ + +#if UIP_ARCH_ADD32 +extern void uip_add32(uint8 *op32, uint16 op16); +#endif + +/* Calculate the Internet checksum over a buffer. + * + * The Internet checksum is the one's complement of the one's + * complement sum of all 16-bit words in the buffer. + * + * See RFC1071. + * + * Note: This function is not called in the current version of uIP, + * but future versions might make use of it. + * + * buf A pointer to the buffer over which the checksum is to be + * computed. + * + * len The length of the buffer over which the checksum is to + * be computed. + * + * Return: The Internet checksum of the buffer. + */ + +extern uint16 uip_chksum(uint16 *buf, uint16 len); + +/* Calculate the IP header checksum of the packet header in uip_buf. + * + * The IP header checksum is the Internet checksum of the 20 bytes of + * the IP header. + * + * Return: The IP header checksum of the IP header in the uip_buf + * buffer. + */ + +extern uint16 uip_ipchksum(void); + +/* Calculate the TCP checksum of the packet in uip_buf and uip_appdata. + * + * The TCP checksum is the Internet checksum of data contents of the + * TCP segment, and a pseudo-header as defined in RFC793. + * + * Note: The uip_appdata pointer that points to the packet data may + * point anywhere in memory, so it is not possible to simply calculate + * the Internet checksum of the contents of the uip_buf buffer. + * + * Return: The TCP checksum of the TCP segment in uip_buf and pointed + * to by uip_appdata. + */ + +extern uint16 uip_tcpchksum(void); + +extern uint16 uip_udpchksum(void); + +#endif /* __UIP_ARCH_H */ diff --git a/nuttx/include/net/uip/uip-arp.h b/nuttx/include/net/uip/uip-arp.h new file mode 100644 index 000000000..2f5148e1a --- /dev/null +++ b/nuttx/include/net/uip/uip-arp.h @@ -0,0 +1,122 @@ +/* uip-arp.h + * Macros and definitions for the ARP module. + * Author: Adam Dunkels <adam@dunkels.com> + * + * Copyright (c) 2001-2003, Adam Dunkels. + * 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. + * + */ + +#ifndef __UIP_ARP_H__ +#define __UIP_ARP_H__ + +#include <sys/types.h> +#include <net/uip/uip.h> + +extern struct uip_eth_addr uip_ethaddr; + +/* The Ethernet header */ + +struct uip_eth_hdr +{ + struct uip_eth_addr dest; + struct uip_eth_addr src; + uint16 type; +}; + +#define UIP_ETHTYPE_ARP 0x0806 +#define UIP_ETHTYPE_IP 0x0800 +#define UIP_ETHTYPE_IP6 0x86dd + +/* The uip_arp_init() function must be called before any of the other + * ARP functions. + */ + +void uip_arp_init(void); + +/* The uip_arp_ipin() function should be called whenever an IP packet + * arrives from the Ethernet. This function refreshes the ARP table or + * inserts a new mapping if none exists. The function assumes that an + * IP packet with an Ethernet header is present in the uip_buf buffer + * and that the length of the packet is in the uip_len variable. + */ + +/*void uip_arp_ipin(void);*/ +#define uip_arp_ipin() + +/* The uip_arp_arpin() should be called when an ARP packet is received + * by the Ethernet driver. This function also assumes that the + * Ethernet frame is present in the uip_buf buffer. When the + * uip_arp_arpin() function returns, the contents of the uip_buf + * buffer should be sent out on the Ethernet if the uip_len variable + * is > 0. + */ + +void uip_arp_arpin(void); + +/* The uip_arp_out() function should be called when an IP packet + * should be sent out on the Ethernet. This function creates an + * Ethernet header before the IP header in the uip_buf buffer. The + * Ethernet header will have the correct Ethernet MAC destination + * address filled in if an ARP table entry for the destination IP + * address (or the IP address of the default router) is present. If no + * such table entry is found, the IP packet is overwritten with an ARP + * request and we rely on TCP to retransmit the packet that was + * overwritten. In any case, the uip_len variable holds the length of + * the Ethernet frame that should be transmitted. + */ + +void uip_arp_out(void); + +/* The uip_arp_timer() function should be called every ten seconds. It + * is responsible for flushing old entries in the ARP table. + */ + +void uip_arp_timer(void); + +/* Specifiy the Ethernet MAC address. + * + * The ARP code needs to know the MAC address of the Ethernet card in + * order to be able to respond to ARP queries and to generate working + * Ethernet headers. + * + * Note: This macro only specifies the Ethernet MAC address to the ARP + * code. It cannot be used to change the MAC address of the Ethernet + * card. + * + * eaddr A pointer to a struct uip_eth_addr containing the + * Ethernet MAC address of the Ethernet card. + */ + +#define uip_setethaddr(eaddr) do {uip_ethaddr.addr[0] = eaddr.addr[0]; \ + uip_ethaddr.addr[1] = eaddr.addr[1];\ + uip_ethaddr.addr[2] = eaddr.addr[2];\ + uip_ethaddr.addr[3] = eaddr.addr[3];\ + uip_ethaddr.addr[4] = eaddr.addr[4];\ + uip_ethaddr.addr[5] = eaddr.addr[5];} while(0) + +#endif /* __UIP_ARP_H__ */ diff --git a/nuttx/include/net/uip/uip.h b/nuttx/include/net/uip/uip.h new file mode 100644 index 000000000..0185a8da0 --- /dev/null +++ b/nuttx/include/net/uip/uip.h @@ -0,0 +1,1172 @@ +/** + * uip.h + * Header file for the uIP TCP/IP stack. + * author Adam Dunkels <adam@dunkels.com> + * + * The uIP TCP/IP stack header file contains definitions for a number + * of C macros that are used by uIP programs as well as internal uIP + * structures, TCP/IP header structures and function declarations. + * + * Copyright (c) 2001-2003, Adam Dunkels. + * 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 uIP TCP/IP stack. + * + * $Id: uip.h,v 1.1.1.1 2007-08-26 23:12:16 patacongo Exp $ + * + ****************************************************************************/ + +#ifndef __UIP_H__ +#define __UIP_H__ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <sys/types.h> +#include <nuttx/config.h> +#include <net/uip/uipopt.h> + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/* The following flags may be set in the global variable uip_flags before + * calling the application callback. The UIP_ACKDATA, UIP_NEWDATA, and + * UIP_CLOSE flags may both be set at the same time, whereas the others are + * mutualy exclusive. Note that these flags should *NOT* be accessed directly, + * but only through the uIP functions/macros. + */ + +#define UIP_ACKDATA (1 << 0) /* Signifies that the outstanding data was acked and the + * application should send out new data instead of retransmitting + * the last data. */ +#define UIP_NEWDATA (1 << 1) /* Flags the fact that the peer has sent us new data. */ +#define UIP_REXMIT (1 << 2) /* Tells the application to retransmit the data that was last + * sent. */ +#define UIP_POLL (1 << 3) /* Used for polling the application, to check if the application + * has data that it wants to send. */ +#define UIP_CLOSE (1 << 4) /* The remote host has closed the connection, thus the connection + * has gone away. Or the application signals that it wants to + * close the connection. */ +#define UIP_ABORT (1 << 5) /* The remote host has aborted the connection, thus the connection + * has gone away. Or the application signals that it wants to + * abort the connection. */ +#define UIP_CONNECTED (1 << 6) /* We have got a connection from a remote host and have set up a + * new connection for it, or an active connection has been + * successfully established. */ +#define UIP_TIMEDOUT (1 << 7) /* The connection has been aborted due to too many retransmissions. */ +#define UIP_APPTIMEOUT (1 << 8) /* Application time limit has elapsed */ + +/* The TCP states used in the uip_conn->tcpstateflags. */ + +#define UIP_CLOSED 0 +#define UIP_SYN_RCVD 1 +#define UIP_SYN_SENT 2 +#define UIP_ESTABLISHED 3 +#define UIP_FIN_WAIT_1 4 +#define UIP_FIN_WAIT_2 5 +#define UIP_CLOSING 6 +#define UIP_TIME_WAIT 7 +#define UIP_LAST_ACK 8 +#define UIP_TS_MASK 15 + +#define UIP_STOPPED 16 + +/* The buffer size available for user data in the \ref uip_buf buffer. + * + * This macro holds the available size for user data in the \ref + * uip_buf buffer. The macro is intended to be used for checking + * bounds of available user data. + * + * Example: + * + * snprintf(uip_appdata, UIP_APPDATA_SIZE, "%u\n", i); + */ + +#define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) + + +#define UIP_PROTO_ICMP 1 +#define UIP_PROTO_TCP 6 +#define UIP_PROTO_UDP 17 +#define UIP_PROTO_ICMP6 58 + +/* Header sizes. */ +#ifdef CONFIG_NET_UIP_IPv6 +# define UIP_IPH_LEN 40 +#else /* CONFIG_NET_UIP_IPv6 */ +# define UIP_IPH_LEN 20 /* Size of IP header */ +#endif /* CONFIG_NET_UIP_IPv6 */ +#define UIP_UDPH_LEN 8 /* Size of UDP header */ +#define UIP_TCPH_LEN 20 /* Size of TCP header */ +#define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP + UDP header */ +#define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + TCP header */ +#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN + +/**************************************************************************** + * Public Type Definitions + ****************************************************************************/ + +/* Repressentation of an IP address. */ + +typedef uint16 uip_ip4addr_t[2]; +typedef uint16 uip_ip6addr_t[8]; + +#ifdef CONFIG_NET_UIP_IPv6 +typedef uip_ip6addr_t uip_ipaddr_t; +#else /* CONFIG_NET_UIP_IPv6 */ +typedef uip_ip4addr_t uip_ipaddr_t; +#endif /* CONFIG_NET_UIP_IPv6 */ + +/* Representation of a uIP TCP connection. + * + * The uip_conn structure is used for identifying a connection. All + * but one field in the structure are to be considered read-only by an + * application. The only exception is the "private: field whos purpose + * is to let the application store application-specific state (e.g., + * file pointers) for the connection. + */ + +struct uip_conn +{ + uip_ipaddr_t ripaddr; /* The IP address of the remote host. */ + + uint16 lport; /* The local TCP port, in network byte order. */ + uint16 rport; /* The local remote TCP port, in network byte + order. */ + + uint8 rcv_nxt[4]; /* The sequence number that we expect to + receive next. */ + uint8 snd_nxt[4]; /* The sequence number that was last sent by + us. */ + uint16 len; /* Length of the data that was previously sent. */ + uint16 mss; /* Current maximum segment size for the + connection. */ + uint16 initialmss; /* Initial maximum segment size for the + connection. */ + uint8 sa; /* Retransmission time-out calculation state + variable. */ + uint8 sv; /* Retransmission time-out calculation state + variable. */ + uint8 rto; /* Retransmission time-out. */ + uint8 tcpstateflags; /* TCP state and flags. */ + uint8 timer; /* The retransmission timer. */ + uint8 nrtx; /* The number of retransmissions for the last + segment sent. */ + + /* Higher level logic can retain application specific information + * in the following: + */ + + void *private; +}; + +#if UIP_UDP +/* Representation of a uIP UDP connection. */ + +struct uip_udp_conn +{ + uip_ipaddr_t ripaddr; /* The IP address of the remote peer. */ + uint16 lport; /* The local port number in network byte order. */ + uint16 rport; /* The remote port number in network byte order. */ + uint8 ttl; /* Default time-to-live. */ + + /* Higher level logic can retain application specific information + * in the following: + */ + + void *private; +}; +#endif /* UIP_UDP */ + +/** + * The structure holding the TCP/IP statistics that are gathered if + * UIP_STATISTICS is set to 1. + * + */ +struct uip_stats { + struct { + uip_stats_t drop; /* Number of dropped packets at the IP layer. */ + uip_stats_t recv; /* Number of received packets at the IP layer. */ + uip_stats_t sent; /* Number of sent packets at the IP layer. */ + uip_stats_t vhlerr; /* Number of packets dropped due to wrong + IP version or header length. */ + uip_stats_t hblenerr; /* Number of packets dropped due to wrong + IP length, high byte. */ + uip_stats_t lblenerr; /* Number of packets dropped due to wrong + IP length, low byte. */ + uip_stats_t fragerr; /* Number of packets dropped since they + were IP fragments. */ + uip_stats_t chkerr; /* Number of packets dropped due to IP + checksum errors. */ + uip_stats_t protoerr; /* Number of packets dropped since they + were neither ICMP, UDP nor TCP. */ + } ip; /* IP statistics. */ + struct { + uip_stats_t drop; /* Number of dropped ICMP packets. */ + uip_stats_t recv; /* Number of received ICMP packets. */ + uip_stats_t sent; /* Number of sent ICMP packets. */ + uip_stats_t typeerr; /* Number of ICMP packets with a wrong type. */ + } icmp; /* ICMP statistics. */ + struct { + uip_stats_t drop; /* Number of dropped TCP segments. */ + uip_stats_t recv; /* Number of recived TCP segments. */ + uip_stats_t sent; /* Number of sent TCP segments. */ + uip_stats_t chkerr; /* Number of TCP segments with a bad checksum. */ + uip_stats_t ackerr; /* Number of TCP segments with a bad ACK number. */ + uip_stats_t rst; /* Number of recevied TCP RST (reset) segments. */ + uip_stats_t rexmit; /* Number of retransmitted TCP segments. */ + uip_stats_t syndrop; /* Number of dropped SYNs due to too few + connections was avaliable. */ + uip_stats_t synrst; /* Number of SYNs for closed ports, + triggering a RST. */ + } tcp; /* TCP statistics. */ +#if UIP_UDP + struct { + uip_stats_t drop; /* Number of dropped UDP segments. */ + uip_stats_t recv; /* Number of recived UDP segments. */ + uip_stats_t sent; /* Number of sent UDP segments. */ + uip_stats_t chkerr; /* Number of UDP segments with a bad checksum. */ + } udp; /* UDP statistics. */ +#endif /* UIP_UDP */ +}; + +/* The TCP and IP headers. */ + +struct uip_tcpip_hdr { +#ifdef CONFIG_NET_UIP_IPv6 + /* IPv6 header. */ + + uint8 vtc, + tcflow; + uint16 flow; + uint8 len[2]; + uint8 proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* CONFIG_NET_UIP_IPv6 */ + /* IPv4 header. */ + + uint8 vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + uint16 ipchksum; + uint16 srcipaddr[2], + destipaddr[2]; +#endif /* CONFIG_NET_UIP_IPv6 */ + + /* TCP header. */ + + uint16 srcport, + destport; + uint8 seqno[4], + ackno[4], + tcpoffset, + flags, + wnd[2]; + uint16 tcpchksum; + uint8 urgp[2]; + uint8 optdata[4]; +}; + +/* The ICMP and IP headers. */ + +struct uip_icmpip_hdr { +#ifdef CONFIG_NET_UIP_IPv6 + /* IPv6 header. */ + + uint8 vtc, + tcf; + uint16 flow; + uint8 len[2]; + uint8 proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* CONFIG_NET_UIP_IPv6 */ + /* IPv4 header. */ + + uint8 vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + uint16 ipchksum; + uint16 srcipaddr[2], + destipaddr[2]; +#endif /* CONFIG_NET_UIP_IPv6 */ + + /* ICMP (echo) header. */ + uint8 type, icode; + uint16 icmpchksum; +#ifndef CONFIG_NET_UIP_IPv6 + uint16 id, seqno; +#else /* !CONFIG_NET_UIP_IPv6 */ + uint8 flags, reserved1, reserved2, reserved3; + uint8 icmp6data[16]; + uint8 options[1]; +#endif /* !CONFIG_NET_UIP_IPv6 */ +}; + +/* The UDP and IP headers. */ + +struct uip_udpip_hdr { +#ifdef CONFIG_NET_UIP_IPv6 + /* IPv6 header. */ + + uint8 vtc, + tcf; + uint16 flow; + uint8 len[2]; + uint8 proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* CONFIG_NET_UIP_IPv6 */ + /* IP header. */ + + uint8 vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + uint16 ipchksum; + uint16 srcipaddr[2], + destipaddr[2]; +#endif /* CONFIG_NET_UIP_IPv6 */ + + /* UDP header. */ + + uint16 srcport, + destport; + uint16 udplen; + uint16 udpchksum; +}; + +/* Representation of a 48-bit Ethernet address. */ + +struct uip_eth_addr { + uint8 addr[6]; +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* The uIP packet buffer. + * + * The uip_buf array is used to hold incoming and outgoing + * packets. The device driver should place incoming data into this + * buffer. When sending data, the device driver should read the link + * level headers and the TCP/IP headers from this buffer. The size of + * the link level headers is configured by the UIP_LLH_LEN define. + * + * Note: The application data need not be placed in this buffer, so + * the device driver must read it from the place pointed to by the + * uip_appdata pointer as illustrated by the following example: + * + * void + * devicedriver_send(void) + * { + * hwsend(&uip_buf[0], UIP_LLH_LEN); + * if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) { + * hwsend(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN); + * } else { + * hwsend(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN); + * hwsend(uip_appdata, uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN); + * } + * } + */ + +extern uint8 uip_buf[UIP_BUFSIZE+2]; + +/* Pointer to the application data in the packet buffer. + * + * This pointer points to the application data when the application is + * called. If the application wishes to send data, the application may + * use this space to write the data into before calling uip_send(). + */ + +extern void *uip_appdata; + +#if UIP_URGDATA > 0 +/* uint8 *uip_urgdata: + * + * This pointer points to any urgent data that has been received. Only + * present if compiled with support for urgent data (UIP_URGDATA). + */ +extern void *uip_urgdata; +#endif /* UIP_URGDATA > 0 */ + + +/* Variables used in uIP device drivers + * + * uIP has a few global variables that are used in device drivers for + * uIP. + * + * The length of the packet in the uip_buf buffer. + * + * The global variable uip_len holds the length of the packet in the + * uip_buf buffer. + * + * When the network device driver calls the uIP input function, + * uip_len should be set to the length of the packet in the uip_buf + * buffer. + * + * When sending packets, the device driver should use the contents of + * the uip_len variable to determine the length of the outgoing + * packet. + * + */ + +extern uint16 uip_len; + +#if UIP_URGDATA > 0 +extern uint16 uip_urglen, uip_surglen; +#endif /* UIP_URGDATA > 0 */ + +/* Pointer to the current TCP connection. + * + * The uip_conn pointer can be used to access the current TCP + * connection. + */ + +extern struct uip_conn *uip_conn; + +/* The array containing all uIP connections. */ +extern struct uip_conn uip_conns[UIP_CONNS]; + +/* 4-byte array used for the 32-bit sequence number calculations.*/ + +extern uint8 uip_acc32[4]; + +/* The current UDP connection. */ + +#if UIP_UDP +extern struct uip_udp_conn *uip_udp_conn; +extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; +#endif /* UIP_UDP */ + +/* The uIP TCP/IP statistics. + * + * This is the variable in which the uIP TCP/IP statistics are gathered. + */ + +extern struct uip_stats uip_stat; + +/* uint16 uip_flags: + * + * When the application is called, uip_flags will contain the flags + * that are defined in this file. Please read below for more + * infomation. + */ + +extern uint16 uip_flags; + +#if UIP_FIXEDADDR +extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +#else /* UIP_FIXEDADDR */ +extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; +#endif /* UIP_FIXEDADDR */ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* uIP configuration functions + * + * The uIP configuration functions are used for setting run-time + * parameters in uIP such as IP addresses. + * + * Set the IP address of this host. + * + * The IP address is represented as a 4-byte array where the first + * octet of the IP address is put in the first member of the 4-byte + * array. + * + * Example: + * + * uip_ipaddr_t addr; + * + * uip_ipaddr(&addr, 192,168,1,2); + * uip_sethostaddr(&addr); + * + * addr A pointer to an IP address of type uip_ipaddr_t; + */ + +#define uip_sethostaddr(addr) uip_ipaddr_copy(uip_hostaddr, (addr)) + +/* Get the IP address of this host. + * + * The IP address is represented as a 4-byte array where the first + * octet of the IP address is put in the first member of the 4-byte + * array. + * + * Example: + * + * uip_ipaddr_t hostaddr; + * + * uip_gethostaddr(&hostaddr); + * + * addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the currently configured IP address. + */ + +#define uip_gethostaddr(addr) uip_ipaddr_copy((addr), uip_hostaddr) + +/* Set the default router's IP address. + * + * addr A pointer to a uip_ipaddr_t variable containing the IP + * address of the default router. + */ + +#define uip_setdraddr(addr) uip_ipaddr_copy(uip_draddr, (addr)) + +/* Set the netmask. + * + * addr A pointer to a uip_ipaddr_t variable containing the IP + * address of the netmask. + */ + +#define uip_setnetmask(addr) uip_ipaddr_copy(uip_netmask, (addr)) + +/* Get the default router's IP address. + * + * addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the IP address of the default router. + */ + +#define uip_getdraddr(addr) uip_ipaddr_copy((addr), uip_draddr) + +/* Get the netmask. + * + * addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the value of the netmask. + */ + +#define uip_getnetmask(addr) uip_ipaddr_copy((addr), uip_netmask) + +/* uIP initialization functions + * + * The uIP initialization functions are used for booting uIP. + * + * This function should be called at boot up to initilize the uIP + * TCP/IP stack. + */ + +void uip_init(void); + +/* This function may be used at boot time to set the initial ip_id.*/ + +void uip_setipid(uint16 id); + +/* uIP application functions + * + * Functions used by an application running of top of uIP. This includes + * functions for opening and closing connections, sending and receiving + * data, etc. + * + * The following function must be provided by the application logic. It + * is called from the UIP interrupt handler when interesting events are + * detected that may be of interest to the application. + */ + +void uip_interrupt_event(void); +#if UIP_UDP +void uip_interrupt_udp_event(void); +#endif + +/* Start listening to the specified port. + * + * Note: Since this function expects the port number in network byte + * order, a conversion using HTONS() or htons() is necessary. + * + * port A 16-bit port number in network byte order. + */ + +void uip_listen(uint16 port); + +/* Stop listening to the specified port. + * + * Note: Since this function expects the port number in network byte + * order, a conversion using HTONS() or htons() is necessary. + * + * port A 16-bit port number in network byte order. + */ + +void uip_unlisten(uint16 port); + +/* Connect to a remote host using TCP. + * + * This function is used to start a new connection to the specified + * port on the specied host. It allocates a new connection identifier, + * sets the connection to the SYN_SENT state and sets the + * retransmission timer to 0. This will cause a TCP SYN segment to be + * sent out the next time this connection is periodically processed, + * which usually is done within 0.5 seconds after the call to + * uip_connect(). + * + * Note: This function is avaliable only if support for active open + * has been configured by defining UIP_ACTIVE_OPEN to 1 in uipopt.h. + * + * Note: Since this function requires the port number to be in network + * byte order, a conversion using HTONS() or htons() is necessary. + * + * Example: + * + * uip_ipaddr_t ipaddr; + * + * uip_ipaddr(&ipaddr, 192,168,1,2); + * uip_connect(&ipaddr, HTONS(80)); + * + * ripaddr The IP address of the remote hot. + * + * port A 16-bit port number in network byte order. + * + * Return: A pointer to the uIP connection identifier for the new connection, + * or NULL if no connection could be allocated. + */ + +struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, uint16 port); + + +/* Check if a connection has outstanding (i.e., unacknowledged) data. + * + * conn A pointer to the uip_conn structure for the connection. + */ + +#define uip_outstanding(conn) ((conn)->len) + +/* Send data on the current connection. + * + * This function is used to send out a single segment of TCP + * data. Only applications that have been invoked by uIP for event + * processing can send data. + * + * The amount of data that actually is sent out after a call to this + * funcion is determined by the maximum amount of data TCP allows. uIP + * will automatically crop the data so that only the appropriate + * amount of data is sent. The function uip_mss() can be used to query + * uIP for the amount of data that actually will be sent. + * + * Note: This function does not guarantee that the sent data will + * arrive at the destination. If the data is lost in the network, the + * application will be invoked with the uip_rexmit() event being + * set. The application will then have to resend the data using this + * function. + * + * data A pointer to the data which is to be sent. + * + * len The maximum amount of data bytes to be sent. + */ + +void uip_send(const void *data, int len); + +/* The length of any incoming data that is currently avaliable (if avaliable) + * in the uip_appdata buffer. + * + * The test function uip_data() must first be used to check if there + * is any data available at all. + */ + +#define uip_datalen() uip_len + +/* The length of any out-of-band data (urgent data) that has arrived + * on the connection. + * + * Note: The configuration parameter UIP_URGDATA must be set for this + * function to be enabled. + */ + +#define uip_urgdatalen() uip_urglen + +/* Close the current connection. + * + * This function will close the current connection in a nice way. + */ + +#define uip_close() (uip_flags = UIP_CLOSE) + +/* Abort the current connection. + * + * This function will abort (reset) the current connection, and is + * usually used when an error has occured that prevents using the + * uip_close() function. + */ + +#define uip_abort() (uip_flags = UIP_ABORT) + +/* Tell the sending host to stop sending data. + * + * This function will close our receiver's window so that we stop + * receiving data for the current connection. + */ + +#define uip_stop() (uip_conn->tcpstateflags |= UIP_STOPPED) + +/* Find out if the current connection has been previously stopped with + * uip_stop(). + */ + +#define uip_stopped(conn) ((conn)->tcpstateflags & UIP_STOPPED) + +/* Restart the current connection, if is has previously been stopped + * with uip_stop(). + * + * This function will open the receiver's window again so that we + * start receiving data for the current connection. + */ + +#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ + uip_conn->tcpstateflags &= ~UIP_STOPPED; \ + } while(0) + + +/* uIP tests that can be made to determine in what state the current + * connection is, and what the application function should do. + * + * Is the current connection a UDP connection? + * + * This function checks whether the current connection is a UDP connection. + */ + +#define uip_udpconnection() (uip_conn == NULL) + +/* Is new incoming data available? + * + * Will reduce to non-zero if there is new data for the application + * present at the uip_appdata pointer. The size of the data is + * avaliable through the uip_len variable. + */ + +#define uip_newdata() (uip_flags & UIP_NEWDATA) + +/* Has previously sent data been acknowledged? + * + * Will reduce to non-zero if the previously sent data has been + * acknowledged by the remote host. This means that the application + * can send new data. + */ + +#define uip_acked() (uip_flags & UIP_ACKDATA) + +/* Has the connection just been connected? + * + * Reduces to non-zero if the current connection has been connected to + * a remote host. This will happen both if the connection has been + * actively opened (with uip_connect()) or passively opened (with + * uip_listen()). + */ + +#define uip_connected() (uip_flags & UIP_CONNECTED) + +/* Has the connection been closed by the other end? + * + * Is non-zero if the connection has been closed by the remote + * host. The application may then do the necessary clean-ups. + */ + +#define uip_closed() (uip_flags & UIP_CLOSE) + +/* Has the connection been aborted by the other end? + * + * Non-zero if the current connection has been aborted (reset) by the + * remote host. + */ + +#define uip_aborted() (uip_flags & UIP_ABORT) + +/* Has the connection timed out? + * + * Non-zero if the current connection has been aborted due to too many + * retransmissions. + */ + +#define uip_timedout() (uip_flags & UIP_TIMEDOUT) + +/* Do we need to retransmit previously data? + * + * Reduces to non-zero if the previously sent data has been lost in + * the network, and the application should retransmit it. The + * application should send the exact same data as it did the last + * time, using the uip_send() function. + */ + +#define uip_rexmit() (uip_flags & UIP_REXMIT) + +/* Is the connection being polled by uIP? + * + * Is non-zero if the reason the application is invoked is that the + * current connection has been idle for a while and should be + * polled. + * + * The polling event can be used for sending data without having to + * wait for the remote host to send data. + */ + +#define uip_poll() (uip_flags & UIP_POLL) + +/* Get the initial maxium segment size (MSS) of the current + * connection. + */ + +#define uip_initialmss() (uip_conn->initialmss) + +/* Get the current maxium segment size that can be sent on the current + * connection. + * + * The current maxiumum segment size that can be sent on the + * connection is computed from the receiver's window and the MSS of + * the connection (which also is available by calling + * uip_initialmss()). + */ + +#define uip_mss() (uip_conn->mss) + +/* Set up a new UDP connection. + * + * This function sets up a new UDP connection. The function will + * automatically allocate an unused local port for the new + * connection. However, another port can be chosen by using the + * uip_udp_bind() call, after the uip_udp_new() function has been + * called. + * + * Example: + * + * uip_ipaddr_t addr; + * struct uip_udp_conn *c; + * + * uip_ipaddr(&addr, 192,168,2,1); + * c = uip_udp_new(&addr, HTONS(12345)); + * if(c != NULL) { + * uip_udp_bind(c, HTONS(12344)); + * } + * + * ripaddr The IP address of the remote host. + * + * rport The remote port number in network byte order. + * + * Return: The uip_udp_conn structure for the new connection or NULL + * if no connection could be allocated. + */ + +struct uip_udp_conn *uip_udp_new(uip_ipaddr_t *ripaddr, uint16 rport); + +/* Removed a UDP connection. + * + * conn A pointer to the uip_udp_conn structure for the connection. + */ + +#define uip_udp_remove(conn) (conn)->lport = 0 + +/* Bind a UDP connection to a local port. + * + * conn A pointer to the uip_udp_conn structure for the + * connection. + * + * port The local port number, in network byte order. + */ + +#define uip_udp_bind(conn, port) (conn)->lport = port + +/* Send a UDP datagram of length len on the current connection. + * + * This function can only be called in response to a UDP event (poll + * or newdata). The data must be present in the uip_buf buffer, at the + * place pointed to by the uip_appdata pointer. + * + * len The length of the data in the uip_buf buffer. + */ + +#define uip_udp_send(len) uip_send((char *)uip_appdata, len) + +/* uIP convenience and converting functions. + * + * These functions can be used for converting between different data + * formats used by uIP. + * + * Construct an IP address from four bytes. + * + * This function constructs an IP address of the type that uIP handles + * internally from four bytes. The function is handy for specifying IP + * addresses to use with e.g. the uip_connect() function. + * + * Example: + * + * uip_ipaddr_t ipaddr; + * struct uip_conn *c; + * + * uip_ipaddr(&ipaddr, 192,168,1,2); + * c = uip_connect(&ipaddr, HTONS(80)); + * + * addr A pointer to a uip_ipaddr_t variable that will be + * filled in with the IP address. + * + * addr0 The first octet of the IP address. + * addr1 The second octet of the IP address. + * addr2 The third octet of the IP address. + * addr3 The forth octet of the IP address. + */ + +#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ + ((uint16 *)(addr))[0] = HTONS(((addr0) << 8) | (addr1)); \ + ((uint16 *)(addr))[1] = HTONS(((addr2) << 8) | (addr3)); \ + } while(0) + +/* Construct an IPv6 address from eight 16-bit words. + * + * This function constructs an IPv6 address. + */ + +#define uip_ip6addr(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) do { \ + ((uint16 *)(addr))[0] = HTONS((addr0)); \ + ((uint16 *)(addr))[1] = HTONS((addr1)); \ + ((uint16 *)(addr))[2] = HTONS((addr2)); \ + ((uint16 *)(addr))[3] = HTONS((addr3)); \ + ((uint16 *)(addr))[4] = HTONS((addr4)); \ + ((uint16 *)(addr))[5] = HTONS((addr5)); \ + ((uint16 *)(addr))[6] = HTONS((addr6)); \ + ((uint16 *)(addr))[7] = HTONS((addr7)); \ + } while(0) + +/* Copy an IP address to another IP address. + * + * Copies an IP address from one place to another. + * + * Example: + * + * uip_ipaddr_t ipaddr1, ipaddr2; + * + * uip_ipaddr(&ipaddr1, 192,16,1,2); + * uip_ipaddr_copy(&ipaddr2, &ipaddr1); + * + * dest The destination for the copy. + * src The source from where to copy. + */ + +#ifndef CONFIG_NET_UIP_IPv6 +#define uip_ipaddr_copy(dest, src) do { \ + ((uint16 *)dest)[0] = ((uint16 *)src)[0]; \ + ((uint16 *)dest)[1] = ((uint16 *)src)[1]; \ + } while(0) +#else /* !CONFIG_NET_UIP_IPv6 */ +#define uip_ipaddr_copy(dest, src) memcpy(dest, src, sizeof(uip_ip6addr_t)) +#endif /* !CONFIG_NET_UIP_IPv6 */ + +/* Compare two IP addresses + * + * Example: + * + * uip_ipaddr_t ipaddr1, ipaddr2; + * + * uip_ipaddr(&ipaddr1, 192,16,1,2); + * if(uip_ipaddr_cmp(&ipaddr2, &ipaddr1)) { + * printf("They are the same"); + * } + * + * addr1 The first IP address. + * addr2 The second IP address. + */ + +#ifndef CONFIG_NET_UIP_IPv6 +#define uip_ipaddr_cmp(addr1, addr2) (((uint16 *)addr1)[0] == ((uint16 *)addr2)[0] && \ + ((uint16 *)addr1)[1] == ((uint16 *)addr2)[1]) +#else /* !CONFIG_NET_UIP_IPv6 */ +#define uip_ipaddr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0) +#endif /* !CONFIG_NET_UIP_IPv6 */ + +/** + * Compare two IP addresses with netmasks + * + * Compares two IP addresses with netmasks. The masks are used to mask + * out the bits that are to be compared. + * + * Example: + * + * uip_ipaddr_t ipaddr1, ipaddr2, mask; + * + * uip_ipaddr(&mask, 255,255,255,0); + * uip_ipaddr(&ipaddr1, 192,16,1,2); + * uip_ipaddr(&ipaddr2, 192,16,1,3); + * if(uip_ipaddr_maskcmp(&ipaddr1, &ipaddr2, &mask)) { + * printf("They are the same"); + * } + * + * addr1 The first IP address. + * addr2 The second IP address. + * mask The netmask. + */ + +#define uip_ipaddr_maskcmp(addr1, addr2, mask) \ + (((((uint16 *)addr1)[0] & ((uint16 *)mask)[0]) == \ + (((uint16 *)addr2)[0] & ((uint16 *)mask)[0])) && \ + ((((uint16 *)addr1)[1] & ((uint16 *)mask)[1]) == \ + (((uint16 *)addr2)[1] & ((uint16 *)mask)[1]))) + + +/** + * Mask out the network part of an IP address. + * + * Masks out the network part of an IP address, given the address and + * the netmask. + * + * Example: + * + * uip_ipaddr_t ipaddr1, ipaddr2, netmask; + * + * uip_ipaddr(&ipaddr1, 192,16,1,2); + * uip_ipaddr(&netmask, 255,255,255,0); + * uip_ipaddr_mask(&ipaddr2, &ipaddr1, &netmask); + * + * In the example above, the variable "ipaddr2" will contain the IP + * address 192.168.1.0. + * + * dest Where the result is to be placed. + * src The IP address. + * mask The netmask. + */ + +#define uip_ipaddr_mask(dest, src, mask) do { \ + ((uint16 *)dest)[0] = ((uint16 *)src)[0] & ((uint16 *)mask)[0]; \ + ((uint16 *)dest)[1] = ((uint16 *)src)[1] & ((uint16 *)mask)[1]; \ + } while(0) + +/* Pick the first octet of an IP address. + * + * Picks out the first octet of an IP address. + * + * Example: + * + * uip_ipaddr_t ipaddr; + * uint8 octet; + * + * uip_ipaddr(&ipaddr, 1,2,3,4); + * octet = uip_ipaddr1(&ipaddr); + * + * In the example above, the variable "octet" will contain the value 1. + */ + +#define uip_ipaddr1(addr) (htons(((uint16 *)(addr))[0]) >> 8) + +/* Pick the second octet of an IP address. + * + * Picks out the second octet of an IP address. + * + * Example: + * + * uip_ipaddr_t ipaddr; + * uint8 octet; + * + * uip_ipaddr(&ipaddr, 1,2,3,4); + * octet = uip_ipaddr2(&ipaddr); + * + * In the example above, the variable "octet" will contain the value 2. + */ + +#define uip_ipaddr2(addr) (htons(((uint16 *)(addr))[0]) & 0xff) + +/* Pick the third octet of an IP address. + * + * Picks out the third octet of an IP address. + * + * Example: + * + * uip_ipaddr_t ipaddr; + * uint8 octet; + * + * uip_ipaddr(&ipaddr, 1,2,3,4); + * octet = uip_ipaddr3(&ipaddr); + * + * In the example above, the variable "octet" will contain the value 3. + */ + +#define uip_ipaddr3(addr) (htons(((uint16 *)(addr))[1]) >> 8) + +/* Pick the fourth octet of an IP address. + * + * Picks out the fourth octet of an IP address. + * + * Example: + * + * uip_ipaddr_t ipaddr; + * uint8 octet; + * + * uip_ipaddr(&ipaddr, 1,2,3,4); + * octet = uip_ipaddr4(&ipaddr); + * + * In the example above, the variable "octet" will contain the value 4. + */ + +#define uip_ipaddr4(addr) (htons(((uint16 *)(addr))[1]) & 0xff) + +/* Convert 16-bit quantity from host byte order to network byte order. + * + * This macro is primarily used for converting constants from host + * byte order to network byte order. For converting variables to + * network byte order, use the htons() function instead. + */ + +#ifndef HTONS +# if UIP_BYTE_ORDER == UIP_BIG_ENDIAN +# define HTONS(n) (n) +# else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ +# define HTONS(n) (uint16)((((uint16) (n)) << 8) | (((uint16) (n)) >> 8)) +# endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */ +#else +#error "HTONS already defined!" +#endif /* HTONS */ + +/* Convert 16-bit quantity from host byte order to network byte order. + * + * This function is primarily used for converting variables from host + * byte order to network byte order. For converting constants to + * network byte order, use the HTONS() macro instead. + */ + +#ifndef htons +uint16 htons(uint16 val); +#endif /* htons */ +#ifndef ntohs +#define ntohs htons +#endif + +/* This function is called user code to set up the wait */ + +#define uip_event_wait(waitflags) uip_event_timedwait(waitflags,0) +extern int uip_event_timedwait(uint16 waitflags, int timeout); + +/* This function is called from uip_interrupt() to wake up any + * waiting threads/tasks. + */ + +extern void uip_event_signal(void); + +#endif /* __UIP_H__ */ diff --git a/nuttx/include/net/uip/uipopt.h b/nuttx/include/net/uip/uipopt.h new file mode 100644 index 000000000..1e468f6d8 --- /dev/null +++ b/nuttx/include/net/uip/uipopt.h @@ -0,0 +1,423 @@ +/**************************************************************************** + * uipopt.h + * Configuration options for uIP. + * author Adam Dunkels <adam@dunkels.com> + * + * This file is used for tweaking various configuration options for + * uIP. You should make a copy of this file into one of your project's + * directories instead of editing this example "uipopt.h" file that + * comes with the uIP distribution. + * + * uIP is configured using the per-project configuration file + * uipopt.h. This file contains all compile-time options for uIP and + * should be tweaked to match each specific project. The uIP + * distribution contains a documented example "uipopt.h" that can be + * copied and modified for each project. + * + * Note: Most of the configuration options in the uipopt.h should not + * be changed, but rather the per-project defconfig file. + * + * Copyright (c) 2001-2003, Adam Dunkels. + * 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 uIP TCP/IP stack. + * + * $Id: uipopt.h,v 1.1.1.1 2007-08-26 23:12:17 patacongo Exp $ + * + */ + +#ifndef __UIPOPT_H__ +#define __UIPOPT_H__ + +#include <sys/types.h> +#include <nuttx/config.h> + +/*------------------------------------------------------------------------------*/ + +/** + * \name Static configuration options + * + * These configuration options can be used for setting the IP address + * settings statically, but only if UIP_FIXEDADDR is set to 1. The + * configuration options for a specific node includes IP address, + * netmask and default router as well as the Ethernet address. The + * netmask, default router and Ethernet address are appliciable only + * if uIP should be run over Ethernet. + * + * All of these should be changed to suit your project. +*/ + +/** + * Statistics datatype + * + * This typedef defines the dataype used for keeping statistics in + * uIP. + */ +typedef uint16 uip_stats_t; + +/** + * Determines if uIP should use a fixed IP address or not. + * + * If uIP should use a fixed IP address, the settings are set in the + * uipopt.h file. If not, the macros uip_sethostaddr(), + * uip_setdraddr() and uip_setnetmask() should be used instead. + */ +#define UIP_FIXEDADDR 0 + +/** + * Ping IP address asignment. + * + * uIP uses a "ping" packets for setting its own IP address if this + * option is set. If so, uIP will start with an empty IP address and + * the destination IP address of the first incoming "ping" (ICMP echo) + * packet will be used for setting the hosts IP address. + * + * \note This works only if UIP_FIXEDADDR is 0. + */ + +#ifdef CONFIG_UIP_PINGADDRCONF +#define UIP_PINGADDRCONF CONFIG_UIP_PINGADDRCONF +#else /* CONFIG_UIP_PINGADDRCONF */ +#define UIP_PINGADDRCONF 0 +#endif /* CONFIG_UIP_PINGADDRCONF */ + +/** + * Specifies if the uIP ARP module should be compiled with a fixed + * Ethernet MAC address or not. + * + * If this configuration option is 0, the macro uip_setethaddr() can + * be used to specify the Ethernet address at run-time. + */ +#define UIP_FIXEDETHADDR 0 + +/*------------------------------------------------------------------------------*/ +/** + * \name IP configuration options + */ +/** + * The IP TTL (time to live) of IP packets sent by uIP. + * + * This should normally not be changed. + */ +#define UIP_TTL 64 + +/** + * Turn on support for IP packet reassembly. + * + * uIP supports reassembly of fragmented IP packets. This features + * requires an additonal amount of RAM to hold the reassembly buffer + * and the reassembly code size is approximately 700 bytes. The + * reassembly buffer is of the same size as the uip_buf buffer + * (configured by UIP_BUFSIZE). + * + * \note IP packet reassembly is not heavily tested. + */ +#define UIP_REASSEMBLY 0 + +/** + * The maximum time an IP fragment should wait in the reassembly + * buffer before it is dropped. + * + */ +#define UIP_REASS_MAXAGE 40 + +/*------------------------------------------------------------------------------*/ +/** + * \name UDP configuration options + */ + +/** + * Toggles wether UDP support should be compiled in or not. + */ +#ifdef CONFIG_UIP_UDP +# define UIP_UDP CONFIG_UIP_UDP +#else /* CONFIG_UIP_UDP */ +# define UIP_UDP 0 +#endif /* CONFIG_UIP_UDP */ + +/** + * Toggles if UDP checksums should be used or not. + * + * \note Support for UDP checksums is currently not included in uIP, + * so this option has no function. + */ +#ifdef CONFIG_UIP_UDP_CHECKSUMS +# define UIP_UDP_CHECKSUMS CONFIG_UIP_UDP_CHECKSUMS +#else +# define UIP_UDP_CHECKSUMS 0 +#endif + +/** + * The maximum amount of concurrent UDP connections. + */ +#ifdef CONFIG_UIP_UDP_CONNS +# define UIP_UDP_CONNS CONFIG_UIP_UDP_CONNS +#else /* CONFIG_UIP_UDP_CONNS */ +# define UIP_UDP_CONNS 10 +#endif /* CONFIG_UIP_UDP_CONNS */ + +/** + * The name of the function that should be called when UDP datagrams arrive. + */ + + +/*------------------------------------------------------------------------------*/ +/** + * \name TCP configuration options + */ + +/** + * Determines if support for opening connections from uIP should be + * compiled in. + * + * If the applications that are running on top of uIP for this project + * do not need to open outgoing TCP connections, this configration + * option can be turned off to reduce the code size of uIP. + */ +#define UIP_ACTIVE_OPEN 1 + +/** + * The maximum number of simultaneously open TCP connections. + * + * Since the TCP connections are statically allocated, turning this + * configuration knob down results in less RAM used. Each TCP + * connection requires approximatly 30 bytes of memory. + */ +#ifndef CONFIG_UIP_MAX_CONNECTIONS +# define UIP_CONNS 10 +#else /* CONFIG_UIP_MAX_CONNECTIONS */ +# define UIP_CONNS CONFIG_UIP_MAX_CONNECTIONS +#endif /* CONFIG_UIP_MAX_CONNECTIONS */ + +/** + * The maximum number of simultaneously listening TCP ports. + * + * Each listening TCP port requires 2 bytes of memory. + */ +#ifndef CONFIG_UIP_MAX_LISTENPORTS +# define UIP_LISTENPORTS 20 +#else /* CONFIG_UIP_MAX_LISTENPORTS */ +# define UIP_LISTENPORTS CONFIG_UIP_MAX_LISTENPORTS +#endif /* CONFIG_UIP_MAX_LISTENPORTS */ + +/** + * Determines if support for TCP urgent data notification should be + * compiled in. + * + * Urgent data (out-of-band data) is a rarely used TCP feature that + * very seldom would be required. + */ +#define UIP_URGDATA 0 + +/** + * The initial retransmission timeout counted in timer pulses. + * + * This should not be changed. + */ +#define UIP_RTO 3 + +/** + * The maximum number of times a segment should be retransmitted + * before the connection should be aborted. + * + * This should not be changed. + */ +#define UIP_MAXRTX 8 + +/** + * The maximum number of times a SYN segment should be retransmitted + * before a connection request should be deemed to have been + * unsuccessful. + * + * This should not need to be changed. + */ +#define UIP_MAXSYNRTX 5 + +/** + * The TCP maximum segment size. + * + * This is should not be to set to more than + * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN. + */ +#define UIP_TCP_MSS (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) + +/** + * The size of the advertised receiver's window. + * + * Should be set low (i.e., to the size of the uip_buf buffer) is the + * application is slow to process incoming data, or high (32768 bytes) + * if the application processes data quickly. + */ +#ifndef CONFIG_UIP_RECEIVE_WINDOW +# define UIP_RECEIVE_WINDOW UIP_TCP_MSS +#else +# define UIP_RECEIVE_WINDOW CONFIG_UIP_RECEIVE_WINDOW +#endif + +/** + * How long a connection should stay in the TIME_WAIT state. + * + * This configiration option has no real implication, and it should be + * left untouched. + */ +#define UIP_TIME_WAIT_TIMEOUT 120 + + +/*------------------------------------------------------------------------------*/ +/** + * \name ARP configuration options + */ + +/** + * The size of the ARP table. + * + * This option should be set to a larger value if this uIP node will + * have many connections from the local network. + */ +#ifdef CONFIG_UIP_ARPTAB_SIZE +# define UIP_ARPTAB_SIZE CONFIG_UIP_ARPTAB_SIZE +#else +# define UIP_ARPTAB_SIZE 8 +#endif + +/** + * The maxium age of ARP table entries measured in 10ths of seconds. + * + * An UIP_ARP_MAXAGE of 120 corresponds to 20 minutes (BSD + * default). + */ +#define UIP_ARP_MAXAGE 120 + +/*------------------------------------------------------------------------------*/ + +/** + * \name General configuration options + */ + +/** + * The size of the uIP packet buffer. + * + * The uIP packet buffer should not be smaller than 60 bytes, and does + * not need to be larger than 1500 bytes. Lower size results in lower + * TCP throughput, larger size results in higher TCP throughput. + */ +#ifndef CONFIG_UIP_BUFFER_SIZE +# define UIP_BUFSIZE 400 +#else /* CONFIG_UIP_BUFFER_SIZE */ +# define UIP_BUFSIZE CONFIG_UIP_BUFFER_SIZE +#endif /* CONFIG_UIP_BUFFER_SIZE */ + + +/** + * Determines if statistics support should be compiled in. + * + * The statistics is useful for debugging and to show the user. + */ + +#ifndef CONFIG_UIP_STATISTICS +# define UIP_STATISTICS 0 +#else /* CONFIG_UIP_STATISTICS */ +# define UIP_STATISTICS CONFIG_UIP_STATISTICS +#endif /* CONFIG_UIP_STATISTICS */ + +/** + * Determines if logging of certain events should be compiled in. + * + * This is useful mostly for debugging. The function uip_log() + * must be implemented to suit the architecture of the project, if + * logging is turned on. + */ + +#ifndef CONFIG_UIP_LOGGING +# define UIP_LOGGING 0 +#else /* CONFIG_UIP_LOGGING */ +# define UIP_LOGGING CONFIG_UIP_LOGGING +#endif /* CONFIG_UIP_LOGGING */ + +/** + * Broadcast support. + * + * This flag configures IP broadcast support. This is useful only + * together with UDP. + */ + +#ifndef CONFIG_UIP_BROADCAST +# define UIP_BROADCAST 0 +#else /* CONFIG_UIP_BROADCAST */ +# define UIP_BROADCAST CONFIG_UIP_BROADCAST +#endif /* CONFIG_UIP_BROADCAST */ + +/** + * Print out a uIP log message. + * + * This function must be implemented by the module that uses uIP, and + * is called by uIP whenever a log message is generated. + */ +void uip_log(char *msg); + +/** + * The link level header length. + * + * This is the offset into the uip_buf where the IP header can be + * found. For Ethernet, this should be set to 14. For SLIP, this + * should be set to 0. + */ + +#ifdef CONFIG_UIP_LLH_LEN +# define UIP_LLH_LEN CONFIG_UIP_LLH_LEN +#else /* CONFIG_UIP_LLH_LEN */ +# define UIP_LLH_LEN 14 +#endif /* CONFIG_UIP_LLH_LEN */ + +/*------------------------------------------------------------------------------*/ +/** + * \name CPU architecture configuration + * + * The CPU architecture configuration is where the endianess of the + * CPU on which uIP is to be run is specified. Most CPUs today are + * little endian, and the most notable exception are the Motorolas + * which are big endian. The CONFIG_ENDIAN_BIG macro should be changed + * if uIP is to be run on a big endian architecture. + */ + +/** + * The byte order of the CPU architecture on which uIP is to be run. + * + * This option can be either CONFIG_ENDIAN_BIG (Motorola byte order) or + * default little endian byte order (Intel byte order). + */ + +#define UIP_BIG_ENDIAN 1234 +#define UIP_LITTLE_ENDIAN 3412 + +#ifdef CONFIG_ENDIAN_BIG +# define UIP_BYTE_ORDER UIP_BIG_ENDIAN +#else +# define UIP_BYTE_ORDER UIP_LITTLE_ENDIAN +#endif + +#endif /* __UIPOPT_H__ */ diff --git a/nuttx/net/Makefile b/nuttx/net/Makefile new file mode 100644 index 000000000..5aeacc213 --- /dev/null +++ b/nuttx/net/Makefile @@ -0,0 +1,86 @@ +############################################################ +# Makefile +# +# Copyright (C) 2007 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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. Neither the name Gregory Nutt nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################ + +-include $(TOPDIR)/Make.defs + +MKDEP = $(TOPDIR)/tools/mkdeps.sh + +ifeq ($(CONFIG_NET_UIP),y) +include uip/Make.defs +endif + +ASRCS = $(UIP_ASRCS) +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +CSRCS = $(UIP_CSRCS) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = libnet$(LIBEXT) + +VPATH = uip + +all: $(BIN) + +$(AOBJS): %$(OBJEXT): %.S + $(CC) -c $(CFLAGS) -D__ASSEMBLY__ $< -o $@ + +$(COBJS): %$(OBJEXT): %.c + $(CC) -c $(CFLAGS) $< -o $@ + +$(BIN): $(OBJS) + ( for obj in $(OBJS) ; do \ + $(AR) $@ $${obj} || \ + { echo "$(AR) $@ $obj FAILED!" ; exit 1 ; } ; \ + done ; ) + +.depend: Makefile $(SRCS) +ifeq ($(CONFIG_NET_UIP),y) + $(MKDEP) --dep-path uip $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep +endif + touch $@ + +depend: .depend + +clean: + rm -f $(BIN) *.o *.rel *.asm *.lst *.sym *.adb *~ + if [ ! -z "$(OBJEXT)" ]; then rm -f *$(OBJEXT); fi + +distclean: clean + rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/net/uip/.psock.h.swo b/nuttx/net/uip/.psock.h.swo Binary files differnew file mode 100644 index 000000000..9daa59748 --- /dev/null +++ b/nuttx/net/uip/.psock.h.swo diff --git a/nuttx/net/uip/Make.defs b/nuttx/net/uip/Make.defs new file mode 100644 index 000000000..85d61d0d9 --- /dev/null +++ b/nuttx/net/uip/Make.defs @@ -0,0 +1,38 @@ +############################################################################ +# Make.defs +# +# Copyright (C) 2007 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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. Neither the name Gregory Nutt nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################################ + +UIP_ASRCS = +UIP_CSRCS = psock.c uip-arp.c uip.c uip-fw.c uip-neighbor.c uip-split.c uip-wait.c + diff --git a/nuttx/net/uip/psock.c b/nuttx/net/uip/psock.c new file mode 100644 index 000000000..892c97602 --- /dev/null +++ b/nuttx/net/uip/psock.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels <adam@sics.se> + * + * $Id: psock.c,v 1.1.1.1 2007-08-26 23:04:11 patacongo Exp $ + */ + +#include <stdio.h> +#include <string.h> +#include <pthread.h> +#include <debug.h> + +#include <net/uip/uip.h> +#include <net/uip/uipopt.h> +#include <net/uip/psock.h> + +#define STATE_NONE 0 +#define STATE_ACKED 1 +#define STATE_READ 2 +#define STATE_BLOCKED_NEWDATA 3 +#define STATE_BLOCKED_CLOSE 4 +#define STATE_BLOCKED_SEND 5 +#define STATE_DATA_SENT 6 + +/* + * Return value of the buffering functions that indicates that a + * buffer was not filled by incoming data. + * + */ +#define BUF_NOT_FULL 0 +#define BUF_NOT_FOUND 0 + +/* + * Return value of the buffering functions that indicates that a + * buffer was completely filled by incoming data. + * + */ +#define BUF_FULL 1 + +/* + * Return value of the buffering functions that indicates that an + * end-marker byte was found. + * + */ +#define BUF_FOUND 2 + +static void buf_setup(struct psock_buf *buf, uint8 *bufptr, uint16 bufsize) +{ + buf->ptr = bufptr; + buf->left = bufsize; +} + +static uint8 buf_bufdata(struct psock_buf *buf, uint16 len, uint8 **dataptr, uint16 *datalen) +{ + if (*datalen < buf->left) + { + memcpy(buf->ptr, *dataptr, *datalen); + buf->ptr += *datalen; + buf->left -= *datalen; + *dataptr += *datalen; + *datalen = 0; + return BUF_NOT_FULL; + } + else if (*datalen == buf->left) + { + memcpy(buf->ptr, *dataptr, *datalen); + buf->ptr += *datalen; + buf->left = 0; + *dataptr += *datalen; + *datalen = 0; + return BUF_FULL; + } + else + { + memcpy(buf->ptr, *dataptr, buf->left); + buf->ptr += buf->left; + *datalen -= buf->left; + *dataptr += buf->left; + buf->left = 0; + return BUF_FULL; + } +} + +static uint8 buf_bufto(struct psock_buf *buf, uint8 endmarker, uint8 **dataptr, uint16 *datalen) +{ + uint8 c; + while(buf->left > 0 && *datalen > 0) + { + c = *buf->ptr = **dataptr; + ++*dataptr; + ++buf->ptr; + --*datalen; + --buf->left; + + if (c == endmarker) + { + return BUF_FOUND; + } + } + + if (*datalen == 0) + { + return BUF_NOT_FOUND; + } + + while(*datalen > 0) + { + c = **dataptr; + --*datalen; + ++*dataptr; + + if (c == endmarker) + { + return BUF_FOUND | BUF_FULL; + } + } + + return BUF_FULL; +} + +static boolean send_data(register struct psock *s) +{ + /* Inidicate that we are blocked waiting for the send to complete */ + + s->state = STATE_BLOCKED_SEND; + + /* Loop until we successfully send the data */ + + for (;;) + { + /* If the data has not been sent OR if it needs to be retransmitted, + * then send it now. + */ + + if (s->state != STATE_DATA_SENT || uip_rexmit()) + { + if (s->sendlen > uip_mss()) + { + uip_send(s->sendptr, uip_mss()); + } + else + { + uip_send(s->sendptr, s->sendlen); + } + + s->state = STATE_DATA_SENT; + } + + /* Check if all data has been sent and acknowledged */ + + if (s->state == STATE_DATA_SENT && uip_acked()) + { + /* Yes.. the data has been sent AND acknowledge */ + + if (s->sendlen > uip_mss()) + { + s->sendlen -= uip_mss(); + s->sendptr += uip_mss(); + } + else + { + s->sendptr += s->sendlen; + s->sendlen = 0; + } + + s->state = STATE_ACKED; + return TRUE; + } + + /* No.. then wait on the retransmit or acked events */ + + (void)uip_event_wait(UIP_ACKDATA|UIP_REXMIT); + } + + return FALSE; /* We never get here */ +} + +void psock_send(struct psock *s, const char *buf, unsigned int len) +{ + /* If there is no data to send, we exit immediately. */ + + if (len > 0) + { + /* Save the length of and a pointer to the data that is to be sent. */ + + s->sendptr = (const uint8*)buf; + s->sendlen = len; + s->state = STATE_NONE; + + /* Loop here until all data is sent. The s->sendlen variable is updated + * by the data_sent() function. + */ + + while(s->sendlen > 0) { + + /* Wait until the data has been sent and acknowledged */ + + send_data(s); + } + + /* Done */ + + s->state = STATE_NONE; + } +} + +void psock_generator_send(register struct psock *s, unsigned short (*generate)(void *), void *arg) +{ + /* Ensure that there is a generator function to call. */ + + if (generate != NULL) + { + /* Call the generator function to generate the data in the uip_appdata + * buffer. + */ + + s->sendlen = generate(arg); + s->sendptr = uip_appdata; + s->state = STATE_NONE; + + do + { + /* Call the generator function again if we are called to perform a + * retransmission. + */ + + if (uip_rexmit()) + { + generate(arg); + } + + /* Wait until all data is sent and acknowledged. */ + + send_data(s); + } + while(s->sendlen > 0); + + /* Done */ + + s->state = STATE_NONE; + } +} + +uint16 psock_datalen(struct psock *psock) +{ + return psock->bufsize - psock->buf.left; +} + +boolean psock_checknewdata(struct psock *s) +{ + if (s->readlen > 0) + { + /* There is data in the uip_appdata buffer that has not yet been read + * with the PSOCK_READ functions. + */ + return TRUE; + } + else if (s->state == STATE_READ) + { + /* All data in uip_appdata buffer already consumed. */ + + s->state = STATE_BLOCKED_NEWDATA; + return FALSE; + } + else if (uip_newdata()) + { + /* There is new data that has not been consumed. */ + + return TRUE; + } + else + { + /* There is no new data. */ + + return FALSE; + } +} + +void psock_waitnewdata(struct psock *s) +{ + while (!psock_checknewdata(s)) + { + uip_event_wait(UIP_NEWDATA); + } +} + +void psock_readto(register struct psock *psock, unsigned char c) +{ +restart: + buf_setup(&psock->buf, psock->bufptr, psock->bufsize); + + /* XXX: Should add buf_checkmarker() before do{} loop, if + incoming data has been handled while waiting for a write. */ + + do + { + if (psock->readlen == 0) + { + psock_waitnewdata(psock); + psock->state = STATE_READ; + psock->readptr = (uint8 *)uip_appdata; + psock->readlen = uip_datalen(); + } + } + while((buf_bufto(&psock->buf, c, &psock->readptr, &psock->readlen) & BUF_FOUND) == 0); + + if (psock_datalen(psock) == 0) + { + psock->state = STATE_NONE; + goto restart; + } +} + +void psock_readbuf(register struct psock *psock) +{ +restart: + buf_setup(&psock->buf, psock->bufptr, psock->bufsize); + + /* XXX: Should add buf_checkmarker() before do{} loop, if + incoming data has been handled while waiting for a write. */ + + do + { + if (psock->readlen == 0) + { + psock_waitnewdata(psock); + dbg("Waited for newdata\n"); + psock->state = STATE_READ; + psock->readptr = (uint8 *)uip_appdata; + psock->readlen = uip_datalen(); + } + } + while(buf_bufdata(&psock->buf, psock->bufsize, &psock->readptr, &psock->readlen) != BUF_FULL); + + if (psock_datalen(psock) == 0) + { + psock->state = STATE_NONE; + goto restart; + } +} + +void psock_init(register struct psock *psock, char *buffer, unsigned int buffersize) +{ + psock->state = STATE_NONE; + psock->readlen = 0; + psock->bufptr = (uint8*)buffer; + psock->bufsize = buffersize; + buf_setup(&psock->buf, (uint8*)buffer, buffersize); +} diff --git a/nuttx/net/uip/uip-arp.c b/nuttx/net/uip/uip-arp.c new file mode 100644 index 000000000..f27f5bb2e --- /dev/null +++ b/nuttx/net/uip/uip-arp.c @@ -0,0 +1,405 @@ +/* uip-arp.c + * Implementation of the ARP Address Resolution Protocol. + * Author: Adam Dunkels <adam@dunkels.com> + * + * The Address Resolution Protocol ARP is used for mapping between IP + * addresses and link level addresses such as the Ethernet MAC + * addresses. ARP uses broadcast queries to ask for the link level + * address of a known IP address and the host which is configured with + * the IP address for which the query was meant, will respond with its + * link level address. + * + * Note: This ARP implementation only supports Ethernet. + * + * Copyright (c) 2001-2003, Adam Dunkels. + * 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. + */ + +#include <sys/types.h> +#include <string.h> +#include <net/uip/uip-arp.h> + +struct arp_hdr +{ + struct uip_eth_hdr ethhdr; + uint16 hwtype; + uint16 protocol; + uint8 hwlen; + uint8 protolen; + uint16 opcode; + struct uip_eth_addr shwaddr; + uint16 sipaddr[2]; + struct uip_eth_addr dhwaddr; + uint16 dipaddr[2]; +}; + +struct ethip_hdr { + struct uip_eth_hdr ethhdr; + /* IP header. */ + uint8 vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + uint16 ipchksum; + uint16 srcipaddr[2], + destipaddr[2]; +}; + +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +#define ARP_HWTYPE_ETH 1 + +struct arp_entry { + uint16 ipaddr[2]; + struct uip_eth_addr ethaddr; + uint8 time; +}; + +static const struct uip_eth_addr broadcast_ethaddr = + {{0xff,0xff,0xff,0xff,0xff,0xff}}; +static const uint16 broadcast_ipaddr[2] = {0xffff,0xffff}; + +static struct arp_entry arp_table[UIP_ARPTAB_SIZE]; +static uint16 ipaddr[2]; +static uint8 i, c; + +static uint8 arptime; +static uint8 tmpage; + +#define BUF ((struct arp_hdr *)&uip_buf[0]) +#define IPBUF ((struct ethip_hdr *)&uip_buf[0]) +/*-----------------------------------------------------------------------------------*/ +/** + * Initialize the ARP module. + * + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_init(void) +{ + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + memset(arp_table[i].ipaddr, 0, 4); + } +} +/*-----------------------------------------------------------------------------------*/ +/** + * Periodic ARP processing function. + * + * This function performs periodic timer processing in the ARP module + * and should be called at regular intervals. The recommended interval + * is 10 seconds between the calls. + * + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_timer(void) +{ + struct arp_entry *tabptr; + + ++arptime; + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if((tabptr->ipaddr[0] | tabptr->ipaddr[1]) != 0 && + arptime - tabptr->time >= UIP_ARP_MAXAGE) { + memset(tabptr->ipaddr, 0, 4); + } + } + +} + +/*-----------------------------------------------------------------------------------*/ +static void +uip_arp_update(uint16 *pipaddr, struct uip_eth_addr *ethaddr) +{ + register struct arp_entry *tabptr; + /* Walk through the ARP mapping table and try to find an entry to + update. If none is found, the IP -> MAC address mapping is + inserted in the ARP table. */ + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + + tabptr = &arp_table[i]; + /* Only check those entries that are actually in use. */ + if(tabptr->ipaddr[0] != 0 && + tabptr->ipaddr[1] != 0) { + + /* Check if the source IP address of the incoming packet matches + the IP address in this ARP table entry. */ + if(pipaddr[0] == tabptr->ipaddr[0] && + pipaddr[1] == tabptr->ipaddr[1]) { + + /* An old entry found, update this and return. */ + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); + tabptr->time = arptime; + + return; + } + } + } + + /* If we get here, no existing ARP table entry was found, so we + create one. */ + + /* First, we try to find an unused entry in the ARP table. */ + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if(tabptr->ipaddr[0] == 0 && + tabptr->ipaddr[1] == 0) { + break; + } + } + + /* If no unused entry is found, we try to find the oldest entry and + throw it away. */ + if(i == UIP_ARPTAB_SIZE) { + tmpage = 0; + c = 0; + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if(arptime - tabptr->time > tmpage) { + tmpage = arptime - tabptr->time; + c = i; + } + } + i = c; + tabptr = &arp_table[i]; + } + + /* Now, i is the ARP table entry which we will fill with the new + information. */ + memcpy(tabptr->ipaddr, pipaddr, 4); + memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); + tabptr->time = arptime; +} +/*-----------------------------------------------------------------------------------*/ +/** + * ARP processing for incoming IP packets + * + * This function should be called by the device driver when an IP + * packet has been received. The function will check if the address is + * in the ARP cache, and if so the ARP cache entry will be + * refreshed. If no ARP cache entry was found, a new one is created. + * + * This function expects an IP packet with a prepended Ethernet header + * in the uip_buf[] buffer, and the length of the packet in the global + * variable uip_len. + */ +/*-----------------------------------------------------------------------------------*/ +#if 0 +void +uip_arp_ipin(void) +{ + uip_len -= sizeof(struct uip_eth_hdr); + + /* Only insert/update an entry if the source IP address of the + incoming IP packet comes from a host on the local network. */ + if((IPBUF->srcipaddr[0] & uip_netmask[0]) != + (uip_hostaddr[0] & uip_netmask[0])) { + return; + } + if((IPBUF->srcipaddr[1] & uip_netmask[1]) != + (uip_hostaddr[1] & uip_netmask[1])) { + return; + } + uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src)); + + return; +} +#endif /* 0 */ +/*-----------------------------------------------------------------------------------*/ +/** + * ARP processing for incoming ARP packets. + * + * This function should be called by the device driver when an ARP + * packet has been received. The function will act differently + * depending on the ARP packet type: if it is a reply for a request + * that we previously sent out, the ARP cache will be filled in with + * the values from the ARP reply. If the incoming ARP packet is an ARP + * request for our IP address, an ARP reply packet is created and put + * into the uip_buf[] buffer. + * + * When the function returns, the value of the global variable uip_len + * indicates whether the device driver should send out a packet or + * not. If uip_len is zero, no packet should be sent. If uip_len is + * non-zero, it contains the length of the outbound packet that is + * present in the uip_buf[] buffer. + * + * This function expects an ARP packet with a prepended Ethernet + * header in the uip_buf[] buffer, and the length of the packet in the + * global variable uip_len. + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_arpin(void) +{ + + if(uip_len < sizeof(struct arp_hdr)) { + uip_len = 0; + return; + } + uip_len = 0; + + switch(BUF->opcode) { + case HTONS(ARP_REQUEST): + /* ARP request. If it asked for our address, we send out a + reply. */ + if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { + /* First, we register the one who made the request in our ARP + table, since it is likely that we will do more communication + with this host in the future. */ + uip_arp_update(BUF->sipaddr, &BUF->shwaddr); + + /* The reply opcode is 2. */ + BUF->opcode = HTONS(2); + + memcpy(BUF->dhwaddr.addr, BUF->shwaddr.addr, 6); + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(BUF->ethhdr.dest.addr, BUF->dhwaddr.addr, 6); + + BUF->dipaddr[0] = BUF->sipaddr[0]; + BUF->dipaddr[1] = BUF->sipaddr[1]; + BUF->sipaddr[0] = uip_hostaddr[0]; + BUF->sipaddr[1] = uip_hostaddr[1]; + + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); + uip_len = sizeof(struct arp_hdr); + } + break; + case HTONS(ARP_REPLY): + /* ARP reply. We insert or update the ARP table if it was meant + for us. */ + if(uip_ipaddr_cmp(BUF->dipaddr, uip_hostaddr)) { + uip_arp_update(BUF->sipaddr, &BUF->shwaddr); + } + break; + } + + return; +} +/*-----------------------------------------------------------------------------------*/ +/** + * Prepend Ethernet header to an outbound IP packet and see if we need + * to send out an ARP request. + * + * This function should be called before sending out an IP packet. The + * function checks the destination IP address of the IP packet to see + * what Ethernet MAC address that should be used as a destination MAC + * address on the Ethernet. + * + * If the destination IP address is in the local network (determined + * by logical ANDing of netmask and our IP address), the function + * checks the ARP cache to see if an entry for the destination IP + * address is found. If so, an Ethernet header is prepended and the + * function returns. If no ARP cache entry is found for the + * destination IP address, the packet in the uip_buf[] is replaced by + * an ARP request packet for the IP address. The IP packet is dropped + * and it is assumed that they higher level protocols (e.g., TCP) + * eventually will retransmit the dropped packet. + * + * If the destination IP address is not on the local network, the IP + * address of the default router is used instead. + * + * When the function returns, a packet is present in the uip_buf[] + * buffer, and the length of the packet is in the global variable + * uip_len. + */ +/*-----------------------------------------------------------------------------------*/ +void +uip_arp_out(void) +{ + struct arp_entry *tabptr; + + /* Find the destination IP address in the ARP table and construct + the Ethernet header. If the destination IP addres isn't on the + local network, we use the default router's IP address instead. + + If not ARP table entry is found, we overwrite the original IP + packet with an ARP request for the IP address. */ + + /* First check if destination is a local broadcast. */ + if(uip_ipaddr_cmp(IPBUF->destipaddr, broadcast_ipaddr)) { + memcpy(IPBUF->ethhdr.dest.addr, broadcast_ethaddr.addr, 6); + } else { + /* Check if the destination address is on the local network. */ + if(!uip_ipaddr_maskcmp(IPBUF->destipaddr, uip_hostaddr, uip_netmask)) { + /* Destination address was not on the local network, so we need to + use the default router's IP address instead of the destination + address when determining the MAC address. */ + uip_ipaddr_copy(ipaddr, uip_draddr); + } else { + /* Else, we use the destination IP address. */ + uip_ipaddr_copy(ipaddr, IPBUF->destipaddr); + } + + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { + tabptr = &arp_table[i]; + if(uip_ipaddr_cmp(ipaddr, tabptr->ipaddr)) { + break; + } + } + + if(i == UIP_ARPTAB_SIZE) { + /* The destination address was not in our ARP table, so we + overwrite the IP packet with an ARP request. */ + + memset(BUF->ethhdr.dest.addr, 0xff, 6); + memset(BUF->dhwaddr.addr, 0x00, 6); + memcpy(BUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(BUF->shwaddr.addr, uip_ethaddr.addr, 6); + + uip_ipaddr_copy(BUF->dipaddr, ipaddr); + uip_ipaddr_copy(BUF->sipaddr, uip_hostaddr); + BUF->opcode = HTONS(ARP_REQUEST); /* ARP request. */ + BUF->hwtype = HTONS(ARP_HWTYPE_ETH); + BUF->protocol = HTONS(UIP_ETHTYPE_IP); + BUF->hwlen = 6; + BUF->protolen = 4; + BUF->ethhdr.type = HTONS(UIP_ETHTYPE_ARP); + + uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN]; + + uip_len = sizeof(struct arp_hdr); + return; + } + + /* Build an ethernet header. */ + memcpy(IPBUF->ethhdr.dest.addr, tabptr->ethaddr.addr, 6); + } + memcpy(IPBUF->ethhdr.src.addr, uip_ethaddr.addr, 6); + + IPBUF->ethhdr.type = HTONS(UIP_ETHTYPE_IP); + + uip_len += sizeof(struct uip_eth_hdr); +} +/*-----------------------------------------------------------------------------------*/ + +/** @} */ +/** @} */ diff --git a/nuttx/net/uip/uip-fw.c b/nuttx/net/uip/uip-fw.c new file mode 100644 index 000000000..7e5356f56 --- /dev/null +++ b/nuttx/net/uip/uip-fw.c @@ -0,0 +1,513 @@ +/* uip-fw.c + * uIP packet forwarding. + * Author: Adam Dunkels <adam@sics.se> + * + * This file implements a number of simple functions which do packet + * forwarding over multiple network interfaces with uIP. + * + * Copyright (c) 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + */ + +#include <net/uip/uip.h> +#include <net/uip/uip-arch.h> + +#include "uip-fw.h" + +#include <string.h> /* for memcpy() */ + +/* + * The list of registered network interfaces. + */ +static struct uip_fw_netif *netifs = NULL; + +/* + * A pointer to the default network interface. + */ +static struct uip_fw_netif *defaultnetif = NULL; + +struct tcpip_hdr { + /* IP header. */ + uint8 vhl, + tos; + uint16 len, + ipid, + ipoffset; + uint8 ttl, + proto; + uint16 ipchksum; + uint16 srcipaddr[2], + destipaddr[2]; + + /* TCP header. */ + uint16 srcport, + destport; + uint8 seqno[4], + ackno[4], + tcpoffset, + flags, + wnd[2]; + uint16 tcpchksum; + uint8 urgp[2]; + uint8 optdata[4]; +}; + +struct icmpip_hdr { + /* IP header. */ + uint8 vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + uint16 ipchksum; + uint16 srcipaddr[2], + destipaddr[2]; + /* ICMP (echo) header. */ + uint8 type, icode; + uint16 icmpchksum; + uint16 id, seqno; + uint8 payload[1]; +}; + +/* ICMP ECHO. */ +#define ICMP_ECHO 8 + +/* ICMP TIME-EXCEEDED. */ +#define ICMP_TE 11 + +/* + * Pointer to the TCP/IP headers of the packet in the uip_buf buffer. + */ +#define BUF ((struct tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +/* + * Pointer to the ICMP/IP headers of the packet in the uip_buf buffer. + */ +#define ICMPBUF ((struct icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +/* + * Certain fields of an IP packet that are used for identifying + * duplicate packets. + */ +struct fwcache_entry { + uint16 timer; + + uint16 srcipaddr[2]; + uint16 destipaddr[2]; + uint16 ipid; + uint8 proto; + uint8 unused; + +#if notdef + uint16 payload[2]; +#endif + +#if UIP_REASSEMBLY > 0 + uint16 len, offset; +#endif +}; + +/* + * The number of packets to remember when looking for duplicates. + */ +#ifdef CONFIG_UIP_FWCACHE_SIZE +# define FWCACHE_SIZE CONFIG_UIP_FWCACHE_SIZE +#else +# define FWCACHE_SIZE 2 +#endif + + +/* + * A cache of packet header fields which are used for + * identifying duplicate packets. + */ +static struct fwcache_entry fwcache[FWCACHE_SIZE]; + +/** + * \internal + * The time that a packet cache is active. + */ +#define FW_TIME 20 + +/*------------------------------------------------------------------------------*/ +/** + * Initialize the uIP packet forwarding module. + */ +/*------------------------------------------------------------------------------*/ +void +uip_fw_init(void) +{ + struct uip_fw_netif *t; + defaultnetif = NULL; + while(netifs != NULL) { + t = netifs; + netifs = netifs->next; + t->next = NULL; + } +} +/*------------------------------------------------------------------------------*/ +/** + * \internal + * Check if an IP address is within the network defined by an IP + * address and a netmask. + * + * \param ipaddr The IP address to be checked. + * \param netipaddr The IP address of the network. + * \param netmask The netmask of the network. + * + * \return Non-zero if IP address is in network, zero otherwise. + */ +/*------------------------------------------------------------------------------*/ +static unsigned char +ipaddr_maskcmp(uint16 *ipaddr, uint16 *netipaddr, uint16 *netmask) +{ + return (ipaddr[0] & netmask [0]) == (netipaddr[0] & netmask[0]) && + (ipaddr[1] & netmask[1]) == (netipaddr[1] & netmask[1]); +} +/*------------------------------------------------------------------------------*/ +/** + * \internal + * Send out an ICMP TIME-EXCEEDED message. + * + * This function replaces the packet in the uip_buf buffer with the + * ICMP packet. + */ +/*------------------------------------------------------------------------------*/ +static void +time_exceeded(void) +{ + uint16 tmp16; + + /* We don't send out ICMP errors for ICMP messages. */ + if(ICMPBUF->proto == UIP_PROTO_ICMP) { + uip_len = 0; + return; + } + /* Copy fields from packet header into payload of this ICMP packet. */ + memcpy(&(ICMPBUF->payload[0]), ICMPBUF, 28); + + /* Set the ICMP type and code. */ + ICMPBUF->type = ICMP_TE; + ICMPBUF->icode = 0; + + /* Calculate the ICMP checksum. */ + ICMPBUF->icmpchksum = 0; + ICMPBUF->icmpchksum = ~uip_chksum((uint16 *)&(ICMPBUF->type), 36); + + /* Set the IP destination address to be the source address of the + original packet. */ + tmp16= BUF->destipaddr[0]; + BUF->destipaddr[0] = BUF->srcipaddr[0]; + BUF->srcipaddr[0] = tmp16; + tmp16 = BUF->destipaddr[1]; + BUF->destipaddr[1] = BUF->srcipaddr[1]; + BUF->srcipaddr[1] = tmp16; + + /* Set our IP address as the source address. */ + BUF->srcipaddr[0] = uip_hostaddr[0]; + BUF->srcipaddr[1] = uip_hostaddr[1]; + + /* The size of the ICMP time exceeded packet is 36 + the size of the + IP header (20) = 56. */ + uip_len = 56; + ICMPBUF->len[0] = 0; + ICMPBUF->len[1] = uip_len; + + /* Fill in the other fields in the IP header. */ + ICMPBUF->vhl = 0x45; + ICMPBUF->tos = 0; + ICMPBUF->ipoffset[0] = ICMPBUF->ipoffset[1] = 0; + ICMPBUF->ttl = UIP_TTL; + ICMPBUF->proto = UIP_PROTO_ICMP; + + /* Calculate IP checksum. */ + ICMPBUF->ipchksum = 0; + ICMPBUF->ipchksum = ~(uip_ipchksum()); + + +} +/*------------------------------------------------------------------------------*/ +/** + * \internal + * Register a packet in the forwarding cache so that it won't be + * forwarded again. + */ +/*------------------------------------------------------------------------------*/ +static void +fwcache_register(void) +{ + struct fwcache_entry *fw; + int i, oldest; + + oldest = FW_TIME; + fw = NULL; + + /* Find the oldest entry in the cache. */ + for(i = 0; i < FWCACHE_SIZE; ++i) { + if(fwcache[i].timer == 0) { + fw = &fwcache[i]; + break; + } else if(fwcache[i].timer <= oldest) { + fw = &fwcache[i]; + oldest = fwcache[i].timer; + } + } + + fw->timer = FW_TIME; + fw->ipid = BUF->ipid; + fw->srcipaddr[0] = BUF->srcipaddr[0]; + fw->srcipaddr[1] = BUF->srcipaddr[1]; + fw->destipaddr[0] = BUF->destipaddr[0]; + fw->destipaddr[1] = BUF->destipaddr[1]; + fw->proto = BUF->proto; +#if notdef + fw->payload[0] = BUF->srcport; + fw->payload[1] = BUF->destport; +#endif +#if UIP_REASSEMBLY > 0 + fw->len = BUF->len; + fw->offset = BUF->ipoffset; +#endif +} +/*------------------------------------------------------------------------------*/ +/** + * \internal + * Find a network interface for the IP packet in uip_buf. + */ +/*------------------------------------------------------------------------------*/ +static struct uip_fw_netif * +find_netif(void) +{ + struct uip_fw_netif *netif; + + /* Walk through every network interface to check for a match. */ + for(netif = netifs; netif != NULL; netif = netif->next) { + if(ipaddr_maskcmp(BUF->destipaddr, netif->ipaddr, + netif->netmask)) { + /* If there was a match, we break the loop. */ + return netif; + } + } + + /* If no matching netif was found, we use default netif. */ + return defaultnetif; +} +/*------------------------------------------------------------------------------*/ +/** + * Output an IP packet on the correct network interface. + * + * The IP packet should be present in the uip_buf buffer and its + * length in the global uip_len variable. + * + * \retval UIP_FW_ZEROLEN Indicates that a zero-length packet + * transmission was attempted and that no packet was sent. + * + * \retval UIP_FW_NOROUTE No suitable network interface could be found + * for the outbound packet, and the packet was not sent. + * + * \return The return value from the actual network interface output + * function is passed unmodified as a return value. + */ +/*------------------------------------------------------------------------------*/ +uint8 +uip_fw_output(void) +{ + struct uip_fw_netif *netif; + + if(uip_len == 0) { + return UIP_FW_ZEROLEN; + } + + fwcache_register(); + +#if UIP_BROADCAST + /* Link local broadcasts go out on all interfaces. */ + if(/*BUF->proto == UIP_PROTO_UDP &&*/ + BUF->destipaddr[0] == 0xffff && + BUF->destipaddr[1] == 0xffff) { + if(defaultnetif != NULL) { + defaultnetif->output(); + } + for(netif = netifs; netif != NULL; netif = netif->next) { + netif->output(); + } + return UIP_FW_OK; + } +#endif /* UIP_BROADCAST */ + + netif = find_netif(); + /* printf("uip_fw_output: netif %p ->output %p len %d\n", netif, + netif->output, + uip_len);*/ + + if(netif == NULL) { + return UIP_FW_NOROUTE; + } + /* If we now have found a suitable network interface, we call its + output function to send out the packet. */ + return netif->output(); +} +/*------------------------------------------------------------------------------*/ +/** + * Forward an IP packet in the uip_buf buffer. + * + * + * + * \return UIP_FW_FORWARDED if the packet was forwarded, UIP_FW_LOCAL if + * the packet should be processed locally. + */ +/*------------------------------------------------------------------------------*/ +uint8 +uip_fw_forward(void) +{ + struct fwcache_entry *fw; + + /* First check if the packet is destined for ourselves and return 0 + to indicate that the packet should be processed locally. */ + if(BUF->destipaddr[0] == uip_hostaddr[0] && + BUF->destipaddr[1] == uip_hostaddr[1]) { + return UIP_FW_LOCAL; + } + + /* If we use ping IP address configuration, and our IP address is + not yet configured, we should intercept all ICMP echo packets. */ +#if UIP_PINGADDRCONF + if((uip_hostaddr[0] | uip_hostaddr[1]) == 0 && + BUF->proto == UIP_PROTO_ICMP && + ICMPBUF->type == ICMP_ECHO) { + return UIP_FW_LOCAL; + } +#endif /* UIP_PINGADDRCONF */ + + /* Check if the packet is in the forwarding cache already, and if so + we drop it. */ + + for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) { + if(fw->timer != 0 && +#if UIP_REASSEMBLY > 0 + fw->len == BUF->len && + fw->offset == BUF->ipoffset && +#endif + fw->ipid == BUF->ipid && + fw->srcipaddr[0] == BUF->srcipaddr[0] && + fw->srcipaddr[1] == BUF->srcipaddr[1] && + fw->destipaddr[0] == BUF->destipaddr[0] && + fw->destipaddr[1] == BUF->destipaddr[1] && +#if notdef + fw->payload[0] == BUF->srcport && + fw->payload[1] == BUF->destport && +#endif + fw->proto == BUF->proto) { + /* Drop packet. */ + return UIP_FW_FORWARDED; + } + } + + /* If the TTL reaches zero we produce an ICMP time exceeded message + in the uip_buf buffer and forward that packet back to the sender + of the packet. */ + if(BUF->ttl <= 1) { + /* No time exceeded for broadcasts and multicasts! */ + if(BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff) { + return UIP_FW_LOCAL; + } + time_exceeded(); + } + + /* Decrement the TTL (time-to-live) value in the IP header */ + BUF->ttl = BUF->ttl - 1; + + /* Update the IP checksum. */ + if(BUF->ipchksum >= HTONS(0xffff - 0x0100)) { + BUF->ipchksum = BUF->ipchksum + HTONS(0x0100) + 1; + } else { + BUF->ipchksum = BUF->ipchksum + HTONS(0x0100); + } + + if(uip_len > 0) { + uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN]; + uip_fw_output(); + } + +#if UIP_BROADCAST + if(BUF->destipaddr[0] == 0xffff && BUF->destipaddr[1] == 0xffff) { + return UIP_FW_LOCAL; + } +#endif /* UIP_BROADCAST */ + + /* Return non-zero to indicate that the packet was forwarded and that no + other processing should be made. */ + return UIP_FW_FORWARDED; +} +/*------------------------------------------------------------------------------*/ +/** + * Register a network interface with the forwarding module. + * + * \param netif A pointer to the network interface that is to be + * registered. + */ +/*------------------------------------------------------------------------------*/ +void +uip_fw_register(struct uip_fw_netif *netif) +{ + netif->next = netifs; + netifs = netif; +} +/*------------------------------------------------------------------------------*/ +/** + * Register a default network interface. + * + * All packets that don't go out on any of the other interfaces will + * be routed to the default interface. + * + * \param netif A pointer to the network interface that is to be + * registered. + */ +/*------------------------------------------------------------------------------*/ +void +uip_fw_default(struct uip_fw_netif *netif) +{ + defaultnetif = netif; +} +/*------------------------------------------------------------------------------*/ +/** + * Perform periodic processing. + */ +/*------------------------------------------------------------------------------*/ +void +uip_fw_periodic(void) +{ + struct fwcache_entry *fw; + for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) { + if(fw->timer > 0) { + --fw->timer; + } + } +} +/*------------------------------------------------------------------------------*/ diff --git a/nuttx/net/uip/uip-fw.h b/nuttx/net/uip/uip-fw.h new file mode 100644 index 000000000..cba0bea13 --- /dev/null +++ b/nuttx/net/uip/uip-fw.h @@ -0,0 +1,176 @@ +/** + * \addtogroup uipfw + * @{ + */ + +/** + * \file + * uIP packet forwarding header file. + * \author Adam Dunkels <adam@sics.se> + */ + +/* + * Copyright (c) 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels <adam@sics.se> + * + * $Id: uip-fw.h,v 1.1.1.1 2007-08-26 23:04:07 patacongo Exp $ + */ +#ifndef __UIP_FW_H__ +#define __UIP_FW_H__ + +#include <net/uip/uip.h> + +/** + * Representation of a uIP network interface. + */ +struct uip_fw_netif { + struct uip_fw_netif *next; /**< Pointer to the next interface when + linked in a list. */ + uint16 ipaddr[2]; /**< The IP address of this interface. */ + uint16 netmask[2]; /**< The netmask of the interface. */ + uint8 (* output)(void); + /**< A pointer to the function that + sends a packet. */ +}; + +/** + * Intantiating macro for a uIP network interface. + * + * Example: + \code + struct uip_fw_netif slipnetif = + {UIP_FW_NETIF(192,168,76,1, 255,255,255,0, slip_output)}; + \endcode + * \param ip1,ip2,ip3,ip4 The IP address of the network interface. + * + * \param nm1,nm2,nm3,nm4 The netmask of the network interface. + * + * \param outputfunc A pointer to the output function of the network interface. + * + * \hideinitializer + */ +#define UIP_FW_NETIF(ip1,ip2,ip3,ip4, nm1,nm2,nm3,nm4, outputfunc) \ + NULL, \ + {HTONS((ip1 << 8) | ip2), HTONS((ip3 << 8) | ip4)}, \ + {HTONS((nm1 << 8) | nm2), HTONS((nm3 << 8) | nm4)}, \ + outputfunc + +/** + * Set the IP address of a network interface. + * + * \param netif A pointer to the uip_fw_netif structure for the network interface. + * + * \param addr A pointer to an IP address. + * + * \hideinitializer + */ +#define uip_fw_setipaddr(netif, addr) \ + do { (netif)->ipaddr[0] = ((uint16 *)(addr))[0]; \ + (netif)->ipaddr[1] = ((uint16 *)(addr))[1]; } while(0) +/** + * Set the netmask of a network interface. + * + * \param netif A pointer to the uip_fw_netif structure for the network interface. + * + * \param addr A pointer to an IP address representing the netmask. + * + * \hideinitializer + */ +#define uip_fw_setnetmask(netif, addr) \ + do { (netif)->netmask[0] = ((uint16 *)(addr))[0]; \ + (netif)->netmask[1] = ((uint16 *)(addr))[1]; } while(0) + +void uip_fw_init(void); +uint8 uip_fw_forward(void); +uint8 uip_fw_output(void); +void uip_fw_register(struct uip_fw_netif *netif); +void uip_fw_default(struct uip_fw_netif *netif); +void uip_fw_periodic(void); + + +/** + * A non-error message that indicates that a packet should be + * processed locally. + * + * \hideinitializer + */ +#define UIP_FW_LOCAL 0 + +/** + * A non-error message that indicates that something went OK. + * + * \hideinitializer + */ +#define UIP_FW_OK 0 + +/** + * A non-error message that indicates that a packet was forwarded. + * + * \hideinitializer + */ +#define UIP_FW_FORWARDED 1 + +/** + * A non-error message that indicates that a zero-length packet + * transmission was attempted, and that no packet was sent. + * + * \hideinitializer + */ +#define UIP_FW_ZEROLEN 2 + +/** + * An error message that indicates that a packet that was too large + * for the outbound network interface was detected. + * + * \hideinitializer + */ +#define UIP_FW_TOOLARGE 3 + +/** + * An error message that indicates that no suitable interface could be + * found for an outbound packet. + * + * \hideinitializer + */ +#define UIP_FW_NOROUTE 4 + +/** + * An error message that indicates that a packet that should be + * forwarded or output was dropped. + * + * \hideinitializer + */ +#define UIP_FW_DROPPED 5 + + +#endif /* __UIP_FW_H__ */ + +/** @} */ diff --git a/nuttx/net/uip/uip-neighbor.c b/nuttx/net/uip/uip-neighbor.c new file mode 100644 index 000000000..6da1a891d --- /dev/null +++ b/nuttx/net/uip/uip-neighbor.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2006, 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the uIP TCP/IP stack + * + * $Id: uip-neighbor.c,v 1.1.1.1 2007-08-26 23:04:08 patacongo Exp $ + */ + +/** + * \file + * Database of link-local neighbors, used by IPv6 code and + * to be used by a future ARP code rewrite. + * \author + * Adam Dunkels <adam@sics.se> + */ + +#include "uip-neighbor.h" + +#include <string.h> + +#define MAX_TIME 128 + +#ifdef UIP_NEIGHBOR_CONF_ENTRIES +#define ENTRIES UIP_NEIGHBOR_CONF_ENTRIES +#else /* UIP_NEIGHBOR_CONF_ENTRIES */ +#define ENTRIES 8 +#endif /* UIP_NEIGHBOR_CONF_ENTRIES */ + +struct neighbor_entry { + uip_ipaddr_t ipaddr; + struct uip_neighbor_addr addr; + uint8 time; +}; +static struct neighbor_entry entries[ENTRIES]; + +/*---------------------------------------------------------------------------*/ +void +uip_neighbor_init(void) +{ + int i; + + for(i = 0; i < ENTRIES; ++i) { + entries[i].time = MAX_TIME; + } +} +/*---------------------------------------------------------------------------*/ +void +uip_neighbor_periodic(void) +{ + int i; + + for(i = 0; i < ENTRIES; ++i) { + if(entries[i].time < MAX_TIME) { + entries[i].time++; + } + } +} +/*---------------------------------------------------------------------------*/ +void +uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr) +{ + int i, oldest; + uint8 oldest_time; + + printf("Adding neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n", + addr->addr.addr[0], addr->addr.addr[1], addr->addr.addr[2], addr->addr.addr[3], + addr->addr.addr[4], addr->addr.addr[5]); + + /* Find the first unused entry or the oldest used entry. */ + oldest_time = 0; + oldest = 0; + for(i = 0; i < ENTRIES; ++i) { + if(entries[i].time == MAX_TIME) { + oldest = i; + break; + } + if(uip_ipaddr_cmp(entries[i].ipaddr, addr)) { + oldest = i; + break; + } + if(entries[i].time > oldest_time) { + oldest = i; + oldest_time = entries[i].time; + } + } + + /* Use the oldest or first free entry (either pointed to by the + "oldest" variable). */ + entries[oldest].time = 0; + uip_ipaddr_copy(entries[oldest].ipaddr, ipaddr); + memcpy(&entries[oldest].addr, addr, sizeof(struct uip_neighbor_addr)); +} +/*---------------------------------------------------------------------------*/ +static struct neighbor_entry * +find_entry(uip_ipaddr_t ipaddr) +{ + int i; + + for(i = 0; i < ENTRIES; ++i) { + if(uip_ipaddr_cmp(entries[i].ipaddr, ipaddr)) { + return &entries[i]; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +void +uip_neighbor_update(uip_ipaddr_t ipaddr) +{ + struct neighbor_entry *e; + + e = find_entry(ipaddr); + if(e != NULL) { + e->time = 0; + } +} +/*---------------------------------------------------------------------------*/ +struct uip_neighbor_addr * +uip_neighbor_lookup(uip_ipaddr_t ipaddr) +{ + struct neighbor_entry *e; + + e = find_entry(ipaddr); + if(e != NULL) { + /* printf("Lookup neighbor with link address %02x:%02x:%02x:%02x:%02x:%02x\n", + e->addr.addr.addr[0], e->addr.addr.addr[1], e->addr.addr.addr[2], e->addr.addr.addr[3], + e->addr.addr.addr[4], e->addr.addr.addr[5]);*/ + + return &e->addr; + } + return NULL; +} +/*---------------------------------------------------------------------------*/ diff --git a/nuttx/net/uip/uip-neighbor.h b/nuttx/net/uip/uip-neighbor.h new file mode 100644 index 000000000..277b5f848 --- /dev/null +++ b/nuttx/net/uip/uip-neighbor.h @@ -0,0 +1,54 @@ +/* uip-neighbor.h + * Header file for database of link-local neighbors, used by IPv6 code and + * to be used by future ARP code. + * Author: Adam Dunkels <adam@sics.se> + * + * Copyright (c) 2006, 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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 __UIP_NEIGHBOR_H__ +#define __UIP_NEIGHBOR_H__ + +#include <net/uip/uip.h> + +struct uip_neighbor_addr +{ +#if UIP_NEIGHBOR_CONF_ADDRTYPE + UIP_NEIGHBOR_CONF_ADDRTYPE addr; +#else + struct uip_eth_addr addr; +#endif +}; + +void uip_neighbor_init(void); +void uip_neighbor_add(uip_ipaddr_t ipaddr, struct uip_neighbor_addr *addr); +void uip_neighbor_update(uip_ipaddr_t ipaddr); +struct uip_neighbor_addr *uip_neighbor_lookup(uip_ipaddr_t ipaddr); +void uip_neighbor_periodic(void); + +#endif /* __UIP-NEIGHBOR_H__ */ diff --git a/nuttx/net/uip/uip-split.c b/nuttx/net/uip/uip-split.c new file mode 100644 index 000000000..155418a9c --- /dev/null +++ b/nuttx/net/uip/uip-split.c @@ -0,0 +1,132 @@ +/* uip-split.c + * Author: Adam Dunkels <adam@sics.se> + * + * Copyright (c) 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + */ + +#include <nuttx/config.h> +#include <string.h> + +#include <net/uip/uip.h> +#include <net/uip/uip-arch.h> + +#include "uip-split.h" +#include "uip-fw.h" + +#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +/*-----------------------------------------------------------------------------*/ +void +uip_split_output(void) +{ + uint16 tcplen, len1, len2; + + /* We only try to split maximum sized TCP segments. */ + if(BUF->proto == UIP_PROTO_TCP && + uip_len == UIP_BUFSIZE - UIP_LLH_LEN) { + + tcplen = uip_len - UIP_TCPIP_HLEN; + /* Split the segment in two. If the original packet length was + odd, we make the second packet one byte larger. */ + len1 = len2 = tcplen / 2; + if(len1 + len2 < tcplen) { + ++len2; + } + + /* Create the first packet. This is done by altering the length + field of the IP header and updating the checksums. */ + uip_len = len1 + UIP_TCPIP_HLEN; +#ifdef CONFIG_NET_UIP_IPv6 + /* For IPv6, the IP length field does not include the IPv6 IP header + length. */ + BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); +#else /* CONFIG_NET_UIP_IPv6 */ + BUF->len[0] = uip_len >> 8; + BUF->len[1] = uip_len & 0xff; +#endif /* CONFIG_NET_UIP_IPv6 */ + + /* Recalculate the TCP checksum. */ + BUF->tcpchksum = 0; + BUF->tcpchksum = ~(uip_tcpchksum()); + +#ifndef CONFIG_NET_UIP_IPv6 + /* Recalculate the IP checksum. */ + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); +#endif /* CONFIG_NET_UIP_IPv6 */ + + /* Transmit the first packet. */ + /* uip_fw_output();*/ + tcpip_output(); + + /* Now, create the second packet. To do this, it is not enough to + just alter the length field, but we must also update the TCP + sequence number and point the uip_appdata to a new place in + memory. This place is detemined by the length of the first + packet (len1). */ + uip_len = len2 + UIP_TCPIP_HLEN; +#ifdef CONFIG_NET_UIP_IPv6 + /* For IPv6, the IP length field does not include the IPv6 IP header + length. */ + BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); +#else /* CONFIG_NET_UIP_IPv6 */ + BUF->len[0] = uip_len >> 8; + BUF->len[1] = uip_len & 0xff; +#endif /* CONFIG_NET_UIP_IPv6 */ + + /* uip_appdata += len1;*/ + memcpy(uip_appdata, (uint8 *)uip_appdata + len1, len2); + + uip_add32(BUF->seqno, len1); + BUF->seqno[0] = uip_acc32[0]; + BUF->seqno[1] = uip_acc32[1]; + BUF->seqno[2] = uip_acc32[2]; + BUF->seqno[3] = uip_acc32[3]; + + /* Recalculate the TCP checksum. */ + BUF->tcpchksum = 0; + BUF->tcpchksum = ~(uip_tcpchksum()); + +#ifndef CONFIG_NET_UIP_IPv6 + /* Recalculate the IP checksum. */ + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); +#endif /* CONFIG_NET_UIP_IPv6 */ + + /* Transmit the second packet. */ + /* uip_fw_output();*/ + tcpip_output(); + } else { + /* uip_fw_output();*/ + tcpip_output(); + } + +} +/*-----------------------------------------------------------------------------*/ diff --git a/nuttx/net/uip/uip-split.h b/nuttx/net/uip/uip-split.h new file mode 100644 index 000000000..99f36ccdb --- /dev/null +++ b/nuttx/net/uip/uip-split.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the uIP TCP/IP stack + * + * Author: Adam Dunkels <adam@sics.se> + * + * $Id: uip-split.h,v 1.1.1.1 2007-08-26 23:04:08 patacongo Exp $ + */ +/** + * \addtogroup uip + * @{ + */ + +/** + * \defgroup uipsplit uIP TCP throughput booster hack + * @{ + * + * The basic uIP TCP implementation only allows each TCP connection to + * have a single TCP segment in flight at any given time. Because of + * the delayed ACK algorithm employed by most TCP receivers, uIP's + * limit on the amount of in-flight TCP segments seriously reduces the + * maximum achievable throughput for sending data from uIP. + * + * The uip-split module is a hack which tries to remedy this + * situation. By splitting maximum sized outgoing TCP segments into + * two, the delayed ACK algorithm is not invoked at TCP + * receivers. This improves the throughput when sending data from uIP + * by orders of magnitude. + * + * The uip-split module uses the uip-fw module (uIP IP packet + * forwarding) for sending packets. Therefore, the uip-fw module must + * be set up with the appropriate network interfaces for this module + * to work. + */ + + +/** + * \file + * Module for splitting outbound TCP segments in two to avoid the + * delayed ACK throughput degradation. + * \author + * Adam Dunkels <adam@sics.se> + * + */ + +#ifndef __UIP_SPLIT_H__ +#define __UIP_SPLIT_H__ + +/** + * Handle outgoing packets. + * + * This function inspects an outgoing packet in the uip_buf buffer and + * sends it out using the uip_fw_output() function. If the packet is a + * full-sized TCP segment it will be split into two segments and + * transmitted separately. This function should be called instead of + * the actual device driver output function, or the uip_fw_output() + * function. + * + * The headers of the outgoing packet is assumed to be in the uip_buf + * buffer and the payload is assumed to be wherever uip_appdata + * points. The length of the outgoing packet is assumed to be in the + * uip_len variable. + * + */ +void uip_split_output(void); + +#endif /* __UIP_SPLIT_H__ */ + +/** @} */ +/** @} */ diff --git a/nuttx/net/uip/uip-wait.c b/nuttx/net/uip/uip-wait.c new file mode 100644 index 000000000..c7bf0a1bb --- /dev/null +++ b/nuttx/net/uip/uip-wait.c @@ -0,0 +1,180 @@ +/************************************************************ + * uip-wait.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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. + * + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include <nuttx/config.h> +#include <semaphore.h> +#include <wdog.h> +#include <arch/irq.h> +#include <net/uip/uip.h> + +/************************************************************ + * Definitions + ************************************************************/ + +/************************************************************ + * Private Data + ************************************************************/ + +/* Threads and tasks can both wait a semaphore. This + * initializer uses internal, non-portable knowledge of the\ + * structure of sem_t to initialize it to the value 0. + */ + +static sem_t uip_waitsem = { 0 }; /* Semaphore to wait on */ +static uint16 uip_waitflags = 0; /* UIP flags to wait for */ + +/************************************************************ + * Private Functions + ************************************************************/ + +/* Called from the timer interrupt handler when a event wait + * watchdog expires. + */ + +static void uip_event_timeout(int argc, uint32 itcb, ...) +{ + irqstate_t save = irqsave(); /* Should not be necessary */ + uip_flags |= UIP_APPTIMEOUT; /* Set software timeout event */ + uip_event_signal(); /* Signal the waiting thread/task */ + irqrestore(save); /* Restore interrupts */ +} + +/************************************************************ + * Global Functions + ************************************************************/ + +/* This function is called user code to set up the wait */ + +int uip_event_timedwait(uint16 waitflags, int timeout) +{ + /* Prevent conflicts with the interrupt level operation of + * uip_event_signal(). + */ + irqstate_t save = irqsave(); + WDOG_ID wdog; + + /* At present, we support only a single waiter. If uip_waitflags + * is non-zero on entry, then there is a problem. + */ + + if ( uip_waitflags == 0) + { + /* If the requested event bits are not set in the uip_flags, + * then wait. We will be awakened as soon as an interrupt is + * received that sets these bits. + */ + + goto errout_with_irqdisabled; + } + + /* Loop until the requested bits are set in the flags */ + + while ((waitflags & uip_flags) != 0) + { + /* Set the event flags that the caller is waiting on */ + + uip_waitflags = waitflags; + + /* Was a timeut requested as well? */ + + if (timeout) + { + /* Yes, then set the application timeout event as well */ + + uip_waitflags |= UIP_APPTIMEOUT; + + /* Create a watchdog */ + + wdog = wd_create(); + if (!wdog) + { + goto errout_with_irqdisabled; + } + + /* Start the watchdog */ + + wd_start(wdog, timeout, (wdentry_t)uip_event_timeout, 0); + } + + /* Wait for the event (or timeout) to occur */ + + if (sem_wait(&uip_waitsem) != 0) + { + goto errout_with_watchdog; + } + + /* We no longer need the watchdog */ + + if (wdog) + { + wd_delete(wdog); + wdog = NULL; + } + } + + irqrestore(save); + return OK; + +errout_with_watchdog: + if (wdog) + { + wd_delete(wdog); + } + +errout_with_irqdisabled: + irqrestore(save); + return ERROR; +} + +/* This function is called from uip_interrupt() to wake up any + * waiting threads/tasks. + */ + +void uip_event_signal(void) +{ + /* If any bits in uip_waitflags match bits set in uip_flags, then + * there must be a thread/task waiting for this event to occur. + */ + + if ((uip_waitflags & uip_flags) != 0) + { + sem_post(&uip_waitsem); /* Post the event */ + uip_waitflags = 0; /* Prohibit posting the event multiple times */ + } +} diff --git a/nuttx/net/uip/uip.c b/nuttx/net/uip/uip.c new file mode 100644 index 000000000..b81c85cd9 --- /dev/null +++ b/nuttx/net/uip/uip.c @@ -0,0 +1,2091 @@ +/**************************************************************************** + * uip.c + * The uIP TCP/IP stack code. + * author Adam Dunkels <adam@dunkels.com> + * + * uIP is an implementation of the TCP/IP protocol stack intended for + * small 8-bit and 16-bit microcontrollers. + * + * uIP provides the necessary protocols for Internet communication, + * with a very small code footprint and RAM requirements - the uIP + * code size is on the order of a few kilobytes and RAM usage is on + * the order of a few hundred bytes. + * + * Copyright (c) 2001-2003, Adam Dunkels. + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * uIP is a small implementation of the IP, UDP and TCP protocols (as + * well as some basic ICMP stuff). The implementation couples the IP, + * UDP, TCP and the application layers very tightly. To keep the size + * of the compiled code down, this code frequently uses the goto + * statement. While it would be possible to break the uip_interrupt() + * function into many smaller functions, this would increase the code + * size because of the overhead of parameter passing and the fact that + * the optimier would not be as efficient. + * + * The principle is that we have a small buffer, called the uip_buf, + * in which the device driver puts an incoming packet. The TCP/IP + * stack parses the headers in the packet, and calls the + * application. If the remote host has sent data to the application, + * this data is present in the uip_buf and the application read the + * data from there. It is up to the application to put this data into + * a byte stream if needed. The application will not be fed with data + * that is out of sequence. + * + * If the application whishes to send data to the peer, it should put + * its data into the uip_buf. The uip_appdata pointer points to the + * first available byte. The TCP/IP stack will calculate the + * checksums, and fill in the necessary header fields and finally send + * the packet back to the peer. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <sys/types.h> +#include <debug.h> + +#include <net/uip/uipopt.h> +#include <net/uip/uip.h> +#include <net/uip/uip-arch.h> + +#ifdef CONFIG_NET_UIP_IPv6 +# include "uip-neighbor.h" +#endif /* CONFIG_NET_UIP_IPv6 */ + +#include <string.h> + +#if UIP_LOGGING == 1 +#include <stdio.h> +extern void uip_log(char *msg); +# define UIP_LOG(m) uip_log(m) +#else +# define UIP_LOG(m) +#endif /* UIP_LOGGING == 1 */ + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +#define TCP_FIN 0x01 +#define TCP_SYN 0x02 +#define TCP_RST 0x04 +#define TCP_PSH 0x08 +#define TCP_ACK 0x10 +#define TCP_URG 0x20 +#define TCP_CTL 0x3f + +#define TCP_OPT_END 0 /* End of TCP options list */ +#define TCP_OPT_NOOP 1 /* "No-operation" TCP option */ +#define TCP_OPT_MSS 2 /* Maximum segment size TCP option */ + +#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */ + +#define ICMP_ECHO_REPLY 0 +#define ICMP_ECHO 8 + +#define ICMP6_ECHO_REPLY 129 +#define ICMP6_ECHO 128 +#define ICMP6_NEIGHBOR_SOLICITATION 135 +#define ICMP6_NEIGHBOR_ADVERTISEMENT 136 + +#define ICMP6_FLAG_S (1 << 6) + +#define ICMP6_OPTION_SOURCE_LINK_ADDRESS 1 +#define ICMP6_OPTION_TARGET_LINK_ADDRESS 2 + +/* Macros. */ +#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0]) +#define ICMPBUF ((struct uip_icmpip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UDPBUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) + +/**************************************************************************** + * Public Variables + ****************************************************************************/ + +/* The IP address of this host. If it is defined to be fixed (by + setting UIP_FIXEDADDR to 1 in uipopt.h), the address is set + here. Otherwise, the address */ +#if UIP_FIXEDADDR > 0 +const uip_ipaddr_t uip_hostaddr = + {HTONS((UIP_IPADDR0 << 8) | UIP_IPADDR1), + HTONS((UIP_IPADDR2 << 8) | UIP_IPADDR3)}; + +const uip_ipaddr_t uip_draddr = + {HTONS((UIP_DRIPADDR0 << 8) | UIP_DRIPADDR1), + HTONS((UIP_DRIPADDR2 << 8) | UIP_DRIPADDR3)}; + +const uip_ipaddr_t uip_netmask = + {HTONS((UIP_NETMASK0 << 8) | UIP_NETMASK1), + HTONS((UIP_NETMASK2 << 8) | UIP_NETMASK3)}; +#else +uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask; +#endif /* UIP_FIXEDADDR */ + +#ifndef CONFIG_UIP_EXTERNAL_BUFFER +uint8 uip_buf[UIP_BUFSIZE + 2]; /* The packet buffer that contains incoming packets. */ +#endif /* CONFIG_UIP_EXTERNAL_BUFFER */ + +void *uip_appdata; /* The uip_appdata pointer points to application data. */ +void *uip_sappdata; /* The uip_appdata pointer points to the application + * data which is to be sent. */ +#if UIP_URGDATA > 0 +void *uip_urgdata; /* The uip_urgdata pointer points to urgent data + * (out-of-band data), if present. */ +uint16 uip_urglen, uip_surglen; +#endif /* UIP_URGDATA > 0 */ + +uint16 uip_len, uip_slen; /* The uip_len is either 8 or 16 bits, depending + * on the maximum packet size. */ + +uint16 uip_flags; /* The uip_flags variable is used for communication + * between the TCP/IP stack and the application + * program. */ +struct uip_conn *uip_conn; /* uip_conn always points to the current connection. */ + +struct uip_conn uip_conns[UIP_CONNS]; + /* The uip_conns array holds all TCP connections. */ +uint16 uip_listenports[UIP_LISTENPORTS]; + /* The uip_listenports list all currently listning ports. */ +#if UIP_UDP +struct uip_udp_conn *uip_udp_conn; +struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; +#endif /* UIP_UDP */ + +/* Temporary variables. */ +uint8 uip_acc32[4]; + +#if UIP_STATISTICS == 1 +struct uip_stats uip_stat; +# define UIP_STAT(s) s +#else +# define UIP_STAT(s) +#endif /* UIP_STATISTICS == 1 */ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +static const uip_ipaddr_t all_ones_addr = +#ifdef CONFIG_NET_UIP_IPv6 + {0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff}; +#else /* CONFIG_NET_UIP_IPv6 */ + {0xffff,0xffff}; +#endif /* CONFIG_NET_UIP_IPv6 */ + +static const uip_ipaddr_t all_zeroes_addr = +#ifdef CONFIG_NET_UIP_IPv6 + {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}; +#else /* CONFIG_NET_UIP_IPv6 */ + {0x0000,0x0000}; +#endif /* CONFIG_NET_UIP_IPv6 */ + +#if UIP_FIXEDETHADDR +const struct uip_eth_addr uip_ethaddr = +{{ UIP_ETHADDR0, UIP_ETHADDR1, UIP_ETHADDR2, UIP_ETHADDR3, UIP_ETHADDR4, UIP_ETHADDR5 }}; +#else +struct uip_eth_addr uip_ethaddr = {{ 0,0,0,0,0,0 }}; +#endif + +static uint16 ipid; /* Ths ipid variable is an increasing number that is + * used for the IP ID field. */ + +static uint8 iss[4]; /* The iss variable is used for the TCP initial + * sequence number. */ + +#if UIP_ACTIVE_OPEN +static uint16 lastport; /* Keeps track of the last port used for a new + * connection. */ +#endif /* UIP_ACTIVE_OPEN */ + +/* Temporary variables. */ +static uint8 c, opt; +static uint16 tmp16; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#if !UIP_ARCH_ADD32 +static void uip_add32(uint8 *op32, uint16 op16) +{ + uip_acc32[3] = op32[3] + (op16 & 0xff); + uip_acc32[2] = op32[2] + (op16 >> 8); + uip_acc32[1] = op32[1]; + uip_acc32[0] = op32[0]; + + if (uip_acc32[2] < (op16 >> 8)) { + ++uip_acc32[1]; + if (uip_acc32[1] == 0) { + ++uip_acc32[0]; + } + } + + if (uip_acc32[3] < (op16 & 0xff)) { + ++uip_acc32[2]; + if (uip_acc32[2] == 0) { + ++uip_acc32[1]; + if (uip_acc32[1] == 0) { + ++uip_acc32[0]; + } + } + } +} +#endif /* UIP_ARCH_ADD32 */ + +#if !UIP_ARCH_CHKSUM +static uint16 chksum(uint16 sum, const uint8 *data, uint16 len) +{ + uint16 t; + const uint8 *dataptr; + const uint8 *last_byte; + + dataptr = data; + last_byte = data + len - 1; + + while(dataptr < last_byte) { + /* At least two more bytes */ + t = (dataptr[0] << 8) + dataptr[1]; + sum += t; + if (sum < t) { + sum++; /* carry */ + } + dataptr += 2; + } + + if (dataptr == last_byte) { + t = (dataptr[0] << 8) + 0; + sum += t; + if (sum < t) { + sum++; /* carry */ + } + } + + /* Return sum in host byte order. */ + return sum; +} + +static uint16 upper_layer_chksum(uint8 proto) +{ + uint16 upper_layer_len; + uint16 sum; + +#ifdef CONFIG_NET_UIP_IPv6 + upper_layer_len = (((uint16)(BUF->len[0]) << 8) + BUF->len[1]); +#else /* CONFIG_NET_UIP_IPv6 */ + upper_layer_len = (((uint16)(BUF->len[0]) << 8) + BUF->len[1]) - UIP_IPH_LEN; +#endif /* CONFIG_NET_UIP_IPv6 */ + + /* First sum pseudoheader. */ + + /* IP protocol and length fields. This addition cannot carry. */ + sum = upper_layer_len + proto; + + /* Sum IP source and destination addresses. */ + sum = chksum(sum, (uint8 *)&BUF->srcipaddr[0], 2 * sizeof(uip_ipaddr_t)); + + /* Sum TCP header and data. */ + sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN], upper_layer_len); + + return (sum == 0) ? 0xffff : htons(sum); +} + +#ifdef CONFIG_NET_UIP_IPv6 +static uint16 uip_icmp6chksum(void) +{ + return upper_layer_chksum(UIP_PROTO_ICMP6); +} +#endif /* CONFIG_NET_UIP_IPv6 */ + +#endif /* UIP_ARCH_CHKSUM */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/* This function may be used at boot time to set the initial ip_id.*/ + +void uip_setipid(uint16 id) +{ + ipid = id; +} + +/* Calculate the Internet checksum over a buffer. */ + +#if !UIP_ARCH_CHKSUM +uint16 uip_chksum(uint16 *data, uint16 len) +{ + return htons(chksum(0, (uint8 *)data, len)); +} + +/* Calculate the IP header checksum of the packet header in uip_buf. */ + +#ifndef UIP_ARCH_IPCHKSUM +uint16 uip_ipchksum(void) +{ + uint16 sum; + + sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN); + dbg("uip_ipchksum: sum 0x%04x\n", sum); + return (sum == 0) ? 0xffff : htons(sum); +} +#endif + +/* Calculate the TCP checksum of the packet in uip_buf and uip_appdata. */ + +uint16 uip_tcpchksum(void) +{ + return upper_layer_chksum(UIP_PROTO_TCP); +} + +/* Calculate the UDP checksum of the packet in uip_buf and uip_appdata. */ + +#if UIP_UDP_CHECKSUMS +uint16 uip_udpchksum(void) +{ + return upper_layer_chksum(UIP_PROTO_UDP); +} +#endif /* UIP_UDP_CHECKSUMS */ +#endif /* UIP_ARCH_CHKSUM */ + +void uip_init(void) +{ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + uip_listenports[c] = 0; + } + for(c = 0; c < UIP_CONNS; ++c) { + uip_conns[c].tcpstateflags = UIP_CLOSED; + } +#if UIP_ACTIVE_OPEN + lastport = 1024; +#endif /* UIP_ACTIVE_OPEN */ + +#if UIP_UDP + for(c = 0; c < UIP_UDP_CONNS; ++c) { + uip_udp_conns[c].lport = 0; + } +#endif /* UIP_UDP */ + + /* IPv4 initialization. */ +#if UIP_FIXEDADDR == 0 + /* uip_hostaddr[0] = uip_hostaddr[1] = 0;*/ +#endif /* UIP_FIXEDADDR */ + +} + +#if UIP_ACTIVE_OPEN +struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, uint16 rport) +{ + register struct uip_conn *conn, *cconn; + + /* Find an unused local port. */ + again: + ++lastport; + + if (lastport >= 32000) { + lastport = 4096; + } + + /* Check if this port is already in use, and if so try to find + another one. */ + for(c = 0; c < UIP_CONNS; ++c) { + conn = &uip_conns[c]; + if (conn->tcpstateflags != UIP_CLOSED && + conn->lport == htons(lastport)) { + goto again; + } + } + + conn = 0; + for(c = 0; c < UIP_CONNS; ++c) { + cconn = &uip_conns[c]; + if (cconn->tcpstateflags == UIP_CLOSED) { + conn = cconn; + break; + } + if (cconn->tcpstateflags == UIP_TIME_WAIT) { + if (conn == 0 || cconn->timer > conn->timer) { + conn = cconn; + } + } + } + + if (conn == 0) { + return 0; + } + + conn->tcpstateflags = UIP_SYN_SENT; + + conn->snd_nxt[0] = iss[0]; + conn->snd_nxt[1] = iss[1]; + conn->snd_nxt[2] = iss[2]; + conn->snd_nxt[3] = iss[3]; + + conn->initialmss = conn->mss = UIP_TCP_MSS; + + conn->len = 1; /* TCP length of the SYN is one. */ + conn->nrtx = 0; + conn->timer = 1; /* Send the SYN next time around. */ + conn->rto = UIP_RTO; + conn->sa = 0; + conn->sv = 16; /* Initial value of the RTT variance. */ + conn->lport = htons(lastport); + conn->rport = rport; + uip_ipaddr_copy(&conn->ripaddr, ripaddr); + + return conn; +} +#endif /* UIP_ACTIVE_OPEN */ + +#if UIP_UDP +struct uip_udp_conn * +uip_udp_new(uip_ipaddr_t *ripaddr, uint16 rport) +{ + register struct uip_udp_conn *conn; + + /* Find an unused local port. */ + again: + ++lastport; + + if (lastport >= 32000) { + lastport = 4096; + } + + for(c = 0; c < UIP_UDP_CONNS; ++c) { + if (uip_udp_conns[c].lport == htons(lastport)) { + goto again; + } + } + + + conn = 0; + for(c = 0; c < UIP_UDP_CONNS; ++c) { + if (uip_udp_conns[c].lport == 0) { + conn = &uip_udp_conns[c]; + break; + } + } + + if (conn == 0) { + return 0; + } + + conn->lport = HTONS(lastport); + conn->rport = rport; + if (ripaddr == NULL) { + memset(conn->ripaddr, 0, sizeof(uip_ipaddr_t)); + } else { + uip_ipaddr_copy(&conn->ripaddr, ripaddr); + } + conn->ttl = UIP_TTL; + + return conn; +} +#endif /* UIP_UDP */ + +void uip_unlisten(uint16 port) +{ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + if (uip_listenports[c] == port) { + uip_listenports[c] = 0; + return; + } + } +} + +void uip_listen(uint16 port) +{ + for(c = 0; c < UIP_LISTENPORTS; ++c) { + if (uip_listenports[c] == 0) { + uip_listenports[c] = port; + return; + } + } +} + +/* XXX: IP fragment reassembly: not well-tested. */ + +#if UIP_REASSEMBLY && !defined(CONFIG_NET_UIP_IPv6) +#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN) +static uint8 uip_reassbuf[UIP_REASS_BUFSIZE]; +static uint8 uip_reassbitmap[UIP_REASS_BUFSIZE / (8 * 8)]; +static const uint8 bitmap_bits[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01}; +static uint16 uip_reasslen; +static uint8 uip_reassflags; +#define UIP_REASS_FLAG_LASTFRAG 0x01 +static uint8 uip_reasstmr; + +#define IP_MF 0x20 + +static uint8 uip_reass(void) +{ + uint16 offset, len; + uint16 i; + + /* If ip_reasstmr is zero, no packet is present in the buffer, so we + write the IP header of the fragment into the reassembly + buffer. The timer is updated with the maximum age. */ + if (uip_reasstmr == 0) { + memcpy(uip_reassbuf, &BUF->vhl, UIP_IPH_LEN); + uip_reasstmr = UIP_REASS_MAXAGE; + uip_reassflags = 0; + /* Clear the bitmap. */ + memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap)); + } + + /* Check if the incoming fragment matches the one currently present + in the reasembly buffer. If so, we proceed with copying the + fragment into the buffer. */ + if (BUF->srcipaddr[0] == FBUF->srcipaddr[0] && + BUF->srcipaddr[1] == FBUF->srcipaddr[1] && + BUF->destipaddr[0] == FBUF->destipaddr[0] && + BUF->destipaddr[1] == FBUF->destipaddr[1] && + BUF->ipid[0] == FBUF->ipid[0] && + BUF->ipid[1] == FBUF->ipid[1]) { + + len = (BUF->len[0] << 8) + BUF->len[1] - (BUF->vhl & 0x0f) * 4; + offset = (((BUF->ipoffset[0] & 0x3f) << 8) + BUF->ipoffset[1]) * 8; + + /* If the offset or the offset + fragment length overflows the + reassembly buffer, we discard the entire packet. */ + if (offset > UIP_REASS_BUFSIZE || + offset + len > UIP_REASS_BUFSIZE) { + uip_reasstmr = 0; + goto nullreturn; + } + + /* Copy the fragment into the reassembly buffer, at the right + offset. */ + memcpy(&uip_reassbuf[UIP_IPH_LEN + offset], + (char *)BUF + (int)((BUF->vhl & 0x0f) * 4), + len); + + /* Update the bitmap. */ + if (offset / (8 * 8) == (offset + len) / (8 * 8)) { + /* If the two endpoints are in the same byte, we only update + that byte. */ + + uip_reassbitmap[offset / (8 * 8)] |= + bitmap_bits[(offset / 8 ) & 7] & + ~bitmap_bits[((offset + len) / 8 ) & 7]; + } else { + /* If the two endpoints are in different bytes, we update the + bytes in the endpoints and fill the stuff inbetween with + 0xff. */ + uip_reassbitmap[offset / (8 * 8)] |= + bitmap_bits[(offset / 8 ) & 7]; + for(i = 1 + offset / (8 * 8); i < (offset + len) / (8 * 8); ++i) { + uip_reassbitmap[i] = 0xff; + } + uip_reassbitmap[(offset + len) / (8 * 8)] |= + ~bitmap_bits[((offset + len) / 8 ) & 7]; + } + + /* If this fragment has the More Fragments flag set to zero, we + know that this is the last fragment, so we can calculate the + size of the entire packet. We also set the + IP_REASS_FLAG_LASTFRAG flag to indicate that we have received + the final fragment. */ + + if ((BUF->ipoffset[0] & IP_MF) == 0) { + uip_reassflags |= UIP_REASS_FLAG_LASTFRAG; + uip_reasslen = offset + len; + } + + /* Finally, we check if we have a full packet in the buffer. We do + this by checking if we have the last fragment and if all bits + in the bitmap are set. */ + if (uip_reassflags & UIP_REASS_FLAG_LASTFRAG) { + /* Check all bytes up to and including all but the last byte in + the bitmap. */ + for(i = 0; i < uip_reasslen / (8 * 8) - 1; ++i) { + if (uip_reassbitmap[i] != 0xff) { + goto nullreturn; + } + } + + /* Check the last byte in the bitmap. It should contain just the + right amount of bits. */ + if (uip_reassbitmap[uip_reasslen / (8 * 8)] != + (uint8)~bitmap_bits[uip_reasslen / 8 & 7]) { + goto nullreturn; + } + + /* If we have come this far, we have a full packet in the + buffer, so we allocate a pbuf and copy the packet into it. We + also reset the timer. */ + uip_reasstmr = 0; + memcpy(BUF, FBUF, uip_reasslen); + + /* Pretend to be a "normal" (i.e., not fragmented) IP packet + from now on. */ + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; + BUF->len[0] = uip_reasslen >> 8; + BUF->len[1] = uip_reasslen & 0xff; + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); + + return uip_reasslen; + } + } + + nullreturn: + return 0; +} +#endif /* UIP_REASSEMBLY */ + +static void uip_add_rcv_nxt(uint16 n) +{ + uip_add32(uip_conn->rcv_nxt, n); + uip_conn->rcv_nxt[0] = uip_acc32[0]; + uip_conn->rcv_nxt[1] = uip_acc32[1]; + uip_conn->rcv_nxt[2] = uip_acc32[2]; + uip_conn->rcv_nxt[3] = uip_acc32[3]; +} + +void uip_interrupt(uint8 flag) +{ + register struct uip_conn *uip_connr = uip_conn; + +#if UIP_UDP + if (flag == UIP_UDP_SEND_CONN) + { + goto udp_send; + } +#endif /* UIP_UDP */ + + uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN]; + + /* Check if we were invoked because of a poll request for a + * particular connection. + */ + + if (flag == UIP_POLL_REQUEST) + { + if ((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED && + !uip_outstanding(uip_connr)) + { + uip_flags = UIP_POLL; + uip_event_signal(); + uip_interrupt_event(); + goto appsend; + } + goto drop; + } + + /* Check if we were invoked because of the perodic timer fireing. */ + + else if (flag == UIP_TIMER) + { +#if UIP_REASSEMBLY + if (uip_reasstmr != 0) + { + --uip_reasstmr; + } +#endif /* UIP_REASSEMBLY */ + + /* Increase the initial sequence number */ + + if (++iss[3] == 0) + { + if (++iss[2] == 0) + { + if (++iss[1] == 0) + { + ++iss[0]; + } + } + } + + /* Reset the length variables. */ + + uip_len = 0; + uip_slen = 0; + + /* Check if the connection is in a state in which we simply wait + * for the connection to time out. If so, we increase the + * connection's timer and remove the connection if it times + * out. + */ + + if (uip_connr->tcpstateflags == UIP_TIME_WAIT || + uip_connr->tcpstateflags == UIP_FIN_WAIT_2) + { + ++(uip_connr->timer); + if (uip_connr->timer == UIP_TIME_WAIT_TIMEOUT) + { + uip_connr->tcpstateflags = UIP_CLOSED; + } + } + else if (uip_connr->tcpstateflags != UIP_CLOSED) + { + /* If the connection has outstanding data, we increase the + * connection's timer and see if it has reached the RTO value + * in which case we retransmit. + */ + + if (uip_outstanding(uip_connr)) + { + if (uip_connr->timer-- == 0) + { + if (uip_connr->nrtx == UIP_MAXRTX || + ((uip_connr->tcpstateflags == UIP_SYN_SENT || + uip_connr->tcpstateflags == UIP_SYN_RCVD) && + uip_connr->nrtx == UIP_MAXSYNRTX)) + { + uip_connr->tcpstateflags = UIP_CLOSED; + + /* We call uip_interrupt_event() with uip_flags set to + * UIP_TIMEDOUT to inform the application that the + * connection has timed out. + */ + + uip_flags = UIP_TIMEDOUT; + uip_event_signal(); + uip_interrupt_event(); + + /* We also send a reset packet to the remote host. */ + + BUF->flags = TCP_RST | TCP_ACK; + goto tcp_send_nodata; + } + + /* Exponential backoff. */ + + uip_connr->timer = UIP_RTO << (uip_connr->nrtx > 4 ? 4: uip_connr->nrtx); + ++(uip_connr->nrtx); + + /* Ok, so we need to retransmit. We do this differently + * depending on which state we are in. In ESTABLISHED, we + * call upon the application so that it may prepare the + * data for the retransmit. In SYN_RCVD, we resend the + * SYNACK that we sent earlier and in LAST_ACK we have to + * retransmit our FINACK. + */ + + UIP_STAT(++uip_stat.tcp.rexmit); + switch(uip_connr->tcpstateflags & UIP_TS_MASK) + { + case UIP_SYN_RCVD: + /* In the SYN_RCVD state, we should retransmit our + * SYNACK. + */ + + goto tcp_send_synack; + +#if UIP_ACTIVE_OPEN + case UIP_SYN_SENT: + /* In the SYN_SENT state, we retransmit out SYN. */ + BUF->flags = 0; + goto tcp_send_syn; +#endif /* UIP_ACTIVE_OPEN */ + + case UIP_ESTABLISHED: + /* In the ESTABLISHED state, we call upon the application + * to do the actual retransmit after which we jump into + * the code for sending out the packet (the apprexmit + * label). + */ + + uip_flags = UIP_REXMIT; + uip_event_signal(); + uip_interrupt_event(); + goto apprexmit; + + case UIP_FIN_WAIT_1: + case UIP_CLOSING: + case UIP_LAST_ACK: + /* In all these states we should retransmit a FINACK. */ + goto tcp_send_finack; + + } + } + } + else if ((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) + { + /* If there was no need for a retransmission, we poll the + * application for new data. + */ + + uip_flags = UIP_POLL; + uip_event_signal(); + uip_interrupt_event(); + goto appsend; + } + } + goto drop; + } + +#if UIP_UDP + if (flag == UIP_UDP_TIMER) + { + if (uip_udp_conn->lport != 0) + { + uip_conn = NULL; + uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + uip_len = uip_slen = 0; + uip_flags = UIP_POLL; + uip_event_signal(); + uip_interrupt_udp_event(); + goto udp_send; + } + else + { + goto drop; + } + } +#endif + + /* This is where the input processing starts. */ + UIP_STAT(++uip_stat.ip.recv); + + /* Start of IP input header processing code. */ + +#ifdef CONFIG_NET_UIP_IPv6 + /* Check validity of the IP header. */ + if ((BUF->vtc & 0xf0) != 0x60) + { + /* IP version and header length. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.vhlerr); + UIP_LOG("ipv6: invalid version."); + goto drop; + } +#else /* CONFIG_NET_UIP_IPv6 */ + /* Check validity of the IP header. */ + if (BUF->vhl != 0x45) + { + /* IP version and header length. */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.vhlerr); + UIP_LOG("ip: invalid version or header length."); + goto drop; + } +#endif /* CONFIG_NET_UIP_IPv6 */ + + /* Check the size of the packet. If the size reported to us in + uip_len is smaller the size reported in the IP header, we assume + that the packet has been corrupted in transit. If the size of + uip_len is larger than the size reported in the IP packet header, + the packet has been padded and we set uip_len to the correct + value.. */ + + if ((BUF->len[0] << 8) + BUF->len[1] <= uip_len) + { + uip_len = (BUF->len[0] << 8) + BUF->len[1]; +#ifdef CONFIG_NET_UIP_IPv6 + uip_len += 40; /* The length reported in the IPv6 header is the + length of the payload that follows the + header. However, uIP uses the uip_len variable + for holding the size of the entire packet, + including the IP header. For IPv4 this is not a + problem as the length field in the IPv4 header + contains the length of the entire packet. But + for IPv6 we need to add the size of the IPv6 + header (40 bytes). */ +#endif /* CONFIG_NET_UIP_IPv6 */ + } + else + { + UIP_LOG("ip: packet shorter than reported in IP header."); + goto drop; + } + +#ifndef CONFIG_NET_UIP_IPv6 + /* Check the fragment flag. */ + + if ((BUF->ipoffset[0] & 0x3f) != 0 || + BUF->ipoffset[1] != 0) + { +#if UIP_REASSEMBLY + uip_len = uip_reass(); + if (uip_len == 0) + { + goto drop; + } +#else /* UIP_REASSEMBLY */ + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.fragerr); + UIP_LOG("ip: fragment dropped."); + goto drop; +#endif /* UIP_REASSEMBLY */ + } +#endif /* CONFIG_NET_UIP_IPv6 */ + + if (uip_ipaddr_cmp(uip_hostaddr, all_zeroes_addr)) + { + /* If we are configured to use ping IP address configuration and + hasn't been assigned an IP address yet, we accept all ICMP + packets. */ +#if UIP_PINGADDRCONF && !CONFIG_NET_UIP_IPv6 + if (BUF->proto == UIP_PROTO_ICMP) + { + UIP_LOG("ip: possible ping config packet received."); + goto icmp_input; + } + else + { + UIP_LOG("ip: packet dropped since no address assigned."); + goto drop; + } +#endif /* UIP_PINGADDRCONF */ + + } + else + { + /* If IP broadcast support is configured, we check for a broadcast + UDP packet, which may be destined to us. */ +#if UIP_BROADCAST + dbg("UDP IP checksum 0x%04x\n", uip_ipchksum()); + if (BUF->proto == UIP_PROTO_UDP && + uip_ipaddr_cmp(BUF->destipaddr, all_ones_addr) + /*&& uip_ipchksum() == 0xffff*/) + { + goto udp_input; + } +#endif /* UIP_BROADCAST */ + + /* Check if the packet is destined for our IP address. */ +#ifndef CONFIG_NET_UIP_IPv6 + if (!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr)) + { + UIP_STAT(++uip_stat.ip.drop); + goto drop; + } +#else /* CONFIG_NET_UIP_IPv6 */ + /* For IPv6, packet reception is a little trickier as we need to + make sure that we listen to certain multicast addresses (all + hosts multicast address, and the solicited-node multicast + address) as well. However, we will cheat here and accept all + multicast packets that are sent to the ff02::/16 addresses. */ + if (!uip_ipaddr_cmp(BUF->destipaddr, uip_hostaddr) && + BUF->destipaddr[0] != HTONS(0xff02)) + { + UIP_STAT(++uip_stat.ip.drop); + goto drop; + } +#endif /* CONFIG_NET_UIP_IPv6 */ + } + +#ifndef CONFIG_NET_UIP_IPv6 + if (uip_ipchksum() != 0xffff) + { + /* Compute and check the IP header checksum. */ + + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.chkerr); + UIP_LOG("ip: bad checksum."); + goto drop; + } +#endif /* CONFIG_NET_UIP_IPv6 */ + + if (BUF->proto == UIP_PROTO_TCP) + { + /* Check for TCP packet. If so, proceed with TCP input processing. */ + + goto tcp_input; + } + +#if UIP_UDP + if (BUF->proto == UIP_PROTO_UDP) + { + goto udp_input; + } +#endif /* UIP_UDP */ + +#ifndef CONFIG_NET_UIP_IPv6 + /* ICMPv4 processing code follows. */ + if (BUF->proto != UIP_PROTO_ICMP) + { + /* We only allow ICMP packets from here. */ + + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.protoerr); + UIP_LOG("ip: neither tcp nor icmp."); + goto drop; + } + +#if UIP_PINGADDRCONF + icmp_input: +#endif /* UIP_PINGADDRCONF */ + UIP_STAT(++uip_stat.icmp.recv); + + /* ICMP echo (i.e., ping) processing. This is simple, we only change + the ICMP type from ECHO to ECHO_REPLY and adjust the ICMP + checksum before we return the packet. */ + if (ICMPBUF->type != ICMP_ECHO) + { + UIP_STAT(++uip_stat.icmp.drop); + UIP_STAT(++uip_stat.icmp.typeerr); + UIP_LOG("icmp: not icmp echo."); + goto drop; + } + + /* If we are configured to use ping IP address assignment, we use + the destination IP address of this ping packet and assign it to + ourself. */ +#if UIP_PINGADDRCONF + if ((uip_hostaddr[0] | uip_hostaddr[1]) == 0) + { + uip_hostaddr[0] = BUF->destipaddr[0]; + uip_hostaddr[1] = BUF->destipaddr[1]; + } +#endif /* UIP_PINGADDRCONF */ + + ICMPBUF->type = ICMP_ECHO_REPLY; + + if (ICMPBUF->icmpchksum >= HTONS(0xffff - (ICMP_ECHO << 8))) + { + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8) + 1; + } + else + { + ICMPBUF->icmpchksum += HTONS(ICMP_ECHO << 8); + } + + /* Swap IP addresses. */ + + uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + + UIP_STAT(++uip_stat.icmp.sent); + goto send; + + /* End of IPv4 input header processing code. */ +#else /* !CONFIG_NET_UIP_IPv6 */ + + /* This is IPv6 ICMPv6 processing code. */ + dbg("icmp6_input: length %d\n", uip_len); + + if (BUF->proto != UIP_PROTO_ICMP6) + { + /* We only allow ICMPv6 packets from here. */ + + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.protoerr); + UIP_LOG("ip: neither tcp nor icmp6."); + goto drop; + } + + UIP_STAT(++uip_stat.icmp.recv); + + /* If we get a neighbor solicitation for our address we should send + a neighbor advertisement message back. */ + if (ICMPBUF->type == ICMP6_NEIGHBOR_SOLICITATION) + { + if (uip_ipaddr_cmp(ICMPBUF->icmp6data, uip_hostaddr)) + { + if (ICMPBUF->options[0] == ICMP6_OPTION_SOURCE_LINK_ADDRESS) + { + /* Save the sender's address in our neighbor list. */ + uip_neighbor_add(ICMPBUF->srcipaddr, &(ICMPBUF->options[2])); + } + + /* We should now send a neighbor advertisement back to where the + neighbor solicication came from. */ + ICMPBUF->type = ICMP6_NEIGHBOR_ADVERTISEMENT; + ICMPBUF->flags = ICMP6_FLAG_S; /* Solicited flag. */ + + ICMPBUF->reserved1 = ICMPBUF->reserved2 = ICMPBUF->reserved3 = 0; + + uip_ipaddr_copy(ICMPBUF->destipaddr, ICMPBUF->srcipaddr); + uip_ipaddr_copy(ICMPBUF->srcipaddr, uip_hostaddr); + ICMPBUF->options[0] = ICMP6_OPTION_TARGET_LINK_ADDRESS; + ICMPBUF->options[1] = 1; /* Options length, 1 = 8 bytes. */ + memcpy(&(ICMPBUF->options[2]), &uip_ethaddr, sizeof(uip_ethaddr)); + ICMPBUF->icmpchksum = 0; + ICMPBUF->icmpchksum = ~uip_icmp6chksum(); + goto send; + } + goto drop; + } + else if (ICMPBUF->type == ICMP6_ECHO) + { + /* ICMP echo (i.e., ping) processing. This is simple, we only + change the ICMP type from ECHO to ECHO_REPLY and update the + ICMP checksum before we return the packet. */ + + ICMPBUF->type = ICMP6_ECHO_REPLY; + + uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + ICMPBUF->icmpchksum = 0; + ICMPBUF->icmpchksum = ~uip_icmp6chksum(); + + UIP_STAT(++uip_stat.icmp.sent); + goto send; + } + else + { + dbg("Unknown icmp6 message type %d\n", ICMPBUF->type); + UIP_STAT(++uip_stat.icmp.drop); + UIP_STAT(++uip_stat.icmp.typeerr); + UIP_LOG("icmp: unknown ICMP message."); + goto drop; + } + + /* End of IPv6 ICMP processing. */ + +#endif /* !CONFIG_NET_UIP_IPv6 */ + +#if UIP_UDP + /* UDP input processing. */ + udp_input: + /* UDP processing is really just a hack. We don't do anything to the + UDP/IP headers, but let the UDP application do all the hard + work. If the application sets uip_slen, it has a packet to + send. */ +#if UIP_UDP_CHECKSUMS + uip_len = uip_len - UIP_IPUDPH_LEN; + uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + if (UDPBUF->udpchksum != 0 && uip_udpchksum() != 0xffff) + { + UIP_STAT(++uip_stat.udp.drop); + UIP_STAT(++uip_stat.udp.chkerr); + UIP_LOG("udp: bad checksum."); + goto drop; + } +#else /* UIP_UDP_CHECKSUMS */ + uip_len = uip_len - UIP_IPUDPH_LEN; +#endif /* UIP_UDP_CHECKSUMS */ + + /* Demultiplex this UDP packet between the UDP "connections". */ + for (uip_udp_conn = &uip_udp_conns[0]; + uip_udp_conn < &uip_udp_conns[UIP_UDP_CONNS]; + ++uip_udp_conn) + { + /* If the local UDP port is non-zero, the connection is considered + to be used. If so, the local port number is checked against the + destination port number in the received packet. If the two port + numbers match, the remote port number is checked if the + connection is bound to a remote port. Finally, if the + connection is bound to a remote IP address, the source IP + address of the packet is checked. */ + if (uip_udp_conn->lport != 0 && + UDPBUF->destport == uip_udp_conn->lport && + (uip_udp_conn->rport == 0 || + UDPBUF->srcport == uip_udp_conn->rport) && + (uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_zeroes_addr) || + uip_ipaddr_cmp(uip_udp_conn->ripaddr, all_ones_addr) || + uip_ipaddr_cmp(BUF->srcipaddr, uip_udp_conn->ripaddr))) + { + goto udp_found; + } + } + UIP_LOG("udp: no matching connection found"); + goto drop; + + udp_found: + uip_conn = NULL; + uip_flags = UIP_NEWDATA; + uip_sappdata = uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN]; + uip_slen = 0; + uip_event_signal(); + uip_interrupt_udp_event(); + + udp_send: + if (uip_slen == 0) + { + goto drop; + } + uip_len = uip_slen + UIP_IPUDPH_LEN; + +#ifdef CONFIG_NET_UIP_IPv6 + /* For IPv6, the IP length field does not include the IPv6 IP header + length. */ + BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); +#else /* CONFIG_NET_UIP_IPv6 */ + BUF->len[0] = (uip_len >> 8); + BUF->len[1] = (uip_len & 0xff); +#endif /* CONFIG_NET_UIP_IPv6 */ + + BUF->ttl = uip_udp_conn->ttl; + BUF->proto = UIP_PROTO_UDP; + + UDPBUF->udplen = HTONS(uip_slen + UIP_UDPH_LEN); + UDPBUF->udpchksum = 0; + + BUF->srcport = uip_udp_conn->lport; + BUF->destport = uip_udp_conn->rport; + + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + uip_ipaddr_copy(BUF->destipaddr, uip_udp_conn->ripaddr); + + uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN]; + +#if UIP_UDP_CHECKSUMS + /* Calculate UDP checksum. */ + UDPBUF->udpchksum = ~(uip_udpchksum()); + if (UDPBUF->udpchksum == 0) + { + UDPBUF->udpchksum = 0xffff; + } +#endif /* UIP_UDP_CHECKSUMS */ + + goto ip_send_nolen; +#endif /* UIP_UDP */ + + /* TCP input processing. */ + tcp_input: + UIP_STAT(++uip_stat.tcp.recv); + + /* Start of TCP input header processing code. */ + + if (uip_tcpchksum() != 0xffff) + { + /* Compute and check the TCP checksum. */ + UIP_STAT(++uip_stat.tcp.drop); + UIP_STAT(++uip_stat.tcp.chkerr); + UIP_LOG("tcp: bad checksum."); + goto drop; + } + + /* Demultiplex this segment. */ + /* First check any active connections. */ + for (uip_connr = &uip_conns[0]; uip_connr <= &uip_conns[UIP_CONNS - 1]; + ++uip_connr) + { + if (uip_connr->tcpstateflags != UIP_CLOSED && + BUF->destport == uip_connr->lport && + BUF->srcport == uip_connr->rport && + uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) + { + goto found; + } + } + + /* If we didn't find and active connection that expected the packet, + either this packet is an old duplicate, or this is a SYN packet + destined for a connection in LISTEN. If the SYN flag isn't set, + it is an old packet and we send a RST. */ + if ((BUF->flags & TCP_CTL) != TCP_SYN) + { + goto reset; + } + + tmp16 = BUF->destport; + + /* Next, check listening connections. */ + for(c = 0; c < UIP_LISTENPORTS; ++c) + { + if (tmp16 == uip_listenports[c]) + goto found_listen; + } + + /* No matching connection found, so we send a RST packet. */ + UIP_STAT(++uip_stat.tcp.synrst); + reset: + + /* We do not send resets in response to resets. */ + if (BUF->flags & TCP_RST) + { + goto drop; + } + + UIP_STAT(++uip_stat.tcp.rst); + + BUF->flags = TCP_RST | TCP_ACK; + uip_len = UIP_IPTCPH_LEN; + BUF->tcpoffset = 5 << 4; + + /* Flip the seqno and ackno fields in the TCP header. */ + c = BUF->seqno[3]; + BUF->seqno[3] = BUF->ackno[3]; + BUF->ackno[3] = c; + + c = BUF->seqno[2]; + BUF->seqno[2] = BUF->ackno[2]; + BUF->ackno[2] = c; + + c = BUF->seqno[1]; + BUF->seqno[1] = BUF->ackno[1]; + BUF->ackno[1] = c; + + c = BUF->seqno[0]; + BUF->seqno[0] = BUF->ackno[0]; + BUF->ackno[0] = c; + + /* We also have to increase the sequence number we are + acknowledging. If the least significant byte overflowed, we need + to propagate the carry to the other bytes as well. */ + if (++BUF->ackno[3] == 0) + { + if (++BUF->ackno[2] == 0) + { + if (++BUF->ackno[1] == 0) + { + ++BUF->ackno[0]; + } + } + } + + /* Swap port numbers. */ + tmp16 = BUF->srcport; + BUF->srcport = BUF->destport; + BUF->destport = tmp16; + + /* Swap IP addresses. */ + uip_ipaddr_copy(BUF->destipaddr, BUF->srcipaddr); + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + + /* And send out the RST packet! */ + goto tcp_send_noconn; + + /* This label will be jumped to if we matched the incoming packet + with a connection in LISTEN. In that case, we should create a new + connection and send a SYNACK in return. */ + found_listen: + /* First we check if there are any connections avaliable. Unused + connections are kept in the same table as used connections, but + unused ones have the tcpstate set to CLOSED. Also, connections in + TIME_WAIT are kept track of and we'll use the oldest one if no + CLOSED connections are found. Thanks to Eddie C. Dost for a very + nice algorithm for the TIME_WAIT search. */ + uip_connr = 0; + for(c = 0; c < UIP_CONNS; ++c) + { + if (uip_conns[c].tcpstateflags == UIP_CLOSED) + { + uip_connr = &uip_conns[c]; + break; + } + if (uip_conns[c].tcpstateflags == UIP_TIME_WAIT) + { + if (uip_connr == 0 || uip_conns[c].timer > uip_connr->timer) + { + uip_connr = &uip_conns[c]; + } + } + } + + if (uip_connr == 0) + { + /* All connections are used already, we drop packet and hope that + the remote end will retransmit the packet at a time when we + have more spare connections. */ + UIP_STAT(++uip_stat.tcp.syndrop); + UIP_LOG("tcp: found no unused connections."); + goto drop; + } + uip_conn = uip_connr; + + /* Fill in the necessary fields for the new connection. */ + uip_connr->rto = uip_connr->timer = UIP_RTO; + uip_connr->sa = 0; + uip_connr->sv = 4; + uip_connr->nrtx = 0; + uip_connr->lport = BUF->destport; + uip_connr->rport = BUF->srcport; + uip_ipaddr_copy(uip_connr->ripaddr, BUF->srcipaddr); + uip_connr->tcpstateflags = UIP_SYN_RCVD; + + uip_connr->snd_nxt[0] = iss[0]; + uip_connr->snd_nxt[1] = iss[1]; + uip_connr->snd_nxt[2] = iss[2]; + uip_connr->snd_nxt[3] = iss[3]; + uip_connr->len = 1; + + /* rcv_nxt should be the seqno from the incoming packet + 1. */ + uip_connr->rcv_nxt[3] = BUF->seqno[3]; + uip_connr->rcv_nxt[2] = BUF->seqno[2]; + uip_connr->rcv_nxt[1] = BUF->seqno[1]; + uip_connr->rcv_nxt[0] = BUF->seqno[0]; + uip_add_rcv_nxt(1); + + /* Parse the TCP MSS option, if present. */ + if ((BUF->tcpoffset & 0xf0) > 0x50) + { + for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) + { + opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c]; + if (opt == TCP_OPT_END) + { + /* End of options. */ + break; + } + else if (opt == TCP_OPT_NOOP) + { + ++c; + /* NOP option. */ + } + else if (opt == TCP_OPT_MSS && + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) + { + /* An MSS option with the right option length. */ + tmp16 = ((uint16)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | + (uint16)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c]; + uip_connr->initialmss = uip_connr->mss = + tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; + + /* And we are done processing options. */ + break; + } + else + { + /* All other options have a length field, so that we easily + can skip past them. */ + if (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) + { + /* If the length field is zero, the options are malformed + and we don't process them further. */ + break; + } + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; + } + } + } + + /* Our response will be a SYNACK. */ +#if UIP_ACTIVE_OPEN + tcp_send_synack: + BUF->flags = TCP_ACK; + + tcp_send_syn: + BUF->flags |= TCP_SYN; +#else /* UIP_ACTIVE_OPEN */ + tcp_send_synack: + BUF->flags = TCP_SYN | TCP_ACK; +#endif /* UIP_ACTIVE_OPEN */ + + /* We send out the TCP Maximum Segment Size option with our + SYNACK. */ + BUF->optdata[0] = TCP_OPT_MSS; + BUF->optdata[1] = TCP_OPT_MSS_LEN; + BUF->optdata[2] = (UIP_TCP_MSS) / 256; + BUF->optdata[3] = (UIP_TCP_MSS) & 255; + uip_len = UIP_IPTCPH_LEN + TCP_OPT_MSS_LEN; + BUF->tcpoffset = ((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4) << 4; + goto tcp_send; + + /* This label will be jumped to if we found an active connection. */ + found: + uip_conn = uip_connr; + uip_flags = 0; + + /* We do a very naive form of TCP reset processing; we just accept + * any RST and kill our connection. We should in fact check if the + * sequence number of this reset is wihtin our advertised window + * before we accept the reset. + */ + + if (BUF->flags & TCP_RST) + { + uip_connr->tcpstateflags = UIP_CLOSED; + UIP_LOG("tcp: got reset, aborting connection."); + uip_flags = UIP_ABORT; + uip_event_signal(); + uip_interrupt_event(); + goto drop; + } + + /* Calculated the length of the data, if the application has sent + * any data to us. + */ + + c = (BUF->tcpoffset >> 4) << 2; + + /* uip_len will contain the length of the actual TCP data. This is + * calculated by subtracing the length of the TCP header (in + * c) and the length of the IP header (20 bytes). + */ + + uip_len = uip_len - c - UIP_IPH_LEN; + + /* First, check if the sequence number of the incoming packet is + * what we're expecting next. If not, we send out an ACK with the + * correct numbers in. + */ + + if (!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) && + ((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) + { + if ((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) && + (BUF->seqno[0] != uip_connr->rcv_nxt[0] || + BUF->seqno[1] != uip_connr->rcv_nxt[1] || + BUF->seqno[2] != uip_connr->rcv_nxt[2] || + BUF->seqno[3] != uip_connr->rcv_nxt[3])) + { + goto tcp_send_ack; + } + } + + /* Next, check if the incoming segment acknowledges any outstanding + data. If so, we update the sequence number, reset the length of + the outstanding data, calculate RTT estimations, and reset the + retransmission timer. */ + if ((BUF->flags & TCP_ACK) && uip_outstanding(uip_connr)) + { + uip_add32(uip_connr->snd_nxt, uip_connr->len); + + if (BUF->ackno[0] == uip_acc32[0] && + BUF->ackno[1] == uip_acc32[1] && + BUF->ackno[2] == uip_acc32[2] && + BUF->ackno[3] == uip_acc32[3]) + { + /* Update sequence number. */ + uip_connr->snd_nxt[0] = uip_acc32[0]; + uip_connr->snd_nxt[1] = uip_acc32[1]; + uip_connr->snd_nxt[2] = uip_acc32[2]; + uip_connr->snd_nxt[3] = uip_acc32[3]; + + /* Do RTT estimation, unless we have done retransmissions. */ + if (uip_connr->nrtx == 0) + { + signed char m; + m = uip_connr->rto - uip_connr->timer; + + /* This is taken directly from VJs original code in his paper */ + m = m - (uip_connr->sa >> 3); + uip_connr->sa += m; + if (m < 0) + { + m = -m; + } + m = m - (uip_connr->sv >> 2); + uip_connr->sv += m; + uip_connr->rto = (uip_connr->sa >> 3) + uip_connr->sv; + } + + /* Set the acknowledged flag. */ + uip_flags = UIP_ACKDATA; + + /* Reset the retransmission timer. */ + uip_connr->timer = uip_connr->rto; + + /* Reset length of outstanding data. */ + uip_connr->len = 0; + } + } + + /* Do different things depending on in what state the connection is. */ + switch(uip_connr->tcpstateflags & UIP_TS_MASK) + { + /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not + implemented, since we force the application to close when the + peer sends a FIN (hence the application goes directly from + ESTABLISHED to LAST_ACK). */ + case UIP_SYN_RCVD: + /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and + * we are waiting for an ACK that acknowledges the data we sent + * out the last time. Therefore, we want to have the UIP_ACKDATA + * flag set. If so, we enter the ESTABLISHED state. + */ + + if (uip_flags & UIP_ACKDATA) + { + uip_connr->tcpstateflags = UIP_ESTABLISHED; + uip_flags = UIP_CONNECTED; + uip_connr->len = 0; + if (uip_len > 0) + { + uip_flags |= UIP_NEWDATA; + uip_add_rcv_nxt(uip_len); + } + uip_slen = 0; + uip_event_signal(); + uip_interrupt_event(); + goto appsend; + } + goto drop; + +#if UIP_ACTIVE_OPEN + case UIP_SYN_SENT: + /* In SYN_SENT, we wait for a SYNACK that is sent in response to + our SYN. The rcv_nxt is set to sequence number in the SYNACK + plus one, and we send an ACK. We move into the ESTABLISHED + state. */ + if ((uip_flags & UIP_ACKDATA) && + (BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) + { + /* Parse the TCP MSS option, if present. */ + if ((BUF->tcpoffset & 0xf0) > 0x50) + { + for(c = 0; c < ((BUF->tcpoffset >> 4) - 5) << 2 ;) + { + opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c]; + if (opt == TCP_OPT_END) + { + /* End of options. */ + break; + } + else if (opt == TCP_OPT_NOOP) + { + ++c; + /* NOP option. */ + } + else if (opt == TCP_OPT_MSS && + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) + { + /* An MSS option with the right option length. */ + tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; + uip_connr->initialmss = + uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; + + /* And we are done processing options. */ + break; + } + else + { + /* All other options have a length field, so that we easily + can skip past them. */ + if (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) + { + /* If the length field is zero, the options are malformed + and we don't process them further. */ + break; + } + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; + } + } + } + uip_connr->tcpstateflags = UIP_ESTABLISHED; + uip_connr->rcv_nxt[0] = BUF->seqno[0]; + uip_connr->rcv_nxt[1] = BUF->seqno[1]; + uip_connr->rcv_nxt[2] = BUF->seqno[2]; + uip_connr->rcv_nxt[3] = BUF->seqno[3]; + uip_add_rcv_nxt(1); + uip_flags = UIP_CONNECTED | UIP_NEWDATA; + uip_connr->len = 0; + uip_len = 0; + uip_slen = 0; + uip_event_signal(); + uip_interrupt_event(); + goto appsend; + } + + /* Inform the application that the connection failed */ + uip_flags = UIP_ABORT; + uip_event_signal(); + uip_interrupt_event(); + + /* The connection is closed after we send the RST */ + uip_conn->tcpstateflags = UIP_CLOSED; + goto reset; +#endif /* UIP_ACTIVE_OPEN */ + + case UIP_ESTABLISHED: + /* In the ESTABLISHED state, we call upon the application to feed + data into the uip_buf. If the UIP_ACKDATA flag is set, the + application should put new data into the buffer, otherwise we are + retransmitting an old segment, and the application should put that + data into the buffer. + + If the incoming packet is a FIN, we should close the connection on + this side as well, and we send out a FIN and enter the LAST_ACK + state. We require that there is no outstanding data; otherwise the + sequence numbers will be screwed up. */ + + if (BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) + { + if (uip_outstanding(uip_connr)) + { + goto drop; + } + uip_add_rcv_nxt(1 + uip_len); + uip_flags |= UIP_CLOSE; + if (uip_len > 0) + { + uip_flags |= UIP_NEWDATA; + } + uip_event_signal(); + uip_interrupt_event(); + uip_connr->len = 1; + uip_connr->tcpstateflags = UIP_LAST_ACK; + uip_connr->nrtx = 0; + + tcp_send_finack: + BUF->flags = TCP_FIN | TCP_ACK; + goto tcp_send_nodata; + } + + /* Check the URG flag. If this is set, the segment carries urgent + data that we must pass to the application. */ + if ((BUF->flags & TCP_URG) != 0) + { +#if UIP_URGDATA > 0 + uip_urglen = (BUF->urgp[0] << 8) | BUF->urgp[1]; + if (uip_urglen > uip_len) + { + /* There is more urgent data in the next segment to come. */ + uip_urglen = uip_len; + } + uip_add_rcv_nxt(uip_urglen); + uip_len -= uip_urglen; + uip_urgdata = uip_appdata; + uip_appdata += uip_urglen; + } + else + { + uip_urglen = 0; +#else /* UIP_URGDATA > 0 */ + uip_appdata = ((char *)uip_appdata) + ((BUF->urgp[0] << 8) | BUF->urgp[1]); + uip_len -= (BUF->urgp[0] << 8) | BUF->urgp[1]; +#endif /* UIP_URGDATA > 0 */ + } + + /* If uip_len > 0 we have TCP data in the packet, and we flag this + by setting the UIP_NEWDATA flag and update the sequence number + we acknowledge. If the application has stopped the dataflow + using uip_stop(), we must not accept any data packets from the + remote host. */ + if (uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) + { + uip_flags |= UIP_NEWDATA; + uip_add_rcv_nxt(uip_len); + } + + /* Check if the available buffer space advertised by the other end + is smaller than the initial MSS for this connection. If so, we + set the current MSS to the window size to ensure that the + application does not send more data than the other end can + handle. + + If the remote host advertises a zero window, we set the MSS to + the initial MSS so that the application will send an entire MSS + of data. This data will not be acknowledged by the receiver, + and the application will retransmit it. This is called the + "persistent timer" and uses the retransmission mechanim. + */ + tmp16 = ((uint16)BUF->wnd[0] << 8) + (uint16)BUF->wnd[1]; + if (tmp16 > uip_connr->initialmss || tmp16 == 0) + { + tmp16 = uip_connr->initialmss; + } + uip_connr->mss = tmp16; + + /* If this packet constitutes an ACK for outstanding data (flagged + by the UIP_ACKDATA flag, we should call the application since it + might want to send more data. If the incoming packet had data + from the peer (as flagged by the UIP_NEWDATA flag), the + application must also be notified. + + When the application is called, the global variable uip_len + contains the length of the incoming data. The application can + access the incoming data through the global pointer + uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN + bytes into the uip_buf array. + + If the application wishes to send any data, this data should be + put into the uip_appdata and the length of the data should be + put into uip_len. If the application don't have any data to + send, uip_len must be set to 0. */ + if (uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) + { + uip_slen = 0; + uip_event_signal(); + uip_interrupt_event(); + + appsend: + if (uip_flags & UIP_ABORT) + { + uip_slen = 0; + uip_connr->tcpstateflags = UIP_CLOSED; + BUF->flags = TCP_RST | TCP_ACK; + goto tcp_send_nodata; + } + + if (uip_flags & UIP_CLOSE) + { + uip_slen = 0; + uip_connr->len = 1; + uip_connr->tcpstateflags = UIP_FIN_WAIT_1; + uip_connr->nrtx = 0; + BUF->flags = TCP_FIN | TCP_ACK; + goto tcp_send_nodata; + } + + /* If uip_slen > 0, the application has data to be sent. */ + if (uip_slen > 0) + { + /* If the connection has acknowledged data, the contents of + the ->len variable should be discarded. */ + if ((uip_flags & UIP_ACKDATA) != 0) + { + uip_connr->len = 0; + } + + /* If the ->len variable is non-zero the connection has + already data in transit and cannot send anymore right + now. */ + if (uip_connr->len == 0) + { + /* The application cannot send more than what is allowed by + the mss (the minumum of the MSS and the available + window). */ + if (uip_slen > uip_connr->mss) + { + uip_slen = uip_connr->mss; + } + + /* Remember how much data we send out now so that we know + when everything has been acknowledged. */ + uip_connr->len = uip_slen; + } + else + { + /* If the application already had unacknowledged data, we + make sure that the application does not send (i.e., + retransmit) out more than it previously sent out. */ + uip_slen = uip_connr->len; + } + } + uip_connr->nrtx = 0; + apprexmit: + uip_appdata = uip_sappdata; + + /* If the application has data to be sent, or if the incoming + packet had new data in it, we must send out a packet. */ + if (uip_slen > 0 && uip_connr->len > 0) + { + /* Add the length of the IP and TCP headers. */ + uip_len = uip_connr->len + UIP_TCPIP_HLEN; + + /* We always set the ACK flag in response packets. */ + BUF->flags = TCP_ACK | TCP_PSH; + + /* Send the packet. */ + goto tcp_send_noopts; + } + + /* If there is no data to send, just send out a pure ACK if + there is newdata. */ + if (uip_flags & UIP_NEWDATA) + { + uip_len = UIP_TCPIP_HLEN; + BUF->flags = TCP_ACK; + goto tcp_send_noopts; + } + } + goto drop; + + case UIP_LAST_ACK: + /* We can close this connection if the peer has acknowledged our + FIN. This is indicated by the UIP_ACKDATA flag. */ + if (uip_flags & UIP_ACKDATA) + { + uip_connr->tcpstateflags = UIP_CLOSED; + uip_flags = UIP_CLOSE; + uip_event_signal(); + uip_interrupt_event(); + } + break; + + case UIP_FIN_WAIT_1: + /* The application has closed the connection, but the remote host + hasn't closed its end yet. Thus we do nothing but wait for a + FIN from the other side. */ + if (uip_len > 0) + { + uip_add_rcv_nxt(uip_len); + } + if (BUF->flags & TCP_FIN) + { + if (uip_flags & UIP_ACKDATA) + { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + uip_connr->len = 0; + } + else + { + uip_connr->tcpstateflags = UIP_CLOSING; + } + uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + uip_event_signal(); + uip_interrupt_event(); + goto tcp_send_ack; + } + else if (uip_flags & UIP_ACKDATA) + { + uip_connr->tcpstateflags = UIP_FIN_WAIT_2; + uip_connr->len = 0; + goto drop; + } + if (uip_len > 0) + { + goto tcp_send_ack; + } + goto drop; + + case UIP_FIN_WAIT_2: + if (uip_len > 0) + { + uip_add_rcv_nxt(uip_len); + } + if (BUF->flags & TCP_FIN) + { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + uip_event_signal(); + uip_interrupt_event(); + goto tcp_send_ack; + } + if (uip_len > 0) + { + goto tcp_send_ack; + } + goto drop; + + case UIP_TIME_WAIT: + goto tcp_send_ack; + + case UIP_CLOSING: + if (uip_flags & UIP_ACKDATA) + { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + } + } + goto drop; + + /* We jump here when we are ready to send the packet, and just want + to set the appropriate TCP sequence numbers in the TCP header. */ + tcp_send_ack: + BUF->flags = TCP_ACK; + tcp_send_nodata: + uip_len = UIP_IPTCPH_LEN; + tcp_send_noopts: + BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4; + tcp_send: + /* We're done with the input processing. We are now ready to send a + reply. Our job is to fill in all the fields of the TCP and IP + headers before calculating the checksum and finally send the + packet. */ + BUF->ackno[0] = uip_connr->rcv_nxt[0]; + BUF->ackno[1] = uip_connr->rcv_nxt[1]; + BUF->ackno[2] = uip_connr->rcv_nxt[2]; + BUF->ackno[3] = uip_connr->rcv_nxt[3]; + + BUF->seqno[0] = uip_connr->snd_nxt[0]; + BUF->seqno[1] = uip_connr->snd_nxt[1]; + BUF->seqno[2] = uip_connr->snd_nxt[2]; + BUF->seqno[3] = uip_connr->snd_nxt[3]; + + BUF->proto = UIP_PROTO_TCP; + + BUF->srcport = uip_connr->lport; + BUF->destport = uip_connr->rport; + + uip_ipaddr_copy(BUF->srcipaddr, uip_hostaddr); + uip_ipaddr_copy(BUF->destipaddr, uip_connr->ripaddr); + + if (uip_connr->tcpstateflags & UIP_STOPPED) + { + /* If the connection has issued uip_stop(), we advertise a zero + window so that the remote host will stop sending data. */ + BUF->wnd[0] = BUF->wnd[1] = 0; + } + else + { + BUF->wnd[0] = ((UIP_RECEIVE_WINDOW) >> 8); + BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); + } + + tcp_send_noconn: + BUF->ttl = UIP_TTL; +#ifdef CONFIG_NET_UIP_IPv6 + /* For IPv6, the IP length field does not include the IPv6 IP header + length. */ + BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); +#else /* CONFIG_NET_UIP_IPv6 */ + BUF->len[0] = (uip_len >> 8); + BUF->len[1] = (uip_len & 0xff); +#endif /* CONFIG_NET_UIP_IPv6 */ + + BUF->urgp[0] = BUF->urgp[1] = 0; + + /* Calculate TCP checksum. */ + BUF->tcpchksum = 0; + BUF->tcpchksum = ~(uip_tcpchksum()); + +#if UIP_UDP + ip_send_nolen: +#endif /* UIP_UDP */ + +#ifdef CONFIG_NET_UIP_IPv6 + BUF->vtc = 0x60; + BUF->tcflow = 0x00; + BUF->flow = 0x00; +#else /* CONFIG_NET_UIP_IPv6 */ + BUF->vhl = 0x45; + BUF->tos = 0; + BUF->ipoffset[0] = BUF->ipoffset[1] = 0; + ++ipid; + BUF->ipid[0] = ipid >> 8; + BUF->ipid[1] = ipid & 0xff; + + /* Calculate IP checksum. */ + BUF->ipchksum = 0; + BUF->ipchksum = ~(uip_ipchksum()); + dbg("uip ip_send_nolen: chkecum 0x%04x\n", uip_ipchksum()); +#endif /* CONFIG_NET_UIP_IPv6 */ + + UIP_STAT(++uip_stat.tcp.sent); + send: + dbg("Sending packet with length %d (%d)\n", uip_len, + (BUF->len[0] << 8) | BUF->len[1]); + + UIP_STAT(++uip_stat.ip.sent); + + /* Return and let the caller do the actual transmission. */ + uip_flags = 0; + return; + drop: + uip_len = 0; + uip_flags = 0; + return; +} + +uint16 htons(uint16 val) +{ + return HTONS(val); +} + +void uip_send(const void *data, int len) +{ + if (len > 0) + { + uip_slen = len; + if (data != uip_sappdata) + { + memcpy(uip_sappdata, (data), uip_slen); + } + } +} diff --git a/nuttx/netutils/Makefile b/nuttx/netutils/Makefile new file mode 100644 index 000000000..0534f59d1 --- /dev/null +++ b/nuttx/netutils/Makefile @@ -0,0 +1,97 @@ +############################################################ +# Makefile +# +# Copyright (C) 2007 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################ + +-include $(TOPDIR)/Make.defs + +MKDEP = $(TOPDIR)/tools/mkdeps.sh + +ifeq ($(CONFIG_NET_UIP),y) +include uiplib/Make.defs +include dhcpc/Make.defs +include resolv/Make.defs +include smtp/Make.defs +include telnetd/Make.defs +include webclient/Make.defs +include webserver/Make.defs +endif + +ASRCS = $(UIPLIB_ASRCS) $(DHCPC_ASRCS) $(RESOLV_ASRCS) $(SMTP_ASRCS) \ + $(TELNETD_ASRCS) $(WEBCLIENT_ASRCS) $(WEBSERVER_ASRCS) +AOBJS = $(ASRCS:.S=$(OBJEXT)) + +CSRCS = $(UIPLIB_CSRCS) $(DHCPC_CSRCS) $(RESOLV_CSRCS) $(SMTP_CSRCS) \ + $(TELNETD_CSRCS) $(WEBCLIENT_CSRCS) $(WEBSERVER_CSRCS) +COBJS = $(CSRCS:.c=$(OBJEXT)) + +SRCS = $(ASRCS) $(CSRCS) +OBJS = $(AOBJS) $(COBJS) + +BIN = libnetutils$(LIBEXT) + +VPATH = uiplib:dhcpc:resolv:smtp:telnetd:webclient:webserver + +all: $(BIN) + +$(AOBJS): %$(OBJEXT): %.S + $(CC) -c $(CFLAGS) -D__ASSEMBLY__ $< -o $@ + +$(COBJS): %$(OBJEXT): %.c + $(CC) -c $(CFLAGS) $< -o $@ + +$(BIN): $(OBJS) + ( for obj in $(OBJS) ; do \ + $(AR) $@ $${obj} || \ + { echo "$(AR) $@ $obj FAILED!" ; exit 1 ; } ; \ + done ; ) + +.depend: Makefile $(SRCS) +ifeq ($(CONFIG_NET_UIP),y) + $(MKDEP) --dep-path uiplib --dep-path dhcpc --dep-path smtp --dep-path webclient \ + --dep-path resolv --dep-path telnetd --dep-path webserver \ + $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep +endif + touch $@ + +depend: .depend + +clean: + rm -f $(BIN) *.o *.rel *.asm *.lst *.sym *.adb *~ + rm -f uiplib/*~ dhcpc/*~ resolv/*~ smtp/*~ telnetd/*~ webclient/*~ webserver/*~ + if [ ! -z "$(OBJEXT)" ]; then rm -f *$(OBJEXT); fi + +distclean: clean + rm -f Make.dep .depend + +-include Make.dep diff --git a/nuttx/netutils/README b/nuttx/netutils/README new file mode 100644 index 000000000..9f6969b5f --- /dev/null +++ b/nuttx/netutils/README @@ -0,0 +1,5 @@ +netutils +^^^^^^^^ + +This directory contains most of the network applications contained under the uIP-1.0 apps directory. +As the uIP apps/README says, there applications "are not all heavily tested."
\ No newline at end of file diff --git a/nuttx/netutils/dhcpc/Make.defs b/nuttx/netutils/dhcpc/Make.defs new file mode 100644 index 000000000..b4aa9acbf --- /dev/null +++ b/nuttx/netutils/dhcpc/Make.defs @@ -0,0 +1,39 @@ +############################################################################ +# Make.defs +# +# Copyright (C) 2007 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################################ + +ifeq ($(CONFIG_UIP_UDP),y) +DHCPC_ASRCS = +DHCPC_CSRCS = dhcpc.c +endif
\ No newline at end of file diff --git a/nuttx/netutils/dhcpc/dhcpc.c b/nuttx/netutils/dhcpc/dhcpc.c new file mode 100644 index 000000000..096649b68 --- /dev/null +++ b/nuttx/netutils/dhcpc/dhcpc.c @@ -0,0 +1,390 @@ +/************************************************************ + * dhcpc.c + * + * Copyright (C) 2007 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * Based heavily on portions of uIP: + * + * Copyright (c) 2005, 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * 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. + * + ************************************************************/ + +/************************************************************ + * Included Files + ************************************************************/ + +#include <sys/types.h> +#include <stdio.h> +#include <string.h> +#include <pthread.h> +#include <time.h> +#include <debug.h> + +#include <net/uip/uip.h> + +#include "dhcpc.h" + +/************************************************************ + * Definitions + ************************************************************/ + +/* CLK_TCK is the frequency of the system clock (typically 100Hz) */ +#define CLOCK_SECOND CLK_TCK + +#define STATE_INITIAL 0 +#define STATE_SENDING 1 +#define STATE_OFFER_RECEIVED 2 +#define STATE_CONFIG_RECEIVED 3 + +#define BOOTP_BROADCAST 0x8000 + +#define DHCP_REQUEST 1 +#define DHCP_REPLY 2 +#define DHCP_HTYPE_ETHERNET 1 +#define DHCP_HLEN_ETHERNET 6 +#define DHCP_MSG_LEN 236 + +#define DHCPC_SERVER_PORT 67 +#define DHCPC_CLIENT_PORT 68 + +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPDECLINE 4 +#define DHCPACK 5 +#define DHCPNAK 6 +#define DHCPRELEASE 7 + +#define DHCP_OPTION_SUBNET_MASK 1 +#define DHCP_OPTION_ROUTER 3 +#define DHCP_OPTION_DNS_SERVER 6 +#define DHCP_OPTION_REQ_IPADDR 50 +#define DHCP_OPTION_LEASE_TIME 51 +#define DHCP_OPTION_MSG_TYPE 53 +#define DHCP_OPTION_SERVER_ID 54 +#define DHCP_OPTION_REQ_LIST 55 +#define DHCP_OPTION_END 255 + +/************************************************************ + * Private Types + ************************************************************/ + +struct dhcp_msg +{ + uint8 op, htype, hlen, hops; + uint8 xid[4]; + uint16 secs, flags; + uint8 ciaddr[4]; + uint8 yiaddr[4]; + uint8 siaddr[4]; + uint8 giaddr[4]; + uint8 chaddr[16]; +#ifndef CONFIG_UIP_DHCP_LIGHT + uint8 sname[64]; + uint8 file[128]; +#endif + uint8 options[312]; +}; + +/************************************************************ + * Private Data + ************************************************************/ + +static struct dhcpc_state s; + +static const uint8 xid[4] = {0xad, 0xde, 0x12, 0x23}; +static const uint8 magic_cookie[4] = {99, 130, 83, 99}; + +/************************************************************ + * Private Functions + ************************************************************/ + +static uint8 *add_msg_type(uint8 *optptr, uint8 type) +{ + *optptr++ = DHCP_OPTION_MSG_TYPE; + *optptr++ = 1; + *optptr++ = type; + return optptr; +} + +static uint8 *add_server_id(uint8 *optptr) +{ + *optptr++ = DHCP_OPTION_SERVER_ID; + *optptr++ = 4; + memcpy(optptr, s.serverid, 4); + return optptr + 4; +} + +static uint8 *add_req_ipaddr(uint8 *optptr) +{ + *optptr++ = DHCP_OPTION_REQ_IPADDR; + *optptr++ = 4; + memcpy(optptr, s.ipaddr, 4); + return optptr + 4; +} + +static uint8 *add_req_options(uint8 *optptr) +{ + *optptr++ = DHCP_OPTION_REQ_LIST; + *optptr++ = 3; + *optptr++ = DHCP_OPTION_SUBNET_MASK; + *optptr++ = DHCP_OPTION_ROUTER; + *optptr++ = DHCP_OPTION_DNS_SERVER; + return optptr; +} + +static uint8 *add_end(uint8 *optptr) +{ + *optptr++ = DHCP_OPTION_END; + return optptr; +} + +static void create_msg(register struct dhcp_msg *m) +{ + m->op = DHCP_REQUEST; + m->htype = DHCP_HTYPE_ETHERNET; + m->hlen = s.mac_len; + m->hops = 0; + memcpy(m->xid, xid, sizeof(m->xid)); + m->secs = 0; + m->flags = HTONS(BOOTP_BROADCAST); /* Broadcast bit. */ + /* uip_ipaddr_copy(m->ciaddr, uip_hostaddr);*/ + memcpy(m->ciaddr, uip_hostaddr, sizeof(m->ciaddr)); + memset(m->yiaddr, 0, sizeof(m->yiaddr)); + memset(m->siaddr, 0, sizeof(m->siaddr)); + memset(m->giaddr, 0, sizeof(m->giaddr)); + memcpy(m->chaddr, s.mac_addr, s.mac_len); + memset(&m->chaddr[s.mac_len], 0, sizeof(m->chaddr) - s.mac_len); +#ifndef CONFIG_UIP_DHCP_LIGHT + memset(m->sname, 0, sizeof(m->sname)); + memset(m->file, 0, sizeof(m->file)); +#endif + + memcpy(m->options, magic_cookie, sizeof(magic_cookie)); +} + +static void send_discover(void) +{ + uint8 *end; + struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata; + + create_msg(m); + + end = add_msg_type(&m->options[4], DHCPDISCOVER); + end = add_req_options(end); + end = add_end(end); + + uip_send(uip_appdata, end - (uint8 *)uip_appdata); +} + +static void send_request(void) +{ + uint8 *end; + struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata; + + create_msg(m); + + end = add_msg_type(&m->options[4], DHCPREQUEST); + end = add_server_id(end); + end = add_req_ipaddr(end); + end = add_end(end); + + uip_send(uip_appdata, end - (uint8 *)uip_appdata); +} + +static uint8 parse_options(uint8 *optptr, int len) +{ + uint8 *end = optptr + len; + uint8 type = 0; + + while (optptr < end) + { + switch(*optptr) + { + case DHCP_OPTION_SUBNET_MASK: + memcpy(s.netmask, optptr + 2, 4); + break; + case DHCP_OPTION_ROUTER: + memcpy(s.default_router, optptr + 2, 4); + break; + case DHCP_OPTION_DNS_SERVER: + memcpy(s.dnsaddr, optptr + 2, 4); + break; + case DHCP_OPTION_MSG_TYPE: + type = *(optptr + 2); + break; + case DHCP_OPTION_SERVER_ID: + memcpy(s.serverid, optptr + 2, 4); + break; + case DHCP_OPTION_LEASE_TIME: + memcpy(s.lease_time, optptr + 2, 4); + break; + case DHCP_OPTION_END: + return type; + } + + optptr += optptr[1] + 2; + } + return type; +} + +static uint8 parse_msg(void) +{ + struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata; + + if (m->op == DHCP_REPLY && + memcmp(m->xid, xid, sizeof(xid)) == 0 && + memcmp(m->chaddr, s.mac_addr, s.mac_len) == 0) + { + memcpy(s.ipaddr, m->yiaddr, 4); + return parse_options(&m->options[4], uip_datalen()); + } + return 0; +} + +static void handle_dhcp(void) +{ +restart: + s.state = STATE_SENDING; + s.ticks = CLOCK_SECOND; + + do + { + /* Send the command */ + + send_discover(); + + /* Wait for the response */ + + uip_event_timedwait(UIP_NEWDATA, CLOCK_SECOND); + + if (uip_newdata() && parse_msg() == DHCPOFFER) + { + s.state = STATE_OFFER_RECEIVED; + break; + } + + if (s.ticks < CLOCK_SECOND * 60) + { + s.ticks *= 2; + } + } + while(s.state != STATE_OFFER_RECEIVED); + + s.ticks = CLOCK_SECOND; + + do + { + /* Send the request */ + + send_request(); + + /* Then wait to received the response */ + + uip_event_timedwait(UIP_NEWDATA, CLOCK_SECOND); + + if (uip_newdata() && parse_msg() == DHCPACK) + { + s.state = STATE_CONFIG_RECEIVED; + break; + } + + if (s.ticks <= CLOCK_SECOND * 10) + { + s.ticks += CLOCK_SECOND; + } + else + { + goto restart; + } + } + while(s.state != STATE_CONFIG_RECEIVED); + + dbg("Got IP address %d.%d.%d.%d\n", + uip_ipaddr1(s.ipaddr), uip_ipaddr2(s.ipaddr), + uip_ipaddr3(s.ipaddr), uip_ipaddr4(s.ipaddr)); + dbg("Got netmask %d.%d.%d.%d\n", + uip_ipaddr1(s.netmask), uip_ipaddr2(s.netmask), + uip_ipaddr3(s.netmask), uip_ipaddr4(s.netmask)); + dbg("Got DNS server %d.%d.%d.%d\n", + uip_ipaddr1(s.dnsaddr), uip_ipaddr2(s.dnsaddr), + uip_ipaddr3(s.dnsaddr), uip_ipaddr4(s.dnsaddr)); + dbg("Got default router %d.%d.%d.%d\n", + uip_ipaddr1(s.default_router), uip_ipaddr2(s.default_router), + uip_ipaddr3(s.default_router), uip_ipaddr4(s.default_router)); + dbg("Lease expires in %ld seconds\n", + ntohs(s.lease_time[0])*65536ul + ntohs(s.lease_time[1])); + + dhcpc_configured(&s); + + pthread_exit(NULL); +} + +/************************************************************ + * Global Functions + ************************************************************/ + +void dhcpc_init(const void *mac_addr, int mac_len) +{ + uip_ipaddr_t addr; + + s.mac_addr = mac_addr; + s.mac_len = mac_len; + + s.state = STATE_INITIAL; + uip_ipaddr(addr, 255,255,255,255); + s.conn = uip_udp_new(&addr, HTONS(DHCPC_SERVER_PORT)); + if (s.conn != NULL) + { + uip_udp_bind(s.conn, HTONS(DHCPC_CLIENT_PORT)); + } +} + +/* This function is called by the UIP interrupt handling logic whenevent an + * event of interest occurs. + */ + +void uip_interrupt_udp_event(void) +{ + handle_dhcp(); +} + +void dhcpc_request(void) +{ + uint16 ipaddr[2]; + + if (s.state == STATE_INITIAL) + { + uip_ipaddr(ipaddr, 0,0,0,0); + uip_sethostaddr(ipaddr); + } +} diff --git a/nuttx/netutils/dhcpc/dhcpc.h b/nuttx/netutils/dhcpc/dhcpc.h new file mode 100644 index 000000000..b46ae4dfd --- /dev/null +++ b/nuttx/netutils/dhcpc/dhcpc.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2005, 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the uIP TCP/IP stack + * + * @(#)$Id: dhcpc.h,v 1.1.1.1 2007-08-26 23:07:02 patacongo Exp $ + */ +#ifndef __DHCPC_H__ +#define __DHCPC_H__ + +#include <sys/types.h> + +struct dhcpc_state { + char state; + struct uip_udp_conn *conn; + uint16 ticks; + const void *mac_addr; + int mac_len; + + uint8 serverid[4]; + + uint16 lease_time[2]; + uint16 ipaddr[2]; + uint16 netmask[2]; + uint16 dnsaddr[2]; + uint16 default_router[2]; +}; + +void dhcpc_init(const void *mac_addr, int mac_len); +void dhcpc_request(void); +void dhcpc_configured(const struct dhcpc_state *s); + +#endif /* __DHCPC_H__ */ diff --git a/nuttx/netutils/resolv/Make.defs b/nuttx/netutils/resolv/Make.defs new file mode 100644 index 000000000..e83757d36 --- /dev/null +++ b/nuttx/netutils/resolv/Make.defs @@ -0,0 +1,39 @@ +############################################################################ +# Make.defs +# +# Copyright (C) 2007 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################################ + +ifeq ($(CONFIG_UIP_UDP),y) +RESOLV_ASRCS = +RESOLV_CSRCS = resolv.c +endif diff --git a/nuttx/netutils/resolv/resolv.c b/nuttx/netutils/resolv/resolv.c new file mode 100644 index 000000000..0a38faea8 --- /dev/null +++ b/nuttx/netutils/resolv/resolv.c @@ -0,0 +1,450 @@ +/* uip-resolv.c + * DNS host name to IP address resolver. + * Author: Adam Dunkels <adam@dunkels.com> + * + * The uIP DNS resolver functions are used to lookup a hostname and + * map it to a numerical IP address. It maintains a list of resolved + * hostnames that can be queried with the resolv_lookup() + * function. New hostnames can be resolved using the resolv_query() + * function. + * + * When a hostname has been resolved (or found to be non-existant), + * the resolver code calls a callback function called resolv_found() + * that must be implemented by the module that uses the resolver. + * + * Copyright (c) 2002-2003, Adam Dunkels. + * 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 uIP TCP/IP stack. + * + * $Id: resolv.c,v 1.1.1.1 2007-08-26 23:07:05 patacongo Exp $ + * + */ + +#include <sys/types.h> +#include <string.h> + +#include <net/uip/uip.h> +#include <net/uip/resolv.h> + +#ifndef NULL +#define NULL (void *)0 +#endif /* NULL */ + +/** \internal The maximum number of retries when asking for a name. */ +#define MAX_RETRIES 8 + +/** \internal The DNS message header. */ +struct dns_hdr { + uint16 id; + uint8 flags1, flags2; +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + uint16 numquestions; + uint16 numanswers; + uint16 numauthrr; + uint16 numextrarr; +}; + +/** \internal The DNS answer message structure. */ +struct dns_answer { + /* DNS answer record starts with either a domain name or a pointer + to a name already present somewhere in the packet. */ + uint16 type; + uint16 class; + uint16 ttl[2]; + uint16 len; + uip_ipaddr_t ipaddr; +}; + +struct namemap { +#define STATE_UNUSED 0 +#define STATE_NEW 1 +#define STATE_ASKING 2 +#define STATE_DONE 3 +#define STATE_ERROR 4 + uint8 state; + uint8 tmr; + uint8 retries; + uint8 seqno; + uint8 err; + char name[32]; + uip_ipaddr_t ipaddr; +}; + +#ifndef CONFIG_UIP_RESOLV_ENTRIES +#define RESOLV_ENTRIES 4 +#else /* CONFIG_UIP_RESOLV_ENTRIES */ +#define RESOLV_ENTRIES CONFIG_UIP_RESOLV_ENTRIES +#endif /* CONFIG_UIP_RESOLV_ENTRIES */ + + +static struct namemap names[RESOLV_ENTRIES]; + +static uint8 seqno; + +static struct uip_udp_conn *resolv_conn = NULL; + + +/*---------------------------------------------------------------------------*/ +/** \internal + * Walk through a compact encoded DNS name and return the end of it. + * + * \return The end of the name. + */ +/*---------------------------------------------------------------------------*/ +static unsigned char *parse_name(unsigned char *query) +{ + unsigned char n; + + do { + n = *query++; + + while(n > 0) + { + ++query; + --n; + }; + } while(*query != 0); + return query + 1; +} + +/*---------------------------------------------------------------------------*/ +/** \internal + * Runs through the list of names to see if there are any that have + * not yet been queried and, if so, sends out a query. + */ +/*---------------------------------------------------------------------------*/ +static void +check_entries(void) +{ + register struct dns_hdr *hdr; + char *query, *nptr, *nameptr; + static uint8 i; + static uint8 n; + register struct namemap *namemapptr; + + for(i = 0; i < RESOLV_ENTRIES; ++i) { + namemapptr = &names[i]; + if(namemapptr->state == STATE_NEW || + namemapptr->state == STATE_ASKING) { + if(namemapptr->state == STATE_ASKING) { + if(--namemapptr->tmr == 0) { + if(++namemapptr->retries == MAX_RETRIES) { + namemapptr->state = STATE_ERROR; + resolv_found(namemapptr->name, NULL); + continue; + } + namemapptr->tmr = namemapptr->retries; + } else { + /* printf("Timer %d\n", namemapptr->tmr);*/ + /* Its timer has not run out, so we move on to next + entry. */ + continue; + } + } else { + namemapptr->state = STATE_ASKING; + namemapptr->tmr = 1; + namemapptr->retries = 0; + } + hdr = (struct dns_hdr *)uip_appdata; + memset(hdr, 0, sizeof(struct dns_hdr)); + hdr->id = htons(i); + hdr->flags1 = DNS_FLAG1_RD; + hdr->numquestions = HTONS(1); + query = (char *)uip_appdata + 12; + nameptr = namemapptr->name; + --nameptr; + /* Convert hostname into suitable query format. */ + do { + ++nameptr; + nptr = query; + ++query; + for(n = 0; *nameptr != '.' && *nameptr != 0; ++nameptr) { + *query = *nameptr; + ++query; + ++n; + } + *nptr = n; + } while(*nameptr != 0); + { + static unsigned char endquery[] = + {0,0,1,0,1}; + memcpy(query, endquery, 5); + } + uip_udp_send((unsigned char)(query + 5 - (char *)uip_appdata)); + break; + } + } +} +/*---------------------------------------------------------------------------*/ +/** \internal + * Called when new UDP data arrives. + */ +/*---------------------------------------------------------------------------*/ +static void +newdata(void) +{ + unsigned char *nameptr; + struct dns_answer *ans; + struct dns_hdr *hdr; + static uint8 nquestions, nanswers; + static uint8 i; + register struct namemap *namemapptr; + + hdr = (struct dns_hdr *)uip_appdata; + /* printf("ID %d\n", htons(hdr->id)); + printf("Query %d\n", hdr->flags1 & DNS_FLAG1_RESPONSE); + printf("Error %d\n", hdr->flags2 & DNS_FLAG2_ERR_MASK); + printf("Num questions %d, answers %d, authrr %d, extrarr %d\n", + htons(hdr->numquestions), + htons(hdr->numanswers), + htons(hdr->numauthrr), + htons(hdr->numextrarr)); + */ + + /* The ID in the DNS header should be our entry into the name + table. */ + i = htons(hdr->id); + namemapptr = &names[i]; + if(i < RESOLV_ENTRIES && + namemapptr->state == STATE_ASKING) { + + /* This entry is now finished. */ + namemapptr->state = STATE_DONE; + namemapptr->err = hdr->flags2 & DNS_FLAG2_ERR_MASK; + + /* Check for error. If so, call callback to inform. */ + if(namemapptr->err != 0) { + namemapptr->state = STATE_ERROR; + resolv_found(namemapptr->name, NULL); + return; + } + + /* We only care about the question(s) and the answers. The authrr + and the extrarr are simply discarded. */ + nquestions = htons(hdr->numquestions); + nanswers = htons(hdr->numanswers); + + /* Skip the name in the question. XXX: This should really be + checked agains the name in the question, to be sure that they + match. */ + nameptr = parse_name((unsigned char *)uip_appdata + 12) + 4; + + while(nanswers > 0) { + /* The first byte in the answer resource record determines if it + is a compressed record or a normal one. */ + if(*nameptr & 0xc0) { + /* Compressed name. */ + nameptr +=2; + /* printf("Compressed anwser\n");*/ + } else { + /* Not compressed name. */ + nameptr = parse_name(nameptr); + } + + ans = (struct dns_answer *)nameptr; + /* printf("Answer: type %x, class %x, ttl %x, length %x\n", + htons(ans->type), htons(ans->class), (htons(ans->ttl[0]) + << 16) | htons(ans->ttl[1]), htons(ans->len));*/ + + /* Check for IP address type and Internet class. Others are + discarded. */ + if(ans->type == HTONS(1) && + ans->class == HTONS(1) && + ans->len == HTONS(4)) { + /* printf("IP address %d.%d.%d.%d\n", + htons(ans->ipaddr[0]) >> 8, + htons(ans->ipaddr[0]) & 0xff, + htons(ans->ipaddr[1]) >> 8, + htons(ans->ipaddr[1]) & 0xff);*/ + /* XXX: we should really check that this IP address is the one + we want. */ + namemapptr->ipaddr[0] = ans->ipaddr[0]; + namemapptr->ipaddr[1] = ans->ipaddr[1]; + + resolv_found(namemapptr->name, namemapptr->ipaddr); + return; + } else { + nameptr = nameptr + 10 + htons(ans->len); + } + --nanswers; + } + } + +} + +/* This function is called by the UIP interrupt handling logic whenevent an + * event of interest occurs. + */ + +void uip_interrupt_udp_event(void) +{ + if(uip_udp_conn->rport == HTONS(53)) + { + if(uip_poll()) + { + check_entries(); + } + if(uip_newdata()) + { + newdata(); + } + } +} + +/** + * Queues a name so that a question for the name will be sent out. + * + * \param name The hostname that is to be queried. + */ +/*---------------------------------------------------------------------------*/ +void +resolv_query(char *name) +{ + static uint8 i; + static uint8 lseq, lseqi; + register struct namemap *nameptr; + + lseq = lseqi = 0; + + for(i = 0; i < RESOLV_ENTRIES; ++i) { + nameptr = &names[i]; + if(nameptr->state == STATE_UNUSED) { + break; + } + if(seqno - nameptr->seqno > lseq) { + lseq = seqno - nameptr->seqno; + lseqi = i; + } + } + + if(i == RESOLV_ENTRIES) { + i = lseqi; + nameptr = &names[i]; + } + + /* printf("Using entry %d\n", i);*/ + + strcpy(nameptr->name, name); + nameptr->state = STATE_NEW; + nameptr->seqno = seqno; + ++seqno; +} +/*---------------------------------------------------------------------------*/ +/** + * Look up a hostname in the array of known hostnames. + * + * \note This function only looks in the internal array of known + * hostnames, it does not send out a query for the hostname if none + * was found. The function resolv_query() can be used to send a query + * for a hostname. + * + * \return A pointer to a 4-byte representation of the hostname's IP + * address, or NULL if the hostname was not found in the array of + * hostnames. + */ +/*---------------------------------------------------------------------------*/ +uint16 * +resolv_lookup(char *name) +{ + static uint8 i; + struct namemap *nameptr; + + /* Walk through the list to see if the name is in there. If it is + not, we return NULL. */ + for(i = 0; i < RESOLV_ENTRIES; ++i) { + nameptr = &names[i]; + if(nameptr->state == STATE_DONE && + strcmp(name, nameptr->name) == 0) { + return nameptr->ipaddr; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +/** + * Obtain the currently configured DNS server. + * + * \return A pointer to a 4-byte representation of the IP address of + * the currently configured DNS server or NULL if no DNS server has + * been configured. + */ +/*---------------------------------------------------------------------------*/ +uint16 * +resolv_getserver(void) +{ + if(resolv_conn == NULL) { + return NULL; + } + return resolv_conn->ripaddr; +} +/*---------------------------------------------------------------------------*/ +/** + * Configure which DNS server to use for queries. + * + * \param dnsserver A pointer to a 4-byte representation of the IP + * address of the DNS server to be configured. + */ +/*---------------------------------------------------------------------------*/ +void +resolv_conf(uint16 *dnsserver) +{ + if(resolv_conn != NULL) { + uip_udp_remove(resolv_conn); + } + + resolv_conn = uip_udp_new(dnsserver, HTONS(53)); +} +/*---------------------------------------------------------------------------*/ +/** + * Initalize the resolver. + */ +/*---------------------------------------------------------------------------*/ +void +resolv_init(void) +{ + static uint8 i; + + for(i = 0; i < RESOLV_ENTRIES; ++i) { + names[i].state = STATE_DONE; + } + +} +/*---------------------------------------------------------------------------*/ + +/** @} */ +/** @} */ diff --git a/nuttx/netutils/smtp/Make.defs b/nuttx/netutils/smtp/Make.defs new file mode 100644 index 000000000..b749677c9 --- /dev/null +++ b/nuttx/netutils/smtp/Make.defs @@ -0,0 +1,38 @@ +############################################################################ +# Make.defs +# +# Copyright (C) 2007 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################################ + +# Does not build +# SMTP_ASRCS = +# SMTP_CSRCS = smtp.c smtp-strings.c diff --git a/nuttx/netutils/smtp/makestrings b/nuttx/netutils/smtp/makestrings new file mode 100755 index 000000000..bea18a6c3 --- /dev/null +++ b/nuttx/netutils/smtp/makestrings @@ -0,0 +1,40 @@ +#!/usr/bin/perl + + +sub stringify { + my $name = shift(@_); + open(OUTPUTC, "> $name.c"); + open(OUTPUTH, "> $name.h"); + + open(FILE, "$name"); + + while(<FILE>) { + if(/(.+) "(.+)"/) { + $var = $1; + $data = $2; + + $datan = $data; + $datan =~ s/\\r/\r/g; + $datan =~ s/\\n/\n/g; + $datan =~ s/\\01/\01/g; + $datan =~ s/\\0/\0/g; + + printf(OUTPUTC "const char $var\[%d] = \n", length($datan) + 1); + printf(OUTPUTC "/* \"$data\" */\n"); + printf(OUTPUTC "{"); + for($j = 0; $j < length($datan); $j++) { + printf(OUTPUTC "%#02x, ", unpack("C", substr($datan, $j, 1))); + } + printf(OUTPUTC "};\n"); + + printf(OUTPUTH "extern const char $var\[%d];\n", length($datan) + 1); + + } + } + close(OUTPUTC); + close(OUTPUTH); +} +stringify("smtp-strings"); + +exit 0; + diff --git a/nuttx/netutils/smtp/smtp-strings b/nuttx/netutils/smtp/smtp-strings new file mode 100644 index 000000000..27f639c2e --- /dev/null +++ b/nuttx/netutils/smtp/smtp-strings @@ -0,0 +1,11 @@ +smtp_220 "220" +smtp_helo "HELO " +smtp_mail_from "MAIL FROM: " +smtp_rcpt_to "RCPT TO: " +smtp_data "DATA\r\n" +smtp_to "To: " +smtp_from "From: " +smtp_subject "Subject: " +smtp_quit "QUIT\r\n" +smtp_crnl "\r\n" +smtp_crnlperiodcrnl "\r\n.\r\n"
\ No newline at end of file diff --git a/nuttx/netutils/smtp/smtp-strings.c b/nuttx/netutils/smtp/smtp-strings.c new file mode 100644 index 000000000..ab216ef0b --- /dev/null +++ b/nuttx/netutils/smtp/smtp-strings.c @@ -0,0 +1,33 @@ +const char smtp_220[4] = +/* "220" */ +{0x32, 0x32, 0x30, }; +const char smtp_helo[6] = +/* "HELO " */ +{0x48, 0x45, 0x4c, 0x4f, 0x20, }; +const char smtp_mail_from[12] = +/* "MAIL FROM: " */ +{0x4d, 0x41, 0x49, 0x4c, 0x20, 0x46, 0x52, 0x4f, 0x4d, 0x3a, 0x20, }; +const char smtp_rcpt_to[10] = +/* "RCPT TO: " */ +{0x52, 0x43, 0x50, 0x54, 0x20, 0x54, 0x4f, 0x3a, 0x20, }; +const char smtp_data[7] = +/* "DATA\r\n" */ +{0x44, 0x41, 0x54, 0x41, 0xd, 0xa, }; +const char smtp_to[5] = +/* "To: " */ +{0x54, 0x6f, 0x3a, 0x20, }; +const char smtp_from[7] = +/* "From: " */ +{0x46, 0x72, 0x6f, 0x6d, 0x3a, 0x20, }; +const char smtp_subject[10] = +/* "Subject: " */ +{0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3a, 0x20, }; +const char smtp_quit[7] = +/* "QUIT\r\n" */ +{0x51, 0x55, 0x49, 0x54, 0xd, 0xa, }; +const char smtp_crnl[3] = +/* "\r\n" */ +{0xd, 0xa, }; +const char smtp_crnlperiodcrnl[6] = +/* "\r\n.\r\n" */ +{0xd, 0xa, 0x2e, 0xd, 0xa, }; diff --git a/nuttx/netutils/smtp/smtp-strings.h b/nuttx/netutils/smtp/smtp-strings.h new file mode 100644 index 000000000..4bff8583c --- /dev/null +++ b/nuttx/netutils/smtp/smtp-strings.h @@ -0,0 +1,11 @@ +extern const char smtp_220[4]; +extern const char smtp_helo[6]; +extern const char smtp_mail_from[12]; +extern const char smtp_rcpt_to[10]; +extern const char smtp_data[7]; +extern const char smtp_to[5]; +extern const char smtp_from[7]; +extern const char smtp_subject[10]; +extern const char smtp_quit[7]; +extern const char smtp_crnl[3]; +extern const char smtp_crnlperiodcrnl[6]; diff --git a/nuttx/netutils/smtp/smtp.c b/nuttx/netutils/smtp/smtp.c new file mode 100644 index 000000000..98dd468e3 --- /dev/null +++ b/nuttx/netutils/smtp/smtp.c @@ -0,0 +1,252 @@ +/* smtp.c + * smtp SMTP E-mail sender + * Author: Adam Dunkels <adam@dunkels.com> + * + * The Simple Mail Transfer Protocol (SMTP) as defined by RFC821 is + * the standard way of sending and transfering e-mail on the + * Internet. This simple example implementation is intended as an + * example of how to implement protocols in uIP, and is able to send + * out e-mail but has not been extensively tested. + * + * Copyright (c) 2004, Adam Dunkels. + * 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the uIP TCP/IP stack. + * + * Author: Adam Dunkels <adam@sics.se> + * + * $Id: smtp.c,v 1.1.1.1 2007-08-26 23:07:06 patacongo Exp $ + */ + +#include <sys/types.h> +#include <string.h> + +#include <net/uip/uip.h> +#include <net/uip/psock.h> +#include <net/uip/smtp.h> + +#include "smtp-strings.h" + +static struct smtp_state s; + +static char *localhostname; +static uip_ipaddr_t smtpserver; + +#define ISO_nl 0x0a +#define ISO_cr 0x0d + +#define ISO_period 0x2e + +#define ISO_2 0x32 +#define ISO_3 0x33 +#define ISO_4 0x34 +#define ISO_5 0x35 + + +/*---------------------------------------------------------------------------*/ +static +void smtp_thread(void) +{ + psock_readto(&s.psock, ISO_nl); + + if(strncmp(s.inputbuffer, smtp_220, 3) != 0) { + PSOCK_CLOSE(&s.psock); + smtp_done(2); + pthread_exit(NULL); + } + + PSOCK_SEND_STR(&s.psock, (char *)smtp_helo); + PSOCK_SEND_STR(&s.psock, localhostname); + PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); + + psock_readto(&s.psock, ISO_nl); + + if(s.inputbuffer[0] != ISO_2) { + PSOCK_CLOSE(&s.psock); + smtp_done(3); + pthread_exit(NULL); + } + + PSOCK_SEND_STR(&s.psock, (char *)smtp_mail_from); + PSOCK_SEND_STR(&s.psock, s.from); + PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); + + psock_readto(&s.psock, ISO_nl); + + if(s.inputbuffer[0] != ISO_2) { + PSOCK_CLOSE(&s.psock); + smtp_done(4); + pthread_exit(NULL); + } + + PSOCK_SEND_STR(&s.psock, (char *)smtp_rcpt_to); + PSOCK_SEND_STR(&s.psock, s.to); + PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); + + psock_readto(&s.psock, ISO_nl); + + if(s.inputbuffer[0] != ISO_2) { + PSOCK_CLOSE(&s.psock); + smtp_done(5); + pthread_exit(NULL); + } + + if(s.cc != 0) { + PSOCK_SEND_STR(&s.psock, (char *)smtp_rcpt_to); + PSOCK_SEND_STR(&s.psock, s.cc); + PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); + + psock_readto(&s.psock, ISO_nl); + + if(s.inputbuffer[0] != ISO_2) { + PSOCK_CLOSE(&s.psock); + smtp_done(6); + pthread_exit(NULL); + } + } + + PSOCK_SEND_STR(&s.psock, (char *)smtp_data); + + psock_readto(&s.psock, ISO_nl); + + if(s.inputbuffer[0] != ISO_3) { + PSOCK_CLOSE(&s.psock); + smtp_done(7); + pthread_exit(NULL); + } + + PSOCK_SEND_STR(&s.psock, (char *)smtp_to); + PSOCK_SEND_STR(&s.psock, s.to); + PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); + + if(s.cc != 0) { + PSOCK_SEND_STR(&s.psock, (char *)smtp_cc); + PSOCK_SEND_STR(&s.psock, s.cc); + PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); + } + + PSOCK_SEND_STR(&s.psock, (char *)smtp_from); + PSOCK_SEND_STR(&s.psock, s.from); + PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); + + PSOCK_SEND_STR(&s.psock, (char *)smtp_subject); + PSOCK_SEND_STR(&s.psock, s.subject); + PSOCK_SEND_STR(&s.psock, (char *)smtp_crnl); + + psock_send(&s.psock, s.msg, s.msglen); + + PSOCK_SEND_STR(&s.psock, (char *)smtp_crnlperiodcrnl); + + psock_readto(&s.psock, ISO_nl); + if(s.inputbuffer[0] != ISO_2) { + PSOCK_CLOSE(&s.psock); + smtp_done(8); + pthread_exit(NULL); + } + + PSOCK_SEND_STR(&s.psock, (char *)smtp_quit); + smtp_done(SMTP_ERR_OK); +} + +/* This function is called by the UIP interrupt handling logic whenevent an + * event of interest occurs. + */ + +void uip_interrupt_event(void) +{ + if(uip_closed()) { + s.connected = 0; + return; + } + if(uip_aborted() || uip_timedout()) { + s.connected = 0; + smtp_done(1); + return; + } + smtp_thread(); +} + +/*---------------------------------------------------------------------------*/ +/** + * Specificy an SMTP server and hostname. + * + * This function is used to configure the SMTP module with an SMTP + * server and the hostname of the host. + * + * \param lhostname The hostname of the uIP host. + * + * \param server A pointer to a 4-byte array representing the IP + * address of the SMTP server to be configured. + */ +void +smtp_configure(char *lhostname, void *server) +{ + localhostname = lhostname; + uip_ipaddr_copy(smtpserver, server); +} +/*---------------------------------------------------------------------------*/ +/** + * Send an e-mail. + * + * \param to The e-mail address of the receiver of the e-mail. + * \param cc The e-mail address of the CC: receivers of the e-mail. + * \param from The e-mail address of the sender of the e-mail. + * \param subject The subject of the e-mail. + * \param msg The actual e-mail message. + * \param msglen The length of the e-mail message. + */ +unsigned char +smtp_send(char *to, char *cc, char *from, + char *subject, char *msg, uint16 msglen) +{ + struct uip_conn *conn; + + conn = uip_connect(smtpserver, HTONS(25)); + if(conn == NULL) { + return 0; + } + s.connected = 1; + s.to = to; + s.cc = cc; + s.from = from; + s.subject = subject; + s.msg = msg; + s.msglen = msglen; + + psock_init(&s.psock, s.inputbuffer, sizeof(s.inputbuffer)); + + return 1; +} +/*---------------------------------------------------------------------------*/ +void +smtp_init(void) +{ + s.connected = 0; +} +/*---------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/nuttx/netutils/telnetd/Make.defs b/nuttx/netutils/telnetd/Make.defs new file mode 100644 index 000000000..7aafdfd27 --- /dev/null +++ b/nuttx/netutils/telnetd/Make.defs @@ -0,0 +1,37 @@ +############################################################################ +# Make.defs +# +# Copyright (C) 2007 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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. Neither the name Nuttx nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################################ + +TELNETD_ASRCS = +TELNETD_CSRCS = telnetd.c shell.c diff --git a/nuttx/netutils/telnetd/shell.c b/nuttx/netutils/telnetd/shell.c new file mode 100644 index 000000000..2c1ddbaae --- /dev/null +++ b/nuttx/netutils/telnetd/shell.c @@ -0,0 +1,123 @@ + /* + * Copyright (c) 2003, Adam Dunkels. + * 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 uIP TCP/IP stack. + * + * $Id: shell.c,v 1.1.1.1 2007-08-26 23:07:06 patacongo Exp $ + * + */ + +#include "shell.h" + +#include <string.h> + +struct ptentry { + char *commandstr; + void (* pfunc)(char *str); +}; + +#define SHELL_PROMPT "uIP 1.0> " + +/*---------------------------------------------------------------------------*/ +static void +parse(register char *str, struct ptentry *t) +{ + struct ptentry *p; + for(p = t; p->commandstr != NULL; ++p) { + if(strncmp(p->commandstr, str, strlen(p->commandstr)) == 0) { + break; + } + } + + p->pfunc(str); +} +/*---------------------------------------------------------------------------*/ +static void +inttostr(register char *str, unsigned int i) +{ + str[0] = '0' + i / 100; + if(str[0] == '0') { + str[0] = ' '; + } + str[1] = '0' + (i / 10) % 10; + if(str[0] == ' ' && str[1] == '0') { + str[1] = ' '; + } + str[2] = '0' + i % 10; + str[3] = ' '; + str[4] = 0; +} +/*---------------------------------------------------------------------------*/ +static void +help(char *str) +{ + shell_output("Available commands:", ""); + shell_output("stats - show network statistics", ""); + shell_output("conn - show TCP connections", ""); + shell_output("help, ? - show help", ""); + shell_output("exit - exit shell", ""); +} +/*---------------------------------------------------------------------------*/ +static void +unknown(char *str) +{ + if(strlen(str) > 0) { + shell_output("Unknown command: ", str); + } +} +/*---------------------------------------------------------------------------*/ +static struct ptentry parsetab[] = + {{"stats", help}, + {"conn", help}, + {"help", help}, + {"exit", shell_quit}, + {"?", help}, + + /* Default action */ + {NULL, unknown}}; +/*---------------------------------------------------------------------------*/ +void +shell_init(void) +{ +} +/*---------------------------------------------------------------------------*/ +void +shell_start(void) +{ + shell_output("uIP command shell", ""); + shell_output("Type '?' and return for help", ""); + shell_prompt(SHELL_PROMPT); +} +/*---------------------------------------------------------------------------*/ +void +shell_input(char *cmd) +{ + parse(cmd, parsetab); + shell_prompt(SHELL_PROMPT); +} +/*---------------------------------------------------------------------------*/ diff --git a/nuttx/netutils/telnetd/shell.h b/nuttx/netutils/telnetd/shell.h new file mode 100644 index 000000000..7d81849c7 --- /dev/null +++ b/nuttx/netutils/telnetd/shell.h @@ -0,0 +1,104 @@ +/** + * \file + * Interface for the Contiki shell. + * \author Adam Dunkels <adam@dunkels.com> + * + * Some of the functions declared in this file must be implemented as + * a shell back-end in the architecture specific files of a Contiki + * port. + */ + + +/* + * Copyright (c) 2003, Adam Dunkels. + * 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 Contiki desktop OS. + * + * $Id: shell.h,v 1.1.1.1 2007-08-26 23:07:06 patacongo Exp $ + * + */ +#ifndef __SHELL_H__ +#define __SHELL_H__ + +/** + * Initialize the shell. + * + * Called when the shell front-end process starts. This function may + * be used to start listening for signals. + */ +void shell_init(void); + +/** + * Start the shell back-end. + * + * Called by the front-end when a new shell is started. + */ +void shell_start(void); + +/** + * Process a shell command. + * + * This function will be called by the shell GUI / telnet server whan + * a command has been entered that should be processed by the shell + * back-end. + * + * \param command The command to be processed. + */ +void shell_input(char *command); + +/** + * Quit the shell. + * + */ +void shell_quit(char *); + + +/** + * Print a string to the shell window. + * + * This function is implemented by the shell GUI / telnet server and + * can be called by the shell back-end to output a string in the + * shell window. The string is automatically appended with a linebreak. + * + * \param str1 The first half of the string to be output. + * \param str2 The second half of the string to be output. + */ +void shell_output(char *str1, char *str2); + +/** + * Print a prompt to the shell window. + * + * This function can be used by the shell back-end to print out a + * prompt to the shell window. + * + * \param prompt The prompt to be printed. + * + */ +void shell_prompt(char *prompt); + +#endif /* __SHELL_H__ */ diff --git a/nuttx/netutils/telnetd/telnetd.c b/nuttx/netutils/telnetd/telnetd.c new file mode 100644 index 000000000..21700023c --- /dev/null +++ b/nuttx/netutils/telnetd/telnetd.c @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2003, Adam Dunkels. + * 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 uIP TCP/IP stack + * + * $Id: telnetd.c,v 1.1.1.1 2007-08-26 23:07:06 patacongo Exp $ + * + */ + +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> + +#include <net/uip/uip.h> + +#include "telnetd.h" +#include "shell.h" + +#define ISO_nl 0x0a +#define ISO_cr 0x0d + +#define STATE_NORMAL 0 +#define STATE_IAC 1 +#define STATE_WILL 2 +#define STATE_WONT 3 +#define STATE_DO 4 +#define STATE_DONT 5 +#define STATE_CLOSE 6 + +static struct telnetd_state s; + +#define TELNET_IAC 255 +#define TELNET_WILL 251 +#define TELNET_WONT 252 +#define TELNET_DO 253 +#define TELNET_DONT 254 + +/*---------------------------------------------------------------------------*/ +void +shell_quit(char *str) +{ + s.state = STATE_CLOSE; +} + +/*---------------------------------------------------------------------------*/ +static void +sendline(char *line) +{ + static unsigned int i; + + for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) { + if(s.lines[i] == NULL) { + s.lines[i] = line; + break; + } + } + if(i == TELNETD_CONF_NUMLINES) { + free(line); + } +} +/*---------------------------------------------------------------------------*/ +void +shell_prompt(char *str) +{ + char *line; + line = (char*)malloc(TELNETD_CONF_LINELEN); + if(line != NULL) { + strncpy(line, str, TELNETD_CONF_LINELEN); + /* petsciiconv_toascii(line, TELNETD_CONF_LINELEN);*/ + sendline(line); + } +} +/*---------------------------------------------------------------------------*/ +void +shell_output(char *str1, char *str2) +{ + static unsigned len; + char *line; + + line = (char*)malloc(TELNETD_CONF_LINELEN); + if(line != NULL) { + len = strlen(str1); + strncpy(line, str1, TELNETD_CONF_LINELEN); + if(len < TELNETD_CONF_LINELEN) { + strncpy(line + len, str2, TELNETD_CONF_LINELEN - len); + } + len = strlen(line); + if(len < TELNETD_CONF_LINELEN - 2) { + line[len] = ISO_cr; + line[len+1] = ISO_nl; + line[len+2] = 0; + } + /* petsciiconv_toascii(line, TELNETD_CONF_LINELEN);*/ + sendline(line); + } +} +/*---------------------------------------------------------------------------*/ +void +telnetd_init(void) +{ + uip_listen(HTONS(23)); + shell_init(); +} +/*---------------------------------------------------------------------------*/ +static void +acked(void) +{ + static unsigned int i; + + while(s.numsent > 0) { + free(s.lines[0]); + for(i = 1; i < TELNETD_CONF_NUMLINES; ++i) { + s.lines[i - 1] = s.lines[i]; + } + s.lines[TELNETD_CONF_NUMLINES - 1] = NULL; + --s.numsent; + } +} +/*---------------------------------------------------------------------------*/ +static void +senddata(void) +{ + static char *bufptr, *lineptr; + static int buflen, linelen; + + bufptr = uip_appdata; + buflen = 0; + for(s.numsent = 0; s.numsent < TELNETD_CONF_NUMLINES && + s.lines[s.numsent] != NULL ; ++s.numsent) { + lineptr = s.lines[s.numsent]; + linelen = strlen(lineptr); + if(linelen > TELNETD_CONF_LINELEN) { + linelen = TELNETD_CONF_LINELEN; + } + if(buflen + linelen < uip_mss()) { + memcpy(bufptr, lineptr, linelen); + bufptr += linelen; + buflen += linelen; + } else { + break; + } + } + uip_send(uip_appdata, buflen); +} +/*---------------------------------------------------------------------------*/ +static void +closed(void) +{ + static unsigned int i; + + for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) { + if(s.lines[i] != NULL) { + free(s.lines[i]); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +get_char(uint8 c) +{ + if(c == ISO_cr) { + return; + } + + s.buf[(int)s.bufptr] = c; + if(s.buf[(int)s.bufptr] == ISO_nl || + s.bufptr == sizeof(s.buf) - 1) { + if(s.bufptr > 0) { + s.buf[(int)s.bufptr] = 0; + /* petsciiconv_topetscii(s.buf, TELNETD_CONF_LINELEN);*/ + } + shell_input(s.buf); + s.bufptr = 0; + } else { + ++s.bufptr; + } +} +/*---------------------------------------------------------------------------*/ +static void +sendopt(uint8 option, uint8 value) +{ + char *line; + line = (char*)malloc(TELNETD_CONF_LINELEN); + if(line != NULL) { + line[0] = TELNET_IAC; + line[1] = option; + line[2] = value; + line[3] = 0; + sendline(line); + } +} +/*---------------------------------------------------------------------------*/ +static void +newdata(void) +{ + uint16 len; + uint8 c; + char *dataptr; + + + len = uip_datalen(); + dataptr = (char *)uip_appdata; + + while(len > 0 && s.bufptr < sizeof(s.buf)) { + c = *dataptr; + ++dataptr; + --len; + switch(s.state) { + case STATE_IAC: + if(c == TELNET_IAC) { + get_char(c); + s.state = STATE_NORMAL; + } else { + switch(c) { + case TELNET_WILL: + s.state = STATE_WILL; + break; + case TELNET_WONT: + s.state = STATE_WONT; + break; + case TELNET_DO: + s.state = STATE_DO; + break; + case TELNET_DONT: + s.state = STATE_DONT; + break; + default: + s.state = STATE_NORMAL; + break; + } + } + break; + case STATE_WILL: + /* Reply with a DONT */ + sendopt(TELNET_DONT, c); + s.state = STATE_NORMAL; + break; + + case STATE_WONT: + /* Reply with a DONT */ + sendopt(TELNET_DONT, c); + s.state = STATE_NORMAL; + break; + case STATE_DO: + /* Reply with a WONT */ + sendopt(TELNET_WONT, c); + s.state = STATE_NORMAL; + break; + case STATE_DONT: + /* Reply with a WONT */ + sendopt(TELNET_WONT, c); + s.state = STATE_NORMAL; + break; + case STATE_NORMAL: + if(c == TELNET_IAC) { + s.state = STATE_IAC; + } else { + get_char(c); + } + break; + } + } +} + +/* This function is called by the UIP interrupt handling logic whenevent an + * event of interest occurs. + */ + +void uip_interrupt_event(void) +{ + static unsigned int i; + if(uip_connected()) { + /* tcp_markconn(uip_conn, &s);*/ + for(i = 0; i < TELNETD_CONF_NUMLINES; ++i) { + s.lines[i] = NULL; + } + s.bufptr = 0; + s.state = STATE_NORMAL; + + shell_start(); + } + + if(s.state == STATE_CLOSE) { + s.state = STATE_NORMAL; + uip_close(); + return; + } + + if(uip_closed() || + uip_aborted() || + uip_timedout()) { + closed(); + } + + if(uip_acked()) { + acked(); + } + + if(uip_newdata()) { + newdata(); + } + + if(uip_rexmit() || + uip_newdata() || + uip_acked() || + uip_connected() || + uip_poll()) { + senddata(); + } +} +/*---------------------------------------------------------------------------*/ diff --git a/nuttx/netutils/telnetd/telnetd.h b/nuttx/netutils/telnetd/telnetd.h new file mode 100644 index 000000000..4eef0b726 --- /dev/null +++ b/nuttx/netutils/telnetd/telnetd.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2003, Adam Dunkels. + * 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. + */ + +#ifndef __TELNETD_H__ +#define __TELNETD_H__ + +#include <sys/types.h> +#include <net/uip/uipopt.h> + +#ifndef TELNETD_CONF_LINELEN +#define TELNETD_CONF_LINELEN 40 +#endif +#ifndef TELNETD_CONF_NUMLINES +#define TELNETD_CONF_NUMLINES 16 +#endif + +struct telnetd_state +{ + char *lines[TELNETD_CONF_NUMLINES]; + char buf[TELNETD_CONF_LINELEN]; + char bufptr; + uint8 numsent; + uint8 state; +}; + +#endif /* __TELNETD_H__ */ diff --git a/nuttx/netutils/uiplib/Make.defs b/nuttx/netutils/uiplib/Make.defs new file mode 100644 index 000000000..2e3425761 --- /dev/null +++ b/nuttx/netutils/uiplib/Make.defs @@ -0,0 +1,37 @@ +############################################################################ +# Make.defs +# +# Copyright (C) 2007 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################################ + +UIPLIB_ASRCS = +UIPLIB_CSRCS = uiplib.c diff --git a/nuttx/netutils/uiplib/uiplib.c b/nuttx/netutils/uiplib/uiplib.c new file mode 100644 index 000000000..1b6f7528c --- /dev/null +++ b/nuttx/netutils/uiplib/uiplib.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2004, Adam Dunkels and the 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 uIP TCP/IP stack + * + * $Id: uiplib.c,v 1.1.1.1 2007-08-26 23:07:05 patacongo Exp $ + * + */ + +#include <net/uip/uip.h> + +#include "uiplib.h" + +/*-----------------------------------------------------------------------------------*/ +unsigned char +uiplib_ipaddrconv(char *addrstr, unsigned char *ipaddr) +{ + unsigned char tmp; + char c; + unsigned char i, j; + + tmp = 0; + + for(i = 0; i < 4; ++i) { + j = 0; + do { + c = *addrstr; + ++j; + if(j > 4) { + return 0; + } + if(c == '.' || c == 0) { + *ipaddr = tmp; + ++ipaddr; + tmp = 0; + } else if(c >= '0' && c <= '9') { + tmp = (tmp * 10) + (c - '0'); + } else { + return 0; + } + ++addrstr; + } while(c != '.' && c != 0); + } + return 1; +} + +/*-----------------------------------------------------------------------------------*/ diff --git a/nuttx/netutils/uiplib/uiplib.h b/nuttx/netutils/uiplib/uiplib.h new file mode 100644 index 000000000..a980e389e --- /dev/null +++ b/nuttx/netutils/uiplib/uiplib.h @@ -0,0 +1,71 @@ +/** + * \file + * Various uIP library functions. + * \author + * Adam Dunkels <adam@sics.se> + * + */ + +/* + * Copyright (c) 2002, Adam Dunkels. + * 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 uIP TCP/IP stack + * + * $Id: uiplib.h,v 1.1.1.1 2007-08-26 23:07:05 patacongo Exp $ + * + */ +#ifndef __UIPLIB_H__ +#define __UIPLIB_H__ + +/** + * \addtogroup uipconvfunc + * @{ + */ + +/** + * Convert a textual representation of an IP address to a numerical representation. + * + * This function takes a textual representation of an IP address in + * the form a.b.c.d and converts it into a 4-byte array that can be + * used by other uIP functions. + * + * \param addrstr A pointer to a string containing the IP address in + * textual form. + * + * \param addr A pointer to a 4-byte array that will be filled in with + * the numerical representation of the address. + * + * \retval 0 If the IP address could not be parsed. + * \retval Non-zero If the IP address was parsed. + */ +unsigned char uiplib_ipaddrconv(char *addrstr, unsigned char *addr); + +/** @} */ + +#endif /* __UIPLIB_H__ */ diff --git a/nuttx/netutils/webclient/Make.defs b/nuttx/netutils/webclient/Make.defs new file mode 100644 index 000000000..a5bffd45a --- /dev/null +++ b/nuttx/netutils/webclient/Make.defs @@ -0,0 +1,37 @@ +############################################################################ +# Make.defs +# +# Copyright (C) 2007 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################################ + +WEBCLIENT_ASRCS = +WEBCLIENT_CSRCS = webclient-strings.c webclient.c diff --git a/nuttx/netutils/webclient/makestrings b/nuttx/netutils/webclient/makestrings new file mode 100755 index 000000000..6dec075dd --- /dev/null +++ b/nuttx/netutils/webclient/makestrings @@ -0,0 +1,40 @@ +#!/usr/bin/perl + + +sub stringify { + my $name = shift(@_); + open(OUTPUTC, "> $name.c"); + open(OUTPUTH, "> $name.h"); + + open(FILE, "$name"); + + while(<FILE>) { + if(/(.+) "(.+)"/) { + $var = $1; + $data = $2; + + $datan = $data; + $datan =~ s/\\r/\r/g; + $datan =~ s/\\n/\n/g; + $datan =~ s/\\01/\01/g; + $datan =~ s/\\0/\0/g; + + printf(OUTPUTC "const char $var\[%d] = \n", length($datan) + 1); + printf(OUTPUTC "/* \"$data\" */\n"); + printf(OUTPUTC "{"); + for($j = 0; $j < length($datan); $j++) { + printf(OUTPUTC "%#02x, ", unpack("C", substr($datan, $j, 1))); + } + printf(OUTPUTC "0 };\n"); + + printf(OUTPUTH "extern const char $var\[%d];\n", length($datan) + 1); + + } + } + close(OUTPUTC); + close(OUTPUTH); +} +stringify("webclient-strings"); + +exit 0; + diff --git a/nuttx/netutils/webclient/webclient-strings b/nuttx/netutils/webclient/webclient-strings new file mode 100644 index 000000000..a33139723 --- /dev/null +++ b/nuttx/netutils/webclient/webclient-strings @@ -0,0 +1,31 @@ +http_http "http://" +http_200 "200 " +http_301 "301 " +http_302 "302 " +http_get "GET " +http_10 "HTTP/1.0" +http_11 "HTTP/1.1" +http_content_type "content-type: " +http_texthtml "text/html" +http_location "location: " +http_host "host: " +http_crnl "\r\n" +http_index_html "/index.html" +http_404_html "/404.html" +http_content_type_html "Content-type: text/html\r\n\r\n" +http_content_type_css "Content-type: text/css\r\n\r\n" +http_content_type_text "Content-type: text/text\r\n\r\n" +http_content_type_png "Content-type: image/png\r\n\r\n" +http_content_type_gif "Content-type: image/gif\r\n\r\n" +http_content_type_jpg "Content-type: image/jpeg\r\n\r\n" +http_content_type_binary "Content-type: application/octet-stream\r\n\r\n" +http_html ".html" +http_shtml ".shtml" +http_htm ".htm" +http_css ".css" +http_png ".png" +http_gif ".gif" +http_jpg ".jpg" +http_text ".text" +http_txt ".txt" +http_user_agent_fields "Connection: close\r\nUser-Agent: uIP/1.0 (; http://www.sics.se/~adam/uip/)\r\n\r\n" diff --git a/nuttx/netutils/webclient/webclient-strings.c b/nuttx/netutils/webclient/webclient-strings.c new file mode 100644 index 000000000..94723308e --- /dev/null +++ b/nuttx/netutils/webclient/webclient-strings.c @@ -0,0 +1,93 @@ +const char http_http[8] = +/* "http://" */ +{0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0 }; +const char http_200[5] = +/* "200 " */ +{0x32, 0x30, 0x30, 0x20, 0 }; +const char http_301[5] = +/* "301 " */ +{0x33, 0x30, 0x31, 0x20, 0 }; +const char http_302[5] = +/* "302 " */ +{0x33, 0x30, 0x32, 0x20, 0 }; +const char http_get[5] = +/* "GET " */ +{0x47, 0x45, 0x54, 0x20, 0 }; +const char http_10[9] = +/* "HTTP/1.0" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0 }; +const char http_11[9] = +/* "HTTP/1.1" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, 0 }; +const char http_content_type[15] = +/* "content-type: " */ +{0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0 }; +const char http_texthtml[10] = +/* "text/html" */ +{0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0 }; +const char http_location[11] = +/* "location: " */ +{0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0 }; +const char http_host[7] = +/* "host: " */ +{0x68, 0x6f, 0x73, 0x74, 0x3a, 0x20, 0 }; +const char http_crnl[3] = +/* "\r\n" */ +{0xd, 0xa, 0 }; +const char http_index_html[12] = +/* "/index.html" */ +{0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0 }; +const char http_404_html[10] = +/* "/404.html" */ +{0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0 }; +const char http_content_type_html[28] = +/* "Content-type: text/html\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, 0 }; +const char http_content_type_css [27] = +/* "Content-type: text/css\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0xd, 0xa, 0xd, 0xa, 0 }; +const char http_content_type_text[28] = +/* "Content-type: text/text\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x65, 0x78, 0x74, 0xd, 0xa, 0xd, 0xa, 0 }; +const char http_content_type_png [28] = +/* "Content-type: image/png\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0xd, 0xa, 0xd, 0xa, 0 }; +const char http_content_type_gif [28] = +/* "Content-type: image/gif\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0xd, 0xa, 0xd, 0xa, 0 }; +const char http_content_type_jpg [29] = +/* "Content-type: image/jpeg\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0xd, 0xa, 0xd, 0xa, 0 }; +const char http_content_type_binary[43] = +/* "Content-type: application/octet-stream\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0xd, 0xa, 0xd, 0xa, 0 }; +const char http_html[6] = +/* ".html" */ +{0x2e, 0x68, 0x74, 0x6d, 0x6c, 0 }; +const char http_shtml[7] = +/* ".shtml" */ +{0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0 }; +const char http_htm[5] = +/* ".htm" */ +{0x2e, 0x68, 0x74, 0x6d, 0 }; +const char http_css[5] = +/* ".css" */ +{0x2e, 0x63, 0x73, 0x73, 0 }; +const char http_png[5] = +/* ".png" */ +{0x2e, 0x70, 0x6e, 0x67, 0 }; +const char http_gif[5] = +/* ".gif" */ +{0x2e, 0x67, 0x69, 0x66, 0 }; +const char http_jpg[5] = +/* ".jpg" */ +{0x2e, 0x6a, 0x70, 0x67, 0 }; +const char http_text[6] = +/* ".text" */ +{0x2e, 0x74, 0x65, 0x78, 0x74, 0 }; +const char http_txt[5] = +/* ".txt" */ +{0x2e, 0x74, 0x78, 0x74, 0 }; +const char http_user_agent_fields[77] = +/* "Connection: close\r\nUser-Agent: uIP/1.0 (; http://www.sics.se/~adam/uip/)\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, 0x55, 0x73, 0x65, 0x72, 0x2d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x28, 0x3b, 0x20, 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, 0x75, 0x69, 0x70, 0x2f, 0x29, 0xd, 0xa, 0xd, 0xa, 0 }; diff --git a/nuttx/netutils/webclient/webclient-strings.h b/nuttx/netutils/webclient/webclient-strings.h new file mode 100644 index 000000000..9e3ec9347 --- /dev/null +++ b/nuttx/netutils/webclient/webclient-strings.h @@ -0,0 +1,31 @@ +extern const char http_http[8]; +extern const char http_200[5]; +extern const char http_301[5]; +extern const char http_302[5]; +extern const char http_get[5]; +extern const char http_10[9]; +extern const char http_11[9]; +extern const char http_content_type[15]; +extern const char http_texthtml[10]; +extern const char http_location[11]; +extern const char http_host[7]; +extern const char http_crnl[3]; +extern const char http_index_html[12]; +extern const char http_404_html[10]; +extern const char http_content_type_html[28]; +extern const char http_content_type_css [27]; +extern const char http_content_type_text[28]; +extern const char http_content_type_png [28]; +extern const char http_content_type_gif [28]; +extern const char http_content_type_jpg [29]; +extern const char http_content_type_binary[43]; +extern const char http_html[6]; +extern const char http_shtml[7]; +extern const char http_htm[5]; +extern const char http_css[5]; +extern const char http_png[5]; +extern const char http_gif[5]; +extern const char http_jpg[5]; +extern const char http_text[6]; +extern const char http_txt[5]; +extern const char http_user_agent_fields[77]; diff --git a/nuttx/netutils/webclient/webclient.c b/nuttx/netutils/webclient/webclient.c new file mode 100644 index 000000000..30718e723 --- /dev/null +++ b/nuttx/netutils/webclient/webclient.c @@ -0,0 +1,450 @@ +/* webclient.c + * Implementation of the HTTP client. + * Author: Adam Dunkels <adam@dunkels.com> + * + * This example shows a HTTP client that is able to download web pages + * and files from web servers. It requires a number of callback + * functions to be implemented by the module that utilizes the code: + * webclient_datahandler(), webclient_connected(), + * webclient_timedout(), webclient_aborted(), webclient_closed(). + * + * Copyright (c) 2002, Adam Dunkels. + * 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 uIP TCP/IP stack. + * + * $Id: webclient.c,v 1.1.1.1 2007-08-26 23:07:05 patacongo Exp $ + * + */ + +#include <sys/types.h> +#include <string.h> + +#include <net/uip/uip.h> +#include <net/uip/resolv.h> + +#include "uiplib/uiplib.h" +#include "webclient.h" + +#define WEBCLIENT_TIMEOUT 100 + +#define WEBCLIENT_STATE_STATUSLINE 0 +#define WEBCLIENT_STATE_HEADERS 1 +#define WEBCLIENT_STATE_DATA 2 +#define WEBCLIENT_STATE_CLOSE 3 + +#define HTTPFLAG_NONE 0 +#define HTTPFLAG_OK 1 +#define HTTPFLAG_MOVED 2 +#define HTTPFLAG_ERROR 3 + + +#define ISO_nl 0x0a +#define ISO_cr 0x0d +#define ISO_space 0x20 + + +static struct webclient_state s; + +char *webclient_mimetype(void) +{ + return s.mimetype; +} + +char *webclient_filename(void) +{ + return s.file; +} + +char *webclient_hostname(void) +{ + return s.host; +} + +unsigned shortwebclient_port(void) +{ + return s.port; +} + +void webclient_init(void) +{ +} + +static void init_connection(void) +{ + s.state = WEBCLIENT_STATE_STATUSLINE; + + s.getrequestleft = sizeof(http_get) - 1 + 1 + + sizeof(http_10) - 1 + + sizeof(http_crnl) - 1 + + sizeof(http_host) - 1 + + sizeof(http_crnl) - 1 + + strlen(http_user_agent_fields) + + strlen(s.file) + strlen(s.host); + s.getrequestptr = 0; + + s.httpheaderlineptr = 0; +} + +void webclient_close(void) +{ + s.state = WEBCLIENT_STATE_CLOSE; +} + +unsigned char webclient_get(char *host, uint16 port, char *file) +{ + struct uip_conn *conn; + uip_ipaddr_t *ipaddr; + static uip_ipaddr_t addr; + + /* First check if the host is an IP address. */ + ipaddr = &addr; + if (uiplib_ipaddrconv(host, (unsigned char *)addr) == 0) { + ipaddr = (uip_ipaddr_t *)resolv_lookup(host); + + if (ipaddr == NULL) { + return 0; + } + } + + conn = uip_connect(ipaddr, htons(port)); + + if (conn == NULL) { + return 0; + } + + s.port = port; + strncpy(s.file, file, sizeof(s.file)); + strncpy(s.host, host, sizeof(s.host)); + + init_connection(); + return 1; +} + +static char *copy_string(char *dest, const char *src, int len) +{ + strncpy(dest, src, len); + return dest + len; +} + +static void senddata(void) +{ + uint16 len; + char *getrequest; + char *cptr; + + if (s.getrequestleft > 0) { + cptr = getrequest = (char *)uip_appdata; + + cptr = copy_string(cptr, http_get, sizeof(http_get) - 1); + cptr = copy_string(cptr, s.file, strlen(s.file)); + *cptr++ = ISO_space; + cptr = copy_string(cptr, http_10, sizeof(http_10) - 1); + + cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1); + + cptr = copy_string(cptr, http_host, sizeof(http_host) - 1); + cptr = copy_string(cptr, s.host, strlen(s.host)); + cptr = copy_string(cptr, http_crnl, sizeof(http_crnl) - 1); + + cptr = copy_string(cptr, http_user_agent_fields, + strlen(http_user_agent_fields)); + + len = s.getrequestleft > uip_mss()? + uip_mss(): + s.getrequestleft; + uip_send(&(getrequest[s.getrequestptr]), len); + } +} + +static void acked(void) +{ + uint16 len; + + if (s.getrequestleft > 0) { + len = s.getrequestleft > uip_mss()? + uip_mss(): + s.getrequestleft; + s.getrequestleft -= len; + s.getrequestptr += len; + } +} + +static uint16 parse_statusline(uint16 len) +{ + char *cptr; + + while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) + { + char *pappdata = (char*)uip_appdata; + s.httpheaderline[s.httpheaderlineptr] = *pappdata++; + uip_appdata = (void*)pappdata; + len--; + + if (s.httpheaderline[s.httpheaderlineptr] == ISO_nl) + { + if ((strncmp(s.httpheaderline, http_10, sizeof(http_10) - 1) == 0) || + (strncmp(s.httpheaderline, http_11, sizeof(http_11) - 1) == 0)) + { + cptr = &(s.httpheaderline[9]); + s.httpflag = HTTPFLAG_NONE; + if (strncmp(cptr, http_200, sizeof(http_200) - 1) == 0) + { + /* 200 OK */ + s.httpflag = HTTPFLAG_OK; + } + else if (strncmp(cptr, http_301, sizeof(http_301) - 1) == 0 || + strncmp(cptr, http_302, sizeof(http_302) - 1) == 0) + { + /* 301 Moved permanently or 302 Found. Location: header line + * will contain thw new location. + */ + + s.httpflag = HTTPFLAG_MOVED; + } + else + { + s.httpheaderline[s.httpheaderlineptr - 1] = 0; + } + } + else + { + uip_abort(); + webclient_aborted(); + return 0; + } + + /* We're done parsing the status line, so we reset the pointer + * and start parsing the HTTP headers. + */ + + s.httpheaderlineptr = 0; + s.state = WEBCLIENT_STATE_HEADERS; + break; + } + else + { + ++s.httpheaderlineptr; + } + } + return len; +} + +static char casecmp(char *str1, const char *str2, char len) +{ + static char c; + + while(len > 0) { + c = *str1; + /* Force lower-case characters. */ + if (c & 0x40) { + c |= 0x20; + } + if (*str2 != c) { + return 1; + } + ++str1; + ++str2; + --len; + } + return 0; +} + +static uint16 parse_headers(uint16 len) +{ + char *cptr; + static unsigned char i; + + while(len > 0 && s.httpheaderlineptr < sizeof(s.httpheaderline)) + { + char *pappdata = (char*)uip_appdata; + s.httpheaderline[s.httpheaderlineptr] = *pappdata++; + uip_appdata = (void*)pappdata; + len--; + + if (s.httpheaderline[s.httpheaderlineptr] == ISO_nl) + { + /* We have an entire HTTP header line in s.httpheaderline, so + * we parse it. + */ + + if (s.httpheaderline[0] == ISO_cr) + { + /* This was the last header line (i.e., and empty "\r\n"), so + * we are done with the headers and proceed with the actual + * data. + */ + + s.state = WEBCLIENT_STATE_DATA; + return len; + } + + s.httpheaderline[s.httpheaderlineptr - 1] = 0; + + /* Check for specific HTTP header fields. */ + if (casecmp(s.httpheaderline, http_content_type, sizeof(http_content_type) - 1) == 0) + { + /* Found Content-type field. */ + cptr = strchr(s.httpheaderline, ';'); + if (cptr != NULL) + { + *cptr = 0; + } + strncpy(s.mimetype, s.httpheaderline + sizeof(http_content_type) - 1, sizeof(s.mimetype)); + } + else if (casecmp(s.httpheaderline, http_location, sizeof(http_location) - 1) == 0) + { + cptr = s.httpheaderline + sizeof(http_location) - 1; + + if (strncmp(cptr, http_http, 7) == 0) + { + cptr += 7; + for(i = 0; i < s.httpheaderlineptr - 7; ++i) + { + if (*cptr == 0 || *cptr == '/' || *cptr == ' ' || *cptr == ':') + { + s.host[i] = 0; + break; + } + s.host[i] = *cptr; + ++cptr; + } + } + strncpy(s.file, cptr, sizeof(s.file)); + } + + /* We're done parsing, so we reset the pointer and start the + * next line. + */ + + s.httpheaderlineptr = 0; + } + else + { + ++s.httpheaderlineptr; + } + } + return len; +} + +static void newdata(void) +{ + uint16 len; + + len = uip_datalen(); + + if (s.state == WEBCLIENT_STATE_STATUSLINE) { + len = parse_statusline(len); + } + + if (s.state == WEBCLIENT_STATE_HEADERS && len > 0) { + len = parse_headers(len); + } + + if (len > 0 && s.state == WEBCLIENT_STATE_DATA && + s.httpflag != HTTPFLAG_MOVED) { + webclient_datahandler((char *)uip_appdata, len); + } +} + +/* This function is called by the UIP interrupt handling logic whenevent an + * event of interest occurs. + */ + +void uip_interrupt_event(void) +{ + if (uip_connected()) + { + s.timer = 0; + s.state = WEBCLIENT_STATE_STATUSLINE; + senddata(); + webclient_connected(); + return; + } + + if (s.state == WEBCLIENT_STATE_CLOSE) + { + webclient_closed(); + uip_abort(); + return; + } + + if (uip_aborted()) + { + webclient_aborted(); + } + + if (uip_timedout()) + { + webclient_timedout(); + } + + if (uip_acked()) + { + s.timer = 0; + acked(); + } + + if (uip_newdata()) + { + s.timer = 0; + newdata(); + } + + if (uip_rexmit() || uip_newdata() || uip_acked()) + { + senddata(); + } + else if (uip_poll()) + { + ++s.timer; + if (s.timer == WEBCLIENT_TIMEOUT) + { + webclient_timedout(); + uip_abort(); + return; + } + } + + if (uip_closed()) + { + if (s.httpflag != HTTPFLAG_MOVED) + { + /* Send NULL data to signal EOF. */ + webclient_datahandler(NULL, 0); + } + else + { + if (resolv_lookup(s.host) == NULL) + { + resolv_query(s.host); + } + webclient_get(s.host, s.port, s.file); + } + } +} diff --git a/nuttx/netutils/webclient/webclient.h b/nuttx/netutils/webclient/webclient.h new file mode 100644 index 000000000..c6559e3f0 --- /dev/null +++ b/nuttx/netutils/webclient/webclient.h @@ -0,0 +1,214 @@ +/** + * webclient.h + * Header file for the HTTP client. + * Author: Adam Dunkels <adam@dunkels.com> + * + * Copyright (c) 2002, Adam Dunkels. + * 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 uIP TCP/IP stack. + * + * $Id: webclient.h,v 1.1.1.1 2007-08-26 23:07:04 patacongo Exp $ + * + */ +#ifndef __WEBCLIENT_H__ +#define __WEBCLIENT_H__ + +#include <sys/types.h> +#include <net/uip/uipopt.h> + +#include "webclient-strings.h" + +#define WEBCLIENT_CONF_MAX_URLLEN 100 + +struct webclient_state { + uint8 timer; + uint8 state; + uint8 httpflag; + + uint16 port; + char host[40]; + char file[WEBCLIENT_CONF_MAX_URLLEN]; + uint16 getrequestptr; + uint16 getrequestleft; + + char httpheaderline[200]; + uint16 httpheaderlineptr; + + char mimetype[32]; +}; + +/** + * Callback function that is called from the webclient code when HTTP + * data has been received. + * + * This function must be implemented by the module that uses the + * webclient code. The function is called from the webclient module + * when HTTP data has been received. The function is not called when + * HTTP headers are received, only for the actual data. + * + * \note This function is called many times, repetedly, when data is + * being received, and not once when all data has been received. + * + * \param data A pointer to the data that has been received. + * \param len The length of the data that has been received. + */ +void webclient_datahandler(char *data, uint16 len); + +/** + * Callback function that is called from the webclient code when the + * HTTP connection has been connected to the web server. + * + * This function must be implemented by the module that uses the + * webclient code. + */ +void webclient_connected(void); + +/** + * Callback function that is called from the webclient code if the + * HTTP connection to the web server has timed out. + * + * This function must be implemented by the module that uses the + * webclient code. + */ +void webclient_timedout(void); + +/** + * Callback function that is called from the webclient code if the + * HTTP connection to the web server has been aborted by the web + * server. + * + * This function must be implemented by the module that uses the + * webclient code. + */ +void webclient_aborted(void); + +/** + * Callback function that is called from the webclient code when the + * HTTP connection to the web server has been closed. + * + * This function must be implemented by the module that uses the + * webclient code. + */ +void webclient_closed(void); + +/** + * Initialize the webclient module. + */ +void webclient_init(void); + +/** + * Open an HTTP connection to a web server and ask for a file using + * the GET method. + * + * This function opens an HTTP connection to the specified web server + * and requests the specified file using the GET method. When the HTTP + * connection has been connected, the webclient_connected() callback + * function is called and when the HTTP data arrives the + * webclient_datahandler() callback function is called. + * + * The callback function webclient_timedout() is called if the web + * server could not be contacted, and the webclient_aborted() callback + * function is called if the HTTP connection is aborted by the web + * server. + * + * When the HTTP request has been completed and the HTTP connection is + * closed, the webclient_closed() callback function will be called. + * + * \note If the function is passed a host name, it must already be in + * the resolver cache in order for the function to connect to the web + * server. It is therefore up to the calling module to implement the + * resolver calls and the signal handler used for reporting a resolv + * query answer. + * + * \param host A pointer to a string containing either a host name or + * a numerical IP address in dotted decimal notation (e.g., 192.168.23.1). + * + * \param port The port number to which to connect, in host byte order. + * + * \param file A pointer to the name of the file to get. + * + * \retval 0 if the host name could not be found in the cache, or + * if a TCP connection could not be created. + * + * \retval 1 if the connection was initiated. + */ +unsigned char webclient_get(char *host, uint16 port, char *file); + +/** + * Close the currently open HTTP connection. + */ +void webclient_close(void); + +/** + * Obtain the MIME type of the current HTTP data stream. + * + * \return A pointer to a string contaning the MIME type. The string + * may be empty if no MIME type was reported by the web server. + */ +char *webclient_mimetype(void); + +/** + * Obtain the filename of the current HTTP data stream. + * + * The filename of an HTTP request may be changed by the web server, + * and may therefore not be the same as when the original GET request + * was made with webclient_get(). This function is used for obtaining + * the current filename. + * + * \return A pointer to the current filename. + */ +char *webclient_filename(void); + +/** + * Obtain the hostname of the current HTTP data stream. + * + * The hostname of the web server of an HTTP request may be changed + * by the web server, and may therefore not be the same as when the + * original GET request was made with webclient_get(). This function + * is used for obtaining the current hostname. + * + * \return A pointer to the current hostname. + */ +char *webclient_hostname(void); + +/** + * Obtain the port number of the current HTTP data stream. + * + * The port number of an HTTP request may be changed by the web + * server, and may therefore not be the same as when the original GET + * request was made with webclient_get(). This function is used for + * obtaining the current port number. + * + * \return The port number of the current HTTP data stream, in host byte order. + */ +unsigned short webclient_port(void); + +#endif /* __WEBCLIENT_H__ */ + +/** @} */ diff --git a/nuttx/netutils/webserver/Make.defs b/nuttx/netutils/webserver/Make.defs new file mode 100644 index 000000000..94469f526 --- /dev/null +++ b/nuttx/netutils/webserver/Make.defs @@ -0,0 +1,37 @@ +############################################################################ +# Make.defs +# +# Copyright (C) 2007 Gregory Nutt. All rights reserved. +# Author: Gregory Nutt <spudmonkey@racsa.co.cr> +# +# 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. Neither the name NuttX nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# 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. +# +############################################################################ + +WEBSERVER_ASRCS = +WEBSERVER_CSRCS = httpd.c http-strings.c httpd-fs.c httpd-cgi.c diff --git a/nuttx/netutils/webserver/http-strings b/nuttx/netutils/webserver/http-strings new file mode 100644 index 000000000..d0b9121be --- /dev/null +++ b/nuttx/netutils/webserver/http-strings @@ -0,0 +1,35 @@ +http_http "http://" +http_200 "200 " +http_301 "301 " +http_302 "302 " +http_get "GET " +http_10 "HTTP/1.0" +http_11 "HTTP/1.1" +http_content_type "content-type: " +http_texthtml "text/html" +http_location "location: " +http_host "host: " +http_crnl "\r\n" +http_index_html "/index.html" +http_404_html "/404.html" +http_referer "Referer:" +http_header_200 "HTTP/1.0 200 OK\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" +http_header_404 "HTTP/1.0 404 Not found\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" +http_content_type_plain "Content-type: text/plain\r\n\r\n" +http_content_type_html "Content-type: text/html\r\n\r\n" +http_content_type_css "Content-type: text/css\r\n\r\n" +http_content_type_text "Content-type: text/text\r\n\r\n" +http_content_type_png "Content-type: image/png\r\n\r\n" +http_content_type_gif "Content-type: image/gif\r\n\r\n" +http_content_type_jpg "Content-type: image/jpeg\r\n\r\n" +http_content_type_binary "Content-type: application/octet-stream\r\n\r\n" +http_html ".html" +http_shtml ".shtml" +http_htm ".htm" +http_css ".css" +http_png ".png" +http_gif ".gif" +http_jpg ".jpg" +http_text ".txt" +http_txt ".txt" + diff --git a/nuttx/netutils/webserver/http-strings.c b/nuttx/netutils/webserver/http-strings.c new file mode 100644 index 000000000..0d822baf7 --- /dev/null +++ b/nuttx/netutils/webserver/http-strings.c @@ -0,0 +1,102 @@ +const char http_http[8] = +/* "http://" */ +{0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, }; +const char http_200[5] = +/* "200 " */ +{0x32, 0x30, 0x30, 0x20, }; +const char http_301[5] = +/* "301 " */ +{0x33, 0x30, 0x31, 0x20, }; +const char http_302[5] = +/* "302 " */ +{0x33, 0x30, 0x32, 0x20, }; +const char http_get[5] = +/* "GET " */ +{0x47, 0x45, 0x54, 0x20, }; +const char http_10[9] = +/* "HTTP/1.0" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, }; +const char http_11[9] = +/* "HTTP/1.1" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x31, }; +const char http_content_type[15] = +/* "content-type: " */ +{0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, }; +const char http_texthtml[10] = +/* "text/html" */ +{0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_location[11] = +/* "location: " */ +{0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, }; +const char http_host[7] = +/* "host: " */ +{0x68, 0x6f, 0x73, 0x74, 0x3a, 0x20, }; +const char http_crnl[3] = +/* "\r\n" */ +{0xd, 0xa, }; +const char http_index_html[12] = +/* "/index.html" */ +{0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_404_html[10] = +/* "/404.html" */ +{0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_referer[9] = +/* "Referer:" */ +{0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, 0x3a, }; +const char http_header_200[84] = +/* "HTTP/1.0 200 OK\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, 0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 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, 0x75, 0x69, 0x70, 0x2f, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, }; +const char http_header_404[91] = +/* "HTTP/1.0 404 Not found\r\nServer: uIP/1.0 http://www.sics.se/~adam/uip/\r\nConnection: close\r\n" */ +{0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x34, 0x30, 0x34, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0xd, 0xa, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x20, 0x75, 0x49, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 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, 0x75, 0x69, 0x70, 0x2f, 0xd, 0xa, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0xd, 0xa, }; +const char http_content_type_plain[29] = +/* "Content-type: text/plain\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_html[28] = +/* "Content-type: text/html\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_css [27] = +/* "Content-type: text/css\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_text[28] = +/* "Content-type: text/text\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x74, 0x65, 0x78, 0x74, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_png [28] = +/* "Content-type: image/png\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_gif [28] = +/* "Content-type: image/gif\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, 0x69, 0x66, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_jpg [29] = +/* "Content-type: image/jpeg\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0xd, 0xa, 0xd, 0xa, }; +const char http_content_type_binary[43] = +/* "Content-type: application/octet-stream\r\n\r\n" */ +{0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x63, 0x74, 0x65, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0xd, 0xa, 0xd, 0xa, }; +const char http_html[6] = +/* ".html" */ +{0x2e, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_shtml[7] = +/* ".shtml" */ +{0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, }; +const char http_htm[5] = +/* ".htm" */ +{0x2e, 0x68, 0x74, 0x6d, }; +const char http_css[5] = +/* ".css" */ +{0x2e, 0x63, 0x73, 0x73, }; +const char http_png[5] = +/* ".png" */ +{0x2e, 0x70, 0x6e, 0x67, }; +const char http_gif[5] = +/* ".gif" */ +{0x2e, 0x67, 0x69, 0x66, }; +const char http_jpg[5] = +/* ".jpg" */ +{0x2e, 0x6a, 0x70, 0x67, }; +const char http_text[5] = +/* ".txt" */ +{0x2e, 0x74, 0x78, 0x74, }; +const char http_txt[5] = +/* ".txt" */ +{0x2e, 0x74, 0x78, 0x74, }; diff --git a/nuttx/netutils/webserver/http-strings.h b/nuttx/netutils/webserver/http-strings.h new file mode 100644 index 000000000..f121dd73a --- /dev/null +++ b/nuttx/netutils/webserver/http-strings.h @@ -0,0 +1,34 @@ +extern const char http_http[8]; +extern const char http_200[5]; +extern const char http_301[5]; +extern const char http_302[5]; +extern const char http_get[5]; +extern const char http_10[9]; +extern const char http_11[9]; +extern const char http_content_type[15]; +extern const char http_texthtml[10]; +extern const char http_location[11]; +extern const char http_host[7]; +extern const char http_crnl[3]; +extern const char http_index_html[12]; +extern const char http_404_html[10]; +extern const char http_referer[9]; +extern const char http_header_200[84]; +extern const char http_header_404[91]; +extern const char http_content_type_plain[29]; +extern const char http_content_type_html[28]; +extern const char http_content_type_css [27]; +extern const char http_content_type_text[28]; +extern const char http_content_type_png [28]; +extern const char http_content_type_gif [28]; +extern const char http_content_type_jpg [29]; +extern const char http_content_type_binary[43]; +extern const char http_html[6]; +extern const char http_shtml[7]; +extern const char http_htm[5]; +extern const char http_css[5]; +extern const char http_png[5]; +extern const char http_gif[5]; +extern const char http_jpg[5]; +extern const char http_text[5]; +extern const char http_txt[5]; diff --git a/nuttx/netutils/webserver/httpd-cgi.c b/nuttx/netutils/webserver/httpd-cgi.c new file mode 100644 index 000000000..5c9609ee7 --- /dev/null +++ b/nuttx/netutils/webserver/httpd-cgi.c @@ -0,0 +1,178 @@ +/* httpd-cgi.c + * Web server script interface + * Author: Adam Dunkels <adam@sics.se> + * + * Copyright (c) 2001-2006, Adam Dunkels. + * 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. + */ + +#include <net/uip/uip.h> +#include <net/uip/psock.h> +#include <net/uip/httpd.h> + +#include "httpd-cgi.h" + +#include <stdio.h> +#include <string.h> + +HTTPD_CGI_CALL(file, "file-stats", file_stats); +HTTPD_CGI_CALL(tcp, "tcp-connections", tcp_stats); +HTTPD_CGI_CALL(net, "net-stats", net_stats); + +static const struct httpd_cgi_call *calls[] = { &file, &tcp, &net, NULL }; + +/*---------------------------------------------------------------------------*/ +static +void nullfunction(struct httpd_state *s, char *ptr) +{ +} + +/*---------------------------------------------------------------------------*/ +httpd_cgifunction +httpd_cgi(char *name) +{ + const struct httpd_cgi_call **f; + + /* Find the matching name in the table, return the function. */ + for(f = calls; *f != NULL; ++f) { + if(strncmp((*f)->name, name, strlen((*f)->name)) == 0) { + return (*f)->function; + } + } +#warning REVISIT -- must wait to return + return nullfunction; +} +/*---------------------------------------------------------------------------*/ +static unsigned short +generate_file_stats(void *arg) +{ + char *f = (char *)arg; + return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, "%5u", httpd_fs_count(f)); +} +/*---------------------------------------------------------------------------*/ +static +void file_stats(struct httpd_state *s, char *ptr) +{ + psock_generator_send(&s->sout, generate_file_stats, strchr(ptr, ' ') + 1); +} + +/*---------------------------------------------------------------------------*/ +static const char closed[] = /* "CLOSED",*/ +{0x43, 0x4c, 0x4f, 0x53, 0x45, 0x44, 0}; +static const char syn_rcvd[] = /* "SYN-RCVD",*/ +{0x53, 0x59, 0x4e, 0x2d, 0x52, 0x43, 0x56, + 0x44, 0}; +static const char syn_sent[] = /* "SYN-SENT",*/ +{0x53, 0x59, 0x4e, 0x2d, 0x53, 0x45, 0x4e, + 0x54, 0}; +static const char established[] = /* "ESTABLISHED",*/ +{0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48, + 0x45, 0x44, 0}; +static const char fin_wait_1[] = /* "FIN-WAIT-1",*/ +{0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, + 0x54, 0x2d, 0x31, 0}; +static const char fin_wait_2[] = /* "FIN-WAIT-2",*/ +{0x46, 0x49, 0x4e, 0x2d, 0x57, 0x41, 0x49, + 0x54, 0x2d, 0x32, 0}; +static const char closing[] = /* "CLOSING",*/ +{0x43, 0x4c, 0x4f, 0x53, 0x49, + 0x4e, 0x47, 0}; +static const char time_wait[] = /* "TIME-WAIT,"*/ +{0x54, 0x49, 0x4d, 0x45, 0x2d, 0x57, 0x41, + 0x49, 0x54, 0}; +static const char last_ack[] = /* "LAST-ACK"*/ +{0x4c, 0x41, 0x53, 0x54, 0x2d, 0x41, 0x43, + 0x4b, 0}; + +static const char *states[] = { + closed, + syn_rcvd, + syn_sent, + established, + fin_wait_1, + fin_wait_2, + closing, + time_wait, + last_ack}; + + +static unsigned short +generate_tcp_stats(void *arg) +{ + struct uip_conn *conn; + struct httpd_state *s = (struct httpd_state *)arg; + + conn = &uip_conns[s->count]; + return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, + "<tr><td>%d</td><td>%u.%u.%u.%u:%u</td><td>%s</td><td>%u</td><td>%u</td><td>%c %c</td></tr>\r\n", + htons(conn->lport), + htons(conn->ripaddr[0]) >> 8, + htons(conn->ripaddr[0]) & 0xff, + htons(conn->ripaddr[1]) >> 8, + htons(conn->ripaddr[1]) & 0xff, + htons(conn->rport), + states[conn->tcpstateflags & UIP_TS_MASK], + conn->nrtx, + conn->timer, + (uip_outstanding(conn))? '*':' ', + (uip_stopped(conn))? '!':' '); +} +/*---------------------------------------------------------------------------*/ +static +void tcp_stats(struct httpd_state *s, char *ptr) +{ + for(s->count = 0; s->count < UIP_CONNS; ++s->count) { + if((uip_conns[s->count].tcpstateflags & UIP_TS_MASK) != UIP_CLOSED) { + psock_generator_send(&s->sout, generate_tcp_stats, s); + } + } +} + +/*---------------------------------------------------------------------------*/ +static unsigned short +generate_net_stats(void *arg) +{ + struct httpd_state *s = (struct httpd_state *)arg; + return snprintf((char *)uip_appdata, UIP_APPDATA_SIZE, + "%5u\n", ((uip_stats_t *)&uip_stat)[s->count]); +} + +static +void net_stats(struct httpd_state *s, char *ptr) +{ +#if UIP_STATISTICS + + for(s->count = 0; s->count < sizeof(uip_stat) / sizeof(uip_stats_t); + ++s->count) { + psock_generator_send(&s->sout, generate_net_stats, s); + } + +#endif /* UIP_STATISTICS */ +} + +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/nuttx/netutils/webserver/httpd-cgi.h b/nuttx/netutils/webserver/httpd-cgi.h new file mode 100644 index 000000000..bd22feb85 --- /dev/null +++ b/nuttx/netutils/webserver/httpd-cgi.h @@ -0,0 +1,67 @@ +/* httpd-cgi.h + * Web server script interface header file + * Author: Adam Dunkels <adam@sics.se> + * + * Copyright (c) 2001, Adam Dunkels. + * 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. + */ + +#ifndef __HTTPD_CGI_H__ +#define __HTTPD_CGI_H__ + +#include <net/uip/psock.h> +#include <net/uip/httpd.h> + +typedef void (* httpd_cgifunction)(struct httpd_state *, char *); + +httpd_cgifunction httpd_cgi(char *name); + +struct httpd_cgi_call { + const char *name; + const httpd_cgifunction function; +}; + +/** + * \brief HTTPD CGI function declaration + * \param name The C variable name of the function + * \param str The string name of the function, used in the script file + * \param function A pointer to the function that implements it + * + * This macro is used for declaring a HTTPD CGI + * function. This function is then added to the list of + * HTTPD CGI functions with the httpd_cgi_add() function. + * + * \hideinitializer + */ +#define HTTPD_CGI_CALL(name, str, function) \ +static void function(struct httpd_state *, char *); \ +static const struct httpd_cgi_call name = {str, function} + +void httpd_cgi_init(void); +#endif /* __HTTPD_CGI_H__ */ + +/** @} */ diff --git a/nuttx/netutils/webserver/httpd-fs.c b/nuttx/netutils/webserver/httpd-fs.c new file mode 100644 index 000000000..679b65be2 --- /dev/null +++ b/nuttx/netutils/webserver/httpd-fs.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2001, 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels <adam@sics.se> + * + * $Id: httpd-fs.c,v 1.1.1.1 2007-08-26 23:07:02 patacongo Exp $ + */ + +#include <sys/types.h> + +#include <net/uip/httpd.h> + +#include "httpd-fsdata.h" + +#ifndef NULL +#define NULL 0 +#endif /* NULL */ + +#include "httpd-fsdata.c" + +#if HTTPD_FS_STATISTICS +static uint16 count[HTTPD_FS_NUMFILES]; +#endif /* HTTPD_FS_STATISTICS */ + +/*-----------------------------------------------------------------------------------*/ +static uint8 +httpd_fs_strcmp(const char *str1, const char *str2) +{ + uint8 i; + i = 0; + loop: + + if(str2[i] == 0 || + str1[i] == '\r' || + str1[i] == '\n') { + return 0; + } + + if(str1[i] != str2[i]) { + return 1; + } + + + ++i; + goto loop; +} +/*-----------------------------------------------------------------------------------*/ +int +httpd_fs_open(const char *name, struct httpd_fs_file *file) +{ +#if HTTPD_FS_STATISTICS + uint16 i = 0; +#endif /* HTTPD_FS_STATISTICS */ + struct httpd_fsdata_file_noconst *f; + + for(f = (struct httpd_fsdata_file_noconst *)HTTPD_FS_ROOT; + f != NULL; + f = (struct httpd_fsdata_file_noconst *)f->next) { + + if(httpd_fs_strcmp(name, f->name) == 0) { + file->data = f->data; + file->len = f->len; +#if HTTPD_FS_STATISTICS + ++count[i]; +#endif /* HTTPD_FS_STATISTICS */ + return 1; + } +#if HTTPD_FS_STATISTICS + ++i; +#endif /* HTTPD_FS_STATISTICS */ + + } + return 0; +} +/*-----------------------------------------------------------------------------------*/ +void +httpd_fs_init(void) +{ +#if HTTPD_FS_STATISTICS + uint16 i; + for(i = 0; i < HTTPD_FS_NUMFILES; i++) { + count[i] = 0; + } +#endif /* HTTPD_FS_STATISTICS */ +} +/*-----------------------------------------------------------------------------------*/ +#if HTTPD_FS_STATISTICS +uint16 httpd_fs_count +(char *name) +{ + struct httpd_fsdata_file_noconst *f; + uint16 i; + + i = 0; + for(f = (struct httpd_fsdata_file_noconst *)HTTPD_FS_ROOT; + f != NULL; + f = (struct httpd_fsdata_file_noconst *)f->next) { + + if(httpd_fs_strcmp(name, f->name) == 0) { + return count[i]; + } + ++i; + } + return 0; +} +#endif /* HTTPD_FS_STATISTICS */ +/*-----------------------------------------------------------------------------------*/ diff --git a/nuttx/netutils/webserver/httpd-fsdata.c b/nuttx/netutils/webserver/httpd-fsdata.c new file mode 100644 index 000000000..20327baba --- /dev/null +++ b/nuttx/netutils/webserver/httpd-fsdata.c @@ -0,0 +1,617 @@ +static const unsigned char data_processes_shtml[] = { + /* /processes.shtml */ + 0x2f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31, + 0x3e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x70, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x73, 0x3c, 0x2f, 0x68, + 0x31, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, + 0x31, 0x30, 0x30, 0x25, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, + 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x49, 0x44, 0x3c, 0x2f, 0x74, + 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x4e, 0x61, 0x6d, 0x65, + 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x50, + 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x3c, 0x2f, 0x74, + 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x50, 0x6f, 0x6c, 0x6c, + 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3c, 0x2f, + 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, + 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x50, + 0x72, 0x6f, 0x63, 0x73, 0x74, 0x61, 0x74, 0x65, 0x3c, 0x2f, + 0x74, 0x68, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x25, + 0x21, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, + 0x73, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x66, 0x6f, 0x6f, + 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0}; + +static const unsigned char data_404_html[] = { + /* /404.html */ + 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x20, 0x20, 0x3c, + 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, + 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, + 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x63, 0x65, 0x6e, + 0x74, 0x65, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, + 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x68, 0x33, + 0x3e, 0x47, 0x6f, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, + 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x68, 0x65, 0x72, 0x65, + 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, + 0x61, 0x64, 0x2e, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, + 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x62, 0x6f, 0x64, + 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, +0}; + +static const unsigned char data_files_shtml[] = { + /* /files.shtml */ + 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31, + 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3e, + 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, + 0x64, 0x74, 0x68, 0x3d, 0x22, 0x33, 0x30, 0x30, 0x22, 0x3e, + 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, + 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x69, + 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, + 0x3e, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, + 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, + 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, + 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, + 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, + 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, + 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, 0x63, 0x3d, + 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, + 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x31, + 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x25, 0x21, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, + 0x73, 0x20, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, + 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, 0x74, 0x64, + 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x72, + 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, + 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, + 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x2f, 0x66, + 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, + 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, + 0x3c, 0x74, 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x66, + 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, + 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, + 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x22, + 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x22, + 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x31, 0x30, + 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x25, 0x21, 0x20, + 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, + 0x20, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, + 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, 0x74, 0x64, + 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x72, + 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, + 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x74, 0x63, 0x70, 0x2e, 0x73, + 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x2f, 0x74, 0x63, 0x70, + 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e, + 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, + 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, + 0x61, 0x74, 0x73, 0x20, 0x2f, 0x74, 0x63, 0x70, 0x2e, 0x73, + 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, + 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, + 0x72, 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, + 0x70, 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, + 0x3d, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, + 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x74, 0x63, 0x70, 0x2e, + 0x73, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, + 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, + 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x73, 0x74, 0x61, + 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, + 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74, + 0x6d, 0x6c, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, + 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, + 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, + 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74, + 0x6d, 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, + 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, 0x63, + 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, + 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, + 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x25, + 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, 0x61, + 0x74, 0x73, 0x20, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, + 0x73, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, + 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, + 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x73, 0x74, 0x79, + 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x22, 0x3e, 0x2f, 0x73, + 0x74, 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x3c, 0x2f, + 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, + 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, + 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x73, 0x74, 0x79, + 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0xa, 0x3c, 0x2f, 0x74, + 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, + 0x20, 0x73, 0x72, 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, + 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, + 0x74, 0x68, 0x3d, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x73, 0x74, + 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0xa, 0x3e, 0x20, + 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, + 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, + 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x34, + 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x2f, + 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x3c, 0x2f, + 0x61, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, + 0x64, 0x3e, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, + 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x34, 0x30, 0x34, + 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x2f, 0x74, 0x64, + 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, + 0x73, 0x72, 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, + 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, + 0x68, 0x3d, 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, + 0x73, 0x74, 0x61, 0x74, 0x73, 0x20, 0x2f, 0x34, 0x30, 0x34, + 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3e, 0x20, 0x3c, 0x2f, + 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, + 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, + 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x22, 0x3e, 0x2f, 0x66, 0x61, + 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, 0x3c, 0x2f, 0x61, 0x3e, + 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x64, 0x3e, + 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, + 0x61, 0x74, 0x73, 0x20, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, + 0x70, 0x6e, 0x67, 0xa, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, + 0x74, 0x64, 0x3e, 0x3c, 0x69, 0x6d, 0x67, 0x20, 0x73, 0x72, + 0x63, 0x3d, 0x22, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, + 0x6e, 0x67, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x3d, 0x31, 0x30, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, + 0x25, 0x21, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2d, 0x73, 0x74, + 0x61, 0x74, 0x73, 0x20, 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, + 0x70, 0x6e, 0x67, 0xa, 0x3e, 0x20, 0x3c, 0x2f, 0x74, 0x64, + 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x3c, 0x2f, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x3c, 0x2f, 0x63, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x3e, 0xa, 0x25, 0x21, 0x3a, 0x20, + 0x2f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, + 0x6d, 0x6c, 0xa, 0}; + +static const unsigned char data_footer_html[] = { + /* /footer.html */ + 0x2f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x20, 0x20, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, + 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0}; + +static const unsigned char data_header_html[] = { + /* /header.html */ + 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, + 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, + 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f, + 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20, + 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45, + 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34, + 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64, + 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0x57, 0x65, 0x6c, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x49, 0x50, 0x20, 0x77, + 0x65, 0x62, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x21, + 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72, + 0x65, 0x6c, 0x3d, 0x22, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, + 0x68, 0x65, 0x65, 0x74, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, + 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x73, 0x74, + 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x22, 0x3e, 0x20, + 0x20, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, + 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, + 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, + 0x66, 0x66, 0x66, 0x65, 0x65, 0x63, 0x22, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x3d, 0x22, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x22, + 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, + 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, + 0x75, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, + 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, + 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x46, + 0x72, 0x6f, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x67, 0x65, 0x3c, + 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, + 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62, 0x6f, + 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, + 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, + 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, + 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, + 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62, + 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, + 0x66, 0x3d, 0x22, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, + 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, + 0x74, 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, + 0x64, 0x69, 0x76, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, + 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, + 0x65, 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, + 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x74, 0x63, 0x70, + 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0xa, 0x20, 0x20, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c, + 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c, + 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x20, 0x20, 0xa, 0x20, + 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x3d, 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x3e, 0xa, 0}; + +static const unsigned char data_index_html[] = { + /* /index.html */ + 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, + 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, + 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f, + 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20, + 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45, + 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34, + 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64, + 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, + 0x57, 0x65, 0x6c, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x74, 0x6f, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x75, 0x49, 0x50, 0x20, 0x77, + 0x65, 0x62, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x21, + 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x72, + 0x65, 0x6c, 0x3d, 0x22, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x73, + 0x68, 0x65, 0x65, 0x74, 0x22, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x63, 0x73, 0x73, + 0x22, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x73, 0x74, + 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0x22, 0x3e, 0x20, + 0x20, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, + 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x20, + 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3d, 0x22, 0x23, + 0x66, 0x66, 0x66, 0x65, 0x65, 0x63, 0x22, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x3d, 0x22, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x22, + 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, + 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, + 0x75, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, + 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, + 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, + 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x46, + 0x72, 0x6f, 0x6e, 0x74, 0x20, 0x70, 0x61, 0x67, 0x65, 0x3c, + 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, + 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62, 0x6f, + 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, + 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x68, + 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x46, 0x69, 0x6c, 0x65, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, + 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, + 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, + 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, 0x65, 0x6e, 0x75, 0x62, + 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, + 0x66, 0x3d, 0x22, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, + 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, 0x73, + 0x74, 0x69, 0x63, 0x73, 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, + 0x64, 0x69, 0x76, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x64, 0x69, + 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x6d, + 0x65, 0x6e, 0x75, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x61, + 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x74, 0x63, 0x70, + 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, 0x3e, 0x4e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0xa, 0x20, 0x20, 0x63, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c, + 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, + 0x20, 0x20, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c, + 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, + 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, + 0x22, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x62, 0x6c, + 0x6f, 0x63, 0x6b, 0x22, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x70, + 0x3e, 0xa, 0x20, 0x20, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, + 0x77, 0x65, 0x62, 0x20, 0x70, 0x61, 0x67, 0x65, 0x73, 0x20, + 0x61, 0x72, 0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, + 0x20, 0x62, 0x79, 0x20, 0x61, 0x20, 0x73, 0x6d, 0x61, 0x6c, + 0x6c, 0x20, 0x77, 0x65, 0x62, 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, + 0xa, 0x20, 0x20, 0x74, 0x68, 0x65, 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, 0x7e, 0x61, 0x64, 0x61, 0x6d, + 0x2f, 0x75, 0x69, 0x70, 0x2f, 0x22, 0x3e, 0x75, 0x49, 0x50, + 0x20, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x20, + 0x54, 0x43, 0x50, 0x2f, 0x49, 0x50, 0xa, 0x20, 0x20, 0x73, + 0x74, 0x61, 0x63, 0x6b, 0x3c, 0x2f, 0x61, 0x3e, 0x2e, 0xa, + 0x20, 0x20, 0x3c, 0x2f, 0x70, 0x3e, 0xa, 0x20, 0x20, 0x3c, + 0x70, 0x3e, 0xa, 0x20, 0x20, 0x43, 0x6c, 0x69, 0x63, 0x6b, + 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, + 0x6e, 0x6b, 0x73, 0x20, 0x61, 0x62, 0x6f, 0x76, 0x65, 0x20, + 0x66, 0x6f, 0x72, 0x20, 0x77, 0x65, 0x62, 0x20, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x73, 0x74, 0x69, 0x63, 0x73, 0x2e, 0xa, 0x20, 0x20, 0x3c, + 0x2f, 0x70, 0x3e, 0xa, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x62, + 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, + 0x6c, 0x3e, 0xa, 0}; + +static const unsigned char data_style_css[] = { + /* /style.css */ + 0x2f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x2e, 0x63, 0x73, 0x73, 0, + 0x68, 0x31, 0x20, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x74, 0x65, + 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, + 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0xa, 0x20, 0x20, + 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, + 0x31, 0x34, 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, + 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, + 0x61, 0x72, 0x69, 0x61, 0x6c, 0x2c, 0x68, 0x65, 0x6c, 0x76, + 0x65, 0x74, 0x69, 0x63, 0x61, 0x3b, 0xa, 0x20, 0x20, 0x66, + 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x3a, 0x62, 0x6f, 0x6c, 0x64, 0x3b, 0xa, 0x20, 0x20, 0x70, + 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x31, 0x30, 0x70, + 0x78, 0x3b, 0x20, 0xa, 0x7d, 0xa, 0xa, 0x62, 0x6f, 0x64, + 0x79, 0xa, 0x7b, 0xa, 0xa, 0x20, 0x20, 0x62, 0x61, 0x63, + 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, + 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x65, + 0x65, 0x63, 0x3b, 0xa, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, + 0x72, 0x3a, 0x62, 0x6c, 0x61, 0x63, 0x6b, 0x3b, 0xa, 0xa, + 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, + 0x65, 0x3a, 0x38, 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, + 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, + 0x3a, 0x61, 0x72, 0x69, 0x61, 0x6c, 0x2c, 0x68, 0x65, 0x6c, + 0x76, 0x65, 0x74, 0x69, 0x63, 0x61, 0x3b, 0xa, 0x7d, 0xa, + 0xa, 0x2e, 0x6d, 0x65, 0x6e, 0x75, 0xa, 0x7b, 0xa, 0x20, + 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x34, + 0x70, 0x78, 0x3b, 0xa, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, + 0x68, 0x3a, 0x36, 0x30, 0x25, 0x3b, 0xa, 0xa, 0x20, 0x20, + 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x32, 0x70, + 0x78, 0x3b, 0xa, 0x9, 0xa, 0x20, 0x20, 0x62, 0x6f, 0x72, + 0x64, 0x65, 0x72, 0x3a, 0x20, 0x73, 0x6f, 0x6c, 0x69, 0x64, + 0x20, 0x31, 0x70, 0x78, 0x3b, 0xa, 0x20, 0x20, 0x62, 0x61, + 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, + 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, + 0x63, 0x64, 0x32, 0x3b, 0xa, 0x20, 0x20, 0x74, 0x65, 0x78, + 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x6c, 0x65, + 0x66, 0x74, 0x3b, 0xa, 0x20, 0x20, 0xa, 0x20, 0x20, 0x66, + 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x39, + 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, + 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x61, 0x72, + 0x69, 0x61, 0x6c, 0x2c, 0x68, 0x65, 0x6c, 0x76, 0x65, 0x74, + 0x69, 0x63, 0x61, 0x3b, 0x20, 0x20, 0xa, 0x7d, 0xa, 0xa, + 0x64, 0x69, 0x76, 0x2e, 0x6d, 0x65, 0x6e, 0x75, 0x62, 0x6f, + 0x78, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, + 0x68, 0x3a, 0x20, 0x32, 0x35, 0x25, 0x3b, 0xa, 0x20, 0x20, + 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x30, 0x3b, + 0xa, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3a, 0x20, + 0x6c, 0x65, 0x66, 0x74, 0x3b, 0xa, 0x74, 0x65, 0x78, 0x74, + 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x63, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x3b, 0xa, 0x7d, 0xa, 0xa, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0xa, 0x7b, 0x20, 0x20, 0xa, 0x20, 0x20, 0x6d, + 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x34, 0x70, 0x78, + 0x3b, 0xa, 0x20, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, + 0x36, 0x30, 0x25, 0x3b, 0xa, 0xa, 0x20, 0x20, 0x70, 0x61, + 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x32, 0x70, 0x78, 0x3b, + 0xa, 0xa, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, + 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x64, 0x6f, 0x74, 0x74, + 0x65, 0x64, 0x3b, 0xa, 0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, + 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d, 0x63, 0x6f, 0x6c, + 0x6f, 0x72, 0x3a, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65, 0x3b, + 0xa, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, + 0x69, 0x7a, 0x65, 0x3a, 0x38, 0x70, 0x74, 0x3b, 0xa, 0x20, + 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, + 0x6c, 0x79, 0x3a, 0x61, 0x72, 0x69, 0x61, 0x6c, 0x2c, 0x68, + 0x65, 0x6c, 0x76, 0x65, 0x74, 0x69, 0x63, 0x61, 0x3b, 0x20, + 0x20, 0xa, 0xa, 0x7d, 0xa, 0xa, 0x70, 0x2e, 0x69, 0x6e, + 0x74, 0x72, 0x6f, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x6d, 0x61, + 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x3a, + 0x32, 0x30, 0x70, 0x78, 0x3b, 0xa, 0x20, 0x20, 0x6d, 0x61, + 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x72, 0x69, 0x67, 0x68, 0x74, + 0x3a, 0x32, 0x30, 0x70, 0x78, 0x3b, 0xa, 0xa, 0x20, 0x20, + 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, + 0x31, 0x30, 0x70, 0x74, 0x3b, 0xa, 0x2f, 0x2a, 0x20, 0x20, + 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x77, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x3a, 0x62, 0x6f, 0x6c, 0x64, 0x3b, 0x20, 0x2a, 0x2f, + 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, + 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x61, 0x72, 0x69, 0x61, 0x6c, + 0x2c, 0x68, 0x65, 0x6c, 0x76, 0x65, 0x74, 0x69, 0x63, 0x61, + 0x3b, 0x20, 0x20, 0xa, 0x7d, 0xa, 0xa, 0x70, 0x2e, 0x63, + 0x6c, 0x69, 0x6e, 0x6b, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x66, + 0x6f, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x31, + 0x32, 0x70, 0x74, 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, + 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x63, + 0x6f, 0x75, 0x72, 0x69, 0x65, 0x72, 0x2c, 0x6d, 0x6f, 0x6e, + 0x6f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3b, 0x20, 0x20, 0xa, + 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, + 0x67, 0x6e, 0x3a, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, + 0xa, 0x7d, 0xa, 0xa, 0x70, 0x2e, 0x63, 0x6c, 0x69, 0x6e, + 0x6b, 0x39, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, + 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x39, 0x70, 0x74, + 0x3b, 0xa, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, + 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x63, 0x6f, 0x75, 0x72, + 0x69, 0x65, 0x72, 0x2c, 0x6d, 0x6f, 0x6e, 0x6f, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x3b, 0x20, 0x20, 0xa, 0x20, 0x20, 0x74, + 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, + 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0xa, 0x7d, 0xa, + 0xa, 0xa, 0x70, 0xa, 0x7b, 0xa, 0x20, 0x20, 0x70, 0x61, + 0x64, 0x64, 0x69, 0x6e, 0x67, 0x2d, 0x6c, 0x65, 0x66, 0x74, + 0x3a, 0x31, 0x30, 0x70, 0x78, 0x3b, 0xa, 0x7d, 0xa, 0xa, + 0x70, 0x2e, 0x72, 0x69, 0x67, 0x68, 0x74, 0xa, 0x7b, 0xa, + 0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, + 0x67, 0x6e, 0x3a, 0x72, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x20, + 0xa, 0x7d, 0xa, 0xa, 0}; + +static const unsigned char data_tcp_shtml[] = { + /* /tcp.shtml */ + 0x2f, 0x74, 0x63, 0x70, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31, + 0x3e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0x3c, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, + 0x68, 0x3d, 0x22, 0x31, 0x30, 0x30, 0x25, 0x22, 0x3e, 0xa, + 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, + 0x68, 0x3e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x3c, 0x2f, + 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, + 0x3e, 0x52, 0x65, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x74, 0x68, + 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x54, 0x69, 0x6d, 0x65, 0x72, + 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, 0x74, 0x68, 0x3e, 0x46, + 0x6c, 0x61, 0x67, 0x73, 0x3c, 0x2f, 0x74, 0x68, 0x3e, 0x3c, + 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x25, 0x21, 0x20, 0x74, 0x63, + 0x70, 0x2d, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x66, + 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, +0}; + +static const unsigned char data_fade_png[] = { + /* /fade.png */ + 0x2f, 0x66, 0x61, 0x64, 0x65, 0x2e, 0x70, 0x6e, 0x67, 0, + 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 00, 00, + 00, 0xd, 0x49, 0x48, 0x44, 0x52, 00, 00, 00, 0x4, + 00, 00, 00, 0xa, 0x8, 0x2, 00, 00, 00, 0x1c, + 0x99, 0x68, 0x59, 00, 00, 00, 0x9, 0x70, 0x48, 0x59, + 0x73, 00, 00, 0xb, 0x13, 00, 00, 0xb, 0x13, 0x1, + 00, 0x9a, 0x9c, 0x18, 00, 00, 00, 0x7, 0x74, 0x49, + 0x4d, 0x45, 0x7, 0xd6, 0x6, 0x8, 0x14, 0x1b, 0x39, 0xaf, + 0x5b, 0xc0, 0xe3, 00, 00, 00, 0x1d, 0x74, 0x45, 0x58, + 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 00, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, + 0x68, 0x20, 0x54, 0x68, 0x65, 0x20, 0x47, 0x49, 0x4d, 0x50, + 0xef, 0x64, 0x25, 0x6e, 00, 00, 00, 0x3a, 0x49, 0x44, + 0x41, 0x54, 0x8, 0xd7, 0x75, 0x8c, 0x31, 0x12, 00, 0x10, + 0x10, 0xc4, 0x2e, 0x37, 0x9e, 0x40, 0x65, 0xfd, 0xff, 0x83, + 0xf4, 0xa, 0x1c, 0x8d, 0x54, 0x9b, 0xc9, 0xcc, 0x9a, 0x3d, + 0x90, 0x73, 0x71, 0x67, 0x91, 0xd4, 0x74, 0x36, 0xa9, 0x55, + 0x1, 0xf8, 0x29, 0x58, 0xc8, 0xbf, 0x48, 0xc4, 0x81, 0x74, + 0xb, 0xa3, 0xf, 0x7c, 0xdb, 0x4, 0xe8, 0x40, 0x5, 0xdf, + 0xa1, 0xf3, 0xfc, 0x73, 00, 00, 00, 00, 0x49, 0x45, + 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82, 0}; + +static const unsigned char data_stats_shtml[] = { + /* /stats.shtml */ + 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31, + 0x3e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x73, 0x3c, + 0x2f, 0x68, 0x31, 0x3e, 0xa, 0x3c, 0x63, 0x65, 0x6e, 0x74, + 0x65, 0x72, 0x3e, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x33, 0x30, + 0x30, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, + 0x22, 0x30, 0x22, 0x3e, 0xa, 0x3c, 0x74, 0x72, 0x3e, 0x3c, + 0x74, 0x64, 0x3e, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0xa, 0x49, + 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, + 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, + 0x73, 0x65, 0x6e, 0x74, 0xa, 0x9, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, + 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x49, 0x50, 0x20, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x20, 0x20, 0x20, 0x20, + 0x49, 0x50, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50, + 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x2c, 0x20, 0x68, + 0x69, 0x67, 0x68, 0x20, 0x62, 0x79, 0x74, 0x65, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x49, 0x50, 0x20, 0x6c, 0x65, 0x6e, 0x67, 0x74, + 0x68, 0x2c, 0x20, 0x6c, 0x6f, 0x77, 0x20, 0x62, 0x79, 0x74, + 0x65, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x50, 0x20, 0x66, 0x72, + 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0xa, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x57, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0xa, 0x49, 0x43, 0x4d, 0x50, 0x9, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, + 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74, 0xa, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, + 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x54, 0x79, 0x70, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x73, 0xa, 0x54, 0x43, 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x73, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, + 0x64, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, + 0x74, 0x73, 0x20, 0x73, 0x65, 0x6e, 0x74, 0xa, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x20, 0x64, + 0x72, 0x6f, 0x70, 0x70, 0x65, 0x64, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x20, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x44, + 0x61, 0x74, 0x61, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, + 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x20, + 0x41, 0x43, 0x4b, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, + 0x73, 0x65, 0x74, 0x73, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x65, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0xa, 0x9, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x4e, 0x6f, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x76, 0x61, 0x6c, 0x69, 0x61, + 0x62, 0x6c, 0x65, 0xa, 0x9, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x20, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x73, 0x20, + 0x74, 0x6f, 0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x64, 0x20, + 0x70, 0x6f, 0x72, 0x74, 0x73, 0xa, 0x3c, 0x2f, 0x70, 0x72, + 0x65, 0x3e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, + 0x3e, 0x3c, 0x70, 0x72, 0x65, 0x3e, 0x25, 0x21, 0x20, 0x6e, + 0x65, 0x74, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x73, 0xa, 0x3c, + 0x2f, 0x70, 0x72, 0x65, 0x3e, 0x3c, 0x2f, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x3e, 0xa, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, + 0x65, 0x72, 0x3e, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x66, + 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, + 0xa, 0}; + +const struct httpd_fsdata_file file_processes_shtml[] = +{{NULL, data_processes_shtml, data_processes_shtml + 17, sizeof(data_processes_shtml) - 17}}; + +const struct httpd_fsdata_file file_404_html[] = +{{file_processes_shtml, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}}; + +const struct httpd_fsdata_file file_files_shtml[] = +{{file_404_html, data_files_shtml, data_files_shtml + 13, sizeof(data_files_shtml) - 13}}; + +const struct httpd_fsdata_file file_footer_html[] = +{{file_files_shtml, data_footer_html, data_footer_html + 13, sizeof(data_footer_html) - 13}}; + +const struct httpd_fsdata_file file_header_html[] = +{{file_footer_html, data_header_html, data_header_html + 13, sizeof(data_header_html) - 13}}; + +const struct httpd_fsdata_file file_index_html[] = +{{file_header_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}}; + +const struct httpd_fsdata_file file_style_css[] = +{{file_index_html, data_style_css, data_style_css + 11, sizeof(data_style_css) - 11}}; + +const struct httpd_fsdata_file file_tcp_shtml[] = +{{file_style_css, data_tcp_shtml, data_tcp_shtml + 11, sizeof(data_tcp_shtml) - 11}}; + +const struct httpd_fsdata_file file_fade_png[] = +{{file_tcp_shtml, data_fade_png, data_fade_png + 10, sizeof(data_fade_png) - 10}}; + +const struct httpd_fsdata_file file_stats_shtml[] = +{{file_fade_png, data_stats_shtml, data_stats_shtml + 13, sizeof(data_stats_shtml) - 13}}; + +#define HTTPD_FS_ROOT file_stats_shtml + +#define HTTPD_FS_NUMFILES 10 diff --git a/nuttx/netutils/webserver/httpd-fsdata.h b/nuttx/netutils/webserver/httpd-fsdata.h new file mode 100644 index 000000000..bc36cbb54 --- /dev/null +++ b/nuttx/netutils/webserver/httpd-fsdata.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2001, 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels <adam@sics.se> + * + * $Id: httpd-fsdata.h,v 1.1.1.1 2007-08-26 23:07:04 patacongo Exp $ + */ +#ifndef __HTTPD_FSDATA_H__ +#define __HTTPD_FSDATA_H__ + +#include <sys/types.h> +#include <net/uip/uip.h> + +struct httpd_fsdata_file +{ + const struct httpd_fsdata_file *next; + const unsigned char *name; + const unsigned char *data; + const int len; +#ifdef HTTPD_FS_STATISTICS +#if HTTPD_FS_STATISTICS == 1 + uint16 count; +#endif /* HTTPD_FS_STATISTICS */ +#endif /* HTTPD_FS_STATISTICS */ +}; + +struct httpd_fsdata_file_noconst { + struct httpd_fsdata_file *next; + char *name; + char *data; + int len; +#ifdef HTTPD_FS_STATISTICS +#if HTTPD_FS_STATISTICS == 1 + uint16 count; +#endif /* HTTPD_FS_STATISTICS */ +#endif /* HTTPD_FS_STATISTICS */ +}; + +#endif /* __HTTPD_FSDATA_H__ */ diff --git a/nuttx/netutils/webserver/httpd.c b/nuttx/netutils/webserver/httpd.c new file mode 100644 index 000000000..d6c855e61 --- /dev/null +++ b/nuttx/netutils/webserver/httpd.c @@ -0,0 +1,305 @@ +/* httpd + * httpd Web server + * Author: Adam Dunkels <adam@sics.se> + * + * The uIP web server is a very simplistic implementation of an HTTP + * server. It can serve web pages and files from a read-only ROM + * filesystem, and provides a very small scripting language. + * + * Copyright (c) 2004, Adam Dunkels. + * 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. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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. + */ + +#include <stdlib.h> +#include <net/uip/uip.h> +#include <net/uip/httpd.h> + +#include "httpd-cgi.h" +#include "http-strings.h" + +#include <string.h> + +#define STATE_WAITING 0 +#define STATE_OUTPUT 1 + +#define ISO_nl 0x0a +#define ISO_space 0x20 +#define ISO_bang 0x21 +#define ISO_percent 0x25 +#define ISO_period 0x2e +#define ISO_slash 0x2f +#define ISO_colon 0x3a + +static unsigned short generate_part_of_file(void *state) +{ + struct httpd_state *s = (struct httpd_state *)state; + + if (s->file.len > uip_mss()) { + s->len = uip_mss(); + } else { + s->len = s->file.len; + } + memcpy(uip_appdata, s->file.data, s->len); + + return s->len; +} + +static void send_file(struct httpd_state *s) +{ + do { + psock_generator_send(&s->sout, generate_part_of_file, s); + s->file.len -= s->len; + s->file.data += s->len; + } while(s->file.len > 0); +#warning REVISIT must not return until file sent +} + +static void send_part_of_file(struct httpd_state *s) +{ + psock_send(&s->sout, s->file.data, s->len); +#warning REVISIT must not return until file sent +} + +static void next_scriptstate(struct httpd_state *s) +{ + char *p; + p = strchr(s->scriptptr, ISO_nl) + 1; + s->scriptlen -= (unsigned short)(p - s->scriptptr); + s->scriptptr = p; +} + +static void handle_script(struct httpd_state *s) +{ + char *ptr; + + while(s->file.len > 0) { + + /* Check if we should start executing a script. */ + if (*s->file.data == ISO_percent && + *(s->file.data + 1) == ISO_bang) { + s->scriptptr = s->file.data + 3; + s->scriptlen = s->file.len - 3; + if (*(s->scriptptr - 1) == ISO_colon) { + httpd_fs_open(s->scriptptr + 1, &s->file); + send_file(s); + } else { + httpd_cgi(s->scriptptr)(s, s->scriptptr); + } + next_scriptstate(s); + + /* The script is over, so we reset the pointers and continue + sending the rest of the file. */ + s->file.data = s->scriptptr; + s->file.len = s->scriptlen; + } else { + /* See if we find the start of script marker in the block of HTML + to be sent. */ + + if (s->file.len > uip_mss()) { + s->len = uip_mss(); + } else { + s->len = s->file.len; + } + + if (*s->file.data == ISO_percent) { + ptr = strchr(s->file.data + 1, ISO_percent); + } else { + ptr = strchr(s->file.data, ISO_percent); + } + if (ptr != NULL && + ptr != s->file.data) { + s->len = (int)(ptr - s->file.data); + if (s->len >= uip_mss()) { + s->len = uip_mss(); + } + } + send_part_of_file(s); + s->file.data += s->len; + s->file.len -= s->len; + } + } +#warning REVISIT must not return until sent +} + +static void send_headers(struct httpd_state *s, const char *statushdr) +{ + char *ptr; + + PSOCK_SEND_STR(&s->sout, statushdr); + + ptr = strrchr(s->filename, ISO_period); + if (ptr == NULL) { + PSOCK_SEND_STR(&s->sout, http_content_type_binary); + } else if (strncmp(http_html, ptr, 5) == 0 || + strncmp(http_shtml, ptr, 6) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_html); + } else if (strncmp(http_css, ptr, 4) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_css); + } else if (strncmp(http_png, ptr, 4) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_png); + } else if (strncmp(http_gif, ptr, 4) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_gif); + } else if (strncmp(http_jpg, ptr, 4) == 0) { + PSOCK_SEND_STR(&s->sout, http_content_type_jpg); + } else { + PSOCK_SEND_STR(&s->sout, http_content_type_plain); + } +#warning REVISIT must not return until sent +} + +static void handle_output(struct httpd_state *s) +{ + char *ptr; + + if (!httpd_fs_open(s->filename, &s->file)) + { + httpd_fs_open(http_404_html, &s->file); + strcpy(s->filename, http_404_html); + send_headers(s, http_header_404); + send_file(s); + } + else + { + send_headers(s, http_header_200); + ptr = strchr(s->filename, ISO_period); + if (ptr != NULL && strncmp(ptr, http_shtml, 6) == 0) + { + handle_script(s); + } + else + { + send_file(s); + } + } + PSOCK_CLOSE(&s->sout); +} + +static void handle_input(struct httpd_state *s) +{ + psock_readto(&s->sin, ISO_space); + + if (strncmp(s->inputbuf, http_get, 4) != 0) + { + PSOCK_CLOSE(&s->sin); + return; + } + + psock_readto(&s->sin, ISO_space); + + if (s->inputbuf[0] != ISO_slash) + { + PSOCK_CLOSE(&s->sin); + return; + } + + if (s->inputbuf[1] == ISO_space) + { + strncpy(s->filename, http_index_html, sizeof(s->filename)); + } + else + { + s->inputbuf[psock_datalen(&s->sin) - 1] = 0; + strncpy(s->filename, &s->inputbuf[0], sizeof(s->filename)); + } + + s->state = STATE_OUTPUT; + + while(1) + { + psock_readto(&s->sin, ISO_nl); + + if (strncmp(s->inputbuf, http_referer, 8) == 0) + { + s->inputbuf[psock_datalen(&s->sin) - 2] = 0; + } + } +} + +static void handle_connection(struct httpd_state *s) +{ + handle_input(s); + if (s->state == STATE_OUTPUT) { + handle_output(s); + } +} + +/* This function is called by the UIP interrupt handling logic whenevent an + * event of interest occurs. + */ + +void uip_interrupt_event(void) +{ + /* Get the private application specific data */ + struct httpd_state *s = (struct httpd_state *)(uip_conn->private); + + /* Has application specific data been allocate yet? */ + + if (!s) + { + /* No.. allocate it now */ + s = (struct httpd_state *)malloc(sizeof(struct httpd_state)); + if (!s) + { + return; + } + + /* And assign the private instance to the connection */ + uip_conn->private = s; + } + + if (uip_closed() || uip_aborted() || uip_timedout()) { + } else if (uip_connected()) { + psock_init(&s->sin, s->inputbuf, sizeof(s->inputbuf) - 1); + psock_init(&s->sout, s->inputbuf, sizeof(s->inputbuf) - 1); + s->state = STATE_WAITING; + s->timer = 0; + handle_connection(s); + } else if (s != NULL) { + if (uip_poll()) { + ++s->timer; + if (s->timer >= 20) { + uip_abort(); + } + } else { + s->timer = 0; + } + handle_connection(s); + } else { + uip_abort(); + } +} + +/* Initialize the web server + * + * This function initializes the web server and should be + * called at system boot-up. + */ + +void httpd_init(void) +{ + uip_listen(HTONS(80)); +} diff --git a/nuttx/netutils/webserver/makefsdata b/nuttx/netutils/webserver/makefsdata new file mode 100755 index 000000000..b2109abdb --- /dev/null +++ b/nuttx/netutils/webserver/makefsdata @@ -0,0 +1,78 @@ +#!/usr/bin/perl + +open(OUTPUT, "> httpd-fsdata.c"); + +chdir("httpd-fs"); + +opendir(DIR, "."); +@files = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR); +closedir(DIR); + +foreach $file (@files) { + + if(-d $file && $file !~ /^\./) { + print "Processing directory $file\n"; + opendir(DIR, $file); + @newfiles = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR); + closedir(DIR); + printf "Adding files @newfiles\n"; + @files = (@files, map { $_ = "$file/$_" } @newfiles); + next; + } +} + +foreach $file (@files) { + if(-f $file) { + + print "Adding file $file\n"; + + open(FILE, $file) || die "Could not open file $file\n"; + + $file =~ s-^-/-; + $fvar = $file; + $fvar =~ s-/-_-g; + $fvar =~ s-\.-_-g; + # for AVR, add PROGMEM here + 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 "0};\n\n"); + close(FILE); + push(@fvars, $fvar); + push(@pfiles, $file); + } +} + +for($i = 0; $i < @fvars; $i++) { + $file = $pfiles[$i]; + $fvar = $fvars[$i]; + + if($i == 0) { + $prevfile = "NULL"; + } else { + $prevfile = "file" . $fvars[$i - 1]; + } + print(OUTPUT "const struct httpd_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 HTTPD_FS_ROOT file$fvars[$i - 1]\n\n"); +print(OUTPUT "#define HTTPD_FS_NUMFILES $i\n"); diff --git a/nuttx/netutils/webserver/makestrings b/nuttx/netutils/webserver/makestrings new file mode 100755 index 000000000..20f0e2429 --- /dev/null +++ b/nuttx/netutils/webserver/makestrings @@ -0,0 +1,40 @@ +#!/usr/bin/perl + + +sub stringify { + my $name = shift(@_); + open(OUTPUTC, "> $name.c"); + open(OUTPUTH, "> $name.h"); + + open(FILE, "$name"); + + while(<FILE>) { + if(/(.+) "(.+)"/) { + $var = $1; + $data = $2; + + $datan = $data; + $datan =~ s/\\r/\r/g; + $datan =~ s/\\n/\n/g; + $datan =~ s/\\01/\01/g; + $datan =~ s/\\0/\0/g; + + printf(OUTPUTC "const char $var\[%d] = \n", length($datan) + 1); + printf(OUTPUTC "/* \"$data\" */\n"); + printf(OUTPUTC "{"); + for($j = 0; $j < length($datan); $j++) { + printf(OUTPUTC "%#02x, ", unpack("C", substr($datan, $j, 1))); + } + printf(OUTPUTC "};\n"); + + printf(OUTPUTH "extern const char $var\[%d];\n", length($datan) + 1); + + } + } + close(OUTPUTC); + close(OUTPUTH); +} +stringify("http-strings"); + +exit 0; + |