aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2007-11-07 04:24:56 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-11-07 07:14:19 -0500
commit0fc00e2440b717e19bab1ae0015f03936bdf7967 (patch)
tree4ae26ce4c71511fad3bad97384dce22a69c16bb6
parent543821c6f5dea5221426eaf1eac98b100249c7ac (diff)
[TTY]: Fix network driver interactions with TCGET/SET calls.
Dave Miller noted various cases where line disciplines for things like ppp go poking around in termios themselves in ways that broke with the new termios code. Rather than have them all learning about termios internals provide proper methods for this - tty_mode_ioctl() This handles all the terminal mode handling for speed/carrier etc and none of the methods are ldisc dependant so they can be called by any user - tty_perform_flush() This extracts the flush functionality and enables pppd the ppp layer to share it cleanly. The existing n_tty_ioctl code is refactored in this patch to provide the new functions and to call them itself appropriately. This patch has no (intended) behaviour changes and simply prepares for the other fixes. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/char/tty_ioctl.c170
-rw-r--r--include/linux/tty.h4
2 files changed, 107 insertions, 67 deletions
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 7a003504c265..1bdd2bf4f37d 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -730,13 +730,23 @@ static int send_prio_char(struct tty_struct *tty, char ch)
730 return 0; 730 return 0;
731} 731}
732 732
733int n_tty_ioctl(struct tty_struct * tty, struct file * file, 733/**
734 unsigned int cmd, unsigned long arg) 734 * tty_mode_ioctl - mode related ioctls
735 * @tty: tty for the ioctl
736 * @file: file pointer for the tty
737 * @cmd: command
738 * @arg: ioctl argument
739 *
740 * Perform non line discipline specific mode control ioctls. This
741 * is designed to be called by line disciplines to ensure they provide
742 * consistent mode setting.
743 */
744
745int tty_mode_ioctl(struct tty_struct * tty, struct file *file,
746 unsigned int cmd, unsigned long arg)
735{ 747{
736 struct tty_struct * real_tty; 748 struct tty_struct * real_tty;
737 void __user *p = (void __user *)arg; 749 void __user *p = (void __user *)arg;
738 int retval;
739 struct tty_ldisc *ld;
740 750
741 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 751 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
742 tty->driver->subtype == PTY_TYPE_MASTER) 752 tty->driver->subtype == PTY_TYPE_MASTER)
@@ -799,6 +809,93 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
799 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO); 809 return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
800 case TCSETA: 810 case TCSETA:
801 return set_termios(real_tty, p, TERMIOS_TERMIO); 811 return set_termios(real_tty, p, TERMIOS_TERMIO);
812#ifndef TCGETS2
813 case TIOCGLCKTRMIOS:
814 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
815 return -EFAULT;
816 return 0;
817
818 case TIOCSLCKTRMIOS:
819 if (!capable(CAP_SYS_ADMIN))
820 return -EPERM;
821 if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
822 return -EFAULT;
823 return 0;
824#else
825 case TIOCGLCKTRMIOS:
826 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
827 return -EFAULT;
828 return 0;
829
830 case TIOCSLCKTRMIOS:
831 if (!capable(CAP_SYS_ADMIN))
832 return -EPERM;
833 if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
834 return -EFAULT;
835 return 0;
836#endif
837 case TIOCGSOFTCAR:
838 return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
839 case TIOCSSOFTCAR:
840 if (get_user(arg, (unsigned int __user *) arg))
841 return -EFAULT;
842 mutex_lock(&tty->termios_mutex);
843 tty->termios->c_cflag =
844 ((tty->termios->c_cflag & ~CLOCAL) |
845 (arg ? CLOCAL : 0));
846 mutex_unlock(&tty->termios_mutex);
847 return 0;
848 default:
849 return -ENOIOCTLCMD;
850 }
851}
852
853EXPORT_SYMBOL_GPL(tty_mode_ioctl);
854
855int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
856{
857 struct tty_ldisc *ld;
858 int retval = tty_check_change(tty);
859 if (retval)
860 return retval;
861
862 ld = tty_ldisc_ref(tty);
863 switch (arg) {
864 case TCIFLUSH:
865 if (ld && ld->flush_buffer)
866 ld->flush_buffer(tty);
867 break;
868 case TCIOFLUSH:
869 if (ld && ld->flush_buffer)
870 ld->flush_buffer(tty);
871 /* fall through */
872 case TCOFLUSH:
873 if (tty->driver->flush_buffer)
874 tty->driver->flush_buffer(tty);
875 break;
876 default:
877 tty_ldisc_deref(ld);
878 return -EINVAL;
879 }
880 tty_ldisc_deref(ld);
881 return 0;
882}
883
884EXPORT_SYMBOL_GPL(tty_perform_flush);
885
886int n_tty_ioctl(struct tty_struct * tty, struct file * file,
887 unsigned int cmd, unsigned long arg)
888{
889 struct tty_struct * real_tty;
890 int retval;
891
892 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
893 tty->driver->subtype == PTY_TYPE_MASTER)
894 real_tty = tty->link;
895 else
896 real_tty = tty;
897
898 switch (cmd) {
802 case TCXONC: 899 case TCXONC:
803 retval = tty_check_change(tty); 900 retval = tty_check_change(tty);
804 if (retval) 901 if (retval)
@@ -829,30 +926,7 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
829 } 926 }
830 return 0; 927 return 0;
831 case TCFLSH: 928 case TCFLSH:
832 retval = tty_check_change(tty); 929 return tty_perform_flush(tty, arg);
833 if (retval)
834 return retval;
835
836 ld = tty_ldisc_ref(tty);
837 switch (arg) {
838 case TCIFLUSH:
839 if (ld && ld->flush_buffer)
840 ld->flush_buffer(tty);
841 break;
842 case TCIOFLUSH:
843 if (ld && ld->flush_buffer)
844 ld->flush_buffer(tty);
845 /* fall through */
846 case TCOFLUSH:
847 if (tty->driver->flush_buffer)
848 tty->driver->flush_buffer(tty);
849 break;
850 default:
851 tty_ldisc_deref(ld);
852 return -EINVAL;
853 }
854 tty_ldisc_deref(ld);
855 return 0;
856 case TIOCOUTQ: 930 case TIOCOUTQ:
857 return put_user(tty->driver->chars_in_buffer ? 931 return put_user(tty->driver->chars_in_buffer ?
858 tty->driver->chars_in_buffer(tty) : 0, 932 tty->driver->chars_in_buffer(tty) : 0,
@@ -862,32 +936,6 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
862 if (L_ICANON(tty)) 936 if (L_ICANON(tty))
863 retval = inq_canon(tty); 937 retval = inq_canon(tty);
864 return put_user(retval, (unsigned int __user *) arg); 938 return put_user(retval, (unsigned int __user *) arg);
865#ifndef TCGETS2
866 case TIOCGLCKTRMIOS:
867 if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
868 return -EFAULT;
869 return 0;
870
871 case TIOCSLCKTRMIOS:
872 if (!capable(CAP_SYS_ADMIN))
873 return -EPERM;
874 if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
875 return -EFAULT;
876 return 0;
877#else
878 case TIOCGLCKTRMIOS:
879 if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
880 return -EFAULT;
881 return 0;
882
883 case TIOCSLCKTRMIOS:
884 if (!capable(CAP_SYS_ADMIN))
885 return -EPERM;
886 if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
887 return -EFAULT;
888 return 0;
889#endif
890
891 case TIOCPKT: 939 case TIOCPKT:
892 { 940 {
893 int pktmode; 941 int pktmode;
@@ -906,19 +954,9 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
906 tty->packet = 0; 954 tty->packet = 0;
907 return 0; 955 return 0;
908 } 956 }
909 case TIOCGSOFTCAR:
910 return put_user(C_CLOCAL(tty) ? 1 : 0, (int __user *)arg);
911 case TIOCSSOFTCAR:
912 if (get_user(arg, (unsigned int __user *) arg))
913 return -EFAULT;
914 mutex_lock(&tty->termios_mutex);
915 tty->termios->c_cflag =
916 ((tty->termios->c_cflag & ~CLOCAL) |
917 (arg ? CLOCAL : 0));
918 mutex_unlock(&tty->termios_mutex);
919 return 0;
920 default: 957 default:
921 return -ENOIOCTLCMD; 958 /* Try the mode commands */
959 return tty_mode_ioctl(tty, file, cmd, arg);
922 } 960 }
923} 961}
924 962
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 56164d7ba0ad..c555f5442bd7 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -332,7 +332,9 @@ extern void tty_ldisc_flush(struct tty_struct *tty);
332 332
333extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 333extern int tty_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
334 unsigned long arg); 334 unsigned long arg);
335 335extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
336 unsigned int cmd, unsigned long arg);
337extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
336extern dev_t tty_devnum(struct tty_struct *tty); 338extern dev_t tty_devnum(struct tty_struct *tty);
337extern void proc_clear_tty(struct task_struct *p); 339extern void proc_clear_tty(struct task_struct *p);
338extern struct tty_struct *get_current_tty(void); 340extern struct tty_struct *get_current_tty(void);