File: ifvc.c

package info (click to toggle)
smcroute 2.0.0-4
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 624 kB
  • ctags: 221
  • sloc: ansic: 2,296; sh: 1,306; perl: 161; makefile: 60
file content (245 lines) | stat: -rw-r--r-- 6,034 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/* Physical and virtual interface API
 *
 * Copyright (C) 2001-2005  Carsten Schill <carsten@cschill.de>
 * Copyright (C) 2006-2009  Julien BLACHE <jb@jblache.org>
 * Copyright (C) 2009       Todd Hayton <todd.hayton@gmail.com>
 * Copyright (C) 2009-2011  Micha Lenk <micha@debian.org>
 * Copyright (C) 2011-2013  Joachim Nilsson <troglobit@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 */

#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <ifaddrs.h>
#include "mclab.h"

static unsigned int num_ifaces = 0;
static struct iface *iface_list = NULL;

/**
 * iface_init - Setup vector of active interfaces
 *
 * Builds up a vector with active system interfaces.  Must be called
 * before any other interface functions in this module!
 */
void iface_init(void)
{
	int family;
	struct iface *iface;
	struct ifaddrs *ifaddr, *ifa;

	num_ifaces = 0;

	if (iface_list)
		free(iface_list);

	iface_list = calloc(MAX_IF, sizeof(struct iface));
	if (!iface_list) {
		smclog(LOG_ERR, errno, "Failed allocating space for interfaces");
		return;
	}

	if (getifaddrs(&ifaddr) == -1) {
		smclog(LOG_ERR, errno, "Failed retrieving interface addresses");
		return;
	}

	for (ifa = ifaddr; ifa && num_ifaces < MAX_IF; ifa = ifa->ifa_next) {
		/* Skip interface without internet address */
		if (!ifa->ifa_addr)
			continue;

		/* Skip non-IPv4 and non-IPv6 interfaces */
		family = ifa->ifa_addr->sa_family;
		if ((family != AF_INET) && (family != AF_INET6))
			continue;

		/* Check if already added? */
		if (iface_find_by_name (ifa->ifa_name))
			continue;

		/* Copy data from interface iterator 'ifa' */
		iface = &iface_list[num_ifaces++];
		strncpy(iface->name, ifa->ifa_name, IFNAMSIZ);
		iface->name[IFNAMSIZ] = 0;
		if (family == AF_INET)
			iface->inaddr.s_addr = ((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
		iface->flags = ifa->ifa_flags;
		iface->ifindex = if_nametoindex(iface->name);
		iface->vif = -1;
		iface->mif = -1;
	}
	freeifaddrs(ifaddr);
}

/**
 * iface_find_by_name - Find an interface by name
 * @ifname: Interface name
 *
 * Returns:
 * Pointer to a @struct iface of the matching interface, or %NULL if no
 * interface exists, or is up.  If more than one interface exists, chose
 * the interface that corresponds to a virtual interface.
 */
struct iface *iface_find_by_name(const char *ifname)
{
	unsigned int i;
	struct iface *iface;
	struct iface *candidate = NULL;

	for (i = 0; i < num_ifaces; i++) {
		iface = &iface_list[i];
		if (!strcmp(ifname, iface->name)) {
			if (iface->vif >= 0)
				return iface;
			candidate = iface;
		}
	}

	return candidate;
}

/**
 * iface_find_by_vif - Find by virtual interface index
 * @vif: Virtual multicast interface index
 *
 * Returns:
 * Pointer to a @struct iface of the requested interface, or %NULL if no
 * interface matching @vif exists.
 */
struct iface *iface_find_by_vif(int vif)
{
	size_t i;

	for (i = 0; i < num_ifaces; i++) {
		struct iface *iface = &iface_list[i];

		if (iface->vif >= 0 && iface->vif == vif)
			return iface;
	}

	return NULL;
}

/**
 * iface_find_by_index - Find by kernel interface index
 * @ifindex: Kernel interface index
 *
 * Returns:
 * Pointer to a @struct iface of the requested interface, or %NULL if no
 * interface @ifindex exists.
 */
struct iface *iface_find_by_index(unsigned int ifindex)
{
	if (ifindex >= num_ifaces)
		return NULL;

	return &iface_list[ifindex];
}


/**
 * iface_get_vif - Get virtual interface index for an interface (IPv4)
 * @iface: Pointer to a @struct iface interface
 *
 * Returns:
 * The virtual interface index if the interface is known and registered
 * with the kernel, or -1 if no virtual interface exists.
 */
int iface_get_vif(struct iface *iface)
{
	if (!iface)
		return -1;

	return iface->vif;
}

/**
 * iface_get_mif - Get virtual interface index for an interface (IPv6)
 * @iface: Pointer to a @struct iface interface
 *
 * Returns:
 * The virtual interface index if the interface is known and registered
 * with the kernel, or -1 if no virtual interface exists.
 */
int iface_get_mif(struct iface *iface __attribute__ ((unused)))
{
#ifndef HAVE_IPV6_MULTICAST_ROUTING
	return -1;
#else
	if (!iface)
		return -1;

	return iface->mif;
#endif				/* HAVE_IPV6_MULTICAST_ROUTING */
}

/**
 * iface_get_vif_by_name - Get virtual interface index by interface name (IPv4)
 * @ifname: Interface name
 *
 * Returns:
 * The virtual interface index if the interface is known and registered
 * with the kernel, or -1 if no virtual interface by that name is found.
 */
int iface_get_vif_by_name(const char *ifname)
{
	int vif;
	struct iface *iface;

	iface = iface_find_by_name(ifname);
	if (!iface)
		return -1;

	vif = iface_get_vif(iface);
	if (vif < 0)
		return -1;

	return vif;
}

/**
 * iface_get_mif_by_name - Get virtual interface index by interface name (IPv6)
 * @ifname: Interface name
 *
 * Returns:
 * The virtual interface index if the interface is known and registered
 * with the kernel, or -1 if no virtual interface by that name is found.
 */
int iface_get_mif_by_name(const char *ifname)
{
	int vif;
	struct iface *iface;

	iface = iface_find_by_name(ifname);
	if (!iface)
		return -1;

	vif = iface_get_mif(iface);
	if (vif < 0)
		return -1;

	return vif;
}

/**
 * Local Variables:
 *  version-control: t
 *  indent-tabs-mode: t
 *  c-file-style: "linux"
 * End:
 */