netsniff-ng: dissector_sll: Fix potential NULL dereference
[netsniff-ng.git] / dev.c
blobcf8d6435054b4065f0ad75fa8685549eddde7315
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 size_t device_mtu(const char *ifname)
129 size_t mtu = 0;
130 int ret, sock;
131 struct ifreq ifr;
133 sock = af_socket(AF_INET);
135 memset(&ifr, 0, sizeof(ifr));
136 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
138 ret = ioctl(sock, SIOCGIFMTU, &ifr);
139 if (likely(!ret))
140 mtu = ifr.ifr_mtu;
142 close(sock);
143 return mtu;
146 short device_get_flags(const char *ifname)
148 short flags = 0;
149 int ret, sock;
150 struct ifreq ifr;
152 sock = af_socket(AF_INET);
154 memset(&ifr, 0, sizeof(ifr));
155 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
157 ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
158 if (likely(!ret))
159 flags = ifr.ifr_flags;
161 close(sock);
162 return flags;
165 void device_set_flags(const char *ifname, const short flags)
167 int ret, sock;
168 struct ifreq ifr;
170 sock = af_socket(AF_INET);
172 memset(&ifr, 0, sizeof(ifr));
173 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
174 ifr.ifr_flags = flags;
176 ret = ioctl(sock, SIOCSIFFLAGS, &ifr);
177 if (unlikely(ret < 0))
178 panic("Cannot set NIC flags (%s)!\n", strerror(errno));
180 close(sock);
183 int device_up_and_running(const char *ifname)
185 if (!ifname)
186 return -EINVAL;
187 if (!strncmp("any", ifname, strlen("any")))
188 return 1;
190 return (device_get_flags(ifname) &
191 (IFF_UP | IFF_RUNNING)) ==
192 (IFF_UP | IFF_RUNNING);
195 u32 device_bitrate(const char *ifname)
197 u32 scopper, swireless;
199 scopper = ethtool_bitrate(ifname);
200 swireless = wireless_bitrate(ifname);
202 return scopper ? : swireless;
205 short device_enter_promiscuous_mode(const char *ifname)
207 short ifflags;
209 if (!strncmp("any", ifname, strlen("any")))
210 return 0;
212 ifflags = device_get_flags(ifname);
213 device_set_flags(ifname, ifflags | IFF_PROMISC);
215 return ifflags;
218 void device_leave_promiscuous_mode(const char *ifname, short oldflags)
220 if (!strncmp("any", ifname, strlen("any")))
221 return;
223 device_set_flags(ifname, oldflags);
226 const char *device_type2str(uint16_t type)
228 switch (type) {
229 case ARPHRD_ETHER:
230 return "ether";
231 case ARPHRD_EETHER:
232 return "eether";
233 case ARPHRD_AX25:
234 return "ax25";
235 case ARPHRD_PRONET:
236 return "pronet";
237 case ARPHRD_CHAOS:
238 return "chaos";
239 case ARPHRD_IEEE802:
240 return "ieee802";
241 case ARPHRD_ARCNET:
242 return "arcnet";
243 case ARPHRD_APPLETLK:
244 return "appletlk";
245 case ARPHRD_DLCI:
246 return "dlci";
247 case ARPHRD_ATM:
248 return "atm";
249 case ARPHRD_METRICOM:
250 return "metricom";
251 case ARPHRD_IEEE1394:
252 return "ieee1394";
253 case ARPHRD_INFINIBAND:
254 return "infiniband";
255 case ARPHRD_SLIP:
256 return "slip";
257 case ARPHRD_CSLIP:
258 return "cslip";
259 case ARPHRD_SLIP6:
260 return "slip6";
261 case ARPHRD_CSLIP6:
262 return "cslip6";
263 case ARPHRD_RSRVD:
264 return "RSRVD";
265 case ARPHRD_ADAPT:
266 return "adapt";
267 case ARPHRD_ROSE:
268 return "rose";
269 case ARPHRD_X25:
270 return "x25";
271 case ARPHRD_HWX25:
272 return "hwx25";
273 case ARPHRD_CAN:
274 return "can";
275 case ARPHRD_PPP:
276 return "ppp";
277 case ARPHRD_HDLC:
278 return "hdlc";
279 case ARPHRD_LAPB:
280 return "lapb";
281 case ARPHRD_DDCMP:
282 return "ddcmp";
283 case ARPHRD_RAWHDLC:
284 return "rawhdlc";
285 case ARPHRD_TUNNEL:
286 return "tunnel";
287 case ARPHRD_TUNNEL6:
288 return "tunnel6";
289 case ARPHRD_FRAD:
290 return "frad";
291 case ARPHRD_SKIP:
292 return "skip";
293 case ARPHRD_LOOPBACK:
294 return "loopback";
295 case ARPHRD_LOCALTLK:
296 return "localtlk";
297 case ARPHRD_FDDI:
298 return "fddi";
299 case ARPHRD_BIF:
300 return "bif";
301 case ARPHRD_SIT:
302 return "sit";
303 case ARPHRD_IPDDP:
304 return "ipddp";
305 case ARPHRD_IPGRE:
306 return "ipgre";
307 case ARPHRD_PIMREG:
308 return "pimreg";
309 case ARPHRD_HIPPI:
310 return "hippi";
311 case ARPHRD_ASH:
312 return "ash";
313 case ARPHRD_ECONET:
314 return "econet";
315 case ARPHRD_IRDA:
316 return "irda";
317 case ARPHRD_FCPP:
318 return "fcpp";
319 case ARPHRD_FCAL:
320 return "fcal";
321 case ARPHRD_FCPL:
322 return "fcpl";
323 case ARPHRD_FCFABRIC:
324 return "fcfb0";
325 case ARPHRD_FCFABRIC + 1:
326 return "fcfb1";
327 case ARPHRD_FCFABRIC + 2:
328 return "fcfb2";
329 case ARPHRD_FCFABRIC + 3:
330 return "fcfb3";
331 case ARPHRD_FCFABRIC + 4:
332 return "fcfb4";
333 case ARPHRD_FCFABRIC + 5:
334 return "fcfb5";
335 case ARPHRD_FCFABRIC + 6:
336 return "fcfb6";
337 case ARPHRD_FCFABRIC + 7:
338 return "fcfb7";
339 case ARPHRD_FCFABRIC + 8:
340 return "fcfb8";
341 case ARPHRD_FCFABRIC + 9:
342 return "fcfb9";
343 case ARPHRD_FCFABRIC + 10:
344 return "fcfb10";
345 case ARPHRD_FCFABRIC + 11:
346 return "fcfb11";
347 case ARPHRD_FCFABRIC + 12:
348 return "fcfb12";
349 case ARPHRD_IEEE802_TR:
350 return "ieee802_tr";
351 case ARPHRD_IEEE80211:
352 return "ieee80211";
353 case ARPHRD_IEEE80211_PRISM:
354 return "ieee80211_prism";
355 case ARPHRD_IEEE80211_RADIOTAP:
356 return "ieee80211_radiotap";
357 case ARPHRD_IEEE802154:
358 return "ieee802154";
359 case ARPHRD_PHONET:
360 return "phonet";
361 case ARPHRD_PHONET_PIPE:
362 return "phonet_pipe";
363 case ARPHRD_CAIF:
364 return "caif";
365 case ARPHRD_IP6GRE:
366 return "ip6gre";
367 case ARPHRD_NETLINK:
368 return "netlink";
369 case ARPHRD_NONE:
370 return "none";
371 case ARPHRD_VOID:
372 return "void";
373 default:
374 return "Unknown";
378 /* Taken from iproute2 ll_addr_n2a func */
379 const char *device_addr2str(const unsigned char *addr, int alen, int type,
380 char *buf, int blen)
382 int i, l;
384 if (alen == 4 &&
385 (type == ARPHRD_TUNNEL || type == ARPHRD_SIT ||
386 type == ARPHRD_IPGRE))
387 return inet_ntop(AF_INET, addr, buf, blen);
389 if (alen == 16 && type == ARPHRD_TUNNEL6)
390 return inet_ntop(AF_INET6, addr, buf, blen);
392 for (l = 0, i = 0; i < alen; i++) {
393 if (i == 0) {
394 snprintf(buf + l, blen, "%02x", addr[i]);
395 blen -= 2;
396 l += 2;
397 } else {
398 snprintf(buf + l, blen, ":%02x", addr[i]);
399 blen -= 3;
400 l += 3;
404 return buf;