]> git.proxmox.com Git - mirror_frr.git/blob - ospfclient/ospfclient.c
*: reindent
[mirror_frr.git] / ospfclient / ospfclient.c
1 /* This file is part of Quagga.
2 *
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
6 * later version.
7 *
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.
12 *
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
16 * 02111-1307, USA.
17 */
18
19 /*
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.
25 */
26
27 /* The following includes are needed in all OSPF API client
28 applications. */
29
30 #include <zebra.h>
31 #include "prefix.h" /* needed by ospf_asbr.h */
32 #include "privs.h"
33 #include "log.h"
34
35 /* work around gcc bug 69981, disable MTYPEs in libospf */
36 #define _QUAGGA_OSPF_MEMORY_H
37
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"
44
45 /* privileges struct.
46 * set cap_num_* and uid/gid to nothing to use NULL privs
47 * as ospfapiclient links in libospf.a which uses privs.
48 */
49 struct zebra_privs_t ospfd_privs = {.user = NULL,
50 .group = NULL,
51 .cap_num_p = 0,
52 .cap_num_i = 0};
53
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). */
57
58 #include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
59 #include "thread.h"
60 #include "log.h"
61
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
65
66 /* Master thread */
67 struct thread_master *master;
68
69 /* Global variables */
70 struct ospf_apiclient *oclient;
71 char **args;
72
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 */
77 };
78
79
80 /* ---------------------------------------------------------
81 * Threads for asynchronous messages and LSA update/delete
82 * ---------------------------------------------------------
83 */
84
85 static int lsa_delete(struct thread *t)
86 {
87 struct ospf_apiclient *oclient;
88 struct in_addr area_id;
89 int rc;
90
91 oclient = THREAD_ARG(t);
92
93 inet_aton(args[6], &area_id);
94
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);
101 return rc;
102 }
103
104 static int lsa_inject(struct thread *t)
105 {
106 struct ospf_apiclient *cl;
107 struct in_addr ifaddr;
108 struct in_addr area_id;
109 u_char lsa_type;
110 u_char opaque_type;
111 u_int32_t opaque_id;
112 void *opaquedata;
113 int opaquelen;
114
115 static u_int32_t counter = 1; /* Incremented each time invoked */
116 int rc;
117
118 cl = THREAD_ARG(t);
119
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);
127
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,
131 opaquelen);
132
133 printf("done, return code is %d\n", rc);
134
135 counter++;
136
137 return 0;
138 }
139
140
141 /* This thread handles asynchronous messages coming in from the OSPF
142 API server */
143 static int lsa_read(struct thread *thread)
144 {
145 struct ospf_apiclient *oclient;
146 int fd;
147 int ret;
148
149 printf("lsa_read called\n");
150
151 oclient = THREAD_ARG(thread);
152 fd = THREAD_FD(thread);
153
154 /* Handle asynchronous message */
155 ret = ospf_apiclient_handle_async(oclient);
156 if (ret < 0) {
157 printf("Connection closed, exiting...");
158 exit(0);
159 }
160
161 /* Reschedule read thread */
162 thread_add_read(master, lsa_read, oclient, fd);
163
164 return 0;
165 }
166
167 /* ---------------------------------------------------------
168 * Callback functions for asynchronous events
169 * ---------------------------------------------------------
170 */
171
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)
175 {
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);
180
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,
184 e.g.:
185
186 if (lsa->type == OSPF_ROUTER_LSA) {
187 struct router_lsa *rl = (struct router_lsa) lsa;
188 ...
189 u_int16_t links = rl->links;
190 ...
191 }
192 */
193
194 ospf_lsa_header_dump(lsa);
195 }
196
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)
200 {
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);
205
206 ospf_lsa_header_dump(lsa);
207 }
208
209 static void ready_callback(u_char lsa_type, u_char opaque_type,
210 struct in_addr addr)
211 {
212 printf("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
213 lsa_type, opaque_type, inet_ntoa(addr));
214
215 /* Schedule opaque LSA originate in 5 secs */
216 thread_add_timer(master, lsa_inject, oclient, 5);
217
218 /* Schedule opaque LSA update with new value */
219 thread_add_timer(master, lsa_inject, oclient, 10);
220
221 /* Schedule delete */
222 thread_add_timer(master, lsa_delete, oclient, 30);
223 }
224
225 static void new_if_callback(struct in_addr ifaddr, struct in_addr area_id)
226 {
227 printf("new_if_callback: ifaddr: %s ", inet_ntoa(ifaddr));
228 printf("area_id: %s\n", inet_ntoa(area_id));
229 }
230
231 static void del_if_callback(struct in_addr ifaddr)
232 {
233 printf("new_if_callback: ifaddr: %s\n ", inet_ntoa(ifaddr));
234 }
235
236 static void ism_change_callback(struct in_addr ifaddr, struct in_addr area_id,
237 u_char state)
238 {
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));
243 }
244
245 static void nsm_change_callback(struct in_addr ifaddr, struct in_addr nbraddr,
246 struct in_addr router_id, u_char state)
247 {
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));
253 }
254
255
256 /* ---------------------------------------------------------
257 * Main program
258 * ---------------------------------------------------------
259 */
260
261 static int usage(void)
262 {
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");
270
271 exit(1);
272 }
273
274 int main(int argc, char *argv[])
275 {
276 struct thread thread;
277
278 args = argv;
279
280 /* ospfclient should be started with the following arguments:
281 *
282 * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
283 * (6) area_id
284 *
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
291 */
292
293 if (argc != 7) {
294 usage();
295 }
296
297 /* Initialization */
298 zprivs_init(&ospfd_privs);
299 master = thread_master_create();
300
301 /* Open connection to OSPF daemon */
302 oclient = ospf_apiclient_connect(args[1], ASYNCPORT);
303 if (!oclient) {
304 printf("Connecting to OSPF daemon on %s failed!\n", args[1]);
305 exit(1);
306 }
307
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);
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 thread_fetch(master, &thread);
327 thread_call(&thread);
328 }
329
330 /* Never reached */
331 return 0;
332 }