GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/net/if_nameindex.c Lines: 31 37 83.8 %
Date: 2017-11-07 Branches: 11 18 61.1 %

Line Branch Exec Source
1
/*	$OpenBSD: if_nameindex.c,v 1.13 2016/12/16 17:44:59 krw Exp $	*/
2
/*	$KAME: if_nameindex.c,v 1.7 2000/11/24 08:17:20 itojun Exp $	*/
3
4
/*-
5
 * Copyright (c) 2015 Claudio Jeker <claudio@openbsd.org>
6
 * Copyright (c) 1997, 2000
7
 *	Berkeley Software Design, Inc.  All rights reserved.
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 *	BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
28
 */
29
30
#include <sys/types.h>
31
#include <sys/socket.h>
32
#include <sys/sysctl.h>
33
#include <net/if.h>
34
#include <stdlib.h>
35
#include <string.h>
36
#include <errno.h>
37
38
/*
39
 * From RFC 2553:
40
 *
41
 * 4.3 Return All Interface Names and Indexes
42
 *
43
 *    The if_nameindex structure holds the information about a single
44
 *    interface and is defined as a result of including the <net/if.h>
45
 *    header.
46
 *
47
 *       struct if_nameindex {
48
 *         unsigned int   if_index;
49
 *         char          *if_name;
50
 *       };
51
 *
52
 *    The final function returns an array of if_nameindex structures, one
53
 *    structure per interface.
54
 *
55
 *       struct if_nameindex  *if_nameindex(void);
56
 *
57
 *    The end of the array of structures is indicated by a structure with
58
 *    an if_index of 0 and an if_name of NULL.  The function returns a NULL
59
 *    pointer upon an error, and would set errno to the appropriate value.
60
 *
61
 *    The memory used for this array of structures along with the interface
62
 *    names pointed to by the if_name members is obtained dynamically.
63
 *    This memory is freed by the next function.
64
 *
65
 * 4.4.  Free Memory
66
 *
67
 *    The following function frees the dynamic memory that was allocated by
68
 *    if_nameindex().
69
 *
70
 *        #include <net/if.h>
71
 *
72
 *        void  if_freenameindex(struct if_nameindex *ptr);
73
 *
74
 *    The argument to this function must be a pointer that was returned by
75
 *    if_nameindex().
76
 */
77
78
struct if_nameindex *
79
if_nameindex(void)
80
{
81
	struct if_nameindex_msg *ifnm = NULL;
82
	struct if_nameindex *ifni = NULL, *ifni2;
83
	char *cp;
84
1022
	size_t needed;
85
	unsigned int ni, i;
86
511
	int mib[6];
87
88
511
	mib[0] = CTL_NET;
89
511
	mib[1] = PF_ROUTE;
90
511
	mib[2] = 0;		/* protocol */
91
511
	mib[3] = 0;		/* not used */
92
511
	mib[4] = NET_RT_IFNAMES;
93
511
	mib[5] = 0;		/* no flags */
94
511
	while (1) {
95
		struct if_nameindex_msg *buf = NULL;
96
97
511
		if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
98
			goto out;
99
511
		if (needed == 0)
100
			break;
101
511
		if ((buf = realloc(ifnm, needed)) == NULL)
102
			goto out;
103
		ifnm = buf;
104
511
		if (sysctl(mib, 6, ifnm, &needed, NULL, 0) == -1) {
105
			if (errno == ENOMEM)
106
				continue;
107
			goto out;
108
		}
109

511
		break;
110
	}
111
112
	/*
113
	 * Allocate a chunk of memory, use the first part for the array of
114
	 * structures, and the last part for the strings.
115
	 */
116
511
	ni = needed / sizeof(*ifnm);
117
511
	ifni = calloc(ni + 1, sizeof(struct if_nameindex) + IF_NAMESIZE);
118
511
	if (ifni == NULL)
119
		goto out;
120
511
	cp = (char *)(ifni + (ni + 1));
121
122
	ifni2 = ifni;
123
11984
	for (i = 0; i < ni; i++) {
124
5481
		ifni2->if_index = ifnm[i].if_index;
125
		/* don't care about truncation */
126
5481
		strlcpy(cp, ifnm[i].if_name, IF_NAMESIZE);
127
5481
		ifni2->if_name = cp;
128
5481
		ifni2++;
129
5481
		cp += IF_NAMESIZE;
130
	}
131
	/* Finally, terminate the array. */
132
511
	ifni2->if_index = 0;
133
511
	ifni2->if_name = NULL;
134
out:
135
511
	free(ifnm);
136
511
	return ifni;
137
511
}
138
139
void
140
if_freenameindex(struct if_nameindex *ptr)
141
{
142
1022
	free(ptr);
143
511
}
144
DEF_WEAK(if_nameindex);
145
DEF_WEAK(if_freenameindex);