1/** 2 * @file 3 * IP API 4 */ 5 6/* 7 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without modification, 11 * are permitted provided that the following conditions are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright notice, 14 * this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 24 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 30 * OF SUCH DAMAGE. 31 * 32 * This file is part of the lwIP TCP/IP stack. 33 * 34 * Author: Adam Dunkels <adam@sics.se> 35 * 36 */ 37#ifndef LWIP_HDR_IP_H 38#define LWIP_HDR_IP_H 39 40#include "lwip/opt.h" 41 42#include "lwip/def.h" 43#include "lwip/pbuf.h" 44#include "lwip/ip_addr.h" 45#include "lwip/err.h" 46#include "lwip/netif.h" 47#include "lwip/ip4.h" 48#include "lwip/ip6.h" 49#include "lwip/prot/ip.h" 50 51#ifdef __cplusplus 52extern "C" { 53#endif 54 55/* This is passed as the destination address to ip_output_if (not 56 to ip_output), meaning that an IP header already is constructed 57 in the pbuf. This is used when TCP retransmits. */ 58#define LWIP_IP_HDRINCL NULL 59 60/** pbufs passed to IP must have a ref-count of 1 as their payload pointer 61 gets altered as the packet is passed down the stack */ 62#ifndef LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX 63#define LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p) LWIP_ASSERT("p->ref == 1", (p)->ref == 1) 64#endif 65 66#if LWIP_NETIF_HWADDRHINT 67#define IP_PCB_ADDRHINT ;u8_t addr_hint 68#else 69#define IP_PCB_ADDRHINT 70#endif /* LWIP_NETIF_HWADDRHINT */ 71 72/** This is the common part of all PCB types. It needs to be at the 73 beginning of a PCB type definition. It is located here so that 74 changes to this common part are made in one location instead of 75 having to change all PCB structs. */ 76#define IP_PCB \ 77 /* ip addresses in network byte order */ \ 78 ip_addr_t local_ip; \ 79 ip_addr_t remote_ip; \ 80 /* Socket options */ \ 81 u8_t so_options; \ 82 /* Type Of Service */ \ 83 u8_t tos; \ 84 /* Time To Live */ \ 85 u8_t ttl \ 86 /* link layer address resolution hint */ \ 87 IP_PCB_ADDRHINT 88 89struct ip_pcb { 90/* Common members of all PCB types */ 91 IP_PCB; 92}; 93 94/* 95 * Option flags per-socket. These are the same like SO_XXX in sockets.h 96 */ 97#define SOF_REUSEADDR 0x04U /* allow local address reuse */ 98#define SOF_KEEPALIVE 0x08U /* keep connections alive */ 99#define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ 100 101/* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ 102#define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) 103 104/** Global variables of this module, kept in a struct for efficient access using base+index. */ 105struct ip_globals 106{ 107 /** The interface that accepted the packet for the current callback invocation. */ 108 struct netif *current_netif; 109 /** The interface that received the packet for the current callback invocation. */ 110 struct netif *current_input_netif; 111#if LWIP_IPV4 112 /** Header of the input packet currently being processed. */ 113 struct ip_hdr *current_ip4_header; 114#endif /* LWIP_IPV4 */ 115#if LWIP_IPV6 116 /** Header of the input IPv6 packet currently being processed. */ 117 struct ip6_hdr *current_ip6_header; 118#endif /* LWIP_IPV6 */ 119 /** Total header length of current_ip4/6_header (i.e. after this, the UDP/TCP header starts) */ 120 u16_t current_ip_header_tot_len; 121 /** Source IP address of current_header */ 122 ip_addr_t current_iphdr_src; 123 /** Destination IP address of current_header */ 124 ip_addr_t current_iphdr_dest; 125}; 126extern struct ip_globals ip_data; 127 128 129/** Get the interface that accepted the current packet. 130 * This may or may not be the receiving netif, depending on your netif/network setup. 131 * This function must only be called from a receive callback (udp_recv, 132 * raw_recv, tcp_accept). It will return NULL otherwise. */ 133#define ip_current_netif() (ip_data.current_netif) 134/** Get the interface that received the current packet. 135 * This function must only be called from a receive callback (udp_recv, 136 * raw_recv, tcp_accept). It will return NULL otherwise. */ 137#define ip_current_input_netif() (ip_data.current_input_netif) 138/** Total header length of ip(6)_current_header() (i.e. after this, the UDP/TCP header starts) */ 139#define ip_current_header_tot_len() (ip_data.current_ip_header_tot_len) 140/** Source IP address of current_header */ 141#define ip_current_src_addr() (&ip_data.current_iphdr_src) 142/** Destination IP address of current_header */ 143#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) 144 145#if LWIP_IPV4 && LWIP_IPV6 146/** Get the IPv4 header of the current packet. 147 * This function must only be called from a receive callback (udp_recv, 148 * raw_recv, tcp_accept). It will return NULL otherwise. */ 149#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header)) 150/** Get the IPv6 header of the current packet. 151 * This function must only be called from a receive callback (udp_recv, 152 * raw_recv, tcp_accept). It will return NULL otherwise. */ 153#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) 154/** Returns TRUE if the current IP input packet is IPv6, FALSE if it is IPv4 */ 155#define ip_current_is_v6() (ip6_current_header() != NULL) 156/** Source IPv6 address of current_header */ 157#define ip6_current_src_addr() (ip_2_ip6(&ip_data.current_iphdr_src)) 158/** Destination IPv6 address of current_header */ 159#define ip6_current_dest_addr() (ip_2_ip6(&ip_data.current_iphdr_dest)) 160/** Get the transport layer protocol */ 161#define ip_current_header_proto() (ip_current_is_v6() ? \ 162 IP6H_NEXTH(ip6_current_header()) :\ 163 IPH_PROTO(ip4_current_header())) 164/** Get the transport layer header */ 165#define ip_next_header_ptr() ((const void*)((ip_current_is_v6() ? \ 166 (const u8_t*)ip6_current_header() : (const u8_t*)ip4_current_header()) + ip_current_header_tot_len())) 167 168/** Source IP4 address of current_header */ 169#define ip4_current_src_addr() (ip_2_ip4(&ip_data.current_iphdr_src)) 170/** Destination IP4 address of current_header */ 171#define ip4_current_dest_addr() (ip_2_ip4(&ip_data.current_iphdr_dest)) 172 173#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ 174 175/** Get the IPv4 header of the current packet. 176 * This function must only be called from a receive callback (udp_recv, 177 * raw_recv, tcp_accept). It will return NULL otherwise. */ 178#define ip4_current_header() ((const struct ip_hdr*)(ip_data.current_ip4_header)) 179/** Always returns FALSE when only supporting IPv4 only */ 180#define ip_current_is_v6() 0 181/** Get the transport layer protocol */ 182#define ip_current_header_proto() IPH_PROTO(ip4_current_header()) 183/** Get the transport layer header */ 184#define ip_next_header_ptr() ((const void*)((const u8_t*)ip4_current_header() + ip_current_header_tot_len())) 185/** Source IP4 address of current_header */ 186#define ip4_current_src_addr() (&ip_data.current_iphdr_src) 187/** Destination IP4 address of current_header */ 188#define ip4_current_dest_addr() (&ip_data.current_iphdr_dest) 189 190#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ 191 192/** Get the IPv6 header of the current packet. 193 * This function must only be called from a receive callback (udp_recv, 194 * raw_recv, tcp_accept). It will return NULL otherwise. */ 195#define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) 196/** Always returns TRUE when only supporting IPv6 only */ 197#define ip_current_is_v6() 1 198/** Get the transport layer protocol */ 199#define ip_current_header_proto() IP6H_NEXTH(ip6_current_header()) 200/** Get the transport layer header */ 201#define ip_next_header_ptr() ((const void*)((const u8_t*)ip6_current_header())) 202/** Source IP6 address of current_header */ 203#define ip6_current_src_addr() (&ip_data.current_iphdr_src) 204/** Destination IP6 address of current_header */ 205#define ip6_current_dest_addr() (&ip_data.current_iphdr_dest) 206 207#endif /* LWIP_IPV6 */ 208 209/** Union source address of current_header */ 210#define ip_current_src_addr() (&ip_data.current_iphdr_src) 211/** Union destination address of current_header */ 212#define ip_current_dest_addr() (&ip_data.current_iphdr_dest) 213 214/** Gets an IP pcb option (SOF_* flags) */ 215#define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) 216/** Sets an IP pcb option (SOF_* flags) */ 217#define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) 218/** Resets an IP pcb option (SOF_* flags) */ 219#define ip_reset_option(pcb, opt) ((pcb)->so_options &= ~(opt)) 220 221#if LWIP_IPV4 && LWIP_IPV6 222/** 223 * @ingroup ip 224 * Output IP packet, netif is selected by source address 225 */ 226#define ip_output(p, src, dest, ttl, tos, proto) \ 227 (IP_IS_V6(dest) ? \ 228 ip6_output(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto) : \ 229 ip4_output(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto)) 230/** 231 * @ingroup ip 232 * Output IP packet to specified interface 233 */ 234#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ 235 (IP_IS_V6(dest) ? \ 236 ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ 237 ip4_output_if(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) 238/** 239 * @ingroup ip 240 * Output IP packet to interface specifying source address 241 */ 242#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ 243 (IP_IS_V6(dest) ? \ 244 ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ 245 ip4_output_if_src(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) 246/** Output IP packet with addr_hint */ 247#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ 248 (IP_IS_V6(dest) ? \ 249 ip6_output_hinted(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, addr_hint) : \ 250 ip4_output_hinted(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, addr_hint)) 251/** 252 * @ingroup ip 253 * Get netif for address combination. See \ref ip6_route and \ref ip4_route 254 */ 255#define ip_route(src, dest) \ 256 (IP_IS_V6(dest) ? \ 257 ip6_route(ip_2_ip6(src), ip_2_ip6(dest)) : \ 258 ip4_route_src(ip_2_ip4(dest), ip_2_ip4(src))) 259/** 260 * @ingroup ip 261 * Get netif for IP. 262 */ 263#define ip_netif_get_local_ip(netif, dest) (IP_IS_V6(dest) ? \ 264 ip6_netif_get_local_ip(netif, ip_2_ip6(dest)) : \ 265 ip4_netif_get_local_ip(netif)) 266#define ip_debug_print(is_ipv6, p) ((is_ipv6) ? ip6_debug_print(p) : ip4_debug_print(p)) 267 268err_t ip_input(struct pbuf *p, struct netif *inp); 269 270#elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ 271 272#define ip_output(p, src, dest, ttl, tos, proto) \ 273 ip4_output(p, src, dest, ttl, tos, proto) 274#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ 275 ip4_output_if(p, src, dest, ttl, tos, proto, netif) 276#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ 277 ip4_output_if_src(p, src, dest, ttl, tos, proto, netif) 278#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ 279 ip4_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) 280#define ip_route(src, dest) \ 281 ip4_route_src(dest, src) 282#define ip_netif_get_local_ip(netif, dest) \ 283 ip4_netif_get_local_ip(netif) 284#define ip_debug_print(is_ipv6, p) ip4_debug_print(p) 285 286#define ip_input ip4_input 287 288#elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ 289 290#define ip_output(p, src, dest, ttl, tos, proto) \ 291 ip6_output(p, src, dest, ttl, tos, proto) 292#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ 293 ip6_output_if(p, src, dest, ttl, tos, proto, netif) 294#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ 295 ip6_output_if_src(p, src, dest, ttl, tos, proto, netif) 296#define ip_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) \ 297 ip6_output_hinted(p, src, dest, ttl, tos, proto, addr_hint) 298#define ip_route(src, dest) \ 299 ip6_route(src, dest) 300#define ip_netif_get_local_ip(netif, dest) \ 301 ip6_netif_get_local_ip(netif, dest) 302#define ip_debug_print(is_ipv6, p) ip6_debug_print(p) 303 304#define ip_input ip6_input 305 306#endif /* LWIP_IPV6 */ 307 308#define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \ 309 (netif) = ip_route(src, dest); \ 310 (ipaddr) = ip_netif_get_local_ip(netif, dest); \ 311}while(0) 312 313#ifdef __cplusplus 314} 315#endif 316 317#endif /* LWIP_HDR_IP_H */ 318 319 320