Commits

ripencc committed 9493788

IS-626 fix ipv6 formatting inconsistancies

Comments (0)

Files changed (5)

 SYS_LIBS= @LIBS@
 
 LIB_H	 = bgpdump.h bgpdump_attr.h bgpdump_formats.h bgpdump_lib.h bgpdump_mstream.h cfile_tools.h util.h
-LIB_O	 = bgpdump_lib.o bgpdump_mstream.o cfile_tools.o util.o
+LIB_O	 = bgpdump_lib.o bgpdump_mstream.o cfile_tools.o util.o inet_ntop.o
 
 all: libbgpdump.so bgpdump 
 
     -m         output in one-line machine readable format 1\n\
     -M         output in one-line machine readable format 2\n\
 \n\
-Common Options:\n\
+Common options:\n\
     -O <file>  output to <file> instead of STDOUT\n\
     -s         log to syslog (the default)\n\
     -v         log to STDERR\n\
 Options for -m and -M modes:\n\
     -t dump    timestamps for RIB dumps reflect the time of the dump (the default)\n\
     -t change  timestamps for RIB dumps reflect the last route modification\n\
+\n\
+Special options:\n\
+    -T         run unit tests and exit\n\
 \n";
 
 int main(int argc, char *argv[]) {
  
     log_to_stderr();
     
-    while ((c=getopt(argc,argv,"if:o:t:mMHO:sv"))!=-1)
+    while ((c=getopt(argc,argv,"if:o:t:mMHO:svT"))!=-1)
 	switch(c)
 	{
        case 'H':
         case 'o':
                 warn("ignoring option '-%c'", c);
                 break;
+        case 'T':
+                test_fmt_ip();
+                exit(0);
         case '?':
         default:
                 usage_error = true;
 #ifdef BGPDUMP_HAVE_IPV6
 	    	case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6:
 	    		printf("TYPE: TABLE_DUMP/INET6\n");
-			prefix_str = inet_ntop(AF_INET6,&entry->body.mrtd_table_dump.prefix.v6_addr,prefix,sizeof(prefix));
+			prefix_str = fmt_ipv6(entry->body.mrtd_table_dump.prefix,prefix);
 		break;
 
 	    	case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6_32BIT_AS:
 	    		printf("TYPE: TABLE_DUMP/INET6_32BIT_AS\n");
-			prefix_str = inet_ntop(AF_INET6,&entry->body.mrtd_table_dump.prefix.v6_addr,prefix,sizeof(prefix));
+			prefix_str = fmt_ipv6(entry->body.mrtd_table_dump.prefix,prefix);
 		break;
 
 #endif
 		case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6:
 		case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6_32BIT_AS:
 
-			inet_ntop(AF_INET6,&entry->body.mrtd_table_dump.peer_ip.v6_addr,prefix,sizeof(prefix));
+			fmt_ipv6(entry->body.mrtd_table_dump.peer_ip,prefix);
 			printf("%s ",prefix);
 			break;
 #endif
 				strncpy(prefix, inet_ntoa(e->prefix.v4_addr), BGPDUMP_ADDRSTRLEN);
 #ifdef BGPDUMP_HAVE_IPV6
 			} else if(e->afi == AFI_IP6){
-				inet_ntop(AF_INET6, &e->prefix.v6_addr, prefix, BGPDUMP_ADDRSTRLEN);
+				fmt_ipv6(e->prefix, prefix);
 #endif
 			}
 
     			printf("SEQUENCE: %d\n",e->seq);
 
 				if(e->entries[i].peer->afi == AFI_IP){
-					inet_ntop(AF_INET, &e->entries[i].peer->peer_ip, peer_ip, BGPDUMP_ADDRSTRLEN);
+					fmt_ipv4(e->entries[i].peer->peer_ip, peer_ip);
 #ifdef BGPDUMP_HAVE_IPV6
 				} else if (e->entries[i].peer->afi == AFI_IP6){
-					inet_ntop(AF_INET6, &e->entries[i].peer->peer_ip, peer_ip, BGPDUMP_ADDRSTRLEN);
+					fmt_ipv6(e->entries[i].peer->peer_ip, peer_ip);
 #endif
 				} else {
 					sprintf(peer_ip, "[N/A, unsupported AF]");
 #ifdef BGPDUMP_HAVE_IPV6
 						case AFI_IP6:
 
-							inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip.v6_addr,prefix,sizeof(prefix));
+							fmt_ipv6(entry->body.zebra_message.source_ip,prefix);
 							printf(" %s ",prefix);
 							break;
 #endif
 #ifdef BGPDUMP_HAVE_IPV6
 						case AFI_IP6:
 
-							inet_ntop(AF_INET6,&entry->body.zebra_message.destination_ip.v6_addr,prefix,sizeof(prefix));
+							fmt_ipv6(entry->body.zebra_message.destination_ip,prefix);
 							printf(" %s ",prefix);
 							break;
 #endif
 #ifdef BGPDUMP_HAVE_IPV6
 						case AFI_IP6:
 
-							inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip.v6_addr,prefix,sizeof(prefix));
+							fmt_ipv6(entry->body.zebra_message.source_ip,prefix);
 							printf(" %s ",prefix);
 							break;
 #endif
 #ifdef BGPDUMP_HAVE_IPV6
 						case AFI_IP6:
 
