blob: e495a4fa67cc5f7cb70763678204c847a87f4c3f [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
11#include <openbsc/select.h>
12#include <openbsc/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
65 rc = connect(fd, (struct sockaddr *)&sa, sizeof(sa));
66 if (rc < 0)
67 goto err;
68#endif
69 return fd;
70
71err:
72 close(fd);
73 return rc;
74}
75
Harald Welte4f361fc2009-02-15 15:32:53 +000076const unsigned char find_pkt[] = { 0x00, 0x0b+8, IPAC_PROTO_IPACCESS, 0x00,
77 IPAC_MSGT_ID_GET,
78 0x01, IPAC_IDTAG_MACADDR,
79 0x01, IPAC_IDTAG_IPADDR,
80 0x01, IPAC_IDTAG_UNIT,
81 0x01, IPAC_IDTAG_LOCATION1,
82 0x01, IPAC_IDTAG_LOCATION2,
83 0x01, IPAC_IDTAG_EQUIPVERS,
84 0x01, IPAC_IDTAG_SWVERSION,
85 0x01, IPAC_IDTAG_UNITNAME,
86 0x01, IPAC_IDTAG_SERNR,
87 };
Harald Welte923a3bd2009-02-14 12:51:36 +000088
89
90static int bcast_find(int fd)
91{
92 struct sockaddr_in sa;
93
94 sa.sin_family = AF_INET;
95 sa.sin_port = htons(3006);
96 inet_aton("255.255.255.255", &sa.sin_addr);
97
98 return sendto(fd, find_pkt, sizeof(find_pkt), 0, (struct sockaddr *) &sa, sizeof(sa));
99}
100
101static int parse_response(unsigned char *buf, int len)
102{
103 u_int8_t t_len;
104 u_int8_t t_tag;
105 u_int8_t *cur = buf;
106
Harald Welte923a3bd2009-02-14 12:51:36 +0000107 while (cur < buf + len) {
108 t_len = *cur++;
109 t_tag = *cur++;
110
Harald Welte37881962009-04-30 15:15:37 +0000111 printf("%s='%s' ", ipac_idtag_name(t_tag), cur);
Harald Welte923a3bd2009-02-14 12:51:36 +0000112
113 cur += t_len;
114 }
115 printf("\n");
116 return 0;
117}
118
119static int read_response(int fd)
120{
121 unsigned char buf[255];
122 struct sockaddr_in sa;
123 int len;
124 socklen_t sa_len = sizeof(sa);
125
126 len = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sa, &sa_len);
127 if (len < 0)
128 return len;
129
Harald Welte4593ff32009-05-01 14:53:36 +0000130 return parse_response(buf+6, len-6);
Harald Welte923a3bd2009-02-14 12:51:36 +0000131}
132
133static int bfd_cb(struct bsc_fd *bfd, unsigned int flags)
134{
135 if (flags & BSC_FD_READ)
136 return read_response(bfd->fd);
137 if (flags & BSC_FD_WRITE) {
138 bfd->when &= ~BSC_FD_WRITE;
139 return bcast_find(bfd->fd);
140 }
141 return 0;
142}
143
144static struct timer_list timer;
145
146static void timer_cb(void *_data)
147{
148 struct bsc_fd *bfd = _data;
149
150 bfd->when |= BSC_FD_WRITE;
151
Harald Welteff117a82009-05-23 05:22:08 +0000152 bsc_schedule_timer(&timer, 5, 0);
Harald Welte923a3bd2009-02-14 12:51:36 +0000153}
154
155int main(int argc, char **argv)
156{
157 struct bsc_fd bfd;
Harald Weltee26d0792009-08-08 11:47:20 +0200158 char *ifname;
Harald Welte923a3bd2009-02-14 12:51:36 +0000159 int rc;
160
161 printf("ipaccess-find (C) 2009 by Harald Welte\n");
162 printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
163
Harald Welte042401c2009-06-29 10:43:04 +0200164 if (argc < 2) {
Harald Weltee26d0792009-08-08 11:47:20 +0200165 fprintf(stdout, "you might need to specify the outgoing\n"
166 " network interface, e.g. ``%s eth0''\n", argv[0]);
Harald Welte042401c2009-06-29 10:43:04 +0200167 }
168
Harald Weltee26d0792009-08-08 11:47:20 +0200169 ifname = argv[1];
Harald Welte923a3bd2009-02-14 12:51:36 +0000170 bfd.cb = bfd_cb;
171 bfd.when = BSC_FD_READ | BSC_FD_WRITE;
Harald Weltee26d0792009-08-08 11:47:20 +0200172 bfd.fd = udp_sock(ifname);
Harald Welte042401c2009-06-29 10:43:04 +0200173 if (bfd.fd < 0) {
174 perror("Cannot create local socket for broadcast udp");
175 exit(1);
176 }
Harald Welte923a3bd2009-02-14 12:51:36 +0000177
178 bsc_register_fd(&bfd);
179
180 timer.cb = timer_cb;
181 timer.data = &bfd;
182
Harald Welteff117a82009-05-23 05:22:08 +0000183 bsc_schedule_timer(&timer, 5, 0);
Harald Welte923a3bd2009-02-14 12:51:36 +0000184
185 printf("Trying to find ip.access BTS by broadcast UDP...\n");
186
187 while (1) {
Harald Welte04d3c922009-05-23 06:07:04 +0000188 rc = bsc_select_main(0);
Harald Welte923a3bd2009-02-14 12:51:36 +0000189 if (rc < 0)
190 exit(3);
191 }
192
193 exit(0);
194}
195