setsockopt HDRINCL 'error code 22, Invalid arg' OpenBSD 3.3 using gcc 2.95.3
Asked by crizza in OpenBSD
Tags: hdrincl, setsockopt
Hi all. Im having problems allowing the kernel to let me include my own ip header.
I am writing anetwork /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 whenrun ; '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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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 ) ) < style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "> 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 ) ) < style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "> 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
/* initialcommand 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
--------------------------------------------------
I am writing a
The src compiles ok, but when
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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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 ) ) < style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "> 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 ) ) < style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; "> 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
typedef struct opts {
unsigned char *cfg; // absolute path
unsigned char *
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
--------------------------
No comments:
Post a Comment