1 /**
2 * collectd - src/protocols.c
3 * Copyright (C) 2009,2010 Florian octo Forster
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Florian octo Forster <octo at collectd.org>
25 **/
27 #include "collectd.h"
28 #include "common.h"
29 #include "plugin.h"
30 #include "utils_ignorelist.h"
32 #if !KERNEL_LINUX
33 # error "No applicable input method."
34 #endif
36 #define SNMP_FILE "/proc/net/snmp"
37 #define NETSTAT_FILE "/proc/net/netstat"
39 /*
40 * Global variables
41 */
42 static const char *config_keys[] =
43 {
44 "Value",
45 "IgnoreSelected",
46 };
47 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
49 static ignorelist_t *values_list = NULL;
51 /*
52 * Functions
53 */
54 static void submit (const char *protocol_name,
55 const char *str_key, const char *str_value)
56 {
57 value_t values[1];
58 value_list_t vl = VALUE_LIST_INIT;
59 int status;
61 status = parse_value (str_value, values, DS_TYPE_DERIVE);
62 if (status != 0)
63 {
64 ERROR ("protocols plugin: Parsing string as integer failed: %s",
65 str_value);
66 return;
67 }
69 vl.values = values;
70 vl.values_len = 1;
71 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
72 sstrncpy (vl.plugin, "protocols", sizeof (vl.plugin));
73 sstrncpy (vl.plugin_instance, protocol_name, sizeof (vl.plugin_instance));
74 sstrncpy (vl.type, "protocol_counter", sizeof (vl.type));
75 sstrncpy (vl.type_instance, str_key, sizeof (vl.type_instance));
77 plugin_dispatch_values (&vl);
78 } /* void submit */
80 static int read_file (const char *path)
81 {
82 FILE *fh;
83 char key_buffer[4096];
84 char value_buffer[4096];
85 char *key_ptr;
86 char *value_ptr;
87 char *key_fields[256];
88 char *value_fields[256];
89 int key_fields_num;
90 int value_fields_num;
91 int status;
92 int i;
94 fh = fopen (path, "r");
95 if (fh == NULL)
96 {
97 ERROR ("protocols plugin: fopen (%s) failed: %s.",
98 path, sstrerror (errno, key_buffer, sizeof (key_buffer)));
99 return (-1);
100 }
102 status = -1;
103 while (42)
104 {
105 clearerr (fh);
106 key_ptr = fgets (key_buffer, sizeof (key_buffer), fh);
107 if (key_ptr == NULL)
108 {
109 if (feof (fh) != 0)
110 {
111 status = 0;
112 break;
113 }
114 else if (ferror (fh) != 0)
115 {
116 ERROR ("protocols plugin: Reading from %s failed.", path);
117 break;
118 }
119 else
120 {
121 ERROR ("protocols plugin: fgets failed for an unknown reason.");
122 break;
123 }
124 } /* if (key_ptr == NULL) */
126 value_ptr = fgets (value_buffer, sizeof (value_buffer), fh);
127 if (value_ptr == NULL)
128 {
129 ERROR ("protocols plugin: read_file (%s): Could not read values line.",
130 path);
131 break;
132 }
134 key_ptr = strchr (key_buffer, ':');
135 if (key_ptr == NULL)
136 {
137 ERROR ("protocols plugin: Could not find protocol name in keys line.");
138 break;
139 }
140 *key_ptr = 0;
141 key_ptr++;
143 value_ptr = strchr (value_buffer, ':');
144 if (value_ptr == NULL)
145 {
146 ERROR ("protocols plugin: Could not find protocol name "
147 "in values line.");
148 break;
149 }
150 *value_ptr = 0;
151 value_ptr++;
153 if (strcmp (key_buffer, value_buffer) != 0)
154 {
155 ERROR ("protocols plugin: Protocol names in keys and values lines "
156 "don't match: `%s' vs. `%s'.",
157 key_buffer, value_buffer);
158 break;
159 }
162 key_fields_num = strsplit (key_ptr,
163 key_fields, STATIC_ARRAY_SIZE (key_fields));
164 value_fields_num = strsplit (value_ptr,
165 value_fields, STATIC_ARRAY_SIZE (value_fields));
167 if (key_fields_num != value_fields_num)
168 {
169 ERROR ("protocols plugin: Number of fields in keys and values lines "
170 "don't match: %i vs %i.",
171 key_fields_num, value_fields_num);
172 break;
173 }
175 for (i = 0; i < key_fields_num; i++)
176 {
177 if (values_list != NULL)
178 {
179 char match_name[2 * DATA_MAX_NAME_LEN];
181 ssnprintf (match_name, sizeof (match_name), "%s:%s",
182 key_buffer, key_fields[i]);
184 if (ignorelist_match (values_list, match_name))
185 continue;
186 } /* if (values_list != NULL) */
188 submit (key_buffer, key_fields[i], value_fields[i]);
189 } /* for (i = 0; i < key_fields_num; i++) */
190 } /* while (42) */
192 fclose (fh);
194 return (status);
195 } /* int read_file */
197 static int protocols_read (void)
198 {
199 int status;
200 int success = 0;
202 status = read_file (SNMP_FILE);
203 if (status == 0)
204 success++;
206 status = read_file (NETSTAT_FILE);
207 if (status == 0)
208 success++;
210 if (success == 0)
211 return (-1);
213 return (0);
214 } /* int protocols_read */
216 static int protocols_config (const char *key, const char *value)
217 {
218 if (values_list == NULL)
219 values_list = ignorelist_create (/* invert = */ 1);
221 if (strcasecmp (key, "Value") == 0)
222 {
223 ignorelist_add (values_list, value);
224 }
225 else if (strcasecmp (key, "IgnoreSelected") == 0)
226 {
227 int invert = 1;
228 if (IS_TRUE (value))
229 invert = 0;
230 ignorelist_set_invert (values_list, invert);
231 }
232 else
233 {
234 return (-1);
235 }
237 return (0);
238 } /* int protocols_config */
240 void module_register (void)
241 {
242 plugin_register_config ("protocols", protocols_config,
243 config_keys, config_keys_num);
244 plugin_register_read ("protocols", protocols_read);
245 } /* void module_register */
247 /* vim: set sw=2 sts=2 et : */