Thread: sending raw packets in loop

  1. #1
    Registered User
    Join Date
    Oct 2010
    Posts
    11

    sending raw packets in loop

    I would like to send ethernet packets in a loop and then receive the reply packet (if any). Here the short version of the code (hope its understandable enough):

    Code:
    for (int i=0; i<someValue; i++) {
        // Submit request for a raw socket descriptor.
        if ((sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
            perror ("socket() failed ");
            exit (EXIT_FAILURE);
        }
    
        struct timeval tv;
        tv.tv_sec = 0;
        tv.tv_usec = 1000;
        if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
            perror("Error");
        }
    
        char packet[1024];
        int bytes;
        // Send ethernet frame to socket.
         if ((bytes = sendto (sock_fd, ether_frame, packet_length, 0, (struct sockaddr *) &device, sizeof (device))) <= 0) {
             perror ("sendto() failed");
             exit (EXIT_FAILURE);
         } else {
    
            if ((bytes = recv(sock_fd, packet, sizeof(packet), 0)) <= 0) {
                printf("ERROR READ\n");
                exit(1);
            }
    
                //Do something with the received packet...
         }
    }
    When I omit the setting of the timeout setsocket(...) everything works fine so there must be something wrong with that but I can't figure out what??

    P.S. Is there probably a better way to send those packets as the way I'm doing it?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Well you shouldn't be making lots of socket() calls inside the loop - you'll run out of descriptors.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Oct 2010
    Posts
    11
    Alright, but if I omit the loop and simply send only one packet, when calling the recv(...)
    Code:
    if ((bytes = recv(sock_fd, packet, sizeof(packet), 0)) <= 0) {
    			printf("ERROR READ\n");
    			exit(1);
    }
    it still gives me "ERROR READ"??

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You might be more enlightened if you called perror() instead to find out why it failed.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Oct 2010
    Posts
    11
    Ok now I get the additional info:
    Code:
    Resource temporarily unavailable

  6. #6
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    First, you only need to create one socket. So, start with
    Code:
        sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
        if (sock_fd == -1) {
            perror("socket() failed");
            exit(EXIT_FAILURE);
        } 
    
        struct timeval tv;
        tv.tv_sec = 0;
        tv.tv_usec = 1000;
        if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1)
            perror("Warning: Cannot set socket receive timeout");
    Then, you can do the loop.
    Code:
        for (int i=0; i<someValue; i++) {
            ssize_t bytes;
    
            // Send ethernet frame to socket.
            bytes = sendto(sock_fd, ether_frame, packet_length, 0, (struct sockaddr *) &device, sizeof (device));
            if (bytes != packet_length) {
                if (bytes == (ssize_t)-1)
                    perror("sendto() failed");
                else
                    fprintf(stderr, "sendto() only sent %d of %d bytes!\n", (int)bytes, (int)packet_length);
                exit(EXIT_FAILURE);
            }
    
            bytes = recv(sock_fd, packet, sizeof packet, 0);
            if (bytes == (ssize_t)-1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
                fprintf(stderr, "No packet yet.\n");
                continue;
            }
            if (bytes == (ssize_t)-1 && errno == EINTR) {
                fprintf(stderr, "No packet yet; interrupted by a signal.\n");
                continue;
            }
            if (bytes == (ssize_t)-1) {
                perror("recv() failed");
                exit(EXIT_FAILURE);
            }
    
            //Do something with the received packet...
    
         }
    Quote Originally Posted by Freaky256 View Post
    When I omit the setting of the timeout setsocket(...) everything works fine so there must be something wrong with that but I can't figure out what??
    You get -1 and errno==EAGAIN (or errno==EWOULDBLOCK), because you have set a timeout of one millisecond, and it elapses before a packet arrives.

    May I suggest you set a higher timeout than 1ms? 1000 µs = 1 ms = 0.000001 second. The valid range for .tv_usec is between 0 and 999999, i.e. zero and just under one million. (Don't exceed 999999, either; put full seconds in .tv_sec.)

  7. #7
    Registered User
    Join Date
    Oct 2010
    Posts
    11
    Quote Originally Posted by Nominal Animal View Post
    You get -1 and errno==EAGAIN (or errno==EWOULDBLOCK), because you have set a timeout of one millisecond, and it elapses before a packet arrives.
    Does that mean every time when the timeout elapses before I receive a packet I get an error? Because than it would not make any difference to increase the timeout because I'm not even sure I will receive a reply (thats because I need the timeout). If I increase the timeout and don't receive a packet anyway I still get the error is that correct?

  8. #8
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by Freaky256 View Post
    Does that mean every time when the timeout elapses before I receive a packet I get an error? Because than it would not make any difference to increase the timeout because I'm not even sure I will receive a reply (thats because I need the timeout). If I increase the timeout and don't receive a packet anyway I still get the error is that correct?
    These questions could be answered by reading the documentation, which you really ought to do. Yes, you will still get an error if you increase the timeout and no data arrives before the timeout expires. Whether or not it "makes a difference" depends on your situation. Are you communicating with some system halfway around the world? Better increase the timeout to allow for the latency of your packets going on their world tour. If it's going to another computer one or two hops away on your 100MB LAN, then a few seconds should be sufficient, unless the other end has to do a lot of processing before replying. If you pick a reasonable timeout value to begin with, you are more likely to get an actual reply before you get your EAGAIN/EWOULDBLOCK error, and you could treat getting that error as the other end simply failing to reply. The timeout should be the maximum amount of time you will wait before your program considers the other side to have not responded. If data arrives early, recv will return early, so nothing is lost.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Sending ARP packets
    By Poincare in forum C Programming
    Replies: 5
    Last Post: 07-15-2009, 09:02 AM
  2. Sending requests with packets
    By joeprogrammer in forum Networking/Device Communication
    Replies: 14
    Last Post: 05-21-2006, 07:33 PM
  3. Sending Raw Packets?
    By Coder87C in forum Networking/Device Communication
    Replies: 7
    Last Post: 12-03-2003, 01:27 PM
  4. Sending data packets
    By neandrake in forum Networking/Device Communication
    Replies: 6
    Last Post: 11-26-2003, 01:41 PM
  5. Sending raw packets.
    By Denethor2000 in forum C++ Programming
    Replies: 3
    Last Post: 06-04-2002, 02:08 PM

Tags for this Thread