xref: /plan9/sys/src/cmd/ip/linklocal.c (revision 14cc0f535177405a84c5b73603a98e5db6674719)
1e47528f3SDavid du Colombier /*
24af5a9a1SDavid du Colombier  * linklocal - print ipv6 link-local or 6to4 address of a mac address.
34af5a9a1SDavid du Colombier  * eui is ieee's extended unique identifier, per rfc2373.
4e47528f3SDavid du Colombier  */
5e47528f3SDavid du Colombier 
6e47528f3SDavid du Colombier #include <u.h>
7e47528f3SDavid du Colombier #include <libc.h>
8e47528f3SDavid du Colombier #include <ip.h>
9e47528f3SDavid du Colombier 
104af5a9a1SDavid du Colombier enum {
114af5a9a1SDavid du Colombier 	Mac0mcast	= 1<<0,		/* multicast address */
124af5a9a1SDavid du Colombier 	Mac0localadm	= 1<<1,		/* locally-administered address, */
134af5a9a1SDavid du Colombier 	V60globaladm	= 1<<1,		/* but ipv6 reverses the meaning */
144af5a9a1SDavid du Colombier };
154af5a9a1SDavid du Colombier 
164af5a9a1SDavid du Colombier static char *v4_6to4;
174af5a9a1SDavid du Colombier 
184af5a9a1SDavid du Colombier static void
usage(void)194af5a9a1SDavid du Colombier usage(void)
204af5a9a1SDavid du Colombier {
214af5a9a1SDavid du Colombier 	fprint(2, "usage: %s [-t ipv4] ether...\n", argv0);
224af5a9a1SDavid du Colombier 	exits("usage");
234af5a9a1SDavid du Colombier }
244af5a9a1SDavid du Colombier 
254af5a9a1SDavid du Colombier void
ea2eui64(uchar * lla,uchar * ea)264af5a9a1SDavid du Colombier ea2eui64(uchar *lla, uchar *ea)
274af5a9a1SDavid du Colombier {
284af5a9a1SDavid du Colombier 	*lla++ = *ea++ | V60globaladm;	/* oui (company id) */
294af5a9a1SDavid du Colombier 	*lla++ = *ea++;			/* " */
304af5a9a1SDavid du Colombier 	*lla++ = *ea++;			/* " */
314af5a9a1SDavid du Colombier 	*lla++ = 0xFF;			/* mac-48 in eui-64 (sic) */
324af5a9a1SDavid du Colombier 	*lla++ = 0xFE;			/* " */
334af5a9a1SDavid du Colombier 	*lla++ = *ea++;			/* manufacturer-assigned */
344af5a9a1SDavid du Colombier 	*lla++ = *ea++;			/* " */
354af5a9a1SDavid du Colombier 	*lla = *ea;			/* " */
364af5a9a1SDavid du Colombier }
374af5a9a1SDavid du Colombier 
384af5a9a1SDavid du Colombier void
eaip26to4(uchar * lla,uchar * ea,uchar * ipv4)394af5a9a1SDavid du Colombier eaip26to4(uchar *lla, uchar *ea, uchar *ipv4)
404af5a9a1SDavid du Colombier {
414af5a9a1SDavid du Colombier 	*lla++ = 0x20;			/* 6to4 address */
424af5a9a1SDavid du Colombier 	*lla++ = 0x02;			/* " */
434af5a9a1SDavid du Colombier 	memmove(lla, ipv4, IPv4addrlen);
444af5a9a1SDavid du Colombier 	lla += IPv4addrlen;
454af5a9a1SDavid du Colombier 	memset(lla, 0, 2);
464af5a9a1SDavid du Colombier 	ea2eui64(lla + 2, ea);
474af5a9a1SDavid du Colombier }
484af5a9a1SDavid du Colombier 
49e47528f3SDavid du Colombier void
ea2lla(uchar * lla,uchar * ea)50e47528f3SDavid du Colombier ea2lla(uchar *lla, uchar *ea)
51e47528f3SDavid du Colombier {
524af5a9a1SDavid du Colombier 	*lla++ = 0xFE;			/* link-local v6 */
534af5a9a1SDavid du Colombier 	*lla++ = 0x80;			/* " */
544af5a9a1SDavid du Colombier 	memset(lla, 0, 6);
554af5a9a1SDavid du Colombier 	ea2eui64(lla + 6, ea);
56e47528f3SDavid du Colombier }
57e47528f3SDavid du Colombier 
58e47528f3SDavid du Colombier static void
process(char * ether)59e47528f3SDavid du Colombier process(char *ether)
60e47528f3SDavid du Colombier {
614af5a9a1SDavid du Colombier 	uchar ethaddr[6], ipaddr[IPaddrlen], ipv4[IPv4addrlen];
62e47528f3SDavid du Colombier 
63e47528f3SDavid du Colombier 	if (parseether(ethaddr, ether) < 0)
64*14cc0f53SDavid du Colombier 		sysfatal("%s: not an ether address", ether);
654af5a9a1SDavid du Colombier 	if (v4_6to4) {
664af5a9a1SDavid du Colombier 		v4parseip(ipv4, v4_6to4);
674af5a9a1SDavid du Colombier 		eaip26to4(ipaddr, ethaddr, ipv4);
684af5a9a1SDavid du Colombier 	} else
69e47528f3SDavid du Colombier 		ea2lla(ipaddr, ethaddr);
70e47528f3SDavid du Colombier 	print("%I\n", ipaddr);
71e47528f3SDavid du Colombier }
72e47528f3SDavid du Colombier 
73e47528f3SDavid du Colombier void
main(int argc,char * argv[])74e47528f3SDavid du Colombier main(int argc, char *argv[])
75e47528f3SDavid du Colombier {
764af5a9a1SDavid du Colombier 	int i;
77e47528f3SDavid du Colombier 
78e47528f3SDavid du Colombier 	ARGBEGIN {
794af5a9a1SDavid du Colombier 	case 't':
804af5a9a1SDavid du Colombier 		v4_6to4 = EARGF(usage());
814af5a9a1SDavid du Colombier 		break;
82e47528f3SDavid du Colombier 	default:
834af5a9a1SDavid du Colombier 		usage();
84e47528f3SDavid du Colombier 		break;
85e47528f3SDavid du Colombier 	} ARGEND
86e47528f3SDavid du Colombier 
87e47528f3SDavid du Colombier 	fmtinstall('I', eipfmt);
884af5a9a1SDavid du Colombier 	if (argc <= 0)
894af5a9a1SDavid du Colombier 		usage();
90e47528f3SDavid du Colombier 
91e47528f3SDavid du Colombier 	for (i = 0; i < argc; i++)
92e47528f3SDavid du Colombier 		process(argv[i]);
93e47528f3SDavid du Colombier 	exits(0);
94e47528f3SDavid du Colombier }
95