mirror of
https://github.com/0intro/conterm
synced 2024-11-22 13:51:34 +03:00
23a48c7cfe
Addresses are now stored as uchar[16] instead of ulong, with enough room for IPv6. Generic IP functions have been removed from devip.c and replaced by libip, imported from Plan 9. Names and addresses are resolved using either gethostbyname() or getaddrinfo() functions. On Windows, IPv6 name resolution is not enabled, because mingw32 doesn't provide inet_ntop(). R=rsc http://codereview.appspot.com/6408044
110 lines
2.1 KiB
C
110 lines
2.1 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <ip.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,
|
|
};
|
|
|
|
int
|
|
eipfmt(Fmt *f)
|
|
{
|
|
char buf[5*8];
|
|
static char *efmt = "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux";
|
|
static char *ifmt = "%d.%d.%d.%d";
|
|
uchar *p, ip[16];
|
|
ulong *lp;
|
|
ushort s;
|
|
int i, j, n, eln, eli;
|
|
|
|
switch(f->r) {
|
|
case 'E': /* Ethernet address */
|
|
p = va_arg(f->args, uchar*);
|
|
snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
|
|
return fmtstrcpy(f, buf);
|
|
|
|
case 'I': /* Ip address */
|
|
p = va_arg(f->args, uchar*);
|
|
common:
|
|
if(memcmp(p, v4prefix, 12) == 0){
|
|
snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]);
|
|
return fmtstrcpy(f, buf);
|
|
}
|
|
|
|
/* 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);
|
|
}
|
|
return fmtstrcpy(f, buf);
|
|
|
|
case 'i': /* v6 address as 4 longs */
|
|
lp = va_arg(f->args, ulong*);
|
|
for(i = 0; i < 4; i++)
|
|
hnputl(ip+4*i, *lp++);
|
|
p = ip;
|
|
goto common;
|
|
|
|
case 'V': /* v4 ip address */
|
|
p = va_arg(f->args, uchar*);
|
|
snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]);
|
|
return fmtstrcpy(f, buf);
|
|
|
|
case 'M': /* ip mask */
|
|
p = va_arg(f->args, 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 */
|
|
snprint(buf, sizeof buf, "/%d", n);
|
|
return fmtstrcpy(f, buf);
|
|
}
|
|
return fmtstrcpy(f, "(eipfmt)");
|
|
}
|