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