Home | History | Annotate | Download | only in smbsrv
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"@(#)smb_common_door_decode.c	1.2	08/08/07 SMI"
     27 
     28 /*
     29  * Provides encode/decode routines for all door servers/clients.
     30  */
     31 
     32 #ifdef _KERNEL
     33 #include <sys/types.h>
     34 #include <sys/sunddi.h>
     35 #else
     36 #include <string.h>
     37 #endif
     38 #include <sys/errno.h>
     39 #ifndef _KERNEL
     40 #include <errno.h>
     41 #endif
     42 
     43 #include <smbsrv/alloc.h>
     44 #include <smbsrv/smb_common_door.h>
     45 #include <smbsrv/wintypes.h>
     46 
     47 
     48 smb_dr_ctx_t *
     49 smb_dr_decode_start(char *ptr, int size)
     50 {
     51 	smb_dr_ctx_t *ctx = MEM_MALLOC("CommonDoor", sizeof (smb_dr_ctx_t));
     52 	if (ctx) {
     53 		ctx->start_ptr = ctx->ptr = ptr;
     54 		ctx->end_ptr = ptr + size;
     55 		ctx->status = 0;
     56 	}
     57 	return (ctx);
     58 }
     59 
     60 int
     61 smb_dr_decode_finish(smb_dr_ctx_t *ctx)
     62 {
     63 	int status = ctx->status;
     64 	if (status == 0 && ctx->ptr != ctx->end_ptr) {
     65 		status = ENOTEMPTY;
     66 	}
     67 	MEM_FREE("CommonDoor", ctx);
     68 	return (status);
     69 }
     70 
     71 smb_dr_ctx_t *
     72 smb_dr_encode_start(char *ptr, int size)
     73 {
     74 	smb_dr_ctx_t *ctx = MEM_MALLOC("CommonDoor",  sizeof (smb_dr_ctx_t));
     75 	if (ctx) {
     76 		ctx->start_ptr = ctx->ptr = ptr;
     77 		ctx->end_ptr = ptr + size;
     78 		ctx->status = 0;
     79 	}
     80 	return (ctx);
     81 }
     82 
     83 int
     84 smb_dr_encode_finish(smb_dr_ctx_t *ctx, unsigned int *used)
     85 {
     86 	int status = ctx->status;
     87 	if (status == 0) {
     88 		if (ctx->ptr < ctx->end_ptr) {
     89 			/*LINTED E_PTRDIFF_OVERFLOW*/
     90 			*used = ctx->ptr - ctx->start_ptr;
     91 		}
     92 		else
     93 			status = ENOSPC;
     94 	}
     95 
     96 	MEM_FREE("CommonDoor", ctx);
     97 	return (status);
     98 }
     99 
    100 DWORD
    101 smb_dr_get_dword(smb_dr_ctx_t *ctx)
    102 {
    103 	DWORD num = 0;
    104 	if (ctx->status == 0) {
    105 		if (ctx->ptr + sizeof (DWORD) <= ctx->end_ptr) {
    106 			(void) memcpy(&num, ctx->ptr, sizeof (DWORD));
    107 			ctx->ptr += sizeof (DWORD);
    108 		}
    109 		else
    110 			ctx->status = ENOSPC;
    111 	}
    112 	return (num);
    113 }
    114 
    115 int32_t
    116 smb_dr_get_int32(smb_dr_ctx_t *ctx)
    117 {
    118 	int32_t num = 0;
    119 	if (ctx->status == 0) {
    120 		if (ctx->ptr + sizeof (int32_t) <= ctx->end_ptr) {
    121 			(void) memcpy(&num, ctx->ptr, sizeof (int32_t));
    122 			ctx->ptr += sizeof (int32_t);
    123 		}
    124 		else
    125 			ctx->status = ENOSPC;
    126 	}
    127 	return (num);
    128 }
    129 
    130 uint32_t
    131 smb_dr_get_uint32(smb_dr_ctx_t *ctx)
    132 {
    133 	return ((uint32_t)smb_dr_get_int32(ctx));
    134 }
    135 
    136 char *
    137 smb_dr_get_string(smb_dr_ctx_t *ctx)
    138 {
    139 	char *buf = NULL;
    140 	int len = smb_dr_get_int32(ctx);
    141 
    142 	if (ctx->status == 0) {
    143 		if (len == -1)
    144 			return (buf);
    145 
    146 		if (ctx->ptr + len <= ctx->end_ptr) {
    147 			buf = MEM_MALLOC("CommonDoor", len +1);
    148 			if (buf) {
    149 				if (len == 0)
    150 					(void) strcpy(buf, "");
    151 				else {
    152 					(void) memcpy(buf, ctx->ptr, len);
    153 					ctx->ptr += len;
    154 					*(buf + len) = '\0';
    155 				}
    156 			}
    157 			else
    158 #ifndef _KERNEL
    159 				ctx->status = errno;
    160 #else
    161 				ctx->status = ENOMEM;
    162 #endif
    163 		}
    164 		else
    165 			ctx->status = ENOSPC;
    166 	}
    167 	return (buf);
    168 }
    169 
    170 void
    171 smb_dr_put_dword(smb_dr_ctx_t *ctx, DWORD num)
    172 {
    173 	if (ctx->status == 0) {
    174 		if (ctx->ptr + sizeof (DWORD) <= ctx->end_ptr) {
    175 			(void) memcpy(ctx->ptr, &num, sizeof (DWORD));
    176 			ctx->ptr += sizeof (DWORD);
    177 		} else
    178 			ctx->status = ENOSPC;
    179 	}
    180 }
    181 
    182 void
    183 smb_dr_put_int32(smb_dr_ctx_t *ctx, int32_t num)
    184 {
    185 	if (ctx->status == 0) {
    186 		if (ctx->ptr + sizeof (int32_t) <= ctx->end_ptr) {
    187 			(void) memcpy(ctx->ptr, &num, sizeof (int32_t));
    188 			ctx->ptr += sizeof (int32_t);
    189 		} else
    190 			ctx->status = ENOSPC;
    191 	}
    192 }
    193 
    194 void
    195 smb_dr_put_uint32(smb_dr_ctx_t *ctx, uint32_t num)
    196 {
    197 	smb_dr_put_int32(ctx, (int32_t)num);
    198 }
    199 
    200 void
    201 smb_dr_put_string(smb_dr_ctx_t *ctx, const char *buf)
    202 {
    203 	int len;
    204 
    205 	if (!buf)
    206 		len = -1;
    207 	else
    208 		len = strlen(buf);
    209 
    210 	if (ctx->status == 0) {
    211 		smb_dr_put_int32(ctx, len);
    212 		if (len <= 0)
    213 			return;
    214 
    215 		if (ctx->ptr + len <= ctx->end_ptr) {
    216 			(void) memcpy(ctx->ptr, buf, len);
    217 			ctx->ptr += len;
    218 		}
    219 		else
    220 			ctx->status = ENOSPC;
    221 	}
    222 }
    223 
    224 void
    225 smb_dr_free_string(char *buf)
    226 {
    227 	if (buf)
    228 		MEM_FREE("CommonDoor", buf);
    229 }
    230 
    231 int64_t
    232 smb_dr_get_int64(smb_dr_ctx_t *ctx)
    233 {
    234 	int64_t num = 0;
    235 	if (ctx->status == 0) {
    236 		if (ctx->ptr + sizeof (int64_t) <= ctx->end_ptr) {
    237 			(void) memcpy(&num, ctx->ptr, sizeof (int64_t));
    238 			ctx->ptr += sizeof (int64_t);
    239 		}
    240 		else
    241 			ctx->status = ENOSPC;
    242 	}
    243 	return (num);
    244 }
    245 
    246 uint64_t
    247 smb_dr_get_uint64(smb_dr_ctx_t *ctx)
    248 {
    249 	return ((uint64_t)smb_dr_get_int64(ctx));
    250 }
    251 
    252 
    253 void
    254 smb_dr_put_int64(smb_dr_ctx_t *ctx, int64_t num)
    255 {
    256 	if (ctx->status == 0) {
    257 		if (ctx->ptr + sizeof (int64_t) <= ctx->end_ptr) {
    258 			(void) memcpy(ctx->ptr, &num, sizeof (int64_t));
    259 			ctx->ptr += sizeof (int64_t);
    260 		} else
    261 			ctx->status = ENOSPC;
    262 	}
    263 }
    264 
    265 void
    266 smb_dr_put_uint64(smb_dr_ctx_t *ctx, uint64_t num)
    267 {
    268 	smb_dr_put_int64(ctx, (int64_t)num);
    269 }
    270 
    271 void
    272 smb_dr_put_short(smb_dr_ctx_t *ctx, short num)
    273 {
    274 	if (ctx->status == 0) {
    275 		if (ctx->ptr + sizeof (short) <= ctx->end_ptr) {
    276 			(void) memcpy(ctx->ptr, &num, sizeof (short));
    277 			ctx->ptr += sizeof (short);
    278 		} else
    279 			ctx->status = ENOSPC;
    280 	}
    281 }
    282 
    283 short
    284 smb_dr_get_short(smb_dr_ctx_t *ctx)
    285 {
    286 	short num = 0;
    287 	if (ctx->status == 0) {
    288 		if (ctx->ptr + sizeof (short) <= ctx->end_ptr) {
    289 			(void) memcpy(&num, ctx->ptr, sizeof (short));
    290 			ctx->ptr += sizeof (short);
    291 		}
    292 		else
    293 			ctx->status = ENOSPC;
    294 	}
    295 	return (num);
    296 }
    297 
    298 void
    299 smb_dr_put_ushort(smb_dr_ctx_t *ctx, unsigned short num)
    300 {
    301 	smb_dr_put_short(ctx, (short)num);
    302 }
    303 
    304 unsigned short
    305 smb_dr_get_ushort(smb_dr_ctx_t *ctx)
    306 {
    307 	return ((unsigned short)smb_dr_get_short(ctx));
    308 }
    309 
    310 void
    311 smb_dr_put_word(smb_dr_ctx_t *ctx, WORD num)
    312 {
    313 	smb_dr_put_ushort(ctx, num);
    314 }
    315 
    316 WORD
    317 smb_dr_get_word(smb_dr_ctx_t *ctx)
    318 {
    319 	return (smb_dr_get_ushort(ctx));
    320 }
    321 
    322 void
    323 smb_dr_put_BYTE(smb_dr_ctx_t *ctx, BYTE byte)
    324 {
    325 	if (ctx->status == 0) {
    326 		if (ctx->ptr + sizeof (BYTE) <= ctx->end_ptr) {
    327 			(void) memcpy(ctx->ptr, &byte, sizeof (BYTE));
    328 			ctx->ptr += sizeof (BYTE);
    329 		} else
    330 			ctx->status = ENOSPC;
    331 	}
    332 }
    333 
    334 BYTE
    335 smb_dr_get_BYTE(smb_dr_ctx_t *ctx)
    336 {
    337 	BYTE byte = 0;
    338 	if (ctx->status == 0) {
    339 		if (ctx->ptr + sizeof (BYTE) <= ctx->end_ptr) {
    340 			(void) memcpy(&byte, ctx->ptr, sizeof (BYTE));
    341 			ctx->ptr += sizeof (BYTE);
    342 		}
    343 		else
    344 			ctx->status = ENOSPC;
    345 	}
    346 	return (byte);
    347 }
    348 
    349 void
    350 smb_dr_put_buf(smb_dr_ctx_t *ctx, unsigned char *start, int len)
    351 {
    352 	smb_dr_put_int32(ctx, len);
    353 	if (ctx->status == 0) {
    354 		if (ctx->ptr + len <= ctx->end_ptr) {
    355 			(void) memcpy(ctx->ptr, start, len);
    356 			ctx->ptr += len;
    357 		} else
    358 			ctx->status = ENOSPC;
    359 	}
    360 }
    361 
    362 int
    363 smb_dr_get_buf(smb_dr_ctx_t *ctx, unsigned char *buf, int bufsize)
    364 {
    365 	int len = -1;
    366 
    367 	if (!buf)
    368 		return (-1);
    369 
    370 	len = smb_dr_get_int32(ctx);
    371 	if (ctx->status == 0) {
    372 		if (bufsize < len) {
    373 			ctx->status = ENOSPC;
    374 			return (-2);
    375 		}
    376 
    377 		if (ctx->ptr + len <= ctx->end_ptr) {
    378 			(void) memcpy(buf, ctx->ptr, len);
    379 			ctx->ptr += len;
    380 		} else {
    381 			ctx->status = ENOSPC;
    382 			return (-3);
    383 		}
    384 	}
    385 
    386 	return (len);
    387 }
    388