]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/lwip/lib/contrib/src/core/raw.c
Update
[l4.git] / l4 / pkg / lwip / lib / contrib / src / core / raw.c
index 2adc8a9649e72468542be52f15a345013bfbdc02..b61b57cb6cac4992d406c0b5fc78e013e125816f 100644 (file)
@@ -48,9 +48,9 @@
 #include "lwip/netif.h"
 #include "lwip/raw.h"
 #include "lwip/stats.h"
-#include "arch/perf.h"
 #include "lwip/ip6.h"
 #include "lwip/ip6_addr.h"
+#include "lwip/inet_chksum.h"
 
 #include <string.h>
 
@@ -78,27 +78,28 @@ u8_t
 raw_input(struct pbuf *p, struct netif *inp)
 {
   struct raw_pcb *pcb, *prev;
-  struct ip_hdr *iphdr;
   s16_t proto;
   u8_t eaten = 0;
-#if LWIP_IPV6
-  struct ip6_hdr *ip6hdr;
-#endif /* LWIP_IPV6 */
-
 
   LWIP_UNUSED_ARG(inp);
 
-  iphdr = (struct ip_hdr *)p->payload;
 #if LWIP_IPV6
-  if (IPH_V(iphdr) == 6) {
-    ip6hdr = (struct ip6_hdr *)p->payload;
+#if LWIP_IPV4
+  if (IP_HDR_GET_VERSION(p->payload) == 6)
+#endif /* LWIP_IPV4 */
+  {
+    struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload;
     proto = IP6H_NEXTH(ip6hdr);
   }
+#if LWIP_IPV4
   else
+#endif /* LWIP_IPV4 */
 #endif /* LWIP_IPV6 */
+#if LWIP_IPV4
   {
-    proto = IPH_PROTO(iphdr);
+    proto = IPH_PROTO((struct ip_hdr *)p->payload);
   }
+#endif /* LWIP_IPV4 */
 
   prev = NULL;
   pcb = raw_pcbs;
@@ -106,21 +107,24 @@ raw_input(struct pbuf *p, struct netif *inp)
   /* this allows multiple pcbs to match against the packet by design */
   while ((eaten == 0) && (pcb != NULL)) {
     if ((pcb->protocol == proto) && IP_PCB_IPVER_INPUT_MATCH(pcb) &&
-        (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip) ||
-         ipX_addr_cmp(PCB_ISIPV6(pcb), &(pcb->local_ip), ipX_current_dest_addr()))) {
+        (ip_addr_isany(&pcb->local_ip) ||
+         ip_addr_cmp(&pcb->local_ip, ip_current_dest_addr()))) {
 #if IP_SOF_BROADCAST_RECV
       /* broadcast filter? */
-      if (((pcb->so_options & SOF_BROADCAST) || !ip_addr_isbroadcast(ip_current_dest_addr(), inp))
+      if ((ip_get_option(pcb, SOF_BROADCAST) || !ip_addr_isbroadcast(ip_current_dest_addr(), ip_current_netif()))
 #if LWIP_IPV6
-          && !PCB_ISIPV6(pcb)
+          || PCB_ISIPV6(pcb)
 #endif /* LWIP_IPV6 */
           )
 #endif /* IP_SOF_BROADCAST_RECV */
       {
         /* receive callback function available? */
-        if (pcb->recv.ip4 != NULL) {
+        if (pcb->recv != NULL) {
+#ifndef LWIP_NOASSERT
+          void* old_payload = p->payload;
+#endif
           /* the receive callback function did not eat the packet? */
-          eaten = pcb->recv.ip4(pcb->recv_arg, pcb, p, ip_current_src_addr());
+          eaten = pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr());
           if (eaten != 0) {
             /* receive function ate the packet */
             p = NULL;
@@ -132,6 +136,10 @@ raw_input(struct pbuf *p, struct netif *inp)
               pcb->next = raw_pcbs;
               raw_pcbs = pcb;
             }
+          } else {
+            /* sanity-check that the receive callback did not alter the pbuf */
+            LWIP_ASSERT("raw pcb recv callback altered pbuf payload pointer without eating packet",
+              p->payload == old_payload);
           }
         }
         /* no receive callback function was set for this raw PCB */
@@ -152,16 +160,19 @@ raw_input(struct pbuf *p, struct netif *inp)
  * bind to all local interfaces.
  *
  * @return lwIP error code.
- * - ERR_OK. Successful. No error occured.
+ * - ERR_OK. Successful. No error occurred.
  * - ERR_USE. The specified IP address is already bound to by
  * another RAW PCB.
  *
  * @see raw_disconnect()
  */
 err_t
-raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr)
+raw_bind(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
 {
-  ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->local_ip, ipaddr);
+  if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
+    return ERR_VAL;
+  }
+  ip_addr_set_ipaddr(&pcb->local_ip, ipaddr);
   return ERR_OK;
 }
 
@@ -179,23 +190,25 @@ raw_bind(struct raw_pcb *pcb, ip_addr_t *ipaddr)
  * @see raw_disconnect() and raw_sendto()
  */
 err_t
-raw_connect(struct raw_pcb *pcb, ip_addr_t *ipaddr)
+raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr)
 {
-  ipX_addr_set_ipaddr(PCB_ISIPV6(pcb), &pcb->remote_ip, ipaddr);
+  if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
+    return ERR_VAL;
+  }
+  ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr);
   return ERR_OK;
 }
 
