/*
sptps_test.c -- Simple Peer-to-Peer Security test program
- Copyright (C) 2011-2013 Guus Sliepen <guus@tinc-vpn.org>,
+ Copyright (C) 2011-2014 Guus Sliepen <guus@tinc-vpn.org>
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
struct list_t *connection_list = NULL;
bool send_meta(void *c, const char *msg , int len) { return false; }
char *logfilename = NULL;
+bool do_detach = false;
struct timeval now;
+static bool special;
static bool verbose;
static bool readonly;
static bool writeonly;
static int in = 0;
static int out = 1;
-static bool send_data(void *handle, uint8_t type, const char *data, size_t len) {
+static bool send_data(void *handle, uint8_t type, const void *data, size_t len) {
char hex[len * 2 + 1];
bin2hex(data, hex, len);
if(verbose)
return true;
}
-static bool receive_record(void *handle, uint8_t type, const char *data, uint16_t len) {
+static bool receive_record(void *handle, uint8_t type, const void *data, uint16_t len) {
if(verbose)
fprintf(stderr, "Received type %d record of %hu bytes:\n", type, len);
if(!writeonly)
{"writeonly", no_argument, NULL, 'w'},
{"packet-loss", required_argument, NULL, 'L'},
{"replay-window", required_argument, NULL, 'W'},
+ {"special", no_argument, NULL, 's'},
{"verbose", required_argument, NULL, 'v'},
{"help", no_argument, NULL, 1},
{NULL, 0, NULL, 0}
const char *program_name;
static void usage() {
- fprintf(stderr, "Usage: %s [options] my_ecdsa_key_file his_ecdsa_key_file [host] port\n\n", program_name);
+ fprintf(stderr, "Usage: %s [options] my_ed25519_key_file his_ed25519_key_file [host] port\n\n", program_name);
fprintf(stderr, "Valid options are:\n"
" -d, --datagram Enable datagram mode.\n"
" -q, --quit Quit when EOF occurs on stdin.\n"
" -w, --writeonly Only send data from stdin to the socket.\n"
" -L, --packet-loss RATE Fake packet loss of RATE percent.\n"
" -R, --replay-window N Set replay window to N bytes.\n"
+ " -s, --special Enable special handling of lines starting with #, ^ and $.\n"
" -v, --verbose Display debug messages.\n"
"\n");
fprintf(stderr, "Report bugs to tinc@tinc-vpn.org.\n");
ecdsa_t *mykey = NULL, *hiskey = NULL;
bool quit = false;
- while((r = getopt_long(argc, argv, "dqrtwL:W:v", long_options, &option_index)) != EOF) {
+ while((r = getopt_long(argc, argv, "dqrstwL:W:v", long_options, &option_index)) != EOF) {
switch (r) {
case 0: /* long option */
break;
verbose = true;
break;
+ case 's': /* special character handling */
+ special = true;
+ break;
+
case '?': /* wrong options */
usage();
return 1;
hint.ai_flags = initiator ? 0 : AI_PASSIVE;
if(getaddrinfo(initiator ? argv[3] : NULL, initiator ? argv[4] : argv[3], &hint, &ai) || !ai) {
- fprintf(stderr, "getaddrinfo() failed: %s\n", strerror(errno));
+ fprintf(stderr, "getaddrinfo() failed: %s\n", sockstrerror(sockerrno));
return 1;
}
int sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if(sock < 0) {
- fprintf(stderr, "Could not create socket: %s\n", strerror(errno));
+ fprintf(stderr, "Could not create socket: %s\n", sockstrerror(sockerrno));
return 1;
}
if(initiator) {
if(connect(sock, ai->ai_addr, ai->ai_addrlen)) {
- fprintf(stderr, "Could not connect to peer: %s\n", strerror(errno));
+ fprintf(stderr, "Could not connect to peer: %s\n", sockstrerror(sockerrno));
return 1;
}
fprintf(stderr, "Connected\n");
} else {
if(bind(sock, ai->ai_addr, ai->ai_addrlen)) {
- fprintf(stderr, "Could not bind socket: %s\n", strerror(errno));
+ fprintf(stderr, "Could not bind socket: %s\n", sockstrerror(sockerrno));
return 1;
}
if(!datagram) {
if(listen(sock, 1)) {
- fprintf(stderr, "Could not listen on socket: %s\n", strerror(errno));
+ fprintf(stderr, "Could not listen on socket: %s\n", sockstrerror(sockerrno));
return 1;
}
fprintf(stderr, "Listening...\n");
sock = accept(sock, NULL, NULL);
if(sock < 0) {
- fprintf(stderr, "Could not accept connection: %s\n", strerror(errno));
+ fprintf(stderr, "Could not accept connection: %s\n", sockstrerror(sockerrno));
return 1;
}
} else {
socklen_t addrlen = sizeof addr;
if(recvfrom(sock, buf, sizeof buf, MSG_PEEK, &addr, &addrlen) <= 0) {
- fprintf(stderr, "Could not read from socket: %s\n", strerror(errno));
+ fprintf(stderr, "Could not read from socket: %s\n", sockstrerror(sockerrno));
return 1;
}
if(connect(sock, &addr, addrlen)) {
- fprintf(stderr, "Could not accept connection: %s\n", strerror(errno));
+ fprintf(stderr, "Could not accept connection: %s\n", sockstrerror(sockerrno));
return 1;
}
}
crypto_init();
FILE *fp = fopen(argv[1], "r");
+ if(!fp) {
+ fprintf(stderr, "Could not open %s: %s\n", argv[1], strerror(errno));
+ return 1;
+ }
if(!(mykey = ecdsa_read_pem_private_key(fp)))
return 1;
fclose(fp);
fp = fopen(argv[2], "r");
+ if(!fp) {
+ fprintf(stderr, "Could not open %s: %s\n", argv[2], strerror(errno));
+ return 1;
+ }
if(!(hiskey = ecdsa_read_pem_public_key(fp)))
return 1;
fclose(fp);
readonly = true;
continue;
}
- if(buf[0] == '#')
+ if(special && buf[0] == '#')
s.outseqno = atoi(buf + 1);
- if(buf[0] == '^')
+ if(special && buf[0] == '^')
sptps_send_record(&s, SPTPS_HANDSHAKE, NULL, 0);
- else if(buf[0] == '$') {
+ else if(special && buf[0] == '$') {
sptps_force_kex(&s);
if(len > 1)
sptps_send_record(&s, 0, buf, len);
if(FD_ISSET(sock, &fds)) {
ssize_t len = recv(sock, buf, sizeof buf, 0);
if(len < 0) {
- fprintf(stderr, "Could not read from socket: %s\n", strerror(errno));
+ fprintf(stderr, "Could not read from socket: %s\n", sockstrerror(sockerrno));
return 1;
}
if(len == 0) {
fprintf(stderr, "Dropped.\n");
continue;
}
- if(!sptps_receive_data(&s, buf, len) && !datagram)
- return 1;
+ char *bufp = buf;
+ while(len) {
+ size_t done = sptps_receive_data(&s, bufp, len);
+ if(!done) {
+ if(!datagram)
+ return 1;
+ } else {
+ break;
+ }
+
+ bufp += done;
+ len -= done;
+ }
}
}