| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: smb_smb.c,v 1.29 2008/06/24 10:37:19 gmcgarry Exp $ */ | | 1 | /* $NetBSD: smb_smb.c,v 1.29.6.1 2009/10/27 20:31:15 bouyer Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2000-2001 Boris Popov | | 4 | * Copyright (c) 2000-2001 Boris Popov |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -28,27 +28,27 @@ | | | @@ -28,27 +28,27 @@ |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 29 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 30 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | * SUCH DAMAGE. | | 32 | * SUCH DAMAGE. |
33 | * | | 33 | * |
34 | * FreeBSD: src/sys/netsmb/smb_smb.c,v 1.10 2003/02/19 05:47:38 imp Exp | | 34 | * FreeBSD: src/sys/netsmb/smb_smb.c,v 1.10 2003/02/19 05:47:38 imp Exp |
35 | */ | | 35 | */ |
36 | /* | | 36 | /* |
37 | * various SMB requests. Most of the routines merely packs data into mbufs. | | 37 | * various SMB requests. Most of the routines merely packs data into mbufs. |
38 | */ | | 38 | */ |
39 | | | 39 | |
40 | #include <sys/cdefs.h> | | 40 | #include <sys/cdefs.h> |
41 | __KERNEL_RCSID(0, "$NetBSD: smb_smb.c,v 1.29 2008/06/24 10:37:19 gmcgarry Exp $"); | | 41 | __KERNEL_RCSID(0, "$NetBSD: smb_smb.c,v 1.29.6.1 2009/10/27 20:31:15 bouyer Exp $"); |
42 | | | 42 | |
43 | #include <sys/param.h> | | 43 | #include <sys/param.h> |
44 | #include <sys/systm.h> | | 44 | #include <sys/systm.h> |
45 | #include <sys/kernel.h> | | 45 | #include <sys/kernel.h> |
46 | #include <sys/malloc.h> | | 46 | #include <sys/malloc.h> |
47 | #include <sys/proc.h> | | 47 | #include <sys/proc.h> |
48 | #include <sys/lock.h> | | 48 | #include <sys/lock.h> |
49 | #include <sys/sysctl.h> | | 49 | #include <sys/sysctl.h> |
50 | #include <sys/socket.h> | | 50 | #include <sys/socket.h> |
51 | #include <sys/uio.h> | | 51 | #include <sys/uio.h> |
52 | | | 52 | |
53 | #include <netsmb/iconv.h> | | 53 | #include <netsmb/iconv.h> |
54 | | | 54 | |
| @@ -584,26 +584,42 @@ smb_smb_treedisconnect(struct smb_share | | | @@ -584,26 +584,42 @@ smb_smb_treedisconnect(struct smb_share |
584 | | | 584 | |
585 | static inline int | | 585 | static inline int |
586 | smb_smb_readx(struct smb_share *ssp, u_int16_t fid, size_t *len, size_t *rresid, | | 586 | smb_smb_readx(struct smb_share *ssp, u_int16_t fid, size_t *len, size_t *rresid, |
587 | struct uio *uio, struct smb_cred *scred) | | 587 | struct uio *uio, struct smb_cred *scred) |
588 | { | | 588 | { |
589 | struct smb_rq *rqp; | | 589 | struct smb_rq *rqp; |
590 | struct mbchain *mbp; | | 590 | struct mbchain *mbp; |
591 | struct mdchain *mdp; | | 591 | struct mdchain *mdp; |
592 | u_int8_t wc; | | 592 | u_int8_t wc; |
593 | int error; | | 593 | int error; |
594 | u_int16_t residhi, residlo, off, doff; | | 594 | u_int16_t residhi, residlo, off, doff; |
595 | u_int32_t resid; | | 595 | u_int32_t resid; |
596 | | | 596 | |
| | | 597 | if (!(SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_FILES) && |
| | | 598 | uio->uio_offset >= (1LL << 32)) { |
| | | 599 | /* Cannot read at/beyond 4G */ |
| | | 600 | return (EFBIG); |
| | | 601 | } |
| | | 602 | |
| | | 603 | if (!(SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_READX)) { |
| | | 604 | size_t blksz; |
| | | 605 | |
| | | 606 | blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 64; |
| | | 607 | if (blksz > 0xffff) |
| | | 608 | blksz = 0xffff; |
| | | 609 | |
| | | 610 | *len = min(blksz, *len); |
| | | 611 | } |
| | | 612 | |
597 | error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp); | | 613 | error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp); |
598 | if (error) | | 614 | if (error) |
599 | return error; | | 615 | return error; |
600 | smb_rq_getrequest(rqp, &mbp); | | 616 | smb_rq_getrequest(rqp, &mbp); |
601 | smb_rq_wstart(rqp); | | 617 | smb_rq_wstart(rqp); |
602 | mb_put_uint8(mbp, 0xff); /* no secondary command */ | | 618 | mb_put_uint8(mbp, 0xff); /* no secondary command */ |
603 | mb_put_uint8(mbp, 0); /* MBZ */ | | 619 | mb_put_uint8(mbp, 0); /* MBZ */ |
604 | mb_put_uint16le(mbp, 0); /* offset to secondary */ | | 620 | mb_put_uint16le(mbp, 0); /* offset to secondary */ |
605 | mb_put_mem(mbp, (void *)&fid, sizeof(fid), MB_MSYSTEM); | | 621 | mb_put_mem(mbp, (void *)&fid, sizeof(fid), MB_MSYSTEM); |
606 | mb_put_uint32le(mbp, uio->uio_offset); | | 622 | mb_put_uint32le(mbp, uio->uio_offset); |
607 | *len = min(SSTOVC(ssp)->vc_rxmax, *len); | | 623 | *len = min(SSTOVC(ssp)->vc_rxmax, *len); |
608 | mb_put_uint16le(mbp, *len); /* MaxCount */ | | 624 | mb_put_uint16le(mbp, *len); /* MaxCount */ |
609 | mb_put_uint16le(mbp, *len); /* MinCount (only indicates blocking) */ | | 625 | mb_put_uint16le(mbp, *len); /* MinCount (only indicates blocking) */ |
| @@ -664,40 +680,57 @@ smb_smb_readx(struct smb_share *ssp, u_i | | | @@ -664,40 +680,57 @@ smb_smb_readx(struct smb_share *ssp, u_i |
664 | } | | 680 | } |
665 | | | 681 | |
666 | static inline int | | 682 | static inline int |
667 | smb_smb_writex(struct smb_share *ssp, u_int16_t fid, size_t *len, size_t *rresid, | | 683 | smb_smb_writex(struct smb_share *ssp, u_int16_t fid, size_t *len, size_t *rresid, |
668 | struct uio *uio, struct smb_cred *scred) | | 684 | struct uio *uio, struct smb_cred *scred) |
669 | { | | 685 | { |
670 | struct smb_rq *rqp; | | 686 | struct smb_rq *rqp; |
671 | struct mbchain *mbp; | | 687 | struct mbchain *mbp; |
672 | struct mdchain *mdp; | | 688 | struct mdchain *mdp; |
673 | int error; | | 689 | int error; |
674 | u_int8_t wc; | | 690 | u_int8_t wc; |
675 | u_int16_t resid; | | 691 | u_int16_t resid; |
676 | | | 692 | |
| | | 693 | if (!(SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_FILES) && |
| | | 694 | uio->uio_offset >= (1LL << 32)) { |
| | | 695 | /* Cannot write at/beyond 4G */ |
| | | 696 | return (EFBIG); |
| | | 697 | } |
| | | 698 | |
| | | 699 | if (SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_WRITEX) { |
| | | 700 | *len = min(SSTOVC(ssp)->vc_wxmax, *len); |
| | | 701 | } else { |
| | | 702 | size_t blksz; |
| | | 703 | |
| | | 704 | blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 64; |
| | | 705 | if (blksz > 0xffff) |
| | | 706 | blksz = 0xffff; |
| | | 707 | |
| | | 708 | *len = min(blksz, *len); |
| | | 709 | } |
| | | 710 | |
677 | error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp); | | 711 | error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp); |
678 | if (error) | | 712 | if (error != 0) |
679 | return (error); | | 713 | return (error); |
680 | smb_rq_getrequest(rqp, &mbp); | | 714 | smb_rq_getrequest(rqp, &mbp); |
681 | smb_rq_wstart(rqp); | | 715 | smb_rq_wstart(rqp); |
682 | mb_put_uint8(mbp, 0xff); /* no secondary command */ | | 716 | mb_put_uint8(mbp, 0xff); /* no secondary command */ |
683 | mb_put_uint8(mbp, 0); /* MBZ */ | | 717 | mb_put_uint8(mbp, 0); /* MBZ */ |
684 | mb_put_uint16le(mbp, 0); /* offset to secondary */ | | 718 | mb_put_uint16le(mbp, 0); /* offset to secondary */ |
685 | mb_put_mem(mbp, (void *)&fid, sizeof(fid), MB_MSYSTEM); | | 719 | mb_put_mem(mbp, (void *)&fid, sizeof(fid), MB_MSYSTEM); |
686 | mb_put_uint32le(mbp, uio->uio_offset); | | 720 | mb_put_uint32le(mbp, uio->uio_offset); |
687 | mb_put_uint32le(mbp, 0); /* MBZ (timeout) */ | | 721 | mb_put_uint32le(mbp, 0); /* MBZ (timeout) */ |
688 | mb_put_uint16le(mbp, 0); /* !write-thru */ | | 722 | mb_put_uint16le(mbp, 0); /* !write-thru */ |
689 | mb_put_uint16le(mbp, 0); | | 723 | mb_put_uint16le(mbp, 0); |
690 | *len = min(SSTOVC(ssp)->vc_wxmax, *len); | | | |
691 | mb_put_uint16le(mbp, *len >> 16); | | 724 | mb_put_uint16le(mbp, *len >> 16); |
692 | mb_put_uint16le(mbp, *len); | | 725 | mb_put_uint16le(mbp, *len); |
693 | mb_put_uint16le(mbp, 64); /* data offset from header start */ | | 726 | mb_put_uint16le(mbp, 64); /* data offset from header start */ |
694 | mb_put_uint32le(mbp, uio->uio_offset >> 32); /* OffsetHigh */ | | 727 | mb_put_uint32le(mbp, uio->uio_offset >> 32); /* OffsetHigh */ |
695 | smb_rq_wend(rqp); | | 728 | smb_rq_wend(rqp); |
696 | smb_rq_bstart(rqp); | | 729 | smb_rq_bstart(rqp); |
697 | do { | | 730 | do { |
698 | mb_put_uint8(mbp, 0xee); /* mimic xp pad byte! */ | | 731 | mb_put_uint8(mbp, 0xee); /* mimic xp pad byte! */ |
699 | error = mb_put_uio(mbp, uio, *len); | | 732 | error = mb_put_uio(mbp, uio, *len); |
700 | if (error) | | 733 | if (error) |
701 | break; | | 734 | break; |
702 | smb_rq_bend(rqp); | | 735 | smb_rq_bend(rqp); |
703 | error = smb_rq_simple(rqp); | | 736 | error = smb_rq_simple(rqp); |
| @@ -775,27 +808,28 @@ smb_smb_read(struct smb_share *ssp, u_in | | | @@ -775,27 +808,28 @@ smb_smb_read(struct smb_share *ssp, u_in |
775 | break; | | 808 | break; |
776 | *rresid = resid; | | 809 | *rresid = resid; |
777 | } while(0); | | 810 | } while(0); |
778 | smb_rq_done(rqp); | | 811 | smb_rq_done(rqp); |
779 | return error; | | 812 | return error; |
780 | } | | 813 | } |
781 | | | 814 | |
782 | int | | 815 | int |
783 | smb_read(struct smb_share *ssp, u_int16_t fid, struct uio *uio, | | 816 | smb_read(struct smb_share *ssp, u_int16_t fid, struct uio *uio, |
784 | struct smb_cred *scred) | | 817 | struct smb_cred *scred) |
785 | { | | 818 | { |
786 | size_t tsize, len, resid; | | 819 | size_t tsize, len, resid; |
787 | int error = 0; | | 820 | int error = 0; |
788 | int rx = (SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_READX); | | 821 | bool rx = (SMB_CAPS(SSTOVC(ssp)) & |
| | | 822 | (SMB_CAP_LARGE_FILES|SMB_CAP_LARGE_READX)) != 0; |
789 | | | 823 | |
790 | resid = 0; /* XXX gcc */ | | 824 | resid = 0; /* XXX gcc */ |
791 | | | 825 | |
792 | tsize = uio->uio_resid; | | 826 | tsize = uio->uio_resid; |
793 | while (tsize > 0) { | | 827 | while (tsize > 0) { |
794 | len = tsize; | | 828 | len = tsize; |
795 | if (rx) | | 829 | if (rx) |
796 | error = smb_smb_readx(ssp, fid, &len, &resid, uio, scred); | | 830 | error = smb_smb_readx(ssp, fid, &len, &resid, uio, scred); |
797 | else | | 831 | else |
798 | error = smb_smb_read(ssp, fid, &len, &resid, uio, scred); | | 832 | error = smb_smb_read(ssp, fid, &len, &resid, uio, scred); |
799 | if (error) | | 833 | if (error) |
800 | break; | | 834 | break; |
801 | tsize -= resid; | | 835 | tsize -= resid; |
| @@ -856,38 +890,39 @@ smb_smb_write(struct smb_share *ssp, u_i | | | @@ -856,38 +890,39 @@ smb_smb_write(struct smb_share *ssp, u_i |
856 | md_get_uint16le(mdp, &resid); | | 890 | md_get_uint16le(mdp, &resid); |
857 | *rresid = resid; | | 891 | *rresid = resid; |
858 | } while(0); | | 892 | } while(0); |
859 | smb_rq_done(rqp); | | 893 | smb_rq_done(rqp); |
860 | return error; | | 894 | return error; |
861 | } | | 895 | } |
862 | | | 896 | |
863 | int | | 897 | int |
864 | smb_write(struct smb_share *ssp, u_int16_t fid, struct uio *uio, | | 898 | smb_write(struct smb_share *ssp, u_int16_t fid, struct uio *uio, |
865 | struct smb_cred *scred) | | 899 | struct smb_cred *scred) |
866 | { | | 900 | { |
867 | int error = 0; | | 901 | int error = 0; |
868 | size_t len, tsize, resid; | | 902 | size_t len, tsize, resid; |
869 | int wx = (SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_WRITEX); | | 903 | bool wx = (SMB_CAPS(SSTOVC(ssp)) & |
| | | 904 | (SMB_CAP_LARGE_FILES|SMB_CAP_LARGE_WRITEX)) != 0; |
870 | | | 905 | |
871 | resid = 0; /* XXX gcc */ | | 906 | resid = 0; /* XXX gcc */ |
872 | | | 907 | |
873 | tsize = uio->uio_resid; | | 908 | tsize = uio->uio_resid; |
874 | while (tsize > 0) { | | 909 | while (tsize > 0) { |
875 | len = tsize; | | 910 | len = tsize; |
876 | if (wx) | | 911 | if (wx) |
877 | error = smb_smb_writex(ssp, fid, &len, &resid, uio, scred); | | 912 | error = smb_smb_writex(ssp, fid, &len, &resid, uio, scred); |
878 | else | | 913 | else |
879 | error = smb_smb_write(ssp, fid, &len, &resid, uio, scred); | | 914 | error = smb_smb_write(ssp, fid, &len, &resid, uio, scred); |
880 | if (error) | | 915 | if (error != 0) |
881 | break; | | 916 | break; |
882 | if (resid < len) { | | 917 | if (resid < len) { |
883 | error = EIO; | | 918 | error = EIO; |
884 | break; | | 919 | break; |
885 | } | | 920 | } |
886 | tsize -= resid; | | 921 | tsize -= resid; |
887 | } | | 922 | } |
888 | return error; | | 923 | return error; |
889 | } | | 924 | } |
890 | | | 925 | |
891 | #if 0 | | 926 | #if 0 |
892 | int | | 927 | int |
893 | smb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred) | | 928 | smb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred) |