Watt-32 tcp/ip  2.2 dev-rel.10
echo.c
Go to the documentation of this file.
1 
7 /*
8  * Copyright (c) 1997-2002 Gisle Vanem <gvanem@yahoo.no>
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  * must display the following acknowledgement:
20  * This product includes software developed by Gisle Vanem
21  * Bergen, Norway.
22  *
23  * THIS SOFTWARE IS PROVIDED BY ME (Gisle Vanem) AND CONTRIBUTORS ``AS IS''
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL I OR CONTRIBUTORS BE LIABLE FOR ANY
27  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  */
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 
39 #include "wattcp.h"
40 #include "strings.h"
41 #include "pcconfig.h"
42 #include "pctcp.h"
43 #include "pcdbug.h"
44 #include "misc.h"
45 #include "run.h"
46 #include "netaddr.h"
47 #include "echo.h"
48 
49 #if defined(USE_ECHO_DISC)
50 
51 static _udp_Socket *udp_echo_sock, *udp_disc_sock;
52 static _tcp_Socket *tcp_echo_sock, *tcp_disc_sock;
53 
54 static BOOL do_echo = 0;
55 static WORD echo_port = 7;
56 static DWORD echo_host = 0;
57 
58 static BOOL do_disc = 0;
59 static WORD disc_port = 9;
60 static DWORD disc_host = 0;
61 
62 static void (W32_CALL *prev_hook) (const char*, const char*) = NULL;
63 
64 static void echo_discard_daemon (void);
65 
66 static void W32_CALL udp_handler (sock_type *s, void *data, int len,
67  const tcp_PseudoHeader *ph,
68  const void *udp_hdr);
69 
70 /*
71  * Parse and match "echo.daemon = 0/1", "echo.port = <n>" etc.
72  */
73 static void W32_CALL echo_config (const char *name, const char *value)
74 {
75  static const struct config_table echo_cfg[] = {
76  { "DAEMON", ARG_ATOI, (void*)&do_echo },
77  { "HOST", ARG_RESOLVE, (void*)&echo_host },
78  { "PORT", ARG_ATOI, (void*)&echo_port },
79  { NULL, 0, NULL }
80  };
81  static const struct config_table disc_cfg[] = {
82  { "DAEMON", ARG_ATOI, (void*)&do_disc },
83  { "HOST", ARG_RESOLVE, (void*)&disc_host },
84  { "PORT", ARG_ATOI, (void*)&disc_port },
85  { NULL, 0, NULL }
86  };
87 
88  if (!parse_config_table(&echo_cfg[0], "ECHO.", name, value) &&
89  !parse_config_table(&disc_cfg[0], "DISCARD.", name, value))
90  {
91  if (prev_hook)
92  (*prev_hook) (name, value);
93  }
94 }
95 
100 static void echo_discard_exit (void)
101 {
102  DAEMON_DEL (echo_discard_daemon);
103  if (udp_echo_sock)
104  free (udp_echo_sock);
105  if (tcp_echo_sock)
106  free (tcp_echo_sock);
107  if (udp_disc_sock)
108  free (udp_disc_sock);
109  if (tcp_disc_sock)
110  free (tcp_disc_sock);
111 }
112 
117 void echo_discard_init (void)
118 {
119  prev_hook = usr_init;
120  usr_init = echo_config;
121  udp_echo_sock = udp_disc_sock = NULL;
122  tcp_echo_sock = tcp_disc_sock = NULL;
123  RUNDOWN_ADD (echo_discard_exit, 258);
124 }
125 
130 {
131  if (do_echo)
132  {
133  udp_echo_sock = malloc (sizeof(*udp_echo_sock));
134 #if !defined(USE_UDP_ONLY)
135  tcp_echo_sock = malloc (sizeof(*tcp_echo_sock));
136 #endif
137  if (!udp_echo_sock && !tcp_echo_sock)
138  do_echo = FALSE;
139 
140  if (udp_echo_sock)
141  {
142  udp_listen (udp_echo_sock, echo_port, echo_host, 0,
143  (ProtoHandler)udp_handler);
144  udp_echo_sock->sockmode &= ~SOCK_MODE_UDPCHK; /* no checksum testing */
145  }
146 #if !defined(USE_UDP_ONLY)
147  if (tcp_echo_sock)
148  tcp_listen (tcp_echo_sock, echo_port, echo_host, 0, NULL, 0);
149 #endif
150  }
151 
152  if (do_disc)
153  {
154  udp_disc_sock = malloc (sizeof(*udp_disc_sock));
155 #if !defined(USE_UDP_ONLY)
156  tcp_disc_sock = malloc (sizeof(*tcp_disc_sock));
157 #endif
158  if (!udp_disc_sock && !tcp_disc_sock)
159  do_disc = FALSE;
160 
161  if (udp_disc_sock)
162  {
163  udp_listen (udp_disc_sock, disc_port, disc_host, 0,
164  (ProtoHandler)udp_handler);
165  udp_disc_sock->sockmode &= ~SOCK_MODE_UDPCHK;
166  }
167 #if !defined(USE_UDP_ONLY)
168  if (tcp_disc_sock)
169  tcp_listen (tcp_disc_sock, disc_port, disc_host, 0, NULL, 0);
170 #endif
171  }
172 
173  if (do_echo || do_disc)
174  DAEMON_ADD (echo_discard_daemon);
175 }
176 
181 static void echo_discard_daemon (void)
182 {
183  sock_type *s = (sock_type*) tcp_echo_sock;
184 
185  if (!s || !tcp_disc_sock)
186  return;
187 
188  if (sock_dataready(s)) /* only echo back from echo-socket */
189  {
190  BYTE buf[MAX_IP4_DATA-sizeof(tcp_Header)];
191  int len = sock_read (s, buf, sizeof(buf));
192  sock_write (s, buf, len);
193  }
194  tcp_disc_sock->rx_datalen = 0; /* discard recv data */
195 }
196 
200 static void W32_CALL udp_handler (sock_type *s, void *data, int len,
201  const tcp_PseudoHeader *ph,
202  const void *udp)
203 {
204  if (s == (sock_type*)udp_echo_sock)
205  {
206  TCP_CONSOLE_MSG (2, ("echo (udp): looping %d bytes from %s\n",
207  len, _inet_ntoa(NULL,intel(ph->src))));
208 
209  if (!sock_enqueue(s, (const BYTE*)data, len))
210  sock_close (s);
211  }
212  else /* discard packet */
213  {
214  TCP_CONSOLE_MSG (2, ("discard (udp): dropping %d bytes from %s\n",
215  len, _inet_ntoa(NULL,intel(ph->src))));
216  }
217  ARGSUSED (ph);
218  ARGSUSED (udp);
219 }
220 
221 #if defined(TEST_PROG)
222 
223 int main (int argc, char **argv)
224 {
226  return (0);
227 }
228 #endif /* TEST_PROG */
229 #endif /* USE_ECHO_DISC */
230 
int W32_CALL parse_config_table(const struct config_table *tab, const char *section, const char *name, const char *value)
Parse the config-table and if a match is found for ('section'+'.
Definition: pcconfig.c:379
static const char *static void echo_discard_daemon(void)
"background" process handling echo + discard TCP sockets.
Definition: echo.c:181
int W32_CALL sock_read(sock_type *s, BYTE *buf, size_t maxlen)
Read a socket with maximum 'maxlen' bytes.
Definition: pctcp.c:2875
convert to int
Definition: tcp.h:424
int W32_CALL udp_listen(_udp_Socket *s, WORD lport, DWORD ip, WORD port, ProtoHandler handler)
UDP passive open.
Definition: pctcp.c:157
void echo_discard_init(void)
Called from watt_sock_init(): Setup config-file parser for "echo..." and "discard.." keywords.
Definition: echo.c:117
int W32_CALL sock_close(sock_type *s)
Close a UDP/TCP socket.
Definition: pctcp.c:3139
resolve host to IPv4-address
Definition: tcp.h:433
Core definitions.
static void echo_discard_exit(void)
Don't bother resetting any connections.
Definition: echo.c:100
int W32_CALL tcp_listen(_tcp_Socket *s, WORD lport, DWORD ip, WORD port, ProtoHandler handler, WORD timeout)
Passively opens TCP a connection.
Definition: pctcp.c:389
int W32_CALL sock_write(sock_type *s, const BYTE *data, int len)
Writes data and returns length written.
Definition: pctcp.c:2960
void echo_discard_start(void)
Starts the echo/discard services (udp/tcp).
Definition: echo.c:129
static void W32_CALL udp_handler(sock_type *s, void *data, int len, const tcp_PseudoHeader *ph, const void *udp_hdr)
Callback handler for echo + discard UDP sockets.
Definition: echo.c:200
char *W32_CALL _inet_ntoa(char *s, DWORD ip)
Convert an IP-address 'ip' into a string.
Definition: netaddr.c:43
WORD W32_CALL sock_dataready(sock_type *s)
sock_dataready - returns number of bytes waiting to be read.
Definition: sock_io.c:246
int W32_CALL sock_enqueue(sock_type *s, const BYTE *data, int len)
For UDP, this function is same as sock_write().
Definition: pctcp.c:3044
int main(int argc, char **argv)
Definition: echo.c:223