1//
2// NetworkInterface.cpp
3//
4// Library: Net
5// Package: NetCore
6// Module: NetworkInterface
7//
8// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/Net/NetworkInterface.h"
16
17
18#ifdef POCO_NET_HAS_INTERFACE
19
20
21#include "Poco/Net/DatagramSocket.h"
22#include "Poco/Net/NetException.h"
23#include "Poco/NumberFormatter.h"
24#include "Poco/NumberParser.h"
25#include "Poco/StringTokenizer.h"
26#include "Poco/RefCountedObject.h"
27#include "Poco/Format.h"
28#if defined(POCO_OS_FAMILY_WINDOWS)
29 #include "Poco/Platform_WIN32_OSVER.h"
30 #include "Poco/UnicodeConverter.h"
31 #include "Poco/Error.h"
32 #include <wincrypt.h>
33 #include <iphlpapi.h>
34 #include <ipifcons.h>
35#endif
36#include <cstring>
37#include <fstream>
38#include <iostream>
39#include <iomanip>
40
41
42using Poco::NumberFormatter;
43using Poco::FastMutex;
44using Poco::format;
45
46
47std::ostream& operator << (std::ostream& os, const Poco::Net::NetworkInterface::MACAddress& mac)
48{
49 std::ios state(0);
50 state.copyfmt(os);
51 for (unsigned i = 0; i < mac.size(); ++i)
52 {
53 if (i > 0) os << Poco::Net::NetworkInterface::MAC_SEPARATOR;
54 os << std::hex << std::setw(2) << std::setfill('0') << (unsigned) mac[i];
55 }
56 os.copyfmt(state);
57 return os;
58}
59
60
61namespace Poco {
62namespace Net {
63
64
65//
66// NetworkInterfaceImpl
67//
68
69class NetworkInterfaceImpl: public Poco::RefCountedObject
70{
71public:
72 typedef NetworkInterface::AddressTuple AddressTuple;
73 typedef NetworkInterface::AddressList AddressList;
74 typedef NetworkInterface::Type Type;
75
76 NetworkInterfaceImpl(unsigned index);
77 NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, const IPAddress& address, unsigned index, NetworkInterface::MACAddress* pMACAddress = 0);
78 NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const std::string& adapterName, unsigned index = 0, NetworkInterface::MACAddress* pMACAddress = 0);
79 NetworkInterfaceImpl(const std::string& name,
80 const std::string& displayName,
81 const std::string& adapterName,
82 const IPAddress& address,
83 const IPAddress& subnetMask,
84 const IPAddress& broadcastAddress,
85 unsigned index,
86 NetworkInterface::MACAddress* pMACAddress = 0);
87
88 unsigned index() const;
89 const std::string& name() const;
90 const std::string& displayName() const;
91 const std::string& adapterName() const;
92 const IPAddress& firstAddress(IPAddress::Family family) const;
93 void addAddress(const AddressTuple& address);
94 const IPAddress& address(unsigned index) const;
95 const NetworkInterface::AddressList& addressList() const;
96 bool hasAddress(const IPAddress& address) const;
97 const IPAddress& subnetMask(unsigned index) const;
98 const IPAddress& broadcastAddress(unsigned index) const;
99 const IPAddress& destAddress(unsigned index) const;
100 const NetworkInterface::MACAddress& macAddress() const;
101 bool supportsIPv4() const;
102 bool supportsIPv6() const;
103
104 void setName(const std::string& name);
105 void setDisplayName(const std::string& name);
106 void setAdapterName(const std::string& name);
107 void addAddress(const IPAddress& addr);
108 void setMACAddress(const NetworkInterface::MACAddress& addr);
109 void setMACAddress(const void *addr, std::size_t len);
110
111 unsigned mtu() const;
112 unsigned ifindex() const;
113 Type type() const;
114
115 bool broadcast() const;
116 bool loopback() const;
117 bool multicast() const;
118 bool pointToPoint() const;
119 bool running() const;
120 bool up() const;
121
122#if defined(POCO_OS_FAMILY_WINDOWS)
123 void setFlags(DWORD flags, DWORD iftype);
124 void setRunning(bool running);
125#else
126 void setFlags(short flags);
127#endif
128
129 void setUp(bool up);
130 void setMTU(unsigned mtu);
131 void setType(Type type);
132 void setIndex(unsigned index);
133 void setPhyParams();
134
135protected:
136 ~NetworkInterfaceImpl();
137
138private:
139 std::string _name;
140 std::string _displayName;
141 std::string _adapterName;
142 AddressList _addressList;
143 unsigned _index;
144 bool _broadcast;
145 bool _loopback;
146 bool _multicast;
147 bool _pointToPoint;
148 bool _up;
149 bool _running;
150 unsigned _mtu;
151 Type _type;
152
153 NetworkInterface::MACAddress _macAddress;
154
155 friend class NetworkInterface;
156};
157
158
159NetworkInterfaceImpl::NetworkInterfaceImpl(unsigned index):
160 _index(index),
161 _broadcast(false),
162 _loopback(false),
163 _multicast(false),
164 _pointToPoint(false),
165 _up(false),
166 _running(false),
167 _mtu(0),
168 _type(NetworkInterface::NI_TYPE_OTHER)
169{
170}
171
172
173NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name,
174 const std::string& displayName,
175 const std::string& adapterName,
176 const IPAddress& address,
177 unsigned index,
178 NetworkInterface::MACAddress* pMACAddress): _name(name),
179 _displayName(displayName),
180 _adapterName(adapterName),
181 _index(index),
182 _broadcast(false),
183 _loopback(false),
184 _multicast(false),
185 _pointToPoint(false),
186 _up(false),
187 _running(false),
188 _mtu(0),
189 _type(NetworkInterface::NI_TYPE_OTHER)
190{
191 _addressList.push_back(AddressTuple(address, IPAddress(), IPAddress()));
192 setPhyParams();
193 if (pMACAddress) setMACAddress(*pMACAddress);
194}
195
196
197NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name,
198 const std::string& displayName,
199 const std::string& adapterName,
200 unsigned index,
201 NetworkInterface::MACAddress* pMACAddress): _name(name),
202 _displayName(displayName),
203 _adapterName(adapterName),
204 _index(index),
205 _broadcast(false),
206 _loopback(false),
207 _multicast(false),
208 _pointToPoint(false),
209 _up(false),
210 _running(false),
211 _mtu(0),
212 _type(NetworkInterface::NI_TYPE_OTHER)
213{
214 setPhyParams();
215 if (pMACAddress) setMACAddress(*pMACAddress);
216}
217
218
219NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name,
220 const std::string& displayName,
221 const std::string& adapterName,
222 const IPAddress& address,
223 const IPAddress& subnetMask,
224 const IPAddress& broadcastAddress,
225 unsigned index,
226 NetworkInterface::MACAddress* pMACAddress): _name(name),
227 _displayName(displayName),
228 _adapterName(adapterName),
229 _index(index),
230 _broadcast(false),
231 _loopback(false),
232 _multicast(false),
233 _pointToPoint(false),
234 _up(false),
235 _running(false),
236 _mtu(0),
237 _type(NetworkInterface::NI_TYPE_OTHER)
238{
239 _addressList.push_back(AddressTuple(address, subnetMask, broadcastAddress));
240 setPhyParams();
241 if (pMACAddress) setMACAddress(*pMACAddress);
242}
243
244
245void NetworkInterfaceImpl::setPhyParams()
246{
247#if !defined(POCO_OS_FAMILY_WINDOWS) && !defined(POCO_VXWORKS)
248 struct ifreq ifr;
249 std::strncpy(ifr.ifr_name, _name.c_str(), IFNAMSIZ);
250 DatagramSocket ds(SocketAddress::IPv4);
251
252 ds.impl()->ioctl(SIOCGIFFLAGS, &ifr);
253 setFlags(ifr.ifr_flags);
254
255 ds.impl()->ioctl(SIOCGIFMTU, &ifr);
256 setMTU(ifr.ifr_mtu);
257#endif
258}
259
260
261NetworkInterfaceImpl::~NetworkInterfaceImpl()
262{
263}
264
265
266bool NetworkInterfaceImpl::supportsIPv4() const
267{
268 AddressList::const_iterator it = _addressList.begin();
269 AddressList::const_iterator end = _addressList.end();
270 for (; it != end; ++it)
271 {
272 if (IPAddress::IPv4 == it->get<NetworkInterface::IP_ADDRESS>().family())
273 return true;
274 }
275
276 return false;
277}
278
279
280bool NetworkInterfaceImpl::supportsIPv6() const
281{
282#ifdef POCO_HAVE_IPv6
283 AddressList::const_iterator it = _addressList.begin();
284 AddressList::const_iterator end = _addressList.end();
285 for (; it != end; ++it)
286 {
287 if (IPAddress::IPv6 == it->get<NetworkInterface::IP_ADDRESS>().family())
288 return true;
289 }
290#endif
291 return false;
292}
293
294
295inline unsigned NetworkInterfaceImpl::index() const
296{
297 return _index;
298}
299
300
301inline const std::string& NetworkInterfaceImpl::name() const
302{
303 return _name;
304}
305
306
307inline const std::string& NetworkInterfaceImpl::displayName() const
308{
309 return _displayName;
310}
311
312
313inline const std::string& NetworkInterfaceImpl::adapterName() const
314{
315 return _adapterName;
316}
317
318
319const IPAddress& NetworkInterfaceImpl::firstAddress(IPAddress::Family family) const
320{
321 AddressList::const_iterator it = _addressList.begin();
322 AddressList::const_iterator end = _addressList.end();
323 for (;it != end; ++it)
324 {
325 const IPAddress& addr = it->get<NetworkInterface::IP_ADDRESS>();
326 if (addr.family() == family) return addr;
327 }
328
329 throw NotFoundException(format("%s family address not found.",
330 (family == IPAddress::IPv4) ? std::string("IPv4") : std::string("IPv6")));
331}
332
333
334inline void NetworkInterfaceImpl::addAddress(const AddressTuple& address)
335{
336 _addressList.push_back(address);
337}
338
339
340bool NetworkInterfaceImpl::hasAddress(const IPAddress& address) const
341{
342 NetworkInterface::ConstAddressIterator it = _addressList.begin();
343 NetworkInterface::ConstAddressIterator end = _addressList.end();
344 for (; it != end; ++it)
345 {
346 if (it->get<NetworkInterface::IP_ADDRESS>() == address)
347 return true;
348 }
349 return false;
350}
351
352
353inline const IPAddress& NetworkInterfaceImpl::address(unsigned index) const
354{
355 if (index < _addressList.size()) return _addressList[index].get<NetworkInterface::IP_ADDRESS>();
356 else throw NotFoundException(Poco::format("No address with index %u.", index));
357}
358
359
360inline const NetworkInterface::AddressList& NetworkInterfaceImpl::addressList() const
361{
362 return _addressList;
363}
364
365
366const IPAddress& NetworkInterfaceImpl::subnetMask(unsigned index) const
367{
368 if (index < _addressList.size())
369 return _addressList[index].get<NetworkInterface::SUBNET_MASK>();
370
371 throw NotFoundException(Poco::format("No subnet mask with index %u.", index));
372}
373
374
375const IPAddress& NetworkInterfaceImpl::broadcastAddress(unsigned index) const
376{
377 if (index < _addressList.size())
378 return _addressList[index].get<NetworkInterface::BROADCAST_ADDRESS>();
379
380 throw NotFoundException(Poco::format("No subnet mask with index %u.", index));
381}
382
383
384const IPAddress& NetworkInterfaceImpl::destAddress(unsigned index) const
385{
386 if (!pointToPoint())
387 throw InvalidAccessException("Only PPP addresses have destination address.");
388 else if (index < _addressList.size())
389 return _addressList[index].get<NetworkInterface::BROADCAST_ADDRESS>();
390
391 throw NotFoundException(Poco::format("No address with index %u.", index));
392}
393
394
395const NetworkInterface::MACAddress& NetworkInterfaceImpl::macAddress() const
396{
397 return _macAddress;
398}
399
400
401inline unsigned NetworkInterfaceImpl::mtu() const
402{
403 return _mtu;
404}
405
406
407inline NetworkInterface::Type NetworkInterfaceImpl::type() const
408{
409 return _type;
410}
411
412
413inline bool NetworkInterfaceImpl::broadcast() const
414{
415 return _broadcast;
416}
417
418
419inline bool NetworkInterfaceImpl::loopback() const
420{
421 return _loopback;
422}
423
424
425inline bool NetworkInterfaceImpl::multicast() const
426{
427 return _multicast;
428}
429
430
431inline bool NetworkInterfaceImpl::pointToPoint() const
432{
433 return _pointToPoint;
434}
435
436
437inline bool NetworkInterfaceImpl::running() const
438{
439 return _running;
440}
441
442
443inline bool NetworkInterfaceImpl::up() const
444{
445 return _up;
446}
447
448
449#if defined(POCO_OS_FAMILY_WINDOWS)
450
451
452void NetworkInterfaceImpl::setFlags(DWORD flags, DWORD iftype)
453{
454 _running = _up = false;
455 switch (iftype) {
456 case IF_TYPE_ETHERNET_CSMACD:
457 case IF_TYPE_ISO88025_TOKENRING:
458 case IF_TYPE_IEEE80211:
459 _multicast = _broadcast = true;
460 break;
461 case IF_TYPE_SOFTWARE_LOOPBACK:
462 _loopback = true;
463 break;
464 case IF_TYPE_PPP:
465 case IF_TYPE_ATM:
466 case IF_TYPE_TUNNEL:
467 case IF_TYPE_IEEE1394:
468 _pointToPoint = true;
469 break;
470 }
471 if (!(flags & IP_ADAPTER_NO_MULTICAST))
472 _multicast = true;
473}
474
475
476void NetworkInterfaceImpl::setRunning(bool running)
477{
478 _running = running;
479}
480
481
482#else
483
484
485void NetworkInterfaceImpl::setFlags(short flags)
486{
487#ifdef POCO_OS_FAMILY_UNIX
488 _broadcast = ((flags & IFF_BROADCAST) != 0);
489 _loopback = ((flags & IFF_LOOPBACK) != 0);
490 _multicast = ((flags & IFF_MULTICAST) != 0);
491 _pointToPoint = ((flags & IFF_POINTOPOINT) != 0);
492 _running = ((flags & IFF_RUNNING) != 0);
493 _up = ((flags & IFF_UP) != 0);
494#endif
495}
496
497
498#endif
499
500
501inline void NetworkInterfaceImpl::setUp(bool up)
502{
503 _up = up;
504}
505
506
507inline void NetworkInterfaceImpl::setMTU(unsigned mtu)
508{
509 _mtu = mtu;
510}
511
512
513inline void NetworkInterfaceImpl::setType(Type type)
514{
515 _type = type;
516}
517
518
519inline void NetworkInterfaceImpl::setIndex(unsigned index)
520{
521 _index = index;
522}
523
524
525inline void NetworkInterfaceImpl::setName(const std::string& name)
526{
527 _name = name;
528}
529
530
531inline void NetworkInterfaceImpl::setDisplayName(const std::string& name)
532{
533 _displayName = name;
534}
535
536
537inline void NetworkInterfaceImpl::setAdapterName(const std::string& name)
538{
539 _adapterName = name;
540}
541
542
543inline void NetworkInterfaceImpl::addAddress(const IPAddress& addr)
544{
545 _addressList.push_back(addr);
546}
547
548
549inline void NetworkInterfaceImpl::setMACAddress(const NetworkInterface::MACAddress& addr)
550{
551 _macAddress = addr;
552}
553
554
555inline void NetworkInterfaceImpl::setMACAddress(const void *addr, std::size_t len)
556{
557 _macAddress.clear();
558 _macAddress.insert(_macAddress.end(), static_cast<const unsigned char*>(addr), static_cast<const unsigned char*>(addr) + len);
559}
560
561
562//
563// NetworkInterface
564//
565
566
567FastMutex NetworkInterface::_mutex;
568
569
570NetworkInterface::NetworkInterface(unsigned index):
571 _pImpl(new NetworkInterfaceImpl(index))
572{
573}
574
575
576NetworkInterface::NetworkInterface(const NetworkInterface& interfc):
577 _pImpl(interfc._pImpl)
578{
579 _pImpl->duplicate();
580}
581
582
583NetworkInterface::NetworkInterface(const std::string& name, const std::string& displayName, const std::string& adapterName, const IPAddress& address, unsigned index, MACAddress* pMACAddress):
584 _pImpl(new NetworkInterfaceImpl(name, displayName, adapterName, address, index, pMACAddress))
585{
586}
587
588
589NetworkInterface::NetworkInterface(const std::string& name, const std::string& displayName, const std::string& adapterName, unsigned index, MACAddress* pMACAddress):
590 _pImpl(new NetworkInterfaceImpl(name, displayName, adapterName, index, pMACAddress))
591{
592}
593
594
595NetworkInterface::NetworkInterface(const std::string& name, const IPAddress& address, unsigned index, MACAddress* pMACAddress):
596 _pImpl(new NetworkInterfaceImpl(name, name, name, address, index, pMACAddress))
597{
598}
599
600
601NetworkInterface::NetworkInterface(const std::string& name,
602 const std::string& displayName,
603 const std::string& adapterName,
604 const IPAddress& address,
605 const IPAddress& subnetMask,
606 const IPAddress& broadcastAddress,
607 unsigned index,
608 MACAddress* pMACAddress):
609 _pImpl(new NetworkInterfaceImpl(name, displayName, adapterName, address, subnetMask, broadcastAddress, index, pMACAddress))
610{
611}
612
613
614NetworkInterface::NetworkInterface(const std::string& name,
615 const IPAddress& address,
616 const IPAddress& subnetMask,
617 const IPAddress& broadcastAddress,
618 unsigned index,
619 MACAddress* pMACAddress):
620 _pImpl(new NetworkInterfaceImpl(name, name, name, address, subnetMask, broadcastAddress, index, pMACAddress))
621{
622}
623
624
625NetworkInterface::~NetworkInterface()
626{
627 _pImpl->release();
628}
629
630
631NetworkInterface& NetworkInterface::operator = (const NetworkInterface& interfc)
632{
633 NetworkInterface tmp(interfc);
634 swap(tmp);
635 return *this;
636}
637
638
639void NetworkInterface::swap(NetworkInterface& other)
640{
641 using std::swap;
642 swap(_pImpl, other._pImpl);
643}
644
645
646unsigned NetworkInterface::index() const
647{
648 return _pImpl->index();
649}
650
651
652const std::string& NetworkInterface::name() const
653{
654 return _pImpl->name();
655}
656
657
658const std::string& NetworkInterface::displayName() const
659{
660 return _pImpl->displayName();
661}
662
663
664const std::string& NetworkInterface::adapterName() const
665{
666 return _pImpl->adapterName();
667}
668
669
670const IPAddress& NetworkInterface::firstAddress(IPAddress::Family family) const
671{
672 return _pImpl->firstAddress(family);
673}
674
675
676void NetworkInterface::firstAddress(IPAddress& addr, IPAddress::Family family) const
677{
678 try
679 {
680 addr = firstAddress(family);
681 }
682 catch (NotFoundException&)
683 {
684 addr = IPAddress(family);
685 }
686}
687
688
689void NetworkInterface::addAddress(const IPAddress& address)
690{
691 _pImpl->addAddress(AddressTuple(address, IPAddress(), IPAddress()));
692}
693
694
695void NetworkInterface::addAddress(const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress)
696{
697 _pImpl->addAddress(AddressTuple(address, subnetMask, broadcastAddress));
698}
699
700
701const IPAddress& NetworkInterface::address(unsigned index) const
702{
703 return _pImpl->address(index);
704}
705
706
707const NetworkInterface::AddressList& NetworkInterface::addressList() const
708{
709 return _pImpl->addressList();
710}
711
712
713const IPAddress& NetworkInterface::subnetMask(unsigned index) const
714{
715 return _pImpl->subnetMask(index);
716}
717
718
719const IPAddress& NetworkInterface::broadcastAddress(unsigned index) const
720{
721 return _pImpl->broadcastAddress(index);
722}
723
724
725const NetworkInterface::MACAddress& NetworkInterface::macAddress() const
726{
727 return _pImpl->macAddress();
728}
729
730
731const IPAddress& NetworkInterface::destAddress(unsigned index) const
732{
733 return _pImpl->destAddress(index);
734}
735
736
737unsigned NetworkInterface::mtu() const
738{
739 return _pImpl->mtu();
740}
741
742
743NetworkInterface::Type NetworkInterface::type() const
744{
745 return _pImpl->type();
746}
747
748
749bool NetworkInterface::supportsIP() const
750{
751 return _pImpl->supportsIPv4() || _pImpl->supportsIPv6();
752}
753
754
755bool NetworkInterface::supportsIPv4() const
756{
757 return _pImpl->supportsIPv4();
758}
759
760
761bool NetworkInterface::supportsIPv6() const
762{
763 return _pImpl->supportsIPv6();
764}
765
766
767bool NetworkInterface::supportsBroadcast() const
768{
769 return _pImpl->broadcast();
770}
771
772
773bool NetworkInterface::supportsMulticast() const
774{
775 return _pImpl->multicast();
776}
777
778
779bool NetworkInterface::isLoopback() const
780{
781 return _pImpl->loopback();
782}
783
784
785bool NetworkInterface::isPointToPoint() const
786{
787 return _pImpl->pointToPoint();
788}
789
790
791bool NetworkInterface::isRunning() const
792{
793 return _pImpl->running();
794}
795
796
797bool NetworkInterface::isUp() const
798{
799 return _pImpl->up();
800}
801
802
803NetworkInterface NetworkInterface::forName(const std::string& name, bool requireIPv6)
804{
805 if (requireIPv6)
806 return forName(name, IPv6_ONLY);
807 else
808 return forName(name, IPv4_OR_IPv6);
809}
810
811
812NetworkInterface NetworkInterface::forName(const std::string& name, IPVersion ipVersion)
813{
814 Map map = NetworkInterface::map(false, false);
815 Map::const_iterator it = map.begin();
816 Map::const_iterator end = map.end();
817
818 for (; it != end; ++it)
819 {
820 if (it->second.name() == name)
821 {
822 if (ipVersion == IPv4_ONLY && it->second.supportsIPv4())
823 return it->second;
824 else if (ipVersion == IPv6_ONLY && it->second.supportsIPv6())
825 return it->second;
826 else if (ipVersion == IPv4_OR_IPv6)
827 return it->second;
828 }
829 }
830 throw InterfaceNotFoundException(name);
831}
832
833
834NetworkInterface NetworkInterface::forAddress(const IPAddress& addr)
835{
836 Map map = NetworkInterface::map(true, false);
837 Map::const_iterator it = map.begin();
838 Map::const_iterator end = map.end();
839
840 for (; it != end; ++it)
841 {
842 const std::size_t count = it->second.addressList().size();
843 for (int i = 0; i < count; ++i)
844 {
845 if (it->second.address(i) == addr)
846 return it->second;
847 }
848 }
849 throw InterfaceNotFoundException(addr.toString());
850}
851
852
853NetworkInterface NetworkInterface::forIndex(unsigned i)
854{
855 if (i != NetworkInterface::NO_INDEX)
856 {
857 Map map = NetworkInterface::map(false, false);
858 Map::const_iterator it = map.find(i);
859 if (it != map.end())
860 return it->second;
861 else
862 throw InterfaceNotFoundException("#" + NumberFormatter::format(i));
863 }
864 throw InterfaceNotFoundException("#" + NumberFormatter::format(i));
865}
866
867
868std::string NetworkInterface::toString(const MACAddress& addr)
869{
870 std::string ret;
871 if(addr.size() >= 6)
872 {
873 ret = Poco::format("%02x:%02x:%02x:%02x:%02x:%02x",
874 static_cast<unsigned>(addr[0]),
875 static_cast<unsigned>(addr[1]),
876 static_cast<unsigned>(addr[2]),
877 static_cast<unsigned>(addr[3]),
878 static_cast<unsigned>(addr[4]),
879 static_cast<unsigned>(addr[5]));
880 }
881 return ret;
882}
883
884
885NetworkInterface::List NetworkInterface::list(bool ipOnly, bool upOnly)
886{
887 List list;
888 Map m = map(ipOnly, upOnly);
889 NetworkInterface::Map::const_iterator it = m.begin();
890 NetworkInterface::Map::const_iterator end = m.end();
891 for (; it != end; ++it)
892 {
893 int index = it->second.index();
894 std::string name = it->second.name();
895 std::string displayName = it->second.displayName();
896 std::string adapterName = it->second.adapterName();
897 NetworkInterface::MACAddress mac = it->second.macAddress();
898
899 typedef NetworkInterface::AddressList AddrList;
900 const AddrList& ipList = it->second.addressList();
901 if (ipList.size() > 0)
902 {
903 AddrList::const_iterator ipIt = ipList.begin();
904 AddrList::const_iterator ipEnd = ipList.end();
905 for(; ipIt != ipEnd; ++ipIt)
906 {
907 IPAddress addr = ipIt->get<NetworkInterface::IP_ADDRESS>();
908 IPAddress mask = ipIt->get<NetworkInterface::SUBNET_MASK>();
909 NetworkInterface ni;
910 if(mask.isWildcard())
911 {
912 ni = NetworkInterface(name, displayName, adapterName, addr, index, &mac);
913 }
914 else
915 {
916 IPAddress broadcast = ipIt->get<NetworkInterface::BROADCAST_ADDRESS>();
917 ni = NetworkInterface(name, displayName, adapterName, addr, mask, broadcast, index, &mac);
918 }
919
920 ni._pImpl->_broadcast = it->second._pImpl->_broadcast;
921 ni._pImpl->_loopback = it->second._pImpl->_loopback;
922 ni._pImpl->_multicast = it->second._pImpl->_multicast;
923 ni._pImpl->_pointToPoint = it->second._pImpl->_pointToPoint;
924 ni._pImpl->_up = it->second._pImpl->_up;
925 ni._pImpl->_running = it->second._pImpl->_running;
926 ni._pImpl->_mtu = it->second._pImpl->_mtu;
927 ni._pImpl->_type = it->second._pImpl->_type;
928
929 list.push_back(ni);
930 }
931 }
932 else
933 {
934 list.push_back(NetworkInterface(name, displayName, adapterName, index, &mac));
935 }
936 }
937
938 return list;
939}
940
941
942} } // namespace Poco::Net
943
944
945//
946// platform-specific code below
947//
948
949
950#if defined(POCO_OS_FAMILY_WINDOWS)
951//
952// Windows
953//
954
955
956#include "Poco/Buffer.h"
957#include <iterator>
958
959
960namespace Poco {
961namespace Net {
962
963
964namespace {
965
966
967IPAddress getBroadcastAddress(PIP_ADAPTER_PREFIX pPrefix, const IPAddress& addr, ULONG* pprefix = 0)
968 /// This function relies on (1) subnet prefix being at the position
969 /// immediately preceding and (2) broadcast address being at the position
970 /// immediately succeeding the IPv4 unicast address.
971 ///
972 /// Since there is no explicit guarantee on order, to ensure correctness,
973 /// the above constraints are checked prior to returning the result.
974 /// Additionally, on pre-Vista versions on Windows, the main structure does
975 /// not contain prefix length; for those platforms, this function
976 /// returns prefix through pprefix argument.
977{
978 PIP_ADAPTER_PREFIX pPrev = 0;
979 for (int i = 0; pPrefix; pPrefix = pPrefix->Next, ++i)
980 {
981 ADDRESS_FAMILY family = pPrefix->Address.lpSockaddr->sa_family;
982 if ((family == AF_INET) && (addr == IPAddress(pPrefix->Address)))
983 break;
984 pPrev = pPrefix;
985 }
986
987 if (pPrefix && pPrefix->Next && pPrev)
988 {
989 IPAddress ipPrefix(pPrev->PrefixLength, IPAddress::IPv4);
990 IPAddress mask(pPrefix->Next->Address);
991 if ((ipPrefix & mask) == (ipPrefix & addr))
992 {
993 if (pprefix) *pprefix = pPrefix->PrefixLength;
994 return IPAddress(pPrefix->Next->Address);
995 }
996 }
997
998 return IPAddress(IPAddress::IPv4);
999}
1000
1001
1002NetworkInterface::Type fromNative(DWORD type)
1003{
1004 switch (type)
1005 {
1006 case IF_TYPE_ETHERNET_CSMACD: return NetworkInterface::NI_TYPE_ETHERNET_CSMACD;
1007 case IF_TYPE_ISO88025_TOKENRING: return NetworkInterface::NI_TYPE_ISO88025_TOKENRING;
1008 case IF_TYPE_FRAMERELAY: return NetworkInterface::NI_TYPE_FRAMERELAY;
1009 case IF_TYPE_PPP: return NetworkInterface::NI_TYPE_PPP;
1010 case IF_TYPE_SOFTWARE_LOOPBACK: return NetworkInterface::NI_TYPE_SOFTWARE_LOOPBACK;
1011 case IF_TYPE_ATM: return NetworkInterface::NI_TYPE_ATM;
1012 case IF_TYPE_IEEE80211: return NetworkInterface::NI_TYPE_IEEE80211;
1013 case IF_TYPE_TUNNEL: return NetworkInterface::NI_TYPE_TUNNEL;
1014 case IF_TYPE_IEEE1394: return NetworkInterface::NI_TYPE_IEEE1394;
1015 default: return NetworkInterface::NI_TYPE_OTHER;
1016 }
1017}
1018
1019
1020IPAddress subnetMaskForInterface(const std::string& name, bool isLoopback)
1021{
1022 if (isLoopback)
1023 {
1024 return IPAddress::parse("255.0.0.0");
1025 }
1026 else
1027 {
1028#if !defined(_WIN32_WCE)
1029 std::string subKey("SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces\\");
1030 subKey += name;
1031 std::string netmask;
1032 HKEY hKey;
1033#if !defined(POCO_NO_WSTRING)
1034 std::wstring usubKey;
1035 Poco::UnicodeConverter::toUTF16(subKey, usubKey);
1036 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, usubKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
1037 return IPAddress();
1038 wchar_t unetmask[16];
1039 DWORD size = sizeof(unetmask);
1040 if (RegQueryValueExW(hKey, L"DhcpSubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS)
1041 {
1042 if (RegQueryValueExW(hKey, L"SubnetMask", NULL, NULL, (LPBYTE)&unetmask, &size) != ERROR_SUCCESS)
1043 {
1044 RegCloseKey(hKey);
1045 return IPAddress();
1046 }
1047 }
1048 Poco::UnicodeConverter::toUTF8(unetmask, netmask);
1049#endif
1050 RegCloseKey(hKey);
1051 return IPAddress::parse(netmask);
1052#else
1053 return IPAddress();
1054#endif // !defined(_WIN32_WCE)
1055 }
1056}
1057
1058
1059} /// namespace
1060
1061
1062NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
1063{
1064 OSVERSIONINFO osvi;
1065 ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
1066 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
1067 GetVersionEx(&osvi);
1068
1069 FastMutex::ScopedLock lock(_mutex);
1070 Map result;
1071 ULONG outBufLen = 16384;
1072 Poco::Buffer<UCHAR> memory(outBufLen);
1073 ULONG flags = (GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_PREFIX);
1074#ifdef GAA_FLAG_INCLUDE_ALL_INTERFACES
1075 flags |= GAA_FLAG_INCLUDE_ALL_INTERFACES;
1076#endif
1077#if defined(POCO_HAVE_IPv6)
1078 const unsigned family = AF_UNSPEC; //IPv4 and IPv6
1079#else
1080 const unsigned family = AF_INET; //IPv4 only
1081#endif
1082 DWORD dwRetVal = 0;
1083 ULONG iterations = 0;
1084 PIP_ADAPTER_ADDRESSES pAddress = 0;
1085 do
1086 {
1087 pAddress = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(memory.begin()); // leave in the loop, begin may change after resize
1088 poco_assert (memory.capacity() >= outBufLen);
1089 if (ERROR_BUFFER_OVERFLOW == (dwRetVal = GetAdaptersAddresses(family, flags, 0, pAddress, &outBufLen)))
1090 memory.resize(outBufLen, false); // adjust size and try again
1091 else if (ERROR_NO_DATA == dwRetVal) // no network interfaces found
1092 return result;
1093 else if (NO_ERROR != dwRetVal) // error occurred
1094 throw SystemException(format("An error occurred while trying to obtain list of network interfaces: [%s]",
1095 Error::getMessage(dwRetVal)));
1096 else
1097 break;
1098 }
1099 while ((ERROR_BUFFER_OVERFLOW == dwRetVal) && (++iterations <= 2));
1100
1101 poco_assert (NO_ERROR == dwRetVal);
1102 for (; pAddress; pAddress = pAddress->Next)
1103 {
1104 IPAddress address;
1105 IPAddress subnetMask;
1106 IPAddress broadcastAddress;
1107 unsigned ifIndex = 0;
1108
1109#if defined(POCO_HAVE_IPv6)
1110 #if defined(_WIN32_WCE)
1111 ifIndex = pAddress->Ipv6IfIndex;
1112 #elif (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) // Win XP SP1
1113 #if defined (IP_ADAPTER_IPV6_ENABLED) // Vista
1114 if(osvi.dwMajorVersion>=6)//vista
1115 {
1116 if ((pAddress->Flags & IP_ADAPTER_IPV6_ENABLED) &&
1117 (osvi.dwMajorVersion >= 5) &&
1118 (osvi.dwMinorVersion >= 1) &&
1119 (osvi.dwBuildNumber >=1))
1120 {
1121 ifIndex = pAddress->Ipv6IfIndex;
1122 }
1123 }
1124 else
1125 {
1126 if ((osvi.dwMajorVersion >= 5) &&
1127 (osvi.dwMinorVersion >= 1) &&
1128 (osvi.dwBuildNumber >= 1))
1129 {
1130 ifIndex = pAddress->Ipv6IfIndex;
1131 }
1132 }
1133 #else // !defined(IP_ADAPTER_IPV6_ENABLED)
1134 if ((osvi.dwMajorVersion >= 5) &&
1135 (osvi.dwMinorVersion >= 1) &&
1136 (osvi.dwBuildNumber >= 1))
1137 {
1138 ifIndex = pAddress->Ipv6IfIndex;
1139 }
1140 #endif // defined(IP_ADAPTER_IPV6_ENABLED)
1141 #endif // (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100)
1142#endif // POCO_HAVE_IPv6
1143
1144#if defined (IP_ADAPTER_IPV4_ENABLED)
1145 if(osvi.dwMajorVersion>=6)
1146 {//vista
1147 if (pAddress->Flags & IP_ADAPTER_IPV4_ENABLED)
1148 {
1149 ifIndex = pAddress->IfIndex;
1150 }
1151 }
1152 else
1153 {
1154 ifIndex = pAddress->IfIndex;
1155 }
1156#else // !IP_ADAPTER_IPV4_ENABLED
1157 ifIndex = pAddress->IfIndex;
1158#endif
1159 if (ifIndex == 0) continue;
1160
1161 std::string name;
1162 std::string displayName;
1163 std::string adapterName(pAddress->AdapterName);
1164 Poco::UnicodeConverter::toUTF8(pAddress->FriendlyName, name);
1165 Poco::UnicodeConverter::toUTF8(pAddress->Description, displayName);
1166
1167 bool isUp = (pAddress->OperStatus == IfOperStatusUp);
1168 bool isIP = (0 != pAddress->FirstUnicastAddress);
1169 if (((ipOnly && isIP) || !ipOnly) && ((upOnly && isUp) || !upOnly))
1170 {
1171 NetworkInterface ni(name, displayName, adapterName, ifIndex);
1172 // Create interface even if it has an empty list of addresses; also, set
1173 // physical attributes which are protocol independent (name, media type,
1174 // MAC address, MTU, operational status, etc).
1175 Map::iterator ifIt = result.find(ifIndex);
1176 if (ifIt == result.end())
1177 ifIt = result.insert(Map::value_type(ifIndex, ni)).first;
1178
1179 ifIt->second.impl().setFlags(pAddress->Flags, pAddress->IfType);
1180 ifIt->second.impl().setMTU(pAddress->Mtu);
1181 ifIt->second.impl().setUp(pAddress->OperStatus == IfOperStatusUp);
1182#if (_WIN32_WINNT >= 0x0600) // Vista and newer only
1183 if ((osvi.dwMajorVersion >= 6) &&
1184 (osvi.dwMinorVersion >= 0) &&
1185 (osvi.dwBuildNumber >= 0))
1186 {
1187 ifIt->second.impl().setRunning(pAddress->ReceiveLinkSpeed > 0 || pAddress->TransmitLinkSpeed > 0);
1188 }
1189#endif
1190 ifIt->second.impl().setType(fromNative(pAddress->IfType));
1191 if (pAddress->PhysicalAddressLength)
1192 ifIt->second.impl().setMACAddress(pAddress->PhysicalAddress, pAddress->PhysicalAddressLength);
1193
1194 for (PIP_ADAPTER_UNICAST_ADDRESS pUniAddr = pAddress->FirstUnicastAddress;
1195 pUniAddr;
1196 pUniAddr = pUniAddr->Next)
1197 {
1198 address = IPAddress(pUniAddr->Address);
1199 ADDRESS_FAMILY family2 = pUniAddr->Address.lpSockaddr->sa_family;
1200 switch (family2)
1201 {
1202 case AF_INET:
1203 {
1204 // Windows lists broadcast address on localhost
1205 bool hasBroadcast = (pAddress->IfType == IF_TYPE_ETHERNET_CSMACD) || (pAddress->IfType == IF_TYPE_SOFTWARE_LOOPBACK) || (pAddress->IfType == IF_TYPE_IEEE80211);
1206 if (hasBroadcast)
1207 {
1208 // On Windows, a valid broadcast address will be all 1's (== address | ~subnetMask); additionally, on pre-Vista versions of
1209 // OS, master address structure does not contain member for prefix length; we go an extra mile here in order to make sure
1210 // we reflect the actual values held by system and protect against misconfiguration (e.g. bad DHCP config entry)
1211 ULONG prefixLength = 0;
1212#if defined(_WIN32_WCE)
1213 #if _WIN32_WCE >= 0x0800
1214 prefixLength = pUniAddr->OnLinkPrefixLength;
1215 broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address);
1216 #else
1217 broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength);
1218 #endif
1219 // if previous call did not do it, make last-ditch attempt for prefix and broadcast
1220 if (prefixLength == 0 && pAddress->FirstPrefix)
1221 prefixLength = pAddress->FirstPrefix->PrefixLength;
1222 poco_assert (prefixLength <= 32);
1223 if (broadcastAddress.isWildcard())
1224 {
1225 IPAddress mask(static_cast<unsigned>(prefixLength), IPAddress::IPv4);
1226 IPAddress host(mask & address);
1227 broadcastAddress = host | ~mask;
1228 }
1229#elif (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100) // Win XP SP1
1230 #if (_WIN32_WINNT >= 0x0600) // Vista and newer
1231 if (osvi.dwMajorVersion >= 6)
1232 {
1233 prefixLength = pUniAddr->OnLinkPrefixLength;
1234 broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address);
1235 }
1236 else
1237 {
1238 broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength);
1239 }
1240 #else
1241 broadcastAddress = getBroadcastAddress(pAddress->FirstPrefix, address, &prefixLength);
1242 #endif
1243 poco_assert (prefixLength <= 32);
1244 if (broadcastAddress.isWildcard())
1245 {
1246 IPAddress mask(static_cast<unsigned>(prefixLength), IPAddress::IPv4);
1247 IPAddress host(mask & address);
1248 broadcastAddress = host | ~mask;
1249 }
1250#endif // (_WIN32_WINNT >= 0x0501) && (NTDDI_VERSION >= 0x05010100)
1251 if (prefixLength)
1252 {
1253 subnetMask = IPAddress(static_cast<unsigned>(prefixLength), IPAddress::IPv4);
1254 }
1255 else // if all of the above fails, look up the subnet mask in the registry
1256 {
1257 address = IPAddress(&reinterpret_cast<struct sockaddr_in*>(pUniAddr->Address.lpSockaddr)->sin_addr, sizeof(in_addr));
1258 subnetMask = subnetMaskForInterface(name, address.isLoopback());
1259 if (!address.isLoopback())
1260 {
1261 broadcastAddress = address;
1262 broadcastAddress.mask(subnetMask, IPAddress::broadcast());
1263 }
1264 }
1265 ifIt->second.addAddress(address, subnetMask, broadcastAddress);
1266 }
1267 else
1268 {
1269 ifIt->second.addAddress(address);
1270 }
1271 }
1272 break;
1273#if defined(POCO_HAVE_IPv6)
1274 case AF_INET6:
1275 ifIt->second.addAddress(address);
1276 break;
1277#endif
1278 } // switch family
1279 } // for addresses
1280 } // if ipOnly/upOnly
1281 } // for adapters
1282 return result;
1283}
1284
1285
1286} } // namespace Poco::Net
1287
1288
1289#elif defined(POCO_VXWORKS)
1290//
1291// VxWorks
1292//
1293
1294#error TODO
1295
1296/*
1297namespace Poco {
1298namespace Net {
1299
1300
1301NetworkInterface::NetworkInterfaceList NetworkInterface::list()
1302{
1303 FastMutex::ScopedLock lock(_mutex);
1304 NetworkInterfaceList result;
1305
1306 int ifIndex = 1;
1307 char ifName[32];
1308 char ifAddr[INET_ADDR_LEN];
1309
1310 for (;;)
1311 {
1312 if (ifIndexToIfName(ifIndex, ifName) == OK)
1313 {
1314 std::string name(ifName);
1315 IPAddress addr;
1316 IPAddress mask;
1317 IPAddress bcst;
1318 if (ifAddrGet(ifName, ifAddr) == OK)
1319 {
1320 addr = IPAddress(std::string(ifAddr));
1321 }
1322 int ifMask;
1323 if (ifMaskGet(ifName, &ifMask) == OK)
1324 {
1325 mask = IPAddress(&ifMask, sizeof(ifMask));
1326 }
1327 if (ifBroadcastGet(ifName, ifAddr) == OK)
1328 {
1329 bcst = IPAddress(std::string(ifAddr));
1330 }
1331 result.push_back(NetworkInterface(name, name, name, addr, mask, bcst));
1332 ifIndex++;
1333 }
1334 else break;
1335 }
1336
1337 return result;
1338}
1339
1340
1341} } // namespace Poco::Net
1342*/
1343
1344#elif defined(POCO_OS_FAMILY_BSD) || (POCO_OS == POCO_OS_QNX) || (POCO_OS == POCO_OS_SOLARIS)
1345//
1346// BSD variants, QNX(?) and Solaris
1347//
1348#include <sys/types.h>
1349#include <sys/socket.h>
1350#include <ifaddrs.h>
1351#include <net/if.h>
1352#include <net/if_dl.h>
1353#ifndef POCO_NO_NET_IFTYPES
1354#include <net/if_types.h>
1355#endif
1356
1357
1358namespace Poco {
1359namespace Net {
1360
1361
1362namespace {
1363
1364
1365NetworkInterface::Type fromNative(u_char nativeType)
1366{
1367 switch (nativeType)
1368 {
1369#ifndef POCO_NO_NET_IFTYPES
1370 case IFT_ETHER: return NetworkInterface::NI_TYPE_ETHERNET_CSMACD;
1371 case IFT_ISO88025: return NetworkInterface::NI_TYPE_ISO88025_TOKENRING;
1372 case IFT_FRELAY: return NetworkInterface::NI_TYPE_FRAMERELAY;
1373 case IFT_PPP: return NetworkInterface::NI_TYPE_PPP;
1374 case IFT_LOOP: return NetworkInterface::NI_TYPE_SOFTWARE_LOOPBACK;
1375 case IFT_ATM: return NetworkInterface::NI_TYPE_ATM;
1376#if (POCO_OS != POCO_OS_SOLARIS)
1377 case IFT_IEEE1394: return NetworkInterface::NI_TYPE_IEEE1394;
1378#endif
1379#endif
1380 default: return NetworkInterface::NI_TYPE_OTHER;
1381
1382 }
1383}
1384
1385
1386void setInterfaceParams(struct ifaddrs* iface, NetworkInterfaceImpl& impl)
1387{
1388 struct sockaddr_dl* sdl = (struct sockaddr_dl*) iface->ifa_addr;
1389 impl.setName(iface->ifa_name);
1390 impl.setDisplayName(iface->ifa_name);
1391 impl.setAdapterName(iface->ifa_name);
1392 impl.setPhyParams();
1393
1394 impl.setMACAddress(LLADDR(sdl), sdl->sdl_alen);
1395 impl.setType(fromNative(sdl->sdl_type));
1396}
1397
1398
1399} // namespace
1400
1401
1402NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
1403{
1404 FastMutex::ScopedLock lock(_mutex);
1405 Map result;
1406 unsigned ifIndex = 0;
1407 NetworkInterface intf;
1408 Map::iterator ifIt;
1409
1410 struct ifaddrs* ifaces = 0;
1411 struct ifaddrs* currIface = 0;
1412
1413 if (getifaddrs(&ifaces) < 0)
1414 throw NetException("cannot get network adapter list");
1415
1416 try
1417 {
1418 for (currIface = ifaces; currIface != 0; currIface = currIface->ifa_next)
1419 {
1420 if (!currIface->ifa_addr) continue;
1421
1422 IPAddress address, subnetMask, broadcastAddress;
1423 unsigned family = currIface->ifa_addr->sa_family;
1424 switch (family)
1425 {
1426#if defined(POCO_OS_FAMILY_BSD)
1427 case AF_LINK:
1428 {
1429 struct sockaddr_dl* sdl = (struct sockaddr_dl*) currIface->ifa_addr;
1430 ifIndex = sdl->sdl_index;
1431 intf = NetworkInterface(ifIndex);
1432 setInterfaceParams(currIface, intf.impl());
1433 if ((result.find(ifIndex) == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
1434 ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
1435 break;
1436 }
1437#endif
1438 case AF_INET:
1439 ifIndex = if_nametoindex(currIface->ifa_name);
1440 ifIt = result.find(ifIndex);
1441 intf = NetworkInterface(ifIndex);
1442 setInterfaceParams(currIface, intf.impl());
1443 if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
1444 ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
1445
1446 address = IPAddress(*(currIface->ifa_addr));
1447
1448 if (( currIface->ifa_flags & IFF_LOOPBACK ) == 0 && currIface->ifa_netmask)
1449 subnetMask = IPAddress(*(currIface->ifa_netmask));
1450
1451 if (currIface->ifa_flags & IFF_BROADCAST && currIface->ifa_broadaddr)
1452 broadcastAddress = IPAddress(*(currIface->ifa_broadaddr));
1453 else if (currIface->ifa_flags & IFF_POINTOPOINT && currIface->ifa_dstaddr)
1454 broadcastAddress = IPAddress(*(currIface->ifa_dstaddr));
1455 else
1456 broadcastAddress = IPAddress();
1457 break;
1458#if defined(POCO_HAVE_IPv6)
1459 case AF_INET6:
1460 ifIndex = if_nametoindex(currIface->ifa_name);
1461 ifIt = result.find(ifIndex);
1462 intf = NetworkInterface(ifIndex);
1463 setInterfaceParams(currIface, intf.impl());
1464 if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
1465 ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
1466
1467 address = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(currIface->ifa_addr)->sin6_addr,
1468 sizeof(struct in6_addr), ifIndex);
1469 subnetMask = IPAddress(*(currIface->ifa_netmask));
1470 broadcastAddress = IPAddress();
1471 break;
1472#endif
1473 default:
1474 continue;
1475 }
1476
1477 if (family == AF_INET
1478#ifdef POCO_HAVE_IPv6
1479 || family == AF_INET6
1480#endif
1481 )
1482 {
1483 if ((upOnly && intf.isUp()) || !upOnly)
1484 {
1485 if ((ifIt = result.find(ifIndex)) != result.end())
1486 ifIt->second.addAddress(address, subnetMask, broadcastAddress);
1487 }
1488 }
1489 }
1490 }
1491 catch (...) { }
1492 if (ifaces) freeifaddrs(ifaces);
1493
1494 if (ipOnly)
1495 {
1496 Map::iterator it = result.begin();
1497 Map::iterator end = result.end();
1498 for (; it != end;)
1499 {
1500 if (!it->second.supportsIPv4() && !it->second.supportsIPv6())
1501 result.erase(it++);
1502 else ++it;
1503 }
1504 }
1505
1506 return result;
1507}
1508
1509
1510} } // namespace Poco::Net
1511
1512
1513#elif POCO_OS == POCO_OS_LINUX || POCO_OS == POCO_OS_ANDROID
1514//
1515// Linux
1516//
1517
1518
1519#include <sys/types.h>
1520#if POCO_OS != POCO_OS_ANDROID // Android doesn't have <ifaddrs.h>
1521#include <ifaddrs.h>
1522#endif
1523#include <net/if.h>
1524#ifndef POCO_NO_LINUX_IF_PACKET_H
1525#include <linux/if_packet.h>
1526#endif
1527#include <net/if_arp.h>
1528#include <iostream>
1529
1530namespace Poco {
1531namespace Net {
1532
1533
1534namespace {
1535
1536
1537static NetworkInterface::Type fromNative(unsigned arphrd)
1538{
1539 switch (arphrd)
1540 {
1541 case ARPHRD_ETHER: return NetworkInterface::NI_TYPE_ETHERNET_CSMACD;
1542 case ARPHRD_IEEE802: return NetworkInterface::NI_TYPE_ISO88025_TOKENRING;
1543 case ARPHRD_DLCI: return NetworkInterface::NI_TYPE_FRAMERELAY;
1544 case ARPHRD_PPP: return NetworkInterface::NI_TYPE_PPP;
1545 case ARPHRD_LOOPBACK: return NetworkInterface::NI_TYPE_SOFTWARE_LOOPBACK;
1546 case ARPHRD_ATM: return NetworkInterface::NI_TYPE_ATM;
1547 case ARPHRD_IEEE80211: return NetworkInterface::NI_TYPE_IEEE80211;
1548 case ARPHRD_TUNNEL:
1549 case ARPHRD_TUNNEL6: return NetworkInterface::NI_TYPE_TUNNEL;
1550 case ARPHRD_IEEE1394: return NetworkInterface::NI_TYPE_IEEE1394;
1551 default: return NetworkInterface::NI_TYPE_OTHER;
1552 }
1553}
1554
1555#if POCO_OS != POCO_OS_ANDROID
1556
1557void setInterfaceParams(struct ifaddrs* iface, NetworkInterfaceImpl& impl)
1558{
1559 impl.setName(iface->ifa_name);
1560 impl.setDisplayName(iface->ifa_name);
1561 impl.setAdapterName(iface->ifa_name);
1562 impl.setPhyParams();
1563
1564#ifndef POCO_NO_LINUX_IF_PACKET_H
1565 struct sockaddr_ll* sdl = (struct sockaddr_ll*) iface->ifa_addr;
1566 impl.setMACAddress(sdl->sll_addr, sdl->sll_halen);
1567 impl.setType(fromNative(sdl->sll_hatype));
1568#else
1569 std::string ifPath("/sys/class/net/");
1570 ifPath += iface->ifa_name;
1571
1572 std::string addrPath(ifPath);
1573 addrPath += "/address";
1574
1575 std::ifstream addrStream(addrPath.c_str());
1576 if (addrStream.good())
1577 {
1578 std::string addr;
1579 std::getline(addrStream, addr);
1580 Poco::StringTokenizer tok(addr, ":");
1581 std::vector<unsigned char> mac;
1582 for (Poco::StringTokenizer::Iterator it = tok.begin(); it != tok.end(); ++it)
1583 {
1584 mac.push_back(static_cast<unsigned char>(Poco::NumberParser::parseHex(*it)));
1585 }
1586 impl.setMACAddress(&mac[0], mac.size());
1587 addrStream.close();
1588 }
1589
1590 std::string typePath(ifPath);
1591 typePath += "/type";
1592 std::ifstream typeStream(typePath.c_str());
1593 if (typeStream.good())
1594 {
1595 int type;
1596 typeStream >> type;
1597 impl.setType(fromNative(type));
1598 typeStream.close();
1599 }
1600#endif // POCO_NO_LINUX_IF_PACKET_H
1601}
1602
1603#endif
1604
1605
1606}
1607
1608
1609NetworkInterface::Map NetworkInterface::map(bool ipOnly, bool upOnly)
1610{
1611#if POCO_OS != POCO_OS_ANDROID
1612 FastMutex::ScopedLock lock(_mutex);
1613 Map result;
1614 unsigned ifIndex = 0;
1615 NetworkInterface intf;
1616 Map::iterator ifIt;
1617
1618 struct ifaddrs* ifaces = 0;
1619 struct ifaddrs* iface = 0;
1620
1621 if (getifaddrs(&ifaces) < 0)
1622 throw NetException("cannot get network adapter list");
1623
1624 try
1625 {
1626 for (iface = ifaces; iface; iface = iface->ifa_next)
1627 {
1628 if (!iface->ifa_addr) continue;
1629
1630 IPAddress address, subnetMask, broadcastAddress;
1631 unsigned family = iface->ifa_addr->sa_family;
1632 switch (family)
1633 {
1634#ifndef POCO_NO_LINUX_IF_PACKET_H
1635 case AF_PACKET:
1636 {
1637 struct sockaddr_ll* sll = (struct sockaddr_ll*)iface->ifa_addr;
1638 ifIndex = sll->sll_ifindex;
1639 intf = NetworkInterface(ifIndex);
1640 setInterfaceParams(iface, intf.impl());
1641
1642 if ((result.find(ifIndex) == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
1643 ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
1644
1645 break;
1646 }
1647#endif // POCO_NO_LINUX_IF_PACKET_H
1648 case AF_INET:
1649 ifIndex = if_nametoindex(iface->ifa_name);
1650 ifIt = result.find(ifIndex);
1651 intf = NetworkInterface(ifIndex);
1652 setInterfaceParams(iface, intf.impl());
1653
1654 if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
1655 ifIt = result.insert(Map::value_type(ifIndex, intf)).first;
1656
1657 address = IPAddress(*(iface->ifa_addr));
1658 subnetMask = IPAddress(*(iface->ifa_netmask));
1659
1660 if (iface->ifa_flags & IFF_BROADCAST && iface->ifa_broadaddr)
1661 broadcastAddress = IPAddress(*(iface->ifa_broadaddr));
1662 else if (iface->ifa_flags & IFF_POINTOPOINT && iface->ifa_dstaddr)
1663 broadcastAddress = IPAddress(*(iface->ifa_dstaddr));
1664 else
1665 broadcastAddress = IPAddress();
1666
1667 break;
1668#if defined(POCO_HAVE_IPv6)
1669 case AF_INET6:
1670 ifIndex = if_nametoindex(iface->ifa_name);
1671 ifIt = result.find(ifIndex);
1672 intf = NetworkInterface(ifIndex);
1673 setInterfaceParams(iface, intf.impl());
1674
1675 if ((ifIt == result.end()) && ((upOnly && intf.isUp()) || !upOnly))
1676 result.insert(Map::value_type(ifIndex, intf));
1677
1678 address = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(iface->ifa_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
1679 subnetMask = IPAddress(*(iface->ifa_netmask));
1680 broadcastAddress = IPAddress();
1681
1682 break;
1683#endif
1684 default:
1685 continue;
1686 }
1687
1688 if (family == AF_INET
1689#ifdef POCO_HAVE_IPv6
1690 || family == AF_INET6
1691#endif
1692 )
1693 {
1694 intf = NetworkInterface(std::string(iface->ifa_name), address, subnetMask, broadcastAddress, ifIndex);
1695 if ((upOnly && intf.isUp()) || !upOnly)
1696 {
1697 if ((ifIt = result.find(ifIndex)) != result.end())
1698 ifIt->second.addAddress(address, subnetMask, broadcastAddress);
1699 }
1700 }
1701 } // for interface
1702 }
1703 catch (...)
1704 {
1705 if (ifaces) freeifaddrs(ifaces);
1706 throw;
1707 }
1708
1709 if (ifaces) freeifaddrs(ifaces);
1710
1711 if (ipOnly)
1712 {
1713 Map::iterator it = result.begin();
1714 Map::iterator end = result.end();
1715 for (; it != end;)
1716 {
1717 if (!it->second.supportsIPv4() && !it->second.supportsIPv6())
1718 result.erase(it++);
1719 else ++it;
1720 }
1721 }
1722
1723 return result;
1724#else
1725 throw Poco::NotImplementedException("Not implemented in Android");
1726#endif
1727}
1728
1729
1730} } // namespace Poco::Net
1731
1732
1733#else
1734//
1735// Non-BSD Unix variants
1736//
1737#error TODO
1738/*
1739NetworkInterface::NetworkInterfaceList NetworkInterface::list()
1740{
1741 FastMutex::ScopedLock lock(_mutex);
1742 NetworkInterfaceList result;
1743 DatagramSocket socket;
1744 // the following code is loosely based
1745 // on W. Richard Stevens, UNIX Network Programming, pp 434ff.
1746 int lastlen = 0;
1747 int len = 100*sizeof(struct ifreq);
1748 char* buf = 0;
1749 try
1750 {
1751 struct ifconf ifc;
1752 for (;;)
1753 {
1754 buf = new char[len];
1755 ifc.ifc_len = len;
1756 ifc.ifc_buf = buf;
1757 if (::ioctl(socket.impl()->sockfd(), SIOCGIFCONF, &ifc) < 0)
1758 {
1759 if (errno != EINVAL || lastlen != 0)
1760 throw NetException("cannot get network adapter list");
1761 }
1762 else
1763 {
1764 if (ifc.ifc_len == lastlen)
1765 break;
1766 lastlen = ifc.ifc_len;
1767 }
1768 len += 10*sizeof(struct ifreq);
1769 delete [] buf;
1770 }
1771 for (const char* ptr = buf; ptr < buf + ifc.ifc_len;)
1772 {
1773 const struct ifreq* ifr = reinterpret_cast<const struct ifreq*>(ptr);
1774#if defined(POCO_HAVE_SALEN)
1775 len = ifr->ifr_addr.sa_len;
1776 if (sizeof(struct sockaddr) > len) len = sizeof(struct sockaddr);
1777#else
1778 len = sizeof(struct sockaddr);
1779#endif
1780 IPAddress addr;
1781 bool haveAddr = false;
1782 int ifIndex(-1);
1783 switch (ifr->ifr_addr.sa_family)
1784 {
1785#if defined(POCO_HAVE_IPv6)
1786 case AF_INET6:
1787 ifIndex = if_nametoindex(ifr->ifr_name);
1788 if (len < sizeof(struct sockaddr_in6)) len = sizeof(struct sockaddr_in6);
1789 addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
1790 haveAddr = true;
1791 break;
1792#endif
1793 case AF_INET:
1794 if (len < sizeof(struct sockaddr_in)) len = sizeof(struct sockaddr_in);
1795 addr = IPAddress(ifr->ifr_addr);
1796 haveAddr = true;
1797 break;
1798 default:
1799 break;
1800 }
1801 if (haveAddr)
1802 {
1803 std::string name(ifr->ifr_name);
1804 result.push_back(NetworkInterface(name, name, name, addr, ifIndex));
1805 }
1806 len += sizeof(ifr->ifr_name);
1807 ptr += len;
1808 }
1809 }
1810 catch (...)
1811 {
1812 delete [] buf;
1813 throw;
1814 }
1815 delete [] buf;
1816 return result;
1817}
1818*/
1819
1820} } // namespace Poco::Net
1821
1822
1823#endif
1824
1825
1826#endif // POCO_NET_HAS_INTERFACE
1827