LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 10-26-2009, 05:41 PM   #1
bobble
LQ Newbie
 
Registered: Oct 2009
Posts: 8

Rep: Reputation: 0
Raw UDP Socket and ICMP Destination (Port) Unreachable


I'm using a single raw socket to read UDP packets from local test network with 1024 ports. Each UDP src and dest port is unique and I need access to IP and UDP header fields. I can stream and process data (in and out) at 100 mbps in linux-rt kernel with very low jitter < 250 usec, 10 usec nominal.

I'd like to prevent kernel from issuing ICMP port unreachable errors back to the sending host, however, I don't want to create 1024 vanilla UDP sockets and bind to each one because of resource constraints.

Currently, I'm using iptables to drop the outbound port unreachable messages. Does anyone know of a way (programmatic using C code) to prevent the ICMP unreachable traffic? Perhaps an IOCTL or socket option?

I also tried changing /proc/sys/net/ipv4/icmp_ratelimit but that seemed to have no effect.

By default the ratemask is set for dest unreachables and a variety of ratelimit values did not change any behavior that I could see.

Thanks very much!
 
Old 10-27-2009, 10:04 AM   #2
zhjim
Senior Member
 
Registered: Oct 2004
Distribution: Debian Squeeze x86_64
Posts: 1,467
Blog Entries: 11

Rep: Reputation: 184Reputation: 184
I don't know how to accomplish what your asking for but wonder why the ICMP message are send. I always payed close attention to ICMP message cause they are most vital for the network. So maybe it's better to search for the cause of the message instead of preventing them...

Something that puzzles me a bit is that your hunting the port unreachable packages but set the rate limit for dest unreachable...
 
Old 10-27-2009, 12:17 PM   #3
bobble
LQ Newbie
 
Registered: Oct 2009
Posts: 8

Original Poster
Rep: Reputation: 0
My RT kernel is sending the port unreachables to the peer who is sending him UDP packets. This is expected behavior becaues I have not bound 1024 ports to 1024 sockets on the receiving side. I am using a single raw socket. So when the peer starts sending me UDP packets, my kernel checks to see if there is a "formal" bind in place to a port number. If not, my kernel sends dest unreach/port unreach. Perfectly normal for default behavior and all UDP raw sockets on RX will exhibit this behavior if there is no formal UDP bind in place.

Regarding /proc/sys/net... my understanding is that the dest unreachable is icmp message type 3. The port is a code 3 in the dest unreachable message. In /proc/sys/net... the icmp dest unreach rate limit applies to outbound dest-unreachables regardless of code (I think).

So I am looking for a simple way to tell my kernel "do not send out dest-unreach/port messages for these ports when you receive UDP data on these ports". I don't want the extra the memory and management overhead required for 1024 sockets & binds just to stop a meaningless error to my peer on a private test network.

In summary, seems like there should be a simpler way to tell the kernel that these UDP ports are OK so don't complain to the peer that they aren't without resorting to 1024 sockets and 1024 binds.

Hope this clarifies things.
 
Old 07-05-2011, 11:52 AM   #4
mibo
LQ Newbie
 
Registered: Aug 2009
Posts: 21

Rep: Reputation: 1
Sorry, for "necroposting", but does anybody know an aswer to bobbles question?

I have the same problem with a kernel 2.6.34 Linux machine. On eth2 I receive UDP packets with a raw socket and my kernel generates a ICMP message "Type: 3 (Destination unreachable)". On eth0 I would like to keep the normal ICMP behavior.

Is using iptables really the only solution? (I find it not elegant to block a message that I would rather not generate in the first place).

Cheers,
mibo
 
Old 07-05-2011, 02:43 PM   #5
orgcandman
Member
 
Registered: May 2002
Location: dracut MA
Distribution: Ubuntu; PNE-LE; LFS (no book)
Posts: 594

Rep: Reputation: 102Reputation: 102
IPTables is the best 'catch-all' solution. Otherwise, you could bind to all those ports on your eth2 interface and set the recv buffers to 0.
 
Old 07-06-2011, 05:07 AM   #6
mibo
LQ Newbie
 
Registered: Aug 2009
Posts: 21

Rep: Reputation: 1
orgcandman, in my case, binding a socket to the port (I use just one) seems to be the simplest solution.
I tried to set the rcvbuf to 0 as you suggested, but it sets itself to 256 bytes. This is probably the lowest possible value.
What is the reason to set rcvbuf to 0? Just save memory?

Other than this, it seems to work fine (no more ICMP packets) - thank you.


Code:
  if ((dummy_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 
  {
    printf ("failed to create UDP socket (%s) \n", strerror(errno));
    exit (EXIT_FAILURE);
  }
  printf ("UDP socket created\n");
  // set the receive buffer size
  rc = getsockopt(dummy_sock, SOL_SOCKET, SO_RCVBUF, &receive_buffer, &opt_length);
  if (rc != 0) 
  {
     printf ("UDP socket: could not get SO_RCVBUF (%s)\n", strerror(errno));
     exit (EXIT_FAILURE);
  }
  printf ("before: UDP receive buffer = %d bytes\n", receive_buffer);

  receive_buffer = 0; 
  rc = setsockopt(dummy_sock, SOL_SOCKET, SO_RCVBUF, &receive_buffer,
                sizeof(receive_buffer));
  if (rc != 0) 
  {
     printf ("UDP socket: could not set SO_RCVBUF (%s)\n", strerror(errno));
     exit (EXIT_FAILURE);
  }
  rc = getsockopt(dummy_sock, SOL_SOCKET, SO_RCVBUF, &receive_buffer, &opt_length);
  if (rc != 0) 
  {
     printf ("UDP socket: could not get SO_RCVBUF (%s)\n", strerror(errno));
     exit (EXIT_FAILURE);
  }
  printf ("now: UDP receive buffer = %d bytes\n", receive_buffer);

  // bind my local (PC) port
  memset(&pc_addr_in, 0, sizeof(pc_addr_in));		// Clear struct
  pc_addr_in.sin_family = AF_INET;
  pc_addr_in.sin_addr.s_addr = inet_addr(PC_IP); 	// my IP address
  pc_addr_in.sin_port = htons(PC_PORT);
  rc = bind (dummy_sock, (struct sockaddr *) &pc_addr_in, sizeof(pc_addr_in));
  if (rc < 0) 
  {
     printf ("could not bind UDP socket to port (%s)\n", strerror(errno));
     exit (EXIT_FAILURE);
  }
  printf ("UDP socket bound to port\n");
 
  


Reply

Tags
icmp, raw, socket, udp


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
ICMP Destination Unreachable (Host administratively prohibited) jiml8 Linux - Networking 7 04-25-2013 05:07 AM
ICMP Port unreachable Ciralia Linux - Software 1 06-14-2007 11:20 AM
How to receive UDP and ICMP packets, by one UDP socket(PMTUD) myself_rajat Linux - Networking 0 05-28-2004 06:43 AM
UDP socket and ICMP messages myself_rajat Linux - Networking 0 05-25-2004 09:49 AM
Using Raw Socket for UDP myself_rajat Linux - Networking 0 05-17-2004 04:35 AM


All times are GMT -5. The time now is 08:11 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration