static int settunnel(prop_dictionary_t env, prop_dictionary_t oenv) { const struct paddr_prefix *srcpfx, *dstpfx; struct if_laddrreq req; prop_data_t srcdata, dstdata; srcdata = (prop_data_t)prop_dictionary_get(env, "tunsrc"); dstdata = (prop_data_t)prop_dictionary_get(env, "tundst"); if (srcdata == NULL || dstdata == NULL) { warnx("%s.%d", __func__, __LINE__); errno = ENOENT; return -1; } srcpfx = prop_data_data_nocopy(srcdata); dstpfx = prop_data_data_nocopy(dstdata); if (srcpfx->pfx_addr.sa_family != dstpfx->pfx_addr.sa_family) errx(EXIT_FAILURE, "source and destination address families do not match"); memset(&req, 0, sizeof(req)); memcpy(&req.addr, &srcpfx->pfx_addr, MIN(sizeof(req.addr), srcpfx->pfx_addr.sa_len)); memcpy(&req.dstaddr, &dstpfx->pfx_addr, MIN(sizeof(req.dstaddr), dstpfx->pfx_addr.sa_len)); #ifdef INET6 if (req.addr.ss_family == AF_INET6) { struct sockaddr_in6 *s6, *d; s6 = (struct sockaddr_in6 *)&req.addr; d = (struct sockaddr_in6 *)&req.dstaddr; if (s6->sin6_scope_id != d->sin6_scope_id) { errx(EXIT_FAILURE, "scope mismatch"); /* NOTREACHED */ } if (IN6_IS_ADDR_MULTICAST(&d->sin6_addr) || IN6_IS_ADDR_MULTICAST(&s6->sin6_addr)) errx(EXIT_FAILURE, "tunnel src/dst is multicast"); /* embed scopeid */ inet6_putscopeid(s6, INET6_IS_ADDR_LINKLOCAL); inet6_putscopeid(d, INET6_IS_ADDR_LINKLOCAL); } #endif /* INET6 */ if (direct_ioctl(env, SIOCSLIFPHYADDR, &req) == -1) warn("SIOCSLIFPHYADDR"); return 0; }
/* * Display an individual neighbor cache entry */ static void get(char *host) { struct sockaddr_in6 *mysin = &sin_m; struct addrinfo hints, *res; int gai_error; sin_m = blank_sin; (void)memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; gai_error = getaddrinfo(host, NULL, &hints, &res); if (gai_error) { warnx("%s: %s\n", host, gai_strerror(gai_error)); return; } mysin->sin6_addr = ((struct sockaddr_in6 *)(void *)res->ai_addr)->sin6_addr; inet6_putscopeid(mysin, INET6_IS_ADDR_LINKLOCAL); dump(&mysin->sin6_addr, 0); if (found_entry == 0) { (void)getnameinfo((struct sockaddr *)(void *)mysin, (socklen_t)mysin->sin6_len, host_buf, sizeof(host_buf), NULL ,0, (nflag ? NI_NUMERICHOST : 0)); errx(1, "%s (%s) -- no entry", host, host_buf); } }
static void makeaddr(struct sockaddr_in6 *mysin, const void *resp) { const struct sockaddr_in6 *res = resp; mysin->sin6_addr = res->sin6_addr; mysin->sin6_scope_id = res->sin6_scope_id; inet6_putscopeid(mysin, INET6_IS_ADDR_LINKLOCAL); }
/* * Set an individual neighbor cache entry */ static int set(int argc, char **argv) { register struct sockaddr_in6 *mysin = &sin_m; register struct sockaddr_dl *sdl; register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm); struct addrinfo hints, *res; int gai_error; u_char *ea; char *host = argv[0], *eaddr = argv[1]; getsocket(); argc -= 2; argv += 2; sdl_m = blank_sdl; sin_m = blank_sin; (void)memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; gai_error = getaddrinfo(host, NULL, &hints, &res); if (gai_error) { warnx("%s: %s\n", host, gai_strerror(gai_error)); return 1; } mysin->sin6_addr = ((struct sockaddr_in6 *)(void *)res->ai_addr)->sin6_addr; inet6_putscopeid(mysin, INET6_IS_ADDR_LINKLOCAL); ea = (u_char *)LLADDR(&sdl_m); if (ndp_ether_aton(eaddr, ea) == 0) sdl_m.sdl_alen = 6; flags = expire_time = 0; while (argc-- > 0) { if (strncmp(argv[0], "temp", 4) == 0) { struct timeval tim; (void)gettimeofday(&tim, 0); expire_time = tim.tv_sec + 20 * 60; } else if (strncmp(argv[0], "proxy", 5) == 0) flags |= RTF_ANNOUNCE; argv++; } if (rtmsg(RTM_GET) < 0) { errx(1, "RTM_GET(%s) failed", host); /* NOTREACHED */ } mysin = (struct sockaddr_in6 *)(void *)(rtm + 1); sdl = (struct sockaddr_dl *)(void *)(RT_ROUNDUP(mysin->sin6_len) + (char *)(void *)mysin); if (IN6_ARE_ADDR_EQUAL(&mysin->sin6_addr, &sin_m.sin6_addr)) { if (sdl->sdl_family == AF_LINK && (rtm->rtm_flags & RTF_LLINFO) && !(rtm->rtm_flags & RTF_GATEWAY)) { switch (sdl->sdl_type) { case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023: case IFT_ISO88024: case IFT_ISO88025: goto overwrite; } } /* * IPv4 arp command retries with sin_other = SIN_PROXY here. */ (void)fprintf(stderr, "set: cannot configure a new entry\n"); return 1; } overwrite: if (sdl->sdl_family != AF_LINK) { warnx("cannot intuit interface index and type for %s", host); return (1); } sdl_m.sdl_type = sdl->sdl_type; sdl_m.sdl_index = sdl->sdl_index; return (rtmsg(RTM_ADD)); }