int nat_ioctl(data, cmd, mode) caddr_t data; int cmd, mode;
nat_ioctl(data, cmd, mode) caddr_t data; int cmd, mode;
int nat_ioctl(data, cmd, mode)caddr_t data;int cmd, mode;{	register ipnat_t *nat, *n, **np;	ipnat_t natd;	int error = 0, ret;	/*	 * For add/delete, look to see if the NAT entry is already present	 */	MUTEX_ENTER(&ipf_nat);	if ((cmd == SIOCADNAT) || (cmd == SIOCRMNAT)) {		IRCOPY(data, &natd, sizeof(natd));		nat = &natd;		for (np = &nat_list; (n = *np); np = &n->in_next)			if (!bcmp((char *)&nat->in_port, (char *)&n->in_port,					IPN_CMPSIZ))				break;	}	switch (cmd)	{	case SIOCADNAT :		if (!(mode & FWRITE)) {			error = EPERM;			break;		}		if (n) {			error = EEXIST;			break;		}		if (!(n = (ipnat_t *)KMALLOC(sizeof(*n)))) {			error = ENOMEM;			break;		}		IRCOPY((char *)data, (char *)n, sizeof(*n));		n->in_ifp = (void *)GETUNIT(n->in_ifname);		n->in_next = *np;		n->in_space = ~(0xffffffff & ntohl(n->in_outmsk));		n->in_space -= 2; /* lose 2: broadcast + network address */		if (n->in_inmsk != 0xffffffff)			n->in_nip = ntohl(n->in_outip) + 1;		else			n->in_nip = ntohl(n->in_outip);		if (n->in_redir == NAT_MAP)			n->in_pnext = ntohs(n->in_pmin);		/* Otherwise, these fields are preset */		*np = n;		break;	case SIOCRMNAT :		if (!(mode & FWRITE)) {			error = EPERM;			break;		}		if (!n) {			error = ESRCH;			break;		}		*np = n->in_next;		KFREE(n);		break;	case SIOCGNATS :		nat_stats.ns_table = (nat_t ***)nat_table;		nat_stats.ns_list = nat_list;		nat_stats.ns_inuse = nat_inuse;		IWCOPY((char *)&nat_stats, (char *)data, sizeof(nat_stats));		break;	case SIOCGNATL :	    {		natlookup_t nl;		nat_t	*na;		IRCOPY((char *)data, (char *)&nl, sizeof(nl));		if ((na = nat_lookupredir(&nl))) {			nl.nl_inip = na->nat_outip;			nl.nl_inport = na->nat_outport;			IWCOPY((char *)&nl, (char *)data, sizeof(nl));		} else			error = ESRCH;		break;	    }	case SIOCFLNAT :		if (!(mode & FWRITE)) {			error = EPERM;			break;		}		ret = flush_nattable();		IWCOPY((caddr_t)&ret, data, sizeof(ret));		break;	case SIOCCNATL :		if (!(mode & FWRITE)) {			error = EPERM;			break;		}		ret = clear_natlist();		IWCOPY((caddr_t)&ret, data, sizeof(ret));		break;	}	MUTEX_EXIT(&ipf_nat);	return error;}