-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdevice.h
997 lines (828 loc) · 43.7 KB
/
device.h
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
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SHILL_DEVICE_H_
#define SHILL_DEVICE_H_
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include <base/macros.h>
#include <base/memory/ref_counted.h>
#include <base/memory/weak_ptr.h>
#include <base/time/time.h>
#include <chromeos/patchpanel/dbus/client.h>
#include <gtest/gtest_prod.h> // for FRIEND_TEST
#include <patchpanel/proto_bindings/patchpanel_service.pb.h>
#include "shill/adaptor_interfaces.h"
#include "shill/callbacks.h"
#include "shill/connection_diagnostics.h"
#include "shill/dns_server_tester.h"
#include "shill/event_dispatcher.h"
#include "shill/geolocation_info.h"
#include "shill/ipconfig.h"
#include "shill/net/ip_address.h"
#include "shill/net/shill_time.h"
#include "shill/portal_detector.h"
#include "shill/property_store.h"
#include "shill/refptr_types.h"
#include "shill/service.h"
#include "shill/technology.h"
namespace shill {
class ControlInterface;
class DHCPProvider;
class DeviceAdaptorInterface;
class Error;
class EventDispatcher;
class LinkMonitor;
class Manager;
class Metrics;
class RoutingTable;
class RTNLHandler;
class TrafficMonitor;
// Device superclass. Individual network interfaces types will inherit from
// this class.
class Device : public base::RefCounted<Device> {
public:
// The maximum value of time difference between the detection time of the two
// link monitors. If one link monitor detects a failure at time t, but the
// other one does not report a failure before (t + this value), we could
// consider the second link monitor fails to detect this failure, and we will
// report this value (or its opposite number) to UMA metrics in this case.
//
// In theory, the link monitor should detect a failure after it happens in a
// given time period:
// - For shill::LinkMonitor, this value is 75 seconds (two passive periods and
// one active period, each period is 25 seconds).
// - For patchpanel::NeighborLinkMonitor, this value is 68 seconds (60 seconds
// for probe period, 8 seconds to wait for the state transiting from
// NUD_DELAY ot NUD_FAILED, which is the worst case).
// So 80 seconds should be a good enough value to accommodate these two
// theoretical values.
static constexpr base::TimeDelta kLinkMonitorsDetectionTimeDiffMax =
base::TimeDelta::FromSeconds(80);
// A constructor for the Device object
Device(Manager* manager,
const std::string& link_name,
const std::string& mac_address,
int interface_index,
Technology technology);
Device(const Device&) = delete;
Device& operator=(const Device&) = delete;
// Initialize type-specific network interface properties.
virtual void Initialize();
// Enable or disable the device. This is a convenience method for
// cases where we want to SetEnabledNonPersistent, but don't care
// about the results.
mockable void SetEnabled(bool enable);
// Enable or disable the device. Unlike SetEnabledPersistent, it does not
// save the setting in the profile.
//
// TODO(quiche): Replace both of the next two methods with calls to
// SetEnabledChecked.
mockable void SetEnabledNonPersistent(bool enable,
Error* error,
const ResultCallback& callback);
// Enable or disable the device, and save the setting in the profile.
// The setting is persisted before the enable or disable operation
// starts, so that even if it fails, the user's intent is still recorded
// for the next time shill restarts.
mockable void SetEnabledPersistent(bool enable,
Error* error,
const ResultCallback& callback);
// Enable or disable the Device, depending on |enable|.
// Save the new setting to the profile, if |persist| is true.
// Report synchronous errors using |error|, and asynchronous completion
// with |callback|.
void SetEnabledChecked(bool enable,
bool persist,
Error* error,
const ResultCallback& callback);
// Similar to SetEnabledChecked, but without sanity checking, and
// without saving the new value of |enable| to the profile. If you
// are sane (i.e. not Cellular), you should use
// SetEnabledChecked instead.
void SetEnabledUnchecked(bool enable,
Error* error,
const ResultCallback& callback);
// Returns true if the underlying device reports that it is already enabled.
// Used when the device is registered with the Manager, so that shill can
// sync its state/ with the true state of the device. The default is to
// report false.
virtual bool IsUnderlyingDeviceEnabled() const;
virtual void LinkEvent(unsigned flags, unsigned change);
// The default implementation sets |error| to kNotSupported.
virtual void Scan(Error* error, const std::string& reason);
virtual void RegisterOnNetwork(const std::string& network_id,
Error* error,
const ResultCallback& callback);
virtual void RequirePin(const std::string& pin,
bool require,
Error* error,
const ResultCallback& callback);
virtual void EnterPin(const std::string& pin,
Error* error,
const ResultCallback& callback);
virtual void UnblockPin(const std::string& unblock_code,
const std::string& pin,
Error* error,
const ResultCallback& callback);
virtual void ChangePin(const std::string& old_pin,
const std::string& new_pin,
Error* error,
const ResultCallback& callback);
virtual void Reset(Error* error, const ResultCallback& callback);
virtual void RefreshIPConfig(Error* error);
// Returns false if IPv6 is allowed and should be enabled when the device
// tries to acquire an IP configuration. The default implementation allows
// IPv6, which can be overridden by a derived class.
virtual bool IsIPv6DisabledByDefault() const;
void StopIPv6();
void StartIPv6();
mockable void EnableIPv6Privacy();
// Returns true if the selected service on the device (if any) is connected.
// Returns false if there is no selected service, or if the selected service
// is not connected.
bool IsConnected() const;
// Called by Device so that subclasses can run hooks on the selected service
// getting an IP. Subclasses should call up to the parent first.
virtual void OnConnected();
// Called by the Connection so that the Device can update the service sorting
// after one connection is bound to another.
mockable void OnConnectionUpdated();
// Returns true if the selected service on the device (if any) is connected
// and matches the passed-in argument |service|. Returns false if there is
// no connected service, or if it does not match |service|.
mockable bool IsConnectedToService(const ServiceRefPtr& service) const;
// Returns true if the DHCP parameters provided indicate that we are tethered
// to a mobile device.
mockable bool IsConnectedViaTether() const;
// Restart the portal detection process on a connected device. This is
// useful if the properties on the connected service have changed in a
// way that may affect the decision to run portal detection at all.
// Returns true if portal detection was started.
mockable bool RestartPortalDetection();
// Called by the manager to start a single connectivity test. This is used to
// log connection state triggered by a user feedback log request.
mockable bool StartConnectivityTest();
// Get receive and transmit byte counters.
mockable uint64_t GetReceiveByteCount();
mockable uint64_t GetTransmitByteCount();
// Reset the persisted byte counters associated with the device.
void ResetByteCounters();
// Requests that portal detection be done, if this device has the default
// connection. Returns true if portal detection was started.
mockable bool RequestPortalDetection();
const RpcIdentifier& GetRpcIdentifier() const;
virtual std::string GetStorageIdentifier() const;
// Returns a list of Geolocation objects. Each object is multiple
// key-value pairs representing one entity that can be used for
// Geolocation.
virtual std::vector<GeolocationInfo> GetGeolocationObjects() const;
// Enable or disable this interface to receive packets even if it is not
// the default connection. This is useful in limited situations such as
// during portal detection.
mockable void SetLooseRouting(bool is_loose_routing);
// Enable or disable same-net multi-home support for this interface. When
// enabled, ARP filtering is enabled in order to avoid the "ARP Flux"
// effect where peers may end up with inaccurate IP address mappings due to
// the default Linux ARP transmit / reply behavior. See
// http://linux-ip.net/html/ether-arp.html for more details on this effect.
mockable void SetIsMultiHomed(bool is_multi_homed);
// Used for devices that are managed by an entity other than shill.
// If true, shill will not attempt to change the device's IP
// address, subnet mask, broadcast address, or manipulate the interface
// state. This setting is disabled by default.
void SetFixedIpParams(bool fixed_ip_params);
const std::string& mac_address() const { return mac_address_; }
const std::string& link_name() const { return link_name_; }
int interface_index() const { return interface_index_; }
mockable const ConnectionRefPtr& connection() const { return connection_; }
bool enabled() const { return enabled_; }
bool enabled_persistent() const { return enabled_persistent_; }
mockable Technology technology() const { return technology_; }
std::string GetTechnologyString(Error* error);
const IPConfigRefPtr& ipconfig() const { return ipconfig_; }
const IPConfigRefPtr& ip6config() const { return ip6config_; }
const IPConfigRefPtr& dhcpv6_config() const { return dhcpv6_config_; }
void set_ipconfig(const IPConfigRefPtr& config) { ipconfig_ = config; }
void set_ip6config(const IPConfigRefPtr& config) { ip6config_ = config; }
// Returns a string that is guaranteed to uniquely identify this Device
// instance.
const std::string& UniqueName() const;
// Returns a WeakPtr of the Device.
base::WeakPtr<Device> AsWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }
PropertyStore* mutable_store() { return &store_; }
const PropertyStore& store() const { return store_; }
RTNLHandler* rtnl_handler() { return rtnl_handler_; }
bool running() const { return running_; }
EventDispatcher* dispatcher() const;
// Load configuration for the device from |storage|. This may include
// instantiating non-visible services for which configuration has been
// stored.
virtual bool Load(const StoreInterface* storage);
// Save configuration for the device to |storage|.
virtual bool Save(StoreInterface* storage);
void set_dhcp_provider(DHCPProvider* provider) { dhcp_provider_ = provider; }
DeviceAdaptorInterface* adaptor() const { return adaptor_.get(); }
// Suspend event handler. Called by Manager before the system
// suspends. This handler, along with any other suspend handlers,
// will have Manager::kTerminationActionsTimeoutMilliseconds to
// execute before the system enters the suspend state. |callback|
// must be invoked after all synchronous and/or asynchronous actions
// this function performs complete. Code that needs to run on exit should use
// Manager::AddTerminationAction, rather than OnBeforeSuspend.
//
// The default implementation invokes the |callback| immediately, since
// there is nothing to be done in the general case.
virtual void OnBeforeSuspend(const ResultCallback& callback);
// Resume event handler. Called by Manager as the system resumes.
// The base class implementation takes care of renewing a DHCP lease
// (if necessary). Derived classes may implement any technology
// specific requirements by overriding, but should include a call to
// the base class implementation.
virtual void OnAfterResume();
// This method is invoked when the system resumes from suspend temporarily in
// the "dark resume" state. The system will reenter suspend in
// Manager::kTerminationActionsTimeoutMilliseconds. |callback| must be invoked
// after all synchronous and/or asynchronous actions this function performs
// and/or posts complete.
//
// The default implementation invokes the |callback| immediately, since
// there is nothing to be done in the general case.
virtual void OnDarkResume(const ResultCallback& callback);
// Destroy the lease, if any, with this |name|.
// Called by the service during Unload() as part of the cleanup sequence.
mockable void DestroyIPConfigLease(const std::string& name);
// Called by DeviceInfo when the kernel adds or removes a globally-scoped
// IPv6 address from this interface.
mockable void OnIPv6AddressChanged(const IPAddress* address);
// Called by DeviceInfo when the kernel receives a update for IPv6 DNS server
// addresses from this interface.
mockable void OnIPv6DnsServerAddressesChanged();
// Program a rule into the NIC to wake the system from suspend upon receiving
// packets from |ip_endpoint|. |error| indicates the result of the
// operation.
virtual void AddWakeOnPacketConnection(const std::string& ip_endpoint,
Error* error);
// Programs the NIC to wake on every packet of IP protocol type belonging to
// |packet_types|. |error| indicates the result of the operation.
virtual void AddWakeOnPacketOfTypes(
const std::vector<std::string>& packet_types, Error* error);
// Removes a rule previously programmed into the NIC to wake the system from
// suspend upon receiving packets from |ip_endpoint|. |error| indicates the
// result of the operation.
virtual void RemoveWakeOnPacketConnection(const std::string& ip_endpoint,
Error* error);
// Removes a rule previously programmed to wake on every packet of IP
// protocol type belonging to |packet_types|.
// |error| indicates the result of the operation.
virtual void RemoveWakeOnPacketOfTypes(
const std::vector<std::string>& packet_types, Error* error);
// Removes all wake-on-packet rules programmed into the NIC. |error| indicates
// the result of the operation.
virtual void RemoveAllWakeOnPacketConnections(Error* error);
// Sets MAC address source for USB Ethernet device. Callback will only be
// invoke when device successfully changed MAC address or failed to change MAC
// address.
virtual void SetUsbEthernetMacAddressSource(const std::string& source,
Error* error,
const ResultCallback& callback);
// Initiate renewal of existing DHCP lease.
void RenewDHCPLease(bool from_dbus, Error* error);
// Resolve the |input| string into a MAC address for a peer local to this
// device. This could be a trivial operation if the |input| is already a MAC
// address, or could involve an ARP table lookup. Returns true and populates
// |output| if the resolution completes, otherwise returns false and
// populates |error|.
bool ResolvePeerMacAddress(const std::string& input,
std::string* output,
Error* error);
// Creates a byte vector from a colon-separated hardware address string.
static std::vector<uint8_t> MakeHardwareAddressFromString(
const std::string& address_string);
// Creates a colon-separated hardware address string from a byte vector.
static std::string MakeStringFromHardwareAddress(
const std::vector<uint8_t>& address_data);
// Request the WiFi device to roam to AP with |addr|.
// This call will send Roam command to wpa_supplicant.
virtual bool RequestRoam(const std::string& addr, Error* error);
const ServiceRefPtr& selected_service() const { return selected_service_; }
// Drops the current connection and the selected service, if any. Does not
// change the state of the previously selected service.
mockable void ResetConnection();
// If the status of browser traffic blackholing changed, this will restart
// the active connection with the right setting.
mockable void UpdateBlackholeUserTraffic();
// Responds to a neighbor failure event from patchpanel. Currently it
// will send the UMA metrics about the type of the detected failure, and also
// be used for comparing performance between the two types of link monitors.
mockable void OnNeighborLinkFailure(
const IPAddress& ip_address,
patchpanel::NeighborReachabilityEventSignal::Role role);
// Responds to a neighbor recovered event from patchpanel. Currently it will
// only call LinkMonitorComparisonReset() for the link monitor comparison
// purposes.
mockable void OnNeighborLinkRecovered(
const IPAddress& ip_address,
patchpanel::NeighborReachabilityEventSignal::Role role);
protected:
friend class base::RefCounted<Device>;
FRIEND_TEST(CellularServiceTest, IsAutoConnectable);
FRIEND_TEST(CellularTest, ModemStateChangeDisable);
FRIEND_TEST(CellularTest, UseNoArpGateway);
FRIEND_TEST(DevicePortalDetectionTest, PortalIntervalIsZero);
FRIEND_TEST(DevicePortalDetectionTest, RequestStartConnectivityTest);
FRIEND_TEST(DevicePortalDetectionTest, RestartPortalDetection);
FRIEND_TEST(DeviceTest, AcquireIPConfigWithoutSelectedService);
FRIEND_TEST(DeviceTest, AcquireIPConfigWithSelectedService);
FRIEND_TEST(DeviceTest, AvailableIPConfigs);
FRIEND_TEST(DeviceTest, DestroyIPConfig);
FRIEND_TEST(DeviceTest, DestroyIPConfigNULL);
FRIEND_TEST(DeviceTest, ConfigWithMinimumMTU);
FRIEND_TEST(DeviceTest, FetchTrafficCounters);
FRIEND_TEST(DeviceTest, GetProperties);
FRIEND_TEST(DeviceTest, IPConfigUpdatedFailureWithIPv6Config);
FRIEND_TEST(DeviceTest, IPConfigUpdatedFailureWithIPv6Connection);
FRIEND_TEST(DeviceTest, IsConnectedViaTether);
FRIEND_TEST(DeviceTest, LinkMonitorComparison);
FRIEND_TEST(DeviceTest, LinkMonitorFailure);
FRIEND_TEST(DeviceTest, Load);
FRIEND_TEST(DeviceTest, OnDHCPv6ConfigExpired);
FRIEND_TEST(DeviceTest, OnDHCPv6ConfigFailed);
FRIEND_TEST(DeviceTest, OnDHCPv6ConfigUpdated);
FRIEND_TEST(DeviceTest, OnIPv6AddressChanged);
FRIEND_TEST(DeviceTest, OnIPv6ConfigurationCompleted);
FRIEND_TEST(DeviceTest, OnIPv6DnsServerAddressesChanged);
FRIEND_TEST(DeviceTest, PrependIPv4DNSServers);
FRIEND_TEST(DeviceTest, PrependIPv6DNSServers);
FRIEND_TEST(DeviceTest, ResetConnection);
FRIEND_TEST(DeviceTest, Save);
FRIEND_TEST(DeviceTest, SelectedService);
FRIEND_TEST(DeviceTest, SetEnabledNonPersistent);
FRIEND_TEST(DeviceTest, SetEnabledPersistent);
FRIEND_TEST(DeviceTest, ShouldUseArpGateway);
FRIEND_TEST(DeviceTest, Start);
FRIEND_TEST(DeviceTest, StartIPv6);
FRIEND_TEST(DeviceTest, StartIPv6Disabled);
FRIEND_TEST(DeviceTest, Stop);
FRIEND_TEST(DeviceTest, StopWithFixedIpParams);
FRIEND_TEST(DeviceTest, StopWithNetworkInterfaceDisabledAfterward);
FRIEND_TEST(ManagerTest, ConnectedTechnologies);
FRIEND_TEST(ManagerTest, DefaultTechnology);
FRIEND_TEST(ManagerTest, DeviceRegistrationAndStart);
FRIEND_TEST(ManagerTest, GetEnabledDeviceWithTechnology);
FRIEND_TEST(ManagerTest, RefreshAllTrafficCountersTask);
FRIEND_TEST(ManagerTest, SetEnabledStateForTechnology);
FRIEND_TEST(WiFiMainTest, UseArpGateway);
virtual ~Device();
// Each device must implement this method to do the work needed to
// enable the device to operate for establishing network connections.
// The |error| argument, if not nullptr,
// will refer to an Error that starts out with the value
// Error::kOperationInitiated. This reflects the assumption that
// enable (and disable) operations will usually be non-blocking,
// and their completion will be indicated by means of an asynchronous
// reply sometime later. There are two circumstances in which a
// device's Start() method may overwrite |error|:
//
// 1. If an early failure is detected, such that the non-blocking
// part of the operation never takes place, then |error| should
// be set to the appropriate value corresponding to the type
// of failure. This is the "immediate failure" case.
// 2. If the device is enabled without performing any non-blocking
// steps, then |error| should be Reset, i.e., its value set
// to Error::kSuccess. This is the "immediate success" case.
//
// In these two cases, because completion is immediate, |callback|
// is not used. If neither of these two conditions holds, then |error|
// should not be modified, and |callback| should be passed to the
// method that will initiate the non-blocking operation.
virtual void Start(Error* error,
const EnabledStateChangedCallback& callback) = 0;
// Each device must implement this method to do the work needed to
// disable the device, i.e., clear any running state, and make the
// device no longer capable of establishing network connections.
// The discussion for Start() regarding the use of |error| and
// |callback| apply to Stop() as well.
virtual void Stop(Error* error,
const EnabledStateChangedCallback& callback) = 0;
// Returns true if the associated network interface should be brought down
// after the device is disabled, or false if that should be done before the
// device is disabled.
virtual bool ShouldBringNetworkInterfaceDownAfterDisabled() const;
// The EnabledStateChangedCallback that gets passed to the device's
// Start() and Stop() methods is bound to this method. |callback|
// is the callback that was passed to SetEnabled().
void OnEnabledStateChanged(const ResultCallback& callback,
const Error& error);
// Drops the currently selected service along with its IP configuration and
// connection, if any.
virtual void DropConnection();
// If there's an IP configuration in |ipconfig_|, releases the IP address and
// destroys the configuration instance.
void DestroyIPConfig();
// Creates a new DHCP IP configuration instance, stores it in |ipconfig_| and
// requests a new IP configuration. Saves the DHCP lease to the generic
// lease filename based on the interface name. Registers a callback to
// IPConfigUpdatedCallback on IP configuration changes. Returns true if the IP
// request was successfully sent.
bool AcquireIPConfig();
// Creates a new DHCP IP configuration instance, stores it in |ipconfig_| and
// requests a new IP configuration. Saves the DHCP lease to a filename
// based on the passed-in |lease_name|. Registers a callback to
// IPConfigUpdatedCallback on IP configuration changes. Returns true if the IP
// request was successfully sent.
bool AcquireIPConfigWithLeaseName(const std::string& lease_name);
#ifndef DISABLE_DHCPV6
// Creates a new DHCPv6 configuration instances, stores it in
// |dhcpv6_config_| and requests a new configuration. Saves the DHCPv6
// lease to a filename based on the passed-in |lease_name|.
// The acquired configurations will not be used to setup a connection
// for the device.
bool AcquireIPv6ConfigWithLeaseName(const std::string& lease_name);
#endif
// Assigns the IP configuration |properties| to |ipconfig_|.
void AssignIPConfig(const IPConfig::Properties& properties);
// Callback invoked on successful IP configuration updates.
virtual void OnIPConfigUpdated(const IPConfigRefPtr& ipconfig,
bool new_lease_acquired);
// Called when IPv6 configuration changes.
virtual void OnIPv6ConfigUpdated();
// Called by Device so that subclasses can run hooks on the selected service
// failing to get an IP. The default implementation disconnects the selected
// service with Service::kFailureDHCP.
virtual void OnIPConfigFailure();
// Selects a service to be "current" -- i.e. link-state or configuration
// events that happen to the device are attributed to this service.
void SelectService(const ServiceRefPtr& service);
// Set the state of the |selected_service_|.
virtual void SetServiceState(Service::ConnectState state);
// Set the failure of the selected service (implicitly sets the state to
// "failure").
virtual void SetServiceFailure(Service::ConnectFailure failure_state);
// Records the failure mode and time of the selected service, and
// sets the Service state of the selected service to "Idle".
// Avoids showing a failure mole in the UI.
virtual void SetServiceFailureSilent(Service::ConnectFailure failure_state);
// Schedule a single portal detection trial, and set loose routing.
bool StartPortalDetectionTrial(PortalDetector* portal_detector,
const PortalDetector::Properties& props,
int delay_seconds);
// Respond to a LinkMonitor failure in a Device-specific manner.
virtual void OnLinkMonitorFailure();
// Indicates if the selected service is configured with a static IP address.
bool IsUsingStaticIP() const;
// RPC getter, setter, and clear method for the "IPv6Disabled" property.
bool GetIPv6Disabled(Error* error);
bool SetIPv6Disabled(const bool& connect, Error* error);
void ClearIPv6Disabled(Error* error);
void HelpRegisterDerivedBool(const std::string& name,
bool (Device::*get)(Error* error),
bool (Device::*set)(const bool& value,
Error* error),
void (Device::*clear)(Error* error));
void HelpRegisterConstDerivedString(const std::string& name,
std::string (Device::*get)(Error*));
void HelpRegisterConstDerivedRpcIdentifier(
const std::string& name, RpcIdentifier (Device::*get)(Error*));
void HelpRegisterConstDerivedRpcIdentifiers(
const std::string& name, RpcIdentifiers (Device::*get)(Error*));
void HelpRegisterConstDerivedUint64(const std::string& name,
uint64_t (Device::*get)(Error*));
// Property getters reserved for subclasses
ControlInterface* control_interface() const;
Metrics* metrics() const;
Manager* manager() const { return manager_; }
const LinkMonitor* link_monitor() const { return link_monitor_.get(); }
void set_link_monitor(LinkMonitor* link_monitor);
bool fixed_ip_params() const { return fixed_ip_params_; }
// Calculates the time (in seconds) till a DHCP lease is due for renewal,
// and stores this value in |result|. Returns false is there is no upcoming
// DHCP lease renewal, true otherwise.
bool TimeToNextDHCPLeaseRenewal(uint32_t* result);
virtual void set_mac_address(const std::string& mac_address);
private:
friend class CellularTest;
friend class DeviceAdaptorInterface;
friend class DeviceByteCountTest;
friend class DevicePortalDetectionTest;
friend class DeviceTest;
friend class EthernetTest;
friend class OpenVPNDriverTest;
friend class TestDevice;
friend class VirtualDeviceTest;
friend class WiFiObjectTest;
static const char kIPFlagDisableIPv6[];
static const char kIPFlagAcceptRouterAdvertisements[];
static const char kStoragePowered[];
static const char kStorageReceiveByteCount[];
static const char kStorageTransmitByteCount[];
// Brings the associated network interface down unless |fixed_ip_params_| is
// true, which indicates that the interface state shouldn't be changed.
void BringNetworkInterfaceDown();
// Configure static IP address parameters if the service provides them.
void ConfigureStaticIPTask();
// Set an IP configuration flag on the device. |family| should be "ipv6" or
// "ipv4". |flag| should be the name of the flag to be set and |value| is
// what this flag should be set to. Overridden by unit tests to pretend
// writing to procfs.
mockable bool SetIPFlag(IPAddress::Family family,
const std::string& flag,
const std::string& value);
// Request the removal of reverse-path filtering for this interface.
// This will allow packets destined for this interface to be accepted,
// even if this is not the default route for such a packet to arrive.
void DisableReversePathFilter();
// Request reverse-path filtering for this interface.
void EnableReversePathFilter();
// Disable ARP filtering on the device. The interface will exhibit the
// default Linux behavior -- incoming ARP requests are responded to by all
// interfaces. Outgoing ARP requests can contain any local address.
void DisableArpFiltering();
// Enable ARP filtering on the device. Incoming ARP requests are responded
// to only by the interface(s) owning the address. Outgoing ARP requests
// will contain the best local address for the target.
void EnableArpFiltering();
RpcIdentifier GetSelectedServiceRpcIdentifier(Error* error);
RpcIdentifiers AvailableIPConfigs(Error* error);
// Get receive and transmit byte counters. These methods simply wrap
// GetReceiveByteCount and GetTransmitByteCount in order to be used by
// HelpRegisterConstDerivedUint64.
uint64_t GetReceiveByteCountProperty(Error* error);
uint64_t GetTransmitByteCountProperty(Error* error);
// Emit a property change signal for the "IPConfigs" property of this device.
void UpdateIPConfigsProperty();
// Called by DNS server tester when the fallback DNS servers test completes.
void FallbackDNSResultCallback(const DnsServerTester::Status status);
// Called by DNS server tester when the configured DNS servers test completes.
void ConfigDNSResultCallback(const DnsServerTester::Status status);
// Update DNS setting with the given DNS servers for the current connection.
void SwitchDNSServers(const std::vector<std::string>& dns_servers);
// Timer function for monitoring IPv6 DNS server's lifetime.
void StartIPv6DNSServerTimer(uint32_t lifetime_seconds);
void StopIPv6DNSServerTimer();
// Called when the lifetime for IPv6 DNS server expires.
void IPv6DNSServerExpired();
// Callback invoked on IP configuration failures.
void OnIPConfigFailed(const IPConfigRefPtr& ipconfig);
// Callback invoked when "Refresh" is invoked on an IPConfig. This usually
// signals a change in static IP parameters.
void OnIPConfigRefreshed(const IPConfigRefPtr& ipconfig);
// Callback invoked when an IPConfig restarts due to lease expiry. This
// is advisory, since an "Updated" or "Failed" signal is guaranteed to
// follow.
void OnIPConfigExpired(const IPConfigRefPtr& ipconfig);
// Callback invoked on successful DHCPv6 configuration updates.
void OnDHCPv6ConfigUpdated(const IPConfigRefPtr& ipconfig,
bool new_lease_acquired);
// Callback invoked on DHCPv6 configuration failures.
void OnDHCPv6ConfigFailed(const IPConfigRefPtr& ipconfig);
// Callback invoked when an DHCPv6Config restarts due to lease expiry. This
// is advisory, since an "Updated" or "Failed" signal is guaranteed to
// follow.
void OnDHCPv6ConfigExpired(const IPConfigRefPtr& ipconfig);
// Called when link becomes unreliable (multiple link monitor failures
// detected in short period of time).
void OnUnreliableLink();
// Called when link becomes reliable (no link failures in a predefined period
// of time).
void OnReliableLink();
// Return true if given IP configuration contain both IP address and DNS
// servers. Hence, ready to be used for network connection.
bool IPConfigCompleted(const IPConfigRefPtr& ipconfig);
// Setup network connection with given IP configuration, and start portal
// detection on that connection.
void SetupConnection(const IPConfigRefPtr& ipconfig);
// Maintain connection state (Routes, IP Addresses and DNS) in the OS.
void CreateConnection();
// Remove connection state
void DestroyConnection();
// Set the system hostname to |hostname| if this device is configured to
// do so. If |hostname| is too long, truncate this parameter to fit within
// the maximum hostname size.
bool SetHostname(const std::string& hostname);
// Prepend the Manager's configured list of DNS servers into |ipconfig|
// ensuring that only DNS servers of the same address family as |ipconfig| are
// included in the final list.
void PrependDNSServersIntoIPConfig(const IPConfigRefPtr& ipconfig);
// Mutate |servers| to include the Manager's prepended list of DNS servers for
// |family|. On return, it is guaranteed that there are no duplicate entries
// in |servers|.
void PrependDNSServers(const IPAddress::Family family,
std::vector<std::string>* servers);
// Called by the Portal Detector whenever a trial completes. Device
// subclasses that choose unique mappings from portal results to connected
// states can override this method in order to do so.
void PortalDetectorCallback(const PortalDetector::Result& http_result,
const PortalDetector::Result& https_result);
// Initiate portal detection, if enabled for this device type.
bool StartPortalDetection();
// Stop portal detection if it is running.
void StopPortalDetection();
// Initiate connection diagnostics with the |result| from a completed portal
// detection attempt.
mockable bool StartConnectionDiagnosticsAfterPortalDetection(
const PortalDetector::Result& http_result,
const PortalDetector::Result& https_result);
// Stop connection diagnostics if it is running.
void StopConnectionDiagnostics();
// Stop connectivity tester if it exists.
void StopConnectivityTest();
// Called by |connection_diagnostics| after diagnostics have finished.
void ConnectionDiagnosticsCallback(
const std::string& connection_issue,
const std::vector<ConnectionDiagnostics::Event>& diagnostic_events);
// Called by the ConnectionTester whenever a connectivity test completes.
void ConnectionTesterCallback(const PortalDetector::Result& http_result,
const PortalDetector::Result& https_result);
// Initiate link monitoring, if enabled for this device type.
bool StartLinkMonitor();
// Stop link monitoring if it is running.
void StopLinkMonitor();
// Get the LinkMonitor's average response time.
uint64_t GetLinkMonitorResponseTime(Error* error);
// Respond to a LinkMonitor gateway's MAC address found/change event.
void OnLinkMonitorGatewayChange();
// Returns true if traffic monitor is enabled on this device. The default
// implementation will return false, which can be overridden by a derived
// class.
virtual bool IsTrafficMonitorEnabled() const;
// Initiates traffic monitoring on the device if traffic monitor is enabled.
void StartTrafficMonitor();
// Stops traffic monitoring on the device if traffic monitor is enabled.
void StopTrafficMonitor();
// Start DNS test for the given servers. When retry_until_success is set,
// callback will only be invoke when the test succeed or the test failed to
// start (internal error). This function will return false if there is a test
// that's already running, and true otherwise.
mockable bool StartDNSTest(
const std::vector<std::string>& dns_servers,
const bool retry_until_success,
const base::Callback<void(const DnsServerTester::Status)>& callback);
// Stop DNS test if one is running.
void StopDNSTest();
// Stop all monitoring/testing activities on this device. Called when tearing
// down or changing network connection on the device.
void StopAllActivities();
// Called by the Traffic Monitor when it detects a network problem. Handles
// metric reporting of the network problem.
void OnEncounterNetworkProblem(int reason);
// Set the state of the selected service, with checks to make sure
// the service is already in a connected state before doing so.
void SetServiceConnectedState(Service::ConnectState state);
// Specifies whether an ARP gateway should be used for the
// device technology.
virtual bool ShouldUseArpGateway() const;
// Indicates if the selected service is configured with static nameservers.
bool IsUsingStaticNameServers() const;
// Returns true if any of the addresses for this Device are on the same
// network prefix as |address|.
bool HasDirectConnectivityTo(const IPAddress& address) const;
// Atomically update the counters of the old service and the snapshot of the
// new service. |GetTrafficCountersPatchpanelCallback| calls
// |GetTrafficCountersCallback| using the |get_traffic_counters_callback_|
// callback below. This is necessary because the callback that holds a
// reference to the ServiceRefPtrs needs to be reset to release the
// references. We can't directly cancel the callback we give to patchpanel
// client since it expects a OnceCallback.
void GetTrafficCountersCallback(
const ServiceRefPtr& old_service,
const ServiceRefPtr& new_service,
const std::vector<patchpanel::TrafficCounter>& counters);
void GetTrafficCountersPatchpanelCallback(
unsigned int id, const std::vector<patchpanel::TrafficCounter>& counters);
// Asynchronously get all the traffic counters for this device during a
// selected_service_ change and update the counters and snapshots for the old
// and new selected_service_ respectively.
void FetchTrafficCounters(const ServiceRefPtr& old_service,
const ServiceRefPtr& new_service);
// Use for unit test.
void set_traffic_monitor_for_test(
std::unique_ptr<TrafficMonitor> traffic_monitor);
// b/162194516: Functions for comparing two types of link monitors. The basic
// idea is that we try to record and compare the time that link monitors
// detect one failure (i.e., the IPv4 gateway neighbor lost since
// shill::LinkMonitor is only able to detect such failures) (in
// |arp_link_monitor_failed_time_| and |neighbor_link_monitor_failed_time_|).
// To make sure those two variables are pointing to the same failure:
// 1) We will not update the time each time a link monitor reports a failure,
// but only record the first one (for each link monitor). Only after
// receiving a clear signal that the device has been recovered from the
// failure, we reset the times which we store and move to wait for the next
// failure. The signal could be a) patchpanel reports the link is connected
// again, or b) another service is selected (i.e., Device::SelectService()
// is called).
// 2) When one link monitor reports a failure and the other one haven't yet,
// we will setup a one shot timer to send the result, in case that another
// link monitor fails to detect this failure.
// Resets all related variables to make us ready for the next failure.
void LinkMonitorComparisonReset();
// Records a failure from one link monitor and set a timer to or directly call
// LinkMonitorComparisonSendResult(). |t| must be the pointer to either
// |arp_link_monitor_failed_time_| or |neighbor_link_monitor_failed_time_|.
void LinkMonitorComparisonSetFailedTime(struct timeval* t);
// Sends UMA metrics for the comparison result.
void LinkMonitorComparisonSendResult();
// |enabled_persistent_| is the value of the Powered property, as
// read from the profile. If it is not found in the profile, it
// defaults to true. |enabled_| reflects the real-time state of
// the device, i.e., enabled or disabled. |enabled_pending_| reflects
// the target state of the device while an enable or disable operation
// is occurring.
//
// Some typical sequences for these state variables are shown below.
//
// Shill starts up, profile has been read:
// |enabled_persistent_|=true |enabled_|=false |enabled_pending_|=false
//
// Shill acts on the value of |enabled_persistent_|, calls SetEnabled(true):
// |enabled_persistent_|=true |enabled_|=false |enabled_pending_|=true
//
// SetEnabled completes successfully, device is enabled:
// |enabled_persistent_|=true |enabled_|=true |enabled_pending_|=true
//
// User presses "Disable" button, SetEnabled(false) is called:
// |enabled_persistent_|=false |enabled_|=true |enabled_pending_|=false
//
// SetEnabled completes successfully, device is disabled:
// |enabled_persistent_|=false |enabled_|=false |enabled_pending_|=false
bool enabled_;
bool enabled_persistent_;
bool enabled_pending_;
std::string mac_address_;
PropertyStore store_;
const int interface_index_;
bool running_; // indicates whether the device is actually in operation
const std::string link_name_;
Manager* manager_;
IPConfigRefPtr ipconfig_;
IPConfigRefPtr ip6config_;
IPConfigRefPtr dhcpv6_config_;
ConnectionRefPtr connection_;
std::unique_ptr<DeviceAdaptorInterface> adaptor_;
std::unique_ptr<PortalDetector> portal_detector_;
std::unique_ptr<LinkMonitor> link_monitor_;
// Used for verifying whether DNS server is functional.
std::unique_ptr<DnsServerTester> dns_server_tester_;
// Callback to invoke when IPv6 DNS servers lifetime expired.
base::CancelableClosure ipv6_dns_server_expired_callback_;
std::unique_ptr<TrafficMonitor> traffic_monitor_;
// DNS servers obtained from ipconfig (either from DHCP or static config)
// that are not working.
std::vector<std::string> config_dns_servers_;
Technology technology_;
int portal_check_interval_seconds_;
// Keep track of the offset between the interface-reported byte counters
// and our persisted value.
uint64_t receive_byte_offset_;
uint64_t transmit_byte_offset_;
// Maintain a reference to the connected / connecting service
ServiceRefPtr selected_service_;
// Cache singleton pointers for performance and test purposes.
DHCPProvider* dhcp_provider_;
RoutingTable* routing_table_;
RTNLHandler* rtnl_handler_;
// Time when link monitor last failed.
Time* time_;
time_t last_link_monitor_failed_time_;
// Callback to invoke when link becomes reliable again after it was previously
// unreliable.
base::CancelableClosure reliable_link_callback_;
// b/162194516: Temporary variables for comparing two types of link monitors.
// "arp_link_monitor" represents shill::LinkMonitor and
// "neighbor_link_monitor" represents patchpanel::NeighborLinkMonitor. See the
// above comments for LinkMonitorComparison*() functions for more details.
struct timeval arp_link_monitor_failed_time_;
struct timeval neighbor_link_monitor_failed_time_;
// Indicates whether the current failure has already been reported. This
// variable is checked and set to true in LinkMonitorComparisonSendResult() to
// make sure we only send each result once.
bool link_monitor_comparison_reported_;
// To call LinkMonitorComparisonSendResult() to send the UMA metrics.
base::CancelableClosure link_monitor_comparison_send_result_callback_;
std::unique_ptr<PortalDetector> connection_tester_;
bool ipv6_disabled_;
// Track whether packets from non-optimal routes will be accepted by this
// device. This is referred to as "loose mode" (see RFC3704).
bool is_loose_routing_;
// Track the current same-net multi-home state.
bool is_multi_homed_;
// If true, IP parameters should not be modified.
bool fixed_ip_params_;
// Remember which flag files were previously successfully written.
std::set<std::string> written_flags_;
std::unique_ptr<ConnectionDiagnostics> connection_diagnostics_;
// See GetTrafficCountersCallback.
unsigned int traffic_counter_callback_id_;
// Maps the callback ID, created when FetchTrafficCounters is called, to the
// corresponding callback.
std::map<
unsigned int,
base::OnceCallback<void(const std::vector<patchpanel::TrafficCounter>&)>>
traffic_counters_callback_map_;
base::WeakPtrFactory<Device> weak_ptr_factory_;
};
} // namespace shill
#endif // SHILL_DEVICE_H_