]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libncp/ncpl_subr.c
This commit was generated by cvs2svn to compensate for changes in r82017,
[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  * $FreeBSD$
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
53 extern char *__progname;
54
55 int sysentoffset;
56
57 void
58 ncp_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
64 void
65 ncp_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
71 void
72 ncp_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
78 void
79 ncp_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
85 void
86 ncp_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
92 void
93 ncp_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
99 void
100 ncp_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
111 void
112 ncp_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
126 void
127 ncp_init_request(struct ncp_buf *conn) {
128         conn->rqsize = 0;
129         conn->rpsize = 0;
130 }
131
132 void
133 ncp_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
139 u_int16_t
140 ncp_reply_word_hl(struct ncp_buf *conn, int offset) {
141         return getwbe(ncp_reply_data(conn, offset), 0);
142 }
143
144 u_int16_t
145 ncp_reply_word_lh(struct ncp_buf *conn, int offset) {
146         return getwle(ncp_reply_data(conn, offset), 0);
147 }
148
149 u_int32_t
150 ncp_reply_dword_hl(struct ncp_buf *conn, int offset) {
151         return getdbe(ncp_reply_data(conn, offset), 0);
152 }
153
154 u_int32_t
155 ncp_reply_dword_lh(struct ncp_buf *conn, int offset) {
156         return getdle(ncp_reply_data(conn, offset), 0);
157 }
158
159
160 int
161 ncp_connect(struct ncp_conn_args *li, int *connHandle) {
162         return syscall(NCP_CONNECT,li,connHandle);
163 }
164
165 int
166 ncp_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
174 int
175 ncp_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
180 int
181 ncp_conn_request(int connHandle, struct ncp_buf *ncpbuf){
182         return syscall(SNCP_REQUEST, connHandle, NCP_CONN, ncpbuf);
183 }
184
185 int
186 ncp_conn_scan(struct ncp_conn_loginfo *li, int *connid) {
187         return syscall(NCP_CONNSCAN,li, connid);
188 }
189
190 NWCCODE
191 NWRequest(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
212 int
213 ncp_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  */
258 int     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 */
262 char    *ncp_optarg;            /* argument associated with option */
263
264 #define BADCH   (int)'?'
265 #define BADARG  (int)':'
266 #define EMSG    ""
267
268 int
269 ncp_getopt(nargc, nargv, ostr)
270         int nargc;
271         char * const *nargv;
272         const char *ostr;
273 {
274         static char *place = EMSG;              /* option letter processing */
275         char *oli;                              /* option letter list index */
276         int tmpind;
277
278         if (ncp_optreset || !*place) {          /* update scanning pointer */
279                 ncp_optreset = 0;
280                 tmpind = ncp_optind;
281                 while (1) {
282                         if (tmpind >= nargc) {
283                                 place = EMSG;
284                                 return (-1);
285                         }
286                         if (*(place = nargv[tmpind]) != '-') {
287                                 tmpind++;
288                                 continue;       /* lookup next option */
289                         }
290                         if (place[1] && *++place == '-') {      /* found "--" */
291                                 ncp_optind = ++tmpind;
292                                 place = EMSG;
293                                 return (-1);
294                         }
295                         ncp_optind = tmpind;
296                         break;
297                 }
298         }                                       /* option letter okay? */
299         if ((ncp_optopt = (int)*place++) == (int)':' ||
300             !(oli = strchr(ostr, ncp_optopt))) {
301                 /*
302                  * if the user didn't specify '-' as an option,
303                  * assume it means -1.
304                  */
305                 if (ncp_optopt == (int)'-')
306                         return (-1);
307                 if (!*place)
308                         ++ncp_optind;
309                 if (ncp_opterr && *ostr != ':')
310                         (void)fprintf(stderr,
311                             "%s: illegal option -- %c\n", __progname, ncp_optopt);
312                 return (BADCH);
313         }
314         if (*++oli != ':') {                    /* don't need argument */
315                 ncp_optarg = NULL;
316                 if (!*place)
317                         ++ncp_optind;
318         }
319         else {                                  /* need an argument */
320                 if (*place)                     /* no white space */
321                         ncp_optarg = place;
322                 else if (nargc <= ++ncp_optind) {       /* no arg */
323                         place = EMSG;
324                         if (*ostr == ':')
325                                 return (BADARG);
326                         if (ncp_opterr)
327                                 (void)fprintf(stderr,
328                                     "%s: option requires an argument -- %c\n",
329                                     __progname, ncp_optopt);
330                         return (BADCH);
331                 }
332                 else                            /* white space */
333                         ncp_optarg = nargv[ncp_optind];
334                 place = EMSG;
335                 ++ncp_optind;
336         }
337         return (ncp_optopt);                    /* dump back option letter */
338 }
339 /*
340  * misc options parsing routines
341  */
342 int
343 ncp_args_parserc(struct ncp_args *na, char *sect, ncp_setopt_t *set_callback) {
344         int len, error;
345
346         for (; na->opt; na++) {
347                 switch (na->at) {
348                     case NCA_STR:
349                         if (rc_getstringptr(ncp_rc,sect,na->name,&na->str) == 0) {
350                                 len = strlen(na->str);
351                                 if (len > na->ival) {
352                                         fprintf(stderr,"rc: Argument for option '%c' (%s) too long\n",na->opt,na->name);
353                                         return EINVAL;
354                                 }
355                                 set_callback(na);
356                         }
357                         break;
358                     case NCA_BOOL:
359                         error = rc_getbool(ncp_rc,sect,na->name,&na->ival);
360                         if (error == ENOENT) break;
361                         if (error) return EINVAL;
362                         set_callback(na);
363                         break;
364                     case NCA_INT:
365                         if (rc_getint(ncp_rc,sect,na->name,&na->ival) == 0) {
366                                 if (((na->flag & NAFL_HAVEMIN) && 
367                                      (na->ival < na->min)) || 
368                                     ((na->flag & NAFL_HAVEMAX) && 
369                                      (na->ival > na->max))) {
370                                         fprintf(stderr,"rc: Argument for option '%c' (%s) should be in [%d-%d] range\n",na->opt,na->name,na->min,na->max);
371                                         return EINVAL;
372                                 }
373                                 set_callback(na);
374                         };
375                         break;
376                     default:
377                         break;
378                 }
379         }
380         return 0;
381 }
382
383 int
384 ncp_args_parseopt(struct ncp_args *na, int opt, char *optarg, ncp_setopt_t *set_callback) {
385         int len;
386
387         for (; na->opt; na++) {
388                 if (na->opt != opt) continue;
389                 switch (na->at) {
390                     case NCA_STR:
391                         na->str = optarg;
392                         if (optarg) {
393                                 len = strlen(na->str);
394                                 if (len > na->ival) {
395                                         fprintf(stderr,"opt: Argument for option '%c' (%s) too long\n",na->opt,na->name);
396                                         return EINVAL;
397                                 }
398                                 set_callback(na);
399                         }
400                         break;
401                     case NCA_BOOL:
402                         na->ival = 0;
403                         set_callback(na);
404                         break;
405                     case NCA_INT:
406                         errno = 0;
407                         na->ival = strtol(optarg, NULL, 0);
408                         if (errno) {
409                                 fprintf(stderr,"opt: Invalid integer value for option '%c' (%s).\n",na->opt,na->name);
410                                 return EINVAL;
411                         }
412                         if (((na->flag & NAFL_HAVEMIN) && 
413                              (na->ival < na->min)) || 
414                             ((na->flag & NAFL_HAVEMAX) && 
415                              (na->ival > na->max))) {
416                                 fprintf(stderr,"opt: Argument for option '%c' (%s) should be in [%d-%d] range\n",na->opt,na->name,na->min,na->max);
417                                 return EINVAL;
418                         }
419                         set_callback(na);
420                         break;
421                     default:
422                         break;
423                 }
424                 break;
425         }
426         return 0;
427 }
428
429 /*
430  * Print a (descriptive) error message
431  * error values:
432  *         0 - no specific error code available;
433  *  -999..-1 - NDS error
434  *  1..32767 - system error
435  *  the rest - requester error;
436  */
437 void
438 ncp_error(const char *fmt, int error, ...) {
439         va_list ap;
440
441         fprintf(stderr, "%s: ", __progname);
442         va_start(ap, error);
443         vfprintf(stderr, fmt, ap);
444         va_end(ap);
445         if (error == -1)
446                 error = errno;
447         if (error > -1000 && error < 0) {
448                 fprintf(stderr, ": dserr = %d\n", error);
449         } else if (error & 0x8000) {
450                 fprintf(stderr, ": nwerr = %04x\n", error);
451         } else if (error) {
452                 fprintf(stderr, ": syserr = %s\n", strerror(error));
453         } else
454                 fprintf(stderr, "\n");
455 }
456
457 char *
458 ncp_printb(char *dest, int flags, const struct ncp_bitname *bnp) {
459         int first = 1;
460
461         strcpy(dest, "<");
462         for(; bnp->bn_bit; bnp++) {
463                 if (flags & bnp->bn_bit) {
464                         strcat(dest, bnp->bn_name);
465                         first = 0;
466                 }
467                 if (!first && (flags & bnp[1].bn_bit))
468                         strcat(dest, "|");
469         }
470         strcat(dest, ">");
471         return dest;
472 }