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
32NetCat::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
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}
Result
Result codes.
Definition Application.h:54
const ArgumentContainer & arguments() const
Get program arguments.
ArgumentParser & parser()
Get program arguments parser.
void setDescription(const String &desc)
Set program description.
Result registerPositional(const char *name, const char *description, Size count=1)
Register a positional argument.
Result registerFlag(char arg, const char *name, const char *description)
Register a flag Argument.
static const Address toAddress(const char *address)
Convert string to IPV4 address.
Definition IPV4.cpp:94
virtual Result initialize()
Initialize the application.
Definition NetCat.cpp:53
Size m_lineLen
Definition NetCat.h:82
char m_lineBuf[64]
Line buffer.
Definition NetCat.h:81
virtual Result exec()
Execute the application event loop.
Definition NetCat.cpp:92
NetCat(int argc, char **argv)
Class constructor.
Definition NetCat.cpp:32
virtual ~NetCat()
Class destructor.
Definition NetCat.cpp:49
int m_socket
Socket.
Definition NetCat.h:78
Result udpReceive()
Definition NetCat.cpp:198
Result printLine()
Definition NetCat.cpp:121
Result udpSend()
Send UDP packet.
Definition NetCat.cpp:179
IPV4::Address m_host
Host IP.
Definition NetCat.h:85
u16 m_port
Host port.
Definition NetCat.h:88
NetworkClient * m_client
Networking client.
Definition NetCat.h:75
Result readLine()
Read one line from standard input.
Definition NetCat.cpp:129
Networking Client implementation.
Result bindSocket(const int sock, const IPV4::Address addr=0, const u16 port=0)
Bind socket to address/port.
Result initialize()
Perform initialization.
Result createSocket(const SocketType type, int *socket)
Create new socket.
POSIX-compatible application.
C int atoi(const char *nptr)
Convert a string to an integer.
Definition atoi.cpp:21
C char * strerror(int errnum)
The strerror function maps the number in errnum to a message string.
Definition strerror.cpp:20
C int errno
The lvalue errno is used by many functions to return error values.
C void exit(int status)
Terminate a process.
Definition exit.cpp:21
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
C int strcmp(const char *dest, const char *src)
Compare two strings.
Definition strcmp.cpp:20
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
C int printf(const char *format,...)
Output a formatted string to standard output.
Definition printf.cpp:22
C ssize_t read(int fildes, void *buf, size_t nbyte)
Read from a file.
Definition read.cpp:22
slong Error
Error code defined in Error.h.
Definition Types.h:159
#define ERROR(msg)
Output an error message.
Definition Log.h:61
#define ZERO
Zero value.
Definition Macros.h:43
#define DEBUG(msg)
Output a debug message to standard output.
Definition Log.h:89
Defines a socket address and port pair.
Definition socket.h:36
u32 addr
Definition socket.h:37
u16 port
Definition socket.h:38