1 /**
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 */
19 struct 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
if_getname_handler(const char * ifname,const struct sa * sa,void * arg)28 static 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 (0 == 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 */
net_if_getname(char * ifname,size_t sz,int af,const struct sa * ip)56 int 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
if_getaddr_handler(const char * ifname,const struct sa * sa,void * arg)76 static 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 */
net_if_getaddr(const char * ifname,int af,struct sa * ip)117 int 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
if_debug_handler(const char * ifname,const struct sa * sa,void * arg)141 static 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 */
net_if_debug(struct re_printf * pf,void * unused)160 int 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
linklocal_handler(const char * ifname,const struct sa * sa,void * arg)178 static 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 */
net_if_getlinklocal(const char * ifname,int af,struct sa * ip)208 int 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] = ⁡
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 }
234