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 [EMAIL PROTECTED] with "unsubscribe freebsd-current" in the body of the message