if (keychain)
key = key_lookup_for_send(keychain);
+ if (!key) {
+ zlog_warn("Interface %s: Expected key value not found in config",
+ nbr->ei->ifp->name);
+ return 0;
+ }
+
memset(&ctx, 0, sizeof(ctx));
MD5Init(&ctx);
}
/* save neighbor's crypt_seqnum */
- if (nbr)
- nbr->crypt_seqnum = authTLV->key_sequence;
+ nbr->crypt_seqnum = authTLV->key_sequence;
return 1;
}
{
struct key *key = NULL;
struct keychain *keychain;
- char *source_ip;
+ char source_ip[PREFIX_STRLEN];
unsigned char digest[EIGRP_AUTH_TYPE_SHA256_LEN];
unsigned char buffer[1 + PLAINTEXT_LENGTH + 45 + 1] = {0};
+
HMAC_SHA256_CTX ctx;
void *ibuf;
size_t backup_get, backup_end;
if (keychain)
key = key_lookup_for_send(keychain);
- // saved_len[index] = strnzcpyn(saved_key[index], key,
- // PLAINTEXT_LENGTH + 1);
+ if (!key) {
+ zlog_warn("Interface %s: Expected key value not found in config",
+ ei->ifp->name);
+ return 0;
+ }
- source_ip = calloc(16, sizeof(char));
- inet_ntop(AF_INET, &ei->address->u.prefix4, source_ip, 16);
+ inet_ntop(AF_INET, &ei->address->u.prefix4, source_ip, PREFIX_STRLEN);
memset(&ctx, 0, sizeof(ctx));
buffer[0] = '\n';
stream_set_endp(s, backup_end);
eigrp_authTLV_SHA256_free(auth_TLV);
- free(source_ip);
return EIGRP_AUTH_TYPE_SHA256_LEN;
}
return 1;
}
-/*
- * eigrp_packet_dump
- *
- * This routing dumps the contents of the IP packet either received or
- * built by EIGRP.
- */
-static void eigrp_packet_dump(struct stream *s)
-{
- // not yet...
- return;
-}
-
int eigrp_write(struct thread *thread)
{
struct eigrp *eigrp = THREAD_ARG(thread);
struct msghdr msg;
struct iovec iov[2];
u_int16_t opcode = 0;
+ u_int32_t seqno, ack;
int ret;
int flags = 0;
#endif /* WANT_EIGRP_WRITE_FRAGMENT */
/* Get one packet from queue. */
- ep = eigrp_fifo_head(ei->obuf);
+ ep = eigrp_fifo_next(ei->obuf);
assert(ep);
assert(ep->length >= EIGRP_HEADER_LEN);
memset(&iph, 0, sizeof(struct ip));
memset(&sa_dst, 0, sizeof(sa_dst));
+ /*
+ * We build and schedule packets to go out
+ * in the future. In the mean time we may
+ * process some update packets from the
+ * neighbor, thus making it necessary
+ * to update the ack we are using for
+ * this outgoing packet.
+ */
+ eigrph = (struct eigrp_header *)STREAM_DATA(ep->s);
+ opcode = eigrph->opcode;
+ seqno = ntohl(eigrph->sequence);
+ ack = ntohl(eigrph->ack);
+ if (ep->nbr && (ack != ep->nbr->recv_sequence_number)) {
+ eigrph->ack = htonl(ep->nbr->recv_sequence_number);
+ ack = ep->nbr->recv_sequence_number;
+ eigrph->checksum = 0;
+ eigrp_packet_checksum(ei, ep->s, ep->length);
+ }
+
sa_dst.sin_family = AF_INET;
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
sa_dst.sin_len = sizeof(sa_dst);
if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND)) {
eigrph = (struct eigrp_header *)STREAM_DATA(ep->s);
opcode = eigrph->opcode;
- zlog_debug("Sending [%s] to [%s] via [%s] ret [%d].",
+ zlog_debug("Sending [%s][%d/%d] to [%s] via [%s] ret [%d].",
lookup_msg(eigrp_packet_type_str, opcode, NULL),
+ seqno, ack,
inet_ntoa(ep->dst), IF_NAME(ei), ret);
}
iph.ip_len, ei->ifp->name, ei->ifp->mtu,
safe_strerror(errno));
- /* Show debug sending packet. */
- if (IS_DEBUG_EIGRP_TRANSMIT(0, SEND)
- && (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))) {
- zlog_debug(
- "-----------------------------------------------------");
- eigrp_ip_header_dump(&iph);
- stream_set_getp(ep->s, 0);
- eigrp_packet_dump(ep->s);
- zlog_debug(
- "-----------------------------------------------------");
- }
-
/* Now delete packet from queue. */
eigrp_packet_delete(ei);
- if (eigrp_fifo_head(ei->obuf) == NULL) {
+ if (eigrp_fifo_next(ei->obuf) == NULL) {
ei->on_write_q = 0;
list_delete_node(eigrp->oi_write_q, node);
}
start of the eigrp TLVs */
opcode = eigrph->opcode;
- if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
- zlog_debug(
- "Received [%s] length [%u] via [%s] src [%s] dst [%s]",
- lookup_msg(eigrp_packet_type_str, opcode, NULL), length,
- IF_NAME(ei), inet_ntoa(iph->ip_src),
- inet_ntoa(iph->ip_dst));
+ if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) {
+ char src[PREFIX_STRLEN], dst[PREFIX_STRLEN];
+
+ strncpy(src, inet_ntoa(iph->ip_src), PREFIX_STRLEN);
+ strncpy(dst, inet_ntoa(iph->ip_dst), PREFIX_STRLEN);
+ zlog_debug("Received [%s][%d/%d] length [%u] via [%s] src [%s] dst [%s]",
+ lookup_msg(eigrp_packet_type_str, opcode, NULL),
+ ntohl(eigrph->sequence), ntohl(eigrph->ack), length,
+ IF_NAME(ei), src, dst);
+ }
/* Read rest of the packet and call each sort of packet routine. */
stream_forward_getp(ibuf, EIGRP_HEADER_LEN);
/* New testing block of code for handling Acks */
if (ntohl(eigrph->ack) != 0) {
+ struct eigrp_packet *ep = NULL;
+
nbr = eigrp_nbr_get(ei, eigrph, iph);
- /* neighbor must be valid, eigrp_nbr_get creates if none existed
- */
+ // neighbor must be valid, eigrp_nbr_get creates if none existed
assert(nbr);
- struct eigrp_packet *ep;
-
- ep = eigrp_fifo_tail(nbr->retrans_queue);
- if (ep) {
- if (ntohl(eigrph->ack) == ep->sequence_number) {
- if ((nbr->state == EIGRP_NEIGHBOR_PENDING)
- && (ntohl(eigrph->ack)
- == nbr->init_sequence_number)) {
- eigrp_nbr_state_set(nbr,
- EIGRP_NEIGHBOR_UP);
- zlog_info(
- "Neighbor adjacency became full");
- nbr->init_sequence_number = 0;
- nbr->recv_sequence_number =
- ntohl(eigrph->sequence);
- eigrp_update_send_EOT(nbr);
- }
- ep = eigrp_fifo_pop_tail(nbr->retrans_queue);
- eigrp_packet_free(ep);
- if (nbr->retrans_queue->count > 0) {
- eigrp_send_packet_reliably(nbr);
- }
+ ep = eigrp_fifo_next(nbr->retrans_queue);
+ if ((ep) && (ntohl(eigrph->ack) == ep->sequence_number)) {
+ ep = eigrp_fifo_pop(nbr->retrans_queue);
+ eigrp_packet_free(ep);
+
+ if ((nbr->state == EIGRP_NEIGHBOR_PENDING)
+ && (ntohl(eigrph->ack) == nbr->init_sequence_number)) {
+ eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_UP);
+ zlog_info("Neighbor(%s) adjacency became full",
+ inet_ntoa(nbr->src));
+ nbr->init_sequence_number = 0;
+ nbr->recv_sequence_number =
+ ntohl(eigrph->sequence);
+ eigrp_update_send_EOT(nbr);
}
+ else
+ eigrp_send_packet_reliably(nbr);
}
- ep = eigrp_fifo_tail(nbr->multicast_queue);
+ ep = eigrp_fifo_next(nbr->multicast_queue);
if (ep) {
if (ntohl(eigrph->ack) == ep->sequence_number) {
- ep = eigrp_fifo_pop_tail(nbr->multicast_queue);
+ ep = eigrp_fifo_pop(nbr->multicast_queue);
eigrp_packet_free(ep);
if (nbr->multicast_queue->count > 0) {
eigrp_send_packet_reliably(nbr);
fifo->count = 0;
}
-struct eigrp_packet *eigrp_packet_new(size_t size)
+struct eigrp_packet *eigrp_packet_new(size_t size, struct eigrp_neighbor *nbr)
{
struct eigrp_packet *new;
new = XCALLOC(MTYPE_EIGRP_PACKET, sizeof(struct eigrp_packet));
new->s = stream_new(size);
new->retrans_counter = 0;
+ new->nbr = nbr;
return new;
}
{
struct eigrp_packet *ep;
- ep = eigrp_fifo_tail(nbr->retrans_queue);
+ ep = eigrp_fifo_next(nbr->retrans_queue);
if (ep) {
struct eigrp_packet *duplicate;
duplicate = eigrp_packet_duplicate(ep, nbr);
/* Add packet to the top of the interface output queue*/
- eigrp_fifo_push_head(nbr->ei->obuf, duplicate);
+ eigrp_fifo_push(nbr->ei->obuf, duplicate);
/*Start retransmission timer*/
thread_add_timer(master, eigrp_unack_packet_retrans, nbr,
}
/* Make EIGRP header. */
-void eigrp_packet_header_init(int type, struct eigrp_interface *ei,
+void eigrp_packet_header_init(int type, struct eigrp *eigrp,
struct stream *s, u_int32_t flags,
u_int32_t sequence, u_int32_t ack)
{
eigrph->opcode = (u_char)type;
eigrph->checksum = 0;
- eigrph->vrid = htons(ei->eigrp->vrid);
- eigrph->ASNumber = htons(ei->eigrp->AS);
+ eigrph->vrid = htons(eigrp->vrid);
+ eigrph->ASNumber = htons(eigrp->AS);
eigrph->ack = htonl(ack);
eigrph->sequence = htonl(sequence);
// if(flags == EIGRP_INIT_FLAG)
// eigrph->sequence = htonl(3);
eigrph->flags = htonl(flags);
- if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
+ if (IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))
zlog_debug("Packet Header Init Seq [%u] Ack [%u]",
htonl(eigrph->sequence), htonl(eigrph->ack));
}
/* Add new packet to head of fifo. */
-void eigrp_fifo_push_head(struct eigrp_fifo *fifo, struct eigrp_packet *ep)
+void eigrp_fifo_push(struct eigrp_fifo *fifo, struct eigrp_packet *ep)
{
ep->next = fifo->head;
ep->previous = NULL;
fifo->count++;
}
-/* Return first fifo entry. */
-struct eigrp_packet *eigrp_fifo_head(struct eigrp_fifo *fifo)
-{
- return fifo->head;
-}
-
/* Return last fifo entry. */
-struct eigrp_packet *eigrp_fifo_tail(struct eigrp_fifo *fifo)
+struct eigrp_packet *eigrp_fifo_next(struct eigrp_fifo *fifo)
{
return fifo->tail;
}
eigrp_packet_free(ep);
}
-/* Delete first packet from fifo. */
-struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *fifo)
-{
- struct eigrp_packet *ep;
-
- ep = fifo->head;
-
- if (ep) {
- fifo->head = ep->next;
-
- if (fifo->head == NULL)
- fifo->tail = NULL;
- else
- fifo->head->previous = NULL;
-
- fifo->count--;
- }
-
- return ep;
-}
-
void eigrp_packet_free(struct eigrp_packet *ep)
{
if (ep->s)
nbr = (struct eigrp_neighbor *)THREAD_ARG(thread);
struct eigrp_packet *ep;
- ep = eigrp_fifo_tail(nbr->retrans_queue);
+ ep = eigrp_fifo_next(nbr->retrans_queue);
if (ep) {
struct eigrp_packet *duplicate;
duplicate = eigrp_packet_duplicate(ep, nbr);
/* Add packet to the top of the interface output queue*/
- eigrp_fifo_push_head(nbr->ei->obuf, duplicate);
+ eigrp_fifo_push(nbr->ei->obuf, duplicate);
ep->retrans_counter++;
if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX)
nbr = (struct eigrp_neighbor *)THREAD_ARG(thread);
struct eigrp_packet *ep;
- ep = eigrp_fifo_tail(nbr->multicast_queue);
+ ep = eigrp_fifo_next(nbr->multicast_queue);
if (ep) {
struct eigrp_packet *duplicate;
duplicate = eigrp_packet_duplicate(ep, nbr);
/* Add packet to the top of the interface output queue*/
- eigrp_fifo_push_head(nbr->ei->obuf, duplicate);
+ eigrp_fifo_push(nbr->ei->obuf, duplicate);
ep->retrans_counter++;
if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX)
}
/* Get packet from tail of fifo. */
-struct eigrp_packet *eigrp_fifo_pop_tail(struct eigrp_fifo *fifo)
+struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *fifo)
{
- struct eigrp_packet *ep;
+ struct eigrp_packet *ep = NULL;
ep = fifo->tail;
{
struct eigrp_packet *new;
- new = eigrp_packet_new(nbr->ei->ifp->mtu);
+ new = eigrp_packet_new(nbr->ei->ifp->mtu, nbr);
new->length = old->length;
new->retrans_counter = old->retrans_counter;
new->dst = old->dst;
return new;
}
+static struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new()
+{
+ struct TLV_IPv4_Internal_type *new;
+
+ new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV,
+ sizeof(struct TLV_IPv4_Internal_type));
+
+ return new;
+}
+
struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv(struct stream *s)
{
struct TLV_IPv4_Internal_type *tlv;
u_int16_t length;
stream_putw(s, EIGRP_TLV_IPv4_INT);
- if (pe->destination_ipv4->prefixlen <= 8) {
+ if (pe->destination->prefixlen <= 8) {
stream_putw(s, 0x001A);
length = 0x001A;
}
- if ((pe->destination_ipv4->prefixlen > 8)
- && (pe->destination_ipv4->prefixlen <= 16)) {
+ if ((pe->destination->prefixlen > 8)
+ && (pe->destination->prefixlen <= 16)) {
stream_putw(s, 0x001B);
length = 0x001B;
}
- if ((pe->destination_ipv4->prefixlen > 16)
- && (pe->destination_ipv4->prefixlen <= 24)) {
+ if ((pe->destination->prefixlen > 16)
+ && (pe->destination->prefixlen <= 24)) {
stream_putw(s, 0x001C);
length = 0x001C;
}
- if (pe->destination_ipv4->prefixlen > 24) {
+ if (pe->destination->prefixlen > 24) {
stream_putw(s, 0x001D);
length = 0x001D;
}
stream_putc(s, pe->reported_metric.tag);
stream_putc(s, pe->reported_metric.flags);
- stream_putc(s, pe->destination_ipv4->prefixlen);
+ stream_putc(s, pe->destination->prefixlen);
- if (pe->destination_ipv4->prefixlen <= 8) {
- stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
- }
- if ((pe->destination_ipv4->prefixlen > 8)
- && (pe->destination_ipv4->prefixlen <= 16)) {
- stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
+ stream_putc(s, pe->destination->u.prefix4.s_addr & 0xFF);
+ if (pe->destination->prefixlen > 8)
stream_putc(s,
- (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF);
- }
- if ((pe->destination_ipv4->prefixlen > 16)
- && (pe->destination_ipv4->prefixlen <= 24)) {
- stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
+ (pe->destination->u.prefix4.s_addr >> 8) & 0xFF);
+ if (pe->destination->prefixlen > 16)
stream_putc(s,
- (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF);
+ (pe->destination->u.prefix4.s_addr >> 16) & 0xFF);
+ if (pe->destination->prefixlen > 24)
stream_putc(s,
- (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF);
- }
- if (pe->destination_ipv4->prefixlen > 24) {
- stream_putc(s, pe->destination_ipv4->prefix.s_addr & 0xFF);
- stream_putc(s,
- (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF);
- stream_putc(s,
- (pe->destination_ipv4->prefix.s_addr >> 16) & 0xFF);
- stream_putc(s,
- (pe->destination_ipv4->prefix.s_addr >> 24) & 0xFF);
- }
+ (pe->destination->u.prefix4.s_addr >> 24) & 0xFF);
return length;
}
XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV);
}
-struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new()
-{
- struct TLV_IPv4_Internal_type *new;
-
- new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV,
- sizeof(struct TLV_IPv4_Internal_type));
-
- return new;
-}
-
void eigrp_IPv4_InternalTLV_free(
struct TLV_IPv4_Internal_type *IPv4_InternalTLV)
{