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