1 1.14 kefren /* $NetBSD: ldp_command.c,v 1.14 2013/08/02 07:29:56 kefren Exp $ */ 2 1.1 kefren 3 1.1 kefren /*- 4 1.1 kefren * Copyright (c) 2010 The NetBSD Foundation, Inc. 5 1.1 kefren * All rights reserved. 6 1.1 kefren * 7 1.1 kefren * This code is derived from software contributed to The NetBSD Foundation 8 1.1 kefren * by Mihai Chelaru <kefren (at) NetBSD.org> 9 1.1 kefren * 10 1.1 kefren * Redistribution and use in source and binary forms, with or without 11 1.1 kefren * modification, are permitted provided that the following conditions 12 1.1 kefren * are met: 13 1.1 kefren * 1. Redistributions of source code must retain the above copyright 14 1.1 kefren * notice, this list of conditions and the following disclaimer. 15 1.1 kefren * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 kefren * notice, this list of conditions and the following disclaimer in the 17 1.1 kefren * documentation and/or other materials provided with the distribution. 18 1.1 kefren * 19 1.1 kefren * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 kefren * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 kefren * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 kefren * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 kefren * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 kefren * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 kefren * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 kefren * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 kefren * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 kefren * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 kefren * POSSIBILITY OF SUCH DAMAGE. 30 1.1 kefren */ 31 1.1 kefren 32 1.1 kefren #include <arpa/inet.h> 33 1.1 kefren 34 1.1 kefren #include <netinet/in.h> 35 1.4 kefren #include <netinet/tcp.h> 36 1.1 kefren 37 1.1 kefren #include <sys/socket.h> 38 1.1 kefren #include <sys/queue.h> 39 1.1 kefren 40 1.1 kefren #include <errno.h> 41 1.1 kefren #include <pwd.h> 42 1.1 kefren #include <stdio.h> 43 1.1 kefren #include <stdlib.h> 44 1.1 kefren #include <string.h> 45 1.1 kefren #include <unistd.h> 46 1.1 kefren 47 1.1 kefren #include "label.h" 48 1.1 kefren #include "ldp.h" 49 1.1 kefren #include "ldp_command.h" 50 1.1 kefren #include "ldp_errors.h" 51 1.1 kefren #include "ldp_peer.h" 52 1.1 kefren #include "socketops.h" 53 1.1 kefren 54 1.1 kefren struct com_sock csockets[MAX_COMMAND_SOCKETS]; 55 1.3 kefren extern int ldp_hello_time, ldp_keepalive_time, ldp_holddown_time, 56 1.3 kefren min_label, max_label, debug_f, warn_f; 57 1.1 kefren 58 1.1 kefren #define writestr(soc, str) write(soc, str, strlen(str)) 59 1.1 kefren 60 1.1 kefren #define MAXSEND 1024 61 1.1 kefren char sendspace[MAXSEND]; 62 1.1 kefren 63 1.5 kefren static void send_prompt(int); 64 1.5 kefren static void send_pwd_prompt(int); 65 1.5 kefren static int command_match(struct com_func*, int, char*, char*); 66 1.5 kefren 67 1.1 kefren static int verify_root_pwd(char *); 68 1.1 kefren static void echo_on(int s); 69 1.1 kefren static void echo_off(int s); 70 1.1 kefren 71 1.5 kefren /* Main functions */ 72 1.5 kefren static int show_func(int, char *); 73 1.5 kefren static int set_func(int, char *); 74 1.5 kefren static int exit_func(int, char *); 75 1.5 kefren 76 1.5 kefren /* Show functions */ 77 1.5 kefren static int show_debug(int, char *); 78 1.5 kefren static int show_hellos(int, char *); 79 1.5 kefren static int show_parameters(int, char *); 80 1.5 kefren static int show_version(int, char *); 81 1.5 kefren static int show_warning(int, char *); 82 1.5 kefren 83 1.5 kefren /* Set functions */ 84 1.5 kefren static int set_hello_time(int, char *); 85 1.5 kefren static int set_debug(int, char *); 86 1.5 kefren static int set_warning(int, char *); 87 1.5 kefren 88 1.3 kefren static struct com_func main_commands[] = { 89 1.1 kefren { "show", show_func }, 90 1.1 kefren { "set", set_func }, 91 1.1 kefren { "quit", exit_func }, 92 1.1 kefren { "exit", exit_func }, 93 1.1 kefren { "", NULL } 94 1.1 kefren }; 95 1.1 kefren 96 1.3 kefren static struct com_func show_commands[] = { 97 1.1 kefren { "neighbours", show_neighbours }, 98 1.1 kefren { "bindings", show_bindings }, 99 1.1 kefren { "debug", show_debug }, 100 1.1 kefren { "hellos", show_hellos }, 101 1.5 kefren { "labels", show_labels }, 102 1.1 kefren { "parameters", show_parameters }, 103 1.1 kefren { "version", show_version }, 104 1.1 kefren { "warning", show_warning }, 105 1.1 kefren { "", NULL } 106 1.1 kefren }; 107 1.1 kefren 108 1.1 kefren struct com_func set_commands[] = { 109 1.1 kefren { "debug", set_debug }, 110 1.1 kefren { "hello-time", set_hello_time }, 111 1.1 kefren { "warning", set_warning }, 112 1.1 kefren { "", NULL } 113 1.1 kefren }; 114 1.1 kefren 115 1.5 kefren static int 116 1.1 kefren verify_root_pwd(char *pw) 117 1.1 kefren { 118 1.1 kefren struct passwd *p; 119 1.1 kefren 120 1.1 kefren if ((p = getpwuid(0)) == NULL) 121 1.1 kefren return 0; 122 1.1 kefren 123 1.1 kefren if (strcmp(crypt(pw, p->pw_passwd), p->pw_passwd)) 124 1.1 kefren return 0; 125 1.1 kefren 126 1.1 kefren return 1; 127 1.1 kefren } 128 1.1 kefren 129 1.1 kefren 130 1.1 kefren void 131 1.1 kefren init_command_sockets() 132 1.1 kefren { 133 1.1 kefren int i; 134 1.1 kefren 135 1.1 kefren for (i = 0; i<MAX_COMMAND_SOCKETS; i++) { 136 1.1 kefren csockets[i].socket = -1; 137 1.1 kefren csockets[i].auth = 0; 138 1.1 kefren } 139 1.1 kefren } 140 1.1 kefren 141 1.1 kefren int 142 1.1 kefren create_command_socket(int port) 143 1.1 kefren { 144 1.1 kefren struct sockaddr_in sin; 145 1.1 kefren int s; 146 1.1 kefren 147 1.1 kefren sin.sin_len = sizeof(sin); 148 1.1 kefren sin.sin_family = AF_INET; 149 1.1 kefren sin.sin_port = htons(port); 150 1.1 kefren sin.sin_addr.s_addr = ntohl(INADDR_LOOPBACK); 151 1.1 kefren 152 1.1 kefren s = socket(PF_INET, SOCK_STREAM, 6); 153 1.1 kefren if (s < 0) 154 1.1 kefren return s; 155 1.1 kefren 156 1.1 kefren if (bind(s, (struct sockaddr *) &sin, sizeof(sin))) { 157 1.1 kefren fatalp("bind: %s", strerror(errno)); 158 1.1 kefren close(s); 159 1.1 kefren return -1; 160 1.1 kefren } 161 1.1 kefren 162 1.1 kefren if (listen(s, 5) == -1) { 163 1.1 kefren fatalp("listen: %s", strerror(errno)); 164 1.1 kefren close(s); 165 1.1 kefren return -1; 166 1.1 kefren } 167 1.8 kefren debugp("Command socket created (%d)\n", s); 168 1.1 kefren return s; 169 1.1 kefren } 170 1.1 kefren 171 1.1 kefren void 172 1.1 kefren command_accept(int s) 173 1.1 kefren { 174 1.1 kefren int as = accept(s, NULL, 0); 175 1.1 kefren 176 1.1 kefren if (as < 0) { 177 1.1 kefren fatalp("Cannot accept new command socket %s", 178 1.1 kefren strerror(errno)); 179 1.1 kefren return; 180 1.1 kefren } 181 1.1 kefren 182 1.1 kefren if (add_command_socket(as) != 0) { 183 1.1 kefren fatalp("Cannot accept command. Too many connections\n"); 184 1.1 kefren close(as); 185 1.1 kefren return; 186 1.1 kefren } 187 1.1 kefren 188 1.1 kefren /* auth */ 189 1.1 kefren send_pwd_prompt(as); 190 1.1 kefren } 191 1.1 kefren 192 1.1 kefren struct com_sock * 193 1.1 kefren is_command_socket(int s) 194 1.1 kefren { 195 1.1 kefren int i; 196 1.1 kefren 197 1.1 kefren if (s == -1) 198 1.1 kefren return NULL; 199 1.1 kefren for (i=0; i<MAX_COMMAND_SOCKETS; i++) 200 1.1 kefren if (s == csockets[i].socket) 201 1.1 kefren return &csockets[i]; 202 1.1 kefren return NULL; 203 1.1 kefren } 204 1.1 kefren 205 1.1 kefren int 206 1.1 kefren add_command_socket(int s) 207 1.1 kefren { 208 1.1 kefren int i; 209 1.1 kefren 210 1.1 kefren for (i=0; i<MAX_COMMAND_SOCKETS; i++) 211 1.1 kefren if (csockets[i].socket == -1) { 212 1.1 kefren csockets[i].socket = s; 213 1.1 kefren csockets[i].auth = 0; 214 1.1 kefren return 0; 215 1.1 kefren } 216 1.1 kefren return -1; 217 1.1 kefren } 218 1.1 kefren 219 1.1 kefren void 220 1.1 kefren command_dispatch(struct com_sock *cs) 221 1.1 kefren { 222 1.1 kefren char recvspace[MAX_COMMAND_SIZE + 1]; 223 1.1 kefren char *nextc = recvspace; 224 1.1 kefren int r = recv(cs->socket, recvspace, MAX_COMMAND_SIZE, MSG_PEEK); 225 1.1 kefren 226 1.1 kefren if (r < 0) { 227 1.1 kefren command_close(cs->socket); 228 1.1 kefren return; 229 1.1 kefren } 230 1.1 kefren 231 1.1 kefren recv(cs->socket, recvspace, r, MSG_WAITALL); 232 1.1 kefren 233 1.1 kefren if (r < 3) { /*at least \r\n */ 234 1.1 kefren if (cs->auth) { 235 1.1 kefren /*writestr(cs->socket, "Unknown command. Use ? for help\n");*/ 236 1.1 kefren send_prompt(cs->socket); 237 1.1 kefren } else { 238 1.1 kefren writestr(cs->socket, "Bad password\n"); 239 1.1 kefren command_close(cs->socket); 240 1.1 kefren } 241 1.1 kefren return; 242 1.1 kefren } 243 1.1 kefren 244 1.1 kefren recvspace[r - 2] = '\0'; 245 1.1 kefren 246 1.1 kefren if (!cs->auth) { 247 1.1 kefren if (verify_root_pwd(recvspace)) { 248 1.1 kefren echo_on(cs->socket); 249 1.1 kefren cs->auth = 1; 250 1.1 kefren writestr(cs->socket, "\n"); 251 1.1 kefren send_prompt(cs->socket); 252 1.1 kefren } else { 253 1.1 kefren echo_on(cs->socket); 254 1.1 kefren writestr(cs->socket, "Bad password\n"); 255 1.1 kefren command_close(cs->socket); 256 1.1 kefren } 257 1.1 kefren return; 258 1.1 kefren } 259 1.1 kefren 260 1.1 kefren strsep(&nextc, " "); 261 1.1 kefren 262 1.1 kefren command_match(main_commands, cs->socket, recvspace, nextc); 263 1.1 kefren 264 1.1 kefren } 265 1.1 kefren 266 1.1 kefren void 267 1.1 kefren command_close(int s) 268 1.1 kefren { 269 1.1 kefren int i; 270 1.1 kefren 271 1.1 kefren for (i=0; i<MAX_COMMAND_SOCKETS; i++) 272 1.1 kefren if (s == csockets[i].socket) { 273 1.1 kefren close(s); 274 1.1 kefren csockets[i].socket = -1; 275 1.1 kefren csockets[i].auth = 0; 276 1.1 kefren break; 277 1.1 kefren } 278 1.1 kefren } 279 1.1 kefren 280 1.5 kefren static void 281 1.1 kefren send_prompt(int s) { 282 1.1 kefren writestr(s, "LDP> "); 283 1.1 kefren } 284 1.1 kefren 285 1.5 kefren static void 286 1.1 kefren send_pwd_prompt(int s) { 287 1.1 kefren echo_off(s); 288 1.1 kefren writestr(s, "Password: "); 289 1.1 kefren } 290 1.1 kefren 291 1.5 kefren static void 292 1.5 kefren echo_off(int s) 293 1.1 kefren { 294 1.1 kefren char iac_will_echo[3] = { 0xff, 0xfb, 0x01 }, bf[32]; 295 1.1 kefren write(s, iac_will_echo, sizeof(iac_will_echo)); 296 1.1 kefren read(s, bf, sizeof(bf)); 297 1.1 kefren } 298 1.1 kefren 299 1.5 kefren static void 300 1.5 kefren echo_on(int s) 301 1.1 kefren { 302 1.1 kefren char iac_wont_echo[3] = { 0xff, 0xfc, 0x01 }, bf[32]; 303 1.1 kefren write(s, iac_wont_echo, sizeof(iac_wont_echo)); 304 1.1 kefren read(s, bf, sizeof(bf)); 305 1.1 kefren } 306 1.1 kefren 307 1.1 kefren /* 308 1.1 kefren * Matching function 309 1.1 kefren * Returns 1 if matched anything 310 1.1 kefren */ 311 1.5 kefren static int 312 1.1 kefren command_match(struct com_func *cf, int s, char *orig, char *next) 313 1.1 kefren { 314 1.2 christos size_t i, len; 315 1.2 christos int last_match = -1; 316 1.2 christos const char *msg = NULL; 317 1.1 kefren 318 1.2 christos if (orig == NULL || orig[0] == '\0') 319 1.2 christos goto out; 320 1.1 kefren 321 1.1 kefren if (!strcmp(orig, "?")) { 322 1.2 christos for (i = 0; cf[i].func != NULL; i++) { 323 1.1 kefren snprintf(sendspace, MAXSEND, "\t%s\n", cf[i].com); 324 1.1 kefren writestr(s, sendspace); 325 1.1 kefren } 326 1.2 christos goto out; 327 1.1 kefren } 328 1.1 kefren 329 1.2 christos len = strlen(orig); 330 1.2 christos for (i = 0; cf[i].func != NULL; i++) { 331 1.2 christos if (strncasecmp(orig, cf[i].com, len) == 0) { 332 1.2 christos if (last_match != -1) { 333 1.2 christos msg = "Ambiguous"; 334 1.2 christos goto out; 335 1.2 christos } else 336 1.2 christos last_match = i; 337 1.1 kefren } 338 1.1 kefren } 339 1.1 kefren 340 1.2 christos if (last_match == -1) { 341 1.2 christos msg = "Unknown"; 342 1.2 christos goto out; 343 1.1 kefren } 344 1.1 kefren 345 1.2 christos if (cf[last_match].func(s, next) != 0) 346 1.1 kefren send_prompt(s); 347 1.1 kefren return 1; 348 1.2 christos out: 349 1.2 christos if (msg) { 350 1.2 christos writestr(s, msg); 351 1.2 christos writestr(s, " command. Use ? for help\n"); 352 1.2 christos } 353 1.2 christos send_prompt(s); 354 1.2 christos return 0; 355 1.1 kefren } 356 1.1 kefren 357 1.1 kefren /* 358 1.1 kefren * Main CLI functions 359 1.1 kefren */ 360 1.5 kefren static int 361 1.1 kefren set_func(int s, char *recvspace) 362 1.1 kefren { 363 1.1 kefren char *nextc = recvspace; 364 1.1 kefren 365 1.1 kefren if (recvspace == NULL || recvspace[0] == '\0') { 366 1.1 kefren writestr(s, "Unknown set command. Use set ? for help\n"); 367 1.1 kefren return 1; 368 1.1 kefren } 369 1.1 kefren 370 1.1 kefren strsep(&nextc, " "); 371 1.1 kefren 372 1.1 kefren command_match(set_commands, s, recvspace, nextc); 373 1.1 kefren return 0; 374 1.1 kefren } 375 1.1 kefren 376 1.5 kefren static int 377 1.1 kefren show_func(int s, char *recvspace) 378 1.1 kefren { 379 1.1 kefren char *nextc = recvspace; 380 1.1 kefren 381 1.1 kefren if (recvspace == NULL || recvspace[0] == '\0') { 382 1.1 kefren writestr(s, "Unknown show command. Use show ? for help\n"); 383 1.1 kefren return 1; 384 1.1 kefren } 385 1.1 kefren 386 1.1 kefren strsep(&nextc, " "); 387 1.1 kefren 388 1.1 kefren command_match(show_commands, s, recvspace, nextc); 389 1.1 kefren return 0; 390 1.1 kefren } 391 1.1 kefren 392 1.5 kefren static int 393 1.1 kefren exit_func(int s, char *recvspace) 394 1.1 kefren { 395 1.1 kefren command_close(s); 396 1.1 kefren return 0; 397 1.1 kefren } 398 1.1 kefren 399 1.1 kefren /* 400 1.1 kefren * Show functions 401 1.1 kefren */ 402 1.12 kefren int 403 1.1 kefren show_neighbours(int s, char *recvspace) 404 1.1 kefren { 405 1.1 kefren struct ldp_peer *p; 406 1.1 kefren struct ldp_peer_address *wp; 407 1.1 kefren struct sockaddr_in ssin; 408 1.1 kefren socklen_t sin_len = sizeof(struct sockaddr_in); 409 1.4 kefren int enc; 410 1.4 kefren socklen_t enclen = sizeof(enc); 411 1.1 kefren 412 1.1 kefren SLIST_FOREACH(p, &ldp_peer_head, peers) { 413 1.1 kefren snprintf(sendspace, MAXSEND, "LDP peer: %s\n", 414 1.1 kefren inet_ntoa(p->ldp_id)); 415 1.1 kefren writestr(s, sendspace); 416 1.1 kefren snprintf(sendspace, MAXSEND, "Transport address: %s\n", 417 1.10 kefren satos(p->transport_address)); 418 1.1 kefren writestr(s, sendspace); 419 1.1 kefren snprintf(sendspace, MAXSEND, "Next-hop address: %s\n", 420 1.10 kefren satos(p->address)); 421 1.1 kefren writestr(s, sendspace); 422 1.1 kefren snprintf(sendspace, MAXSEND, "State: %s\n", 423 1.1 kefren ldp_state_to_name(p->state)); 424 1.1 kefren writestr(s, sendspace); 425 1.1 kefren if (p->state == LDP_PEER_ESTABLISHED) { 426 1.1 kefren snprintf(sendspace, MAXSEND, "Since: %s", 427 1.1 kefren ctime(&p->established_t)); 428 1.1 kefren writestr(s, sendspace); 429 1.1 kefren } 430 1.1 kefren snprintf(sendspace, MAXSEND, "Holdtime: %d\nTimeout: %d\n", 431 1.1 kefren p->holdtime, p->timeout); 432 1.1 kefren writestr(s, sendspace); 433 1.1 kefren 434 1.1 kefren switch(p->state) { 435 1.1 kefren case LDP_PEER_CONNECTING: 436 1.1 kefren case LDP_PEER_CONNECTED: 437 1.1 kefren case LDP_PEER_ESTABLISHED: 438 1.1 kefren if (getsockname(p->socket,(struct sockaddr *) &ssin, 439 1.1 kefren &sin_len)) 440 1.1 kefren break; 441 1.4 kefren 442 1.4 kefren if (getsockopt(p->socket, IPPROTO_TCP, TCP_MD5SIG, 443 1.4 kefren &enc, &enclen) == 0) { 444 1.4 kefren snprintf(sendspace, MAXSEND, 445 1.4 kefren "Authenticated: %s\n", 446 1.4 kefren enc != 0 ? "YES" : "NO"); 447 1.4 kefren writestr(s, sendspace); 448 1.4 kefren } 449 1.4 kefren 450 1.1 kefren snprintf(sendspace, MAXSEND,"Socket: %d\nLocal %s:%d\n", 451 1.1 kefren p->socket, inet_ntoa(ssin.sin_addr), 452 1.1 kefren ntohs(ssin.sin_port)); 453 1.1 kefren writestr(s, sendspace); 454 1.1 kefren 455 1.1 kefren if (getpeername(p->socket,(struct sockaddr *) &ssin, 456 1.1 kefren &sin_len)) 457 1.1 kefren break; 458 1.1 kefren snprintf(sendspace, MAXSEND, "Remote %s:%d\n", 459 1.1 kefren inet_ntoa(ssin.sin_addr), ntohs(ssin.sin_port)); 460 1.1 kefren writestr(s, sendspace); 461 1.1 kefren } 462 1.1 kefren 463 1.1 kefren snprintf(sendspace, MAXSEND,"Addresses bounded to this peer: "); 464 1.1 kefren writestr(s, sendspace); 465 1.1 kefren SLIST_FOREACH(wp, &p->ldp_peer_address_head, addresses) { 466 1.8 kefren /* XXX: TODO */ 467 1.8 kefren if (wp->address.sa.sa_family != AF_INET) 468 1.8 kefren continue; 469 1.1 kefren snprintf(sendspace, MAXSEND, "%s ", 470 1.8 kefren inet_ntoa(wp->address.sin.sin_addr)); 471 1.1 kefren writestr(s, sendspace); 472 1.1 kefren } 473 1.1 kefren sendspace[0] = sendspace[1] = '\n'; 474 1.1 kefren write(s, sendspace, 2); 475 1.1 kefren } 476 1.1 kefren return 1; 477 1.1 kefren } 478 1.1 kefren 479 1.5 kefren /* Shows labels grabbed from unsolicited label maps */ 480 1.12 kefren int 481 1.5 kefren show_labels(int s, char *recvspace) 482 1.5 kefren { 483 1.5 kefren struct ldp_peer *p; 484 1.14 kefren struct label_mapping *lm = NULL; 485 1.5 kefren 486 1.5 kefren SLIST_FOREACH(p, &ldp_peer_head, peers) { 487 1.5 kefren if (p->state != LDP_PEER_ESTABLISHED) 488 1.5 kefren continue; 489 1.14 kefren while ((lm = ldp_peer_lm_right(p, lm)) != NULL) { 490 1.7 christos char lma[256]; 491 1.8 kefren /* XXX: TODO */ 492 1.8 kefren if (lm->address.sa.sa_family != AF_INET) 493 1.8 kefren continue; 494 1.8 kefren strlcpy(lma, inet_ntoa(lm->address.sin.sin_addr), 495 1.8 kefren sizeof(lma)); 496 1.6 christos snprintf(sendspace, MAXSEND, "%s:%d\t%s/%d\n", 497 1.7 christos inet_ntoa(p->ldp_id), lm->label, lma, lm->prefix); 498 1.5 kefren writestr(s, sendspace); 499 1.5 kefren } 500 1.5 kefren } 501 1.5 kefren return 1; 502 1.5 kefren } 503 1.5 kefren 504 1.12 kefren int 505 1.1 kefren show_bindings(int s, char *recvspace) 506 1.1 kefren { 507 1.13 kefren struct label *l = NULL; 508 1.1 kefren 509 1.1 kefren snprintf(sendspace, MAXSEND, "Local label\tNetwork\t\t\t\tNexthop\n"); 510 1.1 kefren writestr(s, sendspace); 511 1.13 kefren while((l = label_get_right(l)) != NULL) { 512 1.1 kefren snprintf(sendspace, MAXSEND, "%d\t\t%s/", l->binding, 513 1.11 kefren satos(&l->so_dest.sa)); 514 1.1 kefren writestr(s, sendspace); 515 1.11 kefren snprintf(sendspace, MAXSEND, "%s", satos(&l->so_pref.sa)); 516 1.1 kefren writestr(s, sendspace); 517 1.10 kefren if (l->p) 518 1.1 kefren snprintf(sendspace, MAXSEND, "\t%s:%d\n", 519 1.10 kefren satos(l->p->address), l->label); 520 1.10 kefren else 521 1.1 kefren snprintf(sendspace, MAXSEND, "\n"); 522 1.1 kefren writestr(s, sendspace); 523 1.1 kefren } 524 1.1 kefren return 1; 525 1.1 kefren } 526 1.1 kefren 527 1.5 kefren static int 528 1.1 kefren show_debug(int s, char *recvspace) 529 1.1 kefren { 530 1.1 kefren if (recvspace) { 531 1.1 kefren writestr(s, "Invalid command\n"); 532 1.1 kefren return 1; 533 1.1 kefren } 534 1.1 kefren 535 1.1 kefren snprintf(sendspace, MAXSEND, "Debug: %s\n", 536 1.1 kefren debug_f ? "YES" : "NO"); 537 1.1 kefren writestr(s, sendspace); 538 1.1 kefren return 1; 539 1.1 kefren } 540 1.1 kefren 541 1.5 kefren static int 542 1.1 kefren show_hellos(int s, char *recvspace) 543 1.1 kefren { 544 1.1 kefren struct hello_info *hi; 545 1.1 kefren 546 1.1 kefren SLIST_FOREACH(hi, &hello_info_head, infos) { 547 1.9 kefren snprintf(sendspace, MAXSEND, 548 1.9 kefren "ID: %s\nKeepalive: %ds\nTransport address: %s\n\n", 549 1.9 kefren inet_ntoa(hi->ldp_id), 550 1.9 kefren hi->keepalive, 551 1.9 kefren hi->transport_address.sa.sa_family != 0 ? 552 1.9 kefren satos(&hi->transport_address.sa) : "None"); 553 1.1 kefren writestr(s, sendspace); 554 1.1 kefren } 555 1.1 kefren return 1; 556 1.1 kefren } 557 1.1 kefren 558 1.5 kefren static int 559 1.1 kefren show_parameters(int s, char *recvspace) 560 1.1 kefren { 561 1.1 kefren snprintf(sendspace, MAXSEND, "LDP ID: %s\nProtocol version: %d\n" 562 1.1 kefren "Hello time: %d\nKeepalive time: %d\nHoldtime: %d\n" 563 1.1 kefren "Minimum label: %d\nMaximum label: %d\n", 564 1.1 kefren my_ldp_id, 565 1.1 kefren LDP_VERSION, 566 1.1 kefren ldp_hello_time, 567 1.3 kefren ldp_keepalive_time, 568 1.3 kefren ldp_holddown_time, 569 1.3 kefren min_label, 570 1.3 kefren max_label); 571 1.1 kefren writestr(s, sendspace); 572 1.1 kefren return 1; 573 1.1 kefren } 574 1.1 kefren 575 1.5 kefren static int 576 1.1 kefren show_version(int s, char *recvspace) 577 1.1 kefren { 578 1.1 kefren if (recvspace) { /* Nothing more after this */ 579 1.1 kefren writestr(s, "Invalid command\n"); 580 1.1 kefren return 1; 581 1.1 kefren } 582 1.1 kefren 583 1.1 kefren snprintf(sendspace, MAXSEND, "NetBSD LDP daemon version: %s\n", 584 1.1 kefren LDPD_VER); 585 1.1 kefren writestr(s, sendspace); 586 1.1 kefren return 1; 587 1.1 kefren } 588 1.1 kefren 589 1.5 kefren static int 590 1.1 kefren show_warning(int s, char *recvspace) 591 1.1 kefren { 592 1.1 kefren if (recvspace) { 593 1.1 kefren writestr(s, "Invalid command\n"); 594 1.1 kefren return 1; 595 1.1 kefren } 596 1.1 kefren 597 1.1 kefren snprintf(sendspace, MAXSEND, "Warnings: %s\n", 598 1.1 kefren warn_f ? "YES" : "NO"); 599 1.1 kefren writestr(s, sendspace); 600 1.1 kefren return 1; 601 1.1 kefren } 602 1.1 kefren 603 1.1 kefren /* Set commands */ 604 1.5 kefren static int 605 1.1 kefren set_hello_time(int s, char *recvspace) 606 1.1 kefren { 607 1.1 kefren if (!recvspace || atoi(recvspace) < 1) { 608 1.1 kefren writestr(s, "Invalid timeout\n"); 609 1.1 kefren return 1; 610 1.1 kefren } 611 1.1 kefren 612 1.1 kefren ldp_hello_time = atoi(recvspace); 613 1.1 kefren return 1; 614 1.1 kefren } 615 1.1 kefren 616 1.5 kefren static int 617 1.1 kefren set_debug(int s, char *recvspace) 618 1.1 kefren { 619 1.1 kefren if (!recvspace || atoi(recvspace) < 0) { 620 1.1 kefren writestr(s, "Invalid command\n"); 621 1.1 kefren return 1; 622 1.1 kefren } 623 1.1 kefren 624 1.1 kefren debug_f = atoi(recvspace); 625 1.1 kefren return 1; 626 1.1 kefren } 627 1.1 kefren 628 1.5 kefren static int 629 1.1 kefren set_warning(int s, char *recvspace) 630 1.1 kefren { 631 1.1 kefren if (!recvspace || atoi(recvspace) < 0) { 632 1.1 kefren writestr(s, "Invalid command\n"); 633 1.1 kefren return 1; 634 1.1 kefren } 635 1.1 kefren 636 1.1 kefren warn_f = atoi(recvspace); 637 1.1 kefren return 1; 638 1.1 kefren } 639