-							inet_ntop(AF_INET6,&entry->body.zebra_message.destination_ip.v6_addr,prefix,sizeof(prefix));
+							fmt_ipv6(entry->body.zebra_message.destination_ip,prefix);
 							printf(" %s ",prefix);
 							break;
 #endif
 #ifdef BGPDUMP_HAVE_IPV6
 						case AFI_IP6:
 
-							inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip.v6_addr,prefix,sizeof(prefix));
+							fmt_ipv6(entry->body.zebra_message.source_ip,prefix);
 							printf(" %s ",prefix);
 							break;
 #endif
 #ifdef BGPDUMP_HAVE_IPV6
 						case AFI_IP6:
 
-							inet_ntop(AF_INET6,&entry->body.zebra_message.destination_ip.v6_addr,prefix,sizeof(prefix));
+							fmt_ipv6(entry->body.zebra_message.destination_ip,prefix);
 							printf(" %s ",prefix);
 							break;
 #endif
 #ifdef BGPDUMP_HAVE_IPV6
 						case AFI_IP6:
 
-							inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip.v6_addr,prefix,sizeof(prefix));
+							fmt_ipv6(entry->body.zebra_message.source_ip,prefix);
 							printf(" %s ",prefix);
 							break;
 #endif
 #ifdef BGPDUMP_HAVE_IPV6
 						case AFI_IP6:
 
-							inet_ntop(AF_INET6,&entry->body.zebra_message.destination_ip.v6_addr,prefix,sizeof(prefix));
+							fmt_ipv6(entry->body.zebra_message.destination_ip,prefix);
 							printf(" %s ",prefix);
 							break;
 #endif
 #ifdef BGPDUMP_HAVE_IPV6
 			case AFI_IP6:
 
-				inet_ntop(AF_INET6,&entry->body.zebra_state_change.source_ip.v6_addr,prefix,sizeof(prefix));
+				fmt_ipv6(entry->body.zebra_state_change.source_ip,prefix);
 				printf(" %s ",prefix);
 				break;
 #endif
 #ifdef BGPDUMP_HAVE_IPV6
 				case AFI_IP6:
 
