Question

setsockopt HDRINCL 'error code 22, Invalid arg' OpenBSD 3.3 using gcc 2.95.3

Asked by: crizza

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
--------------------------------------------------

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2003-08-29 at 17:06:56ID20724273
Tags

hdrincl

,

setsockopt

Topic

OpenBSD

Participating Experts
1
Points
500
Comments
9

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. Warning: unsigned int format, pointer arg (arg 3)
    I compiled the code below using: gcc voidpointer.c -o voidpointer -Wall and I got a warning message: Warning: unsigned int format, pointer arg (arg 3) Also, please answer my question (commented in the code). #include <stdio.h> /* according ansi c, which one is correc...
  2. printf, vprintf and va_arg
    Hi, My problem is that I want to call printf with variable number of arguments, which are known only during runtime(!). Let me explain. The user configures output of my program in config file and let's say he wants to print "%s", ProgramName. I can internally find c...
  3. for args?
    for args do echo $args done what the args mean,it has specific meaning?
  4. printf implementation
    Sample program: ------------------------------------------------- #include <stdio.h> void main() { printf("%d"); } -------------------------------------------------- This program prints junk value. I'm curious, how printf is implemented. How it interp...
  5. jni - passing args
    What's wrong with the following code? I try to pass a string (from C++ code) into a Java's main(..). However, I receive a "null" inside the Java class. JNIEnv *env; jstring jstr; jobjectArray args; char buff[100]; ........... printf(buff); // 'buff' is "3...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

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

 

by: crizzaPosted on 2003-08-30 at 05:05:42ID: 9253760

Hi Sunnycoder.

Thanks for your 2 cents!!! you spotted a rather stupid error on my part.
I have thus changed the code to this ==>

if ( ( s = socket( AF_INET, SOCK_RAW, IPPROTO_TCP ) ) < 0 )
              perror( "socket error" );

changed s to a regular unsigned integer to make the comparison meaningful and hopefully now I will get an error if the socket descriptor cannot be assigned.

Unfortunately I am still encountering the same error as before with the setsockopt .

I had a look through the code for the ping prog because ping uses raw sockets and the setsockopt is the same there using the same values as I have ( eg uno = 1 , the ping code uses a var hold = 1 and they pass the address of hold to the function aswell )

Even if we cannot come across a full solution for this problem together sunny I would still like to give you some points for pointing out the error on my return value comparison for the socket function. How does 150 sound??? Unfortunately I do not know how to allocate a portion of my points to you individually. Any ideas???

 

by: sunnycoderPosted on 2003-08-30 at 06:11:32ID: 9253844

sounds great ...
to divide points, use point split feature ... you will find it right on top of the box in which you type your replies
split points when you have decided to close the question ...

Incase you dont get a satisfactory reply to the question, you can post in community support to adjust the point value

alternatively you can request mods to delete the question and post another question with 150 points

meanwhile i will try to find out why is setsockopt failing ...

linux man page lists following errors

ERRORS
       EBADF  The argument s is not a valid descriptor.

       ENOTSOCK
              The argument s is a file, not a socket.

       ENOPROTOOPT
              The option is unknown at the level indicated.

       EFAULT The  address pointed to by optval is not in a valid
              part of the process address space.  For getsockopt,
              this error may also be returned if optlen is not in
              a valid part of the process address space.

is it EBADF or ENOTSOCK which you are encountering

 

by: crizzaPosted on 2003-08-30 at 08:35:54ID: 9254173

Apparently I have to allocate all points over a spread of answers at one time. If for some reason I forget then dont hesitate to remind me pls.  Unless of course you get all the points !

Back to business!

I have the same/similar manpage with same errors, but the only error I can deduce Is the one that perror is sent on the failure of the call.

I dont know about Linux but 'perror' translates the global error code ( extern int errno that resides in header file errno.h ) that is set whenever ( most ) functions fail.

The global  errno translated by perror is code 22 EINVAL - Invalid arg ( see 'man 2 errno' ) 'Ive printed it via printf ( eg without perror ) to check'

