19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <ip.h>
49a747e4fSDavid du Colombier
59a747e4fSDavid du Colombier enum
69a747e4fSDavid du Colombier {
79a747e4fSDavid du Colombier Isprefix= 16,
89a747e4fSDavid du Colombier };
99a747e4fSDavid du Colombier
109a747e4fSDavid du Colombier uchar prefixvals[256] =
119a747e4fSDavid du Colombier {
129a747e4fSDavid du Colombier [0x00] 0 | Isprefix,
139a747e4fSDavid du Colombier [0x80] 1 | Isprefix,
149a747e4fSDavid du Colombier [0xC0] 2 | Isprefix,
159a747e4fSDavid du Colombier [0xE0] 3 | Isprefix,
169a747e4fSDavid du Colombier [0xF0] 4 | Isprefix,
179a747e4fSDavid du Colombier [0xF8] 5 | Isprefix,
189a747e4fSDavid du Colombier [0xFC] 6 | Isprefix,
199a747e4fSDavid du Colombier [0xFE] 7 | Isprefix,
209a747e4fSDavid du Colombier [0xFF] 8 | Isprefix,
219a747e4fSDavid du Colombier };
229a747e4fSDavid du Colombier
239a747e4fSDavid du Colombier int
eipfmt(Fmt * f)249a747e4fSDavid du Colombier eipfmt(Fmt *f)
259a747e4fSDavid du Colombier {
269a747e4fSDavid du Colombier char buf[5*8];
27*6063170eSDavid du Colombier static char *efmt = "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux";
289a747e4fSDavid du Colombier static char *ifmt = "%d.%d.%d.%d";
299a747e4fSDavid du Colombier uchar *p, ip[16];
309a747e4fSDavid du Colombier ulong *lp;
319a747e4fSDavid du Colombier ushort s;
329a747e4fSDavid du Colombier int i, j, n, eln, eli;
339a747e4fSDavid du Colombier
349a747e4fSDavid du Colombier switch(f->r) {
359a747e4fSDavid du Colombier case 'E': /* Ethernet address */
369a747e4fSDavid du Colombier p = va_arg(f->args, uchar*);
379a747e4fSDavid du Colombier snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
389a747e4fSDavid du Colombier return fmtstrcpy(f, buf);
399a747e4fSDavid du Colombier
409a747e4fSDavid du Colombier case 'I': /* Ip address */
419a747e4fSDavid du Colombier p = va_arg(f->args, uchar*);
429a747e4fSDavid du Colombier common:
439a747e4fSDavid du Colombier if(memcmp(p, v4prefix, 12) == 0){
449a747e4fSDavid du Colombier snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]);
459a747e4fSDavid du Colombier return fmtstrcpy(f, buf);
469a747e4fSDavid du Colombier }
479a747e4fSDavid du Colombier
489a747e4fSDavid du Colombier /* find longest elision */
499a747e4fSDavid du Colombier eln = eli = -1;
509a747e4fSDavid du Colombier for(i = 0; i < 16; i += 2){
519a747e4fSDavid du Colombier for(j = i; j < 16; j += 2)
529a747e4fSDavid du Colombier if(p[j] != 0 || p[j+1] != 0)
539a747e4fSDavid du Colombier break;
549a747e4fSDavid du Colombier if(j > i && j - i > eln){
559a747e4fSDavid du Colombier eli = i;
569a747e4fSDavid du Colombier eln = j - i;
579a747e4fSDavid du Colombier }
589a747e4fSDavid du Colombier }
599a747e4fSDavid du Colombier
609a747e4fSDavid du Colombier /* print with possible elision */
619a747e4fSDavid du Colombier n = 0;
629a747e4fSDavid du Colombier for(i = 0; i < 16; i += 2){
639a747e4fSDavid du Colombier if(i == eli){
649a747e4fSDavid du Colombier n += sprint(buf+n, "::");
659a747e4fSDavid du Colombier i += eln;
669a747e4fSDavid du Colombier if(i >= 16)
679a747e4fSDavid du Colombier break;
689a747e4fSDavid du Colombier } else if(i != 0)
699a747e4fSDavid du Colombier n += sprint(buf+n, ":");
709a747e4fSDavid du Colombier s = (p[i]<<8) + p[i+1];
719a747e4fSDavid du Colombier n += sprint(buf+n, "%ux", s);
729a747e4fSDavid du Colombier }
739a747e4fSDavid du Colombier return fmtstrcpy(f, buf);
749a747e4fSDavid du Colombier
759a747e4fSDavid du Colombier case 'i': /* v6 address as 4 longs */
769a747e4fSDavid du Colombier lp = va_arg(f->args, ulong*);
779a747e4fSDavid du Colombier for(i = 0; i < 4; i++)
789a747e4fSDavid du Colombier hnputl(ip+4*i, *lp++);
799a747e4fSDavid du Colombier p = ip;
809a747e4fSDavid du Colombier goto common;
819a747e4fSDavid du Colombier
829a747e4fSDavid du Colombier case 'V': /* v4 ip address */
839a747e4fSDavid du Colombier p = va_arg(f->args, uchar*);
849a747e4fSDavid du Colombier snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]);
859a747e4fSDavid du Colombier return fmtstrcpy(f, buf);
869a747e4fSDavid du Colombier
879a747e4fSDavid du Colombier case 'M': /* ip mask */
889a747e4fSDavid du Colombier p = va_arg(f->args, uchar*);
899a747e4fSDavid du Colombier
909a747e4fSDavid du Colombier /* look for a prefix mask */
919a747e4fSDavid du Colombier for(i = 0; i < 16; i++)
929a747e4fSDavid du Colombier if(p[i] != 0xff)
939a747e4fSDavid du Colombier break;
949a747e4fSDavid du Colombier if(i < 16){
959a747e4fSDavid du Colombier if((prefixvals[p[i]] & Isprefix) == 0)
969a747e4fSDavid du Colombier goto common;
979a747e4fSDavid du Colombier for(j = i+1; j < 16; j++)
989a747e4fSDavid du Colombier if(p[j] != 0)
999a747e4fSDavid du Colombier goto common;
1009a747e4fSDavid du Colombier n = 8*i + (prefixvals[p[i]] & ~Isprefix);
1019a747e4fSDavid du Colombier } else
1029a747e4fSDavid du Colombier n = 8*16;
1039a747e4fSDavid du Colombier
1049a747e4fSDavid du Colombier /* got one, use /xx format */
1059a747e4fSDavid du Colombier snprint(buf, sizeof buf, "/%d", n);
1069a747e4fSDavid du Colombier return fmtstrcpy(f, buf);
1079a747e4fSDavid du Colombier }
1089a747e4fSDavid du Colombier return fmtstrcpy(f, "(eipfmt)");
1099a747e4fSDavid du Colombier }
110