forked from Archive/PX4-Autopilot
Add new psock layer; telnet session is now wrapped in a character device
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@4347 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
parent
a11ad68eed
commit
622ac27bfa
|
@ -164,3 +164,13 @@
|
|||
a USB serial console, then NSH needs to wait until the USB console is
|
||||
connected and available.
|
||||
* apps/examples/composite: Add a test of the USB composite device.
|
||||
* apps/examples/telnetd: Move the tiny uIP shell example from
|
||||
netutils/telnetd to examples/telnetd. Enhanced the telnetd daemon so that
|
||||
it supports telnetd via a TTY device driver: A new TTY device driver is
|
||||
created when each new telnet connection is created. The shell thread
|
||||
is started with stdin, stdout, and stderror mapped to the TTY device.
|
||||
* netutils/telnetd: The old uIP telnet demo is gone. In its place is a new
|
||||
telnet infrastructure. The new telnet daemon creates sessions that are
|
||||
"wrapped" as character devices and mapped to stdin, stdout, and stderr.
|
||||
Now the telnet session can be inherited by spawned tasks.
|
||||
* examples/telnetd: Add a test for the nte telnet daemon.
|
||||
|
|
|
@ -40,8 +40,8 @@
|
|||
SUBDIRS = adc buttons can composite dhcpd ftpc hello helloxx hidkbd igmp \
|
||||
lcdrw mm mount nettest nsh null nx nxffs nxflat nxhello nximage \
|
||||
nxlines nxtext ostest pashello pipe poll pwm rgmp romfs sendmail \
|
||||
serloop thttpd tiff touchscreen udp uip usbserial usbstorage usbterm \
|
||||
wget wlan
|
||||
serloop telnetd thttpd tiff touchscreen udp uip usbserial \
|
||||
usbstorage usbterm wget wlan
|
||||
|
||||
# Sub-directories that might need context setup. Directories may need
|
||||
# context setup for a variety of reasons, but the most common is because
|
||||
|
@ -56,7 +56,7 @@ SUBDIRS = adc buttons can composite dhcpd ftpc hello helloxx hidkbd igmp \
|
|||
CNTXTDIRS = pwm
|
||||
|
||||
ifeq ($(CONFIG_NSH_BUILTIN_APPS),y)
|
||||
CNTXTDIRS += adc can composite dhcpd nettest
|
||||
CNTXTDIRS += adc can composite dhcpd nettest telnetd
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_EXAMPLES_HELLOXX_BUILTIN),y)
|
||||
|
|
|
@ -894,6 +894,28 @@ examples/serloop
|
|||
Use C buffered I/O (getchar/putchar) vs. raw console I/O
|
||||
(read/read).
|
||||
|
||||
examples/telnetd
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
This directory contains a functional port of the tiny uIP shell. In
|
||||
the NuttX environment, the NuttShell (at apps/nshlib) supercedes this
|
||||
tiny shell and also supports telnetd.
|
||||
|
||||
CONFIG_EXAMPLES_TELNETD_DAEMONPRIO - Priority of the Telnet daemon.
|
||||
Default: SCHED_PRIORITY_DEFAULT
|
||||
CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE - Stack size allocated for the
|
||||
Telnet daemon. Default: 2048
|
||||
CONFIG_EXAMPLES_TELNETD_CLIENTPRIO- Priority of the Telnet client.
|
||||
Default: SCHED_PRIORITY_DEFAULT
|
||||
CONFIG_EXAMPLES_TELNETD_CLIENTSTACKSIZE - Stack size allocated for the
|
||||
Telnet client. Default: 2048
|
||||
CONFIG_EXAMPLE_TELNETD_NOMAC - If the hardware has no MAC address of its
|
||||
own, define this =y to provide a bogus address for testing.
|
||||
CONFIG_EXAMPLE_TELNETD_IPADDR - The target IP address. Default 10.0.0.2
|
||||
CONFIG_EXAMPLE_TELNETD_DRIPADDR - The default router address. Default
|
||||
10.0.0.1
|
||||
CONFIG_EXAMPLE_TELNETD_NETMASK - The network mask. Default: 255.255.255.0
|
||||
|
||||
examples/thttpd
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
############################################################################
|
||||
# apps/examples/telnetd/Makefile
|
||||
#
|
||||
# Copyright (C) 2012 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)/.config
|
||||
-include $(TOPDIR)/Make.defs
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
# Hello, World! Example
|
||||
|
||||
ASRCS =
|
||||
CSRCS = shell.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 .
|
||||
|
||||
# Buttons built-in application info
|
||||
|
||||
APPNAME = buttons
|
||||
PRIORITY = SCHED_PRIORITY_DEFAULT
|
||||
STACKSIZE = 2048
|
||||
|
||||
# Common build
|
||||
|
||||
VPATH =
|
||||
|
||||
all: .built
|
||||
.PHONY: context 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
|
|
@ -0,0 +1,8 @@
|
|||
README.txt
|
||||
^^^^^^^^^^
|
||||
|
||||
This directory contains a functional port of the tiny uIP shell. In the
|
||||
NuttX environment, the NuttShell (at apps/nshlib) supercedes this tiny
|
||||
shell and also supports telnetd.
|
||||
|
||||
This example is retained here for reference purposes only.
|
|
@ -0,0 +1,251 @@
|
|||
/****************************************************************************
|
||||
* examples/telnetd/shell.c
|
||||
*
|
||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* This is a leverage of similar logic from uIP:
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
* 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. 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.
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <apps/netutils/telnetd.h>
|
||||
#include <apps/netutils/uiplib.h>
|
||||
#include "shell.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct ptentry_s
|
||||
{
|
||||
FAR const char *commandstr;
|
||||
void (*pfunc)(int argc, char **argv);
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static void shell_help(int argc, char **argv);
|
||||
static void shell_quit(int argc, char **argv);
|
||||
static void shell_unknown(int argc, char **argv);
|
||||
static void shell_parse(FAR char *line, int len);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct ptentry_s g_parsetab[] =
|
||||
{
|
||||
{"help", shell_help},
|
||||
{"exit", shell_quit},
|
||||
{"?", shell_help},
|
||||
{NULL, shell_unknown}
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: shell_help
|
||||
****************************************************************************/
|
||||
|
||||
static void shell_help(int argc, char **argv)
|
||||
{
|
||||
printf("Available commands:");
|
||||
printf(" help, ? - show help");
|
||||
printf(" exit - exit shell");
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: shell_help
|
||||
****************************************************************************/
|
||||
|
||||
static void shell_unknown(int argc, char **argv)
|
||||
{
|
||||
if (argv[0])
|
||||
{
|
||||
printf("Unknown command: %s\n", argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: shell_quit
|
||||
****************************************************************************/
|
||||
|
||||
static void shell_quit(int argc, char **argv)
|
||||
{
|
||||
printf("Bye!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: shell_parse
|
||||
****************************************************************************/
|
||||
|
||||
static void shell_parse(FAR char *line, int len)
|
||||
{
|
||||
struct ptentry_s *entry;
|
||||
FAR char *cmd;
|
||||
FAR char *saveptr;
|
||||
|
||||
/* Get the command from the beginning the line */
|
||||
|
||||
cmd = strtok_r(line, " \t\n\r\f\v", &saveptr);
|
||||
if (cmd)
|
||||
{
|
||||
/* Now find the matching command in the command table */
|
||||
|
||||
for (entry = g_parsetab; entry->commandstr != NULL; entry++)
|
||||
{
|
||||
if (strncmp(entry->commandstr, cmd, strlen(entry->commandstr)) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
entry->pfunc(1, &cmd);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: shell_session
|
||||
****************************************************************************/
|
||||
|
||||
int shell_session(int argc, char *argv[])
|
||||
{
|
||||
char line[128];
|
||||
|
||||
printf("uIP command shell -- NuttX style");
|
||||
printf("Type '?' and return for help");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
printf(SHELL_PROMPT);
|
||||
|
||||
if (fgets(line, 128, stdin) == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
shell_parse(line, 128);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: shell_netinit
|
||||
****************************************************************************/
|
||||
|
||||
static void shell_netinit(void)
|
||||
{
|
||||
struct in_addr addr;
|
||||
#ifdef CONFIG_EXAMPLE_TELNETD_NOMAC
|
||||
uint8_t mac[IFHWADDRLEN];
|
||||
#endif
|
||||
|
||||
/* Many embedded network interfaces must have a software assigned MAC */
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_TELNETD_NOMAC
|
||||
mac[0] = 0x00;
|
||||
mac[1] = 0xe0;
|
||||
mac[2] = 0xb0;
|
||||
mac[3] = 0x0b;
|
||||
mac[4] = 0xba;
|
||||
mac[5] = 0xbe;
|
||||
uip_setmacaddr("eth0", mac);
|
||||
#endif
|
||||
|
||||
/* Set up our host address */
|
||||
|
||||
addr.s_addr = HTONL(CONFIG_EXAMPLE_TELNETD_IPADDR);
|
||||
uip_sethostaddr("eth0", &addr);
|
||||
|
||||
/* Set up the default router address */
|
||||
|
||||
addr.s_addr = HTONL(CONFIG_EXAMPLE_TELNETD_DRIPADDR);
|
||||
uip_setdraddr("eth0", &addr);
|
||||
|
||||
/* Setup the subnet mask */
|
||||
|
||||
addr.s_addr = HTONL(CONFIG_EXAMPLE_TELNETD_NETMASK);
|
||||
uip_setnetmask("eth0", &addr);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int MAIN_NAME(int argc, char *argv[])
|
||||
{
|
||||
struct telnetd_config_s config;
|
||||
int ret;
|
||||
|
||||
/* Configure the network */
|
||||
|
||||
printf(MAIN_STRING "Initializing the network\n");
|
||||
shell_netinit();
|
||||
|
||||
/* Configure the telnet daemon */
|
||||
|
||||
config.d_port = HTONS(23);
|
||||
config.d_priority = CONFIG_EXAMPLES_TELNETD_DAEMONPRIO;
|
||||
config.d_stacksize = CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE;
|
||||
config.t_priority = CONFIG_EXAMPLES_TELNETD_CLIENTPRIO;
|
||||
config.t_stacksize = CONFIG_EXAMPLES_TELNETD_CLIENTSTACKSIZE;
|
||||
config.t_entry = shell_session;
|
||||
|
||||
/* Start the telnet daemon */
|
||||
|
||||
printf(MAIN_STRING "Starting the Telnet daemon\n");
|
||||
ret = telnetd_start(&config);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("Failed to tart the Telnet daemon\n");
|
||||
}
|
||||
|
||||
printf(MAIN_STRING "Exiting\n");
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/****************************************************************************
|
||||
* apps/examples/telnetd/shell.h
|
||||
* Interface for the Contiki shell.
|
||||
*
|
||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: 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. 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 __APPS_EXAMPLES_TELNETD_SHELL_H
|
||||
#define __APPS_EXAMPLES_TELNETD_SHELL_H
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
/* CONFIG_EXAMPLES_TELNETD_DAEMONPRIO - Priority of the Telnet daemon.
|
||||
* Default: SCHED_PRIORITY_DEFAULT
|
||||
* CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE - Stack size allocated for the
|
||||
* Telnet daemon. Default: 2048
|
||||
* CONFIG_EXAMPLES_TELNETD_CLIENTPRIO- Priority of the Telnet client.
|
||||
* Default: SCHED_PRIORITY_DEFAULT
|
||||
* CONFIG_EXAMPLES_TELNETD_CLIENTSTACKSIZE - Stack size allocated for the
|
||||
* Telnet client. Default: 2048
|
||||
* CONFIG_EXAMPLE_TELNETD_NOMAC - If the hardware has no MAC address of its
|
||||
* own, define this =y to provide a bogus address for testing.
|
||||
* CONFIG_EXAMPLE_TELNETD_IPADDR - The target IP address. Default 10.0.0.2
|
||||
* CONFIG_EXAMPLE_TELNETD_DRIPADDR - The default router address. Default
|
||||
* 10.0.0.1
|
||||
* CONFIG_EXAMPLE_TELNETD_NETMASK - The network mask. Default: 255.255.255.0
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_TELNETD_DAEMONPRIO
|
||||
# define CONFIG_EXAMPLES_TELNETD_DAEMONPRIO SCHED_PRIORITY_DEFAULT
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE
|
||||
# define CONFIG_EXAMPLES_TELNETD_DAEMONSTACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_TELNETD_CLIENTPRIO
|
||||
# define CONFIG_EXAMPLES_TELNETD_CLIENTPRIO SCHED_PRIORITY_DEFAULT
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_TELNETD_CLIENTSTACKSIZE
|
||||
# define CONFIG_EXAMPLES_TELNETD_CLIENTSTACKSIZE 2048
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_EXAMPLE_TELNETD_IPADDR
|
||||
# define CONFIG_EXAMPLE_TELNETD_IPADDR 0x0a000002
|
||||
#endif
|
||||
#ifndef CONFIG_EXAMPLE_TELNETD_DRIPADDR
|
||||
# define CONFIG_EXAMPLE_TELNETD_DRIPADDR 0x0a000002
|
||||
#endif
|
||||
#ifndef CONFIG_EXAMPLE_TELNETD_NETMASK
|
||||
# define CONFIG_EXAMPLE_TELNETD_NETMASK 0xffffff00
|
||||
#endif
|
||||
|
||||
/* Is this being built as an NSH built-in application? */
|
||||
|
||||
#ifdef CONFIG_NSH_BUILTIN_APPS
|
||||
# define MAIN_NAME shell_main
|
||||
# define MAIN_STRING "shell_main: "
|
||||
#else
|
||||
# define MAIN_NAME user_start
|
||||
# define MAIN_STRING "user_start: "
|
||||
#endif
|
||||
|
||||
|
||||
/* Other definitions ********************************************************/
|
||||
|
||||
#define SHELL_PROMPT "uIP 1.0> "
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#endif /* __APPS_EXAMPLES_TELNETD_SHELL_H */
|
|
@ -1,14 +1,8 @@
|
|||
/****************************************************************************
|
||||
* include/apps/netutils/telnetd.h
|
||||
*
|
||||
* Copyright (C) 2007, 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* This is a leverage of similar logic from uIP:
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
* Copyright (c) 2003, Adam Dunkels.
|
||||
* All rights reserved.
|
||||
* Copyright (C) 2007, 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -17,35 +11,83 @@
|
|||
* 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
|
||||
* 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 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 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_NETUTILS_TELNETD_H
|
||||
#define __APPS_NETUTILS_TELNETD_H
|
||||
#ifndef __APPS_INCLUDE_NETUTILS_TELNETD_H
|
||||
#define __APPS_INCLUDE_NETUTILS_TELNETD_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* CONFIG_TELNETD_CONSOLE - Use the first telnet session as the default
|
||||
* console.
|
||||
* CONFIG_TELNETD_NPOLLWAITERS - If the poll method is enabled, then this
|
||||
* value will defined the maximum number of threads that can be waiting
|
||||
* for events. Default: 1
|
||||
* CONFIG_TELNETD_DUMPBUFFER - dumping of all input/output buffers.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_TELNETD_NPOLLWAITERS
|
||||
# define CONFIG_TELNETD_NPOLLWAITERS 1
|
||||
#endif
|
||||
|
||||
/* Configurable settings */
|
||||
|
||||
#ifndef CONFIG_TELNETD_IOBUFFER_SIZE
|
||||
# define CONFIG_TELNETD_IOBUFFER_SIZE 512
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* An instance of the struct telnetd_config_s structure must be passed to
|
||||
* telnetd_start in order to configure the new telnet daemon.
|
||||
*/
|
||||
|
||||
struct telnetd_config_s
|
||||
{
|
||||
/* These fields describe the telnet daemon */
|
||||
|
||||
int d_port; /* The port to listen on (in network byte order) */
|
||||
int d_priority; /* The execution priority of the telnet daemon task */
|
||||
int d_stacksize; /* The stack size needed by the telnet daemon task */
|
||||
|
||||
/* These fields describe the priority of each thread created by the telnet
|
||||
* daemon.
|
||||
*/
|
||||
|
||||
int t_priority; /* The execution priority of the spawned task, */
|
||||
int t_stacksize; /* The stack size needed by the spawned task */
|
||||
main_t t_entry; /* The entrypoint of the task to spawn when a new
|
||||
* connection is accepted. */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
|
@ -58,13 +100,29 @@ extern "C" {
|
|||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/* Start the telnet server -- does not return unless an error occurs */
|
||||
/****************************************************************************
|
||||
* Name: telnetd_start
|
||||
*
|
||||
* Description:
|
||||
* Start the telnet daemon.
|
||||
*
|
||||
* Parameters:
|
||||
* config A pointer to a configuration structure that characterizes the
|
||||
* telnet daemon. This configuration structure may be defined
|
||||
* on the caller's stack because it is not retained by the
|
||||
* daemon.
|
||||
*
|
||||
* Return:
|
||||
* The process ID (pid) of the new telnet daemon is returned on
|
||||
* success; A negated errno is returned if the daemon was not successfully
|
||||
* started.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
EXTERN void telnetd_init(void);
|
||||
EXTERN int telnetd_start(FAR struct telnetd_config_s *config);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __APPS_NETUTILS_TELNETD_H */
|
||||
#endif /* __APPS_INCLUDE_NETUTILS_TELNETD_H */
|
||||
|
|
|
@ -9,7 +9,6 @@ include:
|
|||
dhcpc - Dynamic Host Configuration Protocol (DHCP) client
|
||||
resolv - uIP DNS resolver
|
||||
smtp - Simple Mail Transfer Protocol (SMTP) client
|
||||
telnetd - TELNET server
|
||||
webclient - HTTP web client
|
||||
webserver - HTTP web server
|
||||
|
||||
|
@ -21,6 +20,12 @@ highly influenced by uIP) include:
|
|||
|
||||
dhcpd - Dynamic Host Configuration Protocol (DHCP) server
|
||||
tftpc - TFTP client
|
||||
telnetd - TELNET server. This is the Telnet logic adapted from
|
||||
uIP and generalized for use as the front end to any
|
||||
shell. The telnet daemon creates sessions that are
|
||||
"wrapped" as character devices and mapped to stdin,
|
||||
stdout, and stderr. Now the telnet session can be
|
||||
inherited by spawned tasks.
|
||||
ftpc - FTP client
|
||||
thttpd - This is a port of Jef Poskanzer's THTTPD HTPPD server.
|
||||
See http://acme.com/software/thttpd/.
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
############################################################################
|
||||
# apps/netutils/telnetd/Makefile
|
||||
#
|
||||
# Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
# Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
|
@ -43,7 +43,7 @@ ASRCS =
|
|||
CSRCS =
|
||||
|
||||
ifeq ($(CONFIG_NET_TCP),y)
|
||||
CSRCS += telnetd.c shell.c
|
||||
CSRCS += telnetd_daemon.c telnetd_driver.c
|
||||
endif
|
||||
|
||||
AOBJS = $(ASRCS:.S=$(OBJEXT))
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
This directory is here for historical reasons. Nothing contained in this
|
||||
directory is currently used by NuttX. This directly contains a functional
|
||||
port of the tiny uIP shell. In the NuttX environment, the NuttShell (at
|
||||
apps/nshlib) supercedes this tiny shell and also supports telnetd.
|
||||
|
||||
This example is retained here for reference purposes only.
|
||||
README.txt
|
||||
^^^^^^^^^^
|
||||
|
||||
This directly contains a generic Telnet daemon.
|
||||
|
|
|
@ -1,139 +0,0 @@
|
|||
/****************************************************************************
|
||||
* netutils/telnetd/telnetd.c
|
||||
*
|
||||
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* This is a leverage of similar logic from uIP:
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
* 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. 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.
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "shell.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define SHELL_PROMPT "uIP 1.0> "
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct ptentry_s
|
||||
{
|
||||
char *commandstr;
|
||||
void (* pfunc)(void *handle, char *str);
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static void parse(void *handle, register char *str, struct ptentry_s *t);
|
||||
static void help(void *handle, char *str);
|
||||
static void unknown(void *handle, char *str);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct ptentry_s g_parsetab[] =
|
||||
{
|
||||
{"stats", help},
|
||||
{"conn", help},
|
||||
{"help", help},
|
||||
{"exit", shell_quit},
|
||||
{"?", help},
|
||||
{NULL, unknown}
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static void parse(void *handle, char *str, struct ptentry_s *t)
|
||||
{
|
||||
struct ptentry_s *p;
|
||||
|
||||
for (p = t; p->commandstr != NULL; ++p)
|
||||
{
|
||||
if (strncmp(p->commandstr, str, strlen(p->commandstr)) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p->pfunc(handle, str);
|
||||
}
|
||||
|
||||
static void help(void *handle, char *str)
|
||||
{
|
||||
shell_output(handle, "Available commands:");
|
||||
shell_output(handle, "stats - show network statistics");
|
||||
shell_output(handle, "conn - show TCP connections");
|
||||
shell_output(handle, "help, ? - show help");
|
||||
shell_output(handle, "exit - exit shell");
|
||||
}
|
||||
|
||||
static void unknown(void *handle, char *str)
|
||||
{
|
||||
if (strlen(str) > 0)
|
||||
{
|
||||
shell_output(handle, "Unknown command: ", str);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void shell_init(void *handle)
|
||||
{
|
||||
}
|
||||
|
||||
void shell_start(void *handle)
|
||||
{
|
||||
shell_output(handle, "uIP command shell");
|
||||
shell_output(handle, "Type '?' and return for help");
|
||||
shell_prompt(handle, SHELL_PROMPT);
|
||||
}
|
||||
|
||||
void shell_input(void *handle, char *cmd)
|
||||
{
|
||||
parse(handle, cmd, g_parsetab);
|
||||
shell_prompt(handle, SHELL_PROMPT);
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
/****************************************************************************
|
||||
* netutils/telnetd/shell.h
|
||||
* Interface for the Contiki shell.
|
||||
*
|
||||
* Copyright (C) 2007 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Based on uIP which also has a BSD style license:
|
||||
*
|
||||
* Author: Adam Dunkels <adam@dunkels.com>
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#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 *handle);
|
||||
|
||||
/* Start the shell back-end.
|
||||
*
|
||||
* Called by the front-end when a new shell is started.
|
||||
*/
|
||||
|
||||
void shell_start(void *handle);
|
||||
|
||||
/* 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.
|
||||
*
|
||||
* command The command to be processed.
|
||||
*/
|
||||
|
||||
void shell_input(void *handle, char *command);
|
||||
|
||||
/* Quit the shell. */
|
||||
|
||||
void shell_quit(void *handle, 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.
|
||||
*/
|
||||
|
||||
void shell_output(void *handle, const char *fmt, ...);
|
||||
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
void shell_prompt(void *handle, char *prompt);
|
||||
|
||||
#endif /* __SHELL_H__ */
|
|
@ -1,459 +0,0 @@
|
|||
/****************************************************************************
|
||||
* netutils/telnetd/telnetd.c
|
||||
*
|
||||
* Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* This is a leverage of similar logic from uIP:
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
* 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. 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.
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <apps/netutils/telnetd.h>
|
||||
#include <apps/netutils/uiplib.h>
|
||||
|
||||
#include "shell.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#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
|
||||
|
||||
#define TELNET_IAC 255
|
||||
#define TELNET_WILL 251
|
||||
#define TELNET_WONT 252
|
||||
#define TELNET_DO 253
|
||||
#define TELNET_DONT 254
|
||||
|
||||
/* Configurable settings */
|
||||
|
||||
#ifndef CONFIG_NETUTILS_IOBUFFER_SIZE
|
||||
# define CONFIG_NETUTILS_IOBUFFER_SIZE 512
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_NETUTILS_CMD_SIZE
|
||||
# define CONFIG_NETUTILS_CMD_SIZE 40
|
||||
#endif
|
||||
|
||||
/* As threads are created to handle each request, a stack must be allocated
|
||||
* for the thread. Use a default if the user provided no stacksize.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_NETUTILS_TELNETDSTACKSIZE
|
||||
# define CONFIG_NETUTILS_TELNETDSTACKSIZE 4096
|
||||
#endif
|
||||
|
||||
/* Enabled dumping of all input/output buffers */
|
||||
|
||||
#undef CONFIG_NETUTILS_TELNETD_DUMPBUFFER
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct telnetd_s
|
||||
{
|
||||
int tn_sockfd;
|
||||
char tn_iobuffer[CONFIG_NETUTILS_IOBUFFER_SIZE];
|
||||
char tn_cmd[CONFIG_NETUTILS_CMD_SIZE];
|
||||
uint8_t tn_bufndx;
|
||||
uint8_t tn_state;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_dumpbuffer
|
||||
*
|
||||
* Description:
|
||||
* Dump a buffer of data (debug only)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NETUTILS_TELNETD_DUMPBUFFER
|
||||
static inline void telnetd_dumpbuffer(FAR const char *msg, FAR const char *buffer, unsigned int nbytes)
|
||||
{
|
||||
/* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_NET have to be
|
||||
* defined or the following does nothing.
|
||||
*/
|
||||
|
||||
nvdbgdumpbuffer(msg, (FAR const uint8_t*)buffer, nbytes);
|
||||
}
|
||||
#else
|
||||
# define telnetd_dumpbuffer(msg,buffer,nbytes)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_putchar
|
||||
*
|
||||
* Description:
|
||||
* Add another parsed character to the TELNET command string
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void telnetd_putchar(struct telnetd_s *pstate, uint8_t ch)
|
||||
{
|
||||
/* Ignore carriage returns */
|
||||
|
||||
if (ch == ISO_cr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add all other characters to the cmd buffer */
|
||||
|
||||
pstate->tn_cmd[pstate->tn_bufndx] = ch;
|
||||
|
||||
/* If a newline was added or if the buffer is full, then process it now */
|
||||
|
||||
if (ch == ISO_nl || pstate->tn_bufndx == (CONFIG_NETUTILS_CMD_SIZE - 1))
|
||||
{
|
||||
if (pstate->tn_bufndx > 0)
|
||||
{
|
||||
pstate->tn_cmd[pstate->tn_bufndx] = '\0';
|
||||
}
|
||||
|
||||
telnetd_dumpbuffer("TELNET CMD", pstate->tn_cmd, strlen(pstate->tn_cmd));
|
||||
shell_input(pstate, pstate->tn_cmd);
|
||||
pstate->tn_bufndx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pstate->tn_bufndx++;
|
||||
vdbg("Add '%c', bufndx=%d\n", ch, pstate->tn_bufndx);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_sendopt
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void telnetd_sendopt(struct telnetd_s *pstate, uint8_t option, uint8_t value)
|
||||
{
|
||||
uint8_t optbuf[4];
|
||||
optbuf[0] = TELNET_IAC;
|
||||
optbuf[1] = option;
|
||||
optbuf[2] = value;
|
||||
optbuf[3] = 0;
|
||||
|
||||
telnetd_dumpbuffer("Send optbuf", optbuf, 4);
|
||||
if (send(pstate->tn_sockfd, optbuf, 4, 0) < 0)
|
||||
{
|
||||
dbg("[%d] Failed to send TELNET_IAC\n", pstate->tn_sockfd);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_receive
|
||||
*
|
||||
* Description:
|
||||
* Process a received TELENET buffer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int telnetd_receive(struct telnetd_s *pstate, size_t len)
|
||||
{
|
||||
char *ptr = pstate->tn_iobuffer;
|
||||
uint8_t ch;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
ch = *ptr++;
|
||||
len--;
|
||||
|
||||
vdbg("ch=%02x state=%d\n", ch, pstate->tn_state);
|
||||
switch (pstate->tn_state)
|
||||
{
|
||||
case STATE_IAC:
|
||||
if (ch == TELNET_IAC)
|
||||
{
|
||||
telnetd_putchar(pstate, ch);
|
||||
pstate->tn_state = STATE_NORMAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case TELNET_WILL:
|
||||
pstate->tn_state = STATE_WILL;
|
||||
break;
|
||||
|
||||
case TELNET_WONT:
|
||||
pstate->tn_state = STATE_WONT;
|
||||
break;
|
||||
|
||||
case TELNET_DO:
|
||||
pstate->tn_state = STATE_DO;
|
||||
break;
|
||||
|
||||
case TELNET_DONT:
|
||||
pstate->tn_state = STATE_DONT;
|
||||
break;
|
||||
|
||||
default:
|
||||
pstate->tn_state = STATE_NORMAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_WILL:
|
||||
/* Reply with a DONT */
|
||||
|
||||
telnetd_sendopt(pstate, TELNET_DONT, ch);
|
||||
pstate->tn_state = STATE_NORMAL;
|
||||
break;
|
||||
|
||||
case STATE_WONT:
|
||||
/* Reply with a DONT */
|
||||
|
||||
telnetd_sendopt(pstate, TELNET_DONT, ch);
|
||||
pstate->tn_state = STATE_NORMAL;
|
||||
break;
|
||||
|
||||
case STATE_DO:
|
||||
/* Reply with a WONT */
|
||||
|
||||
telnetd_sendopt(pstate, TELNET_WONT, ch);
|
||||
pstate->tn_state = STATE_NORMAL;
|
||||
break;
|
||||
|
||||
case STATE_DONT:
|
||||
/* Reply with a WONT */
|
||||
|
||||
telnetd_sendopt(pstate, TELNET_WONT, ch);
|
||||
pstate->tn_state = STATE_NORMAL;
|
||||
break;
|
||||
|
||||
case STATE_NORMAL:
|
||||
if (ch == TELNET_IAC)
|
||||
{
|
||||
pstate->tn_state = STATE_IAC;
|
||||
}
|
||||
else
|
||||
{
|
||||
telnetd_putchar(pstate, ch);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_handler
|
||||
*
|
||||
* Description:
|
||||
* Each time a new connection to port 23 is made, a new thread is created
|
||||
* that begins at this entry point. There should be exactly one argument
|
||||
* and it should be the socket descriptor (+1).
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void *telnetd_handler(void *arg)
|
||||
{
|
||||
struct telnetd_s *pstate = (struct telnetd_s *)malloc(sizeof(struct telnetd_s));
|
||||
int sockfd = (int)arg;
|
||||
int ret = ERROR;
|
||||
|
||||
dbg("[%d] Started\n", sockfd);
|
||||
|
||||
/* Verify that the state structure was successfully allocated */
|
||||
|
||||
if (pstate)
|
||||
{
|
||||
/* Initialize the thread state structure */
|
||||
|
||||
memset(pstate, 0, sizeof(struct telnetd_s));
|
||||
pstate->tn_sockfd = sockfd;
|
||||
pstate->tn_state = STATE_NORMAL;
|
||||
|
||||
/* Start up the shell */
|
||||
|
||||
shell_init(pstate);
|
||||
shell_start(pstate);
|
||||
|
||||
/* Loop processing each TELNET command */
|
||||
do
|
||||
{
|
||||
/* Read a buffer of data from the TELNET client */
|
||||
|
||||
ret = recv(pstate->tn_sockfd, pstate->tn_iobuffer, CONFIG_NETUTILS_IOBUFFER_SIZE, 0);
|
||||
if (ret > 0)
|
||||
{
|
||||
|
||||
/* Process the received TELNET data */
|
||||
|
||||
telnetd_dumpbuffer("Received buffer", pstate->tn_iobuffer, ret);
|
||||
ret = telnetd_receive(pstate, ret);
|
||||
}
|
||||
}
|
||||
while (ret >= 0 && pstate->tn_state != STATE_CLOSE);
|
||||
dbg("[%d] ret=%d tn_state=%d\n", sockfd, ret, pstate->tn_state);
|
||||
|
||||
/* End of command processing -- Clean up and exit */
|
||||
|
||||
free(pstate);
|
||||
}
|
||||
|
||||
/* Exit the task */
|
||||
|
||||
dbg("[%d] Exitting\n", sockfd);
|
||||
close(sockfd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_init
|
||||
*
|
||||
* Description:
|
||||
* This is the main processing thread for telnetd. It never returns
|
||||
* unless an error occurs
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void telnetd_init(void)
|
||||
{
|
||||
/* Execute telnetd_handler on each connection to port 23 */
|
||||
|
||||
uip_server(HTONS(23), telnetd_handler, CONFIG_NETUTILS_TELNETDSTACKSIZE);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: shell_prompt
|
||||
*
|
||||
* Description:
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void shell_prompt(void *handle, char *str)
|
||||
{
|
||||
struct telnetd_s *pstate = (struct telnetd_s *)handle;
|
||||
int len = strlen(str);
|
||||
|
||||
strncpy(pstate->tn_iobuffer, str, len);
|
||||
telnetd_dumpbuffer("Shell prompt", pstate->tn_iobuffer, len);
|
||||
if (send(pstate->tn_sockfd, pstate->tn_iobuffer, len, 0) < 0)
|
||||
{
|
||||
dbg("[%d] Failed to send prompt\n", pstate->tn_sockfd);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: shell_output
|
||||
*
|
||||
* Description:
|
||||
* 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void shell_output(void *handle, const char *fmt, ...)
|
||||
{
|
||||
struct telnetd_s *pstate = (struct telnetd_s *)handle;
|
||||
unsigned len;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(pstate->tn_iobuffer, CONFIG_NETUTILS_IOBUFFER_SIZE, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
len = strlen(pstate->tn_iobuffer);
|
||||
if (len < CONFIG_NETUTILS_IOBUFFER_SIZE - 2)
|
||||
{
|
||||
pstate->tn_iobuffer[len] = ISO_cr;
|
||||
pstate->tn_iobuffer[len+1] = ISO_nl;
|
||||
pstate->tn_iobuffer[len+2] = '\0';
|
||||
}
|
||||
|
||||
telnetd_dumpbuffer("Shell output", pstate->tn_iobuffer, len+2);
|
||||
if (send(pstate->tn_sockfd, pstate->tn_iobuffer, len+2, 0) < 0)
|
||||
{
|
||||
dbg("[%d] Failed to send response\n", pstate->tn_sockfd);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: shell_quit
|
||||
*
|
||||
* Description:
|
||||
* Quit the shell
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void shell_quit(void *handle, char *str)
|
||||
{
|
||||
struct telnetd_s *pstate = (struct telnetd_s *)handle;
|
||||
pstate->tn_state = STATE_CLOSE;
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/****************************************************************************
|
||||
* apps/netutils/telnetd/telnetd.c
|
||||
*
|
||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: 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 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __APPS_NETUTILS_TELNETD_TELNETD_H
|
||||
#define __APPS_NETUTILS_TELNETD_TELNETD_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure represents the overall state of one telnet daemon instance
|
||||
* (Yes, multiple telnet daemons are supported).
|
||||
*/
|
||||
|
||||
struct telnetd_s
|
||||
{
|
||||
int port; /* The port to listen on (in network byte order) */
|
||||
int priority; /* The execution priority of the spawned task, */
|
||||
int stacksize; /* The stack size needed by the spawned task */
|
||||
main_t entry; /* The entrypoint of the task to spawn when a new
|
||||
* connection is accepted. */
|
||||
};
|
||||
|
||||
/* This structure is used to passed information to telnet daemon when it
|
||||
* started. It contains global information visable to all telnet daemons.
|
||||
*/
|
||||
|
||||
struct telnetd_common_s
|
||||
{
|
||||
uint8_t ndaemons; /* The total number of daemons running */
|
||||
sem_t startsem; /* Enforces one-at-a-time startup */
|
||||
sem_t exclsem; /* Enforces exclusive access to 'minor' */
|
||||
FAR struct telnetd_s *daemon; /* Describes the new daemon */
|
||||
int minor; /* The next minor number to use */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure is used to passed information to telnet daemon when it
|
||||
* started. It contains global information visable to all telnet daemons.
|
||||
*/
|
||||
|
||||
extern struct telnetd_common_s g_telnetdcommon;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_driver
|
||||
*
|
||||
* Description:
|
||||
* Create a character driver to "wrap" the telnet session. This function
|
||||
* will select and return a unique path for the new telnet device.
|
||||
*
|
||||
* Parameters:
|
||||
* sd - The socket descriptor that represents the new telnet connection.
|
||||
* daemon - A pointer to the structure representing the overall state of
|
||||
* this instance of the telnet daemon.
|
||||
*
|
||||
* Return:
|
||||
* An allocated string represent the full path to the created driver. The
|
||||
* receiver of the string must de-allocate this memory when it is no longer
|
||||
* needed. NULL is returned on a failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR char *telnetd_driver(int sd, FAR struct telnetd_s *daemon);
|
||||
|
||||
#endif /* __APPS_NETUTILS_TELNETD_TELNETD_H */
|
||||
|
|
@ -0,0 +1,349 @@
|
|||
/****************************************************************************
|
||||
* netutils/telnetd/telnetd_daemon.c
|
||||
*
|
||||
* Copyright (C) 2012 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <semaphore.h>
|
||||
#include <sched.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <apps/netutils/telnetd.h>
|
||||
#include <apps/netutils/uiplib.h>
|
||||
|
||||
#include "telnetd.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure is used to passed information to telnet daemon when it
|
||||
* started.
|
||||
*/
|
||||
|
||||
struct telnetd_common_s g_telnetdcommon;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_daemon
|
||||
*
|
||||
* Description:
|
||||
* This function is the Telnet daemon. It does not return (unless an
|
||||
* error occurs).
|
||||
*
|
||||
* Parameters:
|
||||
* Standard task start up arguments.
|
||||
*
|
||||
* Return:
|
||||
* Does not return unless an error occurs.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int telnetd_daemon(int argc, char *argv[])
|
||||
{
|
||||
FAR struct telnetd_s *daemon;
|
||||
struct sockaddr_in myaddr;
|
||||
#ifdef CONFIG_NET_HAVE_SOLINGER
|
||||
struct linger ling;
|
||||
#endif
|
||||
socklen_t addrlen;
|
||||
FAR char *devpath;
|
||||
pid_t pid;
|
||||
int listensd;
|
||||
int acceptsd;
|
||||
int drvrfd;
|
||||
#ifdef CONFIG_NET_HAVE_REUSEADDR
|
||||
int optval;
|
||||
#endif
|
||||
|
||||
/* Get daemon startup info */
|
||||
|
||||
daemon = g_telnetdcommon.daemon;
|
||||
g_telnetdcommon.daemon = NULL;
|
||||
sem_post(&g_telnetdcommon.startsem);
|
||||
DEBUGASSERT(daemon != NULL);
|
||||
|
||||
/* Create a new TCP socket to use to listen for connections */
|
||||
|
||||
listensd = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (listensd < 0)
|
||||
{
|
||||
int errval = errno;
|
||||
ndbg("socket failure: %d\n", errval);
|
||||
return -errval;
|
||||
}
|
||||
|
||||
/* Set socket to reuse address */
|
||||
|
||||
#ifdef CONFIG_NET_HAVE_REUSEADDR
|
||||
optval = 1;
|
||||
if (setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0)
|
||||
{
|
||||
ndbg("setsockopt SO_REUSEADDR failure: %d\n", errno);
|
||||
goto errout_with_socket;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Bind the socket to a local address */
|
||||
|
||||
myaddr.sin_family = AF_INET;
|
||||
myaddr.sin_port = daemon->port;
|
||||
myaddr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if (bind(listensd, (struct sockaddr*)&myaddr, sizeof(struct sockaddr_in)) < 0)
|
||||
{
|
||||
ndbg("bind failure: %d\n", errno);
|
||||
goto errout_with_socket;
|
||||
}
|
||||
|
||||
/* Listen for connections on the bound TCP socket */
|
||||
|
||||
if (listen(listensd, 5) < 0)
|
||||
{
|
||||
ndbg("listen failure %d\n", errno);
|
||||
goto errout_with_socket;
|
||||
}
|
||||
|
||||
/* Now go silent */
|
||||
|
||||
#ifndef CONFIG_DEBUG
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
#endif
|
||||
|
||||
/* Begin accepting connections */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
nvdbg("Accepting connections on port %d\n", ntohs(daemon->port));
|
||||
|
||||
addrlen = sizeof(struct sockaddr_in);
|
||||
acceptsd = accept(listensd, (struct sockaddr*)&myaddr, &addrlen);
|
||||
if (acceptsd < 0)
|
||||
{
|
||||
ndbg("accept failed: %d\n", errno);
|
||||
goto errout_with_socket;
|
||||
}
|
||||
|
||||
/* Configure to "linger" until all data is sent when the socket is closed */
|
||||
|
||||
#ifdef CONFIG_NET_HAVE_SOLINGER
|
||||
ling.l_onoff = 1;
|
||||
ling.l_linger = 30; /* timeout is seconds */
|
||||
if (setsockopt(acceptsd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger)) < 0)
|
||||
{
|
||||
ndbg("setsockopt failed: %d\n", errno);
|
||||
goto errout_with_acceptsd;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create a character device to "wrap" the accepted socket descriptor */
|
||||
|
||||
nvdbg("Creating the telnet driver\n");
|
||||
devpath = telnetd_driver(acceptsd, daemon);
|
||||
if (devpath < 0)
|
||||
{
|
||||
ndbg("telnetd_driver failed\n");
|
||||
goto errout_with_acceptsd;
|
||||
}
|
||||
|
||||
/* Open the driver */
|
||||
|
||||
nvdbg("Opening the telnet driver\n");
|
||||
drvrfd = open(devpath, O_RDWR);
|
||||
if (drvrfd < 0)
|
||||
{
|
||||
ndbg("Failed to open %s: %d\n", devpath, errno);
|
||||
goto errout_with_acceptsd;
|
||||
}
|
||||
|
||||
/* We can now free the driver string */
|
||||
|
||||
free(devpath);
|
||||
|
||||
/* Use this driver as stdin, stdout, and stderror */
|
||||
|
||||
(void)dup2(drvrfd, 0);
|
||||
(void)dup2(drvrfd, 1);
|
||||
(void)dup2(drvrfd, 2);
|
||||
|
||||
/* And we can close our original driver fd */
|
||||
|
||||
if (drvrfd > 2)
|
||||
{
|
||||
close(drvrfd);
|
||||
}
|
||||
|
||||
/* Create a task to handle the connection. The created task
|
||||
* will inherit the new stdin, stdout, and stderr.
|
||||
*/
|
||||
|
||||
nvdbg("Starting the telnet session\n");
|
||||
pid = TASK_CREATE("Telnet session", daemon->priority, daemon->stacksize,
|
||||
daemon->entry, NULL);
|
||||
if (pid < 0)
|
||||
{
|
||||
ndbg("Failed start the telnet session: %d\n", errno);
|
||||
goto errout_with_acceptsd;
|
||||
}
|
||||
|
||||
/* Forget about the connection. */
|
||||
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
}
|
||||
|
||||
errout_with_acceptsd:
|
||||
close(acceptsd);
|
||||
|
||||
errout_with_socket:
|
||||
close(listensd);
|
||||
free(daemon);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_start
|
||||
*
|
||||
* Description:
|
||||
* Start the telnet daemon.
|
||||
*
|
||||
* Parameters:
|
||||
* config A pointer to a configuration structure that characterizes the
|
||||
* telnet daemon. This configuration structure may be defined
|
||||
* on the caller's stack because it is not retained by the
|
||||
* daemon.
|
||||
*
|
||||
* Return:
|
||||
* The process ID (pid) of the new telnet daemon is returned on
|
||||
* success; A negated errno is returned if the daemon was not successfully
|
||||
* started.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int telnetd_start(FAR struct telnetd_config_s *config)
|
||||
{
|
||||
FAR struct telnetd_s *daemon;
|
||||
pid_t pid;
|
||||
int ret;
|
||||
|
||||
/* Allocate a state structure for the new daemon */
|
||||
|
||||
daemon = (FAR struct telnetd_s *)malloc(sizeof(struct telnetd_s));
|
||||
if (!daemon)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Initialize the daemon structure */
|
||||
|
||||
daemon->port = config->d_port;
|
||||
daemon->priority = config->t_priority;
|
||||
daemon->stacksize = config->t_stacksize;
|
||||
daemon->entry = config->t_entry;
|
||||
|
||||
/* Initialize the common structure if this is the first daemon */
|
||||
|
||||
if (g_telnetdcommon.ndaemons < 1)
|
||||
{
|
||||
sem_init(&g_telnetdcommon.startsem, 0, 0);
|
||||
sem_init(&g_telnetdcommon.exclsem, 0, 1);
|
||||
g_telnetdcommon.minor = 0;
|
||||
}
|
||||
|
||||
/* Then start the new daemon */
|
||||
|
||||
g_telnetdcommon.daemon = daemon;
|
||||
pid = TASK_CREATE("Telnet daemon", config->d_priority, config->d_stacksize,
|
||||
telnetd_daemon, NULL);
|
||||
if (pid < 0)
|
||||
{
|
||||
int errval = errno;
|
||||
free(daemon);
|
||||
ndbg("Failed to start the telnet daemon: %d\n", errval);
|
||||
return -errval;
|
||||
}
|
||||
|
||||
/* Then wait for the daemon to start and complete the handshake */
|
||||
|
||||
do
|
||||
{
|
||||
ret = sem_wait(&g_telnetdcommon.startsem);
|
||||
|
||||
/* The only expected error condition is for sem_wait to be awakened by
|
||||
* a receipt of a signal.
|
||||
*/
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
DEBUGASSERT(errno == -EINTR);
|
||||
}
|
||||
}
|
||||
while (ret < 0);
|
||||
|
||||
/* Return success */
|
||||
|
||||
return pid;
|
||||
}
|
|
@ -0,0 +1,735 @@
|
|||
/****************************************************************************
|
||||
* apps/netutils/telnetd_driver.c
|
||||
*
|
||||
* Copyright (C) 2008-2 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* This is a leverage of similar logic from uIP which has a compatible BSD
|
||||
* license:
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
* 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. Neither the name of the Institute, 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 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
#include <nuttx/fs.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <net/psock.h>
|
||||
|
||||
#include <apps/netutils/telnetd.h>
|
||||
#include <apps/netutils/uiplib.h>
|
||||
|
||||
#include "telnetd.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define ISO_nl 0x0a
|
||||
#define ISO_cr 0x0d
|
||||
|
||||
#define TELNET_IAC 255
|
||||
#define TELNET_WILL 251
|
||||
#define TELNET_WONT 252
|
||||
#define TELNET_DO 253
|
||||
#define TELNET_DONT 254
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
/* The state of the telnet parser */
|
||||
|
||||
enum telnetd_state_e
|
||||
{
|
||||
STATE_NORMAL = 0,
|
||||
STATE_IAC,
|
||||
STATE_WILL,
|
||||
STATE_WONT,
|
||||
STATE_DO,
|
||||
STATE_DONT
|
||||
};
|
||||
|
||||
/* This structure describes the internal state of the driver */
|
||||
|
||||
struct telnetd_dev_s
|
||||
{
|
||||
sem_t td_exclsem; /* Enforces mutually exclusive access */
|
||||
uint8_t td_state; /* (See telnetd_state_e) */
|
||||
uint8_t td_pending; /* Number of valid, pending bytes in the rxbuffer */
|
||||
uint8_t td_offset; /* Offset to the valid, pending bytes in the rxbuffer */
|
||||
uint8_t td_crefs; /* The number of open references to the session */
|
||||
FAR struct socket *td_psock; /* A reference to the internal socket structure */
|
||||
char td_rxbuffer[CONFIG_TELNETD_IOBUFFER_SIZE];
|
||||
char td_txbuffer[CONFIG_TELNETD_IOBUFFER_SIZE];
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
/* Support functions */
|
||||
|
||||
#ifdef CONFIG_TELNETD_DUMPBUFFER
|
||||
static inline void telnetd_dumpbuffer(FAR const char *msg,
|
||||
FAR const char *buffer, unsigned int nbytes)
|
||||
#else
|
||||
# define telnetd_dumpbuffer(msg,buffer,nbytes)
|
||||
#endif
|
||||
static void telnetd_getchar(struct telnetd_dev_s *priv, uint8_t ch,
|
||||
FAR char *dest, int *nread);
|
||||
static ssize_t telnetd_receive(struct telnetd_dev_s *priv, FAR const char *src,
|
||||
size_t srclen, FAR char *dest, size_t destlen);
|
||||
static bool telnetd_putchar(struct telnetd_dev_s *priv, uint8_t ch,
|
||||
int *nwritten);
|
||||
static void telnetd_sendopt(struct telnetd_dev_s *priv, uint8_t option,
|
||||
uint8_t value);
|
||||
|
||||
/* Character driver methods */
|
||||
|
||||
static int telnetd_open(FAR struct file *filep);
|
||||
static int telnetd_close(FAR struct file *filep);
|
||||
static ssize_t telnetd_read(FAR struct file *, FAR char *, size_t);
|
||||
static ssize_t telnetd_write(FAR struct file *, FAR const char *, size_t);
|
||||
static int telnetd_ioctl(FAR struct file *filep, int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct file_operations g_telnetdfops =
|
||||
{
|
||||
telnetd_open, /* open */
|
||||
telnetd_close, /* close */
|
||||
telnetd_read, /* read */
|
||||
telnetd_write, /* write */
|
||||
0, /* seek */
|
||||
telnetd_ioctl /* ioctl */
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
, 0 /* poll */
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_dumpbuffer
|
||||
*
|
||||
* Description:
|
||||
* Dump a buffer of data (debug only)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_TELNETD_DUMPBUFFER
|
||||
static inline void telnetd_dumpbuffer(FAR const char *msg,
|
||||
FAR const char *buffer,
|
||||
unsigned int nbytes)
|
||||
{
|
||||
/* CONFIG_DEBUG, CONFIG_DEBUG_VERBOSE, and CONFIG_DEBUG_NET have to be
|
||||
* defined or the following does nothing.
|
||||
*/
|
||||
|
||||
nvdbgdumpbuffer(msg, (FAR const uint8_t*)buffer, nbytes);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_getchar
|
||||
*
|
||||
* Description:
|
||||
* Get another character for the user received buffer from the RX buffer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void telnetd_getchar(struct telnetd_dev_s *priv, uint8_t ch,
|
||||
FAR char *dest, int *nread)
|
||||
{
|
||||
register int index;
|
||||
|
||||
/* Ignore carriage returns */
|
||||
|
||||
if (ch != ISO_cr)
|
||||
{
|
||||
/* Add all other characters to the destination buffer */
|
||||
|
||||
index = *nread;
|
||||
dest[index++] = ch;
|
||||
*nread = index;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_receive
|
||||
*
|
||||
* Description:
|
||||
* Process a received telenet buffer
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t telnetd_receive(struct telnetd_dev_s *priv, FAR const char *src,
|
||||
size_t srclen, FAR char *dest, size_t destlen)
|
||||
{
|
||||
int nread;
|
||||
uint8_t ch;
|
||||
|
||||
for (nread = 0; srclen > 0 && nread < destlen; srclen--)
|
||||
{
|
||||
ch = *src++;
|
||||
nvdbg("ch=%02x state=%d\n", ch, priv->td_state);
|
||||
|
||||
switch (priv->td_state)
|
||||
{
|
||||
case STATE_IAC:
|
||||
if (ch == TELNET_IAC)
|
||||
{
|
||||
telnetd_getchar(priv, ch, dest, &nread);
|
||||
priv->td_state = STATE_NORMAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case TELNET_WILL:
|
||||
priv->td_state = STATE_WILL;
|
||||
break;
|
||||
|
||||
case TELNET_WONT:
|
||||
priv->td_state = STATE_WONT;
|
||||
break;
|
||||
|
||||
case TELNET_DO:
|
||||
priv->td_state = STATE_DO;
|
||||
break;
|
||||
|
||||
case TELNET_DONT:
|
||||
priv->td_state = STATE_DONT;
|
||||
break;
|
||||
|
||||
default:
|
||||
priv->td_state = STATE_NORMAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_WILL:
|
||||
/* Reply with a DONT */
|
||||
|
||||
telnetd_sendopt(priv, TELNET_DONT, ch);
|
||||
priv->td_state = STATE_NORMAL;
|
||||
break;
|
||||
|
||||
case STATE_WONT:
|
||||
/* Reply with a DONT */
|
||||
|
||||
telnetd_sendopt(priv, TELNET_DONT, ch);
|
||||
priv->td_state = STATE_NORMAL;
|
||||
break;
|
||||
|
||||
case STATE_DO:
|
||||
/* Reply with a WONT */
|
||||
|
||||
telnetd_sendopt(priv, TELNET_WONT, ch);
|
||||
priv->td_state = STATE_NORMAL;
|
||||
break;
|
||||
|
||||
case STATE_DONT:
|
||||
/* Reply with a WONT */
|
||||
|
||||
telnetd_sendopt(priv, TELNET_WONT, ch);
|
||||
priv->td_state = STATE_NORMAL;
|
||||
break;
|
||||
|
||||
case STATE_NORMAL:
|
||||
if (ch == TELNET_IAC)
|
||||
{
|
||||
priv->td_state = STATE_IAC;
|
||||
}
|
||||
else
|
||||
{
|
||||
telnetd_getchar(priv, ch, dest, &nread);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We get here if (1) all of the received bytes have been processed, or
|
||||
* (2) if the user's buffer has become full.
|
||||
*/
|
||||
|
||||
if (srclen > 0)
|
||||
{
|
||||
/* Remember where we left off. These bytes will be returned the next
|
||||
* time that telnetd_read() is called.
|
||||
*/
|
||||
|
||||
priv->td_pending = srclen;
|
||||
priv->td_offset = (src - priv->td_rxbuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All of the received bytes were consumed */
|
||||
|
||||
priv->td_pending = 0;
|
||||
priv->td_offset = 0;
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_putchar
|
||||
*
|
||||
* Description:
|
||||
* Put another character from the user buffer to the TX buffer.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static bool telnetd_putchar(struct telnetd_dev_s *priv, uint8_t ch,
|
||||
int *nread)
|
||||
{
|
||||
register int index;
|
||||
bool ret = false;
|
||||
|
||||
/* Ignore carriage returns (we will put these in automatically as necesary) */
|
||||
|
||||
if (ch != ISO_cr)
|
||||
{
|
||||
/* Add all other characters to the destination buffer */
|
||||
|
||||
index = *nread;
|
||||
priv->td_txbuffer[index++] = ch;
|
||||
|
||||
/* Check for line feeds */
|
||||
|
||||
if (ch == ISO_nl)
|
||||
{
|
||||
/* Now add the carriage return */
|
||||
|
||||
priv->td_txbuffer[index++] = ISO_cr;
|
||||
priv->td_txbuffer[index++] = '\0';
|
||||
|
||||
/* End of line */
|
||||
|
||||
ret = true;
|
||||
}
|
||||
|
||||
*nread = index;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_sendopt
|
||||
*
|
||||
* Description:
|
||||
* Send the telnet option bytes
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void telnetd_sendopt(struct telnetd_dev_s *priv, uint8_t option,
|
||||
uint8_t value)
|
||||
{
|
||||
uint8_t optbuf[4];
|
||||
optbuf[0] = TELNET_IAC;
|
||||
optbuf[1] = option;
|
||||
optbuf[2] = value;
|
||||
optbuf[3] = 0;
|
||||
|
||||
telnetd_dumpbuffer("Send optbuf", optbuf, 4);
|
||||
if (psock_send(priv->td_psock, optbuf, 4, 0) < 0)
|
||||
{
|
||||
ndbg("Failed to send TELNET_IAC\n");
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_open
|
||||
****************************************************************************/
|
||||
|
||||
static int telnetd_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct telnetd_dev_s *priv = inode->i_private;
|
||||
int tmp;
|
||||
int ret;
|
||||
|
||||
nvdbg("td_crefs: %d\n", priv->td_crefs);
|
||||
|
||||
/* O_NONBLOCK is not supported */
|
||||
|
||||
if (filep->f_oflags & O_NONBLOCK)
|
||||
{
|
||||
ret = -ENOSYS;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Get exclusive access to the device structures */
|
||||
|
||||
ret = sem_wait(&priv->td_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -errno;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Increment the count of references to the device. If this the first
|
||||
* time that the driver has been opened for this device, then initialize
|
||||
* the device.
|
||||
*/
|
||||
|
||||
tmp = priv->td_crefs + 1;
|
||||
if (tmp > 255)
|
||||
{
|
||||
/* More than 255 opens; uint8_t would overflow to zero */
|
||||
|
||||
ret = -EMFILE;
|
||||
goto errout_with_sem;
|
||||
}
|
||||
|
||||
/* Save the new open count on success */
|
||||
|
||||
priv->td_crefs = tmp;
|
||||
ret = OK;
|
||||
|
||||
errout_with_sem:
|
||||
sem_post(&priv->td_exclsem);
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_close
|
||||
****************************************************************************/
|
||||
|
||||
static int telnetd_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct telnetd_dev_s *priv = inode->i_private;
|
||||
int ret;
|
||||
|
||||
nvdbg("td_crefs: %d\n", priv->td_crefs);
|
||||
|
||||
/* Get exclusive access to the device structures */
|
||||
|
||||
ret = sem_wait(&priv->td_exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -errno;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Decrement the references to the driver. If the reference count will
|
||||
* decrement to 0, then uninitialize the driver.
|
||||
*/
|
||||
|
||||
if (priv->td_crefs > 1)
|
||||
{
|
||||
priv->td_crefs--;
|
||||
sem_post(&priv->td_exclsem);
|
||||
}
|
||||
else
|
||||
{
|
||||
psock_close(priv->td_psock);
|
||||
sem_post(&priv->td_exclsem);
|
||||
sem_destroy(&priv->td_exclsem);
|
||||
free(priv);
|
||||
}
|
||||
|
||||
ret = OK;
|
||||
|
||||
errout:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_read
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t telnetd_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct telnetd_dev_s *priv = inode->i_private;
|
||||
ssize_t ret;
|
||||
|
||||
/* First, handle the case where there are still valid bytes left in the
|
||||
* I/O buffer from the last time that read was called.
|
||||
*/
|
||||
|
||||
if (priv->td_pending > 0)
|
||||
{
|
||||
FAR const char *src = &priv->td_rxbuffer[priv->td_offset];
|
||||
ret = telnetd_receive(priv, src, priv->td_pending, buffer, len);
|
||||
}
|
||||
|
||||
/* Read a buffer of data from the telnet client */
|
||||
|
||||
else
|
||||
{
|
||||
ret = psock_recv(priv->td_psock, priv->td_rxbuffer,
|
||||
CONFIG_TELNETD_IOBUFFER_SIZE, 0);
|
||||
if (ret > 0)
|
||||
{
|
||||
/* Process the received telnet data */
|
||||
|
||||
telnetd_dumpbuffer("Received buffer", priv->td_rxbuffer, ret);
|
||||
ret = telnetd_receive(priv, priv->td_rxbuffer, ret, buffer, len);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_write
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t telnetd_write(FAR struct file *filep, FAR const char *buffer, size_t len)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct telnetd_dev_s *priv = inode->i_private;
|
||||
FAR const char *src = buffer;
|
||||
ssize_t nsent;
|
||||
ssize_t ret;
|
||||
int ncopied;
|
||||
char ch;
|
||||
bool eol;
|
||||
|
||||
/* Process each character from the user buffer */
|
||||
|
||||
for (nsent = 0, ncopied = 0; len > 0; len--)
|
||||
{
|
||||
/* Get the next character from the user buffer */
|
||||
|
||||
ch = *src++;
|
||||
|
||||
/* Add the character to the TX buffer */
|
||||
|
||||
eol = telnetd_putchar(priv, ch, &ncopied);
|
||||
|
||||
/* Was that the end of a line? */
|
||||
|
||||
if (eol)
|
||||
{
|
||||
/* Yes... send the data now */
|
||||
|
||||
ret = psock_send(priv->td_psock, priv->td_txbuffer, ncopied, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
ndbg("Failed to send response: %s\n", priv->td_txbuffer);
|
||||
}
|
||||
|
||||
/* Reset the index to the beginning of the TX buffer. Remember
|
||||
* the total number of bytes sent;
|
||||
*/
|
||||
|
||||
nsent += ret;
|
||||
ncopied = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send anything remaining in the TX buffer */
|
||||
|
||||
if (ncopied > 0)
|
||||
{
|
||||
ret = psock_send(priv->td_psock, priv->td_txbuffer, ncopied, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
ndbg("Failed to send response: %s\n", priv->td_txbuffer);
|
||||
}
|
||||
nsent += ret;
|
||||
}
|
||||
|
||||
return nsent;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_poll
|
||||
****************************************************************************/
|
||||
|
||||
static int telnetd_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
#if 0 /* No ioctl commands are yet supported */
|
||||
struct inode *inode = filep->f_inode;
|
||||
struct cdcacm_dev_s *priv = inode->i_private;
|
||||
int ret = OK;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
/* Add ioctl commands here */
|
||||
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return -ENOTTY;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_poll
|
||||
****************************************************************************/
|
||||
|
||||
#if 0 /* Not used by this driver */
|
||||
static int telnetd_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
bool setup)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct telnetd_dev_s *priv = inode->i_private;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: telnetd_driver
|
||||
*
|
||||
* Description:
|
||||
* Create a character driver to "wrap" the telnet session. This function
|
||||
* will select and return a unique path for the new telnet device.
|
||||
*
|
||||
* Parameters:
|
||||
* sd - The socket descriptor that represents the new telnet connection.
|
||||
* daemon - A pointer to the structure representing the overall state of
|
||||
* this instance of the telnet daemon.
|
||||
*
|
||||
* Return:
|
||||
* An allocated string represent the full path to the created driver. The
|
||||
* receiver of the string must de-allocate this memory when it is no longer
|
||||
* needed. NULL is returned on a failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
FAR char *telnetd_driver(int sd, FAR struct telnetd_s *daemon)
|
||||
{
|
||||
FAR struct telnetd_dev_s *priv;
|
||||
FAR char *devpath = NULL;
|
||||
int minor;
|
||||
int ret;
|
||||
|
||||
/* Allocate instance data for this driver */
|
||||
|
||||
priv = (FAR struct telnetd_dev_s*)malloc(sizeof(struct telnetd_dev_s));
|
||||
if (!priv)
|
||||
{
|
||||
ndbg("Failed to allocate the driver data structure\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize the allocated driver instance */
|
||||
|
||||
priv->td_psock = sockfd_socket(sd);
|
||||
priv->td_state = STATE_NORMAL;
|
||||
priv->td_crefs = 0;
|
||||
priv->td_pending = 0;
|
||||
priv->td_offset = 0;
|
||||
|
||||
if (!priv->td_psock)
|
||||
{
|
||||
ndbg("Failed to convert sd=%d to a socket structure\n");
|
||||
goto errout_with_dev;
|
||||
}
|
||||
|
||||
/* Allocation a unique minor device number of the telnet drvier */
|
||||
|
||||
do
|
||||
{
|
||||
ret = sem_wait(&g_telnetdcommon.exclsem);
|
||||
if (ret < 0 && errno != -EINTR)
|
||||
{
|
||||
goto errout_with_dev;
|
||||
}
|
||||
}
|
||||
while (ret < 0);
|
||||
|
||||
minor = g_telnetdcommon.minor;
|
||||
g_telnetdcommon.minor++;
|
||||
sem_post(&g_telnetdcommon.exclsem);
|
||||
|
||||
/* Create a path and name for the driver. */
|
||||
|
||||
ret = asprintf(&devpath, "/dev/telnetd%d", minor);
|
||||
if (ret < 0)
|
||||
{
|
||||
ndbg("Failed to allocate the driver path\n");
|
||||
goto errout_with_dev;
|
||||
}
|
||||
|
||||
/* Register the driver */
|
||||
|
||||
ret = register_driver(devpath, &g_telnetdfops, 0666, priv);
|
||||
if (ret < 0)
|
||||
{
|
||||
ndbg("Failed to register the driver %s: %d\n", ret);
|
||||
goto errout_with_devpath;
|
||||
}
|
||||
|
||||
/* Return the path to the new telnet driver */
|
||||
|
||||
return devpath;
|
||||
|
||||
errout_with_devpath:
|
||||
free(devpath);
|
||||
errout_with_dev:
|
||||
free(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2408,3 +2408,5 @@
|
|||
sub-directory: By making libboard.a a "phony" target, libboard.a should
|
||||
always rebuilt (the end result is worth the small increase in build time)
|
||||
(submitted by Mike Smith).
|
||||
* include/net/psock.h: A new low level socket interface that allows the OS
|
||||
to use the socket interface without having a socket descriptor.
|
||||
|
|
|
@ -0,0 +1,312 @@
|
|||
/****************************************************************************
|
||||
* include/net/psock.h
|
||||
*
|
||||
* Copyright (C) 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __NET_PSOCK_H
|
||||
#define __NET_PSOCK_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef CONFIG_NET
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-Processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Type Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C" {
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Function: sockfd_socket
|
||||
*
|
||||
* Description:
|
||||
* Given a socket descriptor, return the underly NuttX-specific socket
|
||||
* structure.
|
||||
*
|
||||
* Parameters:
|
||||
* psock Socket instance
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success; -1 on error with errno set appropriately.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct socket;
|
||||
EXTERN FAR struct socket *sockfd_socket(int sockfd);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: psock_close
|
||||
*
|
||||
* Description:
|
||||
* Performs the close operation on a socket instance
|
||||
*
|
||||
* Parameters:
|
||||
* psock Socket instance
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success; -1 on error with errno set appropriately.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct socket;
|
||||
EXTERN int psock_close(FAR struct socket *psock);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: psock_send
|
||||
*
|
||||
* Description:
|
||||
* The send() call may be used only when the socket is in a connected state
|
||||
* (so that the intended recipient is known). The only difference between
|
||||
* send() and write() is the presence of flags. With zero flags parameter,
|
||||
* send() is equivalent to write(). Also, send(sockfd,buf,len,flags) is
|
||||
* equivalent to sendto(sockfd,buf,len,flags,NULL,0).
|
||||
*
|
||||
* Parameters:
|
||||
* psock And instance of the internal socket structure.
|
||||
* buf Data to send
|
||||
* len Length of data to send
|
||||
* flags Send flags
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, returns the number of characters sent. On error,
|
||||
* -1 is returned, and errno is set appropriately:
|
||||
*
|
||||
* EAGAIN or EWOULDBLOCK
|
||||
* The socket is marked non-blocking and the requested operation
|
||||
* would block.
|
||||
* EBADF
|
||||
* An invalid descriptor was specified.
|
||||
* ECONNRESET
|
||||
* Connection reset by peer.
|
||||
* EDESTADDRREQ
|
||||
* The socket is not connection-mode, and no peer address is set.
|
||||
* EFAULT
|
||||
* An invalid user space address was specified for a parameter.
|
||||
* EINTR
|
||||
* A signal occurred before any data was transmitted.
|
||||
* EINVAL
|
||||
* Invalid argument passed.
|
||||
* EISCONN
|
||||
* The connection-mode socket was connected already but a recipient
|
||||
* was specified. (Now either this error is returned, or the recipient
|
||||
* specification is ignored.)
|
||||
* EMSGSIZE
|
||||
* The socket type requires that message be sent atomically, and the
|
||||
* size of the message to be sent made this impossible.
|
||||
* ENOBUFS
|
||||
* The output queue for a network interface was full. This generally
|
||||
* indicates that the interface has stopped sending, but may be
|
||||
* caused by transient congestion.
|
||||
* ENOMEM
|
||||
* No memory available.
|
||||
* ENOTCONN
|
||||
* The socket is not connected, and no target has been given.
|
||||
* ENOTSOCK
|
||||
* The argument s is not a socket.
|
||||
* EOPNOTSUPP
|
||||
* Some bit in the flags argument is inappropriate for the socket
|
||||
* type.
|
||||
* EPIPE
|
||||
* The local end has been shut down on a connection oriented socket.
|
||||
* In this case the process will also receive a SIGPIPE unless
|
||||
* MSG_NOSIGNAL is set.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct socket;
|
||||
EXTERN ssize_t psock_send(FAR struct socket *psock, const void *buf,
|
||||
size_t len, int flags);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: psock_sendto
|
||||
*
|
||||
* Description:
|
||||
* If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
|
||||
* socket, the parameters to and 'tolen' are ignored (and the error EISCONN
|
||||
* may be returned when they are not NULL and 0), and the error ENOTCONN is
|
||||
* returned when the socket was not actually connected.
|
||||
*
|
||||
* Parameters:
|
||||
* psock A pointer to a NuttX-specific, internal socket structure
|
||||
* buf Data to send
|
||||
* len Length of data to send
|
||||
* flags Send flags
|
||||
* to Address of recipient
|
||||
* tolen The length of the address structure
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, returns the number of characters sent. On error,
|
||||
* -1 is returned, and errno is set appropriately:
|
||||
*
|
||||
* EAGAIN or EWOULDBLOCK
|
||||
* The socket is marked non-blocking and the requested operation
|
||||
* would block.
|
||||
* EBADF
|
||||
* An invalid descriptor was specified.
|
||||
* ECONNRESET
|
||||
* Connection reset by peer.
|
||||
* EDESTADDRREQ
|
||||
* The socket is not connection-mode, and no peer address is set.
|
||||
* EFAULT
|
||||
* An invalid user space address was specified for a parameter.
|
||||
* EINTR
|
||||
* A signal occurred before any data was transmitted.
|
||||
* EINVAL
|
||||
* Invalid argument passed.
|
||||
* EISCONN
|
||||
* The connection-mode socket was connected already but a recipient
|
||||
* was specified. (Now either this error is returned, or the recipient
|
||||
* specification is ignored.)
|
||||
* EMSGSIZE
|
||||
* The socket type requires that message be sent atomically, and the
|
||||
* size of the message to be sent made this impossible.
|
||||
* ENOBUFS
|
||||
* The output queue for a network interface was full. This generally
|
||||
* indicates that the interface has stopped sending, but may be
|
||||
* caused by transient congestion.
|
||||
* ENOMEM
|
||||
* No memory available.
|
||||
* ENOTCONN
|
||||
* The socket is not connected, and no target has been given.
|
||||
* ENOTSOCK
|
||||
* The argument s is not a socket.
|
||||
* EOPNOTSUPP
|
||||
* Some bit in the flags argument is inappropriate for the socket
|
||||
* type.
|
||||
* EPIPE
|
||||
* The local end has been shut down on a connection oriented socket.
|
||||
* In this case the process will also receive a SIGPIPE unless
|
||||
* MSG_NOSIGNAL is set.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct socket;
|
||||
struct sockaddr;
|
||||
EXTERN ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
size_t len, int flags, FAR const struct sockaddr *to,
|
||||
socklen_t tolen);
|
||||
|
||||
/****************************************************************************
|
||||
* Function: psock_recvfrom
|
||||
*
|
||||
* Description:
|
||||
* recvfrom() receives messages from a socket, and may be used to receive
|
||||
* data on a socket whether or not it is connection-oriented.
|
||||
*
|
||||
* If from is not NULL, and the underlying protocol provides the source
|
||||
* address, this source address is filled in. The argument fromlen
|
||||
* initialized to the size of the buffer associated with from, and modified
|
||||
* on return to indicate the actual size of the address stored there.
|
||||
*
|
||||
* Parameters:
|
||||
* psock A pointer to a NuttX-specific, internal socket structure
|
||||
* buf Buffer to receive data
|
||||
* len Length of buffer
|
||||
* flags Receive flags
|
||||
* from Address of source (may be NULL)
|
||||
* fromlen The length of the address structure
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, returns the number of characters sent. On error,
|
||||
* -1 is returned, and errno is set appropriately:
|
||||
*
|
||||
* EAGAIN
|
||||
* The socket is marked non-blocking and the receive operation would block,
|
||||
* or a receive timeout had been set and the timeout expired before data
|
||||
* was received.
|
||||
* EBADF
|
||||
* The argument sockfd is an invalid descriptor.
|
||||
* ECONNREFUSED
|
||||
* A remote host refused to allow the network connection (typically because
|
||||
* it is not running the requested service).
|
||||
* EFAULT
|
||||
* The receive buffer pointer(s) point outside the process's address space.
|
||||
* EINTR
|
||||
* The receive was interrupted by delivery of a signal before any data were
|
||||
* available.
|
||||
* EINVAL
|
||||
* Invalid argument passed.
|
||||
* ENOMEM
|
||||
* Could not allocate memory.
|
||||
* ENOTCONN
|
||||
* The socket is associated with a connection-oriented protocol and has
|
||||
* not been connected.
|
||||
* ENOTSOCK
|
||||
* The argument sockfd does not refer to a socket.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct socket;
|
||||
struct sockaddr;
|
||||
EXTERN ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf,
|
||||
size_t len, int flags,FAR struct sockaddr *from,
|
||||
FAR socklen_t *fromlen);
|
||||
|
||||
#define psock_recv(psock,buf,len,flags) psock_recvfrom(psock,buf,len,flags,NULL,0)
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NET */
|
||||
#endif /* __NET_PSOCK_H */
|
|
@ -1,8 +1,8 @@
|
|||
/****************************************************************************
|
||||
* net/net_close.c
|
||||
*
|
||||
* Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -199,10 +199,10 @@ static inline void netclose_disconnect(FAR struct socket *psock)
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: net_closesocket
|
||||
* Function: psock_close
|
||||
*
|
||||
* Description:
|
||||
* Performs the close operation on asocket instance
|
||||
* Performs the close operation on a socket instance
|
||||
*
|
||||
* Parameters:
|
||||
* psock Socket instance
|
||||
|
@ -214,7 +214,7 @@ static inline void netclose_disconnect(FAR struct socket *psock)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
int net_closesocket(FAR struct socket *psock)
|
||||
int psock_close(FAR struct socket *psock)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -324,7 +324,7 @@ errout:
|
|||
|
||||
int net_close(int sockfd)
|
||||
{
|
||||
return net_closesocket(sockfd_socket(sockfd));
|
||||
return psock_close(sockfd_socket(sockfd));
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET */
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/****************************************************************************
|
||||
* net/net_internal.h
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -48,6 +48,7 @@
|
|||
#include <time.h>
|
||||
|
||||
#include <nuttx/net.h>
|
||||
#include <net/psock.h>
|
||||
#include <net/uip/uip.h>
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -157,7 +158,7 @@ EXTERN FAR struct socket *sockfd_socket(int sockfd);
|
|||
|
||||
/* net_close.c ***************************************************************/
|
||||
|
||||
EXTERN int net_closesocket(FAR struct socket *psock);
|
||||
EXTERN int psock_close(FAR struct socket *psock);
|
||||
|
||||
/* sockopt support ***********************************************************/
|
||||
|
||||
|
@ -206,6 +207,11 @@ EXTERN void arptimer_init(void);
|
|||
# define arptimer_init()
|
||||
#endif
|
||||
|
||||
/* send.c ********************************************************************/
|
||||
|
||||
EXTERN ssize_t psock_send(FAR struct socket *psock, const void *buf,
|
||||
size_t len, int flags);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/****************************************************************************
|
||||
* net/net_poll.c
|
||||
*
|
||||
* Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2008-2009, 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/****************************************************************************
|
||||
* net/net_sockets.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -186,7 +186,7 @@ int net_releaselist(FAR struct socketlist *list)
|
|||
if (crefs <= 0)
|
||||
{
|
||||
/* Close each open socket in the list
|
||||
* REVISIT: net_closesocket() will attempt to use semaphores.
|
||||
* REVISIT: psock_close() will attempt to use semaphores.
|
||||
* If we actually are in the IDLE thread, then could this cause
|
||||
* problems? Probably not, it the task has exited and crefs is
|
||||
* zero, then there probably could not be a contender for the
|
||||
|
@ -198,7 +198,7 @@ int net_releaselist(FAR struct socketlist *list)
|
|||
FAR struct socket *psock = &list->sl_sockets[ndx];
|
||||
if (psock->s_crefs > 0)
|
||||
{
|
||||
(void)net_closesocket(psock);
|
||||
(void)psock_close(psock);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/****************************************************************************
|
||||
* net/recv.c
|
||||
*
|
||||
* Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2007, 2008, 2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/****************************************************************************
|
||||
* net/recvfrom.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -988,7 +988,7 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: recvfrom
|
||||
* Function: psock_recvfrom
|
||||
*
|
||||
* Description:
|
||||
* recvfrom() receives messages from a socket, and may be used to receive
|
||||
|
@ -1000,7 +1000,7 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
|
|||
* on return to indicate the actual size of the address stored there.
|
||||
*
|
||||
* Parameters:
|
||||
* sockfd Socket descriptor of socket
|
||||
* psock A pointer to a NuttX-specific, internal socket structure
|
||||
* buf Buffer to receive data
|
||||
* len Length of buffer
|
||||
* flags Receive flags
|
||||
|
@ -1039,11 +1039,10 @@ static ssize_t tcp_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
|
||||
FAR struct sockaddr *from, FAR socklen_t *fromlen)
|
||||
ssize_t psock_recvfrom(FAR struct socket *psock, FAR void *buf, size_t len,
|
||||
int flags,FAR struct sockaddr *from,
|
||||
FAR socklen_t *fromlen)
|
||||
{
|
||||
FAR struct socket *psock;
|
||||
|
||||
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_TCP)
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
FAR struct sockaddr_in6 *infrom = (struct sockaddr_in6 *)from;
|
||||
|
@ -1065,10 +1064,8 @@ ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Get the underlying socket structure */
|
||||
/* Verify that the sockfd corresponds to valid, allocated socket */
|
||||
|
||||
psock = sockfd_socket(sockfd);
|
||||
if (!psock || psock->s_crefs <= 0)
|
||||
{
|
||||
err = EBADF;
|
||||
|
@ -1136,4 +1133,70 @@ errout:
|
|||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: recvfrom
|
||||
*
|
||||
* Description:
|
||||
* recvfrom() receives messages from a socket, and may be used to receive
|
||||
* data on a socket whether or not it is connection-oriented.
|
||||
*
|
||||
* If from is not NULL, and the underlying protocol provides the source
|
||||
* address, this source address is filled in. The argument fromlen
|
||||
* initialized to the size of the buffer associated with from, and modified
|
||||
* on return to indicate the actual size of the address stored there.
|
||||
*
|
||||
* Parameters:
|
||||
* sockfd Socket descriptor of socket
|
||||
* buf Buffer to receive data
|
||||
* len Length of buffer
|
||||
* flags Receive flags
|
||||
* from Address of source (may be NULL)
|
||||
* fromlen The length of the address structure
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, returns the number of characters sent. On error,
|
||||
* -1 is returned, and errno is set appropriately:
|
||||
*
|
||||
* EAGAIN
|
||||
* The socket is marked non-blocking and the receive operation would block,
|
||||
* or a receive timeout had been set and the timeout expired before data
|
||||
* was received.
|
||||
* EBADF
|
||||
* The argument sockfd is an invalid descriptor.
|
||||
* ECONNREFUSED
|
||||
* A remote host refused to allow the network connection (typically because
|
||||
* it is not running the requested service).
|
||||
* EFAULT
|
||||
* The receive buffer pointer(s) point outside the process's address space.
|
||||
* EINTR
|
||||
* The receive was interrupted by delivery of a signal before any data were
|
||||
* available.
|
||||
* EINVAL
|
||||
* Invalid argument passed.
|
||||
* ENOMEM
|
||||
* Could not allocate memory.
|
||||
* ENOTCONN
|
||||
* The socket is associated with a connection-oriented protocol and has
|
||||
* not been connected.
|
||||
* ENOTSOCK
|
||||
* The argument sockfd does not refer to a socket.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t recvfrom(int sockfd, FAR void *buf, size_t len, int flags,
|
||||
FAR struct sockaddr *from, FAR socklen_t *fromlen)
|
||||
{
|
||||
FAR struct socket *psock;
|
||||
|
||||
/* Get the underlying socket structure */
|
||||
|
||||
psock = sockfd_socket(sockfd);
|
||||
|
||||
/* Then let psock_recvfrom() do all of the work */
|
||||
|
||||
return psock_recvfrom(psock, buf, len, flags, from, fromlen);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET */
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/****************************************************************************
|
||||
* net/send.c
|
||||
*
|
||||
* Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -336,7 +336,7 @@ end_wait:
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: send
|
||||
* Function: psock_send
|
||||
*
|
||||
* Description:
|
||||
* The send() call may be used only when the socket is in a connected state
|
||||
|
@ -346,7 +346,7 @@ end_wait:
|
|||
* equivalent to sendto(sockfd,buf,len,flags,NULL,0).
|
||||
*
|
||||
* Parameters:
|
||||
* sockfd Socket descriptor of socket
|
||||
* psock And instance of the internal socket structure.
|
||||
* buf Data to send
|
||||
* len Length of data to send
|
||||
* flags Send flags
|
||||
|
@ -399,9 +399,8 @@ end_wait:
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t send(int sockfd, const void *buf, size_t len, int flags)
|
||||
ssize_t psock_send(FAR struct socket *psock, const void *buf, size_t len, int flags)
|
||||
{
|
||||
FAR struct socket *psock = sockfd_socket(sockfd);
|
||||
struct send_s state;
|
||||
uip_lock_t save;
|
||||
int err;
|
||||
|
@ -525,4 +524,73 @@ errout:
|
|||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: send
|
||||
*
|
||||
* Description:
|
||||
* The send() call may be used only when the socket is in a connected state
|
||||
* (so that the intended recipient is known). The only difference between
|
||||
* send() and write() is the presence of flags. With zero flags parameter,
|
||||
* send() is equivalent to write(). Also, send(sockfd,buf,len,flags) is
|
||||
* equivalent to sendto(sockfd,buf,len,flags,NULL,0).
|
||||
*
|
||||
* Parameters:
|
||||
* sockfd Socket descriptor of socket
|
||||
* buf Data to send
|
||||
* len Length of data to send
|
||||
* flags Send flags
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, returns the number of characters sent. On error,
|
||||
* -1 is returned, and errno is set appropriately:
|
||||
*
|
||||
* EAGAIN or EWOULDBLOCK
|
||||
* The socket is marked non-blocking and the requested operation
|
||||
* would block.
|
||||
* EBADF
|
||||
* An invalid descriptor was specified.
|
||||
* ECONNRESET
|
||||
* Connection reset by peer.
|
||||
* EDESTADDRREQ
|
||||
* The socket is not connection-mode, and no peer address is set.
|
||||
* EFAULT
|
||||
* An invalid user space address was specified for a parameter.
|
||||
* EINTR
|
||||
* A signal occurred before any data was transmitted.
|
||||
* EINVAL
|
||||
* Invalid argument passed.
|
||||
* EISCONN
|
||||
* The connection-mode socket was connected already but a recipient
|
||||
* was specified. (Now either this error is returned, or the recipient
|
||||
* specification is ignored.)
|
||||
* EMSGSIZE
|
||||
* The socket type requires that message be sent atomically, and the
|
||||
* size of the message to be sent made this impossible.
|
||||
* ENOBUFS
|
||||
* The output queue for a network interface was full. This generally
|
||||
* indicates that the interface has stopped sending, but may be
|
||||
* caused by transient congestion.
|
||||
* ENOMEM
|
||||
* No memory available.
|
||||
* ENOTCONN
|
||||
* The socket is not connected, and no target has been given.
|
||||
* ENOTSOCK
|
||||
* The argument s is not a socket.
|
||||
* EOPNOTSUPP
|
||||
* Some bit in the flags argument is inappropriate for the socket
|
||||
* type.
|
||||
* EPIPE
|
||||
* The local end has been shut down on a connection oriented socket.
|
||||
* In this case the process will also receive a SIGPIPE unless
|
||||
* MSG_NOSIGNAL is set.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t send(int sockfd, const void *buf, size_t len, int flags)
|
||||
{
|
||||
return psock_send(sockfd_socket(sockfd), buf, len, flags);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET && CONFIG_NET_TCP */
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/****************************************************************************
|
||||
* net/sendto.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -157,7 +157,7 @@ static uint16_t sendto_interrupt(struct uip_driver_s *dev, void *conn,
|
|||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Function: sendto
|
||||
* Function: psock_sendto
|
||||
*
|
||||
* Description:
|
||||
* If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
|
||||
|
@ -166,7 +166,7 @@ static uint16_t sendto_interrupt(struct uip_driver_s *dev, void *conn,
|
|||
* returned when the socket was not actually connected.
|
||||
*
|
||||
* Parameters:
|
||||
* sockfd Socket descriptor of socket
|
||||
* psock A pointer to a NuttX-specific, internal socket structure
|
||||
* buf Data to send
|
||||
* len Length of data to send
|
||||
* flags Send flags
|
||||
|
@ -221,10 +221,10 @@ static uint16_t sendto_interrupt(struct uip_driver_s *dev, void *conn,
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
|
||||
const struct sockaddr *to, socklen_t tolen)
|
||||
ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||
size_t len, int flags, FAR const struct sockaddr *to,
|
||||
socklen_t tolen)
|
||||
{
|
||||
FAR struct socket *psock;
|
||||
#ifdef CONFIG_NET_UDP
|
||||
FAR struct uip_udp_conn *conn;
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
|
@ -245,7 +245,7 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
|
|||
if (!to || !tolen)
|
||||
{
|
||||
#ifdef CONFIG_NET_TCP
|
||||
return send(sockfd, buf, len, flags);
|
||||
return psock_send(psock, buf, len, flags);
|
||||
#else
|
||||
err = EINVAL;
|
||||
goto errout;
|
||||
|
@ -264,10 +264,8 @@ ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
|
|||
goto errout;
|
||||
}
|
||||
|
||||
/* Get the underlying socket structure */
|
||||
/* Verify that the sockfd corresponds to valid, allocated socket */
|
||||
/* Verify that the psock corresponds to valid, allocated socket */
|
||||
|
||||
psock = sockfd_socket(sockfd);
|
||||
if (!psock || psock->s_crefs <= 0)
|
||||
{
|
||||
err = EBADF;
|
||||
|
@ -369,4 +367,83 @@ errout:
|
|||
return ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Function: sendto
|
||||
*
|
||||
* Description:
|
||||
* If sendto() is used on a connection-mode (SOCK_STREAM, SOCK_SEQPACKET)
|
||||
* socket, the parameters to and 'tolen' are ignored (and the error EISCONN
|
||||
* may be returned when they are not NULL and 0), and the error ENOTCONN is
|
||||
* returned when the socket was not actually connected.
|
||||
*
|
||||
* Parameters:
|
||||
* sockfd Socket descriptor of socket
|
||||
* buf Data to send
|
||||
* len Length of data to send
|
||||
* flags Send flags
|
||||
* to Address of recipient
|
||||
* tolen The length of the address structure
|
||||
*
|
||||
* Returned Value:
|
||||
* On success, returns the number of characters sent. On error,
|
||||
* -1 is returned, and errno is set appropriately:
|
||||
*
|
||||
* EAGAIN or EWOULDBLOCK
|
||||
* The socket is marked non-blocking and the requested operation
|
||||
* would block.
|
||||
* EBADF
|
||||
* An invalid descriptor was specified.
|
||||
* ECONNRESET
|
||||
* Connection reset by peer.
|
||||
* EDESTADDRREQ
|
||||
* The socket is not connection-mode, and no peer address is set.
|
||||
* EFAULT
|
||||
* An invalid user space address was specified for a parameter.
|
||||
* EINTR
|
||||
* A signal occurred before any data was transmitted.
|
||||
* EINVAL
|
||||
* Invalid argument passed.
|
||||
* EISCONN
|
||||
* The connection-mode socket was connected already but a recipient
|
||||
* was specified. (Now either this error is returned, or the recipient
|
||||
* specification is ignored.)
|
||||
* EMSGSIZE
|
||||
* The socket type requires that message be sent atomically, and the
|
||||
* size of the message to be sent made this impossible.
|
||||
* ENOBUFS
|
||||
* The output queue for a network interface was full. This generally
|
||||
* indicates that the interface has stopped sending, but may be
|
||||
* caused by transient congestion.
|
||||
* ENOMEM
|
||||
* No memory available.
|
||||
* ENOTCONN
|
||||
* The socket is not connected, and no target has been given.
|
||||
* ENOTSOCK
|
||||
* The argument s is not a socket.
|
||||
* EOPNOTSUPP
|
||||
* Some bit in the flags argument is inappropriate for the socket
|
||||
* type.
|
||||
* EPIPE
|
||||
* The local end has been shut down on a connection oriented socket.
|
||||
* In this case the process will also receive a SIGPIPE unless
|
||||
* MSG_NOSIGNAL is set.
|
||||
*
|
||||
* Assumptions:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags,
|
||||
FAR const struct sockaddr *to, socklen_t tolen)
|
||||
{
|
||||
FAR struct socket *psock;
|
||||
|
||||
/* Get the underlying socket structure */
|
||||
|
||||
psock = sockfd_socket(sockfd);
|
||||
|
||||
/* And let psock_sendto do all of the work */
|
||||
|
||||
return psock_sendto(psock, buf, len, flags, to, tolen);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET */
|
||||
|
|
Loading…
Reference in New Issue