From e9e99bf88a02c9617265c0c105e1d34ffddf6e4a Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Wed, 16 Oct 2019 13:51:20 -0700 Subject: [PATCH] (to squash) allow RA prefix info (multiple prefixes) This commit adds prefix info option to RA (multiple prefixes) Also adds a property to allow user to disable "Router Info" option in RA. --- doc/router-advert-feature-guide.md | 175 +++++++++++++++++++- src/wpantund/ICMP6RouterAdvertiser.cpp | 178 +++++++++++++++++---- src/wpantund/ICMP6RouterAdvertiser.h | 27 ++++ src/wpantund/NCPInstanceBase-Addresses.cpp | 1 + src/wpantund/NCPInstanceBase.cpp | 159 ++++++++++++++++++ src/wpantund/NCPInstanceBase.h | 21 +++ src/wpantund/wpan-properties.h | 8 + 7 files changed, 535 insertions(+), 34 deletions(-) diff --git a/doc/router-advert-feature-guide.md b/doc/router-advert-feature-guide.md index ddffdfeb..5770338a 100644 --- a/doc/router-advert-feature-guide.md +++ b/doc/router-advert-feature-guide.md @@ -2,7 +2,9 @@ The `"Router Advertisement"` feature enables `wpantund` to emit periodic Neighbor Discovery ICMPv6 Router Advertisement (RA) messages announcing routes on other network interfaces related to Thread network routes. -The routes included in RA message mirror all the routes added on the host primary interface corresponding to the Thread network: +The emitted RA can inlcude a set of prefixes (determined by user) or annoucne a default route. + +When "Route Info" option is enabled, the routes included in RA message mirror all the routes added on the host primary interface corresponding to the Thread network: - Host routes associated with off-mesh routes within the Thread network (when `Daemon:OffMeshRoute:AutoAddOnInterface` feature is enabled). - Host routes associated with on-mesh prefixes within the Thread network (when `Daemon:OnMeshPrefix:AutoAddAsInterfaceRoute` feature is enabled). - The list of interface routes is available form wpan property `IPv6:Routes`. @@ -14,6 +16,16 @@ The wpantund RA feature can be enabled through property `RouterAdvert:Enable` (b - `RouterAdvert:TxPeriod` the tx period of RA messages in units of seconds. Minimum period is 4 seconds, max period is 1800 seconds. The period is set to min or max if the value being set is out of the supported range. On start it is set to 10 seconds. - `RouterAdvert:DefaultRoute:Lifetime` specifies the lifetime value in RA header (non-zero indicates that we are a default route). By default it is set to zero (i.e. not a default route). - `RouterAdvert:DefaultRoute:Preference` specifies the default route preference. Positive value indicates high, zero indicates medium, and negative indicates low preference. Default value is zero (medium). +- `RouterAdvert:AddRouteInfoOption` can be used to enable or disable adding of "Route Info" option in RA. When set to false, the emitted RAs would not contain any "Route Info" options. By default it is enabled (set to true). +- `RouterAdvert:Prefixes` specifies the list of prefixes which are included in the RA message. This is a list-based property (we can set the entire list or use `add` or `remove` command to update the list item by item). When adding to the list, we can specify the length, valid and preferred lifetime, and associated flags (on-link and auto-config). A set of wpan properties are defined to help specify these. The value specified through these properties would apply to any next prefix added/removed to the list: + + - `RouterAdvert:Prefix:PrefixLength` in bits 0-128 - default is 64. + - `RouterAdvert:Prefix:ValidLifetime` in seconds - default is 3600. + - `RouterAdvert:Prefix:PreferredLifetime` in seconds - default is 3600. + - `RouterAdvert:Prefix:Flag:OnLink` boolean value for on-link flag - default is true. + - `RouterAdvert:Prefix:Flag:AutoConfig` boolean value for auto-config flag - default is true. + +When issuing a wpantund `leave` command, the list of prefixes and netifs for router advertisement will be cleared. # Example of behavior @@ -166,5 +178,166 @@ The property `RouterAdvert:DefaultRoute:Preference` determines default route pre 11:13:08.078489 IP6 (flowlabel 0xba663, hlim 255, next-header ICMPv6 (58) payload length: 56) fe80::4801:7e22:7895:a656 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 56 hop limit 255, Flags [none], pref low, router lifetime 1000s, reachable time 3600s, retrans time 0s + +The command below show an example of how to add a prefix to RA. + + wpanctl:wpan1> get RouterAdvert:Prefixes + RouterAdvert:Prefixes = [] + +We first set all related parameters using `RouterAdvert:Prefix:` properties: + + wpanctl:wpan1> set RouterAdvert:Prefix:ValidLifetime 3000 + wpanctl:wpan1> set RouterAdvert:Prefix:PreferredLifetime 5000 + wpanctl:wpan1> set RouterAdvert:Prefix:PrefixLength 64 + wpanctl:wpan1> set RouterAdvert:Prefix:Flag:OnLink false + wpanctl:wpan1> set RouterAdvert:Prefix:Flag:AutoConfig false + wpanctl:wpan1> add RouterAdvert:Prefixes fd00:7777:: + wpanctl:wpan1> + wpanctl:wpan1> get RouterAdvert:Prefixes + RouterAdvert:Prefixes = [ + "prefix: fd00:7777::/64, flags:[ ], valid lifetime:3000, preferred lifetime:5000" + ] + +tcpdump shows the prefix option: + + 20:57:26.624969 IP6 (flowlabel 0x034c9, hlim 255, next-header ICMPv6 (58) payload length: 56) fe80::70c8:17e:f25a:6733 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 56 + hop limit 255, Flags [none], pref medium, router lifetime 0s, reachable time 3600s, retrans time 0s + source link-address option (1), length 8 (1): 00:00:00:00:00:00 + 0x0000: 0000 0000 0000 + prefix info option (3), length 32 (4): fd00:7777::/64, Flags [none], valid time 3000s, pref. time 5000s + 0x0000: 4000 0000 0bb8 0000 1388 0000 0000 fd00 + 0x0010: 7777 0000 0000 0000 0000 0000 0000 + 0x0000: 6000 34c9 0038 3aff fe80 0000 0000 0000 `.4..8:......... + 0x0010: 70c8 017e f25a 6733 ff02 0000 0000 0000 p..~.Zg3........ + 0x0020: 0000 0000 0000 0001 8600 cb64 ff00 0000 ...........d.... + 0x0030: 0000 0e10 0000 0000 0101 0000 0000 0000 ................ + 0x0040: 0304 4000 0000 0bb8 0000 1388 0000 0000 ..@............. + 0x0050: fd00 7777 0000 0000 0000 0000 0000 0000 ..ww............ + +Adding a new prefix with a different set of parameters: + + wpanctl:wpan1> set RouterAdvert:Prefix:Flag:AutoConfig true + wpanctl:wpan1> set RouterAdvert:Prefix:Flag:OnLink true + wpanctl:wpan1> set RouterAdvert:Prefix:PreferredLifetime 2500 + wpanctl:wpan1> set RouterAdvert:Prefix:PreferredLifetime 3000 + wpanctl:wpan1> set RouterAdvert:Prefix:PrefixLength 48 + wpanctl:wpan1> add RouterAdvert:Prefixes fd00:4321:: + + wpanctl:wpan1> get RouterAdvert:Prefixes + RouterAdvert:Prefixes = [ + "prefix: fd00:7777::/64, flags:[ ], valid lifetime:3000, preferred lifetime:5000" + "prefix: fd00:4321::/48, flags:[ on-link auto ], valid lifetime:3000, preferred lifetime:3000" + ] + +tcpdump + + 20:59:56.041669 IP6 (flowlabel 0x034c9, hlim 255, next-header ICMPv6 (58) payload length: 88) fe80::70c8:17e:f25a:6733 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 88 + hop limit 255, Flags [none], pref medium, router lifetime 0s, reachable time 3600s, retrans time 0s + source link-address option (1), length 8 (1): 00:00:00:00:00:00 + 0x0000: 0000 0000 0000 + prefix info option (3), length 32 (4): fd00:7777::/64, Flags [none], valid time 3000s, pref. time 5000s + 0x0000: 4000 0000 0bb8 0000 1388 0000 0000 fd00 + 0x0010: 7777 0000 0000 0000 0000 0000 0000 + prefix info option (3), length 32 (4): fd00:4321::/48, Flags [onlink, auto], valid time 3000s, pref. time 3000s + 0x0000: 30c0 0000 0bb8 0000 0bb8 0000 0000 fd00 + 0x0010: 4321 0000 0000 0000 0000 0000 0000 + 0x0000: 6000 34c9 0058 3aff fe80 0000 0000 0000 `.4..X:......... + 0x0010: 70c8 017e f25a 6733 ff02 0000 0000 0000 p..~.Zg3........ + 0x0020: 0000 0000 0000 0001 8600 3fee ff00 0000 ..........?..... + 0x0030: 0000 0e10 0000 0000 0101 0000 0000 0000 ................ + 0x0040: 0304 4000 0000 0bb8 0000 1388 0000 0000 ..@............. + 0x0050: fd00 7777 0000 0000 0000 0000 0000 0000 ..ww............ + 0x0060: 0304 30c0 0000 0bb8 0000 0bb8 0000 0000 ..0............. + 0x0070: fd00 4321 0000 0000 0000 0000 0000 0000 ..C!............ + +Removing a prefix (when removing prefix only prefix length paramter is required along with the pregfix itself) + + wpanctl:wpan1> set RouterAdvert:Prefix:PrefixLength 48 + wpanctl:wpan1> remove RouterAdvert:Prefixes fd00:4321:: + wpanctl:wpan1> get RouterAdvert:Prefixes + RouterAdvert:Prefixes = [ + "prefix: fd00:7777::/64, flags:[ ], valid lifetime:3000, preferred lifetime:5000" + ] + +tcpdump + + 21:25:43.421691 IP6 (flowlabel 0x034c9, hlim 255, next-header ICMPv6 (58) payload length: 56) fe80::70c8:17e:f25a:6733 > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 56 + hop limit 255, Flags [none], pref medium, router lifetime 0s, reachable time 3600s, retrans time 0s + source link-address option (1), length 8 (1): 00:00:00:00:00:00 + 0x0000: 0000 0000 0000 + prefix info option (3), length 32 (4): fd00:7777::/64, Flags [none], valid time 3000s, pref. time 5000s + 0x0000: 4000 0000 0bb8 0000 1388 0000 0000 fd00 + 0x0010: 7777 0000 0000 0000 0000 0000 0000 + 0x0000: 6000 34c9 0038 3aff fe80 0000 0000 0000 `.4..8:......... + 0x0010: 70c8 017e f25a 6733 ff02 0000 0000 0000 p..~.Zg3........ + 0x0020: 0000 0000 0000 0001 8600 cb64 ff00 0000 ...........d.... + 0x0030: 0000 0e10 0000 0000 0101 0000 0000 0000 ................ + 0x0040: 0304 4000 0000 0bb8 0000 1388 0000 0000 ..@............. + 0x0050: fd00 7777 0000 0000 0000 0000 0000 0000 ..ww............ + +The `RouterAdvert:AddRouteInfoOption` can be used to disable adding of ant "Route Info" option to RA: + + # Add a prefix to RA and also a Thread on-mesh prefix (which will add a corresponding route on host): + wpanctl:wpan1> set RouterAdvert:Netifs wpan1 + wpanctl:wpan1> set RouterAdvert:Prefixes fd00:cafe:beef:: + wpanctl:wpan1> get RouterAdvert:Prefixes + RouterAdvert:Prefixes = [ + "prefix: fd00:cafe:beef::/64, flags:[ on-link auto ], valid lifetime:3600, preferred lifetime:3600" + ] + wpanctl:wpan1> add-prefix fd00:abba:: -o -c + Successfully added prefix "fd00:abba::" len:64 stable:0 [on-mesh:1 def-route:0 config:1 dhcp:0 slaac:0 pref:0 prio:med] + + wpanctl:wpan1> get IPv6:Routes + IPv6:Routes = [ + "fd00:abba::/64 metric:256 " + ] + + wpanctl:wpan1> set RouterAdvert:Enable true + +tcpdump shows prefix info and two route option. + +(NOTE: Since we are seing RA with `fd00:cafe:beef::` on wpan1 interface with on-link and auto-config flags, linux itself added an address with this prefix on `wpan1` interface which in turn was pushed to NCP by wpantund and its prefix added to list of on-mesh prefixes within Thread network. This in turn caused it to be added as a router info option as well) + + + 21:33:00.653646 IP6 (flowlabel 0x3d2ab, hlim 255, next-header ICMPv6 (58) payload length: 88) fe80::a4ab:2dcb:6a20:ca2b > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 88 + hop limit 255, Flags [none], pref medium, router lifetime 0s, reachable time 3600s, retrans time 0s + source link-address option (1), length 8 (1): 00:00:00:00:00:00 + 0x0000: 0000 0000 0000 + prefix info option (3), length 32 (4): fd00:cafe:beef::/64, Flags [onlink, auto], valid time 3600s, pref. time 3600s + 0x0000: 40c0 0000 0e10 0000 0e10 0000 0000 fd00 + 0x0010: cafe beef 0000 0000 0000 0000 0000 + route info option (24), length 16 (2): fd00:abba::/64, pref=medium, lifetime=3600s + 0x0000: 4000 0000 0e10 fd00 abba 0000 0000 + route info option (24), length 16 (2): fd00:cafe:beef::/64, pref=medium, lifetime=3600s + 0x0000: 4000 0000 0e10 fd00 cafe beef 0000 + 0x0000: 6003 d2ab 0058 3aff fe80 0000 0000 0000 `....X:......... + 0x0010: a4ab 2dcb 6a20 ca2b ff02 0000 0000 0000 ..-.j..+........ + 0x0020: 0000 0000 0000 0001 8600 846f ff00 0000 ...........o.... + 0x0030: 0000 0e10 0000 0000 0101 0000 0000 0000 ................ + 0x0040: 0304 40c0 0000 0e10 0000 0e10 0000 0000 ..@............. + 0x0050: fd00 cafe beef 0000 0000 0000 0000 0000 ................ + 0x0060: 1802 4000 0000 0e10 fd00 abba 0000 0000 ..@............. + 0x0070: 1802 4000 0000 0e10 fd00 cafe beef 0000 ..@............. + +Now setting `RouterAdvert:AddRouteInfoOption` to `false` removes all route info options: + + set RouterAdvert:AddRouteInfoOption false + + + 21:33:43.462431 IP6 (flowlabel 0x3d2ab, hlim 255, next-header ICMPv6 (58) payload length: 56) fe80::a4ab:2dcb:6a20:ca2b > ff02::1: [icmp6 sum ok] ICMP6, router advertisement, length 56 + hop limit 255, Flags [none], pref medium, router lifetime 0s, reachable time 3600s, retrans time 0s + source link-address option (1), length 8 (1): 00:00:00:00:00:00 + 0x0000: 0000 0000 0000 + prefix info option (3), length 32 (4): fd00:cafe:beef::/64, Flags [onlink, auto], valid time 3600s, pref. time 3600s + 0x0000: 40c0 0000 0e10 0000 0e10 0000 0000 fd00 + 0x0010: cafe beef 0000 0000 0000 0000 0000 + 0x0000: 6003 d2ab 0038 3aff fe80 0000 0000 0000 `....8:......... + 0x0010: a4ab 2dcb 6a20 ca2b ff02 0000 0000 0000 ..-.j..+........ + 0x0020: 0000 0000 0000 0001 8600 805f ff00 0000 ..........._.... + 0x0030: 0000 0e10 0000 0000 0101 0000 0000 0000 ................ + 0x0040: 0304 40c0 0000 0e10 0000 0e10 0000 0000 ..@............. + 0x0050: fd00 cafe beef 0000 0000 0000 0000 0000 ................ + + Limitations: - The current implementation does not support replying to Router Solicitation messages. diff --git a/src/wpantund/ICMP6RouterAdvertiser.cpp b/src/wpantund/ICMP6RouterAdvertiser.cpp index cf92e492..7f754b06 100644 --- a/src/wpantund/ICMP6RouterAdvertiser.cpp +++ b/src/wpantund/ICMP6RouterAdvertiser.cpp @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -51,6 +50,7 @@ nl::wpantund::ICMP6RouterAdvertiser::ICMP6RouterAdvertiser(NCPInstanceBase* inst , mTxPeriod(DEFAULT_ROUTER_ADV_TX_PERIOD) , mDefaultRoutePreference(0) , mDefaultRouteLifetime(0) + , mShouldAddRouteInfoOption(true) , mStateChanged(false) { mSocket = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); @@ -70,6 +70,13 @@ nl::wpantund::ICMP6RouterAdvertiser::~ICMP6RouterAdvertiser(void) close(mSocket); } +void +nl::wpantund::ICMP6RouterAdvertiser::clear(void) +{ + clear_netifs(); + clear_prefixes(); +} + void nl::wpantund::ICMP6RouterAdvertiser::set_tx_period(uint32_t period) { @@ -84,6 +91,77 @@ nl::wpantund::ICMP6RouterAdvertiser::set_tx_period(uint32_t period) mStateChanged = true; } +std::list +nl::wpantund::ICMP6RouterAdvertiser::get_prefix_list(void) const +{ + std::list prefix_list; + char c_string[300]; + + for (std::list::const_iterator it = mPrefixes.cbegin(); it != mPrefixes.cend(); it++) { + snprintf(c_string, sizeof(c_string), "prefix: %s/%d, flags:[ %s%s], valid lifetime:%u, preferred lifetime:%u", + in6_addr_to_string(it->mPrefix).c_str(), it->mPrefixLength, + it->mFlagOnLink ? "on-link " : "", it->mFlagAutoAddressConfig ? "auto ": "", + it->mValidLifetime, it->mPreferredLifetime); + prefix_list.push_back(std::string(c_string)); + } + + return prefix_list; +} + +void +nl::wpantund::ICMP6RouterAdvertiser::add_prefix( + const struct in6_addr &prefix, + uint8_t prefix_len, + uint32_t valid_lifetime, + uint32_t preferred_lifetime, + bool flag_on_link, + bool flag_auto_config +) { + Prefix entry; + + remove_prefix(prefix, prefix_len); + + entry.mPrefix = prefix; + entry.mPrefixLength = prefix_len; + entry.mValidLifetime = valid_lifetime; + entry.mPreferredLifetime = preferred_lifetime; + entry.mFlagOnLink = flag_on_link; + entry.mFlagAutoAddressConfig = flag_auto_config; + + in6_addr_apply_mask(entry.mPrefix, entry.mPrefixLength); + + remove_prefix(entry.mPrefix, entry.mPrefixLength); + mPrefixes.push_back(entry); + + mStateChanged = true; +} + + +void +nl::wpantund::ICMP6RouterAdvertiser::remove_prefix(const struct in6_addr &prefix, uint8_t prefix_len) +{ + struct in6_addr masked_prefix = prefix; + + in6_addr_apply_mask(masked_prefix, prefix_len); + + for (std::list::iterator iter = mPrefixes.begin(); iter != mPrefixes.end(); iter++) { + if ((iter->mPrefixLength == prefix_len) && (iter->mPrefix == masked_prefix)) { + mPrefixes.erase(iter); + mStateChanged = true; + break; + } + } +} + +void +nl::wpantund::ICMP6RouterAdvertiser::clear_prefixes(void) +{ + if (!mPrefixes.empty()) { + mPrefixes.clear(); + mStateChanged = true; + } +} + void nl::wpantund::ICMP6RouterAdvertiser::send_router_advert(const char *netif_name) { @@ -114,8 +192,11 @@ nl::wpantund::ICMP6RouterAdvertiser::send_router_advert(const char *netif_name) } opt_route_info; std::map::iterator iter; int num_route_info_opt = 0; + int num_prefix_info_opt = 0; - if (mInstance->mInterfaceRoutes.empty() && (mDefaultRouteLifetime == 0)) { + if ((mDefaultRouteLifetime == 0) && mPrefixes.empty() && + (!mShouldAddRouteInfoOption || mInstance->mInterfaceRoutes.empty()) + ) { goto bail; } @@ -165,43 +246,73 @@ nl::wpantund::ICMP6RouterAdvertiser::send_router_advert(const char *netif_name) msg.append(reinterpret_cast(&opt_hdr), sizeof(opt_hdr)); msg.append(hw_addr, sizeof(hw_addr)); - // Prepare `Route Info` option for each interface route - for (iter = mInstance->mInterfaceRoutes.begin(); iter != mInstance->mInterfaceRoutes.end(); ++iter) { - uint8_t prefix_len = iter->first.get_length(); - uint32_t metric = iter->second.get_metric(); - - opt_route_info.mType = ROUTE_INFO_OPTION_TYPE; - - if (prefix_len > 64) { - opt_route_info.mLength = 3; - } else if (prefix_len > 0) { - opt_route_info.mLength = 2; - } else { - opt_route_info.mLength = 1; - } + // Prepare `Prefix Info` options + for (std::list::iterator it = mPrefixes.begin(); it != mPrefixes.end(); ++it) { + struct nd_opt_prefix_info opt_pi; - opt_route_info.mPrefixLength = prefix_len; + memset(&opt_pi, 0, sizeof(opt_pi)); - // Note that smaller metric is higher preference. - if (metric < NCPInstanceBase::InterfaceRouteEntry::kRouteMetricMedium) { - opt_route_info.mPreferenceFlags = ROUTE_INFO_OPTION_PRF_HIGH; - } else if (metric < NCPInstanceBase::InterfaceRouteEntry::kRouteMetricLow) { - opt_route_info.mPreferenceFlags = ROUTE_INFO_OPTION_PRF_MEDIUM; - } else { - opt_route_info.mPreferenceFlags = ROUTE_INFO_OPTION_PRF_LOW; - } + opt_pi.nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION; + opt_pi.nd_opt_pi_len = 4; // in units of 8 octets - opt_route_info.mLifetime = htonl(ROUTE_INFO_OPTION_LIFETIME); + opt_pi.nd_opt_pi_prefix_len = it->mPrefixLength; - msg.append(reinterpret_cast(&opt_route_info), sizeof(opt_route_info)); + if (it->mFlagOnLink) { + opt_pi.nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK; + } - if (prefix_len > 64) { - msg.append(iter->first.get_prefix().s6_addr, 16); - } else if (prefix_len > 0) { - msg.append(iter->first.get_prefix().s6_addr, 8); + if (it->mFlagAutoAddressConfig) { + opt_pi.nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO; } - num_route_info_opt++; + opt_pi.nd_opt_pi_valid_time = htonl(it->mValidLifetime); + opt_pi.nd_opt_pi_preferred_time = htonl(it->mPreferredLifetime); + memcpy(&opt_pi.nd_opt_pi_prefix, &it->mPrefix, sizeof(struct in6_addr)); + + msg.append(reinterpret_cast(&opt_pi), sizeof(opt_pi)); + + num_prefix_info_opt++; + } + + // Prepare `Route Info` option for each interface route + if (mShouldAddRouteInfoOption) { + for (iter = mInstance->mInterfaceRoutes.begin(); iter != mInstance->mInterfaceRoutes.end(); ++iter) { + uint8_t prefix_len = iter->first.get_length(); + uint32_t metric = iter->second.get_metric(); + + opt_route_info.mType = ROUTE_INFO_OPTION_TYPE; + + if (prefix_len > 64) { + opt_route_info.mLength = 3; + } else if (prefix_len > 0) { + opt_route_info.mLength = 2; + } else { + opt_route_info.mLength = 1; + } + + opt_route_info.mPrefixLength = prefix_len; + + // Note that smaller metric is higher preference. + if (metric < NCPInstanceBase::InterfaceRouteEntry::kRouteMetricMedium) { + opt_route_info.mPreferenceFlags = ROUTE_INFO_OPTION_PRF_HIGH; + } else if (metric < NCPInstanceBase::InterfaceRouteEntry::kRouteMetricLow) { + opt_route_info.mPreferenceFlags = ROUTE_INFO_OPTION_PRF_MEDIUM; + } else { + opt_route_info.mPreferenceFlags = ROUTE_INFO_OPTION_PRF_LOW; + } + + opt_route_info.mLifetime = htonl(ROUTE_INFO_OPTION_LIFETIME); + + msg.append(reinterpret_cast(&opt_route_info), sizeof(opt_route_info)); + + if (prefix_len > 64) { + msg.append(iter->first.get_prefix().s6_addr, 16); + } else if (prefix_len > 0) { + msg.append(iter->first.get_prefix().s6_addr, 8); + } + + num_route_info_opt++; + } } if (sendto(mSocket, msg.data(), msg.size(), 0, reinterpret_cast(&saddr), sizeof(saddr)) < 0) { @@ -209,7 +320,8 @@ nl::wpantund::ICMP6RouterAdvertiser::send_router_advert(const char *netif_name) goto bail; } - syslog(LOG_INFO, "Sent ICMP6 RouterAdvert on \"%s\" (%d route info options)", netif_name, num_route_info_opt); + syslog(LOG_INFO, "Sent ICMP6 RouterAdvert on \"%s\" (options: %d prefix info, %d route info)", netif_name, + num_prefix_info_opt, num_route_info_opt); bail: return; diff --git a/src/wpantund/ICMP6RouterAdvertiser.h b/src/wpantund/ICMP6RouterAdvertiser.h index 98b00f62..2fed9dbc 100644 --- a/src/wpantund/ICMP6RouterAdvertiser.h +++ b/src/wpantund/ICMP6RouterAdvertiser.h @@ -23,9 +23,12 @@ #ifndef __wpantund__ICMP6RouterAdvetiser__ #define __wpantund__ICMP6RouterAdvetiser__ +#include #include #include +#include + #include "EventHandler.h" namespace nl { @@ -45,6 +48,8 @@ class ICMP6RouterAdvertiser : public EventHandler ICMP6RouterAdvertiser(NCPInstanceBase* instance); ~ICMP6RouterAdvertiser(void); + void clear(void); + void set_enabled(bool enabled) { mEnabled = enabled; mStateChanged = true; } bool is_enabled(void) const { return mEnabled; } @@ -63,10 +68,30 @@ class ICMP6RouterAdvertiser : public EventHandler void set_default_route_lifetime(uint16_t lifetime) { mDefaultRouteLifetime = lifetime; mStateChanged = true; } uint16_t get_default_route_lifetime(void) const { return mDefaultRouteLifetime; } + void set_should_add_route_info_option(bool enable) { mShouldAddRouteInfoOption = enable; mStateChanged = true; } + bool get_should_add_route_info_option(void) const { return mShouldAddRouteInfoOption; } + + std::list get_prefix_list(void) const; + + void add_prefix(const struct in6_addr &prefix, uint8_t prefix_len, uint32_t valid_lifetime, + uint32_t preferred_lifetime, bool flag_on_link, bool flag_auto_config); + void remove_prefix(const struct in6_addr &prefix, uint8_t prefix_len); + void clear_prefixes(void); + void signal_routes_changed(void) { mStateChanged = true; } virtual int vprocess_event(int event, va_list args); + private: + struct Prefix { + struct in6_addr mPrefix; + uint8_t mPrefixLength; + uint32_t mValidLifetime; + uint32_t mPreferredLifetime; + bool mFlagOnLink; + bool mFlagAutoAddressConfig; + }; + void send_router_advert(const char *netif_name); NCPInstanceBase *mInstance; @@ -77,7 +102,9 @@ class ICMP6RouterAdvertiser : public EventHandler uint32_t mTxPeriod; int mDefaultRoutePreference; uint16_t mDefaultRouteLifetime; + bool mShouldAddRouteInfoOption; bool mStateChanged; + std::list mPrefixes; }; }; // namespace wpantund diff --git a/src/wpantund/NCPInstanceBase-Addresses.cpp b/src/wpantund/NCPInstanceBase-Addresses.cpp index 0fa306b3..47ef0933 100644 --- a/src/wpantund/NCPInstanceBase-Addresses.cpp +++ b/src/wpantund/NCPInstanceBase-Addresses.cpp @@ -442,6 +442,7 @@ NCPInstanceBase::remove_all_address_prefix_route_entries(void) mOffMeshRoutes.clear(); mInterfaceRoutes.clear(); mServiceEntries.clear(); + mICMP6RouterAdvertiser.clear(); } void diff --git a/src/wpantund/NCPInstanceBase.cpp b/src/wpantund/NCPInstanceBase.cpp index 0677f7d9..ee59f276 100644 --- a/src/wpantund/NCPInstanceBase.cpp +++ b/src/wpantund/NCPInstanceBase.cpp @@ -87,6 +87,12 @@ NCPInstanceBase::NCPInstanceBase(const Settings& settings): mWasBusy = false; mNCPIsMisbehaving = false; + mRouterAdvertPrefixValidLifetime = 3600; + mRouterAdvertPrefixPreferredLifetime = 3600; + mRouterAdvertPrefixLength = 64; + mRouterAdvertPrefixFlagOnLink = true; + mRouterAdvertPrefixFlagAutoConfig = true; + regsiter_all_get_handlers(); regsiter_all_set_handlers(); regsiter_all_insert_handlers(); @@ -336,6 +342,13 @@ NCPInstanceBase::get_supported_property_keys(void) const properties.insert(kWPANTUNDProperty_RouterAdvertTxPeriod); properties.insert(kWPANTUNDProperty_RouterAdvertDefaultRoutePreference); properties.insert(kWPANTUNDProperty_RouterAdvertDefaultRouteLifetime); + properties.insert(kWPANTUNDProperty_RouterAdvertAddRouteInfoOption); + properties.insert(kWPANTUNDProperty_RouterAdvertPrefixes); + properties.insert(kWPANTUNDProperty_RouterAdvertPrefixValidLifetime); + properties.insert(kWPANTUNDProperty_RouterAdvertPrefixPreferredLifetime); + properties.insert(kWPANTUNDProperty_RouterAdvertPrefixPrefixLength); + properties.insert(kWPANTUNDProperty_RouterAdvertPrefixFlagOnLink); + properties.insert(kWPANTUNDProperty_RouterAdvertPrefixFlagAutoConfig); return properties; } @@ -418,6 +431,13 @@ NCPInstanceBase::regsiter_all_get_handlers(void) REGISTER_GET_HANDLER(RouterAdvertTxPeriod); REGISTER_GET_HANDLER(RouterAdvertDefaultRoutePreference); REGISTER_GET_HANDLER(RouterAdvertDefaultRouteLifetime); + REGISTER_GET_HANDLER(RouterAdvertAddRouteInfoOption); + REGISTER_GET_HANDLER(RouterAdvertPrefixes); + REGISTER_GET_HANDLER(RouterAdvertPrefixValidLifetime); + REGISTER_GET_HANDLER(RouterAdvertPrefixPreferredLifetime); + REGISTER_GET_HANDLER(RouterAdvertPrefixPrefixLength); + REGISTER_GET_HANDLER(RouterAdvertPrefixFlagOnLink); + REGISTER_GET_HANDLER(RouterAdvertPrefixFlagAutoConfig); #undef REGISTER_GET_HANDLER } @@ -861,6 +881,49 @@ NCPInstanceBase::get_prop_RouterAdvertDefaultRouteLifetime(CallbackWithStatusArg cb(kWPANTUNDStatus_Ok, boost::any(mICMP6RouterAdvertiser.get_default_route_lifetime())); } +void +NCPInstanceBase::get_prop_RouterAdvertAddRouteInfoOption(CallbackWithStatusArg1 cb) +{ + cb(kWPANTUNDStatus_Ok, boost::any(mICMP6RouterAdvertiser.get_should_add_route_info_option())); +} + +void +NCPInstanceBase::get_prop_RouterAdvertPrefixes(CallbackWithStatusArg1 cb) +{ + cb(kWPANTUNDStatus_Ok, boost::any(mICMP6RouterAdvertiser.get_prefix_list())); +} + +void +NCPInstanceBase::get_prop_RouterAdvertPrefixValidLifetime(CallbackWithStatusArg1 cb) +{ + cb(kWPANTUNDStatus_Ok, boost::any(mRouterAdvertPrefixValidLifetime)); + +} + +void +NCPInstanceBase::get_prop_RouterAdvertPrefixPreferredLifetime(CallbackWithStatusArg1 cb) +{ + cb(kWPANTUNDStatus_Ok, boost::any(mRouterAdvertPrefixPreferredLifetime)); +} + +void +NCPInstanceBase::get_prop_RouterAdvertPrefixPrefixLength(CallbackWithStatusArg1 cb) +{ + cb(kWPANTUNDStatus_Ok, boost::any(static_cast(mRouterAdvertPrefixLength))); +} + +void +NCPInstanceBase::get_prop_RouterAdvertPrefixFlagOnLink(CallbackWithStatusArg1 cb) +{ + cb(kWPANTUNDStatus_Ok, boost::any(mRouterAdvertPrefixFlagOnLink)); +} + +void +NCPInstanceBase::get_prop_RouterAdvertPrefixFlagAutoConfig(CallbackWithStatusArg1 cb) +{ + cb(kWPANTUNDStatus_Ok, boost::any(mRouterAdvertPrefixFlagAutoConfig)); +} + // ---------------------------------------------------------------------------- // MARK: - // MARK: Property Set Handlers @@ -901,6 +964,13 @@ NCPInstanceBase::regsiter_all_set_handlers(void) REGISTER_SET_HANDLER(RouterAdvertTxPeriod); REGISTER_SET_HANDLER(RouterAdvertDefaultRoutePreference); REGISTER_SET_HANDLER(RouterAdvertDefaultRouteLifetime); + REGISTER_SET_HANDLER(RouterAdvertAddRouteInfoOption); + REGISTER_SET_HANDLER(RouterAdvertPrefixValidLifetime); + REGISTER_SET_HANDLER(RouterAdvertPrefixPreferredLifetime); + REGISTER_SET_HANDLER(RouterAdvertPrefixPrefixLength); + REGISTER_SET_HANDLER(RouterAdvertPrefixFlagOnLink); + REGISTER_SET_HANDLER(RouterAdvertPrefixFlagAutoConfig); + REGISTER_SET_HANDLER(RouterAdvertPrefixes); #undef REGISTER_SET_HANDLER } @@ -1210,6 +1280,77 @@ NCPInstanceBase::set_prop_RouterAdvertDefaultRouteLifetime(const boost::any &val cb(kWPANTUNDStatus_Ok); } +void +NCPInstanceBase::set_prop_RouterAdvertAddRouteInfoOption(const boost::any &value, CallbackWithStatus cb) +{ + mICMP6RouterAdvertiser.set_should_add_route_info_option(any_to_bool(value)); + cb(kWPANTUNDStatus_Ok); +} + +void +NCPInstanceBase::set_prop_RouterAdvertPrefixValidLifetime(const boost::any &value, CallbackWithStatus cb) +{ + int lifetime = any_to_int(value); + + if (lifetime < 0) { + lifetime = 0; + } + + mRouterAdvertPrefixValidLifetime = static_cast(lifetime); + cb(kWPANTUNDStatus_Ok); +} + +void +NCPInstanceBase::set_prop_RouterAdvertPrefixPreferredLifetime(const boost::any &value, CallbackWithStatus cb) +{ + int lifetime = any_to_int(value); + + if (lifetime < 0) { + lifetime = 0; + } + + mRouterAdvertPrefixPreferredLifetime = static_cast(lifetime); + cb(kWPANTUNDStatus_Ok); +} + +void +NCPInstanceBase::set_prop_RouterAdvertPrefixPrefixLength(const boost::any &value, CallbackWithStatus cb) +{ + int plen = any_to_int(value); + + if (plen < 0) { + plen = 0; + } + + if (plen > 128) { + plen = 128; + } + + mRouterAdvertPrefixLength = static_cast(plen); + cb(kWPANTUNDStatus_Ok); +} + +void +NCPInstanceBase::set_prop_RouterAdvertPrefixFlagOnLink(const boost::any &value, CallbackWithStatus cb) +{ + mRouterAdvertPrefixFlagOnLink = any_to_bool(value); + cb(kWPANTUNDStatus_Ok); +} + +void +NCPInstanceBase::set_prop_RouterAdvertPrefixFlagAutoConfig(const boost::any &value, CallbackWithStatus cb) +{ + mRouterAdvertPrefixFlagAutoConfig = any_to_bool(value); + cb(kWPANTUNDStatus_Ok); +} + +void +NCPInstanceBase::set_prop_RouterAdvertPrefixes(const boost::any &value, CallbackWithStatus cb) +{ + mICMP6RouterAdvertiser.clear_prefixes(); + insert_prop_RouterAdvertPrefixes(value, cb); +} + // ---------------------------------------------------------------------------- // MARK: - // MARK: Property Insert Handlers @@ -1231,6 +1372,7 @@ NCPInstanceBase::regsiter_all_insert_handlers(void) REGISTER_INSERT_HANDLER(IPv6MulticastAddresses); REGISTER_INSERT_HANDLER(RouterAdvertNetifs); + REGISTER_INSERT_HANDLER(RouterAdvertPrefixes); #undef REGISTER_INSERT_HANDLER } @@ -1278,6 +1420,15 @@ NCPInstanceBase::insert_prop_RouterAdvertNetifs(const boost::any &value, Callbac cb(kWPANTUNDStatus_Ok); } +void +NCPInstanceBase::insert_prop_RouterAdvertPrefixes(const boost::any &value, CallbackWithStatus cb) +{ + mICMP6RouterAdvertiser.add_prefix(any_to_ipv6(value), mRouterAdvertPrefixLength, mRouterAdvertPrefixValidLifetime, + mRouterAdvertPrefixPreferredLifetime, mRouterAdvertPrefixFlagOnLink, mRouterAdvertPrefixFlagAutoConfig); + + cb(kWPANTUNDStatus_Ok); +} + // ---------------------------------------------------------------------------- // MARK: - // MARK: Property Remove Handlers @@ -1299,6 +1450,7 @@ NCPInstanceBase::regsiter_all_remove_handlers(void) REGISTER_REMOVE_HANDLER(IPv6MulticastAddresses); REGISTER_REMOVE_HANDLER(RouterAdvertNetifs); + REGISTER_REMOVE_HANDLER(RouterAdvertPrefixes); #undef REGISTER_REMOVE_HANDLER } @@ -1345,6 +1497,13 @@ NCPInstanceBase::remove_prop_RouterAdvertNetifs(const boost::any &value, Callbac cb(kWPANTUNDStatus_Ok); } +void +NCPInstanceBase::remove_prop_RouterAdvertPrefixes(const boost::any &value, CallbackWithStatus cb) +{ + mICMP6RouterAdvertiser.remove_prefix(any_to_ipv6(value), mRouterAdvertPrefixLength); + cb(kWPANTUNDStatus_Ok); +} + void NCPInstanceBase::signal_property_changed( const std::string& key, diff --git a/src/wpantund/NCPInstanceBase.h b/src/wpantund/NCPInstanceBase.h index ce43eea1..8c33db81 100644 --- a/src/wpantund/NCPInstanceBase.h +++ b/src/wpantund/NCPInstanceBase.h @@ -372,6 +372,13 @@ class NCPInstanceBase : public NCPInstance, public EventHandler { void get_prop_RouterAdvertTxPeriod(CallbackWithStatusArg1 cb); void get_prop_RouterAdvertDefaultRoutePreference(CallbackWithStatusArg1 cb); void get_prop_RouterAdvertDefaultRouteLifetime(CallbackWithStatusArg1 cb); + void get_prop_RouterAdvertAddRouteInfoOption(CallbackWithStatusArg1 cb); + void get_prop_RouterAdvertPrefixes(CallbackWithStatusArg1 cb); + void get_prop_RouterAdvertPrefixValidLifetime(CallbackWithStatusArg1 cb); + void get_prop_RouterAdvertPrefixPreferredLifetime(CallbackWithStatusArg1 cb); + void get_prop_RouterAdvertPrefixPrefixLength(CallbackWithStatusArg1 cb); + void get_prop_RouterAdvertPrefixFlagOnLink(CallbackWithStatusArg1 cb); + void get_prop_RouterAdvertPrefixFlagAutoConfig(CallbackWithStatusArg1 cb); void regsiter_all_set_handlers(void); @@ -398,16 +405,25 @@ class NCPInstanceBase : public NCPInstance, public EventHandler { void set_prop_RouterAdvertTxPeriod(const boost::any &value, CallbackWithStatus cb); void set_prop_RouterAdvertDefaultRoutePreference(const boost::any &value, CallbackWithStatus cb); void set_prop_RouterAdvertDefaultRouteLifetime(const boost::any &value, CallbackWithStatus cb); + void set_prop_RouterAdvertAddRouteInfoOption(const boost::any &value, CallbackWithStatus cb); + void set_prop_RouterAdvertPrefixValidLifetime(const boost::any &value, CallbackWithStatus cb); + void set_prop_RouterAdvertPrefixPreferredLifetime(const boost::any &value, CallbackWithStatus cb); + void set_prop_RouterAdvertPrefixPrefixLength(const boost::any &value, CallbackWithStatus cb); + void set_prop_RouterAdvertPrefixFlagOnLink(const boost::any &value, CallbackWithStatus cb); + void set_prop_RouterAdvertPrefixFlagAutoConfig(const boost::any &value, CallbackWithStatus cb); + void set_prop_RouterAdvertPrefixes(const boost::any &value, CallbackWithStatus cb); void regsiter_all_insert_handlers(void); void insert_prop_IPv6MulticastAddresses(const boost::any &value, CallbackWithStatus cb); void insert_prop_RouterAdvertNetifs(const boost::any &value, CallbackWithStatus cb); + void insert_prop_RouterAdvertPrefixes(const boost::any &value, CallbackWithStatus cb); void regsiter_all_remove_handlers(void); void remove_prop_IPv6MulticastAddresses(const boost::any &value, CallbackWithStatus cb); void remove_prop_RouterAdvertNetifs(const boost::any &value, CallbackWithStatus cb); + void remove_prop_RouterAdvertPrefixes(const boost::any &value, CallbackWithStatus cb); private: @@ -792,6 +808,11 @@ class NCPInstanceBase : public NCPInstance, public EventHandler { RunawayResetBackoffManager mRunawayResetBackoffManager; ICMP6RouterAdvertiser mICMP6RouterAdvertiser; + uint32_t mRouterAdvertPrefixValidLifetime; + uint32_t mRouterAdvertPrefixPreferredLifetime; + uint8_t mRouterAdvertPrefixLength; + bool mRouterAdvertPrefixFlagOnLink; + bool mRouterAdvertPrefixFlagAutoConfig; protected: // ======================================================================== diff --git a/src/wpantund/wpan-properties.h b/src/wpantund/wpan-properties.h index c49542e3..fb4792f2 100644 --- a/src/wpantund/wpan-properties.h +++ b/src/wpantund/wpan-properties.h @@ -344,6 +344,14 @@ #define kWPANTUNDProperty_RouterAdvertTxPeriod "RouterAdvert:TxPeriod" #define kWPANTUNDProperty_RouterAdvertDefaultRoutePreference "RouterAdvert:DefaultRoute:Preference" #define kWPANTUNDProperty_RouterAdvertDefaultRouteLifetime "RouterAdvert:DefaultRoute:Lifetime" +#define kWPANTUNDProperty_RouterAdvertAddRouteInfoOption "RouterAdvert:AddRouteInfoOption" +#define kWPANTUNDProperty_RouterAdvertPrefixes "RouterAdvert:Prefixes" +// Properties to configure parameters associated with any next added prefix +#define kWPANTUNDProperty_RouterAdvertPrefixValidLifetime "RouterAdvert:Prefix:ValidLifetime" +#define kWPANTUNDProperty_RouterAdvertPrefixPreferredLifetime "RouterAdvert:Prefix:PreferredLifetime" +#define kWPANTUNDProperty_RouterAdvertPrefixPrefixLength "RouterAdvert:Prefix:PrefixLength" +#define kWPANTUNDProperty_RouterAdvertPrefixFlagOnLink "RouterAdvert:Prefix:Flag:OnLink" +#define kWPANTUNDProperty_RouterAdvertPrefixFlagAutoConfig "RouterAdvert:Prefix:Flag:AutoConfig" // ----------------------------------------------------------------------------