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

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

PicoTCP. Copyright (c) 2013 TASS Belgium NV.

Released under the GNU General Public License, version 2.

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

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

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

Development steps:

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

Demo application (measuring TCP sender performance):

Import programlpc1768-picotcp-demo

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

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

Who changed what in which revision?

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