diff --git a/src/core/raw.c b/src/core/raw.c index 1729fc7d..4828df6f 100644 --- a/src/core/raw.c +++ b/src/core/raw.c @@ -287,11 +287,9 @@ raw_recv(struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg) /** * @ingroup raw_raw - * Send the raw IP packet to the given address. Note that actually you cannot - * modify the IP headers (this is inconsistent with the receive callback where - * you actually get the IP headers), you can only specify the IP payload here. - * It requires some more changes in lwIP. (there will be a raw_send() function - * then.) + * Send the raw IP packet to the given address. An IP header will be prepended + * to the packet, unless the RAW_FLAGS_HDRINCL flag is set on the PCB. In that + * case, the packet must include an IP header, which will then be sent as is. * * @param pcb the raw pcb which to send * @param p the IP payload to send @@ -342,7 +340,9 @@ raw_sendto(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *ipaddr) /** * @ingroup raw_raw * Send the raw IP packet to the given address, using a particular outgoing - * netif and source IP address. An IP header will be prepended to the packet. + * netif and source IP address. An IP header will be prepended to the packet, + * unless the RAW_FLAGS_HDRINCL flag is set on the PCB. In that case, the + * packet must include an IP header, which will then be sent as is. * * @param pcb RAW PCB used to send the data * @param p chain of pbufs to be sent @@ -372,6 +372,20 @@ raw_sendto_if_src(struct raw_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, IP6_HLEN); #endif + /* Handle the HDRINCL option as an exception: none of the code below applies + * to this case, and sending the packet needs to be done differently too. */ + if (pcb->flags & RAW_FLAGS_HDRINCL) { + /* A full header *must* be present in the first pbuf of the chain, as the + * output routines may access its fields directly. */ + if (p->len < header_size) { + return ERR_VAL; + } + NETIF_SET_HWADDRHINT(netif, &pcb->addr_hint); + err = ip_output_if_hdrincl(p, src_ip, dst_ip, netif); + NETIF_SET_HWADDRHINT(netif, NULL); + return err; + } + /* not enough space to add an IP header to first pbuf in given p chain? */ if (pbuf_header(p, header_size)) { /* allocate header in new pbuf */ diff --git a/src/include/lwip/ip.h b/src/include/lwip/ip.h index 0673be9b..f104917c 100644 --- a/src/include/lwip/ip.h +++ b/src/include/lwip/ip.h @@ -243,6 +243,11 @@ extern struct ip_globals ip_data; (IP_IS_V6(dest) ? \ ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ ip4_output_if_src(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) +/** Output IP packet that already includes an IP header. */ +#define ip_output_if_hdrincl(p, src, dest, netif) \ + (IP_IS_V6(dest) ? \ + ip6_output_if(p, ip_2_ip6(src), LWIP_IP_HDRINCL, 0, 0, 0, netif) : \ + ip4_output_if(p, ip_2_ip4(src), LWIP_IP_HDRINCL, 0, 0, 0, netif)) /** Output IP packet with addr_hint */ #define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ (IP_IS_V6(dest) ? \ @@ -277,6 +282,8 @@ err_t ip_input(struct pbuf *p, struct netif *inp); ip4_output_if_src(p, src, dest, ttl, tos, proto, netif) #define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ ip4_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) +#define ip_output_if_hdrincl(p, src, dest, netif) \ + ip4_output_if(p, src, LWIP_IP_HDRINCL, 0, 0, 0, netif) #define ip_route(src, dest) \ ip4_route_src(dest, src) #define ip_netif_get_local_ip(netif, dest) \ @@ -295,6 +302,8 @@ err_t ip_input(struct pbuf *p, struct netif *inp); ip6_output_if_src(p, src, dest, ttl, tos, proto, netif) #define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ ip6_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) +#define ip_output_if_hdrincl(p, src, dest, netif) \ + ip6_output_if(p, src, LWIP_IP_HDRINCL, 0, 0, 0, netif) #define ip_route(src, dest) \ ip6_route(src, dest) #define ip_netif_get_local_ip(netif, dest) \ diff --git a/src/include/lwip/raw.h b/src/include/lwip/raw.h index c5a3b21b..644ba1a8 100644 --- a/src/include/lwip/raw.h +++ b/src/include/lwip/raw.h @@ -53,6 +53,7 @@ extern "C" { #endif #define RAW_FLAGS_CONNECTED 0x01U +#define RAW_FLAGS_HDRINCL 0x02U struct raw_pcb; @@ -106,6 +107,7 @@ err_t raw_send (struct raw_pcb *pcb, struct pbuf *p); void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); #define raw_flags(pcb) ((pcb)->flags) +#define raw_setflags(pcb,f) ((pcb)->flags = (f)) /* The following functions are the lower layer interface to RAW. */ u8_t raw_input (struct pbuf *p, struct netif *inp);