/* * Set an individual neighbor cache entry */ int set(int argc, char **argv) { struct sockaddr_in6 *sin = &sin_m; struct sockaddr_dl *sdl; 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; bzero(&hints, sizeof(hints)); hints.ai_family = AF_INET6; gai_error = getaddrinfo(host, NULL, &hints, &res); if (gai_error) { fprintf(stderr, "ndp: %s: %s\n", host, gai_strerror(gai_error)); return 1; } sin->sin6_addr = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; #ifdef __KAME__ if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr)) { *(u_int16_t *)&sin->sin6_addr.s6_addr[2] = htons(((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id); } #endif ea = (u_char *)LLADDR(&sdl_m); if (ndp_ether_aton(eaddr, ea) == 0) sdl_m.sdl_alen = 6; flags = 0; expire_time = 0; while (argc-- > 0) { if (strncmp(argv[0], "temp", 4) == 0) { struct timespec sp; clock_gettime(CLOCK_MONOTONIC, &sp); expire_time = sp.tv_sec + 20 * 60; } else if (strncmp(argv[0], "proxy", 5) == 0) flags |= RTF_ANNOUNCE; argv++; } if (rtmsg(RTM_GET) < 0) { perror(host); return (1); } sin = (struct sockaddr_in6 *)(rtm + 1); sdl = (struct sockaddr_dl *)(RT_ROUNDUP(sin->sin6_len) + (char *)sin); if (IN6_ARE_ADDR_EQUAL(&sin->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. */ fprintf(stderr, "set: cannot configure a new entry\n"); return 1; } overwrite: if (sdl->sdl_family != AF_LINK) { printf("cannot intuit interface index and type for %s\n", host); return (1); } sdl_m.sdl_type = sdl->sdl_type; sdl_m.sdl_index = sdl->sdl_index; return (rtmsg(RTM_ADD)); }
/* * Set an individual arp entry */ int arptab_set(u_char *eaddr, u_int32_t host) { struct sockaddr_inarp *sin = &sin_m; struct rt_msghdr *rtm = &(m_rtmsg.m_rtm); struct sockaddr_dl *sdl; struct timeval now; int rt; getsocket(); pid = getpid(); sdl_m = blank_sdl; sin_m = blank_sin; sin->sin_addr.s_addr = host; memcpy((u_char *)LLADDR(&sdl_m), (char *)eaddr, 6); sdl_m.sdl_alen = 6; expire_time = 0; doing_proxy = flags = export_only = 0; gettimeofday(&now, 0); expire_time = now.tv_sec + 20 * 60; tryagain: if (rtmsg(RTM_GET) < 0) { syslog(LOG_ERR,"%s: %m", inet_ntoa(sin->sin_addr)); close(s); s = -1; return (1); } sin = (struct sockaddr_inarp *)((char *)rtm + rtm->rtm_hdrlen); sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin); if (sin->sin_addr.s_addr == sin_m.sin_addr.s_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; default: break; } if (doing_proxy == 0) { syslog(LOG_ERR, "arptab_set: can only proxy for %s", inet_ntoa(sin->sin_addr)); close(s); s = -1; return (1); } if (sin_m.sin_other & SIN_PROXY) { syslog(LOG_ERR, "arptab_set: proxy entry exists for non 802 device"); close(s); s = -1; return(1); } sin_m.sin_other = SIN_PROXY; export_only = 1; goto tryagain; } overwrite: if (sdl->sdl_family != AF_LINK) { syslog(LOG_ERR, "arptab_set: cannot intuit interface index and type for %s", inet_ntoa(sin->sin_addr)); close(s); s = -1; return (1); } sdl_m.sdl_type = sdl->sdl_type; sdl_m.sdl_index = sdl->sdl_index; rt = rtmsg(RTM_ADD); close(s); s = -1; return (rt); }
/* * Set an individual arp entry */ int set(int argc, char *argv[]) { struct sockaddr_inarp *sin; struct sockaddr_dl *sdl; struct rt_msghdr *rtm; char *eaddr = argv[1], *host = argv[0]; struct ether_addr *ea; sin = &sin_m; rtm = &(m_rtmsg.m_rtm); getsocket(); argc -= 2; argv += 2; sdl_m = blank_sdl; /* struct copy */ sin_m = blank_sin; /* struct copy */ if (getinetaddr(host, &sin->sin_addr) == -1) return (1); ea = ether_aton(eaddr); if (ea == NULL) errx(1, "invalid ethernet address: %s", eaddr); memcpy(LLADDR(&sdl_m), ea, sizeof(*ea)); sdl_m.sdl_alen = 6; expire_time = 0; doing_proxy = flags = export_only = 0; while (argc-- > 0) { if (strncmp(argv[0], "temp", 4) == 0) { struct timeval now; gettimeofday(&now, 0); expire_time = now.tv_sec + 20 * 60; if (flags & RTF_PERMANENT_ARP) { /* temp or permanent, not both */ usage(); return (0); } } else if (strncmp(argv[0], "pub", 3) == 0) { flags |= RTF_ANNOUNCE; doing_proxy = SIN_PROXY; } else if (strncmp(argv[0], "permanent", 9) == 0) { flags |= RTF_PERMANENT_ARP; if (expire_time != 0) { /* temp or permanent, not both */ usage(); return (0); } } argv++; } tryagain: if (rtget(&sin, &sdl)) { warn("%s", host); return (1); } if (sin->sin_addr.s_addr == sin_m.sin_addr.s_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: case IFT_CARP: goto overwrite; } if (doing_proxy == 0) { printf("set: can only proxy for %s\n", host); return (1); } if (sin_m.sin_other & SIN_PROXY) { printf("set: proxy entry exists for non 802 device\n"); return (1); } sin_m.sin_other = SIN_PROXY; export_only = 1; goto tryagain; } overwrite: if (sdl->sdl_family != AF_LINK) { printf("cannot intuit interface index and type for %s\n", host); return (1); } sdl_m.sdl_type = sdl->sdl_type; sdl_m.sdl_index = sdl->sdl_index; return (rtmsg(RTM_ADD)); }
/* * Set an individual neighbor cache entry */ static int set(int argc, char **argv) { register struct sockaddr_in6 *sin = &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; bzero(&hints, sizeof(hints)); hints.ai_family = AF_INET6; gai_error = getaddrinfo(host, NULL, &hints, &res); if (gai_error) { fprintf(stderr, "ndp: %s: %s\n", host, gai_strerror(gai_error)); return 1; } sin->sin6_addr = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; sin->sin6_scope_id = ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id; 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 now; gettimeofday(&now, 0); expire_time = now.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 */ } sin = (struct sockaddr_in6 *)(rtm + 1); sdl = (struct sockaddr_dl *)(ALIGN(sin->sin6_len) + (char *)sin); if (IN6_ARE_ADDR_EQUAL(&sin->sin6_addr, &sin_m.sin6_addr)) { if (sdl->sdl_family == AF_LINK && !(rtm->rtm_flags & RTF_GATEWAY)) { switch (sdl->sdl_type) { case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023: case IFT_ISO88024: case IFT_ISO88025: case IFT_L2VLAN: case IFT_BRIDGE: goto overwrite; } } fprintf(stderr, "set: cannot configure a new entry\n"); return 1; } overwrite: if (sdl->sdl_family != AF_LINK) { printf("cannot intuit interface index and type for %s\n", host); return (1); } sdl_m.sdl_type = sdl->sdl_type; sdl_m.sdl_index = sdl->sdl_index; return (rtmsg(RTM_ADD)); }
/* * Set an individual arp entry */ static int set(int argc, char **argv) { struct sockaddr_in *addr; struct sockaddr_in *dst; /* what are we looking for */ struct sockaddr_dl *sdl; struct rt_msghdr *rtm; struct ether_addr *ea; char *host = argv[0], *eaddr = argv[1]; struct sockaddr_dl sdl_m; argc -= 2; argv += 2; bzero(&sdl_m, sizeof(sdl_m)); sdl_m.sdl_len = sizeof(sdl_m); sdl_m.sdl_family = AF_LINK; dst = getaddr(host); if (dst == NULL) return (1); doing_proxy = flags = expire_time = 0; while (argc-- > 0) { if (strncmp(argv[0], "temp", 4) == 0) { struct timespec tp; int max_age; size_t len = sizeof(max_age); clock_gettime(CLOCK_MONOTONIC, &tp); if (sysctlbyname("net.link.ether.inet.max_age", &max_age, &len, NULL, 0) != 0) err(1, "sysctlbyname"); expire_time = tp.tv_sec + max_age; } else if (strncmp(argv[0], "pub", 3) == 0) { flags |= RTF_ANNOUNCE; doing_proxy = 1; if (argc && strncmp(argv[1], "only", 3) == 0) { /* * Compatibility: in pre FreeBSD 8 times * the "only" keyword used to mean that * an ARP entry should be announced, but * not installed into routing table. */ argc--; argv++; } } else if (strncmp(argv[0], "blackhole", 9) == 0) { if (flags & RTF_REJECT) { printf("Choose one of blackhole or reject, not both.\n"); } flags |= RTF_BLACKHOLE; } else if (strncmp(argv[0], "reject", 6) == 0) { if (flags & RTF_BLACKHOLE) { printf("Choose one of blackhole or reject, not both.\n"); } flags |= RTF_REJECT; } else if (strncmp(argv[0], "trail", 5) == 0) { /* XXX deprecated and undocumented feature */ printf("%s: Sending trailers is no longer supported\n", host); } argv++; } ea = (struct ether_addr *)LLADDR(&sdl_m); if (doing_proxy && !strcmp(eaddr, "auto")) { if (!get_ether_addr(dst->sin_addr.s_addr, ea)) { printf("no interface found for %s\n", inet_ntoa(dst->sin_addr)); return (1); } sdl_m.sdl_alen = ETHER_ADDR_LEN; } else { struct ether_addr *ea1 = ether_aton(eaddr); if (ea1 == NULL) { warnx("invalid Ethernet address '%s'", eaddr); return (1); } else { *ea = *ea1; sdl_m.sdl_alen = ETHER_ADDR_LEN; } } /* * In the case a proxy-arp entry is being added for * a remote end point, the RTF_ANNOUNCE flag in the * RTM_GET command is an indication to the kernel * routing code that the interface associated with * the prefix route covering the local end of the * PPP link should be returned, on which ARP applies. */ rtm = rtmsg(RTM_GET, dst, &sdl_m); if (rtm == NULL) { warn("%s", host); return (1); } addr = (struct sockaddr_in *)(rtm + 1); sdl = (struct sockaddr_dl *)(SA_SIZE(addr) + (char *)addr); if ((sdl->sdl_family != AF_LINK) || (rtm->rtm_flags & RTF_GATEWAY) || !valid_type(sdl->sdl_type)) { printf("cannot intuit interface index and type for %s\n", host); return (1); } sdl_m.sdl_type = sdl->sdl_type; sdl_m.sdl_index = sdl->sdl_index; return (rtmsg(RTM_ADD, dst, &sdl_m) == NULL); }
/* * Set an individual arp entry */ int bsd_arp_set(struct in_addr *ia, char *eaddr, int len) { struct sockaddr_inarp *sin = &sin_m; struct sockaddr_dl *sdl; struct rt_msghdr *rtm = &(m_rtmsg.m_rtm); u_char *ea; struct timeval time; int op = RTM_ADD; getsocket(); sdl_m = blank_sdl; sin_m = blank_sin; sin->sin_addr = *ia; ea = (u_char *)LLADDR(&sdl_m); bcopy(eaddr, ea, len); sdl_m.sdl_alen = len; doing_proxy = flags = export_only = expire_time = 0; /* make arp entry temporary */ gettimeofday(&time, 0); expire_time = time.tv_sec + 20 * 60; tryagain: if (rtmsg(RTM_GET) < 0) { report(LOG_WARNING, "rtmget: %s", strerror(errno)); return (1); } sin = (struct sockaddr_inarp *)(rtm + 1); sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin); if (sin->sin_addr.s_addr == sin_m.sin_addr.s_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: op = RTM_CHANGE; goto overwrite; } if (doing_proxy == 0) { report(LOG_WARNING, "set: can only proxy for %s\n", inet_ntoa(sin->sin_addr)); return (1); } if (sin_m.sin_other & SIN_PROXY) { report(LOG_WARNING, "set: proxy entry exists for non 802 device\n"); return(1); } sin_m.sin_other = SIN_PROXY; export_only = 1; goto tryagain; } overwrite: if (sdl->sdl_family != AF_LINK) { report(LOG_WARNING, "cannot intuit interface index and type for %s\n", inet_ntoa(sin->sin_addr)); return (1); } sdl_m.sdl_type = sdl->sdl_type; sdl_m.sdl_index = sdl->sdl_index; return (rtmsg(op)); }
/* * 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)); }
/* * Set an individual arp entry */ static int set(int argc, char **argv) { struct sockaddr_inarp *sina; struct sockaddr_dl *sdl; struct rt_msghdr *rtm; char *host = argv[0], *eaddr; struct sockaddr_inarp sin_m = blank_sin; /* struct copy */ struct sockaddr_dl sdl_m = blank_sdl; /* struct copy */ int s; eaddr = argv[1]; s = getsocket(); argc -= 2; argv += 2; if (getinetaddr(host, &sin_m.sin_addr) == -1) return (1); if (atosdl(eaddr, &sdl_m)) warnx("invalid link-level address '%s'", eaddr); doing_proxy = flags = export_only = expire_time = 0; for (; argc-- > 0; argv++) { if (strncmp(argv[0], "temp", 4) == 0) { struct timeval timev; (void)gettimeofday(&timev, 0); expire_time = timev.tv_sec + 20 * 60; } else if (strncmp(argv[0], "pub", 3) == 0) { flags |= RTF_ANNOUNCE; doing_proxy = SIN_PROXY; if (argc && strncmp(argv[1], "pro", 3) == 0) { export_only = 1; argc--; argv++; } } else if (strncmp(argv[0], "trail", 5) == 0) { warnx("%s: Sending trailers is no longer supported", host); } else if (strcmp(argv[0], "ifscope") == 0) { if (argc == 0) { warnx("missing interface for ifscope"); continue; } argc--; argv++; if (!getlink(argv[0], &sdl_m)) warnx("cannot get link address for %s", argv[0]); } } if (memcmp(&sdl_m, &blank_sdl, sizeof(blank_sdl))) goto out; tryagain: rtm = rtmsg(s, RTM_GET, &sin_m, &sdl_m); if (rtm == NULL) { warn("%s", host); return (1); } sina = (struct sockaddr_inarp *)(void *)(rtm + 1); sdl = (struct sockaddr_dl *)(void *)(RT_ROUNDUP(sina->sin_len) + (char *)(void *)sina); if (sina->sin_addr.s_addr == sin_m.sin_addr.s_addr) { if (is_llinfo(sdl, rtm->rtm_flags)) goto overwrite; if (doing_proxy == 0) { warnx("set: can only proxy for %s", host); return (1); } if (sin_m.sin_other & SIN_PROXY) { warnx("set: proxy entry exists for non 802 device"); return (1); } sin_m.sin_other = SIN_PROXY; export_only = 1; goto tryagain; } 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; out: sin_m.sin_other = 0; if (doing_proxy && export_only) sin_m.sin_other = SIN_PROXY; rtm = rtmsg(s, RTM_ADD, &sin_m, &sdl_m); if (vflag) (void)printf("%s (%s) added\n", host, eaddr); return (rtm == NULL) ? 1 : 0; }
/* * Set an individual arp entry */ int set(int argc, char **argv) { struct hostent *hp; struct sockaddr_inarp *addr = &sin_m; struct sockaddr_dl *sdl; struct rt_msghdr *rtm = &(m_rtmsg.m_rtm); struct ether_addr *ea; char *host = argv[0], *eaddr = argv[1]; getsocket(); argc -= 2; argv += 2; sdl_m = blank_sdl; sin_m = blank_sin; addr->sin_addr.s_addr = inet_addr(host); if (addr->sin_addr.s_addr == INADDR_NONE) { if (!(hp = gethostbyname(host))) { warnx("%s: %s", host, hstrerror(h_errno)); return(1); } bcopy((char *)hp->h_addr, (char *)&addr->sin_addr, sizeof(addr->sin_addr)); } doing_proxy = flags = proxy_only = expire_time = 0; while (argc-- > 0) { if (strncmp(argv[0], "temp", 4) == 0) { struct timeval tv; gettimeofday(&tv, 0); expire_time = tv.tv_sec + 20 * 60; } else if (strncmp(argv[0], "pub", 3) == 0) { flags |= RTF_ANNOUNCE; doing_proxy = 1; if (argc && strncmp(argv[1], "only", 3) == 0) { proxy_only = 1; sin_m.sin_other = SIN_PROXY; argc--; argv++; } } else if (strncmp(argv[0], "trail", 5) == 0) { printf("%s: Sending trailers is no longer supported\n", host); } argv++; } ea = (struct ether_addr *)LLADDR(&sdl_m); if (doing_proxy && !strcmp(eaddr, "auto")) { if (!get_ether_addr(addr->sin_addr.s_addr, ea)) { printf("no interface found for %s\n", inet_ntoa(addr->sin_addr)); return(1); } sdl_m.sdl_alen = ETHER_ADDR_LEN; } else { if (my_ether_aton(eaddr, ea) == 0) sdl_m.sdl_alen = ETHER_ADDR_LEN; } tryagain: if (rtmsg(RTM_GET) < 0) { warn("%s", host); return(1); } addr = (struct sockaddr_inarp *)(rtm + 1); sdl = (struct sockaddr_dl *)(ROUNDUP(addr->sin_len) + (char *)addr); if (addr->sin_addr.s_addr == sin_m.sin_addr.s_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: case IFT_L2VLAN: case IFT_CARP: goto overwrite; } if (doing_proxy == 0) { printf("set: can only proxy for %s\n", host); return(1); } if (sin_m.sin_other & SIN_PROXY) { printf("set: proxy entry exists for non 802 device\n"); return(1); } sin_m.sin_other = SIN_PROXY; proxy_only = 1; goto tryagain; } overwrite: if (sdl->sdl_family != AF_LINK) { printf("cannot intuit interface index and type for %s\n", host); return(1); } sdl_m.sdl_type = sdl->sdl_type; sdl_m.sdl_index = sdl->sdl_index; return(rtmsg(RTM_ADD)); }