The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/emulation/linux/linux_ioctl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1994-1995 Søren Schmidt
    3  * Copyright (c) 2004 Simon 'corecode' Schubert
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer
   11  *    in this position and unchanged.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  *
   29  * $FreeBSD: src/sys/compat/linux/linux_ioctl.c,v 1.55.2.11 2003/05/01 20:16:09 anholt Exp $
   30  * $DragonFly: src/sys/emulation/linux/linux_ioctl.c,v 1.25 2008/03/07 11:34:19 sephe Exp $
   31  */
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/sysproto.h>
   36 #include <sys/cdio.h>
   37 #include <sys/consio.h>
   38 #include <sys/ctype.h>
   39 #include <sys/diskslice.h>
   40 #include <sys/fcntl.h>
   41 #include <sys/file.h>
   42 #include <sys/filedesc.h>
   43 #include <sys/filio.h>
   44 #include <sys/kbio.h>
   45 #include <sys/kernel.h>
   46 #include <sys/linker_set.h>
   47 #include <sys/malloc.h>
   48 #include <sys/mapped_ioctl.h>
   49 #include <sys/proc.h>
   50 #include <sys/socket.h>
   51 #include <sys/sockio.h>
   52 #include <sys/soundcard.h>
   53 #include <sys/tty.h>
   54 #include <sys/uio.h>
   55 #include <net/if.h>
   56 #include <net/if_dl.h>
   57 #include <net/if_types.h>
   58 
   59 #include <sys/file2.h>
   60 #include <sys/mplock2.h>
   61 
   62 #include <arch_linux/linux.h>
   63 #include <arch_linux/linux_proto.h>
   64 
   65 #include "linux_ioctl.h"
   66 #include "linux_mib.h"
   67 #include "linux_util.h"
   68 
   69 
   70 static int
   71 linux_ioctl_BLKGETSIZE32(struct file *fp, u_long cmd, u_long ocmd,
   72                          caddr_t data, struct ucred *cred)
   73 {
   74         struct partinfo dpart;
   75         u_int32_t value;
   76         int error;
   77 
   78         error = fo_ioctl(fp, DIOCGPART, (caddr_t)&dpart, cred, NULL);
   79         if (error)
   80                 return (error);
   81         value = dpart.media_blocks;     /* 64->32 */
   82         bcopy(&value, data, sizeof(value));
   83         return (0);
   84 }
   85 
   86 
   87 /*
   88  * termio related ioctls
   89  */
   90 
   91 struct linux_termio {
   92         unsigned short c_iflag;
   93         unsigned short c_oflag;
   94         unsigned short c_cflag;
   95         unsigned short c_lflag;
   96         unsigned char c_line;
   97         unsigned char c_cc[LINUX_NCC];
   98 };
   99 
  100 struct linux_termios {
  101         unsigned int c_iflag;
  102         unsigned int c_oflag;
  103         unsigned int c_cflag;
  104         unsigned int c_lflag;
  105         unsigned char c_line;
  106         unsigned char c_cc[LINUX_NCCS];
  107 };
  108 
  109 struct linux_winsize {
  110         unsigned short ws_row, ws_col;
  111         unsigned short ws_xpixel, ws_ypixel;
  112 };
  113 
  114 static struct speedtab sptab[] = {
  115         { B0, LINUX_B0 }, { B50, LINUX_B50 },
  116         { B75, LINUX_B75 }, { B110, LINUX_B110 },
  117         { B134, LINUX_B134 }, { B150, LINUX_B150 },
  118         { B200, LINUX_B200 }, { B300, LINUX_B300 },
  119         { B600, LINUX_B600 }, { B1200, LINUX_B1200 },
  120         { B1800, LINUX_B1800 }, { B2400, LINUX_B2400 },
  121         { B4800, LINUX_B4800 }, { B9600, LINUX_B9600 },
  122         { B19200, LINUX_B19200 }, { B38400, LINUX_B38400 },
  123         { B57600, LINUX_B57600 }, { B115200, LINUX_B115200 },
  124         {-1, -1 }
  125 };
  126 
  127 struct linux_serial_struct {
  128         int     type;
  129         int     line;
  130         int     port;
  131         int     irq;
  132         int     flags;
  133         int     xmit_fifo_size;
  134         int     custom_divisor;
  135         int     baud_base;
  136         unsigned short close_delay;
  137         char    reserved_char[2];
  138         int     hub6;
  139         unsigned short closing_wait;
  140         unsigned short closing_wait2;
  141         int     reserved[4];
  142 };
  143 
  144 static int
  145 linux_to_bsd_speed(int code, struct speedtab *table)
  146 {
  147         for ( ; table->sp_code != -1; table++)
  148                 if (table->sp_code == code)
  149                         return (table->sp_speed);
  150         return -1;
  151 }
  152 
  153 static int
  154 bsd_to_linux_speed(int speed, struct speedtab *table)
  155 {
  156         for ( ; table->sp_speed != -1; table++)
  157                 if (table->sp_speed == speed)
  158                         return (table->sp_code);
  159         return -1;
  160 }
  161 
  162 static void
  163 bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios)
  164 {
  165         int i;
  166 
  167 #ifdef DEBUG
  168         if (ldebug(ioctl)) {
  169                 kprintf("LINUX: BSD termios structure (input):\n");
  170                 kprintf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
  171                     bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag,
  172                     bios->c_ispeed, bios->c_ospeed);
  173                 kprintf("c_cc ");
  174                 for (i=0; i<NCCS; i++)
  175                         kprintf("%02x ", bios->c_cc[i]);
  176                 kprintf("\n");
  177         }
  178 #endif
  179 
  180         lios->c_iflag = 0;
  181         if (bios->c_iflag & IGNBRK)
  182                 lios->c_iflag |= LINUX_IGNBRK;
  183         if (bios->c_iflag & BRKINT)
  184                 lios->c_iflag |= LINUX_BRKINT;
  185         if (bios->c_iflag & IGNPAR)
  186                 lios->c_iflag |= LINUX_IGNPAR;
  187         if (bios->c_iflag & PARMRK)
  188                 lios->c_iflag |= LINUX_PARMRK;
  189         if (bios->c_iflag & INPCK)
  190                 lios->c_iflag |= LINUX_INPCK;
  191         if (bios->c_iflag & ISTRIP)
  192                 lios->c_iflag |= LINUX_ISTRIP;
  193         if (bios->c_iflag & INLCR)
  194                 lios->c_iflag |= LINUX_INLCR;
  195         if (bios->c_iflag & IGNCR)
  196                 lios->c_iflag |= LINUX_IGNCR;
  197         if (bios->c_iflag & ICRNL)
  198                 lios->c_iflag |= LINUX_ICRNL;
  199         if (bios->c_iflag & IXON)
  200                 lios->c_iflag |= LINUX_IXON;
  201         if (bios->c_iflag & IXANY)
  202                 lios->c_iflag |= LINUX_IXANY;
  203         if (bios->c_iflag & IXOFF)
  204                 lios->c_iflag |= LINUX_IXOFF;
  205         if (bios->c_iflag & IMAXBEL)
  206                 lios->c_iflag |= LINUX_IMAXBEL;
  207 
  208         lios->c_oflag = 0;
  209         if (bios->c_oflag & OPOST)
  210                 lios->c_oflag |= LINUX_OPOST;
  211         if (bios->c_oflag & ONLCR)
  212                 lios->c_oflag |= LINUX_ONLCR;
  213         if (bios->c_oflag & OXTABS)
  214                 lios->c_oflag |= LINUX_XTABS;
  215 
  216         lios->c_cflag = bsd_to_linux_speed(bios->c_ispeed, sptab);
  217         lios->c_cflag |= (bios->c_cflag & CSIZE) >> 4;
  218         if (bios->c_cflag & CSTOPB)
  219                 lios->c_cflag |= LINUX_CSTOPB;
  220         if (bios->c_cflag & CREAD)
  221                 lios->c_cflag |= LINUX_CREAD;
  222         if (bios->c_cflag & PARENB)
  223                 lios->c_cflag |= LINUX_PARENB;
  224         if (bios->c_cflag & PARODD)
  225                 lios->c_cflag |= LINUX_PARODD;
  226         if (bios->c_cflag & HUPCL)
  227                 lios->c_cflag |= LINUX_HUPCL;
  228         if (bios->c_cflag & CLOCAL)
  229                 lios->c_cflag |= LINUX_CLOCAL;
  230         if (bios->c_cflag & CRTSCTS)
  231                 lios->c_cflag |= LINUX_CRTSCTS;
  232 
  233         lios->c_lflag = 0;
  234         if (bios->c_lflag & ISIG)
  235                 lios->c_lflag |= LINUX_ISIG;
  236         if (bios->c_lflag & ICANON)
  237                 lios->c_lflag |= LINUX_ICANON;
  238         if (bios->c_lflag & ECHO)
  239                 lios->c_lflag |= LINUX_ECHO;
  240         if (bios->c_lflag & ECHOE)
  241                 lios->c_lflag |= LINUX_ECHOE;
  242         if (bios->c_lflag & ECHOK)
  243                 lios->c_lflag |= LINUX_ECHOK;
  244         if (bios->c_lflag & ECHONL)
  245                 lios->c_lflag |= LINUX_ECHONL;
  246         if (bios->c_lflag & NOFLSH)
  247                 lios->c_lflag |= LINUX_NOFLSH;
  248         if (bios->c_lflag & TOSTOP)
  249                 lios->c_lflag |= LINUX_TOSTOP;
  250         if (bios->c_lflag & ECHOCTL)
  251                 lios->c_lflag |= LINUX_ECHOCTL;
  252         if (bios->c_lflag & ECHOPRT)
  253                 lios->c_lflag |= LINUX_ECHOPRT;
  254         if (bios->c_lflag & ECHOKE)
  255                 lios->c_lflag |= LINUX_ECHOKE;
  256         if (bios->c_lflag & FLUSHO)
  257                 lios->c_lflag |= LINUX_FLUSHO;
  258         if (bios->c_lflag & PENDIN)
  259                 lios->c_lflag |= LINUX_PENDIN;
  260         if (bios->c_lflag & IEXTEN)
  261                 lios->c_lflag |= LINUX_IEXTEN;
  262 
  263         for (i=0; i<LINUX_NCCS; i++)
  264                 lios->c_cc[i] = LINUX_POSIX_VDISABLE;
  265         lios->c_cc[LINUX_VINTR] = bios->c_cc[VINTR];
  266         lios->c_cc[LINUX_VQUIT] = bios->c_cc[VQUIT];
  267         lios->c_cc[LINUX_VERASE] = bios->c_cc[VERASE];
  268         lios->c_cc[LINUX_VKILL] = bios->c_cc[VKILL];
  269         lios->c_cc[LINUX_VEOF] = bios->c_cc[VEOF];
  270         lios->c_cc[LINUX_VEOL] = bios->c_cc[VEOL];
  271         lios->c_cc[LINUX_VMIN] = bios->c_cc[VMIN];
  272         lios->c_cc[LINUX_VTIME] = bios->c_cc[VTIME];
  273         lios->c_cc[LINUX_VEOL2] = bios->c_cc[VEOL2];
  274         lios->c_cc[LINUX_VSUSP] = bios->c_cc[VSUSP];
  275         lios->c_cc[LINUX_VSTART] = bios->c_cc[VSTART];
  276         lios->c_cc[LINUX_VSTOP] = bios->c_cc[VSTOP];
  277         lios->c_cc[LINUX_VREPRINT] = bios->c_cc[VREPRINT];
  278         lios->c_cc[LINUX_VDISCARD] = bios->c_cc[VDISCARD];
  279         lios->c_cc[LINUX_VWERASE] = bios->c_cc[VWERASE];
  280         lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT];
  281 
  282         for (i=0; i<LINUX_NCCS; i++) {
  283                  if (i != LINUX_VMIN && i != LINUX_VTIME &&
  284                     lios->c_cc[i] == _POSIX_VDISABLE)
  285                         lios->c_cc[i] = LINUX_POSIX_VDISABLE;
  286         }
  287         lios->c_line = 0;
  288 
  289 #ifdef DEBUG
  290         if (ldebug(ioctl)) {
  291                 kprintf("LINUX: LINUX termios structure (output):\n");
  292                 kprintf("i=%08x o=%08x c=%08x l=%08x line=%d\n",
  293                     lios->c_iflag, lios->c_oflag, lios->c_cflag,
  294                     lios->c_lflag, (int)lios->c_line);
  295                 kprintf("c_cc ");
  296                 for (i=0; i<LINUX_NCCS; i++) 
  297                         kprintf("%02x ", lios->c_cc[i]);
  298                 kprintf("\n");
  299         }
  300 #endif
  301 }
  302 
  303 static void
  304 linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios)
  305 {
  306         int i;
  307 
  308 #ifdef DEBUG
  309         if (ldebug(ioctl)) {
  310                 kprintf("LINUX: LINUX termios structure (input):\n");
  311                 kprintf("i=%08x o=%08x c=%08x l=%08x line=%d\n", 
  312                     lios->c_iflag, lios->c_oflag, lios->c_cflag,
  313                     lios->c_lflag, (int)lios->c_line);
  314                 kprintf("c_cc ");
  315                 for (i=0; i<LINUX_NCCS; i++)
  316                         kprintf("%02x ", lios->c_cc[i]);
  317                 kprintf("\n");
  318         }
  319 #endif
  320 
  321         bios->c_iflag = 0;
  322         if (lios->c_iflag & LINUX_IGNBRK)
  323                 bios->c_iflag |= IGNBRK;
  324         if (lios->c_iflag & LINUX_BRKINT)
  325                 bios->c_iflag |= BRKINT;
  326         if (lios->c_iflag & LINUX_IGNPAR)
  327                 bios->c_iflag |= IGNPAR;
  328         if (lios->c_iflag & LINUX_PARMRK)
  329                 bios->c_iflag |= PARMRK;
  330         if (lios->c_iflag & LINUX_INPCK)
  331                 bios->c_iflag |= INPCK;
  332         if (lios->c_iflag & LINUX_ISTRIP)
  333                 bios->c_iflag |= ISTRIP;
  334         if (lios->c_iflag & LINUX_INLCR)
  335                 bios->c_iflag |= INLCR;
  336         if (lios->c_iflag & LINUX_IGNCR)
  337                 bios->c_iflag |= IGNCR;
  338         if (lios->c_iflag & LINUX_ICRNL)
  339                 bios->c_iflag |= ICRNL;
  340         if (lios->c_iflag & LINUX_IXON)
  341                 bios->c_iflag |= IXON;
  342         if (lios->c_iflag & LINUX_IXANY)
  343                 bios->c_iflag |= IXANY;
  344         if (lios->c_iflag & LINUX_IXOFF)
  345                 bios->c_iflag |= IXOFF;
  346         if (lios->c_iflag & LINUX_IMAXBEL)
  347                 bios->c_iflag |= IMAXBEL;
  348 
  349         bios->c_oflag = 0;
  350         if (lios->c_oflag & LINUX_OPOST)
  351                 bios->c_oflag |= OPOST;
  352         if (lios->c_oflag & LINUX_ONLCR)
  353                 bios->c_oflag |= ONLCR;
  354         if (lios->c_oflag & LINUX_XTABS)
  355                 bios->c_oflag |= OXTABS;
  356 
  357         bios->c_cflag = (lios->c_cflag & LINUX_CSIZE) << 4;
  358         if (lios->c_cflag & LINUX_CSTOPB)
  359                 bios->c_cflag |= CSTOPB;
  360         if (lios->c_cflag & LINUX_CREAD)
  361                 bios->c_cflag |= CREAD;
  362         if (lios->c_cflag & LINUX_PARENB)
  363                 bios->c_cflag |= PARENB;
  364         if (lios->c_cflag & LINUX_PARODD)
  365                 bios->c_cflag |= PARODD;
  366         if (lios->c_cflag & LINUX_HUPCL)
  367                 bios->c_cflag |= HUPCL;
  368         if (lios->c_cflag & LINUX_CLOCAL)
  369                 bios->c_cflag |= CLOCAL;
  370         if (lios->c_cflag & LINUX_CRTSCTS)
  371                 bios->c_cflag |= CRTSCTS;
  372 
  373         bios->c_lflag = 0;
  374         if (lios->c_lflag & LINUX_ISIG)
  375                 bios->c_lflag |= ISIG;
  376         if (lios->c_lflag & LINUX_ICANON)
  377                 bios->c_lflag |= ICANON;
  378         if (lios->c_lflag & LINUX_ECHO)
  379                 bios->c_lflag |= ECHO;
  380         if (lios->c_lflag & LINUX_ECHOE)
  381                 bios->c_lflag |= ECHOE;
  382         if (lios->c_lflag & LINUX_ECHOK)
  383                 bios->c_lflag |= ECHOK;
  384         if (lios->c_lflag & LINUX_ECHONL)
  385                 bios->c_lflag |= ECHONL;
  386         if (lios->c_lflag & LINUX_NOFLSH)
  387                 bios->c_lflag |= NOFLSH;
  388         if (lios->c_lflag & LINUX_TOSTOP)
  389                 bios->c_lflag |= TOSTOP;
  390         if (lios->c_lflag & LINUX_ECHOCTL)
  391                 bios->c_lflag |= ECHOCTL;
  392         if (lios->c_lflag & LINUX_ECHOPRT)
  393                 bios->c_lflag |= ECHOPRT;
  394         if (lios->c_lflag & LINUX_ECHOKE)
  395                 bios->c_lflag |= ECHOKE;
  396         if (lios->c_lflag & LINUX_FLUSHO)
  397                 bios->c_lflag |= FLUSHO;
  398         if (lios->c_lflag & LINUX_PENDIN)
  399                 bios->c_lflag |= PENDIN;
  400         if (lios->c_lflag & LINUX_IEXTEN)
  401                 bios->c_lflag |= IEXTEN;
  402 
  403         for (i=0; i<NCCS; i++)
  404                 bios->c_cc[i] = _POSIX_VDISABLE;
  405         bios->c_cc[VINTR] = lios->c_cc[LINUX_VINTR];
  406         bios->c_cc[VQUIT] = lios->c_cc[LINUX_VQUIT];
  407         bios->c_cc[VERASE] = lios->c_cc[LINUX_VERASE];
  408         bios->c_cc[VKILL] = lios->c_cc[LINUX_VKILL];
  409         bios->c_cc[VEOF] = lios->c_cc[LINUX_VEOF];
  410         bios->c_cc[VEOL] = lios->c_cc[LINUX_VEOL];
  411         bios->c_cc[VMIN] = lios->c_cc[LINUX_VMIN];
  412         bios->c_cc[VTIME] = lios->c_cc[LINUX_VTIME];
  413         bios->c_cc[VEOL2] = lios->c_cc[LINUX_VEOL2];
  414         bios->c_cc[VSUSP] = lios->c_cc[LINUX_VSUSP];
  415         bios->c_cc[VSTART] = lios->c_cc[LINUX_VSTART];
  416         bios->c_cc[VSTOP] = lios->c_cc[LINUX_VSTOP];
  417         bios->c_cc[VREPRINT] = lios->c_cc[LINUX_VREPRINT];
  418         bios->c_cc[VDISCARD] = lios->c_cc[LINUX_VDISCARD];
  419         bios->c_cc[VWERASE] = lios->c_cc[LINUX_VWERASE];
  420         bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT];
  421 
  422         for (i=0; i<NCCS; i++) {
  423                  if (i != VMIN && i != VTIME &&
  424                     bios->c_cc[i] == LINUX_POSIX_VDISABLE)
  425                         bios->c_cc[i] = _POSIX_VDISABLE;
  426         }
  427 
  428         bios->c_ispeed = bios->c_ospeed =
  429             linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab);
  430 
  431 #ifdef DEBUG
  432         if (ldebug(ioctl)) {
  433                 kprintf("LINUX: BSD termios structure (output):\n");
  434                 kprintf("i=%08x o=%08x c=%08x l=%08x ispeed=%d ospeed=%d\n",
  435                     bios->c_iflag, bios->c_oflag, bios->c_cflag, bios->c_lflag,
  436                     bios->c_ispeed, bios->c_ospeed);
  437                 kprintf("c_cc ");
  438                 for (i=0; i<NCCS; i++) 
  439                         kprintf("%02x ", bios->c_cc[i]);
  440                 kprintf("\n");
  441         }
  442 #endif
  443 }
  444 
  445 static void
  446 bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio)
  447 {
  448         struct linux_termios lios;
  449 
  450         bsd_to_linux_termios(bios, &lios);
  451         lio->c_iflag = lios.c_iflag;
  452         lio->c_oflag = lios.c_oflag;
  453         lio->c_cflag = lios.c_cflag;
  454         lio->c_lflag = lios.c_lflag;
  455         lio->c_line  = lios.c_line;
  456         memcpy(lio->c_cc, lios.c_cc, LINUX_NCC);
  457 }
  458 
  459 static void
  460 linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios)
  461 {
  462         struct linux_termios lios;
  463         int i;
  464 
  465         lios.c_iflag = lio->c_iflag;
  466         lios.c_oflag = lio->c_oflag;
  467         lios.c_cflag = lio->c_cflag;
  468         lios.c_lflag = lio->c_lflag;
  469         for (i=LINUX_NCC; i<LINUX_NCCS; i++)
  470                 lios.c_cc[i] = LINUX_POSIX_VDISABLE;
  471         memcpy(lios.c_cc, lio->c_cc, LINUX_NCC);
  472         linux_to_bsd_termios(&lios, bios);
  473 }
  474 
  475 static int
  476 linux_ioctl_TCGETS(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  477 {
  478         struct termios bios;
  479         struct linux_termios lios;
  480         int error;
  481 
  482         error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, cred, NULL);
  483         if (error)
  484                 return (error);
  485         bsd_to_linux_termios(&bios, &lios);
  486         bcopy(&lios, data, sizeof(lios));
  487         return (0);
  488 }
  489 
  490 static int
  491 linux_ioctl_TCSETS(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  492 {
  493         struct termios bios;
  494         struct linux_termios lios;
  495 
  496         bcopy(data, &lios, sizeof(lios));
  497         linux_to_bsd_termios(&lios, &bios);
  498         return (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, cred, NULL));
  499 }
  500 
  501 static int
  502 linux_ioctl_TCSETSW(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  503 {
  504         struct termios bios;
  505         struct linux_termios lios;
  506 
  507         bcopy(data, &lios, sizeof(lios));
  508         linux_to_bsd_termios(&lios, &bios);
  509         return (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, cred, NULL));
  510 }
  511 
  512 static int
  513 linux_ioctl_TCSETSF(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  514 {
  515         struct termios bios;
  516         struct linux_termios lios;
  517 
  518         bcopy(data, &lios, sizeof(lios));
  519         linux_to_bsd_termios(&lios, &bios);
  520         return (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, cred, NULL));
  521 }
  522 
  523 static int
  524 linux_ioctl_TCGETA(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  525 {
  526         struct termios bios;
  527         struct linux_termio lio;
  528         int error;
  529 
  530         error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, cred, NULL);
  531         if (error)
  532                 return (error);
  533         bsd_to_linux_termio(&bios, &lio);
  534         bcopy(&lio, data, sizeof(lio));
  535         return (0);
  536 }
  537 
  538 static int
  539 linux_ioctl_TCSETA(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  540 {
  541         struct termios bios;
  542         struct linux_termio lio;
  543 
  544         bcopy(data, &lio, sizeof(lio));
  545         linux_to_bsd_termio(&lio, &bios);
  546         return (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, cred, NULL));
  547 }
  548 
  549 static int
  550 linux_ioctl_TCSETAW(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  551 {
  552         struct termios bios;
  553         struct linux_termio lio;
  554 
  555         bcopy(data, &lio, sizeof(lio));
  556         linux_to_bsd_termio(&lio, &bios);
  557         return (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, cred, NULL));
  558 }
  559 
  560 static int
  561 linux_ioctl_TCSETAF(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  562 {
  563         struct termios bios;
  564         struct linux_termio lio;
  565 
  566         bcopy(data, &lio, sizeof(lio));
  567         linux_to_bsd_termio(&lio, &bios);
  568         return (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, cred, NULL));
  569 }
  570 
  571 static int
  572 linux_ioctl_TIOCLINUX(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  573 {
  574         switch ((u_char)*data) {
  575         case 11: /* LINUX_TIOCLINUX_KERNMSG */
  576                 return 0;
  577         default:
  578                 kprintf("Unknown LINUX_TIOCLINUX: %d\n", ((u_char)*data));
  579                 kprintf("cmd = %lu, ocmd = %lu\n", cmd, ocmd);
  580                 return 0;
  581         }
  582         return 0;
  583 }
  584 
  585 static int
  586 linux_ioctl_TCXONC(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  587 {
  588         switch ((u_long)data) {
  589         case LINUX_TCOOFF:
  590                 cmd = TIOCSTOP;
  591                 break;
  592         case LINUX_TCOON:
  593                 cmd = TIOCSTART;
  594                 break;
  595         case LINUX_TCIOFF:
  596         case LINUX_TCION: {
  597                 struct termios bios;
  598                 int error, c;
  599                 
  600                 error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, cred, NULL);
  601                 if (error)
  602                         return (error);
  603                 c = ((u_long)data == LINUX_TCIOFF) ? VSTOP : VSTART;
  604                 c = bios.c_cc[c];
  605                 if (c != _POSIX_VDISABLE) {
  606                         struct uio auio;
  607                         struct iovec aiov;
  608 
  609                         aiov.iov_base = (char *)&c;
  610                         aiov.iov_len = sizeof(*bios.c_cc);
  611                         auio.uio_iov = &aiov;
  612                         auio.uio_iovcnt = 1;
  613                         auio.uio_offset = -1;
  614                         auio.uio_resid = sizeof(*bios.c_cc);
  615                         auio.uio_rw = UIO_WRITE;
  616                         auio.uio_segflg = UIO_SYSSPACE;
  617                         auio.uio_td = curthread;
  618 
  619                         return (fo_write(fp, &auio, fp->f_cred, 0));
  620                 }
  621 
  622                 return (0);
  623         }
  624         default:
  625                 return (EINVAL);
  626         }
  627         return (fo_ioctl(fp, cmd, 0, cred, NULL));
  628 }
  629 
  630 static int
  631 linux_ioctl_TCFLSH(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  632 {
  633         switch ((u_long)data) {
  634         case LINUX_TCIFLUSH:
  635                 *(u_long *)data = FREAD;
  636                 break;
  637         case LINUX_TCOFLUSH:
  638                 *(u_long *)data = FWRITE;
  639                 break;
  640         case LINUX_TCIOFLUSH:
  641                 *(u_long *)data = FREAD | FWRITE;
  642                 break;
  643         default:
  644                 return (EINVAL);
  645         }
  646         return (fo_ioctl(fp, TIOCFLUSH, data, cred, NULL));
  647 }
  648 
  649 static int
  650 linux_ioctl_TIOCGSERIAL(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  651 {
  652         struct linux_serial_struct lss;
  653 
  654         lss.type = LINUX_PORT_16550A;
  655         lss.flags = 0;
  656         lss.close_delay = 0;
  657         bcopy(&lss, data, sizeof(lss));
  658         return (0);
  659 }
  660 
  661 static int
  662 linux_ioctl_TIOCSSERIAL(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  663 {
  664 #if 0
  665         struct linux_serial_struct lss;
  666 
  667         bcopy(data, &lss, sizeof(lss));
  668         /* XXX - It really helps to have an implementation that
  669          * does nothing. NOT!
  670          */
  671 #endif
  672         return (0);
  673 }
  674 
  675 static int
  676 linux_ioctl_TIOCSETD(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  677 {
  678         int line;
  679 
  680         switch ((u_long)data) {
  681         case LINUX_N_TTY:
  682                 line = TTYDISC;
  683                 break;
  684         case LINUX_N_SLIP:
  685                 line = SLIPDISC;
  686                 break;
  687         case LINUX_N_PPP:
  688                 line = PPPDISC;
  689                 break;
  690         default:
  691                 return (EINVAL);
  692         }
  693         return (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, cred, NULL));
  694 }
  695 
  696 static int
  697 linux_ioctl_TIOCGETD(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  698 {
  699         int linux_line, error;
  700         int bsd_line = TTYDISC;
  701 
  702         error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line, cred, NULL);
  703         if (error)
  704                 return (error);
  705         switch (bsd_line) {
  706         case TTYDISC:
  707                 linux_line = LINUX_N_TTY;
  708                 break;
  709         case SLIPDISC:
  710                 linux_line = LINUX_N_SLIP;
  711                 break;
  712         case PPPDISC:
  713                 linux_line = LINUX_N_PPP;
  714                 break;
  715         default:
  716                 return (EINVAL);
  717         }
  718         bcopy(&linux_line, data, sizeof(int));
  719         return (0);
  720 }       
  721 
  722 
  723 /*
  724  * CDROM related ioctls
  725  */
  726 
  727 struct linux_cdrom_msf
  728 {
  729         u_char  cdmsf_min0;
  730         u_char  cdmsf_sec0;
  731         u_char  cdmsf_frame0;
  732         u_char  cdmsf_min1;
  733         u_char  cdmsf_sec1;
  734         u_char  cdmsf_frame1;
  735 };
  736 
  737 struct linux_cdrom_tochdr
  738 {
  739         u_char  cdth_trk0;
  740         u_char  cdth_trk1;
  741 };
  742 
  743 union linux_cdrom_addr
  744 {
  745         struct {
  746                 u_char  minute;
  747                 u_char  second;
  748                 u_char  frame;
  749         } msf;
  750         int     lba;
  751 };
  752 
  753 struct linux_cdrom_tocentry
  754 {
  755         u_char  cdte_track;     
  756         u_char  cdte_adr:4;
  757         u_char  cdte_ctrl:4;
  758         u_char  cdte_format;    
  759         union linux_cdrom_addr cdte_addr;
  760         u_char  cdte_datamode;  
  761 };
  762 
  763 struct linux_cdrom_subchnl
  764 {
  765         u_char  cdsc_format;
  766         u_char  cdsc_audiostatus;
  767         u_char  cdsc_adr:4;
  768         u_char  cdsc_ctrl:4;
  769         u_char  cdsc_trk;
  770         u_char  cdsc_ind;
  771         union linux_cdrom_addr cdsc_absaddr;
  772         union linux_cdrom_addr cdsc_reladdr;
  773 };
  774 
  775 static void
  776 bsd_to_linux_msf_lba(u_char af, union msf_lba *bp, union linux_cdrom_addr *lp)
  777 {
  778         if (af == CD_LBA_FORMAT)
  779                 lp->lba = bp->lba;
  780         else {
  781                 lp->msf.minute = bp->msf.minute;
  782                 lp->msf.second = bp->msf.second;
  783                 lp->msf.frame = bp->msf.frame;
  784         }
  785 }
  786 
  787 static void
  788 set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba)
  789 {
  790         if (format == LINUX_CDROM_MSF) {
  791                 addr->msf.frame = lba % 75;
  792                 lba /= 75;
  793                 lba += 2;
  794                 addr->msf.second = lba % 60;
  795                 addr->msf.minute = lba / 60;
  796         } else
  797                 addr->lba = lba;
  798 }
  799 
  800 static int
  801 linux_ioctl_CDROMREADTOCHDR(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  802 {
  803         struct ioc_toc_header th;
  804         struct linux_cdrom_tochdr lth;
  805         int error;
  806 
  807         error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th, cred, NULL);
  808         if (error)
  809                 return (error);
  810         lth.cdth_trk0 = th.starting_track;
  811         lth.cdth_trk1 = th.ending_track;
  812         bcopy(&lth, data, sizeof(lth));
  813         return (0);
  814 }
  815 
  816 static int
  817 linux_ioctl_CDROMREADTOCENTRY(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  818 {
  819         struct linux_cdrom_tocentry *ltep = (struct linux_cdrom_tocentry *)data;
  820         struct ioc_read_toc_single_entry irtse;
  821         int error;
  822 
  823         irtse.address_format = ltep->cdte_format;
  824         irtse.track = ltep->cdte_track;
  825         error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse, cred, NULL);
  826         if (error)
  827                 return (error);
  828 
  829         ltep->cdte_ctrl = irtse.entry.control;
  830         ltep->cdte_adr = irtse.entry.addr_type;
  831         bsd_to_linux_msf_lba(irtse.address_format, &irtse.entry.addr,
  832                              &ltep->cdte_addr);
  833         return (0);
  834 }       
  835 
  836 static int
  837 linux_ioctl_CDROMSUBCHNL(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  838 {
  839         struct linux_cdrom_subchnl *sc = (struct linux_cdrom_subchnl *)data;
  840         struct ioc_read_subchannel bsdsc;
  841         struct cd_sub_channel_info *bsdinfo;
  842         int error;
  843         caddr_t sg = stackgap_init();
  844 
  845         bsdinfo = stackgap_alloc(&sg, sizeof(struct cd_sub_channel_info));
  846         bsdsc.address_format = CD_LBA_FORMAT;
  847         bsdsc.data_format = CD_CURRENT_POSITION;
  848         bsdsc.track = 0;
  849         bsdsc.data_len = sizeof(struct cd_sub_channel_info);
  850         bsdsc.data = bsdinfo;
  851         error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc, cred, NULL);
  852         if (error)
  853                 return (error);
  854         sc->cdsc_audiostatus = bsdinfo->header.audio_status;
  855         sc->cdsc_adr = bsdinfo->what.position.addr_type;
  856         sc->cdsc_ctrl = bsdinfo->what.position.control;
  857         sc->cdsc_trk = bsdinfo->what.position.track_number;
  858         sc->cdsc_ind = bsdinfo->what.position.index_number;
  859         set_linux_cdrom_addr(&sc->cdsc_absaddr, sc->cdsc_format, bsdinfo->what.position.absaddr.lba);
  860         set_linux_cdrom_addr(&sc->cdsc_reladdr, sc->cdsc_format, bsdinfo->what.position.reladdr.lba);
  861         return (0);
  862 }
  863 
  864 
  865 /*
  866  * Sound related ioctls
  867  */
  868 
  869 static int
  870 linux_ioctl_OSS_GETVERSION(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  871 {
  872         int version = linux_get_oss_version(curthread);
  873 
  874         bcopy(&version, data, sizeof(int));
  875         return (0);
  876 }
  877 
  878 
  879 /*
  880  * Console related ioctls
  881  */
  882 
  883 #define ISSIGVALID(sig)         ((sig) > 0 && (sig) < NSIG)
  884 
  885 static int
  886 linux_ioctl_KDSKBMODE(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  887 {
  888         int kbdmode;
  889 
  890         switch ((u_long)data) {
  891         case LINUX_KBD_RAW:
  892                 kbdmode = K_RAW;
  893                 break;
  894         case LINUX_KBD_XLATE:
  895                 kbdmode = K_XLATE;
  896                 break;
  897         case LINUX_KBD_MEDIUMRAW:
  898                 kbdmode = K_RAW;
  899                 break;
  900         default:
  901                 return (EINVAL);
  902         }
  903         return (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode, cred, NULL));
  904 }
  905 
  906 static int
  907 linux_ioctl_VT_SETMODE(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  908 {
  909         struct vt_mode *mode = (struct vt_mode *)data;
  910 
  911         if (!ISSIGVALID(mode->frsig) && ISSIGVALID(mode->acqsig))
  912                 mode->frsig = mode->acqsig;
  913         return (fo_ioctl(fp, VT_SETMODE, data, cred, NULL));
  914 }
  915 
  916 
  917 /*
  918  * Socket related ioctls
  919  */
  920 
  921 /*
  922  * Criteria for interface name translation
  923  */
  924 #define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER)
  925 
  926 /*
  927  * Interface function used by linprocfs (at the time of writing). It's not
  928  * used by the Linuxulator itself.
  929  */
  930 int
  931 linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen)
  932 {
  933         struct ifnet *ifscan;
  934         int ethno;
  935 
  936         /* Short-circuit non ethernet interfaces */
  937         if (!IFP_IS_ETH(ifp))
  938                 return (strlcpy(buffer, ifp->if_xname, buflen));
  939 
  940         /* Determine the (relative) unit number for ethernet interfaces */
  941         ethno = 0;
  942         TAILQ_FOREACH(ifscan, &ifnet, if_link) {
  943                 if (ifscan == ifp)
  944                         return (ksnprintf(buffer, buflen, "eth%d", ethno));
  945                 if (IFP_IS_ETH(ifscan))
  946                         ethno++;
  947         }
  948 
  949         return (0);
  950 }
  951 
  952 /*
  953  * Translate a Linux interface name to a FreeBSD interface name,
  954  * and return the associated ifnet structure
  955  * bsdname and lxname need to be least IFNAMSIZ bytes long, but
  956  * can point to the same buffer.
  957  */
  958 
  959 static struct ifnet *
  960 ifname_linux_to_bsd(const char *lxname, char *bsdname)
  961 {
  962         struct ifnet *ifp;
  963         int len, unit;
  964         char *ep;
  965         int is_eth, index;
  966 
  967         for (len = 0; len < LINUX_IFNAMSIZ; ++len)
  968                 if (!isalpha(lxname[len]))
  969                         break;
  970         if (len == 0 || len == LINUX_IFNAMSIZ)
  971                 return (NULL);
  972         unit = (int)strtoul(lxname + len, &ep, 10);
  973         if (ep == NULL || ep == lxname + len || ep >= lxname + LINUX_IFNAMSIZ)
  974                 return (NULL);
  975         index = 0;
  976         is_eth = (len == 3 && !strncmp(lxname, "eth", len)) ? 1 : 0;
  977         TAILQ_FOREACH(ifp, &ifnet, if_link) {
  978                 /*
  979                  * Allow Linux programs to use FreeBSD names. Don't presume
  980                  * we never have an interface named "eth", so don't make
  981                  * the test optional based on is_eth.
  982                  */
  983                 if (strncmp(ifp->if_xname, lxname, LINUX_IFNAMSIZ) == 0)
  984                         break;
  985                 if (is_eth && IFP_IS_ETH(ifp) && unit == index++)
  986                         break;
  987         }
  988         if (ifp != NULL)
  989                 strlcpy(bsdname, ifp->if_xname, IFNAMSIZ);
  990         return (ifp);
  991 }
  992 
  993 static int
  994 linux_ioctl_SIOCGIFCONF(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
  995 {
  996         struct ifconf *ifc = (struct ifconf *)data;
  997         struct l_ifreq ifr;
  998         struct ifnet *ifp;
  999         struct iovec iov;
 1000         struct uio uio;
 1001         int error, ethno;
 1002 
 1003         /* much easier to use uiomove than keep track ourselves */
 1004         iov.iov_base = ifc->ifc_buf;
 1005         iov.iov_len = ifc->ifc_len;
 1006         uio.uio_iov = &iov;
 1007         uio.uio_iovcnt = 1;
 1008         uio.uio_offset = 0;
 1009         uio.uio_resid = ifc->ifc_len;
 1010         uio.uio_segflg = UIO_USERSPACE;
 1011         uio.uio_rw = UIO_READ;
 1012         uio.uio_td = curthread;
 1013 
 1014         /* Keep track of eth interfaces */
 1015         ethno = 0;
 1016 
 1017         /* Return all AF_INET addresses of all interfaces */
 1018         TAILQ_FOREACH(ifp, &ifnet, if_link) {
 1019                 struct ifaddr_container *ifac;
 1020 
 1021                 if (uio.uio_resid <= 0)
 1022                         break;
 1023 
 1024                 bzero(&ifr, sizeof ifr);
 1025                 if (IFP_IS_ETH(ifp))
 1026                         ksnprintf(ifr.ifr_name, LINUX_IFNAMSIZ, "eth%d",
 1027                             ethno++);
 1028                 else
 1029                         strlcpy(ifr.ifr_name, ifp->if_xname, LINUX_IFNAMSIZ);
 1030 
 1031                 /* Walk the address list */
 1032                 TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) {
 1033                         struct ifaddr *ifa = ifac->ifa;
 1034                         struct sockaddr *sa = ifa->ifa_addr;
 1035 
 1036                         if (uio.uio_resid <= 0)
 1037                                 break;
 1038 
 1039                         if (sa->sa_family == AF_INET) {
 1040                                 ifr.ifr_addr.sa_family = LINUX_AF_INET;
 1041                                 memcpy(ifr.ifr_addr.sa_data, sa->sa_data,
 1042                                     sizeof(ifr.ifr_addr.sa_data));
 1043 
 1044                                 error = uiomove((caddr_t)&ifr, sizeof ifr,
 1045                                     &uio);
 1046                                 if (error != 0)
 1047                                         return (error);
 1048                         }
 1049                 }
 1050         }
 1051 
 1052         ifc->ifc_len -= uio.uio_resid;
 1053 
 1054         return (0);
 1055 }
 1056 
 1057 static int
 1058 linux_ioctl_SIOCGIFFLAGS(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
 1059 {
 1060         struct l_ifreq *ifr = (struct l_ifreq *)data;
 1061         struct ifnet *ifp;
 1062         char ifname[IFNAMSIZ];
 1063         l_short flags;
 1064 
 1065 #if 0
 1066         if (fp->f_type != DTYPE_SOCKET) {
 1067                 /* XXX: I doubt this is correct because
 1068                  *      we don't translate the ifname and
 1069                  *      use l_ifreq instead of ifreq
 1070                  */
 1071                 return (fo_ioctl(fp, SIOCGIFFLAGS, data, cred, NULL));
 1072         }
 1073 #endif
 1074 
 1075         ifp = ifname_linux_to_bsd(ifr->ifr_name, ifname);
 1076         if (ifp == NULL)
 1077                 return (EINVAL);
 1078 
 1079         flags = ifp->if_flags;
 1080         /* these flags have no Linux equivalent */
 1081         flags &= ~(IFF_SMART|IFF_SIMPLEX| IFF_LINK0|IFF_LINK1|IFF_LINK2);
 1082         /* Linux' multicast flag is in a different bit */
 1083         if (flags & IFF_MULTICAST) {
 1084                 flags &= ~IFF_MULTICAST;
 1085                 flags |= 0x1000;
 1086         }
 1087 
 1088         ifr->ifr_flags = flags;
 1089         return (0);
 1090 }
 1091 
 1092 #define ARPHRD_ETHER    1
 1093 #define ARPHRD_LOOPBACK 772
 1094 
 1095 /* XXX: could implement using native ioctl, so only mapping */
 1096 static int
 1097 linux_ioctl_SIOCGIFINDEX(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
 1098 {
 1099         struct l_ifreq *ifr = (struct l_ifreq *)data;
 1100         struct ifnet *ifp;
 1101         char ifname[IFNAMSIZ];
 1102         l_int index;
 1103 
 1104         ifp = ifname_linux_to_bsd(ifr->ifr_name, ifname);
 1105         if (ifp == NULL)
 1106                 return EINVAL;
 1107 
 1108 #if DEBUG
 1109         kprintf("Interface index: %d\n", ifp->if_index);
 1110 #endif
 1111 
 1112         index = ifp->if_index;
 1113         return (copyout(&index, &ifr->ifr_ifindex, sizeof(index)));
 1114 }
 1115 
 1116 static int
 1117 linux_ioctl_SIOCGIFMETRIC(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
 1118 {
 1119         struct l_ifreq *ifr = (struct l_ifreq *)data;
 1120         struct ifnet *ifp;
 1121         char ifname[IFNAMSIZ];
 1122         l_int metric;
 1123 
 1124         ifp = ifname_linux_to_bsd(ifr->ifr_name, ifname);
 1125         if (ifp == NULL)
 1126                 return EINVAL;
 1127 
 1128         metric = ifp->if_metric;
 1129         return (copyout(&metric, &ifr->ifr_ifmetric, sizeof(metric)));
 1130 }
 1131 
 1132 static int
 1133 linux_ioctl_SIOGIFHWADDR(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
 1134 {
 1135         struct l_ifreq *ifr = (struct l_ifreq *)data;
 1136         struct ifnet *ifp;
 1137         char ifname[IFNAMSIZ];
 1138         struct sockaddr_dl *sdl;
 1139         struct l_sockaddr lsa;
 1140         struct ifaddr_container *ifac;
 1141 
 1142         ifp = ifname_linux_to_bsd(ifr->ifr_name, ifname);
 1143         if (ifp == NULL) {
 1144                 return EINVAL;
 1145         }
 1146 
 1147         if (ifp->if_type == IFT_LOOP) {
 1148                 bzero(&ifr->ifr_hwaddr, sizeof lsa);
 1149                 ifr->ifr_hwaddr.sa_family = ARPHRD_LOOPBACK;
 1150                 return (0);
 1151         }
 1152         
 1153         if (ifp->if_type != IFT_ETHER)
 1154                 return (ENOENT);
 1155 
 1156         TAILQ_FOREACH(ifac, &ifp->if_addrheads[mycpuid], ifa_link) {
 1157                 struct ifaddr *ifa = ifac->ifa;
 1158 
 1159                 sdl = (struct sockaddr_dl*)ifa->ifa_addr;
 1160                 if (sdl != NULL && (sdl->sdl_family == AF_LINK) &&
 1161                     (sdl->sdl_type == IFT_ETHER)) {
 1162                         bzero(&ifr->ifr_hwaddr, sizeof lsa);
 1163                         ifr->ifr_hwaddr.sa_family = ARPHRD_ETHER;
 1164                         bcopy(LLADDR(sdl), ifr->ifr_hwaddr.sa_data, LINUX_IFHWADDRLEN);
 1165                         return (0);
 1166                 }
 1167         }
 1168         
 1169         return (ENOENT);
 1170 }
 1171 
 1172 static int
 1173 linux_ioctl_map_ifname(struct file *fp, u_long cmd, u_long ocmd, caddr_t data, struct ucred *cred)
 1174 {
 1175         struct ifnet *ifp;
 1176         int error;
 1177         char *oifname = (char *)data;
 1178         char lifname[LINUX_IFNAMSIZ];
 1179 
 1180         KASSERT(LINUX_IFNAMSIZ == IFNAMSIZ,
 1181             ("%s(): LINUX_IFNAMSIZ != IFNAMSIZ", __func__));
 1182         
 1183         if (fp->f_type != DTYPE_SOCKET) {
 1184                 /*
 1185                  *  XXX: I doubt this is correct because
 1186                  *       we don't map the ifname
 1187                  */
 1188                 /* not a socket - probably a tap / vmnet device */
 1189                 if (ocmd == LINUX_SIOCGIFADDR || ocmd == LINUX_SIOCSIFADDR) {
 1190                         cmd = (ocmd == LINUX_SIOCGIFADDR) ? SIOCGIFADDR : SIOCSIFADDR;
 1191                         return (fo_ioctl(fp, cmd, data, cred, NULL));
 1192                 } else
 1193                         return (ENOIOCTL);
 1194         }
 1195 
 1196         /* Save the original ifname */
 1197         bcopy(oifname, lifname, LINUX_IFNAMSIZ);
 1198 #ifdef DEBUG
 1199         kprintf("%s(): ioctl %d on %.*s\n", __func__,
 1200                 (int)(cmd & 0xffff), LINUX_IFNAMSIZ, lifname);
 1201 #endif
 1202         /* Replace linux ifname with bsd ifname */
 1203         ifp = ifname_linux_to_bsd(lifname, oifname);
 1204         if (ifp == NULL) {
 1205                 error = EINVAL;
 1206                 goto clean_ifname;
 1207         }
 1208 
 1209 #ifdef DEBUG
 1210         kprintf("%s(): %s translated to %s\n", __func__,
 1211                 lifname, oifname);
 1212 #endif
 1213 
 1214         error = fo_ioctl(fp, cmd, data, cred, NULL);
 1215 
 1216 clean_ifname:
 1217         bcopy(lifname, oifname, LINUX_IFNAMSIZ);
 1218         return (error);
 1219 }
 1220 
 1221 
 1222 /*
 1223  * generic linux -> BSD syscall direction mapper
 1224  */
 1225 u_long
 1226 linux_gen_dirmap(u_long lstart, u_long lend, u_long bstart, u_long bend, u_long cmd, u_long ocmd)
 1227 {
 1228         static u_int32_t dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT };
 1229 
 1230         return ((cmd & ~IOC_DIRMASK) | dirbits[ocmd >> 30]);
 1231 }
 1232 
 1233 
 1234 static struct ioctl_map_range linux_ioctl_map_entries[] = {
 1235         /* disk ioctl */
 1236         MAPPED_IOCTL_IOR(LINUX_BLKGETSIZE, linux_ioctl_BLKGETSIZE32, uint32_t),
 1237         /* termio ioctl */
 1238         MAPPED_IOCTL_IOR(LINUX_TCGETS, linux_ioctl_TCGETS, struct linux_termios),
 1239         MAPPED_IOCTL_IOW(LINUX_TCSETS, linux_ioctl_TCSETS, struct linux_termios),
 1240         MAPPED_IOCTL_IOW(LINUX_TCSETSW, linux_ioctl_TCSETSW, struct linux_termios),
 1241         MAPPED_IOCTL_IOW(LINUX_TCSETSF, linux_ioctl_TCSETSF, struct linux_termios),
 1242         MAPPED_IOCTL_IOR(LINUX_TCGETA, linux_ioctl_TCGETA, struct linux_termio),
 1243         MAPPED_IOCTL_IOW(LINUX_TCSETA, linux_ioctl_TCSETA, struct linux_termio),
 1244         MAPPED_IOCTL_IOW(LINUX_TCSETAW, linux_ioctl_TCSETAW, struct linux_termio),
 1245         MAPPED_IOCTL_IOW(LINUX_TCSETAF, linux_ioctl_TCSETAF, struct linux_termio),
 1246         MAPPED_IOCTL_IO(LINUX_TCXONC, linux_ioctl_TCXONC),
 1247         MAPPED_IOCTL_IO(LINUX_TCFLSH, linux_ioctl_TCFLSH),
 1248         MAPPED_IOCTL_IO(LINUX_TIOCLINUX, linux_ioctl_TIOCLINUX),
 1249         MAPPED_IOCTL_MAP(LINUX_TIOCEXCL, TIOCEXCL),
 1250         MAPPED_IOCTL_MAP(LINUX_TIOCNXCL, TIOCNXCL),
 1251         MAPPED_IOCTL_MAP(LINUX_TIOCGPGRP, TIOCGPGRP),
 1252         MAPPED_IOCTL_MAP(LINUX_TIOCSPGRP, TIOCSPGRP),
 1253         MAPPED_IOCTL_MAP(LINUX_TIOCGWINSZ, TIOCGWINSZ),
 1254         MAPPED_IOCTL_MAP(LINUX_TIOCSWINSZ, TIOCSWINSZ),
 1255         MAPPED_IOCTL_MAP(LINUX_TIOCMGET, TIOCMGET),
 1256         MAPPED_IOCTL_MAP(LINUX_TIOCMBIS, TIOCMBIS),
 1257         MAPPED_IOCTL_MAP(LINUX_TIOCMBIC, TIOCMBIC),
 1258         MAPPED_IOCTL_MAP(LINUX_TIOCMSET, TIOCMSET),
 1259         MAPPED_IOCTL_MAP(LINUX_FIONREAD, FIONREAD),
 1260         MAPPED_IOCTL_MAP(LINUX_TIOCCONS, TIOCCONS),
 1261         MAPPED_IOCTL_IOR(LINUX_TIOCGSERIAL, linux_ioctl_TIOCGSERIAL, struct linux_serial_struct),
 1262         MAPPED_IOCTL_IOW(LINUX_TIOCSSERIAL, linux_ioctl_TIOCSSERIAL, struct linux_serial_struct),
 1263         MAPPED_IOCTL_MAP(LINUX_FIONBIO, FIONBIO),
 1264         MAPPED_IOCTL_MAP(LINUX_TIOCNOTTY, TIOCNOTTY),
 1265         MAPPED_IOCTL_IO(LINUX_TIOCSETD, linux_ioctl_TIOCSETD),
 1266         MAPPED_IOCTL_IOR(LINUX_TIOCGETD, linux_ioctl_TIOCGETD, int),
 1267         MAPPED_IOCTL_MAP(LINUX_FIONCLEX, FIONCLEX),
 1268         MAPPED_IOCTL_MAP(LINUX_FIOCLEX, FIOCLEX),
 1269         MAPPED_IOCTL_MAP(LINUX_FIOASYNC, FIOASYNC),
 1270         /* cdrom ioctl */
 1271         MAPPED_IOCTL_MAP(LINUX_CDROMPAUSE, CDIOCPAUSE),
 1272         MAPPED_IOCTL_MAP(LINUX_CDROMRESUME, CDIOCRESUME),
 1273         MAPPED_IOCTL_MAP(LINUX_CDROMPLAYMSF, CDIOCPLAYMSF),
 1274         MAPPED_IOCTL_MAP(LINUX_CDROMPLAYTRKIND, CDIOCPLAYTRACKS),
 1275         MAPPED_IOCTL_IOR(LINUX_CDROMREADTOCHDR, linux_ioctl_CDROMREADTOCHDR, struct linux_cdrom_tochdr),
 1276         MAPPED_IOCTL_IOWR(LINUX_CDROMREADTOCENTRY, linux_ioctl_CDROMREADTOCENTRY, struct linux_cdrom_tocentry),
 1277         MAPPED_IOCTL_MAP(LINUX_CDROMSTOP, CDIOCSTOP),
 1278         MAPPED_IOCTL_MAP(LINUX_CDROMSTART, CDIOCSTART),
 1279         MAPPED_IOCTL_MAP(LINUX_CDROMEJECT, CDIOCEJECT),
 1280         MAPPED_IOCTL_IOWR(LINUX_CDROMSUBCHNL, linux_ioctl_CDROMSUBCHNL, struct linux_cdrom_subchnl),
 1281         MAPPED_IOCTL_MAP(LINUX_CDROMRESET, CDIOCRESET),
 1282         /* sound ioctl */
 1283         MAPPED_IOCTL_MAPRANGE(LINUX_SOUND_MIXER_WRITE_MIN, LINUX_SOUND_MIXER_WRITE_MAX,
 1284                               LINUX_SOUND_MIXER_WRITE_MIN, LINUX_SOUND_MIXER_WRITE_MAX,
 1285                               NULL, linux_gen_dirmap),
 1286         MAPPED_IOCTL_IOR(LINUX_OSS_GETVERSION, linux_ioctl_OSS_GETVERSION, int),
 1287         MAPPED_IOCTL_MAP(LINUX_SOUND_MIXER_READ_DEVMASK, SOUND_MIXER_READ_DEVMASK),
 1288         MAPPED_IOCTL_MAPRANGE(LINUX_SNDCTL_DSP_MIN, LINUX_SNDCTL_DSP_MAX, LINUX_SNDCTL_DSP_MIN,
 1289                               LINUX_SNDCTL_DSP_MAX, NULL, linux_gen_dirmap),
 1290         MAPPED_IOCTL_MAPRANGE(LINUX_SNDCTL_SEQ_MIN, LINUX_SNDCTL_SEQ_MAX, LINUX_SNDCTL_SEQ_MIN,
 1291                               LINUX_SNDCTL_SEQ_MAX, NULL, linux_gen_dirmap),
 1292         /* console ioctl */
 1293         MAPPED_IOCTL_MAP(LINUX_KIOCSOUND, KIOCSOUND),
 1294         MAPPED_IOCTL_MAP(LINUX_KDMKTONE, KDMKTONE),
 1295         MAPPED_IOCTL_MAP(LINUX_KDGETLED, KDGETLED),
 1296         MAPPED_IOCTL_MAP(LINUX_KDSETLED, KDSETLED),
 1297         MAPPED_IOCTL_MAP(LINUX_KDSETMODE, KDSETMODE),
 1298         MAPPED_IOCTL_MAP(LINUX_KDGETMODE, KDGETMODE),
 1299         MAPPED_IOCTL_MAP(LINUX_KDGKBMODE, KDGKBMODE),
 1300         MAPPED_IOCTL_IOW(LINUX_KDSKBMODE, linux_ioctl_KDSKBMODE, int),
 1301         MAPPED_IOCTL_MAP(LINUX_VT_OPENQRY, VT_OPENQRY),
 1302         MAPPED_IOCTL_MAP(LINUX_VT_GETMODE, VT_GETMODE),
 1303         MAPPED_IOCTL_IOW(LINUX_VT_SETMODE, linux_ioctl_VT_SETMODE, struct vt_mode),
 1304         MAPPED_IOCTL_MAP(LINUX_VT_GETSTATE, VT_GETACTIVE),
 1305         MAPPED_IOCTL_MAP(LINUX_VT_RELDISP, VT_RELDISP),
 1306         MAPPED_IOCTL_MAP(LINUX_VT_ACTIVATE, VT_ACTIVATE),
 1307         MAPPED_IOCTL_MAP(LINUX_VT_WAITACTIVE, VT_WAITACTIVE),
 1308         /* socket ioctl */
 1309         MAPPED_IOCTL_MAP(LINUX_FIOSETOWN, FIOSETOWN),
 1310         MAPPED_IOCTL_MAP(LINUX_SIOCSPGRP, SIOCSPGRP),
 1311         MAPPED_IOCTL_MAP(LINUX_FIOGETOWN, FIOGETOWN),
 1312         MAPPED_IOCTL_MAP(LINUX_SIOCGPGRP, SIOCGPGRP),
 1313         MAPPED_IOCTL_MAP(LINUX_SIOCATMARK, SIOCATMARK),
 1314         MAPPED_IOCTL_IOWR(LINUX_SIOCGIFCONF, linux_ioctl_SIOCGIFCONF, struct ifconf),
 1315         MAPPED_IOCTL_IOWR(LINUX_SIOCGIFFLAGS, linux_ioctl_SIOCGIFFLAGS, struct l_ifreq),
 1316         MAPPED_IOCTL_MAPF(LINUX_SIOCGIFADDR, OSIOCGIFADDR, linux_ioctl_map_ifname),
 1317         MAPPED_IOCTL_MAPF(LINUX_SIOCSIFADDR, SIOCSIFADDR, linux_ioctl_map_ifname),
 1318         MAPPED_IOCTL_MAPF(LINUX_SIOCGIFDSTADDR, OSIOCGIFDSTADDR, linux_ioctl_map_ifname),
 1319         MAPPED_IOCTL_MAPF(LINUX_SIOCGIFBRDADDR, OSIOCGIFBRDADDR, linux_ioctl_map_ifname),
 1320         MAPPED_IOCTL_MAPF(LINUX_SIOCGIFNETMASK, OSIOCGIFNETMASK, linux_ioctl_map_ifname),
 1321         /*MAPPED_IOCTL_IOx(LINUX_SIOCSIFNETMASK, x, x),*/
 1322         MAPPED_IOCTL_MAPF(LINUX_SIOCGIFMTU, SIOCGIFMTU, linux_ioctl_map_ifname),
 1323         MAPPED_IOCTL_MAPF(LINUX_SIOCSIFMTU, SIOCSIFMTU, linux_ioctl_map_ifname),
 1324         MAPPED_IOCTL_IOWR(LINUX_SIOCGIFHWADDR, linux_ioctl_SIOGIFHWADDR, struct l_ifreq),
 1325         MAPPED_IOCTL_IOR(LINUX_SIOCGIFINDEX, linux_ioctl_SIOCGIFINDEX, struct l_ifreq),
 1326         MAPPED_IOCTL_IOR(LINUX_SIOCGIFMETRIC, linux_ioctl_SIOCGIFMETRIC, struct l_ifreq),
 1327         MAPPED_IOCTL_MAP(LINUX_SIOCADDMULTI, SIOCADDMULTI),
 1328         MAPPED_IOCTL_MAP(LINUX_SIOCDELMULTI, SIOCDELMULTI),
 1329         /*
 1330          * XXX This is slightly bogus, but these ioctls are currently
 1331          * XXX only used by the aironet (if_an) network driver.
 1332          */
 1333         MAPPED_IOCTL_MAPF(LINUX_SIOCDEVPRIVATE, SIOCGPRIVATE_0, linux_ioctl_map_ifname),
 1334         MAPPED_IOCTL_MAPF(LINUX_SIOCDEVPRIVATE+1, SIOCGPRIVATE_1, linux_ioctl_map_ifname),
 1335         MAPPED_IOCTL_MAPF(0, 0, NULL)
 1336         };
 1337 
 1338 struct ioctl_map linux_ioctl_map = {
 1339         0xffff,         /* mask */
 1340         "linux",        /* subsys */
 1341         LIST_HEAD_INITIALIZER(mapping)
 1342         };
 1343 
 1344 static struct ioctl_map_handler linux_ioctl_base_handler = {
 1345         &linux_ioctl_map,
 1346         "base",
 1347         linux_ioctl_map_entries
 1348         };
 1349 
 1350 /*
 1351  * main ioctl syscall function
 1352  *
 1353  * MPALMOSTSAFE
 1354  */
 1355 int
 1356 sys_linux_ioctl(struct linux_ioctl_args *args)
 1357 {
 1358         int error;
 1359 
 1360 #ifdef DEBUG
 1361         if (ldebug(ioctl))
 1362                 kprintf(ARGS(ioctl, "%d, %04x, *"), args->fd, args->cmd);
 1363 #endif
 1364 
 1365         get_mplock();
 1366         error = mapped_ioctl(args->fd, args->cmd, (caddr_t)args->arg,
 1367                              &linux_ioctl_map, &args->sysmsg);
 1368         rel_mplock();
 1369         return (error);
 1370 }
 1371 
 1372 SYSINIT  (linux_ioctl_register, SI_BOOT2_KLD, SI_ORDER_MIDDLE,
 1373           mapped_ioctl_register_handler, &linux_ioctl_base_handler);
 1374 SYSUNINIT(linux_ioctl_register, SI_BOOT2_KLD, SI_ORDER_MIDDLE,
 1375           mapped_ioctl_unregister_handler, &linux_ioctl_base_handler);

Cache object: f5333bd5e3cd70e35674a83eb0ce095c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.