1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Component */
16 /** */
17 /** Internet Group Management Protocol (IGMP) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "nx_api.h"
28 #include "nx_igmp.h"
29
30 #ifndef NX_DISABLE_IPV4
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _nx_igmp_multicast_interface_leave_internal PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Yuxin Zhou, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function handles the request to leave the specified multicast */
44 /* group. */
45 /* */
46 /* INPUT */
47 /* */
48 /* ip_ptr IP instance pointer */
49 /* group_address Multicast group to join */
50 /* interface_index Interface index */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* NX_SUCCESS Successful completion status */
55 /* NX_ENTRY_NOT_FOUND Group address not found in the*/
56 /* IGMP join list */
57 /* */
58 /* CALLS */
59 /* */
60 /* tx_mutex_get Obtain protection mutex */
61 /* tx_mutex_put Release protection mutex */
62 /* (ip_link_driver) Associated IP link driver */
63 /* nx_igmp_interface_report_send Send IGMP group reports */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* Application Code */
68 /* */
69 /* RELEASE HISTORY */
70 /* */
71 /* DATE NAME DESCRIPTION */
72 /* */
73 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
74 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
75 /* resulting in version 6.1 */
76 /* */
77 /**************************************************************************/
_nx_igmp_multicast_interface_leave_internal(NX_IP * ip_ptr,ULONG group_address,UINT interface_index)78 UINT _nx_igmp_multicast_interface_leave_internal(NX_IP *ip_ptr, ULONG group_address, UINT interface_index)
79 {
80
81 UINT i;
82 NX_IP_DRIVER driver_request;
83 NX_INTERFACE *nx_interface;
84
85
86 /* If trace is enabled, insert this event into the trace buffer. */
87 NX_TRACE_IN_LINE_INSERT(NX_TRACE_IGMP_MULTICAST_LEAVE, ip_ptr, group_address, 0, 0, NX_TRACE_IGMP_EVENTS, 0, 0);
88
89 /* Obtain the IP mutex so we can search the multicast join list. */
90 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
91
92 nx_interface = &ip_ptr -> nx_ip_interface[interface_index];
93
94 /* Search the multicast join list for the group request. */
95
96 for (i = 0; i < NX_MAX_MULTICAST_GROUPS; i++)
97 {
98
99 /* Determine if the specified entry is present. */
100 if ((ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_list == group_address) &&
101 (ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_interface_list == nx_interface))
102 {
103
104 /* Yes, we have found the same entry. */
105
106 /* Decrease the join count. */
107 ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_count--;
108
109 /* Determine if there are no other join requests for this group address. */
110 if (ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_count == 0)
111 {
112
113 /* Clear the group join value. */
114 ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_list = 0;
115
116 /* Un-register the new multicast group with the underlying driver. */
117 driver_request.nx_ip_driver_ptr = ip_ptr;
118 driver_request.nx_ip_driver_command = NX_LINK_MULTICAST_LEAVE;
119 driver_request.nx_ip_driver_physical_address_msw = NX_IP_MULTICAST_UPPER;
120 driver_request.nx_ip_driver_physical_address_lsw = NX_IP_MULTICAST_LOWER | (group_address & NX_IP_MULTICAST_MASK);
121 driver_request.nx_ip_driver_interface = ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_interface_list;
122
123 /* If trace is enabled, insert this event into the trace buffer. */
124 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_MULTICAST_LEAVE, ip_ptr, 0, 0, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
125
126 (ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_interface_list -> nx_interface_link_driver_entry)(&driver_request);
127
128 /* Clear the interface entry for version IGMPv1. Don't need it anymore. */
129 ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_interface_list = NX_NULL;
130
131 #ifndef NX_DISABLE_IGMP_INFO
132 /* Decrement the IGMP groups joined count. */
133 ip_ptr -> nx_ip_igmp_groups_joined--;
134 #endif
135
136 #ifndef NX_DISABLE_IGMPV2
137 /* Check if the entry is a local multicast join. */
138 if (ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_update_time == NX_WAIT_FOREVER)
139 {
140
141 /* It is. Release the IP protection. */
142 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
143
144 /* Return success. */
145 return(NX_SUCCESS);
146 }
147
148 /* IGMPv1 hosts do not send a leave group message. */
149 if (ip_ptr -> nx_ip_igmp_router_version == NX_IGMP_HOST_VERSION_1)
150 {
151
152 /* Release the IP protection. */
153 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
154
155 /* Return success! */
156 return(NX_SUCCESS);
157 }
158
159 /* Build and send the leave report packet. */
160 _nx_igmp_interface_report_send(ip_ptr, group_address, interface_index, NX_FALSE);
161
162 #endif /* NX_DISABLE_IGMPV2 */
163 }
164
165 /* Release the IP protection. */
166 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
167
168 /* Return success. */
169 return(NX_SUCCESS);
170 }
171 }
172
173 /* At this point we know that the supplied entry was not found. */
174
175 /* Release the protection of the IP instance. */
176 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
177
178 /* Return an error code. */
179 return(NX_ENTRY_NOT_FOUND);
180 }
181 #endif /* !NX_DISABLE_IPV4 */
182
183