blob: 72bccf918fb4b31e5bf13b35f3851ee332d6fdd0 [file] [log] [blame]
Harald Welte59b04682009-06-10 05:40:52 +08001/* ip.access nanoBTS configuration tool */
2
Harald Welteecb2b412010-06-28 15:17:57 +02003/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
4 * (C) 2009-2010 by Holger Hans Peter Freyther
5 * (C) 2009-2010 by On Waves
Harald Welte59b04682009-06-10 05:40:52 +08006 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24#include <unistd.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <getopt.h>
Harald Weltef4625b12010-02-20 16:24:02 +010029#include <errno.h>
Holger Hans Peter Freytherf3d4a1b2009-12-30 07:08:39 +010030#include <sys/fcntl.h>
31#include <sys/stat.h>
Harald Welte59b04682009-06-10 05:40:52 +080032#include <sys/types.h>
33
34#include <sys/socket.h>
35#include <netinet/in.h>
36#include <arpa/inet.h>
37
38
Harald Weltef4625b12010-02-20 16:24:02 +010039#include <osmocore/select.h>
40#include <osmocore/timer.h>
Harald Welte59b04682009-06-10 05:40:52 +080041#include <openbsc/ipaccess.h>
42#include <openbsc/gsm_data.h>
43#include <openbsc/e1_input.h>
44#include <openbsc/abis_nm.h>
Holger Hans Peter Freyther72baef32009-07-07 12:40:07 +020045#include <openbsc/signal.h>
Harald Welte0bf8e302009-08-08 00:02:36 +020046#include <openbsc/debug.h>
Harald Welte0f317752010-03-05 19:36:20 +010047#include <openbsc/network_listen.h>
Harald Weltef4625b12010-02-20 16:24:02 +010048#include <osmocore/talloc.h>
Harald Welte59b04682009-06-10 05:40:52 +080049
50static struct gsm_network *gsmnet;
51
Harald Welte12a721e2009-08-10 11:39:47 +020052static int net_listen_testnr;
Harald Welte59b04682009-06-10 05:40:52 +080053static int restart;
54static char *prim_oml_ip;
Harald Welteecb2b412010-06-28 15:17:57 +020055static char *bts_ip_addr, *bts_ip_mask, *bts_ip_gw;
Harald Welte59b04682009-06-10 05:40:52 +080056static char *unit_id;
Harald Welte21460f02009-07-03 11:26:45 +020057static u_int16_t nv_flags;
58static u_int16_t nv_mask;
Holger Hans Peter Freyther4b513382009-12-28 03:11:33 +010059static char *software = NULL;
Holger Hans Peter Freyther0e15b932009-12-28 12:18:37 +010060static int sw_load_state = 0;
Holger Hans Peter Freyther0fc5ab42009-12-30 08:38:43 +010061static int oml_state = 0;
Holger Hans Peter Freytherc6f57c52010-03-22 11:22:54 +010062static int dump_files = 0;
Holger Hans Peter Freyther70c67d52010-03-24 05:26:24 +010063static char *firmware_analysis = NULL;
Holger Hans Peter Freytherf39ff072010-05-12 16:44:01 +080064static int found_trx = 0;
Holger Hans Peter Freyther0e15b932009-12-28 12:18:37 +010065
66struct sw_load {
67 u_int8_t file_id[255];
68 u_int8_t file_id_len;
69
70 u_int8_t file_version[255];
71 u_int8_t file_version_len;
72};
73
Holger Hans Peter Freytherf7f27122009-12-30 08:11:18 +010074static void *tall_ctx_config = NULL;
Holger Hans Peter Freyther0e15b932009-12-28 12:18:37 +010075static struct sw_load *sw_load1 = NULL;
76static struct sw_load *sw_load2 = NULL;
Harald Welte59b04682009-06-10 05:40:52 +080077
78/*
79static u_int8_t prim_oml_attr[] = { 0x95, 0x00, 7, 0x88, 192, 168, 100, 11, 0x00, 0x00 };
80static u_int8_t unit_id_attr[] = { 0x91, 0x00, 9, '2', '3', '4', '2', '/' , '0', '/', '0', 0x00 };
81*/
82
Holger Hans Peter Freyther72baef32009-07-07 12:40:07 +020083/*
84 * Callback function for NACK on the OML NM
85 *
86 * Currently we send the config requests but don't check the
87 * result. The nanoBTS will send us a NACK when we did something the
88 * BTS didn't like.
89 */
Harald Welte6a21c732009-11-17 06:09:56 +010090static int ipacc_msg_nack(u_int8_t mt)
Holger Hans Peter Freyther72baef32009-07-07 12:40:07 +020091{
92 fprintf(stderr, "Failure to set attribute. This seems fatal\n");
93 exit(-1);
94 return 0;
95}
96
Holger Hans Peter Freyther37783842010-05-12 23:34:51 +080097static void check_restart_or_exit(struct gsm_bts_trx *trx)
Holger Hans Peter Freyther98d6de02010-05-12 23:16:59 +080098{
99 if (restart) {
Holger Hans Peter Freyther37783842010-05-12 23:34:51 +0800100 abis_nm_ipaccess_restart(trx);
Holger Hans Peter Freyther98d6de02010-05-12 23:16:59 +0800101 } else {
102 exit(0);
103 }
104}
105
Holger Hans Peter Freyther37783842010-05-12 23:34:51 +0800106static int ipacc_msg_ack(u_int8_t mt, struct gsm_bts_trx *trx)
Holger Hans Peter Freyther257b8db2009-12-29 11:26:38 +0100107{
108 if (sw_load_state == 1) {
109 fprintf(stderr, "The new software is activaed.\n");
Holger Hans Peter Freyther37783842010-05-12 23:34:51 +0800110 check_restart_or_exit(trx);
Holger Hans Peter Freyther0fc5ab42009-12-30 08:38:43 +0100111 } else if (oml_state == 1) {
Harald Weltebfd40a82010-06-28 14:41:09 +0200112 fprintf(stderr, "Set the NV Attributes.\n");
Holger Hans Peter Freyther37783842010-05-12 23:34:51 +0800113 check_restart_or_exit(trx);
Holger Hans Peter Freyther257b8db2009-12-29 11:26:38 +0100114 }
115
116 return 0;
117}
118
Harald Welte0f317752010-03-05 19:36:20 +0100119static int nwl_sig_cb(unsigned int subsys, unsigned int signal,
120 void *handler_data, void *signal_data)
Harald Welte0bf8e302009-08-08 00:02:36 +0200121{
Harald Welte0f317752010-03-05 19:36:20 +0100122 struct gsm_bts_trx *trx;
Harald Welte0bf8e302009-08-08 00:02:36 +0200123
Harald Welte0f317752010-03-05 19:36:20 +0100124 switch (signal) {
125 case S_IPAC_NWL_COMPLETE:
126 trx = signal_data;
127 ipac_nwl_test_start(trx, net_listen_testnr);
Harald Welte0bf8e302009-08-08 00:02:36 +0200128 break;
129 }
Harald Welte0bf8e302009-08-08 00:02:36 +0200130 return 0;
131}
132
Holger Hans Peter Freyther72baef32009-07-07 12:40:07 +0200133static int nm_sig_cb(unsigned int subsys, unsigned int signal,
134 void *handler_data, void *signal_data)
135{
Holger Hans Peter Freyther0fc5ab42009-12-30 08:38:43 +0100136 struct ipacc_ack_signal_data *ipacc_data;
Harald Welte6a21c732009-11-17 06:09:56 +0100137
Holger Hans Peter Freyther72baef32009-07-07 12:40:07 +0200138 switch (signal) {
139 case S_NM_IPACC_NACK:
Holger Hans Peter Freyther0fc5ab42009-12-30 08:38:43 +0100140 ipacc_data = signal_data;
141 return ipacc_msg_nack(ipacc_data->msg_type);
Holger Hans Peter Freyther257b8db2009-12-29 11:26:38 +0100142 case S_NM_IPACC_ACK:
Holger Hans Peter Freyther0fc5ab42009-12-30 08:38:43 +0100143 ipacc_data = signal_data;
Holger Hans Peter Freyther37783842010-05-12 23:34:51 +0800144 return ipacc_msg_ack(ipacc_data->msg_type, ipacc_data->trx);
Holger Hans Peter Freyther9ef8e5a2009-12-30 09:00:01 +0100145 case S_NM_IPACC_RESTART_ACK:
146 printf("The BTS has acked the restart. Exiting.\n");
147 exit(0);
148 break;
149 case S_NM_IPACC_RESTART_NACK:
150 printf("The BTS has nacked the restart. Exiting.\n");
151 exit(0);
152 break;
Holger Hans Peter Freyther72baef32009-07-07 12:40:07 +0200153 default:
154 break;
155 }
156
157 return 0;
158}
159
Holger Hans Peter Freyther4b513382009-12-28 03:11:33 +0100160/* callback function passed to the ABIS OML code */
161static int percent;
162static int percent_old;
Holger Hans Peter Freyther0e15b932009-12-28 12:18:37 +0100163static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *_msg,
Holger Hans Peter Freyther4b513382009-12-28 03:11:33 +0100164 void *data, void *param)
165{
Holger Hans Peter Freyther0e15b932009-12-28 12:18:37 +0100166 struct msgb *msg;
Holger Hans Peter Freytherfaeab8e2010-05-13 00:14:46 +0800167 struct gsm_bts_trx *trx;
Holger Hans Peter Freyther4b513382009-12-28 03:11:33 +0100168
169 if (hook != GSM_HOOK_NM_SWLOAD)
170 return 0;
171
Holger Hans Peter Freytherfaeab8e2010-05-13 00:14:46 +0800172 trx = (struct gsm_bts_trx *) data;
Holger Hans Peter Freyther4b513382009-12-28 03:11:33 +0100173
174 switch (event) {
175 case NM_MT_LOAD_INIT_ACK:
176 fprintf(stdout, "Software Load Initiate ACK\n");
177 break;
178 case NM_MT_LOAD_INIT_NACK:
179 fprintf(stderr, "ERROR: Software Load Initiate NACK\n");
180 exit(5);
181 break;
182 case NM_MT_LOAD_END_ACK:
183 fprintf(stderr, "LOAD END ACK...");
Holger Hans Peter Freyther0e15b932009-12-28 12:18:37 +0100184 /* now make it the default */
185 sw_load_state = 1;
186
187 msg = msgb_alloc(1024, "sw: nvattr");
188 msg->l2h = msgb_put(msg, 3);
189 msg->l3h = &msg->l2h[3];
190
191 /* activate software */
192 if (sw_load1) {
193 msgb_v_put(msg, NM_ATT_SW_DESCR);
194 msgb_tl16v_put(msg, NM_ATT_FILE_ID, sw_load1->file_id_len, sw_load1->file_id);
195 msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, sw_load1->file_version_len,
196 sw_load1->file_version);
Holger Hans Peter Freyther4b513382009-12-28 03:11:33 +0100197 }
Holger Hans Peter Freyther0e15b932009-12-28 12:18:37 +0100198
199 if (sw_load2) {
200 msgb_v_put(msg, NM_ATT_SW_DESCR);
Holger Hans Peter Freytherf81445e2009-12-29 11:12:00 +0100201 msgb_tl16v_put(msg, NM_ATT_FILE_ID, sw_load2->file_id_len, sw_load2->file_id);
Holger Hans Peter Freyther0e15b932009-12-28 12:18:37 +0100202 msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, sw_load2->file_version_len,
203 sw_load2->file_version);
204 }
205
206 /* fill in the data */
207 msg->l2h[0] = NM_ATT_IPACC_CUR_SW_CFG;
208 msg->l2h[1] = msgb_l3len(msg) >> 8;
209 msg->l2h[2] = msgb_l3len(msg) & 0xff;
210 printf("Foo l2h: %p l3h: %p... length l2: %u l3: %u\n", msg->l2h, msg->l3h, msgb_l2len(msg), msgb_l3len(msg));
Holger Hans Peter Freytherfaeab8e2010-05-13 00:14:46 +0800211 abis_nm_ipaccess_set_nvattr(trx, msg->l2h, msgb_l2len(msg));
Holger Hans Peter Freyther0e15b932009-12-28 12:18:37 +0100212 msgb_free(msg);
Holger Hans Peter Freyther4b513382009-12-28 03:11:33 +0100213 break;
214 case NM_MT_LOAD_END_NACK:
215 fprintf(stderr, "ERROR: Software Load End NACK\n");
216 exit(3);
217 break;
218 case NM_MT_ACTIVATE_SW_NACK:
219 fprintf(stderr, "ERROR: Activate Software NACK\n");
220 exit(4);
221 break;
222 case NM_MT_ACTIVATE_SW_ACK:
223 break;
224 case NM_MT_LOAD_SEG_ACK:
Holger Hans Peter Freytherfaeab8e2010-05-13 00:14:46 +0800225 percent = abis_nm_software_load_status(trx->bts);
Holger Hans Peter Freyther4b513382009-12-28 03:11:33 +0100226 if (percent > percent_old)
227 printf("Software Download Progress: %d%%\n", percent);
228 percent_old = percent;
229 break;
Holger Hans Peter Freyther61f814d2009-12-28 12:23:02 +0100230 case NM_MT_LOAD_ABORT:
231 fprintf(stderr, "ERROR: Load aborted by the BTS.\n");
232 exit(6);
233 break;
Holger Hans Peter Freyther4b513382009-12-28 03:11:33 +0100234 }
235 return 0;
236}
237
Harald Welteecb2b412010-06-28 15:17:57 +0200238static void nv_put_ip_if_cfg(struct msgb *nmsg, uint32_t ip, uint32_t mask)
239{
240 msgb_put_u8(nmsg, NM_ATT_IPACC_IP_IF_CFG);
241
242 msgb_put_u32(nmsg, ip);
243 msgb_put_u32(nmsg, mask);
244}
245
246static void nv_put_gw_cfg(struct msgb *nmsg, uint32_t addr, uint32_t mask, uint32_t gw)
247{
248 msgb_put_u8(nmsg, NM_ATT_IPACC_IP_GW_CFG);
249 msgb_put_u32(nmsg, addr);
250 msgb_put_u32(nmsg, mask);
251 msgb_put_u32(nmsg, gw);
252}
253
254static void nv_put_unit_id(struct msgb *nmsg, const char *unit_id)
255{
256 msgb_tl16v_put(nmsg, NM_ATT_IPACC_UNIT_ID, strlen(unit_id)+1,
257 (const uint8_t *)unit_id);
258}
259
260static void nv_put_prim_oml(struct msgb *nmsg, uint32_t ip, uint16_t port)
Harald Welte59b04682009-06-10 05:40:52 +0800261{
262 int len;
Harald Welteecb2b412010-06-28 15:17:57 +0200263
264 /* 0x88 + IP + port */
265 len = 1 + sizeof(ip) + sizeof(port);
266
267 msgb_put_u8(nmsg, NM_ATT_IPACC_PRIM_OML_CFG_LIST);
268 msgb_put_u16(nmsg, len);
269
270 msgb_put_u8(nmsg, 0x88);
271
272 /* IP address */
273 msgb_put_u32(nmsg, ip);
274
275 /* port number */
276 msgb_put_u16(nmsg, port);
277}
278
279static void nv_put_flags(struct msgb *nmsg, uint16_t nv_flags, uint16_t nv_mask)
280{
281 msgb_put_u8(nmsg, NM_ATT_IPACC_NV_FLAGS);
282 msgb_put_u16(nmsg, sizeof(nv_flags) + sizeof(nv_mask));
283 msgb_put_u8(nmsg, nv_flags & 0xff);
284 msgb_put_u8(nmsg, nv_mask & 0xff);
285 msgb_put_u8(nmsg, nv_flags >> 8);
286 msgb_put_u8(nmsg, nv_mask >> 8);
287}
288
Harald Welte901c8192010-06-28 15:52:56 +0200289/* human-readable names for the ip.access nanoBTS NVRAM Flags */
290static const struct value_string ipa_nvflag_strs[] = {
291 { 0x0001, "static-ip" },
292 { 0x0002, "static-gw" },
293 { 0x0004, "no-dhcp-vsi" },
294 { 0x0008, "dhcp-enabled" },
295 { 0x0040, "led-disabled" },
296 { 0x0100, "secondary-oml-enabled" },
297 { 0x0200, "diag-enabled" },
298 { 0x0400, "cli-enabled" },
299 { 0x0800, "http-enabled" },
300 { 0x1000, "post-enabled" },
301 { 0x2000, "snmp-enabled" },
302 { 0, NULL }
303};
304
305/* set the flags in flags/mask according to a string-identified flag and 'enable' */
306static int ipa_nvflag_set(uint16_t *flags, uint16_t *mask, const char *name, int en)
307{
308 int rc;
309 rc = get_string_value(ipa_nvflag_strs, name);
310 if (rc < 0)
311 return rc;
312
313 *mask |= rc;
314 if (en)
315 *flags |= rc;
316 else
317 *flags &= ~rc;
318
319 return 0;
320}
321
Harald Welteecb2b412010-06-28 15:17:57 +0200322static void bootstrap_om(struct gsm_bts_trx *trx)
323{
Harald Weltebfd40a82010-06-28 14:41:09 +0200324 struct msgb *nmsg = msgb_alloc(1024, "nested msgb");
Harald Welteecb2b412010-06-28 15:17:57 +0200325 int need_to_set_attr = 0;
326 int len;
Harald Welte59b04682009-06-10 05:40:52 +0800327
Holger Hans Peter Freytherf39ff072010-05-12 16:44:01 +0800328 printf("OML link established using TRX %d\n", trx->nr);
Harald Welte59b04682009-06-10 05:40:52 +0800329
330 if (unit_id) {
331 len = strlen(unit_id);
Harald Weltebfd40a82010-06-28 14:41:09 +0200332 if (len > nmsg->data_len-10)
333 goto out_err;
Harald Welte59b04682009-06-10 05:40:52 +0800334 printf("setting Unit ID to '%s'\n", unit_id);
Harald Welteecb2b412010-06-28 15:17:57 +0200335 nv_put_unit_id(nmsg, unit_id);
336 need_to_set_attr = 1;
Harald Welte59b04682009-06-10 05:40:52 +0800337 }
338 if (prim_oml_ip) {
339 struct in_addr ia;
Harald Welte59b04682009-06-10 05:40:52 +0800340
341 if (!inet_aton(prim_oml_ip, &ia)) {
342 fprintf(stderr, "invalid IP address: %s\n",
343 prim_oml_ip);
Harald Weltebfd40a82010-06-28 14:41:09 +0200344 goto out_err;
Harald Welte59b04682009-06-10 05:40:52 +0800345 }
346
Harald Welte59b04682009-06-10 05:40:52 +0800347 printf("setting primary OML link IP to '%s'\n", inet_ntoa(ia));
Harald Welteecb2b412010-06-28 15:17:57 +0200348 nv_put_prim_oml(nmsg, ntohl(ia.s_addr), 0);
349 need_to_set_attr = 1;
Harald Welte59b04682009-06-10 05:40:52 +0800350 }
Harald Welte21460f02009-07-03 11:26:45 +0200351 if (nv_mask) {
Harald Welte21460f02009-07-03 11:26:45 +0200352 printf("setting NV Flags/Mask to 0x%04x/0x%04x\n",
353 nv_flags, nv_mask);
Harald Welteecb2b412010-06-28 15:17:57 +0200354 nv_put_flags(nmsg, nv_flags, nv_mask);
355 need_to_set_attr = 1;
356 }
357 if (bts_ip_addr && bts_ip_mask) {
358 struct in_addr ia_addr, ia_mask;
359
360 if (!inet_aton(bts_ip_addr, &ia_addr)) {
361 fprintf(stderr, "invalid IP address: %s\n",
362 bts_ip_addr);
363 goto out_err;
364 }
365
366 if (!inet_aton(bts_ip_mask, &ia_mask)) {
367 fprintf(stderr, "invalid IP address: %s\n",
368 bts_ip_mask);
369 goto out_err;
370 }
371
372 printf("setting static IP Address/Mask\n");
373 nv_put_ip_if_cfg(nmsg, ntohl(ia_addr.s_addr), ntohl(ia_mask.s_addr));
374 need_to_set_attr = 1;
375 }
376 if (bts_ip_gw) {
377 struct in_addr ia_gw;
378
379 if (!inet_aton(bts_ip_gw, &ia_gw)) {
380 fprintf(stderr, "invalid IP address: %s\n",
381 bts_ip_gw);
382 goto out_err;
383 }
384
385 printf("setting static IP Gateway\n");
386 /* we only set the default gateway with zero addr/mask */
387 nv_put_gw_cfg(nmsg, 0, 0, ntohl(ia_gw.s_addr));
388 need_to_set_attr = 1;
Harald Welte21460f02009-07-03 11:26:45 +0200389 }
Harald Welte59b04682009-06-10 05:40:52 +0800390
Harald Welteecb2b412010-06-28 15:17:57 +0200391 if (need_to_set_attr) {
392 abis_nm_ipaccess_set_nvattr(trx, nmsg->head, nmsg->len);
393 oml_state = 1;
394 }
Harald Weltebfd40a82010-06-28 14:41:09 +0200395
Holger Hans Peter Freyther0fc5ab42009-12-30 08:38:43 +0100396 if (restart && !prim_oml_ip && !software) {
Harald Welte59b04682009-06-10 05:40:52 +0800397 printf("restarting BTS\n");
Holger Hans Peter Freyther37783842010-05-12 23:34:51 +0800398 abis_nm_ipaccess_restart(trx);
Harald Welte59b04682009-06-10 05:40:52 +0800399 }
Holger Hans Peter Freyther4b513382009-12-28 03:11:33 +0100400
Harald Weltebfd40a82010-06-28 14:41:09 +0200401out_err:
402 msgb_free(nmsg);
Harald Welte59b04682009-06-10 05:40:52 +0800403}
404
405void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
406{
407 switch (event) {
408 case EVT_E1_TEI_UP:
409 switch (type) {
410 case E1INP_SIGN_OML:
Harald Welte59b04682009-06-10 05:40:52 +0800411 break;
412 case E1INP_SIGN_RSL:
413 /* FIXME */
414 break;
415 default:
416 break;
417 }
418 break;
419 case EVT_E1_TEI_DN:
420 fprintf(stderr, "Lost some E1 TEI link\n");
421 /* FIXME: deal with TEI or L1 link loss */
422 break;
423 default:
424 break;
425 }
426}
427
428int nm_state_event(enum nm_evt evt, u_int8_t obj_class, void *obj,
Holger Hans Peter Freyther9aec6db2010-05-13 00:37:48 +0800429 struct gsm_nm_state *old_state, struct gsm_nm_state *new_state,
430 struct abis_om_obj_inst *obj_inst)
Harald Welte59b04682009-06-10 05:40:52 +0800431{
Holger Hans Peter Freytherf39ff072010-05-12 16:44:01 +0800432 if (obj_class == NM_OC_BASEB_TRANSC) {
433 if (!found_trx && obj_inst->trx_nr != 0xff) {
434 struct gsm_bts_trx *trx = container_of(obj, struct gsm_bts_trx, bb_transc);
435 bootstrap_om(trx);
436 found_trx = 1;
437 }
438 } else if (evt == EVT_STATECHG_OPER &&
Harald Welte0bf8e302009-08-08 00:02:36 +0200439 obj_class == NM_OC_RADIO_CARRIER &&
Holger Hans Peter Freytherf6dbf7f2009-12-28 07:27:43 +0100440 new_state->availability == 3) {
Harald Welte0bf8e302009-08-08 00:02:36 +0200441 struct gsm_bts_trx *trx = obj;
Holger Hans Peter Freytherf6dbf7f2009-12-28 07:27:43 +0100442
Harald Welte0f317752010-03-05 19:36:20 +0100443 if (net_listen_testnr)
444 ipac_nwl_test_start(trx, net_listen_testnr);
445 else if (software) {
Holger Hans Peter Freytherf6dbf7f2009-12-28 07:27:43 +0100446 int rc;
447 printf("Attempting software upload with '%s'\n", software);
Holger Hans Peter Freytherfaeab8e2010-05-13 00:14:46 +0800448 rc = abis_nm_software_load(trx->bts, trx->nr, software, 19, 0, swload_cbfn, trx);
Holger Hans Peter Freytherf6dbf7f2009-12-28 07:27:43 +0100449 if (rc < 0) {
450 fprintf(stderr, "Failed to start software load\n");
451 exit(-3);
452 }
453 }
Harald Welte0bf8e302009-08-08 00:02:36 +0200454 }
Harald Welte59b04682009-06-10 05:40:52 +0800455 return 0;
456}
457
Holger Hans Peter Freyther39d4c8e2009-12-30 09:31:31 +0100458static struct sw_load *create_swload(struct sdp_header *header)
459{
460 struct sw_load *load;
461
462 load = talloc_zero(tall_ctx_config, struct sw_load);
463
464 strncpy((char *)load->file_id, header->firmware_info.sw_part, 20);
465 load->file_id_len = strlen(header->firmware_info.sw_part) + 1;
466
467 strncpy((char *)load->file_version, header->firmware_info.version, 20);
468 load->file_version_len = strlen(header->firmware_info.version) + 1;
469
470 return load;
471}
472
Holger Hans Peter Freyther3789c122010-03-22 09:50:56 +0100473static int find_sw_load_params(const char *filename)
Holger Hans Peter Freytherf7f27122009-12-30 08:11:18 +0100474{
475 struct stat stat;
476 struct sdp_header *header;
477 struct llist_head *entry;
478 int fd;
479 void *tall_firm_ctx = 0;
480
481 entry = talloc_zero(tall_firm_ctx, struct llist_head);
482 INIT_LLIST_HEAD(entry);
483
484 fd = open(filename, O_RDONLY);
485 if (!fd) {
486 perror("nada");
Holger Hans Peter Freyther3789c122010-03-22 09:50:56 +0100487 return -1;
Holger Hans Peter Freytherf7f27122009-12-30 08:11:18 +0100488 }
489
490 /* verify the file */
491 if (fstat(fd, &stat) == -1) {
492 perror("Can not stat the file");
Holger Hans Peter Freyther3789c122010-03-22 09:50:56 +0100493 return -1;
Holger Hans Peter Freytherf7f27122009-12-30 08:11:18 +0100494 }
495
496 ipaccess_analyze_file(fd, stat.st_size, 0, entry);
497 if (close(fd) != 0) {
498 perror("Close failed.\n");
Holger Hans Peter Freyther3789c122010-03-22 09:50:56 +0100499 return -1;
Holger Hans Peter Freytherf7f27122009-12-30 08:11:18 +0100500 }
501
502 /* try to find what we are looking for */
503 llist_for_each_entry(header, entry, entry) {
504 if (ntohs(header->firmware_info.more_more_magic) == 0x1000) {
Holger Hans Peter Freyther39d4c8e2009-12-30 09:31:31 +0100505 sw_load1 = create_swload(header);
Holger Hans Peter Freytherf7f27122009-12-30 08:11:18 +0100506 } else if (ntohs(header->firmware_info.more_more_magic) == 0x2001) {
Holger Hans Peter Freyther39d4c8e2009-12-30 09:31:31 +0100507 sw_load2 = create_swload(header);
Holger Hans Peter Freytherf7f27122009-12-30 08:11:18 +0100508 }
509 }
510
Holger Hans Peter Freyther3789c122010-03-22 09:50:56 +0100511 if (!sw_load1 || !sw_load2) {
512 fprintf(stderr, "Did not find data.\n");
513 talloc_free(tall_firm_ctx);
514 return -1;
515 }
516
Holger Hans Peter Freytherf7f27122009-12-30 08:11:18 +0100517 talloc_free(tall_firm_ctx);
Holger Hans Peter Freyther3789c122010-03-22 09:50:56 +0100518 return 0;
Holger Hans Peter Freytherf7f27122009-12-30 08:11:18 +0100519}
520
Holger Hans Peter Freytherc6f57c52010-03-22 11:22:54 +0100521static void dump_entry(struct sdp_header_item *sub_entry, int part, int fd)
522{
523 int out_fd;
524 int copied;
525 char filename[4096];
526 off_t target;
527
528 if (!dump_files)
529 return;
530
531 if (sub_entry->header_entry.something1 == 0)
532 return;
533
534 snprintf(filename, sizeof(filename), "part.%d", part++);
535 out_fd = open(filename, O_WRONLY | O_CREAT, 0660);
536 if (out_fd < 0) {
537 perror("Can not dump firmware");
538 return;
539 }
540
Holger Hans Peter Freytherc52dd362010-03-22 11:50:30 +0100541 target = sub_entry->absolute_offset + ntohl(sub_entry->header_entry.start) + 4;
Holger Hans Peter Freytherc6f57c52010-03-22 11:22:54 +0100542 if (lseek(fd, target, SEEK_SET) != target) {
543 perror("seek failed");
544 close(out_fd);
545 return;
546 }
547
548 for (copied = 0; copied < ntohl(sub_entry->header_entry.length); ++copied) {
549 char c;
550 if (read(fd, &c, sizeof(c)) != sizeof(c)) {
551 perror("copy failed");
552 break;
553 }
554
555 if (write(out_fd, &c, sizeof(c)) != sizeof(c)) {
556 perror("write failed");
557 break;
558 }
559 }
560
561 close(out_fd);
562}
563
Holger Hans Peter Freytherf3d4a1b2009-12-30 07:08:39 +0100564static void analyze_firmware(const char *filename)
565{
566 struct stat stat;
567 struct sdp_header *header;
568 struct sdp_header_item *sub_entry;
569 struct llist_head *entry;
570 int fd;
571 void *tall_firm_ctx = 0;
Holger Hans Peter Freytherc6f57c52010-03-22 11:22:54 +0100572 int part = 0;
Holger Hans Peter Freytherf3d4a1b2009-12-30 07:08:39 +0100573
574 entry = talloc_zero(tall_firm_ctx, struct llist_head);
575 INIT_LLIST_HEAD(entry);
576
577 printf("Opening possible firmware '%s'\n", filename);
578 fd = open(filename, O_RDONLY);
579 if (!fd) {
580 perror("nada");
581 return;
582 }
583
584 /* verify the file */
585 if (fstat(fd, &stat) == -1) {
586 perror("Can not stat the file");
587 return;
588 }
589
590 ipaccess_analyze_file(fd, stat.st_size, 0, entry);
591
592 llist_for_each_entry(header, entry, entry) {
593 printf("Printing header information:\n");
594 printf("more_more_magic: 0x%x\n", ntohs(header->firmware_info.more_more_magic));
595 printf("header_length: %u\n", ntohl(header->firmware_info.header_length));
596 printf("file_length: %u\n", ntohl(header->firmware_info.file_length));
597 printf("sw_part: %.20s\n", header->firmware_info.sw_part);
598 printf("text1: %.64s\n", header->firmware_info.text1);
599 printf("time: %.12s\n", header->firmware_info.time);
600 printf("date: %.14s\n", header->firmware_info.date);
601 printf("text2: %.10s\n", header->firmware_info.text2);
602 printf("version: %.20s\n", header->firmware_info.version);
603 printf("subitems...\n");
604
605 llist_for_each_entry(sub_entry, &header->header_list, entry) {
606 printf("\tsomething1: %u\n", sub_entry->header_entry.something1);
607 printf("\ttext1: %.64s\n", sub_entry->header_entry.text1);
608 printf("\ttime: %.12s\n", sub_entry->header_entry.time);
609 printf("\tdate: %.14s\n", sub_entry->header_entry.date);
610 printf("\ttext2: %.10s\n", sub_entry->header_entry.text2);
611 printf("\tversion: %.20s\n", sub_entry->header_entry.version);
612 printf("\tlength: %u\n", ntohl(sub_entry->header_entry.length));
613 printf("\taddr1: 0x%x\n", ntohl(sub_entry->header_entry.addr1));
614 printf("\taddr2: 0x%x\n", ntohl(sub_entry->header_entry.addr2));
615 printf("\tstart: 0x%x\n", ntohl(sub_entry->header_entry.start));
Holger Hans Peter Freytherc6f57c52010-03-22 11:22:54 +0100616 printf("\tabs. offset: 0x%lx\n", sub_entry->absolute_offset);
Holger Hans Peter Freytherf3d4a1b2009-12-30 07:08:39 +0100617 printf("\n\n");
Holger Hans Peter Freytherc6f57c52010-03-22 11:22:54 +0100618
619 dump_entry(sub_entry, part++, fd);
Holger Hans Peter Freytherf3d4a1b2009-12-30 07:08:39 +0100620 }
621 printf("\n\n");
622 }
623
Holger Hans Peter Freytherc6f57c52010-03-22 11:22:54 +0100624 if (close(fd) != 0) {
625 perror("Close failed.\n");
626 return;
627 }
628
Holger Hans Peter Freytherf3d4a1b2009-12-30 07:08:39 +0100629 talloc_free(tall_firm_ctx);
630}
631
Holger Hans Peter Freyther5bcfb4f2009-07-04 11:53:10 +0200632static void print_usage(void)
633{
634 printf("Usage: ipaccess-config\n");
635}
636
637static void print_help(void)
638{
Harald Welte901c8192010-06-28 15:52:56 +0200639#if 0
640 printf("Commmands for reading from the BTS:\n");
641 printf(" -D --dump\t\t\tDump the BTS configuration\n");
642 printf("\n");
643#endif
644 printf("Commmands for writing to the BTS:\n");
Harald Welteecb2b412010-06-28 15:17:57 +0200645 printf(" -u --unit-id UNIT_ID\t\tSet the Unit ID of the BTS\n");
646 printf(" -o --oml-ip IP\t\tSet primary OML IP (IP of your BSC)\n");
647 printf(" -i --ip-address IP/MASK\tSet static IP address + netmask of BTS\n");
648 printf(" -g --ip-gateway IP\t\tSet static IP gateway of BTS\n");
649 printf(" -r --restart\t\t\tRestart the BTS (after other operations)\n");
Harald Welte901c8192010-06-28 15:52:56 +0200650 printf(" -n --nvram-flags FLAGS/MASK\tSet NVRAM attributes\n");
651 printf(" -S --nvattr-set FLAG\tSet one additional NVRAM attribute\n");
652 printf(" -U --nvattr-unset FLAG\tSet one additional NVRAM attribute\n");
Harald Welteecb2b412010-06-28 15:17:57 +0200653 printf(" -l --listen TESTNR\t\tPerform specified test number\n");
Harald Welteecb2b412010-06-28 15:17:57 +0200654 printf(" -s --stream-id ID\t\tSet the IPA Stream Identifier for OML\n");
655 printf(" -d --software FIRMWARE\tDownload firmware into BTS\n");
Harald Welte901c8192010-06-28 15:52:56 +0200656 printf("\n");
657 printf("Miscellaneous commands:\n");
658 printf(" -h --help\t\t\tthis text\n");
Harald Welteecb2b412010-06-28 15:17:57 +0200659 printf(" -f --firmware FIRMWARE\tProvide firmware information\n");
660 printf(" -w --write-firmware\t\tThis will dump the firmware parts to the filesystem. Use with -f.\n");
Holger Hans Peter Freyther5bcfb4f2009-07-04 11:53:10 +0200661}
662
Holger Hans Peter Freytherb0e46792010-05-14 02:54:40 +0800663extern void bts_model_nanobts_init();
664
Harald Welte59b04682009-06-10 05:40:52 +0800665int main(int argc, char **argv)
666{
667 struct gsm_bts *bts;
668 struct sockaddr_in sin;
Holger Hans Peter Freyther2e021c62009-10-27 03:41:09 +0100669 int rc, option_index = 0, stream_id = 0xff;
Harald Welte51d2a592010-03-26 21:28:59 +0800670 struct log_target *stderr_target;
Holger Hans Peter Freytherc8d862e2009-12-22 22:32:51 +0100671
Harald Welte51d2a592010-03-26 21:28:59 +0800672 log_init(&log_info);
673 stderr_target = log_target_create_stderr();
674 log_add_target(stderr_target);
675 log_set_all_filter(stderr_target, 1);
676 log_set_log_level(stderr_target, 0);
677 log_parse_category_mask(stderr_target, "DNM,0");
Harald Weltee4620192010-01-10 18:37:38 +0100678 bts_model_nanobts_init();
Harald Welte59b04682009-06-10 05:40:52 +0800679
Harald Welteecb2b412010-06-28 15:17:57 +0200680 printf("ipaccess-config (C) 2009-2010 by Harald Welte and others\n");
Harald Welte59b04682009-06-10 05:40:52 +0800681 printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
682
683 while (1) {
684 int c;
Harald Welte21460f02009-07-03 11:26:45 +0200685 unsigned long ul;
686 char *slash;
Harald Welte59b04682009-06-10 05:40:52 +0800687 static struct option long_options[] = {
688 { "unit-id", 1, 0, 'u' },
689 { "oml-ip", 1, 0, 'o' },
Harald Welteecb2b412010-06-28 15:17:57 +0200690 { "ip-address", 1, 0, 'i' },
691 { "ip-gateway", 1, 0, 'g' },
Harald Welte59b04682009-06-10 05:40:52 +0800692 { "restart", 0, 0, 'r' },
Harald Welteecb2b412010-06-28 15:17:57 +0200693 { "nvram-flags", 1, 0, 'n' },
Harald Welte901c8192010-06-28 15:52:56 +0200694 { "nvattr-set", 1, 0, 'S' },
695 { "nvattr-unset", 1, 0, 'U' },
Holger Hans Peter Freyther5bcfb4f2009-07-04 11:53:10 +0200696 { "help", 0, 0, 'h' },
Harald Welte12a721e2009-08-10 11:39:47 +0200697 { "listen", 1, 0, 'l' },
Holger Hans Peter Freyther2e021c62009-10-27 03:41:09 +0100698 { "stream-id", 1, 0, 's' },
Holger Hans Peter Freyther4b513382009-12-28 03:11:33 +0100699 { "software", 1, 0, 'd' },
Holger Hans Peter Freytherf3d4a1b2009-12-30 07:08:39 +0100700 { "firmware", 1, 0, 'f' },
Holger Hans Peter Freytherc6f57c52010-03-22 11:22:54 +0100701 { "write-firmware", 0, 0, 'w' },
Holger Hans Peter Freyther86165252010-04-20 22:22:00 +0800702 { 0, 0, 0, 0 },
Harald Welte59b04682009-06-10 05:40:52 +0800703 };
704
Harald Welte901c8192010-06-28 15:52:56 +0200705 c = getopt_long(argc, argv, "u:o:i:g:rn:S:U:l:hs:d:f:w", long_options,
Harald Welte59b04682009-06-10 05:40:52 +0800706 &option_index);
707
708 if (c == -1)
709 break;
710
711 switch (c) {
712 case 'u':
713 unit_id = optarg;
714 break;
715 case 'o':
716 prim_oml_ip = optarg;
717 break;
Harald Welteecb2b412010-06-28 15:17:57 +0200718 case 'i':
719 slash = strchr(optarg, '/');
720 if (!slash)
721 exit(2);
722 bts_ip_addr = optarg;
Harald Welte901c8192010-06-28 15:52:56 +0200723 *slash = 0;
Harald Welteecb2b412010-06-28 15:17:57 +0200724 bts_ip_mask = slash+1;
725 break;
726 case 'g':
727 bts_ip_gw = optarg;
728 break;
Harald Welte59b04682009-06-10 05:40:52 +0800729 case 'r':
730 restart = 1;
731 break;
Harald Welte21460f02009-07-03 11:26:45 +0200732 case 'n':
733 slash = strchr(optarg, '/');
734 if (!slash)
735 exit(2);
736 ul = strtoul(optarg, NULL, 16);
737 nv_flags = ul & 0xffff;
738 ul = strtoul(slash+1, NULL, 16);
739 nv_mask = ul & 0xffff;
740 break;
Harald Welte901c8192010-06-28 15:52:56 +0200741 case 'S':
742 if (ipa_nvflag_set(&nv_flags, &nv_mask, optarg, 1) < 0)
743 exit(2);
744 break;
745 case 'U':
746 if (ipa_nvflag_set(&nv_flags, &nv_mask, optarg, 0) < 0)
747 exit(2);
748 break;
Harald Welte0bf8e302009-08-08 00:02:36 +0200749 case 'l':
Harald Welte12a721e2009-08-10 11:39:47 +0200750 net_listen_testnr = atoi(optarg);
Harald Welte0bf8e302009-08-08 00:02:36 +0200751 break;
Holger Hans Peter Freyther2e021c62009-10-27 03:41:09 +0100752 case 's':
753 stream_id = atoi(optarg);
Holger Hans Peter Freyther2e021c62009-10-27 03:41:09 +0100754 break;
Holger Hans Peter Freyther4b513382009-12-28 03:11:33 +0100755 case 'd':
756 software = strdup(optarg);
Holger Hans Peter Freyther3789c122010-03-22 09:50:56 +0100757 if (find_sw_load_params(optarg) != 0)
758 exit(0);
Holger Hans Peter Freyther4b513382009-12-28 03:11:33 +0100759 break;
Holger Hans Peter Freytherf3d4a1b2009-12-30 07:08:39 +0100760 case 'f':
Holger Hans Peter Freyther70c67d52010-03-24 05:26:24 +0100761 firmware_analysis = optarg;
762 break;
Holger Hans Peter Freytherc6f57c52010-03-22 11:22:54 +0100763 case 'w':
764 dump_files = 1;
765 break;
Holger Hans Peter Freyther5bcfb4f2009-07-04 11:53:10 +0200766 case 'h':
767 print_usage();
768 print_help();
769 exit(0);
Harald Welte59b04682009-06-10 05:40:52 +0800770 }
771 };
772
Holger Hans Peter Freyther70c67d52010-03-24 05:26:24 +0100773 if (firmware_analysis)
774 analyze_firmware(firmware_analysis);
775
Harald Welte59b04682009-06-10 05:40:52 +0800776 if (optind >= argc) {
Holger Hans Peter Freyther70c67d52010-03-24 05:26:24 +0100777 /* only warn if we have not done anything else */
778 if (!firmware_analysis)
779 fprintf(stderr, "you have to specify the IP address of the BTS. Use --help for more information\n");
Harald Welte59b04682009-06-10 05:40:52 +0800780 exit(2);
781 }
782
Harald Weltee712a5f2009-06-21 16:17:15 +0200783 gsmnet = gsm_network_init(1, 1, NULL);
Harald Welte59b04682009-06-10 05:40:52 +0800784 if (!gsmnet)
785 exit(1);
786
Mike Haben66e0ba02009-10-02 12:19:34 +0100787 bts = gsm_bts_alloc(gsmnet, GSM_BTS_TYPE_NANOBTS, HARDCODED_TSC,
Harald Weltee712a5f2009-06-21 16:17:15 +0200788 HARDCODED_BSIC);
Harald Welte (local)19497042009-12-28 23:15:36 +0100789 /* ip.access supports up to 4 chained TRX */
790 gsm_bts_trx_alloc(bts);
791 gsm_bts_trx_alloc(bts);
792 gsm_bts_trx_alloc(bts);
Holger Hans Peter Freyther2e021c62009-10-27 03:41:09 +0100793 bts->oml_tei = stream_id;
Harald Welte59b04682009-06-10 05:40:52 +0800794
Holger Hans Peter Freyther72baef32009-07-07 12:40:07 +0200795 register_signal_handler(SS_NM, nm_sig_cb, NULL);
Harald Welte0f317752010-03-05 19:36:20 +0100796 register_signal_handler(SS_IPAC_NWL, nwl_sig_cb, NULL);
797
798 ipac_nwl_init();
799
Harald Welte59b04682009-06-10 05:40:52 +0800800 printf("Trying to connect to ip.access BTS ...\n");
801
802 memset(&sin, 0, sizeof(sin));
803 sin.sin_family = AF_INET;
804 inet_aton(argv[optind], &sin.sin_addr);
805 rc = ia_config_connect(bts, &sin);
806 if (rc < 0) {
807 perror("Error connecting to the BTS");
808 exit(1);
809 }
810
811 while (1) {
812 rc = bsc_select_main(0);
813 if (rc < 0)
814 exit(3);
815 }
816
817 exit(0);
818}
819