linklocal.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. /*
  10. * linklocal - print ipv6 link-local or 6to4 address of a mac address.
  11. * eui is ieee's extended unique identifier, per rfc2373.
  12. */
  13. #include <u.h>
  14. #include <libc.h>
  15. #include <ip.h>
  16. enum {
  17. Mac0mcast = 1<<0, /* multicast address */
  18. Mac0localadm = 1<<1, /* locally-administered address, */
  19. V60globaladm = 1<<1, /* but ipv6 reverses the meaning */
  20. };
  21. static char *v4_6to4;
  22. static void
  23. usage(void)
  24. {
  25. fprint(2, "usage: %s [-t ipv4] ether...\n", argv0);
  26. exits("usage");
  27. }
  28. void
  29. ea2eui64(uint8_t *lla, uint8_t *ea)
  30. {
  31. *lla++ = *ea++ | V60globaladm; /* oui (company id) */
  32. *lla++ = *ea++; /* " */
  33. *lla++ = *ea++; /* " */
  34. *lla++ = 0xFF; /* mac-48 in eui-64 (sic) */
  35. *lla++ = 0xFE; /* " */
  36. *lla++ = *ea++; /* manufacturer-assigned */
  37. *lla++ = *ea++; /* " */
  38. *lla = *ea; /* " */
  39. }
  40. void
  41. eaip26to4(uint8_t *lla, uint8_t *ea, uint8_t *ipv4)
  42. {
  43. *lla++ = 0x20; /* 6to4 address */
  44. *lla++ = 0x02; /* " */
  45. memmove(lla, ipv4, IPv4addrlen);
  46. lla += IPv4addrlen;
  47. memset(lla, 0, 2);
  48. ea2eui64(lla + 2, ea);
  49. }
  50. void
  51. ea2lla(uint8_t *lla, uint8_t *ea)
  52. {
  53. *lla++ = 0xFE; /* link-local v6 */
  54. *lla++ = 0x80; /* " */
  55. memset(lla, 0, 6);
  56. ea2eui64(lla + 6, ea);
  57. }
  58. static void
  59. process(char *ether)
  60. {
  61. uint8_t ethaddr[6], ipaddr[IPaddrlen], ipv4[IPv4addrlen];
  62. if (parseether(ethaddr, ether) < 0)
  63. sysfatal("%s: not an ether address", ether);
  64. if (v4_6to4) {
  65. v4parseip(ipv4, v4_6to4);
  66. eaip26to4(ipaddr, ethaddr, ipv4);
  67. } else
  68. ea2lla(ipaddr, ethaddr);
  69. print("%I\n", ipaddr);
  70. }
  71. void
  72. main(int argc, char *argv[])
  73. {
  74. int i;
  75. ARGBEGIN {
  76. case 't':
  77. v4_6to4 = EARGF(usage());
  78. break;
  79. default:
  80. usage();
  81. break;
  82. } ARGEND
  83. fmtinstall('I', eipfmt);
  84. if (argc <= 0)
  85. usage();
  86. for (i = 0; i < argc; i++)
  87. process(argv[i]);
  88. exits(0);
  89. }