vx32

Local 9vx git repository for patches.
git clone git://r-36.net/vx32
Log | Files | Refs

eipfmt.c (2189B)


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