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[])
289 /* ospfclient should be started with the following arguments:
291 * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
294 * host: name or IP of host where ospfd is running
295 * lsa_type: 9, 10, or 11
296 * opaque_type: 0-255 (e.g., experimental applications use > 128)
297 * opaque_id: arbitrary application instance (24 bits)
298 * if_addr: interface IP address (for type 9) otherwise ignored
299 * area_id: area in IP address format (for type 10) otherwise ignored
308 zprivs_init (&ospfd_privs);
309 master = thread_master_create ();
311 /* Open connection to OSPF daemon */
312 oclient = ospf_apiclient_connect (args[1], ASYNCPORT);
315 printf ("Connecting to OSPF daemon on %s failed!\n",
320 /* Register callback functions. */
321 ospf_apiclient_register_callback (oclient,
328 lsa_delete_callback);
330 /* Register LSA type and opaque type. */
331 ospf_apiclient_register_opaque_type (oclient, atoi (args[2]),
334 /* Synchronize database with OSPF daemon. */
335 ospf_apiclient_sync_lsdb (oclient);
337 /* Schedule thread that handles asynchronous messages */
338 thread_add_read (master, lsa_read, oclient, oclient->fd_async);
340 /* Now connection is established, run loop */
341 thread_main (master);