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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since df96271 was 1433ecda, checked in by Jiri Svoboda <jiri@…>, 8 years ago

Fix cstyle: make ccheck-fix and commit only files where all the changes are good.

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