Beispiel #1
0
static void
i_ipadm_create_ngz_route(int rtsock, char *link, uint8_t *buf, size_t buflen)
{
	struct in6_addr defrouter;
	boolean_t isv6;
	struct in_addr gw4;
	uint8_t *cp;
	const in6_addr_t ipv6_all_zeros = { 0, 0, 0, 0 };

	if (rtsock == -1)
		return;

	for (cp = buf; cp < buf + buflen; cp += sizeof (defrouter)) {
		bcopy(cp, &defrouter, sizeof (defrouter));
		if (IN6_IS_ADDR_UNSPECIFIED(&defrouter))
			break;
		isv6 = !IN6_IS_ADDR_V4MAPPED(&defrouter);
		if (isv6) {
			i_ipadm_rtioctl6(rtsock, RTM_ADD, ipv6_all_zeros,
			    defrouter, 0, link, RTF_GATEWAY);
		} else {
			IN6_V4MAPPED_TO_INADDR(&defrouter, &gw4);
			i_ipadm_rtioctl4(rtsock, RTM_ADD, INADDR_ANY,
			    gw4.s_addr, 0, link, 0, RTF_GATEWAY);
		}
	}
}
Beispiel #2
0
/*
 * This is a wrapper function for inet_ntop(). In case the af is AF_INET6
 * and the address pointed by src is a IPv4-mapped IPv6 address, it returns
 * a printable IPv4 address, not an IPv4-mapped IPv6 address. In other cases it
 * behaves just like inet_ntop().
 */
const char *
inet_ntop_native(int af, const void *addr, char *dst, size_t size)
{
	struct in_addr	v4addr;

	if ((af == AF_INET6) && IN6_IS_ADDR_V4MAPPED((struct in6_addr *)addr)) {
		IN6_V4MAPPED_TO_INADDR((struct in6_addr *)addr, &v4addr);
		return (inet_ntop(AF_INET, &v4addr, dst, size));
	} else {
		return (inet_ntop(af, addr, dst, size));
	}
}
Beispiel #3
0
static int
print_rh(const char *rh_name)
{
	int herr;
	struct hostent *hp;
	in6_addr_t in6;
	char abuf[INET6_ADDRSTRLEN];
	tsol_rhent_t rhent;

	if ((hp = getipnodebyname(rh_name, AF_INET6,
	    AI_ALL | AI_ADDRCONFIG | AI_V4MAPPED, &herr)) == NULL) {
		(void) fprintf(stderr, gettext("tninfo: unknown host or "
		    "invalid literal address: %s\n"), rh_name);
		if (herr == TRY_AGAIN)
			(void) fprintf(stderr,
			    gettext("\t(try again later)\n"));
		return (1);
	}

	(void) memset(&rhent, 0, sizeof (rhent));
	(void) memcpy(&in6, hp->h_addr, hp->h_length);

	if (IN6_IS_ADDR_V4MAPPED(&in6)) {
		rhent.rh_address.ta_family = AF_INET;
		IN6_V4MAPPED_TO_INADDR(&in6, &rhent.rh_address.ta_addr_v4);
		(void) inet_ntop(AF_INET, &rhent.rh_address.ta_addr_v4, abuf,
		    sizeof (abuf));
	} else {
		rhent.rh_address.ta_family = AF_INET6;
		rhent.rh_address.ta_addr_v6 = in6;
		(void) inet_ntop(AF_INET6, &in6, abuf, sizeof (abuf));
	}

	(void) printf(gettext("IP address= %s\n"), abuf);

	if (tnrh(TNDB_GET, &rhent) != 0) {
		if (errno == ENOENT)
			(void) fprintf(stderr, gettext("tninfo: tnrhdb entry "
			    "%1$s does not exist\n"), abuf);
		else
			(void) fprintf(stderr, gettext("tninfo: TNDB_GET(%1$s) "
			    "failed: %2$s\n"), abuf, strerror(errno));
		return (1);
	}

	if (rhent.rh_template[0] != '\0')
		(void) printf(gettext("Template = %.*s\n"), TNTNAMSIZ,
		    rhent.rh_template);
	else
		(void) printf(gettext("No template exists.\n"));

	return (0);
}
Beispiel #4
0
/*
 * SCTP interface for geting the primary peer address of a sctp_t.
 */
static int
sctp_getpeeraddr(sctp_t *sctp, struct sockaddr *addr)
{
	struct sockaddr_in	*sin4;
	struct sockaddr_in6	*sin6;
	sctp_faddr_t		sctp_primary;
	in6_addr_t		faddr;
	conn_t			*connp = sctp->sctp_connp;

	if (sctp->sctp_faddrs == NULL)
		return (-1);

	addr->sa_family = connp->conn_family;
	if (mdb_vread(&sctp_primary, sizeof (sctp_faddr_t),
	    (uintptr_t)sctp->sctp_primary) == -1) {
		mdb_warn("failed to read sctp primary faddr");
		return (-1);
	}
	faddr = sctp_primary.sf_faddr;

	switch (connp->conn_family) {
	case AF_INET:
		/* LINTED: alignment */
		sin4 = (struct sockaddr_in *)addr;
		IN6_V4MAPPED_TO_INADDR(&faddr, &sin4->sin_addr);
		sin4->sin_port = connp->conn_fport;
		sin4->sin_family = AF_INET;
		break;

	case AF_INET6:
		/* LINTED: alignment */
		sin6 = (struct sockaddr_in6 *)addr;
		sin6->sin6_addr = faddr;
		sin6->sin6_port = connp->conn_fport;
		sin6->sin6_family = AF_INET6;
		sin6->sin6_flowinfo = 0;
		sin6->sin6_scope_id = 0;
		sin6->__sin6_src_id = 0;
		break;
	}

	return (0);
}
Beispiel #5
0
/*
 * Taken from inetd.c
 * This is a wrapper function for inet_ntop(). In case the af is AF_INET6
 * and the address pointed by src is a IPv4-mapped IPv6 address, it
 * returns printable IPv4 address, not IPv4-mapped IPv6 address. In other cases
 * it behaves just like inet_ntop().
 */
