source: mainline/uspace/app/nic/nic.c@ 338d54a7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 338d54a7 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • 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: return "unknown";
185 case NIC_CS_PLUGGED: return "up";
186 case NIC_CS_UNPLUGGED: return "down";
187 default: assert(false); return NULL;
188 }
189}
190
191static const char *nic_duplex_mode_str(nic_channel_mode_t mode)
192{
193 switch (mode) {
194 case NIC_CM_FULL_DUPLEX: return "full-duplex";
195 case NIC_CM_HALF_DUPLEX: return "half-duplex";
196 case NIC_CM_SIMPLEX: return "simplex";
197 default: assert(false); return NULL;
198 }
199}
200
201static const char *nic_unicast_mode_str(nic_unicast_mode_t mode)
202{
203 switch (mode) {
204 case NIC_UNICAST_UNKNOWN: return "unknown";
205 case NIC_UNICAST_BLOCKED: return "blocked";
206 case NIC_UNICAST_DEFAULT: return "default";
207 case NIC_UNICAST_LIST: return "list";
208 case NIC_UNICAST_PROMISC: return "promisc";
209 default: assert(false); return NULL;
210 }
211}
212
213static const char *nic_multicast_mode_str(nic_multicast_mode_t mode)
214{
215 switch (mode) {
216 case NIC_MULTICAST_UNKNOWN: return "unknown";
217 case NIC_MULTICAST_BLOCKED: return "blocked";
218 case NIC_MULTICAST_LIST: return "list";
219 case NIC_MULTICAST_PROMISC: return "promisc";
220 default: assert(false); return NULL;
221 }
222}
223
224static const char *nic_broadcast_mode_str(nic_broadcast_mode_t mode)
225{
226 switch (mode) {
227 case NIC_BROADCAST_UNKNOWN: return "unknown";
228 case NIC_BROADCAST_BLOCKED: return "blocked";
229 case NIC_BROADCAST_ACCEPTED: return "accepted";
230 default: assert(false); return NULL;
231 }
232}
233
234static char *nic_addr_format(nic_address_t *a)
235{
236 int rc;
237 char *s;
238
239 rc = asprintf(&s, "%02x:%02x:%02x:%02x:%02x:%02x",
240 a->address[0], a->address[1], a->address[2],
241 a->address[3], a->address[4], a->address[5]);
242 if (rc < 0)
243 return NULL;
244
245 return s;
246}
247
248static errno_t nic_list(void)
249{
250 category_id_t nic_cat;
251 service_id_t *nics = NULL;
252 nic_info_t nic_info;
253 size_t count, i;
254 char *svc_name;
255 char *addr_str;
256 errno_t rc;
257
258 rc = loc_category_get_id("nic", &nic_cat, 0);
259 if (rc != EOK) {
260 printf("Error resolving category 'nic'.\n");
261 goto error;
262 }
263
264 rc = loc_category_get_svcs(nic_cat, &nics, &count);
265 if (rc != EOK) {
266 printf("Error getting list of NICs.\n");
267 goto error;
268 }
269
270 printf("[Index]: [Service Name]\n");
271 for (i = 0; i < count; i++) {
272 rc = loc_service_get_name(nics[i], &svc_name);
273 if (rc != EOK) {
274 printf("Error getting service name.\n");
275 goto error;
276 }
277
278 rc = nic_get_info(nics[i], svc_name, &nic_info);
279 if (rc != EOK)
280 goto error;
281
282 addr_str = nic_addr_format(&nic_info.address);
283 if (addr_str == NULL) {
284 printf("Out of memory.\n");
285 rc = ENOMEM;
286 goto error;
287 }
288
289 printf("%zu: %s\n", i, svc_name);
290 printf("\tMAC address: %s\n", addr_str);
291 printf("\tVendor name: %s\n",
292 nic_info.device_info.vendor_name);
293 printf("\tModel name: %s\n",
294 nic_info.device_info.model_name);
295 printf("\tLink state: %s\n",
296 nic_link_state_str(nic_info.link_state));
297 printf("\tUnicast receive mode: %s\n",
298 nic_unicast_mode_str(nic_info.unicast_mode));
299 printf("\tMulticast receive mode: %s\n",
300 nic_multicast_mode_str(nic_info.multicast_mode));
301 printf("\tBroadcast receive mode: %s\n",
302 nic_broadcast_mode_str(nic_info.broadcast_mode));
303
304 if (nic_info.link_state == NIC_CS_PLUGGED) {
305 printf("\tSpeed: %dMbps %s\n", nic_info.speed,
306 nic_duplex_mode_str(nic_info.duplex));
307 }
308
309 free(svc_name);
310 free(addr_str);
311 }
312
313 return EOK;
314error:
315 free(nics);
316 return rc;
317}
318
319static errno_t nic_set_speed(int i, char *str)
320{
321 async_sess_t *sess;
322 uint32_t speed;
323 int oldspeed;
324 nic_channel_mode_t oldduplex;
325 nic_role_t oldrole;
326 errno_t rc;
327
328 rc = str_uint32_t(str, NULL, 10, false, &speed);
329 if (rc != EOK) {
330 printf("Speed must be a numeric value.\n");
331 return rc;
332 }
333
334 if (speed != 10 && speed != 100 && speed != 1000) {
335 printf("Speed must be one of: 10, 100, 1000.\n");
336 return EINVAL;
337 }
338
339 sess = get_nic_by_index(i);
340 if (sess == NULL) {
341 printf("Specified NIC doesn't exist or cannot connect to it.\n");
342 return EINVAL;
343 }
344
345 rc = nic_get_operation_mode(sess, &oldspeed, &oldduplex, &oldrole);
346 if (rc != EOK) {
347 printf("Error getting NIC speed and duplex mode.\n");
348 return EIO;
349 }
350
351 return nic_set_operation_mode(sess, speed, oldduplex, oldrole);
352}
353
354static errno_t nic_set_duplex(int i, char *str)
355{
356 async_sess_t *sess;
357 int oldspeed;
358 nic_channel_mode_t duplex = NIC_CM_UNKNOWN;
359 nic_channel_mode_t oldduplex;
360 nic_role_t oldrole;
361 errno_t rc;
362
363 if (!str_cmp(str, "half"))
364 duplex = NIC_CM_HALF_DUPLEX;
365
366 if (!str_cmp(str, "full"))
367 duplex = NIC_CM_FULL_DUPLEX;
368
369 if (!str_cmp(str, "simplex"))
370 duplex = NIC_CM_SIMPLEX;
371
372 if (duplex == NIC_CM_UNKNOWN) {
373 printf("Invalid duplex specification.\n");
374 return EINVAL;
375 }
376
377 sess = get_nic_by_index(i);
378 if (sess == NULL) {
379 printf("Specified NIC doesn't exist or cannot connect to it.\n");
380 return EINVAL;
381 }
382
383 rc = nic_get_operation_mode(sess, &oldspeed, &oldduplex, &oldrole);
384 if (rc != EOK) {
385 printf("Error getting NIC speed and duplex mode.\n");
386 return EIO;
387 }
388
389 return nic_set_operation_mode(sess, oldspeed, duplex, oldrole);
390}
391
392static errno_t nic_set_autoneg(int i)
393{
394 async_sess_t *sess;
395 errno_t rc;
396
397 sess = get_nic_by_index(i);
398 if (sess == NULL) {
399 printf("Specified NIC doesn't exist or cannot connect to it.\n");
400 return EINVAL;
401 }
402
403 rc = nic_autoneg_restart(sess);
404 if (rc != EOK) {
405 printf("Error restarting NIC autonegotiation.\n");
406 return EIO;
407 }
408
409 return EOK;
410}
411
412static errno_t nic_set_addr(int i, char *str)
413{
414 async_sess_t *sess;
415 nic_address_t addr;
416 errno_t rc;
417 int idx;
418
419 sess = get_nic_by_index(i);
420 if (sess == NULL) {
421 printf("Specified NIC doesn't exist or cannot connect to it.\n");
422 return EINVAL;
423 }
424
425 if (str_size(str) != 17) {
426 printf("Invalid MAC address specified");
427 return EINVAL;
428 }
429
430 for (idx = 0; idx < 6; idx++) {
431 rc = str_uint8_t(&str[idx * 3], NULL, 16, false, &addr.address[idx]);
432 if (rc != EOK) {
433 printf("Invalid MAC address specified");
434 return EINVAL;
435 }
436 }
437
438 return nic_set_address(sess, &addr);
439}
440
441static errno_t nic_set_rx_unicast(int i, char *str)
442{
443 async_sess_t *sess;
444
445 sess = get_nic_by_index(i);
446 if (sess == NULL) {
447 printf("Specified NIC doesn't exist or cannot connect to it.\n");
448 return EINVAL;
449 }
450
451 if (!str_cmp(str, "block")) {
452 nic_unicast_set_mode(sess, NIC_UNICAST_BLOCKED, NULL, 0);
453 return EOK;
454 }
455
456 if (!str_cmp(str, "default")) {
457 nic_unicast_set_mode(sess, NIC_UNICAST_DEFAULT, NULL, 0);
458 return EOK;
459 }
460
461 if (!str_cmp(str, "list")) {
462 nic_unicast_set_mode(sess, NIC_UNICAST_LIST, NULL, 0);
463 return EOK;
464 }
465
466 if (!str_cmp(str, "promisc")) {
467 nic_unicast_set_mode(sess, NIC_UNICAST_PROMISC, NULL, 0);
468 return EOK;
469 }
470
471
472 printf("Invalid pameter - should be one of: block, default, promisc\n");
473 return EINVAL;
474}
475
476static errno_t nic_set_rx_multicast(int i, char *str)
477{
478 async_sess_t *sess;
479
480 sess = get_nic_by_index(i);
481 if (sess == NULL) {
482 printf("Specified NIC doesn't exist or cannot connect to it.\n");
483 return EINVAL;
484 }
485
486 if (!str_cmp(str, "block")) {
487 nic_multicast_set_mode(sess, NIC_MULTICAST_BLOCKED, NULL, 0);
488 return EOK;
489 }
490
491 if (!str_cmp(str, "list")) {
492 nic_multicast_set_mode(sess, NIC_MULTICAST_LIST, NULL, 0);
493 return EOK;
494 }
495
496 if (!str_cmp(str, "promisc")) {
497 nic_multicast_set_mode(sess, NIC_MULTICAST_PROMISC, NULL, 0);
498 return EOK;
499 }
500
501 printf("Invalid pameter - should be one of: block, promisc\n");
502 return EINVAL;
503}
504
505static errno_t nic_set_rx_broadcast(int i, char *str)
506{
507 async_sess_t *sess;
508
509 sess = get_nic_by_index(i);
510 if (sess == NULL) {
511 printf("Specified NIC doesn't exist or cannot connect to it.\n");
512 return EINVAL;
513 }
514
515 if (!str_cmp(str, "block")) {
516 nic_broadcast_set_mode(sess, NIC_BROADCAST_BLOCKED);
517 return EOK;
518 }
519
520 if (!str_cmp(str, "accept")) {
521 nic_broadcast_set_mode(sess, NIC_BROADCAST_ACCEPTED);
522 return EOK;
523 }
524
525 printf("Invalid pameter - should be 'block' or 'accept'\n");
526 return EINVAL;
527}
528
529int main(int argc, char *argv[])
530{
531 errno_t rc;
532 uint32_t index;
533
534 if (argc == 1) {
535 rc = nic_list();
536 if (rc != EOK)
537 return 1;
538 } else if (argc >= 3) {
539 rc = str_uint32_t(argv[1], NULL, 10, false, &index);
540 if (rc != EOK) {
541 printf(NAME ": Invalid argument.\n");
542 print_syntax();
543 return 1;
544 }
545
546 if (!str_cmp(argv[2], "addr"))
547 return nic_set_addr(index, argv[3]);
548
549 if (!str_cmp(argv[2], "speed"))
550 return nic_set_speed(index, argv[3]);
551
552 if (!str_cmp(argv[2], "duplex"))
553 return nic_set_duplex(index, argv[3]);
554
555 if (!str_cmp(argv[2], "auto"))
556 return nic_set_autoneg(index);
557
558 if (!str_cmp(argv[2], "unicast"))
559 return nic_set_rx_unicast(index, argv[3]);
560
561 if (!str_cmp(argv[2], "multicast"))
562 return nic_set_rx_multicast(index, argv[3]);
563
564 if (!str_cmp(argv[2], "broadcast"))
565 return nic_set_rx_broadcast(index, argv[3]);
566
567 } else {
568 printf(NAME ": Invalid argument.\n");
569 print_syntax();
570 return 1;
571 }
572
573 return 0;
574}
575
576/** @}
577 */
Note: See TracBrowser for help on using the repository browser.