suricata
util-ioctl.c
Go to the documentation of this file.
1 /* Copyright (C) 2010 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Eric Leblond <eric@regit.org>
22  * \author Victor Julien <victor@inliniac.net>
23  */
24 
25 #include "suricata-common.h"
26 #include "conf.h"
27 #include "util-device.h"
28 
29 #ifdef HAVE_SYS_IOCTL_H
30 #include <sys/ioctl.h>
31 #endif
32 
33 #ifdef HAVE_LINUX_ETHTOOL_H
34 #include <linux/types.h>
35 #include <linux/ethtool.h>
36 #ifdef HAVE_LINUX_SOCKIOS_H
37 #include <linux/sockios.h>
38 #else
39 #error "ethtool.h present but sockios.h is missing"
40 #endif /* HAVE_LINUX_SOCKIOS_H */
41 #endif /* HAVE_LINUX_ETHTOOL_H */
42 
43 #ifdef HAVE_NET_IF_H
44 #include <net/if.h>
45 #endif
46 
47 #ifdef OS_WIN32
48 #include "win32-syscall.h"
49 #endif
50 
51 #include "util-ioctl.h"
52 
53 /**
54  * \brief output a majorant of hardware header length
55  *
56  * \param Name of a network interface
57  */
58 static int GetIfaceMaxHWHeaderLength(const char *pcap_dev)
59 {
60  if ((!strcmp("eth", pcap_dev))
61  ||
62  (!strcmp("br", pcap_dev))
63  ||
64  (!strcmp("bond", pcap_dev))
65  ||
66  (!strcmp("wlan", pcap_dev))
67  ||
68  (!strcmp("tun", pcap_dev))
69  ||
70  (!strcmp("tap", pcap_dev))
71  ||
72  (!strcmp("lo", pcap_dev))) {
73  /* Add possible VLAN tag or Qing headers */
74  return 8 + ETHERNET_HEADER_LEN;
75  }
76 
77  if (!strcmp("ppp", pcap_dev))
78  return SLL_HEADER_LEN;
79  /* SLL_HEADER_LEN is the biggest one and
80  add possible VLAN tag and Qing headers */
81  return 8 + SLL_HEADER_LEN;
82 }
83 
84 
85 /**
86  * \brief output the link MTU
87  *
88  * \param Name of link
89  * \retval -1 in case of error, 0 if MTU can not be found
90  */
91 int GetIfaceMTU(const char *pcap_dev)
92 {
93 #if defined SIOCGIFMTU
94  struct ifreq ifr;
95  int fd;
96 
97  (void)strlcpy(ifr.ifr_name, pcap_dev, sizeof(ifr.ifr_name));
98  fd = socket(AF_INET, SOCK_DGRAM, 0);
99  if (fd == -1) {
100  return -1;
101  }
102 
103  if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) {
105  "Failure when trying to get MTU via ioctl for '%s': %s (%d)",
106  pcap_dev, strerror(errno), errno);
107  close(fd);
108  return -1;
109  }
110  close(fd);
111  SCLogInfo("Found an MTU of %d for '%s'", ifr.ifr_mtu,
112  pcap_dev);
113  return ifr.ifr_mtu;
114 #elif defined OS_WIN32
115  return GetIfaceMTUWin32(pcap_dev);
116 #else
117  /* ioctl is not defined, let's pretend returning 0 is ok */
118  return 0;
119 #endif
120 }
121 
122 /**
123  * \brief output max packet size for a link
124  *
125  * This does a best effort to find the maximum packet size
126  * for the link. In case of uncertainty, it will output a
127  * majorant to be sure avoid the cost of dynamic allocation.
128  *
129  * \param Name of a network interface
130  * \retval 0 in case of error
131  */
132 int GetIfaceMaxPacketSize(const char *pcap_dev)
133 {
134  if ((pcap_dev == NULL) || strlen(pcap_dev) == 0)
135  return 0;
136 
137  int mtu = GetIfaceMTU(pcap_dev);
138  switch (mtu) {
139  case 0:
140  case -1:
141  return 0;
142  }
143  int ll_header = GetIfaceMaxHWHeaderLength(pcap_dev);
144  if (ll_header == -1) {
145  /* be conservative, choose a big one */
146  ll_header = 16;
147  }
148  return ll_header + mtu;
149 }
150 
151 #ifdef SIOCGIFFLAGS
152 /**
153  * \brief Get interface flags.
154  * \param ifname Inteface name.
155  * \return Interface flags or -1 on error
156  */
157 int GetIfaceFlags(const char *ifname)
158 {
159  struct ifreq ifr;
160 
161  int fd = socket(AF_INET, SOCK_DGRAM, 0);
162  if (fd < 0) {
163  return -1;
164  }
165 
166  memset(&ifr, 0, sizeof(ifr));
167  strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
168 
169  if (ioctl(fd, SIOCGIFFLAGS, &ifr) == -1) {
171  "Unable to get flags for iface \"%s\": %s",
172  ifname, strerror(errno));
173  close(fd);
174  return -1;
175  }
176 
177  close(fd);
178 #ifdef OS_FREEBSD
179  int flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
180  return flags;
181 #else
182  return ifr.ifr_flags;
183 #endif
184 }
185 #endif
186 
187 #ifdef SIOCSIFFLAGS
188 /**
189  * \brief Set interface flags.
190  * \param ifname Inteface name.
191  * \param flags Flags to set.
192  * \return Zero on success.
193  */
194 int SetIfaceFlags(const char *ifname, int flags)
195 {
196  struct ifreq ifr;
197 
198  int fd = socket(AF_INET, SOCK_DGRAM, 0);
199  if (fd < 0) {
200  return -1;
201  }
202 
203  memset(&ifr, 0, sizeof(ifr));
204  strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
205 #ifdef OS_FREEBSD
206  ifr.ifr_flags = flags & 0xffff;
207  ifr.ifr_flagshigh = flags >> 16;
208 #else
209  ifr.ifr_flags = flags;
210 #endif
211 
212  if (ioctl(fd, SIOCSIFFLAGS, &ifr) == -1) {
214  "Unable to set flags for iface \"%s\": %s",
215  ifname, strerror(errno));
216  close(fd);
217  return -1;
218  }
219 
220  close(fd);
221  return 0;
222 }
223 #endif /* SIOCGIFFLAGS */
224 
225 #ifdef SIOCGIFCAP
226 int GetIfaceCaps(const char *ifname)
227 {
228  struct ifreq ifr;
229 
230  int fd = socket(AF_INET, SOCK_DGRAM, 0);
231  if (fd < 0) {
232  return -1;
233  }
234 
235  memset(&ifr, 0, sizeof(ifr));
236  strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
237 
238  if (ioctl(fd, SIOCGIFCAP, &ifr) == -1) {
240  "Unable to get caps for iface \"%s\": %s",
241  ifname, strerror(errno));
242  close(fd);
243  return -1;
244  }
245 
246  close(fd);
247  return ifr.ifr_curcap;
248 }
249 #endif
250 #ifdef SIOCSIFCAP
251 int SetIfaceCaps(const char *ifname, int caps)
252 {
253  struct ifreq ifr;
254 
255  int fd = socket(AF_INET, SOCK_DGRAM, 0);
256  if (fd < 0) {
257  return -1;
258  }
259 
260  memset(&ifr, 0, sizeof(ifr));
261  strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
262  ifr.ifr_reqcap = caps;
263 
264  if (ioctl(fd, SIOCSIFCAP, &ifr) == -1) {
266  "Unable to set caps for iface \"%s\": %s",
267  ifname, strerror(errno));
268  close(fd);
269  return -1;
270  }
271 
272  close(fd);
273  return 0;
274 }
275 #endif
276 
277 
278 #if defined HAVE_LINUX_ETHTOOL_H && defined SIOCETHTOOL
279 static int GetEthtoolValue(const char *dev, int cmd, uint32_t *value)
280 {
281  struct ifreq ifr;
282  int fd;
283  struct ethtool_value ethv;
284 
285  fd = socket(AF_INET, SOCK_DGRAM, 0);
286  if (fd == -1) {
287  return -1;
288  }
289  (void)strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
290 
291  ethv.cmd = cmd;
292  ifr.ifr_data = (void *) &ethv;
293  if (ioctl(fd, SIOCETHTOOL, (char *)&ifr) < 0) {
295  "Failure when trying to get feature via ioctl for '%s': %s (%d)",
296  dev, strerror(errno), errno);
297  close(fd);
298  return -1;
299  }
300 
301  *value = ethv.data;
302  close(fd);
303  return 0;
304 }
305 
306 static int SetEthtoolValue(const char *dev, int cmd, uint32_t value)
307 {
308  struct ifreq ifr;
309  int fd;
310  struct ethtool_value ethv;
311 
312  fd = socket(AF_INET, SOCK_DGRAM, 0);
313  if (fd == -1) {
314  return -1;
315  }
316  (void)strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name));
317 
318  ethv.cmd = cmd;
319  ethv.data = value;
320  ifr.ifr_data = (void *) &ethv;
321  if (ioctl(fd, SIOCETHTOOL, (char *)&ifr) < 0) {
323  "Failure when trying to set feature via ioctl for '%s': %s (%d)",
324  dev, strerror(errno), errno);
325  close(fd);
326  return -1;
327  }
328 
329  close(fd);
330  return 0;
331 }
332 
333 static int GetIfaceOffloadingLinux(const char *dev, int csum, int other)
334 {
335  int ret = 0;
336  uint32_t value = 0;
337 
338  if (csum) {
339  const char *rx = "unset", *tx = "unset";
340  int csum_ret = 0;
341 #ifdef ETHTOOL_GRXCSUM
342  if (GetEthtoolValue(dev, ETHTOOL_GRXCSUM, &value) == 0 && value != 0) {
343  rx = "SET";
344  csum_ret = 1;
345  }
346 #endif
347 #ifdef ETHTOOL_GTXCSUM
348  if (GetEthtoolValue(dev, ETHTOOL_GTXCSUM, &value) == 0 && value != 0) {
349  tx = "SET";
350  csum_ret = 1;
351  }
352 #endif
353  if (csum_ret == 0)
354  SCLogPerf("NIC offloading on %s: RX %s TX %s", dev, rx, tx);
355  else {
357  "NIC offloading on %s: RX %s TX %s. Run: "
358  "ethtool -K %s rx off tx off", dev, rx, tx, dev);
359  ret = 1;
360  }
361  }
362 
363  if (other) {
364  const char *lro = "unset", *gro = "unset", *tso = "unset", *gso = "unset";
365  const char *sg = "unset";
366  int other_ret = 0;
367 #ifdef ETHTOOL_GGRO
368  if (GetEthtoolValue(dev, ETHTOOL_GGRO, &value) == 0 && value != 0) {
369  gro = "SET";
370  other_ret = 1;
371  }
372 #endif
373 #ifdef ETHTOOL_GTSO
374  if (GetEthtoolValue(dev, ETHTOOL_GTSO, &value) == 0 && value != 0) {
375  tso = "SET";
376  other_ret = 1;
377  }
378 #endif
379 #ifdef ETHTOOL_GGSO
380  if (GetEthtoolValue(dev, ETHTOOL_GGSO, &value) == 0 && value != 0) {
381  gso = "SET";
382  other_ret = 1;
383  }
384 #endif
385 #ifdef ETHTOOL_GSG
386  if (GetEthtoolValue(dev, ETHTOOL_GSG, &value) == 0 && value != 0) {
387  sg = "SET";
388  other_ret = 1;
389  }
390 #endif
391 #ifdef ETHTOOL_GFLAGS
392  if (GetEthtoolValue(dev, ETHTOOL_GFLAGS, &value) == 0) {
393  if (value & ETH_FLAG_LRO) {
394  lro = "SET";
395  other_ret = 1;
396  }
397  }
398 #endif
399  if (other_ret == 0) {
400  SCLogPerf("NIC offloading on %s: SG: %s, GRO: %s, LRO: %s, "
401  "TSO: %s, GSO: %s", dev, sg, gro, lro, tso, gso);
402  } else {
403  SCLogWarning(SC_ERR_NIC_OFFLOADING, "NIC offloading on %s: SG: %s, "
404  " GRO: %s, LRO: %s, TSO: %s, GSO: %s. Run: "
405  "ethtool -K %s sg off gro off lro off tso off gso off",
406  dev, sg, gro, lro, tso, gso, dev);
407  ret = 1;
408  }
409  }
410  return ret;
411 }
412 
413 static int DisableIfaceOffloadingLinux(LiveDevice *ldev, int csum, int other)
414 {
415  int ret = 0;
416  uint32_t value = 0;
417 
418  if (ldev == NULL)
419  return -1;
420 
421  const char *dev = ldev->dev;
422 
423  if (csum) {
424 #ifdef ETHTOOL_GRXCSUM
425  if (GetEthtoolValue(dev, ETHTOOL_GRXCSUM, &value) == 0 && value != 0) {
426  SCLogPerf("%s: disabling rxcsum offloading", dev);
427  SetEthtoolValue(dev, ETHTOOL_SRXCSUM, 0);
429  }
430 #endif
431 #ifdef ETHTOOL_GTXCSUM
432  if (GetEthtoolValue(dev, ETHTOOL_GTXCSUM, &value) == 0 && value != 0) {
433  SCLogPerf("%s: disabling txcsum offloading", dev);
434  SetEthtoolValue(dev, ETHTOOL_STXCSUM, 0);
436  }
437 #endif
438  }
439  if (other) {
440 #ifdef ETHTOOL_GGRO
441  if (GetEthtoolValue(dev, ETHTOOL_GGRO, &value) == 0 && value != 0) {
442  SCLogPerf("%s: disabling gro offloading", dev);
443  SetEthtoolValue(dev, ETHTOOL_SGRO, 0);
445  }
446 #endif
447 #ifdef ETHTOOL_GTSO
448  if (GetEthtoolValue(dev, ETHTOOL_GTSO, &value) == 0 && value != 0) {
449  SCLogPerf("%s: disabling tso offloading", dev);
450  SetEthtoolValue(dev, ETHTOOL_STSO, 0);
452  }
453 #endif
454 #ifdef ETHTOOL_GGSO
455  if (GetEthtoolValue(dev, ETHTOOL_GGSO, &value) == 0 && value != 0) {
456  SCLogPerf("%s: disabling gso offloading", dev);
457  SetEthtoolValue(dev, ETHTOOL_SGSO, 0);
459  }
460 #endif
461 #ifdef ETHTOOL_GSG
462  if (GetEthtoolValue(dev, ETHTOOL_GSG, &value) == 0 && value != 0) {
463  SCLogPerf("%s: disabling sg offloading", dev);
464  SetEthtoolValue(dev, ETHTOOL_SSG, 0);
465  ldev->offload_orig |= OFFLOAD_FLAG_SG;
466  }
467 #endif
468 #ifdef ETHTOOL_GFLAGS
469  if (GetEthtoolValue(dev, ETHTOOL_GFLAGS, &value) == 0) {
470  if (value & ETH_FLAG_LRO) {
471  SCLogPerf("%s: disabling lro offloading", dev);
472  SetEthtoolValue(dev, ETHTOOL_SFLAGS, value & ~ETH_FLAG_LRO);
474  }
475  }
476 #endif
477  }
478  return ret;
479 }
480 
481 static int RestoreIfaceOffloadingLinux(LiveDevice *ldev)
482 {
483  if (ldev == NULL)
484  return -1;
485 
486  const char *dev = ldev->dev;
487 
488 #ifdef ETHTOOL_GRXCSUM
489  if (ldev->offload_orig & OFFLOAD_FLAG_RXCSUM) {
490  SCLogPerf("%s: restoring rxcsum offloading", dev);
491  SetEthtoolValue(dev, ETHTOOL_SRXCSUM, 1);
492  }
493 #endif
494 #ifdef ETHTOOL_GTXCSUM
495  if (ldev->offload_orig & OFFLOAD_FLAG_TXCSUM) {
496  SCLogPerf("%s: restoring txcsum offloading", dev);
497  SetEthtoolValue(dev, ETHTOOL_STXCSUM, 1);
498  }
499 #endif
500 #ifdef ETHTOOL_GGRO
501  if (ldev->offload_orig & OFFLOAD_FLAG_GRO) {
502  SCLogPerf("%s: restoring gro offloading", dev);
503  SetEthtoolValue(dev, ETHTOOL_SGRO, 1);
504  }
505 #endif
506 #ifdef ETHTOOL_GTSO
507  if (ldev->offload_orig & OFFLOAD_FLAG_TSO) {
508  SCLogPerf("%s: restoring tso offloading", dev);
509  SetEthtoolValue(dev, ETHTOOL_STSO, 1);
510  }
511 #endif
512 #ifdef ETHTOOL_GGSO
513  if (ldev->offload_orig & OFFLOAD_FLAG_GSO) {
514  SCLogPerf("%s: restoring gso offloading", dev);
515  SetEthtoolValue(dev, ETHTOOL_SGSO, 1);
516  }
517 #endif
518 #ifdef ETHTOOL_GSG
519  if (ldev->offload_orig & OFFLOAD_FLAG_SG) {
520  SCLogPerf("%s: restoring sg offloading", dev);
521  SetEthtoolValue(dev, ETHTOOL_SSG, 1);
522  }
523 #endif
524 #ifdef ETHTOOL_GFLAGS
525  if (ldev->offload_orig & OFFLOAD_FLAG_LRO) {
526  uint32_t value = 0;
527  if (GetEthtoolValue(dev, ETHTOOL_GFLAGS, &value) == 0) {
528  SCLogPerf("%s: restoring lro offloading", dev);
529  SetEthtoolValue(dev, ETHTOOL_SFLAGS, value & ETH_FLAG_LRO);
530  }
531  }
532 #endif
533  return 0;
534 }
535 
536 #endif /* defined HAVE_LINUX_ETHTOOL_H && defined SIOCETHTOOL */
537 
538 #ifdef SIOCGIFCAP
539 static int GetIfaceOffloadingBSD(const char *ifname)
540 {
541  int ret = 0;
542  int if_caps = GetIfaceCaps(ifname);
543  if (if_caps == -1) {
544  return -1;
545  }
546  SCLogDebug("if_caps %X", if_caps);
547 
548  if (if_caps & IFCAP_RXCSUM) {
550  "Using %s with RXCSUM activated can lead to capture "
551  "problems. Run: ifconfig %s -rxcsum", ifname, ifname);
552  ret = 1;
553  }
554 #ifdef IFCAP_TOE
555  if (if_caps & (IFCAP_TSO|IFCAP_TOE|IFCAP_LRO)) {
557  "Using %s with TSO, TOE or LRO activated can lead to "
558  "capture problems. Run: ifconfig %s -tso -toe -lro",
559  ifname, ifname);
560  ret = 1;
561  }
562 #else
563  if (if_caps & (IFCAP_TSO|IFCAP_LRO)) {
565  "Using %s with TSO or LRO activated can lead to "
566  "capture problems. Run: ifconfig %s -tso -lro",
567  ifname, ifname);
568  ret = 1;
569  }
570 #endif
571  return ret;
572 }
573 #endif
574 
575 #ifdef SIOCSIFCAP
576 static int DisableIfaceOffloadingBSD(LiveDevice *ldev)
577 {
578  int ret = 0;
579 
580  if (ldev == NULL)
581  return -1;
582 
583  const char *ifname = ldev->dev;
584  int if_caps = GetIfaceCaps(ifname);
585  int set_caps = if_caps;
586  if (if_caps == -1) {
587  return -1;
588  }
589  SCLogDebug("if_caps %X", if_caps);
590 
591  if (if_caps & IFCAP_RXCSUM) {
592  SCLogPerf("%s: disabling rxcsum offloading", ifname);
593  set_caps &= ~IFCAP_RXCSUM;
594  }
595  if (if_caps & IFCAP_TXCSUM) {
596  SCLogPerf("%s: disabling txcsum offloading", ifname);
597  set_caps &= ~IFCAP_TXCSUM;
598  }
599 #ifdef IFCAP_RXCSUM_IPV6
600  if (if_caps & IFCAP_RXCSUM_IPV6) {
601  SCLogPerf("%s: disabling rxcsum6 offloading", ifname);
602  set_caps &= ~IFCAP_RXCSUM_IPV6;
603  }
604 #endif
605 #ifdef IFCAP_TXCSUM_IPV6
606  if (if_caps & IFCAP_TXCSUM_IPV6) {
607  SCLogPerf("%s: disabling txcsum6 offloading", ifname);
608  set_caps &= ~IFCAP_TXCSUM_IPV6;
609  }
610 #endif
611 #ifdef IFCAP_TOE
612  if (if_caps & (IFCAP_TSO|IFCAP_TOE|IFCAP_LRO)) {
613  SCLogPerf("%s: disabling tso|toe|lro offloading", ifname);
614  set_caps &= ~(IFCAP_TSO|IFCAP_LRO);
615  }
616 #else
617  if (if_caps & (IFCAP_TSO|IFCAP_LRO)) {
618  SCLogPerf("%s: disabling tso|lro offloading", ifname);
619  set_caps &= ~(IFCAP_TSO|IFCAP_LRO);
620  }
621 #endif
622  if (set_caps != if_caps) {
623  if (if_caps & IFCAP_RXCSUM)
625  if (if_caps & IFCAP_TSO)
627 #ifdef IFCAP_TOE
628  if (if_caps & IFCAP_TOE)
630 #endif
631  if (if_caps & IFCAP_LRO)
633 
634  SetIfaceCaps(ifname, set_caps);
635  }
636  return ret;
637 }
638 
639 static int RestoreIfaceOffloadingBSD(LiveDevice *ldev)
640 {
641  int ret = 0;
642 
643  if (ldev == NULL)
644  return -1;
645 
646  const char *ifname = ldev->dev;
647  int if_caps = GetIfaceCaps(ifname);
648  int set_caps = if_caps;
649  if (if_caps == -1) {
650  return -1;
651  }
652  SCLogDebug("if_caps %X", if_caps);
653 
654  if (ldev->offload_orig & OFFLOAD_FLAG_RXCSUM) {
655  SCLogPerf("%s: restoring rxcsum offloading", ifname);
656  set_caps |= IFCAP_RXCSUM;
657  }
658  if (ldev->offload_orig & OFFLOAD_FLAG_TSO) {
659  SCLogPerf("%s: restoring tso offloading", ifname);
660  set_caps |= IFCAP_TSO;
661  }
662 #ifdef IFCAP_TOE
663  if (ldev->offload_orig & OFFLOAD_FLAG_TOE) {
664  SCLogPerf("%s: restoring toe offloading", ifname);
665  set_caps |= IFCAP_TOE;
666  }
667 #endif
668  if (ldev->offload_orig & OFFLOAD_FLAG_LRO) {
669  SCLogPerf("%s: restoring lro offloading", ifname);
670  set_caps |= IFCAP_LRO;
671  }
672 
673  if (set_caps != if_caps) {
674  SetIfaceCaps(ifname, set_caps);
675  }
676  return ret;
677 }
678 #endif
679 
680 /**
681  * \brief output offloading status of the link
682  *
683  * Test interface for offloading features. If one of them is
684  * activated then suricata mays received packets merge at reception.
685  * The result is oversized packets and this may cause some serious
686  * problem in some capture mode where the size of the packet is
687  * limited (AF_PACKET in V2 more for example).
688  *
689  * \param Name of link
690  * \param csum check if checksums are offloaded
691  * \param other check if other things are offloaded: TSO, GRO, etc.
692  * \retval -1 in case of error, 0 if none, 1 if some
693  */
694 int GetIfaceOffloading(const char *dev, int csum, int other)
695 {
696 #if defined HAVE_LINUX_ETHTOOL_H && defined SIOCETHTOOL
697  return GetIfaceOffloadingLinux(dev, csum, other);
698 #elif defined SIOCGIFCAP
699  return GetIfaceOffloadingBSD(dev);
700 #elif defined OS_WIN32
701  return GetIfaceOffloadingWin32(dev, csum, other);
702 #else
703  return 0;
704 #endif
705 }
706 
707 int DisableIfaceOffloading(LiveDevice *dev, int csum, int other)
708 {
709  /* already set */
710  if (dev->offload_orig != 0)
711  return 0;
712 #if defined HAVE_LINUX_ETHTOOL_H && defined SIOCETHTOOL
713  return DisableIfaceOffloadingLinux(dev, csum, other);
714 #elif defined SIOCSIFCAP
715  return DisableIfaceOffloadingBSD(dev);
716 #elif defined OS_WIN32
717  return DisableIfaceOffloadingWin32(dev, csum, other);
718 #else
719  return 0;
720 #endif
721 
722 }
723 
725 {
726  if (dev->offload_orig != 0) {
727 #if defined HAVE_LINUX_ETHTOOL_H && defined SIOCETHTOOL
728  RestoreIfaceOffloadingLinux(dev);
729 #elif defined SIOCSIFCAP
730  RestoreIfaceOffloadingBSD(dev);
731 #elif defined OS_WIN32
732  RestoreIfaceOffloadingWin32(dev);
733 #endif
734  }
735 }
736 
737 int GetIfaceRSSQueuesNum(const char *pcap_dev)
738 {
739 #if defined HAVE_LINUX_ETHTOOL_H && defined ETHTOOL_GRXRINGS
740  struct ifreq ifr;
741  struct ethtool_rxnfc nfccmd;
742  int fd;
743 
744  (void)strlcpy(ifr.ifr_name, pcap_dev, sizeof(ifr.ifr_name));
745  fd = socket(AF_INET, SOCK_DGRAM, 0);
746  if (fd == -1) {
748  "Failure when opening socket for ioctl: %s (%d)",
749  strerror(errno), errno);
750  return -1;
751  }
752 
753  nfccmd.cmd = ETHTOOL_GRXRINGS;
754  ifr.ifr_data = (void*) &nfccmd;
755 
756  if (ioctl(fd, SIOCETHTOOL, (char *)&ifr) < 0) {
757  if (errno != ENOTSUP) {
759  "Failure when trying to get number of RSS queue ioctl for '%s': %s (%d)",
760  pcap_dev, strerror(errno), errno);
761  }
762  close(fd);
763  return 0;
764  }
765  close(fd);
766  SCLogInfo("Found %d RX RSS queues for '%s'", (int)nfccmd.data,
767  pcap_dev);
768  return (int)nfccmd.data;
769 #else
770  return 0;
771 #endif
772 }
uint16_t flags
#define SCLogDebug(...)
Definition: util-debug.h:335
uint32_t offload_orig
Definition: util-device.h:55
#define SLL_HEADER_LEN
Definition: decode-sll.h:27
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: util-strlcpyu.c:43
int GetIfaceMaxPacketSize(const char *pcap_dev)
output max packet size for a link
Definition: util-ioctl.c:132
#define OFFLOAD_FLAG_RXCSUM
Definition: util-device.h:29
#define OFFLOAD_FLAG_TOE
Definition: util-device.h:31
int GetIfaceOffloading(const char *dev, int csum, int other)
output offloading status of the link
Definition: util-ioctl.c:694
char * dev
Definition: util-device.h:41
#define OFFLOAD_FLAG_SG
Definition: util-device.h:24
#define OFFLOAD_FLAG_LRO
Definition: util-device.h:28
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
int GetIfaceMTU(const char *pcap_dev)
output the link MTU
Definition: util-ioctl.c:91
#define OFFLOAD_FLAG_TXCSUM
Definition: util-device.h:30
#define OFFLOAD_FLAG_GRO
Definition: util-device.h:27
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:281
#define ETHERNET_HEADER_LEN
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
int DisableIfaceOffloading(LiveDevice *dev, int csum, int other)
Definition: util-ioctl.c:707
int GetIfaceRSSQueuesNum(const char *pcap_dev)
Definition: util-ioctl.c:737
#define SCLogPerf(...)
Definition: util-debug.h:261
void RestoreIfaceOffloading(LiveDevice *dev)
Definition: util-ioctl.c:724
#define OFFLOAD_FLAG_TSO
Definition: util-device.h:25
#define OFFLOAD_FLAG_GSO
Definition: util-device.h:26