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 Protocol (IP)                                              */
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_ip.h"
29 #ifdef FEATURE_NX_IPV6
30 #include "nx_ipv6.h"
31 #endif
32 
33 
34 
35 /**************************************************************************/
36 /*                                                                        */
37 /*  FUNCTION                                               RELEASE        */
38 /*                                                                        */
39 /*    _nx_ip_interface_attach                             PORTABLE C      */
40 /*                                                           6.1.8        */
41 /*  AUTHOR                                                                */
42 /*                                                                        */
43 /*    Yuxin Zhou, Microsoft Corporation                                   */
44 /*                                                                        */
45 /*  DESCRIPTION                                                           */
46 /*                                                                        */
47 /*    This function attaches a physical network interface to the IP       */
48 /*    instance, invokes the associated device driver to initialize and    */
49 /*    enable the device.                                                  */
50 /*                                                                        */
51 /*    If this function is called before the IP thread starts running,     */
52 /*    the deivce initialization is executed as part of the device         */
53 /*    initialization during IP thread start up phase.  If this function   */
54 /*    is called after the IP thread has been started, the device          */
55 /*    initialization is executed as part of this function call.           */
56 /*                                                                        */
57 /*                                                                        */
58 /*  INPUT                                                                 */
59 /*                                                                        */
60 /*    ip_ptr_value                          Pointer to IP control block   */
61 /*    interface_name                        Name of this interface        */
62 /*    ip_address                            Interface IP Address, in host */
63 /*                                            byte order                  */
64 /*    network_mask                          Network Mask, in host byte    */
65 /*                                             order                      */
66 /*    ip_link_driver                        User supplied link driver     */
67 /*                                                                        */
68 /*  OUTPUT                                                                */
69 /*                                                                        */
70 /*    status                                Completion status             */
71 /*                                                                        */
72 /*  CALLS                                                                 */
73 /*                                                                        */
74 /*    tx_mutex_get                          Obtain protection mutex       */
75 /*    tx_mutex_put                          Release protection mutex      */
76 /*    (ip_link_driver)                      User supplied link driver     */
77 /*    _nx_ipv6_multicast_join               Join IPv6 multicast group     */
78 /*                                                                        */
79 /*  CALLED BY                                                             */
80 /*                                                                        */
81 /*    Application                                                         */
82 /*                                                                        */
83 /*  RELEASE HISTORY                                                       */
84 /*                                                                        */
85 /*    DATE              NAME                      DESCRIPTION             */
86 /*                                                                        */
87 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
88 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
89 /*                                            resulting in version 6.1    */
90 /*  08-02-2021     Yuxin Zhou               Modified comment(s), and      */
91 /*                                            supported TCP/IP offload,   */
92 /*                                            resulting in version 6.1.8  */
93 /*                                                                        */
94 /**************************************************************************/
_nx_ip_interface_attach(NX_IP * ip_ptr,CHAR * interface_name,ULONG ip_address,ULONG network_mask,VOID (* ip_link_driver)(struct NX_IP_DRIVER_STRUCT *))95 UINT _nx_ip_interface_attach(NX_IP *ip_ptr, CHAR *interface_name, ULONG ip_address, ULONG network_mask, VOID (*ip_link_driver)(struct NX_IP_DRIVER_STRUCT *))
96 {
97 
98 INT           i;
99 NX_INTERFACE *nx_interface = NX_NULL;
100 NX_IP_DRIVER  driver_request;
101 UINT          status = NX_SUCCESS;
102 
103 #if defined(FEATURE_NX_IPV6) && !defined(NX_DISABLE_ICMPV6_ROUTER_SOLICITATION)
104 ULONG         address[4];
105 #endif
106 
107 #ifdef NX_DISABLE_IPV4
108     NX_PARAMETER_NOT_USED(ip_address);
109     NX_PARAMETER_NOT_USED(network_mask);
110 #else
111     /* Perform duplicate address detection.  */
112     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
113     {
114         if ((ip_ptr -> nx_ip_interface[i].nx_interface_ip_address == ip_address) &&
115             (ip_address != 0))
116         {
117 
118             /* The IPv4 address already exists.  */
119             return(NX_DUPLICATED_ENTRY);
120         }
121     }
122 #endif /* !NX_DISABLE_IPV4  */
123 
124     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
125     {
126 
127         nx_interface = &(ip_ptr -> nx_ip_interface[i]);
128 
129         if (!(nx_interface -> nx_interface_valid))
130         {
131             /* Find a valid entry. */
132             break;
133         }
134     }
135 
136     if (i == NX_MAX_PHYSICAL_INTERFACES)
137     {
138         /* No more free entry.  return. */
139         return(NX_NO_MORE_ENTRIES);
140     }
141 
142     /* Obtain the IP internal mutex before calling the driver.  */
143     tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
144 
145     /* Mark the entry as valid. */
146     nx_interface -> nx_interface_valid = NX_TRUE;
147 
148     /* Fill in the interface information. */
149 #ifndef NX_DISABLE_IPV4
150     nx_interface -> nx_interface_ip_address        = ip_address;
151     nx_interface -> nx_interface_ip_network_mask   = network_mask;
152     nx_interface -> nx_interface_ip_network        = ip_address & network_mask;
153 #endif /* !NX_DISABLE_IPV4  */
154     nx_interface -> nx_interface_link_driver_entry = ip_link_driver;
155     nx_interface -> nx_interface_name              = interface_name;
156 
157     /* If trace is enabled, insert this event into the trace buffer.  */
158     NX_TRACE_IN_LINE_INSERT(NX_TRACE_IP_INTERFACE_ATTACH, ip_ptr, ip_address, i, 0, NX_TRACE_IP_EVENTS, 0, 0);
159 
160     /* If the IP thread is already running, this service needs to go through the rest of the initializeation process. */
161     if (ip_ptr -> nx_ip_initialize_done == NX_TRUE)
162     {
163 
164 #ifdef NX_ENABLE_INTERFACE_CAPABILITY
165         /* Clear capability flag.  */
166         ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag = 0;
167 #endif /* NX_ENABLE_INTERFACE_CAPABILITY */
168 
169         /* First attach the interface to the device. */
170         driver_request.nx_ip_driver_ptr       =  ip_ptr;
171         driver_request.nx_ip_driver_command   =  NX_LINK_INTERFACE_ATTACH;
172         driver_request.nx_ip_driver_interface = &(ip_ptr -> nx_ip_interface[i]);
173         (ip_ptr -> nx_ip_interface[i].nx_interface_link_driver_entry)(&driver_request);
174 
175 #ifdef NX_ENABLE_TCPIP_OFFLOAD
176         if (ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD)
177         {
178 
179             /* Set checksum capability for TCP/IP offload interface.  */
180             ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag |= NX_INTERFACE_CAPABILITY_CHECKSUM_ALL;
181         }
182 #endif /* NX_ENABLE_TCPIP_OFFLOAD */
183 
184         /* Call the link driver to initialize the hardware. Among other
185            responsibilities, the driver is required to provide the
186            Maximum Transfer Unit (MTU) for the physical layer. The MTU
187            should represent the actual physical layer transfer size
188            less the physical layer headers and trailers.  */
189         driver_request.nx_ip_driver_ptr =      ip_ptr;
190         driver_request.nx_ip_driver_command =  NX_LINK_INITIALIZE;
191 
192         /* If trace is enabled, insert this event into the trace buffer.  */
193         NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_INITIALIZE, ip_ptr, 0, 0, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
194 
195         /*
196            When an IP instance is created, the first interface (nx_ip_interface[0]) is configured using parameters
197            provided in the IP create call.
198 
199            When IP thread runs, it invokes the 1st interface link driver for link initialization.
200          */
201         (ip_ptr -> nx_ip_interface[i].nx_interface_link_driver_entry)(&driver_request);
202 
203 
204 
205         /* Call the link driver again to enable the interface.  */
206         driver_request.nx_ip_driver_ptr =      ip_ptr;
207         driver_request.nx_ip_driver_command =  NX_LINK_ENABLE;
208 
209         /* If trace is enabled, insert this event into the trace buffer.  */
210         NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_LINK_ENABLE, ip_ptr, 0, 0, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
211 
212         (ip_ptr -> nx_ip_interface[i].nx_interface_link_driver_entry)(&driver_request);
213 
214         /* Also configure the all-node multicast address. */
215 #if defined(FEATURE_NX_IPV6) && !defined(NX_DISABLE_ICMPV6_ROUTER_SOLICITATION)
216         /* Create the all-node multicast group address, */
217         address[0] = 0xFF020000;
218         address[1] = 0;
219         address[2] = 0;
220         address[3] = 1;
221 
222 
223         /* Join all-node multicast group. */
224         status = _nx_ipv6_multicast_join(ip_ptr, address, &ip_ptr -> nx_ip_interface[i]);
225 
226 #endif
227     }
228 
229     /* Release the IP internal mutex.  */
230     tx_mutex_put(&(ip_ptr -> nx_ip_protection));
231 
232 
233     /* All done.  Return. */
234     return(status);
235 }
236 
237