astraceroute: use switch instead of lookup table for short proto id
[netsniff-ng.git] / dev.c
blob2ced4955b0aa5b3dd0e7b62eac1467f39c808a5e
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 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 uint32_t device_bitrate(const char *ifname)
222 uint32_t scopper;
224 scopper = ethtool_bitrate(ifname);
226 return scopper ? : wireless_bitrate(ifname);
229 short device_enter_promiscuous_mode(const char *ifname)
231 short ifflags;
233 if (!strncmp("any", ifname, strlen("any")))
234 return 0;
236 ifflags = device_get_flags(ifname);
237 device_set_flags(ifname, ifflags | IFF_PROMISC);
239 return ifflags;
242 void device_leave_promiscuous_mode(const char *ifname, short oldflags)
244 if (!strncmp("any", ifname, strlen("any")))
245 return;
247 device_set_flags(ifname, oldflags);
250 const char *device_type2str(uint16_t type)
252 switch (type) {
253 case ARPHRD_ETHER:
254 return "ether";
255 case ARPHRD_EETHER:
256 return "eether";
257 case ARPHRD_AX25:
258 return "ax25";
259 case ARPHRD_PRONET:
260 return "pronet";
261 case ARPHRD_CHAOS:
262 return "chaos";
263 case ARPHRD_IEEE802:
264 return "ieee802";
265 case ARPHRD_ARCNET:
266 return "arcnet";
267 case ARPHRD_APPLETLK:
268 return "appletlk";
269 case ARPHRD_DLCI:
270 return "dlci";
271 case ARPHRD_ATM:
272 return "atm";
273 case ARPHRD_METRICOM:
274 return "metricom";
275 case ARPHRD_IEEE1394:
276 return "ieee1394";
277 case ARPHRD_INFINIBAND:
278 return "infiniband";
279 case ARPHRD_SLIP:
280 return "slip";
281 case ARPHRD_CSLIP:
282 return "cslip";
283 case ARPHRD_SLIP6:
284 return "slip6";
285 case ARPHRD_CSLIP6:
286 return "cslip6";
287 case ARPHRD_RSRVD:
288 return "RSRVD";
289 case ARPHRD_ADAPT:
290 return "adapt";
291 case ARPHRD_ROSE:
292 return "rose";
293 case ARPHRD_X25:
294 return "x25";
295 case ARPHRD_HWX25:
296 return "hwx25";
297 case ARPHRD_CAN:
298 return "can";
299 case ARPHRD_PPP:
300 return "ppp";
301 case ARPHRD_HDLC:
302 return "hdlc";
303 case ARPHRD_LAPB:
304 return "lapb";
305 case ARPHRD_DDCMP:
306 return "ddcmp";
307 case ARPHRD_RAWHDLC:
308 return "rawhdlc";
309 case ARPHRD_TUNNEL:
310 return "tunnel";
311 case ARPHRD_TUNNEL6:
312 return "tunnel6";
313 case ARPHRD_FRAD:
314 return "frad";
315 case ARPHRD_SKIP:
316 return "skip";
317 case ARPHRD_LOOPBACK:
318 return "loopback";
319 case ARPHRD_LOCALTLK:
320 return "localtlk";
321 case ARPHRD_FDDI:
322 return "fddi";
323 case ARPHRD_BIF:
324 return "bif";
325 case ARPHRD_SIT:
326 return "sit";
327 case ARPHRD_IPDDP:
328 return "ipddp";
329 case ARPHRD_IPGRE:
330 return "ipgre";
331 case ARPHRD_PIMREG:
332 return "pimreg";
333 case ARPHRD_HIPPI:
334 return "hippi";
335 case ARPHRD_ASH:
336 return "ash";
337 case ARPHRD_ECONET:
338 return "econet";
339 case ARPHRD_IRDA:
340 return "irda";
341 case ARPHRD_FCPP:
342 return "fcpp";
343 case ARPHRD_FCAL:
344 return "fcal";
345 case ARPHRD_FCPL:
346 return "fcpl";
347 case ARPHRD_FCFABRIC:
348 return "fcfb0";
349 case ARPHRD_FCFABRIC + 1:
350 return "fcfb1";
351 case ARPHRD_FCFABRIC + 2:
352 return "fcfb2";
353 case ARPHRD_FCFABRIC + 3:
354 return "fcfb3";
355 case ARPHRD_FCFABRIC + 4:
356 return "fcfb4";
357 case ARPHRD_FCFABRIC + 5:
358 return "fcfb5";
359 case ARPHRD_FCFABRIC + 6:
360 return "fcfb6";
361 case ARPHRD_FCFABRIC + 7:
362 return "fcfb7";
363 case ARPHRD_FCFABRIC + 8:
364 return "fcfb8";
365 case ARPHRD_FCFABRIC + 9:
366 return "fcfb9";
367 case ARPHRD_FCFABRIC + 10:
368 return "fcfb10";
369 case ARPHRD_FCFABRIC + 11:
370 return "fcfb11";
371 case ARPHRD_FCFABRIC + 12:
372 return "fcfb12";
373 case ARPHRD_IEEE802_TR:
374 return "ieee802_tr";
375 case ARPHRD_IEEE80211:
376 return "ieee80211";
377 case ARPHRD_IEEE80211_PRISM:
378 return "ieee80211_prism";
379 case ARPHRD_IEEE80211_RADIOTAP:
380 return "ieee80211_radiotap";
381 case ARPHRD_IEEE802154:
382 return "ieee802154";
383 case ARPHRD_PHONET:
384 return "phonet";
385 case ARPHRD_PHONET_PIPE:
386 return "phonet_pipe";
387 case ARPHRD_CAIF:
388 return "caif";
389 case ARPHRD_IP6GRE:
390 return "ip6gre";
391 case ARPHRD_NETLINK:
392 return "netlink";
393 case ARPHRD_NONE:
394 return "none";
395 case ARPHRD_VOID:
396 return "void";
397 default:
398 return "Unknown";
402 /* Taken from iproute2 ll_addr_n2a func */
403 const char *device_addr2str(const unsigned char *addr, int alen, int type,
404 char *buf, int blen)
406 int i, l;
408 if (alen == 4 &&
409 (type == ARPHRD_TUNNEL || type == ARPHRD_SIT ||
410 type == ARPHRD_IPGRE))
411 return inet_ntop(AF_INET, addr, buf, blen);
413 if (alen == 16 && type == ARPHRD_TUNNEL6)
414 return inet_ntop(AF_INET6, addr, buf, blen);
416 snprintf(buf, blen, "%02x", addr[0]);
417 for (i = 1, l = 2; i < alen && l < blen; i++, l += 3)
418 snprintf(buf + l, blen - l, ":%02x", addr[i]);
420 return buf;