source: mainline/uspace/app/inet/inet.c

Last change on this file was 3e6bca8, checked in by Jiri Svoboda <jiri@…>, 4 years ago

Represent Ethernet address as a number instead of an array

Carefully document the design since this breaks the principle of least
surprise. Also add unit tests.

  • Property mode set to 100644
File size: 11.3 KB
Line 
1/*
2 * Copyright (c) 2021 Jiri Svoboda
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/** @addtogroup inet
30 * @{
31 */
32/** @file Internet configuration utility.
33 *
34 * Controls the internet service (@c inet).
35 */
36
37#include <errno.h>
38#include <inet/addr.h>
39#include <inet/eth_addr.h>
40#include <inet/inetcfg.h>
41#include <io/table.h>
42#include <loc.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <stdint.h>
46#include <str.h>
47#include <str_error.h>
48
49#define NAME "inet"
50
51static void print_syntax(void)
52{
53 printf("%s: Internet configuration utility.\n", NAME);
54 printf("Syntax:\n");
55 printf(" %s list-addr\n", NAME);
56 printf(" %s create-addr <addr>/<width> <link-name> <addr-name>\n", NAME);
57 printf(" %s delete-addr <link-name> <addr-name>\n", NAME);
58 printf(" %s list-sr\n", NAME);
59 printf(" %s create-sr <dest-addr>/<width> <router-addr> <route-name>\n", NAME);
60 printf(" %s delete-sr <route-name>\n", NAME);
61 printf(" %s list-link\n", NAME);
62}
63
64static errno_t addr_create_static(int argc, char *argv[])
65{
66 char *aobj_name;
67 char *addr_spec;
68 char *link_name;
69
70 inet_naddr_t naddr;
71 sysarg_t link_id;
72 sysarg_t addr_id;
73 errno_t rc;
74
75 if (argc < 3) {
76 printf(NAME ": Missing arguments.\n");
77 print_syntax();
78 return EINVAL;
79 }
80
81 if (argc > 3) {
82 printf(NAME ": Too many arguments.\n");
83 print_syntax();
84 return EINVAL;
85 }
86
87 addr_spec = argv[0];
88 link_name = argv[1];
89 aobj_name = argv[2];
90
91 rc = loc_service_get_id(link_name, &link_id, 0);
92 if (rc != EOK) {
93 printf(NAME ": Service '%s' not found: %s.\n", link_name, str_error(rc));
94 return ENOENT;
95 }
96
97 rc = inet_naddr_parse(addr_spec, &naddr, NULL);
98 if (rc != EOK) {
99 printf(NAME ": Invalid network address format '%s'.\n",
100 addr_spec);
101 return EINVAL;
102 }
103
104 rc = inetcfg_addr_create_static(aobj_name, &naddr, link_id, &addr_id);
105 if (rc != EOK) {
106 printf(NAME ": Failed creating static address '%s' (%s)\n",
107 aobj_name, str_error(rc));
108 return EIO;
109 }
110
111 return EOK;
112}
113
114static errno_t addr_delete(int argc, char *argv[])
115{
116 char *aobj_name;
117 char *link_name;
118 sysarg_t link_id;
119 sysarg_t addr_id;
120 errno_t rc;
121
122 if (argc < 2) {
123 printf(NAME ": Missing arguments.\n");
124 print_syntax();
125 return EINVAL;
126 }
127
128 if (argc > 2) {
129 printf(NAME ": Too many arguments.\n");
130 print_syntax();
131 return EINVAL;
132 }
133
134 link_name = argv[0];
135 aobj_name = argv[1];
136
137 rc = loc_service_get_id(link_name, &link_id, 0);
138 if (rc != EOK) {
139 printf(NAME ": Service '%s' not found: %s.\n", link_name,
140 str_error(rc));
141 return ENOENT;
142 }
143
144 rc = inetcfg_addr_get_id(aobj_name, link_id, &addr_id);
145 if (rc != EOK) {
146 printf(NAME ": Address '%s' not found: %s.\n", aobj_name,
147 str_error(rc));
148 return ENOENT;
149 }
150
151 rc = inetcfg_addr_delete(addr_id);
152 if (rc != EOK) {
153 printf(NAME ": Failed deleting address '%s': %s\n", aobj_name,
154 str_error(rc));
155 return EIO;
156 }
157
158 return EOK;
159}
160
161static errno_t sroute_create(int argc, char *argv[])
162{
163 char *dest_str;
164 char *router_str;
165 char *route_name;
166
167 inet_naddr_t dest;
168 inet_addr_t router;
169 sysarg_t sroute_id;
170 errno_t rc;
171
172 if (argc < 3) {
173 printf(NAME ": Missing arguments.\n");
174 print_syntax();
175 return EINVAL;
176 }
177
178 if (argc > 3) {
179 printf(NAME ": Too many arguments.\n");
180 print_syntax();
181 return EINVAL;
182 }
183
184 dest_str = argv[0];
185 router_str = argv[1];
186 route_name = argv[2];
187
188 rc = inet_naddr_parse(dest_str, &dest, NULL);
189 if (rc != EOK) {
190 printf(NAME ": Invalid network address format '%s'.\n",
191 dest_str);
192 return EINVAL;
193 }
194
195 rc = inet_addr_parse(router_str, &router, NULL);
196 if (rc != EOK) {
197 printf(NAME ": Invalid address format '%s'.\n", router_str);
198 return EINVAL;
199 }
200
201 rc = inetcfg_sroute_create(route_name, &dest, &router, &sroute_id);
202 if (rc != EOK) {
203 printf(NAME ": Failed creating static route '%s': %s\n",
204 route_name, str_error(rc));
205 return EIO;
206 }
207
208 return EOK;
209}
210
211static errno_t sroute_delete(int argc, char *argv[])
212{
213 char *route_name;
214 sysarg_t sroute_id;
215 errno_t rc;
216
217 if (argc < 1) {
218 printf(NAME ": Missing arguments.\n");
219 print_syntax();
220 return EINVAL;
221 }
222
223 if (argc > 1) {
224 printf(NAME ": Too many arguments.\n");
225 print_syntax();
226 return EINVAL;
227 }
228
229 route_name = argv[0];
230
231 rc = inetcfg_sroute_get_id(route_name, &sroute_id);
232 if (rc != EOK) {
233 printf(NAME ": Static route '%s' not found: %s.\n",
234 route_name, str_error(rc));
235 return ENOENT;
236 }
237
238 rc = inetcfg_sroute_delete(sroute_id);
239 if (rc != EOK) {
240 printf(NAME ": Failed deleting static route '%s': %s\n",
241 route_name, str_error(rc));
242 return EIO;
243 }
244
245 return EOK;
246}
247
248static errno_t addr_list(void)
249{
250 sysarg_t *addr_list;
251 inet_addr_info_t ainfo;
252 inet_link_info_t linfo;
253 table_t *table = NULL;
254
255 size_t count;
256 size_t i;
257 errno_t rc;
258 char *astr = NULL;
259
260 ainfo.name = NULL;
261 linfo.name = NULL;
262
263 rc = inetcfg_get_addr_list(&addr_list, &count);
264 if (rc != EOK) {
265 printf(NAME ": Failed getting address list.\n");
266 return rc;
267 }
268
269 rc = table_create(&table);
270 if (rc != EOK) {
271 printf("Memory allocation failed.\n");
272 goto out;
273 }
274
275 table_header_row(table);
276 table_printf(table, "Addr/Width\t" "Link-Name\t" "Addr-Name\t"
277 "Def-MTU\n");
278
279 for (i = 0; i < count; i++) {
280 rc = inetcfg_addr_get(addr_list[i], &ainfo);
281 if (rc != EOK) {
282 printf("Failed getting properties of address %zu.\n",
283 (size_t)addr_list[i]);
284 ainfo.name = NULL;
285 continue;
286 }
287
288 rc = inetcfg_link_get(ainfo.ilink, &linfo);
289 if (rc != EOK) {
290 printf("Failed getting properties of link %zu.\n",
291 (size_t)ainfo.ilink);
292 linfo.name = NULL;
293 continue;
294 }
295
296 rc = inet_naddr_format(&ainfo.naddr, &astr);
297 if (rc != EOK) {
298 printf("Memory allocation failed.\n");
299 astr = NULL;
300 goto out;
301 }
302
303 table_printf(table, "%s\t" "%s\t" "%s\t" "%zu\n", astr,
304 linfo.name, ainfo.name, linfo.def_mtu);
305
306 free(ainfo.name);
307 free(linfo.name);
308 free(astr);
309
310 ainfo.name = NULL;
311 linfo.name = NULL;
312 astr = NULL;
313 }
314
315 if (count != 0) {
316 rc = table_print_out(table, stdout);
317 if (rc != EOK) {
318 printf("Error printing table.\n");
319 goto out;
320 }
321 }
322
323 rc = EOK;
324out:
325 table_destroy(table);
326 if (ainfo.name != NULL)
327 free(ainfo.name);
328 if (linfo.name != NULL)
329 free(linfo.name);
330 if (astr != NULL)
331 free(astr);
332
333 free(addr_list);
334
335 return rc;
336}
337
338static errno_t link_list(void)
339{
340 sysarg_t *link_list = NULL;
341 inet_link_info_t linfo;
342 table_t *table = NULL;
343 eth_addr_str_t saddr;
344
345 size_t count;
346 size_t i;
347 errno_t rc;
348
349 rc = inetcfg_get_link_list(&link_list, &count);
350 if (rc != EOK) {
351 printf(NAME ": Failed getting link list.\n");
352 return rc;
353 }
354
355 rc = table_create(&table);
356 if (rc != EOK) {
357 printf("Memory allocation failed.\n");
358 goto out;
359 }
360
361 table_header_row(table);
362 table_printf(table, "Link-layer Address\t" "Link-Name\t" "Def-MTU\n");
363
364 for (i = 0; i < count; i++) {
365 rc = inetcfg_link_get(link_list[i], &linfo);
366 if (rc != EOK) {
367 printf("Failed getting properties of link %zu.\n",
368 (size_t)link_list[i]);
369 continue;
370 }
371
372 eth_addr_format(&linfo.mac_addr, &saddr);
373 table_printf(table, "%s\t %s\t %zu\n", saddr.str, linfo.name,
374 linfo.def_mtu);
375
376 free(linfo.name);
377
378 linfo.name = NULL;
379 }
380
381 if (count != 0) {
382 rc = table_print_out(table, stdout);
383 if (rc != EOK) {
384 printf("Error printing table.\n");
385 goto out;
386 }
387 }
388
389 rc = EOK;
390out:
391 table_destroy(table);
392 free(link_list);
393
394 return rc;
395}
396
397static errno_t sroute_list(void)
398{
399 sysarg_t *sroute_list = NULL;
400 inet_sroute_info_t srinfo;
401 table_t *table = NULL;
402
403 size_t count;
404 size_t i;
405 errno_t rc;
406 char *dest_str = NULL;
407 char *router_str = NULL;
408
409 srinfo.name = NULL;
410
411 rc = inetcfg_get_sroute_list(&sroute_list, &count);
412 if (rc != EOK) {
413 printf(NAME ": Failed getting address list.\n");
414 return rc;
415 }
416
417 rc = table_create(&table);
418 if (rc != EOK) {
419 printf("Memory allocation failed.\n");
420 goto out;
421 }
422
423 table_header_row(table);
424 table_printf(table, "Dest/Width\t" "Router-Addr\t" "Route-Name\n");
425
426 for (i = 0; i < count; i++) {
427 rc = inetcfg_sroute_get(sroute_list[i], &srinfo);
428 if (rc != EOK) {
429 printf("Failed getting properties of static route %zu.\n",
430 (size_t)sroute_list[i]);
431 srinfo.name = NULL;
432 continue;
433 }
434
435 rc = inet_naddr_format(&srinfo.dest, &dest_str);
436 if (rc != EOK) {
437 printf("Memory allocation failed.\n");
438 dest_str = NULL;
439 goto out;
440 }
441
442 rc = inet_addr_format(&srinfo.router, &router_str);
443 if (rc != EOK) {
444 printf("Memory allocation failed.\n");
445 router_str = NULL;
446 goto out;
447 }
448
449 table_printf(table, "%s\t" "%s\t" "%s\n", dest_str, router_str,
450 srinfo.name);
451
452 free(srinfo.name);
453 free(dest_str);
454 free(router_str);
455
456 router_str = NULL;
457 srinfo.name = NULL;
458 dest_str = NULL;
459 }
460
461 if (count != 0) {
462 rc = table_print_out(table, stdout);
463 if (rc != EOK) {
464 printf("Error printing table.\n");
465 goto out;
466 }
467 }
468
469 rc = EOK;
470out:
471 table_destroy(table);
472 if (srinfo.name != NULL)
473 free(srinfo.name);
474 if (dest_str != NULL)
475 free(dest_str);
476 if (router_str != NULL)
477 free(router_str);
478
479 free(sroute_list);
480
481 return rc;
482}
483
484int main(int argc, char *argv[])
485{
486 errno_t rc;
487
488 rc = inetcfg_init();
489 if (rc != EOK) {
490 printf(NAME ": Failed connecting to internet service: %s.\n",
491 str_error(rc));
492 return 1;
493 }
494
495 if (argc < 2 || str_cmp(argv[1], "-h") == 0) {
496 print_syntax();
497 return 0;
498 }
499
500 if (str_cmp(argv[1], "list-addr") == 0) {
501 rc = addr_list();
502 if (rc != EOK)
503 return 1;
504 } else if (str_cmp(argv[1], "create-addr") == 0) {
505 rc = addr_create_static(argc - 2, argv + 2);
506 if (rc != EOK)
507 return 1;
508 } else if (str_cmp(argv[1], "delete-addr") == 0) {
509 rc = addr_delete(argc - 2, argv + 2);
510 if (rc != EOK)
511 return 1;
512 } else if (str_cmp(argv[1], "list-sr") == 0) {
513 rc = sroute_list();
514 if (rc != EOK)
515 return 1;
516 } else if (str_cmp(argv[1], "create-sr") == 0) {
517 rc = sroute_create(argc - 2, argv + 2);
518 if (rc != EOK)
519 return 1;
520 } else if (str_cmp(argv[1], "delete-sr") == 0) {
521 rc = sroute_delete(argc - 2, argv + 2);
522 if (rc != EOK)
523 return 1;
524 } else if (str_cmp(argv[1], "list-link") == 0) {
525 rc = link_list();
526 if (rc != EOK)
527 return 1;
528 } else {
529 printf(NAME ": Unknown command '%s'.\n", argv[1]);
530 print_syntax();
531 return 1;
532 }
533
534 return 0;
535}
536
537/** @}
538 */
Note: See TracBrowser for help on using the repository browser.