]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lwip.git/commitdiff
Added new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast packets...
authorgoldsimon <goldsimon>
Sat, 15 May 2010 14:52:39 +0000 (14:52 +0000)
committergoldsimon <goldsimon>
Sat, 15 May 2010 14:52:39 +0000 (14:52 +0000)
CHANGELOG
src/core/udp.c
src/include/lwip/opt.h

index fe3458e4fb4c047ea88fe2c10a88c0e1c6a9ca8f..d6e2a2c1de669282a8a58b774fd84e3675091ccb 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -14,7 +14,9 @@ HISTORY
   ++ New features:
 
   2010-05-13: Simon Goldschmidt
-  * tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly)
+  * tcp.c, udp.c: task #6995: Implement SO_REUSEADDR (correctly), added
+    new option SO_REUSE_RXTOALL to pass received UDP broadcast/multicast
+    packets to more than one pcb.
 
   2010-05-02: Simon Goldschmidt
   * netbuf.h/.c, sockets.c, api_msg.c: use checksum-on-copy for sending
index 954e1c19e817d6db36e5d5aa6ee1a0a14042b45e..7b5d04923c74ab406af16c3ea37fc1e91eec92a3 100644 (file)
@@ -276,6 +276,48 @@ udp_input(struct pbuf *p, struct netif *inp)
     }
     if (pcb != NULL) {
       snmp_inc_udpindatagrams();
+#if SO_REUSE_RXTOALL
+      if ((broadcast || ip_addr_ismulticast(&iphdr->dest)) &&
+          ((pcb->so_options & SOF_REUSEADDR) != 0)) {
+        /* pass broadcast- or multicast packets to all multicast pcbs
+           if SOF_REUSEADDR is set on the first match */
+        struct udp_pcb *mpcb;
+        /* for that, move payload to IP header again */
+        pbuf_header(p, (s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
+        for (mpcb = udp_pcbs; mpcb != NULL; mpcb = mpcb->next) {
+          if (mpcb != pcb) {
+            /* compare PCB local addr+port to UDP destination addr+port */
+            if ((mpcb->local_port == dest) &&
+                ((!broadcast && ip_addr_isany(&mpcb->local_ip)) ||
+                 ip_addr_cmp(&(mpcb->local_ip), &(iphdr->dest)) ||
+#if LWIP_IGMP
+                 ip_addr_ismulticast(&(iphdr->dest)) ||
+#endif /* LWIP_IGMP */
+#if IP_SOF_BROADCAST_RECV
+                 (broadcast && (mpcb->so_options & SOF_BROADCAST)))) {
+#else  /* IP_SOF_BROADCAST_RECV */
+                 (broadcast))) {
+#endif /* IP_SOF_BROADCAST_RECV */
+              /* pass a copy of the packet to all local matches */
+              if (mpcb->recv != NULL) {
+                struct pbuf *q = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
+                if (q != NULL) {
+                  err_t err = pbuf_copy(q, p);
+                  if (err == ERR_OK) {
+                    /* move payload to UDP data */
+                    struct ip_hdr *q_iphdr = (struct ip_hdr *)q->payload;
+                    pbuf_header(q, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
+                    mpcb->recv(mpcb->recv_arg, mpcb, q, &q_iphdr->src, src);
+                  }
+                }
+              }
+            }
+          }
+        }
+        /* and move payload to UDP data again */
+        pbuf_header(p, -(s16_t)((IPH_HL(iphdr) * 4) + UDP_HLEN));
+      }
+#endif /* SO_REUSE_RXTOALL */
       /* callback */
       if (pcb->recv != NULL) {
         /* now the recv function is responsible for freeing p */
index 81d98970537e221a9ed582ed8cbf08da9a3883d5..1aa2c40068ba41d3a5773fcc113e9d20214e11d1 100644 (file)
 #endif
 
 /**
- * SO_REUSE==1: Enable SO_REUSEADDR and SO_REUSEPORT options. DO NOT USE!
+ * SO_REUSE==1: Enable SO_REUSEADDR option.
  */
 #ifndef SO_REUSE
 #define SO_REUSE                        0
 #endif
 
+/**
+ * SO_REUSE_RXTOALL==1: Pass a copy of incoming broadcast/multicast packets
+ * to all local matches if SO_REUSEADDR is turned on.
+ * WARNING: Adds a memcpy for every packet if passing to more than one pcb!
+ */
+#ifndef SO_REUSE_RXTOALL
+#define SO_REUSE_RXTOALL                0
+#endif
+
 /*
    ----------------------------------------
    ---------- Statistics options ----------