xref: /haiku/src/system/libnetwork/interfaces.cpp (revision e705c841d784f0035a0ef3e9e96f6e017df16681)
1 /*
2  * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Axel Dörfler, axeld@pinc-software.de
7  */
8 
9 
10 #include <errno.h>
11 #include <net/if.h>
12 #include <sys/socket.h>
13 #include <sys/sockio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17 
18 #include <AutoDeleter.h>
19 
20 #include "compatibility/bsd/ifaddrs.h"
21 
22 
23 namespace BPrivate {
24 	class Socket {
25 		public:
26 			Socket()
27 			{
28 				fFD = socket(AF_INET, SOCK_DGRAM, 0);
29 			}
30 
31 			~Socket()
32 			{
33 				if (fFD >= 0)
34 					close(fFD);
35 			}
36 
37 			int FD() const { return fFD; }
38 
39 		private:
40 			int	fFD;
41 	};
42 }	// namespace BPrivate
43 
44 
45 //	#pragma mark -
46 
47 
48 unsigned
49 if_nametoindex(const char* name)
50 {
51 	BPrivate::Socket socket;
52 	if (socket.FD() < 0)
53 		return 0;
54 
55 	ifreq request;
56 	strlcpy(request.ifr_name, name, IF_NAMESIZE);
57 	if (ioctl(socket.FD(), SIOCGIFINDEX, &request, sizeof(struct ifreq)) < 0)
58 		return 0;
59 
60 	return request.ifr_index;
61 }
62 
63 
64 char*
65 if_indextoname(unsigned index, char* nameBuffer)
66 {
67 	BPrivate::Socket socket;
68 	if (socket.FD() < 0)
69 		return NULL;
70 
71 	ifreq request;
72 	request.ifr_index = index;
73 	if (ioctl(socket.FD(), SIOCGIFNAME, &request, sizeof(struct ifreq)) < 0)
74 		return NULL;
75 
76 	strlcpy(nameBuffer, request.ifr_name, IF_NAMESIZE);
77 	return nameBuffer;
78 }
79 
80 
81 struct if_nameindex*
82 if_nameindex(void)
83 {
84 	BPrivate::Socket socket;
85 	if (socket.FD() < 0)
86 		return NULL;
87 
88 	// get a list of all interfaces
89 
90 	ifconf config;
91 	config.ifc_len = sizeof(config.ifc_value);
92 	if (ioctl(socket.FD(), SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
93 		return NULL;
94 
95 	int count = (int)config.ifc_value;
96 	ifreq* interfaces = (ifreq*)malloc(count * sizeof(struct ifreq));
97 	if (interfaces == NULL)
98 		return NULL;
99 
100 	MemoryDeleter deleter(interfaces);
101 
102 	config.ifc_len = count * sizeof(struct ifreq);
103 	config.ifc_req = interfaces;
104 	if (ioctl(socket.FD(), SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
105 		return NULL;
106 
107 	struct if_nameindex* interfaceArray = (struct if_nameindex*)malloc(
108 		sizeof(struct if_nameindex) * (count + 1));
109 	if (interfaceArray == NULL)
110 		return NULL;
111 
112 	int i = 0;
113 	while (count > 0) {
114 		// retrieve interface index
115 		ifreq request;
116 		strlcpy(((struct ifreq&)request).ifr_name, interfaces->ifr_name,
117 			IF_NAMESIZE);
118 
119 		if (ioctl(socket.FD(), SIOCGIFINDEX, &request,
120 				sizeof(struct ifreq)) >= 0) {
121 			interfaceArray[i].if_index = request.ifr_index;
122 			interfaceArray[i].if_name = strdup(interfaces->ifr_name);
123 			i++;
124 		}
125 
126 		interfaces = (ifreq*)((char*)interfaces
127 			+ _SIZEOF_ADDR_IFREQ(interfaces[0]));
128 		count--;
129 	}
130 
131 	interfaceArray[i].if_index = 0;
132 	interfaceArray[i].if_name = NULL;
133 
134 	return interfaceArray;
135 }
136 
137 
138 void
139 if_freenameindex(struct if_nameindex *interfaceArray)
140 {
141 	for (int i = 0; interfaceArray[i].if_name; i++)
142 		free(interfaceArray[i].if_name);
143 
144 	free(interfaceArray);
145 }
146