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 #ifdef LOSCFG_NET_CONTAINER 51 #include "lwip/net_group.h" 52 #endif 53 54 #ifdef __cplusplus 55 extern "C" { 56 #endif 57 58 /* This is passed as the destination address to ip_output_if (not 59 to ip_output), meaning that an IP header already is constructed 60 in the pbuf. This is used when TCP retransmits. */ 61 #define LWIP_IP_HDRINCL NULL 62 63 /** pbufs passed to IP must have a ref-count of 1 as their payload pointer 64 gets altered as the packet is passed down the stack */ 65 #ifndef LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX 66 #define LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p) LWIP_ASSERT("p->ref == 1", (p)->ref == 1) 67 #endif 68 69 #if LWIP_NETIF_USE_HINTS 70 #define IP_PCB_NETIFHINT ;struct netif_hint netif_hints 71 #else /* LWIP_NETIF_USE_HINTS */ 72 #define IP_PCB_NETIFHINT 73 #endif /* LWIP_NETIF_USE_HINTS */ 74 75 #ifdef LOSCFG_NET_CONTAINER 76 #ifndef IP_PCB_NETGROUP 77 #define IP_PCB_NETGROUP 78 #endif 79 #endif 80 81 /** This is the common part of all PCB types. It needs to be at the 82 beginning of a PCB type definition. It is located here so that 83 changes to this common part are made in one location instead of 84 having to change all PCB structs. */ 85 #ifdef LOSCFG_NET_CONTAINER 86 #define IP_PCB \ 87 /* ip addresses in network byte order */ \ 88 ip_addr_t local_ip; \ 89 ip_addr_t remote_ip; \ 90 /* Bound netif index */ \ 91 u8_t netif_idx; \ 92 /* Socket options */ \ 93 u8_t so_options; \ 94 /* Type Of Service */ \ 95 u8_t tos; \ 96 /* Time To Live */ \ 97 u8_t ttl \ 98 /* link layer address resolution hint */ \ 99 IP_PCB_NETIFHINT \ 100 IP_PCB_NETGROUP 101 #else 102 #define IP_PCB \ 103 /* ip addresses in network byte order */ \ 104 ip_addr_t local_ip; \ 105 ip_addr_t remote_ip; \ 106 /* Bound netif index */ \ 107 u8_t netif_idx; \ 108 /* Socket options */ \ 109 u8_t so_options; \ 110 /* Type Of Service */ \ 111 u8_t tos; \ 112 /* Time To Live */ \ 113 u8_t ttl \ 114 /* link layer address resolution hint */ \ 115 IP_PCB_NETIFHINT 116 #endif 117 118 struct ip_pcb { 119 /* Common members of all PCB types */ 120 IP_PCB; 121 }; 122 123 #if LWIP_VLAN_PCP 124 #define pcb_has_tci(pcb) ((pcb)->netif_hints.tci >= 0) 125 #define pcb_tci_get(pcb) ((pcb)->netif_hints.tci) 126 #define pcb_tci_clear(pcb) do { (pcb)->netif_hints.tci = -1; } while(0) 127 #define pcb_tci_set(pcb, tci_val) do { (pcb)->netif_hints.tci = (tci_val) & 0xffff; } while(0) 128 #define pcb_tci_set_pcp_dei_vid(pcb, pcp, dei, vid) pcb_tci_set(pcb, (((pcp) & 7) << 13) | (((dei) & 1) << 12) | ((vid) & 0xFFF)) 129 #define pcb_tci_init(pcb) pcb_tci_clear(pcb) 130 #else 131 #define pcb_tci_init(pcb) 132 #endif 133 134 /* 135 * Option flags per-socket. These are the same like SO_XXX in sockets.h 136 */ 137 #define SOF_REUSEADDR 0x04U /* allow local address reuse */ 138 #define SOF_KEEPALIVE 0x08U /* keep connections alive */ 139 #define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ 140 141 /* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ 142 #define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) 143 144 /** Global variables of this module, kept in a struct for efficient access using base+index. */ 145 struct ip_globals 146 { 147 /** The interface that accepted the packet for the current callback invocation. */ 148 struct netif *current_netif; 149 /** The interface that received the packet for the current callback invocation. */ 150 struct netif *current_input_netif; 151 #if LWIP_IPV4 152 /** Header of the input packet currently being processed. */ 153 const struct ip_hdr *current_ip4_header; 154 #endif /* LWIP_IPV4 */ 155 #if LWIP_IPV6 156 /** Header of the input IPv6 packet currently being processed. */ 157 struct ip6_hdr *current_ip6_header; 158 #endif /* LWIP_IPV6 */ 159 /** Total header length of current_ip4/6_header (i.e. after this, the UDP/TCP header starts) */ 160 u16_t current_ip_header_tot_len; 161 /** Source IP address of current_header */ 162 ip_addr_t current_iphdr_src; 163 /** Destination IP address of current_header */ 164 ip_addr_t current_iphdr_dest; 165 }; 166 extern struct ip_globals ip_data; 167 168 169 /** Get the interface that accepted the current packet. 170 * This may or may not be the receiving netif, depending on your netif/network setup. 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 ip_current_netif() (ip_data.current_netif) 174 /** Get the interface that received 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 ip_current_input_netif() (ip_data.current_input_netif) 178 /** Total header length of ip(6)_current_header() (i.e. after this, the UDP/TCP header starts) */ 179 #define ip_current_header_tot_len() (ip_data.current_ip_header_tot_len) 180 /** Source IP address of current_header */ 181 #define ip_current_src_addr() (&ip_data.current_iphdr_src) 182 /** Destination IP address of current_header */ 183 #define ip_current_dest_addr() (&ip_data.current_iphdr_dest) 184 185 #if LWIP_IPV4 && LWIP_IPV6 186 /** Get the IPv4 header of the current packet. 187 * This function must only be called from a receive callback (udp_recv, 188 * raw_recv, tcp_accept). It will return NULL otherwise. */ 189 #define ip4_current_header() ip_data.current_ip4_header 190 /** Get the IPv6 header of the current packet. 191 * This function must only be called from a receive callback (udp_recv, 192 * raw_recv, tcp_accept). It will return NULL otherwise. */ 193 #define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) 194 /** Returns TRUE if the current IP input packet is IPv6, FALSE if it is IPv4 */ 195 #define ip_current_is_v6() (ip6_current_header() != NULL) 196 /** Source IPv6 address of current_header */ 197 #define ip6_current_src_addr() (ip_2_ip6(&ip_data.current_iphdr_src)) 198 /** Destination IPv6 address of current_header */ 199 #define ip6_current_dest_addr() (ip_2_ip6(&ip_data.current_iphdr_dest)) 200 /** Get the transport layer protocol */ 201 #define ip_current_header_proto() (ip_current_is_v6() ? \ 202 IP6H_NEXTH(ip6_current_header()) :\ 203 IPH_PROTO(ip4_current_header())) 204 /** Get the transport layer header */ 205 #define ip_next_header_ptr() ((const void*)((ip_current_is_v6() ? \ 206 (const u8_t*)ip6_current_header() : (const u8_t*)ip4_current_header()) + ip_current_header_tot_len())) 207 208 /** Source IP4 address of current_header */ 209 #define ip4_current_src_addr() (ip_2_ip4(&ip_data.current_iphdr_src)) 210 /** Destination IP4 address of current_header */ 211 #define ip4_current_dest_addr() (ip_2_ip4(&ip_data.current_iphdr_dest)) 212 213 #elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ 214 215 /** Get the IPv4 header of the current packet. 216 * This function must only be called from a receive callback (udp_recv, 217 * raw_recv, tcp_accept). It will return NULL otherwise. */ 218 #define ip4_current_header() ip_data.current_ip4_header 219 /** Always returns FALSE when only supporting IPv4 only */ 220 #define ip_current_is_v6() 0 221 /** Get the transport layer protocol */ 222 #define ip_current_header_proto() IPH_PROTO(ip4_current_header()) 223 /** Get the transport layer header */ 224 #define ip_next_header_ptr() ((const void*)((const u8_t*)ip4_current_header() + ip_current_header_tot_len())) 225 /** Source IP4 address of current_header */ 226 #define ip4_current_src_addr() (&ip_data.current_iphdr_src) 227 /** Destination IP4 address of current_header */ 228 #define ip4_current_dest_addr() (&ip_data.current_iphdr_dest) 229 230 #elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ 231 232 /** Get the IPv6 header of the current packet. 233 * This function must only be called from a receive callback (udp_recv, 234 * raw_recv, tcp_accept). It will return NULL otherwise. */ 235 #define ip6_current_header() ((const struct ip6_hdr*)(ip_data.current_ip6_header)) 236 /** Always returns TRUE when only supporting IPv6 only */ 237 #define ip_current_is_v6() 1 238 /** Get the transport layer protocol */ 239 #define ip_current_header_proto() IP6H_NEXTH(ip6_current_header()) 240 /** Get the transport layer header */ 241 #define ip_next_header_ptr() ((const void*)(((const u8_t*)ip6_current_header()) + ip_current_header_tot_len())) 242 /** Source IP6 address of current_header */ 243 #define ip6_current_src_addr() (&ip_data.current_iphdr_src) 244 /** Destination IP6 address of current_header */ 245 #define ip6_current_dest_addr() (&ip_data.current_iphdr_dest) 246 247 #endif /* LWIP_IPV6 */ 248 249 /** Union source address of current_header */ 250 #define ip_current_src_addr() (&ip_data.current_iphdr_src) 251 /** Union destination address of current_header */ 252 #define ip_current_dest_addr() (&ip_data.current_iphdr_dest) 253 254 /** Gets an IP pcb option (SOF_* flags) */ 255 #define ip_get_option(pcb, opt) ((pcb)->so_options & (opt)) 256 /** Sets an IP pcb option (SOF_* flags) */ 257 #define ip_set_option(pcb, opt) ((pcb)->so_options = (u8_t)((pcb)->so_options | (opt))) 258 /** Resets an IP pcb option (SOF_* flags) */ 259 #define ip_reset_option(pcb, opt) ((pcb)->so_options = (u8_t)((pcb)->so_options & ~(opt))) 260 261 #if LWIP_IPV4 && LWIP_IPV6 262 /** 263 * @ingroup ip 264 * Output IP packet, netif is selected by source address 265 */ 266 #define ip_output(p, src, dest, ttl, tos, proto) \ 267 (IP_IS_V6(dest) ? \ 268 ip6_output(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto) : \ 269 ip4_output(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto)) 270 /** 271 * @ingroup ip 272 * Output IP packet to specified interface 273 */ 274 #define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ 275 (IP_IS_V6(dest) ? \ 276 ip6_output_if(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ 277 ip4_output_if(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) 278 /** 279 * @ingroup ip 280 * Output IP packet to interface specifying source address 281 */ 282 #define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ 283 (IP_IS_V6(dest) ? \ 284 ip6_output_if_src(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif) : \ 285 ip4_output_if_src(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif)) 286 /** Output IP packet that already includes an IP header. */ 287 #define ip_output_if_hdrincl(p, src, dest, netif) \ 288 (IP_IS_V6(dest) ? \ 289 ip6_output_if(p, ip_2_ip6(src), LWIP_IP_HDRINCL, 0, 0, 0, netif) : \ 290 ip4_output_if(p, ip_2_ip4(src), LWIP_IP_HDRINCL, 0, 0, 0, netif)) 291 /** Output IP packet with netif_hint */ 292 #define ip_output_hinted(p, src, dest, ttl, tos, proto, netif_hint) \ 293 (IP_IS_V6(dest) ? \ 294 ip6_output_hinted(p, ip_2_ip6(src), ip_2_ip6(dest), ttl, tos, proto, netif_hint) : \ 295 ip4_output_hinted(p, ip_2_ip4(src), ip_2_ip4(dest), ttl, tos, proto, netif_hint)) 296 /** 297 * @ingroup ip 298 * Get netif for address combination. See \ref ip6_route and \ref ip4_route 299 */ 300 #ifdef LOSCFG_NET_CONTAINER 301 #define ip_route(src, dest, group) \ 302 (IP_IS_V6(dest) ? \ 303 ip6_route(ip_2_ip6(src), ip_2_ip6(dest), group) : \ 304 ip4_route_src(ip_2_ip4(src), ip_2_ip4(dest), group)) 305 #else 306 #define ip_route(src, dest) \ 307 (IP_IS_V6(dest) ? \ 308 ip6_route(ip_2_ip6(src), ip_2_ip6(dest)) : \ 309 ip4_route_src(ip_2_ip4(src), ip_2_ip4(dest))) 310 #endif 311 /** 312 * @ingroup ip 313 * Get netif for IP. 314 */ 315 #define ip_netif_get_local_ip(netif, dest) (IP_IS_V6(dest) ? \ 316 ip6_netif_get_local_ip(netif, ip_2_ip6(dest)) : \ 317 ip4_netif_get_local_ip(netif)) 318 #define ip_debug_print(is_ipv6, p) ((is_ipv6) ? ip6_debug_print(p) : ip4_debug_print(p)) 319 320 err_t ip_input(struct pbuf *p, struct netif *inp); 321 322 #elif LWIP_IPV4 /* LWIP_IPV4 && LWIP_IPV6 */ 323 324 #define ip_output(p, src, dest, ttl, tos, proto) \ 325 ip4_output(p, src, dest, ttl, tos, proto) 326 #define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ 327 ip4_output_if(p, src, dest, ttl, tos, proto, netif) 328 #define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ 329 ip4_output_if_src(p, src, dest, ttl, tos, proto, netif) 330 #define ip_output_hinted(p, src, dest, ttl, tos, proto, netif_hint) \ 331 ip4_output_hinted(p, src, dest, ttl, tos, proto, netif_hint) 332 #define ip_output_if_hdrincl(p, src, dest, netif) \ 333 ip4_output_if(p, src, LWIP_IP_HDRINCL, 0, 0, 0, netif) 334 #define ip_route(src, dest) \ 335 ip4_route_src(src, dest) 336 #define ip_netif_get_local_ip(netif, dest) \ 337 ip4_netif_get_local_ip(netif) 338 #define ip_debug_print(is_ipv6, p) ip4_debug_print(p) 339 340 #define ip_input ip4_input 341 342 #elif LWIP_IPV6 /* LWIP_IPV4 && LWIP_IPV6 */ 343 344 #define ip_output(p, src, dest, ttl, tos, proto) \ 345 ip6_output(p, src, dest, ttl, tos, proto) 346 #define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ 347 ip6_output_if(p, src, dest, ttl, tos, proto, netif) 348 #define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ 349 ip6_output_if_src(p, src, dest, ttl, tos, proto, netif) 350 #define ip_output_hinted(p, src, dest, ttl, tos, proto, netif_hint) \ 351 ip6_output_hinted(p, src, dest, ttl, tos, proto, netif_hint) 352 #define ip_output_if_hdrincl(p, src, dest, netif) \ 353 ip6_output_if(p, src, LWIP_IP_HDRINCL, 0, 0, 0, netif) 354 #define ip_route(src, dest) \ 355 ip6_route(src, dest) 356 #define ip_netif_get_local_ip(netif, dest) \ 357 ip6_netif_get_local_ip(netif, dest) 358 #define ip_debug_print(is_ipv6, p) ip6_debug_print(p) 359 360 #define ip_input ip6_input 361 362 #endif /* LWIP_IPV6 */ 363 364 #define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \ 365 (netif) = ip_route(src, dest); \ 366 (ipaddr) = ip_netif_get_local_ip(netif, dest); \ 367 }while(0) 368 369 #ifdef LOSCFG_NET_CONTAINER 370 void set_ippcb_net_group(struct ip_pcb *pcb, struct net_group *group); 371 struct net_group *get_net_group_from_ippcb(struct ip_pcb *pcb); 372 #endif 373 #ifdef __cplusplus 374 } 375 #endif 376 377 #endif /* LWIP_HDR_IP_H */ 378