static const char *
inet_ntop_native(int af, const void *src, char *dst, size_t size)
{
	struct in_addr src4;
	const char *result;

	if (af == AF_INET6) {
		if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)) {
			IN6_V4MAPPED_TO_INADDR((struct in6_addr *)src, &src4);
			result = inet_ntop(AF_INET, &src4, dst, size);
		} else {
			result = inet_ntop(AF_INET6, src, dst, size);
		}
	} else {
		result = inet_ntop(af, src, dst, size);
	}

	return (result);
}
Beispiel #6
0
/*
 * Get the information for the channel structure.
 */
void
get_inet_addr_info(struct sockaddr_in6 *in_ipaddr, gss_buffer_t in_buffer)
{
	size_t length;
	char *value;

	if (in_ipaddr == NULL) {
		in_buffer->length = 0;
		in_buffer->value = NULL;
		return;
	}

	/* get the initiator address.value and address.length */

	if (in_ipaddr->sin6_family == AF_INET6) {
		struct in_addr in_ipv4addr;
		struct sockaddr_in6 *sin6 =
			(struct sockaddr_in6 *)in_ipaddr;
		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
			IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
				&in_ipv4addr);
			in_buffer->length = length = sizeof (struct in_addr);
			in_buffer->value = value = malloc(length);
			memcpy(value, &in_ipv4addr, length);
		} else {
			in_buffer->length = length = sizeof (struct in6_addr);
			in_buffer->value = value = malloc(length);
			memcpy(value, &(sin6->sin6_addr.s6_addr),
				length);
		}
	} else {
		in_buffer->length = length = sizeof (struct in_addr);
		in_buffer->value = value = malloc(in_buffer->length);
		memcpy(value,
			&((struct sockaddr_in *)(in_ipaddr))->sin_addr,
			length);
	}
}
Beispiel #7
0
/*
 * SCTP interface for geting the first source address of a sctp_t.
 */
int
sctp_getsockaddr(sctp_t *sctp, struct sockaddr *addr)
{
	int			err = -1;
	int			i;
	int			l;
	sctp_saddr_ipif_t	*pobj;
	sctp_saddr_ipif_t	obj;
	size_t			added = 0;
	sin6_t			*sin6;
	sin_t			*sin4;
	int			scanned = 0;
	boolean_t		skip_lback = B_FALSE;
	conn_t			*connp = sctp->sctp_connp;

	addr->sa_family = connp->conn_family;
	if (sctp->sctp_nsaddrs == 0)
		goto done;

	/*
	 * Skip loopback addresses for non-loopback assoc.
	 */
	if (sctp->sctp_state >= SCTPS_ESTABLISHED && !sctp->sctp_loopback) {
		skip_lback = B_TRUE;
	}

	for (i = 0; i < SCTP_IPIF_HASH; i++) {
		if (sctp->sctp_saddrs[i].ipif_count == 0)
			continue;

		pobj = list_object(&sctp->sctp_saddrs[i].sctp_ipif_list,
		    sctp->sctp_saddrs[i].sctp_ipif_list.list_head.list_next);
		if (mdb_vread(&obj, sizeof (sctp_saddr_ipif_t),
		    (uintptr_t)pobj) == -1) {
			mdb_warn("failed to read sctp_saddr_ipif_t");
			return (err);
		}

		for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) {
			sctp_ipif_t	ipif;
			in6_addr_t	laddr;
			list_node_t 	*pnode;
			list_node_t	node;

			if (mdb_vread(&ipif, sizeof (sctp_ipif_t),
			    (uintptr_t)obj.saddr_ipifp) == -1) {
				mdb_warn("failed to read sctp_ipif_t");
				return (err);
			}
			laddr = ipif.sctp_ipif_saddr;

			scanned++;
			if ((ipif.sctp_ipif_state == SCTP_IPIFS_CONDEMNED) ||
			    SCTP_DONT_SRC(&obj) ||
			    (ipif.sctp_ipif_ill->sctp_ill_flags &
			    PHYI_LOOPBACK) && skip_lback) {
				if (scanned >= sctp->sctp_nsaddrs)
					goto done;

				/* LINTED: alignment */
				pnode = list_d2l(&sctp->sctp_saddrs[i].
				    sctp_ipif_list, pobj);
				if (mdb_vread(&node, sizeof (list_node_t),
				    (uintptr_t)pnode) == -1) {
					mdb_warn("failed to read list_node_t");
					return (err);
				}
				pobj = list_object(&sctp->sctp_saddrs[i].
				    sctp_ipif_list, node.list_next);
				if (mdb_vread(&obj, sizeof (sctp_saddr_ipif_t),
				    (uintptr_t)pobj) == -1) {
					mdb_warn("failed to read "
					    "sctp_saddr_ipif_t");
					return (err);
				}
				continue;
			}

			switch (connp->conn_family) {
			case AF_INET:
				/* LINTED: alignment */
				sin4 = (sin_t *)addr;
				if ((sctp->sctp_state <= SCTPS_LISTEN) &&
				    sctp->sctp_bound_to_all) {
					sin4->sin_addr.s_addr = INADDR_ANY;
					sin4->sin_port = connp->conn_lport;
				} else {
					sin4 += added;
					sin4->sin_family = AF_INET;
					sin4->sin_port = connp->conn_lport;
					IN6_V4MAPPED_TO_INADDR(&laddr,
					    &sin4->sin_addr);
				}
				break;

			case AF_INET6:
				/* LINTED: alignment */
				sin6 = (sin6_t *)addr;
				if ((sctp->sctp_state <= SCTPS_LISTEN) &&
				    sctp->sctp_bound_to_all) {
					bzero(&sin6->sin6_addr,
					    sizeof (sin6->sin6_addr));
					sin6->sin6_port = connp->conn_lport;
				} else {
					sin6 += added;
					sin6->sin6_family = AF_INET6;
					sin6->sin6_port = connp->conn_lport;
					sin6->sin6_addr = laddr;
				}
				sin6->sin6_flowinfo = connp->conn_flowinfo;
				sin6->sin6_scope_id = 0;
				sin6->__sin6_src_id = 0;
				break;
			}
			added++;
			if (added >= 1) {
				err = 0;
				goto done;
			}
			if (scanned >= sctp->sctp_nsaddrs)
				goto done;

			/* LINTED: alignment */
			pnode = list_d2l(&sctp->sctp_saddrs[i].sctp_ipif_list,
			    pobj);
			if (mdb_vread(&node, sizeof (list_node_t),
			    (uintptr_t)pnode) == -1) {
				mdb_warn("failed to read list_node_t");
				return (err);
			}
			pobj = list_object(&sctp->sctp_saddrs[i].
			    sctp_ipif_list, node.list_next);
			if (mdb_vread(&obj, sizeof (sctp_saddr_ipif_t),
			    (uintptr_t)pobj) == -1) {
				mdb_warn("failed to read sctp_saddr_ipif_t");
				return (err);
			}
		}
	}
