Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / iface.c @ 23d67029

History | View | Annotate | Download (15 KB)

1
/*
2
 *        BIRD -- OSPF
3
 *
4
 *        (c) 1999--2005 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
char *ospf_is[] = { "down", "loop", "waiting", "point-to-point", "drother",
12
  "backup", "dr"
13
};
14

    
15
char *ospf_ism[] = { "interface up", "wait timer fired", "backup seen",
16
  "neighbor change", "loop indicated", "unloop indicated", "interface down"
17
};
18

    
19
char *ospf_it[] = { "broadcast", "nbma", "point-to-point", "virtual link" };
20

    
21
static void
22
poll_timer_hook(timer * timer)
23
{
24
  log("POLL!");
25
  ospf_hello_send(timer, 1, NULL);
26
}
27

    
28
static void
29
hello_timer_hook(timer * timer)
30
{
31
  ospf_hello_send(timer, 0, NULL);
32
}
33

    
34
static void
35
wait_timer_hook(timer * timer)
36
{
37
  struct ospf_iface *ifa = (struct ospf_iface *) timer->data;
38
  struct proto *p = &ifa->oa->po->proto;
39

    
40
  OSPF_TRACE(D_EVENTS, "Wait timer fired on interface %s.", ifa->iface->name);
41
  ospf_iface_sm(ifa, ISM_WAITF);
42
}
43

    
44
u32
45
rxbufsize(struct ospf_iface *ifa)
46
{
47
  switch(ifa->rxbuf)
48
  {
49
    case OSPF_RXBUF_NORMAL:
50
      return (ifa->iface->mtu * 2);
51
      break;
52
    case OSPF_RXBUF_LARGE:
53
      return OSPF_MAX_PKT_SIZE;
54
      break;
55
    default:
56
      return ifa->rxbuf;
57
      break;
58
  }
59
}
60

    
61
static sock *
62
ospf_open_ip_socket(struct ospf_iface *ifa)
63
{
64
  sock *ipsk;
65
  struct proto *p = &ifa->oa->po->proto;
66

    
67
  ipsk = sk_new(p->pool);
68
  ipsk->type = SK_IP;
69
  ipsk->dport = OSPF_PROTO;
70
  ipsk->saddr = ifa->iface->addr->ip;
71
  ipsk->tos = IP_PREC_INTERNET_CONTROL;
72
  ipsk->ttl = 1;
73
  if (ifa->type == OSPF_IT_VLINK)
74
    ipsk->ttl = 255;
75
  ipsk->rx_hook = ospf_rx_hook;
76
  ipsk->tx_hook = ospf_tx_hook;
77
  ipsk->err_hook = ospf_err_hook;
78
  ipsk->iface = ifa->iface;
79
  ipsk->rbsize = rxbufsize(ifa);
80
  ipsk->tbsize = ifa->iface->mtu;
81
  ipsk->data = (void *) ifa;
82
  if (sk_open(ipsk) != 0)
83
  {
84
    DBG("%s: SK_OPEN: ip open failed.\n", p->name);
85
    return (NULL);
86
  }
87
  DBG("%s: SK_OPEN: ip opened.\n", p->name);
88
  return (ipsk);
89
}
90

    
91

    
92
/**
93
 * ospf_iface_chstate - handle changes of interface state
94
 * @ifa: OSPF interface
95
 * @state: new state
96
 *
97
 * Many actions must be taken according to interface state changes. New network
98
 * LSAs must be originated, flushed, new multicast sockets to listen for messages for
99
 * %ALLDROUTERS have to be opened, etc.
100
 */
