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:
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?

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 RFC 1112, 2236, 3376, 3569, 3678, 4607
tass 68:0847e35d08a6 6
TASS Belgium NV 131:4758606c9316 7 Authors: Kristof Roelants (IGMPv3), Simon Maes, Brecht Van Cauwenberghe
TASS Belgium NV 131:4758606c9316 8 *********************************************************************/
tass 68:0847e35d08a6 9
tass 68:0847e35d08a6 10 #include "pico_stack.h"
tass 68:0847e35d08a6 11 #include "pico_ipv4.h"
tass 68:0847e35d08a6 12 #include "pico_igmp.h"
tass 68:0847e35d08a6 13 #include "pico_config.h"
tass 68:0847e35d08a6 14 #include "pico_eth.h"
tass 68:0847e35d08a6 15 #include "pico_addressing.h"
tass 68:0847e35d08a6 16 #include "pico_frame.h"
tass 68:0847e35d08a6 17 #include "pico_tree.h"
tass 68:0847e35d08a6 18 #include "pico_device.h"
tass 68:0847e35d08a6 19 #include "pico_socket.h"
tass 68:0847e35d08a6 20
tass 152:a3d286bf94e5 21 #if defined(PICO_SUPPORT_IGMP) && defined(PICO_SUPPORT_MCAST)
tass 152:a3d286bf94e5 22
TASS Belgium NV 131:4758606c9316 23 #define igmp_dbg(...) do {} while(0)
TASS Belgium NV 131:4758606c9316 24 /* #define igmp_dbg dbg */
tass 68:0847e35d08a6 25
tass 68:0847e35d08a6 26 /* membership states */
tass 68:0847e35d08a6 27 #define IGMP_STATE_NON_MEMBER (0x0)
tass 68:0847e35d08a6 28 #define IGMP_STATE_DELAYING_MEMBER (0x1)
tass 68:0847e35d08a6 29 #define IGMP_STATE_IDLE_MEMBER (0x2)
tass 68:0847e35d08a6 30
TASS Belgium NV 131:4758606c9316 31 /* events */
tass 68:0847e35d08a6 32 #define IGMP_EVENT_DELETE_GROUP (0x0)
tass 68:0847e35d08a6 33 #define IGMP_EVENT_CREATE_GROUP (0x1)
tass 68:0847e35d08a6 34 #define IGMP_EVENT_UPDATE_GROUP (0x2)
tass 68:0847e35d08a6 35 #define IGMP_EVENT_QUERY_RECV (0x3)
tass 68:0847e35d08a6 36 #define IGMP_EVENT_REPORT_RECV (0x4)
tass 68:0847e35d08a6 37 #define IGMP_EVENT_TIMER_EXPIRED (0x5)
tass 68:0847e35d08a6 38
tass 68:0847e35d08a6 39 /* message types */
tass 68:0847e35d08a6 40 #define IGMP_TYPE_MEM_QUERY (0x11)
tass 68:0847e35d08a6 41 #define IGMP_TYPE_MEM_REPORT_V1 (0x12)
tass 68:0847e35d08a6 42 #define IGMP_TYPE_MEM_REPORT_V2 (0x16)
tass 68:0847e35d08a6 43 #define IGMP_TYPE_LEAVE_GROUP (0x17)
tass 68:0847e35d08a6 44 #define IGMP_TYPE_MEM_REPORT_V3 (0x22)
tass 68:0847e35d08a6 45
tass 68:0847e35d08a6 46 /* group record types */
tass 68:0847e35d08a6 47 #define IGMP_MODE_IS_INCLUDE (1)
tass 68:0847e35d08a6 48 #define IGMP_MODE_IS_EXCLUDE (2)
tass 68:0847e35d08a6 49 #define IGMP_CHANGE_TO_INCLUDE_MODE (3)
tass 68:0847e35d08a6 50 #define IGMP_CHANGE_TO_EXCLUDE_MODE (4)
tass 68:0847e35d08a6 51 #define IGMP_ALLOW_NEW_SOURCES (5)
tass 68:0847e35d08a6 52 #define IGMP_BLOCK_OLD_SOURCES (6)
tass 68:0847e35d08a6 53
tass 68:0847e35d08a6 54 /* host flag */
tass 68:0847e35d08a6 55 #define IGMP_HOST_LAST (0x1)
tass 68:0847e35d08a6 56 #define IGMP_HOST_NOT_LAST (0x0)
tass 68:0847e35d08a6 57
tass 68:0847e35d08a6 58 /* list of timers, counters and their default values */
tass 70:cd218dd180e5 59 #define IGMP_ROBUSTNESS (2u)
tass 68:0847e35d08a6 60 #define IGMP_QUERY_INTERVAL (125) /* secs */
tass 70:cd218dd180e5 61 #define IGMP_QUERY_RESPONSE_INTERVAL (10u) /* secs */
tass 68:0847e35d08a6 62 #define IGMP_STARTUP_QUERY_INTERVAL (IGMPV3_QUERY_INTERVAL / 4)
tass 68:0847e35d08a6 63 #define IGMP_STARTUP_QUERY_COUNT (IGMPV3_ROBUSTNESS)
tass 68:0847e35d08a6 64 #define IGMP_LAST_MEMBER_QUERY_INTERVAL (1) /* secs */
tass 68:0847e35d08a6 65 #define IGMP_LAST_MEMBER_QUERY_COUNT (IGMPV3_ROBUSTNESS)
tass 68:0847e35d08a6 66 #define IGMP_UNSOLICITED_REPORT_INTERVAL (1) /* secs */
tass 68:0847e35d08a6 67 #define IGMP_DEFAULT_MAX_RESPONSE_TIME (100)
tass 68:0847e35d08a6 68
tass 68:0847e35d08a6 69 /* custom timers types */
tass 68:0847e35d08a6 70 #define IGMP_TIMER_GROUP_REPORT (1)
tass 68:0847e35d08a6 71 #define IGMP_TIMER_V1_QUERIER (2)
tass 68:0847e35d08a6 72 #define IGMP_TIMER_V2_QUERIER (3)
tass 68:0847e35d08a6 73
tass 68:0847e35d08a6 74 /* IGMP groups */
tass 68:0847e35d08a6 75 #define IGMP_ALL_HOST_GROUP long_be(0xE0000001) /* 224.0.0.1 */
tass 68:0847e35d08a6 76 #define IGMP_ALL_ROUTER_GROUP long_be(0xE0000002) /* 224.0.0.2 */
tass 68:0847e35d08a6 77 #define IGMPV3_ALL_ROUTER_GROUP long_be(0xE0000016) /* 224.0.0.22 */
tass 68:0847e35d08a6 78
tass 68:0847e35d08a6 79 /* misc */
tass 68:0847e35d08a6 80 #define IGMP_TIMER_STOPPED (1)
tass 70:cd218dd180e5 81 #define IP_OPTION_ROUTER_ALERT_LEN (4u)
tass 68:0847e35d08a6 82 #define IGMP_MAX_GROUPS (32) /* max 255 */
tass 68:0847e35d08a6 83
tass picotcp@tass.be 149:5f4cb161cec3 84 PACKED_STRUCT_DEF igmp_message {
TASS Belgium NV 131:4758606c9316 85 uint8_t type;
TASS Belgium NV 131:4758606c9316 86 uint8_t max_resp_time;
TASS Belgium NV 131:4758606c9316 87 uint16_t crc;
TASS Belgium NV 131:4758606c9316 88 uint32_t mcast_group;
tass 68:0847e35d08a6 89 };
tass 68:0847e35d08a6 90
tass picotcp@tass.be 149:5f4cb161cec3 91 PACKED_STRUCT_DEF igmpv3_query {
TASS Belgium NV 131:4758606c9316 92 uint8_t type;
TASS Belgium NV 131:4758606c9316 93 uint8_t max_resp_time;
TASS Belgium NV 131:4758606c9316 94 uint16_t crc;
TASS Belgium NV 131:4758606c9316 95 uint32_t mcast_group;
TASS Belgium NV 131:4758606c9316 96 uint8_t rsq;
TASS Belgium NV 131:4758606c9316 97 uint8_t qqic;
TASS Belgium NV 131:4758606c9316 98 uint16_t sources;
tass 152:a3d286bf94e5 99 uint32_t source_addr[0];
tass 68:0847e35d08a6 100 };
tass 68:0847e35d08a6 101
tass picotcp@tass.be 149:5f4cb161cec3 102 PACKED_STRUCT_DEF igmpv3_group_record {
TASS Belgium NV 131:4758606c9316 103 uint8_t type;
TASS Belgium NV 131:4758606c9316 104 uint8_t aux;
TASS Belgium NV 131:4758606c9316 105 uint16_t sources;
TASS Belgium NV 131:4758606c9316 106 uint32_t mcast_group;
tass 152:a3d286bf94e5 107 uint32_t source_addr[0];
tass 68:0847e35d08a6 108 };
tass 68:0847e35d08a6 109
tass picotcp@tass.be 149:5f4cb161cec3 110 PACKED_STRUCT_DEF igmpv3_report {
TASS Belgium NV 131:4758606c9316 111 uint8_t type;
TASS Belgium NV 131:4758606c9316 112 uint8_t res0;
TASS Belgium NV 131:4758606c9316 113 uint16_t crc;
TASS Belgium NV 131:4758606c9316 114 uint16_t res1;
TASS Belgium NV 131:4758606c9316 115 uint16_t groups;
tass 152:a3d286bf94e5 116 struct igmpv3_group_record record[0];
tass 68:0847e35d08a6 117 };
tass 68:0847e35d08a6 118
tass 68:0847e35d08a6 119 struct igmp_parameters {
TASS Belgium NV 131:4758606c9316 120 uint8_t event;
TASS Belgium NV 131:4758606c9316 121 uint8_t state;
TASS Belgium NV 131:4758606c9316 122 uint8_t last_host;
TASS Belgium NV 131:4758606c9316 123 uint8_t filter_mode;
TASS Belgium NV 131:4758606c9316 124 uint8_t max_resp_time;
TASS Belgium NV 131:4758606c9316 125 struct pico_ip4 mcast_link;
TASS Belgium NV 131:4758606c9316 126 struct pico_ip4 mcast_group;
TASS Belgium NV 131:4758606c9316 127 struct pico_tree *MCASTFilter;
TASS Belgium NV 131:4758606c9316 128 struct pico_frame *f;
tass 68:0847e35d08a6 129 };
tass 68:0847e35d08a6 130
tass 68:0847e35d08a6 131 struct igmp_timer {
TASS Belgium NV 131:4758606c9316 132 uint8_t type;
TASS Belgium NV 131:4758606c9316 133 uint8_t stopped;
TASS Belgium NV 131:4758606c9316 134 pico_time start;
TASS Belgium NV 131:4758606c9316 135 pico_time delay;
TASS Belgium NV 131:4758606c9316 136 struct pico_ip4 mcast_link;
TASS Belgium NV 131:4758606c9316 137 struct pico_ip4 mcast_group;
TASS Belgium NV 131:4758606c9316 138 struct pico_frame *f;
TASS Belgium NV 131:4758606c9316 139 void (*callback)(struct igmp_timer *t);
tass 68:0847e35d08a6 140 };
tass 68:0847e35d08a6 141
tass 68:0847e35d08a6 142 /* queues */
TASS Belgium NV 131:4758606c9316 143 static struct pico_queue igmp_in = {
TASS Belgium NV 131:4758606c9316 144 0
TASS Belgium NV 131:4758606c9316 145 };
TASS Belgium NV 131:4758606c9316 146 static struct pico_queue igmp_out = {
TASS Belgium NV 131:4758606c9316 147 0
TASS Belgium NV 131:4758606c9316 148 };
tass 68:0847e35d08a6 149
tass 68:0847e35d08a6 150 /* finite state machine caller */
tass 68:0847e35d08a6 151 static int pico_igmp_process_event(struct igmp_parameters *p);
tass 68:0847e35d08a6 152
tass 68:0847e35d08a6 153 /* state callback prototype */
tass 68:0847e35d08a6 154 typedef int (*callback)(struct igmp_parameters *);
tass 68:0847e35d08a6 155
tass 152:a3d286bf94e5 156 static inline int igmpt_type_compare(struct igmp_timer *a, struct igmp_timer *b)
tass 68:0847e35d08a6 157 {
TASS Belgium NV 131:4758606c9316 158 if (a->type < b->type)
TASS Belgium NV 131:4758606c9316 159 return -1;
TASS Belgium NV 131:4758606c9316 160
TASS Belgium NV 131:4758606c9316 161 if (a->type > b->type)
TASS Belgium NV 131:4758606c9316 162 return 1;
TASS Belgium NV 131:4758606c9316 163
TASS Belgium NV 131:4758606c9316 164 return 0;
tass 68:0847e35d08a6 165 }
tass 152:a3d286bf94e5 166
tass 152:a3d286bf94e5 167
tass 152:a3d286bf94e5 168 static inline int igmpt_group_compare(struct igmp_timer *a, struct igmp_timer *b)
tass 152:a3d286bf94e5 169 {
tass 152:a3d286bf94e5 170 return pico_ipv4_compare(&a->mcast_group, &b->mcast_group);
tass 152:a3d286bf94e5 171 }
tass 152:a3d286bf94e5 172
tass 152:a3d286bf94e5 173 static inline int igmpt_link_compare(struct igmp_timer *a, struct igmp_timer *b)
tass 152:a3d286bf94e5 174 {
tass 152:a3d286bf94e5 175 return pico_ipv4_compare(&a->mcast_link, &b->mcast_link);
tass 152:a3d286bf94e5 176 }
tass 152:a3d286bf94e5 177
tass 152:a3d286bf94e5 178 /* redblack trees */
tass 152:a3d286bf94e5 179 static int igmp_timer_cmp(void *ka, void *kb)
tass 152:a3d286bf94e5 180 {
tass 152:a3d286bf94e5 181 struct igmp_timer *a = ka, *b = kb;
tass 152:a3d286bf94e5 182 int cmp = igmpt_type_compare(a, b);
tass 152:a3d286bf94e5 183 if (cmp)
tass 152:a3d286bf94e5 184 return cmp;
tass 152:a3d286bf94e5 185
tass 152:a3d286bf94e5 186 cmp = igmpt_group_compare(a, b);
tass 152:a3d286bf94e5 187 if (cmp)
tass 152:a3d286bf94e5 188 return cmp;
tass 152:a3d286bf94e5 189
tass 152:a3d286bf94e5 190 return igmpt_link_compare(a, b);
tass 152:a3d286bf94e5 191
tass 152:a3d286bf94e5 192 }
tass 68:0847e35d08a6 193 PICO_TREE_DECLARE(IGMPTimers, igmp_timer_cmp);
tass 68:0847e35d08a6 194
tass 152:a3d286bf94e5 195 static inline int igmpparm_group_compare(struct igmp_parameters *a, struct igmp_parameters *b)
tass 152:a3d286bf94e5 196 {
tass 152:a3d286bf94e5 197 return pico_ipv4_compare(&a->mcast_group, &b->mcast_group);
tass 152:a3d286bf94e5 198 }
tass 152:a3d286bf94e5 199
tass 152:a3d286bf94e5 200 static inline int igmpparm_link_compare(struct igmp_parameters *a, struct igmp_parameters *b)
tass 152:a3d286bf94e5 201 {
tass 152:a3d286bf94e5 202 return pico_ipv4_compare(&a->mcast_link, &b->mcast_link);
tass 152:a3d286bf94e5 203 }
tass 152:a3d286bf94e5 204
tass 68:0847e35d08a6 205 static int igmp_parameters_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 206 {
TASS Belgium NV 131:4758606c9316 207 struct igmp_parameters *a = ka, *b = kb;
tass 152:a3d286bf94e5 208 int cmp = igmpparm_group_compare(a, b);
tass 152:a3d286bf94e5 209 if (cmp)
tass 152:a3d286bf94e5 210 return cmp;
TASS Belgium NV 131:4758606c9316 211
tass 152:a3d286bf94e5 212 return igmpparm_link_compare(a, b);
tass 68:0847e35d08a6 213 }
tass 68:0847e35d08a6 214 PICO_TREE_DECLARE(IGMPParameters, igmp_parameters_cmp);
tass 68:0847e35d08a6 215
tass 68:0847e35d08a6 216 static int igmp_sources_cmp(void *ka, void *kb)
tass 68:0847e35d08a6 217 {
TASS Belgium NV 131:4758606c9316 218 struct pico_ip4 *a = ka, *b = kb;
tass 152:a3d286bf94e5 219 return pico_ipv4_compare(a, b);
tass 68:0847e35d08a6 220 }
tass 68:0847e35d08a6 221 PICO_TREE_DECLARE(IGMPAllow, igmp_sources_cmp);
tass 68:0847e35d08a6 222 PICO_TREE_DECLARE(IGMPBlock, igmp_sources_cmp);
tass 68:0847e35d08a6 223
tass 68:0847e35d08a6 224 static struct igmp_parameters *pico_igmp_find_parameter(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group)
tass 68:0847e35d08a6 225 {
TASS Belgium NV 131:4758606c9316 226 struct igmp_parameters test = {
TASS Belgium NV 131:4758606c9316 227 0
TASS Belgium NV 131:4758606c9316 228 };
tass picotcp@tass.be 149:5f4cb161cec3 229 if (!mcast_link || !mcast_group)
tass picotcp@tass.be 149:5f4cb161cec3 230 return NULL;
tass picotcp@tass.be 149:5f4cb161cec3 231
TASS Belgium NV 131:4758606c9316 232 test.mcast_link.addr = mcast_link->addr;
TASS Belgium NV 131:4758606c9316 233 test.mcast_group.addr = mcast_group->addr;
TASS Belgium NV 131:4758606c9316 234 return pico_tree_findKey(&IGMPParameters, &test);
tass 68:0847e35d08a6 235 }
tass 68:0847e35d08a6 236
tass 68:0847e35d08a6 237 static int pico_igmp_delete_parameter(struct igmp_parameters *p)
tass 68:0847e35d08a6 238 {
TASS Belgium NV 131:4758606c9316 239 if (pico_tree_delete(&IGMPParameters, p))
tass picotcp@tass.be 149:5f4cb161cec3 240 PICO_FREE(p);
TASS Belgium NV 131:4758606c9316 241 else
TASS Belgium NV 131:4758606c9316 242 return -1;
tass 68:0847e35d08a6 243
TASS Belgium NV 131:4758606c9316 244 return 0;
tass 68:0847e35d08a6 245 }
tass 68:0847e35d08a6 246
tass 128:ae39e6e81531 247 static void pico_igmp_timer_expired(pico_time now, void *arg)
tass 68:0847e35d08a6 248 {
TASS Belgium NV 131:4758606c9316 249 struct igmp_timer *t = NULL, *timer = NULL, test = {
TASS Belgium NV 131:4758606c9316 250 0
TASS Belgium NV 131:4758606c9316 251 };
TASS Belgium NV 131:4758606c9316 252
TASS Belgium NV 131:4758606c9316 253 IGNORE_PARAMETER(now);
TASS Belgium NV 131:4758606c9316 254 t = (struct igmp_timer *)arg;
TASS Belgium NV 131:4758606c9316 255 test.type = t->type;
TASS Belgium NV 131:4758606c9316 256 test.mcast_link = t->mcast_link;
TASS Belgium NV 131:4758606c9316 257 test.mcast_group = t->mcast_group;
TASS Belgium NV 131:4758606c9316 258 igmp_dbg("IGMP: timer expired for %08X link %08X type %u, delay %lu\n", t->mcast_group.addr, t->mcast_link.addr, t->type, t->delay);
TASS Belgium NV 131:4758606c9316 259 timer = pico_tree_findKey(&IGMPTimers, &test);
TASS Belgium NV 131:4758606c9316 260 if (!timer) {
TASS Belgium NV 131:4758606c9316 261 return;
TASS Belgium NV 131:4758606c9316 262 }
tass 68:0847e35d08a6 263
TASS Belgium NV 131:4758606c9316 264 if (timer->stopped == IGMP_TIMER_STOPPED) {
tass picotcp@tass.be 149:5f4cb161cec3 265 PICO_FREE(t);
TASS Belgium NV 131:4758606c9316 266 return;
TASS Belgium NV 131:4758606c9316 267 }
TASS Belgium NV 131:4758606c9316 268
TASS Belgium NV 131:4758606c9316 269 if (timer->start + timer->delay < PICO_TIME_MS()) {
TASS Belgium NV 131:4758606c9316 270 pico_tree_delete(&IGMPTimers, timer);
TASS Belgium NV 131:4758606c9316 271 if (timer->callback)
TASS Belgium NV 131:4758606c9316 272 timer->callback(timer);
TASS Belgium NV 131:4758606c9316 273
tass picotcp@tass.be 149:5f4cb161cec3 274 PICO_FREE(timer);
TASS Belgium NV 131:4758606c9316 275 } else {
TASS Belgium NV 131:4758606c9316 276 igmp_dbg("IGMP: restart timer for %08X, delay %lu, new delay %lu\n", t->mcast_group.addr, t->delay, (timer->start + timer->delay) - PICO_TIME_MS());
TASS Belgium NV 131:4758606c9316 277 pico_timer_add((timer->start + timer->delay) - PICO_TIME_MS(), &pico_igmp_timer_expired, timer);
TASS Belgium NV 131:4758606c9316 278 }
TASS Belgium NV 131:4758606c9316 279
tass 68:0847e35d08a6 280 return;
tass 68:0847e35d08a6 281 }
tass 68:0847e35d08a6 282
tass 68:0847e35d08a6 283 static int pico_igmp_timer_reset(struct igmp_timer *t)
tass 68:0847e35d08a6 284 {
TASS Belgium NV 131:4758606c9316 285 struct igmp_timer *timer = NULL, test = {
TASS Belgium NV 131:4758606c9316 286 0
TASS Belgium NV 131:4758606c9316 287 };
tass 68:0847e35d08a6 288
TASS Belgium NV 131:4758606c9316 289 igmp_dbg("IGMP: reset timer for %08X, delay %lu\n", t->mcast_group.addr, t->delay);
TASS Belgium NV 131:4758606c9316 290 test.type = t->type;
TASS Belgium NV 131:4758606c9316 291 test.mcast_link = t->mcast_link;
TASS Belgium NV 131:4758606c9316 292 test.mcast_group = t->mcast_group;
TASS Belgium NV 131:4758606c9316 293 timer = pico_tree_findKey(&IGMPTimers, &test);
TASS Belgium NV 131:4758606c9316 294 if (!timer)
TASS Belgium NV 131:4758606c9316 295 return -1;
tass 68:0847e35d08a6 296
TASS Belgium NV 131:4758606c9316 297 *timer = *t;
TASS Belgium NV 131:4758606c9316 298 timer->start = PICO_TIME_MS();
TASS Belgium NV 131:4758606c9316 299 return 0;
tass 68:0847e35d08a6 300 }
tass 68:0847e35d08a6 301
tass 68:0847e35d08a6 302 static int pico_igmp_timer_start(struct igmp_timer *t)
tass 68:0847e35d08a6 303 {
TASS Belgium NV 131:4758606c9316 304 struct igmp_timer *timer = NULL, test = {
TASS Belgium NV 131:4758606c9316 305 0
TASS Belgium NV 131:4758606c9316 306 };
tass 68:0847e35d08a6 307
TASS Belgium NV 131:4758606c9316 308 igmp_dbg("IGMP: start timer for %08X link %08X type %u, delay %lu\n", t->mcast_group.addr, t->mcast_link.addr, t->type, t->delay);
TASS Belgium NV 131:4758606c9316 309 test.type = t->type;
TASS Belgium NV 131:4758606c9316 310 test.mcast_link = t->mcast_link;
TASS Belgium NV 131:4758606c9316 311 test.mcast_group = t->mcast_group;
TASS Belgium NV 131:4758606c9316 312 timer = pico_tree_findKey(&IGMPTimers, &test);
TASS Belgium NV 131:4758606c9316 313 if (timer)
TASS Belgium NV 131:4758606c9316 314 return pico_igmp_timer_reset(t);
tass 68:0847e35d08a6 315
tass picotcp@tass.be 149:5f4cb161cec3 316 timer = PICO_ZALLOC(sizeof(struct igmp_timer));
TASS Belgium NV 131:4758606c9316 317 if (!timer) {
TASS Belgium NV 131:4758606c9316 318 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 319 return -1;
TASS Belgium NV 131:4758606c9316 320 }
tass 68:0847e35d08a6 321
TASS Belgium NV 131:4758606c9316 322 *timer = *t;
TASS Belgium NV 131:4758606c9316 323 timer->start = PICO_TIME_MS();
TASS Belgium NV 131:4758606c9316 324
TASS Belgium NV 131:4758606c9316 325 pico_tree_insert(&IGMPTimers, timer);
TASS Belgium NV 131:4758606c9316 326 pico_timer_add(timer->delay, &pico_igmp_timer_expired, timer);
TASS Belgium NV 131:4758606c9316 327 return 0;
tass 68:0847e35d08a6 328 }
tass 68:0847e35d08a6 329
tass 68:0847e35d08a6 330 static int pico_igmp_timer_stop(struct igmp_timer *t)
tass 68:0847e35d08a6 331 {
TASS Belgium NV 131:4758606c9316 332 struct igmp_timer *timer = NULL, test = {
TASS Belgium NV 131:4758606c9316 333 0
TASS Belgium NV 131:4758606c9316 334 };
tass 68:0847e35d08a6 335
TASS Belgium NV 131:4758606c9316 336 test.type = t->type;
TASS Belgium NV 131:4758606c9316 337 test.mcast_link = t->mcast_link;
TASS Belgium NV 131:4758606c9316 338 test.mcast_group = t->mcast_group;
TASS Belgium NV 131:4758606c9316 339 timer = pico_tree_findKey(&IGMPTimers, &test);
TASS Belgium NV 131:4758606c9316 340 if (!timer)
TASS Belgium NV 131:4758606c9316 341 return 0;
TASS Belgium NV 131:4758606c9316 342
TASS Belgium NV 131:4758606c9316 343 igmp_dbg("IGMP: stop timer for %08X, delay %lu\n", timer->mcast_group.addr, timer->delay);
TASS Belgium NV 131:4758606c9316 344 timer->stopped = IGMP_TIMER_STOPPED;
tass 68:0847e35d08a6 345 return 0;
tass 68:0847e35d08a6 346 }
tass 68:0847e35d08a6 347
tass 68:0847e35d08a6 348 static int pico_igmp_timer_is_running(struct igmp_timer *t)
tass 68:0847e35d08a6 349 {
TASS Belgium NV 131:4758606c9316 350 struct igmp_timer *timer = NULL, test = {
TASS Belgium NV 131:4758606c9316 351 0
TASS Belgium NV 131:4758606c9316 352 };
tass 68:0847e35d08a6 353
TASS Belgium NV 131:4758606c9316 354 test.type = t->type;
TASS Belgium NV 131:4758606c9316 355 test.mcast_link = t->mcast_link;
TASS Belgium NV 131:4758606c9316 356 test.mcast_group = t->mcast_group;
TASS Belgium NV 131:4758606c9316 357 timer = pico_tree_findKey(&IGMPTimers, &test);
TASS Belgium NV 131:4758606c9316 358 if (timer)
TASS Belgium NV 131:4758606c9316 359 return 1;
TASS Belgium NV 131:4758606c9316 360
TASS Belgium NV 131:4758606c9316 361 return 0;
tass 68:0847e35d08a6 362 }
tass 68:0847e35d08a6 363
tass 68:0847e35d08a6 364 static struct igmp_timer *pico_igmp_find_timer(uint8_t type, struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group)
tass 68:0847e35d08a6 365 {
TASS Belgium NV 131:4758606c9316 366 struct igmp_timer test = {
TASS Belgium NV 131:4758606c9316 367 0
TASS Belgium NV 131:4758606c9316 368 };
tass 68:0847e35d08a6 369
TASS Belgium NV 131:4758606c9316 370 test.type = type;
TASS Belgium NV 131:4758606c9316 371 test.mcast_link = *mcast_link;
TASS Belgium NV 131:4758606c9316 372 test.mcast_group = *mcast_group;
TASS Belgium NV 131:4758606c9316 373 return pico_tree_findKey(&IGMPTimers, &test);
tass 68:0847e35d08a6 374 }
tass 68:0847e35d08a6 375
tass 68:0847e35d08a6 376 static void pico_igmp_report_expired(struct igmp_timer *t)
tass 68:0847e35d08a6 377 {
TASS Belgium NV 131:4758606c9316 378 struct igmp_parameters *p = NULL;
tass 68:0847e35d08a6 379
TASS Belgium NV 131:4758606c9316 380 p = pico_igmp_find_parameter(&t->mcast_link, &t->mcast_group);
TASS Belgium NV 131:4758606c9316 381 if (!p)
TASS Belgium NV 131:4758606c9316 382 return;
tass 68:0847e35d08a6 383
TASS Belgium NV 131:4758606c9316 384 p->event = IGMP_EVENT_TIMER_EXPIRED;
TASS Belgium NV 131:4758606c9316 385 pico_igmp_process_event(p);
tass 68:0847e35d08a6 386 }
tass 68:0847e35d08a6 387
tass 68:0847e35d08a6 388 static void pico_igmp_v2querier_expired(struct igmp_timer *t)
tass 68:0847e35d08a6 389 {
TASS Belgium NV 131:4758606c9316 390 struct pico_ipv4_link *link = NULL;
TASS Belgium NV 131:4758606c9316 391 struct pico_tree_node *index = NULL, *_tmp = NULL;
tass 68:0847e35d08a6 392
TASS Belgium NV 131:4758606c9316 393 link = pico_ipv4_link_by_dev(t->f->dev);
TASS Belgium NV 131:4758606c9316 394 if (!link)
TASS Belgium NV 131:4758606c9316 395 return;
tass 68:0847e35d08a6 396
TASS Belgium NV 131:4758606c9316 397 /* When changing compatibility mode, cancel all pending response
TASS Belgium NV 131:4758606c9316 398 * and retransmission timers.
TASS Belgium NV 131:4758606c9316 399 */
TASS Belgium NV 131:4758606c9316 400 pico_tree_foreach_safe(index, &IGMPTimers, _tmp)
TASS Belgium NV 131:4758606c9316 401 {
TASS Belgium NV 131:4758606c9316 402 ((struct igmp_timer *)index->keyValue)->stopped = IGMP_TIMER_STOPPED;
TASS Belgium NV 131:4758606c9316 403 pico_tree_delete(&IGMPTimers, index->keyValue);
TASS Belgium NV 131:4758606c9316 404 }
TASS Belgium NV 131:4758606c9316 405 igmp_dbg("IGMP: switch to compatibility mode IGMPv3\n");
TASS Belgium NV 131:4758606c9316 406 link->mcast_compatibility = PICO_IGMPV3;
TASS Belgium NV 131:4758606c9316 407 return;
tass 68:0847e35d08a6 408 }
tass 68:0847e35d08a6 409
tass 68:0847e35d08a6 410 static int pico_igmp_is_checksum_valid(struct pico_frame *f)
tass 68:0847e35d08a6 411 {
TASS Belgium NV 131:4758606c9316 412 struct pico_ipv4_hdr *hdr = NULL;
TASS Belgium NV 131:4758606c9316 413 uint8_t ihl = 24, datalen = 0;
tass 68:0847e35d08a6 414
TASS Belgium NV 131:4758606c9316 415 hdr = (struct pico_ipv4_hdr *)f->net_hdr;
TASS Belgium NV 131:4758606c9316 416 ihl = (uint8_t)((hdr->vhl & 0x0F) * 4); /* IHL is in 32bit words */
TASS Belgium NV 131:4758606c9316 417 datalen = (uint8_t)(short_be(hdr->len) - ihl);
tass 68:0847e35d08a6 418
TASS Belgium NV 131:4758606c9316 419 if (short_be(pico_checksum(f->transport_hdr, datalen)) == 0)
TASS Belgium NV 131:4758606c9316 420 return 1;
TASS Belgium NV 131:4758606c9316 421
TASS Belgium NV 131:4758606c9316 422 igmp_dbg("IGMP: invalid checksum\n");
TASS Belgium NV 131:4758606c9316 423 return 0;
tass 68:0847e35d08a6 424 }
tass 68:0847e35d08a6 425
tass 68:0847e35d08a6 426 /* RFC 3376 $7.1 */
tass 68:0847e35d08a6 427 static int pico_igmp_compatibility_mode(struct pico_frame *f)
tass 68:0847e35d08a6 428 {
TASS Belgium NV 131:4758606c9316 429 struct pico_ipv4_hdr *hdr = NULL;
TASS Belgium NV 131:4758606c9316 430 struct pico_ipv4_link *link = NULL;
TASS Belgium NV 131:4758606c9316 431 struct pico_tree_node *index = NULL, *_tmp = NULL;
TASS Belgium NV 131:4758606c9316 432 struct igmp_timer t = {
TASS Belgium NV 131:4758606c9316 433 0
TASS Belgium NV 131:4758606c9316 434 };
TASS Belgium NV 131:4758606c9316 435 uint8_t ihl = 24, datalen = 0;
tass 68:0847e35d08a6 436
TASS Belgium NV 131:4758606c9316 437 link = pico_ipv4_link_by_dev(f->dev);
TASS Belgium NV 131:4758606c9316 438 if (!link)
TASS Belgium NV 131:4758606c9316 439 return -1;
TASS Belgium NV 131:4758606c9316 440
TASS Belgium NV 131:4758606c9316 441 hdr = (struct pico_ipv4_hdr *) f->net_hdr;
TASS Belgium NV 131:4758606c9316 442 ihl = (uint8_t)((hdr->vhl & 0x0F) * 4); /* IHL is in 32bit words */
TASS Belgium NV 131:4758606c9316 443 datalen = (uint8_t)(short_be(hdr->len) - ihl);
TASS Belgium NV 131:4758606c9316 444 igmp_dbg("IGMP: IHL = %u, LEN = %u, OCTETS = %u\n", ihl, short_be(hdr->len), datalen);
tass 68:0847e35d08a6 445
tass 152:a3d286bf94e5 446 if (datalen >= 12) {
TASS Belgium NV 131:4758606c9316 447 /* IGMPv3 query */
TASS Belgium NV 131:4758606c9316 448 t.type = IGMP_TIMER_V2_QUERIER;
TASS Belgium NV 131:4758606c9316 449 if (pico_igmp_timer_is_running(&t)) { /* IGMPv2 querier present timer still running */
tass 152:a3d286bf94e5 450 igmp_dbg("Timer is already running\n");
TASS Belgium NV 131:4758606c9316 451 return -1;
TASS Belgium NV 131:4758606c9316 452 } else {
TASS Belgium NV 131:4758606c9316 453 link->mcast_compatibility = PICO_IGMPV3;
tass 152:a3d286bf94e5 454 igmp_dbg("IGMP Compatibility: v3\n");
TASS Belgium NV 131:4758606c9316 455 return 0;
TASS Belgium NV 131:4758606c9316 456 }
TASS Belgium NV 131:4758606c9316 457 } else if (datalen == 8) {
TASS Belgium NV 131:4758606c9316 458 struct igmp_message *query = (struct igmp_message *)f->transport_hdr;
TASS Belgium NV 131:4758606c9316 459 if (query->max_resp_time != 0) {
TASS Belgium NV 131:4758606c9316 460 /* IGMPv2 query */
TASS Belgium NV 131:4758606c9316 461 /* When changing compatibility mode, cancel all pending response
TASS Belgium NV 131:4758606c9316 462 * and retransmission timers.
TASS Belgium NV 131:4758606c9316 463 */
TASS Belgium NV 131:4758606c9316 464 pico_tree_foreach_safe(index, &IGMPTimers, _tmp)
TASS Belgium NV 131:4758606c9316 465 {
TASS Belgium NV 131:4758606c9316 466 ((struct igmp_timer *)index->keyValue)->stopped = IGMP_TIMER_STOPPED;
TASS Belgium NV 131:4758606c9316 467 pico_tree_delete(&IGMPTimers, index->keyValue);
TASS Belgium NV 131:4758606c9316 468 }
TASS Belgium NV 131:4758606c9316 469 igmp_dbg("IGMP: switch to compatibility mode IGMPv2\n");
TASS Belgium NV 131:4758606c9316 470 link->mcast_compatibility = PICO_IGMPV2;
TASS Belgium NV 131:4758606c9316 471 t.type = IGMP_TIMER_V2_QUERIER;
TASS Belgium NV 131:4758606c9316 472 t.delay = ((IGMP_ROBUSTNESS * link->mcast_last_query_interval) + IGMP_QUERY_RESPONSE_INTERVAL) * 1000;
TASS Belgium NV 131:4758606c9316 473 t.f = f;
TASS Belgium NV 131:4758606c9316 474 t.callback = pico_igmp_v2querier_expired;
TASS Belgium NV 131:4758606c9316 475 /* only one of this type of timer may exist! */
TASS Belgium NV 131:4758606c9316 476 pico_igmp_timer_start(&t);
TASS Belgium NV 131:4758606c9316 477 } else {
TASS Belgium NV 131:4758606c9316 478 /* IGMPv1 query, not supported */
TASS Belgium NV 131:4758606c9316 479 return -1;
TASS Belgium NV 131:4758606c9316 480 }
tass 68:0847e35d08a6 481 } else {
TASS Belgium NV 131:4758606c9316 482 /* invalid query, silently ignored */
TASS Belgium NV 131:4758606c9316 483 return -1;
tass 68:0847e35d08a6 484 }
TASS Belgium NV 131:4758606c9316 485
TASS Belgium NV 131:4758606c9316 486 return 0;
tass 68:0847e35d08a6 487 }
tass 68:0847e35d08a6 488
tass 68:0847e35d08a6 489 static struct igmp_parameters *pico_igmp_analyse_packet(struct pico_frame *f)
tass 68:0847e35d08a6 490 {
TASS Belgium NV 131:4758606c9316 491 struct igmp_message *message = NULL;
TASS Belgium NV 131:4758606c9316 492 struct igmp_parameters *p = NULL;
TASS Belgium NV 131:4758606c9316 493 struct pico_ipv4_link *link = NULL;
TASS Belgium NV 131:4758606c9316 494 struct pico_ip4 mcast_group = {
TASS Belgium NV 131:4758606c9316 495 0
TASS Belgium NV 131:4758606c9316 496 };
tass 68:0847e35d08a6 497
TASS Belgium NV 131:4758606c9316 498 link = pico_ipv4_link_by_dev(f->dev);
TASS Belgium NV 131:4758606c9316 499 if (!link)
TASS Belgium NV 131:4758606c9316 500 return NULL;
TASS Belgium NV 131:4758606c9316 501
TASS Belgium NV 131:4758606c9316 502 /* IGMPv2 and IGMPv3 have a similar structure for the first 8 bytes */
TASS Belgium NV 131:4758606c9316 503 message = (struct igmp_message *)f->transport_hdr;
TASS Belgium NV 131:4758606c9316 504 mcast_group.addr = message->mcast_group;
TASS Belgium NV 131:4758606c9316 505 p = pico_igmp_find_parameter(&link->address, &mcast_group);
TASS Belgium NV 131:4758606c9316 506 if (!p && mcast_group.addr == 0) { /* general query */
tass picotcp@tass.be 149:5f4cb161cec3 507 p = PICO_ZALLOC(sizeof(struct igmp_parameters));
TASS Belgium NV 131:4758606c9316 508 if (!p)
TASS Belgium NV 131:4758606c9316 509 return NULL;
tass 68:0847e35d08a6 510
TASS Belgium NV 131:4758606c9316 511 p->state = IGMP_STATE_NON_MEMBER;
TASS Belgium NV 131:4758606c9316 512 p->mcast_link.addr = link->address.addr;
TASS Belgium NV 131:4758606c9316 513 p->mcast_group.addr = mcast_group.addr;
TASS Belgium NV 131:4758606c9316 514 pico_tree_insert(&IGMPParameters, p);
TASS Belgium NV 131:4758606c9316 515 } else if (!p) {
TASS Belgium NV 131:4758606c9316 516 return NULL;
TASS Belgium NV 131:4758606c9316 517 }
tass 68:0847e35d08a6 518
TASS Belgium NV 131:4758606c9316 519 switch (message->type) {
tass 68:0847e35d08a6 520 case IGMP_TYPE_MEM_QUERY:
TASS Belgium NV 131:4758606c9316 521 p->event = IGMP_EVENT_QUERY_RECV;
TASS Belgium NV 131:4758606c9316 522 break;
tass 68:0847e35d08a6 523 case IGMP_TYPE_MEM_REPORT_V1:
TASS Belgium NV 131:4758606c9316 524 p->event = IGMP_EVENT_REPORT_RECV;
TASS Belgium NV 131:4758606c9316 525 break;
tass 68:0847e35d08a6 526 case IGMP_TYPE_MEM_REPORT_V2:
TASS Belgium NV 131:4758606c9316 527 p->event = IGMP_EVENT_REPORT_RECV;
TASS Belgium NV 131:4758606c9316 528 break;
tass 68:0847e35d08a6 529 case IGMP_TYPE_MEM_REPORT_V3:
TASS Belgium NV 131:4758606c9316 530 p->event = IGMP_EVENT_REPORT_RECV;
TASS Belgium NV 131:4758606c9316 531 break;
tass 68:0847e35d08a6 532 default:
TASS Belgium NV 131:4758606c9316 533 return NULL;
TASS Belgium NV 131:4758606c9316 534 }
TASS Belgium NV 131:4758606c9316 535 p->max_resp_time = message->max_resp_time; /* if IGMPv3 report this will be 0 (res0 field) */
TASS Belgium NV 131:4758606c9316 536 p->f = f;
tass 68:0847e35d08a6 537
TASS Belgium NV 131:4758606c9316 538 return p;
tass 68:0847e35d08a6 539 }
tass 68:0847e35d08a6 540
tass 68:0847e35d08a6 541 static int pico_igmp_process_in(struct pico_protocol *self, struct pico_frame *f)
tass 68:0847e35d08a6 542 {
TASS Belgium NV 131:4758606c9316 543 struct igmp_parameters *p = NULL;
TASS Belgium NV 131:4758606c9316 544 IGNORE_PARAMETER(self);
TASS Belgium NV 131:4758606c9316 545
TASS Belgium NV 131:4758606c9316 546 if (!pico_igmp_is_checksum_valid(f))
TASS Belgium NV 131:4758606c9316 547 goto out;
tass 68:0847e35d08a6 548
TASS Belgium NV 131:4758606c9316 549 if (pico_igmp_compatibility_mode(f) < 0)
TASS Belgium NV 131:4758606c9316 550 goto out;
tass 68:0847e35d08a6 551
TASS Belgium NV 131:4758606c9316 552 p = pico_igmp_analyse_packet(f);
TASS Belgium NV 131:4758606c9316 553 if (!p)
TASS Belgium NV 131:4758606c9316 554 goto out;
tass 68:0847e35d08a6 555
TASS Belgium NV 131:4758606c9316 556 return pico_igmp_process_event(p);
TASS Belgium NV 131:4758606c9316 557
TASS Belgium NV 131:4758606c9316 558 out:
tass 68:0847e35d08a6 559 pico_frame_discard(f);
tass 68:0847e35d08a6 560 return 0;
tass 68:0847e35d08a6 561 }
tass 68:0847e35d08a6 562
TASS Belgium NV 131:4758606c9316 563 static int pico_igmp_process_out(struct pico_protocol *self, struct pico_frame *f)
TASS Belgium NV 131:4758606c9316 564 {
TASS Belgium NV 131:4758606c9316 565 /* packets are directly transferred to the IP layer by calling pico_ipv4_frame_push */
TASS Belgium NV 131:4758606c9316 566 IGNORE_PARAMETER(self);
TASS Belgium NV 131:4758606c9316 567 IGNORE_PARAMETER(f);
TASS Belgium NV 131:4758606c9316 568 return 0;
tass 68:0847e35d08a6 569 }
tass 68:0847e35d08a6 570
tass 68:0847e35d08a6 571 /* Interface: protocol definition */
tass 68:0847e35d08a6 572 struct pico_protocol pico_proto_igmp = {
TASS Belgium NV 131:4758606c9316 573 .name = "igmp",
TASS Belgium NV 131:4758606c9316 574 .proto_number = PICO_PROTO_IGMP,
TASS Belgium NV 131:4758606c9316 575 .layer = PICO_LAYER_TRANSPORT,
TASS Belgium NV 131:4758606c9316 576 .process_in = pico_igmp_process_in,
TASS Belgium NV 131:4758606c9316 577 .process_out = pico_igmp_process_out,
TASS Belgium NV 131:4758606c9316 578 .q_in = &igmp_in,
TASS Belgium NV 131:4758606c9316 579 .q_out = &igmp_out,
tass 68:0847e35d08a6 580 };
tass 68:0847e35d08a6 581
tass 152:a3d286bf94e5 582 int pico_igmp_state_change(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t filter_mode, struct pico_tree *_MCASTFilter, uint8_t state)
tass 68:0847e35d08a6 583 {
TASS Belgium NV 131:4758606c9316 584 struct igmp_parameters *p = NULL;
TASS Belgium NV 131:4758606c9316 585
TASS Belgium NV 131:4758606c9316 586 if (mcast_group->addr == IGMP_ALL_HOST_GROUP)
TASS Belgium NV 131:4758606c9316 587 return 0;
tass 68:0847e35d08a6 588
TASS Belgium NV 131:4758606c9316 589 p = pico_igmp_find_parameter(mcast_link, mcast_group);
TASS Belgium NV 131:4758606c9316 590 if (!p && state == PICO_IGMP_STATE_CREATE) {
tass picotcp@tass.be 149:5f4cb161cec3 591 p = PICO_ZALLOC(sizeof(struct igmp_parameters));
TASS Belgium NV 131:4758606c9316 592 if (!p) {
TASS Belgium NV 131:4758606c9316 593 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 594 return -1;
TASS Belgium NV 131:4758606c9316 595 }
TASS Belgium NV 131:4758606c9316 596
tass picotcp@tass.be 149:5f4cb161cec3 597 if (!mcast_link || !mcast_group) {
tass picotcp@tass.be 149:5f4cb161cec3 598 pico_err = PICO_ERR_EINVAL;
tass picotcp@tass.be 149:5f4cb161cec3 599 return -1;
tass picotcp@tass.be 149:5f4cb161cec3 600 }
tass picotcp@tass.be 149:5f4cb161cec3 601
TASS Belgium NV 131:4758606c9316 602 p->state = IGMP_STATE_NON_MEMBER;
TASS Belgium NV 131:4758606c9316 603 p->mcast_link = *mcast_link;
TASS Belgium NV 131:4758606c9316 604 p->mcast_group = *mcast_group;
TASS Belgium NV 131:4758606c9316 605 pico_tree_insert(&IGMPParameters, p);
TASS Belgium NV 131:4758606c9316 606 } else if (!p) {
TASS Belgium NV 131:4758606c9316 607 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 608 return -1;
tass 68:0847e35d08a6 609 }
tass 68:0847e35d08a6 610
TASS Belgium NV 131:4758606c9316 611 switch (state) {
tass 68:0847e35d08a6 612 case PICO_IGMP_STATE_CREATE:
TASS Belgium NV 131:4758606c9316 613 p->event = IGMP_EVENT_CREATE_GROUP;
TASS Belgium NV 131:4758606c9316 614 break;
tass 68:0847e35d08a6 615
tass 68:0847e35d08a6 616 case PICO_IGMP_STATE_UPDATE:
TASS Belgium NV 131:4758606c9316 617 p->event = IGMP_EVENT_UPDATE_GROUP;
TASS Belgium NV 131:4758606c9316 618 break;
TASS Belgium NV 131:4758606c9316 619
tass 68:0847e35d08a6 620 case PICO_IGMP_STATE_DELETE:
TASS Belgium NV 131:4758606c9316 621 p->event = IGMP_EVENT_DELETE_GROUP;
TASS Belgium NV 131:4758606c9316 622 break;
tass 68:0847e35d08a6 623
tass 68:0847e35d08a6 624 default:
TASS Belgium NV 131:4758606c9316 625 return -1;
TASS Belgium NV 131:4758606c9316 626 }
TASS Belgium NV 131:4758606c9316 627 p->filter_mode = filter_mode;
tass 152:a3d286bf94e5 628 p->MCASTFilter = _MCASTFilter;
tass 68:0847e35d08a6 629
TASS Belgium NV 131:4758606c9316 630 return pico_igmp_process_event(p);
tass 68:0847e35d08a6 631 }
tass 68:0847e35d08a6 632
tass 68:0847e35d08a6 633 static int pico_igmp_send_report(struct igmp_parameters *p, struct pico_frame *f)
tass 68:0847e35d08a6 634 {
TASS Belgium NV 131:4758606c9316 635 struct pico_ip4 dst = {
TASS Belgium NV 131:4758606c9316 636 0
TASS Belgium NV 131:4758606c9316 637 };
TASS Belgium NV 131:4758606c9316 638 struct pico_ip4 mcast_group = {
TASS Belgium NV 131:4758606c9316 639 0
TASS Belgium NV 131:4758606c9316 640 };
TASS Belgium NV 131:4758606c9316 641 struct pico_ipv4_link *link = NULL;
tass 68:0847e35d08a6 642
TASS Belgium NV 131:4758606c9316 643 link = pico_ipv4_link_get(&p->mcast_link);
TASS Belgium NV 131:4758606c9316 644 if (!link)
TASS Belgium NV 131:4758606c9316 645 return -1;
TASS Belgium NV 131:4758606c9316 646
TASS Belgium NV 131:4758606c9316 647 mcast_group.addr = p->mcast_group.addr;
TASS Belgium NV 131:4758606c9316 648 switch (link->mcast_compatibility) {
tass 68:0847e35d08a6 649 case PICO_IGMPV2:
TASS Belgium NV 131:4758606c9316 650 if (p->event == IGMP_EVENT_DELETE_GROUP)
TASS Belgium NV 131:4758606c9316 651 dst.addr = IGMP_ALL_ROUTER_GROUP;
TASS Belgium NV 131:4758606c9316 652 else
TASS Belgium NV 131:4758606c9316 653 dst.addr = mcast_group.addr;
TASS Belgium NV 131:4758606c9316 654
TASS Belgium NV 131:4758606c9316 655 break;
tass 68:0847e35d08a6 656
tass 68:0847e35d08a6 657 case PICO_IGMPV3:
TASS Belgium NV 131:4758606c9316 658 dst.addr = IGMPV3_ALL_ROUTER_GROUP;
TASS Belgium NV 131:4758606c9316 659 break;
tass 68:0847e35d08a6 660
tass 68:0847e35d08a6 661 default:
TASS Belgium NV 131:4758606c9316 662 pico_err = PICO_ERR_EPROTONOSUPPORT;
TASS Belgium NV 131:4758606c9316 663 return -1;
TASS Belgium NV 131:4758606c9316 664 }
tass 68:0847e35d08a6 665
TASS Belgium NV 131:4758606c9316 666 igmp_dbg("IGMP: send membership report on group %08X to %08X\n", mcast_group.addr, dst.addr);
TASS Belgium NV 131:4758606c9316 667 pico_ipv4_frame_push(f, &dst, PICO_PROTO_IGMP);
TASS Belgium NV 131:4758606c9316 668 return 0;
tass 68:0847e35d08a6 669 }
tass 68:0847e35d08a6 670
tass 70:cd218dd180e5 671 static int8_t pico_igmp_generate_report(struct igmp_parameters *p)
tass 68:0847e35d08a6 672 {
TASS Belgium NV 131:4758606c9316 673 struct pico_ipv4_link *link = NULL;
TASS Belgium NV 131:4758606c9316 674 int i = 0;
tass 68:0847e35d08a6 675
TASS Belgium NV 131:4758606c9316 676 link = pico_ipv4_link_get(&p->mcast_link);
TASS Belgium NV 131:4758606c9316 677 if (!link) {
TASS Belgium NV 131:4758606c9316 678 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 679 return -1;
TASS Belgium NV 131:4758606c9316 680 }
tass 68:0847e35d08a6 681
TASS Belgium NV 131:4758606c9316 682 switch (link->mcast_compatibility) {
tass 68:0847e35d08a6 683 case PICO_IGMPV1:
TASS Belgium NV 131:4758606c9316 684 pico_err = PICO_ERR_EPROTONOSUPPORT;
TASS Belgium NV 131:4758606c9316 685 return -1;
TASS Belgium NV 131:4758606c9316 686
tass 68:0847e35d08a6 687 case PICO_IGMPV2:
tass 68:0847e35d08a6 688 {
TASS Belgium NV 131:4758606c9316 689 struct igmp_message *report = NULL;
TASS Belgium NV 131:4758606c9316 690 uint8_t report_type = IGMP_TYPE_MEM_REPORT_V2;
TASS Belgium NV 131:4758606c9316 691 if (p->event == IGMP_EVENT_DELETE_GROUP)
TASS Belgium NV 131:4758606c9316 692 report_type = IGMP_TYPE_LEAVE_GROUP;
tass 68:0847e35d08a6 693
TASS Belgium NV 131:4758606c9316 694 p->f = pico_proto_ipv4.alloc(&pico_proto_ipv4, IP_OPTION_ROUTER_ALERT_LEN + sizeof(struct igmp_message));
TASS Belgium NV 131:4758606c9316 695 p->f->net_len = (uint16_t)(p->f->net_len + IP_OPTION_ROUTER_ALERT_LEN);
TASS Belgium NV 131:4758606c9316 696 p->f->transport_hdr += IP_OPTION_ROUTER_ALERT_LEN;
TASS Belgium NV 131:4758606c9316 697 p->f->transport_len = (uint16_t)(p->f->transport_len - IP_OPTION_ROUTER_ALERT_LEN);
TASS Belgium NV 131:4758606c9316 698 p->f->dev = pico_ipv4_link_find(&p->mcast_link);
TASS Belgium NV 131:4758606c9316 699 /* p->f->len is correctly set by alloc */
tass 68:0847e35d08a6 700
TASS Belgium NV 131:4758606c9316 701 report = (struct igmp_message *)p->f->transport_hdr;
TASS Belgium NV 131:4758606c9316 702 report->type = report_type;
TASS Belgium NV 131:4758606c9316 703 report->max_resp_time = IGMP_DEFAULT_MAX_RESPONSE_TIME;
TASS Belgium NV 131:4758606c9316 704 report->mcast_group = p->mcast_group.addr;
tass 68:0847e35d08a6 705
TASS Belgium NV 131:4758606c9316 706 report->crc = 0;
TASS Belgium NV 131:4758606c9316 707 report->crc = short_be(pico_checksum(report, sizeof(struct igmp_message)));
TASS Belgium NV 131:4758606c9316 708 break;
tass 68:0847e35d08a6 709 }
tass 68:0847e35d08a6 710 case PICO_IGMPV3:
tass 68:0847e35d08a6 711 {
TASS Belgium NV 131:4758606c9316 712 struct igmpv3_report *report = NULL;
TASS Belgium NV 131:4758606c9316 713 struct igmpv3_group_record *record = NULL;
TASS Belgium NV 131:4758606c9316 714 struct pico_mcast_group *g = NULL, test = {
TASS Belgium NV 131:4758606c9316 715 0
TASS Belgium NV 131:4758606c9316 716 };
TASS Belgium NV 131:4758606c9316 717 struct pico_tree_node *index = NULL, *_tmp = NULL;
TASS Belgium NV 131:4758606c9316 718 struct pico_tree *IGMPFilter = NULL;
TASS Belgium NV 131:4758606c9316 719 struct pico_ip4 *source = NULL;
TASS Belgium NV 131:4758606c9316 720 uint8_t record_type = 0;
TASS Belgium NV 131:4758606c9316 721 uint8_t sources = 0;
TASS Belgium NV 131:4758606c9316 722 uint16_t len = 0;
tass 68:0847e35d08a6 723
TASS Belgium NV 131:4758606c9316 724 test.mcast_addr = p->mcast_group;
TASS Belgium NV 131:4758606c9316 725 g = pico_tree_findKey(link->MCASTGroups, &test);
TASS Belgium NV 131:4758606c9316 726 if (!g) {
TASS Belgium NV 131:4758606c9316 727 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 728 return -1;
TASS Belgium NV 131:4758606c9316 729 }
TASS Belgium NV 131:4758606c9316 730
TASS Belgium NV 131:4758606c9316 731 if (p->event == IGMP_EVENT_DELETE_GROUP) { /* "non-existent" state of filter mode INCLUDE and empty source list */
TASS Belgium NV 131:4758606c9316 732 p->filter_mode = PICO_IP_MULTICAST_INCLUDE;
TASS Belgium NV 131:4758606c9316 733 p->MCASTFilter = NULL;
TASS Belgium NV 131:4758606c9316 734 }
tass 68:0847e35d08a6 735
tass 152:a3d286bf94e5 736 if (p->event == IGMP_EVENT_QUERY_RECV) {
tass 152:a3d286bf94e5 737 goto igmp3_report;
tass 152:a3d286bf94e5 738 }
tass 152:a3d286bf94e5 739
tass 152:a3d286bf94e5 740
TASS Belgium NV 131:4758606c9316 741 /* cleanup filters */
TASS Belgium NV 131:4758606c9316 742 pico_tree_foreach_safe(index, &IGMPAllow, _tmp)
TASS Belgium NV 131:4758606c9316 743 {
TASS Belgium NV 131:4758606c9316 744 pico_tree_delete(&IGMPAllow, index->keyValue);
TASS Belgium NV 131:4758606c9316 745 }
TASS Belgium NV 131:4758606c9316 746 pico_tree_foreach_safe(index, &IGMPBlock, _tmp)
TASS Belgium NV 131:4758606c9316 747 {
TASS Belgium NV 131:4758606c9316 748 pico_tree_delete(&IGMPBlock, index->keyValue);
TASS Belgium NV 131:4758606c9316 749 }
tass 68:0847e35d08a6 750
TASS Belgium NV 131:4758606c9316 751 switch (g->filter_mode) {
tass 68:0847e35d08a6 752
tass 68:0847e35d08a6 753 case PICO_IP_MULTICAST_INCLUDE:
TASS Belgium NV 131:4758606c9316 754 switch (p->filter_mode) {
tass 68:0847e35d08a6 755 case PICO_IP_MULTICAST_INCLUDE:
TASS Belgium NV 131:4758606c9316 756 if (p->event == IGMP_EVENT_DELETE_GROUP) { /* all ADD_SOURCE_MEMBERSHIP had an equivalent DROP_SOURCE_MEMBERSHIP */
TASS Belgium NV 131:4758606c9316 757 /* TO_IN (B) */
TASS Belgium NV 131:4758606c9316 758 record_type = IGMP_CHANGE_TO_INCLUDE_MODE;
TASS Belgium NV 131:4758606c9316 759 IGMPFilter = &IGMPAllow;
TASS Belgium NV 131:4758606c9316 760 if (p->MCASTFilter) {
TASS Belgium NV 131:4758606c9316 761 pico_tree_foreach(index, p->MCASTFilter) /* B */
TASS Belgium NV 131:4758606c9316 762 {
TASS Belgium NV 131:4758606c9316 763 pico_tree_insert(&IGMPAllow, index->keyValue);
TASS Belgium NV 131:4758606c9316 764 sources++;
TASS Belgium NV 131:4758606c9316 765 }
TASS Belgium NV 131:4758606c9316 766 } /* else { IGMPAllow stays empty } */
TASS Belgium NV 131:4758606c9316 767
TASS Belgium NV 131:4758606c9316 768 break;
TASS Belgium NV 131:4758606c9316 769 }
TASS Belgium NV 131:4758606c9316 770
TASS Belgium NV 131:4758606c9316 771 /* ALLOW (B-A) */
TASS Belgium NV 131:4758606c9316 772 /* if event is CREATE A will be empty, thus only ALLOW (B-A) has sense */
TASS Belgium NV 131:4758606c9316 773 if (p->event == IGMP_EVENT_CREATE_GROUP) /* first ADD_SOURCE_MEMBERSHIP */
TASS Belgium NV 131:4758606c9316 774 record_type = IGMP_CHANGE_TO_INCLUDE_MODE;
TASS Belgium NV 131:4758606c9316 775 else
TASS Belgium NV 131:4758606c9316 776 record_type = IGMP_ALLOW_NEW_SOURCES;
TASS Belgium NV 131:4758606c9316 777
TASS Belgium NV 131:4758606c9316 778 IGMPFilter = &IGMPAllow;
TASS Belgium NV 131:4758606c9316 779 pico_tree_foreach(index, p->MCASTFilter) /* B */
TASS Belgium NV 131:4758606c9316 780 {
TASS Belgium NV 131:4758606c9316 781 pico_tree_insert(&IGMPAllow, index->keyValue);
TASS Belgium NV 131:4758606c9316 782 sources++;
TASS Belgium NV 131:4758606c9316 783 }
TASS Belgium NV 131:4758606c9316 784 pico_tree_foreach(index, &g->MCASTSources) /* A */
TASS Belgium NV 131:4758606c9316 785 {
TASS Belgium NV 131:4758606c9316 786 source = pico_tree_findKey(&IGMPAllow, index->keyValue);
TASS Belgium NV 131:4758606c9316 787 if (source) {
TASS Belgium NV 131:4758606c9316 788 pico_tree_delete(&IGMPAllow, source);
TASS Belgium NV 131:4758606c9316 789 sources--;
TASS Belgium NV 131:4758606c9316 790 }
TASS Belgium NV 131:4758606c9316 791 }
TASS Belgium NV 131:4758606c9316 792 if (!pico_tree_empty(&IGMPAllow)) /* record type is ALLOW */
TASS Belgium NV 131:4758606c9316 793 break;
TASS Belgium NV 131:4758606c9316 794
TASS Belgium NV 131:4758606c9316 795 /* BLOCK (A-B) */
TASS Belgium NV 131:4758606c9316 796 record_type = IGMP_BLOCK_OLD_SOURCES;
TASS Belgium NV 131:4758606c9316 797 IGMPFilter = &IGMPBlock;
TASS Belgium NV 131:4758606c9316 798 pico_tree_foreach(index, &g->MCASTSources) /* A */
TASS Belgium NV 131:4758606c9316 799 {
TASS Belgium NV 131:4758606c9316 800 pico_tree_insert(&IGMPBlock, index->keyValue);
TASS Belgium NV 131:4758606c9316 801 sources++;
TASS Belgium NV 131:4758606c9316 802 }
TASS Belgium NV 131:4758606c9316 803 pico_tree_foreach(index, p->MCASTFilter) /* B */
TASS Belgium NV 131:4758606c9316 804 {
TASS Belgium NV 131:4758606c9316 805 source = pico_tree_findKey(&IGMPBlock, index->keyValue);
TASS Belgium NV 131:4758606c9316 806 if (source) {
TASS Belgium NV 131:4758606c9316 807 pico_tree_delete(&IGMPBlock, source);
TASS Belgium NV 131:4758606c9316 808 sources--;
TASS Belgium NV 131:4758606c9316 809 }
TASS Belgium NV 131:4758606c9316 810 }
TASS Belgium NV 131:4758606c9316 811 if (!pico_tree_empty(&IGMPBlock)) /* record type is BLOCK */
TASS Belgium NV 131:4758606c9316 812 break;
TASS Belgium NV 131:4758606c9316 813
TASS Belgium NV 131:4758606c9316 814 /* ALLOW (B-A) and BLOCK (A-B) are empty: do not send report (RFC 3376 $5.1) */
TASS Belgium NV 131:4758606c9316 815 p->f = NULL;
TASS Belgium NV 131:4758606c9316 816 return 0;
TASS Belgium NV 131:4758606c9316 817
TASS Belgium NV 131:4758606c9316 818 case PICO_IP_MULTICAST_EXCLUDE:
TASS Belgium NV 131:4758606c9316 819 /* TO_EX (B) */
TASS Belgium NV 131:4758606c9316 820 record_type = IGMP_CHANGE_TO_EXCLUDE_MODE;
TASS Belgium NV 131:4758606c9316 821 IGMPFilter = &IGMPBlock;
TASS Belgium NV 131:4758606c9316 822 pico_tree_foreach(index, p->MCASTFilter) /* B */
TASS Belgium NV 131:4758606c9316 823 {
TASS Belgium NV 131:4758606c9316 824 pico_tree_insert(&IGMPBlock, index->keyValue);
TASS Belgium NV 131:4758606c9316 825 sources++;
TASS Belgium NV 131:4758606c9316 826 }
TASS Belgium NV 131:4758606c9316 827 break;
TASS Belgium NV 131:4758606c9316 828
TASS Belgium NV 131:4758606c9316 829 default:
TASS Belgium NV 131:4758606c9316 830 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 831 return -1;
TASS Belgium NV 131:4758606c9316 832 }
TASS Belgium NV 131:4758606c9316 833 break;
TASS Belgium NV 131:4758606c9316 834
TASS Belgium NV 131:4758606c9316 835 case PICO_IP_MULTICAST_EXCLUDE:
TASS Belgium NV 131:4758606c9316 836 switch (p->filter_mode) {
TASS Belgium NV 131:4758606c9316 837 case PICO_IP_MULTICAST_INCLUDE:
tass 68:0847e35d08a6 838 /* TO_IN (B) */
tass 68:0847e35d08a6 839 record_type = IGMP_CHANGE_TO_INCLUDE_MODE;
tass 68:0847e35d08a6 840 IGMPFilter = &IGMPAllow;
tass 68:0847e35d08a6 841 if (p->MCASTFilter) {
TASS Belgium NV 131:4758606c9316 842 pico_tree_foreach(index, p->MCASTFilter) /* B */
TASS Belgium NV 131:4758606c9316 843 {
TASS Belgium NV 131:4758606c9316 844 pico_tree_insert(&IGMPAllow, index->keyValue);
TASS Belgium NV 131:4758606c9316 845 sources++;
TASS Belgium NV 131:4758606c9316 846 }
tass 68:0847e35d08a6 847 } /* else { IGMPAllow stays empty } */
tass 68:0847e35d08a6 848
tass 68:0847e35d08a6 849 break;
tass 68:0847e35d08a6 850
TASS Belgium NV 131:4758606c9316 851 case PICO_IP_MULTICAST_EXCLUDE:
TASS Belgium NV 131:4758606c9316 852 /* BLOCK (B-A) */
TASS Belgium NV 131:4758606c9316 853 record_type = IGMP_BLOCK_OLD_SOURCES;
TASS Belgium NV 131:4758606c9316 854 IGMPFilter = &IGMPBlock;
TASS Belgium NV 131:4758606c9316 855 pico_tree_foreach(index, p->MCASTFilter)
TASS Belgium NV 131:4758606c9316 856 {
TASS Belgium NV 131:4758606c9316 857 pico_tree_insert(&IGMPBlock, index->keyValue);
TASS Belgium NV 131:4758606c9316 858 sources++;
tass 68:0847e35d08a6 859 }
TASS Belgium NV 131:4758606c9316 860 pico_tree_foreach(index, &g->MCASTSources) /* A */
TASS Belgium NV 131:4758606c9316 861 {
TASS Belgium NV 131:4758606c9316 862 source = pico_tree_findKey(&IGMPBlock, index->keyValue); /* B */
TASS Belgium NV 131:4758606c9316 863 if (source) {
TASS Belgium NV 131:4758606c9316 864 pico_tree_delete(&IGMPBlock, source);
TASS Belgium NV 131:4758606c9316 865 sources--;
TASS Belgium NV 131:4758606c9316 866 }
TASS Belgium NV 131:4758606c9316 867 }
TASS Belgium NV 131:4758606c9316 868 if (!pico_tree_empty(&IGMPBlock)) /* record type is BLOCK */
TASS Belgium NV 131:4758606c9316 869 break;
tass 68:0847e35d08a6 870
TASS Belgium NV 131:4758606c9316 871 /* ALLOW (A-B) */
TASS Belgium NV 131:4758606c9316 872 record_type = IGMP_ALLOW_NEW_SOURCES;
TASS Belgium NV 131:4758606c9316 873 IGMPFilter = &IGMPAllow;
TASS Belgium NV 131:4758606c9316 874 pico_tree_foreach(index, &g->MCASTSources)
TASS Belgium NV 131:4758606c9316 875 {
TASS Belgium NV 131:4758606c9316 876 pico_tree_insert(&IGMPAllow, index->keyValue);
TASS Belgium NV 131:4758606c9316 877 sources++;
TASS Belgium NV 131:4758606c9316 878 }
tass 68:0847e35d08a6 879 pico_tree_foreach(index, p->MCASTFilter) /* B */
tass 68:0847e35d08a6 880 {
TASS Belgium NV 131:4758606c9316 881 source = pico_tree_findKey(&IGMPAllow, index->keyValue); /* A */
TASS Belgium NV 131:4758606c9316 882 if (source) {
TASS Belgium NV 131:4758606c9316 883 pico_tree_delete(&IGMPAllow, source);
TASS Belgium NV 131:4758606c9316 884 sources--;
TASS Belgium NV 131:4758606c9316 885 }
tass 68:0847e35d08a6 886 }
TASS Belgium NV 131:4758606c9316 887 if (!pico_tree_empty(&IGMPAllow)) /* record type is ALLOW */
TASS Belgium NV 131:4758606c9316 888 break;
tass 68:0847e35d08a6 889
TASS Belgium NV 131:4758606c9316 890 /* BLOCK (B-A) and ALLOW (A-B) are empty: do not send report (RFC 3376 $5.1) */
TASS Belgium NV 131:4758606c9316 891 p->f = NULL;
TASS Belgium NV 131:4758606c9316 892 return 0;
tass 68:0847e35d08a6 893
tass 68:0847e35d08a6 894 default:
TASS Belgium NV 131:4758606c9316 895 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 896 return -1;
TASS Belgium NV 131:4758606c9316 897 }
TASS Belgium NV 131:4758606c9316 898 break;
tass 68:0847e35d08a6 899
tass 68:0847e35d08a6 900 default:
TASS Belgium NV 131:4758606c9316 901 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 902 return -1;
TASS Belgium NV 131:4758606c9316 903 }
tass 68:0847e35d08a6 904
tass 152:a3d286bf94e5 905 igmp3_report:
TASS Belgium NV 131:4758606c9316 906 len = (uint16_t)(sizeof(struct igmpv3_report) + sizeof(struct igmpv3_group_record) + (sources * sizeof(struct pico_ip4)));
TASS Belgium NV 131:4758606c9316 907 p->f = pico_proto_ipv4.alloc(&pico_proto_ipv4, (uint16_t)(IP_OPTION_ROUTER_ALERT_LEN + len));
TASS Belgium NV 131:4758606c9316 908 p->f->net_len = (uint16_t)(p->f->net_len + IP_OPTION_ROUTER_ALERT_LEN);
TASS Belgium NV 131:4758606c9316 909 p->f->transport_hdr += IP_OPTION_ROUTER_ALERT_LEN;
TASS Belgium NV 131:4758606c9316 910 p->f->transport_len = (uint16_t)(p->f->transport_len - IP_OPTION_ROUTER_ALERT_LEN);
TASS Belgium NV 131:4758606c9316 911 p->f->dev = pico_ipv4_link_find(&p->mcast_link);
TASS Belgium NV 131:4758606c9316 912 /* p->f->len is correctly set by alloc */
tass 68:0847e35d08a6 913
TASS Belgium NV 131:4758606c9316 914 report = (struct igmpv3_report *)p->f->transport_hdr;
TASS Belgium NV 131:4758606c9316 915 report->type = IGMP_TYPE_MEM_REPORT_V3;
TASS Belgium NV 131:4758606c9316 916 report->res0 = 0;
TASS Belgium NV 131:4758606c9316 917 report->crc = 0;
TASS Belgium NV 131:4758606c9316 918 report->res1 = 0;
TASS Belgium NV 131:4758606c9316 919 report->groups = short_be(1);
tass 68:0847e35d08a6 920
TASS Belgium NV 131:4758606c9316 921 record = &report->record[0];
TASS Belgium NV 131:4758606c9316 922 record->type = record_type;
TASS Belgium NV 131:4758606c9316 923 record->aux = 0;
TASS Belgium NV 131:4758606c9316 924 record->sources = short_be(sources);
TASS Belgium NV 131:4758606c9316 925 record->mcast_group = p->mcast_group.addr;
tass 152:a3d286bf94e5 926 if (IGMPFilter && !pico_tree_empty(IGMPFilter)) {
TASS Belgium NV 131:4758606c9316 927 i = 0;
TASS Belgium NV 131:4758606c9316 928 pico_tree_foreach(index, IGMPFilter)
TASS Belgium NV 131:4758606c9316 929 {
TASS Belgium NV 131:4758606c9316 930 record->source_addr[i] = ((struct pico_ip4 *)index->keyValue)->addr;
TASS Belgium NV 131:4758606c9316 931 i++;
TASS Belgium NV 131:4758606c9316 932 }
tass 68:0847e35d08a6 933 }
TASS Belgium NV 131:4758606c9316 934
TASS Belgium NV 131:4758606c9316 935 report->crc = short_be(pico_checksum(report, len));
TASS Belgium NV 131:4758606c9316 936 break;
tass 68:0847e35d08a6 937 }
tass 68:0847e35d08a6 938
tass 68:0847e35d08a6 939 default:
TASS Belgium NV 131:4758606c9316 940 pico_err = PICO_ERR_EINVAL;
TASS Belgium NV 131:4758606c9316 941 return -1;
TASS Belgium NV 131:4758606c9316 942 }
TASS Belgium NV 131:4758606c9316 943 return 0;
tass 68:0847e35d08a6 944 }
tass 68:0847e35d08a6 945
tass 68:0847e35d08a6 946 /* stop timer, send leave if flag set */
tass 68:0847e35d08a6 947 static int stslifs(struct igmp_parameters *p)
tass 68:0847e35d08a6 948 {
TASS Belgium NV 131:4758606c9316 949 struct igmp_timer t = {
TASS Belgium NV 131:4758606c9316 950 0
TASS Belgium NV 131:4758606c9316 951 };
tass 68:0847e35d08a6 952
TASS Belgium NV 131:4758606c9316 953 igmp_dbg("IGMP: event = leave group | action = stop timer, send leave if flag set\n");
tass 68:0847e35d08a6 954
TASS Belgium NV 131:4758606c9316 955 t.type = IGMP_TIMER_GROUP_REPORT;
TASS Belgium NV 131:4758606c9316 956 t.mcast_link = p->mcast_link;
TASS Belgium NV 131:4758606c9316 957 t.mcast_group = p->mcast_group;
TASS Belgium NV 131:4758606c9316 958 if (pico_igmp_timer_stop(&t) < 0)
TASS Belgium NV 131:4758606c9316 959 return -1;
tass 68:0847e35d08a6 960
TASS Belgium NV 131:4758606c9316 961 /* always send leave, even if not last host */
TASS Belgium NV 131:4758606c9316 962 if (pico_igmp_send_report(p, p->f) < 0)
TASS Belgium NV 131:4758606c9316 963 return -1;
tass 68:0847e35d08a6 964
TASS Belgium NV 131:4758606c9316 965 pico_igmp_delete_parameter(p);
TASS Belgium NV 131:4758606c9316 966 igmp_dbg("IGMP: new state = non-member\n");
TASS Belgium NV 131:4758606c9316 967 return 0;
tass 68:0847e35d08a6 968 }
tass 68:0847e35d08a6 969
tass 68:0847e35d08a6 970 /* send report, set flag, start timer */
tass 68:0847e35d08a6 971 static int srsfst(struct igmp_parameters *p)
tass 68:0847e35d08a6 972 {
TASS Belgium NV 131:4758606c9316 973 struct igmp_timer t = {
TASS Belgium NV 131:4758606c9316 974 0
TASS Belgium NV 131:4758606c9316 975 };
TASS Belgium NV 131:4758606c9316 976 struct pico_frame *copy_frame = NULL;
TASS Belgium NV 131:4758606c9316 977
TASS Belgium NV 131:4758606c9316 978 igmp_dbg("IGMP: event = join group | action = send report, set flag, start timer\n");
tass 68:0847e35d08a6 979
TASS Belgium NV 131:4758606c9316 980 p->last_host = IGMP_HOST_LAST;
TASS Belgium NV 131:4758606c9316 981
TASS Belgium NV 131:4758606c9316 982 if (pico_igmp_generate_report(p) < 0)
TASS Belgium NV 131:4758606c9316 983 return -1;
TASS Belgium NV 131:4758606c9316 984
TASS Belgium NV 131:4758606c9316 985 if (!p->f)
TASS Belgium NV 131:4758606c9316 986 return 0;
tass 68:0847e35d08a6 987
TASS Belgium NV 131:4758606c9316 988 copy_frame = pico_frame_copy(p->f);
TASS Belgium NV 131:4758606c9316 989 if (!copy_frame) {
TASS Belgium NV 131:4758606c9316 990 pico_err = PICO_ERR_ENOMEM;
TASS Belgium NV 131:4758606c9316 991 return -1;
TASS Belgium NV 131:4758606c9316 992 }
TASS Belgium NV 131:4758606c9316 993
TASS Belgium NV 131:4758606c9316 994 if (pico_igmp_send_report(p, copy_frame) < 0)
TASS Belgium NV 131:4758606c9316 995 return -1;
tass 68:0847e35d08a6 996
TASS Belgium NV 131:4758606c9316 997 t.type = IGMP_TIMER_GROUP_REPORT;
TASS Belgium NV 131:4758606c9316 998 t.mcast_link = p->mcast_link;
TASS Belgium NV 131:4758606c9316 999 t.mcast_group = p->mcast_group;
TASS Belgium NV 131:4758606c9316 1000 t.delay = (pico_rand() % (IGMP_UNSOLICITED_REPORT_INTERVAL * 10000));
TASS Belgium NV 131:4758606c9316 1001 t.f = p->f;
TASS Belgium NV 131:4758606c9316 1002 t.callback = pico_igmp_report_expired;
TASS Belgium NV 131:4758606c9316 1003 pico_igmp_timer_start(&t);
TASS Belgium NV 131:4758606c9316 1004
TASS Belgium NV 131:4758606c9316 1005 p->state = IGMP_STATE_DELAYING_MEMBER;
TASS Belgium NV 131:4758606c9316 1006 igmp_dbg("IGMP: new state = delaying member\n");
tass 68:0847e35d08a6 1007 return 0;
tass 68:0847e35d08a6 1008 }
tass 68:0847e35d08a6 1009
tass 68:0847e35d08a6 1010 /* merge report, send report, reset timer (IGMPv3 only) */
tass 68:0847e35d08a6 1011 static int mrsrrt(struct igmp_parameters *p)
tass 68:0847e35d08a6 1012 {
TASS Belgium NV 131:4758606c9316 1013 struct igmp_timer *t = NULL;
TASS Belgium NV 131:4758606c9316 1014 struct pico_frame *copy_frame = NULL;
TASS Belgium NV 131:4758606c9316 1015 struct pico_ipv4_link *link = NULL;
tass 68:0847e35d08a6 1016
TASS Belgium NV 131:4758606c9316 1017 igmp_dbg("IGMP: event = update group | action = merge report, send report, reset timer (IGMPv3 only)\n");
tass 68:0847e35d08a6 1018
TASS Belgium NV 131:4758606c9316 1019 link = pico_ipv4_link_get(&p->mcast_link);
TASS Belgium NV 131:4758606c9316 1020 if (!link)
TASS Belgium NV 131:4758606c9316 1021 return -1;
tass 68:0847e35d08a6 1022
TASS Belgium NV 131:4758606c9316 1023 if (link->mcast_compatibility != PICO_IGMPV3) {
TASS Belgium NV 131:4758606c9316 1024 igmp_dbg("IGMP: no IGMPv3 compatible router on network\n");
TASS Belgium NV 131:4758606c9316 1025 return -1;
TASS Belgium NV 131:4758606c9316 1026 }
TASS Belgium NV 131:4758606c9316 1027
TASS Belgium NV 131:4758606c9316 1028 /* XXX: merge with pending report rfc 3376 $5.1 */
tass 68:0847e35d08a6 1029
TASS Belgium NV 131:4758606c9316 1030 copy_frame = pico_frame_copy(p->f);
TASS Belgium NV 131:4758606c9316 1031 if (!copy_frame)
TASS Belgium NV 131:4758606c9316 1032 return -1;
tass 68:0847e35d08a6 1033
TASS Belgium NV 131:4758606c9316 1034 if (pico_igmp_send_report(p, copy_frame) < 0)
TASS Belgium NV 131:4758606c9316 1035 return -1;
tass 68:0847e35d08a6 1036
TASS Belgium NV 131:4758606c9316 1037 t = pico_igmp_find_timer(IGMP_TIMER_GROUP_REPORT, &p->mcast_link, &p->mcast_group);
TASS Belgium NV 131:4758606c9316 1038 if (!t)
TASS Belgium NV 131:4758606c9316 1039 return -1;
tass 68:0847e35d08a6 1040
TASS Belgium NV 131:4758606c9316 1041 t->delay = (pico_rand() % (IGMP_UNSOLICITED_REPORT_INTERVAL * 10000));
TASS Belgium NV 131:4758606c9316 1042 pico_igmp_timer_reset(t);
TASS Belgium NV 131:4758606c9316 1043
TASS Belgium NV 131:4758606c9316 1044 p->state = IGMP_STATE_DELAYING_MEMBER;
TASS Belgium NV 131:4758606c9316 1045 igmp_dbg("IGMP: new state = delaying member\n");
TASS Belgium NV 131:4758606c9316 1046 return 0;
tass 68:0847e35d08a6 1047 }
tass 68:0847e35d08a6 1048
tass 68:0847e35d08a6 1049 /* send report, start timer (IGMPv3 only) */
tass 68:0847e35d08a6 1050 static int srst(struct igmp_parameters *p)
tass 68:0847e35d08a6 1051 {
TASS Belgium NV 131:4758606c9316 1052 struct igmp_timer t = {
TASS Belgium NV 131:4758606c9316 1053 0
TASS Belgium NV 131:4758606c9316 1054 };
TASS Belgium NV 131:4758606c9316 1055 struct pico_frame *copy_frame = NULL;
TASS Belgium NV 131:4758606c9316 1056 struct pico_ipv4_link *link = NULL;
tass 68:0847e35d08a6 1057
TASS Belgium NV 131:4758606c9316 1058 igmp_dbg("IGMP: event = update group | action = send report, start timer (IGMPv3 only)\n");
tass 68:0847e35d08a6 1059
TASS Belgium NV 131:4758606c9316 1060 link = pico_ipv4_link_get(&p->mcast_link);
TASS Belgium NV 131:4758606c9316 1061 if (!link)
TASS Belgium NV 131:4758606c9316 1062 return -1;
tass 68:0847e35d08a6 1063
TASS Belgium NV 131:4758606c9316 1064 if (link->mcast_compatibility != PICO_IGMPV3) {
TASS Belgium NV 131:4758606c9316 1065 igmp_dbg("IGMP: no IGMPv3 compatible router on network\n");
TASS Belgium NV 131:4758606c9316 1066 return -1;
TASS Belgium NV 131:4758606c9316 1067 }
TASS Belgium NV 131:4758606c9316 1068
TASS Belgium NV 131:4758606c9316 1069 if (pico_igmp_generate_report(p) < 0)
TASS Belgium NV 131:4758606c9316 1070 return -1;
tass 68:0847e35d08a6 1071
TASS Belgium NV 131:4758606c9316 1072 if (!p->f)
TASS Belgium NV 131:4758606c9316 1073 return 0;
TASS Belgium NV 131:4758606c9316 1074
TASS Belgium NV 131:4758606c9316 1075 copy_frame = pico_frame_copy(p->f);
TASS Belgium NV 131:4758606c9316 1076 if (!copy_frame)
TASS Belgium NV 131:4758606c9316 1077 return -1;
TASS Belgium NV 131:4758606c9316 1078
TASS Belgium NV 131:4758606c9316 1079 if (pico_igmp_send_report(p, copy_frame) < 0)
TASS Belgium NV 131:4758606c9316 1080 return -1;
tass 68:0847e35d08a6 1081
TASS Belgium NV 131:4758606c9316 1082 t.type = IGMP_TIMER_GROUP_REPORT;
TASS Belgium NV 131:4758606c9316 1083 t.mcast_link = p->mcast_link;
TASS Belgium NV 131:4758606c9316 1084 t.mcast_group = p->mcast_group;
TASS Belgium NV 131:4758606c9316 1085 t.delay = (pico_rand() % (IGMP_UNSOLICITED_REPORT_INTERVAL * 10000));
TASS Belgium NV 131:4758606c9316 1086 t.f = p->f;
TASS Belgium NV 131:4758606c9316 1087 t.callback = pico_igmp_report_expired;
TASS Belgium NV 131:4758606c9316 1088 pico_igmp_timer_start(&t);
tass 68:0847e35d08a6 1089
TASS Belgium NV 131:4758606c9316 1090 p->state = IGMP_STATE_DELAYING_MEMBER;
TASS Belgium NV 131:4758606c9316 1091 igmp_dbg("IGMP: new state = delaying member\n");
TASS Belgium NV 131:4758606c9316 1092 return 0;
tass 68:0847e35d08a6 1093 }
tass 68:0847e35d08a6 1094
tass 68:0847e35d08a6 1095 /* send leave if flag set */
tass 68:0847e35d08a6 1096 static int slifs(struct igmp_parameters *p)
tass 68:0847e35d08a6 1097 {
TASS Belgium NV 131:4758606c9316 1098 igmp_dbg("IGMP: event = leave group | action = send leave if flag set\n");
tass 68:0847e35d08a6 1099
TASS Belgium NV 131:4758606c9316 1100 /* always send leave, even if not last host */
TASS Belgium NV 131:4758606c9316 1101 if (pico_igmp_send_report(p, p->f) < 0)
TASS Belgium NV 131:4758606c9316 1102 return -1;
tass 68:0847e35d08a6 1103
TASS Belgium NV 131:4758606c9316 1104 pico_igmp_delete_parameter(p);
TASS Belgium NV 131:4758606c9316 1105 igmp_dbg("IGMP: new state = non-member\n");
TASS Belgium NV 131:4758606c9316 1106 return 0;
tass 68:0847e35d08a6 1107 }
tass 68:0847e35d08a6 1108
tass 68:0847e35d08a6 1109 /* start timer */
tass 68:0847e35d08a6 1110 static int st(struct igmp_parameters *p)
tass 68:0847e35d08a6 1111 {
TASS Belgium NV 131:4758606c9316 1112 struct igmp_timer t = {
TASS Belgium NV 131:4758606c9316 1113 0
TASS Belgium NV 131:4758606c9316 1114 };
tass 68:0847e35d08a6 1115
TASS Belgium NV 131:4758606c9316 1116 igmp_dbg("IGMP: event = query received | action = start timer\n");
tass 68:0847e35d08a6 1117
tass 152:a3d286bf94e5 1118 if (pico_igmp_generate_report(p) < 0) {
tass 152:a3d286bf94e5 1119 igmp_dbg("Failed to generate report\n");
TASS Belgium NV 131:4758606c9316 1120 return -1;
tass 152:a3d286bf94e5 1121 }
TASS Belgium NV 131:4758606c9316 1122
tass 152:a3d286bf94e5 1123 if (!p->f) {
tass 152:a3d286bf94e5 1124 igmp_dbg("No pending frame\n");
TASS Belgium NV 131:4758606c9316 1125 return -1;
tass 152:a3d286bf94e5 1126 }
tass 68:0847e35d08a6 1127
TASS Belgium NV 131:4758606c9316 1128 t.type = IGMP_TIMER_GROUP_REPORT;
TASS Belgium NV 131:4758606c9316 1129 t.mcast_link = p->mcast_link;
TASS Belgium NV 131:4758606c9316 1130 t.mcast_group = p->mcast_group;
tass 152:a3d286bf94e5 1131 t.delay = (pico_rand() % ((1u + p->max_resp_time) * 100u));
TASS Belgium NV 131:4758606c9316 1132 t.f = p->f;
TASS Belgium NV 131:4758606c9316 1133 t.callback = pico_igmp_report_expired;
TASS Belgium NV 131:4758606c9316 1134 pico_igmp_timer_start(&t);
tass 68:0847e35d08a6 1135
TASS Belgium NV 131:4758606c9316 1136 p->state = IGMP_STATE_DELAYING_MEMBER;
TASS Belgium NV 131:4758606c9316 1137 igmp_dbg("IGMP: new state = delaying member\n");
TASS Belgium NV 131:4758606c9316 1138 return 0;
tass 68:0847e35d08a6 1139 }
tass 68:0847e35d08a6 1140
tass 68:0847e35d08a6 1141 /* stop timer, clear flag */
tass 68:0847e35d08a6 1142 static int stcl(struct igmp_parameters *p)
tass 68:0847e35d08a6 1143 {
TASS Belgium NV 131:4758606c9316 1144 struct igmp_timer t = {
TASS Belgium NV 131:4758606c9316 1145 0
TASS Belgium NV 131:4758606c9316 1146 };
tass 68:0847e35d08a6 1147
TASS Belgium NV 131:4758606c9316 1148 igmp_dbg("IGMP: event = report received | action = stop timer, clear flag\n");
tass 68:0847e35d08a6 1149
TASS Belgium NV 131:4758606c9316 1150 t.type = IGMP_TIMER_GROUP_REPORT;
TASS Belgium NV 131:4758606c9316 1151 t.mcast_link = p->mcast_link;
TASS Belgium NV 131:4758606c9316 1152 t.mcast_group = p->mcast_group;
TASS Belgium NV 131:4758606c9316 1153 if (pico_igmp_timer_stop(&t) < 0)
TASS Belgium NV 131:4758606c9316 1154 return -1;
tass 68:0847e35d08a6 1155
TASS Belgium NV 131:4758606c9316 1156 p->last_host = IGMP_HOST_NOT_LAST;
TASS Belgium NV 131:4758606c9316 1157 p->state = IGMP_STATE_IDLE_MEMBER;
TASS Belgium NV 131:4758606c9316 1158 igmp_dbg("IGMP: new state = idle member\n");
TASS Belgium NV 131:4758606c9316 1159 return 0;
tass 68:0847e35d08a6 1160 }
tass 68:0847e35d08a6 1161
tass 68:0847e35d08a6 1162 /* send report, set flag */
tass 68:0847e35d08a6 1163 static int srsf(struct igmp_parameters *p)
tass 68:0847e35d08a6 1164 {
TASS Belgium NV 131:4758606c9316 1165 igmp_dbg("IGMP: event = timer expired | action = send report, set flag\n");
tass 68:0847e35d08a6 1166
TASS Belgium NV 131:4758606c9316 1167 if (pico_igmp_send_report(p, p->f) < 0)
TASS Belgium NV 131:4758606c9316 1168 return -1;
tass 68:0847e35d08a6 1169
TASS Belgium NV 131:4758606c9316 1170 p->state = IGMP_STATE_IDLE_MEMBER;
TASS Belgium NV 131:4758606c9316 1171 igmp_dbg("IGMP: new state = idle member\n");
TASS Belgium NV 131:4758606c9316 1172 return 0;
tass 68:0847e35d08a6 1173 }
tass 68:0847e35d08a6 1174
tass 68:0847e35d08a6 1175 /* reset timer if max response time < current timer */
tass 68:0847e35d08a6 1176 static int rtimrtct(struct igmp_parameters *p)
tass 68:0847e35d08a6 1177 {
TASS Belgium NV 131:4758606c9316 1178 struct igmp_timer *t = NULL;
TASS Belgium NV 131:4758606c9316 1179 uint32_t time_to_run = 0;
tass 68:0847e35d08a6 1180
TASS Belgium NV 131:4758606c9316 1181 igmp_dbg("IGMP: event = query received | action = reset timer if max response time < current timer\n");
tass 68:0847e35d08a6 1182
TASS Belgium NV 131:4758606c9316 1183 t = pico_igmp_find_timer(IGMP_TIMER_GROUP_REPORT, &p->mcast_link, &p->mcast_group);
TASS Belgium NV 131:4758606c9316 1184 if (!t)
TASS Belgium NV 131:4758606c9316 1185 return -1;
tass 68:0847e35d08a6 1186
TASS Belgium NV 131:4758606c9316 1187 time_to_run = (uint32_t)(t->start + t->delay - PICO_TIME_MS());
tass picotcp@tass.be 149:5f4cb161cec3 1188 if ((p->max_resp_time * 100u) < time_to_run) { /* max_resp_time in units of 1/10 seconds */
tass 152:a3d286bf94e5 1189 t->delay = pico_rand() % ((1u + p->max_resp_time) * 100u);
TASS Belgium NV 131:4758606c9316 1190 pico_igmp_timer_reset(t);
TASS Belgium NV 131:4758606c9316 1191 }
tass 68:0847e35d08a6 1192
TASS Belgium NV 131:4758606c9316 1193 p->state = IGMP_STATE_DELAYING_MEMBER;
TASS Belgium NV 131:4758606c9316 1194 igmp_dbg("IGMP: new state = delaying member\n");
TASS Belgium NV 131:4758606c9316 1195 return 0;
tass 68:0847e35d08a6 1196 }
tass 68:0847e35d08a6 1197
TASS Belgium NV 131:4758606c9316 1198 static int discard(struct igmp_parameters *p)
TASS Belgium NV 131:4758606c9316 1199 {
TASS Belgium NV 131:4758606c9316 1200 igmp_dbg("IGMP: ignore and discard frame\n");
TASS Belgium NV 131:4758606c9316 1201 pico_frame_discard(p->f);
TASS Belgium NV 131:4758606c9316 1202 return 0;
tass 68:0847e35d08a6 1203 }
tass 68:0847e35d08a6 1204
tass 68:0847e35d08a6 1205 /* finite state machine table */
tass 68:0847e35d08a6 1206 const callback host_membership_diagram_table[3][6] =
tass 68:0847e35d08a6 1207 { /* event |Delete Group |Create Group |Update Group |Query Received |Report Received |Timer Expired */
TASS Belgium NV 131:4758606c9316 1208 /* state Non-Member */
TASS Belgium NV 131:4758606c9316 1209 { discard, srsfst, srsfst, discard, discard, discard },
tass 68:0847e35d08a6 1210 /* state Delaying Member */ { stslifs, mrsrrt, mrsrrt, rtimrtct, stcl, srsf },
tass 68:0847e35d08a6 1211 /* state Idle Member */ { slifs, srst, srst, st, discard, discard }
tass 68:0847e35d08a6 1212 };
tass 68:0847e35d08a6 1213
tass 68:0847e35d08a6 1214 static int pico_igmp_process_event(struct igmp_parameters *p)
tass 68:0847e35d08a6 1215 {
TASS Belgium NV 131:4758606c9316 1216 struct pico_tree_node *index = NULL;
TASS Belgium NV 131:4758606c9316 1217 struct igmp_parameters *_p = NULL;
tass 68:0847e35d08a6 1218
TASS Belgium NV 131:4758606c9316 1219 igmp_dbg("IGMP: process event on group address %08X\n", p->mcast_group.addr);
TASS Belgium NV 131:4758606c9316 1220 if (p->event == IGMP_EVENT_QUERY_RECV && p->mcast_group.addr == 0) { /* general query */
TASS Belgium NV 131:4758606c9316 1221 pico_tree_foreach(index, &IGMPParameters) {
TASS Belgium NV 131:4758606c9316 1222 _p = index->keyValue;
TASS Belgium NV 131:4758606c9316 1223 _p->max_resp_time = p->max_resp_time;
TASS Belgium NV 131:4758606c9316 1224 _p->event = IGMP_EVENT_QUERY_RECV;
TASS Belgium NV 131:4758606c9316 1225 igmp_dbg("IGMP: for each mcast_group = %08X | state = %u\n", _p->mcast_group.addr, _p->state);
TASS Belgium NV 131:4758606c9316 1226 host_membership_diagram_table[_p->state][_p->event](_p);
TASS Belgium NV 131:4758606c9316 1227 }
TASS Belgium NV 131:4758606c9316 1228 } else {
TASS Belgium NV 131:4758606c9316 1229 igmp_dbg("IGMP: state = %u (0: non-member - 1: delaying member - 2: idle member)\n", p->state);
TASS Belgium NV 131:4758606c9316 1230 host_membership_diagram_table[p->state][p->event](p);
tass 68:0847e35d08a6 1231 }
TASS Belgium NV 131:4758606c9316 1232
TASS Belgium NV 131:4758606c9316 1233 return 0;
tass 68:0847e35d08a6 1234 }
tass 68:0847e35d08a6 1235
tass 152:a3d286bf94e5 1236 #else
tass 152:a3d286bf94e5 1237 static struct pico_queue igmp_in = {
tass 152:a3d286bf94e5 1238 0
tass 152:a3d286bf94e5 1239 };
tass 152:a3d286bf94e5 1240 static struct pico_queue igmp_out = {
tass 152:a3d286bf94e5 1241 0
tass 152:a3d286bf94e5 1242 };
tass 152:a3d286bf94e5 1243
tass 152:a3d286bf94e5 1244 static int pico_igmp_process_in(struct pico_protocol *self, struct pico_frame *f) {
tass 152:a3d286bf94e5 1245 IGNORE_PARAMETER(self);
tass 152:a3d286bf94e5 1246 IGNORE_PARAMETER(f);
tass 152:a3d286bf94e5 1247 pico_err = PICO_ERR_EPROTONOSUPPORT;
tass 152:a3d286bf94e5 1248 return -1;
tass 152:a3d286bf94e5 1249 }
tass 152:a3d286bf94e5 1250
tass 152:a3d286bf94e5 1251 static int pico_igmp_process_out(struct pico_protocol *self, struct pico_frame *f) {
tass 152:a3d286bf94e5 1252 IGNORE_PARAMETER(self);
tass 152:a3d286bf94e5 1253 IGNORE_PARAMETER(f);
tass 152:a3d286bf94e5 1254 return -1;
tass 152:a3d286bf94e5 1255 }
tass 152:a3d286bf94e5 1256
tass 152:a3d286bf94e5 1257 /* Interface: protocol definition */
tass 152:a3d286bf94e5 1258 struct pico_protocol pico_proto_igmp = {
tass 152:a3d286bf94e5 1259 .name = "igmp",
tass 152:a3d286bf94e5 1260 .proto_number = PICO_PROTO_IGMP,
tass 152:a3d286bf94e5 1261 .layer = PICO_LAYER_TRANSPORT,
tass 152:a3d286bf94e5 1262 .process_in = pico_igmp_process_in,
tass 152:a3d286bf94e5 1263 .process_out = pico_igmp_process_out,
tass 152:a3d286bf94e5 1264 .q_in = &igmp_in,
tass 152:a3d286bf94e5 1265 .q_out = &igmp_out,
tass 152:a3d286bf94e5 1266 };
tass 152:a3d286bf94e5 1267
tass 152:a3d286bf94e5 1268 int pico_igmp_state_change(struct pico_ip4 *mcast_link, struct pico_ip4 *mcast_group, uint8_t filter_mode, struct pico_tree *_MCASTFilter, uint8_t state) {
tass 152:a3d286bf94e5 1269 IGNORE_PARAMETER(mcast_link);
tass 152:a3d286bf94e5 1270 IGNORE_PARAMETER(mcast_group);
tass 152:a3d286bf94e5 1271 IGNORE_PARAMETER(filter_mode);
tass 152:a3d286bf94e5 1272 IGNORE_PARAMETER(_MCASTFilter);
tass 152:a3d286bf94e5 1273 IGNORE_PARAMETER(state);
tass 152:a3d286bf94e5 1274 pico_err = PICO_ERR_EPROTONOSUPPORT;
tass 152:a3d286bf94e5 1275 return -1;
tass 152:a3d286bf94e5 1276 }
tass 152:a3d286bf94e5 1277 #endif