]> git.proxmox.com Git - mirror_frr.git/blob - ospfclient/ospfclient.c
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[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 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
16 */
17
18 /*
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.
24 */
25
26 /* The following includes are needed in all OSPF API client
27 applications. */
28
29 #include <zebra.h>
30 #include "prefix.h" /* needed by ospf_asbr.h */
31 #include "privs.h"
32 #include "log.h"
33 #include "lib/printfrr.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 uint8_t 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 void 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 rc = inet_aton(args[6], &area_id);
94 if (rc <= 0) {
95 printf("Address Specified: %s is invalid\n", args[6]);
96 return;
97 }
98
99 printf("Deleting LSA... ");
100 rc = ospf_apiclient_lsa_delete(oclient, area_id,
101 atoi(args[2]), /* lsa type */
102 atoi(args[3]), /* opaque type */
103 atoi(args[4]), /* opaque ID */
104 0); /* send data in withdrawals */
105 printf("done, return code is = %d\n", rc);
106 }
107
108 static void lsa_inject(struct thread *t)
109 {
110 struct ospf_apiclient *cl;
111 struct in_addr ifaddr;
112 struct in_addr area_id;
113 uint8_t lsa_type;
114 uint8_t opaque_type;
115 uint32_t opaque_id;
116 void *opaquedata;
117 int opaquelen;
118
119 static uint32_t counter = 1; /* Incremented each time invoked */
120 int rc;
121
122 cl = THREAD_ARG(t);
123
124 rc = inet_aton(args[5], &ifaddr);
125 if (rc <= 0) {
126 printf("Ifaddr specified %s is invalid\n", args[5]);
127 return;
128 }
129
130 rc = inet_aton(args[6], &area_id);
131 if (rc <= 0) {
132 printf("Area ID specified %s is invalid\n", args[6]);
133 return;
134 }
135 lsa_type = atoi(args[2]);
136 opaque_type = atoi(args[3]);
137 opaque_id = atoi(args[4]);
138 opaquedata = &counter;
139 opaquelen = sizeof(uint32_t);
140
141 printf("Originating/updating LSA with counter=%d... ", counter);
142 rc = ospf_apiclient_lsa_originate(cl, ifaddr, area_id, lsa_type,
143 opaque_type, opaque_id, opaquedata,
144 opaquelen);
145
146 printf("done, return code is %d\n", rc);
147
148 counter++;
149 }
150
151
152 /* This thread handles asynchronous messages coming in from the OSPF
153 API server */
154 static void lsa_read(struct thread *thread)
155 {
156 struct ospf_apiclient *oclient;
157 int fd;
158 int ret;
159
160 printf("lsa_read called\n");
161
162 oclient = THREAD_ARG(thread);
163 fd = THREAD_FD(thread);
164
165 /* Handle asynchronous message */
166 ret = ospf_apiclient_handle_async(oclient);
167 if (ret < 0) {
168 printf("Connection closed, exiting...");
169 exit(0);
170 }
171
172 /* Reschedule read thread */
173 thread_add_read(master, lsa_read, oclient, fd, NULL);
174 }
175
176 /* ---------------------------------------------------------
177 * Callback functions for asynchronous events
178 * ---------------------------------------------------------
179 */
180
181 static void lsa_update_callback(struct in_addr ifaddr, struct in_addr area_id,
182 uint8_t is_self_originated,
183 struct lsa_header *lsa)
184 {
185 printf("lsa_update_callback: ");
186 printfrr("ifaddr: %pI4 ", &ifaddr);
187 printfrr("area: %pI4\n", &area_id);
188 printf("is_self_origin: %u\n", is_self_originated);
189
190 /* It is important to note that lsa_header does indeed include the
191 header and the LSA payload. To access the payload, first check
192 the LSA type and then typecast lsa into the corresponding type,
193 e.g.:
194
195 if (lsa->type == OSPF_ROUTER_LSA) {
196 struct router_lsa *rl = (struct router_lsa) lsa;
197 ...
198 uint16_t links = rl->links;
199 ...
200 }
201 */
202
203 ospf_lsa_header_dump(lsa);
204 }
205
206 static void lsa_delete_callback(struct in_addr ifaddr, struct in_addr area_id,
207 uint8_t is_self_originated,
208 struct lsa_header *lsa)
209 {
210 printf("lsa_delete_callback: ");
211 printf("ifaddr: %pI4 ", &ifaddr);
212 printf("area: %pI4\n", &area_id);
213 printf("is_self_origin: %u\n", is_self_originated);
214
215 ospf_lsa_header_dump(lsa);
216 }
217
218 static void ready_callback(uint8_t lsa_type, uint8_t opaque_type,
219 struct in_addr addr)
220 {
221 printfrr("ready_callback: lsa_type: %d opaque_type: %d addr=%pI4\n",
222 lsa_type, opaque_type, &addr);
223
224 /* Schedule opaque LSA originate in 5 secs */
225 thread_add_timer(master, lsa_inject, oclient, 5, NULL);
226
227 /* Schedule opaque LSA update with new value */
228 thread_add_timer(master, lsa_inject, oclient, 10, NULL);
229
230 /* Schedule delete */
231 thread_add_timer(master, lsa_delete, oclient, 30, NULL);
232 }
233
234 static void new_if_callback(struct in_addr ifaddr, struct in_addr area_id)
235 {
236 printfrr("new_if_callback: ifaddr: %pI4 ", &ifaddr);
237 printfrr("area_id: %pI4\n", &area_id);
238 }
239
240 static void del_if_callback(struct in_addr ifaddr)
241 {
242 printfrr("new_if_callback: ifaddr: %pI4\n ", &ifaddr);
243 }
244
245 static void ism_change_callback(struct in_addr ifaddr, struct in_addr area_id,
246 uint8_t state)
247 {
248 printfrr("ism_change: ifaddr: %pI4 ", &ifaddr);
249 printfrr("area_id: %pI4\n", &area_id);
250 printf("state: %d [%s]\n", state,
251 lookup_msg(ospf_ism_state_msg, state, NULL));
252 }
253
254 static void nsm_change_callback(struct in_addr ifaddr, struct in_addr nbraddr,
255 struct in_addr router_id, uint8_t state)
256 {
257 printfrr("nsm_change: ifaddr: %pI4 ", &ifaddr);
258 printfrr("nbraddr: %pI4\n", &nbraddr);
259 printfrr("router_id: %pI4\n", &router_id);
260 printf("state: %d [%s]\n", state,
261 lookup_msg(ospf_nsm_state_msg, state, NULL));
262 }
263
264
265 /* ---------------------------------------------------------
266 * Main program
267 * ---------------------------------------------------------
268 */
269
270 static int usage(void)
271 {
272 printf("Usage: ospfclient <ospfd> <lsatype> <opaquetype> <opaqueid> <ifaddr> <areaid>\n");
273 printf("where ospfd : router where API-enabled OSPF daemon is running\n");
274 printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n");
275 printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n");
276 printf(" opaqueid : arbitrary application instance (24 bits)\n");
277 printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n");
278 printf(" areaid : area in IP address format (for type 10) otherwise ignored\n");
279
280 exit(1);
281 }
282
283 int main(int argc, char *argv[])
284 {
285 struct thread thread;
286
287 args = argv;
288
289 /* ospfclient should be started with the following arguments:
290 *
291 * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
292 * (6) area_id
293 *
294 * host: name or IP of host where ospfd is running
295 * lsa_type: 9, 10, or 11
296 * opaque_type: 0-255 (e.g., experimental applications use > 128)
297 * opaque_id: arbitrary application instance (24 bits)
298 * if_addr: interface IP address (for type 9) otherwise ignored
299 * area_id: area in IP address format (for type 10) otherwise ignored
300 */
301
302 if (argc != 7) {
303 usage();
304 }
305
306 /* Initialization */
307 zprivs_preinit(&ospfd_privs);
308 zprivs_init(&ospfd_privs);
309 master = thread_master_create(NULL);
310
311 /* Open connection to OSPF daemon */
312 oclient = ospf_apiclient_connect(args[1], ASYNCPORT);
313 if (!oclient) {
314 printf("Connecting to OSPF daemon on %s failed!\n", args[1]);
315 exit(1);
316 }
317
318 /* Register callback functions. */
319 ospf_apiclient_register_callback(
320 oclient, ready_callback, new_if_callback, del_if_callback,
321 ism_change_callback, nsm_change_callback, lsa_update_callback,
322 lsa_delete_callback);
323
324 /* Register LSA type and opaque type. */
325 ospf_apiclient_register_opaque_type(oclient, atoi(args[2]),
326 atoi(args[3]));
327
328 /* Synchronize database with OSPF daemon. */
329 ospf_apiclient_sync_lsdb(oclient);
330
331 /* Schedule thread that handles asynchronous messages */
332 thread_add_read(master, lsa_read, oclient, oclient->fd_async, NULL);
333
334 /* Now connection is established, run loop */
335 while (1) {
336 thread_fetch(master, &thread);
337 thread_call(&thread);
338 }
339
340 /* Never reached */
341 return 0;
342 }