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

Last change on this file was 09ab0a9a, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix vertical spacing with new Ccheck revision.

  • Property mode set to 100644
File size: 13.5 KB
RevLine 
[6bcecc2]1/*
2 * Copyright (c) 2014 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 nic
30 * @{
31 */
32/** @file NIC configuration utility.
33 *
34 */
35
[d73d992]36#include <assert.h>
[6bcecc2]37#include <errno.h>
38#include <loc.h>
39#include <nic_iface.h>
40#include <stdio.h>
41#include <stdlib.h>
[8d2dd7f2]42#include <stddef.h>
[1d6dd2a]43#include <str.h>
[6bcecc2]44#include <str_error.h>
45
46#define NAME "nic"
47
48typedef struct {
[7493e7b]49 nic_device_info_t device_info;
[6bcecc2]50 nic_address_t address;
51 nic_cable_state_t link_state;
[7493e7b]52 nic_channel_mode_t duplex;
[aa2f865]53 nic_unicast_mode_t unicast_mode;
54 nic_multicast_mode_t multicast_mode;
55 nic_broadcast_mode_t broadcast_mode;
[7493e7b]56 int speed;
[6bcecc2]57} nic_info_t;
58
59static void print_syntax(void)
60{
61 printf("syntax:\n");
[278fede]62 printf("\t" NAME " [<index> <cmd> [<args...>]]\n");
63 printf("\t<index> is NIC index number reported by the tool\n");
64 printf("\t<cmd> is:\n");
65 printf("\taddr <mac_address> - set MAC address\n");
66 printf("\tspeed <10|100|1000> - set NIC speed\n");
[cbfece7]67 printf("\tduplex <half|full|simplex> - set duplex mode\n");
68 printf("\tauto - enable autonegotiation\n");
[aa2f865]69 printf("\tunicast <block|default|list|promisc> - set unicast receive filtering\n");
70 printf("\tmulticast <block|list|promisc> - set multicast receive filtering\n");
71 printf("\tbroadcast <block|allow> - block or allow incoming broadcast frames\n");
[278fede]72}
73
74static async_sess_t *get_nic_by_index(size_t i)
75{
[b7fd2a0]76 errno_t rc;
[278fede]77 size_t count;
78 char *svc_name;
79 category_id_t nic_cat;
80 service_id_t *nics = NULL;
81 async_sess_t *sess;
82
83 rc = loc_category_get_id("nic", &nic_cat, 0);
84 if (rc != EOK) {
85 printf("Error resolving category 'nic'.\n");
86 goto error;
87 }
88
89 rc = loc_category_get_svcs(nic_cat, &nics, &count);
90 if (rc != EOK) {
91 printf("Error getting list of NICs.\n");
92 goto error;
93 }
94
95 rc = loc_service_get_name(nics[i], &svc_name);
96 if (rc != EOK) {
97 printf("Error getting service name.\n");
98 goto error;
99 }
100
101 printf("Using device: %s\n", svc_name);
102
[f9b2cb4c]103 sess = loc_service_connect(nics[i], INTERFACE_DDF, 0);
[278fede]104 if (sess == NULL) {
105 printf("Error connecting to service.\n");
106 goto error;
107 }
108
109 return sess;
110error:
111 return NULL;
[6bcecc2]112}
113
[b7fd2a0]114static errno_t nic_get_info(service_id_t svc_id, char *svc_name,
[6bcecc2]115 nic_info_t *info)
116{
117 async_sess_t *sess;
[7493e7b]118 nic_role_t role;
[b7fd2a0]119 errno_t rc;
[6bcecc2]120
[f9b2cb4c]121 sess = loc_service_connect(svc_id, INTERFACE_DDF, 0);
[6bcecc2]122 if (sess == NULL) {
[278fede]123 printf("Error connecting to service.\n");
[18902ca6]124 rc = EIO;
[6bcecc2]125 goto error;
126 }
[a35b458]127
[6bcecc2]128 rc = nic_get_address(sess, &info->address);
129 if (rc != EOK) {
130 printf("Error getting NIC address.\n");
131 rc = EIO;
132 goto error;
133 }
134
[7493e7b]135 rc = nic_get_device_info(sess, &info->device_info);
136 if (rc != EOK) {
137 printf("Error getting NIC device info.\n");
138 rc = EIO;
139 goto error;
140 }
141
[6bcecc2]142 rc = nic_get_cable_state(sess, &info->link_state);
143 if (rc != EOK) {
144 printf("Error getting link state.\n");
145 rc = EIO;
146 goto error;
147 }
148
[7493e7b]149 rc = nic_get_operation_mode(sess, &info->speed, &info->duplex, &role);
150 if (rc != EOK) {
151 printf("Error getting NIC speed and duplex mode.\n");
152 rc = EIO;
153 goto error;
154 }
155
[aa2f865]156 rc = nic_unicast_get_mode(sess, &info->unicast_mode, 0, NULL, NULL);
157 if (rc != EOK) {
158 printf("Error gettinc NIC unicast receive mode.\n");
159 rc = EIO;
160 goto error;
161 }
162
163 rc = nic_multicast_get_mode(sess, &info->multicast_mode, 0, NULL, NULL);
164 if (rc != EOK) {
165 printf("Error gettinc NIC multicast receive mode.\n");
166 rc = EIO;
167 goto error;
168 }
169
170 rc = nic_broadcast_get_mode(sess, &info->broadcast_mode);
171 if (rc != EOK) {
172 printf("Error gettinc NIC broadcast receive mode.\n");
173 rc = EIO;
174 goto error;
175 }
[7493e7b]176
[6bcecc2]177 return EOK;
178error:
179 return rc;
180}
181
182static const char *nic_link_state_str(nic_cable_state_t link_state)
183{
184 switch (link_state) {
[1433ecda]185 case NIC_CS_UNKNOWN:
186 return "unknown";
187 case NIC_CS_PLUGGED:
188 return "up";
189 case NIC_CS_UNPLUGGED:
190 return "down";
191 default:
192 assert(false);
193 return NULL;
[6bcecc2]194 }
195}
196
[7493e7b]197static const char *nic_duplex_mode_str(nic_channel_mode_t mode)
198{
199 switch (mode) {
[1433ecda]200 case NIC_CM_FULL_DUPLEX:
201 return "full-duplex";
202 case NIC_CM_HALF_DUPLEX:
203 return "half-duplex";
204 case NIC_CM_SIMPLEX:
205 return "simplex";
206 default:
207 assert(false);
208 return NULL;
[7493e7b]209 }
210}
211
[aa2f865]212static const char *nic_unicast_mode_str(nic_unicast_mode_t mode)
213{
214 switch (mode) {
[1433ecda]215 case NIC_UNICAST_UNKNOWN:
216 return "unknown";
217 case NIC_UNICAST_BLOCKED:
218 return "blocked";
219 case NIC_UNICAST_DEFAULT:
220 return "default";
221 case NIC_UNICAST_LIST:
222 return "list";
223 case NIC_UNICAST_PROMISC:
224 return "promisc";
225 default:
226 assert(false);
227 return NULL;
[aa2f865]228 }
229}
230
[18902ca6]231static const char *nic_multicast_mode_str(nic_multicast_mode_t mode)
[aa2f865]232{
233 switch (mode) {
[1433ecda]234 case NIC_MULTICAST_UNKNOWN:
235 return "unknown";
236 case NIC_MULTICAST_BLOCKED:
237 return "blocked";
238 case NIC_MULTICAST_LIST:
239 return "list";
240 case NIC_MULTICAST_PROMISC:
241 return "promisc";
242 default:
243 assert(false);
244 return NULL;
[aa2f865]245 }
246}
247
[18902ca6]248static const char *nic_broadcast_mode_str(nic_broadcast_mode_t mode)
[aa2f865]249{
250 switch (mode) {
[1433ecda]251 case NIC_BROADCAST_UNKNOWN:
252 return "unknown";
253 case NIC_BROADCAST_BLOCKED:
254 return "blocked";
255 case NIC_BROADCAST_ACCEPTED:
256 return "accepted";
257 default:
258 assert(false);
259 return NULL;
[aa2f865]260 }
261}
262
[6bcecc2]263static char *nic_addr_format(nic_address_t *a)
264{
265 int rc;
266 char *s;
267
268 rc = asprintf(&s, "%02x:%02x:%02x:%02x:%02x:%02x",
269 a->address[0], a->address[1], a->address[2],
270 a->address[3], a->address[4], a->address[5]);
271 if (rc < 0)
272 return NULL;
273
274 return s;
275}
276
[b7fd2a0]277static errno_t nic_list(void)
[6bcecc2]278{
279 category_id_t nic_cat;
280 service_id_t *nics = NULL;
281 nic_info_t nic_info;
282 size_t count, i;
283 char *svc_name;
284 char *addr_str;
[b7fd2a0]285 errno_t rc;
[6bcecc2]286
287 rc = loc_category_get_id("nic", &nic_cat, 0);
288 if (rc != EOK) {
289 printf("Error resolving category 'nic'.\n");
290 goto error;
291 }
292
293 rc = loc_category_get_svcs(nic_cat, &nics, &count);
294 if (rc != EOK) {
295 printf("Error getting list of NICs.\n");
296 goto error;
297 }
298
[cbfece7]299 printf("[Index]: [Service Name]\n");
[6bcecc2]300 for (i = 0; i < count; i++) {
301 rc = loc_service_get_name(nics[i], &svc_name);
302 if (rc != EOK) {
303 printf("Error getting service name.\n");
304 goto error;
305 }
306
307 rc = nic_get_info(nics[i], svc_name, &nic_info);
308 if (rc != EOK)
309 goto error;
310
311 addr_str = nic_addr_format(&nic_info.address);
312 if (addr_str == NULL) {
313 printf("Out of memory.\n");
314 rc = ENOMEM;
315 goto error;
316 }
317
[ee95794]318 printf("%zu: %s\n", i, svc_name);
[278fede]319 printf("\tMAC address: %s\n", addr_str);
[7493e7b]320 printf("\tVendor name: %s\n",
321 nic_info.device_info.vendor_name);
322 printf("\tModel name: %s\n",
323 nic_info.device_info.model_name);
324 printf("\tLink state: %s\n",
325 nic_link_state_str(nic_info.link_state));
[aa2f865]326 printf("\tUnicast receive mode: %s\n",
327 nic_unicast_mode_str(nic_info.unicast_mode));
328 printf("\tMulticast receive mode: %s\n",
329 nic_multicast_mode_str(nic_info.multicast_mode));
330 printf("\tBroadcast receive mode: %s\n",
331 nic_broadcast_mode_str(nic_info.broadcast_mode));
[7493e7b]332
333 if (nic_info.link_state == NIC_CS_PLUGGED) {
334 printf("\tSpeed: %dMbps %s\n", nic_info.speed,
335 nic_duplex_mode_str(nic_info.duplex));
336 }
[6bcecc2]337
338 free(svc_name);
339 free(addr_str);
340 }
341
342 return EOK;
343error:
344 free(nics);
345 return rc;
346}
347
[b7fd2a0]348static errno_t nic_set_speed(int i, char *str)
[278fede]349{
350 async_sess_t *sess;
351 uint32_t speed;
352 int oldspeed;
353 nic_channel_mode_t oldduplex;
354 nic_role_t oldrole;
[b7fd2a0]355 errno_t rc;
[278fede]356
357 rc = str_uint32_t(str, NULL, 10, false, &speed);
358 if (rc != EOK) {
359 printf("Speed must be a numeric value.\n");
360 return rc;
361 }
362
363 if (speed != 10 && speed != 100 && speed != 1000) {
364 printf("Speed must be one of: 10, 100, 1000.\n");
365 return EINVAL;
366 }
367
368 sess = get_nic_by_index(i);
369 if (sess == NULL) {
370 printf("Specified NIC doesn't exist or cannot connect to it.\n");
371 return EINVAL;
372 }
373
374 rc = nic_get_operation_mode(sess, &oldspeed, &oldduplex, &oldrole);
375 if (rc != EOK) {
376 printf("Error getting NIC speed and duplex mode.\n");
377 return EIO;
378 }
379
380 return nic_set_operation_mode(sess, speed, oldduplex, oldrole);
381}
382
[b7fd2a0]383static errno_t nic_set_duplex(int i, char *str)
[278fede]384{
385 async_sess_t *sess;
386 int oldspeed;
387 nic_channel_mode_t duplex = NIC_CM_UNKNOWN;
388 nic_channel_mode_t oldduplex;
389 nic_role_t oldrole;
[b7fd2a0]390 errno_t rc;
[278fede]391
392 if (!str_cmp(str, "half"))
393 duplex = NIC_CM_HALF_DUPLEX;
394
395 if (!str_cmp(str, "full"))
396 duplex = NIC_CM_FULL_DUPLEX;
397
398 if (!str_cmp(str, "simplex"))
399 duplex = NIC_CM_SIMPLEX;
400
401 if (duplex == NIC_CM_UNKNOWN) {
402 printf("Invalid duplex specification.\n");
403 return EINVAL;
404 }
405
406 sess = get_nic_by_index(i);
407 if (sess == NULL) {
408 printf("Specified NIC doesn't exist or cannot connect to it.\n");
409 return EINVAL;
410 }
411
412 rc = nic_get_operation_mode(sess, &oldspeed, &oldduplex, &oldrole);
413 if (rc != EOK) {
414 printf("Error getting NIC speed and duplex mode.\n");
415 return EIO;
416 }
417
418 return nic_set_operation_mode(sess, oldspeed, duplex, oldrole);
419}
420
[b7fd2a0]421static errno_t nic_set_autoneg(int i)
[cbfece7]422{
423 async_sess_t *sess;
[b7fd2a0]424 errno_t rc;
[cbfece7]425
426 sess = get_nic_by_index(i);
427 if (sess == NULL) {
428 printf("Specified NIC doesn't exist or cannot connect to it.\n");
429 return EINVAL;
430 }
431
432 rc = nic_autoneg_restart(sess);
433 if (rc != EOK) {
434 printf("Error restarting NIC autonegotiation.\n");
435 return EIO;
436 }
437
438 return EOK;
439}
440
[b7fd2a0]441static errno_t nic_set_addr(int i, char *str)
[278fede]442{
443 async_sess_t *sess;
444 nic_address_t addr;
[b7fd2a0]445 errno_t rc;
446 int idx;
[278fede]447
448 sess = get_nic_by_index(i);
449 if (sess == NULL) {
450 printf("Specified NIC doesn't exist or cannot connect to it.\n");
451 return EINVAL;
452 }
453
454 if (str_size(str) != 17) {
455 printf("Invalid MAC address specified");
456 return EINVAL;
457 }
458
459 for (idx = 0; idx < 6; idx++) {
460 rc = str_uint8_t(&str[idx * 3], NULL, 16, false, &addr.address[idx]);
461 if (rc != EOK) {
462 printf("Invalid MAC address specified");
463 return EINVAL;
464 }
465 }
466
467 return nic_set_address(sess, &addr);
468}
469
[b7fd2a0]470static errno_t nic_set_rx_unicast(int i, char *str)
[aa2f865]471{
472 async_sess_t *sess;
473
474 sess = get_nic_by_index(i);
475 if (sess == NULL) {
476 printf("Specified NIC doesn't exist or cannot connect to it.\n");
477 return EINVAL;
478 }
479
480 if (!str_cmp(str, "block")) {
481 nic_unicast_set_mode(sess, NIC_UNICAST_BLOCKED, NULL, 0);
482 return EOK;
483 }
484
485 if (!str_cmp(str, "default")) {
486 nic_unicast_set_mode(sess, NIC_UNICAST_DEFAULT, NULL, 0);
487 return EOK;
488 }
489
490 if (!str_cmp(str, "list")) {
491 nic_unicast_set_mode(sess, NIC_UNICAST_LIST, NULL, 0);
492 return EOK;
493 }
494
495 if (!str_cmp(str, "promisc")) {
496 nic_unicast_set_mode(sess, NIC_UNICAST_PROMISC, NULL, 0);
497 return EOK;
498 }
499
500 printf("Invalid pameter - should be one of: block, default, promisc\n");
501 return EINVAL;
502}
503
[b7fd2a0]504static errno_t nic_set_rx_multicast(int i, char *str)
[aa2f865]505{
506 async_sess_t *sess;
507
508 sess = get_nic_by_index(i);
509 if (sess == NULL) {
510 printf("Specified NIC doesn't exist or cannot connect to it.\n");
511 return EINVAL;
512 }
513
514 if (!str_cmp(str, "block")) {
515 nic_multicast_set_mode(sess, NIC_MULTICAST_BLOCKED, NULL, 0);
516 return EOK;
517 }
518
519 if (!str_cmp(str, "list")) {
520 nic_multicast_set_mode(sess, NIC_MULTICAST_LIST, NULL, 0);
521 return EOK;
522 }
523
524 if (!str_cmp(str, "promisc")) {
525 nic_multicast_set_mode(sess, NIC_MULTICAST_PROMISC, NULL, 0);
526 return EOK;
527 }
528
529 printf("Invalid pameter - should be one of: block, promisc\n");
530 return EINVAL;
531}
532
[b7fd2a0]533static errno_t nic_set_rx_broadcast(int i, char *str)
[aa2f865]534{
535 async_sess_t *sess;
536
537 sess = get_nic_by_index(i);
538 if (sess == NULL) {
539 printf("Specified NIC doesn't exist or cannot connect to it.\n");
540 return EINVAL;
541 }
542
543 if (!str_cmp(str, "block")) {
544 nic_broadcast_set_mode(sess, NIC_BROADCAST_BLOCKED);
545 return EOK;
546 }
547
548 if (!str_cmp(str, "accept")) {
549 nic_broadcast_set_mode(sess, NIC_BROADCAST_ACCEPTED);
550 return EOK;
551 }
552
553 printf("Invalid pameter - should be 'block' or 'accept'\n");
554 return EINVAL;
555}
556
[6bcecc2]557int main(int argc, char *argv[])
558{
[b7fd2a0]559 errno_t rc;
[278fede]560 uint32_t index;
[6bcecc2]561
562 if (argc == 1) {
563 rc = nic_list();
564 if (rc != EOK)
565 return 1;
[278fede]566 } else if (argc >= 3) {
567 rc = str_uint32_t(argv[1], NULL, 10, false, &index);
568 if (rc != EOK) {
569 printf(NAME ": Invalid argument.\n");
570 print_syntax();
571 return 1;
572 }
573
574 if (!str_cmp(argv[2], "addr"))
575 return nic_set_addr(index, argv[3]);
576
577 if (!str_cmp(argv[2], "speed"))
578 return nic_set_speed(index, argv[3]);
579
580 if (!str_cmp(argv[2], "duplex"))
581 return nic_set_duplex(index, argv[3]);
582
[cbfece7]583 if (!str_cmp(argv[2], "auto"))
584 return nic_set_autoneg(index);
585
[aa2f865]586 if (!str_cmp(argv[2], "unicast"))
587 return nic_set_rx_unicast(index, argv[3]);
588
589 if (!str_cmp(argv[2], "multicast"))
590 return nic_set_rx_multicast(index, argv[3]);
591
592 if (!str_cmp(argv[2], "broadcast"))
593 return nic_set_rx_broadcast(index, argv[3]);
594
[6bcecc2]595 } else {
596 printf(NAME ": Invalid argument.\n");
597 print_syntax();
598 return 1;
599 }
600
601 return 0;
602}
603
604/** @}
605 */
Note: See TracBrowser for help on using the repository browser.