Free (GPLv2) TCP/IP stack developed by TASS Belgium

Dependents:   lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

Different licensing models may exist, at the sole discretion of the Copyright holders.

Official homepage: http://www.picotcp.com

Bug tracker: https://github.com/tass-belgium/picotcp/issues

Development steps:

  • initial integration with mbed RTOS
  • generic mbed Ethernet driver
  • high performance NXP LPC1768 specific Ethernet driver
  • Multi-threading support for mbed RTOS
  • Berkeley sockets and integration with the New Socket API
  • Fork of the apps running on top of the New Socket API
  • Scheduling optimizations
  • Debugging/benchmarking/testing

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.

Committer:
tass
Date:
Thu Jan 28 15:12:00 2016 +0100
Revision:
155:a70f34550c34
Parent:
152:a3d286bf94e5
Adding TCP flag for FIN.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
tass 68:0847e35d08a6 1 /*********************************************************************
tass 152:a3d286bf94e5 2 PicoTCP. Copyright (c) 2012-2015 Altran Intelligent Systems. Some rights reserved.
TASS Belgium NV 131:4758606c9316 3 See LICENSE and COPYING for usage.
tass 68:0847e35d08a6 4
TASS Belgium NV 131:4758606c9316 5 Authors: Daniele Lacamera, Markian Yskout
TASS Belgium NV 131:4758606c9316 6 *********************************************************************/
tass 68:0847e35d08a6 7
tass 68:0847e35d08a6 8
tass 68:0847e35d08a6 9 #include "pico_config.h"
tass 68:0847e35d08a6 10 #include "pico_ipfilter.h"
tass 68:0847e35d08a6 11 #include "pico_ipv4.h"
tass 68:0847e35d08a6 12 #include "pico_icmp4.h"
tass 68:0847e35d08a6 13 #include "pico_stack.h"
tass 68:0847e35d08a6 14 #include "pico_eth.h"
tass 68:0847e35d08a6 15 #include "pico_udp.h"
tass 68:0847e35d08a6 16 #include "pico_tcp.h"
tass 68:0847e35d08a6 17 #include "pico_socket.h"
tass 68:0847e35d08a6 18 #include "pico_device.h"
tass 68:0847e35d08a6 19 #include "pico_nat.h"
tass 68:0847e35d08a6 20 #include "pico_igmp.h"
tass 68:0847e35d08a6 21 #include "pico_tree.h"
tass 152:a3d286bf94e5 22 #include "pico_aodv.h"
tass picotcp@tass.be 149:5f4cb161cec3 23 #include "pico_socket_multicast.h"
tass 152:a3d286bf94e5 24 #include "pico_fragments.h"
tass 68:0847e35d08a6 25
tass 68:0847e35d08a6 26 #ifdef PICO_SUPPORT_IPV4
tass 68:0847e35d08a6 27
tass 68:0847e35d08a6 28 #ifdef PICO_SUPPORT_MCAST
TASS Belgium NV 131:4758606c9316 29 # define ip_mcast_dbg(...) do {} while(0) /* so_mcast_dbg in pico_socket.c */
tass picotcp@tass.be 149:5f4cb161cec3 30 /* #define ip_mcast_dbg dbg */
tass 68:0847e35d08a6 31 # define PICO_MCAST_ALL_HOSTS long_be(0xE0000001) /* 224.0.0.1 */
tass 68:0847e35d08a6 32 /* Default network interface for multicast transmission */
tass 68:0847e35d08a6 33 static struct pico_ipv4_link *mcast_default_link = NULL;
tass 68:0847e35d08a6 34 #endif
tass 152:a3d286bf94e5 35 #ifdef PICO_SUPPORT_IPV4FRAG
tass picotcp@tass.be 149:5f4cb161cec3 36 /* # define reassembly_dbg dbg */
TASS Belgium NV 131:4758606c9316 37 # define reassembly_dbg(...) do {} while(0)
tass 68:0847e35d08a6 38 #endif
tass 68:0847e35d08a6 39
tass 68:0847e35d08a6 40 /* Queues */
TASS Belgium NV 131:4758606c9316 41 static struct pico_queue in = {
TASS Belgium NV 131:4758606c9316 42 0
TASS Belgium NV 131:4758606c9316 43 };
TASS Belgium NV 131:4758606c9316 44 static struct pico_queue out = {
TASS Belgium NV 131:4758606c9316 45 0
TASS Belgium NV 131:4758606c9316 46 };
tass 68:0847e35d08a6 47
tass 68:0847e35d08a6 48 /* Functions */
TASS Belgium NV 131:4758606c9316 49 static int ipv4_route_compare(void *ka, void *kb);
tass picotcp@tass.be 149:5f4cb161cec3 50 static struct pico_frame *pico_ipv4_alloc(struct pico_protocol *self, uint16_t size);
tass 68:0847e35d08a6 51
tass 152:a3d286bf94e5 52
tass 152:a3d286bf94e5 53 int pico_ipv4_compare(struct pico_ip4 *a, struct pico_ip4 *b)
tass 152:a3d286bf94e5 54 {
tass 152:a3d286bf94e5 55 if (a->addr < b->addr)
tass 152:a3d286bf94e5 56 return -1;
tass 152:a3d286bf94e5 57
tass 152:a3d286bf94e5 58 if (a->addr > b->addr)
tass 152:a3d286bf94e5 59 return 1;
tass 152:a3d286bf94e5 60
tass 152:a3d286bf94e5 61 return 0;
tass 152:a3d286bf94e5 62 }
tass 152:a3d286bf94e5 63
tass 68:0847e35d08a6 64 int pico_ipv4_to_string(char *ipbuf, const uint32_t ip)
tass 68:0847e35d08a6 65 {
TASS Belgium NV 131:4758606c9316 66 const unsigned char *addr = (const unsigned char *) &ip;
TASS Belgium NV 131:4758606c9316 67 int i;
tass 68:0847e35d08a6 68
TASS Belgium NV 131:4758606c9316 69 if (!ipbuf) {
TASS Belgium NV 131:4758606c9316 70 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 71 return -1;
TASS Belgium NV 131:4758606c9316 72 }
tass 68:0847e35d08a6 73
TASS Belgium NV 131:4758606c9316 74 for(i = 0; i < 4; i++)
TASS Belgium NV 131:4758606c9316 75 {
tass 152:a3d286bf94e5 76 if (addr[i] > 99) {
TASS Belgium NV 131:4758606c9316 77 *ipbuf++ = (char)('0' + (addr[i] / 100));
TASS Belgium NV 131:4758606c9316 78 *ipbuf++ = (char)('0' + ((addr[i] % 100) / 10));
TASS Belgium NV 131:4758606c9316 79 *ipbuf++ = (char)('0' + ((addr[i] % 100) % 10));
tass 152:a3d286bf94e5 80 } else if (addr[i] > 9) {
TASS Belgium NV 131:4758606c9316 81 *ipbuf++ = (char)('0' + (addr[i] / 10));
TASS Belgium NV 131:4758606c9316 82 *ipbuf++ = (char)('0' + (addr[i] % 10));
tass 152:a3d286bf94e5 83 } else {
TASS Belgium NV 131:4758606c9316 84 *ipbuf++ = (char)('0' + addr[i]);
TASS Belgium NV 131:4758606c9316 85 }
TASS Belgium NV 131:4758606c9316 86
tass 152:a3d286bf94e5 87 if (i < 3)
TASS Belgium NV 131:4758606c9316 88 *ipbuf++ = '.';
tass 68:0847e35d08a6 89 }
TASS Belgium NV 131:4758606c9316 90 *ipbuf = '\0';
TASS Belgium NV 131:4758606c9316 91
TASS Belgium NV 131:4758606c9316 92 return 0;
tass 68:0847e35d08a6 93 }
TASS Belgium NV 131:4758606c9316 94
tass picotcp@tass.be 149:5f4cb161cec3 95 static int pico_string_check_null_args(const char *ipstr, uint32_t *ip)
tass picotcp@tass.be 149:5f4cb161cec3 96 {
tass picotcp@tass.be 149:5f4cb161cec3 97
tass 152:a3d286bf94e5 98 if (!ipstr || !ip) {
tass picotcp@tass.be 149:5f4cb161cec3 99 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 100 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 101 }
tass picotcp@tass.be 149:5f4cb161cec3 102
tass picotcp@tass.be 149:5f4cb161cec3 103 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 104
tass picotcp@tass.be 149:5f4cb161cec3 105 }
tass picotcp@tass.be 149:5f4cb161cec3 106
tass 68:0847e35d08a6 107 int pico_string_to_ipv4(const char *ipstr, uint32_t *ip)
tass 68:0847e35d08a6 108 {
tass 152:a3d286bf94e5 109 unsigned char buf[PICO_SIZE_IP4] = {
TASS Belgium NV 131:4758606c9316 110 0
TASS Belgium NV 131:4758606c9316 111 };
TASS Belgium NV 131:4758606c9316 112 int cnt = 0;
TASS Belgium NV 131:4758606c9316 113 char p;
tass 68:0847e35d08a6 114
tass picotcp@tass.be 149:5f4cb161cec3 115 if (pico_string_check_null_args(ipstr, ip) < 0)
TASS Belgium NV 131:4758606c9316 116 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 117
tass 152:a3d286bf94e5 118 while((p = *ipstr++) != 0 && cnt < PICO_SIZE_IP4)
TASS Belgium NV 131:4758606c9316 119 {
tass 152:a3d286bf94e5 120 if (pico_is_digit(p)) {
TASS Belgium NV 131:4758606c9316 121 buf[cnt] = (uint8_t)((10 * buf[cnt]) + (p - '0'));
tass 152:a3d286bf94e5 122 } else if (p == '.') {
TASS Belgium NV 131:4758606c9316 123 cnt++;
tass 152:a3d286bf94e5 124 } else {
TASS Belgium NV 131:4758606c9316 125 return -1;
TASS Belgium NV 131:4758606c9316 126 }
TASS Belgium NV 131:4758606c9316 127 }
TASS Belgium NV 131:4758606c9316 128 /* Handle short notation */
tass 152:a3d286bf94e5 129 if (cnt == 1) {
TASS Belgium NV 131:4758606c9316 130 buf[3] = buf[1];
TASS Belgium NV 131:4758606c9316 131 buf[1] = 0;
TASS Belgium NV 131:4758606c9316 132 buf[2] = 0;
tass 152:a3d286bf94e5 133 } else if (cnt == 2) {
TASS Belgium NV 131:4758606c9316 134 buf[3] = buf[2];
TASS Belgium NV 131:4758606c9316 135 buf[2] = 0;
tass 152:a3d286bf94e5 136 } else if (cnt != 3) {
TASS Belgium NV 131:4758606c9316 137 /* String could not be parsed, return error */
TASS Belgium NV 131:4758606c9316 138 return -1;
TASS Belgium NV 131:4758606c9316 139 }
tass 68:0847e35d08a6 140
TASS Belgium NV 131:4758606c9316 141 *ip = long_from(buf);
tass 68:0847e35d08a6 142
TASS Belgium NV 131:4758606c9316 143 return 0;
TASS Belgium NV 131:4758606c9316 144 }
tass 68:0847e35d08a6 145
tass 68:0847e35d08a6 146 int pico_ipv4_valid_netmask(uint32_t mask)
tass 68:0847e35d08a6 147 {
TASS Belgium NV 131:4758606c9316 148 int cnt = 0;
TASS Belgium NV 131:4758606c9316 149 int end = 0;
TASS Belgium NV 131:4758606c9316 150 int i;
TASS Belgium NV 131:4758606c9316 151 uint32_t mask_swap = long_be(mask);
tass 68:0847e35d08a6 152
TASS Belgium NV 131:4758606c9316 153 /*
TASS Belgium NV 131:4758606c9316 154 * Swap bytes for convenient parsing
TASS Belgium NV 131:4758606c9316 155 * e.g. 0x..f8ff will become 0xfff8..
TASS Belgium NV 131:4758606c9316 156 * Then, we count the consecutive bits
TASS Belgium NV 131:4758606c9316 157 *
TASS Belgium NV 131:4758606c9316 158 * */
tass 68:0847e35d08a6 159
TASS Belgium NV 131:4758606c9316 160 for(i = 0; i < 32; i++) {
tass 152:a3d286bf94e5 161 if ((mask_swap << i) & 0x80000000) {
tass 152:a3d286bf94e5 162 if (end) {
TASS Belgium NV 131:4758606c9316 163 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 164 return -1;
TASS Belgium NV 131:4758606c9316 165 }
TASS Belgium NV 131:4758606c9316 166
TASS Belgium NV 131:4758606c9316 167 cnt++;
tass 152:a3d286bf94e5 168 } else {
TASS Belgium NV 131:4758606c9316 169 end = 1;
TASS Belgium NV 131:4758606c9316 170 }
TASS Belgium NV 131:4758606c9316 171 }
TASS Belgium NV 131:4758606c9316 172 return cnt;
tass 68:0847e35d08a6 173 }
tass 68:0847e35d08a6 174
TASS Belgium NV 131:4758606c9316 175 int pico_ipv4_is_unicast(uint32_t address)
tass 68:0847e35d08a6 176 {
TASS Belgium NV 131:4758606c9316 177 const unsigned char *addr = (unsigned char *) &address;
tass 152:a3d286bf94e5 178 if ((addr[0] & 0xe0) == 0xe0)
TASS Belgium NV 131:4758606c9316 179 return 0; /* multicast */
TASS Belgium NV 131:4758606c9316 180
TASS Belgium NV 131:4758606c9316 181 return 1;
tass 68:0847e35d08a6 182 }
tass 68:0847e35d08a6 183
TASS Belgium NV 131:4758606c9316 184 int pico_ipv4_is_multicast(uint32_t address)
tass 68:0847e35d08a6 185 {
TASS Belgium NV 131:4758606c9316 186 const unsigned char *addr = (unsigned char *) &address;
tass 152:a3d286bf94e5 187 if ((addr[0] != 0xff) && ((addr[0] & 0xe0) == 0xe0))
TASS Belgium NV 131:4758606c9316 188 return 1; /* multicast */
TASS Belgium NV 131:4758606c9316 189
TASS Belgium NV 131:4758606c9316 190 return 0;
tass 68:0847e35d08a6 191 }
tass 68:0847e35d08a6 192
tass picotcp@tass.be 137:a1c8bfa9d691 193 int pico_ipv4_is_loopback(uint32_t address)
tass picotcp@tass.be 137:a1c8bfa9d691 194 {
tass picotcp@tass.be 137:a1c8bfa9d691 195 const unsigned char *addr = (unsigned char *) &address;
tass 152:a3d286bf94e5 196 if (addr[0] == 0x7f)
tass picotcp@tass.be 137:a1c8bfa9d691 197 return 1;
tass picotcp@tass.be 137:a1c8bfa9d691 198
tass picotcp@tass.be 137:a1c8bfa9d691 199 return 0;
tass picotcp@tass.be 137:a1c8bfa9d691 200 }
tass picotcp@tass.be 137:a1c8bfa9d691 201
tass picotcp@tass.be 149:5f4cb161cec3 202 static int pico_ipv4_is_invalid_loopback(uint32_t address, struct pico_device *dev)
tass picotcp@tass.be 149:5f4cb161cec3 203 {
tass picotcp@tass.be 149:5f4cb161cec3 204 return pico_ipv4_is_loopback(address) && ((!dev) || strcmp(dev->name, "loop"));
tass picotcp@tass.be 149:5f4cb161cec3 205 }
tass picotcp@tass.be 149:5f4cb161cec3 206
tass picotcp@tass.be 149:5f4cb161cec3 207 int pico_ipv4_is_valid_src(uint32_t address, struct pico_device *dev)
tass picotcp@tass.be 137:a1c8bfa9d691 208 {
tass picotcp@tass.be 137:a1c8bfa9d691 209 if (pico_ipv4_is_broadcast(address)) {
tass picotcp@tass.be 137:a1c8bfa9d691 210 dbg("Source is a broadcast address, discard packet\n");
tass picotcp@tass.be 137:a1c8bfa9d691 211 return 0;
tass 152:a3d286bf94e5 212 } else if ( pico_ipv4_is_multicast(address)) {
tass picotcp@tass.be 137:a1c8bfa9d691 213 dbg("Source is a multicast address, discard packet\n");
tass picotcp@tass.be 137:a1c8bfa9d691 214 return 0;
tass 152:a3d286bf94e5 215 } else if (pico_ipv4_is_invalid_loopback(address, dev)) {
tass picotcp@tass.be 137:a1c8bfa9d691 216 dbg("Source is a loopback address, discard packet\n");
tass picotcp@tass.be 137:a1c8bfa9d691 217 return 0;
tass 152:a3d286bf94e5 218 } else {
tass 152:a3d286bf94e5 219 #ifdef PICO_SUPPORT_AODV
tass 152:a3d286bf94e5 220 union pico_address src;
tass 152:a3d286bf94e5 221 src.ip4.addr = address;
tass 152:a3d286bf94e5 222 pico_aodv_refresh(&src);
tass 152:a3d286bf94e5 223 #endif
tass picotcp@tass.be 137:a1c8bfa9d691 224 return 1;
tass picotcp@tass.be 137:a1c8bfa9d691 225 }
tass picotcp@tass.be 137:a1c8bfa9d691 226 }
tass picotcp@tass.be 137:a1c8bfa9d691 227
tass 68:0847e35d08a6 228 static int pico_ipv4_checksum(struct pico_frame *f)
tass 68:0847e35d08a6 229 {
TASS Belgium NV 131:4758606c9316 230 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
TASS Belgium NV 131:4758606c9316 231 if (!hdr)
TASS Belgium NV 131:4758606c9316 232 return -1;
TASS Belgium NV 131:4758606c9316 233
TASS Belgium NV 131:4758606c9316 234 hdr->crc = 0;
TASS Belgium NV 131:4758606c9316 235 hdr->crc = short_be(pico_checksum(hdr, f->net_len));
TASS Belgium NV 131:4758606c9316 236 return 0;
tass 68:0847e35d08a6 237 }
tass 68:0847e35d08a6 238
tass 68:0847e35d08a6 239
tass 68:0847e35d08a6 240 #ifdef PICO_SUPPORT_CRC
tass 68:0847e35d08a6 241 static inline int pico_ipv4_crc_check(struct pico_frame *f)
tass 68:0847e35d08a6 242 {
TASS Belgium NV 131:4758606c9316 243 uint16_t checksum_invalid = 1;
TASS Belgium NV 131:4758606c9316 244 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass 68:0847e35d08a6 245
TASS Belgium NV 131:4758606c9316 246 checksum_invalid = short_be(pico_checksum(hdr, f->net_len));
TASS Belgium NV 131:4758606c9316 247 if (checksum_invalid) {
TASS Belgium NV 131:4758606c9316 248 dbg("IP: checksum failed!\n");
TASS Belgium NV 131:4758606c9316 249 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 250 return 0;
TASS Belgium NV 131:4758606c9316 251 }
TASS Belgium NV 131:4758606c9316 252
TASS Belgium NV 131:4758606c9316 253 return 1;
tass 68:0847e35d08a6 254 }
tass 68:0847e35d08a6 255 #else
tass 68:0847e35d08a6 256 static inline int pico_ipv4_crc_check(struct pico_frame *f)
tass 68:0847e35d08a6 257 {
TASS Belgium NV 131:4758606c9316 258 IGNORE_PARAMETER(f);
TASS Belgium NV 131:4758606c9316 259 return 1;
tass 68:0847e35d08a6 260 }
tass 68:0847e35d08a6 261 #endif /* PICO_SUPPORT_CRC */
tass 68:0847e35d08a6 262
tass 68:0847e35d08a6 263 static int pico_ipv4_forward(struct pico_frame *f);
tass 68:0847e35d08a6 264 #ifdef PICO_SUPPORT_MCAST
tass 68:0847e35d08a6 265 static int pico_ipv4_mcast_filter(struct pico_frame *f);
tass 68:0847e35d08a6 266 #endif
tass 68:0847e35d08a6 267
tass 68:0847e35d08a6 268 static int ipv4_link_compare(void *ka, void *kb)
tass 68:0847e35d08a6 269 {
TASS Belgium NV 131:4758606c9316 270 struct pico_ipv4_link *a = ka, *b = kb;
tass 152:a3d286bf94e5 271 int cmp = pico_ipv4_compare(&a->address, &b->address);
tass 152:a3d286bf94e5 272 if (cmp)
tass 152:a3d286bf94e5 273 return cmp;
tass 68:0847e35d08a6 274
TASS Belgium NV 131:4758606c9316 275 /* zero can be assigned multiple times (e.g. for DHCP) */
TASS Belgium NV 131:4758606c9316 276 if (a->dev != NULL && b->dev != NULL && a->address.addr == PICO_IP4_ANY && b->address.addr == PICO_IP4_ANY) {
TASS Belgium NV 131:4758606c9316 277 if (a->dev < b->dev)
TASS Belgium NV 131:4758606c9316 278 return -1;
TASS Belgium NV 131:4758606c9316 279
TASS Belgium NV 131:4758606c9316 280 if (a->dev > b->dev)
TASS Belgium NV 131:4758606c9316 281 return 1;
TASS Belgium NV 131:4758606c9316 282 }
TASS Belgium NV 131:4758606c9316 283
TASS Belgium NV 131:4758606c9316 284 return 0;
tass 68:0847e35d08a6 285 }
tass 68:0847e35d08a6 286
tass 68:0847e35d08a6 287 PICO_TREE_DECLARE(Tree_dev_link, ipv4_link_compare);
tass 68:0847e35d08a6 288
tass picotcp@tass.be 149:5f4cb161cec3 289 static int pico_ipv4_process_bcast_in(struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 290 {
tass picotcp@tass.be 149:5f4cb161cec3 291 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass picotcp@tass.be 149:5f4cb161cec3 292 #ifdef PICO_SUPPORT_UDP
tass picotcp@tass.be 149:5f4cb161cec3 293 if (pico_ipv4_is_broadcast(hdr->dst.addr) && (hdr->proto == PICO_PROTO_UDP)) {
tass picotcp@tass.be 149:5f4cb161cec3 294 /* Receiving UDP broadcast datagram */
tass picotcp@tass.be 149:5f4cb161cec3 295 f->flags |= PICO_FRAME_FLAG_BCAST;
tass picotcp@tass.be 149:5f4cb161cec3 296 pico_enqueue(pico_proto_udp.q_in, f);
tass picotcp@tass.be 149:5f4cb161cec3 297 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 298 }
tass picotcp@tass.be 149:5f4cb161cec3 299
tass 152:a3d286bf94e5 300 #endif
tass 152:a3d286bf94e5 301
tass 152:a3d286bf94e5 302 #ifdef PICO_SUPPORT_ICMP4
tass picotcp@tass.be 149:5f4cb161cec3 303 if (pico_ipv4_is_broadcast(hdr->dst.addr) && (hdr->proto == PICO_PROTO_ICMP4)) {
tass picotcp@tass.be 149:5f4cb161cec3 304 /* Receiving ICMP4 bcast packet */
tass picotcp@tass.be 149:5f4cb161cec3 305 f->flags |= PICO_FRAME_FLAG_BCAST;
tass picotcp@tass.be 149:5f4cb161cec3 306 pico_enqueue(pico_proto_icmp4.q_in, f);
tass picotcp@tass.be 149:5f4cb161cec3 307 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 308 }
tass picotcp@tass.be 149:5f4cb161cec3 309
tass picotcp@tass.be 149:5f4cb161cec3 310 #endif
tass picotcp@tass.be 149:5f4cb161cec3 311 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 312 }
tass picotcp@tass.be 149:5f4cb161cec3 313
tass picotcp@tass.be 149:5f4cb161cec3 314 static int pico_ipv4_process_mcast_in(struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 315 {
tass picotcp@tass.be 149:5f4cb161cec3 316 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass picotcp@tass.be 149:5f4cb161cec3 317 if (pico_ipv4_is_multicast(hdr->dst.addr)) {
tass 152:a3d286bf94e5 318 #ifdef PICO_SUPPORT_IGMP
tass picotcp@tass.be 149:5f4cb161cec3 319 /* Receiving UDP multicast datagram TODO set f->flags? */
tass picotcp@tass.be 149:5f4cb161cec3 320 if (hdr->proto == PICO_PROTO_IGMP) {
tass picotcp@tass.be 149:5f4cb161cec3 321 ip_mcast_dbg("MCAST: received IGMP message\n");
tass picotcp@tass.be 149:5f4cb161cec3 322 pico_transport_receive(f, PICO_PROTO_IGMP);
tass picotcp@tass.be 149:5f4cb161cec3 323 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 324 } else if ((pico_ipv4_mcast_filter(f) == 0) && (hdr->proto == PICO_PROTO_UDP)) {
tass picotcp@tass.be 149:5f4cb161cec3 325 pico_enqueue(pico_proto_udp.q_in, f);
tass picotcp@tass.be 149:5f4cb161cec3 326 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 327 }
tass picotcp@tass.be 149:5f4cb161cec3 328
tass picotcp@tass.be 149:5f4cb161cec3 329 #endif
tass picotcp@tass.be 149:5f4cb161cec3 330 pico_frame_discard(f);
tass picotcp@tass.be 149:5f4cb161cec3 331 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 332 }
tass picotcp@tass.be 149:5f4cb161cec3 333
tass picotcp@tass.be 149:5f4cb161cec3 334 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 335 }
tass picotcp@tass.be 149:5f4cb161cec3 336
tass picotcp@tass.be 149:5f4cb161cec3 337 static int pico_ipv4_process_local_unicast_in(struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 338 {
tass picotcp@tass.be 149:5f4cb161cec3 339 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass picotcp@tass.be 149:5f4cb161cec3 340 struct pico_ipv4_link test = {
tass picotcp@tass.be 149:5f4cb161cec3 341 .address = {.addr = PICO_IP4_ANY}, .dev = NULL
tass picotcp@tass.be 149:5f4cb161cec3 342 };
tass picotcp@tass.be 149:5f4cb161cec3 343 if (pico_ipv4_link_find(&hdr->dst)) {
tass picotcp@tass.be 149:5f4cb161cec3 344 if (pico_ipv4_nat_inbound(f, &hdr->dst) == 0)
tass picotcp@tass.be 149:5f4cb161cec3 345 pico_enqueue(pico_proto_ipv4.q_in, f); /* dst changed, reprocess */
tass picotcp@tass.be 149:5f4cb161cec3 346 else
tass picotcp@tass.be 149:5f4cb161cec3 347 pico_transport_receive(f, hdr->proto);
tass picotcp@tass.be 149:5f4cb161cec3 348
tass picotcp@tass.be 149:5f4cb161cec3 349 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 350 } else if (pico_tree_findKey(&Tree_dev_link, &test)) {
tass picotcp@tass.be 149:5f4cb161cec3 351 #ifdef PICO_SUPPORT_UDP
tass picotcp@tass.be 149:5f4cb161cec3 352 /* address of this device is apparently 0.0.0.0; might be a DHCP packet */
tass picotcp@tass.be 149:5f4cb161cec3 353 /* XXX KRO: is obsolete. Broadcast flag is set on outgoing DHCP messages.
tass picotcp@tass.be 149:5f4cb161cec3 354 * incomming DHCP messages are to be broadcasted. Our current DHCP server
tass picotcp@tass.be 149:5f4cb161cec3 355 * implementation does not take this flag into account yet though ... */
tass picotcp@tass.be 149:5f4cb161cec3 356 pico_enqueue(pico_proto_udp.q_in, f);
tass picotcp@tass.be 149:5f4cb161cec3 357 return 1;
tass picotcp@tass.be 149:5f4cb161cec3 358 #endif
tass picotcp@tass.be 149:5f4cb161cec3 359 }
tass picotcp@tass.be 149:5f4cb161cec3 360
tass picotcp@tass.be 149:5f4cb161cec3 361 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 362 }
tass picotcp@tass.be 149:5f4cb161cec3 363
tass picotcp@tass.be 149:5f4cb161cec3 364 static void pico_ipv4_process_finally_try_forward(struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 365 {
tass picotcp@tass.be 149:5f4cb161cec3 366 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass 152:a3d286bf94e5 367 if ((pico_ipv4_is_broadcast(hdr->dst.addr)) || ((f->flags & PICO_FRAME_FLAG_BCAST)!= 0)) {
tass picotcp@tass.be 149:5f4cb161cec3 368 /* don't forward broadcast frame, discard! */
tass picotcp@tass.be 149:5f4cb161cec3 369 pico_frame_discard(f);
tass picotcp@tass.be 149:5f4cb161cec3 370 } else if (pico_ipv4_forward(f) != 0) {
tass picotcp@tass.be 149:5f4cb161cec3 371 pico_frame_discard(f);
tass picotcp@tass.be 149:5f4cb161cec3 372 /* dbg("Forward failed.\n"); */
tass picotcp@tass.be 149:5f4cb161cec3 373 }
tass picotcp@tass.be 149:5f4cb161cec3 374 }
tass picotcp@tass.be 149:5f4cb161cec3 375
tass picotcp@tass.be 149:5f4cb161cec3 376
tass picotcp@tass.be 149:5f4cb161cec3 377
tass 68:0847e35d08a6 378 static int pico_ipv4_process_in(struct pico_protocol *self, struct pico_frame *f)
tass 68:0847e35d08a6 379 {
TASS Belgium NV 131:4758606c9316 380 uint8_t option_len = 0;
TASS Belgium NV 131:4758606c9316 381 int ret = 0;
TASS Belgium NV 131:4758606c9316 382 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass 152:a3d286bf94e5 383 uint16_t max_allowed = (uint16_t) ((int)f->buffer_len - (f->net_hdr - f->buffer) - (int)PICO_SIZE_IP4HDR);
tass 152:a3d286bf94e5 384 uint16_t flag = short_be(hdr->frag);
tass 68:0847e35d08a6 385
tass 152:a3d286bf94e5 386 (void)self;
TASS Belgium NV 131:4758606c9316 387 /* NAT needs transport header information */
tass 152:a3d286bf94e5 388 if (((hdr->vhl) & 0x0F) > 5) {
TASS Belgium NV 131:4758606c9316 389 option_len = (uint8_t)(4 * (((hdr->vhl) & 0x0F) - 5));
TASS Belgium NV 131:4758606c9316 390 }
TASS Belgium NV 131:4758606c9316 391
TASS Belgium NV 131:4758606c9316 392 f->transport_hdr = ((uint8_t *)f->net_hdr) + PICO_SIZE_IP4HDR + option_len;
TASS Belgium NV 131:4758606c9316 393 f->transport_len = (uint16_t)(short_be(hdr->len) - PICO_SIZE_IP4HDR - option_len);
TASS Belgium NV 131:4758606c9316 394 f->net_len = (uint16_t)(PICO_SIZE_IP4HDR + option_len);
tass 68:0847e35d08a6 395
tass 152:a3d286bf94e5 396 if (f->transport_len > max_allowed) {
tass 152:a3d286bf94e5 397 pico_frame_discard(f);
tass 152:a3d286bf94e5 398 return 0; /* Packet is discarded due to unfeasible length */
tass 152:a3d286bf94e5 399 }
tass 152:a3d286bf94e5 400
tass 68:0847e35d08a6 401 #ifdef PICO_SUPPORT_IPFILTER
TASS Belgium NV 131:4758606c9316 402 if (ipfilter(f)) {
TASS Belgium NV 131:4758606c9316 403 /*pico_frame is discarded as result of the filtering*/
TASS Belgium NV 131:4758606c9316 404 return 0;
TASS Belgium NV 131:4758606c9316 405 }
TASS Belgium NV 131:4758606c9316 406
tass 68:0847e35d08a6 407 #endif
tass 68:0847e35d08a6 408
tass 152:a3d286bf94e5 409
TASS Belgium NV 131:4758606c9316 410 /* ret == 1 indicates to continue the function */
TASS Belgium NV 131:4758606c9316 411 ret = pico_ipv4_crc_check(f);
TASS Belgium NV 131:4758606c9316 412 if (ret < 1)
TASS Belgium NV 131:4758606c9316 413 return ret;
TASS Belgium NV 131:4758606c9316 414
tass picotcp@tass.be 137:a1c8bfa9d691 415 /* Validate source IP address. Discard quietly if invalid */
tass picotcp@tass.be 149:5f4cb161cec3 416 if (!pico_ipv4_is_valid_src(hdr->src.addr, f->dev)) {
TASS Belgium NV 131:4758606c9316 417 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 418 return 0;
TASS Belgium NV 131:4758606c9316 419 }
TASS Belgium NV 131:4758606c9316 420
tass 152:a3d286bf94e5 421 if (hdr->frag & short_be(PICO_IPV4_EVIL)) {
tass 152:a3d286bf94e5 422 (void)pico_icmp4_param_problem(f, 0);
TASS Belgium NV 131:4758606c9316 423 pico_frame_discard(f); /* RFC 3514 */
TASS Belgium NV 131:4758606c9316 424 return 0;
TASS Belgium NV 131:4758606c9316 425 }
TASS Belgium NV 131:4758606c9316 426
tass 152:a3d286bf94e5 427 if ((hdr->vhl & 0x0f) < 5) {
tass 152:a3d286bf94e5 428 /* RFC 791: IHL minimum value is 5 */
tass 152:a3d286bf94e5 429 (void)pico_icmp4_param_problem(f, 0);
tass 152:a3d286bf94e5 430 pico_frame_discard(f);
tass 152:a3d286bf94e5 431 return 0;
tass 152:a3d286bf94e5 432 }
tass 152:a3d286bf94e5 433
tass 152:a3d286bf94e5 434 if (flag & (PICO_IPV4_MOREFRAG | PICO_IPV4_FRAG_MASK))
tass 152:a3d286bf94e5 435 {
tass 152:a3d286bf94e5 436 #ifdef PICO_SUPPORT_IPV4FRAG
tass 152:a3d286bf94e5 437 pico_ipv4_process_frag(hdr, f, hdr ? hdr->proto : 0 );
tass 152:a3d286bf94e5 438 /* Frame can be discarded, frag will handle its own copy */
tass 152:a3d286bf94e5 439 #endif
tass 152:a3d286bf94e5 440 /* We do not support fragmentation, discard quietly */
tass 152:a3d286bf94e5 441 pico_frame_discard(f);
tass 152:a3d286bf94e5 442 return 0;
tass 152:a3d286bf94e5 443 }
tass 152:a3d286bf94e5 444
tass picotcp@tass.be 149:5f4cb161cec3 445 if (pico_ipv4_process_bcast_in(f) > 0)
tass picotcp@tass.be 149:5f4cb161cec3 446 return 0;
TASS Belgium NV 131:4758606c9316 447
tass picotcp@tass.be 149:5f4cb161cec3 448 if (pico_ipv4_process_mcast_in(f) > 0)
tass picotcp@tass.be 149:5f4cb161cec3 449 return 0;
TASS Belgium NV 131:4758606c9316 450
tass picotcp@tass.be 149:5f4cb161cec3 451 if (pico_ipv4_process_local_unicast_in(f) > 0)
tass picotcp@tass.be 149:5f4cb161cec3 452 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 453
tass picotcp@tass.be 149:5f4cb161cec3 454 pico_ipv4_process_finally_try_forward(f);
TASS Belgium NV 131:4758606c9316 455
TASS Belgium NV 131:4758606c9316 456 return 0;
tass 68:0847e35d08a6 457 }
tass 68:0847e35d08a6 458
tass 68:0847e35d08a6 459 PICO_TREE_DECLARE(Routes, ipv4_route_compare);
tass 68:0847e35d08a6 460
tass 68:0847e35d08a6 461
tass 68:0847e35d08a6 462 static int pico_ipv4_process_out(struct pico_protocol *self, struct pico_frame *f)
tass 68:0847e35d08a6 463 {
TASS Belgium NV 131:4758606c9316 464 IGNORE_PARAMETER(self);
TASS Belgium NV 131:4758606c9316 465 f->start = (uint8_t*) f->net_hdr;
tass 152:a3d286bf94e5 466 #ifdef PICO_SUPPORT_IPFILTER
TASS Belgium NV 131:4758606c9316 467 if (ipfilter(f)) {
TASS Belgium NV 131:4758606c9316 468 /*pico_frame is discarded as result of the filtering*/
TASS Belgium NV 131:4758606c9316 469 return 0;
TASS Belgium NV 131:4758606c9316 470 }
TASS Belgium NV 131:4758606c9316 471
tass 152:a3d286bf94e5 472 #endif
TASS Belgium NV 131:4758606c9316 473 return pico_sendto_dev(f);
tass 68:0847e35d08a6 474 }
tass 68:0847e35d08a6 475
tass 68:0847e35d08a6 476
tass 70:cd218dd180e5 477 static struct pico_frame *pico_ipv4_alloc(struct pico_protocol *self, uint16_t size)
tass 68:0847e35d08a6 478 {
TASS Belgium NV 131:4758606c9316 479 struct pico_frame *f = pico_frame_alloc(size + PICO_SIZE_IP4HDR + PICO_SIZE_ETHHDR);
TASS Belgium NV 131:4758606c9316 480 IGNORE_PARAMETER(self);
TASS Belgium NV 131:4758606c9316 481
TASS Belgium NV 131:4758606c9316 482 if (!f)
TASS Belgium NV 131:4758606c9316 483 return NULL;
tass 68:0847e35d08a6 484
TASS Belgium NV 131:4758606c9316 485 f->datalink_hdr = f->buffer;
TASS Belgium NV 131:4758606c9316 486 f->net_hdr = f->buffer + PICO_SIZE_ETHHDR;
TASS Belgium NV 131:4758606c9316 487 f->net_len = PICO_SIZE_IP4HDR;
TASS Belgium NV 131:4758606c9316 488 f->transport_hdr = f->net_hdr + PICO_SIZE_IP4HDR;
TASS Belgium NV 131:4758606c9316 489 f->transport_len = size;
TASS Belgium NV 131:4758606c9316 490 f->len = size + PICO_SIZE_IP4HDR;
TASS Belgium NV 131:4758606c9316 491 return f;
tass 68:0847e35d08a6 492 }
tass 68:0847e35d08a6 493
tass 68:0847e35d08a6 494 static int pico_ipv4_frame_sock_push(struct pico_protocol *self, struct pico_frame *f);
tass 68:0847e35d08a6 495
tass 68:0847e35d08a6 496 /* Interface: protocol definition */
tass 68:0847e35d08a6 497 struct pico_protocol pico_proto_ipv4 = {
TASS Belgium NV 131:4758606c9316 498 .name = "ipv4",
TASS Belgium NV 131:4758606c9316 499 .proto_number = PICO_PROTO_IPV4,
TASS Belgium NV 131:4758606c9316 500 .layer = PICO_LAYER_NETWORK,
TASS Belgium NV 131:4758606c9316 501 .alloc = pico_ipv4_alloc,
TASS Belgium NV 131:4758606c9316 502 .process_in = pico_ipv4_process_in,
TASS Belgium NV 131:4758606c9316 503 .process_out = pico_ipv4_process_out,
TASS Belgium NV 131:4758606c9316 504 .push = pico_ipv4_frame_sock_push,
TASS Belgium NV 131:4758606c9316 505 .q_in = &in,
TASS Belgium NV 131:4758606c9316 506 .q_out = &out,
tass 68:0847e35d08a6 507 };
tass 68:0847e35d08a6 508
tass 68:0847e35d08a6 509
TASS Belgium NV 131:4758606c9316 510 static int ipv4_route_compare(void *ka, void *kb)
tass 68:0847e35d08a6 511 {
TASS Belgium NV 131:4758606c9316 512 struct pico_ipv4_route *a = ka, *b = kb;
tass picotcp@tass.be 149:5f4cb161cec3 513 uint32_t a_nm, b_nm;
tass 152:a3d286bf94e5 514 int cmp;
tass picotcp@tass.be 149:5f4cb161cec3 515
tass picotcp@tass.be 149:5f4cb161cec3 516 a_nm = long_be(a->netmask.addr);
tass picotcp@tass.be 149:5f4cb161cec3 517 b_nm = long_be(b->netmask.addr);
tass 68:0847e35d08a6 518
TASS Belgium NV 131:4758606c9316 519 /* Routes are sorted by (host side) netmask len, then by addr, then by metric. */
tass picotcp@tass.be 149:5f4cb161cec3 520 if (a_nm < b_nm)
TASS Belgium NV 131:4758606c9316 521 return -1;
tass 68:0847e35d08a6 522
tass picotcp@tass.be 149:5f4cb161cec3 523 if (b_nm < a_nm)
TASS Belgium NV 131:4758606c9316 524 return 1;
tass 68:0847e35d08a6 525
tass 152:a3d286bf94e5 526 cmp = pico_ipv4_compare(&a->dest, &b->dest);
tass 152:a3d286bf94e5 527 if (cmp)
tass 152:a3d286bf94e5 528 return cmp;
tass 68:0847e35d08a6 529
TASS Belgium NV 131:4758606c9316 530 if (a->metric < b->metric)
TASS Belgium NV 131:4758606c9316 531 return -1;
tass 68:0847e35d08a6 532
TASS Belgium NV 131:4758606c9316 533 if (a->metric > b->metric)
TASS Belgium NV 131:4758606c9316 534 return 1;
tass 68:0847e35d08a6 535
TASS Belgium NV 131:4758606c9316 536 return 0;
tass 68:0847e35d08a6 537 }
tass 68:0847e35d08a6 538
tass 152:a3d286bf94e5 539
tass 152:a3d286bf94e5 540 static struct pico_ipv4_route default_bcast_route = {
tass 152:a3d286bf94e5 541 .dest = {PICO_IP4_BCAST},
tass 152:a3d286bf94e5 542 .netmask = {PICO_IP4_BCAST},
tass 152:a3d286bf94e5 543 .gateway = { 0 },
tass 152:a3d286bf94e5 544 .link = NULL,
tass 152:a3d286bf94e5 545 .metric = 1000
tass 152:a3d286bf94e5 546 };
tass 152:a3d286bf94e5 547
tass 152:a3d286bf94e5 548 static struct pico_ipv4_route *route_find_default_bcast(void)
tass 152:a3d286bf94e5 549 {
tass 152:a3d286bf94e5 550 return &default_bcast_route;
tass 152:a3d286bf94e5 551 }
tass 152:a3d286bf94e5 552
tass 152:a3d286bf94e5 553
tass 68:0847e35d08a6 554 static struct pico_ipv4_route *route_find(const struct pico_ip4 *addr)
tass 68:0847e35d08a6 555 {
TASS Belgium NV 131:4758606c9316 556 struct pico_ipv4_route *r;
TASS Belgium NV 131:4758606c9316 557 struct pico_tree_node *index;
tass 68:0847e35d08a6 558
tass 152:a3d286bf94e5 559 if (addr->addr != PICO_IP4_BCAST) {
TASS Belgium NV 131:4758606c9316 560 pico_tree_foreach_reverse(index, &Routes) {
TASS Belgium NV 131:4758606c9316 561 r = index->keyValue;
TASS Belgium NV 131:4758606c9316 562 if ((addr->addr & (r->netmask.addr)) == (r->dest.addr)) {
TASS Belgium NV 131:4758606c9316 563 return r;
TASS Belgium NV 131:4758606c9316 564 }
TASS Belgium NV 131:4758606c9316 565 }
tass 152:a3d286bf94e5 566 return NULL;
tass 68:0847e35d08a6 567 }
tass 68:0847e35d08a6 568
tass 152:a3d286bf94e5 569 return route_find_default_bcast();
tass 68:0847e35d08a6 570 }
tass 68:0847e35d08a6 571
tass 68:0847e35d08a6 572 struct pico_ip4 pico_ipv4_route_get_gateway(struct pico_ip4 *addr)
tass 68:0847e35d08a6 573 {
TASS Belgium NV 131:4758606c9316 574 struct pico_ip4 nullip;
TASS Belgium NV 131:4758606c9316 575 struct pico_ipv4_route *route;
TASS Belgium NV 131:4758606c9316 576 nullip.addr = 0U;
tass 68:0847e35d08a6 577
tass 152:a3d286bf94e5 578 if (!addr) {
TASS Belgium NV 131:4758606c9316 579 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 580 return nullip;
TASS Belgium NV 131:4758606c9316 581 }
tass 68:0847e35d08a6 582
TASS Belgium NV 131:4758606c9316 583 route = route_find(addr);
TASS Belgium NV 131:4758606c9316 584 if (!route) {
TASS Belgium NV 131:4758606c9316 585 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 586 return nullip;
TASS Belgium NV 131:4758606c9316 587 }
TASS Belgium NV 131:4758606c9316 588 else
TASS Belgium NV 131:4758606c9316 589 return route->gateway;
tass 68:0847e35d08a6 590 }
tass 68:0847e35d08a6 591
tass 68:0847e35d08a6 592 struct pico_ip4 *pico_ipv4_source_find(const struct pico_ip4 *dst)
tass 68:0847e35d08a6 593 {
TASS Belgium NV 131:4758606c9316 594 struct pico_ip4 *myself = NULL;
TASS Belgium NV 131:4758606c9316 595 struct pico_ipv4_route *rt;
tass 152:a3d286bf94e5 596 #ifdef PICO_SUPPORT_AODV
tass 152:a3d286bf94e5 597 union pico_address node_address;
tass 152:a3d286bf94e5 598 node_address.ip4.addr = dst->addr;
tass 152:a3d286bf94e5 599 if (dst->addr && pico_ipv4_is_unicast(dst->addr))
tass 152:a3d286bf94e5 600 pico_aodv_lookup(&node_address);
TASS Belgium NV 131:4758606c9316 601
tass 152:a3d286bf94e5 602 #endif
tass 152:a3d286bf94e5 603
tass 152:a3d286bf94e5 604 if (!dst) {
TASS Belgium NV 131:4758606c9316 605 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 606 return NULL;
TASS Belgium NV 131:4758606c9316 607 }
tass 68:0847e35d08a6 608
TASS Belgium NV 131:4758606c9316 609 rt = route_find(dst);
tass 152:a3d286bf94e5 610 if (rt && rt->link) {
TASS Belgium NV 131:4758606c9316 611 myself = &rt->link->address;
tass 152:a3d286bf94e5 612 } else {
TASS Belgium NV 131:4758606c9316 613 pico_err = PICO_ERR_EHOSTUNREACH;
tass 152:a3d286bf94e5 614 }
tass 68:0847e35d08a6 615
TASS Belgium NV 131:4758606c9316 616 return myself;
tass 68:0847e35d08a6 617 }
tass 68:0847e35d08a6 618
tass 152:a3d286bf94e5 619 struct pico_device *pico_ipv4_source_dev_find(const struct pico_ip4 *dst)
tass 152:a3d286bf94e5 620 {
tass 152:a3d286bf94e5 621 struct pico_device *dev = NULL;
tass 152:a3d286bf94e5 622 struct pico_ipv4_route *rt;
tass 152:a3d286bf94e5 623
tass 152:a3d286bf94e5 624 if (!dst) {
tass 152:a3d286bf94e5 625 pico_err = PICO_ERR_EINVAL;
tass 152:a3d286bf94e5 626 return NULL;
tass 152:a3d286bf94e5 627 }
tass 152:a3d286bf94e5 628
tass 152:a3d286bf94e5 629 rt = route_find(dst);
tass 152:a3d286bf94e5 630 if (rt && rt->link) {
tass 152:a3d286bf94e5 631 dev = rt->link->dev;
tass 152:a3d286bf94e5 632 } else {
tass 152:a3d286bf94e5 633 pico_err = PICO_ERR_EHOSTUNREACH;
tass 152:a3d286bf94e5 634 }
tass 152:a3d286bf94e5 635
tass 152:a3d286bf94e5 636 return dev;
tass 152:a3d286bf94e5 637 }
tass 152:a3d286bf94e5 638
tass 68:0847e35d08a6 639
tass 68:0847e35d08a6 640 #ifdef PICO_SUPPORT_MCAST
tass 68:0847e35d08a6 641 /* link
TASS Belgium NV 131:4758606c9316 642 * |
tass 68:0847e35d08a6 643 * MCASTGroups
tass 68:0847e35d08a6 644 * | | |
tass 68:0847e35d08a6 645 * ------------ | ------------
tass 68:0847e35d08a6 646 * | | |
TASS Belgium NV 131:4758606c9316 647 * MCASTSources MCASTSources MCASTSources
tass 68:0847e35d08a6 648 * | | | | | | | | | | | |
tass 68:0847e35d08a6 649 * S S S S S S S S S S S S
tass 68:0847e35d08a6 650 *
tass 68:0847e35d08a6 651 * MCASTGroups: RBTree(mcast_group)
tass 68:0847e35d08a6 652 * MCASTSources: RBTree(source)
tass 68:0847e35d08a6 653 */
TASS Belgium NV 131:4758606c9316 654 static int ipv4_mcast_groups_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 655 {
TASS Belgium NV 131:4758606c9316 656 struct pico_mcast_group *a = ka, *b = kb;
tass 152:a3d286bf94e5 657 return pico_ipv4_compare(&a->mcast_addr, &b->mcast_addr);
tass 68:0847e35d08a6 658 }
tass 68:0847e35d08a6 659
tass 68:0847e35d08a6 660 static int ipv4_mcast_sources_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 661 {
TASS Belgium NV 131:4758606c9316 662 struct pico_ip4 *a = ka, *b = kb;
tass 152:a3d286bf94e5 663 return pico_ipv4_compare(a, b);
tass 68:0847e35d08a6 664 }
tass 68:0847e35d08a6 665
tass 68:0847e35d08a6 666 static void pico_ipv4_mcast_print_groups(struct pico_ipv4_link *mcast_link)
tass 68:0847e35d08a6 667 {
TASS Belgium NV 131:4758606c9316 668 uint16_t i = 0;
tass picotcp@tass.be 149:5f4cb161cec3 669 struct pico_mcast_group *g = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 670 struct pico_ip4 *source = NULL;
TASS Belgium NV 131:4758606c9316 671 struct pico_tree_node *index = NULL, *index2 = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 672 (void) source;
tass 68:0847e35d08a6 673
TASS Belgium NV 131:4758606c9316 674 ip_mcast_dbg("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
TASS Belgium NV 131:4758606c9316 675 ip_mcast_dbg("+ MULTICAST list interface %-16s +\n", mcast_link->dev->name);
TASS Belgium NV 131:4758606c9316 676 ip_mcast_dbg("+---------------------------------------------------------------------------------+\n");
TASS Belgium NV 131:4758606c9316 677 ip_mcast_dbg("+ nr | interface | host group | reference count | filter mode | source +\n");
TASS Belgium NV 131:4758606c9316 678 ip_mcast_dbg("+---------------------------------------------------------------------------------+\n");
tass 68:0847e35d08a6 679
tass 152:a3d286bf94e5 680 pico_tree_foreach(index, mcast_link->MCASTGroups) {
TASS Belgium NV 131:4758606c9316 681 g = index->keyValue;
TASS Belgium NV 131:4758606c9316 682 ip_mcast_dbg("+ %04d | %16s | %08X | %05u | %u | %8s +\n", i, mcast_link->dev->name, g->mcast_addr.addr, g->reference_count, g->filter_mode, "");
tass 152:a3d286bf94e5 683 pico_tree_foreach(index2, &g->MCASTSources) {
TASS Belgium NV 131:4758606c9316 684 source = index2->keyValue;
TASS Belgium NV 131:4758606c9316 685 ip_mcast_dbg("+ %4s | %16s | %8s | %5s | %s | %08X +\n", "", "", "", "", "", source->addr);
TASS Belgium NV 131:4758606c9316 686 }
TASS Belgium NV 131:4758606c9316 687 i++;
tass 68:0847e35d08a6 688 }
TASS Belgium NV 131:4758606c9316 689 ip_mcast_dbg("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
tass 68:0847e35d08a6 690 }
tass 68:0847e35d08a6 691
tass 70:cd218dd180e5 692 static int mcast_group_update(struct pico_mcast_group *g, struct pico_tree *MCASTFilter, uint8_t filter_mode)
tass 70:cd218dd180e5 693 {
TASS Belgium NV 131:4758606c9316 694 struct pico_tree_node *index = NULL, *_tmp = NULL;
TASS Belgium NV 131:4758606c9316 695 struct pico_ip4 *source = NULL;
TASS Belgium NV 131:4758606c9316 696 /* cleanup filter */
tass 152:a3d286bf94e5 697 pico_tree_foreach_safe(index, &g->MCASTSources, _tmp) {
TASS Belgium NV 131:4758606c9316 698 source = index->keyValue;
TASS Belgium NV 131:4758606c9316 699 pico_tree_delete(&g->MCASTSources, source);
tass picotcp@tass.be 149:5f4cb161cec3 700 PICO_FREE(source);
tass 70:cd218dd180e5 701 }
TASS Belgium NV 131:4758606c9316 702 /* insert new filter */
TASS Belgium NV 131:4758606c9316 703 if (MCASTFilter) {
tass 152:a3d286bf94e5 704 pico_tree_foreach(index, MCASTFilter) {
tass picotcp@tass.be 149:5f4cb161cec3 705 if (index->keyValue) {
tass picotcp@tass.be 149:5f4cb161cec3 706 source = PICO_ZALLOC(sizeof(struct pico_ip4));
tass picotcp@tass.be 149:5f4cb161cec3 707 if (!source) {
tass picotcp@tass.be 149:5f4cb161cec3 708 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 709 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 710 }
tass picotcp@tass.be 149:5f4cb161cec3 711
tass picotcp@tass.be 149:5f4cb161cec3 712 source->addr = ((struct pico_ip4 *)index->keyValue)->addr;
tass picotcp@tass.be 149:5f4cb161cec3 713 pico_tree_insert(&g->MCASTSources, source);
TASS Belgium NV 131:4758606c9316 714 }
TASS Belgium NV 131:4758606c9316 715 }
TASS Belgium NV 131:4758606c9316 716 }
TASS Belgium NV 131:4758606c9316 717
TASS Belgium NV 131:4758606c9316 718 g->filter_mode = filter_mode;
TASS Belgium NV 131:4758606c9316 719 return 0;
tass 70:cd218dd180e5 720 }
tass 70:cd218dd180e5 721
tass 68:0847e35d08a6 722 int pico_ipv4_mcast_join(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t reference_count, uint8_t filter_mode, struct pico_tree *MCASTFilter)
tass 68:0847e35d08a6 723 {
TASS Belgium NV 131:4758606c9316 724 struct pico_mcast_group *g = NULL, test = {
TASS Belgium NV 131:4758606c9316 725 0
TASS Belgium NV 131:4758606c9316 726 };
TASS Belgium NV 131:4758606c9316 727 struct pico_ipv4_link *link = NULL;
tass 68:0847e35d08a6 728
TASS Belgium NV 131:4758606c9316 729 if (mcast_link)
TASS Belgium NV 131:4758606c9316 730 link = pico_ipv4_link_get(mcast_link);
tass 152:a3d286bf94e5 731
tass 152:a3d286bf94e5 732 if (!link)
TASS Belgium NV 131:4758606c9316 733 link = mcast_default_link;
TASS Belgium NV 131:4758606c9316 734
TASS Belgium NV 131:4758606c9316 735 test.mcast_addr = *mcast_group;
TASS Belgium NV 131:4758606c9316 736 g = pico_tree_findKey(link->MCASTGroups, &test);
TASS Belgium NV 131:4758606c9316 737 if (g) {
TASS Belgium NV 131:4758606c9316 738 if (reference_count)
TASS Belgium NV 131:4758606c9316 739 g->reference_count++;
tass 68:0847e35d08a6 740
TASS Belgium NV 131:4758606c9316 741 pico_igmp_state_change(mcast_link, mcast_group, filter_mode, MCASTFilter, PICO_IGMP_STATE_UPDATE);
TASS Belgium NV 131:4758606c9316 742 } else {
tass picotcp@tass.be 149:5f4cb161cec3 743 g = PICO_ZALLOC(sizeof(struct pico_mcast_group));
TASS Belgium NV 131:4758606c9316 744 if (!g) {
TASS Belgium NV 131:4758606c9316 745 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 746 return -1;
TASS Belgium NV 131:4758606c9316 747 }
TASS Belgium NV 131:4758606c9316 748
TASS Belgium NV 131:4758606c9316 749 /* "non-existent" state of filter mode INCLUDE and empty source list */
TASS Belgium NV 131:4758606c9316 750 g->filter_mode = PICO_IP_MULTICAST_INCLUDE;
TASS Belgium NV 131:4758606c9316 751 g->reference_count = 1;
TASS Belgium NV 131:4758606c9316 752 g->mcast_addr = *mcast_group;
TASS Belgium NV 131:4758606c9316 753 g->MCASTSources.root = &LEAF;
TASS Belgium NV 131:4758606c9316 754 g->MCASTSources.compare = ipv4_mcast_sources_cmp;
TASS Belgium NV 131:4758606c9316 755 pico_tree_insert(link->MCASTGroups, g);
TASS Belgium NV 131:4758606c9316 756 pico_igmp_state_change(mcast_link, mcast_group, filter_mode, MCASTFilter, PICO_IGMP_STATE_CREATE);
tass 68:0847e35d08a6 757 }
TASS Belgium NV 131:4758606c9316 758
tass picotcp@tass.be 149:5f4cb161cec3 759 if (mcast_group_update(g, MCASTFilter, filter_mode) < 0) {
tass picotcp@tass.be 149:5f4cb161cec3 760 dbg("Error in mcast_group update\n");
TASS Belgium NV 131:4758606c9316 761 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 762 }
TASS Belgium NV 131:4758606c9316 763
TASS Belgium NV 131:4758606c9316 764 pico_ipv4_mcast_print_groups(link);
TASS Belgium NV 131:4758606c9316 765 return 0;
tass 68:0847e35d08a6 766 }
tass 68:0847e35d08a6 767
tass 68:0847e35d08a6 768 int pico_ipv4_mcast_leave(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t reference_count, uint8_t filter_mode, struct pico_tree *MCASTFilter)
tass 68:0847e35d08a6 769 {
tass 68:0847e35d08a6 770
TASS Belgium NV 131:4758606c9316 771 struct pico_mcast_group *g = NULL, test = {
TASS Belgium NV 131:4758606c9316 772 0
TASS Belgium NV 131:4758606c9316 773 };
TASS Belgium NV 131:4758606c9316 774 struct pico_ipv4_link *link = NULL;
TASS Belgium NV 131:4758606c9316 775 struct pico_tree_node *index = NULL, *_tmp = NULL;
TASS Belgium NV 131:4758606c9316 776 struct pico_ip4 *source = NULL;
tass 68:0847e35d08a6 777
TASS Belgium NV 131:4758606c9316 778 if (mcast_link)
TASS Belgium NV 131:4758606c9316 779 link = pico_ipv4_link_get(mcast_link);
tass 152:a3d286bf94e5 780
tass 152:a3d286bf94e5 781 if (!link)
TASS Belgium NV 131:4758606c9316 782 link = mcast_default_link;
tass 68:0847e35d08a6 783
TASS Belgium NV 131:4758606c9316 784 test.mcast_addr = *mcast_group;
TASS Belgium NV 131:4758606c9316 785 g = pico_tree_findKey(link->MCASTGroups, &test);
TASS Belgium NV 131:4758606c9316 786 if (!g) {
TASS Belgium NV 131:4758606c9316 787 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 788 return -1;
tass 68:0847e35d08a6 789 } else {
TASS Belgium NV 131:4758606c9316 790 if (reference_count && (--(g->reference_count) < 1)) {
TASS Belgium NV 131:4758606c9316 791 pico_igmp_state_change(mcast_link, mcast_group, filter_mode, MCASTFilter, PICO_IGMP_STATE_DELETE);
TASS Belgium NV 131:4758606c9316 792 /* cleanup filter */
tass 152:a3d286bf94e5 793 pico_tree_foreach_safe(index, &g->MCASTSources, _tmp) {
TASS Belgium NV 131:4758606c9316 794 source = index->keyValue;
TASS Belgium NV 131:4758606c9316 795 pico_tree_delete(&g->MCASTSources, source);
tass picotcp@tass.be 149:5f4cb161cec3 796 PICO_FREE(source);
TASS Belgium NV 131:4758606c9316 797 }
TASS Belgium NV 131:4758606c9316 798 pico_tree_delete(link->MCASTGroups, g);
tass picotcp@tass.be 149:5f4cb161cec3 799 PICO_FREE(g);
TASS Belgium NV 131:4758606c9316 800 } else {
TASS Belgium NV 131:4758606c9316 801 pico_igmp_state_change(mcast_link, mcast_group, filter_mode, MCASTFilter, PICO_IGMP_STATE_UPDATE);
TASS Belgium NV 131:4758606c9316 802 if (mcast_group_update(g, MCASTFilter, filter_mode) < 0)
TASS Belgium NV 131:4758606c9316 803 return -1;
TASS Belgium NV 131:4758606c9316 804 }
tass 68:0847e35d08a6 805 }
tass 68:0847e35d08a6 806
TASS Belgium NV 131:4758606c9316 807 pico_ipv4_mcast_print_groups(link);
TASS Belgium NV 131:4758606c9316 808 return 0;
tass 68:0847e35d08a6 809 }
tass 68:0847e35d08a6 810
tass 68:0847e35d08a6 811 struct pico_ipv4_link *pico_ipv4_get_default_mcastlink(void)
tass 68:0847e35d08a6 812 {
TASS Belgium NV 131:4758606c9316 813 return mcast_default_link;
tass 68:0847e35d08a6 814 }
tass 68:0847e35d08a6 815
tass 68:0847e35d08a6 816 static int pico_ipv4_mcast_filter(struct pico_frame *f)
tass 68:0847e35d08a6 817 {
TASS Belgium NV 131:4758606c9316 818 struct pico_ipv4_link *link = NULL;
TASS Belgium NV 131:4758606c9316 819 struct pico_tree_node *index = NULL, *index2 = NULL;
TASS Belgium NV 131:4758606c9316 820 struct pico_mcast_group *g = NULL, test = {
TASS Belgium NV 131:4758606c9316 821 0
TASS Belgium NV 131:4758606c9316 822 };
TASS Belgium NV 131:4758606c9316 823 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass 68:0847e35d08a6 824
TASS Belgium NV 131:4758606c9316 825 test.mcast_addr = hdr->dst;
tass 68:0847e35d08a6 826
tass 152:a3d286bf94e5 827 pico_tree_foreach(index, &Tree_dev_link) {
TASS Belgium NV 131:4758606c9316 828 link = index->keyValue;
TASS Belgium NV 131:4758606c9316 829 g = pico_tree_findKey(link->MCASTGroups, &test);
TASS Belgium NV 131:4758606c9316 830 if (g) {
TASS Belgium NV 131:4758606c9316 831 if (f->dev == link->dev) {
TASS Belgium NV 131:4758606c9316 832 ip_mcast_dbg("MCAST: IP %08X is group member of current link %s\n", hdr->dst.addr, f->dev->name);
TASS Belgium NV 131:4758606c9316 833 /* perform source filtering */
tass 152:a3d286bf94e5 834 switch (g->filter_mode) {
TASS Belgium NV 131:4758606c9316 835 case PICO_IP_MULTICAST_INCLUDE:
tass 152:a3d286bf94e5 836 pico_tree_foreach(index2, &g->MCASTSources) {
TASS Belgium NV 131:4758606c9316 837 if (hdr->src.addr == ((struct pico_ip4 *)index2->keyValue)->addr) {
TASS Belgium NV 131:4758606c9316 838 ip_mcast_dbg("MCAST: IP %08X in included interface source list\n", hdr->src.addr);
TASS Belgium NV 131:4758606c9316 839 return 0;
TASS Belgium NV 131:4758606c9316 840 }
TASS Belgium NV 131:4758606c9316 841 }
TASS Belgium NV 131:4758606c9316 842 ip_mcast_dbg("MCAST: IP %08X NOT in included interface source list\n", hdr->src.addr);
TASS Belgium NV 131:4758606c9316 843 return -1;
TASS Belgium NV 131:4758606c9316 844
TASS Belgium NV 131:4758606c9316 845 case PICO_IP_MULTICAST_EXCLUDE:
tass 152:a3d286bf94e5 846 pico_tree_foreach(index2, &g->MCASTSources) {
TASS Belgium NV 131:4758606c9316 847 if (hdr->src.addr == ((struct pico_ip4 *)index2->keyValue)->addr) {
TASS Belgium NV 131:4758606c9316 848 ip_mcast_dbg("MCAST: IP %08X in excluded interface source list\n", hdr->src.addr);
TASS Belgium NV 131:4758606c9316 849 return -1;
TASS Belgium NV 131:4758606c9316 850 }
TASS Belgium NV 131:4758606c9316 851 }
TASS Belgium NV 131:4758606c9316 852 ip_mcast_dbg("MCAST: IP %08X NOT in excluded interface source list\n", hdr->src.addr);
TASS Belgium NV 131:4758606c9316 853 return 0;
TASS Belgium NV 131:4758606c9316 854
TASS Belgium NV 131:4758606c9316 855 default:
TASS Belgium NV 131:4758606c9316 856 return -1;
TASS Belgium NV 131:4758606c9316 857 }
TASS Belgium NV 131:4758606c9316 858 } else {
TASS Belgium NV 131:4758606c9316 859 ip_mcast_dbg("MCAST: IP %08X is group member of different link %s\n", hdr->dst.addr, link->dev->name);
tass 68:0847e35d08a6 860 }
TASS Belgium NV 131:4758606c9316 861 } else {
TASS Belgium NV 131:4758606c9316 862 ip_mcast_dbg("MCAST: IP %08X is not a group member of link %s\n", hdr->dst.addr, f->dev->name);
tass 68:0847e35d08a6 863 }
tass 68:0847e35d08a6 864 }
TASS Belgium NV 131:4758606c9316 865 return -1;
tass 68:0847e35d08a6 866 }
tass 68:0847e35d08a6 867
TASS Belgium NV 131:4758606c9316 868 #else
tass 68:0847e35d08a6 869
tass 68:0847e35d08a6 870 int pico_ipv4_mcast_join(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t reference_count, uint8_t filter_mode, struct pico_tree *MCASTFilter)
tass 68:0847e35d08a6 871 {
TASS Belgium NV 131:4758606c9316 872 pico_err = PICO_ERR_EPROTONOSUPPORT;
TASS Belgium NV 131:4758606c9316 873 return -1;
tass 68:0847e35d08a6 874 }
tass 152:a3d286bf94e5 875
tass 68:0847e35d08a6 876 int pico_ipv4_mcast_leave(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t reference_count, uint8_t filter_mode, struct pico_tree *MCASTFilter)
tass 68:0847e35d08a6 877 {
TASS Belgium NV 131:4758606c9316 878 pico_err = PICO_ERR_EPROTONOSUPPORT;
TASS Belgium NV 131:4758606c9316 879 return -1;
tass 68:0847e35d08a6 880 }
tass 152:a3d286bf94e5 881
tass 68:0847e35d08a6 882 struct pico_ipv4_link *pico_ipv4_get_default_mcastlink(void)
tass 68:0847e35d08a6 883 {
TASS Belgium NV 131:4758606c9316 884 pico_err = PICO_ERR_EPROTONOSUPPORT;
TASS Belgium NV 131:4758606c9316 885 return NULL;
tass 68:0847e35d08a6 886 }
tass 68:0847e35d08a6 887 #endif /* PICO_SUPPORT_MCAST */
tass 68:0847e35d08a6 888
tass 152:a3d286bf94e5 889 /* #define DEBUG_ROUTE */
tass 88:0e827d0d8017 890 #ifdef DEBUG_ROUTE
tass 152:a3d286bf94e5 891 void dbg_route(void)
tass 88:0e827d0d8017 892 {
TASS Belgium NV 131:4758606c9316 893 struct pico_ipv4_route *r;
TASS Belgium NV 131:4758606c9316 894 struct pico_tree_node *index;
tass 152:a3d286bf94e5 895 int count_hosts = 0;
tass 152:a3d286bf94e5 896 dbg("==== ROUTING TABLE =====\n");
tass 152:a3d286bf94e5 897 pico_tree_foreach(index, &Routes) {
TASS Belgium NV 131:4758606c9316 898 r = index->keyValue;
TASS Belgium NV 131:4758606c9316 899 dbg("Route to %08x/%08x, gw %08x, dev: %s, metric: %d\n", r->dest.addr, r->netmask.addr, r->gateway.addr, r->link->dev->name, r->metric);
tass 152:a3d286bf94e5 900 if (r->netmask.addr == 0xFFFFFFFF)
tass 152:a3d286bf94e5 901 count_hosts++;
TASS Belgium NV 131:4758606c9316 902 }
tass 152:a3d286bf94e5 903 dbg("================ total HOST nodes: %d ======\n\n\n", count_hosts);
tass 88:0e827d0d8017 904 }
tass 88:0e827d0d8017 905 #else
TASS Belgium NV 131:4758606c9316 906 #define dbg_route() do { } while(0)
tass 88:0e827d0d8017 907 #endif
tass 88:0e827d0d8017 908
tass 68:0847e35d08a6 909 int pico_ipv4_frame_push(struct pico_frame *f, struct pico_ip4 *dst, uint8_t proto)
tass 68:0847e35d08a6 910 {
tass 68:0847e35d08a6 911
TASS Belgium NV 131:4758606c9316 912 struct pico_ipv4_route *route;
TASS Belgium NV 131:4758606c9316 913 struct pico_ipv4_link *link;
TASS Belgium NV 131:4758606c9316 914 struct pico_ipv4_hdr *hdr;
TASS Belgium NV 131:4758606c9316 915 uint8_t ttl = PICO_IPV4_DEFAULT_TTL;
TASS Belgium NV 131:4758606c9316 916 uint8_t vhl = 0x45; /* version 4, header length 20 */
TASS Belgium NV 131:4758606c9316 917 static uint16_t ipv4_progressive_id = 0x91c0;
tass 68:0847e35d08a6 918 #ifdef PICO_SUPPORT_MCAST
TASS Belgium NV 131:4758606c9316 919 struct pico_tree_node *index;
tass 68:0847e35d08a6 920 #endif
tass 68:0847e35d08a6 921
tass 152:a3d286bf94e5 922 if (!f || !dst) {
TASS Belgium NV 131:4758606c9316 923 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 924 return -1;
TASS Belgium NV 131:4758606c9316 925 }
TASS Belgium NV 131:4758606c9316 926
tass 152:a3d286bf94e5 927
TASS Belgium NV 131:4758606c9316 928 hdr = (struct pico_ipv4_hdr *) f->net_hdr;
TASS Belgium NV 131:4758606c9316 929 if (!hdr) {
TASS Belgium NV 131:4758606c9316 930 dbg("IP header error\n");
TASS Belgium NV 131:4758606c9316 931 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 932 goto drop;
TASS Belgium NV 131:4758606c9316 933 }
tass 68:0847e35d08a6 934
TASS Belgium NV 131:4758606c9316 935 if (dst->addr == 0) {
TASS Belgium NV 131:4758606c9316 936 dbg("IP destination addr error\n");
TASS Belgium NV 131:4758606c9316 937 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 938 goto drop;
TASS Belgium NV 131:4758606c9316 939 }
tass 68:0847e35d08a6 940
TASS Belgium NV 131:4758606c9316 941 route = route_find(dst);
TASS Belgium NV 131:4758606c9316 942 if (!route) {
TASS Belgium NV 131:4758606c9316 943 /* dbg("Route to %08x not found.\n", long_be(dst->addr)); */
TASS Belgium NV 131:4758606c9316 944
TASS Belgium NV 131:4758606c9316 945
TASS Belgium NV 131:4758606c9316 946 pico_err = PICO_ERR_EHOSTUNREACH;
TASS Belgium NV 131:4758606c9316 947 goto drop;
TASS Belgium NV 131:4758606c9316 948 } else {
TASS Belgium NV 131:4758606c9316 949 link = route->link;
tass 68:0847e35d08a6 950 #ifdef PICO_SUPPORT_MCAST
TASS Belgium NV 131:4758606c9316 951 if (pico_ipv4_is_multicast(dst->addr)) { /* if multicast */
TASS Belgium NV 131:4758606c9316 952 switch (proto) {
TASS Belgium NV 131:4758606c9316 953 case PICO_PROTO_UDP:
tass 152:a3d286bf94e5 954 if (pico_udp_get_mc_ttl(f->sock, &ttl) < 0)
TASS Belgium NV 131:4758606c9316 955 ttl = PICO_IP_DEFAULT_MULTICAST_TTL;
TASS Belgium NV 131:4758606c9316 956
tass 68:0847e35d08a6 957 break;
tass 152:a3d286bf94e5 958 #ifdef PICO_SUPPORT_IGMP
TASS Belgium NV 131:4758606c9316 959 case PICO_PROTO_IGMP:
TASS Belgium NV 131:4758606c9316 960 vhl = 0x46; /* header length 24 */
TASS Belgium NV 131:4758606c9316 961 ttl = 1;
TASS Belgium NV 131:4758606c9316 962 /* router alert (RFC 2113) */
TASS Belgium NV 131:4758606c9316 963 hdr->options[0] = 0x94;
TASS Belgium NV 131:4758606c9316 964 hdr->options[1] = 0x04;
TASS Belgium NV 131:4758606c9316 965 hdr->options[2] = 0x00;
TASS Belgium NV 131:4758606c9316 966 hdr->options[3] = 0x00;
TASS Belgium NV 131:4758606c9316 967 if (f->dev && link->dev != f->dev) { /* default link is not requested link */
TASS Belgium NV 131:4758606c9316 968 pico_tree_foreach(index, &Tree_dev_link) {
TASS Belgium NV 131:4758606c9316 969 link = index->keyValue;
TASS Belgium NV 131:4758606c9316 970 if (link->dev == f->dev)
TASS Belgium NV 131:4758606c9316 971 break;
TASS Belgium NV 131:4758606c9316 972 }
TASS Belgium NV 131:4758606c9316 973 }
TASS Belgium NV 131:4758606c9316 974
TASS Belgium NV 131:4758606c9316 975 break;
tass 152:a3d286bf94e5 976 #endif
TASS Belgium NV 131:4758606c9316 977 default:
TASS Belgium NV 131:4758606c9316 978 ttl = PICO_IPV4_DEFAULT_TTL;
tass 68:0847e35d08a6 979 }
TASS Belgium NV 131:4758606c9316 980 }
TASS Belgium NV 131:4758606c9316 981
TASS Belgium NV 131:4758606c9316 982 #endif
tass 68:0847e35d08a6 983 }
tass 68:0847e35d08a6 984
TASS Belgium NV 131:4758606c9316 985 hdr->vhl = vhl;
TASS Belgium NV 131:4758606c9316 986 hdr->len = short_be((uint16_t)(f->transport_len + f->net_len));
tass picotcp@tass.be 149:5f4cb161cec3 987 if ((f->transport_hdr != f->payload) &&
tass 152:a3d286bf94e5 988 #ifdef PICO_SUPPORT_IPV4FRAG
tass 152:a3d286bf94e5 989 ( (0 == (f->frag & PICO_IPV4_MOREFRAG)) ||
tass 152:a3d286bf94e5 990 (0 == (f->frag & PICO_IPV4_FRAG_MASK)) )
tass 152:a3d286bf94e5 991 &&
tass picotcp@tass.be 149:5f4cb161cec3 992 #endif
tass picotcp@tass.be 149:5f4cb161cec3 993 1 )
TASS Belgium NV 131:4758606c9316 994 ipv4_progressive_id++;
TASS Belgium NV 131:4758606c9316 995
tass 152:a3d286bf94e5 996 if (f->send_ttl > 0) {
tass 152:a3d286bf94e5 997 ttl = f->send_ttl;
tass 152:a3d286bf94e5 998 }
tass 152:a3d286bf94e5 999
TASS Belgium NV 131:4758606c9316 1000 hdr->id = short_be(ipv4_progressive_id);
TASS Belgium NV 131:4758606c9316 1001 hdr->dst.addr = dst->addr;
TASS Belgium NV 131:4758606c9316 1002 hdr->src.addr = link->address.addr;
TASS Belgium NV 131:4758606c9316 1003 hdr->ttl = ttl;
tass 152:a3d286bf94e5 1004 hdr->tos = f->send_tos;
TASS Belgium NV 131:4758606c9316 1005 hdr->proto = proto;
TASS Belgium NV 131:4758606c9316 1006 hdr->frag = short_be(PICO_IPV4_DONTFRAG);
tass 152:a3d286bf94e5 1007
tass 152:a3d286bf94e5 1008 #ifdef PICO_SUPPORT_IPV4FRAG
tass 68:0847e35d08a6 1009 # ifdef PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1010 if (proto == PICO_PROTO_UDP) {
TASS Belgium NV 131:4758606c9316 1011 /* first fragment, can not use transport_len to calculate IP length */
TASS Belgium NV 131:4758606c9316 1012 if (f->transport_hdr != f->payload)
TASS Belgium NV 131:4758606c9316 1013 hdr->len = short_be((uint16_t)(f->payload_len + sizeof(struct pico_udp_hdr) + f->net_len));
TASS Belgium NV 131:4758606c9316 1014
TASS Belgium NV 131:4758606c9316 1015 /* set fragmentation flags and offset calculated in socket layer */
tass 152:a3d286bf94e5 1016 hdr->frag = short_be(f->frag);
TASS Belgium NV 131:4758606c9316 1017 }
TASS Belgium NV 131:4758606c9316 1018
tass picotcp@tass.be 149:5f4cb161cec3 1019 if (proto == PICO_PROTO_ICMP4)
tass 152:a3d286bf94e5 1020 {
tass 152:a3d286bf94e5 1021 hdr->frag = short_be(f->frag);
tass 152:a3d286bf94e5 1022 }
tass picotcp@tass.be 149:5f4cb161cec3 1023
tass picotcp@tass.be 149:5f4cb161cec3 1024 # endif
tass 152:a3d286bf94e5 1025 #endif /* PICO_SUPPORT_IPV4FRAG */
TASS Belgium NV 131:4758606c9316 1026 pico_ipv4_checksum(f);
tass 68:0847e35d08a6 1027
TASS Belgium NV 131:4758606c9316 1028 if (f->sock && f->sock->dev) {
TASS Belgium NV 131:4758606c9316 1029 /* if the socket has its device set, use that (currently used for DHCP) */
TASS Belgium NV 131:4758606c9316 1030 f->dev = f->sock->dev;
TASS Belgium NV 131:4758606c9316 1031 } else {
TASS Belgium NV 131:4758606c9316 1032 f->dev = link->dev;
tass 152:a3d286bf94e5 1033 if (f->sock)
tass 152:a3d286bf94e5 1034 f->sock->dev = f->dev;
TASS Belgium NV 131:4758606c9316 1035 }
tass 68:0847e35d08a6 1036
tass 68:0847e35d08a6 1037 #ifdef PICO_SUPPORT_MCAST
TASS Belgium NV 131:4758606c9316 1038 if (pico_ipv4_is_multicast(hdr->dst.addr)) {
TASS Belgium NV 131:4758606c9316 1039 struct pico_frame *cpy;
TASS Belgium NV 131:4758606c9316 1040 /* Sending UDP multicast datagram, am I member? If so, loopback copy */
TASS Belgium NV 131:4758606c9316 1041 if ((proto != PICO_PROTO_IGMP) && (pico_ipv4_mcast_filter(f) == 0)) {
TASS Belgium NV 131:4758606c9316 1042 ip_mcast_dbg("MCAST: sender is member of group, loopback copy\n");
TASS Belgium NV 131:4758606c9316 1043 cpy = pico_frame_copy(f);
TASS Belgium NV 131:4758606c9316 1044 pico_enqueue(&in, cpy);
TASS Belgium NV 131:4758606c9316 1045 }
tass 68:0847e35d08a6 1046 }
TASS Belgium NV 131:4758606c9316 1047
tass 68:0847e35d08a6 1048 #endif
tass 68:0847e35d08a6 1049
tass 152:a3d286bf94e5 1050 /* #ifdef PICO_SUPPORT_AODV */
tass 152:a3d286bf94e5 1051 #if 0
tass 152:a3d286bf94e5 1052 {
tass 152:a3d286bf94e5 1053 union pico_address node_address;
tass 152:a3d286bf94e5 1054 node_address.ip4.addr = hdr->dst.addr;
tass 152:a3d286bf94e5 1055 if(hdr->dst.addr && pico_ipv4_is_unicast(hdr->dst.addr))
tass 152:a3d286bf94e5 1056 pico_aodv_lookup(&node_address);
tass 152:a3d286bf94e5 1057 }
tass 152:a3d286bf94e5 1058 #endif
tass 152:a3d286bf94e5 1059
tass 152:a3d286bf94e5 1060 if (pico_ipv4_link_get(&hdr->dst)) {
TASS Belgium NV 131:4758606c9316 1061 /* it's our own IP */
TASS Belgium NV 131:4758606c9316 1062 return pico_enqueue(&in, f);
tass 152:a3d286bf94e5 1063 } else{
TASS Belgium NV 131:4758606c9316 1064 /* TODO: Check if there are members subscribed here */
TASS Belgium NV 131:4758606c9316 1065 return pico_enqueue(&out, f);
TASS Belgium NV 131:4758606c9316 1066 }
tass 68:0847e35d08a6 1067
tass 68:0847e35d08a6 1068 drop:
TASS Belgium NV 131:4758606c9316 1069 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 1070 return -1;
tass 68:0847e35d08a6 1071 }
tass 68:0847e35d08a6 1072
tass 68:0847e35d08a6 1073
tass 68:0847e35d08a6 1074 static int pico_ipv4_frame_sock_push(struct pico_protocol *self, struct pico_frame *f)
tass 68:0847e35d08a6 1075 {
TASS Belgium NV 131:4758606c9316 1076 struct pico_ip4 *dst;
tass picotcp@tass.be 149:5f4cb161cec3 1077 struct pico_remote_endpoint *remote_endpoint = (struct pico_remote_endpoint *) f->info;
TASS Belgium NV 131:4758606c9316 1078 IGNORE_PARAMETER(self);
tass 68:0847e35d08a6 1079
TASS Belgium NV 131:4758606c9316 1080 if (!f->sock) {
TASS Belgium NV 131:4758606c9316 1081 pico_frame_discard(f);
TASS Belgium NV 131:4758606c9316 1082 return -1;
TASS Belgium NV 131:4758606c9316 1083 }
tass 68:0847e35d08a6 1084
tass picotcp@tass.be 149:5f4cb161cec3 1085 if (remote_endpoint) {
tass picotcp@tass.be 149:5f4cb161cec3 1086 dst = &remote_endpoint->remote_addr.ip4;
TASS Belgium NV 131:4758606c9316 1087 } else {
TASS Belgium NV 131:4758606c9316 1088 dst = &f->sock->remote_addr.ip4;
TASS Belgium NV 131:4758606c9316 1089 }
tass 68:0847e35d08a6 1090
TASS Belgium NV 131:4758606c9316 1091 return pico_ipv4_frame_push(f, dst, (uint8_t)f->sock->proto->proto_number);
tass 68:0847e35d08a6 1092 }
tass 68:0847e35d08a6 1093
tass 68:0847e35d08a6 1094
tass 152:a3d286bf94e5 1095 int MOCKABLE pico_ipv4_route_add(struct pico_ip4 address, struct pico_ip4 netmask, struct pico_ip4 gateway, int metric, struct pico_ipv4_link *link)
tass 68:0847e35d08a6 1096 {
TASS Belgium NV 131:4758606c9316 1097 struct pico_ipv4_route test, *new;
TASS Belgium NV 131:4758606c9316 1098 test.dest.addr = address.addr;
TASS Belgium NV 131:4758606c9316 1099 test.netmask.addr = netmask.addr;
TASS Belgium NV 131:4758606c9316 1100 test.metric = (uint32_t)metric;
TASS Belgium NV 131:4758606c9316 1101
tass 152:a3d286bf94e5 1102 if (pico_tree_findKey(&Routes, &test)) {
TASS Belgium NV 131:4758606c9316 1103 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1104 return -1;
TASS Belgium NV 131:4758606c9316 1105 }
TASS Belgium NV 131:4758606c9316 1106
tass picotcp@tass.be 149:5f4cb161cec3 1107 new = PICO_ZALLOC(sizeof(struct pico_ipv4_route));
TASS Belgium NV 131:4758606c9316 1108 if (!new) {
TASS Belgium NV 131:4758606c9316 1109 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1110 return -1;
TASS Belgium NV 131:4758606c9316 1111 }
tass 68:0847e35d08a6 1112
TASS Belgium NV 131:4758606c9316 1113 new->dest.addr = address.addr;
TASS Belgium NV 131:4758606c9316 1114 new->netmask.addr = netmask.addr;
TASS Belgium NV 131:4758606c9316 1115 new->gateway.addr = gateway.addr;
TASS Belgium NV 131:4758606c9316 1116 new->metric = (uint32_t)metric;
TASS Belgium NV 131:4758606c9316 1117 if (gateway.addr == 0) {
TASS Belgium NV 131:4758606c9316 1118 /* No gateway provided, use the link */
TASS Belgium NV 131:4758606c9316 1119 new->link = link;
TASS Belgium NV 131:4758606c9316 1120 } else {
TASS Belgium NV 131:4758606c9316 1121 struct pico_ipv4_route *r = route_find(&gateway);
TASS Belgium NV 131:4758606c9316 1122 if (!r ) { /* Specified Gateway is unreachable */
TASS Belgium NV 131:4758606c9316 1123 pico_err = PICO_ERR_EHOSTUNREACH;
tass picotcp@tass.be 149:5f4cb161cec3 1124 PICO_FREE(new);
TASS Belgium NV 131:4758606c9316 1125 return -1;
TASS Belgium NV 131:4758606c9316 1126 }
TASS Belgium NV 131:4758606c9316 1127
TASS Belgium NV 131:4758606c9316 1128 if (r->gateway.addr) { /* Specified Gateway is not a neighbor */
TASS Belgium NV 131:4758606c9316 1129 pico_err = PICO_ERR_ENETUNREACH;
tass picotcp@tass.be 149:5f4cb161cec3 1130 PICO_FREE(new);
TASS Belgium NV 131:4758606c9316 1131 return -1;
TASS Belgium NV 131:4758606c9316 1132 }
TASS Belgium NV 131:4758606c9316 1133
TASS Belgium NV 131:4758606c9316 1134 new->link = r->link;
tass 68:0847e35d08a6 1135 }
TASS Belgium NV 131:4758606c9316 1136
TASS Belgium NV 131:4758606c9316 1137 if (!new->link) {
TASS Belgium NV 131:4758606c9316 1138 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 1139 PICO_FREE(new);
TASS Belgium NV 131:4758606c9316 1140 return -1;
tass 68:0847e35d08a6 1141 }
tass 68:0847e35d08a6 1142
TASS Belgium NV 131:4758606c9316 1143 pico_tree_insert(&Routes, new);
tass 152:a3d286bf94e5 1144 dbg_route();
TASS Belgium NV 131:4758606c9316 1145 return 0;
tass 68:0847e35d08a6 1146 }
tass 68:0847e35d08a6 1147
tass 72:887bc44746ff 1148 int pico_ipv4_route_del(struct pico_ip4 address, struct pico_ip4 netmask, int metric)
tass 68:0847e35d08a6 1149 {
TASS Belgium NV 131:4758606c9316 1150 struct pico_ipv4_route test, *found;
tass 68:0847e35d08a6 1151
TASS Belgium NV 131:4758606c9316 1152 test.dest.addr = address.addr;
TASS Belgium NV 131:4758606c9316 1153 test.netmask.addr = netmask.addr;
TASS Belgium NV 131:4758606c9316 1154 test.metric = (uint32_t)metric;
tass 68:0847e35d08a6 1155
TASS Belgium NV 131:4758606c9316 1156 found = pico_tree_findKey(&Routes, &test);
TASS Belgium NV 131:4758606c9316 1157 if (found) {
tass 68:0847e35d08a6 1158
TASS Belgium NV 131:4758606c9316 1159 pico_tree_delete(&Routes, found);
tass picotcp@tass.be 149:5f4cb161cec3 1160 PICO_FREE(found);
tass 68:0847e35d08a6 1161
tass 152:a3d286bf94e5 1162 dbg_route();
TASS Belgium NV 131:4758606c9316 1163 return 0;
TASS Belgium NV 131:4758606c9316 1164 }
TASS Belgium NV 131:4758606c9316 1165
TASS Belgium NV 131:4758606c9316 1166 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1167 return -1;
tass 68:0847e35d08a6 1168 }
tass 68:0847e35d08a6 1169
tass 68:0847e35d08a6 1170
tass 68:0847e35d08a6 1171 int pico_ipv4_link_add(struct pico_device *dev, struct pico_ip4 address, struct pico_ip4 netmask)
tass 68:0847e35d08a6 1172 {
TASS Belgium NV 131:4758606c9316 1173 struct pico_ipv4_link test, *new;
TASS Belgium NV 131:4758606c9316 1174 struct pico_ip4 network, gateway;
TASS Belgium NV 131:4758606c9316 1175 char ipstr[30];
TASS Belgium NV 131:4758606c9316 1176
tass 152:a3d286bf94e5 1177 if (!dev) {
TASS Belgium NV 131:4758606c9316 1178 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1179 return -1;
TASS Belgium NV 131:4758606c9316 1180 }
tass 68:0847e35d08a6 1181
TASS Belgium NV 131:4758606c9316 1182 test.address.addr = address.addr;
TASS Belgium NV 131:4758606c9316 1183 test.netmask.addr = netmask.addr;
TASS Belgium NV 131:4758606c9316 1184 test.dev = dev;
TASS Belgium NV 131:4758606c9316 1185 /** XXX: Valid netmask / unicast address test **/
tass 68:0847e35d08a6 1186
tass 152:a3d286bf94e5 1187 if (pico_tree_findKey(&Tree_dev_link, &test)) {
TASS Belgium NV 131:4758606c9316 1188 pico_err = PICO_ERR_EADDRINUSE;
TASS Belgium NV 131:4758606c9316 1189 return -1;
TASS Belgium NV 131:4758606c9316 1190 }
tass 68:0847e35d08a6 1191
TASS Belgium NV 131:4758606c9316 1192 /** XXX: Check for network already in use (e.g. trying to assign 10.0.0.1/24 where 10.1.0.1/8 is in use) **/
tass picotcp@tass.be 149:5f4cb161cec3 1193 new = PICO_ZALLOC(sizeof(struct pico_ipv4_link));
TASS Belgium NV 131:4758606c9316 1194 if (!new) {
TASS Belgium NV 131:4758606c9316 1195 dbg("IPv4: Out of memory!\n");
TASS Belgium NV 131:4758606c9316 1196 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1197 return -1;
TASS Belgium NV 131:4758606c9316 1198 }
TASS Belgium NV 131:4758606c9316 1199
TASS Belgium NV 131:4758606c9316 1200 new->address.addr = address.addr;
TASS Belgium NV 131:4758606c9316 1201 new->netmask.addr = netmask.addr;
TASS Belgium NV 131:4758606c9316 1202 new->dev = dev;
tass 68:0847e35d08a6 1203 #ifdef PICO_SUPPORT_MCAST
tass picotcp@tass.be 149:5f4cb161cec3 1204 new->MCASTGroups = PICO_ZALLOC(sizeof(struct pico_tree));
TASS Belgium NV 131:4758606c9316 1205 if (!new->MCASTGroups) {
tass picotcp@tass.be 149:5f4cb161cec3 1206 PICO_FREE(new);
TASS Belgium NV 131:4758606c9316 1207 dbg("IPv4: Out of memory!\n");
TASS Belgium NV 131:4758606c9316 1208 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 1209 return -1;
TASS Belgium NV 131:4758606c9316 1210 }
tass 68:0847e35d08a6 1211
TASS Belgium NV 131:4758606c9316 1212 new->MCASTGroups->root = &LEAF;
TASS Belgium NV 131:4758606c9316 1213 new->MCASTGroups->compare = ipv4_mcast_groups_cmp;
tass 152:a3d286bf94e5 1214 #ifdef PICO_SUPPORT_IGMP
TASS Belgium NV 131:4758606c9316 1215 new->mcast_compatibility = PICO_IGMPV3; /* default RFC 3376 $7.2.1 */
TASS Belgium NV 131:4758606c9316 1216 new->mcast_last_query_interval = PICO_IGMP_QUERY_INTERVAL;
tass 68:0847e35d08a6 1217 #endif
tass 152:a3d286bf94e5 1218 #endif
tass 68:0847e35d08a6 1219
TASS Belgium NV 131:4758606c9316 1220 pico_tree_insert(&Tree_dev_link, new);
tass 68:0847e35d08a6 1221 #ifdef PICO_SUPPORT_MCAST
TASS Belgium NV 131:4758606c9316 1222 do {
TASS Belgium NV 131:4758606c9316 1223 struct pico_ip4 mcast_all_hosts, mcast_addr, mcast_nm, mcast_gw;
TASS Belgium NV 131:4758606c9316 1224 if (!mcast_default_link) {
TASS Belgium NV 131:4758606c9316 1225 mcast_addr.addr = long_be(0xE0000000); /* 224.0.0.0 */
TASS Belgium NV 131:4758606c9316 1226 mcast_nm.addr = long_be(0xF0000000); /* 15.0.0.0 */
TASS Belgium NV 131:4758606c9316 1227 mcast_gw.addr = long_be(0x00000000);
TASS Belgium NV 131:4758606c9316 1228 mcast_default_link = new;
TASS Belgium NV 131:4758606c9316 1229 pico_ipv4_route_add(mcast_addr, mcast_nm, mcast_gw, 1, new);
TASS Belgium NV 131:4758606c9316 1230 }
TASS Belgium NV 131:4758606c9316 1231
TASS Belgium NV 131:4758606c9316 1232 mcast_all_hosts.addr = PICO_MCAST_ALL_HOSTS;
TASS Belgium NV 131:4758606c9316 1233 pico_ipv4_mcast_join(&address, &mcast_all_hosts, 1, PICO_IP_MULTICAST_EXCLUDE, NULL);
TASS Belgium NV 131:4758606c9316 1234 } while(0);
tass 68:0847e35d08a6 1235 #endif
tass 68:0847e35d08a6 1236
TASS Belgium NV 131:4758606c9316 1237 network.addr = address.addr & netmask.addr;
TASS Belgium NV 131:4758606c9316 1238 gateway.addr = 0U;
TASS Belgium NV 131:4758606c9316 1239 pico_ipv4_route_add(network, netmask, gateway, 1, new);
TASS Belgium NV 131:4758606c9316 1240 pico_ipv4_to_string(ipstr, new->address.addr);
TASS Belgium NV 131:4758606c9316 1241 dbg("Assigned ipv4 %s to device %s\n", ipstr, new->dev->name);
tass 152:a3d286bf94e5 1242 if (default_bcast_route.link == NULL)
tass 152:a3d286bf94e5 1243 default_bcast_route.link = new;
tass 152:a3d286bf94e5 1244
TASS Belgium NV 131:4758606c9316 1245 return 0;
tass 68:0847e35d08a6 1246 }
tass 68:0847e35d08a6 1247
tass 72:887bc44746ff 1248 static int pico_ipv4_cleanup_routes(struct pico_ipv4_link *link)
tass 72:887bc44746ff 1249 {
TASS Belgium NV 131:4758606c9316 1250 struct pico_tree_node *index = NULL, *tmp = NULL;
TASS Belgium NV 131:4758606c9316 1251 struct pico_ipv4_route *route = NULL;
tass 72:887bc44746ff 1252
tass 152:a3d286bf94e5 1253 pico_tree_foreach_safe(index, &Routes, tmp) {
TASS Belgium NV 131:4758606c9316 1254 route = index->keyValue;
TASS Belgium NV 131:4758606c9316 1255 if (link == route->link)
TASS Belgium NV 131:4758606c9316 1256 pico_ipv4_route_del(route->dest, route->netmask, (int)route->metric);
TASS Belgium NV 131:4758606c9316 1257 }
TASS Belgium NV 131:4758606c9316 1258 return 0;
tass 72:887bc44746ff 1259 }
tass 68:0847e35d08a6 1260
tass 152:a3d286bf94e5 1261 void MOCKABLE pico_ipv4_route_set_bcast_link(struct pico_ipv4_link *link)
tass 152:a3d286bf94e5 1262 {
tass 152:a3d286bf94e5 1263 if (link)
tass 152:a3d286bf94e5 1264 default_bcast_route.link = link;
tass 152:a3d286bf94e5 1265 }
tass 152:a3d286bf94e5 1266
tass 68:0847e35d08a6 1267 int pico_ipv4_link_del(struct pico_device *dev, struct pico_ip4 address)
tass 68:0847e35d08a6 1268 {
TASS Belgium NV 131:4758606c9316 1269 struct pico_ipv4_link test, *found;
TASS Belgium NV 131:4758606c9316 1270
tass 152:a3d286bf94e5 1271 if (!dev) {
TASS Belgium NV 131:4758606c9316 1272 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1273 return -1;
TASS Belgium NV 131:4758606c9316 1274 }
tass 68:0847e35d08a6 1275
TASS Belgium NV 131:4758606c9316 1276 test.address.addr = address.addr;
TASS Belgium NV 131:4758606c9316 1277 test.dev = dev;
TASS Belgium NV 131:4758606c9316 1278 found = pico_tree_findKey(&Tree_dev_link, &test);
TASS Belgium NV 131:4758606c9316 1279 if (!found) {
TASS Belgium NV 131:4758606c9316 1280 pico_err = PICO_ERR_ENXIO;
TASS Belgium NV 131:4758606c9316 1281 return -1;
TASS Belgium NV 131:4758606c9316 1282 }
tass 68:0847e35d08a6 1283
tass 68:0847e35d08a6 1284 #ifdef PICO_SUPPORT_MCAST
TASS Belgium NV 131:4758606c9316 1285 do {
TASS Belgium NV 131:4758606c9316 1286 struct pico_ip4 mcast_all_hosts, mcast_addr, mcast_nm;
TASS Belgium NV 131:4758606c9316 1287 struct pico_mcast_group *g = NULL;
TASS Belgium NV 131:4758606c9316 1288 struct pico_tree_node *index, *_tmp;
TASS Belgium NV 131:4758606c9316 1289 if (found == mcast_default_link) {
TASS Belgium NV 131:4758606c9316 1290 mcast_addr.addr = long_be(0xE0000000); /* 224.0.0.0 */
TASS Belgium NV 131:4758606c9316 1291 mcast_nm.addr = long_be(0xF0000000); /* 15.0.0.0 */
TASS Belgium NV 131:4758606c9316 1292 mcast_default_link = NULL;
TASS Belgium NV 131:4758606c9316 1293 pico_ipv4_route_del(mcast_addr, mcast_nm, 1);
TASS Belgium NV 131:4758606c9316 1294 }
TASS Belgium NV 131:4758606c9316 1295
TASS Belgium NV 131:4758606c9316 1296 mcast_all_hosts.addr = PICO_MCAST_ALL_HOSTS;
TASS Belgium NV 131:4758606c9316 1297 pico_ipv4_mcast_leave(&address, &mcast_all_hosts, 1, PICO_IP_MULTICAST_EXCLUDE, NULL);
tass 152:a3d286bf94e5 1298 pico_tree_foreach_safe(index, found->MCASTGroups, _tmp) {
TASS Belgium NV 131:4758606c9316 1299 g = index->keyValue;
TASS Belgium NV 131:4758606c9316 1300 pico_tree_delete(found->MCASTGroups, g);
tass picotcp@tass.be 149:5f4cb161cec3 1301 PICO_FREE(g);
TASS Belgium NV 131:4758606c9316 1302 }
TASS Belgium NV 131:4758606c9316 1303 } while(0);
tass 68:0847e35d08a6 1304 #endif
tass 68:0847e35d08a6 1305
TASS Belgium NV 131:4758606c9316 1306 pico_ipv4_cleanup_routes(found);
TASS Belgium NV 131:4758606c9316 1307 pico_tree_delete(&Tree_dev_link, found);
tass 152:a3d286bf94e5 1308 if (default_bcast_route.link == found)
tass 152:a3d286bf94e5 1309 default_bcast_route.link = NULL;
tass 152:a3d286bf94e5 1310
tass picotcp@tass.be 149:5f4cb161cec3 1311 PICO_FREE(found);
tass 72:887bc44746ff 1312
TASS Belgium NV 131:4758606c9316 1313 return 0;
tass 68:0847e35d08a6 1314 }
tass 68:0847e35d08a6 1315
tass 68:0847e35d08a6 1316
tass 68:0847e35d08a6 1317 struct pico_ipv4_link *pico_ipv4_link_get(struct pico_ip4 *address)
tass 68:0847e35d08a6 1318 {
TASS Belgium NV 131:4758606c9316 1319 struct pico_ipv4_link test = {
TASS Belgium NV 131:4758606c9316 1320 0
TASS Belgium NV 131:4758606c9316 1321 }, *found = NULL;
TASS Belgium NV 131:4758606c9316 1322 test.address.addr = address->addr;
tass 68:0847e35d08a6 1323
TASS Belgium NV 131:4758606c9316 1324 found = pico_tree_findKey(&Tree_dev_link, &test);
TASS Belgium NV 131:4758606c9316 1325 if (!found)
TASS Belgium NV 131:4758606c9316 1326 return NULL;
TASS Belgium NV 131:4758606c9316 1327 else
TASS Belgium NV 131:4758606c9316 1328 return found;
tass 68:0847e35d08a6 1329 }
tass 68:0847e35d08a6 1330
tass 152:a3d286bf94e5 1331 struct pico_ipv4_link *MOCKABLE pico_ipv4_link_by_dev(struct pico_device *dev)
tass 68:0847e35d08a6 1332 {
TASS Belgium NV 131:4758606c9316 1333 struct pico_tree_node *index = NULL;
TASS Belgium NV 131:4758606c9316 1334 struct pico_ipv4_link *link = NULL;
tass 68:0847e35d08a6 1335
tass 152:a3d286bf94e5 1336 pico_tree_foreach(index, &Tree_dev_link) {
TASS Belgium NV 131:4758606c9316 1337 link = index->keyValue;
TASS Belgium NV 131:4758606c9316 1338 if (link->dev == dev)
TASS Belgium NV 131:4758606c9316 1339 return link;
TASS Belgium NV 131:4758606c9316 1340 }
TASS Belgium NV 131:4758606c9316 1341 return NULL;
tass 68:0847e35d08a6 1342 }
tass 68:0847e35d08a6 1343
tass 74:c146c4e346c4 1344 struct pico_ipv4_link *pico_ipv4_link_by_dev_next(struct pico_device *dev, struct pico_ipv4_link *last)
tass 74:c146c4e346c4 1345 {
TASS Belgium NV 131:4758606c9316 1346 struct pico_tree_node *index = NULL;
TASS Belgium NV 131:4758606c9316 1347 struct pico_ipv4_link *link = NULL;
TASS Belgium NV 131:4758606c9316 1348 int valid = 0;
tass 74:c146c4e346c4 1349
TASS Belgium NV 131:4758606c9316 1350 if (last == NULL)
TASS Belgium NV 131:4758606c9316 1351 valid = 1;
tass 74:c146c4e346c4 1352
tass 152:a3d286bf94e5 1353 pico_tree_foreach(index, &Tree_dev_link) {
TASS Belgium NV 131:4758606c9316 1354 link = index->keyValue;
TASS Belgium NV 131:4758606c9316 1355 if (link->dev == dev) {
TASS Belgium NV 131:4758606c9316 1356 if (last == link)
TASS Belgium NV 131:4758606c9316 1357 valid = 1;
TASS Belgium NV 131:4758606c9316 1358 else if (valid > 0)
TASS Belgium NV 131:4758606c9316 1359 return link;
TASS Belgium NV 131:4758606c9316 1360 }
tass 74:c146c4e346c4 1361 }
TASS Belgium NV 131:4758606c9316 1362 return NULL;
tass 74:c146c4e346c4 1363 }
tass 68:0847e35d08a6 1364
tass 152:a3d286bf94e5 1365 struct pico_device *MOCKABLE pico_ipv4_link_find(struct pico_ip4 *address)
tass 68:0847e35d08a6 1366 {
TASS Belgium NV 131:4758606c9316 1367 struct pico_ipv4_link test, *found;
tass 152:a3d286bf94e5 1368 if (!address) {
TASS Belgium NV 131:4758606c9316 1369 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1370 return NULL;
TASS Belgium NV 131:4758606c9316 1371 }
TASS Belgium NV 131:4758606c9316 1372
TASS Belgium NV 131:4758606c9316 1373 test.dev = NULL;
TASS Belgium NV 131:4758606c9316 1374 test.address.addr = address->addr;
TASS Belgium NV 131:4758606c9316 1375 found = pico_tree_findKey(&Tree_dev_link, &test);
TASS Belgium NV 131:4758606c9316 1376 if (!found) {
TASS Belgium NV 131:4758606c9316 1377 pico_err = PICO_ERR_ENXIO;
TASS Belgium NV 131:4758606c9316 1378 return NULL;
TASS Belgium NV 131:4758606c9316 1379 }
TASS Belgium NV 131:4758606c9316 1380
TASS Belgium NV 131:4758606c9316 1381 return found->dev;
tass 68:0847e35d08a6 1382 }
tass 68:0847e35d08a6 1383
tass picotcp@tass.be 149:5f4cb161cec3 1384
tass picotcp@tass.be 149:5f4cb161cec3 1385 static int pico_ipv4_rebound_large(struct pico_frame *f)
tass picotcp@tass.be 149:5f4cb161cec3 1386 {
tass 152:a3d286bf94e5 1387 #ifdef PICO_SUPPORT_IPV4FRAG
tass 152:a3d286bf94e5 1388 uint16_t total_payload_written = 0;
tass picotcp@tass.be 149:5f4cb161cec3 1389 uint32_t len = f->transport_len;
tass picotcp@tass.be 149:5f4cb161cec3 1390 struct pico_frame *fr;
tass picotcp@tass.be 149:5f4cb161cec3 1391 struct pico_ip4 dst;
tass picotcp@tass.be 149:5f4cb161cec3 1392 struct pico_ipv4_hdr *hdr;
tass picotcp@tass.be 149:5f4cb161cec3 1393 hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass picotcp@tass.be 149:5f4cb161cec3 1394 dst.addr = hdr->src.addr;
tass picotcp@tass.be 149:5f4cb161cec3 1395
tass picotcp@tass.be 149:5f4cb161cec3 1396 while(total_payload_written < len) {
tass picotcp@tass.be 149:5f4cb161cec3 1397 uint32_t space = (uint32_t)len - total_payload_written;
tass picotcp@tass.be 149:5f4cb161cec3 1398 if (space > PICO_IPV4_MAXPAYLOAD)
tass picotcp@tass.be 149:5f4cb161cec3 1399 space = PICO_IPV4_MAXPAYLOAD;
tass picotcp@tass.be 149:5f4cb161cec3 1400
tass picotcp@tass.be 149:5f4cb161cec3 1401 fr = pico_ipv4_alloc(&pico_proto_ipv4, (uint16_t)space);
tass picotcp@tass.be 149:5f4cb161cec3 1402 if (!fr) {
tass picotcp@tass.be 149:5f4cb161cec3 1403 pico_err = PICO_ERR_ENOMEM;
tass picotcp@tass.be 149:5f4cb161cec3 1404 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1405 }
tass picotcp@tass.be 149:5f4cb161cec3 1406
tass picotcp@tass.be 149:5f4cb161cec3 1407 if (space + total_payload_written < len)
tass 152:a3d286bf94e5 1408 {
tass 152:a3d286bf94e5 1409 fr->frag |= PICO_IPV4_MOREFRAG;
tass 152:a3d286bf94e5 1410 }
tass picotcp@tass.be 149:5f4cb161cec3 1411 else
tass 152:a3d286bf94e5 1412 {
tass 152:a3d286bf94e5 1413 fr->frag &= PICO_IPV4_FRAG_MASK;
tass 152:a3d286bf94e5 1414 }
tass picotcp@tass.be 149:5f4cb161cec3 1415
tass 152:a3d286bf94e5 1416 fr->frag = (((total_payload_written) >> 3u) & 0xffffu) | fr->frag;
tass picotcp@tass.be 149:5f4cb161cec3 1417
tass picotcp@tass.be 149:5f4cb161cec3 1418 memcpy(fr->transport_hdr, f->transport_hdr + total_payload_written, fr->transport_len);
tass picotcp@tass.be 149:5f4cb161cec3 1419 if (pico_ipv4_frame_push(fr, &dst, hdr->proto) > 0) {
tass 152:a3d286bf94e5 1420 total_payload_written = (uint16_t)((uint16_t)fr->transport_len + total_payload_written);
tass picotcp@tass.be 149:5f4cb161cec3 1421 } else {
tass picotcp@tass.be 149:5f4cb161cec3 1422 pico_frame_discard(fr);
tass picotcp@tass.be 149:5f4cb161cec3 1423 break;
tass picotcp@tass.be 149:5f4cb161cec3 1424 }
tass picotcp@tass.be 149:5f4cb161cec3 1425 } /* while() */
tass picotcp@tass.be 149:5f4cb161cec3 1426 return (int)total_payload_written;
tass picotcp@tass.be 149:5f4cb161cec3 1427 #else
tass 152:a3d286bf94e5 1428 (void)f;
tass picotcp@tass.be 149:5f4cb161cec3 1429 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 1430 #endif
tass picotcp@tass.be 149:5f4cb161cec3 1431 }
tass picotcp@tass.be 149:5f4cb161cec3 1432
tass 68:0847e35d08a6 1433 int pico_ipv4_rebound(struct pico_frame *f)
tass 68:0847e35d08a6 1434 {
TASS Belgium NV 131:4758606c9316 1435 struct pico_ip4 dst;
TASS Belgium NV 131:4758606c9316 1436 struct pico_ipv4_hdr *hdr;
tass 152:a3d286bf94e5 1437 if (!f) {
TASS Belgium NV 131:4758606c9316 1438 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1439 return -1;
TASS Belgium NV 131:4758606c9316 1440 }
tass 68:0847e35d08a6 1441
TASS Belgium NV 131:4758606c9316 1442 hdr = (struct pico_ipv4_hdr *) f->net_hdr;
TASS Belgium NV 131:4758606c9316 1443 if (!hdr) {
TASS Belgium NV 131:4758606c9316 1444 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 1445 return -1;
TASS Belgium NV 131:4758606c9316 1446 }
TASS Belgium NV 131:4758606c9316 1447
TASS Belgium NV 131:4758606c9316 1448 dst.addr = hdr->src.addr;
tass picotcp@tass.be 149:5f4cb161cec3 1449 if (f->transport_len > PICO_IPV4_MAXPAYLOAD) {
tass picotcp@tass.be 149:5f4cb161cec3 1450 return pico_ipv4_rebound_large(f);
tass picotcp@tass.be 149:5f4cb161cec3 1451 }
tass picotcp@tass.be 149:5f4cb161cec3 1452
TASS Belgium NV 131:4758606c9316 1453 return pico_ipv4_frame_push(f, &dst, hdr->proto);
tass 68:0847e35d08a6 1454 }
tass 68:0847e35d08a6 1455
tass 152:a3d286bf94e5 1456 static int pico_ipv4_pre_forward_checks(struct pico_frame *f)
tass 152:a3d286bf94e5 1457 {
tass 152:a3d286bf94e5 1458 static uint16_t last_id = 0;
tass 152:a3d286bf94e5 1459 static uint16_t last_proto = 0;
tass 152:a3d286bf94e5 1460 static struct pico_ip4 last_src = {
tass 152:a3d286bf94e5 1461 0
tass 152:a3d286bf94e5 1462 };
tass 152:a3d286bf94e5 1463 static struct pico_ip4 last_dst = {
tass 152:a3d286bf94e5 1464 0
tass 152:a3d286bf94e5 1465 };
tass 152:a3d286bf94e5 1466 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr;
tass 152:a3d286bf94e5 1467
tass 152:a3d286bf94e5 1468 /* Decrease TTL, check if expired */
tass 152:a3d286bf94e5 1469 hdr->ttl = (uint8_t)(hdr->ttl - 1);
tass 152:a3d286bf94e5 1470 if (hdr->ttl < 1) {
tass 152:a3d286bf94e5 1471 pico_notify_ttl_expired(f);
tass 152:a3d286bf94e5 1472 dbg(" ------------------- TTL EXPIRED\n");
tass 152:a3d286bf94e5 1473 return -1;
tass 152:a3d286bf94e5 1474 }
tass 152:a3d286bf94e5 1475
tass 152:a3d286bf94e5 1476 /* HACK: increase crc to compensate decreased TTL */
tass 152:a3d286bf94e5 1477 hdr->crc++;
tass 152:a3d286bf94e5 1478
tass 152:a3d286bf94e5 1479 /* If source is local, discard anyway (packets bouncing back and forth) */
tass 152:a3d286bf94e5 1480 if (pico_ipv4_link_get(&hdr->src))
tass 152:a3d286bf94e5 1481 return -1;
tass 152:a3d286bf94e5 1482
tass 152:a3d286bf94e5 1483 /* If this was the last forwarded packet, silently discard to prevent duplications */
tass 152:a3d286bf94e5 1484 if ((last_src.addr == hdr->src.addr) && (last_id == hdr->id)
tass 152:a3d286bf94e5 1485 && (last_dst.addr == hdr->dst.addr) && (last_proto == hdr->proto)) {
tass 152:a3d286bf94e5 1486 return -1;
tass 152:a3d286bf94e5 1487 } else {
tass 152:a3d286bf94e5 1488 last_src.addr = hdr->src.addr;
tass 152:a3d286bf94e5 1489 last_dst.addr = hdr->dst.addr;
tass 152:a3d286bf94e5 1490 last_id = hdr->id;
tass 152:a3d286bf94e5 1491 last_proto = hdr->proto;
tass 152:a3d286bf94e5 1492 }
tass 152:a3d286bf94e5 1493
tass 152:a3d286bf94e5 1494 return 0;
tass 152:a3d286bf94e5 1495 }
tass 152:a3d286bf94e5 1496
tass 152:a3d286bf94e5 1497 static int pico_ipv4_forward_check_dev(struct pico_frame *f)
tass 152:a3d286bf94e5 1498 {
tass 152:a3d286bf94e5 1499 if (f->dev->eth != NULL)
tass 152:a3d286bf94e5 1500 f->len -= PICO_SIZE_ETHHDR;
tass 152:a3d286bf94e5 1501
tass 152:a3d286bf94e5 1502 if (f->len > f->dev->mtu) {
tass 152:a3d286bf94e5 1503 pico_notify_pkt_too_big(f);
tass 152:a3d286bf94e5 1504 return -1;
tass 152:a3d286bf94e5 1505 }
tass 152:a3d286bf94e5 1506
tass 152:a3d286bf94e5 1507 return 0;
tass 152:a3d286bf94e5 1508 }
tass 152:a3d286bf94e5 1509
tass 68:0847e35d08a6 1510 static int pico_ipv4_forward(struct pico_frame *f)
tass 68:0847e35d08a6 1511 {
TASS Belgium NV 131:4758606c9316 1512 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *)f->net_hdr;
TASS Belgium NV 131:4758606c9316 1513 struct pico_ipv4_route *rt;
TASS Belgium NV 131:4758606c9316 1514 if (!hdr) {
TASS Belgium NV 131:4758606c9316 1515 return -1;
TASS Belgium NV 131:4758606c9316 1516 }
tass 68:0847e35d08a6 1517
TASS Belgium NV 131:4758606c9316 1518 rt = route_find(&hdr->dst);
TASS Belgium NV 131:4758606c9316 1519 if (!rt) {
TASS Belgium NV 131:4758606c9316 1520 pico_notify_dest_unreachable(f);
TASS Belgium NV 131:4758606c9316 1521 return -1;
TASS Belgium NV 131:4758606c9316 1522 }
tass 110:0ece1bbbd36e 1523
TASS Belgium NV 131:4758606c9316 1524 f->dev = rt->link->dev;
tass 152:a3d286bf94e5 1525
tass 152:a3d286bf94e5 1526 if (pico_ipv4_pre_forward_checks(f) < 0)
TASS Belgium NV 131:4758606c9316 1527 return -1;
TASS Belgium NV 131:4758606c9316 1528
TASS Belgium NV 131:4758606c9316 1529 pico_ipv4_nat_outbound(f, &rt->link->address);
tass 68:0847e35d08a6 1530
TASS Belgium NV 131:4758606c9316 1531 f->start = f->net_hdr;
tass 152:a3d286bf94e5 1532
tass 152:a3d286bf94e5 1533 if (pico_ipv4_forward_check_dev(f) < 0)
tass 152:a3d286bf94e5 1534 return -1;
TASS Belgium NV 131:4758606c9316 1535
TASS Belgium NV 131:4758606c9316 1536 pico_sendto_dev(f);
TASS Belgium NV 131:4758606c9316 1537 return 0;
tass 68:0847e35d08a6 1538
tass 68:0847e35d08a6 1539 }
tass 68:0847e35d08a6 1540
tass 68:0847e35d08a6 1541 int pico_ipv4_is_broadcast(uint32_t addr)
tass 68:0847e35d08a6 1542 {
TASS Belgium NV 131:4758606c9316 1543 struct pico_ipv4_link *link;
TASS Belgium NV 131:4758606c9316 1544 struct pico_tree_node *index;
TASS Belgium NV 131:4758606c9316 1545 if (addr == PICO_IP4_BCAST)
TASS Belgium NV 131:4758606c9316 1546 return 1;
TASS Belgium NV 131:4758606c9316 1547
TASS Belgium NV 131:4758606c9316 1548 pico_tree_foreach(index, &Tree_dev_link) {
TASS Belgium NV 131:4758606c9316 1549 link = index->keyValue;
TASS Belgium NV 131:4758606c9316 1550 if ((link->address.addr | (~link->netmask.addr)) == addr)
TASS Belgium NV 131:4758606c9316 1551 return 1;
TASS Belgium NV 131:4758606c9316 1552 }
TASS Belgium NV 131:4758606c9316 1553 return 0;
tass 68:0847e35d08a6 1554 }
tass 68:0847e35d08a6 1555
tass 68:0847e35d08a6 1556 void pico_ipv4_unreachable(struct pico_frame *f, int err)
tass 68:0847e35d08a6 1557 {
TASS Belgium NV 131:4758606c9316 1558 struct pico_ipv4_hdr *hdr = (struct pico_ipv4_hdr *) f->net_hdr;
tass 68:0847e35d08a6 1559 #if defined PICO_SUPPORT_TCP || defined PICO_SUPPORT_UDP
TASS Belgium NV 131:4758606c9316 1560 f->transport_hdr = ((uint8_t *)f->net_hdr) + PICO_SIZE_IP4HDR;
TASS Belgium NV 131:4758606c9316 1561 pico_transport_error(f, hdr->proto, err);
tass 68:0847e35d08a6 1562 #endif
tass 68:0847e35d08a6 1563 }
tass 68:0847e35d08a6 1564
tass picotcp@tass.be 149:5f4cb161cec3 1565 int pico_ipv4_cleanup_links(struct pico_device *dev)
tass picotcp@tass.be 149:5f4cb161cec3 1566 {
tass picotcp@tass.be 149:5f4cb161cec3 1567 struct pico_tree_node *index = NULL, *_tmp = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 1568 struct pico_ipv4_link *link = NULL;
tass picotcp@tass.be 149:5f4cb161cec3 1569
tass 152:a3d286bf94e5 1570 pico_tree_foreach_safe(index, &Tree_dev_link, _tmp) {
tass picotcp@tass.be 149:5f4cb161cec3 1571 link = index->keyValue;
tass picotcp@tass.be 149:5f4cb161cec3 1572 if (dev == link->dev)
tass picotcp@tass.be 149:5f4cb161cec3 1573 pico_ipv4_link_del(dev, link->address);
tass picotcp@tass.be 149:5f4cb161cec3 1574 }
tass picotcp@tass.be 149:5f4cb161cec3 1575 return 0;
tass picotcp@tass.be 149:5f4cb161cec3 1576 }
tass picotcp@tass.be 149:5f4cb161cec3 1577
tass picotcp@tass.be 149:5f4cb161cec3 1578
tass 68:0847e35d08a6 1579 #endif