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 */
33 #include "lib/printfrr.h"
35 /* work around gcc bug 69981, disable MTYPEs in libospf */
36 #define _QUAGGA_OSPF_MEMORY_H
38 #include "ospfd/ospfd.h"
39 #include "ospfd/ospf_asbr.h"
40 #include "ospfd/ospf_lsa.h"
41 #include "ospfd/ospf_opaque.h"
42 #include "ospfd/ospf_api.h"
43 #include "ospf_apiclient.h"
46 * set cap_num_* and uid/gid to nothing to use NULL privs
47 * as ospfapiclient links in libospf.a which uses privs.
49 struct zebra_privs_t ospfd_privs
= {.user
= NULL
,
54 /* The following includes are specific to this application. For
55 example it uses threads from libfrr, 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. */
74 struct my_opaque_lsa
{
75 struct lsa_header hdr
; /* include common LSA header */
76 uint8_t data
[4]; /* our own data format then follows here */
80 /* ---------------------------------------------------------
81 * Threads for asynchronous messages and LSA update/delete
82 * ---------------------------------------------------------
85 static int lsa_delete(struct thread
*t
)
87 struct ospf_apiclient
*oclient
;
88 struct in_addr area_id
;
91 oclient
= THREAD_ARG(t
);
93 rc
= inet_aton(args
[6], &area_id
);
95 printf("Address Specified: %s is invalid\n", args
[6]);
99 printf("Deleting LSA... ");
100 rc
= ospf_apiclient_lsa_delete(oclient
, area_id
,
101 atoi(args
[2]), /* lsa type */
102 atoi(args
[3]), /* opaque type */
103 atoi(args
[4])); /* opaque ID */
104 printf("done, return code is = %d\n", rc
);
108 static int lsa_inject(struct thread
*t
)
110 struct ospf_apiclient
*cl
;
111 struct in_addr ifaddr
;
112 struct in_addr area_id
;
119 static uint32_t counter
= 1; /* Incremented each time invoked */
124 rc
= inet_aton(args
[5], &ifaddr
);
126 printf("Ifaddr specified %s is invalid\n", args
[5]);
130 rc
= inet_aton(args
[6], &area_id
);
132 printf("Area ID specified %s is invalid\n", args
[6]);
135 lsa_type
= atoi(args
[2]);
136 opaque_type
= atoi(args
[3]);
137 opaque_id
= atoi(args
[4]);
138 opaquedata
= &counter
;
139 opaquelen
= sizeof(uint32_t);
141 printf("Originating/updating LSA with counter=%d... ", counter
);
142 rc
= ospf_apiclient_lsa_originate(cl
, ifaddr
, area_id
, lsa_type
,
143 opaque_type
, opaque_id
, opaquedata
,
146 printf("done, return code is %d\n", rc
);
154 /* This thread handles asynchronous messages coming in from the OSPF
156 static int lsa_read(struct thread
*thread
)
158 struct ospf_apiclient
*oclient
;
162 printf("lsa_read called\n");
164 oclient
= THREAD_ARG(thread
);
165 fd
= THREAD_FD(thread
);
167 /* Handle asynchronous message */
168 ret
= ospf_apiclient_handle_async(oclient
);
170 printf("Connection closed, exiting...");
174 /* Reschedule read thread */
175 thread_add_read(master
, lsa_read
, oclient
, fd
, NULL
);
180 /* ---------------------------------------------------------
181 * Callback functions for asynchronous events
182 * ---------------------------------------------------------
185 static void lsa_update_callback(struct in_addr ifaddr
, struct in_addr area_id
,
186 uint8_t is_self_originated
,
187 struct lsa_header
*lsa
)
189 printf("lsa_update_callback: ");
190 printfrr("ifaddr: %pI4 ", &ifaddr
);
191 printfrr("area: %pI4\n", &area_id
);
192 printf("is_self_origin: %u\n", is_self_originated
);
194 /* It is important to note that lsa_header does indeed include the
195 header and the LSA payload. To access the payload, first check
196 the LSA type and then typecast lsa into the corresponding type,
199 if (lsa->type == OSPF_ROUTER_LSA) {
200 struct router_lsa *rl = (struct router_lsa) lsa;
202 uint16_t links = rl->links;
207 ospf_lsa_header_dump(lsa
);
210 static void lsa_delete_callback(struct in_addr ifaddr
, struct in_addr area_id
,
211 uint8_t is_self_originated
,
212 struct lsa_header
*lsa
)
214 printf("lsa_delete_callback: ");
215 printf("ifaddr: %pI4 ", &ifaddr
);
216 printf("area: %pI4\n", &area_id
);
217 printf("is_self_origin: %u\n", is_self_originated
);
219 ospf_lsa_header_dump(lsa
);
222 static void ready_callback(uint8_t lsa_type
, uint8_t opaque_type
,
225 printfrr("ready_callback: lsa_type: %d opaque_type: %d addr=%pI4\n",
226 lsa_type
, opaque_type
, &addr
);
228 /* Schedule opaque LSA originate in 5 secs */
229 thread_add_timer(master
, lsa_inject
, oclient
, 5, NULL
);
231 /* Schedule opaque LSA update with new value */
232 thread_add_timer(master
, lsa_inject
, oclient
, 10, NULL
);
234 /* Schedule delete */
235 thread_add_timer(master
, lsa_delete
, oclient
, 30, NULL
);
238 static void new_if_callback(struct in_addr ifaddr
, struct in_addr area_id
)
240 printfrr("new_if_callback: ifaddr: %pI4 ", &ifaddr
);
241 printfrr("area_id: %pI4\n", &area_id
);
244 static void del_if_callback(struct in_addr ifaddr
)
246 printfrr("new_if_callback: ifaddr: %pI4\n ", &ifaddr
);
249 static void ism_change_callback(struct in_addr ifaddr
, struct in_addr area_id
,
252 printfrr("ism_change: ifaddr: %pI4 ", &ifaddr
);
253 printfrr("area_id: %pI4\n", &area_id
);
254 printf("state: %d [%s]\n", state
,
255 lookup_msg(ospf_ism_state_msg
, state
, NULL
));
258 static void nsm_change_callback(struct in_addr ifaddr
, struct in_addr nbraddr
,
259 struct in_addr router_id
, uint8_t state
)
261 printfrr("nsm_change: ifaddr: %pI4 ", &ifaddr
);
262 printfrr("nbraddr: %pI4\n", &nbraddr
);
263 printfrr("router_id: %pI4\n", &router_id
);
264 printf("state: %d [%s]\n", state
,
265 lookup_msg(ospf_nsm_state_msg
, state
, NULL
));
269 /* ---------------------------------------------------------
271 * ---------------------------------------------------------
274 static int usage(void)
276 printf("Usage: ospfclient <ospfd> <lsatype> <opaquetype> <opaqueid> <ifaddr> <areaid>\n");
277 printf("where ospfd : router where API-enabled OSPF daemon is running\n");
278 printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n");
279 printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n");
280 printf(" opaqueid : arbitrary application instance (24 bits)\n");
281 printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n");
282 printf(" areaid : area in IP address format (for type 10) otherwise ignored\n");
287 int main(int argc
, char *argv
[])
289 struct thread thread
;
293 /* ospfclient should be started with the following arguments:
295 * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
298 * host: name or IP of host where ospfd is running
299 * lsa_type: 9, 10, or 11
300 * opaque_type: 0-255 (e.g., experimental applications use > 128)
301 * opaque_id: arbitrary application instance (24 bits)
302 * if_addr: interface IP address (for type 9) otherwise ignored
303 * area_id: area in IP address format (for type 10) otherwise ignored
311 zprivs_preinit(&ospfd_privs
);
312 zprivs_init(&ospfd_privs
);
313 master
= thread_master_create(NULL
);
315 /* Open connection to OSPF daemon */
316 oclient
= ospf_apiclient_connect(args
[1], ASYNCPORT
);
318 printf("Connecting to OSPF daemon on %s failed!\n", args
[1]);
322 /* Register callback functions. */
323 ospf_apiclient_register_callback(
324 oclient
, ready_callback
, new_if_callback
, del_if_callback
,
325 ism_change_callback
, nsm_change_callback
, lsa_update_callback
,
326 lsa_delete_callback
);
328 /* Register LSA type and opaque type. */
329 ospf_apiclient_register_opaque_type(oclient
, atoi(args
[2]),
332 /* Synchronize database with OSPF daemon. */
333 ospf_apiclient_sync_lsdb(oclient
);
335 /* Schedule thread that handles asynchronous messages */
336 thread_add_read(master
, lsa_read
, oclient
, oclient
->fd_async
, NULL
);
338 /* Now connection is established, run loop */
340 thread_fetch(master
, &thread
);
341 thread_call(&thread
);