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