aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/wext.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/wext.c')
-rw-r--r--net/wireless/wext.c258
1 files changed, 134 insertions, 124 deletions
diff --git a/net/wireless/wext.c b/net/wireless/wext.c
index cd2cf9fec10f..d17c0f45accb 100644
--- a/net/wireless/wext.c
+++ b/net/wireless/wext.c
@@ -694,6 +694,138 @@ void wext_proc_exit(struct net *net)
694 */ 694 */
695 695
696/* ---------------------------------------------------------------- */ 696/* ---------------------------------------------------------------- */
697static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd,
698 const struct iw_ioctl_description *descr,
699 iw_handler handler, struct net_device *dev,
700 struct iw_request_info *info)
701{
702 int err, extra_size, user_length = 0, essid_compat = 0;
703 char *extra;
704
705 /* Calculate space needed by arguments. Always allocate
706 * for max space.
707 */
708 extra_size = descr->max_tokens * descr->token_size;
709
710 /* Check need for ESSID compatibility for WE < 21 */
711 switch (cmd) {
712 case SIOCSIWESSID:
713 case SIOCGIWESSID:
714 case SIOCSIWNICKN:
715 case SIOCGIWNICKN:
716 if (iwp->length == descr->max_tokens + 1)
717 essid_compat = 1;
718 else if (IW_IS_SET(cmd) && (iwp->length != 0)) {
719 char essid[IW_ESSID_MAX_SIZE + 1];
720
721 err = copy_from_user(essid, iwp->pointer,
722 iwp->length *
723 descr->token_size);
724 if (err)
725 return -EFAULT;
726
727 if (essid[iwp->length - 1] == '\0')
728 essid_compat = 1;
729 }
730 break;
731 default:
732 break;
733 }
734
735 iwp->length -= essid_compat;
736
737 /* Check what user space is giving us */
738 if (IW_IS_SET(cmd)) {
739 /* Check NULL pointer */
740 if (!iwp->pointer && iwp->length != 0)
741 return -EFAULT;
742 /* Check if number of token fits within bounds */
743 if (iwp->length > descr->max_tokens)
744 return -E2BIG;
745 if (iwp->length < descr->min_tokens)
746 return -EINVAL;
747 } else {
748 /* Check NULL pointer */
749 if (!iwp->pointer)
750 return -EFAULT;
751 /* Save user space buffer size for checking */
752 user_length = iwp->length;
753
754 /* Don't check if user_length > max to allow forward
755 * compatibility. The test user_length < min is
756 * implied by the test at the end.
757 */
758
759 /* Support for very large requests */
760 if ((descr->flags & IW_DESCR_FLAG_NOMAX) &&
761 (user_length > descr->max_tokens)) {
762 /* Allow userspace to GET more than max so
763 * we can support any size GET requests.
764 * There is still a limit : -ENOMEM.
765 */
766 extra_size = user_length * descr->token_size;
767
768 /* Note : user_length is originally a __u16,
769 * and token_size is controlled by us,
770 * so extra_size won't get negative and
771 * won't overflow...
772 */
773 }
774 }
775
776 /* kzalloc() ensures NULL-termination for essid_compat. */
777 extra = kzalloc(extra_size, GFP_KERNEL);
778 if (!extra)
779 return -ENOMEM;
780
781 /* If it is a SET, get all the extra data in here */
782 if (IW_IS_SET(cmd) && (iwp->length != 0)) {
783 if (copy_from_user(extra, iwp->pointer,
784 iwp->length *
785 descr->token_size)) {
786 err = -EFAULT;
787 goto out;
788 }
789 }
790
791 err = handler(dev, info, (union iwreq_data *) iwp, extra);
792
793 iwp->length += essid_compat;
794
795 /* If we have something to return to the user */
796 if (!err && IW_IS_GET(cmd)) {
797 /* Check if there is enough buffer up there */
798 if (user_length < iwp->length) {
799 err = -E2BIG;
800 goto out;
801 }
802
803 if (copy_to_user(iwp->pointer, extra,
804 iwp->length *
805 descr->token_size)) {
806 err = -EFAULT;
807 goto out;
808 }
809 }
810
811 /* Generate an event to notify listeners of the change */
812 if ((descr->flags & IW_DESCR_FLAG_EVENT) && err == -EIWCOMMIT) {
813 union iwreq_data *data = (union iwreq_data *) iwp;
814
815 if (descr->flags & IW_DESCR_FLAG_RESTRICT)
816 /* If the event is restricted, don't
817 * export the payload.
818 */
819 wireless_send_event(dev, cmd, data, NULL);
820 else
821 wireless_send_event(dev, cmd, data, extra);
822 }
823
824out:
825 kfree(extra);
826 return err;
827}
828
697/* 829/*
698 * Wrapper to call a standard Wireless Extension handler. 830 * Wrapper to call a standard Wireless Extension handler.
699 * We do various checks and also take care of moving data between 831 * We do various checks and also take care of moving data between
@@ -729,130 +861,8 @@ static int ioctl_standard_call(struct net_device * dev,
729 ((ret == 0) || (ret == -EIWCOMMIT))) 861 ((ret == 0) || (ret == -EIWCOMMIT)))
730 wireless_send_event(dev, cmd, &(iwr->u), NULL); 862 wireless_send_event(dev, cmd, &(iwr->u), NULL);
731 } else { 863 } else {
732 char * extra; 864 ret = ioctl_standard_iw_point(&iwr->u.data, cmd, descr,
733 int extra_size; 865 handler, dev, &info);
734 int user_length = 0;
735 int err;
736 int essid_compat = 0;
737
738 /* Calculate space needed by arguments. Always allocate
739 * for max space. Easier, and won't last long... */
740 extra_size = descr->max_tokens * descr->token_size;
741
742 /* Check need for ESSID compatibility for WE < 21 */
743 switch (cmd) {
744 case SIOCSIWESSID:
745 case SIOCGIWESSID:
746 case SIOCSIWNICKN:
747 case SIOCGIWNICKN:
748 if (iwr->u.data.length == descr->max_tokens + 1)
749 essid_compat = 1;
750 else if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
751 char essid[IW_ESSID_MAX_SIZE + 1];
752
753 err = copy_from_user(essid, iwr->u.data.pointer,
754 iwr->u.data.length *
755 descr->token_size);
756 if (err)
757 return -EFAULT;
758
759 if (essid[iwr->u.data.length - 1] == '\0')
760 essid_compat = 1;
761 }
762 break;
763 default:
764 break;
765 }
766
767 iwr->u.data.length -= essid_compat;
768
769 /* Check what user space is giving us */
770 if (IW_IS_SET(cmd)) {
771 /* Check NULL pointer */
772 if ((iwr->u.data.pointer == NULL) &&
773 (iwr->u.data.length != 0))
774 return -EFAULT;
775 /* Check if number of token fits within bounds */
776 if (iwr->u.data.length > descr->max_tokens)
777 return -E2BIG;
778 if (iwr->u.data.length < descr->min_tokens)
779 return -EINVAL;
780 } else {
781 /* Check NULL pointer */
782 if (iwr->u.data.pointer == NULL)
783 return -EFAULT;
784 /* Save user space buffer size for checking */
785 user_length = iwr->u.data.length;
786
787 /* Don't check if user_length > max to allow forward
788 * compatibility. The test user_length < min is
789 * implied by the test at the end. */
790
791 /* Support for very large requests */
792 if ((descr->flags & IW_DESCR_FLAG_NOMAX) &&
793 (user_length > descr->max_tokens)) {
794 /* Allow userspace to GET more than max so
795 * we can support any size GET requests.
796 * There is still a limit : -ENOMEM. */
797 extra_size = user_length * descr->token_size;
798 /* Note : user_length is originally a __u16,
799 * and token_size is controlled by us,
800 * so extra_size won't get negative and
801 * won't overflow... */
802 }
803 }
804
805 /* Create the kernel buffer */
806 /* kzalloc ensures NULL-termination for essid_compat */
807 extra = kzalloc(extra_size, GFP_KERNEL);
808 if (extra == NULL)
809 return -ENOMEM;
810
811 /* If it is a SET, get all the extra data in here */
812 if (IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
813 err = copy_from_user(extra, iwr->u.data.pointer,
814 iwr->u.data.length *
815 descr->token_size);
816 if (err) {
817 kfree(extra);
818 return -EFAULT;
819 }
820 }
821
822 /* Call the handler */
823 ret = handler(dev, &info, &(iwr->u), extra);
824
825 iwr->u.data.length += essid_compat;
826
827 /* If we have something to return to the user */
828 if (!ret && IW_IS_GET(cmd)) {
829 /* Check if there is enough buffer up there */
830 if (user_length < iwr->u.data.length) {
831 kfree(extra);
832 return -E2BIG;
833 }
834
835 err = copy_to_user(iwr->u.data.pointer, extra,
836 iwr->u.data.length *
837 descr->token_size);
838 if (err)
839 ret = -EFAULT;
840 }
841
842 /* Generate an event to notify listeners of the change */
843 if ((descr->flags & IW_DESCR_FLAG_EVENT) &&
844 ((ret == 0) || (ret == -EIWCOMMIT))) {
845 if (descr->flags & IW_DESCR_FLAG_RESTRICT)
846 /* If the event is restricted, don't
847 * export the payload */
848 wireless_send_event(dev, cmd, &(iwr->u), NULL);
849 else
850 wireless_send_event(dev, cmd, &(iwr->u),
851 extra);
852 }
853
854 /* Cleanup - I told you it wasn't that long ;-) */
855 kfree(extra);
856 } 866 }
857 867
858 /* Call commit handler if needed and defined */ 868 /* Call commit handler if needed and defined */