-
 /**
  * Set the callback function for received packets that match the
- * raw PCB's protocol and binding. 
- * 
+ * raw PCB's protocol and binding.
+ *
  * The callback function MUST either
  * - eat the packet by calling pbuf_free() and returning non-zero. The
  *   packet will not be passed to other raw PCBs or other protocol layers.
  * - not free the packet, and return zero. The packet will be matched
  *   against further PCBs and/or forwarded to another protocol layers.
- * 
+ *
  * @return non-zero if the packet was free()d, zero if the packet remains
  * available for others.
  */
@@ -203,7 +216,7 @@ void
 raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)
 {
   /* remember recv() callback and user data */
-  pcb->recv.ip4 = recv;
+  pcb->recv = recv;
   pcb->recv_arg = recv_arg;
 }
 
@@ -220,22 +233,29 @@ raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg)
  *
  */
 err_t
-raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
+raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr)
 {
   err_t err;
   struct netif *netif;
-  ipX_addr_t *src_ip;
+  const ip_addr_t *src_ip;
   struct pbuf *q; /* q will be sent down the stack */
   s16_t header_size;
-  ipX_addr_t *dst_ip = ip_2_ipX(ipaddr);
+  const ip_addr_t *dst_ip = ipaddr;
+
+  if ((pcb == NULL) || (ipaddr == NULL) || !IP_ADDR_PCB_VERSION_MATCH(pcb, ipaddr)) {
+    return ERR_VAL;
+  }
 
   LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_sendto\n"));
 
   header_size = (
-#if LWIP_IPV6
-    PCB_ISIPV6(pcb) ? IP6_HLEN :
-#endif /* LWIP_IPV6 */
+#if LWIP_IPV4 && LWIP_IPV6
+    PCB_ISIPV6(pcb) ? IP6_HLEN : IP_HLEN);
+#elif LWIP_IPV4
     IP_HLEN);
+#else
+    IP6_HLEN);
+#endif
 
   /* not enough space to add an IP header to first pbuf in given p chain? */
   if (pbuf_header(p, header_size)) {
@@ -252,19 +272,19 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
     }
     /* { first pbuf q points to header pbuf } */
     LWIP_DEBUGF(RAW_DEBUG, ("raw_sendto: added header pbuf %p before given pbuf %p\n", (void *)q, (void *)p));
