]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_packet.c
zebra: Allow ns delete to happen after under/over flow checks
[mirror_frr.git] / eigrpd / eigrp_packet.c
1 /*
2 * EIGRP General Sending and Receiving of EIGRP Packets.
3 * Copyright (C) 2013-2014
4 * Authors:
5 * Donnie Savage
6 * Jan Janovic
7 * Matej Perina
8 * Peter Orsag
9 * Peter Paluch
10 *
11 * This file is part of GNU Zebra.
12 *
13 * GNU Zebra is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2, or (at your option) any
16 * later version.
17 *
18 * GNU Zebra is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License along
24 * with this program; see the file COPYING; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 */
27
28 #include <zebra.h>
29
30 #include "thread.h"
31 #include "memory.h"
32 #include "linklist.h"
33 #include "vty.h"
34 #include "keychain.h"
35 #include "prefix.h"
36 #include "if.h"
37 #include "table.h"
38 #include "sockunion.h"
39 #include "stream.h"
40 #include "log.h"
41 #include "sockopt.h"
42 #include "checksum.h"
43 #include "md5.h"
44 #include "sha256.h"
45 #include "lib_errors.h"
46
47 #include "eigrpd/eigrp_structs.h"
48 #include "eigrpd/eigrpd.h"
49 #include "eigrpd/eigrp_interface.h"
50 #include "eigrpd/eigrp_neighbor.h"
51 #include "eigrpd/eigrp_packet.h"
52 #include "eigrpd/eigrp_zebra.h"
53 #include "eigrpd/eigrp_vty.h"
54 #include "eigrpd/eigrp_dump.h"
55 #include "eigrpd/eigrp_macros.h"
56 #include "eigrpd/eigrp_network.h"
57 #include "eigrpd/eigrp_topology.h"
58 #include "eigrpd/eigrp_fsm.h"
59 #include "eigrpd/eigrp_memory.h"
60 #include "eigrpd/eigrp_errors.h"
61
62 /* Packet Type String. */
63 const struct message eigrp_packet_type_str[] = {
64 {EIGRP_OPC_UPDATE, "Update"},
65 {EIGRP_OPC_REQUEST, "Request"},
66 {EIGRP_OPC_QUERY, "Query"},
67 {EIGRP_OPC_REPLY, "Reply"},
68 {EIGRP_OPC_HELLO, "Hello"},
69 {EIGRP_OPC_IPXSAP, "IPX-SAP"},
70 {EIGRP_OPC_PROBE, "Probe"},
71 {EIGRP_OPC_ACK, "Ack"},
72 {EIGRP_OPC_SIAQUERY, "SIAQuery"},
73 {EIGRP_OPC_SIAREPLY, "SIAReply"},
74 {0}};
75
76
77 static unsigned char zeropad[16] = {0};
78
79 /* Forward function reference*/
80 static struct stream *eigrp_recv_packet(int, struct interface **,
81 struct stream *);
82 static int eigrp_verify_header(struct stream *, struct eigrp_interface *,
83 struct ip *, struct eigrp_header *);
84 static int eigrp_check_network_mask(struct eigrp_interface *, struct in_addr);
85
86 static int eigrp_retrans_count_exceeded(struct eigrp_packet *ep,
87 struct eigrp_neighbor *nbr)
88 {
89 return 1;
90 }
91
92 int eigrp_make_md5_digest(struct eigrp_interface *ei, struct stream *s,
93 uint8_t flags)
94 {
95 struct key *key = NULL;
96 struct keychain *keychain;
97
98 unsigned char digest[EIGRP_AUTH_TYPE_MD5_LEN];
99 MD5_CTX ctx;
100 uint8_t *ibuf;
101 size_t backup_get, backup_end;
102 struct TLV_MD5_Authentication_Type *auth_TLV;
103
104 ibuf = s->data;
105 backup_end = s->endp;
106 backup_get = s->getp;
107
108 auth_TLV = eigrp_authTLV_MD5_new();
109
110 stream_set_getp(s, EIGRP_HEADER_LEN);
111 stream_get(auth_TLV, s, EIGRP_AUTH_MD5_TLV_SIZE);
112 stream_set_getp(s, backup_get);
113
114 keychain = keychain_lookup(ei->params.auth_keychain);
115 if (keychain)
116 key = key_lookup_for_send(keychain);
117 else {
118 eigrp_authTLV_MD5_free(auth_TLV);
119 return EIGRP_AUTH_TYPE_NONE;
120 }
121
122 memset(&ctx, 0, sizeof(ctx));
123 MD5Init(&ctx);
124
125 /* Generate a digest. Each situation needs different handling */
126 if (flags & EIGRP_AUTH_BASIC_HELLO_FLAG) {
127 MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE);
128 MD5Update(&ctx, key->string, strlen(key->string));
129 if (strlen(key->string) < 16)
130 MD5Update(&ctx, zeropad, 16 - strlen(key->string));
131 } else if (flags & EIGRP_AUTH_UPDATE_INIT_FLAG) {
132 MD5Update(&ctx, ibuf, EIGRP_MD5_UPDATE_INIT_COMPUTE);
133 } else if (flags & EIGRP_AUTH_UPDATE_FLAG) {
134 MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE);
135 MD5Update(&ctx, key->string, strlen(key->string));
136 if (strlen(key->string) < 16)
137 MD5Update(&ctx, zeropad, 16 - strlen(key->string));
138 if (backup_end > (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)) {
139 MD5Update(&ctx,
140 ibuf + (EIGRP_HEADER_LEN
141 + EIGRP_AUTH_MD5_TLV_SIZE),
142 backup_end - 20
143 - (EIGRP_HEADER_LEN
144 + EIGRP_AUTH_MD5_TLV_SIZE));
145 }
146 }
147
148 MD5Final(digest, &ctx);
149
150 /* Append md5 digest to the end of the stream. */
151 memcpy(auth_TLV->digest, digest, EIGRP_AUTH_TYPE_MD5_LEN);
152
153 stream_set_endp(s, EIGRP_HEADER_LEN);
154 stream_put(s, auth_TLV, EIGRP_AUTH_MD5_TLV_SIZE);
155 stream_set_endp(s, backup_end);
156
157 eigrp_authTLV_MD5_free(auth_TLV);
158 return EIGRP_AUTH_TYPE_MD5_LEN;
159 }
160
161 int eigrp_check_md5_digest(struct stream *s,
162 struct TLV_MD5_Authentication_Type *authTLV,
163 struct eigrp_neighbor *nbr, uint8_t flags)
164 {
165 MD5_CTX ctx;
166 unsigned char digest[EIGRP_AUTH_TYPE_MD5_LEN];
167 unsigned char orig[EIGRP_AUTH_TYPE_MD5_LEN];
168 struct key *key = NULL;
169 struct keychain *keychain;
170 uint8_t *ibuf;
171 size_t backup_end;
172 struct TLV_MD5_Authentication_Type *auth_TLV;
173 struct eigrp_header *eigrph;
174
175 if (ntohl(nbr->crypt_seqnum) > ntohl(authTLV->key_sequence)) {
176 zlog_warn(
177 "interface %s: eigrp_check_md5 bad sequence %d (expect %d)",
178 IF_NAME(nbr->ei), ntohl(authTLV->key_sequence),
179 ntohl(nbr->crypt_seqnum));
180 return 0;
181 }
182
183 eigrph = (struct eigrp_header *)s->data;
184 eigrph->checksum = 0;
185
186 auth_TLV = (struct TLV_MD5_Authentication_Type *)(s->data
187 + EIGRP_HEADER_LEN);
188 memcpy(orig, auth_TLV->digest, EIGRP_AUTH_TYPE_MD5_LEN);
189 memset(digest, 0, EIGRP_AUTH_TYPE_MD5_LEN);
190 memset(auth_TLV->digest, 0, EIGRP_AUTH_TYPE_MD5_LEN);
191
192 ibuf = s->data;
193 backup_end = s->endp;
194
195 keychain = keychain_lookup(nbr->ei->params.auth_keychain);
196 if (keychain)
197 key = key_lookup_for_send(keychain);
198
199 if (!key) {
200 zlog_warn(
201 "Interface %s: Expected key value not found in config",
202 nbr->ei->ifp->name);
203 return 0;
204 }
205
206 memset(&ctx, 0, sizeof(ctx));
207 MD5Init(&ctx);
208
209 /* Generate a digest. Each situation needs different handling */
210 if (flags & EIGRP_AUTH_BASIC_HELLO_FLAG) {
211 MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE);
212 MD5Update(&ctx, key->string, strlen(key->string));
213 if (strlen(key->string) < 16)
214 MD5Update(&ctx, zeropad, 16 - strlen(key->string));
215 } else if (flags & EIGRP_AUTH_UPDATE_INIT_FLAG) {
216 MD5Update(&ctx, ibuf, EIGRP_MD5_UPDATE_INIT_COMPUTE);
217 } else if (flags & EIGRP_AUTH_UPDATE_FLAG) {
218 MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE);
219 MD5Update(&ctx, key->string, strlen(key->string));
220 if (strlen(key->string) < 16)
221 MD5Update(&ctx, zeropad, 16 - strlen(key->string));
222 if (backup_end > (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)) {
223 MD5Update(&ctx,
224 ibuf + (EIGRP_HEADER_LEN
225 + EIGRP_AUTH_MD5_TLV_SIZE),
226 backup_end - 20
227 - (EIGRP_HEADER_LEN
228 + EIGRP_AUTH_MD5_TLV_SIZE));
229 }
230 }
231
232 MD5Final(digest, &ctx);
233
234 /* compare the two */
235 if (memcmp(orig, digest, EIGRP_AUTH_TYPE_MD5_LEN) != 0) {
236 zlog_warn("interface %s: eigrp_check_md5 checksum mismatch",
237 IF_NAME(nbr->ei));
238 return 0;
239 }
240
241 /* save neighbor's crypt_seqnum */
242 nbr->crypt_seqnum = authTLV->key_sequence;
243
244 return 1;
245 }
246
247 int eigrp_make_sha256_digest(struct eigrp_interface *ei, struct stream *s,
248 uint8_t flags)
249 {
250 struct key *key = NULL;
251 struct keychain *keychain;
252 char source_ip[PREFIX_STRLEN];
253
254 unsigned char digest[EIGRP_AUTH_TYPE_SHA256_LEN];
255 unsigned char buffer[1 + PLAINTEXT_LENGTH + 45 + 1] = {0};
256
257 HMAC_SHA256_CTX ctx;
258 void *ibuf;
259 size_t backup_get, backup_end;
260 struct TLV_SHA256_Authentication_Type *auth_TLV;
261
262 ibuf = s->data;
263 backup_end = s->endp;
264 backup_get = s->getp;
265
266 auth_TLV = eigrp_authTLV_SHA256_new();
267
268 stream_set_getp(s, EIGRP_HEADER_LEN);
269 stream_get(auth_TLV, s, EIGRP_AUTH_SHA256_TLV_SIZE);
270 stream_set_getp(s, backup_get);
271
272 keychain = keychain_lookup(ei->params.auth_keychain);
273 if (keychain)
274 key = key_lookup_for_send(keychain);
275
276 if (!key) {
277 zlog_warn(
278 "Interface %s: Expected key value not found in config",
279 ei->ifp->name);
280 eigrp_authTLV_SHA256_free(auth_TLV);
281 return 0;
282 }
283
284 inet_ntop(AF_INET, &ei->address->u.prefix4, source_ip, PREFIX_STRLEN);
285
286 memset(&ctx, 0, sizeof(ctx));
287 buffer[0] = '\n';
288 memcpy(buffer + 1, key, strlen(key->string));
289 memcpy(buffer + 1 + strlen(key->string), source_ip, strlen(source_ip));
290 HMAC__SHA256_Init(&ctx, buffer,
291 1 + strlen(key->string) + strlen(source_ip));
292 HMAC__SHA256_Update(&ctx, ibuf, strlen(ibuf));
293 HMAC__SHA256_Final(digest, &ctx);
294
295
296 /* Put hmac-sha256 digest to it's place */
297 memcpy(auth_TLV->digest, digest, EIGRP_AUTH_TYPE_SHA256_LEN);
298
299 stream_set_endp(s, EIGRP_HEADER_LEN);
300 stream_put(s, auth_TLV, EIGRP_AUTH_SHA256_TLV_SIZE);
301 stream_set_endp(s, backup_end);
302
303 eigrp_authTLV_SHA256_free(auth_TLV);
304
305 return EIGRP_AUTH_TYPE_SHA256_LEN;
306 }
307
308 int eigrp_check_sha256_digest(struct stream *s,
309 struct TLV_SHA256_Authentication_Type *authTLV,
310 struct eigrp_neighbor *nbr, uint8_t flags)
311 {
312 return 1;
313 }
314
315 int eigrp_write(struct thread *thread)
316 {
317 struct eigrp *eigrp = THREAD_ARG(thread);
318 struct eigrp_header *eigrph;
319 struct eigrp_interface *ei;
320 struct eigrp_packet *ep;
321 struct sockaddr_in sa_dst;
322 struct ip iph;
323 struct msghdr msg;
324 struct iovec iov[2];
325 uint32_t seqno, ack;
326
327 int ret;
328 int flags = 0;
329 struct listnode *node;
330 #ifdef WANT_EIGRP_WRITE_FRAGMENT
331 static uint16_t ipid = 0;
332 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
333 #define EIGRP_WRITE_IPHL_SHIFT 2
334
335 eigrp->t_write = NULL;
336
337 node = listhead(eigrp->oi_write_q);
338 assert(node);
339 ei = listgetdata(node);
340 assert(ei);
341
342 #ifdef WANT_EIGRP_WRITE_FRAGMENT
343 /* seed ipid static with low order bits of time */
344 if (ipid == 0)
345 ipid = (time(NULL) & 0xffff);
346 #endif /* WANT_EIGRP_WRITE_FRAGMENT */
347
348 /* Get one packet from queue. */
349 ep = eigrp_fifo_next(ei->obuf);
350 if (!ep) {
351 flog_err(EC_LIB_DEVELOPMENT,
352 "%s: Interface %s no packet on queue?",
353 __PRETTY_FUNCTION__, ei->ifp->name);
354 goto out;
355 }
356 if (ep->length < EIGRP_HEADER_LEN) {
357 flog_err(EC_EIGRP_PACKET, "%s: Packet just has a header?",
358 __PRETTY_FUNCTION__);
359 eigrp_header_dump((struct eigrp_header *)ep->s->data);
360 eigrp_packet_delete(ei);
361 goto out;
362 }
363
364 if (ep->dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS))
365 eigrp_if_ipmulticast(eigrp, ei->address, ei->ifp->ifindex);
366
367 memset(&iph, 0, sizeof(struct ip));
368 memset(&sa_dst, 0, sizeof(sa_dst));
369
370 /*
371 * We build and schedule packets to go out
372 * in the future. In the mean time we may
373 * process some update packets from the
374 * neighbor, thus making it necessary
375 * to update the ack we are using for
376 * this outgoing packet.
377 */
378 eigrph = (struct eigrp_header *)STREAM_DATA(ep->s);
379 seqno = ntohl(eigrph->sequence);
380 ack = ntohl(eigrph->ack);
381 if (ep->nbr && (ack != ep->nbr->recv_sequence_number)) {
382 eigrph->ack = htonl(ep->nbr->recv_sequence_number);
383 ack = ep->nbr->recv_sequence_number;
384 eigrph->checksum = 0;
385 eigrp_packet_checksum(ei, ep->s, ep->length);
386 }
387
388 sa_dst.sin_family = AF_INET;
389 #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
390 sa_dst.sin_len = sizeof(sa_dst);
391 #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
392 sa_dst.sin_addr = ep->dst;
393 sa_dst.sin_port = htons(0);
394
395 /* Set DONTROUTE flag if dst is unicast. */
396 if (!IN_MULTICAST(htonl(ep->dst.s_addr)))
397 flags = MSG_DONTROUTE;
398
399 iph.ip_hl = sizeof(struct ip) >> EIGRP_WRITE_IPHL_SHIFT;
400 /* it'd be very strange for header to not be 4byte-word aligned but.. */
401 if (sizeof(struct ip)
402 > (unsigned int)(iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT))
403 iph.ip_hl++; /* we presume sizeof struct ip cant overflow
404 ip_hl.. */
405
406 iph.ip_v = IPVERSION;
407 iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;
408 iph.ip_len = (iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT) + ep->length;
409
410 #if defined(__DragonFly__)
411 /*
412 * DragonFly's raw socket expects ip_len/ip_off in network byte order.
413 */
414 iph.ip_len = htons(iph.ip_len);
415 #endif
416
417 iph.ip_off = 0;
418 iph.ip_ttl = EIGRP_IP_TTL;
419 iph.ip_p = IPPROTO_EIGRPIGP;
420 iph.ip_sum = 0;
421 iph.ip_src.s_addr = ei->address->u.prefix4.s_addr;
422 iph.ip_dst.s_addr = ep->dst.s_addr;
423
424 memset(&msg, 0, sizeof(msg));
425 msg.msg_name = (caddr_t)&sa_dst;
426 msg.msg_namelen = sizeof(sa_dst);
427 msg.msg_iov = iov;
428 msg.msg_iovlen = 2;
429
430 iov[0].iov_base = (char *)&iph;
431 iov[0].iov_len = iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT;
432 iov[1].iov_base = stream_pnt(ep->s);
433 iov[1].iov_len = ep->length;
434
435 /* send final fragment (could be first) */
436 sockopt_iphdrincl_swab_htosys(&iph);
437 ret = sendmsg(eigrp->fd, &msg, flags);
438 sockopt_iphdrincl_swab_systoh(&iph);
439
440 if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND)) {
441 eigrph = (struct eigrp_header *)STREAM_DATA(ep->s);
442 zlog_debug(
443 "Sending [%s][%d/%d] to [%s] via [%s] ret [%d].",
444 lookup_msg(eigrp_packet_type_str, eigrph->opcode, NULL),
445 seqno, ack, inet_ntoa(ep->dst), IF_NAME(ei), ret);
446 }
447
448 if (ret < 0)
449 zlog_warn(
450 "*** sendmsg in eigrp_write failed to %s, "
451 "id %d, off %d, len %d, interface %s, mtu %u: %s",
452 inet_ntoa(iph.ip_dst), iph.ip_id, iph.ip_off,
453 iph.ip_len, ei->ifp->name, ei->ifp->mtu,
454 safe_strerror(errno));
455
456 /* Now delete packet from queue. */
457 eigrp_packet_delete(ei);
458
459 out:
460 if (eigrp_fifo_next(ei->obuf) == NULL) {
461 ei->on_write_q = 0;
462 list_delete_node(eigrp->oi_write_q, node);
463 }
464
465 /* If packets still remain in queue, call write thread. */
466 if (!list_isempty(eigrp->oi_write_q)) {
467 eigrp->t_write = NULL;
468 thread_add_write(master, eigrp_write, eigrp, eigrp->fd,
469 &eigrp->t_write);
470 }
471
472 return 0;
473 }
474
475 /* Starting point of packet process function. */
476 int eigrp_read(struct thread *thread)
477 {
478 int ret;
479 struct stream *ibuf;
480 struct eigrp *eigrp;
481 struct eigrp_interface *ei;
482 struct ip *iph;
483 struct eigrp_header *eigrph;
484 struct interface *ifp;
485 struct eigrp_neighbor *nbr;
486
487 uint16_t opcode = 0;
488 uint16_t length = 0;
489
490 /* first of all get interface pointer. */
491 eigrp = THREAD_ARG(thread);
492
493 /* prepare for next packet. */
494 eigrp->t_read = NULL;
495 thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read);
496
497 stream_reset(eigrp->ibuf);
498 if (!(ibuf = eigrp_recv_packet(eigrp->fd, &ifp, eigrp->ibuf))) {
499 /* This raw packet is known to be at least as big as its IP
500 * header. */
501 return -1;
502 }
503
504 /* Note that there should not be alignment problems with this assignment
505 because this is at the beginning of the stream data buffer. */
506 iph = (struct ip *)STREAM_DATA(ibuf);
507
508 // Substract IPv4 header size from EIGRP Packet itself
509 if (iph->ip_v == 4)
510 length = (iph->ip_len) - 20U;
511
512
513 /* IP Header dump. */
514 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)
515 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))
516 eigrp_ip_header_dump(iph);
517
518 /* Note that sockopt_iphdrincl_swab_systoh was called in
519 * eigrp_recv_packet. */
520 if (ifp == NULL) {
521 struct connected *c;
522 /* Handle cases where the platform does not support retrieving
523 the ifindex,
524 and also platforms (such as Solaris 8) that claim to support
525 ifindex
526 retrieval but do not. */
527 c = if_lookup_address((void *)&iph->ip_src, AF_INET,
528 VRF_DEFAULT);
529
530 if (c == NULL)
531 return 0;
532
533 ifp = c->ifp;
534 }
535
536 /* associate packet with eigrp interface */
537 ei = ifp->info;
538
539 /* eigrp_verify_header() relies on a valid "ei" and thus can be called
540 only
541 after the checks below are passed. These checks in turn access the
542 fields of unverified "eigrph" structure for their own purposes and
543 must remain very accurate in doing this.
544 */
545 if (!ei)
546 return 0;
547
548 /* Self-originated packet should be discarded silently. */
549 if (eigrp_if_lookup_by_local_addr(eigrp, NULL, iph->ip_src)
550 || (IPV4_ADDR_SAME(&iph->ip_src, &ei->address->u.prefix4))) {
551 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
552 zlog_debug(
553 "eigrp_read[%s]: Dropping self-originated packet",
554 inet_ntoa(iph->ip_src));
555 return 0;
556 }
557
558 /* Advance from IP header to EIGRP header (iph->ip_hl has been verified
559 by eigrp_recv_packet() to be correct). */
560
561 stream_forward_getp(ibuf, (iph->ip_hl * 4));
562 eigrph = (struct eigrp_header *)stream_pnt(ibuf);
563
564 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)
565 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))
566 eigrp_header_dump(eigrph);
567
568 // if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) -
569 // stream_get_getp(ibuf)))
570 // return -1;
571
572 /* If incoming interface is passive one, ignore it. */
573 if (eigrp_if_is_passive(ei)) {
574 char buf[3][INET_ADDRSTRLEN];
575
576 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
577 zlog_debug(
578 "ignoring packet from router %s sent to %s, "
579 "received on a passive interface, %s",
580 inet_ntop(AF_INET, &eigrph->vrid, buf[0],
581 sizeof(buf[0])),
582 inet_ntop(AF_INET, &iph->ip_dst, buf[1],
583 sizeof(buf[1])),
584 inet_ntop(AF_INET, &ei->address->u.prefix4,
585 buf[2], sizeof(buf[2])));
586
587 if (iph->ip_dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS)) {
588 eigrp_if_set_multicast(ei);
589 }
590 return 0;
591 }
592
593 /* else it must be a local eigrp interface, check it was received on
594 * correct link
595 */
596 else if (ei->ifp != ifp) {
597 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
598 zlog_warn("Packet from [%s] received on wrong link %s",
599 inet_ntoa(iph->ip_src), ifp->name);
600 return 0;
601 }
602
603 /* Verify more EIGRP header fields. */
604 ret = eigrp_verify_header(ibuf, ei, iph, eigrph);
605 if (ret < 0) {
606 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
607 zlog_debug(
608 "eigrp_read[%s]: Header check failed, dropping.",
609 inet_ntoa(iph->ip_src));
610 return ret;
611 }
612
613 /* calcualte the eigrp packet length, and move the pounter to the
614 start of the eigrp TLVs */
615 opcode = eigrph->opcode;
616
617 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) {
618 char src[PREFIX_STRLEN], dst[PREFIX_STRLEN];
619
620 strlcpy(src, inet_ntoa(iph->ip_src), sizeof(src));
621 strlcpy(dst, inet_ntoa(iph->ip_dst), sizeof(dst));
622 zlog_debug(
623 "Received [%s][%d/%d] length [%u] via [%s] src [%s] dst [%s]",
624 lookup_msg(eigrp_packet_type_str, opcode, NULL),
625 ntohl(eigrph->sequence), ntohl(eigrph->ack), length,
626 IF_NAME(ei), src, dst);
627 }
628
629 /* Read rest of the packet and call each sort of packet routine. */
630 stream_forward_getp(ibuf, EIGRP_HEADER_LEN);
631
632 /* New testing block of code for handling Acks */
633 if (ntohl(eigrph->ack) != 0) {
634 struct eigrp_packet *ep = NULL;
635
636 nbr = eigrp_nbr_get(ei, eigrph, iph);
637
638 // neighbor must be valid, eigrp_nbr_get creates if none existed
639 assert(nbr);
640
641 ep = eigrp_fifo_next(nbr->retrans_queue);
642 if ((ep) && (ntohl(eigrph->ack) == ep->sequence_number)) {
643 ep = eigrp_fifo_pop(nbr->retrans_queue);
644 eigrp_packet_free(ep);
645
646 if ((nbr->state == EIGRP_NEIGHBOR_PENDING)
647 && (ntohl(eigrph->ack)
648 == nbr->init_sequence_number)) {
649 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_UP);
650 zlog_info("Neighbor(%s) adjacency became full",
651 inet_ntoa(nbr->src));
652 nbr->init_sequence_number = 0;
653 nbr->recv_sequence_number =
654 ntohl(eigrph->sequence);
655 eigrp_update_send_EOT(nbr);
656 } else
657 eigrp_send_packet_reliably(nbr);
658 }
659 ep = eigrp_fifo_next(nbr->multicast_queue);
660 if (ep) {
661 if (ntohl(eigrph->ack) == ep->sequence_number) {
662 ep = eigrp_fifo_pop(nbr->multicast_queue);
663 eigrp_packet_free(ep);
664 if (nbr->multicast_queue->count > 0) {
665 eigrp_send_packet_reliably(nbr);
666 }
667 }
668 }
669 }
670
671
672 switch (opcode) {
673 case EIGRP_OPC_HELLO:
674 eigrp_hello_receive(eigrp, iph, eigrph, ibuf, ei, length);
675 break;
676 case EIGRP_OPC_PROBE:
677 // eigrp_probe_receive(eigrp, iph, eigrph, ibuf, ei,
678 // length);
679 break;
680 case EIGRP_OPC_QUERY:
681 eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length);
682 break;
683 case EIGRP_OPC_REPLY:
684 eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length);
685 break;
686 case EIGRP_OPC_REQUEST:
687 // eigrp_request_receive(eigrp, iph, eigrph, ibuf, ei,
688 // length);
689 break;
690 case EIGRP_OPC_SIAQUERY:
691 eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length);
692 break;
693 case EIGRP_OPC_SIAREPLY:
694 eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length);
695 break;
696 case EIGRP_OPC_UPDATE:
697 eigrp_update_receive(eigrp, iph, eigrph, ibuf, ei, length);
698 break;
699 default:
700 zlog_warn(
701 "interface %s: EIGRP packet header type %d unsupported",
702 IF_NAME(ei), opcode);
703 break;
704 }
705
706 return 0;
707 }
708
709 static struct stream *eigrp_recv_packet(int fd, struct interface **ifp,
710 struct stream *ibuf)
711 {
712 int ret;
713 struct ip *iph;
714 uint16_t ip_len;
715 unsigned int ifindex = 0;
716 struct iovec iov;
717 /* Header and data both require alignment. */
718 char buff[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
719 struct msghdr msgh;
720
721 memset(&msgh, 0, sizeof(struct msghdr));
722 msgh.msg_iov = &iov;
723 msgh.msg_iovlen = 1;
724 msgh.msg_control = (caddr_t)buff;
725 msgh.msg_controllen = sizeof(buff);
726
727 ret = stream_recvmsg(ibuf, fd, &msgh, 0, (EIGRP_PACKET_MAX_LEN + 1));
728 if (ret < 0) {
729 zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno));
730 return NULL;
731 }
732 if ((unsigned int)ret < sizeof(*iph)) /* ret must be > 0 now */
733 {
734 zlog_warn(
735 "eigrp_recv_packet: discarding runt packet of length %d "
736 "(ip header size is %u)",
737 ret, (unsigned int)sizeof(*iph));
738 return NULL;
739 }
740
741 /* Note that there should not be alignment problems with this assignment
742 because this is at the beginning of the stream data buffer. */
743 iph = (struct ip *)STREAM_DATA(ibuf);
744 sockopt_iphdrincl_swab_systoh(iph);
745
746 ip_len = iph->ip_len;
747
748 #if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000)
749 /*
750 * Kernel network code touches incoming IP header parameters,
751 * before protocol specific processing.
752 *
753 * 1) Convert byteorder to host representation.
754 * --> ip_len, ip_id, ip_off
755 *
756 * 2) Adjust ip_len to strip IP header size!
757 * --> If user process receives entire IP packet via RAW
758 * socket, it must consider adding IP header size to
759 * the "ip_len" field of "ip" structure.
760 *
761 * For more details, see <netinet/ip_input.c>.
762 */
763 ip_len = ip_len + (iph->ip_hl << 2);
764 #endif
765
766 #if defined(__DragonFly__)
767 /*
768 * in DragonFly's raw socket, ip_len/ip_off are read
769 * in network byte order.
770 * As OpenBSD < 200311 adjust ip_len to strip IP header size!
771 */
772 ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2);
773 #endif
774
775 ifindex = getsockopt_ifindex(AF_INET, &msgh);
776
777 *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
778
779 if (ret != ip_len) {
780 zlog_warn(
781 "eigrp_recv_packet read length mismatch: ip_len is %d, "
782 "but recvmsg returned %d",
783 ip_len, ret);
784 return NULL;
785 }
786
787 return ibuf;
788 }
789
790 struct eigrp_fifo *eigrp_fifo_new(void)
791 {
792 struct eigrp_fifo *new;
793
794 new = XCALLOC(MTYPE_EIGRP_FIFO, sizeof(struct eigrp_fifo));
795 return new;
796 }
797
798 /* Free eigrp packet fifo. */
799 void eigrp_fifo_free(struct eigrp_fifo *fifo)
800 {
801 struct eigrp_packet *ep;
802 struct eigrp_packet *next;
803
804 for (ep = fifo->head; ep; ep = next) {
805 next = ep->next;
806 eigrp_packet_free(ep);
807 }
808 fifo->head = fifo->tail = NULL;
809 fifo->count = 0;
810
811 XFREE(MTYPE_EIGRP_FIFO, fifo);
812 }
813
814 /* Free eigrp fifo entries without destroying fifo itself*/
815 void eigrp_fifo_reset(struct eigrp_fifo *fifo)
816 {
817 struct eigrp_packet *ep;
818 struct eigrp_packet *next;
819
820 for (ep = fifo->head; ep; ep = next) {
821 next = ep->next;
822 eigrp_packet_free(ep);
823 }
824 fifo->head = fifo->tail = NULL;
825 fifo->count = 0;
826 }
827
828 struct eigrp_packet *eigrp_packet_new(size_t size, struct eigrp_neighbor *nbr)
829 {
830 struct eigrp_packet *new;
831
832 new = XCALLOC(MTYPE_EIGRP_PACKET, sizeof(struct eigrp_packet));
833 new->s = stream_new(size);
834 new->retrans_counter = 0;
835 new->nbr = nbr;
836
837 return new;
838 }
839
840 void eigrp_send_packet_reliably(struct eigrp_neighbor *nbr)
841 {
842 struct eigrp_packet *ep;
843
844 ep = eigrp_fifo_next(nbr->retrans_queue);
845
846 if (ep) {
847 struct eigrp_packet *duplicate;
848 duplicate = eigrp_packet_duplicate(ep, nbr);
849 /* Add packet to the top of the interface output queue*/
850 eigrp_fifo_push(nbr->ei->obuf, duplicate);
851
852 /*Start retransmission timer*/
853 thread_add_timer(master, eigrp_unack_packet_retrans, nbr,
854 EIGRP_PACKET_RETRANS_TIME,
855 &ep->t_retrans_timer);
856
857 /*Increment sequence number counter*/
858 nbr->ei->eigrp->sequence_number++;
859
860 /* Hook thread to write packet. */
861 if (nbr->ei->on_write_q == 0) {
862 listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei);
863 nbr->ei->on_write_q = 1;
864 }
865 thread_add_write(master, eigrp_write, nbr->ei->eigrp,
866 nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write);
867 }
868 }
869
870 /* Calculate EIGRP checksum */
871 void eigrp_packet_checksum(struct eigrp_interface *ei, struct stream *s,
872 uint16_t length)
873 {
874 struct eigrp_header *eigrph;
875
876 eigrph = (struct eigrp_header *)STREAM_DATA(s);
877
878 /* Calculate checksum. */
879 eigrph->checksum = in_cksum(eigrph, length);
880 }
881
882 /* Make EIGRP header. */
883 void eigrp_packet_header_init(int type, struct eigrp *eigrp, struct stream *s,
884 uint32_t flags, uint32_t sequence, uint32_t ack)
885 {
886 struct eigrp_header *eigrph;
887
888 stream_reset(s);
889 eigrph = (struct eigrp_header *)STREAM_DATA(s);
890
891 eigrph->version = (uint8_t)EIGRP_HEADER_VERSION;
892 eigrph->opcode = (uint8_t)type;
893 eigrph->checksum = 0;
894
895 eigrph->vrid = htons(eigrp->vrid);
896 eigrph->ASNumber = htons(eigrp->AS);
897 eigrph->ack = htonl(ack);
898 eigrph->sequence = htonl(sequence);
899 // if(flags == EIGRP_INIT_FLAG)
900 // eigrph->sequence = htonl(3);
901 eigrph->flags = htonl(flags);
902
903 if (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))
904 zlog_debug("Packet Header Init Seq [%u] Ack [%u]",
905 htonl(eigrph->sequence), htonl(eigrph->ack));
906
907 stream_forward_endp(s, EIGRP_HEADER_LEN);
908 }
909
910 /* Add new packet to head of fifo. */
911 void eigrp_fifo_push(struct eigrp_fifo *fifo, struct eigrp_packet *ep)
912 {
913 ep->next = fifo->head;
914 ep->previous = NULL;
915
916 if (fifo->tail == NULL)
917 fifo->tail = ep;
918
919 if (fifo->count != 0)
920 fifo->head->previous = ep;
921
922 fifo->head = ep;
923
924 fifo->count++;
925 }
926
927 /* Return last fifo entry. */
928 struct eigrp_packet *eigrp_fifo_next(struct eigrp_fifo *fifo)
929 {
930 return fifo->tail;
931 }
932
933 void eigrp_packet_delete(struct eigrp_interface *ei)
934 {
935 struct eigrp_packet *ep;
936
937 ep = eigrp_fifo_pop(ei->obuf);
938
939 if (ep)
940 eigrp_packet_free(ep);
941 }
942
943 void eigrp_packet_free(struct eigrp_packet *ep)
944 {
945 if (ep->s)
946 stream_free(ep->s);
947
948 THREAD_OFF(ep->t_retrans_timer);
949
950 XFREE(MTYPE_EIGRP_PACKET, ep);
951 }
952
953 /* EIGRP Header verification. */
954 static int eigrp_verify_header(struct stream *ibuf, struct eigrp_interface *ei,
955 struct ip *iph, struct eigrp_header *eigrph)
956 {
957 /* Check network mask, Silently discarded. */
958 if (!eigrp_check_network_mask(ei, iph->ip_src)) {
959 zlog_warn(
960 "interface %s: eigrp_read network address is not same [%s]",
961 IF_NAME(ei), inet_ntoa(iph->ip_src));
962 return -1;
963 }
964 //
965 // /* Check authentication. The function handles logging actions, where
966 // required. */
967 // if (! eigrp_check_auth(ei, eigrph))
968 // return -1;
969
970 return 0;
971 }
972
973 /* Unbound socket will accept any Raw IP packets if proto is matched.
974 To prevent it, compare src IP address and i/f address with masking
975 i/f network mask. */
976 static int eigrp_check_network_mask(struct eigrp_interface *ei,
977 struct in_addr ip_src)
978 {
979 struct in_addr mask, me, him;
980
981 if (ei->type == EIGRP_IFTYPE_POINTOPOINT)
982 return 1;
983
984 masklen2ip(ei->address->prefixlen, &mask);
985
986 me.s_addr = ei->address->u.prefix4.s_addr & mask.s_addr;
987 him.s_addr = ip_src.s_addr & mask.s_addr;
988
989 if (IPV4_ADDR_SAME(&me, &him))
990 return 1;
991
992 return 0;
993 }
994
995 int eigrp_unack_packet_retrans(struct thread *thread)
996 {
997 struct eigrp_neighbor *nbr;
998 nbr = (struct eigrp_neighbor *)THREAD_ARG(thread);
999
1000 struct eigrp_packet *ep;
1001 ep = eigrp_fifo_next(nbr->retrans_queue);
1002
1003 if (ep) {
1004 struct eigrp_packet *duplicate;
1005 duplicate = eigrp_packet_duplicate(ep, nbr);
1006
1007 /* Add packet to the top of the interface output queue*/
1008 eigrp_fifo_push(nbr->ei->obuf, duplicate);
1009
1010 ep->retrans_counter++;
1011 if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX)
1012 return eigrp_retrans_count_exceeded(ep, nbr);
1013
1014 /*Start retransmission timer*/
1015 ep->t_retrans_timer = NULL;
1016 thread_add_timer(master, eigrp_unack_packet_retrans, nbr,
1017 EIGRP_PACKET_RETRANS_TIME,
1018 &ep->t_retrans_timer);
1019
1020 /* Hook thread to write packet. */
1021 if (nbr->ei->on_write_q == 0) {
1022 listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei);
1023 nbr->ei->on_write_q = 1;
1024 }
1025 thread_add_write(master, eigrp_write, nbr->ei->eigrp,
1026 nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write);
1027 }
1028
1029 return 0;
1030 }
1031
1032 int eigrp_unack_multicast_packet_retrans(struct thread *thread)
1033 {
1034 struct eigrp_neighbor *nbr;
1035 nbr = (struct eigrp_neighbor *)THREAD_ARG(thread);
1036
1037 struct eigrp_packet *ep;
1038 ep = eigrp_fifo_next(nbr->multicast_queue);
1039
1040 if (ep) {
1041 struct eigrp_packet *duplicate;
1042 duplicate = eigrp_packet_duplicate(ep, nbr);
1043 /* Add packet to the top of the interface output queue*/
1044 eigrp_fifo_push(nbr->ei->obuf, duplicate);
1045
1046 ep->retrans_counter++;
1047 if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX)
1048 return eigrp_retrans_count_exceeded(ep, nbr);
1049
1050 /*Start retransmission timer*/
1051 ep->t_retrans_timer = NULL;
1052 thread_add_timer(master, eigrp_unack_multicast_packet_retrans,
1053 nbr, EIGRP_PACKET_RETRANS_TIME,
1054 &ep->t_retrans_timer);
1055
1056 /* Hook thread to write packet. */
1057 if (nbr->ei->on_write_q == 0) {
1058 listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei);
1059 nbr->ei->on_write_q = 1;
1060 }
1061 thread_add_write(master, eigrp_write, nbr->ei->eigrp,
1062 nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write);
1063 }
1064
1065 return 0;
1066 }
1067
1068 /* Get packet from tail of fifo. */
1069 struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *fifo)
1070 {
1071 struct eigrp_packet *ep = NULL;
1072
1073 ep = fifo->tail;
1074
1075 if (ep) {
1076 fifo->tail = ep->previous;
1077
1078 if (fifo->tail == NULL)
1079 fifo->head = NULL;
1080 else
1081 fifo->tail->next = NULL;
1082
1083 fifo->count--;
1084 }
1085
1086 return ep;
1087 }
1088
1089 struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old,
1090 struct eigrp_neighbor *nbr)
1091 {
1092 struct eigrp_packet *new;
1093
1094 new = eigrp_packet_new(EIGRP_PACKET_MTU(nbr->ei->ifp->mtu), nbr);
1095 new->length = old->length;
1096 new->retrans_counter = old->retrans_counter;
1097 new->dst = old->dst;
1098 new->sequence_number = old->sequence_number;
1099 stream_copy(new->s, old->s);
1100
1101 return new;
1102 }
1103
1104 static struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new()
1105 {
1106 struct TLV_IPv4_Internal_type *new;
1107
1108 new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV,
1109 sizeof(struct TLV_IPv4_Internal_type));
1110
1111 return new;
1112 }
1113
1114 struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv(struct stream *s)
1115 {
1116 struct TLV_IPv4_Internal_type *tlv;
1117
1118 tlv = eigrp_IPv4_InternalTLV_new();
1119
1120 tlv->type = stream_getw(s);
1121 tlv->length = stream_getw(s);
1122 tlv->forward.s_addr = stream_getl(s);
1123 tlv->metric.delay = stream_getl(s);
1124 tlv->metric.bandwidth = stream_getl(s);
1125 tlv->metric.mtu[0] = stream_getc(s);
1126 tlv->metric.mtu[1] = stream_getc(s);
1127 tlv->metric.mtu[2] = stream_getc(s);
1128 tlv->metric.hop_count = stream_getc(s);
1129 tlv->metric.reliability = stream_getc(s);
1130 tlv->metric.load = stream_getc(s);
1131 tlv->metric.tag = stream_getc(s);
1132 tlv->metric.flags = stream_getc(s);
1133
1134 tlv->prefix_length = stream_getc(s);
1135
1136 if (tlv->prefix_length <= 8) {
1137 tlv->destination_part[0] = stream_getc(s);
1138 tlv->destination.s_addr = (tlv->destination_part[0]);
1139 } else if (tlv->prefix_length > 8 && tlv->prefix_length <= 16) {
1140 tlv->destination_part[0] = stream_getc(s);
1141 tlv->destination_part[1] = stream_getc(s);
1142 tlv->destination.s_addr = ((tlv->destination_part[1] << 8)
1143 + tlv->destination_part[0]);
1144 } else if (tlv->prefix_length > 16 && tlv->prefix_length <= 24) {
1145 tlv->destination_part[0] = stream_getc(s);
1146 tlv->destination_part[1] = stream_getc(s);
1147 tlv->destination_part[2] = stream_getc(s);
1148 tlv->destination.s_addr = ((tlv->destination_part[2] << 16)
1149 + (tlv->destination_part[1] << 8)
1150 + tlv->destination_part[0]);
1151 } else if (tlv->prefix_length > 24 && tlv->prefix_length <= 32) {
1152 tlv->destination_part[0] = stream_getc(s);
1153 tlv->destination_part[1] = stream_getc(s);
1154 tlv->destination_part[2] = stream_getc(s);
1155 tlv->destination_part[3] = stream_getc(s);
1156 tlv->destination.s_addr = ((tlv->destination_part[3] << 24)
1157 + (tlv->destination_part[2] << 16)
1158 + (tlv->destination_part[1] << 8)
1159 + tlv->destination_part[0]);
1160 }
1161 return tlv;
1162 }
1163
1164 uint16_t eigrp_add_internalTLV_to_stream(struct stream *s,
1165 struct eigrp_prefix_entry *pe)
1166 {
1167 uint16_t length;
1168
1169 stream_putw(s, EIGRP_TLV_IPv4_INT);
1170 switch (pe->destination->prefixlen) {
1171 case 0:
1172 case 1:
1173 case 2:
1174 case 3:
1175 case 4:
1176 case 5:
1177 case 6:
1178 case 7:
1179 case 8:
1180 length = EIGRP_TLV_IPV4_SIZE_GRT_0_BIT;
1181 stream_putw(s, length);
1182 break;
1183 case 9:
1184 case 10:
1185 case 11:
1186 case 12:
1187 case 13:
1188 case 14:
1189 case 15:
1190 case 16:
1191 length = EIGRP_TLV_IPV4_SIZE_GRT_8_BIT;
1192 stream_putw(s, length);
1193 break;
1194 case 17:
1195 case 18:
1196 case 19:
1197 case 20:
1198 case 21:
1199 case 22:
1200 case 23:
1201 case 24:
1202 length = EIGRP_TLV_IPV4_SIZE_GRT_16_BIT;
1203 stream_putw(s, length);
1204 break;
1205 case 25:
1206 case 26:
1207 case 27:
1208 case 28:
1209 case 29:
1210 case 30:
1211 case 31:
1212 case 32:
1213 length = EIGRP_TLV_IPV4_SIZE_GRT_24_BIT;
1214 stream_putw(s, length);
1215 break;
1216 default:
1217 flog_err(EC_LIB_DEVELOPMENT, "%s: Unexpected prefix length: %d",
1218 __PRETTY_FUNCTION__, pe->destination->prefixlen);
1219 return 0;
1220 }
1221 stream_putl(s, 0x00000000);
1222
1223 /*Metric*/
1224 stream_putl(s, pe->reported_metric.delay);
1225 stream_putl(s, pe->reported_metric.bandwidth);
1226 stream_putc(s, pe->reported_metric.mtu[2]);
1227 stream_putc(s, pe->reported_metric.mtu[1]);
1228 stream_putc(s, pe->reported_metric.mtu[0]);
1229 stream_putc(s, pe->reported_metric.hop_count);
1230 stream_putc(s, pe->reported_metric.reliability);
1231 stream_putc(s, pe->reported_metric.load);
1232 stream_putc(s, pe->reported_metric.tag);
1233 stream_putc(s, pe->reported_metric.flags);
1234
1235 stream_putc(s, pe->destination->prefixlen);
1236
1237 stream_putc(s, pe->destination->u.prefix4.s_addr & 0xFF);
1238 if (pe->destination->prefixlen > 8)
1239 stream_putc(s, (pe->destination->u.prefix4.s_addr >> 8) & 0xFF);
1240 if (pe->destination->prefixlen > 16)
1241 stream_putc(s,
1242 (pe->destination->u.prefix4.s_addr >> 16) & 0xFF);
1243 if (pe->destination->prefixlen > 24)
1244 stream_putc(s,
1245 (pe->destination->u.prefix4.s_addr >> 24) & 0xFF);
1246
1247 return length;
1248 }
1249
1250 uint16_t eigrp_add_authTLV_MD5_to_stream(struct stream *s,
1251 struct eigrp_interface *ei)
1252 {
1253 struct key *key;
1254 struct keychain *keychain;
1255 struct TLV_MD5_Authentication_Type *authTLV;
1256
1257 authTLV = eigrp_authTLV_MD5_new();
1258
1259 authTLV->type = htons(EIGRP_TLV_AUTH);
1260 authTLV->length = htons(EIGRP_AUTH_MD5_TLV_SIZE);
1261 authTLV->auth_type = htons(EIGRP_AUTH_TYPE_MD5);
1262 authTLV->auth_length = htons(EIGRP_AUTH_TYPE_MD5_LEN);
1263 authTLV->key_sequence = 0;
1264 memset(authTLV->Nullpad, 0, sizeof(authTLV->Nullpad));
1265
1266 keychain = keychain_lookup(ei->params.auth_keychain);
1267 if (keychain)
1268 key = key_lookup_for_send(keychain);
1269 else {
1270 free(ei->params.auth_keychain);
1271 ei->params.auth_keychain = NULL;
1272 eigrp_authTLV_MD5_free(authTLV);
1273 return 0;
1274 }
1275
1276 if (key) {
1277 authTLV->key_id = htonl(key->index);
1278 memset(authTLV->digest, 0, EIGRP_AUTH_TYPE_MD5_LEN);
1279 stream_put(s, authTLV,
1280 sizeof(struct TLV_MD5_Authentication_Type));
1281 eigrp_authTLV_MD5_free(authTLV);
1282 return EIGRP_AUTH_MD5_TLV_SIZE;
1283 }
1284
1285 eigrp_authTLV_MD5_free(authTLV);
1286
1287 return 0;
1288 }
1289
1290 uint16_t eigrp_add_authTLV_SHA256_to_stream(struct stream *s,
1291 struct eigrp_interface *ei)
1292 {
1293 struct key *key;
1294 struct keychain *keychain;
1295 struct TLV_SHA256_Authentication_Type *authTLV;
1296
1297 authTLV = eigrp_authTLV_SHA256_new();
1298
1299 authTLV->type = htons(EIGRP_TLV_AUTH);
1300 authTLV->length = htons(EIGRP_AUTH_SHA256_TLV_SIZE);
1301 authTLV->auth_type = htons(EIGRP_AUTH_TYPE_SHA256);
1302 authTLV->auth_length = htons(EIGRP_AUTH_TYPE_SHA256_LEN);
1303 authTLV->key_sequence = 0;
1304 memset(authTLV->Nullpad, 0, sizeof(authTLV->Nullpad));
1305
1306 keychain = keychain_lookup(ei->params.auth_keychain);
1307 if (keychain)
1308 key = key_lookup_for_send(keychain);
1309 else {
1310 free(ei->params.auth_keychain);
1311 ei->params.auth_keychain = NULL;
1312 eigrp_authTLV_SHA256_free(authTLV);
1313 return 0;
1314 }
1315
1316 if (key) {
1317 authTLV->key_id = 0;
1318 memset(authTLV->digest, 0, EIGRP_AUTH_TYPE_SHA256_LEN);
1319 stream_put(s, authTLV,
1320 sizeof(struct TLV_SHA256_Authentication_Type));
1321 eigrp_authTLV_SHA256_free(authTLV);
1322 return EIGRP_AUTH_SHA256_TLV_SIZE;
1323 }
1324
1325 eigrp_authTLV_SHA256_free(authTLV);
1326
1327 return 0;
1328 }
1329
1330 struct TLV_MD5_Authentication_Type *eigrp_authTLV_MD5_new()
1331 {
1332 struct TLV_MD5_Authentication_Type *new;
1333
1334 new = XCALLOC(MTYPE_EIGRP_AUTH_TLV,
1335 sizeof(struct TLV_MD5_Authentication_Type));
1336
1337 return new;
1338 }
1339
1340 void eigrp_authTLV_MD5_free(struct TLV_MD5_Authentication_Type *authTLV)
1341 {
1342 XFREE(MTYPE_EIGRP_AUTH_TLV, authTLV);
1343 }
1344
1345 struct TLV_SHA256_Authentication_Type *eigrp_authTLV_SHA256_new()
1346 {
1347 struct TLV_SHA256_Authentication_Type *new;
1348
1349 new = XCALLOC(MTYPE_EIGRP_AUTH_SHA256_TLV,
1350 sizeof(struct TLV_SHA256_Authentication_Type));
1351
1352 return new;
1353 }
1354
1355 void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type *authTLV)
1356 {
1357 XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV);
1358 }
1359
1360 void eigrp_IPv4_InternalTLV_free(
1361 struct TLV_IPv4_Internal_type *IPv4_InternalTLV)
1362 {
1363 XFREE(MTYPE_EIGRP_IPV4_INT_TLV, IPv4_InternalTLV);
1364 }
1365
1366 struct TLV_Sequence_Type *eigrp_SequenceTLV_new()
1367 {
1368 struct TLV_Sequence_Type *new;
1369
1370 new = XCALLOC(MTYPE_EIGRP_SEQ_TLV, sizeof(struct TLV_Sequence_Type));
1371
1372 return new;
1373 }