-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathipconfigd.c
More file actions
10309 lines (9248 loc) · 282 KB
/
Copy pathipconfigd.c
File metadata and controls
10309 lines (9248 loc) · 282 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright (c) 1999-2025 Apple Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* ipconfigd.c
* - daemon that configures interfaces using manual settings,
* manual with DHCP INFORM, BOOTP, or DHCP
*/
/*
* Modification History
*
* September, 1999 Dieter Siegmund (dieter@apple.com)
* - initial revision
*
* May 8, 2000 Dieter Siegmund (dieter@apple.com)
* - re-architected to be event-driven to satisfy mobility
* requirements
* - converted to use a single main configuration thread
* instead of a thread per interface
* - removed dependency on objective C
*
* June 12, 2000 Dieter Siegmund (dieter@apple.com)
* - converted to use CFRunLoop
* - added ability to change the configuration on the fly, either by
* a configuration data change, or having the user send a command
* via ipconfig
*
* July 5, 2000 Dieter Siegmund (dieter@apple.com)
* - added code to publish information with configd
* - wrote common IP config module to read information from the cache,
* and update the default route, DNS, and netinfo parent(s) on the fly
*
* August 20, 2000 Dieter Siegmund (dieter@apple.com)
* - moved common IP config module to configd_plugins/IPMonitor.bproj
* - added code to handle information from setup/cache only
*
* October 4, 2000 Dieter Siegmund (dieter@apple.com)
* - added code to handle error cases and force the interface
* state to be ready to avoid hanging the system startup in case
* there is bad data in the cache
*
* November 20, 2000 Dieter Siegmund (dieter@apple.com)
* - changed to use new preferences keys and service-based configuration
*
* March 27, 2001 Dieter Siegmund (dieter@apple.com)
* - turned ipconfigd into the IPConfiguration bundle
*
* May 17, 2001 Dieter Siegmund (dieter@apple.com)
* - publish information in service state instead of interface state
*
* June 14, 2001 Dieter Siegmund (dieter@apple.com)
* - publish DHCP options in dynamic store, and allow third party
* applications to request additional options using a DHCPClient
* preference
* - add notification handler to automatically force the DHCP client
* to renew its lease
*
* July 12, 2001 Dieter Siegmund (dieter@apple.com)
* - don't bother reporting arp collisions with our own interfaces
*
* July 19, 2001 Dieter Siegmund (dieter@apple.com)
* - port to use public SystemConfiguration APIs
*
* August 28, 2001 Dieter Siegmund (dieter@apple.com)
* - when multiple interfaces are configured to be on the same subnet,
* keep the subnet route correct and have it follow the service/interface
* with the highest priority
* - this also eliminates problems with the subnet route getting lost
* when an interface is de-configured, yet another interface is on
* the same subnet
*
* September 10, 2001 Dieter Siegmund (dieter@apple.com)
* - added multiple service per interface support
* - separated ad-hoc/link-local address configuration into its own service
*
* January 4, 2002 Dieter Siegmund (dieter@apple.com)
* - always configure the link-local service on the service with the
* highest priority service that's active
* - modified link-local service to optionally allocate an IP address;
* if we don't allocate an IP, we just set the link-local subnet
* - allow a previously failed DHCP service to acquire a link-local IP
* address if it later becomes the primary service
* - a link-local address will only be allocated when a DHCP service fails,
* and it is the primary service, and the G_dhcp_failure_configures_linklocal
* is TRUE
*
* February 1, 2002 Dieter Siegmund (dieter@apple.com)
* - make IPConfiguration netboot-aware:
* + grab the DHCP information from the packet in the device tree
*
* May 20, 2002 Dieter Siegmund (dieter@apple.com)
* - allocate a link-local address more quickly, after the first
* DHCP request fails
* - re-structured the automatic link-local service allocation to do
* most of the work from a run-loop observer instead of within the
* context of the caller; this avoids unnecessary re-entrancy issues
* and complexity
*
* December 3, 2002 Dieter Siegmund (dieter@apple.com)
* - add support to detect ARP collisions after we have already
* assigned ourselves the address
*
* June 16, 2003 Dieter Siegmund (dieter@apple.com)
* - added support for firewire (IFT_IEEE1394)
*
* November 19, 2003 Dieter Siegmund (dieter@apple.com)
* - added support for VLAN's (IFT_L2VLAN)
*
* April 13, 2005 Dieter Siegmund (dieter@apple.com)
* - added support for multiple link-local services, one per interface
* - changed logic to favor a successful service (i.e. one with an IP address)
* over simply the highest ranked service per interface
* - maintain the link-local subnet on the interface with the highest ranked
* active service
*
* October 20, 2006 Dieter Siegmund (dieter@apple.com)
* - resolve the router's MAC address using ARP, and publish that
* information to the NetworkSignature in the IPv4 dict
*
* December 19, 2007 Dieter Siegmund (dieter@apple.com)
* - removed subnet route maintenance code since IPMonitor now takes
* care of that
*
* September 4, 2009 Dieter Siegmund (dieter@apple.com)
* - added support for IPv6 configuration
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/wait.h>
#include <sys/errno.h>
#include <sys/socket.h>
#define KERNEL_PRIVATE
#include <sys/ioctl.h>
#undef KERNEL_PRIVATE
#include <ctype.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <net/firewire.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <netinet/ip.h>
#include <netinet/bootp.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <paths.h>
#include <syslog.h>
#include <net/if_types.h>
#include <mach/boolean.h>
#include "ipconfigd_globals.h"
#include <SystemConfiguration/SystemConfiguration.h>
#include <SystemConfiguration/SCPrivate.h>
#include <SystemConfiguration/SCValidation.h>
#include <SystemConfiguration/SCDPlugin.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
#include <TargetConditionals.h>
#include <Availability.h>
#include <os/state_private.h>
#include <os/variant_private.h>
#if TARGET_OS_OSX
#include <CoreFoundation/CFUserNotification.h>
#include <CoreFoundation/CFUserNotificationPriv.h>
#include <IOKit/pwr_mgt/IOPMLibPrivate.h>
#endif /* TARGET_OS_OSX */
#include <CommonCrypto/CommonDigest.h>
#include "rfc_options.h"
#include "dhcp_options.h"
#include "interfaces.h"
#include "util.h"
#include "IPv4ClasslessRoute.h"
#include "dhcplib.h"
#include "ioregpath.h"
#include "ipconfig_types.h"
#include "ipconfigd.h"
#include "server.h"
#include "timer.h"
#include "ipconfigd_threads.h"
#include "FDSet.h"
#include "symbol_scope.h"
#include "cfutil.h"
#include "sysconfig.h"
#include "ifutil.h"
#include "rtutil.h"
#include "DHCPv6Client.h"
#include "DHCPv6Socket.h"
#include "IPConfigurationServiceInternal.h"
#include "IPConfigurationControlPrefs.h"
#include "CGA.h"
#include "ICMPv6Socket.h"
#include "DHCPDUIDIAID.h"
#include "report_symptoms.h"
#include "bootp_transmit.h"
#include "wireless.h"
#define IPCONFIGURATION_SUBSYSTEM "com.apple.SystemConfiguration.IPConfiguration"
#define RIFLAGS_IADDR_VALID ((uint32_t)0x1)
#define RIFLAGS_HWADDR_VALID ((uint32_t)0x2)
#define RIFLAGS_ARP_VERIFIED ((uint32_t)0x4)
#define RIFLAGS_RESOLVE_IN_PROGRESS ((uint32_t)0x8)
#define RIFLAGS_RESOLVE_TIMED_OUT ((uint32_t)0x10)
#define RIFLAGS_ALL_VALID (RIFLAGS_IADDR_VALID \
| RIFLAGS_HWADDR_VALID \
| RIFLAGS_ARP_VERIFIED)
#define IPV6_LL_MAX_COLLISION_COUNT 3
typedef struct {
uint32_t flags;
struct in_addr iaddr;
uint8_t hwaddr[MAX_LINK_ADDR_LEN];
} router_info_t;
STATIC void service_router_clear_arp_verified(ServiceRef service_p);
STATIC void service_router_set_resolve_in_progress(ServiceRef service_p);
STATIC void service_router_clear_resolve_in_progress(ServiceRef service_p);
STATIC boolean_t service_router_resolve_in_progress(ServiceRef service_p);
STATIC void service_router_set_resolve_timed_out(ServiceRef service_p);
STATIC void service_router_clear_resolve_timed_out(ServiceRef service_p);
STATIC boolean_t service_router_resolve_timed_out(ServiceRef service_p);
typedef struct IFState * IFStateRef;
typedef struct {
struct in_addr addr;
struct in_addr mask;
struct in_addr dest;
} ip_addr_mask_t;
typedef struct {
ip_addr_mask_t requested_ip;
inet_addrinfo_t info;
router_info_t router;
absolute_time_t ip_assigned_time;
absolute_time_t ip_conflict_time;
int ip_conflict_count;
} ServiceIPv4, * ServiceIPv4Ref;
typedef struct {
struct in6_addr addr;
int prefix_length;
} inet6_addr_prefix_t;
typedef struct {
inet6_addr_prefix_t requested_ip;
struct in6_addr router; /* manual_v6 only */
boolean_t enable_clat46;
boolean_t disable_dhcpv6;
boolean_t have_signature; /* rtadv only */
} ServiceIPv6, * ServiceIPv6Ref;
struct ServiceInfo {
CFStringRef serviceID;
CFStringRef apn_name;
IFStateRef ifstate;
ipconfig_method_t method;
ipconfig_status_t status;
boolean_t is_dynamic;
boolean_t no_publish;
boolean_t ready;
CFStringRef parent_serviceID;
CFStringRef child_serviceID;
dispatch_source_t pid_source;
boolean_t busy;
boolean_t address_acquisition_failure;
void * private;
#if TARGET_OS_OSX
CFUserNotificationRef user_notification;
CFRunLoopSourceRef user_rls;
#endif /* TARGET_OS_OSX */
union {
ServiceIPv4 v4;
ServiceIPv6 v6;
} u;
};
typedef struct {
boolean_t needs_attention;
boolean_t requested;
} ActiveDuringSleepInfo, * ActiveDuringSleepInfoRef;
typedef struct {
boolean_t interface_disabled;
boolean_t prefs_set;
boolean_t prefs_requested;
} DisableUntilNeededInfo, * DisableUntilNeededInfoRef;
typedef CF_ENUM(uint32_t, IFStateFlags) {
kIFStateFlagsStartupReady = 0x00000001,
kIFStateFlagsBusy = 0x00000002,
kIFStateFlagsServicesReady = 0x00000004,
kIFStateFlagsFailureSymptomReported = 0x00000008,
kIFStateFlagsNetBoot = 0x00000010,
kIFStateFlagsLinkTimerSuppressed = 0x00000020,
kIFStateFlagsIPv4PublishNeedsAttention = 0x00000040,
kIFStateFlagsIPv4AddressesScrubbed = 0x00000080,
kIFStateFlagsDisableCGA = 0x00010000,
kIFStateFlagsDisablePerformNUD = 0x00020000,
kIFStateFlagsDisableDAD = 0x00040000,
kIFStateFlagsPLATDiscoveryComplete = 0x00080000,
kIFStateFlagsNAT64PrefixAvailable = 0x00100000,
kIFStateFlagsCLAT46Available = 0x00200000,
kIFStateFlagsCLAT46Active = 0x00400000,
};
struct IFState {
IFStateFlags flags;
interface_t * if_p;
CFStringRef ifname;
dynarray_t services;
dynarray_t services_v6;
ServiceRef linklocal_service_p;
WiFiInfoRef wifi_info_p;
WiFiConnectionID wifi_connectionID;
timer_callout_t * timer;
struct in_addr v4_link_local;
uint32_t wake_generation;
struct in6_addr ipv6_linklocal;
CFMutableArrayRef neighbor_advert_list;
ActiveDuringSleepInfo active_during_sleep;
DisableUntilNeededInfo disable_until_needed;
unsigned int rank;
uint8_t v6_ll_collision_count;
};
STATIC Boolean
FlagsAreSet(uint32_t flags, uint32_t flags_to_check)
{
return ((flags & flags_to_check) != 0);
}
STATIC Boolean
IFStateFlagsAreSet(IFStateRef ifstate, IFStateFlags flags)
{
return (FlagsAreSet(ifstate->flags, flags));
}
STATIC void
IFStateFlagsSet(IFStateRef ifstate, IFStateFlags flags)
{
ifstate->flags |= flags;
}
STATIC void
IFStateFlagsClear(IFStateRef ifstate, IFStateFlags flags)
{
ifstate->flags &= ~flags;
}
STATIC void
IFStateFlagsSetOrClear(IFStateRef ifstate, IFStateFlags flags,
boolean_t set)
{
if (set) {
IFStateFlagsSet(ifstate, flags);
}
else {
IFStateFlagsClear(ifstate, flags);
}
}
typedef dynarray_t IFStateList_t;
typedef void (^ServiceInitHandler)(ServiceRef service);
#define IS_IPV4 TRUE
#define IS_IPV6 FALSE
#ifndef kSCEntNetRefreshConfiguration
#define kSCEntNetRefreshConfiguration CFSTR("RefreshConfiguration")
#endif /* kSCEntNetRefreshConfiguration */
#ifndef kSCEntNetIPv4ARPCollision
#define kSCEntNetIPv4ARPCollision CFSTR("IPv4ARPCollision")
#endif /* kSCEntNetIPv4ARPCollision */
#ifndef kSCEntNetNAT64
#define kSCEntNetNAT64 CFSTR("NAT64")
#endif /* kSCEntNetNAT64 */
#ifndef kSCValNetIPv4ConfigMethodFailover
static const CFStringRef kIPConfigurationConfigMethodFailover = CFSTR("Failover");
#define kSCValNetIPv4ConfigMethodFailover kIPConfigurationConfigMethodFailover
#endif /* kSCValNetIPv4ConfigMethodFailover */
#ifndef kSCValNetIPv6ConfigMethodLinkLocal
static const CFStringRef kIPConfigurationIPv6ConfigMethodLinkLocal = CFSTR("LinkLocal");
#define kSCValNetIPv6ConfigMethodLinkLocal kIPConfigurationIPv6ConfigMethodLinkLocal
#endif /* kSCValNetIPv6ConfigMethodLinkLocal */
#ifndef kSCPropNetIPv4FailoverAddressTimeout
static const CFStringRef kIPConfigurationFailoverAddressTimeout = CFSTR("FailoverAddressTimeout");
#define kSCPropNetIPv4FailoverAddressTimeout kIPConfigurationFailoverAddressTimeout
#endif /* kSCPropNetIPv4FailoverAddressTimeout */
#ifndef kSCPropNetIgnoreLinkStatus
static const CFStringRef kIPConfigurationIgnoreLinkStatus = CFSTR("IgnoreLinkStatus");
#define kSCPropNetIgnoreLinkStatus kIPConfigurationIgnoreLinkStatus
#endif /* kSCPropNetIgnoreLinkStatus */
#ifndef kSCPropNetIPv66to4Relay
static const CFStringRef kSCPropNetIPv66to4Relay = CFSTR("6to4Relay");
#endif /* kSCPropNetIPv66to4Relay */
#ifndef kSCPropNetIPv6EnableCGA
/* CFNumber (0,1), default 1 */
static const CFStringRef kSCPropNetIPv6EnableCGA = CFSTR("EnableCGA");
#define kSCPropNetIPv6EnableCGA kSCPropNetIPv6EnableCGA
#endif /* kSCPropNetIPv66to4Relay */
#ifndef kSCPropNetIPv6LinkLocalAddress
static const CFStringRef kSCPropNetIPv6LinkLocalAddress = CFSTR("LinkLocalAddress");
#define kSCPropNetIPv6LinkLocalAddress kSCPropNetIPv6LinkLocalAddress
#endif /* kSCPropNetIPv6LinkLocalAddress */
#ifndef kSCPropNetIPv6PerformPLATDiscovery
static const CFStringRef kSCPropNetIPv6PerformPLATDiscovery = CFSTR("PerformPLATDiscovery");
#define kSCPropNetIPv6PerformPLATDiscovery kSCPropNetIPv6PerformPLATDiscovery
#endif /* kSCPropNetIPv6PerformPLATDiscovery */
#ifndef kSCPropNetNAT64PLATDiscoveryCompletionTime
static const CFStringRef kSCPropNetNAT64PLATDiscoveryCompletionTime = CFSTR("PLATDiscoveryCompletionTime");
#endif /* kSCPropNetNAT64PLATDiscoveryCompletionTime */
#ifndef kSCPropNetIPv4CLAT46
static const CFStringRef kSCPropNetIPv4CLAT46 = CFSTR("CLAT46");
#define kSCPropNetIPv4CLAT46 kSCPropNetIPv4CLAT46
#endif /* kSCPropNetIPv4CLAT46 */
#ifndef kSCEntNetInterfaceActiveDuringSleepRequested
#define kSCEntNetInterfaceActiveDuringSleepRequested CFSTR("ActiveDuringSleepRequested")
#endif /* kSCEntNetInterfaceActiveDuringSleepRequested */
#ifndef kSCEntNetInterfaceActiveDuringSleepSupported
#define kSCEntNetInterfaceActiveDuringSleepSupported CFSTR("ActiveDuringSleepSupported")
#endif /* kSCEntNetInterfaceActiveDuringSleepSupported */
#ifndef kSCPropNetInterfaceDisableUntilNeeded
/* number (0,1) */
#define kSCPropNetInterfaceDisableUntilNeeded CFSTR("DisableUntilNeeded")
#endif /* kSCPropNetInterfaceDisableUntilNeeded */
#ifndef kSCEntNetIPv6RouterExpired
#define kSCEntNetIPv6RouterExpired CFSTR("IPv6RouterExpired")
#endif /* kSCEntNetIPv6RouterExpired */
#ifndef kSCEntNetInterfaceIPConfigurationBusy
#define kSCEntNetInterfaceIPConfigurationBusy CFSTR("IPConfigurationBusy")
#endif /* kSCEntNetInterfaceIPConfigurationBusy */
#define k_DisableUntilNeeded CFSTR("_DisableUntilNeeded") /* bool */
#define kDHCPClientPreferencesID CFSTR("DHCPClient.plist")
#define kDHCPClientApplicationPref CFSTR("Application")
#define kDHCPRequestedParameterList CFSTR("DHCPRequestedParameterList")
#define kDHCPv6RequestedOptions CFSTR("DHCPv6RequestedOptions")
/* default values */
#define MAX_RETRIES 9
#define INITIAL_WAIT_SECS 1
#define MAX_WAIT_SECS 8
#define GATHER_SECS 1
#define LINK_INACTIVE_WAIT_SECS 0.1
#define DHCP_INIT_REBOOT_RETRY_COUNT 2
#define DHCP_SELECT_RETRY_COUNT 3
#define DHCP_ROUTER_ARP_AT_RETRY_COUNT 3
#define DHCP_ALLOCATE_LINKLOCAL_AT_RETRY_COUNT 4
#define DHCP_GENERATE_FAILURE_SYMPTOM_AT_RETRY_COUNT 6
#define DHCP_FAILURE_CONFIGURES_LINKLOCAL TRUE
#define DHCP_SUCCESS_DECONFIGURES_LINKLOCAL TRUE
#define DHCP_LOCAL_HOSTNAME_LENGTH_MAX 15
#define DISCOVER_ROUTER_MAC_ADDRESS_SECS 60
#define DEFEND_IP_ADDRESS_INTERVAL_SECS 10
#define DEFEND_IP_ADDRESS_COUNT 5
#define DHCP_LEASE_WRITE_T1_THRESHOLD_SECS 3600
#define MANUAL_CONFLICT_RETRY_INTERVAL_SECS 300
#define USER_ERROR 1
#define UNEXPECTED_ERROR 2
#define TIMEOUT_ERROR 3
/* global variables */
PRIVATE_EXTERN uint16_t G_client_port = IPPORT_BOOTPC;
PRIVATE_EXTERN boolean_t G_dhcp_accepts_bootp = FALSE;
PRIVATE_EXTERN boolean_t G_dhcp_failure_configures_linklocal
= DHCP_FAILURE_CONFIGURES_LINKLOCAL;
PRIVATE_EXTERN boolean_t G_dhcp_success_deconfigures_linklocal
= DHCP_SUCCESS_DECONFIGURES_LINKLOCAL;
PRIVATE_EXTERN int G_dhcp_allocate_linklocal_at_retry_count
= DHCP_ALLOCATE_LINKLOCAL_AT_RETRY_COUNT;
PRIVATE_EXTERN int G_dhcp_generate_failure_symptom_at_retry_count
= DHCP_GENERATE_FAILURE_SYMPTOM_AT_RETRY_COUNT;
PRIVATE_EXTERN int G_dhcp_router_arp_at_retry_count
= DHCP_ROUTER_ARP_AT_RETRY_COUNT;
PRIVATE_EXTERN int G_dhcp_init_reboot_retry_count
= DHCP_INIT_REBOOT_RETRY_COUNT;
PRIVATE_EXTERN int G_dhcp_select_retry_count
= DHCP_SELECT_RETRY_COUNT;
PRIVATE_EXTERN int G_dhcp_lease_write_t1_threshold_secs
= DHCP_LEASE_WRITE_T1_THRESHOLD_SECS;
PRIVATE_EXTERN uint16_t G_server_port = IPPORT_BOOTPS;
PRIVATE_EXTERN int G_manual_conflict_retry_interval_secs
= MANUAL_CONFLICT_RETRY_INTERVAL_SECS;
PRIVATE_EXTERN boolean_t G_is_netboot = FALSE;
PRIVATE_EXTERN IPConfigurationInterfaceTypes
G_awd_interface_types = kIPConfigurationInterfaceTypesCellular;
;
/*
* Static: S_link_inactive_secs
* Purpose:
* Time to wait after the link goes inactive before unpublishing
* the interface state information
*/
static CFTimeInterval S_link_inactive_secs = LINK_INACTIVE_WAIT_SECS;
/*
* Global: G_gather_secs
* Purpose:
* Time to wait for the ideal packet after receiving
* the first acceptable packet.
*/
int G_gather_secs = GATHER_SECS;
/*
* Global: G_initial_wait_secs
* Purpose:
* First timeout interval in seconds.
*/
int G_initial_wait_secs = INITIAL_WAIT_SECS;
/*
* Global: G_max_retries
* Purpose:
* Number of times to retry sending the packet.
*/
int G_max_retries = MAX_RETRIES;
/*
* Global: G_max_wait_secs
* Purpose:
* Maximum timeout interval. Timeouts timeout[i] are chosen as:
* i = 0:
* timeout[0] = G_initial_wait_secs;
* i > 0:
* timeout[i] = min(timeout[i - 1] * 2, G_max_wait_secs);
* If G_initial_wait_secs = 4, G_max_wait_secs = 16, the sequence is:
* 4, 8, 16, 16, ...
*/
int G_max_wait_secs = MAX_WAIT_SECS;
boolean_t G_must_broadcast;
Boolean G_IPConfiguration_verbose;
boolean_t G_router_arp = TRUE;
int G_router_arp_wifi_lease_start_threshold_secs = (3600 * 24); /* 1 day */
boolean_t G_discover_and_publish_router_mac_address = TRUE;
#define DHCPv6_ENABLED TRUE
#define DHCPv6_STATEFUL_ENABLED TRUE
boolean_t G_dhcpv6_enabled = DHCPv6_ENABLED;
boolean_t G_dhcpv6_stateful_enabled = DHCPv6_STATEFUL_ENABLED;
DHCPDUIDType G_dhcp_duid_type;
const unsigned char G_rfc_magic[4] = RFC_OPTIONS_MAGIC;
const struct in_addr G_ip_broadcast = { INADDR_BROADCAST };
const struct in_addr G_ip_zeroes = { 0 };
#define MIN_SHORT_WAKE_INTERVAL_SECS 60
PRIVATE_EXTERN int G_min_short_wake_interval_secs = MIN_SHORT_WAKE_INTERVAL_SECS;
#define MIN_WAKE_INTERVAL_SECS (60 * 15)
PRIVATE_EXTERN int G_min_wake_interval_secs = MIN_WAKE_INTERVAL_SECS;
#define WAKE_SKEW_SECS 30
PRIVATE_EXTERN int G_wake_skew_secs = WAKE_SKEW_SECS;
/* local variables */
static interface_list_t * S_interfaces;
static CFBundleRef S_bundle;
static boolean_t S_sockets_need_close;
static boolean_t S_linklocal_needs_attention;
static boolean_t S_ipv4_publish_needs_attention;
static IFStateList_t S_ifstate_list;
static io_connect_t S_power_connection;
static SCDynamicStoreRef S_scd_session;
static CFStringRef S_setup_service_prefix;
static CFStringRef S_state_interface_prefix;
static char * S_dhcp_hostname;
static char * S_dns_hostname;
static CFStringRef S_computer_name_key;
static CFStringRef S_hostnames_key;
static int S_arp_probe_count = ARP_PROBE_COUNT;
static int S_arp_gratuitous_count = ARP_GRATUITOUS_COUNT;
static CFTimeInterval S_arp_retry = ARP_RETRY_SECS;
static int S_arp_detect_count = ARP_DETECT_COUNT;
static CFTimeInterval S_arp_detect_retry = ARP_DETECT_RETRY_SECS;
static int S_discover_router_mac_address_secs
= DISCOVER_ROUTER_MAC_ADDRESS_SECS;
static int S_arp_conflict_retry = ARP_CONFLICT_RETRY_COUNT;
static CFTimeInterval S_arp_conflict_delay = ARP_CONFLICT_RETRY_DELAY_SECS;
static int S_defend_ip_address_interval_secs
= DEFEND_IP_ADDRESS_INTERVAL_SECS;
static int S_defend_ip_address_count
= DEFEND_IP_ADDRESS_COUNT;
static int S_dhcp_local_hostname_length_max = DHCP_LOCAL_HOSTNAME_LENGTH_MAX;
static struct in_addr S_netboot_ip;
static struct in_addr S_netboot_server_ip;
static char S_netboot_ifname[IFNAMSIZ + 1];
static boolean_t S_awake = TRUE;
#if TARGET_OS_OSX
static boolean_t S_use_maintenance_wake = TRUE;
static boolean_t S_wake_event_sent;
static boolean_t S_hide_wifi_info;
static boolean_t S_hide_wifi_info_was_set;
#endif /* TARGET_OS_OSX */
static uint32_t S_wake_generation;
static absolute_time_t S_wake_time;
static boolean_t S_configure_ipv6 = TRUE;
STATIC boolean_t S_active_during_sleep_needs_attention;
STATIC boolean_t S_disable_until_needed_needs_attention;
STATIC boolean_t S_disable_unneeded_interfaces = TRUE;
static boolean_t S_cellular_clat46_autoenable;
static boolean_t S_ipv6_linklocal_modifier_expires;
#define PROP_SERVICEID CFSTR("ServiceID")
/*
* forward declarations
*/
STATIC void
schedule_async_work(void);
static void
S_add_dhcp_parameters(SCPreferencesRef prefs);
static void
configuration_changed(SCDynamicStoreRef session);
static ipconfig_status_t
config_method_event(ServiceRef service_p, IFEventID_t event, void * data);
static ipconfig_status_t
config_method_start(ServiceRef service_p, ipconfig_method_info_t info);
static ipconfig_status_t
config_method_change(ServiceRef service_p,
ipconfig_method_info_t info,
boolean_t * needs_stop);
static ipconfig_status_t
config_method_stop(ServiceRef service_p);
static ipconfig_status_t
config_method_media(ServiceRef service_p, link_event_data_t link_event);
static ipconfig_status_t
config_method_bssid_changed(ServiceRef service_p);
static ipconfig_status_t
config_method_renew(ServiceRef service_p, link_event_data_t link_event);
static void
service_publish_clear(ServiceRef service_p, ipconfig_status_t status);
static boolean_t
all_services_ready();
static void
linklocal_elect(CFArrayRef service_order);
static CFArrayRef
S_copy_service_order(SCDynamicStoreRef session);
static __inline__ IFStateRef
service_ifstate(ServiceRef service_p)
{
return (service_p->ifstate);
}
static __inline__ void
service_set_apn_name(ServiceRef service_p, CFStringRef apn_name)
{
if (apn_name != NULL) {
CFRetain(apn_name);
}
if (service_p->apn_name != NULL) {
CFRelease(service_p->apn_name);
}
service_p->apn_name = apn_name;
return;
}
static void
service_add_ipv4_router_info_to_dict(ServiceRef service_p,
CFMutableDictionaryRef dict,
boolean_t include_signature);
static boolean_t
S_get_plist_boolean_quiet(CFDictionaryRef plist, CFStringRef key,
boolean_t def);
static int
S_get_plist_int_quiet(CFDictionaryRef plist, CFStringRef key,
int def);
typedef unsigned int Rank;
#define RANK_HIGHEST (0)
#define RANK_LOWEST (1024 * 1024)
#define RANK_NONE (RANK_LOWEST + 1)
static IFStateRef
IFStateList_ifstate_with_name(IFStateList_t * list, const char * ifname,
int * where);
static IFStateRef
IFStateListGetIFState(IFStateList_t * list, CFStringRef ifname,
int * where);
static void
IFStateFreeService(IFStateRef ifstate, ServiceRef service_p);
static ServiceRef
IFState_service_with_ip(IFStateRef ifstate, struct in_addr iaddr);
static void
IFState_set_wifi_info(IFStateRef ifstate, WiFiInfoRef info_p);
STATIC void
IFStateSetActiveDuringSleepRequested(IFStateRef ifstate, boolean_t requested);
STATIC void
IFStateProcessActiveDuringSleep(IFStateRef ifstate);
STATIC boolean_t
IFStateGetDisableUntilNeededRequested(IFStateRef ifstate);
STATIC void
IFStateSetDisableUntilNeededRequested(IFStateRef ifstate, CFBooleanRef req);
STATIC boolean_t
IFState_attach_IPv6(IFStateRef ifstate, boolean_t set_iff_up);
STATIC void
IFState_detach_IPv4(IFStateRef ifstate);
STATIC void
IFState_detach_IPv6(IFStateRef ifstate);
STATIC const struct in6_addr *
IFStateIPv6LinkLocalAddress(IFStateRef ifstate);
STATIC void
IFStateSetIPv6LinkLocalAddress(IFStateRef ifstate,
const struct in6_addr * addr);
STATIC void
IFStateUpdateAddressAcquisitionFailureSymptom(IFStateRef ifstate,
ServiceRef service_p);
STATIC ServiceRef
IFStateFindServiceWithAddressAcquisitionFailure(IFStateRef ifstate);
STATIC ServiceRef
IFStateGetFirstRoutableService(IFStateRef ifstate);
static void
linklocal_start(ServiceRef parent_service_p, boolean_t allocate);
static WiFiInfoRef
S_copy_wifi_info(CFStringRef ifname);
static void
S_remove_ip_address(const char * ifname, struct in_addr this_ip);
STATIC ipconfig_status_t
S_remove_service_with_id_str(const char * ifname, CFStringRef serviceID);
static ipconfig_status_t
method_info_from_dict(CFDictionaryRef dict,
ipconfig_method_info_t method_info);
static ipconfig_status_t
method_info_from_ipv6_dict(CFDictionaryRef dict,
ipconfig_method_info_t method_info);
STATIC CFDictionaryRef
ServiceIPv4CopyMergedDNSAndCaptive(ServiceRef service_p,
dhcp_info_t * info_p,
CFDictionaryRef *capport_dict_p);
STATIC CFDictionaryRef
ServiceIPv6CopyMergedDNSAndCaptive(ServiceRef service_p,
ipv6_info_t * info_v6_p,
CFDictionaryRef * ret_capport_dict);
STATIC Rank
ServiceGetRank(ServiceRef service_p, CFArrayRef service_order);
STATIC CFDictionaryRef
ServiceCopySummary(ServiceRef service_p);
STATIC void
ServiceSetIPv4PublishNeedsAttention(ServiceRef service_p);
STATIC void
ServiceSetIsPublished(ServiceRef service_p);
STATIC void
process_link_timer_expired(IFStateRef ifstate);
static void
service_list_event(dynarray_t * services_p, IFEventID_t event, void * data);
static ServiceRef
service_list_first_routable_service(dynarray_t * list);
STATIC boolean_t
service_list_check_busy(dynarray_t * services_p);
static ServiceRef
service_list_get_address_acquisition_failure(dynarray_t * services_p);
PRIVATE_EXTERN const char *
ipconfig_method_string(ipconfig_method_t m)
{
const char * str;
switch (m) {
case ipconfig_method_none_e:
str = "NONE";
break;
case ipconfig_method_none_v4_e:
str = "NONE-V4";
break;
case ipconfig_method_none_v6_e:
str = "NONE-V6";
break;
case ipconfig_method_manual_e:
str = "MANUAL";
break;
case ipconfig_method_bootp_e:
str = "BOOTP";
break;
case ipconfig_method_dhcp_e:
str = "DHCP";
break;
case ipconfig_method_inform_e:
str = "INFORM";
break;
case ipconfig_method_linklocal_e:
str = "LINKLOCAL";
break;
case ipconfig_method_failover_e:
str = "FAILOVER";
break;
case ipconfig_method_manual_v6_e:
str = "MANUAL-V6";
break;
case ipconfig_method_automatic_v6_e:
str = "AUTOMATIC-V6";
break;
case ipconfig_method_rtadv_e:
str = "RTADV";
break;
case ipconfig_method_stf_e:
str = "6TO4";
break;
case ipconfig_method_linklocal_v6_e:
str = "LINKLOCAL-V6";
break;
case ipconfig_method_dhcpv6_pd_e:
str = "DHCPV6-PD";
break;
}
return (str);
}
STATIC boolean_t
service_is_routable(ServiceRef service_p)
{
boolean_t routable = FALSE;
switch (service_p->method) {
case ipconfig_method_bootp_e:
case ipconfig_method_dhcp_e:
case ipconfig_method_inform_e:
case ipconfig_method_manual_e:
routable = service_router_is_iaddr_valid(service_p);
break;
case ipconfig_method_manual_v6_e:
routable = !IN6_IS_ADDR_UNSPECIFIED(&service_p->u.v6.router);
break;
case ipconfig_method_automatic_v6_e:
case ipconfig_method_rtadv_e:
routable = service_p->u.v6.have_signature;
break;
default:
break;
}
return (routable);
}
STATIC Rank
service_list_get_rank(dynarray_t * services_p, CFArrayRef service_order,
boolean_t * services_ready_p);
/*
* Function: S_is_our_hardware_address
*
* Purpose:
* Returns whether the given hardware address is that of any of
* our attached network interfaces.
*/
static boolean_t
S_is_our_hardware_address(interface_t * ignored,
int hwtype, void * hwaddr, int hwlen)
{
int i;
for (i = 0; i < ifl_count(S_interfaces); i++) {
interface_t * if_p = ifl_at_index(S_interfaces, i);
int link_length = if_link_length(if_p);
if (hwlen != link_length) {
continue;
}
if (hwtype != if_link_arptype(if_p)) {
continue;
}
if (bcmp(hwaddr, if_link_address(if_p), link_length) == 0) {
return (TRUE);
}
}
return (FALSE);
}
/* State:/Network/Interface/en4/BonjourSleepProxyOPTRecord */
#define kBSPOPTRecord CFSTR("BonjourSleepProxyOPTRecord")
#define kBSPOwnerOPTRecord CFSTR("OwnerOPTRecord")
/* State:/Network/Interface/en4/BonjourSleepProxyAddress */
#define kBSPAddress CFSTR("BonjourSleepProxyAddress")
#define kBSPMACAddress kSCPropMACAddress
#define kBSPIPAddress CFSTR("IPAddress")
#define kBSPRegisteredAddresses CFSTR("RegisteredAddresses")
STATIC CFStringRef
S_copy_bsp_address_key(CFStringRef ifname)
{
CFStringRef key;
key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL,
kSCDynamicStoreDomainState,
ifname,
kBSPAddress);
return (key);
}
STATIC CFStringRef
S_copy_bsp_opt_key(CFStringRef ifname)
{