UPnPsdk 0.1
Universal Plug and Play +, Software Development Kit
 
Loading...
Searching...
No Matches
netadapter_unix.cpp
Go to the documentation of this file.
1// Copyright (C) 2024+ GPL 3 and higher by Ingo Höft, <Ingo@Hoeft-online.de>
2// Redistribution only with this Copyright remark. Last modified: 2025-03-25
9#include <UPnPsdk/synclog.hpp>
11#include <umock/ifaddrs.hpp>
12#include <umock/net_if.hpp>
13#include <cstring>
15
16namespace UPnPsdk {
17
18CNetadapter_platform::CNetadapter_platform(){
19 TRACE2(this, " Construct CNetadapter_platform()") //
20}
21
22CNetadapter_platform::~CNetadapter_platform() {
23 TRACE2(this, " Destruct CNetadapter_platform()")
24 this->free_ifaddrs();
25}
26
28 TRACE2(this, " Executing CNetadapter_platform::get_first()")
29
30 // Get system adapters addresses.
31 this->free_ifaddrs();
32 if (getifaddrs(&m_ifa_first) != 0) {
33 throw std::runtime_error(
34 UPnPsdk_LOGEXCEPT("MSG1119") "Failed to get information from "
35 "the network adapters: " +
36 std::string(std::strerror(errno)) + '\n');
37 }
38 UPnPsdk_LOGINFO("MSG1132") "syscall ::getifaddrs() gets " << m_ifa_first
39 << "\n";
40 this->reset();
41}
42
44 TRACE2(this, " Executing CNetadapter_platform::get_next()")
45 if (m_ifa_current == nullptr)
46 return false;
47
48 m_ifa_current = m_ifa_current->ifa_next;
49
50 for (; m_ifa_current != nullptr; m_ifa_current = m_ifa_current->ifa_next) {
51 if (is_valid_if(m_ifa_current))
52 return true; // Does not increment m_ifa_current
53 }
54 return false;
55}
56
57unsigned int CNetadapter_platform::index() const {
58 TRACE2(this, " Executing CNetadapter_platform::index()")
59 return (m_ifa_current == nullptr)
60 ? 0
61 : umock::net_if_h.if_nametoindex(m_ifa_current->ifa_name);
62}
63
64std::string CNetadapter_platform::name() const {
65 TRACE2(this, " Executing CNetadapter_platform::name()")
66 return (m_ifa_current == nullptr) ? "" : m_ifa_current->ifa_name;
67}
68
69#if 0
70// Due to RFC4038 I code IP Version-Independent, so this method is not provided.
71//
72sa_family_t CNetadapter_platform::in_family() { // noexcept
73 TRACE2(this, " Executing CNetadapter_platform::in_family()")
74 if (m_ifa_current == nullptr)
75 return AF_UNSPEC;
76 return m_ifa_current->ifa_addr->sa_family;
77}
78#endif
79
81 TRACE2(this, " Executing CNetadapter_platform::sockaddr()")
82 if (m_ifa_current == nullptr) {
83 // If no information found then return an empty netaddress.
84 a_saddr = "";
85 } else {
86 // Copy address of the network adapter.
87 a_saddr = reinterpret_cast<sockaddr_storage&>(*m_ifa_current->ifa_addr);
88 }
89}
90
92 TRACE2(this, " Executing CNetadapter_platform::socknetmask()")
93 if (m_ifa_current != nullptr) {
94 // Copy netmask of the network adapter
95 a_snetmask =
96 reinterpret_cast<sockaddr_storage&>(*m_ifa_current->ifa_netmask);
97 }
98}
99
100
101unsigned int CNetadapter_platform::bitmask() const {
102 TRACE2(this, " Executing CNetadapter_platform::bitmask()")
103 if (m_ifa_current == nullptr)
104 return 0;
105
106 return netmask_to_bitmask(reinterpret_cast<const ::sockaddr_storage*>(
107 m_ifa_current->ifa_netmask));
108}
109
110
111// Private helper methods
112// ----------------------
113//
114void CNetadapter_platform::free_ifaddrs() noexcept {
115 TRACE2(this, " Executing CNetadapter::free_ifaddrs()")
116 if (m_ifa_first != nullptr) {
117 UPnPsdk_LOGINFO("MSG1116") "syscall ::freeifaddrs(" << m_ifa_first
118 << ")\n";
119 freeifaddrs(m_ifa_first);
120 m_ifa_first = nullptr;
121 }
122 m_ifa_current = nullptr;
123}
124
125inline bool
126CNetadapter_platform::is_valid_if(const ifaddrs* a_ifa) const noexcept {
127 // Accept IFF_LOOPBACK or up AF_INET6/AF_INET interfaces with address
128 // (e.g. not bonded) and that support MULTICAST.
129 if (a_ifa == nullptr || a_ifa->ifa_addr == nullptr)
130 return false;
131
132 if (a_ifa->ifa_flags & IFF_LOOPBACK &&
133 (a_ifa->ifa_addr->sa_family == AF_INET6 ||
134 a_ifa->ifa_addr->sa_family == AF_INET))
135 return true;
136
137 if ((a_ifa->ifa_addr->sa_family == AF_INET6 ||
138 a_ifa->ifa_addr->sa_family == AF_INET) &&
139 a_ifa->ifa_flags & IFF_UP && a_ifa->ifa_flags & IFF_MULTICAST)
140 return true;
141
142 return false;
143}
144
146 TRACE2(this, " Executing CNetadapter_platform::reset()")
147 m_ifa_current = nullptr;
148 // m_ifa_first is not necessary a valid entry. I have to look for the first
149 // valid entry.
150 for (ifaddrs* ifa_current = m_ifa_first; ifa_current != nullptr;
151 ifa_current = ifa_current->ifa_next) {
152 if (is_valid_if(ifa_current)) {
153 m_ifa_current = ifa_current;
154 break; // Does not increment ifa_current
155 }
156 }
157}
158
159} // namespace UPnPsdk
Manage information from Unix like platforms about network adapters.
void sockaddr(SSockaddr &a_saddr) const override
Get socket address from current selected list entry.
void socknetmask(SSockaddr &a_snetmask) const override
Get socket address netmask from current selected list entry.
void reset() noexcept override
Reset pointer and point to the first entry of the local network adapter list if available.
bool get_next() override
Select next entry from the network adapter list that was initial loaded with get_first().
std::string name() const override
Get network adapter name from current selected list entry.
unsigned int bitmask() const override
Get prefix length from the ip address of the current selected local network adapter.
void get_first() override
Load a list of network adapters from the operating system and select its first entry.
unsigned int index() const override
Get index number from current selected list entry.
uint8_t netmask_to_bitmask(const ::sockaddr_storage *a_netmask)
Get prefix bit number from a network address mask.
Reengineered Object Oriented UPnP+ program code.
Manage information about network adapters.
Trivial ::sockaddr structures enhanced with methods.
Definition sockaddr.hpp:94
Define macro for synced logging to the console for detailed info and debug.