ospfclient.c 8.7 KB

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