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