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:
Fri May 17 12:09:59 2013 +0000
Revision:
1:cfe8984a32b4
Parent:
libraries/picotcp/modules/pico_ipfilter.c@0:d7f2341ab245
Update for smaller SOCKETQ

Who changed what in which revision?

UserRevisionLine numberNew contents of line
daniele 0:d7f2341ab245 1 /*********************************************************************
daniele 0:d7f2341ab245 2 PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved.
daniele 0:d7f2341ab245 3 See LICENSE and COPYING for usage.
daniele 0:d7f2341ab245 4
daniele 0:d7f2341ab245 5 Authors: Simon Maes
daniele 0:d7f2341ab245 6 *********************************************************************/
daniele 0:d7f2341ab245 7
daniele 0:d7f2341ab245 8 #include "pico_ipv4.h"
daniele 0:d7f2341ab245 9 #include "pico_config.h"
daniele 0:d7f2341ab245 10 #include "pico_icmp4.h"
daniele 0:d7f2341ab245 11 #include "pico_stack.h"
daniele 0:d7f2341ab245 12 #include "pico_eth.h"
daniele 0:d7f2341ab245 13 #include "pico_socket.h"
daniele 0:d7f2341ab245 14 #include "pico_device.h"
daniele 0:d7f2341ab245 15 #include "pico_ipfilter.h"
daniele 0:d7f2341ab245 16 #include "pico_tcp.h"
daniele 0:d7f2341ab245 17 #include "pico_udp.h"
daniele 0:d7f2341ab245 18
daniele 0:d7f2341ab245 19
daniele 0:d7f2341ab245 20 //#define ipf_dbg dbg
daniele 0:d7f2341ab245 21 #define ipf_dbg(...) do{}while(0)
daniele 0:d7f2341ab245 22
daniele 0:d7f2341ab245 23 struct filter_node;
daniele 0:d7f2341ab245 24 typedef int (*func_pntr)(struct filter_node *filter, struct pico_frame *f);
daniele 0:d7f2341ab245 25
daniele 0:d7f2341ab245 26 struct filter_node {
daniele 0:d7f2341ab245 27 struct pico_device *fdev;
daniele 0:d7f2341ab245 28 struct filter_node *next_filter;
daniele 0:d7f2341ab245 29 uint32_t out_addr;
daniele 0:d7f2341ab245 30 uint32_t out_addr_netmask;
daniele 0:d7f2341ab245 31 uint32_t in_addr;
daniele 0:d7f2341ab245 32 uint32_t in_addr_netmask;
daniele 0:d7f2341ab245 33 uint16_t out_port;
daniele 0:d7f2341ab245 34 uint16_t in_port;
daniele 0:d7f2341ab245 35 uint8_t proto;
daniele 0:d7f2341ab245 36 int8_t priority;
daniele 0:d7f2341ab245 37 uint8_t tos;
daniele 0:d7f2341ab245 38 uint8_t filter_id;
daniele 0:d7f2341ab245 39 func_pntr function_ptr;
daniele 0:d7f2341ab245 40 };
daniele 0:d7f2341ab245 41
daniele 0:d7f2341ab245 42 static struct filter_node *head = NULL;
daniele 0:d7f2341ab245 43 static struct filter_node *tail = NULL;
daniele 0:d7f2341ab245 44
daniele 0:d7f2341ab245 45 /*======================== FUNCTION PNTRS ==========================*/
daniele 0:d7f2341ab245 46
daniele 0:d7f2341ab245 47 static int fp_accept(struct filter_node *filter, struct pico_frame *f) {return 0;}
daniele 0:d7f2341ab245 48
daniele 0:d7f2341ab245 49 static int fp_priority(struct filter_node *filter, struct pico_frame *f) {
daniele 0:d7f2341ab245 50
daniele 0:d7f2341ab245 51 //TODO do priority-stuff
daniele 0:d7f2341ab245 52 return 0;
daniele 0:d7f2341ab245 53 }
daniele 0:d7f2341ab245 54
daniele 0:d7f2341ab245 55 static int fp_reject(struct filter_node *filter, struct pico_frame *f) {
daniele 0:d7f2341ab245 56 // TODO check first if sender is pico itself or not
daniele 0:d7f2341ab245 57 ipf_dbg("ipfilter> #reject\n");
daniele 0:d7f2341ab245 58 pico_icmp4_packet_filtered(f);
daniele 0:d7f2341ab245 59 pico_frame_discard(f);
daniele 0:d7f2341ab245 60 return 1;
daniele 0:d7f2341ab245 61 }
daniele 0:d7f2341ab245 62
daniele 0:d7f2341ab245 63 static int fp_drop(struct filter_node *filter, struct pico_frame *f) {
daniele 0:d7f2341ab245 64
daniele 0:d7f2341ab245 65 ipf_dbg("ipfilter> # drop\n");
daniele 0:d7f2341ab245 66 pico_frame_discard(f);
daniele 0:d7f2341ab245 67 return 1;
daniele 0:d7f2341ab245 68 }
daniele 0:d7f2341ab245 69
daniele 0:d7f2341ab245 70 /*============================ API CALLS ============================*/
daniele 0:d7f2341ab245 71 int pico_ipv4_filter_add(struct pico_device *dev, uint8_t proto, struct pico_ip4 *out_addr, struct pico_ip4 *out_addr_netmask, struct pico_ip4 *in_addr, struct pico_ip4 *in_addr_netmask, uint16_t out_port, uint16_t in_port, int8_t priority, uint8_t tos, enum filter_action action)
daniele 0:d7f2341ab245 72 {
daniele 0:d7f2341ab245 73 static uint8_t filter_id = 0;
daniele 0:d7f2341ab245 74 struct filter_node *new_filter;
daniele 0:d7f2341ab245 75
daniele 0:d7f2341ab245 76 if ( !(dev != NULL || proto != 0 || (out_addr != NULL && out_addr->addr != 0U) || (out_addr_netmask != NULL && out_addr_netmask->addr != 0U)|| (in_addr != NULL && in_addr->addr != 0U) || (in_addr_netmask != NULL && in_addr_netmask->addr != 0U)|| out_port != 0 || in_port !=0 || tos != 0 )) {
daniele 0:d7f2341ab245 77 pico_err = PICO_ERR_EINVAL;
daniele 0:d7f2341ab245 78 return -1;
daniele 0:d7f2341ab245 79 }
daniele 0:d7f2341ab245 80 if ( priority > 10 || priority < -10) {
daniele 0:d7f2341ab245 81 pico_err = PICO_ERR_EINVAL;
daniele 0:d7f2341ab245 82 return -1;
daniele 0:d7f2341ab245 83 }
daniele 0:d7f2341ab245 84 if (action > 3 || action < 0) {
daniele 0:d7f2341ab245 85 pico_err = PICO_ERR_EINVAL;
daniele 0:d7f2341ab245 86 return -1;
daniele 0:d7f2341ab245 87 }
daniele 0:d7f2341ab245 88 ipf_dbg("ipfilter> # adding filter\n");
daniele 0:d7f2341ab245 89
daniele 0:d7f2341ab245 90 new_filter = pico_zalloc(sizeof(struct filter_node));
daniele 0:d7f2341ab245 91 if (!head) {
daniele 0:d7f2341ab245 92 head = tail = new_filter;
daniele 0:d7f2341ab245 93 } else {
daniele 0:d7f2341ab245 94 tail->next_filter = new_filter;
daniele 0:d7f2341ab245 95 tail = new_filter;
daniele 0:d7f2341ab245 96 }
daniele 0:d7f2341ab245 97
daniele 0:d7f2341ab245 98 new_filter->fdev = dev;
daniele 0:d7f2341ab245 99 new_filter->proto = proto;
daniele 0:d7f2341ab245 100 if (out_addr != NULL)
daniele 0:d7f2341ab245 101 new_filter->out_addr = out_addr->addr;
daniele 0:d7f2341ab245 102 else
daniele 0:d7f2341ab245 103 new_filter->out_addr = 0U;
daniele 0:d7f2341ab245 104
daniele 0:d7f2341ab245 105 if (out_addr_netmask != NULL)
daniele 0:d7f2341ab245 106 new_filter->out_addr_netmask = out_addr_netmask->addr;
daniele 0:d7f2341ab245 107 else
daniele 0:d7f2341ab245 108 new_filter->out_addr_netmask = 0U;
daniele 0:d7f2341ab245 109
daniele 0:d7f2341ab245 110 if (in_addr != NULL)
daniele 0:d7f2341ab245 111 new_filter->in_addr = in_addr->addr;
daniele 0:d7f2341ab245 112 else
daniele 0:d7f2341ab245 113 new_filter->in_addr = 0U;
daniele 0:d7f2341ab245 114
daniele 0:d7f2341ab245 115 if (in_addr_netmask != NULL)
daniele 0:d7f2341ab245 116 new_filter->in_addr_netmask = in_addr_netmask->addr;
daniele 0:d7f2341ab245 117 else
daniele 0:d7f2341ab245 118 new_filter->in_addr_netmask = 0U;
daniele 0:d7f2341ab245 119
daniele 0:d7f2341ab245 120 new_filter->out_port = out_port;
daniele 0:d7f2341ab245 121 new_filter->in_port = in_port;
daniele 0:d7f2341ab245 122 new_filter->priority = priority;
daniele 0:d7f2341ab245 123 new_filter->tos = tos;
daniele 0:d7f2341ab245 124 new_filter->filter_id = filter_id++;
daniele 0:d7f2341ab245 125
daniele 0:d7f2341ab245 126 /*Define filterType_functionPointer here instead of in ipfilter-function, to prevent running multiple times through switch*/
daniele 0:d7f2341ab245 127 switch (action) {
daniele 0:d7f2341ab245 128 case FILTER_ACCEPT:
daniele 0:d7f2341ab245 129 new_filter->function_ptr = fp_accept;
daniele 0:d7f2341ab245 130 break;
daniele 0:d7f2341ab245 131 case FILTER_PRIORITY:
daniele 0:d7f2341ab245 132 new_filter->function_ptr = fp_priority;
daniele 0:d7f2341ab245 133 break;
daniele 0:d7f2341ab245 134 case FILTER_REJECT:
daniele 0:d7f2341ab245 135 new_filter->function_ptr = fp_reject;
daniele 0:d7f2341ab245 136 break;
daniele 0:d7f2341ab245 137 case FILTER_DROP:
daniele 0:d7f2341ab245 138 new_filter->function_ptr = fp_drop;
daniele 0:d7f2341ab245 139 break;
daniele 0:d7f2341ab245 140 default:
daniele 0:d7f2341ab245 141 ipf_dbg("ipfilter> #unknown filter action\n");
daniele 0:d7f2341ab245 142 break;
daniele 0:d7f2341ab245 143 }
daniele 0:d7f2341ab245 144 return new_filter->filter_id;
daniele 0:d7f2341ab245 145 }
daniele 0:d7f2341ab245 146
daniele 0:d7f2341ab245 147 int pico_ipv4_filter_del(uint8_t filter_id)
daniele 0:d7f2341ab245 148 {
daniele 0:d7f2341ab245 149 struct filter_node *work;
daniele 0:d7f2341ab245 150 struct filter_node *prev;
daniele 0:d7f2341ab245 151
daniele 0:d7f2341ab245 152 if (!tail || !head) {
daniele 0:d7f2341ab245 153 pico_err = PICO_ERR_EPERM;
daniele 0:d7f2341ab245 154 return -1;
daniele 0:d7f2341ab245 155 }
daniele 0:d7f2341ab245 156
daniele 0:d7f2341ab245 157 work = head;
daniele 0:d7f2341ab245 158 if (work->filter_id == filter_id) {
daniele 0:d7f2341ab245 159 /*delete filter_node from linked list*/
daniele 0:d7f2341ab245 160 head = work->next_filter;
daniele 0:d7f2341ab245 161 pico_free(work);
daniele 0:d7f2341ab245 162 return 0;
daniele 0:d7f2341ab245 163 }
daniele 0:d7f2341ab245 164 prev = work;
daniele 0:d7f2341ab245 165 work = work->next_filter;
daniele 0:d7f2341ab245 166
daniele 0:d7f2341ab245 167 while (1) {
daniele 0:d7f2341ab245 168 if (work->filter_id == filter_id) {
daniele 0:d7f2341ab245 169 if (work != tail) {
daniele 0:d7f2341ab245 170 /*delete filter_node from linked list*/
daniele 0:d7f2341ab245 171 prev->next_filter = work->next_filter;
daniele 0:d7f2341ab245 172 pico_free(work);
daniele 0:d7f2341ab245 173 return 0;
daniele 0:d7f2341ab245 174 } else {
daniele 0:d7f2341ab245 175 prev->next_filter = NULL;
daniele 0:d7f2341ab245 176 pico_free(work);
daniele 0:d7f2341ab245 177 return 0;
daniele 0:d7f2341ab245 178 }
daniele 0:d7f2341ab245 179 } else {
daniele 0:d7f2341ab245 180 /*check next filter_node*/
daniele 0:d7f2341ab245 181 prev = work;
daniele 0:d7f2341ab245 182 work = work->next_filter;
daniele 0:d7f2341ab245 183 if (work == tail) {
daniele 0:d7f2341ab245 184 pico_err = PICO_ERR_EINVAL;
daniele 0:d7f2341ab245 185 return -1;
daniele 0:d7f2341ab245 186 }
daniele 0:d7f2341ab245 187 }
daniele 0:d7f2341ab245 188 }
daniele 0:d7f2341ab245 189 }
daniele 0:d7f2341ab245 190
daniele 0:d7f2341ab245 191 /*================================== CORE FILTER FUNCTIONS ==================================*/
daniele 0:d7f2341ab245 192 int match_filter(struct filter_node *filter, struct pico_frame *f)
daniele 0:d7f2341ab245 193 {
daniele 0:d7f2341ab245 194 struct filter_node temp;
daniele 0:d7f2341ab245 195 struct pico_ipv4_hdr *ipv4_hdr = (struct pico_ipv4_hdr *) f->net_hdr;
daniele 0:d7f2341ab245 196 struct pico_tcp_hdr *tcp_hdr;
daniele 0:d7f2341ab245 197 struct pico_udp_hdr *udp_hdr;
daniele 0:d7f2341ab245 198
daniele 0:d7f2341ab245 199 if (!filter|| !f) {
daniele 0:d7f2341ab245 200 ipf_dbg("ipfilter> ## nullpointer in match filter \n");
daniele 0:d7f2341ab245 201 return -1;
daniele 0:d7f2341ab245 202 }
daniele 0:d7f2341ab245 203
daniele 0:d7f2341ab245 204 temp.fdev = f->dev;
daniele 0:d7f2341ab245 205 temp.out_addr = ipv4_hdr->dst.addr;
daniele 0:d7f2341ab245 206 temp.in_addr = ipv4_hdr->src.addr;
daniele 0:d7f2341ab245 207 if (ipv4_hdr->proto == PICO_PROTO_TCP ) {
daniele 0:d7f2341ab245 208 tcp_hdr = (struct pico_tcp_hdr *) f->transport_hdr;
daniele 0:d7f2341ab245 209 temp.out_port = short_be(tcp_hdr->trans.dport);
daniele 0:d7f2341ab245 210 temp.in_port = short_be(tcp_hdr->trans.sport);
daniele 0:d7f2341ab245 211 }else if (ipv4_hdr->proto == PICO_PROTO_UDP ) {
daniele 0:d7f2341ab245 212 udp_hdr = (struct pico_udp_hdr *) f->transport_hdr;
daniele 0:d7f2341ab245 213 temp.out_port = short_be(udp_hdr->trans.dport);
daniele 0:d7f2341ab245 214 temp.in_port = short_be(udp_hdr->trans.sport);
daniele 0:d7f2341ab245 215 } else {
daniele 0:d7f2341ab245 216 temp.out_port = temp.in_port = 0;
daniele 0:d7f2341ab245 217 }
daniele 0:d7f2341ab245 218 temp.proto = ipv4_hdr->proto;
daniele 0:d7f2341ab245 219 temp.priority = f->priority;
daniele 0:d7f2341ab245 220 temp.tos = ipv4_hdr->tos;
daniele 0:d7f2341ab245 221
daniele 0:d7f2341ab245 222
daniele 0:d7f2341ab245 223
daniele 0:d7f2341ab245 224 if ( ((filter->fdev == NULL || filter->fdev == temp.fdev) && \
daniele 0:d7f2341ab245 225 (filter->in_addr == 0 || ((filter->in_addr_netmask == 0) ? (filter->in_addr == temp.in_addr) : 1)) &&\
daniele 0:d7f2341ab245 226 (filter->in_port == 0 || filter->in_port == temp.in_port) &&\
daniele 0:d7f2341ab245 227 (filter->out_addr == 0 || ((filter->out_addr_netmask == 0) ? (filter->out_addr == temp.out_addr) : 1)) && \
daniele 0:d7f2341ab245 228 (filter->out_port == 0 || filter->out_port == temp.out_port) && \
daniele 0:d7f2341ab245 229 (filter->proto == 0 || filter->proto == temp.proto ) &&\
daniele 0:d7f2341ab245 230 (filter->priority == 0 || filter->priority == temp.priority ) &&\
daniele 0:d7f2341ab245 231 (filter->tos == 0 || filter->tos == temp.tos ) &&\
daniele 0:d7f2341ab245 232 (filter->out_addr_netmask == 0 || ((filter->out_addr & filter->out_addr_netmask) == (temp.out_addr & filter->out_addr_netmask)) ) &&\
daniele 0:d7f2341ab245 233 (filter->in_addr_netmask == 0 || ((filter->in_addr & filter->in_addr_netmask) == (temp.in_addr & filter->in_addr_netmask)) )\
daniele 0:d7f2341ab245 234 ) )
daniele 0:d7f2341ab245 235 return 0;
daniele 0:d7f2341ab245 236
daniele 0:d7f2341ab245 237 //No filter match!
daniele 0:d7f2341ab245 238 ipf_dbg("ipfilter> #no match\n");
daniele 0:d7f2341ab245 239 return 1;
daniele 0:d7f2341ab245 240 }
daniele 0:d7f2341ab245 241
daniele 0:d7f2341ab245 242 int ipfilter(struct pico_frame *f)
daniele 0:d7f2341ab245 243 {
daniele 0:d7f2341ab245 244 struct filter_node *work = head;
daniele 0:d7f2341ab245 245
daniele 0:d7f2341ab245 246 /*return 1 if pico_frame is discarded as result of the filtering, 0 for an incomming packet, -1 for faults*/
daniele 0:d7f2341ab245 247 if (!tail || !head) {
daniele 0:d7f2341ab245 248 return 0;
daniele 0:d7f2341ab245 249 }
daniele 0:d7f2341ab245 250
daniele 0:d7f2341ab245 251 if ( match_filter(work, f) == 0 ) {
daniele 0:d7f2341ab245 252 ipf_dbg("ipfilter> # ipfilter match\n");
daniele 0:d7f2341ab245 253 /*filter match, execute filter!*/
daniele 0:d7f2341ab245 254 return work->function_ptr(work, f);
daniele 0:d7f2341ab245 255 }
daniele 0:d7f2341ab245 256 while (tail != work) {
daniele 0:d7f2341ab245 257 ipf_dbg("ipfilter> next filter..\n");
daniele 0:d7f2341ab245 258 work = work->next_filter;
daniele 0:d7f2341ab245 259 if ( match_filter(work, f) == 0 ) {
daniele 0:d7f2341ab245 260 ipf_dbg("ipfilter> # ipfilter match\n");
daniele 0:d7f2341ab245 261 /*filter match, execute filter!*/
daniele 0:d7f2341ab245 262 return work->function_ptr(work, f);
daniele 0:d7f2341ab245 263 }
daniele 0:d7f2341ab245 264 }
daniele 0:d7f2341ab245 265 return 0;
daniele 0:d7f2341ab245 266 }
daniele 0:d7f2341ab245 267