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