Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / lsalib.c @ 394acced

History | View | Annotate | Download (6.83 KB)

1
/*
2
 *        BIRD -- OSPF
3
 *
4
 *        (c) 1999-2000 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
void
12
htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
13
{
14
  n->age=htons(h->age);
15
  n->options=h->options;
16
  n->type=h->type;
17
  n->id=htonl(h->id);
18
  n->rt=htonl(h->rt);
19
  n->sn=htonl(h->sn);
20
  n->checksum=htons(h->checksum);
21
  n->length=htons(h->length);
22
};
23

    
24
void
25
ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
26
{
27
  h->age=ntohs(n->age);
28
  h->options=n->options;
29
  h->type=n->type;
30
  h->id=ntohl(n->id);
31
  h->rt=ntohl(n->rt);
32
  h->sn=ntohl(n->sn);
33
  h->checksum=ntohs(n->checksum);
34
  h->length=ntohs(n->length);
35
};
36

    
37
void
38
htonlsab(void *h, void *n, u8 type, u16 len)
39
{
40
  unsigned int i;
41
  switch(type)
42
  {
43
    case LSA_T_RT:
44
    {
45
      struct ospf_lsa_rt *hrt, *nrt;
46
      struct ospf_lsa_rt_link *hrtl,*nrtl;
47
      u16 links;
48

    
49
      nrt=n;
50
      hrt=h;
51
      links=hrt->links;
52

    
53
      nrt->VEB=hrt->VEB;
54
      nrt->padding=0;
55
      nrt->links=htons(hrt->links);
56
      nrtl=(struct ospf_lsa_rt_link *)(nrt+1);
57
      hrtl=(struct ospf_lsa_rt_link *)(hrt+1);
58
      for(i=0;i<links;i++)
59
      {
60
        (nrtl+i)->id=htonl((hrtl+i)->id);
61
        (nrtl+i)->data=htonl((hrtl+i)->data);
62
        (nrtl+i)->type=(hrtl+i)->type;
63
        (nrtl+i)->notos=(hrtl+i)->notos;
64
        (nrtl+i)->metric=htons((hrtl+i)->metric);
65
      }
66
      break;
67
    }
68
    case LSA_T_NET:
69
    {
70
      u32 *hid,*nid;
71

    
72
      nid=n;
73
      hid=h;
74

    
75
      for(i=0;i<(len/sizeof(u32));i++)
76
      {
77
        *(nid+i)=htonl(*(hid+i));
78
      }
79
      break;
80
    }
81
    case LSA_T_SUM_NET:
82
    case LSA_T_SUM_RT:
83
    {
84
      struct ospf_lsa_summ *hs, *ns;
85
      struct ospf_lsa_summ_net *hn, *nn;
86

    
87
      hs=h;
88
      ns=n;
89

    
90
      ns->netmask=htonl(hs->netmask);
91

    
92
      hn=(struct ospf_lsa_summ_net *)(hs+1);
93
      nn=(struct ospf_lsa_summ_net *)(ns+1);
94

    
95
      for(i=0;i<((len-sizeof(struct ospf_lsa_summ))/
96
        sizeof(struct ospf_lsa_summ_net));i++)
97
      {
98
        (nn+i)->tos=(hn+i)->tos;
99
        (nn+i)->metric=htons((hn+i)->metric);
100
        (nn+i)->padding=0;
101
      }
102
      break;
103
    }
104
    case LSA_T_EXT:
105
    {
106
      struct ospf_lsa_ext *he, *ne;
107
      struct ospf_lsa_ext_tos *ht, *nt;
108

    
109
      he=h;
110
      ne=n;
111

    
112
      ne->netmask=htonl(he->netmask);
113

    
114
      ht=(struct ospf_lsa_ext_tos *)(he+1);
115
      nt=(struct ospf_lsa_ext_tos *)(ne+1);
116

    
117
      for(i=0;i<((len-sizeof(struct ospf_lsa_ext))/
118
        sizeof(struct ospf_lsa_ext_tos));i++)
119
      {
120
        (nt+i)->etos=(ht+i)->etos;
121
        (nt+i)->padding=0;
122
        (nt+i)->metric=htons((ht+i)->metric);
123
        (nt+i)->fwaddr=htonl((ht+i)->fwaddr);
124
        (nt+i)->tag=htonl((ht+i)->tag);
125
      }
126
      break;
127
    }
128
    default: die("(hton): Unknown LSA\n");
129
  }
130
};
131

    
132
void
133
ntohlsab(void *n, void *h, u8 type, u16 len)
134
{
135
  unsigned int i;
136
  switch(type)
137
  {
138
    case LSA_T_RT:
139
    {
140
      struct ospf_lsa_rt *hrt, *nrt;
141
      struct ospf_lsa_rt_link *hrtl,*nrtl;
142
      u16 links;
143

    
144
      nrt=n;
145
      hrt=h;
146

    
147
      hrt->VEB=nrt->VEB;
148
      hrt->padding=0;
149
      links=hrt->links=ntohs(nrt->links);
150
      nrtl=(struct ospf_lsa_rt_link *)(nrt+1);
151
      hrtl=(struct ospf_lsa_rt_link *)(hrt+1);
152
      for(i=0;i<links;i++)
153
      {
154
        (hrtl+i)->id=ntohl((nrtl+i)->id);
155
        (hrtl+i)->data=ntohl((nrtl+i)->data);
156
        (hrtl+i)->type=(nrtl+i)->type;
157
        (hrtl+i)->notos=(nrtl+i)->notos;
158
        (hrtl+i)->metric=ntohs((nrtl+i)->metric);
159
      }
160
      break;
161
    }
162
    case LSA_T_NET:
163
    {
164
      u32 *hid,*nid;
165

    
166
      hid=h;
167
      nid=n;
168

    
169
      for(i=0;i<(len/sizeof(u32));i++)
170
      {
171
        *(hid+i)=ntohl(*(nid+i));
172
      }
173
      break;
174
    }
175
    case LSA_T_SUM_NET:
176
    case LSA_T_SUM_RT:
177
    {
178
      struct ospf_lsa_summ *hs, *ns;
179
      struct ospf_lsa_summ_net *hn, *nn;
180

    
181
      hs=h;
182
      ns=n;
183

    
184
      hs->netmask=ntohl(ns->netmask);
185

    
186
      hn=(struct ospf_lsa_summ_net *)(hs+1);
187
      nn=(struct ospf_lsa_summ_net *)(ns+1);
188

    
189
      for(i=0;i<((len-sizeof(struct ospf_lsa_summ))/
190
        sizeof(struct ospf_lsa_summ_net));i++)
191
      {
192
        (hn+i)->tos=(nn+i)->tos;
193
        (hn+i)->metric=ntohs((nn+i)->metric);
194
        (hn+i)->padding=0;
195
      }
196
      break;
197
    }
198
    case LSA_T_EXT:
199
    {
200
      struct ospf_lsa_ext *he, *ne;
201
      struct ospf_lsa_ext_tos *ht, *nt;
202

    
203
      he=h;
204
      ne=n;
205

    
206
      he->netmask=ntohl(ne->netmask);
207

    
208
      ht=(struct ospf_lsa_ext_tos *)(he+1);
209
      nt=(struct ospf_lsa_ext_tos *)(ne+1);
210

    
211
      for(i=0;i<((len-sizeof(struct ospf_lsa_ext))/
212
        sizeof(struct ospf_lsa_ext_tos));i++)
213
      {
214
        (ht+i)->etos=(nt+i)->etos;
215
        (ht+i)->padding=0;
216
        (ht+i)->metric=ntohs((nt+i)->metric);
217
        (ht+i)->fwaddr=ntohl((nt+i)->fwaddr);
218
        (ht+i)->tag=ntohl((nt+i)->tag);
219
      }
220
      break;
221
    }
222
    default: die("(ntoh): Unknown LSA\n");
223
  }
224
};
225

    
226
#define MODX 4102                /* larges signed value without overflow */
227

    
228
/* Fletcher Checksum -- Refer to RFC1008. */
229
#define MODX                 4102
230
#define LSA_CHECKSUM_OFFSET    15
231

    
232
/* FIXME This is VERY uneficient, I have huge endianity problems */
233
void
234
lsasum_calculate(struct ospf_lsa_header *h,void *body,struct proto_ospf *po)
235
{
236
  u16 length;
237
  
238
  length=h->length;
239

    
240
  htonlsah(h,h);
241
  htonlsab(body,body,h->type,length);
242

    
243
  (void)lsasum_check(h,body,po);
244
  
245
  ntohlsah(h,h);
246
  ntohlsab(body,body,h->type,length);
247
}
248

    
249
/*
250
 * Note, that this function expects that LSA is in big endianity
251
 * It also returns value in big endian
252
 */
