]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/Ip6Dxe/Ip6Output.c
Fix a bug about the iSCSI DHCP dependency issue.
[mirror_edk2.git] / NetworkPkg / Ip6Dxe / Ip6Output.c
1 /** @file
2 The internal functions and routines to transmit the IP6 packet.
3
4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "Ip6Impl.h"
17
18 UINT32 mIp6Id;
19
20 /**
21 Output all the available source addresses to a list entry head SourceList. The
22 number of source addresses are also returned.
23
24 @param[in] IpSb Points to an IP6 service binding instance.
25 @param[out] SourceList The list entry head of all source addresses.
26 It is the caller's responsiblity to free the
27 resources.
28 @param[out] SourceCount The number of source addresses.
29
30 @retval EFI_SUCCESS The source addresses were copied to a list entry head
31 SourceList.
32 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
33
34 **/
35 EFI_STATUS
36 Ip6CandidateSource (
37 IN IP6_SERVICE *IpSb,
38 OUT LIST_ENTRY *SourceList,
39 OUT UINT32 *SourceCount
40 )
41 {
42 IP6_INTERFACE *IpIf;
43 LIST_ENTRY *Entry;
44 LIST_ENTRY *Entry2;
45 IP6_ADDRESS_INFO *AddrInfo;
46 IP6_ADDRESS_INFO *Copy;
47
48 *SourceCount = 0;
49
50 if (IpSb->LinkLocalOk) {
51 Copy = AllocatePool (sizeof (IP6_ADDRESS_INFO));
52 if (Copy == NULL) {
53 return EFI_OUT_OF_RESOURCES;
54 }
55
56 Copy->Signature = IP6_ADDR_INFO_SIGNATURE;
57 IP6_COPY_ADDRESS (&Copy->Address, &IpSb->LinkLocalAddr);
58 Copy->IsAnycast = FALSE;
59 Copy->PrefixLength = IP6_LINK_LOCAL_PREFIX_LENGTH;
60 Copy->ValidLifetime = (UINT32) IP6_INFINIT_LIFETIME;
61 Copy->PreferredLifetime = (UINT32) IP6_INFINIT_LIFETIME;
62
63 InsertTailList (SourceList, &Copy->Link);
64 (*SourceCount)++;
65 }
66
67 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
68 IpIf = NET_LIST_USER_STRUCT (Entry, IP6_INTERFACE, Link);
69
70 NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) {
71 AddrInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
72
73 if (AddrInfo->IsAnycast) {
74 //
75 // Never use an anycast address.
76 //
77 continue;
78 }
79
80 Copy = AllocateCopyPool (sizeof (IP6_ADDRESS_INFO), AddrInfo);
81 if (Copy == NULL) {
82 return EFI_OUT_OF_RESOURCES;
83 }
84
85 InsertTailList (SourceList, &Copy->Link);
86 (*SourceCount)++;
87 }
88 }
89
90 return EFI_SUCCESS;
91 }
92
93 /**
94 Caculate how many bits are the same between two IPv6 addresses.
95
96 @param[in] AddressA Points to an IPv6 address.
97 @param[in] AddressB Points to another IPv6 address.
98
99 @return The common bits of the AddressA and AddressB.
100
101 **/
102 UINT8
103 Ip6CommonPrefixLen (
104 IN EFI_IPv6_ADDRESS *AddressA,
105 IN EFI_IPv6_ADDRESS *AddressB
106 )
107 {
108 UINT8 Count;
109 UINT8 Index;
110 UINT8 ByteA;
111 UINT8 ByteB;
112 UINT8 NumBits;
113
114 Count = 0;
115 Index = 0;
116
117 while (Index < 16) {
118 ByteA = AddressA->Addr[Index];
119 ByteB = AddressB->Addr[Index];
120
121 if (ByteA == ByteB) {
122 Count += 8;
123 Index++;
124 continue;
125 }
126
127 //
128 // Check how many bits are common between the two bytes.
129 //
130 NumBits = 8;
131 ByteA = (UINT8) (ByteA ^ ByteB);
132
133 while (ByteA != 0) {
134 NumBits--;
135 ByteA = (UINT8) (ByteA >> 1);
136 }
137
138 return (UINT8) (Count + NumBits);
139 }
140
141 return Count;
142 }
143
144 /**
145 Output all the available source addresses to a list entry head SourceList. The
146 number of source addresses are also returned.
147
148 @param[in] IpSb Points to a IP6 service binding instance.
149 @param[in] Destination The IPv6 destination address.
150 @param[out] Source The selected IPv6 source address according to
151 the Destination.
152
153 @retval EFI_SUCCESS The source addresses were copied to a list entry
154 head SourceList.
155 @retval EFI_NO_MAPPING The IPv6 stack is not auto configured.
156
157 **/
158 EFI_STATUS
159 Ip6SelectSourceAddress (
160 IN IP6_SERVICE *IpSb,
161 IN EFI_IPv6_ADDRESS *Destination,
162 OUT EFI_IPv6_ADDRESS *Source
163 )
164 {
165 EFI_STATUS Status;
166 LIST_ENTRY SourceList;
167 UINT32 SourceCount;
168 UINT8 ScopeD;
169 LIST_ENTRY *Entry;
170 IP6_ADDRESS_INFO *AddrInfo;
171 IP6_PREFIX_LIST_ENTRY *Prefix;
172 UINT8 LastCommonLength;
173 UINT8 CurrentCommonLength;
174 EFI_IPv6_ADDRESS *TmpAddress;
175
176 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
177
178 Status = EFI_SUCCESS;
179 InitializeListHead (&SourceList);
180
181 if (!IpSb->LinkLocalOk) {
182 return EFI_NO_MAPPING;
183 }
184
185 //
186 // Rule 1: Prefer same address.
187 //
188 if (Ip6IsOneOfSetAddress (IpSb, Destination, NULL, NULL)) {
189 IP6_COPY_ADDRESS (Source, Destination);
190 goto Exit;
191 }
192
193 //
194 // Rule 2: Prefer appropriate scope.
195 //
196 if (IP6_IS_MULTICAST (Destination)) {
197 ScopeD = (UINT8) (Destination->Addr[1] >> 4);
198 } else if (NetIp6IsLinkLocalAddr (Destination)) {
199 ScopeD = 0x2;
200 } else {
201 ScopeD = 0xE;
202 }
203
204 if (ScopeD <= 0x2) {
205 //
206 // Return the link-local address if it exists
207 // One IP6_SERVICE only has one link-local address.
208 //
209 IP6_COPY_ADDRESS (Source, &IpSb->LinkLocalAddr);
210 goto Exit;
211 }
212
213 //
214 // All candidate source addresses are global unicast address.
215 //
216 Ip6CandidateSource (IpSb, &SourceList, &SourceCount);
217
218 if (SourceCount == 0) {
219 Status = EFI_NO_MAPPING;
220 goto Exit;
221 }
222
223 IP6_COPY_ADDRESS (Source, &IpSb->LinkLocalAddr);
224
225 if (SourceCount == 1) {
226 goto Exit;
227 }
228
229 //
230 // Rule 3: Avoid deprecated addresses.
231 // TODO: check the "deprecated" state of the stateful configured address
232 //
233 NET_LIST_FOR_EACH (Entry, &IpSb->AutonomousPrefix) {
234 Prefix = NET_LIST_USER_STRUCT (Entry, IP6_PREFIX_LIST_ENTRY, Link);
235 if (Prefix->PreferredLifetime == 0) {
236 Ip6RemoveAddr (NULL, &SourceList, &SourceCount, &Prefix->Prefix, Prefix->PrefixLength);
237
238 if (SourceCount == 1) {
239 goto Exit;
240 }
241 }
242 }
243
244 //
245 // TODO: Rule 4: Prefer home addresses.
246 // TODO: Rule 5: Prefer outgoing interface.
247 // TODO: Rule 6: Prefer matching label.
248 // TODO: Rule 7: Prefer public addresses.
249 //
250
251 //
252 // Rule 8: Use longest matching prefix.
253 //
254 LastCommonLength = Ip6CommonPrefixLen (Source, Destination);
255 TmpAddress = NULL;
256
257 for (Entry = SourceList.ForwardLink; Entry != &SourceList; Entry = Entry->ForwardLink) {
258 AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);
259
260 CurrentCommonLength = Ip6CommonPrefixLen (&AddrInfo->Address, Destination);
261 if (CurrentCommonLength > LastCommonLength) {
262 LastCommonLength = CurrentCommonLength;
263 TmpAddress = &AddrInfo->Address;
264 }
265 }
266
267 if (TmpAddress != NULL) {
268 IP6_COPY_ADDRESS (Source, TmpAddress);
269 }
270
271 Exit:
272
273 Ip6RemoveAddr (NULL, &SourceList, &SourceCount, NULL, 0);
274
275 return Status;
276 }
277
278 /**
279 Select an interface to send the packet generated in the IP6 driver
280 itself: that is, not by the requests of the IP6 child's consumer. Such
281 packets include the ICMPv6 echo replies and other ICMPv6 error packets.
282
283 @param[in] IpSb The IP4 service that wants to send the packets.
284 @param[in] Destination The destination of the packet.
285 @param[in, out] Source The source of the packet.
286
287 @return NULL if no proper interface is found, otherwise, the interface that
288 can be used to send the system packet from.
289
290 **/
291 IP6_INTERFACE *
292 Ip6SelectInterface (
293 IN IP6_SERVICE *IpSb,
294 IN EFI_IPv6_ADDRESS *Destination,
295 IN OUT EFI_IPv6_ADDRESS *Source
296 )
297 {
298 EFI_STATUS Status;
299 EFI_IPv6_ADDRESS SelectedSource;
300 IP6_INTERFACE *IpIf;
301 BOOLEAN Exist;
302
303 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
304 ASSERT (Destination != NULL && Source != NULL);
305
306 if (NetIp6IsUnspecifiedAddr (Destination)) {
307 return NULL;
308 }
309
310 if (!NetIp6IsUnspecifiedAddr (Source)) {
311 Exist = Ip6IsOneOfSetAddress (IpSb, Source, &IpIf, NULL);
312 ASSERT (Exist);
313
314 return IpIf;
315 }
316
317 //
318 // If source is unspecified, select a source according to the destination.
319 //
320 Status = Ip6SelectSourceAddress (IpSb, Destination, &SelectedSource);
321 if (EFI_ERROR (Status)) {
322 return IpSb->DefaultInterface;
323 }
324
325 Ip6IsOneOfSetAddress (IpSb, &SelectedSource, &IpIf, NULL);
326 IP6_COPY_ADDRESS (Source, &SelectedSource);
327
328 return IpIf;
329 }
330
331 /**
332 The default callback function for the system generated packet.
333 It will free the packet.
334
335 @param[in] Packet The packet that transmitted.
336 @param[in] IoStatus The result of the transmission, succeeded or failed.
337 @param[in] LinkFlag Not used when transmitted. Check IP6_FRAME_CALLBACK
338 for reference.
339 @param[in] Context The context provided by us.
340
341 **/
342 VOID
343 Ip6SysPacketSent (
344 NET_BUF *Packet,
345 EFI_STATUS IoStatus,
346 UINT32 LinkFlag,
347 VOID *Context
348 )
349 {
350 NetbufFree (Packet);
351 Packet = NULL;
352 }
353
354 /**
355 Prefix an IP6 basic head and unfragmentable extension headers and a fragment header
356 to the Packet. Used for IP6 fragmentation.
357
358 @param[in] IpSb The IP6 service instance to transmit the packet.
359 @param[in] Packet The packet to prefix the IP6 header to.
360 @param[in] Head The caller supplied header.
361 @param[in] FragmentOffset The fragment offset of the data following the header.
362 @param[in] ExtHdrs The length of the original extension header.
363 @param[in] ExtHdrsLen The length of the extension headers.
364 @param[in] LastHeader The pointer of next header of last extension header.
365 @param[in] HeadLen The length of the unfragmented part of the IP6 header.
366
367 @retval EFI_BAD_BUFFER_SIZE There is no enought room in the head space of
368 Packet.
369 @retval EFI_SUCCESS The operation performed successfully.
370
371 **/
372 EFI_STATUS
373 Ip6PrependHead (
374 IN IP6_SERVICE *IpSb,
375 IN NET_BUF *Packet,
376 IN EFI_IP6_HEADER *Head,
377 IN UINT16 FragmentOffset,
378 IN UINT8 *ExtHdrs,
379 IN UINT32 ExtHdrsLen,
380 IN UINT8 LastHeader,
381 IN UINT32 HeadLen
382 )
383 {
384 UINT32 Len;
385 UINT32 UnFragExtHdrsLen;
386 EFI_IP6_HEADER *PacketHead;
387 UINT8 *UpdatedExtHdrs;
388 EFI_STATUS Status;
389 UINT8 NextHeader;
390
391 //
392 // HeadLen is the length of the fixed part of the sequences of fragments, i.e.
393 // the unfragment part.
394 //
395 PacketHead = (EFI_IP6_HEADER *) NetbufAllocSpace (Packet, HeadLen, NET_BUF_HEAD);
396 if (PacketHead == NULL) {
397 return EFI_BAD_BUFFER_SIZE;
398 }
399
400 //
401 // Set the head up, convert the host byte order to network byte order
402 //
403 CopyMem (PacketHead, Head, sizeof (EFI_IP6_HEADER));
404 PacketHead->PayloadLength = HTONS ((UINT16) (Packet->TotalSize - sizeof (EFI_IP6_HEADER)));
405 Packet->Ip.Ip6 = PacketHead;
406
407 Len = HeadLen - sizeof (EFI_IP6_HEADER);
408 UnFragExtHdrsLen = Len - sizeof (IP6_FRAGMENT_HEADER);
409
410 if (UnFragExtHdrsLen == 0) {
411 PacketHead->NextHeader = IP6_FRAGMENT;
412 }
413
414 //
415 // Append the extension headers: firstly copy the unfragmentable headers, then append
416 // fragmentation header.
417 //
418 if ((FragmentOffset & IP6_FRAGMENT_OFFSET_MASK) == 0) {
419 NextHeader = Head->NextHeader;
420 } else {
421 NextHeader = PacketHead->NextHeader;
422 }
423
424 Status = Ip6FillFragmentHeader (
425 IpSb,
426 NextHeader,
427 LastHeader,
428 ExtHdrs,
429 ExtHdrsLen,
430 FragmentOffset,
431 &UpdatedExtHdrs
432 );
433 if (EFI_ERROR (Status)) {
434 return Status;
435 }
436
437 CopyMem (
438 (UINT8 *) (PacketHead + 1),
439 UpdatedExtHdrs,
440 UnFragExtHdrsLen + sizeof (IP6_FRAGMENT_HEADER)
441 );
442
443 FreePool (UpdatedExtHdrs);
444 return EFI_SUCCESS;
445 }
446
447 /**
448 Transmit an IP6 packet. The packet comes either from the IP6
449 child's consumer (IpInstance != NULL) or the IP6 driver itself
450 (IpInstance == NULL). It will route the packet, fragment it,
451 then transmit all the fragments through an interface.
452
453 @param[in] IpSb The IP6 service instance to transmit the packet.
454 @param[in] Interface The IP6 interface to transmit the packet. Ignored
455 if NULL.
456 @param[in] IpInstance The IP6 child that issues the transmission. It is
457 NULL if the packet is from the system.
458 @param[in] Packet The user data to send, excluding the IP header.
459 @param[in] Head The caller supplied header. The caller should set
460 the following header fields: NextHeader, HopLimit,
461 Src, Dest, FlowLabel, PayloadLength. This function
462 will fill in the Ver, TrafficClass.
463 @param[in] ExtHdrs The extension headers to append to the IPv6 basic
464 header.
465 @param[in] ExtHdrsLen The length of the extension headers.
466 @param[in] Callback The callback function to issue when transmission
467 completed.
468 @param[in] Context The opaque context for the callback.
469
470 @retval EFI_INVALID_PARAMETER Any input parameter or the packet is invalid.
471 @retval EFI_NO_MAPPING There is no interface to the destination.
472 @retval EFI_NOT_FOUND There is no route to the destination.
473 @retval EFI_SUCCESS The packet successfully transmitted.
474 @retval EFI_OUT_OF_RESOURCES Failed to finish the operation due to lack of
475 resources.
476 @retval Others Failed to transmit the packet.
477
478 **/
479 EFI_STATUS
480 Ip6Output (
481 IN IP6_SERVICE *IpSb,
482 IN IP6_INTERFACE *Interface OPTIONAL,
483 IN IP6_PROTOCOL *IpInstance OPTIONAL,
484 IN NET_BUF *Packet,
485 IN EFI_IP6_HEADER *Head,
486 IN UINT8 *ExtHdrs,
487 IN UINT32 ExtHdrsLen,
488 IN IP6_FRAME_CALLBACK Callback,
489 IN VOID *Context
490 )
491 {
492 IP6_INTERFACE *IpIf;
493 EFI_IPv6_ADDRESS NextHop;
494 IP6_NEIGHBOR_ENTRY *NeighborCache;
495 IP6_ROUTE_CACHE_ENTRY *RouteCache;
496 EFI_STATUS Status;
497 UINT32 Mtu;
498 UINT32 HeadLen;
499 UINT16 FragmentOffset;
500 UINT8 *LastHeader;
501 UINT32 UnFragmentLen;
502 UINT32 UnFragmentHdrsLen;
503 UINT32 FragmentHdrsLen;
504 UINT16 *Checksum;
505 UINT16 PacketChecksum;
506 UINT16 PseudoChecksum;
507 UINT32 Index;
508 UINT32 PacketLen;
509 UINT32 RealExtLen;
510 UINT32 Offset;
511 NET_BUF *TmpPacket;
512 NET_BUF *Fragment;
513 UINT32 Num;
514 UINT8 *Buf;
515 EFI_IP6_HEADER *PacketHead;
516 IP6_ICMP_HEAD *IcmpHead;
517 IP6_TXTOKEN_WRAP *Wrap;
518 IP6_ROUTE_ENTRY *RouteEntry;
519 UINT8 *UpdatedExtHdrs;
520 UINT8 NextHeader;
521 UINT8 LastHeaderBackup;
522 BOOLEAN FragmentHeadInserted;
523 UINT8 *ExtHdrsBackup;
524 UINT8 NextHeaderBackup;
525 EFI_IPv6_ADDRESS Source;
526 EFI_IPv6_ADDRESS Destination;
527
528 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
529
530 //
531 // RFC2460: Each extension header is an integer multiple of 8 octets long,
532 // in order to retain 8-octet alignment for subsequent headers.
533 //
534 if ((ExtHdrsLen & 0x7) != 0) {
535 return EFI_INVALID_PARAMETER;
536 }
537
538 LastHeader = NULL;
539
540 Ip6IsExtsValid (
541 NULL,
542 NULL,
543 &Head->NextHeader,
544 ExtHdrs,
545 ExtHdrsLen,
546 FALSE,
547 NULL,
548 &LastHeader,
549 NULL,
550 NULL,
551 NULL
552 );
553
554 //
555 // Select an interface/source for system packet, application
556 // should select them itself.
557 //
558 IpIf = Interface;
559 if (IpIf == NULL) {
560 //
561 // IpInstance->Interface is NULL when IpInstance is configured with both stationaddress
562 // and destinationaddress is unspecified.
563 //
564 if (IpInstance == NULL || IpInstance->Interface == NULL) {
565 IpIf = Ip6SelectInterface (IpSb, &Head->DestinationAddress, &Head->SourceAddress);
566 if (IpInstance != NULL) {
567 IpInstance->Interface = IpIf;
568 }
569 } else {
570 IpIf = IpInstance->Interface;
571 }
572 }
573
574 if (IpIf == NULL) {
575 return EFI_NO_MAPPING;
576 }
577
578 //
579 // Update the common field in Head here.
580 //
581 Head->Version = 6;
582 Head->TrafficClassL = 0;
583 Head->TrafficClassH = 0;
584
585 Checksum = NULL;
586 NextHeader = *LastHeader;
587
588 switch (NextHeader) {
589 case EFI_IP_PROTO_UDP:
590 Packet->Udp = (EFI_UDP_HEADER *) NetbufGetByte (Packet, 0, NULL);
591 ASSERT (Packet->Udp != NULL);
592 if (Packet->Udp->Checksum == 0) {
593 Checksum = &Packet->Udp->Checksum;
594 }
595 break;
596
597 case EFI_IP_PROTO_TCP:
598 Packet->Tcp = (TCP_HEAD *) NetbufGetByte (Packet, 0, NULL);
599 ASSERT (Packet->Tcp != NULL);
600 if (Packet->Tcp->Checksum == 0) {
601 Checksum = &Packet->Tcp->Checksum;
602 }
603 break;
604
605 case IP6_ICMP:
606 //
607 // Don't send ICMP packet to an IPv6 anycast address.
608 //
609 if (Ip6IsAnycast (IpSb, &Head->DestinationAddress)) {
610 return EFI_INVALID_PARAMETER;
611 }
612
613 IcmpHead = (IP6_ICMP_HEAD *) NetbufGetByte (Packet, 0, NULL);
614 ASSERT (IcmpHead != NULL);
615 if (IcmpHead->Checksum == 0) {
616 Checksum = &IcmpHead->Checksum;
617 }
618 break;
619
620 default:
621 break;
622 }
623
624 if (Checksum != NULL) {
625 //
626 // Calculate the checksum for upper layer protocol if it is not calculated due to lack of
627 // IPv6 source address.
628 //
629 PacketChecksum = NetbufChecksum (Packet);
630 PseudoChecksum = NetIp6PseudoHeadChecksum (
631 &Head->SourceAddress,
632 &Head->DestinationAddress,
633 NextHeader,
634 Packet->TotalSize
635 );
636 *Checksum = (UINT16) ~NetAddChecksum (PacketChecksum, PseudoChecksum);
637 }
638
639 Status = Ip6IpSecProcessPacket (
640 IpSb,
641 &Head,
642 LastHeader, // no need get the lasthead value for output
643 &Packet,
644 &ExtHdrs,
645 &ExtHdrsLen,
646 EfiIPsecOutBound,
647 Context
648 );
649
650 if (EFI_ERROR(Status)) {
651 return Status;
652 }
653
654 LastHeader = NULL;
655 //
656 // Check incoming parameters.
657 //
658 if (!Ip6IsExtsValid (
659 IpSb,
660 Packet,
661 &Head->NextHeader,
662 ExtHdrs,
663 ExtHdrsLen,
664 FALSE,
665 NULL,
666 &LastHeader,
667 &RealExtLen,
668 &UnFragmentHdrsLen,
669 NULL
670 )) {
671 return EFI_INVALID_PARAMETER;
672 }
673
674 if ((RealExtLen & 0x7) != 0) {
675 return EFI_INVALID_PARAMETER;
676 }
677
678 LastHeaderBackup = *LastHeader;
679
680 //
681 // Perform next hop determination:
682 // For multicast packets, the next-hop is always the destination address and
683 // is considered to be on-link.
684 //
685 if (IP6_IS_MULTICAST (&Head->DestinationAddress)) {
686 IP6_COPY_ADDRESS (&NextHop, &Head->DestinationAddress);
687 } else {
688 //
689 // For unicast packets, use a combination of the Destination Cache, the Prefix List
690 // and the Default Router List to determine the IP address of the appropriate next hop.
691 //
692
693 NeighborCache = Ip6FindNeighborEntry (IpSb, &Head->DestinationAddress);
694 if (NeighborCache != NULL) {
695 //
696 // Hit Neighbor Cache.
697 //
698 IP6_COPY_ADDRESS (&NextHop, &Head->DestinationAddress);
699 } else {
700 //
701 // Not in Neighbor Cache, check Router cache
702 //
703 RouteCache = Ip6Route (IpSb, &Head->DestinationAddress, &Head->SourceAddress);
704 if (RouteCache == NULL) {
705 return EFI_NOT_FOUND;
706 }
707
708 IP6_COPY_ADDRESS (&NextHop, &RouteCache->NextHop);
709 Ip6FreeRouteCacheEntry (RouteCache);
710 }
711 }
712
713 //
714 // Examines the Neighbor Cache for link-layer information about that neighbor.
715 // DO NOT create neighbor cache if neighbor is itself - when reporting ICMP error.
716 //
717 if (!IP6_IS_MULTICAST (&NextHop) && !EFI_IP6_EQUAL (&Head->DestinationAddress, &Head->SourceAddress)) {
718 NeighborCache = Ip6FindNeighborEntry (IpSb, &NextHop);
719 if (NeighborCache == NULL) {
720 NeighborCache = Ip6CreateNeighborEntry (IpSb, Ip6OnArpResolved, &NextHop, NULL);
721
722 if (NeighborCache == NULL) {
723 return EFI_OUT_OF_RESOURCES;
724 }
725
726 //
727 // Send out multicast neighbor solicitation for address resolution immediatly.
728 //
729 Ip6CreateSNMulticastAddr (&NeighborCache->Neighbor, &Destination);
730 Status = Ip6SelectSourceAddress (IpSb, &NeighborCache->Neighbor, &Source);
731 if (EFI_ERROR (Status)) {
732 return Status;
733 }
734
735 Status = Ip6SendNeighborSolicit (
736 IpSb,
737 &Source,
738 &Destination,
739 &NeighborCache->Neighbor,
740 &IpSb->SnpMode.CurrentAddress
741 );
742 if (EFI_ERROR (Status)) {
743 return Status;
744 }
745
746 --NeighborCache->Transmit;
747 NeighborCache->Ticks = IP6_GET_TICKS (IpSb->RetransTimer) + 1;
748 }
749
750 NeighborCache->Interface = IpIf;
751 }
752
753 UpdatedExtHdrs = NULL;
754 ExtHdrsBackup = NULL;
755 NextHeaderBackup = 0;
756 FragmentHeadInserted = FALSE;
757
758 //
759 // Check whether we received Packet Too Big message for the packet sent to the
760 // Destination. If yes include a Fragment Header in the subsequent packets.
761 //
762 RouteEntry = Ip6FindRouteEntry (
763 IpSb->RouteTable,
764 &Head->DestinationAddress,
765 NULL
766 );
767 if (RouteEntry != NULL) {
768 if ((RouteEntry->Flag & IP6_PACKET_TOO_BIG) == IP6_PACKET_TOO_BIG) {
769
770 //
771 // FragmentHead is inserted after Hop-by-Hop Options header, Destination
772 // Options header (first occur), Routing header, and before Fragment header,
773 // Authentication header, Encapsulating Security Payload header, and
774 // Destination Options header (last occur), and upper-layer header.
775 //
776 Status = Ip6FillFragmentHeader (
777 IpSb,
778 Head->NextHeader,
779 LastHeaderBackup,
780 ExtHdrs,
781 ExtHdrsLen,
782 0,
783 &UpdatedExtHdrs
784 );
785 if (EFI_ERROR (Status)) {
786 return Status;
787 }
788
789 if ((ExtHdrs == NULL) && (ExtHdrsLen == 0)) {
790 NextHeaderBackup = Head->NextHeader;
791 Head->NextHeader = IP6_FRAGMENT;
792 }
793
794 ExtHdrsBackup = ExtHdrs;
795 ExtHdrs = UpdatedExtHdrs;
796 ExtHdrsLen = ExtHdrsLen + sizeof (IP6_FRAGMENT_HEADER);
797 RealExtLen = RealExtLen + sizeof (IP6_FRAGMENT_HEADER);
798
799 mIp6Id++;
800
801 FragmentHeadInserted = TRUE;
802 }
803
804 Ip6FreeRouteEntry (RouteEntry);
805 }
806
807 //
808 // OK, selected the source and route, fragment the packet then send
809 // them. Tag each fragment other than the first one as spawn from it.
810 // Each extension header is an integar multiple of 8 octets long, in
811 // order to retain 8-octet alignment for subsequent headers.
812 //
813 Mtu = IpSb->MaxPacketSize + sizeof (EFI_IP6_HEADER);
814 HeadLen = sizeof (EFI_IP6_HEADER) + RealExtLen;
815
816 if (Packet->TotalSize + HeadLen > Mtu) {
817 //
818 // Remove the inserted Fragment Header since we need fragment the packet.
819 //
820 if (FragmentHeadInserted) {
821 ExtHdrs = ExtHdrsBackup;
822 ExtHdrsLen = ExtHdrsLen - sizeof (IP6_FRAGMENT_HEADER);
823
824 if ((ExtHdrs == NULL) && (ExtHdrsLen == 0)) {
825 Head->NextHeader = NextHeaderBackup;
826 }
827 }
828
829 FragmentHdrsLen = ExtHdrsLen - UnFragmentHdrsLen;
830
831 //
832 // The packet is beyond the maximum which can be described through the
833 // fragment offset field in Fragment header.
834 //
835 if ((((Packet->TotalSize + FragmentHdrsLen) >> 3) & (~0x1fff)) != 0) {
836 Status = EFI_BAD_BUFFER_SIZE;
837 goto Error;
838 }
839
840 if (FragmentHdrsLen != 0) {
841 //
842 // Append the fragmentable extension hdrs before the upper layer payload
843 // to form a new NET_BUF. This NET_BUF contains all the buffer which will
844 // be fragmented below.
845 //
846 TmpPacket = NetbufGetFragment (Packet, 0, Packet->TotalSize, FragmentHdrsLen);
847 ASSERT (TmpPacket != NULL);
848
849 //
850 // Allocate the space to contain the fragmentable hdrs and copy the data.
851 //
852 Buf = NetbufAllocSpace (TmpPacket, FragmentHdrsLen, TRUE);
853 ASSERT (Buf != NULL);
854 CopyMem (Buf, ExtHdrs + UnFragmentHdrsLen, FragmentHdrsLen);
855
856 //
857 // Free the old Packet.
858 //
859 NetbufFree (Packet);
860 Packet = TmpPacket;
861 }
862
863 //
864 // The unfragment part which appears in every fragmented IPv6 packet includes
865 // the IPv6 header, the unfragmentable extension hdrs and the fragment header.
866 //
867 UnFragmentLen = sizeof (EFI_IP6_HEADER) + UnFragmentHdrsLen + sizeof (IP6_FRAGMENT_HEADER);
868
869 //
870 // Mtu now is the length of the fragment part in a full-length fragment.
871 //
872 Mtu = (Mtu - UnFragmentLen) & (~0x07);
873 Num = (Packet->TotalSize + Mtu - 1) / Mtu;
874
875 for (Index = 0, Offset = 0, PacketLen = Mtu; Index < Num; Index++) {
876 //
877 // Get fragment from the Packet, append UnFragnmentLen spare buffer
878 // before the fragmented data, the corresponding data is filled in later.
879 //
880 Fragment = NetbufGetFragment (Packet, Offset, PacketLen, UnFragmentLen);
881 if (Fragment == NULL) {
882 Status = EFI_OUT_OF_RESOURCES;
883 goto Error;
884 }
885
886 FragmentOffset = (UINT16) ((UINT16) Offset | 0x1);
887 if (Index == Num - 1){
888 //
889 // The last fragment, clear the M flag.
890 //
891 FragmentOffset &= (~0x1);
892 }
893
894 Status = Ip6PrependHead (
895 IpSb,
896 Fragment,
897 Head,
898 FragmentOffset,
899 ExtHdrs,
900 ExtHdrsLen,
901 LastHeaderBackup,
902 UnFragmentLen
903 );
904 ASSERT (Status == EFI_SUCCESS);
905
906 Status = Ip6SendFrame (
907 IpIf,
908 IpInstance,
909 Fragment,
910 &NextHop,
911 Ip6SysPacketSent,
912 Packet
913 );
914 if (EFI_ERROR (Status)) {
915 goto Error;
916 }
917
918 //
919 // The last fragment of upper layer packet, update the IP6 token status.
920 //
921 if ((Index == Num -1) && (Context != NULL)) {
922 Wrap = (IP6_TXTOKEN_WRAP *) Context;
923 Wrap->Token->Status = Status;
924 }
925
926 Offset += PacketLen;
927 PacketLen = Packet->TotalSize - Offset;
928 if (PacketLen > Mtu) {
929 PacketLen = Mtu;
930 }
931 }
932
933 NetbufFree (Packet);
934 mIp6Id++;
935
936 if (UpdatedExtHdrs != NULL) {
937 FreePool (UpdatedExtHdrs);
938 }
939
940 return EFI_SUCCESS;
941 }
942
943 //
944 // Need not fragment the packet, send it in one frame.
945 //
946 PacketHead = (EFI_IP6_HEADER *) NetbufAllocSpace (Packet, HeadLen, NET_BUF_HEAD);
947 if (PacketHead == NULL) {
948 Status = EFI_BAD_BUFFER_SIZE;
949 goto Error;
950 }
951
952 CopyMem (PacketHead, Head, sizeof (EFI_IP6_HEADER));
953 Packet->Ip.Ip6 = PacketHead;
954
955 if (ExtHdrs != NULL) {
956 Buf = (UINT8 *) (PacketHead + 1);
957 CopyMem (Buf, ExtHdrs, ExtHdrsLen);
958 }
959
960 if (UpdatedExtHdrs != NULL) {
961 //
962 // A Fragment Header is inserted to the packet, update the payload length.
963 //
964 PacketHead->PayloadLength = (UINT16) (NTOHS (PacketHead->PayloadLength) +
965 sizeof (IP6_FRAGMENT_HEADER));
966 PacketHead->PayloadLength = HTONS (PacketHead->PayloadLength);
967 FreePool (UpdatedExtHdrs);
968 }
969
970 return Ip6SendFrame (
971 IpIf,
972 IpInstance,
973 Packet,
974 &NextHop,
975 Callback,
976 Context
977 );
978
979 Error:
980 if (UpdatedExtHdrs != NULL) {
981 FreePool (UpdatedExtHdrs);
982 }
983 Ip6CancelPacket (IpIf, Packet, Status);
984 return Status;
985 }
986
987 /**
988 The filter function to find a packet and all its fragments.
989 The packet's fragments have their Context set to the packet.
990
991 @param[in] Frame The frames hold by the low level interface.
992 @param[in] Context Context to the function, which is the packet.
993
994 @retval TRUE This is the packet to cancel or its fragments.
995 @retval FALSE This is an unrelated packet.
996
997 **/
998 BOOLEAN
999 Ip6CancelPacketFragments (
1000 IN IP6_LINK_TX_TOKEN *Frame,
1001 IN VOID *Context
1002 )
1003 {
1004 if ((Frame->Packet == (NET_BUF *) Context) || (Frame->Context == Context)) {
1005 return TRUE;
1006 }
1007
1008 return FALSE;
1009 }
1010
1011 /**
1012 Remove all the frames on the interface that pass the FrameToCancel,
1013 either queued on ARP queues or that have already been delivered to
1014 MNP and not yet recycled.
1015
1016 @param[in] Interface Interface to remove the frames from.
1017 @param[in] IoStatus The transmit status returned to the frames' callback.
1018 @param[in] FrameToCancel Function to select the frame to cancel; NULL to select all.
1019 @param[in] Context Opaque parameters passed to FrameToCancel. Ignored if
1020 FrameToCancel is NULL.
1021
1022 **/
1023 VOID
1024 Ip6CancelFrames (
1025 IN IP6_INTERFACE *Interface,
1026 IN EFI_STATUS IoStatus,
1027 IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
1028 IN VOID *Context OPTIONAL
1029 )
1030 {
1031 LIST_ENTRY *Entry;
1032 LIST_ENTRY *Next;
1033 IP6_LINK_TX_TOKEN *Token;
1034 IP6_SERVICE *IpSb;
1035 IP6_NEIGHBOR_ENTRY *ArpQue;
1036 EFI_STATUS Status;
1037
1038 IpSb = Interface->Service;
1039 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);
1040
1041 //
1042 // Cancel all the pending frames on ARP requests
1043 //
1044 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->ArpQues) {
1045 ArpQue = NET_LIST_USER_STRUCT (Entry, IP6_NEIGHBOR_ENTRY, ArpList);
1046
1047 Status = Ip6FreeNeighborEntry (
1048 IpSb,
1049 ArpQue,
1050 FALSE,
1051 FALSE,
1052 IoStatus,
1053 FrameToCancel,
1054 Context
1055 );
1056 ASSERT_EFI_ERROR (Status);
1057 }
1058
1059 //
1060 // Cancel all the frames that have been delivered to MNP
1061 // but not yet recycled.
1062 //
1063 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->SentFrames) {
1064 Token = NET_LIST_USER_STRUCT (Entry, IP6_LINK_TX_TOKEN, Link);
1065
1066 if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {
1067 IpSb->Mnp->Cancel (IpSb->Mnp, &Token->MnpToken);
1068 }
1069 }
1070 }
1071
1072 /**
1073 Cancel the Packet and all its fragments.
1074
1075 @param[in] IpIf The interface from which the Packet is sent.
1076 @param[in] Packet The Packet to cancel.
1077 @param[in] IoStatus The status returns to the sender.
1078
1079 **/
1080 VOID
1081 Ip6CancelPacket (
1082 IN IP6_INTERFACE *IpIf,
1083 IN NET_BUF *Packet,
1084 IN EFI_STATUS IoStatus
1085 )
1086 {
1087 Ip6CancelFrames (IpIf, IoStatus, Ip6CancelPacketFragments, Packet);
1088 }
1089