done:
	return (err);
}
Beispiel #8
0
static void
doit(int f,
	struct sockaddr_storage *fromp,
	krb5_context krb_context,
	int encr_flag,
	krb5_keytab keytab)
{
	int p, t, on = 1;
	char c;
	char abuf[INET6_ADDRSTRLEN];
	struct sockaddr_in *sin;
	struct sockaddr_in6 *sin6;
	int fromplen;
	in_port_t port;
	struct termios tp;
	boolean_t bad_port;
	boolean_t no_name;
	char rhost_addra[INET6_ADDRSTRLEN];

	if (!(rlbuf = malloc(BUFSIZ))) {
		syslog(LOG_ERR, "rlbuf malloc failed\n");
		exit(EXIT_FAILURE);
	}
	(void) alarm(60);
	if (read(f, &c, 1) != 1 || c != 0) {
		syslog(LOG_ERR, "failed to receive protocol zero byte\n");
		exit(EXIT_FAILURE);
	}
	(void) alarm(0);
	if (fromp->ss_family == AF_INET) {
		sin = (struct sockaddr_in *)fromp;
		port = sin->sin_port = ntohs((ushort_t)sin->sin_port);
		fromplen = sizeof (struct sockaddr_in);

		if (!inet_ntop(AF_INET, &sin->sin_addr,
			    rhost_addra, sizeof (rhost_addra)))
			goto badconversion;
	} else if (fromp->ss_family == AF_INET6) {
		sin6 = (struct sockaddr_in6 *)fromp;
		port = sin6->sin6_port = ntohs((ushort_t)sin6->sin6_port);
		fromplen = sizeof (struct sockaddr_in6);

		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
			struct in_addr ipv4_addr;

			IN6_V4MAPPED_TO_INADDR(&sin6->sin6_addr,
					    &ipv4_addr);
			if (!inet_ntop(AF_INET, &ipv4_addr, rhost_addra,
				    sizeof (rhost_addra)))
				goto badconversion;
		} else {
			if (!inet_ntop(AF_INET6, &sin6->sin6_addr,
				    rhost_addra, sizeof (rhost_addra)))
				goto badconversion;
		}
	} else {
		syslog(LOG_ERR, "unknown address family %d\n",
		    fromp->ss_family);
		fatal(f, "Permission denied");
	}

	/*
	 * Allow connections only from the "ephemeral" reserved
	 * ports(ports 512 - 1023) by checking the remote port
	 * because other utilities(e.g. in.ftpd) can be used to
	 * allow a unprivileged user to originate a connection
	 * from a privileged port and provide untrustworthy
	 * authentication.
	 */
	bad_port = (use_auth != KRB5_RECVAUTH_V5 &&
		    (port >= (in_port_t)IPPORT_RESERVED) ||
		    (port < (in_port_t)(IPPORT_RESERVED/2)));
	no_name = getnameinfo((const struct sockaddr *) fromp,
			    fromplen, hostname, sizeof (hostname),
			    NULL, 0, 0) != 0;

	if (no_name || bad_port) {
		(void) strlcpy(abuf, rhost_addra, sizeof (abuf));
		/* If no host name, use IP address for name later on. */
		if (no_name)
			(void) strlcpy(hostname, abuf, sizeof (hostname));
	}

	if (!no_name) {
		/*
		 * Even if getnameinfo() succeeded, we still have to check
		 * for spoofing.
		 */
		check_address("rlogind", fromp, sin, sin6, rhost_addra,
		    hostname, sizeof (hostname));
	}

	if (bad_port) {
		if (no_name)
			syslog(LOG_NOTICE,
			    "connection from %s - bad port\n",
			    abuf);
		else
			syslog(LOG_NOTICE,
			    "connection from %s(%s) - bad port\n",
			    hostname, abuf);
		fatal(f, "Permission denied");
	}

	if (use_auth == KRB5_RECVAUTH_V5) {
		do_krb_login(f, rhost_addra, hostname,
			    krb_context, encr_flag, keytab);
		if (krusername != NULL && strlen(krusername)) {
			/*
			 * Kerberos Authentication succeeded,
			 * so set the proper program name to use
			 * with pam (important during 'cleanup'
			 * routine later).
			 */
			pam_prog_name = KRB5_PROG_NAME;
		}
	}

	if (write(f, "", 1) != 1) {
		syslog(LOG_NOTICE,
		    "send of the zero byte(to %s) failed:"
		    " cannot start data transfer mode\n",
		    (no_name ? abuf : hostname));
		exit(EXIT_FAILURE);
	}
	if ((p = open("/dev/ptmx", O_RDWR)) == -1)
		fatalperror(f, "cannot open /dev/ptmx");
	if (grantpt(p) == -1)
		fatal(f, "could not grant slave pty");
	if (unlockpt(p) == -1)
		fatal(f, "could not unlock slave pty");
	if ((line = ptsname(p)) == NULL)
		fatal(f, "could not enable slave pty");
	if ((t = open(line, O_RDWR)) == -1)
		fatal(f, "could not open slave pty");
	if (ioctl(t, I_PUSH, "ptem") == -1)
		fatalperror(f, "ioctl I_PUSH ptem");
	if (ioctl(t, I_PUSH, "ldterm") == -1)
		fatalperror(f, "ioctl I_PUSH ldterm");
	if (ioctl(t, I_PUSH, "ttcompat") == -1)
		fatalperror(f, "ioctl I_PUSH ttcompat");
	/*
	 * POP the sockmod and push the rlmod module.
	 *
	 * Note that sockmod has to be removed since readstream assumes
	 * a "raw" TPI endpoint(e.g. it uses getmsg).
	 */
	if (removemod(f, "sockmod") < 0)
		fatalperror(f, "couldn't remove sockmod");

	if (encr_flag) {
		if (ioctl(f, I_PUSH, "cryptmod") < 0)
		    fatalperror(f, "ioctl I_PUSH rlmod");

	}

	if (ioctl(f, I_PUSH, "rlmod") < 0)
		fatalperror(f, "ioctl I_PUSH rlmod");

	if (encr_flag) {
		/*
		 * Make sure rlmod will pass unrecognized IOCTLs to cryptmod
		 */
		uchar_t passthru = 1;
		struct strioctl rlmodctl;

		rlmodctl.ic_cmd = CRYPTPASSTHRU;
		rlmodctl.ic_timout = -1;
		rlmodctl.ic_len = sizeof (uchar_t);
		rlmodctl.ic_dp = (char *)&passthru;

		if (ioctl(f, I_STR, &rlmodctl) < 0)
			fatal(f, "ioctl CRYPTPASSTHRU failed\n");
	}

	/*
	 * readstream will do a getmsg till it receives
	 * M_PROTO type T_DATA_REQ from rloginmodopen()
	 * indicating all data on the stream prior to pushing rlmod has
	 * been drained at the stream head.
	 */
	if ((nsize = readstream(f, rlbuf, BUFSIZ)) < 0)
		fatalperror(f, "readstream failed");
	/*
	 * Make sure the pty doesn't modify the strings passed
	 * to login as part of the "rlogin protocol."  The login
	 * program should set these flags to apropriate values
	 * after it has read the strings.
	 */
	if (ioctl(t, TCGETS, &tp) == -1)
		fatalperror(f, "ioctl TCGETS");
	tp.c_lflag &= ~(ECHO|ICANON);
	tp.c_oflag &= ~(XTABS|OCRNL);
	tp.c_iflag &= ~(IGNPAR|ICRNL);
	if (ioctl(t, TCSETS, &tp) == -1)
		fatalperror(f, "ioctl TCSETS");

	/*
	 * System V ptys allow the TIOC{SG}WINSZ ioctl to be
	 * issued on the master side of the pty.  Luckily, that's
	 * the only tty ioctl we need to do do, so we can close the
	 * slave side in the parent process after the fork.
	 */
	(void) ioctl(p, TIOCSWINSZ, &win);

	pid = fork();
	if (pid < 0)
		fatalperror(f, "fork");
	if (pid == 0) {
		int tt;
		struct utmpx ut;

		/* System V login expects a utmp entry to already be there */
		(void) memset(&ut, 0, sizeof (ut));
		(void) strncpy(ut.ut_user, ".rlogin", sizeof (ut.ut_user));
		(void) strncpy(ut.ut_line, line, sizeof (ut.ut_line));
		ut.ut_pid = getpid();
		ut.ut_id[0] = 'r';
		ut.ut_id[1] = (char)SC_WILDC;
		ut.ut_id[2] = (char)SC_WILDC;
		ut.ut_id[3] = (char)SC_WILDC;
		ut.ut_type = LOGIN_PROCESS;
		ut.ut_exit.e_termination = 0;
		ut.ut_exit.e_exit = 0;
		(void) time(&ut.ut_tv.tv_sec);
		if (makeutx(&ut) == NULL)
			syslog(LOG_INFO, "in.rlogind:\tmakeutx failed");

		/* controlling tty */
		if (setsid() == -1)
			fatalperror(f, "setsid");
		if ((tt = open(line, O_RDWR)) == -1)
			fatalperror(f, "could not re-open slave pty");

		if (close(p) == -1)
			fatalperror(f, "error closing pty master");
		if (close(t) == -1)
			fatalperror(f, "error closing pty slave"
				    " opened before session established");
		/*
		 * If this fails we may or may not be able to output an
		 * error message.
		 */
		if (close(f) == -1)
			fatalperror(f, "error closing deamon stdout");
		if (dup2(tt, STDIN_FILENO) == -1 ||
		    dup2(tt, STDOUT_FILENO) == -1 ||
		    dup2(tt, STDERR_FILENO) == -1)
			exit(EXIT_FAILURE);	/* Disaster! No stderr! */

		(void) close(tt);

		if (use_auth == KRB5_RECVAUTH_V5 &&
		    krusername != NULL && strlen(krusername)) {
			(void) execl(LOGIN_PROGRAM, "login",
				    "-d", line,
				    "-r", hostname,
				    "-u", krusername, /* KRB5 principal name */
				    "-s", pam_prog_name,
				    "-t", term,	/* Remote Terminal */
				    "-U", rusername,	/* Remote User */
				    "-R", KRB5_REPOSITORY_NAME,
				    lusername,  /* local user */
				    NULL);
		} else {
			(void) execl(LOGIN_PROGRAM, "login",
				"-d", line,
				"-r", hostname,
				NULL);
		}

		fatalperror(STDERR_FILENO, "/bin/login");
		/*NOTREACHED*/
	}
	(void) close(t);
	(void) ioctl(f, FIONBIO, &on);
	(void) ioctl(p, FIONBIO, &on);

	/*
	 * Must ignore SIGTTOU, otherwise we'll stop
	 * when we try and set slave pty's window shape
	 * (our controlling tty is the master pty).
	 * Likewise, we don't want any of the tty-generated
	 * signals from chars passing through.
	 */
	(void) sigset(SIGTSTP, SIG_IGN);
	(void) sigset(SIGINT, SIG_IGN);
	(void) sigset(SIGQUIT, SIG_IGN);
	(void) sigset(SIGTTOU, SIG_IGN);
	(void) sigset(SIGTTIN, SIG_IGN);
	(void) sigset(SIGCHLD, cleanup);
	(void) setpgrp();

	if (encr_flag) {
		krb5_data ivec, *ivptr;
		uint_t ivec_usage;
		stop_stream(f, CRYPT_ENCRYPT|CRYPT_DECRYPT);

		/*
		 * Configure the STREAMS crypto module.  For now,
		 * don't use any IV parameter.  KCMDV0.2 support
		 * will require the use of Initialization Vectors
		 * for both encrypt and decrypt modes.
		 */
		if (kcmd_protocol == KCMD_OLD_PROTOCOL) {
			if (session_key->enctype == ENCTYPE_DES_CBC_CRC) {
				/*
				 * This is gross but necessary for MIT compat.
				 */
				ivec.length = session_key->length;
				ivec.data = (char *)session_key->contents;
				ivec_usage = IVEC_REUSE;
				ivptr = &ivec;
			} else {
				ivptr = NULL; /* defaults to all 0's */
				ivec_usage = IVEC_NEVER;
			}
			/*
			 * configure both sides of stream together
			 * since they share the same IV.
			 * This is what makes the OLD KCMD protocol
			 * less secure than the newer one - Bad ivecs.
			 */
			if (configure_stream(f, session_key,
				CRYPT_ENCRYPT|CRYPT_DECRYPT,
				ivptr, ivec_usage) != 0)
				fatal(f, "Cannot initialize encryption -"
					" exiting.\n");
		} else {
			size_t blocksize;
			if (session_key->enctype == ENCTYPE_ARCFOUR_HMAC ||
			    session_key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) {
				if (configure_stream(f, session_key,
					CRYPT_ENCRYPT|CRYPT_DECRYPT,
					NULL, IVEC_NEVER) != 0)
					fatal(f,
					"Cannot initialize encryption -"
					" exiting.\n");
				goto startcrypto;
			}
			if (krb5_c_block_size(krb_context,
					    session_key->enctype,
					    &blocksize)) {
				syslog(LOG_ERR, "Cannot determine blocksize "
				    "for encryption type %d",
				    session_key->enctype);
				fatal(f, "Cannot determine blocksize "
				    "for encryption - exiting.\n");
			}
			ivec.data = (char *)malloc(blocksize);
			ivec.length = blocksize;
			if (ivec.data == NULL)
				fatal(f, "memory error - exiting\n");
			/*
			 * Following MIT convention -
			 *   encrypt IV = 0x01 x blocksize
			 *   decrypt IV = 0x00 x blocksize
			 *   ivec_usage = IVEC_ONETIME
			 *
			 * configure_stream separately for encrypt and
			 * decrypt because there are 2 different IVs.
			 *
			 * AES uses 0's for IV.
			 */
			if (session_key->enctype ==
				ENCTYPE_AES128_CTS_HMAC_SHA1_96 ||
			    session_key->enctype ==
				ENCTYPE_AES256_CTS_HMAC_SHA1_96)
				(void) memset(ivec.data, 0x00, blocksize);
			else
				(void) memset(ivec.data, 0x01, blocksize);
			if (configure_stream(f, session_key, CRYPT_ENCRYPT,
				&ivec, IVEC_ONETIME) != 0)
				fatal(f, "Cannot initialize encryption -"
					" exiting.\n");
			(void) memset(ivec.data, 0x00, blocksize);
			if (configure_stream(f, session_key, CRYPT_DECRYPT,
				&ivec, IVEC_ONETIME) != 0)
				fatal(f, "Cannot initialize encryption -"
					" exiting.\n");

			(void) free(ivec.data);
		}
startcrypto:
		start_stream(f, CRYPT_ENCRYPT);
		start_stream(f, CRYPT_DECRYPT);
	}
	protocol(f, p, encr_flag);
	cleanup(0);
	/*NOTREACHED*/

badconversion:
	fatalperror(f, "address conversion");
	/*NOTREACHED*/
}
Beispiel #9
0
/*
 * Display selected fields of the flow_entry_t structure
 */
static int
mac_flow_dcmd_output(uintptr_t addr, uint_t flags, uint_t args)
{
	static const mdb_bitmask_t flow_type_bits[] = {
		{"P", FLOW_PRIMARY_MAC, FLOW_PRIMARY_MAC},
		{"V", FLOW_VNIC_MAC, FLOW_VNIC_MAC},
		{"M", FLOW_MCAST, FLOW_MCAST},
		{"O", FLOW_OTHER, FLOW_OTHER},
		{"U", FLOW_USER, FLOW_USER},
		{"V", FLOW_VNIC, FLOW_VNIC},
		{"NS", FLOW_NO_STATS, FLOW_NO_STATS},
		{ NULL, 0, 0 }
	};
#define	FLOW_MAX_TYPE	(sizeof (flow_type_bits) / sizeof (mdb_bitmask_t))

	static const mdb_bitmask_t flow_flag_bits[] = {
		{"Q", FE_QUIESCE, FE_QUIESCE},
		{"W", FE_WAITER, FE_WAITER},
		{"T", FE_FLOW_TAB, FE_FLOW_TAB},
		{"G", FE_G_FLOW_HASH, FE_G_FLOW_HASH},
		{"I", FE_INCIPIENT, FE_INCIPIENT},
		{"C", FE_CONDEMNED, FE_CONDEMNED},
		{"NU", FE_UF_NO_DATAPATH, FE_UF_NO_DATAPATH},
		{"NC", FE_MC_NO_DATAPATH, FE_MC_NO_DATAPATH},
		{ NULL, 0, 0 }
	};
#define	FLOW_MAX_FLAGS	(sizeof (flow_flag_bits) / sizeof (mdb_bitmask_t))
	flow_entry_t		fe;
	mac_client_impl_t	mcip;
	mac_impl_t		mip;

	if (mdb_vread(&fe, sizeof (fe), addr) == -1) {
		mdb_warn("failed to read struct flow_entry_s at %p", addr);
		return (DCMD_ERR);
	}
	if (args & MAC_FLOW_USER) {
		args &= ~MAC_FLOW_USER;
		if (fe.fe_type & FLOW_MCAST) {
			if (DCMD_HDRSPEC(flags))
				mac_flow_print_header(args);
			return (DCMD_OK);
		}
	}
	if (DCMD_HDRSPEC(flags))
		mac_flow_print_header(args);
	bzero(&mcip, sizeof (mcip));
	bzero(&mip, sizeof (mip));
	if (fe.fe_mcip != NULL && mdb_vread(&mcip, sizeof (mcip),
	    (uintptr_t)fe.fe_mcip) == sizeof (mcip)) {
		(void) mdb_vread(&mip, sizeof (mip), (uintptr_t)mcip.mci_mip);
	}
	switch (args) {
	case MAC_FLOW_NONE: {
		mdb_printf("%?p %-20s %4d %?p "
		    "%?p %-16s\n",
		    addr, fe.fe_flow_name, fe.fe_link_id, fe.fe_mcip,
		    mcip.mci_mip, mip.mi_name);
		break;
	}
	case MAC_FLOW_ATTR: {
		struct	in_addr	in4;
		uintptr_t	desc_addr;
		flow_desc_t	fdesc;

		desc_addr = addr + OFFSETOF(flow_entry_t, fe_flow_desc);
		if (mdb_vread(&fdesc, sizeof (fdesc), desc_addr) == -1) {
			mdb_warn("failed to read struct flow_description at %p",
			    desc_addr);
			return (DCMD_ERR);
		}
		mdb_printf("%?p %-32s "
		    "%-7s %6d "
		    "%4d:%-4d ",
		    addr, fe.fe_flow_name,
		    mac_flow_proto2str(fdesc.fd_protocol), fdesc.fd_local_port,
		    fdesc.fd_dsfield, fdesc.fd_dsfield_mask);
		if (fdesc.fd_ipversion == IPV4_VERSION) {
			IN6_V4MAPPED_TO_INADDR(&fdesc.fd_local_addr, &in4);
			mdb_printf("%I", in4.s_addr);
		} else if (fdesc.fd_ipversion == IPV6_VERSION) {
			mdb_printf("%N", &fdesc.fd_local_addr);
		} else {
			mdb_printf("%s", "--");
		}
		mdb_printf("\n");
		break;
	}
	case MAC_FLOW_PROP: {
		uintptr_t	prop_addr;
		char		bwstr[STRSIZE];
		mac_resource_props_t	fprop;

		prop_addr = addr + OFFSETOF(flow_entry_t, fe_resource_props);
		if (mdb_vread(&fprop, sizeof (fprop), prop_addr) == -1) {
			mdb_warn("failed to read struct mac_resoource_props "
			    "at %p", prop_addr);
			return (DCMD_ERR);
		}
		mdb_printf("%?p %-32s "
		    "%8s %9s\n",
		    addr, fe.fe_flow_name,
		    mac_flow_bw2str(fprop.mrp_maxbw, bwstr, STRSIZE),
		    mac_flow_priority2str(fprop.mrp_priority));
		break;
	}
	case MAC_FLOW_MISC: {
		char		flow_flags[2 * FLOW_MAX_FLAGS];
		char		flow_type[2 * FLOW_MAX_TYPE];
		GElf_Sym	sym;
		char		func_name[MDB_SYM_NAMLEN] = "";
		uintptr_t	func, match_addr;

		match_addr = addr + OFFSETOF(flow_entry_t, fe_match);
		(void) mdb_vread(&func, sizeof (func), match_addr);
		(void) mdb_lookup_by_addr(func, MDB_SYM_EXACT, func_name,
		    MDB_SYM_NAMLEN, &sym);
		mdb_snprintf(flow_flags, 2 * FLOW_MAX_FLAGS, "%hb",
		    fe.fe_flags, flow_flag_bits);
		mdb_snprintf(flow_type, 2 * FLOW_MAX_TYPE, "%hb",
		    fe.fe_type, flow_type_bits);
		mdb_printf("%?p %-24s %10s %10s %20s\n",
		    addr, fe.fe_flow_name, flow_type, flow_flags, func_name);
		break;
	}
	case MAC_FLOW_RX: {
		uintptr_t	rxaddr, rx_srs[MAX_RINGS_PER_GROUP] = {0};
		int		i;

		rxaddr = addr + OFFSETOF(flow_entry_t, fe_rx_srs);
		(void) mdb_vread(rx_srs, MAC_RX_SRS_SIZE, rxaddr);
		mdb_printf("%?p %-24s %3d ",
		    addr, fe.fe_flow_name, fe.fe_rx_srs_cnt);
		for (i = 0; i < MAX_RINGS_PER_GROUP; i++) {
			if (rx_srs[i] == 0)
				continue;
			mdb_printf("%p ", rx_srs[i]);
		}
		mdb_printf("\n");
		break;
	}
	case MAC_FLOW_TX: {
		uintptr_t	tx_srs = 0, txaddr;

		txaddr = addr + OFFSETOF(flow_entry_t, fe_tx_srs);
		(void) mdb_vread(&tx_srs, sizeof (uintptr_t), txaddr);
		mdb_printf("%?p %-32s %?p\n",
		    addr, fe.fe_flow_name, fe.fe_tx_srs);
		break;
	}
	case MAC_FLOW_STATS: {
		uint64_t		totibytes = 0;
		uint64_t		totobytes = 0;
		mac_soft_ring_set_t	*mac_srs;
		mac_rx_stats_t		mac_rx_stat;
		mac_tx_stats_t		mac_tx_stat;
		int			i;

		/*
		 * Sum bytes for all Rx SRS.
		 */
		for (i = 0; i < fe.fe_rx_srs_cnt; i++) {
			mac_srs = (mac_soft_ring_set_t *)(fe.fe_rx_srs[i]);
			if (mdb_vread(&mac_rx_stat, sizeof (mac_rx_stats_t),
			    (uintptr_t)&mac_srs->srs_rx.sr_stat) == -1) {
				mdb_warn("failed to read mac_rx_stats_t at %p",
				    &mac_srs->srs_rx.sr_stat);
				return (DCMD_ERR);
			}

			totibytes += mac_rx_stat.mrs_intrbytes +
			    mac_rx_stat.mrs_pollbytes +
			    mac_rx_stat.mrs_lclbytes;
		}

		/*
		 * Sum bytes for Tx SRS.
		 */
		mac_srs = (mac_soft_ring_set_t *)(fe.fe_tx_srs);
		if (mac_srs != NULL) {
			if (mdb_vread(&mac_tx_stat, sizeof (mac_tx_stats_t),
			    (uintptr_t)&mac_srs->srs_tx.st_stat) == -1) {
				mdb_warn("failed to read max_tx_stats_t at %p",
				    &mac_srs->srs_tx.st_stat);
				return (DCMD_ERR);
			}

			totobytes = mac_tx_stat.mts_obytes;
		}

		mdb_printf("%?p %-32s %16llu %16llu\n",
		    addr, fe.fe_flow_name, totibytes, totobytes);

		break;
	}
	}
	return (DCMD_OK);
}
Beispiel #10
0
void *
port_watcher(void *v)
{
	int			s,
				fd,
				on = 1;
	char			debug[80];
	struct sockaddr_in	sin_ip;
	struct sockaddr_in6	sin6_ip;
	struct sockaddr_storage	st;
	socklen_t		socklen;
	iscsi_conn_t		*conn;
	port_args_t		*p = (port_args_t *)v;
	target_queue_t		*q = p->port_mgmtq;
	int			l,
				accept_err_sleep = 1;
	pthread_t		junk;
	struct in_addr		addr;
	struct in6_addr		addr6;

	/*
	 * Try creating an IPv6 socket first
	 * If failed, try creating an IPv4 socket
	 */
	if ((s = socket(PF_INET6, SOCK_STREAM, 0)) == -1) {

		queue_str(q, Q_GEN_ERRS, msg_log, "Opening IPv4 socket");
		if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
			queue_str(q, Q_GEN_ERRS, msg_log,
			    "Can't open socket");
			return (NULL);
		} else {
			bzero(&sin_ip, sizeof (sin_ip));
			sin_ip.sin_family = AF_INET;
			sin_ip.sin_port = htons(p->port_num);
			sin_ip.sin_addr.s_addr = INADDR_ANY;

			(void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
			    (char *)&on, sizeof (on));

			if ((bind(s, (struct sockaddr *)&sin_ip,
				sizeof (sin_ip))) < 0) {
				(void) snprintf(debug, sizeof (debug),
				    "bind on port %d failed, errno %d",
				    p->port_num, errno);
				queue_str(q, Q_GEN_ERRS, msg_status, debug);
				return (NULL);
			}
		}

	} else {

		queue_str(q, Q_GEN_DETAILS, msg_log, "Got IPv6 socket");
		bzero(&sin6_ip, sizeof (sin6_ip));
		sin6_ip.sin6_family = AF_INET6;
		sin6_ip.sin6_port = htons(p->port_num);
		sin6_ip.sin6_addr = in6addr_any;

		(void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
		    sizeof (on));

		if ((bind(s, (struct sockaddr *)&sin6_ip, sizeof (sin6_ip)))
		    < 0) {
			(void) snprintf(debug, sizeof (debug),
			    "bind on port %d failed, errno %d",
			    p->port_num, errno);
			queue_str(q, Q_GEN_ERRS, msg_status, debug);
			return (NULL);
		}
	}

	if (listen(s, 5) < 0) {
		queue_str(q, Q_GEN_ERRS, msg_status, "listen failed");
		return (NULL);
	}

	/*CONSTANTCONDITION*/
	while (1) {

		socklen = sizeof (st);
		if ((fd = accept(s, (struct sockaddr *)&st,
		    &socklen)) < 0) {
			accept_err_sleep *= 2;
			(void) sleep(accept_err_sleep);
			if (accept_err_sleep > 60) {
				accept_err_sleep = 1;
				queue_prt(q, Q_GEN_ERRS,
				    "accept failed, errno %d", errno);
			}
			continue;
		}

		l = 128 * 1024;
		if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&l,
		    sizeof (l)) < 0)
			queue_str(q, Q_GEN_ERRS, msg_status,
			    "setsockopt failed");
		if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&l,
		    sizeof (l)) < 0)
			queue_str(q, Q_GEN_ERRS, msg_status,
			    "setsockopt failed");
		l = 1;
		if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&l,
		    sizeof (l)) < 0)
			queue_str(q, Q_GEN_ERRS, msg_status,
			    "setsockopt keepalive failed");

		if ((conn = (iscsi_conn_t *)calloc(sizeof (iscsi_conn_t),
		    1)) == NULL) {
			/*
			 * If we fail to get memory this is all rather
			 * pointless, since it's unlikely that queue_str
			 * could malloc memory to send a message.
			 */
			queue_str(q, Q_GEN_ERRS, msg_status,
			    "connection malloc failed");
			return (NULL);
		}

		/*
		 * Save initiator sockaddr for future use
		 */
		conn->c_initiator_sockaddr = st;

		socklen = sizeof (st);
		if (getsockname(fd, (struct sockaddr *)&st,
		    &socklen) == 0) {
			/*
			 * Save target sockaddr for future use
			 */

			addr6 = ((struct sockaddr_in6 *)&st)->sin6_addr;
			if (st.ss_family == AF_INET6 &&
			    IN6_IS_ADDR_V4MAPPED(&addr6)) {
				/*
				 * If target address is IPv4 mapped IPv6 address
				 * convert it to IPv4 address
				 */
				IN6_V4MAPPED_TO_INADDR(&addr6, &addr);
				((struct sockaddr_in *)&st)->sin_addr = addr;
				st.ss_family = AF_INET;
			}

			conn->c_target_sockaddr = st;
		}

		conn->c_fd	= fd;
		conn->c_mgmtq	= q;
		conn->c_up_at	= time(NULL);
		conn->c_state	= S1_FREE;
		(void) pthread_mutex_init(&conn->c_mutex, NULL);
		(void) pthread_mutex_init(&conn->c_state_mutex, NULL);
		(void) pthread_mutex_lock(&port_mutex);
		conn->c_num	= port_conn_num++;
		if (conn_head == NULL) {
			conn_head = conn;
			assert(conn_tail == NULL);
			conn_tail = conn;
		} else {
			conn_tail->c_next = conn;
			conn->c_prev = conn_tail;
			conn_tail = conn;
		}
		(void) pthread_mutex_unlock(&port_mutex);

		(void) pthread_create(&junk, NULL, conn_process, conn);
	}
	return (NULL);
}
Beispiel #11
0
/*
 * This routine will convert a mapped v4 hostent (AF_INET6) to a
 * AF_INET hostent. If no mapped addrs found, then a NULL is returned.
 * If mapped addrs found, then a new buffer is alloc'd and all the v4 mapped
 * addresses are extracted and copied to it. On sucess, a pointer to a new
 * hostent is returned.
 * There are two possible errors in which case a NULL is returned.
 * One of two error codes are returned:
 *
 * NO_RECOVERY - a malloc failed or the like for which there's no recovery.
 * NO_ADDRESS - after filtering all the v4, there was nothing left!
 *
 * Inputs:
 *              he              pointer to hostent with mapped v4 addresses
 *              filter_error    pointer to return error code
 * Return:
 *		pointer to a malloc'd hostent with v4 addresses.
 *
 * The results are packed into the res->buffer as follows:
 * <--------------- buffer + buflen -------------------------------------->
 * |-----------------|-----------------|----------------|----------------|
 * | pointers vector | pointers vector | aliases grow   | addresses grow |
 * | for addresses   | for aliases     |                |                |
 * | this way ->     | this way ->     | <- this way    |<- this way     |
 * |-----------------|-----------------|----------------|----------------|
 * | grows in PASS 1 | grows in PASS2  | grows in PASS2 | grows in PASS 1|
 */
