Esempio n. 1
0
static int INET_setroute(int action, int options, char **args)
{
    struct rtentry rt;
    char target[128], gateway[128] = "NONE", netmask[128] = "default";
    int xflag, isnet;

    xflag = 0;

    if (!strcmp(*args, "#net")) {
	xflag = 1;
	args++;
    } else if (!strcmp(*args, "#host")) {
	xflag = 2;
	args++;
    }
    if (*args == NULL)
	return usage(E_OPTERR);

    safe_strncpy(target, *args++, (sizeof target));

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

    /* Special hack for /prefix syntax */
    {
	union {
	    struct sockaddr_in m;
	    struct sockaddr d;
	} mask;
	int n;

	n = inet_aftype.getmask(target, &mask.d, netmask);
	if (n < 0)
	    return usage(E_OPTERR);
	else if (n)
	    rt.rt_genmask = full_mask(mask.d);
    }

    /* Prefer hostname lookup is -host flag was given */
    if ((isnet = inet_aftype.input((xflag!=2? 0: 256), target, &rt.rt_dst)) < 0) {
	inet_aftype.herror(target);
	return (E_LOOKUP);
    }
    switch (xflag) {
    case 1:
       isnet = 1; break;
    case 2:
       isnet = 0; 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")) {
	    int metric;

	    args++;
	    if (!*args || !isdigit(**args))
		return usage(E_OPTERR);
	    metric = atoi(*args);
#if HAVE_NEW_ADDRT
	    rt.rt_metric = metric + 1;
#else
	    ENOSUPP("inet_setroute", "NEW_ADDRT (metric)");
#endif
	    args++;
	    continue;
	}
	if (!strcmp(*args, "netmask")) {
	    struct sockaddr mask;

	    args++;
	    if (!*args || mask_in_addr(rt))
		return usage(E_OPTERR);
	    safe_strncpy(netmask, *args, (sizeof netmask));
	    if ((isnet = inet_aftype.input(0, netmask, &mask)) < 0) {
		inet_aftype.herror(netmask);
		return (E_LOOKUP);
	    }
	    rt.rt_genmask = full_mask(mask);
	    args++;
	    continue;
	}
	if (!strcmp(*args, "gw") || !strcmp(*args, "gateway")) {
	    args++;
	    if (!*args)
		return usage(E_OPTERR);
	    if (rt.rt_flags & RTF_GATEWAY)
		return usage(E_OPTERR);
	    safe_strncpy(gateway, *args, (sizeof gateway));
	    if ((isnet = inet_aftype.input(256, gateway, &rt.rt_gateway)) < 0) {
		inet_aftype.herror(gateway);
		return (E_LOOKUP);
	    }
	    if (isnet) {
		fprintf(stderr, _("route: %s: cannot use a NETWORK as gateway!\n"),
			gateway);
		return usage(E_OPTERR);
	    }
	    rt.rt_flags |= RTF_GATEWAY;
	    args++;
	    continue;
	}
	if (!strcmp(*args, "mss") || !strcmp(*args,"mtu")) {
	    args++;
	    rt.rt_flags |= RTF_MSS;
	    if (!*args)
		return usage(E_OPTERR);
	    rt.rt_mss = atoi(*args);
	    args++;
	    if (rt.rt_mss < 64 || rt.rt_mss > 65536) {
		fprintf(stderr, _("route: Invalid MSS/MTU.\n"));
		return usage(E_OPTERR);
	    }
	    continue;
	}
	if (!strcmp(*args, "window")) {
	    args++;
	    if (!*args)
		return usage(E_OPTERR);
	    rt.rt_flags |= RTF_WINDOW;
	    rt.rt_window = atoi(*args);
	    args++;
	    if (rt.rt_window < 128) {
		fprintf(stderr, _("route: Invalid window.\n"));
		return usage(E_OPTERR);
	    }
	    continue;
	}
	if (!strcmp(*args, "irtt")) {
	    args++;
	    if (!*args)
		return usage(E_OPTERR);
	    args++;
#if HAVE_RTF_IRTT
	    rt.rt_flags |= RTF_IRTT;
	    rt.rt_irtt = atoi(*(args - 1));
	    rt.rt_irtt *= (HZ / 100);	/* FIXME */
#if 0				/* FIXME: do we need to check anything of this? */
	    if (rt.rt_irtt < 1 || rt.rt_irtt > (120 * HZ)) {
		fprintf(stderr, _("route: Invalid initial rtt.\n"));
		return usage(E_OPTERR);
	    }
#endif
#else
	    ENOSUPP("inet_setroute", "RTF_IRTT");
#endif
	    continue;
	}
	if (!strcmp(*args, "reject")) {
	    args++;
#if HAVE_RTF_REJECT
	    rt.rt_flags |= RTF_REJECT;
#else
	    ENOSUPP("inet_setroute", "RTF_REJECT");
#endif
	    continue;
	}
	if (!strcmp(*args, "mod")) {
	    args++;
	    rt.rt_flags |= RTF_MODIFIED;
	    continue;
	}
	if (!strcmp(*args, "dyn")) {
	    args++;
	    rt.rt_flags |= RTF_DYNAMIC;
	    continue;
	}
	if (!strcmp(*args, "reinstate")) {
	    args++;
	    rt.rt_flags |= RTF_REINSTATE;
	    continue;
	}
	if (!strcmp(*args, "device") || !strcmp(*args, "dev")) {
	    args++;
	    if (rt.rt_dev || *args == NULL)
		return usage(E_OPTERR);
	    rt.rt_dev = *args++;
	    continue;
	}
	/* nothing matches */
	if (!rt.rt_dev) {
	    rt.rt_dev = *args++;
	    if (*args)
		return usage(E_OPTERR);	/* must be last to catch typos */
	} else
	    return usage(E_OPTERR);
    }

#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)) {
	__u32 mask = ~ntohl(mask_in_addr(rt));
	if ((rt.rt_flags & RTF_HOST) && mask != 0xffffffff) {
	    fprintf(stderr, _("route: netmask %.8x doesn't make sense with host route\n"), mask);
	    return usage(E_OPTERR);
	}
	if (mask & (mask + 1)) {
	    fprintf(stderr, _("route: bogus netmask %s\n"), netmask);
	    return usage(E_OPTERR);
	}
	mask = ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr;
	if (mask & ~mask_in_addr(rt)) {
	    fprintf(stderr, _("route: netmask doesn't match route address\n"));
	    return usage(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 (0);
}
Esempio n. 2
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. 3
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;
}