#include <u.h>#include <libc.h> enum{ Isprefix= 16,}; uchar prefixvals[256] ={[0x00] 0 | Isprefix,[0x80] 1 | Isprefix,[0xC0] 2 | Isprefix,[0xE0] 3 | Isprefix,[0xF0] 4 | Isprefix,[0xF8] 5 | Isprefix,[0xFC] 6 | Isprefix,[0xFE] 7 | Isprefix,[0xFF] 8 | Isprefix,}; uchar v4prefix[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0}; voidhnputl(void *p, ulong v){ uchar *a; a = p; a[0] = v>>24; a[1] = v>>16; a[2] = v>>8; a[3] = v;} inteipconv(va_list *arg, Fconv *f){ char buf[8*5]; static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux"; static char *ifmt = "%d.%d.%d.%d"; uchar *p, ip[16]; ulong *lp; ushort s; int i, j, n, eln, eli; switch(f->chr) { case 'E': /* Ethernet address */ p = va_arg(*arg, uchar*); sprint(buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]); break; case 'I': /* Ip address */ p = va_arg(*arg, uchar*);common: if(memcmp(p, v4prefix, 12) == 0) sprint(buf, ifmt, p[12], p[13], p[14], p[15]); else { /* find longest elision */ eln = eli = -1; for(i = 0; i < 16; i += 2){ for(j = i; j < 16; j += 2) if(p[j] != 0 || p[j+1] != 0) break; if(j > i && j - i > eln){ eli = i; eln = j - i; } } /* print with possible elision */ n = 0; for(i = 0; i < 16; i += 2){ if(i == eli){ n += sprint(buf+n, "::"); i += eln; if(i >= 16) break; } else if(i != 0) n += sprint(buf+n, ":"); s = (p[i]<<8) + p[i+1]; n += sprint(buf+n, "%ux", s); } } break; case 'i': /* v6 address as 4 longs */ lp = va_arg(*arg, ulong*); for(i = 0; i < 4; i++) hnputl(ip+4*i, *lp++); p = ip; goto common; case 'V': /* v4 ip address */ p = va_arg(*arg, uchar*); sprint(buf, ifmt, p[0], p[1], p[2], p[3]); break; case 'M': /* ip mask */ p = va_arg(*arg, uchar*); /* look for a prefix mask */ for(i = 0; i < 16; i++) if(p[i] != 0xff) break; if(i < 16){ if((prefixvals[p[i]] & Isprefix) == 0) goto common; for(j = i+1; j < 16; j++) if(p[j] != 0) goto common; n = 8*i + (prefixvals[p[i]] & ~Isprefix); } else n = 8*16; /* got one, use /xx format */ sprint(buf, "/%d", n); break; default: strcpy(buf, "(eipconv)"); } strconv(buf, f); return sizeof(uchar*);} uchar testvec[11][16] ={ { 0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 1,3,4,5, }, { 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, }, { 0xff,0xff,0x80,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }, { 0xff,0xff,0xff,0xc0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }, { 0xff,0xff,0xff,0xff, 0xe0,0,0,0, 0,0,0,0, 0,0,0,0, }, { 0xff,0xff,0xff,0xff, 0xff,0xf0,0,0, 0,0,0,0, 0,0,0,0, }, { 0xff,0xff,0xff,0xff, 0xff,0xff,0xf8,0, 0,0,0,0, 0,0,0,0, }, { 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, }, { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, }, { 0,0,0,0, 0,0x11,0,0, 0,0,0,0, 0,0,0,0, }, { 0,0,0,0x11, 0,0,0,0, 0,0,0,0, 0,0,0,0x12, },}; voidmain(void){ int i; fmtinstall('I', eipconv); fmtinstall('M', eipconv); for(i = 0; i < 11; i++) print("%I\n%M\n", testvec[i], testvec[i]); exits(0);}
#include <u.h>
#include <libc.h>
enum
{
Isprefix= 16,
};
uchar prefixvals[256] =
{
[0x00] 0 | Isprefix,
[0x80] 1 | Isprefix,
[0xC0] 2 | Isprefix,
[0xE0] 3 | Isprefix,
[0xF0] 4 | Isprefix,
[0xF8] 5 | Isprefix,
[0xFC] 6 | Isprefix,
[0xFE] 7 | Isprefix,
[0xFF] 8 | Isprefix,
};
uchar v4prefix[16] = {
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0xff, 0xff,
0, 0, 0, 0
};
void
hnputl(void *p, ulong v)
{
uchar *a;
a = p;
a[0] = v>>24;
a[1] = v>>16;
a[2] = v>>8;
a[3] = v;
}
int
eipconv(va_list *arg, Fconv *f)
{
char buf[8*5];
static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
static char *ifmt = "%d.%d.%d.%d";
uchar *p, ip[16];
ulong *lp;
ushort s;
int i, j, n, eln, eli;
switch(f->chr) {
case 'E': /* Ethernet address */
p = va_arg(*arg, uchar*);
sprint(buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
break;
case 'I': /* Ip address */
p = va_arg(*arg, uchar*);
common:
if(memcmp(p, v4prefix, 12) == 0)
sprint(buf, ifmt, p[12], p[13], p[14], p[15]);
else {
/* find longest elision */
eln = eli = -1;
for(i = 0; i < 16; i += 2){
for(j = i; j < 16; j += 2)
if(p[j] != 0 || p[j+1] != 0)
break;
if(j > i && j - i > eln){
eli = i;
eln = j - i;
}
}
/* print with possible elision */
n = 0;
for(i = 0; i < 16; i += 2){
if(i == eli){
n += sprint(buf+n, "::");
i += eln;
if(i >= 16)
break;
} else if(i != 0)
n += sprint(buf+n, ":");
s = (p[i]<<8) + p[i+1];
n += sprint(buf+n, "%ux", s);
}
}
break;
case 'i': /* v6 address as 4 longs */
lp = va_arg(*arg, ulong*);
for(i = 0; i < 4; i++)
hnputl(ip+4*i, *lp++);
p = ip;
goto common;
case 'V': /* v4 ip address */
p = va_arg(*arg, uchar*);
sprint(buf, ifmt, p[0], p[1], p[2], p[3]);
break;
case 'M': /* ip mask */
p = va_arg(*arg, uchar*);
/* look for a prefix mask */
for(i = 0; i < 16; i++)
if(p[i] != 0xff)
break;
if(i < 16){
if((prefixvals[p[i]] & Isprefix) == 0)
goto common;
for(j = i+1; j < 16; j++)
if(p[j] != 0)
goto common;
n = 8*i + (prefixvals[p[i]] & ~Isprefix);
} else
n = 8*16;
/* got one, use /xx format */
sprint(buf, "/%d", n);
break;
default:
strcpy(buf, "(eipconv)");
}
strconv(buf, f);
return sizeof(uchar*);
}
uchar testvec[11][16] =
{
{ 0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 1,3,4,5, },
{ 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, },
{ 0xff,0xff,0x80,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, },
{ 0xff,0xff,0xff,0xc0, 0,0,0,0, 0,0,0,0, 0,0,0,0, },
{ 0xff,0xff,0xff,0xff, 0xe0,0,0,0, 0,0,0,0, 0,0,0,0, },
{ 0xff,0xff,0xff,0xff, 0xff,0xf0,0,0, 0,0,0,0, 0,0,0,0, },
{ 0xff,0xff,0xff,0xff, 0xff,0xff,0xf8,0, 0,0,0,0, 0,0,0,0, },
{ 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, },
{ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, },
{ 0,0,0,0, 0,0x11,0,0, 0,0,0,0, 0,0,0,0, },
{ 0,0,0,0x11, 0,0,0,0, 0,0,0,0, 0,0,0,0x12, },
};
void
main(void)
{
int i;
fmtinstall('I', eipconv);
fmtinstall('M', eipconv);
for(i = 0; i < 11; i++)
print("%I\n%M\n", testvec[i], testvec[i]);
exits(0);
}