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 <net/if.h>
11#include <sys/socket.h>
12#include <sys/sockio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <unistd.h>
16
17#include <AutoDeleter.h>
18
19
20namespace BPrivate {
21	class Socket {
22		public:
23			Socket()
24			{
25				fFD = socket(AF_INET, SOCK_DGRAM, 0);
26			}
27
28			~Socket()
29			{
30				if (fFD >= 0)
31					close(fFD);
32			}
33
34			int FD() const { return fFD; }
35
36		private:
37			int	fFD;
38	};
39}	// namespace BPrivate
40
41
42//	#pragma mark -
43
44
45unsigned
46if_nametoindex(const char* name)
47{
48	BPrivate::Socket socket;
49	if (socket.FD() < 0)
50		return 0;
51
52	ifreq request;
53	strlcpy(request.ifr_name, name, IF_NAMESIZE);
54	if (ioctl(socket.FD(), SIOCGIFINDEX, &request, sizeof(struct ifreq)) < 0)
55		return 0;
56
57	return request.ifr_index;
58}
59
60
61char*
62if_indextoname(unsigned index, char* nameBuffer)
63{
64	BPrivate::Socket socket;
65	if (socket.FD() < 0)
66		return NULL;
67
68	ifreq request;
69	request.ifr_index = index;
70	if (ioctl(socket.FD(), SIOCGIFNAME, &request, sizeof(struct ifreq)) < 0)
71		return NULL;
72
73	strlcpy(nameBuffer, request.ifr_name, IF_NAMESIZE);
74	return nameBuffer;
75}
76
77
78struct if_nameindex*
79if_nameindex(void)
80{
81	BPrivate::Socket socket;
82	if (socket.FD() < 0)
83		return NULL;
84
85	// get a list of all interfaces
86
87	ifconf config;
88	config.ifc_len = sizeof(config.ifc_value);
89	if (ioctl(socket.FD(), SIOCGIFCOUNT, &config, sizeof(struct ifconf)) < 0)
90		return NULL;
91
92	int count = (int)config.ifc_value;
93	ifreq* interfaces = (ifreq*)malloc(count * sizeof(struct ifreq));
94	if (interfaces == NULL)
95		return NULL;
96
97	MemoryDeleter deleter(interfaces);
98
99	config.ifc_len = count * sizeof(struct ifreq);
100	config.ifc_req = interfaces;
101	if (ioctl(socket.FD(), SIOCGIFCONF, &config, sizeof(struct ifconf)) < 0)
102		return NULL;
103
104	struct if_nameindex* interfaceArray = (struct if_nameindex*)malloc(
105		sizeof(struct if_nameindex) * (count + 1));
106	if (interfaceArray == NULL)
107		return NULL;
108
109	for (int i = 0; i < count; i++) {
110		interfaceArray[i].if_index = interfaces->ifr_index;
111		interfaceArray[i].if_name = strdup(interfaces->ifr_name);
112
113		interfaces
114			= (ifreq*)((char*)interfaces + _SIZEOF_ADDR_IFREQ(interfaces[0]));
115	}
116
117	interfaceArray[count].if_index = 0;
118	interfaceArray[count].if_name = NULL;
119
120	return interfaceArray;
121}
122
123
124void
125if_freenameindex(struct if_nameindex *interfaceArray)
126{
127	for (int i = 0; interfaceArray[i].if_name; i++) {
128		free(interfaceArray[i].if_name);
129	}
130	free(interfaceArray);
131}
132
133