eipconvtest.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #include <u.h>
  2. #include <libc.h>
  3. enum
  4. {
  5. Isprefix= 16,
  6. };
  7. uchar prefixvals[256] =
  8. {
  9. [0x00] 0 | Isprefix,
  10. [0x80] 1 | Isprefix,
  11. [0xC0] 2 | Isprefix,
  12. [0xE0] 3 | Isprefix,
  13. [0xF0] 4 | Isprefix,
  14. [0xF8] 5 | Isprefix,
  15. [0xFC] 6 | Isprefix,
  16. [0xFE] 7 | Isprefix,
  17. [0xFF] 8 | Isprefix,
  18. };
  19. uchar v4prefix[16] = {
  20. 0, 0, 0, 0,
  21. 0, 0, 0, 0,
  22. 0, 0, 0xff, 0xff,
  23. 0, 0, 0, 0
  24. };
  25. void
  26. hnputl(void *p, ulong v)
  27. {
  28. uchar *a;
  29. a = p;
  30. a[0] = v>>24;
  31. a[1] = v>>16;
  32. a[2] = v>>8;
  33. a[3] = v;
  34. }
  35. int
  36. eipconv(va_list *arg, Fconv *f)
  37. {
  38. char buf[8*5];
  39. static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
  40. static char *ifmt = "%d.%d.%d.%d";
  41. uchar *p, ip[16];
  42. ulong *lp;
  43. ushort s;
  44. int i, j, n, eln, eli;
  45. switch(f->chr) {
  46. case 'E': /* Ethernet address */
  47. p = va_arg(*arg, uchar*);
  48. sprint(buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
  49. break;
  50. case 'I': /* Ip address */
  51. p = va_arg(*arg, uchar*);
  52. common:
  53. if(memcmp(p, v4prefix, 12) == 0)
  54. sprint(buf, ifmt, p[12], p[13], p[14], p[15]);
  55. else {
  56. /* find longest elision */
  57. eln = eli = -1;
  58. for(i = 0; i < 16; i += 2){
  59. for(j = i; j < 16; j += 2)
  60. if(p[j] != 0 || p[j+1] != 0)
  61. break;
  62. if(j > i && j - i > eln){
  63. eli = i;
  64. eln = j - i;
  65. }
  66. }
  67. /* print with possible elision */
  68. n = 0;
  69. for(i = 0; i < 16; i += 2){
  70. if(i == eli){
  71. n += sprint(buf+n, "::");
  72. i += eln;
  73. if(i >= 16)
  74. break;
  75. } else if(i != 0)
  76. n += sprint(buf+n, ":");
  77. s = (p[i]<<8) + p[i+1];
  78. n += sprint(buf+n, "%ux", s);
  79. }
  80. }
  81. break;
  82. case 'i': /* v6 address as 4 longs */
  83. lp = va_arg(*arg, ulong*);
  84. for(i = 0; i < 4; i++)
  85. hnputl(ip+4*i, *lp++);
  86. p = ip;
  87. goto common;
  88. case 'V': /* v4 ip address */
  89. p = va_arg(*arg, uchar*);
  90. sprint(buf, ifmt, p[0], p[1], p[2], p[3]);
  91. break;
  92. case 'M': /* ip mask */
  93. p = va_arg(*arg, uchar*);
  94. /* look for a prefix mask */
  95. for(i = 0; i < 16; i++)
  96. if(p[i] != 0xff)
  97. break;
  98. if(i < 16){
  99. if((prefixvals[p[i]] & Isprefix) == 0)
  100. goto common;
  101. for(j = i+1; j < 16; j++)
  102. if(p[j] != 0)
  103. goto common;
  104. n = 8*i + (prefixvals[p[i]] & ~Isprefix);
  105. } else
  106. n = 8*16;
  107. /* got one, use /xx format */
  108. sprint(buf, "/%d", n);
  109. break;
  110. default:
  111. strcpy(buf, "(eipconv)");
  112. }
  113. strconv(buf, f);
  114. return sizeof(uchar*);
  115. }
  116. uchar testvec[11][16] =
  117. {
  118. { 0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 1,3,4,5, },
  119. { 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, },
  120. { 0xff,0xff,0x80,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, },
  121. { 0xff,0xff,0xff,0xc0, 0,0,0,0, 0,0,0,0, 0,0,0,0, },
  122. { 0xff,0xff,0xff,0xff, 0xe0,0,0,0, 0,0,0,0, 0,0,0,0, },
  123. { 0xff,0xff,0xff,0xff, 0xff,0xf0,0,0, 0,0,0,0, 0,0,0,0, },
  124. { 0xff,0xff,0xff,0xff, 0xff,0xff,0xf8,0, 0,0,0,0, 0,0,0,0, },
  125. { 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, },
  126. { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, },
  127. { 0,0,0,0, 0,0x11,0,0, 0,0,0,0, 0,0,0,0, },
  128. { 0,0,0,0x11, 0,0,0,0, 0,0,0,0, 0,0,0,0x12, },
  129. };
  130. void
  131. main(void)
  132. {
  133. int i;
  134. fmtinstall('I', eipconv);
  135. fmtinstall('M', eipconv);
  136. for(i = 0; i < 11; i++)
  137. print("%I\n%M\n", testvec[i], testvec[i]);
  138. exits(0);
  139. }