blob: c31636917ddfb0fb484cff4ecd11b08aae22ba6d [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 Freyther71760302011-02-22 20:57:08 +010021#include <cellmgr_debug.h>
Harald Welteff397ed2011-05-08 10:29:23 +020022#include <osmocom/core/talloc.h>
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080023
24static void add_pdu_var(netsnmp_pdu *pdu, const char *mib_name, int id, const char *value)
25{
26 oid oid_name[MAX_OID_LEN];
27 size_t name_length;
28
29 char buf[4096];
30 buf[4095] = '\0';
31 snprintf(buf, sizeof(buf)-1, "%s.%d", mib_name, id);
32
33 name_length = MAX_OID_LEN;
34 if (snmp_parse_oid(buf, oid_name, &name_length) == NULL) {
35 snmp_perror(buf);
36 return;
37 }
38
39 if (snmp_add_var(pdu, oid_name, name_length, '=', value)) {
40 snmp_perror(buf);
41 return;
42 }
43}
44
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +010045static int link_up_cb(int op, netsnmp_session *ss,
46 int reqid, netsnmp_pdu *pdu, void *data)
47{
48 struct snmp_mtp_session *mtp = ss->myvoid;
49 int link_index = (int) data;
50
51 if (mtp->last_up_req != reqid)
52 return 0;
53
54 mtp->last_up_req = 0;
55 snmp_mtp_callback(mtp, SNMP_LINK_UP,
56 op == STAT_TIMEOUT ? SNMP_STATUS_TIMEOUT : SNMP_STATUS_OK,
57 link_index);
58 return 0;
59}
60
61static int link_down_cb(int op, netsnmp_session *ss,
62 int reqid, netsnmp_pdu *pdu, void *data)
63{
64 struct snmp_mtp_session *mtp = ss->myvoid;
65 int link_index = (int) data;
66
67 if (mtp->last_do_req != reqid)
68 return 0;
69
70 mtp->last_do_req = 0;
71 snmp_mtp_callback(mtp, SNMP_LINK_DOWN,
72 op == STAT_TIMEOUT ? SNMP_STATUS_TIMEOUT : SNMP_STATUS_OK,
73 link_index);
74 return 0;
75}
76
77static int send_pdu(netsnmp_session *ss, netsnmp_pdu *pdu, int kind, int link_id)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080078{
79 int status;
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +010080 netsnmp_callback cb;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080081
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +010082 cb = kind == SNMP_LINK_UP ? link_up_cb : link_down_cb;
83
84 status = snmp_async_send(ss, pdu, cb, (void *) link_id);
85 if (status == 0) {
86 snmp_log(LOG_ERR, "Failed to send async request.\n");
87 snmp_free_pdu(pdu);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080088 }
89
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +010090 return status;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080091}
92
Holger Hans Peter Freyther4da421d2011-01-21 13:36:11 +010093static void snmp_mtp_start_c7_datalink(struct snmp_mtp_session *session, int link_id)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080094{
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +010095 int status;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +080096 netsnmp_pdu *pdu;
97 pdu = snmp_pdu_create(SNMP_MSG_SET);
98
99 add_pdu_var(pdu, "PTI-NexusWareC7-MIB::nwc7DatalinkCommand", link_id, "nwc7DatalinkCmdPowerOn");
100 add_pdu_var(pdu, "PTI-NexusWareC7-MIB::nwc7Mtp2Active", link_id, "true");
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +0100101 status = send_pdu(session->ss, pdu, SNMP_LINK_UP, link_id);
102
103 if (status == 0)
104 snmp_mtp_callback(session, SNMP_LINK_UP, SNMP_STATUS_TIMEOUT, link_id);
105 else
106 session->last_up_req = status;
107
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800108}
109
Holger Hans Peter Freyther4da421d2011-01-21 13:36:11 +0100110static void snmp_mtp_stop_c7_datalink(struct snmp_mtp_session *session, int link_id)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800111{
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +0100112 int status;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800113 netsnmp_pdu *pdu;
114 pdu = snmp_pdu_create(SNMP_MSG_SET);
115
116 add_pdu_var(pdu, "PTI-NexusWareC7-MIB::nwc7Mtp2Active", link_id, "false");
Holger Hans Peter Freythereab20962011-01-21 18:00:36 +0100117 status = send_pdu(session->ss, pdu, SNMP_LINK_DOWN, link_id);
118 if (status == 0)
119 snmp_mtp_callback(session, SNMP_LINK_DOWN, SNMP_STATUS_TIMEOUT, link_id);
120 else
121 session->last_do_req = status;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800122}
123
Holger Hans Peter Freyther71760302011-02-22 20:57:08 +0100124struct snmp_mtp_session *snmp_mtp_session_create()
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800125{
126 struct snmp_mtp_session *session = talloc_zero(NULL, struct snmp_mtp_session);
127 if (!session)
128 return NULL;
129
130 init_snmp("cellmgr_ng");
131 snmp_sess_init(&session->session);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800132 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
Holger Hans Peter Freyther71760302011-02-22 20:57:08 +0100137 return session;
138}
139
140int snmp_mtp_peer_name(struct snmp_mtp_session *session, char *host)
141{
142 if (session->ss) {
143 snmp_close(session->ss);
144 session->ss = NULL;
145 }
146
147 session->session.peername = host;
148
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800149 session->ss = snmp_open(&session->session);
150 if (!session->ss) {
151 snmp_perror("create failure");
152 snmp_log(LOG_ERR, "Could not connect to the remote.\n");
Holger Hans Peter Freyther71760302011-02-22 20:57:08 +0100153 LOGP(DINP, LOGL_ERROR, "Failed to open a SNMP session.\n");
154 return -1;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800155 }
156
Holger Hans Peter Freyther71760302011-02-22 20:57:08 +0100157 return 0;
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800158}
159
Holger Hans Peter Freytherb6edf972011-01-02 16:41:11 +0100160void snmp_mtp_deactivate(struct snmp_mtp_session *session, int index)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800161{
Holger Hans Peter Freytherb6edf972011-01-02 16:41:11 +0100162 snmp_mtp_stop_c7_datalink(session, index);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800163}
164
Holger Hans Peter Freytherb6edf972011-01-02 16:41:11 +0100165void snmp_mtp_activate(struct snmp_mtp_session *session, int index)
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800166{
Holger Hans Peter Freytherb6edf972011-01-02 16:41:11 +0100167 snmp_mtp_start_c7_datalink(session, index);
Holger Hans Peter Freyther97f66e22010-07-28 03:32:52 +0800168}
Holger Hans Peter Freyther083a30b2011-01-21 12:57:12 +0100169
170/**
171 * This is the easiest way to integrate SNMP without
172 * introducing threads. It would be nicer if it could
173 * register a timeout and the fd it wants to have selected
174 * for reading. We could try to find the fd's it is using
175 * for the session but there is no difference in performance
176 */
177void snmp_mtp_poll()
178{
179 int num_fds = 0, block = 0;
180 fd_set fds;
181 FD_ZERO(&fds);
182 struct timeval tv;
183 int rc;
184
185 snmp_select_info(&num_fds, &fds, &tv, &block);
186
187
188 memset(&tv, 0, sizeof(tv));
189
190 rc = select(num_fds, &fds, NULL, NULL, &tv);
191 if (rc == 0)
192 snmp_timeout();
193 else
194 snmp_read(&fds);
195}