Solved

sendto gives error with PF_PACKET

Posted on 2001-07-18
9
4,199 Views
Last Modified: 2012-01-25
HI !!

I would like to send a raw packet over the network  -
Below is the code I have written -
When I do a strace - I see that the sendto call is sending to if0 for some reason - MY Lan card is eth0.
for the sockaddr_ll structure YOU CAN ONLY SPECIFY THE INTERFACE INDEX ----
AM I MISSING SOMEHING ???? Is this whats causing the error? i have attached the strace for the bind call too.

----------------------------------------------------------
 int sockfd, portno=4500, n;
  struct sockaddr_in serv_addr;
  struct hostent *server;
  struct sockaddr_ll link1, myaddr;
  struct sockaddr from, to;
 
  struct ifreq ifr;  
  char hwaddr[6]={0xb5,0x0e,0x50,0x96,0x40,0x00};
  unsigned char proto[2]={0x00, 0x03};
  unsigned char buffer[256];
  unsigned char *pkt;
  pkt = buffer;
 
  memset(buffer, 0 , sizeof(buffer));
  memset(&ifr,0,sizeof(ifr));
 
  memset(&myaddr, '\0' , sizeof(myaddr));
  myaddr.sll_family = AF_PACKET ;
  myaddr.sll_protocol = htons(ETH_P_ALL);
  myaddr.sll_ifindex = 0;

  from.sa_family=AF_PACKET;
  strcpy(from.sa_data,"eth0");
 
 
  memset(&from,0,sizeof(from));
  strcpy(ifr.ifr_name,"eth0");

  ifr.ifr_ifindex=0;
 

  sockfd = socket (PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL));
 
 
  printf(" Socket call returned %d \n", sockfd);
  printf(" ioctl returns %d ",ioctl(sockfd, SIOCGIWNAME, &ifr));
  printf(" Name is %s \n",&ifr.ifr_name);
 
  /****************************************************************
    Build sockaddr_ll here
  ***************************************************************/

  link1.sll_family=AF_PACKET;
  link1.sll_protocol=0x300;
  link1.sll_hatype=0xFFFF;
  link1.sll_pkttype=PACKET_OUTGOING;
  link1.sll_ifindex = 0 ;
  link1.sll_addr[0]=0xff;
  link1.sll_addr[1]=0xff;
  link1.sll_addr[2]=0xff;
  link1.sll_addr[3]=0xff;
  link1.sll_addr[4]=0xff;
  link1.sll_addr[5]=0xff;
  link1.sll_addr[6]=0x00;
  link1.sll_addr[7]=0x00;
 
  link1.sll_halen = 6;

  /***************************** Finished building sockaddr_11 */

  printf("Binding returns %d \n",bind(sockfd, &link1, sizeof(link1)));
 
 
 
  printf("\n\nEnter Data Message:");
 
  printf("Setting Destination MAC Address\n");
  memcpy(pkt, &hwaddr, 6);
  printf(" -Done \n");
  memcpy(pkt+6, &hwaddr, 6);
  memcpy(pkt+12, &proto ,2);
  printf(" Done protocol \n");
  memcpy(pkt+14, ".DATA.", sizeof(".DATA."));

 
  n=send(sockfd, &pkt,  sizeof(pkt), 0, (struct sockaddr *) &link1, 6 );
  printf(" Bytes Sent %d. Error Number %s\n ",n, strerror(errno));
 
----------------------------------------------------------
strace --bind

