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