14bff34e3Sthurlow /* 2*430b4c46SGordon Ross * Copyright 2011 Nexenta Systems, Inc. All rights reserved. 34bff34e3Sthurlow * Copyright (c) 2000, Boris Popov 44bff34e3Sthurlow * All rights reserved. 54bff34e3Sthurlow * 64bff34e3Sthurlow * Redistribution and use in source and binary forms, with or without 74bff34e3Sthurlow * modification, are permitted provided that the following conditions 84bff34e3Sthurlow * are met: 94bff34e3Sthurlow * 1. Redistributions of source code must retain the above copyright 104bff34e3Sthurlow * notice, this list of conditions and the following disclaimer. 114bff34e3Sthurlow * 2. Redistributions in binary form must reproduce the above copyright 124bff34e3Sthurlow * notice, this list of conditions and the following disclaimer in the 134bff34e3Sthurlow * documentation and/or other materials provided with the distribution. 144bff34e3Sthurlow * 3. All advertising materials mentioning features or use of this software 154bff34e3Sthurlow * must display the following acknowledgement: 164bff34e3Sthurlow * This product includes software developed by Boris Popov. 174bff34e3Sthurlow * 4. Neither the name of the author nor the names of any co-contributors 184bff34e3Sthurlow * may be used to endorse or promote products derived from this software 194bff34e3Sthurlow * without specific prior written permission. 204bff34e3Sthurlow * 214bff34e3Sthurlow * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 224bff34e3Sthurlow * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 234bff34e3Sthurlow * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 244bff34e3Sthurlow * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 254bff34e3Sthurlow * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 264bff34e3Sthurlow * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 274bff34e3Sthurlow * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 284bff34e3Sthurlow * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 294bff34e3Sthurlow * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 304bff34e3Sthurlow * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 314bff34e3Sthurlow * SUCH DAMAGE. 324bff34e3Sthurlow * 334bff34e3Sthurlow * $Id: rap.c,v 1.5 2004/12/13 00:25:23 lindak Exp $ 344bff34e3Sthurlow * 354bff34e3Sthurlow * This is very simple implementation of RAP protocol. 364bff34e3Sthurlow */ 374bff34e3Sthurlow 384bff34e3Sthurlow #include <sys/param.h> 394bff34e3Sthurlow #include <sys/errno.h> 404bff34e3Sthurlow #include <sys/stat.h> 414bff34e3Sthurlow #include <sys/isa_defs.h> 424bff34e3Sthurlow 434bff34e3Sthurlow #include <ctype.h> 444bff34e3Sthurlow #include <stdio.h> 454bff34e3Sthurlow #include <unistd.h> 464bff34e3Sthurlow #include <strings.h> 474bff34e3Sthurlow #include <stdlib.h> 484bff34e3Sthurlow #include <libintl.h> 494bff34e3Sthurlow #include <sysexits.h> 504bff34e3Sthurlow 514bff34e3Sthurlow #include <netsmb/mchain.h> 524bff34e3Sthurlow #include <netsmb/smb_lib.h> 534bff34e3Sthurlow #include <netsmb/smb_rap.h> 549c9af259SGordon Ross #include "private.h" 554bff34e3Sthurlow 564bff34e3Sthurlow static int 574bff34e3Sthurlow smb_rap_parserqparam(const char *s, char **next, int *rlen) 584bff34e3Sthurlow { 594bff34e3Sthurlow char *np; 604bff34e3Sthurlow int len; 614bff34e3Sthurlow 624bff34e3Sthurlow switch (*s++) { 634bff34e3Sthurlow case 'L': 644bff34e3Sthurlow case 'T': 654bff34e3Sthurlow case 'W': 664bff34e3Sthurlow len = 2; 674bff34e3Sthurlow break; 684bff34e3Sthurlow case 'D': 694bff34e3Sthurlow case 'O': 704bff34e3Sthurlow len = 4; 714bff34e3Sthurlow break; 724bff34e3Sthurlow case 'b': 734bff34e3Sthurlow case 'F': 744bff34e3Sthurlow len = 1; 754bff34e3Sthurlow break; 764bff34e3Sthurlow case 'r': 774bff34e3Sthurlow case 's': 784bff34e3Sthurlow len = 0; 794bff34e3Sthurlow break; 804bff34e3Sthurlow default: 814bff34e3Sthurlow return (EINVAL); 824bff34e3Sthurlow } 834bff34e3Sthurlow if (isdigit(*s)) { 844bff34e3Sthurlow len *= strtoul(s, &np, 10); 854bff34e3Sthurlow s = np; 864bff34e3Sthurlow } 874bff34e3Sthurlow *rlen = len; 884bff34e3Sthurlow *(const char **)next = s; 894bff34e3Sthurlow return (0); 904bff34e3Sthurlow } 914bff34e3Sthurlow 924bff34e3Sthurlow static int 934bff34e3Sthurlow smb_rap_parserpparam(const char *s, char **next, int *rlen) 944bff34e3Sthurlow { 954bff34e3Sthurlow char *np; 964bff34e3Sthurlow int len = 0; 974bff34e3Sthurlow 984bff34e3Sthurlow switch (*s++) { 994bff34e3Sthurlow case 'e': 1004bff34e3Sthurlow case 'h': 1014bff34e3Sthurlow len = 2; 1024bff34e3Sthurlow break; 1034bff34e3Sthurlow case 'i': 1044bff34e3Sthurlow len = 4; 1054bff34e3Sthurlow break; 1064bff34e3Sthurlow case 'g': 1074bff34e3Sthurlow len = 1; 1084bff34e3Sthurlow break; 1094bff34e3Sthurlow default: 1104bff34e3Sthurlow return (EINVAL); 1114bff34e3Sthurlow } 1124bff34e3Sthurlow if (isdigit(*s)) { 1134bff34e3Sthurlow len *= strtoul(s, &np, 10); 1144bff34e3Sthurlow s = np; 1154bff34e3Sthurlow } 1164bff34e3Sthurlow *rlen = len; 1174bff34e3Sthurlow *(const char **)next = s; 1184bff34e3Sthurlow return (0); 1194bff34e3Sthurlow } 1204bff34e3Sthurlow 1214bff34e3Sthurlow static int 1224bff34e3Sthurlow smb_rap_parserpdata(const char *s, char **next, int *rlen) 1234bff34e3Sthurlow { 1244bff34e3Sthurlow char *np; 1254bff34e3Sthurlow int len; 1264bff34e3Sthurlow 1274bff34e3Sthurlow switch (*s++) { 1284bff34e3Sthurlow case 'B': 1294bff34e3Sthurlow len = 1; 1304bff34e3Sthurlow break; 1314bff34e3Sthurlow case 'W': 1324bff34e3Sthurlow len = 2; 1334bff34e3Sthurlow break; 1344bff34e3Sthurlow case 'D': 1354bff34e3Sthurlow case 'O': 1364bff34e3Sthurlow case 'z': 1374bff34e3Sthurlow len = 4; 1384bff34e3Sthurlow break; 1394bff34e3Sthurlow default: 1404bff34e3Sthurlow return (EINVAL); 1414bff34e3Sthurlow } 1424bff34e3Sthurlow if (isdigit(*s)) { 1434bff34e3Sthurlow len *= strtoul(s, &np, 10); 1444bff34e3Sthurlow s = np; 1454bff34e3Sthurlow } 1464bff34e3Sthurlow *rlen = len; 1474bff34e3Sthurlow *(const char **)next = s; 1484bff34e3Sthurlow return (0); 1494bff34e3Sthurlow } 1504bff34e3Sthurlow 1514bff34e3Sthurlow static int 1524bff34e3Sthurlow smb_rap_rqparam_z(struct smb_rap *rap, const char *value) 1534bff34e3Sthurlow { 1544bff34e3Sthurlow int len = strlen(value) + 1; 1554bff34e3Sthurlow 1564bff34e3Sthurlow bcopy(value, rap->r_npbuf, len); 1574bff34e3Sthurlow rap->r_npbuf += len; 1584bff34e3Sthurlow rap->r_plen += len; 1594bff34e3Sthurlow return (0); 1604bff34e3Sthurlow } 1614bff34e3Sthurlow 1624bff34e3Sthurlow /* 1634bff34e3Sthurlow * Marshal RAP request parameters. 1644bff34e3Sthurlow * Note: value is in host order. 1654bff34e3Sthurlow */ 1664bff34e3Sthurlow static int 1674bff34e3Sthurlow smb_rap_rqparam(struct smb_rap *rap, char ptype, char plen, int value) 1684bff34e3Sthurlow { 1694bff34e3Sthurlow int len = 0; 1704bff34e3Sthurlow uint_t uv = (uint_t)value; 1719c9af259SGordon Ross uint32_t *lp; 1729c9af259SGordon Ross uint16_t *sp; 1739c9af259SGordon Ross char *p; 1744bff34e3Sthurlow 1754bff34e3Sthurlow switch (ptype) { 1764bff34e3Sthurlow case 'L': 1774bff34e3Sthurlow case 'W': 1784bff34e3Sthurlow /* LINTED */ 1799c9af259SGordon Ross sp = (uint16_t *)rap->r_npbuf; 1809c9af259SGordon Ross *sp = htoles(uv); 1819c9af259SGordon Ross len = sizeof (*sp); 1824bff34e3Sthurlow break; 1834bff34e3Sthurlow case 'D': 1844bff34e3Sthurlow /* LINTED */ 1859c9af259SGordon Ross lp = (uint32_t *)rap->r_npbuf; 1869c9af259SGordon Ross *lp = htolel(uv); 1879c9af259SGordon Ross len = sizeof (*lp); 1884bff34e3Sthurlow break; 1894bff34e3Sthurlow case 'b': 1909c9af259SGordon Ross p = rap->r_npbuf; 1914bff34e3Sthurlow memset(p, uv, plen); 1924bff34e3Sthurlow len = plen; 1934bff34e3Sthurlow default: 1944bff34e3Sthurlow return (EINVAL); 1954bff34e3Sthurlow } 1964bff34e3Sthurlow rap->r_npbuf += len; 1974bff34e3Sthurlow rap->r_plen += len; 1984bff34e3Sthurlow return (0); 1994bff34e3Sthurlow } 2004bff34e3Sthurlow 2014bff34e3Sthurlow int 2024bff34e3Sthurlow smb_rap_create(int fn, const char *param, const char *data, 2034bff34e3Sthurlow struct smb_rap **rapp) 2044bff34e3Sthurlow { 2054bff34e3Sthurlow struct smb_rap *rap; 2064bff34e3Sthurlow char *p; 2074bff34e3Sthurlow int plen = 0, len = 0; 2084bff34e3Sthurlow 2094bff34e3Sthurlow rap = malloc(sizeof (*rap)); 2104bff34e3Sthurlow if (rap == NULL) 2114bff34e3Sthurlow return (ENOMEM); 2124bff34e3Sthurlow bzero(rap, sizeof (*rap)); 2134bff34e3Sthurlow p = rap->r_sparam = rap->r_nparam = strdup(param); 2144bff34e3Sthurlow rap->r_sdata = rap->r_ndata = strdup(data); 2154bff34e3Sthurlow 2164bff34e3Sthurlow /* 2174bff34e3Sthurlow * Calculate length of request parameter block 2184bff34e3Sthurlow */ 2194bff34e3Sthurlow len = 2 + strlen(param) + 1 + strlen(data) + 1; 2204bff34e3Sthurlow while (*p) { 2214bff34e3Sthurlow if (smb_rap_parserqparam(p, &p, &plen) != 0) 2224bff34e3Sthurlow break; 2234bff34e3Sthurlow len += plen; 2244bff34e3Sthurlow } 2254bff34e3Sthurlow rap->r_pbuf = rap->r_npbuf = malloc(len); 22602d09e03SGordon Ross if (rap->r_pbuf == NULL) 22702d09e03SGordon Ross return (ENOMEM); 22802d09e03SGordon Ross (void) smb_rap_rqparam(rap, 'W', 1, fn); 22902d09e03SGordon Ross (void) smb_rap_rqparam_z(rap, rap->r_sparam); 23002d09e03SGordon Ross (void) smb_rap_rqparam_z(rap, rap->r_sdata); 2314bff34e3Sthurlow *rapp = rap; 2324bff34e3Sthurlow return (0); 2334bff34e3Sthurlow } 2344bff34e3Sthurlow 2354bff34e3Sthurlow void 2364bff34e3Sthurlow smb_rap_done(struct smb_rap *rap) 2374bff34e3Sthurlow { 2384bff34e3Sthurlow if (rap->r_sparam) 2394bff34e3Sthurlow free(rap->r_sparam); 2404bff34e3Sthurlow if (rap->r_sdata) 2414bff34e3Sthurlow free(rap->r_sdata); 2424bff34e3Sthurlow if (rap->r_pbuf) 2434bff34e3Sthurlow free(rap->r_pbuf); 2444bff34e3Sthurlow #ifdef NOTYETDEFINED 2454bff34e3Sthurlow if (rap->r_npbuf) 2464bff34e3Sthurlow free(rap->r_npbuf); 2474bff34e3Sthurlow if (rap->r_dbuf) 2484bff34e3Sthurlow free(rap->r_dbuf); 2494bff34e3Sthurlow if (rap->r_rcvbuf) 2504bff34e3Sthurlow free(rap->r_rcvbuf); 2514bff34e3Sthurlow #endif 2524bff34e3Sthurlow free(rap); 2534bff34e3Sthurlow } 2544bff34e3Sthurlow 2554bff34e3Sthurlow int 2564bff34e3Sthurlow smb_rap_setNparam(struct smb_rap *rap, int value) 2574bff34e3Sthurlow { 2584bff34e3Sthurlow char *p = rap->r_nparam; 2594bff34e3Sthurlow char ptype = *p; 2604bff34e3Sthurlow int error, plen; 2614bff34e3Sthurlow 2624bff34e3Sthurlow error = smb_rap_parserqparam(p, &p, &plen); 2634bff34e3Sthurlow if (error) 2644bff34e3Sthurlow return (error); 2654bff34e3Sthurlow switch (ptype) { 2664bff34e3Sthurlow case 'L': 2674bff34e3Sthurlow rap->r_rcvbuflen = value; 2684bff34e3Sthurlow /* FALLTHROUGH */ 2694bff34e3Sthurlow case 'W': 2704bff34e3Sthurlow case 'D': 2714bff34e3Sthurlow case 'b': 2724bff34e3Sthurlow error = smb_rap_rqparam(rap, ptype, plen, value); 2734bff34e3Sthurlow break; 2744bff34e3Sthurlow default: 2754bff34e3Sthurlow return (EINVAL); 2764bff34e3Sthurlow } 2774bff34e3Sthurlow rap->r_nparam = p; 2784bff34e3Sthurlow return (0); 2794bff34e3Sthurlow } 2804bff34e3Sthurlow 2814bff34e3Sthurlow int 2824bff34e3Sthurlow smb_rap_setPparam(struct smb_rap *rap, void *value) 2834bff34e3Sthurlow { 2844bff34e3Sthurlow char *p = rap->r_nparam; 2854bff34e3Sthurlow char ptype = *p; 2864bff34e3Sthurlow int error, plen; 2874bff34e3Sthurlow 2884bff34e3Sthurlow error = smb_rap_parserqparam(p, &p, &plen); 2894bff34e3Sthurlow if (error) 2904bff34e3Sthurlow return (error); 2914bff34e3Sthurlow switch (ptype) { 2924bff34e3Sthurlow case 'r': 2934bff34e3Sthurlow rap->r_rcvbuf = value; 2944bff34e3Sthurlow break; 2954bff34e3Sthurlow default: 2964bff34e3Sthurlow return (EINVAL); 2974bff34e3Sthurlow } 2984bff34e3Sthurlow rap->r_nparam = p; 2994bff34e3Sthurlow return (0); 3004bff34e3Sthurlow } 3014bff34e3Sthurlow 3029c9af259SGordon Ross int 3034bff34e3Sthurlow smb_rap_getNparam(struct smb_rap *rap, long *value) 3044bff34e3Sthurlow { 3054bff34e3Sthurlow char *p = rap->r_nparam; 3064bff34e3Sthurlow char ptype = *p; 3074bff34e3Sthurlow int error, plen; 3084bff34e3Sthurlow uint16_t *te; 3094bff34e3Sthurlow 3104bff34e3Sthurlow error = smb_rap_parserpparam(p, &p, &plen); 3114bff34e3Sthurlow if (error) 3124bff34e3Sthurlow return (error); 3134bff34e3Sthurlow switch (ptype) { 3144bff34e3Sthurlow case 'h': 3154bff34e3Sthurlow /* LINTED */ 3164bff34e3Sthurlow te = (uint16_t *)rap->r_npbuf; 3174bff34e3Sthurlow *value = letohs(*te); 3184bff34e3Sthurlow break; 3194bff34e3Sthurlow default: 3204bff34e3Sthurlow return (EINVAL); 3214bff34e3Sthurlow } 3224bff34e3Sthurlow rap->r_npbuf += plen; 3234bff34e3Sthurlow rap->r_nparam = p; 3244bff34e3Sthurlow return (0); 3254bff34e3Sthurlow } 3264bff34e3Sthurlow 3274bff34e3Sthurlow int 3284bff34e3Sthurlow smb_rap_request(struct smb_rap *rap, struct smb_ctx *ctx) 3294bff34e3Sthurlow { 3304bff34e3Sthurlow uint16_t *rp, conv, *tmp; 331613a2f6bSGordon Ross uint32_t *p32; 3324bff34e3Sthurlow char *dp, *p = rap->r_nparam; 3334bff34e3Sthurlow char ptype; 334613a2f6bSGordon Ross int error, rdatacnt, rparamcnt, entries, done, dlen, buffer_oflow; 3354bff34e3Sthurlow 3364bff34e3Sthurlow rdatacnt = rap->r_rcvbuflen; 3374bff34e3Sthurlow rparamcnt = rap->r_plen; 338*430b4c46SGordon Ross error = smb_t2_request(ctx->ct_dev_fd, 339*430b4c46SGordon Ross 0, NULL, "\\PIPE\\LANMAN", 3404bff34e3Sthurlow rap->r_plen, rap->r_pbuf, /* int tparamcnt,void *tparam */ 3414bff34e3Sthurlow 0, NULL, /* int tdatacnt, void *tdata */ 3424bff34e3Sthurlow &rparamcnt, rap->r_pbuf, /* rparamcnt, void *rparam */ 3434bff34e3Sthurlow &rdatacnt, rap->r_rcvbuf, /* int *rdatacnt, void *rdata */ 3444bff34e3Sthurlow &buffer_oflow); 3454bff34e3Sthurlow if (error) 3464bff34e3Sthurlow return (error); 3474bff34e3Sthurlow 3484bff34e3Sthurlow /* LINTED */ 3494bff34e3Sthurlow rp = (uint16_t *)rap->r_pbuf; 3504bff34e3Sthurlow 3514bff34e3Sthurlow /* 3524bff34e3Sthurlow * Note: First is a "LanMan API" error code. 3534bff34e3Sthurlow * See: usr/src/uts/common/smbsrv/lmerr.h 3544bff34e3Sthurlow */ 3554bff34e3Sthurlow if (rparamcnt < 2) 3564bff34e3Sthurlow return (EBADRPC); 3574bff34e3Sthurlow rap->r_result = letohs(*rp); 3584bff34e3Sthurlow rp++; rparamcnt -= 2; 3594bff34e3Sthurlow 3604bff34e3Sthurlow if (rap->r_result != 0) { 3614bff34e3Sthurlow /* 3624bff34e3Sthurlow * Could also return zero and let the caller 3634bff34e3Sthurlow * come get r_result via smb_rap_error(), 3644bff34e3Sthurlow * but in case they dont... 3654bff34e3Sthurlow */ 3664bff34e3Sthurlow return (rap->r_result | SMB_RAP_ERROR); 3674bff34e3Sthurlow } 3684bff34e3Sthurlow 3694bff34e3Sthurlow if (rparamcnt < 2) 3704bff34e3Sthurlow return (EBADRPC); 3714bff34e3Sthurlow conv = letohs(*rp); 3724bff34e3Sthurlow rp++; rparamcnt -= 2; 3734bff34e3Sthurlow 3744bff34e3Sthurlow rap->r_npbuf = (char *)rp; 3754bff34e3Sthurlow rap->r_entries = entries = 0; 3764bff34e3Sthurlow /* Save the returned data length */ 3774bff34e3Sthurlow rap->r_rcvbuflen = rdatacnt; 3784bff34e3Sthurlow done = 0; 3794bff34e3Sthurlow 3804bff34e3Sthurlow while (!done && *p) { 3814bff34e3Sthurlow ptype = *p; 3824bff34e3Sthurlow switch (ptype) { 3834bff34e3Sthurlow case 'e': 3844bff34e3Sthurlow if (rparamcnt < 2) 3854bff34e3Sthurlow return (EBADRPC); 3864bff34e3Sthurlow /* LINTED */ 3874bff34e3Sthurlow tmp = (uint16_t *)rap->r_npbuf; 3884bff34e3Sthurlow rap->r_entries = entries = letohs(*tmp); 3894bff34e3Sthurlow rap->r_npbuf += 2; 3904bff34e3Sthurlow rparamcnt -= 2; 3914bff34e3Sthurlow p++; 3924bff34e3Sthurlow break; 3934bff34e3Sthurlow default: 3944bff34e3Sthurlow done = 1; 3954bff34e3Sthurlow } 3964bff34e3Sthurlow #if 0 /* commented out in Darwin. Why? */ 3974bff34e3Sthurlow error = smb_rap_parserpparam(p, &p, &plen); 3984bff34e3Sthurlow if (error) { 3994bff34e3Sthurlow smb_error(dgettext(TEXT_DOMAIN, 4004bff34e3Sthurlow "reply parameter mismatch %s"), 0, p); 4014bff34e3Sthurlow return (EBADRPC); 4024bff34e3Sthurlow } 4034bff34e3Sthurlow #endif 4044bff34e3Sthurlow } 4054bff34e3Sthurlow rap->r_nparam = p; 4064bff34e3Sthurlow /* 4074bff34e3Sthurlow * In general, unpacking entries we may need to relocate 4084bff34e3Sthurlow * entries for proper aligning. For now use them as is. 4094bff34e3Sthurlow */ 4104bff34e3Sthurlow dp = rap->r_rcvbuf; 4114bff34e3Sthurlow while (entries--) { 4124bff34e3Sthurlow p = rap->r_sdata; 4134bff34e3Sthurlow while (*p) { 4144bff34e3Sthurlow ptype = *p; 4154bff34e3Sthurlow error = smb_rap_parserpdata(p, &p, &dlen); 4164bff34e3Sthurlow if (error) { 4174bff34e3Sthurlow smb_error(dgettext(TEXT_DOMAIN, 4184bff34e3Sthurlow "reply data mismatch %s"), 0, p); 4194bff34e3Sthurlow return (EBADRPC); 4204bff34e3Sthurlow } 4214bff34e3Sthurlow if (rdatacnt < dlen) 4224bff34e3Sthurlow return (EBADRPC); 4234bff34e3Sthurlow switch (ptype) { 4244bff34e3Sthurlow case 'z': 4254bff34e3Sthurlow /* LINTED */ 4264bff34e3Sthurlow p32 = (uint32_t *)dp; 4274bff34e3Sthurlow *p32 = (letohl(*p32) & 0xffff) - conv; 4284bff34e3Sthurlow break; 4294bff34e3Sthurlow } 4304bff34e3Sthurlow dp += dlen; 4314bff34e3Sthurlow rdatacnt -= dlen; 4324bff34e3Sthurlow } 4334bff34e3Sthurlow } 4344bff34e3Sthurlow return (error); 4354bff34e3Sthurlow } 4364bff34e3Sthurlow 4374bff34e3Sthurlow int 4384bff34e3Sthurlow smb_rap_error(struct smb_rap *rap, int error) 4394bff34e3Sthurlow { 4404bff34e3Sthurlow if (error) 4414bff34e3Sthurlow return (error); 4424bff34e3Sthurlow if (rap->r_result == 0) 4434bff34e3Sthurlow return (0); 4444bff34e3Sthurlow return (rap->r_result | SMB_RAP_ERROR); 4454bff34e3Sthurlow } 446