I am trying to build a program that can send TCP packets, but when I compiled my code to test the send function it just doesn't run the way it should. When given arguments it skips to the getchar and exits the program as if the function wasn't called at all. Now I am not particularly experienced and this is probably a stupid question, but I haven't been able to find a solution elsewhere. My guess is I'm calling it wrong somehow and that maybe the send_tcp function can't be inside of the forgepacket function.
The following is my code (not finished at all but should be good enough for a little test run) and the function giving me problems is forgepacket.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#define VERSION "1.0"
#define PCKT_LEN 8192
/* Prototypes */
void forgepacket (unsigned int, unsigned int, unsigned short, unsigned short);
void usage();
/* Checksum */
unsigned short checksum (unsigned short *pac, int len)
{
unsigned long sum;
for (sum = 0; len > 0; len--)
sum += *pac++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return(~sum);
}
in_addr_t sip;
in_addr_t dip;
int sport;
int dport;
int main(int argc,char **argv)
{
int c;
/* Are we in root? */
if(geteuid() !=0)
{
printf("Root access is required to run this program.\n\n");
exit(0);
}
while (1)
{
static struct option long_options[] =
{
/* Options */
{"send", no_argument, 0, 's'}, /* args s, r and f have no function yet */
{"recieve", no_argument, 0, 'r'},
{"file", required_argument, 0, 'f'},
{"destip", required_argument, 0, 'i'},
{"destport", required_argument, 0, 'p'},
{"sourceip", required_argument, 0, 'o'},
{"sourceport", required_argument, 0, 't'},
{0, 0, 0, 0}
};
int option_index = 0;
c = getopt_long (argc, argv, "srf:d:i:p:o:t:",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 's':
puts ("option -s\n");
break;
case 'r':
puts ("option -r\n");
break;
case 'f':
printf ("option -f with value `%s'\n", optarg);
break;
case 'i':
dip = inet_addr(optarg);
break;
case 'p':
dport = htons(atoi(optarg));
/* Add handling of bad/non number input here */
break;
case 'o':
sip = inet_addr(optarg);
break;
case 't':
sport = htons(atoi(optarg));
break;
case '?':
/* Error message printed */
break;
default:
abort ();
}
}
/* Print any remaining command line arguments (not options). */
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
/* check if all mandatory options are set and for unknown arguments */
/* This REALLY needs changing... */
if (dip, sip, dport, sport == 0)
{
usage();
return (-1);
}
forgepacket(dip, sip, dport, sport);
getchar ();
exit (0);
}
void forgepacket(unsigned int sourceip, unsigned int destip, unsigned short sourceport,
unsigned short destport)
{
/* IP header structure */
struct ipheader {
unsigned char iph_ihl:5,
iph_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_id;
unsigned char iph_flags;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};
/* TCP header structure */
struct tcpheader {
unsigned short int tcph_sourceport;
unsigned short int tcph_destport;
unsigned int tcph_seqnum;
unsigned int tcph_acknum;
unsigned char tcph_reserved:4, tcph_offset:4;
unsigned int
tcp_res1:4,
tcph_hlen:4,
tcph_fin:1,
tcph_syn:1,
tcph_rst:1,
tcph_psh:1,
tcph_ack:1,
tcph_urg:1,
tcph_res2:2;
unsigned short int tcph_win;
unsigned short int tcph_chksum;
unsigned short int tcph_urgptr;
};
int send_tcp()
{
int sock, one = 1;
char buffer[PCKT_LEN];
struct sockaddr_in sin, din;
const int *val = &one;
sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
if (sock < 0)
{
printf("\nError: socket()\n\n");
exit (-1);
}
else
printf ("\nsocket() - Using SOCK_RAW and TCP protocol is OK.\n\n");
/* Size of the headers */
struct ipheader *ip = (struct ipheader *) buffer;
struct tcpheader *tcp = (struct tcpheader *) (buffer + sizeof (struct ipheader));
memset (buffer, 0, PCKT_LEN);
/* IP attributes */
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
ip->iph_id = htons(54321);
ip->iph_offset = 0;
ip->iph_ttl = 64;
ip->iph_protocol = 6;
ip->iph_chksum = 0;
ip->iph_sourceip = sip;
ip->iph_destip = dip;
/* TCP attributes */
tcp->tcph_sourceport = sport;
tcp->tcph_destport = dport;
tcp->tcph_seqnum = htonl(1);
tcp->tcph_acknum = 0;
tcp->tcph_offset = 5;
tcp->tcph_syn = 1;
tcp->tcph_ack = 0;
tcp->tcph_win = htons(32767);
tcp->tcph_chksum = 0;
tcp->tcph_urgptr = 0;
ip->iph_chksum = checksum ((unsigned short *) buffer, (sizeof (struct ipheader )+ sizeof (struct tcpheader)));
/* Address family */
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
/* Source port */
sin.sin_port = sport;
din.sin_port = dport;
/* Source IP */
sin.sin_addr.s_addr = sip;
din.sin_addr.s_addr = dip;
/* Tell the Kernel we're building our own packet */
if ((setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof (one))) < 0)
{
printf("\nError: Can't set socketoptions\n\n");
return (-1);
}
/* Send */
if (sendto(sock, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
printf("\nError: Can't send packet\n\n");
return (-1);
}
else
printf("Packet sent to %d", dip);
close(sock);
}
}
void usage()
{
/* This is the user manual */
printf("\nTCP project %s\n\n", VERSION);
printf("Usage: -s -f <file> -i <destip> -p <destport> -o <sourceip> -t <sourceport>\n\n");
printf("-s, --send, Puts program in send mode\n");
printf("-r, --recieve, Puts program in recieve mode\n");
printf("-f, --file, Specify file containing steganographic message\n");
printf("-i, --destip, Destination IP address\n");
printf("-p, --destport, Destination port\n");
printf("-o, --sourceip Source IP address\n");
printf("-t, --sourceport Source port\n");
}
It appears the function definition of send_tcp() is within the function definition of forgepacket() (I didn't know this was even possible??), but there is no call to it. Replicate the arrangement you have for forgepacket() for send_tcp():
/* Prototype. */
int send_tcp(); /* add whatever parameters are required. */
and move definition of send_tcp() outside of forgepacket() and add a call to send_tcp() within forgepacket().
C doesn't allow nested functions by default. Furthermore, even if it did, I am not seeing a call to send_tcp in the code (it may be there, but a quick scan doesn't show it).
What happens if you break the send_tcp function out of forge_packet and make sure to pass the required data in as parameters?
Related
Recently I have been struggling with servers for the first time:
The case is: I have a software (Motive from Optitrack) that provides a streaming of data via multicasting.
I have tried to modify a previous program, it can be build but I have some issues to solve:
1º- I want a .bat file to automatically open the server with the argc parameters, I have made one, but it doesn't work. The code is at the end.
2º When executing the .exe file, the console bips for a moment and closes. I suppose that it is because it returns -1, but maybe there is some error in the code.
I'm on Windows 10, using Code::Blocks and Gcc compiler.
The server code is:
#include <sys/types.h> /* for type definitions */
#include <winsock2.h> /* for win socket API calls */
#include <ws2tcpip.h> /* for win socket structs */
#include <stdio.h> /* for printf() and fprintf() */
#include <stdlib.h> /* for atoi() */
#include <string.h> /* for strlen() */
#define MAX_LEN 1024 /* maximum receive string size */
#define MIN_PORT 1051 /* minimum port allowed */
#define MAX_PORT 1051 /* maximum port allowed */
#define NUM_RIG_OBJ 2
int main(int argc, char *argv[]) {
int sock; /* socket descriptor */
int flag_on = 1; /* socket option flag */
struct sockaddr_in mc_addr; /* socket address structure */
char recv_str[MAX_LEN+1]; /* buffer to receive string */
int recv_len, ID ; /* length of string received */
struct ip_mreq mc_req; /* multicast request structure */
char* mc_addr_str ; /* multicast IP address */
unsigned short mc_port; /* multicast port */
struct sockaddr_in from_addr; /* packet source */
unsigned int from_len; /* source addr length */
WSADATA wsaData; /* Windows socket DLL structure */
float xa,ya,za,qx,qy,qz,qw;
/* validate number of arguments */
if (argc != 3) {
fprintf(stderr,
"Usage: %s <Multicast IP> <Multicast Port>\n",
argv[0]);
exit(1);
}
mc_addr_str = argv[1]; /* arg 1: multicast ip address */
mc_port = atoi(argv[2]); /* arg 2: multicast port number */
/* validate the port range */
if ((mc_port < MIN_PORT) || (mc_port > MAX_PORT)) {
fprintf(stderr, "Invalid port number argument %d.\n",
mc_port);
fprintf(stderr, "Valid range is between %d and %d.\n",
MIN_PORT, MAX_PORT);
exit(1);
}
/* Load Winsock 2.0 DLL */
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
fprintf(stderr, "WSAStartup() failed");
exit(1);
}
/* create socket to join multicast group on */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("socket() failed");
exit(1);
}
/* set reuse port to on to allow multiple binds per host */
if ((setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&flag_on,
sizeof(flag_on))) < 0) {
perror("setsockopt() failed");
exit(1);
}
/* construct a multicast address structure */
memset(&mc_addr, 0, sizeof(mc_addr));
mc_addr.sin_family = AF_INET;
mc_addr.sin_addr.s_addr = htonl(INADDR_ANY);
mc_addr.sin_port = htons(mc_port);
/* bind to multicast address to socket */
if ((bind(sock, (struct sockaddr *) &mc_addr,
sizeof(mc_addr))) < 0) {
perror("bind() failed");
exit(1);
}
/* construct an IGMP join request structure */
mc_req.imr_multiaddr.s_addr = inet_addr(mc_addr_str);
mc_req.imr_interface.s_addr = htonl(INADDR_ANY);
/* send an ADD MEMBERSHIP message via setsockopt */
if ((setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(char*) &mc_req, sizeof(mc_req))) < 0) {
perror("setsockopt() failed");
exit(1);
}
int md=recv_str[0];
char *ptr = recv_str;
float x[NUM_RIG_OBJ]= {0};
float y[NUM_RIG_OBJ]= {0};
float z[NUM_RIG_OBJ]= {0};
float q1[NUM_RIG_OBJ]= {0};
float q2[NUM_RIG_OBJ]= {0};
float q3[NUM_RIG_OBJ]= {0};
float q4[NUM_RIG_OBJ]= {0};
for (;;) { /* loop forever */
/* clear the receive buffers & structs */
memset(recv_str, 0, sizeof(recv_str));
from_len = sizeof(from_addr);
memset(&from_addr, 0, from_len);
/* block waiting to receive a packet */
if ((recv_len = recvfrom(sock, recv_str, MAX_LEN, 0,
(struct sockaddr*)&from_addr, &from_len)) < 0) {
perror("recvfrom() failed");
exit(1);
}
/* output received string */
printf("Received %d bytes from %s: ", recv_len,
inet_ntoa(from_addr.sin_addr));
printf("%s", recv_str);
// rigid body pos/ori
if (md==7){
for (int i=0;i<NUM_RIG_OBJ;i++){
memcpy(&ID, ptr, 4); ptr += 4;
memcpy(&xa, ptr, 4); ptr += 4;
memcpy(&ya, ptr, 4); ptr += 4;
memcpy(&za, ptr, 4); ptr += 4;
memcpy(&qx, ptr, 4); ptr += 4;
memcpy(&qy, ptr, 4); ptr += 4;
memcpy(&qz, ptr, 4); ptr += 4;
memcpy(&qw, ptr, 4); ptr += 4;
printf("ID : %d\n", ID);
printf("pos: [%3.4f,%3.4f,%3.4f]\n", xa,ya,za);
printf("ori: [%3.4f,%3.4f,%3.4f,%3.4f]\n", qx,qy,qz,qw);
x[i]=xa;
y[i]=ya;
z[i]=za;
q1[i]=qx;
q2[i]=qy;
q3[i]=qz;
q4[i]=qw;
ptr = recv_str;
memcpy(ptr, &i, 4); ptr += 4;
memcpy(ptr, &x[i], 4); ptr += 4;
memcpy(ptr, &y[i], 4); ptr += 4;
memcpy(ptr, &z[i], 4); ptr += 4;
memcpy(ptr, &q1[i], 4); ptr += 4;
memcpy(ptr, &q2[i], 4); ptr += 4;
memcpy(ptr, &q3[i], 4); ptr += 4;
memcpy(ptr, &q4[i], 4); ptr += 4;
}
}
/* send a DROP MEMBERSHIP message via setsockopt */
if ((setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP,
(void*) &mc_req, sizeof(mc_req))) < 0) {
perror("setsockopt() failed");
exit(1);
}
closesocket(sock);
WSACleanup(); /* Cleanup Winsock */
}
return 0;
}
and the .bat file is
#echo off
echo Opening server...
cd C:\Users\Optitrack\Desktop\Conrado\mcreceive
start mcreceive.exe 259.44.99.107 1051
Any piece of advice would be much appreciated.
thank you
Can anybody give me a hand trying to implement the following server and client?:
The server:
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
int main(void) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv_addr = { 0 };
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(1234);
bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
listen(sock, 128);
struct sockaddr_in cli_addr = { 0 };
socklen_t cli_addrlen = sizeof(cli_addr);
int acc_sock = accept(sock, (struct sockaddr *)&cli_addr, &cli_addrlen);
printf("[+] Connected \n");
char buf[1024];
ssize_t nread;
memset(buf, 0, sizeof(buf));
int a;
while (1) {
nread = read(0, buf, 1024);
write(acc_sock, buf, nread);
memset(buf, 0, sizeof(buf));
while ((read(acc_sock, buf, 1024)) != 0) {
printf("%s", buf);
memset(buf, 0, sizeof(buf));
}
}
}
All the servers does is scanning a command from stdin and send it to the client via sockets. Then scans the client response and prints it out to stdout.
The client:
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
int main(int argc, const char *argv[]) {
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in serv = { 0 };
char buf[1024];
char command[1024];
memset(buf, 0, sizeof(buf));
memset(command, 0, sizeof(command));
int nread;
FILE *in;
extern FILE *popen();
serv.sin_family = AF_INET;
serv.sin_port = htons(atoi(argv[1]));
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
int a;
connect(sock, (struct sockaddr*)&serv, sizeof(serv));
while (1) {
nread = read(sock, buf, 1024);
in = popen(buf, "r");
while ((fgets(command, sizeof(command), in)) != NULL) {;
write(sock, command, sizeof(command));
}
memset(buf, 0, sizeof(buf));
}
return 0;
}
Essentially the client receives the command scanned by the server, executes it using popen(), and sends the contents of the command line by line until NULL.
The problem is that the code suddenly stops working just after the first command. the transmission of the command and the command's output is satisfactory, however after printing the output of the first command the program just stops working. I think is a problem with fgets(), however I could be wrong. Is there any solutions for this problem?
Caveat: This may [or may not] fit your needs because I reversed the sense of the client and server loops in the corrected code below. As I had mentioned in my comment above:
The normal orientation for an app like this is that a client connects to a server and the client feeds the commands [read from stdin] to the server [which does popen] and feeds back the results. That's how ssh works. Your orientation is reversed. What you've got is you fire sshd and wait for ssh to connect and then sshd sends commands to ssh. In other words, the loops in the respective sides should be switched.
Reversing this was the only way things made sense to me. If the reversal doesn't work [well] for your desired use case, the code below may still give you some ideas.
I solved the hang problem by introducing the concept of a flag character to denote end-of-output. I borrowed this concept from the PPP [point-to-point] protocol over RS-232.
The flag character is just a given value (e.g. 0x10) that is not likely to be part of normal data. Since your data is most likely ascii or utf-8, any [unused] chars in the range 0x00-0x1F may be used (i.e. don't use tab, cr, newline, etc).
If you need to transmit the flag character (i.e. your data has to be the full binary range 0x00-0xFF), I've included some packet encode/decode routines that implement the escape codes used in PPP above. I've coded them, but did not actually hook them in. In this case, the flag [and escape] chars can be any binary value [usually 0xFF and 0xFE respectively].
For simplicity, I combined both sides into a single .c file. Invoke the server with -s [first].
Anyway, here's the tested code [please pardon the gratuitous style cleanup]:
// inetpair/inetpair -- server/client communication
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef unsigned char byte;
#define BUFMAX 1024
int port = 1234;
int opt_svr;
int opt_debug;
#define FLAG 0x10
#define ESC 0x11
#define ESC_FLAG 0x01
#define ESC_ESC 0x02
#define dbgprt(_fmt...) \
do { \
if (opt_debug) \
printf(_fmt); \
} while (0)
// client
int
client(void)
{
int sock;
struct sockaddr_in serv = { 0 };
char *cp;
char buf[BUFMAX + 1];
int nread;
int flag;
int exitflg;
sock = socket(AF_INET, SOCK_STREAM, 0);
serv.sin_family = AF_INET;
serv.sin_port = htons(port);
serv.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(sock, (struct sockaddr *) &serv, sizeof(serv));
while (1) {
cp = fgets(buf,BUFMAX,stdin);
if (cp == NULL)
break;
exitflg = (strcmp(buf,"exit\n") == 0);
// send the command
nread = strlen(buf);
write(sock, buf, nread);
if (exitflg)
break;
while (1) {
dbgprt("client: PREREAD\n");
nread = read(sock, buf, 1024);
dbgprt("client: POSTREAD nread=%d\n",nread);
if (nread <= 0)
break;
cp = memchr(buf,FLAG,nread);
flag = (cp != NULL);
if (flag)
nread = cp - buf;
write(1,buf,nread);
if (flag)
break;
}
}
close(sock);
return 0;
}
// server
int
server(void)
{
struct sockaddr_in serv_addr = { 0 };
int sock;
int acc_sock;
char buf[BUFMAX + 1];
char command[BUFMAX + 1];
ssize_t nread;
FILE *pin;
FILE *xfin;
char *cp;
struct sockaddr_in cli_addr = { 0 };
opt_debug = ! opt_debug;
dbgprt("[+] Starting\n");
sock = socket(AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(port);
bind(sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
listen(sock, 128);
while (1) {
socklen_t cli_addrlen = sizeof(cli_addr);
dbgprt("[+] Waiting for connection\n");
acc_sock = accept(sock,(struct sockaddr *)&cli_addr,&cli_addrlen);
dbgprt("[+] Connected\n");
xfin = fdopen(acc_sock,"r");
while (1) {
dbgprt("[+] Waiting for command\n");
cp = fgets(buf,BUFMAX,xfin);
if (cp == NULL)
break;
cp = strchr(buf,'\n');
if (cp != NULL)
*cp = 0;
dbgprt("[+] Command '%s'\n",buf);
if (strcmp(buf,"exit") == 0)
break;
pin = popen(buf, "r");
while (1) {
cp = fgets(command, BUFMAX, pin);
if (cp == NULL)
break;
nread = strlen(command);
write(acc_sock, command, nread);
}
pclose(pin);
command[0] = FLAG;
write(acc_sock,command,1);
}
fclose(xfin);
close(acc_sock);
dbgprt("[+] Disconnect\n");
}
}
// packet_encode -- encode packet
// RETURNS: (outlen << 1)
int
packet_encode(void *dst,const void *src,int srclen)
{
const byte *sp = src;
byte *dp = dst;
const byte *ep;
byte chr;
int dstlen;
// encode packet in manner similar to PPP (point-to-point) protocol does
// over RS-232 line
ep = sp + srclen;
for (; sp < ep; ++sp) {
chr = *sp;
switch (chr) {
case FLAG:
*dp++ = ESC;
*dp++ = ESC_FLAG;
break;
case ESC:
*dp++ = ESC;
*dp++ = ESC_ESC;
break;
default:
*dp++ = chr;
break;
}
}
dstlen = dp - (byte *) dst;
dstlen <<= 1;
return dstlen;
}
// packet_decode -- decode packet
// RETURNS: (outlen << 1) | flag
int
packet_decode(void *dst,const void *src,int srclen)
{
const byte *sp = src;
byte *dp = dst;
const byte *ep;
byte chr;
int flag;
int dstlen;
// decode packet in manner similar to PPP (point-to-point) protocol does
// over RS-232 line
ep = sp + srclen;
flag = 0;
while (sp < ep) {
chr = *sp++;
flag = (chr == FLAG);
if (flag)
break;
switch (chr) {
case ESC:
chr = *sp++;
switch (chr) {
case ESC_FLAG:
*dp++ = FLAG;
break;
case ESC_ESC:
*dp++ = ESC;
break;
}
break;
default:
*dp++ = chr;
break;
}
}
dstlen = dp - (byte *) dst;
dstlen <<= 1;
if (flag)
dstlen |= 0x01;
return dstlen;
}
int
main(int argc, char **argv)
{
char *cp;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
case 'd':
opt_debug = 1;
break;
case 'P':
port = atoi(cp + 2);
break;
case 's':
opt_svr = 1;
break;
}
}
if (opt_svr)
server();
else
client();
return 0;
}
The client never closes sock. Therefore the server's loop
while ((read(acc_sock, buf, 1024)) != 0) {
printf("%s", buf);
memset(buf, 0, sizeof(buf));
}
never terminates. You need some mechanism to inform server that all the command's output has been sent. Maybe something similar to HTTP chunked transfer encoding.
I have, as requested, included the code in its entirety so that you can test it. Keep in mind that this is nowhere near completion, but should be able to send and recieve packets through a stable tcp connection.
When I run it I get:
./bunny -i 84.49.76.98 -p 80 -o 79.161.200.48 -t 80
Raw packet reader created
Waiting 1 second for packet reader thread to settle down...
socket() - Using SOCK_RAW and TCP protocol is OK.
Socketoptions OK.
and then it just hangs. I've also used strace and that gave me (only including the last bit where it stopped):
setsockopt(4, SOL_IP, IP_HDRINCL, [1], 4) = 0
write(1, "Socketoptions OK.\n", 18Socketoptions OK.
) = 18
sendto(4, "", 0, 0, {sa_family=AF_INET, sin_port=htons(63239), sin_addr=inet_addr("84.49.76.98")}, 16) = 0
close(4) = 0
futex(0x7f4c07bf89d0, FUTEX_WAIT, 3278, NULLsendto(4, "", 0, 0, {sa_family=AF_INET, sin_port=htons(63239), sin_addr=inet_addr("84.49.76.98")}, 16) = 0
close(4) = 0
and the system monitor says the program is sleeping, and gives futex_wait_queue_me.
Could this be down to a memory leak somewhere causing too many calls to futex?
#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <pcap.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#define VERSION "1.0"
#define PCKT_LEN 8192
/* Prototypes */
int sock;
void run();
void capture();
void usage();
in_addr_t sip;
in_addr_t dip;
char *dstip = 0;
int s_seq;
int sport;
int dport;
struct pseudo {
struct in_addr sourceip;
struct in_addr destip;
unsigned char placeholder;
unsigned char protocol;
unsigned char tcp_len;
struct tcphdr tcp;
};
struct ipheader {
unsigned char iph_ihl:5,
iph_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_id;
unsigned char iph_flags;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};
struct tcpheader {
unsigned short int tcph_sourceport;
unsigned short int tcph_destport;
unsigned int tcph_seqnum;
unsigned int tcph_acknum;
unsigned char tcph_reserved:4, tcph_offset:4;
unsigned char tcph_flags;
unsigned short int tcph_win;
unsigned short int tcph_chksum;
unsigned short int tcph_urgptr;
};
/* Checksum */
unsigned short checksum (unsigned short *pac, int len)
{
unsigned long sum;
for (sum = 0; len > 0; len--)
sum += *pac++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return(~sum);
}
/* Checksum TCP */
unsigned short checksum_tcp (unsigned short len, unsigned short sourceip[],
unsigned short destip[], unsigned short buf[])
{
unsigned char protocol = 6;
unsigned long sum;
int nleft;
unsigned short *w;
sum = 0;
nleft = len;
w=buf;
while(nleft > 1)
{
sum += *w++;
nleft -= 2;
}
if(nleft > 0)
{
sum += *w&ntohs(0xFF00);
}
sum += sourceip[0];
sum += sourceip[1];
sum += destip[0];
sum += destip[1];
sum += htons(len);
sum += htons(protocol);
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
sum = ~sum;
return ((unsigned short) sum);
}
int main(int argc,char **argv)
{
int c;
/* Are we in root? */
if(geteuid() !=0)
{
printf("Root access is required to run this program.\n\n");
exit(0);
}
while (1)
{
static struct option long_options[] =
{
/* Options */
{"send", no_argument, 0, 's'}, /* args s, r and f have no function yet */
{"receive", no_argument, 0, 'r'},
{"file", required_argument, 0, 'f'},
{"destip", required_argument, 0, 'i'},
{"destport", required_argument, 0, 'p'},
{"sourceip", required_argument, 0, 'o'},
{"sourceport", required_argument, 0, 't'},
{0, 0, 0, 0}
};
int option_index = 0;
c = getopt_long (argc, argv, "srf:d:i:p:o:t:",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0: /* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 's': puts ("option -s\n");
break;
case 'r': puts ("option -r\n");
break;
case 'f': printf ("option -f with value `%s'\n", optarg);
break;
case 'i': dip = inet_addr(optarg);
dstip = optarg;
break;
case 'p': dport = htons(atoi(optarg));
/* Add handling of bad/non number input here */
break;
case 'o': sip = inet_addr(optarg);
break;
case 't': sport = htons(atoi(optarg));
break;
case '?': /* Error message printed */
break;
default: abort ();
}
}
/* Print any remaining command line arguments (not options). */
if (optind < argc)
{
printf ("\nNon-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
/* check if all mandatory options are set and for unknown arguments */
/* This really needs changing... */
if (dip, sip, dport, sport == 0)
{
usage();
return (-1);
}
/* change */
pthread_t tid_pr;
if (pthread_create(&tid_pr, NULL, capture, NULL) != 0) {
fprintf(stderr, "can't create raw packet reader: %s\n", strerror(errno));
exit(1);
}
printf("\nRaw packet reader created\nWaiting 1 second for packet reader thread to settle down...\n\n");
sleep(1);
run();
pthread_join(tid_pr, NULL);
getchar ();
exit (0);
}
int send_syn(unsigned int sourceip, unsigned int destip, unsigned short sourceport,
unsigned short destport)
{
const int one = 1;
char buffer[PCKT_LEN];
struct sockaddr_in sin;
struct ipheader *ip;
struct tcpheader *tcp;
ip = (struct ipheader *) buffer;
tcp = (struct tcpheader *) buffer + ip->iph_ihl *4;
/* IP attributes */
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
ip->iph_id = htons(54321);
ip->iph_offset = 0;
ip->iph_ttl = 64;
ip->iph_protocol = IPPROTO_TCP;
ip->iph_chksum = 0;
ip->iph_sourceip = sip;
ip->iph_destip = dip;
ip->iph_chksum = checksum ((unsigned short *) buffer, (sizeof (struct
ipheader )+ sizeof (struct tcpheader)));
/* TCP attributes */
tcp->tcph_sourceport = sport;
tcp->tcph_destport = dport;
tcp->tcph_seqnum = htonl(1); /* ADD SEQ NUM THINGY */
tcp->tcph_offset = 5;
tcp->tcph_flags = TH_SYN;
tcp->tcph_win = htons(32767);
tcp->tcph_chksum = 0;
tcp->tcph_urgptr = 0;
tcp->tcph_chksum = (unsigned short) checksum_tcp((unsigned short) (ip->iph_len - ip->iph_ihl *4), (unsigned short *) &ip->iph_sourceip,
(unsigned short *) &ip->iph_destip, (unsigned short *) &tcp);
/* Address family */
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ip->iph_destip;
/* Send */
if (sendto(sock, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
fprintf(stderr, "\nCan't send packet\n");
return (-1);
}
else
printf("Packet sent to %d", dip);
close(sock);
}
int send_syn_ack(unsigned int sourceip, unsigned int destip, unsigned short sourceport,
unsigned short destport, unsigned long s_seq)
{
const int one = 1;
char buffer[PCKT_LEN];
struct sockaddr_in sin;
struct ipheader *ip;
struct tcpheader *tcp;
ip = (struct ipheader *) buffer;
tcp = (struct tcpheader *) buffer + ip->iph_ihl *4;
/* IP attributes */
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
ip->iph_id = htons(54321);
ip->iph_offset = 0;
ip->iph_ttl = 64;
ip->iph_protocol = IPPROTO_TCP;
ip->iph_chksum = 0;
ip->iph_sourceip = sip;
ip->iph_destip = dip;
ip->iph_chksum = checksum ((unsigned short *) buffer, (sizeof (struct
ipheader )+ sizeof (struct tcpheader)));
/* TCP attributes */
tcp->tcph_sourceport = sport;
tcp->tcph_destport = dport;
tcp->tcph_seqnum = htonl(1 + 1); /* ADD SEQ NUM THINGY */
tcp->tcph_acknum = htonl (s_seq + 1); /* ADD ACK NUM THINGY */
tcp->tcph_offset = 5;
tcp->tcph_flags = TH_ACK;
tcp->tcph_win = htons(32767);
tcp->tcph_chksum = 0;
tcp->tcph_urgptr = 0;
tcp->tcph_chksum = (unsigned short) checksum_tcp((unsigned short) (ip->iph_len - ip->iph_ihl *4), (unsigned short *) &ip->iph_sourceip,
(unsigned short *) &ip->iph_destip, (unsigned short *) &tcp);
/* Address family */
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ip->iph_destip;
/* Send */
if (sendto(sock, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
fprintf(stderr, "\nCan't send packet\n");
return (-1);
}
else
printf("Packet sent to %d\n", dip);
close(sock);
}
void run()
{
const int one = 1;
char buffer[PCKT_LEN];
struct sockaddr_in sin;
struct ipheader *ip;
struct tcpheader *tcp;
ip = (struct ipheader *) buffer;
tcp = (struct tcpheader *) buffer + ip->iph_ihl *4;
sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
if (sock < 0)
{
fprintf(stderr, "\nSocket()\n\n");
exit (-1);
}
else
printf ("socket() - Using SOCK_RAW and TCP protocol is OK.\n");
if ((setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof (one))) < 0)
{
fprintf(stderr, "Can't set socketoptions\n");
exit (-1);
}
else
printf("Socketoptions OK.\n");
send_syn(dip, sip, dport, sport);
}
void receive(u_char *args, const struct pcap_pkthdr *pkthdr, const u_char *buffer)
{
const int one = 1;
int LEN = strtol(args, NULL, 0); /* LEN = strtol(args, NULL, 0) ---- int LEN = *args;*/
struct ipheader *ip;
struct tcpheader *tcp;
ip = (struct ipheader *)(buffer + LEN);
tcp = (struct tcpheader *)(buffer + LEN + sizeof (struct ipheader));
printf("%d\n", LEN);
printf("Packet received. ACK number: %d\n", ntohl (tcp->tcph_seqnum));
printf("Packet received. SEQ number: %d\n", ntohl (tcp->tcph_acknum));
s_seq = ntohl (tcp->tcph_seqnum);
send_syn_ack(s_seq, dip, sip, dport, sport);
sleep(100);
}
void capture()
{
pcap_t *pd;
bpf_u_int32 netmask;
bpf_u_int32 localnet;
char filterbuf[64];
snprintf(filterbuf, sizeof(filterbuf), "ip dst host %s", dstip);
char *filter = filterbuf;
char *dev = NULL;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program filterprog;
int dl = 0, dl_len = 0;
if ((pd = pcap_open_live(dev, 1514, 1, 500, errbuf)) == NULL) /* Look into snaplen size */
{
fprintf(stderr, "can't open device %s: %s\n", dev, errbuf);
exit(1);
}
pcap_lookupnet(dev, &localnet, &netmask, errbuf);
pcap_compile(pd, &filterprog, filter, 0, localnet);
if (pcap_setfilter(pd, &filterprog) == - 1)
{
fprintf(stderr, "can't set pcap filter: %s %s\n", filter, errbuf);
exit(1);
}
pcap_freecode(&filterprog);
dl = pcap_datalink(pd);
switch(dl) {
case 1:
dl_len = 14;
break;
default:
dl_len = 14;
break;
}
if (pcap_loop(pd, -1, receive, (u_char *) &dl_len) < 0)
{
fprintf(stderr, "can't get raw packet: %s\n", pcap_geterr(pd));
exit(1);
}
}
void usage()
{
/* This is the user manual (CHANGE) */
printf("\nChannelBunny %s, created 2012\n\n", VERSION);
printf("ChannelBunny Usage: -s -f <file> -i <destip> -p <destport> -o <sourceip> -t <sourceport>\n\n");
printf("-s, --send, Puts program in send mode\n");
printf("-r, --receive, Puts program in receive mode\n");
printf("-f, --file, Specify file\n");
printf("-i, --destip, Destination IP address\n");
printf("-p, --destport, Destination port\n");
printf("-o, --sourceip Source IP address\n");
printf("-t, --sourceport Source port\n");
}
The main problem of your code is that you're not handling correctly the LINK-LAYER TYPE, you are using:
pcap_open_live with the fisrt argument set to NULL, this mean that the kernel will choose "any" interface to sniff and inject RAW packets, in this case your are using "LINKTYPE_LINUX_SLL" instead of ETHERNET which is what you want (LINK_TYPE 1).
So you need to handle the link layer correctly (checkout the list here: http://www.tcpdump.org/linktypes.html). I modify your code and it works now(replace device eth0 with what you want):
#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <pcap.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define VERSION "1.0"
#define PCKT_LEN 8192
/* Prototypes */
int sock;
void run();
void* capture(void *);
void usage();
in_addr_t sip;
in_addr_t dip;
char *dstip = 0;
int s_seq;
unsigned short sport;
unsigned short dport;
struct pseudo {
struct in_addr sourceip;
struct in_addr destip;
unsigned char placeholder;
unsigned char protocol;
unsigned char tcp_len;
struct tcphdr tcp;
};
struct ipheader {
unsigned char iph_ihl:5,
iph_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_id;
unsigned char iph_flags;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};
struct tcpheader {
unsigned short int tcph_sourceport;
unsigned short int tcph_destport;
unsigned int tcph_seqnum;
unsigned int tcph_acknum;
unsigned char tcph_reserved:4, tcph_offset:4;
unsigned char tcph_flags;
unsigned short int tcph_win;
unsigned short int tcph_chksum;
unsigned short int tcph_urgptr;
};
/* Checksum */
unsigned short checksum (unsigned short *pac, int len)
{
unsigned long sum;
for (sum = 0; len > 0; len--)
sum += *pac++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return(~sum);
}
/* Checksum TCP */
unsigned short checksum_tcp (unsigned short len, unsigned short sourceip[],
unsigned short destip[], unsigned short buf[])
{
unsigned char protocol = 6;
unsigned long sum;
int nleft;
unsigned short *w;
sum = 0;
nleft = len;
w=buf;
while(nleft > 1)
{
sum += *w++;
nleft -= 2;
}
if(nleft > 0)
{
sum += *w&ntohs(0xFF00);
}
sum += sourceip[0];
sum += sourceip[1];
sum += destip[0];
sum += destip[1];
sum += htons(len);
sum += htons(protocol);
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
sum = ~sum;
return ((unsigned short) sum);
}
int main(int argc,char **argv)
{
int c;
/* Are we in root? */
if(geteuid() !=0)
{
printf("Root access is required to run this program.\n\n");
exit(0);
}
while (1)
{
static struct option long_options[] =
{
/* Options */
{"send", no_argument, 0, 's'}, /* args s, r and f have no function yet */
{"receive", no_argument, 0, 'r'},
{"file", required_argument, 0, 'f'},
{"destip", required_argument, 0, 'i'},
{"destport", required_argument, 0, 'p'},
{"sourceip", required_argument, 0, 'o'},
{"sourceport", required_argument, 0, 't'},
{0, 0, 0, 0}
};
int option_index = 0;
c = getopt_long (argc, argv, "srf:d:i:p:o:t:",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0: /* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 's': puts ("option -s\n");
break;
case 'r': puts ("option -r\n");
break;
case 'f': printf ("option -f with value `%s'\n", optarg);
break;
case 'i': dip = inet_addr(optarg);
dstip = optarg;
break;
case 'p': dport = htons(atoi(optarg));
/* Add handling of bad/non number input here */
break;
case 'o': sip = inet_addr(optarg);
break;
case 't': sport = htons(atoi(optarg));
break;
case '?': /* Error message printed */
break;
default: abort ();
}
}
/* Print any remaining command line arguments (not options). */
if (optind < argc)
{
printf ("\nNon-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
/* check if all mandatory options are set and for unknown arguments */
/* This really needs changing... */
if ((dip && sip && dport && sport) == 0)
{
usage();
return (-1);
}
fprintf(stdout, "SPORT : %d, DPORT : %d\n", sport, dport);
/* change */
pthread_t tid_pr;
if (pthread_create(&tid_pr, NULL, capture, NULL) != 0) {
fprintf(stderr, "can't create raw packet reader: %s\n", strerror(errno));
exit(1);
}
printf("\nRaw packet reader created\nWaiting 1 second for packet reader thread to settle down...\n\n");
sleep(1);
run();
pthread_join(tid_pr, NULL);
getchar ();
exit (0);
}
int send_syn(unsigned int sourceip, unsigned int destip, unsigned short sourceport,
unsigned short destport)
{
//const int one = 1;
char buffer[PCKT_LEN];
struct sockaddr_in sin;
struct ipheader *ip;
struct tcpheader *tcp;
ip = (struct ipheader *) buffer;
tcp = (struct tcpheader *) buffer + ip->iph_ihl *4;
/* IP attributes */
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
ip->iph_id = htons(54321);
ip->iph_offset = 0;
ip->iph_ttl = 64;
ip->iph_protocol = IPPROTO_TCP;
ip->iph_chksum = 0;
ip->iph_sourceip = sip;
ip->iph_destip = dip;
ip->iph_chksum = checksum ((unsigned short *) buffer, (sizeof (struct
ipheader )+ sizeof (struct tcpheader)));
/* TCP attributes */
tcp->tcph_sourceport = sport;
tcp->tcph_destport = dport;
tcp->tcph_seqnum = htonl(1); /* ADD SEQ NUM THINGY */
tcp->tcph_offset = 5;
tcp->tcph_flags = TH_SYN;
tcp->tcph_win = htons(32767);
tcp->tcph_chksum = 0;
tcp->tcph_urgptr = 0;
tcp->tcph_chksum = (unsigned short) checksum_tcp((unsigned short) (ip->iph_len - ip->iph_ihl *4), (unsigned short *) &ip->iph_sourceip,
(unsigned short *) &ip->iph_destip, (unsigned short *) &tcp);
/* Address family */
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ip->iph_destip;
/* Send */
if (sendto(sock, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
fprintf(stderr, "\nCan't send packet\n");
return (-1);
}
else
printf("Packet sent to %d", dip);
close(sock);
return 0;
}
int send_syn_ack(unsigned int sourceip, unsigned int destip, unsigned short sourceport,
unsigned short destport, unsigned long s_seq)
{
//const int one = 1;
char buffer[PCKT_LEN];
struct sockaddr_in sin;
struct ipheader *ip;
struct tcpheader *tcp;
ip = (struct ipheader *) buffer;
tcp = (struct tcpheader *) buffer + ip->iph_ihl *4;
/* IP attributes */
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
ip->iph_id = htons(54321);
ip->iph_offset = 0;
ip->iph_ttl = 64;
ip->iph_protocol = IPPROTO_TCP;
ip->iph_chksum = 0;
ip->iph_sourceip = sip;
ip->iph_destip = dip;
ip->iph_chksum = checksum ((unsigned short *) buffer, (sizeof (struct
ipheader )+ sizeof (struct tcpheader)));
/* TCP attributes */
tcp->tcph_sourceport = sport;
tcp->tcph_destport = dport;
tcp->tcph_seqnum = htonl(1 + 1); /* ADD SEQ NUM THINGY */
tcp->tcph_acknum = htonl (s_seq + 1); /* ADD ACK NUM THINGY */
tcp->tcph_offset = 5;
tcp->tcph_flags = TH_ACK;
tcp->tcph_win = htons(32767);
tcp->tcph_chksum = 0;
tcp->tcph_urgptr = 0;
tcp->tcph_chksum = (unsigned short) checksum_tcp((unsigned short) (ip->iph_len - ip->iph_ihl *4), (unsigned short *) &ip->iph_sourceip,
(unsigned short *) &ip->iph_destip, (unsigned short *) &tcp);
/* Address family */
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = ip->iph_destip;
/* Send */
if (sendto(sock, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
fprintf(stderr, "\nCan't send packet : %s\n", strerror(errno));
return (-1);
}
else
printf("Packet sent to %d\n", dip);
close(sock);
return 0;
}
void run()
{
const int one = 1;
//char buffer[PCKT_LEN];
//struct sockaddr_in sin;
//struct ipheader *ip;
//struct tcpheader *tcp;
//ip = (struct ipheader *) buffer;
//tcp = (struct tcpheader *) buffer + ip->iph_ihl *4;
sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
if (sock < 0)
{
fprintf(stderr, "\nSocket()\n\n");
exit (-1);
}
else
printf ("socket() - Using SOCK_RAW and TCP protocol is OK.\n");
if ((setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof (one))) < 0)
{
fprintf(stderr, "Can't set socketoptions\n");
exit (-1);
}
else
printf("Socketoptions OK.\n");
send_syn(dip, sip, dport, sport);
}
void receive(u_char *args, const struct pcap_pkthdr *pkthdr, const u_char *buffer)
{
//const int one = 1;
//int LEN = strtol(args, NULL, 0); /* LEN = strtol(args, NULL, 0) ---- int LEN = *args;*/
int LEN = atoi((char *)args);
//struct ipheader *ip;
struct tcpheader *tcp;
//ip = (struct ipheader *)(buffer + LEN);
tcp = (struct tcpheader *)(buffer + LEN + sizeof (struct ipheader));
printf("LEN = %d\n", LEN);
printf("Packet received. ACK number: %d\n", ntohl (tcp->tcph_seqnum));
printf("Packet received. SEQ number: %d\n", ntohl (tcp->tcph_acknum));
s_seq = ntohl (tcp->tcph_seqnum);
send_syn_ack(s_seq, dip, sip, dport, sport);
sleep(100);
}
void* capture(void *unused_arg)
{
pcap_t *pd;
bpf_u_int32 netmask;
bpf_u_int32 localnet;
char filterbuf[64];
snprintf(filterbuf, sizeof(filterbuf), "ip dst host %s", dstip);
char *filter = filterbuf;
//char *dev = NULL;
char dev[] = "eth0";
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program filterprog;
int dl = 0, dl_len = 0;
/* TODO : SET THE INTERFACE CORRECTLY */
//if ((pd = pcap_open_live(dev, 1514, 1, 500, errbuf)) == NULL) /* Look into snaplen size */
if ((pd = pcap_open_live(dev, 1514, 1, 500, errbuf)) == NULL) /* Look into snaplen size */
{
fprintf(stderr, "can't open device %s: %s\n", dev, errbuf);
exit(1);
}
pcap_lookupnet(dev, &localnet, &netmask, errbuf);
pcap_compile(pd, &filterprog, filter, 0, localnet);
if (pcap_setfilter(pd, &filterprog) == - 1)
{
fprintf(stderr, "can't set pcap filter: %s %s\n", filter, errbuf);
exit(1);
}
pcap_freecode(&filterprog);
dl = pcap_datalink(pd);
switch(dl) {
/* TODO : HANDLE THIS PART CORRECTLY */
case 1:
dl_len = 14; /* Ethernet header */
fprintf(stdout, "\nDL = %d (ETHERNET)\n", dl);
break;
default:
dl_len = 14;
fprintf(stdout, "\nDL = %d (if you are here please handle correctly)\n", dl);
break;
}
if (pcap_loop(pd, -1, receive, (u_char *) &dl_len) < 0)
{
fprintf(stderr, "can't get raw packet: %s\n", pcap_geterr(pd));
exit(1);
}
return NULL;
}
void usage()
{
/* This is the user manual (CHANGE) */
printf("\nChannelBunny %s, created 2012\n\n", VERSION);
printf("ChannelBunny Usage: -s -f <file> -i <destip> -p <destport> -o <sourceip> -t <sourceport>\n\n");
printf("-s, --send, Puts program in send mode\n");
printf("-r, --receive, Puts program in receive mode\n");
printf("-f, --file, Specify file\n");
printf("-i, --destip, Destination IP address\n");
printf("-p, --destport, Destination port\n");
printf("-o, --sourceip Source IP address\n");
printf("-t, --sourceport Source port\n");
}
EDIT : Setting interface
To set the interface for pcap_open_live, use ifconfig command to check which interface you want to use, in the case of other interface than ETHERNET, you need to change your code, because the header will change.
To debug your code, you can use the old printf (it's always useful), add this in line in all parts that you suspect to be the cause of trouble:
fprintf(stdout, "Function : %s, Line : %d\n", __FUNCTION__, __LINE__);
EDIT2 : The value of the ETHERNET header passed to the receive function was wrong
Use :
int LEN = *(int *)args;
instead of:
int LEN = strtol(args, NULL, 0);
And then you can see clearly that the LEN is now 14 (Ethernet header length).
Another thing : i don't really understand how you think the global var sock will behave! your socket is created in the run function after the thread was launched! and you try to close it twice : inside send_syn_ack and send_syn.
You need to think the design of your code (take some time to do so).
I think that you should create the main socket inside the main function and close it when you want (inside the main function or when some errors occur).
Last thing please use : strerror(errno) with all your calls so you can trace the errors easily.
Hope this help.
I am having some trouble with compiling my code due to these error messages (I suspect they are somewhat related)
In function ‘forgepacket’:
error: expected specifier-qualifier-list before ‘send_tcp’
In function ‘send_tcp’:
error: invalid application of ‘sizeof’ to incomplete type ‘struct ipheader’
error: invalid application of ‘sizeof’ to incomplete type ‘struct tcpheader’
and
error: dereferencing pointer to incomplete type
every time i try to access ip->iph or tcp->tcph. Now I've gathered that the problem lies with the definition of struct ipheader and struct tcpheader, but I can't really figure out what.
I've been looking at similar error message questions as the ones above but I can't really figure it out.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#define VERSION "1.0"
#define PCKT_LEN 8192
/* Prototypes */
void forgepacket (unsigned int, unsigned int, unsigned short, unsigned short);
int send_tcp();
void usage();
/* Checksum */
unsigned short checksum (unsigned short *pac, int len)
{
unsigned long sum;
for (sum = 0; len > 0; len--)
sum += *pac++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return(~sum);
}
in_addr_t sip;
in_addr_t dip;
int sport;
int dport;
int main(int argc,char **argv)
{
int c;
/* Are we in root? */
if(geteuid() !=0)
{
printf("Root access is required to run this program.\n\n");
exit(0);
}
while (1)
{
static struct option long_options[] =
{
/* Options */
{"send", no_argument, 0, 's'}, /* args s and r have no function yet */
{"recieve", no_argument, 0, 'r'},
{"file", required_argument, 0, 'f'},
{"destip", required_argument, 0, 'i'},
{"destport", required_argument, 0, 'p'},
{"sourceip", required_argument, 0, 'o'},
{"sourceport", required_argument, 0, 't'},
{0, 0, 0, 0}
};
int option_index = 0;
c = getopt_long (argc, argv, "srf:d:i:p:o:t:",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 's':
puts ("option -s\n");
break;
case 'r':
puts ("option -r\n");
break;
case 'f':
printf ("option -f with value `%s'\n", optarg);
break;
case 'i':
dip = inet_addr(optarg);
break;
case 'p':
dport = htons(atoi(optarg));
/* Add handling of bad/non number input here */
break;
case 'o':
sip = inet_addr(optarg);
break;
case 't':
sport = htons(atoi(optarg));
break;
case '?':
/* Error message printed */
break;
default:
abort ();
}
}
/* Print any remaining command line arguments (not options). */
if (optind < argc)
{
printf ("\nNon-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
/* check if all mandatory options are set and for unknown arguments */
/* This really needs changing... */
if (dip, sip, dport, sport == 0)
{
usage();
return (-1);
}
forgepacket(dip, sip, dport, sport);
getchar ();
exit (0);
}
void forgepacket(unsigned int sourceip, unsigned int destip, unsigned short sourceport,
unsigned short destport)
{
/* IP header structure */
struct ipheader {
unsigned char iph_ihl:5,
iph_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_id;
unsigned char iph_flags;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};
/* TCP header structure */
struct tcpheader {
unsigned short int tcph_sourceport;
unsigned short int tcph_destport;
unsigned int tcph_seqnum;
unsigned int tcph_acknum;
unsigned char tcph_reserved:4, tcph_offset:4;
unsigned int
tcp_res1:4,
tcph_hlen:4,
tcph_fin:1,
tcph_syn:1,
tcph_rst:1,
tcph_psh:1,
tcph_ack:1,
tcph_urg:1,
tcph_res2:2;
unsigned short int tcph_win;
unsigned short int tcph_chksum;
unsigned short int tcph_urgptr;
send_tcp();
};
}
int send_tcp()
{
int sock, one = 1;
char buffer[PCKT_LEN];
struct sockaddr_in sin, din;
const int *val = &one;
sock = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
if (sock < 0)
{
printf("\nError: socket()\n\n");
exit (-1);
}
else
printf ("\nsocket() - Using SOCK_RAW and TCP protocol is OK.\n\n");
/* Size of the headers */
struct ipheader *ip = (struct ipheader *) buffer;
struct tcpheader *tcp = (struct tcpheader *) (buffer + sizeof (struct ipheader));
memset (buffer, 0, PCKT_LEN);
/* IP attributes */
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
ip->iph_id = htons(54321);
ip->iph_offset = 0;
ip->iph_ttl = 64;
ip->iph_protocol = 6;
ip->iph_chksum = 0;
ip->iph_sourceip = sip;
ip->iph_destip = dip;
/* TCP attributes */
tcp->tcph_sourceport = sport;
tcp->tcph_destport = dport;
tcp->tcph_seqnum = htonl(1);
tcp->tcph_acknum = 0;
tcp->tcph_offset = 5;
tcp->tcph_syn = 1;
tcp->tcph_ack = 0;
tcp->tcph_win = htons(32767);
tcp->tcph_chksum = 0;
tcp->tcph_urgptr = 0;
ip->iph_chksum = checksum ((unsigned short *) buffer, (sizeof (struct ipheader )+ sizeof (struct tcpheader)));
/* Address family */
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
/* Source port */
sin.sin_port = sport;
din.sin_port = dport;
/* Source IP */
sin.sin_addr.s_addr = sip;
din.sin_addr.s_addr = dip;
/* Tell the Kernel we're building our own packet */
if ((setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof (one))) < 0)
{
printf("\nError: Can't set socketoptions\n\n");
return (-1);
}
/* Send */
if (sendto(sock, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
printf("\nError: Can't send packet\n\n");
return (-1);
}
else
printf("Packet sent to %d", dip);
close(sock);
}
void usage()
{
/* This is the user manual */
printf("\nTCP project %s\n\n", VERSION);
printf("Usage: -s -f <file> -i <destip> -p <destport> -o <sourceip> -t <sourceport>\n\n");
printf("-s, --send, Puts program in send mode\n");
printf("-r, --recieve, Puts program in recieve mode\n");
printf("-f, --file, Specify file containing steganographic message\n");
printf("-i, --destip, Destination IP address\n");
printf("-p, --destport, Destination port\n");
printf("-o, --sourceip Source IP address\n");
printf("-t, --sourceport Source port\n");
}
1) The call to send_tcp should be moved outside of the sturct definition, of course:
};
send_tcp();
2) struct tcpheader and ipheader should be moved outside forgepacket
The code compiles fine now.
If I may add, I suggest you learn C and indent your code properly !
Just Add this header file. It will work.
/* Ethernet header */
struct ethheader {
u_char ether_dhost[6]; /* destination host address */
u_char ether_shost[6]; /* source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};
/* IP Header */
struct ipheader {
unsigned char iph_ihl:4, //IP header length
iph_ver:4; //IP version
unsigned char iph_tos; //Type of service
unsigned short int iph_len; //IP Packet length (data + header)
unsigned short int iph_ident; //Identification
unsigned short int iph_flag:3, //Fragmentation flags
iph_offset:13; //Flags offset
unsigned char iph_ttl; //Time to Live
unsigned char iph_protocol; //Protocol type
unsigned short int iph_chksum; //IP datagram checksum
struct in_addr iph_sourceip; //Source IP address
struct in_addr iph_destip; //Destination IP address
};
/* ICMP Header */
struct icmpheader {
unsigned char icmp_type; // ICMP message type
unsigned char icmp_code; // Error code
unsigned short int icmp_chksum; //Checksum for ICMP Header and data
unsigned short int icmp_id; //Used for identifying request
unsigned short int icmp_seq; //Sequence number
};
/* UDP Header */
struct udpheader
{
u_int16_t udp_sport; /* source port */
u_int16_t udp_dport; /* destination port */
u_int16_t udp_ulen; /* udp length */
u_int16_t udp_sum; /* udp checksum */
};
/* TCP Header */
struct tcpheader {
u_short tcp_sport; /* source port */
u_short tcp_dport; /* destination port */
u_int tcp_seq; /* sequence number */
u_int tcp_ack; /* acknowledgement number */
u_char tcp_offx2; /* data offset, rsvd */
#define TH_OFF(th) (((th)->tcp_offx2 & 0xf0) >> 4)
u_char tcp_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short tcp_win; /* window */
u_short tcp_sum; /* checksum */
u_short tcp_urp; /* urgent pointer */
};
/* Psuedo TCP header */
struct pseudo_tcp
{
unsigned saddr, daddr;
unsigned char mbz;
unsigned char ptcl;
unsigned short tcpl;
struct tcpheader tcp;
char payload[1500];
};
I want to sent TCP packets via raw socket and then I got stuck with the checksum field of tcp header. since I dont know how to figure out the actual IP address that raw socket had used, it seems impossible to construct TCP pseudo-header for checksum computation.
You know the ip address.
Because: Prior to sending any data over this socket you ought to bind() it, for doing so you need to specify the ip address you are looking for.
Update:
Binding to INADDR_ANY binds to any local interface. To get information on all local interfaces (including each's ip address) you might use getifaddrs().
Look at the following code if its any help. I used this code to make my own send_raw_tcp() function so i know it works.
//---cat rawtcp.c---
// Run as root or SUID 0, just datagram no data/payload
#include <unistd.h>mm
#include <netinet/tcp.h>
// Packet length
#define PCKT_LEN 8192
// May create separate header file (.h) for all
// headers' structures
// IP header's structure
struct ipheader {
unsigned char iph_ihl:5, /* Little-endian */
iph_ver:4;
unsigned char iph_tos;
unsigned short int iph_len;
unsigned short int iph_ident;
unsigned char iph_flags;
unsigned short int iph_offset;
unsigned char iph_ttl;
unsigned char iph_protocol;
unsigned short int iph_chksum;
unsigned int iph_sourceip;
unsigned int iph_destip;
};
/* Structure of a TCP header */
struct tcpheader {
unsigned short int tcph_srcport;
unsigned short int tcph_destport;
unsigned int tcph_seqnum;
unsigned int tcph_acknum;
unsigned char tcph_reserved:4, tcph_offset:4;
// unsigned char tcph_flags;
unsigned int
tcp_res1:4, /*little-endian*/
tcph_hlen:4, /*length of tcp header in 32-bit words*/
tcph_fin:1, /*Finish flag "fin"*/
tcph_syn:1, /*Synchronize sequence numbers to start a connection*/
tcph_rst:1, /*Reset flag */
tcph_psh:1, /*Push, sends data to the application*/
tcph_ack:1, /*acknowledge*/
tcph_urg:1, /*urgent pointer*/
tcph_res2:2;
unsigned short int tcph_win;
unsigned short int tcph_chksum;
unsigned short int tcph_urgptr;
};
// Simple checksum function, may use others such as Cyclic Redundancy Check, CRC
unsigned short csum(unsigned short *buf, int len)
{
unsigned long sum;
for(sum=0; len>0; len--)
sum += *buf++;
sum = (sum >> 16) + (sum &0xffff);
sum += (sum >> 16);
return (unsigned short)(~sum);
}
int main(int argc, char *argv[])
{
int sd;
// No data, just datagram
char buffer[PCKT_LEN];
// The size of the headers
struct ipheader *ip = (struct ipheader *) buffer;
struct tcpheader *tcp = (struct tcpheader *) (buffer + sizeof(struct ipheader));
struct sockaddr_in sin, din;
int one = 1;
const int *val = &one;
memset(buffer, 0, PCKT_LEN);
if(argc != 5)
{
printf("- Invalid parameters!!!\n");
printf("- Usage: %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n", argv[0]);
exit(-1);
}
sd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
if(sd < 0)
{
perror("socket() error");
exit(-1);
}
else
printf("socket()-SOCK_RAW and tcp protocol is OK.\n");
// The source is redundant, may be used later if needed
// Address family
sin.sin_family = AF_INET;
din.sin_family = AF_INET;
// Source port, can be any, modify as needed
sin.sin_port = htons(atoi(argv[2]));
din.sin_port = htons(atoi(argv[4]));
// Source IP, can be any, modify as needed
sin.sin_addr.s_addr = inet_addr(argv[1]);
din.sin_addr.s_addr = inet_addr(argv[3]);
// IP structure
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;
ip->iph_len = sizeof(struct ipheader) + sizeof(struct tcpheader);
ip->iph_ident = htons(54321);
ip->iph_offset = 0;
ip->iph_ttl = 64;
ip->iph_protocol = 6; // TCP
ip->iph_chksum = 0; // Done by kernel
// Source IP, modify as needed, spoofed, we accept through command line argument
ip->iph_sourceip = inet_addr(argv[1]);
// Destination IP, modify as needed, but here we accept through command line argument
ip->iph_destip = inet_addr(argv[3]);
// The TCP structure. The source port, spoofed, we accept through the command line
tcp->tcph_srcport = htons(atoi(argv[2]));
// The destination port, we accept through command line
tcp->tcph_destport = htons(atoi(argv[4]));
tcp->tcph_seqnum = htonl(1);
tcp->tcph_acknum = 0;
tcp->tcph_offset = 5;
tcp->tcph_syn = 1;
tcp->tcph_ack = 0;
tcp->tcph_win = htons(32767);
tcp->tcph_chksum = 0; // Done by kernel
tcp->tcph_urgptr = 0;
// IP checksum calculation
ip->iph_chksum = csum((unsigned short *) buffer, (sizeof(struct ipheader) + sizeof(struct tcpheader)));
// Inform the kernel do not fill up the headers' structure, we fabricated our own
if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0)
{
perror("setsockopt() error");
exit(-1);
}
else
printf("setsockopt() is OK\n");
printf("Using:::::Source IP: %s port: %u, Target IP: %s port: %u.\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4]));
// sendto() loop, send every 2 second for 50 counts
unsigned int count;
for(count = 0; count < 20; count++)
{
if(sendto(sd, buffer, ip->iph_len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0)
// Verify
{
perror("sendto() error");
exit(-1);
}
else
printf("Count #%u - sendto() is OK\n", count);
sleep(2);
}
close(sd);
return 0;
}