|
41 | 41 | #include <sys/socket.h> |
42 | 42 | #include <sys/types.h> |
43 | 43 | #include <unistd.h> |
| 44 | +#ifdef __linux__ |
| 45 | +#include <linux/rtnetlink.h> |
| 46 | +#endif |
44 | 47 |
|
45 | 48 | #include <openthread/platform/time.h> |
46 | 49 |
|
47 | 50 | #include "ip6_utils.hpp" |
48 | 51 | #include "platform-posix.h" |
| 52 | +#include "utils.hpp" |
49 | 53 | #include "common/code_utils.hpp" |
50 | 54 |
|
51 | 55 | extern "C" otError otPlatMdnsSetListeningEnabled(otInstance *aInstance, bool aEnable, uint32_t aInfraIfIndex) |
@@ -100,6 +104,10 @@ void MdnsSocket::Init(void) |
100 | 104 | mMulticastIp4Address.mFields.m8[3] = 251; |
101 | 105 |
|
102 | 106 | memset(&mTxQueue, 0, sizeof(mTxQueue)); |
| 107 | + |
| 108 | +#if OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_NETLINK |
| 109 | + mNetlinkFd = -1; |
| 110 | +#endif |
103 | 111 | } |
104 | 112 |
|
105 | 113 | void MdnsSocket::SetUp(void) |
@@ -154,6 +162,8 @@ void MdnsSocket::Update(otSysMainloopContext &aContext) |
154 | 162 |
|
155 | 163 | #if (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC) |
156 | 164 | UpdateTimeout(aContext.mTimeout); |
| 165 | +#elif (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_NETLINK) |
| 166 | + UpdateNetlink(aContext); |
157 | 167 | #endif |
158 | 168 |
|
159 | 169 | exit: |
@@ -186,6 +196,8 @@ void MdnsSocket::Process(const otSysMainloopContext &aContext) |
186 | 196 |
|
187 | 197 | #if (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC) |
188 | 198 | ProcessTimeout(); |
| 199 | +#elif (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_NETLINK) |
| 200 | + ProcessNetlink(aContext); |
189 | 201 | #endif |
190 | 202 |
|
191 | 203 | exit: |
@@ -508,13 +520,13 @@ void MdnsSocket::ReceiveMessage(MsgType aMsgType) |
508 | 520 | //--------------------------------------------------------------------------------------------------------------------- |
509 | 521 | // Monitoring address on infra netif |
510 | 522 |
|
511 | | -#if (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC) |
512 | | - |
513 | 523 | void MdnsSocket::ReportInfraIfAddresses(void) |
514 | 524 | { |
515 | 525 | struct ifaddrs *ifAddrs = nullptr; |
516 | 526 |
|
| 527 | +#if (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC) |
517 | 528 | mNextReportTime = otPlatTimeGet() + kAddrMonitorPeriod * OT_US_PER_MS; |
| 529 | +#endif |
518 | 530 |
|
519 | 531 | if (getifaddrs(&ifAddrs) < 0) |
520 | 532 | { |
@@ -558,6 +570,12 @@ void MdnsSocket::ReportInfraIfAddresses(void) |
558 | 570 | } |
559 | 571 | } |
560 | 572 |
|
| 573 | +#if (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC) |
| 574 | + |
| 575 | +void MdnsSocket::StartAddressMonitoring(void) { ReportInfraIfAddresses(); } |
| 576 | + |
| 577 | +void MdnsSocket::StopAddressMonitoring(void) {} |
| 578 | + |
561 | 579 | void MdnsSocket::UpdateTimeout(struct timeval &aTimeout) |
562 | 580 | { |
563 | 581 | uint64_t now = otPlatTimeGet(); |
@@ -588,6 +606,165 @@ void MdnsSocket::ProcessTimeout(void) |
588 | 606 |
|
589 | 607 | #endif // (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_PERIODIC) |
590 | 608 |
|
| 609 | +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
| 610 | + |
| 611 | +#if (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_NETLINK) |
| 612 | + |
| 613 | +void MdnsSocket::StartAddressMonitoring(void) |
| 614 | +{ |
| 615 | + int rval; |
| 616 | + struct sockaddr_nl addr; |
| 617 | + |
| 618 | + mNetlinkFd = SocketWithCloseExec(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, kSocketBlock); |
| 619 | + VerifyOrDie(mNetlinkFd >= 0, OT_EXIT_ERROR_ERRNO); |
| 620 | + |
| 621 | + memset(&addr, 0, sizeof(addr)); |
| 622 | + addr.nl_family = AF_NETLINK; |
| 623 | + addr.nl_groups = RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR; |
| 624 | + |
| 625 | + rval = bind(mNetlinkFd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)); |
| 626 | + VerifyOrDie(rval == 0, OT_EXIT_ERROR_ERRNO); |
| 627 | + |
| 628 | + ReportInfraIfAddresses(); |
| 629 | +} |
| 630 | + |
| 631 | +void MdnsSocket::StopAddressMonitoring(void) |
| 632 | +{ |
| 633 | + if (mNetlinkFd >= 0) |
| 634 | + { |
| 635 | + close(mNetlinkFd); |
| 636 | + } |
| 637 | + |
| 638 | + mNetlinkFd = -1; |
| 639 | +} |
| 640 | + |
| 641 | +void MdnsSocket::UpdateNetlink(otSysMainloopContext &aContext) const |
| 642 | +{ |
| 643 | + VerifyOrExit(mNetlinkFd >= 0); |
| 644 | + |
| 645 | + FD_SET(mNetlinkFd, &aContext.mReadFdSet); |
| 646 | + |
| 647 | + if (aContext.mMaxFd < mNetlinkFd) |
| 648 | + { |
| 649 | + aContext.mMaxFd = mNetlinkFd; |
| 650 | + } |
| 651 | + |
| 652 | +exit: |
| 653 | + return; |
| 654 | +} |
| 655 | + |
| 656 | +void MdnsSocket::ProcessNetlink(const otSysMainloopContext &aContext) const |
| 657 | +{ |
| 658 | + static const size_t kBufSize = 8192; |
| 659 | + |
| 660 | + union NetlinkMessage |
| 661 | + { |
| 662 | + struct nlmsghdr mHeader; |
| 663 | + uint8_t mBuffer[kBufSize]; |
| 664 | + }; |
| 665 | + |
| 666 | + NetlinkMessage rcvMsg; |
| 667 | + ssize_t rval; |
| 668 | + size_t len; |
| 669 | + |
| 670 | + VerifyOrExit(mNetlinkFd >= 0); |
| 671 | + |
| 672 | + VerifyOrExit(FD_ISSET(mNetlinkFd, &aContext.mReadFdSet)); |
| 673 | + |
| 674 | + rval = recv(mNetlinkFd, rcvMsg.mBuffer, sizeof(rcvMsg.mBuffer), 0); |
| 675 | + |
| 676 | + if (rval < 0) |
| 677 | + { |
| 678 | + LogCrit("Failed to receive netlink message: %s", strerror(errno)); |
| 679 | + ExitNow(); |
| 680 | + } |
| 681 | + |
| 682 | + VerifyOrExit(static_cast<size_t>(rval) <= sizeof(rcvMsg.mBuffer)); |
| 683 | + |
| 684 | + len = static_cast<size_t>(rval); |
| 685 | + |
| 686 | + VerifyOrExit(len >= sizeof(nlmsghdr)); |
| 687 | + |
| 688 | + for (struct nlmsghdr *msg = &rcvMsg.mHeader; NLMSG_OK(msg, len); msg = NLMSG_NEXT(msg, len)) |
| 689 | + { |
| 690 | + switch (msg->nlmsg_type) |
| 691 | + { |
| 692 | + case RTM_NEWADDR: |
| 693 | + case RTM_DELADDR: |
| 694 | + ProcessNetlinkAddrEvent(msg); |
| 695 | + break; |
| 696 | + case NLMSG_ERROR: |
| 697 | + LogWarn("netlink error:%d", reinterpret_cast<struct nlmsgerr *>(NLMSG_DATA(msg))->error); |
| 698 | + break; |
| 699 | + case NLMSG_DONE: |
| 700 | + ExitNow(); |
| 701 | + } |
| 702 | + } |
| 703 | + |
| 704 | +exit: |
| 705 | + return; |
| 706 | +} |
| 707 | + |
| 708 | +void MdnsSocket::ProcessNetlinkAddrEvent(void *aNetlinkMsg) const |
| 709 | +{ |
| 710 | + struct nlmsghdr *msg = static_cast<struct nlmsghdr *>(aNetlinkMsg); |
| 711 | + struct ifaddrmsg *addrmsg = reinterpret_cast<struct ifaddrmsg *>(NLMSG_DATA(msg)); |
| 712 | + bool added = (msg->nlmsg_type == RTM_NEWADDR); |
| 713 | + size_t len; |
| 714 | + struct rtattr *rta; |
| 715 | + otIp6Address ip6Addr; |
| 716 | + otIp4Address ip4Addr; |
| 717 | + |
| 718 | + VerifyOrExit(addrmsg->ifa_index == mInfraIfIndex); |
| 719 | + |
| 720 | + switch (addrmsg->ifa_family) |
| 721 | + { |
| 722 | + case AF_INET6: |
| 723 | + case AF_INET: |
| 724 | + break; |
| 725 | + default: |
| 726 | + ExitNow(); |
| 727 | + } |
| 728 | + |
| 729 | + len = IFA_PAYLOAD(msg); |
| 730 | + |
| 731 | + for (rta = reinterpret_cast<struct rtattr *>(IFA_RTA(addrmsg)); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) |
| 732 | + { |
| 733 | + switch (rta->rta_type) |
| 734 | + { |
| 735 | + case IFA_ADDRESS: |
| 736 | + case IFA_LOCAL: |
| 737 | + if (addrmsg->ifa_family == AF_INET6) |
| 738 | + { |
| 739 | + if (RTA_PAYLOAD(rta) < sizeof(otIp6Address)) |
| 740 | + { |
| 741 | + continue; |
| 742 | + } |
| 743 | + |
| 744 | + ReadIp6AddressFrom(RTA_DATA(rta), ip6Addr); |
| 745 | + } |
| 746 | + else |
| 747 | + { |
| 748 | + if (RTA_PAYLOAD(rta) < sizeof(otIp4Address)) |
| 749 | + { |
| 750 | + continue; |
| 751 | + } |
| 752 | + |
| 753 | + memcpy(&ip4Addr, RTA_DATA(rta), sizeof(otIp4Address)); |
| 754 | + otIp4ToIp4MappedIp6Address(&ip4Addr, &ip6Addr); |
| 755 | + } |
| 756 | + |
| 757 | + otPlatMdnsHandleHostAddressEvent(mInstance, &ip6Addr, added, mInfraIfIndex); |
| 758 | + break; |
| 759 | + } |
| 760 | + } |
| 761 | + |
| 762 | +exit: |
| 763 | + return; |
| 764 | +} |
| 765 | + |
| 766 | +#endif // (OPENTHREAD_POSIX_CONFIG_MDNS_ADDR_MONITOR == OT_POSIX_MDNS_ADDR_MONITOR_NETLINK) |
| 767 | + |
591 | 768 | //--------------------------------------------------------------------------------------------------------------------- |
592 | 769 | // Socket helpers |
593 | 770 |
|
|
0 commit comments