Import version 1.8.3
[s390-tools.git] / osasnmpd / osasnmpd.c
blob8605d3effe5b79afb03c609361bb643a18138f53
1 /*
2 * File...........: osasnmpd.c
3 * Author(s)......: Thomas Weber <tweber@de.ibm.com>
4 * Copyright IBM Corp. 2002,2007
6 * History of changes:
7 * 07/29 added logic '-x agentx_socket' parm
8 * exit subagent on startup, if init_agent() fails
9 *
10 * OSA-E subagent main module
11 * This subagent extends the ucd-snmp master agent to support
12 * the Direct SNMP feature of zSeries OSA-E network cards.
13 * ucd-snmp AgentX support must be enabled to allow the
14 * subagent connecting to the master agent (snmpd).
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2, or (at your option)
19 * any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 /* basic includes */
33 #include "ibmOSAMibUtil.h"
34 #include "ibmOSAMib.h"
35 #include <zt_common.h>
37 #include <signal.h>
38 #include <getopt.h>
40 #include <sys/utsname.h>
41 #include <linux/version.h>
43 /* osasnmpd version */
44 #define COPYRIGHT "Copyright IBM Corp. 2003, 2009"
46 /* ptr to OSA Express MIB information stored in linked lists */
47 extern TABLE_OID* oid_list_head;
49 sig_atomic_t keep_running = 1;
50 sig_atomic_t interfaces_changed = 0;
52 /* signal handler for SIGTERM or SIGINT */
53 RETSIGTYPE
54 stop_server(int UNUSED(a))
56 keep_running = 0;
59 /* signal handler for SIGUSR1
60 * which is send by the kernel if the interface information changes
62 RETSIGTYPE
63 on_interfaces_changed( int UNUSED(a) )
65 interfaces_changed++;
69 static void
70 sysfs_register()
72 int sys_fd;
73 char buf[10] = {0, };
75 sys_fd = open( QETH_SYSFILE, O_WRONLY );
76 if (sys_fd < 0) {
77 fprintf(stderr, "open(%s) failed - reason %s\n",
78 QETH_SYSFILE, strerror( errno ) );
79 exit(1);
81 sprintf(buf, "%d", QETH_UPDATE_MIB_SIGNAL);
82 /* register our process to receive SIGUSR1 on interface changes */
83 if(write(sys_fd, buf, 10) < 0){
84 fprintf(stderr, "registration with qeth driver failed - "
85 "reason %s\n", strerror( errno ) );
86 close(sys_fd);
87 exit(1);
89 close(sys_fd);
92 static void
93 sysfs_unregister()
95 int sys_fd;
97 sys_fd = open( QETH_SYSFILE, O_WRONLY );
98 if (sys_fd < 0) {
99 fprintf(stderr, "open(%s) failed - reason %s\n",
100 QETH_SYSFILE, strerror( errno ) );
101 exit(1);
103 /* unregister our process to receive SIGUSR1 on interface changes */
104 if(write(sys_fd, "unregister", 11) < 0){
105 fprintf(stderr, "deregistration with qeth driver failed - "
106 "reason %s\n", strerror( errno ) );
107 close(sys_fd);
108 exit(1);
110 close(sys_fd);
113 static struct option longopts[] = {
114 {"help",no_argument,0,'h'},
115 {"version",no_argument,0,'v'},
116 {"append",no_argument,0,'A'},
117 {"stderrlog",no_argument,0,'L'},
118 {"nofork",no_argument,0,'f'},
119 {"logfile",required_argument,0,'l'},
120 {"pidfile",required_argument,0,'P'},
121 {"sockaddr",required_argument,0,'x'},
122 {0,0,0,0}
125 #define OPTSTRING "hvALfl:A:P:x:"
128 * main routine
130 int main( int argc, char *argv[] )
132 TABLE_OID* li_ptr;
133 char oidstr[MAX_OID_STR_LEN];
134 char logfile[PATH_MAX + 1];
135 char pid_file[PATH_MAX + 1];
136 FILE *PID;
137 struct sigaction act;
138 int res,c,longIndex,rc;
139 unsigned char rel_a, rel_b, rel_c;
140 struct utsname buf;
141 char suffix[sizeof(buf.release)];
143 /* default settings, may be overridden by parameters */
144 int std_err_log = 0; /* 0=turn off stderr logging; 1=turn on */
145 /* if turned off; use file logging */
146 int dont_zero_log = 0; /* 0=clear logfile; 1=append to logfile */
147 int dont_fork = 0; /* 0=dont detach from shell; 1=detach */
148 int pid_file_set = 0;
149 strcpy( logfile, OSAE_LOGFILE ); /* default log file */
151 /* check for parameters */
152 while((c = getopt_long(argc, argv, OPTSTRING, longopts,
153 &longIndex)) != -1) {
154 switch (c) {
155 case 'h':
156 usage();
157 exit(0);
158 case 'v':
159 printf( "osasnmpd: version %s\n",
160 RELEASE_STRING);
161 printf( "%s\n" , COPYRIGHT );
162 exit(0);
163 case 'l':
164 if (strlen(optarg) > PATH_MAX)
166 fprintf( stderr, "osasnmpd: logfile "\
167 "path too long (limit %d "\
168 "chars)\n", PATH_MAX);
169 exit(1);
171 strncpy(logfile, optarg, PATH_MAX);
172 break;
173 case 'A':
174 dont_zero_log = 1;
175 break;
176 case 'L':
177 std_err_log=1;
178 break;
179 case 'f':
180 dont_fork = 1;
181 break;
182 case 'P':
183 if (strlen(optarg) > PATH_MAX)
185 fprintf( stderr, "osasnmpd: logfile "\
186 "path too long (limit %d "\
187 "chars)\n", PATH_MAX);
188 exit(1);
190 strncpy(pid_file,optarg,PATH_MAX);
191 pid_file_set = 1;
192 break;
193 case 'x':
194 #ifdef NETSNMP5
195 netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
196 NETSNMP_DS_AGENT_X_SOCKET, optarg);
197 #else
198 ds_set_string(NETSNMP_DS_APPLICATION_ID,
199 NETSNMP_DS_AGENT_X_SOCKET, optarg);
200 #endif
201 break;
202 default:
203 fprintf(stderr, "Try 'osasnmpd --help' for more"
204 " information.\n");
205 exit(1);
206 } /* end switch */
207 } /* end-while */
209 while (optind < argc) {
210 fprintf(stderr, "osasnmpd: unrecognized argument '%s'\n",
211 argv[optind++]);
212 fprintf(stderr, "Try 'osasnmpd --help' for more"
213 " information.\n");
214 exit(1);
216 /* detach from shell (default) */
217 if (!dont_fork && fork() != 0)
218 exit(0);
220 /* create a pidfile if requested */
221 if (pid_file_set) {
222 if ((PID = fopen(pid_file, "w")) == NULL) {
223 snmp_log_perror("fopen");
224 fprintf(stderr, "osasnmpd: cannot create PIDFILE\n");
225 exit(1);
226 } else {
227 fprintf(PID, "%d\n", (int) getpid() );
228 fclose(PID);
232 /* enable logging to stderr or logfile */
233 if ( !std_err_log ) {
234 snmp_disable_stderrlog();
235 snmp_enable_filelog( logfile, dont_zero_log );
236 } else {
237 snmp_enable_stderrlog();
241 #ifdef NETSNMP5
242 snmp_log(LOG_INFO, "IBM OSA-E NET-SNMP 5.1.x subagent version %s\n",
243 RELEASE_STRING );
244 #else
245 snmp_log(LOG_INFO, "IBM OSA-E ucd-snmp 4.2.x subagent version %s\n",
246 RELEASE_STRING );
247 #endif
249 /* make us a agentx client. */
250 #ifdef NETSNMP5
251 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE,
252 1);
253 #else
254 ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1);
255 #endif
257 /* initialize the agent library */
258 if ( init_agent("osasnmpd") != 0 ) {
259 fprintf(stderr, "osasnmpd: init_agent() failed\n"
260 "osasnmpd: check subagent logfile for detailed "
261 "information\n" );
262 exit(1);
264 /* initialize OSA Express MIB module here */
265 init_ibmOSAMib();
267 /* osasnmpd will be used to read osasnmpd.conf files. */
268 init_snmp("osasnmpd");
270 act.sa_flags = 0;
271 sigemptyset( &act.sa_mask );
273 /* handle termination requests (kill -TERM or kill -INT) */
274 act.sa_handler = stop_server;
275 if( sigaction( SIGTERM, &act, NULL ) < 0 ){
276 fprintf(stderr, "sigaction( SIGTERM, ... ) failed - "
277 "reason %s\n", strerror( errno ) );
278 exit( 1 );
281 act.sa_handler = stop_server;
282 if( sigaction( SIGINT, &act, NULL ) < 0 ){
283 fprintf(stderr, "sigaction( SIGINT, ... ) failed - reason %s\n",
284 strerror( errno ) );
285 exit( 1 );
288 /* handle iterface count change requests ( kill -SIGUSR1 ) */
289 act.sa_handler = on_interfaces_changed;
290 if( sigaction( SIGUSR1, &act, NULL ) ){
291 fprintf(stderr, "sigaction( SIGUSR1, ... ) failed - "
292 "reason %s\n", strerror( errno ) );
293 exit( 1 );
296 rc = uname(&buf);
297 if (!rc)
298 sscanf(buf.release, "%c.%c.%c-%s",
299 &rel_a, &rel_b, &rel_c, suffix);
301 if(KERNEL_VERSION(2,6,22) >= KERNEL_VERSION(rel_a, rel_b, rel_c))
302 sysfs_register();
304 signal(SIGALRM, update_mib_info);
305 snmp_log(LOG_INFO, "Initialization of OSA-E subagent successful...\n");
307 /* subagent main loop, that calls
308 * agent_check_and_process() in blocking mode
309 * */
310 while(keep_running) {
311 if( interfaces_changed > 0 ){
312 interfaces_changed = 0;
313 alarm(0); /* cancel a potentially scheduled alarm */
314 update_mib_info();
315 /* reschedule another update_mib_info() since
316 netsnmp does not update the interface counter
317 immediately, but within the next 60 seconds */
318 alarm(70);
319 } else
320 agent_check_and_process(1);
323 snmp_log(LOG_INFO, "Received TERM or STOP signal...shutting down "
324 "agent...\n");
326 /* unregister all Toplevel OIDs we support */
327 for(li_ptr = oid_list_head; li_ptr->next != NULL; li_ptr =li_ptr->next){
328 oid_to_str_conv((oid*)li_ptr->next->pObjid,
329 li_ptr->next->length, oidstr);
330 snmp_log(LOG_INFO, "unregister Toplevel OID .%s.....", oidstr );
331 res = unregister_mib(li_ptr->next->pObjid,
332 li_ptr->next->length);
333 if (res == MIB_UNREGISTERED_OK)
334 snmp_log(LOG_INFO, "successful\n");
335 else
336 snmp_log(LOG_INFO, "failed %d\n",res);
339 if(KERNEL_VERSION(2,6,22) >= KERNEL_VERSION(rel_a, rel_b, rel_c))
340 sysfs_unregister();
342 snmp_shutdown("osasnmpd");
344 return 0;