]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_packet.c
Merge pull request #9472 from rampxxxx/pathd_doc_augmented
[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 int 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(struct ip));
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 return 0;
476 }
477
478 /* Starting point of packet process function. */
479 int eigrp_read(struct thread *thread)
480 {
481 int ret;
482 struct stream *ibuf;
483 struct eigrp *eigrp;
484 struct eigrp_interface *ei;
485 struct ip *iph;
486 struct eigrp_header *eigrph;
487 struct interface *ifp;
488 struct eigrp_neighbor *nbr;
489 struct in_addr srcaddr;
490 uint16_t opcode = 0;
491 uint16_t length = 0;
492
493 /* first of all get interface pointer. */
494 eigrp = THREAD_ARG(thread);
495
496 /* prepare for next packet. */
497 thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read);
498
499 stream_reset(eigrp->ibuf);
500 if (!(ibuf = eigrp_recv_packet(eigrp, eigrp->fd, &ifp, eigrp->ibuf))) {
501 /* This raw packet is known to be at least as big as its IP
502 * header. */
503 return -1;
504 }
505
506 /* Note that there should not be alignment problems with this assignment
507 because this is at the beginning of the stream data buffer. */
508 iph = (struct ip *)STREAM_DATA(ibuf);
509
510 // Substract IPv4 header size from EIGRP Packet itself
511 if (iph->ip_v == 4)
512 length = (iph->ip_len) - 20U;
513
514 srcaddr = iph->ip_src;
515
516 /* IP Header dump. */
517 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)
518 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))
519 eigrp_ip_header_dump(iph);
520
521 /* Note that sockopt_iphdrincl_swab_systoh was called in
522 * eigrp_recv_packet. */
523 if (ifp == NULL) {
524 struct connected *c;
525 /* Handle cases where the platform does not support retrieving
526 the ifindex,
527 and also platforms (such as Solaris 8) that claim to support
528 ifindex
529 retrieval but do not. */
530 c = if_lookup_address((void *)&srcaddr, AF_INET,
531 eigrp->vrf_id);
532
533 if (c == NULL)
534 return 0;
535
536 ifp = c->ifp;
537 }
538
539 /* associate packet with eigrp interface */
540 ei = ifp->info;
541
542 /* eigrp_verify_header() relies on a valid "ei" and thus can be called
543 only
544 after the checks below are passed. These checks in turn access the
545 fields of unverified "eigrph" structure for their own purposes and
546 must remain very accurate in doing this.
547 */
548 if (!ei)
549 return 0;
550
551 /* Self-originated packet should be discarded silently. */
552 if (eigrp_if_lookup_by_local_addr(eigrp, NULL, iph->ip_src)
553 || (IPV4_ADDR_SAME(&srcaddr, &ei->address.u.prefix4))) {
554 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
555 zlog_debug(
556 "eigrp_read[%pI4]: Dropping self-originated packet",
557 &srcaddr);
558 return 0;
559 }
560
561 /* Advance from IP header to EIGRP header (iph->ip_hl has been verified
562 by eigrp_recv_packet() to be correct). */
563
564 stream_forward_getp(ibuf, (iph->ip_hl * 4));
565 eigrph = (struct eigrp_header *)stream_pnt(ibuf);
566
567 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)
568 && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))
569 eigrp_header_dump(eigrph);
570
571 if (ntohs(eigrph->ASNumber) != eigrp->AS) {
572 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
573 zlog_debug(
574 "ignoring packet from router %u sent to %pI4, wrong AS Number received: %u",
575 ntohs(eigrph->vrid), &iph->ip_dst,
576 ntohs(eigrph->ASNumber));
577 return 0;
578 }
579
580 /* If incoming interface is passive one, ignore it. */
581 if (eigrp_if_is_passive(ei)) {
582 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
583 zlog_debug(
584 "ignoring packet from router %u sent to %pI4, received on a passive interface, %pI4",
585 ntohs(eigrph->vrid), &iph->ip_dst,
586 &ei->address.u.prefix4);
587
588 if (iph->ip_dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS)) {
589 eigrp_if_set_multicast(ei);
590 }
591 return 0;
592 }
593
594 /* else it must be a local eigrp interface, check it was received on
595 * correct link
596 */
597 else if (ei->ifp != ifp) {
598 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
599 zlog_warn(
600 "Packet from [%pI4] received on wrong link %s",
601 &iph->ip_src, ifp->name);
602 return 0;
603 }
604
605 /* Verify more EIGRP header fields. */
606 ret = eigrp_verify_header(ibuf, ei, iph, eigrph);
607 if (ret < 0) {
608 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
609 zlog_debug(
610 "eigrp_read[%pI4]: Header check failed, dropping.",
611 &iph->ip_src);
612 return ret;
613 }
614
615 /* calcualte the eigrp packet length, and move the pounter to the
616 start of the eigrp TLVs */
617 opcode = eigrph->opcode;
618
619 if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
620 zlog_debug(
621 "Received [%s][%d/%d] length [%u] via [%s] src [%pI4] dst [%pI4]",
622 lookup_msg(eigrp_packet_type_str, opcode, NULL),
623 ntohl(eigrph->sequence), ntohl(eigrph->ack), length,
624 IF_NAME(ei), &iph->ip_src, &iph->ip_dst);
625
626 /* Read rest of the packet and call each sort of packet routine. */
627 stream_forward_getp(ibuf, EIGRP_HEADER_LEN);
628
629 /* New testing block of code for handling Acks */
630 if (ntohl(eigrph->ack) != 0) {
631 struct eigrp_packet *ep = NULL;
632
633 nbr = eigrp_nbr_get(ei, eigrph, iph);
634
635 // neighbor must be valid, eigrp_nbr_get creates if none existed
636 assert(nbr);
637
638 ep = eigrp_fifo_next(nbr->retrans_queue);
639 if ((ep) && (ntohl(eigrph->ack) == ep->sequence_number)) {
640 ep = eigrp_fifo_pop(nbr->retrans_queue);
641 eigrp_packet_free(ep);
642
643 if ((nbr->state == EIGRP_NEIGHBOR_PENDING)
644 && (ntohl(eigrph->ack)
645 == nbr->init_sequence_number)) {
646 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_UP);
647 zlog_info(
648 "Neighbor(%pI4) adjacency became full",
649 &nbr->src);
650 nbr->init_sequence_number = 0;
651 nbr->recv_sequence_number =
652 ntohl(eigrph->sequence);
653 eigrp_update_send_EOT(nbr);
654 } else
655 eigrp_send_packet_reliably(nbr);
656 }
657 ep = eigrp_fifo_next(nbr->multicast_queue);
658 if (ep) {
659 if (ntohl(eigrph->ack) == ep->sequence_number) {
660 ep = eigrp_fifo_pop(nbr->multicast_queue);
661 eigrp_packet_free(ep);
662 if (nbr->multicast_queue->count > 0) {
663 eigrp_send_packet_reliably(nbr);
664 }
665 }
666 }
667 }
668
669
670 switch (opcode) {
671 case EIGRP_OPC_HELLO:
672 eigrp_hello_receive(eigrp, iph, eigrph, ibuf, ei, length);
673 break;
674 case EIGRP_OPC_PROBE:
675 // eigrp_probe_receive(eigrp, iph, eigrph, ibuf, ei,
676 // length);
677 break;
678 case EIGRP_OPC_QUERY:
679 eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length);
680 break;
681 case EIGRP_OPC_REPLY:
682 eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length);
683 break;
684 case EIGRP_OPC_REQUEST:
685 // eigrp_request_receive(eigrp, iph, eigrph, ibuf, ei,
686 // length);
687 break;
688 case EIGRP_OPC_SIAQUERY:
689 eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length);
690 break;
691 case EIGRP_OPC_SIAREPLY:
692 eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length);
693 break;
694 case EIGRP_OPC_UPDATE:
695 eigrp_update_receive(eigrp, iph, eigrph, ibuf, ei, length);
696 break;
697 default:
698 zlog_warn(
699 "interface %s: EIGRP packet header type %d unsupported",
700 IF_NAME(ei), opcode);
701 break;
702 }
703
704 return 0;
705 }
706
707 static struct stream *eigrp_recv_packet(struct eigrp *eigrp,
708 int fd, struct interface **ifp,
709 struct stream *ibuf)
710 {
711 int ret;
712 struct ip *iph;
713 uint16_t ip_len;
714 unsigned int ifindex = 0;
715 struct iovec iov;
716 /* Header and data both require alignment. */
717 char buff[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())];
718 struct msghdr msgh;
719
720 memset(&msgh, 0, sizeof(struct msghdr));
721 msgh.msg_iov = &iov;
722 msgh.msg_iovlen = 1;
723 msgh.msg_control = (caddr_t)buff;
724 msgh.msg_controllen = sizeof(buff);
725
726 ret = stream_recvmsg(ibuf, fd, &msgh, 0, (EIGRP_PACKET_MAX_LEN + 1));
727 if (ret < 0) {
728 zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno));
729 return NULL;
730 }
731 if ((unsigned int)ret < sizeof(*iph)) /* ret must be > 0 now */
732 {
733 zlog_warn(
734 "eigrp_recv_packet: discarding runt packet of length %d (ip header size is %u)",
735 ret, (unsigned int)sizeof(*iph));
736 return NULL;
737 }
738
739 /* Note that there should not be alignment problems with this assignment
740 because this is at the beginning of the stream data buffer. */
741 iph = (struct ip *)STREAM_DATA(ibuf);
742 sockopt_iphdrincl_swab_systoh(iph);
743
744 ip_len = iph->ip_len;
745
746 #if defined(__FreeBSD__) && (__FreeBSD_version < 1000000)
747 /*
748 * Kernel network code touches incoming IP header parameters,
749 * before protocol specific processing.
750 *
751 * 1) Convert byteorder to host representation.
752 * --> ip_len, ip_id, ip_off
753 *
754 * 2) Adjust ip_len to strip IP header size!
755 * --> If user process receives entire IP packet via RAW
756 * socket, it must consider adding IP header size to
757 * the "ip_len" field of "ip" structure.
758 *
759 * For more details, see <netinet/ip_input.c>.
760 */
761 ip_len = ip_len + (iph->ip_hl << 2);
762 #endif
763
764 #if defined(__DragonFly__)
765 /*
766 * in DragonFly's raw socket, ip_len/ip_off are read
767 * in network byte order.
768 * As OpenBSD < 200311 adjust ip_len to strip IP header size!
769 */
770 ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2);
771 #endif
772
773 ifindex = getsockopt_ifindex(AF_INET, &msgh);
774
775 *ifp = if_lookup_by_index(ifindex, eigrp->vrf_id);
776
777 if (ret != ip_len) {
778 zlog_warn(
779 "eigrp_recv_packet read length mismatch: ip_len is %d, but recvmsg returned %d",
780 ip_len, ret);
781 return NULL;
782 }
783
784 return ibuf;
785 }
786
787 struct eigrp_fifo *eigrp_fifo_new(void)
788 {
789 struct eigrp_fifo *new;
790
791 new = XCALLOC(MTYPE_EIGRP_FIFO, sizeof(struct eigrp_fifo));
792 return new;
793 }
794
795 /* Free eigrp packet fifo. */
796 void eigrp_fifo_free(struct eigrp_fifo *fifo)
797 {
798 struct eigrp_packet *ep;
799 struct eigrp_packet *next;
800
801 for (ep = fifo->head; ep; ep = next) {
802 next = ep->next;
803 eigrp_packet_free(ep);
804 }
805 fifo->head = fifo->tail = NULL;
806 fifo->count = 0;
807
808 XFREE(MTYPE_EIGRP_FIFO, fifo);
809 }
810
811 /* Free eigrp fifo entries without destroying fifo itself*/
812 void eigrp_fifo_reset(struct eigrp_fifo *fifo)
813 {
814 struct eigrp_packet *ep;
815 struct eigrp_packet *next;
816
817 for (ep = fifo->head; ep; ep = next) {
818 next = ep->next;
819 eigrp_packet_free(ep);
820 }
821 fifo->head = fifo->tail = NULL;
822 fifo->count = 0;
823 }
824
825 struct eigrp_packet *eigrp_packet_new(size_t size, struct eigrp_neighbor *nbr)
826 {
827 struct eigrp_packet *new;
828
829 new = XCALLOC(MTYPE_EIGRP_PACKET, sizeof(struct eigrp_packet));
830 new->s = stream_new(size);
831 new->retrans_counter = 0;
832 new->nbr = nbr;
833
834 return new;
835 }
836
837 void eigrp_send_packet_reliably(struct eigrp_neighbor *nbr)
838 {
839 struct eigrp_packet *ep;
840
841 ep = eigrp_fifo_next(nbr->retrans_queue);
842
843 if (ep) {
844 struct eigrp_packet *duplicate;
845 duplicate = eigrp_packet_duplicate(ep, nbr);
846 /* Add packet to the top of the interface output queue*/
847 eigrp_fifo_push(nbr->ei->obuf, duplicate);
848
849 /*Start retransmission timer*/
850 thread_add_timer(master, eigrp_unack_packet_retrans, nbr,
851 EIGRP_PACKET_RETRANS_TIME,
852 &ep->t_retrans_timer);
853
854 /*Increment sequence number counter*/
855 nbr->ei->eigrp->sequence_number++;
856
857 /* Hook thread to write packet. */
858 if (nbr->ei->on_write_q == 0) {
859 listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei);
860 nbr->ei->on_write_q = 1;
861 }
862 thread_add_write(master, eigrp_write, nbr->ei->eigrp,
863 nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write);
864 }
865 }
866
867 /* Calculate EIGRP checksum */
868 void eigrp_packet_checksum(struct eigrp_interface *ei, struct stream *s,
869 uint16_t length)
870 {
871 struct eigrp_header *eigrph;
872
873 eigrph = (struct eigrp_header *)STREAM_DATA(s);
874
875 /* Calculate checksum. */
876 eigrph->checksum = in_cksum(eigrph, length);
877 }
878
879 /* Make EIGRP header. */
880 void eigrp_packet_header_init(int type, struct eigrp *eigrp, struct stream *s,
881 uint32_t flags, uint32_t sequence, uint32_t ack)
882 {
883 struct eigrp_header *eigrph;
884
885 stream_reset(s);
886 eigrph = (struct eigrp_header *)STREAM_DATA(s);
887
888 eigrph->version = (uint8_t)EIGRP_HEADER_VERSION;
889 eigrph->opcode = (uint8_t)type;
890 eigrph->checksum = 0;
891
892 eigrph->vrid = htons(eigrp->vrid);
893 eigrph->ASNumber = htons(eigrp->AS);
894 eigrph->ack = htonl(ack);
895 eigrph->sequence = htonl(sequence);
896 // if(flags == EIGRP_INIT_FLAG)
897 // eigrph->sequence = htonl(3);
898 eigrph->flags = htonl(flags);
899
900 if (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))
901 zlog_debug("Packet Header Init Seq [%u] Ack [%u]",
902 htonl(eigrph->sequence), htonl(eigrph->ack));
903
904 stream_forward_endp(s, EIGRP_HEADER_LEN);
905 }
906
907 /* Add new packet to head of fifo. */
908 void eigrp_fifo_push(struct eigrp_fifo *fifo, struct eigrp_packet *ep)
909 {
910 ep->next = fifo->head;
911 ep->previous = NULL;
912
913 if (fifo->tail == NULL)
914 fifo->tail = ep;
915
916 if (fifo->count != 0)
917 fifo->head->previous = ep;
918
919 fifo->head = ep;
920
921 fifo->count++;
922 }
923
924 /* Return last fifo entry. */
925 struct eigrp_packet *eigrp_fifo_next(struct eigrp_fifo *fifo)
926 {
927 return fifo->tail;
928 }
929
930 void eigrp_packet_delete(struct eigrp_interface *ei)
931 {
932 struct eigrp_packet *ep;
933
934 ep = eigrp_fifo_pop(ei->obuf);
935
936 if (ep)
937 eigrp_packet_free(ep);
938 }
939
940 void eigrp_packet_free(struct eigrp_packet *ep)
941 {
942 if (ep->s)
943 stream_free(ep->s);
944
945 THREAD_OFF(ep->t_retrans_timer);
946
947 XFREE(MTYPE_EIGRP_PACKET, ep);
948 }
949
950 /* EIGRP Header verification. */
951 static int eigrp_verify_header(struct stream *ibuf, struct eigrp_interface *ei,
952 struct ip *iph, struct eigrp_header *eigrph)
953 {
954 /* Check network mask, Silently discarded. */
955 if (!eigrp_check_network_mask(ei, iph->ip_src)) {
956 zlog_warn(
957 "interface %s: eigrp_read network address is not same [%pI4]",
958 IF_NAME(ei), &iph->ip_src);
959 return -1;
960 }
961 //
962 // /* Check authentication. The function handles logging actions, where
963 // required. */
964 // if (! eigrp_check_auth(ei, eigrph))
965 // return -1;
966
967 return 0;
968 }
969
970 /* Unbound socket will accept any Raw IP packets if proto is matched.
971 To prevent it, compare src IP address and i/f address with masking
972 i/f network mask. */
973 static int eigrp_check_network_mask(struct eigrp_interface *ei,
974 struct in_addr ip_src)
975 {
976 struct in_addr mask, me, him;
977
978 if (ei->type == EIGRP_IFTYPE_POINTOPOINT)
979 return 1;
980
981 masklen2ip(ei->address.prefixlen, &mask);
982
983 me.s_addr = ei->address.u.prefix4.s_addr & mask.s_addr;
984 him.s_addr = ip_src.s_addr & mask.s_addr;
985
986 if (IPV4_ADDR_SAME(&me, &him))
987 return 1;
988
989 return 0;
990 }
991
992 int eigrp_unack_packet_retrans(struct thread *thread)
993 {
994 struct eigrp_neighbor *nbr;
995 nbr = (struct eigrp_neighbor *)THREAD_ARG(thread);
996
997 struct eigrp_packet *ep;
998 ep = eigrp_fifo_next(nbr->retrans_queue);
999
1000 if (ep) {
1001 struct eigrp_packet *duplicate;
1002 duplicate = eigrp_packet_duplicate(ep, nbr);
1003
1004 /* Add packet to the top of the interface output queue*/
1005 eigrp_fifo_push(nbr->ei->obuf, duplicate);
1006
1007 ep->retrans_counter++;
1008 if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX)
1009 return eigrp_retrans_count_exceeded(ep, nbr);
1010
1011 /*Start retransmission timer*/
1012 thread_add_timer(master, eigrp_unack_packet_retrans, nbr,
1013 EIGRP_PACKET_RETRANS_TIME,
1014 &ep->t_retrans_timer);
1015
1016 /* Hook thread to write packet. */
1017 if (nbr->ei->on_write_q == 0) {
1018 listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei);
1019 nbr->ei->on_write_q = 1;
1020 }
1021 thread_add_write(master, eigrp_write, nbr->ei->eigrp,
1022 nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write);
1023 }
1024
1025 return 0;
1026 }
1027
1028 int eigrp_unack_multicast_packet_retrans(struct thread *thread)
1029 {
1030 struct eigrp_neighbor *nbr;
1031 nbr = (struct eigrp_neighbor *)THREAD_ARG(thread);
1032
1033 struct eigrp_packet *ep;
1034 ep = eigrp_fifo_next(nbr->multicast_queue);
1035
1036 if (ep) {
1037 struct eigrp_packet *duplicate;
1038 duplicate = eigrp_packet_duplicate(ep, nbr);
1039 /* Add packet to the top of the interface output queue*/
1040 eigrp_fifo_push(nbr->ei->obuf, duplicate);
1041
1042 ep->retrans_counter++;
1043 if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX)
1044 return eigrp_retrans_count_exceeded(ep, nbr);
1045
1046 /*Start retransmission timer*/
1047 thread_add_timer(master, eigrp_unack_multicast_packet_retrans,
1048 nbr, EIGRP_PACKET_RETRANS_TIME,
1049 &ep->t_retrans_timer);
1050
1051 /* Hook thread to write packet. */
1052 if (nbr->ei->on_write_q == 0) {
1053 listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei);
1054 nbr->ei->on_write_q = 1;
1055 }
1056 thread_add_write(master, eigrp_write, nbr->ei->eigrp,
1057 nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write);
1058 }
1059
1060 return 0;
1061 }
1062
1063 /* Get packet from tail of fifo. */
1064 struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *fifo)
1065 {
1066 struct eigrp_packet *ep = NULL;
1067
1068 ep = fifo->tail;
1069
1070 if (ep) {
1071 fifo->tail = ep->previous;
1072
1073 if (fifo->tail == NULL)
1074 fifo->head = NULL;
1075 else
1076 fifo->tail->next = NULL;
1077
1078 fifo->count--;
1079 }
1080
1081 return ep;
1082 }
1083
1084 struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old,
1085 struct eigrp_neighbor *nbr)
1086 {
1087 struct eigrp_packet *new;
1088
1089 new = eigrp_packet_new(EIGRP_PACKET_MTU(nbr->ei->ifp->mtu), nbr);
1090 new->length = old->length;
1091 new->retrans_counter = old->retrans_counter;
1092 new->dst = old->dst;
1093 new->sequence_number = old->sequence_number;
1094 stream_copy(new->s, old->s);
1095
1096 return new;
1097 }
1098
1099 static struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new(void)
1100 {
1101 struct TLV_IPv4_Internal_type *new;
1102
1103 new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV,
1104 sizeof(struct TLV_IPv4_Internal_type));
1105
1106 return new;
1107 }
1108
1109 struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv(struct stream *s)
1110 {
1111 struct TLV_IPv4_Internal_type *tlv;
1112 uint32_t destination_tmp;
1113
1114 tlv = eigrp_IPv4_InternalTLV_new();
1115
1116 tlv->type = stream_getw(s);
1117 tlv->length = stream_getw(s);
1118 tlv->forward.s_addr = stream_getl(s);
1119 tlv->metric.delay = stream_getl(s);
1120 tlv->metric.bandwidth = stream_getl(s);
1121 tlv->metric.mtu[0] = stream_getc(s);
1122 tlv->metric.mtu[1] = stream_getc(s);
1123 tlv->metric.mtu[2] = stream_getc(s);
1124 tlv->metric.hop_count = stream_getc(s);
1125 tlv->metric.reliability = stream_getc(s);
1126 tlv->metric.load = stream_getc(s);
1127 tlv->metric.tag = stream_getc(s);
1128 tlv->metric.flags = stream_getc(s);
1129
1130 tlv->prefix_length = stream_getc(s);
1131
1132 destination_tmp = stream_getc(s) << 24;
1133 if (tlv->prefix_length > 8)
1134 destination_tmp |= stream_getc(s) << 16;
1135 if (tlv->prefix_length > 16)
1136 destination_tmp |= stream_getc(s) << 8;
1137 if (tlv->prefix_length > 24)
1138 destination_tmp |= stream_getc(s);
1139
1140 tlv->destination.s_addr = htonl(destination_tmp);
1141
1142 return tlv;
1143 }
1144
1145 uint16_t eigrp_add_internalTLV_to_stream(struct stream *s,
1146 struct eigrp_prefix_descriptor *pe)
1147 {
1148 uint16_t length;
1149
1150 stream_putw(s, EIGRP_TLV_IPv4_INT);
1151 switch (pe->destination->prefixlen) {
1152 case 0:
1153 case 1:
1154 case 2:
1155 case 3:
1156 case 4:
1157 case 5:
1158 case 6:
1159 case 7:
1160 case 8:
1161 length = EIGRP_TLV_IPV4_SIZE_GRT_0_BIT;
1162 stream_putw(s, length);
1163 break;
1164 case 9:
1165 case 10:
1166 case 11:
1167 case 12:
1168 case 13:
1169 case 14:
1170 case 15:
1171 case 16:
1172 length = EIGRP_TLV_IPV4_SIZE_GRT_8_BIT;
1173 stream_putw(s, length);
1174 break;
1175 case 17:
1176 case 18:
1177 case 19:
1178 case 20:
1179 case 21:
1180 case 22:
1181 case 23:
1182 case 24:
1183 length = EIGRP_TLV_IPV4_SIZE_GRT_16_BIT;
1184 stream_putw(s, length);
1185 break;
1186 case 25:
1187 case 26:
1188 case 27:
1189 case 28:
1190 case 29:
1191 case 30:
1192 case 31:
1193 case 32:
1194 length = EIGRP_TLV_IPV4_SIZE_GRT_24_BIT;
1195 stream_putw(s, length);
1196 break;
1197 default:
1198 flog_err(EC_LIB_DEVELOPMENT, "%s: Unexpected prefix length: %d",
1199 __func__, pe->destination->prefixlen);
1200 return 0;
1201 }
1202 stream_putl(s, 0x00000000);
1203
1204 /*Metric*/
1205 stream_putl(s, pe->reported_metric.delay);
1206 stream_putl(s, pe->reported_metric.bandwidth);
1207 stream_putc(s, pe->reported_metric.mtu[2]);
1208 stream_putc(s, pe->reported_metric.mtu[1]);
1209 stream_putc(s, pe->reported_metric.mtu[0]);
1210 stream_putc(s, pe->reported_metric.hop_count);
1211 stream_putc(s, pe->reported_metric.reliability);
1212 stream_putc(s, pe->reported_metric.load);
1213 stream_putc(s, pe->reported_metric.tag);
1214 stream_putc(s, pe->reported_metric.flags);
1215
1216 stream_putc(s, pe->destination->prefixlen);
1217
1218 stream_putc(s, (ntohl(pe->destination->u.prefix4.s_addr) >> 24) & 0xFF);
1219 if (pe->destination->prefixlen > 8)
1220 stream_putc(s, (ntohl(pe->destination->u.prefix4.s_addr) >> 16) & 0xFF);
1221 if (pe->destination->prefixlen > 16)
1222 stream_putc(s, (ntohl(pe->destination->u.prefix4.s_addr) >> 8) & 0xFF);
1223 if (pe->destination->prefixlen > 24)
1224 stream_putc(s, ntohl(pe->destination->u.prefix4.s_addr) & 0xFF);
1225
1226 return length;
1227 }
1228
1229 uint16_t eigrp_add_authTLV_MD5_to_stream(struct stream *s,
1230 struct eigrp_interface *ei)
1231 {
1232 struct key *key;
1233 struct keychain *keychain;
1234 struct TLV_MD5_Authentication_Type *authTLV;
1235
1236 authTLV = eigrp_authTLV_MD5_new();
1237
1238 authTLV->type = htons(EIGRP_TLV_AUTH);
1239 authTLV->length = htons(EIGRP_AUTH_MD5_TLV_SIZE);
1240 authTLV->auth_type = htons(EIGRP_AUTH_TYPE_MD5);
1241 authTLV->auth_length = htons(EIGRP_AUTH_TYPE_MD5_LEN);
1242 authTLV->key_sequence = 0;
1243 memset(authTLV->Nullpad, 0, sizeof(authTLV->Nullpad));
1244
1245 keychain = keychain_lookup(ei->params.auth_keychain);
1246 if (keychain)
1247 key = key_lookup_for_send(keychain);
1248 else {
1249 free(ei->params.auth_keychain);
1250 ei->params.auth_keychain = NULL;
1251 eigrp_authTLV_MD5_free(authTLV);
1252 return 0;
1253 }
1254
1255 if (key) {
1256 authTLV->key_id = htonl(key->index);
1257 memset(authTLV->digest, 0, EIGRP_AUTH_TYPE_MD5_LEN);
1258 stream_put(s, authTLV,
1259 sizeof(struct TLV_MD5_Authentication_Type));
1260 eigrp_authTLV_MD5_free(authTLV);
1261 return EIGRP_AUTH_MD5_TLV_SIZE;
1262 }
1263
1264 eigrp_authTLV_MD5_free(authTLV);
1265
1266 return 0;
1267 }
1268
1269 uint16_t eigrp_add_authTLV_SHA256_to_stream(struct stream *s,
1270 struct eigrp_interface *ei)
1271 {
1272 struct key *key;
1273 struct keychain *keychain;
1274 struct TLV_SHA256_Authentication_Type *authTLV;
1275
1276 authTLV = eigrp_authTLV_SHA256_new();
1277
1278 authTLV->type = htons(EIGRP_TLV_AUTH);
1279 authTLV->length = htons(EIGRP_AUTH_SHA256_TLV_SIZE);
1280 authTLV->auth_type = htons(EIGRP_AUTH_TYPE_SHA256);
1281 authTLV->auth_length = htons(EIGRP_AUTH_TYPE_SHA256_LEN);
1282 authTLV->key_sequence = 0;
1283 memset(authTLV->Nullpad, 0, sizeof(authTLV->Nullpad));
1284
1285 keychain = keychain_lookup(ei->params.auth_keychain);
1286 if (keychain)
1287 key = key_lookup_for_send(keychain);
1288 else {
1289 free(ei->params.auth_keychain);
1290 ei->params.auth_keychain = NULL;
1291 eigrp_authTLV_SHA256_free(authTLV);
1292 return 0;
1293 }
1294
1295 if (key) {
1296 authTLV->key_id = 0;
1297 memset(authTLV->digest, 0, EIGRP_AUTH_TYPE_SHA256_LEN);
1298 stream_put(s, authTLV,
1299 sizeof(struct TLV_SHA256_Authentication_Type));
1300 eigrp_authTLV_SHA256_free(authTLV);
1301 return EIGRP_AUTH_SHA256_TLV_SIZE;
1302 }
1303
1304 eigrp_authTLV_SHA256_free(authTLV);
1305
1306 return 0;
1307 }
1308
1309 struct TLV_MD5_Authentication_Type *eigrp_authTLV_MD5_new(void)
1310 {
1311 struct TLV_MD5_Authentication_Type *new;
1312
1313 new = XCALLOC(MTYPE_EIGRP_AUTH_TLV,
1314 sizeof(struct TLV_MD5_Authentication_Type));
1315
1316 return new;
1317 }
1318
1319 void eigrp_authTLV_MD5_free(struct TLV_MD5_Authentication_Type *authTLV)
1320 {
1321 XFREE(MTYPE_EIGRP_AUTH_TLV, authTLV);
1322 }
1323
1324 struct TLV_SHA256_Authentication_Type *eigrp_authTLV_SHA256_new(void)
1325 {
1326 struct TLV_SHA256_Authentication_Type *new;
1327
1328 new = XCALLOC(MTYPE_EIGRP_AUTH_SHA256_TLV,
1329 sizeof(struct TLV_SHA256_Authentication_Type));
1330
1331 return new;
1332 }
1333
1334 void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type *authTLV)
1335 {
1336 XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV);
1337 }
1338
1339 void eigrp_IPv4_InternalTLV_free(
1340 struct TLV_IPv4_Internal_type *IPv4_InternalTLV)
1341 {
1342 XFREE(MTYPE_EIGRP_IPV4_INT_TLV, IPv4_InternalTLV);
1343 }
1344
1345 struct TLV_Sequence_Type *eigrp_SequenceTLV_new(void)
1346 {
1347 struct TLV_Sequence_Type *new;
1348
1349 new = XCALLOC(MTYPE_EIGRP_SEQ_TLV, sizeof(struct TLV_Sequence_Type));
1350
1351 return new;
1352 }