blob: ec4a0b778dd90ef6dc8cff70f88db6efd455c8c6 [file] [log] [blame]
Harald Welte923a3bd2009-02-14 12:51:36 +00001
2#include <unistd.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <sys/types.h>
6#include <sys/socket.h>
7#include <netinet/in.h>
8#include <arpa/inet.h>
9
10
Harald Weltedfe6c7d2010-02-20 16:24:02 +010011#include <osmocore/select.h>
12#include <osmocore/timer.h>
Harald Welte4f361fc2009-02-15 15:32:53 +000013#include <openbsc/ipaccess.h>
Harald Welte37881962009-04-30 15:15:37 +000014#include <openbsc/gsm_data.h>
15
16static const char *idtag_names[] = {
17 [IPAC_IDTAG_SERNR] = "Serial Number",
18 [IPAC_IDTAG_UNITNAME] = "Unit Name",
19 [IPAC_IDTAG_LOCATION1] = "Location 1",
20 [IPAC_IDTAG_LOCATION2] = "Location 2",
21 [IPAC_IDTAG_EQUIPVERS] = "Equipment Version",
22 [IPAC_IDTAG_SWVERSION] = "Software Version",
23 [IPAC_IDTAG_IPADDR] = "IP Address",
24 [IPAC_IDTAG_MACADDR] = "MAC Address",
25 [IPAC_IDTAG_UNIT] = "Unit ID",
26};
27
28static const char *ipac_idtag_name(int tag)
29{
30 if (tag >= ARRAY_SIZE(idtag_names))
31 return "unknown";
32
33 return idtag_names[tag];
34}
Harald Welte923a3bd2009-02-14 12:51:36 +000035
Harald Weltee26d0792009-08-08 11:47:20 +020036static int udp_sock(const char *ifname)
Harald Welte923a3bd2009-02-14 12:51:36 +000037{
38 int fd, rc, bc = 1;
39 struct sockaddr_in sa;
40
41 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
42 if (fd < 0)
43 return fd;
44
Harald Weltee26d0792009-08-08 11:47:20 +020045 if (ifname) {
46 rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
47 strlen(ifname));
48 if (rc < 0)
49 goto err;
50 }
51
Harald Welte923a3bd2009-02-14 12:51:36 +000052 sa.sin_family = AF_INET;
53 sa.sin_port = htons(3006);
54 sa.sin_addr.s_addr = INADDR_ANY;
Harald Welte923a3bd2009-02-14 12:51:36 +000055
56 rc = bind(fd, (struct sockaddr *)&sa, sizeof(sa));
57 if (rc < 0)
58 goto err;
59
60 rc = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &bc, sizeof(bc));
61 if (rc < 0)
62 goto err;
63
64#if 0
Harald Welte81cff3c2009-08-08 12:14:53 +020065 /* we cannot bind, since the response packets don't come from
66 * the broadcast address */
67 sa.sin_family = AF_INET;
68 sa.sin_port = htons(3006);
69 inet_aton("255.255.255.255", &sa.sin_addr);
70
Harald Welte923a3bd2009-02-14 12:51:36 +000071 rc = connect(fd, (struct sockaddr *)&sa, sizeof(sa));
72 if (rc < 0)
73 goto err;
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +020074#endif
Harald Welte923a3bd2009-02-14 12:51:36 +000075 return fd;
76
77err:
78 close(fd);
79 return rc;
80}
81
Holger Hans Peter Freytheracf8a0c2010-03-29 08:47:44 +020082const unsigned char find_pkt[] = { 0x00, 0x0b+8, IPAC_PROTO_IPACCESS, 0x00,
Harald Welte4f361fc2009-02-15 15:32:53 +000083 IPAC_MSGT_ID_GET,
84 0x01, IPAC_IDTAG_MACADDR,
85 0x01, IPAC_IDTAG_IPADDR,
86 0x01, IPAC_IDTAG_UNIT,
87 0x01, IPAC_IDTAG_LOCATION1,
88 0x01, IPAC_IDTAG_LOCATION2,
89 0x01, IPAC_IDTAG_EQUIPVERS,
90 0x01, IPAC_IDTAG_SWVERSION,
91 0x01, IPAC_IDTAG_UNITNAME,
92 0x01, IPAC_IDTAG_SERNR,
93 };
Harald Welte923a3bd2009-02-14 12:51:36 +000094
95
96static int bcast_find(int fd)
97{
98 struct sockaddr_in sa;
99
100 sa.sin_family = AF_INET;
101 sa.sin_port = htons(3006);
102 inet_aton("255.255.255.255", &sa.sin_addr);
103
104 return sendto(fd, find_pkt, sizeof(find_pkt), 0, (struct sockaddr *) &sa, sizeof(sa));
105}
106
107static int parse_response(unsigned char *buf, int len)
108{
109 u_int8_t t_len;
110 u_int8_t t_tag;
111 u_int8_t *cur = buf;
112
Harald Welte923a3bd2009-02-14 12:51:36 +0000113 while (cur < buf + len) {
114 t_len = *cur++;
115 t_tag = *cur++;
116
Harald Welte37881962009-04-30 15:15:37 +0000117 printf("%s='%s' ", ipac_idtag_name(t_tag), cur);
Harald Welte923a3bd2009-02-14 12:51:36 +0000118
119 cur += t_len;
120 }
121 printf("\n");
122 return 0;
123}
124
125static int read_response(int fd)
126{
127 unsigned char buf[255];
128 struct sockaddr_in sa;
129 int len;
130 socklen_t sa_len = sizeof(sa);
131
132 len = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sa, &sa_len);
133 if (len < 0)
134 return len;
135
Harald Welte81cff3c2009-08-08 12:14:53 +0200136 /* 2 bytes length, 1 byte protocol (0xfe) */
137 if (buf[2] != 0xfe)
138 return 0;
139
140 if (buf[4] != IPAC_MSGT_ID_RESP)
141 return 0;
142
Harald Welte4593ff32009-05-01 14:53:36 +0000143 return parse_response(buf+6, len-6);
Harald Welte923a3bd2009-02-14 12:51:36 +0000144}
145
146static int bfd_cb(struct bsc_fd *bfd, unsigned int flags)
147{
148 if (flags & BSC_FD_READ)
149 return read_response(bfd->fd);
150 if (flags & BSC_FD_WRITE) {
151 bfd->when &= ~BSC_FD_WRITE;
152 return bcast_find(bfd->fd);
153 }
154 return 0;
155}
156
157static struct timer_list timer;
158
159static void timer_cb(void *_data)
160{
161 struct bsc_fd *bfd = _data;
162
163 bfd->when |= BSC_FD_WRITE;
164
Harald Welteff117a82009-05-23 05:22:08 +0000165 bsc_schedule_timer(&timer, 5, 0);
Harald Welte923a3bd2009-02-14 12:51:36 +0000166}
167
168int main(int argc, char **argv)
169{
170 struct bsc_fd bfd;
Harald Weltee26d0792009-08-08 11:47:20 +0200171 char *ifname;
Harald Welte923a3bd2009-02-14 12:51:36 +0000172 int rc;
173
174 printf("ipaccess-find (C) 2009 by Harald Welte\n");
175 printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
176
Harald Welte042401c2009-06-29 10:43:04 +0200177 if (argc < 2) {
Harald Weltee26d0792009-08-08 11:47:20 +0200178 fprintf(stdout, "you might need to specify the outgoing\n"
179 " network interface, e.g. ``%s eth0''\n", argv[0]);
Harald Welte042401c2009-06-29 10:43:04 +0200180 }
181
Harald Weltee26d0792009-08-08 11:47:20 +0200182 ifname = argv[1];
Harald Welte923a3bd2009-02-14 12:51:36 +0000183 bfd.cb = bfd_cb;
184 bfd.when = BSC_FD_READ | BSC_FD_WRITE;
Harald Weltee26d0792009-08-08 11:47:20 +0200185 bfd.fd = udp_sock(ifname);
Harald Welte042401c2009-06-29 10:43:04 +0200186 if (bfd.fd < 0) {
187 perror("Cannot create local socket for broadcast udp");
188 exit(1);
189 }
Harald Welte923a3bd2009-02-14 12:51:36 +0000190
191 bsc_register_fd(&bfd);
192
193 timer.cb = timer_cb;
194 timer.data = &bfd;
195
Harald Welteff117a82009-05-23 05:22:08 +0000196 bsc_schedule_timer(&timer, 5, 0);
Harald Welte923a3bd2009-02-14 12:51:36 +0000197
198 printf("Trying to find ip.access BTS by broadcast UDP...\n");
199
200 while (1) {
Harald Welte04d3c922009-05-23 06:07:04 +0000201 rc = bsc_select_main(0);
Harald Welte923a3bd2009-02-14 12:51:36 +0000202 if (rc < 0)
203 exit(3);
204 }
205
206 exit(0);
207}
208