]> arthur.barton.de Git - netdata.git/blob - src/macos_sysctl.c
Add uptime badge to macOS plugin
[netdata.git] / src / macos_sysctl.c
1 #include "common.h"
2 #include <sys/sysctl.h>
3 // NEEDED BY: do_bandwidth
4 #include <net/route.h>
5 // NEEDED BY do_tcp...
6 #include <sys/socketvar.h>
7 #include <netinet/tcp_var.h>
8 #include <netinet/tcp_fsm.h>
9 // NEEDED BY do_udp..., do_ip...
10 #include <netinet/ip_var.h>
11 // NEEDED BY do_udp...
12 #include <netinet/udp.h>
13 #include <netinet/udp_var.h>
14 // NEEDED BY do_icmp...
15 #include <netinet/ip.h>
16 #include <netinet/ip_icmp.h>
17 #include <netinet/icmp_var.h>
18 // NEEDED BY do_icmp6...
19 #include <netinet/icmp6.h>
20 // NEEDED BY do_uptime
21 #include <time.h>
22
23 #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
24
25 // MacOS calculates load averages once every 5 seconds
26 #define MIN_LOADAVG_UPDATE_EVERY 5
27
28 int getsysctl(const char *name, void *ptr, size_t len);
29
30 int do_macos_sysctl(int update_every, usec_t dt) {
31     (void)dt;
32
33     static int do_loadavg = -1, do_swap = -1, do_bandwidth = -1,
34                do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_ecn = -1,
35                do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1,
36                do_udp_packets = -1, do_udp_errors = -1, do_icmp_packets = -1, do_icmpmsg = -1,
37                do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
38                do_ip6_packets = -1, do_ip6_fragsout = -1, do_ip6_fragsin = -1, do_ip6_errors = -1,
39                do_icmp6 = -1, do_icmp6_redir = -1, do_icmp6_errors = -1, do_icmp6_echos = -1,
40                do_icmp6_router = -1, do_icmp6_neighbor = -1, do_icmp6_types = -1, do_uptime = -1;
41
42
43     if (unlikely(do_loadavg == -1)) {
44         do_loadavg              = config_get_boolean("plugin:macos:sysctl", "enable load average", 1);
45         do_swap                 = config_get_boolean("plugin:macos:sysctl", "system swap", 1);
46         do_bandwidth            = config_get_boolean("plugin:macos:sysctl", "bandwidth", 1);
47         do_tcp_packets          = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP packets", 1);
48         do_tcp_errors           = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP errors", 1);
49         do_tcp_handshake        = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP handshake issues", 1);
50         do_ecn                  = config_get_boolean_ondemand("plugin:macos:sysctl", "ECN packets", CONFIG_ONDEMAND_ONDEMAND);
51         do_tcpext_syscookies    = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND);
52         do_tcpext_ofo           = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND);
53         do_tcpext_connaborts    = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND);
54         do_udp_packets          = config_get_boolean("plugin:macos:sysctl", "ipv4 UDP packets", 1);
55         do_udp_errors           = config_get_boolean("plugin:macos:sysctl", "ipv4 UDP errors", 1);
56         do_icmp_packets         = config_get_boolean("plugin:macos:sysctl", "ipv4 ICMP packets", 1);
57         do_icmpmsg              = config_get_boolean("plugin:macos:sysctl", "ipv4 ICMP messages", 1);
58         do_ip_packets           = config_get_boolean("plugin:macos:sysctl", "ipv4 packets", 1);
59         do_ip_fragsout          = config_get_boolean("plugin:macos:sysctl", "ipv4 fragments sent", 1);
60         do_ip_fragsin           = config_get_boolean("plugin:macos:sysctl", "ipv4 fragments assembly", 1);
61         do_ip_errors            = config_get_boolean("plugin:macos:sysctl", "ipv4 errors", 1);
62         do_ip6_packets          = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 packets", CONFIG_ONDEMAND_ONDEMAND);
63         do_ip6_fragsout         = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 fragments sent", CONFIG_ONDEMAND_ONDEMAND);
64         do_ip6_fragsin          = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 fragments assembly", CONFIG_ONDEMAND_ONDEMAND);
65         do_ip6_errors           = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 errors", CONFIG_ONDEMAND_ONDEMAND);
66         do_icmp6                = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp", CONFIG_ONDEMAND_ONDEMAND);
67         do_icmp6_redir          = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp redirects", CONFIG_ONDEMAND_ONDEMAND);
68         do_icmp6_errors         = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp errors", CONFIG_ONDEMAND_ONDEMAND);
69         do_icmp6_echos          = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp echos", CONFIG_ONDEMAND_ONDEMAND);
70         do_icmp6_router         = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp router", CONFIG_ONDEMAND_ONDEMAND);
71         do_icmp6_neighbor       = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp neighbor", CONFIG_ONDEMAND_ONDEMAND);
72         do_icmp6_types          = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp types", CONFIG_ONDEMAND_ONDEMAND);
73         do_uptime               = config_get_boolean("plugin:macos:sysctl", "system uptime", 1);
74     }
75
76     RRDSET *st;
77
78     int system_pagesize = getpagesize(); // wouldn't it be better to get value directly from hw.pagesize?
79     int i, n;
80     int common_error = 0;
81     size_t size;
82
83     // NEEDED BY: do_loadavg
84     static usec_t last_loadavg_usec = 0;
85     struct loadavg sysload;
86
87     // NEEDED BY: do_swap
88     struct xsw_usage swap_usage;
89
90     // NEEDED BY: do_bandwidth
91     int mib[6];
92     static char *ifstatdata = NULL;
93     char *lim, *next;
94     struct if_msghdr *ifm;
95     struct iftot {
96         u_long  ift_ibytes;
97         u_long  ift_obytes;
98     } iftot = {0, 0};
99
100     // NEEDED BY: do_tcp...
101     struct tcpstat tcpstat;
102     uint64_t tcps_states[TCP_NSTATES];
103
104     // NEEDED BY: do_udp...
105     struct udpstat udpstat;
106
107     // NEEDED BY: do_icmp...
108     struct icmpstat icmpstat;
109     struct icmp_total {
110         u_long  msgs_in;
111         u_long  msgs_out;
112     } icmp_total = {0, 0};
113
114     // NEEDED BY: do_ip...
115     struct ipstat ipstat;
116
117     // NEEDED BY: do_ip6...
118     /*
119      * Dirty workaround for /usr/include/netinet6/ip6_var.h absence.
120      * Struct ip6stat was copied from bsd/netinet6/ip6_var.h from xnu sources.
121      */
122 #define IP6S_SRCRULE_COUNT 16
123 #include <netinet6/scope6_var.h>
124     struct      ip6stat {
125         u_quad_t ip6s_total;            /* total packets received */
126         u_quad_t ip6s_tooshort;         /* packet too short */
127         u_quad_t ip6s_toosmall;         /* not enough data */
128         u_quad_t ip6s_fragments;        /* fragments received */
129         u_quad_t ip6s_fragdropped;      /* frags dropped(dups, out of space) */
130         u_quad_t ip6s_fragtimeout;      /* fragments timed out */
131         u_quad_t ip6s_fragoverflow;     /* fragments that exceeded limit */
132         u_quad_t ip6s_forward;          /* packets forwarded */
133         u_quad_t ip6s_cantforward;      /* packets rcvd for unreachable dest */
134         u_quad_t ip6s_redirectsent;     /* packets forwarded on same net */
135         u_quad_t ip6s_delivered;        /* datagrams delivered to upper level */
136         u_quad_t ip6s_localout;         /* total ip packets generated here */
137         u_quad_t ip6s_odropped;         /* lost packets due to nobufs, etc. */
138         u_quad_t ip6s_reassembled;      /* total packets reassembled ok */
139         u_quad_t ip6s_atmfrag_rcvd;     /* atomic fragments received */
140         u_quad_t ip6s_fragmented;       /* datagrams successfully fragmented */
141         u_quad_t ip6s_ofragments;       /* output fragments created */
142         u_quad_t ip6s_cantfrag;         /* don't fragment flag was set, etc. */
143         u_quad_t ip6s_badoptions;       /* error in option processing */
144         u_quad_t ip6s_noroute;          /* packets discarded due to no route */
145         u_quad_t ip6s_badvers;          /* ip6 version != 6 */
146         u_quad_t ip6s_rawout;           /* total raw ip packets generated */
147         u_quad_t ip6s_badscope;         /* scope error */
148         u_quad_t ip6s_notmember;        /* don't join this multicast group */
149         u_quad_t ip6s_nxthist[256];     /* next header history */
150         u_quad_t ip6s_m1;               /* one mbuf */
151         u_quad_t ip6s_m2m[32];          /* two or more mbuf */
152         u_quad_t ip6s_mext1;            /* one ext mbuf */
153         u_quad_t ip6s_mext2m;           /* two or more ext mbuf */
154         u_quad_t ip6s_exthdrtoolong;    /* ext hdr are not continuous */
155         u_quad_t ip6s_nogif;            /* no match gif found */
156         u_quad_t ip6s_toomanyhdr;       /* discarded due to too many headers */
157
158         /*
159          * statistics for improvement of the source address selection
160          * algorithm:
161          */
162         /* number of times that address selection fails */
163         u_quad_t ip6s_sources_none;
164         /* number of times that an address on the outgoing I/F is chosen */
165         u_quad_t ip6s_sources_sameif[SCOPE6_ID_MAX];
166         /* number of times that an address on a non-outgoing I/F is chosen */
167         u_quad_t ip6s_sources_otherif[SCOPE6_ID_MAX];
168         /*
169          * number of times that an address that has the same scope
170          * from the destination is chosen.
171          */
172         u_quad_t ip6s_sources_samescope[SCOPE6_ID_MAX];
173         /*
174          * number of times that an address that has a different scope
175          * from the destination is chosen.
176          */
177         u_quad_t ip6s_sources_otherscope[SCOPE6_ID_MAX];
178         /* number of times that a deprecated address is chosen */
179         u_quad_t ip6s_sources_deprecated[SCOPE6_ID_MAX];
180
181         u_quad_t ip6s_forward_cachehit;
182         u_quad_t ip6s_forward_cachemiss;
183
184         /* number of times that each rule of source selection is applied. */
185         u_quad_t ip6s_sources_rule[IP6S_SRCRULE_COUNT];
186
187         /* number of times we ignored address on expensive secondary interfaces */
188         u_quad_t ip6s_sources_skip_expensive_secondary_if;
189
190         /* pkt dropped, no mbufs for control data */
191         u_quad_t ip6s_pktdropcntrl;
192
193         /* total packets trimmed/adjusted  */
194         u_quad_t ip6s_adj;
195         /* hwcksum info discarded during adjustment */
196         u_quad_t ip6s_adj_hwcsum_clr;
197
198         /* duplicate address detection collisions */
199         u_quad_t ip6s_dad_collide;
200
201         /* DAD NS looped back */
202         u_quad_t ip6s_dad_loopcount;
203     } ip6stat;
204
205     // NEEDED BY: do_icmp6...
206     struct icmp6stat icmp6stat;
207     struct icmp6_total {
208         u_long  msgs_in;
209         u_long  msgs_out;
210     } icmp6_total = {0, 0};
211
212     // NEEDED BY: do_uptime
213     struct timespec boot_time, cur_time;
214
215     // --------------------------------------------------------------------
216
217     if (last_loadavg_usec <= dt) {
218         if (likely(do_loadavg)) {
219             if (unlikely(GETSYSCTL("vm.loadavg", sysload))) {
220                 do_loadavg = 0;
221                 error("DISABLED: system.load");
222             } else {
223
224                 st = rrdset_find_bytype("system", "load");
225                 if (unlikely(!st)) {
226                     st = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE);
227                     rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE);
228                     rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE);
229                     rrddim_add(st, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE);
230                 }
231                 else rrdset_next(st);
232
233                 rrddim_set(st, "load1", (collected_number) ((double)sysload.ldavg[0] / sysload.fscale * 1000));
234                 rrddim_set(st, "load5", (collected_number) ((double)sysload.ldavg[1] / sysload.fscale * 1000));
235                 rrddim_set(st, "load15", (collected_number) ((double)sysload.ldavg[2] / sysload.fscale * 1000));
236                 rrdset_done(st);
237             }
238         }
239
240         last_loadavg_usec = st->update_every * USEC_PER_SEC;
241     }
242     else last_loadavg_usec -= dt;
243
244     // --------------------------------------------------------------------
245
246     if (likely(do_swap)) {
247         if (unlikely(GETSYSCTL("vm.swapusage", swap_usage))) {
248             do_swap = 0;
249             error("DISABLED: system.swap");
250         } else {
251             st = rrdset_find("system.swap");
252             if (unlikely(!st)) {
253                 st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED);
254                 st->isdetail = 1;
255
256                 rrddim_add(st, "free",    NULL, 1, 1048576, RRDDIM_ABSOLUTE);
257                 rrddim_add(st, "used",    NULL, 1, 1048576, RRDDIM_ABSOLUTE);
258             }
259             else rrdset_next(st);
260
261             rrddim_set(st, "free", swap_usage.xsu_avail);
262             rrddim_set(st, "used", swap_usage.xsu_used);
263             rrdset_done(st);
264         }
265     }
266
267     // --------------------------------------------------------------------
268
269     if (likely(do_bandwidth)) {
270         mib[0] = CTL_NET;
271         mib[1] = PF_ROUTE;
272         mib[2] = 0;
273         mib[3] = AF_INET;
274         mib[4] = NET_RT_IFLIST2;
275         mib[5] = 0;
276         if (unlikely(sysctl(mib, 6, NULL, &size, NULL, 0))) {
277             error("MACOS: sysctl(%s...) failed: %s", "net interfaces", strerror(errno));
278             do_bandwidth = 0;
279             error("DISABLED: system.ipv4");
280         } else {
281             ifstatdata = reallocz(ifstatdata, size);
282             if (unlikely(sysctl(mib, 6, ifstatdata, &size, NULL, 0) < 0)) {
283                 error("MACOS: sysctl(%s...) failed: %s", "net interfaces", strerror(errno));
284                 do_bandwidth = 0;
285                 error("DISABLED: system.ipv4");
286             } else {
287                 lim = ifstatdata + size;
288                 iftot.ift_ibytes = iftot.ift_obytes = 0;
289                 for (next = ifstatdata; next < lim; ) {
290                     ifm = (struct if_msghdr *)next;
291                     next += ifm->ifm_msglen;
292
293                     if (ifm->ifm_type == RTM_IFINFO2) {
294                         struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
295
296                         iftot.ift_ibytes += if2m->ifm_data.ifi_ibytes;
297                         iftot.ift_obytes += if2m->ifm_data.ifi_obytes;
298                     }
299                 }
300                 st = rrdset_find("system.ipv4");
301                 if (unlikely(!st)) {
302                     st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);
303
304                     rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
305                     rrddim_add(st, "OutOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
306                 }
307                 else rrdset_next(st);
308
309                 rrddim_set(st, "InOctets", iftot.ift_ibytes);
310                 rrddim_set(st, "OutOctets", iftot.ift_obytes);
311                 rrdset_done(st);
312             }
313         }
314     }
315
316     // --------------------------------------------------------------------
317
318     // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
319     if (likely(do_tcp_packets || do_tcp_errors || do_tcp_handshake || do_tcpext_connaborts || do_tcpext_ofo || do_tcpext_syscookies || do_ecn)) {
320         if (unlikely(GETSYSCTL("net.inet.tcp.stats", tcpstat))){
321             do_tcp_packets = 0;
322             error("DISABLED: ipv4.tcppackets");
323             do_tcp_errors = 0;
324             error("DISABLED: ipv4.tcperrors");
325             do_tcp_handshake = 0;
326             error("DISABLED: ipv4.tcphandshake");
327             do_tcpext_connaborts = 0;
328             error("DISABLED: ipv4.tcpconnaborts");
329             do_tcpext_ofo = 0;
330             error("DISABLED: ipv4.tcpofo");
331             do_tcpext_syscookies = 0;
332             error("DISABLED: ipv4.tcpsyncookies");
333             do_ecn = 0;
334             error("DISABLED: ipv4.ecnpkts");
335         } else {
336             if (likely(do_tcp_packets)) {
337                 st = rrdset_find("ipv4.tcppackets");
338                 if (unlikely(!st)) {
339                     st = rrdset_create("ipv4", "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets",
340                                        "packets/s",
341                                        2600, update_every, RRDSET_TYPE_LINE);
342
343                     rrddim_add(st, "InSegs", "received", 1, 1, RRDDIM_INCREMENTAL);
344                     rrddim_add(st, "OutSegs", "sent", -1, 1, RRDDIM_INCREMENTAL);
345                 } else
346                     rrdset_next(st);
347
348                 rrddim_set(st, "InSegs", tcpstat.tcps_rcvtotal);
349                 rrddim_set(st, "OutSegs", tcpstat.tcps_sndtotal);
350                 rrdset_done(st);
351             }
352
353             // --------------------------------------------------------------------
354
355             if (likely(do_tcp_errors)) {
356                 st = rrdset_find("ipv4.tcperrors");
357                 if (unlikely(!st)) {
358                     st = rrdset_create("ipv4", "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors",
359                                        "packets/s",
360                                        2700, update_every, RRDSET_TYPE_LINE);
361                     st->isdetail = 1;
362
363                     rrddim_add(st, "InErrs", NULL, 1, 1, RRDDIM_INCREMENTAL);
364                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
365                     rrddim_add(st, "RetransSegs", NULL, -1, 1, RRDDIM_INCREMENTAL);
366                 } else
367                     rrdset_next(st);
368
369                 rrddim_set(st, "InErrs", tcpstat.tcps_rcvbadoff + tcpstat.tcps_rcvshort);
370                 rrddim_set(st, "InCsumErrors", tcpstat.tcps_rcvbadsum);
371                 rrddim_set(st, "RetransSegs", tcpstat.tcps_sndrexmitpack);
372                 rrdset_done(st);
373             }
374
375             // --------------------------------------------------------------------
376
377             if (likely(do_tcp_handshake)) {
378                 st = rrdset_find("ipv4.tcphandshake");
379                 if (unlikely(!st)) {
380                     st = rrdset_create("ipv4", "tcphandshake", NULL, "tcp", NULL,
381                                        "IPv4 TCP Handshake Issues",
382                                        "events/s", 2900, update_every, RRDSET_TYPE_LINE);
383                     st->isdetail = 1;
384
385                     rrddim_add(st, "EstabResets", NULL, 1, 1, RRDDIM_INCREMENTAL);
386                     rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL);
387                     rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL);
388                     rrddim_add(st, "AttemptFails", NULL, 1, 1, RRDDIM_INCREMENTAL);
389                 } else
390                     rrdset_next(st);
391
392                 rrddim_set(st, "EstabResets", tcpstat.tcps_drops);
393                 rrddim_set(st, "ActiveOpens", tcpstat.tcps_connattempt);
394                 rrddim_set(st, "PassiveOpens", tcpstat.tcps_accepts);
395                 rrddim_set(st, "AttemptFails", tcpstat.tcps_conndrops);
396                 rrdset_done(st);
397             }
398
399             // --------------------------------------------------------------------
400
401             if (do_tcpext_connaborts == CONFIG_ONDEMAND_YES || (do_tcpext_connaborts == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_rcvpackafterwin || tcpstat.tcps_rcvafterclose || tcpstat.tcps_rcvmemdrop || tcpstat.tcps_persistdrop))) {
402                 do_tcpext_connaborts = CONFIG_ONDEMAND_YES;
403                 st = rrdset_find("ipv4.tcpconnaborts");
404                 if (unlikely(!st)) {
405                     st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE);
406
407                     rrddim_add(st, "TCPAbortOnData",    "baddata",     1, 1, RRDDIM_INCREMENTAL);
408                     rrddim_add(st, "TCPAbortOnClose",   "userclosed",  1, 1, RRDDIM_INCREMENTAL);
409                     rrddim_add(st, "TCPAbortOnMemory",  "nomemory",    1, 1, RRDDIM_INCREMENTAL);
410                     rrddim_add(st, "TCPAbortOnTimeout", "timeout",     1, 1, RRDDIM_INCREMENTAL);
411                 }
412                 else rrdset_next(st);
413
414                 rrddim_set(st, "TCPAbortOnData",    tcpstat.tcps_rcvpackafterwin);
415                 rrddim_set(st, "TCPAbortOnClose",   tcpstat.tcps_rcvafterclose);
416                 rrddim_set(st, "TCPAbortOnMemory",  tcpstat.tcps_rcvmemdrop);
417                 rrddim_set(st, "TCPAbortOnTimeout", tcpstat.tcps_persistdrop);
418                 rrdset_done(st);
419             }
420
421             // --------------------------------------------------------------------
422
423             if (do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && tcpstat.tcps_rcvoopack)) {
424                 do_tcpext_ofo = CONFIG_ONDEMAND_YES;
425                 st = rrdset_find("ipv4.tcpofo");
426                 if (unlikely(!st)) {
427                     st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE);
428
429                     rrddim_add(st, "TCPOFOQueue", "inqueue",  1, 1, RRDDIM_INCREMENTAL);
430                 }
431                 else rrdset_next(st);
432
433                 rrddim_set(st, "TCPOFOQueue",   tcpstat.tcps_rcvoopack);
434                 rrdset_done(st);
435             }
436
437             // --------------------------------------------------------------------
438
439             if (do_tcpext_syscookies == CONFIG_ONDEMAND_YES || (do_tcpext_syscookies == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_sc_sendcookie || tcpstat.tcps_sc_recvcookie || tcpstat.tcps_sc_zonefail))) {
440                 do_tcpext_syscookies = CONFIG_ONDEMAND_YES;
441
442                 st = rrdset_find("ipv4.tcpsyncookies");
443                 if (unlikely(!st)) {
444                     st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE);
445
446                     rrddim_add(st, "SyncookiesRecv",   "received",  1, 1, RRDDIM_INCREMENTAL);
447                     rrddim_add(st, "SyncookiesSent",   "sent",     -1, 1, RRDDIM_INCREMENTAL);
448                     rrddim_add(st, "SyncookiesFailed", "failed",   -1, 1, RRDDIM_INCREMENTAL);
449                 }
450                 else rrdset_next(st);
451
452                 rrddim_set(st, "SyncookiesRecv",   tcpstat.tcps_sc_recvcookie);
453                 rrddim_set(st, "SyncookiesSent",   tcpstat.tcps_sc_sendcookie);
454                 rrddim_set(st, "SyncookiesFailed", tcpstat.tcps_sc_zonefail);
455                 rrdset_done(st);
456             }
457
458             // --------------------------------------------------------------------
459
460             if (do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_ecn_recv_ce || tcpstat.tcps_ecn_not_supported))) {
461                 do_ecn = CONFIG_ONDEMAND_YES;
462                 st = rrdset_find("ipv4.ecnpkts");
463                 if (unlikely(!st)) {
464                     st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE);
465                     st->isdetail = 1;
466
467                     rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRDDIM_INCREMENTAL);
468                     rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRDDIM_INCREMENTAL);
469                 }
470                 else rrdset_next(st);
471
472                 rrddim_set(st, "InCEPkts", tcpstat.tcps_ecn_recv_ce);
473                 rrddim_set(st, "InNoECTPkts", tcpstat.tcps_ecn_not_supported);
474                 rrdset_done(st);
475             }
476
477         }
478     }
479
480     // --------------------------------------------------------------------
481
482     // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
483     if (likely(do_udp_packets || do_udp_errors)) {
484         if (unlikely(GETSYSCTL("net.inet.udp.stats", udpstat))) {
485             do_udp_packets = 0;
486             error("DISABLED: ipv4.udppackets");
487             do_udp_errors = 0;
488             error("DISABLED: ipv4.udperrors");
489         } else {
490             if (likely(do_udp_packets)) {
491                 st = rrdset_find("ipv4.udppackets");
492                 if (unlikely(!st)) {
493                     st = rrdset_create("ipv4", "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets",
494                                        "packets/s", 2601, update_every, RRDSET_TYPE_LINE);
495
496                     rrddim_add(st, "InDatagrams", "received", 1, 1, RRDDIM_INCREMENTAL);
497                     rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRDDIM_INCREMENTAL);
498                 } else
499                     rrdset_next(st);
500
501                 rrddim_set(st, "InDatagrams", udpstat.udps_ipackets);
502                 rrddim_set(st, "OutDatagrams", udpstat.udps_opackets);
503                 rrdset_done(st);
504             }
505
506             // --------------------------------------------------------------------
507
508             if (likely(do_udp_errors)) {
509                 st = rrdset_find("ipv4.udperrors");
510                 if (unlikely(!st)) {
511                     st = rrdset_create("ipv4", "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s",
512                                        2701, update_every, RRDSET_TYPE_LINE);
513                     st->isdetail = 1;
514
515                     rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
516                     rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
517                     rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL);
518                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
519                     rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRDDIM_INCREMENTAL);
520                 } else
521                     rrdset_next(st);
522
523                 rrddim_set(st, "InErrors", udpstat.udps_hdrops + udpstat.udps_badlen);
524                 rrddim_set(st, "NoPorts", udpstat.udps_noport);
525                 rrddim_set(st, "RcvbufErrors", udpstat.udps_fullsock);
526                 rrddim_set(st, "InCsumErrors", udpstat.udps_badsum + udpstat.udps_nosum);
527                 rrddim_set(st, "IgnoredMulti", udpstat.udps_filtermcast);
528                 rrdset_done(st);
529             }
530         }
531     }
532
533     // --------------------------------------------------------------------
534
535     if (likely(do_icmp_packets || do_icmpmsg)) {
536         if (unlikely(GETSYSCTL("net.inet.icmp.stats", icmpstat))) {
537             do_icmp_packets = 0;
538             error("DISABLED: ipv4.icmp");
539             error("DISABLED: ipv4.icmp_errors");
540             do_icmpmsg = 0;
541             error("DISABLED: ipv4.icmpmsg");
542         } else {
543             for (i = 0; i <= ICMP_MAXTYPE; i++) {
544                 icmp_total.msgs_in += icmpstat.icps_inhist[i];
545                 icmp_total.msgs_out += icmpstat.icps_outhist[i];
546             }
547             icmp_total.msgs_in += icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort;
548
549             // --------------------------------------------------------------------
550
551             if (likely(do_icmp_packets)) {
552                 st = rrdset_find("ipv4.icmp");
553                 if (unlikely(!st)) {
554                     st = rrdset_create("ipv4", "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets", "packets/s",
555                                        2602,
556                                        update_every, RRDSET_TYPE_LINE);
557
558                     rrddim_add(st, "InMsgs", "received", 1, 1, RRDDIM_INCREMENTAL);
559                     rrddim_add(st, "OutMsgs", "sent", -1, 1, RRDDIM_INCREMENTAL);
560                 } else
561                     rrdset_next(st);
562
563                 rrddim_set(st, "InMsgs", icmp_total.msgs_in);
564                 rrddim_set(st, "OutMsgs", icmp_total.msgs_out);
565
566                 rrdset_done(st);
567
568                 // --------------------------------------------------------------------
569
570                 st = rrdset_find("ipv4.icmp_errors");
571                 if (unlikely(!st)) {
572                     st = rrdset_create("ipv4", "icmp_errors", NULL, "icmp", NULL, "IPv4 ICMP Errors",
573                                        "packets/s",
574                                        2603, update_every, RRDSET_TYPE_LINE);
575
576                     rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
577                     rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
578                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
579                 } else
580                     rrdset_next(st);
581
582                 rrddim_set(st, "InErrors", icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort);
583                 rrddim_set(st, "OutErrors", icmpstat.icps_error);
584                 rrddim_set(st, "InCsumErrors", icmpstat.icps_checksum);
585
586                 rrdset_done(st);
587             }
588
589             // --------------------------------------------------------------------
590
591             if (likely(do_icmpmsg)) {
592                 st = rrdset_find("ipv4.icmpmsg");
593                 if (unlikely(!st)) {
594                     st = rrdset_create("ipv4", "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messsages",
595                                        "packets/s", 2604, update_every, RRDSET_TYPE_LINE);
596
597                     rrddim_add(st, "InEchoReps", NULL, 1, 1, RRDDIM_INCREMENTAL);
598                     rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRDDIM_INCREMENTAL);
599                     rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_INCREMENTAL);
600                     rrddim_add(st, "OutEchos", NULL, -1, 1, RRDDIM_INCREMENTAL);
601                 } else
602                     rrdset_next(st);
603
604                     rrddim_set(st, "InEchoReps", icmpstat.icps_inhist[ICMP_ECHOREPLY]);
605                     rrddim_set(st, "OutEchoReps", icmpstat.icps_outhist[ICMP_ECHOREPLY]);
606                     rrddim_set(st, "InEchos", icmpstat.icps_inhist[ICMP_ECHO]);
607                     rrddim_set(st, "OutEchos", icmpstat.icps_outhist[ICMP_ECHO]);
608
609                 rrdset_done(st);
610             }
611         }
612     }
613
614     // --------------------------------------------------------------------
615
616     // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html
617     if (likely(do_ip_packets || do_ip_fragsout || do_ip_fragsin || do_ip_errors)) {
618         if (unlikely(GETSYSCTL("net.inet.ip.stats", ipstat))) {
619             do_ip_packets = 0;
620             error("DISABLED: ipv4.packets");
621             do_ip_fragsout = 0;
622             error("DISABLED: ipv4.fragsout");
623             do_ip_fragsin = 0;
624             error("DISABLED: ipv4.fragsin");
625             do_ip_errors = 0;
626             error("DISABLED: ipv4.errors");
627         } else {
628             if (likely(do_ip_packets)) {
629                 st = rrdset_find("ipv4.packets");
630                 if (unlikely(!st)) {
631                     st = rrdset_create("ipv4", "packets", NULL, "packets", NULL, "IPv4 Packets", "packets/s",
632                                        3000, update_every, RRDSET_TYPE_LINE);
633
634                     rrddim_add(st, "InReceives", "received", 1, 1, RRDDIM_INCREMENTAL);
635                     rrddim_add(st, "OutRequests", "sent", -1, 1, RRDDIM_INCREMENTAL);
636                     rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRDDIM_INCREMENTAL);
637                     rrddim_add(st, "InDelivers", "delivered", 1, 1, RRDDIM_INCREMENTAL);
638                 } else
639                     rrdset_next(st);
640
641                 rrddim_set(st, "OutRequests", ipstat.ips_localout);
642                 rrddim_set(st, "InReceives", ipstat.ips_total);
643                 rrddim_set(st, "ForwDatagrams", ipstat.ips_forward);
644                 rrddim_set(st, "InDelivers", ipstat.ips_delivered);
645                 rrdset_done(st);
646             }
647
648             // --------------------------------------------------------------------
649
650             if (likely(do_ip_fragsout)) {
651                 st = rrdset_find("ipv4.fragsout");
652                 if (unlikely(!st)) {
653                     st = rrdset_create("ipv4", "fragsout", NULL, "fragments", NULL, "IPv4 Fragments Sent",
654                                        "packets/s", 3010, update_every, RRDSET_TYPE_LINE);
655                     st->isdetail = 1;
656
657                     rrddim_add(st, "FragOKs", "ok", 1, 1, RRDDIM_INCREMENTAL);
658                     rrddim_add(st, "FragFails", "failed", -1, 1, RRDDIM_INCREMENTAL);
659                     rrddim_add(st, "FragCreates", "created", 1, 1, RRDDIM_INCREMENTAL);
660                 } else
661                     rrdset_next(st);
662
663                 rrddim_set(st, "FragOKs", ipstat.ips_fragmented);
664                 rrddim_set(st, "FragFails", ipstat.ips_cantfrag);
665                 rrddim_set(st, "FragCreates", ipstat.ips_ofragments);
666                 rrdset_done(st);
667             }
668
669             // --------------------------------------------------------------------
670
671             if (likely(do_ip_fragsin)) {
672                 st = rrdset_find("ipv4.fragsin");
673                 if (unlikely(!st)) {
674                     st = rrdset_create("ipv4", "fragsin", NULL, "fragments", NULL,
675                                        "IPv4 Fragments Reassembly",
676                                        "packets/s", 3011, update_every, RRDSET_TYPE_LINE);
677                     st->isdetail = 1;
678
679                     rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRDDIM_INCREMENTAL);
680                     rrddim_add(st, "ReasmFails", "failed", -1, 1, RRDDIM_INCREMENTAL);
681                     rrddim_add(st, "ReasmReqds", "all", 1, 1, RRDDIM_INCREMENTAL);
682                 } else
683                     rrdset_next(st);
684
685                 rrddim_set(st, "ReasmOKs", ipstat.ips_fragments);
686                 rrddim_set(st, "ReasmFails", ipstat.ips_fragdropped);
687                 rrddim_set(st, "ReasmReqds", ipstat.ips_reassembled);
688                 rrdset_done(st);
689             }
690
691             // --------------------------------------------------------------------
692
693             if (likely(do_ip_errors)) {
694                 st = rrdset_find("ipv4.errors");
695                 if (unlikely(!st)) {
696                     st = rrdset_create("ipv4", "errors", NULL, "errors", NULL, "IPv4 Errors", "packets/s",
697                                        3002,
698                                        update_every, RRDSET_TYPE_LINE);
699                     st->isdetail = 1;
700
701                     rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_INCREMENTAL);
702                     rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_INCREMENTAL);
703
704                     rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
705                     rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_INCREMENTAL);
706
707                     rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
708                     rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRDDIM_INCREMENTAL);
709                 } else
710                     rrdset_next(st);
711
712                 rrddim_set(st, "InDiscards", ipstat.ips_badsum + ipstat.ips_tooshort + ipstat.ips_toosmall + ipstat.ips_toolong);
713                 rrddim_set(st, "OutDiscards", ipstat.ips_odropped);
714                 rrddim_set(st, "InHdrErrors", ipstat.ips_badhlen + ipstat.ips_badlen + ipstat.ips_badoptions + ipstat.ips_badvers);
715                 rrddim_set(st, "InAddrErrors", ipstat.ips_badaddr);
716                 rrddim_set(st, "InUnknownProtos", ipstat.ips_noproto);
717                 rrddim_set(st, "OutNoRoutes", ipstat.ips_noroute);
718                 rrdset_done(st);
719             }
720         }
721     }
722  
723     // --------------------------------------------------------------------
724
725     if (likely(do_ip6_packets || do_ip6_fragsout || do_ip6_fragsin || do_ip6_errors)) {
726         if (unlikely(GETSYSCTL("net.inet6.ip6.stats", ip6stat))) {
727             do_ip6_packets = 0;
728             error("DISABLED: ipv6.packets");
729             do_ip6_fragsout = 0;
730             error("DISABLED: ipv6.fragsout");
731             do_ip6_fragsin = 0;
732             error("DISABLED: ipv6.fragsin");
733             do_ip6_errors = 0;
734             error("DISABLED: ipv6.errors");
735         } else {
736             if (do_ip6_packets == CONFIG_ONDEMAND_YES || (do_ip6_packets == CONFIG_ONDEMAND_ONDEMAND &&
737                                                           (ip6stat.ip6s_localout || ip6stat.ip6s_total ||
738                                                            ip6stat.ip6s_forward || ip6stat.ip6s_delivered))) {
739                 do_ip6_packets = CONFIG_ONDEMAND_YES;
740                 st = rrdset_find("ipv6.packets");
741                 if (unlikely(!st)) {
742                     st = rrdset_create("ipv6", "packets", NULL, "packets", NULL, "IPv6 Packets", "packets/s", 3000,
743                                        update_every, RRDSET_TYPE_LINE);
744
745                     rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
746                     rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
747                     rrddim_add(st, "forwarded", NULL, 1, 1, RRDDIM_INCREMENTAL);
748                     rrddim_add(st, "delivers", NULL, -1, 1, RRDDIM_INCREMENTAL);
749                 } else
750                     rrdset_next(st);
751
752                 rrddim_set(st, "sent", ip6stat.ip6s_localout);
753                 rrddim_set(st, "received", ip6stat.ip6s_total);
754                 rrddim_set(st, "forwarded", ip6stat.ip6s_forward);
755                 rrddim_set(st, "delivers", ip6stat.ip6s_delivered);
756                 rrdset_done(st);
757             }
758
759             // --------------------------------------------------------------------
760
761             if (do_ip6_fragsout == CONFIG_ONDEMAND_YES || (do_ip6_fragsout == CONFIG_ONDEMAND_ONDEMAND &&
762                                                            (ip6stat.ip6s_fragmented || ip6stat.ip6s_cantfrag ||
763                                                             ip6stat.ip6s_ofragments))) {
764                 do_ip6_fragsout = CONFIG_ONDEMAND_YES;
765                 st = rrdset_find("ipv6.fragsout");
766                 if (unlikely(!st)) {
767                     st = rrdset_create("ipv6", "fragsout", NULL, "fragments", NULL, "IPv6 Fragments Sent",
768                                        "packets/s", 3010, update_every, RRDSET_TYPE_LINE);
769                     st->isdetail = 1;
770
771                     rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL);
772                     rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
773                     rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL);
774                 } else
775                     rrdset_next(st);
776
777                 rrddim_set(st, "ok", ip6stat.ip6s_fragmented);
778                 rrddim_set(st, "failed", ip6stat.ip6s_cantfrag);
779                 rrddim_set(st, "all", ip6stat.ip6s_ofragments);
780                 rrdset_done(st);
781             }
782
783             // --------------------------------------------------------------------
784
785             if (do_ip6_fragsin == CONFIG_ONDEMAND_YES || (do_ip6_fragsin == CONFIG_ONDEMAND_ONDEMAND &&
786                                                           (ip6stat.ip6s_reassembled || ip6stat.ip6s_fragdropped ||
787                                                            ip6stat.ip6s_fragtimeout || ip6stat.ip6s_fragments))) {
788                 do_ip6_fragsin = CONFIG_ONDEMAND_YES;
789                 st = rrdset_find("ipv6.fragsin");
790                 if (unlikely(!st)) {
791                     st = rrdset_create("ipv6", "fragsin", NULL, "fragments", NULL, "IPv6 Fragments Reassembly",
792                                        "packets/s", 3011, update_every, RRDSET_TYPE_LINE);
793                     st->isdetail = 1;
794
795                     rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_INCREMENTAL);
796                     rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_INCREMENTAL);
797                     rrddim_add(st, "timeout", NULL, -1, 1, RRDDIM_INCREMENTAL);
798                     rrddim_add(st, "all", NULL, 1, 1, RRDDIM_INCREMENTAL);
799                 } else
800                     rrdset_next(st);
801
802                 rrddim_set(st, "ok", ip6stat.ip6s_reassembled);
803                 rrddim_set(st, "failed", ip6stat.ip6s_fragdropped);
804                 rrddim_set(st, "timeout", ip6stat.ip6s_fragtimeout);
805                 rrddim_set(st, "all", ip6stat.ip6s_fragments);
806                 rrdset_done(st);
807             }
808
809             // --------------------------------------------------------------------
810
811             if (do_ip6_errors == CONFIG_ONDEMAND_YES || (do_ip6_errors == CONFIG_ONDEMAND_ONDEMAND && (
812                     ip6stat.ip6s_toosmall ||
813                     ip6stat.ip6s_odropped ||
814                     ip6stat.ip6s_badoptions ||
815                     ip6stat.ip6s_badvers ||
816                     ip6stat.ip6s_exthdrtoolong ||
817                     ip6stat.ip6s_sources_none ||
818                     ip6stat.ip6s_tooshort ||
819                     ip6stat.ip6s_cantforward ||
820                     ip6stat.ip6s_noroute))) {
821                 do_ip6_errors = CONFIG_ONDEMAND_YES;
822                 st = rrdset_find("ipv6.errors");
823                 if (unlikely(!st)) {
824                     st = rrdset_create("ipv6", "errors", NULL, "errors", NULL, "IPv6 Errors", "packets/s", 3002,
825                                        update_every, RRDSET_TYPE_LINE);
826                     st->isdetail = 1;
827
828                     rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_INCREMENTAL);
829                     rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_INCREMENTAL);
830
831                     rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
832                     rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
833                     rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRDDIM_INCREMENTAL);
834                     rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRDDIM_INCREMENTAL);
835
836                     rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_INCREMENTAL);
837                 } else
838                     rrdset_next(st);
839
840                 rrddim_set(st, "InDiscards", ip6stat.ip6s_toosmall);
841                 rrddim_set(st, "OutDiscards", ip6stat.ip6s_odropped);
842
843                 rrddim_set(st, "InHdrErrors",
844                            ip6stat.ip6s_badoptions + ip6stat.ip6s_badvers + ip6stat.ip6s_exthdrtoolong);
845                 rrddim_set(st, "InAddrErrors", ip6stat.ip6s_sources_none);
846                 rrddim_set(st, "InTruncatedPkts", ip6stat.ip6s_tooshort);
847                 rrddim_set(st, "InNoRoutes", ip6stat.ip6s_cantforward);
848
849                 rrddim_set(st, "OutNoRoutes", ip6stat.ip6s_noroute);
850                 rrdset_done(st);
851             }
852         }
853     }
854
855     // --------------------------------------------------------------------
856
857     if (likely(do_icmp6 || do_icmp6_redir || do_icmp6_errors || do_icmp6_echos || do_icmp6_router || do_icmp6_neighbor || do_icmp6_types)) {
858         if (unlikely(GETSYSCTL("net.inet6.icmp6.stats", icmp6stat))) {
859             do_icmp6 = 0;
860             error("DISABLED: ipv6.icmp");
861         } else {
862             for (i = 0; i <= ICMP6_MAXTYPE; i++) {
863                 icmp6_total.msgs_in += icmp6stat.icp6s_inhist[i];
864                 icmp6_total.msgs_out += icmp6stat.icp6s_outhist[i];
865             }
866             icmp6_total.msgs_in += icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen + icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort;
867             if (do_icmp6 == CONFIG_ONDEMAND_YES || (do_icmp6 == CONFIG_ONDEMAND_ONDEMAND && (icmp6_total.msgs_in || icmp6_total.msgs_out))) {
868                 do_icmp6 = CONFIG_ONDEMAND_YES;
869                 st = rrdset_find("ipv6.icmp");
870                 if (unlikely(!st)) {
871                     st = rrdset_create("ipv6", "icmp", NULL, "icmp", NULL, "IPv6 ICMP Messages",
872                                        "messages/s", 10000, update_every, RRDSET_TYPE_LINE);
873
874                     rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
875                     rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
876                 } else
877                     rrdset_next(st);
878
879                 rrddim_set(st, "sent", icmp6_total.msgs_in);
880                 rrddim_set(st, "received", icmp6_total.msgs_out);
881                 rrdset_done(st);
882             }
883
884             // --------------------------------------------------------------------
885
886             if (do_icmp6_redir == CONFIG_ONDEMAND_YES || (do_icmp6_redir == CONFIG_ONDEMAND_ONDEMAND && (icmp6stat.icp6s_inhist[ND_REDIRECT] || icmp6stat.icp6s_outhist[ND_REDIRECT]))) {
887                 do_icmp6_redir = CONFIG_ONDEMAND_YES;
888                 st = rrdset_find("ipv6.icmpredir");
889                 if (unlikely(!st)) {
890                     st = rrdset_create("ipv6", "icmpredir", NULL, "icmp", NULL, "IPv6 ICMP Redirects",
891                                        "redirects/s", 10050, update_every, RRDSET_TYPE_LINE);
892
893                     rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
894                     rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
895                 } else
896                     rrdset_next(st);
897
898                 rrddim_set(st, "sent", icmp6stat.icp6s_inhist[ND_REDIRECT]);
899                 rrddim_set(st, "received", icmp6stat.icp6s_outhist[ND_REDIRECT]);
900                 rrdset_done(st);
901             }
902
903             // --------------------------------------------------------------------
904
905             if (do_icmp6_errors == CONFIG_ONDEMAND_YES || (do_icmp6_errors == CONFIG_ONDEMAND_ONDEMAND && (
906                                                                             icmp6stat.icp6s_badcode ||
907                                                                             icmp6stat.icp6s_badlen ||
908                                                                             icmp6stat.icp6s_checksum ||
909                                                                             icmp6stat.icp6s_tooshort ||
910                                                                             icmp6stat.icp6s_error ||
911                                                                             icmp6stat.icp6s_inhist[ICMP6_DST_UNREACH] ||
912                                                                             icmp6stat.icp6s_inhist[ICMP6_TIME_EXCEEDED] ||
913                                                                             icmp6stat.icp6s_inhist[ICMP6_PARAM_PROB] ||
914                                                                             icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH] ||
915                                                                             icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED] ||
916                                                                             icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]))) {
917                 do_icmp6_errors = CONFIG_ONDEMAND_YES;
918                 st = rrdset_find("ipv6.icmperrors");
919                 if (unlikely(!st)) {
920                     st = rrdset_create("ipv6", "icmperrors", NULL, "icmp", NULL, "IPv6 ICMP Errors", "errors/s", 10100, update_every, RRDSET_TYPE_LINE);
921
922                     rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
923                     rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
924
925                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
926                     rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRDDIM_INCREMENTAL);
927                     rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRDDIM_INCREMENTAL);
928                     rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRDDIM_INCREMENTAL);
929                     rrddim_add(st, "InParmProblems", NULL, 1, 1, RRDDIM_INCREMENTAL);
930                     rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRDDIM_INCREMENTAL);
931                     rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRDDIM_INCREMENTAL);
932                     rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRDDIM_INCREMENTAL);
933                 } else
934                     rrdset_next(st);
935
936                 rrddim_set(st, "InErrors", icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen + icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort);
937                 rrddim_set(st, "OutErrors", icmp6stat.icp6s_error);
938                 rrddim_set(st, "InCsumErrors", icmp6stat.icp6s_checksum);
939                 rrddim_set(st, "InDestUnreachs", icmp6stat.icp6s_inhist[ICMP6_DST_UNREACH]);
940                 rrddim_set(st, "InPktTooBigs", icmp6stat.icp6s_badlen);
941                 rrddim_set(st, "InTimeExcds", icmp6stat.icp6s_inhist[ICMP6_TIME_EXCEEDED]);
942                 rrddim_set(st, "InParmProblems", icmp6stat.icp6s_inhist[ICMP6_PARAM_PROB]);
943                 rrddim_set(st, "OutDestUnreachs", icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH]);
944                 rrddim_set(st, "OutTimeExcds", icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED]);
945                 rrddim_set(st, "OutParmProblems", icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]);
946                 rrdset_done(st);
947             }
948
949             // --------------------------------------------------------------------
950
951             if (do_icmp6_echos == CONFIG_ONDEMAND_YES || (do_icmp6_echos == CONFIG_ONDEMAND_ONDEMAND && (
952                                                                  icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST] ||
953                                                                  icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST] ||
954                                                                  icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY] ||
955                                                                  icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]))) {
956                 do_icmp6_echos = CONFIG_ONDEMAND_YES;
957                 st = rrdset_find("ipv6.icmpechos");
958                 if (unlikely(!st)) {
959                     st = rrdset_create("ipv6", "icmpechos", NULL, "icmp", NULL, "IPv6 ICMP Echo", "messages/s", 10200, update_every, RRDSET_TYPE_LINE);
960
961                     rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_INCREMENTAL);
962                     rrddim_add(st, "OutEchos", NULL, -1, 1, RRDDIM_INCREMENTAL);
963                     rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRDDIM_INCREMENTAL);
964                     rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRDDIM_INCREMENTAL);
965                 } else
966                     rrdset_next(st);
967
968                 rrddim_set(st, "InEchos", icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST]);
969                 rrddim_set(st, "OutEchos", icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST]);
970                 rrddim_set(st, "InEchoReplies", icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY]);
971                 rrddim_set(st, "OutEchoReplies", icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]);
972                 rrdset_done(st);
973             }
974
975             // --------------------------------------------------------------------
976
977             if (do_icmp6_router == CONFIG_ONDEMAND_YES || (do_icmp6_router == CONFIG_ONDEMAND_ONDEMAND && (
978                                                                     icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT] ||
979                                                                     icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT] ||
980                                                                     icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT] ||
981                                                                     icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]))) {
982                 do_icmp6_router = CONFIG_ONDEMAND_YES;
983                 st = rrdset_find("ipv6.icmprouter");
984                 if (unlikely(!st)) {
985                     st = rrdset_create("ipv6", "icmprouter", NULL, "icmp", NULL, "IPv6 Router Messages", "messages/s", 10400, update_every, RRDSET_TYPE_LINE);
986
987                     rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL);
988                     rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_INCREMENTAL);
989                     rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_INCREMENTAL);
990                     rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_INCREMENTAL);
991                 } else
992                     rrdset_next(st);
993
994                 rrddim_set(st, "InSolicits", icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT]);
995                 rrddim_set(st, "OutSolicits", icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT]);
996                 rrddim_set(st, "InAdvertisements", icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT]);
997                 rrddim_set(st, "OutAdvertisements", icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]);
998                 rrdset_done(st);
999             }
1000
1001             // --------------------------------------------------------------------
1002
1003             if (do_icmp6_neighbor == CONFIG_ONDEMAND_YES || (do_icmp6_neighbor == CONFIG_ONDEMAND_ONDEMAND && (
1004                                                                     icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT] ||
1005                                                                     icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT] ||
1006                                                                     icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT] ||
1007                                                                     icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]))) {
1008                 do_icmp6_neighbor = CONFIG_ONDEMAND_YES;
1009                 st = rrdset_find("ipv6.icmpneighbor");
1010                 if (unlikely(!st)) {
1011                     st = rrdset_create("ipv6", "icmpneighbor", NULL, "icmp", NULL, "IPv6 Neighbor Messages", "messages/s", 10500, update_every, RRDSET_TYPE_LINE);
1012
1013                     rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_INCREMENTAL);
1014                     rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_INCREMENTAL);
1015                     rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_INCREMENTAL);
1016                     rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_INCREMENTAL);
1017                 } else
1018                     rrdset_next(st);
1019
1020                 rrddim_set(st, "InSolicits", icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT]);
1021                 rrddim_set(st, "OutSolicits", icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]);
1022                 rrddim_set(st, "InAdvertisements", icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT]);
1023                 rrddim_set(st, "OutAdvertisements", icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]);
1024                 rrdset_done(st);
1025             }
1026
1027             // --------------------------------------------------------------------
1028
1029             if (do_icmp6_types == CONFIG_ONDEMAND_YES || (do_icmp6_types == CONFIG_ONDEMAND_ONDEMAND && (
1030                                                                     icmp6stat.icp6s_inhist[1] ||
1031                                                                     icmp6stat.icp6s_inhist[128] ||
1032                                                                     icmp6stat.icp6s_inhist[129] ||
1033                                                                     icmp6stat.icp6s_inhist[136] ||
1034                                                                     icmp6stat.icp6s_outhist[1] ||
1035                                                                     icmp6stat.icp6s_outhist[128] ||
1036                                                                     icmp6stat.icp6s_outhist[129] ||
1037                                                                     icmp6stat.icp6s_outhist[133] ||
1038                                                                     icmp6stat.icp6s_outhist[135] ||
1039                                                                     icmp6stat.icp6s_outhist[136]))) {
1040                 do_icmp6_types = CONFIG_ONDEMAND_YES;
1041                 st = rrdset_find("ipv6.icmptypes");
1042                 if (unlikely(!st)) {
1043                     st = rrdset_create("ipv6", "icmptypes", NULL, "icmp", NULL, "IPv6 ICMP Types",
1044                                        "messages/s", 10700, update_every, RRDSET_TYPE_LINE);
1045
1046                     rrddim_add(st, "InType1", NULL, 1, 1, RRDDIM_INCREMENTAL);
1047                     rrddim_add(st, "InType128", NULL, 1, 1, RRDDIM_INCREMENTAL);
1048                     rrddim_add(st, "InType129", NULL, 1, 1, RRDDIM_INCREMENTAL);
1049                     rrddim_add(st, "InType136", NULL, 1, 1, RRDDIM_INCREMENTAL);
1050                     rrddim_add(st, "OutType1", NULL, -1, 1, RRDDIM_INCREMENTAL);
1051                     rrddim_add(st, "OutType128", NULL, -1, 1, RRDDIM_INCREMENTAL);
1052                     rrddim_add(st, "OutType129", NULL, -1, 1, RRDDIM_INCREMENTAL);
1053                     rrddim_add(st, "OutType133", NULL, -1, 1, RRDDIM_INCREMENTAL);
1054                     rrddim_add(st, "OutType135", NULL, -1, 1, RRDDIM_INCREMENTAL);
1055                     rrddim_add(st, "OutType143", NULL, -1, 1, RRDDIM_INCREMENTAL);
1056                 } else
1057                     rrdset_next(st);
1058
1059                 rrddim_set(st, "InType1", icmp6stat.icp6s_inhist[1]);
1060                 rrddim_set(st, "InType128", icmp6stat.icp6s_inhist[128]);
1061                 rrddim_set(st, "InType129", icmp6stat.icp6s_inhist[129]);
1062                 rrddim_set(st, "InType136", icmp6stat.icp6s_inhist[136]);
1063                 rrddim_set(st, "OutType1", icmp6stat.icp6s_outhist[1]);
1064                 rrddim_set(st, "OutType128", icmp6stat.icp6s_outhist[128]);
1065                 rrddim_set(st, "OutType129", icmp6stat.icp6s_outhist[129]);
1066                 rrddim_set(st, "OutType133", icmp6stat.icp6s_outhist[133]);
1067                 rrddim_set(st, "OutType135", icmp6stat.icp6s_outhist[135]);
1068                 rrddim_set(st, "OutType143", icmp6stat.icp6s_outhist[143]);
1069                 rrdset_done(st);
1070             }
1071         }
1072     }
1073
1074     // --------------------------------------------------------------------
1075
1076     if (likely(do_uptime)) {
1077         if (unlikely(GETSYSCTL("kern.boottime", boot_time))) {
1078             do_uptime = 0;
1079             error("DISABLED: system.uptime");
1080         } else {
1081             clock_gettime(CLOCK_REALTIME, &cur_time);
1082             st = rrdset_find("system.uptime");
1083
1084             if(unlikely(!st)) {
1085                 st = rrdset_create("system", "uptime", NULL, "uptime", NULL, "System Uptime", "seconds", 1000, update_every, RRDSET_TYPE_LINE);
1086                 rrddim_add(st, "uptime", NULL, 1, 1, RRDDIM_ABSOLUTE);
1087             }
1088             else rrdset_next(st);
1089
1090             rrddim_set(st, "uptime", cur_time.tv_sec - boot_time.tv_sec);
1091             rrdset_done(st);
1092         }
1093     }
1094
1095     return 0;
1096 }
1097
1098 int getsysctl(const char *name, void *ptr, size_t len)
1099 {
1100     size_t nlen = len;
1101
1102     if (unlikely(sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)) {
1103         error("MACOS: sysctl(%s...) failed: %s", name, strerror(errno));
1104         return 1;
1105     }
1106     if (unlikely(nlen != len)) {
1107         error("MACOS: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen);
1108         return 1;
1109     }
1110     return 0;
1111 }