eipfmt.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) 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 }