101
void
102
ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
103
{
104
  struct proto_ospf *po = ifa->oa->po;
105
  struct proto *p = &po->proto;
106
  u8 oldstate = ifa->state;
107

    
108
  if (oldstate != state)
109
  {
110
    ifa->state = state;
111

    
112
    if (ifa->type == OSPF_IT_VLINK)
113
    {
114
      OSPF_TRACE(D_EVENTS,
115
                 "Changing state of virtual link %I from \"%s\" into \"%s\".",
116
                 ifa->vid, ospf_is[oldstate], ospf_is[state]);
117
      if (state == OSPF_IS_PTP)
118
      {
119
        ifa->ip_sk = ospf_open_ip_socket(ifa);
120
      }
121
    }
122
    else
123
    {
124
      OSPF_TRACE(D_EVENTS,
125
                 "Changing state of iface: %s from \"%s\" into \"%s\".",
126
                 ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
127
      if (ifa->iface->flags & IF_MULTICAST)
128
      {
129
        if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
130
        {
131
          if ((ifa->dr_sk == NULL) && (ifa->type != OSPF_IT_NBMA))
132
          {
133
            DBG("%s: Adding new multicast socket for (B)DR\n", p->name);
134
            ifa->dr_sk = sk_new(p->pool);
135
            ifa->dr_sk->type = SK_IP_MC;
136
            ifa->dr_sk->sport = 0;
137
            ifa->dr_sk->dport = OSPF_PROTO;
138
            ifa->dr_sk->saddr = AllDRouters;
139
            ifa->dr_sk->daddr = AllDRouters;
140
            ifa->dr_sk->tos = IP_PREC_INTERNET_CONTROL;
141
            ifa->dr_sk->ttl = 1;
142
            ifa->dr_sk->rx_hook = ospf_rx_hook;
143
            ifa->dr_sk->tx_hook = ospf_tx_hook;
144
            ifa->dr_sk->err_hook = ospf_err_hook;
145
            ifa->dr_sk->iface = ifa->iface;
146
            ifa->dr_sk->rbsize = rxbufsize(ifa);
147
            ifa->dr_sk->tbsize = ifa->iface->mtu;
148
            ifa->dr_sk->data = (void *) ifa;
149
            if (sk_open(ifa->dr_sk) != 0)
150
            {
151
              DBG("%s: SK_OPEN: new? mc open failed.\n", p->name);
152
            }
153
          }
154
        }
155
        else
156
        {
157
          rfree(ifa->dr_sk);
158
          ifa->dr_sk = NULL;
159
        }
160
        if ((oldstate == OSPF_IS_DR) && (ifa->nlsa != NULL))
161
        {
162
          ifa->nlsa->lsa.age = LSA_MAXAGE;
163
          if (state >= OSPF_IS_WAITING)
164
          {
165
            ospf_lsupd_flush_nlsa(ifa->nlsa, ifa->oa);
166
          }
167
          if (can_flush_lsa(po))
168
            flush_lsa(ifa->nlsa, po);
169
          ifa->nlsa = NULL;
170
        }
171
      }
172
    }
173
  }
174
}
175

    
176
static void
177
ospf_iface_down(struct ospf_iface *ifa)
178
{
179
  struct ospf_neighbor *n, *nx;
180
  struct proto_ospf *po = ifa->oa->po;
181
  struct proto *p = &po->proto;
182
  struct ospf_iface *iff;
183

    
184
  /* First of all kill all the related vlinks */
185
  if (ifa->type != OSPF_IT_VLINK)
186
  {
187
    WALK_LIST(iff, po->iface_list)
188
    {
189
      if ((iff->type == OSPF_IT_VLINK) && (iff->iface == ifa->iface))
190
        ospf_iface_down(iff);
191
    }
192
  }
193

    
194
  WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
195
  {
196
    OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
197
    ospf_neigh_remove(n);
198
  }
199
  rfree(ifa->hello_sk);
200
  rfree(ifa->dr_sk);
201
  rfree(ifa->ip_sk);
202

    
203
  if (ifa->type == OSPF_IT_VLINK)
204
  {
205
    ifa->ip_sk = NULL;
206
    ifa->iface = NULL;
207
    return;
208
  }
209
  else
210
  {
211
    rfree(ifa->wait_timer);
212
    rfree(ifa->hello_timer);
213
    rfree(ifa->poll_timer);
214
    rfree(ifa->lock);
215
    rem_node(NODE ifa);
216
    mb_free(ifa);
217
  }
218
}
219

    
220
/**
221
 * ospf_iface_sm - OSPF interface state machine
222
 * @ifa: OSPF interface
223
 * @event: event comming to state machine
224
 *
225
 * This fully respects 9.3 of RFC 2328 except we don't use %LOOP state of
226
 * interface.
227
 */
228
void
229
ospf_iface_sm(struct ospf_iface *ifa, int event)
230
{
231
  struct ospf_area *oa = ifa->oa;
232

    
233
  DBG("SM on iface %s. Event is '%s'\n", ifa->iface->name, ospf_ism[event]);
234

    
235
  switch (event)
236
  {
237
  case ISM_UP:
238
    if (ifa->state == OSPF_IS_DOWN)
239
    {
240
      /* Now, nothing should be adjacent */
241
      if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_VLINK))
242
      {
243
        ospf_iface_chstate(ifa, OSPF_IS_PTP);
244
      }
245
      else
246
      {
247
        if (ifa->priority == 0)
248
          ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
249
        else
250
        {
251
          ospf_iface_chstate(ifa, OSPF_IS_WAITING);
252
          tm_start(ifa->wait_timer, ifa->waitint);
253
        }
254
      }
255

    
256
      tm_start(ifa->hello_timer, ifa->helloint);
257

    
258
      if (ifa->poll_timer)
259
        tm_start(ifa->poll_timer, ifa->pollint);
260

    
261
      hello_timer_hook(ifa->hello_timer);
262
    }
263
    schedule_rt_lsa(ifa->oa);
264
    break;
265
  case ISM_BACKS:
266
  case ISM_WAITF:
267
    if (ifa->state == OSPF_IS_WAITING)
268
    {
269
      bdr_election(ifa);
270
    }
271
    break;
272
  case ISM_NEICH:
273
    if ((ifa->state == OSPF_IS_DROTHER) || (ifa->state == OSPF_IS_DR) ||
274
        (ifa->state == OSPF_IS_BACKUP))
275
    {
276
      bdr_election(ifa);
277
      schedule_rt_lsa(ifa->oa);
278
    }
279
    break;
280
  case ISM_DOWN:
281
    ospf_iface_chstate(ifa, OSPF_IS_DOWN);
282
    ospf_iface_down(ifa);
283
    schedule_rt_lsa(oa);
284
    break;
285
  case ISM_LOOP:                /* Useless? */
286
    ospf_iface_chstate(ifa, OSPF_IS_LOOP);
287
    ospf_iface_down(ifa);
288
    schedule_rt_lsa(ifa->oa);
289
    break;
290
  case ISM_UNLOOP:
291
    ospf_iface_chstate(ifa, OSPF_IS_DOWN);
292
    schedule_rt_lsa(ifa->oa);
293
    break;
294
  default:
295
    bug("OSPF_I_SM - Unknown event?");
296
    break;
297
  }
