blob: ed99cbf61193d5d3dd053e8fc91c41e71f8d4343 [file] [log] [blame]
James Kuszmaul82f6c042021-01-17 11:30:16 -08001/**
2 * @file net/if.c Network interface code
3 *
4 * Copyright (C) 2010 Creytiv.com
5 */
6#include <re_types.h>
7#include <re_fmt.h>
8#include <re_mbuf.h>
9#include <re_sa.h>
10#include <re_net.h>
11
12
13#define DEBUG_MODULE "netif"
14#define DEBUG_LEVEL 5
15#include <re_dbg.h>
16
17
18/** Interface address entry */
19struct ifentry {
20 int af; /**< Address family */
21 char *ifname; /**< Interface name */
22 struct sa *ip; /**< IP address */
23 size_t sz; /**< Size of buffer */
24 bool found; /**< Found flag */
25};
26
27
28static bool if_getname_handler(const char *ifname, const struct sa *sa,
29 void *arg)
30{
31 struct ifentry *ife = arg;
32
33 if (ife->af != sa_af(sa))
34 return false;
35
36 if (sa_cmp(sa, ife->ip, SA_ADDR)) {
37 str_ncpy(ife->ifname, ifname, ife->sz);
38 ife->found = true;
39 return true;
40 }
41
42 return false;
43}
44
45
46/**
47 * Get the name of the interface for a given IP address
48 *
49 * @param ifname Buffer for returned network interface name
50 * @param sz Size of buffer
51 * @param af Address Family
52 * @param ip Given IP address
53 *
54 * @return 0 if success, otherwise errorcode
55 */
56int net_if_getname(char *ifname, size_t sz, int af, const struct sa *ip)
57{
58 struct ifentry ife;
59 int err;
60
61 if (!ifname || !sz || !ip)
62 return EINVAL;
63
64 ife.af = af;
65 ife.ifname = ifname;
66 ife.ip = (struct sa *)ip;
67 ife.sz = sz;
68 ife.found = false;
69
70 err = net_if_list(if_getname_handler, &ife);
71
72 return ife.found ? err : ENODEV;
73}
74
75
76static bool if_getaddr_handler(const char *ifname,
77 const struct sa *sa, void *arg)
78{
79 struct ifentry *ife = arg;
80
81 /* Match name of interface? */
82 if (str_isset(ife->ifname) && 0 != str_casecmp(ife->ifname, ifname))
83 return false;
84
85 if (!sa_isset(sa, SA_ADDR))
86 return false;
87
88#if 1
89 /* skip loopback and link-local IP */
90 if (sa_is_loopback(sa) || sa_is_linklocal(sa))
91 return false;
92#endif
93
94 /* Match address family */
95 if (ife->af != sa_af(sa))
96 return false;
97
98 /* Match - copy address */
99 sa_cpy(ife->ip, sa);
100 ife->found = true;
101
102 return ife->found;
103}
104
105
106/**
107 * Get IP address for a given network interface
108 *
109 * @param ifname Network interface name (optional)
110 * @param af Address Family
111 * @param ip Returned IP address
112 *
113 * @return 0 if success, otherwise errorcode
114 *
115 * @deprecated Works for IPv4 only
116 */
117int net_if_getaddr(const char *ifname, int af, struct sa *ip)
118{
119 struct ifentry ife;
120 int err;
121
122 if (!ip)
123 return EINVAL;
124
125 ife.af = af;
126 ife.ifname = (char *)ifname;
127 ife.ip = ip;
128 ife.sz = 0;
129 ife.found = false;
130
131#ifdef HAVE_GETIFADDRS
132 err = net_getifaddrs(if_getaddr_handler, &ife);
133#else
134 err = net_if_list(if_getaddr_handler, &ife);
135#endif
136
137 return ife.found ? err : ENODEV;
138}
139
140
141static bool if_debug_handler(const char *ifname, const struct sa *sa,
142 void *arg)
143{
144 struct re_printf *pf = arg;
145
146 (void)re_hprintf(pf, " %10s: %j\n", ifname, sa);
147
148 return false;
149}
150
151
152/**
153 * Debug network interfaces
154 *
155 * @param pf Print handler for debug output
156 * @param unused Unused parameter
157 *
158 * @return 0 if success, otherwise errorcode
159 */
160int net_if_debug(struct re_printf *pf, void *unused)
161{
162 int err;
163
164 (void)unused;
165
166 err = re_hprintf(pf, "net interfaces:\n");
167
168#ifdef HAVE_GETIFADDRS
169 err |= net_getifaddrs(if_debug_handler, pf);
170#else
171 err |= net_if_list(if_debug_handler, pf);
172#endif
173
174 return err;
175}
176
177
178static bool linklocal_handler(const char *ifname, const struct sa *sa,
179 void *arg)
180{
181 void **argv = arg;
182 int af = *(int *)argv[1];
183
184 if (argv[0] && 0 != str_casecmp(argv[0], ifname))
185 return false;
186
187 if (af != AF_UNSPEC && af != sa_af(sa))
188 return false;
189
190 if (sa_is_linklocal(sa)) {
191 *((struct sa *)argv[2]) = *sa;
192 return true;
193 }
194
195 return false;
196}
197
198
199/**
200 * Get the Link-local address for a specific network interface
201 *
202 * @param ifname Name of the interface
203 * @param af Address family
204 * @param ip Returned link-local address
205 *
206 * @return 0 if success, otherwise errorcode
207 */
208int net_if_getlinklocal(const char *ifname, int af, struct sa *ip)
209{
210 struct sa addr;
211 void *argv[3];
212 int err;
213
214 if (!ip)
215 return EINVAL;
216
217 sa_init(&addr, sa_af(ip));
218
219 argv[0] = (void *)ifname;
220 argv[1] = &af;
221 argv[2] = &addr;
222
223 err = net_if_apply(linklocal_handler, argv);
224 if (err)
225 return err;
226
227 if (!sa_isset(&addr, SA_ADDR))
228 return ENOENT;
229
230 *ip = addr;
231
232 return 0;
233}