xref: /haiku/src/kits/network/libnetapi/NetworkRoster.cpp (revision 3a5082aa46f958b1f49398c8b69458fa12dd581e)
1 /*
2  * Copyright 2010, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <NetworkRoster.h>
8 
9 #include <errno.h>
10 #include <sys/sockio.h>
11 
12 #include <NetworkInterface.h>
13 
14 #include <net_notifications.h>
15 #include <AutoDeleter.h>
16 
17 
18 BNetworkRoster BNetworkRoster::sDefault;
19 
20 
21 /*static*/ BNetworkRoster&
22 BNetworkRoster::Default()
23 {
24 	return sDefault;
25 }
26 
27 
28 size_t
29 BNetworkRoster::CountInterfaces() const
30 {
31 	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
32 	if (socket < 0)
33 		return 0;
34 
35 	FileDescriptorCloser closer(socket);
36 
37 	ifconf config;
38 	config.ifc_len = sizeof(config.ifc_value);
39 	if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) != 0)
40 		return 0;
41 
42 	return (size_t)config.ifc_value;
43 }
44 
45 
46 status_t
47 BNetworkRoster::GetNextInterface(uint32* cookie,
48 	BNetworkInterface& interface) const
49 {
50 	// TODO: think about caching the interfaces!
51 
52 	if (cookie == NULL)
53 		return B_BAD_VALUE;
54 
55 	// get a list of all interfaces
56 
57 	int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
58 	if (socket < 0)
59 		return errno;
60 
61 	FileDescriptorCloser closer(socket);
62 
63 	ifconf config;
64 	config.ifc_len = sizeof(config.ifc_value);
65 	if (ioctl(socket, SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
66 		return errno;
67 
68 	size_t count = (size_t)config.ifc_value;
69 	if (count == 0)
70 		return B_BAD_VALUE;
71 
72 	char* buffer = (char*)malloc(count * sizeof(struct ifreq));
73 	if (buffer == NULL)
74 		return B_NO_MEMORY;
75 
76 	MemoryDeleter deleter(buffer);
77 
78 	config.ifc_len = count * sizeof(struct ifreq);
79 	config.ifc_buf = buffer;
80 	if (ioctl(socket, SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
81 		return errno;
82 
83 	ifreq* interfaces = (ifreq*)buffer;
84 	ifreq* end = (ifreq*)(buffer + config.ifc_len);
85 
86 	for (uint32 i = 0; interfaces < end; i++) {
87 		interface.SetTo(interfaces[0].ifr_name);
88 		if (i == *cookie) {
89 			(*cookie)++;
90 			return B_OK;
91 		}
92 
93 		interfaces = (ifreq*)((uint8*)interfaces
94 			+ _SIZEOF_ADDR_IFREQ(interfaces[0]));
95 	}
96 
97 	return B_BAD_VALUE;
98 }
99 
100 
101 status_t
102 BNetworkRoster::AddInterface(const BNetworkInterface& interface)
103 {
104 	// TODO: implement me
105 	return B_NOT_SUPPORTED;
106 }
107 
108 
109 status_t
110 BNetworkRoster::RemoveInterface(const BNetworkInterface& interface)
111 {
112 	// TODO: implement me
113 	return B_NOT_SUPPORTED;
114 }
115 
116 
117 status_t
118 BNetworkRoster::StartWatching(const BMessenger& target, uint32 eventMask)
119 {
120 	return start_watching_network(eventMask, target);
121 }
122 
123 
124 void
125 BNetworkRoster::StopWatching(const BMessenger& target)
126 {
127 	stop_watching_network(target);
128 }
129 
130 
131 // #pragma mark - private
132 
133 
134 BNetworkRoster::BNetworkRoster()
135 {
136 }
137 
138 
139 BNetworkRoster::~BNetworkRoster()
140 {
141 }
142