- import of strongswan-2.7.0
- applied patch for charon
This commit is contained in:
@@ -0,0 +1 @@
|
||||
ikeping
|
||||
@@ -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.
|
||||
#
|
||||
#
|
||||
#
|
||||
@@ -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
|
||||
@@ -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:
|
||||
*
|
||||
*/
|
||||
Reference in New Issue
Block a user