BPicture: Fix archive constructor.
[haiku.git] / src / kits / network / libnetapi / NetworkInterface.cpp
blob9d9ab8e505b41f005399ea83cfe40f436415a98f
1 /*
2 * Copyright 2010, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
6 #include <NetworkInterface.h>
8 #include <errno.h>
9 #include <net/if.h>
10 #include <sys/sockio.h>
12 #include <AutoDeleter.h>
13 #include <Messenger.h>
14 #include <NetServer.h>
15 #include <NetworkRoute.h>
18 static int
19 family_from_interface_address(const BNetworkInterfaceAddress& address)
21 if (address.Address().Family() != AF_UNSPEC)
22 return address.Address().Family();
23 if (address.Mask().Family() != AF_UNSPEC)
24 return address.Mask().Family();
25 if (address.Destination().Family() != AF_UNSPEC)
26 return address.Destination().Family();
28 return AF_INET;
32 static status_t
33 do_ifaliasreq(const char* name, int32 option, BNetworkInterfaceAddress& address,
34 bool readBack = false)
36 int family = AF_INET;
37 if (!readBack)
38 family = family_from_interface_address(address);
40 int socket = ::socket(family, SOCK_DGRAM, 0);
41 if (socket < 0)
42 return errno;
44 FileDescriptorCloser closer(socket);
46 ifaliasreq request;
47 strlcpy(request.ifra_name, name, IF_NAMESIZE);
48 request.ifra_index = address.Index();
49 request.ifra_flags = address.Flags();
51 memcpy(&request.ifra_addr, &address.Address().SockAddr(),
52 address.Address().Length());
53 memcpy(&request.ifra_mask, &address.Mask().SockAddr(),
54 address.Mask().Length());
55 memcpy(&request.ifra_broadaddr, &address.Broadcast().SockAddr(),
56 address.Broadcast().Length());
58 if (ioctl(socket, option, &request, sizeof(struct ifaliasreq)) < 0)
59 return errno;
61 if (readBack) {
62 address.SetFlags(request.ifra_flags);
63 address.Address().SetTo(request.ifra_addr);
64 address.Mask().SetTo(request.ifra_mask);
65 address.Broadcast().SetTo(request.ifra_broadaddr);
68 return B_OK;
72 static status_t
73 do_ifaliasreq(const char* name, int32 option,
74 const BNetworkInterfaceAddress& address)
76 return do_ifaliasreq(name, option,
77 const_cast<BNetworkInterfaceAddress&>(address));
81 template<typename T> status_t
82 do_request(int family, T& request, const char* name, int option)
84 int socket = ::socket(family, SOCK_DGRAM, 0);
85 if (socket < 0)
86 return errno;
88 FileDescriptorCloser closer(socket);
90 strlcpy(((struct ifreq&)request).ifr_name, name, IF_NAMESIZE);
92 if (ioctl(socket, option, &request, sizeof(T)) < 0)
93 return errno;
95 return B_OK;
99 // #pragma mark -
102 BNetworkInterfaceAddress::BNetworkInterfaceAddress()
104 fIndex(-1),
105 fFlags(0)
110 BNetworkInterfaceAddress::~BNetworkInterfaceAddress()
115 status_t
116 BNetworkInterfaceAddress::SetTo(const BNetworkInterface& interface, int32 index)
118 fIndex = index;
119 return do_ifaliasreq(interface.Name(), B_SOCKET_GET_ALIAS, *this, true);
123 void
124 BNetworkInterfaceAddress::SetAddress(const BNetworkAddress& address)
126 fAddress = address;
130 void
131 BNetworkInterfaceAddress::SetMask(const BNetworkAddress& mask)
133 fMask = mask;
137 void
138 BNetworkInterfaceAddress::SetBroadcast(const BNetworkAddress& broadcast)
140 fBroadcast = broadcast;
144 void
145 BNetworkInterfaceAddress::SetDestination(const BNetworkAddress& destination)
147 fBroadcast = destination;
151 void
152 BNetworkInterfaceAddress::SetFlags(uint32 flags)
154 fFlags = flags;
158 // #pragma mark -
161 BNetworkInterface::BNetworkInterface()
163 Unset();
167 BNetworkInterface::BNetworkInterface(const char* name)
169 SetTo(name);
173 BNetworkInterface::BNetworkInterface(uint32 index)
175 SetTo(index);
179 BNetworkInterface::~BNetworkInterface()
184 void
185 BNetworkInterface::Unset()
187 fName[0] = '\0';
191 void
192 BNetworkInterface::SetTo(const char* name)
194 strlcpy(fName, name, IF_NAMESIZE);
198 status_t
199 BNetworkInterface::SetTo(uint32 index)
201 ifreq request;
202 request.ifr_index = index;
204 status_t status = do_request(AF_INET, request, "", SIOCGIFNAME);
205 if (status != B_OK)
206 return status;
208 strlcpy(fName, request.ifr_name, IF_NAMESIZE);
209 return B_OK;
213 bool
214 BNetworkInterface::Exists() const
216 ifreq request;
217 return do_request(AF_INET, request, Name(), SIOCGIFINDEX) == B_OK;
221 const char*
222 BNetworkInterface::Name() const
224 return fName;
228 uint32
229 BNetworkInterface::Index() const
231 ifreq request;
232 if (do_request(AF_INET, request, Name(), SIOCGIFINDEX) != B_OK)
233 return 0;
235 return request.ifr_index;
239 uint32
240 BNetworkInterface::Flags() const
242 ifreq request;
243 if (do_request(AF_INET, request, Name(), SIOCGIFFLAGS) != B_OK)
244 return 0;
246 return request.ifr_flags;
250 uint32
251 BNetworkInterface::MTU() const
253 ifreq request;
254 if (do_request(AF_INET, request, Name(), SIOCGIFMTU) != B_OK)
255 return 0;
257 return request.ifr_mtu;
261 int32
262 BNetworkInterface::Media() const
264 ifmediareq request;
265 request.ifm_count = 0;
266 request.ifm_ulist = NULL;
268 if (do_request(AF_INET, request, Name(), SIOCGIFMEDIA) != B_OK)
269 return -1;
271 return request.ifm_current;
275 uint32
276 BNetworkInterface::Metric() const
278 ifreq request;
279 if (do_request(AF_INET, request, Name(), SIOCGIFMETRIC) != B_OK)
280 return 0;
282 return request.ifr_metric;
286 uint32
287 BNetworkInterface::Type() const
289 ifreq request;
290 if (do_request(AF_INET, request, Name(), SIOCGIFTYPE) != B_OK)
291 return 0;
293 return request.ifr_type;
297 status_t
298 BNetworkInterface::GetStats(ifreq_stats& stats)
300 ifreq request;
301 status_t status = do_request(AF_INET, request, Name(), SIOCGIFSTATS);
302 if (status != B_OK)
303 return status;
305 memcpy(&stats, &request.ifr_stats, sizeof(ifreq_stats));
306 return B_OK;
310 bool
311 BNetworkInterface::HasLink() const
313 return (Flags() & IFF_LINK) != 0;
317 status_t
318 BNetworkInterface::SetFlags(uint32 flags)
320 ifreq request;
321 request.ifr_flags = flags;
322 return do_request(AF_INET, request, Name(), SIOCSIFFLAGS);
326 status_t
327 BNetworkInterface::SetMTU(uint32 mtu)
329 ifreq request;
330 request.ifr_mtu = mtu;
331 return do_request(AF_INET, request, Name(), SIOCSIFMTU);
335 status_t
336 BNetworkInterface::SetMedia(int32 media)
338 ifreq request;
339 request.ifr_media = media;
340 return do_request(AF_INET, request, Name(), SIOCSIFMEDIA);
344 status_t
345 BNetworkInterface::SetMetric(uint32 metric)
347 ifreq request;
348 request.ifr_metric = metric;
349 return do_request(AF_INET, request, Name(), SIOCSIFMETRIC);
353 int32
354 BNetworkInterface::CountAddresses() const
356 ifreq request;
357 if (do_request(AF_INET, request, Name(), B_SOCKET_COUNT_ALIASES) != B_OK)
358 return 0;
360 return request.ifr_count;
364 status_t
365 BNetworkInterface::GetAddressAt(int32 index, BNetworkInterfaceAddress& address)
367 return address.SetTo(*this, index);
371 int32
372 BNetworkInterface::FindAddress(const BNetworkAddress& address)
374 int socket = ::socket(address.Family(), SOCK_DGRAM, 0);
375 if (socket < 0)
376 return -1;
378 FileDescriptorCloser closer(socket);
380 ifaliasreq request;
381 memset(&request, 0, sizeof(ifaliasreq));
383 strlcpy(request.ifra_name, Name(), IF_NAMESIZE);
384 request.ifra_index = -1;
385 memcpy(&request.ifra_addr, &address.SockAddr(), address.Length());
387 if (ioctl(socket, B_SOCKET_GET_ALIAS, &request, sizeof(struct ifaliasreq))
388 < 0) {
389 return -1;
392 return request.ifra_index;
396 int32
397 BNetworkInterface::FindFirstAddress(int family)
399 int socket = ::socket(family, SOCK_DGRAM, 0);
400 if (socket < 0)
401 return -1;
403 FileDescriptorCloser closer(socket);
405 ifaliasreq request;
406 memset(&request, 0, sizeof(ifaliasreq));
408 strlcpy(request.ifra_name, Name(), IF_NAMESIZE);
409 request.ifra_index = -1;
410 request.ifra_addr.ss_family = AF_UNSPEC;
412 if (ioctl(socket, B_SOCKET_GET_ALIAS, &request, sizeof(struct ifaliasreq))
413 < 0) {
414 return -1;
417 return request.ifra_index;
421 status_t
422 BNetworkInterface::AddAddress(const BNetworkInterfaceAddress& address)
424 return do_ifaliasreq(Name(), B_SOCKET_ADD_ALIAS, address);
428 status_t
429 BNetworkInterface::AddAddress(const BNetworkAddress& local)
431 BNetworkInterfaceAddress address;
432 address.SetAddress(local);
434 return do_ifaliasreq(Name(), B_SOCKET_ADD_ALIAS, address);
438 status_t
439 BNetworkInterface::SetAddress(const BNetworkInterfaceAddress& address)
441 return do_ifaliasreq(Name(), B_SOCKET_SET_ALIAS, address);
445 status_t
446 BNetworkInterface::RemoveAddress(const BNetworkInterfaceAddress& address)
448 ifreq request;
449 memcpy(&request.ifr_addr, &address.Address().SockAddr(),
450 address.Address().Length());
452 return do_request(family_from_interface_address(address), request, Name(),
453 B_SOCKET_REMOVE_ALIAS);
457 status_t
458 BNetworkInterface::RemoveAddress(const BNetworkAddress& address)
460 ifreq request;
461 memcpy(&request.ifr_addr, &address.SockAddr(), address.Length());
463 return do_request(address.Family(), request, Name(), B_SOCKET_REMOVE_ALIAS);
467 status_t
468 BNetworkInterface::RemoveAddressAt(int32 index)
470 BNetworkInterfaceAddress address;
471 status_t status = GetAddressAt(index, address);
472 if (status != B_OK)
473 return status;
475 return RemoveAddress(address);
479 status_t
480 BNetworkInterface::GetHardwareAddress(BNetworkAddress& address)
482 int socket = ::socket(AF_LINK, SOCK_DGRAM, 0);
483 if (socket < 0)
484 return errno;
486 FileDescriptorCloser closer(socket);
488 ifreq request;
489 strlcpy(request.ifr_name, Name(), IF_NAMESIZE);
491 if (ioctl(socket, SIOCGIFADDR, &request, sizeof(struct ifreq)) < 0)
492 return errno;
494 address.SetTo(request.ifr_addr);
495 return B_OK;
499 status_t
500 BNetworkInterface::AddRoute(const BNetworkRoute& route)
502 int family = route.AddressFamily();
503 if (family == AF_UNSPEC)
504 return B_BAD_VALUE;
506 ifreq request;
507 request.ifr_route = route.RouteEntry();
508 return do_request(family, request, Name(), SIOCADDRT);
512 status_t
513 BNetworkInterface::AddDefaultRoute(const BNetworkAddress& gateway)
515 BNetworkRoute route;
516 status_t result = route.SetGateway(gateway);
517 if (result != B_OK)
518 return result;
520 route.SetFlags(RTF_STATIC | RTF_DEFAULT | RTF_GATEWAY);
521 return AddRoute(route);
525 status_t
526 BNetworkInterface::RemoveRoute(const BNetworkRoute& route)
528 int family = route.AddressFamily();
529 if (family == AF_UNSPEC)
530 return B_BAD_VALUE;
532 return RemoveRoute(family, route);
536 status_t
537 BNetworkInterface::RemoveRoute(int family, const BNetworkRoute& route)
539 ifreq request;
540 request.ifr_route = route.RouteEntry();
541 return do_request(family, request, Name(), SIOCDELRT);
545 status_t
546 BNetworkInterface::RemoveDefaultRoute(int family)
548 BNetworkRoute route;
549 route.SetFlags(RTF_STATIC | RTF_DEFAULT);
550 return RemoveRoute(family, route);
554 status_t
555 BNetworkInterface::GetRoutes(int family,
556 BObjectList<BNetworkRoute>& routes) const
558 return BNetworkRoute::GetRoutes(family, Name(), routes);
562 status_t
563 BNetworkInterface::GetDefaultRoute(int family, BNetworkRoute& route) const
565 return BNetworkRoute::GetDefaultRoute(family, Name(), route);
569 status_t
570 BNetworkInterface::GetDefaultGateway(int family, BNetworkAddress& gateway) const
572 return BNetworkRoute::GetDefaultGateway(family, Name(), gateway);
576 status_t
577 BNetworkInterface::AutoConfigure(int family)
579 BMessage message(kMsgConfigureInterface);
580 message.AddString("device", Name());
582 BMessage address;
583 address.AddInt32("family", family);
584 address.AddBool("auto_config", true);
585 message.AddMessage("address", &address);
587 BMessenger networkServer(kNetServerSignature);
588 BMessage reply;
589 status_t status = networkServer.SendMessage(&message, &reply);
590 if (status == B_OK)
591 reply.FindInt32("status", &status);
593 return status;