From dc4ae400ba93fa2cc9e6c9ceb988012aa8308033 Mon Sep 17 00:00:00 2001 From: Florian Obser Date: Sun, 19 Mar 2017 16:10:24 +0000 Subject: Get and display link local address, needed to generate addresses from a router advertisement. --- usr.sbin/slaacd/engine.c | 11 ++++++++- usr.sbin/slaacd/frontend.c | 51 +++++++++++++++++++++++++++--------------- usr.sbin/slaacd/slaacd.h | 4 +++- usr.sbin/slaacdctl/slaacdctl.c | 9 ++++++-- 4 files changed, 53 insertions(+), 22 deletions(-) (limited to 'usr.sbin') diff --git a/usr.sbin/slaacd/engine.c b/usr.sbin/slaacd/engine.c index 9ba7b4b6cca..5cc9d2568ea 100644 --- a/usr.sbin/slaacd/engine.c +++ b/usr.sbin/slaacd/engine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: engine.c,v 1.1 2017/03/18 17:33:13 florian Exp $ */ +/* $OpenBSD: engine.c,v 1.2 2017/03/19 16:10:23 florian Exp $ */ /* * Copyright (c) 2017 Florian Obser @@ -146,6 +146,7 @@ struct slaacd_iface { int running; int autoconfprivacy; struct ether_addr hw_address; + struct sockaddr_in6 ll_address; LIST_HEAD(, radv) radvs; }; @@ -354,6 +355,9 @@ engine_dispatch_frontend(int fd, short event, void *bula) memcpy(&iface->hw_address, &imsg_ifinfo.hw_address, sizeof(struct ether_addr)); + memcpy(&iface->ll_address, + &imsg_ifinfo.ll_address, + sizeof(struct sockaddr_in6)); LIST_INIT(&iface->radvs); LIST_INSERT_HEAD(&slaacd_interfaces, iface, entries); @@ -375,6 +379,9 @@ engine_dispatch_frontend(int fd, short event, void *bula) memcpy(&iface->hw_address, &imsg_ifinfo.hw_address, sizeof(struct ether_addr)); + memcpy(&iface->ll_address, + &imsg_ifinfo.ll_address, + sizeof(struct sockaddr_in6)); } break; case IMSG_REMOVE_IF: @@ -526,6 +533,8 @@ send_interface_info(struct slaacd_iface *iface, pid_t pid) cei.running = iface->running; cei.autoconfprivacy = iface->autoconfprivacy; memcpy(&cei.hw_address, &iface->hw_address, sizeof(struct ether_addr)); + memcpy(&cei.ll_address, &iface->ll_address, + sizeof(struct sockaddr_in6)); engine_imsg_compose_frontend(IMSG_CTL_SHOW_INTERFACE_INFO, pid, &cei, sizeof(cei)); LIST_FOREACH(ra, &iface->radvs, entries) { diff --git a/usr.sbin/slaacd/frontend.c b/usr.sbin/slaacd/frontend.c index 9596e1cf501..a6dee74849d 100644 --- a/usr.sbin/slaacd/frontend.c +++ b/usr.sbin/slaacd/frontend.c @@ -1,4 +1,4 @@ -/* $OpenBSD: frontend.c,v 1.1 2017/03/18 17:33:13 florian Exp $ */ +/* $OpenBSD: frontend.c,v 1.2 2017/03/19 16:10:23 florian Exp $ */ /* * Copyright (c) 2017 Florian Obser @@ -63,7 +63,7 @@ void route_receive(int, short, void *); void icmp6_receive(int, short, void *); int get_flags(char *); int get_xflags(char *); -int get_lladdr(char *, struct ether_addr *); +void get_lladdr(char *, struct ether_addr *, struct sockaddr_in6 *); void send_solicitation(uint32_t); struct imsgev *iev_main; @@ -498,8 +498,9 @@ frontend_startup(void) imsg_ifinfo.running = (flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING); imsg_ifinfo.autoconfprivacy = !(xflags & IFXF_INET6_NOPRIVACY); - if (get_lladdr(ifnidx->if_name, &imsg_ifinfo.hw_address) < 0) - fatal("cannot get lladdr"); + get_lladdr(ifnidx->if_name, &imsg_ifinfo.hw_address, + &imsg_ifinfo.ll_address); + frontend_imsg_compose_engine(IMSG_UPDATE_IF, 0, 0, &imsg_ifinfo, sizeof(imsg_ifinfo)); } @@ -578,34 +579,48 @@ route_receive(int fd, short events, void *arg) } } -int -get_lladdr(char *if_name, struct ether_addr *hw_address) +void +get_lladdr(char *if_name, struct ether_addr *mac, struct sockaddr_in6 *ll) { struct ifaddrs *ifap, *ifa; struct sockaddr_dl *sdl; + struct sockaddr_in6 *sin6; if (getifaddrs(&ifap) != 0) fatal("getifaddrs"); + memset(mac, 0, sizeof(*mac)); + memset(ll, 0, sizeof(*ll)); + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { if (strcmp(if_name, ifa->ifa_name) != 0) continue; - if (ifa->ifa_addr->sa_family != AF_LINK) - continue; - sdl = (struct sockaddr_dl *)ifa->ifa_addr; - if (sdl->sdl_type != IFT_ETHER || - sdl->sdl_alen != ETHER_ADDR_LEN) - continue; + switch(ifa->ifa_addr->sa_family) { + case AF_LINK: + sdl = (struct sockaddr_dl *)ifa->ifa_addr; + if (sdl->sdl_type != IFT_ETHER || + sdl->sdl_alen != ETHER_ADDR_LEN) + continue; - memcpy(hw_address->ether_addr_octet, LLADDR(sdl), - ETHER_ADDR_LEN); - freeifaddrs(ifap); - return (0); + memcpy(mac->ether_addr_octet, LLADDR(sdl), + ETHER_ADDR_LEN); + break; + case AF_INET6: + sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + sin6->sin6_scope_id = ntohs(*(u_int16_t *) + &sin6->sin6_addr.s6_addr[2]); + sin6->sin6_addr.s6_addr[2] = + sin6->sin6_addr.s6_addr[3] = 0; + memcpy(ll, sin6, sizeof(*ll)); + } + break; + default: + break; + } } - freeifaddrs(ifap); - return (-1); } void diff --git a/usr.sbin/slaacd/slaacd.h b/usr.sbin/slaacd/slaacd.h index b21c715782a..1ba21609c70 100644 --- a/usr.sbin/slaacd/slaacd.h +++ b/usr.sbin/slaacd/slaacd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: slaacd.h,v 1.2 2017/03/18 21:22:08 florian Exp $ */ +/* $OpenBSD: slaacd.h,v 1.3 2017/03/19 16:10:23 florian Exp $ */ /* * Copyright (c) 2017 Florian Obser @@ -78,6 +78,7 @@ struct ctl_engine_info { int running; int autoconfprivacy; struct ether_addr hw_address; + struct sockaddr_in6 ll_address; }; enum rpref { @@ -123,6 +124,7 @@ struct imsg_ifinfo { int running; int autoconfprivacy; struct ether_addr hw_address; + struct sockaddr_in6 ll_address; }; struct imsg_ra { diff --git a/usr.sbin/slaacdctl/slaacdctl.c b/usr.sbin/slaacdctl/slaacdctl.c index db55e128e0f..6b233ec1d81 100644 --- a/usr.sbin/slaacdctl/slaacdctl.c +++ b/usr.sbin/slaacdctl/slaacdctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: slaacdctl.c,v 1.1 2017/03/18 17:33:13 florian Exp $ */ +/* $OpenBSD: slaacdctl.c,v 1.2 2017/03/19 16:10:23 florian Exp $ */ /* * Copyright (c) 2005 Claudio Jeker @@ -192,7 +192,12 @@ show_interface_msg(struct imsg *imsg) printf("\t index: %3u ", cei->if_index); printf("running: %3s ", cei->running ? "yes" : "no"); printf("privacy: %3s\n", cei->autoconfprivacy ? "yes" : "no"); - printf("\tlladdr: %s\n", ether_ntoa(&cei->hw_address)); + printf("\tlladdr: %s\n", ether_ntoa(&cei->hw_address)); + if (getnameinfo((struct sockaddr *)&cei->ll_address, + cei->ll_address.sin6_len, hbuf, sizeof(hbuf), NULL, 0, + NI_NUMERICHOST | NI_NUMERICSERV)) + err(1, "cannot get link local address"); + printf("\t inet6: %s\n", hbuf); break; case IMSG_CTL_SHOW_INTERFACE_INFO_RA: cei_ra = imsg->data; -- cgit v1.2.3