]> git.ipfire.org Git - thirdparty/bird.git/blame - sysdep/linux/krt-scan.c
More changes to the kernel syncer.
[thirdparty/bird.git] / sysdep / linux / krt-scan.c
CommitLineData
7e7790c6
MM
1/*
2 * BIRD -- Linux Routing Table Scanning
3 *
ed245f96 4 * (c) 1998--1999 Martin Mares <mj@ucw.cz>
7e7790c6
MM
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9#include <string.h>
16a8ba30 10#include <stdio.h>
8e66a0eb 11#include <ctype.h>
16a8ba30
MM
12#include <fcntl.h>
13#include <unistd.h>
14#include <net/route.h>
7e7790c6
MM
15
16#define LOCAL_DEBUG
17
18#include "nest/bird.h"
7e7790c6
MM
19#include "nest/route.h"
20#include "nest/protocol.h"
16a8ba30 21#include "nest/iface.h"
7e7790c6
MM
22#include "lib/timer.h"
23#include "lib/unix.h"
24#include "lib/krt.h"
25
16a8ba30
MM
26static int krt_scan_fd = -1;
27
8e66a0eb 28struct iface *
2d140452 29krt_temp_iface(struct krt_proto *p, char *name)
8e66a0eb 30{
8e66a0eb
MM
31 struct iface *i;
32
2d140452 33 WALK_LIST(i, p->scan.temp_ifs)
8e66a0eb
MM
34 if (!strcmp(i->name, name))
35 return i;
f81dc856 36 i = mb_allocz(p->p.pool, sizeof(struct iface));
8e66a0eb 37 strcpy(i->name, name);
2d140452 38 add_tail(&p->scan.temp_ifs, &i->n);
8e66a0eb
MM
39 return i;
40}
41
756b86de 42static void
2d140452 43krt_parse_entry(byte *ent, struct krt_proto *p)
16a8ba30
MM
44{
45 u32 dest0, gw0, mask0;
46 ip_addr dest, gw, mask;
2d140452 47 unsigned int flags;
16a8ba30
MM
48 int masklen;
49 net *net;
f39e4713
MM
50 byte *iface = ent;
51 rta a;
2d140452 52 rte *e;
16a8ba30 53
f39e4713 54 if (sscanf(ent, "%*s\t%x\t%x\t%x\t%*d\t%*d\t%*d\t%x\t", &dest0, &gw0, &flags, &mask0) != 4)
16a8ba30 55 {
f39e4713 56 log(L_ERR "krt read: unable to parse `%s'", ent);
16a8ba30
MM
57 return;
58 }
f39e4713
MM
59 while (*ent != '\t')
60 ent++;
61 *ent = 0;
16a8ba30
MM
62
63 dest = ipa_from_u32(dest0);
64 ipa_ntoh(dest);
65 gw = ipa_from_u32(gw0);
66 ipa_ntoh(gw);
67 mask = ipa_from_u32(mask0);
68 ipa_ntoh(mask);
69 if ((masklen = ipa_mklen(mask)) < 0)
70 {
71 log(L_ERR "krt read: invalid netmask %08x", mask0);
72 return;
73 }
74 DBG("Got %I/%d via %I flags %x\n", dest, masklen, gw, flags);
75
76 if (!(flags & RTF_UP))
8e66a0eb
MM
77 {
78 DBG("Down.\n");
79 return;
80 }
16a8ba30
MM
81 if (flags & RTF_HOST)
82 masklen = 32;
83 if (flags & (RTF_DYNAMIC | RTF_MODIFIED)) /* Redirect route */
84 {
85 log(L_WARN "krt: Ignoring redirect to %I/%d via %I", dest, masklen, gw);
86 return;
87 }
f39e4713 88
16a8ba30 89 net = net_get(&master_table, 0, dest, masklen);
8e66a0eb 90
2d140452 91 a.proto = &p->p;
f39e4713
MM
92 a.source = RTS_INHERIT;
93 a.scope = SCOPE_UNIVERSE;
94 a.cast = RTC_UNICAST;
95 a.tos = a.flags = a.aflags = 0;
96 a.from = IPA_NONE;
97 a.iface = NULL;
98 a.attrs = NULL;
99
100 if (flags & RTF_GATEWAY)
16a8ba30 101 {
2d140452 102 neighbor *ng = neigh_find(&p->p, &gw, 0);
f39e4713
MM
103 if (ng)
104 a.iface = ng->iface;
105 else
106 /* FIXME: Remove this warning? */
8e66a0eb 107 log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", gw, net->n.prefix, net->n.pxlen);
f39e4713
MM
108 a.dest = RTD_ROUTER;
109 a.gw = gw;
110 }
111 else if (flags & RTF_REJECT)
112 {
113 a.dest = RTD_UNREACHABLE;
114 a.gw = IPA_NONE;
16a8ba30 115 }
8e66a0eb
MM
116 else if (isalpha(iface[0]))
117 {
118 a.dest = RTD_DEVICE;
119 a.gw = IPA_NONE;
2d140452 120 a.iface = krt_temp_iface(p, iface);
8e66a0eb 121 }
16a8ba30
MM
122 else
123 {
8e66a0eb 124 log(L_WARN "Kernel reporting unknown route type to %I/%d", net->n.prefix, net->n.pxlen);
f39e4713
MM
125 return;
126 }
127
128 e = rte_get_temp(&a);
129 e->net = net;
c10421d3 130 e->u.krt.src = KRT_SRC_UNKNOWN;
2d140452 131 krt_got_route(p, e);
16a8ba30
MM
132}
133
2d140452
MM
134void
135krt_scan_fire(struct krt_proto *p)
16a8ba30
MM
136{
137 byte buf[32768];
138 int l, seen_hdr;
139
140 if (krt_scan_fd < 0)
141 {
142 krt_scan_fd = open("/proc/net/route", O_RDONLY);
143 if (krt_scan_fd < 0)
144 die("/proc/net/route: %m");
145 }
146 else if (lseek(krt_scan_fd, 0, SEEK_SET) < 0)
147 {
148 log(L_ERR "krt seek: %m");
2d140452 149 return;
16a8ba30
MM
150 }
151 seen_hdr = 0;
152 while ((l = read(krt_scan_fd, buf, sizeof(buf))) > 0)
153 {
154 byte *z = buf;
155 if (l & 127)
156 {
157 log(L_ERR "krt read: misaligned entry: l=%d", l);
2d140452 158 return;
16a8ba30
MM
159 }
160 while (l >= 128)
161 {
162 if (seen_hdr++)
756b86de 163 krt_parse_entry(z, p);
16a8ba30
MM
164 z += 128;
165 l -= 128;
166 }
167 }
168 if (l < 0)
169 {
170 log(L_ERR "krt read: %m");
2d140452 171 return;
16a8ba30
MM
172 }
173 DBG("KRT scan done, seen %d lines\n", seen_hdr);
7e7790c6
MM
174}
175
176void
ed245f96 177krt_scan_preconfig(struct krt_config *c)
7e7790c6 178{
7e7790c6
MM
179}
180
181void
182krt_scan_start(struct krt_proto *x)
183{
2d140452 184 init_list(&x->scan.temp_ifs);
7e7790c6
MM
185}
186
187void
188krt_scan_shutdown(struct krt_proto *x)
189{
7e7790c6 190}