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