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"
29 #include "common.h"
30 #include "plugin.h"
31 #include "utils_ignorelist.h"
33 #if !KERNEL_LINUX
34 # error "No applicable input method."
35 #endif
37 #define SNMP_FILE "/proc/net/snmp"
38 #define NETSTAT_FILE "/proc/net/netstat"
40 /*
41 * Global variables
42 */
43 static const char *config_keys[] =
44 {
45 "Value",
46 "IgnoreSelected",
47 };
48 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
50 static ignorelist_t *values_list = NULL;
52 /*
53 * Functions
54 */
55 static void submit (const char *protocol_name,
56 const char *str_key, const char *str_value)
57 {
58 value_t values[1];
59 value_list_t vl = VALUE_LIST_INIT;
60 int status;
62 status = parse_value (str_value, values, DS_TYPE_DERIVE);
63 if (status != 0)
64 {
65 ERROR ("protocols plugin: Parsing string as integer failed: %s",
66 str_value);
67 return;
68 }
70 vl.values = values;
71 vl.values_len = 1;
72 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
73 sstrncpy (vl.plugin, "protocols", sizeof (vl.plugin));
74 sstrncpy (vl.plugin_instance, protocol_name, sizeof (vl.plugin_instance));
75 sstrncpy (vl.type, "protocol_counter", sizeof (vl.type));
76 sstrncpy (vl.type_instance, str_key, sizeof (vl.type_instance));
78 plugin_dispatch_values (&vl);
79 } /* void submit */
81 static int read_file (const char *path)
82 {
83 FILE *fh;
84 char key_buffer[4096];
85 char value_buffer[4096];
86 char *key_ptr;
87 char *value_ptr;
88 char *key_fields[256];
89 char *value_fields[256];
90 int key_fields_num;
91 int value_fields_num;
92 int status;
93 int i;
95 fh = fopen (path, "r");
96 if (fh == NULL)
97 {
98 ERROR ("protocols plugin: fopen (%s) failed: %s.",
99 path, sstrerror (errno, key_buffer, sizeof (key_buffer)));
100 return (-1);
101 }
103 status = -1;
104 while (42)
105 {
106 clearerr (fh);
107 key_ptr = fgets (key_buffer, sizeof (key_buffer), fh);
108 if (key_ptr == NULL)
109 {
110 if (feof (fh) != 0)
111 {
112 status = 0;
113 break;
114 }
115 else if (ferror (fh) != 0)
116 {
117 ERROR ("protocols plugin: Reading from %s failed.", path);
118 break;
119 }
120 else
121 {
122 ERROR ("protocols plugin: fgets failed for an unknown reason.");
123 break;
124 }
125 } /* if (key_ptr == NULL) */
127 value_ptr = fgets (value_buffer, sizeof (value_buffer), fh);
128 if (value_ptr == NULL)
129 {
130 ERROR ("protocols plugin: read_file (%s): Could not read values line.",
131 path);
132 break;
133 }
135 key_ptr = strchr (key_buffer, ':');
136 if (key_ptr == NULL)
137 {
138 ERROR ("protocols plugin: Could not find protocol name in keys line.");
139 break;
140 }
141 *key_ptr = 0;
142 key_ptr++;
144 value_ptr = strchr (value_buffer, ':');
145 if (value_ptr == NULL)
146 {
147 ERROR ("protocols plugin: Could not find protocol name "
148 "in values line.");
149 break;
150 }
151 *value_ptr = 0;
152 value_ptr++;
154 if (strcmp (key_buffer, value_buffer) != 0)
155 {
156 ERROR ("protocols plugin: Protocol names in keys and values lines "
157 "don't match: `%s' vs. `%s'.",
158 key_buffer, value_buffer);
159 break;
160 }
163 key_fields_num = strsplit (key_ptr,
164 key_fields, STATIC_ARRAY_SIZE (key_fields));
165 value_fields_num = strsplit (value_ptr,
166 value_fields, STATIC_ARRAY_SIZE (value_fields));
168 if (key_fields_num != value_fields_num)
169 {
170 ERROR ("protocols plugin: Number of fields in keys and values lines "
171 "don't match: %i vs %i.",
172 key_fields_num, value_fields_num);
173 break;
174 }
176 for (i = 0; i < key_fields_num; i++)
177 {
178 if (values_list != NULL)
179 {
180 char match_name[2 * DATA_MAX_NAME_LEN];
182 ssnprintf (match_name, sizeof (match_name), "%s:%s",
183 key_buffer, key_fields[i]);
185 if (ignorelist_match (values_list, match_name))
186 continue;
187 } /* if (values_list != NULL) */
189 submit (key_buffer, key_fields[i], value_fields[i]);
190 } /* for (i = 0; i < key_fields_num; i++) */
191 } /* while (42) */
193 fclose (fh);
195 return (status);
196 } /* int read_file */
198 static int protocols_read (void)
199 {
200 int status;
201 int success = 0;
203 status = read_file (SNMP_FILE);
204 if (status == 0)
205 success++;
207 status = read_file (NETSTAT_FILE);
208 if (status == 0)
209 success++;
211 if (success == 0)
212 return (-1);
214 return (0);
215 } /* int protocols_read */
217 static int protocols_config (const char *key, const char *value)
218 {
219 if (values_list == NULL)
220 values_list = ignorelist_create (/* invert = */ 1);
222 if (strcasecmp (key, "Value") == 0)
223 {
224 ignorelist_add (values_list, value);
225 }
226 else if (strcasecmp (key, "IgnoreSelected") == 0)
227 {
228 int invert = 1;
229 if (IS_TRUE (value))
230 invert = 0;
231 ignorelist_set_invert (values_list, invert);
232 }
233 else
234 {
235 return (-1);
236 }
238 return (0);
239 } /* int protocols_config */
241 void module_register (void)
242 {
243 plugin_register_config ("protocols", protocols_config,
244 config_keys, config_keys_num);
245 plugin_register_read ("protocols", protocols_read);
246 } /* void module_register */
248 /* vim: set sw=2 sts=2 et : */