blob: 2cdf32318e391c8c92d79a5f3d4549d02ab60211 [file] [log] [blame]
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +08001/*
2 * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
3 * (C) 2010 by On-Waves
4 * All Rights Reserved
5 *
Holger Hans Peter Freytherde56c222011-01-16 17:45:14 +01006 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +08009 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Holger Hans Peter Freytherde56c222011-01-16 17:45:14 +010014 * GNU Affero General Public License for more details.
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080015 *
Holger Hans Peter Freytherde56c222011-01-16 17:45:14 +010016 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080018 *
19 */
20#include <snmp_mtp.h>
Holger Hans Peter Freythercbf7d182010-07-31 05:25:35 +080021#include <osmocore/talloc.h>
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080022
23static void add_pdu_var(netsnmp_pdu *pdu, const char *mib_name, int id, const char *value)
24{
25 oid oid_name[MAX_OID_LEN];
26 size_t name_length;
27
28 char buf[4096];
29 buf[4095] = '\0';
30 snprintf(buf, sizeof(buf)-1, "%s.%d", mib_name, id);
31
32 name_length = MAX_OID_LEN;
33 if (snmp_parse_oid(buf, oid_name, &name_length) == NULL) {
34 snmp_perror(buf);
35 return;
36 }
37
38 if (snmp_add_var(pdu, oid_name, name_length, '=', value)) {
39 snmp_perror(buf);
40 return;
41 }
42}
43
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +010044static int link_up_cb(int op, netsnmp_session *ss,
45 int reqid, netsnmp_pdu *pdu, void *data)
46{
47 struct snmp_mtp_session *mtp = ss->myvoid;
48 int link_index = (int) data;
49
50 if (mtp->last_up_req != reqid)
51 return 0;
52
53 mtp->last_up_req = 0;
54 snmp_mtp_callback(mtp, SNMP_LINK_UP,
55 op == STAT_TIMEOUT ? SNMP_STATUS_TIMEOUT : SNMP_STATUS_OK,
56 link_index);
57 return 0;
58}
59
60static int link_down_cb(int op, netsnmp_session *ss,
61 int reqid, netsnmp_pdu *pdu, void *data)
62{
63 struct snmp_mtp_session *mtp = ss->myvoid;
64 int link_index = (int) data;
65
66 if (mtp->last_do_req != reqid)
67 return 0;
68
69 mtp->last_do_req = 0;
70 snmp_mtp_callback(mtp, SNMP_LINK_DOWN,
71 op == STAT_TIMEOUT ? SNMP_STATUS_TIMEOUT : SNMP_STATUS_OK,
72 link_index);
73 return 0;
74}
75
76static int send_pdu(netsnmp_session *ss, netsnmp_pdu *pdu, int kind, int link_id)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080077{
78 int status;
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +010079 netsnmp_callback cb;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080080
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +010081 cb = kind == SNMP_LINK_UP ? link_up_cb : link_down_cb;
82
83 status = snmp_async_send(ss, pdu, cb, (void *) link_id);
84 if (status == 0) {
85 snmp_log(LOG_ERR, "Failed to send async request.\n");
86 snmp_free_pdu(pdu);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080087 }
88
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +010089 return status;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080090}
91
Holger Hans Peter Freyther4da421d2011-01-21 13:36:11 +010092static void snmp_mtp_start_c7_datalink(struct snmp_mtp_session *session, int link_id)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080093{
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +010094 int status;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080095 netsnmp_pdu *pdu;
96 pdu = snmp_pdu_create(SNMP_MSG_SET);
97
98 add_pdu_var(pdu, "PTI-NexusWareC7-MIB::nwc7DatalinkCommand", link_id, "nwc7DatalinkCmdPowerOn");
99 add_pdu_var(pdu, "PTI-NexusWareC7-MIB::nwc7Mtp2Active", link_id, "true");
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +0100100 status = send_pdu(session->ss, pdu, SNMP_LINK_UP, link_id);
101
102 if (status == 0)
103 snmp_mtp_callback(session, SNMP_LINK_UP, SNMP_STATUS_TIMEOUT, link_id);
104 else
105 session->last_up_req = status;
106
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800107}
108
Holger Hans Peter Freyther4da421d2011-01-21 13:36:11 +0100109static void snmp_mtp_stop_c7_datalink(struct snmp_mtp_session *session, int link_id)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800110{
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +0100111 int status;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800112 netsnmp_pdu *pdu;
113 pdu = snmp_pdu_create(SNMP_MSG_SET);
114
115 add_pdu_var(pdu, "PTI-NexusWareC7-MIB::nwc7Mtp2Active", link_id, "false");
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +0100116 status = send_pdu(session->ss, pdu, SNMP_LINK_DOWN, link_id);
117 if (status == 0)
118 snmp_mtp_callback(session, SNMP_LINK_DOWN, SNMP_STATUS_TIMEOUT, link_id);
119 else
120 session->last_do_req = status;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800121}
122
123struct snmp_mtp_session *snmp_mtp_session_create(char *host)
124{
125 struct snmp_mtp_session *session = talloc_zero(NULL, struct snmp_mtp_session);
126 if (!session)
127 return NULL;
128
129 init_snmp("cellmgr_ng");
130 snmp_sess_init(&session->session);
131 session->session.peername = host;
132 session->session.version = SNMP_VERSION_1;
133 session->session.community = (unsigned char *) "private";
134 session->session.community_len = strlen((const char *) session->session.community);
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +0100135 session->session.myvoid = session;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800136
137 session->ss = snmp_open(&session->session);
138 if (!session->ss) {
139 snmp_perror("create failure");
140 snmp_log(LOG_ERR, "Could not connect to the remote.\n");
141 talloc_free(session);
142 return NULL;
143 }
144
145 return session;
146}
147
Holger Hans Peter Freytherb6edf972011-01-02 16:41:11 +0100148void snmp_mtp_deactivate(struct snmp_mtp_session *session, int index)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800149{
Holger Hans Peter Freytherb6edf972011-01-02 16:41:11 +0100150 snmp_mtp_stop_c7_datalink(session, index);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800151}
152
Holger Hans Peter Freytherb6edf972011-01-02 16:41:11 +0100153void snmp_mtp_activate(struct snmp_mtp_session *session, int index)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800154{
Holger Hans Peter Freytherb6edf972011-01-02 16:41:11 +0100155 snmp_mtp_start_c7_datalink(session, index);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800156}
Holger Hans Peter Freyther083a30b2011-01-21 12:57:12 +0100157
158/**
159 * This is the easiest way to integrate SNMP without
160 * introducing threads. It would be nicer if it could
161 * register a timeout and the fd it wants to have selected
162 * for reading. We could try to find the fd's it is using
163 * for the session but there is no difference in performance
164 */
165void snmp_mtp_poll()
166{
167 int num_fds = 0, block = 0;
168 fd_set fds;
169 FD_ZERO(&fds);
170 struct timeval tv;
171 int rc;
172
173 snmp_select_info(&num_fds, &fds, &tv, &block);
174
175
176 memset(&tv, 0, sizeof(tv));
177
178 rc = select(num_fds, &fds, NULL, NULL, &tv);
179 if (rc == 0)
180 snmp_timeout();
181 else
182 snmp_read(&fds);
183}