From 41cfec2c0234181158049ff25ca1f5de503d7f1a Mon Sep 17 00:00:00 2001 From: bp Date: Tue, 12 Oct 1999 11:56:41 +0000 Subject: Initial import of ncp library sources. Reviewed by: jdp, mdodd --- lib/libncp/CREDITS | 27 +++ lib/libncp/Makefile | 24 +++ lib/libncp/ipx.c | 351 ++++++++++++++++++++++++++++++++ lib/libncp/ipxsap.h | 95 +++++++++ lib/libncp/ncp_cfg.h | 9 + lib/libncp/ncp_file.h | 92 +++++++++ lib/libncp/ncp_lib.h | 258 +++++++++++++++++++++++ lib/libncp/ncp_mod.h | 16 ++ lib/libncp/ncp_rcfile.h | 64 ++++++ lib/libncp/ncpl_bind.c | 263 ++++++++++++++++++++++++ lib/libncp/ncpl_conn.c | 517 +++++++++++++++++++++++++++++++++++++++++++++++ lib/libncp/ncpl_crypt.c | 137 +++++++++++++ lib/libncp/ncpl_file.c | 263 ++++++++++++++++++++++++ lib/libncp/ncpl_misc.c | 289 ++++++++++++++++++++++++++ lib/libncp/ncpl_msg.c | 131 ++++++++++++ lib/libncp/ncpl_net.c | 150 ++++++++++++++ lib/libncp/ncpl_nls.c | 272 +++++++++++++++++++++++++ lib/libncp/ncpl_queue.c | 214 ++++++++++++++++++++ lib/libncp/ncpl_rcfile.c | 407 +++++++++++++++++++++++++++++++++++++ lib/libncp/ncpl_rpc.c | 136 +++++++++++++ lib/libncp/ncpl_subr.c | 470 ++++++++++++++++++++++++++++++++++++++++++ lib/libncp/sap.c | 302 +++++++++++++++++++++++++++ sys/netncp/ncp_cfg.h | 9 + sys/netncp/ncp_file.h | 92 +++++++++ sys/netncp/ncp_lib.h | 258 +++++++++++++++++++++++ sys/netncp/ncp_rcfile.h | 64 ++++++ 26 files changed, 4910 insertions(+) create mode 100644 lib/libncp/CREDITS create mode 100644 lib/libncp/Makefile create mode 100644 lib/libncp/ipx.c create mode 100644 lib/libncp/ipxsap.h create mode 100644 lib/libncp/ncp_cfg.h create mode 100644 lib/libncp/ncp_file.h create mode 100644 lib/libncp/ncp_lib.h create mode 100644 lib/libncp/ncp_mod.h create mode 100644 lib/libncp/ncp_rcfile.h create mode 100644 lib/libncp/ncpl_bind.c create mode 100644 lib/libncp/ncpl_conn.c create mode 100644 lib/libncp/ncpl_crypt.c create mode 100644 lib/libncp/ncpl_file.c create mode 100644 lib/libncp/ncpl_misc.c create mode 100644 lib/libncp/ncpl_msg.c create mode 100644 lib/libncp/ncpl_net.c create mode 100644 lib/libncp/ncpl_nls.c create mode 100644 lib/libncp/ncpl_queue.c create mode 100644 lib/libncp/ncpl_rcfile.c create mode 100644 lib/libncp/ncpl_rpc.c create mode 100644 lib/libncp/ncpl_subr.c create mode 100644 lib/libncp/sap.c create mode 100644 sys/netncp/ncp_cfg.h create mode 100644 sys/netncp/ncp_file.h create mode 100644 sys/netncp/ncp_lib.h create mode 100644 sys/netncp/ncp_rcfile.h diff --git a/lib/libncp/CREDITS b/lib/libncp/CREDITS new file mode 100644 index 0000000..4338055 --- /dev/null +++ b/lib/libncp/CREDITS @@ -0,0 +1,27 @@ +# $FreeBSD$ + +In the development of NetWare client for FreeBSD next sources was used: + +ncpfs for Linux - written by Volker Lendecke (lendecke@math.uni-goettingen.de), + thanks to him for giving a permission to publish his code under BSD-style + license. + +"Interrupt List" from Ralf Brown, + +Many files from the /sys directory. + +NDK documentation from Novell Inc. + + +Also thanks to thouse who gets time to testing, reporting problems and give +a good suggestions (in alphabet order): + +Anatoly A. Orehovsky +Andrew Petrenko +Jesus Rodriguez +Matthew N. Dodd +Mike Pitt +Vadim Mikhailov + + +Author - Boris Popov , diff --git a/lib/libncp/Makefile b/lib/libncp/Makefile new file mode 100644 index 0000000..b1170ba --- /dev/null +++ b/lib/libncp/Makefile @@ -0,0 +1,24 @@ +# $FreeBSD$ + +NCPLIB=${.CURDIR} + +LIB= ncp + +SHLIB_MAJOR= 1 +SHLIB_MINOR= 0 + +NOMAN= + +SRCS= ncpl_subr.c ncpl_bind.c ncpl_queue.c ncpl_file.c ncpl_misc.c \ + ncpl_net.c ncpl_rcfile.c ncpl_conn.c ncpl_nls.c ncpl_msg.c \ + ncpl_rpc.c ncpl_crypt.c ipx.c sap.c + +HEADERS=ncp_cfg.h ncp_lib.h ncp_file.h ncp_rcfile.h + +beforeinstall: +.for hdr in ${HEADERS} + install -c -o ${BINOWN} -g ${BINGRP} -m 0444 \ + ${.CURDIR}/${hdr} ${DESTDIR}/usr/include/netncp +.endfor + +.include diff --git a/lib/libncp/ipx.c b/lib/libncp/ipx.c new file mode 100644 index 0000000..9284d08 --- /dev/null +++ b/lib/libncp/ipx.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* IPX */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define IPX_NODE_LEN 6 + +typedef u_long IPXNet; +typedef u_short IPXPort; +typedef union ipx_host IPXNode; + + +void +ipx_fprint_node(FILE * file, IPXNode node){ + fprintf(file, "%02X%02X%02X%02X%02X%02X", + (unsigned char) node.c_host[0], + (unsigned char) node.c_host[1], + (unsigned char) node.c_host[2], + (unsigned char) node.c_host[3], + (unsigned char) node.c_host[4], + (unsigned char) node.c_host[5] + ); +} + +void +ipx_fprint_network(FILE * file, const IPXNet net){ + fprintf(file, "%08X", (u_int32_t)ntohl(net)); +} + +void +ipx_fprint_port(FILE * file, IPXPort port) +{ + fprintf(file, "%04X", ntohs(port)); +} + +void +ipx_fprint_addr(FILE * file, struct ipx_addr *ipx) +{ + ipx_fprint_network(file, ipx_netlong(*ipx)); + fprintf(file, ":"); + ipx_fprint_node(file, ipx->x_host); + fprintf(file, ":"); + ipx_fprint_port(file, ipx->x_port); +} + +void +ipx_print_node(IPXNode node) +{ + ipx_fprint_node(stdout, node); +} + +void +ipx_print_network(IPXNet net) +{ + ipx_fprint_network(stdout, net); +} + +void +ipx_print_port(IPXPort port) +{ + ipx_fprint_port(stdout, port); +} + +void +ipx_print_addr(struct ipx_addr *ipx) +{ + ipx_fprint_addr(stdout, ipx); +} + +int +ipx_sscanf_node(char *buf, unsigned char node[6]) +{ + int i; + int n[6]; + + if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x", + &(n[0]), &(n[1]), &(n[2]), + &(n[3]), &(n[4]), &(n[5]))) != 6) + { + return i; + } + for (i = 0; i < 6; i++) + { + node[i] = n[i]; + } + return 6; +} + +int +ipx_sscanf_saddr(char *buf, struct sockaddr_ipx *target) +{ + char *p; + struct sockaddr_ipx addr; + unsigned long sipx_net; + + addr.sipx_family = AF_IPX; +/*!! addr.sipx_type = NCP_PTYPE;*/ + + if (sscanf(buf, "%lx", &sipx_net) != 1) + { + return 1; + } + ((union ipx_net_u*)(&addr.sipx_addr.x_net))->long_e = htonl(sipx_net); + if ((p = strchr(buf, ':')) == NULL){ + return 1; + } + p += 1; + if (ipx_sscanf_node(p, addr.sipx_node) != 6) + { + return 1; + } + if ((p = strchr(p, ':')) == NULL) + { + return 1; + } + p += 1; + if (sscanf(p, "%hx", &addr.sipx_port) != 1) + { + return 1; + } + addr.sipx_port = htons(addr.sipx_port); + *target = addr; + return 0; +} + + +void ipx_assign_node(IPXNode *dest, IPXNode *src) { + memcpy(dest, src, IPX_NODE_LEN); +} + + +static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); +static int if_ipxscan __P((int addrcount, struct sockaddr_dl *sdl, struct if_msghdr *ifm, + struct ifa_msghdr *ifam,struct ipx_addr *addr)); + +/* + * Find an IPX interface. + * ifname specifies interface name, if NULL search for all interfaces + * if ifname[0]='0', also all interfaces, but return its name + * addr on input preferred net address can be specified or 0 for any, + * on return contains full address (except port) + * returns 0 if interface was found + */ +int +ipx_iffind(char *ifname,struct ipx_addr *addr){ + char name[32]; + int all=0, flags, foundit = 0, addrcount; + struct if_msghdr *ifm, *nextifm; + struct ifa_msghdr *ifam; + struct sockaddr_dl *sdl; + char *buf, *lim, *next; + size_t needed; + int mib[6]; + + if( ifname!=NULL ) { + strncpy(name,ifname,sizeof(name)-1); + if( name[0]==0 ) + all=1; + } else + all = 1; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = AF_IPX; + mib[4] = NET_RT_IFLIST; + mib[5] = 0; + + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + return(1); + if ((buf = malloc(needed)) == NULL) + return(1); + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + free(buf); + return(1); + } + lim = buf + needed; + + next = buf; + while (next < lim) { + ifm = (struct if_msghdr *)next; + if (ifm->ifm_type == RTM_IFINFO) { + sdl = (struct sockaddr_dl *)(ifm + 1); + flags = ifm->ifm_flags; + } else { + fprintf(stderr, "if_ipxfind: out of sync parsing NET_RT_IFLIST\n"); + fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO, ifm->ifm_type); + fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen); + fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next, lim); + free(buf); + return(1); + } + + next += ifm->ifm_msglen; + ifam = NULL; + addrcount = 0; + while (next < lim) { + nextifm = (struct if_msghdr *)next; + if (nextifm->ifm_type != RTM_NEWADDR) + break; + if (ifam == NULL) + ifam = (struct ifa_msghdr *)nextifm; + addrcount++; + next += nextifm->ifm_msglen; + } + + if (all) { + if ((flags & IFF_UP) == 0) + continue; /* not up */ + strncpy(name, sdl->sdl_data, sdl->sdl_nlen); + name[sdl->sdl_nlen] = '\0'; + } else { + if (strlen(name) != sdl->sdl_nlen) + continue; /* not same len */ + if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0) + continue; /* not same name */ + } + + foundit=if_ipxscan(addrcount, sdl, ifm, ifam, addr); + if( foundit ) { + if( ifname!=NULL && ifname[0]==0) { + strncpy(ifname,sdl->sdl_data, sdl->sdl_nlen); + ifname[sdl->sdl_nlen]=0; + } + break; + } + } + free(buf); + + return foundit ? 0:1; +} + + +int +if_ipxscan(addrcount, sdl, ifm, ifam, addr) + int addrcount; + struct sockaddr_dl *sdl; + struct if_msghdr *ifm; + struct ifa_msghdr *ifam; + struct ipx_addr *addr; +{ + struct rt_addrinfo info; + struct sockaddr_ipx *sipx; + int s; + + if ((s = socket(AF_IPX, SOCK_DGRAM, 0)) < 0) { + perror("ifconfig: socket"); + return 0; + } + + while (addrcount > 0) { + info.rti_addrs = ifam->ifam_addrs; + /* Expand the compacted addresses */ + rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info); + addrcount--; + ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); + if (info.rti_info[RTAX_IFA]->sa_family == AF_IPX) { + sipx = (struct sockaddr_ipx *)info.rti_info[RTAX_IFA]; + if( ipx_nullnet(sipx->sipx_addr) ) continue; + if( ipx_nullnet(*addr) || + ipx_neteq(sipx->sipx_addr,*addr) ) { + *addr=sipx->sipx_addr; + close(s); + return(1); + } + } + } + close(s); + return(0); +} +/* + * Expand the compacted form of addresses as returned via the + * configuration read via sysctl(). + */ + +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +static void +rt_xaddrs(cp, cplim, rtinfo) + caddr_t cp, cplim; + struct rt_addrinfo *rtinfo; +{ + struct sockaddr *sa; + int i; + + memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); + for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { + if ((rtinfo->rti_addrs & (1 << i)) == 0) + continue; + rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; + ADVANCE(cp, sa); + } +} + diff --git a/lib/libncp/ipxsap.h b/lib/libncp/ipxsap.h new file mode 100644 index 0000000..2d8d7f0 --- /dev/null +++ b/lib/libncp/ipxsap.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef _IPXSAP_H_ +#define _IPXSAP_H_ + +#define IPX_SAP_GENERAL_QUERY 1 +#define IPX_SAP_GENERAL_RESPONSE 2 +#define IPX_SAP_NEAREST_QUERY 3 +#define IPX_SAP_NEAREST_RESPONSE 4 + + +#define IPX_SAP_MAX_ENTRIES 7 +#define IPX_SAP_SERVER_DOWN 16 +#define IPX_SAP_SERVER_NAME_LEN 48 +#define IPX_SAP_REQUEST_LEN 4 + +/* Values for server_type */ +#define IPX_SAP_FILE_SERVER 4 + +struct sap_query { + u_short query_type; /* net order */ + u_short server_type; /* net order */ +}; + +struct sap_entry { + u_short server_type; + u_char server_name[IPX_SAP_SERVER_NAME_LEN]; + struct ipx_addr ipx; + u_short hops; +}; + +struct sap_packet { + u_short operation; + struct sap_entry sap_entries[1]; +}; + +struct sap_rq { + struct sockaddr_ipx dest_addr; + int sock; + int entries; + struct sap_packet* buffer; +}; +/* +#define sap_name_equal(n1,n2) (strncmp(n1,n2,IPX_SAP_SERVER_NAME_LEN) == 0); +#define sap_type_equal(t1,t2) (t1==IPX_SAP_GENERAL_RQ || t2==IPX_SAP_GENERAL_RQ || t1==t2); +*/ +void sap_copy_name(char *dest,char *src); +int sap_getsock(int *rsock); + + +int sap_rq_init(struct sap_rq* out,int sock); +int sap_rq_flush(struct sap_rq* out); +void sap_rq_general(struct sap_rq* out,u_short ser_type); +void sap_rq_gns_request(struct sap_rq* out,u_short ser_type); +void sap_rq_response(struct sap_rq* out,u_short type,char *name,struct sockaddr_ipx* addr,u_short hops,int down_allow); +void sap_rq_gns_response(struct sap_rq* out,u_short type,char * name,struct sockaddr_ipx* addr,u_short hops); +void sap_rq_set_destination(struct sap_rq* out,struct ipx_addr *dest); + +int sap_find_nearest(int server_type, struct sockaddr_ipx *result,char *server_name); + +extern int (*sap_sendto_func)(void* buffer,int size,struct sockaddr_ipx* daddr,int sock); +int ipx_iffind(char *ifname, struct ipx_addr *addr); + +#endif /* !_IPXSAP_H_ */ diff --git a/lib/libncp/ncp_cfg.h b/lib/libncp/ncp_cfg.h new file mode 100644 index 0000000..82a30d7 --- /dev/null +++ b/lib/libncp/ncp_cfg.h @@ -0,0 +1,9 @@ +/* + * static configuration for libncp + * + * $FreeBSD$ + */ + +#define NCP_NLS_KOI2CP866 +#define NCP_NLS_DEFAULT NCP_NLS_KOI_866 +#define NCP_PREFIX "" diff --git a/lib/libncp/ncp_file.h b/lib/libncp/ncp_file.h new file mode 100644 index 0000000..17b5bd5 --- /dev/null +++ b/lib/libncp/ncp_file.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _NCP_NCP_FILE_H_ +#define _NCP_NCP_FILE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + nuint32 sequence; + nuint32 parent; + nuint32 attributes; + nuint8 uniqueID; + nuint8 flags; + nuint8 nameSpace; + nuint8 nameLength; + nuint8 name [256]; + nuint32 creationDateAndTime; + nuint32 ownerID; + nuint32 lastArchiveDateAndTime; + nuint32 lastArchiverID; + nuint32 updateDateAndTime; + nuint32 updatorID; + nuint32 fileSize; + nuint8 reserved[44]; + nuint16 inheritedRightsMask; + nuint16 lastAccessDate; + nuint32 deletedTime; + nuint32 deletedDateAndTime; + nuint32 deletorID; + nuint8 reserved3 [16]; +} __attribute__((packed)) NWDELETED_INFO; + +int ncp_AllocTempDirHandle(char *path, NWDIR_HANDLE *pdh); +int ncp_DeallocateDirHandle(NWDIR_HANDLE dh); +int ncp_GetNSEntryInfo(NWDIR_HANDLE dh, struct nw_entry_info *fi, int *ns); + +NWCCODE ncp_ScanNSEntryInfo(NWCONN_HANDLE cH, nuint8 namSpc, nuint16 attrs, + SEARCH_SEQUENCE *seq, pnstr8 searchPattern, nuint32 retInfoMask, + NW_ENTRY_INFO *entryInfo); + +NWCCODE ncp_PurgeDeletedFile(NWCONN_HANDLE cH, nuint32 iterHandle, + nuint32 volNum, nuint32 dirBase, nuint8 ns); + +NWCCODE NWRecoverDeletedFile(NWCONN_HANDLE conn, NWDIR_HANDLE dirHandle, + nuint32 iterHandle, + nuint32 volNum, nuint32 dirBase, + pnstr8 delFileName, pnstr8 rcvrFileName); + +NWCCODE ncp_ScanForDeletedFiles(NWCONN_HANDLE cH, pnuint32 iterHandle, + pnuint32 volNum, pnuint32 dirBase, nuint8 ns, + NWDELETED_INFO *entryInfo); + + +#ifdef __cplusplus +} +#endif + +#endif /* _NCP_NCP_FILE_ */ diff --git a/lib/libncp/ncp_lib.h b/lib/libncp/ncp_lib.h new file mode 100644 index 0000000..bff6339 --- /dev/null +++ b/lib/libncp/ncp_lib.h @@ -0,0 +1,258 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _NCP_LIB_H_ +#define _NCP_LIB_H_ + +#define IPX +#define INET + +#include +#include +#include +#include + +#define ncp_printf printf + +#define sipx_cnetwork sipx_addr.x_net.c_net +#define sipx_node sipx_addr.x_host.c_host +#define ipx_netlong(iaddr) (((union ipx_net_u *)(&((iaddr).x_net)))->long_e) + +#define STDPARAM_ARGS 'A':case 'B':case 'C':case 'I':case 'M': \ + case 'N':case 'U':case 'R':case 'S':case 'T': \ + case 'W':case 'O':case 'P' + +#define STDPARAM_OPT "A:BCI:M:N:O:P:U:R:S:T:W:" + +#ifndef min +#define min(a,b) (((a)<(b)) ? (a) : (b)) +#endif + + +/* + * An attempt to do a unified options parser + */ +enum ncp_argtype {NCA_STR,NCA_INT,NCA_BOOL}; + +struct ncp_args; + +typedef int ncp_setopt_t (struct ncp_args*); + +#define NAFL_NONE 0x0000 +#define NAFL_HAVEMIN 0x0001 +#define NAFL_HAVEMAX 0x0002 +#define NAFL_MINMAX NAFL_HAVEMIN | NAFL_HAVEMAX + +struct ncp_args { + enum ncp_argtype at; + int opt; /* command line option */ + char *name; /* rc file equiv */ + int flag; /* NAFL_* */ + int ival; /* int/bool values, or max len for str value */ + char *str; /* string value */ + int min; /* min for ival */ + int max; /* max for ival */ + ncp_setopt_t *fn;/* call back to validate */ +}; + +typedef struct { + nuint8 day; + nuint8 month; + nuint16 year; +} NW_DATE; + +/* hours is a nuint16 so that this structure will be the same length as a dword */ +typedef struct { + nuint8 seconds; + nuint8 minutes; + nuint16 hours; +} NW_TIME; + +struct ncp_bitname { + u_int bn_bit; + char *bn_name; +}; + +int ncp_args_parserc(struct ncp_args *na, char *sect, ncp_setopt_t *set_callback); +int ncp_args_parseopt(struct ncp_args *na, int opt, char *optarg, ncp_setopt_t *set_callback); + + +struct sockaddr_ipx; +struct ipx_addr; +struct sockaddr; +struct ncp_buf; +struct rcfile; + +int ncp_initlib(void); +int ncp_connect(struct ncp_conn_args *li, int *connHandle); +int ncp_connect_addr(struct sockaddr *sa, NWCONN_HANDLE *chp); +int ncp_disconnect(int connHandle); +int ncp_request(int connHandle,int function, struct ncp_buf *ncpbuf); +int ncp_conn_request(int connHandle, struct ncp_buf *ncpbuf); +int ncp_login(int connHandle, const char *user, int objtype, const char *password); +int ncp_conn_scan(struct ncp_conn_loginfo *li, int *connHandle); +int ncp_conn_cnt(void); +void *ncp_conn_list(void); +int ncp_conn_getinfo(int connHandle, struct ncp_conn_stat *ps); +int ncp_conn_getuser(int connHandle, char **user); +int ncp_conn2ref(int connHandle, int *connRef); +int ncp_conn_dup(NWCONN_HANDLE org, NWCONN_HANDLE *res); +int ncp_path2conn(char *path, int *connHandle); +int ncp_li_init(struct ncp_conn_loginfo *li, int argc, char *argv[]); +void ncp_li_done(struct ncp_conn_loginfo *li); +int ncp_li_login(struct ncp_conn_loginfo *li, int *aconnHandle); +int ncp_li_readrc(struct ncp_conn_loginfo *li); +int ncp_li_check(struct ncp_conn_loginfo *li); +int ncp_li_arg(struct ncp_conn_loginfo *li, int opt, char *arg); +int ncp_li_setserver(struct ncp_conn_loginfo *li, const char *arg); +int ncp_li_setuser(struct ncp_conn_loginfo *li, char *arg); +int ncp_li_setpassword(struct ncp_conn_loginfo *li, const char *passwd); +int ncp_conn_setflags(int connHandle, u_int16_t mask, u_int16_t flags); +int ncp_conn_find(char *server, char *user); +NWCCODE NWRequest(NWCONN_HANDLE cH, nuint16 fn, + nuint16 nrq, NW_FRAGMENT* rq, + nuint16 nrp, NW_FRAGMENT* rp) ; + +#define ncp_setpermanent(connHandle,on) ncp_conn_setflags(connHandle, NCPFL_PERMANENT, (on) ? NCPFL_PERMANENT : 0) +#define ncp_setprimary(connHandle,on) ncp_conn_setflags(connHandle, NCPFL_PRIMARY, (on) ? NCPFL_PRIMARY : 0) + +int ncp_find_fileserver(struct ncp_conn_loginfo *li, int af,char *name); +int ncp_find_server(struct ncp_conn_loginfo *li, int type, int af,char *name); + +/* misc rotines */ +char* ncp_str_upper(char *name); +int ncp_open_rcfile(void); +int ncp_getopt(int nargc, char * const *nargv, const char *ostr); +void NWUnpackDateTime(nuint32 dateTime, NW_DATE *sDate, NW_TIME *sTime); +void NWUnpackDate(nuint16 date, NW_DATE *sDate); +void NWUnpackTime(nuint16 time, NW_TIME *sTime); +time_t ncp_UnpackDateTime(nuint32 dateTime); +int ncp_GetFileServerDateAndTime(NWCONN_HANDLE cH, time_t *target); +int ncp_SetFileServerDateAndTime(NWCONN_HANDLE cH, time_t * source); +NWCCODE NWDownFileServer(NWCONN_HANDLE cH, int force); +NWCCODE NWCloseBindery(NWCONN_HANDLE cH); +NWCCODE NWOpenBindery(NWCONN_HANDLE cH); +NWCCODE NWDisableTTS(NWCONN_HANDLE cH); +NWCCODE NWEnableTTS(NWCONN_HANDLE cH); +NWCCODE NWDisableFileServerLogin(NWCONN_HANDLE cH); +NWCCODE NWEnableFileServerLogin(NWCONN_HANDLE cH); +void ncp_error(char *fmt, int error,...); +char *ncp_printb(char *dest, int flags, const struct ncp_bitname *bnp); +void nw_keyhash(const u_char *key, const u_char *buf, int buflen, u_char *target); +void nw_encrypt(const u_char *fra, const u_char *buf, u_char *target); +void ipx_print_addr(struct ipx_addr *ipx); + +/* bindery calls */ +int ncp_get_bindery_object_id(int connHandle, u_int16_t object_type, const char *object_name, + struct ncp_bindery_object *target); +int ncp_get_bindery_object_name(int connHandle, u_int32_t object_id, + struct ncp_bindery_object *target); +int ncp_scan_bindery_object(int connHandle, u_int32_t last_id, u_int16_t object_type, + char *search_string, struct ncp_bindery_object *target); +int ncp_read_property_value(int connHandle,int object_type, const char *object_name, + int segment, const char *prop_name, struct nw_property *target); +void shuffle(const u_char *lon, const u_char *buf, int buflen, u_char *target); +int ncp_get_encryption_key(NWCONN_HANDLE cH, char *target); +int ncp_change_obj_passwd(NWCONN_HANDLE connid, + const struct ncp_bindery_object *object, + const u_char *key, + const u_char *oldpasswd, const u_char *newpasswd); +int ncp_keyed_verify_password(NWCONN_HANDLE cH, char *key, char *passwd, + struct ncp_bindery_object *objinfo); + +/* queue calls */ +int ncp_create_queue_job_and_file(int connHandle, u_int32_t queue_id, struct queue_job *job); +int ncp_close_file_and_start_job(int connHandle, u_int32_t queue_id, struct queue_job *job); +int ncp_attach_to_queue(int connHandle, u_int32_t queue_id); +int ncp_detach_from_queue(int connHandle, u_int32_t queue_id); +int ncp_service_queue_job(int connHandle, u_int32_t queue_id, u_int16_t job_type, + struct queue_job *job); +int ncp_finish_servicing_job(int connHandle, u_int32_t queue_id, u_int32_t job_number, + u_int32_t charge_info); +int ncp_abort_servicing_job(int connHandle, u_int32_t queue_id, u_int32_t job_number); +int ncp_get_queue_length(int connHandle, u_int32_t queue_id, u_int32_t *queue_length); +int ncp_get_queue_job_ids(int connHandle, u_int32_t queue_id, u_int32_t queue_section, + u_int32_t *length1, u_int32_t *length2, u_int32_t ids[]); +int ncp_get_queue_job_info(int connHandle, u_int32_t queue_id, u_int32_t job_id, + struct nw_queue_job_entry *jobdata); +/* + * file system and volume calls + */ +int ncp_read(int connHandle, ncp_fh *fh, off_t offset, size_t count, char *target); +int ncp_write(int connHandle, ncp_fh *fh, off_t offset, size_t count, char *source); +int ncp_geteinfo(char *path, struct nw_entry_info *fi); +int ncp_NSEntryInfo(NWCONN_HANDLE cH, nuint8 ns, nuint8 vol, nuint32 dirent, + NW_ENTRY_INFO *entryInfo); + +NWCCODE NWGetVolumeName(NWCONN_HANDLE cH, u_char volume, char *name); + +/* misc ncp calls */ +int ncp_get_file_server_information(int connHandle, struct ncp_file_server_info *target); +int ncp_get_stations_logged_info(int connHandle, u_int32_t connection, + struct ncp_bindery_object *target, time_t *login_time); +int ncp_get_internet_address(int connHandle, u_int32_t connection, struct ipx_addr *target, + u_int8_t * conn_type); +NWCCODE NWGetObjectConnectionNumbers(NWCONN_HANDLE connHandle, + pnstr8 pObjName, nuint16 objType, + pnuint16 pNumConns, pnuint16 pConnHandleList, + nuint16 maxConns); +/* + * Message broadcast + */ +NWCCODE NWDisableBroadcasts(NWCONN_HANDLE connHandle); +NWCCODE NWEnableBroadcasts(NWCONN_HANDLE connHandle); +NWCCODE NWBroadcastToConsole(NWCONN_HANDLE connHandle, pnstr8 message); +NWCCODE NWSendBroadcastMessage(NWCONN_HANDLE connHandle, pnstr8 message, + nuint16 connCount, pnuint16 connList, pnuint8 resultList); +NWCCODE NWGetBroadcastMessage(NWCONN_HANDLE connHandle, pnstr8 message); + +/* + * RPC calls + */ +NWCCODE NWSMExecuteNCFFile(NWCONN_HANDLE cH, pnstr8 NCFFileName); +NWCCODE NWSMLoadNLM(NWCONN_HANDLE cH, pnstr8 cmd); +NWCCODE NWSMUnloadNLM(NWCONN_HANDLE cH, pnstr8 cmd); +NWCCODE NWSMMountVolume(NWCONN_HANDLE cH, pnstr8 volName, nuint32* volnum); +NWCCODE NWSMDismountVolumeByName(NWCONN_HANDLE cH, pnstr8 vol); +NWCCODE NWSMSetDynamicCmdIntValue(NWCONN_HANDLE cH, pnstr8 setCommandName, nuint32 cmdValue); +NWCCODE NWSMSetDynamicCmdStrValue(NWCONN_HANDLE cH, pnstr8 setCommandName, pnstr8 cmdValue); + +int dostat(int modnum, char *modname, int *offset); + +extern int ncp_opterr, ncp_optind, ncp_optopt, ncp_optreset; +extern char *ncp_optarg; + +extern struct rcfile *ncp_rc; +extern int sysentoffset; +#endif /* _NCP_LIB_H_ */ diff --git a/lib/libncp/ncp_mod.h b/lib/libncp/ncp_mod.h new file mode 100644 index 0000000..4bdc39a --- /dev/null +++ b/lib/libncp/ncp_mod.h @@ -0,0 +1,16 @@ +/* + * Describes all ncp_lib kernel functions + * + * $FreeBSD$ + */ +#ifndef _NCP_MOD_H_ +#define _NCP_MOD_H_ + +/* order of calls in syscall table relative to offset in system table */ +#define NCP_SE(callno) (callno+sysentoffset) +#define NCP_CONNSCAN NCP_SE(0) +#define NCP_CONNECT NCP_SE(1) +#define NCP_INTFN NCP_SE(2) +#define SNCP_REQUEST NCP_SE(3) + +#endif /* !_NCP_MOD_H_ */ \ No newline at end of file diff --git a/lib/libncp/ncp_rcfile.h b/lib/libncp/ncp_rcfile.h new file mode 100644 index 0000000..bbdf8eb --- /dev/null +++ b/lib/libncp/ncp_rcfile.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef _NCP_RCFILE_H_ +#define _NCP_RCFILE_H_ +#include + +struct rckey { + SLIST_ENTRY(rckey) rk_next; + char *rk_name; + char *rk_value; +}; + +struct rcsection { + SLIST_ENTRY(rcsection) rs_next; + SLIST_HEAD(rckey_head,rckey) rs_keys; + char *rs_name; +}; + +struct rcfile { + SLIST_ENTRY(rcfile) rf_next; + SLIST_HEAD(rcsec_head, rcsection) rf_sect; + char *rf_name; + FILE *rf_f; +}; + +int rc_open(char *filename,char *mode,struct rcfile **rcfile); +int rc_close(struct rcfile *rcp); +int rc_getstringptr(struct rcfile *rcp,char *section, char *key,char **dest); +int rc_getstring(struct rcfile *rcp,char *section, char *key,int maxlen,char *dest); +int rc_getint(struct rcfile *rcp,char *section, char *key,int *value); +int rc_getbool(struct rcfile *rcp,char *section, char *key,int *value); + +#endif /* _NCP_RCFILE_H_ */ diff --git a/lib/libncp/ncpl_bind.c b/lib/libncp/ncpl_bind.c new file mode 100644 index 0000000..40d0b73 --- /dev/null +++ b/lib/libncp/ncpl_bind.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include +#include +#include +#include + +static void nw_passencrypt(char *old, char *new, char *out); + +int +ncp_get_bindery_object_id(int connid, u_int16_t object_type, const char *object_name, + struct ncp_bindery_object *target) { + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 53); + ncp_add_word_hl(conn, object_type); + ncp_add_pstring(conn, object_name); + + if ((error = ncp_request(connid, 23, conn)) != 0) { + return error; + } + if (conn->rpsize < 54) { + return EACCES; + } + target->object_id = ncp_reply_dword_hl(conn, 0); + target->object_type = ncp_reply_word_hl(conn, 4); + memcpy(target->object_name, ncp_reply_data(conn, 6), 48); + return 0; +} + +int +ncp_read_property_value(int connid, int object_type, const char *object_name, + int segment, const char *prop_name, + struct nw_property *target) +{ + int error; + struct ncp_buf conn; + ncp_init_request_s(&conn, 61); + ncp_add_word_hl(&conn, object_type); + ncp_add_pstring(&conn, object_name); + ncp_add_byte(&conn, segment); + ncp_add_pstring(&conn, prop_name); + + if ((error = ncp_request(connid,23,&conn)) != 0) { + return error; + } + memcpy(&(target->value), ncp_reply_data(&conn, 0), 128); + target->more_flag = ncp_reply_byte(&conn, 128); + target->property_flag = ncp_reply_byte(&conn, 129); + return 0; +} + +int +ncp_scan_bindery_object(int connid, u_int32_t last_id, u_int16_t object_type, + char *search_string, struct ncp_bindery_object *target) +{ + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 55); + ncp_add_dword_hl(conn, last_id); + ncp_add_word_hl(conn, object_type); + ncp_add_pstring(conn, search_string); + error = ncp_request(connid, 23, conn); + if (error) return error; + target->object_id = ncp_reply_dword_hl(conn, 0); + target->object_type = ncp_reply_word_hl(conn, 4); + memcpy(target->object_name, ncp_reply_data(conn, 6),NCP_BINDERY_NAME_LEN); + target->object_flags = ncp_reply_byte(conn, 54); + target->object_security = ncp_reply_byte(conn, 55); + target->object_has_prop = ncp_reply_byte(conn, 56); + return 0; +} + +int +ncp_get_bindery_object_name(int connid, u_int32_t object_id, + struct ncp_bindery_object *target) { + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 54); + ncp_add_dword_hl(conn, object_id); + if ((error = ncp_request(connid, 23, conn)) != 0) + return error; + target->object_id = ncp_reply_dword_hl(conn, 0); + target->object_type = ncp_reply_word_hl(conn, 4); + memcpy(target->object_name, ncp_reply_data(conn, 6), 48); + return 0; +} + +int +ncp_change_obj_passwd(NWCONN_HANDLE connid, + const struct ncp_bindery_object *object, + const u_char *key, + const u_char *oldpasswd, + const u_char *newpasswd) +{ + long id = htonl(object->object_id); + u_char cryptkey[8]; + u_char newpwd[16]; /* new passwd as stored by server */ + u_char oldpwd[16]; /* old passwd as stored by server */ + u_char len; + DECLARE_RQ; + + memcpy(cryptkey, key, 8); + nw_keyhash((u_char *)&id, oldpasswd, strlen(oldpasswd), oldpwd); + nw_keyhash((u_char *)&id, newpasswd, strlen(newpasswd), newpwd); + nw_encrypt(cryptkey, oldpwd, cryptkey); + nw_passencrypt(oldpwd, newpwd, newpwd); + nw_passencrypt(oldpwd + 8, newpwd + 8, newpwd + 8); + if ((len = strlen(newpasswd)) > 63) { + len = 63; + } + len = ((len ^ oldpwd[0] ^ oldpwd[1]) & 0x7f) | 0x40; + + ncp_init_request_s(conn, 75); + ncp_add_mem(conn, cryptkey, 8); + ncp_add_word_hl(conn, object->object_type); + ncp_add_pstring(conn, object->object_name); + ncp_add_byte(conn, len); + ncp_add_mem(conn, newpwd, 16); + return ncp_request(connid, 23, conn); +} + +/* + * target is a 8-byte buffer + */ +int +ncp_get_encryption_key(NWCONN_HANDLE cH, char *target) { + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 23); + + error = ncp_request(cH, 23, conn); + if (error) + return error; + if (conn->rpsize < 8) + return EACCES; + memcpy(target, ncp_reply_data(conn, 0), 8); + return 0; +} + +int +ncp_keyed_verify_password(NWCONN_HANDLE cH, char *key, char *passwd, + struct ncp_bindery_object *objinfo) { + u_long id = htonl(objinfo->object_id); + u_char cryptkey[8]; + u_char buf[128]; + DECLARE_RQ; + + nw_keyhash((u_char *)&id, passwd, strlen(passwd), buf); + nw_encrypt(key, buf, cryptkey); + + ncp_init_request_s(conn, 74); + ncp_add_mem(conn, cryptkey, sizeof(cryptkey)); + ncp_add_word_hl(conn, objinfo->object_type); + ncp_add_pstring(conn, objinfo->object_name); + + return ncp_request(cH, 23, conn); +} + +static char passkeys[256 + 16] = { + 0x0f, 0x08, 0x05, 0x07, 0x0c, 0x02, 0x0e, 0x09, + 0x00, 0x01, 0x06, 0x0d, 0x03, 0x04, 0x0b, 0x0a, + 0x02, 0x0c, 0x0e, 0x06, 0x0f, 0x00, 0x01, 0x08, + 0x0d, 0x03, 0x0a, 0x04, 0x09, 0x0b, 0x05, 0x07, + 0x05, 0x02, 0x09, 0x0f, 0x0c, 0x04, 0x0d, 0x00, + 0x0e, 0x0a, 0x06, 0x08, 0x0b, 0x01, 0x03, 0x07, + 0x0f, 0x0d, 0x02, 0x06, 0x07, 0x08, 0x05, 0x09, + 0x00, 0x04, 0x0c, 0x03, 0x01, 0x0a, 0x0b, 0x0e, + 0x05, 0x0e, 0x02, 0x0b, 0x0d, 0x0a, 0x07, 0x00, + 0x08, 0x06, 0x04, 0x01, 0x0f, 0x0c, 0x03, 0x09, + 0x08, 0x02, 0x0f, 0x0a, 0x05, 0x09, 0x06, 0x0c, + 0x00, 0x0b, 0x01, 0x0d, 0x07, 0x03, 0x04, 0x0e, + 0x0e, 0x08, 0x00, 0x09, 0x04, 0x0b, 0x02, 0x07, + 0x0c, 0x03, 0x0a, 0x05, 0x0d, 0x01, 0x06, 0x0f, + 0x01, 0x04, 0x08, 0x0a, 0x0d, 0x0b, 0x07, 0x0e, + 0x05, 0x0f, 0x03, 0x09, 0x00, 0x02, 0x06, 0x0c, + 0x05, 0x03, 0x0c, 0x08, 0x0b, 0x02, 0x0e, 0x0a, + 0x04, 0x01, 0x0d, 0x00, 0x06, 0x07, 0x0f, 0x09, + 0x06, 0x00, 0x0b, 0x0e, 0x0d, 0x04, 0x0c, 0x0f, + 0x07, 0x02, 0x08, 0x0a, 0x01, 0x05, 0x03, 0x09, + 0x0b, 0x05, 0x0a, 0x0e, 0x0f, 0x01, 0x0c, 0x00, + 0x06, 0x04, 0x02, 0x09, 0x03, 0x0d, 0x07, 0x08, + 0x07, 0x02, 0x0a, 0x00, 0x0e, 0x08, 0x0f, 0x04, + 0x0c, 0x0b, 0x09, 0x01, 0x05, 0x0d, 0x03, 0x06, + 0x07, 0x04, 0x0f, 0x09, 0x05, 0x01, 0x0c, 0x0b, + 0x00, 0x03, 0x08, 0x0e, 0x02, 0x0a, 0x06, 0x0d, + 0x09, 0x04, 0x08, 0x00, 0x0a, 0x03, 0x01, 0x0c, + 0x05, 0x0f, 0x07, 0x02, 0x0b, 0x0e, 0x06, 0x0d, + 0x09, 0x05, 0x04, 0x07, 0x0e, 0x08, 0x03, 0x01, + 0x0d, 0x0b, 0x0c, 0x02, 0x00, 0x0f, 0x06, 0x0a, + 0x09, 0x0a, 0x0b, 0x0d, 0x05, 0x03, 0x0f, 0x00, + 0x01, 0x0c, 0x08, 0x07, 0x06, 0x04, 0x0e, 0x02, + 0x03, 0x0e, 0x0f, 0x02, 0x0d, 0x0c, 0x04, 0x05, + 0x09, 0x06, 0x00, 0x01, 0x0b, 0x07, 0x0a, 0x08 +}; + +static void +nw_passencrypt(char *old, char *new, char *out) +{ + char *p, v; + char copy[8]; + int i, di, ax; + +#define HIGH(x) (((x) >> 4) & 0xf) +#define LOW(x) ((x) & 0xf) + memcpy(copy, new, 8); + + for (i = 0; i < 16; i++) { + for (di = 0, ax = 0, p = old; di < 8; di++, ax += 0x20, p++) { + v = copy[di] ^ *p; + copy[di] = (passkeys[HIGH(v) + ax + 0x10] << 4) | + passkeys[LOW(v) + ax]; + } + v = old[7]; + for (p = old + 7; p > old; p--) { + *p = HIGH(p[-1]) | ((*p) << 4); + } + *old = HIGH(v) | (*old) << 4; + bzero(out, 8); + + for (di = 0; di < 16; di++) { + v = passkeys[di + 0x100]; + v = (v & 1) ? HIGH(copy[v / 2]) : LOW(copy[v / 2]); + out[di / 2] |= ((di & 1) ? v << 4 : v); + } + memcpy(copy, out, 8); + } +} diff --git a/lib/libncp/ncpl_conn.c b/lib/libncp/ncpl_conn.c new file mode 100644 index 0000000..df95807 --- /dev/null +++ b/lib/libncp/ncpl_conn.c @@ -0,0 +1,517 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * + * Current scheme to create/open connection: + * 1. ncp_li_init() - lookup -S [-U] options in command line + * 2. ncp_li_init() - try to find existing connection + * 3. ncp_li_init() - if no server name and no accessible connections - bail out + * 4. This is connection candidate, read .rc file, override with command line + * and go ahead + * Note: connection referenced only via ncp_login() call. Although it is + * possible to get connection handle in other way, it will be unwise to use + * it, since conn can be destroyed at any time. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static char *server_name; /* need a better way ! */ + + + +int +ncp_li_setserver(struct ncp_conn_loginfo *li, const char *arg) { + if (strlen(arg) >= NCP_BINDERY_NAME_LEN) { + fprintf(stderr, "Server name too long:%s\n", arg); + return ENAMETOOLONG; + } + ncp_str_upper(strcpy(li->server, arg)); + return 0; +} + +int +ncp_li_setuser(struct ncp_conn_loginfo *li, char *arg) { + if (arg && strlen(arg) >= NCP_BINDERY_NAME_LEN) { + fprintf(stderr, "User name too long:%s\n", arg); + return ENAMETOOLONG; + } + if (li->user) + free(li->user); + if (arg) { + li->user = strdup(arg); + if (li->user == NULL) + return ENOMEM; + ncp_str_upper(li->user); + } else + li->user = NULL; + return 0; +} + +int +ncp_li_setpassword(struct ncp_conn_loginfo *li, const char *passwd) { + if (passwd && strlen(passwd) >= 127) { + fprintf(stderr, "Password too long:%s\n", passwd); + return ENAMETOOLONG; + } + if (li->password) { + bzero(li->password, strlen(li->password)); + free(li->password); + } + if (passwd) { + li->password = strdup(passwd); + if (li->password == NULL) + return ENOMEM; + } else + li->password = NULL; + return 0; +} +/* + * Prescan command line for [-S server] [-U user] arguments + * and fill li structure with defaults + */ +int +ncp_li_init(struct ncp_conn_loginfo *li, int argc, char *argv[]) { + int opt, error = 0; + char *arg; + + bzero(li,sizeof(*li)); + li->timeout = 15; /* these values should be large enough to handle */ + li->retry_count = 4; /* slow servers, even on ethernet */ + li->access_mode = 0; + li->password = NULL; + li->sig_level = 1; + li->objtype = NCP_BINDERY_USER; + li->owner = NCP_DEFAULT_OWNER; + li->group = NCP_DEFAULT_GROUP; + server_name = NULL; + if (argv == NULL) return 0; + while ((opt = ncp_getopt(argc, argv, ":S:U:")) != -1) { + arg = ncp_optarg; + switch (opt) { + case 'S': + error = ncp_li_setserver(li, arg); + break; + case 'U': + error = ncp_li_setuser(li, arg); + break; + } + } + ncp_optind = ncp_optreset = 1; + return error; +} + +void +ncp_li_done(struct ncp_conn_loginfo *li) { + if (li->user) + free(li->user); + if (li->password) + free(li->password); +} + +/* + * Lookup existing connection based on li structure, if connection + * found, it will be referenced. Otherwise full login sequence performed. + */ +int +ncp_li_login(struct ncp_conn_loginfo *li, int *aconnid) { + int connHandle, error; + + if ((error = ncp_conn_scan(li, &connHandle)) == 0) { + *aconnid = connHandle; + return 0; + } + error = ncp_connect(li, &connHandle); + if (error) return errno; + error = ncp_login(connHandle, li->user, li->objtype, li->password); + if (error) { + ncp_disconnect(connHandle); + } else + *aconnid = connHandle; + return error; +} + +/* + * read rc file as follows: + * 1. read [server] section + * 2. override with [server:user] section + * Since abcence of rcfile is not a bug, silently ignore that fact. + * rcfile never closed to reduce number of open/close operations. + */ +int +ncp_li_readrc(struct ncp_conn_loginfo *li) { + int i, val, error; + char uname[NCP_BINDERY_NAME_LEN*2+1]; + char *sect = NULL, *p; + + /* + * if info from cmd line incomplete, try to find existing + * connection and fill server/user from it. + */ + if (li->server[0] == 0 || li->user == NULL) { + int connHandle; + struct ncp_conn_stat cs; + + if ((error = ncp_conn_scan(li, &connHandle)) != 0) { + fprintf(stderr, "no default connection found: %s\n",strerror(errno)); + return error; + } + ncp_conn_getinfo(connHandle, &cs); + ncp_li_setserver(li, cs.li.server); + ncp_li_setuser(li, cs.user); + ncp_li_setpassword(li, ""); + ncp_disconnect(connHandle); + } + if (ncp_open_rcfile()) return 0; + + for (i = 0; i < 2; i++) { + switch (i) { + case 0: + sect = li->server; + break; + case 1: + strcat(strcat(strcpy(uname,li->server),":"),li->user ? li->user : "default"); + sect = uname; + break; + } + rc_getstringptr(ncp_rc, sect, "password", &p); + if (p) + ncp_li_setpassword(li, p); + rc_getint(ncp_rc,sect, "timeout", &li->timeout); + rc_getint(ncp_rc,sect, "retry_count", &li->retry_count); + rc_getint(ncp_rc,sect, "sig_level", &li->sig_level); + if (rc_getint(ncp_rc,sect,"access_mode",&val) == 0) + li->access_mode = val; + if(rc_getbool(ncp_rc,sect,"bindery",&val) == 0 && val) { + li->opt |= NCP_OPT_BIND; + } + } + return 0; +} + +/* + * check for all uncompleted fields + */ +int +ncp_li_check(struct ncp_conn_loginfo *li) { + int error = 0; + char *p; + + do { + if (li->server[0] == 0) { + fprintf(stderr, "no server name specified\n"); + error = 1; + break; + } + error = ncp_find_fileserver(li, + (server_name==NULL) ? AF_IPX : AF_INET, server_name); + if (error) { + fprintf(stderr,"Can't find server %s, error=%s\n",li->server,strerror(errno)); + break; + } + if (li->user == NULL || li->user[0] == 0) { + fprintf(stderr, "no user name specified for server %s\n",li->server); + error = 1; + break; + } + if (li->password == NULL) { + p = getpass("Netware password:"); + error = ncp_li_setpassword(li, p) ? 1 : 0; + } + } while (0); + return error; +} + +int +ncp_conn_cnt(void) { + int error, cnt = 0, len = sizeof(cnt); + +#if __FreeBSD_version < 400001 + error = sysctlbyname("net.ipx.ncp.conn_cnt", &cnt, &len, NULL, 0); +#else + error = sysctlbyname("net.ncp.conn_cnt", &cnt, &len, NULL, 0); +#endif + if (error) cnt = 0; + return cnt; +} + +/* + * Find an existing connection and reference it + */ +int +ncp_conn_find(char *server,char *user) { + struct ncp_conn_args ca; + int connid, error; + + if (server == NULL && user == NULL) { + error = ncp_conn_scan(NULL,&connid); + if (error) return -2; + return connid; + } + if (server == NULL) + return -2; + ncp_str_upper(server); + if (user) ncp_str_upper(user); + bzero(&ca, sizeof(ca)); + ncp_li_setserver(&ca, server); + ncp_li_setuser(&ca, user); + error = ncp_conn_scan(&ca,&connid); + if (error) + connid = -1; + return connid; +} + +int +ncp_li_arg(struct ncp_conn_loginfo *li, int opt, char *arg) { + int error = 0, sig_level; + char *p, *cp; + struct group *gr; + struct passwd *pw; + + switch(opt) { + case 'S': /* we already fill server/[user] pair */ + case 'U': + break; + case 'A': + server_name = arg; + break; + case 'B': + li->opt |= NCP_OPT_BIND; + break; + case 'C': + li->opt |= NCP_OPT_NOUPCASEPASS; + break; + case 'I': + sig_level = atoi(arg); + if (sig_level < 0 || sig_level > 3) { + fprintf(stderr, "Invalid NCP signature level option `%s' (must be number between 0 and 3)\n", arg); + error = 1; + } + li->sig_level = sig_level; + if (sig_level > 1) li->opt |= NCP_OPT_SIGN; + break; + case 'M': + li->access_mode = strtol(arg, NULL, 8); + break; + case 'N': + ncp_li_setpassword(li, ""); + break; + case 'O': + p = strdup(arg); + cp = strchr(p, ':'); + if (cp) { + *cp++ = '\0'; + if (*cp) { + gr = getgrnam(cp); + if (gr) { + li->group = gr->gr_gid; + } else + ncp_error("Invalid group name %s, ignored", + 0, cp); + } + } + if (*p) { + pw = getpwnam(p); + if (pw) { + li->owner = pw->pw_uid; + } else + ncp_error("Invalid user name %s, ignored", 0, p); + } + endpwent(); + free(p); + break; + case 'P': + li->opt |= NCP_OPT_PERMANENT; + break; + case 'R': + li->retry_count = atoi(arg); + break; + case 'W': + li->timeout = atoi(arg); + break; + } + return error; +} + +void * +ncp_conn_list(void) { + int error, cnt = 0, len; + void *p; + + cnt = ncp_conn_cnt(); + if (cnt == 0) return NULL; + len = cnt*(sizeof(struct ncp_conn_stat))+sizeof(int); + p = malloc(len); + if (p == NULL) return NULL; +#if __FreeBSD_version < 400001 + error = sysctlbyname("net.ipx.ncp.conn_stat", p, &len, NULL, 0); +#else + error = sysctlbyname("net.ncp.conn_stat", p, &len, NULL, 0); +#endif + if (error) { + free(p); + p = NULL; + } + return p; +} + + +int +ncp_conn_setflags(int connid, u_int16_t mask, u_int16_t flags) { + int error; + DECLARE_RQ; + + ncp_init_request(conn); + ncp_add_byte(conn, NCP_CONN_SETFLAGS); + ncp_add_word_lh(conn, mask); + ncp_add_word_lh(conn, flags); + if ((error = ncp_conn_request(connid, conn)) < 0) + return -1; + return error; +} + +int +ncp_login(int connHandle, const char *user, int objtype, const char *password) { + int error; + struct ncp_conn_login *p; + DECLARE_RQ; + + ncp_init_request(conn); + ncp_add_byte(conn, NCP_CONN_LOGIN); + p = (struct ncp_conn_login *)&conn->packet[conn->rqsize]; + (const char*)p->username = user; + p->objtype = objtype; + (const char*)p->password = password; + conn->rqsize += sizeof(*p); + if ((error = ncp_conn_request(connHandle, conn)) < 0) + return -1; + return error; +} + +int +ncp_connect_addr(struct sockaddr *sa, NWCONN_HANDLE *chp) { + int error; + struct ncp_conn_args li; + + bzero(&li, sizeof(li)); + bcopy(sa, &li.addr, sa->sa_len); + /* + * XXX Temporary !!!. server will be filled in kernel !!! + */ + strcpy(li.server,ipx_ntoa(li.ipxaddr.sipx_addr)); + error = ncp_connect(&li, chp); + return error; +} + +int +ncp_conn_getinfo(int connHandle, struct ncp_conn_stat *ps) { + int error; + DECLARE_RQ; + + ncp_init_request(conn); + ncp_add_byte(conn, NCP_CONN_GETINFO); + if ((error = ncp_conn_request(connHandle, conn)) < 0) + return -1; + memcpy(ps, ncp_reply_data(conn,0), sizeof(*ps)); + return error; +} + +int +ncp_conn_getuser(int connHandle, char **user) { + int error; + DECLARE_RQ; + + ncp_init_request(conn); + ncp_add_byte(conn, NCP_CONN_GETUSER); + if ((error = ncp_conn_request(connHandle, conn)) < 0) + return -1; + *user = strdup(ncp_reply_data(conn,0)); + return error; +} + +int +ncp_conn2ref(int connHandle, int *connRef) { + int error; + DECLARE_RQ; + + ncp_init_request(conn); + ncp_add_byte(conn, NCP_CONN_CONN2REF); + if ((error = ncp_conn_request(connHandle, conn)) < 0) + return -1; + *connRef = *((int*)ncp_reply_data(conn,0)); + return error; +} + +int +ncp_path2conn(char *path, int *connHandle) { + struct statfs st; + int d, error; + + if ((error = statfs(path, &st)) != 0) return errno; + if (strcmp(st.f_fstypename,"nwfs") != 0) return EINVAL; + if ((d = open(path, O_RDONLY)) < 0) return errno; + if ((error = ioctl(d,NWFSIOC_GETCONN, connHandle)) != 0) return errno; + close(d); + return 0; +} + +int +ncp_conn_dup(NWCONN_HANDLE org, NWCONN_HANDLE *res) { + int error; + DECLARE_RQ; + + ncp_init_request(conn); + ncp_add_byte(conn, NCP_CONN_DUP); + if ((error = ncp_conn_request(org, conn)) < 0) + return errno; + *res = *((int*)ncp_reply_data(conn, 0)); + return 0; +} diff --git a/lib/libncp/ncpl_crypt.c b/lib/libncp/ncpl_crypt.c new file mode 100644 index 0000000..00ce9bf --- /dev/null +++ b/lib/libncp/ncpl_crypt.c @@ -0,0 +1,137 @@ +/* + * Routines in this file based on the work of Volker Lendecke, + * Adapted for ncplib by Boris Popov + * Please note that ncpl_crypt.c file should be indentical to this one + * + * $FreeBSD$ + */ +#include +#include +#include +#include + +/*$********************************************************* + $* + $* This code has been taken from DDJ 11/93, from an + $* article by Pawel Szczerbina. + $* + $* Password encryption routines follow. + $* Converted to C from Barry Nance's Pascal + $* prog published in the March -93 issue of Byte. + $* + $* Adapted to be useable for ncpfs by + $* Volker Lendecke in + $* October 1995. + $* + $********************************************************* */ + + + +typedef unsigned char buf32[32]; + +static unsigned char encrypttable[256] = { +0x7, 0x8, 0x0, 0x8, 0x6, 0x4, 0xE, 0x4, 0x5, 0xC, 0x1, 0x7, 0xB, 0xF, 0xA, 0x8, +0xF, 0x8, 0xC, 0xC, 0x9, 0x4, 0x1, 0xE, 0x4, 0x6, 0x2, 0x4, 0x0, 0xA, 0xB, 0x9, +0x2, 0xF, 0xB, 0x1, 0xD, 0x2, 0x1, 0x9, 0x5, 0xE, 0x7, 0x0, 0x0, 0x2, 0x6, 0x6, +0x0, 0x7, 0x3, 0x8, 0x2, 0x9, 0x3, 0xF, 0x7, 0xF, 0xC, 0xF, 0x6, 0x4, 0xA, 0x0, +0x2, 0x3, 0xA, 0xB, 0xD, 0x8, 0x3, 0xA, 0x1, 0x7, 0xC, 0xF, 0x1, 0x8, 0x9, 0xD, +0x9, 0x1, 0x9, 0x4, 0xE, 0x4, 0xC, 0x5, 0x5, 0xC, 0x8, 0xB, 0x2, 0x3, 0x9, 0xE, +0x7, 0x7, 0x6, 0x9, 0xE, 0xF, 0xC, 0x8, 0xD, 0x1, 0xA, 0x6, 0xE, 0xD, 0x0, 0x7, +0x7, 0xA, 0x0, 0x1, 0xF, 0x5, 0x4, 0xB, 0x7, 0xB, 0xE, 0xC, 0x9, 0x5, 0xD, 0x1, +0xB, 0xD, 0x1, 0x3, 0x5, 0xD, 0xE, 0x6, 0x3, 0x0, 0xB, 0xB, 0xF, 0x3, 0x6, 0x4, +0x9, 0xD, 0xA, 0x3, 0x1, 0x4, 0x9, 0x4, 0x8, 0x3, 0xB, 0xE, 0x5, 0x0, 0x5, 0x2, +0xC, 0xB, 0xD, 0x5, 0xD, 0x5, 0xD, 0x2, 0xD, 0x9, 0xA, 0xC, 0xA, 0x0, 0xB, 0x3, +0x5, 0x3, 0x6, 0x9, 0x5, 0x1, 0xE, 0xE, 0x0, 0xE, 0x8, 0x2, 0xD, 0x2, 0x2, 0x0, +0x4, 0xF, 0x8, 0x5, 0x9, 0x6, 0x8, 0x6, 0xB, 0xA, 0xB, 0xF, 0x0, 0x7, 0x2, 0x8, +0xC, 0x7, 0x3, 0xA, 0x1, 0x4, 0x2, 0x5, 0xF, 0x7, 0xA, 0xC, 0xE, 0x5, 0x9, 0x3, +0xE, 0x7, 0x1, 0x2, 0xE, 0x1, 0xF, 0x4, 0xA, 0x6, 0xC, 0x6, 0xF, 0x4, 0x3, 0x0, +0xC, 0x0, 0x3, 0x6, 0xF, 0x8, 0x7, 0xB, 0x2, 0xD, 0xC, 0x6, 0xA, 0xA, 0x8, 0xD +}; + +static buf32 encryptkeys = { + 0x48, 0x93, 0x46, 0x67, 0x98, 0x3D, 0xE6, 0x8D, + 0xB7, 0x10, 0x7A, 0x26, 0x5A, 0xB9, 0xB1, 0x35, + 0x6B, 0x0F, 0xD5, 0x70, 0xAE, 0xFB, 0xAD, 0x11, + 0xF4, 0x47, 0xDC, 0xA7, 0xEC, 0xCF, 0x50, 0xC0 +}; + +/* + * Create table-based 16-bytes hash from a 32-bytes array + */ +static void +nw_hash(buf32 temp, unsigned char *target) { + short sum; + unsigned char b3; + int s, b2, i; + + sum = 0; + + for (b2 = 0; b2 <= 1; ++b2) { + for (s = 0; s <= 31; ++s) { + b3 = (temp[s] + sum) ^ (temp[(s + sum) & 31] - encryptkeys[s]); + sum += b3; + temp[s] = b3; + } + } + + for (i = 0; i <= 15; ++i) { + target[i] = encrypttable[temp[2 * i]] + | (encrypttable[temp[2 * i + 1]] << 4); + } +} + + +/* + * Create a 16-bytes pattern from given buffer based on a four bytes key + */ +void +nw_keyhash(const u_char *key, const u_char *buf, int buflen, u_char *target) { + int b2, d, s; + buf32 temp; + + while (buflen > 0 && buf[buflen - 1] == 0) + buflen--; + + bzero(temp, sizeof(temp)); + + d = 0; + while (buflen >= 32) { + for (s = 0; s <= 31; ++s) + temp[s] ^= buf[d++]; + buflen -= 32; + } + b2 = d; + if (buflen > 0) { + for (s = 0; s <= 31; ++s) { + if (d + buflen == b2) { + temp[s] ^= encryptkeys[s]; + b2 = d; + } else + temp[s] ^= buf[b2++]; + } + } + for (s = 0; s <= 31; ++s) + temp[s] ^= key[s & 3]; + + nw_hash(temp, target); +} + +/* + * Create an 8-bytes pattern from an 8-bytes key and 16-bytes of data + */ +void +nw_encrypt(const u_char *fra, const u_char *buf, u_char *target) { + buf32 k; + int s; + + nw_keyhash(fra, buf, 16, k); + nw_keyhash(fra + 4, buf, 16, k + 16); + + for (s = 0; s < 16; s++) + k[s] ^= k[31 - s]; + + for (s = 0; s < 8; s++) + *target++ = k[s] ^ k[15 - s]; +} + + diff --git a/lib/libncp/ncpl_file.c b/lib/libncp/ncpl_file.c new file mode 100644 index 0000000..e305bc0 --- /dev/null +++ b/lib/libncp/ncpl_file.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +int +ncp_read(int connid, ncp_fh *fh, off_t offset, size_t count, char *target) { + int result; + struct ncp_rw rwrq; + DECLARE_RQ; + + ncp_init_request(conn); + ncp_add_byte(conn, NCP_CONN_READ); + rwrq.nrw_fh = *fh; + rwrq.nrw_base = target; + rwrq.nrw_cnt = count; + rwrq.nrw_offset = offset; + ncp_add_mem(conn, &rwrq, sizeof(rwrq)); + if ((result = ncp_conn_request(connid, conn)) < 0) + return -1; + return result; +} + +int +ncp_write(int connid, ncp_fh *fh, off_t offset, size_t count, char *source) +{ + int result; + struct ncp_rw rwrq; + DECLARE_RQ; + + ncp_init_request(conn); + ncp_add_byte(conn, NCP_CONN_WRITE); + rwrq.nrw_fh = *fh; + rwrq.nrw_base = source; + rwrq.nrw_cnt = count; + rwrq.nrw_offset = offset; + ncp_add_mem(conn, &rwrq, sizeof(rwrq)); + + if ((result = ncp_conn_request(connid, conn)) < 0) + return -1; + return result; +} + +int +ncp_geteinfo(char *path, struct nw_entry_info *fi) { + int d, error; + + if ((d = open(path, O_RDONLY)) < 0) return errno; + if ((error = ioctl(d, NWFSIOC_GETEINFO, fi)) != 0) return errno; + close(d); + return 0; +} + + +int +ncp_AllocTempDirHandle(char *path, NWDIR_HANDLE *pdh) { + int d; + + if ((d = open(path, O_RDONLY)) < 0) return errno; + *pdh = d; + return 0; +} + +int +ncp_DeallocateDirHandle(NWDIR_HANDLE dh) { + close(dh); + return 0; +} + +int +ncp_GetNSEntryInfo(NWDIR_HANDLE dh, struct nw_entry_info *fi, int *ns) { + int error; + + if ((error = ioctl(dh, NWFSIOC_GETEINFO, fi)) != 0) return errno; + if ((error = ioctl(dh, NWFSIOC_GETNS, ns)) != 0) return errno; + return 0; +} + +NWCCODE +ncp_ScanForDeletedFiles(NWCONN_HANDLE cH, pnuint32 iterHandle, + pnuint32 volNum, pnuint32 dirBase, nuint8 ns, + NWDELETED_INFO *entryInfo) +{ + int error; + struct nw_entry_info *pfi; + DECLARE_RQ; +#define UNITEDT(d,t) (((d) << 16) | (t)) + + bzero(entryInfo, sizeof(NWDELETED_INFO)); + ncp_init_request(conn); + ncp_add_byte(conn, 16); + ncp_add_byte(conn, ns); + ncp_add_byte(conn, 0); /* data stream */ + ncp_add_dword_lh(conn, IM_ALL & ~(IM_SPACE_ALLOCATED | IM_TOTAL_SIZE | IM_EA | IM_DIRECTORY)); + ncp_add_dword_lh(conn, *iterHandle); + + ncp_add_byte(conn, *volNum); + ncp_add_dword_lh(conn, *dirBase); + ncp_add_byte(conn, NCP_HF_DIRBASE); /* dirBase */ + ncp_add_byte(conn, 0); /* no component */ + if ((error = ncp_request(cH, 87, conn)) != 0) { + return error; + } + if (conn->rpsize < 0x61) { + return EBADRPC; /* EACCES ? */ + } + *iterHandle = entryInfo->sequence = ncp_reply_dword_lh(conn, 0x00); + entryInfo->deletedTime = ncp_reply_word_lh(conn, 0x04); + entryInfo->deletedDateAndTime = UNITEDT(ncp_reply_word_lh(conn, 0x06), entryInfo->deletedTime); + entryInfo->deletorID = ncp_reply_dword_hl(conn, 0x08); + *volNum = ncp_reply_dword_lh(conn, 0x0C); + *dirBase = ncp_reply_dword_lh(conn, 0x10); + entryInfo->parent = ncp_reply_dword_lh(conn, 0x10); + pfi = (struct nw_entry_info*) ncp_reply_data(conn, 0x14); + entryInfo->nameLength = pfi->nameLen; + memcpy(entryInfo->name, pfi->entryName, pfi->nameLen); + return error; +} + +NWCCODE +ncp_PurgeDeletedFile(NWCONN_HANDLE cH, nuint32 iterHandle, + nuint32 volNum, nuint32 dirBase, nuint8 ns) +{ + DECLARE_RQ; + + ncp_init_request(conn); + ncp_add_byte(conn, 18); + ncp_add_byte(conn, ns); + ncp_add_byte(conn, 0); /* reserved */ + ncp_add_dword_lh(conn, iterHandle); + ncp_add_dword_lh(conn, volNum); + ncp_add_dword_lh(conn, dirBase); + return ncp_request(cH, 87, conn); +} + + +static void +ncp_extract_entryInfo(char *data, NW_ENTRY_INFO *entry) { + u_char l; + const int info_struct_size = sizeof(NW_ENTRY_INFO) - 257; + + memcpy(entry, data, info_struct_size); + data += info_struct_size; + l = *data++; + entry->nameLen = l; + memcpy(entry->entryName, data, l); + entry->entryName[l] = '\0'; + return; +} + +NWCCODE +ncp_ScanNSEntryInfo(NWCONN_HANDLE cH, + nuint8 namSpc, nuint16 attrs, SEARCH_SEQUENCE *seq, + pnstr8 searchPattern, nuint32 retInfoMask, NW_ENTRY_INFO *entryInfo) +{ + int error, l; + DECLARE_RQ; + + if (seq->searchDirNumber == -1) { + seq->searchDirNumber = 0; + ncp_init_request(conn); + ncp_add_byte(conn, 2); + ncp_add_byte(conn, namSpc); + ncp_add_byte(conn, 0); + ncp_add_handle_path(conn, seq->volNumber, seq->dirNumber, + NCP_HF_DIRBASE, NULL); + error = ncp_request(cH, 87, conn); + if (error) return error; + memcpy(seq, ncp_reply_data(conn, 0), 9); + } + ncp_init_request(conn); + ncp_add_byte(conn, 3); + ncp_add_byte(conn, namSpc); + ncp_add_byte(conn, 0); /* dataStream */ + ncp_add_word_lh(conn, attrs); /* SearchAttributes */ + ncp_add_dword_lh(conn, retInfoMask); + ncp_add_mem(conn, seq, sizeof(*seq)); + l = strlen(searchPattern); + ncp_add_byte(conn, l); + ncp_add_mem(conn, searchPattern, l); + error = ncp_request(cH, 87, conn); + if (error) return error; + memcpy(seq, ncp_reply_data(conn, 0), sizeof(*seq)); + ncp_extract_entryInfo(ncp_reply_data(conn, 10), entryInfo); + return 0; +} + +int +ncp_NSEntryInfo(NWCONN_HANDLE cH, nuint8 ns, nuint8 vol, nuint32 dirent, + NW_ENTRY_INFO *entryInfo) +{ + DECLARE_RQ; + int error; + + ncp_init_request(conn); + ncp_add_byte(conn, 6); + ncp_add_byte(conn, ns); + ncp_add_byte(conn, ns); /* DestNameSpace */ + ncp_add_word_lh(conn, htons(0xff00)); /* get all */ + ncp_add_dword_lh(conn, IM_ALL); + ncp_add_handle_path(conn, vol, dirent, NCP_HF_DIRBASE, NULL); + error = ncp_request(cH, 87, conn); + if (error) return error; + ncp_extract_entryInfo(ncp_reply_data(conn, 0), entryInfo); + return 0; +} + +NWCCODE +NWGetVolumeName(NWCONN_HANDLE cH, u_char volume, char *name) { + int error, len; + DECLARE_RQ; + + ncp_init_request_s(conn, 44); + ncp_add_byte(conn, volume); + error = ncp_request(cH, 22, conn); + if (error) return error; + len = ncp_reply_byte(conn, 29); + if (len == 0) + return ENOENT; + bcopy(ncp_reply_data(conn, 30), name, len); + name[len] = 0; + return 0; +} diff --git a/lib/libncp/ncpl_misc.c b/lib/libncp/ncpl_misc.c new file mode 100644 index 0000000..7f7a67a --- /dev/null +++ b/lib/libncp/ncpl_misc.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + * calls that don't fit to any other category + * + */ +#include +#include +#include +#include +#include + +#include + +static time_t +ncp_nw_to_ctime(struct nw_time_buffer *source) { + struct tm u_time; + + bzero(&u_time,sizeof(struct tm)); + /* + * XXX: NW 4.x tracks daylight automatically + */ + u_time.tm_isdst = -1; + u_time.tm_sec = source->second; + u_time.tm_min = source->minute; + u_time.tm_hour = source->hour; + u_time.tm_mday = source->day; + u_time.tm_mon = source->month - 1; + u_time.tm_year = source->year; + + if (u_time.tm_year < 80) { + u_time.tm_year += 100; + } + return mktime(&u_time); +} + +int +ncp_get_file_server_information(int connid, struct ncp_file_server_info *target) +{ + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 17); + if ((error = ncp_request(connid, 23, conn)) != 0) + return error; + memcpy(target, ncp_reply_data(conn, 0), sizeof(*target)); + target->MaximumServiceConnections + = htons(target->MaximumServiceConnections); + target->ConnectionsInUse + = htons(target->ConnectionsInUse); + target->MaxConnectionsEverUsed + = htons(target->MaxConnectionsEverUsed); + target->NumberMountedVolumes + = htons(target->NumberMountedVolumes); + return 0; +} + +int +ncp_get_stations_logged_info(int connid, u_int32_t connection, + struct ncp_bindery_object *target, + time_t *login_time) +{ + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 28); + ncp_add_dword_lh(conn, connection); + + if ((error = ncp_request(connid, 23, conn)) != 0) + return error; + bzero(target, sizeof(*target)); + target->object_id = ncp_reply_dword_hl(conn, 0); + target->object_type = ncp_reply_word_hl(conn, 4); + memcpy(target->object_name, ncp_reply_data(conn, 6), + sizeof(target->object_name)); + *login_time = ncp_nw_to_ctime((struct nw_time_buffer *)ncp_reply_data(conn, 54)); + return 0; +} + +int +ncp_get_internet_address(int connid, u_int32_t connection, struct ipx_addr *target, + u_int8_t * conn_type) { + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 26); + ncp_add_dword_lh(conn, connection); + error = ncp_request(connid, 23, conn); + if (error) return error; + bzero(target, sizeof(*target)); + ipx_netlong(*target) = ncp_reply_dword_lh(conn, 0); + memcpy(&(target->x_host), ncp_reply_data(conn, 4), 6); + target->x_port = ncp_reply_word_lh(conn, 10); + *conn_type = ncp_reply_byte(conn, 12); + return 0; +} + +NWCCODE +NWGetObjectConnectionNumbers(NWCONN_HANDLE connHandle, + pnstr8 pObjName, nuint16 objType, + pnuint16 pNumConns, pnuint16 pConnHandleList, + nuint16 maxConns) +{ + int error, i; + DECLARE_RQ; + ncp_init_request_s(conn, 21); + ncp_add_word_hl(conn, objType); + ncp_add_pstring(conn, pObjName); + if ((error = ncp_request(connHandle, 23, conn)) != 0) return error; + i = ncp_reply_byte(conn,0); + *pNumConns = i; + for (i = min(i, maxConns); i; i--) { + pConnHandleList[i-1] = ncp_reply_byte(conn, i); + } + return 0; +} + +void +NWUnpackDateTime(nuint32 dateTime, NW_DATE *sDate, NW_TIME *sTime) { + NWUnpackDate(dateTime >> 16, sDate); + NWUnpackTime(dateTime & 0xffff, sTime); +} + +void +NWUnpackDate(nuint16 date, NW_DATE *sDate) { + sDate->day = date & 0x1f; + sDate->month = (date >> 5) & 0xf; + sDate->year = ((date >> 9) & 0x7f) + 1980; +} + +void +NWUnpackTime(nuint16 time, NW_TIME *sTime) { + sTime->seconds = time & 0x1f; + sTime->minutes = (time >> 5) & 0x3f; + sTime->hours = (time >> 11) & 0x1f; +} + +nuint32 +NWPackDateTime(NW_DATE *sDate, NW_TIME *sTime) { + return 0; +} + +nuint16 +NWPackDate(NW_DATE *sDate) { + return 0; +} + +nuint16 +NWPackTime(NW_TIME *sTime) { + return 0; +} + +time_t +ncp_UnpackDateTime(nuint32 dateTime) { + struct tm u_time; + NW_DATE d; + NW_TIME t; + + NWUnpackDateTime(dateTime, &d, &t); + bzero(&u_time,sizeof(struct tm)); + u_time.tm_isdst = -1; + u_time.tm_sec = t.seconds; + u_time.tm_min = t.minutes; + u_time.tm_hour = t.hours; + u_time.tm_mday = d.day; + u_time.tm_mon = d.month - 1; + u_time.tm_year = d.year - 1900; + + return mktime(&u_time); +} + +int +ncp_GetFileServerDateAndTime(NWCONN_HANDLE cH, time_t *target) { + int error; + DECLARE_RQ; + + ncp_init_request(conn); + if ((error = ncp_request(cH, 20, conn)) != 0) + return error; + *target = ncp_nw_to_ctime((struct nw_time_buffer *) ncp_reply_data(conn, 0)); + return 0; +} + +int +ncp_SetFileServerDateAndTime(NWCONN_HANDLE cH, time_t * source) { + int year; + struct tm *utime = localtime(source); + DECLARE_RQ; + + year = utime->tm_year; + if (year > 99) { + year -= 100; + } + ncp_init_request_s(conn, 202); + ncp_add_byte(conn, year); + ncp_add_byte(conn, utime->tm_mon + 1); + ncp_add_byte(conn, utime->tm_mday); + ncp_add_byte(conn, utime->tm_hour); + ncp_add_byte(conn, utime->tm_min); + ncp_add_byte(conn, utime->tm_sec); + return ncp_request(cH, 23, conn); +} + +NWCCODE +NWDownFileServer(NWCONN_HANDLE cH, int force) { + DECLARE_RQ; + + ncp_init_request_s(conn, 211); + ncp_add_byte(conn, force ? 0 : 0xff); + return ncp_request(cH, 23, conn); +} + +NWCCODE +NWCloseBindery(NWCONN_HANDLE cH) { + DECLARE_RQ; + + ncp_init_request_s(conn, 68); + return ncp_request(cH, 23, conn); +} + +NWCCODE +NWOpenBindery(NWCONN_HANDLE cH) { + DECLARE_RQ; + + ncp_init_request_s(conn, 69); + return ncp_request(cH, 23, conn); +} + +NWCCODE +NWDisableTTS(NWCONN_HANDLE cH) { + DECLARE_RQ; + + ncp_init_request_s(conn, 207); + return ncp_request(cH, 23, conn); +} + +NWCCODE +NWEnableTTS(NWCONN_HANDLE cH) { + DECLARE_RQ; + + ncp_init_request_s(conn, 208); + return ncp_request(cH, 23, conn); +} + +NWCCODE +NWDisableFileServerLogin(NWCONN_HANDLE cH) { + DECLARE_RQ; + + ncp_init_request_s(conn, 203); + return ncp_request(cH, 23, conn); +} + +NWCCODE +NWEnableFileServerLogin(NWCONN_HANDLE cH) { + DECLARE_RQ; + + ncp_init_request_s(conn, 204); + return ncp_request(cH, 23, conn); +} diff --git a/lib/libncp/ncpl_msg.c b/lib/libncp/ncpl_msg.c new file mode 100644 index 0000000..a65131b --- /dev/null +++ b/lib/libncp/ncpl_msg.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include +#include +#include +#include + +#include +#include + +NWCCODE +NWDisableBroadcasts(NWCONN_HANDLE connHandle) { + DECLARE_RQ; + + ncp_init_request_s(conn, 2); + return ncp_request(connHandle, 21, conn); +} + +NWCCODE +NWEnableBroadcasts(NWCONN_HANDLE connHandle) { + DECLARE_RQ; + + ncp_init_request_s(conn, 3); + return ncp_request(connHandle, 21, conn); +} + +NWCCODE +NWBroadcastToConsole(NWCONN_HANDLE connHandle, pnstr8 message) { + int l, error; + DECLARE_RQ; + + l = strlen(message); + if (l > 60) return EMSGSIZE; + ncp_init_request_s(conn, 9); + ncp_add_byte(conn, l); + ncp_add_mem_nls(conn, message, l); + error = ncp_request(connHandle, 21, conn); + return error; +} + +NWCCODE +NWSendBroadcastMessage(NWCONN_HANDLE connHandle, pnstr8 message, + nuint16 connCount, pnuint16 connList, pnuint8 resultList) +{ + int l, i, error; + DECLARE_RQ; + + l = strlen(message); + if (l > 255) return EMSGSIZE; + if (connCount > 350) return EINVAL; + + ncp_init_request_s(conn, 0x0A); + ncp_add_word_lh(conn, connCount); + for (i = 0; i < connCount; i++) + ncp_add_dword_lh(conn, connList[i]); + ncp_add_byte(conn, l); + ncp_add_mem_nls(conn, message, l); + error = ncp_request(connHandle, 0x15, conn); + if (!error) { + l = ncp_reply_word_lh(conn, 0); + for (i = 0; i < l; i++) + resultList[i] = ncp_reply_dword_lh(conn, (i)*4 + 2); + return 0; + } + if (error != 0xfb) return error; + if (l > 58) return EMSGSIZE; + ncp_init_request_s(conn, 0); + ncp_add_byte(conn, connCount); + for (i = 0; i < connCount; i++) + ncp_add_byte(conn, connList[i]); + ncp_add_byte(conn, l); + ncp_add_mem_nls(conn, message, l); + error = ncp_request(connHandle, 0x15, conn); + if (error) return error; + i = ncp_reply_byte(conn, 0); + memcpy(resultList, ncp_reply_data(conn, 1), i); + return 0; +} + + +NWCCODE +NWGetBroadcastMessage(NWCONN_HANDLE connHandle, pnstr8 message) { + int i, error; + DECLARE_RQ; + + ncp_init_request_s(conn, 0x0B); + error = ncp_request(connHandle, 0x15, conn); + if (error) { + if (error != 0x89fb) return error; + ncp_init_request_s(conn, 0x01); + if ((error = ncp_request(connHandle, 0x15, conn)) != 0) + return error; + } + i = ncp_reply_byte(conn, 0); + if (i == 0) return ENOENT; + memcpy(message, ncp_reply_data(conn, 1), i); + message[i] = 0; + ncp_nls_str_n2u(message, message); + return 0; +} diff --git a/lib/libncp/ncpl_net.c b/lib/libncp/ncpl_net.c new file mode 100644 index 0000000..da21b66 --- /dev/null +++ b/lib/libncp/ncpl_net.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ipxsap.h" +#include +#include "ncp_mod.h" + +static int ncp_find_server_in(struct ncp_conn_loginfo *li, int type, char *server_name); + +static int +ncp_find_server_ipx(struct ncp_conn_loginfo *li, int type) { + char server[NCP_BINDERY_NAME_LEN + 1]; + int error; + char nearest[NCP_BINDERY_NAME_LEN + 1]; + struct nw_property prop; + struct ipx_addr *n_addr = (struct ipx_addr *) ∝ +/* struct ncp_conn_loginfo ltmp;*/ + int connid; + + bzero(server, sizeof(server)); + bzero(nearest, sizeof(nearest)); + + strcpy(server, li->server); + ncp_str_upper(server); + + if ((error = sap_find_nearest(type, &li->ipxaddr, nearest)) != 0) { + return error; + } + /* if no server specified return info about nearest */ + if (!li->server[0]) { + strcpy(li->server, nearest); + return 0; + } +/* printf("%s\n",ipx_ntoa(li->ipxaddr.sipx_addr));*/ + if (strcmp(server, nearest) == 0) { + return 0; + } + /* We have to ask the nearest server for our wanted server */ + li->opt=0; + if ((error = ncp_connect(li, &connid)) != 0) { + return error; + } + if (ncp_read_property_value(connid, type, server, 1, "NET_ADDRESS", &prop) != 0) { + ncp_disconnect(connid); + return EHOSTUNREACH; + } + if ((error = ncp_disconnect(connid)) != 0) { + return error; + } + li->ipxaddr.sipx_family = AF_IPX; + li->ipxaddr.sipx_addr.x_net = n_addr->x_net; + li->ipxaddr.sipx_port = n_addr->x_port; + li->ipxaddr.sipx_addr.x_host = n_addr->x_host; + return 0; +} + +static int +ncp_find_server_in(struct ncp_conn_loginfo *li, int type, char *server_name) { + struct hostent* h; + int l; + + h = gethostbyname(server_name); + if (!h) { + fprintf(stderr, "Get host address `%s': ", server_name); + herror(NULL); + return 1; + } + if (h->h_addrtype != AF_INET) { + fprintf(stderr, "Get host address `%s': Not AF_INET\n", server_name); + return 1; + } + if (h->h_length != 4) { + fprintf(stderr, "Get host address `%s': Bad address length\n", server_name); + return 1; + } + l = sizeof(struct sockaddr_in); + bzero(&li->inaddr, l); + li->inaddr.sin_len = l; + li->inaddr.sin_family = h->h_addrtype; + memcpy(&li->inaddr.sin_addr.s_addr, h->h_addr, 4); + li->inaddr.sin_port = htons(524); /* ncp */ + return 0; +} + +int +ncp_find_server(struct ncp_conn_loginfo *li, int type, int af, char *name) { + int error = EHOSTUNREACH; + + switch(af) { + case AF_IPX: + error = ncp_find_server_ipx(li, type); + break; + case AF_INET: + if (name) + error = ncp_find_server_in(li, type, name); + break; + default: + error = EPROTONOSUPPORT; + } + return error; +} + +int +ncp_find_fileserver(struct ncp_conn_loginfo *li, int af, char *name) { + return ncp_find_server(li, NCP_BINDERY_FSERVER, af, name); +} diff --git a/lib/libncp/ncpl_nls.c b/lib/libncp/ncpl_nls.c new file mode 100644 index 0000000..92bc013 --- /dev/null +++ b/lib/libncp/ncpl_nls.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * Languages support. Currently is very primitive. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifndef NCP_NLS_DEFAULT +#define NCP_NLS_DEFAULT NCP_NLS_AS_IS +#endif + +/* + * TODO: Make all tables dynamically loadable. + */ +#ifdef NCP_NLS_KOI2CP866 +/* Russian tables from easy-cyrillic: + * Copyright (C) 1993-1994 by Andrey A. Chernov, Moscow, Russia + */ +static u_int8_t alt2koi8[] = { + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x00 */ + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x10 */ + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30 */ + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x5f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40 */ + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50 */ + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60 */ + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70 */ + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0xe1, 0xe2, 0xf7, 0xe7, 0xe4, 0xe5, 0xf6, 0xfa, + 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, + 0xf2, 0xf3, 0xf4, 0xf5, 0xe6, 0xe8, 0xe3, 0xfe, + 0xfb, 0xfd, 0xff, 0xf9, 0xf8, 0xfc, 0xe0, 0xf1, + 0xc1, 0xc2, 0xd7, 0xc7, 0xc4, 0xc5, 0xd6, 0xda, + 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, + 0x90, 0x91, 0x92, 0x81, 0x87, 0xb2, 0xb4, 0xa7, + 0xa6, 0xb5, 0xa1, 0xa8, 0xae, 0xad, 0xac, 0x83, + 0x84, 0x89, 0x88, 0x86, 0x80, 0x8a, 0xaf, 0xb0, + 0xab, 0xa5, 0xbb, 0xb8, 0xb1, 0xa0, 0xbe, 0xb9, + 0xba, 0xb6, 0xb7, 0xaa, 0xa9, 0xa2, 0xa4, 0xbd, + 0xbc, 0x85, 0x82, 0x8d, 0x8c, 0x8e, 0x8f, 0x8b, + 0xd2, 0xd3, 0xd4, 0xd5, 0xc6, 0xc8, 0xc3, 0xde, + 0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1, + 0xb3, 0xa3, 0x99, 0x98, 0x93, 0x9b, 0x9f, 0x97, + 0x9c, 0x95, 0x9e, 0x96, 0xbf, 0x9d, 0x94, 0x9a +}; + +static u_int8_t koi82alt[] = { + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x00 */ + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, /* 0x10 */ + 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20 */ + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30 */ + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x5f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40 */ + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50 */ + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60 */ + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70 */ + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0xc4, 0xb3, 0xda, 0xbf, 0xc0, 0xd9, 0xc3, 0xb4, /* 0x80 */ + 0xc2, 0xc1, 0xc5, 0xdf, 0xdc, 0xdb, 0xdd, 0xde, + 0xb0, 0xb1, 0xb2, 0xf4, 0xfe, 0xf9, 0xfb, 0xf7, + 0xf3, 0xf2, 0xff, 0xf5, 0xf8, 0xfd, 0xfa, 0xf6, + 0xcd, 0xba, 0xd5, 0xf1, 0xd6, 0xc9, 0xb8, 0xb7, + 0xbb, 0xd4, 0xd3, 0xc8, 0xbe, 0xbd, 0xbc, 0xc6, + 0xc7, 0xcc, 0xb5, 0xf0, 0xb6, 0xb9, 0xd1, 0xd2, + 0xcb, 0xcf, 0xd0, 0xca, 0xd8, 0xd7, 0xce, 0xfc, + 0xee, 0xa0, 0xa1, 0xe6, 0xa4, 0xa5, 0xe4, 0xa3, + 0xe5, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, + 0xaf, 0xef, 0xe0, 0xe1, 0xe2, 0xe3, 0xa6, 0xa2, + 0xec, 0xeb, 0xa7, 0xe8, 0xed, 0xe9, 0xe7, 0xea, + 0x9e, 0x80, 0x81, 0x96, 0x84, 0x85, 0x94, 0x83, + 0x95, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, + 0x8f, 0x9f, 0x90, 0x91, 0x92, 0x93, 0x86, 0x82, /* 0xf0 */ + 0x9c, 0x9b, 0x87, 0x98, 0x9d, 0x99, 0x97, 0x9a +}; + +#endif + +static u_int8_t def2lower[256]; +static u_int8_t def2upper[256]; + +/* + * List of available charsets + */ +struct ncp_nlsdesc { + int scheme; + char *name; + struct ncp_nlstables nls; +}; + +static struct ncp_nlsdesc ncp_nlslist[] = { + {NCP_NLS_AS_IS, NCP_NLS_AS_IS_NAME, + {def2lower, def2upper, NULL, NULL, 0} + }, +#ifdef NCP_NLS_KOI2CP866 + {NCP_NLS_KOI_866, NCP_NLS_KOI_866_NAME, + {def2lower, def2upper, alt2koi8, koi82alt, 0} + }, +#endif + {NULL, 0} +}; + +struct ncp_nlstables ncp_nls; + +int +ncp_nls_setlocale(char *name) { + int i; + + ncp_nls.tolower = def2lower; + ncp_nls.toupper = def2upper; + if (setlocale(LC_CTYPE, name) == NULL) { + fprintf(stderr, "Can't set locale '%s'\n", name); + return EINVAL; + } + for (i = 0; i < 256; i++) { + ncp_nls.tolower[i] = tolower(i); + ncp_nls.toupper[i] = toupper(i); + } + return 0; +} + +int +ncp_nls_setrecode(int scheme) { + struct ncp_nlsdesc *nd; + + if (scheme == 0) { +#if NCP_NLS_DEFAULT + scheme = NCP_NLS_DEFAULT; +#else + scheme = NCP_NLS_AS_IS; +#endif + } + for (nd = ncp_nlslist; nd->name; nd++) { + if (nd->scheme != scheme) continue; + ncp_nls.u2n = nd->nls.u2n; + ncp_nls.n2u = nd->nls.n2u; + return ncp_nls_setlocale(""); + } + fprintf(stderr, "Character conversion scheme %d was not compiled in\n", scheme); + return EINVAL; +} + +int +ncp_nls_setrecodebyname(char *name) { + struct ncp_nlsdesc *nd; + + for (nd = ncp_nlslist; nd->name; nd++) { + if (strcmp(nd->name, name) != 0) continue; + ncp_nls.u2n = nd->nls.u2n; + ncp_nls.n2u = nd->nls.n2u; + return 0; + } + fprintf(stderr, "Character conversion scheme %s was not compiled in\n", name); + return EINVAL; +} + +char * +ncp_nls_str_n2u(char *dst, const char *src) { + char *p; + + if (ncp_nls.n2u == NULL) { + return strcpy(dst, src); + } + p = dst; + while (*src) + *p++ = ncp_nls.n2u[(u_char)*(src++)]; + *p = 0; + return dst; +} + +char * +ncp_nls_str_u2n(char *dst, const char *src) { + char *p; + + if (ncp_nls.u2n == NULL) { + return strcpy(dst, src); + } + p = dst; + while (*src) + *p++ = ncp_nls.u2n[(u_char)*(src++)]; + *p = 0; + return dst; +} + +char * +ncp_nls_mem_n2u(char *dst, const char *src, int size) { + char *p; + + if (size == 0) return NULL; + if (ncp_nls.n2u == NULL) { + return memcpy(dst, src, size); + } + for(p = dst; size; size--, p++) + *p = ncp_nls.n2u[(u_char)*(src++)]; + return dst; +} + +char * +ncp_nls_mem_u2n(char *dst, const char *src, int size) { + char *p; + + if (size == 0) return NULL; + if (ncp_nls.u2n == NULL) { + return strcpy(dst, src); + } + for(p = dst; size; size--, p++) + *p = ncp_nls.u2n[(u_char)*(src++)]; + return dst; +} + +char * +ncp_str_upper(char *s) { + char *p = s; + while (*s) { + *s = toupper(*s); + s++; + } + return p; +} diff --git a/lib/libncp/ncpl_queue.c b/lib/libncp/ncpl_queue.c new file mode 100644 index 0000000..beb34c7 --- /dev/null +++ b/lib/libncp/ncpl_queue.c @@ -0,0 +1,214 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + * NetWare queue interface + * + */ +#include +#include +#include +#include + +int +ncp_create_queue_job_and_file(int connid, u_int32_t queue_id, + struct queue_job *job) +{ + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 121); + ncp_add_dword_hl(conn, queue_id); + ncp_add_mem(conn, &(job->j), sizeof(job->j)); + + if ((error = ncp_request(connid, 23, conn)) != 0) + return error; + memcpy(&(job->j), ncp_reply_data(conn, 0), 78); + ConvertToNWfromDWORD(job->j.JobFileHandle, &job->file_handle); + return 0; +} + +int +ncp_close_file_and_start_job(int connid, u_int32_t queue_id, struct queue_job *job) +{ + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 127); + ncp_add_dword_hl(conn, queue_id); + ncp_add_dword_lh(conn, job->j.JobNumber); + error = ncp_request(connid, 23, conn); + return error; +} + +int +ncp_attach_to_queue(int connid, u_int32_t queue_id) { + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 111); + ncp_add_dword_hl(conn, queue_id); + error = ncp_request(connid, 23, conn); + return error; +} + +int +ncp_detach_from_queue(int connid, u_int32_t queue_id) { + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 112); + ncp_add_dword_hl(conn, queue_id); + error= ncp_request(connid, 23, conn); + return error; +} + +int +ncp_service_queue_job(int connid, u_int32_t queue_id, u_int16_t job_type, + struct queue_job *job) { + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 124); + ncp_add_dword_hl(conn, queue_id); + ncp_add_word_hl(conn, job_type); + if ((error = ncp_request(connid, 23, conn)) != 0) { + return error; + } + memcpy(&(job->j), ncp_reply_data(conn, 0), 78); + ConvertToNWfromDWORD(job->j.JobFileHandle, &job->file_handle); + return error; +} + +int +ncp_finish_servicing_job(int connid, u_int32_t queue_id, u_int32_t job_number, + u_int32_t charge_info) { + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 131); + ncp_add_dword_hl(conn, queue_id); + ncp_add_dword_lh(conn, job_number); + ncp_add_dword_hl(conn, charge_info); + + error = ncp_request(connid, 23, conn); + return error; +} + +int +ncp_abort_servicing_job(int connid, u_int32_t queue_id, u_int32_t job_number) { + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 132); + ncp_add_dword_hl(conn, queue_id); + ncp_add_dword_lh(conn, job_number); + error = ncp_request(connid, 23, conn); + return error; +} + +int +ncp_get_queue_length(int connid, u_int32_t queue_id, u_int32_t *queue_length) { + int error; + DECLARE_RQ; + + ncp_init_request_s(conn, 125); + ncp_add_dword_hl(conn, queue_id); + + if ((error = ncp_request(connid, 23, conn)) != 0) + return error; + if (conn->rpsize < 12) { + ncp_printf("ncp_reply_size %d < 12\n", conn->rpsize); + return EINVAL; + } + if (ncp_reply_dword_hl(conn,0) != queue_id) { + printf("Ouch! Server didn't reply with same queue id in ncp_get_queue_length!\n"); + return EINVAL; + } + *queue_length = ncp_reply_dword_lh(conn,8); + return error; +} + +int +ncp_get_queue_job_ids(int connid, u_int32_t queue_id, u_int32_t queue_section, + u_int32_t *length1, u_int32_t *length2, u_int32_t ids[]) +{ + int error; + DECLARE_RQ; + + ncp_init_request_s(conn,129); + ncp_add_dword_hl(conn, queue_id); + ncp_add_dword_lh(conn, queue_section); + + if ((error = ncp_request(connid, 23, conn)) != 0) + return error; + if (conn->rpsize < 8) { + ncp_printf("ncp_reply_size %d < 8\n", conn->rpsize); + return EINVAL; + } + *length2 = ncp_reply_dword_lh(conn,4); + if (conn->rpsize < 8 + 4*(*length2)) { + ncp_printf("ncp_reply_size %d < %d\n", conn->rpsize, 8+4*(*length2)); + return EINVAL; + } + if (ids) { + int count = min(*length1, *length2)*sizeof(u_int32_t); + int pos; + + for (pos=0; posrpsize < sizeof(struct nw_queue_job_entry)) { + ncp_printf("ncp_reply_size %d < %d\n", conn->rpsize,sizeof(struct nw_queue_job_entry)); + return EINVAL; + } + memcpy(jobdata,ncp_reply_data(conn,0), sizeof(struct nw_queue_job_entry)); + return error; +} diff --git a/lib/libncp/ncpl_rcfile.c b/lib/libncp/ncpl_rcfile.c new file mode 100644 index 0000000..7a69071 --- /dev/null +++ b/lib/libncp/ncpl_rcfile.c @@ -0,0 +1,407 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define NWFS_CFG_FILE NCP_PREFIX"/etc/nwfs.conf" + +struct rcfile *ncp_rc = NULL; + +SLIST_HEAD(rcfile_head, rcfile); +static struct rcfile_head pf_head = {NULL}; + +int rc_merge(char *filename,struct rcfile **rcfile); +static struct rcfile* rc_find(char *filename); +static struct rcsection *rc_findsect(struct rcfile *rcp, char *sectname); +static struct rcsection *rc_addsect(struct rcfile *rcp, char *sectname); +static int rc_sect_free(struct rcsection *rsp); +static struct rckey *rc_sect_findkey(struct rcsection *rsp, char *keyname); +static struct rckey *rc_sect_addkey(struct rcsection *rsp, char *name, char *value); +static void rc_key_free(struct rckey *p); +static void rc_parse(struct rcfile *rcp); + + +/* + * open rcfile and load its content, if already open - return previous handle + */ +int +rc_open(char *filename,char *mode,struct rcfile **rcfile) { + struct rcfile *rcp; + FILE *f; + + rcp = rc_find(filename); + if( rcp ) { + *rcfile = rcp; + return 0; + } + f = fopen (filename, mode); + if (f==NULL) + return errno; + rcp = malloc(sizeof(struct rcfile)); + if (rcp==NULL) { + fclose(f); + return ENOMEM; + } + bzero(rcp, sizeof(struct rcfile)); + rcp->rf_name = strdup (filename); + rcp->rf_f = f; + SLIST_INSERT_HEAD(&pf_head, rcp, rf_next); + rc_parse(rcp); + *rcfile = rcp; + return 0; +} + +int +rc_merge(char *filename,struct rcfile **rcfile) { + struct rcfile *rcp = *rcfile; + FILE *f, *t; + + if (rcp == NULL) { + return rc_open(filename,"r",rcfile); + } + f = fopen (filename, "r"); + if (f==NULL) + return errno; + t = rcp->rf_f; + rcp->rf_f = f; + rc_parse(rcp); + rcp->rf_f = t; + fclose(f); + return 0; +} + +int +rc_close(struct rcfile *rcp) { + struct rcsection *p,*n; + + fclose(rcp->rf_f); + for(p = SLIST_FIRST(&rcp->rf_sect);p;) { + n = p; + p = SLIST_NEXT(p,rs_next); + rc_sect_free(n); + } + free(rcp->rf_name); + SLIST_REMOVE(&pf_head, rcp, rcfile, rf_next); + free(rcp); + return 0; +} + +static struct rcfile* +rc_find(char *filename) { + struct rcfile *p; + + SLIST_FOREACH(p, &pf_head, rf_next) + if (strcmp (filename, p->rf_name)==0) + return p; + return 0; +} + +static struct rcsection * +rc_findsect(struct rcfile *rcp, char *sectname) { + struct rcsection *p; + + SLIST_FOREACH(p, &rcp->rf_sect, rs_next) + if (strcmp(p->rs_name, sectname)==0) + return p; + return NULL; +} + +static struct rcsection * +rc_addsect(struct rcfile *rcp, char *sectname) { + struct rcsection *p; + + p = rc_findsect(rcp, sectname); + if (p) return p; + p = malloc(sizeof(*p)); + if (!p) return NULL; + p->rs_name = strdup(sectname); + SLIST_INIT(&p->rs_keys); + SLIST_INSERT_HEAD(&rcp->rf_sect, p, rs_next); + return p; +} + +static int +rc_sect_free(struct rcsection *rsp) { + struct rckey *p,*n; + + for(p = SLIST_FIRST(&rsp->rs_keys);p;) { + n = p; + p = SLIST_NEXT(p,rk_next); + rc_key_free(n); + } + free(rsp->rs_name); + free(rsp); + return 0; +} + +static struct rckey * +rc_sect_findkey(struct rcsection *rsp, char *keyname) { + struct rckey *p; + + SLIST_FOREACH(p, &rsp->rs_keys, rk_next) + if (strcmp(p->rk_name, keyname)==0) + return p; + return NULL; +} + +static struct rckey * +rc_sect_addkey(struct rcsection *rsp, char *name, char *value) { + struct rckey *p; + + p = rc_sect_findkey(rsp, name); + if (p) { + free(p->rk_value); + } else { + p = malloc(sizeof(*p)); + if (!p) return NULL; + SLIST_INSERT_HEAD(&rsp->rs_keys, p, rk_next); + p->rk_name = strdup(name); + } + p->rk_value = value ? strdup(value) : strdup(""); + return p; +} + +void +rc_sect_delkey(struct rcsection *rsp, struct rckey *p) { + + SLIST_REMOVE(&rsp->rs_keys,p,rckey,rk_next); + rc_key_free(p); + return; +} + +static void +rc_key_free(struct rckey *p){ + free(p->rk_value); + free(p->rk_name); + free(p); +} + +enum { stNewLine, stHeader, stSkipToEOL, stGetKey, stGetValue}; + +static void +rc_parse(struct rcfile *rcp) { + FILE *f = rcp->rf_f; + int state = stNewLine, c; + struct rcsection *rsp = NULL; + struct rckey *rkp = NULL; + char buf[2048]; + char *next = buf, *last = &buf[sizeof(buf)-1]; + + while ((c = getc (f)) != EOF) { + if (c == '\r') + continue; + if (state == stNewLine) { + next = buf; + if (isspace(c)) + continue; /* skip leading junk */ + if (c == '[') { + state = stHeader; + rsp = NULL; + continue; + } + if (c == '#' || c == ';') { + state = stSkipToEOL; + } else { /* something meaningfull */ + state = stGetKey; + } + } + if (state == stSkipToEOL || next == last) {/* ignore long lines */ + if (c == '\n'){ + state = stNewLine; + next = buf; + } + continue; + } + if (state == stHeader) { + if (c == ']') { + *next = 0; + next = buf; + rsp = rc_addsect(rcp, buf); + state = stSkipToEOL; + } else + *next++ = c; + continue; + } + if (state == stGetKey) { + if (c == ' ' || c == '\t')/* side effect: 'key name='*/ + continue; /* become 'keyname=' */ + if (c == '\n') { /* silently ignore ... */ + state = stNewLine; + continue; + } + if (c != '=') { + *next++ = c; + continue; + } + *next = 0; + if (rsp == NULL) { + fprintf(stderr, "Key '%s' defined before section\n", buf); + state = stSkipToEOL; + continue; + } + rkp = rc_sect_addkey(rsp, buf, NULL); + next = buf; + state = stGetValue; + continue; + } + /* only stGetValue left */ + if (state != stGetValue) { + fprintf(stderr, "Well, I can't parse file '%s'\n",rcp->rf_name); + state = stSkipToEOL; + } + if (c != '\n') { + *next++ = c; + continue; + } + *next = 0; + rkp->rk_value = strdup(buf); + state = stNewLine; + rkp = NULL; + } /* while */ + if (c == EOF && state == stGetValue) { + *next = 0; + rkp->rk_value = strdup(buf); + } + return; +} + +int +rc_getstringptr(struct rcfile *rcp,char *section, char *key,char **dest) { + struct rcsection *rsp; + struct rckey *rkp; + + *dest = NULL; + rsp = rc_findsect(rcp, section); + if (!rsp) return ENOENT; + rkp = rc_sect_findkey(rsp,key); + if (!rkp) return ENOENT; + *dest = rkp->rk_value; + return 0; +} + +int +rc_getstring(struct rcfile *rcp,char *section, char *key,int maxlen,char *dest) { + char *value; + int error; + + error = rc_getstringptr(rcp, section, key, &value); + if (error) return error; + if (strlen(value) >= maxlen) { + fprintf(stderr, "line too long for key '%s' in section '%s', max = %d\n",key, section, maxlen); + return EINVAL; + } + strcpy(dest,value); + return 0; +} + +int +rc_getint(struct rcfile *rcp,char *section, char *key,int *value) { + struct rcsection *rsp; + struct rckey *rkp; + + rsp = rc_findsect(rcp, section); + if (!rsp) return ENOENT; + rkp = rc_sect_findkey(rsp,key); + if (!rkp) return ENOENT; + errno = 0; + *value = strtol(rkp->rk_value,NULL,0); + if (errno) { + fprintf(stderr, "invalid int value '%s' for key '%s' in section '%s'\n",rkp->rk_value,key,section); + return errno; + } + return 0; +} + +/* + * 1,yes,true + * 0,no,false + */ +int +rc_getbool(struct rcfile *rcp,char *section, char *key,int *value) { + struct rcsection *rsp; + struct rckey *rkp; + char *p; + + rsp = rc_findsect(rcp, section); + if (!rsp) return ENOENT; + rkp = rc_sect_findkey(rsp,key); + if (!rkp) return ENOENT; + p = rkp->rk_value; + while (*p && isspace(*p)) p++; + if (*p == '0' || strcasecmp(p,"no") == 0 || strcasecmp(p,"false") == 0) { + *value = 0; + return 0; + } + if (*p == '1' || strcasecmp(p,"yes") == 0 || strcasecmp(p,"true") == 0) { + *value = 1; + return 0; + } + fprintf(stderr, "invalid boolean value '%s' for key '%s' in section '%s' \n",p, key, section); + return EINVAL; +} + +/* + * first read ~/.nwfsrc, next try to merge NWFS_CFG_FILE + */ +int +ncp_open_rcfile(void) { + char *home, *fn; + int error; + + home = getenv("HOME"); + if (home) { + fn = malloc(strlen(home) + 20); + sprintf(fn, "%s/.nwfsrc", home); + error = rc_open(fn,"r",&ncp_rc); + free (fn); + } + error = rc_merge(NWFS_CFG_FILE, &ncp_rc); + if( ncp_rc == NULL ) { + printf("Warning: no cfg files found.\n"); + return 1; + } + return 0; +} + diff --git a/lib/libncp/ncpl_rpc.c b/lib/libncp/ncpl_rpc.c new file mode 100644 index 0000000..f2f9e54 --- /dev/null +++ b/lib/libncp/ncpl_rpc.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * NetWare RPCs + * + * $FreeBSD$ + */ +#include +#include +#include +#include +#include +#include + +struct ncp_rpc_rq { + nuint16 len; /* HL */ + nuint8 subfn; + nuint32 reserved[4]; + nuint8 flags[4]; +} __attribute__ ((packed)); + +struct ncp_rpc_rp { + nuint32 rpccode; + nuint32 reserved[4]; + nuint32 rpcval; +} __attribute__ ((packed)); + +static NWCCODE +ncp_rpc(NWCONN_HANDLE cH, int rpcfn, + const nuint8* rpcarg, char* arg1, char *arg2, + nuint32* rpcval) { + NWCCODE error; + NW_FRAGMENT rq[4], rp; + struct ncp_rpc_rq rqh; + struct ncp_rpc_rp rph; + + rqh.subfn = rpcfn; + if (rpcarg) + bcopy(rpcarg, rqh.reserved, 4 * 4 + 4); + else + bzero(rqh.reserved, 4 * 4 + 4); + rq[0].fragAddress = (char*)&rqh; + rq[0].fragSize = sizeof(rqh); + rq[1].fragAddress = arg1; + rq[1].fragSize = strlen(arg1) + 1; + rq[2].fragAddress = arg2; + rq[2].fragSize = arg2 ? (strlen(arg2) + 1) : 0; + rqh.len = htons(rq[2].fragSize + rq[1].fragSize + sizeof(rqh) - 2); + rp.fragAddress = (char*)&rph; + rp.fragSize = sizeof(rph); + error = NWRequest(cH, 131, 3, rq, 1, &rp); + if (error) return error; + if (rp.fragSize < 4) return EBADRPC; + error = rph.rpccode; + if (error) return error; + if (rpcval) { + if (rp.fragSize < 24) + return EBADRPC; + *rpcval = rph.rpcval; + } + return 0; +} + +NWCCODE +NWSMLoadNLM(NWCONN_HANDLE cH, pnstr8 cmd) { + return ncp_rpc(cH, 1, NULL, cmd, NULL, NULL); +} + +NWCCODE +NWSMUnloadNLM(NWCONN_HANDLE cH, pnstr8 cmd) { + return ncp_rpc(cH, 2, NULL, cmd, NULL, NULL); +} + +NWCCODE +NWSMMountVolume(NWCONN_HANDLE cH, pnstr8 volName, nuint32* volnum) { + return ncp_rpc(cH, 3, NULL, volName, NULL, volnum); +} + +NWCCODE +NWSMDismountVolumeByName(NWCONN_HANDLE cH, pnstr8 vol) { + return ncp_rpc(cH, 4, NULL, vol, NULL, NULL); +} + +struct ncp_set_hdr { + nuint32 typeFlag; /* 0 - str, 1 - value */ + nuint32 value; + nuint32 pad[20 - 4 - 4]; +} __attribute__ ((packed)); + +NWCCODE +NWSMSetDynamicCmdIntValue(NWCONN_HANDLE cH, pnstr8 setCommandName, nuint32 cmdValue) { + struct ncp_set_hdr rq; + + memset(&rq, 0, sizeof(rq)); + rq.typeFlag = 1; + rq.value = cmdValue; + return ncp_rpc(cH, 6, (char*)&rq, setCommandName, NULL, NULL); +} + +NWCCODE +NWSMSetDynamicCmdStrValue(NWCONN_HANDLE cH, pnstr8 setCommandName, + pnstr8 cmdValue) { + return ncp_rpc(cH, 6, NULL, setCommandName, cmdValue, NULL); +} + +NWCCODE +NWSMExecuteNCFFile(NWCONN_HANDLE cH, pnstr8 NCFFileName) { + return ncp_rpc(cH, 7, NULL, NCFFileName, NULL, NULL); +} diff --git a/lib/libncp/ncpl_subr.c b/lib/libncp/ncpl_subr.c new file mode 100644 index 0000000..c7606c7 --- /dev/null +++ b/lib/libncp/ncpl_subr.c @@ -0,0 +1,470 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +/*#include */ +#include "ncp_mod.h" + +int sysentoffset; + +void +ncp_add_word_lh(struct ncp_buf *conn, u_int16_t x) { + setwle(conn->packet, conn->rqsize, x); + conn->rqsize += 2; + return; +} + +void +ncp_add_dword_lh(struct ncp_buf *conn, u_int32_t x) { + setdle(conn->packet, conn->rqsize, x); + conn->rqsize += 4; + return; +} + +void +ncp_add_word_hl(struct ncp_buf *conn, u_int16_t x){ + setwbe(conn->packet, conn->rqsize, x); + conn->rqsize += 2; + return; +} + +void +ncp_add_dword_hl(struct ncp_buf *conn, u_int32_t x) { + setdbe(conn->packet, conn->rqsize, x); + conn->rqsize += 4; + return; +} + +void +ncp_add_mem(struct ncp_buf *conn, const void *source, int size) { + memcpy(conn->packet+conn->rqsize, source, size); + conn->rqsize += size; + return; +} + +void +ncp_add_mem_nls(struct ncp_buf *conn, const void *source, int size) { + ncp_nls_mem_u2n(conn->packet+conn->rqsize, source, size); + conn->rqsize += size; + return; +} + +void +ncp_add_pstring(struct ncp_buf *conn, const char *s) { + int len = strlen(s); + if (len > 255) { + ncp_printf("ncp_add_pstring: string too long: %s\n", s); + len = 255; + } + ncp_add_byte(conn, len); + ncp_add_mem(conn, s, len); + return; +} + +void +ncp_add_handle_path(struct ncp_buf *conn, nuint32 volNumber, nuint32 dirNumber, + int handleFlag, const char *path) +{ + ncp_add_byte(conn, volNumber); + ncp_add_dword_lh(conn, dirNumber); + ncp_add_byte(conn, handleFlag); + if (path) { + ncp_add_byte(conn, 1); /* 1 component */ + ncp_add_pstring(conn, path); + } else { + ncp_add_byte(conn, 0); + } +} + +void +ncp_init_request(struct ncp_buf *conn) { + conn->rqsize = 0; + conn->rpsize = 0; +} + +void +ncp_init_request_s(struct ncp_buf *conn, int subfn) { + ncp_init_request(conn); + ncp_add_word_lh(conn, 0); + ncp_add_byte(conn, subfn); +} + +u_int16_t +ncp_reply_word_hl(struct ncp_buf *conn, int offset) { + return getwbe(ncp_reply_data(conn, offset), 0); +} + +u_int16_t +ncp_reply_word_lh(struct ncp_buf *conn, int offset) { + return getwle(ncp_reply_data(conn, offset), 0); +} + +u_int32_t +ncp_reply_dword_hl(struct ncp_buf *conn, int offset) { + return getdbe(ncp_reply_data(conn, offset), 0); +} + +u_int32_t +ncp_reply_dword_lh(struct ncp_buf *conn, int offset) { + return getdle(ncp_reply_data(conn, offset), 0); +} + + +int +ncp_connect(struct ncp_conn_args *li, int *connHandle) { + return syscall(NCP_CONNECT,li,connHandle); +} + +int +ncp_disconnect(int cH) { + DECLARE_RQ; + + ncp_init_request(conn); + ncp_add_byte(conn, NCP_CONN_CONNCLOSE); + return ncp_conn_request(cH, conn); +} + +int +ncp_request(int connHandle,int function, struct ncp_buf *ncpbuf){ + int err = syscall(SNCP_REQUEST,connHandle,function,ncpbuf); + return (err<0) ? errno : 0; +} + +int +ncp_conn_request(int connHandle, struct ncp_buf *ncpbuf){ + return syscall(SNCP_REQUEST, connHandle, NCP_CONN, ncpbuf); +} + +int +ncp_conn_scan(struct ncp_conn_loginfo *li, int *connid) { + return syscall(NCP_CONNSCAN,li, connid); +} + +NWCCODE +NWRequest(NWCONN_HANDLE cH, nuint16 fn, + nuint16 nrq, NW_FRAGMENT* rq, + nuint16 nrp, NW_FRAGMENT* rp) +{ + int error; + struct ncp_conn_frag nf; + DECLARE_RQ; + + ncp_init_request(conn); + ncp_add_byte(conn, NCP_CONN_FRAG); + nf.fn = fn; + nf.rqfcnt = nrq; + nf.rqf = rq; + nf.rpf = rp; + nf.rpfcnt = nrp; + ncp_add_mem(conn, &nf, sizeof(nf)); + error = ncp_conn_request(cH, conn); + return error; +} + + +int +ncp_initlib(void){ + int error; + int len = sizeof(sysentoffset); + int kv, kvlen = sizeof(kv); + static int ncp_initialized; + + if (ncp_initialized) + return 0; +#if __FreeBSD_version < 400001 + error = sysctlbyname("net.ipx.ncp.sysent", &sysentoffset, &len, NULL, 0); +#else + error = sysctlbyname("net.ncp.sysent", &sysentoffset, &len, NULL, 0); +#endif + if (error) { + fprintf(stderr, "%s: can't find kernel module\n", __FUNCTION__); + return error; + } +#if __FreeBSD_version < 400001 + error = sysctlbyname("net.ipx.ncp.version", &kv, &kvlen, NULL, 0); +#else + error = sysctlbyname("net.ncp.version", &kv, &kvlen, NULL, 0); +#endif + if (error) { + fprintf(stderr, "%s: kernel module is old, please recompile it.\n", __FUNCTION__); + return error; + } + if (NCP_VERSION != kv) { + fprintf(stderr, "%s: kernel module version(%d) don't match library(%d).\n", __FUNCTION__, kv, NCP_VERSION); + return EINVAL; + } + if ((error = ncp_nls_setrecode(0)) != 0) { + fprintf(stderr, "%s: can't initialise recode\n", __FUNCTION__); + return error; + } + if ((error = ncp_nls_setlocale("")) != 0) { + fprintf(stderr, "%s: can't initialise locale\n", __FUNCTION__); + return error; + } + ncp_initialized++; + return 0; +} + + +/* + */ +int ncp_opterr = 1, /* if error message should be printed */ + ncp_optind = 1, /* index into parent argv vector */ + ncp_optopt, /* character checked for validity */ + ncp_optreset; /* reset getopt */ +char *ncp_optarg; /* argument associated with option */ + +#define BADCH (int)'?' +#define BADARG (int)':' +#define EMSG "" + +int +ncp_getopt(nargc, nargv, ostr) + int nargc; + char * const *nargv; + const char *ostr; +{ + extern char *__progname; + static char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ + int tmpind; + + if (ncp_optreset || !*place) { /* update scanning pointer */ + ncp_optreset = 0; + tmpind = ncp_optind; + while (1) { + if (tmpind >= nargc) { + place = EMSG; + return (-1); + } + if (*(place = nargv[tmpind]) != '-') { + tmpind++; + continue; /* lookup next option */ + } + if (place[1] && *++place == '-') { /* found "--" */ + ncp_optind = ++tmpind; + place = EMSG; + return (-1); + } + ncp_optind = tmpind; + break; + } + } /* option letter okay? */ + if ((ncp_optopt = (int)*place++) == (int)':' || + !(oli = strchr(ostr, ncp_optopt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means -1. + */ + if (ncp_optopt == (int)'-') + return (-1); + if (!*place) + ++ncp_optind; + if (ncp_opterr && *ostr != ':') + (void)fprintf(stderr, + "%s: illegal option -- %c\n", __progname, ncp_optopt); + return (BADCH); + } + if (*++oli != ':') { /* don't need argument */ + ncp_optarg = NULL; + if (!*place) + ++ncp_optind; + } + else { /* need an argument */ + if (*place) /* no white space */ + ncp_optarg = place; + else if (nargc <= ++ncp_optind) { /* no arg */ + place = EMSG; + if (*ostr == ':') + return (BADARG); + if (ncp_opterr) + (void)fprintf(stderr, + "%s: option requires an argument -- %c\n", + __progname, ncp_optopt); + return (BADCH); + } + else /* white space */ + ncp_optarg = nargv[ncp_optind]; + place = EMSG; + ++ncp_optind; + } + return (ncp_optopt); /* dump back option letter */ +} +/* + * misc options parsing routines + */ +int +ncp_args_parserc(struct ncp_args *na, char *sect, ncp_setopt_t *set_callback) { + int len, error; + + for (; na->opt; na++) { + switch (na->at) { + case NCA_STR: + if (rc_getstringptr(ncp_rc,sect,na->name,&na->str) == 0) { + len = strlen(na->str); + if (len > na->ival) { + fprintf(stderr,"rc: Argument for option '%c' (%s) too long\n",na->opt,na->name); + return EINVAL; + } + set_callback(na); + } + break; + case NCA_BOOL: + error = rc_getbool(ncp_rc,sect,na->name,&na->ival); + if (error == ENOENT) break; + if (error) return EINVAL; + set_callback(na); + break; + case NCA_INT: + if (rc_getint(ncp_rc,sect,na->name,&na->ival) == 0) { + if (((na->flag & NAFL_HAVEMIN) && + (na->ival < na->min)) || + ((na->flag & NAFL_HAVEMAX) && + (na->ival > na->max))) { + fprintf(stderr,"rc: Argument for option '%c' (%s) should be in [%d-%d] range\n",na->opt,na->name,na->min,na->max); + return EINVAL; + } + set_callback(na); + }; + break; + default: + break; + } + } + return 0; +} + +int +ncp_args_parseopt(struct ncp_args *na, int opt, char *optarg, ncp_setopt_t *set_callback) { + int len; + + for (; na->opt; na++) { + if (na->opt != opt) continue; + switch (na->at) { + case NCA_STR: + na->str = optarg; + if (optarg) { + len = strlen(na->str); + if (len > na->ival) { + fprintf(stderr,"opt: Argument for option '%c' (%s) too long\n",na->opt,na->name); + return EINVAL; + } + set_callback(na); + } + break; + case NCA_BOOL: + na->ival = 0; + set_callback(na); + break; + case NCA_INT: + errno = 0; + na->ival = strtol(optarg, NULL, 0); + if (errno) { + fprintf(stderr,"opt: Invalid integer value for option '%c' (%s).\n",na->opt,na->name); + return EINVAL; + } + if (((na->flag & NAFL_HAVEMIN) && + (na->ival < na->min)) || + ((na->flag & NAFL_HAVEMAX) && + (na->ival > na->max))) { + fprintf(stderr,"opt: Argument for option '%c' (%s) should be in [%d-%d] range\n",na->opt,na->name,na->min,na->max); + return EINVAL; + } + set_callback(na); + break; + default: + break; + } + break; + } + return 0; +} + +/* + * Print a (descriptive) error message + * error values: + * 0 - no specific error code available; + * -999..-1 - NDS error + * 1..32767 - system error + * the rest - requester error; + */ +void +ncp_error(char *fmt, int error,...) { + va_list ap; + + va_start(ap, error); + vfprintf(stderr, fmt, ap); + va_end(ap); + if (error == -1) + error = errno; + if (error > -1000 && error < 0) { + fprintf(stderr, ": dserr = %d\n", error); + } else if (error & 0x8000) { + fprintf(stderr, ": nwerr = %04x\n", error); + } else if (error) { + fprintf(stderr, ": syserr = %s\n", strerror(error)); + } else + fprintf(stderr, "\n"); +} + +char * +ncp_printb(char *dest, int flags, const struct ncp_bitname *bnp) { + int first = 1; + + strcpy(dest, "<"); + for(; bnp->bn_bit; bnp++) { + if (flags & bnp->bn_bit) { + strcat(dest, bnp->bn_name); + first = 0; + } + if (!first && (flags & bnp[1].bn_bit)) + strcat(dest, "|"); + } + strcat(dest, ">"); + return dest; +} diff --git a/lib/libncp/sap.c b/lib/libncp/sap.c new file mode 100644 index 0000000..32e0ab2 --- /dev/null +++ b/lib/libncp/sap.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "ipxsap.h" + +/* + * TODO: These should go to ipx headers + */ +#define ipx_set_net(x,y) ((x).x_net.s_net[0] = (y).x_net.s_net[0]); \ + ((x).x_net.s_net[1]=(y).x_net.s_net[1]) +#define ipx_set_nullnet(x) ((x).x_net.s_net[0]=0); ((x).x_net.s_net[1]=0) +#define ipx_set_nullhost(x) ((x).x_host.s_host[0] = 0); \ + ((x).x_host.s_host[1] = 0); ((x).x_host.s_host[2] = 0) +#define ipx_set_wildnet(x) ((x).x_net.s_net[0] = 0xFFFF); \ + ((x).x_net.s_net[1]=0xFFFF) +#define ipx_set_wildhost(x) ((x).x_host.s_host[0] = 0xFFFF); \ + ((x).x_host.s_host[1] = 0xFFFF); ((x).x_host.s_host[2] = 0xFFFF); + + +static struct sap_packet* sap_packet_alloc(int entries); +static int sap_size(int entries, u_short operation); +int (*sap_sendto_func)(void*,int,struct sockaddr_ipx*,int sock)=NULL; + +static int +sap_sendto(void* buffer, int size, struct sockaddr_ipx* daddr, int sock) +{ + if (sap_sendto_func) + return sap_sendto_func(buffer,size,daddr,sock); + return sendto(sock, (char*)buffer, size, 0, + (struct sockaddr*)daddr, sizeof(*daddr)); +} + +static struct sap_packet* +sap_packet_alloc(int entries) +{ + if (entries > IPX_SAP_MAX_ENTRIES) + return NULL; + return + (struct sap_packet*)malloc(sap_size(entries, IPX_SAP_GENERAL_RESPONSE)); +} + +static int +sap_size(int entries, u_short operation) +{ + if (entries <= 0) + return 0; + switch (operation) { + case IPX_SAP_GENERAL_QUERY: + return entries == 1 ? IPX_SAP_REQUEST_LEN : 0; + case IPX_SAP_GENERAL_RESPONSE: + if (entries > IPX_SAP_MAX_ENTRIES) + return 0; + return sizeof(struct sap_packet) + (entries - 1) * sizeof(struct sap_entry); + case IPX_SAP_NEAREST_QUERY: + return entries == 1 ? IPX_SAP_REQUEST_LEN : 0; + case IPX_SAP_NEAREST_RESPONSE: + return entries == 1 ? sizeof(struct sap_packet) : 0; + default: + return 0; + } +} + +void +sap_copyname(char *dest, const char *src) +{ + bzero(dest, IPX_SAP_SERVER_NAME_LEN); + strncpy(dest, src, IPX_SAP_SERVER_NAME_LEN - 1); +} + +int +sap_rq_init(struct sap_rq* rq, int sock) +{ + rq->buffer = sap_packet_alloc(IPX_SAP_MAX_ENTRIES); + if (rq->buffer == NULL) + return 0; + rq->entries = 0; + rq->buffer->operation = htons(IPX_SAP_GENERAL_QUERY); + rq->dest_addr.sipx_family = AF_IPX; + rq->dest_addr.sipx_len = sizeof(struct sockaddr_ipx); + rq->sock = sock; + return 1; +} + +int +sap_rq_flush(struct sap_rq* rq) +{ + int result; + + if (rq->entries == 0) + return 0; + result = sap_sendto(rq->buffer, + sap_size(rq->entries, ntohs(rq->buffer->operation)), + &rq->dest_addr, rq->sock); + rq->entries = 0; + return result; +} + +void +sap_rq_general_query(struct sap_rq* rq, u_short ser_type) +{ + struct sap_entry* sep; + + sap_rq_flush(rq); + rq->buffer->operation = htons(IPX_SAP_GENERAL_QUERY); + sep = rq->buffer->sap_entries + rq->entries++; + sep->server_type = htons(ser_type); +} + +void +sap_rq_gns_request(struct sap_rq* rq, u_short ser_type) +{ + struct sap_entry* sep; + + sap_rq_flush(rq); + rq->buffer->operation = htons(IPX_SAP_NEAREST_QUERY); + sep = rq->buffer->sap_entries + rq->entries++; + sep->server_type = htons(ser_type); +} + +void +sap_rq_general_response(struct sap_rq* rq,u_short type,char *name,struct sockaddr_ipx* addr, u_short hops,int down_allow) +{ + struct sap_entry* sep; + + if (hops >= IPX_SAP_SERVER_DOWN && !down_allow) return; + if (rq->entries >= IPX_SAP_MAX_ENTRIES) + sap_rq_flush(rq); + if (rq->buffer->operation != htons(IPX_SAP_GENERAL_RESPONSE)){ + sap_rq_flush(rq); + rq->buffer->operation = htons(IPX_SAP_GENERAL_RESPONSE); + } + sep = rq->buffer->sap_entries + rq->entries; + sep->server_type = htons(type); + sap_copyname(sep->server_name, name); + memcpy(&sep->ipx, &addr->sipx_addr, sizeof(struct ipx_addr)); + sep->hops = htons(hops); + rq->entries++; +} + +void +sap_rq_gns_response(struct sap_rq* rq,u_short type,char *name,struct sockaddr_ipx* addr,u_short hops) +{ + struct sap_entry* sep; + + if (hops >= IPX_SAP_SERVER_DOWN) return; + sap_rq_flush(rq); + rq->buffer->operation = htons(IPX_SAP_NEAREST_RESPONSE); + sep = rq->buffer->sap_entries + rq->entries; + sep->server_type = htons(type); + sap_copyname(sep->server_name, name); + memcpy(&sep->ipx, &addr->sipx_addr, sizeof(struct ipx_addr)); + sep->hops = htons(hops); + rq->entries++; +} + +void +sap_rq_set_destination(struct sap_rq* rq,struct ipx_addr *dest) +{ + sap_rq_flush(rq); + memcpy(&rq->dest_addr.sipx_addr,dest,sizeof(struct ipx_addr)); +} + +int +sap_getsock(int *rsock) { + struct sockaddr_ipx sap_addr; + int opt, sock, slen; + + sock = socket(AF_IPX, SOCK_DGRAM, 0); + if (sock < 0) + return (errno); + slen = sizeof(sap_addr); + bzero(&sap_addr, slen); + sap_addr.sipx_family = AF_IPX; + sap_addr.sipx_len = slen; + if (bind(sock, (struct sockaddr*)&sap_addr, slen) == -1) { + close(sock); + return(errno); + } + opt = 1; + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) != 0){ + close(sock); + return(errno); + } + *rsock = sock; + return(0); +} + +static int +sap_recv(int sock,void *buf,int len,int flags, int timeout){ + fd_set rd, wr, ex; + struct timeval tv; + int result; + + FD_ZERO(&rd); + FD_ZERO(&wr); + FD_ZERO(&ex); + FD_SET(sock, &rd); + + tv.tv_sec = timeout; + tv.tv_usec = 0; + + if ((result = select(sock + 1, &rd, &wr, &ex, &tv)) == -1) { + return result; + } + if (FD_ISSET(sock, &rd)) { + result = recv(sock, buf, len, flags); + } else { + errno = ETIMEDOUT; + result = -1; + } + return result; +} + +int +sap_find_nearest(int server_type, struct sockaddr_ipx *daddr, char *server_name) +{ + struct ipx_addr addr; + char data[1024]; + int sock, error, packets, len; + struct sap_packet *reply = (struct sap_packet*)&data; + struct sap_rq sap_rq; + + error = sap_getsock(&sock); + if (error) + return error; + bzero(&addr, sizeof(addr)); + /* BAD: we should enum all ifs (and nets ?) */ + if (ipx_iffind(NULL, &addr) != 0) { + return (EPROTONOSUPPORT); + } + ipx_set_wildhost(addr); + addr.x_port = htons(IPXPORT_SAP); + + if (!sap_rq_init(&sap_rq, sock)) { + close(sock); + return(ENOMEM); + } + sap_rq_set_destination(&sap_rq, &addr); + sap_rq_gns_request(&sap_rq, server_type); + sap_rq_flush(&sap_rq); + packets = 5; + do { + len = sap_recv(sock, data, sizeof(data), 0, 1); + if (len < 66) { + packets++; + continue; + } + } while (ntohs(reply->operation) != IPX_SAP_NEAREST_RESPONSE && + packets > 0); + + if (packets == 0) { + close(sock); + return ENETDOWN; + } + + daddr->sipx_addr = reply->sap_entries[0].ipx; + daddr->sipx_family = AF_IPX; + daddr->sipx_len = sizeof(struct sockaddr_ipx); + sap_copyname(server_name, reply->sap_entries[0].server_name); + errno = 0; + close(sock); + return 0; +} diff --git a/sys/netncp/ncp_cfg.h b/sys/netncp/ncp_cfg.h new file mode 100644 index 0000000..82a30d7 --- /dev/null +++ b/sys/netncp/ncp_cfg.h @@ -0,0 +1,9 @@ +/* + * static configuration for libncp + * + * $FreeBSD$ + */ + +#define NCP_NLS_KOI2CP866 +#define NCP_NLS_DEFAULT NCP_NLS_KOI_866 +#define NCP_PREFIX "" diff --git a/sys/netncp/ncp_file.h b/sys/netncp/ncp_file.h new file mode 100644 index 0000000..17b5bd5 --- /dev/null +++ b/sys/netncp/ncp_file.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _NCP_NCP_FILE_H_ +#define _NCP_NCP_FILE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + nuint32 sequence; + nuint32 parent; + nuint32 attributes; + nuint8 uniqueID; + nuint8 flags; + nuint8 nameSpace; + nuint8 nameLength; + nuint8 name [256]; + nuint32 creationDateAndTime; + nuint32 ownerID; + nuint32 lastArchiveDateAndTime; + nuint32 lastArchiverID; + nuint32 updateDateAndTime; + nuint32 updatorID; + nuint32 fileSize; + nuint8 reserved[44]; + nuint16 inheritedRightsMask; + nuint16 lastAccessDate; + nuint32 deletedTime; + nuint32 deletedDateAndTime; + nuint32 deletorID; + nuint8 reserved3 [16]; +} __attribute__((packed)) NWDELETED_INFO; + +int ncp_AllocTempDirHandle(char *path, NWDIR_HANDLE *pdh); +int ncp_DeallocateDirHandle(NWDIR_HANDLE dh); +int ncp_GetNSEntryInfo(NWDIR_HANDLE dh, struct nw_entry_info *fi, int *ns); + +NWCCODE ncp_ScanNSEntryInfo(NWCONN_HANDLE cH, nuint8 namSpc, nuint16 attrs, + SEARCH_SEQUENCE *seq, pnstr8 searchPattern, nuint32 retInfoMask, + NW_ENTRY_INFO *entryInfo); + +NWCCODE ncp_PurgeDeletedFile(NWCONN_HANDLE cH, nuint32 iterHandle, + nuint32 volNum, nuint32 dirBase, nuint8 ns); + +NWCCODE NWRecoverDeletedFile(NWCONN_HANDLE conn, NWDIR_HANDLE dirHandle, + nuint32 iterHandle, + nuint32 volNum, nuint32 dirBase, + pnstr8 delFileName, pnstr8 rcvrFileName); + +NWCCODE ncp_ScanForDeletedFiles(NWCONN_HANDLE cH, pnuint32 iterHandle, + pnuint32 volNum, pnuint32 dirBase, nuint8 ns, + NWDELETED_INFO *entryInfo); + + +#ifdef __cplusplus +} +#endif + +#endif /* _NCP_NCP_FILE_ */ diff --git a/sys/netncp/ncp_lib.h b/sys/netncp/ncp_lib.h new file mode 100644 index 0000000..bff6339 --- /dev/null +++ b/sys/netncp/ncp_lib.h @@ -0,0 +1,258 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _NCP_LIB_H_ +#define _NCP_LIB_H_ + +#define IPX +#define INET + +#include +#include +#include +#include + +#define ncp_printf printf + +#define sipx_cnetwork sipx_addr.x_net.c_net +#define sipx_node sipx_addr.x_host.c_host +#define ipx_netlong(iaddr) (((union ipx_net_u *)(&((iaddr).x_net)))->long_e) + +#define STDPARAM_ARGS 'A':case 'B':case 'C':case 'I':case 'M': \ + case 'N':case 'U':case 'R':case 'S':case 'T': \ + case 'W':case 'O':case 'P' + +#define STDPARAM_OPT "A:BCI:M:N:O:P:U:R:S:T:W:" + +#ifndef min +#define min(a,b) (((a)<(b)) ? (a) : (b)) +#endif + + +/* + * An attempt to do a unified options parser + */ +enum ncp_argtype {NCA_STR,NCA_INT,NCA_BOOL}; + +struct ncp_args; + +typedef int ncp_setopt_t (struct ncp_args*); + +#define NAFL_NONE 0x0000 +#define NAFL_HAVEMIN 0x0001 +#define NAFL_HAVEMAX 0x0002 +#define NAFL_MINMAX NAFL_HAVEMIN | NAFL_HAVEMAX + +struct ncp_args { + enum ncp_argtype at; + int opt; /* command line option */ + char *name; /* rc file equiv */ + int flag; /* NAFL_* */ + int ival; /* int/bool values, or max len for str value */ + char *str; /* string value */ + int min; /* min for ival */ + int max; /* max for ival */ + ncp_setopt_t *fn;/* call back to validate */ +}; + +typedef struct { + nuint8 day; + nuint8 month; + nuint16 year; +} NW_DATE; + +/* hours is a nuint16 so that this structure will be the same length as a dword */ +typedef struct { + nuint8 seconds; + nuint8 minutes; + nuint16 hours; +} NW_TIME; + +struct ncp_bitname { + u_int bn_bit; + char *bn_name; +}; + +int ncp_args_parserc(struct ncp_args *na, char *sect, ncp_setopt_t *set_callback); +int ncp_args_parseopt(struct ncp_args *na, int opt, char *optarg, ncp_setopt_t *set_callback); + + +struct sockaddr_ipx; +struct ipx_addr; +struct sockaddr; +struct ncp_buf; +struct rcfile; + +int ncp_initlib(void); +int ncp_connect(struct ncp_conn_args *li, int *connHandle); +int ncp_connect_addr(struct sockaddr *sa, NWCONN_HANDLE *chp); +int ncp_disconnect(int connHandle); +int ncp_request(int connHandle,int function, struct ncp_buf *ncpbuf); +int ncp_conn_request(int connHandle, struct ncp_buf *ncpbuf); +int ncp_login(int connHandle, const char *user, int objtype, const char *password); +int ncp_conn_scan(struct ncp_conn_loginfo *li, int *connHandle); +int ncp_conn_cnt(void); +void *ncp_conn_list(void); +int ncp_conn_getinfo(int connHandle, struct ncp_conn_stat *ps); +int ncp_conn_getuser(int connHandle, char **user); +int ncp_conn2ref(int connHandle, int *connRef); +int ncp_conn_dup(NWCONN_HANDLE org, NWCONN_HANDLE *res); +int ncp_path2conn(char *path, int *connHandle); +int ncp_li_init(struct ncp_conn_loginfo *li, int argc, char *argv[]); +void ncp_li_done(struct ncp_conn_loginfo *li); +int ncp_li_login(struct ncp_conn_loginfo *li, int *aconnHandle); +int ncp_li_readrc(struct ncp_conn_loginfo *li); +int ncp_li_check(struct ncp_conn_loginfo *li); +int ncp_li_arg(struct ncp_conn_loginfo *li, int opt, char *arg); +int ncp_li_setserver(struct ncp_conn_loginfo *li, const char *arg); +int ncp_li_setuser(struct ncp_conn_loginfo *li, char *arg); +int ncp_li_setpassword(struct ncp_conn_loginfo *li, const char *passwd); +int ncp_conn_setflags(int connHandle, u_int16_t mask, u_int16_t flags); +int ncp_conn_find(char *server, char *user); +NWCCODE NWRequest(NWCONN_HANDLE cH, nuint16 fn, + nuint16 nrq, NW_FRAGMENT* rq, + nuint16 nrp, NW_FRAGMENT* rp) ; + +#define ncp_setpermanent(connHandle,on) ncp_conn_setflags(connHandle, NCPFL_PERMANENT, (on) ? NCPFL_PERMANENT : 0) +#define ncp_setprimary(connHandle,on) ncp_conn_setflags(connHandle, NCPFL_PRIMARY, (on) ? NCPFL_PRIMARY : 0) + +int ncp_find_fileserver(struct ncp_conn_loginfo *li, int af,char *name); +int ncp_find_server(struct ncp_conn_loginfo *li, int type, int af,char *name); + +/* misc rotines */ +char* ncp_str_upper(char *name); +int ncp_open_rcfile(void); +int ncp_getopt(int nargc, char * const *nargv, const char *ostr); +void NWUnpackDateTime(nuint32 dateTime, NW_DATE *sDate, NW_TIME *sTime); +void NWUnpackDate(nuint16 date, NW_DATE *sDate); +void NWUnpackTime(nuint16 time, NW_TIME *sTime); +time_t ncp_UnpackDateTime(nuint32 dateTime); +int ncp_GetFileServerDateAndTime(NWCONN_HANDLE cH, time_t *target); +int ncp_SetFileServerDateAndTime(NWCONN_HANDLE cH, time_t * source); +NWCCODE NWDownFileServer(NWCONN_HANDLE cH, int force); +NWCCODE NWCloseBindery(NWCONN_HANDLE cH); +NWCCODE NWOpenBindery(NWCONN_HANDLE cH); +NWCCODE NWDisableTTS(NWCONN_HANDLE cH); +NWCCODE NWEnableTTS(NWCONN_HANDLE cH); +NWCCODE NWDisableFileServerLogin(NWCONN_HANDLE cH); +NWCCODE NWEnableFileServerLogin(NWCONN_HANDLE cH); +void ncp_error(char *fmt, int error,...); +char *ncp_printb(char *dest, int flags, const struct ncp_bitname *bnp); +void nw_keyhash(const u_char *key, const u_char *buf, int buflen, u_char *target); +void nw_encrypt(const u_char *fra, const u_char *buf, u_char *target); +void ipx_print_addr(struct ipx_addr *ipx); + +/* bindery calls */ +int ncp_get_bindery_object_id(int connHandle, u_int16_t object_type, const char *object_name, + struct ncp_bindery_object *target); +int ncp_get_bindery_object_name(int connHandle, u_int32_t object_id, + struct ncp_bindery_object *target); +int ncp_scan_bindery_object(int connHandle, u_int32_t last_id, u_int16_t object_type, + char *search_string, struct ncp_bindery_object *target); +int ncp_read_property_value(int connHandle,int object_type, const char *object_name, + int segment, const char *prop_name, struct nw_property *target); +void shuffle(const u_char *lon, const u_char *buf, int buflen, u_char *target); +int ncp_get_encryption_key(NWCONN_HANDLE cH, char *target); +int ncp_change_obj_passwd(NWCONN_HANDLE connid, + const struct ncp_bindery_object *object, + const u_char *key, + const u_char *oldpasswd, const u_char *newpasswd); +int ncp_keyed_verify_password(NWCONN_HANDLE cH, char *key, char *passwd, + struct ncp_bindery_object *objinfo); + +/* queue calls */ +int ncp_create_queue_job_and_file(int connHandle, u_int32_t queue_id, struct queue_job *job); +int ncp_close_file_and_start_job(int connHandle, u_int32_t queue_id, struct queue_job *job); +int ncp_attach_to_queue(int connHandle, u_int32_t queue_id); +int ncp_detach_from_queue(int connHandle, u_int32_t queue_id); +int ncp_service_queue_job(int connHandle, u_int32_t queue_id, u_int16_t job_type, + struct queue_job *job); +int ncp_finish_servicing_job(int connHandle, u_int32_t queue_id, u_int32_t job_number, + u_int32_t charge_info); +int ncp_abort_servicing_job(int connHandle, u_int32_t queue_id, u_int32_t job_number); +int ncp_get_queue_length(int connHandle, u_int32_t queue_id, u_int32_t *queue_length); +int ncp_get_queue_job_ids(int connHandle, u_int32_t queue_id, u_int32_t queue_section, + u_int32_t *length1, u_int32_t *length2, u_int32_t ids[]); +int ncp_get_queue_job_info(int connHandle, u_int32_t queue_id, u_int32_t job_id, + struct nw_queue_job_entry *jobdata); +/* + * file system and volume calls + */ +int ncp_read(int connHandle, ncp_fh *fh, off_t offset, size_t count, char *target); +int ncp_write(int connHandle, ncp_fh *fh, off_t offset, size_t count, char *source); +int ncp_geteinfo(char *path, struct nw_entry_info *fi); +int ncp_NSEntryInfo(NWCONN_HANDLE cH, nuint8 ns, nuint8 vol, nuint32 dirent, + NW_ENTRY_INFO *entryInfo); + +NWCCODE NWGetVolumeName(NWCONN_HANDLE cH, u_char volume, char *name); + +/* misc ncp calls */ +int ncp_get_file_server_information(int connHandle, struct ncp_file_server_info *target); +int ncp_get_stations_logged_info(int connHandle, u_int32_t connection, + struct ncp_bindery_object *target, time_t *login_time); +int ncp_get_internet_address(int connHandle, u_int32_t connection, struct ipx_addr *target, + u_int8_t * conn_type); +NWCCODE NWGetObjectConnectionNumbers(NWCONN_HANDLE connHandle, + pnstr8 pObjName, nuint16 objType, + pnuint16 pNumConns, pnuint16 pConnHandleList, + nuint16 maxConns); +/* + * Message broadcast + */ +NWCCODE NWDisableBroadcasts(NWCONN_HANDLE connHandle); +NWCCODE NWEnableBroadcasts(NWCONN_HANDLE connHandle); +NWCCODE NWBroadcastToConsole(NWCONN_HANDLE connHandle, pnstr8 message); +NWCCODE NWSendBroadcastMessage(NWCONN_HANDLE connHandle, pnstr8 message, + nuint16 connCount, pnuint16 connList, pnuint8 resultList); +NWCCODE NWGetBroadcastMessage(NWCONN_HANDLE connHandle, pnstr8 message); + +/* + * RPC calls + */ +NWCCODE NWSMExecuteNCFFile(NWCONN_HANDLE cH, pnstr8 NCFFileName); +NWCCODE NWSMLoadNLM(NWCONN_HANDLE cH, pnstr8 cmd); +NWCCODE NWSMUnloadNLM(NWCONN_HANDLE cH, pnstr8 cmd); +NWCCODE NWSMMountVolume(NWCONN_HANDLE cH, pnstr8 volName, nuint32* volnum); +NWCCODE NWSMDismountVolumeByName(NWCONN_HANDLE cH, pnstr8 vol); +NWCCODE NWSMSetDynamicCmdIntValue(NWCONN_HANDLE cH, pnstr8 setCommandName, nuint32 cmdValue); +NWCCODE NWSMSetDynamicCmdStrValue(NWCONN_HANDLE cH, pnstr8 setCommandName, pnstr8 cmdValue); + +int dostat(int modnum, char *modname, int *offset); + +extern int ncp_opterr, ncp_optind, ncp_optopt, ncp_optreset; +extern char *ncp_optarg; + +extern struct rcfile *ncp_rc; +extern int sysentoffset; +#endif /* _NCP_LIB_H_ */ diff --git a/sys/netncp/ncp_rcfile.h b/sys/netncp/ncp_rcfile.h new file mode 100644 index 0000000..bbdf8eb --- /dev/null +++ b/sys/netncp/ncp_rcfile.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1999, Boris Popov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Boris Popov. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +#ifndef _NCP_RCFILE_H_ +#define _NCP_RCFILE_H_ +#include + +struct rckey { + SLIST_ENTRY(rckey) rk_next; + char *rk_name; + char *rk_value; +}; + +struct rcsection { + SLIST_ENTRY(rcsection) rs_next; + SLIST_HEAD(rckey_head,rckey) rs_keys; + char *rs_name; +}; + +struct rcfile { + SLIST_ENTRY(rcfile) rf_next; + SLIST_HEAD(rcsec_head, rcsection) rf_sect; + char *rf_name; + FILE *rf_f; +}; + +int rc_open(char *filename,char *mode,struct rcfile **rcfile); +int rc_close(struct rcfile *rcp); +int rc_getstringptr(struct rcfile *rcp,char *section, char *key,char **dest); +int rc_getstring(struct rcfile *rcp,char *section, char *key,int maxlen,char *dest); +int rc_getint(struct rcfile *rcp,char *section, char *key,int *value); +int rc_getbool(struct rcfile *rcp,char *section, char *key,int *value); + +#endif /* _NCP_RCFILE_H_ */ -- cgit v1.1