Esempio n. 1
0
static int INET_input(int type, char *bufp, struct sockaddr *sap)
{
    switch (type) {
    case 1:
	return (INET_getsock(bufp, sap));
    case 256:
	return (INET_resolve(bufp, (struct sockaddr_in *) sap, 1));
    default:
	return (INET_resolve(bufp, (struct sockaddr_in *) sap, 0));
    }
}
Esempio n. 2
0
static int INET_input(int type, char *bufp, struct sockaddr_storage *sasp)
{
    switch (type) {
    case 1:
	return INET_getsock(bufp, sasp);
    case 256:
	return INET_resolve(bufp, sasp, 1);
    default:
	return INET_resolve(bufp, sasp, 0);
    }
}
Esempio n. 3
0
static NOINLINE void INET_setroute(int action, char **args)
{
	/* char buffer instead of bona-fide struct avoids aliasing warning */
	char rt_buf[sizeof(struct rtentry)];
	struct rtentry *const rt = (void *)rt_buf;

	const char *netmask = NULL;
	int skfd, isnet, xflag;

	/* Grab the -net or -host options.  Remember they were transformed. */
	xflag = kw_lookup(tbl_hash_net_host, &args);

	/* If we did grab -net or -host, make sure we still have an arg left. */
	if (*args == NULL) {
		bb_show_usage();
	}

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

	{
		const char *target = *args++;
		char *prefix;

		/* recognize x.x.x.x/mask format. */
		prefix = strchr(target, '/');
		if (prefix) {
			int prefix_len;

			prefix_len = xatoul_range(prefix+1, 0, 32);
			mask_in_addr(*rt) = htonl( ~(0xffffffffUL >> prefix_len));
			*prefix = '\0';
#if HAVE_NEW_ADDRT
			rt->rt_genmask.sa_family = AF_INET;
#endif
		} else {
			/* Default netmask. */
			netmask = "default";
		}
		/* Prefer hostname lookup is -host flag (xflag==1) was given. */
		isnet = INET_resolve(target, (struct sockaddr_in *) &rt->rt_dst,
							 (xflag & HOST_FLAG));
		if (isnet < 0) {
			bb_error_msg_and_die("resolving %s", target);
		}
		if (prefix) {
			/* do not destroy prefix for process args */
			*prefix = '/';
		}
	}
Esempio n. 4
0
static void INET_setroute(int action, char **args)
{
	struct rtentry rt;
	const char *netmask = NULL;
	int skfd, isnet, xflag;

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

	/* Grab the -net or -host options.  Remember they were transformed. */
	xflag = kw_lookup(tbl_hash_net_host, &args);

	/* If we did grab -net or -host, make sure we still have an arg left. */
	if (*args == NULL) {
		bb_show_usage();
	}

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

	{
		const char *target = *args++;
		char *prefix;

		/* recognize x.x.x.x/mask format. */
		prefix = strchr(target, '/');
		if(prefix) {
			int prefix_len;

			prefix_len = bb_xgetularg10_bnd(prefix+1, 0, 32);
			mask_in_addr(rt) = htonl( ~ (0xffffffffUL >> prefix_len));
			*prefix = '\0';
#if HAVE_NEW_ADDRT
			rt.rt_genmask.sa_family = AF_INET;
#endif
		} else {
			/* Default netmask. */
			netmask = bb_INET_default;
		}
		/* Prefer hostname lookup is -host flag (xflag==1) was given. */
		isnet = INET_resolve(target, (struct sockaddr_in *) &rt.rt_dst,
							 (xflag & HOST_FLAG));
		if (isnet < 0) {
			bb_error_msg_and_die("resolving %s", target);
		}
		if(prefix) {
			/* do not destroy prefix for process args */
			*prefix = '/';
		}
	}
Esempio n. 5
0
static void INET_setroute(int action, char **args)
{
	struct rtentry rt;
	const char *netmask;
	int skfd, isnet, xflag;

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

	/* Grab the -net or -host options.  Remember they were transformed. */
	xflag = kw_lookup(tbl_hash_net_host, &args);

	/* If we did grab -net or -host, make sure we still have an arg left. */
	if (*args == NULL) {
		bb_show_usage();
	}

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

	{
		const char *target = *args++;

		/* Prefer hostname lookup is -host flag (xflag==1) was given. */
 		isnet = INET_resolve(target, (struct sockaddr_in *) &rt.rt_dst,
							 (xflag & HOST_FLAG));
		if (isnet < 0) {
			bb_error_msg_and_die("resolving %s", target);
		}

	}

	if (xflag) {		/* Reinit isnet if -net or -host was specified. */
		isnet = (xflag & NET_FLAG);
	}

	/* Fill in the other fields. */
	rt.rt_flags = ((isnet) ? RTF_UP : (RTF_UP | RTF_HOST));

	netmask = bb_INET_default;

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

		if (k & KW_IPVx_FLAG_ONLY) {
			rt.rt_flags |= flags_ipvx[k & 3];
			continue;
		}

#if HAVE_NEW_ADDRT
		if (k == KW_IPVx_METRIC) {
			rt.rt_metric = bb_xgetularg10(args_m1) + 1;
			continue;
		}
#endif

		if (k == KW_IPVx_NETMASK) {
			struct sockaddr mask;

			if (mask_in_addr(rt)) {
				bb_show_usage();
			}

			netmask = args_m1;
			isnet = INET_resolve(netmask, (struct sockaddr_in *) &mask, 0);
			if (isnet < 0) {
				bb_error_msg_and_die("resolving %s", netmask);
			}
			rt.rt_genmask = full_mask(mask);
			continue;
		}

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

			isnet = INET_resolve(args_m1,
								 (struct sockaddr_in *) &rt.rt_gateway, 1);
			rt.rt_flags |= RTF_GATEWAY;

			if (isnet) {
				if (isnet < 0) {
					bb_error_msg_and_die("resolving %s", args_m1);
				}
				bb_error_msg_and_die("gateway %s is a NETWORK", args_m1);
			}
			continue;
		}

		if (k == KW_IPVx_MSS) {	/* Check valid MSS bounds. */
			rt.rt_flags |= RTF_MSS;
			rt.rt_mss = bb_xgetularg10_bnd(args_m1, 64, 32768);
			continue;
		}

		if (k == KW_IPVx_WINDOW) {	/* Check valid window bounds. */
			rt.rt_flags |= RTF_WINDOW;
			rt.rt_window = bb_xgetularg10_bnd(args_m1, 128, INT_MAX);
			continue;
		}

#ifdef RTF_IRTT
		if (k == KW_IPVx_IRTT) {
			rt.rt_flags |= RTF_IRTT;
			rt.rt_irtt = bb_xgetularg10(args_m1);
			rt.rt_irtt *= (sysconf(_SC_CLK_TCK) / 100);	/* FIXME */
#if 0					/* FIXME: do we need to check anything of this? */
			if (rt.rt_irtt < 1 || rt.rt_irtt > (120 * HZ)) {
				bb_error_msg_and_die("bad irtt");
			}
#endif
			continue;
		}
#endif

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

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

#ifdef RTF_REJECT
	if ((rt.rt_flags & RTF_REJECT) && !rt.rt_dev) {
		rt.rt_dev = "lo";
	}
#endif

	/* sanity checks.. */
	if (mask_in_addr(rt)) {
		unsigned long mask = mask_in_addr(rt);

		mask = ~ntohl(mask);
		if ((rt.rt_flags & RTF_HOST) && mask != 0xffffffff) {
			bb_error_msg_and_die("netmask %.8x and host route conflict",
								 (unsigned int) mask);
		}
		if (mask & (mask + 1)) {
			bb_error_msg_and_die("bogus netmask %s", netmask);
		}
		mask = ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr;
		if (mask & ~mask_in_addr(rt)) {
			bb_error_msg_and_die("netmask and route address conflict");
		}
	}

	/* Fill out netmask if still unset */
	if ((action == RTACTION_ADD) && (rt.rt_flags & RTF_HOST)) {
		mask_in_addr(rt) = 0xffffffff;
	}

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

	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. 6
0
static int INET_setroute(int action, int options, char **args)
{
	struct rtentry rt;
	char target[128], gateway[128] = "NONE";
	const char *netmask = bb_INET_default;
	int xflag, isnet;
	int skfd;

	xflag = 0;

	if (*args == NULL)
		bb_show_usage();
	if (strcmp(*args, "-net") == 0) {
		xflag = 1;
		args++;
	} else if (strcmp(*args, "-host") == 0) {
		xflag = 2;
		args++;
	}
	if (*args == NULL)
		bb_show_usage();
	safe_strncpy(target, *args++, (sizeof target));

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


	if ((isnet =
		 INET_resolve(target, (struct sockaddr_in *) &rt.rt_dst,
					  xflag != 1)) < 0) {
		bb_error_msg(_("can't resolve %s"), target);
		return EXIT_FAILURE;	/* XXX change to E_something */
	}

	switch (xflag) {
	case 1:
		isnet = 1;
		break;

	case 2:
		isnet = 0;
		break;

	default:
		break;
	}

	/* Fill in the other fields. */
	rt.rt_flags = (RTF_UP | RTF_HOST);
	if (isnet)
		rt.rt_flags &= ~RTF_HOST;

	while (*args) {
		if (strcmp(*args, "metric") == 0) {
			int metric;

			args++;
			if (!*args || !isdigit(**args))
				bb_show_usage();
			metric = atoi(*args);
#if HAVE_NEW_ADDRT
			rt.rt_metric = metric + 1;
#else
			ENOSUPP("inet_setroute", "NEW_ADDRT (metric)");	/* XXX Fixme */
#endif
			args++;
			continue;
		}

		if (strcmp(*args, "netmask") == 0) {
			struct sockaddr mask;

			args++;
			if (!*args || mask_in_addr(rt))
				bb_show_usage();
			netmask = *args;
			if ((isnet =
				 INET_resolve(netmask, (struct sockaddr_in *) &mask,
							  0)) < 0) {
				bb_error_msg(_("can't resolve netmask %s"), netmask);
				return E_LOOKUP;
			}
			rt.rt_genmask = full_mask(mask);
			args++;
			continue;
		}

		if (strcmp(*args, "gw") == 0 || strcmp(*args, "gateway") == 0) {
			args++;
			if (!*args)
				bb_show_usage();
			if (rt.rt_flags & RTF_GATEWAY)
				bb_show_usage();
			safe_strncpy(gateway, *args, (sizeof gateway));
			if ((isnet =
				 INET_resolve(gateway, (struct sockaddr_in *) &rt.rt_gateway,
							  1)) < 0) {
				bb_error_msg(_("can't resolve gw %s"), gateway);
				return E_LOOKUP;
			}
			if (isnet) {
				bb_error_msg(_("%s: cannot use a NETWORK as gateway!"), gateway);
				return E_OPTERR;
			}
			rt.rt_flags |= RTF_GATEWAY;
			args++;
			continue;
		}

		if (strcmp(*args, "mss") == 0) {
			args++;
			rt.rt_flags |= RTF_MSS;
			if (!*args)
				bb_show_usage();
			rt.rt_mss = atoi(*args);
			args++;
			if (rt.rt_mss < 64 || rt.rt_mss > 32768) {
				bb_error_msg(_("Invalid MSS."));
				return E_OPTERR;
			}
			continue;
		}

		if (strcmp(*args, "window") == 0) {
			args++;
			if (!*args)
				bb_show_usage();
			rt.rt_flags |= RTF_WINDOW;
			rt.rt_window = atoi(*args);
			args++;
			if (rt.rt_window < 128) {
				bb_error_msg(_("Invalid window."));
				return E_OPTERR;
			}
			continue;
		}

		if (strcmp(*args, "irtt") == 0) {
			args++;
			if (!*args)
				bb_show_usage();
			args++;
#if HAVE_RTF_IRTT
			rt.rt_flags |= RTF_IRTT;
			rt.rt_irtt = atoi(*(args - 1));
			rt.rt_irtt *= (sysconf(_SC_CLK_TCK) / 100);	/* FIXME */
#if 0					/* FIXME: do we need to check anything of this? */
			if (rt.rt_irtt < 1 || rt.rt_irtt > (120 * HZ)) {
				bb_error_msg(_("Invalid initial rtt."));
				return E_OPTERR;
			}
#endif
#else
			ENOSUPP("inet_setroute", "RTF_IRTT");	/* XXX Fixme */
#endif
			continue;
		}

		if (strcmp(*args, "reject") == 0) {
			args++;
#if HAVE_RTF_REJECT
			rt.rt_flags |= RTF_REJECT;
#else
			ENOSUPP("inet_setroute", "RTF_REJECT");	/* XXX Fixme */
#endif
			continue;
		}
		if (strcmp(*args, "mod") == 0) {
			args++;
			rt.rt_flags |= RTF_MODIFIED;
			continue;
		}
		if (strcmp(*args, "dyn") == 0) {
			args++;
			rt.rt_flags |= RTF_DYNAMIC;
			continue;
		}
		if (strcmp(*args, "reinstate") == 0) {
			args++;
			rt.rt_flags |= RTF_REINSTATE;
			continue;
		}
		if (strcmp(*args, "device") == 0 || strcmp(*args, "dev") == 0) {
			args++;
			if (rt.rt_dev || *args == NULL)
				bb_show_usage();
			rt.rt_dev = *args++;
			continue;
		}
		/* nothing matches */
		if (!rt.rt_dev) {
			rt.rt_dev = *args++;
			if (*args)
				bb_show_usage();	/* must be last to catch typos */
		} else {
			bb_show_usage();
		}
	}

#if HAVE_RTF_REJECT
	if ((rt.rt_flags & RTF_REJECT) && !rt.rt_dev)
		rt.rt_dev = "lo";
#endif

	/* sanity checks.. */
	if (mask_in_addr(rt)) {
		unsigned long mask = mask_in_addr(rt);

		mask = ~ntohl(mask);
		if ((rt.rt_flags & RTF_HOST) && mask != 0xffffffff) {
			bb_error_msg(_("netmask %.8x doesn't make sense with host route"),
					  (unsigned int) mask);
			return E_OPTERR;
		}
		if (mask & (mask + 1)) {
			bb_error_msg(_("bogus netmask %s"), netmask);
			return E_OPTERR;
		}
		mask = ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr;
		if (mask & ~mask_in_addr(rt)) {
			bb_error_msg(_("netmask doesn't match route address"));
			return E_OPTERR;
		}
	}
	/* Fill out netmask if still unset */
	if ((action == RTACTION_ADD) && rt.rt_flags & RTF_HOST)
		mask_in_addr(rt) = 0xffffffff;

	/* Create a socket to the INET kernel. */
	if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		perror("socket");
		return E_SOCK;
	}
	/* 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 EXIT_SUCCESS;
}