]>
Commit | Line | Data |
---|---|---|
7e7790c6 MM |
1 | /* |
2 | * BIRD -- Linux Routing Table Scanning | |
3 | * | |
832fa033 | 4 | * (c) 1998--2000 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 | 15 | |
832fa033 | 16 | #undef LOCAL_DEBUG |
7e7790c6 MM |
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 |
26 | static int krt_scan_fd = -1; |
27 | ||
8e66a0eb | 28 | struct iface * |
2d140452 | 29 | krt_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 | 42 | static void |
2d140452 | 43 | krt_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 | |
4f1a6d27 | 89 | net = net_get(p->p.table, 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; | |
08e2d625 | 95 | a.flags = a.aflags = 0; |
f39e4713 MM |
96 | a.from = IPA_NONE; |
97 | a.iface = NULL; | |
2727bb7c | 98 | a.eattrs = NULL; |
f39e4713 MM |
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 | |
476e1084 | 106 | /* FIXME: Remove this warning? Handle it somehow... */ |
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 |
134 | void |
135 | krt_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 | ||
176 | void | |
7de45ba4 | 177 | krt_scan_construct(struct krt_config *c) |
7e7790c6 | 178 | { |
7e7790c6 MM |
179 | } |
180 | ||
181 | void | |
7de45ba4 MM |
182 | krt_scan_preconfig(struct config *c) |
183 | { | |
184 | } | |
185 | ||
186 | void | |
187 | krt_scan_postconfig(struct krt_config *c) | |
188 | { | |
189 | } | |
190 | ||
191 | void | |
192 | krt_scan_start(struct krt_proto *x, int first) | |
7e7790c6 | 193 | { |
2d140452 | 194 | init_list(&x->scan.temp_ifs); |
7e7790c6 MM |
195 | } |
196 | ||
197 | void | |
7de45ba4 | 198 | krt_scan_shutdown(struct krt_proto *x, int last) |
7e7790c6 | 199 | { |
7e7790c6 | 200 | } |