]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libncp/ncpl_subr.c
This commit was generated by cvs2svn to compensate for changes in r160157,
[FreeBSD/FreeBSD.git] / lib / libncp / ncpl_subr.c
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$");
35
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>
41 #include <unistd.h>
42 #include <ctype.h>
43 #include <fcntl.h>
44 #include <paths.h>
45 #include <string.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <stdarg.h>
49
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>
55
56 #define _PATH_NCP       _PATH_DEV NCP_NAME
57
58 void
59 ncp_add_word_lh(struct ncp_buf *conn, u_int16_t x) {
60         setwle(conn->packet, conn->rqsize, x);
61         conn->rqsize += 2;
62         return;
63 }
64
65 void
66 ncp_add_dword_lh(struct ncp_buf *conn, u_int32_t x) {
67         setdle(conn->packet, conn->rqsize, x);
68         conn->rqsize += 4;
69         return;
70 }
71
72 void
73 ncp_add_word_hl(struct ncp_buf *conn, u_int16_t x){
74         setwbe(conn->packet, conn->rqsize, x);
75         conn->rqsize += 2;
76         return;
77 }
78
79 void
80 ncp_add_dword_hl(struct ncp_buf *conn, u_int32_t x) {
81         setdbe(conn->packet, conn->rqsize, x);
82         conn->rqsize += 4;
83         return;
84 }
85
86 void
87 ncp_add_mem(struct ncp_buf *conn, const void *source, int size) {
88         memcpy(conn->packet+conn->rqsize, source, size);
89         conn->rqsize += size;
90         return;
91 }
92
93 void
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);
96         conn->rqsize += size;
97         return;
98 }
99
100 void
101 ncp_add_pstring(struct ncp_buf *conn, const char *s) {
102         int len = strlen(s);
103         if (len > 255) {
104                 ncp_printf("ncp_add_pstring: string too long: %s\n", s);
105                 len = 255;
106         }
107         ncp_add_byte(conn, len);
108         ncp_add_mem(conn, s, len);
109         return;
110 }
111
112 void
113 ncp_add_handle_path(struct ncp_buf *conn, nuint32 volNumber, nuint32 dirNumber,
114         int handleFlag, const char *path)
115 {
116         ncp_add_byte(conn, volNumber);
117         ncp_add_dword_lh(conn, dirNumber);
118         ncp_add_byte(conn, handleFlag);
119         if (path) {
120                 ncp_add_byte(conn, 1);          /* 1 component */
121                 ncp_add_pstring(conn, path);
122         } else {
123                 ncp_add_byte(conn, 0);
124         }
125 }
126
127 void
128 ncp_init_request(struct ncp_buf *conn) {
129         conn->rqsize = 0;
130         conn->rpsize = 0;
131 }
132
133 void
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);
138 }
139
140 u_int16_t
141 ncp_reply_word_hl(struct ncp_buf *conn, int offset) {
142         return getwbe(ncp_reply_data(conn, offset), 0);
143 }
144
145 u_int16_t
146 ncp_reply_word_lh(struct ncp_buf *conn, int offset) {
147         return getwle(ncp_reply_data(conn, offset), 0);
148 }
149
150 u_int32_t
151 ncp_reply_dword_hl(struct ncp_buf *conn, int offset) {
152         return getdbe(ncp_reply_data(conn, offset), 0);
153 }
154
155 u_int32_t
156 ncp_reply_dword_lh(struct ncp_buf *conn, int offset) {
157         return getdle(ncp_reply_data(conn, offset), 0);
158 }
159
160
161 int
162 ncp_connect(struct ncp_conn_args *li, int *connHandle) {
163         struct ncpioc_connect args;
164         int fd, r;
165         if ((fd = open(_PATH_NCP, O_RDWR)) < 0)
166                 return (errno);
167         args.ioc_li = li;
168         args.ioc_connhandle = connHandle;
169         errno = 0;
170         (void)ioctl(fd, NCPIOC_CONNECT, &args);
171         r = errno;
172         close(fd);
173         return (r);
174 }
175
176 int
177 ncp_disconnect(int cH) {
178         DECLARE_RQ;
179
180         ncp_init_request(conn);
181         ncp_add_byte(conn, NCP_CONN_CONNCLOSE);
182         return ncp_conn_request(cH, conn);
183 }
184
185 int
186 ncp_request(int connHandle,int function, struct ncp_buf *ncpbuf){
187         struct ncpioc_request args;
188         int fd, r;
189         if ((fd = open(_PATH_NCP, O_RDWR)) < 0)
190                 return (errno);
191         args.ioc_connhandle = connHandle;
192         args.ioc_fn = function;
193         args.ioc_ncpbuf = ncpbuf;
194         errno = 0;
195         (void)ioctl(fd, NCPIOC_REQUEST, &args);
196         r = errno;
197         close(fd);
198         return (r);
199 }
200
201 int
202 ncp_conn_request(int connHandle, struct ncp_buf *ncpbuf){
203         return (ncp_request(connHandle, NCP_CONN, ncpbuf));
204 }
205
206 int
207 ncp_conn_scan(struct ncp_conn_loginfo *li, int *connid) {
208         struct ncpioc_connscan args;
209         int fd, r;
210         if ((fd = open(_PATH_NCP, O_RDWR)) < 0)
211                 return (errno);
212         args.ioc_li = li;
213         args.ioc_connhandle = connid;
214         errno = 0;
215         (void)ioctl(fd, NCPIOC_CONNSCAN, &args);
216         r = errno;
217         close(fd);
218         return (r);
219 }
220
221 NWCCODE
222 NWRequest(NWCONN_HANDLE cH, nuint16 fn,
223         nuint16 nrq, NW_FRAGMENT* rq, 
224         nuint16 nrp, NW_FRAGMENT* rp) 
225 {
226         int error;
227         struct ncp_conn_frag nf;
228         DECLARE_RQ;
229
230         ncp_init_request(conn);
231         ncp_add_byte(conn, NCP_CONN_FRAG);
232         nf.fn = fn;
233         nf.rqfcnt = nrq;
234         nf.rqf = rq;
235         nf.rpf = rp;
236         nf.rpfcnt = nrp;
237         ncp_add_mem(conn, &nf, sizeof(nf));
238         error = ncp_conn_request(cH, conn);
239         return error;
240 }
241
242
243 int
244 ncp_initlib(void){
245         int error;
246         int kv;
247         size_t kvlen = sizeof(kv);
248         static int ncp_initialized;
249
250         if (ncp_initialized)
251                 return 0;
252         error = sysctlbyname("net.ncp.version", &kv, &kvlen, NULL, 0);
253         if (error) {
254                 if (errno == ENOENT)
255                         fprintf(stderr, "Kernel module ncp is not loaded.\n");
256                 else
257                         fprintf(stderr, "%s: kernel module is old, please recompile it.\n", __func__);
258                 return error;
259         }
260         if (NCP_VERSION != kv) {
261                 fprintf(stderr, "%s: kernel module version(%d) don't match library(%d).\n", __func__, kv, NCP_VERSION);
262                 return EINVAL;
263         }
264         if ((error = ncp_nls_setrecode(0)) != 0) {
265                 fprintf(stderr, "%s: can't initialise recode\n", __func__);
266                 return error;
267         }
268         if ((error = ncp_nls_setlocale("")) != 0) {
269                 fprintf(stderr, "%s: can't initialise locale\n", __func__);
270                 return error;
271         }
272         ncp_initialized++;
273         return 0;
274 }
275
276
277 /*
278  */
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 */
284
285 #define BADCH   (int)'?'
286 #define BADARG  (int)':'
287 #define EMSG    ""
288
289 int
290 ncp_getopt(nargc, nargv, ostr)
291         int nargc;
292         char * const *nargv;
293         const char *ostr;
294 {
295         static char *place = EMSG;              /* option letter processing */
296         char *oli;                              /* option letter list index */
297         int tmpind;
298
299         if (ncp_optreset || !*place) {          /* update scanning pointer */
300                 ncp_optreset = 0;
301                 tmpind = ncp_optind;
302                 while (1) {
303                         if (tmpind >= nargc) {
304                                 place = EMSG;
305                                 return (-1);
306                         }
307                         if (*(place = nargv[tmpind]) != '-') {
308                                 tmpind++;
309                                 continue;       /* lookup next option */
310                         }
311                         if (place[1] && *++place == '-') {      /* found "--" */
312                                 ncp_optind = ++tmpind;
313                                 place = EMSG;
314                                 return (-1);
315                         }
316                         ncp_optind = tmpind;
317                         break;
318                 }
319         }                                       /* option letter okay? */
320         if ((ncp_optopt = (int)*place++) == (int)':' ||
321             !(oli = strchr(ostr, ncp_optopt))) {
322                 /*
323                  * if the user didn't specify '-' as an option,
324                  * assume it means -1.
325                  */
326                 if (ncp_optopt == (int)'-')
327                         return (-1);
328                 if (!*place)
329                         ++ncp_optind;
330                 if (ncp_opterr && *ostr != ':')
331                         (void)fprintf(stderr,
332                             "%s: illegal option -- %c\n", _getprogname(), ncp_optopt);
333                 return (BADCH);
334         }
335         if (*++oli != ':') {                    /* don't need argument */
336                 ncp_optarg = NULL;
337                 if (!*place)
338                         ++ncp_optind;
339         }
340         else {                                  /* need an argument */
341                 if (*place)                     /* no white space */
342                         ncp_optarg = place;
343                 else if (nargc <= ++ncp_optind) {       /* no arg */
344                         place = EMSG;
345                         if (*ostr == ':')
346                                 return (BADARG);
347                         if (ncp_opterr)
348                                 (void)fprintf(stderr,
349                                     "%s: option requires an argument -- %c\n",
350                                     _getprogname(), ncp_optopt);
351                         return (BADCH);
352                 }
353                 else                            /* white space */
354                         ncp_optarg = nargv[ncp_optind];
355                 place = EMSG;
356                 ++ncp_optind;
357         }
358         return (ncp_optopt);                    /* dump back option letter */
359 }
360 /*
361  * misc options parsing routines
362  */
363 int
364 ncp_args_parserc(struct ncp_args *na, char *sect, ncp_setopt_t *set_callback) {
365         int len, error;
366
367         for (; na->opt; na++) {
368                 switch (na->at) {
369                     case NCA_STR:
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);
374                                         return EINVAL;
375                                 }
376                                 set_callback(na);
377                         }
378                         break;
379                     case NCA_BOOL:
380                         error = rc_getbool(ncp_rc,sect,na->name,&na->ival);
381                         if (error == ENOENT) break;
382                         if (error) return EINVAL;
383                         set_callback(na);
384                         break;
385                     case NCA_INT:
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);
392                                         return EINVAL;
393                                 }
394                                 set_callback(na);
395                         };
396                         break;
397                     default:
398                         break;
399                 }
400         }
401         return 0;
402 }
403
404 int
405 ncp_args_parseopt(struct ncp_args *na, int opt, char *optarg, ncp_setopt_t *set_callback) {
406         int len;
407
408         for (; na->opt; na++) {
409                 if (na->opt != opt) continue;
410                 switch (na->at) {
411                     case NCA_STR:
412                         na->str = optarg;
413                         if (optarg) {
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);
417                                         return EINVAL;
418                                 }
419                                 set_callback(na);
420                         }
421                         break;
422                     case NCA_BOOL:
423                         na->ival = 0;
424                         set_callback(na);
425                         break;
426                     case NCA_INT:
427                         errno = 0;
428                         na->ival = strtol(optarg, NULL, 0);
429                         if (errno) {
430                                 fprintf(stderr,"opt: Invalid integer value for option '%c' (%s).\n",na->opt,na->name);
431                                 return EINVAL;
432                         }
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);
438                                 return EINVAL;
439                         }
440                         set_callback(na);
441                         break;
442                     default:
443                         break;
444                 }
445                 break;
446         }
447         return 0;
448 }
449
450 /*
451  * Print a (descriptive) error message
452  * error values:
453  *         0 - no specific error code available;
454  *  -999..-1 - NDS error
455  *  1..32767 - system error
456  *  the rest - requester error;
457  */
458 void
459 ncp_error(const char *fmt, int error, ...) {
460         va_list ap;
461
462         fprintf(stderr, "%s: ", _getprogname());
463         va_start(ap, error);
464         vfprintf(stderr, fmt, ap);
465         va_end(ap);
466         if (error == -1)
467                 error = errno;
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);
472         } else if (error) {
473                 fprintf(stderr, ": syserr = %s\n", strerror(error));
474         } else
475                 fprintf(stderr, "\n");
476 }
477
478 char *
479 ncp_printb(char *dest, int flags, const struct ncp_bitname *bnp) {
480         int first = 1;
481
482         strcpy(dest, "<");
483         for(; bnp->bn_bit; bnp++) {
484                 if (flags & bnp->bn_bit) {
485                         strcat(dest, bnp->bn_name);
486                         first = 0;
487                 }
488                 if (!first && (flags & bnp[1].bn_bit))
489                         strcat(dest, "|");
490         }
491         strcat(dest, ">");
492         return dest;
493 }