1 /* $OpenBSD: ldpctl.c,v 1.5 2009/09/14 11:49:25 claudio Exp $ 2 * 3 * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> 4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 5 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 6 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/types.h> 22 #include <sys/socket.h> 23 #include <sys/un.h> 24 #include <netinet/in.h> 25 #include <arpa/inet.h> 26 #include <net/if_media.h> 27 #include <net/if_types.h> 28 #include <netmpls/mpls.h> 29 30 #include <err.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <unistd.h> 35 36 #include "ldp.h" 37 #include "ldpd.h" 38 #include "ldpe.h" 39 #include "parser.h" 40 41 __dead void usage(void); 42 const char *fmt_timeframe_core(time_t); 43 const char *get_linkstate(int, int); 44 int show_interface_msg(struct imsg *); 45 int get_ifms_type(int); 46 int show_lib_msg(struct imsg *); 47 int show_nbr_msg(struct imsg *); 48 void show_lfib_head(void); 49 int show_lfib_msg(struct imsg *); 50 void show_interface_head(void); 51 int show_lfib_interface_msg(struct imsg *); 52 const char *get_media_descr(int); 53 void print_baudrate(u_int64_t); 54 55 struct imsgbuf *ibuf; 56 57 __dead void 58 usage(void) 59 { 60 extern char *__progname; 61 62 fprintf(stderr, "usage: %s command [argument ...]\n", __progname); 63 exit(1); 64 } 65 66 int 67 main(int argc, char *argv[]) 68 { 69 struct sockaddr_un sun; 70 struct parse_result *res; 71 struct imsg imsg; 72 unsigned int ifidx = 0; 73 int ctl_sock; 74 int done = 0; 75 int n; 76 77 /* parse options */ 78 if ((res = parse(argc - 1, argv + 1)) == NULL) 79 exit(1); 80 81 /* connect to ldpd control socket */ 82 if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 83 err(1, "socket"); 84 85 bzero(&sun, sizeof(sun)); 86 sun.sun_family = AF_UNIX; 87 strlcpy(sun.sun_path, LDPD_SOCKET, sizeof(sun.sun_path)); 88 if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) 89 err(1, "connect: %s", LDPD_SOCKET); 90 91 if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) 92 err(1, NULL); 93 imsg_init(ibuf, ctl_sock); 94 done = 0; 95 96 /* process user request */ 97 switch (res->action) { 98 case NONE: 99 usage(); 100 /* not reached */ 101 case SHOW: 102 case SHOW_IFACE: 103 printf("%-11s %-18s %-10s %-10s %-8s\n", 104 "Interface", "Address", "State", "Linkstate", 105 "Uptime"); 106 if (*res->ifname) { 107 ifidx = if_nametoindex(res->ifname); 108 if (ifidx == 0) 109 errx(1, "no such interface %s", res->ifname); 110 } 111 imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1, 112 &ifidx, sizeof(ifidx)); 113 break; 114 case SHOW_NBR: 115 printf("%-15s %-18s %-15s %-9s %-10s\n", "ID", 116 "State", "Address", "Iface", "Uptime"); 117 imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0); 118 break; 119 case SHOW_LIB: 120 printf("%-20s %-17s %-17s %s\n", "Destination", 121 "Nexthop", "Local Label", "Remote Label"); 122 imsg_compose(ibuf, IMSG_CTL_SHOW_LIB, 0, 0, -1, NULL, 0); 123 break; 124 case SHOW_LFIB: 125 if (!res->addr.s_addr) 126 imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1, 127 &res->flags, sizeof(res->flags)); 128 else 129 imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1, 130 &res->addr, sizeof(res->addr)); 131 show_lfib_head(); 132 break; 133 case SHOW_LFIB_IFACE: 134 if (*res->ifname) 135 imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, 136 res->ifname, sizeof(res->ifname)); 137 else 138 imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0); 139 show_interface_head(); 140 break; 141 case LFIB: 142 errx(1, "lfib couple|decouple"); 143 break; 144 case LFIB_COUPLE: 145 imsg_compose(ibuf, IMSG_CTL_LFIB_COUPLE, 0, 0, -1, NULL, 0); 146 printf("couple request sent.\n"); 147 done = 1; 148 break; 149 case LFIB_DECOUPLE: 150 imsg_compose(ibuf, IMSG_CTL_LFIB_DECOUPLE, 0, 0, -1, NULL, 0); 151 printf("decouple request sent.\n"); 152 done = 1; 153 break; 154 case RELOAD: 155 imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0); 156 printf("reload request sent.\n"); 157 done = 1; 158 break; 159 } 160 161 while (ibuf->w.queued) 162 if (msgbuf_write(&ibuf->w) < 0) 163 err(1, "write error"); 164 165 while (!done) { 166 if ((n = imsg_read(ibuf)) == -1) 167 errx(1, "imsg_read error"); 168 if (n == 0) 169 errx(1, "pipe closed"); 170 171 while (!done) { 172 if ((n = imsg_get(ibuf, &imsg)) == -1) 173 errx(1, "imsg_get error"); 174 if (n == 0) 175 break; 176 switch (res->action) { 177 case SHOW: 178 case SHOW_IFACE: 179 done = show_interface_msg(&imsg); 180 break; 181 case SHOW_NBR: 182 done = show_nbr_msg(&imsg); 183 break; 184 case SHOW_LIB: 185 done = show_lib_msg(&imsg); 186 break; 187 case SHOW_LFIB: 188 done = show_lfib_msg(&imsg); 189 break; 190 case SHOW_LFIB_IFACE: 191 done = show_lfib_interface_msg(&imsg); 192 break; 193 case NONE: 194 case LFIB: 195 case LFIB_COUPLE: 196 case LFIB_DECOUPLE: 197 case RELOAD: 198 break; 199 } 200 imsg_free(&imsg); 201 } 202 } 203 close(ctl_sock); 204 free(ibuf); 205 206 return (0); 207 } 208 209 int 210 get_ifms_type(int mediatype) 211 { 212 switch (mediatype) { 213 case IFT_ETHER: 214 return (IFM_ETHER); 215 break; 216 case IFT_FDDI: 217 return (IFM_FDDI); 218 break; 219 case IFT_CARP: 220 return (IFM_CARP); 221 break; 222 default: 223 return (0); 224 break; 225 } 226 } 227 228 #define TF_BUFS 8 229 #define TF_LEN 9 230 231 const char * 232 fmt_timeframe_core(time_t t) 233 { 234 char *buf; 235 static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */ 236 static int idx = 0; 237 unsigned int sec, min, hrs, day, week; 238 239 if (t == 0) 240 return ("Stopped"); 241 242 buf = tfbuf[idx++]; 243 if (idx == TF_BUFS) 244 idx = 0; 245 246 week = t; 247 248 sec = week % 60; 249 week /= 60; 250 min = week % 60; 251 week /= 60; 252 hrs = week % 24; 253 week /= 24; 254 day = week % 7; 255 week /= 7; 256 257 if (week > 0) 258 snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs); 259 else if (day > 0) 260 snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min); 261 else 262 snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec); 263 264 return (buf); 265 } 266 267 /* prototype defined in ldpd.h and shared with the kroute.c version */ 268 u_int8_t 269 mask2prefixlen(in_addr_t ina) 270 { 271 if (ina == 0) 272 return (0); 273 else 274 return (33 - ffs(ntohl(ina))); 275 } 276 277 int 278 show_interface_msg(struct imsg *imsg) 279 { 280 struct ctl_iface *iface; 281 char *netid; 282 283 switch (imsg->hdr.type) { 284 case IMSG_CTL_SHOW_INTERFACE: 285 iface = imsg->data; 286 287 if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr), 288 mask2prefixlen(iface->mask.s_addr)) == -1) 289 err(1, NULL); 290 printf("%-11s %-18s %-10s %-10s %-8s\n", 291 iface->name, netid, if_state_name(iface->state), 292 get_linkstate(iface->mediatype, iface->linkstate), 293 iface->uptime == 0 ? "00:00:00" : 294 fmt_timeframe_core(iface->uptime)); 295 free(netid); 296 break; 297 case IMSG_CTL_END: 298 printf("\n"); 299 return (1); 300 default: 301 break; 302 } 303 304 return (0); 305 } 306 307 int 308 show_lib_msg(struct imsg *imsg) 309 { 310 struct ctl_rt *rt; 311 char *dstnet, *remote; 312 313 switch (imsg->hdr.type) { 314 case IMSG_CTL_SHOW_LIB: 315 rt = imsg->data; 316 if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix), 317 rt->prefixlen) == -1) 318 err(1, NULL); 319 320 if (rt->connected) { 321 if (asprintf(&remote, "-") == -1) 322 err(1, NULL); 323 } else { 324 if (asprintf(&remote, "%u", (ntohl(rt->remote_label) >> MPLS_LABEL_OFFSET)) == -1) 325 err(1, NULL); 326 } 327 328 printf("%-20s %-17s %-17u %s\n", dstnet, 329 inet_ntoa(rt->nexthop), 330 (ntohl(rt->local_label) >> MPLS_LABEL_OFFSET), 331 remote); 332 free(remote); 333 free(dstnet); 334 335 break; 336 case IMSG_CTL_END: 337 printf("\n"); 338 return (1); 339 default: 340 break; 341 } 342 343 return (0); 344 } 345 346 int 347 show_nbr_msg(struct imsg *imsg) 348 { 349 struct ctl_nbr *nbr; 350 char *state; 351 352 switch (imsg->hdr.type) { 353 case IMSG_CTL_SHOW_NBR: 354 nbr = imsg->data; 355 if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state), 356 if_state_name(nbr->iface_state)) == -1) 357 err(1, NULL); 358 printf("%-15s %-19s", inet_ntoa(nbr->id), 359 state); 360 printf("%-15s %-10s", inet_ntoa(nbr->addr), nbr->name); 361 printf("%-15s\n", nbr->uptime == 0 ? "-" : 362 fmt_timeframe_core(nbr->uptime)); 363 free(state); 364 break; 365 case IMSG_CTL_END: 366 printf("\n"); 367 return (1); 368 default: 369 break; 370 } 371 372 return (0); 373 } 374 375 void 376 show_lfib_head(void) 377 { 378 printf("flags: * = valid, C = Connected, S = Static\n"); 379 printf("%-6s %-20s %-17s %-17s %s\n", "Flags", "Destination", "Nexthop", 380 "Local Label", "Remote Label"); 381 } 382 383 int 384 show_lfib_msg(struct imsg *imsg) 385 { 386 struct kroute *k; 387 char *p; 388 389 switch (imsg->hdr.type) { 390 case IMSG_CTL_KROUTE: 391 if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute)) 392 errx(1, "wrong imsg len"); 393 k = imsg->data; 394 395 if (k->flags & F_DOWN) 396 printf(" "); 397 else 398 printf("*"); 399 400 if (!(k->flags & F_KERNEL)) 401 printf("R"); 402 else if (k->flags & F_CONNECTED) 403 printf("C"); 404 else if (k->flags & F_STATIC) 405 printf("S"); 406 else 407 printf(" "); 408 409 printf(" "); 410 if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), 411 k->prefixlen) == -1) 412 err(1, NULL); 413 printf("%-20s ", p); 414 free(p); 415 416 if (k->nexthop.s_addr) 417 printf("%-18s", inet_ntoa(k->nexthop)); 418 else if (k->flags & F_CONNECTED) 419 printf("link#%-13u", k->ifindex); 420 421 if (k->local_label) { 422 printf("%-18u", (ntohl(k->local_label) >> 423 MPLS_LABEL_OFFSET)); 424 } else 425 printf("- "); 426 427 if (k->remote_label) { 428 printf("%u", (ntohl(k->remote_label) >> 429 MPLS_LABEL_OFFSET)); 430 } else 431 printf("-"); 432 433 printf("\n"); 434 435 break; 436 case IMSG_CTL_END: 437 printf("\n"); 438 return (1); 439 default: 440 break; 441 } 442 443 return (0); 444 } 445 446 void 447 show_interface_head(void) 448 { 449 printf("%-15s%-15s%s\n", "Interface", "Flags", 450 "Link state"); 451 } 452 453 int 454 show_lfib_interface_msg(struct imsg *imsg) 455 { 456 struct kif *k; 457 int ifms_type; 458 459 switch (imsg->hdr.type) { 460 case IMSG_CTL_IFINFO: 461 k = imsg->data; 462 printf("%-15s", k->ifname); 463 printf("%-15s", k->flags & IFF_UP ? "UP" : ""); 464 ifms_type = get_ifms_type(k->media_type); 465 if (ifms_type) 466 printf("%s, ", get_media_descr(ifms_type)); 467 468 printf("%s", get_linkstate(k->media_type, k->link_state)); 469 470 if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) { 471 printf(", "); 472 print_baudrate(k->baudrate); 473 } 474 printf("\n"); 475 break; 476 case IMSG_CTL_END: 477 printf("\n"); 478 return (1); 479 default: 480 break; 481 } 482 483 return (0); 484 } 485 486 const struct if_status_description 487 if_status_descriptions[] = LINK_STATE_DESCRIPTIONS; 488 const struct ifmedia_description 489 ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS; 490 491 const char * 492 get_media_descr(int media_type) 493 { 494 const struct ifmedia_description *p; 495 496 for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++) 497 if (media_type == p->ifmt_word) 498 return (p->ifmt_string); 499 500 return ("unknown"); 501 } 502 503 const char * 504 get_linkstate(int media_type, int link_state) 505 { 506 const struct if_status_description *p; 507 static char buf[8]; 508 509 for (p = if_status_descriptions; p->ifs_string != NULL; p++) { 510 if (LINK_STATE_DESC_MATCH(p, media_type, link_state)) 511 return (p->ifs_string); 512 } 513 snprintf(buf, sizeof(buf), "[#%d]", link_state); 514 return (buf); 515 } 516 517 void 518 print_baudrate(u_int64_t baudrate) 519 { 520 if (baudrate > IF_Gbps(1)) 521 printf("%llu GBit/s", baudrate / IF_Gbps(1)); 522 else if (baudrate > IF_Mbps(1)) 523 printf("%llu MBit/s", baudrate / IF_Mbps(1)); 524 else if (baudrate > IF_Kbps(1)) 525 printf("%llu KBit/s", baudrate / IF_Kbps(1)); 526 else 527 printf("%llu Bit/s", baudrate); 528 } 529