⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ikeping.c

📁 This a good VPN source
💻 C
字号:
/* 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.7 2004/10/17 23:58:59 mcr 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 <openswan.h>#include "constants.h"#include "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 voidhelp(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 voidhton_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 voidntoh_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 voidsend_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 voidreply_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 voidreceive_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 }};intmain(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: * */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -