linklocal.c 1.7 KB

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