struct hostent *
__mappedtov4(struct hostent *he, int *extract_error)
{
	char	*buffer, *limit;
	nss_XbyY_buf_t *res;
	int	buflen = NSS_BUFLEN_HOSTS;
	struct	in_addr *addr4p;
	char	*buff_locp;
	struct	hostent *host;
	int	count = 0, len, i;
	char	*h_namep;

	if (he == NULL) {
		*extract_error = NO_ADDRESS;
		return (NULL);
	}
	if ((__find_mapped(he, 0)) == 0) {
		*extract_error = NO_ADDRESS;
		return (NULL);
	}
	if ((res = __IPv6_alloc(NSS_BUFLEN_HOSTS)) == 0) {
		*extract_error = NO_RECOVERY;
		return (NULL);
	}
	limit = res->buffer + buflen;
	host = (struct hostent *)res->result;
	buffer = res->buffer;

	buff_locp = (char *)ROUND_DOWN(limit, sizeof (struct in_addr));
	host->h_addr_list = (char **)ROUND_UP(buffer, sizeof (char **));
	if ((char *)host->h_addr_list >= limit ||
	    buff_locp <= (char *)host->h_addr_list)
		goto cleanup;
	/*
	 * "Unmap" the v4 mapped address(es) into a v4 hostent format.
	 * This is used for getipnodebyaddr() (single address) or for
	 * v4 mapped for getipnodebyname(), which could be multiple
	 * addresses. This could also be a literal address string,
	 * which is why there is a inet_addr() call.
	 */
	for (i = 0; he->h_addr_list[i] != NULL; i++) {
		/* LINTED pointer cast */
		if (!IN6_IS_ADDR_V4MAPPED((struct in6_addr *)
		    he->h_addr_list[i]))
			continue;
		buff_locp -= sizeof (struct in6_addr);
		/*
		 * Has to be room for the pointer to the address we're
		 * about to add, as well as the final NULL ptr.
		 */
		if (buff_locp <=
		    (char *)&(host->h_addr_list[count + 1]))
			goto cleanup;
		/* LINTED pointer cast */
		addr4p = (struct in_addr *)buff_locp;
		host->h_addr_list[count] = (char *)addr4p;
		bzero((char *)&addr4p->s_addr,
		    sizeof (struct in_addr));
		/* LINTED pointer cast */
		IN6_V4MAPPED_TO_INADDR(
		    (struct in6_addr *)he->h_addr_list[i], addr4p);
		++count;
	}
	/*
	 * Set last array element to NULL and add cname as first alias
	 */
	host->h_addr_list[count] = NULL;
	host->h_aliases = host->h_addr_list + count + 1;
	count = 0;
	/* Copy official host name */
	buff_locp -= (len = strlen(he->h_name) + 1);
	h_namep = he->h_name;
	if (buff_locp <= (char *)(host->h_aliases))
		goto cleanup;
	bcopy(h_namep, buff_locp, len);
	host->h_name = buff_locp;
	/*
	 * Pass 2 (IPv4 aliases):
	 */
	if (he->h_aliases != NULL) {
		for (i = 0; he->h_aliases[i] != NULL; i++) {
			buff_locp -= (len = strlen(he->h_aliases[i]) + 1);
			/*
			 * Has to be room for the pointer to the address we're
			 * about to add, as well as the final NULL ptr.
			 */
			if (buff_locp <=
			    (char *)&(host->h_aliases[count + 1]))
				goto cleanup;
			host->h_aliases[count] = buff_locp;
			bcopy((char *)he->h_aliases[i], buff_locp, len);
			++count;
		}
	}
	host->h_aliases[count] = NULL;
	host->h_length = sizeof (struct in_addr);
	host->h_addrtype = AF_INET;
	free(res);
	return (host);
cleanup:
	*extract_error = NO_RECOVERY;
	(void) __IPv6_cleanup(res);
	return (NULL);
}