Added sending via tcp (established) conneciton. removed --debug as an option. Some minor code reformatting and refactoring.
git-svn-id: file:///home/mbr/svn/fwknop/trunk@95 510a4753-2344-4c79-9c09-4d669213fbeb
This commit is contained in:
parent
7206fa03a6
commit
7817e44264
@ -202,82 +202,36 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
|
||||
options->port = FKO_DEFAULT_PORT;
|
||||
|
||||
while ((cmd_arg = getopt_long(argc, argv,
|
||||
"A:a:D:G:S:Q:p:P:B:bghqdTvVn", cmd_opts, &index)) != -1) {
|
||||
"a:A:bB:D:gG:hm:np:P:qQ:S:TU:vV", cmd_opts, &index)) != -1) {
|
||||
|
||||
switch(cmd_arg) {
|
||||
case 'A':
|
||||
strlcpy(options->access_str, optarg, MAX_LINE_LEN);
|
||||
break;
|
||||
case 'D':
|
||||
strlcpy(options->spa_server_ip_str, optarg, MAX_IP_STR_LEN);
|
||||
break;
|
||||
case 'a':
|
||||
strlcpy(options->allow_ip_str, optarg, MAX_IP_STR_LEN);
|
||||
break;
|
||||
case 'G':
|
||||
strlcpy(options->get_key_file, optarg, MAX_PATH_LEN);
|
||||
break;
|
||||
case 'B':
|
||||
strlcpy(options->save_packet_file, optarg, MAX_PATH_LEN);
|
||||
case 'A':
|
||||
strlcpy(options->access_str, optarg, MAX_LINE_LEN);
|
||||
break;
|
||||
case 'b':
|
||||
options->save_packet_file_append = 1;
|
||||
break;
|
||||
case 'Q':
|
||||
strlcpy(options->spoof_ip_src_str, optarg, MAX_IP_STR_LEN);
|
||||
case 'B':
|
||||
strlcpy(options->save_packet_file, optarg, MAX_PATH_LEN);
|
||||
break;
|
||||
case 'U':
|
||||
strlcpy(options->spoof_user, optarg, MAX_USERNAME_LEN);
|
||||
case 'D':
|
||||
strlcpy(options->spa_server_ip_str, optarg, MAX_IP_STR_LEN);
|
||||
break;
|
||||
case 'p':
|
||||
options->port = atoi(optarg);
|
||||
if (options->port < 0 || options->port > 65535) {
|
||||
fprintf(stderr, "[*] Unrecognized port: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
case 'g':
|
||||
case GPG_ENCRYPTION:
|
||||
options->use_gpg = 1;
|
||||
break;
|
||||
case 'P':
|
||||
if (strncmp(optarg, "udp", strlen("udp")) == 0)
|
||||
options->proto = IPPROTO_UDP;
|
||||
else if (strncmp(optarg, "tcp", strlen("tcp")) == 0)
|
||||
options->proto = IPPROTO_TCP;
|
||||
else if (strncmp(optarg, "icmp", strlen("icmp")) == 0)
|
||||
options->proto = IPPROTO_ICMP;
|
||||
else {
|
||||
fprintf(stderr, "[*] Unrecognized protocol: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
options->src_port = atoi(optarg);
|
||||
if (options->port < 0 || options->port > 65535) {
|
||||
fprintf(stderr, "[*] Unrecognized port: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
options->quiet = 1;
|
||||
break;
|
||||
case 'n':
|
||||
options->no_save = 1;
|
||||
break;
|
||||
case 'T':
|
||||
options->test = 1;
|
||||
break;
|
||||
case 'd':
|
||||
options->debug = 1;
|
||||
break;
|
||||
case 'v':
|
||||
options->verbose = 1;
|
||||
break;
|
||||
case 'V':
|
||||
options->version = 1;
|
||||
case 'G':
|
||||
strlcpy(options->get_key_file, optarg, MAX_PATH_LEN);
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
exit(0);
|
||||
case 'm':
|
||||
case FKO_DIGEST_NAME:
|
||||
case 'm':
|
||||
if(strncasecmp(optarg, "md5", 3) == 0)
|
||||
options->digest_type = FKO_DIGEST_MD5;
|
||||
else if(strncasecmp(optarg, "sha1", 4) == 0)
|
||||
@ -290,9 +244,54 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
case GPG_ENCRYPTION:
|
||||
options->use_gpg = 1;
|
||||
case 'n':
|
||||
options->no_save = 1;
|
||||
break;
|
||||
case 'p':
|
||||
options->port = atoi(optarg);
|
||||
if (options->port < 0 || options->port > 65535) {
|
||||
fprintf(stderr, "[*] Unrecognized port: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
if (strncmp(optarg, "udp", strlen("udp")) == 0)
|
||||
options->proto = FKO_PROTO_UDP;
|
||||
else if (strncmp(optarg, "tcpraw", strlen("tcpraw")) == 0)
|
||||
options->proto = FKO_PROTO_TCP_RAW;
|
||||
else if (strncmp(optarg, "tcp", strlen("tcp")) == 0)
|
||||
options->proto = FKO_PROTO_TCP;
|
||||
else if (strncmp(optarg, "icmp", strlen("icmp")) == 0)
|
||||
options->proto = FKO_PROTO_ICMP;
|
||||
else {
|
||||
fprintf(stderr, "[*] Unrecognized protocol: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
options->quiet = 1;
|
||||
break;
|
||||
case 'Q':
|
||||
strlcpy(options->spoof_ip_src_str, optarg, MAX_IP_STR_LEN);
|
||||
break;
|
||||
case 'S':
|
||||
options->src_port = atoi(optarg);
|
||||
if (options->port < 0 || options->port > 65535) {
|
||||
fprintf(stderr, "[*] Unrecognized port: %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'T':
|
||||
options->test = 1;
|
||||
break;
|
||||
case 'U':
|
||||
strlcpy(options->spoof_user, optarg, MAX_USERNAME_LEN);
|
||||
break;
|
||||
case 'v':
|
||||
options->verbose = 1;
|
||||
break;
|
||||
case 'V':
|
||||
options->version = 1;
|
||||
break;
|
||||
case GPG_RECIP_KEY:
|
||||
options->use_gpg = 1;
|
||||
@ -334,7 +333,7 @@ config_init(fko_cli_options_t *options, int argc, char **argv)
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "\n%s version %s\n%s\n\n", MY_NAME, MY_VERSION, MY_DESC);
|
||||
fprintf(stderr, "\n%s client version %s\n%s\n\n", MY_NAME, MY_VERSION, MY_DESC);
|
||||
fprintf(stderr,
|
||||
"Usage: fwknop -A <port list> [-s|-R|-a] -D <spa_server> [options]\n\n"
|
||||
" -h, --help - Print this usage message and exit.\n"
|
||||
@ -348,8 +347,10 @@ usage(void)
|
||||
" -D, --destination - Specify the IP address of the fwknop server.\n"
|
||||
" -p, --server-port - Set the destination port for outgoing SPA\n"
|
||||
" packet.\n"
|
||||
" -P, --source-protocol - Set the protocol (UDP, TCP, ICMP) for the\n"
|
||||
" outgoing SPA packet.\n"
|
||||
" -P, --source-protocol - Set the protocol (udp, tcp, tcpraw, icmp) for\n"
|
||||
" the outgoing SPA packet. Note: The 'tcpraw'\n"
|
||||
" and 'icmp' modes use raw sockets and thus\n"
|
||||
" require root access to run.\n"
|
||||
" -S, --source-port - Set the source port for outgoing SPA packet.\n"
|
||||
" -Q, --spoof-source - Set the source IP for outgoing SPA packet.\n"
|
||||
" -U, --spoof-user - Set the username within outgoing SPA packet.\n"
|
||||
@ -357,7 +358,6 @@ usage(void)
|
||||
" -G, --get-key - Load an encryption key/password from a file.\n"
|
||||
" -T, --test - Build the SPA packet but do not send it over\n"
|
||||
" the network.\n"
|
||||
" -d, --debug - Set debug mode.\n"
|
||||
" -v, --verbose - Set verbose mode.\n"
|
||||
" -V, --version - Print version number.\n"
|
||||
" -m, --digest-type - Speciy the message digest algorithm to use.\n"
|
||||
|
||||
@ -46,30 +46,29 @@ enum {
|
||||
*/
|
||||
static struct option cmd_opts[] =
|
||||
{
|
||||
{"access", 1, NULL, 'A'},
|
||||
{"destination", 1, NULL, 'D'},
|
||||
{"allow-ip", 1, NULL, 'a'},
|
||||
{"server-port", 1, NULL, 'p'},
|
||||
{"server-proto", 1, NULL, 'P'},
|
||||
{"source-port", 1, NULL, 'S'},
|
||||
{"spoof-src", 1, NULL, 'Q'},
|
||||
{"spoof-user", 1, NULL, 'U'},
|
||||
{"save-packet", 1, NULL, 'B'},
|
||||
{"access", 1, NULL, 'A'},
|
||||
{"save-packet-append", 0, NULL, 'b'},
|
||||
{"get-key", 1, NULL, 'G'},
|
||||
{"quiet", 0, NULL, 'q'},
|
||||
{"debug", 0, NULL, 'd'},
|
||||
{"test", 0, NULL, 'T'},
|
||||
{"no-save", 0, NULL, 'n'},
|
||||
{"verbose", 0, NULL, 'v'},
|
||||
{"version", 0, NULL, 'V'},
|
||||
{"help", 0, NULL, 'h'},
|
||||
{"save-packet", 1, NULL, 'B'},
|
||||
{"digest-type", 1, NULL, FKO_DIGEST_NAME},
|
||||
{"destination", 1, NULL, 'D'},
|
||||
{"gpg-encryption", 0, NULL, 'g'},
|
||||
{"gpg-recipient-key", 1, NULL, GPG_RECIP_KEY },
|
||||
{"gpg-signer-key", 1, NULL, GPG_SIGNER_KEY },
|
||||
{"gpg-home-dir", 1, NULL, GPG_HOME_DIR },
|
||||
{"gpg-agent", 0, NULL, GPG_AGENT },
|
||||
{"get-key", 1, NULL, 'G'},
|
||||
{"help", 0, NULL, 'h'},
|
||||
{"no-save", 0, NULL, 'n'},
|
||||
{"server-port", 1, NULL, 'p'},
|
||||
{"server-proto", 1, NULL, 'P'},
|
||||
{"quiet", 0, NULL, 'q'},
|
||||
{"spoof-src", 1, NULL, 'Q'},
|
||||
{"source-port", 1, NULL, 'S'},
|
||||
{"test", 0, NULL, 'T'},
|
||||
{"spoof-user", 1, NULL, 'U'},
|
||||
{"verbose", 0, NULL, 'v'},
|
||||
{"version", 0, NULL, 'V'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
17
src/fwknop.c
17
src/fwknop.c
@ -29,12 +29,10 @@
|
||||
#include "utils.h"
|
||||
#include "getpasswd.h"
|
||||
|
||||
/* Used by the get_user_pw function below.
|
||||
/* prototypes
|
||||
*/
|
||||
#define CRYPT_OP_ENCRYPT 1
|
||||
#define CRYPT_OP_DECRYPT 2
|
||||
|
||||
char* get_user_pw(fko_cli_options_t *options, int crypt_op);
|
||||
static void display_ctx(fko_ctx_t ctx);
|
||||
void errmsg(char *msg, int err);
|
||||
|
||||
int
|
||||
@ -60,7 +58,6 @@ main(int argc, char **argv)
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* Display version info and exit.
|
||||
*/
|
||||
if (options.version) {
|
||||
@ -184,13 +181,17 @@ main(int argc, char **argv)
|
||||
*/
|
||||
if (!options.test)
|
||||
{
|
||||
//if(send_spa_packet(ctx, &options) < 1)
|
||||
res = send_spa_packet(ctx, &options);
|
||||
if(res < 1)
|
||||
if(res < 0)
|
||||
{
|
||||
perror("send_spa_packet");
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(options.verbose)
|
||||
fprintf(stderr, "[+] send_spa_packet: bytes sent: %i\n", res);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -295,6 +296,8 @@ errmsg(char *msg, int err) {
|
||||
MY_NAME, msg, err, fko_errstr(err));
|
||||
}
|
||||
|
||||
/* Show the fields of the FKO context.
|
||||
*/
|
||||
static void
|
||||
display_ctx(fko_ctx_t ctx)
|
||||
{
|
||||
|
||||
@ -29,8 +29,9 @@
|
||||
|
||||
#include "fwknop_common.h"
|
||||
|
||||
/* prototypes
|
||||
/* Used by the get_user_pw function below.
|
||||
*/
|
||||
static void display_ctx(fko_ctx_t ctx);
|
||||
#define CRYPT_OP_ENCRYPT 1
|
||||
#define CRYPT_OP_DECRYPT 2
|
||||
|
||||
#endif /* FWKNOP_H */
|
||||
|
||||
@ -35,6 +35,8 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#if STDC_HEADERS
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -74,9 +76,18 @@
|
||||
*/
|
||||
#define DEF_CONFIG_FILE MY_NAME".conf"
|
||||
|
||||
/* Protocol assignment values
|
||||
*/
|
||||
enum {
|
||||
FKO_PROTO_UDP,
|
||||
FKO_PROTO_TCP,
|
||||
FKO_PROTO_TCP_RAW,
|
||||
FKO_PROTO_ICMP
|
||||
};
|
||||
|
||||
/* Other common defines
|
||||
*/
|
||||
#define FKO_DEFAULT_PROTO IPPROTO_UDP
|
||||
#define FKO_DEFAULT_PROTO FKO_PROTO_UDP
|
||||
#define FKO_DEFAULT_PORT 62201
|
||||
#define MAX_IP_STR_LEN 16
|
||||
|
||||
@ -109,7 +120,6 @@ typedef struct fko_cli_options
|
||||
unsigned int digest_type;
|
||||
|
||||
/* Various command-line flags */
|
||||
unsigned char debug;
|
||||
unsigned char quiet; /* --quiet mode */
|
||||
unsigned char verbose; /* --verbose mode */
|
||||
unsigned char version; /* --version */
|
||||
|
||||
327
src/spa_comm.c
327
src/spa_comm.c
@ -31,96 +31,134 @@
|
||||
unsigned short
|
||||
chksum(unsigned short *buf, int nbytes)
|
||||
{
|
||||
unsigned int sum;
|
||||
unsigned short oddbyte;
|
||||
unsigned int sum;
|
||||
unsigned short oddbyte;
|
||||
|
||||
sum = 0;
|
||||
while (nbytes > 1) {
|
||||
sum += *buf++;
|
||||
nbytes -= 2;
|
||||
}
|
||||
sum = 0;
|
||||
while (nbytes > 1)
|
||||
{
|
||||
sum += *buf++;
|
||||
nbytes -= 2;
|
||||
}
|
||||
|
||||
if (nbytes == 1) {
|
||||
oddbyte = 0;
|
||||
*((unsigned short *) &oddbyte) = *(unsigned short *) buf;
|
||||
sum += oddbyte;
|
||||
}
|
||||
if (nbytes == 1)
|
||||
{
|
||||
oddbyte = 0;
|
||||
*((unsigned short *) &oddbyte) = *(unsigned short *) buf;
|
||||
sum += oddbyte;
|
||||
}
|
||||
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
|
||||
return (unsigned short) ~sum;
|
||||
return (unsigned short) ~sum;
|
||||
}
|
||||
|
||||
/* Send the SPA data via UDP packet.
|
||||
*/
|
||||
int
|
||||
send_spa_packet_udp(fko_ctx_t ctx, struct sockaddr_in *saddr,
|
||||
send_spa_packet_udp(char *spa_data, int sd_len, struct sockaddr_in *saddr,
|
||||
struct sockaddr_in *daddr, fko_cli_options_t *options)
|
||||
{
|
||||
int res;
|
||||
char *spa_data;
|
||||
int sock, res;
|
||||
|
||||
int sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
if (sock < 0) {
|
||||
fprintf(stderr, "[*] Could not create UDP socket.\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
res = fko_get_spa_data(ctx, &spa_data);
|
||||
|
||||
if(res != FKO_SUCCESS)
|
||||
if (sock < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"send_spa_packet_udp: Error #%i from fko_get_spa_data: %s\n",
|
||||
res, fko_errstr(res)
|
||||
);
|
||||
return(0);
|
||||
perror("[*] send_spa_packet_udp: create socket: ");
|
||||
return(sock);
|
||||
}
|
||||
|
||||
return(sendto(sock, spa_data, strlen(spa_data), 0,
|
||||
(struct sockaddr *)daddr, sizeof(*daddr)));
|
||||
res = sendto(sock, spa_data, sd_len, 0,
|
||||
(struct sockaddr *)daddr, sizeof(*daddr));
|
||||
|
||||
if(res < 0)
|
||||
{
|
||||
perror("[*] send_spa_packet_udp: sendto error: ");
|
||||
}
|
||||
else if(res != sd_len)
|
||||
{
|
||||
fprintf(stderr, "[#] Warning: bytes sent (%i) not spa data length (%i).\n",
|
||||
res, sd_len);
|
||||
}
|
||||
|
||||
close(sock);
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
/* Send the SPA data via TCP packet.
|
||||
/* Send the SPA data packet via an established TCP connection.
|
||||
*/
|
||||
int
|
||||
send_spa_packet_tcp(fko_ctx_t ctx, struct sockaddr_in *saddr,
|
||||
send_spa_packet_tcp(char *spa_data, int sd_len, struct sockaddr_in *saddr,
|
||||
struct sockaddr_in *daddr, fko_cli_options_t *options)
|
||||
{
|
||||
int res;
|
||||
|
||||
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if (sock < 0)
|
||||
{
|
||||
perror("[*] send_spa_packet_tcp: create socket: ");
|
||||
return(sock);
|
||||
}
|
||||
|
||||
res = connect(sock, (struct sockaddr *)daddr, sizeof(*daddr));
|
||||
if(res < 0)
|
||||
{
|
||||
perror("[*] send_spa_packet_tcp: connect: ");
|
||||
close(sock);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
res = send(sock, spa_data, sd_len, 0);
|
||||
|
||||
if(res < 0)
|
||||
{
|
||||
perror("[*] send_spa_packet_tcp: send error: ");
|
||||
}
|
||||
else if(res != sd_len)
|
||||
{
|
||||
fprintf(stderr, "[#] Warning: bytes sent (%i) not spa data length (%i).\n",
|
||||
res, sd_len);
|
||||
}
|
||||
|
||||
close(sock);
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
/* Send the SPA data via raw TCP packet.
|
||||
*/
|
||||
int
|
||||
send_spa_packet_tcp_raw(char *spa_data, int sd_len, struct sockaddr_in *saddr,
|
||||
struct sockaddr_in *daddr, fko_cli_options_t *options)
|
||||
{
|
||||
#ifdef WIN32
|
||||
fprintf(stderr, "[*] send_spa_packet_tcp_raw: raw packets are not yet supported.\n");
|
||||
return(-1);
|
||||
#else
|
||||
int sock, res;
|
||||
char pkt_data[2048] = {0}; /* Should be enough for our purposes */
|
||||
char *spa_data;
|
||||
int sd_len;
|
||||
|
||||
struct iphdr *iph = (struct iphdr *) pkt_data;
|
||||
struct tcphdr *tcph = (struct tcphdr *) (pkt_data + sizeof (struct iphdr));
|
||||
|
||||
int hdrlen = sizeof(struct iphdr) + sizeof(struct tcphdr);
|
||||
|
||||
char one = 1;
|
||||
/* Values for setsockopt.
|
||||
*/
|
||||
int one = 1;
|
||||
const int *so_val = &one;
|
||||
|
||||
int sock = socket (PF_INET, SOCK_RAW, IPPROTO_RAW);
|
||||
|
||||
if (sock < 0) {
|
||||
fprintf(stderr, "[*] Could not create UDP socket. Error = %i\n", errno);
|
||||
return(0);
|
||||
}
|
||||
|
||||
res = fko_get_spa_data(ctx, &spa_data);
|
||||
|
||||
if(res != FKO_SUCCESS)
|
||||
sock = socket (PF_INET, SOCK_RAW, IPPROTO_RAW);
|
||||
if (sock < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"send_spa_packet_tcp: Error #%i from fko_get_spa_data: %s\n",
|
||||
res, fko_errstr(res)
|
||||
);
|
||||
return(0);
|
||||
perror("[*] send_spa_packet_tcp_raw: create socket: ");
|
||||
return(sock);
|
||||
}
|
||||
|
||||
sd_len = strlen(spa_data);
|
||||
|
||||
/* Put the spa data in place.
|
||||
*/
|
||||
memcpy((pkt_data + hdrlen), spa_data, sd_len);
|
||||
@ -170,51 +208,60 @@ send_spa_packet_tcp(fko_ctx_t ctx, struct sockaddr_in *saddr,
|
||||
/* Make sure the kernel knows the header is included in the data so it
|
||||
* doesn't try to insert its own header into the packet.
|
||||
*/
|
||||
if ((res = setsockopt (sock, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one))) < 0)
|
||||
fprintf (stderr, "[*] send_spa_packet_tcp: setsockopt: error %i - Cannot set HDRINCL!\n", errno);
|
||||
if (setsockopt (sock, IPPROTO_IP, IP_HDRINCL, so_val, sizeof(one)) < 0)
|
||||
perror("[*] send_spa_packet_tcp_raw: setsockopt HDRINCL: ");
|
||||
|
||||
return(sendto (sock, pkt_data, iph->tot_len, 0,
|
||||
(struct sockaddr *)daddr, sizeof(*daddr)));
|
||||
res = sendto (sock, pkt_data, iph->tot_len, 0,
|
||||
(struct sockaddr *)daddr, sizeof(*daddr));
|
||||
|
||||
if(res < 0)
|
||||
{
|
||||
perror("[*] send_spa_packet_tcp_raw: sendto error: ");
|
||||
}
|
||||
else if(res != sd_len)
|
||||
{
|
||||
fprintf(stderr, "[#] Warning: bytes sent (%i) not spa data length (%i).\n",
|
||||
res, sd_len);
|
||||
}
|
||||
|
||||
close(sock);
|
||||
|
||||
return(res);
|
||||
|
||||
#endif /* !WIN32 */
|
||||
}
|
||||
|
||||
/* Send the SPA data via ICMP packet.
|
||||
*/
|
||||
int
|
||||
send_spa_packet_icmp(fko_ctx_t ctx, struct sockaddr_in *saddr,
|
||||
send_spa_packet_icmp(char *spa_data, int sd_len, struct sockaddr_in *saddr,
|
||||
struct sockaddr_in *daddr, fko_cli_options_t *options)
|
||||
{
|
||||
#ifdef WIN32
|
||||
fprintf(stderr, "[*] send_spa_packet_icmp: raw packets are not yet supported.\n");
|
||||
return(-1);
|
||||
#else
|
||||
int res;
|
||||
char pkt_data[2048] = {0};
|
||||
char *spa_data;
|
||||
int sd_len;
|
||||
|
||||
struct iphdr *iph = (struct iphdr *) pkt_data;
|
||||
struct icmphdr *icmph = (struct icmphdr *) (pkt_data + sizeof (struct iphdr));
|
||||
|
||||
int hdrlen = sizeof(struct iphdr) + sizeof(struct icmphdr);
|
||||
|
||||
char one = 1;
|
||||
/* Values for setsockopt.
|
||||
*/
|
||||
int one = 1;
|
||||
const int *so_val = &one;
|
||||
|
||||
int sock = socket (PF_INET, SOCK_RAW, IPPROTO_RAW);
|
||||
|
||||
if (sock < 0) {
|
||||
fprintf(stderr, "[*] Could not create UDP socket. Error = %i\n", errno);
|
||||
return(0);
|
||||
}
|
||||
|
||||
res = fko_get_spa_data(ctx, &spa_data);
|
||||
|
||||
if(res != FKO_SUCCESS)
|
||||
if (sock < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"send_spa_packet_tcp: Error #%i from fko_get_spa_data: %s\n",
|
||||
res, fko_errstr(res)
|
||||
);
|
||||
return(0);
|
||||
perror("[*] send_spa_packet_icmp: create socket: ");
|
||||
return(sock);
|
||||
}
|
||||
|
||||
sd_len = strlen(spa_data);
|
||||
|
||||
/* Put the spa data in place.
|
||||
*/
|
||||
memcpy((pkt_data + hdrlen), spa_data, sd_len);
|
||||
@ -250,11 +297,27 @@ send_spa_packet_icmp(fko_ctx_t ctx, struct sockaddr_in *saddr,
|
||||
/* Make sure the kernel knows the header is included in the data so it
|
||||
* doesn't try to insert its own header into the packet.
|
||||
*/
|
||||
if ((res = setsockopt (sock, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one))) < 0)
|
||||
fprintf (stderr, "[*] send_spa_packet_tcp: setsockopt: error %i - Cannot set HDRINCL!\n", errno);
|
||||
if (setsockopt (sock, IPPROTO_IP, IP_HDRINCL, so_val, sizeof(one)) < 0)
|
||||
perror("[*] send_spa_packet_icmp: setsockopt HDRINCL: ");
|
||||
|
||||
return(sendto (sock, pkt_data, iph->tot_len, 0,
|
||||
(struct sockaddr *)daddr, sizeof(*daddr)));
|
||||
res = sendto (sock, pkt_data, iph->tot_len, 0,
|
||||
(struct sockaddr *)daddr, sizeof(*daddr));
|
||||
|
||||
if(res < 0)
|
||||
{
|
||||
perror("[*] send_spa_packet_icmp: sendto error: ");
|
||||
}
|
||||
else if(res != sd_len)
|
||||
{
|
||||
fprintf(stderr, "[#] Warning: bytes sent (%i) not spa data length (%i).\n",
|
||||
res, sd_len);
|
||||
}
|
||||
|
||||
close(sock);
|
||||
|
||||
return(res);
|
||||
|
||||
#endif /* !WIN32 */
|
||||
}
|
||||
|
||||
/* Function used to send the SPA data.
|
||||
@ -262,12 +325,33 @@ send_spa_packet_icmp(fko_ctx_t ctx, struct sockaddr_in *saddr,
|
||||
int
|
||||
send_spa_packet(fko_ctx_t ctx, fko_cli_options_t *options)
|
||||
{
|
||||
int rv = 0;
|
||||
struct sockaddr_in saddr, daddr;
|
||||
int res, sd_len;
|
||||
char *spa_data;
|
||||
|
||||
struct sockaddr_in saddr, daddr;
|
||||
|
||||
#ifdef WIN32
|
||||
WSADATA wsa_data;
|
||||
#endif
|
||||
|
||||
/* Get our spa data here.
|
||||
*/
|
||||
res = fko_get_spa_data(ctx, &spa_data);
|
||||
|
||||
if(res != FKO_SUCCESS)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"send_spa_packet: Error #%i from fko_get_spa_data: %s\n",
|
||||
res, fko_errstr(res)
|
||||
);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
sd_len = strlen(spa_data);
|
||||
|
||||
#ifdef WIN32
|
||||
/* Winsock needs to be initialized...
|
||||
*/
|
||||
rv = WSAStartup( MAKEWORD(1,1), &wsa_data );
|
||||
if( rv != 0 )
|
||||
{
|
||||
@ -276,15 +360,13 @@ send_spa_packet(fko_ctx_t ctx, fko_cli_options_t *options)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* initialize to zeros
|
||||
*/
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
memset(&daddr, 0, sizeof(daddr));
|
||||
|
||||
saddr.sin_family = AF_INET;
|
||||
daddr.sin_family = AF_INET;
|
||||
|
||||
/* set source address and port
|
||||
/* Set source address and port
|
||||
*/
|
||||
if (options->src_port)
|
||||
saddr.sin_port = htons(options->src_port);
|
||||
@ -296,18 +378,39 @@ send_spa_packet(fko_ctx_t ctx, fko_cli_options_t *options)
|
||||
else
|
||||
saddr.sin_addr.s_addr = INADDR_ANY; /* default */
|
||||
|
||||
/* set destination address and port */
|
||||
/* Set destination address and port
|
||||
*/
|
||||
daddr.sin_port = htons(options->port);
|
||||
daddr.sin_addr.s_addr = inet_addr(options->spa_server_ip_str);
|
||||
|
||||
if (options->proto == IPPROTO_UDP)
|
||||
rv = send_spa_packet_udp(ctx, &saddr, &daddr, options);
|
||||
else if (options->proto == IPPROTO_TCP)
|
||||
rv = send_spa_packet_tcp(ctx, &saddr, &daddr, options);
|
||||
else if (options->proto == IPPROTO_ICMP)
|
||||
rv = send_spa_packet_icmp(ctx, &saddr, &daddr, options);
|
||||
errno = 0;
|
||||
|
||||
return rv;
|
||||
switch (options->proto)
|
||||
{
|
||||
case FKO_PROTO_UDP:
|
||||
res = send_spa_packet_udp(spa_data, sd_len, &saddr, &daddr, options);
|
||||
break;
|
||||
|
||||
case FKO_PROTO_TCP:
|
||||
res = send_spa_packet_tcp(spa_data, sd_len, &saddr, &daddr, options);
|
||||
break;
|
||||
|
||||
case FKO_PROTO_TCP_RAW:
|
||||
res = send_spa_packet_tcp_raw(spa_data, sd_len, &saddr, &daddr, options);
|
||||
break;
|
||||
|
||||
case FKO_PROTO_ICMP:
|
||||
res = send_spa_packet_icmp(spa_data, sd_len, &saddr, &daddr, options);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* --DSS XXX: What to we really want to do here? */
|
||||
fprintf(stderr, "[*] %i is not a valid or supported protocol.\n",
|
||||
options->proto);
|
||||
res = -1;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Function to write SPA packet data to the filesystem
|
||||
@ -318,17 +421,6 @@ int write_spa_packet_data(fko_ctx_t ctx, fko_cli_options_t *options)
|
||||
char *spa_data;
|
||||
int res;
|
||||
|
||||
if (options->save_packet_file_append) {
|
||||
if((fp = fopen(options->save_packet_file, "a")) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
unlink(options->save_packet_file);
|
||||
if((fp = fopen(options->save_packet_file, "w")) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
res = fko_get_spa_data(ctx, &spa_data);
|
||||
|
||||
if(res != FKO_SUCCESS)
|
||||
@ -337,7 +429,24 @@ int write_spa_packet_data(fko_ctx_t ctx, fko_cli_options_t *options)
|
||||
"write_spa_packet_data: Error #%i from fko_get_spa_data: %s\n",
|
||||
res, fko_errstr(res)
|
||||
);
|
||||
exit(1);
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
if (options->save_packet_file_append)
|
||||
{
|
||||
fp = fopen(options->save_packet_file, "a");
|
||||
}
|
||||
else
|
||||
{
|
||||
unlink(options->save_packet_file);
|
||||
fp = fopen(options->save_packet_file, "w");
|
||||
}
|
||||
|
||||
if(fp == NULL)
|
||||
{
|
||||
perror("write_spa_packet_data: ");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
fprintf(fp, "%s\n",
|
||||
@ -345,7 +454,7 @@ int write_spa_packet_data(fko_ctx_t ctx, fko_cli_options_t *options)
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 1;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/***EOF***/
|
||||
|
||||
105
src/spa_comm.h
105
src/spa_comm.h
@ -39,12 +39,107 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
/* We will roll our own packet header structs. */
|
||||
|
||||
/* The IP header
|
||||
*/
|
||||
struct iphdr
|
||||
{
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
unsigned int ihl:4;
|
||||
unsigned int version:4;
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned int version:4;
|
||||
unsigned int ihl:4;
|
||||
#else
|
||||
#error "Please fix <bits/endian.h>"
|
||||
#endif
|
||||
unsigned char tos;
|
||||
unsigned short tot_len;
|
||||
unsigned short id;
|
||||
unsigned short frag_off;
|
||||
unsigned char ttl;
|
||||
unsigned char protocol;
|
||||
unsigned short check;
|
||||
unsigned int saddr;
|
||||
unsigned int daddr;
|
||||
};
|
||||
|
||||
/* Prototypes
|
||||
/* The TCP header
|
||||
*/
|
||||
struct tcphdr
|
||||
{
|
||||
unsigned short source;
|
||||
unsigned short dest;
|
||||
unsigned int seq;
|
||||
unsigned int ack_seq;
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
unsigned short res1:4;
|
||||
unsigned short doff:4;
|
||||
unsigned short fin:1;
|
||||
unsigned short syn:1;
|
||||
unsigned short rst:1;
|
||||
unsigned short psh:1;
|
||||
unsigned short ack:1;
|
||||
unsigned short urg:1;
|
||||
unsigned short res2:2;
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned short doff:4;
|
||||
unsigned short res1:4;
|
||||
unsigned short res2:2;
|
||||
unsigned short urg:1;
|
||||
unsigned short ack:1;
|
||||
unsigned short psh:1;
|
||||
unsigned short rst:1;
|
||||
unsigned short syn:1;
|
||||
unsigned short fin:1;
|
||||
#else
|
||||
#error "Adjust your <bits/endian.h> defines"
|
||||
#endif
|
||||
unsigned short window;
|
||||
unsigned short check;
|
||||
unsigned short urg_ptr;
|
||||
};
|
||||
|
||||
/* The ICMP header
|
||||
*/
|
||||
struct icmphdr
|
||||
{
|
||||
unsigned char type; /* message type */
|
||||
unsigned char code; /* type sub-code */
|
||||
unsigned short checksum;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned short id;
|
||||
unsigned short sequence;
|
||||
} echo; /* echo datagram */
|
||||
unsigned int gateway; /* gateway address */
|
||||
struct
|
||||
{
|
||||
unsigned short __unused;
|
||||
unsigned short mtu;
|
||||
} frag; /* path mtu discovery */
|
||||
} un;
|
||||
};
|
||||
|
||||
#define ICMP_ECHOREPLY 0 /* Echo Reply */
|
||||
#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */
|
||||
#define ICMP_SOURCE_QUENCH 4 /* Source Quench */
|
||||
#define ICMP_REDIRECT 5 /* Redirect (change route) */
|
||||
#define ICMP_ECHO 8 /* Echo Request */
|
||||
#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */
|
||||
#define ICMP_PARAMETERPROB 12 /* Parameter Problem */
|
||||
#define ICMP_TIMESTAMP 13 /* Timestamp Request */
|
||||
#define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */
|
||||
#define ICMP_INFO_REQUEST 15 /* Information Request */
|
||||
#define ICMP_INFO_REPLY 16 /* Information Reply */
|
||||
#define ICMP_ADDRESS 17 /* Address Mask Request */
|
||||
#define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */
|
||||
|
||||
|
||||
/* Function Prototypes
|
||||
*/
|
||||
int send_spa_packet(fko_ctx_t ctx, fko_cli_options_t *options);
|
||||
int write_spa_packet_data(fko_ctx_t ctx, fko_cli_options_t *options);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user