Ejemplo n.º 1
0
static void             
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
{
    int		i;

    for (i = 0; i < RTAX_MAX; i++) {
	if (addrs & (1 << i)) {
	    rti_info[i] = sa;
	    sa = (struct sockaddr *)((char *)(sa) + RT_ROUNDUP(sa->sa_len));
	} else
	    rti_info[i] = NULL;
    }
}
Ejemplo n.º 2
0
void
iface_ParseHdr(struct ifa_msghdr *ifam, struct sockaddr *sa[RTAX_MAX])
{
  char *wp;
  int rtax;

  wp = (char *)(ifam + 1);

  for (rtax = 0; rtax < RTAX_MAX; rtax++)
    if (ifam->ifam_addrs & (1 << rtax)) {
      sa[rtax] = (struct sockaddr *)wp;
      wp += RT_ROUNDUP(sa[rtax]->sa_len);
    } else
      sa[rtax] = NULL;
}
Ejemplo n.º 3
0
/*
 * 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));
}
Ejemplo n.º 4
0
/**
 *
 * @retval  0 no errors
 * @retval !0 errors
 */
static int
_load_defaultrouter_from_sysctl(netsnmp_container *container, int family)
{
    netsnmp_defaultrouter_entry *entry;
    struct rt_msghdr *rtm;
    struct sockaddr *dst_sa, *gw_sa;
    char *buf, *lim, *newbuf, *next;
    char address[NETSNMP_ACCESS_DEFAULTROUTER_BUF_SIZE + 1];
    int mib[6];
    size_t address_len, needed;
    int address_type, err, preference, st;

    netsnmp_assert(NULL != container);

    mib[0] = CTL_NET;
    mib[1] = PF_ROUTE;
    mib[2] = 0;
    mib[3] = family;
    mib[4] = NET_RT_DUMP;
    mib[5] = 0;

    err = 0;

    buf = newbuf = NULL;

    if (family == AF_INET) {
        address_len = 4;
        address_type = INETADDRESSTYPE_IPV4;
#ifdef NETSNMP_ENABLE_IPV6
    } else if (family == AF_INET6) {
        address_len = 16;
        address_type = INETADDRESSTYPE_IPV6;
#endif
    } else {
        err = EINVAL;
        goto out;
    }

    if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
        err = errno;
        goto out;
    }

    /* Empty arp table. */
    if (needed == 0)
        goto out;

    for (;;) {
        newbuf = realloc(buf, needed);
        if (newbuf == NULL) {
            err = ENOMEM;
            goto out;
        }
        buf = newbuf;
        st = sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &needed, NULL, 0);
        if (st == 0 || errno != ENOMEM)
            break;
        else
            needed += needed / 8; /* XXX: why 8? */
    }
    if (st == -1) {
        err = errno;
        goto out;
    }

    lim = buf + needed;
    for (next = buf; next < lim; next += rtm->rtm_msglen) {
#ifdef NETSNMP_ENABLE_IPV6
	struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
#endif

        rtm = (struct rt_msghdr *)next;

        if (!(rtm->rtm_addrs & RTA_GATEWAY))
            continue;

        dst_sa = (struct sockaddr*)(rtm + 1);
#ifdef SA_SIZE
        gw_sa = (struct sockaddr*)(SA_SIZE(dst_sa) + (char*)dst_sa);
#else
        gw_sa = (struct sockaddr*)(RT_ROUNDUP(dst_sa->sa_len) + (char*)dst_sa);
#endif

        switch (family) {
        case AF_INET:
            if (((struct sockaddr_in*)dst_sa)->sin_addr.s_addr != INADDR_ANY)
                continue;
	    memcpy(address, &((struct sockaddr_in*)gw_sa)->sin_addr.s_addr,
	           address_len);
            break;
#ifdef NETSNMP_ENABLE_IPV6
        case AF_INET6:
            if (memcmp(((struct sockaddr_in6*)dst_sa)->sin6_addr.s6_addr,
			&in6addr_any, sizeof in6addr_any) != 0)
		continue; /* XXX: need to determine qualifying criteria for
                       * default gateways in IPv6. */
            memcpy(address, &((struct sockaddr_in6*)dst_sa)->sin6_addr.s6_addr,
		   address_len);
            break;
#endif
        default:
            break;
        }

        entry = netsnmp_access_defaultrouter_entry_create();
        if (NULL == entry) {
            err = ENOMEM;
            break;
        }

        /* XXX: this is wrong (hardcoding the router preference to medium). */
        preference = 0;

        entry->ns_dr_index    = ++idx_offset;
        entry->dr_addresstype = address_type;
        entry->dr_address_len = address_len;
        memcpy(entry->dr_address, address, sizeof(address));
        entry->dr_if_index = rtm->rtm_index;
        entry->dr_lifetime    = rtm->rtm_rmx.rmx_expire;
        entry->dr_preference  = preference;

        if (CONTAINER_INSERT(container, entry) < 0) {
            DEBUGMSGTL(("access:arp:container",
                        "error with defaultrouter_entry: "
                        "insert into container failed.\n"));
            netsnmp_access_defaultrouter_entry_free(entry);
            goto out;
        }
    }

