FreeBSD/Linux Kernel Cross Reference
sys/netsmb/smb_subr.c
1 /*
2 * Copyright (c) 2000-2001 Boris Popov
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: releng/5.1/sys/netsmb/smb_subr.c 114983 2003-05-13 20:36:02Z jhb $
33 */
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/endian.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/proc.h>
40 #include <sys/lock.h>
41 #include <sys/sysctl.h>
42 #include <sys/socket.h>
43 #include <sys/signalvar.h>
44 #include <sys/mbuf.h>
45
46 #include <sys/iconv.h>
47
48 #include <netsmb/smb.h>
49 #include <netsmb/smb_conn.h>
50 #include <netsmb/smb_rq.h>
51 #include <netsmb/smb_subr.h>
52
53 MALLOC_DEFINE(M_SMBDATA, "SMBDATA", "Misc netsmb data");
54 MALLOC_DEFINE(M_SMBSTR, "SMBSTR", "netsmb string data");
55 MALLOC_DEFINE(M_SMBTEMP, "SMBTEMP", "Temp netsmb data");
56
57 smb_unichar smb_unieol = 0;
58
59 void
60 smb_makescred(struct smb_cred *scred, struct thread *td, struct ucred *cred)
61 {
62 if (td) {
63 scred->scr_td = td;
64 scred->scr_cred = cred ? cred : td->td_ucred;
65 } else {
66 scred->scr_td = NULL;
67 scred->scr_cred = cred ? cred : NULL;
68 }
69 }
70
71 int
72 smb_td_intr(struct thread *td)
73 {
74 struct proc *p;
75 sigset_t tmpset;
76
77 if (td == NULL)
78 return 0;
79
80 p = td->td_proc;
81 PROC_LOCK(p);
82 tmpset = p->p_siglist;
83 SIGSETOR(tmpset, td->td_siglist);
84 SIGSETNAND(tmpset, td->td_sigmask);
85 mtx_lock(&p->p_sigacts->ps_mtx);
86 SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore);
87 mtx_unlock(&p->p_sigacts->ps_mtx);
88 if (SIGNOTEMPTY(td->td_siglist) && SMB_SIGMASK(tmpset)) {
89 PROC_UNLOCK(p);
90 return EINTR;
91 }
92 PROC_UNLOCK(p);
93 return 0;
94 }
95
96 char *
97 smb_strdup(const char *s)
98 {
99 char *p;
100 int len;
101
102 len = s ? strlen(s) + 1 : 1;
103 p = malloc(len, M_SMBSTR, M_WAITOK);
104 if (s)
105 bcopy(s, p, len);
106 else
107 *p = 0;
108 return p;
109 }
110
111 /*
112 * duplicate string from a user space.
113 */
114 char *
115 smb_strdupin(char *s, int maxlen)
116 {
117 char *p, bt;
118 int len = 0;
119
120 for (p = s; ;p++) {
121 if (copyin(p, &bt, 1))
122 return NULL;
123 len++;
124 if (maxlen && len > maxlen)
125 return NULL;
126 if (bt == 0)
127 break;
128 }
129 p = malloc(len, M_SMBSTR, M_WAITOK);
130 copyin(s, p, len);
131 return p;
132 }
133
134 /*
135 * duplicate memory block from a user space.
136 */
137 void *
138 smb_memdupin(void *umem, int len)
139 {
140 char *p;
141
142 if (len > 8 * 1024)
143 return NULL;
144 p = malloc(len, M_SMBSTR, M_WAITOK);
145 if (copyin(umem, p, len) == 0)
146 return p;
147 free(p, M_SMBSTR);
148 return NULL;
149 }
150
151 /*
152 * duplicate memory block in the kernel space.
153 */
154 void *
155 smb_memdup(const void *umem, int len)
156 {
157 char *p;
158
159 if (len > 8 * 1024)
160 return NULL;
161 p = malloc(len, M_SMBSTR, M_WAITOK);
162 if (p == NULL)
163 return NULL;
164 bcopy(umem, p, len);
165 return p;
166 }
167
168 void
169 smb_strfree(char *s)
170 {
171 free(s, M_SMBSTR);
172 }
173
174 void
175 smb_memfree(void *s)
176 {
177 free(s, M_SMBSTR);
178 }
179
180 void *
181 smb_zmalloc(unsigned long size, struct malloc_type *type, int flags)
182 {
183
184 return malloc(size, type, flags | M_ZERO);
185 }
186
187 void
188 smb_strtouni(u_int16_t *dst, const char *src)
189 {
190 while (*src) {
191 *dst++ = htole16(*src++);
192 }
193 *dst = 0;
194 }
195
196 #ifdef SMB_SOCKETDATA_DEBUG
197 void
198 m_dumpm(struct mbuf *m) {
199 char *p;
200 int len;
201 printf("d=");
202 while(m) {
203 p=mtod(m,char *);
204 len=m->m_len;
205 printf("(%d)",len);
206 while(len--){
207 printf("%02x ",((int)*(p++)) & 0xff);
208 }
209 m=m->m_next;
210 };
211 printf("\n");
212 }
213 #endif
214
215 int
216 smb_maperror(int eclass, int eno)
217 {
218 if (eclass == 0 && eno == 0)
219 return 0;
220 switch (eclass) {
221 case ERRDOS:
222 switch (eno) {
223 case ERRbadfunc:
224 case ERRbadmcb:
225 case ERRbadenv:
226 case ERRbadformat:
227 case ERRrmuns:
228 return EINVAL;
229 case ERRbadfile:
230 case ERRbadpath:
231 case ERRremcd:
232 case 66: /* nt returns it when share not available */
233 case 67: /* observed from nt4sp6 when sharename wrong */
234 return ENOENT;
235 case ERRnofids:
236 return EMFILE;
237 case ERRnoaccess:
238 case ERRbadshare:
239 return EACCES;
240 case ERRbadfid:
241 return EBADF;
242 case ERRnomem:
243 return ENOMEM; /* actually remote no mem... */
244 case ERRbadmem:
245 return EFAULT;
246 case ERRbadaccess:
247 return EACCES;
248 case ERRbaddata:
249 return E2BIG;
250 case ERRbaddrive:
251 case ERRnotready: /* nt */
252 return ENXIO;
253 case ERRdiffdevice:
254 return EXDEV;
255 case ERRnofiles:
256 return 0; /* eeof ? */
257 return ETXTBSY;
258 case ERRlock:
259 return EDEADLK;
260 case ERRfilexists:
261 return EEXIST;
262 case 123: /* dunno what is it, but samba maps as noent */
263 return ENOENT;
264 case 145: /* samba */
265 return ENOTEMPTY;
266 case 183:
267 return EEXIST;
268 case ERRquota:
269 return EDQUOT;
270 }
271 break;
272 case ERRSRV:
273 switch (eno) {
274 case ERRerror:
275 return EINVAL;
276 case ERRbadpw:
277 case ERRpasswordExpired:
278 return EAUTH;
279 case ERRaccess:
280 return EACCES;
281 case ERRinvnid:
282 return ENETRESET;
283 case ERRinvnetname:
284 SMBERROR("NetBIOS name is invalid\n");
285 return EAUTH;
286 case 3: /* reserved and returned */
287 return EIO;
288 case ERRaccountExpired:
289 case ERRbadClient:
290 case ERRbadLogonTime:
291 return EPERM;
292 case ERRnosupport:
293 return EBADRPC;
294 }
295 break;
296 case ERRHRD:
297 switch (eno) {
298 case ERRnowrite:
299 return EROFS;
300 case ERRbadunit:
301 return ENODEV;
302 case ERRnotready:
303 case ERRbadcmd:
304 case ERRdata:
305 return EIO;
306 case ERRbadreq:
307 return EBADRPC;
308 case ERRbadshare:
309 return ETXTBSY;
310 case ERRlock:
311 return EDEADLK;
312 }
313 break;
314 }
315 SMBERROR("Unmapped error %d:%d\n", eclass, eno);
316 return EBADRPC;
317 }
318
319 static int
320 smb_copy_iconv(struct mbchain *mbp, c_caddr_t src, caddr_t dst, size_t len)
321 {
322 size_t outlen = len;
323
324 return iconv_conv((struct iconv_drv*)mbp->mb_udata, &src, &len, &dst, &outlen);
325 }
326
327 int
328 smb_put_dmem(struct mbchain *mbp, struct smb_vc *vcp, const char *src,
329 int size, int caseopt)
330 {
331 struct iconv_drv *dp = vcp->vc_toserver;
332
333 if (size == 0)
334 return 0;
335 if (dp == NULL) {
336 return mb_put_mem(mbp, src, size, MB_MSYSTEM);
337 }
338 mbp->mb_copy = smb_copy_iconv;
339 mbp->mb_udata = dp;
340 return mb_put_mem(mbp, src, size, MB_MCUSTOM);
341 }
342
343 int
344 smb_put_dstring(struct mbchain *mbp, struct smb_vc *vcp, const char *src,
345 int caseopt)
346 {
347 int error;
348
349 error = smb_put_dmem(mbp, vcp, src, strlen(src), caseopt);
350 if (error)
351 return error;
352 return mb_put_uint8(mbp, 0);
353 }
354
355 int
356 smb_put_asunistring(struct smb_rq *rqp, const char *src)
357 {
358 struct mbchain *mbp = &rqp->sr_rq;
359 struct iconv_drv *dp = rqp->sr_vc->vc_toserver;
360 u_char c;
361 int error;
362
363 while (*src) {
364 iconv_convmem(dp, &c, src++, 1);
365 error = mb_put_uint16le(mbp, c);
366 if (error)
367 return error;
368 }
369 return mb_put_uint16le(mbp, 0);
370 }
Cache object: 3afca3be3b3b8a7772fff730910ee5f2
|