253
u16
254
lsasum_check(struct ospf_lsa_header *h,void *body,struct proto_ospf *po)
255
{
256
  u8 *sp, *ep, *p, *q, *b;
257
  int c0 = 0, c1 = 0;
258
  int x, y;
259
  u16 length,chsum;
260

    
261
  b=body;
262
  sp = (char *) &h->options;
263
  length=ntohs(h->length)-2;
264
  h->checksum = 0;
265

    
266
  for (ep = sp + length; sp < ep; sp = q)
267
  {                /* Actually MODX is very large, do we need the for-cyclus? */
268
    q = sp + MODX;
269
    if (q > ep) q = ep;
270
    for (p = sp; p < q; p++)
271
    {
272
      /* 
273
       * I count with bytes from header and than from body
274
       * but if there is no body, it's appended to header
275
       * (probably checksum in update receiving) and I go on
276
       * after header
277
       */
278
      if((b==NULL) || (p<(u8 *)(h+1)))
279
      {
280
              c0 += *p;
281
      }
282
      else
283
      {
284
              c0 += *(b+(p-sp)-sizeof(struct ospf_lsa_header)+2);
285
      }
286

    
287
      c1 += c0;
288
    }
289
    c0 %= 255;
290
    c1 %= 255;
291
  }
292

    
293
  x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255;
294
  if (x <= 0) x += 255;
295
  y = 510 - c0 - x;
296
  if (y > 255) y -= 255;
297

    
298
  chsum= x + (y << 8);
299
  h->checksum = chsum;
300
  return chsum;
301
}
302

    
303
int
304
lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2)
305
                        /* Return codes from point of view of l1 */
306
{
307
  if(l1->sn<l2->sn) return CMP_NEWER;
308
    if(l1->sn==l2->sn)
309
    {
310
      if(l1->checksum=!l2->checksum)
311
        return l1->checksum<l2->checksum ? CMP_OLDER : CMP_NEWER;
312
      if(l1->age==MAXAGE) return CMP_NEWER;
313
      if(l2->age==MAXAGE) return CMP_OLDER;
314
      if(abs(l1->age-l2->age)>MAXAGEDIFF)
315
        return l1->age<l2->age ? CMP_NEWER : CMP_OLDER;
316
    }
317
    return CMP_SAME;
318
}
319