Annotation of embedaddon/quagga/ospfclient/ospf_apiclient.c, revision 1.1

1.1     ! misho       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: 
        !            60: void ospf_apiclient_handle_reply (struct ospf_apiclient *oclient,
        !            61:                                  struct msg *msg);
        !            62: void ospf_apiclient_handle_update_notify (struct ospf_apiclient *oclient,
        !            63:                                          struct msg *msg);
        !            64: void ospf_apiclient_handle_delete_notify (struct ospf_apiclient *oclient,
        !            65:                                          struct msg *msg);
        !            66: 
        !            67: /* -----------------------------------------------------------
        !            68:  * Initialization
        !            69:  * -----------------------------------------------------------
        !            70:  */
        !            71: 
        !            72: static unsigned short
        !            73: ospf_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: 
        !            85: struct ospf_apiclient *
        !            86: ospf_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: 
        !           271: int
        !           272: ospf_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 */
        !           296: static int
        !           297: ospf_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: 
        !           338: static u_int32_t
        !           339: ospf_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:  */
        !           365: int
        !           366: ospf_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:  */
        !           390: int
        !           391: ospf_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: 
        !           420: out:
        !           421:   return rc;
        !           422: }
        !           423: 
        !           424: /* 
        !           425:  * Synchronous request to originate or update an LSA.
        !           426:  */
        !           427: 
        !           428: int
        !           429: ospf_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: 
        !           478: int
        !           479: ospf_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: 
        !           507: static void
        !           508: ospf_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: 
        !           520: static void
        !           521: ospf_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: 
        !           533: static void
        !           534: ospf_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: 
        !           546: static void
        !           547: ospf_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: 
        !           561: static void
        !           562: ospf_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: 
        !           575: static void
        !           576: ospf_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: 
        !           606: static void
        !           607: ospf_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: 
        !           637: static void
        !           638: ospf_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: 
        !           676: void
        !           677: ospf_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: 
        !           725: int
        !           726: ospf_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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>