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 along
14 * with this program; see the file COPYING; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Simple program to demonstrate how OSPF API can be used. This
20 * application retrieves the LSDB from the OSPF daemon and then
21 * originates, updates and finally deletes an application-specific
22 * opaque LSA. You can use this application as a template when writing
23 * your own application.
26 /* The following includes are needed in all OSPF API client
30 #include "prefix.h" /* needed by ospf_asbr.h */
34 /* work around gcc bug 69981, disable MTYPEs in libospf */
35 #define _QUAGGA_OSPF_MEMORY_H
37 #include "ospfd/ospfd.h"
38 #include "ospfd/ospf_asbr.h"
39 #include "ospfd/ospf_lsa.h"
40 #include "ospfd/ospf_opaque.h"
41 #include "ospfd/ospf_api.h"
42 #include "ospf_apiclient.h"
45 * set cap_num_* and uid/gid to nothing to use NULL privs
46 * as ospfapiclient links in libospf.a which uses privs.
48 struct zebra_privs_t ospfd_privs
=
56 /* The following includes are specific to this application. For
57 example it uses threads from libfrr, however your application is
58 free to use any thread library (like pthreads). */
60 #include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
64 /* Local portnumber for async channel. Note that OSPF API library will also
65 allocate a sync channel at ASYNCPORT+1. */
66 #define ASYNCPORT 4000
69 struct thread_master
*master
;
71 /* Global variables */
72 struct ospf_apiclient
*oclient
;
75 /* Our opaque LSAs have the following format. */
78 struct lsa_header hdr
; /* include common LSA header */
79 u_char data
[4]; /* our own data format then follows here */
83 /* ---------------------------------------------------------
84 * Threads for asynchronous messages and LSA update/delete
85 * ---------------------------------------------------------
89 lsa_delete (struct thread
*t
)
91 struct ospf_apiclient
*oclient
;
92 struct in_addr area_id
;
95 oclient
= THREAD_ARG (t
);
97 rc
= inet_aton (args
[6], &area_id
);
100 printf("Address Specified: %s is invalid\n", args
[6]);
104 printf ("Deleting LSA... ");
105 rc
= ospf_apiclient_lsa_delete (oclient
,
107 atoi (args
[2]), /* lsa type */
108 atoi (args
[3]), /* opaque type */
109 atoi (args
[4])); /* opaque ID */
110 printf ("done, return code is = %d\n", rc
);
115 lsa_inject (struct thread
*t
)
117 struct ospf_apiclient
*cl
;
118 struct in_addr ifaddr
;
119 struct in_addr area_id
;
126 static u_int32_t counter
= 1; /* Incremented each time invoked */
131 rc
= inet_aton (args
[5], &ifaddr
);
134 printf ("Ifaddr specified %s is invalid\n", args
[5]);
138 rc
= inet_aton (args
[6], &area_id
);
141 printf( "Area ID specified %s is invalid\n", args
[6]);
144 lsa_type
= atoi (args
[2]);
145 opaque_type
= atoi (args
[3]);
146 opaque_id
= atoi (args
[4]);
147 opaquedata
= &counter
;
148 opaquelen
= sizeof (u_int32_t
);
150 printf ("Originating/updating LSA with counter=%d... ", counter
);
151 rc
= ospf_apiclient_lsa_originate(cl
, ifaddr
, area_id
,
153 opaque_type
, opaque_id
,
154 opaquedata
, opaquelen
);
156 printf ("done, return code is %d\n", rc
);
164 /* This thread handles asynchronous messages coming in from the OSPF
167 lsa_read (struct thread
*thread
)
169 struct ospf_apiclient
*oclient
;
173 printf ("lsa_read called\n");
175 oclient
= THREAD_ARG (thread
);
176 fd
= THREAD_FD (thread
);
178 /* Handle asynchronous message */
179 ret
= ospf_apiclient_handle_async (oclient
);
181 printf ("Connection closed, exiting...");
185 /* Reschedule read thread */
186 thread_add_read(master
, lsa_read
, oclient
, fd
, NULL
);
191 /* ---------------------------------------------------------
192 * Callback functions for asynchronous events
193 * ---------------------------------------------------------
197 lsa_update_callback (struct in_addr ifaddr
, struct in_addr area_id
,
198 u_char is_self_originated
,
199 struct lsa_header
*lsa
)
201 printf ("lsa_update_callback: ");
202 printf ("ifaddr: %s ", inet_ntoa (ifaddr
));
203 printf ("area: %s\n", inet_ntoa (area_id
));
204 printf ("is_self_origin: %u\n", is_self_originated
);
206 /* It is important to note that lsa_header does indeed include the
207 header and the LSA payload. To access the payload, first check
208 the LSA type and then typecast lsa into the corresponding type,
211 if (lsa->type == OSPF_ROUTER_LSA) {
212 struct router_lsa *rl = (struct router_lsa) lsa;
214 u_int16_t links = rl->links;
219 ospf_lsa_header_dump (lsa
);
223 lsa_delete_callback (struct in_addr ifaddr
, struct in_addr area_id
,
224 u_char is_self_originated
,
225 struct lsa_header
*lsa
)
227 printf ("lsa_delete_callback: ");
228 printf ("ifaddr: %s ", inet_ntoa (ifaddr
));
229 printf ("area: %s\n", inet_ntoa (area_id
));
230 printf ("is_self_origin: %u\n", is_self_originated
);
232 ospf_lsa_header_dump (lsa
);
236 ready_callback (u_char lsa_type
, u_char opaque_type
, struct in_addr addr
)
238 printf ("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
239 lsa_type
, opaque_type
, inet_ntoa (addr
));
241 /* Schedule opaque LSA originate in 5 secs */
242 thread_add_timer(master
, lsa_inject
, oclient
, 5, NULL
);
244 /* Schedule opaque LSA update with new value */
245 thread_add_timer(master
, lsa_inject
, oclient
, 10, NULL
);
247 /* Schedule delete */
248 thread_add_timer(master
, lsa_delete
, oclient
, 30, NULL
);
252 new_if_callback (struct in_addr ifaddr
, struct in_addr area_id
)
254 printf ("new_if_callback: ifaddr: %s ", inet_ntoa (ifaddr
));
255 printf ("area_id: %s\n", inet_ntoa (area_id
));
259 del_if_callback (struct in_addr ifaddr
)
261 printf ("new_if_callback: ifaddr: %s\n ", inet_ntoa (ifaddr
));
265 ism_change_callback (struct in_addr ifaddr
, struct in_addr area_id
,
268 printf ("ism_change: ifaddr: %s ", inet_ntoa (ifaddr
));
269 printf ("area_id: %s\n", inet_ntoa (area_id
));
270 printf ("state: %d [%s]\n", state
, lookup_msg(ospf_ism_state_msg
, state
, NULL
));
274 nsm_change_callback (struct in_addr ifaddr
, struct in_addr nbraddr
,
275 struct in_addr router_id
, u_char state
)
277 printf ("nsm_change: ifaddr: %s ", inet_ntoa (ifaddr
));
278 printf ("nbraddr: %s\n", inet_ntoa (nbraddr
));
279 printf ("router_id: %s\n", inet_ntoa (router_id
));
280 printf ("state: %d [%s]\n", state
, lookup_msg(ospf_nsm_state_msg
, state
, NULL
));
284 /* ---------------------------------------------------------
286 * ---------------------------------------------------------
289 static int usage(void)
291 printf("Usage: ospfclient <ospfd> <lsatype> <opaquetype> <opaqueid> <ifaddr> <areaid>\n");
292 printf("where ospfd : router where API-enabled OSPF daemon is running\n");
293 printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n");
294 printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n");
295 printf(" opaqueid : arbitrary application instance (24 bits)\n");
296 printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n");
297 printf(" areaid : area in IP address format (for type 10) otherwise ignored\n");
303 main (int argc
, char *argv
[])
305 struct thread thread
;
309 /* ospfclient should be started with the following arguments:
311 * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
314 * host: name or IP of host where ospfd is running
315 * lsa_type: 9, 10, or 11
316 * opaque_type: 0-255 (e.g., experimental applications use > 128)
317 * opaque_id: arbitrary application instance (24 bits)
318 * if_addr: interface IP address (for type 9) otherwise ignored
319 * area_id: area in IP address format (for type 10) otherwise ignored
328 zprivs_init (&ospfd_privs
);
329 master
= thread_master_create ();
331 /* Open connection to OSPF daemon */
332 oclient
= ospf_apiclient_connect (args
[1], ASYNCPORT
);
335 printf ("Connecting to OSPF daemon on %s failed!\n",
340 /* Register callback functions. */
341 ospf_apiclient_register_callback (oclient
,
348 lsa_delete_callback
);
350 /* Register LSA type and opaque type. */
351 ospf_apiclient_register_opaque_type (oclient
, atoi (args
[2]),
354 /* Synchronize database with OSPF daemon. */
355 ospf_apiclient_sync_lsdb (oclient
);
357 /* Schedule thread that handles asynchronous messages */
358 thread_add_read(master
, lsa_read
, oclient
, oclient
->fd_async
, NULL
);
360 /* Now connection is established, run loop */
363 thread_fetch (master
, &thread
);
364 thread_call (&thread
);