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