2 * Copyright (c) 1999, Boris Popov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 #include <sys/param.h>
37 #include <sys/types.h>
38 #include <sys/errno.h>
39 #include <sys/sysctl.h>
40 #include <sys/ioctl.h>
50 #include <netncp/ncp_lib.h>
51 #include <netncp/ncp_rcfile.h>
52 #include <netncp/ncp_nls.h>
53 /*#include <netncp/ncp_cfg.h>*/
54 #include <netncp/ncpio.h>
56 #define _PATH_NCP _PATH_DEV NCP_NAME
59 ncp_add_word_lh(struct ncp_buf *conn, u_int16_t x) {
60 setwle(conn->packet, conn->rqsize, x);
66 ncp_add_dword_lh(struct ncp_buf *conn, u_int32_t x) {
67 setdle(conn->packet, conn->rqsize, x);
73 ncp_add_word_hl(struct ncp_buf *conn, u_int16_t x){
74 setwbe(conn->packet, conn->rqsize, x);
80 ncp_add_dword_hl(struct ncp_buf *conn, u_int32_t x) {
81 setdbe(conn->packet, conn->rqsize, x);
87 ncp_add_mem(struct ncp_buf *conn, const void *source, int size) {
88 memcpy(conn->packet+conn->rqsize, source, size);
94 ncp_add_mem_nls(struct ncp_buf *conn, const void *source, int size) {
95 ncp_nls_mem_u2n(conn->packet+conn->rqsize, source, size);
101 ncp_add_pstring(struct ncp_buf *conn, const char *s) {
104 ncp_printf("ncp_add_pstring: string too long: %s\n", s);
107 ncp_add_byte(conn, len);
108 ncp_add_mem(conn, s, len);
113 ncp_add_handle_path(struct ncp_buf *conn, nuint32 volNumber, nuint32 dirNumber,
114 int handleFlag, const char *path)
116 ncp_add_byte(conn, volNumber);
117 ncp_add_dword_lh(conn, dirNumber);
118 ncp_add_byte(conn, handleFlag);
120 ncp_add_byte(conn, 1); /* 1 component */
121 ncp_add_pstring(conn, path);
123 ncp_add_byte(conn, 0);
128 ncp_init_request(struct ncp_buf *conn) {
134 ncp_init_request_s(struct ncp_buf *conn, int subfn) {
135 ncp_init_request(conn);
136 ncp_add_word_lh(conn, 0);
137 ncp_add_byte(conn, subfn);
141 ncp_reply_word_hl(struct ncp_buf *conn, int offset) {
142 return getwbe(ncp_reply_data(conn, offset), 0);
146 ncp_reply_word_lh(struct ncp_buf *conn, int offset) {
147 return getwle(ncp_reply_data(conn, offset), 0);
151 ncp_reply_dword_hl(struct ncp_buf *conn, int offset) {
152 return getdbe(ncp_reply_data(conn, offset), 0);
156 ncp_reply_dword_lh(struct ncp_buf *conn, int offset) {
157 return getdle(ncp_reply_data(conn, offset), 0);
162 ncp_connect(struct ncp_conn_args *li, int *connHandle) {
163 struct ncpioc_connect args;
165 if ((fd = open(_PATH_NCP, O_RDWR)) < 0)
168 args.ioc_connhandle = connHandle;
170 (void)ioctl(fd, NCPIOC_CONNECT, &args);
177 ncp_disconnect(int cH) {
180 ncp_init_request(conn);
181 ncp_add_byte(conn, NCP_CONN_CONNCLOSE);
182 return ncp_conn_request(cH, conn);
186 ncp_request(int connHandle,int function, struct ncp_buf *ncpbuf){
187 struct ncpioc_request args;
189 if ((fd = open(_PATH_NCP, O_RDWR)) < 0)
191 args.ioc_connhandle = connHandle;
192 args.ioc_fn = function;
193 args.ioc_ncpbuf = ncpbuf;
195 (void)ioctl(fd, NCPIOC_REQUEST, &args);
202 ncp_conn_request(int connHandle, struct ncp_buf *ncpbuf){
203 return (ncp_request(connHandle, NCP_CONN, ncpbuf));
207 ncp_conn_scan(struct ncp_conn_loginfo *li, int *connid) {
208 struct ncpioc_connscan args;
210 if ((fd = open(_PATH_NCP, O_RDWR)) < 0)
213 args.ioc_connhandle = connid;
215 (void)ioctl(fd, NCPIOC_CONNSCAN, &args);
222 NWRequest(NWCONN_HANDLE cH, nuint16 fn,
223 nuint16 nrq, NW_FRAGMENT* rq,
224 nuint16 nrp, NW_FRAGMENT* rp)
227 struct ncp_conn_frag nf;
230 ncp_init_request(conn);
231 ncp_add_byte(conn, NCP_CONN_FRAG);
237 ncp_add_mem(conn, &nf, sizeof(nf));
238 error = ncp_conn_request(cH, conn);
247 size_t kvlen = sizeof(kv);
248 static int ncp_initialized;
252 error = sysctlbyname("net.ncp.version", &kv, &kvlen, NULL, 0);
255 fprintf(stderr, "Kernel module ncp is not loaded.\n");
257 fprintf(stderr, "%s: kernel module is old, please recompile it.\n", __func__);
260 if (NCP_VERSION != kv) {
261 fprintf(stderr, "%s: kernel module version(%d) don't match library(%d).\n", __func__, kv, NCP_VERSION);
264 if ((error = ncp_nls_setrecode(0)) != 0) {
265 fprintf(stderr, "%s: can't initialise recode\n", __func__);
268 if ((error = ncp_nls_setlocale("")) != 0) {
269 fprintf(stderr, "%s: can't initialise locale\n", __func__);
279 int ncp_opterr = 1, /* if error message should be printed */
280 ncp_optind = 1, /* index into parent argv vector */
281 ncp_optopt, /* character checked for validity */
282 ncp_optreset; /* reset getopt */
283 char *ncp_optarg; /* argument associated with option */
285 #define BADCH (int)'?'
286 #define BADARG (int)':'
290 ncp_getopt(nargc, nargv, ostr)
295 static char *place = EMSG; /* option letter processing */
296 char *oli; /* option letter list index */
299 if (ncp_optreset || !*place) { /* update scanning pointer */
303 if (tmpind >= nargc) {
307 if (*(place = nargv[tmpind]) != '-') {
309 continue; /* lookup next option */
311 if (place[1] && *++place == '-') { /* found "--" */
312 ncp_optind = ++tmpind;
319 } /* option letter okay? */
320 if ((ncp_optopt = (int)*place++) == (int)':' ||
321 !(oli = strchr(ostr, ncp_optopt))) {
323 * if the user didn't specify '-' as an option,
324 * assume it means -1.
326 if (ncp_optopt == (int)'-')
330 if (ncp_opterr && *ostr != ':')
331 (void)fprintf(stderr,
332 "%s: illegal option -- %c\n", _getprogname(), ncp_optopt);
335 if (*++oli != ':') { /* don't need argument */
340 else { /* need an argument */
341 if (*place) /* no white space */
343 else if (nargc <= ++ncp_optind) { /* no arg */
348 (void)fprintf(stderr,
349 "%s: option requires an argument -- %c\n",
350 _getprogname(), ncp_optopt);
353 else /* white space */
354 ncp_optarg = nargv[ncp_optind];
358 return (ncp_optopt); /* dump back option letter */
361 * misc options parsing routines
364 ncp_args_parserc(struct ncp_args *na, char *sect, ncp_setopt_t *set_callback) {
367 for (; na->opt; na++) {
370 if (rc_getstringptr(ncp_rc,sect,na->name,&na->str) == 0) {
371 len = strlen(na->str);
372 if (len > na->ival) {
373 fprintf(stderr,"rc: Argument for option '%c' (%s) too long\n",na->opt,na->name);
380 error = rc_getbool(ncp_rc,sect,na->name,&na->ival);
381 if (error == ENOENT) break;
382 if (error) return EINVAL;
386 if (rc_getint(ncp_rc,sect,na->name,&na->ival) == 0) {
387 if (((na->flag & NAFL_HAVEMIN) &&
388 (na->ival < na->min)) ||
389 ((na->flag & NAFL_HAVEMAX) &&
390 (na->ival > na->max))) {
391 fprintf(stderr,"rc: Argument for option '%c' (%s) should be in [%d-%d] range\n",na->opt,na->name,na->min,na->max);
405 ncp_args_parseopt(struct ncp_args *na, int opt, char *optarg, ncp_setopt_t *set_callback) {
408 for (; na->opt; na++) {
409 if (na->opt != opt) continue;
414 len = strlen(na->str);
415 if (len > na->ival) {
416 fprintf(stderr,"opt: Argument for option '%c' (%s) too long\n",na->opt,na->name);
428 na->ival = strtol(optarg, NULL, 0);
430 fprintf(stderr,"opt: Invalid integer value for option '%c' (%s).\n",na->opt,na->name);
433 if (((na->flag & NAFL_HAVEMIN) &&
434 (na->ival < na->min)) ||
435 ((na->flag & NAFL_HAVEMAX) &&
436 (na->ival > na->max))) {
437 fprintf(stderr,"opt: Argument for option '%c' (%s) should be in [%d-%d] range\n",na->opt,na->name,na->min,na->max);
451 * Print a (descriptive) error message
453 * 0 - no specific error code available;
454 * -999..-1 - NDS error
455 * 1..32767 - system error
456 * the rest - requester error;
459 ncp_error(const char *fmt, int error, ...) {
462 fprintf(stderr, "%s: ", _getprogname());
464 vfprintf(stderr, fmt, ap);
468 if (error > -1000 && error < 0) {
469 fprintf(stderr, ": dserr = %d\n", error);
470 } else if (error & 0x8000) {
471 fprintf(stderr, ": nwerr = %04x\n", error);
473 fprintf(stderr, ": syserr = %s\n", strerror(error));
475 fprintf(stderr, "\n");
479 ncp_printb(char *dest, int flags, const struct ncp_bitname *bnp) {
483 for(; bnp->bn_bit; bnp++) {
484 if (flags & bnp->bn_bit) {
485 strcat(dest, bnp->bn_name);
488 if (!first && (flags & bnp[1].bn_bit))