master
c 3,056 lines 75.9 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 vnet.c
8
9 Abstract:
10
11 This file is a test of virtual network devices.
12
13 --*/
14
15 #include "lxtcommon.h"
16 #include "unittests.h"
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <sys/ioctl.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <sys/wait.h>
23 #include <sys/socket.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stddef.h>
28 #include <bits/local_lim.h>
29 #include <net/if.h>
30 #include <net/if_arp.h>
31 #include <arpa/inet.h>
32 #include <netinet/in.h>
33 #include <netinet/ip.h>
34 #include <netinet/udp.h>
35 #include <netinet/tcp.h>
36 #include <linux/icmp.h>
37 #include <netinet/icmp6.h>
38 #include <net/if.h>
39 #include <linux/net_namespace.h>
40 #include <linux/netlink.h>
41 #include <linux/rtnetlink.h>
42 #include <linux/sockios.h>
43 #include <linux/veth.h>
44
45 //
46 // Globals.
47 //
48
49 #define LXT_NAME "VirtualNetwork"
50 #define LXT_REQUEST_SEQUENCE 0x4567
51 #define LXT_IP_ADDRESS1 "172.12.13.113"
52 #define LXT_IP_ADDRESS2 "172.12.13.114"
53
54 //
55 // Functions.
56 //
57
58 int BindSocketForNetlink(int Socket);
59
60 int CreateVirtualBridgeViaIoctl(const char* Name);
61
62 int CreateVirtualBridgeViaNetlink(const char* Name);
63
64 void CreateVirtualDeviceInfo(const char* Type, const char* Name, const char* DeviceData, int DeviceDataSize, char* Buffer, int* BufferSize);
65
66 int CreateVirtualDeviceViaNetlink(int Flags, const char* DeviceData, int DeviceDataSize, struct nlmsghdr** Response);
67
68 int CreateVirtualEthernetPairViaNetlink(const char* Name, const char* PeerName);
69
70 int DeleteVirtualDeviceViaNetlink(const char* Name);
71
72 int DeleteVirtualBridgeViaIoctl(const char* Name);
73
74 int GetNetworkInterfaceIndex(const char* Name);
75
76 int SetIpAddress(const char* InterfaceName, const struct in_addr* AddressIpv4, char PrefixLength);
77
78 int SetRoute(const char* InterfaceName, const struct in_addr* AddressIpv4, int PrefixLength);
79
80 int SetVirtualDeviceAttributeViaNetlink(const char* Name, int AttributeType, int AttributeValue, int* Response);
81
82 int SetVirtualDeviceFlagViaNetlink(const char* Name, int Flag, bool IsFlagEnabled, int* Response);
83
84 int VerifyRouteLinkDoesNotExist(
85 const char* InterfaceName,
86 /* optional */ int* SocketToUse);
87
88 int VerifyRouteLinkExists(
89 const char* InterfaceName,
90 /* optional */ int* SocketToUse);
91
92 //
93 // Test cases.
94 //
95
96 LXT_VARIATION_HANDLER EmptyDeviceErrorFromNetlink;
97 LXT_VARIATION_HANDLER PhysicalDeviceNamespace1;
98 LXT_VARIATION_HANDLER SanityPermissionsCheck;
99 LXT_VARIATION_HANDLER VirtualBridgeAutoName;
100 LXT_VARIATION_HANDLER VirtualBridgeFromIoctl1;
101 LXT_VARIATION_HANDLER VirtualBridgeNamespace1;
102 LXT_VARIATION_HANDLER VirtualBridgeFromNetlink1;
103 LXT_VARIATION_HANDLER VirtualEthernetPairFromNetlink1;
104 LXT_VARIATION_HANDLER VirtualEthernetPairFromNetlink2;
105 LXT_VARIATION_HANDLER VirtualEthernetPairNamespace1;
106 LXT_VARIATION_HANDLER VirtualEthernetPairNamespace2;
107 LXT_VARIATION_HANDLER VirtualEthernetPairNamespace3;
108 LXT_VARIATION_HANDLER VirtualEthernetPairNamespace4;
109 LXT_VARIATION_HANDLER VirtualEthernetPairNamespace5;
110 LXT_VARIATION_HANDLER VirtualEthernetPairConfigure;
111 LXT_VARIATION_HANDLER VirtualEthernetPairData;
112 LXT_VARIATION_HANDLER VirtualEthernetPairNamespaceData;
113
114 //
115 // Global constants
116 //
117
118 static const LXT_VARIATION g_LxtVariations[] = {
119 {"Permissions Check", SanityPermissionsCheck},
120 {"No Device Error Check", EmptyDeviceErrorFromNetlink},
121 {"Virtual Bridge IOCTL", VirtualBridgeFromIoctl1},
122 {"Virtual Bridge Netlink", VirtualBridgeFromNetlink1},
123 {"Virtual Bridge auto name generation", VirtualBridgeAutoName},
124 {"Virtual Ethernet Pair", VirtualEthernetPairFromNetlink1},
125 {"Virtual Ethernet Pair (part 2)", VirtualEthernetPairFromNetlink2},
126 {"Virtual Bridge basic namespace check", VirtualBridgeNamespace1},
127 {"Virtual Ethernet Pair basic namespace check", VirtualEthernetPairNamespace1},
128 {"Virtual Ethernet Pair namespace check (part 2)", VirtualEthernetPairNamespace2},
129 {"Virtual Ethernet Pair namespace check (part 3)", VirtualEthernetPairNamespace3},
130 {"Virtual Ethernet Pair namespace link verification", VirtualEthernetPairNamespace4},
131 {"Virtual Ethernet Pair namespace socket check", VirtualEthernetPairNamespace5},
132 {"Virtual Ethernet Pair simple configuration", VirtualEthernetPairConfigure},
133
134 //
135 // Requires firewall manipulation to allow packet traversal
136 //
137
138 //{"Virtual Ethernet Pair data check", VirtualEthernetPairData},
139 //{"Virtual Ethernet Pair namespace data check", VirtualEthernetPairNamespaceData},
140
141 //
142 // Moving physical adapters between namespaces is not currently supported
143 //
144
145 //{"Physical device basic namespace check", PhysicalDeviceNamespace1},
146 };
147
148 int VnetTestEntry(int Argc, char* Argv[])
149
150 /*++
151
152 Routine Description:
153
154 This routine main entry point for the virtual network device test.
155
156 Arguments:
157
158 Argc - Supplies the number of command line arguments.
159
160 Argv - Supplies the command line arguments.
161
162 Return Value:
163
164 Returns 0 on success, -1 on failure.
165
166 --*/
167
168 {
169
170 LXT_ARGS Args;
171 int OriginalNetworkNamespaceFd;
172 int Result;
173
174 OriginalNetworkNamespaceFd = -1;
175 LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
176
177 //
178 // Since new devices are going to be created/destroyed, move to a new
179 // network namespace to try to prevent polluting the root namespace in case
180 // of errors.
181 //
182
183 LxtCheckErrno(OriginalNetworkNamespaceFd = open("/proc/self/ns/net", 0));
184 LxtCheckErrno(unshare(CLONE_NEWNET));
185
186 //
187 // Run tests.
188 //
189
190 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
191
192 ErrorExit:
193
194 //
195 // Try to restore to original network namespace.
196 //
197
198 if (OriginalNetworkNamespaceFd > 0)
199 {
200 setns(OriginalNetworkNamespaceFd, CLONE_NEWNET);
201 close(OriginalNetworkNamespaceFd);
202 }
203
204 LxtUninitialize();
205 return !LXT_SUCCESS(Result);
206 }
207
208 int BindSocketForNetlink(int Socket)
209
210 /*++
211
212 Routine Description:
213
214 This routine is a helper function to bind a socket for NETLINK use.
215
216 Arguments:
217
218 Socket - Supplies the socket to bind.
219
220 Return Value:
221
222 Returns 0 on success, -1 on failure.
223
224 --*/
225
226 {
227
228 struct sockaddr_nl BindAddress;
229 int Result;
230
231 memset(&BindAddress, 0, sizeof(BindAddress));
232 BindAddress.nl_family = AF_NETLINK;
233 LxtCheckErrno(bind(Socket, (struct sockaddr*)&BindAddress, sizeof(BindAddress)));
234
235 Result = 0;
236
237 ErrorExit:
238 return Result;
239 }
240
241 int CreateVirtualBridgeViaIoctl(const char* Name)
242
243 /*++
244
245 Routine Description:
246
247 This routine creates a virtual bridge device via the SIOCBRADDBR ioctl.
248
249 Arguments:
250
251 Name - Supplies the name to assign the new bridge.
252
253 Return Value:
254
255 Returns 0 on success, -1 on failure.
256
257 --*/
258
259 {
260
261 int Result;
262 int Sock;
263
264 Sock = socket(AF_UNIX, SOCK_STREAM, 0);
265 if (Sock < 0)
266 {
267 Result = -1;
268 goto ErrorExit;
269 }
270
271 Result = ioctl(Sock, SIOCBRADDBR, Name);
272
273 ErrorExit:
274 if (Sock > 0)
275 {
276 close(Sock);
277 }
278
279 return Result;
280 }
281
282 void CreateVirtualDeviceInfo(const char* Type, const char* Name, const char* DeviceData, int DeviceDataSize, char* Buffer, int* BufferSize)
283
284 /*++
285
286 Routine Description:
287
288 This routine generates the ifinfomsg and attributes representing a virtual
289 device.
290
291 Arguments:
292
293 Type - Supplies the optional name of the virtual device type.
294
295 Name - Supplies the name to assign the new device.
296
297 DeviceData - Supplies an optional buffer of device-type specific data.
298
299 DeviceDataSize - Supplies the size in bytes of DeviceData.
300
301 Buffer - Supplies the buffer to store the message. If this is null
302 BufferSize will return the number of bytes required.
303
304 BufferSize - Supplies a pointer to the size of the buffer.
305
306 Return Value:
307
308 None.
309
310 --*/
311
312 {
313
314 struct rtattr* Attribute;
315 int BufferOffset;
316 struct rtattr* LinkAttribute;
317 int LinkAttributeMessageOffset;
318 int LocalBufferSize;
319 int MessageSize;
320 int StringLength;
321
322 BufferOffset = 0;
323 if (Buffer == NULL)
324 {
325 LocalBufferSize = 0;
326 }
327 else
328 {
329 LocalBufferSize = *BufferSize;
330 }
331
332 MessageSize = RTA_ALIGN(sizeof(struct ifinfomsg));
333 if (LocalBufferSize >= MessageSize)
334 {
335 memset(&Buffer[BufferOffset], 0, (MessageSize - BufferOffset));
336 BufferOffset = MessageSize;
337 }
338
339 StringLength = strlen(Name);
340 MessageSize += RTA_SPACE(StringLength + 1);
341 if (LocalBufferSize >= MessageSize)
342 {
343 Attribute = (struct rtattr*)&Buffer[BufferOffset];
344 Attribute->rta_len = RTA_LENGTH(StringLength + 1);
345 Attribute->rta_type = IFLA_IFNAME;
346 memcpy(RTA_DATA(Attribute), Name, StringLength + 1);
347 BufferOffset = MessageSize;
348 }
349
350 if ((Type != NULL) || ((DeviceData != NULL) && (DeviceDataSize > 0)))
351 {
352 MessageSize += RTA_SPACE(0);
353 if (LocalBufferSize >= MessageSize)
354 {
355 LinkAttribute = (struct rtattr*)&Buffer[BufferOffset];
356 LinkAttribute->rta_type = IFLA_LINKINFO;
357
358 //
359 // The length of the link attribute contains other nested
360 // attributes, so remember it here and set it later.
361 //
362
363 LinkAttributeMessageOffset = BufferOffset;
364 BufferOffset = MessageSize;
365 }
366 else
367 {
368 LinkAttribute = NULL;
369 }
370
371 StringLength = strlen(Type);
372 MessageSize += RTA_SPACE(StringLength);
373 if (LocalBufferSize >= MessageSize)
374 {
375 Attribute = (struct rtattr*)&Buffer[BufferOffset];
376 Attribute->rta_len = RTA_LENGTH(StringLength);
377 Attribute->rta_type = IFLA_INFO_KIND;
378 memcpy(RTA_DATA(Attribute), Type, StringLength);
379 BufferOffset = MessageSize;
380 }
381
382 if ((DeviceData != NULL) && (DeviceDataSize > 0))
383 {
384 MessageSize += RTA_SPACE(DeviceDataSize);
385 if (LocalBufferSize >= MessageSize)
386 {
387 Attribute = (struct rtattr*)&Buffer[BufferOffset];
388 Attribute->rta_len = RTA_LENGTH(DeviceDataSize);
389 Attribute->rta_type = IFLA_INFO_DATA;
390 memcpy(RTA_DATA(Attribute), DeviceData, DeviceDataSize);
391 BufferOffset = MessageSize;
392 }
393 }
394
395 if (LinkAttribute != NULL)
396 {
397 LinkAttribute->rta_len = MessageSize - LinkAttributeMessageOffset;
398 }
399 }
400
401 *BufferSize = MessageSize;
402 return;
403 }
404
405 int CreateVirtualBridgeViaNetlink(const char* Name)
406
407 /*++
408
409 Routine Description:
410
411 This routine creates a new virtual bridge using the netlink RTM_NEWLINK
412 message. On success the caller should free the Response buffer.
413
414 Arguments:
415
416 Name - Supplies the name to give the new virtual bridge.
417
418 Return Value:
419
420 Returns 0 on success, -1 on failure.
421
422 --*/
423
424 {
425
426 char* DeviceData;
427 int DeviceDataSize;
428 struct nlmsgerr* ErrorMessage;
429 struct nlmsghdr* Response;
430 int Result;
431
432 Response = NULL;
433
434 //
435 // Determine the size of the device data part of the message.
436 //
437
438 CreateVirtualDeviceInfo("bridge", Name, NULL, 0, NULL, &DeviceDataSize);
439
440 //
441 // Allocate a buffer to hold the device data.
442 //
443
444 DeviceData = LxtAlloc(DeviceDataSize);
445 if (DeviceData == NULL)
446 {
447 Result = -1;
448 goto ErrorExit;
449 }
450
451 //
452 // Fill in the device data buffer.
453 //
454
455 CreateVirtualDeviceInfo("bridge", Name, NULL, 0, DeviceData, &DeviceDataSize);
456
457 //
458 // Attempt to create the device.
459 //
460
461 LxtCheckResult(CreateVirtualDeviceViaNetlink((NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK | NLM_F_REQUEST), DeviceData, DeviceDataSize, &Response));
462
463 //
464 // Verify success.
465 //
466
467 ErrorMessage = NLMSG_DATA(Response);
468 LxtCheckEqual(ErrorMessage->error, 0, "%d");
469 Result = 0;
470
471 ErrorExit:
472 if (Response != NULL)
473 {
474 LxtFree(Response);
475 }
476
477 if (DeviceData != NULL)
478 {
479 LxtFree(DeviceData);
480 }
481
482 return Result;
483 }
484
485 int CreateVirtualDeviceViaNetlink(int Flags, const char* DeviceData, int DeviceDataSize, struct nlmsghdr** Response)
486
487 /*++
488
489 Routine Description:
490
491 This routine creates a new virtual device using the netlink RTM_NEWLINK
492 message. On success the caller should free the Response buffer.
493
494 Arguments:
495
496 Flags - Supplies the message flags.
497
498 DeviceData - Supplies the optional device data.
499
500 DeviceDataSize - Supplies the size in bytes of the device data.
501
502 Response - Supplies a pointer to be filled in with newly allocated memory
503 holding the response. It is the caller's responsibility to free this
504 memory.
505
506 Return Value:
507
508 Returns 0 on success, -1 on failure.
509
510 --*/
511
512 {
513
514 socklen_t AddressLength;
515 struct nlmsgerr* ErrorMessage;
516 struct nlmsghdr* NextResponseMessage;
517 struct nlmsghdr* RequestMessage;
518 int RequestMessageSize;
519 struct nlmsghdr* ResponseMessage;
520 int ResponseMessageSize;
521 int ReceiveResult;
522 int Result;
523 int Socket;
524
525 //
526 // Allocate space for the request and the response.
527 //
528
529 RequestMessageSize = NLMSG_SPACE(DeviceDataSize);
530 RequestMessage = LxtAlloc(RequestMessageSize);
531 if (RequestMessage == NULL)
532 {
533 Result = ENOMEM;
534 goto ErrorExit;
535 }
536
537 ResponseMessageSize = RequestMessageSize + sizeof(*ErrorMessage);
538 ResponseMessage = LxtAlloc(ResponseMessageSize);
539 if (RequestMessage == NULL)
540 {
541 Result = ENOMEM;
542 goto ErrorExit;
543 }
544
545 //
546 // Create and bind socket.
547 //
548
549 LxtCheckErrno(Socket = socket(AF_NETLINK, SOCK_RAW, 0));
550 LxtCheckErrno(BindSocketForNetlink(Socket));
551
552 //
553 // Create a RTM_NEWLINK request.
554 //
555
556 memset(RequestMessage, 0, sizeof(*RequestMessage));
557 RequestMessage->nlmsg_len = RequestMessageSize;
558 RequestMessage->nlmsg_type = RTM_NEWLINK;
559 RequestMessage->nlmsg_seq = LXT_REQUEST_SEQUENCE;
560 RequestMessage->nlmsg_flags = Flags;
561 memcpy(NLMSG_DATA(RequestMessage), DeviceData, DeviceDataSize);
562 LxtCheckErrno(sendto(Socket, RequestMessage, RequestMessageSize, 0, NULL, 0));
563
564 //
565 // Get the response.
566 //
567
568 memset(ResponseMessage, 0, ResponseMessageSize);
569 LxtCheckErrno(ReceiveResult = recvfrom(Socket, ResponseMessage, ResponseMessageSize, 0, NULL, 0));
570
571 LxtCheckTrue(NLMSG_OK(ResponseMessage, ReceiveResult));
572 LxtCheckEqual(ResponseMessage->nlmsg_type, NLMSG_ERROR, "%d");
573 LxtCheckGreater((ResponseMessage->nlmsg_len + 1), NLMSG_PAYLOAD(ResponseMessage, 0), "%d");
574
575 ErrorMessage = NLMSG_DATA(ResponseMessage);
576 if (ErrorMessage->error < 0)
577 {
578
579 //
580 // On error, the entire message should be returned.
581 //
582
583 LxtCheckEqual(ResponseMessage->nlmsg_len, ResponseMessageSize, "%d");
584 }
585 else
586 {
587
588 //
589 // On success, just the header of the original message is expected to
590 // be returned, which is already included in the error message size.
591 //
592
593 LxtCheckEqual(ResponseMessage->nlmsg_len, NLMSG_SPACE(sizeof(*ErrorMessage)), "%d");
594 }
595
596 LxtCheckEqual(ResponseMessage->nlmsg_flags, 0, "%d");
597 LxtCheckEqual(ResponseMessage->nlmsg_seq, LXT_REQUEST_SEQUENCE, "%d");
598 LxtCheckEqual(ResponseMessage->nlmsg_pid, getpid(), "%d");
599 NextResponseMessage = NLMSG_NEXT(ResponseMessage, ReceiveResult);
600 LxtCheckTrue(NLMSG_OK(NextResponseMessage, ReceiveResult) == FALSE);
601 Result = 0;
602
603 ErrorExit:
604 if (Socket > 0)
605 {
606 close(Socket);
607 }
608
609 if (RequestMessage != NULL)
610 {
611 LxtFree(RequestMessage);
612 }
613
614 if (Result != 0)
615 {
616 if (ResponseMessage != NULL)
617 {
618 LxtFree(ResponseMessage);
619 }
620
621 errno = Result;
622 return -1;
623 }
624 else
625 {
626 *Response = ResponseMessage;
627 return 0;
628 }
629 }
630
631 int DeleteVirtualBridgeViaIoctl(const char* Name)
632
633 /*++
634
635 Routine Description:
636
637 This routine deletes a virtual bridge device via the SIOCBRDELBR ioctl.
638
639 Arguments:
640
641 Name - Supplies the name to assign the new bridge.
642
643 Return Value:
644
645 Returns 0 on success, -1 on failure.
646
647 --*/
648
649 {
650
651 int Result;
652 int Sock;
653
654 Sock = socket(AF_UNIX, SOCK_STREAM, 0);
655 if (Sock < 0)
656 {
657 Result = -1;
658 goto ErrorExit;
659 }
660
661 Result = ioctl(Sock, SIOCBRDELBR, Name);
662
663 ErrorExit:
664 if (Sock > 0)
665 {
666 close(Sock);
667 }
668
669 return Result;
670 }
671
672 int DeleteVirtualDeviceViaNetlink(const char* Name)
673
674 /*++
675
676 Routine Description:
677
678 This routine removes a virtual device using the netlink RTM_DELLINK
679 message.
680
681 Arguments:
682
683 Name - Supplies the name of the device to delete.
684
685 Return Value:
686
687 Returns 0 on success, -1 on failure.
688
689 --*/
690
691 {
692
693 socklen_t AddressLength;
694 int InterfaceIndex;
695 struct nlmsghdr* NextResponseMessage;
696 int ReceiveResult;
697 struct
698 {
699 struct nlmsghdr Header;
700 struct ifinfomsg Message __attribute__((aligned(NLMSG_ALIGNTO)));
701 } RequestMessage;
702 struct
703 {
704 struct nlmsghdr Header;
705 struct nlmsgerr Error __attribute__((aligned(NLMSG_ALIGNTO)));
706 } ResponseMessage;
707 int Result;
708 int Socket;
709
710 LxtCheckErrno(InterfaceIndex = GetNetworkInterfaceIndex(Name));
711
712 //
713 // Create and bind NETLINK socket.
714 //
715
716 LxtCheckErrno(Socket = socket(AF_NETLINK, SOCK_RAW, 0));
717 LxtCheckErrno(BindSocketForNetlink(Socket));
718
719 //
720 // Create a RTM_DELLINK request.
721 //
722
723 memset(&RequestMessage, 0, sizeof(RequestMessage));
724 RequestMessage.Header.nlmsg_len = sizeof(RequestMessage);
725 RequestMessage.Header.nlmsg_type = RTM_DELLINK;
726 RequestMessage.Header.nlmsg_seq = LXT_REQUEST_SEQUENCE;
727 RequestMessage.Header.nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST;
728 RequestMessage.Message.ifi_index = InterfaceIndex;
729 LxtCheckErrno(sendto(Socket, &RequestMessage, sizeof(RequestMessage), 0, NULL, 0));
730
731 //
732 // Get the response.
733 //
734
735 memset(&ResponseMessage, 0, sizeof(ResponseMessage));
736 LxtCheckErrno(ReceiveResult = recvfrom(Socket, &ResponseMessage, sizeof(ResponseMessage), 0, NULL, 0));
737
738 LxtCheckTrue(NLMSG_OK(&ResponseMessage.Header, ReceiveResult));
739 LxtCheckEqual(ResponseMessage.Header.nlmsg_type, NLMSG_ERROR, "%d");
740 LxtCheckEqual(ResponseMessage.Header.nlmsg_len, sizeof(ResponseMessage), "%d");
741
742 LxtCheckEqual(ResponseMessage.Header.nlmsg_flags, 0, "%d");
743 LxtCheckEqual(ResponseMessage.Header.nlmsg_seq, LXT_REQUEST_SEQUENCE, "%d");
744 LxtCheckEqual(ResponseMessage.Header.nlmsg_pid, getpid(), "%d");
745 LxtCheckEqual(ResponseMessage.Error.error, 0, "%d");
746 NextResponseMessage = NLMSG_NEXT(&ResponseMessage.Header, ReceiveResult);
747 LxtCheckTrue(NLMSG_OK(NextResponseMessage, ReceiveResult) == FALSE);
748 Result = 0;
749
750 ErrorExit:
751 if (Socket > 0)
752 {
753 close(Socket);
754 }
755
756 return Result;
757 }
758
759 int CreateVirtualEthernetPairViaNetlink(const char* Name, const char* PeerName)
760
761 /*++
762
763 Routine Description:
764
765 This routine creates a new virtual bridge using the netlink RTM_NEWLINK
766 message. On success the caller should free the Response buffer.
767
768 Arguments:
769
770 Name - Supplies the name to give the new virtual ethernet.
771
772 PeerName - Supplies the name to give the other end of the new virtual
773 ethernet pair.
774
775 Return Value:
776
777 Returns 0 on success, -1 on failure.
778
779 --*/
780
781 {
782
783 struct rtattr* Attribute;
784 char* DeviceData;
785 int DeviceDataSize;
786 struct nlmsgerr* ErrorMessage;
787 char* PeerDeviceData;
788 int PeerDeviceDataSize;
789 struct nlmsghdr* Response;
790 int Result;
791
792 Response = NULL;
793
794 //
795 // Determine the size of the peer device data part of the message.
796 //
797
798 CreateVirtualDeviceInfo(NULL, PeerName, NULL, 0, NULL, &PeerDeviceDataSize);
799
800 //
801 // Allocate a buffer to hold the peer device data.
802 //
803
804 PeerDeviceData = LxtAlloc(RTA_SPACE(PeerDeviceDataSize));
805 if (PeerDeviceData == NULL)
806 {
807 Result = -1;
808 goto ErrorExit;
809 }
810
811 //
812 // Fill in the peer device data buffer.
813 //
814
815 Attribute = (struct rtattr*)PeerDeviceData;
816 Attribute->rta_len = RTA_LENGTH(PeerDeviceDataSize);
817 Attribute->rta_type = VETH_INFO_PEER;
818 CreateVirtualDeviceInfo(NULL, PeerName, NULL, 0, RTA_DATA(Attribute), &PeerDeviceDataSize);
819
820 //
821 // Determine the size of the device data part of the message.
822 //
823
824 CreateVirtualDeviceInfo("veth", Name, PeerDeviceData, Attribute->rta_len, NULL, &DeviceDataSize);
825
826 //
827 // Allocate a buffer to hold the peer device data.
828 //
829
830 DeviceData = LxtAlloc(DeviceDataSize);
831 if (DeviceData == NULL)
832 {
833 Result = -1;
834 goto ErrorExit;
835 }
836
837 //
838 // Fill in the peer device data buffer.
839 //
840
841 CreateVirtualDeviceInfo("veth", Name, PeerDeviceData, Attribute->rta_len, DeviceData, &DeviceDataSize);
842
843 //
844 // Attempt to create the device.
845 //
846
847 LxtCheckResult(CreateVirtualDeviceViaNetlink((NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK | NLM_F_REQUEST), DeviceData, DeviceDataSize, &Response));
848
849 //
850 // Verify success.
851 //
852
853 ErrorMessage = NLMSG_DATA(Response);
854 LxtCheckEqual(ErrorMessage->error, 0, "%d");
855 Result = 0;
856
857 ErrorExit:
858 if (Response != NULL)
859 {
860 LxtFree(Response);
861 }
862
863 if (DeviceData != NULL)
864 {
865 LxtFree(DeviceData);
866 }
867
868 if (PeerDeviceData != NULL)
869 {
870 LxtFree(PeerDeviceData);
871 }
872
873 return Result;
874 }
875
876 int GetNetworkInterfaceIndex(const char* Name)
877
878 /*++
879
880 Routine Description:
881
882 This routine returns the network interface index of a device.
883
884 Arguments:
885
886 Name - Supplies the name of the device
887
888 Return Value:
889
890 Returns the index on success, -1 on failure.
891
892 --*/
893
894 {
895
896 struct ifreq InterfaceRequest;
897 int Result;
898 int Socket;
899
900 Socket = socket(AF_UNIX, SOCK_DGRAM, 0);
901 if (Socket < 0)
902 {
903 Result = -1;
904 goto ErrorExit;
905 }
906
907 memset(&InterfaceRequest, 0, sizeof(InterfaceRequest));
908 strcpy(InterfaceRequest.ifr_name, Name);
909 Result = ioctl(Socket, SIOCGIFINDEX, &InterfaceRequest);
910 LxtClose(Socket);
911 if (Result < 0)
912 {
913 goto ErrorExit;
914 }
915
916 Result = InterfaceRequest.ifr_ifindex;
917
918 ErrorExit:
919 return Result;
920 }
921
922 int EmptyDeviceErrorFromNetlink(PLXT_ARGS Args)
923
924 /*++
925
926 Routine Description:
927
928 This routine sends a create message with no device described. This pattern
929 is used by tools like 'ip' to determine if the system supports virtual
930 network device creation.
931
932 Arguments:
933
934 Args - Supplies the command line arguments.
935
936 Return Value:
937
938 Returns 0 on success, -1 on failure.
939
940 --*/
941
942 {
943
944 struct ifinfomsg DeviceData;
945 struct nlmsgerr* ErrorMessage;
946 struct nlmsghdr* Response;
947 int Result;
948
949 Response = NULL;
950 memset(&DeviceData, 0, sizeof(DeviceData));
951 LxtCheckResult(CreateVirtualDeviceViaNetlink((NLM_F_REQUEST | NLM_F_ACK), (const char*)&DeviceData, sizeof(DeviceData), &Response));
952
953 ErrorMessage = NLMSG_DATA(Response);
954 LxtCheckEqual(ErrorMessage->error, -ENODEV, "%d");
955 Result = 0;
956
957 ErrorExit:
958 if (Response != NULL)
959 {
960 LxtFree(Response);
961 }
962
963 return Result;
964 }
965
966 int PhysicalDeviceNamespace1(PLXT_ARGS Args)
967
968 /*++
969
970 Routine Description:
971
972 This routine does basic network namespace sanity testing with a physical
973 device (assumes existence of eth0):
974 1) creates a new namespace
975 2) attempt to move eth0 to new namespace
976 3) close new namespace
977 4) verify device was returned to the root namespace
978
979 Arguments:
980
981 Args - Supplies the command line arguments.
982
983 Return Value:
984
985 Returns 0 on success, -1 on failure.
986
987 --*/
988
989 {
990
991 int NewNetworkNamespaceFd;
992 int OriginalNetworkNamespaceFd;
993 int RootNetworkNamespaceFd;
994 int Response;
995 int Result;
996
997 NewNetworkNamespaceFd = 0;
998 OriginalNetworkNamespaceFd = 0;
999
1000 //
1001 // Open file descriptor of default network namespace.
1002 //
1003
1004 LxtCheckErrno(OriginalNetworkNamespaceFd = open("/proc/self/ns/net", 0));
1005
1006 //
1007 // Open file descriptor of the root network namespace.
1008 //
1009
1010 LxtCheckErrno(RootNetworkNamespaceFd = open("/proc/1/ns/net", 0));
1011
1012 //
1013 // Switch to a new network namespace.
1014 //
1015
1016 LxtCheckErrno(unshare(CLONE_NEWNET));
1017
1018 //
1019 // Open file descriptor of the new network namespace.
1020 //
1021
1022 LxtCheckErrno(NewNetworkNamespaceFd = open("/proc/self/ns/net", 0));
1023
1024 //
1025 // Switch to root network namespace.
1026 //
1027
1028 LxtCheckErrno(setns(RootNetworkNamespaceFd, CLONE_NEWNET));
1029
1030 //
1031 // Try to move eth0 to the new network namespace.
1032 //
1033
1034 LxtCheckResult(SetVirtualDeviceAttributeViaNetlink("eth0", IFLA_NET_NS_FD, NewNetworkNamespaceFd, &Response));
1035
1036 LxtCheckEqual(Response, 0, "%d");
1037
1038 //
1039 // Verify that the device is gone.
1040 //
1041
1042 LxtCheckErrnoFailure(GetNetworkInterfaceIndex("eth0"), ENODEV);
1043
1044 //
1045 // Close the new network namespace. This should restore any physical
1046 // devices to the root network namespace.
1047 //
1048
1049 LxtCheckClose(NewNetworkNamespaceFd);
1050
1051 //
1052 // Pause for a bit to allow background processing to occur.
1053 //
1054
1055 sleep(1);
1056
1057 //
1058 // Verify that the device is back.
1059 //
1060
1061 LxtCheckErrno(GetNetworkInterfaceIndex("eth0"));
1062
1063 //
1064 // Restore back to default network namespace.
1065 //
1066
1067 LxtCheckErrno(setns(OriginalNetworkNamespaceFd, CLONE_NEWNET));
1068
1069 ErrorExit:
1070 if (NewNetworkNamespaceFd > 0)
1071 {
1072 close(NewNetworkNamespaceFd);
1073 }
1074
1075 if (RootNetworkNamespaceFd > 0)
1076 {
1077 close(RootNetworkNamespaceFd);
1078 }
1079
1080 if (OriginalNetworkNamespaceFd > 0)
1081 {
1082 close(OriginalNetworkNamespaceFd);
1083 }
1084
1085 return Result;
1086 }
1087
1088 int SanityPermissionsCheck(PLXT_ARGS Args)
1089
1090 /*++
1091
1092 Routine Description:
1093
1094 This routine does a simple operation to check that the current user has
1095 appropriate permissions. This should be run as the first test to give a
1096 quick error to the user that typically the entire test needs to be run
1097 with sudo.
1098
1099 Arguments:
1100
1101 Args - Supplies the command line arguments.
1102
1103 Return Value:
1104
1105 Returns 0 on success, -1 on failure.
1106
1107 --*/
1108
1109 {
1110
1111 struct ifinfomsg DeviceData;
1112 struct nlmsgerr* ErrorMessage;
1113 struct nlmsghdr* Response;
1114 int Result;
1115
1116 Response = NULL;
1117 memset(&DeviceData, 0, sizeof(DeviceData));
1118 LxtCheckResult(CreateVirtualDeviceViaNetlink((NLM_F_REQUEST | NLM_F_ACK), (const char*)&DeviceData, sizeof(DeviceData), &Response));
1119
1120 ErrorMessage = NLMSG_DATA(Response);
1121 if (ErrorMessage->error == -1)
1122 {
1123 LxtLogError("Make sure test is run with sudo!");
1124 Result = -1;
1125 goto ErrorExit;
1126 }
1127
1128 Result = 0;
1129
1130 ErrorExit:
1131 if (Response != NULL)
1132 {
1133 LxtFree(Response);
1134 }
1135
1136 return Result;
1137 }
1138
1139 int SetIpAddress(const char* InterfaceName, const struct in_addr* AddressIpv4, char PrefixLength)
1140
1141 /*++
1142
1143 Routine Description:
1144
1145 This routine adds an IP address to a network interface.
1146
1147 Arguments:
1148
1149 InterfaceName - Supplies the interface name.
1150
1151 AddressIpv4 - Supplies the IP address.
1152
1153 PrefixLength - Supplies the prefix length of the address.
1154
1155 Return Value:
1156
1157 Returns 0 on success, -1 on failure.
1158
1159 --*/
1160
1161 {
1162
1163 socklen_t AddressLength;
1164 struct nlmsgerr* ErrorMessage;
1165 int InterfaceIndex;
1166 int ReceiveResult;
1167 struct
1168 {
1169 struct nlmsghdr Header;
1170 struct ifaddrmsg Message __attribute__((aligned(NLMSG_ALIGNTO)));
1171 struct
1172 {
1173 struct rtattr RtHeader __attribute__((aligned(RTA_ALIGNTO)));
1174 struct in_addr AddressIpv4 __attribute__((aligned(RTA_ALIGNTO)));
1175 } AddressAttribute;
1176 struct
1177 {
1178 struct rtattr RtHeader __attribute__((aligned(RTA_ALIGNTO)));
1179 struct in_addr AddressIpv4 __attribute__((aligned(RTA_ALIGNTO)));
1180 } LocalAddressAttribute;
1181 } RequestMessage;
1182 struct
1183 {
1184 struct nlmsghdr Header;
1185 struct nlmsgerr Error __attribute__((aligned(NLMSG_ALIGNTO)));
1186 } ResponseMessage;
1187 int Result;
1188 int Socket;
1189
1190 LxtCheckErrno(InterfaceIndex = GetNetworkInterfaceIndex(InterfaceName));
1191
1192 //
1193 // Create and bind NETLINK socket.
1194 //
1195
1196 LxtCheckErrno(Socket = socket(AF_NETLINK, SOCK_RAW, 0));
1197 LxtCheckErrno(BindSocketForNetlink(Socket));
1198
1199 //
1200 // Create a RTM_NEWLINK request.
1201 //
1202
1203 memset(&RequestMessage, 0, sizeof(RequestMessage));
1204 RequestMessage.Header.nlmsg_len = sizeof(RequestMessage);
1205 RequestMessage.Header.nlmsg_type = RTM_NEWADDR;
1206 RequestMessage.Header.nlmsg_seq = LXT_REQUEST_SEQUENCE;
1207 RequestMessage.Header.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK | NLM_F_REQUEST;
1208
1209 RequestMessage.Message.ifa_family = AF_INET;
1210 RequestMessage.Message.ifa_prefixlen = PrefixLength;
1211 RequestMessage.Message.ifa_index = InterfaceIndex;
1212 RequestMessage.AddressAttribute.RtHeader.rta_len = RTA_LENGTH(sizeof(*AddressIpv4));
1213
1214 RequestMessage.AddressAttribute.RtHeader.rta_type = IFA_ADDRESS;
1215 memcpy(&RequestMessage.AddressAttribute.AddressIpv4, AddressIpv4, sizeof(*AddressIpv4));
1216
1217 RequestMessage.LocalAddressAttribute.RtHeader.rta_len = RTA_LENGTH(sizeof(*AddressIpv4));
1218
1219 RequestMessage.LocalAddressAttribute.RtHeader.rta_type = IFA_LOCAL;
1220 memcpy(&RequestMessage.LocalAddressAttribute.AddressIpv4, AddressIpv4, sizeof(*AddressIpv4));
1221
1222 LxtCheckErrno(sendto(Socket, &RequestMessage, sizeof(RequestMessage), 0, NULL, 0));
1223
1224 //
1225 // Get the response.
1226 //
1227
1228 memset(&ResponseMessage, 0, sizeof(ResponseMessage));
1229 LxtCheckErrno(ReceiveResult = recvfrom(Socket, &ResponseMessage, sizeof(ResponseMessage), 0, NULL, 0));
1230
1231 LxtCheckEqual(ReceiveResult, sizeof(ResponseMessage), "%d");
1232 if (ResponseMessage.Header.nlmsg_len != ReceiveResult)
1233 {
1234 LxtCheckGreater(ResponseMessage.Header.nlmsg_len, ReceiveResult, "%d");
1235 }
1236
1237 LxtCheckEqual(ResponseMessage.Header.nlmsg_type, NLMSG_ERROR, "%d");
1238 LxtCheckEqual(ResponseMessage.Header.nlmsg_flags, 0, "%d");
1239 LxtCheckEqual(ResponseMessage.Header.nlmsg_seq, LXT_REQUEST_SEQUENCE, "%d");
1240 LxtCheckEqual(ResponseMessage.Header.nlmsg_pid, getpid(), "%d");
1241 LxtCheckEqual(ResponseMessage.Error.error, 0, "%d");
1242 Result = 0;
1243
1244 ErrorExit:
1245 if (Socket > 0)
1246 {
1247 close(Socket);
1248 }
1249
1250 return Result;
1251 }
1252
1253 int SetRoute(const char* InterfaceName, const struct in_addr* AddressIpv4, int PrefixLength)
1254
1255 /*++
1256
1257 Routine Description:
1258
1259 This routine adds a route to a network interface.
1260
1261 Arguments:
1262
1263 InterfaceName - Supplies the interface name.
1264
1265 AddressIpv4 - Supplies the IP address.
1266
1267 PrefixLength - Supplies the prefix length of AddressIpv4.
1268
1269 Return Value:
1270
1271 Returns 0 on success, -1 on failure.
1272
1273 --*/
1274
1275 {
1276
1277 socklen_t AddressLength;
1278 struct nlmsgerr* ErrorMessage;
1279 int InterfaceIndex;
1280 int ReceiveResult;
1281 struct
1282 {
1283 struct nlmsghdr Header;
1284 struct rtmsg Message __attribute__((aligned(NLMSG_ALIGNTO)));
1285 struct
1286 {
1287 struct rtattr RtHeader __attribute__((aligned(RTA_ALIGNTO)));
1288 struct in_addr AddressIpv4 __attribute__((aligned(RTA_ALIGNTO)));
1289 } DestAttribute;
1290 struct
1291 {
1292 struct rtattr RtHeader __attribute__((aligned(RTA_ALIGNTO)));
1293 int InterfaceIndex __attribute__((aligned(RTA_ALIGNTO)));
1294 } IndexAttribute;
1295 } RequestMessage;
1296 struct
1297 {
1298 struct nlmsghdr Header;
1299 struct nlmsgerr Error __attribute__((aligned(NLMSG_ALIGNTO)));
1300 } ResponseMessage;
1301 int Result;
1302 int Socket;
1303
1304 LxtCheckErrno(InterfaceIndex = GetNetworkInterfaceIndex(InterfaceName));
1305
1306 //
1307 // Create and bind NETLINK socket.
1308 //
1309
1310 LxtCheckErrno(Socket = socket(AF_NETLINK, SOCK_RAW, 0));
1311 LxtCheckErrno(BindSocketForNetlink(Socket));
1312
1313 //
1314 // Create a RTM_NEWROUTE request.
1315 //
1316
1317 memset(&RequestMessage, 0, sizeof(RequestMessage));
1318 RequestMessage.Header.nlmsg_len = sizeof(RequestMessage);
1319 RequestMessage.Header.nlmsg_type = RTM_NEWROUTE;
1320 RequestMessage.Header.nlmsg_seq = LXT_REQUEST_SEQUENCE;
1321 RequestMessage.Header.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL | NLM_F_ACK | NLM_F_REQUEST;
1322
1323 RequestMessage.Message.rtm_family = AF_INET;
1324 RequestMessage.Message.rtm_dst_len = PrefixLength;
1325 RequestMessage.Message.rtm_table = RT_TABLE_MAIN;
1326 RequestMessage.Message.rtm_protocol = RTPROT_BOOT;
1327 RequestMessage.Message.rtm_scope = RT_SCOPE_LINK;
1328 RequestMessage.Message.rtm_type = RTA_DST;
1329
1330 RequestMessage.DestAttribute.RtHeader.rta_len = RTA_LENGTH(sizeof(*AddressIpv4));
1331
1332 RequestMessage.DestAttribute.RtHeader.rta_type = RTA_DST;
1333 memcpy(&RequestMessage.DestAttribute.AddressIpv4, AddressIpv4, sizeof(*AddressIpv4));
1334
1335 RequestMessage.IndexAttribute.RtHeader.rta_len = RTA_LENGTH(sizeof(int));
1336
1337 RequestMessage.IndexAttribute.RtHeader.rta_type = RTA_OIF;
1338 RequestMessage.IndexAttribute.InterfaceIndex = InterfaceIndex;
1339
1340 LxtCheckErrno(sendto(Socket, &RequestMessage, sizeof(RequestMessage), 0, NULL, 0));
1341
1342 //
1343 // Get the response.
1344 //
1345
1346 memset(&ResponseMessage, 0, sizeof(ResponseMessage));
1347 LxtCheckErrno(ReceiveResult = recvfrom(Socket, &ResponseMessage, sizeof(ResponseMessage), 0, NULL, 0));
1348
1349 LxtCheckEqual(ReceiveResult, sizeof(ResponseMessage), "%d");
1350 if (ResponseMessage.Header.nlmsg_len != ReceiveResult)
1351 {
1352 LxtCheckGreater(ResponseMessage.Header.nlmsg_len, ReceiveResult, "%d");
1353 }
1354
1355 LxtCheckEqual(ResponseMessage.Header.nlmsg_type, NLMSG_ERROR, "%d");
1356 LxtCheckEqual(ResponseMessage.Header.nlmsg_flags, 0, "%d");
1357 LxtCheckEqual(ResponseMessage.Header.nlmsg_seq, LXT_REQUEST_SEQUENCE, "%d");
1358 LxtCheckEqual(ResponseMessage.Header.nlmsg_pid, getpid(), "%d");
1359 LxtCheckEqual(ResponseMessage.Error.error, 0, "%d");
1360 Result = 0;
1361
1362 ErrorExit:
1363 if (Socket > 0)
1364 {
1365 close(Socket);
1366 }
1367
1368 return Result;
1369 }
1370
1371 int SetVirtualDeviceAttributeViaNetlink(const char* Name, int AttributeType, int AttributeValue, int* Response)
1372
1373 /*++
1374
1375 Routine Description:
1376
1377 This routine attempts to move a virtual device to the network namespace
1378 referenced by the NamespaceFd.
1379
1380 Arguments:
1381
1382 Name - Supplies the name of the virtual device.
1383
1384 AttributeType - Supplies the attribute type.
1385
1386 AttributeValue - Supplies the attribute value.
1387
1388 NetworkNamespaceFd - Supplies the file descriptor of a network namespace.
1389
1390 Response - Supplies a pointer to receive the response errno.
1391
1392 Return Value:
1393
1394 Returns 0 on success, -1 on failure.
1395
1396 --*/
1397
1398 {
1399
1400 socklen_t AddressLength;
1401 struct nlmsgerr* ErrorMessage;
1402 int InterfaceIndex;
1403 int ReceiveResult;
1404 struct
1405 {
1406 struct nlmsghdr Header;
1407 struct ifinfomsg Message __attribute__((aligned(NLMSG_ALIGNTO)));
1408 struct
1409 {
1410 struct rtattr RtHeader __attribute__((aligned(RTA_ALIGNTO)));
1411 int RtValue __attribute__((aligned(RTA_ALIGNTO)));
1412 } Attribute;
1413 } RequestMessage;
1414 struct
1415 {
1416 struct nlmsghdr Header;
1417 struct nlmsgerr Error __attribute__((aligned(NLMSG_ALIGNTO)));
1418 } ResponseMessage;
1419 int Result;
1420 int Socket;
1421
1422 LxtCheckErrno(InterfaceIndex = GetNetworkInterfaceIndex(Name));
1423
1424 //
1425 // Create and bind NETLINK socket.
1426 //
1427
1428 LxtCheckErrno(Socket = socket(AF_NETLINK, SOCK_RAW, 0));
1429 LxtCheckErrno(BindSocketForNetlink(Socket));
1430
1431 //
1432 // Create a RTM_NEWLINK update request.
1433 //
1434
1435 memset(&RequestMessage, 0, sizeof(RequestMessage));
1436 RequestMessage.Header.nlmsg_len = sizeof(RequestMessage);
1437 RequestMessage.Header.nlmsg_type = RTM_NEWLINK;
1438 RequestMessage.Header.nlmsg_seq = LXT_REQUEST_SEQUENCE;
1439 RequestMessage.Header.nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST;
1440 RequestMessage.Message.ifi_index = InterfaceIndex;
1441 RequestMessage.Attribute.RtHeader.rta_len = RTA_LENGTH(sizeof(int));
1442 RequestMessage.Attribute.RtHeader.rta_type = AttributeType;
1443 RequestMessage.Attribute.RtValue = AttributeValue;
1444 LxtCheckErrno(sendto(Socket, &RequestMessage, sizeof(RequestMessage), 0, NULL, 0));
1445
1446 //
1447 // Get the response.
1448 //
1449
1450 memset(&ResponseMessage, 0, sizeof(ResponseMessage));
1451 LxtCheckErrno(ReceiveResult = recvfrom(Socket, &ResponseMessage, sizeof(ResponseMessage), 0, NULL, 0));
1452
1453 LxtCheckEqual(ReceiveResult, sizeof(ResponseMessage), "%d");
1454 if (ResponseMessage.Header.nlmsg_len != ReceiveResult)
1455 {
1456 LxtCheckGreater(ResponseMessage.Header.nlmsg_len, ReceiveResult, "%d");
1457 }
1458
1459 LxtCheckEqual(ResponseMessage.Header.nlmsg_type, NLMSG_ERROR, "%d");
1460 LxtCheckEqual(ResponseMessage.Header.nlmsg_flags, 0, "%d");
1461 LxtCheckEqual(ResponseMessage.Header.nlmsg_seq, LXT_REQUEST_SEQUENCE, "%d");
1462 LxtCheckEqual(ResponseMessage.Header.nlmsg_pid, getpid(), "%d");
1463 *Response = ResponseMessage.Error.error;
1464 Result = 0;
1465
1466 ErrorExit:
1467 if (Socket > 0)
1468 {
1469 close(Socket);
1470 }
1471
1472 return Result;
1473 }
1474
1475 int SetVirtualDeviceFlagViaNetlink(const char* Name, int Flag, bool IsFlagEnabled, int* Response)
1476
1477 /*++
1478
1479 Routine Description:
1480
1481 This routine toggles network interface flags (e.g. up/down).
1482
1483 Arguments:
1484
1485 Name - Supplies the name of the virtual device.
1486
1487 Flag - Supplies the flag to toggle.
1488
1489 IsFlagEnabled - Supplies the state to which the flag should be set.
1490
1491 Response - Supplies a pointer to receive the response errno.
1492
1493 Return Value:
1494
1495 Returns 0 on success, -1 on failure.
1496
1497 --*/
1498
1499 {
1500
1501 socklen_t AddressLength;
1502 struct nlmsgerr* ErrorMessage;
1503 int InterfaceIndex;
1504 int ReceiveResult;
1505 struct
1506 {
1507 struct nlmsghdr Header;
1508 struct ifinfomsg Message __attribute__((aligned(NLMSG_ALIGNTO)));
1509 } RequestMessage;
1510 struct
1511 {
1512 struct nlmsghdr Header;
1513 struct nlmsgerr Error __attribute__((aligned(NLMSG_ALIGNTO)));
1514 } ResponseMessage;
1515 int Result;
1516 int Socket;
1517
1518 LxtCheckErrno(InterfaceIndex = GetNetworkInterfaceIndex(Name));
1519
1520 //
1521 // Create and bind NETLINK socket.
1522 //
1523
1524 LxtCheckErrno(Socket = socket(AF_NETLINK, SOCK_RAW, 0));
1525 LxtCheckErrno(BindSocketForNetlink(Socket));
1526
1527 //
1528 // Create a RTM_NEWLINK update request.
1529 //
1530
1531 memset(&RequestMessage, 0, sizeof(RequestMessage));
1532 RequestMessage.Header.nlmsg_len = sizeof(RequestMessage);
1533 RequestMessage.Header.nlmsg_type = RTM_NEWLINK;
1534 RequestMessage.Header.nlmsg_seq = LXT_REQUEST_SEQUENCE;
1535 RequestMessage.Header.nlmsg_flags = NLM_F_ACK | NLM_F_REQUEST;
1536 RequestMessage.Message.ifi_index = InterfaceIndex;
1537 RequestMessage.Message.ifi_change = Flag;
1538 if (IsFlagEnabled)
1539 {
1540 RequestMessage.Message.ifi_flags = Flag;
1541 }
1542
1543 LxtCheckErrno(sendto(Socket, &RequestMessage, sizeof(RequestMessage), 0, NULL, 0));
1544
1545 //
1546 // Get the response.
1547 //
1548
1549 memset(&ResponseMessage, 0, sizeof(ResponseMessage));
1550 LxtCheckErrno(ReceiveResult = recvfrom(Socket, &ResponseMessage, sizeof(ResponseMessage), 0, NULL, 0));
1551
1552 LxtCheckEqual(ReceiveResult, sizeof(ResponseMessage), "%d");
1553 if (ResponseMessage.Header.nlmsg_len != ReceiveResult)
1554 {
1555 LxtCheckGreater(ResponseMessage.Header.nlmsg_len, ReceiveResult, "%d");
1556 }
1557
1558 LxtCheckEqual(ResponseMessage.Header.nlmsg_type, NLMSG_ERROR, "%d");
1559 LxtCheckEqual(ResponseMessage.Header.nlmsg_flags, 0, "%d");
1560 LxtCheckEqual(ResponseMessage.Header.nlmsg_seq, LXT_REQUEST_SEQUENCE, "%d");
1561 LxtCheckEqual(ResponseMessage.Header.nlmsg_pid, getpid(), "%d");
1562 *Response = ResponseMessage.Error.error;
1563 Result = 0;
1564
1565 ErrorExit:
1566 if (Socket > 0)
1567 {
1568 close(Socket);
1569 }
1570
1571 return Result;
1572 }
1573
1574 int VerifyRouteLinkDoesNotExist(
1575 const char* InterfaceName,
1576 /* optional */ int* SocketToUse)
1577
1578 /*++
1579
1580 Routine Description:
1581
1582 This routine attempts to retrieve the link information for a network
1583 interface, expecting that interface not to exist.
1584
1585 Arguments:
1586
1587 InterfaceName - Supplies the name of the network interface.
1588
1589 SocketToUse - Supplies an optional socket bound to NETLINK to use for the
1590 query.
1591
1592 Return Value:
1593
1594 Returns 0 on success, -1 on failure.
1595
1596 --*/
1597
1598 {
1599
1600 socklen_t AddressLength;
1601 bool CloseSocket;
1602 struct nlmsgerr* ErrorMessage;
1603 struct nlmsghdr* Header;
1604 int InterfaceIndex;
1605 size_t InterfaceNameLength;
1606 char ReceiveBuffer[5000];
1607 int ReceiveResult;
1608 int Result;
1609 int Socket;
1610
1611 struct _RequestMessage
1612 {
1613 struct nlmsghdr Header;
1614 struct ifinfomsg Message __attribute__((aligned(NLMSG_ALIGNTO)));
1615 struct
1616 {
1617 struct rtattr RtHeader __attribute__((aligned(RTA_ALIGNTO)));
1618 char InterfaceName[32] __attribute__((aligned(RTA_ALIGNTO)));
1619 } Attribute;
1620 } RequestMessage;
1621
1622 if (SocketToUse != NULL)
1623 {
1624 CloseSocket = false;
1625 Socket = *SocketToUse;
1626 }
1627 else
1628 {
1629
1630 //
1631 // Create and bind socket. Create a RTM_GETLINK request.
1632 //
1633
1634 LxtCheckErrno(Socket = socket(AF_NETLINK, SOCK_RAW, 0));
1635 CloseSocket = true;
1636 LxtCheckErrno(BindSocketForNetlink(Socket));
1637 }
1638
1639 memset(&RequestMessage, 0, sizeof(RequestMessage));
1640 RequestMessage.Header.nlmsg_type = RTM_GETLINK;
1641 RequestMessage.Header.nlmsg_seq = LXT_REQUEST_SEQUENCE;
1642 ;
1643 RequestMessage.Message.ifi_family = AF_NETLINK;
1644 RequestMessage.Header.nlmsg_flags = NLM_F_REQUEST;
1645 InterfaceNameLength = strlen(InterfaceName) + 1;
1646 LxtCheckGreaterOrEqual(sizeof(RequestMessage.Attribute.InterfaceName), InterfaceNameLength, "%lu");
1647
1648 RequestMessage.Attribute.RtHeader.rta_len = RTA_LENGTH(InterfaceNameLength);
1649 RequestMessage.Attribute.RtHeader.rta_type = IFLA_IFNAME;
1650 memcpy(RequestMessage.Attribute.InterfaceName, InterfaceName, InterfaceNameLength);
1651
1652 RequestMessage.Header.nlmsg_len = offsetof(struct _RequestMessage, Attribute.InterfaceName) + InterfaceNameLength;
1653
1654 LxtCheckErrno(sendto(Socket, &RequestMessage, RequestMessage.Header.nlmsg_len, 0, NULL, 0));
1655
1656 LxtCheckErrno(ReceiveResult = recv(Socket, ReceiveBuffer, sizeof(ReceiveBuffer), 0));
1657
1658 Header = (struct nlmsghdr*)ReceiveBuffer;
1659 LxtCheckTrue(NLMSG_OK(Header, ReceiveResult));
1660 LxtCheckEqual(Header->nlmsg_type, NLMSG_ERROR, "%d");
1661 LxtCheckGreater((Header->nlmsg_len + 1), NLMSG_PAYLOAD(Header, 0), "%d");
1662
1663 ErrorMessage = NLMSG_DATA(Header);
1664 LxtCheckEqual(ErrorMessage->error, -ENODEV, "%d");
1665
1666 ErrorExit:
1667 if (CloseSocket)
1668 {
1669 close(Socket);
1670 }
1671
1672 return Result;
1673 }
1674
1675 int VerifyRouteLinkExists(
1676 const char* InterfaceName,
1677 /* optional */ int* SocketToUse)
1678
1679 /*++
1680
1681 Routine Description:
1682
1683 This routine retrieves the link information for a network interface.
1684
1685 Arguments:
1686
1687 InterfaceName - Supplies the name of the network interface.
1688
1689 SocketToUse - Supplies an optional socket bound to NETLINK to use for the
1690 query.
1691
1692 Return Value:
1693
1694 Returns 0 on success, -1 on failure.
1695
1696 --*/
1697
1698 {
1699
1700 socklen_t AddressLength;
1701 bool CloseSocket;
1702 struct nlmsghdr* Header;
1703 struct ifinfomsg* InterfaceInfo;
1704 int InterfaceIndex;
1705 size_t InterfaceNameLength;
1706 char ReceiveBuffer[5000];
1707 int ReceiveResult;
1708 int Result;
1709 int Socket;
1710
1711 struct _RequestMessage
1712 {
1713 struct nlmsghdr Header;
1714 struct ifinfomsg Message __attribute__((aligned(NLMSG_ALIGNTO)));
1715 struct
1716 {
1717 struct rtattr RtHeader __attribute__((aligned(RTA_ALIGNTO)));
1718 char InterfaceName[32] __attribute__((aligned(RTA_ALIGNTO)));
1719 } Attribute;
1720 } RequestMessage;
1721
1722 if (SocketToUse != NULL)
1723 {
1724 CloseSocket = false;
1725 Socket = *SocketToUse;
1726 }
1727 else
1728 {
1729
1730 //
1731 // Create and bind socket. Create a RTM_GETLINK request.
1732 //
1733
1734 LxtCheckErrno(Socket = socket(AF_NETLINK, SOCK_RAW, 0));
1735 CloseSocket = true;
1736 LxtCheckErrno(BindSocketForNetlink(Socket));
1737 }
1738
1739 memset(&RequestMessage, 0, sizeof(RequestMessage));
1740 RequestMessage.Header.nlmsg_type = RTM_GETLINK;
1741 RequestMessage.Header.nlmsg_seq = LXT_REQUEST_SEQUENCE;
1742 ;
1743 RequestMessage.Message.ifi_family = AF_NETLINK;
1744 RequestMessage.Header.nlmsg_flags = NLM_F_REQUEST;
1745 InterfaceNameLength = strlen(InterfaceName) + 1;
1746 LxtCheckGreaterOrEqual(sizeof(RequestMessage.Attribute.InterfaceName), InterfaceNameLength, "%lu");
1747
1748 RequestMessage.Attribute.RtHeader.rta_len = RTA_LENGTH(InterfaceNameLength);
1749 RequestMessage.Attribute.RtHeader.rta_type = IFLA_IFNAME;
1750 memcpy(RequestMessage.Attribute.InterfaceName, InterfaceName, InterfaceNameLength);
1751
1752 RequestMessage.Header.nlmsg_len = offsetof(struct _RequestMessage, Attribute.InterfaceName) + InterfaceNameLength;
1753
1754 LxtCheckErrno(sendto(Socket, &RequestMessage, RequestMessage.Header.nlmsg_len, 0, NULL, 0));
1755
1756 LxtCheckErrno(ReceiveResult = recv(Socket, ReceiveBuffer, sizeof(ReceiveBuffer), 0));
1757
1758 Header = (struct nlmsghdr*)ReceiveBuffer;
1759 LxtCheckTrue(NLMSG_OK(Header, ReceiveResult));
1760 LxtCheckEqual(Header->nlmsg_type, RTM_NEWLINK, "%d");
1761 LxtCheckGreaterOrEqual((Header->nlmsg_len + 1), NLMSG_PAYLOAD(Header, sizeof(*InterfaceInfo)), "%d");
1762
1763 InterfaceInfo = NLMSG_DATA(Header);
1764 if (SocketToUse == NULL)
1765 {
1766 LxtCheckErrno(InterfaceIndex = GetNetworkInterfaceIndex(InterfaceName));
1767 LxtCheckEqual(InterfaceIndex, InterfaceInfo->ifi_index, "%d");
1768 }
1769
1770 ErrorExit:
1771 if (CloseSocket)
1772 {
1773 close(Socket);
1774 }
1775
1776 return Result;
1777 }
1778
1779 int VirtualBridgeAutoName(PLXT_ARGS Args)
1780
1781 /*++
1782
1783 Routine Description:
1784
1785 This routine creates and deletes new bridges, allowing the system to
1786 assign them default "bridgexx" names.
1787
1788 Arguments:
1789
1790 Args - Supplies the command line arguments.
1791
1792 Return Value:
1793
1794 Returns 0 on success, -1 on failure.
1795
1796 --*/
1797
1798 {
1799
1800 bool DeleteDeviceOne;
1801 bool DeleteDeviceTwo;
1802 int Result;
1803
1804 DeleteDeviceOne = false;
1805 DeleteDeviceTwo = false;
1806
1807 LxtCheckResult(CreateVirtualBridgeViaNetlink(""));
1808 DeleteDeviceOne = true;
1809 LxtCheckErrno(GetNetworkInterfaceIndex("bridge0"));
1810 LxtCheckResult(CreateVirtualBridgeViaNetlink(""));
1811 DeleteDeviceTwo = true;
1812 LxtCheckErrno(GetNetworkInterfaceIndex("bridge1"));
1813
1814 ErrorExit:
1815 if (DeleteDeviceTwo)
1816 {
1817 (void)DeleteVirtualDeviceViaNetlink("bridge1");
1818 }
1819
1820 if (DeleteDeviceOne)
1821 {
1822 (void)DeleteVirtualDeviceViaNetlink("bridge0");
1823 }
1824
1825 return Result;
1826 }
1827
1828 int VirtualBridgeFromIoctl1(PLXT_ARGS Args)
1829
1830 /*++
1831
1832 Routine Description:
1833
1834 This routine creates and deletes a new bridge using UNIX socket ioctls.
1835
1836 Arguments:
1837
1838 Args - Supplies the command line arguments.
1839
1840 Return Value:
1841
1842 Returns 0 on success, -1 on failure.
1843
1844 --*/
1845
1846 {
1847
1848 int Result;
1849
1850 LxtCheckResult(CreateVirtualBridgeViaIoctl("testbridge"));
1851 LxtCheckErrno(GetNetworkInterfaceIndex("testbridge"));
1852 LxtCheckResult(DeleteVirtualBridgeViaIoctl("testbridge"));
1853 LxtCheckErrnoFailure(GetNetworkInterfaceIndex("testbridge"), ENODEV);
1854
1855 ErrorExit:
1856 return Result;
1857 }
1858
1859 int VirtualBridgeFromNetlink1(PLXT_ARGS Args)
1860
1861 /*++
1862
1863 Routine Description:
1864
1865 This routine creates and deletes a new bridge using netlink messages.
1866
1867 Arguments:
1868
1869 Args - Supplies the command line arguments.
1870
1871 Return Value:
1872
1873 Returns 0 on success, -1 on failure.
1874
1875 --*/
1876
1877 {
1878
1879 bool DeleteDevice;
1880 int Result;
1881
1882 DeleteDevice = false;
1883
1884 LxtCheckResult(CreateVirtualBridgeViaNetlink("testbridge"));
1885 DeleteDevice = true;
1886 LxtCheckErrno(GetNetworkInterfaceIndex("testbridge"));
1887 LxtCheckResult(DeleteVirtualDeviceViaNetlink("testbridge"));
1888 DeleteDevice = false;
1889 LxtCheckErrnoFailure(GetNetworkInterfaceIndex("testbridge"), ENODEV);
1890
1891 ErrorExit:
1892 if (DeleteDevice)
1893 {
1894 (void)DeleteVirtualDeviceViaNetlink("testbridge");
1895 }
1896
1897 return Result;
1898 }
1899
1900 int VirtualBridgeNamespace1(PLXT_ARGS Args)
1901
1902 /*++
1903
1904 Routine Description:
1905
1906 This routine does basic network namespace sanity testing with a bridge:
1907 1) creates a new virtual bridge device
1908 1) creates a new namespace
1909 3) try to move the bridge into the other namespace - should fail.
1910
1911 Arguments:
1912
1913 Args - Supplies the command line arguments.
1914
1915 Return Value:
1916
1917 Returns 0 on success, -1 on failure.
1918
1919 --*/
1920
1921 {
1922
1923 bool DeleteDevice;
1924 int NewNetworkNamespaceFd;
1925 int OriginalNetworkNamespaceFd;
1926 int Response;
1927 int Result;
1928
1929 DeleteDevice = false;
1930 NewNetworkNamespaceFd = 0;
1931 OriginalNetworkNamespaceFd = 0;
1932
1933 //
1934 // Open file descriptor of default network namespace.
1935 //
1936
1937 LxtCheckErrno(OriginalNetworkNamespaceFd = open("/proc/self/ns/net", 0));
1938
1939 //
1940 // Create a new virtual bridge.
1941 //
1942
1943 LxtCheckResult(CreateVirtualBridgeViaNetlink("testbridge"));
1944 DeleteDevice = true;
1945
1946 //
1947 // Switch to a new network namespace.
1948 //
1949
1950 LxtCheckErrno(unshare(CLONE_NEWNET));
1951
1952 //
1953 // Open file descriptor of the new network namespace.
1954 //
1955
1956 LxtCheckErrno(NewNetworkNamespaceFd = open("/proc/self/ns/net", 0));
1957
1958 //
1959 // Switch back to original network namespace.
1960 //
1961
1962 LxtCheckErrno(setns(OriginalNetworkNamespaceFd, CLONE_NEWNET));
1963
1964 //
1965 // Try to move the bridge into the new namespace. This should fail as
1966 // bridges are not allowed to move between namespaces.
1967 //
1968
1969 LxtCheckResult(SetVirtualDeviceAttributeViaNetlink("testbridge", IFLA_NET_NS_FD, NewNetworkNamespaceFd, &Response));
1970
1971 LxtCheckEqual(Response, -EINVAL, "%d");
1972
1973 //
1974 // Delete the device.
1975 //
1976
1977 LxtCheckResult(DeleteVirtualDeviceViaNetlink("testbridge"));
1978 DeleteDevice = false;
1979
1980 ErrorExit:
1981 if (NewNetworkNamespaceFd > 0)
1982 {
1983 close(NewNetworkNamespaceFd);
1984 }
1985
1986 if (OriginalNetworkNamespaceFd > 0)
1987 {
1988 close(OriginalNetworkNamespaceFd);
1989 }
1990
1991 if (DeleteDevice)
1992 {
1993 (void)DeleteVirtualDeviceViaNetlink("testbridge");
1994 }
1995
1996 return Result;
1997 }
1998
1999 int VirtualEthernetPairFromNetlink1(PLXT_ARGS Args)
2000
2001 /*++
2002
2003 Routine Description:
2004
2005 This routine creates and deletes a new virtual ethernet pair using netlink
2006 messages. The delete is performed on the primary device.
2007
2008 Arguments:
2009
2010 Args - Supplies the command line arguments.
2011
2012 Return Value:
2013
2014 Returns 0 on success, -1 on failure.
2015
2016 --*/
2017
2018 {
2019
2020 bool DeleteDevice;
2021 int Result;
2022
2023 DeleteDevice = false;
2024
2025 LxtCheckResult(CreateVirtualEthernetPairViaNetlink("veth_tst0", "veth_tst1"));
2026 LxtCheckErrno(GetNetworkInterfaceIndex("veth_tst0"));
2027 LxtCheckErrno(GetNetworkInterfaceIndex("veth_tst1"));
2028 LxtCheckResult(DeleteVirtualDeviceViaNetlink("veth_tst0"));
2029 LxtCheckErrnoFailure(GetNetworkInterfaceIndex("veth_tst0"), ENODEV);
2030 LxtCheckErrnoFailure(GetNetworkInterfaceIndex("veth_tst1"), ENODEV);
2031
2032 ErrorExit:
2033 if (DeleteDevice)
2034 {
2035 (void)DeleteVirtualDeviceViaNetlink("veth_tst0");
2036 }
2037
2038 return Result;
2039 }
2040
2041 int VirtualEthernetPairFromNetlink2(PLXT_ARGS Args)
2042
2043 /*++
2044
2045 Routine Description:
2046
2047 This routine creates and deletes a new virtual ethernet pair using netlink
2048 messages. The delete is performed on the peer device.
2049
2050 Arguments:
2051
2052 Args - Supplies the command line arguments.
2053
2054 Return Value:
2055
2056 Returns 0 on success, -1 on failure.
2057
2058 --*/
2059
2060 {
2061
2062 bool DeleteDevice;
2063 int Result;
2064
2065 DeleteDevice = false;
2066
2067 LxtCheckResult(CreateVirtualEthernetPairViaNetlink("veth_tst0", "veth_tst1"));
2068 DeleteDevice = true;
2069 LxtCheckErrno(GetNetworkInterfaceIndex("veth_tst0"));
2070 LxtCheckErrno(GetNetworkInterfaceIndex("veth_tst1"));
2071 LxtCheckResult(DeleteVirtualDeviceViaNetlink("veth_tst1"));
2072 DeleteDevice = false;
2073 LxtCheckErrnoFailure(GetNetworkInterfaceIndex("veth_tst0"), ENODEV);
2074 LxtCheckErrnoFailure(GetNetworkInterfaceIndex("veth_tst1"), ENODEV);
2075
2076 ErrorExit:
2077 if (DeleteDevice)
2078 {
2079 (void)DeleteVirtualDeviceViaNetlink("veth_tst1");
2080 }
2081
2082 return Result;
2083 }
2084
2085 int VirtualEthernetPairNamespace1(PLXT_ARGS Args)
2086
2087 /*++
2088
2089 Routine Description:
2090
2091 This routine does basic network namespace sanity testing with a virtual
2092 ethernet pair:
2093 1) creates a new virtual ethernet pair
2094 2) creates a new namespace
2095 3) try to move one end of the pair into the other namespace
2096
2097 Arguments:
2098
2099 Args - Supplies the command line arguments.
2100
2101 Return Value:
2102
2103 Returns 0 on success, -1 on failure.
2104
2105 --*/
2106
2107 {
2108
2109 bool DeleteDevice;
2110 int NewNetworkNamespaceFd;
2111 int OriginalNetworkNamespaceFd;
2112 int Response;
2113 int Result;
2114
2115 DeleteDevice = false;
2116 NewNetworkNamespaceFd = 0;
2117 OriginalNetworkNamespaceFd = 0;
2118
2119 //
2120 // Open file descriptor of default network namespace.
2121 //
2122
2123 LxtCheckErrno(OriginalNetworkNamespaceFd = open("/proc/self/ns/net", 0));
2124
2125 //
2126 // Create a new virtual ethernet pair.
2127 //
2128
2129 LxtCheckResult(CreateVirtualEthernetPairViaNetlink("veth0", "veth1"));
2130 DeleteDevice = true;
2131
2132 //
2133 // Switch to a new network namespace.
2134 //
2135
2136 LxtCheckErrno(unshare(CLONE_NEWNET));
2137
2138 //
2139 // Open file descriptor of the new network namespace.
2140 //
2141
2142 LxtCheckErrno(NewNetworkNamespaceFd = open("/proc/self/ns/net", 0));
2143
2144 //
2145 // Switch back to original network namespace.
2146 //
2147
2148 LxtCheckErrno(setns(OriginalNetworkNamespaceFd, CLONE_NEWNET));
2149
2150 //
2151 // Try to move one half of the pair into the new namespace.
2152 //
2153
2154 LxtCheckResult(SetVirtualDeviceAttributeViaNetlink("veth1", IFLA_NET_NS_FD, NewNetworkNamespaceFd, &Response));
2155
2156 LxtCheckEqual(Response, 0, "%d");
2157
2158 //
2159 // Delete the device.
2160 //
2161
2162 LxtCheckResult(DeleteVirtualDeviceViaNetlink("veth0"));
2163 DeleteDevice = false;
2164
2165 ErrorExit:
2166 if (NewNetworkNamespaceFd > 0)
2167 {
2168 close(NewNetworkNamespaceFd);
2169 }
2170
2171 if (OriginalNetworkNamespaceFd > 0)
2172 {
2173 (void)setns(OriginalNetworkNamespaceFd, CLONE_NEWNET);
2174 close(OriginalNetworkNamespaceFd);
2175 }
2176
2177 if (DeleteDevice)
2178 {
2179 (void)DeleteVirtualDeviceViaNetlink("veth0");
2180 }
2181
2182 return Result;
2183 }
2184
2185 int VirtualEthernetPairNamespace2(PLXT_ARGS Args)
2186
2187 /*++
2188
2189 Routine Description:
2190
2191 This routine does basic network namespace sanity testing with a virtual
2192 ethernet pair:
2193 1) create a virtual ethernet pair.
2194 2) create a new namespace
2195 3) move one end of the pair into the new namespace.
2196 4) create another virtual ethernet pair using the same name as that of
2197 the moved end.
2198 5) try to move the same-named end again.
2199
2200 Arguments:
2201
2202 Args - Supplies the command line arguments.
2203
2204 Return Value:
2205
2206 Returns 0 on success, -1 on failure.
2207
2208 --*/
2209
2210 {
2211
2212 bool DeleteFirstDevice;
2213 bool DeleteSecondDevice;
2214 int NewNetworkNamespaceFd;
2215 int OriginalNetworkNamespaceFd;
2216 int Response;
2217 int Result;
2218
2219 DeleteFirstDevice = false;
2220 DeleteSecondDevice = false;
2221 NewNetworkNamespaceFd = 0;
2222 OriginalNetworkNamespaceFd = 0;
2223
2224 //
2225 // Open file descriptor of default network namespace.
2226 //
2227
2228 LxtCheckErrno(OriginalNetworkNamespaceFd = open("/proc/self/ns/net", 0));
2229
2230 //
2231 // Create a new virtual ethernet pair.
2232 //
2233
2234 LxtCheckResult(CreateVirtualEthernetPairViaNetlink("veth0", "veth1"));
2235 DeleteFirstDevice = true;
2236
2237 //
2238 // Switch to a new network namespace.
2239 //
2240
2241 LxtCheckErrno(unshare(CLONE_NEWNET));
2242
2243 //
2244 // Open file descriptor of the new network namespace.
2245 //
2246
2247 LxtCheckErrno(NewNetworkNamespaceFd = open("/proc/self/ns/net", 0));
2248
2249 //
2250 // Switch back to original network namespace.
2251 //
2252
2253 LxtCheckErrno(setns(OriginalNetworkNamespaceFd, CLONE_NEWNET));
2254
2255 //
2256 // Try to move one half of the pair into the new namespace.
2257 //
2258
2259 LxtCheckResult(SetVirtualDeviceAttributeViaNetlink("veth1", IFLA_NET_NS_FD, NewNetworkNamespaceFd, &Response));
2260
2261 LxtCheckEqual(Response, 0, "%d");
2262
2263 //
2264 // Create a new virtual ethernet pair, re-using the moved name.
2265 //
2266
2267 LxtCheckResult(CreateVirtualEthernetPairViaNetlink("veth2", "veth1"));
2268 DeleteSecondDevice = true;
2269
2270 //
2271 // Try to move it again, expecting failure.
2272 //
2273
2274 LxtCheckErrno(setns(OriginalNetworkNamespaceFd, CLONE_NEWNET));
2275 LxtCheckResult(SetVirtualDeviceAttributeViaNetlink("veth1", IFLA_NET_NS_FD, NewNetworkNamespaceFd, &Response));
2276
2277 LxtCheckEqual(Response, -EEXIST, "%d");
2278
2279 //
2280 // Cleanup.
2281 //
2282
2283 LxtCheckResult(DeleteVirtualDeviceViaNetlink("veth0"));
2284 DeleteFirstDevice = false;
2285 LxtCheckResult(DeleteVirtualDeviceViaNetlink("veth2"));
2286 DeleteSecondDevice = false;
2287
2288 ErrorExit:
2289 if (NewNetworkNamespaceFd > 0)
2290 {
2291 close(NewNetworkNamespaceFd);
2292 }
2293
2294 if (OriginalNetworkNamespaceFd > 0)
2295 {
2296 (void)setns(OriginalNetworkNamespaceFd, CLONE_NEWNET);
2297 close(OriginalNetworkNamespaceFd);
2298 }
2299
2300 if (DeleteFirstDevice)
2301 {
2302 (void)DeleteVirtualDeviceViaNetlink("veth0");
2303 }
2304
2305 if (DeleteSecondDevice)
2306 {
2307 (void)DeleteVirtualDeviceViaNetlink("veth2");
2308 }
2309
2310 return Result;
2311 }
2312
2313 int VirtualEthernetPairNamespace3(PLXT_ARGS Args)
2314
2315 /*++
2316
2317 Routine Description:
2318
2319 This routine does basic network namespace sanity testing with a virtual
2320 ethernet pair:
2321 1) creates a new virtual ethernet pair
2322 2) creates a new namespace
2323 3) move one end of the pair into the other namespace
2324 4) close the new namespace
2325
2326 Arguments:
2327
2328 Args - Supplies the command line arguments.
2329
2330 Return Value:
2331
2332 Returns 0 on success, -1 on failure.
2333
2334 --*/
2335
2336 {
2337
2338 bool DeleteDevice;
2339 int NewNetworkNamespaceFd;
2340 int OriginalNetworkNamespaceFd;
2341 int Response;
2342 int Result;
2343
2344 DeleteDevice = false;
2345 NewNetworkNamespaceFd = 0;
2346 OriginalNetworkNamespaceFd = 0;
2347
2348 //
2349 // Open file descriptor of default network namespace.
2350 //
2351
2352 LxtCheckErrno(OriginalNetworkNamespaceFd = open("/proc/self/ns/net", 0));
2353
2354 //
2355 // Create a new virtual ethernet pair.
2356 //
2357
2358 LxtCheckResult(CreateVirtualEthernetPairViaNetlink("veth0", "veth1"));
2359 DeleteDevice = true;
2360
2361 //
2362 // Switch to a new network namespace.
2363 //
2364
2365 LxtCheckErrno(unshare(CLONE_NEWNET));
2366
2367 //
2368 // Open file descriptor of the new network namespace.
2369 //
2370
2371 LxtCheckErrno(NewNetworkNamespaceFd = open("/proc/self/ns/net", 0));
2372
2373 //
2374 // Switch back to original network namespace.
2375 //
2376
2377 LxtCheckErrno(setns(OriginalNetworkNamespaceFd, CLONE_NEWNET));
2378
2379 //
2380 // Try to move one half of the pair into the new namespace.
2381 //
2382
2383 LxtCheckResult(SetVirtualDeviceAttributeViaNetlink("veth1", IFLA_NET_NS_FD, NewNetworkNamespaceFd, &Response));
2384
2385 LxtCheckEqual(Response, 0, "%d");
2386
2387 //
2388 // Close the new namespace.
2389 //
2390
2391 LxtCheckClose(NewNetworkNamespaceFd);
2392
2393 //
2394 // Both endpoints should have been deleted when the namespace was closed.
2395 // Delay a bit to let the state settle.
2396 //
2397
2398 sleep(1);
2399 LxtCheckErrnoFailure(GetNetworkInterfaceIndex("veth0"), ENODEV);
2400 DeleteDevice = false;
2401
2402 ErrorExit:
2403 if (NewNetworkNamespaceFd > 0)
2404 {
2405 close(NewNetworkNamespaceFd);
2406 }
2407
2408 if (OriginalNetworkNamespaceFd > 0)
2409 {
2410 (void)setns(OriginalNetworkNamespaceFd, CLONE_NEWNET);
2411 close(OriginalNetworkNamespaceFd);
2412 }
2413
2414 if (DeleteDevice)
2415 {
2416 (void)DeleteVirtualDeviceViaNetlink("veth0");
2417 }
2418
2419 return Result;
2420 }
2421
2422 int VirtualEthernetPairNamespace4(PLXT_ARGS Args)
2423
2424 /*++
2425
2426 Routine Description:
2427
2428 This routine does simple validation on network interface link information
2429 when creating virtual ethernet adapters and moving them between namespaces.
2430
2431 Arguments:
2432
2433 Args - Supplies the command line arguments.
2434
2435 Return Value:
2436
2437 Returns 0 on success, -1 on failure.
2438
2439 --*/
2440
2441 {
2442
2443 bool DeleteDevice;
2444 int NewNetworkNamespaceFd;
2445 int OriginalNetworkNamespaceFd;
2446 int Response;
2447 int Result;
2448
2449 DeleteDevice = false;
2450 NewNetworkNamespaceFd = 0;
2451 OriginalNetworkNamespaceFd = 0;
2452
2453 //
2454 // Open file descriptor of default network namespace.
2455 //
2456
2457 LxtCheckErrno(OriginalNetworkNamespaceFd = open("/proc/self/ns/net", 0));
2458
2459 //
2460 // Create a new virtual ethernet pair.
2461 //
2462
2463 LxtCheckResult(CreateVirtualEthernetPairViaNetlink("veth0", "veth1"));
2464 DeleteDevice = true;
2465
2466 //
2467 // Switch to a new network namespace.
2468 //
2469
2470 LxtCheckErrno(unshare(CLONE_NEWNET));
2471
2472 //
2473 // Open file descriptor of the new network namespace.
2474 //
2475
2476 LxtCheckErrno(NewNetworkNamespaceFd = open("/proc/self/ns/net", 0));
2477
2478 //
2479 // Switch back to original network namespace.
2480 //
2481
2482 LxtCheckErrno(setns(OriginalNetworkNamespaceFd, CLONE_NEWNET));
2483
2484 //
2485 // Check the route link entries.
2486 //
2487
2488 LxtCheckResult(VerifyRouteLinkExists("veth0", NULL));
2489 LxtCheckResult(VerifyRouteLinkExists("veth1", NULL));
2490
2491 //
2492 // Try to move one half of the pair into the new namespace.
2493 //
2494
2495 LxtCheckResult(SetVirtualDeviceAttributeViaNetlink("veth1", IFLA_NET_NS_FD, NewNetworkNamespaceFd, &Response));
2496
2497 LxtCheckEqual(Response, 0, "%d");
2498
2499 //
2500 // Check the route link entries.
2501 //
2502
2503 LxtCheckErrno(setns(NewNetworkNamespaceFd, CLONE_NEWNET));
2504 LxtCheckResult(VerifyRouteLinkExists("veth1", NULL));
2505 LxtCheckErrno(setns(OriginalNetworkNamespaceFd, CLONE_NEWNET));
2506 LxtCheckResult(VerifyRouteLinkExists("veth0", NULL));
2507
2508 //
2509 // Close the new namespace, and wait a second for state to settle.
2510 //
2511
2512 LxtCheckClose(NewNetworkNamespaceFd);
2513 sleep(1);
2514
2515 //
2516 // The namespace deletion should have removed the devices.
2517 //
2518
2519 LxtCheckResult(VerifyRouteLinkDoesNotExist("veth0", NULL));
2520 DeleteDevice = false;
2521 LxtCheckResult(VerifyRouteLinkDoesNotExist("veth1", NULL));
2522
2523 ErrorExit:
2524 if (NewNetworkNamespaceFd > 0)
2525 {
2526 close(NewNetworkNamespaceFd);
2527 }
2528
2529 if (OriginalNetworkNamespaceFd > 0)
2530 {
2531 (void)setns(OriginalNetworkNamespaceFd, CLONE_NEWNET);
2532 close(OriginalNetworkNamespaceFd);
2533 }
2534
2535 if (DeleteDevice)
2536 {
2537 (void)DeleteVirtualDeviceViaNetlink("veth0");
2538 }
2539
2540 return Result;
2541 }
2542
2543 int VirtualEthernetPairNamespace5(PLXT_ARGS Args)
2544
2545 /*++
2546
2547 Routine Description:
2548
2549 This routine does simple validation of socket creation being tied to the
2550 network namespace.
2551
2552 Arguments:
2553
2554 Args - Supplies the command line arguments.
2555
2556 Return Value:
2557
2558 Returns 0 on success, -1 on failure.
2559
2560 --*/
2561
2562 {
2563
2564 bool DeleteDevice;
2565 int NewNetworkNamespaceFd;
2566 int OriginalNetworkNamespaceFd;
2567 int Response;
2568 int Result;
2569 int SocketNewNs;
2570
2571 DeleteDevice = false;
2572 NewNetworkNamespaceFd = 0;
2573 OriginalNetworkNamespaceFd = 0;
2574
2575 //
2576 // Open file descriptor of default network namespace.
2577 //
2578
2579 LxtCheckErrno(OriginalNetworkNamespaceFd = open("/proc/self/ns/net", 0));
2580
2581 //
2582 // Create a new virtual ethernet pair.
2583 //
2584
2585 LxtCheckResult(CreateVirtualEthernetPairViaNetlink("veth0", "veth1"));
2586 DeleteDevice = true;
2587
2588 //
2589 // Switch to a new network namespace.
2590 //
2591
2592 LxtCheckErrno(unshare(CLONE_NEWNET));
2593
2594 //
2595 // Create a socket while in the new network namespace.
2596 //
2597
2598 LxtCheckErrno(SocketNewNs = socket(AF_NETLINK, SOCK_RAW, 0));
2599
2600 //
2601 // Open file descriptor of the new network namespace.
2602 //
2603
2604 LxtCheckErrno(NewNetworkNamespaceFd = open("/proc/self/ns/net", 0));
2605
2606 //
2607 // Switch back to original network namespace.
2608 //
2609
2610 LxtCheckErrno(setns(OriginalNetworkNamespaceFd, CLONE_NEWNET));
2611
2612 //
2613 // Bind the socket created in the new network namespace.
2614 //
2615
2616 LxtCheckErrno(BindSocketForNetlink(SocketNewNs));
2617
2618 //
2619 // Check the route link entries.
2620 //
2621
2622 LxtCheckResult(VerifyRouteLinkExists("veth0", NULL));
2623 LxtCheckResult(VerifyRouteLinkExists("veth1", NULL));
2624
2625 //
2626 // Check the non-existence of the entries with the other socket.
2627 //
2628
2629 LxtCheckResult(VerifyRouteLinkDoesNotExist("veth0", &SocketNewNs));
2630 LxtCheckResult(VerifyRouteLinkDoesNotExist("veth1", &SocketNewNs));
2631
2632 //
2633 // Try to move one half of the pair into the new namespace.
2634 //
2635
2636 LxtCheckResult(SetVirtualDeviceAttributeViaNetlink("veth1", IFLA_NET_NS_FD, NewNetworkNamespaceFd, &Response));
2637
2638 LxtCheckEqual(Response, 0, "%d");
2639
2640 //
2641 // Check the route link entries.
2642 //
2643
2644 LxtCheckResult(VerifyRouteLinkExists("veth0", NULL));
2645 LxtCheckResult(VerifyRouteLinkDoesNotExist("veth0", &SocketNewNs));
2646 LxtCheckResult(VerifyRouteLinkDoesNotExist("veth1", NULL));
2647 LxtCheckResult(VerifyRouteLinkExists("veth1", &SocketNewNs));
2648
2649 //
2650 // Close the new namespace and the related socket, and wait a second for
2651 // state to settle.
2652 //
2653
2654 LxtCheckClose(SocketNewNs);
2655 SocketNewNs = 0;
2656 LxtCheckClose(NewNetworkNamespaceFd);
2657 sleep(1);
2658
2659 //
2660 // The namespace deletion should have removed the devices.
2661 //
2662
2663 LxtCheckResult(VerifyRouteLinkDoesNotExist("veth0", NULL));
2664 DeleteDevice = false;
2665 LxtCheckResult(VerifyRouteLinkDoesNotExist("veth1", NULL));
2666
2667 ErrorExit:
2668 if (SocketNewNs > 0)
2669 {
2670 close(SocketNewNs);
2671 }
2672
2673 if (NewNetworkNamespaceFd > 0)
2674 {
2675 close(NewNetworkNamespaceFd);
2676 }
2677
2678 if (OriginalNetworkNamespaceFd > 0)
2679 {
2680 (void)setns(OriginalNetworkNamespaceFd, CLONE_NEWNET);
2681 close(OriginalNetworkNamespaceFd);
2682 }
2683
2684 if (DeleteDevice)
2685 {
2686 (void)DeleteVirtualDeviceViaNetlink("veth0");
2687 }
2688
2689 return Result;
2690 }
2691
2692 int VirtualEthernetPairConfigure(PLXT_ARGS Args)
2693
2694 /*++
2695
2696 Routine Description:
2697
2698 This routine creates a virtual ethernet pair and attempts to bring them up
2699 and assign them static IP addresses.
2700
2701 Arguments:
2702
2703 Args - Supplies the command line arguments.
2704
2705 Return Value:
2706
2707 Returns 0 on success, -1 on failure.
2708
2709 --*/
2710
2711 {
2712
2713 bool DeleteDevice;
2714 struct in_addr AddressIpv4;
2715 int Response;
2716 int Result;
2717
2718 DeleteDevice = false;
2719
2720 //
2721 // Create a new virtual ethernet pair.
2722 //
2723
2724 LxtCheckResult(CreateVirtualEthernetPairViaNetlink("veth0", "veth1"));
2725 DeleteDevice = true;
2726
2727 //
2728 // Bring the interfaces up and assign static IP addresses.
2729 //
2730
2731 LxtCheckResult(SetVirtualDeviceFlagViaNetlink("veth0", IFF_UP, true, &Response));
2732
2733 LxtCheckEqual(Response, 0, "%d");
2734 inet_aton(LXT_IP_ADDRESS1, &AddressIpv4);
2735 LxtCheckResult(SetIpAddress("veth0", &AddressIpv4, 32));
2736
2737 LxtCheckResult(SetVirtualDeviceFlagViaNetlink("veth1", IFF_UP, true, &Response));
2738
2739 LxtCheckEqual(Response, 0, "%d");
2740 inet_aton(LXT_IP_ADDRESS2, &AddressIpv4);
2741 LxtCheckResult(SetIpAddress("veth1", &AddressIpv4, 32));
2742
2743 //
2744 // Try to delete the device.
2745 //
2746
2747 LxtCheckResult(DeleteVirtualDeviceViaNetlink("veth0"));
2748 DeleteDevice = false;
2749
2750 ErrorExit:
2751 if (DeleteDevice)
2752 {
2753 (void)DeleteVirtualDeviceViaNetlink("veth0");
2754 }
2755
2756 return Result;
2757 }
2758
2759 int VirtualEthernetPairData(PLXT_ARGS Args)
2760
2761 /*++
2762
2763 Routine Description:
2764
2765
2766 Arguments:
2767
2768 Args - Supplies the command line arguments.
2769
2770 Return Value:
2771
2772 Returns 0 on success, -1 on failure.
2773
2774 --*/
2775
2776 {
2777
2778 struct sockaddr_in AddressIpv4 = {};
2779 socklen_t AddressLength;
2780 ssize_t BytesReceived;
2781 ssize_t BytesSent;
2782 bool DeleteDevice;
2783 struct sockaddr_in FromAddressIpv4;
2784 ;
2785 char RecvBuffer[10] = {0};
2786 int Response;
2787 int Result;
2788 char SendBuffer[10] = {"123456789"};
2789 int Socket;
2790 int Socket2;
2791
2792 DeleteDevice = false;
2793 Socket = -1;
2794 Socket2 = -1;
2795
2796 //
2797 // Make sure the loopback adapter is up.
2798 //
2799
2800 (void)SetVirtualDeviceFlagViaNetlink("lo", IFF_UP, true, &Response);
2801
2802 //
2803 // Create a new virtual ethernet pair.
2804 //
2805
2806 LxtCheckResult(CreateVirtualEthernetPairViaNetlink("veth0", "veth1"));
2807 DeleteDevice = true;
2808
2809 //
2810 // Bring the interfaces up and assign static IP addresses.
2811 //
2812
2813 LxtCheckResult(SetVirtualDeviceFlagViaNetlink("veth0", IFF_UP, true, &Response));
2814
2815 LxtCheckEqual(Response, 0, "%d");
2816 AddressIpv4.sin_family = AF_INET;
2817 inet_aton(LXT_IP_ADDRESS1, &AddressIpv4.sin_addr);
2818 LxtCheckResult(SetIpAddress("veth0", &AddressIpv4.sin_addr, 32));
2819 LxtCheckErrno((Socket = socket(AF_INET, SOCK_DGRAM, 0)));
2820 LxtCheckErrno(bind(Socket, (struct sockaddr*)&AddressIpv4, sizeof(AddressIpv4)));
2821
2822 LxtCheckResult(SetVirtualDeviceFlagViaNetlink("veth1", IFF_UP, true, &Response));
2823
2824 LxtCheckEqual(Response, 0, "%d");
2825 LxtCheckResult(SetRoute("veth1", &AddressIpv4.sin_addr, 32));
2826 inet_aton(LXT_IP_ADDRESS2, &AddressIpv4.sin_addr);
2827 LxtCheckResult(SetIpAddress("veth1", &AddressIpv4.sin_addr, 32));
2828 LxtCheckErrno((Socket2 = socket(AF_INET, SOCK_DGRAM, 0)));
2829 LxtCheckErrno(bind(Socket2, (struct sockaddr*)&AddressIpv4, sizeof(AddressIpv4)));
2830
2831 //
2832 // Send a packet between the devices.
2833 //
2834
2835 AddressLength = sizeof(AddressIpv4);
2836 LxtCheckErrno(getsockname(Socket2, (struct sockaddr*)&AddressIpv4, &AddressLength));
2837
2838 LxtCheckEqual(AddressLength, sizeof(AddressIpv4), "%lu");
2839 LxtCheckResult(SetRoute("veth0", &AddressIpv4.sin_addr, 32));
2840 LxtLogInfo("AddressIpv4.sin_family = %d", AddressIpv4.sin_family);
2841 LxtLogInfo("AddressIpv4.sin_port = %d", AddressIpv4.sin_port);
2842 LxtLogInfo("AddressIpv4.sin_addr = %08x", AddressIpv4.sin_addr.s_addr);
2843 LxtCheckErrno((BytesSent = sendto(Socket, SendBuffer, sizeof(SendBuffer), 0, (struct sockaddr*)&AddressIpv4, sizeof(AddressIpv4))));
2844
2845 LxtCheckEqual(BytesSent, sizeof(SendBuffer), "%lu");
2846 AddressLength = sizeof(FromAddressIpv4);
2847 LxtCheckErrno((BytesReceived = recvfrom(Socket2, RecvBuffer, sizeof(RecvBuffer), 0, (struct sockaddr*)&FromAddressIpv4, &AddressLength)));
2848
2849 LxtCheckEqual(BytesReceived, sizeof(SendBuffer), "%lu");
2850 LxtCheckMemoryEqual(RecvBuffer, SendBuffer, BytesReceived);
2851 LxtCheckEqual(AddressLength, sizeof(FromAddressIpv4), "%lu");
2852
2853 //
2854 // Try to delete the device.
2855 //
2856
2857 LxtCheckResult(DeleteVirtualDeviceViaNetlink("veth0"));
2858 DeleteDevice = false;
2859
2860 ErrorExit:
2861 if (Socket > 0)
2862 {
2863 close(Socket);
2864 }
2865
2866 if (Socket2 > 0)
2867 {
2868 close(Socket2);
2869 }
2870
2871 if (DeleteDevice)
2872 {
2873 (void)DeleteVirtualDeviceViaNetlink("veth0");
2874 }
2875
2876 return Result;
2877 }
2878
2879 int VirtualEthernetPairNamespaceData(PLXT_ARGS Args)
2880
2881 /*++
2882
2883 Routine Description:
2884
2885
2886 Arguments:
2887
2888 Args - Supplies the command line arguments.
2889
2890 Return Value:
2891
2892 Returns 0 on success, -1 on failure.
2893
2894 --*/
2895
2896 {
2897
2898 struct sockaddr_in AddressIpv4 = {};
2899 socklen_t AddressLength;
2900 ssize_t BytesReceived;
2901 ssize_t BytesSent;
2902 bool DeleteDevice;
2903 struct sockaddr_in FromAddressIpv4;
2904 ;
2905 int NewNetworkNamespaceFd;
2906 int OriginalNetworkNamespaceFd;
2907 char RecvBuffer[10] = {0};
2908 int Response;
2909 int Result;
2910 char SendBuffer[10] = {"123456789"};
2911 int Socket;
2912 int Socket2;
2913
2914 DeleteDevice = false;
2915 NewNetworkNamespaceFd = 0;
2916 OriginalNetworkNamespaceFd = 0;
2917 Socket = -1;
2918 Socket2 = -1;
2919
2920 //
2921 // Open file descriptor of default network namespace.
2922 //
2923
2924 LxtCheckErrno(OriginalNetworkNamespaceFd = open("/proc/self/ns/net", 0));
2925
2926 //
2927 // Switch to a new network namespace.
2928 //
2929
2930 LxtCheckErrno(unshare(CLONE_NEWNET));
2931
2932 //
2933 // Open file descriptor of the new network namespace.
2934 //
2935
2936 LxtCheckErrno(NewNetworkNamespaceFd = open("/proc/self/ns/net", 0));
2937
2938 //
2939 // Switch back to original network namespace.
2940 //
2941
2942 LxtCheckErrno(setns(OriginalNetworkNamespaceFd, CLONE_NEWNET));
2943
2944 //
2945 // Create a new virtual ethernet pair.
2946 //
2947
2948 LxtCheckResult(CreateVirtualEthernetPairViaNetlink("veth0", "veth1"));
2949 DeleteDevice = true;
2950
2951 //
2952 // Try to move one half of the pair into the new namespace.
2953 //
2954
2955 LxtCheckResult(SetVirtualDeviceAttributeViaNetlink("veth1", IFLA_NET_NS_FD, NewNetworkNamespaceFd, &Response));
2956
2957 LxtCheckEqual(Response, 0, "%d");
2958
2959 //
2960 // Bring the interfaces up and assign static IP addresses.
2961 //
2962
2963 LxtCheckResult(SetVirtualDeviceFlagViaNetlink("veth0", IFF_UP, true, &Response));
2964
2965 LxtCheckEqual(Response, 0, "%d");
2966 AddressIpv4.sin_family = AF_INET;
2967 inet_aton(LXT_IP_ADDRESS1, &AddressIpv4.sin_addr);
2968 LxtCheckResult(SetIpAddress("veth0", &AddressIpv4.sin_addr, 32));
2969 LxtCheckErrno((Socket = socket(AF_INET, SOCK_DGRAM, 0)));
2970 LxtCheckErrno(bind(Socket, (struct sockaddr*)&AddressIpv4, sizeof(AddressIpv4)));
2971
2972 //
2973 // Switch to the new network namespace to configure the other endpoint.
2974 //
2975
2976 LxtCheckErrno(setns(NewNetworkNamespaceFd, CLONE_NEWNET));
2977 LxtCheckResult(SetVirtualDeviceFlagViaNetlink("veth1", IFF_UP, true, &Response));
2978
2979 LxtCheckEqual(Response, 0, "%d");
2980 LxtCheckResult(SetRoute("veth1", &AddressIpv4.sin_addr, 32));
2981 inet_aton(LXT_IP_ADDRESS2, &AddressIpv4.sin_addr);
2982 LxtCheckResult(SetIpAddress("veth1", &AddressIpv4.sin_addr, 32));
2983
2984 //
2985 // Open UDP sockets to try to send and receive on the IP addresses assigned
2986 // above.
2987 //
2988
2989 LxtCheckErrno((Socket2 = socket(AF_INET, SOCK_DGRAM, 0)));
2990 LxtCheckErrno(bind(Socket2, (struct sockaddr*)&AddressIpv4, sizeof(AddressIpv4)));
2991
2992 AddressLength = sizeof(AddressIpv4);
2993 LxtCheckErrno(getsockname(Socket2, (struct sockaddr*)&AddressIpv4, &AddressLength));
2994
2995 LxtCheckEqual(AddressLength, sizeof(AddressIpv4), "%lu");
2996
2997 //
2998 // Switch back to original network namespace.
2999 //
3000
3001 LxtCheckErrno(setns(OriginalNetworkNamespaceFd, CLONE_NEWNET));
3002
3003 //
3004 // Send a packet between the devices.
3005 //
3006
3007 LxtCheckResult(SetRoute("veth0", &AddressIpv4.sin_addr, 32));
3008 LxtLogInfo("AddressIpv4.sin_family = %d", AddressIpv4.sin_family);
3009 LxtLogInfo("AddressIpv4.sin_port = %d", AddressIpv4.sin_port);
3010 LxtLogInfo("AddressIpv4.sin_addr = %08x", AddressIpv4.sin_addr.s_addr);
3011 LxtCheckErrno((BytesSent = sendto(Socket, SendBuffer, sizeof(SendBuffer), 0, (struct sockaddr*)&AddressIpv4, sizeof(AddressIpv4))));
3012
3013 LxtCheckEqual(BytesSent, sizeof(SendBuffer), "%lu");
3014 AddressLength = sizeof(FromAddressIpv4);
3015 LxtCheckErrno((BytesReceived = recvfrom(Socket2, RecvBuffer, sizeof(RecvBuffer), 0, (struct sockaddr*)&FromAddressIpv4, &AddressLength)));
3016
3017 LxtCheckEqual(BytesReceived, sizeof(SendBuffer), "%lu");
3018 LxtCheckMemoryEqual(RecvBuffer, SendBuffer, BytesReceived);
3019 LxtCheckEqual(AddressLength, sizeof(FromAddressIpv4), "%lu");
3020
3021 //
3022 // Try to delete the device.
3023 //
3024
3025 LxtCheckResult(DeleteVirtualDeviceViaNetlink("veth0"));
3026 DeleteDevice = false;
3027
3028 ErrorExit:
3029 if (NewNetworkNamespaceFd > 0)
3030 {
3031 close(NewNetworkNamespaceFd);
3032 }
3033
3034 if (OriginalNetworkNamespaceFd > 0)
3035 {
3036 (void)setns(OriginalNetworkNamespaceFd, CLONE_NEWNET);
3037 close(OriginalNetworkNamespaceFd);
3038 }
3039
3040 if (Socket > 0)
3041 {
3042 close(Socket);
3043 }
3044
3045 if (Socket2 > 0)
3046 {
3047 close(Socket2);
3048 }
3049
3050 if (DeleteDevice)
3051 {
3052 (void)DeleteVirtualDeviceViaNetlink("veth0");
3053 }
3054
3055 return Result;
3056 }