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
= {.user
= NULL
,
53 /* The following includes are specific to this application. For
54 example it uses threads from libfrr, however your application is
55 free to use any thread library (like pthreads). */
57 #include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
61 /* Local portnumber for async channel. Note that OSPF API library will also
62 allocate a sync channel at ASYNCPORT+1. */
63 #define ASYNCPORT 4000
66 struct thread_master
*master
;
68 /* Global variables */
69 struct ospf_apiclient
*oclient
;
72 /* Our opaque LSAs have the following format. */
73 struct my_opaque_lsa
{
74 struct lsa_header hdr
; /* include common LSA header */
75 u_char data
[4]; /* our own data format then follows here */
79 /* ---------------------------------------------------------
80 * Threads for asynchronous messages and LSA update/delete
81 * ---------------------------------------------------------
84 static int lsa_delete(struct thread
*t
)
86 struct ospf_apiclient
*oclient
;
87 struct in_addr area_id
;
90 oclient
= THREAD_ARG(t
);
92 rc
= inet_aton(args
[6], &area_id
);
94 printf("Address Specified: %s is invalid\n", args
[6]);
98 printf("Deleting LSA... ");
99 rc
= ospf_apiclient_lsa_delete(oclient
, area_id
,
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
);
107 static int lsa_inject(struct thread
*t
)
109 struct ospf_apiclient
*cl
;
110 struct in_addr ifaddr
;
111 struct in_addr area_id
;
118 static u_int32_t counter
= 1; /* Incremented each time invoked */
123 rc
= inet_aton(args
[5], &ifaddr
);
125 printf("Ifaddr specified %s is invalid\n", args
[5]);
129 rc
= inet_aton(args
[6], &area_id
);
131 printf("Area ID specified %s is invalid\n", args
[6]);
134 lsa_type
= atoi(args
[2]);
135 opaque_type
= atoi(args
[3]);
136 opaque_id
= atoi(args
[4]);
137 opaquedata
= &counter
;
138 opaquelen
= sizeof(u_int32_t
);
140 printf("Originating/updating LSA with counter=%d... ", counter
);
141 rc
= ospf_apiclient_lsa_originate(cl
, ifaddr
, area_id
, lsa_type
,
142 opaque_type
, opaque_id
, opaquedata
,
145 printf("done, return code is %d\n", rc
);
153 /* This thread handles asynchronous messages coming in from the OSPF
155 static int lsa_read(struct thread
*thread
)
157 struct ospf_apiclient
*oclient
;
161 printf("lsa_read called\n");
163 oclient
= THREAD_ARG(thread
);
164 fd
= THREAD_FD(thread
);
166 /* Handle asynchronous message */
167 ret
= ospf_apiclient_handle_async(oclient
);
169 printf("Connection closed, exiting...");
173 /* Reschedule read thread */
174 thread_add_read(master
, lsa_read
, oclient
, fd
, NULL
);
179 /* ---------------------------------------------------------
180 * Callback functions for asynchronous events
181 * ---------------------------------------------------------
184 static void lsa_update_callback(struct in_addr ifaddr
, struct in_addr area_id
,
185 u_char is_self_originated
,
186 struct lsa_header
*lsa
)
188 printf("lsa_update_callback: ");
189 printf("ifaddr: %s ", inet_ntoa(ifaddr
));
190 printf("area: %s\n", inet_ntoa(area_id
));
191 printf("is_self_origin: %u\n", is_self_originated
);
193 /* It is important to note that lsa_header does indeed include the
194 header and the LSA payload. To access the payload, first check
195 the LSA type and then typecast lsa into the corresponding type,
198 if (lsa->type == OSPF_ROUTER_LSA) {
199 struct router_lsa *rl = (struct router_lsa) lsa;
201 u_int16_t links = rl->links;
206 ospf_lsa_header_dump(lsa
);
209 static void lsa_delete_callback(struct in_addr ifaddr
, struct in_addr area_id
,
210 u_char is_self_originated
,
211 struct lsa_header
*lsa
)
213 printf("lsa_delete_callback: ");
214 printf("ifaddr: %s ", inet_ntoa(ifaddr
));
215 printf("area: %s\n", inet_ntoa(area_id
));
216 printf("is_self_origin: %u\n", is_self_originated
);
218 ospf_lsa_header_dump(lsa
);
221 static void ready_callback(u_char lsa_type
, u_char opaque_type
,
224 printf("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
225 lsa_type
, opaque_type
, inet_ntoa(addr
));
227 /* Schedule opaque LSA originate in 5 secs */
228 thread_add_timer(master
, lsa_inject
, oclient
, 5, NULL
);
230 /* Schedule opaque LSA update with new value */
231 thread_add_timer(master
, lsa_inject
, oclient
, 10, NULL
);
233 /* Schedule delete */
234 thread_add_timer(master
, lsa_delete
, oclient
, 30, NULL
);
237 static void new_if_callback(struct in_addr ifaddr
, struct in_addr area_id
)
239 printf("new_if_callback: ifaddr: %s ", inet_ntoa(ifaddr
));
240 printf("area_id: %s\n", inet_ntoa(area_id
));
243 static void del_if_callback(struct in_addr ifaddr
)
245 printf("new_if_callback: ifaddr: %s\n ", inet_ntoa(ifaddr
));
248 static void ism_change_callback(struct in_addr ifaddr
, struct in_addr area_id
,
251 printf("ism_change: ifaddr: %s ", inet_ntoa(ifaddr
));
252 printf("area_id: %s\n", inet_ntoa(area_id
));
253 printf("state: %d [%s]\n", state
,
254 lookup_msg(ospf_ism_state_msg
, state
, NULL
));
257 static void nsm_change_callback(struct in_addr ifaddr
, struct in_addr nbraddr
,
258 struct in_addr router_id
, u_char state
)
260 printf("nsm_change: ifaddr: %s ", inet_ntoa(ifaddr
));
261 printf("nbraddr: %s\n", inet_ntoa(nbraddr
));
262 printf("router_id: %s\n", inet_ntoa(router_id
));
263 printf("state: %d [%s]\n", state
,
264 lookup_msg(ospf_nsm_state_msg
, state
, NULL
));
268 /* ---------------------------------------------------------
270 * ---------------------------------------------------------
273 static int usage(void)
275 printf("Usage: ospfclient <ospfd> <lsatype> <opaquetype> <opaqueid> <ifaddr> <areaid>\n");
276 printf("where ospfd : router where API-enabled OSPF daemon is running\n");
277 printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n");
278 printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n");
279 printf(" opaqueid : arbitrary application instance (24 bits)\n");
280 printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n");
281 printf(" areaid : area in IP address format (for type 10) otherwise ignored\n");
286 int main(int argc
, char *argv
[])
288 struct thread thread
;
292 /* ospfclient should be started with the following arguments:
294 * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
297 * host: name or IP of host where ospfd is running
298 * lsa_type: 9, 10, or 11
299 * opaque_type: 0-255 (e.g., experimental applications use > 128)
300 * opaque_id: arbitrary application instance (24 bits)
301 * if_addr: interface IP address (for type 9) otherwise ignored
302 * area_id: area in IP address format (for type 10) otherwise ignored
310 zprivs_preinit(&ospfd_privs
);
311 zprivs_init(&ospfd_privs
);
312 master
= thread_master_create(NULL
);
314 /* Open connection to OSPF daemon */
315 oclient
= ospf_apiclient_connect(args
[1], ASYNCPORT
);
317 printf("Connecting to OSPF daemon on %s failed!\n", args
[1]);
321 /* Register callback functions. */
322 ospf_apiclient_register_callback(
323 oclient
, ready_callback
, new_if_callback
, del_if_callback
,
324 ism_change_callback
, nsm_change_callback
, lsa_update_callback
,
325 lsa_delete_callback
);
327 /* Register LSA type and opaque type. */
328 ospf_apiclient_register_opaque_type(oclient
, atoi(args
[2]),
331 /* Synchronize database with OSPF daemon. */
332 ospf_apiclient_sync_lsdb(oclient
);
334 /* Schedule thread that handles asynchronous messages */
335 thread_add_read(master
, lsa_read
, oclient
, oclient
->fd_async
, NULL
);
337 /* Now connection is established, run loop */
339 thread_fetch(master
, &thread
);
340 thread_call(&thread
);