Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 03 Sep 1997 17:51:57 +0930
From:      Mike Smith <mike@smith.net.au>
To:        Simon Shapiro <Shimon@i-Connect.Net>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: IOCTL Commands - Where is my mistake? 
Message-ID:  <199709030821.RAA00286@word.smith.net.au>
In-Reply-To: Your message of "Wed, 03 Sep 1997 00:40:53 MST." <XFMail.970903004053.Shimon@i-Connect.Net> 

next in thread | previous in thread | raw e-mail | index | archive | help
> I want to pass IOCTL commands to a driver.  This is what I do:
> 
>     #define DPT_IOCTL_INTERNAL_METRICS       _IOW('D', 1, dpt_perf_t)

You want to pass a pointer to the struct, not the struct itself.

>     switch (cmd) {
>     case DPT_IOCTL_INTERNAL_METRICS:
>          result = copyout((char *)&dpt->performance, 
>                          (dpt_softc_t *)(*(caddr_t *)cmdarg),
>                          sizeof(dpt_perf_t));

This is *hideously* bogus.  Try :

	caddr_t dest;

		/* get address in userspace */
	dest = fuword(*(caddr_t *)cmdarg);
		/* copy out to userspace */
	return(copyout(&dpt->performance, dest, 
			sizeof(dpt->performance))


ie. cmdarg is a pointer in kernel space to a *copy* of the value
passed as an argument to the ioctl.

You could also define the ioctl :

#define DPT_IOCTL_INTERNAL_METRICS	_IOR('D', 1, dpt_perf_t)

and then in the kernel say :

	memcpy(cmdarg, &dpt->performance,
		sizeof(dpt->performance));

however this will perform two copies; once as you copy it to the arg
area, and another when the ioctl returns the copy to userspace.  This 
approach is somewhat discouraged from an efficiency point of view.

You would call this as :

	ioctl(fd, DPT_IOCTL_INTERNAL_METRICS, metrics)

ie. pass the structure, not a pointer to it.  Think of an ioctl define 
as being like a function prototype.

mike





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