-					inet_ntop(AF_INET6,&entry->body.zebra_state_change.source_ip.v6_addr,prefix,sizeof(prefix));
+					fmt_ipv6(entry->body.zebra_state_change.source_ip,prefix);
 					if (mode == 1)
 						printf("BGP4MP|%ld|STATE|%s|%s|%d|%d\n",entry->time,prefix,print_asn(entry->body.zebra_state_change.source_as),entry->body.zebra_state_change.old_state,entry->body.zebra_state_change.new_state);
 					else
 			   if (attr->mp_info->announce[AFI_IP6][SAFI_UNICAST])
 			   {
 				   printf("(IPv6 Unicast)\n");
-			   	   printf("NEXT_HOP: %s\n",inet_ntop(AF_INET6,&attr->mp_info->announce[AFI_IP6][SAFI_UNICAST]->nexthop.v6_addr,buf,128));
+			   	   printf("NEXT_HOP: %s\n",fmt_ipv6(attr->mp_info->announce[AFI_IP6][SAFI_UNICAST]->nexthop,buf));
 			           if (attr->mp_info->announce[AFI_IP6][SAFI_UNICAST]->nexthop_len==32)
-					printf("NEXT_HOP: %s\n",inet_ntop(AF_INET6,&attr->mp_info->announce[AFI_IP6][SAFI_UNICAST]->nexthop_local.v6_addr,buf,128));
+					printf("NEXT_HOP: %s\n",fmt_ipv6(attr->mp_info->announce[AFI_IP6][SAFI_UNICAST]->nexthop_local,buf));
 			   }
 			   else if (attr->mp_info->announce[AFI_IP6][SAFI_MULTICAST])	 
 		  	   {
 			   	   printf("(IPv6 Multicast)\n");
-				   printf("NEXT_HOP: %s\n",inet_ntop(AF_INET6,&attr->mp_info->announce[AFI_IP6][SAFI_MULTICAST]->nexthop.v6_addr,buf,128));
+				   printf("NEXT_HOP: %s\n",fmt_ipv6(attr->mp_info->announce[AFI_IP6][SAFI_MULTICAST]->nexthop,buf));
 			           if (attr->mp_info->announce[AFI_IP6][SAFI_MULTICAST]->nexthop_len==32)
-					printf("NEXT_HOP: %s\n",inet_ntop(AF_INET6,&attr->mp_info->announce[AFI_IP6][SAFI_MULTICAST]->nexthop_local.v6_addr,buf,128));
+					printf("NEXT_HOP: %s\n",fmt_ipv6(attr->mp_info->announce[AFI_IP6][SAFI_MULTICAST]->nexthop_local,buf));
 
 		           }
 			   else
 		           {
 				   printf("(IPv6 Both unicast and multicast)\n");
-				   printf("NEXT_HOP: %s\n",inet_ntop(AF_INET6,&attr->mp_info->announce[AFI_IP6][SAFI_UNICAST_MULTICAST]->nexthop.v6_addr,buf,128));
+				   printf("NEXT_HOP: %s\n",fmt_ipv6(attr->mp_info->announce[AFI_IP6][SAFI_UNICAST_MULTICAST]->nexthop,buf));
 			           if (attr->mp_info->announce[AFI_IP6][SAFI_UNICAST_MULTICAST]->nexthop_len==32)
-					printf("NEXT_HOP: %s\n",inet_ntop(AF_INET6,&attr->mp_info->announce[AFI_IP6][SAFI_UNICAST_MULTICAST]->nexthop_local.v6_addr,buf,128));
+					printf("NEXT_HOP: %s\n",fmt_ipv6(attr->mp_info->announce[AFI_IP6][SAFI_UNICAST_MULTICAST]->nexthop_local,buf));
 
 
 			   }
 	char buf[128];
 
 	for (i=0;i<count;i++)
-	 printf("  %s/%d\n",inet_ntop(AF_INET6,&prefix[i].address.v6_addr,buf,128),prefix[i].len);
+	 printf("  %s/%d\n",fmt_ipv6(prefix[i].address,buf),prefix[i].len);
 }
 #endif
 
 			{
 #ifdef BGPDUMP_HAVE_IPV6
 			case AFI_IP6:
-				printf("BGP4MP|%ld|W|%s|%s|",entry->time,inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip.v6_addr,buf,128),print_asn(entry->body.zebra_message.source_as));
+				printf("BGP4MP|%ld|W|%s|%s|",entry->time,fmt_ipv6(entry->body.zebra_message.source_ip,buf),print_asn(entry->body.zebra_message.source_as));
 				break;
 #endif
 			case AFI_IP:
 			{
 #ifdef BGPDUMP_HAVE_IPV6
 			case AFI_IP6:
-				printf("BGP4MP|%s|W|%s|%s|",time_str,inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip.v6_addr,buf,128),print_asn(entry->body.zebra_message.source_as));
+				printf("BGP4MP|%s|W|%s|%s|",time_str,fmt_ipv6(entry->body.zebra_message.source_ip,buf),print_asn(entry->body.zebra_message.source_as));
 				break;
 #endif
 			case AFI_IP:
 			switch(entry->body.zebra_message.address_family)
 			{
 			case AFI_IP6:
-				printf("BGP4MP|%ld|W|%s|%s|%s/%d\n",entry->time,inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip,buf1,128),print_asn(entry->body.zebra_message.source_as),inet_ntop(AF_INET6,&prefix[index].address.v6_addr,buf,128),prefix[index].len);
+				printf("BGP4MP|%ld|W|%s|%s|%s/%d\n",entry->time,fmt_ipv6(entry->body.zebra_message.source_ip,buf1),print_asn(entry->body.zebra_message.source_as),fmt_ipv6(prefix[index].address,buf),prefix[index].len);
 				break;
 			case AFI_IP:
 			default:
