ioctl.c revision 123807fb8274cf8e22f09732e34303ba6baf55a5
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * CDDL HEADER START
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * The contents of this file are subject to the terms of the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Common Development and Distribution License (the "License").
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * You may not use this file except in compliance with the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * See the License for the specific language governing permissions
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * and limitations under the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * When distributing Covered Code, include this CDDL HEADER in each
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * If applicable, add the following below this CDDL HEADER, with the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * fields enclosed by brackets "[]" replaced with your own identifying
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * information: Portions Copyright [yyyy] [name of copyright owner]
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * CDDL HEADER END
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Use is subject to license terms.
ccf9d4a5c6453fa9f8b839baeee25147865fbb7dJames Phillpotts#pragma ident "%Z%%M% %I% %E% SMI"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Define _KERNEL to get the devt manipulation macros. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Maximum number of modules on a stream that we can handle. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Maximum buffer size for debugging messages. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Structure used to define an ioctl translator. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Structures used to associate a group of ioctl translators with
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * a specific device.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Array of command translators. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Structures used to associate a group of ioctl translators with
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * a specific filesystem.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Array of command translators. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Structure used to define a unsupported ioctl error codes. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Structure used to convert oss format flags into Solaris options. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Translator forward declerations. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic ioc_cmd_translator_t ioc_translators_file[];
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic ioc_cmd_translator_t ioc_translators_fifo[];
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic ioc_cmd_translator_t ioc_translators_sock[];
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic ioc_dev_translator_t *ioc_translators_dev[];
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic ioc_fs_translator_t *ioc_translators_fs[];
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic ioc_errno_translator_t ioc_translators_errno[];
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Interface name table.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fostertypedef struct ifname_map {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Macros and structures to help convert integers to string
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * values that they represent (for displaying in debug output).
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#define I2S_ENTRY(x) { x, #x },
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fostertypedef struct int2str {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterlx_ioctl_msg(int fd, int cmd, char *lx_cmd_str, struct stat *stat, char *msg)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster path = lx_fd_to_path(fd, path_buf, sizeof (path_buf));
0748565aad6a8878aecb88a26081c9bb10c00279Peter Major /* Display the initial error message and extended ioctl information. */
0748565aad6a8878aecb88a26081c9bb10c00279Peter Major lx_debug("\tlx_ioctl(): cmd = 0x%x - %s, fd = %d - %s",
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Display information about the target file, if it's available. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Translate the file type bits into a string. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (i = 0; st_mode_strings[i].i2s_str != NULL; i++) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((fd_mode == S_IFCHR) || (fd_mode == S_IFBLK)) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* This is a device so display the devt. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Try to display the drivers name. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster fd_driver, sizeof (fd_driver), &fd_major) == 0)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Restore errno. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Get the number of modules on the stream. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((i = ioctl(fd, I_LIST, (struct str_list *)NULL)) < 0) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster lx_debug("\tldlinux_check(): unable to count stream modules");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Sanity check the number of modules on the stream. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Get the list of modules on the stream. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster lx_debug("\tldlinux_check(): unable to list stream modules");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (strcmp(strlist.sl_modlist[i].l_name, LDLINUX_MOD) == 0)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterioctl_istr(int fd, int cmd, char *cmd_str, void *arg, int arg_len)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster lx_debug("\tioctl_istr(%d, 0x%x - %s, ...)", fd, cmd, cmd_str);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (-1);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Add an interface name mapping if it doesn't already exist.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Interfaces with IFF_LOOPBACK flag get renamed to loXXX.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Interfaces with IFF_BROADCAST flag get renamed to ethXXX.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Caller locks the name table.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster static int eth_index = 0;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster static int lo_index = 0;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (im_pp = &ifname_map; *im_pp; im_pp = &(*im_pp)->im_next)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (strncmp((*im_pp)->im_solaris, if_name, IFNAMSIZ) == 0)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (-1);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) strlcpy((*im_pp)->im_solaris, if_name, IFNAMSIZ);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Loopback */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) strlcpy((*im_pp)->im_linux, "lo", IFNAMSIZ);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Assume ether if it has a broadcast address */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Do not translate unknown interfaces */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) strlcpy((*im_pp)->im_linux, if_name, IFNAMSIZ);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster lx_debug("map interface %s -> %s", if_name, (*im_pp)->im_linux);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (strncmp(rp1->ifr_name, rp2->ifr_name, IFNAMSIZ));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * (Re-)scan all interfaces and add them to the name table.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Caller locks the name table.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster lx_debug("\tioctl(%d, 0x%x - %s, ...)", fd, SIOCGIFNUM, "SIOCGIFNUM");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster lx_debug("\tifname_scan(): unable to get number of interfaces");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster conf.ifc_len = ifcount * sizeof (struct ifreq);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((conf.ifc_buf = calloc(ifcount, sizeof (struct ifreq))) == NULL)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster lx_debug("\tioctl(%d, 0x%x - %s, ...)", fd, SIOCGIFCONF, "SIOCGIFCONF");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster lx_debug("\tifname_scan(): unable to get interfaces");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Get the interface flags */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (i = 0; i < ifcount; i++) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (ioctl(fd, SIOCGIFFLAGS, &conf.ifc_req[i]) < 0) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster lx_debug("\tifname_scan(): unable to get flags for %s",
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Sort the interfaces by name to preserve the order
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * across reboots of this zone. Note that the order of
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * interface names won't be consistent across network
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * configuration changes. ie. If network interfaces
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * are added or removed from a zone (either dynamically
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * or statically) the network interfaces names to physical
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * network interface mappings that linux apps see may
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster qsort(conf.ifc_req, ifcount, sizeof (struct ifreq), ifname_cmp);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Add to the name table */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (i = 0; i < ifcount; i++)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (-1);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (im_p = ifname_map; im_p; im_p = im_p->im_next)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (strncmp(im_p->im_linux, name, IFNAMSIZ) == 0)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (im_p != NULL || (pass == 0 && ifname_scan() != 0))
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) strlcpy(name, im_p->im_solaris, IFNAMSIZ);
int pass;
if (im_p) {
int i, ret;
if (ret != 0) {
if (ifname_scan() != 0)
static ioc_cmd_translator_t *
return (ict);
ict++;
return (NULL);
int i, ret;
case S_IFREG:
case S_IFSOCK:
case S_IFIFO:
case S_IFCHR:
arg);
return (ret);
arg);
return (ret);
return (ret);
cmd);
return (-EINVAL);
return (-EINVAL);
int ret;
return (-errno);
return (-EINVAL);
return (-EINVAL);
return (-errno);
return (-errno);
return (-errno);
return (-EINVAL);
return (-errno);
return (-EINVAL);
return (-errno);
return (-errno);
return (-errno);
return (-errno);
if (ret < 0)
return (-errno);
return (-EINVAL);
return (-errno);
return (-errno);
return (-EINVAL);
return (-errno);
return (-EINVAL);
return (-errno);
return (-errno);
return (-EINVAL);
return (-errno);
return (-errno);
return (ldlinux);
return (-errno);
return (-errno);
return (ldlinux);
return (-errno);
int ret;
return (-errno);
return (-errno);
return (-ENOTTY);
return (-errno);
return (-errno);
return (-errno);
return (-errno);
return (-errno);
return (-errno);
int ldlinux;
return (ldlinux);
return (-errno);
return (-errno);
if (ldlinux == 0)
return (-errno);
return (-errno);
int ldlinux;
return (ldlinux);
return (-errno);
return (-errno);
if (ldlinux == 0)
return (-errno);
return (-errno);
return (-errno);
(void) setpgrp();
return (-errno);
int minor;
return (-EINVAL);
return (-EINVAL);
int err;
return (err);
if (first)
first = 0;
return (err);
return (-EINVAL);
if (lx_debug_enabled != 0) {
return (-errno);
return (err);
return (-errno);
if (lx_debug_enabled != 0) {
return (-EINVAL);
return (-EINVAL);
return (-EINVAL);
return (-EINVAL);
return (err);
return (-errno);
return (-EINVAL);
return (-EINVAL);
return (-EINVAL);
return (-EINVAL);
return (-errno);
return (err);
return (-errno);
return (-EINVAL);
return (-EINVAL);
int err;
return (err);
return (-errno);
return (-errno);
int err;
return (err);
return (-errno);
return (-errno);
int err;
return (err);
return (-errno);
return (-EINVAL);
return (-EINVAL);
int err;
return (err);
return (-errno);
int err;
return (err);
return (-errno);
return (-EINVAL);
return (err);
return (-errno);
return (-errno);
return (-errno);
return (err);
return (-EINVAL);
* the comments in lx_audio.c.
int minor;
return (-EINVAL);
return (-EINVAL);
return (-EINVAL);
char *cmd_txt;
return (err);
return (-errno);
return (err);
return (-errno);
char *cmd_txt;
return (err);
return (-errno);
return (-errno);
return (-errno);
return (err);
return (-errno);
int err;
return (err);
return (-errno);
return (-errno);
int err;
return (err);
return (-errno);
return (-errno);
int err;
return (err);
return (-errno);
#define IOC_CMD_TRANSLATOR_END \
#define IOC_CMD_TRANSLATORS_ALL \
#define IOC_CMD_TRANSLATORS_STREAMS \
#define IOC_ERRNO_TRANSLATOR_END \
{ 0, NULL, 0 }
lx_vhangup(void)
if (geteuid() != 0)
return (-EPERM);
vhangup();