ncpl_subr.c revision 52626
1/* 2 * Copyright (c) 1999, 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: head/lib/libncp/ncpl_subr.c 52626 1999-10-29 12:59:59Z bp $ 33 */ 34 35#include <sys/param.h> 36#include <sys/types.h> 37#include <sys/errno.h> 38#include <sys/sysctl.h> 39#include <sys/syscall.h> 40#include <unistd.h> 41#include <ctype.h> 42#include <string.h> 43#include <stdio.h> 44#include <stdlib.h> 45#include <stdarg.h> 46 47#include <netncp/ncp_lib.h> 48#include <netncp/ncp_rcfile.h> 49#include <netncp/ncp_nls.h> 50/*#include <netncp/ncp_cfg.h>*/ 51#include "ncp_mod.h" 52 53extern char *__progname; 54 55int sysentoffset; 56 57void 58ncp_add_word_lh(struct ncp_buf *conn, u_int16_t x) { 59 setwle(conn->packet, conn->rqsize, x); 60 conn->rqsize += 2; 61 return; 62} 63 64void 65ncp_add_dword_lh(struct ncp_buf *conn, u_int32_t x) { 66 setdle(conn->packet, conn->rqsize, x); 67 conn->rqsize += 4; 68 return; 69} 70 71void 72ncp_add_word_hl(struct ncp_buf *conn, u_int16_t x){ 73 setwbe(conn->packet, conn->rqsize, x); 74 conn->rqsize += 2; 75 return; 76} 77 78void 79ncp_add_dword_hl(struct ncp_buf *conn, u_int32_t x) { 80 setdbe(conn->packet, conn->rqsize, x); 81 conn->rqsize += 4; 82 return; 83} 84 85void 86ncp_add_mem(struct ncp_buf *conn, const void *source, int size) { 87 memcpy(conn->packet+conn->rqsize, source, size); 88 conn->rqsize += size; 89 return; 90} 91 92void 93ncp_add_mem_nls(struct ncp_buf *conn, const void *source, int size) { 94 ncp_nls_mem_u2n(conn->packet+conn->rqsize, source, size); 95 conn->rqsize += size; 96 return; 97} 98 99void 100ncp_add_pstring(struct ncp_buf *conn, const char *s) { 101 int len = strlen(s); 102 if (len > 255) { 103 ncp_printf("ncp_add_pstring: string too long: %s\n", s); 104 len = 255; 105 } 106 ncp_add_byte(conn, len); 107 ncp_add_mem(conn, s, len); 108 return; 109} 110 111void 112ncp_add_handle_path(struct ncp_buf *conn, nuint32 volNumber, nuint32 dirNumber, 113 int handleFlag, const char *path) 114{ 115 ncp_add_byte(conn, volNumber); 116 ncp_add_dword_lh(conn, dirNumber); 117 ncp_add_byte(conn, handleFlag); 118 if (path) { 119 ncp_add_byte(conn, 1); /* 1 component */ 120 ncp_add_pstring(conn, path); 121 } else { 122 ncp_add_byte(conn, 0); 123 } 124} 125 126void 127ncp_init_request(struct ncp_buf *conn) { 128 conn->rqsize = 0; 129 conn->rpsize = 0; 130} 131 132void 133ncp_init_request_s(struct ncp_buf *conn, int subfn) { 134 ncp_init_request(conn); 135 ncp_add_word_lh(conn, 0); 136 ncp_add_byte(conn, subfn); 137} 138 139u_int16_t 140ncp_reply_word_hl(struct ncp_buf *conn, int offset) { 141 return getwbe(ncp_reply_data(conn, offset), 0); 142} 143 144u_int16_t 145ncp_reply_word_lh(struct ncp_buf *conn, int offset) { 146 return getwle(ncp_reply_data(conn, offset), 0); 147} 148 149u_int32_t 150ncp_reply_dword_hl(struct ncp_buf *conn, int offset) { 151 return getdbe(ncp_reply_data(conn, offset), 0); 152} 153 154u_int32_t 155ncp_reply_dword_lh(struct ncp_buf *conn, int offset) { 156 return getdle(ncp_reply_data(conn, offset), 0); 157} 158 159 160int 161ncp_connect(struct ncp_conn_args *li, int *connHandle) { 162 return syscall(NCP_CONNECT,li,connHandle); 163} 164 165int 166ncp_disconnect(int cH) { 167 DECLARE_RQ; 168 169 ncp_init_request(conn); 170 ncp_add_byte(conn, NCP_CONN_CONNCLOSE); 171 return ncp_conn_request(cH, conn); 172} 173 174int 175ncp_request(int connHandle,int function, struct ncp_buf *ncpbuf){ 176 int err = syscall(SNCP_REQUEST,connHandle,function,ncpbuf); 177 return (err<0) ? errno : 0; 178} 179 180int 181ncp_conn_request(int connHandle, struct ncp_buf *ncpbuf){ 182 return syscall(SNCP_REQUEST, connHandle, NCP_CONN, ncpbuf); 183} 184 185int 186ncp_conn_scan(struct ncp_conn_loginfo *li, int *connid) { 187 return syscall(NCP_CONNSCAN,li, connid); 188} 189 190NWCCODE 191NWRequest(NWCONN_HANDLE cH, nuint16 fn, 192 nuint16 nrq, NW_FRAGMENT* rq, 193 nuint16 nrp, NW_FRAGMENT* rp) 194{ 195 int error; 196 struct ncp_conn_frag nf; 197 DECLARE_RQ; 198 199 ncp_init_request(conn); 200 ncp_add_byte(conn, NCP_CONN_FRAG); 201 nf.fn = fn; 202 nf.rqfcnt = nrq; 203 nf.rqf = rq; 204 nf.rpf = rp; 205 nf.rpfcnt = nrp; 206 ncp_add_mem(conn, &nf, sizeof(nf)); 207 error = ncp_conn_request(cH, conn); 208 return error; 209} 210 211 212int 213ncp_initlib(void){ 214 int error; 215 int len = sizeof(sysentoffset); 216 int kv, kvlen = sizeof(kv); 217 static int ncp_initialized; 218 219 if (ncp_initialized) 220 return 0; 221#if __FreeBSD_version < 400001 222 error = sysctlbyname("net.ipx.ncp.sysent", &sysentoffset, &len, NULL, 0); 223#else 224 error = sysctlbyname("net.ncp.sysent", &sysentoffset, &len, NULL, 0); 225#endif 226 if (error) { 227 fprintf(stderr, "%s: can't find kernel module\n", __FUNCTION__); 228 return error; 229 } 230#if __FreeBSD_version < 400001 231 error = sysctlbyname("net.ipx.ncp.version", &kv, &kvlen, NULL, 0); 232#else 233 error = sysctlbyname("net.ncp.version", &kv, &kvlen, NULL, 0); 234#endif 235 if (error) { 236 fprintf(stderr, "%s: kernel module is old, please recompile it.\n", __FUNCTION__); 237 return error; 238 } 239 if (NCP_VERSION != kv) { 240 fprintf(stderr, "%s: kernel module version(%d) don't match library(%d).\n", __FUNCTION__, kv, NCP_VERSION); 241 return EINVAL; 242 } 243 if ((error = ncp_nls_setrecode(0)) != 0) { 244 fprintf(stderr, "%s: can't initialise recode\n", __FUNCTION__); 245 return error; 246 } 247 if ((error = ncp_nls_setlocale("")) != 0) { 248 fprintf(stderr, "%s: can't initialise locale\n", __FUNCTION__); 249 return error; 250 } 251 ncp_initialized++; 252 return 0; 253} 254 255 256/* 257 */ 258int ncp_opterr = 1, /* if error message should be printed */ 259 ncp_optind = 1, /* index into parent argv vector */ 260 ncp_optopt, /* character checked for validity */ 261 ncp_optreset; /* reset getopt */ 262char *ncp_optarg; /* argument associated with option */ 263 264#define BADCH (int)'?' 265#define BADARG (int)':' 266#define EMSG "" 267 268int 269ncp_getopt(nargc, nargv, ostr) 270 int nargc; 271 char * const *nargv; 272 const char *ostr; 273{ 274 extern char *__progname; 275 static char *place = EMSG; /* option letter processing */ 276 char *oli; /* option letter list index */ 277 int tmpind; 278 279 if (ncp_optreset || !*place) { /* update scanning pointer */ 280 ncp_optreset = 0; 281 tmpind = ncp_optind; 282 while (1) { 283 if (tmpind >= nargc) { 284 place = EMSG; 285 return (-1); 286 } 287 if (*(place = nargv[tmpind]) != '-') { 288 tmpind++; 289 continue; /* lookup next option */ 290 } 291 if (place[1] && *++place == '-') { /* found "--" */ 292 ncp_optind = ++tmpind; 293 place = EMSG; 294 return (-1); 295 } 296 ncp_optind = tmpind; 297 break; 298 } 299 } /* option letter okay? */ 300 if ((ncp_optopt = (int)*place++) == (int)':' || 301 !(oli = strchr(ostr, ncp_optopt))) { 302 /* 303 * if the user didn't specify '-' as an option, 304 * assume it means -1. 305 */ 306 if (ncp_optopt == (int)'-') 307 return (-1); 308 if (!*place) 309 ++ncp_optind; 310 if (ncp_opterr && *ostr != ':') 311 (void)fprintf(stderr, 312 "%s: illegal option -- %c\n", __progname, ncp_optopt); 313 return (BADCH); 314 } 315 if (*++oli != ':') { /* don't need argument */ 316 ncp_optarg = NULL; 317 if (!*place) 318 ++ncp_optind; 319 } 320 else { /* need an argument */ 321 if (*place) /* no white space */ 322 ncp_optarg = place; 323 else if (nargc <= ++ncp_optind) { /* no arg */ 324 place = EMSG; 325 if (*ostr == ':') 326 return (BADARG); 327 if (ncp_opterr) 328 (void)fprintf(stderr, 329 "%s: option requires an argument -- %c\n", 330 __progname, ncp_optopt); 331 return (BADCH); 332 } 333 else /* white space */ 334 ncp_optarg = nargv[ncp_optind]; 335 place = EMSG; 336 ++ncp_optind; 337 } 338 return (ncp_optopt); /* dump back option letter */ 339} 340/* 341 * misc options parsing routines 342 */ 343int 344ncp_args_parserc(struct ncp_args *na, char *sect, ncp_setopt_t *set_callback) { 345 int len, error; 346 347 for (; na->opt; na++) { 348 switch (na->at) { 349 case NCA_STR: 350 if (rc_getstringptr(ncp_rc,sect,na->name,&na->str) == 0) { 351 len = strlen(na->str); 352 if (len > na->ival) { 353 fprintf(stderr,"rc: Argument for option '%c' (%s) too long\n",na->opt,na->name); 354 return EINVAL; 355 } 356 set_callback(na); 357 } 358 break; 359 case NCA_BOOL: 360 error = rc_getbool(ncp_rc,sect,na->name,&na->ival); 361 if (error == ENOENT) break; 362 if (error) return EINVAL; 363 set_callback(na); 364 break; 365 case NCA_INT: 366 if (rc_getint(ncp_rc,sect,na->name,&na->ival) == 0) { 367 if (((na->flag & NAFL_HAVEMIN) && 368 (na->ival < na->min)) || 369 ((na->flag & NAFL_HAVEMAX) && 370 (na->ival > na->max))) { 371 fprintf(stderr,"rc: Argument for option '%c' (%s) should be in [%d-%d] range\n",na->opt,na->name,na->min,na->max); 372 return EINVAL; 373 } 374 set_callback(na); 375 }; 376 break; 377 default: 378 break; 379 } 380 } 381 return 0; 382} 383 384int 385ncp_args_parseopt(struct ncp_args *na, int opt, char *optarg, ncp_setopt_t *set_callback) { 386 int len; 387 388 for (; na->opt; na++) { 389 if (na->opt != opt) continue; 390 switch (na->at) { 391 case NCA_STR: 392 na->str = optarg; 393 if (optarg) { 394 len = strlen(na->str); 395 if (len > na->ival) { 396 fprintf(stderr,"opt: Argument for option '%c' (%s) too long\n",na->opt,na->name); 397 return EINVAL; 398 } 399 set_callback(na); 400 } 401 break; 402 case NCA_BOOL: 403 na->ival = 0; 404 set_callback(na); 405 break; 406 case NCA_INT: 407 errno = 0; 408 na->ival = strtol(optarg, NULL, 0); 409 if (errno) { 410 fprintf(stderr,"opt: Invalid integer value for option '%c' (%s).\n",na->opt,na->name); 411 return EINVAL; 412 } 413 if (((na->flag & NAFL_HAVEMIN) && 414 (na->ival < na->min)) || 415 ((na->flag & NAFL_HAVEMAX) && 416 (na->ival > na->max))) { 417 fprintf(stderr,"opt: Argument for option '%c' (%s) should be in [%d-%d] range\n",na->opt,na->name,na->min,na->max); 418 return EINVAL; 419 } 420 set_callback(na); 421 break; 422 default: 423 break; 424 } 425 break; 426 } 427 return 0; 428} 429 430/* 431 * Print a (descriptive) error message 432 * error values: 433 * 0 - no specific error code available; 434 * -999..-1 - NDS error 435 * 1..32767 - system error 436 * the rest - requester error; 437 */ 438void 439ncp_error(char *fmt, int error,...) { 440 va_list ap; 441 442 fprintf(stderr, "%s: ", __progname); 443 va_start(ap, error); 444 vfprintf(stderr, fmt, ap); 445 va_end(ap); 446 if (error == -1) 447 error = errno; 448 if (error > -1000 && error < 0) { 449 fprintf(stderr, ": dserr = %d\n", error); 450 } else if (error & 0x8000) { 451 fprintf(stderr, ": nwerr = %04x\n", error); 452 } else if (error) { 453 fprintf(stderr, ": syserr = %s\n", strerror(error)); 454 } else 455 fprintf(stderr, "\n"); 456} 457 458char * 459ncp_printb(char *dest, int flags, const struct ncp_bitname *bnp) { 460 int first = 1; 461 462 strcpy(dest, "<"); 463 for(; bnp->bn_bit; bnp++) { 464 if (flags & bnp->bn_bit) { 465 strcat(dest, bnp->bn_name); 466 first = 0; 467 } 468 if (!first && (flags & bnp[1].bn_bit)) 469 strcat(dest, "|"); 470 } 471 strcat(dest, ">"); 472 return dest; 473} 474