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_join_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 join the specified multicast */
44 /* group on a specified network device. */
45 /* */
46 /* INPUT */
47 /* */
48 /* ip_ptr IP instance pointer */
49 /* group_address Multicast group to join */
50 /* interface_index Index to the interface */
51 /* update_time Update time */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* status Completion status */
56 /* */
57 /* CALLS */
58 /* */
59 /* tx_mutex_get Obtain protection mutex */
60 /* tx_mutex_put Release protection mutex */
61 /* (ip_link_driver) Associated IP link driver */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* Application Code */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
72 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
73 /* resulting in version 6.1 */
74 /* */
75 /**************************************************************************/
_nx_igmp_multicast_interface_join_internal(NX_IP * ip_ptr,ULONG group_address,UINT interface_index,UINT update_time)76 UINT _nx_igmp_multicast_interface_join_internal(NX_IP *ip_ptr, ULONG group_address,
77 UINT interface_index, UINT update_time)
78 {
79
80 UINT i;
81 UINT first_free;
82 NX_IP_DRIVER driver_request;
83 NX_INTERFACE *nx_interface;
84
85 /* If trace is enabled, insert this event into the trace buffer. */
86 NX_TRACE_IN_LINE_INSERT(NX_TRACE_IGMP_MULTICAST_JOIN, ip_ptr, group_address, interface_index, 0, NX_TRACE_IGMP_EVENTS, 0, 0);
87
88 /* Obtain the IP mutex so we can search the multicast join list. */
89 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
90
91 nx_interface = &ip_ptr -> nx_ip_interface[interface_index];
92
93 /* Search the multicast join list for either the same group request. */
94 first_free = NX_MAX_MULTICAST_GROUPS;
95
96 for (i = 0; i < NX_MAX_MULTICAST_GROUPS; i++)
97 {
98
99 /* Determine if the specified entry is already in the multicast join list. */
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. The only thing required in this
105 case is to increment the join count and return. */
106 ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_count++;
107
108 /* Release the IP protection. */
109 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
110
111 /* Return success! */
112 return(NX_SUCCESS);
113 }
114
115 /* Check for an empty entry. */
116 if ((ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_list == 0) &&
117 (first_free == NX_MAX_MULTICAST_GROUPS))
118 {
119
120 /* Remember the first free entry. */
121 first_free = i;
122 }
123 }
124
125 /* At this point, we have a new entry. First, check to see if there is an available
126 entry. */
127 if (first_free == NX_MAX_MULTICAST_GROUPS)
128 {
129
130 /* Release the protection of the IP instance. */
131 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
132
133 /* Return an error code to indicate there are no more group addresses
134 available. */
135 return(NX_NO_MORE_ENTRIES);
136 }
137
138 /* Register the new multicast group with the underlying driver to
139 ensure that there is room for the new group at the hardware level. */
140 driver_request.nx_ip_driver_ptr = ip_ptr;
141 driver_request.nx_ip_driver_command = NX_LINK_MULTICAST_JOIN;
142 driver_request.nx_ip_driver_physical_address_msw = NX_IP_MULTICAST_UPPER;
143 driver_request.nx_ip_driver_physical_address_lsw = NX_IP_MULTICAST_LOWER | (group_address & NX_IP_MULTICAST_MASK);
144 driver_request.nx_ip_driver_interface = nx_interface;
145
146 /* If trace is enabled, insert this event into the trace buffer. */
147 NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_MULTICAST_JOIN, ip_ptr, 0, 0, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
148
149 (nx_interface -> nx_interface_link_driver_entry)(&driver_request);
150
151 /* Check the return driver status. */
152 /*lint -e{644} suppress variable might not be initialized, since "nx_ip_driver_status" was initialized in nx_interface_link_driver_entry. */
153 if (driver_request.nx_ip_driver_status != NX_SUCCESS)
154 {
155
156 /* Release the protection of the IP instance. */
157 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
158
159 /* Return an error code to indicate there are no more group addresses
160 available. */
161 return(NX_NO_MORE_ENTRIES);
162 }
163
164 /* Set it up in the IP control structures. */
165 ip_ptr -> nx_ipv4_multicast_entry[first_free].nx_ipv4_multicast_join_list = group_address;
166 ip_ptr -> nx_ipv4_multicast_entry[first_free].nx_ipv4_multicast_join_interface_list = nx_interface;
167 ip_ptr -> nx_ipv4_multicast_entry[first_free].nx_ipv4_multicast_join_count = 1;
168 ip_ptr -> nx_ipv4_multicast_entry[first_free].nx_ipv4_multicast_update_time = update_time; /* Update on next IGMP periodic */
169 ip_ptr -> nx_ipv4_multicast_entry[first_free].nx_ipv4_multicast_loopback_enable = ip_ptr -> nx_ip_igmp_global_loopback_enable;
170
171 #ifndef NX_DISABLE_IGMP_INFO
172 /* Increment the IGMP groups joined count. */
173 ip_ptr -> nx_ip_igmp_groups_joined++;
174 #endif
175
176 /* Release the protection over the IP instance. */
177 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
178
179 /* Return a successful status! */
180 return(NX_SUCCESS);
181 }
182 #endif /* !NX_DISABLE_IPV4 */
183
184