Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 29 Jul 2002 02:47:08 -0700 (PDT)
From:      Don Lewis <dl-freebsd@catspoiler.org>
To:        current@FreeBSD.org
Cc:        hsu@FreeBSD.org, ume@FreeBSD.org, suz@kame.net
Subject:   unbloating {tcp,tcp6,udp,udp6}_getcred()
Message-ID:  <200207290947.g6T9l8wr065555@gw.catspoiler.org>

next in thread | raw e-mail | index | archive | help
The tcp_getcred(), tcp6_getcred(), udp_getcred(), udp6_getcred() look
like a bad example of mostly duplicated code caused by cut and paste
programming.  By passing a pointer to the inpcbinfo structure as an
argument to the sysctl hander it is possible to combine the use a common
handler for the TCP and UDP cases, and the IPv4 and IPv6 handlers can
use a common back end once the PCB has been looked up.

To switch tcp_getcred() to use this new handler, you would make the
following change:

 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, getcred,
-    CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0,
-    tcp_getcred, "S,xucred", "Get the xucred of a TCP connection");
+    CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_PRISON, &tcbinfo, 0,
+    in_pcbgetcred_handler, "S,xucred", "Get the xucred of a TCP connection");


The pcblist sysctl handlers look like another case of cut and paste
programming ...


=======================Cut Here===========================
#include "opt_inet6.h"

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/jail.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/ucred.h>

#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/in_pcbgetcred.h>
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/in6_pcb.h>
#endif /* INET6 */


/*
 * Convert the socket credential for inp to external format, unlock pcbinfo,
 * and return the credential info using SYSCTL_OUT().
 */
static int
in_getcred(struct sysctl_req *req, struct inpcbinfo *pcbinfo, struct inpcb *inp,
    int s)
{
	struct xucred xuc;
	int error;

	if (inp == NULL) {
		error = ENOENT;
		goto out;
	}
	/*
	 * XXX - It should not be necessary to lock the PCB or
	 *       test inp_socket, since inp_socket is static
	 *       for the life of the PCB.
	 */
	INP_LOCK(inp);
	if (inp->inp_socket == NULL) {
		error = ENOENT;
		goto outlocked;
	}
	error = cr_canseesocket(req->td->td_ucred, inp->inp_socket);
	if (error == 0)
		cru2x(inp->inp_socket->so_cred, &xuc);
outlocked:
	INP_UNLOCK(inp);
out:
	INP_INFO_RUNLOCK(pcbinfo);
	splx(s);
	if (error == 0)
		error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
	return (error);
}

/*
 * Socket credential sysctl handler.
 * The pcbinfo pointer should be passed as arg1.
 */
int
in_pcbgetcred_handler(SYSCTL_HANDLER_ARGS)
{
	struct inpcbinfo *pcbinfo = arg1;
	struct sockaddr_in addrs[2];
	struct inpcb *inp;
	int error, s;

	error = suser_cred(req->td->td_ucred, PRISON_ROOT);
	if (error)
		return (error);
	error = SYSCTL_IN(req, addrs, sizeof(addrs));
	if (error)
		return (error);
	s = splnet();
	INP_INFO_RLOCK(pcbinfo);
	inp = in_pcblookup_hash(pcbinfo, addrs[1].sin_addr, addrs[1].sin_port,
	    addrs[0].sin_addr, addrs[0].sin_port, 0, NULL);
	return (in_getcred(req, pcbinfo, inp, s));
}

#ifdef INET6
int
in6_pcbgetcred_handler(SYSCTL_HANDLER_ARGS)
{
	struct inpcbinfo *pcbinfo = arg1;
	struct sockaddr_in6 addrs[2];
	struct inpcb *inp;
	int error, s, mapped = 0;

	error = suser_cred(req->td->td_ucred, PRISON_ROOT);
	if (error)
		return (error);
	error = SYSCTL_IN(req, addrs, sizeof(addrs));
	if (error)
		return (error);
	if (IN6_IS_ADDR_V4MAPPED(&addrs[0].sin6_addr)) {
		if (IN6_IS_ADDR_V4MAPPED(&addrs[1].sin6_addr))
			mapped = 1;
		else
			return (EINVAL);
	}
	s = splnet();
	INP_INFO_RLOCK(pcbinfo);
	if (mapped == 1)
		inp = in_pcblookup_hash(pcbinfo,
			*(struct in_addr *)&addrs[1].sin6_addr.s6_addr[12],
			addrs[1].sin6_port,
			*(struct in_addr *)&addrs[0].sin6_addr.s6_addr[12],
			addrs[0].sin6_port,
			0, NULL);
	else
		inp = in6_pcblookup_hash(pcbinfo, &addrs[1].sin6_addr,
				 addrs[1].sin6_port,
				 &addrs[0].sin6_addr, addrs[0].sin6_port,
				 0, NULL);
	return (in_getcred(req, pcbinfo, inp, s));
}
#endif
=======================Cut Here===========================


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200207290947.g6T9l8wr065555>