out:
    free(buf);
    return err;
}
Ejemplo n.º 5
0
/*
 * 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));
}
Ejemplo n.º 6
0
static int
_load_ndp_table_from_sysctl(netsnmp_arp_access *access)
{
#if 1
    netsnmp_arp_entry *entry;
    struct rt_msghdr *rtm;
    struct sockaddr_in6 *sin2;
    struct sockaddr_dl *sdl;
    size_t needed;
    int err, mib[6], st;
    char *buf, *lim, *newbuf, *next;

    netsnmp_assert(NULL != access);

    mib[0] = CTL_NET;
    mib[1] = PF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_INET6;
    mib[4] = NET_RT_FLAGS;
    mib[5] = RTF_LLINFO;

    err = 0;
    buf = newbuf = NULL;

    if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
        err = errno;
        goto out;
    }

    /* Empty arp table. */
    if (needed == 0)
        goto out;

    for (;;) {
        newbuf = realloc(buf, needed);
        if (newbuf == NULL) {
            err = ENOMEM;
            goto out;
        }
        buf = newbuf;
        st = sysctl(mib, 6, buf, &needed, NULL, 0);
        if (st == 0 || errno != ENOMEM)
            break;
        else
            needed += needed / 8; /* XXX: why 8? */
    }
    if (st == -1) {
        err = errno;
        goto out;
    }

    lim = buf + needed;
    for (next = buf; next < lim; next += rtm->rtm_msglen) {

        rtm = (struct rt_msghdr *)next;
        sin2 = (struct sockaddr_in6*)(rtm + 1);
#ifdef SA_SIZE
        sdl = (struct sockaddr_dl*)((char *)sin2 + SA_SIZE(sin2));
#else
	sdl = (struct sockaddr_dl*)(void *)(RT_ROUNDUP(sin2->sin6_len) + (char *)(void *)sin2);
#endif

        if (!(rtm->rtm_flags & RTF_HOST) ||
            IN6_IS_ADDR_MULTICAST(&sin2->sin6_addr))
            continue;

        entry = netsnmp_access_arp_entry_create();
        if (NULL == entry) {
            err = ENOMEM;
            break;
        }

        entry->generation = access->generation;
        entry->if_index = rtm->rtm_index;

        entry->arp_ipaddress_len = 16;

        memcpy(entry->arp_ipaddress, &sin2->sin6_addr.s6_addr,
            entry->arp_ipaddress_len);

        /* HW Address */
        entry->arp_physaddress_len = sdl->sdl_alen;
        if (0 < sdl->sdl_alen &&
            sdl->sdl_alen <= NETSNMP_ACCESS_ARP_PHYSADDR_BUF_SIZE) {
            memcpy(entry->arp_physaddress, LLADDR(sdl), sdl->sdl_alen);
            /* Process status */
            /* XXX: setting this value for all states is wrong. */
            entry->arp_state = INETNETTOMEDIASTATE_REACHABLE;
        } else {
            entry->arp_physaddress[0] = '\0';
            entry->arp_state = INETNETTOMEDIASTATE_INCOMPLETE;
        }

        /* Process type */
        /* XXX: more states should be handled here, probably.. */
        if (rtm->rtm_rmx.rmx_expire == 0)
            entry->arp_type = INETNETTOMEDIATYPE_STATIC;
        else
            entry->arp_type = INETNETTOMEDIATYPE_DYNAMIC;

        access->update_hook(access, entry);

    }

