aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/imsi-catcher.c
blob: 86c50ba74d6d966d3fd540fd58f64045d0a6486d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <openbsc/linuxlist.h>

struct network_info {
	struct llist_head list;

	u_int16_t mcc;
	u_int16_t mnc;

	struct llist_head bcch_infos;
};

static LLIST_HEAD(bcch_infos);

static LLIST_HEAD(network_infos);

static struct network_info *network_find(u_int16_t mcc, u_int16_t mnc)
{
	struct network_info *ni;

	llist_for_each_head(ni, &network_infos, list) {
		if (ni->mcc == mcc && ni->mnc == mnc)
			return ni;
	}

	return NULL;
}

static struct network_info *network_alloc(u_int16_t mcc, u_int16_t mnc)
{
	struct network_info *ni = talloc_zero(NULL, struct network_info);

	if (!ni)
		return NULL;

	ni->mcc = mcc;
	ni->mnc = mnc;

	llist_add_tail(&ni->list, &network_infos);
	
	return ni;
}

/* here we get handed in the BCCH info structure */
int receive_bcch_info(const struct ipac_bcch_info *binfo)
{
	struct ipac_bcch_info *binfo2;
	struct network_info *ni;

	binfo2 = talloc_zero(NULL, struct ipac_bcch_info);
	if (!binfo2)
		return -ENOMEM;

	memcpy(binfo2, binfo, sizeof(*binfo2));

	ni = network_find(binfo->cgi.mcc, binfo->cgi.mnc);
	if (!ni)
		ni = network_alloc(binfo->cgi.mcc, binfo->cgi.mnc);

	llist_add_tail(&binfo2->list, &ni->bcch_infos);

	return 0;
}