ospfclient.c 9.4 KB

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