blob: bea4b77ad88824c3031d544c10f3a8ce44018cea [file] [log] [blame]
Harald Welte0e3e88e2011-01-01 15:25:50 +01001/* ip.access nanoBTS configuration tool */
2
3/* (C) 2009-2010 by Harald Welte <laforge@gnumonks.org>
4 * All Rights Reserved
5 *
6 * 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
9 * (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
14 * GNU Affero General Public License for more details.
15 *
16 * 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/>.
18 *
19 */
Harald Welte59b04682009-06-10 05:40:52 +080020
21#include <unistd.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <netinet/in.h>
27#include <arpa/inet.h>
28
29
Harald Weltef4625b12010-02-20 16:24:02 +010030#include <osmocore/select.h>
31#include <osmocore/timer.h>
Harald Welte59b04682009-06-10 05:40:52 +080032#include <openbsc/ipaccess.h>
33#include <openbsc/gsm_data.h>
34
35static const char *idtag_names[] = {
36 [IPAC_IDTAG_SERNR] = "Serial Number",
37 [IPAC_IDTAG_UNITNAME] = "Unit Name",
38 [IPAC_IDTAG_LOCATION1] = "Location 1",
39 [IPAC_IDTAG_LOCATION2] = "Location 2",
40 [IPAC_IDTAG_EQUIPVERS] = "Equipment Version",
41 [IPAC_IDTAG_SWVERSION] = "Software Version",
42 [IPAC_IDTAG_IPADDR] = "IP Address",
43 [IPAC_IDTAG_MACADDR] = "MAC Address",
44 [IPAC_IDTAG_UNIT] = "Unit ID",
45};
46
47static const char *ipac_idtag_name(int tag)
48{
49 if (tag >= ARRAY_SIZE(idtag_names))
50 return "unknown";
51
52 return idtag_names[tag];
53}
54
Harald Welte84acf052009-08-08 11:47:20 +020055static int udp_sock(const char *ifname)
Harald Welte59b04682009-06-10 05:40:52 +080056{
57 int fd, rc, bc = 1;
58 struct sockaddr_in sa;
59
60 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
61 if (fd < 0)
62 return fd;
63
Harald Welte84acf052009-08-08 11:47:20 +020064 if (ifname) {
65 rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
66 strlen(ifname));
67 if (rc < 0)
68 goto err;
69 }
70
Harald Welte59b04682009-06-10 05:40:52 +080071 sa.sin_family = AF_INET;
72 sa.sin_port = htons(3006);
73 sa.sin_addr.s_addr = INADDR_ANY;
Harald Welte59b04682009-06-10 05:40:52 +080074
75 rc = bind(fd, (struct sockaddr *)&sa, sizeof(sa));
76 if (rc < 0)
77 goto err;
78
79 rc = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &bc, sizeof(bc));
80 if (rc < 0)
81 goto err;
82
83#if 0
Harald Welte71e49a02009-08-08 12:14:53 +020084 /* we cannot bind, since the response packets don't come from
85 * the broadcast address */
86 sa.sin_family = AF_INET;
87 sa.sin_port = htons(3006);
88 inet_aton("255.255.255.255", &sa.sin_addr);
89
Harald Welte59b04682009-06-10 05:40:52 +080090 rc = connect(fd, (struct sockaddr *)&sa, sizeof(sa));
91 if (rc < 0)
92 goto err;
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +020093#endif
Harald Welte59b04682009-06-10 05:40:52 +080094 return fd;
95
96err:
97 close(fd);
98 return rc;
99}
100
Holger Hans Peter Freyther71135142010-03-29 08:47:44 +0200101const unsigned char find_pkt[] = { 0x00, 0x0b+8, IPAC_PROTO_IPACCESS, 0x00,
Harald Welte59b04682009-06-10 05:40:52 +0800102 IPAC_MSGT_ID_GET,
103 0x01, IPAC_IDTAG_MACADDR,
104 0x01, IPAC_IDTAG_IPADDR,
105 0x01, IPAC_IDTAG_UNIT,
106 0x01, IPAC_IDTAG_LOCATION1,
107 0x01, IPAC_IDTAG_LOCATION2,
108 0x01, IPAC_IDTAG_EQUIPVERS,
109 0x01, IPAC_IDTAG_SWVERSION,
110 0x01, IPAC_IDTAG_UNITNAME,
111 0x01, IPAC_IDTAG_SERNR,
112 };
113
114
115static int bcast_find(int fd)
116{
117 struct sockaddr_in sa;
118
119 sa.sin_family = AF_INET;
120 sa.sin_port = htons(3006);
121 inet_aton("255.255.255.255", &sa.sin_addr);
122
123 return sendto(fd, find_pkt, sizeof(find_pkt), 0, (struct sockaddr *) &sa, sizeof(sa));
124}
125
126static int parse_response(unsigned char *buf, int len)
127{
128 u_int8_t t_len;
129 u_int8_t t_tag;
130 u_int8_t *cur = buf;
131
132 while (cur < buf + len) {
133 t_len = *cur++;
134 t_tag = *cur++;
135
136 printf("%s='%s' ", ipac_idtag_name(t_tag), cur);
137
138 cur += t_len;
139 }
140 printf("\n");
141 return 0;
142}
143
144static int read_response(int fd)
145{
146 unsigned char buf[255];
147 struct sockaddr_in sa;
148 int len;
149 socklen_t sa_len = sizeof(sa);
150
151 len = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sa, &sa_len);
152 if (len < 0)
153 return len;
154
Harald Welte71e49a02009-08-08 12:14:53 +0200155 /* 2 bytes length, 1 byte protocol (0xfe) */
156 if (buf[2] != 0xfe)
157 return 0;
158
159 if (buf[4] != IPAC_MSGT_ID_RESP)
160 return 0;
161
Harald Welte59b04682009-06-10 05:40:52 +0800162 return parse_response(buf+6, len-6);
163}
164
165static int bfd_cb(struct bsc_fd *bfd, unsigned int flags)
166{
167 if (flags & BSC_FD_READ)
168 return read_response(bfd->fd);
169 if (flags & BSC_FD_WRITE) {
170 bfd->when &= ~BSC_FD_WRITE;
171 return bcast_find(bfd->fd);
172 }
173 return 0;
174}
175
176static struct timer_list timer;
177
178static void timer_cb(void *_data)
179{
180 struct bsc_fd *bfd = _data;
181
182 bfd->when |= BSC_FD_WRITE;
183
184 bsc_schedule_timer(&timer, 5, 0);
185}
186
187int main(int argc, char **argv)
188{
189 struct bsc_fd bfd;
Harald Welte84acf052009-08-08 11:47:20 +0200190 char *ifname;
Harald Welte59b04682009-06-10 05:40:52 +0800191 int rc;
192
193 printf("ipaccess-find (C) 2009 by Harald Welte\n");
194 printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
195
Harald Welte81d517d2009-06-29 10:43:04 +0200196 if (argc < 2) {
Harald Welte84acf052009-08-08 11:47:20 +0200197 fprintf(stdout, "you might need to specify the outgoing\n"
198 " network interface, e.g. ``%s eth0''\n", argv[0]);
Harald Welte81d517d2009-06-29 10:43:04 +0200199 }
200
Harald Welte84acf052009-08-08 11:47:20 +0200201 ifname = argv[1];
Harald Welte59b04682009-06-10 05:40:52 +0800202 bfd.cb = bfd_cb;
203 bfd.when = BSC_FD_READ | BSC_FD_WRITE;
Harald Welte84acf052009-08-08 11:47:20 +0200204 bfd.fd = udp_sock(ifname);
Harald Welte81d517d2009-06-29 10:43:04 +0200205 if (bfd.fd < 0) {
206 perror("Cannot create local socket for broadcast udp");
207 exit(1);
208 }
Harald Welte59b04682009-06-10 05:40:52 +0800209
210 bsc_register_fd(&bfd);
211
212 timer.cb = timer_cb;
213 timer.data = &bfd;
214
215 bsc_schedule_timer(&timer, 5, 0);
216
217 printf("Trying to find ip.access BTS by broadcast UDP...\n");
218
219 while (1) {
220 rc = bsc_select_main(0);
221 if (rc < 0)
222 exit(3);
223 }
224
225 exit(0);
226}
227