298

    
299
}
300

    
301
static sock *
302
ospf_open_mc_socket(struct ospf_iface *ifa)
303
{
304
  sock *mcsk;
305
  struct proto *p = &ifa->oa->po->proto;
306

    
307
  mcsk = sk_new(p->pool);
308
  mcsk->type = SK_IP_MC;
309
  mcsk->sport = 0;
310
  mcsk->dport = OSPF_PROTO;
311
  mcsk->saddr = AllSPFRouters;
312
  mcsk->daddr = AllSPFRouters;
313
  mcsk->tos = IP_PREC_INTERNET_CONTROL;
314
  mcsk->ttl = 1;
315
  mcsk->rx_hook = ospf_rx_hook;
316
  mcsk->tx_hook = ospf_tx_hook;
317
  mcsk->err_hook = ospf_err_hook;
318
  mcsk->iface = ifa->iface;
319
  mcsk->rbsize = rxbufsize(ifa);
320
  mcsk->tbsize = ifa->iface->mtu;
321
  mcsk->data = (void *) ifa;
322
  if (sk_open(mcsk) != 0)
323
  {
324
    DBG("%s: SK_OPEN: mc open failed.\n", p->name);
325
    return (NULL);
326
  }
327
  DBG("%s: SK_OPEN: mc opened.\n", p->name);
328
  return (mcsk);
329
}
330

    
331
u8
332
ospf_iface_clasify(struct iface * ifa)
333
{
334
  if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) ==
