1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
|
/*
* Simple program to demonstrate how OSPF API can be used. This
* application retrieves the LSDB from the OSPF daemon and then
* originates, updates and finally deletes an application-specific
* opaque LSA. You can use this application as a template when writing
* your own application.
*/
/* The following includes are needed in all OSPF API client
applications. */
#include <zebra.h>
#include "prefix.h" /* needed by ospf_asbr.h */
#include "privs.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_asbr.h"
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_opaque.h"
#include "ospfd/ospf_api.h"
#include "ospf_apiclient.h"
/* privileges struct.
* set cap_num_* and uid/gid to nothing to use NULL privs
* as ospfapiclient links in libospf.a which uses privs.
*/
struct zebra_privs_t ospfd_privs =
{
.user = NULL,
.group = NULL,
.cap_num_p = 0,
.cap_num_i = 0
};
/* The following includes are specific to this application. For
example it uses threads from libzebra, however your application is
free to use any thread library (like pthreads). */
#include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
#include "thread.h"
#include "log.h"
/* Local portnumber for async channel. Note that OSPF API library will also
allocate a sync channel at ASYNCPORT+1. */
#define ASYNCPORT 4000
/* Master thread */
struct thread_master *master;
/* Global variables */
struct ospf_apiclient *oclient;
char **args;
/* Our opaque LSAs have the following format. */
struct my_opaque_lsa
{
struct lsa_header hdr; /* include common LSA header */
u_char data[4]; /* our own data format then follows here */
};
/* ---------------------------------------------------------
* Threads for asynchronous messages and LSA update/delete
* ---------------------------------------------------------
*/
static int
lsa_delete (struct thread *t)
{
struct ospf_apiclient *oclient;
struct in_addr area_id;
int rc;
oclient = THREAD_ARG (t);
inet_aton (args[6], &area_id);
printf ("Deleting LSA... ");
rc = ospf_apiclient_lsa_delete (oclient,
area_id,
atoi (args[2]), /* lsa type */
atoi (args[3]), /* opaque type */
atoi (args[4])); /* opaque ID */
printf ("done, return code is = %d\n", rc);
return rc;
}
static int
lsa_inject (struct thread *t)
{
struct ospf_apiclient *cl;
struct in_addr ifaddr;
struct in_addr area_id;
u_char lsa_type;
u_char opaque_type;
u_int32_t opaque_id;
void *opaquedata;
int opaquelen;
static u_int32_t counter = 1; /* Incremented each time invoked */
int rc;
cl = THREAD_ARG (t);
inet_aton (args[5], &ifaddr);
inet_aton (args[6], &area_id);
lsa_type = atoi (args[2]);
opaque_type = atoi (args[3]);
opaque_id = atoi (args[4]);
opaquedata = &counter;
opaquelen = sizeof (u_int32_t);
printf ("Originating/updating LSA with counter=%d... ", counter);
rc = ospf_apiclient_lsa_originate(cl, ifaddr, area_id,
lsa_type,
opaque_type, opaque_id,
opaquedata, opaquelen);
printf ("done, return code is %d\n", rc);
counter++;
return 0;
};
/* This thread handles asynchronous messages coming in from the OSPF
API server */
static int
lsa_read (struct thread *thread)
{
struct ospf_apiclient *oclient;
int fd;
int ret;
printf ("lsa_read called\n");
oclient = THREAD_ARG (thread);
fd = THREAD_FD (thread);
/* Handle asynchronous message */
ret = ospf_apiclient_handle_async (oclient);
if (ret < 0) {
printf ("Connection closed, exiting...");
exit(0);
}
/* Reschedule read thread */
thread_add_read (master, lsa_read, oclient, fd);
return 0;
}
/* ---------------------------------------------------------
* Callback functions for asynchronous events
* ---------------------------------------------------------
*/
static void
lsa_update_callback (struct in_addr ifaddr, struct in_addr area_id,
u_char is_self_originated,
struct lsa_header *lsa)
{
printf ("lsa_update_callback: ");
printf ("ifaddr: %s ", inet_ntoa (ifaddr));
printf ("area: %s\n", inet_ntoa (area_id));
printf ("is_self_origin: %u\n", is_self_originated);
/* It is important to note that lsa_header does indeed include the
header and the LSA payload. To access the payload, first check
the LSA type and then typecast lsa into the corresponding type,
e.g.:
if (lsa->type == OSPF_ROUTER_LSA) {
struct router_lsa *rl = (struct router_lsa) lsa;
...
u_int16_t links = rl->links;
...
}
*/
ospf_lsa_header_dump (lsa);
}
static void
lsa_delete_callback (struct in_addr ifaddr, struct in_addr area_id,
u_char is_self_originated,
struct lsa_header *lsa)
{
printf ("lsa_delete_callback: ");
printf ("ifaddr: %s ", inet_ntoa (ifaddr));
printf ("area: %s\n", inet_ntoa (area_id));
printf ("is_self_origin: %u\n", is_self_originated);
ospf_lsa_header_dump (lsa);
}
static void
ready_callback (u_char lsa_type, u_char opaque_type, struct in_addr addr)
{
printf ("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
lsa_type, opaque_type, inet_ntoa (addr));
/* Schedule opaque LSA originate in 5 secs */
thread_add_timer (master, lsa_inject, oclient, 5);
/* Schedule opaque LSA update with new value */
thread_add_timer (master, lsa_inject, oclient, 10);
/* Schedule delete */
thread_add_timer (master, lsa_delete, oclient, 30);
}
static void
new_if_callback (struct in_addr ifaddr, struct in_addr area_id)
{
printf ("new_if_callback: ifaddr: %s ", inet_ntoa (ifaddr));
printf ("area_id: %s\n", inet_ntoa (area_id));
}
static void
del_if_callback (struct in_addr ifaddr)
{
printf ("new_if_callback: ifaddr: %s\n ", inet_ntoa (ifaddr));
}
static void
ism_change_callback (struct in_addr ifaddr, struct in_addr area_id,
u_char state)
{
printf ("ism_change: ifaddr: %s ", inet_ntoa (ifaddr));
printf ("area_id: %s\n", inet_ntoa (area_id));
printf ("state: %d [%s]\n", state, LOOKUP (ospf_ism_state_msg, state));
}
static void
nsm_change_callback (struct in_addr ifaddr, struct in_addr nbraddr,
struct in_addr router_id, u_char state)
{
printf ("nsm_change: ifaddr: %s ", inet_ntoa (ifaddr));
printf ("nbraddr: %s\n", inet_ntoa (nbraddr));
printf ("router_id: %s\n", inet_ntoa (router_id));
printf ("state: %d [%s]\n", state, LOOKUP (ospf_nsm_state_msg, state));
}
/* ---------------------------------------------------------
* Main program
* ---------------------------------------------------------
*/
static int usage()
{
printf("Usage: ospfclient <ospfd> <lsatype> <opaquetype> <opaqueid> <ifaddr> <areaid>\n");
printf("where ospfd : router where API-enabled OSPF daemon is running\n");
printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n");
printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n");
printf(" opaqueid : arbitrary application instance (24 bits)\n");
printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n");
printf(" areaid : area in IP address format (for type 10) otherwise ignored\n");
exit(1);
}
int
main (int argc, char *argv[])
{
struct thread thread;
args = argv;
/* ospfclient should be started with the following arguments:
*
* (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
* (6) area_id
*
* host: name or IP of host where ospfd is running
* lsa_type: 9, 10, or 11
* opaque_type: 0-255 (e.g., experimental applications use > 128)
* opaque_id: arbitrary application instance (24 bits)
* if_addr: interface IP address (for type 9) otherwise ignored
* area_id: area in IP address format (for type 10) otherwise ignored
*/
if (argc != 7)
{
usage();
}
/* Initialization */
zprivs_init (&ospfd_privs);
master = thread_master_create ();
/* Open connection to OSPF daemon */
oclient = ospf_apiclient_connect (args[1], ASYNCPORT);
if (!oclient)
{
printf ("Connecting to OSPF daemon on %s failed!\n",
args[1]);
exit (1);
}
/* Register callback functions. */
ospf_apiclient_register_callback (oclient,
ready_callback,
new_if_callback,
del_if_callback,
ism_change_callback,
nsm_change_callback,
lsa_update_callback,
lsa_delete_callback);
/* Register LSA type and opaque type. */
ospf_apiclient_register_opaque_type (oclient, atoi (args[2]),
atoi (args[3]));
/* Synchronize database with OSPF daemon. */
ospf_apiclient_sync_lsdb (oclient);
/* Schedule thread that handles asynchronous messages */
thread_add_read (master, lsa_read, oclient, oclient->fd_async);
/* Now connection is established, run loop */
while (1)
{
thread_fetch (master, &thread);
thread_call (&thread);
}
/* Never reached */
return 0;
}
|