source: mainline/uspace/lib/nic/src/nic_addr_db.c@ 00d7e1b

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 00d7e1b was 00d7e1b, checked in by Martin Decky <martin@…>, 14 years ago

networking improvements

  • start the networking stack from init
  • add loopback network interface driver (cherrypicked and sanitized from lp:~helenos-nicf/helenos/nicf)
  • add libnic and various small pieces from lp:~helenos-nicf/helenos/nicf
  • fix client side of NIC_GET_ADDRESS
  • net binary overhaul

Note: "ping 127.0.0.1" works, but the first three pings timeout for some reason

  • Property mode set to 100644
File size: 6.8 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 Generic hash-set based database of addresses
36 */
37#include <assert.h>
38#include <stdlib.h>
39#include <bool.h>
40#include <errno.h>
41#include <mem.h>
42
43#include "nic_addr_db.h"
44
45/**
46 * Hash set helper function
47 */
48static int nic_addr_equals(const link_t *item1, const link_t *item2)
49{
50 assert(item1 && item2);
51 size_t addr_len = ((const nic_addr_entry_t *) item1)->addr_len;
52
53 assert(addr_len == ((const nic_addr_entry_t *) item2)->addr_len);
54
55 size_t i;
56 for (i = 0; i < addr_len; ++i) {
57 if (((nic_addr_entry_t *) item1)->addr[i] !=
58 ((nic_addr_entry_t *) item2)->addr[i])
59 return false;
60 }
61 return true;
62}
63
64/**
65 * Hash set helper function
66 */
67static unsigned long nic_addr_hash(const link_t *item)
68{
69 assert(item);
70 const nic_addr_entry_t *entry = (const nic_addr_entry_t *) item;
71 unsigned long hash = 0;
72
73 size_t i;
74 for (i = 0; i < entry->addr_len; ++i) {
75 hash = (hash << 8) ^ (hash >> 24) ^ entry->addr[i];
76 }
77 return hash;
78}
79
80/**
81 * Helper wrapper
82 */
83static void nic_addr_destroy(link_t *item, void *unused)
84{
85 free(item);
86}
87
88/**
89 * Initialize the database
90 *
91 * @param[in,out] db Uninitialized storage
92 * @param[in] addr_len Size of addresses in the db
93 *
94 * @return EOK If successfully initialized
95 * @return EINVAL If the address length is too big
96 * @return ENOMEM If there was not enough memory to initialize the storage
97 */
98int nic_addr_db_init(nic_addr_db_t *db, size_t addr_len)
99{
100 assert(db);
101 if (addr_len > NIC_ADDR_MAX_LENGTH) {
102 return EINVAL;
103 }
104 if (!hash_set_init(&db->set, nic_addr_hash, nic_addr_equals,
105 NIC_ADDR_DB_INIT_SIZE)) {
106 return ENOMEM;
107 }
108 db->addr_len = addr_len;
109 return EOK;
110}
111
112/**
113 * Remove all records from the DB
114 *
115 * @param db
116 */
117void nic_addr_db_clear(nic_addr_db_t *db)
118{
119 assert(db);
120 hash_set_clear(&db->set, nic_addr_destroy, NULL);
121}
122
123/**
124 * Free the memory used by db, including all records...
125 *
126 * @param db
127 */
128void nic_addr_db_destroy(nic_addr_db_t *db)
129{
130 assert(db);
131 hash_set_apply(&db->set, nic_addr_destroy, NULL);
132 hash_set_destroy(&db->set);
133}
134
135/**
136 * Get number of addresses in the db
137 *
138 * @param db
139 *
140 * @return Number of adresses
141 */
142size_t nic_addr_db_count(const nic_addr_db_t *db)
143{
144 assert(db);
145 return hash_set_count(&db->set);
146}
147
148/**
149 * Insert an address to the db
150 *
151 * @param db
152 * @param addr Inserted address. Length is implicitly concluded from the
153 * db's address length.
154 *
155 * @return EOK If the address was inserted
156 * @return ENOMEM If there was not enough memory
157 * @return EEXIST If this adress already is in the db
158 */
159int nic_addr_db_insert(nic_addr_db_t *db, const uint8_t *addr)
160{
161 assert(db && addr);
162 nic_addr_entry_t *entry = malloc(sizeof (nic_addr_entry_t));
163 if (entry == NULL) {
164 return ENOMEM;
165 }
166 entry->addr_len = db->addr_len;
167 memcpy(entry->addr, addr, db->addr_len);
168
169 return hash_set_insert(&db->set, &entry->item) ? EOK : EEXIST;
170}
171
172/**
173 * Remove the address from the db
174 *
175 * @param db
176 * @param addr Removed address.
177 *
178 * @return EOK If the address was removed
179 * @return ENOENT If there is no address
180 */
181int nic_addr_db_remove(nic_addr_db_t *db, const uint8_t *addr)
182{
183 assert(db && addr);
184 nic_addr_entry_t entry;
185 entry.addr_len = db->addr_len;
186 memcpy(entry.addr, addr, db->addr_len);
187
188 link_t *removed = hash_set_remove(&db->set, &entry.item);
189 free(removed);
190 return removed != NULL ? EOK : ENOENT;
191}
192
193/**
194 * Test if the address is contained in the db
195 *
196 * @param db
197 * @param addr Tested addresss
198 *
199 * @return true if the address is in the db, false otherwise
200 */
201int nic_addr_db_contains(const nic_addr_db_t *db, const uint8_t *addr)
202{
203 assert(db && addr);
204 nic_addr_entry_t entry;
205 entry.addr_len = db->addr_len;
206 memcpy(entry.addr, addr, db->addr_len);
207
208 return hash_set_contains(&db->set, &entry.item);
209}
210
211/**
212 * Helper structure for nic_addr_db_foreach
213 */
214typedef struct {
215 void (*func)(const uint8_t *, void *);
216 void *arg;
217} nic_addr_db_fe_arg_t;
218
219/**
220 * Helper function for nic_addr_db_foreach
221 */
222static void nic_addr_db_fe_helper(link_t *item, void *arg) {
223 nic_addr_db_fe_arg_t *hs = (nic_addr_db_fe_arg_t *) arg;
224 hs->func(((nic_addr_entry_t *) item)->addr, hs->arg);
225}
226
227/**
228 * Executes a user-defined function on all addresses in the DB. The function
229 * must not change the addresses.
230 *
231 * @param db
232 * @param func User-defined function
233 * @param arg Custom argument passed to the function
234 */
235void nic_addr_db_foreach(const nic_addr_db_t *db,
236 void (*func)(const uint8_t *, void *), void *arg)
237{
238 nic_addr_db_fe_arg_t hs = { .func = func, .arg = arg };
239 hash_set_apply((hash_set_t *) &db->set, nic_addr_db_fe_helper, &hs);
240}
241
242/**
243 * Helper structure for nic_addr_db_remove_selected
244 */
245typedef struct {
246 int (*func)(const uint8_t *, void *);
247 void *arg;
248} nic_addr_db_rs_arg_t;
249
250/**
251 * Helper function for nic_addr_db_foreach
252 */
253static int nic_addr_db_rs_helper(link_t *item, void *arg) {
254 nic_addr_db_rs_arg_t *hs = (nic_addr_db_rs_arg_t *) arg;
255 int retval = hs->func(((nic_addr_entry_t *) item)->addr, hs->arg);
256 if (retval) {
257 free(item);
258 }
259 return retval;
260}
261
262/**
263 * Removes all addresses for which the function returns non-zero.
264 *
265 * @param db
266 * @param func User-defined function
267 * @param arg Custom argument passed to the function
268 */
269void nic_addr_db_remove_selected(nic_addr_db_t *db,
270 int (*func)(const uint8_t *, void *), void *arg)
271{
272 nic_addr_db_rs_arg_t hs = { .func = func, .arg = arg };
273 hash_set_remove_selected(&db->set, nic_addr_db_rs_helper, &hs);
274}
275
276/** @}
277 */
Note: See TracBrowser for help on using the repository browser.