]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libncp/ncpl_subr.c
This commit was generated by cvs2svn to compensate for changes in r98681,
[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/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
54 int sysentoffset;
55
56 void
57 ncp_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
63 void
64 ncp_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
70 void
71 ncp_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
77 void
78 ncp_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
84 void
85 ncp_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
91 void
92 ncp_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
98 void
99 ncp_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
110 void
111 ncp_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
125 void
126 ncp_init_request(struct ncp_buf *conn) {
127         conn->rqsize = 0;
128         conn->rpsize = 0;
129 }
130
131 void
132 ncp_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
138 u_int16_t
139 ncp_reply_word_hl(struct ncp_buf *conn, int offset) {
140         return getwbe(ncp_reply_data(conn, offset), 0);
141 }
142
143 u_int16_t
144 ncp_reply_word_lh(struct ncp_buf *conn, int offset) {
145         return getwle(ncp_reply_data(conn, offset), 0);
146 }
147
148 u_int32_t
149 ncp_reply_dword_hl(struct ncp_buf *conn, int offset) {
150         return getdbe(ncp_reply_data(conn, offset), 0);
151 }
152
153 u_int32_t
154 ncp_reply_dword_lh(struct ncp_buf *conn, int offset) {
155         return getdle(ncp_reply_data(conn, offset), 0);
156 }
157
158
159 int
160 ncp_connect(struct ncp_conn_args *li, int *connHandle) {
161         return syscall(NCP_CONNECT,li,connHandle);
162 }
163
164 int
165 ncp_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
173 int
174 ncp_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
179 int
180 ncp_conn_request(int connHandle, struct ncp_buf *ncpbuf){
181         return syscall(SNCP_REQUEST, connHandle, NCP_CONN, ncpbuf);
182 }
183
184 int
185 ncp_conn_scan(struct ncp_conn_loginfo *li, int *connid) {
186         return syscall(NCP_CONNSCAN,li, connid);
187 }
188
189 NWCCODE
190 NWRequest(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
211 int
212 ncp_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  */
257 int     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 */
261 char    *ncp_optarg;            /* argument associated with option */
262
263 #define BADCH   (int)'?'
264 #define BADARG  (int)':'
265 #define EMSG    ""
266
267 int
268 ncp_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  */
341 int
342 ncp_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
382 int
383 ncp_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  */
436 void
437 ncp_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
456 char *
457 ncp_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 }