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
23namespace 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
48unsigned
49if_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
64char*
65if_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
81struct if_nameindex*
82if_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
138void
139if_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