Implemented sending spa data via TCP or ICMP via SOCK_RAW (unix only so far).

git-svn-id: file:///home/mbr/svn/fwknop/trunk@93 510a4753-2344-4c79-9c09-4d669213fbeb
This commit is contained in:
Damien Stuart
2009-05-26 15:03:00 +00:00
parent 9c9d46cc09
commit c509b53dd4
3 changed files with 206 additions and 15 deletions
+6 -1
View File
@@ -184,8 +184,13 @@ main(int argc, char **argv)
*/
if (!options.test)
{
if(send_spa_packet(ctx, &options) < 1)
//if(send_spa_packet(ctx, &options) < 1)
res = send_spa_packet(ctx, &options);
if(res < 1)
{
perror("send_spa_packet");
return(1);
}
}
else
{
+194 -14
View File
@@ -26,17 +26,42 @@
*/
#include "spa_comm.h"
/* Function to generate a header checksum.
*/
unsigned short
chksum(unsigned short *buf, int nbytes)
{
unsigned int sum;
unsigned short oddbyte;
sum = 0;
while (nbytes > 1) {
sum += *buf++;
nbytes -= 2;
}
if (nbytes == 1) {
oddbyte = 0;
*((unsigned short *) &oddbyte) = *(unsigned short *) buf;
sum += oddbyte;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return (unsigned short) ~sum;
}
/* Send the SPA data via UDP packet.
*/
int
send_spa_packet_udp(fko_ctx_t ctx, struct sockaddr_in *saddr,
struct sockaddr_in *daddr, fko_cli_options_t *options)
{
int sock = 0;
int res;
char *spa_data;
sock = socket(AF_INET, SOCK_DGRAM, 0);
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
fprintf(stderr, "[*] Could not create UDP socket.\n");
@@ -64,17 +89,172 @@ int
send_spa_packet_tcp(fko_ctx_t ctx, struct sockaddr_in *saddr,
struct sockaddr_in *daddr, fko_cli_options_t *options)
{
int rv = 0;
return rv;
int 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;
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)
{
fprintf(stderr,
"send_spa_packet_tcp: Error #%i from fko_get_spa_data: %s\n",
res, fko_errstr(res)
);
return(0);
}
sd_len = strlen(spa_data);
/* Put the spa data in place.
*/
memcpy((pkt_data + hdrlen), spa_data, sd_len);
/* Construct our own header by filling in the ip/tcp header values,
* starting with the IP header values.
*/
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
/* Total size is header plus payload */
iph->tot_len = hdrlen + sd_len;
/* The value here does not matter */
iph->id = random() & 0xffff;
iph->frag_off = 0;
iph->ttl = 255;
iph->protocol = IPPROTO_TCP;
iph->check = 0;
iph->saddr = saddr->sin_addr.s_addr;
iph->daddr = daddr->sin_addr.s_addr;
/* Now the TCP header values.
*/
tcph->source = saddr->sin_port;
tcph->dest = daddr->sin_port;
tcph->seq = htonl(1);
tcph->ack_seq = 0;
tcph->doff = 5;
tcph->res1 = 0;
/* TCP flags */
tcph->fin = 0;
tcph->syn = 1;
tcph->rst = 0;
tcph->psh = 0;
tcph->ack = 0;
tcph->urg = 0;
tcph->res2 = 0;
tcph->window = htons(32767);
tcph->check = 0;
tcph->urg_ptr = 0;
/* No we can compute our checksum.
*/
iph->check = chksum((unsigned short *)pkt_data, iph->tot_len);
/* 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);
return(sendto (sock, pkt_data, iph->tot_len, 0,
(struct sockaddr *)daddr, sizeof(*daddr)));
}
/* Send the SPA data via ICMP packet.
*/
int
send_spa_packet_icmp(fko_ctx_t ctx, fko_cli_options_t *options)
send_spa_packet_icmp(fko_ctx_t ctx, struct sockaddr_in *saddr,
struct sockaddr_in *daddr, fko_cli_options_t *options)
{
int rv = 0;
return rv;
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;
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)
{
fprintf(stderr,
"send_spa_packet_tcp: Error #%i from fko_get_spa_data: %s\n",
res, fko_errstr(res)
);
return(0);
}
sd_len = strlen(spa_data);
/* Put the spa data in place.
*/
memcpy((pkt_data + hdrlen), spa_data, sd_len);
/* Construct our own header by filling in the ip/icmp header values,
* starting with the IP header values.
*/
iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
/* Total size is header plus payload */
iph->tot_len = hdrlen + sd_len;
/* The value here does not matter */
iph->id = random() & 0xffff;
iph->frag_off = 0;
iph->ttl = 255;
iph->protocol = IPPROTO_ICMP;
iph->check = 0;
iph->saddr = saddr->sin_addr.s_addr;
iph->daddr = daddr->sin_addr.s_addr;
/* Now the ICMP header values.
*/
icmph->type = ICMP_ECHOREPLY; /* Make it an echo reply */
icmph->code = 0;
icmph->checksum = 0;
/* No we can compute our checksum.
*/
iph->check = chksum((unsigned short *)pkt_data, iph->tot_len);
icmph->checksum = chksum((unsigned short *)icmph, sizeof(struct icmphdr) + sd_len);
/* 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);
return(sendto (sock, pkt_data, iph->tot_len, 0,
(struct sockaddr *)daddr, sizeof(*daddr)));
}
/* Function used to send the SPA data.
@@ -86,14 +266,14 @@ send_spa_packet(fko_ctx_t ctx, fko_cli_options_t *options)
struct sockaddr_in saddr, daddr;
#ifdef WIN32
WSADATA wsa_data;
WSADATA wsa_data;
rv = WSAStartup( MAKEWORD(1,1), &wsa_data );
rv = WSAStartup( MAKEWORD(1,1), &wsa_data );
if( rv != 0 )
{
fprintf(stderr, "[*] Winsock initialization error %d\n", rv );
return(0);
}
{
fprintf(stderr, "[*] Winsock initialization error %d\n", rv );
return(0);
}
#endif
/* initialize to zeros
@@ -125,7 +305,7 @@ send_spa_packet(fko_ctx_t ctx, fko_cli_options_t *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, options);
rv = send_spa_packet_icmp(ctx, &saddr, &daddr, options);
return rv;
}
+6
View File
@@ -27,6 +27,7 @@
#define SPA_COMM_H
#include "fwknop_common.h"
#include <errno.h>
#ifdef WIN32
#include <winsock2.h>
@@ -38,6 +39,11 @@
#endif
#endif
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
/* Prototypes
*/
int send_spa_packet(fko_ctx_t ctx, fko_cli_options_t *options);