1 /*
2 * Copyright (c) 2023-2023 Huawei Device Co., Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific prior written
16 * permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifdef LOSCFG_NET_CONTAINER
32 #include <sched.h>
33 #include "los_net_container_pri.h"
34 #include "los_config.h"
35 #include "los_memory.h"
36 #include "los_process_pri.h"
37
38 STATIC UINT32 g_currentNetContainerNum = 0;
39 STATIC NetContainer *g_rootNetContainer = NULL;
40
NetifAlloc(VOID)41 STATIC struct netif *NetifAlloc(VOID)
42 {
43 UINT32 size = sizeof(struct netif);
44 struct netif *netif = LOS_MemAlloc(m_aucSysMem1, size);
45 if (netif == NULL) {
46 return NULL;
47 }
48 (VOID)memset_s(netif, size, 0, size);
49
50 return netif;
51 }
52
FreeNetif(struct netif * netif)53 STATIC VOID FreeNetif(struct netif *netif)
54 {
55 if (netif != NULL) {
56 if (netif->peer != NULL) {
57 netif_remove(netif->peer);
58 (VOID)LOS_MemFree(m_aucSysMem1, netif->peer);
59 }
60 netif_remove(netif);
61 (VOID)LOS_MemFree(m_aucSysMem1, netif);
62 }
63 }
64
CreateVethNetif(NetContainer * netContainer,struct netif ** veth)65 STATIC UINT32 CreateVethNetif(NetContainer *netContainer, struct netif **veth)
66 {
67 struct netif *netif = NetifAlloc();
68 if (netif == NULL) {
69 return ENOMEM;
70 }
71
72 veth_init(netif, netContainer->group);
73
74 *veth = netif;
75 return LOS_OK;
76 }
77
InitVethPair(NetContainer * netContainer)78 STATIC UINT32 InitVethPair(NetContainer *netContainer)
79 {
80 struct netif *vethOfNetContainer = NULL;
81 struct netif *vethOfRootNetContainer = NULL;
82
83 UINT32 ret = CreateVethNetif(netContainer, &vethOfNetContainer);
84 if (ret != LOS_OK) {
85 return ret;
86 }
87
88 ret = CreateVethNetif(g_rootNetContainer, &vethOfRootNetContainer);
89 if (ret != LOS_OK) {
90 FreeNetif(vethOfNetContainer);
91 return ret;
92 }
93
94 vethOfNetContainer->peer = vethOfRootNetContainer;
95 vethOfRootNetContainer->peer = vethOfNetContainer;
96 return LOS_OK;
97 }
98
InitLoopNetif(NetContainer * netContainer)99 STATIC UINT32 InitLoopNetif(NetContainer *netContainer)
100 {
101 struct netif *loop_netif = NetifAlloc();
102 if (loop_netif == NULL) {
103 return ENOMEM;
104 }
105
106 netContainer->group->loop_netif = loop_netif;
107 netif_init(netContainer->group);
108 return LOS_OK;
109 }
110
InitContainerNetifs(NetContainer * netContainer)111 STATIC UINT32 InitContainerNetifs(NetContainer *netContainer)
112 {
113 UINT32 ret = InitLoopNetif(netContainer);
114 if (ret != LOS_OK) {
115 return ret;
116 }
117 return InitVethPair(netContainer);
118 }
119
InitNetGroup(NetContainer * netContainer)120 STATIC UINT32 InitNetGroup(NetContainer *netContainer)
121 {
122 UINT32 size = sizeof(struct net_group);
123 struct net_group *group = LOS_MemAlloc(m_aucSysMem1, size);
124 if (group == NULL) {
125 return ENOMEM;
126 }
127 (VOID)memset_s(group, size, 0, size);
128
129 netContainer->group = group;
130 return LOS_OK;
131 }
132
FreeNetContainerGroup(struct net_group * group)133 STATIC VOID FreeNetContainerGroup(struct net_group *group)
134 {
135 if (group == NULL) {
136 return;
137 }
138
139 struct netif *freeNetif = group->netif_list;
140 struct netif *nextNetif = NULL;
141
142 while (freeNetif != NULL) {
143 nextNetif = freeNetif->next;
144 FreeNetif(freeNetif);
145 freeNetif = nextNetif;
146 }
147 }
148
OsNetContainerDestroy(Container * container)149 VOID OsNetContainerDestroy(Container *container)
150 {
151 UINT32 intSave;
152 if (container == NULL) {
153 return;
154 }
155
156 SCHEDULER_LOCK(intSave);
157 NetContainer *netContainer = container->netContainer;
158 if (netContainer == NULL) {
159 SCHEDULER_UNLOCK(intSave);
160 return;
161 }
162
163 LOS_AtomicDec(&netContainer->rc);
164 if (LOS_AtomicRead(&netContainer->rc) > 0) {
165 SCHEDULER_UNLOCK(intSave);
166 return;
167 }
168
169 g_currentNetContainerNum--;
170 SCHEDULER_UNLOCK(intSave);
171 FreeNetContainerGroup(netContainer->group);
172 container->netContainer = NULL;
173 (VOID)LOS_MemFree(m_aucSysMem1, netContainer->group);
174 (VOID)LOS_MemFree(m_aucSysMem1, netContainer);
175 return;
176 }
177
CreateNewNetContainer(NetContainer * parent)178 STATIC NetContainer *CreateNewNetContainer(NetContainer *parent)
179 {
180 NetContainer *netContainer = LOS_MemAlloc(m_aucSysMem1, sizeof(NetContainer));
181 if (netContainer == NULL) {
182 return NULL;
183 }
184 (VOID)memset_s(netContainer, sizeof(NetContainer), 0, sizeof(NetContainer));
185
186 netContainer->containerID = OsAllocContainerID();
187
188 if (parent != NULL) {
189 LOS_AtomicSet(&netContainer->rc, 1);
190 } else {
191 LOS_AtomicSet(&netContainer->rc, 3); /* 3: Three system processes */
192 }
193 return netContainer;
194 }
195
CreateNetContainer(Container * container,NetContainer * parentContainer)196 STATIC UINT32 CreateNetContainer(Container *container, NetContainer *parentContainer)
197 {
198 UINT32 intSave, ret;
199 NetContainer *newNetContainer = CreateNewNetContainer(parentContainer);
200 if (newNetContainer == NULL) {
201 return ENOMEM;
202 }
203
204 ret = InitNetGroup(newNetContainer);
205 if (ret != LOS_OK) {
206 (VOID)LOS_MemFree(m_aucSysMem1, newNetContainer);
207 return ret;
208 }
209
210 ret = InitContainerNetifs(newNetContainer);
211 if (ret != LOS_OK) {
212 (VOID)LOS_MemFree(m_aucSysMem1, newNetContainer->group);
213 (VOID)LOS_MemFree(m_aucSysMem1, newNetContainer);
214 return ret;
215 }
216
217 SCHEDULER_LOCK(intSave);
218 g_currentNetContainerNum++;
219 container->netContainer = newNetContainer;
220 SCHEDULER_UNLOCK(intSave);
221 return LOS_OK;
222 }
223
OsCopyNetContainer(UINTPTR flags,LosProcessCB * child,LosProcessCB * parent)224 UINT32 OsCopyNetContainer(UINTPTR flags, LosProcessCB *child, LosProcessCB *parent)
225 {
226 UINT32 intSave;
227 NetContainer *currNetContainer = parent->container->netContainer;
228
229 if (!(flags & CLONE_NEWNET)) {
230 SCHEDULER_LOCK(intSave);
231 LOS_AtomicInc(&currNetContainer->rc);
232 child->container->netContainer = currNetContainer;
233 SCHEDULER_UNLOCK(intSave);
234 return LOS_OK;
235 }
236
237 if (OsContainerLimitCheck(NET_CONTAINER, &g_currentNetContainerNum) != LOS_OK) {
238 return EPERM;
239 }
240
241 return CreateNetContainer(child->container, currNetContainer);
242 }
243
OsUnshareNetContainer(UINTPTR flags,LosProcessCB * curr,Container * newContainer)244 UINT32 OsUnshareNetContainer(UINTPTR flags, LosProcessCB *curr, Container *newContainer)
245 {
246 UINT32 intSave;
247 NetContainer *parentContainer = curr->container->netContainer;
248
249 if (!(flags & CLONE_NEWNET)) {
250 SCHEDULER_LOCK(intSave);
251 newContainer->netContainer = parentContainer;
252 LOS_AtomicInc(&parentContainer->rc);
253 SCHEDULER_UNLOCK(intSave);
254 return LOS_OK;
255 }
256
257 if (OsContainerLimitCheck(NET_CONTAINER, &g_currentNetContainerNum) != LOS_OK) {
258 return EPERM;
259 }
260
261 return CreateNetContainer(newContainer, parentContainer);
262 }
263
OsSetNsNetContainer(UINT32 flags,Container * container,Container * newContainer)264 UINT32 OsSetNsNetContainer(UINT32 flags, Container *container, Container *newContainer)
265 {
266 if (flags & CLONE_NEWNET) {
267 newContainer->netContainer = container->netContainer;
268 LOS_AtomicInc(&container->netContainer->rc);
269 return LOS_OK;
270 }
271
272 newContainer->netContainer = OsCurrProcessGet()->container->netContainer;
273 LOS_AtomicInc(&newContainer->netContainer->rc);
274 return LOS_OK;
275 }
276
OsGetNetContainerID(NetContainer * netContainer)277 UINT32 OsGetNetContainerID(NetContainer *netContainer)
278 {
279 if (netContainer == NULL) {
280 return OS_INVALID_VALUE;
281 }
282
283 return netContainer->containerID;
284 }
285
DoGetNetGroupFromCurrProcess(VOID)286 STATIC struct net_group *DoGetNetGroupFromCurrProcess(VOID)
287 {
288 LosProcessCB *processCB = OsCurrProcessGet();
289 NetContainer *netContainer = processCB->container->netContainer;
290 return netContainer->group;
291 }
292
DoSetNetifNetGroup(struct netif * netif,struct net_group * group)293 STATIC VOID DoSetNetifNetGroup(struct netif *netif, struct net_group *group)
294 {
295 netif->group = group;
296 }
297
DoGetNetGroupFromNetif(struct netif * netif)298 STATIC struct net_group *DoGetNetGroupFromNetif(struct netif *netif)
299 {
300 return netif != NULL ? netif->group : NULL;
301 }
302
DoSetIppcbNetGroup(struct ip_pcb * pcb,struct net_group * group)303 STATIC VOID DoSetIppcbNetGroup(struct ip_pcb *pcb, struct net_group *group)
304 {
305 pcb->group = group;
306 }
307
DoGetNetGroupFromIppcb(struct ip_pcb * pcb)308 STATIC struct net_group *DoGetNetGroupFromIppcb(struct ip_pcb *pcb)
309 {
310 return pcb != NULL ? pcb->group : NULL;
311 }
312
313 struct net_group_ops netGroupOps = {
314 .get_curr_process_net_group = DoGetNetGroupFromCurrProcess,
315 .set_netif_net_group = DoSetNetifNetGroup,
316 .get_net_group_from_netif = DoGetNetGroupFromNetif,
317 .set_ippcb_net_group = DoSetIppcbNetGroup,
318 .get_net_group_from_ippcb = DoGetNetGroupFromIppcb,
319 };
320
OsInitRootNetContainer(NetContainer ** netContainer)321 UINT32 OsInitRootNetContainer(NetContainer **netContainer)
322 {
323 UINT32 intSave;
324 NetContainer *newNetContainer = CreateNewNetContainer(NULL);
325 if (newNetContainer == NULL) {
326 return ENOMEM;
327 }
328
329 newNetContainer->group = get_root_net_group();
330 set_default_net_group_ops(&netGroupOps);
331
332 SCHEDULER_LOCK(intSave);
333 g_currentNetContainerNum++;
334 *netContainer = newNetContainer;
335 g_rootNetContainer = newNetContainer;
336 SCHEDULER_UNLOCK(intSave);
337 return LOS_OK;
338 }
339
OsGetNetContainerCount(VOID)340 UINT32 OsGetNetContainerCount(VOID)
341 {
342 return g_currentNetContainerNum;
343 }
344 #endif
345