Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

sendto gives error with PF_PACKET

Posted on 2001-07-18
9
Medium Priority
?
4,732 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

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

Accepted Solution

by:
BlackDiamond earned 800 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

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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 fix the unknown display problem in Linux Mint operating system. After installing the OS if you see Display monitor is not recognized then we can install "MESA" utilities to fix this problem or we can install additio…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…

664 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