335
      (IF_MULTIACCESS | IF_MULTICAST))
336
    return OSPF_IT_BCAST;
337

    
338
  if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) == IF_MULTIACCESS)
339
    return OSPF_IT_NBMA;
340

    
341
  return OSPF_IT_PTP;
342
}
343

    
344
struct ospf_iface *
345
ospf_iface_find(struct proto_ospf *p, struct iface *what)
346
{
347
  struct ospf_iface *i;
348

    
349
  WALK_LIST(i, p->iface_list) if ((i->iface == what) && (i->type != OSPF_IT_VLINK))
350
    return i;
351
  return NULL;
352
}
353

    
354
static void
355
ospf_iface_add(struct object_lock *lock)
356
{
357
  struct ospf_iface *ifa = lock->data;
358
  struct proto_ospf *po = ifa->oa->po;
359
  struct proto *p = &po->proto;
360
  struct iface *iface = lock->iface;
361

    
362
  ifa->lock = lock;
363

    
364
  ifa->ioprob = OSPF_I_OK;
365

    
366
  if (ifa->type != OSPF_IT_NBMA)
367
  {
368
    if ((ifa->hello_sk = ospf_open_mc_socket(ifa)) == NULL)
369
    {
370
      log("%s: Huh? could not open mc socket on interface %s?", p->name,
371
          iface->name);
372
      log("%s: Declaring as stub.", p->name);
373
      ifa->stub = 1;
374
      ifa->ioprob += OSPF_I_MC;
375
    }
376
    ifa->dr_sk = NULL;
377
  }
378

    
379
  if ((ifa->ip_sk = ospf_open_ip_socket(ifa)) == NULL)
380
  {
381
    log("%s: Huh? could not open ip socket on interface %s?", p->name,
382
        iface->name);
383
    log("%s: Declaring as stub.", p->name);
384
    ifa->stub = 1;
385
    ifa->ioprob += OSPF_I_IP;
386
  }
387

    
388
  ifa->state = OSPF_IS_DOWN;
389
  ospf_iface_sm(ifa, ISM_UP);
390
}
391

    
392
void
393
ospf_iface_new(struct proto_ospf *po, struct iface *iface,
394
               struct ospf_area_config *ac, struct ospf_iface_patt *ip)
