source: mainline/uspace/lib/nic/src/nic_wol_virtues.c@ 504d103

Last change on this file since 504d103 was 5e801dc, checked in by GitHub <noreply@…>, 6 years ago

Indicate and enforce constness of hash table key in certain functions (#158)

The assumption here is that modifying key in the hash/equal functions in something completely unexpected, and not something you would ever want to do intentionally, so it makes sense to disallow it entirely to get that extra level of checking.

  • Property mode set to 100644
File size: 7.9 KB
Line 
1/*
2 * Copyright (c) 2011 Radim Vansa
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/**
30 * @addtogroup libnic
31 * @{
32 */
33/**
34 * @file
35 * @brief Wake-on-LAN support
36 */
37
38#include "nic_wol_virtues.h"
39#include "nic.h"
40#include <assert.h>
41#include <errno.h>
42
43/*
44 * Hash table helper functions
45 */
46
47static size_t nic_wv_key_hash(const void *key)
48{
49 const nic_wv_id_t *k = key;
50 return *k;
51}
52
53static size_t nic_wv_hash(const ht_link_t *item)
54{
55 nic_wol_virtue_t *virtue = (nic_wol_virtue_t *) item;
56 return virtue->id;
57}
58
59static bool nic_wv_key_equal(const void *key, const ht_link_t *item)
60{
61 const nic_wv_id_t *k = key;
62 const nic_wol_virtue_t *virtue = (const nic_wol_virtue_t *) item;
63 return (virtue->id == *k);
64}
65
66/**
67 * Initializes the WOL virtues structure
68 *
69 * @param wvs
70 *
71 * @return EOK On success
72 * @return ENOMEM On not enough memory
73 */
74errno_t nic_wol_virtues_init(nic_wol_virtues_t *wvs)
75{
76 memset(wvs, 0, sizeof(nic_wol_virtues_t));
77 wvs->table_operations.hash = nic_wv_hash;
78 wvs->table_operations.key_hash = nic_wv_key_hash;
79 wvs->table_operations.key_equal = nic_wv_key_equal;
80 wvs->table_operations.equal = 0;
81 wvs->table_operations.remove_callback = 0;
82
83 if (!hash_table_create(&wvs->table, 0, 0, &wvs->table_operations)) {
84 return ENOMEM;
85 }
86 size_t i;
87 for (i = 0; i < NIC_WV_MAX; ++i) {
88 wvs->caps_max[i] = -1;
89 }
90 wvs->next_id = 0;
91 return EOK;
92}
93
94/**
95 * Reinitializes the structure, destroying all virtues. The next_id is not
96 * changed (some apps could still hold the filter IDs).
97 *
98 * @param wvs
99 */
100void nic_wol_virtues_clear(nic_wol_virtues_t *wvs)
101{
102 hash_table_clear(&wvs->table);
103 nic_wv_type_t type;
104 for (type = NIC_WV_NONE; type < NIC_WV_MAX; ++type) {
105 nic_wol_virtue_t *virtue = wvs->lists[type];
106 while (virtue != NULL) {
107 nic_wol_virtue_t *next = virtue->next;
108 free(virtue->data);
109 free(virtue);
110 virtue = next;
111 }
112 wvs->lists_sizes[type] = 0;
113 }
114}
115
116/**
117 * Verifies that the arguments for the WOL virtues are correct.
118 *
119 * @param type Type of the virtue
120 * @param data Data argument for the virtue
121 * @param length Length of the data
122 *
123 * @return EOK The arguments are correct
124 * @return EINVAL The arguments are incorrect
125 * @return ENOTSUP This type is unknown
126 */
127errno_t nic_wol_virtues_verify(nic_wv_type_t type, const void *data, size_t length)
128{
129 switch (type) {
130 case NIC_WV_ARP_REQUEST:
131 case NIC_WV_BROADCAST:
132 case NIC_WV_LINK_CHANGE:
133 return EOK;
134 case NIC_WV_DESTINATION:
135 return length == sizeof (nic_address_t) ? EOK : EINVAL;
136 case NIC_WV_DIRECTED_IPV4:
137 return length == sizeof (nic_wv_ipv4_data_t) ? EOK : EINVAL;
138 case NIC_WV_DIRECTED_IPV6:
139 return length == sizeof (nic_wv_ipv6_data_t) ? EOK : EINVAL;
140 case NIC_WV_FULL_MATCH:
141 return length % 2 == 0 ? EOK : EINVAL;
142 case NIC_WV_MAGIC_PACKET:
143 return data == NULL || length == sizeof (nic_wv_magic_packet_data_t) ?
144 EOK : EINVAL;
145 default:
146 return ENOTSUP;
147 }
148}
149
150/**
151 * Adds the virtue to the list of known virtues, activating it.
152 *
153 * @param wvs
154 * @param virtue The virtue structure
155 *
156 * @return EOK On success
157 * @return ENOTSUP If the virtue type is not supported
158 * @return EINVAL If the virtue type is a single-filter and there's already
159 * a virtue of this type defined, or there is something wrong
160 * with the data
161 * @return ENOMEM Not enough memory to activate the virtue
162 */
163errno_t nic_wol_virtues_add(nic_wol_virtues_t *wvs, nic_wol_virtue_t *virtue)
164{
165 if (!nic_wv_is_multi(virtue->type) &&
166 wvs->lists[virtue->type] != NULL) {
167 return EINVAL;
168 }
169 do {
170 virtue->id = wvs->next_id++;
171 } while (NULL != hash_table_find(&wvs->table, &virtue->id));
172 hash_table_insert(&wvs->table, &virtue->item);
173 virtue->next = wvs->lists[virtue->type];
174 wvs->lists[virtue->type] = virtue;
175 wvs->lists_sizes[virtue->type]++;
176 return EOK;
177}
178
179/**
180 * Removes the virtue from the list of virtues, but NOT deallocating the
181 * nic_wol_virtue structure.
182 *
183 * @param wvs
184 * @param id Identifier of the removed virtue
185 *
186 * @return Removed virtue structure or NULL if not found.
187 */
188nic_wol_virtue_t *nic_wol_virtues_remove(nic_wol_virtues_t *wvs, nic_wv_id_t id)
189{
190 nic_wol_virtue_t *virtue =
191 (nic_wol_virtue_t *) hash_table_find(&wvs->table, &id);
192 if (virtue == NULL) {
193 return NULL;
194 }
195
196 /* Remove from filter_table */
197 hash_table_remove_item(&wvs->table, &virtue->item);
198
199 /* Remove from filter_types */
200 assert(wvs->lists[virtue->type] != NULL);
201 if (wvs->lists[virtue->type] == virtue) {
202 wvs->lists[virtue->type] = virtue->next;
203 } else {
204 nic_wol_virtue_t *wv = wvs->lists[virtue->type];
205 while (wv->next != virtue) {
206 wv = wv->next;
207 assert(wv != NULL);
208 }
209 wv->next = virtue->next;
210 }
211 wvs->lists_sizes[virtue->type]--;
212
213 virtue->next = NULL;
214 return virtue;
215}
216
217/**
218 * Searches the filters table for a filter with specified ID
219 *
220 * @param wvs
221 * @param id Identifier of the searched virtue
222 *
223 * @return Requested filter or NULL if not found.
224 */
225const nic_wol_virtue_t *nic_wol_virtues_find(const nic_wol_virtues_t *wvs,
226 nic_wv_id_t id)
227{
228 /*
229 * The hash_table_find cannot be const, because it would require the
230 * returned link to be const as well. But in this case, when we're returning
231 * constant virtue the retyping is correct.
232 */
233 ht_link_t *virtue = hash_table_find(&((nic_wol_virtues_t *) wvs)->table, &id);
234 return (const nic_wol_virtue_t *) virtue;
235}
236
237/**
238 * Fill identifiers of current wol virtues of the specified type into the list.
239 * If the type is set to NIC_WV_NONE, all virtues are used.
240 *
241 * @param wvs
242 * @param[in] type Type of the virtues or NIC_WV_NONE
243 * @param[out] id_list The new vector of filter IDs. Can be NULL.
244 * @param[out] count Number of IDs in the filter_list. Can be NULL.
245 *
246 * @return EOK If it completes successfully
247 * @return EINVAL If the filter type is invalid
248 */
249errno_t nic_wol_virtues_list(const nic_wol_virtues_t *wvs, nic_wv_type_t type,
250 size_t max_count, nic_wv_id_t *id_list, size_t *id_count)
251{
252 size_t count = 0;
253 if (type == NIC_WV_NONE) {
254 size_t i;
255 for (i = NIC_WV_NONE; i < NIC_WV_MAX; ++i) {
256 if (id_list != NULL) {
257 nic_wol_virtue_t *virtue = wvs->lists[i];
258 while (virtue != NULL) {
259 if (count < max_count) {
260 id_list[count] = virtue->id;
261 }
262 ++count;
263 virtue = virtue->next;
264 }
265 } else {
266 count += wvs->lists_sizes[i];
267 }
268 }
269 } else if (type >= NIC_WV_MAX) {
270 return EINVAL;
271 } else {
272 if (id_list != NULL) {
273 nic_wol_virtue_t *virtue = wvs->lists[type];
274 while (virtue != NULL) {
275 if (count < max_count) {
276 id_list[count] = virtue->id;
277 }
278 ++count;
279 virtue = virtue->next;
280 }
281 } else {
282 count = wvs->lists_sizes[type];
283 }
284 }
285 if (id_count != NULL) {
286 *id_count = count;
287 }
288 return EOK;
289}
290
291/** @}
292 */
Note: See TracBrowser for help on using the repository browser.