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