2 * File...........: osasnmpd.c
3 * Author(s)......: Thomas Weber <tweber@de.ibm.com>
4 * Copyright IBM Corp. 2002,2007
7 * 07/29 added logic '-x agentx_socket' parm
8 * exit subagent on startup, if init_agent() fails
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)
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.
33 #include "ibmOSAMibUtil.h"
34 #include "ibmOSAMib.h"
35 #include <zt_common.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 */
54 stop_server(int UNUSED(a
))
59 /* signal handler for SIGUSR1
60 * which is send by the kernel if the interface information changes
63 on_interfaces_changed( int UNUSED(a
) )
75 sys_fd
= open( QETH_SYSFILE
, O_WRONLY
);
77 fprintf(stderr
, "open(%s) failed - reason %s\n",
78 QETH_SYSFILE
, strerror( errno
) );
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
) );
97 sys_fd
= open( QETH_SYSFILE
, O_WRONLY
);
99 fprintf(stderr
, "open(%s) failed - reason %s\n",
100 QETH_SYSFILE
, strerror( errno
) );
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
) );
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'},
125 #define OPTSTRING "hvALfl:A:P:x:"
130 int main( int argc
, char *argv
[] )
133 char oidstr
[MAX_OID_STR_LEN
];
134 char logfile
[PATH_MAX
+ 1];
135 char pid_file
[PATH_MAX
+ 1];
137 struct sigaction act
;
138 int res
,c
,longIndex
,rc
;
139 unsigned char rel_a
, rel_b
, rel_c
;
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) {
159 printf( "osasnmpd: version %s\n",
161 printf( "%s\n" , COPYRIGHT
);
164 if (strlen(optarg
) > PATH_MAX
)
166 fprintf( stderr
, "osasnmpd: logfile "\
167 "path too long (limit %d "\
168 "chars)\n", PATH_MAX
);
171 strncpy(logfile
, optarg
, PATH_MAX
);
183 if (strlen(optarg
) > PATH_MAX
)
185 fprintf( stderr
, "osasnmpd: logfile "\
186 "path too long (limit %d "\
187 "chars)\n", PATH_MAX
);
190 strncpy(pid_file
,optarg
,PATH_MAX
);
195 netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID
,
196 NETSNMP_DS_AGENT_X_SOCKET
, optarg
);
198 ds_set_string(NETSNMP_DS_APPLICATION_ID
,
199 NETSNMP_DS_AGENT_X_SOCKET
, optarg
);
203 fprintf(stderr
, "Try 'osasnmpd --help' for more"
209 while (optind
< argc
) {
210 fprintf(stderr
, "osasnmpd: unrecognized argument '%s'\n",
212 fprintf(stderr
, "Try 'osasnmpd --help' for more"
216 /* detach from shell (default) */
217 if (!dont_fork
&& fork() != 0)
220 /* create a pidfile if requested */
222 if ((PID
= fopen(pid_file
, "w")) == NULL
) {
223 snmp_log_perror("fopen");
224 fprintf(stderr
, "osasnmpd: cannot create PIDFILE\n");
227 fprintf(PID
, "%d\n", (int) getpid() );
232 /* enable logging to stderr or logfile */
233 if ( !std_err_log
) {
234 snmp_disable_stderrlog();
235 snmp_enable_filelog( logfile
, dont_zero_log
);
237 snmp_enable_stderrlog();
242 snmp_log(LOG_INFO
, "IBM OSA-E NET-SNMP 5.1.x subagent version %s\n",
245 snmp_log(LOG_INFO
, "IBM OSA-E ucd-snmp 4.2.x subagent version %s\n",
249 /* make us a agentx client. */
251 netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID
, NETSNMP_DS_AGENT_ROLE
,
254 ds_set_boolean(NETSNMP_DS_APPLICATION_ID
, NETSNMP_DS_AGENT_ROLE
, 1);
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 "
264 /* initialize OSA Express MIB module here */
267 /* osasnmpd will be used to read osasnmpd.conf files. */
268 init_snmp("osasnmpd");
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
) );
281 act
.sa_handler
= stop_server
;
282 if( sigaction( SIGINT
, &act
, NULL
) < 0 ){
283 fprintf(stderr
, "sigaction( SIGINT, ... ) failed - reason %s\n",
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
) );
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
))
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
310 while(keep_running
) {
311 if( interfaces_changed
> 0 ){
312 interfaces_changed
= 0;
313 alarm(0); /* cancel a potentially scheduled alarm */
315 /* reschedule another update_mib_info() since
316 netsnmp does not update the interface counter
317 immediately, but within the next 60 seconds */
320 agent_check_and_process(1);
323 snmp_log(LOG_INFO
, "Received TERM or STOP signal...shutting down "
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");
336 snmp_log(LOG_INFO
, "failed %d\n",res
);
339 if(KERNEL_VERSION(2,6,22) >= KERNEL_VERSION(rel_a
, rel_b
, rel_c
))
342 snmp_shutdown("osasnmpd");