-				printf("BGP4MP|%ld|W|%s|%s|%s/%d\n",entry->time,inet_ntop(AF_INET,&entry->body.zebra_message.source_ip,buf1,128),print_asn(entry->body.zebra_message.source_as),inet_ntop(AF_INET6,&prefix[index].address.v6_addr,buf,128),prefix[index].len);
+				printf("BGP4MP|%ld|W|%s|%s|%s/%d\n",entry->time,fmt_ipv4(entry->body.zebra_message.source_ip,buf1),print_asn(entry->body.zebra_message.source_as),fmt_ipv6(prefix[index].address,buf),prefix[index].len);
 				break;
 			}
 		}	
 			switch(entry->body.zebra_message.address_family)
 			{
 			case AFI_IP6:
-				printf("BGP4MP|%s|W|%s|%s|%s/%d\n",time_str,inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip,buf1,128),print_asn(entry->body.zebra_message.source_as),inet_ntop(AF_INET6,&prefix[index].address.v6_addr,buf,128),prefix[index].len);
+				printf("BGP4MP|%s|W|%s|%s|%s/%d\n",time_str,fmt_ipv6(entry->body.zebra_message.source_ip,buf1),print_asn(entry->body.zebra_message.source_as),fmt_ipv6(prefix[index].address,buf),prefix[index].len);
 				break;
 			case AFI_IP:
 			default:
-				printf("BGP4MP|%s|W|%s|%s|%s/%d\n",time_str,inet_ntop(AF_INET,&entry->body.zebra_message.source_ip,buf1,128),print_asn(entry->body.zebra_message.source_as),inet_ntop(AF_INET6,&prefix[index].address.v6_addr,buf,128),prefix[index].len);
+				printf("BGP4MP|%s|W|%s|%s|%s/%d\n",time_str,fmt_ipv4(entry->body.zebra_message.source_ip,buf1),print_asn(entry->body.zebra_message.source_as),fmt_ipv6(prefix[index].address,buf),prefix[index].len);
 				break;
 			}
 		}
 			{
 #ifdef BGPDUMP_HAVE_IPV6
 			case AFI_IP6:
-				printf("BGP4MP|%ld|A|%s|%s|",entry->time,inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip,buf,128),print_asn(entry->body.zebra_message.source_as));
+				printf("BGP4MP|%ld|A|%s|%s|",entry->time,fmt_ipv6(entry->body.zebra_message.source_ip,buf),print_asn(entry->body.zebra_message.source_as));
 				break;
 #endif
 			case AFI_IP:
 			{
 #ifdef BGPDUMP_HAVE_IPV6
 			case AFI_IP6:
-				printf("BGP4MP|%s|A|%s|%s|",time_str,inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip,buf,128),print_asn(entry->body.zebra_message.source_as));
+				printf("BGP4MP|%s|A|%s|%s|",time_str,fmt_ipv6(entry->body.zebra_message.source_ip,buf),print_asn(entry->body.zebra_message.source_as));
 				break;
 #endif
 			case AFI_IP:
 				{
 #ifdef BGPDUMP_HAVE_IPV6
 				case AFI_IP6:
-					printf("BGP4MP|%ld|A|%s|%s|",entry->time,inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip,buf,128),print_asn(entry->body.zebra_message.source_as));
+					printf("BGP4MP|%ld|A|%s|%s|",entry->time,fmt_ipv6(entry->body.zebra_message.source_ip,buf),print_asn(entry->body.zebra_message.source_as));
 					break;
 #endif
 				case AFI_IP:
 				{
 #ifdef BGPDUMP_HAVE_IPV6
 				case AFI_IP6:
-					printf("BGP4MP|%ld|A|%s|%s|",entry->time,inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip,buf,128),print_asn(entry->body.zebra_message.source_as));
+					printf("BGP4MP|%ld|A|%s|%s|",entry->time,fmt_ipv6(entry->body.zebra_message.source_ip,buf),print_asn(entry->body.zebra_message.source_as));
 					break;
 #endif
 				case AFI_IP:
 			{
 #ifdef BGPDUMP_HAVE_IPV6
 			case AFI_IP6:
-				printf("BGP4MP|%s|A|%s|%s|",time_str,inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip,buf,128),print_asn(entry->body.zebra_message.source_as));
+				printf("BGP4MP|%s|A|%s|%s|",time_str,fmt_ipv6(entry->body.zebra_message.source_ip,buf),print_asn(entry->body.zebra_message.source_as));
 				break;
 #endif
 			case AFI_IP:
 	            if( (entry->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC) ) ==0)
 	            nmed=0;
 			    