395
{
396
  struct proto *p = &po->proto;
397
  struct ospf_iface *ifa;
398
  struct nbma_node *nbma, *nb;
399
  struct object_lock *lock;
400
  struct ospf_area *oa;
401

    
402
  ifa = mb_allocz(p->pool, sizeof(struct ospf_iface));
403
  ifa->iface = iface;
404

    
405
  ifa->cost = ip->cost;
406
  ifa->rxmtint = ip->rxmtint;
407
  ifa->inftransdelay = ip->inftransdelay;
408
  ifa->priority = ip->priority;
409
  ifa->helloint = ip->helloint;
410
  ifa->pollint = ip->pollint;
411
  ifa->strictnbma = ip->strictnbma;
412
  ifa->waitint = ip->waitint;
413
  ifa->dead = (ip->dead == 0) ? ip->deadc * ifa->helloint : ip->dead;
414
  ifa->stub = ip->stub;
415
  ifa->autype = ip->autype;
416
  ifa->passwords = ip->passwords;
417
  ifa->rxbuf = ip->rxbuf;
418

    
419
  if (ip->type == OSPF_IT_UNDEF)
420
    ifa->type = ospf_iface_clasify(ifa->iface);
421
  else
422
    ifa->type = ip->type;
423

    
424
  init_list(&ifa->neigh_list);
425
  init_list(&ifa->nbma_list);
426

    
427
  WALK_LIST(nb, ip->nbma_list)
428
  {
429
    nbma = mb_alloc(p->pool, sizeof(struct nbma_node));
430
    nbma->ip = nb->ip;
431
    nbma->eligible = nb->eligible;
432
    add_tail(&ifa->nbma_list, NODE nbma);
433
  }
434

    
435
  /* Add hello timer */
436
  ifa->hello_timer = tm_new(p->pool);
437
  ifa->hello_timer->data = ifa;
438
  ifa->hello_timer->randomize = 0;
439
  ifa->hello_timer->hook = hello_timer_hook;
440
  ifa->hello_timer->recurrent = ifa->helloint;
441
  DBG("%s: Installing hello timer. (%u)\n", p->name, ifa->helloint);
442

    
443
  if (ifa->type == OSPF_IT_NBMA)
444
  {
445
    ifa->poll_timer = tm_new(p->pool);
446
    ifa->poll_timer->data = ifa;
447
    ifa->poll_timer->randomize = 0;
448
    ifa->poll_timer->hook = poll_timer_hook;
449
    ifa->poll_timer->recurrent = ifa->pollint;
450
    DBG("%s: Installing poll timer. (%u)\n", p->name, ifa->pollint);
451
  }
452
  else
453
    ifa->poll_timer = NULL;
454

    
455
  ifa->wait_timer = tm_new(p->pool);
456
  ifa->wait_timer->data = ifa;
457
  ifa->wait_timer->randomize = 0;
458
  ifa->wait_timer->hook = wait_timer_hook;
459
  ifa->wait_timer->recurrent = 0;
460
  DBG("%s: Installing wait timer. (%u)\n", p->name, ifa->waitint);
461
  add_tail(&((struct proto_ospf *) p)->iface_list, NODE ifa);
462
  ifa->state = OSPF_IS_DOWN;
463

    
464
  ifa->oa = NULL;
465
  WALK_LIST(oa, po->area_list)
466
  {
467
    if (oa->areaid == ac->areaid)
468
    {
469
      ifa->oa = oa;
470
      break;
471
    }
472
  }
473

    
474
  if (!ifa->oa)
475
    bug("Cannot add any area to accepted Interface");
476
  else
477

    
478
  if (ifa->type == OSPF_IT_VLINK)
479
  {
480
    ifa->oa = po->backbone;
481
    ifa->voa = oa;
482
    ifa->vid = ip->vid;
483
    return;                        /* Don't lock, don't add sockets */
484
  }
485

    
486
  lock = olock_new(p->pool);
487
  lock->addr = AllSPFRouters;
488
  lock->type = OBJLOCK_IP;
489
  lock->port = OSPF_PROTO;
490
  lock->iface = iface;
491
  lock->data = ifa;
492
  lock->hook = ospf_iface_add;
493

    
494
  olock_acquire(lock);
495
}
496

    
497
void
498
ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa)
499
{
500
  struct proto *p = &po->proto;
501
  struct ospf_packet *op;
502
  struct ospf_neighbor *n;
503
  OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s.", ifa->iface->name);
504
  if (ifa->hello_sk)
505
  {
506
    ifa->hello_sk->rbsize = rxbufsize(ifa);
507
    ifa->hello_sk->tbsize = ifa->iface->mtu;
508
    sk_reallocate(ifa->hello_sk);
509
  }
510
  if (ifa->dr_sk)
511
  {
512
    ifa->dr_sk->rbsize = rxbufsize(ifa);
513
    ifa->dr_sk->tbsize = ifa->iface->mtu;
514
    sk_reallocate(ifa->dr_sk);
515
  }
516
  if (ifa->ip_sk)
517
  {
518
    ifa->ip_sk->rbsize = rxbufsize(ifa);
519
    ifa->ip_sk->tbsize = ifa->iface->mtu;
520
    sk_reallocate(ifa->ip_sk);
521
  }
522

    
523
  WALK_LIST(n, ifa->neigh_list)
524
  {
525
    op = (struct ospf_packet *) n->ldbdes;
526
    n->ldbdes = mb_allocz(n->pool, ifa->iface->mtu);
527

    
528
    if (ntohs(op->length) <= ifa->iface->mtu)        /* If the packet in old buffer is bigger, let it filled by zeros */
529
      memcpy(n->ldbdes, op, ifa->iface->mtu);        /* If the packet is old is same or smaller, copy it */
530

    
531
    rfree(op);
532
  }
533
}
534

    
535
void
536
ospf_iface_notify(struct proto *p, unsigned flags, struct iface *iface)
537
{
538
  struct proto_ospf *po = (struct proto_ospf *) p;
539
  struct ospf_config *c = (struct ospf_config *) (p->cf);
540
  struct ospf_area_config *ac;
541
  struct ospf_iface_patt *ip = NULL;
542
  struct ospf_iface *ifa;
543

    
544
  DBG("%s: If notify called\n", p->name);
545
  if (iface->flags & IF_IGNORE)
546
    return;
547

    
548
  if (flags & IF_CHANGE_UP)
549
  {
550
    WALK_LIST(ac, c->area_list)
551
    {
552
      if (ip = (struct ospf_iface_patt *)
553
          iface_patt_match(&ac->patt_list, iface))
554
        break;
555
    }
556

    
557
    if (ip)
558
    {
559
      OSPF_TRACE(D_EVENTS, "Using interface %s.", iface->name);
560
      ospf_iface_new(po, iface, ac, ip);
561
    }
562
  }
563

    
564
  if (flags & IF_CHANGE_DOWN)
565
  {
566
    if ((ifa = ospf_iface_find((struct proto_ospf *) p, iface)) != NULL)
567
    {
568
      OSPF_TRACE(D_EVENTS, "Killing interface %s.", iface->name);
569
      ospf_iface_sm(ifa, ISM_DOWN);
570
    }
571
  }
572

    
573
  if (flags & IF_CHANGE_MTU)
574
  {
575
    if ((ifa = ospf_iface_find((struct proto_ospf *) p, iface)) != NULL)
576
      ospf_iface_change_mtu(po, ifa);
577
  }
578
}
579

    
580
void
581
ospf_iface_info(struct ospf_iface *ifa)
582
{
583
  char *strict = "(strict)";
584

    
585
  if ((ifa->type != OSPF_IT_NBMA) || (ifa->strictnbma == 0))
586
    strict = "";
587
  if (ifa->type == OSPF_IT_VLINK)
588
  {
589
    cli_msg(-1015, "Virtual link to %I:", ifa->vid);
590
    cli_msg(-1015, "\tTransit area: %I (%u)", ifa->voa->areaid,
591
            ifa->voa->areaid);
592
  }
593
  else
594
  {
595
    cli_msg(-1015, "Interface \"%s\":",
596
            (ifa->iface ? ifa->iface->name : "(none)"));
597
    cli_msg(-1015, "\tType: %s %s", ospf_it[ifa->type], strict);
598
    cli_msg(-1015, "\tArea: %I (%u)", ifa->oa->areaid, ifa->oa->areaid);
599
  }
600
  cli_msg(-1015, "\tState: %s %s", ospf_is[ifa->state],
601
          ifa->stub ? "(stub)" : "");
602
  cli_msg(-1015, "\tPriority: %u", ifa->priority);
603
  cli_msg(-1015, "\tCost: %u", ifa->cost);
604
  cli_msg(-1015, "\tHello timer: %u", ifa->helloint);
605
  if (ifa->type == OSPF_IT_NBMA)
606
  {
607
    cli_msg(-1015, "\tPoll timer: %u", ifa->pollint);
608
  }
609
  cli_msg(-1015, "\tWait timer: %u", ifa->waitint);
610
  cli_msg(-1015, "\tDead timer: %u", ifa->dead);
611
  cli_msg(-1015, "\tRetransmit timer: %u", ifa->rxmtint);
612
  if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
613
  {
614
    cli_msg(-1015, "\tDesigned router (ID): %I", ifa->drid);
615
    cli_msg(-1015, "\tDesigned router (IP): %I", ifa->drip);
616
    cli_msg(-1015, "\tBackup designed router (ID): %I", ifa->bdrid);
617
    cli_msg(-1015, "\tBackup designed router (IP): %I", ifa->bdrip);
618
  }
619
}
620

    
621
void
622
ospf_iface_shutdown(struct ospf_iface *ifa)
623
{
624
  init_list(&ifa->neigh_list);
625
  hello_timer_hook(ifa->hello_timer);
626
}