Revert "mausezahn: Add error handling for mismatched address families"
[netsniff-ng-new.git] / dev.c
blob29609763b1d76d124554d8076fc1518b3bc93d14
1 #include <string.h>
2 #include <errno.h>
3 #include <sys/ioctl.h>
4 #include <sys/types.h>
5 #include <sys/socket.h>
6 #include <linux/if_arp.h>
7 #include <ifaddrs.h>
8 #include <arpa/inet.h>
10 #include "dev.h"
11 #include "str.h"
12 #include "sock.h"
13 #include "die.h"
14 #include "link.h"
15 #include "built_in.h"
17 int __device_ifindex(const char *ifname)
19 int ret, sock, index;
20 struct ifreq ifr;
22 if (!strncmp("any", ifname, strlen("any")))
23 return 0;
25 sock = af_socket(AF_INET);
27 memset(&ifr, 0, sizeof(ifr));
28 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
30 ret = ioctl(sock, SIOCGIFINDEX, &ifr);
31 if (ret)
32 index = -1;
33 else
34 index = ifr.ifr_ifindex;
36 close(sock);
38 return index;
41 int device_ifindex(const char *ifname)
43 int index = __device_ifindex(ifname);
45 if (unlikely(index < 0))
46 panic("Cannot get ifindex from device!\n");
48 return index;
51 int device_type(const char *ifname)
53 int ret, sock, type;
54 struct ifreq ifr;
56 if (!strncmp("any", ifname, strlen("any")))
57 return ARPHRD_ETHER;
59 sock = af_socket(AF_INET);
61 memset(&ifr, 0, sizeof(ifr));
62 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
64 ret = ioctl(sock, SIOCGIFHWADDR, &ifr);
65 if (unlikely(ret))
66 panic("Cannot get iftype from device!\n");
68 /* dev->type */
69 type = ifr.ifr_hwaddr.sa_family;
70 close(sock);
72 return type;
75 static int __device_address6(const char *ifname, struct sockaddr_storage *ss)
77 int ret, family, found = -EINVAL;
78 struct ifaddrs *ifaddr, *ifa;
80 ret = getifaddrs(&ifaddr);
81 if (unlikely(ret < 0))
82 panic("Cannot get device addresses for IPv6!\n");
84 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
85 family = ifa->ifa_addr->sa_family;
86 if (family != AF_INET6)
87 continue;
88 if (strcmp(ifa->ifa_name, ifname))
89 continue;
91 memcpy(ss, ifa->ifa_addr, sizeof(*ss));
92 found = 0;
93 break;
96 freeifaddrs(ifaddr);
97 return found;
100 int device_address(const char *ifname, int af, struct sockaddr_storage *ss)
102 int ret, sock;
103 struct ifreq ifr;
105 if (unlikely(!ss))
106 return -EINVAL;
107 if (!strncmp("any", ifname, strlen("any")))
108 return -EINVAL;
109 if (af == AF_INET6)
110 return __device_address6(ifname, ss);
112 sock = af_socket(af);
114 memset(&ifr, 0, sizeof(ifr));
115 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
117 ifr.ifr_addr.sa_family = af;
119 ret = ioctl(sock, SIOCGIFADDR, &ifr);
120 if (likely(!ret))
121 memcpy(ss, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
123 close(sock);
124 return ret;
127 int device_hw_address(const char *ifname, uint8_t *addr, size_t len)
129 int ret, sock;
130 struct ifreq ifr;
132 if (!addr)
133 return -EINVAL;
134 if (len < IFHWADDRLEN)
135 return -ENOSPC;
136 if (!strncmp("any", ifname, strlen("any")))
137 return -EINVAL;
139 sock = af_socket(AF_INET);
141 memset(&ifr, 0, sizeof(ifr));
142 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
144 ret = ioctl(sock, SIOCGIFHWADDR, &ifr);
145 if (!ret)
146 memcpy(addr, &ifr.ifr_hwaddr.sa_data[0], IFHWADDRLEN);
148 close(sock);
149 return ret;
152 size_t device_mtu(const char *ifname)
154 size_t mtu = 0;
155 int ret, sock;
156 struct ifreq ifr;
158 sock = af_socket(AF_INET);
160 memset(&ifr, 0, sizeof(ifr));
161 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
163 ret = ioctl(sock, SIOCGIFMTU, &ifr);
164 if (likely(!ret))
165 mtu = ifr.ifr_mtu;
167 close(sock);
168 return mtu;
171 short device_get_flags(const char *ifname)
173 short flags = 0;
174 int ret, sock;
175 struct ifreq ifr;
177 sock = af_socket(AF_INET);
179 memset(&ifr, 0, sizeof(ifr));
180 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
182 ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
183 if (likely(!ret))
184 flags = ifr.ifr_flags;
186 close(sock);
187 return flags;
190 void device_set_flags(const char *ifname, const short flags)
192 int ret, sock;
193 struct ifreq ifr;
195 sock = af_socket(AF_INET);
197 memset(&ifr, 0, sizeof(ifr));
198 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
199 ifr.ifr_flags = flags;
201 ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
202 if (unlikely(ret < 0))
203 panic("Cannot set NIC flags (%s)!\n", strerror(errno));
205 close(sock);
208 int device_up_and_running(const char *ifname)
210 if (!ifname)
211 return -EINVAL;
212 if (!strncmp("any", ifname, strlen("any")))
213 return 1;
215 return (device_get_flags(ifname) &
216 (IFF_UP | IFF_RUNNING)) ==
217 (IFF_UP | IFF_RUNNING);
220 u32 device_bitrate(const char *ifname)
222 u32 scopper, swireless;
224 scopper = ethtool_bitrate(ifname);
225 swireless = wireless_bitrate(ifname);
227 return scopper ? : swireless;
230 short device_enter_promiscuous_mode(const char *ifname)
232 short ifflags;
234 if (!strncmp("any", ifname, strlen("any")))
235 return 0;
237 ifflags = device_get_flags(ifname);
238 device_set_flags(ifname, ifflags | IFF_PROMISC);
240 return ifflags;
243 void device_leave_promiscuous_mode(const char *ifname, short oldflags)
245 if (!strncmp("any", ifname, strlen("any")))
246 return;
248 device_set_flags(ifname, oldflags);
251 const char *device_type2str(uint16_t type)
253 switch (type) {
254 case ARPHRD_ETHER:
255 return "ether";
256 case ARPHRD_EETHER:
257 return "eether";
258 case ARPHRD_AX25:
259 return "ax25";
260 case ARPHRD_PRONET:
261 return "pronet";
262 case ARPHRD_CHAOS:
263 return "chaos";
264 case ARPHRD_IEEE802:
265 return "ieee802";
266 case ARPHRD_ARCNET:
267 return "arcnet";
268 case ARPHRD_APPLETLK:
269 return "appletlk";
270 case ARPHRD_DLCI:
271 return "dlci";
272 case ARPHRD_ATM:
273 return "atm";
274 case ARPHRD_METRICOM:
275 return "metricom";
276 case ARPHRD_IEEE1394:
277 return "ieee1394";
278 case ARPHRD_INFINIBAND:
279 return "infiniband";
280 case ARPHRD_SLIP:
281 return "slip";
282 case ARPHRD_CSLIP:
283 return "cslip";
284 case ARPHRD_SLIP6:
285 return "slip6";
286 case ARPHRD_CSLIP6:
287 return "cslip6";
288 case ARPHRD_RSRVD:
289 return "RSRVD";
290 case ARPHRD_ADAPT:
291 return "adapt";
292 case ARPHRD_ROSE:
293 return "rose";
294 case ARPHRD_X25:
295 return "x25";
296 case ARPHRD_HWX25:
297 return "hwx25";
298 case ARPHRD_CAN:
299 return "can";
300 case ARPHRD_PPP:
301 return "ppp";
302 case ARPHRD_HDLC:
303 return "hdlc";
304 case ARPHRD_LAPB:
305 return "lapb";
306 case ARPHRD_DDCMP:
307 return "ddcmp";
308 case ARPHRD_RAWHDLC:
309 return "rawhdlc";
310 case ARPHRD_TUNNEL:
311 return "tunnel";
312 case ARPHRD_TUNNEL6:
313 return "tunnel6";
314 case ARPHRD_FRAD:
315 return "frad";
316 case ARPHRD_SKIP:
317 return "skip";
318 case ARPHRD_LOOPBACK:
319 return "loopback";
320 case ARPHRD_LOCALTLK:
321 return "localtlk";
322 case ARPHRD_FDDI:
323 return "fddi";
324 case ARPHRD_BIF:
325 return "bif";
326 case ARPHRD_SIT:
327 return "sit";
328 case ARPHRD_IPDDP:
329 return "ipddp";
330 case ARPHRD_IPGRE:
331 return "ipgre";
332 case ARPHRD_PIMREG:
333 return "pimreg";
334 case ARPHRD_HIPPI:
335 return "hippi";
336 case ARPHRD_ASH:
337 return "ash";
338 case ARPHRD_ECONET:
339 return "econet";
340 case ARPHRD_IRDA:
341 return "irda";
342 case ARPHRD_FCPP:
343 return "fcpp";
344 case ARPHRD_FCAL:
345 return "fcal";
346 case ARPHRD_FCPL:
347 return "fcpl";
348 case ARPHRD_FCFABRIC:
349 return "fcfb0";
350 case ARPHRD_FCFABRIC + 1:
351 return "fcfb1";
352 case ARPHRD_FCFABRIC + 2:
353 return "fcfb2";
354 case ARPHRD_FCFABRIC + 3:
355 return "fcfb3";
356 case ARPHRD_FCFABRIC + 4:
357 return "fcfb4";
358 case ARPHRD_FCFABRIC + 5:
359 return "fcfb5";
360 case ARPHRD_FCFABRIC + 6:
361 return "fcfb6";
362 case ARPHRD_FCFABRIC + 7:
363 return "fcfb7";
364 case ARPHRD_FCFABRIC + 8:
365 return "fcfb8";
366 case ARPHRD_FCFABRIC + 9:
367 return "fcfb9";
368 case ARPHRD_FCFABRIC + 10:
369 return "fcfb10";
370 case ARPHRD_FCFABRIC + 11:
371 return "fcfb11";
372 case ARPHRD_FCFABRIC + 12:
373 return "fcfb12";
374 case ARPHRD_IEEE802_TR:
375 return "ieee802_tr";
376 case ARPHRD_IEEE80211:
377 return "ieee80211";
378 case ARPHRD_IEEE80211_PRISM:
379 return "ieee80211_prism";
380 case ARPHRD_IEEE80211_RADIOTAP:
381 return "ieee80211_radiotap";
382 case ARPHRD_IEEE802154:
383 return "ieee802154";
384 case ARPHRD_PHONET:
385 return "phonet";
386 case ARPHRD_PHONET_PIPE:
387 return "phonet_pipe";
388 #if defined(ARPHRD_CAIF)
389 case ARPHRD_CAIF:
390 return "caif";
391 #endif
392 case ARPHRD_IP6GRE:
393 return "ip6gre";
394 case ARPHRD_NETLINK:
395 return "netlink";
396 case ARPHRD_NONE:
397 return "none";
398 case ARPHRD_VOID:
399 return "void";
400 default:
401 return "Unknown";
405 /* Taken from iproute2 ll_addr_n2a func */
406 const char *device_addr2str(const unsigned char *addr, int alen, int type,
407 char *buf, int blen)
409 int i, l;
411 if (alen == 4 &&
412 (type == ARPHRD_TUNNEL || type == ARPHRD_SIT ||
413 type == ARPHRD_IPGRE))
414 return inet_ntop(AF_INET, addr, buf, blen);
416 if (alen == 16 && type == ARPHRD_TUNNEL6)
417 return inet_ntop(AF_INET6, addr, buf, blen);
419 for (l = 0, i = 0; i < alen; i++) {
420 if (i == 0) {
421 snprintf(buf + l, blen, "%02x", addr[i]);
422 blen -= 2;
423 l += 2;
424 } else {
425 snprintf(buf + l, blen, ":%02x", addr[i]);
426 blen -= 3;
427 l += 3;
431 return buf;