1 |
|
|
/* $OpenBSD: tlv.c,v 1.15 2016/10/10 02:26:24 gsoares Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org> |
5 |
|
|
* |
6 |
|
|
* Permission to use, copy, modify, and distribute this software for any |
7 |
|
|
* purpose with or without fee is hereby granted, provided that the above |
8 |
|
|
* copyright notice and this permission notice appear in all copies. |
9 |
|
|
* |
10 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 |
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 |
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 |
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
15 |
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
16 |
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 |
|
|
*/ |
18 |
|
|
|
19 |
|
|
#include <sys/types.h> |
20 |
|
|
#include <sys/utsname.h> |
21 |
|
|
|
22 |
|
|
#include <stdio.h> |
23 |
|
|
#include <stdlib.h> |
24 |
|
|
#include <string.h> |
25 |
|
|
|
26 |
|
|
#include "eigrpd.h" |
27 |
|
|
#include "eigrpe.h" |
28 |
|
|
#include "log.h" |
29 |
|
|
|
30 |
|
|
int |
31 |
|
|
gen_parameter_tlv(struct ibuf *buf, struct eigrp_iface *ei, int peerterm) |
32 |
|
|
{ |
33 |
|
|
struct tlv_parameter tp; |
34 |
|
|
|
35 |
|
|
tp.type = htons(TLV_TYPE_PARAMETER); |
36 |
|
|
tp.length = htons(TLV_TYPE_PARAMETER_LEN); |
37 |
|
|
if (peerterm) { |
38 |
|
|
tp.kvalues[0] = 255; |
39 |
|
|
tp.kvalues[1] = 255; |
40 |
|
|
tp.kvalues[2] = 255; |
41 |
|
|
tp.kvalues[3] = 255; |
42 |
|
|
tp.kvalues[4] = 255; |
43 |
|
|
tp.kvalues[5] = 0; |
44 |
|
|
} else |
45 |
|
|
memcpy(tp.kvalues, ei->eigrp->kvalues, 6); |
46 |
|
|
tp.holdtime = htons(ei->hello_holdtime); |
47 |
|
|
|
48 |
|
|
return (ibuf_add(buf, &tp, sizeof(tp))); |
49 |
|
|
} |
50 |
|
|
|
51 |
|
|
int |
52 |
|
|
gen_sequence_tlv(struct ibuf *buf, struct seq_addr_head *seq_addr_list) |
53 |
|
|
{ |
54 |
|
|
struct tlv tlv, *tlvp; |
55 |
|
|
struct seq_addr_entry *sa; |
56 |
|
|
uint8_t alen; |
57 |
|
|
uint16_t len = TLV_HDR_LEN; |
58 |
|
|
size_t original_size = ibuf_size(buf); |
59 |
|
|
|
60 |
|
|
tlv.type = htons(TLV_TYPE_SEQ); |
61 |
|
|
if (ibuf_add(buf, &tlv, sizeof(tlv))) { |
62 |
|
|
log_warn("%s: ibuf_add failed", __func__); |
63 |
|
|
return (-1); |
64 |
|
|
} |
65 |
|
|
|
66 |
|
|
TAILQ_FOREACH(sa, seq_addr_list, entry) { |
67 |
|
|
switch (sa->af) { |
68 |
|
|
case AF_INET: |
69 |
|
|
alen = INADDRSZ; |
70 |
|
|
break; |
71 |
|
|
case AF_INET6: |
72 |
|
|
alen = IN6ADDRSZ; |
73 |
|
|
break; |
74 |
|
|
default: |
75 |
|
|
fatalx("gen_sequence_tlv: unknown address family"); |
76 |
|
|
} |
77 |
|
|
if (ibuf_add(buf, &alen, sizeof(alen))) |
78 |
|
|
return (-1); |
79 |
|
|
if (ibuf_add(buf, &sa->addr, alen)) { |
80 |
|
|
log_warn("%s: ibuf_add failed", __func__); |
81 |
|
|
return (-1); |
82 |
|
|
} |
83 |
|
|
|
84 |
|
|
len += (sizeof(alen) + alen); |
85 |
|
|
} |
86 |
|
|
|
87 |
|
|
/* adjust tlv length */ |
88 |
|
|
if ((tlvp = ibuf_seek(buf, original_size, sizeof(*tlvp))) == NULL) |
89 |
|
|
fatalx("gen_sequence_tlv: buf_seek failed"); |
90 |
|
|
tlvp->length = htons(len); |
91 |
|
|
|
92 |
|
|
return (0); |
93 |
|
|
} |
94 |
|
|
|
95 |
|
|
int |
96 |
|
|
gen_sw_version_tlv(struct ibuf *buf) |
97 |
|
|
{ |
98 |
|
|
struct tlv_sw_version ts; |
99 |
|
|
struct utsname u; |
100 |
|
|
unsigned int vendor_os_major; |
101 |
|
|
unsigned int vendor_os_minor; |
102 |
|
|
|
103 |
|
|
memset(&ts, 0, sizeof(ts)); |
104 |
|
|
ts.type = htons(TLV_TYPE_SW_VERSION); |
105 |
|
|
ts.length = htons(TLV_TYPE_SW_VERSION_LEN); |
106 |
|
|
if (uname(&u) >= 0) { |
107 |
|
|
if (sscanf(u.release, "%u.%u", &vendor_os_major, |
108 |
|
|
&vendor_os_minor) == 2) { |
109 |
|
|
ts.vendor_os_major = (uint8_t) vendor_os_major; |
110 |
|
|
ts.vendor_os_minor = (uint8_t) vendor_os_minor; |
111 |
|
|
} |
112 |
|
|
} |
113 |
|
|
ts.eigrp_major = EIGRP_VERSION_MAJOR; |
114 |
|
|
ts.eigrp_minor = EIGRP_VERSION_MINOR; |
115 |
|
|
|
116 |
|
|
return (ibuf_add(buf, &ts, sizeof(ts))); |
117 |
|
|
} |
118 |
|
|
|
119 |
|
|
int |
120 |
|
|
gen_mcast_seq_tlv(struct ibuf *buf, uint32_t seq) |
121 |
|
|
{ |
122 |
|
|
struct tlv_mcast_seq tm; |
123 |
|
|
|
124 |
|
|
tm.type = htons(TLV_TYPE_MCAST_SEQ); |
125 |
|
|
tm.length = htons(TLV_TYPE_MCAST_SEQ_LEN); |
126 |
|
|
tm.seq = htonl(seq); |
127 |
|
|
|
128 |
|
|
return (ibuf_add(buf, &tm, sizeof(tm))); |
129 |
|
|
} |
130 |
|
|
|
131 |
|
|
uint16_t |
132 |
|
|
len_route_tlv(struct rinfo *ri) |
133 |
|
|
{ |
134 |
|
|
uint16_t len = TLV_HDR_LEN; |
135 |
|
|
|
136 |
|
|
switch (ri->af) { |
137 |
|
|
case AF_INET: |
138 |
|
|
len += sizeof(ri->nexthop.v4); |
139 |
|
|
len += PREFIX_SIZE4(ri->prefixlen); |
140 |
|
|
break; |
141 |
|
|
case AF_INET6: |
142 |
|
|
len += sizeof(ri->nexthop.v6); |
143 |
|
|
len += PREFIX_SIZE6(ri->prefixlen); |
144 |
|
|
break; |
145 |
|
|
default: |
146 |
|
|
break; |
147 |
|
|
} |
148 |
|
|
|
149 |
|
|
len += sizeof(ri->metric); |
150 |
|
|
if (ri->type == EIGRP_ROUTE_EXTERNAL) |
151 |
|
|
len += sizeof(ri->emetric); |
152 |
|
|
|
153 |
|
|
len += sizeof(ri->prefixlen); |
154 |
|
|
|
155 |
|
|
return (len); |
156 |
|
|
} |
157 |
|
|
|
158 |
|
|
int |
159 |
|
|
gen_route_tlv(struct ibuf *buf, struct rinfo *ri) |
160 |
|
|
{ |
161 |
|
|
struct tlv tlv, *tlvp; |
162 |
|
|
struct in_addr addr; |
163 |
|
|
struct classic_metric metric; |
164 |
|
|
struct classic_emetric emetric; |
165 |
|
|
uint16_t tlvlen; |
166 |
|
|
uint8_t pflen; |
167 |
|
|
size_t original_size = ibuf_size(buf); |
168 |
|
|
|
169 |
|
|
switch (ri->af) { |
170 |
|
|
case AF_INET: |
171 |
|
|
tlv.type = TLV_PROTO_IPV4; |
172 |
|
|
break; |
173 |
|
|
case AF_INET6: |
174 |
|
|
tlv.type = TLV_PROTO_IPV6; |
175 |
|
|
break; |
176 |
|
|
default: |
177 |
|
|
fatalx("gen_route_tlv: unknown af"); |
178 |
|
|
} |
179 |
|
|
|
180 |
|
|
switch (ri->type) { |
181 |
|
|
case EIGRP_ROUTE_INTERNAL: |
182 |
|
|
tlv.type |= TLV_ROUTE_INTERNAL; |
183 |
|
|
break; |
184 |
|
|
case EIGRP_ROUTE_EXTERNAL: |
185 |
|
|
tlv.type |= TLV_ROUTE_EXTERNAL; |
186 |
|
|
break; |
187 |
|
|
default: |
188 |
|
|
fatalx("gen_route_tlv: unknown type"); |
189 |
|
|
} |
190 |
|
|
tlv.type = htons(tlv.type); |
191 |
|
|
|
192 |
|
|
if (ibuf_add(buf, &tlv, sizeof(tlv))) |
193 |
|
|
return (-1); |
194 |
|
|
tlvlen = TLV_HDR_LEN; |
195 |
|
|
|
196 |
|
|
/* nexthop */ |
197 |
|
|
switch (ri->af) { |
198 |
|
|
case AF_INET: |
199 |
|
|
addr.s_addr = htonl(ri->nexthop.v4.s_addr); |
200 |
|
|
if (ibuf_add(buf, &addr, sizeof(addr))) |
201 |
|
|
return (-1); |
202 |
|
|
tlvlen += sizeof(ri->nexthop.v4); |
203 |
|
|
break; |
204 |
|
|
case AF_INET6: |
205 |
|
|
if (ibuf_add(buf, &ri->nexthop.v6, sizeof(ri->nexthop.v6))) |
206 |
|
|
return (-1); |
207 |
|
|
tlvlen += sizeof(ri->nexthop.v6); |
208 |
|
|
break; |
209 |
|
|
default: |
210 |
|
|
fatalx("gen_route_tlv: unknown af"); |
211 |
|
|
} |
212 |
|
|
|
213 |
|
|
/* exterior metric */ |
214 |
|
|
if (ri->type == EIGRP_ROUTE_EXTERNAL) { |
215 |
|
|
emetric = ri->emetric; |
216 |
|
|
emetric.routerid = htonl(emetric.routerid); |
217 |
|
|
emetric.as = htonl(emetric.as); |
218 |
|
|
emetric.tag = htonl(emetric.tag); |
219 |
|
|
emetric.metric = htonl(emetric.metric); |
220 |
|
|
emetric.reserved = htons(emetric.reserved); |
221 |
|
|
if (ibuf_add(buf, &emetric, sizeof(emetric))) |
222 |
|
|
return (-1); |
223 |
|
|
tlvlen += sizeof(emetric); |
224 |
|
|
} |
225 |
|
|
|
226 |
|
|
/* metric */ |
227 |
|
|
metric = ri->metric; |
228 |
|
|
metric.delay = htonl(metric.delay); |
229 |
|
|
metric.bandwidth = htonl(metric.bandwidth); |
230 |
|
|
if (ibuf_add(buf, &metric, sizeof(metric))) |
231 |
|
|
return (-1); |
232 |
|
|
tlvlen += sizeof(metric); |
233 |
|
|
|
234 |
|
|
/* destination */ |
235 |
|
|
if (ibuf_add(buf, &ri->prefixlen, sizeof(ri->prefixlen))) |
236 |
|
|
return (-1); |
237 |
|
|
switch (ri->af) { |
238 |
|
|
case AF_INET: |
239 |
|
|
pflen = PREFIX_SIZE4(ri->prefixlen); |
240 |
|
|
if (ibuf_add(buf, &ri->prefix.v4, pflen)) |
241 |
|
|
return (-1); |
242 |
|
|
break; |
243 |
|
|
case AF_INET6: |
244 |
|
|
pflen = PREFIX_SIZE6(ri->prefixlen); |
245 |
|
|
if (ibuf_add(buf, &ri->prefix.v6, pflen)) |
246 |
|
|
return (-1); |
247 |
|
|
break; |
248 |
|
|
default: |
249 |
|
|
fatalx("gen_route_tlv: unknown af"); |
250 |
|
|
} |
251 |
|
|
tlvlen += sizeof(pflen) + pflen; |
252 |
|
|
|
253 |
|
|
/* adjust tlv length */ |
254 |
|
|
if ((tlvp = ibuf_seek(buf, original_size, sizeof(*tlvp))) == NULL) |
255 |
|
|
fatalx("gen_route_tlv: buf_seek failed"); |
256 |
|
|
tlvp->length = htons(tlvlen); |
257 |
|
|
|
258 |
|
|
return (0); |
259 |
|
|
} |
260 |
|
|
|
261 |
|
|
struct tlv_parameter * |
262 |
|
|
tlv_decode_parameter(struct tlv *tlv, char *buf) |
263 |
|
|
{ |
264 |
|
|
struct tlv_parameter *tp; |
265 |
|
|
|
266 |
|
|
if (ntohs(tlv->length) != TLV_TYPE_PARAMETER_LEN) { |
267 |
|
|
log_debug("%s: malformed tlv (bad length)", __func__); |
268 |
|
|
return (NULL); |
269 |
|
|
} |
270 |
|
|
tp = (struct tlv_parameter *)buf; |
271 |
|
|
return (tp); |
272 |
|
|
} |
273 |
|
|
|
274 |
|
|
int |
275 |
|
|
tlv_decode_seq(int af, struct tlv *tlv, char *buf, |
276 |
|
|
struct seq_addr_head *seq_addr_list) |
277 |
|
|
{ |
278 |
|
|
uint16_t len; |
279 |
|
|
uint8_t alen; |
280 |
|
|
struct seq_addr_entry *sa; |
281 |
|
|
|
282 |
|
|
len = ntohs(tlv->length); |
283 |
|
|
if (len < TLV_HDR_LEN) { |
284 |
|
|
log_debug("%s: malformed tlv (bad length)", __func__); |
285 |
|
|
return (-1); |
286 |
|
|
} |
287 |
|
|
buf += TLV_HDR_LEN; |
288 |
|
|
len -= TLV_HDR_LEN; |
289 |
|
|
|
290 |
|
|
while (len > 0) { |
291 |
|
|
memcpy(&alen, buf, sizeof(alen)); |
292 |
|
|
buf += sizeof(alen); |
293 |
|
|
len -= sizeof(alen); |
294 |
|
|
if (alen > len) { |
295 |
|
|
log_debug("%s: malformed tlv (bad length)", __func__); |
296 |
|
|
return (-1); |
297 |
|
|
} |
298 |
|
|
|
299 |
|
|
switch (af) { |
300 |
|
|
case AF_INET: |
301 |
|
|
if (alen != INADDRSZ) { |
302 |
|
|
log_debug("%s: invalid address length", |
303 |
|
|
__func__); |
304 |
|
|
return (-1); |
305 |
|
|
} |
306 |
|
|
break; |
307 |
|
|
case AF_INET6: |
308 |
|
|
if (alen != IN6ADDRSZ) { |
309 |
|
|
log_debug("%s: invalid address length", |
310 |
|
|
__func__); |
311 |
|
|
return (-1); |
312 |
|
|
} |
313 |
|
|
break; |
314 |
|
|
default: |
315 |
|
|
fatalx("tlv_decode_seq: unknown af"); |
316 |
|
|
} |
317 |
|
|
if ((sa = calloc(1, sizeof(*sa))) == NULL) |
318 |
|
|
fatal("tlv_decode_seq"); |
319 |
|
|
sa->af = af; |
320 |
|
|
memcpy(&sa->addr, buf, alen); |
321 |
|
|
TAILQ_INSERT_TAIL(seq_addr_list, sa, entry); |
322 |
|
|
|
323 |
|
|
buf += alen; |
324 |
|
|
len -= alen; |
325 |
|
|
} |
326 |
|
|
|
327 |
|
|
return (0); |
328 |
|
|
} |
329 |
|
|
|
330 |
|
|
struct tlv_sw_version * |
331 |
|
|
tlv_decode_sw_version(struct tlv *tlv, char *buf) |
332 |
|
|
{ |
333 |
|
|
struct tlv_sw_version *tv; |
334 |
|
|
|
335 |
|
|
if (ntohs(tlv->length) != TLV_TYPE_SW_VERSION_LEN) { |
336 |
|
|
log_debug("%s: malformed tlv (bad length)", __func__); |
337 |
|
|
return (NULL); |
338 |
|
|
} |
339 |
|
|
tv = (struct tlv_sw_version *)buf; |
340 |
|
|
return (tv); |
341 |
|
|
} |
342 |
|
|
|
343 |
|
|
struct tlv_mcast_seq * |
344 |
|
|
tlv_decode_mcast_seq(struct tlv *tlv, char *buf) |
345 |
|
|
{ |
346 |
|
|
struct tlv_mcast_seq *tm; |
347 |
|
|
|
348 |
|
|
if (ntohs(tlv->length) != TLV_TYPE_MCAST_SEQ_LEN) { |
349 |
|
|
log_debug("%s: malformed tlv (bad length)", __func__); |
350 |
|
|
return (NULL); |
351 |
|
|
} |
352 |
|
|
tm = (struct tlv_mcast_seq *)buf; |
353 |
|
|
return (tm); |
354 |
|
|
} |
355 |
|
|
|
356 |
|
|
int |
357 |
|
|
tlv_decode_route(int af, struct tlv *tlv, char *buf, struct rinfo *ri) |
358 |
|
|
{ |
359 |
|
|
unsigned int tlv_len, min_len, max_plen, plen, offset; |
360 |
|
|
|
361 |
|
|
ri->af = af; |
362 |
|
|
switch (ri->af) { |
363 |
|
|
case AF_INET: |
364 |
|
|
min_len = TLV_TYPE_IPV4_INT_MIN_LEN; |
365 |
|
|
max_plen = sizeof(ri->prefix.v4); |
366 |
|
|
break; |
367 |
|
|
case AF_INET6: |
368 |
|
|
min_len = TLV_TYPE_IPV6_INT_MIN_LEN; |
369 |
|
|
max_plen = sizeof(ri->prefix.v6); |
370 |
|
|
break; |
371 |
|
|
default: |
372 |
|
|
fatalx("tlv_decode_route: unknown af"); |
373 |
|
|
} |
374 |
|
|
|
375 |
|
|
switch (ntohs(tlv->type) & TLV_TYPE_MASK) { |
376 |
|
|
case TLV_ROUTE_INTERNAL: |
377 |
|
|
ri->type = EIGRP_ROUTE_INTERNAL; |
378 |
|
|
break; |
379 |
|
|
case TLV_ROUTE_EXTERNAL: |
380 |
|
|
ri->type = EIGRP_ROUTE_EXTERNAL; |
381 |
|
|
min_len += sizeof(struct classic_emetric); |
382 |
|
|
break; |
383 |
|
|
default: |
384 |
|
|
fatalx("tlv_decode_route: unknown type"); |
385 |
|
|
} |
386 |
|
|
|
387 |
|
|
tlv_len = ntohs(tlv->length); |
388 |
|
|
if (tlv_len < min_len) { |
389 |
|
|
log_debug("%s: malformed tlv (bad length)", __func__); |
390 |
|
|
return (-1); |
391 |
|
|
} |
392 |
|
|
|
393 |
|
|
/* nexthop */ |
394 |
|
|
offset = TLV_HDR_LEN; |
395 |
|
|
switch (af) { |
396 |
|
|
case AF_INET: |
397 |
|
|
memcpy(&ri->nexthop.v4, buf + offset, sizeof(ri->nexthop.v4)); |
398 |
|
|
offset += sizeof(ri->nexthop.v4); |
399 |
|
|
break; |
400 |
|
|
case AF_INET6: |
401 |
|
|
memcpy(&ri->nexthop.v6, buf + offset, sizeof(ri->nexthop.v6)); |
402 |
|
|
offset += sizeof(ri->nexthop.v6); |
403 |
|
|
break; |
404 |
|
|
default: |
405 |
|
|
fatalx("tlv_decode_route: unknown af"); |
406 |
|
|
} |
407 |
|
|
|
408 |
|
|
/* exterior metric */ |
409 |
|
|
if (ri->type == EIGRP_ROUTE_EXTERNAL) { |
410 |
|
|
memcpy(&ri->emetric, buf + offset, sizeof(ri->emetric)); |
411 |
|
|
ri->emetric.routerid = ntohl(ri->emetric.routerid); |
412 |
|
|
ri->emetric.as = ntohl(ri->emetric.as); |
413 |
|
|
ri->emetric.tag = ntohl(ri->emetric.tag); |
414 |
|
|
ri->emetric.metric = ntohl(ri->emetric.metric); |
415 |
|
|
ri->emetric.reserved = ntohs(ri->emetric.reserved); |
416 |
|
|
offset += sizeof(ri->emetric); |
417 |
|
|
} |
418 |
|
|
|
419 |
|
|
/* metric */ |
420 |
|
|
memcpy(&ri->metric, buf + offset, sizeof(ri->metric)); |
421 |
|
|
ri->metric.delay = ntohl(ri->metric.delay); |
422 |
|
|
ri->metric.bandwidth = ntohl(ri->metric.bandwidth); |
423 |
|
|
offset += sizeof(ri->metric); |
424 |
|
|
|
425 |
|
|
/* prefixlen */ |
426 |
|
|
memcpy(&ri->prefixlen, buf + offset, sizeof(ri->prefixlen)); |
427 |
|
|
offset += sizeof(ri->prefixlen); |
428 |
|
|
|
429 |
|
|
/* |
430 |
|
|
* Different versions of IOS can use a different number of bytes to |
431 |
|
|
* encode the same IPv6 prefix. This sucks but we have to deal with it. |
432 |
|
|
* Instead of calculating the number of bytes based on the value of the |
433 |
|
|
* prefixlen field, let's get this number by subtracting the size of all |
434 |
|
|
* other fields from the total size of the TLV. It works because all |
435 |
|
|
* the other fields have a fixed length. |
436 |
|
|
*/ |
437 |
|
|
plen = tlv_len - min_len; |
438 |
|
|
|
439 |
|
|
/* safety check */ |
440 |
|
|
if (plen > max_plen) { |
441 |
|
|
log_debug("%s: malformed tlv", __func__); |
442 |
|
|
return (-1); |
443 |
|
|
} |
444 |
|
|
|
445 |
|
|
/* destination */ |
446 |
|
|
switch (af) { |
447 |
|
|
case AF_INET: |
448 |
|
|
memset(&ri->prefix.v4, 0, sizeof(ri->prefix.v4)); |
449 |
|
|
memcpy(&ri->prefix.v4, buf + offset, plen); |
450 |
|
|
break; |
451 |
|
|
case AF_INET6: |
452 |
|
|
memset(&ri->prefix.v6, 0, sizeof(ri->prefix.v6)); |
453 |
|
|
memcpy(&ri->prefix.v6, buf + offset, plen); |
454 |
|
|
break; |
455 |
|
|
default: |
456 |
|
|
fatalx("tlv_decode_route: unknown af"); |
457 |
|
|
} |
458 |
|
|
|
459 |
|
|
/* check if the network is valid */ |
460 |
|
|
if (bad_addr(af, &ri->prefix) || |
461 |
|
|
(af == AF_INET6 && IN6_IS_SCOPE_EMBED(&ri->prefix.v6))) { |
462 |
|
|
log_debug("%s: malformed tlv (invalid prefix): %s", __func__, |
463 |
|
|
log_addr(af, &ri->prefix)); |
464 |
|
|
return (-1); |
465 |
|
|
} |
466 |
|
|
|
467 |
|
|
/* just in case... */ |
468 |
|
|
eigrp_applymask(af, &ri->prefix, &ri->prefix, ri->prefixlen); |
469 |
|
|
|
470 |
|
|
return (0); |
471 |
|
|
} |
472 |
|
|
|
473 |
|
|
void |
474 |
|
|
metric_encode_mtu(uint8_t *dst, int mtu) |
475 |
|
|
{ |
476 |
|
|
dst[0] = (mtu & 0x00FF0000) >> 16; |
477 |
|
|
dst[1] = (mtu & 0x0000FF00) >> 8; |
478 |
|
|
dst[2] = (mtu & 0x000000FF); |
479 |
|
|
} |
480 |
|
|
|
481 |
|
|
int |
482 |
|
|
metric_decode_mtu(uint8_t *mtu) |
483 |
|
|
{ |
484 |
|
|
return ((mtu[0] << 16) + (mtu[1] << 8) + mtu[2]); |
485 |
|
|
} |