FreeNOS
NetCat.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Niek Linnenbank
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <errno.h>
23 #include <string.h>
24 #include <sys/socket.h>
25 #include <MemoryBlock.h>
26 #include <NetworkClient.h>
27 #include <NetworkSocket.h>
28 #include <IPV4.h>
29 #include <ICMP.h>
30 #include "NetCat.h"
31 
32 NetCat::NetCat(int argc, char **argv)
33  : POSIXApplication(argc, argv)
34  , m_client(0)
35  , m_socket(0)
36  , m_lineLen(0)
37  , m_host(0)
38  , m_port(0)
39 {
40  parser().setDescription("network send/receive");
41  parser().registerPositional("DEVICE", "device name of network adapter");
42  parser().registerPositional("HOST", "host address");
43  parser().registerPositional("PORT", "host port");
44  parser().registerFlag('u', "udp", "use UDP for transport");
45  parser().registerFlag('t', "tcp", "use TCP for transport");
46  parser().registerFlag('l', "listen", "listen mode");
47 }
48 
50 {
51 }
52 
54 {
55  DEBUG("");
56 
57  // Create a network client
58  m_client = new NetworkClient(arguments().get("DEVICE"));
59 
60  // Initialize networking client
62  {
63  ERROR("failed to initialize network client for device: "
64  << arguments().get("DEVICE"));
65  return IOError;
66  }
67  // Create an UDP socket
69  {
70  ERROR("failed to create UDP socket");
71  return IOError;
72  }
73  // Convert to IPV4 address
74  if (!(m_host = IPV4::toAddress(arguments().get("HOST"))))
75  {
76  ERROR("failed to convert to IPV4 address: " << arguments().get("HOST"));
77  return IOError;
78  }
79  // Convert to port
80  m_port = atoi(arguments().get("PORT"));
81 
82  // Bind to a local port.
83  if (m_client->bindSocket(m_socket, 0, arguments().get("listen") ? m_port : 0))
84  {
85  ERROR("failed to bind socket");
86  return IOError;
87  }
88  // Success
89  return Success;
90 }
91 
93 {
94  DEBUG("");
95 
96  DEBUG("sending on device: " << arguments().get("DEVICE"));
97  DEBUG("sending to host: " << arguments().get("HOST") <<
98  " on port " << arguments().get("PORT"));
99 
100  if (arguments().get("listen"))
101  {
102  // Keep receiving from UDP
103  while (1)
104  {
105  udpReceive();
106  printLine();
107  }
108  }
109  else
110  {
111  // Keep reading and sending UDP
112  while (1)
113  {
114  readLine();
115  udpSend();
116  }
117  }
118  return Success;
119 }
120 
122 {
123  printf("%s\r\n", m_lineBuf);
124  m_lineBuf[0] = 0;
125  m_lineLen = 0;
126  return Success;
127 }
128 
130 {
131  DEBUG("");
132 
133  // Reset
134  m_lineLen = 0;
135  bool reading = true;
136 
137  // Read a line
138  while (m_lineLen < sizeof(m_lineBuf) - 3 && reading)
139  {
140  // Read a character
141  read(0, &m_lineBuf[m_lineLen], 1);
142 
143  // Process character
144  switch (m_lineBuf[m_lineLen])
145  {
146  case '\r':
147  case '\n':
148  printf("\r\n");
149  reading = false;
150  break;
151 
152  case '\b':
153  if (m_lineLen > 0)
154  {
155  m_lineLen--;
156  printf("\b \b");
157  }
158  break;
159 
160  default:
161  printf("%c", m_lineBuf[m_lineLen]);
162  m_lineLen++;
163  break;
164  }
165  }
166 
167  // Done
168  m_lineBuf[m_lineLen++] = '\r';
169  m_lineBuf[m_lineLen++] = '\n';
171 
172  // Single line dot means quit
173  if (strcmp(m_lineBuf, ".\r\n") == 0)
174  ::exit(0);
175 
176  return Success;
177 }
178 
180 {
181  DEBUG("line = " << m_lineBuf);
182 
183  // Send UDP datagram
184  struct sockaddr addr;
185  addr.addr = m_host;
186  addr.port = m_port;
187 
189  &addr, sizeof(addr));
190  if (r <= 0)
191  {
192  ERROR("failed to send UDP datagram: " << strerror(errno));
193  return IOError;
194  }
195  return Success;
196 }
197 
199 {
200  struct sockaddr addr;
201 
202  // Receive UDP datagram
203  int r = recvfrom(m_socket, m_lineBuf, sizeof(m_lineBuf), 0,
204  &addr, sizeof(addr));
205  if (r < 0)
206  {
207  ERROR("failed to receive UDP datagram: " << strerror(errno));
208  return IOError;
209  }
210  DEBUG("got " << r << " bytes from: " << addr.addr << " at port: " << addr.port);
211  m_lineBuf[r] = ZERO;
212  return Success;
213 }
NetworkClient::Success
@ Success
Definition: NetworkClient.h:101
fcntl.h
NetworkClient::initialize
Result initialize()
Perform initialization.
Definition: NetworkClient.cpp:35
NetworkClient::createSocket
Result createSocket(const SocketType type, int *socket)
Create new socket.
Definition: NetworkClient.cpp:80
errno
C int errno
The lvalue errno is used by many functions to return error values.
NetCat::udpSend
Result udpSend()
Send UDP packet.
Definition: NetCat.cpp:179
string.h
atoi
C int atoi(const char *nptr)
Convert a string to an integer.
Definition: atoi.cpp:21
POSIXApplication
POSIX-compatible application.
Definition: POSIXApplication.h:35
NetCat::m_port
u16 m_port
Host port.
Definition: NetCat.h:88
NetCat::m_host
IPV4::Address m_host
Host IP.
Definition: NetCat.h:85
Application::Success
@ Success
Definition: Application.h:55
MemoryBlock.h
Application::arguments
const ArgumentContainer & arguments() const
Get program arguments.
Definition: Application.cpp:112
ArgumentParser::setDescription
void setDescription(const String &desc)
Set program description.
Definition: ArgumentParser.cpp:95
NetCat::readLine
Result readLine()
Read one line from standard input.
Definition: NetCat.cpp:129
sockaddr
Defines a socket address and port pair.
Definition: socket.h:35
NetCat::m_socket
int m_socket
Socket.
Definition: NetCat.h:78
read
ssize_t read(int fildes, void *buf, size_t nbyte)
Read from a file.
Definition: read.cpp:22
NetCat::m_client
NetworkClient * m_client
Networking client.
Definition: NetCat.h:75
recvfrom
C int recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t addrlen)
Receive a single datagram from a socket.
Definition: recvfrom.cpp:25
Application::IOError
@ IOError
Definition: Application.h:57
DEBUG
#define DEBUG(msg)
Output a debug message to standard output.
Definition: Log.h:89
printf
int printf(const char *format,...)
Output a formatted string to standard output.
Definition: printf.cpp:22
IPV4::toAddress
static const Address toAddress(const char *address)
Convert string to IPV4 address.
Definition: IPV4.cpp:94
Error
slong Error
Error code defined in Error.h.
Definition: Types.h:159
strcmp
int strcmp(const char *dest, const char *src)
Compare two strings.
Definition: strcmp.cpp:20
stdio.h
strerror
char * strerror(int errnum)
The strerror function maps the number in errnum to a message string.
Definition: strerror.cpp:20
NetCat::initialize
virtual Result initialize()
Initialize the application.
Definition: NetCat.cpp:53
sendto
C int sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen)
Send a single datagram to a remote host.
Definition: sendto.cpp:25
Application::Result
Result
Result codes.
Definition: Application.h:53
NetCat::~NetCat
virtual ~NetCat()
Class destructor.
Definition: NetCat.cpp:49
ArgumentParser::registerFlag
Result registerFlag(char arg, const char *name, const char *description)
Register a flag Argument.
Definition: ArgumentParser.cpp:100
ICMP.h
NetworkClient
Networking Client implementation.
Definition: NetworkClient.h:44
IPV4.h
NetworkClient::bindSocket
Result bindSocket(const int sock, const IPV4::Address addr=0, const u16 port=0)
Bind socket to address/port.
Definition: NetworkClient.cpp:123
NetCat.h
ArgumentParser::registerPositional
Result registerPositional(const char *name, const char *description, Size count=1)
Register a positional argument.
Definition: ArgumentParser.cpp:119
sockaddr::addr
u32 addr
Definition: socket.h:37
NetCat::m_lineBuf
char m_lineBuf[64]
Line buffer.
Definition: NetCat.h:81
unistd.h
NetCat::m_lineLen
Size m_lineLen
Definition: NetCat.h:82
Application::parser
ArgumentParser & parser()
Get program arguments parser.
Definition: Application.cpp:102
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
socket.h
NetCat::udpReceive
Result udpReceive()
Definition: NetCat.cpp:198
NetCat::printLine
Result printLine()
Definition: NetCat.cpp:121
stdlib.h
NetworkClient.h
exit
C void exit(int status)
Terminate a process.
Definition: exit.cpp:21
NetCat::exec
virtual Result exec()
Execute the application event loop.
Definition: NetCat.cpp:92
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
NetworkClient::UDP
@ UDP
Definition: NetworkClient.h:93
NetworkSocket.h
NetCat::NetCat
NetCat(int argc, char **argv)
Class constructor.
Definition: NetCat.cpp:32
errno.h