summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-09-12 18:42:07 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-09-12 18:42:07 +0000
commitd660afc8fd83a630d0a223dd2796003024ce4f11 (patch)
treece8e776d60e1d48cd2f06d56561536aff5bdd6d7
parentec4b9fcf907986295f1f5e1ccf86821ef5a085b5 (diff)
downloadnuttx-d660afc8fd83a630d0a223dd2796003024ce4f11.tar.gz
nuttx-d660afc8fd83a630d0a223dd2796003024ce4f11.tar.bz2
nuttx-d660afc8fd83a630d0a223dd2796003024ce4f11.zip
Network discover utility from Max Holtzberg
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5137 42af7a65-404d-4744-a932-0658087f49c3
-rwxr-xr-xapps/ChangeLog.txt4
-rw-r--r--apps/examples/README.txt22
-rw-r--r--apps/examples/discover/Kconfig42
-rw-r--r--apps/examples/discover/Makefile106
-rw-r--r--apps/examples/discover/main.c183
-rw-r--r--apps/include/netutils/discover.h58
-rw-r--r--apps/netutils/Kconfig4
-rw-r--r--apps/netutils/Make.defs6
-rw-r--r--apps/netutils/Makefile3
-rw-r--r--apps/netutils/README.txt10
-rw-r--r--apps/netutils/discover/Kconfig39
-rw-r--r--apps/netutils/discover/Makefile100
-rw-r--r--apps/netutils/discover/README.txt9
-rw-r--r--apps/netutils/discover/discover.c456
-rw-r--r--nuttx/Documentation/README.html1
-rw-r--r--nuttx/README.txt2
16 files changed, 1041 insertions, 4 deletions
diff --git a/apps/ChangeLog.txt b/apps/ChangeLog.txt
index 833a62cd1..6df66b95f 100755
--- a/apps/ChangeLog.txt
+++ b/apps/ChangeLog.txt
@@ -319,3 +319,7 @@
* apps/netutils/webserver/httpd_sendfile.c: Add and option,
CONFIG_NETUTILS_HTTPD_SENDFILE to transfer files using the NuttX
sendfile() interface.
+ * apps/netutils/discover: A UDP network discovery utility contributed
+ by Max Holtzberg.
+ * apps/examples/discover: A test example for the UDP network discovery
+ utility (also contribed by Max Holtzberg).
diff --git a/apps/examples/README.txt b/apps/examples/README.txt
index 52d7279da..0d327ebfb 100644
--- a/apps/examples/README.txt
+++ b/apps/examples/README.txt
@@ -275,6 +275,28 @@ examples/dhcpd
CONFIGURED_APPS += uiplib
+examples/discover
+^^^^^^^^^^^^^^^^^
+
+ This example execises netutils/discover utility. This example initializes
+ and starts the UDP discover daemon. This daemon is useful for discovering
+ devices in local networks, especially with DHCP configured devices. It
+ listens for UDP broadcasts which also can include a device class so that
+ groups of devices can be discovered. It is also possible to address all
+ classes with a kind of broadcast discover.
+
+ This example will automatically be built as an NSH built-in if
+ CONFIG_NSH_BUILTIN_APPS is selected. Otherwise, it will be a standalone
+ program with entry point "discover_main".
+
+ NuttX configuration settings:
+
+ CONFIG_EXAMPLE_DISCOVER_DHCPC - DHCP Client
+ CONFIG_EXAMPLE_DISCOVER_NOMAC - Use canned MAC address
+ CONFIG_EXAMPLE_DISCOVER_IPADDR - Target IP address
+ CONFIG_EXAMPLE_DISCOVER_DRIPADDR - Router IP address
+ CONFIG_EXAMPLE_DISCOVER_NETMASK - Network Mask
+
examples/ftpc
^^^^^^^^^^^^^
diff --git a/apps/examples/discover/Kconfig b/apps/examples/discover/Kconfig
new file mode 100644
index 000000000..afdb9ff82
--- /dev/null
+++ b/apps/examples/discover/Kconfig
@@ -0,0 +1,42 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+config EXAMPLES_DISCOVER
+ bool "UDP Discovery Example"
+ default n
+ depends on NET_UDP
+ select NETUTILS_DISCOVER
+ ---help---
+ Enable the netutils/discover utility. This example initializes and
+ starts the UDP discover daemon. This daemon is useful for
+ discovering devices in local networks, especially with DHCP
+ configured devices. It listens for UDP broadcasts which also can
+ include a device class so that groups of devices can be discovered.
+ It is also possible to address all classes with a kind of broadcast
+ discover.
+
+if EXAMPLES_DISCOVER
+
+config EXAMPLE_DISCOVER_DHCPC
+ bool "DHCP Client"
+ default n
+
+config EXAMPLE_DISCOVER_NOMAC
+ bool "Use canned MAC address"
+ default n
+
+config EXAMPLE_DISCOVER_IPADDR
+ hex "Target IP address"
+ default 0x0a000002
+
+config EXAMPLE_DISCOVER_DRIPADDR
+ hex "Router IP address"
+ default 0x0a000001
+
+config EXAMPLE_DISCOVER_NETMASK
+ hex "Network Mask"
+ default 0xffffff00
+
+endif
diff --git a/apps/examples/discover/Makefile b/apps/examples/discover/Makefile
new file mode 100644
index 000000000..f42f310a1
--- /dev/null
+++ b/apps/examples/discover/Makefile
@@ -0,0 +1,106 @@
+############################################################################
+# apps/examples/discover/Makefile
+#
+# Copyright (C) 2012 Max Holtzberg. All rights reserved.
+# Copyright (C) 2008, 2010-2012 Gregory Nutt. All rights reserved.
+#
+# Authors: Max Holtzberg <mh@uvc.de>
+# Gregory Nutt <gnutt@nuttx.org>
+#
+# 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)/.config
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# Discover built-in application info
+
+APPNAME = discover
+PRIORITY = SCHED_PRIORITY_DEFAULT
+STACKSIZE = 2048
+
+ASRCS =
+CSRCS = main.c
+
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+ifeq ($(WINTOOL),y)
+ BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}"
+else
+ BIN = "$(APPDIR)/libapps$(LIBEXT)"
+endif
+
+ROOTDEPPATH = --dep-path .
+
+# Common build
+
+VPATH =
+
+all: .built
+.PHONY: clean depend distclean
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+.built: $(OBJS)
+ @( for obj in $(OBJS) ; do \
+ $(call ARCHIVE, $(BIN), $${obj}); \
+ done ; )
+ @touch .built
+
+.context:
+ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
+ $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main)
+ @touch $@
+endif
+
+context: .context
+
+.depend: Makefile $(SRCS)
+ @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
+ @touch $@
+
+depend: .depend
+
+clean:
+ @rm -f *.o *~ .*.swp .built
+ $(call CLEAN)
+
+distclean: clean
+ @rm -f Make.dep .depend
+
+-include Make.dep
diff --git a/apps/examples/discover/main.c b/apps/examples/discover/main.c
new file mode 100644
index 000000000..b857e4f68
--- /dev/null
+++ b/apps/examples/discover/main.c
@@ -0,0 +1,183 @@
+/****************************************************************************
+ * examples/discover/main.c
+ *
+ * Copyright (C) 2012 Max Holtzberg. All rights reserved.
+ * Copyright (C) 2008, 2011-2012 Gregory Nutt. All rights reserved.
+ *
+ * Authors: Max Holtzberg <mh@uvc.de>
+ * Gregory Nutt <gnutt@nuttx.org>
+ *
+ * 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 <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <debug.h>
+
+#include <net/if.h>
+#include <nuttx/net/uip/uip.h>
+#include <nuttx/net/uip/uip-arp.h>
+
+#include <apps/netutils/uiplib.h>
+#include <apps/netutils/discover.h>
+
+#ifdef CONFIG_EXAMPLE_DISCOVER_DHCPC
+# include <arpa/inet.h>
+#endif
+
+/* Here we include the header file for the application(s) we use in
+ * our project as defined in the config/<board-name>/defconfig file
+ */
+
+/* DHCPC may be used in conjunction with any other feature (or not) */
+
+#ifdef CONFIG_EXAMPLE_DISCOVER_DHCPC
+# include <apps/netutils/resolv.h>
+# include <apps/netutils/dhcpc.h>
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * discover_main
+ ****************************************************************************/
+
+int discover_main(int argc, char *argv[])
+{
+#ifndef CONFIG_NSH_BUILTIN_APPS
+ struct in_addr addr;
+#if defined(CONFIG_EXAMPLE_DISCOVER_DHCPC) || defined(CONFIG_EXAMPLE_DISCOVER_NOMAC)
+ uint8_t mac[IFHWADDRLEN];
+#endif
+#ifdef CONFIG_EXAMPLE_DISCOVER_DHCPC
+ void *handle;
+#endif
+
+/* Many embedded network interfaces must have a software assigned MAC */
+
+#ifdef CONFIG_EXAMPLE_DISCOVER_NOMAC
+ mac[0] = 0x00;
+ mac[1] = 0xe0;
+ mac[2] = 0xde;
+ mac[3] = 0xad;
+ mac[4] = 0xbe;
+ mac[5] = 0xef;
+ uip_setmacaddr("eth0", mac);
+#endif
+
+ /* Set up our host address */
+
+#ifdef CONFIG_EXAMPLE_DISCOVER_DHCPC
+ addr.s_addr = 0;
+#else
+ addr.s_addr = HTONL(CONFIG_EXAMPLE_DISCOVER_IPADDR);
+#endif
+ uip_sethostaddr("eth0", &addr);
+
+ /* Set up the default router address */
+
+ addr.s_addr = HTONL(CONFIG_EXAMPLE_DISCOVER_DRIPADDR);
+ uip_setdraddr("eth0", &addr);
+
+ /* Setup the subnet mask */
+
+ addr.s_addr = HTONL(CONFIG_EXAMPLE_DISCOVER_NETMASK);
+ uip_setnetmask("eth0", &addr);
+
+#ifdef CONFIG_EXAMPLE_DISCOVER_DHCPC
+ /* Set up the resolver */
+
+ resolv_init();
+
+ /* Get the MAC address of the NIC */
+
+ uip_getmacaddr("eth0", mac);
+
+ /* Set up the DHCPC modules */
+
+ handle = dhcpc_open(&mac, IFHWADDRLEN);
+
+ /* Get an IP address. Note: there is no logic here for renewing the address in this
+ * example. The address should be renewed in ds.lease_time/2 seconds.
+ */
+
+ printf("Getting IP address\n");
+ if (handle)
+ {
+ struct dhcpc_state ds;
+ (void)dhcpc_request(handle, &ds);
+ uip_sethostaddr("eth1", &ds.ipaddr);
+
+ if (ds.netmask.s_addr != 0)
+ {
+ uip_setnetmask("eth0", &ds.netmask);
+ }
+
+ if (ds.default_router.s_addr != 0)
+ {
+ uip_setdraddr("eth0", &ds.default_router);
+ }
+
+ if (ds.dnsaddr.s_addr != 0)
+ {
+ resolv_conf(&ds.dnsaddr);
+ }
+
+ dhcpc_close(handle);
+ printf("IP: %s\n", inet_ntoa(ds.ipaddr));
+ }
+#endif
+#endif /* CONFIG_NSH_BUILTIN_APPS */
+
+ if (discover_start() < 0)
+ {
+ ndbg("Could not start discover daemon.\n");
+ return ERROR;
+ }
+
+ return OK;
+}
+
diff --git a/apps/include/netutils/discover.h b/apps/include/netutils/discover.h
new file mode 100644
index 000000000..c2226918d
--- /dev/null
+++ b/apps/include/netutils/discover.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+ * apps/include/netutils/discover.h
+ *
+ * Copyright (C) 2012 Max Holtzberg. All rights reserved.
+ * Author: Max Holtzberg <mh@uvc.de>
+ *
+ * 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 __APPS_INCLUDE_NETUTILS_DISCOVER_H
+#define __APPS_INCLUDE_NETUTILS_DISCOVER_H
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: discover_start
+ *
+ * Description:
+ * Start the discover daemon.
+ *
+ * Return:
+ * The process ID (pid) of the new discover daemon is returned on
+ * success; A negated errno is returned if the daemon was not successfully
+ * started.
+ *
+ ****************************************************************************/
+
+int discover_start(void);
+
+#endif /* __APPS_INCLUDE_NETUTILS_DISCOVER_H */
diff --git a/apps/netutils/Kconfig b/apps/netutils/Kconfig
index cd0cb84dd..aa0f14963 100644
--- a/apps/netutils/Kconfig
+++ b/apps/netutils/Kconfig
@@ -52,3 +52,7 @@ endmenu
menu "uIP web server"
source "$APPSDIR/netutils/webserver/Kconfig"
endmenu
+
+menu "UDP Discovery Utility"
+source "$APPSDIR/netutils/discover/Kconfig"
+endmenu
diff --git a/apps/netutils/Make.defs b/apps/netutils/Make.defs
index 04accf5d2..f957009b5 100644
--- a/apps/netutils/Make.defs
+++ b/apps/netutils/Make.defs
@@ -78,6 +78,10 @@ ifeq ($(CONFIG_NETUTILS_WEBCLIENT),y)
CONFIGURED_APPS += netutils/webclient
endif
-ifeq ($(CONFIGNETUTILS_WEBSERVER),y)
+ifeq ($(CONFIG_NETUTILS_WEBSERVER),y)
CONFIGURED_APPS += netutils/webserver
endif
+
+ifeq ($(CONFIG_NETUTILS_DISCOVER),y)
+CONFIGURED_APPS += netutils/discover
+endif
diff --git a/apps/netutils/Makefile b/apps/netutils/Makefile
index 1313c223d..03261c7a3 100644
--- a/apps/netutils/Makefile
+++ b/apps/netutils/Makefile
@@ -38,7 +38,8 @@
# Sub-directories
ifeq ($(CONFIG_NET),y)
-SUBDIRS = uiplib dhcpc dhcpd ftpc ftpd resolv smtp telnetd webclient webserver tftpc thttpd
+SUBDIRS = uiplib dhcpc dhcpd discover ftpc ftpd resolv smtp telnetd
+SUBDIRS += webclient webserver tftpc thttpd
endif
all: nothing
diff --git a/apps/netutils/README.txt b/apps/netutils/README.txt
index 26f11b7ce..231cf62c1 100644
--- a/apps/netutils/README.txt
+++ b/apps/netutils/README.txt
@@ -1,5 +1,5 @@
-netutils
-^^^^^^^^
+netutils README.txt
+^^^^^^^^^^^^^^^^^^^
Contents
--------
@@ -39,6 +39,12 @@ highly influenced by uIP) include:
dhcpd - Dynamic Host Configuration Protocol (DHCP) server. See
apps/include/netutils/dhcpd.h for interface information.
+ discover - This daemon is useful for discovering devices in local
+ networks, especially with DHCP configured devices. It
+ listens for UDP broadcasts which also can include a
+ device class so that groups of devices can be discovered.
+ It is also possible to address all classes with a kind of
+ broadcast discover. (Contributed by Max Holtzberg).
tftpc - TFTP client. See apps/include/netutils/tftp.h
for interface information.
telnetd - TELNET server. This is the Telnet logic adapted from
diff --git a/apps/netutils/discover/Kconfig b/apps/netutils/discover/Kconfig
new file mode 100644
index 000000000..336550511
--- /dev/null
+++ b/apps/netutils/discover/Kconfig
@@ -0,0 +1,39 @@
+#
+# For a description of the syntax of this configuration file,
+# see misc/tools/kconfig-language.txt.
+#
+
+config NETUTILS_DISCOVER
+ bool "Network Discovery Utility"
+ default n
+ depends on NET_UDP
+ ---help---
+ Tool for discovering devices on the local network per UDP broadcast.
+
+if NETUTILS_DISCOVER
+
+DISCOVER_STACK_SIZE
+ int "Discover Daemon Stack Size"
+ default 1024
+
+DISCOVER_PRIORITY
+ int "Discover Daemon Priority"
+ default 50
+
+DISCOVER_PORT
+ int "Discover Daemon Port Number"
+ default 96
+
+DISCOVER_INTERFACE
+ int "Network Interface Name"
+ default "eth0"
+
+DISCOVER_DEVICE_CLASS
+ hex "Network Discovery Class"
+ default 0xff
+
+CONFIG_DISCOVER_DESCR
+ string "Discoverer Description"
+ default "NuttX"
+
+endif
diff --git a/apps/netutils/discover/Makefile b/apps/netutils/discover/Makefile
new file mode 100644
index 000000000..52099b439
--- /dev/null
+++ b/apps/netutils/discover/Makefile
@@ -0,0 +1,100 @@
+############################################################################
+# apps/netutils/discover/Makefile
+#
+# Copyright (C) 2012 Max Holtzberg. All rights reserved.
+# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+#
+# Authors: Max Holtzberg <mh@uvc.de>
+# Gregory Nutt <gnutt@nuttx.org>
+#
+# 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)/.config
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# Telnet daemon
+
+ASRCS =
+CSRCS =
+
+ifeq ($(CONFIG_NET_UDP),y)
+CSRCS += discover.c
+endif
+
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+ifeq ($(WINTOOL),y)
+ BIN = "${shell cygpath -w $(APPDIR)/libapps$(LIBEXT)}"
+else
+ BIN = "$(APPDIR)/libapps$(LIBEXT)"
+endif
+
+ROOTDEPPATH = --dep-path .
+
+# Common build
+
+VPATH =
+
+all: .built
+.PHONY: context depend clean distclean
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+.built: $(OBJS)
+ @( for obj in $(OBJS) ; do \
+ $(call ARCHIVE, $(BIN), $${obj}); \
+ done ; )
+ @touch .built
+
+context:
+
+.depend: Makefile $(SRCS)
+ @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
+ @touch $@
+
+depend: .depend
+
+clean:
+ @rm -f *.o *~ .*.swp .built
+ $(call CLEAN)
+
+distclean: clean
+ @rm -f Make.dep .depend
+
+-include Make.dep
diff --git a/apps/netutils/discover/README.txt b/apps/netutils/discover/README.txt
new file mode 100644
index 000000000..11aab8bf3
--- /dev/null
+++ b/apps/netutils/discover/README.txt
@@ -0,0 +1,9 @@
+apps/netutils/discover README.txt
+=================================
+
+This daemon is useful for discovering devices in local networks, especially
+with DHCP configured devices. It listens for UDP broadcasts which also can
+include a device class so that groups of devices can be discovered. It is
+also possible to address all classes with a kind of broadcast discover.
+
+See nuttx/tools/discover.py for a client example.
diff --git a/apps/netutils/discover/discover.c b/apps/netutils/discover/discover.c
new file mode 100644
index 000000000..67df02b3f
--- /dev/null
+++ b/apps/netutils/discover/discover.c
@@ -0,0 +1,456 @@
+/****************************************************************************
+ * examples/discover/main.c
+ *
+ * Copyright (C) 2012 Max Holtzberg. All rights reserved.
+ * Copyright (C) 2008, 2011-2012 Gregory Nutt. All rights reserved.
+ *
+ * Authors: Max Holtzberg <mh@uvc.de>
+ * Gregory Nutt <gnutt@nuttx.org>
+ *
+ * This code is derived from the netutils/dhcpd code.
+ *
+ * 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 <debug.h>
+#include <errno.h>
+#include <sched.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <apps/netutils/discover.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* Configuration ************************************************************/
+
+#ifndef CONFIG_DISCOVER_STACK_SIZE
+# define CONFIG_DISCOVER_STACK_SIZE 1024
+#endif
+
+#ifndef CONFIG_DISCOVER_PRIORITY
+# define CONFIG_DISCOVER_PRIORITY SCHED_PRIORITY_DEFAULT
+#endif
+
+#ifndef CONFIG_DISCOVER_PORT
+# define CONFIG_DISCOVER_PORT 96
+#endif
+
+#ifndef CONFIG_DISCOVER_INTERFACE
+# define CONFIG_DISCOVER_INTERFACE "eth0"
+#endif
+
+#ifndef CONFIG_DISCOVER_DEVICE_CLASS
+# define CONFIG_DISCOVER_DEVICE_CLASS DISCOVER_ALL
+#endif
+
+#ifndef CONFIG_DISCOVER_DESCR
+# define CONFIG_DISCOVER_DESCR CONFIG_ARCH_BOARD
+#endif
+
+/* Internal Definitions *****************************************************/
+/* Discover request packet format:
+ * Byte Description
+ * 0 Protocol indentifier (0x99)
+ * 1 Request command 0x01
+ * 2 Destination device class (For querying subsets of available devices)
+ * 0xff for all devices
+ * 3 Checksum (Byte 0 - Byte 1 - Byte n) & 0xff
+ */
+
+/* Discover response packet format:
+ * Byte Description
+ * 0 Protocol indentifier (0x99)
+ * 1 Reponse command (0x02)
+ * 2-33 Device description string with 0 bytes filled
+ * 34 Checksum (Byte 0 - Byte 1 - Byte n) & 0xff
+ */
+
+#define DISCOVER_PROTO_ID 0x99
+#define DISCOVER_REQUEST 0x01
+#define DISCOVER_RESPONSE 0x02
+#define DISCOVER_ALL 0xff
+#define DISCOVER_REQUEST_SIZE 4
+#define DISCOVER_RESPONSE_SIZE 35
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+typedef uint8_t request_t[DISCOVER_REQUEST_SIZE];
+typedef uint8_t response_t[DISCOVER_RESPONSE_SIZE];
+
+struct discover_state_s
+{
+ in_addr_t serverip;
+ request_t request;
+ response_t response;
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+struct discover_state_s g_state;
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int discover_daemon(int argc, char *argv[]);
+static inline int discover_socket(void);
+static inline int discover_openlistener(void);
+static inline int discover_openresponder(void);
+static inline int discover_parse(request_t packet);
+static inline int discover_respond(in_addr_t *ipaddr);
+static inline void discover_initresponse(void);
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static inline void discover_initresponse()
+{
+ int chk = 0;
+ int i;
+
+ g_state.response[0] = DISCOVER_PROTO_ID;
+ g_state.response[1] = DISCOVER_RESPONSE;
+
+ strncpy((char*) &g_state.response[2], CONFIG_DISCOVER_DESCR,
+ DISCOVER_RESPONSE_SIZE-3);
+
+ for (i = 0; i < DISCOVER_RESPONSE_SIZE-1; i++)
+ {
+ chk -= g_state.response[i];
+ }
+
+ /* Append check sum */
+
+ g_state.response[DISCOVER_RESPONSE_SIZE-1] = chk & 0xff;
+}
+
+static int discover_daemon(int argc, char *argv[])
+{
+ int sockfd = -1;
+ int nbytes;
+ int addrlen = sizeof(struct sockaddr_in);
+ struct sockaddr_in srcaddr;
+
+ memset(&g_state, 0, sizeof(struct discover_state_s));
+ discover_initresponse();
+
+ nvdbg("Started\n");
+
+ for (;;)
+ {
+ /* Create a socket to listen for requests from DHCP clients */
+
+ if (sockfd < 0)
+ {
+ sockfd = discover_openlistener();
+ if (sockfd < 0)
+ {
+ ndbg("Failed to create socket\n");
+ break;
+ }
+ }
+
+ /* Read the next packet */
+
+ nbytes = recvfrom(sockfd, &g_state.request, sizeof(g_state.request), 0,
+ (struct sockaddr*) &srcaddr,
+ (socklen_t *) &addrlen);
+ if (nbytes < 0)
+ {
+ /* On errors (other EINTR), close the socket and try again */
+
+ ndbg("recv failed: %d\n", errno);
+ if (errno != EINTR)
+ {
+ close(sockfd);
+ sockfd = -1;
+ }
+ continue;
+ }
+
+ if (discover_parse(g_state.request) != OK)
+ {
+ continue;
+ }
+
+ ndbg("Received discover from %08lx'\n", srcaddr.sin_addr.s_addr);
+
+ discover_respond(&srcaddr.sin_addr.s_addr);
+ }
+
+ return OK;
+}
+
+static inline int discover_parse(request_t packet)
+{
+ int i;
+ uint8_t chk = 0;
+
+ if (packet[0] != DISCOVER_PROTO_ID)
+ {
+ ndbg("Wrong protocol id: %d\n", packet[0]);
+ return ERROR;
+ }
+
+ if (packet[1] != DISCOVER_REQUEST)
+ {
+ ndbg("Wrong command: %d\n", packet[1]);
+ return ERROR;
+ }
+
+ if (packet[2] == 0xff || packet[2] == CONFIG_DISCOVER_DEVICE_CLASS)
+ {
+ for (i = 0; i < DISCOVER_REQUEST_SIZE-1; i++)
+ chk -= packet[i];
+
+ if ((chk & 0xff) != packet[3])
+ {
+ ndbg("Checksum does not match: %d\n", packet[3]);
+ return ERROR;
+ }
+ else
+ {
+ return OK;
+ }
+ }
+ return ERROR;
+}
+
+static inline int discover_respond(in_addr_t *ipaddr)
+{
+ struct sockaddr_in addr;
+ int sockfd;
+ int ret;
+
+ sockfd = discover_openresponder();
+ if (sockfd >= 0)
+ {
+ /* Then send the reponse to the DHCP client port at that address */
+
+ memset(&addr, 0, sizeof(struct sockaddr_in));
+ addr.sin_family = AF_INET;
+ addr.sin_port = HTONS(CONFIG_DISCOVER_PORT);
+ addr.sin_addr.s_addr = *ipaddr;
+
+ ret = sendto(sockfd, &g_state.response, sizeof(g_state.response), 0,
+ (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
+ if (ret < 0)
+ {
+ ndbg("Could not send discovery response: %d\n", errno);
+ }
+
+ close(sockfd);
+ }
+
+ return ret;
+}
+
+static inline int discover_socket()
+{
+ int sockfd;
+#if defined(HAVE_SO_REUSEADDR) || defined(HAVE_SO_BROADCAST)
+ int optval;
+ int ret;
+#endif
+
+ /* Create a socket to listen for requests from DHCP clients */
+
+ sockfd = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ {
+ ndbg("socket failed: %d\n", errno);
+ return ERROR;
+ }
+
+ /* Configure the socket */
+
+#ifdef HAVE_SO_REUSEADDR
+ optval = 1;
+ ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int));
+ if (ret < 0)
+ {
+ ndbg("setsockopt SO_REUSEADDR failed: %d\n", errno);
+ close(sockfd);
+ return ERROR;
+ }
+#endif
+
+#ifdef HAVE_SO_BROADCAST
+ optval = 1;
+ ret = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (void*)&optval, sizeof(int));
+ if (ret < 0)
+ {
+ ndbg("setsockopt SO_BROADCAST failed: %d\n", errno);
+ close(sockfd);
+ return ERROR;
+ }
+#endif
+
+ return sockfd;
+}
+
+static inline int discover_openlistener()
+{
+ struct sockaddr_in addr;
+ struct ifreq req;
+ int sockfd;
+ int ret;
+
+ /* Create a socket to listen for requests from DHCP clients */
+
+ sockfd = discover_socket();
+ if (sockfd < 0)
+ {
+ ndbg("socket failed: %d\n", errno);
+ return ERROR;
+ }
+
+ /* Get the IP address of the selected device */
+
+ strncpy(req.ifr_name, CONFIG_DISCOVER_INTERFACE, IFNAMSIZ);
+ ret = ioctl(sockfd, SIOCGIFADDR, (unsigned long)&req);
+ if (ret < 0)
+ {
+ ndbg("setsockopt SIOCGIFADDR failed: %d\n", errno);
+ close(sockfd);
+ return ERROR;
+ }
+ g_state.serverip = ((struct sockaddr_in*)&req.ifr_addr)->sin_addr.s_addr;
+ nvdbg("serverip: %08lx\n", ntohl(g_state.serverip));
+
+ /* Bind the socket to a local port. We have to bind to INADDRY_ANY to
+ * receive broadcast messages.
+ */
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(CONFIG_DISCOVER_PORT);
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
+ if (ret < 0)
+ {
+ ndbg("bind failed, port=%d addr=%08lx: %d\n",
+ addr.sin_port, (long)addr.sin_addr.s_addr, errno);
+ close(sockfd);
+ return ERROR;
+ }
+
+ return sockfd;
+}
+
+static inline int discover_openresponder(void)
+{
+ struct sockaddr_in addr;
+ int sockfd;
+ int ret;
+
+ /* Create a socket for responding to discovery message */
+
+ sockfd = discover_socket();
+ if (sockfd < 0)
+ {
+ ndbg("socket failed: %d\n", errno);
+ return ERROR;
+ }
+
+ /* Bind the socket to a local port.*/
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0;
+ addr.sin_addr.s_addr = g_state.serverip;
+
+ ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
+ if (ret < 0)
+ {
+ ndbg("bind failed, port=%d addr=%08lx: %d\n",
+ addr.sin_port, (long)addr.sin_addr.s_addr, errno);
+ close(sockfd);
+ return ERROR;
+ }
+
+ return sockfd;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: discover_start
+ *
+ * Description:
+ * Start the discover daemon.
+ *
+ * Return:
+ * The process ID (pid) of the new discover daemon is returned on
+ * success; A negated errno is returned if the daemon was not successfully
+ * started.
+ *
+ ****************************************************************************/
+
+int discover_start()
+{
+ pid_t pid;
+
+ /* Then start the new daemon */
+
+ pid = TASK_CREATE("Discover daemon", CONFIG_DISCOVER_PRIORITY,
+ CONFIG_DISCOVER_STACK_SIZE, discover_daemon, NULL);
+ if (pid < 0)
+ {
+ int errval = errno;
+ ndbg("Failed to start the discover daemon: %d\n", errval);
+ return -errval;
+ }
+
+ /* Return success */
+
+ return pid;
+}
diff --git a/nuttx/Documentation/README.html b/nuttx/Documentation/README.html
index 135c4f359..5bc3d1d96 100644
--- a/nuttx/Documentation/README.html
+++ b/nuttx/Documentation/README.html
@@ -254,6 +254,7 @@
|- modbus/
| `- <a href="http://nuttx.svn.sourceforge.net/viewvc/nuttx/trunk/apps/modbus/README.txt?view=log"><b><i>README.txt</i></b></a>
|- netutils/
+ | | |- <a href="http://nuttx.svn.sourceforge.net/viewvc/nuttx/trunk/apps/netutils/discover/README.txt?view=log">discover/README.txt</a>
| | |- <a href="http://nuttx.svn.sourceforge.net/viewvc/nuttx/trunk/apps/netutils/ftpc/README.txt?view=log">ftpc/README.txt</a>
| | |- <a href="http://nuttx.svn.sourceforge.net/viewvc/nuttx/trunk/apps/netutils/telnetd/README.txt?view=log">telnetd/README.txt</a>
| `- <a href="http://nuttx.svn.sourceforge.net/viewvc/nuttx/trunk/apps/netutils/README?view=log"><b><i>README</i></b></a>
diff --git a/nuttx/README.txt b/nuttx/README.txt
index b0aa5384c..ae33a6e9c 100644
--- a/nuttx/README.txt
+++ b/nuttx/README.txt
@@ -824,6 +824,8 @@ apps
|- modbus/
| `- README.txt
|- netutils/
+ | |- discover
+ | | `- README.txt
| |- ftpc
| | `- README.txt
| |- telnetd