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