From b0d5046428bd45908d5815fb510251e49c0fa4ee Mon Sep 17 00:00:00 2001 From: leitner Date: Sun, 4 Mar 2007 13:13:19 +0000 Subject: [PATCH] fmt_ip6 compresses at best spot, not at first spot (Nikola Vladov) --- CHANGES | 1 + socket/fmt_ip6.c | 63 +++++++++++++++++++++++------------------------- test/fmt_ip6.c | 14 +++++++++++ 3 files changed, 45 insertions(+), 33 deletions(-) create mode 100644 test/fmt_ip6.c diff --git a/CHANGES b/CHANGES index 515e47b..c2e4b21 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,7 @@ connections came in and got newer, higher descriptors since the last io_timeouted loop. (Dirk Engling) add some int overflow check macros to rangecheck.h + fmt_ip6 compresses at best spot, not at first spot (Nikola Vladov) 0.25: array_allocate no longer truncates the array diff --git a/socket/fmt_ip6.c b/socket/fmt_ip6.c index 20ab8b9..a661d00 100644 --- a/socket/fmt_ip6.c +++ b/socket/fmt_ip6.c @@ -5,44 +5,41 @@ unsigned int fmt_ip6(char *s,const char ip[16]) { - unsigned int len; - unsigned int i; - unsigned int temp; - unsigned int compressing; - unsigned int compressed; - int j; + unsigned long len,temp, k, pos0=0,len0=0, pos1=0, compr=0; - len = 0; compressing = 0; compressed = 0; - for (j=0; j<16; j+=2) { - if (j==12 && ip6_isv4mapped(ip)) { - temp=ip4_fmt(s,ip+12); - len+=temp; - break; - } - temp = ((unsigned long) (unsigned char) ip[j] << 8) + - (unsigned long) (unsigned char) ip[j+1]; - if (temp == 0 && !compressed) { - if (!compressing) { - compressing=1; - if (j==0) { - if (s) *s++=':'; ++len; - } - } - } else { - if (compressing) { - compressing=0; ++compressed; - if (s) *s++=':'; ++len; + for (k=0; k<16; k+=2) { + if (ip[k]==0 && ip[k+1]==0) { + if (!compr) { + compr=1; + pos1=k; } - i = fmt_xlong(s,temp); len += i; if (s) s += i; - if (j<14) { - if (s) *s++ = ':'; - ++len; + if (k==14) { k=16; goto last; } + } else if (compr) { + last: + if ((temp=k-pos1) > len0) { + len0=temp; + pos0=pos1; } + compr=0; } } - if (compressing) { if (s) *s++=':'; ++len; } -/* if (s) *s=0; */ + for (len=0,k=0; k<16; k+=2) { + if (k==12 && ip6_isv4mapped(ip)) { + len += ip4_fmt(s,ip+12); + break; + } + if (pos0==k && len0) { + if (k==0) { ++len; if (s) *s++ = ':'; } + ++len; if (s) *s++ = ':'; + k += len0-2; + continue; + } + temp = ((unsigned long) (unsigned char) ip[k] << 8) + + (unsigned long) (unsigned char) ip[k+1]; + temp = fmt_xlong(s,temp); len += temp; if (s) s += temp; + if (k<14) { ++len; if (s) *s++ = ':'; } + } + return len; } - diff --git a/test/fmt_ip6.c b/test/fmt_ip6.c new file mode 100644 index 0000000..8cbfe1d --- /dev/null +++ b/test/fmt_ip6.c @@ -0,0 +1,14 @@ +#include "ip6.h" +#include + +int main() { + char buf[100]; + int i; + buf[i=fmt_ip6(buf,"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")]=0; assert(i==2 && !strcmp(buf,"::")); + buf[i=fmt_ip6(buf,"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")]=0; assert(i==3 && !strcmp(buf,"::1")); + buf[i=fmt_ip6(buf,"\xfe\xc0\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x01")]=0; + assert(i==16 && !strcmp(buf,"fec0:0:0:ffff::1")); + buf[i=fmt_ip6(buf,"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x7f\x00\x00\x01")]=0; + assert(i==16 && !strcmp(buf,"::ffff:127.0.0.1")); + return 0; +}