Skip to content

Commit

Permalink
Added netping application for sending and receiving ping/pong packets…
Browse files Browse the repository at this point in the history
… with libnet.
  • Loading branch information
nieklinnenbank committed Feb 9, 2016
1 parent e30de74 commit f199b94
Show file tree
Hide file tree
Showing 4 changed files with 347 additions and 0 deletions.
33 changes: 33 additions & 0 deletions bin/netping/Main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 1,33 @@
/*
* Copyright (C) 2015 Niek Linnenbank
*
* 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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <Log.h>
#include <KernelLog.h>
#include "NetPing.h"

int main(int argc, char **argv)
{
/*
* TODO: StdioLog does not work yet for libipc because inside ChannelClient()
* there may also be a call to DEBUG() or ERROR().
*/
KernelLog log;
log.setMinimumLogLevel(Log::Debug);

NetPing app(argc, argv);
return app.run();
}
223 changes: 223 additions & 0 deletions bin/netping/NetPing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 1,223 @@
/*
* Copyright (C) 2015 Niek Linnenbank
*
* 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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <FreeNOS/System.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <MemoryBlock.h>
#include <NetworkClient.h>
#include <NetworkSocket.h>
#include <IPV4.h>
#include <ICMP.h>
#include "NetPing.h"

//
// Send manual formatted network packets:
//
// $ NetPing smsc --arp --dest=192.168.1.123
//
// Receive and dump network packets:
//
// $ netrecv smsc
//
// Change device parameters:
//
// $ devctl smsc ip_address=192.168.1.2 ether_address=00:11:22:33:44:55
// $ devctl serial0 baudrate=9600
//
// Show device status and statistics:
//
// $ devstat smsc
// $ devstat serial0
//

NetPing::NetPing(int argc, char **argv)
: POSIXApplication(argc, argv)
{
m_socket = 0;

m_parser.setDescription("send network pings");
m_parser.registerPositional("DEVICE", "device name of network adapter");
m_parser.registerPositional("HOST", "host address to ping");
m_parser.registerPositional("ARGS", "optional key=value arguments", 0);
m_parser.registerFlag('a', "arp", "send ARP pings");
m_parser.registerFlag('i', "icmp", "send ICMP pings");
}

NetPing::~NetPing()
{
}

NetPing::Result NetPing::initialize()
{
DEBUG("");

const char *dev = m_arguments.get("DEVICE");
const char *host = m_arguments.get("HOST");
const char *icmp = m_arguments.get("icmp");
const char *arp = m_arguments.get("arp");

if (dev)
DEBUG("sending on device: " << dev);

if (icmp)
{
DEBUG("sending ICMP packets");
icmpPing(dev, host);
}
else if (dev && host)
{
DEBUG("sending ARP packets");
arpPing(dev, host);
}
else usage();

return Success;
}

NetPing::Result NetPing::exec()
{
DEBUG("");
return Success;
}

NetPing::Result NetPing::arpPing(const char *dev,
const char *host)
{
DEBUG("");

NetworkClient client(dev);
Ethernet::Address ethAddr;
IPV4::Address ipAddr;
Size bytes;
int sock, r;

// Initialize networking client
if (client.initialize() != NetworkClient::Success)
{
ERROR("failed to initialize network client for device: " << dev);
return IOError;
}

// Create an ARP socket
if (client.createSocket(NetworkClient::ARP, &sock) != NetworkClient::Success)
{
ERROR("failed to create ARP socket");
return IOError;
}

// Convert to IPV4 address
if (!(ipAddr = IPV4::toAddress(host)))
{
ERROR("failed to convert to IPV4 address: " << host);
return IOError;
}

// Send ARP request
if (::write(sock, &ipAddr, sizeof(ipAddr)) < 0)
{
ERROR("failed to send ARP request: " << strerror(errno));
return IOError;
}
// Receive ARP reply, if any
// TODO: set a timeout on this call
if (::read(sock, &ethAddr, sizeof(ethAddr)) < 0)
{
ERROR("failed to receive ARP response: " << strerror(errno));
return IOError;
}
// Print the MAC address received
printf("Received reply for: ");

for (Size i = 0; i < sizeof(Ethernet::Address); i )
printf("%x:", ethAddr.addr[i]);
printf("\n");

// Finished
client.close(sock);
return Success;
}

NetPing::Result NetPing::icmpPing(const char *dev, const char *host)
{
DEBUG("");

NetworkClient client(dev);
Ethernet::Address ethAddr;
int sock;
Size bytes;

// Initialize networking client
if (client.initialize() != NetworkClient::Success)
{
ERROR("failed to initialize network client for device: " << dev);
return IOError;
}

// Create an ICMP socket
if (client.createSocket(NetworkClient::ICMP, &sock) != NetworkClient::Success)
{
ERROR("failed to create ARP socket");
return IOError;
}
// Connect socket to the given host
if (client.connectSocket(sock, IPV4::toAddress(host)) != NetworkClient::Success)
{
ERROR("failed to connect ICMP socket");
return IOError;
}
// Send an echo request
ICMP::Header msg;
msg.type = ICMP::EchoRequest;
msg.code = 0;
msg.checksum = 0;
msg.id = 1;
msg.sequence = 1;

// Generate checksum
msg.checksum = ICMP::checksum(&msg);

// Send the packet
if (::write(sock, &msg, sizeof(msg)) <= 0)
{
ERROR("failed to send ICMP request");
return IOError;
}
// Receive echo reply
if (::read(sock, &msg, sizeof(msg)) <= 0)
{
ERROR("failed to receive ICMP response");
return IOError;
}
// Check message type
if (msg.type != ICMP::EchoReply)
{
ERROR("invalid ICMP code in response: " << (int) msg.type);
return IOError;
}
// Print the ICMP address received
printf("Received ICMP response with id=%d sequence=%d\n",
msg.id, msg.sequence);

// Finished
::close(sock);
return Success;
}
68 changes: 68 additions & 0 deletions bin/netping/NetPing.h
Original file line number Diff line number Diff line change
@@ -0,0 1,68 @@
/*
* Copyright (C) 2015 Niek Linnenbank
*
* 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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __BIN_NETPING_H
#define __BIN_NETPING_H

#include <IPV4.h>
#include <Ethernet.h>
#include <POSIXApplication.h>

/**
* Network ping/pong application.
*/
class NetPing : public POSIXApplication
{
public:

/**
* Class constructor.
*/
NetPing(int argc, char **argv);

/**
* Class destructor.
*/
virtual ~NetPing();

/**
* Initialize the application.
*/
virtual Result initialize();

/**
* Execute the application event loop.
*/
virtual Result exec();

private:

/**
* Send ARP ping/pong.
*/
Result arpPing(const char *dev, const char *host);

/**
* Send ICMP ping/pong.
*/
Result icmpPing(const char *dev, const char *host);

/** Socket */
int m_socket;
};

#endif /* __BIN_NETPING_H */
23 changes: 23 additions & 0 deletions bin/netping/SConscript
Original file line number Diff line number Diff line change
@@ -0,0 1,23 @@
#
# Copyright (C) 2010 Niek Linnenbank
#
# 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 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

Import('build_env')

env = build_env.Clone()
env.UseLibraries([ 'libposix', 'liballoc', 'libstd', 'libexec', 'libarch', 'libnet', 'libipc', 'libfs' ])
env.UseServers(['core'])
env.TargetProgram('netping', Glob('*.cpp'), env['bin'])

0 comments on commit f199b94

Please sign in to comment.