"Fossies" - the Fresh Open Source Software Archive

Member "ospfctl/ospfctl.c" (6 Jun 2009, 30485 Bytes) of package /linux/privat/old/openospfd-4.6.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ospfctl.c" see the Fossies "Dox" file reference documentation.

    1 /*  $OpenBSD: ospfctl.c,v 1.48 2009/06/06 07:31:26 eric Exp $ */
    2 
    3 /*
    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 
   29 #include <err.h>
   30 #include <stdio.h>
   31 #include <stdlib.h>
   32 #include <string.h>
   33 #include <unistd.h>
   34 
   35 #include "ospf.h"
   36 #include "ospfd.h"
   37 #include "ospfe.h"
   38 #include "parser.h"
   39 
   40 __dead void  usage(void);
   41 int      show_summary_msg(struct imsg *);
   42 int      get_ifms_type(int);
   43 int      show_interface_msg(struct imsg *);
   44 int      show_interface_detail_msg(struct imsg *);
   45 const char  *print_link(int);
   46 const char  *fmt_timeframe(time_t t);
   47 const char  *fmt_timeframe_core(time_t t);
   48 const char  *log_id(u_int32_t );
   49 const char  *log_adv_rtr(u_int32_t);
   50 void         show_database_head(struct in_addr, u_int8_t);
   51 int      show_database_msg(struct imsg *);
   52 char        *print_ls_type(u_int8_t);
   53 void         show_db_hdr_msg_detail(struct lsa_hdr *);
   54 char        *print_rtr_link_type(u_int8_t);
   55 const char  *print_ospf_flags(u_int8_t);
   56 int      show_db_msg_detail(struct imsg *imsg);
   57 int      show_nbr_msg(struct imsg *);
   58 const char  *print_ospf_options(u_int8_t);
   59 int      show_nbr_detail_msg(struct imsg *);
   60 int      show_rib_msg(struct imsg *);
   61 void         show_rib_head(struct in_addr, u_int8_t, u_int8_t);
   62 const char  *print_ospf_rtr_flags(u_int8_t);
   63 int      show_rib_detail_msg(struct imsg *);
   64 void         show_fib_head(void);
   65 int      show_fib_msg(struct imsg *);
   66 void         show_interface_head(void);
   67 const char *     get_media_descr(int);
   68 const char *     get_linkstate(int, int);
   69 void         print_baudrate(u_int64_t);
   70 int      show_fib_interface_msg(struct imsg *);
   71 
   72 struct imsgbuf  *ibuf;
   73 
   74 __dead void
   75 usage(void)
   76 {
   77     extern char *__progname;
   78 
   79     fprintf(stderr, "usage: %s [-s socket] command [argument ...]\n",
   80         __progname);
   81     exit(1);
   82 }
   83 
   84 int
   85 main(int argc, char *argv[])
   86 {
   87     struct sockaddr_un   sun;
   88     struct parse_result *res;
   89     struct imsg      imsg;
   90     unsigned int         ifidx = 0;
   91     int          ctl_sock;
   92     int          done = 0;
   93     int          n;
   94     int          ch;
   95     char            *sockname;
   96 
   97     sockname = OSPFD_SOCKET;
   98     while ((ch = getopt(argc, argv, "s:")) != -1) {
   99         switch (ch) {
  100         case 's':
  101             sockname = optarg;
  102             break;
  103         default:
  104             usage();
  105             /* NOTREACHED */
  106         }
  107     }
  108     argc -= optind;
  109     argv += optind;
  110 
  111     /* parse options */
  112     if ((res = parse(argc, argv)) == NULL)
  113         exit(1);
  114 
  115     /* connect to ospfd control socket */
  116     if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
  117         err(1, "socket");
  118 
  119     bzero(&sun, sizeof(sun));
  120     sun.sun_family = AF_UNIX;
  121 
  122     strlcpy(sun.sun_path, sockname, sizeof(sun.sun_path));
  123     if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
  124         err(1, "connect: %s", sockname);
  125 
  126     if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
  127         err(1, NULL);
  128     imsg_init(ibuf, ctl_sock);
  129     done = 0;
  130 
  131     /* process user request */
  132     switch (res->action) {
  133     case NONE:
  134         usage();
  135         /* not reached */
  136     case SHOW:
  137     case SHOW_SUM:
  138         imsg_compose(ibuf, IMSG_CTL_SHOW_SUM, 0, 0, -1, NULL, 0);
  139         break;
  140     case SHOW_IFACE:
  141         printf("%-11s %-18s %-6s %-10s %-10s %-8s %3s %3s\n",
  142             "Interface", "Address", "State", "HelloTimer", "Linkstate",
  143             "Uptime", "nc", "ac");
  144         /*FALLTHROUGH*/
  145     case SHOW_IFACE_DTAIL:
  146         if (*res->ifname) {
  147             ifidx = if_nametoindex(res->ifname);
  148             if (ifidx == 0)
  149                 errx(1, "no such interface %s", res->ifname);
  150         }
  151         imsg_compose(ibuf, IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
  152             &ifidx, sizeof(ifidx));
  153         break;
  154     case SHOW_NBR:
  155         printf("%-15s %-3s %-12s %-8s %-15s %-9s %s\n", "ID", "Pri",
  156             "State", "DeadTime", "Address", "Iface","Uptime");
  157         /*FALLTHROUGH*/
  158     case SHOW_NBR_DTAIL:
  159         imsg_compose(ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0);
  160         break;
  161     case SHOW_DB:
  162         imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1, NULL, 0);
  163         break;
  164     case SHOW_DBBYAREA:
  165         imsg_compose(ibuf, IMSG_CTL_SHOW_DATABASE, 0, 0, -1,
  166             &res->addr, sizeof(res->addr));
  167         break;
  168     case SHOW_DBEXT:
  169         imsg_compose(ibuf, IMSG_CTL_SHOW_DB_EXT, 0, 0, -1, NULL, 0);
  170         break;
  171     case SHOW_DBNET:
  172         imsg_compose(ibuf, IMSG_CTL_SHOW_DB_NET, 0, 0, -1, NULL, 0);
  173         break;
  174     case SHOW_DBRTR:
  175         imsg_compose(ibuf, IMSG_CTL_SHOW_DB_RTR, 0, 0, -1, NULL, 0);
  176         break;
  177     case SHOW_DBSELF:
  178         imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SELF, 0, 0, -1, NULL, 0);
  179         break;
  180     case SHOW_DBSUM:
  181         imsg_compose(ibuf, IMSG_CTL_SHOW_DB_SUM, 0, 0, -1, NULL, 0);
  182         break;
  183     case SHOW_DBASBR:
  184         imsg_compose(ibuf, IMSG_CTL_SHOW_DB_ASBR, 0, 0, -1, NULL, 0);
  185         break;
  186     case SHOW_RIB:
  187         printf("%-20s %-17s %-12s %-9s %-7s %-8s\n", "Destination",
  188             "Nexthop", "Path Type", "Type", "Cost", "Uptime");
  189         /*FALLTHROUGH*/
  190     case SHOW_RIB_DTAIL:
  191         imsg_compose(ibuf, IMSG_CTL_SHOW_RIB, 0, 0, -1, NULL, 0);
  192         break;
  193     case SHOW_FIB:
  194         if (!res->addr.s_addr)
  195             imsg_compose(ibuf, IMSG_CTL_KROUTE, 0, 0, -1,
  196                 &res->flags, sizeof(res->flags));
  197         else
  198             imsg_compose(ibuf, IMSG_CTL_KROUTE_ADDR, 0, 0, -1,
  199                 &res->addr, sizeof(res->addr));
  200         show_fib_head();
  201         break;
  202     case SHOW_FIB_IFACE:
  203         if (*res->ifname)
  204             imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1,
  205                 res->ifname, sizeof(res->ifname));
  206         else
  207             imsg_compose(ibuf, IMSG_CTL_IFINFO, 0, 0, -1, NULL, 0);
  208         show_interface_head();
  209         break;
  210     case FIB:
  211         errx(1, "fib couple|decouple");
  212         break;
  213     case FIB_COUPLE:
  214         imsg_compose(ibuf, IMSG_CTL_FIB_COUPLE, 0, 0, -1, NULL, 0);
  215         printf("couple request sent.\n");
  216         done = 1;
  217         break;
  218     case FIB_DECOUPLE:
  219         imsg_compose(ibuf, IMSG_CTL_FIB_DECOUPLE, 0, 0, -1, NULL, 0);
  220         printf("decouple request sent.\n");
  221         done = 1;
  222         break;
  223     case RELOAD:
  224         imsg_compose(ibuf, IMSG_CTL_RELOAD, 0, 0, -1, NULL, 0);
  225         printf("reload request sent.\n");
  226         done = 1;
  227         break;
  228     }
  229 
  230     while (ibuf->w.queued)
  231         if (msgbuf_write(&ibuf->w) < 0)
  232             err(1, "write error");
  233 
  234     while (!done) {
  235         if ((n = imsg_read(ibuf)) == -1)
  236             errx(1, "imsg_read error");
  237         if (n == 0)
  238             errx(1, "pipe closed");
  239 
  240         while (!done) {
  241             if ((n = imsg_get(ibuf, &imsg)) == -1)
  242                 errx(1, "imsg_get error");
  243             if (n == 0)
  244                 break;
  245             switch (res->action) {
  246             case SHOW:
  247             case SHOW_SUM:
  248                 done = show_summary_msg(&imsg);
  249                 break;
  250             case SHOW_IFACE:
  251                 done = show_interface_msg(&imsg);
  252                 break;
  253             case SHOW_IFACE_DTAIL:
  254                 done = show_interface_detail_msg(&imsg);
  255                 break;
  256             case SHOW_NBR:
  257                 done = show_nbr_msg(&imsg);
  258                 break;
  259             case SHOW_NBR_DTAIL:
  260                 done = show_nbr_detail_msg(&imsg);
  261                 break;
  262             case SHOW_DB:
  263             case SHOW_DBBYAREA:
  264             case SHOW_DBSELF:
  265                 done = show_database_msg(&imsg);
  266                 break;
  267             case SHOW_DBEXT:
  268             case SHOW_DBNET:
  269             case SHOW_DBRTR:
  270             case SHOW_DBSUM:
  271             case SHOW_DBASBR:
  272                 done = show_db_msg_detail(&imsg);
  273                 break;
  274             case SHOW_RIB:
  275                 done = show_rib_msg(&imsg);
  276                 break;
  277             case SHOW_RIB_DTAIL:
  278                 done = show_rib_detail_msg(&imsg);
  279                 break;
  280             case SHOW_FIB:
  281                 done = show_fib_msg(&imsg);
  282                 break;
  283             case SHOW_FIB_IFACE:
  284                 done = show_fib_interface_msg(&imsg);
  285                 break;
  286             case NONE:
  287             case FIB:
  288             case FIB_COUPLE:
  289             case FIB_DECOUPLE:
  290             case RELOAD:
  291                 break;
  292             }
  293             imsg_free(&imsg);
  294         }
  295     }
  296     close(ctl_sock);
  297     free(ibuf);
  298 
  299     return (0);
  300 }
  301 
  302 int
  303 show_summary_msg(struct imsg *imsg)
  304 {
  305     struct ctl_sum      *sum;
  306     struct ctl_sum_area *sumarea;
  307 
  308     switch (imsg->hdr.type) {
  309     case IMSG_CTL_SHOW_SUM:
  310         sum = imsg->data;
  311         printf("Router ID: %s\n", inet_ntoa(sum->rtr_id));
  312         printf("Uptime: %s\n", fmt_timeframe_core(sum->uptime));
  313         printf("RFC1583 compatibility flag is ");
  314         if (sum->rfc1583compat)
  315             printf("enabled\n");
  316         else
  317             printf("disabled\n");
  318 
  319         printf("SPF delay is %d sec(s), hold time between two SPFs "
  320             "is %d sec(s)\n", sum->spf_delay, sum->spf_hold_time);
  321         printf("Number of external LSA(s) %d\n", sum->num_ext_lsa);
  322         printf("Number of areas attached to this router: %d\n",
  323             sum->num_area);
  324         break;
  325     case IMSG_CTL_SHOW_SUM_AREA:
  326         sumarea = imsg->data;
  327         printf("\nArea ID: %s\n", inet_ntoa(sumarea->area));
  328         printf("  Number of interfaces in this area: %d\n",
  329             sumarea->num_iface);
  330         printf("  Number of fully adjacent neighbors in this "
  331             "area: %d\n", sumarea->num_adj_nbr);
  332         printf("  SPF algorithm executed %d time(s)\n",
  333             sumarea->num_spf_calc);
  334         printf("  Number LSA(s) %d\n", sumarea->num_lsa);
  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 get_ifms_type(int mediatype)
  348 {
  349     switch (mediatype) {
  350     case IFT_ETHER:
  351         return (IFM_ETHER);
  352     case IFT_FDDI:
  353         return (IFM_FDDI);
  354     case IFT_CARP:
  355         return (IFM_CARP);
  356     case IFT_PPP:
  357         return (IFM_TDM);
  358     default:
  359         return (0);
  360     }
  361 }
  362 
  363 int
  364 show_interface_msg(struct imsg *imsg)
  365 {
  366     struct ctl_iface    *iface;
  367     char            *netid;
  368 
  369     switch (imsg->hdr.type) {
  370     case IMSG_CTL_SHOW_INTERFACE:
  371         iface = imsg->data;
  372 
  373         if (asprintf(&netid, "%s/%d", inet_ntoa(iface->addr),
  374             mask2prefixlen(iface->mask.s_addr)) == -1)
  375             err(1, NULL);
  376         printf("%-11s %-18s %-6s %-10s %-10s %s %3d %3d\n",
  377             iface->name, netid, if_state_name(iface->state),
  378             iface->hello_timer < 0 ? "-" :
  379             fmt_timeframe_core(iface->hello_timer),
  380             get_linkstate(get_ifms_type(iface->mediatype),
  381             iface->linkstate), fmt_timeframe_core(iface->uptime),
  382             iface->nbr_cnt, iface->adj_cnt);
  383         free(netid);
  384         break;
  385     case IMSG_CTL_END:
  386         printf("\n");
  387         return (1);
  388     default:
  389         break;
  390     }
  391 
  392     return (0);
  393 }
  394 
  395 int
  396 show_interface_detail_msg(struct imsg *imsg)
  397 {
  398     struct ctl_iface    *iface;
  399 
  400     switch (imsg->hdr.type) {
  401     case IMSG_CTL_SHOW_INTERFACE:
  402         iface = imsg->data;
  403         printf("\n");
  404         printf("Interface %s, line protocol is %s\n",
  405             iface->name, print_link(iface->flags));
  406         printf("  Internet address %s/%d, ",
  407             inet_ntoa(iface->addr),
  408             mask2prefixlen(iface->mask.s_addr));
  409         printf("Area %s\n", inet_ntoa(iface->area));
  410         printf("  Linkstate %s\n",
  411             get_linkstate(get_ifms_type(iface->mediatype),
  412             iface->linkstate));
  413         printf("  Router ID %s, network type %s, cost: %d\n",
  414             inet_ntoa(iface->rtr_id),
  415             if_type_name(iface->type), iface->metric);
  416         printf("  Transmit delay is %d sec(s), state %s, priority %d\n",
  417             iface->transmit_delay, if_state_name(iface->state),
  418             iface->priority);
  419         printf("  Designated Router (ID) %s, ",
  420             inet_ntoa(iface->dr_id));
  421         printf("interface address %s\n", inet_ntoa(iface->dr_addr));
  422         printf("  Backup Designated Router (ID) %s, ",
  423             inet_ntoa(iface->bdr_id));
  424         printf("interface address %s\n", inet_ntoa(iface->bdr_addr));
  425         printf("  Timer intervals configured, "
  426             "hello %d, dead %d, wait %d, retransmit %d\n",
  427              iface->hello_interval, iface->dead_interval,
  428              iface->dead_interval, iface->rxmt_interval);
  429         if (iface->passive)
  430             printf("    Passive interface (No Hellos)\n");
  431         else if (iface->hello_timer < 0)
  432             printf("    Hello timer not running\n");
  433         else
  434             printf("    Hello timer due in %s\n",
  435                 fmt_timeframe_core(iface->hello_timer));
  436         printf("    Uptime %s\n", fmt_timeframe_core(iface->uptime));
  437         printf("  Neighbor count is %d, adjacent neighbor count is "
  438             "%d\n", iface->nbr_cnt, iface->adj_cnt);
  439         if (iface->auth_type > 0) {
  440             switch (iface->auth_type) {
  441             case AUTH_SIMPLE:
  442                 printf("  Simple password authentication "
  443                     "enabled\n");
  444                 break;
  445             case AUTH_CRYPT:
  446                 printf("  Message digest authentication "
  447                     "enabled\n");
  448                 printf("    Primary key id is %d\n",
  449                     iface->auth_keyid);
  450                 break;
  451             default:
  452                 break;
  453             }
  454         }
  455         break;
  456     case IMSG_CTL_END:
  457         printf("\n");
  458         return (1);
  459     default:
  460         break;
  461     }
  462 
  463     return (0);
  464 }
  465 
  466 const char *
  467 print_link(int state)
  468 {
  469     if (state & IFF_UP)
  470         return ("UP");
  471     else
  472         return ("DOWN");
  473 }
  474 
  475 #define TF_BUFS 8
  476 #define TF_LEN  9
  477 
  478 const char *
  479 fmt_timeframe(time_t t)
  480 {
  481     if (t == 0)
  482         return ("Never");
  483     else
  484         return (fmt_timeframe_core(time(NULL) - t));
  485 }
  486 
  487 const char *
  488 fmt_timeframe_core(time_t t)
  489 {
  490     char        *buf;
  491     static char  tfbuf[TF_BUFS][TF_LEN];    /* ring buffer */
  492     static int   idx = 0;
  493     unsigned int     sec, min, hrs, day, week;
  494 
  495     if (t == 0)
  496         return ("00:00:00");
  497 
  498     buf = tfbuf[idx++];
  499     if (idx == TF_BUFS)
  500         idx = 0;
  501 
  502     week = t;
  503 
  504     sec = week % 60;
  505     week /= 60;
  506     min = week % 60;
  507     week /= 60;
  508     hrs = week % 24;
  509     week /= 24;
  510     day = week % 7;
  511     week /= 7;
  512 
  513     if (week > 0)
  514         snprintf(buf, TF_LEN, "%02uw%01ud%02uh", week, day, hrs);
  515     else if (day > 0)
  516         snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
  517     else
  518         snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
  519 
  520     return (buf);
  521 }
  522 
  523 const char *
  524 log_id(u_int32_t id)
  525 {
  526     static char buf[48];
  527     struct in_addr  addr;
  528 
  529     addr.s_addr = id;
  530 
  531     if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
  532         return ("?");
  533     else
  534         return (buf);
  535 }
  536 
  537 const char *
  538 log_adv_rtr(u_int32_t adv_rtr)
  539 {
  540     static char buf[48];
  541     struct in_addr  addr;
  542 
  543     addr.s_addr = adv_rtr;
  544 
  545     if (inet_ntop(AF_INET, &addr, buf, sizeof(buf)) == NULL)
  546         return ("?");
  547     else
  548         return (buf);
  549 }
  550 
  551 /* prototype defined in ospfd.h and shared with the kroute.c version */
  552 u_int8_t
  553 mask2prefixlen(in_addr_t ina)
  554 {
  555     if (ina == 0)
  556         return (0);
  557     else
  558         return (33 - ffs(ntohl(ina)));
  559 }
  560 
  561 void
  562 show_database_head(struct in_addr aid, u_int8_t type)
  563 {
  564     char    *header, *format;
  565 
  566     switch (type) {
  567     case LSA_TYPE_ROUTER:
  568         format = "Router Link States";
  569         break;
  570     case LSA_TYPE_NETWORK:
  571         format = "Net Link States";
  572         break;
  573     case LSA_TYPE_SUM_NETWORK:
  574         format = "Summary Net Link States";
  575         break;
  576     case LSA_TYPE_SUM_ROUTER:
  577         format = "Summary Router Link States";
  578         break;
  579     case LSA_TYPE_EXTERNAL:
  580         format = NULL;
  581         if ((header = strdup("Type-5 AS External Link States")) == NULL)
  582             err(1, NULL);
  583         break;
  584     default:
  585         errx(1, "unknown LSA type");
  586     }
  587     if (type != LSA_TYPE_EXTERNAL)
  588         if (asprintf(&header, "%s (Area %s)", format,
  589             inet_ntoa(aid)) == -1)
  590             err(1, NULL);
  591 
  592     printf("\n%-15s %s\n\n", "", header);
  593     free(header);
  594 }
  595 
  596 int
  597 show_database_msg(struct imsg *imsg)
  598 {
  599     static struct in_addr    area_id;
  600     static u_int8_t      lasttype;
  601     struct area     *area;
  602     struct lsa_hdr      *lsa;
  603 
  604     switch (imsg->hdr.type) {
  605     case IMSG_CTL_SHOW_DATABASE:
  606     case IMSG_CTL_SHOW_DB_SELF:
  607         lsa = imsg->data;
  608         if (lsa->type != lasttype) {
  609             show_database_head(area_id, lsa->type);
  610             printf("%-15s %-15s %-4s %-10s %-8s\n", "Link ID",
  611                 "Adv Router", "Age", "Seq#", "Checksum");
  612         }
  613         printf("%-15s %-15s %-4d 0x%08x 0x%04x\n",
  614             log_id(lsa->ls_id), log_adv_rtr(lsa->adv_rtr),
  615             ntohs(lsa->age), ntohl(lsa->seq_num),
  616             ntohs(lsa->ls_chksum));
  617         lasttype = lsa->type;
  618         break;
  619     case IMSG_CTL_AREA:
  620         area = imsg->data;
  621         area_id = area->id;
  622         lasttype = 0;
  623         break;
  624     case IMSG_CTL_END:
  625         printf("\n");
  626         return (1);
  627     default:
  628         break;
  629     }
  630 
  631     return (0);
  632 }
  633 
  634 char *
  635 print_ls_type(u_int8_t type)
  636 {
  637     switch (type) {
  638     case LSA_TYPE_ROUTER:
  639         return ("Router");
  640     case LSA_TYPE_NETWORK:
  641         return ("Network");
  642     case LSA_TYPE_SUM_NETWORK:
  643         return ("Summary (Network)");
  644     case LSA_TYPE_SUM_ROUTER:
  645         return ("Summary (Router)");
  646     case LSA_TYPE_EXTERNAL:
  647         return ("AS External");
  648     default:
  649         return ("Unknown");
  650     }
  651 }
  652 
  653 void
  654 show_db_hdr_msg_detail(struct lsa_hdr *lsa)
  655 {
  656     printf("LS age: %d\n", ntohs(lsa->age));
  657     printf("Options: %s\n", print_ospf_options(lsa->opts));
  658     printf("LS Type: %s\n", print_ls_type(lsa->type));
  659 
  660     switch (lsa->type) {
  661     case LSA_TYPE_ROUTER:
  662         printf("Link State ID: %s\n", log_id(lsa->ls_id));
  663         break;
  664     case LSA_TYPE_NETWORK:
  665         printf("Link State ID: %s (address of Designated Router)\n",
  666             log_id(lsa->ls_id));
  667         break;
  668     case LSA_TYPE_SUM_NETWORK:
  669         printf("Link State ID: %s (Network ID)\n", log_id(lsa->ls_id));
  670         break;
  671     case LSA_TYPE_SUM_ROUTER:
  672         printf("Link State ID: %s (ASBR Router ID)\n",
  673             log_id(lsa->ls_id));
  674         break;
  675     case LSA_TYPE_EXTERNAL:
  676         printf("Link State ID: %s (External Network Number)\n",
  677              log_id(lsa->ls_id));
  678         break;
  679     }
  680 
  681     printf("Advertising Router: %s\n", log_adv_rtr(lsa->adv_rtr));
  682     printf("LS Seq Number: 0x%08x\n", ntohl(lsa->seq_num));
  683     printf("Checksum: 0x%04x\n", ntohs(lsa->ls_chksum));
  684     printf("Length: %d\n", ntohs(lsa->len));
  685 }
  686 
  687 char *
  688 print_rtr_link_type(u_int8_t type)
  689 {
  690     switch (type) {
  691     case LINK_TYPE_POINTTOPOINT:
  692         return ("Point-to-Point");
  693     case LINK_TYPE_TRANSIT_NET:
  694         return ("Transit Network");
  695     case LINK_TYPE_STUB_NET:
  696         return ("Stub Network");
  697     case LINK_TYPE_VIRTUAL:
  698         return ("Virtual Link");
  699     default:
  700         return ("Unknown");
  701     }
  702 }
  703 
  704 const char *
  705 print_ospf_flags(u_int8_t opts)
  706 {
  707     static char optbuf[32];
  708 
  709     snprintf(optbuf, sizeof(optbuf), "*|*|*|*|*|%s|%s|%s",
  710         opts & OSPF_RTR_V ? "V" : "-",
  711         opts & OSPF_RTR_E ? "E" : "-",
  712         opts & OSPF_RTR_B ? "B" : "-");
  713     return (optbuf);
  714 }
  715 
  716 int
  717 show_db_msg_detail(struct imsg *imsg)
  718 {
  719     static struct in_addr    area_id;
  720     static u_int8_t      lasttype;
  721     struct in_addr       addr, data;
  722     struct area     *area;
  723     struct lsa      *lsa;
  724     struct lsa_rtr_link *rtr_link;
  725     struct lsa_asext    *asext;
  726     u_int16_t        i, nlinks, off;
  727 
  728     /* XXX sanity checks! */
  729 
  730     switch (imsg->hdr.type) {
  731     case IMSG_CTL_SHOW_DB_EXT:
  732         lsa = imsg->data;
  733         if (lsa->hdr.type != lasttype)
  734             show_database_head(area_id, lsa->hdr.type);
  735         show_db_hdr_msg_detail(&lsa->hdr);
  736         addr.s_addr = lsa->data.asext.mask;
  737         printf("Network Mask: %s\n", inet_ntoa(addr));
  738 
  739         asext = (struct lsa_asext *)((char *)lsa + sizeof(lsa->hdr));
  740 
  741         printf("    Metric type: ");
  742         if (ntohl(lsa->data.asext.metric) & LSA_ASEXT_E_FLAG)
  743             printf("2\n");
  744         else
  745             printf("1\n");
  746         printf("    Metric: %d\n", ntohl(asext->metric)
  747             & LSA_METRIC_MASK);
  748         addr.s_addr = asext->fw_addr;
  749         printf("    Forwarding Address: %s\n", inet_ntoa(addr));
  750         printf("    External Route Tag: %d\n\n", ntohl(asext->ext_tag));
  751 
  752         lasttype = lsa->hdr.type;
  753         break;
  754     case IMSG_CTL_SHOW_DB_NET:
  755         lsa = imsg->data;
  756         if (lsa->hdr.type != lasttype)
  757             show_database_head(area_id, lsa->hdr.type);
  758         show_db_hdr_msg_detail(&lsa->hdr);
  759         addr.s_addr = lsa->data.net.mask;
  760         printf("Network Mask: %s\n", inet_ntoa(addr));
  761 
  762         nlinks = (ntohs(lsa->hdr.len) - sizeof(struct lsa_hdr)
  763             - sizeof(u_int32_t)) / sizeof(struct lsa_net_link);
  764         off = sizeof(lsa->hdr) + sizeof(u_int32_t);
  765 
  766         for (i = 0; i < nlinks; i++) {
  767             addr.s_addr = lsa->data.net.att_rtr[i];
  768             printf("    Attached Router: %s\n", inet_ntoa(addr));
  769         }
  770 
  771         printf("\n");
  772         lasttype = lsa->hdr.type;
  773         break;
  774     case IMSG_CTL_SHOW_DB_RTR:
  775         lsa = imsg->data;
  776         if (lsa->hdr.type != lasttype)
  777             show_database_head(area_id, lsa->hdr.type);
  778         show_db_hdr_msg_detail(&lsa->hdr);
  779         printf("Flags: %s\n", print_ospf_flags(lsa->data.rtr.flags));
  780         nlinks = ntohs(lsa->data.rtr.nlinks);
  781         printf("Number of Links: %d\n\n", nlinks);
  782 
  783         off = sizeof(lsa->hdr) + sizeof(struct lsa_rtr);
  784 
  785         for (i = 0; i < nlinks; i++) {
  786             rtr_link = (struct lsa_rtr_link *)((char *)lsa + off);
  787 
  788             printf("    Link connected to: %s\n",
  789                 print_rtr_link_type(rtr_link->type));
  790 
  791             addr.s_addr = rtr_link->id;
  792             data.s_addr = rtr_link->data;
  793 
  794             switch (rtr_link->type) {
  795             case LINK_TYPE_POINTTOPOINT:
  796             case LINK_TYPE_VIRTUAL:
  797                 printf("    Link ID (Neighbors Router ID):"
  798                     " %s\n", inet_ntoa(addr));
  799                 printf("    Link Data (Router Interface "
  800                     "address): %s\n", inet_ntoa(data));
  801                 break;
  802             case LINK_TYPE_TRANSIT_NET:
  803                 printf("    Link ID (Designated Router "
  804                     "address): %s\n", inet_ntoa(addr));
  805                 printf("    Link Data (Router Interface "
  806                     "address): %s\n", inet_ntoa(data));
  807                 break;
  808             case LINK_TYPE_STUB_NET:
  809                 printf("    Link ID (Network ID): %s\n",
  810                     inet_ntoa(addr));
  811                 printf("    Link Data (Network Mask): %s\n",
  812                     inet_ntoa(data));
  813                 break;
  814             default:
  815                 printf("    Link ID (Unknown): %s\n",
  816                     inet_ntoa(addr));
  817                 printf("    Link Data (Unknown): %s\n",
  818                     inet_ntoa(data));
  819                 break;
  820             }
  821 
  822             printf("    Metric: %d\n\n", ntohs(rtr_link->metric));
  823 
  824             off += sizeof(struct lsa_rtr_link) +
  825                 rtr_link->num_tos * sizeof(u_int32_t);
  826         }
  827 
  828         lasttype = lsa->hdr.type;
  829         break;
  830     case IMSG_CTL_SHOW_DB_SUM:
  831     case IMSG_CTL_SHOW_DB_ASBR:
  832         lsa = imsg->data;
  833         if (lsa->hdr.type != lasttype)
  834             show_database_head(area_id, lsa->hdr.type);
  835         show_db_hdr_msg_detail(&lsa->hdr);
  836         addr.s_addr = lsa->data.sum.mask;
  837         printf("Network Mask: %s\n", inet_ntoa(addr));
  838         printf("Metric: %d\n\n", ntohl(lsa->data.sum.metric) &
  839             LSA_METRIC_MASK);
  840         lasttype = lsa->hdr.type;
  841         break;
  842     case IMSG_CTL_AREA:
  843         area = imsg->data;
  844         area_id = area->id;
  845         lasttype = 0;
  846         break;
  847     case IMSG_CTL_END:
  848         return (1);
  849     default:
  850         break;
  851     }
  852 
  853     return (0);
  854 }
  855 
  856 int
  857 show_nbr_msg(struct imsg *imsg)
  858 {
  859     struct ctl_nbr  *nbr;
  860     char        *state;
  861 
  862     switch (imsg->hdr.type) {
  863     case IMSG_CTL_SHOW_NBR:
  864         nbr = imsg->data;
  865         if (asprintf(&state, "%s/%s", nbr_state_name(nbr->nbr_state),
  866             if_state_name(nbr->iface_state)) == -1)
  867             err(1, NULL);
  868         printf("%-15s %-3d %-12s %-9s", inet_ntoa(nbr->id),
  869             nbr->priority, state, fmt_timeframe_core(nbr->dead_timer));
  870         printf("%-15s %-9s %s\n", inet_ntoa(nbr->addr), nbr->name,
  871             nbr->uptime == 0 ? "-" : fmt_timeframe_core(nbr->uptime));
  872         free(state);
  873         break;
  874     case IMSG_CTL_END:
  875         printf("\n");
  876         return (1);
  877     default:
  878         break;
  879     }
  880 
  881     return (0);
  882 }
  883 
  884 const char *
  885 print_ospf_options(u_int8_t opts)
  886 {
  887     static char optbuf[32];
  888 
  889     snprintf(optbuf, sizeof(optbuf), "*|*|%s|%s|%s|%s|%s|*",
  890         opts & OSPF_OPTION_DC ? "DC" : "-",
  891         opts & OSPF_OPTION_EA ? "EA" : "-",
  892         opts & OSPF_OPTION_NP ? "N/P" : "-",
  893         opts & OSPF_OPTION_MC ? "MC" : "-",
  894         opts & OSPF_OPTION_E ? "E" : "-");
  895     return (optbuf);
  896 }
  897 
  898 int
  899 show_nbr_detail_msg(struct imsg *imsg)
  900 {
  901     struct ctl_nbr  *nbr;
  902 
  903     switch (imsg->hdr.type) {
  904     case IMSG_CTL_SHOW_NBR:
  905         nbr = imsg->data;
  906         printf("\nNeighbor %s, ", inet_ntoa(nbr->id));
  907         printf("interface address %s\n", inet_ntoa(nbr->addr));
  908         printf("  Area %s, interface %s\n", inet_ntoa(nbr->area),
  909             nbr->name);
  910         printf("  Neighbor priority is %d, "
  911             "State is %s, %d state changes\n",
  912             nbr->priority, nbr_state_name(nbr->nbr_state),
  913             nbr->state_chng_cnt);
  914         printf("  DR is %s, ", inet_ntoa(nbr->dr));
  915         printf("BDR is %s\n", inet_ntoa(nbr->bdr));
  916         printf("  Options %s\n", print_ospf_options(nbr->options));
  917         printf("  Dead timer due in %s\n",
  918             fmt_timeframe_core(nbr->dead_timer));
  919         printf("  Uptime %s\n", fmt_timeframe_core(nbr->uptime));
  920         printf("  Database Summary List %d\n", nbr->db_sum_lst_cnt);
  921         printf("  Link State Request List %d\n", nbr->ls_req_lst_cnt);
  922         printf("  Link State Retransmission List %d\n",
  923             nbr->ls_retrans_lst_cnt);
  924         break;
  925     case IMSG_CTL_END:
  926         printf("\n");
  927         return (1);
  928     default:
  929         break;
  930     }
  931 
  932     return (0);
  933 }
  934 
  935 int
  936 show_rib_msg(struct imsg *imsg)
  937 {
  938     struct ctl_rt   *rt;
  939     char        *dstnet;
  940 
  941     switch (imsg->hdr.type) {
  942     case IMSG_CTL_SHOW_RIB:
  943         rt = imsg->data;
  944         switch (rt->d_type) {
  945         case DT_NET:
  946             if (asprintf(&dstnet, "%s/%d", inet_ntoa(rt->prefix),
  947                 rt->prefixlen) == -1)
  948                 err(1, NULL);
  949             break;
  950         case DT_RTR:
  951             if (asprintf(&dstnet, "%s",
  952                 inet_ntoa(rt->prefix)) == -1)
  953                 err(1, NULL);
  954             break;
  955         default:
  956             errx(1, "Invalid route type");
  957         }
  958 
  959         printf("%-20s %-17s %-12s %-9s %-7d %s\n", dstnet,
  960             inet_ntoa(rt->nexthop), path_type_name(rt->p_type),
  961             dst_type_name(rt->d_type), rt->cost,
  962             rt->uptime == 0 ? "-" : fmt_timeframe_core(rt->uptime));
  963         free(dstnet);
  964         break;
  965     case IMSG_CTL_END:
  966         printf("\n");
  967         return (1);
  968     default:
  969         break;
  970     }
  971 
  972     return (0);
  973 }
  974 
  975 void
  976 show_rib_head(struct in_addr aid, u_int8_t d_type, u_int8_t p_type)
  977 {
  978     char    *header, *format, *format2;
  979 
  980     switch (p_type) {
  981     case PT_INTRA_AREA:
  982     case PT_INTER_AREA:
  983         switch (d_type) {
  984         case DT_NET:
  985             format = "Network Routing Table";
  986             format2 = "";
  987             break;
  988         case DT_RTR:
  989             format = "Router Routing Table";
  990             format2 = "Type";
  991             break;
  992         default:
  993             errx(1, "unknown route type");
  994         }
  995         break;
  996     case PT_TYPE1_EXT:
  997     case PT_TYPE2_EXT:
  998         format = NULL;
  999         format2 = "Cost 2";
 1000         if ((header = strdup("External Routing Table")) == NULL)
 1001             err(1, NULL);
 1002         break;
 1003     default:
 1004         errx(1, "unknown route type");
 1005     }
 1006 
 1007     if (p_type != PT_TYPE1_EXT && p_type != PT_TYPE2_EXT)
 1008         if (asprintf(&header, "%s (Area %s)", format,
 1009             inet_ntoa(aid)) == -1)
 1010             err(1, NULL);
 1011 
 1012     printf("\n%-18s %s\n", "", header);
 1013     free(header);
 1014 
 1015     printf("\n%-18s %-15s %-15s %-12s %-7s %-7s\n", "Destination",
 1016         "Nexthop", "Adv Router", "Path type", "Cost", format2);
 1017 }
 1018 
 1019 const char *
 1020 print_ospf_rtr_flags(u_int8_t opts)
 1021 {
 1022     static char optbuf[32];
 1023 
 1024     snprintf(optbuf, sizeof(optbuf), "%s%s%s",
 1025         opts & OSPF_RTR_E ? "AS" : "",
 1026         opts & OSPF_RTR_E && opts & OSPF_RTR_B ? "+" : "",
 1027         opts & OSPF_RTR_B ? "ABR" : "");
 1028     return (optbuf);
 1029 }
 1030 
 1031 int
 1032 show_rib_detail_msg(struct imsg *imsg)
 1033 {
 1034     static struct in_addr    area_id;
 1035     struct ctl_rt       *rt;
 1036     struct area     *area;
 1037     char            *dstnet;
 1038     static u_int8_t      lasttype;
 1039 
 1040     switch (imsg->hdr.type) {
 1041     case IMSG_CTL_SHOW_RIB:
 1042         rt = imsg->data;
 1043 
 1044         switch (rt->p_type) {
 1045         case PT_INTRA_AREA:
 1046         case PT_INTER_AREA:
 1047             switch (rt->d_type) {
 1048             case DT_NET:
 1049                 if (lasttype != RIB_NET)
 1050                     show_rib_head(rt->area, rt->d_type,
 1051                          rt->p_type);
 1052                 if (asprintf(&dstnet, "%s/%d",
 1053                     inet_ntoa(rt->prefix), rt->prefixlen) == -1)
 1054                     err(1, NULL);
 1055                 lasttype = RIB_NET;
 1056                 break;
 1057             case DT_RTR:
 1058                 if (lasttype != RIB_RTR)
 1059                     show_rib_head(rt->area, rt->d_type,
 1060                          rt->p_type);
 1061                 if (asprintf(&dstnet, "%s",
 1062                     inet_ntoa(rt->prefix)) == -1)
 1063                     err(1, NULL);
 1064                 lasttype = RIB_RTR;
 1065                 break;
 1066             default:
 1067                 errx(1, "unknown route type");
 1068             }
 1069             printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop));
 1070             printf("%-15s %-12s %-7d", inet_ntoa(rt->adv_rtr),
 1071                 path_type_name(rt->p_type), rt->cost);
 1072             free(dstnet);
 1073 
 1074             if (rt->d_type == DT_RTR)
 1075                 printf(" %-7s",
 1076                     print_ospf_rtr_flags(rt->flags));
 1077 
 1078             printf("\n");
 1079             break;
 1080         case PT_TYPE1_EXT:
 1081         case PT_TYPE2_EXT:
 1082             if (lasttype != RIB_EXT)
 1083                 show_rib_head(rt->area, rt->d_type, rt->p_type);
 1084 
 1085             if (asprintf(&dstnet, "%s/%d",
 1086                 inet_ntoa(rt->prefix), rt->prefixlen) == -1)
 1087                 err(1, NULL);
 1088 
 1089             printf("%-18s %-15s ", dstnet, inet_ntoa(rt->nexthop));
 1090             printf("%-15s %-12s %-7d %-7d\n",
 1091                 inet_ntoa(rt->adv_rtr), path_type_name(rt->p_type),
 1092                 rt->cost, rt->cost2);
 1093             free(dstnet);
 1094 
 1095             lasttype = RIB_EXT;
 1096             break;
 1097         default:
 1098             errx(1, "unknown route type");
 1099         }
 1100         break;
 1101     case IMSG_CTL_AREA:
 1102         area = imsg->data;
 1103         area_id = area->id;
 1104         break;
 1105     case IMSG_CTL_END:
 1106         printf("\n");
 1107         return (1);
 1108     default:
 1109         break;
 1110     }
 1111 
 1112     return (0);
 1113 }
 1114 
 1115 void
 1116 show_fib_head(void)
 1117 {
 1118     printf("flags: * = valid, O = OSPF, C = Connected, S = Static\n");
 1119     printf("%-6s %-4s %-20s %-17s\n", "Flags", "Prio", "Destination", "Nexthop");
 1120 }
 1121 
 1122 int
 1123 show_fib_msg(struct imsg *imsg)
 1124 {
 1125     struct kroute       *k;
 1126     char            *p;
 1127 
 1128     switch (imsg->hdr.type) {
 1129     case IMSG_CTL_KROUTE:
 1130         if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(struct kroute))
 1131             errx(1, "wrong imsg len");
 1132         k = imsg->data;
 1133 
 1134         if (k->flags & F_DOWN)
 1135             printf(" ");
 1136         else
 1137             printf("*");
 1138 
 1139         if (!(k->flags & F_KERNEL))
 1140             printf("O");
 1141         else if (k->flags & F_CONNECTED)
 1142             printf("C");
 1143         else if (k->flags & F_STATIC)
 1144             printf("S");
 1145         else
 1146             printf(" ");
 1147 
 1148         printf("     ");
 1149         printf("%4d ", k->priority);
 1150         if (asprintf(&p, "%s/%u", inet_ntoa(k->prefix), k->prefixlen) ==
 1151             -1)
 1152             err(1, NULL);
 1153         printf("%-20s ", p);
 1154         free(p);
 1155 
 1156         if (k->nexthop.s_addr)
 1157             printf("%s", inet_ntoa(k->nexthop));
 1158         else if (k->flags & F_CONNECTED)
 1159             printf("link#%u", k->ifindex);
 1160         printf("\n");
 1161 
 1162         break;
 1163     case IMSG_CTL_END:
 1164         printf("\n");
 1165         return (1);
 1166     default:
 1167         break;
 1168     }
 1169 
 1170     return (0);
 1171 }
 1172 
 1173 void
 1174 show_interface_head(void)
 1175 {
 1176     printf("%-15s%-15s%s\n", "Interface", "Flags",
 1177         "Link state");
 1178 }
 1179 
 1180 const int   ifm_status_valid_list[] = IFM_STATUS_VALID_LIST;
 1181 const struct ifmedia_status_description
 1182         ifm_status_descriptions[] = IFM_STATUS_DESCRIPTIONS;
 1183 const struct ifmedia_description
 1184         ifm_type_descriptions[] = IFM_TYPE_DESCRIPTIONS;
 1185 
 1186 const char *
 1187 get_media_descr(int media_type)
 1188 {
 1189     const struct ifmedia_description    *p;
 1190 
 1191     for (p = ifm_type_descriptions; p->ifmt_string != NULL; p++)
 1192         if (media_type == p->ifmt_word)
 1193             return (p->ifmt_string);
 1194 
 1195     return ("unknown");
 1196 }
 1197 
 1198 const char *
 1199 get_linkstate(int media_type, int link_state)
 1200 {
 1201     const struct ifmedia_status_description *p;
 1202     int                  i;
 1203 
 1204     if (link_state == LINK_STATE_UNKNOWN)
 1205         return ("unknown");
 1206 
 1207     for (i = 0; ifm_status_valid_list[i] != 0; i++)
 1208         for (p = ifm_status_descriptions; p->ifms_valid != 0; p++) {
 1209             if (p->ifms_type != media_type ||
 1210                 p->ifms_valid != ifm_status_valid_list[i])
 1211                 continue;
 1212             if (LINK_STATE_IS_UP(link_state))
 1213                 return (p->ifms_string[1]);
 1214             return (p->ifms_string[0]);
 1215         }
 1216 
 1217     return ("unknown");
 1218 }
 1219 
 1220 void
 1221 print_baudrate(u_int64_t baudrate)
 1222 {
 1223     if (baudrate > IF_Gbps(1))
 1224         printf("%llu GBit/s", baudrate / IF_Gbps(1));
 1225     else if (baudrate > IF_Mbps(1))
 1226         printf("%llu MBit/s", baudrate / IF_Mbps(1));
 1227     else if (baudrate > IF_Kbps(1))
 1228         printf("%llu KBit/s", baudrate / IF_Kbps(1));
 1229     else
 1230         printf("%llu Bit/s", baudrate);
 1231 }
 1232 
 1233 int
 1234 show_fib_interface_msg(struct imsg *imsg)
 1235 {
 1236     struct kif  *k;
 1237     int      ifms_type;
 1238 
 1239     switch (imsg->hdr.type) {
 1240     case IMSG_CTL_IFINFO:
 1241         k = imsg->data;
 1242         printf("%-15s", k->ifname);
 1243         printf("%-15s", k->flags & IFF_UP ? "UP" : "");
 1244         switch (k->media_type) {
 1245         case IFT_ETHER:
 1246             ifms_type = IFM_ETHER;
 1247             break;
 1248         case IFT_FDDI:
 1249             ifms_type = IFM_FDDI;
 1250             break;
 1251         case IFT_CARP:
 1252             ifms_type = IFM_CARP;
 1253             break;
 1254         default:
 1255             ifms_type = 0;
 1256             break;
 1257         }
 1258 
 1259         if (ifms_type)
 1260             printf("%s, %s", get_media_descr(ifms_type),
 1261                 get_linkstate(ifms_type, k->link_state));
 1262         else if (k->link_state == LINK_STATE_UNKNOWN)
 1263             printf("unknown");
 1264         else
 1265             printf("link state %u", k->link_state);
 1266 
 1267         if (k->link_state != LINK_STATE_DOWN && k->baudrate > 0) {
 1268             printf(", ");
 1269             print_baudrate(k->baudrate);
 1270         }
 1271         printf("\n");
 1272         break;
 1273     case IMSG_CTL_END:
 1274         printf("\n");
 1275         return (1);
 1276     default:
 1277         break;
 1278     }
 1279 
 1280     return (0);
 1281 }