-				printf("BGP4MP|%ld|A|%s|%s|%s/%d|%s|%s|%s|%u|%u|",entry->time,inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip,buf1,128),print_asn(entry->body.zebra_message.source_as),inet_ntop(AF_INET6,&prefix->nlri[index].address.v6_addr,buf2,128),prefix->nlri[index].len,ATTR_ASPATH(entry->attr),tmp1,inet_ntop(AF_INET6,&prefix->nexthop,buf,128),npref,nmed);
+				printf("BGP4MP|%ld|A|%s|%s|%s/%d|%s|%s|%s|%u|%u|",entry->time,fmt_ipv6(entry->body.zebra_message.source_ip,buf1),print_asn(entry->body.zebra_message.source_as),fmt_ipv6(prefix->nlri[index].address,buf2),prefix->nlri[index].len,ATTR_ASPATH(entry->attr),tmp1,fmt_ipv6(prefix->nexthop,buf),npref,nmed);
 				break;
 			case AFI_IP:
 			default:
 	            nmed=0;
 			    
 			//printf("%s|%d|%d|",inet_ntoa(entry->attr->nexthop),nprof,nmed);
-				printf("BGP4MP|%ld|A|%s|%s|%s/%d|%s|%s|%s|%u|%u|",entry->time,inet_ntop(AF_INET,&entry->body.zebra_message.source_ip,buf1,128),print_asn(entry->body.zebra_message.source_as),inet_ntop(AF_INET6,&prefix->nlri[index].address.v6_addr,buf2,128),prefix->nlri[index].len,ATTR_ASPATH(entry->attr),tmp1,inet_ntop(AF_INET6,&prefix->nexthop,buf,128),npref,nmed);
+				printf("BGP4MP|%ld|A|%s|%s|%s/%d|%s|%s|%s|%u|%u|",entry->time,fmt_ipv4(entry->body.zebra_message.source_ip,buf1),print_asn(entry->body.zebra_message.source_as),fmt_ipv6(prefix->nlri[index].address,buf2),prefix->nlri[index].len,ATTR_ASPATH(entry->attr),tmp1,fmt_ipv6(prefix->nexthop,buf),npref,nmed);
 				break;
 			}
 			if( (entry->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES) ) !=0)	
 			switch(entry->body.zebra_message.address_family)
 			{
 			case AFI_IP6:
-				printf("BGP4MP|%s|A|%s|%s|%s/%d|%s|%s\n",time_str,inet_ntop(AF_INET6,&entry->body.zebra_message.source_ip,buf1,128),print_asn(entry->body.zebra_message.source_as),inet_ntop(AF_INET6,&prefix->nlri[index].address.v6_addr,buf,128),prefix->nlri[index].len,ATTR_ASPATH(entry->attr),tmp1);
+				printf("BGP4MP|%s|A|%s|%s|%s/%d|%s|%s\n",time_str,fmt_ipv6(entry->body.zebra_message.source_ip,buf1),print_asn(entry->body.zebra_message.source_as),fmt_ipv6(prefix->nlri[index].address,buf),prefix->nlri[index].len,ATTR_ASPATH(entry->attr),tmp1);
 				break;
 			case AFI_IP:
 			default:
-				printf("BGP4MP|%s|A|%s|%s|%s/%d|%s|%s\n",time_str,inet_ntop(AF_INET,&entry->body.zebra_message.source_ip,buf1,128),print_asn(entry->body.zebra_message.source_as),inet_ntop(AF_INET6,&prefix->nlri[index].address.v6_addr,buf,128),prefix->nlri[index].len,ATTR_ASPATH(entry->attr),tmp1);
+				printf("BGP4MP|%s|A|%s|%s|%s/%d|%s|%s\n",time_str,fmt_ipv4(entry->body.zebra_message.source_ip,buf1),print_asn(entry->body.zebra_message.source_as),fmt_ipv6(prefix->nlri[index].address,buf),prefix->nlri[index].len,ATTR_ASPATH(entry->attr),tmp1);
 				break;
 			}
 		}		
 #ifdef BGPDUMP_HAVE_IPV6
 	    	if (entry->subtype == AFI_IP6)
 		{
-		    strncpy(peer, inet_ntop(AF_INET6,&route->peer_ip.v6_addr,peer,sizeof(peer)), BGPDUMP_ADDRSTRLEN);
-		    strncpy(prefix, inet_ntop(AF_INET6,&route->prefix.v6_addr,prefix,sizeof(prefix)), BGPDUMP_ADDRSTRLEN);
+		    fmt_ipv6(route->peer_ip,peer);
+		    fmt_ipv6(route->prefix,prefix);
 		}
 	    	else
 #endif
 #ifdef BGPDUMP_HAVE_IPV6
 	    	if ((entry->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) && entry->attr->mp_info->announce[AFI_IP6][SAFI_UNICAST])
 		{
-		    inet_ntop(AF_INET6,&entry->attr->mp_info->announce[AFI_IP6][SAFI_UNICAST]->nexthop,nexthop,sizeof(nexthop));
+		    fmt_ipv6(entry->attr->mp_info->announce[AFI_IP6][SAFI_UNICAST]->nexthop,nexthop);
 		}
 	    	else
 #endif
         char *aggregate = attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE) ? "AG" : "NAG";
         
         if(e->entries[i].peer->afi == AFI_IP){
-            inet_ntop(AF_INET, &e->entries[i].peer->peer_ip, peer, BGPDUMP_ADDRSTRLEN);
+            fmt_ipv4(e->entries[i].peer->peer_ip, peer);
 #ifdef BGPDUMP_HAVE_IPV6
         } else if(e->entries[i].peer->afi == AFI_IP6){
-            inet_ntop(AF_INET6, &e->entries[i].peer->peer_ip, peer, BGPDUMP_ADDRSTRLEN);
+            fmt_ipv6(e->entries[i].peer->peer_ip, peer);
 #endif
         }
         
         if(e->afi == AFI_IP) {
-            inet_ntop(AF_INET, &e->prefix.v4_addr, prefix, BGPDUMP_ADDRSTRLEN);
+            fmt_ipv4(e->prefix, prefix);
 #ifdef BGPDUMP_HAVE_IPV6
         } else if(e->afi == AFI_IP6) {
-            inet_ntop(AF_INET6, &e->prefix.v6_addr, prefix, BGPDUMP_ADDRSTRLEN);
+            fmt_ipv6(e->prefix, prefix);
 #endif
         }
         
 #ifdef BGPDUMP_HAVE_IPV6
             if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI)) && attr->mp_info->announce[AFI_IP6][SAFI_UNICAST])
             {
-                inet_ntop(AF_INET6,&attr->mp_info->announce[AFI_IP6][SAFI_UNICAST]->nexthop,nexthop,sizeof(nexthop));
+                fmt_ipv6(attr->mp_info->announce[AFI_IP6][SAFI_UNICAST]->nexthop,nexthop);
             }
             else
 #endif

