Exemplo n.º 1
0
/*
 * Search the entire arp table, and do some action on matching entries.
 */
void
search(in_addr_t addr, void (*action)(struct sockaddr_dl *sdl,
    struct sockaddr_inarp *sin, struct rt_msghdr *rtm))
{
	int mib[7];
	size_t needed;
	char *lim, *buf = NULL, *next;
	struct rt_msghdr *rtm;
	struct sockaddr_inarp *sin;
	struct sockaddr_dl *sdl;

	mib[0] = CTL_NET;
	mib[1] = PF_ROUTE;
	mib[2] = 0;
	mib[3] = AF_INET;
	mib[4] = NET_RT_FLAGS;
	mib[5] = RTF_LLINFO;
	mib[6] = getrtable();
	while (1) {
		if (sysctl(mib, 7, NULL, &needed, NULL, 0) == -1)
			err(1, "route-sysctl-estimate");
		if (needed == 0)
			return;
		if ((buf = realloc(buf, needed)) == NULL)
			err(1, "malloc");
		if (sysctl(mib, 7, buf, &needed, NULL, 0) == -1) {
			if (errno == ENOMEM)
				continue;
			err(1, "actual retrieval of routing table");
		}
		lim = buf + needed;
		break;
	}
	for (next = buf; next < lim; next += rtm->rtm_msglen) {
		rtm = (struct rt_msghdr *)next;
		if (rtm->rtm_version != RTM_VERSION)
			continue;
		sin = (struct sockaddr_inarp *)(next + rtm->rtm_hdrlen);
		sdl = (struct sockaddr_dl *)(sin + 1);
		if (addr) {
			if (addr != sin->sin_addr.s_addr)
				continue;
			found_entry = 1;
		}
		(*action)(sdl, sin, rtm);
	}
	free(buf);
}
Exemplo n.º 2
0
int
main(int argc, char *argv[])
{
	int		 ch, func = 0, rtn;
	const char	*errstr;

	pid = getpid();
	opterr = 0;
	rdomain = getrtable();
	while ((ch = getopt(argc, argv, "andsFfV:W")) != -1) {
		switch (ch) {
		case 'a':
			aflag = 1;
			break;
		case 'n':
			nflag = 1;
			break;
		case 'd':
			if (func)
				usage();
			func = F_DELETE;
			break;
		case 's':
			if (func)
				usage();
			func = F_SET;
			break;
		case 'F':
			replace = 1;
			break;
		case 'f':
			if (func)
				usage();
			func = F_FILESET;
			break;
		case 'V':
			rdomain = strtonum(optarg, 0, RT_TABLEID_MAX, &errstr);
			if (errstr != NULL) {
				warn("bad rdomain: %s", errstr);
				usage();
			}
			break;
		case 'W':
			if (func)
				usage();
			func = F_WAKE;
			break;
		default:
			usage();
			break;
		}
	}
	argc -= optind;
	argv += optind;

	if (!func)
		func = F_GET;
	rtn = 0;

	switch (func) {
	case F_GET:
		if (aflag && argc == 0)
			dump();
		else if (!aflag && argc == 1)
			rtn = get(argv[0]);
		else
			usage();
		break;
	case F_SET:
		if (argc < 2 || argc > 5)
			usage();
		if (replace)
			delete(argv[0], NULL);
		rtn = set(argc, argv) ? 1 : 0;
		break;
	case F_DELETE:
		if (aflag && argc == 0)
			search(0, nuke_entry);
		else if (!aflag && argc == 1)
			rtn = delete(argv[0], argv[1]);
		else
			usage();
		break;
	case F_FILESET:
		if (argc != 1)
			usage();
		rtn = file(argv[0]);
		break;
	case F_WAKE:
		if (aflag || nflag || replace || rdomain > 0)
			usage();
		if (argc == 1)
			rtn = wake(argv[0], NULL);
		else if (argc == 2)
			rtn = wake(argv[0], argv[1]);
		else
			usage();
		break;
	}
	return (rtn);
}
Exemplo n.º 3
0
int
allow_data_connection(struct session *s)
{
	struct sockaddr *client_sa, *orig_sa, *proxy_sa, *server_sa;
	int prepared = 0;

	/*
	 * The pf rules below do quite some NAT rewriting, to keep up
	 * appearances.  Points to keep in mind:
	 * 1)  The client must think it's talking to the real server,
	 *     for both control and data connections.  Transparently.
	 * 2)  The server must think that the proxy is the client.
	 * 3)  Source and destination ports are rewritten to minimize
	 *     port collisions, to aid security (some systems pick weak
	 *     ports) or to satisfy RFC requirements (source port 20).
	 */
	
	/* Cast this once, to make code below it more readable. */
	client_sa = sstosa(&s->client_ss);
	server_sa = sstosa(&s->server_ss);
	proxy_sa = sstosa(&s->proxy_ss);
	if (fixed_server)
		/* Fixed server: data connections must appear to come
		   from / go to the original server, not the fixed one. */
		orig_sa = sstosa(&s->orig_server_ss);
	else
		/* Server not fixed: orig_server == server. */
		orig_sa = sstosa(&s->server_ss);

	/* Passive modes. */
	if (s->cmd == CMD_PASV || s->cmd == CMD_EPSV) {
		s->port = parse_port(s->cmd);
		if (s->port < MIN_PORT) {
			logmsg(LOG_CRIT, "#%d bad port in '%s'", s->id,
			    linebuf);
			return (0);
		}
		s->proxy_port = pick_proxy_port();
		logmsg(LOG_INFO, "#%d passive: client to server port %d"
		    " via port %d", s->id, s->port, s->proxy_port);

		if (prepare_commit(s->id) == -1)
			goto fail;
		prepared = 1;

		proxy_reply(s->cmd, orig_sa, s->proxy_port);
		logmsg(LOG_DEBUG, "#%d proxy: %s", s->id, linebuf);

		/* pass in from $client to $orig_server port $proxy_port
		    rdr-to $server port $port */
		if (add_rdr(s->id, client_sa, s->client_rd, orig_sa,
		    s->proxy_port, server_sa, s->port, getrtable()) == -1)
			goto fail;

		/* pass out from $client to $server port $port nat-to $proxy */
		if (add_nat(s->id, client_sa, getrtable(), server_sa,
		    s->port, proxy_sa, PF_NAT_PROXY_PORT_LOW,
		    PF_NAT_PROXY_PORT_HIGH) == -1)
			goto fail;
	}

	/* Active modes. */
	if (s->cmd == CMD_PORT || s->cmd == CMD_EPRT) {
		logmsg(LOG_INFO, "#%d active: server to client port %d"
		    " via port %d", s->id, s->port, s->proxy_port);

		if (prepare_commit(s->id) == -1)
			goto fail;
		prepared = 1;

		/* pass in from $server to $proxy port $proxy_port
		    rdr-to $client port $port */
		if (add_rdr(s->id, server_sa, getrtable(), proxy_sa,
		    s->proxy_port, client_sa, s->port, s->client_rd) == -1)
			goto fail;

		/* pass out from $server to $client port $port
		    nat-to $orig_server port $natport */
		if (rfc_mode && s->cmd == CMD_PORT) {
			/* Rewrite sourceport to RFC mandated 20. */
			if (add_nat(s->id, server_sa, s->client_rd, client_sa,
			    s->port, orig_sa, 20, 20) == -1)
				goto fail;
		} else {
			/* Let pf pick a source port from the standard range. */
			if (add_nat(s->id, server_sa, s->client_rd, client_sa,
			    s->port, orig_sa, PF_NAT_PROXY_PORT_LOW,
			    PF_NAT_PROXY_PORT_HIGH) == -1)
			    	goto fail;
		}
	}

	/* Commit rules if they were prepared. */
	if (prepared && (do_commit() == -1)) {
		if (errno != EBUSY)
			goto fail;
		/* One more try if busy. */
		usleep(5000);
		if (do_commit() == -1)
			goto fail;
	}

	s->cmd = CMD_NONE;
	s->port = 0;

	return (1);

 fail:
	logmsg(LOG_CRIT, "#%d pf operation failed: %s", s->id, strerror(errno));
	if (prepared)
		do_rollback();
	return (0);
}