out:
    free(buf);
    return err;
#else
    return 0;
#endif
}
Ejemplo n.º 7
0
/*
 * 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;
}
/*
 * Issue a modifying routing command, which must be one of RTM_ADD, RTM_CHANGE,
 * RTM_DELETE, or RTM_LOCK.  The destination address (IPv4 or IPv6) and netmask
 * prefix are required.  The flags (RTF_), interface name, and gateway are
 * optional depending on the command (and flags) being issued.  Return 0 on
 * success, and -1 with errno set on failure.
 */
static int
test93_route_cmd(int cmd, const struct sockaddr * dest, socklen_t dest_len,
	unsigned int prefix, int flags, const char * ifname,
	const struct sockaddr * gw, socklen_t gw_len)
{
	static unsigned int seq = 0;
	struct sockaddr_storage destss, maskss, ifpss, gwss;
	struct sockaddr_in mask4;
	struct sockaddr_in6 mask6;
	struct sockaddr_dl ifp;
	struct rt_msghdr rtm;
	struct iovec iov[5];
	struct msghdr msg;
	unsigned int i, iovlen;
	int r, fd, err;

	memset(&rtm, 0, sizeof(rtm));
	rtm.rtm_version = RTM_VERSION;
	rtm.rtm_type = cmd;
	rtm.rtm_flags = flags;
	rtm.rtm_addrs = RTA_DST | RTA_NETMASK;
	rtm.rtm_seq = ++seq;

	iovlen = 0;
	iov[iovlen].iov_base = &rtm;
	iov[iovlen++].iov_len = sizeof(rtm);

	memset(&destss, 0, sizeof(destss));
	memcpy(&destss, dest, dest_len);
	destss.ss_len = dest_len;

	iov[iovlen].iov_base = &destss;
	iov[iovlen++].iov_len = RT_ROUNDUP(dest_len);

	/* Do this in RTA order. */
	memset(&gwss, 0, sizeof(gwss));
	if (gw != NULL) {
		memcpy(&gwss, gw, gw_len);
		gwss.ss_len = gw_len;

		rtm.rtm_addrs |= RTA_GATEWAY;
		iov[iovlen].iov_base = &gwss;
		iov[iovlen++].iov_len = RT_ROUNDUP(gwss.ss_len);
	}

	memset(&maskss, 0, sizeof(maskss));
	switch (dest->sa_family) {
	case AF_INET:
		if (prefix > 32) e(0);
		memset(&mask4, 0, sizeof(mask4));
		mask4.sin_family = AF_INET;
		if (prefix < 32)
			mask4.sin_addr.s_addr = htonl(0xffffffffUL << prefix);

		memcpy(&maskss, &mask4, sizeof(mask4));
		maskss.ss_len = sizeof(mask4);

		break;

	case AF_INET6:
		test93_make_netmask6(&mask6, prefix);

		memcpy(&maskss, &mask6, sizeof(mask6));
		maskss.ss_len = sizeof(mask6);

		break;

	default:
		e(0);
	}

	iov[iovlen].iov_base = &maskss;
	iov[iovlen++].iov_len = RT_ROUNDUP(maskss.ss_len);

	if (ifname != NULL) {
		memset(&ifp, 0, sizeof(ifp));
		ifp.sdl_nlen = strlen(ifname);
		ifp.sdl_len = offsetof(struct sockaddr_dl, sdl_data) +
		    ifp.sdl_nlen;
		ifp.sdl_family = AF_LINK;

		memset(&ifpss, 0, sizeof(ifpss));
		memcpy(&ifpss, &ifp, ifp.sdl_len);
		memcpy(&((struct sockaddr_dl *)&ifpss)->sdl_data, ifname,
		    ifp.sdl_nlen);

		rtm.rtm_addrs |= RTA_IFP;
		iov[iovlen].iov_base = &ifpss;
		iov[iovlen++].iov_len = RT_ROUNDUP(ifpss.ss_len);
	}