bind(3,{sin_family=AF_PACKET,proto=0x08, if0, pkttype=2, addr(6)={1,ffffffffffff}, 20) =0

//is successful though

sento() gives the error - No such device or Address?
PLLLLLLEASASSSEE HELLLLLP !!!!
I am DESPARATE -- have been going crazy over this
-
Thanks

Regards
  _  _
  \\//
 Sunny
  //\\
  -  -
0
Comment
Question by:sunny447492
  • 5
  • 2
9 Comments
 
LVL 5

Expert Comment

by:BlackDiamond
ID: 6309843
First of all, you need to be using a SOCK_RAW socket for this instead of a SOCK_DGRAM.  If you still have problems, take a look at the libnet libraries.  They Have nice wrapper functions and examples to do exactly what you are trying to do.  Layer 2 injection can get ugly very fast if you are not careful. :->
0
 

Author Comment

by:sunny447492
ID: 6313558
Hi BlackDiamond,

Thanks for replying ...
My app need to do exactly that - layer 2 injection for testing puposes.
I tried with SOCK_RAW - Then changed it to DGRAM - cause it works
but I never see any packet on the network with the analyzer -
when I send with PF_PACKET and sock_RAW - the transmit function od the device is never called - Is this a bug ?


Its' already gotten UGLY :)

Thanks

Regards

Sunny
0
 
LVL 5

Expert Comment

by:BlackDiamond
ID: 6314629
I'll include an example using the libnet library, as well as a copy of the functions that are used.  You should really get the libnet source and take a look.  It is fairly well written, and should provide some insight.  You can get a copy of it at http://sourceforge.net/projects/libnet ...

----  example -----
-------------------------
   char * OUTINTERFACE; // Normally eth0
   char * packetbuffer; // Need to fill this with eth header + ip header + tcp header + tcp options + data
   long packetbufferlength;
   char * err_buf; // libnet error buffer
   struct libnet_link_int * link_interface;

   OUTINTERFACE= *((char **)(SystemObject::getConfigReader()->getValue("OUTINTERFACE")));

   if((link_interface = libnet_open_link_interface(OUTINTERFACE,err_buf)) == NULL) {
        /*
       *  Throw a libnet error if the interface is not available.  Then
       *   throw a ConfigException to log and stop execution.
       */
        libnet_error(
            LIBNET_ERR_CRITICAL,                  /*  error type         */
            "libnet_open_link_interface: %s\n",   /*  description        */
            err_buf);                             /*  libnet error desc. */
      
      throw new ConfigException(
                      "PacketSender",
                      "PacketSender",
                      "Could not open outbound interface",
                      "Make sure the OUTINTERFACE configuration parameter is specified correctly");
    }
--------------------------
   /* Layer 2 inject */
   
   int writeresult;

   /* Write the packet to the network. */
   writeresult = libnet_write_link_layer(
                     link_interface,          /*  interface struct  */
                     OUTINTERFACE,            /*  interface name    */
                     packetbuffer,  /*  outbound buffer   */
                     packetbufferlength; /*  total send length */

---------------------------

--- The libnet functions ---

struct libnet_link_int *
libnet_open_link_interface(char *device, char *ebuf)
{
    register struct libnet_link_int *l;
    struct ifreq ifr;
#if (HAVE_PF_PACKET)
    struct packet_mreq mr;
#endif

    l = (struct libnet_link_int *)malloc(sizeof (*l));
    if (l == NULL)
    {
        sprintf(ebuf, "malloc: %s", ll_strerror(errno));
        return (NULL);
    }
    memset(l, 0, sizeof (*l));

#if (HAVE_PF_PACKET)
    l->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
#else
    l->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
#endif
    if (l->fd == -1)
    {
        sprintf(ebuf, "socket: %s", ll_strerror(errno));
        goto bad;
    }

#if (HAVE_PF_PACKET)
    memset(&mr, 0, sizeof(mr));
    mr.mr_ifindex = get_iface_index (l->fd, device);
    if (mr.mr_ifindex == -1)
    {
        sprintf(ebuf, "SIOCGIFINDEX %s: %s", device, ll_strerror(errno));
        goto bad;
    }
    mr.mr_type = PACKET_MR_ALLMULTI;

    if (setsockopt(l->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (char *)&mr,
        sizeof (mr)) < 0)
    {
        sprintf(ebuf, "setsockopt %s: %s", device, ll_strerror(errno));
        goto bad;
    }
#endif

    memset(&ifr, 0, sizeof (ifr));
    strncpy(ifr.ifr_name, device, sizeof (ifr.ifr_name));
    if (ioctl(l->fd, SIOCGIFHWADDR, &ifr) < 0 )
    {
        sprintf(ebuf, "SIOCGIFHWADDR: %s", ll_strerror(errno));
        goto bad;
    }

    switch (ifr.ifr_hwaddr.sa_family)
    {
        case ARPHRD_ETHER:
        case ARPHRD_METRICOM:
#ifdef ARPHRD_LOOPBACK
        case ARPHRD_LOOPBACK:  
#endif
            l->linktype = DLT_EN10MB;
            l->linkoffset = 0xe;
            break;
        case ARPHRD_SLIP:
        case ARPHRD_CSLIP:
        case ARPHRD_SLIP6:
        case ARPHRD_CSLIP6:
        case ARPHRD_PPP:
            l->linktype = DLT_RAW;
            break;
        default:
            sprintf(ebuf, "unknown physical layer type 0x%x",
                ifr.ifr_hwaddr.sa_family);
        goto bad;
    }
    return (l);

bad:
    if (l->fd >= 0)
    {
        close(l->fd);
    }
    free(l);
    return (NULL);
}

int
libnet_write_link_layer(struct libnet_link_int *l, const char *device,
            u_char *buf, int len)
{
    int c;
#if (HAVE_PF_PACKET)
    struct sockaddr_ll sa;
#else
    struct sockaddr sa;
#endif

    memset(&sa, 0, sizeof (sa));
#if (HAVE_PF_PACKET)  
    sa.sll_family    = AF_PACKET;
    sa.sll_ifindex   = get_iface_index(l->fd, device);
    if (sa.sll_ifindex == -1)
    {
        return (-1);
    }
    sa.sll_protocol  = htons(ETH_P_ALL);
#else
    strncpy(sa.sa_data, device, sizeof (sa.sa_data));
#endif

    c = sendto(l->fd, buf, len, 0, (struct sockaddr *)&sa, sizeof (sa));
    if (c != len)
    {
#if (__DEBUG)
        libnet_error(LIBNET_ERR_WARNING,
            "write_link_layer: %d bytes written (%s)\n", c,
            strerror(errno));
#endif
    }
    return (c);
}
0
 
LVL 5

Expert Comment

by:BlackDiamond
ID: 6314645
And by the way, if you don't see you packet hit the wire when you are using a RAW socket, it means that either :

1. Your ethernet header (the first 12 bytes of your buffer) is not formatted correctly, or is invalid.

or

2. Your total packet length is not specified correctly.
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 5

Accepted Solution

by:
BlackDiamond earned 200 total points
ID: 6315186
OK, I looked at your original code again.  First, you absolutely need to use SOCK_RAW.  I added some comments to the code below which might help.  There are a number of issues here that will cause your problems.  I commented the lines that are not valid, and tried to enter something appropriate...

-------
/* 0x03 is not a valid protocol.  This identifier is used with a socket to effectively put it in promiscuous mode.  Remember, this is still for the layer 2 stuff. */
//unsigned char proto[2]={0x00, 0x03};
/* Use something like 0x0800 for IP protocol instead */
unsigned char proto[2]={0x08, 0x00};

-------

printf("Setting Destination MAC Address\n");
/* This needs to be set to the destination MAC */
//memcpy(pkt, &hwaddr, 6);
memcpy(pkt, link1.sll_addr, 6);

printf(" -Done \n");
/* This is your source mac.  hwaddr is already a pointer    */
//memcpy(pkt+6, &hwaddr, 6);
memcpy(pkt+6, hwaddr, 6);
memcpy(pkt+12, &proto ,2);
printf(" Done protocol \n");

/* OK, now layer 3 stuff.  Here is where you need to insert an IP header (which you need to build.  Don't forget to checksum it too, which is another useful functoin of a library like libnet :->*/
memcpy(pkt+14, myIPHeader, 20);
/*You  would then have a TCP or UDP or whatever header here */
memcpy(pkt+34, myTCPHeader, 20);
/* Then your data */
memcpy(pkt+54, ".DATA.", sizeof(".DATA."));

/* You would normally go back and update your checksums here */
...

/* Then put the packet on the wire.  Be careful when using sizeof on a malloc'd chunk of memory.  It is likely to always return 4 (the size of your pointer space).. Instead keep a seperate variable with the size of all your data, and use it here */
//n=send(sockfd, &pkt,  sizeof(pkt), 0, (struct sockaddr *) &link1, 6 );

n=sendto(sockfd, pkt, 14+20+20+sizeof(".DATA."), 0, (struct sockaddr *) &link1, sizeof(struct sockaddr));

/* That should be it...... */
0
 

Author Comment

by:sunny447492
ID: 6315396
Hi BlackDiamond

Thanks again for the great examples - I will try them out -I am aware of sending it in such a fashion though -

My aim is NOT to send TCP/IP packets but raw packets as I am communicating with another device - which doesnt understand higher layer protocols -

Therefore I wanted to use SOCK_RAW - and 0x0030 - Thats actually correct - Its in network byte order for .. unknown protocol I thinnk ... I had checked in the appropriate header files...

I am already able to ssend packets as demonstrated above
I want to send a packet with only an ethernet header - It should be transmitted  -  But It is not - I am sure - It does not even reach the driver transmit function.

My objective is to avoid the Kernel IP/TCP encapsulation as the device I am testing for is not able to  process these layers

Thanks!

Regards

Sunny
0
 
LVL 5

Expert Comment

by:BlackDiamond
ID: 6317885
Keep in mind that the Protocol code specified in the ethernet header is a specifier for the layer 3 protocol that will be used in the rest of the packet.  In your case, if you are doing the parsing at both ends, it "shouldn't" matter what is specified in that protocol field, but I would be careful anyway.  If you're curious what the valid protocol codes are, you can find them here :
http://www.cavebear.com/CaveBear/Ethernet/type.html
0
 
LVL 20

Expert Comment

by:jmcg
ID: 9871652
No comment has been added lately, so it's time to clean up this TA.
I will leave the following recommendation for this question in the Cleanup topic area:

Accept: BlackDiamond {http:#6315186}

Please leave any comments here within the next seven days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

jmcg
EE Cleanup Volunteer
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Have you ever been frustrated by having to click seven times in order to retrieve a small bit of information from the web, always the same seven clicks, scrolling down and down until you reach your target? When you know the benefits of the command l…
The purpose of this article is to demonstrate how we can upgrade Python from version 2.7.6 to Python 2.7.10 on the Linux Mint operating system. I am using an Oracle Virtual Box where I have installed Linux Mint operating system version 17.2. Once yo…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now