xref: /freebsd/contrib/wpa/src/ap/neighbor_db.c (revision 85732ac8)
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 	nr->stationary = 0;
47 }
48 
49 
50 static struct hostapd_neighbor_entry *
51 hostapd_neighbor_add(struct hostapd_data *hapd)
52 {
53 	struct hostapd_neighbor_entry *nr;
54 
55 	nr = os_zalloc(sizeof(struct hostapd_neighbor_entry));
56 	if (!nr)
57 		return NULL;
58 
59 	dl_list_add(&hapd->nr_db, &nr->list);
60 
61 	return nr;
62 }
63 
64 
65 int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid,
66 			 const struct wpa_ssid_value *ssid,
67 			 const struct wpabuf *nr, const struct wpabuf *lci,
68 			 const struct wpabuf *civic, int stationary)
69 {
70 	struct hostapd_neighbor_entry *entry;
71 
72 	entry = hostapd_neighbor_get(hapd, bssid, ssid);
73 	if (!entry)
74 		entry = hostapd_neighbor_add(hapd);
75 	if (!entry)
76 		return -1;
77 
78 	hostapd_neighbor_clear_entry(entry);
79 
80 	os_memcpy(entry->bssid, bssid, ETH_ALEN);
81 	os_memcpy(&entry->ssid, ssid, sizeof(entry->ssid));
82 
83 	entry->nr = wpabuf_dup(nr);
84 	if (!entry->nr)
85 		goto fail;
86 
87 	if (lci && wpabuf_len(lci)) {
88 		entry->lci = wpabuf_dup(lci);
89 		if (!entry->lci || os_get_time(&entry->lci_date))
90 			goto fail;
91 	}
92 
93 	if (civic && wpabuf_len(civic)) {
94 		entry->civic = wpabuf_dup(civic);
95 		if (!entry->civic)
96 			goto fail;
97 	}
98 
99 	entry->stationary = stationary;
100 
101 	return 0;
102 
103 fail:
104 	hostapd_neighbor_remove(hapd, bssid, ssid);
105 	return -1;
106 }
107 
108 
109 int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
110 			    const struct wpa_ssid_value *ssid)
111 {
112 	struct hostapd_neighbor_entry *nr;
113 
114 	nr = hostapd_neighbor_get(hapd, bssid, ssid);
115 	if (!nr)
116 		return -1;
117 
118 	hostapd_neighbor_clear_entry(nr);
119 	dl_list_del(&nr->list);
120 	os_free(nr);
121 
122 	return 0;
123 }
124 
125 
126 void hostpad_free_neighbor_db(struct hostapd_data *hapd)
127 {
128 	struct hostapd_neighbor_entry *nr, *prev;
129 
130 	dl_list_for_each_safe(nr, prev, &hapd->nr_db,
131 			      struct hostapd_neighbor_entry, list) {
132 		hostapd_neighbor_clear_entry(nr);
133 		dl_list_del(&nr->list);
134 		os_free(nr);
135 	}
136 }
137