1 /* This file is part of Quagga.
 
   3  * Quagga is free software; you can redistribute it and/or modify it
 
   4  * under the terms of the GNU General Public License as published by the
 
   5  * Free Software Foundation; either version 2, or (at your option) any
 
   8  * Quagga is distributed in the hope that it will be useful, but
 
   9  * WITHOUT ANY WARRANTY; without even the implied warranty of
 
  10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
  11  * General Public License for more details.
 
  13  * You should have received a copy of the GNU General Public License
 
  14  * along with Quagga; see the file COPYING.  If not, write to the Free
 
  15  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
  20  * Simple program to demonstrate how OSPF API can be used. This
 
  21  * application retrieves the LSDB from the OSPF daemon and then
 
  22  * originates, updates and finally deletes an application-specific
 
  23  * opaque LSA. You can use this application as a template when writing
 
  24  * your own application.
 
  27 /* The following includes are needed in all OSPF API client
 
  31 #include "prefix.h" /* needed by ospf_asbr.h */
 
  35 #include "ospfd/ospfd.h"
 
  36 #include "ospfd/ospf_asbr.h"
 
  37 #include "ospfd/ospf_lsa.h"
 
  38 #include "ospfd/ospf_opaque.h"
 
  39 #include "ospfd/ospf_api.h"
 
  40 #include "ospf_apiclient.h"
 
  43  * set cap_num_* and uid/gid to nothing to use NULL privs
 
  44  * as ospfapiclient links in libospf.a which uses privs.
 
  46 struct zebra_privs_t ospfd_privs =
 
  54 /* The following includes are specific to this application. For
 
  55    example it uses threads from libzebra, however your application is
 
  56    free to use any thread library (like pthreads). */
 
  58 #include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
 
  62 /* Local portnumber for async channel. Note that OSPF API library will also
 
  63    allocate a sync channel at ASYNCPORT+1. */
 
  64 #define ASYNCPORT 4000
 
  67 struct thread_master *master;
 
  69 /* Global variables */
 
  70 struct ospf_apiclient *oclient;
 
  73 /* Our opaque LSAs have the following format. */
 
  76   struct lsa_header hdr; /* include common LSA header */
 
  77   u_char data[4]; /* our own data format then follows here */
 
  81 /* ---------------------------------------------------------
 
  82  * Threads for asynchronous messages and LSA update/delete 
 
  83  * ---------------------------------------------------------
 
  87 lsa_delete (struct thread *t)
 
  89   struct ospf_apiclient *oclient;
 
  90   struct in_addr area_id;
 
  93   oclient = THREAD_ARG (t);
 
  95   inet_aton (args[6], &area_id);
 
  97   printf ("Deleting LSA... ");
 
  98   rc = ospf_apiclient_lsa_delete (oclient, 
 
 100                                   atoi (args[2]),       /* lsa type */
 
 101                                   atoi (args[3]),       /* opaque type */
 
 102                                   atoi (args[4]));      /* opaque ID */
 
 103   printf ("done, return code is = %d\n", rc);
 
 108 lsa_inject (struct thread *t)
 
 110   struct ospf_apiclient *cl;
 
 111   struct in_addr ifaddr;
 
 112   struct in_addr area_id;
 
 119   static u_int32_t counter = 1; /* Incremented each time invoked */
 
 124   inet_aton (args[5], &ifaddr);
 
 125   inet_aton (args[6], &area_id);
 
 126   lsa_type = atoi (args[2]);
 
 127   opaque_type = atoi (args[3]);
 
 128   opaque_id = atoi (args[4]);
 
 129   opaquedata = &counter;
 
 130   opaquelen = sizeof (u_int32_t);
 
 132   printf ("Originating/updating LSA with counter=%d... ", counter);
 
 133   rc = ospf_apiclient_lsa_originate(cl, ifaddr, area_id,
 
 135                                     opaque_type, opaque_id,
 
 136                                     opaquedata, opaquelen);
 
 138   printf ("done, return code is %d\n", rc);
 
 146 /* This thread handles asynchronous messages coming in from the OSPF
 
 149 lsa_read (struct thread *thread)
 
 151   struct ospf_apiclient *oclient;
 
 155   printf ("lsa_read called\n");
 
 157   oclient = THREAD_ARG (thread);
 
 158   fd = THREAD_FD (thread);
 
 160   /* Handle asynchronous message */
 
 161   ret = ospf_apiclient_handle_async (oclient);
 
 163     printf ("Connection closed, exiting...");
 
 167   /* Reschedule read thread */
 
 168   thread_add_read (master, lsa_read, oclient, fd);
 
 173 /* ---------------------------------------------------------
 
 174  * Callback functions for asynchronous events 
 
 175  * ---------------------------------------------------------
 
 179 lsa_update_callback (struct in_addr ifaddr, struct in_addr area_id,
 
 180                      u_char is_self_originated,
 
 181                      struct lsa_header *lsa)
 
 183   printf ("lsa_update_callback: ");
 
 184   printf ("ifaddr: %s ", inet_ntoa (ifaddr));
 
 185   printf ("area: %s\n", inet_ntoa (area_id));
 
 186   printf ("is_self_origin: %u\n", is_self_originated);
 
 188   /* It is important to note that lsa_header does indeed include the
 
 189      header and the LSA payload. To access the payload, first check
 
 190      the LSA type and then typecast lsa into the corresponding type,
 
 193      if (lsa->type == OSPF_ROUTER_LSA) {
 
 194        struct router_lsa *rl = (struct router_lsa) lsa;
 
 196        u_int16_t links = rl->links;
 
 201   ospf_lsa_header_dump (lsa);
 
 205 lsa_delete_callback (struct in_addr ifaddr, struct in_addr area_id,
 
 206                      u_char is_self_originated,
 
 207                      struct lsa_header *lsa)
 
 209   printf ("lsa_delete_callback: ");
 
 210   printf ("ifaddr: %s ", inet_ntoa (ifaddr));
 
 211   printf ("area: %s\n", inet_ntoa (area_id));
 
 212   printf ("is_self_origin: %u\n", is_self_originated);
 
 214   ospf_lsa_header_dump (lsa);
 
 218 ready_callback (u_char lsa_type, u_char opaque_type, struct in_addr addr)
 
 220   printf ("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
 
 221           lsa_type, opaque_type, inet_ntoa (addr));
 
 223   /* Schedule opaque LSA originate in 5 secs */
 
 224   thread_add_timer (master, lsa_inject, oclient, 5);
 
 226   /* Schedule opaque LSA update with new value */
 
 227   thread_add_timer (master, lsa_inject, oclient, 10);
 
 229   /* Schedule delete */
 
 230   thread_add_timer (master, lsa_delete, oclient, 30);
 
 234 new_if_callback (struct in_addr ifaddr, struct in_addr area_id)
 
 236   printf ("new_if_callback: ifaddr: %s ", inet_ntoa (ifaddr));
 
 237   printf ("area_id: %s\n", inet_ntoa (area_id));
 
 241 del_if_callback (struct in_addr ifaddr)
 
 243   printf ("new_if_callback: ifaddr: %s\n ", inet_ntoa (ifaddr));
 
 247 ism_change_callback (struct in_addr ifaddr, struct in_addr area_id,
 
 250   printf ("ism_change: ifaddr: %s ", inet_ntoa (ifaddr));
 
 251   printf ("area_id: %s\n", inet_ntoa (area_id));
 
 252   printf ("state: %d [%s]\n", state, LOOKUP (ospf_ism_state_msg, state));
 
 256 nsm_change_callback (struct in_addr ifaddr, struct in_addr nbraddr,
 
 257                      struct in_addr router_id, u_char state)
 
 259   printf ("nsm_change: ifaddr: %s ", inet_ntoa (ifaddr));
 
 260   printf ("nbraddr: %s\n", inet_ntoa (nbraddr));
 
 261   printf ("router_id: %s\n", inet_ntoa (router_id));
 
 262   printf ("state: %d [%s]\n", state, LOOKUP (ospf_nsm_state_msg, state));
 
 266 /* ---------------------------------------------------------
 
 268  * ---------------------------------------------------------
 
 273   printf("Usage: ospfclient <ospfd> <lsatype> <opaquetype> <opaqueid> <ifaddr> <areaid>\n");
 
 274   printf("where ospfd     : router where API-enabled OSPF daemon is running\n");
 
 275   printf("      lsatype   : either 9, 10, or 11 depending on flooding scope\n");
 
 276   printf("      opaquetype: 0-255 (e.g., experimental applications use > 128)\n");
 
 277   printf("      opaqueid  : arbitrary application instance (24 bits)\n");
 
 278   printf("      ifaddr    : interface IP address (for type 9) otherwise ignored\n");
 
 279   printf("      areaid    : area in IP address format (for type 10) otherwise ignored\n");
 
 285 main (int argc, char *argv[])
 
 287   struct thread thread;
 
 291   /* ospfclient should be started with the following arguments:
 
 293    * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr 
 
 296    * host: name or IP of host where ospfd is running
 
 297    * lsa_type: 9, 10, or 11
 
 298    * opaque_type: 0-255 (e.g., experimental applications use > 128) 
 
 299    * opaque_id: arbitrary application instance (24 bits)
 
 300    * if_addr: interface IP address (for type 9) otherwise ignored
 
 301    * area_id: area in IP address format (for type 10) otherwise ignored
 
 310   zprivs_init (&ospfd_privs);
 
 311   master = thread_master_create ();
 
 313   /* Open connection to OSPF daemon */
 
 314   oclient = ospf_apiclient_connect (args[1], ASYNCPORT);
 
 317       printf ("Connecting to OSPF daemon on %s failed!\n",
 
 322   /* Register callback functions. */
 
 323   ospf_apiclient_register_callback (oclient,
 
 330                                     lsa_delete_callback);
 
 332   /* Register LSA type and opaque type. */
 
 333   ospf_apiclient_register_opaque_type (oclient, atoi (args[2]),
 
 336   /* Synchronize database with OSPF daemon. */
 
 337   ospf_apiclient_sync_lsdb (oclient);
 
 339   /* Schedule thread that handles asynchronous messages */
 
 340   thread_add_read (master, lsa_read, oclient, oclient->fd_async);
 
 342   /* Now connection is established, run loop */
 
 345       thread_fetch (master, &thread);
 
 346       thread_call (&thread);