1/* 2 * Client side of OSPF API. 3 * Copyright (C) 2001, 2002, 2003 Ralph Keller 4 * 5 * This file is part of GNU Zebra. 6 * 7 * GNU Zebra is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published 9 * by the Free Software Foundation; either version 2, or (at your 10 * option) any later version. 11 * 12 * GNU Zebra is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with GNU Zebra; see the file COPYING. If not, write to the 19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20 * Boston, MA 02111-1307, USA. 21 */ 22 23#include <zebra.h> 24 25#include <lib/version.h> 26#include "getopt.h" 27#include "thread.h" 28#include "prefix.h" 29#include "linklist.h" 30#include "if.h" 31#include "vector.h" 32#include "vty.h" 33#include "command.h" 34#include "filter.h" 35#include "stream.h" 36#include "log.h" 37#include "memory.h" 38 39#include "ospfd/ospfd.h" 40#include "ospfd/ospf_interface.h" 41#include "ospfd/ospf_asbr.h" 42#include "ospfd/ospf_lsa.h" 43#include "ospfd/ospf_opaque.h" 44#include "ospfd/ospf_lsdb.h" 45#include "ospfd/ospf_neighbor.h" 46#include "ospfd/ospf_dump.h" 47#include "ospfd/ospf_zebra.h" 48#include "ospfd/ospf_api.h" 49 50#include "ospf_apiclient.h" 51 52/* Backlog for listen */ 53#define BACKLOG 5 54 55/* ----------------------------------------------------------- 56 * Forward declarations 57 * ----------------------------------------------------------- 58 */ 59 60void ospf_apiclient_handle_reply (struct ospf_apiclient *oclient, 61 struct msg *msg); 62void ospf_apiclient_handle_update_notify (struct ospf_apiclient *oclient, 63 struct msg *msg); 64void ospf_apiclient_handle_delete_notify (struct ospf_apiclient *oclient, 65 struct msg *msg); 66 67/* ----------------------------------------------------------- 68 * Initialization 69 * ----------------------------------------------------------- 70 */ 71 72static unsigned short 73ospf_apiclient_getport (void) 74{ 75 struct servent *sp = getservbyname ("ospfapi", "tcp"); 76 77 return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT; 78} 79 80/* ----------------------------------------------------------- 81 * Followings are functions for connection management 82 * ----------------------------------------------------------- 83 */ 84 85struct ospf_apiclient * 86ospf_apiclient_connect (char *host, int syncport) 87{ 88 struct sockaddr_in myaddr_sync; 89 struct sockaddr_in myaddr_async; 90 struct sockaddr_in peeraddr; 91 struct hostent *hp; 92 struct ospf_apiclient *new; 93 int size = 0; 94 unsigned int peeraddrlen; 95 int async_server_sock; 96 int fd1, fd2; 97 int ret; 98 int on = 1; 99 100 /* There are two connections between the client and the server. 101 First the client opens a connection for synchronous requests/replies 102 to the server. The server will accept this connection and 103 as a reaction open a reverse connection channel for 104 asynchronous messages. */ 105 106 async_server_sock = socket (AF_INET, SOCK_STREAM, 0); 107 if (async_server_sock < 0) 108 { 109 fprintf (stderr, 110 "ospf_apiclient_connect: creating async socket failed\n"); 111 return NULL; 112 } 113 114 /* Prepare socket for asynchronous messages */ 115 /* Initialize async address structure */ 116 memset (&myaddr_async, 0, sizeof (struct sockaddr_in)); 117 myaddr_async.sin_family = AF_INET; 118 myaddr_async.sin_addr.s_addr = htonl (INADDR_ANY); 119 myaddr_async.sin_port = htons (syncport+1); 120 size = sizeof (struct sockaddr_in); 121#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 122 myaddr_async.sin_len = size; 123#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ 124 125 /* This is a server socket, reuse addr and port */ 126 ret = setsockopt (async_server_sock, SOL_SOCKET, 127 SO_REUSEADDR, (void *) &on, sizeof (on)); 128 if (ret < 0) 129 { 130 fprintf (stderr, "ospf_apiclient_connect: SO_REUSEADDR failed\n"); 131 close (async_server_sock); 132 return NULL; 133 } 134 135#ifdef SO_REUSEPORT 136 ret = setsockopt (async_server_sock, SOL_SOCKET, SO_REUSEPORT, 137 (void *) &on, sizeof (on)); 138 if (ret < 0) 139 { 140 fprintf (stderr, "ospf_apiclient_connect: SO_REUSEPORT failed\n"); 141 close (async_server_sock); 142 return NULL; 143 } 144#endif /* SO_REUSEPORT */ 145 146 /* Bind socket to address structure */ 147 ret = bind (async_server_sock, (struct sockaddr *) &myaddr_async, size); 148 if (ret < 0) 149 { 150 fprintf (stderr, "ospf_apiclient_connect: bind async socket failed\n"); 151 close (async_server_sock); 152 return NULL; 153 } 154 155 /* Wait for reverse channel connection establishment from server */ 156 ret = listen (async_server_sock, BACKLOG); 157 if (ret < 0) 158 { 159 fprintf (stderr, "ospf_apiclient_connect: listen: %s\n", safe_strerror (errno)); 160 close (async_server_sock); 161 return NULL; 162 } 163 164 /* Make connection for synchronous requests and connect to server */ 165 /* Resolve address of server */ 166 hp = gethostbyname (host); 167 if (!hp) 168 { 169 fprintf (stderr, "ospf_apiclient_connect: no such host %s\n", host); 170 close (async_server_sock); 171 return NULL; 172 } 173 174 fd1 = socket (AF_INET, SOCK_STREAM, 0); 175 if (fd1 < 0) 176 { 177 fprintf (stderr, 178 "ospf_apiclient_connect: creating sync socket failed\n"); 179 return NULL; 180 } 181 182 183 /* Reuse addr and port */ 184 ret = setsockopt (fd1, SOL_SOCKET, 185 SO_REUSEADDR, (void *) &on, sizeof (on)); 186 if (ret < 0) 187 { 188 fprintf (stderr, "ospf_apiclient_connect: SO_REUSEADDR failed\n"); 189 close (fd1); 190 return NULL; 191 } 192 193#ifdef SO_REUSEPORT 194 ret = setsockopt (fd1, SOL_SOCKET, SO_REUSEPORT, 195 (void *) &on, sizeof (on)); 196 if (ret < 0) 197 { 198 fprintf (stderr, "ospf_apiclient_connect: SO_REUSEPORT failed\n"); 199 close (fd1); 200 return NULL; 201 } 202#endif /* SO_REUSEPORT */ 203 204 205 /* Bind sync socket to address structure. This is needed since we 206 want the sync port number on a fixed port number. The reverse 207 async channel will be at this port+1 */ 208 209 memset (&myaddr_sync, 0, sizeof (struct sockaddr_in)); 210 myaddr_sync.sin_family = AF_INET; 211 myaddr_sync.sin_port = htons (syncport); 212#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 213 myaddr_sync.sin_len = sizeof (struct sockaddr_in); 214#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ 215 216 ret = bind (fd1, (struct sockaddr *) &myaddr_sync, size); 217 if (ret < 0) 218 { 219 fprintf (stderr, "ospf_apiclient_connect: bind sync socket failed\n"); 220 close (fd1); 221 return NULL; 222 } 223 224 /* Prepare address structure for connect */ 225 memcpy (&myaddr_sync.sin_addr, hp->h_addr, hp->h_length); 226 myaddr_sync.sin_family = AF_INET; 227 myaddr_sync.sin_port = htons(ospf_apiclient_getport ()); 228#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 229 myaddr_sync.sin_len = sizeof (struct sockaddr_in); 230#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ 231 232 /* Now establish synchronous channel with OSPF daemon */ 233 ret = connect (fd1, (struct sockaddr *) &myaddr_sync, 234 sizeof (struct sockaddr_in)); 235 if (ret < 0) 236 { 237 fprintf (stderr, "ospf_apiclient_connect: sync connect failed\n"); 238 close (async_server_sock); 239 close (fd1); 240 return NULL; 241 } 242 243 /* Accept reverse connection */ 244 peeraddrlen = sizeof (struct sockaddr_in); 245 memset (&peeraddr, 0, peeraddrlen); 246 247 fd2 = 248 accept (async_server_sock, (struct sockaddr *) &peeraddr, &peeraddrlen); 249 if (fd2 < 0) 250 { 251 fprintf (stderr, "ospf_apiclient_connect: accept async failed\n"); 252 close (async_server_sock); 253 close (fd1); 254 return NULL; 255 } 256 257 /* Server socket is not needed anymore since we are not accepting more 258 connections */ 259 close (async_server_sock); 260 261 /* Create new client-side instance */ 262 new = XCALLOC (MTYPE_OSPF_APICLIENT, sizeof (struct ospf_apiclient)); 263 264 /* Initialize socket descriptors for sync and async channels */ 265 new->fd_sync = fd1; 266 new->fd_async = fd2; 267 268 return new; 269} 270 271int 272ospf_apiclient_close (struct ospf_apiclient *oclient) 273{ 274 275 if (oclient->fd_sync >= 0) 276 { 277 close (oclient->fd_sync); 278 } 279 280 if (oclient->fd_async >= 0) 281 { 282 close (oclient->fd_async); 283 } 284 285 /* Free client structure */ 286 XFREE (MTYPE_OSPF_APICLIENT, oclient); 287 return 0; 288} 289 290/* ----------------------------------------------------------- 291 * Followings are functions to send a request to OSPFd 292 * ----------------------------------------------------------- 293 */ 294 295/* Send synchronous request, wait for reply */ 296static int 297ospf_apiclient_send_request (struct ospf_apiclient *oclient, struct msg *msg) 298{ 299 u_int32_t reqseq; 300 struct msg_reply *msgreply; 301 int rc; 302 303 /* NB: Given "msg" is freed inside this function. */ 304 305 /* Remember the sequence number of the request */ 306 reqseq = ntohl (msg->hdr.msgseq); 307 308 /* Write message to OSPFd */ 309 rc = msg_write (oclient->fd_sync, msg); 310 msg_free (msg); 311 312 if (rc < 0) 313 { 314 return -1; 315 } 316 317 /* Wait for reply *//* NB: New "msg" is allocated by "msg_read()". */ 318 msg = msg_read (oclient->fd_sync); 319 if (!msg) 320 return -1; 321 322 assert (msg->hdr.msgtype == MSG_REPLY); 323 assert (ntohl (msg->hdr.msgseq) == reqseq); 324 325 msgreply = (struct msg_reply *) STREAM_DATA (msg->s); 326 rc = msgreply->errcode; 327 msg_free (msg); 328 329 return rc; 330} 331 332 333/* ----------------------------------------------------------- 334 * Helper functions 335 * ----------------------------------------------------------- 336 */ 337 338static u_int32_t 339ospf_apiclient_get_seqnr (void) 340{ 341 static u_int32_t seqnr = MIN_SEQ; 342 u_int32_t tmp; 343 344 tmp = seqnr; 345 /* Increment sequence number */ 346 if (seqnr < MAX_SEQ) 347 { 348 seqnr++; 349 } 350 else 351 { 352 seqnr = MIN_SEQ; 353 } 354 return tmp; 355} 356 357/* ----------------------------------------------------------- 358 * API to access OSPF daemon by client applications. 359 * ----------------------------------------------------------- 360 */ 361 362/* 363 * Synchronous request to register opaque type. 364 */ 365int 366ospf_apiclient_register_opaque_type (struct ospf_apiclient *cl, 367 u_char ltype, u_char otype) 368{ 369 struct msg *msg; 370 int rc; 371 372 /* just put 1 as a sequence number. */ 373 msg = new_msg_register_opaque_type (ospf_apiclient_get_seqnr (), 374 ltype, otype); 375 if (!msg) 376 { 377 fprintf (stderr, "new_msg_register_opaque_type failed\n"); 378 return -1; 379 } 380 381 rc = ospf_apiclient_send_request (cl, msg); 382 return rc; 383} 384 385/* 386 * Synchronous request to synchronize with OSPF's LSDB. 387 * Two steps required: register_event in order to get 388 * dynamic updates and LSDB_Sync. 389 */ 390int 391ospf_apiclient_sync_lsdb (struct ospf_apiclient *oclient) 392{ 393 struct msg *msg; 394 int rc; 395 struct lsa_filter_type filter; 396 397 filter.typemask = 0xFFFF; /* all LSAs */ 398 filter.origin = ANY_ORIGIN; 399 filter.num_areas = 0; /* all Areas. */ 400 401 msg = new_msg_register_event (ospf_apiclient_get_seqnr (), &filter); 402 if (!msg) 403 { 404 fprintf (stderr, "new_msg_register_event failed\n"); 405 return -1; 406 } 407 rc = ospf_apiclient_send_request (oclient, msg); 408 409 if (rc != 0) 410 goto out; 411 412 msg = new_msg_sync_lsdb (ospf_apiclient_get_seqnr (), &filter); 413 if (!msg) 414 { 415 fprintf (stderr, "new_msg_sync_lsdb failed\n"); 416 return -1; 417 } 418 rc = ospf_apiclient_send_request (oclient, msg); 419 420out: 421 return rc; 422} 423 424/* 425 * Synchronous request to originate or update an LSA. 426 */ 427 428int 429ospf_apiclient_lsa_originate (struct ospf_apiclient *oclient, 430 struct in_addr ifaddr, 431 struct in_addr area_id, 432 u_char lsa_type, 433 u_char opaque_type, u_int32_t opaque_id, 434 void *opaquedata, int opaquelen) 435{ 436 struct msg *msg; 437 int rc; 438 u_char buf[OSPF_MAX_LSA_SIZE]; 439 struct lsa_header *lsah; 440 u_int32_t tmp; 441 442 443 /* We can only originate opaque LSAs */ 444 if (!IS_OPAQUE_LSA (lsa_type)) 445 { 446 fprintf (stderr, "Cannot originate non-opaque LSA type %d\n", lsa_type); 447 return OSPF_API_ILLEGALLSATYPE; 448 } 449 450 /* Make a new LSA from parameters */ 451 lsah = (struct lsa_header *) buf; 452 lsah->ls_age = 0; 453 lsah->options = 0; 454 lsah->type = lsa_type; 455 456 tmp = SET_OPAQUE_LSID (opaque_type, opaque_id); 457 lsah->id.s_addr = htonl (tmp); 458 lsah->adv_router.s_addr = 0; 459 lsah->ls_seqnum = 0; 460 lsah->checksum = 0; 461 lsah->length = htons (sizeof (struct lsa_header) + opaquelen); 462 463 memcpy (((u_char *) lsah) + sizeof (struct lsa_header), opaquedata, 464 opaquelen); 465 466 msg = new_msg_originate_request (ospf_apiclient_get_seqnr (), 467 ifaddr, area_id, lsah); 468 if (!msg) 469 { 470 fprintf (stderr, "new_msg_originate_request failed\n"); 471 return OSPF_API_NOMEMORY; 472 } 473 474 rc = ospf_apiclient_send_request (oclient, msg); 475 return rc; 476} 477 478int 479ospf_apiclient_lsa_delete (struct ospf_apiclient *oclient, 480 struct in_addr area_id, u_char lsa_type, 481 u_char opaque_type, u_int32_t opaque_id) 482{ 483 struct msg *msg; 484 int rc; 485 486 /* Only opaque LSA can be deleted */ 487 if (!IS_OPAQUE_LSA (lsa_type)) 488 { 489 fprintf (stderr, "Cannot delete non-opaque LSA type %d\n", lsa_type); 490 return OSPF_API_ILLEGALLSATYPE; 491 } 492 493 /* opaque_id is in host byte order and will be converted 494 * to network byte order by new_msg_delete_request */ 495 msg = new_msg_delete_request (ospf_apiclient_get_seqnr (), 496 area_id, lsa_type, opaque_type, opaque_id); 497 498 rc = ospf_apiclient_send_request (oclient, msg); 499 return rc; 500} 501 502/* ----------------------------------------------------------- 503 * Followings are handlers for messages from OSPF daemon 504 * ----------------------------------------------------------- 505 */ 506 507static void 508ospf_apiclient_handle_ready (struct ospf_apiclient *oclient, struct msg *msg) 509{ 510 struct msg_ready_notify *r; 511 r = (struct msg_ready_notify *) STREAM_DATA (msg->s); 512 513 /* Invoke registered callback function. */ 514 if (oclient->ready_notify) 515 { 516 (oclient->ready_notify) (r->lsa_type, r->opaque_type, r->addr); 517 } 518} 519 520static void 521ospf_apiclient_handle_new_if (struct ospf_apiclient *oclient, struct msg *msg) 522{ 523 struct msg_new_if *n; 524 n = (struct msg_new_if *) STREAM_DATA (msg->s); 525 526 /* Invoke registered callback function. */ 527 if (oclient->new_if) 528 { 529 (oclient->new_if) (n->ifaddr, n->area_id); 530 } 531} 532 533static void 534ospf_apiclient_handle_del_if (struct ospf_apiclient *oclient, struct msg *msg) 535{ 536 struct msg_del_if *d; 537 d = (struct msg_del_if *) STREAM_DATA (msg->s); 538 539 /* Invoke registered callback function. */ 540 if (oclient->del_if) 541 { 542 (oclient->del_if) (d->ifaddr); 543 } 544} 545 546static void 547ospf_apiclient_handle_ism_change (struct ospf_apiclient *oclient, 548 struct msg *msg) 549{ 550 struct msg_ism_change *m; 551 m = (struct msg_ism_change *) STREAM_DATA (msg->s); 552 553 /* Invoke registered callback function. */ 554 if (oclient->ism_change) 555 { 556 (oclient->ism_change) (m->ifaddr, m->area_id, m->status); 557 } 558 559} 560 561static void 562ospf_apiclient_handle_nsm_change (struct ospf_apiclient *oclient, 563 struct msg *msg) 564{ 565 struct msg_nsm_change *m; 566 m = (struct msg_nsm_change *) STREAM_DATA (msg->s); 567 568 /* Invoke registered callback function. */ 569 if (oclient->nsm_change) 570 { 571 (oclient->nsm_change) (m->ifaddr, m->nbraddr, m->router_id, m->status); 572 } 573} 574 575static void 576ospf_apiclient_handle_lsa_update (struct ospf_apiclient *oclient, 577 struct msg *msg) 578{ 579 struct msg_lsa_change_notify *cn; 580 struct lsa_header *lsa; 581 int lsalen; 582 583 cn = (struct msg_lsa_change_notify *) STREAM_DATA (msg->s); 584 585 /* Extract LSA from message */ 586 lsalen = ntohs (cn->data.length); 587 lsa = XMALLOC (MTYPE_OSPF_APICLIENT, lsalen); 588 if (!lsa) 589 { 590 fprintf (stderr, "LSA update: Cannot allocate memory for LSA\n"); 591 return; 592 } 593 memcpy (lsa, &(cn->data), lsalen); 594 595 /* Invoke registered update callback function */ 596 if (oclient->update_notify) 597 { 598 (oclient->update_notify) (cn->ifaddr, cn->area_id, 599 cn->is_self_originated, lsa); 600 } 601 602 /* free memory allocated by ospf apiclient library */ 603 XFREE (MTYPE_OSPF_APICLIENT, lsa); 604} 605 606static void 607ospf_apiclient_handle_lsa_delete (struct ospf_apiclient *oclient, 608 struct msg *msg) 609{ 610 struct msg_lsa_change_notify *cn; 611 struct lsa_header *lsa; 612 int lsalen; 613 614 cn = (struct msg_lsa_change_notify *) STREAM_DATA (msg->s); 615 616 /* Extract LSA from message */ 617 lsalen = ntohs (cn->data.length); 618 lsa = XMALLOC (MTYPE_OSPF_APICLIENT, lsalen); 619 if (!lsa) 620 { 621 fprintf (stderr, "LSA delete: Cannot allocate memory for LSA\n"); 622 return; 623 } 624 memcpy (lsa, &(cn->data), lsalen); 625 626 /* Invoke registered update callback function */ 627 if (oclient->delete_notify) 628 { 629 (oclient->delete_notify) (cn->ifaddr, cn->area_id, 630 cn->is_self_originated, lsa); 631 } 632 633 /* free memory allocated by ospf apiclient library */ 634 XFREE (MTYPE_OSPF_APICLIENT, lsa); 635} 636 637static void 638ospf_apiclient_msghandle (struct ospf_apiclient *oclient, struct msg *msg) 639{ 640 /* Call message handler function. */ 641 switch (msg->hdr.msgtype) 642 { 643 case MSG_READY_NOTIFY: 644 ospf_apiclient_handle_ready (oclient, msg); 645 break; 646 case MSG_NEW_IF: 647 ospf_apiclient_handle_new_if (oclient, msg); 648 break; 649 case MSG_DEL_IF: 650 ospf_apiclient_handle_del_if (oclient, msg); 651 break; 652 case MSG_ISM_CHANGE: 653 ospf_apiclient_handle_ism_change (oclient, msg); 654 break; 655 case MSG_NSM_CHANGE: 656 ospf_apiclient_handle_nsm_change (oclient, msg); 657 break; 658 case MSG_LSA_UPDATE_NOTIFY: 659 ospf_apiclient_handle_lsa_update (oclient, msg); 660 break; 661 case MSG_LSA_DELETE_NOTIFY: 662 ospf_apiclient_handle_lsa_delete (oclient, msg); 663 break; 664 default: 665 fprintf (stderr, "ospf_apiclient_read: Unknown message type: %d\n", 666 msg->hdr.msgtype); 667 break; 668 } 669} 670 671/* ----------------------------------------------------------- 672 * Callback handler registration 673 * ----------------------------------------------------------- 674 */ 675 676void 677ospf_apiclient_register_callback (struct ospf_apiclient *oclient, 678 void (*ready_notify) (u_char lsa_type, 679 u_char opaque_type, 680 struct in_addr addr), 681 void (*new_if) (struct in_addr ifaddr, 682 struct in_addr area_id), 683 void (*del_if) (struct in_addr ifaddr), 684 void (*ism_change) (struct in_addr ifaddr, 685 struct in_addr area_id, 686 u_char status), 687 void (*nsm_change) (struct in_addr ifaddr, 688 struct in_addr nbraddr, 689 struct in_addr 690 router_id, 691 u_char status), 692 void (*update_notify) (struct in_addr 693 ifaddr, 694 struct in_addr 695 area_id, 696 u_char self_origin, 697 struct lsa_header * 698 lsa), 699 void (*delete_notify) (struct in_addr 700 ifaddr, 701 struct in_addr 702 area_id, 703 u_char self_origin, 704 struct lsa_header * 705 lsa)) 706{ 707 assert (oclient); 708 assert (update_notify); 709 710 /* Register callback function */ 711 oclient->ready_notify = ready_notify; 712 oclient->new_if = new_if; 713 oclient->del_if = del_if; 714 oclient->ism_change = ism_change; 715 oclient->nsm_change = nsm_change; 716 oclient->update_notify = update_notify; 717 oclient->delete_notify = delete_notify; 718} 719 720/* ----------------------------------------------------------- 721 * Asynchronous message handling 722 * ----------------------------------------------------------- 723 */ 724 725int 726ospf_apiclient_handle_async (struct ospf_apiclient *oclient) 727{ 728 struct msg *msg; 729 730 /* Get a message */ 731 msg = msg_read (oclient->fd_async); 732 733 if (!msg) 734 { 735 /* Connection broke down */ 736 return -1; 737 } 738 739 /* Handle message */ 740 ospf_apiclient_msghandle (oclient, msg); 741 742 /* Don't forget to free this message */ 743 msg_free (msg); 744 745 return 0; 746} 747