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 #if defined (__cplusplus) && __cplusplus 52 extern "C" { 53 #endif 54 55 56 /* This is passed as the destination address to ip_output_if (not 57 to ip_output), meaning that an IP header already is constructed 58 in the pbuf. This is used when TCP retransmits. */ 59 #define LWIP_IP_HDRINCL NULL 60 61 /** pbufs passed to IP must have a ref-count of 1 as their payload pointer 62 gets altered as the packet is passed down the stack */ 63 #ifndef LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX 64 65 #define LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p) LWIP_ASSERT("p->ref == 1", (atomic_read(&p->ref) == 1)) 66 #endif 67 68 #if LWIP_NETIF_USE_HINTS 69 #define IP_PCB_NETIFHINT ;struct netif_hint netif_hints 70 #define IP_PAD 71 #else 72 #define IP_PCB_NETIFHINT 73 #define IP_PAD ;u8_t pad_ip 74 #endif /* LWIP_NETIF_HWADDRHINT */ 75 76 /** This is the common part of all PCB types. It needs to be at the 77 beginning of a PCB type definition. It is located here so that 78 changes to this common part are made in one location instead of 79 having to change all PCB structs. */ 80 #define IP_PCB \ 81 /* ip addresses in network byte order */ \ 82 ip_addr_t local_ip; \ 83 ip_addr_t remote_ip; \ 84 /* Socket options */ \ 85 u32_t so_options; \ 86 /* Type Of Service */ \ 87 u8_t tos; \ 88 /* the netif set by bindtodevice */ \ 89 u8_t ifindex; \ 90 /* Time To Live */ \ 91 u8_t ttl \ 92 /* link layer address resolution hint */ \ 93 IP_PCB_NETIFHINT \ 94 IP_PAD 95 96 struct ip_pcb { 97 /* Common members of all PCB types */ 98 IP_PCB; 99 100 #if LWIP_SO_PRIORITY 101 prio_t priority; 102 #endif /* LWIP_SO_PRIORITY */ 103 104 #if LWIP_IPV6 && LWIP_MAC_SECURITY 105 u8_t macsec_reqd: 1; 106 #endif 107 }; 108 109 /* 110 * Option flags per-socket. These are the same like SO_XXX in sockets.h 111 */ 112 #define SOF_REUSEADDR 0x04U /* allow local address reuse */ 113 #define SOF_KEEPALIVE 0x08U /* keep connections alive */ 114 #define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ 115 #define SOF_REUSEPORT 0x0200U /* Unimplemented: allow local address & port reuse */ 116 #define SOF_DONTROUTE 0X0400U /* all packets sent from this socket should only be routed with link scope entry, */ 117 #define SOF_BINDNONUNICAST 0x0800U /* socket has bind to a non unicast */ 118 119 120 /* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ 121 #define SOF_INHERITED (SOF_REUSEADDR | SOF_KEEPALIVE) 122 123 /** Global variables of this module, kept in a struct for efficient access using base+index. */ 124 struct ip_globals { 125 /** The interface that accepted the packet for the current callback invocation. */ 126 struct netif *current_netif; 127 /** The interface that received the packet for the current callback invocation. */ 128 struct netif *current_input_netif; 129 #if LWIP_IPV4 130 /** Header of the input packet currently being processed. */ 131 const struct ip_hdr *current_ip4_header; 132 #endif /* LWIP_IPV4 */ 133 #if LWIP_IPV6 134 /** Header of the input IPv6 packet currently being processed. */ 135 struct ip6_hdr *current_ip6_header; 136 #endif /* LWIP_IPV6 */ 137 /** Total header length of current_ip4/6_header (i.e. after this, the UDP/TCP header starts) */ 138 u16_t current_ip_header_tot_len; 139 /** Source IP address of current_header */ 140 ip_addr_t current_iphdr_src; 141 /** Destination IP address of current_header */ 142 ip_addr_t current_iphdr_dest; 143 144 /* The IP header ID of the next outgoing IP packet */ 145 #if LWIP_IPV4 146 /* ensure this member of this sturcture is not mem set to zero */ 147 u16_t ip_id; 148 #endif 149 }; 150 extern struct ip_globals ip_data; 151 152 153 /** Get the interface that accepted the current packet. 154 * This may or may not be the receiving netif, depending on your netif/network setup. 155 * This function must only be called from a receive callback (udp_recv, 156 * raw_recv, tcp_accept). It will return NULL otherwise. */ 157 #define ip_current_netif() (ip_data.current_netif) 158 /** Get the interface that received the current packet. 159 * This function must only be called from a receive callback (udp_recv, 160 * raw_recv, tcp_accept). It will return NULL otherwise. */ 161 #define ip_current_input_netif() (ip_data.current_input_netif) 162 /** Total header length of ip(6)_current_header() (i.e. after this, the UDP/TCP header starts) */ 163 #define ip_current_header_tot_len() (ip_data.current_ip_header_tot_len) 164 /** Source IP address of current_header */ 165 #define ip_current_src_addr() (&ip_data.current_iphdr_src) 166 /** Destination IP address of current_header */ 167 #define ip_current_dest_addr() (&ip_data.current_iphdr_dest) 168 169 #if LWIP_IPV4 && LWIP_IPV6 170 /** Get the IPv4 header of the current packet. 171 * This function must only be called from a receive callback (udp_recv, 172 * raw_recv, tcp_accept). It will return NULL otherwise. */ 173 #define ip4_current_header() ip_data.current_ip4_header 174 /** Get the IPv6 header of the current packet. 175 * This function must only be called from a receive callback (udp_recv, 176 * raw_recv, tcp_accept). It will return NULL otherwise. */ 177 #define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) 178 /** Returns TRUE if the current IP input packet is IPv6, FALSE if it is IPv4 */ 179 #define ip_current_is_v6() (ip6_current_header() != NULL) 180 /** Source IPv6 address of current_header */ 181 #define ip6_current_src_addr() (ip_2_ip6(&ip_data.current_iphdr_src)) 182 /** Destination IPv6 address of current_header */ 183 #define ip6_current_dest_addr() (ip_2_ip6(&ip_data.current_iphdr_dest)) 184 /** Get the transport layer protocol */ 185 #define ip_current_header_proto() (ip_current_is_v6() ? \ 186 IP6H_NEXTH(ip6_current_header()) :\ 187 IPH_PROTO(ip4_current_header())) 188 /** Get the transport layer header */ 189 #define ip_next_header_ptr() ((const void*)((ip_current_is_v6() ? \ 190 (const u8_t*)ip6_current_header() : (const u8_t*)ip4_current_header()) + ip_current_header_tot_len())) 191 192 /** Source IP4 address of current_header */ 193 #define ip4_current_src_addr() (ip_2_ip4(&ip_data.current_iphdr_src)) 194 /** Destination IP4 address of current_header */ 195 #define ip4_current_dest_addr() (ip_2_ip4(&ip_data.current_iphdr_dest)) 196 197 /* get ip id for IPv4 */ 198 #define ip4_get_ip_id() (ip_data.ip_id) 199 200 /* get last ip id for IPv4 */ 201 #define ip4_last_ip_id() ((u16_t)(ip_data.ip_id - 1)) 202 203 /* set ip id for IPv4 */ 204 #define ip4_set_ip_id(val) (ip_data.ip_id = (val)) 205 206 /* inc ip id for IPv4 */ 207 #define ip4_inc_ip_id() (++ip_data.ip_id) 208 209 #elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ 210 211 /** Get the IPv4 header of the current packet. 212 * This function must only be called from a receive callback (udp_recv, 213 * raw_recv, tcp_accept). It will return NULL otherwise. */ 214 #define ip4_current_header() ip_data.current_ip4_header 215 /** Always returns FALSE when only supporting IPv4 only */ 216 #define ip_current_is_v6() 0 217 /** Get the transport layer protocol */ 218 #define ip_current_header_proto() IPH_PROTO(ip4_current_header()) 219 /** Get the transport layer header */ 220 #define ip_next_header_ptr() ((const void*)((const u8_t*)ip4_current_header() + ip_current_header_tot_len())) 221 /** Source IP4 address of current_header */ 222 #define ip4_current_src_addr() (&ip_data.current_iphdr_src) 223 /** Destination IP4 address of current_header */ 224 #define ip4_current_dest_addr() (&ip_data.current_iphdr_dest) 225 226 /* get ip id for IPv4 */ 227 #define ip4_get_ip_id() (ip_data.ip_id) 228 229 /* get last ip id for IPv4 */ 230 #define ip4_last_ip_id() ((u16_t)(ip_data.ip_id - 1)) 231 232 /* set ip id for IPv4 */ 233 #define ip4_set_ip_id(val) (ip_data.ip_id = (val)) 234 235 /* inc ip id for IPv4 */ 236 #define ip4_inc_ip_id() (++ip_data.ip_id) 237 238 #elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ 239 240 /** Get the IPv6 header of the current packet. 241 * This function must only be called from a receive callback (udp_recv, 242 * raw_recv, tcp_accept). It will return NULL otherwise. */ 243 #define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) 244 /** Always returns TRUE when only supporting IPv6 only */ 245 #define ip_current_is_v6() 1 246 /** Get the transport layer protocol */ 247 #define ip_current_header_proto() IP6H_NEXTH(ip6_current_header()) 248 /** Get the transport layer header */ 249 #define ip_next_header_ptr() ((const void*)(((const u8_t*)ip6_current_header()) + ip_current_header_tot_len())) 250 /** Source IP6 address of current_header */ 251 #define ip6_current_src_addr() (&ip_data.current_iphdr_src) 252 /** Destination IP6 address of current_header */ 253 #define ip6_current_dest_addr() (&ip_data.current_iphdr_dest) 254 255 #endif /* LWIP_IPV6 */ 256 257 /** Union source address of current_header */ 258 #define ip_current_src_addr() (&ip_data.current_iphdr_src) 259 /** Union destination address of current_header */ 260 #define ip_current_dest_addr() (&ip_data.current_iphdr_dest) 261 262 /** Gets an IP pcb option (SOF_* flags) */ 263 #define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) 264 /** Sets an IP pcb option (SOF_* flags) */ 265 #define ip_set_option(pcb, opt) ((pcb)->so_options |= (opt)) 266 /** Resets an IP pcb option (SOF_* flags) */ 267 #define ip_reset_option(pcb, opt) ((pcb)->so_options &= (u8_t)~(opt)) 268 269 #if LWIP_IPV4 && LWIP_IPV6 270 #if LWIP_API_RICH 271 /** 272 * @ingroup ip 273 * Output IP packet, netif is selected by source address 274 */ 275 #define ip_output(p, src, dest, ttl, tos, proto, pcb) \ 276 (IP_IS_V6(dest) ? \ 277 ip6_output(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, pcb) : \ 278 ip4_output(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, pcb)) 279 #endif /* LWIP_API_RICH */ 280 /** 281 * @ingroup ip 282 * Output IP packet to specified interface 283 */ 284 #define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ 285 (IP_IS_V6(dest) ? \ 286 ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ 287 ip4_output_if(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) 288 /** 289 * @ingroup ip 290 * Output IP packet to interface specifying source address 291 */ 292 #define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ 293 (IP_IS_V6(dest) ? \ 294 ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ 295 ip4_output_if_src(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) 296 /** Output IP packet that already includes an IP header. */ 297 #define ip_output_if_hdrincl(p, src, dest, netif) \ 298 (IP_IS_V6(dest) ? \ 299 ip6_output_if(p, ip_2_ip6(src), LWIP_IP_HDRINCL, 0, 0, 0, netif) : \ 300 ip4_output_if(p, ip_2_ip4(src), LWIP_IP_HDRINCL, 0, 0, 0, netif)) 301 /** Output IP packet with netif_hint */ 302 #define ip_output_hinted(p, src, dest, ttl, tos, proto, netif_hint) \ 303 (IP_IS_V6(dest) ? \ 304 ip6_output_hinted(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif_hint) : \ 305 ip4_output_hinted(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif_hint)) 306 307 #if LWIP_IP_FILTER || LWIP_IPV6_FILTER 308 /** @cond liteos 309 * Function prototype for packet_filter functions. Call this function when an ip packet has 310 * been received and LWIP_IP_FILTER or LWIP_IPV6_FILTERis Enabled. 311 * @note If this registered callback return other than ERR_OK then packet will be dropped. 312 * @param p Indicates the received packet, copied into a pbuf. 313 * @param inp Indicates the netif which received the packet. 314 * @endcond 315 */ 316 typedef err_t (*ip_filter_fn)(const struct pbuf *p, struct netif *inp); 317 318 #if LWIP_IP_FILTER 319 err_t set_ip4_filter(ip_filter_fn filter_fn); 320 #endif /* LWIP_IP_FILTER */ 321 322 #if LWIP_IPV6_FILTER 323 err_t set_ip6_filter(ip_filter_fn filter_fn); 324 #endif /* LWIP_IPV6_FILTER */ 325 #endif /* LWIP_IP_FILTER */ 326 327 /** 328 * @ingroup ip 329 * Get netif for address combination. See \ref ip6_route and \ref ip4_route 330 */ 331 #if LWIP_SO_DONTROUTE 332 #define ip_route(src, dest, scope) \ 333 (IP_IS_V6_VAL(*dest) ? \ 334 ip6_route(ip_2_ip6(src), ip_2_ip6(dest), scope) : \ 335 ip4_route_src(ip_2_ip4(src), ip_2_ip4(dest), scope)) 336 #else 337 #define ip_route(src, dest) \ 338 (IP_IS_V6_VAL(*dest) ? \ 339 ip6_route(ip_2_ip6(src), ip_2_ip6(dest)) : \ 340 ip4_route_src(ip_2_ip4(src), ip_2_ip4(dest))) 341 #endif 342 343 /** 344 * @ingroup ip 345 * Get netif for IP. 346 */ 347 #define ip_netif_get_local_ip(netif, dest) (IP_IS_V6(dest) ? \ 348 ip6_netif_get_local_ip(netif, ip_2_ip6(dest)) : \ 349 ip4_netif_get_local_ip(netif)) 350 #define ip_debug_print(is_ipv6, p) ((is_ipv6) ? ip6_debug_print(p) : ip4_debug_print(p)) 351 352 err_t ip_input(struct pbuf *p, struct netif *inp); 353 354 #if LWIP_PLC || LWIP_IEEE802154 355 err_t ip_input_lln(struct netif *iface, struct pbuf *p, 356 struct linklayer_addr *sendermac, struct linklayer_addr *recvermac); 357 #endif 358 359 #elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ 360 361 #if LWIP_API_RICH 362 #define ip_output(p, src, dest, ttl, tos, proto) \ 363 ip4_output(p, src, dest, ttl, tos, proto, pcb) 364 #endif /* LWIP_API_RICH */ 365 #define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ 366 ip4_output_if(p, src, dest, ttl, tos, proto, netif) 367 #define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ 368 ip4_output_if_src(p, src, dest, ttl, tos, proto, netif) 369 #define ip_output_hinted(p, src, dest, ttl, tos, proto, netif_hint) \ 370 ip4_output_hinted(p, src, dest, ttl, tos, proto, netif_hint) 371 #define ip_output_if_hdrincl(p, src, dest, netif) \ 372 ip6_output_if(p, src, LWIP_IP_HDRINCL, 0, 0, 0, netif) 373 374 #if LWIP_SO_DONTROUTE 375 #define ip_route(src, dest, scope) \ 376 ip4_route_src(src, dest, scope) 377 #else 378 #define ip_route(src, dest) \ 379 ip4_route_src(src, dest) 380 #endif 381 382 #define ip_netif_get_local_ip(netif, dest) \ 383 ip4_netif_get_local_ip(netif) 384 #define ip_debug_print(is_ipv6, p) ip4_debug_print(p) 385 386 #define ip_input ip4_input 387 388 #elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ 389 390 #if LWIP_API_RICH 391 #define ip_output(p, src, dest, ttl, tos, proto) \ 392 ip6_output(p, src, dest, ttl, tos, proto) 393 #endif /* LWIP_API_RICH */ 394 #define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ 395 ip6_output_if(p, src, dest, ttl, tos, proto, netif) 396 #define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ 397 ip6_output_if_src(p, src, dest, ttl, tos, proto, netif) 398 #define ip_output_hinted(p, src, dest, ttl, tos, proto, netif_hint) \ 399 ip6_output_hinted(p, src, dest, ttl, tos, proto, netif_hint) 400 #define ip_output_if_hdrincl(p, src, dest, netif) \ 401 ip4_output_if(p, src, LWIP_IP_HDRINCL, 0, 0, 0, netif) 402 403 #if LWIP_SO_DONTROUTE 404 #define ip_route(src, dest, scope) \ 405 ip6_route(src, dest, scope) 406 #else 407 #define ip_route(src, dest) \ 408 ip6_route(src, dest) 409 #endif 410 #define ip_netif_get_local_ip(netif, dest) \ 411 ip6_netif_get_local_ip(netif, dest) 412 #define ip_debug_print(is_ipv6, p) ip6_debug_print(p) 413 414 #define ip_input ip6_input 415 416 #endif /* LWIP_IPV6 */ 417 418 #define ip_route_get_local_ip(src, dest, netif, ipaddr, scope) do { \ 419 (netif) = ip_route(src, dest, scope); \ 420 (ipaddr) = ip_netif_get_local_ip(netif, dest); \ 421 } while (0) 422 423 struct netif *ip_route_pcb(const ip_addr_t *dest, const struct ip_pcb *pcb); 424 425 #if defined (__cplusplus) && __cplusplus 426 } 427 #endif 428 429 #endif /* LWIP_HDR_IP_H */ 430 431 432