1 /*
2 * Copyright (c) 2014 Chris Anderson
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8
9 #include "minip-internal.h"
10
11 #include <lk/console_cmd.h>
12 #include <kernel/thread.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <platform.h>
17 #include <kernel/timer.h>
18 #include <lk/err.h>
19
str_ip_to_int(const char * s,size_t len)20 static uint32_t str_ip_to_int(const char *s, size_t len) {
21 uint8_t ip[4] = { 0, 0, 0, 0 };
22 uint8_t pos = 0, i = 0;
23
24 while (pos < len) {
25 char c = s[pos];
26 if (c == '.') {
27 i++;
28 } else {
29 ip[i] *= 10;
30 ip[i] += c - '0';
31 }
32 pos++;
33 }
34
35 return IPV4_PACK(ip);
36 }
37
arp_usage(void)38 static void arp_usage(void) {
39 printf("arp list print arp table\n");
40 printf("arp query <ipv4 address> query arp address\n");
41 }
42
cmd_arp(int argc,const console_cmd_args * argv)43 static int cmd_arp(int argc, const console_cmd_args *argv) {
44 if (argc == 1) {
45 arp_usage();
46 return -1;
47 }
48
49 const char *cmd = argv[1].str;
50 if (argc == 2 && strncmp(cmd, "list", sizeof("list")) == 0) {
51 arp_cache_dump();
52 } else if (argc == 3 && strncmp(cmd, "query", sizeof("query")) == 0) {
53 const char *addr_s = argv[2].str;
54 uint32_t addr = str_ip_to_int(addr_s, strlen(addr_s));
55
56 arp_send_request(addr);
57 } else {
58 arp_usage();
59 }
60
61 return 0;
62 }
63
cmd_minip(int argc,const console_cmd_args * argv)64 static int cmd_minip(int argc, const console_cmd_args *argv) {
65 if (argc == 1) {
66 minip_usage:
67 printf("minip commands\n");
68 printf("mi [a]rp dump arp table\n");
69 printf("mi [s]tatus print ip status\n");
70 printf("mi [t]est [dest] [port] [cnt] send <cnt> test packets to the dest:port\n");
71 } else {
72 switch (argv[1].str[0]) {
73
74 case 'a':
75 arp_cache_dump();
76 break;
77
78 case 's': {
79 printf("hostname: %s\n", minip_get_hostname());
80 printf("ip: %u.%u.%u.%u\n", IPV4_SPLIT(minip_get_ipaddr()));
81 printf("netmask: %u.%u.%u.%u\n", IPV4_SPLIT(minip_get_netmask()));
82 printf("broadcast: %u.%u.%u.%u\n", IPV4_SPLIT(minip_get_broadcast()));
83 printf("gateway: %u.%u.%u.%u\n", IPV4_SPLIT(minip_get_gateway()));
84 }
85 break;
86 case 't': {
87 uint32_t count = 1;
88 uint32_t host = 0x0100000A; // 10.0.0.1
89 uint32_t port = 1025;
90 udp_socket_t *handle;
91
92 switch (argc) {
93 case 5:
94 count = argv[4].u;
95 /* fallthrough */
96 case 4:
97 port = argv[3].u;
98 /* fallthrough */
99 case 3:
100 host = str_ip_to_int(argv[2].str, strlen(argv[2].str));
101 break;
102 }
103
104 if (udp_open(host, port, port, &handle) != NO_ERROR) {
105 printf("udp_open to %u.%u.%u.%u:%u failed\n", IPV4_SPLIT(host), port);
106 return -1;
107 }
108
109 #define BUFSIZE 1470
110 uint8_t *buf;
111
112 buf = malloc(BUFSIZE);
113 if (!buf) {
114 udp_close(handle);
115 return -1;
116 }
117
118 memset(buf, 0x00, BUFSIZE);
119 printf("sending %u packet(s) to %u.%u.%u.%u:%u\n", count, IPV4_SPLIT(host), port);
120
121 lk_bigtime_t t = current_time_hires();
122 uint32_t failures = 0;
123 for (uint32_t i = 0; i < count; i++) {
124 if (udp_send(buf, BUFSIZE, handle) != 0) {
125 failures++;
126 }
127 buf[128]++;
128 }
129 t = current_time_hires() - t;
130 if (t == 0)
131 t++;
132 printf("%d pkts failed\n", failures);
133 uint64_t total_count = (uint64_t)count * BUFSIZE;
134 printf("wrote %llu bytes in %u msecs (%llu bytes/sec)\n",
135 total_count, (uint32_t)t, total_count * 1000000 / t);
136
137 free(buf);
138 udp_close(handle);
139 #undef BUFSIZE
140 }
141 break;
142 default:
143 goto minip_usage;
144 }
145 }
146
147 return 0;
148 }
149
150 STATIC_COMMAND_START
151 STATIC_COMMAND("arp", "arp commands", &cmd_arp)
152 STATIC_COMMAND("mi", "minip commands", &cmd_minip)
153 STATIC_COMMAND_END(minip);
154