ring_tx: handle EINTR from sendto
[netsniff-ng.git] / dev.c
bloba4f2b0e165d281d8b3d68fee54102c4137a667c6
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 <net/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 if (ifa->ifa_addr == NULL)
86 continue;
87 family = ifa->ifa_addr->sa_family;
88 if (family != AF_INET6)
89 continue;
90 if (strcmp(ifa->ifa_name, ifname))
91 continue;
93 memcpy(ss, ifa->ifa_addr, sizeof(*ss));
94 found = 0;
95 break;
98 freeifaddrs(ifaddr);
99 return found;
102 int device_address(const char *ifname, int af, struct sockaddr_storage *ss)
104 int ret, sock;
105 struct ifreq ifr;
107 if (unlikely(!ss))
108 return -EINVAL;
109 if (!strncmp("any", ifname, strlen("any")))
110 return -EINVAL;
111 if (af == AF_INET6)
112 return __device_address6(ifname, ss);
114 sock = af_socket(af);
116 memset(&ifr, 0, sizeof(ifr));
117 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
119 ifr.ifr_addr.sa_family = af;
121 ret = ioctl(sock, SIOCGIFADDR, &ifr);
122 if (likely(!ret))
123 memcpy(ss, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
125 close(sock);
126 return ret;
129 int device_hw_address(const char *ifname, uint8_t *addr, size_t len)
131 int ret, sock;
132 struct ifreq ifr;
134 if (!addr)
135 return -EINVAL;
136 if (len < IFHWADDRLEN)
137 return -ENOSPC;
138 if (!strncmp("any", ifname, strlen("any")))
139 return -EINVAL;
141 sock = af_socket(AF_INET);
143 memset(&ifr, 0, sizeof(ifr));
144 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
146 ret = ioctl(sock, SIOCGIFHWADDR, &ifr);
147 if (!ret)
148 memcpy(addr, &ifr.ifr_hwaddr.sa_data[0], IFHWADDRLEN);
150 close(sock);
151 return ret;
154 size_t device_mtu(const char *ifname)
156 size_t mtu = 0;
157 int ret, sock;
158 struct ifreq ifr;
160 sock = af_socket(AF_INET);
162 memset(&ifr, 0, sizeof(ifr));
163 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
165 ret = ioctl(sock, SIOCGIFMTU, &ifr);
166 if (likely(!ret))
167 mtu = ifr.ifr_mtu;
169 close(sock);
170 return mtu;
173 short device_get_flags(const char *ifname)
175 short flags = 0;
176 int ret, sock;
177 struct ifreq ifr;
179 sock = af_socket(AF_INET);
181 memset(&ifr, 0, sizeof(ifr));
182 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
184 ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
185 if (likely(!ret))
186 flags = ifr.ifr_flags;
188 close(sock);
189 return flags;
192 void device_set_flags(const char *ifname, const short flags)
194 int ret, sock;
195 struct ifreq ifr;
197 sock = af_socket(AF_INET);
199 memset(&ifr, 0, sizeof(ifr));
200 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
201 ifr.ifr_flags = flags;
203 ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
204 if (unlikely(ret < 0))
205 panic("Cannot set NIC flags (%s)!\n", strerror(errno));
207 close(sock);
210 int device_up_and_running(const char *ifname)
212 if (!ifname)
213 return -EINVAL;
214 if (!strncmp("any", ifname, strlen("any")))
215 return 1;
217 return (device_get_flags(ifname) &
218 (IFF_UP | IFF_RUNNING)) ==
219 (IFF_UP | IFF_RUNNING);
222 uint32_t device_bitrate(const char *ifname)
224 uint32_t scopper;
226 scopper = ethtool_bitrate(ifname);
228 return scopper ? : wireless_bitrate(ifname);
231 short device_enter_promiscuous_mode(const char *ifname)
233 short ifflags;
235 if (!strncmp("any", ifname, strlen("any")))
236 return 0;
238 ifflags = device_get_flags(ifname);
239 device_set_flags(ifname, ifflags | IFF_PROMISC);
241 return ifflags;
244 void device_leave_promiscuous_mode(const char *ifname, short oldflags)
246 if (!strncmp("any", ifname, strlen("any")))
247 return;
249 device_set_flags(ifname, oldflags);
252 const char *device_type2str(uint16_t type)
254 switch (type) {
255 case ARPHRD_ETHER:
256 return "ether";
257 case ARPHRD_EETHER:
258 return "eether";
259 case ARPHRD_AX25:
260 return "ax25";
261 case ARPHRD_PRONET:
262 return "pronet";
263 case ARPHRD_CHAOS:
264 return "chaos";
265 case ARPHRD_IEEE802:
266 return "ieee802";
267 case ARPHRD_ARCNET:
268 return "arcnet";
269 case ARPHRD_APPLETLK:
270 return "appletlk";
271 case ARPHRD_DLCI:
272 return "dlci";
273 case ARPHRD_ATM:
274 return "atm";
275 case ARPHRD_METRICOM:
276 return "metricom";
277 case ARPHRD_IEEE1394:
278 return "ieee1394";
279 case ARPHRD_INFINIBAND:
280 return "infiniband";
281 case ARPHRD_SLIP:
282 return "slip";
283 case ARPHRD_CSLIP:
284 return "cslip";
285 case ARPHRD_SLIP6:
286 return "slip6";
287 case ARPHRD_CSLIP6:
288 return "cslip6";
289 case ARPHRD_RSRVD:
290 return "RSRVD";
291 case ARPHRD_ADAPT:
292 return "adapt";
293 case ARPHRD_ROSE:
294 return "rose";
295 case ARPHRD_X25:
296 return "x25";
297 case ARPHRD_HWX25:
298 return "hwx25";
299 case ARPHRD_CAN:
300 return "can";
301 case ARPHRD_PPP:
302 return "ppp";
303 case ARPHRD_HDLC:
304 return "hdlc";
305 case ARPHRD_LAPB:
306 return "lapb";
307 case ARPHRD_DDCMP:
308 return "ddcmp";
309 case ARPHRD_RAWHDLC:
310 return "rawhdlc";
311 case ARPHRD_TUNNEL:
312 return "tunnel";
313 case ARPHRD_TUNNEL6:
314 return "tunnel6";
315 case ARPHRD_FRAD:
316 return "frad";
317 case ARPHRD_SKIP:
318 return "skip";
319 case ARPHRD_LOOPBACK:
320 return "loopback";
321 case ARPHRD_LOCALTLK:
322 return "localtlk";
323 case ARPHRD_FDDI:
324 return "fddi";
325 case ARPHRD_BIF:
326 return "bif";
327 case ARPHRD_SIT:
328 return "sit";
329 case ARPHRD_IPDDP:
330 return "ipddp";
331 case ARPHRD_IPGRE:
332 return "ipgre";
333 case ARPHRD_PIMREG:
334 return "pimreg";
335 case ARPHRD_HIPPI:
336 return "hippi";
337 case ARPHRD_ASH:
338 return "ash";
339 case ARPHRD_ECONET:
340 return "econet";
341 case ARPHRD_IRDA:
342 return "irda";
343 case ARPHRD_FCPP:
344 return "fcpp";
345 case ARPHRD_FCAL:
346 return "fcal";
347 case ARPHRD_FCPL:
348 return "fcpl";
349 case ARPHRD_FCFABRIC:
350 return "fcfb0";
351 case ARPHRD_FCFABRIC + 1:
352 return "fcfb1";
353 case ARPHRD_FCFABRIC + 2:
354 return "fcfb2";
355 case ARPHRD_FCFABRIC + 3:
356 return "fcfb3";
357 case ARPHRD_FCFABRIC + 4:
358 return "fcfb4";
359 case ARPHRD_FCFABRIC + 5:
360 return "fcfb5";
361 case ARPHRD_FCFABRIC + 6:
362 return "fcfb6";
363 case ARPHRD_FCFABRIC + 7:
364 return "fcfb7";
365 case ARPHRD_FCFABRIC + 8:
366 return "fcfb8";
367 case ARPHRD_FCFABRIC + 9:
368 return "fcfb9";
369 case ARPHRD_FCFABRIC + 10:
370 return "fcfb10";
371 case ARPHRD_FCFABRIC + 11:
372 return "fcfb11";
373 case ARPHRD_FCFABRIC + 12:
374 return "fcfb12";
375 case ARPHRD_IEEE802_TR:
376 return "ieee802_tr";
377 case ARPHRD_IEEE80211:
378 return "ieee80211";
379 case ARPHRD_IEEE80211_PRISM:
380 return "ieee80211_prism";
381 case ARPHRD_IEEE80211_RADIOTAP:
382 return "ieee80211_radiotap";
383 case ARPHRD_IEEE802154:
384 return "ieee802154";
385 case ARPHRD_PHONET:
386 return "phonet";
387 case ARPHRD_PHONET_PIPE:
388 return "phonet_pipe";
389 case ARPHRD_CAIF:
390 return "caif";
391 case ARPHRD_IP6GRE:
392 return "ip6gre";
393 case ARPHRD_NETLINK:
394 return "netlink";
395 case ARPHRD_NONE:
396 return "none";
397 case ARPHRD_VOID:
398 return "void";
399 default:
400 return "Unknown";
404 /* Taken from iproute2 ll_addr_n2a func */
405 const char *device_addr2str(const unsigned char *addr, int alen, int type,
406 char *buf, int blen)
408 int i, l;
410 if (alen == 4 &&
411 (type == ARPHRD_TUNNEL || type == ARPHRD_SIT ||
412 type == ARPHRD_IPGRE))
413 return inet_ntop(AF_INET, addr, buf, blen);
415 if (alen == 16 && type == ARPHRD_TUNNEL6)
416 return inet_ntop(AF_INET6, addr, buf, blen);
418 snprintf(buf, blen, "%02x", addr[0]);
419 for (i = 1, l = 2; i < alen && l < blen; i++, l += 3)
420 snprintf(buf + l, blen - l, ":%02x", addr[i]);
422 return buf;