diff options
Diffstat (limited to 'eigrpd/eigrp_packet.c')
| -rw-r--r-- | eigrpd/eigrp_packet.c | 2244 |
1 files changed, 1105 insertions, 1139 deletions
diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index f481dffa98..f20ec0ad12 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -57,252 +57,244 @@ #include "eigrpd/eigrp_memory.h" /* Packet Type String. */ -const struct message eigrp_packet_type_str[] = - { - { EIGRP_OPC_UPDATE, "Update"}, - { EIGRP_OPC_REQUEST, "Request"}, - { EIGRP_OPC_QUERY, "Query"}, - { EIGRP_OPC_REPLY, "Reply"}, - { EIGRP_OPC_HELLO, "Hello"}, - { EIGRP_OPC_IPXSAP, "IPX-SAP"}, - { EIGRP_OPC_PROBE, "Probe"}, - { EIGRP_OPC_ACK, "Ack"}, - { EIGRP_OPC_SIAQUERY, "SIAQuery"}, - { EIGRP_OPC_SIAREPLY, "SIAReply"}, - { 0 } -}; +const struct message eigrp_packet_type_str[] = { + {EIGRP_OPC_UPDATE, "Update"}, + {EIGRP_OPC_REQUEST, "Request"}, + {EIGRP_OPC_QUERY, "Query"}, + {EIGRP_OPC_REPLY, "Reply"}, + {EIGRP_OPC_HELLO, "Hello"}, + {EIGRP_OPC_IPXSAP, "IPX-SAP"}, + {EIGRP_OPC_PROBE, "Probe"}, + {EIGRP_OPC_ACK, "Ack"}, + {EIGRP_OPC_SIAQUERY, "SIAQuery"}, + {EIGRP_OPC_SIAREPLY, "SIAReply"}, + {0}}; static unsigned char zeropad[16] = {0}; /* Forward function reference*/ -static struct stream * eigrp_recv_packet (int, struct interface **, struct stream *); -static int eigrp_verify_header (struct stream *, struct eigrp_interface *, struct ip *, - struct eigrp_header *); -static int eigrp_check_network_mask (struct eigrp_interface *, struct in_addr); - -static int eigrp_retrans_count_exceeded(struct eigrp_packet *ep, struct eigrp_neighbor *nbr) +static struct stream *eigrp_recv_packet(int, struct interface **, + struct stream *); +static int eigrp_verify_header(struct stream *, struct eigrp_interface *, + struct ip *, struct eigrp_header *); +static int eigrp_check_network_mask(struct eigrp_interface *, struct in_addr); + +static int eigrp_retrans_count_exceeded(struct eigrp_packet *ep, + struct eigrp_neighbor *nbr) { - return 1; + return 1; } -int -eigrp_make_md5_digest (struct eigrp_interface *ei, struct stream *s, u_char flags) +int eigrp_make_md5_digest(struct eigrp_interface *ei, struct stream *s, + u_char flags) { - struct key *key = NULL; - struct keychain *keychain; - - unsigned char digest[EIGRP_AUTH_TYPE_MD5_LEN]; - MD5_CTX ctx; - u_char *ibuf; - size_t backup_get, backup_end; - struct TLV_MD5_Authentication_Type *auth_TLV; - - ibuf = s->data; - backup_end = s->endp; - backup_get = s->getp; - - auth_TLV = eigrp_authTLV_MD5_new(); - - stream_set_getp(s,EIGRP_HEADER_LEN); - stream_get(auth_TLV,s,EIGRP_AUTH_MD5_TLV_SIZE); - stream_set_getp(s, backup_get); - - keychain = keychain_lookup(IF_DEF_PARAMS (ei->ifp)->auth_keychain); - if(keychain) - key = key_lookup_for_send(keychain); - else - { - eigrp_authTLV_MD5_free(auth_TLV); - return EIGRP_AUTH_TYPE_NONE; - } - - memset(&ctx, 0, sizeof(ctx)); - MD5Init(&ctx); - - /* Generate a digest. Each situation needs different handling */ - if(flags & EIGRP_AUTH_BASIC_HELLO_FLAG) - { - MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); - MD5Update(&ctx, key->string, strlen(key->string)); - if(strlen(key->string) < 16) - MD5Update(&ctx, zeropad, 16 - strlen(key->string)); - } - else if(flags & EIGRP_AUTH_UPDATE_INIT_FLAG) - { - MD5Update(&ctx, ibuf, EIGRP_MD5_UPDATE_INIT_COMPUTE); - } - else if(flags & EIGRP_AUTH_UPDATE_FLAG) - { - MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); - MD5Update(&ctx, key->string, strlen(key->string)); - if(strlen(key->string) < 16) - MD5Update(&ctx, zeropad, 16 - strlen(key->string)); - if(backup_end > (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)) - { - MD5Update(&ctx, ibuf + (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE), - backup_end - 20 - (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)); - } - } - - MD5Final(digest, &ctx); - - /* Append md5 digest to the end of the stream. */ - memcpy(auth_TLV->digest,digest,EIGRP_AUTH_TYPE_MD5_LEN); - - stream_set_endp(s,EIGRP_HEADER_LEN); - stream_put(s,auth_TLV,EIGRP_AUTH_MD5_TLV_SIZE); - stream_set_endp(s, backup_end); - - eigrp_authTLV_MD5_free(auth_TLV); - return EIGRP_AUTH_TYPE_MD5_LEN; + struct key *key = NULL; + struct keychain *keychain; + + unsigned char digest[EIGRP_AUTH_TYPE_MD5_LEN]; + MD5_CTX ctx; + u_char *ibuf; + size_t backup_get, backup_end; + struct TLV_MD5_Authentication_Type *auth_TLV; + + ibuf = s->data; + backup_end = s->endp; + backup_get = s->getp; + + auth_TLV = eigrp_authTLV_MD5_new(); + + stream_set_getp(s, EIGRP_HEADER_LEN); + stream_get(auth_TLV, s, EIGRP_AUTH_MD5_TLV_SIZE); + stream_set_getp(s, backup_get); + + keychain = keychain_lookup(IF_DEF_PARAMS(ei->ifp)->auth_keychain); + if (keychain) + key = key_lookup_for_send(keychain); + else { + eigrp_authTLV_MD5_free(auth_TLV); + return EIGRP_AUTH_TYPE_NONE; + } + + memset(&ctx, 0, sizeof(ctx)); + MD5Init(&ctx); + + /* Generate a digest. Each situation needs different handling */ + if (flags & EIGRP_AUTH_BASIC_HELLO_FLAG) { + MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); + MD5Update(&ctx, key->string, strlen(key->string)); + if (strlen(key->string) < 16) + MD5Update(&ctx, zeropad, 16 - strlen(key->string)); + } else if (flags & EIGRP_AUTH_UPDATE_INIT_FLAG) { + MD5Update(&ctx, ibuf, EIGRP_MD5_UPDATE_INIT_COMPUTE); + } else if (flags & EIGRP_AUTH_UPDATE_FLAG) { + MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); + MD5Update(&ctx, key->string, strlen(key->string)); + if (strlen(key->string) < 16) + MD5Update(&ctx, zeropad, 16 - strlen(key->string)); + if (backup_end > (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)) { + MD5Update(&ctx, + ibuf + (EIGRP_HEADER_LEN + + EIGRP_AUTH_MD5_TLV_SIZE), + backup_end - 20 + - (EIGRP_HEADER_LEN + + EIGRP_AUTH_MD5_TLV_SIZE)); + } + } + + MD5Final(digest, &ctx); + + /* Append md5 digest to the end of the stream. */ + memcpy(auth_TLV->digest, digest, EIGRP_AUTH_TYPE_MD5_LEN); + + stream_set_endp(s, EIGRP_HEADER_LEN); + stream_put(s, auth_TLV, EIGRP_AUTH_MD5_TLV_SIZE); + stream_set_endp(s, backup_end); + + eigrp_authTLV_MD5_free(auth_TLV); + return EIGRP_AUTH_TYPE_MD5_LEN; } -int -eigrp_check_md5_digest (struct stream *s, - struct TLV_MD5_Authentication_Type *authTLV,struct eigrp_neighbor *nbr, u_char flags) +int eigrp_check_md5_digest(struct stream *s, + struct TLV_MD5_Authentication_Type *authTLV, + struct eigrp_neighbor *nbr, u_char flags) { - MD5_CTX ctx; - unsigned char digest[EIGRP_AUTH_TYPE_MD5_LEN]; - struct key *key = NULL; - struct keychain *keychain; - u_char *ibuf; - size_t backup_end; - struct TLV_MD5_Authentication_Type *auth_TLV; - struct eigrp_header *eigrph; - - if (nbr && ntohl(nbr->crypt_seqnum) > ntohl(authTLV->key_sequence)) - { - zlog_warn ("interface %s: eigrp_check_md5 bad sequence %d (expect %d)", - IF_NAME (nbr->ei), - ntohl(authTLV->key_sequence), - ntohl(nbr->crypt_seqnum)); - return 0; - } - - eigrph = (struct eigrp_header *) s->data; - eigrph->checksum = 0; - - auth_TLV =(struct TLV_MD5_Authentication_Type *) (s->data + EIGRP_HEADER_LEN); - memset(auth_TLV->digest, 0, sizeof(auth_TLV->digest)); - - ibuf = s->data; - backup_end = s->endp; - - keychain = keychain_lookup(IF_DEF_PARAMS (nbr->ei->ifp)->auth_keychain); - if(keychain) - key = key_lookup_for_send(keychain); - - memset(&ctx, 0, sizeof(ctx)); - MD5Init(&ctx); - - /* Generate a digest. Each situation needs different handling */ - if(flags & EIGRP_AUTH_BASIC_HELLO_FLAG) - { - MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); - MD5Update(&ctx, key->string, strlen(key->string)); - if(strlen(key->string) < 16) - MD5Update(&ctx, zeropad, 16 - strlen(key->string)); - } - else if(flags & EIGRP_AUTH_UPDATE_INIT_FLAG) - { - MD5Update(&ctx, ibuf, EIGRP_MD5_UPDATE_INIT_COMPUTE); - } - else if(flags & EIGRP_AUTH_UPDATE_FLAG) - { - MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); - MD5Update(&ctx, key->string, strlen(key->string)); - if(strlen(key->string) < 16) - MD5Update(&ctx, zeropad, 16 - strlen(key->string)); - if(backup_end > (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)) - { - MD5Update(&ctx, ibuf + (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE), - backup_end - 20 - (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)); - } - } - - MD5Final(digest, &ctx); - - /* compare the two */ - if (memcmp (authTLV->digest, digest, EIGRP_AUTH_TYPE_MD5_LEN) == 0) - { - zlog_debug("VSETKO OK"); - } - else - { - zlog_warn ("interface %s: eigrp_check_md5 checksum mismatch", - IF_NAME (nbr->ei)); - return 0; - } - - /* save neighbor's crypt_seqnum */ - nbr->crypt_seqnum = authTLV->key_sequence; - - return 1; + MD5_CTX ctx; + unsigned char digest[EIGRP_AUTH_TYPE_MD5_LEN]; + struct key *key = NULL; + struct keychain *keychain; + u_char *ibuf; + size_t backup_end; + struct TLV_MD5_Authentication_Type *auth_TLV; + struct eigrp_header *eigrph; + + if (nbr && ntohl(nbr->crypt_seqnum) > ntohl(authTLV->key_sequence)) { + zlog_warn( + "interface %s: eigrp_check_md5 bad sequence %d (expect %d)", + IF_NAME(nbr->ei), ntohl(authTLV->key_sequence), + ntohl(nbr->crypt_seqnum)); + return 0; + } + + eigrph = (struct eigrp_header *)s->data; + eigrph->checksum = 0; + + auth_TLV = (struct TLV_MD5_Authentication_Type *)(s->data + + EIGRP_HEADER_LEN); + memset(auth_TLV->digest, 0, sizeof(auth_TLV->digest)); + + ibuf = s->data; + backup_end = s->endp; + + keychain = keychain_lookup(IF_DEF_PARAMS(nbr->ei->ifp)->auth_keychain); + if (keychain) + key = key_lookup_for_send(keychain); + + memset(&ctx, 0, sizeof(ctx)); + MD5Init(&ctx); + + /* Generate a digest. Each situation needs different handling */ + if (flags & EIGRP_AUTH_BASIC_HELLO_FLAG) { + MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); + MD5Update(&ctx, key->string, strlen(key->string)); + if (strlen(key->string) < 16) + MD5Update(&ctx, zeropad, 16 - strlen(key->string)); + } else if (flags & EIGRP_AUTH_UPDATE_INIT_FLAG) { + MD5Update(&ctx, ibuf, EIGRP_MD5_UPDATE_INIT_COMPUTE); + } else if (flags & EIGRP_AUTH_UPDATE_FLAG) { + MD5Update(&ctx, ibuf, EIGRP_MD5_BASIC_COMPUTE); + MD5Update(&ctx, key->string, strlen(key->string)); + if (strlen(key->string) < 16) + MD5Update(&ctx, zeropad, 16 - strlen(key->string)); + if (backup_end > (EIGRP_HEADER_LEN + EIGRP_AUTH_MD5_TLV_SIZE)) { + MD5Update(&ctx, + ibuf + (EIGRP_HEADER_LEN + + EIGRP_AUTH_MD5_TLV_SIZE), + backup_end - 20 + - (EIGRP_HEADER_LEN + + EIGRP_AUTH_MD5_TLV_SIZE)); + } + } + + MD5Final(digest, &ctx); + + /* compare the two */ + if (memcmp(authTLV->digest, digest, EIGRP_AUTH_TYPE_MD5_LEN) == 0) { + zlog_debug("VSETKO OK"); + } else { + zlog_warn("interface %s: eigrp_check_md5 checksum mismatch", + IF_NAME(nbr->ei)); + return 0; + } + + /* save neighbor's crypt_seqnum */ + nbr->crypt_seqnum = authTLV->key_sequence; + + return 1; } -int -eigrp_make_sha256_digest (struct eigrp_interface *ei, struct stream *s, u_char flags) +int eigrp_make_sha256_digest(struct eigrp_interface *ei, struct stream *s, + u_char flags) { - struct key *key = NULL; - struct keychain *keychain; - char *source_ip; + struct key *key = NULL; + struct keychain *keychain; + char *source_ip; - 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; - struct TLV_SHA256_Authentication_Type *auth_TLV; + 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; + struct TLV_SHA256_Authentication_Type *auth_TLV; - ibuf = s->data; - backup_end = s->endp; - backup_get = s->getp; + ibuf = s->data; + backup_end = s->endp; + backup_get = s->getp; - auth_TLV = eigrp_authTLV_SHA256_new (); + auth_TLV = eigrp_authTLV_SHA256_new(); - stream_set_getp(s,EIGRP_HEADER_LEN); - stream_get(auth_TLV,s,EIGRP_AUTH_SHA256_TLV_SIZE); - stream_set_getp(s, backup_get); + stream_set_getp(s, EIGRP_HEADER_LEN); + stream_get(auth_TLV, s, EIGRP_AUTH_SHA256_TLV_SIZE); + stream_set_getp(s, backup_get); - keychain = keychain_lookup(IF_DEF_PARAMS (ei->ifp)->auth_keychain); - if(keychain) - key = key_lookup_for_send(keychain); + keychain = keychain_lookup(IF_DEF_PARAMS(ei->ifp)->auth_keychain); + if (keychain) + key = key_lookup_for_send(keychain); - // saved_len[index] = strnzcpyn(saved_key[index], key, - // PLAINTEXT_LENGTH + 1); + // saved_len[index] = strnzcpyn(saved_key[index], key, + // PLAINTEXT_LENGTH + 1); - source_ip = calloc(16, sizeof(char)); - inet_ntop(AF_INET, &ei->address->u.prefix4, source_ip, 16); + source_ip = calloc(16, sizeof(char)); + inet_ntop(AF_INET, &ei->address->u.prefix4, source_ip, 16); - memset(&ctx, 0, sizeof(ctx)); - buffer[0] = '\n'; - memcpy(buffer + 1, key, strlen (key->string)); - memcpy(buffer + 1 + strlen(key->string), source_ip, strlen(source_ip)); - HMAC__SHA256_Init(&ctx, buffer, 1 + strlen (key->string) + strlen(source_ip)); - HMAC__SHA256_Update(&ctx, ibuf, strlen(ibuf)); - HMAC__SHA256_Final(digest, &ctx); + memset(&ctx, 0, sizeof(ctx)); + buffer[0] = '\n'; + memcpy(buffer + 1, key, strlen(key->string)); + memcpy(buffer + 1 + strlen(key->string), source_ip, strlen(source_ip)); + HMAC__SHA256_Init(&ctx, buffer, + 1 + strlen(key->string) + strlen(source_ip)); + HMAC__SHA256_Update(&ctx, ibuf, strlen(ibuf)); + HMAC__SHA256_Final(digest, &ctx); - /* Put hmac-sha256 digest to it's place */ - memcpy(auth_TLV->digest,digest,EIGRP_AUTH_TYPE_SHA256_LEN); + /* Put hmac-sha256 digest to it's place */ + memcpy(auth_TLV->digest, digest, EIGRP_AUTH_TYPE_SHA256_LEN); - stream_set_endp(s,EIGRP_HEADER_LEN); - stream_put(s,auth_TLV,EIGRP_AUTH_SHA256_TLV_SIZE); - stream_set_endp(s, backup_end); + stream_set_endp(s, EIGRP_HEADER_LEN); + stream_put(s, auth_TLV, EIGRP_AUTH_SHA256_TLV_SIZE); + stream_set_endp(s, backup_end); - eigrp_authTLV_SHA256_free(auth_TLV); - free(source_ip); + eigrp_authTLV_SHA256_free(auth_TLV); + free(source_ip); - return EIGRP_AUTH_TYPE_SHA256_LEN; + return EIGRP_AUTH_TYPE_SHA256_LEN; } -int -eigrp_check_sha256_digest (struct stream *s, - struct TLV_SHA256_Authentication_Type *authTLV, - struct eigrp_neighbor *nbr, u_char flags) +int eigrp_check_sha256_digest(struct stream *s, + struct TLV_SHA256_Authentication_Type *authTLV, + struct eigrp_neighbor *nbr, u_char flags) { - return 1; + return 1; } /* @@ -311,1109 +303,1083 @@ eigrp_check_sha256_digest (struct stream *s, * This routing dumps the contents of the IP packet either received or * built by EIGRP. */ -static void -eigrp_packet_dump (struct stream *s) +static void eigrp_packet_dump(struct stream *s) { - // not yet... - return; + // not yet... + return; } -int -eigrp_write (struct thread *thread) +int eigrp_write(struct thread *thread) { - struct eigrp *eigrp = THREAD_ARG(thread); - struct eigrp_header *eigrph; - struct eigrp_interface *ei; - struct eigrp_packet *ep; - struct sockaddr_in sa_dst; - struct ip iph; - struct msghdr msg; - struct iovec iov[2]; - u_int16_t opcode = 0; - - int ret; - int flags = 0; - struct listnode *node; + struct eigrp *eigrp = THREAD_ARG(thread); + struct eigrp_header *eigrph; + struct eigrp_interface *ei; + struct eigrp_packet *ep; + struct sockaddr_in sa_dst; + struct ip iph; + struct msghdr msg; + struct iovec iov[2]; + u_int16_t opcode = 0; + + int ret; + int flags = 0; + struct listnode *node; #ifdef WANT_EIGRP_WRITE_FRAGMENT - static u_int16_t ipid = 0; + static u_int16_t ipid = 0; #endif /* WANT_EIGRP_WRITE_FRAGMENT */ + /* $FRR indent$ */ +/* clang-format off */ #define EIGRP_WRITE_IPHL_SHIFT 2 - eigrp->t_write = NULL; + eigrp->t_write = NULL; - node = listhead(eigrp->oi_write_q); - assert(node); - ei = listgetdata(node); - assert(ei); + node = listhead(eigrp->oi_write_q); + assert(node); + ei = listgetdata(node); + assert(ei); #ifdef WANT_EIGRP_WRITE_FRAGMENT - /* seed ipid static with low order bits of time */ - if (ipid == 0) - ipid = (time(NULL) & 0xffff); + /* seed ipid static with low order bits of time */ + if (ipid == 0) + ipid = (time(NULL) & 0xffff); #endif /* WANT_EIGRP_WRITE_FRAGMENT */ - /* Get one packet from queue. */ - ep = eigrp_fifo_head(ei->obuf); - assert(ep); - assert(ep->length >= EIGRP_HEADER_LEN); + /* Get one packet from queue. */ + ep = eigrp_fifo_head(ei->obuf); + assert(ep); + assert(ep->length >= EIGRP_HEADER_LEN); - if (ep->dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS)) - eigrp_if_ipmulticast(eigrp, ei->address, ei->ifp->ifindex); + if (ep->dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS)) + eigrp_if_ipmulticast(eigrp, ei->address, ei->ifp->ifindex); - memset(&iph, 0, sizeof(struct ip)); - memset(&sa_dst, 0, sizeof(sa_dst)); + memset(&iph, 0, sizeof(struct ip)); + memset(&sa_dst, 0, sizeof(sa_dst)); - sa_dst.sin_family = AF_INET; + sa_dst.sin_family = AF_INET; #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sa_dst.sin_len = sizeof(sa_dst); + sa_dst.sin_len = sizeof(sa_dst); #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - sa_dst.sin_addr = ep->dst; - sa_dst.sin_port = htons(0); - - /* Set DONTROUTE flag if dst is unicast. */ - if (!IN_MULTICAST(htonl(ep->dst.s_addr))) - flags = MSG_DONTROUTE; - - iph.ip_hl = sizeof(struct ip) >> EIGRP_WRITE_IPHL_SHIFT; - /* it'd be very strange for header to not be 4byte-word aligned but.. */ - if (sizeof(struct ip) > (unsigned int)(iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT)) - iph.ip_hl++; /* we presume sizeof struct ip cant overflow ip_hl.. */ - - iph.ip_v = IPVERSION; - iph.ip_tos = IPTOS_PREC_INTERNETCONTROL; - iph.ip_len = (iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT) + ep->length; - -#if defined (__DragonFly__) - /* - * DragonFly's raw socket expects ip_len/ip_off in network byte order. - */ - iph.ip_len = htons(iph.ip_len); + sa_dst.sin_addr = ep->dst; + sa_dst.sin_port = htons(0); + + /* Set DONTROUTE flag if dst is unicast. */ + if (!IN_MULTICAST(htonl(ep->dst.s_addr))) + flags = MSG_DONTROUTE; + + iph.ip_hl = sizeof(struct ip) >> EIGRP_WRITE_IPHL_SHIFT; + /* it'd be very strange for header to not be 4byte-word aligned but.. */ + if (sizeof(struct ip) + > (unsigned int)(iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT)) + iph.ip_hl++; /* we presume sizeof struct ip cant overflow + ip_hl.. */ + + iph.ip_v = IPVERSION; + iph.ip_tos = IPTOS_PREC_INTERNETCONTROL; + iph.ip_len = (iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT) + ep->length; + +#if defined(__DragonFly__) + /* + * DragonFly's raw socket expects ip_len/ip_off in network byte order. + */ + iph.ip_len = htons(iph.ip_len); #endif - iph.ip_off = 0; - iph.ip_ttl = EIGRP_IP_TTL; - iph.ip_p = IPPROTO_EIGRPIGP; - iph.ip_sum = 0; - iph.ip_src.s_addr = ei->address->u.prefix4.s_addr; - iph.ip_dst.s_addr = ep->dst.s_addr; - - memset(&msg, 0, sizeof(msg)); - msg.msg_name = (caddr_t) &sa_dst; - msg.msg_namelen = sizeof(sa_dst); - msg.msg_iov = iov; - msg.msg_iovlen = 2; - - iov[0].iov_base = (char*)&iph; - iov[0].iov_len = iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT; - iov[1].iov_base = STREAM_PNT(ep->s); - iov[1].iov_len = ep->length; - - /* send final fragment (could be first) */ - sockopt_iphdrincl_swab_htosys(&iph); - ret = sendmsg(eigrp->fd, &msg, flags); - sockopt_iphdrincl_swab_systoh(&iph); - - 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].", - lookup_msg(eigrp_packet_type_str, opcode, NULL), - inet_ntoa(ep->dst), - IF_NAME(ei), ret); - } - - if (ret < 0) - zlog_warn("*** sendmsg in eigrp_write failed to %s, " - "id %d, off %d, len %d, interface %s, mtu %u: %s", - inet_ntoa(iph.ip_dst), iph.ip_id, iph.ip_off, 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) - { - ei->on_write_q = 0; - list_delete_node(eigrp->oi_write_q, node); - } - - /* If packets still remain in queue, call write thread. */ - if (!list_isempty(eigrp->oi_write_q)) { - eigrp->t_write = NULL; - thread_add_write(master, eigrp_write, eigrp, eigrp->fd, &eigrp->t_write); - } - - return 0; + iph.ip_off = 0; + iph.ip_ttl = EIGRP_IP_TTL; + iph.ip_p = IPPROTO_EIGRPIGP; + iph.ip_sum = 0; + iph.ip_src.s_addr = ei->address->u.prefix4.s_addr; + iph.ip_dst.s_addr = ep->dst.s_addr; + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = (caddr_t)&sa_dst; + msg.msg_namelen = sizeof(sa_dst); + msg.msg_iov = iov; + msg.msg_iovlen = 2; + + iov[0].iov_base = (char *)&iph; + iov[0].iov_len = iph.ip_hl << EIGRP_WRITE_IPHL_SHIFT; + iov[1].iov_base = STREAM_PNT(ep->s); + iov[1].iov_len = ep->length; + + /* send final fragment (could be first) */ + sockopt_iphdrincl_swab_htosys(&iph); + ret = sendmsg(eigrp->fd, &msg, flags); + sockopt_iphdrincl_swab_systoh(&iph); + + 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].", + lookup_msg(eigrp_packet_type_str, opcode, NULL), + inet_ntoa(ep->dst), IF_NAME(ei), ret); + } + + if (ret < 0) + zlog_warn( + "*** sendmsg in eigrp_write failed to %s, " + "id %d, off %d, len %d, interface %s, mtu %u: %s", + inet_ntoa(iph.ip_dst), iph.ip_id, iph.ip_off, + 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) { + ei->on_write_q = 0; + list_delete_node(eigrp->oi_write_q, node); + } + + /* If packets still remain in queue, call write thread. */ + if (!list_isempty(eigrp->oi_write_q)) { + eigrp->t_write = NULL; + thread_add_write(master, eigrp_write, eigrp, eigrp->fd, + &eigrp->t_write); + } + + return 0; } /* Starting point of packet process function. */ -int -eigrp_read (struct thread *thread) +int eigrp_read(struct thread *thread) { - int ret; - struct stream *ibuf; - struct eigrp *eigrp; - struct eigrp_interface *ei; - struct ip *iph; - struct eigrp_header *eigrph; - struct interface *ifp; - struct eigrp_neighbor *nbr; - - u_int16_t opcode = 0; - u_int16_t length = 0; - - /* first of all get interface pointer. */ - eigrp = THREAD_ARG(thread); - - /* prepare for next packet. */ - eigrp->t_read = NULL; - thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read); - - stream_reset(eigrp->ibuf); - if (!(ibuf = eigrp_recv_packet(eigrp->fd, &ifp, eigrp->ibuf))) - { - /* This raw packet is known to be at least as big as its IP header. */ - return -1; - } - - /* Note that there should not be alignment problems with this assignment - because this is at the beginning of the stream data buffer. */ - iph = (struct ip *)STREAM_DATA(ibuf); - - //Substract IPv4 header size from EIGRP Packet itself - if(iph->ip_v == 4) - length = (iph->ip_len) - 20U; - - - /* IP Header dump. */ - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV) && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL)) - eigrp_ip_header_dump(iph); - - /* Note that sockopt_iphdrincl_swab_systoh was called in eigrp_recv_packet. */ - if (ifp == NULL) - { - struct connected *c; - /* Handle cases where the platform does not support retrieving the ifindex, - and also platforms (such as Solaris 8) that claim to support ifindex - retrieval but do not. */ - c = if_lookup_address((void *)&iph->ip_src, AF_INET, VRF_DEFAULT); - - if (c == NULL) - return 0; - - ifp = c->ifp; - } - - /* associate packet with eigrp interface */ - ei = eigrp_if_lookup_recv_if(eigrp, iph->ip_src, ifp); - - /* eigrp_verify_header() relies on a valid "ei" and thus can be called only - after the checks below are passed. These checks in turn access the - fields of unverified "eigrph" structure for their own purposes and - must remain very accurate in doing this. - */ - if (!ei) - return 0; - - /* Self-originated packet should be discarded silently. */ - if (eigrp_if_lookup_by_local_addr(eigrp, NULL, iph->ip_src) || - (IPV4_ADDR_SAME(&iph->ip_src.s_addr, &ei->address->u.prefix4))) - { - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) - zlog_debug("eigrp_read[%s]: Dropping self-originated packet", - inet_ntoa(iph->ip_src)); - return 0; - } - - /* Advance from IP header to EIGRP header (iph->ip_hl has been verified - by eigrp_recv_packet() to be correct). */ - - stream_forward_getp(ibuf, (iph->ip_hl * 4)); - eigrph = (struct eigrp_header *) STREAM_PNT(ibuf); - - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV) && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL)) - eigrp_header_dump(eigrph); - - // if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) - stream_get_getp(ibuf))) - // return -1; - - /* Now it is safe to access all fields of EIGRP packet header. */ - /* associate packet with eigrp interface */ - ei = eigrp_if_lookup_recv_if(eigrp, iph->ip_src, ifp); - - /* eigrp_verify_header() relies on a valid "ei" and thus can be called only - after the checks below are passed. These checks in turn access the - fields of unverified "eigrph" structure for their own purposes and - must remain very accurate in doing this. - */ - if (!ei) - return 0; - - /* If incoming interface is passive one, ignore it. */ - if (ei && EIGRP_IF_PASSIVE_STATUS(ei) == EIGRP_IF_PASSIVE) - { - char buf[3][INET_ADDRSTRLEN]; - - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) - zlog_debug("ignoring packet from router %s sent to %s, " - "received on a passive interface, %s", - inet_ntop(AF_INET, &eigrph->vrid, buf[0], sizeof(buf[0])), - inet_ntop(AF_INET, &iph->ip_dst, buf[1], sizeof(buf[1])), - inet_ntop(AF_INET, &ei->address->u.prefix4, - buf[2], sizeof(buf[2]))); - - if (iph->ip_dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS)) - { - /* Try to fix multicast membership. - * Some OS:es may have problems in this area, - * make sure it is removed. - */ - EI_MEMBER_JOINED(ei, MEMBER_ALLROUTERS); - eigrp_if_set_multicast(ei); - } - return 0; - } - - /* else it must be a local eigrp interface, check it was received on - * correct link - */ - else if (ei->ifp != ifp) - { - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) - zlog_warn("Packet from [%s] received on wrong link %s", - inet_ntoa(iph->ip_src), ifp->name); - return 0; - } - - /* Verify more EIGRP header fields. */ - ret = eigrp_verify_header(ibuf, ei, iph, eigrph); - if (ret < 0) - { - if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) - zlog_debug("eigrp_read[%s]: Header check failed, dropping.", - inet_ntoa(iph->ip_src)); - return ret; - } - - /* calcualte the eigrp packet length, and move the pounter to the - 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)); - - /* 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) - { - nbr = eigrp_nbr_get(ei, eigrph, iph); - - /* 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_tail(nbr->multicast_queue); - if (ep) - { - if (ntohl(eigrph->ack) == ep->sequence_number) - { - ep = eigrp_fifo_pop_tail(nbr->multicast_queue); - eigrp_packet_free(ep); - if (nbr->multicast_queue->count > 0) - { - eigrp_send_packet_reliably(nbr); - } - } - } - } - - - switch (opcode) - { - case EIGRP_OPC_HELLO: - eigrp_hello_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_PROBE: - // eigrp_probe_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_QUERY: - eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_REPLY: - eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_REQUEST: - // eigrp_request_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_SIAQUERY: - eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_SIAREPLY: - eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - case EIGRP_OPC_UPDATE: - eigrp_update_receive(eigrp, iph, eigrph, ibuf, ei, length); - break; - default: - zlog_warn("interface %s: EIGRP packet header type %d unsupported", - IF_NAME(ei), opcode); - break; - } - - return 0; + int ret; + struct stream *ibuf; + struct eigrp *eigrp; + struct eigrp_interface *ei; + struct ip *iph; + struct eigrp_header *eigrph; + struct interface *ifp; + struct eigrp_neighbor *nbr; + + u_int16_t opcode = 0; + u_int16_t length = 0; + + /* first of all get interface pointer. */ + eigrp = THREAD_ARG(thread); + + /* prepare for next packet. */ + eigrp->t_read = NULL; + thread_add_read(master, eigrp_read, eigrp, eigrp->fd, &eigrp->t_read); + + stream_reset(eigrp->ibuf); + if (!(ibuf = eigrp_recv_packet(eigrp->fd, &ifp, eigrp->ibuf))) { + /* This raw packet is known to be at least as big as its IP + * header. */ + return -1; + } + + /* Note that there should not be alignment problems with this assignment + because this is at the beginning of the stream data buffer. */ + iph = (struct ip *)STREAM_DATA(ibuf); + + // Substract IPv4 header size from EIGRP Packet itself + if (iph->ip_v == 4) + length = (iph->ip_len) - 20U; + + + /* IP Header dump. */ + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV) + && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL)) + eigrp_ip_header_dump(iph); + + /* Note that sockopt_iphdrincl_swab_systoh was called in + * eigrp_recv_packet. */ + if (ifp == NULL) { + struct connected *c; + /* Handle cases where the platform does not support retrieving + the ifindex, + and also platforms (such as Solaris 8) that claim to support + ifindex + retrieval but do not. */ + c = if_lookup_address((void *)&iph->ip_src, AF_INET, + VRF_DEFAULT); + + if (c == NULL) + return 0; + + ifp = c->ifp; + } + + /* associate packet with eigrp interface */ + ei = eigrp_if_lookup_recv_if(eigrp, iph->ip_src, ifp); + + /* eigrp_verify_header() relies on a valid "ei" and thus can be called + only + after the checks below are passed. These checks in turn access the + fields of unverified "eigrph" structure for their own purposes and + must remain very accurate in doing this. + */ + if (!ei) + return 0; + + /* Self-originated packet should be discarded silently. */ + if (eigrp_if_lookup_by_local_addr(eigrp, NULL, iph->ip_src) + || (IPV4_ADDR_SAME(&iph->ip_src.s_addr, &ei->address->u.prefix4))) { + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) + zlog_debug( + "eigrp_read[%s]: Dropping self-originated packet", + inet_ntoa(iph->ip_src)); + return 0; + } + + /* Advance from IP header to EIGRP header (iph->ip_hl has been verified + by eigrp_recv_packet() to be correct). */ + + stream_forward_getp(ibuf, (iph->ip_hl * 4)); + eigrph = (struct eigrp_header *)STREAM_PNT(ibuf); + + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV) + && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL)) + eigrp_header_dump(eigrph); + + // if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) - + // stream_get_getp(ibuf))) + // return -1; + + /* Now it is safe to access all fields of EIGRP packet header. */ + /* associate packet with eigrp interface */ + ei = eigrp_if_lookup_recv_if(eigrp, iph->ip_src, ifp); + + /* eigrp_verify_header() relies on a valid "ei" and thus can be called + only + after the checks below are passed. These checks in turn access the + fields of unverified "eigrph" structure for their own purposes and + must remain very accurate in doing this. + */ + if (!ei) + return 0; + + /* If incoming interface is passive one, ignore it. */ + if (ei && EIGRP_IF_PASSIVE_STATUS(ei) == EIGRP_IF_PASSIVE) { + char buf[3][INET_ADDRSTRLEN]; + + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) + zlog_debug( + "ignoring packet from router %s sent to %s, " + "received on a passive interface, %s", + inet_ntop(AF_INET, &eigrph->vrid, buf[0], + sizeof(buf[0])), + inet_ntop(AF_INET, &iph->ip_dst, buf[1], + sizeof(buf[1])), + inet_ntop(AF_INET, &ei->address->u.prefix4, + buf[2], sizeof(buf[2]))); + + if (iph->ip_dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS)) { + /* Try to fix multicast membership. + * Some OS:es may have problems in this area, + * make sure it is removed. + */ + EI_MEMBER_JOINED(ei, MEMBER_ALLROUTERS); + eigrp_if_set_multicast(ei); + } + return 0; + } + + /* else it must be a local eigrp interface, check it was received on + * correct link + */ + else if (ei->ifp != ifp) { + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) + zlog_warn("Packet from [%s] received on wrong link %s", + inet_ntoa(iph->ip_src), ifp->name); + return 0; + } + + /* Verify more EIGRP header fields. */ + ret = eigrp_verify_header(ibuf, ei, iph, eigrph); + if (ret < 0) { + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) + zlog_debug( + "eigrp_read[%s]: Header check failed, dropping.", + inet_ntoa(iph->ip_src)); + return ret; + } + + /* calcualte the eigrp packet length, and move the pounter to the + 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)); + + /* 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) { + nbr = eigrp_nbr_get(ei, eigrph, iph); + + /* 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_tail(nbr->multicast_queue); + if (ep) { + if (ntohl(eigrph->ack) == ep->sequence_number) { + ep = eigrp_fifo_pop_tail(nbr->multicast_queue); + eigrp_packet_free(ep); + if (nbr->multicast_queue->count > 0) { + eigrp_send_packet_reliably(nbr); + } + } + } + } + + + switch (opcode) { + case EIGRP_OPC_HELLO: + eigrp_hello_receive(eigrp, iph, eigrph, ibuf, ei, length); + break; + case EIGRP_OPC_PROBE: + // eigrp_probe_receive(eigrp, iph, eigrph, ibuf, ei, + // length); + break; + case EIGRP_OPC_QUERY: + eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length); + break; + case EIGRP_OPC_REPLY: + eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length); + break; + case EIGRP_OPC_REQUEST: + // eigrp_request_receive(eigrp, iph, eigrph, ibuf, ei, + // length); + break; + case EIGRP_OPC_SIAQUERY: + eigrp_query_receive(eigrp, iph, eigrph, ibuf, ei, length); + break; + case EIGRP_OPC_SIAREPLY: + eigrp_reply_receive(eigrp, iph, eigrph, ibuf, ei, length); + break; + case EIGRP_OPC_UPDATE: + eigrp_update_receive(eigrp, iph, eigrph, ibuf, ei, length); + break; + default: + zlog_warn( + "interface %s: EIGRP packet header type %d unsupported", + IF_NAME(ei), opcode); + break; + } + + return 0; } -static struct stream * -eigrp_recv_packet (int fd, struct interface **ifp, struct stream *ibuf) +static struct stream *eigrp_recv_packet(int fd, struct interface **ifp, + struct stream *ibuf) { - int ret; - struct ip *iph; - u_int16_t ip_len; - unsigned int ifindex = 0; - struct iovec iov; - /* Header and data both require alignment. */ - char buff[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())]; - struct msghdr msgh; - - memset(&msgh, 0, sizeof(struct msghdr)); - msgh.msg_iov = &iov; - msgh.msg_iovlen = 1; - msgh.msg_control = (caddr_t) buff; - msgh.msg_controllen = sizeof(buff); - - ret = stream_recvmsg(ibuf, fd, &msgh, 0, (EIGRP_PACKET_MAX_LEN + 1)); - if (ret < 0) - { - zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno)); - return NULL; - } - if ((unsigned int) ret < sizeof(iph)) /* ret must be > 0 now */ - { - zlog_warn("eigrp_recv_packet: discarding runt packet of length %d " - "(ip header size is %u)", ret, (u_int) sizeof(iph)); - return NULL; - } - - /* Note that there should not be alignment problems with this assignment - because this is at the beginning of the stream data buffer. */ - iph = (struct ip *) STREAM_DATA(ibuf); - sockopt_iphdrincl_swab_systoh(iph); - - ip_len = iph->ip_len; - -#if !defined (GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000) - /* - * Kernel network code touches incoming IP header parameters, - * before protocol specific processing. - * - * 1) Convert byteorder to host representation. - * --> ip_len, ip_id, ip_off - * - * 2) Adjust ip_len to strip IP header size! - * --> If user process receives entire IP packet via RAW - * socket, it must consider adding IP header size to - * the "ip_len" field of "ip" structure. - * - * For more details, see <netinet/ip_input.c>. - */ - ip_len = ip_len + (iph->ip_hl << 2); + int ret; + struct ip *iph; + u_int16_t ip_len; + unsigned int ifindex = 0; + struct iovec iov; + /* Header and data both require alignment. */ + char buff[CMSG_SPACE(SOPT_SIZE_CMSG_IFINDEX_IPV4())]; + struct msghdr msgh; + + memset(&msgh, 0, sizeof(struct msghdr)); + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + msgh.msg_control = (caddr_t)buff; + msgh.msg_controllen = sizeof(buff); + + ret = stream_recvmsg(ibuf, fd, &msgh, 0, (EIGRP_PACKET_MAX_LEN + 1)); + if (ret < 0) { + zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno)); + return NULL; + } + if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */ + { + zlog_warn( + "eigrp_recv_packet: discarding runt packet of length %d " + "(ip header size is %u)", + ret, (u_int)sizeof(iph)); + return NULL; + } + + /* Note that there should not be alignment problems with this assignment + because this is at the beginning of the stream data buffer. */ + iph = (struct ip *)STREAM_DATA(ibuf); + sockopt_iphdrincl_swab_systoh(iph); + + ip_len = iph->ip_len; + +#if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000) + /* + * Kernel network code touches incoming IP header parameters, + * before protocol specific processing. + * + * 1) Convert byteorder to host representation. + * --> ip_len, ip_id, ip_off + * + * 2) Adjust ip_len to strip IP header size! + * --> If user process receives entire IP packet via RAW + * socket, it must consider adding IP header size to + * the "ip_len" field of "ip" structure. + * + * For more details, see <netinet/ip_input.c>. + */ + ip_len = ip_len + (iph->ip_hl << 2); #endif -#if defined (__DragonFly__) - /* - * in DragonFly's raw socket, ip_len/ip_off are read - * in network byte order. - * As OpenBSD < 200311 adjust ip_len to strip IP header size! - */ - ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2); +#if defined(__DragonFly__) + /* + * in DragonFly's raw socket, ip_len/ip_off are read + * in network byte order. + * As OpenBSD < 200311 adjust ip_len to strip IP header size! + */ + ip_len = ntohs(iph->ip_len) + (iph->ip_hl << 2); #endif - ifindex = getsockopt_ifindex(AF_INET, &msgh); + ifindex = getsockopt_ifindex(AF_INET, &msgh); - *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); - if (ret != ip_len) - { - zlog_warn("eigrp_recv_packet read length mismatch: ip_len is %d, " - "but recvmsg returned %d", ip_len, ret); - return NULL; - } + if (ret != ip_len) { + zlog_warn( + "eigrp_recv_packet read length mismatch: ip_len is %d, " + "but recvmsg returned %d", + ip_len, ret); + return NULL; + } - return ibuf; + return ibuf; } -struct eigrp_fifo * -eigrp_fifo_new (void) +struct eigrp_fifo *eigrp_fifo_new(void) { - struct eigrp_fifo *new; + struct eigrp_fifo *new; - new = XCALLOC(MTYPE_EIGRP_FIFO, sizeof(struct eigrp_fifo)); - return new; + new = XCALLOC(MTYPE_EIGRP_FIFO, sizeof(struct eigrp_fifo)); + return new; } /* Free eigrp packet fifo. */ -void -eigrp_fifo_free (struct eigrp_fifo *fifo) +void eigrp_fifo_free(struct eigrp_fifo *fifo) { - struct eigrp_packet *ep; - struct eigrp_packet *next; - - for (ep = fifo->head; ep; ep = next) - { - next = ep->next; - eigrp_packet_free(ep); - } - fifo->head = fifo->tail = NULL; - fifo->count = 0; - - XFREE(MTYPE_EIGRP_FIFO, fifo); + struct eigrp_packet *ep; + struct eigrp_packet *next; + + for (ep = fifo->head; ep; ep = next) { + next = ep->next; + eigrp_packet_free(ep); + } + fifo->head = fifo->tail = NULL; + fifo->count = 0; + + XFREE(MTYPE_EIGRP_FIFO, fifo); } /* Free eigrp fifo entries without destroying fifo itself*/ -void -eigrp_fifo_reset (struct eigrp_fifo *fifo) +void eigrp_fifo_reset(struct eigrp_fifo *fifo) { - struct eigrp_packet *ep; - struct eigrp_packet *next; - - for (ep = fifo->head; ep; ep = next) - { - next = ep->next; - eigrp_packet_free(ep); - } - fifo->head = fifo->tail = NULL; - fifo->count = 0; + struct eigrp_packet *ep; + struct eigrp_packet *next; + + for (ep = fifo->head; ep; ep = next) { + next = ep->next; + eigrp_packet_free(ep); + } + fifo->head = fifo->tail = NULL; + fifo->count = 0; } -struct eigrp_packet * -eigrp_packet_new (size_t size) +struct eigrp_packet *eigrp_packet_new(size_t size) { - struct eigrp_packet *new; + struct eigrp_packet *new; - new = XCALLOC(MTYPE_EIGRP_PACKET, sizeof(struct eigrp_packet)); - new->s = stream_new(size); - new->retrans_counter = 0; + new = XCALLOC(MTYPE_EIGRP_PACKET, sizeof(struct eigrp_packet)); + new->s = stream_new(size); + new->retrans_counter = 0; - return new; + return new; } -void -eigrp_send_packet_reliably (struct eigrp_neighbor *nbr) +void eigrp_send_packet_reliably(struct eigrp_neighbor *nbr) { - struct eigrp_packet *ep; - - ep = eigrp_fifo_tail(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); - - /*Start retransmission timer*/ - thread_add_timer(master, eigrp_unack_packet_retrans, nbr, - EIGRP_PACKET_RETRANS_TIME, &ep->t_retrans_timer); - - /*Increment sequence number counter*/ - nbr->ei->eigrp->sequence_number++; - - /* Hook thread to write packet. */ - if (nbr->ei->on_write_q == 0) - { - listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); - nbr->ei->on_write_q = 1; - } - thread_add_write(master, eigrp_write, nbr->ei->eigrp, nbr->ei->eigrp->fd, - &nbr->ei->eigrp->t_write); - } + struct eigrp_packet *ep; + + ep = eigrp_fifo_tail(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); + + /*Start retransmission timer*/ + thread_add_timer(master, eigrp_unack_packet_retrans, nbr, + EIGRP_PACKET_RETRANS_TIME, + &ep->t_retrans_timer); + + /*Increment sequence number counter*/ + nbr->ei->eigrp->sequence_number++; + + /* Hook thread to write packet. */ + if (nbr->ei->on_write_q == 0) { + listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); + nbr->ei->on_write_q = 1; + } + thread_add_write(master, eigrp_write, nbr->ei->eigrp, + nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write); + } } /* Calculate EIGRP checksum */ -void -eigrp_packet_checksum (struct eigrp_interface *ei, struct stream *s, - u_int16_t length) +void eigrp_packet_checksum(struct eigrp_interface *ei, struct stream *s, + u_int16_t length) { - struct eigrp_header *eigrph; + struct eigrp_header *eigrph; - eigrph = (struct eigrp_header *) STREAM_DATA(s); + eigrph = (struct eigrp_header *)STREAM_DATA(s); - /* Calculate checksum. */ - eigrph->checksum = in_cksum(eigrph, length); + /* Calculate checksum. */ + eigrph->checksum = in_cksum(eigrph, length); } /* Make EIGRP header. */ -void -eigrp_packet_header_init (int type, struct eigrp_interface *ei, struct stream *s, - u_int32_t flags, u_int32_t sequence, u_int32_t ack) +void eigrp_packet_header_init(int type, struct eigrp_interface *ei, + struct stream *s, u_int32_t flags, + u_int32_t sequence, u_int32_t ack) { - struct eigrp_header *eigrph; + struct eigrp_header *eigrph; - eigrph = (struct eigrp_header *) STREAM_DATA(s); + eigrph = (struct eigrp_header *)STREAM_DATA(s); - eigrph->version = (u_char) EIGRP_HEADER_VERSION; - eigrph->opcode = (u_char) type; - eigrph->checksum = 0; + eigrph->version = (u_char)EIGRP_HEADER_VERSION; + eigrph->opcode = (u_char)type; + eigrph->checksum = 0; - eigrph->vrid = htons(ei->eigrp->vrid); - eigrph->ASNumber = htons(ei->eigrp->AS); - eigrph->ack = htonl(ack); - eigrph->sequence = htonl(sequence); - // if(flags == EIGRP_INIT_FLAG) - // eigrph->sequence = htonl(3); - eigrph->flags = htonl(flags); + eigrph->vrid = htons(ei->eigrp->vrid); + eigrph->ASNumber = htons(ei->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)) - zlog_debug("Packet Header Init Seq [%u] Ack [%u]", - htonl(eigrph->sequence), htonl(eigrph->ack)); + if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV)) + zlog_debug("Packet Header Init Seq [%u] Ack [%u]", + htonl(eigrph->sequence), htonl(eigrph->ack)); - stream_forward_endp(s, EIGRP_HEADER_LEN); + stream_forward_endp(s, EIGRP_HEADER_LEN); } /* Add new packet to head of fifo. */ -void -eigrp_fifo_push_head (struct eigrp_fifo *fifo, struct eigrp_packet *ep) +void eigrp_fifo_push_head(struct eigrp_fifo *fifo, struct eigrp_packet *ep) { - ep->next = fifo->head; - ep->previous = NULL; + ep->next = fifo->head; + ep->previous = NULL; - if (fifo->tail == NULL) - fifo->tail = ep; + if (fifo->tail == NULL) + fifo->tail = ep; - if (fifo->count != 0) - fifo->head->previous = ep; + if (fifo->count != 0) + fifo->head->previous = ep; - fifo->head = ep; + fifo->head = ep; - fifo->count++; + fifo->count++; } /* Return first fifo entry. */ -struct eigrp_packet * -eigrp_fifo_head (struct eigrp_fifo *fifo) +struct eigrp_packet *eigrp_fifo_head(struct eigrp_fifo *fifo) { - return fifo->head; + return fifo->head; } /* Return last fifo entry. */ -struct eigrp_packet * -eigrp_fifo_tail (struct eigrp_fifo *fifo) +struct eigrp_packet *eigrp_fifo_tail(struct eigrp_fifo *fifo) { - return fifo->tail; + return fifo->tail; } -void -eigrp_packet_delete (struct eigrp_interface *ei) +void eigrp_packet_delete(struct eigrp_interface *ei) { - struct eigrp_packet *ep; + struct eigrp_packet *ep; - ep = eigrp_fifo_pop (ei->obuf); + ep = eigrp_fifo_pop(ei->obuf); - if (ep) - eigrp_packet_free(ep); + if (ep) + eigrp_packet_free(ep); } /* Delete first packet from fifo. */ -struct eigrp_packet * -eigrp_fifo_pop (struct eigrp_fifo *fifo) +struct eigrp_packet *eigrp_fifo_pop(struct eigrp_fifo *fifo) { - struct eigrp_packet *ep; + struct eigrp_packet *ep; - ep = fifo->head; + ep = fifo->head; - if (ep) - { - fifo->head = ep->next; + if (ep) { + fifo->head = ep->next; - if (fifo->head == NULL) - fifo->tail = NULL; - else - fifo->head->previous = NULL; + if (fifo->head == NULL) + fifo->tail = NULL; + else + fifo->head->previous = NULL; - fifo->count--; - } + fifo->count--; + } - return ep; + return ep; } -void -eigrp_packet_free (struct eigrp_packet *ep) +void eigrp_packet_free(struct eigrp_packet *ep) { - if (ep->s) - stream_free(ep->s); + if (ep->s) + stream_free(ep->s); - THREAD_OFF(ep->t_retrans_timer); + THREAD_OFF(ep->t_retrans_timer); - XFREE(MTYPE_EIGRP_PACKET, ep); + XFREE(MTYPE_EIGRP_PACKET, ep); - ep = NULL; + ep = NULL; } /* EIGRP Header verification. */ -static int -eigrp_verify_header (struct stream *ibuf, struct eigrp_interface *ei, - struct ip *iph, struct eigrp_header *eigrph) +static int eigrp_verify_header(struct stream *ibuf, struct eigrp_interface *ei, + struct ip *iph, struct eigrp_header *eigrph) { - /* Check network mask, Silently discarded. */ - if (!eigrp_check_network_mask(ei, iph->ip_src)) - { - zlog_warn("interface %s: eigrp_read network address is not same [%s]", - IF_NAME(ei), inet_ntoa(iph->ip_src)); - return -1; - } - // - // /* Check authentication. The function handles logging actions, where required. */ - // if (! eigrp_check_auth(ei, eigrph)) - // return -1; - - return 0; + /* Check network mask, Silently discarded. */ + if (!eigrp_check_network_mask(ei, iph->ip_src)) { + zlog_warn( + "interface %s: eigrp_read network address is not same [%s]", + IF_NAME(ei), inet_ntoa(iph->ip_src)); + return -1; + } + // + // /* Check authentication. The function handles logging actions, where + // required. */ + // if (! eigrp_check_auth(ei, eigrph)) + // return -1; + + return 0; } /* Unbound socket will accept any Raw IP packets if proto is matched. To prevent it, compare src IP address and i/f address with masking i/f network mask. */ -static int -eigrp_check_network_mask (struct eigrp_interface *ei, struct in_addr ip_src) +static int eigrp_check_network_mask(struct eigrp_interface *ei, + struct in_addr ip_src) { - struct in_addr mask, me, him; + struct in_addr mask, me, him; - if (ei->type == EIGRP_IFTYPE_POINTOPOINT) - return 1; + if (ei->type == EIGRP_IFTYPE_POINTOPOINT) + return 1; - masklen2ip(ei->address->prefixlen, &mask); + masklen2ip(ei->address->prefixlen, &mask); - me.s_addr = ei->address->u.prefix4.s_addr & mask.s_addr; - him.s_addr = ip_src.s_addr & mask.s_addr; + me.s_addr = ei->address->u.prefix4.s_addr & mask.s_addr; + him.s_addr = ip_src.s_addr & mask.s_addr; - if (IPV4_ADDR_SAME(&me, &him)) - return 1; + if (IPV4_ADDR_SAME(&me, &him)) + return 1; - return 0; + return 0; } -int -eigrp_unack_packet_retrans (struct thread *thread) +int eigrp_unack_packet_retrans(struct thread *thread) { - struct eigrp_neighbor *nbr; - nbr = (struct eigrp_neighbor *) THREAD_ARG(thread); - - struct eigrp_packet *ep; - ep = eigrp_fifo_tail(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); - - ep->retrans_counter++; - if(ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX) - return eigrp_retrans_count_exceeded(ep, nbr); - - /*Start retransmission timer*/ - ep->t_retrans_timer = NULL; - thread_add_timer(master, eigrp_unack_packet_retrans, nbr, EIGRP_PACKET_RETRANS_TIME, - &ep->t_retrans_timer); - - /* Hook thread to write packet. */ - if (nbr->ei->on_write_q == 0) - { - listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); - nbr->ei->on_write_q = 1; - } - thread_add_write(master, eigrp_write, nbr->ei->eigrp, nbr->ei->eigrp->fd, - &nbr->ei->eigrp->t_write); - } - - return 0; + struct eigrp_neighbor *nbr; + nbr = (struct eigrp_neighbor *)THREAD_ARG(thread); + + struct eigrp_packet *ep; + ep = eigrp_fifo_tail(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); + + ep->retrans_counter++; + if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX) + return eigrp_retrans_count_exceeded(ep, nbr); + + /*Start retransmission timer*/ + ep->t_retrans_timer = NULL; + thread_add_timer(master, eigrp_unack_packet_retrans, nbr, + EIGRP_PACKET_RETRANS_TIME, + &ep->t_retrans_timer); + + /* Hook thread to write packet. */ + if (nbr->ei->on_write_q == 0) { + listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); + nbr->ei->on_write_q = 1; + } + thread_add_write(master, eigrp_write, nbr->ei->eigrp, + nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write); + } + + return 0; } -int -eigrp_unack_multicast_packet_retrans (struct thread *thread) +int eigrp_unack_multicast_packet_retrans(struct thread *thread) { - struct eigrp_neighbor *nbr; - nbr = (struct eigrp_neighbor *) THREAD_ARG(thread); - - struct eigrp_packet *ep; - ep = eigrp_fifo_tail(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); - - ep->retrans_counter++; - if(ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX) - return eigrp_retrans_count_exceeded(ep, nbr); - - /*Start retransmission timer*/ - ep->t_retrans_timer = NULL; - thread_add_timer(master, eigrp_unack_multicast_packet_retrans, nbr, EIGRP_PACKET_RETRANS_TIME, - &ep->t_retrans_timer); - - /* Hook thread to write packet. */ - if (nbr->ei->on_write_q == 0) - { - listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); - nbr->ei->on_write_q = 1; - } - thread_add_write(master, eigrp_write, nbr->ei->eigrp, nbr->ei->eigrp->fd, - &nbr->ei->eigrp->t_write); - } - - return 0; + struct eigrp_neighbor *nbr; + nbr = (struct eigrp_neighbor *)THREAD_ARG(thread); + + struct eigrp_packet *ep; + ep = eigrp_fifo_tail(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); + + ep->retrans_counter++; + if (ep->retrans_counter == EIGRP_PACKET_RETRANS_MAX) + return eigrp_retrans_count_exceeded(ep, nbr); + + /*Start retransmission timer*/ + ep->t_retrans_timer = NULL; + thread_add_timer(master, eigrp_unack_multicast_packet_retrans, + nbr, EIGRP_PACKET_RETRANS_TIME, + &ep->t_retrans_timer); + + /* Hook thread to write packet. */ + if (nbr->ei->on_write_q == 0) { + listnode_add(nbr->ei->eigrp->oi_write_q, nbr->ei); + nbr->ei->on_write_q = 1; + } + thread_add_write(master, eigrp_write, nbr->ei->eigrp, + nbr->ei->eigrp->fd, &nbr->ei->eigrp->t_write); + } + + return 0; } /* Get packet from tail of fifo. */ -struct eigrp_packet * -eigrp_fifo_pop_tail (struct eigrp_fifo *fifo) +struct eigrp_packet *eigrp_fifo_pop_tail(struct eigrp_fifo *fifo) { - struct eigrp_packet *ep; + struct eigrp_packet *ep; - ep = fifo->tail; + ep = fifo->tail; - if (ep) - { - fifo->tail = ep->previous; + if (ep) { + fifo->tail = ep->previous; - if (fifo->tail == NULL) - fifo->head = NULL; - else - fifo->tail->next = NULL; + if (fifo->tail == NULL) + fifo->head = NULL; + else + fifo->tail->next = NULL; - fifo->count--; - } + fifo->count--; + } - return ep; + return ep; } -struct eigrp_packet * -eigrp_packet_duplicate (struct eigrp_packet *old, struct eigrp_neighbor *nbr) +struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old, + struct eigrp_neighbor *nbr) { - struct eigrp_packet *new; + struct eigrp_packet *new; - new = eigrp_packet_new(nbr->ei->ifp->mtu); - new->length = old->length; - new->retrans_counter = old->retrans_counter; - new->dst = old->dst; - new->sequence_number = old->sequence_number; - stream_copy(new->s, old->s); + new = eigrp_packet_new(nbr->ei->ifp->mtu); + new->length = old->length; + new->retrans_counter = old->retrans_counter; + new->dst = old->dst; + new->sequence_number = old->sequence_number; + stream_copy(new->s, old->s); - return new; + return new; } -struct TLV_IPv4_Internal_type * -eigrp_read_ipv4_tlv (struct stream *s) +struct TLV_IPv4_Internal_type *eigrp_read_ipv4_tlv(struct stream *s) { - struct TLV_IPv4_Internal_type *tlv; - - tlv = eigrp_IPv4_InternalTLV_new (); - - tlv->type = stream_getw(s); - tlv->length = stream_getw(s); - tlv->forward.s_addr = stream_getl(s); - tlv->metric.delay = stream_getl(s); - tlv->metric.bandwith = stream_getl(s); - tlv->metric.mtu[0] = stream_getc(s); - tlv->metric.mtu[1] = stream_getc(s); - tlv->metric.mtu[2] = stream_getc(s); - tlv->metric.hop_count = stream_getc(s); - tlv->metric.reliability = stream_getc(s); - tlv->metric.load = stream_getc(s); - tlv->metric.tag = stream_getc(s); - tlv->metric.flags = stream_getc(s); - - tlv->prefix_length = stream_getc(s); - - if (tlv->prefix_length <= 8) - { - tlv->destination_part[0] = stream_getc(s); - tlv->destination.s_addr = (tlv->destination_part[0]); - } - else if (tlv->prefix_length > 8 && tlv->prefix_length <= 16) - { - tlv->destination_part[0] = stream_getc(s); - tlv->destination_part[1] = stream_getc(s); - tlv->destination.s_addr = ((tlv->destination_part[1] << 8) - + tlv->destination_part[0]); - } - else if (tlv->prefix_length > 16 && tlv->prefix_length <= 24) - { - tlv->destination_part[0] = stream_getc(s); - tlv->destination_part[1] = stream_getc(s); - tlv->destination_part[2] = stream_getc(s); - tlv->destination.s_addr = ((tlv->destination_part[2] << 16) + - (tlv->destination_part[1] << 8) + - tlv->destination_part[0]); - } - else if (tlv->prefix_length > 24 && tlv->prefix_length <= 32) - { - tlv->destination_part[0] = stream_getc(s); - tlv->destination_part[1] = stream_getc(s); - tlv->destination_part[2] = stream_getc(s); - tlv->destination_part[3] = stream_getc(s); - tlv->destination.s_addr = ((tlv->destination_part[3] << 24) + - (tlv->destination_part[2] << 16) + - (tlv->destination_part[1] << 8) + - tlv->destination_part[0]); - } - return tlv; + struct TLV_IPv4_Internal_type *tlv; + + tlv = eigrp_IPv4_InternalTLV_new(); + + tlv->type = stream_getw(s); + tlv->length = stream_getw(s); + tlv->forward.s_addr = stream_getl(s); + tlv->metric.delay = stream_getl(s); + tlv->metric.bandwith = stream_getl(s); + tlv->metric.mtu[0] = stream_getc(s); + tlv->metric.mtu[1] = stream_getc(s); + tlv->metric.mtu[2] = stream_getc(s); + tlv->metric.hop_count = stream_getc(s); + tlv->metric.reliability = stream_getc(s); + tlv->metric.load = stream_getc(s); + tlv->metric.tag = stream_getc(s); + tlv->metric.flags = stream_getc(s); + + tlv->prefix_length = stream_getc(s); + + if (tlv->prefix_length <= 8) { + tlv->destination_part[0] = stream_getc(s); + tlv->destination.s_addr = (tlv->destination_part[0]); + } else if (tlv->prefix_length > 8 && tlv->prefix_length <= 16) { + tlv->destination_part[0] = stream_getc(s); + tlv->destination_part[1] = stream_getc(s); + tlv->destination.s_addr = ((tlv->destination_part[1] << 8) + + tlv->destination_part[0]); + } else if (tlv->prefix_length > 16 && tlv->prefix_length <= 24) { + tlv->destination_part[0] = stream_getc(s); + tlv->destination_part[1] = stream_getc(s); + tlv->destination_part[2] = stream_getc(s); + tlv->destination.s_addr = ((tlv->destination_part[2] << 16) + + (tlv->destination_part[1] << 8) + + tlv->destination_part[0]); + } else if (tlv->prefix_length > 24 && tlv->prefix_length <= 32) { + tlv->destination_part[0] = stream_getc(s); + tlv->destination_part[1] = stream_getc(s); + tlv->destination_part[2] = stream_getc(s); + tlv->destination_part[3] = stream_getc(s); + tlv->destination.s_addr = ((tlv->destination_part[3] << 24) + + (tlv->destination_part[2] << 16) + + (tlv->destination_part[1] << 8) + + tlv->destination_part[0]); + } + return tlv; } -u_int16_t -eigrp_add_internalTLV_to_stream (struct stream *s, - struct eigrp_prefix_entry *pe) +u_int16_t eigrp_add_internalTLV_to_stream(struct stream *s, + struct eigrp_prefix_entry *pe) { - u_int16_t length; - - stream_putw(s, EIGRP_TLV_IPv4_INT); - if (pe->destination_ipv4->prefixlen <= 8) - { - stream_putw(s, 0x001A); - length = 0x001A; - } - if ((pe->destination_ipv4->prefixlen > 8) - && (pe->destination_ipv4->prefixlen <= 16)) - { - stream_putw(s, 0x001B); - length = 0x001B; - } - if ((pe->destination_ipv4->prefixlen > 16) - && (pe->destination_ipv4->prefixlen <= 24)) - { - stream_putw(s, 0x001C); - length = 0x001C; - } - if (pe->destination_ipv4->prefixlen > 24) - { - stream_putw(s, 0x001D); - length = 0x001D; - } - - stream_putl(s, 0x00000000); - - /*Metric*/ - stream_putl(s, pe->reported_metric.delay); - stream_putl(s, pe->reported_metric.bandwith); - stream_putc(s, pe->reported_metric.mtu[2]); - stream_putc(s, pe->reported_metric.mtu[1]); - stream_putc(s, pe->reported_metric.mtu[0]); - stream_putc(s, pe->reported_metric.hop_count); - stream_putc(s, pe->reported_metric.reliability); - stream_putc(s, pe->reported_metric.load); - stream_putc(s, pe->reported_metric.tag); - stream_putc(s, pe->reported_metric.flags); - - stream_putc(s, pe->destination_ipv4->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_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); - stream_putc(s, (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); - 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); - } - - return length; + u_int16_t length; + + stream_putw(s, EIGRP_TLV_IPv4_INT); + if (pe->destination_ipv4->prefixlen <= 8) { + stream_putw(s, 0x001A); + length = 0x001A; + } + if ((pe->destination_ipv4->prefixlen > 8) + && (pe->destination_ipv4->prefixlen <= 16)) { + stream_putw(s, 0x001B); + length = 0x001B; + } + if ((pe->destination_ipv4->prefixlen > 16) + && (pe->destination_ipv4->prefixlen <= 24)) { + stream_putw(s, 0x001C); + length = 0x001C; + } + if (pe->destination_ipv4->prefixlen > 24) { + stream_putw(s, 0x001D); + length = 0x001D; + } + + stream_putl(s, 0x00000000); + + /*Metric*/ + stream_putl(s, pe->reported_metric.delay); + stream_putl(s, pe->reported_metric.bandwith); + stream_putc(s, pe->reported_metric.mtu[2]); + stream_putc(s, pe->reported_metric.mtu[1]); + stream_putc(s, pe->reported_metric.mtu[0]); + stream_putc(s, pe->reported_metric.hop_count); + stream_putc(s, pe->reported_metric.reliability); + stream_putc(s, pe->reported_metric.load); + stream_putc(s, pe->reported_metric.tag); + stream_putc(s, pe->reported_metric.flags); + + stream_putc(s, pe->destination_ipv4->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_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); + stream_putc(s, + (pe->destination_ipv4->prefix.s_addr >> 8) & 0xFF); + 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); + } + + return length; } -u_int16_t -eigrp_add_authTLV_MD5_to_stream (struct stream *s, - struct eigrp_interface *ei) +u_int16_t eigrp_add_authTLV_MD5_to_stream(struct stream *s, + struct eigrp_interface *ei) { - struct key *key; - struct keychain *keychain; - struct TLV_MD5_Authentication_Type *authTLV; - - authTLV = eigrp_authTLV_MD5_new(); - - authTLV->type = htons(EIGRP_TLV_AUTH); - authTLV->length = htons(EIGRP_AUTH_MD5_TLV_SIZE); - authTLV->auth_type = htons(EIGRP_AUTH_TYPE_MD5); - authTLV->auth_length = htons(EIGRP_AUTH_TYPE_MD5_LEN); - authTLV->key_sequence = 0; - memset(authTLV->Nullpad,0,sizeof(authTLV->Nullpad)); - - keychain = keychain_lookup(IF_DEF_PARAMS (ei->ifp)->auth_keychain); - if(keychain) - key = key_lookup_for_send(keychain); - else - { - free(IF_DEF_PARAMS (ei->ifp)->auth_keychain); - IF_DEF_PARAMS (ei->ifp)->auth_keychain = NULL; - eigrp_authTLV_MD5_free(authTLV); - return 0; - } - - if(key) - { - authTLV->key_id = htonl(key->index); - memset(authTLV->digest,0,EIGRP_AUTH_TYPE_MD5_LEN); - stream_put(s,authTLV, sizeof(struct TLV_MD5_Authentication_Type)); - eigrp_authTLV_MD5_free(authTLV); - return EIGRP_AUTH_MD5_TLV_SIZE; - } - - eigrp_authTLV_MD5_free(authTLV); - - return 0; + struct key *key; + struct keychain *keychain; + struct TLV_MD5_Authentication_Type *authTLV; + + authTLV = eigrp_authTLV_MD5_new(); + + authTLV->type = htons(EIGRP_TLV_AUTH); + authTLV->length = htons(EIGRP_AUTH_MD5_TLV_SIZE); + authTLV->auth_type = htons(EIGRP_AUTH_TYPE_MD5); + authTLV->auth_length = htons(EIGRP_AUTH_TYPE_MD5_LEN); + authTLV->key_sequence = 0; + memset(authTLV->Nullpad, 0, sizeof(authTLV->Nullpad)); + + keychain = keychain_lookup(IF_DEF_PARAMS(ei->ifp)->auth_keychain); + if (keychain) + key = key_lookup_for_send(keychain); + else { + free(IF_DEF_PARAMS(ei->ifp)->auth_keychain); + IF_DEF_PARAMS(ei->ifp)->auth_keychain = NULL; + eigrp_authTLV_MD5_free(authTLV); + return 0; + } + + if (key) { + authTLV->key_id = htonl(key->index); + memset(authTLV->digest, 0, EIGRP_AUTH_TYPE_MD5_LEN); + stream_put(s, authTLV, + sizeof(struct TLV_MD5_Authentication_Type)); + eigrp_authTLV_MD5_free(authTLV); + return EIGRP_AUTH_MD5_TLV_SIZE; + } + + eigrp_authTLV_MD5_free(authTLV); + + return 0; } -u_int16_t -eigrp_add_authTLV_SHA256_to_stream (struct stream *s, - struct eigrp_interface *ei) +u_int16_t eigrp_add_authTLV_SHA256_to_stream(struct stream *s, + struct eigrp_interface *ei) { - struct key *key; - struct keychain *keychain; - struct TLV_SHA256_Authentication_Type *authTLV; - - authTLV = eigrp_authTLV_SHA256_new(); - - authTLV->type = htons(EIGRP_TLV_AUTH); - authTLV->length = htons(EIGRP_AUTH_SHA256_TLV_SIZE); - authTLV->auth_type = htons(EIGRP_AUTH_TYPE_SHA256); - authTLV->auth_length = htons(EIGRP_AUTH_TYPE_SHA256_LEN); - authTLV->key_sequence = 0; - memset(authTLV->Nullpad,0,sizeof(authTLV->Nullpad)); - - keychain = keychain_lookup(IF_DEF_PARAMS (ei->ifp)->auth_keychain); - if(keychain) - key = key_lookup_for_send(keychain); - else - { - free(IF_DEF_PARAMS (ei->ifp)->auth_keychain); - IF_DEF_PARAMS (ei->ifp)->auth_keychain = NULL; - eigrp_authTLV_SHA256_free(authTLV); - return 0; - } - - if(key) - { - authTLV->key_id = 0; - memset(authTLV->digest,0,EIGRP_AUTH_TYPE_SHA256_LEN); - stream_put(s,authTLV, sizeof(struct TLV_SHA256_Authentication_Type)); - eigrp_authTLV_SHA256_free(authTLV); - return EIGRP_AUTH_SHA256_TLV_SIZE; - } - - eigrp_authTLV_SHA256_free(authTLV); - - return 0; + struct key *key; + struct keychain *keychain; + struct TLV_SHA256_Authentication_Type *authTLV; + + authTLV = eigrp_authTLV_SHA256_new(); + + authTLV->type = htons(EIGRP_TLV_AUTH); + authTLV->length = htons(EIGRP_AUTH_SHA256_TLV_SIZE); + authTLV->auth_type = htons(EIGRP_AUTH_TYPE_SHA256); + authTLV->auth_length = htons(EIGRP_AUTH_TYPE_SHA256_LEN); + authTLV->key_sequence = 0; + memset(authTLV->Nullpad, 0, sizeof(authTLV->Nullpad)); + + keychain = keychain_lookup(IF_DEF_PARAMS(ei->ifp)->auth_keychain); + if (keychain) + key = key_lookup_for_send(keychain); + else { + free(IF_DEF_PARAMS(ei->ifp)->auth_keychain); + IF_DEF_PARAMS(ei->ifp)->auth_keychain = NULL; + eigrp_authTLV_SHA256_free(authTLV); + return 0; + } + + if (key) { + authTLV->key_id = 0; + memset(authTLV->digest, 0, EIGRP_AUTH_TYPE_SHA256_LEN); + stream_put(s, authTLV, + sizeof(struct TLV_SHA256_Authentication_Type)); + eigrp_authTLV_SHA256_free(authTLV); + return EIGRP_AUTH_SHA256_TLV_SIZE; + } + + eigrp_authTLV_SHA256_free(authTLV); + + return 0; } -struct TLV_MD5_Authentication_Type * -eigrp_authTLV_MD5_new () +struct TLV_MD5_Authentication_Type *eigrp_authTLV_MD5_new() { - struct TLV_MD5_Authentication_Type *new; + struct TLV_MD5_Authentication_Type *new; - new = XCALLOC(MTYPE_EIGRP_AUTH_TLV, sizeof(struct TLV_MD5_Authentication_Type)); + new = XCALLOC(MTYPE_EIGRP_AUTH_TLV, + sizeof(struct TLV_MD5_Authentication_Type)); - return new; + return new; } -void -eigrp_authTLV_MD5_free (struct TLV_MD5_Authentication_Type *authTLV) +void eigrp_authTLV_MD5_free(struct TLV_MD5_Authentication_Type *authTLV) { - XFREE(MTYPE_EIGRP_AUTH_TLV, authTLV); + XFREE(MTYPE_EIGRP_AUTH_TLV, authTLV); } -struct TLV_SHA256_Authentication_Type * -eigrp_authTLV_SHA256_new () +struct TLV_SHA256_Authentication_Type *eigrp_authTLV_SHA256_new() { - struct TLV_SHA256_Authentication_Type *new; + struct TLV_SHA256_Authentication_Type *new; - new = XCALLOC(MTYPE_EIGRP_AUTH_SHA256_TLV, sizeof(struct TLV_SHA256_Authentication_Type)); + new = XCALLOC(MTYPE_EIGRP_AUTH_SHA256_TLV, + sizeof(struct TLV_SHA256_Authentication_Type)); - return new; + return new; } -void -eigrp_authTLV_SHA256_free (struct TLV_SHA256_Authentication_Type *authTLV) +void eigrp_authTLV_SHA256_free(struct TLV_SHA256_Authentication_Type *authTLV) { - XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV); + XFREE(MTYPE_EIGRP_AUTH_SHA256_TLV, authTLV); } -struct TLV_IPv4_Internal_type * -eigrp_IPv4_InternalTLV_new () +struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new() { - struct TLV_IPv4_Internal_type *new; + struct TLV_IPv4_Internal_type *new; - new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV,sizeof(struct TLV_IPv4_Internal_type)); + new = XCALLOC(MTYPE_EIGRP_IPV4_INT_TLV, + sizeof(struct TLV_IPv4_Internal_type)); - return new; + return new; } -void -eigrp_IPv4_InternalTLV_free (struct TLV_IPv4_Internal_type *IPv4_InternalTLV) +void eigrp_IPv4_InternalTLV_free( + struct TLV_IPv4_Internal_type *IPv4_InternalTLV) { - XFREE(MTYPE_EIGRP_IPV4_INT_TLV, IPv4_InternalTLV); + XFREE(MTYPE_EIGRP_IPV4_INT_TLV, IPv4_InternalTLV); } -struct TLV_Sequence_Type * -eigrp_SequenceTLV_new () +struct TLV_Sequence_Type *eigrp_SequenceTLV_new() { - struct TLV_Sequence_Type *new; + struct TLV_Sequence_Type *new; - new = XCALLOC(MTYPE_EIGRP_SEQ_TLV,sizeof(struct TLV_Sequence_Type)); + new = XCALLOC(MTYPE_EIGRP_SEQ_TLV, sizeof(struct TLV_Sequence_Type)); - return new; + return new; } |
