URI:
       teipfmt.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       teipfmt.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 }