* Some ICMP test applications originally written by Yin Qiu as part of
GSoC 2008. I've reworked them a bit to let them compile without warnings (or at all), and give better error messages. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37634 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
0f9dda9f00
commit
02e7b23f38
@ -33,3 +33,4 @@ SubInclude HAIKU_TOP src tests kits net preflet ;
|
||||
SubInclude HAIKU_TOP src tests kits net sock ;
|
||||
SubInclude HAIKU_TOP src tests kits net tcp_shell ;
|
||||
SubInclude HAIKU_TOP src tests kits net tcptester ;
|
||||
SubInclude HAIKU_TOP src tests kits net icmp ;
|
||||
|
22
src/tests/kits/net/icmp/Jamfile
Normal file
22
src/tests/kits/net/icmp/Jamfile
Normal file
@ -0,0 +1,22 @@
|
||||
SubDir HAIKU_TOP src tests kits net icmp ;
|
||||
|
||||
SimpleTest big_datagram :
|
||||
big_datagram.cpp
|
||||
: libnetwork.so
|
||||
;
|
||||
|
||||
SimpleTest udp_unreachable :
|
||||
udp_unreachable.cpp
|
||||
: libnetwork.so
|
||||
;
|
||||
|
||||
SimpleTest tcp_unreachable :
|
||||
tcp_unreachable.cpp
|
||||
: libnetwork.so
|
||||
;
|
||||
|
||||
SimpleTest icmp_dumper :
|
||||
icmp_dumper.cpp
|
||||
: libnetwork.so
|
||||
;
|
||||
|
155
src/tests/kits/net/icmp/big_datagram.cpp
Normal file
155
src/tests/kits/net/icmp/big_datagram.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2008-2010, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Yin Qiu
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
#define DGRM_SIZE 1600 // ought to be large enough
|
||||
|
||||
|
||||
struct pseudo_header {
|
||||
struct in_addr src;
|
||||
struct in_addr dst;
|
||||
u_int8_t zero;
|
||||
u_int8_t protocol;
|
||||
u_int16_t len;
|
||||
};
|
||||
|
||||
|
||||
static u_int16_t
|
||||
cksum(u_int16_t* buf, int nwords)
|
||||
{
|
||||
u_int32_t sum;
|
||||
for (sum = 0; nwords > 0; nwords--)
|
||||
sum += *(buf++);
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
return ~sum;
|
||||
}
|
||||
|
||||
|
||||
static struct addrinfo*
|
||||
host_serv(const char* host, const char* serv, int family, int socktype)
|
||||
{
|
||||
struct addrinfo hints, *res;
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = family;
|
||||
hints.ai_socktype = socktype;
|
||||
|
||||
int n = getaddrinfo(host, serv, &hints, &res);
|
||||
if (n != 0)
|
||||
return NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
if (argc < 3) {
|
||||
printf("Usage: %s <ip-address> <port> [nbytes]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t size;
|
||||
if (argc == 3)
|
||||
size = DGRM_SIZE;
|
||||
else
|
||||
size = atoi(argv[3]);
|
||||
|
||||
if (size - sizeof(struct ip) - sizeof(struct udphdr) < 0) {
|
||||
fprintf(stderr, "Datagram size is too small\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct addrinfo* ai = host_serv(argv[1], NULL, 0, 0);
|
||||
if (ai == NULL) {
|
||||
fprintf(stderr, "Cannot resolve %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Using datagram size %zu\n", size);
|
||||
|
||||
char* datagram = (char*)malloc(size);
|
||||
if (datagram == NULL) {
|
||||
fprintf(stderr, "Out of memory.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(datagram, 0, size);
|
||||
|
||||
struct ip* iph = (struct ip*)datagram;
|
||||
iph->ip_hl = 4;
|
||||
iph->ip_v = 4;
|
||||
iph->ip_tos = 0;
|
||||
iph->ip_len = htons(size);
|
||||
iph->ip_id = htonl(54321);
|
||||
iph->ip_off = 0;
|
||||
iph->ip_ttl = 255;
|
||||
iph->ip_p = IPPROTO_ICMP;
|
||||
iph->ip_sum = 0;
|
||||
iph->ip_src.s_addr = INADDR_ANY;
|
||||
iph->ip_dst.s_addr = ((struct sockaddr_in*)ai->ai_addr)->sin_addr.s_addr;
|
||||
// Calculates IP checksum
|
||||
iph->ip_sum = cksum((unsigned short*)datagram, iph->ip_len >> 1);
|
||||
|
||||
struct pseudo_header pHeader; // used to calculate udp checksum
|
||||
|
||||
struct udphdr* udp = (struct udphdr*)(datagram + sizeof(struct ip));
|
||||
udp->uh_sport = 0;
|
||||
udp->uh_dport = htons(atoi(argv[2]));
|
||||
udp->uh_ulen = htons(size - sizeof(struct ip));
|
||||
pHeader.src = iph->ip_src;
|
||||
pHeader.dst = iph->ip_dst;
|
||||
pHeader.zero = 0;
|
||||
pHeader.protocol = iph->ip_p;
|
||||
pHeader.len = udp->uh_ulen;
|
||||
udp->uh_sum = cksum((u_int16_t*)&pHeader, 3);
|
||||
|
||||
// Send it via a raw socket
|
||||
int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
|
||||
if (sockfd < 0) {
|
||||
fprintf(stderr, "Failed to create raw socket: %s\n", strerror(errno));
|
||||
free(datagram);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int one = 1;
|
||||
const int* val = &one;
|
||||
if (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, val, sizeof(int)) != 0) {
|
||||
fprintf(stderr, "Failed to set IP_HDRINCL on socket: %s\n",
|
||||
strerror(errno));
|
||||
free(datagram);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bytesSent = sendto(sockfd, datagram, size, 0, ai->ai_addr,
|
||||
ai->ai_addrlen);
|
||||
if (bytesSent < 0) {
|
||||
fprintf(stderr, "Failed to send the datagram via the raw socket: %s\n",
|
||||
strerror(errno));
|
||||
free(datagram);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Sent %d bytes.\n", bytesSent);
|
||||
return 0;
|
||||
}
|
||||
|
60
src/tests/kits/net/icmp/icmp_dumper.cpp
Normal file
60
src/tests/kits/net/icmp/icmp_dumper.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2008-2010, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Yin Qiu
|
||||
*/
|
||||
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#define MAXLEN 4096
|
||||
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
|
||||
if (sockfd < 0) {
|
||||
fprintf(stderr, "Could not open raw socket: %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct sockaddr_in source;
|
||||
socklen_t addrLen = sizeof(source);
|
||||
char buf[MAXLEN];
|
||||
ssize_t nbytes;
|
||||
|
||||
while ((nbytes = recvfrom(sockfd, buf, MAXLEN, 0,
|
||||
(struct sockaddr*)&source, &addrLen)) > 0) {
|
||||
int ipLen, icmpLen;
|
||||
|
||||
char host[128];
|
||||
if (!inet_ntop(AF_INET, &source.sin_addr, host, sizeof(host)))
|
||||
strcpy(host, "<unknown host>");
|
||||
|
||||
printf("Received %zd bytes of ICMP message from %s\n", nbytes, host);
|
||||
|
||||
struct ip* ip = (struct ip*)buf;
|
||||
ipLen = ip->ip_hl << 2;
|
||||
if ((icmpLen = nbytes - ipLen) < 8) {
|
||||
fprintf(stderr, "ICMP len (%d) < 8\n", icmpLen);
|
||||
exit(1);
|
||||
}
|
||||
struct icmp* icmp = (struct icmp*)(buf + ipLen);
|
||||
printf("Type: %u; Code: %u\n", icmp->icmp_type, icmp->icmp_code);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
48
src/tests/kits/net/icmp/tcp_unreachable.cpp
Normal file
48
src/tests/kits/net/icmp/tcp_unreachable.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2008-2010, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Yin Qiu
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int sockfd, status;
|
||||
struct sockaddr_in serverAddr;
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <ip-address> <port>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(&serverAddr, 0, sizeof(struct sockaddr_in));
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(atoi(argv[2]));
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if ((status = connect(sockfd, (struct sockaddr*)&serverAddr,
|
||||
sizeof(struct sockaddr_in))) < 0) {
|
||||
int e = errno;
|
||||
fprintf(stderr, "Connection failed. Status: %d\n", status);
|
||||
fprintf(stderr, "Error: %s\n", strerror(e));
|
||||
exit(1);
|
||||
} else {
|
||||
printf("Connected to remote server.\n");
|
||||
close(sockfd);
|
||||
printf("Socket closed.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
65
src/tests/kits/net/icmp/udp_unreachable.cpp
Normal file
65
src/tests/kits/net/icmp/udp_unreachable.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2008-2010, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Yin Qiu
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#define MAXLEN 4096
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int sockfd, status;
|
||||
char *str = "Hello";
|
||||
char buf[MAXLEN];
|
||||
struct sockaddr_in serverAddr;
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: %s <ip-address> <port>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(&serverAddr, 0, sizeof(struct sockaddr_in));
|
||||
serverAddr.sin_family = AF_INET;
|
||||
serverAddr.sin_port = htons(atoi(argv[2]));
|
||||
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
// We need to call connect() to receive async ICMP errors
|
||||
if (connect(sockfd, (struct sockaddr*)&serverAddr,
|
||||
sizeof(struct sockaddr_in)) < 0) {
|
||||
fprintf(stderr, "Calling connect() on UDP socket failed\n");
|
||||
exit(1);
|
||||
}
|
||||
if ((status = write(sockfd, str, strlen(str))) < 0) {
|
||||
int e = errno;
|
||||
fprintf(stderr, "UDP send failed. Status: %d\n", status);
|
||||
fprintf(stderr, "Error: %s\n", strerror(e));
|
||||
exit(1);
|
||||
} else {
|
||||
printf("%d bytes sent to remote server.\n", status);
|
||||
if ((status = read(sockfd, buf, MAXLEN)) > 0) {
|
||||
printf("Received %d bytes from remote host\n", status);
|
||||
printf("%s\n", buf);
|
||||
} else {
|
||||
// We are expecting this
|
||||
int e = errno;
|
||||
printf("Error: %s\n", strerror(e));
|
||||
}
|
||||
close(sockfd);
|
||||
printf("Socket closed.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user