grrr...fix reverse chronological order
[dragonfly.git] / lib / libcr / net / if_nameindex.c
1 /*      $KAME: if_nameindex.c,v 1.8 2000/11/24 08:20:01 itojun Exp $    */
2
3 /*-
4  * Copyright (c) 1997, 2000
5  *      Berkeley Software Design, Inc.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  *      BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
26  *
27  * $FreeBSD: src/lib/libc/net/if_nameindex.c,v 1.1.2.1 2002/07/29 18:33:18 ume Exp $
28  * $DragonFly: src/lib/libcr/net/Attic/if_nameindex.c,v 1.2 2003/06/17 04:26:44 dillon Exp $
29  */
30
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <net/if_dl.h>
34 #include <net/if.h>
35 #include <ifaddrs.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 /*
40  * From RFC 2553:
41  *
42  * 4.3 Return All Interface Names and Indexes
43  *
44  *    The if_nameindex structure holds the information about a single
45  *    interface and is defined as a result of including the <net/if.h>
46  *    header.
47  *
48  *       struct if_nameindex {
49  *         unsigned int   if_index;
50  *         char          *if_name;
51  *       };
52  *
53  *    The final function returns an array of if_nameindex structures, one
54  *    structure per interface.
55  *
56  *       struct if_nameindex  *if_nameindex(void);
57  *
58  *    The end of the array of structures is indicated by a structure with
59  *    an if_index of 0 and an if_name of NULL.  The function returns a NULL
60  *    pointer upon an error, and would set errno to the appropriate value.
61  *
62  *    The memory used for this array of structures along with the interface
63  *    names pointed to by the if_name members is obtained dynamically.
64  *    This memory is freed by the next function.
65  *
66  * 4.4.  Free Memory
67  *
68  *    The following function frees the dynamic memory that was allocated by
69  *    if_nameindex().
70  *
71  *        #include <net/if.h>
72  *
73  *        void  if_freenameindex(struct if_nameindex *ptr);
74  *
75  *    The argument to this function must be a pointer that was returned by
76  *    if_nameindex().
77  */
78
79 struct if_nameindex *
80 if_nameindex(void)
81 {
82         struct ifaddrs *ifaddrs, *ifa;
83         unsigned int ni;
84         int nbytes;
85         struct if_nameindex *ifni, *ifni2;
86         char *cp;
87
88         if (getifaddrs(&ifaddrs) < 0)
89                 return(NULL);
90
91         /*
92          * First, find out how many interfaces there are, and how
93          * much space we need for the string names.
94          */
95         ni = 0;
96         nbytes = 0;
97         for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
98                 if (ifa->ifa_addr &&
99                     ifa->ifa_addr->sa_family == AF_LINK) {
100                         nbytes += strlen(ifa->ifa_name) + 1;
101                         ni++;
102                 }
103         }
104
105         /*
106          * Next, allocate a chunk of memory, use the first part
107          * for the array of structures, and the last part for
108          * the strings.
109          */
110         cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes);
111         ifni = (struct if_nameindex *)cp;
112         if (ifni == NULL)
113                 goto out;
114         cp += (ni + 1) * sizeof(struct if_nameindex);
115
116         /*
117          * Now just loop through the list of interfaces again,
118          * filling in the if_nameindex array and making copies
119          * of all the strings.
120          */
121         ifni2 = ifni;
122         for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
123                 if (ifa->ifa_addr &&
124                     ifa->ifa_addr->sa_family == AF_LINK) {
125                         ifni2->if_index =
126                             ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
127                         ifni2->if_name = cp;
128                         strcpy(cp, ifa->ifa_name);
129                         ifni2++;
130                         cp += strlen(cp) + 1;
131                 }
132         }
133         /*
134          * Finally, don't forget to terminate the array.
135          */
136         ifni2->if_index = 0;
137         ifni2->if_name = NULL;
138 out:
139         freeifaddrs(ifaddrs);
140         return(ifni);
141 }
142
143 void
144 if_freenameindex(struct if_nameindex *ptr)
145 {
146         free(ptr);
147 }