Free (GPLv2) TCP/IP stack developed by TASS Belgium
Dependents: lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more
PicoTCP. Copyright (c) 2013 TASS Belgium NV.
Released under the GNU General Public License, version 2.
Different licensing models may exist, at the sole discretion of the Copyright holders.
Official homepage: http://www.picotcp.com
Bug tracker: https://github.com/tass-belgium/picotcp/issues
Development steps:
initial integration with mbed RTOSgeneric mbed Ethernet driverhigh performance NXP LPC1768 specific Ethernet driverMulti-threading support for mbed RTOSBerkeley sockets and integration with the New Socket APIFork of the apps running on top of the New Socket APIScheduling optimizations- Debugging/benchmarking/testing
Demo application (measuring TCP sender performance):
Import programlpc1768-picotcp-demo
A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.
stack/pico_socket_multicast.c@155:a70f34550c34, 2016-01-28 (annotated)
- 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?
User | Revision | Line number | New contents of line |
---|---|---|---|
tass | 152:a3d286bf94e5 | 1 | #include "pico_config.h" |
tass | 152:a3d286bf94e5 | 2 | #include "pico_stack.h" |
tass picotcp@tass.be | 149:5f4cb161cec3 | 3 | #include "pico_socket.h" |
tass picotcp@tass.be | 149:5f4cb161cec3 | 4 | #include "pico_socket_multicast.h" |
tass picotcp@tass.be | 149:5f4cb161cec3 | 5 | #include "pico_tree.h" |
tass picotcp@tass.be | 149:5f4cb161cec3 | 6 | #include "pico_ipv4.h" |
tass | 152:a3d286bf94e5 | 7 | #include "pico_ipv6.h" |
tass picotcp@tass.be | 149:5f4cb161cec3 | 8 | #include "pico_udp.h" |
tass picotcp@tass.be | 149:5f4cb161cec3 | 9 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 10 | #ifdef PICO_SUPPORT_MCAST |
tass | 152:a3d286bf94e5 | 11 | # define so_mcast_dbg(...) do { }while(0) /* ip_mcast_dbg in pico_ipv4.c */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 12 | /* #define so_mcast_dbg dbg */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 13 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 14 | /* socket |
tass | 152:a3d286bf94e5 | 15 | * | |
tass | 152:a3d286bf94e5 | 16 | * MCASTListen |
tass | 152:a3d286bf94e5 | 17 | * | | | |
tass | 152:a3d286bf94e5 | 18 | * ------------ | ------------ |
tass | 152:a3d286bf94e5 | 19 | * | | | |
tass | 152:a3d286bf94e5 | 20 | * MCASTSources MCASTSources MCASTSources |
tass | 152:a3d286bf94e5 | 21 | * | | | | | | | | | | | | |
tass | 152:a3d286bf94e5 | 22 | * S S S S S S S S S S S S |
tass | 152:a3d286bf94e5 | 23 | * |
tass | 152:a3d286bf94e5 | 24 | * MCASTListen: RBTree(mcast_link, mcast_group) |
tass | 152:a3d286bf94e5 | 25 | * MCASTSources: RBTree(source) |
tass | 152:a3d286bf94e5 | 26 | */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 27 | struct pico_mcast_listen |
tass picotcp@tass.be | 149:5f4cb161cec3 | 28 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 29 | uint8_t filter_mode; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 30 | union pico_address mcast_link; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 31 | union pico_address mcast_group; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 32 | struct pico_tree MCASTSources; |
tass | 152:a3d286bf94e5 | 33 | struct pico_tree MCASTSources_ipv6; |
tass | 152:a3d286bf94e5 | 34 | uint16_t proto; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 35 | }; |
tass | 152:a3d286bf94e5 | 36 | //Parameters |
tass | 152:a3d286bf94e5 | 37 | struct pico_mcast |
tass | 152:a3d286bf94e5 | 38 | { |
tass | 152:a3d286bf94e5 | 39 | struct pico_socket *s; |
tass | 154:6c0e92a80c4a | 40 | struct pico_ip_mreq *mreq; |
tass | 154:6c0e92a80c4a | 41 | struct pico_ip_mreq_source *mreq_s; |
tass | 152:a3d286bf94e5 | 42 | union pico_address *address; |
tass | 152:a3d286bf94e5 | 43 | union pico_link *mcast_link; |
tass | 152:a3d286bf94e5 | 44 | struct pico_mcast_listen *listen; |
tass | 152:a3d286bf94e5 | 45 | }; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 46 | static int mcast_listen_link_cmp(struct pico_mcast_listen *a, struct pico_mcast_listen *b) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 47 | { |
tass | 152:a3d286bf94e5 | 48 | |
tass | 152:a3d286bf94e5 | 49 | if (a->proto < b->proto) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 50 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 51 | |
tass | 152:a3d286bf94e5 | 52 | if (a->proto > b->proto) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 53 | return 1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 54 | |
tass | 152:a3d286bf94e5 | 55 | return pico_address_compare(&a->mcast_link, &b->mcast_link, a->proto); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 56 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 57 | |
tass | 152:a3d286bf94e5 | 58 | static int mcast_listen_grp_cmp(struct pico_mcast_listen *a, struct pico_mcast_listen *b) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 59 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 60 | if (a->mcast_group.ip4.addr < b->mcast_group.ip4.addr) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 61 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 62 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 63 | if (a->mcast_group.ip4.addr > b->mcast_group.ip4.addr) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 64 | return 1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 65 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 66 | return mcast_listen_link_cmp(a, b); |
tass | 152:a3d286bf94e5 | 67 | } |
tass | 152:a3d286bf94e5 | 68 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 69 | static int mcast_listen_grp_cmp_ipv6(struct pico_mcast_listen *a, struct pico_mcast_listen *b) |
tass | 152:a3d286bf94e5 | 70 | { |
tass | 152:a3d286bf94e5 | 71 | int tmp = memcmp(&a->mcast_group.ip6, &b->mcast_group.ip6, sizeof(struct pico_ip6)); |
tass | 152:a3d286bf94e5 | 72 | if(!tmp) |
tass | 152:a3d286bf94e5 | 73 | return mcast_listen_link_cmp(a, b); |
tass | 152:a3d286bf94e5 | 74 | return tmp; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 75 | } |
tass | 152:a3d286bf94e5 | 76 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 77 | |
tass | 152:a3d286bf94e5 | 78 | static int mcast_listen_cmp(void *ka, void *kb) |
tass | 152:a3d286bf94e5 | 79 | { |
tass | 152:a3d286bf94e5 | 80 | struct pico_mcast_listen *a = ka, *b = kb; |
tass | 152:a3d286bf94e5 | 81 | if (a->proto < b->proto) |
tass | 152:a3d286bf94e5 | 82 | return -1; |
tass | 152:a3d286bf94e5 | 83 | |
tass | 152:a3d286bf94e5 | 84 | if (a->proto > b->proto) |
tass | 152:a3d286bf94e5 | 85 | return 1; |
tass | 152:a3d286bf94e5 | 86 | |
tass | 152:a3d286bf94e5 | 87 | return mcast_listen_grp_cmp(a, b); |
tass | 152:a3d286bf94e5 | 88 | } |
tass | 152:a3d286bf94e5 | 89 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 90 | static int mcast_listen_cmp_ipv6(void *ka, void *kb) |
tass | 152:a3d286bf94e5 | 91 | { |
tass | 152:a3d286bf94e5 | 92 | struct pico_mcast_listen *a = ka, *b = kb; |
tass | 152:a3d286bf94e5 | 93 | if (a->proto < b->proto) |
tass | 152:a3d286bf94e5 | 94 | return -1; |
tass | 152:a3d286bf94e5 | 95 | |
tass | 152:a3d286bf94e5 | 96 | if (a->proto > b->proto) |
tass | 152:a3d286bf94e5 | 97 | return 1; |
tass | 152:a3d286bf94e5 | 98 | |
tass | 152:a3d286bf94e5 | 99 | return mcast_listen_grp_cmp_ipv6(a, b); |
tass | 152:a3d286bf94e5 | 100 | } |
tass | 152:a3d286bf94e5 | 101 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 102 | static int mcast_sources_cmp(void *ka, void *kb) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 103 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 104 | union pico_address *a = ka, *b = kb; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 105 | if (a->ip4.addr < b->ip4.addr) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 106 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 107 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 108 | if (a->ip4.addr > b->ip4.addr) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 109 | return 1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 110 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 111 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 112 | } |
tass | 152:a3d286bf94e5 | 113 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 114 | static int mcast_sources_cmp_ipv6(void *ka, void *kb) |
tass | 152:a3d286bf94e5 | 115 | { |
tass | 152:a3d286bf94e5 | 116 | union pico_address *a = ka, *b = kb; |
tass | 152:a3d286bf94e5 | 117 | return memcmp(&a->ip6, &b->ip6, sizeof(struct pico_ip6)); |
tass | 152:a3d286bf94e5 | 118 | } |
tass | 152:a3d286bf94e5 | 119 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 120 | static int mcast_socket_cmp(void *ka, void *kb) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 121 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 122 | struct pico_socket *a = ka, *b = kb; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 123 | if (a < b) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 124 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 125 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 126 | if (a > b) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 127 | return 1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 128 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 129 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 130 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 131 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 132 | /* gather all multicast sockets to hasten filter aggregation */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 133 | PICO_TREE_DECLARE(MCASTSockets, mcast_socket_cmp); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 134 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 135 | static int mcast_filter_cmp(void *ka, void *kb) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 136 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 137 | union pico_address *a = ka, *b = kb; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 138 | if (a->ip4.addr < b->ip4.addr) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 139 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 140 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 141 | if (a->ip4.addr > b->ip4.addr) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 142 | return 1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 143 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 144 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 145 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 146 | /* gather sources to be filtered */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 147 | PICO_TREE_DECLARE(MCASTFilter, mcast_filter_cmp); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 148 | |
tass | 152:a3d286bf94e5 | 149 | static int mcast_filter_cmp_ipv6(void *ka, void *kb) |
tass | 152:a3d286bf94e5 | 150 | { |
tass | 152:a3d286bf94e5 | 151 | union pico_address *a = ka, *b = kb; |
tass | 152:a3d286bf94e5 | 152 | return memcmp(&a->ip6, &b->ip6, sizeof(struct pico_ip6)); |
tass | 152:a3d286bf94e5 | 153 | } |
tass | 152:a3d286bf94e5 | 154 | /* gather sources to be filtered */ |
tass | 152:a3d286bf94e5 | 155 | PICO_TREE_DECLARE(MCASTFilter_ipv6, mcast_filter_cmp_ipv6); |
tass | 152:a3d286bf94e5 | 156 | |
tass | 152:a3d286bf94e5 | 157 | inline static struct pico_tree *mcast_get_src_tree(struct pico_socket *s,struct pico_mcast *mcast) { |
tass | 152:a3d286bf94e5 | 158 | if( IS_SOCK_IPV4(s)) { |
tass | 152:a3d286bf94e5 | 159 | mcast->listen->MCASTSources.compare = mcast_sources_cmp; |
tass | 152:a3d286bf94e5 | 160 | return &mcast->listen->MCASTSources; |
tass | 152:a3d286bf94e5 | 161 | } |
tass | 152:a3d286bf94e5 | 162 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 163 | else if( IS_SOCK_IPV6(s) ) { |
tass | 152:a3d286bf94e5 | 164 | mcast->listen->MCASTSources_ipv6.compare = mcast_sources_cmp_ipv6; |
tass | 152:a3d286bf94e5 | 165 | return &mcast->listen->MCASTSources_ipv6; |
tass | 152:a3d286bf94e5 | 166 | } |
tass | 152:a3d286bf94e5 | 167 | #endif |
tass | 152:a3d286bf94e5 | 168 | return NULL; |
tass | 152:a3d286bf94e5 | 169 | } |
tass | 152:a3d286bf94e5 | 170 | inline static struct pico_tree *mcast_get_listen_tree(struct pico_socket *s) { |
tass | 152:a3d286bf94e5 | 171 | if( IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 172 | return s->MCASTListen; |
tass | 152:a3d286bf94e5 | 173 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 174 | else if( IS_SOCK_IPV6(s) ) |
tass | 152:a3d286bf94e5 | 175 | return s->MCASTListen_ipv6; |
tass | 152:a3d286bf94e5 | 176 | #endif |
tass | 152:a3d286bf94e5 | 177 | return NULL; |
tass | 152:a3d286bf94e5 | 178 | } |
tass | 152:a3d286bf94e5 | 179 | inline static void mcast_set_listen_tree_p_null(struct pico_socket *s) { |
tass | 152:a3d286bf94e5 | 180 | if( IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 181 | s->MCASTListen = NULL; |
tass | 152:a3d286bf94e5 | 182 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 183 | else if( IS_SOCK_IPV6(s) ) |
tass | 152:a3d286bf94e5 | 184 | s->MCASTListen_ipv6 = NULL; |
tass | 152:a3d286bf94e5 | 185 | #endif |
tass | 152:a3d286bf94e5 | 186 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 187 | static struct pico_mcast_listen *listen_find(struct pico_socket *s, union pico_address *lnk, union pico_address *grp) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 188 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 189 | struct pico_mcast_listen ltest = { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 190 | 0 |
tass picotcp@tass.be | 149:5f4cb161cec3 | 191 | }; |
tass | 152:a3d286bf94e5 | 192 | ltest.mcast_link = *lnk; |
tass | 152:a3d286bf94e5 | 193 | ltest.mcast_group = *grp; |
tass | 152:a3d286bf94e5 | 194 | |
tass | 152:a3d286bf94e5 | 195 | if(IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 196 | return pico_tree_findKey(s->MCASTListen, <est); |
tass | 152:a3d286bf94e5 | 197 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 198 | else if(IS_SOCK_IPV6(s) ) { |
tass | 152:a3d286bf94e5 | 199 | ltest.proto = PICO_PROTO_IPV6; |
tass | 152:a3d286bf94e5 | 200 | return pico_tree_findKey(s->MCASTListen_ipv6, <est); |
tass | 152:a3d286bf94e5 | 201 | } |
tass | 152:a3d286bf94e5 | 202 | #endif |
tass | 152:a3d286bf94e5 | 203 | return NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 204 | } |
tass | 152:a3d286bf94e5 | 205 | static union pico_address *pico_mcast_get_link_address(struct pico_socket *s, union pico_link *mcast_link) { |
tass | 152:a3d286bf94e5 | 206 | if( IS_SOCK_IPV4(s) ) |
tass | 152:a3d286bf94e5 | 207 | return (union pico_address *) &mcast_link->ipv4.address; |
tass | 152:a3d286bf94e5 | 208 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 209 | if( IS_SOCK_IPV6(s)) |
tass | 152:a3d286bf94e5 | 210 | return (union pico_address *) &mcast_link->ipv6.address; |
tass | 152:a3d286bf94e5 | 211 | #endif |
tass | 152:a3d286bf94e5 | 212 | return NULL; |
tass | 152:a3d286bf94e5 | 213 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 214 | static uint8_t pico_mcast_filter_excl_excl(struct pico_mcast_listen *listen) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 215 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 216 | /* filter = intersection of EXCLUDEs */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 217 | /* any record with filter mode EXCLUDE, causes the interface mode to be EXCLUDE */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 218 | /* remove from the interface EXCLUDE filter any source not in the socket EXCLUDE filter */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 219 | struct pico_tree_node *index = NULL, *_tmp = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 220 | union pico_address *source = NULL; |
tass | 152:a3d286bf94e5 | 221 | if(!pico_tree_empty(&MCASTFilter)) { |
tass | 152:a3d286bf94e5 | 222 | pico_tree_foreach_safe(index, &MCASTFilter, _tmp) |
tass | 152:a3d286bf94e5 | 223 | { |
tass | 152:a3d286bf94e5 | 224 | source = pico_tree_findKey(&listen->MCASTSources, index->keyValue); |
tass | 152:a3d286bf94e5 | 225 | if (!source) |
tass | 152:a3d286bf94e5 | 226 | pico_tree_delete(&MCASTFilter, index->keyValue); |
tass | 152:a3d286bf94e5 | 227 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 228 | } |
tass | 152:a3d286bf94e5 | 229 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 230 | if(!pico_tree_empty(&MCASTFilter_ipv6)) { |
tass | 152:a3d286bf94e5 | 231 | pico_tree_foreach_safe(index, &MCASTFilter_ipv6, _tmp) |
tass | 152:a3d286bf94e5 | 232 | { |
tass | 152:a3d286bf94e5 | 233 | source = pico_tree_findKey(&listen->MCASTSources_ipv6, index->keyValue); |
tass | 152:a3d286bf94e5 | 234 | if (!source) |
tass | 152:a3d286bf94e5 | 235 | pico_tree_delete(&MCASTFilter_ipv6, index->keyValue); |
tass | 152:a3d286bf94e5 | 236 | } |
tass | 152:a3d286bf94e5 | 237 | } |
tass | 152:a3d286bf94e5 | 238 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 239 | return PICO_IP_MULTICAST_EXCLUDE; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 240 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 241 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 242 | static uint8_t pico_mcast_filter_excl_incl(struct pico_mcast_listen *listen) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 243 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 244 | /* filter = EXCLUDE - INCLUDE */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 245 | /* any record with filter mode EXCLUDE, causes the interface mode to be EXCLUDE */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 246 | /* remove from the interface EXCLUDE filter any source in the socket INCLUDE filter */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 247 | struct pico_tree_node *index = NULL, *_tmp = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 248 | union pico_address *source = NULL; |
tass | 152:a3d286bf94e5 | 249 | if(!pico_tree_empty(&listen->MCASTSources)) { |
tass | 152:a3d286bf94e5 | 250 | pico_tree_foreach_safe(index, &listen->MCASTSources, _tmp) |
tass | 152:a3d286bf94e5 | 251 | { |
tass | 152:a3d286bf94e5 | 252 | source = pico_tree_findKey(&MCASTFilter, index->keyValue); |
tass | 152:a3d286bf94e5 | 253 | if (source) |
tass | 152:a3d286bf94e5 | 254 | pico_tree_delete(&MCASTFilter, source); |
tass | 152:a3d286bf94e5 | 255 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 256 | } |
tass | 152:a3d286bf94e5 | 257 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 258 | if(!pico_tree_empty(&listen->MCASTSources_ipv6)) { |
tass | 152:a3d286bf94e5 | 259 | pico_tree_foreach_safe(index, &listen->MCASTSources_ipv6, _tmp) |
tass | 152:a3d286bf94e5 | 260 | { |
tass | 152:a3d286bf94e5 | 261 | source = pico_tree_findKey(&MCASTFilter_ipv6, index->keyValue); |
tass | 152:a3d286bf94e5 | 262 | if (source) |
tass | 152:a3d286bf94e5 | 263 | pico_tree_delete(&MCASTFilter_ipv6, source); |
tass | 152:a3d286bf94e5 | 264 | } |
tass | 152:a3d286bf94e5 | 265 | } |
tass | 152:a3d286bf94e5 | 266 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 267 | return PICO_IP_MULTICAST_EXCLUDE; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 268 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 269 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 270 | static uint8_t pico_mcast_filter_incl_excl(struct pico_mcast_listen *listen) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 271 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 272 | /* filter = EXCLUDE - INCLUDE */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 273 | /* delete from the interface INCLUDE filter any source NOT in the socket EXCLUDE filter */ |
tass | 152:a3d286bf94e5 | 274 | struct pico_tree_node *index = NULL, *_tmp = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 275 | union pico_address *source = NULL; |
tass | 152:a3d286bf94e5 | 276 | if(!pico_tree_empty(&listen->MCASTSources)) { |
tass | 152:a3d286bf94e5 | 277 | pico_tree_foreach_safe(index, &MCASTFilter, _tmp) |
tass | 152:a3d286bf94e5 | 278 | { |
tass | 152:a3d286bf94e5 | 279 | source = pico_tree_findKey(&listen->MCASTSources, index->keyValue); |
tass | 152:a3d286bf94e5 | 280 | if (!source) |
tass | 152:a3d286bf94e5 | 281 | pico_tree_delete(&MCASTFilter, index->keyValue); |
tass | 152:a3d286bf94e5 | 282 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 283 | } |
tass | 152:a3d286bf94e5 | 284 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 285 | if(!pico_tree_empty(&listen->MCASTSources_ipv6)) { |
tass | 152:a3d286bf94e5 | 286 | pico_tree_foreach_safe(index, &MCASTFilter_ipv6, _tmp) |
tass | 152:a3d286bf94e5 | 287 | { |
tass | 152:a3d286bf94e5 | 288 | source = pico_tree_findKey(&listen->MCASTSources_ipv6, index->keyValue); |
tass | 152:a3d286bf94e5 | 289 | if (!source) |
tass | 152:a3d286bf94e5 | 290 | pico_tree_delete(&MCASTFilter_ipv6, index->keyValue); |
tass | 152:a3d286bf94e5 | 291 | } |
tass | 152:a3d286bf94e5 | 292 | } |
tass | 152:a3d286bf94e5 | 293 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 294 | /* any record with filter mode EXCLUDE, causes the interface mode to be EXCLUDE */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 295 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 296 | /* add to the interface EXCLUDE filter any socket source NOT in the former interface INCLUDE filter */ |
tass | 152:a3d286bf94e5 | 297 | if(!pico_tree_empty(&listen->MCASTSources)) { |
tass | 152:a3d286bf94e5 | 298 | pico_tree_foreach_safe(index, &listen->MCASTSources, _tmp) |
tass | 152:a3d286bf94e5 | 299 | { |
tass | 152:a3d286bf94e5 | 300 | source = pico_tree_insert(&MCASTFilter, index->keyValue); |
tass | 152:a3d286bf94e5 | 301 | if (source) |
tass | 152:a3d286bf94e5 | 302 | pico_tree_delete(&MCASTFilter, source); |
tass | 152:a3d286bf94e5 | 303 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 304 | } |
tass | 152:a3d286bf94e5 | 305 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 306 | if(!pico_tree_empty(&listen->MCASTSources_ipv6)) { |
tass | 152:a3d286bf94e5 | 307 | pico_tree_foreach_safe(index, &listen->MCASTSources_ipv6, _tmp) |
tass | 152:a3d286bf94e5 | 308 | { |
tass | 152:a3d286bf94e5 | 309 | source = pico_tree_insert(&MCASTFilter_ipv6, index->keyValue); |
tass | 152:a3d286bf94e5 | 310 | if (source) |
tass | 152:a3d286bf94e5 | 311 | pico_tree_delete(&MCASTFilter_ipv6, source); |
tass | 152:a3d286bf94e5 | 312 | } |
tass | 152:a3d286bf94e5 | 313 | } |
tass | 152:a3d286bf94e5 | 314 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 315 | return PICO_IP_MULTICAST_EXCLUDE; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 316 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 317 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 318 | static uint8_t pico_mcast_filter_incl_incl(struct pico_mcast_listen *listen) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 319 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 320 | /* filter = summation of INCLUDEs */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 321 | /* mode stays INCLUDE, add all sources to filter */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 322 | struct pico_tree_node *index = NULL, *_tmp = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 323 | union pico_address *source = NULL; |
tass | 152:a3d286bf94e5 | 324 | |
tass | 152:a3d286bf94e5 | 325 | if( !pico_tree_empty(&listen->MCASTSources)) { |
tass | 152:a3d286bf94e5 | 326 | pico_tree_foreach_safe(index, &listen->MCASTSources, _tmp) |
tass | 152:a3d286bf94e5 | 327 | { |
tass | 152:a3d286bf94e5 | 328 | source = index->keyValue; |
tass | 152:a3d286bf94e5 | 329 | pico_tree_insert(&MCASTFilter, source); |
tass | 152:a3d286bf94e5 | 330 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 331 | } |
tass | 152:a3d286bf94e5 | 332 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 333 | if( !pico_tree_empty(&listen->MCASTSources_ipv6)) { |
tass | 152:a3d286bf94e5 | 334 | pico_tree_foreach_safe(index, &listen->MCASTSources_ipv6, _tmp) |
tass | 152:a3d286bf94e5 | 335 | { |
tass | 152:a3d286bf94e5 | 336 | source = index->keyValue; |
tass | 152:a3d286bf94e5 | 337 | pico_tree_insert(&MCASTFilter_ipv6, source); |
tass | 152:a3d286bf94e5 | 338 | } |
tass | 152:a3d286bf94e5 | 339 | } |
tass | 152:a3d286bf94e5 | 340 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 341 | return PICO_IP_MULTICAST_INCLUDE; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 342 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 343 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 344 | struct pico_mcast_filter_aggregation |
tass picotcp@tass.be | 149:5f4cb161cec3 | 345 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 346 | uint8_t (*call)(struct pico_mcast_listen *); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 347 | }; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 348 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 349 | static const struct pico_mcast_filter_aggregation mcast_filter_aggr_call[2][2] = |
tass picotcp@tass.be | 149:5f4cb161cec3 | 350 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 351 | { |
tass | 152:a3d286bf94e5 | 352 | /* EXCL + EXCL */ {.call = pico_mcast_filter_excl_excl}, |
tass | 152:a3d286bf94e5 | 353 | /* EXCL + INCL */ {.call = pico_mcast_filter_excl_incl} |
tass picotcp@tass.be | 149:5f4cb161cec3 | 354 | }, |
tass picotcp@tass.be | 149:5f4cb161cec3 | 355 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 356 | { |
tass | 152:a3d286bf94e5 | 357 | /* INCL + EXCL */ {.call = pico_mcast_filter_incl_excl}, |
tass | 152:a3d286bf94e5 | 358 | /* INCL + INCL */ {.call = pico_mcast_filter_incl_incl} |
tass picotcp@tass.be | 149:5f4cb161cec3 | 359 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 360 | }; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 361 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 362 | static int mcast_aggr_validate(uint8_t fm, struct pico_mcast_listen *l) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 363 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 364 | if (!l) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 365 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 366 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 367 | if (fm > 1) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 368 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 369 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 370 | if (l->filter_mode > 1) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 371 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 372 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 373 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 374 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 375 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 376 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 377 | /* MCASTFilter will be empty if no socket is listening on mcast_group on mcast_link anymore */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 378 | static int pico_socket_aggregate_mcastfilters(union pico_address *mcast_link, union pico_address *mcast_group) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 379 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 380 | uint8_t filter_mode = PICO_IP_MULTICAST_INCLUDE; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 381 | struct pico_mcast_listen *listen = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 382 | struct pico_socket *mcast_sock = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 383 | struct pico_tree_node *index = NULL, *_tmp = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 384 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 385 | /* cleanup old filter */ |
tass | 152:a3d286bf94e5 | 386 | if(!pico_tree_empty(&MCASTFilter)) { |
tass | 152:a3d286bf94e5 | 387 | pico_tree_foreach_safe(index, &MCASTFilter, _tmp) |
tass | 152:a3d286bf94e5 | 388 | { |
tass | 152:a3d286bf94e5 | 389 | pico_tree_delete(&MCASTFilter, index->keyValue); |
tass | 152:a3d286bf94e5 | 390 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 391 | } |
tass | 152:a3d286bf94e5 | 392 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 393 | if(!pico_tree_empty(&MCASTFilter_ipv6)) { |
tass | 152:a3d286bf94e5 | 394 | pico_tree_foreach_safe(index, &MCASTFilter_ipv6, _tmp) |
tass | 152:a3d286bf94e5 | 395 | { |
tass | 152:a3d286bf94e5 | 396 | pico_tree_delete(&MCASTFilter_ipv6, index->keyValue); |
tass | 152:a3d286bf94e5 | 397 | } |
tass | 152:a3d286bf94e5 | 398 | } |
tass | 152:a3d286bf94e5 | 399 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 400 | /* construct new filter */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 401 | pico_tree_foreach_safe(index, &MCASTSockets, _tmp) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 402 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 403 | mcast_sock = index->keyValue; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 404 | listen = listen_find(mcast_sock, mcast_link, mcast_group); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 405 | if (listen) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 406 | if (mcast_aggr_validate(filter_mode, listen) < 0) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 407 | pico_err = PICO_ERR_EINVAL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 408 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 409 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 410 | if (mcast_filter_aggr_call[filter_mode][listen->filter_mode].call) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 411 | filter_mode = mcast_filter_aggr_call[filter_mode][listen->filter_mode].call(listen); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 412 | if (filter_mode > 1) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 413 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 414 | } |
tass | 152:a3d286bf94e5 | 415 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 416 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 417 | return filter_mode; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 418 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 419 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 420 | static int pico_socket_mcast_filter_include(struct pico_mcast_listen *listen, union pico_address *src) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 421 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 422 | struct pico_tree_node *index = NULL; |
tass | 152:a3d286bf94e5 | 423 | #ifdef PICO_DEBUG_MCAST |
tass | 152:a3d286bf94e5 | 424 | char tmp_string[PICO_IPV6_STRING]; |
tass | 152:a3d286bf94e5 | 425 | #endif |
tass | 152:a3d286bf94e5 | 426 | if(!pico_tree_empty(&listen->MCASTSources)) { |
tass | 152:a3d286bf94e5 | 427 | pico_tree_foreach(index, &listen->MCASTSources) |
tass | 152:a3d286bf94e5 | 428 | { |
tass | 152:a3d286bf94e5 | 429 | if (src->ip4.addr == ((union pico_address *)index->keyValue)->ip4.addr) { |
tass | 152:a3d286bf94e5 | 430 | so_mcast_dbg("MCAST: IP %08X in included socket source list\n", src->ip4.addr); |
tass | 152:a3d286bf94e5 | 431 | return 0; |
tass | 152:a3d286bf94e5 | 432 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 433 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 434 | } |
tass | 152:a3d286bf94e5 | 435 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 436 | if(!pico_tree_empty(&listen->MCASTSources_ipv6)) { |
tass | 152:a3d286bf94e5 | 437 | pico_tree_foreach(index, &listen->MCASTSources_ipv6) |
tass | 152:a3d286bf94e5 | 438 | { |
tass | 152:a3d286bf94e5 | 439 | if (memcmp(&src->ip6 , &((union pico_address *)index->keyValue)->ip6, sizeof(struct pico_ip6))) { |
tass | 152:a3d286bf94e5 | 440 | #ifdef PICO_DEBUG_MCAST |
tass | 152:a3d286bf94e5 | 441 | pico_ipv6_to_string(tmp_string, src->ip6.addr); |
tass | 152:a3d286bf94e5 | 442 | so_mcast_dbg("MCAST: IP %s in included socket source list\n", tmp_string); |
tass | 152:a3d286bf94e5 | 443 | #endif |
tass | 152:a3d286bf94e5 | 444 | return 0; |
tass | 152:a3d286bf94e5 | 445 | } |
tass | 152:a3d286bf94e5 | 446 | } |
tass | 152:a3d286bf94e5 | 447 | } |
tass | 152:a3d286bf94e5 | 448 | #endif |
tass | 152:a3d286bf94e5 | 449 | /* XXX IPV6 ADDRESS */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 450 | so_mcast_dbg("MCAST: IP %08X NOT in included socket source list\n", src->ip4.addr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 451 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 452 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 453 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 454 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 455 | static int pico_socket_mcast_filter_exclude(struct pico_mcast_listen *listen, union pico_address *src) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 456 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 457 | struct pico_tree_node *index = NULL; |
tass | 152:a3d286bf94e5 | 458 | #ifdef PICO_DEBUG_MCAST |
tass | 152:a3d286bf94e5 | 459 | char tmp_string[PICO_IPV6_STRING]; |
tass | 152:a3d286bf94e5 | 460 | #endif |
tass | 152:a3d286bf94e5 | 461 | if(!pico_tree_empty(&listen->MCASTSources)) { |
tass | 152:a3d286bf94e5 | 462 | pico_tree_foreach(index, &listen->MCASTSources) |
tass | 152:a3d286bf94e5 | 463 | { |
tass | 152:a3d286bf94e5 | 464 | if (src->ip4.addr == ((union pico_address *)index->keyValue)->ip4.addr) { |
tass | 152:a3d286bf94e5 | 465 | so_mcast_dbg("MCAST: IP %08X in excluded socket source list\n", src->ip4.addr); |
tass | 152:a3d286bf94e5 | 466 | return -1; |
tass | 152:a3d286bf94e5 | 467 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 468 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 469 | } |
tass | 152:a3d286bf94e5 | 470 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 471 | if(!pico_tree_empty(&listen->MCASTSources_ipv6)) { |
tass | 152:a3d286bf94e5 | 472 | pico_tree_foreach(index, &listen->MCASTSources_ipv6) |
tass | 152:a3d286bf94e5 | 473 | { |
tass | 152:a3d286bf94e5 | 474 | if (memcmp(&src->ip6 , &((union pico_address *)index->keyValue)->ip6, sizeof(struct pico_ip6))) { |
tass | 152:a3d286bf94e5 | 475 | #ifdef PICO_DEBUG_MCAST |
tass | 152:a3d286bf94e5 | 476 | pico_ipv6_to_string(tmp_string, src->ip6.addr); |
tass | 152:a3d286bf94e5 | 477 | so_mcast_dbg("MCAST: IP %s in excluded socket source list\n", tmp_string); |
tass | 152:a3d286bf94e5 | 478 | #endif |
tass | 152:a3d286bf94e5 | 479 | return 0; |
tass | 152:a3d286bf94e5 | 480 | } |
tass | 152:a3d286bf94e5 | 481 | } |
tass | 152:a3d286bf94e5 | 482 | } |
tass | 152:a3d286bf94e5 | 483 | #endif |
tass | 152:a3d286bf94e5 | 484 | /* XXX IPV6 ADDRESS */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 485 | so_mcast_dbg("MCAST: IP %08X NOT in excluded socket source list\n", src->ip4.addr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 486 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 487 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 488 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 489 | static int pico_socket_mcast_source_filtering(struct pico_mcast_listen *listen, union pico_address *src) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 490 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 491 | /* perform source filtering */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 492 | if (listen->filter_mode == PICO_IP_MULTICAST_INCLUDE) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 493 | return pico_socket_mcast_filter_include(listen, src); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 494 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 495 | if (listen->filter_mode == PICO_IP_MULTICAST_EXCLUDE) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 496 | return pico_socket_mcast_filter_exclude(listen, src); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 497 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 498 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 499 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 500 | |
tass | 152:a3d286bf94e5 | 501 | static void *pico_socket_mcast_filter_link_get(struct pico_socket *s) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 502 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 503 | /* check if no multicast enabled on socket */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 504 | if (!s->MCASTListen) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 505 | return NULL; |
tass | 152:a3d286bf94e5 | 506 | if( IS_SOCK_IPV4(s) ) { |
tass | 152:a3d286bf94e5 | 507 | if (!s->local_addr.ip4.addr) |
tass | 152:a3d286bf94e5 | 508 | return pico_ipv4_get_default_mcastlink(); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 509 | |
tass | 152:a3d286bf94e5 | 510 | return pico_ipv4_link_get(&s->local_addr.ip4); |
tass | 152:a3d286bf94e5 | 511 | } |
tass | 152:a3d286bf94e5 | 512 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 513 | else if( IS_SOCK_IPV6(s)) { |
tass | 152:a3d286bf94e5 | 514 | if (pico_ipv6_is_null_address(&s->local_addr.ip6)) |
tass | 152:a3d286bf94e5 | 515 | return pico_ipv6_get_default_mcastlink(); |
tass | 152:a3d286bf94e5 | 516 | |
tass | 152:a3d286bf94e5 | 517 | return pico_ipv6_link_get(&s->local_addr.ip6); |
tass | 152:a3d286bf94e5 | 518 | } |
tass | 152:a3d286bf94e5 | 519 | #endif |
tass | 152:a3d286bf94e5 | 520 | return NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 521 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 522 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 523 | int pico_socket_mcast_filter(struct pico_socket *s, union pico_address *mcast_group, union pico_address *src) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 524 | { |
tass | 152:a3d286bf94e5 | 525 | void *mcast_link = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 526 | struct pico_mcast_listen *listen = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 527 | mcast_link = pico_socket_mcast_filter_link_get(s); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 528 | if (!mcast_link) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 529 | return -1; |
tass | 152:a3d286bf94e5 | 530 | if(IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 531 | listen = listen_find(s,(union pico_address *) &((struct pico_ipv4_link*)(mcast_link))->address, mcast_group); |
tass | 152:a3d286bf94e5 | 532 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 533 | else if(IS_SOCK_IPV6(s)) |
tass | 152:a3d286bf94e5 | 534 | listen = listen_find(s, (union pico_address *)&((struct pico_ipv6_link*)(mcast_link))->address, mcast_group); |
tass | 152:a3d286bf94e5 | 535 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 536 | if (!listen) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 537 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 538 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 539 | return pico_socket_mcast_source_filtering(listen, src); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 540 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 541 | |
tass | 152:a3d286bf94e5 | 542 | |
tass | 152:a3d286bf94e5 | 543 | static struct pico_ipv4_link *get_mcast_link(union pico_address *a) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 544 | if (!a->ip4.addr) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 545 | return pico_ipv4_get_default_mcastlink(); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 546 | return pico_ipv4_link_get(&a->ip4); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 547 | } |
tass | 152:a3d286bf94e5 | 548 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 549 | static struct pico_ipv6_link *get_mcast_link_ipv6(union pico_address *a) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 550 | |
tass | 152:a3d286bf94e5 | 551 | if (pico_ipv6_is_null_address(&a->ip6)) { |
tass | 152:a3d286bf94e5 | 552 | return pico_ipv6_get_default_mcastlink(); |
tass | 152:a3d286bf94e5 | 553 | } |
tass | 152:a3d286bf94e5 | 554 | return pico_ipv6_link_get(&a->ip6); |
tass | 152:a3d286bf94e5 | 555 | } |
tass | 152:a3d286bf94e5 | 556 | #endif |
tass | 152:a3d286bf94e5 | 557 | |
tass | 154:6c0e92a80c4a | 558 | static int pico_socket_setoption_pre_validation(struct pico_ip_mreq *mreq) |
tass | 152:a3d286bf94e5 | 559 | { |
tass | 152:a3d286bf94e5 | 560 | if (!mreq) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 561 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 562 | |
tass | 152:a3d286bf94e5 | 563 | if (!mreq->mcast_group_addr.ip4.addr) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 564 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 565 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 566 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 567 | } |
tass | 152:a3d286bf94e5 | 568 | #ifdef PICO_SUPPORT_IPV6 |
tass | 154:6c0e92a80c4a | 569 | static int pico_socket_setoption_pre_validation_ipv6(struct pico_ip_mreq *mreq) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 570 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 571 | if (!mreq) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 572 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 573 | |
tass | 152:a3d286bf94e5 | 574 | if (pico_ipv6_is_null_address((struct pico_ip6*)&mreq->mcast_group_addr)) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 575 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 576 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 577 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 578 | } |
tass | 152:a3d286bf94e5 | 579 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 580 | |
tass | 154:6c0e92a80c4a | 581 | static struct pico_ipv4_link *pico_socket_setoption_validate_mreq(struct pico_ip_mreq *mreq) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 582 | { |
tass | 152:a3d286bf94e5 | 583 | if (pico_socket_setoption_pre_validation(mreq) < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 584 | return NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 585 | |
tass | 152:a3d286bf94e5 | 586 | if (pico_ipv4_is_unicast(mreq->mcast_group_addr.ip4.addr)) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 587 | return NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 588 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 589 | return get_mcast_link((union pico_address *)&mreq->mcast_link_addr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 590 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 591 | |
tass | 152:a3d286bf94e5 | 592 | #ifdef PICO_SUPPORT_IPV6 |
tass | 154:6c0e92a80c4a | 593 | static struct pico_ipv6_link *pico_socket_setoption_validate_mreq_ipv6(struct pico_ip_mreq *mreq) |
tass | 152:a3d286bf94e5 | 594 | { |
tass | 152:a3d286bf94e5 | 595 | if (pico_socket_setoption_pre_validation_ipv6(mreq) < 0) |
tass | 152:a3d286bf94e5 | 596 | return NULL; |
tass | 152:a3d286bf94e5 | 597 | |
tass | 152:a3d286bf94e5 | 598 | if (pico_ipv6_is_unicast((struct pico_ip6 *)&mreq->mcast_group_addr)) |
tass | 152:a3d286bf94e5 | 599 | return NULL; |
tass | 152:a3d286bf94e5 | 600 | return get_mcast_link_ipv6((union pico_address *)&mreq->mcast_link_addr); |
tass | 152:a3d286bf94e5 | 601 | } |
tass | 152:a3d286bf94e5 | 602 | #endif |
tass | 152:a3d286bf94e5 | 603 | |
tass | 154:6c0e92a80c4a | 604 | static int pico_socket_setoption_pre_validation_s(struct pico_ip_mreq_source *mreq) |
tass | 152:a3d286bf94e5 | 605 | { |
tass | 152:a3d286bf94e5 | 606 | if (!mreq) |
tass | 152:a3d286bf94e5 | 607 | return -1; |
tass | 152:a3d286bf94e5 | 608 | |
tass | 152:a3d286bf94e5 | 609 | if (!mreq->mcast_group_addr.ip4.addr) |
tass | 152:a3d286bf94e5 | 610 | return -1; |
tass | 152:a3d286bf94e5 | 611 | |
tass | 152:a3d286bf94e5 | 612 | return 0; |
tass | 152:a3d286bf94e5 | 613 | } |
tass | 152:a3d286bf94e5 | 614 | #ifdef PICO_SUPPORT_IPV6 |
tass | 154:6c0e92a80c4a | 615 | static int pico_socket_setoption_pre_validation_s_ipv6(struct pico_ip_mreq_source *mreq) |
tass | 152:a3d286bf94e5 | 616 | { |
tass | 152:a3d286bf94e5 | 617 | if (!mreq) |
tass | 152:a3d286bf94e5 | 618 | return -1; |
tass | 152:a3d286bf94e5 | 619 | |
tass | 152:a3d286bf94e5 | 620 | if (pico_ipv6_is_null_address((struct pico_ip6 *)&mreq->mcast_group_addr)) |
tass | 152:a3d286bf94e5 | 621 | return -1; |
tass | 152:a3d286bf94e5 | 622 | |
tass | 152:a3d286bf94e5 | 623 | return 0; |
tass | 152:a3d286bf94e5 | 624 | } |
tass | 152:a3d286bf94e5 | 625 | #endif |
tass | 152:a3d286bf94e5 | 626 | |
tass | 154:6c0e92a80c4a | 627 | static struct pico_ipv4_link *pico_socket_setoption_validate_s_mreq(struct pico_ip_mreq_source *mreq) |
tass | 152:a3d286bf94e5 | 628 | { |
tass | 152:a3d286bf94e5 | 629 | if (pico_socket_setoption_pre_validation_s(mreq) < 0) |
tass | 152:a3d286bf94e5 | 630 | return NULL; |
tass | 152:a3d286bf94e5 | 631 | |
tass | 152:a3d286bf94e5 | 632 | if (pico_ipv4_is_unicast(mreq->mcast_group_addr.ip4.addr)) |
tass | 152:a3d286bf94e5 | 633 | return NULL; |
tass | 152:a3d286bf94e5 | 634 | |
tass | 152:a3d286bf94e5 | 635 | if (!pico_ipv4_is_unicast(mreq->mcast_source_addr.ip4.addr)) |
tass | 152:a3d286bf94e5 | 636 | return NULL; |
tass | 152:a3d286bf94e5 | 637 | |
tass | 152:a3d286bf94e5 | 638 | return get_mcast_link((union pico_address *)&mreq->mcast_link_addr); |
tass | 152:a3d286bf94e5 | 639 | } |
tass | 152:a3d286bf94e5 | 640 | #ifdef PICO_SUPPORT_IPV6 |
tass | 154:6c0e92a80c4a | 641 | static struct pico_ipv6_link *pico_socket_setoption_validate_s_mreq_ipv6(struct pico_ip_mreq_source *mreq) |
tass | 152:a3d286bf94e5 | 642 | { |
tass | 152:a3d286bf94e5 | 643 | if (pico_socket_setoption_pre_validation_s_ipv6(mreq) < 0) { |
tass | 152:a3d286bf94e5 | 644 | return NULL; |
tass | 152:a3d286bf94e5 | 645 | } |
tass | 152:a3d286bf94e5 | 646 | if (pico_ipv6_is_unicast((struct pico_ip6 *)&mreq->mcast_group_addr)){ |
tass | 152:a3d286bf94e5 | 647 | return NULL; |
tass | 152:a3d286bf94e5 | 648 | } |
tass | 152:a3d286bf94e5 | 649 | if (!pico_ipv6_is_unicast((struct pico_ip6 *)&mreq->mcast_source_addr)){ |
tass | 152:a3d286bf94e5 | 650 | return NULL; |
tass | 152:a3d286bf94e5 | 651 | } |
tass | 152:a3d286bf94e5 | 652 | |
tass | 152:a3d286bf94e5 | 653 | return get_mcast_link_ipv6(&mreq->mcast_link_addr); |
tass | 152:a3d286bf94e5 | 654 | } |
tass | 152:a3d286bf94e5 | 655 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 656 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 657 | static struct pico_ipv4_link *setop_multicast_link_search(void *value, int bysource) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 658 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 659 | |
tass | 154:6c0e92a80c4a | 660 | struct pico_ip_mreq *mreq = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 661 | struct pico_ipv4_link *mcast_link = NULL; |
tass | 154:6c0e92a80c4a | 662 | struct pico_ip_mreq_source *mreq_src = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 663 | if (!bysource) { |
tass | 154:6c0e92a80c4a | 664 | mreq = (struct pico_ip_mreq *)value; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 665 | mcast_link = pico_socket_setoption_validate_mreq(mreq); |
tass | 152:a3d286bf94e5 | 666 | if (!mcast_link) |
tass | 152:a3d286bf94e5 | 667 | return NULL; |
tass | 152:a3d286bf94e5 | 668 | if (!mreq->mcast_link_addr.ip4.addr) |
tass | 152:a3d286bf94e5 | 669 | mreq->mcast_link_addr.ip4.addr = mcast_link->address.addr; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 670 | } else { |
tass | 154:6c0e92a80c4a | 671 | mreq_src = (struct pico_ip_mreq_source *)value; |
tass | 152:a3d286bf94e5 | 672 | if (!mreq_src) { |
tass | 152:a3d286bf94e5 | 673 | return NULL; |
tass | 152:a3d286bf94e5 | 674 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 675 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 676 | mcast_link = pico_socket_setoption_validate_s_mreq(mreq_src); |
tass | 152:a3d286bf94e5 | 677 | if (!mcast_link) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 678 | return NULL; |
tass | 152:a3d286bf94e5 | 679 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 680 | |
tass | 152:a3d286bf94e5 | 681 | if (!mreq_src->mcast_link_addr.ip4.addr) |
tass | 152:a3d286bf94e5 | 682 | mreq_src->mcast_link_addr.ip4 = mcast_link->address; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 683 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 684 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 685 | return mcast_link; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 686 | } |
tass | 152:a3d286bf94e5 | 687 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 688 | static struct pico_ipv6_link *setop_multicast_link_search_ipv6(void *value, int bysource) |
tass | 152:a3d286bf94e5 | 689 | { |
tass | 154:6c0e92a80c4a | 690 | struct pico_ip_mreq *mreq = NULL; |
tass | 152:a3d286bf94e5 | 691 | struct pico_ipv6_link *mcast_link = NULL; |
tass | 154:6c0e92a80c4a | 692 | struct pico_ip_mreq_source *mreq_src = NULL; |
tass | 152:a3d286bf94e5 | 693 | if (!bysource) { |
tass | 154:6c0e92a80c4a | 694 | mreq = (struct pico_ip_mreq *)value; |
tass | 152:a3d286bf94e5 | 695 | mcast_link = pico_socket_setoption_validate_mreq_ipv6(mreq); |
tass | 152:a3d286bf94e5 | 696 | if (!mcast_link) { |
tass | 152:a3d286bf94e5 | 697 | return NULL; |
tass | 152:a3d286bf94e5 | 698 | } |
tass | 152:a3d286bf94e5 | 699 | if (pico_ipv6_is_null_address(&mreq->mcast_link_addr.ip6)) |
tass | 152:a3d286bf94e5 | 700 | mreq->mcast_link_addr.ip6 = mcast_link->address; |
tass | 152:a3d286bf94e5 | 701 | } else { |
tass | 154:6c0e92a80c4a | 702 | mreq_src = (struct pico_ip_mreq_source *)value; |
tass | 152:a3d286bf94e5 | 703 | if (!mreq_src) { |
tass | 152:a3d286bf94e5 | 704 | return NULL; |
tass | 152:a3d286bf94e5 | 705 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 706 | |
tass | 152:a3d286bf94e5 | 707 | mcast_link = pico_socket_setoption_validate_s_mreq_ipv6(mreq_src); |
tass | 152:a3d286bf94e5 | 708 | if (!mcast_link) { |
tass | 152:a3d286bf94e5 | 709 | return NULL; |
tass | 152:a3d286bf94e5 | 710 | } |
tass | 152:a3d286bf94e5 | 711 | if (pico_ipv6_is_null_address(&mreq_src->mcast_link_addr.ip6)) |
tass | 152:a3d286bf94e5 | 712 | mreq_src->mcast_link_addr.ip6 = mcast_link->address; |
tass | 152:a3d286bf94e5 | 713 | } |
tass | 152:a3d286bf94e5 | 714 | return mcast_link; |
tass | 152:a3d286bf94e5 | 715 | } |
tass | 152:a3d286bf94e5 | 716 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 717 | static int setop_verify_listen_tree(struct pico_socket *s, int alloc) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 718 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 719 | if(!alloc) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 720 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 721 | |
tass | 152:a3d286bf94e5 | 722 | if( IS_SOCK_IPV4(s) ) { |
tass | 152:a3d286bf94e5 | 723 | |
tass | 152:a3d286bf94e5 | 724 | s->MCASTListen = PICO_ZALLOC(sizeof(struct pico_tree)); |
tass | 152:a3d286bf94e5 | 725 | if (!s->MCASTListen) { |
tass | 152:a3d286bf94e5 | 726 | pico_err = PICO_ERR_ENOMEM; |
tass | 152:a3d286bf94e5 | 727 | return -1; |
tass | 152:a3d286bf94e5 | 728 | } |
tass | 152:a3d286bf94e5 | 729 | |
tass | 152:a3d286bf94e5 | 730 | s->MCASTListen->root = &LEAF; |
tass | 152:a3d286bf94e5 | 731 | s->MCASTListen->compare = mcast_listen_cmp; |
tass | 152:a3d286bf94e5 | 732 | return 0; |
tass | 152:a3d286bf94e5 | 733 | } |
tass | 152:a3d286bf94e5 | 734 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 735 | else if( IS_SOCK_IPV6(s)){ |
tass | 152:a3d286bf94e5 | 736 | s->MCASTListen_ipv6 = PICO_ZALLOC(sizeof(struct pico_tree)); |
tass | 152:a3d286bf94e5 | 737 | if (!s->MCASTListen_ipv6) { |
tass | 152:a3d286bf94e5 | 738 | pico_err = PICO_ERR_ENOMEM; |
tass | 152:a3d286bf94e5 | 739 | return -1; |
tass | 152:a3d286bf94e5 | 740 | } |
tass | 152:a3d286bf94e5 | 741 | |
tass | 152:a3d286bf94e5 | 742 | s->MCASTListen_ipv6->root = &LEAF; |
tass | 152:a3d286bf94e5 | 743 | s->MCASTListen_ipv6->compare = mcast_listen_cmp_ipv6; |
tass | 152:a3d286bf94e5 | 744 | return 0; |
tass | 152:a3d286bf94e5 | 745 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 746 | } |
tass | 152:a3d286bf94e5 | 747 | #endif |
tass | 152:a3d286bf94e5 | 748 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 749 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 750 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 751 | |
tass | 152:a3d286bf94e5 | 752 | static void *setopt_multicast_check(struct pico_socket *s, void *value, int alloc, int bysource) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 753 | { |
tass | 152:a3d286bf94e5 | 754 | void *mcast_link = NULL; |
tass | 152:a3d286bf94e5 | 755 | struct pico_tree *listen_tree = mcast_get_listen_tree(s); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 756 | if (!value) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 757 | pico_err = PICO_ERR_EINVAL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 758 | return NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 759 | } |
tass | 152:a3d286bf94e5 | 760 | if(IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 761 | mcast_link = setop_multicast_link_search(value, bysource); |
tass | 152:a3d286bf94e5 | 762 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 763 | else if(IS_SOCK_IPV6(s)) |
tass | 152:a3d286bf94e5 | 764 | mcast_link = setop_multicast_link_search_ipv6(value, bysource); |
tass | 152:a3d286bf94e5 | 765 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 766 | if (!mcast_link) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 767 | pico_err = PICO_ERR_EINVAL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 768 | return NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 769 | } |
tass | 152:a3d286bf94e5 | 770 | if (!listen_tree) { /* No RBTree allocated yet */ |
tass | 152:a3d286bf94e5 | 771 | if (setop_verify_listen_tree(s, alloc) < 0) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 772 | return NULL; |
tass | 152:a3d286bf94e5 | 773 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 774 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 775 | return mcast_link; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 776 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 777 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 778 | void pico_multicast_delete(struct pico_socket *s) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 779 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 780 | int filter_mode; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 781 | struct pico_tree_node *index = NULL, *_tmp = NULL, *index2 = NULL, *_tmp2 = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 782 | struct pico_mcast_listen *listen = NULL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 783 | union pico_address *source = NULL; |
tass | 152:a3d286bf94e5 | 784 | struct pico_tree *tree, *listen_tree; |
tass | 152:a3d286bf94e5 | 785 | struct pico_mcast mcast; |
tass | 152:a3d286bf94e5 | 786 | listen_tree = mcast_get_listen_tree(s); |
tass | 152:a3d286bf94e5 | 787 | if(listen_tree) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 788 | pico_tree_delete(&MCASTSockets, s); |
tass | 152:a3d286bf94e5 | 789 | pico_tree_foreach_safe(index, listen_tree, _tmp) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 790 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 791 | listen = index->keyValue; |
tass | 152:a3d286bf94e5 | 792 | mcast.listen = listen; |
tass | 152:a3d286bf94e5 | 793 | tree = mcast_get_src_tree(s, &mcast); |
tass | 152:a3d286bf94e5 | 794 | pico_tree_foreach_safe(index2, tree, _tmp2) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 795 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 796 | source = index->keyValue; |
tass | 152:a3d286bf94e5 | 797 | pico_tree_delete(tree, source); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 798 | PICO_FREE(source); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 799 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 800 | filter_mode = pico_socket_aggregate_mcastfilters((union pico_address *)&listen->mcast_link, (union pico_address *)&listen->mcast_group); |
tass | 152:a3d286bf94e5 | 801 | if (filter_mode >= 0) { |
tass | 152:a3d286bf94e5 | 802 | if(IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 803 | pico_ipv4_mcast_leave(&listen->mcast_link.ip4, &listen->mcast_group.ip4, 1, (uint8_t)filter_mode, &MCASTFilter); |
tass | 152:a3d286bf94e5 | 804 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 805 | else if(IS_SOCK_IPV6(s)) |
tass | 152:a3d286bf94e5 | 806 | pico_ipv6_mcast_leave(&listen->mcast_link.ip6, &listen->mcast_group.ip6, 1, (uint8_t)filter_mode, &MCASTFilter_ipv6); |
tass | 152:a3d286bf94e5 | 807 | #endif |
tass | 152:a3d286bf94e5 | 808 | } |
tass | 152:a3d286bf94e5 | 809 | pico_tree_delete(listen_tree, listen); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 810 | PICO_FREE(listen); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 811 | } |
tass | 152:a3d286bf94e5 | 812 | PICO_FREE(listen_tree); |
tass | 152:a3d286bf94e5 | 813 | mcast_set_listen_tree_p_null(s); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 814 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 815 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 816 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 817 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 818 | int pico_getsockopt_mcast(struct pico_socket *s, int option, void *value) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 819 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 820 | switch(option) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 821 | case PICO_IP_MULTICAST_IF: |
tass picotcp@tass.be | 149:5f4cb161cec3 | 822 | pico_err = PICO_ERR_EOPNOTSUPP; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 823 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 824 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 825 | case PICO_IP_MULTICAST_TTL: |
tass picotcp@tass.be | 149:5f4cb161cec3 | 826 | if (s->proto->proto_number == PICO_PROTO_UDP) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 827 | pico_udp_get_mc_ttl(s, (uint8_t *) value); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 828 | } else { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 829 | *(uint8_t *)value = 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 830 | pico_err = PICO_ERR_EINVAL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 831 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 832 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 833 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 834 | break; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 835 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 836 | case PICO_IP_MULTICAST_LOOP: |
tass picotcp@tass.be | 149:5f4cb161cec3 | 837 | if (s->proto->proto_number == PICO_PROTO_UDP) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 838 | *(uint8_t *)value = (uint8_t)PICO_SOCKET_GETOPT(s, PICO_SOCKET_OPT_MULTICAST_LOOP); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 839 | } else { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 840 | *(uint8_t *)value = 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 841 | pico_err = PICO_ERR_EINVAL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 842 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 843 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 844 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 845 | break; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 846 | default: |
tass picotcp@tass.be | 149:5f4cb161cec3 | 847 | pico_err = PICO_ERR_EINVAL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 848 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 849 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 850 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 851 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 852 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 853 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 854 | static int mcast_so_loop(struct pico_socket *s, void *value) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 855 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 856 | uint8_t val = (*(uint8_t *)value); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 857 | if (val == 0u) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 858 | PICO_SOCKET_SETOPT_DIS(s, PICO_SOCKET_OPT_MULTICAST_LOOP); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 859 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 860 | } else if (val == 1u) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 861 | PICO_SOCKET_SETOPT_EN(s, PICO_SOCKET_OPT_MULTICAST_LOOP); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 862 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 863 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 864 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 865 | pico_err = PICO_ERR_EINVAL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 866 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 867 | } |
tass | 152:a3d286bf94e5 | 868 | static int mcast_get_param(struct pico_mcast *mcast, struct pico_socket *s, void *value,int alloc, int by_source) { |
tass | 152:a3d286bf94e5 | 869 | if(by_source) |
tass | 154:6c0e92a80c4a | 870 | mcast->mreq_s = (struct pico_ip_mreq_source *)value; |
tass | 152:a3d286bf94e5 | 871 | else |
tass | 154:6c0e92a80c4a | 872 | mcast->mreq = (struct pico_ip_mreq *)value; |
tass | 152:a3d286bf94e5 | 873 | mcast->mcast_link = setopt_multicast_check(s, value, alloc, by_source); |
tass | 152:a3d286bf94e5 | 874 | if (!mcast->mcast_link) |
tass | 152:a3d286bf94e5 | 875 | return -1; |
tass | 152:a3d286bf94e5 | 876 | mcast->address = pico_mcast_get_link_address(s, mcast->mcast_link); |
tass | 152:a3d286bf94e5 | 877 | if(by_source) |
tass | 152:a3d286bf94e5 | 878 | mcast->listen = listen_find(s, &(mcast->mreq_s)->mcast_link_addr, &mcast->mreq_s->mcast_group_addr); |
tass | 152:a3d286bf94e5 | 879 | else |
tass | 152:a3d286bf94e5 | 880 | mcast->listen = listen_find(s, &(mcast->mreq)->mcast_link_addr, &mcast->mreq->mcast_group_addr); |
tass | 152:a3d286bf94e5 | 881 | return 0; |
tass | 152:a3d286bf94e5 | 882 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 883 | static int mcast_so_addm(struct pico_socket *s, void *value) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 884 | { |
tass | 152:a3d286bf94e5 | 885 | int filter_mode = 0; |
tass | 152:a3d286bf94e5 | 886 | struct pico_mcast mcast; |
tass | 152:a3d286bf94e5 | 887 | struct pico_tree *tree, *listen_tree; |
tass | 152:a3d286bf94e5 | 888 | if(mcast_get_param(&mcast, s, value, 1,0) < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 889 | return -1; |
tass | 152:a3d286bf94e5 | 890 | |
tass | 152:a3d286bf94e5 | 891 | if (mcast.listen) { |
tass | 152:a3d286bf94e5 | 892 | if (mcast.listen->filter_mode != PICO_IP_MULTICAST_EXCLUDE) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 893 | so_mcast_dbg("pico_socket_setoption: ERROR any-source multicast (exclude) on source-specific multicast (include)\n"); |
tass | 152:a3d286bf94e5 | 894 | } else { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 895 | so_mcast_dbg("pico_socket_setoption: ERROR duplicate PICO_IP_ADD_MEMBERSHIP\n"); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 896 | } |
tass | 152:a3d286bf94e5 | 897 | pico_err = PICO_ERR_EINVAL; |
tass | 152:a3d286bf94e5 | 898 | return -1; |
tass | 152:a3d286bf94e5 | 899 | } |
tass | 152:a3d286bf94e5 | 900 | mcast.listen = PICO_ZALLOC(sizeof(struct pico_mcast_listen)); |
tass | 152:a3d286bf94e5 | 901 | if (!mcast.listen) { |
tass | 152:a3d286bf94e5 | 902 | pico_err = PICO_ERR_ENOMEM; |
tass | 152:a3d286bf94e5 | 903 | return -1; |
tass | 152:a3d286bf94e5 | 904 | } |
tass | 152:a3d286bf94e5 | 905 | mcast.listen->filter_mode = PICO_IP_MULTICAST_EXCLUDE; |
tass | 152:a3d286bf94e5 | 906 | mcast.listen->mcast_link = mcast.mreq->mcast_link_addr; |
tass | 152:a3d286bf94e5 | 907 | mcast.listen->mcast_group = mcast.mreq->mcast_group_addr; |
tass | 152:a3d286bf94e5 | 908 | mcast.listen->proto = s->net->proto_number; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 909 | |
tass | 152:a3d286bf94e5 | 910 | tree = mcast_get_src_tree(s, &mcast); |
tass | 152:a3d286bf94e5 | 911 | listen_tree = mcast_get_listen_tree(s); |
tass | 152:a3d286bf94e5 | 912 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 913 | if( IS_SOCK_IPV6(s)) |
tass | 152:a3d286bf94e5 | 914 | mcast.listen->proto = PICO_PROTO_IPV6; |
tass | 152:a3d286bf94e5 | 915 | #endif |
tass | 152:a3d286bf94e5 | 916 | tree->root = &LEAF; |
tass | 152:a3d286bf94e5 | 917 | pico_tree_insert(listen_tree, mcast.listen); |
tass | 152:a3d286bf94e5 | 918 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 919 | pico_tree_insert(&MCASTSockets, s); |
tass | 152:a3d286bf94e5 | 920 | filter_mode = pico_socket_aggregate_mcastfilters(mcast.address, &mcast.mreq->mcast_group_addr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 921 | if (filter_mode < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 922 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 923 | so_mcast_dbg("PICO_IP_ADD_MEMBERSHIP - success, added %p\n", s); |
tass | 152:a3d286bf94e5 | 924 | if(IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 925 | return pico_ipv4_mcast_join((struct pico_ip4*)&mcast.mreq->mcast_link_addr,(struct pico_ip4*) &mcast.mreq->mcast_group_addr, 1, (uint8_t)filter_mode, &MCASTFilter); |
tass | 152:a3d286bf94e5 | 926 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 927 | else if(IS_SOCK_IPV6(s)) { |
tass | 152:a3d286bf94e5 | 928 | return pico_ipv6_mcast_join((struct pico_ip6*)&mcast.mreq->mcast_link_addr,(struct pico_ip6*)&mcast.mreq->mcast_group_addr, 1, (uint8_t)filter_mode, &MCASTFilter_ipv6); |
tass | 152:a3d286bf94e5 | 929 | } |
tass | 152:a3d286bf94e5 | 930 | #endif |
tass | 152:a3d286bf94e5 | 931 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 932 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 933 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 934 | static int mcast_so_dropm(struct pico_socket *s, void *value) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 935 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 936 | int filter_mode = 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 937 | union pico_address *source = NULL; |
tass | 152:a3d286bf94e5 | 938 | struct pico_tree_node *_tmp,*index; |
tass | 152:a3d286bf94e5 | 939 | struct pico_mcast mcast; |
tass | 152:a3d286bf94e5 | 940 | struct pico_tree *listen_tree,*tree; |
tass | 152:a3d286bf94e5 | 941 | if(mcast_get_param(&mcast, s, value, 0,0) < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 942 | return -1; |
tass | 152:a3d286bf94e5 | 943 | if (!mcast.listen) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 944 | so_mcast_dbg("pico_socket_setoption: ERROR PICO_IP_DROP_MEMBERSHIP before PICO_IP_ADD_MEMBERSHIP/SOURCE_MEMBERSHIP\n"); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 945 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 946 | return -1; |
tass | 152:a3d286bf94e5 | 947 | } |
tass | 152:a3d286bf94e5 | 948 | tree = mcast_get_src_tree(s,&mcast); |
tass | 152:a3d286bf94e5 | 949 | listen_tree = mcast_get_listen_tree(s); |
tass | 152:a3d286bf94e5 | 950 | |
tass | 152:a3d286bf94e5 | 951 | pico_tree_foreach_safe(index, tree, _tmp) |
tass | 152:a3d286bf94e5 | 952 | { |
tass | 152:a3d286bf94e5 | 953 | source = index->keyValue; |
tass | 152:a3d286bf94e5 | 954 | pico_tree_delete(tree, source); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 955 | } |
tass | 152:a3d286bf94e5 | 956 | pico_tree_delete(listen_tree, mcast.listen); |
tass | 152:a3d286bf94e5 | 957 | PICO_FREE(mcast.listen); |
tass | 152:a3d286bf94e5 | 958 | if (pico_tree_empty(listen_tree)) { |
tass | 152:a3d286bf94e5 | 959 | PICO_FREE(listen_tree); |
tass | 152:a3d286bf94e5 | 960 | mcast_set_listen_tree_p_null(s); |
tass | 152:a3d286bf94e5 | 961 | pico_tree_delete(&MCASTSockets, s); |
tass | 152:a3d286bf94e5 | 962 | } |
tass | 152:a3d286bf94e5 | 963 | |
tass | 152:a3d286bf94e5 | 964 | filter_mode = pico_socket_aggregate_mcastfilters(mcast.address, &mcast.mreq->mcast_group_addr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 965 | if (filter_mode < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 966 | return -1; |
tass | 152:a3d286bf94e5 | 967 | if(IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 968 | return pico_ipv4_mcast_leave((struct pico_ip4*) &mcast.mreq->mcast_link_addr,(struct pico_ip4 *) &mcast.mreq->mcast_group_addr, 1, (uint8_t)filter_mode, &MCASTFilter); |
tass | 152:a3d286bf94e5 | 969 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 970 | else if(IS_SOCK_IPV6(s)) { } |
tass | 152:a3d286bf94e5 | 971 | return pico_ipv6_mcast_leave((struct pico_ip6*)&mcast.mreq->mcast_link_addr,(struct pico_ip6*)&mcast.mreq->mcast_group_addr, 1, (uint8_t)filter_mode, &MCASTFilter_ipv6); |
tass | 152:a3d286bf94e5 | 972 | #endif |
tass | 152:a3d286bf94e5 | 973 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 974 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 975 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 976 | static int mcast_so_unblock_src(struct pico_socket *s, void *value) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 977 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 978 | int filter_mode = 0; |
tass | 152:a3d286bf94e5 | 979 | union pico_address stest, *source = NULL; |
tass | 152:a3d286bf94e5 | 980 | struct pico_mcast mcast; |
tass | 152:a3d286bf94e5 | 981 | if(mcast_get_param(&mcast, s, value, 0,1) < 0) |
tass | 152:a3d286bf94e5 | 982 | return -1; |
tass | 152:a3d286bf94e5 | 983 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 984 | memset(&stest, 0, sizeof(union pico_address)); |
tass | 152:a3d286bf94e5 | 985 | if (!mcast.listen) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 986 | so_mcast_dbg("pico_socket_setoption: ERROR PICO_IP_UNBLOCK_SOURCE before PICO_IP_ADD_MEMBERSHIP\n"); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 987 | pico_err = PICO_ERR_EINVAL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 988 | return -1; |
tass | 152:a3d286bf94e5 | 989 | } |
tass | 152:a3d286bf94e5 | 990 | if (mcast.listen->filter_mode != PICO_IP_MULTICAST_EXCLUDE) { |
tass | 152:a3d286bf94e5 | 991 | so_mcast_dbg("pico_socket_setoption: ERROR any-source multicast (exclude) on source-specific multicast (include)\n"); |
tass | 152:a3d286bf94e5 | 992 | pico_err = PICO_ERR_EINVAL; |
tass | 152:a3d286bf94e5 | 993 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 994 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 995 | |
tass | 152:a3d286bf94e5 | 996 | stest = mcast.mreq_s->mcast_source_addr; |
tass | 152:a3d286bf94e5 | 997 | if( IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 998 | source = pico_tree_findKey(&mcast.listen->MCASTSources, &stest); |
tass | 152:a3d286bf94e5 | 999 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 1000 | else if( IS_SOCK_IPV6(s)) |
tass | 152:a3d286bf94e5 | 1001 | source = pico_tree_findKey(&mcast.listen->MCASTSources_ipv6, &stest); |
tass | 152:a3d286bf94e5 | 1002 | #endif |
tass | 152:a3d286bf94e5 | 1003 | if (!source) { |
tass | 152:a3d286bf94e5 | 1004 | so_mcast_dbg("pico_socket_setoption: ERROR address to unblock not in source list\n"); |
tass | 152:a3d286bf94e5 | 1005 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
tass | 152:a3d286bf94e5 | 1006 | return -1; |
tass | 152:a3d286bf94e5 | 1007 | } |
tass | 152:a3d286bf94e5 | 1008 | if( IS_SOCK_IPV4(s) ) |
tass | 152:a3d286bf94e5 | 1009 | pico_tree_delete(&mcast.listen->MCASTSources, source); |
tass | 152:a3d286bf94e5 | 1010 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 1011 | else if( IS_SOCK_IPV6(s) ) |
tass | 152:a3d286bf94e5 | 1012 | pico_tree_delete(&mcast.listen->MCASTSources_ipv6, source); |
tass | 152:a3d286bf94e5 | 1013 | #endif |
tass | 152:a3d286bf94e5 | 1014 | |
tass | 152:a3d286bf94e5 | 1015 | filter_mode = pico_socket_aggregate_mcastfilters(mcast.address, &mcast.mreq_s->mcast_group_addr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1016 | if (filter_mode < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1017 | return -1; |
tass | 152:a3d286bf94e5 | 1018 | if(IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 1019 | return pico_ipv4_mcast_leave((struct pico_ip4 *)&mcast.mreq_s->mcast_link_addr,(struct pico_ip4*) &mcast.mreq_s->mcast_group_addr, 0, (uint8_t)filter_mode, &MCASTFilter); |
tass | 152:a3d286bf94e5 | 1020 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 1021 | else if(IS_SOCK_IPV6(s)) { } |
tass | 152:a3d286bf94e5 | 1022 | return pico_ipv6_mcast_leave((struct pico_ip6*)&mcast.mreq_s->mcast_link_addr,(struct pico_ip6*)&mcast.mreq_s->mcast_group_addr, 0, (uint8_t)filter_mode, &MCASTFilter_ipv6); |
tass | 152:a3d286bf94e5 | 1023 | #endif |
tass | 152:a3d286bf94e5 | 1024 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1025 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1026 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1027 | static int mcast_so_block_src(struct pico_socket *s, void *value) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1028 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1029 | int filter_mode = 0; |
tass | 152:a3d286bf94e5 | 1030 | union pico_address stest, *source = NULL; |
tass | 152:a3d286bf94e5 | 1031 | struct pico_mcast mcast; |
tass | 152:a3d286bf94e5 | 1032 | if(mcast_get_param(&mcast, s, value, 0,1) < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1033 | return -1; |
tass | 152:a3d286bf94e5 | 1034 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1035 | memset(&stest, 0, sizeof(union pico_address)); |
tass | 152:a3d286bf94e5 | 1036 | if (!mcast.listen) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1037 | dbg("pico_socket_setoption: ERROR PICO_IP_BLOCK_SOURCE before PICO_IP_ADD_MEMBERSHIP\n"); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1038 | pico_err = PICO_ERR_EINVAL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1039 | return -1; |
tass | 152:a3d286bf94e5 | 1040 | } |
tass | 152:a3d286bf94e5 | 1041 | if (mcast.listen->filter_mode != PICO_IP_MULTICAST_EXCLUDE) { |
tass | 152:a3d286bf94e5 | 1042 | so_mcast_dbg("pico_socket_setoption: ERROR any-source multicast (exclude) on source-specific multicast (include)\n"); |
tass | 152:a3d286bf94e5 | 1043 | pico_err = PICO_ERR_EINVAL; |
tass | 152:a3d286bf94e5 | 1044 | return -1; |
tass | 152:a3d286bf94e5 | 1045 | } |
tass | 152:a3d286bf94e5 | 1046 | stest = mcast.mreq_s->mcast_source_addr; |
tass | 152:a3d286bf94e5 | 1047 | if( IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 1048 | source = pico_tree_findKey(&mcast.listen->MCASTSources, &stest); |
tass | 152:a3d286bf94e5 | 1049 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 1050 | else if( IS_SOCK_IPV6(s)) |
tass | 152:a3d286bf94e5 | 1051 | source = pico_tree_findKey(&mcast.listen->MCASTSources_ipv6, &stest); |
tass | 152:a3d286bf94e5 | 1052 | #endif |
tass | 152:a3d286bf94e5 | 1053 | if (source) { |
tass | 152:a3d286bf94e5 | 1054 | so_mcast_dbg("pico_socket_setoption: ERROR address to block already in source list\n"); |
tass | 152:a3d286bf94e5 | 1055 | pico_err = PICO_ERR_ENOMEM; |
tass | 152:a3d286bf94e5 | 1056 | return -1; |
tass | 152:a3d286bf94e5 | 1057 | } |
tass | 152:a3d286bf94e5 | 1058 | source = PICO_ZALLOC(sizeof(union pico_address)); |
tass | 152:a3d286bf94e5 | 1059 | if (!source) { |
tass | 152:a3d286bf94e5 | 1060 | pico_err = PICO_ERR_ENOMEM; |
tass | 152:a3d286bf94e5 | 1061 | return -1; |
tass | 152:a3d286bf94e5 | 1062 | } |
tass | 152:a3d286bf94e5 | 1063 | *source = mcast.mreq_s->mcast_source_addr; |
tass | 152:a3d286bf94e5 | 1064 | if( IS_SOCK_IPV4(s) ) |
tass | 152:a3d286bf94e5 | 1065 | pico_tree_insert(&mcast.listen->MCASTSources, source); |
tass | 152:a3d286bf94e5 | 1066 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 1067 | else if( IS_SOCK_IPV6(s) ) |
tass | 152:a3d286bf94e5 | 1068 | pico_tree_insert(&mcast.listen->MCASTSources_ipv6, source); |
tass | 152:a3d286bf94e5 | 1069 | #endif |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1070 | |
tass | 152:a3d286bf94e5 | 1071 | filter_mode = pico_socket_aggregate_mcastfilters(mcast.address, &mcast.mreq_s->mcast_group_addr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1072 | if (filter_mode < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1073 | return -1; |
tass | 152:a3d286bf94e5 | 1074 | if(IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 1075 | return pico_ipv4_mcast_join((struct pico_ip4 *) &mcast.mreq_s->mcast_link_addr, (struct pico_ip4*)&mcast.mreq_s->mcast_group_addr, 0, (uint8_t)filter_mode, &MCASTFilter); |
tass | 152:a3d286bf94e5 | 1076 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 1077 | else if(IS_SOCK_IPV6(s)) { } |
tass | 152:a3d286bf94e5 | 1078 | return pico_ipv6_mcast_join((struct pico_ip6 *)&mcast.mreq_s->mcast_link_addr,(struct pico_ip6*)&mcast.mreq_s->mcast_group_addr, 0, (uint8_t)filter_mode, &MCASTFilter_ipv6); |
tass | 152:a3d286bf94e5 | 1079 | #endif |
tass | 152:a3d286bf94e5 | 1080 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1081 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1082 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1083 | static int mcast_so_addsrcm(struct pico_socket *s, void *value) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1084 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1085 | int filter_mode = 0, reference_count = 0; |
tass | 152:a3d286bf94e5 | 1086 | union pico_address stest, *source = NULL; |
tass | 152:a3d286bf94e5 | 1087 | struct pico_mcast mcast; |
tass | 152:a3d286bf94e5 | 1088 | struct pico_tree *tree,*listen_tree; |
tass | 152:a3d286bf94e5 | 1089 | if(mcast_get_param(&mcast, s, value, 1,1) < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1090 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1091 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1092 | memset(&stest, 0, sizeof(union pico_address)); |
tass | 152:a3d286bf94e5 | 1093 | listen_tree = mcast_get_listen_tree(s); |
tass | 152:a3d286bf94e5 | 1094 | if (mcast.listen) { |
tass | 152:a3d286bf94e5 | 1095 | tree = mcast_get_src_tree(s,&mcast); |
tass | 152:a3d286bf94e5 | 1096 | if (mcast.listen->filter_mode != PICO_IP_MULTICAST_INCLUDE) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1097 | so_mcast_dbg("pico_socket_setoption: ERROR source-specific multicast (include) on any-source multicast (exclude)\n"); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1098 | pico_err = PICO_ERR_EINVAL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1099 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1100 | } |
tass | 152:a3d286bf94e5 | 1101 | stest = mcast.mreq_s->mcast_source_addr; |
tass | 152:a3d286bf94e5 | 1102 | source = pico_tree_findKey(tree, &stest); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1103 | if (source) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1104 | so_mcast_dbg("pico_socket_setoption: ERROR source address to allow already in source list\n"); |
tass | 152:a3d286bf94e5 | 1105 | pico_err = PICO_ERR_ENOMEM; |
tass | 152:a3d286bf94e5 | 1106 | return -1; |
tass | 152:a3d286bf94e5 | 1107 | } |
tass | 152:a3d286bf94e5 | 1108 | source = PICO_ZALLOC(sizeof(union pico_address)); |
tass | 152:a3d286bf94e5 | 1109 | if (!source) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1110 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1111 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1112 | } |
tass | 152:a3d286bf94e5 | 1113 | *source = mcast.mreq_s->mcast_source_addr; |
tass | 152:a3d286bf94e5 | 1114 | pico_tree_insert(tree, source); |
tass | 152:a3d286bf94e5 | 1115 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1116 | } else { |
tass | 152:a3d286bf94e5 | 1117 | mcast.listen = PICO_ZALLOC(sizeof(struct pico_mcast_listen)); |
tass | 152:a3d286bf94e5 | 1118 | if (!mcast.listen) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1119 | pico_err = PICO_ERR_ENOMEM; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1120 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1121 | } |
tass | 152:a3d286bf94e5 | 1122 | tree = mcast_get_src_tree(s,&mcast); |
tass | 152:a3d286bf94e5 | 1123 | mcast.listen->filter_mode = PICO_IP_MULTICAST_INCLUDE; |
tass | 152:a3d286bf94e5 | 1124 | mcast.listen->mcast_link = mcast.mreq_s->mcast_link_addr; |
tass | 152:a3d286bf94e5 | 1125 | mcast.listen->mcast_group = mcast.mreq_s->mcast_group_addr; |
tass | 152:a3d286bf94e5 | 1126 | tree->root = &LEAF; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1127 | source = PICO_ZALLOC(sizeof(union pico_address)); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1128 | if (!source) { |
tass | 152:a3d286bf94e5 | 1129 | PICO_FREE(mcast.listen); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1130 | pico_err = PICO_ERR_ENOMEM; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1131 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1132 | } |
tass | 152:a3d286bf94e5 | 1133 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 1134 | if( IS_SOCK_IPV6(s)) |
tass | 152:a3d286bf94e5 | 1135 | mcast.listen->proto = PICO_PROTO_IPV6; |
tass | 152:a3d286bf94e5 | 1136 | #endif |
tass | 152:a3d286bf94e5 | 1137 | *source = mcast.mreq_s->mcast_source_addr; |
tass | 152:a3d286bf94e5 | 1138 | pico_tree_insert(tree, source); |
tass | 152:a3d286bf94e5 | 1139 | pico_tree_insert(listen_tree, mcast.listen); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1140 | reference_count = 1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1141 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1142 | pico_tree_insert(&MCASTSockets, s); |
tass | 152:a3d286bf94e5 | 1143 | filter_mode = pico_socket_aggregate_mcastfilters(mcast.address, &mcast.mreq_s->mcast_group_addr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1144 | if (filter_mode < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1145 | return -1; |
tass | 152:a3d286bf94e5 | 1146 | if(IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 1147 | return pico_ipv4_mcast_join((struct pico_ip4 *)&mcast.mreq_s->mcast_link_addr, (struct pico_ip4*)&mcast.mreq_s->mcast_group_addr, (uint8_t)reference_count, (uint8_t)filter_mode, &MCASTFilter); |
tass | 152:a3d286bf94e5 | 1148 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 1149 | else if(IS_SOCK_IPV6(s)) { } |
tass | 152:a3d286bf94e5 | 1150 | return pico_ipv6_mcast_join((struct pico_ip6 *) &mcast.mreq_s->mcast_link_addr,(struct pico_ip6*)&mcast.mreq_s->mcast_group_addr, (uint8_t)reference_count, (uint8_t)filter_mode, &MCASTFilter_ipv6); |
tass | 152:a3d286bf94e5 | 1151 | #endif |
tass | 152:a3d286bf94e5 | 1152 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1153 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1154 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1155 | static int mcast_so_dropsrcm(struct pico_socket *s, void *value) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1156 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1157 | int filter_mode = 0, reference_count = 0; |
tass | 152:a3d286bf94e5 | 1158 | union pico_address stest, *source = NULL; |
tass | 152:a3d286bf94e5 | 1159 | struct pico_mcast mcast; |
tass | 152:a3d286bf94e5 | 1160 | struct pico_tree *tree,*listen_tree; |
tass | 152:a3d286bf94e5 | 1161 | if(mcast_get_param(&mcast, s, value, 0,1) < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1162 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1163 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1164 | memset(&stest, 0, sizeof(union pico_address)); |
tass | 152:a3d286bf94e5 | 1165 | listen_tree = mcast_get_listen_tree(s); |
tass | 152:a3d286bf94e5 | 1166 | if (!mcast.listen) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1167 | so_mcast_dbg("pico_socket_setoption: ERROR PICO_IP_DROP_SOURCE_MEMBERSHIP before PICO_IP_ADD_SOURCE_MEMBERSHIP\n"); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1168 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1169 | return -1; |
tass | 152:a3d286bf94e5 | 1170 | } |
tass | 152:a3d286bf94e5 | 1171 | if (mcast.listen->filter_mode != PICO_IP_MULTICAST_INCLUDE) { |
tass | 152:a3d286bf94e5 | 1172 | so_mcast_dbg("pico_socket_setoption: ERROR source-specific multicast (include) on any-source multicast (exclude)\n"); |
tass | 152:a3d286bf94e5 | 1173 | pico_err = PICO_ERR_EINVAL; |
tass | 152:a3d286bf94e5 | 1174 | return -1; |
tass | 152:a3d286bf94e5 | 1175 | } |
tass | 152:a3d286bf94e5 | 1176 | tree = mcast_get_src_tree(s, &mcast); |
tass | 152:a3d286bf94e5 | 1177 | stest = mcast.mreq_s->mcast_source_addr; |
tass | 152:a3d286bf94e5 | 1178 | source = pico_tree_findKey(tree, &stest); |
tass | 152:a3d286bf94e5 | 1179 | if (!source) { |
tass | 152:a3d286bf94e5 | 1180 | so_mcast_dbg("pico_socket_setoption: ERROR address to drop not in source list\n"); |
tass | 152:a3d286bf94e5 | 1181 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
tass | 152:a3d286bf94e5 | 1182 | return -1; |
tass | 152:a3d286bf94e5 | 1183 | } |
tass | 152:a3d286bf94e5 | 1184 | pico_tree_delete(tree, source); |
tass | 152:a3d286bf94e5 | 1185 | if (pico_tree_empty(tree)) { /* 1 if empty, 0 otherwise */ |
tass | 152:a3d286bf94e5 | 1186 | reference_count = 1; |
tass | 152:a3d286bf94e5 | 1187 | pico_tree_delete(listen_tree, mcast.listen); |
tass | 152:a3d286bf94e5 | 1188 | PICO_FREE(mcast.listen); |
tass | 152:a3d286bf94e5 | 1189 | if (pico_tree_empty(listen_tree)) { |
tass | 152:a3d286bf94e5 | 1190 | PICO_FREE(listen_tree); |
tass | 152:a3d286bf94e5 | 1191 | mcast_set_listen_tree_p_null(s); |
tass | 152:a3d286bf94e5 | 1192 | pico_tree_delete(&MCASTSockets, s); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1193 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1194 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1195 | |
tass | 152:a3d286bf94e5 | 1196 | filter_mode = pico_socket_aggregate_mcastfilters(mcast.address, &mcast.mreq_s->mcast_group_addr); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1197 | if (filter_mode < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1198 | return -1; |
tass | 152:a3d286bf94e5 | 1199 | if(IS_SOCK_IPV4(s)) |
tass | 152:a3d286bf94e5 | 1200 | return pico_ipv4_mcast_leave((struct pico_ip4 *) &mcast.mreq_s->mcast_link_addr, (struct pico_ip4*)&mcast.mreq_s->mcast_group_addr, (uint8_t)reference_count, (uint8_t)filter_mode, &MCASTFilter); |
tass | 152:a3d286bf94e5 | 1201 | #ifdef PICO_SUPPORT_IPV6 |
tass | 152:a3d286bf94e5 | 1202 | else if(IS_SOCK_IPV6(s)) { } |
tass | 152:a3d286bf94e5 | 1203 | return pico_ipv6_mcast_leave((struct pico_ip6 *)&mcast.mreq_s->mcast_link_addr,(struct pico_ip6*)&mcast.mreq_s->mcast_group_addr, (uint8_t)reference_count, (uint8_t)filter_mode, &MCASTFilter_ipv6); |
tass | 152:a3d286bf94e5 | 1204 | #endif |
tass | 152:a3d286bf94e5 | 1205 | return -1; |
tass | 152:a3d286bf94e5 | 1206 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1207 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1208 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1209 | struct pico_setsockopt_mcast_call |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1210 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1211 | int option; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1212 | int (*call)(struct pico_socket *, void *); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1213 | }; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1214 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1215 | static const struct pico_setsockopt_mcast_call mcast_so_calls[1 + PICO_IP_DROP_SOURCE_MEMBERSHIP - PICO_IP_MULTICAST_IF] = |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1216 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1217 | { PICO_IP_MULTICAST_IF, NULL }, |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1218 | { PICO_IP_MULTICAST_TTL, pico_udp_set_mc_ttl }, |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1219 | { PICO_IP_MULTICAST_LOOP, mcast_so_loop }, |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1220 | { PICO_IP_ADD_MEMBERSHIP, mcast_so_addm }, |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1221 | { PICO_IP_DROP_MEMBERSHIP, mcast_so_dropm }, |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1222 | { PICO_IP_UNBLOCK_SOURCE, mcast_so_unblock_src }, |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1223 | { PICO_IP_BLOCK_SOURCE, mcast_so_block_src }, |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1224 | { PICO_IP_ADD_SOURCE_MEMBERSHIP, mcast_so_addsrcm }, |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1225 | { PICO_IP_DROP_SOURCE_MEMBERSHIP, mcast_so_dropsrcm } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1226 | }; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1227 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1228 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1229 | static int mcast_so_check_socket(struct pico_socket *s) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1230 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1231 | pico_err = PICO_ERR_EINVAL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1232 | if (!s) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1233 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1234 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1235 | if (!s->proto) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1236 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1237 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1238 | if (s->proto->proto_number != PICO_PROTO_UDP) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1239 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1240 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1241 | pico_err = PICO_ERR_NOERR; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1242 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1243 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1244 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1245 | int pico_setsockopt_mcast(struct pico_socket *s, int option, void *value) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1246 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1247 | int arrayn = option - PICO_IP_MULTICAST_IF; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1248 | if (option < PICO_IP_MULTICAST_IF || option > PICO_IP_DROP_SOURCE_MEMBERSHIP) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1249 | pico_err = PICO_ERR_EOPNOTSUPP; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1250 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1251 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1252 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1253 | if (mcast_so_check_socket(s) < 0) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1254 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1255 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1256 | if (!mcast_so_calls[arrayn].call) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1257 | pico_err = PICO_ERR_EOPNOTSUPP; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1258 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1259 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1260 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1261 | return (mcast_so_calls[arrayn].call(s, value)); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1262 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1263 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1264 | int pico_udp_set_mc_ttl(struct pico_socket *s, void *_ttl) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1265 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1266 | struct pico_socket_udp *u; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1267 | uint8_t ttl = *(uint8_t *)_ttl; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1268 | if(!s) { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1269 | pico_err = PICO_ERR_EINVAL; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1270 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1271 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1272 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1273 | u = (struct pico_socket_udp *) s; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1274 | u->mc_ttl = ttl; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1275 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1276 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1277 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1278 | int pico_udp_get_mc_ttl(struct pico_socket *s, uint8_t *ttl) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1279 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1280 | struct pico_socket_udp *u; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1281 | if(!s) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1282 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1283 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1284 | u = (struct pico_socket_udp *) s; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1285 | *ttl = u->mc_ttl; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1286 | return 0; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1287 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1288 | #else |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1289 | int pico_udp_set_mc_ttl(struct pico_socket *s, void *_ttl) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1290 | { |
tass | 154:6c0e92a80c4a | 1291 | IGNORE_PARAMETER(s); |
tass | 154:6c0e92a80c4a | 1292 | IGNORE_PARAMETER(_ttl); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1293 | pico_err = PICO_ERR_EPROTONOSUPPORT; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1294 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1295 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1296 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1297 | int pico_udp_get_mc_ttl(struct pico_socket *s, uint8_t *ttl) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1298 | { |
tass | 154:6c0e92a80c4a | 1299 | IGNORE_PARAMETER(s); |
tass | 154:6c0e92a80c4a | 1300 | IGNORE_PARAMETER(ttl); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1301 | pico_err = PICO_ERR_EPROTONOSUPPORT; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1302 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1303 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1304 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1305 | int pico_socket_mcast_filter(struct pico_socket *s, union pico_address *mcast_group, union pico_address *src) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1306 | { |
tass | 154:6c0e92a80c4a | 1307 | IGNORE_PARAMETER(s); |
tass | 154:6c0e92a80c4a | 1308 | IGNORE_PARAMETER(mcast_group); |
tass | 154:6c0e92a80c4a | 1309 | IGNORE_PARAMETER(src); |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1310 | pico_err = PICO_ERR_EPROTONOSUPPORT; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1311 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1312 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1313 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1314 | void pico_multicast_delete(struct pico_socket *s) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1315 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1316 | (void)s; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1317 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1318 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1319 | int pico_getsockopt_mcast(struct pico_socket *s, int option, void *value) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1320 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1321 | (void)s; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1322 | (void)option; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1323 | (void)value; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1324 | pico_err = PICO_ERR_EPROTONOSUPPORT; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1325 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1326 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1327 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1328 | int pico_setsockopt_mcast(struct pico_socket *s, int option, void *value) |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1329 | { |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1330 | (void)s; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1331 | (void)option; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1332 | (void)value; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1333 | pico_err = PICO_ERR_EPROTONOSUPPORT; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1334 | return -1; |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1335 | |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1336 | } |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1337 | #endif /* PICO_SUPPORT_MCAST */ |
tass picotcp@tass.be | 149:5f4cb161cec3 | 1338 |