"Fossies" - the Fresh Open Source Software Archive

Member "ospfd/lsreq.c" (6 Jun 2009, 5740 Bytes) of package /linux/privat/old/openospfd-4.6.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*  $OpenBSD: lsreq.c,v 1.18 2009/06/06 07:31:26 eric Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 #include <sys/types.h>
   20 #include <sys/socket.h>
   21 #include <netinet/in.h>
   22 #include <arpa/inet.h>
   23 #include <stdlib.h>
   24 
   25 #include "ospfd.h"
   26 #include "ospf.h"
   27 #include "log.h"
   28 #include "ospfe.h"
   29 
   30 extern struct imsgev        *iev_rde;
   31 
   32 /* link state request packet handling */
   33 int
   34 send_ls_req(struct nbr *nbr)
   35 {
   36     struct sockaddr_in   dst;
   37     struct ls_req_hdr    ls_req_hdr;
   38     struct lsa_entry    *le, *nle;
   39     struct buf      *buf;
   40     int          ret;
   41 
   42     if ((buf = buf_open(nbr->iface->mtu - sizeof(struct ip))) == NULL)
   43         fatal("send_ls_req");
   44 
   45     /* set destination */
   46     dst.sin_family = AF_INET;
   47     dst.sin_len = sizeof(struct sockaddr_in);
   48 
   49     switch (nbr->iface->type) {
   50     case IF_TYPE_POINTOPOINT:
   51         inet_aton(AllSPFRouters, &dst.sin_addr);
   52         break;
   53     case IF_TYPE_BROADCAST:
   54     case IF_TYPE_NBMA:
   55     case IF_TYPE_POINTOMULTIPOINT:
   56     case IF_TYPE_VIRTUALLINK:
   57         dst.sin_addr.s_addr = nbr->addr.s_addr;
   58         break;
   59     default:
   60         fatalx("send_ls_req: unknown interface type");
   61     }
   62 
   63     /* OSPF header */
   64     if (gen_ospf_hdr(buf, nbr->iface, PACKET_TYPE_LS_REQUEST))
   65         goto fail;
   66 
   67     /* LSA header(s), keep space for a possible md5 sum */
   68     for (le = TAILQ_FIRST(&nbr->ls_req_list); le != NULL &&
   69         buf_left(buf) >= sizeof(struct ls_req_hdr) + MD5_DIGEST_LENGTH;
   70         le = nle) {
   71         nbr->ls_req = nle = TAILQ_NEXT(le, entry);
   72         ls_req_hdr.type = htonl(le->le_lsa->type);
   73         ls_req_hdr.ls_id = le->le_lsa->ls_id;
   74         ls_req_hdr.adv_rtr = le->le_lsa->adv_rtr;
   75         if (buf_add(buf, &ls_req_hdr, sizeof(ls_req_hdr)))
   76             goto fail;
   77     }
   78 
   79     /* update authentication and calculate checksum */
   80     if (auth_gen(buf, nbr->iface))
   81         goto fail;
   82 
   83     ret = send_packet(nbr->iface, buf, &dst);
   84 
   85     buf_free(buf);
   86     return (ret);
   87 fail:
   88     log_warn("send_ls_req");
   89     buf_free(buf);
   90     return (-1);
   91 }
   92 
   93 void
   94 recv_ls_req(struct nbr *nbr, char *buf, u_int16_t len)
   95 {
   96     switch (nbr->state) {
   97     case NBR_STA_DOWN:
   98     case NBR_STA_ATTEMPT:
   99     case NBR_STA_INIT:
  100     case NBR_STA_2_WAY:
  101     case NBR_STA_XSTRT:
  102     case NBR_STA_SNAP:
  103         log_debug("recv_ls_req: packet ignored in state %s, "
  104             "neighbor ID %s", nbr_state_name(nbr->state),
  105             inet_ntoa(nbr->id));
  106         break;
  107     case NBR_STA_XCHNG:
  108     case NBR_STA_LOAD:
  109     case NBR_STA_FULL:
  110         imsg_compose_event(iev_rde, IMSG_LS_REQ, nbr->peerid,
  111             0, -1, buf, len);
  112         break;
  113     default:
  114         fatalx("recv_ls_req: unknown neighbor state");
  115     }
  116 }
  117 
  118 /* link state request list */
  119 void
  120 ls_req_list_add(struct nbr *nbr, struct lsa_hdr *lsa)
  121 {
  122     struct lsa_entry    *le;
  123 
  124     if (lsa == NULL)
  125         fatalx("ls_req_list_add: no LSA header");
  126 
  127     if ((le = calloc(1, sizeof(*le))) == NULL)
  128         fatal("ls_req_list_add");
  129 
  130     TAILQ_INSERT_TAIL(&nbr->ls_req_list, le, entry);
  131     le->le_lsa = lsa;
  132     nbr->ls_req_cnt++;
  133 }
  134 
  135 struct lsa_entry *
  136 ls_req_list_get(struct nbr *nbr, struct lsa_hdr *lsa_hdr)
  137 {
  138     struct lsa_entry    *le;
  139 
  140     TAILQ_FOREACH(le, &nbr->ls_req_list, entry) {
  141         if ((lsa_hdr->type == le->le_lsa->type) &&
  142             (lsa_hdr->ls_id == le->le_lsa->ls_id) &&
  143             (lsa_hdr->adv_rtr == le->le_lsa->adv_rtr))
  144             return (le);
  145     }
  146     return (NULL);
  147 }
  148 
  149 void
  150 ls_req_list_free(struct nbr *nbr, struct lsa_entry *le)
  151 {
  152     if (nbr->ls_req == le) {
  153         nbr->ls_req = TAILQ_NEXT(le, entry);
  154     }
  155 
  156     TAILQ_REMOVE(&nbr->ls_req_list, le, entry);
  157     free(le->le_lsa);
  158     free(le);
  159     nbr->ls_req_cnt--;
  160 
  161     /* received all requested LSA(s), send a new LS req */
  162     if (nbr->ls_req != NULL &&
  163         nbr->ls_req == TAILQ_FIRST(&nbr->ls_req_list)) {
  164         start_ls_req_tx_timer(nbr);
  165     }
  166 
  167     if (ls_req_list_empty(nbr) && nbr->dd_pending == 0)
  168         nbr_fsm(nbr, NBR_EVT_LOAD_DONE);
  169 }
  170 
  171 void
  172 ls_req_list_clr(struct nbr *nbr)
  173 {
  174     struct lsa_entry    *le;
  175 
  176     while ((le = TAILQ_FIRST(&nbr->ls_req_list)) != NULL) {
  177         TAILQ_REMOVE(&nbr->ls_req_list, le, entry);
  178         free(le->le_lsa);
  179         free(le);
  180     }
  181 
  182     nbr->ls_req_cnt = 0;
  183     nbr->ls_req = NULL;
  184 }
  185 
  186 int
  187 ls_req_list_empty(struct nbr *nbr)
  188 {
  189     return (TAILQ_EMPTY(&nbr->ls_req_list));
  190 }
  191 
  192 /* timers */
  193 /* ARGSUSED */
  194 void
  195 ls_req_tx_timer(int fd, short event, void *arg)
  196 {
  197     struct nbr  *nbr = arg;
  198     struct timeval   tv;
  199 
  200     switch (nbr->state) {
  201     case NBR_STA_DOWN:
  202     case NBR_STA_ATTEMPT:
  203     case NBR_STA_INIT:
  204     case NBR_STA_2_WAY:
  205     case NBR_STA_SNAP:
  206     case NBR_STA_XSTRT:
  207     case NBR_STA_XCHNG:
  208         return;
  209     case NBR_STA_LOAD:
  210         send_ls_req(nbr);
  211         break;
  212     case NBR_STA_FULL:
  213         return;
  214     default:
  215         log_debug("ls_req_tx_timer: unknown neighbor state, "
  216             "neighbor ID %s", inet_ntoa(nbr->id));
  217         break;
  218     }
  219 
  220     /* reschedule lsreq_tx_timer */
  221     if (nbr->state == NBR_STA_LOAD) {
  222         timerclear(&tv);
  223         tv.tv_sec = nbr->iface->rxmt_interval;
  224         if (evtimer_add(&nbr->lsreq_tx_timer, &tv) == -1)
  225             fatal("ls_req_tx_timer");
  226     }
  227 }
  228 
  229 void
  230 start_ls_req_tx_timer(struct nbr *nbr)
  231 {
  232     struct timeval tv;
  233 
  234     if (nbr == nbr->iface->self)
  235         return;
  236 
  237     timerclear(&tv);
  238     if (evtimer_add(&nbr->lsreq_tx_timer, &tv) == -1)
  239         fatal("start_ls_req_tx_timer");
  240 }
  241 
  242 void
  243 stop_ls_req_tx_timer(struct nbr *nbr)
  244 {
  245     if (nbr == nbr->iface->self)
  246         return;
  247 
  248     if (evtimer_del(&nbr->lsreq_tx_timer) == -1)
  249         fatal("stop_ls_req_tx_timer");
  250 }