blob: ec1aabcbff29958c1609f4d33065af282824a833 [file] [log] [blame]
paul2d33f152003-03-17 01:10:58 +00001/*
paulf894c3a2003-04-09 07:26:33 +00002 * Simple program to demonstrate how OSPF API can be used. This
3 * application retrieves the LSDB from the OSPF daemon and then
4 * originates, updates and finally deletes an application-specific
5 * opaque LSA. You can use this application as a template when writing
6 * your own application.
paul2d33f152003-03-17 01:10:58 +00007 */
8
9/* The following includes are needed in all OSPF API client
paulf894c3a2003-04-09 07:26:33 +000010 applications. */
paul2d33f152003-03-17 01:10:58 +000011
12#include <zebra.h>
paulf894c3a2003-04-09 07:26:33 +000013#include "prefix.h" /* needed by ospf_asbr.h */
paul2d33f152003-03-17 01:10:58 +000014#include "ospfd/ospfd.h"
15#include "ospfd/ospf_asbr.h"
16#include "ospfd/ospf_lsa.h"
17#include "ospfd/ospf_opaque.h"
paul2d33f152003-03-17 01:10:58 +000018#include "ospfd/ospf_api.h"
19#include "ospf_apiclient.h"
20
paulf894c3a2003-04-09 07:26:33 +000021/* The following includes are specific to this application. For
22 example it uses threads from libzebra, however your application is
23 free to use any thread library (like pthreads). */
paul2d33f152003-03-17 01:10:58 +000024
paulf894c3a2003-04-09 07:26:33 +000025#include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
paul2d33f152003-03-17 01:10:58 +000026#include "thread.h"
27#include "log.h"
28
paulf894c3a2003-04-09 07:26:33 +000029/* Local portnumber for async channel. Note that OSPF API library will also
30 allocate a sync channel at ASYNCPORT+1. */
paul2d33f152003-03-17 01:10:58 +000031#define ASYNCPORT 4000
32
33/* Master thread */
34struct thread_master *master;
35
36/* Global variables */
37struct ospf_apiclient *oclient;
38char **args;
39
paulf894c3a2003-04-09 07:26:33 +000040/* Our opaque LSAs have the following format. */
paul2d33f152003-03-17 01:10:58 +000041struct my_opaque_lsa
42{
paulf894c3a2003-04-09 07:26:33 +000043 struct lsa_header hdr; /* include common LSA header */
44 u_char data[4]; /* our own data format then follows here */
paul2d33f152003-03-17 01:10:58 +000045};
46
47
48/* ---------------------------------------------------------
49 * Threads for asynchronous messages and LSA update/delete
50 * ---------------------------------------------------------
51 */
52
53int
54lsa_delete (struct thread *t)
55{
56 struct ospf_apiclient *oclient;
57 struct in_addr area_id;
58 int rc;
59
60 oclient = THREAD_ARG (t);
61
62 inet_aton (args[6], &area_id);
63
64 printf ("Deleting LSA... ");
65 rc = ospf_apiclient_lsa_delete (oclient,
66 area_id,
67 atoi (args[2]), /* lsa type */
68 atoi (args[3]), /* opaque type */
69 atoi (args[4])); /* opaque ID */
70 printf ("done, return code is = %d\n", rc);
71 return rc;
72}
73
74int
75lsa_inject (struct thread *t)
76{
77 struct ospf_apiclient *cl;
78 struct in_addr ifaddr;
79 struct in_addr area_id;
80 u_char lsa_type;
81 u_char opaque_type;
82 u_int32_t opaque_id;
83 void *opaquedata;
84 int opaquelen;
85
paulf894c3a2003-04-09 07:26:33 +000086 static u_int32_t counter = 1; /* Incremented each time invoked */
paul2d33f152003-03-17 01:10:58 +000087 int rc;
88
89 cl = THREAD_ARG (t);
90
91 inet_aton (args[5], &ifaddr);
92 inet_aton (args[6], &area_id);
93 lsa_type = atoi (args[2]);
94 opaque_type = atoi (args[3]);
95 opaque_id = atoi (args[4]);
96 opaquedata = &counter;
97 opaquelen = sizeof (u_int32_t);
98
99 printf ("Originating/updating LSA with counter=%d... ", counter);
100 rc = ospf_apiclient_lsa_originate(cl, ifaddr, area_id,
101 lsa_type,
102 opaque_type, opaque_id,
103 opaquedata, opaquelen);
104
105 printf ("done, return code is %d\n", rc);
106
107 counter++;
108
109 return 0;
110};
111
112
113/* This thread handles asynchronous messages coming in from the OSPF
114 API server */
115int
116lsa_read (struct thread *thread)
117{
118 struct ospf_apiclient *oclient;
119 int fd;
120 int ret;
121
122 printf ("lsa_read called\n");
123
124 oclient = THREAD_ARG (thread);
125 fd = THREAD_FD (thread);
126
127 /* Handle asynchronous message */
128 ret = ospf_apiclient_handle_async (oclient);
129 if (ret < 0) {
130 printf ("Connection closed, exiting...");
131 exit(0);
132 }
133
134 /* Reschedule read thread */
135 thread_add_read (master, lsa_read, oclient, fd);
136
137 return 0;
138}
139
paul2d33f152003-03-17 01:10:58 +0000140/* ---------------------------------------------------------
141 * Callback functions for asynchronous events
142 * ---------------------------------------------------------
143 */
144
145void
146lsa_update_callback (struct in_addr ifaddr, struct in_addr area_id,
147 u_char is_self_originated,
148 struct lsa_header *lsa)
149{
150 printf ("lsa_update_callback: ");
151 printf ("ifaddr: %s ", inet_ntoa (ifaddr));
152 printf ("area: %s\n", inet_ntoa (area_id));
153 printf ("is_self_origin: %u\n", is_self_originated);
154
paulf894c3a2003-04-09 07:26:33 +0000155 /* It is important to note that lsa_header does indeed include the
156 header and the LSA payload. To access the payload, first check
157 the LSA type and then typecast lsa into the corresponding type,
158 e.g.:
159
160 if (lsa->type == OSPF_ROUTER_LSA) {
161 struct router_lsa *rl = (struct router_lsa) lsa;
162 ...
163 u_int16_t links = rl->links;
164 ...
165 }
166 */
167
paul2d33f152003-03-17 01:10:58 +0000168 ospf_lsa_header_dump (lsa);
169}
170
171void
172lsa_delete_callback (struct in_addr ifaddr, struct in_addr area_id,
173 u_char is_self_originated,
174 struct lsa_header *lsa)
175{
176 printf ("lsa_delete_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);
180
181 ospf_lsa_header_dump (lsa);
182}
183
184void
185ready_callback (u_char lsa_type, u_char opaque_type, struct in_addr addr)
186{
187 printf ("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
188 lsa_type, opaque_type, inet_ntoa (addr));
189
190 /* Schedule opaque LSA originate in 5 secs */
191 thread_add_timer (master, lsa_inject, oclient, 5);
192
193 /* Schedule opaque LSA update with new value */
194 thread_add_timer (master, lsa_inject, oclient, 10);
195
196 /* Schedule delete */
197 thread_add_timer (master, lsa_delete, oclient, 30);
198}
199
200void
201new_if_callback (struct in_addr ifaddr, struct in_addr area_id)
202{
203 printf ("new_if_callback: ifaddr: %s ", inet_ntoa (ifaddr));
204 printf ("area_id: %s\n", inet_ntoa (area_id));
205}
206
207void
208del_if_callback (struct in_addr ifaddr)
209{
210 printf ("new_if_callback: ifaddr: %s\n ", inet_ntoa (ifaddr));
211}
212
213void
214ism_change_callback (struct in_addr ifaddr, struct in_addr area_id,
215 u_char state)
216{
217 printf ("ism_change: ifaddr: %s ", inet_ntoa (ifaddr));
218 printf ("area_id: %s\n", inet_ntoa (area_id));
219 printf ("state: %d [%s]\n", state, LOOKUP (ospf_ism_state_msg, state));
220}
221
222void
223nsm_change_callback (struct in_addr ifaddr, struct in_addr nbraddr,
224 struct in_addr router_id, u_char state)
225{
226 printf ("nsm_change: ifaddr: %s ", inet_ntoa (ifaddr));
227 printf ("nbraddr: %s\n", inet_ntoa (nbraddr));
228 printf ("router_id: %s\n", inet_ntoa (router_id));
229 printf ("state: %d [%s]\n", state, LOOKUP (ospf_nsm_state_msg, state));
230}
231
232
233/* ---------------------------------------------------------
234 * Main program
235 * ---------------------------------------------------------
236 */
237
paulf894c3a2003-04-09 07:26:33 +0000238int usage()
239{
240 printf("Usage: ospfclient <ospfd> <lsatype> <opaquetype> <opaqueid> <ifaddr> <areaid>\n");
241 printf("where ospfd : router where API-enabled OSPF daemon is running\n");
242 printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n");
243 printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n");
244 printf(" opaqueid : arbitrary application instance (24 bits)\n");
245 printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n");
246 printf(" areaid : area in IP address format (for type 10) otherwise ignored\n");
247
248 exit(1);
249}
250
paul2d33f152003-03-17 01:10:58 +0000251int
252main (int argc, char *argv[])
253{
254 struct thread thread;
255
256 args = argv;
257
paulf894c3a2003-04-09 07:26:33 +0000258 /* ospfclient should be started with the following arguments:
paul2d33f152003-03-17 01:10:58 +0000259 *
260 * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
261 * (6) area_id
262 *
263 * host: name or IP of host where ospfd is running
264 * lsa_type: 9, 10, or 11
paulf894c3a2003-04-09 07:26:33 +0000265 * opaque_type: 0-255 (e.g., experimental applications use > 128)
paul2d33f152003-03-17 01:10:58 +0000266 * opaque_id: arbitrary application instance (24 bits)
267 * if_addr: interface IP address (for type 9) otherwise ignored
268 * area_id: area in IP address format (for type 10) otherwise ignored
269 */
270
271 if (argc != 7)
272 {
paulf894c3a2003-04-09 07:26:33 +0000273 usage();
paul2d33f152003-03-17 01:10:58 +0000274 }
275
276 /* Initialization */
277 master = thread_master_create ();
278
279 /* Open connection to OSPF daemon */
280 oclient = ospf_apiclient_connect (args[1], ASYNCPORT);
281 if (!oclient)
282 {
paulf894c3a2003-04-09 07:26:33 +0000283 printf ("Connecting to OSPF daemon on %s failed!\n",
284 args[1]);
paul2d33f152003-03-17 01:10:58 +0000285 exit (1);
286 }
287
288 /* Register callback functions. */
289 ospf_apiclient_register_callback (oclient,
290 ready_callback,
291 new_if_callback,
292 del_if_callback,
293 ism_change_callback,
294 nsm_change_callback,
295 lsa_update_callback,
296 lsa_delete_callback);
297
298 /* Register LSA type and opaque type. */
299 ospf_apiclient_register_opaque_type (oclient, atoi (args[2]),
300 atoi (args[3]));
301
302 /* Synchronize database with OSPF daemon. */
303 ospf_apiclient_sync_lsdb (oclient);
304
305 /* Schedule thread that handles asynchronous messages */
306 thread_add_read (master, lsa_read, oclient, oclient->fd_async);
307
308 /* Now connection is established, run loop */
309 while (1)
310 {
311 thread_fetch (master, &thread);
312 thread_call (&thread);
313 }
314
315 /* Never reached */
316 return 0;
317}
318