bgpdump.xcodeproj/project.pbxproj

 	objects = {
 
 /* Begin PBXBuildFile section */
+		4DA3ECA41237A8930007C28C /* inet_ntop.c in Sources */ = {isa = PBXBuildFile; fileRef = 4DA3ECA31237A8930007C28C /* inet_ntop.c */; };
+		4DA3ECA51237A8930007C28C /* inet_ntop.c in Sources */ = {isa = PBXBuildFile; fileRef = 4DA3ECA31237A8930007C28C /* inet_ntop.c */; };
 		4DF74766122D4E800092F3E2 /* bgpdump.c in Sources */ = {isa = PBXBuildFile; fileRef = 4DF7475F122D4E800092F3E2 /* bgpdump.c */; };
 		4DF7479F122D52510092F3E2 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DF7477A122D51850092F3E2 /* libz.dylib */; };
 		4DF747A0122D525A0092F3E2 /* libbz2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DF7477C122D51990092F3E2 /* libbz2.dylib */; };
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+		4DA3ECA31237A8930007C28C /* inet_ntop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = inet_ntop.c; sourceTree = "<group>"; };
 		4DF74757122D4E800092F3E2 /* bgpdump_attr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bgpdump_attr.h; sourceTree = "<group>"; };
 		4DF74758122D4E800092F3E2 /* bgpdump_formats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bgpdump_formats.h; sourceTree = "<group>"; };
 		4DF74759122D4E800092F3E2 /* bgpdump_lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bgpdump_lib.c; sourceTree = "<group>"; };
 		08FB7795FE84155DC02AAC07 /* Source */ = {
 			isa = PBXGroup;
 			children = (
+				4DA3ECA31237A8930007C28C /* inet_ntop.c */,
 				4DF74757122D4E800092F3E2 /* bgpdump_attr.h */,
 				4DF74758122D4E800092F3E2 /* bgpdump_formats.h */,
 				4DF74759122D4E800092F3E2 /* bgpdump_lib.c */,
 			buildActionMask = 2147483647;
 			files = (
 				4DF74865122E52060092F3E2 /* util.c in Sources */,
+				4DA3ECA51237A8930007C28C /* inet_ntop.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 				4DF747A7122D52C30092F3E2 /* bgpdump_mstream.c in Sources */,
 				4DF747A8122D52C50092F3E2 /* cfile_tools.c in Sources */,
 				4DF74863122E52060092F3E2 /* util.c in Sources */,
+				4DA3ECA41237A8930007C28C /* inet_ntop.c in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+/*
+ Copyright (c) 2007 - 2010 RIPE NCC - All Rights Reserved
+ 
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted, provided
+ that the above copyright notice appear in all copies and that both that
+ copyright notice and this permission notice appear in supporting
+ documentation, and that the name of the author not be used in advertising or
+ publicity pertaining to distribution of the software without specific,
+ written prior permission.
+ 
+ THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
+ AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+ DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+ * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Copyright 1994, 1995 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''.  M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include "bgpdump.h"
+
+char *fmt_ipv4(BGPDUMP_IP_ADDRESS addr, char *buffer)
+{
+    assert(buffer);
+    uint8_t *ap = (uint8_t *)&addr.v4_addr.s_addr;
+    
+    sprintf(buffer, "%d.%d.%d.%d", ap[0], ap[1], ap[2], ap[3]);
+    
+    return buffer;
+}
+
+char *fmt_ipv6(BGPDUMP_IP_ADDRESS addr, char *buffer)
+{    
+    static const char hexchars[] = "0123456789abcdef";
+
+    assert(buffer);
+        
+    /*  check for mapped or compat addresses */
+    bool m = IN6_IS_ADDR_V4MAPPED(&addr.v6_addr);
+    bool c = IN6_IS_ADDR_V4COMPAT(&addr.v6_addr);
+    if (m || c) {
+        char buffer2[100];
+        BGPDUMP_IP_ADDRESS mapped = { .v4_addr.s_addr = ((uint32_t *)addr.v6_addr.s6_addr)[3] };
+        
+        sprintf(buffer, "::%s%s", m ? "ffff:" : "", fmt_ipv4(mapped, buffer2));
+        return buffer;
+    }
+    
+    char hexa[8][5];
+    int zr[8];
+    size_t len;
+    uint8_t x8, hx8;
+    uint16_t x16;
+    
+    int i, k = 0;
+    for (i = 0; i < 16; i += 2) {
+        int j = 0;
+        bool skip = 1;
+        
+        memset(hexa[k], 0, 5);
+        
+        x8 = addr.v6_addr.s6_addr[i];
+        
+        hx8 = x8 >> 4;
+        if (hx8 != 0)
+        {
+            skip = 0;
+            hexa[k][j++] = hexchars[hx8];
+        }
+        
+        hx8 = x8 & 0x0f;
+        if ((skip == 0) || ((skip == 1) && (hx8 != 0)))
+        {
+            skip = 0;
+            hexa[k][j++] = hexchars[hx8];
+        }
+        
+        x8 = addr.v6_addr.s6_addr[i + 1];
+        
+        hx8 = x8 >> 4;
+        if ((skip == 0) || ((skip == 1) && (hx8 != 0)))
+        {
+            hexa[k][j++] = hexchars[hx8];
+        }
+        
+        hx8 = x8 & 0x0f;
+        hexa[k][j++] = hexchars[hx8];
+        
+        k++;
+    }
+    
+    /* find runs of zeros for :: convention */
+    int j = 0;
+    for (i = 7; i >= 0; i--)
+    {
+        zr[i] = j;
+        x16 = ((uint16_t *)addr.v6_addr.s6_addr)[i];
+        if (x16 == 0) j++;
+        else j = 0;
+        zr[i] = j;
+    }
+    
+    /* find longest run of zeros */
+    k = -1;
+    j = 0;
+    for(i = 0; i < 8; i++)
+    {
+        if (zr[i] > j)
+        {
+            k = i;
+            j = zr[i];
+        }
+    }
+    
+    for(i = 0; i < 8; i++)
+    {
+        if (i != k) zr[i] = 0;
+    }
+    
+    len = 0;
+    for (i = 0; i < 8; i++)
+    {
+        if (zr[i] != 0)
+        {
+            /* check for leading zero */
+            if (i == 0)
+                buffer[len++] = ':';
+            buffer[len++] = ':';
+            i += (zr[i] - 1);
+            continue;
+        }
+        for (j = 0; hexa[i][j] != '\0'; j++)
+            buffer[len++] = hexa[i][j];
+        if (i != 7)
+            buffer[len++] = ':';
+    }
+    
+    buffer[len] = '\0';
+    
+    return buffer;
+}
+
+static void test_roundtrip(char *str)
+{
+    BGPDUMP_IP_ADDRESS addr;
+    inet_pton(AF_INET6, str, &addr.v6_addr);
+    char tmp[1000];
+    fmt_ipv6(addr, tmp);
+    printf("%s -> %s [%s]\n", str, tmp, strcmp(str, tmp) ? "ERROR" : "ok");
+}
+
+void test_fmt_ip()
+{
+    test_roundtrip("fe80::");
+    test_roundtrip("2001:db8::1");
+    test_roundtrip("::ffff:192.168.2.1");
+    test_roundtrip("::192.168.1.2");
+    test_roundtrip("2001:7f8:30::2:1:0:8447");
+}
 #ifndef _UTIL_H
 #define _UTIL_H
 
+#include "bgpdump.h"
+
 void log_to_stderr();
 void log_to_syslog();
 
 void warn(char *fmt, ...) __attribute__((format(printf, 1, 2)));
 void info(char *fmt, ...) __attribute__((format(printf, 1, 2)));
 
-#endif
+char *fmt_ipv4(BGPDUMP_IP_ADDRESS addr, char *buffer);
+char *fmt_ipv6(BGPDUMP_IP_ADDRESS addr, char *buffer);
+void test_fmt_ip();
+
+#endif