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 /* 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 u_char 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 inet_aton(args
[6], &area_id
);
95 printf("Deleting LSA... ");
96 rc
= ospf_apiclient_lsa_delete(oclient
, area_id
,
97 atoi(args
[2]), /* lsa type */
98 atoi(args
[3]), /* opaque type */
99 atoi(args
[4])); /* opaque ID */
100 printf("done, return code is = %d\n", rc
);
104 static int lsa_inject(struct thread
*t
)
106 struct ospf_apiclient
*cl
;
107 struct in_addr ifaddr
;
108 struct in_addr area_id
;
115 static u_int32_t counter
= 1; /* Incremented each time invoked */
120 inet_aton(args
[5], &ifaddr
);
121 inet_aton(args
[6], &area_id
);
122 lsa_type
= atoi(args
[2]);
123 opaque_type
= atoi(args
[3]);
124 opaque_id
= atoi(args
[4]);
125 opaquedata
= &counter
;
126 opaquelen
= sizeof(u_int32_t
);
128 printf("Originating/updating LSA with counter=%d... ", counter
);
129 rc
= ospf_apiclient_lsa_originate(cl
, ifaddr
, area_id
, lsa_type
,
130 opaque_type
, opaque_id
, opaquedata
,
133 printf("done, return code is %d\n", rc
);
141 /* This thread handles asynchronous messages coming in from the OSPF
143 static int lsa_read(struct thread
*thread
)
145 struct ospf_apiclient
*oclient
;
149 printf("lsa_read called\n");
151 oclient
= THREAD_ARG(thread
);
152 fd
= THREAD_FD(thread
);
154 /* Handle asynchronous message */
155 ret
= ospf_apiclient_handle_async(oclient
);
157 printf("Connection closed, exiting...");
161 /* Reschedule read thread */
162 thread_add_read(master
, lsa_read
, oclient
, fd
);
167 /* ---------------------------------------------------------
168 * Callback functions for asynchronous events
169 * ---------------------------------------------------------
172 static void lsa_update_callback(struct in_addr ifaddr
, struct in_addr area_id
,
173 u_char is_self_originated
,
174 struct lsa_header
*lsa
)
176 printf("lsa_update_callback: ");
177 printf("ifaddr: %s ", inet_ntoa(ifaddr
));
178 printf("area: %s\n", inet_ntoa(area_id
));
179 printf("is_self_origin: %u\n", is_self_originated
);
181 /* It is important to note that lsa_header does indeed include the
182 header and the LSA payload. To access the payload, first check
183 the LSA type and then typecast lsa into the corresponding type,
186 if (lsa->type == OSPF_ROUTER_LSA) {
187 struct router_lsa *rl = (struct router_lsa) lsa;
189 u_int16_t links = rl->links;
194 ospf_lsa_header_dump(lsa
);
197 static void lsa_delete_callback(struct in_addr ifaddr
, struct in_addr area_id
,
198 u_char is_self_originated
,
199 struct lsa_header
*lsa
)
201 printf("lsa_delete_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 ospf_lsa_header_dump(lsa
);
209 static void ready_callback(u_char lsa_type
, u_char opaque_type
,
212 printf("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
213 lsa_type
, opaque_type
, inet_ntoa(addr
));
215 /* Schedule opaque LSA originate in 5 secs */
216 thread_add_timer(master
, lsa_inject
, oclient
, 5);
218 /* Schedule opaque LSA update with new value */
219 thread_add_timer(master
, lsa_inject
, oclient
, 10);
221 /* Schedule delete */
222 thread_add_timer(master
, lsa_delete
, oclient
, 30);
225 static void new_if_callback(struct in_addr ifaddr
, struct in_addr area_id
)
227 printf("new_if_callback: ifaddr: %s ", inet_ntoa(ifaddr
));
228 printf("area_id: %s\n", inet_ntoa(area_id
));
231 static void del_if_callback(struct in_addr ifaddr
)
233 printf("new_if_callback: ifaddr: %s\n ", inet_ntoa(ifaddr
));
236 static void ism_change_callback(struct in_addr ifaddr
, struct in_addr area_id
,
239 printf("ism_change: ifaddr: %s ", inet_ntoa(ifaddr
));
240 printf("area_id: %s\n", inet_ntoa(area_id
));
241 printf("state: %d [%s]\n", state
,
242 lookup_msg(ospf_ism_state_msg
, state
, NULL
));
245 static void nsm_change_callback(struct in_addr ifaddr
, struct in_addr nbraddr
,
246 struct in_addr router_id
, u_char state
)
248 printf("nsm_change: ifaddr: %s ", inet_ntoa(ifaddr
));
249 printf("nbraddr: %s\n", inet_ntoa(nbraddr
));
250 printf("router_id: %s\n", inet_ntoa(router_id
));
251 printf("state: %d [%s]\n", state
,
252 lookup_msg(ospf_nsm_state_msg
, state
, NULL
));
256 /* ---------------------------------------------------------
258 * ---------------------------------------------------------
261 static int usage(void)
263 printf("Usage: ospfclient <ospfd> <lsatype> <opaquetype> <opaqueid> <ifaddr> <areaid>\n");
264 printf("where ospfd : router where API-enabled OSPF daemon is running\n");
265 printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n");
266 printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n");
267 printf(" opaqueid : arbitrary application instance (24 bits)\n");
268 printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n");
269 printf(" areaid : area in IP address format (for type 10) otherwise ignored\n");
274 int main(int argc
, char *argv
[])
276 struct thread thread
;
280 /* ospfclient should be started with the following arguments:
282 * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
285 * host: name or IP of host where ospfd is running
286 * lsa_type: 9, 10, or 11
287 * opaque_type: 0-255 (e.g., experimental applications use > 128)
288 * opaque_id: arbitrary application instance (24 bits)
289 * if_addr: interface IP address (for type 9) otherwise ignored
290 * area_id: area in IP address format (for type 10) otherwise ignored
298 zprivs_init(&ospfd_privs
);
299 master
= thread_master_create();
301 /* Open connection to OSPF daemon */
302 oclient
= ospf_apiclient_connect(args
[1], ASYNCPORT
);
304 printf("Connecting to OSPF daemon on %s failed!\n", args
[1]);
308 /* Register callback functions. */
309 ospf_apiclient_register_callback(
310 oclient
, ready_callback
, new_if_callback
, del_if_callback
,
311 ism_change_callback
, nsm_change_callback
, lsa_update_callback
,
312 lsa_delete_callback
);
314 /* Register LSA type and opaque type. */
315 ospf_apiclient_register_opaque_type(oclient
, atoi(args
[2]),
318 /* Synchronize database with OSPF daemon. */
319 ospf_apiclient_sync_lsdb(oclient
);
321 /* Schedule thread that handles asynchronous messages */
322 thread_add_read(master
, lsa_read
, oclient
, oclient
->fd_async
);
324 /* Now connection is established, run loop */
326 thread_fetch(master
, &thread
);
327 thread_call(&thread
);