summaryrefslogtreecommitdiffstats
path: root/sysdep/bsd/krt-scan.c
blob: e68df318eb66bc9f73dec5ea3c13bc6f09f8b7f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 *	BIRD -- *BSD Table Scanning
 *
 *	(c) 2004 Ondrej Filip <feela@network.cz>
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <net/route.h>

#undef LOCAL_DEBUG
#define LOCAL_DEBUG

#include "nest/bird.h"
#include "nest/route.h"
#include "nest/protocol.h"
#include "nest/iface.h"
#include "lib/timer.h"
#include "lib/unix.h"
#include "lib/krt.h"
#include "lib/string.h"

static int krt_scan_fd = -1;

struct iface *
krt_temp_iface(struct krt_proto *p, char *name)
{
  struct iface *i;

  WALK_LIST(i, p->scan.temp_ifs)
    if (!strcmp(i->name, name))
      return i;
  i = mb_allocz(p->p.pool, sizeof(struct iface));
  strcpy(i->name, name);
  add_tail(&p->scan.temp_ifs, &i->n);
  return i;
}


void
krt_scan_construct(struct krt_config *c)
{
}

void
krt_scan_preconfig(struct config *c)
{
}

void
krt_scan_postconfig(struct krt_config *c)
{
}

void
krt_scan_start(struct krt_proto *x, int first)
{
  init_list(&x->scan.temp_ifs);
}

void
krt_scan_shutdown(struct krt_proto *x, int last)
{
}

void
krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, int *bl, int cmd)
{
  byte *next;
  int obl, needed, mib[6], on;
  struct ks_msg *m;

  mib[0] = CTL_NET;
  mib[1] = PF_ROUTE;
  mib[2] = 0;
  mib[3] = BIRD_PF;
  mib[4] = cmd;
  mib[5] = 0;

  if( sysctl(mib, 6 , NULL , &needed, NULL, 0) < 0)
  {
    die("RT scan...");
  }

  obl = *bl;

  while(needed > *bl) *bl *= 2;
  while(needed < (*bl/2)) *bl /= 2;

  if( (obl!=*bl) || !*buf)
  {
    if(*buf) mb_free(*buf);
    if( (*buf = mb_alloc(pool, *bl)) == NULL ) die("RT scan buf alloc");
  }

  on = needed;

  if( sysctl(mib, 6 , *buf, &needed, NULL, 0) < 0)
  {
    if(on != needed) return; 	/* The buffer size changed since last sysctl */
    die("RT scan 2");
  }

  for (next = *buf; next < (*buf + needed); next += m->rtm.rtm_msglen)
  {
    m = (struct ks_msg *)next;
    krt_read_msg(p, m, 1);
  }
}

void
krt_scan_fire(struct krt_proto *p)
{
  static byte *buf = NULL;
  static int bl = 32768;
  krt_sysctl_scan((struct proto *)p , p->krt_pool, &buf, &bl, NET_RT_DUMP);
}

void
krt_if_scan(struct kif_proto *p)
{
  static byte *buf = NULL;
  static int bl = 4096;
  struct proto *P = (struct proto *)p;
  if_start_update();
  krt_sysctl_scan(P, P->pool, &buf, &bl, NET_RT_IFLIST);
  if_end_update();
}