Esempio n. 1
0
static int INET6_input(int type, char *bufp, struct sockaddr *sap)
{
    switch (type) {
    case 1:
	return (INET6_getsock(bufp, sap));
    default:
	return (INET6_resolve(bufp, (struct sockaddr_in6 *) sap));
    }
}
Esempio n. 2
0
static void INET6_setroute(int action, char **args)
{
	struct sockaddr_in6 sa6;
	struct in6_rtmsg rt;
	int prefix_len, skfd;
	const char *devname;

	assert((action == RTACTION_ADD) || (action == RTACTION_DEL));

	{
		/* We know args isn't NULL from the check in route_main. */
		const char *target = *args++;

		if (strcmp(target, "default") == 0) {
			prefix_len = 0;
			memset(&sa6, 0, sizeof(sa6));
		} else {
			char *cp;
			if ((cp = strchr(target, '/'))) { /* Yes... const to non is ok. */
				*cp = 0;
				prefix_len = bb_xgetularg10_bnd(cp+1, 0, 128);
			} else {
				prefix_len = 128;
			}
			if (INET6_resolve(target, (struct sockaddr_in6 *) &sa6) < 0) {
				bb_error_msg_and_die("resolving %s", target);
			}
		}
	}

	/* Clean out the RTREQ structure. */
	memset((char *) &rt, 0, sizeof(struct in6_rtmsg));

	memcpy(&rt.rtmsg_dst, sa6.sin6_addr.s6_addr, sizeof(struct in6_addr));

	/* Fill in the other fields. */
	rt.rtmsg_dst_len = prefix_len;
	rt.rtmsg_flags = ((prefix_len == 128) ? (RTF_UP|RTF_HOST) : RTF_UP);
	rt.rtmsg_metric = 1;

	devname = NULL;

	while (*args) {
		int k = kw_lookup(tbl_ipvx, &args);
		const char *args_m1 = args[-1];

		if ((k == KW_IPVx_MOD) || (k == KW_IPVx_DYN)) {
			rt.rtmsg_flags |= flags_ipvx[k & 3];
			continue;
		}

		if (k == KW_IPVx_METRIC) {
			rt.rtmsg_metric = bb_xgetularg10(args_m1);
			continue;
		}

		if (k == KW_IPVx_GATEWAY) {
			if (rt.rtmsg_flags & RTF_GATEWAY) {
				bb_show_usage();
			}

			if (INET6_resolve(args_m1, (struct sockaddr_in6 *) &sa6) < 0) {
				bb_error_msg_and_die("resolving %s", args_m1);
			}
			memcpy(&rt.rtmsg_gateway, sa6.sin6_addr.s6_addr,
				   sizeof(struct in6_addr));
			rt.rtmsg_flags |= RTF_GATEWAY;
			continue;
		}

		/* Device is special in that it can be the last arg specified
		 * and doesn't requre the dev/device keyword in that case. */
		if (!devname && ((k == KW_IPVx_DEVICE) || (!k && !*++args))) {
			/* Don't use args_m1 here since args may have changed! */
			devname = args[-1];
			continue;
		}

		/* Nothing matched. */
		bb_show_usage();
	}

	/* Create a socket to the INET6 kernel. */
	if ((skfd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
		bb_perror_msg_and_die("socket");
	}

	rt.rtmsg_ifindex = 0;

	if (devname) {
		struct ifreq ifr;
		memset(&ifr, 0, sizeof(ifr));
		strcpy(ifr.ifr_name, devname);

		if (ioctl(skfd, SIOGIFINDEX, &ifr) < 0) {
			bb_perror_msg_and_die("SIOGIFINDEX");
		}
		rt.rtmsg_ifindex = ifr.ifr_ifindex;
	}

	/* Tell the kernel to accept this route. */
	if (ioctl(skfd, ((action==RTACTION_ADD) ? SIOCADDRT : SIOCDELRT), &rt)<0) {
		bb_perror_msg_and_die("SIOC[ADD|DEL]RT");
	}

	/* Don't bother closing, as we're exiting after we return anyway. */
	/* close(skfd); */
}
Esempio n. 3
0
static int INET6_setroute(int action, int options, char **args)
{
	struct in6_rtmsg rt;
	struct ifreq ifr;
	struct sockaddr_in6 sa6;
	char target[128], gateway[128] = "NONE";
	int metric, prefix_len;
	char *devname = NULL;
	char *cp;
	int skfd;

	if (*args == NULL)
		bb_show_usage();

	strcpy(target, *args++);
	if (!strcmp(target, "default")) {
		prefix_len = 0;
		memset(&sa6, 0, sizeof(sa6));
	} else {
		if ((cp = strchr(target, '/'))) {
			prefix_len = atol(cp + 1);
			if ((prefix_len < 0) || (prefix_len > 128))
				bb_show_usage();
			*cp = 0;
		} else {
			prefix_len = 128;
		}
		if (INET6_resolve(target, (struct sockaddr_in6 *) &sa6) < 0) {
			bb_error_msg(_("can't resolve %s"), target);
			return EXIT_FAILURE;	/* XXX change to E_something */
		}
	}

	/* Clean out the RTREQ structure. */
	memset((char *) &rt, 0, sizeof(struct in6_rtmsg));

	memcpy(&rt.rtmsg_dst, sa6.sin6_addr.s6_addr, sizeof(struct in6_addr));

	/* Fill in the other fields. */
	rt.rtmsg_flags = RTF_UP;
	if (prefix_len == 128)
		rt.rtmsg_flags |= RTF_HOST;
	rt.rtmsg_metric = 1;
	rt.rtmsg_dst_len = prefix_len;

	while (*args) {
		if (!strcmp(*args, "metric")) {

			args++;
			if (!*args || !isdigit(**args))
				bb_show_usage();
			metric = atoi(*args);
			rt.rtmsg_metric = metric;
			args++;
			continue;
		}
		if (!strcmp(*args, "gw") || !strcmp(*args, "gateway")) {
			args++;
			if (!*args)
				bb_show_usage();
			if (rt.rtmsg_flags & RTF_GATEWAY)
				bb_show_usage();
			strcpy(gateway, *args);
			if (INET6_resolve(gateway, (struct sockaddr_in6 *) &sa6) < 0) {
				bb_error_msg(_("can't resolve gw %s"), gateway);
				return (E_LOOKUP);
			}
			memcpy(&rt.rtmsg_gateway, sa6.sin6_addr.s6_addr,
				   sizeof(struct in6_addr));
			rt.rtmsg_flags |= RTF_GATEWAY;
			args++;
			continue;
		}
		if (!strcmp(*args, "mod")) {
			args++;
			rt.rtmsg_flags |= RTF_MODIFIED;
			continue;
		}
		if (!strcmp(*args, "dyn")) {
			args++;
			rt.rtmsg_flags |= RTF_DYNAMIC;
			continue;
		}
		if (!strcmp(*args, "device") || !strcmp(*args, "dev")) {
			args++;
			if (!*args)
				bb_show_usage();
		} else if (args[1])
			bb_show_usage();

		devname = *args;
		args++;
	}

	/* Create a socket to the INET6 kernel. */
	if ((skfd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
		perror("socket");
		return (E_SOCK);
	}
	if (devname) {
		memset(&ifr, 0, sizeof(ifr));
		strcpy(ifr.ifr_name, devname);

		if (ioctl(skfd, SIOGIFINDEX, &ifr) < 0) {
			perror("SIOGIFINDEX");
			return (E_SOCK);
		}
		rt.rtmsg_ifindex = ifr.ifr_ifindex;
	} else
		rt.rtmsg_ifindex = 0;

	/* Tell the kernel to accept this route. */
	if (action == RTACTION_DEL) {
		if (ioctl(skfd, SIOCDELRT, &rt) < 0) {
			perror("SIOCDELRT");
			close(skfd);
			return (E_SOCK);
		}
	} else {
		if (ioctl(skfd, SIOCADDRT, &rt) < 0) {
			perror("SIOCADDRT");
			close(skfd);
			return (E_SOCK);
		}
	}

	/* Close the socket. */
	(void) close(skfd);
	return (0);
}