Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / lsreq.c @ 48e5f32d

History | View | Annotate | Download (3.6 KB)

1
/*
2
 *        BIRD -- OSPF
3
 *
4
 *        (c) 2000--2004 Ondrej Filip <feela@network.cz>
5
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8

    
9
#include "ospf.h"
10

    
11

    
12
struct ospf_lsreq_packet
13
{
14
  struct ospf_packet ospf_packet;
15
  struct ospf_lsreq_header lsh[];
16
};
17

    
18

    
19
static void ospf_dump_lsreq(struct proto *p, struct ospf_lsreq_packet *pkt)
20
{
21
  struct ospf_packet *op = &pkt->ospf_packet;
22

    
23
  ASSERT(op->type == LSREQ_P);
24
  ospf_dump_common(p, op);
25

    
26
  unsigned int i, j;
27
  j = (ntohs(op->length) - sizeof(struct ospf_lsreq_packet)) /
28
    sizeof(struct ospf_lsreq_header);
29

    
30
  for (i = 0; i < j; i++)
31
    log(L_TRACE "%s:     LSR      Type: %04x, Id: %R, Rt: %R", p->name,
32
        htonl(pkt->lsh[i].type), htonl(pkt->lsh[i].id), htonl(pkt->lsh[i].rt));
33
}
34

    
35
void
36
ospf_lsreq_send(struct ospf_neighbor *n)
37
{
38
  snode *sn;
39
  struct top_hash_entry *en;
40
  struct ospf_lsreq_packet *pk;
41
  struct ospf_packet *op;
42
  struct ospf_lsreq_header *lsh;
43
  u16 length;
44
  int i, j;
45
  struct proto *p = &n->ifa->oa->po->proto;
46

    
47
  pk = ospf_tx_buffer(n->ifa);
48
  op = &pk->ospf_packet;
49

    
50
  ospf_pkt_fill_hdr(n->ifa, pk, LSREQ_P);
51

    
52
  sn = SHEAD(n->lsrql);
53
  if (EMPTY_SLIST(n->lsrql))
54
  {
55
    if (n->state == NEIGHBOR_LOADING)
56
      ospf_neigh_sm(n, INM_LOADDONE);
57
    return;
58
  }
59

    
60
  i = j = (ospf_pkt_maxsize(n->ifa) - sizeof(struct ospf_lsreq_packet)) /
61
    sizeof(struct ospf_lsreq_header);
62
  lsh = pk->lsh;
63

    
64
  for (; i > 0; i--)
65
  {
66
    en = (struct top_hash_entry *) sn;
67
    lsh->type = htonl(en->lsa.type);
68
    lsh->rt = htonl(en->lsa.rt);
69
    lsh->id = htonl(en->lsa.id);
70
    DBG("Requesting %uth LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
71
        i, en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age);
72
    lsh++;
73
    if (sn == STAIL(n->lsrql))
74
      break;
75
    sn = sn->next;
76
  }
77
  if (i != 0)
78
    i--;
79

    
80
  length =
81
    sizeof(struct ospf_lsreq_packet) + (j -
82
                                        i) * sizeof(struct ospf_lsreq_header);
83
  op->length = htons(length);
84

    
85
  OSPF_PACKET(ospf_dump_lsreq, pk, "LSREQ packet sent to %I via %s", n->ip, n->ifa->ifname);
86
  ospf_send_to(n->ifa, n->ip);
87
}
88

    
89
void
90
ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
91
                   struct ospf_neighbor *n)
92
{
93
  struct ospf_area *oa = ifa->oa;
94
  struct proto_ospf *po = oa->po;
95
  struct proto *p = &po->proto;
96
  struct ospf_lsreq_header *lsh;
97
  struct l_lsr_head *llsh;
98
  list uplist;
99
  slab *upslab;
100
  int i, lsano;
101

    
102
  unsigned int size = ntohs(ps_i->length);
103
  if (size < sizeof(struct ospf_lsreq_packet))
104
  {
105
    log(L_ERR "Bad OSPF LSREQ packet from %I -  too short (%u B)", n->ip, size);
106
    return;
107
  }
108

    
109
  struct ospf_lsreq_packet *ps = (void *) ps_i;
110
  OSPF_PACKET(ospf_dump_lsreq, ps, "LSREQ packet received from %I via %s", n->ip, ifa->ifname);
111

    
112
  if (n->state < NEIGHBOR_EXCHANGE)
113
    return;
114

    
115
  ospf_neigh_sm(n, INM_HELLOREC);
116

    
117
  lsh = ps->lsh;
118
  init_list(&uplist);
119
  upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
120

    
121
  lsano = (size - sizeof(struct ospf_lsreq_packet)) /
122
    sizeof(struct ospf_lsreq_header);
123
  for (i = 0; i < lsano; lsh++, i++)
124
  {
125
    u32 hid = ntohl(lsh->id);
126
    u32 hrt = ntohl(lsh->rt);
127
    u32 htype = ntohl(lsh->type);
128
    u32 dom = ospf_lsa_domain(htype, ifa);
129
    DBG("Processing requested LSA: Type: %u, ID: %R, RT: %R\n", lsh->type, hid, hrt);
130
    llsh = sl_alloc(upslab);
131
    llsh->lsh.id = hid;
132
    llsh->lsh.rt = hrt;
133
    llsh->lsh.type = htype;
134
    add_tail(&uplist, NODE llsh);
135
    if (ospf_hash_find(po->gr, dom, hid, hrt, htype) == NULL)
136
    {
137
      log(L_WARN "Received bad LSREQ from %I: Type: %04x, Id: %R, Rt: %R",
138
          n->ip, htype, hid, hrt);
139
      ospf_neigh_sm(n, INM_BADLSREQ);
140
      rfree(upslab);
141
      return;
142
    }
143
  }
144
  ospf_lsupd_send_list(n, &uplist);
145
  rfree(upslab);
146
}