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 RTOSgeneric mbed Ethernet driverhigh performance NXP LPC1768 specific Ethernet driverMulti-threading support for mbed RTOSBerkeley sockets and integration with the New Socket APIFork of the apps running on top of the New Socket APIScheduling 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.
modules/pico_ipfilter.c@152:a3d286bf94e5, 2015-09-28 (annotated)
- Committer:
- tass
- Date:
- Mon Sep 28 13:16:18 2015 +0200
- Revision:
- 152:a3d286bf94e5
- Parent:
- 149:5f4cb161cec3
- Child:
- 154:6c0e92a80c4a
Mercurial: latest development version of PicoTCP
Who changed what in which revision?
User | Revision | Line number | New 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: Andrei Carp |
TASS Belgium NV |
131:4758606c9316 | 6 | Simon Maes |
TASS Belgium NV |
131:4758606c9316 | 7 | *********************************************************************/ |
tass | 68:0847e35d08a6 | 8 | |
tass | 68:0847e35d08a6 | 9 | #include "pico_ipv4.h" |
tass | 68:0847e35d08a6 | 10 | #include "pico_config.h" |
tass | 68:0847e35d08a6 | 11 | #include "pico_icmp4.h" |
tass | 68:0847e35d08a6 | 12 | #include "pico_stack.h" |
tass | 68:0847e35d08a6 | 13 | #include "pico_eth.h" |
tass | 68:0847e35d08a6 | 14 | #include "pico_socket.h" |
tass | 68:0847e35d08a6 | 15 | #include "pico_device.h" |
tass | 68:0847e35d08a6 | 16 | #include "pico_ipfilter.h" |
tass | 68:0847e35d08a6 | 17 | #include "pico_tcp.h" |
tass | 68:0847e35d08a6 | 18 | #include "pico_udp.h" |
tass | 125:96003ae6f1d8 | 19 | #include "pico_tree.h" |
tass | 68:0847e35d08a6 | 20 | |
tass | 125:96003ae6f1d8 | 21 | /**************** LOCAL MACROS ****************/ |
TASS Belgium NV |
131:4758606c9316 | 22 | #define MAX_PRIORITY (10) |
TASS Belgium NV |
131:4758606c9316 | 23 | #define MIN_PRIORITY (-10) |
tass | 125:96003ae6f1d8 | 24 | |
TASS Belgium NV |
131:4758606c9316 | 25 | #define ipf_dbg(...) do {} while(0) |
tass | 68:0847e35d08a6 | 26 | |
tass | 125:96003ae6f1d8 | 27 | /**************** LOCAL DECLARATIONS ****************/ |
tass | 68:0847e35d08a6 | 28 | struct filter_node; |
tass | 125:96003ae6f1d8 | 29 | static int filter_compare(void *filterA, void *filterB); |
tass | 125:96003ae6f1d8 | 30 | |
tass | 125:96003ae6f1d8 | 31 | /**************** FILTER TREE ****************/ |
tass | 68:0847e35d08a6 | 32 | |
tass | 68:0847e35d08a6 | 33 | struct filter_node { |
TASS Belgium NV |
131:4758606c9316 | 34 | struct pico_device *fdev; |
TASS Belgium NV |
131:4758606c9316 | 35 | /* output address */ |
TASS Belgium NV |
131:4758606c9316 | 36 | uint32_t out_addr; |
TASS Belgium NV |
131:4758606c9316 | 37 | uint32_t out_addr_netmask; |
TASS Belgium NV |
131:4758606c9316 | 38 | /* input address */ |
TASS Belgium NV |
131:4758606c9316 | 39 | uint32_t in_addr; |
TASS Belgium NV |
131:4758606c9316 | 40 | uint32_t in_addr_netmask; |
TASS Belgium NV |
131:4758606c9316 | 41 | /* transport */ |
TASS Belgium NV |
131:4758606c9316 | 42 | uint16_t out_port; |
TASS Belgium NV |
131:4758606c9316 | 43 | uint16_t in_port; |
TASS Belgium NV |
131:4758606c9316 | 44 | /* filter details */ |
TASS Belgium NV |
131:4758606c9316 | 45 | uint8_t proto; |
TASS Belgium NV |
131:4758606c9316 | 46 | int8_t priority; |
TASS Belgium NV |
131:4758606c9316 | 47 | uint8_t tos; |
tass | 152:a3d286bf94e5 | 48 | uint32_t filter_id; |
TASS Belgium NV |
131:4758606c9316 | 49 | int (*function_ptr)(struct filter_node *filter, struct pico_frame *f); |
tass | 68:0847e35d08a6 | 50 | }; |
tass | 68:0847e35d08a6 | 51 | |
TASS Belgium NV |
131:4758606c9316 | 52 | PICO_TREE_DECLARE(filter_tree, &filter_compare); |
tass | 125:96003ae6f1d8 | 53 | |
tass | 152:a3d286bf94e5 | 54 | static inline int ipfilter_uint32_cmp(uint32_t a, uint32_t b) |
tass | 152:a3d286bf94e5 | 55 | { |
tass | 152:a3d286bf94e5 | 56 | if (a < b) |
tass | 152:a3d286bf94e5 | 57 | return -1; |
tass | 152:a3d286bf94e5 | 58 | |
tass | 152:a3d286bf94e5 | 59 | if (b < a) |
tass | 152:a3d286bf94e5 | 60 | return 1; |
tass | 152:a3d286bf94e5 | 61 | |
tass | 152:a3d286bf94e5 | 62 | return 0; |
tass | 152:a3d286bf94e5 | 63 | } |
tass | 152:a3d286bf94e5 | 64 | |
tass | 152:a3d286bf94e5 | 65 | static inline int ipfilter_uint16_cmp(uint16_t a, uint16_t b) |
tass | 152:a3d286bf94e5 | 66 | { |
tass | 152:a3d286bf94e5 | 67 | if (a < b) |
tass | 152:a3d286bf94e5 | 68 | return -1; |
tass | 152:a3d286bf94e5 | 69 | |
tass | 152:a3d286bf94e5 | 70 | if (b < a) |
tass | 152:a3d286bf94e5 | 71 | return 1; |
tass | 152:a3d286bf94e5 | 72 | |
tass | 152:a3d286bf94e5 | 73 | return 0; |
tass | 152:a3d286bf94e5 | 74 | } |
tass | 152:a3d286bf94e5 | 75 | |
tass | 152:a3d286bf94e5 | 76 | static inline int ipfilter_uint8_cmp(uint8_t a, uint8_t b) |
tass | 152:a3d286bf94e5 | 77 | { |
tass | 152:a3d286bf94e5 | 78 | if (a < b) |
tass | 152:a3d286bf94e5 | 79 | return -1; |
tass | 152:a3d286bf94e5 | 80 | |
tass | 152:a3d286bf94e5 | 81 | if (b < a) |
tass | 152:a3d286bf94e5 | 82 | return 1; |
tass | 152:a3d286bf94e5 | 83 | |
tass | 152:a3d286bf94e5 | 84 | return 0; |
tass | 152:a3d286bf94e5 | 85 | } |
tass | 152:a3d286bf94e5 | 86 | |
tass | 152:a3d286bf94e5 | 87 | static inline int ipfilter_ptr_cmp(void *a, void *b) |
tass | 152:a3d286bf94e5 | 88 | { |
tass | 152:a3d286bf94e5 | 89 | if (a < b) |
tass | 152:a3d286bf94e5 | 90 | return -1; |
tass | 152:a3d286bf94e5 | 91 | |
tass | 152:a3d286bf94e5 | 92 | if (b < a) |
tass | 152:a3d286bf94e5 | 93 | return 1; |
tass | 152:a3d286bf94e5 | 94 | |
tass | 152:a3d286bf94e5 | 95 | return 0; |
tass | 152:a3d286bf94e5 | 96 | } |
tass | 152:a3d286bf94e5 | 97 | |
tass | 152:a3d286bf94e5 | 98 | |
tass | 152:a3d286bf94e5 | 99 | |
tass | 152:a3d286bf94e5 | 100 | static inline int filter_compare_ports(struct filter_node *a, struct filter_node *b) |
tass | 152:a3d286bf94e5 | 101 | { |
tass | 152:a3d286bf94e5 | 102 | int cmp; |
tass | 152:a3d286bf94e5 | 103 | cmp = ipfilter_uint16_cmp(a->in_port, b->in_port); |
tass | 152:a3d286bf94e5 | 104 | if (cmp) |
tass | 152:a3d286bf94e5 | 105 | return cmp; |
tass | 152:a3d286bf94e5 | 106 | |
tass | 152:a3d286bf94e5 | 107 | cmp = ipfilter_uint16_cmp(a->out_port, b->out_port); |
tass | 152:a3d286bf94e5 | 108 | return cmp; |
tass | 152:a3d286bf94e5 | 109 | } |
tass | 152:a3d286bf94e5 | 110 | |
tass | 152:a3d286bf94e5 | 111 | static inline int filter_compare_addresses(struct filter_node *a, struct filter_node *b) |
tass | 152:a3d286bf94e5 | 112 | { |
tass | 152:a3d286bf94e5 | 113 | int cmp; |
tass | 152:a3d286bf94e5 | 114 | /* Compare source address */ |
tass | 152:a3d286bf94e5 | 115 | cmp = ipfilter_uint32_cmp((a->in_addr & a->in_addr_netmask), (b->in_addr & b->in_addr_netmask)); |
tass | 152:a3d286bf94e5 | 116 | if (cmp) |
tass | 152:a3d286bf94e5 | 117 | return cmp; |
tass | 152:a3d286bf94e5 | 118 | |
tass | 152:a3d286bf94e5 | 119 | /* Compare destination address */ |
tass | 152:a3d286bf94e5 | 120 | cmp = ipfilter_uint32_cmp((a->out_addr & a->out_addr_netmask), (b->out_addr & b->out_addr_netmask)); |
tass | 152:a3d286bf94e5 | 121 | return cmp; |
tass | 152:a3d286bf94e5 | 122 | } |
tass | 152:a3d286bf94e5 | 123 | |
tass | 152:a3d286bf94e5 | 124 | static inline int filter_compare_proto(struct filter_node *a, struct filter_node *b) |
tass | 152:a3d286bf94e5 | 125 | { |
tass | 152:a3d286bf94e5 | 126 | return ipfilter_uint8_cmp(a->proto, b->proto); |
tass | 152:a3d286bf94e5 | 127 | } |
tass | 152:a3d286bf94e5 | 128 | |
tass | 152:a3d286bf94e5 | 129 | static inline int filter_compare_address_port(struct filter_node *a, struct filter_node *b) |
tass | 152:a3d286bf94e5 | 130 | { |
tass | 152:a3d286bf94e5 | 131 | int cmp; |
tass | 152:a3d286bf94e5 | 132 | cmp = filter_compare_addresses(a, b); |
tass | 152:a3d286bf94e5 | 133 | if (cmp) |
tass | 152:a3d286bf94e5 | 134 | return cmp; |
tass | 152:a3d286bf94e5 | 135 | |
tass | 152:a3d286bf94e5 | 136 | return filter_compare_ports(a, b); |
tass | 152:a3d286bf94e5 | 137 | } |
tass | 152:a3d286bf94e5 | 138 | |
tass | 152:a3d286bf94e5 | 139 | static inline int filter_match_packet_dev(struct filter_node *a, struct filter_node *b, struct filter_node *rule) |
tass | 152:a3d286bf94e5 | 140 | { |
tass | 152:a3d286bf94e5 | 141 | int cmp; |
tass | 152:a3d286bf94e5 | 142 | /* 1. Compare devices */ |
tass | 152:a3d286bf94e5 | 143 | if (rule->fdev) { |
tass | 152:a3d286bf94e5 | 144 | cmp = ipfilter_ptr_cmp(a->fdev, b->fdev); |
tass | 152:a3d286bf94e5 | 145 | if (cmp) |
tass | 152:a3d286bf94e5 | 146 | return cmp; |
tass | 152:a3d286bf94e5 | 147 | } |
tass | 152:a3d286bf94e5 | 148 | |
tass | 152:a3d286bf94e5 | 149 | return 0; |
tass | 152:a3d286bf94e5 | 150 | |
tass | 152:a3d286bf94e5 | 151 | } |
tass | 152:a3d286bf94e5 | 152 | |
tass | 152:a3d286bf94e5 | 153 | static inline int filter_match_packet_proto(struct filter_node *a, struct filter_node *b, struct filter_node *rule) |
tass | 152:a3d286bf94e5 | 154 | { |
tass | 152:a3d286bf94e5 | 155 | int cmp; |
tass | 152:a3d286bf94e5 | 156 | /* 2. Compare protocol */ |
tass | 152:a3d286bf94e5 | 157 | if (rule->proto) { |
tass | 152:a3d286bf94e5 | 158 | cmp = filter_compare_proto(a, b); |
tass | 152:a3d286bf94e5 | 159 | if (cmp) |
tass | 152:a3d286bf94e5 | 160 | return cmp; |
tass | 152:a3d286bf94e5 | 161 | } |
tass | 152:a3d286bf94e5 | 162 | |
tass | 152:a3d286bf94e5 | 163 | return 0; |
tass | 152:a3d286bf94e5 | 164 | |
tass | 152:a3d286bf94e5 | 165 | } |
tass | 152:a3d286bf94e5 | 166 | static inline int filter_match_packet_addr_in(struct filter_node *a, struct filter_node *b, struct filter_node *rule) |
tass | 152:a3d286bf94e5 | 167 | { |
tass | 152:a3d286bf94e5 | 168 | int cmp; |
tass | 152:a3d286bf94e5 | 169 | /* 3. Compare addresses order: in, out */ |
tass | 152:a3d286bf94e5 | 170 | if (rule->in_addr_netmask) { |
tass | 152:a3d286bf94e5 | 171 | cmp = ipfilter_uint32_cmp(a->in_addr & rule->in_addr_netmask, b->in_addr & rule->in_addr_netmask); |
tass | 152:a3d286bf94e5 | 172 | if (cmp) |
tass | 152:a3d286bf94e5 | 173 | return cmp; |
tass | 152:a3d286bf94e5 | 174 | } |
tass | 152:a3d286bf94e5 | 175 | |
tass | 152:a3d286bf94e5 | 176 | return 0; |
tass | 152:a3d286bf94e5 | 177 | } |
tass | 152:a3d286bf94e5 | 178 | static inline int filter_match_packet_addr_out(struct filter_node *a, struct filter_node *b, struct filter_node *rule) |
tass | 152:a3d286bf94e5 | 179 | { |
tass | 152:a3d286bf94e5 | 180 | int cmp; |
tass | 152:a3d286bf94e5 | 181 | if (rule->out_addr_netmask) { |
tass | 152:a3d286bf94e5 | 182 | cmp = ipfilter_uint32_cmp(a->out_addr & rule->out_addr_netmask, b->out_addr & rule->out_addr_netmask); |
tass | 152:a3d286bf94e5 | 183 | if (cmp) { |
tass | 152:a3d286bf94e5 | 184 | return cmp; |
tass | 152:a3d286bf94e5 | 185 | } |
tass | 152:a3d286bf94e5 | 186 | } |
tass | 152:a3d286bf94e5 | 187 | |
tass | 152:a3d286bf94e5 | 188 | return 0; |
tass | 152:a3d286bf94e5 | 189 | } |
tass | 152:a3d286bf94e5 | 190 | static inline int filter_match_packet_port_in(struct filter_node *a, struct filter_node *b, struct filter_node *rule) |
tass | 152:a3d286bf94e5 | 191 | { |
tass | 152:a3d286bf94e5 | 192 | int cmp; |
tass | 152:a3d286bf94e5 | 193 | /* 4. Compare ports order: in, out */ |
tass | 152:a3d286bf94e5 | 194 | if (rule->in_port) { |
tass | 152:a3d286bf94e5 | 195 | cmp = ipfilter_uint16_cmp(a->in_port, b->in_port); |
tass | 152:a3d286bf94e5 | 196 | if (cmp) |
tass | 152:a3d286bf94e5 | 197 | return cmp; |
tass | 152:a3d286bf94e5 | 198 | } |
tass | 152:a3d286bf94e5 | 199 | |
tass | 152:a3d286bf94e5 | 200 | return 0; |
tass | 152:a3d286bf94e5 | 201 | } |
tass | 152:a3d286bf94e5 | 202 | static inline int filter_match_packet_port_out(struct filter_node *a, struct filter_node *b, struct filter_node *rule) |
tass | 152:a3d286bf94e5 | 203 | { |
tass | 152:a3d286bf94e5 | 204 | int cmp; |
tass | 152:a3d286bf94e5 | 205 | if (rule->out_port) { |
tass | 152:a3d286bf94e5 | 206 | cmp = ipfilter_uint16_cmp(a->out_port, b->out_port); |
tass | 152:a3d286bf94e5 | 207 | if (cmp) |
tass | 152:a3d286bf94e5 | 208 | return cmp; |
tass | 152:a3d286bf94e5 | 209 | } |
tass | 152:a3d286bf94e5 | 210 | |
tass | 152:a3d286bf94e5 | 211 | return 0; |
tass | 152:a3d286bf94e5 | 212 | } |
tass | 152:a3d286bf94e5 | 213 | |
tass | 152:a3d286bf94e5 | 214 | static inline int filter_match_packet_dev_and_proto(struct filter_node *a, struct filter_node *b, struct filter_node *rule) |
tass | 152:a3d286bf94e5 | 215 | { |
tass | 152:a3d286bf94e5 | 216 | int cmp = filter_match_packet_dev(a, b, rule); |
tass | 152:a3d286bf94e5 | 217 | if (cmp) |
tass | 152:a3d286bf94e5 | 218 | return cmp; |
tass | 152:a3d286bf94e5 | 219 | |
tass | 152:a3d286bf94e5 | 220 | return filter_match_packet_proto(a, b, rule); |
tass | 152:a3d286bf94e5 | 221 | } |
tass | 152:a3d286bf94e5 | 222 | |
tass | 152:a3d286bf94e5 | 223 | static inline int filter_match_packet_addr(struct filter_node *a, struct filter_node *b, struct filter_node *rule) |
tass | 152:a3d286bf94e5 | 224 | { |
tass | 152:a3d286bf94e5 | 225 | int cmp = filter_match_packet_addr_in(a, b, rule); |
tass | 152:a3d286bf94e5 | 226 | if (cmp) |
tass | 152:a3d286bf94e5 | 227 | return cmp; |
tass | 152:a3d286bf94e5 | 228 | |
tass | 152:a3d286bf94e5 | 229 | return filter_match_packet_addr_out(a, b, rule); |
tass | 152:a3d286bf94e5 | 230 | |
tass | 152:a3d286bf94e5 | 231 | } |
tass | 152:a3d286bf94e5 | 232 | |
tass | 152:a3d286bf94e5 | 233 | static inline int filter_match_packet_port(struct filter_node *a, struct filter_node *b, struct filter_node *rule) |
tass | 152:a3d286bf94e5 | 234 | { |
tass | 152:a3d286bf94e5 | 235 | int cmp = filter_match_packet_port_in(a, b, rule); |
tass | 152:a3d286bf94e5 | 236 | if (cmp) |
tass | 152:a3d286bf94e5 | 237 | return cmp; |
tass | 152:a3d286bf94e5 | 238 | |
tass | 152:a3d286bf94e5 | 239 | return filter_match_packet_port_out(a, b, rule); |
tass | 152:a3d286bf94e5 | 240 | } |
tass | 152:a3d286bf94e5 | 241 | |
tass | 152:a3d286bf94e5 | 242 | static inline struct filter_node *filter_match_packet_find_rule(struct filter_node *a, struct filter_node *b) |
tass | 152:a3d286bf94e5 | 243 | { |
tass | 152:a3d286bf94e5 | 244 | if (!a->filter_id) |
tass | 152:a3d286bf94e5 | 245 | return b; |
tass | 152:a3d286bf94e5 | 246 | |
tass | 152:a3d286bf94e5 | 247 | return a; |
tass | 152:a3d286bf94e5 | 248 | } |
tass | 152:a3d286bf94e5 | 249 | |
tass | 152:a3d286bf94e5 | 250 | static inline int filter_match_packet(struct filter_node *a, struct filter_node *b) |
tass | 152:a3d286bf94e5 | 251 | { |
tass | 152:a3d286bf94e5 | 252 | struct filter_node *rule; |
tass | 152:a3d286bf94e5 | 253 | int cmp = 0; |
tass | 152:a3d286bf94e5 | 254 | rule = filter_match_packet_find_rule(a, b); |
tass | 152:a3d286bf94e5 | 255 | |
tass | 152:a3d286bf94e5 | 256 | cmp = filter_match_packet_dev_and_proto(a, b, rule); |
tass | 152:a3d286bf94e5 | 257 | if (cmp) |
tass | 152:a3d286bf94e5 | 258 | return cmp; |
tass | 152:a3d286bf94e5 | 259 | |
tass | 152:a3d286bf94e5 | 260 | cmp = filter_match_packet_addr(a, b, rule); |
tass | 152:a3d286bf94e5 | 261 | if (cmp) |
tass | 152:a3d286bf94e5 | 262 | return cmp; |
tass | 152:a3d286bf94e5 | 263 | |
tass | 152:a3d286bf94e5 | 264 | cmp = filter_match_packet_port(a, b, rule); |
tass | 152:a3d286bf94e5 | 265 | if (cmp) |
tass | 152:a3d286bf94e5 | 266 | return cmp; |
tass | 152:a3d286bf94e5 | 267 | |
tass | 152:a3d286bf94e5 | 268 | return 0; |
tass | 152:a3d286bf94e5 | 269 | } |
tass | 125:96003ae6f1d8 | 270 | |
tass | 68:0847e35d08a6 | 271 | |
tass | 125:96003ae6f1d8 | 272 | int filter_compare(void *filterA, void *filterB) |
tass | 125:96003ae6f1d8 | 273 | { |
tass | 152:a3d286bf94e5 | 274 | |
tass | 152:a3d286bf94e5 | 275 | struct filter_node *a = (struct filter_node *)filterA; |
tass | 152:a3d286bf94e5 | 276 | struct filter_node *b = (struct filter_node *)filterB; |
tass | 152:a3d286bf94e5 | 277 | int cmp = 0; |
tass | 152:a3d286bf94e5 | 278 | if (a->filter_id == 0 || b->filter_id == 0) { |
tass | 152:a3d286bf94e5 | 279 | return filter_match_packet(a, b); |
tass | 152:a3d286bf94e5 | 280 | } |
tass | 125:96003ae6f1d8 | 281 | |
TASS Belgium NV |
131:4758606c9316 | 282 | /* improve the search */ |
tass | 152:a3d286bf94e5 | 283 | if(a->filter_id == b->filter_id) |
TASS Belgium NV |
131:4758606c9316 | 284 | return 0; |
tass | 68:0847e35d08a6 | 285 | |
tass | 152:a3d286bf94e5 | 286 | /* 1. Compare devices */ |
tass | 152:a3d286bf94e5 | 287 | cmp = ipfilter_ptr_cmp(a->fdev, a->fdev); |
tass | 152:a3d286bf94e5 | 288 | if (cmp) |
tass | 152:a3d286bf94e5 | 289 | return cmp; |
tass | 125:96003ae6f1d8 | 290 | |
tass | 152:a3d286bf94e5 | 291 | /* 2. Compare protocol */ |
tass | 152:a3d286bf94e5 | 292 | cmp = filter_compare_proto(a, b); |
tass | 152:a3d286bf94e5 | 293 | if(cmp) |
tass | 152:a3d286bf94e5 | 294 | return cmp; |
tass | 152:a3d286bf94e5 | 295 | |
tass | 152:a3d286bf94e5 | 296 | /* 3. Compare addresses order: in, out */ |
tass | 152:a3d286bf94e5 | 297 | /* 4. Compare ports order: in, out */ |
tass | 152:a3d286bf94e5 | 298 | cmp = filter_compare_address_port(a, b); |
tass | 152:a3d286bf94e5 | 299 | |
tass | 152:a3d286bf94e5 | 300 | return cmp; |
tass | 68:0847e35d08a6 | 301 | } |
tass | 68:0847e35d08a6 | 302 | |
tass | 125:96003ae6f1d8 | 303 | /**************** FILTER CALLBACKS ****************/ |
tass | 125:96003ae6f1d8 | 304 | |
TASS Belgium NV |
131:4758606c9316 | 305 | static int fp_priority(struct filter_node *filter, struct pico_frame *f) |
TASS Belgium NV |
131:4758606c9316 | 306 | { |
TASS Belgium NV |
131:4758606c9316 | 307 | /* TODO do priority-stuff */ |
TASS Belgium NV |
131:4758606c9316 | 308 | IGNORE_PARAMETER(filter); |
TASS Belgium NV |
131:4758606c9316 | 309 | IGNORE_PARAMETER(f); |
TASS Belgium NV |
131:4758606c9316 | 310 | return 0; |
tass | 68:0847e35d08a6 | 311 | } |
tass | 68:0847e35d08a6 | 312 | |
TASS Belgium NV |
131:4758606c9316 | 313 | static int fp_reject(struct filter_node *filter, struct pico_frame *f) |
TASS Belgium NV |
131:4758606c9316 | 314 | { |
TASS Belgium NV |
131:4758606c9316 | 315 | /* TODO check first if sender is pico itself or not */ |
TASS Belgium NV |
131:4758606c9316 | 316 | IGNORE_PARAMETER(filter); |
TASS Belgium NV |
131:4758606c9316 | 317 | ipf_dbg("ipfilter> reject\n"); |
tass | 152:a3d286bf94e5 | 318 | (void)pico_icmp4_packet_filtered(f); |
TASS Belgium NV |
131:4758606c9316 | 319 | pico_frame_discard(f); |
TASS Belgium NV |
131:4758606c9316 | 320 | return 1; |
tass | 68:0847e35d08a6 | 321 | } |
tass | 68:0847e35d08a6 | 322 | |
TASS Belgium NV |
131:4758606c9316 | 323 | static int fp_drop(struct filter_node *filter, struct pico_frame *f) |
TASS Belgium NV |
131:4758606c9316 | 324 | { |
TASS Belgium NV |
131:4758606c9316 | 325 | IGNORE_PARAMETER(filter); |
TASS Belgium NV |
131:4758606c9316 | 326 | ipf_dbg("ipfilter> drop\n"); |
TASS Belgium NV |
131:4758606c9316 | 327 | pico_frame_discard(f); |
TASS Belgium NV |
131:4758606c9316 | 328 | return 1; |
tass | 68:0847e35d08a6 | 329 | } |
tass | 68:0847e35d08a6 | 330 | |
tass | 152:a3d286bf94e5 | 331 | struct fp_function { |
tass | 152:a3d286bf94e5 | 332 | int (*fn)(struct filter_node *filter, struct pico_frame *f); |
tass | 152:a3d286bf94e5 | 333 | }; |
tass | 152:a3d286bf94e5 | 334 | |
tass | 152:a3d286bf94e5 | 335 | |
tass | 152:a3d286bf94e5 | 336 | static const struct fp_function fp_function[FILTER_COUNT] = |
tass | 68:0847e35d08a6 | 337 | { |
tass | 152:a3d286bf94e5 | 338 | {&fp_priority}, |
tass | 152:a3d286bf94e5 | 339 | {&fp_reject}, |
tass | 152:a3d286bf94e5 | 340 | {&fp_drop} |
tass | 152:a3d286bf94e5 | 341 | }; |
tass | 68:0847e35d08a6 | 342 | |
tass | 152:a3d286bf94e5 | 343 | static int pico_ipv4_filter_add_validate(int8_t priority, enum filter_action action) |
tass | 152:a3d286bf94e5 | 344 | { |
tass | 152:a3d286bf94e5 | 345 | if ( priority > MAX_PRIORITY || priority < MIN_PRIORITY) { |
tass | 152:a3d286bf94e5 | 346 | return -1; |
tass | 152:a3d286bf94e5 | 347 | } |
tass | 152:a3d286bf94e5 | 348 | |
tass | 152:a3d286bf94e5 | 349 | if (action >= FILTER_COUNT) { |
TASS Belgium NV |
131:4758606c9316 | 350 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 351 | } |
TASS Belgium NV |
131:4758606c9316 | 352 | |
tass | 152:a3d286bf94e5 | 353 | return 0; |
tass | 152:a3d286bf94e5 | 354 | } |
tass | 152:a3d286bf94e5 | 355 | |
tass | 152:a3d286bf94e5 | 356 | |
tass | 152:a3d286bf94e5 | 357 | /**************** FILTER API's ****************/ |
tass | 152:a3d286bf94e5 | 358 | uint32_t pico_ipv4_filter_add(struct pico_device *dev, uint8_t proto, |
tass | 152:a3d286bf94e5 | 359 | struct pico_ip4 *out_addr, struct pico_ip4 *out_addr_netmask, |
tass | 152:a3d286bf94e5 | 360 | struct pico_ip4 *in_addr, struct pico_ip4 *in_addr_netmask, |
tass | 152:a3d286bf94e5 | 361 | uint16_t out_port, uint16_t in_port, int8_t priority, |
tass | 152:a3d286bf94e5 | 362 | uint8_t tos, enum filter_action action) |
tass | 152:a3d286bf94e5 | 363 | { |
tass | 152:a3d286bf94e5 | 364 | static uint32_t filter_id = 1u; /* 0 is a special value used in the binary-tree search for packets being processed */ |
tass | 152:a3d286bf94e5 | 365 | struct filter_node *new_filter; |
tass | 152:a3d286bf94e5 | 366 | |
tass | 152:a3d286bf94e5 | 367 | if (pico_ipv4_filter_add_validate(priority, action) < 0) { |
TASS Belgium NV |
131:4758606c9316 | 368 | pico_err = PICO_ERR_EINVAL; |
tass | 152:a3d286bf94e5 | 369 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 370 | } |
tass | 125:96003ae6f1d8 | 371 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 372 | new_filter = PICO_ZALLOC(sizeof(struct filter_node)); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 373 | if (!new_filter) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 374 | pico_err = PICO_ERR_ENOMEM; |
tass | 152:a3d286bf94e5 | 375 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 376 | } |
tass | 68:0847e35d08a6 | 377 | |
TASS Belgium NV |
131:4758606c9316 | 378 | new_filter->fdev = dev; |
TASS Belgium NV |
131:4758606c9316 | 379 | new_filter->proto = proto; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 380 | new_filter->out_addr = (!out_addr) ? (0U) : (out_addr->addr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 381 | new_filter->out_addr_netmask = (!out_addr_netmask) ? (0U) : (out_addr_netmask->addr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 382 | new_filter->in_addr = (!in_addr) ? (0U) : (in_addr->addr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 383 | new_filter->in_addr_netmask = (!in_addr_netmask) ? (0U) : (in_addr_netmask->addr); |
TASS Belgium NV |
131:4758606c9316 | 384 | new_filter->out_port = out_port; |
TASS Belgium NV |
131:4758606c9316 | 385 | new_filter->in_port = in_port; |
TASS Belgium NV |
131:4758606c9316 | 386 | new_filter->priority = priority; |
TASS Belgium NV |
131:4758606c9316 | 387 | new_filter->tos = tos; |
TASS Belgium NV |
131:4758606c9316 | 388 | new_filter->filter_id = filter_id++; |
tass | 152:a3d286bf94e5 | 389 | new_filter->function_ptr = fp_function[action].fn; |
tass | 68:0847e35d08a6 | 390 | |
TASS Belgium NV |
131:4758606c9316 | 391 | if(pico_tree_insert(&filter_tree, new_filter)) |
TASS Belgium NV |
131:4758606c9316 | 392 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 393 | PICO_FREE(new_filter); |
tass | 152:a3d286bf94e5 | 394 | filter_id--; |
tass | 152:a3d286bf94e5 | 395 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 396 | } |
tass | 125:96003ae6f1d8 | 397 | |
TASS Belgium NV |
131:4758606c9316 | 398 | return new_filter->filter_id; |
tass | 68:0847e35d08a6 | 399 | } |
tass | 68:0847e35d08a6 | 400 | |
tass | 152:a3d286bf94e5 | 401 | int pico_ipv4_filter_del(uint32_t filter_id) |
tass | 68:0847e35d08a6 | 402 | { |
TASS Belgium NV |
131:4758606c9316 | 403 | struct filter_node *node = NULL; |
TASS Belgium NV |
131:4758606c9316 | 404 | struct filter_node dummy = { |
TASS Belgium NV |
131:4758606c9316 | 405 | .filter_id = filter_id |
TASS Belgium NV |
131:4758606c9316 | 406 | }; |
TASS Belgium NV |
131:4758606c9316 | 407 | if((node = pico_tree_delete(&filter_tree, &dummy)) == NULL) |
TASS Belgium NV |
131:4758606c9316 | 408 | { |
TASS Belgium NV |
131:4758606c9316 | 409 | ipf_dbg("ipfilter> failed to delete filter :%d\n", filter_id); |
TASS Belgium NV |
131:4758606c9316 | 410 | return -1; |
TASS Belgium NV |
131:4758606c9316 | 411 | } |
tass | 68:0847e35d08a6 | 412 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 413 | PICO_FREE(node); |
TASS Belgium NV |
131:4758606c9316 | 414 | return 0; |
tass | 68:0847e35d08a6 | 415 | } |
tass | 68:0847e35d08a6 | 416 | |
tass | 152:a3d286bf94e5 | 417 | static int ipfilter_apply_filter(struct pico_frame *f, struct filter_node *pkt) |
tass | 152:a3d286bf94e5 | 418 | { |
tass | 152:a3d286bf94e5 | 419 | struct filter_node *filter_frame = NULL; |
tass | 152:a3d286bf94e5 | 420 | filter_frame = pico_tree_findKey(&filter_tree, pkt); |
tass | 152:a3d286bf94e5 | 421 | if(filter_frame) |
tass | 152:a3d286bf94e5 | 422 | { |
tass | 152:a3d286bf94e5 | 423 | filter_frame->function_ptr(filter_frame, f); |
tass | 152:a3d286bf94e5 | 424 | return 1; |
tass | 152:a3d286bf94e5 | 425 | } |
tass | 152:a3d286bf94e5 | 426 | |
tass | 152:a3d286bf94e5 | 427 | return 0; |
tass | 152:a3d286bf94e5 | 428 | } |
tass | 152:a3d286bf94e5 | 429 | |
tass | 125:96003ae6f1d8 | 430 | int ipfilter(struct pico_frame *f) |
tass | 68:0847e35d08a6 | 431 | { |
TASS Belgium NV |
131:4758606c9316 | 432 | struct filter_node temp; |
TASS Belgium NV |
131:4758606c9316 | 433 | struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *) f->net_hdr; |
tass | 152:a3d286bf94e5 | 434 | struct pico_trans *trans; |
TASS Belgium NV |
131:4758606c9316 | 435 | struct pico_icmp4_hdr *icmp_hdr; |
tass | 68:0847e35d08a6 | 436 | |
TASS Belgium NV |
131:4758606c9316 | 437 | memset(&temp, 0u, sizeof(struct filter_node)); |
tass | 68:0847e35d08a6 | 438 | |
TASS Belgium NV |
131:4758606c9316 | 439 | temp.fdev = f->dev; |
TASS Belgium NV |
131:4758606c9316 | 440 | temp.out_addr = ipv4_hdr->dst.addr; |
TASS Belgium NV |
131:4758606c9316 | 441 | temp.in_addr = ipv4_hdr->src.addr; |
tass | 152:a3d286bf94e5 | 442 | if ((ipv4_hdr->proto == PICO_PROTO_TCP) || (ipv4_hdr->proto == PICO_PROTO_UDP)) { |
tass | 152:a3d286bf94e5 | 443 | trans = (struct pico_trans *) f->transport_hdr; |
tass | 152:a3d286bf94e5 | 444 | temp.out_port = short_be(trans->dport); |
tass | 152:a3d286bf94e5 | 445 | temp.in_port = short_be(trans->sport); |
TASS Belgium NV |
131:4758606c9316 | 446 | } |
tass | 152:a3d286bf94e5 | 447 | else if(ipv4_hdr->proto == PICO_PROTO_ICMP4) { |
tass | 152:a3d286bf94e5 | 448 | icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr; |
tass | 152:a3d286bf94e5 | 449 | if(icmp_hdr->type == PICO_ICMP_UNREACH && icmp_hdr->type == PICO_ICMP_UNREACH_FILTER_PROHIB) |
tass | 152:a3d286bf94e5 | 450 | return 0; |
TASS Belgium NV |
131:4758606c9316 | 451 | } |
TASS Belgium NV |
131:4758606c9316 | 452 | |
TASS Belgium NV |
131:4758606c9316 | 453 | temp.proto = ipv4_hdr->proto; |
TASS Belgium NV |
131:4758606c9316 | 454 | temp.priority = f->priority; |
TASS Belgium NV |
131:4758606c9316 | 455 | temp.tos = ipv4_hdr->tos; |
tass | 152:a3d286bf94e5 | 456 | return ipfilter_apply_filter(f, &temp); |
tass | 68:0847e35d08a6 | 457 | } |
tass | 68:0847e35d08a6 | 458 |