blob: b00561555c8cc1c514529ef0dae7fa508290118e [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 */
pauledd7c242003-06-04 13:59:38 +000014#include "privs.h"
15
paul2d33f152003-03-17 01:10:58 +000016#include "ospfd/ospfd.h"
17#include "ospfd/ospf_asbr.h"
18#include "ospfd/ospf_lsa.h"
19#include "ospfd/ospf_opaque.h"
paul2d33f152003-03-17 01:10:58 +000020#include "ospfd/ospf_api.h"
21#include "ospf_apiclient.h"
22
pauledd7c242003-06-04 13:59:38 +000023/* privileges struct.
24 * set cap_num_* and uid/gid to nothing to use NULL privs
25 * as ospfapiclient links in libospf.a which uses privs.
26 */
27struct zebra_privs_t ospfd_privs =
28{
29 .user = NULL,
30 .group = NULL,
31 .cap_num_p = 0,
32 .cap_num_i = 0
33};
34
paulf894c3a2003-04-09 07:26:33 +000035/* The following includes are specific to this application. For
36 example it uses threads from libzebra, however your application is
37 free to use any thread library (like pthreads). */
paul2d33f152003-03-17 01:10:58 +000038
paulf894c3a2003-04-09 07:26:33 +000039#include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
paul2d33f152003-03-17 01:10:58 +000040#include "thread.h"
41#include "log.h"
42
paulf894c3a2003-04-09 07:26:33 +000043/* Local portnumber for async channel. Note that OSPF API library will also
44 allocate a sync channel at ASYNCPORT+1. */
paul2d33f152003-03-17 01:10:58 +000045#define ASYNCPORT 4000
46
47/* Master thread */
48struct thread_master *master;
49
50/* Global variables */
51struct ospf_apiclient *oclient;
52char **args;
53
paulf894c3a2003-04-09 07:26:33 +000054/* Our opaque LSAs have the following format. */
paul2d33f152003-03-17 01:10:58 +000055struct my_opaque_lsa
56{
paulf894c3a2003-04-09 07:26:33 +000057 struct lsa_header hdr; /* include common LSA header */
58 u_char data[4]; /* our own data format then follows here */
paul2d33f152003-03-17 01:10:58 +000059};
60
61
62/* ---------------------------------------------------------
63 * Threads for asynchronous messages and LSA update/delete
64 * ---------------------------------------------------------
65 */
66
paula0ace1e2005-11-24 12:40:39 +000067static int
paul2d33f152003-03-17 01:10:58 +000068lsa_delete (struct thread *t)
69{
70 struct ospf_apiclient *oclient;
71 struct in_addr area_id;
72 int rc;
73
74 oclient = THREAD_ARG (t);
75
76 inet_aton (args[6], &area_id);
77
78 printf ("Deleting LSA... ");
79 rc = ospf_apiclient_lsa_delete (oclient,
80 area_id,
81 atoi (args[2]), /* lsa type */
82 atoi (args[3]), /* opaque type */
83 atoi (args[4])); /* opaque ID */
84 printf ("done, return code is = %d\n", rc);
85 return rc;
86}
87
paula0ace1e2005-11-24 12:40:39 +000088static int
paul2d33f152003-03-17 01:10:58 +000089lsa_inject (struct thread *t)
90{
91 struct ospf_apiclient *cl;
92 struct in_addr ifaddr;
93 struct in_addr area_id;
94 u_char lsa_type;
95 u_char opaque_type;
96 u_int32_t opaque_id;
97 void *opaquedata;
98 int opaquelen;
99
paulf894c3a2003-04-09 07:26:33 +0000100 static u_int32_t counter = 1; /* Incremented each time invoked */
paul2d33f152003-03-17 01:10:58 +0000101 int rc;
102
103 cl = THREAD_ARG (t);
104
105 inet_aton (args[5], &ifaddr);
106 inet_aton (args[6], &area_id);
107 lsa_type = atoi (args[2]);
108 opaque_type = atoi (args[3]);
109 opaque_id = atoi (args[4]);
110 opaquedata = &counter;
111 opaquelen = sizeof (u_int32_t);
112
113 printf ("Originating/updating LSA with counter=%d... ", counter);
114 rc = ospf_apiclient_lsa_originate(cl, ifaddr, area_id,
115 lsa_type,
116 opaque_type, opaque_id,
117 opaquedata, opaquelen);
118
119 printf ("done, return code is %d\n", rc);
120
121 counter++;
122
123 return 0;
124};
125
126
127/* This thread handles asynchronous messages coming in from the OSPF
128 API server */
paula0ace1e2005-11-24 12:40:39 +0000129static int
paul2d33f152003-03-17 01:10:58 +0000130lsa_read (struct thread *thread)
131{
132 struct ospf_apiclient *oclient;
133 int fd;
134 int ret;
135
136 printf ("lsa_read called\n");
137
138 oclient = THREAD_ARG (thread);
139 fd = THREAD_FD (thread);
140
141 /* Handle asynchronous message */
142 ret = ospf_apiclient_handle_async (oclient);
143 if (ret < 0) {
144 printf ("Connection closed, exiting...");
145 exit(0);
146 }
147
148 /* Reschedule read thread */
149 thread_add_read (master, lsa_read, oclient, fd);
150
151 return 0;
152}
153
paul2d33f152003-03-17 01:10:58 +0000154/* ---------------------------------------------------------
155 * Callback functions for asynchronous events
156 * ---------------------------------------------------------
157 */
158
paula0ace1e2005-11-24 12:40:39 +0000159static void
paul2d33f152003-03-17 01:10:58 +0000160lsa_update_callback (struct in_addr ifaddr, struct in_addr area_id,
161 u_char is_self_originated,
162 struct lsa_header *lsa)
163{
164 printf ("lsa_update_callback: ");
165 printf ("ifaddr: %s ", inet_ntoa (ifaddr));
166 printf ("area: %s\n", inet_ntoa (area_id));
167 printf ("is_self_origin: %u\n", is_self_originated);
168
paulf894c3a2003-04-09 07:26:33 +0000169 /* It is important to note that lsa_header does indeed include the
170 header and the LSA payload. To access the payload, first check
171 the LSA type and then typecast lsa into the corresponding type,
172 e.g.:
173
174 if (lsa->type == OSPF_ROUTER_LSA) {
175 struct router_lsa *rl = (struct router_lsa) lsa;
176 ...
177 u_int16_t links = rl->links;
178 ...
179 }
180 */
181
paul2d33f152003-03-17 01:10:58 +0000182 ospf_lsa_header_dump (lsa);
183}
184
paula0ace1e2005-11-24 12:40:39 +0000185static void
paul2d33f152003-03-17 01:10:58 +0000186lsa_delete_callback (struct in_addr ifaddr, struct in_addr area_id,
187 u_char is_self_originated,
188 struct lsa_header *lsa)
189{
190 printf ("lsa_delete_callback: ");
191 printf ("ifaddr: %s ", inet_ntoa (ifaddr));
192 printf ("area: %s\n", inet_ntoa (area_id));
193 printf ("is_self_origin: %u\n", is_self_originated);
194
195 ospf_lsa_header_dump (lsa);
196}
197
paula0ace1e2005-11-24 12:40:39 +0000198static void
paul2d33f152003-03-17 01:10:58 +0000199ready_callback (u_char lsa_type, u_char opaque_type, struct in_addr addr)
200{
201 printf ("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
202 lsa_type, opaque_type, inet_ntoa (addr));
203
204 /* Schedule opaque LSA originate in 5 secs */
205 thread_add_timer (master, lsa_inject, oclient, 5);
206
207 /* Schedule opaque LSA update with new value */
208 thread_add_timer (master, lsa_inject, oclient, 10);
209
210 /* Schedule delete */
211 thread_add_timer (master, lsa_delete, oclient, 30);
212}
213
paula0ace1e2005-11-24 12:40:39 +0000214static void
paul2d33f152003-03-17 01:10:58 +0000215new_if_callback (struct in_addr ifaddr, struct in_addr area_id)
216{
217 printf ("new_if_callback: ifaddr: %s ", inet_ntoa (ifaddr));
218 printf ("area_id: %s\n", inet_ntoa (area_id));
219}
220
paula0ace1e2005-11-24 12:40:39 +0000221static void
paul2d33f152003-03-17 01:10:58 +0000222del_if_callback (struct in_addr ifaddr)
223{
224 printf ("new_if_callback: ifaddr: %s\n ", inet_ntoa (ifaddr));
225}
226
paula0ace1e2005-11-24 12:40:39 +0000227static void
paul2d33f152003-03-17 01:10:58 +0000228ism_change_callback (struct in_addr ifaddr, struct in_addr area_id,
229 u_char state)
230{
231 printf ("ism_change: ifaddr: %s ", inet_ntoa (ifaddr));
232 printf ("area_id: %s\n", inet_ntoa (area_id));
233 printf ("state: %d [%s]\n", state, LOOKUP (ospf_ism_state_msg, state));
234}
235
paula0ace1e2005-11-24 12:40:39 +0000236static void
paul2d33f152003-03-17 01:10:58 +0000237nsm_change_callback (struct in_addr ifaddr, struct in_addr nbraddr,
238 struct in_addr router_id, u_char state)
239{
240 printf ("nsm_change: ifaddr: %s ", inet_ntoa (ifaddr));
241 printf ("nbraddr: %s\n", inet_ntoa (nbraddr));
242 printf ("router_id: %s\n", inet_ntoa (router_id));
243 printf ("state: %d [%s]\n", state, LOOKUP (ospf_nsm_state_msg, state));
244}
245
246
247/* ---------------------------------------------------------
248 * Main program
249 * ---------------------------------------------------------
250 */
251
paula0ace1e2005-11-24 12:40:39 +0000252static int usage()
paulf894c3a2003-04-09 07:26:33 +0000253{
254 printf("Usage: ospfclient <ospfd> <lsatype> <opaquetype> <opaqueid> <ifaddr> <areaid>\n");
255 printf("where ospfd : router where API-enabled OSPF daemon is running\n");
256 printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n");
257 printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n");
258 printf(" opaqueid : arbitrary application instance (24 bits)\n");
259 printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n");
260 printf(" areaid : area in IP address format (for type 10) otherwise ignored\n");
261
262 exit(1);
263}
264
paul2d33f152003-03-17 01:10:58 +0000265int
266main (int argc, char *argv[])
267{
268 struct thread thread;
269
270 args = argv;
271
paulf894c3a2003-04-09 07:26:33 +0000272 /* ospfclient should be started with the following arguments:
paul2d33f152003-03-17 01:10:58 +0000273 *
274 * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
275 * (6) area_id
276 *
277 * host: name or IP of host where ospfd is running
278 * lsa_type: 9, 10, or 11
paulf894c3a2003-04-09 07:26:33 +0000279 * opaque_type: 0-255 (e.g., experimental applications use > 128)
paul2d33f152003-03-17 01:10:58 +0000280 * opaque_id: arbitrary application instance (24 bits)
281 * if_addr: interface IP address (for type 9) otherwise ignored
282 * area_id: area in IP address format (for type 10) otherwise ignored
283 */
284
285 if (argc != 7)
286 {
paulf894c3a2003-04-09 07:26:33 +0000287 usage();
paul2d33f152003-03-17 01:10:58 +0000288 }
289
290 /* Initialization */
pauledd7c242003-06-04 13:59:38 +0000291 zprivs_init (&ospfd_privs);
paul2d33f152003-03-17 01:10:58 +0000292 master = thread_master_create ();
293
294 /* Open connection to OSPF daemon */
295 oclient = ospf_apiclient_connect (args[1], ASYNCPORT);
296 if (!oclient)
297 {
paulf894c3a2003-04-09 07:26:33 +0000298 printf ("Connecting to OSPF daemon on %s failed!\n",
299 args[1]);
paul2d33f152003-03-17 01:10:58 +0000300 exit (1);
301 }
302
303 /* Register callback functions. */
304 ospf_apiclient_register_callback (oclient,
305 ready_callback,
306 new_if_callback,
307 del_if_callback,
308 ism_change_callback,
309 nsm_change_callback,
310 lsa_update_callback,
311 lsa_delete_callback);
312
313 /* Register LSA type and opaque type. */
314 ospf_apiclient_register_opaque_type (oclient, atoi (args[2]),
315 atoi (args[3]));
316
317 /* Synchronize database with OSPF daemon. */
318 ospf_apiclient_sync_lsdb (oclient);
319
320 /* Schedule thread that handles asynchronous messages */
321 thread_add_read (master, lsa_read, oclient, oclient->fd_async);
322
323 /* Now connection is established, run loop */
324 while (1)
325 {
326 thread_fetch (master, &thread);
327 thread_call (&thread);
328 }
329
330 /* Never reached */
331 return 0;
332}
333