-  }  else {
+  } else {
     /* first pbuf q equals given pbuf */
     q = p;
-    if(pbuf_header(q, -header_size)) {
+    if (pbuf_header(q, -header_size)) {
       LWIP_ASSERT("Can't restore header we just removed!", 0);
       return ERR_MEM;
     }
   }
 
-  netif = ipX_route(PCB_ISIPV6(pcb), &pcb->local_ip, dst_ip);
+  netif = ip_route(PCB_ISIPV6(pcb), &pcb->local_ip, dst_ip);
   if (netif == NULL) {
     LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: No route to "));
-    ipX_addr_debug_print(PCB_ISIPV6(pcb), RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, dst_ip);
+    ip_addr_debug_print(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, dst_ip);
     /* free any temporary header pbuf allocated by pbuf_header() */
     if (q != p) {
       pbuf_free(q);
@@ -274,12 +294,11 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
 
 #if IP_SOF_BROADCAST
 #if LWIP_IPV6
-  /* @todo: why does IPv6 not filter broadcast with SOF_BROADCAST enabled? */
   if (!PCB_ISIPV6(pcb))
 #endif /* LWIP_IPV6 */
   {
     /* broadcast filter? */
-    if (((pcb->so_options & SOF_BROADCAST) == 0) && ip_addr_isbroadcast(ipaddr, netif)) {
+    if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) {
       LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_LEVEL_WARNING, ("raw_sendto: SOF_BROADCAST not enabled on pcb %p\n", (void *)pcb));
       /* free any temporary header pbuf allocated by pbuf_header() */
       if (q != p) {
@@ -290,9 +309,9 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
   }
 #endif /* IP_SOF_BROADCAST */
 
-  if (ipX_addr_isany(PCB_ISIPV6(pcb), &pcb->local_ip)) {
+  if (ip_addr_isany(&pcb->local_ip)) {
     /* use outgoing network interface IP address as source address */
-    src_ip = ipX_netif_get_local_ipX(PCB_ISIPV6(pcb), netif, dst_ip);
+    src_ip = ip_netif_get_local_ip(PCB_ISIPV6(pcb), netif, dst_ip);
 #if LWIP_IPV6
     if (src_ip == NULL) {
       if (q != p) {
@@ -306,8 +325,18 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
     src_ip = &pcb->local_ip;
   }
 
+#if LWIP_IPV6
+  /* If requested, based on the IPV6_CHECKSUM socket option per RFC3542,
+     compute the checksum and update the checksum in the payload. */
+  if (PCB_ISIPV6(pcb) && pcb->chksum_reqd) {
+    u16_t chksum = ip6_chksum_pseudo(p, pcb->protocol, p->tot_len, ip_2_ip6(src_ip), ip_2_ip6(dst_ip));
+    LWIP_ASSERT("Checksum must fit into first pbuf", p->len >= (pcb->chksum_offset + 2));
+    SMEMCPY(((u8_t *)p->payload) + pcb->chksum_offset, &chksum, sizeof(u16_t));
+  }
+#endif
+
   NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint);
-  err = ipX_output_if(PCB_ISIPV6(pcb), q, ipX_2_ip(src_ip), ipX_2_ip(dst_ip), pcb->ttl, pcb->tos, pcb->protocol, netif);
+  err = ip_output_if(PCB_ISIPV6(pcb), q, src_ip, dst_ip, pcb->ttl, pcb->tos, pcb->protocol, netif);
   NETIF_SET_HWADDRHINT(netif, NULL);
 
   /* did we chain a header earlier? */
@@ -328,7 +357,7 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, ip_addr_t *ipaddr)
 err_t
 raw_send(struct raw_pcb *pcb, struct pbuf *p)
 {
-  return raw_sendto(pcb, p, ipX_2_ip(&pcb->remote_ip));
+  return raw_sendto(pcb, p, &pcb->remote_ip);
 }
 
 /**
@@ -349,7 +378,7 @@ raw_remove(struct raw_pcb *pcb)
     raw_pcbs = raw_pcbs->next;
     /* pcb not 1st in list */
   } else {
-    for(pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
+    for (pcb2 = raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) {
       /* find pcb in raw_pcbs list */
       if (pcb2->next != NULL && pcb2->next == pcb) {
         /* remove pcb from list */
@@ -407,7 +436,9 @@ raw_new_ip6(u8_t proto)
 {
   struct raw_pcb *pcb;
   pcb = raw_new(proto);
+#if LWIP_IPV4
   ip_set_v6(pcb, 1);
+#endif /* LWIP_IPV4 */
   return pcb;
 }
 #endif /* LWIP_IPV6 */