eipfmt.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <ip.h>
  12. enum
  13. {
  14. Isprefix= 16,
  15. };
  16. unsigned char prefixvals[256] =
  17. {
  18. [0x00] = 0 | Isprefix,
  19. [0x80] = 1 | Isprefix,
  20. [0xC0] = 2 | Isprefix,
  21. [0xE0] = 3 | Isprefix,
  22. [0xF0] = 4 | Isprefix,
  23. [0xF8] = 5 | Isprefix,
  24. [0xFC] = 6 | Isprefix,
  25. [0xFE] = 7 | Isprefix,
  26. [0xFF] = 8 | Isprefix,
  27. };
  28. int
  29. eipfmt(Fmt *f)
  30. {
  31. char buf[5*8];
  32. static char *efmt = "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux";
  33. static char *ifmt = "%d.%d.%d.%d";
  34. uint8_t *p, ip[16];
  35. uint32_t *lp;
  36. uint16_t s;
  37. int i, j, n, eln, eli;
  38. switch(f->r) {
  39. case 'E': /* Ethernet address */
  40. p = va_arg(f->args, uint8_t*);
  41. snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
  42. return fmtstrcpy(f, buf);
  43. case 'I': /* Ip address */
  44. p = va_arg(f->args, uint8_t*);
  45. common:
  46. if(memcmp(p, v4prefix, 12) == 0){
  47. snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]);
  48. return fmtstrcpy(f, buf);
  49. }
  50. /* find longest elision */
  51. eln = eli = -1;
  52. for(i = 0; i < 16; i += 2){
  53. for(j = i; j < 16; j += 2)
  54. if(p[j] != 0 || p[j+1] != 0)
  55. break;
  56. if(j > i && j - i > eln){
  57. eli = i;
  58. eln = j - i;
  59. }
  60. }
  61. /* print with possible elision */
  62. n = 0;
  63. for(i = 0; i < 16; i += 2){
  64. if(i == eli){
  65. n += sprint(buf+n, "::");
  66. i += eln;
  67. if(i >= 16)
  68. break;
  69. } else if(i != 0)
  70. n += sprint(buf+n, ":");
  71. s = (p[i]<<8) + p[i+1];
  72. n += sprint(buf+n, "%x", s);
  73. }
  74. return fmtstrcpy(f, buf);
  75. case 'i': /* v6 address as 4 longs */
  76. lp = va_arg(f->args, uint32_t*);
  77. for(i = 0; i < 4; i++)
  78. hnputl(ip+4*i, *lp++);
  79. p = ip;
  80. goto common;
  81. case 'V': /* v4 ip address */
  82. p = va_arg(f->args, uint8_t*);
  83. snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]);
  84. return fmtstrcpy(f, buf);
  85. case 'M': /* ip mask */
  86. p = va_arg(f->args, uint8_t*);
  87. /* look for a prefix mask */
  88. for(i = 0; i < 16; i++)
  89. if(p[i] != 0xff)
  90. break;
  91. if(i < 16){
  92. if((prefixvals[p[i]] & Isprefix) == 0)
  93. goto common;
  94. for(j = i+1; j < 16; j++)
  95. if(p[j] != 0)
  96. goto common;
  97. n = 8*i + (prefixvals[p[i]] & ~Isprefix);
  98. } else
  99. n = 8*16;
  100. /* got one, use /xx format */
  101. snprint(buf, sizeof buf, "/%d", n);
  102. return fmtstrcpy(f, buf);
  103. }
  104. return fmtstrcpy(f, "(eipfmt)");
  105. }