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