IP_HDRINCL is defined in hdr file in.h like so:
#define IP_HDRINCL               2  // int; header is included with data

and also ( slightly differently )  in hdr file in_pcb.h like so

#define INP_HDRINCL            0x008 // user supplies entire IP header

I have tried both of these and their header files in different combos with no luck.

I am at my wits end sunny, I have been trying to solve this for days now without even a clue or hint as to were im going wrong ;( And ill put money on it that its something really simple. these things always are, like a needle in a haystack, shoot i dont even like hay  lol.

Oh well, get there in the end I think, just a matter of how long!

Chris

 

by: sunnycoderPosted on 2003-08-31 at 06:19:59ID: 9256942

>>And ill put money on it that its something really simple. these things always are
lol ... thats somehow always true

Ok heres some hit and trial thing

1. are you executing this code as root ? If no, then try executing this as root

2.
if ( !( s = socket( AF_INET, SOCK_RAW, IPPROTO_TCP ) ) )
       perror("socket error"); >>>>>>>>>>>> try using IPPROTO_RAW and execute as root ... does not make sense I know :)

3.
if ( setsockopt( s,       >>>>>>>>>>> if socket is successful then this is a valid argument
   IPPROTO_IP,           >>>>>>>>>>> valid constant
   IP_HDRINCL,          >>>>>>>>>>> valid constant
   &uno,                      >>>>>>>>>>> clearly valid arg
   sizeof( uno ) ) < 0 ) {   >>>>>>>>> another valid arg
   perror( "Alert: setsockopt cannot set HDRINCL" );
   exit( 1 );
   }
so even I am foxed, why the error ??? are you sure of the error message being printed by perror ... try clearing errno before making any calls and then check the error message

 

by: crizzaPosted on 2003-08-31 at 07:18:04ID: 9257074

Hi Sunnycoder, thanks for you post

1. are you executing this code as root ? If no, then try executing this as root

 Program wont run unless uid == 0;

2.
if ( !( s = socket( AF_INET, SOCK_RAW, IPPROTO_TCP ) ) )
      perror("socket error"); >>>>>>>>>>>> try using IPPROTO_RAW and execute as root ... does not make sense I know :)

      global int errno == BAD FILE DESCRIPTOR ( after perror translation )  which as you say, makes sense


same result with gobal int errno set to zero before call to socket

I am thinking that it is todo with openbsd security policy, its so goddam locked down that it makes sense im not allowed to modify kernel things such as the ip header, also am not allowed to bring down secure level past 1, it would seem that 1 is the default setting which also would make sense.

Im gonna re-write this on FreeBSD because Im not making any progress and time is dwindling away. You can have all the points sunny cause you put loads of effort into helping me ;)

Thanks Again

Chris  

 

by: sunnycoderPosted on 2003-08-31 at 07:37:09ID: 9257108

>>global int errno == BAD FILE DESCRIPTOR
now it does make some sense

if socket was successful and setsockopt failed with this error, then it most likely is security policy

if it turns out to be something else, let me know too :-) cuz I am feeling lost too

thanks for the points ...

 

by: crizzaPosted on 2003-09-01 at 08:01:32ID: 9261978

Hi Sunny.

I have found the solution to my problem.

To write and read raw TCP/UDP packets on FreeBSD and OpenBSD you have to use the bpf ( berkely packet filter ) which provides an interface to data link layers and has a builtin Filter to descriminate between packets.

If your not running *BSD then you can check out the manpage here:
http://www.openbsd.org/cgi-bin/man.cgi?query=bpf&apropos=0&sektion=0&manpath=OpenBSD+Current&arch=i386&format=html

Not quite the simple solution lol especially the Filter machine syntax :o

Cheers

Chris

 

by: sunnycoderPosted on 2003-09-02 at 07:31:26ID: 9267516

Thanks Chris... thats something new ... havent read the man page yet ( thanks for the link too ) but this definitely was not so simple ( for someone who does not know it )

Alas!
>>>>And ill put money on it that its something really simple. these things always are
>>lol ... thats somehow always true
no longer holds ;-)

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...