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