1 /**
2 * collectd - src/protocols.c
3 * Copyright (C) 2009 Florian octo Forster
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; only version 2 of the License is applicable.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 * Authors:
19 * Florian octo Forster <octo at verplant.org>
20 **/
22 #include "collectd.h"
23 #include "common.h"
24 #include "plugin.h"
25 #include "utils_ignorelist.h"
27 #if !KERNEL_LINUX
28 # error "No applicable input method."
29 #endif
31 #define SNMP_FILE "/proc/net/snmp"
32 #define NETSTAT_FILE "/proc/net/netstat"
34 /*
35 * Global variables
36 */
37 static const char *config_keys[] =
38 {
39 "Value",
40 "IgnoreSelected",
41 };
42 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
44 static ignorelist_t *values_list = NULL;
46 /*
47 * Functions
48 */
49 static void submit (const char *protocol_name,
50 const char *str_key, const char *str_value)
51 {
52 value_t values[1];
53 value_list_t vl = VALUE_LIST_INIT;
55 char *tmp_ptr;
57 errno = 0;
58 tmp_ptr = NULL;
59 values[0].counter = (counter_t) strtoll (str_value, &tmp_ptr,
60 /* base = */ 0);
61 if ((errno != 0) || (tmp_ptr == str_value))
62 {
63 ERROR ("protocols plugin: Parsing string as integer failed: %s",
64 str_value);
65 return;
66 }
68 vl.values = values;
69 vl.values_len = 1;
70 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
71 sstrncpy (vl.plugin, "protocols", sizeof (vl.plugin));
72 sstrncpy (vl.plugin_instance, protocol_name, sizeof (vl.plugin_instance));
73 sstrncpy (vl.type, "protocol_counter", sizeof (vl.type));
74 sstrncpy (vl.type_instance, str_key, sizeof (vl.type_instance));
76 plugin_dispatch_values (&vl);
77 } /* void submit */
79 static int read_file (const char *path)
80 {
81 FILE *fh;
82 char key_buffer[4096];
83 char value_buffer[4096];
84 char *key_ptr;
85 char *value_ptr;
86 char *key_fields[256];
87 char *value_fields[256];
88 int key_fields_num;
89 int value_fields_num;
90 int status;
91 int i;
93 fh = fopen (path, "r");
94 if (fh == NULL)
95 {
96 ERROR ("protocols plugin: fopen (%s) failed: %s.",
97 path, sstrerror (errno, key_buffer, sizeof (key_buffer)));
98 return (-1);
99 }
101 status = -1;
102 while (42)
103 {
104 clearerr (fh);
105 key_ptr = fgets (key_buffer, sizeof (key_buffer), fh);
106 if (key_ptr == NULL)
107 {
108 if (feof (fh) != 0)
109 {
110 status = 0;
111 break;
112 }
113 else if (ferror (fh) != 0)
114 {
115 ERROR ("protocols plugin: Reading from %s failed.", path);
116 break;
117 }
118 else
119 {
120 ERROR ("protocols plugin: fgets failed for an unknown reason.");
121 break;
122 }
123 } /* if (key_ptr == NULL) */
125 value_ptr = fgets (value_buffer, sizeof (value_buffer), fh);
126 if (value_ptr == NULL)
127 {
128 ERROR ("protocols plugin: read_file (%s): Could not read values line.",
129 path);
130 break;
131 }
133 key_ptr = strchr (key_buffer, ':');
134 if (key_ptr == NULL)
135 {
136 ERROR ("protocols plugin: Could not find protocol name in keys line.");
137 break;
138 }
139 *key_ptr = 0;
140 key_ptr++;
142 value_ptr = strchr (value_buffer, ':');
143 if (value_ptr == NULL)
144 {
145 ERROR ("protocols plugin: Could not find protocol name "
146 "in values line.");
147 break;
148 }
149 *value_ptr = 0;
150 value_ptr++;
152 if (strcmp (key_buffer, value_buffer) != 0)
153 {
154 ERROR ("protocols plugin: Protocol names in keys and values lines "
155 "don't match: `%s' vs. `%s'.",
156 key_buffer, value_buffer);
157 break;
158 }
161 key_fields_num = strsplit (key_ptr,
162 key_fields, STATIC_ARRAY_SIZE (key_fields));
163 value_fields_num = strsplit (value_ptr,
164 value_fields, STATIC_ARRAY_SIZE (value_fields));
166 if (key_fields_num != value_fields_num)
167 {
168 ERROR ("protocols plugin: Number of fields in keys and values lines "
169 "don't match: %i vs %i.",
170 key_fields_num, value_fields_num);
171 break;
172 }
174 for (i = 0; i < key_fields_num; i++)
175 {
176 if (values_list != NULL)
177 {
178 char match_name[2 * DATA_MAX_NAME_LEN];
180 ssnprintf (match_name, sizeof (match_name), "%s:%s",
181 key_buffer, key_fields[i]);
183 if (ignorelist_match (values_list, match_name))
184 continue;
185 } /* if (values_list != NULL) */
187 submit (key_buffer, key_fields[i], value_fields[i]);
188 } /* for (i = 0; i < key_fields_num; i++) */
189 } /* while (42) */
191 fclose (fh);
193 return (status);
194 } /* int read_file */
196 static int protocols_read (void)
197 {
198 int status;
199 int success = 0;
201 status = read_file (SNMP_FILE);
202 if (status == 0)
203 success++;
205 status = read_file (NETSTAT_FILE);
206 if (status == 0)
207 success++;
209 if (success == 0)
210 return (-1);
212 return (0);
213 } /* int protocols_read */
215 static int protocols_config (const char *key, const char *value)
216 {
217 if (values_list == NULL)
218 values_list = ignorelist_create (/* invert = */ 1);
220 if (strcasecmp (key, "Value") == 0)
221 {
222 ignorelist_add (values_list, value);
223 }
224 else if (strcasecmp (key, "IgnoreSelected") == 0)
225 {
226 int invert = 1;
227 if (IS_TRUE (value))
228 invert = 0;
229 ignorelist_set_invert (values_list, invert);
230 }
231 else
232 {
233 return (-1);
234 }
236 return (0);
237 } /* int protocols_config */
239 void module_register (void)
240 {
241 plugin_register_config ("protocols", protocols_config,
242 config_keys, config_keys_num);
243 plugin_register_read ("protocols", protocols_read);
244 } /* void module_register */
246 /* vim: set sw=2 sts=2 et : */