| #include <vfs.h> |
| #include <kfs.h> |
| #include <slab.h> |
| #include <kmalloc.h> |
| #include <kref.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <assert.h> |
| #include <error.h> |
| #include <cpio.h> |
| #include <pmap.h> |
| #include <smp.h> |
| |
| #if 1 |
| /* sadly, we don't have this yet; too bad! |
| */ |
| int eipfmt(void *unused) |
| { |
| return 0; |
| |
| } |
| #else |
| enum |
| { |
| Isprefix= 16, |
| }; |
| |
| uint8_t prefixvals[256] = |
| { |
| [0x00] 0 | Isprefix, |
| [0x80] 1 | Isprefix, |
| [0xC0] 2 | Isprefix, |
| [0xE0] 3 | Isprefix, |
| [0xF0] 4 | Isprefix, |
| [0xF8] 5 | Isprefix, |
| [0xFC] 6 | Isprefix, |
| [0xFE] 7 | Isprefix, |
| [0xFF] 8 | Isprefix, |
| }; |
| |
| int |
| eipfmt(Fmt *f) |
| { |
| char buf[5*8]; |
| static char *efmt = "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux"; |
| static char *ifmt = "%d.%d.%d.%d"; |
| uint8_t *p, ip[16]; |
| uint32_t *lp; |
| uint16_t s; |
| int i, j, n, eln, eli; |
| |
| switch(f->r) { |
| case 'E': /* Ethernet address */ |
| p = va_arg(f->args, uint8_t *unused_uint8_p_t); |
| snprintf(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]); |
| return fmtstrncpy(f, buf, sizeof(f)); |
| |
| case 'I': /* Ip address */ |
| p = va_arg(f->args, uint8_t *unused_uint8_p_t); |
| common: |
| if(memcmp(p, v4prefix, 12) == 0){ |
| snprintf(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]); |
| return fmtstrncpy(f, buf, sizeof(f)); |
| } |
| |
| /* find longest elision */ |
| eln = eli = -1; |
| for(i = 0; i < 16; i += 2){ |
| for(j = i; j < 16; j += 2) |
| if(p[j] != 0 || p[j+1] != 0) |
| break; |
| if(j > i && j - i > eln){ |
| eli = i; |
| eln = j - i; |
| } |
| } |
| |
| /* print with possible elision */ |
| n = 0; |
| for(i = 0; i < 16; i += 2){ |
| if(i == eli){ |
| n += sprint(buf+n, "::"); |
| i += eln; |
| if(i >= 16) |
| break; |
| } else if(i != 0) |
| n += sprint(buf+n, ":"); |
| s = (p[i]<<8) + p[i+1]; |
| n += sprint(buf+n, "%ux", s); |
| } |
| return fmtstrncpy(f, buf, sizeof(f)); |
| |
| case 'i': /* v6 address as 4 longs */ |
| lp = va_arg(f->args, uint32_t*); |
| for(i = 0; i < 4; i++) |
| hnputl(ip+4*i, *lp++); |
| p = ip; |
| goto common; |
| |
| case 'V': /* v4 ip address */ |
| p = va_arg(f->args, uint8_t *unused_uint8_p_t); |
| snprintf(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]); |
| return fmtstrncpy(f, buf, sizeof(f)); |
| |
| case 'M': /* ip mask */ |
| p = va_arg(f->args, uint8_t *unused_uint8_p_t); |
| |
| /* look for a prefix mask */ |
| for(i = 0; i < 16; i++) |
| if(p[i] != 0xff) |
| break; |
| if(i < 16){ |
| if((prefixvals[p[i]] & Isprefix) == 0) |
| goto common; |
| for(j = i+1; j < 16; j++) |
| if(p[j] != 0) |
| goto common; |
| n = 8*i + (prefixvals[p[i]] & ~Isprefix); |
| } else |
| n = 8*16; |
| |
| /* got one, use /xx format */ |
| snprintf(buf, sizeof buf, "/%d", n); |
| return fmtstrncpy(f, buf, sizeof(f)); |
| } |
| return fmtstrncpy(f, "(eipfmt)", sizeof(f)); |
| } |
| #endif |