blob: 227c2278b7ec82f4c18f95f41727ad9aa1274531 [file] [log] [blame]
Jérôme Poichet402e1062017-03-17 16:41:43 -07001// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#define _POSIX_C_SOURCE 200809L
6
7#define _GNU_SOURCE
8#define _DARWIN_C_SOURCE
9
10#include <errno.h>
11#include <fcntl.h>
12#include <netinet/in.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <sys/time.h>
17
18#include "netprotocol.h"
19
20#define MAX_DEVICES 255
21
22static device_info_t devices[MAX_DEVICES];
23static uint32_t devices_count = 0;
24
Erik Gilling6a845582017-04-05 11:31:20 -070025static const char* appname;
26
Jérôme Poichet402e1062017-03-17 16:41:43 -070027static bool has_device(const char* nodename) {
Roland McGrath29b10dc2019-08-06 23:34:54 +000028 for (uint32_t i = 0; i < devices_count; ++i) {
29 if (!strncmp(devices[i].nodename, nodename, sizeof(devices[i].nodename))) {
30 return true;
Jérôme Poichet402e1062017-03-17 16:41:43 -070031 }
Roland McGrath29b10dc2019-08-06 23:34:54 +000032 }
33 return false;
Jérôme Poichet402e1062017-03-17 16:41:43 -070034}
35
36static device_info_t* get_device(const char* nodename) {
Roland McGrath29b10dc2019-08-06 23:34:54 +000037 for (uint32_t i = 0; i < devices_count; ++i) {
38 if (!strncmp(devices[i].nodename, nodename, sizeof(devices[i].nodename))) {
39 return &devices[i];
Jérôme Poichet402e1062017-03-17 16:41:43 -070040 }
Roland McGrath29b10dc2019-08-06 23:34:54 +000041 }
42 return NULL;
Jérôme Poichet402e1062017-03-17 16:41:43 -070043}
44
45static device_info_t* add_device(device_info_t* device) {
Roland McGrath29b10dc2019-08-06 23:34:54 +000046 device_info_t* known_device = get_device(device->nodename);
47 if (!known_device) {
48 if (devices_count > MAX_DEVICES) {
49 return NULL;
Jérôme Poichet402e1062017-03-17 16:41:43 -070050 }
Roland McGrath29b10dc2019-08-06 23:34:54 +000051 known_device = &devices[devices_count];
52 devices_count++;
53 strncpy(known_device->nodename, device->nodename, sizeof(known_device->nodename));
54 }
55 strncpy(known_device->inet6_addr_s, device->inet6_addr_s, INET6_ADDRSTRLEN);
56 memcpy(&known_device->inet6_addr, &device->inet6_addr, sizeof(known_device->inet6_addr));
57 known_device->state = device->state;
58 known_device->bootloader_port = device->bootloader_port;
59 known_device->bootloader_version = device->bootloader_version;
60 return known_device;
Jérôme Poichet402e1062017-03-17 16:41:43 -070061}
62
63static bool on_device(device_info_t* device, void* cookie) {
Roland McGrath29b10dc2019-08-06 23:34:54 +000064 if (!has_device(device->nodename)) {
65 if (device->state == UNKNOWN) {
66 device->state = OFFLINE;
Jérôme Poichet402e1062017-03-17 16:41:43 -070067 }
Roland McGrath29b10dc2019-08-06 23:34:54 +000068 const char* state = "unknown";
69 switch (device->state) {
70 case UNKNOWN:
71 state = "unknown";
72 break;
73 case OFFLINE:
74 state = "offline";
75 break;
76 case DEVICE:
77 state = "device";
78 break;
79 case BOOTLOADER:
80 state = "bootloader";
81 break;
82 }
83
84 // TODO(jimbe): Print the type of the device based on the vendor id of the mac address.
85 fprintf(stdout, "%10s %s", state, device->nodename);
86 if (device->inet6_addr.sin6_scope_id != 0) {
87 fprintf(stdout, " (%s/%d)", device->inet6_addr_s, device->inet6_addr.sin6_scope_id);
88 }
89 if (device->state == BOOTLOADER) {
90 fprintf(stdout, " [Bootloader version 0x%08X listening on %d]", device->bootloader_version,
91 device->bootloader_port);
92 }
93 fprintf(stdout, "\n");
94 if (add_device(device) == NULL) {
95 return false;
96 }
97 }
98 return true;
Jérôme Poichet402e1062017-03-17 16:41:43 -070099}
100
Erik Gilling6a845582017-04-05 11:31:20 -0700101static void usage(void) {
Roland McGrath29b10dc2019-08-06 23:34:54 +0000102 fprintf(stderr, "usage: %s [options]\n", appname);
103 netboot_usage(false);
Erik Gilling6a845582017-04-05 11:31:20 -0700104}
105
Jérôme Poichet402e1062017-03-17 16:41:43 -0700106int main(int argc, char** argv) {
Roland McGrath29b10dc2019-08-06 23:34:54 +0000107 appname = argv[0];
108 int index = netboot_handle_getopt(argc, argv);
109 if (index < 0) {
110 usage();
111 return -1;
112 }
Erik Gilling6a845582017-04-05 11:31:20 -0700113
Joshua Seaton858c5122023-04-02 01:32:44 +0000114 if (netboot_discover(NETBOOT_PORT_SERVER, NULL, on_device, NULL)) {
Roland McGrath29b10dc2019-08-06 23:34:54 +0000115 fprintf(stderr, "Failed to discover\n");
116 return 1;
117 }
118 return 0;
Jérôme Poichet402e1062017-03-17 16:41:43 -0700119}