Revert "s3: Add sys_statvfs() wrapper support for OpenBSD/FreeBSD/DragonFly."
[Samba.git] / source3 / smbd / error.c
blob6655a6fb082a2368a3781bc36eeb85f880f8f155
1 /*
2 Unix SMB/CIFS implementation.
3 error packet handling
4 Copyright (C) Andrew Tridgell 1992-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "smbd/smbd.h"
22 #include "smbd/globals.h"
24 /* From lib/error.c */
25 extern struct unix_error_map unix_dos_nt_errmap[];
27 bool use_nt_status(void)
29 return lp_nt_status_support() && (global_client_caps & CAP_STATUS32);
32 /****************************************************************************
33 Create an error packet. Normally called using the ERROR() macro.
35 Setting eclass and ecode to zero and status to a valid NT error will
36 reply with an NT error if the client supports CAP_STATUS32, otherwise
37 it maps to and returns a DOS error if the client doesn't support CAP_STATUS32.
38 This is the normal mode of calling this function via reply_nterror(req, status).
40 Setting eclass and ecode to non-zero and status to NT_STATUS_OK (0) will map
41 from a DOS error to an NT error and reply with an NT error if the client
42 supports CAP_STATUS32, otherwise it replies with the given DOS error.
43 This mode is currently not used in the server.
45 Setting both eclass, ecode and status to non-zero values allows a non-default
46 mapping from NT error codes to DOS error codes, and will return one or the
47 other depending on the client supporting CAP_STATUS32 or not. This is the
48 path taken by calling reply_botherror(req, eclass, ecode, status);
50 Setting status to NT_STATUS_DOS(eclass, ecode) forces DOS errors even if the
51 client supports CAP_STATUS32. This is the path taken to force a DOS error
52 reply by calling reply_force_doserror(req, eclass, ecode).
54 Setting status only and eclass to -1 forces NT errors even if the client
55 doesn't support CAP_STATUS32. This mode is currently never used in the
56 server.
57 ****************************************************************************/
59 void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
61 bool force_nt_status = False;
62 bool force_dos_status = False;
64 if (eclass == (uint8)-1) {
65 force_nt_status = True;
66 } else if (NT_STATUS_IS_DOS(ntstatus)) {
67 force_dos_status = True;
70 if (force_nt_status || (!force_dos_status && lp_nt_status_support() && (global_client_caps & CAP_STATUS32))) {
71 /* We're returning an NT error. */
72 if (NT_STATUS_V(ntstatus) == 0 && eclass) {
73 ntstatus = dos_to_ntstatus(eclass, ecode);
75 SIVAL(outbuf,smb_rcls,NT_STATUS_V(ntstatus));
76 SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES);
77 DEBUG(3,("error packet at %s(%d) cmd=%d (%s) %s\n",
78 file, line,
79 (int)CVAL(outbuf,smb_com),
80 smb_fn_name(CVAL(outbuf,smb_com)),
81 nt_errstr(ntstatus)));
82 } else {
83 /* We're returning a DOS error only. */
84 if (NT_STATUS_IS_DOS(ntstatus)) {
85 eclass = NT_STATUS_DOS_CLASS(ntstatus);
86 ecode = NT_STATUS_DOS_CODE(ntstatus);
87 } else if (eclass == 0 && NT_STATUS_V(ntstatus)) {
88 ntstatus_to_dos(ntstatus, &eclass, &ecode);
91 SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)&~FLAGS2_32_BIT_ERROR_CODES);
92 SSVAL(outbuf,smb_rcls,eclass);
93 SSVAL(outbuf,smb_err,ecode);
95 DEBUG(3,("error packet at %s(%d) cmd=%d (%s) eclass=%d ecode=%d\n",
96 file, line,
97 (int)CVAL(outbuf,smb_com),
98 smb_fn_name(CVAL(outbuf,smb_com)),
99 eclass,
100 ecode));
104 int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
106 int outsize = srv_set_message(outbuf,0,0,True);
107 error_packet_set(outbuf, eclass, ecode, ntstatus, line, file);
108 return outsize;
111 void reply_nt_error(struct smb_request *req, NTSTATUS ntstatus,
112 int line, const char *file)
114 TALLOC_FREE(req->outbuf);
115 reply_outbuf(req, 0, 0);
116 error_packet_set((char *)req->outbuf, 0, 0, ntstatus, line, file);
119 /****************************************************************************
120 Forces a DOS error on the wire.
121 ****************************************************************************/
123 void reply_force_dos_error(struct smb_request *req, uint8 eclass, uint32 ecode,
124 int line, const char *file)
126 TALLOC_FREE(req->outbuf);
127 reply_outbuf(req, 0, 0);
128 error_packet_set((char *)req->outbuf,
129 eclass, ecode,
130 NT_STATUS_DOS(eclass, ecode),
131 line,
132 file);
135 void reply_both_error(struct smb_request *req, uint8 eclass, uint32 ecode,
136 NTSTATUS status, int line, const char *file)
138 TALLOC_FREE(req->outbuf);
139 reply_outbuf(req, 0, 0);
140 error_packet_set((char *)req->outbuf, eclass, ecode, status,
141 line, file);
144 void reply_openerror(struct smb_request *req, NTSTATUS status)
146 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
148 * We hit an existing file, and if we're returning DOS
149 * error codes OBJECT_NAME_COLLISION would map to
150 * ERRDOS/183, we need to return ERRDOS/80, see bug
151 * 4852.
153 reply_botherror(req, NT_STATUS_OBJECT_NAME_COLLISION,
154 ERRDOS, ERRfilexists);
155 } else if (NT_STATUS_EQUAL(status, NT_STATUS_TOO_MANY_OPENED_FILES)) {
156 /* EMFILE always seems to be returned as a DOS error.
157 * See bug 6837. NOTE this forces a DOS error on the wire
158 * even though it's calling reply_nterror(). */
159 reply_force_doserror(req, ERRDOS, ERRnofids);
160 } else {
161 reply_nterror(req, status);