source: mainline/uspace/app/nic/nic.c@ 2aaba7e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2aaba7e was 18902ca6, checked in by jzr <zarevucky.jiri@…>, 8 years ago

Fix several bugs and typos detected by clang.

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