xref: /freebsd/contrib/wpa/src/ap/neighbor_db.c (revision 31d62a73c2e6ac0ff413a7a17700ffc7dce254ef)
1 /*
2  * hostapd / Neighboring APs DB
3  * Copyright(c) 2013 - 2016 Intel Mobile Communications GmbH.
4  * Copyright(c) 2011 - 2016 Intel Corporation. All rights reserved.
5  *
6  * This software may be distributed under the terms of the BSD license.
7  * See README for more details.
8  */
9 
10 #include "utils/includes.h"
11 
12 #include "utils/common.h"
13 #include "hostapd.h"
14 #include "neighbor_db.h"
15 
16 
17 struct hostapd_neighbor_entry *
18 hostapd_neighbor_get(struct hostapd_data *hapd, const u8 *bssid,
19 		     const struct wpa_ssid_value *ssid)
20 {
21 	struct hostapd_neighbor_entry *nr;
22 
23 	dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
24 			 list) {
25 		if (os_memcmp(bssid, nr->bssid, ETH_ALEN) == 0 &&
26 		    (!ssid ||
27 		     (ssid->ssid_len == nr->ssid.ssid_len &&
28 		      os_memcmp(ssid->ssid, nr->ssid.ssid,
29 				ssid->ssid_len) == 0)))
30 			return nr;
31 	}
32 	return NULL;
33 }
34 
35 
36 static void hostapd_neighbor_clear_entry(struct hostapd_neighbor_entry *nr)
37 {
38 	wpabuf_free(nr->nr);
39 	nr->nr = NULL;
40 	wpabuf_free(nr->lci);
41 	nr->lci = NULL;
42 	wpabuf_free(nr->civic);
43 	nr->civic = NULL;
44 	os_memset(nr->bssid, 0, sizeof(nr->bssid));
45 	os_memset(&nr->ssid, 0, sizeof(nr->ssid));
46 }
47 
48 
49 static struct hostapd_neighbor_entry *
50 hostapd_neighbor_add(struct hostapd_data *hapd)
51 {
52 	struct hostapd_neighbor_entry *nr;
53 
54 	nr = os_zalloc(sizeof(struct hostapd_neighbor_entry));
55 	if (!nr)
56 		return NULL;
57 
58 	dl_list_add(&hapd->nr_db, &nr->list);
59 
60 	return nr;
61 }
62 
63 
64 int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid,
65 			 const struct wpa_ssid_value *ssid,
66 			 const struct wpabuf *nr, const struct wpabuf *lci,
67 			 const struct wpabuf *civic)
68 {
69 	struct hostapd_neighbor_entry *entry;
70 
71 	entry = hostapd_neighbor_get(hapd, bssid, ssid);
72 	if (!entry)
73 		entry = hostapd_neighbor_add(hapd);
74 	if (!entry)
75 		return -1;
76 
77 	hostapd_neighbor_clear_entry(entry);
78 
79 	os_memcpy(entry->bssid, bssid, ETH_ALEN);
80 	os_memcpy(&entry->ssid, ssid, sizeof(entry->ssid));
81 
82 	entry->nr = wpabuf_dup(nr);
83 	if (!entry->nr)
84 		goto fail;
85 
86 	if (lci) {
87 		entry->lci = wpabuf_dup(lci);
88 		if (!entry->lci || os_get_time(&entry->lci_date))
89 			goto fail;
90 	}
91 
92 	if (civic) {
93 		entry->civic = wpabuf_dup(civic);
94 		if (!entry->civic)
95 			goto fail;
96 	}
97 
98 	return 0;
99 
100 fail:
101 	hostapd_neighbor_remove(hapd, bssid, ssid);
102 	return -1;
103 }
104 
105 
106 int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
107 			    const struct wpa_ssid_value *ssid)
108 {
109 	struct hostapd_neighbor_entry *nr;
110 
111 	nr = hostapd_neighbor_get(hapd, bssid, ssid);
112 	if (!nr)
113 		return -1;
114 
115 	hostapd_neighbor_clear_entry(nr);
116 	dl_list_del(&nr->list);
117 	os_free(nr);
118 
119 	return 0;
120 }
121 
122 
123 void hostpad_free_neighbor_db(struct hostapd_data *hapd)
124 {
125 	struct hostapd_neighbor_entry *nr, *prev;
126 
127 	dl_list_for_each_safe(nr, prev, &hapd->nr_db,
128 			      struct hostapd_neighbor_entry, list) {
129 		hostapd_neighbor_clear_entry(nr);
130 		dl_list_del(&nr->list);
131 		os_free(nr);
132 	}
133 }
134