summaryrefslogtreecommitdiff
path: root/programs/ikeping
diff options
context:
space:
mode:
authorRene Mayrhofer <rene@mayrhofer.eu.org>2006-05-22 05:12:18 +0000
committerRene Mayrhofer <rene@mayrhofer.eu.org>2006-05-22 05:12:18 +0000
commitaa0f5b38aec14428b4b80e06f90ff781f8bca5f1 (patch)
tree95f3d0c8cb0d59d88900dbbd72110d7ab6e15b2a /programs/ikeping
parent7c383bc22113b23718be89fe18eeb251942d7356 (diff)
downloadvyos-strongswan-aa0f5b38aec14428b4b80e06f90ff781f8bca5f1.tar.gz
vyos-strongswan-aa0f5b38aec14428b4b80e06f90ff781f8bca5f1.zip
Import initial strongswan 2.7.0 version into SVN.
Diffstat (limited to 'programs/ikeping')
-rw-r--r--programs/ikeping/.cvsignore1
-rw-r--r--programs/ikeping/Makefile57
-rw-r--r--programs/ikeping/ikeping.871
-rw-r--r--programs/ikeping/ikeping.c483
4 files changed, 612 insertions, 0 deletions
diff --git a/programs/ikeping/.cvsignore b/programs/ikeping/.cvsignore
new file mode 100644
index 000000000..755295a5f
--- /dev/null
+++ b/programs/ikeping/.cvsignore
@@ -0,0 +1 @@
+ikeping
diff --git a/programs/ikeping/Makefile b/programs/ikeping/Makefile
new file mode 100644
index 000000000..6c7b31d59
--- /dev/null
+++ b/programs/ikeping/Makefile
@@ -0,0 +1,57 @@
+# Makefile for the KLIPS interface utilities
+# Copyright (C) 1998, 1999 Henry Spencer.
+# Copyright (C) 1999, 2000, 2001 Richard Guy Briggs
+#
+# 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. See <http://www.fsf.org/copyleft/gpl.txt>.
+#
+# 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.
+#
+# RCSID $Id: Makefile,v 1.1 2004/03/15 20:35:27 as Exp $
+
+FREESWANSRCDIR=../..
+include ${FREESWANSRCDIR}/Makefile.inc
+
+PROGRAM=ikeping
+LIBS=${FREESWANLIB}
+
+ifeq ($(USE_IKEPING),false)
+NOINSTALL=true
+install:
+ # do nothing
+
+install_file_list:
+ # do nothing
+
+endif
+
+include ../Makefile.program
+
+#
+# $Log: Makefile,v $
+# Revision 1.1 2004/03/15 20:35:27 as
+# added files from freeswan-2.04-x509-1.5.3
+#
+# Revision 1.4 2003/06/29 21:34:49 mcr
+# added "NOINSTALL" to omit install: target from common
+# Makefile so that it can be overridden
+#
+# Revision 1.3 2003/06/25 03:57:45 mcr
+# build, but do not install "ikeping" even when we do not
+# want it as part of the system.
+#
+# Revision 1.2 2002/06/02 22:02:14 mcr
+# changed TOPDIR->FREESWANSRCDIR in all Makefiles.
+# (note that linux/net/ipsec/Makefile uses TOPDIR because this is the
+# kernel sense.)
+#
+# Revision 1.1 2002/04/24 07:55:32 mcr
+# #include patches and Makefiles for post-reorg compilation.
+#
+#
+#
diff --git a/programs/ikeping/ikeping.8 b/programs/ikeping/ikeping.8
new file mode 100644
index 000000000..a9b80b46d
--- /dev/null
+++ b/programs/ikeping/ikeping.8
@@ -0,0 +1,71 @@
+.TH IPSEC_IKEPING 8 "23 Feb 2002"
+.\" RCSID $Id: ikeping.8,v 1.1 2004/03/15 20:35:27 as Exp $
+.SH NAME
+ipsec ikeping \- send/receive ISAKMP/IKE echo requests/replies
+.SH SYNOPSIS
+.B ipsec
+.B ikeping
+[
+.B \-\-listen
+] [
+.B \-\-verbose
+] [
+.B \-\-wait
+time ] [
+.B \-\-exchangenum
+num ] [
+.B \-\-ikeport
+localport ] [
+.B \-\-ikeaddress
+address ] [
+.B \-\-inet
+] [
+.B \-\-inet6
+] destaddr[/dstport] ...
+.SH DESCRIPTION
+.I Ikeping
+sends and receives ISAKMP/IKE echo request and echo reply packets. These
+packets are intended for diagnostics purposes, in a manner similar to
+.IR ping (8)
+does for ICMP echo request/reply packets.
+.PP
+At the time of this writing, the ISAKMP echo request/reply exchange is still
+an internet-draft, and is therefore completely non-standard.
+.PP
+.I Ikeping
+will bind to the local address given by
+.B \-\-ikeaddress
+and the port number given by
+.B \-\-ikeport
+defaulting to the wildcard address and the ISAKMP port 500. An ISAKMP
+exchange of type 244 (a private use number) is sent to each of the
+address/ports listed on the command line. The exchange number may be
+overridden by the
+.B \-\-exchangenum
+option.
+.PP
+.I Ikeping
+then listens for replies, printing them as they are received. Replies
+are of exchange type 245 or the specified exchange number plus 1.
+.I Ikeping
+will keep listening until it either receives as many echo responses as it sent,
+or until the timeout period (10 seconds) has been reached. Receipt of a
+packet will reset the timer. The
+.B \-\-wait
+option can be used to specify a different timeout period.
+.PP
+If the
+.B \-\-listen
+option is given, then
+.I ikeping
+will not send any packets. Instead, it will listen for them and reply to
+each request received.
+.SH FILES
+no external files
+.SH SEE ALSO
+ping(8), ipsec_pluto(8)
+.SH HISTORY
+Written for the Linux FreeS/WAN project
+<http://www.freeswan.org>
+by Michael Richardson.
+.SH BUGS
diff --git a/programs/ikeping/ikeping.c b/programs/ikeping/ikeping.c
new file mode 100644
index 000000000..7efb26ad7
--- /dev/null
+++ b/programs/ikeping/ikeping.c
@@ -0,0 +1,483 @@
+/* send out an IKE "ping" packet.
+ * Copyright (C) 2002 Michael Richardson
+ * Copyright (C) 2002 D. Hugh Redelmeier.
+ *
+ * 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. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * 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.
+ *
+ * RCSID $Id: ikeping.c,v 1.1 2004/03/15 20:35:27 as Exp $
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <getopt.h>
+#include <assert.h>
+#include <poll.h>
+
+#include <freeswan.h>
+
+#include "../pluto/constants.h"
+#include "../pluto/packet.h"
+
+#ifndef ISAKMP_XCHG_ECHOREQUEST
+#define ISAKMP_XCHG_ECHOREQUEST 30 /* Echo Request */
+#define ISAKMP_XCHG_ECHOREPLY 31 /* Echo Reply */
+#endif
+
+#ifndef ISAKMP_XCGH_ECHOREQUEST_PRIV
+#define ISAKMP_XCHG_ECHOREQUEST_PRIV 244 /* Private Echo Request */
+#define ISAKMP_XCHG_ECHOREPLY_PRIV 245 /* Private Echo Reply */
+#endif
+
+
+/* what exchange number to use for outgoing requests */
+static int exchange_number;
+
+static void
+help(void)
+{
+ fprintf(stderr,
+ "Usage:\n\n"
+ "ikeping"
+ " [--listen] causes IKEping to open a socket and reply to requests.\n"
+ " [--verbose] causes IKEping to hexdump all packets sent/received.\n"
+ " [--ikeport <port-number>] port to listen on/send from\n"
+ " [--ikeaddress <address>] address to listen on/send from\n"
+ " [--inet] just send/listen on IPv4 socket\n"
+ " [--inet6] just send/listen on IPv6 socket\n"
+ " [--version] just dump version number and exit\n"
+ " [--exchangenum num] use num instead of 244 for the exchange type.\n"
+ " [--wait seconds] time to wait for replies, defaults to 10 seconds.\n"
+ " host/port ...\n\n"
+ "FreeS/WAN %s\n",
+ ipsec_version_code());
+}
+
+static void
+hton_ping(struct isakmp_hdr *ih)
+{
+ u_int32_t *ihp;
+
+ ihp=(u_int32_t *)ih;
+
+ /* put it in network byte order. */
+ /* cookies are byte viewed anyway */
+ ihp[4]=htonl(ihp[4]);
+ ih->isa_msgid = htonl(ih->isa_msgid);
+ ih->isa_length = htonl(ih->isa_length);
+}
+
+static void
+ntoh_ping(struct isakmp_hdr *ih)
+{
+ u_int32_t *ihp;
+
+ ihp=(u_int32_t *)ih;
+
+ /* put it in network byte order. */
+ /* cookies are byte viewed anyway */
+ ihp[4]=ntohl(ihp[4]);
+ ih->isa_msgid = ntohl(ih->isa_msgid);
+ ih->isa_length = ntohl(ih->isa_length);
+}
+
+
+/*
+ * send an IKE ping
+ *
+ */
+static void
+send_ping(int afamily,
+ int s,
+ ip_address *raddr,
+ int rport)
+{
+ struct isakmp_hdr ih;
+ int i, raddrlen;
+
+ raddrlen=0;
+
+ for(i=0; i<COOKIE_SIZE; i++) {
+ ih.isa_icookie[i]=rand()&0xff;
+ }
+
+ for(i=0; i<COOKIE_SIZE; i++) {
+ ih.isa_rcookie[i]=rand()&0xff;
+ }
+
+ ih.isa_np = NOTHING_WRONG;
+ ih.isa_version = (1 << ISA_MAJ_SHIFT) | 0;
+ ih.isa_xchg = (exchange_number ?
+ exchange_number : ISAKMP_XCHG_ECHOREQUEST_PRIV);
+ ih.isa_flags =0;
+ ih.isa_msgid =rand();
+ ih.isa_length=0;
+
+ switch(afamily) {
+ case AF_INET:
+ raddr->u.v4.sin_port = htons(rport);
+ raddrlen=sizeof(raddr->u.v4);
+ break;
+
+ case AF_INET6:
+ raddr->u.v6.sin6_port = htons(rport);
+ raddrlen=sizeof(raddr->u.v6);
+ break;
+ }
+
+ hton_ping(&ih);
+
+ if(sendto(s, &ih, sizeof(ih), 0, (struct sockaddr *)raddr, raddrlen) < 0) {
+ perror("sendto");
+ exit(5);
+ }
+}
+
+/*
+ * send an IKE ping
+ *
+ */
+static void
+reply_packet(int afamily,
+ int s,
+ ip_address *dst_addr,
+ int dst_len,
+ struct isakmp_hdr *op)
+{
+ int i, tmp;
+
+ tmp=afamily; /* shut up compiler */
+
+ for(i=0; i<COOKIE_SIZE; i++) {
+ tmp=op->isa_icookie[i];
+ op->isa_icookie[i]=op->isa_rcookie[i];
+ op->isa_rcookie[i]=tmp;
+ }
+
+ op->isa_np = NOTHING_WRONG;
+ op->isa_version = (1 << ISA_MAJ_SHIFT) | 0;
+ op->isa_xchg = ISAKMP_XCHG_ECHOREPLY;
+ op->isa_flags =0;
+ op->isa_msgid =rand();
+ op->isa_length=0;
+
+ hton_ping(op);
+
+ if(sendto(s, op, sizeof(*op), 0, (struct sockaddr *)dst_addr, dst_len) < 0) {
+ perror("sendto");
+ exit(5);
+ }
+}
+
+/*
+ * receive and decode packet.
+ *
+ */
+static void
+receive_ping(int afamily, int s, int reply)
+{
+ ip_address sender;
+ struct isakmp_hdr ih;
+ char buf[64];
+ int n, rport, sendlen;
+ const char *xchg_name;
+ int xchg;
+
+ rport = 500;
+ xchg = 0;
+ sendlen=sizeof(sender);
+ n = recvfrom(s, &ih, sizeof(ih), 0, (struct sockaddr *)&sender, &sendlen);
+
+ addrtot(&sender, 0, buf, sizeof(buf));
+ switch(afamily) {
+ case AF_INET:
+ rport = sender.u.v4.sin_port;
+ break;
+
+ case AF_INET6:
+ rport = sender.u.v6.sin6_port;
+ break;
+ }
+
+ if((unsigned int)n < sizeof(ih)) {
+ fprintf(stderr, "read short packet (%d) from %s/%d\n",
+ n, buf, rport);
+ return;
+ }
+
+ /* translate from network byte order */
+ ntoh_ping(&ih);
+
+
+ if(ih.isa_xchg == ISAKMP_XCHG_ECHOREQUEST ||
+ ih.isa_xchg == ISAKMP_XCHG_ECHOREQUEST_PRIV ||
+ (exchange_number!=0 && ih.isa_xchg == exchange_number)) {
+ xchg_name="echo-request";
+ xchg=ISAKMP_XCHG_ECHOREQUEST;
+ } else if(ih.isa_xchg == ISAKMP_XCHG_ECHOREPLY ||
+ ih.isa_xchg == ISAKMP_XCHG_ECHOREPLY_PRIV ||
+ (exchange_number!=0 && ih.isa_xchg == exchange_number+1)) {
+ xchg_name="echo-reply";
+ } else {
+ xchg_name="";
+ }
+
+ printf("received %d(%s) packet from %s/%d of len: %d\n",
+ ih.isa_xchg, xchg_name, buf, ntohs(rport), n);
+ printf("\trcookie=%08x_%08x icookie=%08x_%08x msgid=%08x\n",
+ *(u_int32_t *)(ih.isa_icookie),
+ *(u_int32_t *)(ih.isa_icookie+4),
+ *(u_int32_t *)(ih.isa_rcookie),
+ *(u_int32_t *)(ih.isa_rcookie+4),
+ ih.isa_msgid);
+ printf("\tnp=%03d version=%d.%d xchg=%s(%d)\n",
+ ih.isa_np,
+ ih.isa_version >> ISA_MAJ_SHIFT,
+ ih.isa_version & ISA_MIN_MASK,
+ xchg_name,
+ ih.isa_xchg);
+
+ if(reply && xchg==ISAKMP_XCHG_ECHOREQUEST) {
+ reply_packet(afamily, s, &sender, sendlen, &ih);
+ }
+}
+
+static const struct option long_opts[] = {
+ /* name, has_arg, flag, val */
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { "verbose", no_argument, NULL, 'v' },
+ { "listen", no_argument, NULL, 's' },
+ { "ikeport", required_argument, NULL, 'p' },
+ { "ikeaddress", required_argument, NULL, 'b' },
+ { "inet", no_argument, NULL, '4' },
+ { "inet6", no_argument, NULL, '6' },
+ { "exchangenum", required_argument, NULL, 'n' },
+ { "wait", required_argument, NULL, 'w' },
+ { 0,0,0,0 }
+};
+
+int
+main(int argc, char **argv)
+{
+ char *foo;
+ const char *errstr;
+ int s;
+ int listen_only;
+ int lport,dport;
+ int afamily;
+ int pfamily;
+ int c;
+ int numSenders, numReceived, noDNS;
+ int waitTime;
+ int verbose, timedOut;
+ ip_address laddr, raddr;
+
+ afamily=AF_INET;
+ pfamily=PF_INET;
+ lport=500;
+ dport=500;
+ waitTime=10;
+ verbose=0;
+ listen_only=0;
+ noDNS=0;
+ bzero(&laddr, sizeof(laddr));
+
+ while((c = getopt_long(argc, argv, "hVnvsp:b:46E:w:", long_opts, 0))!=EOF) {
+ switch (c) {
+ case 'h': /* --help */
+ help();
+ return 0; /* GNU coding standards say to stop here */
+
+ case 'V': /* --version */
+ fprintf(stderr, "FreeS/WAN %s\n", ipsec_version_code());
+ return 0; /* GNU coding standards say to stop here */
+
+ case 'v': /* --label <string> */
+ verbose++;
+ continue;
+
+ case 'n':
+ noDNS=1;
+ break;
+
+ case 'E':
+ exchange_number=strtol(optarg, &foo, 0);
+ if(optarg==foo || exchange_number < 1 || exchange_number>255) {
+ fprintf(stderr, "Invalid exchange number '%s' (should be 1<=x<255)\n",
+ optarg);
+ exit(1);
+ }
+ continue;
+
+
+ case 's':
+ listen_only++;
+ continue;
+
+ case 'p':
+ lport=strtol(optarg, &foo, 0);
+ if(optarg==foo || lport <0 || lport>65535) {
+ fprintf(stderr, "Invalid port number '%s' (should be 0<=x<65536)\n",
+ optarg);
+ exit(1);
+ }
+ continue;
+
+ case 'w':
+ waitTime=strtol(optarg, &foo, 0);
+ if(optarg==foo || waitTime < 0) {
+ fprintf(stderr, "Invalid waittime number '%s' (should be 0<=x)\n",
+ optarg);
+ exit(1);
+ }
+ continue;
+
+ case 'b':
+ errstr = ttoaddr(optarg, strlen(optarg), afamily, &laddr);
+ if(errstr!=NULL) {
+ fprintf(stderr, "Invalid local address '%s': %s\n",
+ optarg, errstr);
+ exit(1);
+ }
+ continue;
+
+ case '4':
+ afamily=AF_INET;
+ pfamily=PF_INET;
+ continue;
+
+ case '6':
+ afamily=AF_INET6;
+ pfamily=PF_INET6;
+ continue;
+
+ default:
+ assert(FALSE); /* unknown return value */
+ }
+ }
+
+ s=socket(pfamily, SOCK_DGRAM, IPPROTO_UDP);
+ if(s < 0) {
+ perror("socket");
+ exit(3);
+ }
+
+ switch(afamily) {
+ case AF_INET:
+ laddr.u.v4.sin_port = htons(lport);
+ if(bind(s, (struct sockaddr *)&laddr.u.v4, sizeof(laddr.u.v4)) < 0) {
+ perror("v4 bind");
+ exit(5);
+ }
+ break;
+
+ case AF_INET6:
+ laddr.u.v6.sin6_port = htons(lport);
+ if(bind(s, (struct sockaddr *)&laddr.u.v6, sizeof(laddr.u.v6)) < 0) {
+ perror("v6 bind");
+ exit(5);
+ }
+ break;
+ }
+
+ numSenders = 0;
+
+ if(!listen_only) {
+ while(optind < argc) {
+ char *port;
+ char *host;
+ char namebuf[128];
+
+ host = argv[optind];
+
+ port = strchr(host, '/');
+ dport=500;
+ if(port) {
+ *port='\0';
+ port++;
+ dport= strtol(port, &foo, 0);
+ if(port==foo || dport < 0 || dport > 65535) {
+ fprintf(stderr, "Invalid port number '%s' "
+ "(should be 0<=x<65536)\n",
+ port);
+ exit(1);
+ }
+ }
+
+ errstr = ttoaddr(host, strlen(host),
+ afamily, &raddr);
+ if(errstr!=NULL) {
+ fprintf(stderr, "Invalid remote address '%s': %s\n",
+ host, errstr);
+ exit(1);
+ }
+
+ addrtot(&raddr, 0, namebuf, sizeof(namebuf));
+
+ printf("Sending packet to %s/%d\n", namebuf, dport);
+
+ send_ping(afamily, s, &raddr, dport);
+ numSenders++;
+ optind++;
+ }
+ }
+
+ timedOut = 0;
+ numReceived=0;
+
+ /* really should catch ^C and print stats on exit */
+ while(numSenders > 0 || listen_only) {
+ struct pollfd ready;
+ int n;
+
+ ready.fd = s;
+ ready.events = POLLIN;
+
+ n = poll(&ready, 1, waitTime);
+ if(n < 0) {
+ perror("poll");
+ exit(1);
+ }
+
+ if(n == 0 && !listen_only) {
+ break;
+ }
+
+ if(n == 1) {
+ numReceived++;
+ receive_ping(afamily, s, listen_only);
+ }
+ }
+
+ if(numReceived > 0) {
+ printf("%d packets sent, %d packets received. %d packet loss\n",
+ numSenders, numReceived, numSenders*100/numReceived);
+ }
+ exit(0);
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * c-basic-offset: 4
+ * End:
+ *
+ */