summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaromil <jaromil@dyne.org>2012-05-09 09:39:36 (GMT)
committer Jaromil <jaromil@dyne.org>2012-05-09 09:39:36 (GMT)
commit97d7c05c1aae0f99dacc7a8e45d0f3acd1483951 (patch)
tree51b83772f41d13bca1c5de0a70b50d162d98aede
parenta8e104dabd0e1ecc479ca1d6abc0f221bda8d559 (diff)
code cleanup after rewrite, removed netcat and older tools
-rw-r--r--src/Makefile.am2
-rw-r--r--src/avremote.h2
-rw-r--r--src/avremote_cli.c331
-rw-r--r--src/broadcaster.cpp86
-rw-r--r--src/core.c917
-rw-r--r--src/discover.c100
-rw-r--r--src/discover.h25
-rw-r--r--src/flagset.c198
-rw-r--r--src/handshake.cpp213
-rw-r--r--src/hdsync_cli.cpp3
-rw-r--r--src/hwclient.cpp38
-rw-r--r--src/hwserver.cpp41
-rw-r--r--src/intl.h55
-rw-r--r--src/misc.c421
-rw-r--r--src/misc.h71
-rw-r--r--src/netcat.c618
-rw-r--r--src/netcat.h203
-rw-r--r--src/network.c602
-rw-r--r--src/parsers.cpp84
-rw-r--r--src/parsers.h31
-rw-r--r--src/proto.h91
-rw-r--r--src/telnet.c203
-rw-r--r--src/udphelper.c302
23 files changed, 1 insertions, 4636 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 30d6c19..06433ba 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,7 +4,7 @@ SUBDIRS = uuid pgm 0mq
bin_PROGRAMS = hdsync
-noinst_HEADERS = avremote.h discover.h intl.h misc.h netcat.h proto.h
+noinst_HEADERS = avremote.h
hdsync_SOURCES = avremote.cpp avremote.h hdsync_cli.cpp
diff --git a/src/avremote.h b/src/avremote.h
index ce6f60c..406b232 100644
--- a/src/avremote.h
+++ b/src/avremote.h
@@ -80,8 +80,6 @@ typedef struct {
upnp_t *create_upnp();
void free_upnp(upnp_t *upnp);
-int upnp_discover(upnp_t *upnp);
-
// should set upnp-> hostname and port before calling this
int connect_upnp(upnp_t *upnp);
diff --git a/src/avremote_cli.c b/src/avremote_cli.c
deleted file mode 100644
index 401dfb8..0000000
--- a/src/avremote_cli.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/* AVRemote
-
- (c) 2011 Nederlands Instituut voor Mediakunst (NIMk)
- 2011 Denis Roio <jaromil@nimk.nl>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>
-
-*/
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#include <errno.h>
-
-#include <avremote.h>
-#include <parsers.h>
-
-// our exit codes are shell style: 1 is error, 0 is success
-#define ERR 1
-
-// uncomment to debug
-#define DEBUG 1
-
-// uncomment to activate discovery
-// (requires miniupnp)
-// #define DISCOVER 1
-
-char filename[512];
-char command[64];
-char server[512];
-int port = 0;
-int dry_run = 0;
-#ifdef DISCOVER
-int discover = 0;
-#endif
-int pipe_stdin = 0;
-
-parser_f *parser = NULL;
-
-// we use only getopt, no _long
-static const char *short_options = "-hvs:p:t";
-
-void cmdline(int argc, char **argv) {
- command[0] = 0;
- filename[0] = 0;
- server[0] = 0;
-
- int res, optlen;
- do {
- res = getopt(argc, argv, short_options);
- switch(res) {
- case 'h':
- fprintf(stderr,
- "%s %s - send AVTransport commands to UPNP media services\n"
- "\n"
- " Copyright (C) 2011 Jaromil @ NIMk.nl Artlab , License GNU AGPL v3+\n"
- " This is free software: you are free to change and redistribute it.\n"
- " The latest AVTransport sourcecode is published on <%s>\n"
- "\n"
- "Syntax: avremote [options] [command] [args...]\n"
- "\n"
- "Commands:\n"
- "\n"
-#ifdef DISCOVER
- " discover scan for upnp devices on the network\n"
-#endif
- " load load a file and prepare it for playback\n"
- " mode set playback mode (NORMAL or REPEAT_ONE)\n"
- " play start playing the selected file\n"
- " pause pause currently running playback\n"
- " stop stop playback and return to menu\n"
- " get get the current status of the device\n"
- " jump seek to a position in time (00:00:00)\n"
- "\n"
- " none means load and play URL, or use - to read xml from stdin\n"
- "\n"
- "Options:\n"
- "\n"
- " -s network address or hostname of the media server\n"
- " -p port on which the UPNP AVTransport daemon is listening\n"
- " -t dry run to test without a server (print out rendered xml)\n"
- "\n"
- " -h print this help\n"
- " -v version information for this tool\n"
- "\n"
- "For more informations on AVRemote read the manual: man avremote\n"
- "Please report bugs on <http://bugs.dyne.org>.\n",
- PACKAGE, VERSION, PACKAGE_URL);
- exit(0);
-
- case 'v':
- fprintf(stderr,"%s - simple commandline tool to send AVTransport commands over UPNP\n"
- "version %s by Jaromil - Netherlands Media Art Institute\n"
- "Copyright (C) 2011 NIMk Artlab, License GNU AGPL v3+\n"
- "This is free software: you are free to change and redistribute it\n",
- PACKAGE, VERSION);
- exit(0);
-
- case 's':
- snprintf(server,511,"%s",optarg);
- break;
-
- case 'p':
- sscanf (optarg, "%u", &port);
- break;
-
- case 't':
- // test dry run
- dry_run = 1;
- fprintf(stderr,"dry run: printint out rendered upnp message without establishing connection\n");
- break;
-
- case '?':
- fprintf(stderr,"unrecognized option: %s\n",optarg);
- break;
-
- case 1:
- if(!command[0]) {
- snprintf(command,63,"%s",optarg);
- } else
- snprintf(filename,511,"%s",optarg);
- break;
- default:
- break;
- }
-
- } while(res != -1);
-
-#ifdef DISCOVER
- if(command[0] == 'd') { // discover
- discover = 1;
- } else
-#endif
-
- if(!dry_run) {
- // check requires args
- if( command[0]=='-' && !command[1]) pipe_stdin++;
- }
-}
-
-
-int main(int argc, char **argv) {
- upnp_t *upnp;
- int found;
-
- cmdline(argc, argv);
-
- upnp = create_upnp();
-
-#ifdef DISCOVER
- // no server specified, force discovery
- if(!server[0] || !port) discover = 1;
-
- if (discover && !dry_run)
- {
- fprintf(stderr,"Performing upnp discovery...\n");
- found = upnp_discover(upnp);
-
- if(found != 1) {
- fprintf(stderr,"Please specify a target device host and port.\n");
- free_upnp(upnp);
- exit(0);
- }
-
- }
-#endif
-
- // commandline or detection found explicit addresses
- snprintf(upnp->hostname, MAX_HOSTNAME_SIZE-1,"%s",server);
- upnp->port = port;
-
- if(!dry_run)
- {
- if ( connect_upnp (upnp) < 0 )
- {
- fprintf(stderr,"can't connect to %s:%u: operation aborted.\n", server, port);
- exit(ERR);
- }
-
- }
- else
- {
-
- sprintf(upnp->hostname,"%s","dry run");
- upnp->port = 0;
-
- }
-
- // pipe raw xml commands from stdin
- if(pipe_stdin) {
- int res;
- int in = 0;
- char raw[8192];
-
- while( !feof(stdin) )
- {
- in = fread(raw,1,8191,stdin);
- res = write(upnp->sockfd,raw,in);
- if(res != in)
- fprintf(stderr,"upnp pipe wrote only %u of %u bytes",res, in);
- recv_upnp(upnp, 1000);
- fprintf(stderr,"%s\n",upnp->res);
- }
- free_upnp(upnp);
- exit(0);
- }
-
- /* command parsing is a cascade switch on single letters
- this is supposedly faster than strcmp. mapping:
-
- D iscovery
- L oad
- P lay
- PA use
- S top
- G et
- M ode
- J ump
-
- */
- switch(command[0]) {
-
-#ifdef DISCOVER
- case 'd': // discovery
- // was processed earlier
- break;
-#endif
-
- case 'l': // load url
- render_uri_meta(upnp,filename);
- render_upnp(upnp,"SetAVTransportURI", upnp->meta);
- // send_upnp(upnp);
- break;
-
- case 'p':
-
- if(command[1]=='l')
- { // 'pl*' is play
-
- render_upnp(upnp,"Play","<Speed>1</Speed>");
-
- }
- else if (command[1]=='a')
- { // 'pa*' is pause
-
- render_upnp(upnp,"Pause","");
-
- }
- break;
-
- case 's': // stop
- render_upnp(upnp,"Stop","");
- break;
-
- case 'g': // dump a parsable full state of the device
- render_upnp(upnp,"GetTransportInfo","");
- parser = GetTransportInfo;
-
- break;
-
- case 'm': // set the playmode:
- // "NORMAL", "REPEAT_ONE", "REPEAT_ALL", "RANDOM"
- {
- char tmp[256];
- snprintf(tmp,255,"<NewPlayMode>%s</NewPlayMode>",filename);
- render_upnp(upnp,"SetPlayMode",tmp);
- }
- break;
-
- case 'j': // jump aka seek
- // <SeekMode> and <SeekTarget>
- {
- char tmp[512];
- snprintf(tmp,511,"<Unit>REL_TIME</Unit><Target>%s</Target>",filename);
- render_upnp(upnp,"Seek",tmp);
- }
- break;
-
- default:
- if(!command[0]) break;
- fprintf(stderr,"warning: command not recognized, loading and playing as url\n");
-
- // load
- render_uri_meta(upnp,command);
- render_upnp(upnp,"SetAVTransportURI", upnp->meta);
- send_upnp(upnp);
- recv_upnp(upnp, 1000);
-
- // must re-connect socket between commands
- close(upnp->sockfd);
- upnp->sockfd = 0;
- connect_upnp(upnp);
-
- render_upnp(upnp,"Play","<Speed>1</Speed>");
- }
-
- if (dry_run)
- print_upnp(upnp);
- else
- {
- send_upnp(upnp);
- recv_upnp(upnp, 1000);
- if (parser)
- (*parser)(upnp->res);
- else
- fprintf(stderr,"%s\n",upnp->res);
- }
-
- free_upnp(upnp);
-
- exit(0);
-}
diff --git a/src/broadcaster.cpp b/src/broadcaster.cpp
deleted file mode 100644
index 761f2a5..0000000
--- a/src/broadcaster.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * (c) Copyright 2001-2010 Denis Roio <jaromil@nimk.nl>
- *
- * This source code is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Public License as published
- * by the Free Software Foundation; either version 3 of the License,
- * or (at your option) any later version.
- *
- * This source code is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * Please refer to the GNU Public License for more details.
- *
- * You should have received a copy of the GNU Public License along with
- * this source code; if not, write to:
- * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * a datagram "client" to broadcast messages over UDP
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-int main(int argc, char *argv[])
-{
- int sockfd;
- struct sockaddr_in their_addr; // connector's address information
- struct hostent *he;
- int numbytes;
- int broadcast = 1;
- //char broadcast = '1'; // if that doesn't work, try this
-
- if (argc != 4) {
- fprintf(stderr,"usage: broadcaster hostname port message\n");
- fprintf(stderr,"hostname can be 255.255.255.255 for broadcast\n");
- exit(1);
- }
-
- if ((he=gethostbyname(argv[1])) == NULL) { // get the host info
- perror("gethostbyname");
- exit(1);
- }
-
- if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
- perror("socket");
- exit(1);
- }
-
- // this call is the difference between this program and talker.c:
- if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast,
- sizeof broadcast) == -1) {
- perror("setsockopt (SO_BROADCAST)");
- exit(1);
- }
-
- their_addr.sin_family = AF_INET; // host byte order
- their_addr.sin_port = htons( atoi(argv[2]) ); // short, network byte order
- their_addr.sin_addr = *((struct in_addr *)he->h_addr);
- memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);
-
- // forge string with newline
- int len = strlen(argv[3]);
- char *temp = (char*)calloc(len+2,sizeof(char));
- snprintf(temp,len+2,"%s\n\n",argv[3]);
-
- if ((numbytes=sendto(sockfd, temp, len+2, 0,
- (struct sockaddr *)&their_addr, sizeof their_addr)) == -1) {
- perror("sendto");
- exit(1);
- }
-
- printf("sent %d bytes to %s\n", numbytes, inet_ntoa(their_addr.sin_addr));
-
- close(sockfd);
- free(temp);
-
- return 0;
-}
diff --git a/src/core.c b/src/core.c
deleted file mode 100644
index daa1ed9..0000000
--- a/src/core.c
+++ /dev/null
@@ -1,917 +0,0 @@
-/*
- * core.c -- core loops and most critical routines
- * Part of the GNU netcat project
- *
- * Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- * Copyright (C) 2002 - 2004 Giovanni Giacobbi
- *
- * $Id: core.c,v 1.38 2004/01/03 16:42:07 themnemonic Exp $
- */
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "netcat.h"
-
-/* Global variables */
-
-unsigned long bytes_sent = 0; /* total bytes received */
-unsigned long bytes_recv = 0; /* total bytes sent */
-
-/* Creates a UDP socket with a default destination address. It also calls
- bind(2) if it is needed in order to specify the source address.
- Returns the new socket number. */
-
-static int core_udp_connect(nc_sock_t *ncsock)
-{
- int ret, sock;
- struct sockaddr_in myaddr;
- debug_v(("core_udp_connect(ncsock=%p)", (void *)ncsock));
-
- sock = netcat_socket_new(PF_INET, SOCK_DGRAM);
- if (sock < 0)
- return -1;
-
- /* prepare myaddr for the bind() call */
- myaddr.sin_family = AF_INET;
- myaddr.sin_port = ncsock->local_port.netnum;
- memcpy(&myaddr.sin_addr, &ncsock->local_host.iaddrs[0],
- sizeof(myaddr.sin_addr));
- /* only call bind if it is really needed */
- if (myaddr.sin_port || myaddr.sin_addr.s_addr) {
- ret = bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr));
- if (ret < 0)
- goto err;
- }
-
- /* now prepare myaddr for the connect() call */
- myaddr.sin_family = AF_INET;
- myaddr.sin_port = ncsock->port.netnum;
- memcpy(&myaddr.sin_addr, &ncsock->host.iaddrs[0], sizeof(myaddr.sin_addr));
- ret = connect(sock, (struct sockaddr *)&myaddr, sizeof(myaddr));
- if (ret < 0)
- goto err;
-
- return sock;
-
- err:
- close(sock);
- return -1;
-} /* end of core_udp_connect() */
-
-/* Emulates a TCP connection but using the UDP protocol. There is a listening
- socket that catches the first valid packet and assumes the packet endpoints
- as the endpoints for the final connection. */
-
-static int core_udp_listen(nc_sock_t *ncsock)
-{
- int ret, *sockbuf, sock, sock_max, timeout = ncsock->timeout;
- bool need_udphelper = TRUE;
-#ifdef USE_PKTINFO
- int sockopt = 1;
-#endif
- struct sockaddr_in myaddr;
- struct timeval tt; /* needed by the select() call */
- debug_v(("core_udp_listen(ncsock=%p)", (void *)ncsock));
-
-#ifdef USE_PKTINFO
- need_udphelper = FALSE;
-#else
- /* if we need a specified source address then go straight to it */
- if (ncsock->local_host.iaddrs[0].s_addr)
- need_udphelper = FALSE;
-#endif
-
- if (!need_udphelper) {
- /* simulates a udphelper_sockets_open() call */
- sockbuf = calloc(2, sizeof(int));
- sockbuf[0] = 1;
- sockbuf[1] = sock = netcat_socket_new(PF_INET, SOCK_DGRAM);
- }
-#ifndef USE_PKTINFO
- else
- sock = udphelper_sockets_open(&sockbuf, ncsock->local_port.netnum);
-#endif
- if (sock < 0)
- goto err;
-
- /* we know that udphelper_sockets_open() returns the highest socket, and
- if we didn't call it we have just one socket */
- sock_max = sock + 1;
-
- if (!need_udphelper) {
- /* prepare myaddr for the bind() call */
- myaddr.sin_family = AF_INET;
- myaddr.sin_port = ncsock->local_port.netnum;
- memcpy(&myaddr.sin_addr, &ncsock->local_host.iaddrs[0],
- sizeof(myaddr.sin_addr));
- /* bind() MUST be called in this function, since it's the final call for
- this type of socket. FIXME: I heard that UDP port 0 is illegal. true? */
- ret = bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr));
- if (ret < 0)
- goto err;
- }
-
-#ifdef USE_PKTINFO
- /* set the right flag in order to obtain the ancillary data */
- ret = setsockopt(sock, SOL_IP, IP_PKTINFO, &sockopt, sizeof(sockopt));
- if (ret < 0)
- goto err;
-#endif
-
- /* if the port was set to 0 this means that it is assigned randomly by the
- OS. Find out which port they assigned to us. */
- if (ncsock->local_port.num == 0) {
- struct sockaddr_in get_myaddr;
- unsigned int get_myaddr_len = sizeof(get_myaddr);
-
- ret = getsockname(sock, (struct sockaddr *)&get_myaddr, &get_myaddr_len);
- if (ret < 0)
- goto err;
- netcat_getport(&ncsock->local_port, NULL, ntohs(get_myaddr.sin_port));
- assert(ncsock->local_port.num != 0);
- }
-
- if (!need_udphelper)
- ncprint(NCPRINT_VERB2, _("Listening on %s"),
- netcat_strid(&ncsock->local_host, &ncsock->local_port));
- else
- ncprint(NCPRINT_VERB2, _("Listening on %s (using %d sockets)"),
- netcat_strid(&ncsock->local_host, &ncsock->local_port), sockbuf[0]);
-
- /* since this protocol is connectionless, we need a special handling here.
- We want to simulate a two-ends connection but in order to do this we need
- a remote address and a local address (in case we bound to INADDR_ANY).
- Wait here until a packet is received, and use its source and destination
- addresses as default endpoints. If we have the zero-I/O option set, we
- just eat the packet and return when timeout is elapsed (maybe never). */
- tt.tv_sec = timeout;
- tt.tv_usec = 0;
-
- while (TRUE) {
- int socks_loop;
- fd_set ins;
-
- FD_ZERO(&ins);
- for (socks_loop = 1; socks_loop <= sockbuf[0]; socks_loop++) {
- debug_v(("Setting sock %d on ins", sockbuf[socks_loop]));
- FD_SET(sockbuf[socks_loop], &ins);
- }
-
- /* automatically use remaining timeout time if in zero-I/O mode */
- ret = select(sock_max, &ins, NULL, NULL, (timeout > 0 ? &tt : NULL));
- if (ret == 0)
- break;
-
- /* loop all the open sockets to find the active one */
- for (socks_loop = 1; socks_loop <= sockbuf[0]; socks_loop++) {
- int recv_ret, write_ret;
- struct msghdr my_hdr;
- unsigned char buf[1024];
- struct iovec my_hdr_vec;
- struct sockaddr_in rem_addr;
- struct sockaddr_in local_addr;
-#ifdef USE_PKTINFO
- unsigned char anc_buf[512];
-#endif
-
- sock = sockbuf[socks_loop];
-
- if (!FD_ISSET(sock, &ins))
- continue;
-
- /* I've looked for this code for a lot of hours, and finally found the
- RFC 2292 which provides a socket API for fetching the destination
- interface of the incoming packet. */
- memset(&my_hdr, 0, sizeof(my_hdr));
- memset(&rem_addr, 0, sizeof(rem_addr));
- memset(&local_addr, 0, sizeof(local_addr));
- my_hdr.msg_name = (void *)&rem_addr;
- my_hdr.msg_namelen = sizeof(rem_addr);
- /* initialize the vector struct and then the vectory member of the header */
- my_hdr_vec.iov_base = buf;
- my_hdr_vec.iov_len = sizeof(buf);
- my_hdr.msg_iov = &my_hdr_vec;
- my_hdr.msg_iovlen = 1;
-#ifdef USE_PKTINFO
- /* now the core part for the IP_PKTINFO support: the ancillary data */
- my_hdr.msg_control = anc_buf;
- my_hdr.msg_controllen = sizeof(anc_buf);
-#endif
-
- /* now check the remote address. If we are simulating a routing then
- use the MSG_PEEK flag, which leaves the received packet untouched */
- recv_ret = recvmsg(sock, &my_hdr, (opt_zero ? 0 : MSG_PEEK));
-
- debug_v(("received packet from %s:%d%s", netcat_inet_ntop(&rem_addr.sin_addr),
- ntohs(rem_addr.sin_port), (opt_zero ? "" : ", using as default dest")));
-
-#ifdef USE_PKTINFO
- ret = udphelper_ancillary_read(&my_hdr, &local_addr);
- local_addr.sin_port = myaddr.sin_port;
- local_addr.sin_family = myaddr.sin_family;
-#else
- ret = sizeof(local_addr);
- ret = getsockname(sock, (struct sockaddr *)&local_addr, &ret);
-#endif
-
- if (ret == 0) {
- char tmpbuf[127];
-
- strncpy(tmpbuf, netcat_inet_ntop(&rem_addr.sin_addr), sizeof(tmpbuf));
- ncprint(NCPRINT_VERB1, _("Received packet from %s:%d -> %s:%d (local)"),
- tmpbuf, ntohs(rem_addr.sin_port),
- netcat_inet_ntop(&local_addr.sin_addr),
- ntohs(local_addr.sin_port));
- }
- else
- ncprint(NCPRINT_VERB1, _("Received packet from %s:%d"),
- netcat_inet_ntop(&rem_addr.sin_addr), ntohs(rem_addr.sin_port));
-
- if (opt_zero) { /* output the packet right here right now */
- write_ret = write(STDOUT_FILENO, buf, recv_ret);
- bytes_recv += write_ret;
- debug_dv(("write_u(stdout) = %d", write_ret));
-
- if (write_ret < 0) {
- perror("write_u(stdout)");
- exit(EXIT_FAILURE);
- }
-
- /* FIXME: unhandled exception */
- assert(write_ret == recv_ret);
-
- /* if the hexdump option is set, hexdump the received data */
- if (opt_hexdump) {
-#ifndef USE_OLD_HEXDUMP
- fprintf(output_fp, "Received %d bytes from %s:%d\n", recv_ret,
- netcat_inet_ntop(&rem_addr.sin_addr), ntohs(rem_addr.sin_port));
-#endif
- netcat_fhexdump(output_fp, '<', buf, write_ret);
- }
- }
- else {
-#ifdef USE_PKTINFO
- nc_sock_t dup_socket;
-
- memset(&dup_socket, 0, sizeof(dup_socket));
- dup_socket.domain = ncsock->domain;
- dup_socket.proto = ncsock->proto;
- memcpy(&dup_socket.local_host.iaddrs[0], &local_addr.sin_addr,
- sizeof(local_addr));
- memcpy(&dup_socket.host.iaddrs[0], &rem_addr.sin_addr,
- sizeof(local_addr));
- dup_socket.local_port.netnum = local_addr.sin_port;
- dup_socket.local_port.num = ntohs(local_addr.sin_port);
- dup_socket.port.netnum = rem_addr.sin_port;
- dup_socket.port.num = ntohs(rem_addr.sin_port);
- /* copy the received data in the socket's queue */
- ncsock->recvq.len = recv_ret;
- ncsock->recvq.head = ncsock->recvq.pos = malloc(recv_ret);
- memcpy(ncsock->recvq.head, my_hdr_vec.iov_base, recv_ret);
- /* FIXME: this ONLY saves the first 1024 bytes! and the others? */
-#else
- ret = connect(sock, (struct sockaddr *)&rem_addr, sizeof(rem_addr));
- if (ret < 0)
- goto err;
-
- /* remove this socket from the array in order not to get it closed */
- sockbuf[socks_loop] = -1;
-#endif
- udphelper_sockets_close(sockbuf);
-
-#ifdef USE_PKTINFO
- /* this is all we want from this function */
- debug_dv(("calling the udp_connect() function..."));
- return core_udp_connect(&dup_socket);
-#else
- return sock;
-#endif
- }
- } /* end of foreach (sock, sockbuf) */
- } /* end of packet receiving loop */
-
- /* no packets until timeout, set errno and proceed to general error handling */
- errno = ETIMEDOUT;
-
- err:
- udphelper_sockets_close(sockbuf);
- return -1;
-} /* end of core_udp_listen() */
-
-/* Creates an outgoing tcp connection to the remote host. If a local address
- or port is also specified in the socket object, it calls bind(2).
- Returns the new socket descriptor or -1 on error. */
-
-static int core_tcp_connect(nc_sock_t *ncsock)
-{
- int ret, sock, timeout = ncsock->timeout;
- struct timeval timest;
- fd_set outs;
- debug_v(("core_tcp_connect(ncsock=%p)", (void *)ncsock));
-
- /* since we are nonblocking now, we could start as many connections as we
- want but it's not a great idea connecting more than one host at time.
- Also don't specify the local address if it's not really needed, so we can
- avoid one bind(2) call. */
- sock = netcat_socket_new_connect(PF_INET, SOCK_STREAM,
- &ncsock->host.iaddrs[0], ncsock->port.netnum,
- (ncsock->local_host.iaddrs[0].s_addr ? &ncsock->local_host.iaddrs[0] :
- NULL), ncsock->local_port.netnum);
-
- if (sock < 0)
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT, "Couldn't create connection (err=%d): %s",
- sock, strerror(errno));
-
- /* initialize select()'s variables */
- FD_ZERO(&outs);
- FD_SET(sock, &outs);
- timest.tv_sec = timeout;
- timest.tv_usec = 0;
-
- ret = select(sock + 1, NULL, &outs, NULL, (timeout > 0 ? &timest : NULL));
- if (ret > 0) {
- int ret, get_ret;
- unsigned int get_len = sizeof(get_ret); /* socklen_t */
-
- /* ok, select([single]), so sock must have triggered this */
- assert(FD_ISSET(sock, &outs));
-
- /* fetch the errors of the socket and handle system request errors */
- ret = getsockopt(sock, SOL_SOCKET, SO_ERROR, &get_ret, &get_len);
- if (ret < 0)
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT, "Critical system request failed: %s",
- strerror(errno));
-
- /* POSIX says that SO_ERROR expects an int, so my_len must be untouched */
- assert(get_len == sizeof(get_ret));
-
- /* FIXME: the error Broken Pipe should probably not stop here */
- debug_v(("Connection returned errcode=%d (%s)", get_ret, strerror(get_ret)));
- if (get_ret > 0) {
- char tmp;
-
- /* Ok, select() returned a write event for this socket AND getsockopt()
- said that some error happened. This mean that EOF is expected. */
- ret = read(sock, &tmp, 1);
- assert(ret == 0);
- /* FIXME: see the TODO entry about false error detection */
-
- shutdown(sock, 2);
- close(sock);
- ncsock->fd = -1;
- errno = get_ret; /* value returned by getsockopt(SO_ERROR) */
- return -1;
- }
-
- /* everything went fine, we have the socket */
- ncprint(NCPRINT_VERB1, _("%s open"), netcat_strid(&ncsock->host,
- &ncsock->port));
- return sock;
- }
- else if (ret) {
- /* Terminated by a signal. Silently exit */
- if (errno == EINTR)
- exit(EXIT_FAILURE);
- /* The error seems to be a little worse */
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT, "Critical system request failed: %s",
- strerror(errno));
- }
-
- /* select returned 0, this means connection timed out for our timing
- directives (in fact the socket has a longer timeout usually, so we need
- to abort the connection try, set the proper errno and return */
- shutdown(sock, 2);
- close(sock);
- errno = ETIMEDOUT;
- return -1;
-} /* end of core_tcp_connect() */
-
-/* This function loops inside the accept() loop until a *VALID* connection is
- fetched. If an unwanted connection arrives, it is shutdown() and close()d.
- If zero I/O mode is enabled, ALL connections are refused and it stays
- unconditionally in listen mode until timeout elapses, if given, otherwise
- forever.
- Returns: The new socket descriptor for the fetched connection */
-
-static int core_tcp_listen(nc_sock_t *ncsock)
-{
- int sock_listen, sock_accept, timeout = ncsock->timeout;
- debug_v(("core_tcp_listen(ncsock=%p)", (void *)ncsock));
-
- sock_listen = netcat_socket_new_listen(PF_INET, &ncsock->local_host.iaddrs[0],
- ncsock->local_port.netnum);
- if (sock_listen < 0)
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("Couldn't setup listening socket (err=%d)"), sock_listen);
-
- /* if the port was set to 0 this means that it is assigned randomly by the
- OS. Find out which port they assigned to us. */
- if (ncsock->local_port.num == 0) {
- int ret;
- struct sockaddr_in myaddr;
- unsigned int myaddr_len = sizeof(myaddr);
-
- ret = getsockname(sock_listen, (struct sockaddr *)&myaddr, &myaddr_len);
- if (ret < 0) {
- close(sock_listen);
- return -1;
- }
- netcat_getport(&ncsock->local_port, NULL, ntohs(myaddr.sin_port));
- }
-
- ncprint(NCPRINT_VERB2, _("Listening on %s"),
- netcat_strid(&ncsock->local_host, &ncsock->local_port));
- while (TRUE) {
- struct sockaddr_in my_addr;
- unsigned int my_len = sizeof(my_addr); /* this *IS* socklen_t */
-
- sock_accept = netcat_socket_accept(sock_listen, timeout);
- /* reset the timeout to the "use remaining time" value (see network.c file)
- if it exited with timeout we also return this function, so losing the
- original value is not a bad thing. */
- timeout = -1;
-
- /* failures in netcat_socket_accept() cause this function to return */
- if (sock_accept < 0)
- return -1;
-
- /* FIXME: i want a library function like netcat_peername() that fetches it
- and resolves with netcat_resolvehost(). */
- getpeername(sock_accept, (struct sockaddr *)&my_addr, &my_len);
-
- /* if a remote address (and optionally some ports) have been specified we
- assume it as the only ip and port that it is allowed to connect to
- this socket */
-
- if ((ncsock->host.iaddrs[0].s_addr && memcmp(&ncsock->host.iaddrs[0],
- &my_addr.sin_addr, sizeof(ncsock->host.iaddrs[0]))) ||
- (netcat_flag_count() && !netcat_flag_get(ntohs(my_addr.sin_port)))) {
- ncprint(NCPRINT_VERB2, _("Unwanted connection from %s:%hu (refused)"),
- netcat_inet_ntop(&my_addr.sin_addr), ntohs(my_addr.sin_port));
- goto refuse;
- }
- ncprint(NCPRINT_VERB1, _("Connection from %s:%hu"),
- netcat_inet_ntop(&my_addr.sin_addr), ntohs(my_addr.sin_port));
-
- /* with zero I/O mode we don't really accept any connection */
- if (opt_zero)
- goto refuse;
-
- /* we have got our socket, now exit the loop */
- break;
-
- refuse:
- shutdown(sock_accept, 2);
- close(sock_accept);
- continue;
- } /* end of infinite accepting loop */
-
- /* we don't need a listening socket anymore */
- close(sock_listen);
- return sock_accept;
-} /* end of core_tcp_listen() */
-
-/* ... */
-
-int core_connect(nc_sock_t *ncsock)
-{
- assert(ncsock);
-
- if (ncsock->proto == NETCAT_PROTO_TCP)
- return ncsock->fd = core_tcp_connect(ncsock);
- else if (ncsock->proto == NETCAT_PROTO_UDP)
- return ncsock->fd = core_udp_connect(ncsock);
- else
- abort();
-
- return -1;
-}
-
-/* ... */
-
-int core_listen(nc_sock_t *ncsock)
-{
- assert(ncsock);
-
- if (ncsock->proto == NETCAT_PROTO_TCP)
- return ncsock->fd = core_tcp_listen(ncsock);
- else if (ncsock->proto == NETCAT_PROTO_UDP)
- return ncsock->fd = core_udp_listen(ncsock);
- else
- abort();
-
- return -1;
-}
-
-/* handle stdin/stdout/network I/O. */
-
-int core_readwrite(nc_sock_t *nc_main, nc_sock_t *nc_slave)
-{
- int fd_stdin, fd_stdout, fd_sock, fd_max;
- int read_ret, write_ret;
- unsigned char buf[1024];
- bool inloop = TRUE;
- fd_set ins, outs;
- struct timeval delayer;
- assert(nc_main && nc_slave);
-
- debug_v(("core_readwrite(nc_main=%p, nc_slave=%p)", (void *)nc_main,
- (void *)nc_slave));
-
- /* set the actual input and output fds and find out the max fd + 1 */
- fd_sock = nc_main->fd;
- assert(fd_sock >= 0);
-
- /* if the domain is unspecified, it means that this is the standard I/O */
- if (nc_slave->domain == PF_UNSPEC) {
- fd_stdin = STDIN_FILENO;
- fd_stdout = STDOUT_FILENO;
- }
- else {
- fd_stdin = fd_stdout = nc_slave->fd;
- assert(fd_stdin >= 0);
- }
- fd_max = 1 + (fd_stdin > fd_sock ? fd_stdin : fd_sock);
- delayer.tv_sec = 0;
- delayer.tv_usec = 0;
-
- /* use the internal signal handler */
- signal_handler = FALSE;
-
- while (inloop) {
- bool call_select = TRUE;
- struct sockaddr_in recv_addr; /* only used by UDP proto */
- unsigned int recv_len = sizeof(recv_addr);
-
- /* if we received an interrupt signal break this function */
- if (got_sigint) {
- got_sigint = FALSE;
- break;
- }
- /* if we received a terminating signal we must terminate */
- if (got_sigterm)
- break;
-
- /* reset the ins and outs events watch because some changes could happen */
- FD_ZERO(&ins);
- FD_ZERO(&outs);
-
- /* if the receiving queue is not empty it means that something bad is
- happening (for example the target sending queue is delaying the output
- and so requires some more time to free up. */
- if (nc_main->recvq.len == 0) {
- debug_v(("watching main sock for incoming data (recvq is empty)"));
- FD_SET(fd_sock, &ins);
- }
- else
- call_select = FALSE;
-
- /* same thing for the other socket */
- if (nc_slave->recvq.len == 0) { /* FIXME: call_select = false but could call it
- anyway and one of them could be set.. so what happens? */
- debug_v(("watching slave sock for incoming data (recvq is empty)"));
- if (use_stdin || (netcat_mode == NETCAT_TUNNEL))
- FD_SET(fd_stdin, &ins);
- }
- else
- call_select = FALSE;
-
- /* now the send queue. There are two cases in which the main sendq is not
- empty. The first one is when we have a delayed output (-i), in which
- case the delayer is not null, and the socket is writable. The second
- case is when the socket buffer is full, so the socket is not writable
- and the delayer is either null or set, depending on the opt_interval
- variable. */
- if (nc_main->sendq.len > 0) {
- if ((delayer.tv_sec == 0) && (delayer.tv_usec == 0)) {
- debug_v(("watching main sock for outgoing availability (there is pending data)"));
- FD_SET(fd_sock, &outs);
- call_select = TRUE;
- }
- }
-
- if (call_select || delayer.tv_sec || delayer.tv_usec) {
- int ret;
-#ifndef USE_LINUX_SELECT
- struct timeval dd_saved;
-
- dd_saved.tv_sec = delayer.tv_sec;
- dd_saved.tv_usec = delayer.tv_usec;
- update_timeval(NULL);
-#endif
-
- debug(("[select] entering with timeout=%d:%d ...", delayer.tv_sec, delayer.tv_usec));
- ret = select(fd_max, &ins, &outs, NULL,
- (delayer.tv_sec || delayer.tv_usec ? &delayer : NULL));
-
-#ifndef USE_LINUX_SELECT
- delayer.tv_sec = dd_saved.tv_sec;
- delayer.tv_usec = dd_saved.tv_usec;
- update_timeval(&delayer);
-#endif
-
- if (ret < 0) { /* something went wrong (maybe a legal signal) */
- if (errno == EINTR)
- goto handle_signal;
- perror("select(core_readwrite)");
- exit(EXIT_FAILURE);
- }
- else if (ret == 0) { /* timeout expired */
- delayer.tv_sec = 0;
- delayer.tv_usec = 0;
- }
-
- call_select = TRUE;
- debug(("ret=%d\n", ret));
- }
-
- /* reading from stdin the incoming data. The data is currently in the
- kernel's receiving queue, and in this session we move that data to our
- own receiving queue, located in the socket object. We can be sure that
- this queue is empty now because otherwise this fd wouldn't have been
- watched. */
- if (call_select && FD_ISSET(fd_stdin, &ins)) {
- read_ret = read(fd_stdin, buf, sizeof(buf));
- debug_dv(("read(stdin) = %d", read_ret));
-
- if (read_ret < 0) {
- perror("read(stdin)");
- exit(EXIT_FAILURE);
- }
- else if (read_ret == 0) {
- /* when we receive EOF and this is a tunnel say goodbye, otherwise
- it means that stdin has finished its input. */
- if ((netcat_mode == NETCAT_TUNNEL) || opt_eofclose) {
- debug_v(("EOF Received from stdin! (exiting from loop..)"));
- inloop = FALSE;
- }
- else {
- debug_v(("EOF Received from stdin! (removing from lookups..)"));
- use_stdin = FALSE;
- }
- }
- else {
- /* we can overwrite safely since if the receive queue is busy this fd
- is not watched at all. */
- nc_slave->recvq.len = read_ret;
- nc_slave->recvq.head = NULL;
- nc_slave->recvq.pos = buf;
- }
- }
-
- /* for optimization reasons we have a common buffer for both receiving
- queues, because of this, handle the data now so the buffer is available
- for the other socket events. */
- if (nc_slave->recvq.len > 0) {
- nc_buffer_t *my_recvq = &nc_slave->recvq;
- nc_buffer_t *rem_sendq = &nc_main->sendq;
- debug_v(("there are %d data bytes in slave->recvq", my_recvq->len));
-
- /* if the remote send queue is empty, move there the entire data block */
- if (rem_sendq->len == 0) {
- debug_v((" moved %d data bytes from slave->recvq to main->sendq", my_recvq->len));
- memcpy(rem_sendq, my_recvq, sizeof(*rem_sendq));
- memset(my_recvq, 0, sizeof(*my_recvq));
- }
- else if (!my_recvq->head) {
- /* move the data block in a dedicated allocated space */
- debug_v((" reallocating %d data bytes in slave->recvq", my_recvq->len));
- my_recvq->head = malloc(my_recvq->len);
- memcpy(my_recvq->head, my_recvq->pos, my_recvq->len);
- my_recvq->pos = my_recvq->head;
- }
- }
-
- /* now handle the nc_slave sendq because of the same reason as above. There
- could be a common buffer that moves around the queues, so if this is the case
- handle it so that it can be reused. If we must delay it some more, copy it
- in a dynamically allocated space. */
- if (nc_main->sendq.len > 0) {
- unsigned char *data = nc_main->sendq.pos;
- int data_len = nc_main->sendq.len;
- nc_buffer_t *my_sendq = &nc_main->sendq;
-
- debug_v(("there are %d data bytes in main->sendq", my_sendq->len));
-
- /* we have a delayed output, but at this point we might have the
- send queue pointing to a stack buffer. In this case, allocate a
- new buffer and copy the data there for the buffered output. */
- if (opt_interval) {
- int i = 0;
-
- if (delayer.tv_sec || delayer.tv_usec)
- goto skip_sect; /* the delay is not yet over! */
-
- /* find the newline character. We are going to output the first line
- immediately while we allocate and safe the rest of the data for a
- later output. */
- while (i < data_len)
- if (data[i++] == '\n')
- break;
-
- data_len = i;
- delayer.tv_sec = opt_interval;
- }
-
- write_ret = write(fd_sock, data, data_len);
- if (write_ret < 0) {
- if (errno == EAGAIN)
- write_ret = 0; /* write would block, append it to select */
- else {
- perror("write(net)");
- exit(EXIT_FAILURE);
- }
- }
-
- /* FIXME: fix the below unhandled exception, and find a way to delay the
- * tries to call write(2) in case of EAGAIN, i think 100ms would be fine
- * for most systems. A too high value would not use all the bandwidth on
- * bigger installations, while a too small value would eat cpu with
- * kernel overhead. */
-
- bytes_sent += write_ret; /* update statistics */
- debug_dv(("write(net) = %d (buf=%p)", write_ret, (void *)data));
-
- if (write_ret < data_len) {
- debug_v(("Damn! I wanted to send to sock %d bytes but it only sent %d",
- data_len, write_ret));
- data_len = write_ret;
- }
-
- /* if the option is set, hexdump the sent data */
- if (opt_hexdump) {
-#ifndef USE_OLD_HEXDUMP
- fprintf(output_fp, "Sent %u bytes to the socket\n", write_ret);
-#endif
- netcat_fhexdump(output_fp, '>', data, data_len);
- }
-
- /* update the queue */
- my_sendq->len -= data_len;
- my_sendq->pos += data_len;
-
- skip_sect:
- debug_v(("there are %d data bytes left in the queue", my_sendq->len));
- if (my_sendq->len == 0) {
- free(my_sendq->head);
- memset(my_sendq, 0, sizeof(*my_sendq));
- }
- else if (!my_sendq->head) {
- my_sendq->head = malloc(my_sendq->len);
- memcpy(my_sendq->head, my_sendq->pos, my_sendq->len);
- my_sendq->pos = my_sendq->head;
- }
-
- } /* end of reading from stdin section */
-
- /* reading from the socket (net). */
- if (call_select && FD_ISSET(fd_sock, &ins)) {
- if ((nc_main->proto == NETCAT_PROTO_UDP) && opt_zero) {
- memset(&recv_addr, 0, sizeof(recv_addr));
- /* this allows us to fetch packets from different addresses */
- read_ret = recvfrom(fd_sock, buf, sizeof(buf), 0,
- (struct sockaddr *)&recv_addr, &recv_len);
- /* when recvfrom() call fails, recv_addr remains untouched */
- debug_dv(("recvfrom(net) = %d (address=%s:%d)", read_ret,
- netcat_inet_ntop(&recv_addr.sin_addr), ntohs(recv_addr.sin_port)));
- }
- else {
- /* common file read fallback */
- read_ret = read(fd_sock, buf, sizeof(buf));
- debug_dv(("read(net) = %d", read_ret));
- }
-
- if (read_ret < 0) {
- perror("read(net)");
- exit(EXIT_FAILURE);
- }
- else if (read_ret == 0) {
- debug_v(("EOF Received from the net"));
- inloop = FALSE;
- }
- else {
- nc_main->recvq.len = read_ret;
- nc_main->recvq.head = NULL;
- nc_main->recvq.pos = buf;
- }
- }
-
- /* handle net receiving queue */
- if (nc_main->recvq.len > 0) {
- nc_buffer_t *my_recvq = &nc_main->recvq;
- nc_buffer_t *rem_sendq = &nc_slave->sendq;
-
- /* check for telnet codes (if enabled). Note that the buffered output
- interval does NOT apply to telnet code answers */
- if (opt_telnet)
- netcat_telnet_parse(nc_main);
-
- /* the telnet parsing could have returned 0 chars! */
- if (my_recvq->len > 0) {
- /* if the remote send queue is empty, move there the entire data block */
- if (rem_sendq->len == 0) {
- memcpy(rem_sendq, my_recvq, sizeof(*rem_sendq));
- memset(my_recvq, 0, sizeof(*my_recvq));
- }
- else if (!my_recvq->head) {
- /* move the data block in a dedicated allocated space */
- my_recvq->head = malloc(my_recvq->len);
- memcpy(my_recvq->head, my_recvq->pos, my_recvq->len);
- my_recvq->pos = my_recvq->head;
- }
- }
- }
-
- if (nc_slave->sendq.len > 0) {
- unsigned char *data = nc_slave->sendq.pos;
- int data_len = nc_slave->sendq.len;
- nc_buffer_t *my_sendq = &nc_slave->sendq;
-
- write_ret = write(fd_stdout, data, data_len);
- bytes_recv += write_ret; /* update statistics */
- debug_dv(("write(stdout) = %d", write_ret));
-
- if (write_ret < 0) {
- perror("write(stdout)");
- exit(EXIT_FAILURE);
- }
-
- /* FIXME: unhandled exception */
- assert((write_ret > 0) && (write_ret <= data_len));
-
- if (write_ret < data_len) {
- debug_v(("Damn! I wanted to send to stdout %d bytes but it only sent %d",
- data_len, write_ret));
- data_len = write_ret;
- }
-
- /* if option is set, hexdump the received data */
- if (opt_hexdump) {
-#ifndef USE_OLD_HEXDUMP
- if ((nc_main->proto == NETCAT_PROTO_UDP) && opt_zero)
- fprintf(output_fp, "Received %d bytes from %s:%d\n", write_ret,
- netcat_inet_ntop(&recv_addr.sin_addr), ntohs(recv_addr.sin_port));
- else
- fprintf(output_fp, "Received %d bytes from the socket\n", write_ret);
-#endif
- netcat_fhexdump(output_fp, '<', data, write_ret);
- }
-
- /* update the queue */
- my_sendq->len -= data_len;
- my_sendq->pos += data_len;
-
- debug_v(("there are %d data bytes left in the queue", my_sendq->len));
- if (my_sendq->len == 0) {
- free(my_sendq->head);
- memset(my_sendq, 0, sizeof(*my_sendq));
- }
- else if (!my_sendq->head) {
- my_sendq->head = malloc(my_sendq->len);
- memcpy(my_sendq->head, my_sendq->pos, my_sendq->len);
- my_sendq->pos = my_sendq->head;
- }
- } /* end of reading from the socket section */
-
- handle_signal: /* FIXME: i'm not sure this is the right place */
- if (got_sigusr1) {
- debug_v(("LOCAL printstats!"));
- netcat_printstats(TRUE);
- got_sigusr1 = FALSE;
- }
- continue;
- } /* end of while (inloop) */
-
- /* we've got an EOF from the net, close the sockets */
- shutdown(fd_sock, SHUT_RDWR);
- close(fd_sock);
- nc_main->fd = -1;
-
- /* close the slave socket only if it wasn't a simulation */
- if (nc_slave->domain != PF_UNSPEC) {
- shutdown(fd_stdin, SHUT_RDWR);
- close(fd_stdin);
- nc_slave->fd = -1;
- }
-
- /* restore the extarnal signal handler */
- signal_handler = TRUE;
-
- return 0;
-} /* end of core_readwrite() */
diff --git a/src/discover.c b/src/discover.c
deleted file mode 100644
index ecce8d4..0000000
--- a/src/discover.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/* AVRemote
-
- (c) 2011 Nederlands Instituut voor Mediakunst (NIMk)
- 2011 Denis Roio <jaromil@nimk.nl>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>
-
-*/
-
-#include <config.h>
-
-#include <stdio.h>
-#include <string.h>
-
-#include <miniwget.h>
-#include <miniupnpc.h>
-#include <upnpcommands.h>
-#include <upnperrors.h>
-
-#include <avremote.h>
-
-
-int upnp_discover(upnp_t *upnp)
-{
- const char * rootdescurl = 0;
- const char * multicastif = 0;
- const char * minissdpdpath = 0;
- char lanaddr[64];
- struct UPNPDev *devlist = 0;
- struct UPNPDev *dev;
- struct UPNPUrls urls;
- struct IGDdatas data;
- int r, err;
- int num = 0;
-
- // damn programmers who change API prototypes in headers
- // without versioning.
-
-/* #ifdef UPNPDISCOVER_SUCCESS */
- devlist = upnpDiscover(1000, multicastif, minissdpdpath, 0, 0, &err);
-/* #else */
-/* devlist = upnpDiscover(1000, multicastif, minissdpdpath, 0); */
-/* #endif */
-
- r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
- if (!r) {
- fprintf(stderr,"no valid UPnP devices found\n");
-
- } else if (r == 3) { // 3 = an UPnP root device has been found (not an IGD)
-
- dev = devlist;
- for( dev = devlist; dev; dev = dev->pNext, num++) {
-
- // parse out ip and port from url
- char ip[MAX_HOSTNAME_SIZE];
- char port[64];
- char tmp[512];
- char *p, *pp;
-
- memcpy(tmp,dev->descURL,511);
- p = tmp;
-
- // ip
- do p+=2; while(*p != '/'); p++;
- pp = p; do pp++; while(*pp != ':'); *pp = 0;
- snprintf(ip,MAX_HOSTNAME_SIZE-1,"%s",p);
-
- // port
- p = pp+1; pp = p;
- do pp++; while(*pp != '/'); *pp = 0;
- snprintf(port,63,"%s",p);
-
- fprintf(stderr,"%s\t%s\t%s\t%s\n", dev->st, dev->descURL, ip, port);
-
- if(!num) { // first found
- sscanf(port, "%u", &upnp->port);
- snprintf(upnp->hostname, MAX_HOSTNAME_SIZE-1, "%s", ip);
- }
-
- }
-
- FreeUPNPUrls(&urls);
-
- }
- freeUPNPDevlist(devlist); devlist = 0;
-
- return(num);
-}
-
diff --git a/src/discover.h b/src/discover.h
deleted file mode 100644
index 40bd95d..0000000
--- a/src/discover.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* AVRemote
-
- (c) 2011 Nederlands Instituut voor Mediakunst (NIMk)
- 2011 Denis Roio <jaromil@nimk.nl>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>
-
-*/
-
-#ifdef USE_UPNP
-
-int upnp_discover();
-
-#endif
diff --git a/src/flagset.c b/src/flagset.c
deleted file mode 100644
index 442b634..0000000
--- a/src/flagset.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * flagset.c -- very big flags array handler
- * Part of the GNU netcat project
- *
- * Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- * Copyright (C) 2002 Giovanni Giacobbi
- *
- * $Id: flagset.c,v 1.7 2003/12/10 16:18:07 themnemonic Exp $
- */
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "netcat.h"
-
-static char *flagset = NULL;
-static size_t flagset_len = 0;
-
-/* Initializes the flagset to the given len. */
-
-bool netcat_flag_init(unsigned int len)
-{
- /* safe double-init */
- if (flagset)
- return TRUE;
-
- /* calculates the block len needed */
- len++; /* the first bit is reserved (FIXME?) */
- flagset_len = (size_t) (len / 8) + (len % 8 ? 1 : 0);
- if (flagset_len == 0) {
- free(flagset);
- flagset = NULL;
- return TRUE;
- }
-
- /* since we may be asking a big amount of memory, this call could fail */
- flagset = malloc(flagset_len);
- if (!flagset)
- return FALSE;
-
- memset(flagset, 0, flagset_len);
- return TRUE;
-}
-
-/* Sets the specified flag `port' to the specified boolean value `flag'. */
-
-void netcat_flag_set(unsigned short port, bool flag)
-{
- register char *p = flagset + (int) (port / 8);
- register int offset = port % 8;
-
- assert(flagset);
- assert(port < (flagset_len * 8));
- if (flag)
- *p |= 1 << offset;
- else
- *p &= ~(1 << offset);
-}
-
-/* Returns the boolean value of the specified flag `port' */
-
-bool netcat_flag_get(unsigned short port)
-{
- register char *p = flagset + (int) (port / 8);
-
- assert(flagset);
- assert(port < (flagset_len * 8));
- if (*p & (1 << (port % 8)))
- return TRUE;
- else
- return FALSE;
-}
-
-/* Finds the next bit set after the specified position.
- Returns the position of the next bit if any, otherwise it returns 0 */
-
-unsigned short netcat_flag_next(unsigned short port)
-{
- register int offset, pos = (int) (++port / 8);
-
- assert(flagset);
- assert(port < (flagset_len * 8));
- if (port == 0) /* just invalid data */
- return 0;
-
- /* the given port could be inside one byte, so we first need to check each
- single bit after this one in order to complete the byte. After that, we
- can start with the fast byte check. */
- while ((offset = port % 8)) {
- if (flagset[pos] & (1 << offset))
- return port;
- if (port == 65535)
- return 0;
- port++;
- }
-
- pos = (int) (port / 8); /* update the byte position */
-
- /* fast checking. leaves the port variable set to the the beginning of the
- next block containing at least one bit set, OR to the beginning of the
- LAST block. */
- while ((flagset[pos] == 0) && (port < 65528)) { /* FIXME */
- pos++;
- port += 8;
- }
-
- /* parse this last byte carefully, but we are NOT sure that there is at
- least one bit set */
- offset = 0;
- do {
- if ((flagset[pos] & (1 << offset++)))
- return port;
- } while (port++ < 65535); /* FIXME */
-
- return 0;
-}
-
-/* Returns the number of flags that are set to TRUE in the full flagset */
-
-int netcat_flag_count(void)
-{
- register char c;
- register int i;
- int ret = 0;
-
- assert(flagset);
- /* scan the flagset for set bits, if found, it counts them */
- for (i = 0; i < flagset_len; i++) {
- c = flagset[i]; /* if c is 0, all these 8 bits are FALSE */
- while (c) {
- /* FIXME Ok, here it comes the big trouble. We are in the following
- situation:
- ret = 0
- c = 1234 5678
-
- We will loop and shift bits away until the number `c' becomes 0 (and
- it will of course become 0, soon or late).
-
- Assumed that the bit number 1 is the sign, and that we will shift the
- bit 1 (or the bit that takes its place later) until the the most right,
- WHY it has to keep the wrong sign? */
- ret -= (c >> 7);
- c <<= 1;
- }
- }
-
- return ret;
-}
-
-/* Returns the position of a random flag set to TRUE. The returned flag is
- then reset, so you can call netcat_flag_rand() repeatedly to get all the
- flags set in a random order. If there are no other flags set the function
- returns 0. */
-
-unsigned short netcat_flag_rand(void)
-{
- int rand, randmax = netcat_flag_count() - 1;
- unsigned short ret = 0;
-
- assert(flagset);
-
- /* if there are no other flags set */
- if (randmax < 0)
- return 0;
-
-#ifdef USE_RANDOM
- /* fetch a random number from the high-order bits */
- rand = 1 + (int) ((float)randmax * RAND() / (RAND_MAX + 1.0));
-#else
-# ifdef __GNUC__
-# warning "random routines not found, removed random support"
-# endif
- rand = 1; /* simulates a random number */
-#endif
-
- /* loop until we find the specified flag */
- while (rand--)
- ret = netcat_flag_next(ret);
-
- /* don't return this same flag again */
- netcat_flag_set(ret, FALSE);
- return ret;
-}
diff --git a/src/handshake.cpp b/src/handshake.cpp
deleted file mode 100644
index 8dd5967..0000000
--- a/src/handshake.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/* Simple handshake on LAN program using TCP broadcast (PGM)
-
- (c) 2012 Denis Roio <jaromil@dyne.org>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>
-
-*/
-
-#include <zmq.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <sys/types.h>
-#include <ifaddrs.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#define ETHDEV "eth0"
-#define PGMPORT "5555"
-
-int main (int argc, char **argv)
-{
- void *context = zmq_init (1);
- void *sock_in = NULL;
- void *sock_out = NULL;
- int request_nbr;
- zmq_msg_t request, reply;
- char message[256];
- char pgmaddr[64];
- char **listeners = NULL;
- int listindex = 0;
- int listmax = 0;
- char res[128];
-
- // discover own IP address
- struct ifaddrs * ifAddrStruct=NULL;
- struct ifaddrs * ifa=NULL;
- void * tmpAddrPtr=NULL;
- char IPv4[24];
- printf("Handshake on LAN\n");
- getifaddrs(&ifAddrStruct);
-
- pgmaddr[0] = NULL; // zero if iface not found
-
- for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) {
- if (ifa ->ifa_addr->sa_family==AF_INET) { // check it is IP4
- // is a valid IP4 Address
- tmpAddrPtr=&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
- char addressBuffer[INET_ADDRSTRLEN];
- inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
- // printf("%s IP Address %s\n", ifa->ifa_name, addressBuffer);
- if( strcmp(ifa->ifa_name, ETHDEV) == 0) {
- strncpy(IPv4, addressBuffer, 16);
- snprintf(pgmaddr,63,"pgm://%s:%s",ifa->ifa_name, PGMPORT);
- }
- }
- }
- if (ifAddrStruct!=NULL) freeifaddrs(ifAddrStruct);
-
- if(!pgmaddr[0]) {
- printf("Error: ethernet interface %s is not configured\n",ETHDEV);
- exit(1);
- }
-
- if(argc!=3) {
- printf("Error: need two arguments: [ offer | listen ] [ total number of peers ]\n");
- printf("Example: handshake offer 3\n");
- exit(1);
- }
-
- // create offer socket
- sock_out = zmq_socket (context, ZMQ_PUB);
- zmq_connect(sock_out, pgmaddr);
-
- // create listen socket
- sock_in = zmq_socket (context, ZMQ_SUB);
- zmq_bind (sock_in, pgmaddr);
-
-
- if(strcmp(argv[1],"offer")==0) {
- //////////////////////////////
- printf ("Offering on %s from address %s\n",pgmaddr, IPv4);
-
- sscanf(argv[2],"%u",&listmax); // number of desired peers
- listmax--; // we count outrselves in
- printf("looking to connect %u peers\n",listmax);
- // allocate space for listener array
- listeners = (char**) calloc(listmax,sizeof(char*));
- for(int i; i<listmax; i++) listeners[i] = (char*)calloc(16, sizeof(char));
-
- // offer subscribes to all broadcasts by default
- // somehow listening to ACK only doesn't works
- zmq_setsockopt(sock_in,ZMQ_SUBSCRIBE,"",0);
- snprintf(message,255,"OFFER;%s;",IPv4);
-
- while(1) {
-
- zmq_msg_init_size (&request, strlen(message));
- memcpy (zmq_msg_data (&request), message, strlen(message));
- // printf ("Sending offer...\n", request_nbr);
- zmq_send (sock_out, &request, 0);
- zmq_msg_close (&request);
-
- sleep(1);
-
- zmq_msg_init (&reply);
- zmq_recv (sock_in, &reply, 0);
- // printf ("Received response\n");
- snprintf(res,127,"%s",zmq_msg_data(&reply));
- zmq_msg_close (&reply);
-
- // parse the response and if ACK insert it in uniq list
- if( strncmp(res,"ACK",3) == 0) {
- int c;
- char *p, *pp;
- // quick and secure string parsing
- p = res; while(*p != ';') p++; p++;
- pp = p; while(*pp != ';') pp++; *pp='\0';
-
- // *p has the ip string
- for(c=0; c<listindex; c++)
- if(strncmp(listeners[c], p, 16) == 0)
- break; // found a duplicate
- if(c==listindex) { // there was no duplicate
- snprintf(listeners[c], 16, "%s", p);
- printf("New listener: %s\n",p);
- listindex++;
- }
- if(listindex==listmax) { // goal reached
- printf("Sending ready signals to listeners:\n");
- ///////////////////////////////////////////////
- for(c=0;c<listmax;c++) {
- char tmpaddr[256];
- snprintf(tmpaddr,255, "tcp://%s:%s",listeners[c],PGMPORT);
- printf (" %s\n", tmpaddr);
- zmq_connect(sock_out, tmpaddr);
- zmq_msg_init_size (&request, 5);
- memcpy (zmq_msg_data (&request), "READY", 5);
- zmq_send (sock_out, &request, 0);
- zmq_msg_close (&request);
- }
- break; // break offer loop
- }
-
- } // if ACK response
-
- } // offer while loop
-
- } else if(strcmp(argv[1],"listen")==0) {
-
- printf ("Listening on %s from address %s\n",pgmaddr, IPv4);
-
- // listen subscribes only to offers and ready
- zmq_setsockopt(sock_in,ZMQ_SUBSCRIBE,"OFFER",5);
- zmq_setsockopt(sock_in,ZMQ_SUBSCRIBE,"READY",5);
-
-
- snprintf(message,255,"ACK;%s;",IPv4);
-
- while (1) {
- // Wait for next request from client
- zmq_msg_init (&request);
- zmq_recv (sock_in, &request, 0);
-
- snprintf(res,127,"%s",zmq_msg_data(&request));
- zmq_msg_close (&request);
- if(strncmp(res,"READY",5) == 0) {
- printf ("Received ready signal\n");
- break;
- }
- sleep (1);
-
- // Send reply back to client
- zmq_msg_init_size (&reply, strlen(message));
- memcpy (zmq_msg_data (&reply), message, strlen(message));
- zmq_send (sock_out, &reply, 0);
- zmq_msg_close (&reply);
-
- }
-
- } else {
- printf("Command not recognized: %s\n",argv[1]);
-
- }
-
- printf("Clean exit.\n");
-
- if(listeners) {
- for(int c; c<listmax; c++)
- free(listeners[c]);
- free(listeners);
- }
-
- if(sock_out) zmq_close (sock_out);
- if(sock_in) zmq_close (sock_in);
-
- zmq_term (context);
-
- exit(0);
-}
diff --git a/src/hdsync_cli.cpp b/src/hdsync_cli.cpp
index f0f591c..886772a 100644
--- a/src/hdsync_cli.cpp
+++ b/src/hdsync_cli.cpp
@@ -37,7 +37,6 @@
#include <arpa/inet.h>
#include <avremote.h>
-#include <parsers.h>
#include <zmq.h>
#include <zmq_utils.h>
@@ -60,8 +59,6 @@ int dryrun = 0;
int chanID = 0;
int chanTOT = 0;
-// upnp reply parser
-parser_f *parser = NULL;
// info on peers
upnp_t **peers;
diff --git a/src/hwclient.cpp b/src/hwclient.cpp
deleted file mode 100644
index ff4c883..0000000
--- a/src/hwclient.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// Hello World client
-// Connects REQ socket to tcp://localhost:5555
-// Sends "Hello" to server, expects "World" back
-//
-#include <zmq.h>
-#include <string.h>
-#include <stdio.h>
-#include <unistd.h>
-
-int main (void)
-{
- void *context = zmq_init (1);
-
- // Socket to talk to server
- printf ("Connecting to hello world server...\n");
- void *requester = zmq_socket (context, ZMQ_REQ);
- zmq_connect (requester, "tcp://10.2.4.132:5555");
-
- int request_nbr;
- for (request_nbr = 0; request_nbr != 10; request_nbr++) {
- zmq_msg_t request;
- zmq_msg_init_size (&request, 5);
- memcpy (zmq_msg_data (&request), "Hello", 5);
- printf ("Sending Hello %d...\n", request_nbr);
- zmq_send (requester, &request, 0);
- zmq_msg_close (&request);
-
- zmq_msg_t reply;
- zmq_msg_init (&reply);
- zmq_recv (requester, &reply, 0);
- printf ("Received World %d\n", request_nbr);
- zmq_msg_close (&reply);
- }
- zmq_close (requester);
- zmq_term (context);
- return 0;
-}
diff --git a/src/hwserver.cpp b/src/hwserver.cpp
deleted file mode 100644
index c71d789..0000000
--- a/src/hwserver.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// Hello World server
-// Binds REP socket to tcp://*:5555
-// Expects "Hello" from client, replies with "World"
-//
-#include <zmq.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-
-int main (void)
-{
- void *context = zmq_init (1);
-
- // Socket to talk to clients
- void *responder = zmq_socket (context, ZMQ_REP);
- zmq_bind (responder, "tcp://*:5555");
-
- while (1) {
- // Wait for next request from client
- zmq_msg_t request;
- zmq_msg_init (&request);
- zmq_recv (responder, &request, 0);
- printf ("Received Hello\n");
- zmq_msg_close (&request);
-
- // Do some 'work'
- sleep (1);
-
- // Send reply back to client
- zmq_msg_t reply;
- zmq_msg_init_size (&reply, 5);
- memcpy (zmq_msg_data (&reply), "World", 5);
- zmq_send (responder, &reply, 0);
- zmq_msg_close (&reply);
- }
- // We never get here but if we did, this would be how we end
- zmq_close (responder);
- zmq_term (context);
- return 0;
-}
diff --git a/src/intl.h b/src/intl.h
deleted file mode 100644
index 3128aa5..0000000
--- a/src/intl.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * intl.h -- main i18n support header file
- * Part of the GNU netcat project
- *
- * Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- * Copyright (C) 2002 Giovanni Giacobbi
- *
- * $Id: intl.h,v 1.6 2002/10/03 10:25:16 themnemonic Exp $
- */
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- ***************************************************************************/
-
-#ifdef ENABLE_NLS
-#include <libintl.h>
-
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#else
-#error You must have locale.h in your system
-#endif /* HAVE_LOCALE_H */
-
-/* Our dear (and very common) gettext macros */
-#define _(String) gettext(String)
-#define N_(String) String
-#define PL_(String1, String2, n) ngettext((String1), (String2), (n))
-
-#else
-
-/* Disabled NLS.
- The casts to 'const char *' serve the purpose of producing warnings
- for invalid uses of the value returned from these functions.
- On pre-ANSI systems without 'const', the config.h file is supposed to
- contain "#define const". */
-
-#define textdomain(Domainname) ((const char *) (Domainname))
-#define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname))
-#define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset))
-
-#define _(String) (String)
-#define N_(String) String
-#define PL_(String1, String2, n) ((n) == 1 ? (String1) : (String2))
-
-#endif /* ENABLE_NLS */
diff --git a/src/misc.c b/src/misc.c
deleted file mode 100644
index 1ff39d1..0000000
--- a/src/misc.c
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * misc.c -- contains generic purposes routines
- * Part of the GNU netcat project
- *
- * Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- * Copyright (C) 2002 - 2004 Giovanni Giacobbi
- *
- * $Id: misc.c,v 1.37 2004/01/03 16:42:07 themnemonic Exp $
- */
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "netcat.h"
-
-/* Hexdump `datalen' bytes starting at `data' to the file pointed to by `stream'.
- If the given block generates a partial line it's rounded up with blank spaces.
- This function was written by Giovanni Giacobbi for The GNU Netcat project,
- credits must be given for any use of this code outside this project */
-
-int netcat_fhexdump(FILE *stream, char c, const void *data, size_t datalen)
-{
- size_t pos;
- char buf[80], *ascii_dump, *p = NULL;
- int flag = 0;
-
-#ifndef USE_OLD_HEXDUMP
- buf[78] = 0;
- ascii_dump = &buf[62];
-#else
- buf[77] = 0;
- ascii_dump = &buf[61];
-#endif
-
- for (pos = 0; pos < datalen; pos++) {
- unsigned char x;
-
- /* save the offset */
- if ((flag = pos % 16) == 0) {
- /* we are at the beginning of the line, reset output buffer */
- p = buf;
-#ifndef USE_OLD_HEXDUMP
- p += sprintf(p, "%08X ", (unsigned int) pos);
-#else
- p += sprintf(p, "%c %08X ", c, (unsigned int) pos);
-#endif
- }
-
- x = *((unsigned char *)((unsigned char *)data + pos));
-#ifndef USE_OLD_HEXDUMP
- p += sprintf(p, "%02hhX ", x);
-#else
- p += sprintf(p, "%02hhx ", x);
-#endif
-
- if ((x < 32) || (x > 126))
- ascii_dump[flag] = '.';
- else
- ascii_dump[flag] = x;
-
-#ifndef USE_OLD_HEXDUMP
- if ((pos + 1) % 4 == 0)
- *p++ = ' ';
-#endif
-
- /* if the offset is 15 then we go for the newline */
- if (flag == 15) {
-#ifdef USE_OLD_HEXDUMP
- *p++ = '#';
- *p++ = ' ';
-#endif
- fprintf(stream, "%s\n", buf);
- }
- }
-
- /* if last line was incomplete (len % 16) != 0, complete it */
- for (pos = datalen; (flag = pos % 16); pos++) {
- ascii_dump[flag] = ' ';
- strcpy(p, " ");
- p += 3;
-
-#ifndef USE_OLD_HEXDUMP
- if (((pos + 1) % 4) == 0)
- *p++ = ' ';
-#endif
-
- if (flag == 15) {
-#ifdef USE_OLD_HEXDUMP
- *p++ = '#';
- *p++ = ' ';
-#endif
- fprintf(stream, "%s\n", buf);
- }
- }
-
- fflush(stream);
- return 0;
-}
-
-/* Fills the buffer pointed to by `str' with the formatted value of `number' */
-
-int netcat_snprintnum(char *str, size_t size, unsigned long number)
-{
- char *p = "\0kMGT";
-
- while ((number > 9999) && (*p != 'T')) {
- number = (number + 500) / 1000;
- p++;
- }
- return snprintf(str, size, "%lu%c", number, *p);
-}
-
-/* This is an advanced function for printing normal and error messages for the
- user. It supports various types and flags which are declared in misc.h. */
-
-void ncprint(int type, const char *fmt, ...)
-{
- int flags = type & 0xFF;
- char buf[512], newline = '\n';
- FILE *fstream = stderr; /* output stream */
- va_list args;
-
- /* clear the flags section so we obtain the pure command */
- type &= ~0xFF;
-
- /* return if this requires some verbosity levels and we haven't got it */
- if (!opt_debug) {
- if ((flags & NCPRINT_VERB2) && (opt_verbose < 2))
- goto end;
-
- if ((flags & NCPRINT_VERB1) && (opt_verbose < 1))
- goto end;
- }
-
- /* known flags */
- if (flags & NCPRINT_STDOUT)
- fstream = stdout;
- if (flags & NCPRINT_NONEWLINE)
- newline = 0;
-
- /* from now on, it's very probable that we will need the string formatted,
- so unless we have the NOFMT flag, resolve it */
- if (!(flags & NCPRINT_NOFMT)) {
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- }
- else {
- strncpy(buf, fmt, sizeof(buf));
- buf[sizeof(buf) - 1] = 0;
- }
-
- switch (type) {
- case NCPRINT_NORMAL:
- fprintf(fstream, "%s%c", buf, newline);
- break;
-#ifdef DEBUG
- case NCPRINT_DEBUG:
- if (opt_debug)
- fprintf(fstream, "%s%c", buf, newline);
- else
- return; /* other flags has no effect with this flag */
- break;
- case NCPRINT_DEBUG_V:
- if (opt_debug)
- fprintf(fstream, "(debug) %s%c", buf, newline);
- else
- return; /* other flags has no effect with this flag */
- break;
-#endif
- case NCPRINT_ERROR:
- fprintf(fstream, "%s %s%c", _("Error:"), buf, newline);
- break;
- case NCPRINT_WARNING:
- fprintf(fstream, "%s %s%c", _("Warning:"), buf, newline);
- break;
- case NCPRINT_NOTICE:
- fprintf(fstream, "%s %s%c", _("Notice:"), buf, newline);
- break;
- }
- /* discard unknown types */
-
- /* post-output effects flags */
- if (flags & NCPRINT_DELAY)
- usleep(NCPRINT_WAITTIME);
-
- end:
- /* now resolve the EXIT flag. If this was a verbosity message but we don't
- have the required level, exit anyway. */
- if (flags & NCPRINT_EXIT)
- exit(EXIT_FAILURE);
-}
-
-/* prints statistics to stderr with the right verbosity level. If `force' is
- TRUE, then the verbosity level is overridden and the statistics are printed
- anyway. */
-
-void netcat_printstats(bool force)
-{
- char *p, str_recv[64], str_sent[64];
-
- /* fill in the buffers but preserve the space for adding the label */
- netcat_snprintnum(str_recv, 32, bytes_recv);
- assert(str_recv[0]);
- for (p = str_recv; *(p + 1); p++); /* find the last char */
- if ((bytes_recv > 0) && !isdigit((int)*p))
- snprintf(++p, sizeof(str_recv) - 32, " (%lu)", bytes_recv);
-
- netcat_snprintnum(str_sent, 32, bytes_sent);
- assert(str_sent[0]);
- for (p = str_sent; *(p + 1); p++); /* find the last char */
- if ((bytes_sent > 0) && !isdigit((int)*p))
- snprintf(++p, sizeof(str_sent) - 32, " (%lu)", bytes_sent);
-
- ncprint(NCPRINT_NONEWLINE | (force ? 0 : NCPRINT_VERB2),
- _("Total received bytes: %s\nTotal sent bytes: %s\n"),
- str_recv, str_sent);
-}
-
-/* This is a safe string split function. It will return a valid pointer
- whatever input parameter was used. In normal behaviour, it will return a
- null-terminated string containing the first word of the string pointer to by
- `buf', while the `buf' pointer will be updated to point to the following
- char which may also be a space. Leading spaces are ignored. */
-
-char *netcat_string_split(char **buf)
-{
- register char *o, *r;
-
- if (!buf || (*buf == NULL))
- return *buf = "";
- /* skip all initial spaces */
- for (o = *buf; isspace((int)*o); o++);
- /* save the pointer and move to the next token */
- for (r = o; *o && !isspace((int)*o); o++);
- if (*o)
- *o++ = 0;
- *buf = o;
- return r;
-}
-
-/* construct an argv, and hand anything left over to readwrite(). */
-
-void netcat_commandline_read(int *argc, char ***argv)
-{
- int my_argc = 1;
- char **my_argv = *argv;
- char *saved_argv0 = my_argv[0];
- char buf[4096], *p, *rest;
-
- /* using this output style makes sure that a careless translator can't take
- down everything while playing with c-format */
- fprintf(stderr, "%s ", _("Cmd line:"));
- fflush(stderr); /* this isn't needed, but on ALL OS? */
- commandline_need_newline = TRUE; /* fancy output handling */
- p = fgets(buf, sizeof(buf), stdin);
- my_argv = malloc(128 * sizeof(char *)); /* FIXME: 128? */
- memset(my_argv, 0, 128 * sizeof(char *));
- my_argv[0] = saved_argv0; /* leave the program name intact */
- if (!buf[0]) /* there is no input (ctrl+d?) */
- printf("\n");
- commandline_need_newline = FALSE;
-
- /* fgets() returns a newline, which is stripped by netcat_string_split() */
- do {
- rest = netcat_string_split(&p);
- my_argv[my_argc++] = (rest[0] ? strdup(rest) : NULL);
- } while (rest[0] && (my_argc < 128));
-
- /* now my_argc counts one more, because we have a NULL element at
- * the end of the list */
- my_argv = realloc(my_argv, my_argc-- * sizeof(char *));
-
- /* sends out the results */
- *argc = my_argc;
- *argv = my_argv;
-
-#if 0
- /* debug this routine */
- printf("new argc is: %d\n", *argc);
- for (my_argc = 0; my_argc < *argc; my_argc++) {
- printf("my_argv[%d] = \"%s\"\n", my_argc, my_argv[my_argc]);
- }
-#endif
-}
-
-/* Prints the help screen to stdout */
-
-void netcat_printhelp(char *argv0)
-{
- printf(_("GNU netcat %s, a rewrite of the famous networking tool.\n"), VERSION);
- printf(_("Basic usages:\n"));
- printf(_("connect to somewhere: %s [options] hostname port [port] ...\n"), argv0);
- printf(_("listen for inbound: %s -l -p port [options] [hostname] [port] ...\n"), argv0);
- printf(_("tunnel to somewhere: %s -L hostname:port -p port [options]\n"), argv0);
- printf("\n");
- printf(_("Mandatory arguments to long options are mandatory for short options too.\n"));
- printf(_("Options:\n"
-" -c, --close close connection on EOF from stdin\n"
-" -e, --exec=PROGRAM program to exec after connect\n"
-" -g, --gateway=LIST source-routing hop point[s], up to 8\n"
-" -G, --pointer=NUM source-routing pointer: 4, 8, 12, ...\n"
-" -h, --help display this help and exit\n"
-" -i, --interval=SECS delay interval for lines sent, ports scanned\n"
-" -l, --listen listen mode, for inbound connects\n"));
- printf(_(""
-" -L, --tunnel=ADDRESS:PORT forward local port to remote address\n"
-" -n, --dont-resolve numeric-only IP addresses, no DNS\n"
-" -o, --output=FILE output hexdump traffic to FILE (implies -x)\n"
-" -p, --local-port=NUM local port number\n"
-" -r, --randomize randomize local and remote ports\n"
-" -s, --source=ADDRESS local source address (ip or hostname)\n"));
-#ifndef USE_OLD_COMPAT
- printf(_(""
-" -t, --tcp TCP mode (default)\n"
-" -T, --telnet answer using TELNET negotiation\n"));
-#else
- printf(_(""
-" --tcp TCP mode (default)\n"
-" -t, --telnet answer using TELNET negotiation\n"
-" -T same as --telnet (compat)\n"));
-#endif
- printf(_(""
-" -u, --udp UDP mode\n"
-" -v, --verbose verbose (use twice to be more verbose)\n"
-" -V, --version output version information and exit\n"
-" -x, --hexdump hexdump incoming and outgoing traffic\n"
-" -w, --wait=SECS timeout for connects and final net reads\n"
-" -z, --zero zero-I/O mode (used for scanning)\n"));
- printf("\n");
- printf(_("Remote port number can also be specified as range. "
- "Example: '1-1024'\n"));
- printf("\n");
-}
-
-/* Prints version and license information to stdout */
-
-void netcat_printversion(void)
-{
- printf("netcat (The GNU Netcat) %s\n", VERSION);
- printf(_("Copyright (C) 2002 - 2003 Giovanni Giacobbi\n\n"
-"This program comes with NO WARRANTY, to the extent permitted by law.\n"
-"You may redistribute copies of this program under the terms of\n"
-"the GNU General Public License.\n"
-"For more information about these matters, see the file named COPYING.\n\n"
-"Original idea and design by Avian Research <hobbit@avian.org>,\n"
-"Written by Giovanni Giacobbi <giovanni@giacobbi.net>.\n"));
-}
-
-#ifdef DEBUG
-/* This function resolves in a totally non-threadsafe way the format strings in
- the debug messages in order to wrap the call to the ncprint facility */
-
-const char *debug_fmt(const char *fmt, ...)
-{
- static char buf[512];
- va_list args;
-
- /* resolve the format strings only if it is really needed */
- if (opt_debug) {
- va_start(args, fmt);
- vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- }
- else {
- strncpy(buf, fmt, sizeof(buf));
- buf[sizeof(buf) - 1] = 0;
- }
-
- return buf;
-}
-#endif
-
-#ifndef USE_LINUX_SELECT
-#define TIMEVAL_DIFF(__t1, __t2) { \
- (__t1)->tv_usec -= (__t2)->tv_usec; \
- if ((__t1)->tv_usec < 0) { \
- (__t1)->tv_usec += 1000000L; \
- (__t1)->tv_sec -= 1; \
- } \
- (__t1)->tv_sec -= (__t2)->tv_sec; \
- if ((__t1)->tv_sec < 0) { \
- (__t1)->tv_sec = 0; \
- (__t1)->tv_usec = 0; \
- } \
- }
-
-void update_timeval(struct timeval *target)
-{
- static struct timeval dd_start;
- struct timeval dd_end;
- struct timezone dd_zone;
-
- if (target == NULL) { /* just initialize the seed */
- if (gettimeofday(&dd_start, &dd_zone))
- return; /* can't handle this type of error */
- }
- else {
- if (gettimeofday(&dd_end, &dd_zone))
- return; /* can't handle this type of error */
-
- TIMEVAL_DIFF(&dd_end, &dd_start); /* get the spent time */
- TIMEVAL_DIFF(target, &dd_end); /* and update the target struct */
- }
-}
-#endif
diff --git a/src/misc.h b/src/misc.h
deleted file mode 100644
index 058b6ad..0000000
--- a/src/misc.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * misc.h -- ncprint constants and debugging functions definition
- * Part of the GNU netcat project
- *
- * Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- * Copyright (C) 2002 - 2003 Giovanni Giacobbi
- *
- * $Id: misc.h,v 1.8 2003/03/06 00:20:07 themnemonic Exp $
- */
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- ***************************************************************************/
-
-/* time to wait (in microseconds) when DELAY is requested (debug mode) */
-#define NCPRINT_WAITTIME 500000
-
-/* NCPRINT flags */
-#define NCPRINT_STDOUT 0x0001 /* force output to stdout */
-#define NCPRINT_NONEWLINE 0x0002 /* don't print a newline at the end */
-#define NCPRINT_DELAY 0x0004 /* delay WAITTIME before returning */
-#define NCPRINT_EXIT 0x0008 /* exit() after printing the string */
-#define NCPRINT_VERB1 0x0010 /* require verbosity level 1 */
-#define NCPRINT_VERB2 0x0020 /* require verbosity level 2 */
-#define NCPRINT_NOFMT 0x0040 /* do not interpret format strings */
-
-/* NCPRINT commands */
-/* normal message printed to stderr by default */
-#define NCPRINT_NORMAL 0x0000
-
-/* debug message. This type of message is only printed if `opt_debug' is true */
-#define NCPRINT_DEBUG 0x1000
-
-/* special debug message. Prepends "(debug)" before the actual string */
-#define NCPRINT_DEBUG_V 0x1100
-
-/* prepends "Error:" and flags the message as ERROR */
-#define NCPRINT_ERROR 0x1200
-
-/* prepends "Warning:" and flags the message as WARNING */
-#define NCPRINT_WARNING 0x1300
-
-/* prepends "Notice:" and flags the message as NOTICE */
-#define NCPRINT_NOTICE 0x1400
-
-/* Debugging output routines */
-#ifdef DEBUG
-# define debug(fmtstring) \
- ncprint(NCPRINT_NOFMT | NCPRINT_NONEWLINE | NCPRINT_DEBUG, debug_fmt fmtstring)
-# define debug_d(fmtstring) \
- ncprint(NCPRINT_NOFMT | NCPRINT_NONEWLINE | NCPRINT_DEBUG | NCPRINT_DELAY, debug_fmt fmtstring)
-# define debug_v(fmtstring) \
- ncprint(NCPRINT_NOFMT | NCPRINT_DEBUG_V, debug_fmt fmtstring)
-# define debug_dv(fmtstring) \
- ncprint(NCPRINT_NOFMT | NCPRINT_DEBUG_V | NCPRINT_DELAY, debug_fmt fmtstring)
-#else
-# define debug(fmtstring)
-# define debug_d(fmtstring)
-# define debug_v(fmtstring)
-# define debug_dv(fmtstring)
-#endif
diff --git a/src/netcat.c b/src/netcat.c
deleted file mode 100644
index 21887cc..0000000
--- a/src/netcat.c
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- * netcat.c -- main project file
- * Part of the GNU netcat project
- *
- * Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- * Copyright (C) 2002 - 2003 Giovanni Giacobbi
- *
- * $Id: netcat.c,v 1.63 2003/08/21 15:27:18 themnemonic Exp $
- */
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "netcat.h"
-#include <signal.h>
-#include <getopt.h>
-#include <time.h> /* time(2) used as random seed */
-
-/* int gatesidx = 0; */ /* LSRR hop count */
-/* int gatesptr = 4; */ /* initial LSRR pointer, settable */
-/* nc_host_t **gates = NULL; */ /* LSRR hop hostpoop */
-/* char *optbuf = NULL; */ /* LSRR or sockopts */
-FILE *output_fp = NULL; /* output fd (FIXME: i don't like this) */
-bool use_stdin = TRUE; /* tells wether stdin was closed or not */
-bool signal_handler = TRUE; /* handle the signals externally */
-bool got_sigterm = FALSE; /* when this TRUE the application must exit */
-bool got_sigint = FALSE; /* when this TRUE the application should exit */
-bool got_sigusr1 = FALSE; /* when set, the application should print stats */
-bool commandline_need_newline = FALSE; /* fancy output handling */
-
-/* global options flags */
-nc_mode_t netcat_mode = 0; /* Netcat working modality */
-bool opt_eofclose = FALSE; /* close connection on EOF from stdin */
-bool opt_debug = FALSE; /* debugging output */
-bool opt_numeric = FALSE; /* don't resolve hostnames */
-bool opt_random = FALSE; /* use random ports */
-bool opt_udpmode = FALSE; /* use udp protocol instead of tcp */
-bool opt_telnet = FALSE; /* answer in telnet mode */
-bool opt_hexdump = FALSE; /* hexdump traffic */
-bool opt_zero = FALSE; /* zero I/O mode (don't expect anything) */
-int opt_interval = 0; /* delay (in seconds) between lines/ports */
-int opt_verbose = 0; /* be verbose (> 1 to be MORE verbose) */
-int opt_wait = 0; /* wait time */
-char *opt_outputfile = NULL; /* hexdump output file */
-char *opt_exec = NULL; /* program to exec after connecting */
-nc_proto_t opt_proto = NETCAT_PROTO_TCP; /* protocol to use for connections */
-
-
-/* signal handling */
-
-static void got_term(int z)
-{
- if (!got_sigterm)
- ncprint(NCPRINT_VERB1, _("Terminated."));
- debug_v(("_____ RECEIVED SIGTERM _____ [signal_handler=%s]",
- BOOL_TO_STR(signal_handler)));
- got_sigterm = TRUE;
- if (signal_handler) /* default action */
- exit(EXIT_FAILURE);
-}
-
-static void got_int(int z)
-{
- if (!got_sigint)
- ncprint(NCPRINT_VERB1, _("Exiting."));
- debug_v(("_____ RECEIVED SIGINT _____ [signal_handler=%s]",
- BOOL_TO_STR(signal_handler)));
- got_sigint = TRUE;
- if (signal_handler) { /* default action */
- if (commandline_need_newline) /* if we were waiting for input */
- printf("\n");
- netcat_printstats(FALSE);
- exit(EXIT_FAILURE);
- }
-}
-
-static void got_usr1(int z)
-{
- debug_dv(("_____ RECEIVED SIGUSR1 _____ [signal_handler=%s]",
- BOOL_TO_STR(signal_handler)));
- if (signal_handler) /* default action */
- netcat_printstats(TRUE);
- else
- got_sigusr1 = TRUE;
-}
-
-/* Execute an external file making its stdin/stdout/stderr the actual socket */
-
-static void ncexec(nc_sock_t *ncsock)
-{
- int saved_stderr;
- char *p;
- assert(ncsock && (ncsock->fd >= 0));
-
- /* save the stderr fd because we may need it later */
- saved_stderr = dup(STDERR_FILENO);
-
- /* duplicate the socket for the child program */
- dup2(ncsock->fd, STDIN_FILENO); /* the precise order of fiddlage */
- close(ncsock->fd); /* is apparently crucial; this is */
- dup2(STDIN_FILENO, STDOUT_FILENO); /* swiped directly out of "inetd". */
- dup2(STDIN_FILENO, STDERR_FILENO); /* also duplicate the stderr channel */
-
- /* change the label for the executed program */
- if ((p = strrchr(opt_exec, '/')))
- p++; /* shorter argv[0] */
- else
- p = opt_exec;
-
- /* replace this process with the new one */
-#ifndef USE_OLD_COMPAT
- execl("/bin/sh", p, "-c", opt_exec, NULL);
-#else
- execl(opt_exec, p, NULL);
-#endif
- dup2(saved_stderr, STDERR_FILENO);
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Couldn't execute %s: %s"),
- opt_exec, strerror(errno));
-} /* end of ncexec() */
-
-/* main: handle command line arguments and listening status */
-
-int main(int argc, char *argv[])
-{
- int c, glob_ret = EXIT_FAILURE;
- int total_ports, left_ports, accept_ret = -1, connect_ret = -1;
- struct sigaction sv;
- nc_port_t local_port; /* local port specified with -p option */
- nc_host_t local_host; /* local host for bind()ing operations */
- nc_host_t remote_host;
- nc_sock_t listen_sock;
- nc_sock_t connect_sock;
- nc_sock_t stdio_sock;
-
- memset(&local_port, 0, sizeof(local_port));
- memset(&local_host, 0, sizeof(local_host));
- memset(&remote_host, 0, sizeof(remote_host));
- memset(&listen_sock, 0, sizeof(listen_sock));
- memset(&connect_sock, 0, sizeof(listen_sock));
- memset(&stdio_sock, 0, sizeof(stdio_sock));
- listen_sock.domain = PF_INET;
- connect_sock.domain = PF_INET;
-
-#ifdef ENABLE_NLS
- setlocale(LC_MESSAGES, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-#endif
-
- /* set up the signal handling system */
- sigemptyset(&sv.sa_mask);
- sv.sa_flags = 0;
- sv.sa_handler = got_int;
- sigaction(SIGINT, &sv, NULL);
- sv.sa_handler = got_term;
- sigaction(SIGTERM, &sv, NULL);
- sv.sa_handler = got_usr1;
- sigaction(SIGUSR1, &sv, NULL);
- /* ignore some boring signals */
- sv.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &sv, NULL);
- sigaction(SIGURG, &sv, NULL);
-
- /* if no args given at all, take them from stdin and generate argv */
- if (argc == 1)
- netcat_commandline_read(&argc, &argv);
-
- /* check for command line switches */
- while (TRUE) {
- int option_index = 0;
- static const struct option long_options[] = {
- { "close", no_argument, NULL, 'c' },
- { "debug", no_argument, NULL, 'd' },
- { "exec", required_argument, NULL, 'e' },
- { "gateway", required_argument, NULL, 'g' },
- { "pointer", required_argument, NULL, 'G' },
- { "help", no_argument, NULL, 'h' },
- { "interval", required_argument, NULL, 'i' },
- { "listen", no_argument, NULL, 'l' },
- { "tunnel", required_argument, NULL, 'L' },
- { "dont-resolve", no_argument, NULL, 'n' },
- { "output", required_argument, NULL, 'o' },
- { "local-port", required_argument, NULL, 'p' },
- { "tunnel-port", required_argument, NULL, 'P' },
- { "randomize", no_argument, NULL, 'r' },
- { "source", required_argument, NULL, 's' },
- { "tunnel-source", required_argument, NULL, 'S' },
-#ifndef USE_OLD_COMPAT
- { "tcp", no_argument, NULL, 't' },
- { "telnet", no_argument, NULL, 'T' },
-#else
- { "tcp", no_argument, NULL, 1 },
- { "telnet", no_argument, NULL, 't' },
-#endif
- { "udp", no_argument, NULL, 'u' },
- { "verbose", no_argument, NULL, 'v' },
- { "version", no_argument, NULL, 'V' },
- { "hexdump", no_argument, NULL, 'x' },
- { "wait", required_argument, NULL, 'w' },
- { "zero", no_argument, NULL, 'z' },
- { 0, 0, 0, 0 }
- };
-
- c = getopt_long(argc, argv, "cde:g:G:hi:lL:no:p:P:rs:S:tTuvVxw:z",
- long_options, &option_index);
- if (c == -1)
- break;
-
- switch (c) {
- case 'c': /* close connection on EOF from stdin */
- opt_eofclose = TRUE;
- break;
- case 'd': /* enable debugging */
- opt_debug = TRUE;
- break;
- case 'e': /* prog to exec */
- if (opt_exec)
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("Cannot specify `-e' option double"));
- opt_exec = strdup(optarg);
- break;
- case 'G': /* srcrt gateways pointer val */
- break;
- case 'g': /* srcroute hop[s] */
- break;
- case 'h': /* display help and exit */
- netcat_printhelp(argv[0]);
- exit(EXIT_SUCCESS);
- case 'i': /* line/ports interval time (seconds) */
- opt_interval = atoi(optarg);
- if (opt_interval <= 0)
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("Invalid interval time \"%s\""), optarg);
- break;
- case 'l': /* mode flag: listen mode */
- if (netcat_mode != NETCAT_UNSPEC)
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("You can specify mode flags (`-l' and `-L') only once"));
- netcat_mode = NETCAT_LISTEN;
- break;
- case 'L': /* mode flag: tunnel mode */
- if (netcat_mode != NETCAT_UNSPEC)
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("You can specify mode flags (`-l' and `-L') only once"));
- if (opt_zero)
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("`-L' and `-z' options are incompatible"));
- do {
- char *div = strchr(optarg, ':');
-
- if (div && *(div + 1))
- *div++ = '\0';
- else
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("Invalid target string for `-L' option"));
-
- /* lookup the remote address and the remote port for tunneling */
- if (!netcat_resolvehost(&connect_sock.host, optarg))
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("Couldn't resolve tunnel target host: %s"), optarg);
- if (!netcat_getport(&connect_sock.port, div, 0))
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("Invalid tunnel target port: %s"), div);
-
- connect_sock.proto = opt_proto;
- connect_sock.timeout = opt_wait;
- netcat_mode = NETCAT_TUNNEL;
- } while (FALSE);
- break;
- case 'n': /* numeric-only, no DNS lookups */
- opt_numeric = TRUE;
- break;
- case 'o': /* output hexdump log to file */
- opt_outputfile = strdup(optarg);
- opt_hexdump = TRUE; /* implied */
- break;
- case 'p': /* local source port */
- if (!netcat_getport(&local_port, optarg, 0))
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Invalid local port: %s"),
- optarg);
- break;
- case 'P': /* used only in tunnel mode (source port) */
- if (!netcat_getport(&connect_sock.local_port, optarg, 0))
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("Invalid tunnel connect port: %s"), optarg);
- break;
- case 'r': /* randomize various things */
- opt_random = TRUE;
- break;
- case 's': /* local source address */
- /* lookup the source address and assign it to the connection address */
- if (!netcat_resolvehost(&local_host, optarg))
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("Couldn't resolve local host: %s"), optarg);
- break;
- case 'S': /* used only in tunnel mode (source ip) */
- if (!netcat_resolvehost(&connect_sock.local_host, optarg))
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("Couldn't resolve tunnel local host: %s"), optarg);
- break;
- case 1: /* use TCP protocol (default) */
-#ifndef USE_OLD_COMPAT
- case 't':
-#endif
- opt_proto = NETCAT_PROTO_TCP;
- break;
-#ifdef USE_OLD_COMPAT
- case 't':
-#endif
- case 'T': /* answer telnet codes */
- opt_telnet = TRUE;
- break;
- case 'u': /* use UDP protocol */
- opt_proto = NETCAT_PROTO_UDP;
- break;
- case 'v': /* be verbose (twice=more verbose) */
- opt_verbose++;
- break;
- case 'V': /* display version and exit */
- netcat_printversion();
- exit(EXIT_SUCCESS);
- case 'w': /* wait time (in seconds) */
- opt_wait = atoi(optarg);
- if (opt_wait <= 0)
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Invalid wait-time: %s"),
- optarg);
- break;
- case 'x': /* hexdump traffic */
- opt_hexdump = TRUE;
- break;
- case 'z': /* little or no data xfer */
- if (netcat_mode == NETCAT_TUNNEL)
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("`-L' and `-z' options are incompatible"));
- opt_zero = TRUE;
- break;
- default:
- ncprint(NCPRINT_EXIT, _("Try `%s --help' for more information."), argv[0]);
- }
- }
-
- if (opt_zero && opt_exec)
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("`-e' and `-z' options are incompatible"));
-
- /* initialize the flag buffer to keep track of the specified ports */
- netcat_flag_init(65535);
-
-#ifndef DEBUG
- /* check for debugging support */
- if (opt_debug)
- ncprint(NCPRINT_WARNING,
- _("Debugging support not compiled, option `-d' discarded. Using maximum verbosity."));
-#endif
-
- /* randomize only if needed */
- if (opt_random)
-#ifdef USE_RANDOM
- SRAND(time(0));
-#else
- ncprint(NCPRINT_WARNING,
- _("Randomization support not compiled, option `-r' discarded."));
-#endif
-
- /* handle the -o option. exit on failure */
- if (opt_outputfile) {
- output_fp = fopen(opt_outputfile, "w");
- if (!output_fp)
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Failed to open output file: %s"),
- strerror(errno));
- }
- else
- output_fp = stderr;
-
- debug_v(("Trying to parse non-args parameters (argc=%d, optind=%d)", argc,
- optind));
-
- /* try to get an hostname parameter */
- if (optind < argc) {
- char *myhost = argv[optind++];
- if (!netcat_resolvehost(&remote_host, myhost))
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT, _("Couldn't resolve host \"%s\""),
- myhost);
- }
-
- /* now loop all the other (maybe optional) parameters for port-ranges */
- while (optind < argc) {
- const char *get_argv = argv[optind++];
- char *q, *parse = strdup(get_argv);
- int port_lo = 0, port_hi = 65535;
- nc_port_t port_tmp;
-
- if (!(q = strchr(parse, '-'))) /* simple number? */
- q = strchr(parse, ':'); /* try with the other separator */
-
- if (!q) {
- if (netcat_getport(&port_tmp, parse, 0))
- netcat_flag_set(port_tmp.num, TRUE);
- else
- goto got_err;
- }
- else { /* could be in the forms: N1-N2, -N2, N1- */
- *q++ = 0;
- if (*parse) {
- if (netcat_getport(&port_tmp, parse, 0))
- port_lo = port_tmp.num;
- else
- goto got_err;
- }
- if (*q) {
- if (netcat_getport(&port_tmp, q, 0))
- port_hi = port_tmp.num;
- else
- goto got_err;
- }
- if (!*parse && !*q) /* don't accept the form '-' */
- goto got_err;
-
- /* now update the flagset (this is int, so it's ok even if hi == 65535) */
- while (port_lo <= port_hi)
- netcat_flag_set(port_lo++, TRUE);
- }
-
- free(parse);
- continue;
-
- got_err:
- free(parse);
- ncprint(NCPRINT_ERROR, _("Invalid port specification: %s"), get_argv);
- exit(EXIT_FAILURE);
- }
-
- debug_dv(("Arguments parsing complete! Total ports=%d", netcat_flag_count()));
-#if 0
- /* pure debugging code */
- c = 0;
- while ((c = netcat_flag_next(c))) {
- printf("Got port=%d\n", c);
- }
- exit(0);
-#endif
-
- /* Handle listen mode and tunnel mode (whose index number is higher) */
- if (netcat_mode > NETCAT_CONNECT) {
- /* in tunnel mode the opt_zero flag is illegal, while on listen mode it
- means that no connections should be accepted. For UDP it means that
- no remote addresses should be used as default endpoint, which means
- that we can't send anything. In both situations, stdin is no longer
- useful, so close it. */
- if (opt_zero) {
- close(STDIN_FILENO);
- use_stdin = FALSE;
- }
-
- /* prepare the socket var and start listening */
- listen_sock.proto = opt_proto;
- listen_sock.timeout = opt_wait;
- memcpy(&listen_sock.local_host, &local_host, sizeof(listen_sock.local_host));
- memcpy(&listen_sock.local_port, &local_port, sizeof(listen_sock.local_port));
- memcpy(&listen_sock.host, &remote_host, sizeof(listen_sock.host));
- accept_ret = core_listen(&listen_sock);
-
- /* in zero I/O mode the core_tcp_listen() call will always return -1
- (ETIMEDOUT) since no connections are accepted, because of this our job
- is completed now. */
- if (accept_ret < 0) {
- /* since i'm planning to make `-z' compatible with `-L' I need to check
- the exact error that caused this failure. */
- if (opt_zero && (errno == ETIMEDOUT))
- exit(0);
-
- ncprint(NCPRINT_VERB1 | NCPRINT_EXIT, _("Listen mode failed: %s"),
- strerror(errno));
- }
-
- /* if we are in listen mode, run the core loop and exit when it returns.
- otherwise now it's the time to connect to the target host and tunnel
- them together (which means passing to the next section. */
- if (netcat_mode == NETCAT_LISTEN) {
- if (opt_exec) {
- ncprint(NCPRINT_VERB2, _("Passing control to the specified program"));
- ncexec(&listen_sock); /* this won't return */
- }
- core_readwrite(&listen_sock, &stdio_sock);
- debug_dv(("Listen: EXIT"));
- }
- else {
- /* otherwise we are in tunnel mode. The connect_sock var was already
- initialized by the command line arguments. */
- assert(netcat_mode == NETCAT_TUNNEL);
- connect_ret = core_connect(&connect_sock);
-
- /* connection failure? (we cannot get this in UDP mode) */
- if (connect_ret < 0) {
- assert(opt_proto != NETCAT_PROTO_UDP);
- ncprint(NCPRINT_VERB1, "%s: %s",
- netcat_strid(&connect_sock.host, &connect_sock.port),
- strerror(errno));
- }
- else {
- glob_ret = EXIT_SUCCESS;
- core_readwrite(&listen_sock, &connect_sock);
- debug_dv(("Tunnel: EXIT (ret=%d)", glob_ret));
- }
- }
-
- /* all jobs should be ok, go to the cleanup */
- goto main_exit;
- } /* end of listen and tunnel mode handling */
-
- /* we need to connect outside, this is the connect mode */
- netcat_mode = NETCAT_CONNECT;
-
- /* first check that a host parameter was given */
- if (!remote_host.iaddrs[0].s_addr) {
- /* FIXME: The Networking specifications state that host address "0" is a
- valid host to connect to but this broken check will assume as not
- specified. */
- ncprint(NCPRINT_NORMAL, _("%s: missing hostname argument"), argv[0]);
- ncprint(NCPRINT_EXIT, _("Try `%s --help' for more information."), argv[0]);
- }
-
- /* since ports are the second argument, checking ports might be enough */
- total_ports = netcat_flag_count();
- if (total_ports == 0)
- ncprint(NCPRINT_ERROR | NCPRINT_EXIT,
- _("No ports specified for connection"));
-
- c = 0; /* must be set to 0 for netcat_flag_next() */
- left_ports = total_ports;
- while (left_ports > 0) {
- /* `c' is the port number independently of the sorting method (linear
- or random). While in linear mode it is also used to fetch the next
- port number */
- if (opt_random)
- c = netcat_flag_rand();
- else
- c = netcat_flag_next(c);
- left_ports--; /* decrease the total ports number to try */
-
- /* since we are nonblocking now, we can start as many connections as we want
- but it's not a great idea connecting more than one host at time */
- connect_sock.proto = opt_proto;
- connect_sock.timeout = opt_wait;
- memcpy(&connect_sock.local_host, &local_host,
- sizeof(connect_sock.local_host));
- memcpy(&connect_sock.local_port, &local_port,
- sizeof(connect_sock.local_port));
- memcpy(&connect_sock.host, &remote_host, sizeof(connect_sock.host));
- netcat_getport(&connect_sock.port, NULL, c);
-
- /* FIXME: in udp mode and NETCAT_CONNECT, opt_zero is senseless */
- connect_ret = core_connect(&connect_sock);
-
- /* connection failure? (we cannot get this in UDP mode) */
- if (connect_ret < 0) {
- int ncprint_flags = NCPRINT_VERB1;
- assert(connect_sock.proto != NETCAT_PROTO_UDP);
-
- /* if we are portscanning or multiple connecting show only open
- ports with verbosity level 1. */
- if (total_ports > 1)
- ncprint_flags = NCPRINT_VERB2;
-
- ncprint(ncprint_flags, "%s: %s",
- netcat_strid(&connect_sock.host, &connect_sock.port),
- strerror(errno));
- continue; /* go with next port */
- }
-
- /* when portscanning (or checking a single port) we are happy if AT LEAST
- ONE port is available. */
- glob_ret = EXIT_SUCCESS;
-
- if (opt_zero) {
- shutdown(connect_ret, 2);
- close(connect_ret);
- }
- else {
- if (opt_exec) {
- ncprint(NCPRINT_VERB2, _("Passing control to the specified program"));
- ncexec(&connect_sock); /* this won't return */
- }
- core_readwrite(&connect_sock, &stdio_sock);
- /* FIXME: add a small delay */
- debug_v(("Connect: EXIT"));
-
- /* both signals are handled inside core_readwrite(), but while the
- SIGINT signal is fully handled, the SIGTERM requires some action
- from outside that function, because of this that flag is not
- cleared. */
- if (got_sigterm)
- break;
- }
- } /* end of while (left_ports > 0) */
-
- /* all basic modes should return here for the final cleanup */
- main_exit:
- debug_v(("Main: EXIT (cleaning up)"));
-
- netcat_printstats(FALSE);
- return glob_ret;
-} /* end of main() */
diff --git a/src/netcat.h b/src/netcat.h
deleted file mode 100644
index 403b7e6..0000000
--- a/src/netcat.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * netcat.h -- main header project file
- * Part of the GNU netcat project
- *
- * Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- * Copyright (C) 2002 - 2004 Giovanni Giacobbi
- *
- * $Id: netcat.h,v 1.35 2004/01/03 16:42:07 themnemonic Exp $
- */
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- ***************************************************************************/
-
-#ifndef NETCAT_H
-#define NETCAT_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <assert.h>
-#include <errno.h>
-#include <sys/types.h> /* basic types definition */
-#include <sys/time.h> /* timeval, time_t */
-#include <sys/socket.h>
-#include <sys/uio.h> /* needed for reading/writing vectors */
-#include <sys/param.h> /* defines MAXHOSTNAMELEN and other stuff */
-#include <netinet/in.h>
-#include <arpa/inet.h> /* inet_ntop(), inet_pton() */
-
-/* other misc unchecked includes */
-#if 0
-#include <netinet/in_systm.h> /* misc crud that netinet/ip.h references */
-#include <netinet/ip.h> /* IPOPT_LSRR, header stuff */
-#endif
-
-/* These are useful to keep the source readable */
-#ifndef STDIN_FILENO
-# define STDIN_FILENO 0
-#endif
-#ifndef STDOUT_FILENO
-# define STDOUT_FILENO 1
-#endif
-#ifndef STDERR_FILENO
-# define STDERR_FILENO 2
-#endif
-#ifndef SHUT_RDWR
-# define SHUT_RDWR 2
-#endif
-
-/* find a random routine */
-#if defined(HAVE_RANDOM) && defined(HAVE_SRANDOM)
-# define USE_RANDOM /* try with most modern random routines */
-# define SRAND srandom
-# define RAND random
-#elif defined(HAVE_RAND) && defined(HAVE_SRAND)
-# define USE_RANDOM /* otherwise fallback to the older rand() */
-# define SRAND srand
-# define RAND rand
-#endif /* if none of them are here, CHANGE OS! */
-
-/* This must be defined to the longest possible internet address length in
- string notation.
- Bugfix: Looks like Solaris 7 doesn't define this standard. It's ok to use
- the following workaround since this is going to change to introduce IPv6
- support. */
-#ifdef INET_ADDRSTRLEN
-# define NETCAT_ADDRSTRLEN INET_ADDRSTRLEN
-#else
-# define NETCAT_ADDRSTRLEN 16
-#endif
-
-/* FIXME: I should search more about this portnames standards. At the moment
- i'll fix my own size for this */
-#define NETCAT_MAXPORTNAMELEN 64
-
-/* Find out whether we can use the RFC 2292 extensions on this machine
- (I've found out only linux supporting this feature so far) */
-#ifdef HAVE_STRUCT_IN_PKTINFO
-# if defined(SOL_IP) && defined(IP_PKTINFO)
-# define USE_PKTINFO
-# endif
-#endif
-
-/* MAXINETADDR defines the maximum number of host aliases that are saved after
- a successfully hostname lookup. Please not that this value will also take
- a significant role in the memory usage. Approximately one struct takes:
- MAXINETADDRS * (NETCAT_ADDRSTRLEN + sizeof(struct in_addr)) */
-#define MAXINETADDRS 6
-
-#ifndef INADDR_NONE
-# define INADDR_NONE 0xffffffff
-#endif
-
-/* FIXME: shall we really change this define? probably not. */
-#ifdef MAXHOSTNAMELEN
-# undef MAXHOSTNAMELEN /* might be too small on aix, so fix it */
-#endif
-#define MAXHOSTNAMELEN 256
-
-/* TRUE and FALSE values for logical type `bool' */
-#ifndef TRUE
-# define TRUE 1
-#endif
-#ifndef FALSE
-# define FALSE 0
-#endif
-
-/* this is just a logical type, but helps a lot */
-#ifndef __cplusplus
-# ifndef bool
-# define bool unsigned char
-# endif
-#endif
-#define BOOL_TO_STR(__var__) (__var__ ? "TRUE" : "FALSE")
-#define NULL_STR(__var__) (__var__ ? __var__ : "(null)")
-
-/* there are some OS that still doesn't support POSIX standards */
-#ifndef HAVE_IN_PORT_T
-typedef unsigned short in_port_t;
-#endif
-
-/* Netcat basic operating modes */
-
-typedef enum {
- NETCAT_UNSPEC,
- NETCAT_CONNECT,
- NETCAT_LISTEN,
- NETCAT_TUNNEL
-} nc_mode_t;
-
-/* Recognized protocols */
-
-typedef enum {
- NETCAT_PROTO_UNSPEC,
- NETCAT_PROTO_TCP,
- NETCAT_PROTO_UDP
-} nc_proto_t;
-
-/* used for queues buffering and data tracking purposes. The `head' field is
- a pointer to the begin of the buffer segment, while `pos' indicates the
- actual position of the data stream. If `head' is NULL, it means that there
- is no dynamically-allocated data in this buffer, *BUT* it MAY still contain
- some local data segment (for example allocated inside the stack).
- `len' indicates the length of the buffer starting from `pos'. */
-
-typedef struct {
- unsigned char *head;
- unsigned char *pos;
- int len;
-} nc_buffer_t;
-
-/* this is the standard netcat hosts record. It contains an "authoritative"
- `name' field, which may be empty, and a list of IP addresses in the network
- notation and in the dotted string notation. */
-
-typedef struct {
- char name[MAXHOSTNAMELEN]; /* dns name */
- char addrs[MAXINETADDRS][NETCAT_ADDRSTRLEN]; /* ascii-format IP addresses */
- struct in_addr iaddrs[MAXINETADDRS]; /* real addresses */
-} nc_host_t;
-
-/* standard netcat port record. It contains the port `name', which may be
- empty, and the port number both as number and as string. */
-
-typedef struct {
- char name[NETCAT_MAXPORTNAMELEN]; /* canonical port name */
- char ascnum[8]; /* ascii port number */
- unsigned short num; /* port number */
- /* FIXME: this is just a test! */
- in_port_t netnum; /* port number in network byte order */
-} nc_port_t;
-
-/* This is a more complex struct that holds socket records. [...] */
-
-typedef struct {
- int fd, domain, timeout;
- nc_proto_t proto;
- nc_host_t local_host, host;
- nc_port_t local_port, port;
- nc_buffer_t sendq, recvq;
-} nc_sock_t;
-
-/* Netcat includes */
-
-#include "proto.h"
-#include "intl.h"
-#include "misc.h"
-
-#endif /* !NETCAT_H */
diff --git a/src/network.c b/src/network.c
deleted file mode 100644
index 1d77d68..0000000
--- a/src/network.c
+++ /dev/null
@@ -1,602 +0,0 @@
-/*
- * network.c -- all network related functions and helpers
- * Part of the GNU netcat project
- *
- * Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- * Copyright (C) 2002 - 2004 Giovanni Giacobbi
- *
- * $Id: network.c,v 1.38 2004/01/03 16:42:07 themnemonic Exp $
- */
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "netcat.h"
-#include <netdb.h> /* hostent, gethostby*, getservby* */
-#include <fcntl.h> /* fcntl() */
-
-/* Fills the structure pointed to by `dst' with the valid DNS information
- for the target identified by `name', which can be an hostname or a valid IP
- address in the dotted notation.
- The hostname field is stored in the results structure only if it is actually
- authoritative for that machine.
- Returns TRUE on success or FALSE otherwise. On success, at least one IP
- address will be in the results, while there could be an empty hostname. */
-
-bool netcat_resolvehost(nc_host_t *dst, const char *name)
-{
- int i, ret;
- struct hostent *hostent;
- struct in_addr res_addr;
-
- assert(name && name[0]);
- debug_v(("netcat_resolvehost(dst=%p, name=\"%s\")", (void *)dst, name));
-
- /* reset all fields of the dst struct */
- memset(dst, 0, sizeof(*dst));
-
- ret = netcat_inet_pton(name, &res_addr);
- if (!ret) { /* couldn't translate: it must be a name! */
- bool host_auth_taken = FALSE;
-
- /* if the opt_numeric option is set, we must not use DNS in any way */
- if (opt_numeric)
- return FALSE;
-
- /* failures to look up a name are reported to the calling function */
- if (!(hostent = gethostbyname(name)))
- return FALSE;
-
- /* now I need to handle the host aliases (CNAME). If we lookup host
- www.bighost.foo, which is an alias for www.bighost.mux.foo, the hostent
- struct will contain the real name in h_name, which is not what we want
- for the output purpose (the user doesn't want to see something he didn't
- type. So assume the lookup name as the "official" name and fetch the
- ips for the reverse lookup. */
- debug(("(lookup) lookup=\"%s\" official=\"%s\" (should match)\n", name,
- hostent->h_name));
- strncpy(dst->name, name, MAXHOSTNAMELEN - 1);
-
- /* now save all the available ip addresses (no more than MAXINETADDRS) */
- for (i = 0; hostent->h_addr_list[i] && (i < MAXINETADDRS); i++) {
- memcpy(&dst->iaddrs[i], hostent->h_addr_list[i], sizeof(dst->iaddrs[0]));
- strncpy(dst->addrs[i], netcat_inet_ntop(&dst->iaddrs[i]),
- sizeof(dst->addrs[0]));
- } /* end of foreach addr, part A */
-
- /* for speed purposes, skip the authoritative checking if we haven't got
- any verbosity level set. note that this will cause invalid results
- in the dst struct, but we don't care at this point. */
- if (!opt_debug && (opt_verbose < 1))
- return TRUE;
-
- /* do inverse lookups in a separated loop for each collected addresses */
- for (i = 0; dst->iaddrs[i].s_addr && (i < MAXINETADDRS); i++) {
- hostent = gethostbyaddr((char *)&dst->iaddrs[i], sizeof(dst->iaddrs[0]),
- AF_INET);
-
- if (!hostent || !hostent->h_name) {
- ncprint(NCPRINT_VERB1 | NCPRINT_WARNING,
- _("Inverse name lookup failed for `%s'"), dst->addrs[i]);
- continue;
- }
-
- /* now the case. hostnames aren't case sensitive because of this we may
- find a different case for the authoritative hostname. For the same
- previous reason we may want to keep the user typed case, but this time
- we are going to override it because this tool is a "network exploration
- tool", thus it's good to see the case they chose for this host. */
- if (strcasecmp(dst->name, hostent->h_name)) {
- int xcmp;
- char savedhost[MAXHOSTNAMELEN];
-
- /* refering to the flowchart (see the drafts directory contained in
- this package), try to guess the real hostname */
- strncpy(savedhost, hostent->h_name, sizeof(savedhost));
- savedhost[sizeof(savedhost) - 1] = 0;
-
- /* ok actually the given host and the reverse-resolved address doesn't
- match, so try to see if we can find the real machine name. In order to
- this to happen the originally found address must match with the newly
- found hostname directly resolved. If this doesn't, or if this resolve
- fails, then fall back to the original warning message: they have a DNS
- misconfigured! */
- hostent = gethostbyname(savedhost);
- if (!hostent)
- continue; /* FIXME: missing information analysis */
-
- for (xcmp = 0; hostent->h_addr_list[xcmp] &&
- (xcmp < MAXINETADDRS); xcmp++) {
- if (!memcmp(&dst->iaddrs[i], hostent->h_addr_list[xcmp],
- sizeof(dst->iaddrs[0])))
- goto found_real_host;
- }
-
- ncprint(NCPRINT_WARNING | NCPRINT_VERB1,
- _("This host's reverse DNS doesn't match! %s -- %s"),
- hostent->h_name, dst->name);
- continue;
-
- found_real_host:
- ncprint(NCPRINT_NOTICE | NCPRINT_VERB2,
- _("Real hostname for %s [%s] is %s"),
- dst->name, dst->addrs[i], savedhost);
- continue;
- }
- else if (!host_auth_taken) { /* case: take only the first one as auth */
- strncpy(dst->name, hostent->h_name, sizeof(dst->name));
- host_auth_taken = TRUE;
- }
- } /* end of foreach addr, part B */
- }
- else { /* `name' is a numeric address, try reverse lookup */
- memcpy(&dst->iaddrs[0], &res_addr, sizeof(dst->iaddrs[0]));
- strncpy(dst->addrs[0], netcat_inet_ntop(&res_addr), sizeof(dst->addrs[0]));
-
- /* if opt_numeric is set or we don't require verbosity, we are done */
- if (opt_numeric)
- return TRUE;
-
- /* numeric or not, failure to look up a PTR is *not* considered fatal */
- hostent = gethostbyaddr((char *)&res_addr, sizeof(res_addr), AF_INET);
- if (!hostent)
- ncprint(NCPRINT_VERB2 | NCPRINT_WARNING,
- _("Inverse name lookup failed for `%s'"), name);
- else {
- strncpy(dst->name, hostent->h_name, MAXHOSTNAMELEN - 2);
- /* now do the direct lookup to see if the PTR was authoritative */
- hostent = gethostbyname(dst->name);
-
- /* Any kind of failure in this section results in a host not auth
- warning, and the dst->name field cleaned (I don't care if there is a
- PTR, if it's unauthoritative). */
- if (!hostent || !hostent->h_addr_list[0]) {
- ncprint(NCPRINT_VERB1 | NCPRINT_WARNING,
- _("Host %s isn't authoritative! (direct lookup failed)"),
- dst->addrs[0]);
- goto check_failed;
- }
- for (i = 0; hostent->h_addr_list[i] && (i < MAXINETADDRS); i++)
- if (!memcmp(&dst->iaddrs[0], hostent->h_addr_list[i],
- sizeof(dst->iaddrs[0])))
- return TRUE;
-
- ncprint(NCPRINT_VERB1 | NCPRINT_WARNING,
- _("Host %s isn't authoritative! (direct lookup mismatch)"),
- dst->addrs[0]);
- ncprint(NCPRINT_VERB1, _(" %s -> %s BUT %s -> %s"),
- dst->addrs[0], dst->name, dst->name,
- netcat_inet_ntop(hostent->h_addr_list[0]));
-
- check_failed:
- memset(dst->name, 0, sizeof(dst->name));
- } /* if hostent */
- }
-
- return TRUE;
-}
-
-/* Identifies a port and fills in the netcat_port structure pointed to by
- `dst'. If `port_string' is not NULL, it is used to identify the port
- (either by port name, listed in /etc/services, or by a string number). In
- this case `port_num' is discarded.
- If `port_string' is NULL then `port_num' is used to identify the port and
- if opt_numeric is not TRUE, the port name is looked up reversely. */
-
-bool netcat_getport(nc_port_t *dst, const char *port_string,
- unsigned short port_num)
-{
- const char *get_proto = (opt_proto == NETCAT_PROTO_UDP ? "udp" : "tcp");
- struct servent *servent;
-
- debug_v(("netcat_getport(dst=%p, port_string=\"%s\", port_num=%hu)",
- (void *)dst, NULL_STR(port_string), port_num));
-
-/* Obligatory netdb.h-inspired rant: servent.s_port is supposed to be an int.
- Despite this, we still have to treat it as a short when copying it around.
- Not only that, but we have to convert it *back* into net order for
- getservbyport to work. Manpages generally aren't clear on all this, but
- there are plenty of examples in which it is just quietly done. -hobbit */
-
- /* reset all fields of the dst struct */
- memset(dst, 0, sizeof(*dst));
-
- if (!port_string) {
- if (port_num == 0)
- return FALSE;
- dst->num = port_num;
- dst->netnum = htons(port_num);
- servent = getservbyport((int)dst->netnum, get_proto);
- if (servent) {
- assert(dst->netnum == servent->s_port);
- strncpy(dst->name, servent->s_name, sizeof(dst->name));
- }
- goto end;
- }
- else {
- long port;
- char *endptr;
-
- /* empty string? refuse it */
- if (!port_string[0])
- return FALSE;
-
- /* try to convert the string into a valid port number. If an error occurs
- but it doesn't occur at the first char, throw an error */
- port = strtol(port_string, &endptr, 10);
- if (!endptr[0]) {
- /* pure numeric value, check it out */
- if ((port > 0) && (port < 65536))
- return netcat_getport(dst, NULL, (in_port_t)port);
- else
- return FALSE;
- }
- else if (endptr != port_string) /* mixed numeric and string value */
- return FALSE;
-
- /* this is a port name, try to lookup it */
- servent = getservbyname(port_string, get_proto);
- if (servent) {
- strncpy(dst->name, servent->s_name, sizeof(dst->name));
- dst->netnum = servent->s_port;
- dst->num = ntohs(dst->netnum);
- goto end;
- }
- return FALSE;
- }
-
- end:
- snprintf(dst->ascnum, sizeof(dst->ascnum), "%hu", dst->num);
- return TRUE;
-} /* end of netcat_getport() */
-
-/* returns a pointer to a static buffer containing a description of the remote
- host in the best form available (using hostnames and portnames) */
-
-/* MAXHOSTNAMELEN _ [ ADDRSTRLEN ] _ 5 _ ( MAXPORTNAMELEN ) */
-/* "my.very.long.hostname [255.255.255.255] 65535 (my_very_long_port_name)" */
-
-const char *netcat_strid(const nc_host_t *host, const nc_port_t *port)
-{
- static char buf[MAXHOSTNAMELEN + NETCAT_ADDRSTRLEN +
- NETCAT_MAXPORTNAMELEN + 15];
- char *p = buf;
- assert(host && port);
-
- if (host->iaddrs[0].s_addr) {
- if (host->name[0])
- p += snprintf(p, sizeof(buf) + buf - p, "%s [%s]", host->name,
- host->addrs[0]);
- else
- p += snprintf(p, sizeof(buf) + buf - p, "%s", host->addrs[0]);
- }
- else
- p += snprintf(p, sizeof(buf) + buf - p, _("any address"));
-
- p += snprintf(p, sizeof(buf) + buf - p, " %s", port->ascnum);
- if (port->name[0])
- p += snprintf(p, sizeof(buf) + buf - p, " (%s)", port->name);
-
- return buf;
-}
-
-/* Create a network address structure. This function is a compatibility
- replacement for the standard POSIX inet_pton() function. */
-
-int netcat_inet_pton(const char *src, void *dst)
-{
- int ret;
-
-#ifdef HAVE_INET_PTON
- ret = inet_pton(AF_INET, src, dst);
-#else
-# ifdef __GNUC__
-# warning Using broken network address conversion function for pton
-# endif
- ret = inet_aton(src, (struct in_addr *)dst);
-#endif
-
- return ret;
-} /* end of netcat_inet_pton() */
-
-/* Parse a network address structure. This function is a compatibility
- replacement for the standard POSIX inet_ntop() function. */
-
-const char *netcat_inet_ntop(const void *src)
-{
-#ifdef HAVE_INET_NTOP
- static char my_buf[127];
-#endif
- const char *ret;
-
- debug_v(("netcat_inet_ntop(src=%p)", src));
-
-#ifdef HAVE_INET_NTOP
- /* FIXME: Since inet_ntop breaks on IPv6-mapped IPv4 addresses i'll need to
- * sort it out by myself. */
- ret = inet_ntop(AF_INET, src, my_buf, sizeof(my_buf));
-#else
-# ifdef __GNUC__
-# warning Using broken network address conversion function for ntop
-# endif
- ret = inet_ntoa(*(struct in_addr *)src);
-#endif
-
- return ret;
-} /* end of netcat_inet_ntop() */
-
-/* Backend for the socket(2) system call. This function wraps the creation of
- new sockets and sets the common SO_REUSEADDR socket option, and the useful
- SO_LINGER option (if system available) handling eventual errors.
- Returns -1 if the socket(2) call failed, -2 if the setsockopt() call failed;
- otherwise the return value is a descriptor referencing the new socket. */
-
-int netcat_socket_new(int domain, int type)
-{
- int sock, ret, sockopt;
- struct linger fix_ling;
-
- sock = socket(domain, type, 0);
- if (sock < 0)
- return -1;
-
- /* don't leave the socket in a TIME_WAIT state if we close the connection */
- fix_ling.l_onoff = 1;
- fix_ling.l_linger = 0;
- ret = setsockopt(sock, SOL_SOCKET, SO_LINGER, &fix_ling, sizeof(fix_ling));
- if (ret < 0) {
- close(sock); /* anyway the socket was created */
- return -2;
- }
-
- /* fix the socket options */
- sockopt = 1;
- ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt));
- if (ret < 0) {
- close(sock); /* anyway the socket was created */
- return -2;
- }
-
- return sock;
-}
-
-/* Creates a full outgoing async socket connection in the specified `domain'
- and `type' to the specified `addr' and `port'. The connection is
- originated using the optionally specified `local_addr' and `local_port'.
- If `local_addr' is NULL and `local_port' is 0 the bind(2) call is skipped.
- Returns the descriptor referencing the new socket on success, otherwise
- returns -1 or -2 if socket creation failed (see netcat_socket_new()),
- or -3 if the bind(2) call failed, -4 if the fcntl(2) call failed, or -5
- if the connect(2) call failed. */
-
-int netcat_socket_new_connect(int domain, int type, const struct in_addr *addr,
- in_port_t port, const struct in_addr *local_addr,
- in_port_t local_port)
-{
- int sock, ret, my_family = AF_UNSPEC;
- struct sockaddr_in rem_addr;
- assert(addr);
-
- debug_dv(("netcat_socket_new_connect(addr=%p, port=%hu, local_addr=%p, local_"
- "port=%hu)", (void *)addr, ntohs(port), (void *)local_addr,
- ntohs(local_port)));
-
- /* selects the currently supported domains */
- if (domain == PF_INET)
- my_family = AF_INET;
- else
- return -1; /* assumes as the socket(2) call failed */
-
- memset(&rem_addr, 0, sizeof(rem_addr));
- rem_addr.sin_family = my_family;
- rem_addr.sin_port = port;
- memcpy(&rem_addr.sin_addr, addr, sizeof(rem_addr.sin_addr));
-
- /* create the socket and fix the options */
- sock = netcat_socket_new(domain, type);
- if (sock < 0)
- return sock; /* just forward the error code */
-
- /* only if needed, bind it to a local address */
- if (local_addr || local_port) {
- struct sockaddr_in my_addr;
-
- memset(&my_addr, 0, sizeof(my_addr));
- my_addr.sin_family = my_family;
- my_addr.sin_port = local_port;
-
- /* local_addr may not be specified because the user may want to only
- enforce the local source port */
- if (local_addr)
- memcpy(&my_addr.sin_addr, local_addr, sizeof(my_addr.sin_addr));
-
- ret = bind(sock, (struct sockaddr *)&my_addr, sizeof(my_addr));
- if (ret < 0) {
- ret = -3;
- goto err;
- }
- }
-
- /* add the non-blocking flag to this socket */
- if ((ret = fcntl(sock, F_GETFL, 0)) >= 0)
- ret = fcntl(sock, F_SETFL, ret | O_NONBLOCK);
- if (ret < 0) {
- ret = -4;
- goto err;
- }
-
- /* now launch the real connection. Since we are in non-blocking mode, this
- call will return -1 in MOST cases (on some systems, a connect() to a local
- address may immediately return successfully) */
- ret = connect(sock, (struct sockaddr *)&rem_addr, sizeof(rem_addr));
- if ((ret < 0) && (errno != EINPROGRESS)) {
- ret = -5;
- goto err;
- }
-
- /* everything went fine, return the (connected or connecting) socket */
- return sock;
-
- err:
- /* the if () statement is unuseful, but I need to for declaring vars */
- if (ret < 0) {
- int tmpret, saved_errno = errno;
-
- /* the close() calls MUST NOT fail */
- tmpret = close(sock);
- assert(tmpret >= 0);
-
- /* restore the original errno */
- errno = saved_errno;
- }
- return ret;
-}
-
-/* Creates a listening TCP (stream) socket already bound and in listening
- state in the specified `domain', ready for accept(2) or select(2). The
- `addr' parameter is optional and specifies the local interface at which
- socket should be bound to. If `addr' is NULL, it defaults to INADDR_ANY,
- which is a valid value as well.
- Returns the descriptor referencing the listening socket on success,
- otherwise returns -1 or -2 if socket creation failed (see
- netcat_socket_new()), -3 if the bind(2) call failed, or -4 if the listen(2)
- call failed. */
-
-int netcat_socket_new_listen(int domain, const struct in_addr *addr,
- in_port_t port)
-{
- int sock, ret, my_family;
- struct sockaddr_in my_addr;
-
- debug_dv(("netcat_socket_new_listen(addr=%p, port=%hu)", (void *)addr, port));
-
- /* selects the currently supported domains */
- if (domain == PF_INET)
- my_family = AF_INET;
- else
- return -1; /* assumes as the socket(2) call failed */
-
- /* Reset the sockaddr structure */
- memset(&my_addr, 0, sizeof(my_addr));
- my_addr.sin_family = my_family;
- my_addr.sin_port = port;
-
- /* this parameter is not mandatory. if it's not present, it's assumed as
- INADDR_ANY, and the behaviour is the same */
- if (addr)
- memcpy(&my_addr.sin_addr, addr, sizeof(my_addr.sin_addr));
-
- /* create the socket and fix the options */
- sock = netcat_socket_new(domain, SOCK_STREAM);
- if (sock < 0)
- return sock; /* forward the error code */
-
- /* bind it to the specified address (can be INADDY_ANY) */
- ret = bind(sock, (struct sockaddr *)&my_addr, sizeof(my_addr));
- if (ret < 0) {
- ret = -3;
- goto err;
- }
-
- /* now make it listening, with a reasonable backlog value */
- ret = listen(sock, 4);
- if (ret < 0) {
- ret = -4;
- goto err;
- }
-
- return sock;
-
- err:
- /* the if () statement is unuseful, but I need to for declaring vars */
- if (ret < 0) {
- int tmpret, saved_errno = errno;
-
- /* the close() calls MUST NOT fail */
- tmpret = close(sock);
- assert(tmpret >= 0);
-
- /* restore the original errno */
- errno = saved_errno;
- }
- return ret;
-}
-
-/* This function is much like the accept(2) call, but implements also the
- parameter `timeout', which specifies the time (in seconds) after which the
- function returns. If `timeout' is negative, the remaining of the last
- valid timeout specified is used. If it reached zero, or if the timeout
- hasn't been initialized already, this function waits forever.
- Returns -1 on error, setting the errno variable. If it succeeds, it
- returns a non-negative integer that is the file descriptor for the accepted
- socket. */
-
-int netcat_socket_accept(int s, int timeout)
-{
- fd_set in;
- int ret;
- static bool timeout_init = FALSE;
- static struct timeval timest;
-
- debug_v(("netcat_socket_accept(s=%d, timeout=%d)", s, timeout));
-
- /* initialize the select() variables */
- FD_ZERO(&in);
- FD_SET(s, &in);
- if (timeout > 0) {
- timest.tv_sec = timeout;
- timest.tv_usec = 0;
- timeout_init = TRUE;
- }
- else if (timeout && !timeout_init) {
- /* means that timeout is < 0 and timest hasn't been initialized */
- timeout = 0;
- }
-
- /* now call select(2). use timest only if we won't wait forever */
- call_select:
- ret = select(s + 1, &in, NULL, NULL, (timeout ? &timest : NULL));
- if (ret < 0) {
- /* if the call was interrupted by a signal nothing happens. signal at this
- stage ought to be handled externally. */
- if (errno == EINTR)
- goto call_select;
- perror("select(sock_accept)");
- exit(EXIT_FAILURE);
- }
-
- /* have we got this connection? */
- if (FD_ISSET(s, &in)) {
- int new_sock;
-
- new_sock = accept(s, NULL, NULL);
- debug_v(("Connection received (new fd=%d)", new_sock));
-
- /* NOTE: as accept() could fail, new_sock might also be a negative value.
- It's application's work to handle the right errno. */
- return new_sock;
- }
-
- /* since we've got a timeout, the timest is now zero and thus it is like
- uninitialized. Next time assume wait forever. */
- timeout_init = FALSE;
-
- /* no connections arrived during the given time. nothing happens */
- errno = ETIMEDOUT;
- return -1;
-}
diff --git a/src/parsers.cpp b/src/parsers.cpp
deleted file mode 100644
index 0063c6f..0000000
--- a/src/parsers.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/* AVRemote
-
- (c) 2011 Nederlands Instituut voor Mediakunst (NIMk)
- 2011 Denis Roio <jaromil@nimk.nl>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>
-
-*/
-
-#include <stdio.h>
-#include <string.h>
-
-
-#define MAX 256 // max XML string size
-
-// returns a pointer to the current position in haystack
-// for subsequent calls
-char *extract_xml(char *dest, char *haystack, const char *needle) {
- char *p, *pp;
-
- p = strstr(haystack, needle);
- if (!p) {
- fprintf(stderr, "parser cannot find \"%s\" in:\n%s\n",needle, haystack);
- return NULL;
- }
- // as you can see, i had a lot of fun with pointers when i was a kid
- pp = p; do pp+=1; while (*pp != '>'); pp++;
- p = pp; do p+=1; while (*p != '<'); *p = 0;
-
- snprintf(dest,MAX-1,"%s",pp);
-
- return(p+1);
-
-}
-
-void GetCurrentTransportActions(char *res) {
- char actions[MAX];
- fprintf(stderr,"#\tactions\n");
- extract_xml(actions, res, "Actions");
- fprintf(stderr,"Act: %s\n");
-}
-
-void GetDeviceCapabilities(char *res) {
- char play[MAX];
- char rec[MAX];
- char qual[MAX];
- char *p;
-
- fprintf(stderr,"#\tPlay\tRec\tQuality\n");
- p = extract_xml(play, res, "PlayMedia");
- p = extract_xml(rec, p, "RecMedia");
- p = extract_xml(qual, p, "RecQualityModes");
-
- fprintf(stderr,"Caps:\t%s\t%s\t%s\n",play,rec,qual);
-}
-
-void GetTransportInfo(char *res) {
- char state[MAX];
- char status[MAX];
- char speed[MAX];
- char *p;
-
- fprintf(stderr,"#\tstate\tstatus\tspeed\n");
-
- p = extract_xml(state, res, "CurrentTransportState");
-
- p = extract_xml(status, p, "CurrentTransportStatus");
-
- p = extract_xml(speed, p, "CurrentSpeed");
-
- fprintf(stderr,"TInfo:\t%s\t%s\t%s\n", state, status, speed);
-}
-
diff --git a/src/parsers.h b/src/parsers.h
deleted file mode 100644
index 4983c59..0000000
--- a/src/parsers.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* AVRemote
-
- (c) 2011 Nederlands Instituut voor Mediakunst (NIMk)
- 2011 Denis Roio <jaromil@nimk.nl>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>
-
-*/
-
-#ifndef __PARSERS_H__
-#define __PARSERS_H__
-
-// function pointers to various parsers
-typedef void (parser_f)(char *res);
-
-// parsers implemented
-void GetTransportInfo(char *res);
-
-#endif
-
diff --git a/src/proto.h b/src/proto.h
deleted file mode 100644
index 07dd562..0000000
--- a/src/proto.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * proto.h -- contains all global variables and functions prototypes
- * Part of the GNU netcat project
- *
- * Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- * Copyright (C) 2002 - 2004 Giovanni Giacobbi
- *
- * $Id: proto.h,v 1.41 2004/01/03 16:42:07 themnemonic Exp $
- */
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- ***************************************************************************/
-
-/* core.c */
-extern unsigned long bytes_sent, bytes_recv;
-int core_connect(nc_sock_t *ncsock);
-int core_listen(nc_sock_t *ncsock);
-int core_readwrite(nc_sock_t *nc_main, nc_sock_t *nc_slave);
-
-/* flagset.c */
-bool netcat_flag_init(unsigned int len);
-void netcat_flag_set(unsigned short port, bool flag);
-bool netcat_flag_get(unsigned short port);
-unsigned short netcat_flag_next(unsigned short port);
-int netcat_flag_count(void);
-unsigned short netcat_flag_rand(void);
-
-/* misc.c */
-int netcat_fhexdump(FILE *stream, char c, const void *data, size_t datalen);
-int netcat_snprintnum(char *str, size_t size, unsigned long number);
-void ncprint(int type, const char *fmt, ...);
-void netcat_printstats(bool force);
-char *netcat_string_split(char **buf);
-void netcat_commandline_read(int *argc, char ***argv);
-void netcat_printhelp(char *argv0);
-void netcat_printversion(void);
-#ifdef DEBUG
-const char *debug_fmt(const char *fmt, ...);
-#endif
-#ifndef USE_LINUX_SELECT
-void update_timeval(struct timeval *target);
-#endif
-
-/* netcat.c */
-extern nc_mode_t netcat_mode;
-extern bool opt_eofclose, opt_debug, opt_numeric, opt_random, opt_hexdump,
- opt_telnet, opt_zero;
-extern int opt_interval, opt_verbose, opt_wait;
-extern char *opt_outputfile;
-extern nc_proto_t opt_proto;
-extern FILE *output_fp;
-extern bool use_stdin, signal_handler, got_sigterm, got_sigint, got_sigusr1,
- commandline_need_newline;
-
-/* network.c */
-bool netcat_resolvehost(nc_host_t *dst, const char *name);
-bool netcat_getport(nc_port_t *dst, const char *port_string,
- unsigned short port_num);
-const char *netcat_strid(const nc_host_t *host, const nc_port_t *port);
-int netcat_inet_pton(const char *src, void *dst);
-const char *netcat_inet_ntop(const void *src);
-int netcat_socket_new(int domain, int type);
-int netcat_socket_new_connect(int domain, int type, const struct in_addr *addr,
- in_port_t port, const struct in_addr *local_addr,
- in_port_t local_port);
-int netcat_socket_new_listen(int domain, const struct in_addr *addr,
- in_port_t port);
-int netcat_socket_accept(int fd, int timeout);
-
-/* telnet.c */
-void netcat_telnet_parse(nc_sock_t *ncsock);
-
-/* udphelper.c */
-#ifdef USE_PKTINFO
-int udphelper_ancillary_read(struct msghdr *my_hdr,
- struct sockaddr_in *get_addr);
-#else
-int udphelper_sockets_open(int **sockbuf, in_port_t nport);
-#endif
-void udphelper_sockets_close(int *sockbuf);
diff --git a/src/telnet.c b/src/telnet.c
deleted file mode 100644
index 9196db8..0000000
--- a/src/telnet.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * telnet.c -- a small implementation of the telnet protocol routines
- * Part of the GNU netcat project
- *
- * Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- * Copyright (C) 2002 - 2003 Giovanni Giacobbi
- *
- * $Id: telnet.c,v 1.11 2003/02/28 21:49:29 themnemonic Exp $
- */
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "netcat.h"
-
-/* RFC0854 DEFINES */
-#define TELNET_SE 240 /* End of subnegotiation parameters. */
-#define TELNET_NOP 241 /* No operation. */
-#define TELNET_DM 242 /* (Data Mark) The data stream portion of a
- * Synch. This should always be accompanied
- * by a TCP Urgent notification. */
-#define TELNET_BRK 243 /* (Break) NVT character BRK. */
-#define TELNET_IP 244 /* (Interrupt Process) The function IP. */
-#define TELNET_AO 245 /* (Abort output) The function AO. */
-#define TELNET_AYT 246 /* (Are You There) The function AYT. */
-#define TELNET_EC 247 /* (Erase character) The function EC. */
-#define TELNET_EL 248 /* (Erase Line) The function EL. */
-#define TELNET_GA 249 /* (Go ahead) The GA signal. */
-#define TELNET_SB 250 /* Indicates that what follows is
- * subnegotiation of the indicated option. */
-#define TELNET_WILL 251 /* Indicates the desire to begin performing,
- * or confirmation that you are now performing,
- * the indicated option. */
-#define TELNET_WONT 252 /* Indicates the refusal to perform, or to
- * continue performing, the indicated option. */
-#define TELNET_DO 253 /* Indicates the request that the other party
- * perform, or confirmation that you are
- * expecting the other party to perform, the
- * indicated option. */
-#define TELNET_DONT 254 /* Indicates the demand that the other party
- * stop performing, or confirmation that you
- * are no longer expecting the other party
- * to perform, the indicated option. */
-#define TELNET_IAC 255 /* Data Byte 255. */
-
-/* Handle the RFC0854 telnet codes found in the receiving buffer of the
- specified socket object. This is a reliable implementation of the rfc,
- which understands most of the described codes, and automatically replies to
- the remote end with the appropriate answer codes.
- The receiving queue is then rewritten with the telnet codes stripped off,
- and the size is updated to the new length which is less than or equal to
- the original one (and can also be 0).
- The case where a telnet code is broken down (i.e. if the buffering block
- cuts it into two different calls to netcat_telnet_parse() is also handled
- properly with an internal buffer.
- If you'll ever need to reset the internal buffer for a fresh call of the
- telnet parsing function just call it with a NULL argument. */
-
-void netcat_telnet_parse(nc_sock_t *ncsock)
-{
- static unsigned char getrq[4];
- static int l = 0;
- unsigned char putrq[4], *buf = ncsock->recvq.pos;
- int i, *size = &ncsock->recvq.len, eat_chars = 0, ref_size = *size;
- debug_v(("netcat_telnet_parse(ncsock=%p)", (void *)ncsock));
-
- /* if the socket object is NULL, assume a reset command */
- if (ncsock == NULL) {
- l = 0;
- return;
- }
-
- /* loop all chars of the string */
- for (i = 0; i < ref_size; i++) {
- /* if we found IAC char OR we are fetching a IAC code string process it */
- if ((buf[i] != TELNET_IAC) && (l == 0))
- continue;
-
-#ifndef USE_OLD_TELNET
- /* this is surely a char that will be eaten */
- eat_chars++;
-#endif
-
- /* copy the char in the IAC-code-building buffer */
- getrq[l++] = buf[i];
-
- /* if this is the first char (IAC!) go straight to the next one */
- if (l == 1)
- continue;
-
- /* identify the IAC code. The effect is resolved here. If the char needs
- further data the subsection just needs to leave the index 'l' set. */
- switch (getrq[1]) {
- case TELNET_SE:
- case TELNET_NOP:
- goto do_eat_chars;
- case TELNET_DM:
- case TELNET_BRK:
- case TELNET_IP:
- case TELNET_AO:
- case TELNET_AYT:
- case TELNET_EC:
- case TELNET_EL:
- case TELNET_GA:
- case TELNET_SB:
- goto do_eat_chars;
- case TELNET_WILL:
- case TELNET_WONT:
- if (l < 3) /* need more data */
- continue;
-
- /* refuse this option */
- putrq[0] = 0xFF;
- putrq[1] = TELNET_DONT;
- putrq[2] = getrq[2];
- /* FIXME: the rfc seems not clean about what to do if the sending queue
- is not empty. Since it's the simplest solution, just override the
- queue for now, but this must change in future. */
- write(ncsock->fd, putrq, 3); /* FIXME: handle failures */
- goto do_eat_chars;
- case TELNET_DO:
- case TELNET_DONT:
- if (l < 3) /* need more data */
- continue;
-
- /* refuse this option */
- putrq[0] = 0xFF;
- putrq[1] = TELNET_WONT;
- putrq[2] = getrq[2];
- write(ncsock->fd, putrq, 3);
- goto do_eat_chars;
- case TELNET_IAC:
-#ifndef USE_OLD_TELNET
- /* insert a byte 255 in the buffer. Note that we don't know in which
- position we are, but there must be at least 1 eaten char where we
- can park our data byte. This effect is senseless if using the old
- telnet codes parsing policy. */
- buf[i - --eat_chars] = 0xFF;
-#endif
- goto do_eat_chars;
- default:
- /* FIXME: how to handle the unknown code? */
- break;
- }
- continue;
-
- do_eat_chars:
- /* ... */
- l = 0;
-
-#ifndef USE_OLD_TELNET
- if (eat_chars > 0) {
- unsigned char *from, *to;
-
- debug(("(telnet) ate %d chars\n", eat_chars));
-
- /* move the index to the overlapper character */
- i++;
-
- /* if this is the end of the string, memmove() does not care of a null
- size, it simply does nothing. */
- from = &buf[i];
- to = &buf[i - eat_chars];
- memmove(to, from, ref_size - i);
-
- /* fix the index. since the loop will auto-increment the index we need
- to put it one char before. this means that it can become negative
- but it isn't a big problem since it is signed. */
- i -= eat_chars + 1;
- ref_size -= eat_chars;
- eat_chars = 0;
- }
-#endif
- }
-
- /* we are at the end of the buffer. all we have to do now is updating the
- authoritative buffer size. In case that there is a broken-down telnet
- code, the do_eat_chars section is not executed, thus there may be some
- pending chars that needs to be removed. This is handled here in an easy
- way: since they are at the end of the buffer, just cut them playing with
- the buffer length. */
-
-#ifdef USE_OLD_TELNET
- assert(eat_chars == 0);
-#endif
-
- *size = ref_size - eat_chars;
-}
diff --git a/src/udphelper.c b/src/udphelper.c
deleted file mode 100644
index 9a3e885..0000000
--- a/src/udphelper.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * udphelper.c -- advanced udp routines for portability
- * Part of the GNU netcat project
- *
- * Author: Giovanni Giacobbi <giovanni@giacobbi.net>
- * Copyright (C) 2002 - 2003 Giovanni Giacobbi
- *
- * $Id: udphelper.c,v 1.10 2003/02/28 21:47:23 themnemonic Exp $
- */
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- ***************************************************************************/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "netcat.h"
-
-#ifndef USE_PKTINFO
-#include <sys/ioctl.h>
-#include <net/if.h>
-#ifdef HAVE_SYS_SOCKIO_H
-#include <sys/sockio.h>
-#endif
-
-/* Support Solaris extended GIFCONF */
-#ifndef SIOCGLIFCONF
-# define SIOCGLIFCONF SIOCGIFCONF
-# define lifc_len ifc_len
-# define lifc_buf ifc_buf
-# define lifc_req ifc_req
-# define lifconf ifconf
-#endif
-
-#if !defined(SIOCGLIFADDR) || !defined(SIOCGLIFFLAGS)
-/* FIXME The following warning occurs on FreeBSD:
- udphelper.c:48: warning: `SIOCGLIFADDR' redefined
- /usr/include/sys/sockio.h:78: warning: this is the location of the previous definition
- */
-# define SIOCGLIFADDR SIOCGIFADDR
-# define SIOCGLIFFLAGS SIOCGIFFLAGS
-# define SIOCGLIFDSTADDR SIOCGIFDSTADDR
-# define SIOCGLIFNETMASK SIOCGIFNETMASK
-# define lifr_addr ifr_addr
-# define lifr_name ifr_name
-# define lifr_dstaddr ifr_dstaddr
-# define lifr_flags ifr_flags
-# define ss_family sa_family
-# define lifreq ifreq
-#endif
-#endif /* !USE_PKTINFO */
-
-#ifdef USE_PKTINFO
-
-/* Reads the ancillary data buffer for the given msghdr and extracts the packet
- destination address which is copied to the `get_addr' struct.
- Returns 0 on success, a negative value otherwise. */
-
-int udphelper_ancillary_read(struct msghdr *my_hdr,
- struct sockaddr_in *get_addr)
-{
- /* let's hope that there is some ancillary data! */
- if (my_hdr->msg_controllen > 0) {
- struct cmsghdr *get_cmsg;
-
- /* We don't know which is the order of the ancillary messages and we don't
- know how many are there. So I simply parse all of them until we find
- the right one, checking the index type. */
- for (get_cmsg = CMSG_FIRSTHDR(my_hdr); get_cmsg;
- get_cmsg = CMSG_NXTHDR(my_hdr, get_cmsg)) {
- debug_v(("Analizing ancillary header (id=%d)", get_cmsg->cmsg_type));
-
- if (get_cmsg->cmsg_type == IP_PKTINFO) {
- struct in_pktinfo *get_pktinfo;
-
- /* fetch the data and run away, we don't need to parse everything */
- get_pktinfo = (struct in_pktinfo *) CMSG_DATA(get_cmsg);
- memcpy(&get_addr->sin_addr, &get_pktinfo->ipi_spec_dst,
- sizeof(get_addr->sin_addr));
- return 0;
- }
- }
- }
-
- return -1;
-}
-
-#else /* USE_PKTINFO */
-
-/* This function opens an array of sockets (stored in `sockbuf'), one for each
- different interface in the current machine. The purpose of this is to allow
- the application to determine which interface received the packet that
- otherwise would be unknown.
- Returns -1 if an error occurred; otherwise the return value is a file
- descriptor referencing the socket in the array with the highest number.
- On success, at least one socket is returned. */
-
-int udphelper_sockets_open(int **sockbuf, in_port_t nport)
-{
- int ret, i, alloc_size, dummy_sock, if_total = 1;
- int *my_sockbuf = NULL, my_sockbuf_max = 0, sock_total = 0;
- unsigned int if_pos = 0;
- struct lifconf nc_ifconf;
- struct lifreq *nc_ifreq = NULL;
-
- /* initialize the sockbuf (assuming the function will be positive */
- my_sockbuf = malloc(sizeof(int));
- if (!my_sockbuf) {
- errno = ENOMEM;
- return -1;
- }
-
- /* this is a dummy socket needed for the ioctl(2) call (this just tells the
- kernel where to look for the needed API */
- dummy_sock = socket(PF_INET, SOCK_DGRAM, 0);
- if (dummy_sock < 0)
- goto err;
-
- /* find out the interfaces configuration, allocating more memory if
- necessary. */
- do { /* FIXME: set max buffer size (what is max IF num?) */
- /* since we don't need at this stage to find out the exact number of
- interfaces, use bigger step in order not to do too many ioctl()s on
- systems with many interfaces. */
- if_total += 5;
- alloc_size = if_total * sizeof(*nc_ifreq);
-
- /* like many other syscalls, ioctl() will adjust lifc_len to the REAL
- lifc_len, so try to allocate a larger buffer in order to determine
- the total interfaces number. */
- free(nc_ifreq); /* don't use realloc here, this way it is faster */
- nc_ifreq = malloc(alloc_size);
- nc_ifconf.lifc_len = alloc_size;
- nc_ifconf.lifc_req = nc_ifreq;
- /* wait for updating nc_ifconf.lifc_req before eventually jumping to the
- error handling or it would cause a double free() to the same pointer */
- if (!nc_ifreq) {
- errno = ENOMEM;
- goto err;
- }
-
- /* FIXME: nc_ifconf has two other members (lifc_family and lifc_flags) on
- some OS (read: SunOS). They should perhaps be initialized too. */
- ret = ioctl(dummy_sock, SIOCGLIFCONF, (char *)&nc_ifconf);
- if (ret < 0)
- goto err;
- } while (nc_ifconf.lifc_len >= alloc_size);
-
- /* Now loop */
- if_total = 0;
- while (if_pos < nc_ifconf.lifc_len) {
- int newsock;
- struct sockaddr_in if_addr;
-
- nc_ifreq = (struct lifreq *)((char *)nc_ifconf.lifc_req + if_pos);
-
- /* calculate the starting offset of the next nc_ifreq */
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- if (nc_ifreq->lifr_addr.sa_len > sizeof(struct sockaddr))
- if_pos += sizeof(nc_ifreq->lifr_name) + nc_ifreq->lifr_addr.sa_len;
- else
- if_pos += sizeof(*nc_ifreq);
-#else
- if_pos += sizeof(*nc_ifreq);
-#endif
-
- /* truncated? */
- assert(if_pos <= nc_ifconf.lifc_len);
-
- /* interfaces counter (not really needed, but useful */
- if_total++;
-
- /* discard any interface not devoted to IP */
- if (nc_ifreq->lifr_addr.ss_family != AF_INET)
- continue;
-
- /* save the sockaddr_in struct before successive ioctl() calls */
- memcpy(&if_addr, &nc_ifreq->lifr_addr, sizeof(if_addr));
-
- /* we need to sort out interesting interfaces, so fetch the interface
- flags */
- ret = ioctl(dummy_sock, SIOCGLIFFLAGS, (char *)nc_ifreq);
- if (ret < 0)
- goto err;
-
- /* check that this interface is up and running */
- if (!(nc_ifreq->lifr_flags & IFF_UP))
- continue;
-
- debug(("(udphelper) Found interface %s (IP address: %s)\n",
- nc_ifreq->lifr_name, netcat_inet_ntop(&if_addr.sin_addr)));
-
- newsock = socket(PF_INET, SOCK_DGRAM, 0);
- if (newsock < 0)
- goto err;
-
- /* update immediately the sockets buffer so that any following error would
- close this one in the cleanup. */
- my_sockbuf = realloc(my_sockbuf, (++sock_total + 1) * sizeof(int));
- if (!my_sockbuf) {
- errno = ENOMEM;
- goto err;
- }
- my_sockbuf[sock_total] = newsock;
- if (newsock > my_sockbuf_max)
- my_sockbuf_max = newsock;
-
- /* bind this address to his address and to the common port */
- if_addr.sin_port = nport;
- ret = bind(newsock, (struct sockaddr *)&if_addr, sizeof(if_addr));
- if (ret < 0)
- goto err;
-
- /* if the nport was set to 0 it means that it is randomly assigned by the
- kernel, but we don't want a different port for each interface, so stick
- to this one. */
- if (nport == 0) {
- int sa_tmp_len = sizeof(if_addr);
-
- /* we don't need anymore if_addr, so we may corrupt it safely */
- ret = getsockname(newsock, (struct sockaddr *)&if_addr, &sa_tmp_len);
- if (ret < 0)
- goto err;
-
- nport = if_addr.sin_port;
- assert(nport != 0);
- }
- } /* end of while (all_interfaces) */
-
- /* ok we don't need anymore the interfaces list and the dummy socket */
- free(nc_ifconf.lifc_req);
- nc_ifconf.lifc_req = NULL;
- close(dummy_sock);
- dummy_sock = -1;
-
- /* save the total sock value in the first member of the sockbuf array */
- my_sockbuf[0] = sock_total;
- *sockbuf = my_sockbuf;
-
- debug(("(udphelper) Successfully created %d socket(s)\n", sock_total));
-
- /* On success, return the first socket for the application use, while if no
- valid interefaces were found step forward to the error handling */
- if (my_sockbuf[0] > 0)
- return my_sockbuf_max;
-
- errno = EAFNOSUPPORT;
- my_sockbuf[0] = -1;
-
- err:
- /* destroy the ifconf struct and buffers */
- free(nc_ifconf.lifc_req);
-
- /* save the errno value */
- ret = errno;
-
- if (dummy_sock >= 0)
- close(dummy_sock);
-
- /* close all the sockets and free the sockets buffer */
- for (i = 1; my_sockbuf && (i <= sock_total); i++)
- close(my_sockbuf[i]);
- free(my_sockbuf);
- *sockbuf = NULL;
-
- /* restore the errno value for parent function handling */
- errno = ret;
-
- return -1;
-}
-
-#endif /* USE_PKTINFO */
-
-/* Closes the `sockbuf' previously allocated with udphelper_sockets_open().
- The global errno is not altered by this function. */
-
-void udphelper_sockets_close(int *sockbuf)
-{
- int i, saved_errno = errno;
-
- if (!sockbuf)
- return;
-
- for (i = 1; i <= sockbuf[0]; i++)
- if (sockbuf[i] >= 0)
- close(sockbuf[i]);
-
- free(sockbuf);
- errno = saved_errno;
-}