plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

eipfmt.c (2870B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <ip.h>
      4 
      5 enum
      6 {
      7 	Isprefix= 16
      8 };
      9 
     10 /* XXX: manually initialize once to placate the Sun monster */
     11 uchar prefixvals[256];
     12 #ifdef NOTDEF
     13 uchar prefixvals[256] =
     14 {
     15 [0x00] 0 | Isprefix,
     16 [0x80] 1 | Isprefix,
     17 [0xC0] 2 | Isprefix,
     18 [0xE0] 3 | Isprefix,
     19 [0xF0] 4 | Isprefix,
     20 [0xF8] 5 | Isprefix,
     21 [0xFC] 6 | Isprefix,
     22 [0xFE] 7 | Isprefix,
     23 [0xFF] 8 | Isprefix,
     24 };
     25 #endif
     26 
     27 int
     28 eipfmt(Fmt *f)
     29 {
     30 	char buf[5*8];
     31 	static char *efmt = "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux";
     32 	static char *altefmt = "%.2ux:%.2ux:%.2ux:%.2ux:%.2ux:%.2ux";
     33 	static char *ifmt = "%d.%d.%d.%d";
     34 	char *fmt;
     35 	uchar *p, ip[16];
     36 	ulong *lp;
     37 	ushort s;
     38 	int i, j, n, eln, eli;
     39 
     40 	static int once = 0;	/* XXX: placate the Sun monster */
     41 
     42 	if(!once){
     43 		once = 1;
     44 		memset(prefixvals, 0, sizeof(prefixvals));
     45 		prefixvals[0x00] = 0 | Isprefix;
     46 		prefixvals[0x80] = 1 | Isprefix;
     47 		prefixvals[0xC0] = 2 | Isprefix;
     48 		prefixvals[0xE0] = 3 | Isprefix;
     49 		prefixvals[0xF0] = 4 | Isprefix;
     50 		prefixvals[0xF8] = 5 | Isprefix;
     51 		prefixvals[0xFC] = 6 | Isprefix;
     52 		prefixvals[0xFE] = 7 | Isprefix;
     53 		prefixvals[0xFF] = 8 | Isprefix;
     54 	}
     55 
     56 	switch(f->r) {
     57 	case 'E':		/* Ethernet address */
     58 		p = va_arg(f->args, uchar*);
     59 		fmt = efmt;
     60 		if(f->flags&FmtSharp)
     61 			fmt = altefmt;
     62 		snprint(buf, sizeof buf, fmt, p[0], p[1], p[2], p[3], p[4], p[5]);
     63 		return fmtstrcpy(f, buf);
     64 
     65 	case 'I':		/* Ip address */
     66 		p = va_arg(f->args, uchar*);
     67 common:
     68 		if(memcmp(p, v4prefix, 12) == 0){
     69 			snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]);
     70 			return fmtstrcpy(f, buf);
     71 		}
     72 
     73 		/* find longest elision */
     74 		eln = eli = -1;
     75 		for(i = 0; i < 16; i += 2){
     76 			for(j = i; j < 16; j += 2)
     77 				if(p[j] != 0 || p[j+1] != 0)
     78 					break;
     79 			if(j > i && j - i > eln){
     80 				eli = i;
     81 				eln = j - i;
     82 			}
     83 		}
     84 
     85 		/* print with possible elision */
     86 		n = 0;
     87 		for(i = 0; i < 16; i += 2){
     88 			if(i == eli){
     89 				n += sprint(buf+n, "::");
     90 				i += eln;
     91 				if(i >= 16)
     92 					break;
     93 			} else if(i != 0)
     94 				n += sprint(buf+n, ":");
     95 			s = (p[i]<<8) + p[i+1];
     96 			n += sprint(buf+n, "%ux", s);
     97 		}
     98 		return fmtstrcpy(f, buf);
     99 
    100 	case 'i':		/* v6 address as 4 longs */
    101 		lp = va_arg(f->args, ulong*);
    102 		for(i = 0; i < 4; i++)
    103 			hnputl(ip+4*i, *lp++);
    104 		p = ip;
    105 		goto common;
    106 
    107 	case 'V':		/* v4 ip address */
    108 		p = va_arg(f->args, uchar*);
    109 		snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]);
    110 		return fmtstrcpy(f, buf);
    111 
    112 	case 'M':		/* ip mask */
    113 		p = va_arg(f->args, uchar*);
    114 
    115 		/* look for a prefix mask */
    116 		for(i = 0; i < 16; i++)
    117 			if(p[i] != 0xff)
    118 				break;
    119 		if(i < 16){
    120 			if((prefixvals[p[i]] & Isprefix) == 0)
    121 				goto common;
    122 			for(j = i+1; j < 16; j++)
    123 				if(p[j] != 0)
    124 					goto common;
    125 			n = 8*i + (prefixvals[p[i]] & ~Isprefix);
    126 		} else
    127 			n = 8*16;
    128 
    129 		/* got one, use /xx format */
    130 		snprint(buf, sizeof buf, "/%d", n);
    131 		return fmtstrcpy(f, buf);
    132 	}
    133 	return fmtstrcpy(f, "(eipfmt)");
    134 }