11#include "ipv6.h"
22#include "ipv6_config.h"
33
4+
45#ifdef HAVE_STDIO_H
56#include <stdio.h>
67#endif
1415#endif
1516
1617#if defined(PARSE_TRACE )
17- #define TRACE (...) printf(__VA_ARGS__)
18+ #define IPV6_TRACE (...) printf(__VA_ARGS__)
1819#else
19- #define TRACE (...)
20+ #define IPV6_TRACE (...)
2021#endif
2122
2223#ifdef HAVE__SNPRINTF_S
@@ -76,7 +77,7 @@ typedef enum {
7677} ipv6_reader_state_flag_t ;
7778
7879//
79- // Reader state encapsulates the process of tokenizing and processing
80+ // Reader state encapsulates the process of token-izing and processing
8081// the incoming address specification
8182//
8283typedef struct ipv6_reader_state_t {
@@ -148,20 +149,20 @@ static const char* eventclass_str (eventclass_t input)
148149// Update the current state logging the transition
149150//
150151#define CHANGE_STATE (value ) \
151- TRACE (" * %s -> %s %s:%u\n", \
152+ IPV6_TRACE (" * %s -> %s %s:%u\n", \
152153 state_str(state->current), state_str(value), __FILE__, (uint32_t)__LINE__); \
153154 state->current = value;
154155
155156#define BEGIN_TOKEN (offset ) \
156- TRACE (" * %s: token begin at %u\n", state_str(state->current), state->position + offset); \
157+ IPV6_TRACE (" * %s: token begin at %u\n", state_str(state->current), state->position + offset); \
157158 state->token_position = state->position + offset; \
158159 state->token_len = 0; \
159160
160161//
161162// Indicate the presence of an invalid event class character for the current state
162163//
163164#define INVALID_INPUT () \
164- TRACE ("invalid input class (%d) in state: %s at position %d of '%s' (%c)\n", \
165+ IPV6_TRACE ("invalid input class (%d) in state: %s at position %d of '%s' (%c)\n", \
165166 input, state_str(state->current), state->position, state->input, state->input[state->position]); \
166167 ipv6_error(state, IPV6_DIAG_INVALID_INPUT, "Invalid input"); \
167168 return;
@@ -171,7 +172,7 @@ static const char* eventclass_str (eventclass_t input)
171172//
172173#define VALIDATE (msg , diag , cond , action ) \
173174 if (!(cond)) { \
174- TRACE (" failed '!" #cond "' in state: %s at position %d of '%s'\n\n", \
175+ IPV6_TRACE (" failed '!" #cond "' in state: %s at position %d of '%s'\n\n", \
175176 state_str(state->current), state->position, state->input); \
176177 ipv6_error(state, diag, msg); \
177178 action; \
@@ -265,7 +266,7 @@ static int32_t read_hexidecimal_token (ipv6_reader_state_t* state)
265266static void ipv6_parse_component (ipv6_reader_state_t * state ) {
266267 int32_t component = read_hexidecimal_token (state );
267268
268- TRACE (" * ipv6 address component %4x (%d)\n" , (uint16_t )component , component );
269+ IPV6_TRACE (" * ipv6 address component %4x (%d)\n" , (uint16_t )component , component );
269270
270271 VALIDATE ("Only 8 16bit components are allowed" ,
271272 IPV6_DIAG_V6_BAD_COMPONENT_COUNT ,
@@ -288,7 +289,7 @@ static void ipv6_parse_component (ipv6_reader_state_t* state) {
288289static void ipv4_parse_component (ipv6_reader_state_t * state ) {
289290 int32_t octet = read_decimal_token (state );
290291
291- TRACE (" * ipv4 address octet %2x (%d)\n" , (uint8_t )octet , octet );
292+ IPV6_TRACE (" * ipv4 address octet %2x (%d)\n" , (uint8_t )octet , octet );
292293
293294 VALIDATE ("Only 4 8bit components are allowed in an IPv4 embedding" ,
294295 IPV6_DIAG_V4_BAD_COMPONENT_COUNT ,
@@ -363,7 +364,7 @@ static void ipv6_state_transition (
363364 ipv6_reader_state_t * state ,
364365 eventclass_t input )
365366{
366- TRACE (" * transition input: %s <- %s\n" , state_str (state -> current ), eventclass_str (input ));
367+ IPV6_TRACE (" * transition input: %s <- %s\n" , state_str (state -> current ), eventclass_str (input ));
367368
368369 switch (state -> current ) {
369370 default :
@@ -455,7 +456,7 @@ static void ipv6_state_transition (
455456 return );
456457
457458 // Backwards compatibility marker for pure IPv4 address
458- if (state -> components == 0 ) {
459+ if (!( state -> flags & READER_FLAG_ZERORUN ) && state -> components == 0 ) {
459460 state -> flags |= READER_FLAG_IPV4_COMPAT ;
460461 }
461462
@@ -500,7 +501,7 @@ static void ipv6_state_transition (
500501 state -> zerorun = state -> components ;
501502 state -> flags |= READER_FLAG_ZERORUN ;
502503
503- TRACE (" * zero run index: %d\n" , state -> zerorun );
504+ IPV6_TRACE (" * zero run index: %d\n" , state -> zerorun );
504505 break ;
505506
506507 case EC_WHITESPACE :
@@ -657,7 +658,7 @@ bool IPV6_API_DEF(ipv6_from_str_diag) (
657658 state .address_full = out ;
658659
659660 while (* cp && cp < ep ) {
660- TRACE (
661+ IPV6_TRACE (
661662 " * parse state: %s, cp: '%c' (%02x) position: %d, flags: %08x\n" ,
662663 state_str (state .current ),
663664 * cp ,
@@ -726,6 +727,18 @@ bool IPV6_API_DEF(ipv6_from_str_diag) (
726727 // Treat the end of input as whitespace to simplify state transitions
727728 ipv6_state_transition (& state , EC_WHITESPACE );
728729
730+ // Early out if there was an error processing the string
731+ if ((state .flags & READER_FLAG_ERROR ) != 0 ) {
732+ return false;
733+ }
734+
735+ // If an IPv4 compatible address was specified the rest of the IPv6 collapsing
736+ // rules can be skipped
737+ if ((state .flags & READER_FLAG_IPV4_COMPAT ) != 0 ) {
738+ state .address_full -> flags |= IPV6_FLAG_IPV4_COMPAT ;
739+ return true;
740+ }
741+
729742 // Mark the presence of embedded IPv4 addresses
730743 if (state .flags & READER_FLAG_IPV4_EMBEDDING ) {
731744 if (state .v4_octets != 4 ) {
@@ -736,18 +749,6 @@ bool IPV6_API_DEF(ipv6_from_str_diag) (
736749 }
737750 }
738751
739- // Early out if there was an error processing the string
740- if ((state .flags & READER_FLAG_ERROR ) != 0 ) {
741- return false;
742- }
743-
744- // If an IPv4 compatible address was specified the rest of the IPv6 collapsing
745- // rules can be skipped
746- if ((state .flags & READER_FLAG_IPV4_COMPAT ) != 0 ) {
747- state .address_full -> flags |= IPV6_FLAG_IPV4_COMPAT ;
748- return true;
749- }
750-
751752 // If there was no abbreviated run all components should be specified
752753 if ((state .flags & READER_FLAG_ZERORUN ) == 0 ) {
753754 if (state .components < IPV6_NUM_COMPONENTS ) {
@@ -765,11 +766,11 @@ bool IPV6_API_DEF(ipv6_from_str_diag) (
765766 int32_t move_count = state .components - state .zerorun ;
766767 int32_t target = IPV6_NUM_COMPONENTS - move_count ;
767768 if (move_count < 0 || move_count > IPV6_NUM_COMPONENTS ) {
768- TRACE ("invalid move_count: %d\n" , move_count );
769+ IPV6_TRACE ("invalid move_count: %d\n" , move_count );
769770 return false;
770771 }
771772 if (target < 0 || target + move_count > IPV6_NUM_COMPONENTS ) {
772- TRACE ("invalid target location: %d:%d\n" , target , move_count );
773+ IPV6_TRACE ("invalid target location: %d:%d\n" , target , move_count );
773774 return false;
774775 }
775776
@@ -806,7 +807,7 @@ bool IPV6_API_DEF(ipv6_from_str) (
806807}
807808
808809#define OUTPUT_TRUNCATED () \
809- TRACE (" ! buffer truncated at position %u\n", (uint32_t)(wp - out)); \
810+ IPV6_TRACE (" ! buffer truncated at position %u\n", (uint32_t)(wp - out)); \
810811 *out = '\0';
811812
812813//--------------------------------------------------------------------------------
@@ -833,7 +834,7 @@ char* IPV6_API_DEF(ipv6_to_str) (
833834 if (in -> flags & IPV6_FLAG_IPV4_COMPAT ) {
834835 const uint32_t host_ipv4 = components [0 ] << 16 | components [1 ];
835836 if (in -> flags & IPV6_FLAG_HAS_PORT ) {
836- platform_snprintf (token , sizeof (token ), "%d.%d.%d.%d:%d" ,
837+ platform_snprintf (token , sizeof (token ), "%d.%d.%d.%d:%d" ,
837838 (uint8_t )(host_ipv4 >> 24 ),
838839 (uint8_t )(host_ipv4 >> 16 ),
839840 (uint8_t )(host_ipv4 >> 8 ),
@@ -969,39 +970,72 @@ char* IPV6_API_DEF(ipv6_to_str) (
969970//--------------------------------------------------------------------------------
970971int32_t IPV6_API_DEF (ipv6_compare ) (
971972 const ipv6_address_full_t * a ,
972- const ipv6_address_full_t * b )
973+ const ipv6_address_full_t * b ,
974+ uint32_t ignore_flags )
973975{
974- int32_t compare ;
976+ const uint16_t * a_components ;
977+ const uint16_t * b_components ;
978+ uint32_t num_components ;
979+
980+ // Mask out flags for comparison
981+ uint32_t compare_flags = (IPV6_FLAG_HAS_MASK | IPV6_FLAG_HAS_PORT ) & ~ignore_flags ;
982+
983+ // Treat any compatibility or embedded address as IPv4
984+ #define HAS_IPV4 (flags ) (((flags) & (IPV6_FLAG_IPV4_COMPAT|IPV6_FLAG_IPV4_EMBED)) != 0)
985+
986+ // Special case format selection:
987+ //
988+ // Allow comparison between embedded and compatible addresses
989+ //
990+ if (0 != (ignore_flags & (IPV6_FLAG_IPV4_EMBED |IPV6_FLAG_IPV4_COMPAT ))
991+ && (HAS_IPV4 (a -> flags ) || HAS_IPV4 (b -> flags )))
992+ {
993+ num_components = IPV4_NUM_COMPONENTS ;
994+ if (a -> flags & IPV6_FLAG_IPV4_COMPAT )
995+ a_components = & a -> address .components [0 ];
996+ else
997+ a_components = & a -> address .components [IPV4_EMBED_INDEX ];
998+ if (b -> flags & IPV6_FLAG_IPV4_COMPAT )
999+ b_components = & b -> address .components [0 ];
1000+ else
1001+ b_components = & b -> address .components [IPV4_EMBED_INDEX ];
1002+ }
1003+ else {
1004+ compare_flags |= (IPV6_FLAG_IPV4_EMBED | IPV6_FLAG_IPV4_COMPAT );
1005+ num_components = IPV6_NUM_COMPONENTS ;
1006+ a_components = & a -> address .components [0 ];
1007+ b_components = & b -> address .components [0 ];
1008+ }
9751009
976- // First compare the components in order
977- for (uint32_t i = 0 ; i < IPV6_NUM_COMPONENTS ; ++ i ) {
978- compare = a -> address .components [i ] - b -> address .components [i ];
979- if (compare != 0 ) {
980- return compare ;
981- }
1010+ // Make sure desired features are the same
1011+ if ((a -> flags & compare_flags ) != (b -> flags & compare_flags )) {
1012+ return IPV6_COMPARE_FORMAT_MISMATCH ;
9821013 }
9831014
984- // Make sure features are the same
985- compare = a -> flags - b -> flags ;
986- if (compare != 0 ) {
987- return compare ;
1015+ // Compare the desired number of components in order
1016+ for (uint32_t i = 0 ; i < num_components ; ++ i ) {
1017+ if (a_components [i ] != b_components [i ]) {
1018+ return IPV6_COMPARE_ADDRESS_MISMATCH ;
1019+ }
9881020 }
9891021
9901022 // Compare port
991- if (a -> flags & IPV6_FLAG_HAS_PORT ) {
992- compare = a -> port - b -> port ;
993- if (compare != 0 ) {
994- return compare ;
1023+ if ( ((ignore_flags & IPV6_FLAG_HAS_PORT ) == 0 )
1024+ && ((a -> flags & IPV6_FLAG_HAS_PORT ) || (b -> flags & IPV6_FLAG_HAS_PORT )))
1025+ {
1026+ if (a -> port != b -> port ) {
1027+ return IPV6_COMPARE_PORT_MISMATCH ;
9951028 }
9961029 }
9971030
9981031 // Compare mask
999- if (a -> flags & IPV6_FLAG_HAS_MASK ) {
1000- compare = a -> mask - b -> mask ;
1001- if (compare != 0 ) {
1002- return compare ;
1032+ if ( ((ignore_flags & IPV6_FLAG_HAS_MASK ) == 0 )
1033+ && ((a -> flags & IPV6_FLAG_HAS_MASK ) || (b -> flags & IPV6_FLAG_HAS_MASK )))
1034+ {
1035+ if (a -> mask != b -> mask ) {
1036+ return IPV6_COMPARE_MASK_MISMATCH ;
10031037 }
10041038 }
10051039
1006- return 0 ;
1040+ return IPV6_COMPARE_OK ;
10071041}
0 commit comments