FreeBSD/sys/netpfil/ipfw/ip_fw2.c
/*
 * Support for uid/gid/jail lookup. These tests are expensive
 * (because we may need to look into the list of active sockets)
 * so we cache the results. ugid_lookupp is 0 if we have not
 * yet done a lookup, 1 if we succeeded, and -1 if we tried
 * and failed. The function always returns the match value.
 * We could actually spare the variable and use *uc, setting
 * it to '(void *)check_uidgid if we have no info, NULL if
 * we tried and failed, or any other value if successful.
 */
Support for uid/gid/jail lookup. These tests are expensive
(because we may need to look into the list of active sockets)
so we cache the results. ugid_lookupp is 0 if we have not
yet done a lookup, 1 if we succeeded, and -1 if we tried
and failed. The function always returns the match value.
We could actually spare the variable and use *uc, setting
it to '(void *)check_uidgid if we have no info, NULL if
we tried and failed, or any other value if successful.
Support for uid / gid / jail lookup . These tests are expensive ( because we may need to look into the list of active sockets ) so we cache the results . ugid_lookupp is 0 if we have not yet done a lookup 1 if we succeeded and - 1 if we tried and failed . The function always returns the match value . We could actually spare the variable and use * uc setting it to ' ( void * ) check_uidgid if we have no info NULL if we tried and failed or any other value if successful .
static int
check_uidgid(ipfw_insn_u32 *insn, struct ip_fw_args *args, int *ugid_lookupp,
    struct ucred **uc)
{
#if defined(USERSPACE)
	return 0;	
#else
#ifndef __FreeBSD__
	return cred_check(insn, proto, oif,
	    dst_ip, dst_port, src_ip, src_port,
	    (struct bsd_ucred *)uc, ugid_lookupp, ((struct mbuf *)inp)->m_skb);
#else  
	struct in_addr src_ip, dst_ip;
	struct inpcbinfo *pi;
	struct ipfw_flow_id *id;
	struct inpcb *pcb, *inp;
	struct ifnet *oif;
	int lookupflags;
	int match;
	id = &args->f_id;
	inp = args->inp;
	oif = args->oif;
	if (inp && *ugid_lookupp == 0) {
		INP_LOCK_ASSERT(inp);
		if (inp->inp_socket != NULL) {
			*uc = crhold(inp->inp_cred);
			*ugid_lookupp = 1;
		} else
			*ugid_lookupp = -1;
	}
	if (*ugid_lookupp == -1)
		return (0);
	if (id->proto == IPPROTO_TCP) {
		lookupflags = 0;
		pi = &V_tcbinfo;
	} else if (id->proto == IPPROTO_UDP) {
		lookupflags = INPLOOKUP_WILDCARD;
		pi = &V_udbinfo;
	} else
		return 0;
	lookupflags |= INPLOOKUP_RLOCKPCB;
	match = 0;
	if (*ugid_lookupp == 0) {
		if (id->addr_type == 6) {
#ifdef INET6
			if (oif == NULL)
				pcb = in6_pcblookup_mbuf(pi,
				    &id->src_ip6, htons(id->src_port),
				    &id->dst_ip6, htons(id->dst_port),
				    lookupflags, oif, args->m);
			else
				pcb = in6_pcblookup_mbuf(pi,
				    &id->dst_ip6, htons(id->dst_port),
				    &id->src_ip6, htons(id->src_port),
				    lookupflags, oif, args->m);
#else
			*ugid_lookupp = -1;
			return (0);
#endif
		} else {
			src_ip.s_addr = htonl(id->src_ip);
			dst_ip.s_addr = htonl(id->dst_ip);
			if (oif == NULL)
				pcb = in_pcblookup_mbuf(pi,
				    src_ip, htons(id->src_port),
				    dst_ip, htons(id->dst_port),
				    lookupflags, oif, args->m);
			else
				pcb = in_pcblookup_mbuf(pi,
				    dst_ip, htons(id->dst_port),
				    src_ip, htons(id->src_port),
				    lookupflags, oif, args->m);
		}
		if (pcb != NULL) {
			INP_RLOCK_ASSERT(pcb);
			*uc = crhold(pcb->inp_cred);
			*ugid_lookupp = 1;
			INP_RUNLOCK(pcb);
		}
		if (*ugid_lookupp == 0) {
			*ugid_lookupp = -1;
			return (0);
		}
	}
	if (insn->o.opcode == O_UID)
		match = ((*uc)->cr_uid == (uid_t)insn->d[0]);
	else if (insn->o.opcode == O_GID)
		match = groupmember((gid_t)insn->d[0], *uc);
	else if (insn->o.opcode == O_JAIL)
		match = ((*uc)->cr_prison->pr_id == (int)insn->d[0]);
	return (match);
#endif 
#endif 
}
static int check_uidgid ( ipfw_insn_u32 * insn , struct ip_fw_args * args , int * ugid_lookupp , struct ucred * * uc ) { #if defined ( USERSPACE ) return 0 ; #else #ifndef __FreeBSD__ return cred_check ( insn , proto , oif , dst_ip , dst_port , src_ip , src_port , ( struct bsd_ucred * ) uc , ugid_lookupp , ( ( struct mbuf * ) inp ) -> m_skb ) ; #else struct in_addr src_ip , dst_ip ; struct inpcbinfo * pi ; struct ipfw_flow_id * id ; struct inpcb * pcb , * inp ; struct ifnet * oif ; int lookupflags ; int match ; id = & args -> f_id ; inp = args -> inp ; oif = args -> oif ; if ( inp && * ugid_lookupp == 0 ) { INP_LOCK_ASSERT ( inp ) ; if ( inp -> inp_socket != NULL ) { * uc = crhold ( inp -> inp_cred ) ; * ugid_lookupp = 1 ; } else * ugid_lookupp = -1 ; } if ( * ugid_lookupp == -1 ) return ( 0 ) ; if ( id -> proto == IPPROTO_TCP ) { lookupflags = 0 ; pi = & V_tcbinfo ; } else if ( id -> proto == IPPROTO_UDP ) { lookupflags = INPLOOKUP_WILDCARD ; pi = & V_udbinfo ; } else return 0 ; lookupflags |= INPLOOKUP_RLOCKPCB ; match = 0 ; if ( * ugid_lookupp == 0 ) { if ( id -> addr_type == 6 ) { #ifdef INET6 if ( oif == NULL ) pcb = in6_pcblookup_mbuf ( pi , & id -> src_ip6 , htons ( id -> src_port ) , & id -> dst_ip6 , htons ( id -> dst_port ) , lookupflags , oif , args -> m ) ; else pcb = in6_pcblookup_mbuf ( pi , & id -> dst_ip6 , htons ( id -> dst_port ) , & id -> src_ip6 , htons ( id -> src_port ) , lookupflags , oif , args -> m ) ; #else * ugid_lookupp = -1 ; return ( 0 ) ; #endif } else { src_ip . s_addr = htonl ( id -> src_ip ) ; dst_ip . s_addr = htonl ( id -> dst_ip ) ; if ( oif == NULL ) pcb = in_pcblookup_mbuf ( pi , src_ip , htons ( id -> src_port ) , dst_ip , htons ( id -> dst_port ) , lookupflags , oif , args -> m ) ; else pcb = in_pcblookup_mbuf ( pi , dst_ip , htons ( id -> dst_port ) , src_ip , htons ( id -> src_port ) , lookupflags , oif , args -> m ) ; } if ( pcb != NULL ) { INP_RLOCK_ASSERT ( pcb ) ; * uc = crhold ( pcb -> inp_cred ) ; * ugid_lookupp = 1 ; INP_RUNLOCK ( pcb ) ; } if ( * ugid_lookupp == 0 ) { * ugid_lookupp = -1 ; return ( 0 ) ; } } if ( insn -> o . opcode == O_UID ) match = ( ( * uc ) -> cr_uid == ( uid_t ) insn -> d [ 0 ] ) ; else if ( insn -> o . opcode == O_GID ) match = groupmember ( ( gid_t ) insn -> d [ 0 ] , * uc ) ; else if ( insn -> o . opcode == O_JAIL ) match = ( ( * uc ) -> cr_prison -> pr_id == ( int ) insn -> d [ 0 ] ) ; return ( match ) ; #endif #endif }
Support for uid/gid/jail lookup.
Support for uid / gid / jail lookup .
// not supported in userspace /* XXX */ /* FreeBSD */ /*
	 * Check to see if the UDP or TCP stack supplied us with
	 * the PCB. If so, rather then holding a lock and looking
	 * up the PCB, we can use the one that was supplied.
	 */ /*
	 * If we have already been here and the packet has no
	 * PCB entry associated with it, then we can safely
	 * assume that this is a no match.
	 */ /*
			 * We tried and failed, set the variable to -1
			 * so we will not try again on this packet.
			 */ /* __FreeBSD__ */ /* not supported in userspace */