1 /** @file
2   Driver Binding functions and Service Binding functions for the Network driver module.
3 
4   Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5 
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "Udp6Impl.h"
11 
12 EFI_DRIVER_BINDING_PROTOCOL gUdp6DriverBinding = {
13   Udp6DriverBindingSupported,
14   Udp6DriverBindingStart,
15   Udp6DriverBindingStop,
16   0xa,
17   NULL,
18   NULL
19 };
20 
21 EFI_SERVICE_BINDING_PROTOCOL mUdp6ServiceBinding = {
22   Udp6ServiceBindingCreateChild,
23   Udp6ServiceBindingDestroyChild
24 };
25 
26 /**
27   Tests to see if this driver supports a given controller. If a child device is provided,
28   it further tests to see if this driver supports creating a handle for the specified child device.
29 
30   This function checks to see if the driver specified by This supports the device specified by
31   ControllerHandle. Drivers will typically use the device path attached to
32   ControllerHandle and/or the services from the bus I/O abstraction attached to
33   ControllerHandle to determine if the driver supports ControllerHandle. This function
34   may be called many times during platform initialization. In order to reduce boot times, the tests
35   performed by this function must be very small, and take as little time as possible to execute. This
36   function must not change the state of any hardware devices, and this function must be aware that the
37   device specified by ControllerHandle may already be managed by the same driver or a
38   different driver. This function must match its calls to AllocatePages() with FreePages(),
39   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
40   Because ControllerHandle may have been previously started by the same driver, if a protocol is
41   already in the opened state, then it must not be closed with CloseProtocol(). This is required
42   to guarantee the state of ControllerHandle is not modified by this function.
43 
44   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
45   @param[in]  ControllerHandle     The handle of the controller to test. This handle
46                                    must support a protocol interface that supplies
47                                    an I/O abstraction to the driver.
48   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
49                                    parameter is ignored by device drivers, and is optional for bus
50                                    drivers. For bus drivers, if this parameter is not NULL, then
51                                    the bus driver must determine if the bus controller specified
52                                    by ControllerHandle and the child controller specified
53                                    by RemainingDevicePath are both supported by this
54                                    bus driver.
55 
56   @retval EFI_SUCCESS              The device specified by ControllerHandle and
57                                    RemainingDevicePath is supported by the driver specified by This.
58   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
59                                    RemainingDevicePath is already being managed by the driver
60                                    specified by This.
61   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
62                                    RemainingDevicePath is already being managed by a different
63                                    driver or an application that requires exclusive access.
64                                    Currently not implemented.
65   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
66                                    RemainingDevicePath is not supported by the driver specified by This.
67 **/
68 EFI_STATUS
69 EFIAPI
Udp6DriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)70 Udp6DriverBindingSupported (
71   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
72   IN EFI_HANDLE                   ControllerHandle,
73   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath  OPTIONAL
74   )
75 {
76   EFI_STATUS  Status;
77   //
78   // Test for the Udp6ServiceBinding Protocol
79   //
80   Status = gBS->OpenProtocol (
81                   ControllerHandle,
82                   &gEfiUdp6ServiceBindingProtocolGuid,
83                   NULL,
84                   This->DriverBindingHandle,
85                   ControllerHandle,
86                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
87                   );
88   if (!EFI_ERROR (Status)) {
89     return EFI_ALREADY_STARTED;
90   }
91   //
92   // Test for the Ip6ServiceBinding Protocol
93   //
94   Status = gBS->OpenProtocol (
95                   ControllerHandle,
96                   &gEfiIp6ServiceBindingProtocolGuid,
97                   NULL,
98                   This->DriverBindingHandle,
99                   ControllerHandle,
100                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
101                   );
102 
103   return Status;
104 }
105 
106 /**
107   Start this driver on ControllerHandle.
108 
109   This service is called by the EFI boot service ConnectController(). In order to make
110   drivers as small as possible, there are a few calling restrictions for
111   this service. ConnectController() must follow these
112   calling restrictions. If any other agent wishes to call Start() it
113   must also follow these calling restrictions.
114 
115   @param[in]  This                   Protocol instance pointer.
116   @param[in]  ControllerHandle       Handle of device to bind the driver to.
117   @param[in]  RemainingDevicePath    Optional parameter use to pick a specific child
118                                      device to start.
119 
120   @retval EFI_SUCCESS            This driver is added to ControllerHandle.
121   @retval EFI_OUT_OF_RESOURCES   The required system resource can't be allocated.
122   @retval other                  This driver does not support this device.
123 
124 **/
125 EFI_STATUS
126 EFIAPI
Udp6DriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)127 Udp6DriverBindingStart (
128   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
129   IN EFI_HANDLE                   ControllerHandle,
130   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath  OPTIONAL
131   )
132 {
133   EFI_STATUS         Status;
134   UDP6_SERVICE_DATA  *Udp6Service;
135 
136   //
137   // Allocate Private Context Data Structure.
138   //
139   Udp6Service = AllocateZeroPool (sizeof (UDP6_SERVICE_DATA));
140   if (Udp6Service == NULL) {
141     Status = EFI_OUT_OF_RESOURCES;
142     goto EXIT;
143   }
144 
145   Status = Udp6CreateService (Udp6Service, This->DriverBindingHandle, ControllerHandle);
146   if (EFI_ERROR (Status)) {
147     goto EXIT;
148   }
149 
150   //
151   // Install the Udp6ServiceBindingProtocol on the ControllerHandle.
152   //
153   Status = gBS->InstallMultipleProtocolInterfaces (
154                   &ControllerHandle,
155                   &gEfiUdp6ServiceBindingProtocolGuid,
156                   &Udp6Service->ServiceBinding,
157                   NULL
158                   );
159   if (EFI_ERROR (Status)) {
160     Udp6CleanService (Udp6Service);
161   }
162 
163 EXIT:
164   if (EFI_ERROR (Status)) {
165     if (Udp6Service != NULL) {
166       FreePool (Udp6Service);
167     }
168   }
169   return Status;
170 }
171 
172 /**
173   Callback function which provided by user to remove one node in NetDestroyLinkList process.
174 
175   @param[in]    Entry           The entry to be removed.
176   @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
177 
178   @retval EFI_INVALID_PARAMETER  Entry is NULL or Context is NULL.
179   @retval EFI_SUCCESS            The entry has been removed successfully.
180   @retval Others                 Fail to remove the entry.
181 
182 **/
183 EFI_STATUS
184 EFIAPI
Udp6DestroyChildEntryInHandleBuffer(IN LIST_ENTRY * Entry,IN VOID * Context)185 Udp6DestroyChildEntryInHandleBuffer (
186   IN LIST_ENTRY         *Entry,
187   IN VOID               *Context
188   )
189 {
190   UDP6_INSTANCE_DATA            *Instance;
191   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;
192   UINTN                         NumberOfChildren;
193   EFI_HANDLE                    *ChildHandleBuffer;
194 
195   if (Entry == NULL || Context == NULL) {
196     return EFI_INVALID_PARAMETER;
197   }
198 
199   Instance = NET_LIST_USER_STRUCT_S (Entry, UDP6_INSTANCE_DATA, Link, UDP6_INSTANCE_DATA_SIGNATURE);
200   ServiceBinding    = ((UDP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;
201   NumberOfChildren  = ((UDP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;
202   ChildHandleBuffer = ((UDP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;
203 
204   if (!NetIsInHandleBuffer (Instance->ChildHandle, NumberOfChildren, ChildHandleBuffer)) {
205     return EFI_SUCCESS;
206   }
207 
208   return ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHandle);
209 }
210 
211 /**
212   Stop this driver on ControllerHandle.
213 
214   This service is called by the  EFI boot service DisconnectController(). In order to
215   make drivers as small as possible, there are a few calling
216   restrictions for this service. DisconnectController()
217   must follow these calling restrictions. If any other agent wishes
218   to call Stop(), it must also follow these calling restrictions.
219 
220   @param[in]  This                   Protocol instance pointer.
221   @param[in]  ControllerHandle       Handle of device to stop the driver on.
222   @param[in]  NumberOfChildren       Number of Handles in ChildHandleBuffer. If the number
223                                      of children is zero stop the entire bus driver.
224   @param[in]  ChildHandleBuffer      List of Child Handles to Stop. It is optional.
225 
226   @retval EFI_SUCCESS            This driver is removed ControllerHandle.
227   @retval EFI_DEVICE_ERROR       Can't find the NicHandle from the ControllerHandle and specified GUID.
228   @retval other                  This driver was not removed from this device.
229 
230 **/
231 EFI_STATUS
232 EFIAPI
Udp6DriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer OPTIONAL)233 Udp6DriverBindingStop (
234   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
235   IN  EFI_HANDLE                   ControllerHandle,
236   IN  UINTN                        NumberOfChildren,
237   IN  EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
238   )
239 {
240   EFI_STATUS                                Status;
241   EFI_HANDLE                                NicHandle;
242   EFI_SERVICE_BINDING_PROTOCOL              *ServiceBinding;
243   UDP6_SERVICE_DATA                         *Udp6Service;
244   LIST_ENTRY                                *List;
245   UDP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT  Context;
246 
247   //
248   // Find the NicHandle where UDP6 ServiceBinding Protocol is installed.
249   //
250   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp6ProtocolGuid);
251   if (NicHandle == NULL) {
252     return EFI_SUCCESS;
253   }
254 
255   //
256   // Retrieve the UDP6 ServiceBinding Protocol.
257   //
258   Status = gBS->OpenProtocol (
259                   NicHandle,
260                   &gEfiUdp6ServiceBindingProtocolGuid,
261                   (VOID **) &ServiceBinding,
262                   This->DriverBindingHandle,
263                   NicHandle,
264                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
265                   );
266   if (EFI_ERROR (Status)) {
267     return EFI_DEVICE_ERROR;
268   }
269 
270   Udp6Service = UDP6_SERVICE_DATA_FROM_THIS (ServiceBinding);
271 
272   if (NumberOfChildren != 0) {
273     //
274     // NumberOfChildren is not zero, destroy the children instances in ChildHandleBuffer.
275     //
276     List = &Udp6Service->ChildrenList;
277     Context.ServiceBinding    = ServiceBinding;
278     Context.NumberOfChildren  = NumberOfChildren;
279     Context.ChildHandleBuffer = ChildHandleBuffer;
280     Status = NetDestroyLinkList (
281                List,
282                Udp6DestroyChildEntryInHandleBuffer,
283                &Context,
284                NULL
285                );
286   } else if (IsListEmpty (&Udp6Service->ChildrenList)) {
287     Status = gBS->UninstallMultipleProtocolInterfaces (
288                NicHandle,
289                &gEfiUdp6ServiceBindingProtocolGuid,
290                &Udp6Service->ServiceBinding,
291                NULL
292                );
293 
294     Udp6CleanService (Udp6Service);
295     FreePool (Udp6Service);
296   }
297 
298   return Status;
299 }
300 
301 /**
302   Creates a child handle and installs a protocol.
303 
304   The CreateChild() function installs a protocol on ChildHandle.
305   If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
306   If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
307 
308   @param[in]       This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
309   @param[in, out]  ChildHandle Pointer to the handle of the child to create. If it is NULL,
310                                then a new handle is created. If it is a pointer to an existing UEFI handle,
311                                then the protocol is added to the existing UEFI handle.
312 
313   @retval EFI_SUCCESS           The protocol was added to ChildHandle.
314   @retval EFI_INVALID_PARAMETER This is NULL or ChildHandle is NULL.
315   @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to create
316                                 the child.
317   @retval other                 The child handle was not created.
318 
319 **/
320 EFI_STATUS
321 EFIAPI
Udp6ServiceBindingCreateChild(IN EFI_SERVICE_BINDING_PROTOCOL * This,IN OUT EFI_HANDLE * ChildHandle)322 Udp6ServiceBindingCreateChild (
323   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
324   IN OUT EFI_HANDLE                *ChildHandle
325   )
326 {
327   EFI_STATUS          Status;
328   UDP6_SERVICE_DATA   *Udp6Service;
329   UDP6_INSTANCE_DATA  *Instance;
330   EFI_TPL             OldTpl;
331   VOID                *Ip6;
332 
333   if ((This == NULL) || (ChildHandle == NULL)) {
334     return EFI_INVALID_PARAMETER;
335   }
336 
337   Udp6Service = UDP6_SERVICE_DATA_FROM_THIS (This);
338 
339   //
340   // Allocate the instance private data structure.
341   //
342   Instance = AllocateZeroPool (sizeof (UDP6_INSTANCE_DATA));
343   if (Instance == NULL) {
344     return EFI_OUT_OF_RESOURCES;
345   }
346 
347   Udp6InitInstance (Udp6Service, Instance);
348 
349   //
350   // Add an IpInfo for this instance.
351   //
352   Instance->IpInfo = IpIoAddIp (Udp6Service->IpIo);
353   if (Instance->IpInfo == NULL) {
354     Status = EFI_OUT_OF_RESOURCES;
355     goto ON_ERROR;
356   }
357 
358   //
359   // Install the Udp6Protocol for this instance.
360   //
361   Status = gBS->InstallMultipleProtocolInterfaces (
362                   ChildHandle,
363                   &gEfiUdp6ProtocolGuid,
364                   &Instance->Udp6Proto,
365                   NULL
366                   );
367   if (EFI_ERROR (Status)) {
368     goto ON_ERROR;
369   }
370 
371   Instance->ChildHandle = *ChildHandle;
372 
373   //
374   // Open the default Ip6 protocol in the IP_IO BY_CHILD.
375   //
376   Status = gBS->OpenProtocol (
377                   Udp6Service->IpIo->ChildHandle,
378                   &gEfiIp6ProtocolGuid,
379                   (VOID **) &Ip6,
380                   gUdp6DriverBinding.DriverBindingHandle,
381                   Instance->ChildHandle,
382                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
383                   );
384   if (EFI_ERROR (Status)) {
385     goto ON_ERROR;
386   }
387 
388   //
389   // Open this instance's Ip6 protocol in the IpInfo BY_CHILD.
390   //
391   Status = gBS->OpenProtocol (
392                   Instance->IpInfo->ChildHandle,
393                   &gEfiIp6ProtocolGuid,
394                   (VOID **) &Ip6,
395                   gUdp6DriverBinding.DriverBindingHandle,
396                   Instance->ChildHandle,
397                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
398                   );
399   if (EFI_ERROR (Status)) {
400     goto ON_ERROR;
401   }
402 
403   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
404 
405   //
406   // Link this instance into the service context data and increase the ChildrenNumber.
407   //
408   InsertTailList (&Udp6Service->ChildrenList, &Instance->Link);
409   Udp6Service->ChildrenNumber++;
410 
411   gBS->RestoreTPL (OldTpl);
412 
413   return EFI_SUCCESS;
414 
415 ON_ERROR:
416 
417   if (Instance->ChildHandle != NULL) {
418     gBS->UninstallMultipleProtocolInterfaces (
419            Instance->ChildHandle,
420            &gEfiUdp6ProtocolGuid,
421            &Instance->Udp6Proto,
422            NULL
423            );
424   }
425 
426   if (Instance->IpInfo != NULL) {
427     IpIoRemoveIp (Udp6Service->IpIo, Instance->IpInfo);
428   }
429 
430   Udp6CleanInstance (Instance);
431 
432   FreePool (Instance);
433 
434   return Status;
435 }
436 
437 /**
438   Destroys a child handle with a set of I/O services.
439   The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
440   that was installed by CreateChild() from ChildHandle. If the removed protocol is the
441   last protocol on ChildHandle, then ChildHandle is destroyed.
442 
443   @param[in]  This               Protocol instance pointer.
444   @param[in]  ChildHandle        Handle of the child to destroy.
445 
446   @retval EFI_SUCCESS            The I/O services were removed from the child
447                                  handle.
448   @retval EFI_UNSUPPORTED        The child handle does not support the I/O services
449                                  that are being removed.
450   @retval EFI_INVALID_PARAMETER  Child handle is NULL.
451   @retval EFI_ACCESS_DENIED      The child handle could not be destroyed because
452                                  its  I/O services are being used.
453   @retval other                  The child handle was not destroyed.
454 
455 **/
456 EFI_STATUS
457 EFIAPI
Udp6ServiceBindingDestroyChild(IN EFI_SERVICE_BINDING_PROTOCOL * This,IN EFI_HANDLE ChildHandle)458 Udp6ServiceBindingDestroyChild (
459   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
460   IN EFI_HANDLE                    ChildHandle
461   )
462 {
463   EFI_STATUS          Status;
464   UDP6_SERVICE_DATA   *Udp6Service;
465   EFI_UDP6_PROTOCOL   *Udp6Proto;
466   UDP6_INSTANCE_DATA  *Instance;
467   EFI_TPL             OldTpl;
468 
469   if ((This == NULL) || (ChildHandle == NULL)) {
470     return EFI_INVALID_PARAMETER;
471   }
472 
473   Udp6Service = UDP6_SERVICE_DATA_FROM_THIS (This);
474 
475   //
476   // Try to get the Udp6 protocol from the ChildHandle.
477   //
478   Status = gBS->OpenProtocol (
479                   ChildHandle,
480                   &gEfiUdp6ProtocolGuid,
481                   (VOID **) &Udp6Proto,
482                   gUdp6DriverBinding.DriverBindingHandle,
483                   ChildHandle,
484                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
485                   );
486   if (EFI_ERROR (Status)) {
487     return EFI_UNSUPPORTED;
488   }
489 
490   Instance = UDP6_INSTANCE_DATA_FROM_THIS (Udp6Proto);
491 
492   if (Instance->InDestroy) {
493     return EFI_SUCCESS;
494   }
495 
496   //
497   // Use the Destroyed flag to avoid the re-entering of the following code.
498   //
499   Instance->InDestroy = TRUE;
500 
501   //
502   // Close the Ip6 protocol on the default IpIo.
503   //
504   Status = gBS->CloseProtocol (
505              Udp6Service->IpIo->ChildHandle,
506              &gEfiIp6ProtocolGuid,
507              gUdp6DriverBinding.DriverBindingHandle,
508              Instance->ChildHandle
509              );
510   if (EFI_ERROR (Status)) {
511     Instance->InDestroy = FALSE;
512     return Status;
513   }
514 
515   //
516   // Close the Ip6 protocol on this instance's IpInfo.
517   //
518   Status = gBS->CloseProtocol (
519              Instance->IpInfo->ChildHandle,
520              &gEfiIp6ProtocolGuid,
521              gUdp6DriverBinding.DriverBindingHandle,
522              Instance->ChildHandle
523              );
524   if (EFI_ERROR (Status)) {
525     Instance->InDestroy = FALSE;
526     return Status;
527   }
528 
529   //
530   // Uninstall the Udp6Protocol previously installed on the ChildHandle.
531   //
532   Status = gBS->UninstallMultipleProtocolInterfaces (
533                   ChildHandle,
534                   &gEfiUdp6ProtocolGuid,
535                   (VOID *) &Instance->Udp6Proto,
536                   NULL
537                   );
538   if (EFI_ERROR (Status)) {
539     Instance->InDestroy = FALSE;
540     return Status;
541   }
542 
543   //
544   // Reset the configuration in case the instance's consumer forgets to do this.
545   //
546   Udp6Proto->Configure (Udp6Proto, NULL);
547 
548   //
549   // Remove the IpInfo this instance consumes.
550   //
551   IpIoRemoveIp (Udp6Service->IpIo, Instance->IpInfo);
552 
553   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
554 
555   //
556   // Remove this instance from the service context data's ChildrenList.
557   //
558   RemoveEntryList (&Instance->Link);
559   Udp6Service->ChildrenNumber--;
560 
561   //
562   // Clean the instance.
563   //
564   Udp6CleanInstance (Instance);
565 
566   gBS->RestoreTPL (OldTpl);
567 
568   FreePool (Instance);
569 
570   return EFI_SUCCESS;
571 }
572 
573 /**
574   This is the declaration of an EFI image entry point. This entry point is
575   the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
576   both device drivers and bus drivers.
577 
578   The entry point for Udp6 driver that installs the driver binding
579   and component name protocol on its ImageHandle.
580 
581   @param[in] ImageHandle        The firmware allocated handle for the UEFI image.
582   @param[in] SystemTable        A pointer to the EFI System Table.
583 
584   @retval EFI_SUCCESS           The operation completed successfully.
585   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
586 
587 **/
588 EFI_STATUS
589 EFIAPI
Udp6DriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)590 Udp6DriverEntryPoint (
591   IN EFI_HANDLE        ImageHandle,
592   IN EFI_SYSTEM_TABLE  *SystemTable
593   )
594 {
595   EFI_STATUS  Status;
596 
597   //
598   // Install the Udp6DriverBinding and Udp6ComponentName protocols.
599   //
600 
601   Status = EfiLibInstallDriverBindingComponentName2 (
602              ImageHandle,
603              SystemTable,
604              &gUdp6DriverBinding,
605              ImageHandle,
606              &gUdp6ComponentName,
607              &gUdp6ComponentName2
608              );
609   if (!EFI_ERROR (Status)) {
610     //
611     // Initialize the UDP random port.
612     //
613     mUdp6RandomPort = (UINT16)(
614                         ((UINT16) NetRandomInitSeed ()) %
615                          UDP6_PORT_KNOWN +
616                          UDP6_PORT_KNOWN
617                          );
618   }
619 
620   return Status;
621 }
622 
623 
624