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