Hi all. Im having problems allowing the kernel to let me include my own ip header.
I am writing a network/firewall and protocol analysis tool for my work.
Running on x86/OpenBSD 3.3 platform using gcc 2.95.3 with no special opts apart from debugging.
The src compiles ok, but when run; 'perror' recieves error code '22' 'invalid arg' from setsockopt ( i presume ) and I cannot understand why???
I have tested the prog bypassing the setsockopt function and it works ok, alas with the kernel ip header included ;(
Please forgive me if its a glaringly obvious error on my part as I am returning to c & *nix after a few years in the wilderness.
N.B Apologies, but my code seems to have lost all its tabs when i posted it
Many thanks for any help offered
Chris
--------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include <unistd.h>
#include "decs.h"
int main( void )
{
unsigned int tport;
unsigned short uno, s;
struct iphead *iphead;
struct tcphead *tcphead;
struct sockaddr_in dst;
char dgram[BUFFER];
tport = 1500;
uno = 1;
if( getuid() ) {
printf("ALERT: You need to be r00t\n");
exit( 0 );
}
if ( !( s = socket( AF_INET, SOCK_RAW, IPPROTO_TCP ) ) )
perror("socket error");
// cast dgram to struct and point *iphead at element
iphead = ( struct iphead *) dgram;
// as above but with size of ip_header offset
tcphead = ( struct tcphead *) dgram + sizeof( struct iphead );
dst.sin_family = AF_INET;
dst.sin_port = htons( tport );
dst.sin_addr.s_addr = inet_addr( "192.168.0.7" );
memset( dgram, 0, BUFFER );
// custom values
iphead->ip_hl = 5;
iphead->ip_v = 4;
iphead->ip_tos = 0;
iphead->ip_len = BUFFER;
iphead->ip_id = htonl( 1234 );
iphead->ip_off = 0;
iphead->ip_ttl = 255;
iphead->ip_p = 6; // tcp
iphead->ip_sum = 0; // set to 0 by default
iphead->ip_src.s_addr = inet_addr( "192.168.0.1" );
iphead->ip_dst.s_addr = dst.sin_addr.s_addr;
tcphead->th_sport = htons( 1234 );
tcphead->th_dport = htons( tport );
tcphead->th_seq = random();
tcphead->th_ack = 0;
tcphead->th_x2 = 0;
tcphead->th_off = 0;
tcphead->th_flags = TH_SYN; // init new connection
tcphead->th_win = htonl( MAX_WINDOW );
tcphead->th_sum = 0;
tcphead->th_urp = 0; // no urgency flags
// generate chksum
iphead->ip_sum = chksum( ( unsigned short *)dgram, iphead->ip_len >> 1 );
// header check
if ( setsockopt( s,
IPPROTO_IP,
IP_HDRINCL,
&uno,
sizeof( uno ) ) < 0 ) {
perror( "Alert: setsockopt cannot set HDRINCL" );
exit( 1 );
}
// kill with control-c
while( 1 ) {
if( sendto( s,
dgram,
sizeof( dgram ),
0,
( struct sockaddr * ) &dst,
sizeof( dst ) ) < 0 ) {
perror( "Alert: sendto failed" );
exit( 1 );
} else {
printf( "." );
}
}
exit( 0 );
}
--------------------------------------------------
// Decs.h
#ifndef H_DECS
#define H_DECS
#define BUFFER sizeof( struct iphead ) + sizeof( struct tcphead )
#define MAX_WINDOW 65535
__BEGIN_DECLS
unsigned short chksum( unsigned short *, int );
void chkhdr( unsigned short );
__END_DECLS
/* initial command line opts */
typedef struct opts {
unsigned char *cfg; // absolute path
unsigned char *host; // dest host
unsigned short int port; // dest port
unsigned short int pkts; // number of packets to send
}cli_opts;
struct iphead {
unsigned char ip_hl, ip_v; // 4 bits respectively
unsigned char ip_tos; // limo or taxi???
unsigned short int ip_len; // total len of header and data
unsigned short int ip_id; // help assemble fragments
unsigned short ip_off; // 3bit control flags, 13bit offset. Do i frag?
unsigned char ip_ttl; // --ttl each hop. if 0 then destroy
unsigned char ip_p; // next level protocol
unsigned short int ip_sum; // header checksum
struct in_addr ip_src, ip_dst; // source and dest
};
struct tcphead {
unsigned short int th_sport; // source port
unsigned short int th_dport; // destination port
unsigned int th_seq; // seq number of first data octet in segment
unsigned int th_ack; // next seq num expected to recieve
unsigned char th_x2, th_off; /* x2 reserved for future use ( must be 0 )
* data_off indicates where data begins */
unsigned char th_flags; /* TH_URG: urgent, TH_ACK: yup, TH_PSH, do not
* buffer segment push straight thro stack
* TH_RST: tell peer to terminate
* TH_SYN: init new connect
* TH_FIN: close connection
* control bits */
unsigned short int th_win; /* amount of data octets to be accepted
* including original seq_num octet */
unsigned short int th_sum; // initial value = 0
unsigned short int th_urp; // only used if TH_URG is set in tcp_flags
};
/* standard BSD checksum */
unsigned short chksum ( unsigned short *addr, int len ) {
register int sum = 0;
u_short answer = 0;
register u_short *w = addr;
register int nleft = len;
/* 32 bit accumulator 'sum', add sequential 16 bit words to it '*w'.
* At the end fold back all the carry bits from top 16 bits into
* lower 16 bits */
while ( nleft > 1 ) {
sum += *w++;
nleft -= 2;
}
// mop up odd byte, if necessary
if ( nleft == 1 ) {
*( u_char * ) ( &answer ) = *( u_char * )w ;
sum += answer;
}
// add back carry outs from top 16 bits to lower 16 bits
sum = ( sum >> 16 ) + ( sum + 0xffff ); // add hi 16 to low 16
sum += ( sum >> 16 ); // add carry
answer = ~sum; // truncate to 16bits
return ( answer );
}
// check kernel hasnt inserted header
void chkhdr( unsigned short sockd ) {
}
#endif
--------------------------------------------------
by: sunnycoderPosted on 2003-08-30 at 00:51:53ID: 9253373
I hevent worked on BSD but here are my 2 cents
>> if ( !( s = socket( AF_INET, SOCK_RAW, IPPROTO_TCP ) ) )
>> perror("socket error");
socket returns -1 and not 0 if error occurs.... and in C everything except 0 is true ...
thus in case of error your statement would look like
if ( ! -1 ) == if ( 0 )
perror();
It may be possible that you are encountering some error in socket() and the invalid socket descriptor is being used in setsockopt() and hence the error